1*297694a9Sguenther /* $OpenBSD: sem_wait.c,v 1.3 2012/03/03 09:51:00 guenther Exp $ */
23fbe19a4Smpi /*
33fbe19a4Smpi * Martin Pieuchot <mpi@openbsd.org>, 2011. Public Domain.
43fbe19a4Smpi */
53fbe19a4Smpi
6*297694a9Sguenther #include <err.h>
73fbe19a4Smpi #include <errno.h>
83fbe19a4Smpi #include <unistd.h>
93fbe19a4Smpi #include <semaphore.h>
10*297694a9Sguenther #include <signal.h>
113fbe19a4Smpi #include <pthread.h>
123fbe19a4Smpi #include "test.h"
133fbe19a4Smpi
143fbe19a4Smpi
153fbe19a4Smpi void *waiter(void *arg);
163fbe19a4Smpi
17*297694a9Sguenther void
handler(int sig)18*297694a9Sguenther handler(int sig)
19*297694a9Sguenther {
20*297694a9Sguenther static char message[] = "got sig\n";
21*297694a9Sguenther
22*297694a9Sguenther write(STDERR_FILENO, message, sizeof(message) - 1);
23*297694a9Sguenther }
24*297694a9Sguenther
25ce8a7339Sguenther sem_t sem;
26*297694a9Sguenther volatile int posted = 0, eintr_ok = 0;
27ce8a7339Sguenther
283fbe19a4Smpi int
main(int argc,char ** argv)293fbe19a4Smpi main(int argc, char **argv)
303fbe19a4Smpi {
313fbe19a4Smpi pthread_t th;
32*297694a9Sguenther struct sigaction sa;
333fbe19a4Smpi
343fbe19a4Smpi CHECKn(sem_wait(&sem));
353fbe19a4Smpi ASSERT(errno == EINVAL);
363fbe19a4Smpi
373fbe19a4Smpi CHECKr(sem_init(&sem, 0, 0));
383fbe19a4Smpi
393fbe19a4Smpi CHECKr(pthread_create(&th, NULL, waiter, &sem));
403fbe19a4Smpi
413fbe19a4Smpi sleep(1);
423fbe19a4Smpi
43*297694a9Sguenther printf("expect: sem_destroy on semaphore with waiters!\n");
443fbe19a4Smpi CHECKn(sem_destroy(&sem));
453fbe19a4Smpi ASSERT(errno == EBUSY);
463fbe19a4Smpi
47*297694a9Sguenther posted = 1;
48*297694a9Sguenther CHECKr(sem_post(&sem));
49*297694a9Sguenther CHECKr(pthread_join(th, NULL));
50*297694a9Sguenther
51*297694a9Sguenther /* test that sem_wait() resumes after handling a signal */
52*297694a9Sguenther memset(&sa, 0, sizeof sa);
53*297694a9Sguenther sa.sa_handler = &handler;
54*297694a9Sguenther sigemptyset(&sa.sa_mask);
55*297694a9Sguenther sa.sa_flags = 0;
56*297694a9Sguenther if (sigaction(SIGUSR1, &sa, NULL))
57*297694a9Sguenther err(1, "sigaction");
58*297694a9Sguenther posted = 0;
59*297694a9Sguenther CHECKr(pthread_create(&th, NULL, waiter, &sem));
60*297694a9Sguenther sleep(1);
61*297694a9Sguenther fprintf(stderr, "sending sig\n");
62*297694a9Sguenther eintr_ok = 1;
63*297694a9Sguenther pthread_kill(th, SIGUSR1);
64*297694a9Sguenther sleep(1);
65*297694a9Sguenther fprintf(stderr, "posting\n");
66*297694a9Sguenther posted = 1;
67*297694a9Sguenther eintr_ok = 0;
683fbe19a4Smpi CHECKr(sem_post(&sem));
693fbe19a4Smpi CHECKr(pthread_join(th, NULL));
703fbe19a4Smpi
713fbe19a4Smpi CHECKe(sem_destroy(&sem));
723fbe19a4Smpi
733fbe19a4Smpi SUCCEED;
743fbe19a4Smpi }
753fbe19a4Smpi
763fbe19a4Smpi void *
waiter(void * arg)773fbe19a4Smpi waiter(void *arg)
783fbe19a4Smpi {
793fbe19a4Smpi sem_t *semp = arg;
80*297694a9Sguenther int value;
81*297694a9Sguenther int r;
823fbe19a4Smpi
83*297694a9Sguenther r = sem_wait(semp);
84*297694a9Sguenther CHECKr(sem_getvalue(semp, &value));
85*297694a9Sguenther if (r == 0) {
86*297694a9Sguenther ASSERT(value == 0);
87*297694a9Sguenther ASSERT(posted != 0);
88*297694a9Sguenther } else {
89*297694a9Sguenther ASSERT(r == -1);
90*297694a9Sguenther ASSERT(errno == EINTR);
91*297694a9Sguenther ASSERT(eintr_ok);
92*297694a9Sguenther if (posted)
93*297694a9Sguenther ASSERT(value == 1);
94*297694a9Sguenther else
95*297694a9Sguenther ASSERT(value == 0);
96*297694a9Sguenther }
973fbe19a4Smpi
983fbe19a4Smpi return (NULL);
993fbe19a4Smpi }
100