• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // sem_wait and sem_timedwait are cancellation points
2 #include <pthread.h>
3 #include <semaphore.h>
4 #include <string.h>
5 #include "test.h"
6 
7 #define TESTC(c, m) ( (c) || (t_error("%s failed (" m ")\n", #c), 0) )
8 #define TESTR(r, f, m) ( \
9 	((r) = (f)) == 0 || (t_error("%s failed: %s (" m ")\n", #f, strerror(r)), 0) )
10 
11 static sem_t sem1, sem2;
12 
13 static int seqno;
14 
wait_cancel(void * arg)15 static void wait_cancel(void *arg)
16 {
17 	pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, 0);
18 	while (sem_wait(&sem1));
19 	pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, 0);
20 	seqno = 1;
21 }
22 
start_sem_wait(void * arg)23 static void *start_sem_wait(void *arg)
24 {
25 	wait_cancel(arg);
26 	sem_wait(&sem2);
27 	seqno = 2;
28 	return 0;
29 }
30 
start_sem_timedwait(void * arg)31 static void *start_sem_timedwait(void *arg)
32 {
33 	wait_cancel(arg);
34 	sem_timedwait(&sem2, &(struct timespec){1, 0});
35 	seqno = 2;
36 	return 0;
37 }
38 
main(void)39 int main(void)
40 {
41 	pthread_t td;
42 	int r;
43 	void *res;
44 
45 	TESTR(r, sem_init(&sem1, 0, 0), "creating semaphore");
46 	TESTR(r, sem_init(&sem2, 0, 1), "creating semaphore");
47 
48 	/* Cancellation on uncontended sem_wait */
49 	seqno = 0;
50 	TESTR(r, pthread_create(&td, 0, start_sem_wait, 0), "failed to create thread");
51 	TESTR(r, pthread_cancel(td), "canceling");
52 	sem_post(&sem1);
53 	TESTR(r, pthread_join(td, &res), "joining canceled thread after uncontended sem_wait");
54 	TESTC(res == PTHREAD_CANCELED, "canceled thread exit status after uncontended sem_wait");
55 	TESTC(seqno == 1, "uncontended sem_wait");
56 
57 	/* Cancellation on blocking sem_wait */
58 	seqno = 0;
59 	sem_trywait(&sem2);
60 	TESTR(r, pthread_create(&td, 0, start_sem_wait, 0), "failed to create thread");
61 	TESTR(r, pthread_cancel(td), "canceling");
62 	sem_post(&sem1);
63 	TESTR(r, pthread_join(td, &res), "joining canceled thread after blocking sem_wait");
64 	TESTC(res == PTHREAD_CANCELED, "canceled thread exit status after blocking sem_wait");
65 	TESTC(seqno == 1, "blocking sem_wait");
66 
67 	/* Cancellation on uncontended sem_timedwait */
68 	seqno = 0;
69 	sem_post(&sem2);
70 	TESTR(r, pthread_create(&td, 0, start_sem_timedwait, 0), "failed to create thread");
71 	TESTR(r, pthread_cancel(td), "canceling");
72 	sem_post(&sem1);
73 	TESTR(r, pthread_join(td, &res), "joining canceled thread after uncontended sem_timedwait");
74 	TESTC(res == PTHREAD_CANCELED, "canceled thread exit status after uncontended sem_timedwait");
75 	TESTC(seqno == 1, "uncontended sem_timedwait");
76 
77 	/* Cancellation on blocking sem_timedwait */
78 	seqno = 0;
79 	sem_trywait(&sem2);
80 	TESTR(r, pthread_create(&td, 0, start_sem_timedwait, 0), "failed to create thread");
81 	TESTR(r, pthread_cancel(td), "canceling");
82 	sem_post(&sem1);
83 	TESTR(r, pthread_join(td, &res), "joining canceled thread after blocking sem_timedwait");
84 	TESTC(res == PTHREAD_CANCELED, "canceled thread exit status after blocking sem_timedwait");
85 	TESTC(seqno == 1, "blocking sem_timedwait");
86 
87 	return t_status;
88 }
89