err_disable4.c revision b32f58018498ea2225959b0ba11c18f0c433deef
1 2/* Check that recycling thread slots doesn't cause new threads to 3 inherit the disablement status of the previous thread to occupy 4 that slot. 5 6 1. Create N threads, disable error reporting in them, and get them 7 all to exit (join with them). That creates N thread slots that 8 were vacated by threads with error reporting disabled. There 9 should be N complaints about threads exiting with errors 10 disabled. 11 12 2. Create N new threads and get them to wait at a barrier. 13 14 3. Let them all go past the barrier and call err(). There 15 should be N resulting error reports. 16 17 4. Join with the N threads. 18*/ 19 20#include <stdlib.h> 21#include <stdio.h> 22#include <assert.h> 23#include <pthread.h> 24#include <semaphore.h> 25#include <limits.h> /* PTHREAD_STACK_MIN */ 26#include "../include/valgrind.h" 27 28char* block = NULL; 29sem_t sem; 30 31__attribute__((noinline)) void usechar ( char c ) 32{ 33 // Spook gcc into believing mysterious bad things are 34 // happening behind its back, and that 'c' is definitely 35 // used in some (unknown) way. 36 __asm__ __volatile__("" : : "r"(c) : "memory","cc"); 37} 38 39__attribute__((noinline)) void err ( void ) 40{ 41 usechar( block[5] ); 42} 43 44void* child_fn_1 ( void* arg ) 45{ 46 // Disable error reporting, then wait to exit 47 VALGRIND_DISABLE_ERROR_REPORTING; 48 int r = sem_wait(&sem); assert(!r); 49 return NULL; 50} 51 52void* child_fn_2 ( void* arg ) 53{ 54 // make an error, then wait to exit 55 err(); 56 int r = sem_wait(&sem); assert(!r); 57 return NULL; 58} 59 60#define NTHREADS 498 // VG_N_THREADS - 2 61 62int main ( void ) 63{ 64 int r, i; 65 pthread_t child[NTHREADS]; 66 67 block = malloc(10); 68 free(block); 69 70 // part 1 71 fprintf(stderr, "\n-------- Letting %d threads exit " 72 "w/ errs disabled ------\n\n", 73 NTHREADS); 74 75 // set up the semaphore 76 r = sem_init(&sem, 0, 0); assert(!r); 77 78 pthread_attr_t attr; 79 r = pthread_attr_init(&attr); assert(!r); 80 r = pthread_attr_setstacksize(&attr, PTHREAD_STACK_MIN); 81 82 // create N threads to do child_fn_1 ... 83 for (i = 0; i < NTHREADS; i++) { 84 r = pthread_create(&child[i], &attr, child_fn_1, NULL); 85 assert(!r); 86 } 87 88 // let them all exit 89 for (i = 0; i < NTHREADS; i++) { 90 r = sem_post(&sem); assert(!r); 91 } 92 93 // join 94 for (i = 0; i < NTHREADS; i++) { 95 r = pthread_join(child[i], NULL); assert(!r); 96 } 97 98 // part 2 99 100 fprintf(stderr, "\n-------- Letting %d threads make an error " 101 "------\n\n", 102 NTHREADS); 103 // semaphore is already back at zero 104 105 // create N threads to do child_fn_2 ... 106 for (i = 0; i < NTHREADS; i++) { 107 r = pthread_create(&child[i], &attr, child_fn_2, NULL); 108 assert(!r); 109 } 110 111 // let them all exit 112 for (i = 0; i < NTHREADS; i++) { 113 r = sem_post(&sem); assert(!r); 114 } 115 116 // join 117 for (i = 0; i < NTHREADS; i++) { 118 r = pthread_join(child[i], NULL); assert(!r); 119 } 120 121 // Print the final error counts. There need to be 498 errors 122 // in 1 context. Anything else, and something is not right. 123 int nerrors = VALGRIND_COUNT_ERRORS; 124 fprintf(stderr, "\n-------- Got %d errors (expected %d ==> %s) ------\n\n", 125 nerrors, NTHREADS, nerrors == NTHREADS ? "PASS" : "FAIL" ); 126 127 return 0; 128} 129