1570af302Sopenharmony_ci// commit: 7e6be42a77989c01155bdc7333ea58206e1563d4 2011-03-08 2570af302Sopenharmony_ci// pthread_once should not deadlock 3570af302Sopenharmony_ci#include <pthread.h> 4570af302Sopenharmony_ci#include <semaphore.h> 5570af302Sopenharmony_ci#include <errno.h> 6570af302Sopenharmony_ci#include <string.h> 7570af302Sopenharmony_ci#include "test.h" 8570af302Sopenharmony_ci 9570af302Sopenharmony_ci#define T(f) if ((r=(f))) t_error(#f " failed: %s\n", strerror(r)) 10570af302Sopenharmony_ci#define E(f) if (f) t_error(#f " failed: %s\n", strerror(errno)) 11570af302Sopenharmony_ci 12570af302Sopenharmony_cistatic int count; 13570af302Sopenharmony_ci 14570af302Sopenharmony_cistatic void init(void) 15570af302Sopenharmony_ci{ 16570af302Sopenharmony_ci count++; 17570af302Sopenharmony_ci} 18570af302Sopenharmony_ci 19570af302Sopenharmony_cistatic void *start(void *arg) 20570af302Sopenharmony_ci{ 21570af302Sopenharmony_ci void **a = arg; 22570af302Sopenharmony_ci int r; 23570af302Sopenharmony_ci E(sem_post(a[1])); 24570af302Sopenharmony_ci T(pthread_once(a[0], init)); 25570af302Sopenharmony_ci E(sem_post(a[1])); 26570af302Sopenharmony_ci return 0; 27570af302Sopenharmony_ci} 28570af302Sopenharmony_ci 29570af302Sopenharmony_cistatic int deadlocked(sem_t *s) 30570af302Sopenharmony_ci{ 31570af302Sopenharmony_ci struct timespec ts; 32570af302Sopenharmony_ci 33570af302Sopenharmony_ci E(sem_wait(s)); 34570af302Sopenharmony_ci E(clock_gettime(CLOCK_REALTIME, &ts)); 35570af302Sopenharmony_ci ts.tv_nsec += 100*1000*1000; 36570af302Sopenharmony_ci if (ts.tv_nsec >= 1000*1000*1000) { 37570af302Sopenharmony_ci ts.tv_nsec -= 1000*1000*1000; 38570af302Sopenharmony_ci ts.tv_sec += 1; 39570af302Sopenharmony_ci } 40570af302Sopenharmony_ci errno = 0; 41570af302Sopenharmony_ci E(sem_timedwait(s,&ts)); 42570af302Sopenharmony_ci if (errno != ETIMEDOUT) 43570af302Sopenharmony_ci return 0; 44570af302Sopenharmony_ci t_error("pthread_once deadlocked\n"); 45570af302Sopenharmony_ci return 1; 46570af302Sopenharmony_ci} 47570af302Sopenharmony_ci 48570af302Sopenharmony_ciint main(void) 49570af302Sopenharmony_ci{ 50570af302Sopenharmony_ci pthread_t t1,t2,t3; 51570af302Sopenharmony_ci pthread_once_t once = PTHREAD_ONCE_INIT; 52570af302Sopenharmony_ci sem_t s1,s2,s3; 53570af302Sopenharmony_ci void *a1[] = {&once, &s1}; 54570af302Sopenharmony_ci void *a2[] = {&once, &s2}; 55570af302Sopenharmony_ci void *a3[] = {&once, &s3}; 56570af302Sopenharmony_ci void *p; 57570af302Sopenharmony_ci int r; 58570af302Sopenharmony_ci 59570af302Sopenharmony_ci E(sem_init(&s1,0,0)); 60570af302Sopenharmony_ci E(sem_init(&s2,0,0)); 61570af302Sopenharmony_ci E(sem_init(&s3,0,0)); 62570af302Sopenharmony_ci T(pthread_create(&t1, 0, start, a1)); 63570af302Sopenharmony_ci T(pthread_create(&t2, 0, start, a2)); 64570af302Sopenharmony_ci T(pthread_create(&t3, 0, start, a3)); 65570af302Sopenharmony_ci if (!deadlocked(&s1)) T(pthread_join(t1,&p)); 66570af302Sopenharmony_ci if (!deadlocked(&s2)) T(pthread_join(t2,&p)); 67570af302Sopenharmony_ci if (!deadlocked(&s3)) T(pthread_join(t3,&p)); 68570af302Sopenharmony_ci if (count != 1) 69570af302Sopenharmony_ci t_error("pthread_once ran init %d times instead of once\n", count); 70570af302Sopenharmony_ci E(sem_destroy(&s1)); 71570af302Sopenharmony_ci E(sem_destroy(&s2)); 72570af302Sopenharmony_ci E(sem_destroy(&s3)); 73570af302Sopenharmony_ci return t_status; 74570af302Sopenharmony_ci} 75