|
Szabolcs Nagy |
02466c |
// commit: 7e6be42a77989c01155bdc7333ea58206e1563d4 2011-03-08
|
|
Szabolcs Nagy |
02466c |
// pthread_once should not deadlock
|
|
Szabolcs Nagy |
02466c |
#include <pthread.h>
|
|
Szabolcs Nagy |
02466c |
#include <semaphore.h>
|
|
Szabolcs Nagy |
02466c |
#include <errno.h>
|
|
Szabolcs Nagy |
02466c |
#include <string.h>
|
|
Szabolcs Nagy |
02466c |
#include "test.h"
|
|
Szabolcs Nagy |
02466c |
|
|
Szabolcs Nagy |
02466c |
#define T(f) if ((r=(f))) t_error(#f " failed: %s\n", strerror(r))
|
|
Szabolcs Nagy |
02466c |
#define E(f) if (f) t_error(#f " failed: %s\n", strerror(errno))
|
|
Szabolcs Nagy |
02466c |
|
|
Szabolcs Nagy |
02466c |
static int count;
|
|
Szabolcs Nagy |
02466c |
|
|
Szabolcs Nagy |
02466c |
static void init(void)
|
|
Szabolcs Nagy |
02466c |
{
|
|
Szabolcs Nagy |
02466c |
count++;
|
|
Szabolcs Nagy |
02466c |
}
|
|
Szabolcs Nagy |
02466c |
|
|
Szabolcs Nagy |
02466c |
static void *start(void *arg)
|
|
Szabolcs Nagy |
02466c |
{
|
|
Szabolcs Nagy |
02466c |
void **a = arg;
|
|
Szabolcs Nagy |
02466c |
int r;
|
|
Szabolcs Nagy |
02466c |
E(sem_post(a[1]));
|
|
Szabolcs Nagy |
02466c |
T(pthread_once(a[0], init));
|
|
Szabolcs Nagy |
02466c |
E(sem_post(a[1]));
|
|
Szabolcs Nagy |
02466c |
return 0;
|
|
Szabolcs Nagy |
02466c |
}
|
|
Szabolcs Nagy |
02466c |
|
|
Szabolcs Nagy |
02466c |
static int deadlocked(sem_t *s)
|
|
Szabolcs Nagy |
02466c |
{
|
|
Szabolcs Nagy |
02466c |
struct timespec ts;
|
|
Szabolcs Nagy |
02466c |
|
|
Szabolcs Nagy |
02466c |
E(sem_wait(s));
|
|
Szabolcs Nagy |
02466c |
E(clock_gettime(CLOCK_REALTIME, &ts);;
|
|
Szabolcs Nagy |
02466c |
ts.tv_nsec += 100*1000*1000;
|
|
Szabolcs Nagy |
02466c |
if (ts.tv_nsec >= 1000*1000*1000) {
|
|
Szabolcs Nagy |
02466c |
ts.tv_nsec -= 1000*1000*1000;
|
|
Szabolcs Nagy |
02466c |
ts.tv_sec += 1;
|
|
Szabolcs Nagy |
02466c |
}
|
|
Szabolcs Nagy |
02466c |
errno = 0;
|
|
Szabolcs Nagy |
02466c |
E(sem_timedwait(s,&ts);;
|
|
Szabolcs Nagy |
02466c |
if (errno != ETIMEDOUT)
|
|
Szabolcs Nagy |
02466c |
return 0;
|
|
Szabolcs Nagy |
02466c |
t_error("pthread_once deadlocked\n");
|
|
Szabolcs Nagy |
02466c |
return 1;
|
|
Szabolcs Nagy |
02466c |
}
|
|
Szabolcs Nagy |
02466c |
|
|
Szabolcs Nagy |
02466c |
int main(void)
|
|
Szabolcs Nagy |
02466c |
{
|
|
Szabolcs Nagy |
02466c |
pthread_t t1,t2,t3;
|
|
Szabolcs Nagy |
02466c |
pthread_once_t once = PTHREAD_ONCE_INIT;
|
|
Szabolcs Nagy |
02466c |
sem_t s1,s2,s3;
|
|
Szabolcs Nagy |
02466c |
void *p;
|
|
Szabolcs Nagy |
02466c |
int r;
|
|
Szabolcs Nagy |
02466c |
|
|
Szabolcs Nagy |
02466c |
E(sem_init(&s1,0,0));
|
|
Szabolcs Nagy |
02466c |
E(sem_init(&s2,0,0));
|
|
Szabolcs Nagy |
02466c |
E(sem_init(&s3,0,0));
|
|
Szabolcs Nagy |
02466c |
T(pthread_create(&t1, 0, start, (void*[]){&once,&s1}));
|
|
Szabolcs Nagy |
02466c |
T(pthread_create(&t2, 0, start, (void*[]){&once,&s2}));
|
|
Szabolcs Nagy |
02466c |
T(pthread_create(&t3, 0, start, (void*[]){&once,&s3}));
|
|
Szabolcs Nagy |
02466c |
if (!deadlocked(&s1)) T(pthread_join(t1,&p);;
|
|
Szabolcs Nagy |
02466c |
if (!deadlocked(&s2)) T(pthread_join(t2,&p);;
|
|
Szabolcs Nagy |
02466c |
if (!deadlocked(&s3)) T(pthread_join(t3,&p);;
|
|
Szabolcs Nagy |
02466c |
if (count != 1)
|
|
Szabolcs Nagy |
02466c |
t_error("pthread_once ran init %d times instead of once\n", count);
|
|
Szabolcs Nagy |
02466c |
E(sem_destroy(&s1));
|
|
Szabolcs Nagy |
02466c |
E(sem_destroy(&s2));
|
|
Szabolcs Nagy |
02466c |
E(sem_destroy(&s3));
|
|
Szabolcs Nagy |
02466c |
return t_status;
|
|
Szabolcs Nagy |
02466c |
}
|