15054e3e7Sguenther /*
25054e3e7Sguenther * Copyright (c) 2008 Bret S. Lambert <blambert@openbsd.org>
35054e3e7Sguenther *
45054e3e7Sguenther * Permission to use, copy, modify, and distribute this software for any
55054e3e7Sguenther * purpose with or without fee is hereby granted, provided that the above
65054e3e7Sguenther * copyright notice and this permission notice appear in all copies.
75054e3e7Sguenther *
85054e3e7Sguenther * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
95054e3e7Sguenther * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
105054e3e7Sguenther * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
115054e3e7Sguenther * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
125054e3e7Sguenther * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
135054e3e7Sguenther * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
145054e3e7Sguenther * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
155054e3e7Sguenther */
165054e3e7Sguenther
17f1f3d9f4Sguenther #include <err.h>
18*ffb4dd05Sguenther #include <errno.h>
195054e3e7Sguenther #include <stdio.h>
20cd1eb269Snaddy #include <stdlib.h>
215054e3e7Sguenther #include <string.h>
225054e3e7Sguenther #include <unistd.h>
235054e3e7Sguenther #include <pthread.h>
245054e3e7Sguenther
255054e3e7Sguenther #define THREAD_COUNT 64
265054e3e7Sguenther
275054e3e7Sguenther #define TEXT "barnacles"
285054e3e7Sguenther #define TEXT_N "barnacles\n"
295054e3e7Sguenther
305054e3e7Sguenther void run_threads(void (*)(void *), void *);
315054e3e7Sguenther
325054e3e7Sguenther static pthread_rwlock_t start;
335054e3e7Sguenther static void (*real_func)(void *);
345054e3e7Sguenther
355054e3e7Sguenther static void *
thread(void * arg)365054e3e7Sguenther thread(void *arg)
375054e3e7Sguenther {
385054e3e7Sguenther int r;
395054e3e7Sguenther
405054e3e7Sguenther if ((r = pthread_rwlock_rdlock(&start)))
415ad04d35Sguenther errc(1, r, "could not obtain lock in thread");
425054e3e7Sguenther real_func(arg);
435054e3e7Sguenther if ((r = pthread_rwlock_unlock(&start)))
445ad04d35Sguenther errc(1, r, "could not release lock in thread");
455054e3e7Sguenther return NULL;
465054e3e7Sguenther }
475054e3e7Sguenther
485054e3e7Sguenther void
run_threads(void (* func)(void *),void * arg)495054e3e7Sguenther run_threads(void (*func)(void *), void *arg)
505054e3e7Sguenther {
515054e3e7Sguenther pthread_t self, pthread[THREAD_COUNT];
525054e3e7Sguenther int i, r;
535054e3e7Sguenther
545054e3e7Sguenther self = pthread_self();
555054e3e7Sguenther real_func = func;
565054e3e7Sguenther if ((r = pthread_rwlock_init(&start, NULL)))
575ad04d35Sguenther errc(1, r, "could not initialize lock");
585054e3e7Sguenther
595054e3e7Sguenther if ((r = pthread_rwlock_wrlock(&start))) /* block */
605ad04d35Sguenther errc(1, r, "could not lock lock");
615054e3e7Sguenther
625054e3e7Sguenther for (i = 0; i < THREAD_COUNT; i++)
635054e3e7Sguenther if ((r = pthread_create(&pthread[i], NULL, thread, arg))) {
645ad04d35Sguenther warnc(r, "could not create thread");
655054e3e7Sguenther pthread[i] = self;
665054e3e7Sguenther }
675054e3e7Sguenther
685054e3e7Sguenther
695054e3e7Sguenther if ((r = pthread_rwlock_unlock(&start))) /* unleash */
705ad04d35Sguenther errc(1, r, "could not release lock");
715054e3e7Sguenther
725054e3e7Sguenther sleep(1);
735054e3e7Sguenther
745054e3e7Sguenther if ((r = pthread_rwlock_wrlock(&start))) /* sync */
755054e3e7Sguenther errx(1, "parent could not sync with children: %s",
765054e3e7Sguenther strerror(r));
775054e3e7Sguenther
785054e3e7Sguenther for (i = 0; i < THREAD_COUNT; i++)
795054e3e7Sguenther if (! pthread_equal(pthread[i], self) &&
805054e3e7Sguenther (r = pthread_join(pthread[i], NULL)))
815ad04d35Sguenther warnc(r, "could not join thread");
825054e3e7Sguenther }
835054e3e7Sguenther
84