xref: /openbsd-src/regress/lib/libpthread/semaphore/sem_wait/sem_wait.c (revision 297694a9a755dc4fe7c18dcfc0ae7c6466927a06)
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