1ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Check that an error is reported for various kinds of bogus 3ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown pthread_mutex_unlock calls. */ 4ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 5ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include <pthread.h> 6ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include <stdio.h> 7ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include <stdlib.h> 8ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 9ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid* child_fn ( void* arg ) 10ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 11ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown pthread_mutex_unlock( (pthread_mutex_t*)arg ); /* ERROR */ 12ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return NULL; 13ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 14ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 15ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid nearly_main ( void ) 16ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 17ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown pthread_t child; 18ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown pthread_mutex_t mx1, mx2; 19ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown int bogus[100], i; 20ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* fill bogus with values which will cause glibc's pth_mx_unlock to fail */ 21ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown for (i = 0; i < 100; i++) bogus[i] = 0xFFFFFFFF; 22ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Unlocking a lock that is already unlocked */ 23ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown pthread_mutex_init( &mx1, NULL ); 24ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown pthread_mutex_lock( &mx1 ); 25ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown pthread_mutex_unlock( &mx1 ); 26ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 27ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown pthread_mutex_unlock( &mx1 ); /* ERROR */ 28ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 29ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Unlocking a lock that is held by a different thread */ 30ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 31ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown pthread_mutex_init( &mx2, NULL ); 32ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown pthread_mutex_lock( &mx2 ); 33ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // start child and get it to unlock this lock 34ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 35ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown pthread_create( &child, NULL, child_fn, (void*)&mx2 ); 36ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* child runs and attempts to unlock our lock. Error 37ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown is reported in child_fn. */ 38ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown pthread_join(child, NULL ); 39ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 40ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Unlocking a totally bogus lock. */ 41ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown pthread_mutex_unlock( (pthread_mutex_t*) &bogus[50] ); /* ERROR */ 42ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 43ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Now we get a freeing-locked-lock error, since the stack 44ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown frame is removed whilst mx2 is still locked. */ 45ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 46ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 47ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownint main ( void ) 48ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 49ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown nearly_main(); fprintf(stderr, "---------------------\n" ); 50ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown nearly_main(); 51ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return 0; 52ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 53