@@ -304,7 +304,10 @@ tests = tst-typesizes \
c89 gnu89 c99 gnu99 c11 gnu11) \
tst-bad-schedattr \
tst-thread_local1 tst-mutex-errorcheck tst-robust10 \
- tst-robust-fork tst-create-detached
+ tst-robust-fork tst-create-detached \
+ tst-cnd-basic tst-mtx-trylock tst-cnd-broadcast \
+ tst-cnd-timedwait tst-thrd-detach tst-mtx-basic tst-thrd-sleep \
+ tst-mtx-recursive tst-tss-basic tst-call-once tst-mtx-timedlock
xtests = tst-setuid1 tst-setuid1-static tst-setuid2 \
tst-mutexpp1 tst-mutexpp6 tst-mutexpp10
test-srcs = tst-oddstacklimit
new file mode 100644
@@ -0,0 +1,66 @@
+/* C11 threads call_once test.
+ Copyright (C) 2017 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <threads.h>
+#include <stdio.h>
+#include <unistd.h>
+
+#include <support/check.h>
+
+/* Flag that controls the first thread access. */
+static once_flag flag = ONCE_FLAG_INIT;
+
+static int value = 0;
+
+static void
+do_once (void)
+{
+ value++;
+}
+
+static int
+func (void* data)
+{
+ call_once (&flag, do_once);
+ thrd_exit (thrd_success);
+}
+
+#define N 20
+
+int
+do_test (void)
+{
+ thrd_t ids[N];
+
+ for (int i = 0; i < N; ++i)
+ {
+ if (thrd_create (&ids[i], func, NULL) != thrd_success)
+ FAIL_EXIT1 ("thrd_create failed");
+ }
+
+ /* Join threads. */
+ for (int i = 0; i < N; ++i)
+ {
+ if (thrd_join (ids[i], NULL) != thrd_success)
+ FAIL_EXIT1 ("thrd_join failed");
+ }
+
+ return (value != 1);
+}
+
+#include <support/test-driver.c>
new file mode 100644
@@ -0,0 +1,68 @@
+/* C11 threads condition variable tests.
+ Copyright (C) 2017 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <threads.h>
+#include <stdio.h>
+#include <unistd.h>
+
+#include <support/check.h>
+
+/* Shared condition variable between child and parent. */
+static cnd_t cond;
+
+/* Mutex needed to signal and wait threads. */
+static mtx_t mutex;
+
+static int
+signal_parent (void)
+{
+ if (cnd_signal (&cond) != thrd_success)
+ FAIL_EXIT1 ("cnd_signal");
+
+ thrd_exit (thrd_success);
+}
+
+static int
+do_test (void)
+{
+ thrd_t id;
+
+ if (cnd_init (&cond) != thrd_success)
+ FAIL_EXIT1 ("cnd_init failed");
+ if (mtx_init (&mutex, mtx_plain) != thrd_success)
+ FAIL_EXIT1 ("mtx_init failed");
+
+ if (thrd_create (&id, (thrd_start_t) signal_parent, NULL)
+ != thrd_success)
+ FAIL_EXIT1 ("thrd_create failed");
+
+ if (cnd_wait (&cond, &mutex) != thrd_success)
+ FAIL_EXIT1 ("cnd_wait failed");
+
+ /* Joining is not mandatory here, but still done to assure child thread
+ ends correctly. */
+ if (thrd_join (id, NULL) != thrd_success)
+ FAIL_EXIT1 ("thrd_join failed");
+
+ mtx_destroy (&mutex);
+ cnd_destroy (&cond);
+
+ return 0;
+}
+
+#include <support/test-driver.c>
new file mode 100644
@@ -0,0 +1,83 @@
+/* C11 threads condition broadcast variable tests.
+ Copyright (C) 2017 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <threads.h>
+#include <stdio.h>
+#include <unistd.h>
+
+#include <support/check.h>
+
+/* Condition variable where child threads will wait. */
+static cnd_t cond;
+
+/* Mutex to control wait on cond. */
+static mtx_t mutex;
+
+/* Code executed by each thread. */
+static int
+child_wait (void* data)
+{
+ /* Wait until parent thread sends broadcast here. */
+ mtx_lock (&mutex);
+ cnd_wait (&cond, &mutex);
+ mtx_unlock (&mutex);
+
+ thrd_exit (thrd_success);
+}
+
+#define N 5
+
+static int
+do_test (void)
+{
+ thrd_t ids[N];
+ unsigned char i;
+
+ if (cnd_init (&cond) != thrd_success)
+ FAIL_EXIT1 ("cnd_init failed");
+ if (mtx_init (&mutex, mtx_plain) != thrd_success)
+ FAIL_EXIT1 ("mtx_init failed");
+
+ /* Create N new threads. */
+ for (i = 0; i < N; ++i)
+ {
+ if (thrd_create (&ids[i], child_wait, NULL) != thrd_success)
+ FAIL_EXIT1 ("thrd_create failed");
+ }
+
+ /* Wait for other threads to reach their wait func. */
+ thrd_sleep (&((struct timespec){.tv_sec = 2}), NULL);
+
+ mtx_lock (&mutex);
+ if (cnd_broadcast (&cond) != thrd_success)
+ FAIL_EXIT1 ("cnd_broadcast failed");
+ mtx_unlock (&mutex);
+
+ for (i = 0; i < N; ++i)
+ {
+ if (thrd_join (ids[i], NULL) != thrd_success)
+ FAIL_EXIT1 ("thrd_join failed");
+ }
+
+ mtx_destroy (&mutex);
+ cnd_destroy (&cond);
+
+ return 0;
+}
+
+#include <support/test-driver.c>
new file mode 100644
@@ -0,0 +1,70 @@
+/* C11 threads condition timed wait variable tests.
+ Copyright (C) 2017 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <threads.h>
+#include <stdio.h>
+#include <unistd.h>
+
+#include <support/check.h>
+
+/* Shared condition variable between child and parent. */
+static cnd_t cond;
+
+/* Mutex needed to signal and wait threads. */
+static mtx_t mutex;
+
+static int
+signal_parent (void *arg)
+{
+ if (cnd_signal (&cond) != thrd_success)
+ FAIL_EXIT1 ("cnd_signal failed");
+
+ thrd_exit (thrd_success);
+}
+
+static int
+do_test (void)
+{
+ thrd_t id;
+ struct timespec w_time;
+
+ if (cnd_init (&cond) != thrd_success)
+ FAIL_EXIT1 ("cnd_init failed");
+ if (mtx_init (&mutex, mtx_plain) != thrd_success)
+ FAIL_EXIT1 ("mtx_init failed");
+
+ if (clock_gettime (CLOCK_REALTIME, &w_time) != 0)
+ FAIL_EXIT1 ("clock_gettime failed");
+ w_time.tv_nsec += 150000;
+
+ if (thrd_create (&id, signal_parent, NULL) != thrd_success)
+ FAIL_EXIT1 ("thrd_create failed");
+
+ if (cnd_timedwait (&cond, &mutex, &w_time) != thrd_success)
+ FAIL_EXIT1 ("cnd_timedwait failed");
+
+ if (thrd_join (id, NULL) != thrd_success)
+ FAIL_EXIT1 ("thrd_join failed");
+
+ mtx_destroy (&mutex);
+ cnd_destroy (&cond);
+
+ return 0;
+}
+
+#include <support/test-driver.c>
new file mode 100644
@@ -0,0 +1,73 @@
+/* C11 threads basic mutex tests.
+ Copyright (C) 2017 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <threads.h>
+#include <stdio.h>
+#include <unistd.h>
+
+#include <support/check.h>
+
+/* Shared mutex between child and parent. */
+static mtx_t mutex;
+
+/* Shared counter to check possible race conditions. */
+static int counter;
+
+static int
+child_add (void *arg)
+{
+ if (mtx_lock (&mutex) != thrd_success)
+ FAIL_EXIT1 ("mtx_lock failed");
+
+ counter++;
+
+ if (mtx_unlock (&mutex) != thrd_success)
+ FAIL_EXIT1 ("mtx_unlock failed");
+
+ thrd_exit (thrd_success);
+}
+
+static int
+do_test (void)
+{
+ mtx_init (&mutex, mtx_plain);
+
+ thrd_t id;
+ if (thrd_create (&id, child_add, NULL) != thrd_success)
+ FAIL_EXIT1 ("thrd_create failed");
+
+ if (mtx_lock (&mutex) != thrd_success)
+ FAIL_EXIT1 ("mtx_lock failed");
+
+ counter++;
+
+ if (mtx_unlock (&mutex) != thrd_success)
+ FAIL_EXIT1 ("mtx_unlock failed");
+
+ if (thrd_join (id, NULL) != thrd_success)
+ FAIL_EXIT1 ("thrd_join failed");
+
+ if (counter != 2)
+ FAIL_EXIT1 ("counter (%d) != 2", counter);
+
+ mtx_destroy (&mutex);
+
+ return 0;
+}
+
+#include <support/test-driver.c>
new file mode 100644
@@ -0,0 +1,45 @@
+/* C11 threads recursive mutex tests.
+ Copyright (C) 2017 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <threads.h>
+#include <stdio.h>
+#include <unistd.h>
+
+#include <support/check.h>
+
+static int
+do_test (void)
+{
+ static mtx_t mutex;
+
+ if (mtx_init (&mutex, mtx_recursive) != thrd_success)
+ FAIL_EXIT1 ("mtx_init failed");
+
+ if (mtx_lock (&mutex) != thrd_success)
+ FAIL_EXIT1 ("mtx_lock failed");
+
+ /* Lock mutex second time, if not recursive should deadlock. */
+ if (mtx_lock (&mutex) != thrd_success)
+ FAIL_EXIT1 ("mtx_lock failed");
+
+ mtx_destroy (&mutex);
+
+ return 0;
+}
+
+#include <support/test-driver.c>
new file mode 100644
@@ -0,0 +1,98 @@
+/* C11 threads timed mutex tests.
+ Copyright (C) 2017 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <threads.h>
+#include <stdio.h>
+#include <unistd.h>
+
+#include <support/check.h>
+
+/* Shared mutex between child and parent. */
+static mtx_t mutex;
+
+/* Shared counter to check possible race conditions. */
+static char shrd_counter;
+
+/* Maximum amount of time waiting for mutex. */
+static struct timespec wait_time;
+
+/* Function to choose an action to do, depending on mtx_timedlock
+ return value. */
+static inline void
+choose_action (int action, char* thread_name)
+{
+ switch (action)
+ {
+ case thrd_success:
+ ++shrd_counter;
+
+ if (mtx_unlock (&mutex) != thrd_success)
+ FAIL_EXIT1 ("mtx_unlock failed");
+ break;
+
+ case thrd_timedout:
+ break;
+
+ case thrd_error:
+ FAIL_EXIT1 ("%s lock error", thread_name);
+ break;
+ }
+}
+
+static int
+child_add (void *arg)
+{
+ char child_name[] = "child";
+
+ /* Try to lock mutex. */
+ choose_action (mtx_timedlock (&mutex, &wait_time), child_name);
+ thrd_exit (thrd_success);
+}
+
+static int
+do_test (void)
+{
+ thrd_t id;
+ char parent_name[] = "parent";
+
+ if (mtx_init (&mutex, mtx_timed) != thrd_success)
+ FAIL_EXIT1 ("mtx_init failed");
+
+ if (clock_gettime (CLOCK_REALTIME, &wait_time) != 0)
+ FAIL_EXIT1 ("clock_gettime failed");
+ /* Tiny amount of time, to assure that if any thread finds it busy.
+ It will receive thrd_timedout. */
+ wait_time.tv_nsec += 1;
+
+ if (thrd_create (&id, child_add, NULL) != thrd_success)
+ FAIL_EXIT1 ("thrd_create failed");
+
+ choose_action (mtx_timedlock (&mutex, &wait_time), parent_name);
+
+ if (thrd_join (id, NULL) != thrd_success)
+ FAIL_EXIT1 ("thrd_join failed");
+
+ if (shrd_counter != 2 && shrd_counter != 1)
+ FAIL_EXIT1 ("shrd_counter != {1,2} (%d)", shrd_counter);
+
+ mtx_destroy (&mutex);
+
+ return 0;
+}
+
+#include <support/test-driver.c>
new file mode 100644
@@ -0,0 +1,90 @@
+/* C11 threads trylock mutex tests.
+ Copyright (C) 2017 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <threads.h>
+#include <stdio.h>
+#include <unistd.h>
+
+#include <support/check.h>
+
+/* Shared mutex between child and parent. */
+static mtx_t mutex;
+
+/* Shared counter to check possible race conditions. */
+static char shrd_counter;
+
+/* Function to choose an action to do, depending on mtx_trylock
+ return value. */
+static inline void
+choose_action (int action, char* thread_name)
+{
+ switch (action)
+ {
+ case thrd_success:
+ ++shrd_counter;
+
+ if (mtx_unlock (&mutex) != thrd_success)
+ FAIL_EXIT1 ("mtx_unlock failed");
+ break;
+
+ case thrd_busy:
+ break;
+
+ case thrd_error:
+ FAIL_EXIT1 ("%s lock error", thread_name);
+ break;
+ }
+}
+
+static int
+child_add (void *arg)
+{
+ char child_name[] = "child";
+
+ /* Try to lock mutex. */
+ choose_action (mtx_trylock (&mutex), child_name);
+
+ thrd_exit (thrd_success);
+}
+
+static int
+do_test (void)
+{
+ thrd_t id;
+ char parent_name[] = "parent";
+
+ if (mtx_init (&mutex, mtx_timed) != thrd_success)
+ FAIL_EXIT1 ("mtx_init failed");
+
+ if (thrd_create (&id, child_add, NULL) != thrd_success)
+ FAIL_EXIT1 ("thrd_create failed");
+
+ choose_action (mtx_trylock (&mutex), parent_name);
+
+ if (thrd_join (id, NULL) != thrd_success)
+ FAIL_EXIT1 ("thrd_join failed");
+
+ if (shrd_counter != 2 && shrd_counter != 1)
+ FAIL_EXIT1 ("shrd_counter != {1,2} (%d)", shrd_counter);
+
+ mtx_destroy (&mutex);
+
+ return 0;
+}
+
+#include <support/test-driver.c>
new file mode 100644
@@ -0,0 +1,52 @@
+/* C11 threads thread detach tests.
+ Copyright (C) 2017 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <threads.h>
+#include <time.h>
+#include <stdio.h>
+#include <unistd.h>
+
+#include <support/check.h>
+
+static int
+detach_thrd (void *arg)
+{
+ if (thrd_detach (thrd_current ()) != thrd_success)
+ FAIL_EXIT1 ("thrd_detach failed");
+ thrd_exit (thrd_success);
+}
+
+static int
+do_test (void)
+{
+ thrd_t id;
+
+ /* Create new thread. */
+ if (thrd_create (&id, detach_thrd, NULL) != thrd_success)
+ FAIL_EXIT1 ("thrd_create failed");
+
+ /* Give some time so the thread can finish. */
+ thrd_sleep (&(struct timespec){.tv_sec = 2}, NULL);
+
+ if (thrd_join (id, NULL) == thrd_success)
+ FAIL_EXIT1 ("thrd_join succeed where it should fail");
+
+ return 0;
+}
+
+#include <support/test-driver.c>
new file mode 100644
@@ -0,0 +1,51 @@
+/* C11 threads thread sleep tests.
+ Copyright (C) 2017 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <threads.h>
+#include <time.h>
+#include <stdio.h>
+#include <unistd.h>
+
+#include <support/check.h>
+
+static int
+sleep_thrd (void *arg)
+{
+ struct timespec const *tl = (struct timespec const *) arg;
+ if (thrd_sleep (tl, NULL) != thrd_success)
+ FAIL_EXIT1 ("thrd_sleep failed");
+
+ thrd_exit (thrd_success);
+}
+
+static int
+do_test (void)
+{
+ thrd_t id;
+ struct timespec wait_time = {.tv_sec = 3};
+
+ if (thrd_create (&id, sleep_thrd, (void *) (&wait_time)) != thrd_success)
+ FAIL_EXIT1 ("thrd_create failed");
+
+ if (thrd_join (id, NULL) != thrd_success)
+ FAIL_EXIT1 ("thrd failed");
+
+ return 0;
+}
+
+#include <support/test-driver.c>
new file mode 100644
@@ -0,0 +1,75 @@
+/* C11 threads specific storage tests.
+ Copyright (C) 2017 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <threads.h>
+#include <stdio.h>
+#include <unistd.h>
+
+#include <support/check.h>
+
+/* Thread specific storage. */
+static tss_t key;
+
+#define TSS_VALUE (void*) 0xFF
+
+static int
+tss_thrd (void *arg)
+{
+ if (tss_create (&key, NULL) != thrd_success)
+ FAIL_EXIT1 ("tss_create failed");
+
+ if (tss_set (key, TSS_VALUE))
+ FAIL_EXIT1 ("tss_set failed");
+
+ void *value = tss_get (key);
+ if (value == 0)
+ FAIL_EXIT1 ("tss_get failed");
+ if (value != TSS_VALUE)
+ FAIL_EXIT1 ("tss_get returned %p, expected %p", value, TSS_VALUE);
+
+ thrd_exit (thrd_success);
+}
+
+static int
+do_test (void)
+{
+ /* Setting an invalid key should return an error. */
+ if (tss_set (key, TSS_VALUE) == thrd_success)
+ FAIL_EXIT1 ("tss_set succeed where it should have failed");
+
+ if (tss_create (&key, NULL) != thrd_success)
+ FAIL_EXIT1 ("tss_create failed");
+
+ thrd_t id;
+ if (thrd_create (&id, tss_thrd, NULL) != thrd_success)
+ FAIL_EXIT1 ("thrd_create failed");
+
+ if (thrd_join (id, NULL) != thrd_success)
+ FAIL_EXIT1 ("thrd failed");
+
+ /* The value set in tss_thrd should not be visible here. */
+ void *value = tss_get (key);
+ if (value != 0)
+ FAIL_EXIT1 ("tss_get succeed where it should have failed");
+
+ tss_delete (key);
+
+ return 0;
+}
+
+#include <support/test-driver.c>