1 #include <pthread.h>
2 #include <stdio.h>
3 #include <strings.h>
4 #include <assert.h>
5 
6 static pthread_barrier_t bar;
7 static pthread_mutex_t mtx = PTHREAD_MUTEX_INITIALIZER;
8 static pthread_cond_t cnd = PTHREAD_COND_INITIALIZER;
9 static int called = 0;
10 
11 #ifndef ASSERT
12 #define ASSERT(x) assert(x)
13 #endif /* ASSERT */
14 
cleanupmutex(void * arg)15 static void cleanupmutex(void * arg)
16 {
17 	printf("cancelation cleanup handler called\n");
18 	if (arg) {
19 		ASSERT( pthread_mutex_unlock((pthread_mutex_t *)arg) == 0 );
20 		called++;
21 	}
22 
23 }
24 
mythread(void * a)25 static void * mythread(void * a)
26 {
27 	int ret;
28 
29 	/* lock mutex */
30 	ASSERT( pthread_mutex_lock(&mtx) == 0 );
31 
32 	/* Push cleanup */
33 	pthread_cleanup_push(cleanupmutex, &mtx);
34 
35 	printf("thread synchronization (mutex acquired)\n");
36 
37 	/* Wake the other thread */
38 	ret = pthread_barrier_wait(&bar);
39 	ASSERT( (ret == 0) || (ret == PTHREAD_BARRIER_SERIAL_THREAD) );
40 
41 	/* Now wait for the condition, this unlocks the mutex */
42 	do {
43 		printf("thread waiting cond\n");
44 		ASSERT( pthread_cond_wait(&cnd, &mtx) == 0);
45 		printf("thread woken\n");
46 	} while (1);
47 
48 	/* Cleanup, never reached */
49 	pthread_cleanup_pop(1);
50 	return NULL;
51 }
52 
main(int argc,char * argv[])53 int main(int argc, char * argv[])
54 {
55 	int ret;
56 	pthread_t thr;
57 	void * dummy;
58 
59 	/* initialize the barrier */
60 	ASSERT( pthread_barrier_init(&bar, NULL, 2) == 0 );
61 
62 	printf("Creating thread\n");
63 
64 	/* Create the thread */
65 	ASSERT( pthread_create(&thr, NULL, mythread, NULL) == 0 );
66 
67 	printf("main synchronization\n");
68 	ret = pthread_barrier_wait(&bar);
69 	ASSERT( (ret == 0) || (ret == PTHREAD_BARRIER_SERIAL_THREAD) );
70 
71 	ASSERT( pthread_mutex_lock(&mtx) == 0 );
72 	printf("main: thread is now waiting for condvar\n");
73 
74 	/* Cancel the thread */
75 	ASSERT( pthread_cancel(thr) == 0 );
76 
77 	/* Now, unlock, so that the thread can actually really exit */
78 	ASSERT( pthread_mutex_unlock(&mtx) == 0 );
79 
80 	/* Release thread resources */
81 	ASSERT( pthread_join(thr, &dummy) == 0 );
82 
83 	if (called == 1)
84 		printf("Test successful!\n");
85 	else
86 		printf("Test failed! Cleanup was not called (& lock not released)\n");
87 
88 	return 0;
89 
90 }
91