#include #include #include #include #include #include #include unsigned long long nloop; static void onsig(int signo) { char buf[128]; snprintf_ss(buf, sizeof(buf), "signal %d after %llu trials\n", signo, nloop); (void)write(STDOUT_FILENO, buf, strlen(buf)); if (signo == SIGINFO) return; (void)signal(signo, SIG_DFL); (void)raise(signo); } pthread_once_t once, once0 = PTHREAD_ONCE_INIT; int done = 0; static void init(void) { done = 1; } static void * thread(void *cookie) { pthread_barrier_t *bar = cookie; (void)pthread_barrier_wait(bar); pthread_once(&once, &init); if (!done) errx(1, "fail after %llu trials", nloop); } int main(int argc, char **argv) { enum { N = 256 }; unsigned n = argc == 2 ? atoi(argv[1]) : 16; if (n < 1) errx(1, "not enough"); if (n > N) errx(1, "too many"); if (signal(SIGINT, &onsig) == SIG_ERR) err(1, "signal(SIGINT)"); if (signal(SIGINFO, &onsig) == SIG_ERR) err(1, "signal(SIGINFO)"); for (;; nloop++) { pthread_barrier_t bar; pthread_t t[N]; unsigned i; int error; error = pthread_barrier_init(&bar, NULL, n); if (error) errc(1, error, "pthread_barrier_init"); for (i = 0; i < n - 1; i++) { error = pthread_create(&t[i], NULL, &thread, &bar); if (error) errc(1, error, "pthread_create"); } once = once0; done = 0; (void)pthread_barrier_wait(&bar); pthread_once(&once, &init); if (!done) errx(1, "fail"); for (i = 0; i < n - 1; i++) { error = pthread_join(t[i], NULL); if (error) errc(1, error, "pthread_join"); } error = pthread_barrier_destroy(&bar); if (error) errc(1, error, "pthread_barrier_destroy"); } }