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