tests/vg_regtest: Always evaluate prerequisite expressions with sh
[valgrind.git] / memcheck / tests / err_disable4.c
blob44487afd2f55866308aa1cb2c261c9b2643f66ae
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.
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.
12 2. Create N new threads and get them to wait at a barrier.
14 3. Let them all go past the barrier and call err(). There
15 should be N resulting error reports.
17 4. Join with the N threads.
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"
28 char* block = NULL;
29 # if !defined(VGO_darwin)
30 sem_t sem;
31 # else
32 sem_t *sem;
33 static const char *semname = "Semaphore1";
34 # endif
36 __attribute__((noinline)) void usechar ( char c )
38 // Spook gcc into believing mysterious bad things are
39 // happening behind its back, and that 'c' is definitely
40 // used in some (unknown) way.
41 __asm__ __volatile__("" : : "r"(c) : "memory","cc");
44 __attribute__((noinline)) void err ( void )
46 usechar( block[5] );
49 void* child_fn_1 ( void* arg )
51 // Disable error reporting, then wait to exit
52 VALGRIND_DISABLE_ERROR_REPORTING;
53 # if !defined(VGO_darwin)
54 int r = sem_wait(&sem); assert(!r);
55 # else
56 int r = sem_wait(sem); assert(!r);
57 # endif
58 return NULL;
61 void* child_fn_2 ( void* arg )
63 // make an error, then wait to exit
64 err();
65 # if !defined(VGO_darwin)
66 int r = sem_wait(&sem); assert(!r);
67 # else
68 int r = sem_wait(sem); assert(!r);
69 # endif
70 return NULL;
73 #define NTHREADS 498 // VG_N_THREADS - 2
75 int main ( void )
77 int r, i;
78 pthread_t child[NTHREADS];
80 block = malloc(10);
81 free(block);
83 // part 1
84 fprintf(stderr, "\n-------- Letting %d threads exit "
85 "w/ errs disabled ------\n\n",
86 NTHREADS);
88 // set up the semaphore
89 # if !defined(VGO_darwin)
90 r = sem_init(&sem, 0, 0); assert(!r);
91 # else
92 sem = sem_open(semname, O_CREAT, 0777, 0); assert(!(sem == SEM_FAILED));
93 # endif
95 pthread_attr_t attr;
96 r = pthread_attr_init(&attr); assert(!r);
97 r = pthread_attr_setstacksize(&attr, PTHREAD_STACK_MIN);
99 // create N threads to do child_fn_1 ...
100 for (i = 0; i < NTHREADS; i++) {
101 r = pthread_create(&child[i], &attr, child_fn_1, NULL);
102 assert(!r);
105 // let them all exit
106 for (i = 0; i < NTHREADS; i++) {
107 # if !defined(VGO_darwin)
108 r = sem_post(&sem); assert(!r);
109 # else
110 r = sem_post(sem); assert(!r);
111 # endif
114 // join
115 for (i = 0; i < NTHREADS; i++) {
116 r = pthread_join(child[i], NULL); assert(!r);
119 // part 2
121 fprintf(stderr, "\n-------- Letting %d threads make an error "
122 "------\n\n",
123 NTHREADS);
124 // semaphore is already back at zero
126 // create N threads to do child_fn_2 ...
127 for (i = 0; i < NTHREADS; i++) {
128 r = pthread_create(&child[i], &attr, child_fn_2, NULL);
129 assert(!r);
132 // let them all exit
133 for (i = 0; i < NTHREADS; i++) {
134 # if !defined(VGO_darwin)
135 r = sem_post(&sem); assert(!r);
136 # else
137 r = sem_post(sem); assert(!r);
138 # endif
141 // join
142 for (i = 0; i < NTHREADS; i++) {
143 r = pthread_join(child[i], NULL); assert(!r);
146 // Print the final error counts. There need to be 498 errors
147 // in 1 context. Anything else, and something is not right.
148 int nerrors = VALGRIND_COUNT_ERRORS;
149 fprintf(stderr, "\n-------- Got %d errors (expected %d ==> %s) ------\n\n",
150 nerrors, NTHREADS, nerrors == NTHREADS ? "PASS" : "FAIL" );
152 return 0;