1ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Expect 5 errors total (4 re cvs, 1 re exiting w/lock.). 2ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Tests passing bogus mutexes to pthread_cond_wait. */ 3ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define _GNU_SOURCE 1 /* needed by glibc <= 2.3 for pthread_rwlock_* */ 4ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include <pthread.h> 5ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include <assert.h> 6ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include <unistd.h> 7ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include <semaphore.h> 8ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include <stdio.h> 9b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#include <stdlib.h> 10b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovpthread_mutex_t mx[4]; 11b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovpthread_cond_t cv; pthread_rwlock_t rwl; 12b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovsem_t* quit_now; 13b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovstatic sem_t* my_sem_init(char*, int, unsigned); 14ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic int my_sem_destroy(sem_t*); 15ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic int my_sem_wait(sem_t*); static int my_sem_post(sem_t*); 16ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid* rescue_me ( void* uu ) 17ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 18ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* wait for, and unblock, the first wait */ 19ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown sleep(1); 20ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown pthread_cond_signal( &cv ); 21ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 22ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* wait for, and unblock, the second wait */ 23ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown sleep(1); 24ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown pthread_cond_signal( &cv ); 25ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 26ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* wait for, and unblock, the third wait */ 27ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown sleep(1); 28ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown pthread_cond_signal( &cv ); 29ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 30ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* wait for, and unblock, the fourth wait */ 31ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown sleep(1); 32ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown pthread_cond_signal( &cv ); 33ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 34b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov my_sem_wait( quit_now ); 35ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return NULL; 36ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 37ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 38ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid* grab_the_lock ( void* uu ) 39ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 40ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown int r= pthread_mutex_lock( &mx[2] ); assert(!r); 41b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov my_sem_wait( quit_now ); 42ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown r= pthread_mutex_unlock( &mx[2] ); assert(!r); 43ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return NULL; 44ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 45ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 46ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownint main ( void ) 47ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 48ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown int r; 49ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown pthread_t my_rescuer, grabber; 50ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 51ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown r= pthread_mutex_init(&mx[0], NULL); assert(!r); 52ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown r= pthread_mutex_init(&mx[1], NULL); assert(!r); 53ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown r= pthread_mutex_init(&mx[2], NULL); assert(!r); 54ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown r= pthread_mutex_init(&mx[3], NULL); assert(!r); 55ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 56ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown r= pthread_cond_init(&cv, NULL); assert(!r); 57ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown r= pthread_rwlock_init(&rwl, NULL); assert(!r); 58ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 59b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov quit_now = my_sem_init( "quit_now", 0,0 ); assert(quit_now); 60ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 61ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown r= pthread_create( &grabber, NULL, grab_the_lock, NULL ); assert(!r); 62ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown sleep(1); /* let the grabber get there first */ 63ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 64ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown r= pthread_create( &my_rescuer, NULL, rescue_me, NULL ); assert(!r); 65ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Do stupid things and hope that rescue_me gets us out of 66ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown trouble */ 67ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 68ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* mx is bogus */ 69b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov r= pthread_cond_wait(&cv, (pthread_mutex_t*)(4 + (char*)&mx[0]) ); 70ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 71ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* mx is not locked */ 72ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown r= pthread_cond_wait(&cv, &mx[0]); 73ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 74ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* wrong flavour of lock */ 75ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown r= pthread_cond_wait(&cv, (pthread_mutex_t*)&rwl ); 76ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 77ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* mx is held by someone else. */ 78ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown r= pthread_cond_wait(&cv, &mx[2] ); 79ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 80b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov r= my_sem_post( quit_now ); assert(!r); 81b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov r= my_sem_post( quit_now ); assert(!r); 82ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 83ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown r= pthread_join( my_rescuer, NULL ); assert(!r); 84ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown r= pthread_join( grabber, NULL ); assert(!r); 85ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 86b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov r= my_sem_destroy( quit_now ); assert(!r); 87ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return 0; 88ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 89ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 90ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 91ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 92ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 93ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 94ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 95ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 96ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 97b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovstatic sem_t* my_sem_init (char* identity, int pshared, unsigned count) 98ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 99b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov sem_t* s; 100b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 101ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#if defined(VGO_linux) 102b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov s = malloc(sizeof(*s)); 103b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov if (s) { 104b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov if (sem_init(s, pshared, count) < 0) { 105b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov perror("sem_init"); 106b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov free(s); 107b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov s = NULL; 108b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov } 109b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov } 110ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#elif defined(VGO_darwin) 111ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown char name[100]; 112ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown sprintf(name, "anonsem_%s_pid%d", identity, (int)getpid()); 113ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown name[ sizeof(name)-1 ] = 0; 114ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (0) printf("name = %s\n", name); 115b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov s = sem_open(name, O_CREAT | O_EXCL, 0600, count); 116b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov if (s == SEM_FAILED) { 117b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov perror("sem_open"); 118b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov s = NULL; 119b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov } 120ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#else 121ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# error "Unsupported OS" 122ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif 123b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 124b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov return s; 125ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 126ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 127ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic int my_sem_destroy ( sem_t* s ) 128ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 129ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return sem_destroy(s); 130ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 131ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 132ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic int my_sem_wait(sem_t* s) 133ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 134ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return sem_wait(s); 135ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 136ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 137ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic int my_sem_post(sem_t* s) 138ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 139ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return sem_post(s); 140ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 141