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> 10pthread_mutex_t mx[4]; 11pthread_cond_t cv; pthread_rwlock_t rwl; 12sem_t* quit_now; 13static sem_t* my_sem_init(char*, int, unsigned); 14static int my_sem_destroy(sem_t*); 15static int my_sem_wait(sem_t*); static int my_sem_post(sem_t*); 16void* 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 38void* 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 46int 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 97static 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 127static int my_sem_destroy ( sem_t* s ) 128{ 129 return sem_destroy(s); 130} 131 132static int my_sem_wait(sem_t* s) 133{ 134 return sem_wait(s); 135} 136 137static int my_sem_post(sem_t* s) 138{ 139 return sem_post(s); 140} 141