regtest: fix compiler warnings with clang 16
[valgrind.git] / memcheck / tests / err_disable4.c
blob0692192ec836d17571af22ba14d38c933e5d770e
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 #if !defined(VGO_freebsd)
98 r = pthread_attr_setstacksize(&attr, PTHREAD_STACK_MIN);
99 #endif
101 // create N threads to do child_fn_1 ...
102 for (i = 0; i < NTHREADS; i++) {
103 r = pthread_create(&child[i], &attr, child_fn_1, NULL);
104 assert(!r);
107 // let them all exit
108 for (i = 0; i < NTHREADS; i++) {
109 # if !defined(VGO_darwin)
110 r = sem_post(&sem); assert(!r);
111 # else
112 r = sem_post(sem); assert(!r);
113 # endif
116 // join
117 for (i = 0; i < NTHREADS; i++) {
118 r = pthread_join(child[i], NULL); assert(!r);
121 // part 2
123 fprintf(stderr, "\n-------- Letting %d threads make an error "
124 "------\n\n",
125 NTHREADS);
126 // semaphore is already back at zero
128 // create N threads to do child_fn_2 ...
129 for (i = 0; i < NTHREADS; i++) {
130 r = pthread_create(&child[i], &attr, child_fn_2, NULL);
131 assert(!r);
134 // let them all exit
135 for (i = 0; i < NTHREADS; i++) {
136 # if !defined(VGO_darwin)
137 r = sem_post(&sem); assert(!r);
138 # else
139 r = sem_post(sem); assert(!r);
140 # endif
143 // join
144 for (i = 0; i < NTHREADS; i++) {
145 r = pthread_join(child[i], NULL); assert(!r);
148 // Print the final error counts. There need to be 498 errors
149 // in 1 context. Anything else, and something is not right.
150 int nerrors = VALGRIND_COUNT_ERRORS;
151 fprintf(stderr, "\n-------- Got %d errors (expected %d ==> %s) ------\n\n",
152 nerrors, NTHREADS, nerrors == NTHREADS ? "PASS" : "FAIL" );
154 return 0;