Home | History | Annotate | Download | only in tests
      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[3]);
     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) || defined(VGO_solaris)
    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