fix regression/pthread_once-deadlock
[libc-test.git] / src / regression / pthread_once-deadlock.c
blobf8970c30b59754cd6386a4f56542e055f982ddc8
1 // commit: 7e6be42a77989c01155bdc7333ea58206e1563d4 2011-03-08
2 // pthread_once should not deadlock
3 #include <pthread.h>
4 #include <semaphore.h>
5 #include <errno.h>
6 #include <string.h>
7 #include "test.h"
9 #define T(f) if ((r=(f))) t_error(#f " failed: %s\n", strerror(r))
10 #define E(f) if (f) t_error(#f " failed: %s\n", strerror(errno))
12 static int count;
14 static void init(void)
16 count++;
19 static void *start(void *arg)
21 void **a = arg;
22 int r;
23 E(sem_post(a[1]));
24 T(pthread_once(a[0], init));
25 E(sem_post(a[1]));
26 return 0;
29 static int deadlocked(sem_t *s)
31 struct timespec ts;
33 E(sem_wait(s));
34 E(clock_gettime(CLOCK_REALTIME, &ts));
35 ts.tv_nsec += 100*1000*1000;
36 if (ts.tv_nsec >= 1000*1000*1000) {
37 ts.tv_nsec -= 1000*1000*1000;
38 ts.tv_sec += 1;
40 errno = 0;
41 E(sem_timedwait(s,&ts));
42 if (errno != ETIMEDOUT)
43 return 0;
44 t_error("pthread_once deadlocked\n");
45 return 1;
48 int main(void)
50 pthread_t t1,t2,t3;
51 pthread_once_t once = PTHREAD_ONCE_INIT;
52 sem_t s1,s2,s3;
53 void *a1[] = {&once, &s1};
54 void *a2[] = {&once, &s2};
55 void *a3[] = {&once, &s3};
56 void *p;
57 int r;
59 E(sem_init(&s1,0,0));
60 E(sem_init(&s2,0,0));
61 E(sem_init(&s3,0,0));
62 T(pthread_create(&t1, 0, start, a1));
63 T(pthread_create(&t2, 0, start, a2));
64 T(pthread_create(&t3, 0, start, a3));
65 if (!deadlocked(&s1)) T(pthread_join(t1,&p));
66 if (!deadlocked(&s2)) T(pthread_join(t2,&p));
67 if (!deadlocked(&s3)) T(pthread_join(t3,&p));
68 if (count != 1)
69 t_error("pthread_once ran init %d times instead of once\n", count);
70 E(sem_destroy(&s1));
71 E(sem_destroy(&s2));
72 E(sem_destroy(&s3));
73 return t_status;