diff options
| author | Enji Cooper <ngie@FreeBSD.org> | 2023-08-11 08:41:49 +0000 |
|---|---|---|
| committer | Enji Cooper <ngie@FreeBSD.org> | 2023-08-11 08:41:49 +0000 |
| commit | dc9c7dc6ec9ecb5449d71d79ae13f9782c866b73 (patch) | |
| tree | 77811130a73711377eb46a3e3eb9fac15fdcf746 /lib/libpthread | |
| parent | d328162dcb73d9041fe8ceb9fbae7276c3dacb53 (diff) | |
Diffstat (limited to 'lib/libpthread')
| -rw-r--r-- | lib/libpthread/Makefile | 11 | ||||
| -rw-r--r-- | lib/libpthread/h_resolv.c | 27 | ||||
| -rw-r--r-- | lib/libpthread/h_thread_local_dtor.cpp | 80 | ||||
| -rw-r--r--[-rwxr-xr-x] | lib/libpthread/t_atexit.sh | 0 | ||||
| -rw-r--r-- | lib/libpthread/t_call_once.c | 89 | ||||
| -rw-r--r--[-rwxr-xr-x] | lib/libpthread/t_cancel.sh | 0 | ||||
| -rw-r--r-- | lib/libpthread/t_cnd.c | 175 | ||||
| -rw-r--r-- | lib/libpthread/t_cond.c | 6 | ||||
| -rw-r--r-- | lib/libpthread/t_condwait.c | 23 | ||||
| -rw-r--r--[-rwxr-xr-x] | lib/libpthread/t_exit.sh | 0 | ||||
| -rw-r--r-- | lib/libpthread/t_join.c | 11 | ||||
| -rw-r--r-- | lib/libpthread/t_mtx.c | 212 | ||||
| -rw-r--r-- | lib/libpthread/t_mutex.c | 162 | ||||
| -rw-r--r-- | lib/libpthread/t_once.c | 5 | ||||
| -rw-r--r--[-rwxr-xr-x] | lib/libpthread/t_resolv.sh | 0 | ||||
| -rw-r--r-- | lib/libpthread/t_swapcontext.c | 24 | ||||
| -rw-r--r-- | lib/libpthread/t_thrd.c | 237 | ||||
| -rw-r--r-- | lib/libpthread/t_thread_local_dtor.sh | 41 | ||||
| -rw-r--r-- | lib/libpthread/t_tss.c | 174 |
19 files changed, 1071 insertions, 206 deletions
diff --git a/lib/libpthread/Makefile b/lib/libpthread/Makefile index cb84bcd0a807..6e689f263a1b 100644 --- a/lib/libpthread/Makefile +++ b/lib/libpthread/Makefile @@ -1,4 +1,4 @@ -# $NetBSD: Makefile,v 1.12 2016/10/30 16:17:16 kamil Exp $ +# $NetBSD: Makefile,v 1.15 2020/06/21 07:06:05 lukem Exp $ NOMAN= # defined @@ -38,6 +38,7 @@ TESTS_C+= t_sigsuspend TESTS_C+= t_siglongjmp TESTS_C+= t_sleep TESTS_C+= t_swapcontext +TESTS_SH+= t_thread_local_dtor TESTS_C+= t_timedmutex LDADD.t_sem+= -lrt @@ -47,6 +48,14 @@ PROGS= h_atexit PROGS+= h_cancel PROGS+= h_exit PROGS+= h_resolv +PROGS_CXX+= h_thread_local_dtor + +TESTS_C+= t_call_once t_cnd t_mtx t_thrd t_tss # C11 threads(3) + +COPTS.h_thread_local_dtor.cpp+= -std=c++11 +# Deal with questionable warning and header quality in libstdc++. +COPTS.h_thread_local_dtor.cpp+= ${${ACTIVE_CC} == "gcc" :? -Wno-ctor-dtor-privacy -Wno-sign-compare -Wno-shadow :} +SRCS.h_thread_local_dtor= h_thread_local_dtor.cpp FILESDIR= ${TESTSDIR} FILES= d_mach diff --git a/lib/libpthread/h_resolv.c b/lib/libpthread/h_resolv.c index 9c5fedcc2e7f..977cc02ec51f 100644 --- a/lib/libpthread/h_resolv.c +++ b/lib/libpthread/h_resolv.c @@ -1,4 +1,4 @@ -/* $NetBSD: h_resolv.c,v 1.2 2010/11/03 16:10:22 christos Exp $ */ +/* $NetBSD: h_resolv.c,v 1.3 2019/03/06 01:20:15 christos Exp $ */ /*- * Copyright (c) 2004, 2008 The NetBSD Foundation, Inc. @@ -32,7 +32,7 @@ #include <sys/cdefs.h> __COPYRIGHT("@(#) Copyright (c) 2008\ The NetBSD Foundation, inc. All rights reserved."); -__RCSID("$NetBSD: h_resolv.c,v 1.2 2010/11/03 16:10:22 christos Exp $"); +__RCSID("$NetBSD: h_resolv.c,v 1.3 2019/03/06 01:20:15 christos Exp $"); #include <pthread.h> #include <stdio.h> @@ -56,7 +56,7 @@ static void usage(void) __attribute__((__noreturn__)); static void load(const char *); static void resolvone(int); static void *resolvloop(void *); -static void run(int *); +static pthread_t run(int *); static pthread_mutex_t stats = PTHREAD_MUTEX_INITIALIZER; @@ -77,7 +77,7 @@ load(const char *fname) char *line; if ((fp = fopen(fname, "r")) == NULL) - err(1, "Cannot open `%s'", fname); + err(EXIT_FAILURE, "Cannot open `%s'", fname); while ((line = fgetln(fp, &len)) != NULL) { char c = line[len]; char *ptr; @@ -130,18 +130,20 @@ resolvloop(void *p) return NULL; } -static void +static pthread_t run(int *nhosts) { pthread_t self = pthread_self(); if (pthread_create(&self, NULL, resolvloop, nhosts) != 0) - err(1, "pthread_create"); + err(EXIT_FAILURE, "pthread_create"); + return self; } int main(int argc, char *argv[]) { int nthreads = NTHREADS; + pthread_t *threads; int nhosts = NHOSTS; int i, c, done, *nleft; hosts = sl_init(); @@ -170,16 +172,18 @@ main(int argc, char *argv[]) usage(); if ((nleft = malloc(nthreads * sizeof(int))) == NULL) - err(1, "malloc"); + err(EXIT_FAILURE, "malloc"); if ((ask = calloc(hosts->sl_cur, sizeof(int))) == NULL) - err(1, "calloc"); + err(EXIT_FAILURE, "calloc"); if ((got = calloc(hosts->sl_cur, sizeof(int))) == NULL) - err(1, "calloc"); + err(EXIT_FAILURE, "calloc"); + if ((threads = malloc(nthreads * sizeof(pthread_t))) == NULL) + err(EXIT_FAILURE, "calloc"); for (i = 0; i < nthreads; i++) { nleft[i] = nhosts; - run(&nleft[i]); + threads[i] = run(&nleft[i]); } for (done = 0; !done;) { @@ -200,6 +204,9 @@ main(int argc, char *argv[]) c++; } } + for (i = 0; i < nthreads; i++) + pthread_join(threads[i], NULL); + free(threads); free(nleft); free(ask); free(got); diff --git a/lib/libpthread/h_thread_local_dtor.cpp b/lib/libpthread/h_thread_local_dtor.cpp new file mode 100644 index 000000000000..337c207502db --- /dev/null +++ b/lib/libpthread/h_thread_local_dtor.cpp @@ -0,0 +1,80 @@ +/* + * Copyright (c) 2016 Tavian Barnes. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include <sys/cdefs.h> +__RCSID("$NetBSD: h_thread_local_dtor.cpp,v 1.1 2017/07/11 15:21:36 joerg Exp $"); + +#include <cstdlib> +#include <thread> + +static int seq; + +class OrderChecker { +public: + explicit OrderChecker(int n) : n_{n} { } + + ~OrderChecker() { + if (seq != n_) { + printf("Unexpected sequence point: %d\n", 3); + _Exit(1); + } + ++seq; + } + +private: + int n_; +}; + +template <int ID> +class CreatesThreadLocalInDestructor { +public: + ~CreatesThreadLocalInDestructor() { + thread_local OrderChecker checker{ID}; + } +}; + +OrderChecker global{7}; + +void thread_fn() { + static OrderChecker fn_static{5}; + thread_local CreatesThreadLocalInDestructor<2> creates_tl2; + thread_local OrderChecker fn_thread_local{1}; + thread_local CreatesThreadLocalInDestructor<0> creates_tl0; +} + +int main() { + static OrderChecker fn_static{6}; + + std::thread{thread_fn}.join(); + if (seq != 3) { + printf("Unexpected sequence point: %d\n", 3); + _Exit(1); + } + + thread_local OrderChecker fn_thread_local{4}; + thread_local CreatesThreadLocalInDestructor<3> creates_tl; + + return 0; +} diff --git a/lib/libpthread/t_atexit.sh b/lib/libpthread/t_atexit.sh index 7b99618e5bf3..7b99618e5bf3 100755..100644 --- a/lib/libpthread/t_atexit.sh +++ b/lib/libpthread/t_atexit.sh diff --git a/lib/libpthread/t_call_once.c b/lib/libpthread/t_call_once.c new file mode 100644 index 000000000000..92774ecced26 --- /dev/null +++ b/lib/libpthread/t_call_once.c @@ -0,0 +1,89 @@ +/* $NetBSD: t_call_once.c,v 1.1 2019/04/24 11:43:19 kamil Exp $ */ + +/*- + * Copyright (c) 2019 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Kamil Rytarowski. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include <sys/cdefs.h> +__COPYRIGHT("@(#) Copyright (c) 2019\ + The NetBSD Foundation, inc. All rights reserved."); +__RCSID("$NetBSD: t_call_once.c,v 1.1 2019/04/24 11:43:19 kamil Exp $"); + +#include <threads.h> + +#include <atf-c.h> + +ATF_TC(call_once); +ATF_TC_HEAD(call_once, tc) +{ + atf_tc_set_md_var(tc, "descr", "Test C11 call_once(3)"); +} + +#define CO_THREADS 8 + +static int co_val; +static once_flag oflag = ONCE_FLAG_INIT; + +static void +called_once(void) +{ + + ++co_val; +} + +static int +co_func(void *arg __unused) +{ + + call_once(&oflag, called_once); + + return 0; +} + +ATF_TC_BODY(call_once, tc) +{ + thrd_t t[CO_THREADS]; + size_t i; + + for (i = 0; i < CO_THREADS; i++) { + ATF_REQUIRE_EQ(thrd_create(&t[i], co_func, NULL), thrd_success); + } + + for (i = 0; i < CO_THREADS; i++) { + ATF_REQUIRE_EQ(thrd_join(t[i], NULL), thrd_success); + } + + ATF_REQUIRE_EQ(co_val, 1); +} + +ATF_TP_ADD_TCS(tp) +{ + ATF_TP_ADD_TC(tp, call_once); + + return atf_no_error(); +} diff --git a/lib/libpthread/t_cancel.sh b/lib/libpthread/t_cancel.sh index 4a0701ef3c76..4a0701ef3c76 100755..100644 --- a/lib/libpthread/t_cancel.sh +++ b/lib/libpthread/t_cancel.sh diff --git a/lib/libpthread/t_cnd.c b/lib/libpthread/t_cnd.c new file mode 100644 index 000000000000..c7846594f0a4 --- /dev/null +++ b/lib/libpthread/t_cnd.c @@ -0,0 +1,175 @@ +/* $NetBSD: t_cnd.c,v 1.1 2019/04/24 11:43:19 kamil Exp $ */ + +/*- + * Copyright (c) 2019 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Kamil Rytarowski. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include <sys/cdefs.h> +__COPYRIGHT("@(#) Copyright (c) 2019\ + The NetBSD Foundation, inc. All rights reserved."); +__RCSID("$NetBSD: t_cnd.c,v 1.1 2019/04/24 11:43:19 kamil Exp $"); + +#include <stdbool.h> +#include <threads.h> +#include <time.h> + +#include <atf-c.h> + +ATF_TC(cnd_init); +ATF_TC_HEAD(cnd_init, tc) +{ + atf_tc_set_md_var(tc, "descr", "Test C11 cnd_init(3)"); +} + +ATF_TC_BODY(cnd_init, tc) +{ + cnd_t c; + + ATF_REQUIRE_EQ(cnd_init(&c), thrd_success); + cnd_destroy(&c); +} + +#define B_THREADS 8 + +static mtx_t b_m; +static cnd_t b_c; +static bool b_finished; + +static int +b_func(void *arg) +{ + bool signal; + + signal = (bool)(intptr_t)arg; + + ATF_REQUIRE_EQ(mtx_lock(&b_m), thrd_success); + while (!b_finished) { + ATF_REQUIRE_EQ(cnd_wait(&b_c, &b_m), thrd_success); + } + ATF_REQUIRE_EQ(mtx_unlock(&b_m), thrd_success); + + if (signal) { + ATF_REQUIRE_EQ(cnd_signal(&b_c), thrd_success); + } + + return 0; +} + +static void +cnd_notify(bool signal) +{ + size_t i; + thrd_t t[B_THREADS]; + void *n; + + n = (void *)(intptr_t)signal; + + ATF_REQUIRE_EQ(mtx_init(&b_m, mtx_plain), thrd_success); + ATF_REQUIRE_EQ(cnd_init(&b_c), thrd_success); + + for (i = 0; i < B_THREADS; i++) { + ATF_REQUIRE_EQ(thrd_create(&t[i], b_func, n), thrd_success); + } + + ATF_REQUIRE_EQ(mtx_lock(&b_m), thrd_success); + b_finished = true; + ATF_REQUIRE_EQ(mtx_unlock(&b_m), thrd_success); + + if (signal) { + ATF_REQUIRE_EQ(cnd_signal(&b_c), thrd_success); + } else { + ATF_REQUIRE_EQ(cnd_broadcast(&b_c), thrd_success); + } + + for (i = 0; i < B_THREADS; i++) { + ATF_REQUIRE_EQ(thrd_join(t[i], NULL), thrd_success); + } + + mtx_destroy(&b_m); + cnd_destroy(&b_c); +} + +ATF_TC(cnd_broadcast); +ATF_TC_HEAD(cnd_broadcast, tc) +{ + atf_tc_set_md_var(tc, "descr", "Test C11 cnd_broadcast(3)"); +} + +ATF_TC_BODY(cnd_broadcast, tc) +{ + + cnd_notify(false); +} + +ATF_TC(cnd_signal); +ATF_TC_HEAD(cnd_signal, tc) +{ + atf_tc_set_md_var(tc, "descr", "Test C11 cnd_signal(3)"); +} + +ATF_TC_BODY(cnd_signal, tc) +{ + + cnd_notify(true); +} + +ATF_TC(cnd_timedwait); +ATF_TC_HEAD(cnd_timedwait, tc) +{ + atf_tc_set_md_var(tc, "descr", "Test C11 cnd_timedwait(3)"); +} + +ATF_TC_BODY(cnd_timedwait, tc) +{ + mtx_t m; + cnd_t c; + struct timespec ts; + + ts.tv_sec = 0; + ts.tv_nsec = 1; + + ATF_REQUIRE_EQ(mtx_init(&m, mtx_plain), thrd_success); + ATF_REQUIRE_EQ(cnd_init(&c), thrd_success); + + ATF_REQUIRE_EQ(mtx_lock(&m), thrd_success); + ATF_REQUIRE_EQ(cnd_timedwait(&c, &m, &ts), thrd_timedout); + ATF_REQUIRE_EQ(mtx_unlock(&m), thrd_success); + + mtx_destroy(&m); + cnd_destroy(&c); +} + +ATF_TP_ADD_TCS(tp) +{ + ATF_TP_ADD_TC(tp, cnd_init); + ATF_TP_ADD_TC(tp, cnd_broadcast); + ATF_TP_ADD_TC(tp, cnd_signal); + ATF_TP_ADD_TC(tp, cnd_timedwait); + + return atf_no_error(); +} diff --git a/lib/libpthread/t_cond.c b/lib/libpthread/t_cond.c index 83a3833015d1..8c93d706af23 100644 --- a/lib/libpthread/t_cond.c +++ b/lib/libpthread/t_cond.c @@ -1,4 +1,4 @@ -/* $NetBSD: t_cond.c,v 1.7 2016/07/03 14:24:59 christos Exp $ */ +/* $NetBSD: t_cond.c,v 1.8 2020/06/10 21:46:50 ad Exp $ */ /* * Copyright (c) 2008 The NetBSD Foundation, Inc. @@ -29,7 +29,7 @@ #include <sys/cdefs.h> __COPYRIGHT("@(#) Copyright (c) 2008\ The NetBSD Foundation, inc. All rights reserved."); -__RCSID("$NetBSD: t_cond.c,v 1.7 2016/07/03 14:24:59 christos Exp $"); +__RCSID("$NetBSD: t_cond.c,v 1.8 2020/06/10 21:46:50 ad Exp $"); #include <sys/time.h> @@ -329,7 +329,7 @@ pthread_cond_timedwait_func(void *arg) * Sometimes we catch ESRCH. * This should never happen. */ - ATF_REQUIRE(rv == ETIMEDOUT); + ATF_REQUIRE(rv == ETIMEDOUT || rv == 0); PTHREAD_REQUIRE(pthread_mutex_unlock(&static_mutex)); } } diff --git a/lib/libpthread/t_condwait.c b/lib/libpthread/t_condwait.c index 58b4a8bc155a..fcdaa27acf94 100644 --- a/lib/libpthread/t_condwait.c +++ b/lib/libpthread/t_condwait.c @@ -1,4 +1,4 @@ -/* $NetBSD: t_condwait.c,v 1.5 2017/01/16 16:29:19 christos Exp $ */ +/* $NetBSD: t_condwait.c,v 1.10 2022/12/11 10:02:53 kre Exp $ */ /* * Copyright (c) 2013 The NetBSD Foundation, Inc. @@ -26,7 +26,7 @@ * POSSIBILITY OF SUCH DAMAGE. */ #include <sys/cdefs.h> -__RCSID("$NetBSD: t_condwait.c,v 1.5 2017/01/16 16:29:19 christos Exp $"); +__RCSID("$NetBSD: t_condwait.c,v 1.10 2022/12/11 10:02:53 kre Exp $"); #include <sys/time.h> #include <errno.h> @@ -43,7 +43,7 @@ __RCSID("$NetBSD: t_condwait.c,v 1.5 2017/01/16 16:29:19 christos Exp $"); #include "h_common.h" -#define WAITTIME 2 /* Timeout wait secound */ +#define WAITTIME 2 /* Timeout wait in seconds */ static const int debug = 1; @@ -78,21 +78,18 @@ run(void *param) case ETIMEDOUT: /* Timeout */ ATF_REQUIRE_EQ(clock_gettime(clck, &te), 0); - timespecsub(&te, &to, &to); if (debug) { printf("timeout: %lld.%09ld sec\n", (long long)te.tv_sec, te.tv_nsec); + timespecsub(&te, &to, &to); printf("elapsed: %lld.%09ld sec\n", (long long)to.tv_sec, to.tv_nsec); } - if (isQEMU()) { - double to_seconds = to.tv_sec + 1e-9 * to.tv_nsec; - ATF_REQUIRE(to_seconds >= WAITTIME * 0.9); - /* Loose upper limit because of qemu timing bugs */ - ATF_REQUIRE(to_seconds < WAITTIME * 2.5); - } else { - ATF_REQUIRE_EQ(to.tv_sec, WAITTIME); - } + if (clck == CLOCK_MONOTONIC) + ATF_REQUIRE(timespeccmp(&te, &ts, >=)); + break; + case 0: + atf_tc_fail("pthread_cond_timedwait returned before timeout"); break; default: ATF_REQUIRE_MSG(0, "pthread_cond_timedwait: %s", strerror(ret)); @@ -141,5 +138,5 @@ ATF_TP_ADD_TCS(tp) { ATF_TP_ADD_TC(tp, cond_wait_real); ATF_TP_ADD_TC(tp, cond_wait_mono); - return 0; + return atf_no_error(); } diff --git a/lib/libpthread/t_exit.sh b/lib/libpthread/t_exit.sh index 7fbd689f5a68..7fbd689f5a68 100755..100644 --- a/lib/libpthread/t_exit.sh +++ b/lib/libpthread/t_exit.sh diff --git a/lib/libpthread/t_join.c b/lib/libpthread/t_join.c index 7f6f8348acfa..3823b0b77968 100644 --- a/lib/libpthread/t_join.c +++ b/lib/libpthread/t_join.c @@ -1,4 +1,4 @@ -/* $NetBSD: t_join.c,v 1.8 2012/03/12 20:17:16 joerg Exp $ */ +/* $NetBSD: t_join.c,v 1.10 2020/01/29 13:40:23 kamil Exp $ */ /*- * Copyright (c) 2010 The NetBSD Foundation, Inc. @@ -29,7 +29,7 @@ * POSSIBILITY OF SUCH DAMAGE. */ #include <sys/cdefs.h> -__RCSID("$NetBSD: t_join.c,v 1.8 2012/03/12 20:17:16 joerg Exp $"); +__RCSID("$NetBSD: t_join.c,v 1.10 2020/01/29 13:40:23 kamil Exp $"); #include <errno.h> #include <pthread.h> @@ -104,6 +104,7 @@ threadfunc1(void *arg) error = true; ATF_REQUIRE(pthread_attr_setstacksize(&attr, STACKSIZE * (i + 1)) == 0); + ATF_REQUIRE(pthread_attr_setguardsize(&attr, STACKSIZE * (i + 2)) == 0); rv = pthread_create(&thread[i], &attr, threadfunc2, (void *)i); @@ -148,13 +149,15 @@ threadfunc2(void *arg) static uintptr_t i = 0; uintptr_t j; pthread_attr_t attr; - size_t stacksize; + size_t stacksize, guardsize; j = (uintptr_t)arg; - ATF_REQUIRE(pthread_attr_get_np(pthread_self(), &attr) == 0); + ATF_REQUIRE(pthread_getattr_np(pthread_self(), &attr) == 0); ATF_REQUIRE(pthread_attr_getstacksize(&attr, &stacksize) == 0); ATF_REQUIRE(stacksize == STACKSIZE * (j + 1)); + ATF_REQUIRE(pthread_attr_getguardsize(&attr, &guardsize) == 0); + ATF_REQUIRE(guardsize == STACKSIZE * (j + 2)); ATF_REQUIRE(pthread_attr_destroy(&attr) == 0); if (i++ == j) diff --git a/lib/libpthread/t_mtx.c b/lib/libpthread/t_mtx.c new file mode 100644 index 000000000000..c559ff9087db --- /dev/null +++ b/lib/libpthread/t_mtx.c @@ -0,0 +1,212 @@ +/* $NetBSD: t_mtx.c,v 1.2 2020/06/11 11:40:54 martin Exp $ */ + +/*- + * Copyright (c) 2019 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Kamil Rytarowski. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include <sys/cdefs.h> +__COPYRIGHT("@(#) Copyright (c) 2019\ + The NetBSD Foundation, inc. All rights reserved."); +__RCSID("$NetBSD: t_mtx.c,v 1.2 2020/06/11 11:40:54 martin Exp $"); + +#include <time.h> +#include <threads.h> + +#include <atf-c.h> + +ATF_TC(mtx_init); +ATF_TC_HEAD(mtx_init, tc) +{ + atf_tc_set_md_var(tc, "descr", "Test C11 mtx_init(3)"); +} + +ATF_TC_BODY(mtx_init, tc) +{ + mtx_t m; + + ATF_REQUIRE_EQ(mtx_init(&m, mtx_plain), thrd_success); + mtx_destroy(&m); + + ATF_REQUIRE_EQ(mtx_init(&m, mtx_plain | mtx_recursive), thrd_success); + mtx_destroy(&m); + + ATF_REQUIRE_EQ(mtx_init(&m, mtx_timed), thrd_success); + mtx_destroy(&m); + + ATF_REQUIRE_EQ(mtx_init(&m, mtx_timed | mtx_recursive), thrd_success); + mtx_destroy(&m); + + ATF_REQUIRE_EQ(mtx_init(&m, mtx_recursive), thrd_error); + + ATF_REQUIRE_EQ(mtx_init(&m, mtx_plain | mtx_timed), thrd_error); + + ATF_REQUIRE_EQ(mtx_init(&m, -1), thrd_error); +} + +ATF_TC(mtx_lock); +ATF_TC_HEAD(mtx_lock, tc) +{ + atf_tc_set_md_var(tc, "descr", "Test C11 mtx_lock(3)"); +} + +ATF_TC_BODY(mtx_lock, tc) +{ + mtx_t m; + + ATF_REQUIRE_EQ(mtx_init(&m, mtx_plain), thrd_success); + ATF_REQUIRE_EQ(mtx_lock(&m), thrd_success); + ATF_REQUIRE_EQ(mtx_unlock(&m), thrd_success); + mtx_destroy(&m); + + ATF_REQUIRE_EQ(mtx_init(&m, mtx_timed), thrd_success); + ATF_REQUIRE_EQ(mtx_lock(&m), thrd_success); + ATF_REQUIRE_EQ(mtx_unlock(&m), thrd_success); + mtx_destroy(&m); + + ATF_REQUIRE_EQ(mtx_init(&m, mtx_plain | mtx_recursive), thrd_success); + ATF_REQUIRE_EQ(mtx_lock(&m), thrd_success); + ATF_REQUIRE_EQ(mtx_lock(&m), thrd_success); + ATF_REQUIRE_EQ(mtx_lock(&m), thrd_success); + ATF_REQUIRE_EQ(mtx_unlock(&m), thrd_success); + ATF_REQUIRE_EQ(mtx_unlock(&m), thrd_success); + ATF_REQUIRE_EQ(mtx_unlock(&m), thrd_success); + mtx_destroy(&m); + + ATF_REQUIRE_EQ(mtx_init(&m, mtx_timed | mtx_recursive), thrd_success); + ATF_REQUIRE_EQ(mtx_lock(&m), thrd_success); + ATF_REQUIRE_EQ(mtx_lock(&m), thrd_success); + ATF_REQUIRE_EQ(mtx_lock(&m), thrd_success); + ATF_REQUIRE_EQ(mtx_unlock(&m), thrd_success); + ATF_REQUIRE_EQ(mtx_unlock(&m), thrd_success); + ATF_REQUIRE_EQ(mtx_unlock(&m), thrd_success); + mtx_destroy(&m); +} + +ATF_TC(mtx_timedlock); +ATF_TC_HEAD(mtx_timedlock, tc) +{ + atf_tc_set_md_var(tc, "descr", "Test C11 mtx_timedlock(3)"); +} + +ATF_TC_BODY(mtx_timedlock, tc) +{ + mtx_t m; + struct timespec ts; + + ts.tv_sec = 0; + ts.tv_nsec = 1; + + ATF_REQUIRE_EQ(mtx_init(&m, mtx_timed), thrd_success); + ATF_REQUIRE_EQ(mtx_timedlock(&m, &ts), thrd_success); + ATF_REQUIRE_EQ(mtx_unlock(&m), thrd_success); + mtx_destroy(&m); + + ATF_REQUIRE_EQ(mtx_init(&m, mtx_timed), thrd_success); + ATF_REQUIRE_EQ(mtx_lock(&m), thrd_success); + ATF_REQUIRE_EQ(mtx_timedlock(&m, &ts), thrd_timedout); + ATF_REQUIRE_EQ(mtx_unlock(&m), thrd_success); + mtx_destroy(&m); + + ATF_REQUIRE_EQ(mtx_init(&m, mtx_timed | mtx_recursive), thrd_success); + ATF_REQUIRE_EQ(mtx_lock(&m), thrd_success); + ATF_REQUIRE_EQ(mtx_timedlock(&m, &ts), thrd_success); + ATF_REQUIRE_EQ(mtx_unlock(&m), thrd_success); + ATF_REQUIRE_EQ(mtx_unlock(&m), thrd_success); + mtx_destroy(&m); + + ATF_REQUIRE_EQ(mtx_init(&m, mtx_timed | mtx_recursive), thrd_success); + ATF_REQUIRE_EQ(mtx_timedlock(&m, &ts), thrd_success); + ATF_REQUIRE_EQ(mtx_timedlock(&m, &ts), thrd_success); + ATF_REQUIRE_EQ(mtx_unlock(&m), thrd_success); + ATF_REQUIRE_EQ(mtx_unlock(&m), thrd_success); + mtx_destroy(&m); + + ATF_REQUIRE_EQ(mtx_init(&m, mtx_timed | mtx_recursive), thrd_success); + ATF_REQUIRE_EQ(mtx_timedlock(&m, &ts), thrd_success); + ATF_REQUIRE_EQ(mtx_lock(&m), thrd_success); + ATF_REQUIRE_EQ(mtx_unlock(&m), thrd_success); + ATF_REQUIRE_EQ(mtx_unlock(&m), thrd_success); + mtx_destroy(&m); +} + +ATF_TC(mtx_trylock); +ATF_TC_HEAD(mtx_trylock, tc) +{ + atf_tc_set_md_var(tc, "descr", "Test C11 mtx_trylock(3)"); +} + +ATF_TC_BODY(mtx_trylock, tc) +{ + mtx_t m; + + ATF_REQUIRE_EQ(mtx_init(&m, mtx_plain), thrd_success); + ATF_REQUIRE_EQ(mtx_trylock(&m), thrd_success); + ATF_REQUIRE_EQ(mtx_unlock(&m), thrd_success); + mtx_destroy(&m); + + ATF_REQUIRE_EQ(mtx_init(&m, mtx_plain), thrd_success); + ATF_REQUIRE_EQ(mtx_lock(&m), thrd_success); + ATF_REQUIRE_EQ(mtx_trylock(&m), thrd_busy); + ATF_REQUIRE_EQ(mtx_unlock(&m), thrd_success); + mtx_destroy(&m); + + ATF_REQUIRE_EQ(mtx_init(&m, mtx_plain | mtx_recursive), thrd_success); + ATF_REQUIRE_EQ(mtx_lock(&m), thrd_success); + ATF_REQUIRE_EQ(mtx_trylock(&m), thrd_success); + ATF_REQUIRE_EQ(mtx_unlock(&m), thrd_success); + ATF_REQUIRE_EQ(mtx_unlock(&m), thrd_success); + mtx_destroy(&m); + + ATF_REQUIRE_EQ(mtx_init(&m, mtx_timed), thrd_success); + ATF_REQUIRE_EQ(mtx_trylock(&m), thrd_success); + ATF_REQUIRE_EQ(mtx_unlock(&m), thrd_success); + mtx_destroy(&m); + + ATF_REQUIRE_EQ(mtx_init(&m, mtx_timed), thrd_success); + ATF_REQUIRE_EQ(mtx_lock(&m), thrd_success); + ATF_REQUIRE_EQ(mtx_trylock(&m), thrd_busy); + ATF_REQUIRE_EQ(mtx_unlock(&m), thrd_success); + mtx_destroy(&m); + + ATF_REQUIRE_EQ(mtx_init(&m, mtx_timed | mtx_recursive), thrd_success); + ATF_REQUIRE_EQ(mtx_lock(&m), thrd_success); + ATF_REQUIRE_EQ(mtx_trylock(&m), thrd_success); + ATF_REQUIRE_EQ(mtx_unlock(&m), thrd_success); + ATF_REQUIRE_EQ(mtx_unlock(&m), thrd_success); + mtx_destroy(&m); +} + +ATF_TP_ADD_TCS(tp) +{ + ATF_TP_ADD_TC(tp, mtx_init); + ATF_TP_ADD_TC(tp, mtx_lock); + ATF_TP_ADD_TC(tp, mtx_timedlock); + ATF_TP_ADD_TC(tp, mtx_trylock); + + return atf_no_error(); +} diff --git a/lib/libpthread/t_mutex.c b/lib/libpthread/t_mutex.c index b706e462f3db..cef0d53e8fe8 100644 --- a/lib/libpthread/t_mutex.c +++ b/lib/libpthread/t_mutex.c @@ -1,4 +1,4 @@ -/* $NetBSD: t_mutex.c,v 1.15 2017/01/16 16:23:41 christos Exp $ */ +/* $NetBSD: t_mutex.c,v 1.20 2022/05/07 05:13:17 rin Exp $ */ /* * Copyright (c) 2008 The NetBSD Foundation, Inc. @@ -29,7 +29,7 @@ #include <sys/cdefs.h> __COPYRIGHT("@(#) Copyright (c) 2008\ The NetBSD Foundation, inc. All rights reserved."); -__RCSID("$NetBSD: t_mutex.c,v 1.15 2017/01/16 16:23:41 christos Exp $"); +__RCSID("$NetBSD: t_mutex.c,v 1.20 2022/05/07 05:13:17 rin Exp $"); #include <sys/time.h> /* For timespecadd */ #include <inttypes.h> /* For UINT16_MAX */ @@ -148,9 +148,7 @@ ATF_TC(mutex2); ATF_TC_HEAD(mutex2, tc) { atf_tc_set_md_var(tc, "descr", "Checks mutexes"); -#if defined(__powerpc__) - atf_tc_set_md_var(tc, "timeout", "40"); -#endif + atf_tc_set_md_var(tc, "timeout", "600"); } ATF_TC_BODY(mutex2, tc) { @@ -160,10 +158,6 @@ ATF_TC_BODY(mutex2, tc) printf("1: Mutex-test 2\n"); -#if defined(__powerpc__) - atf_tc_expect_timeout("PR port-powerpc/44387"); -#endif - PTHREAD_REQUIRE(pthread_mutex_init(&mutex, NULL)); global_x = 0; @@ -188,14 +182,6 @@ ATF_TC_BODY(mutex2, tc) printf("1: Thread joined. X was %d. Return value (long) was %ld\n", global_x, (long)joinval); ATF_REQUIRE_EQ(global_x, 20000000); - -#if defined(__powerpc__) - /* XXX force a timeout in ppc case since an un-triggered race - otherwise looks like a "failure" */ - /* We sleep for longer than the timeout to make ATF not - complain about unexpected success */ - sleep(41); -#endif } static void * @@ -219,9 +205,7 @@ ATF_TC_HEAD(mutex3, tc) { atf_tc_set_md_var(tc, "descr", "Checks mutexes using a static " "initializer"); -#if defined(__powerpc__) - atf_tc_set_md_var(tc, "timeout", "40"); -#endif + atf_tc_set_md_var(tc, "timeout", "600"); } ATF_TC_BODY(mutex3, tc) { @@ -231,10 +215,6 @@ ATF_TC_BODY(mutex3, tc) printf("1: Mutex-test 3\n"); -#if defined(__powerpc__) - atf_tc_expect_timeout("PR port-powerpc/44387"); -#endif - global_x = 0; count = count2 = 10000000; @@ -257,14 +237,6 @@ ATF_TC_BODY(mutex3, tc) printf("1: Thread joined. X was %d. Return value (long) was %ld\n", global_x, (long)joinval); ATF_REQUIRE_EQ(global_x, 20000000); - -#if defined(__powerpc__) - /* XXX force a timeout in ppc case since an un-triggered race - otherwise looks like a "failure" */ - /* We sleep for longer than the timeout to make ATF not - complain about unexpected success */ - sleep(41); -#endif } static void * @@ -401,131 +373,6 @@ ATF_TC_BODY(mutex5, tc) PTHREAD_REQUIRE(pthread_join(child, NULL)); } -static pthread_mutex_t mutex6; -static int start = 0; -static uintmax_t high_cnt = 0, low_cnt = 0, MAX_LOOP = 100000000; - -static void * -high_prio(void* arg) -{ - struct sched_param param; - int policy; - param.sched_priority = min_fifo_prio + 10; - pthread_t childid = pthread_self(); - - PTHREAD_REQUIRE(pthread_setschedparam(childid, 1, ¶m)); - PTHREAD_REQUIRE(pthread_getschedparam(childid, &policy, ¶m)); - printf("high protect = %d, prio = %d\n", - _sched_protect(-2), param.sched_priority); - ATF_REQUIRE_EQ(policy, 1); - printf("high prio = %d\n", param.sched_priority); - sleep(1); - long tmp = 0; - for (int i = 0; i < 20; i++) { - while (high_cnt < MAX_LOOP) { - tmp += (123456789 % 1234) * (987654321 % 54321); - high_cnt += 1; - } - high_cnt = 0; - sleep(1); - } - PTHREAD_REQUIRE(mutex_lock(&mutex6, &ts_lengthy)); - if (start == 0) start = 2; - PTHREAD_REQUIRE(pthread_mutex_unlock(&mutex6)); - - return 0; -} - -static void * -low_prio(void* arg) -{ - struct sched_param param; - int policy; - param.sched_priority = min_fifo_prio; - pthread_t childid = pthread_self(); - int res = _sched_protect(max_fifo_prio); - ATF_REQUIRE_EQ(res, 0); - PTHREAD_REQUIRE(pthread_setschedparam(childid, 1, ¶m)); - PTHREAD_REQUIRE(pthread_getschedparam(childid, &policy, ¶m)); - printf("low protect = %d, prio = %d\n", _sched_protect(-2), - param.sched_priority); - ATF_REQUIRE_EQ(policy, 1); - printf("low prio = %d\n", param.sched_priority); - sleep(1); - long tmp = 0; - for (int i = 0; i < 20; i++) { - while (low_cnt < MAX_LOOP) { - tmp += (123456789 % 1234) * (987654321 % 54321); - low_cnt += 1; - } - low_cnt = 0; - sleep(1); - } - PTHREAD_REQUIRE(mutex_lock(&mutex6, &ts_lengthy)); - if (start == 0) - start = 1; - PTHREAD_REQUIRE(pthread_mutex_unlock(&mutex6)); - - return 0; -} - -ATF_TC(mutex6); -ATF_TC_HEAD(mutex6, tc) -{ - atf_tc_set_md_var(tc, "descr", - "Checks scheduling for priority ceiling"); - atf_tc_set_md_var(tc, "require.user", "root"); -} - -/* - * 1. main thread sets itself to be a realtime task and launched two tasks, - * one has higher priority and the other has lower priority. - * 2. each child thread(low and high priority thread) sets its scheduler and - * priority. - * 3. each child thread did several rounds of computation, after each round it - * sleep 1 second. - * 4. the child thread with low priority will call _sched_protect to increase - * its protect priority. - * 5. We verify the thread with low priority runs first. - * - * Why does it work? From the main thread, we launched the high - * priority thread first. This gives this thread the benefit of - * starting first. The low priority thread did not call _sched_protect(2). - * The high priority thread should finish the task first. After each - * round of computation, we call sleep, to put the task into the - * sleep queue, and wake up again after the timer expires. This - * gives the scheduler the chance to decide which task to run. So, - * the thread with real high priority will always block the thread - * with real low priority. - * - */ -ATF_TC_BODY(mutex6, tc) -{ - struct sched_param param; - int res; - pthread_t high, low; - - min_fifo_prio = sched_get_priority_min(SCHED_FIFO); - max_fifo_prio = sched_get_priority_max(SCHED_FIFO); - PTHREAD_REQUIRE(pthread_mutex_init(&mutex, NULL)); - printf("min_fifo_prio = %d, max_fifo_info = %d\n", min_fifo_prio, - max_fifo_prio); - - param.sched_priority = min_fifo_prio; - res = sched_setscheduler(getpid(), SCHED_FIFO, ¶m); - printf("previous policy used = %d\n", res); - - res = sched_getscheduler(getpid()); - ATF_REQUIRE_EQ(res, 1); - PTHREAD_REQUIRE(pthread_create(&high, NULL, high_prio, NULL)); - PTHREAD_REQUIRE(pthread_create(&low, NULL, low_prio, NULL)); - sleep(5); - PTHREAD_REQUIRE(pthread_join(low, NULL)); - PTHREAD_REQUIRE(pthread_join(high, NULL)); - - ATF_REQUIRE_EQ(start, 1); -} - ATF_TC(mutexattr1); ATF_TC_HEAD(mutexattr1, tc) { @@ -710,7 +557,6 @@ ATF_TP_ADD_TCS(tp) ATF_TP_ADD_TC(tp, mutex3); ATF_TP_ADD_TC(tp, mutex4); ATF_TP_ADD_TC(tp, mutex5); - ATF_TP_ADD_TC(tp, mutex6); ATF_TP_ADD_TC(tp, mutexattr1); ATF_TP_ADD_TC(tp, mutexattr2); diff --git a/lib/libpthread/t_once.c b/lib/libpthread/t_once.c index 575d5d7ef890..650f3ee68dfd 100644 --- a/lib/libpthread/t_once.c +++ b/lib/libpthread/t_once.c @@ -1,4 +1,4 @@ -/* $NetBSD: t_once.c,v 1.1 2010/07/16 15:42:53 jmmv Exp $ */ +/* $NetBSD: t_once.c,v 1.2 2017/08/25 22:59:47 ginsbach Exp $ */ /* * Copyright (c) 2008 The NetBSD Foundation, Inc. @@ -29,8 +29,9 @@ #include <sys/cdefs.h> __COPYRIGHT("@(#) Copyright (c) 2008\ The NetBSD Foundation, inc. All rights reserved."); -__RCSID("$NetBSD: t_once.c,v 1.1 2010/07/16 15:42:53 jmmv Exp $"); +__RCSID("$NetBSD: t_once.c,v 1.2 2017/08/25 22:59:47 ginsbach Exp $"); +#include <sys/time.h> #include <pthread.h> #include <signal.h> #include <stdio.h> diff --git a/lib/libpthread/t_resolv.sh b/lib/libpthread/t_resolv.sh index 847eadcaec24..847eadcaec24 100755..100644 --- a/lib/libpthread/t_resolv.sh +++ b/lib/libpthread/t_resolv.sh diff --git a/lib/libpthread/t_swapcontext.c b/lib/libpthread/t_swapcontext.c index 677c51fc8601..69f004ead082 100644 --- a/lib/libpthread/t_swapcontext.c +++ b/lib/libpthread/t_swapcontext.c @@ -1,4 +1,4 @@ -/* $NetBSD: t_swapcontext.c,v 1.3 2017/01/16 16:27:06 christos Exp $ */ +/* $NetBSD: t_swapcontext.c,v 1.9 2018/02/28 21:36:50 uwe Exp $ */ /* * Copyright (c) 2012 Emmanuel Dreyfus. All rights reserved. @@ -26,7 +26,7 @@ */ #include <sys/cdefs.h> -__RCSID("$NetBSD"); +__RCSID("$NetBSD: t_swapcontext.c,v 1.9 2018/02/28 21:36:50 uwe Exp $"); #include <sys/types.h> #include <errno.h> @@ -49,24 +49,18 @@ void *oself; void *nself; int val1, val2; -/* ARGSUSED0 */ static void -swapfunc(void *arg) +swapfunc(void) { /* - * If the test fails, we are very likely to crash + * If the test fails, we are very likely to crash * without the opportunity to report - */ + */ nself = (void *)pthread_self(); printf("after swapcontext self = %p\n", nself); ATF_REQUIRE_EQ(oself, nself); printf("Test succeeded\n"); - /* Go back in main */ - ATF_REQUIRE(swapcontext(&nctx, &octx)); - - /* NOTREACHED */ - return; } /* ARGSUSED0 */ @@ -75,15 +69,15 @@ threadfunc(void *arg) { nctx.uc_stack.ss_sp = stack; nctx.uc_stack.ss_size = sizeof(stack); - - makecontext(&nctx, (void *)*swapfunc, 0); - + nctx.uc_link = &octx; + + makecontext(&nctx, swapfunc, 0); + oself = (void *)pthread_self(); printf("before swapcontext self = %p\n", oself); ATF_REQUIRE_MSG(swapcontext(&octx, &nctx) != -1, "swapcontext failed: %s", strerror(errno)); - /* NOTREACHED */ return NULL; } diff --git a/lib/libpthread/t_thrd.c b/lib/libpthread/t_thrd.c new file mode 100644 index 000000000000..7cbebdae9d27 --- /dev/null +++ b/lib/libpthread/t_thrd.c @@ -0,0 +1,237 @@ +/* $NetBSD: t_thrd.c,v 1.2 2020/05/14 08:34:19 msaitoh Exp $ */ + +/*- + * Copyright (c) 2019 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Kamil Rytarowski. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include <sys/cdefs.h> +__COPYRIGHT("@(#) Copyright (c) 2019\ + The NetBSD Foundation, inc. All rights reserved."); +__RCSID("$NetBSD: t_thrd.c,v 1.2 2020/05/14 08:34:19 msaitoh Exp $"); + +#include <signal.h> +#include <stdbool.h> +#include <threads.h> +#include <time.h> + +#include <atf-c.h> + +ATF_TC(thrd_create); +ATF_TC_HEAD(thrd_create, tc) +{ + atf_tc_set_md_var(tc, "descr", "Test C11 thrd_create(3)"); +} + +#define TC_ADDON 5 + +static int +tcr_func(void *arg) +{ + int a; + + a = (int)(intptr_t)arg; + + return a + TC_ADDON; +} + +ATF_TC_BODY(thrd_create, tc) +{ + thrd_t t; + const int a = 5; + int b; + void *v; + + v = (void *)(intptr_t)a; + + ATF_REQUIRE_EQ(thrd_create(&t, tcr_func, v), thrd_success); + ATF_REQUIRE_EQ(thrd_join(t, &b), thrd_success); + ATF_REQUIRE_EQ(a + TC_ADDON, b); +} + +ATF_TC(thrd_current); +ATF_TC_HEAD(thrd_current, tc) +{ + atf_tc_set_md_var(tc, "descr", "Test C11 thrd_current(3)"); +} + +static int +tcur_func(void *arg __unused) +{ + + return 0; +} + +ATF_TC_BODY(thrd_current, tc) +{ + thrd_t s, t; + + s = thrd_current(); + + ATF_REQUIRE(thrd_equal(s, s) != 0); + ATF_REQUIRE_EQ(thrd_create(&t, tcur_func, NULL), thrd_success); + ATF_REQUIRE(thrd_equal(t, s) == 0); + ATF_REQUIRE(thrd_equal(s, t) == 0); + ATF_REQUIRE(thrd_equal(t, t) != 0); + + ATF_REQUIRE_EQ(thrd_join(t, NULL), thrd_success); +} + +ATF_TC(thrd_detach); +ATF_TC_HEAD(thrd_detach, tc) +{ + atf_tc_set_md_var(tc, "descr", "Test C11 thrd_detach(3)"); +} + +static int +tdet_func(void *arg __unused) +{ + + return 0; +} + +ATF_TC_BODY(thrd_detach, tc) +{ + thrd_t t; + + ATF_REQUIRE_EQ(thrd_create(&t, tdet_func, NULL), thrd_success); + ATF_REQUIRE_EQ(thrd_detach(t), thrd_success); +} + +ATF_TC(thrd_exit); +ATF_TC_HEAD(thrd_exit, tc) +{ + atf_tc_set_md_var(tc, "descr", "Test C11 thrd_exit(3)"); +} + +static void +tex_func2(void) +{ + + thrd_exit(1); +} + +static int +tex_func(void *arg __unused) +{ + + tex_func2(); + + return -1; +} + +ATF_TC_BODY(thrd_exit, tc) +{ + thrd_t t; + int b = 0; + + ATF_REQUIRE_EQ(thrd_create(&t, tex_func, NULL), thrd_success); + ATF_REQUIRE_EQ(thrd_join(t, &b), thrd_success); + ATF_REQUIRE_EQ(b, 1); +} + +ATF_TC(thrd_sleep); +ATF_TC_HEAD(thrd_sleep, tc) +{ + atf_tc_set_md_var(tc, "descr", "Test C11 thrd_sleep(3)"); +} + +static int alarmed; + +static void +alarm_handler(int signum) +{ + + ATF_REQUIRE_EQ(signum, SIGALRM); + ++alarmed; +} + +ATF_TC_BODY(thrd_sleep, tc) +{ + struct timespec start, stop, diff; + struct timespec ts, rem; + struct timespec zero; + struct sigaction sa; + struct itimerval timer; + + zero.tv_sec = 0; + zero.tv_nsec = 0; + + ts.tv_sec = 1; + ts.tv_nsec = -1; + ATF_REQUIRE_EQ(!thrd_sleep(&ts, NULL), 0); + + ts.tv_sec = 0; + ts.tv_nsec = 1000000000/100; /* 1/100 sec */ + ATF_REQUIRE_EQ(clock_gettime(CLOCK_MONOTONIC, &start), 0); + ATF_REQUIRE_EQ(thrd_sleep(&ts, &rem), 0); + ATF_REQUIRE_EQ(clock_gettime(CLOCK_MONOTONIC, &stop), 0); + timespecsub(&stop, &start, &diff); + ATF_REQUIRE(timespeccmp(&diff, &ts, >=)); + ATF_REQUIRE(timespeccmp(&zero, &rem, ==)); + + ts.tv_sec = 1; + ts.tv_nsec = 0; + memset(&sa, 0, sizeof(sa)); + sa.sa_handler = alarm_handler; + sigaction(SIGALRM, &sa, NULL); + memset(&timer, 0, sizeof(timer)); + timer.it_value.tv_sec = 0; + timer.it_value.tv_usec = 100000; /* 100 msec */ + ATF_REQUIRE_EQ(setitimer(ITIMER_MONOTONIC, &timer, NULL), 0); + ATF_REQUIRE_EQ(clock_gettime(CLOCK_MONOTONIC, &start), 0); + ATF_REQUIRE_EQ(!thrd_sleep(&ts, &rem), 0); + ATF_REQUIRE_EQ(clock_gettime(CLOCK_MONOTONIC, &stop), 0); + timespecsub(&stop, &start, &diff); + ATF_REQUIRE(timespeccmp(&diff, &ts, <)); + ATF_REQUIRE(timespeccmp(&zero, &rem, !=)); + ATF_REQUIRE_EQ(alarmed, 1); +} + +ATF_TC(thrd_yield); +ATF_TC_HEAD(thrd_yield, tc) +{ + atf_tc_set_md_var(tc, "descr", "Test C11 thrd_yield(3)"); +} + +ATF_TC_BODY(thrd_yield, tc) +{ + + thrd_yield(); +} + +ATF_TP_ADD_TCS(tp) +{ + ATF_TP_ADD_TC(tp, thrd_create); + ATF_TP_ADD_TC(tp, thrd_current); + ATF_TP_ADD_TC(tp, thrd_detach); + ATF_TP_ADD_TC(tp, thrd_exit); + ATF_TP_ADD_TC(tp, thrd_sleep); + ATF_TP_ADD_TC(tp, thrd_yield); + + return atf_no_error(); +} diff --git a/lib/libpthread/t_thread_local_dtor.sh b/lib/libpthread/t_thread_local_dtor.sh new file mode 100644 index 000000000000..439ebd798505 --- /dev/null +++ b/lib/libpthread/t_thread_local_dtor.sh @@ -0,0 +1,41 @@ +# $NetBSD: t_thread_local_dtor.sh,v 1.1 2017/07/11 15:21:36 joerg Exp $ +# +# Copyright (c) 2008 The NetBSD Foundation, Inc. +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS +# ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED +# TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS +# BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. +# + +atf_test_case thread_local_dtor_order +thread_local_dtor_order_head() +{ + atf_set "descr" "Checks destructor order for thread_local objects" +} +thread_local_dtor_order_body() +{ + atf_check -o ignore "$(atf_get_srcdir)/h_thread_local_dtor" +} + +atf_init_test_cases() +{ + atf_add_test_case thread_local_dtor_order +} diff --git a/lib/libpthread/t_tss.c b/lib/libpthread/t_tss.c new file mode 100644 index 000000000000..7bdd231f22ca --- /dev/null +++ b/lib/libpthread/t_tss.c @@ -0,0 +1,174 @@ +/* $NetBSD: t_tss.c,v 1.1 2019/04/24 11:43:19 kamil Exp $ */ + +/*- + * Copyright (c) 2019 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Kamil Rytarowski. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include <sys/cdefs.h> +__COPYRIGHT("@(#) Copyright (c) 2019\ + The NetBSD Foundation, inc. All rights reserved."); +__RCSID("$NetBSD: t_tss.c,v 1.1 2019/04/24 11:43:19 kamil Exp $"); + +#include <stdlib.h> +#include <threads.h> + +#include <atf-c.h> + +ATF_TC(tss_create); +ATF_TC_HEAD(tss_create, tc) +{ + atf_tc_set_md_var(tc, "descr", "Test C11 tss_create(3)"); +} + +ATF_TC_BODY(tss_create, tc) +{ + tss_t s; + + ATF_REQUIRE_EQ(tss_create(&s, NULL), thrd_success); + tss_delete(s); +} + +ATF_TC(tss_set); +ATF_TC_HEAD(tss_set, tc) +{ + atf_tc_set_md_var(tc, "descr", "Test C11 tss_set(3)"); +} + +ATF_TC_BODY(tss_set, tc) +{ + tss_t s; + int b = 5; + void *v; + + v = (void *)(intptr_t)b; + + ATF_REQUIRE_EQ(tss_create(&s, NULL), thrd_success); + ATF_REQUIRE_EQ(tss_get(s), NULL); + ATF_REQUIRE_EQ(tss_set(s, v), thrd_success); + ATF_REQUIRE_EQ(tss_get(s), v); + + tss_delete(s); +} + +ATF_TC(tss_destructor_main_thread); +ATF_TC_HEAD(tss_destructor_main_thread, tc) +{ + atf_tc_set_md_var(tc, "descr", + "Test C11 tss(3) destructor in main thread"); +} + +static void +c_destructor_main(void *arg) +{ + + abort(); +} + +ATF_TC_BODY(tss_destructor_main_thread, tc) +{ + tss_t s; + int b = 5; + void *v; + + v = (void *)(intptr_t)b; + + ATF_REQUIRE_EQ(tss_create(&s, c_destructor_main), thrd_success); + ATF_REQUIRE_EQ(tss_set(s, v), thrd_success); + + tss_delete(s); + + /* Destructor must NOT be called for tss_delete(3) */ +} + +ATF_TC(tss_destructor_thread_exit); +ATF_TC_HEAD(tss_destructor_thread_exit, tc) +{ + atf_tc_set_md_var(tc, "descr", + "Test C11 tss(3) destructor on thread exit"); +} + +static tss_t s_empty, s_nonempty; +static int c_iter_empty, c_iter_nonempty; + +static void +c_destructor_thread_empty(void *arg) +{ + + tss_set(s_empty, arg); + ++c_iter_empty; +} + +static void +c_destructor_thread_nonempty(void *arg) +{ + + tss_set(s_nonempty, arg); + ++c_iter_nonempty; +} + +static int +t_func(void *arg __unused) +{ + int b = 5; + void *v; + + v = (void *)(intptr_t)b; + + ATF_REQUIRE_EQ(tss_set(s_nonempty, v), thrd_success); + + return 0; +} + +ATF_TC_BODY(tss_destructor_thread_exit, tc) +{ + thrd_t t; + + ATF_REQUIRE_EQ(tss_create(&s_empty, c_destructor_thread_empty), + thrd_success); + ATF_REQUIRE_EQ(tss_create(&s_nonempty, c_destructor_thread_nonempty), + thrd_success); + + ATF_REQUIRE_EQ(thrd_create(&t, t_func, NULL), thrd_success); + ATF_REQUIRE_EQ(thrd_join(t, NULL), thrd_success); + + ATF_REQUIRE_EQ(c_iter_empty, 0); + ATF_REQUIRE_EQ(c_iter_nonempty, TSS_DTOR_ITERATIONS); + + tss_delete(s_empty); + tss_delete(s_nonempty); +} + +ATF_TP_ADD_TCS(tp) +{ + ATF_TP_ADD_TC(tp, tss_create); + ATF_TP_ADD_TC(tp, tss_set); + ATF_TP_ADD_TC(tp, tss_destructor_main_thread); + ATF_TP_ADD_TC(tp, tss_destructor_thread_exit); + + return atf_no_error(); +} |
