2 /* Check that recycling thread slots doesn't cause new threads to
3 inherit the disablement status of the previous thread to occupy
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
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.
24 #include <semaphore.h>
25 #include <limits.h> /* PTHREAD_STACK_MIN */
26 #include "../include/valgrind.h"
29 # if !defined(VGO_darwin)
33 static const char *semname
= "Semaphore1";
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 )
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
);
56 int r
= sem_wait(sem
); assert(!r
);
61 void* child_fn_2 ( void* arg
)
63 // make an error, then wait to exit
65 # if !defined(VGO_darwin)
66 int r
= sem_wait(&sem
); assert(!r
);
68 int r
= sem_wait(sem
); assert(!r
);
73 #define NTHREADS 498 // VG_N_THREADS - 2
78 pthread_t child
[NTHREADS
];
84 fprintf(stderr
, "\n-------- Letting %d threads exit "
85 "w/ errs disabled ------\n\n",
88 // set up the semaphore
89 # if !defined(VGO_darwin)
90 r
= sem_init(&sem
, 0, 0); assert(!r
);
92 sem
= sem_open(semname
, O_CREAT
, 0777, 0); assert(!(sem
== SEM_FAILED
));
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
);
106 for (i
= 0; i
< NTHREADS
; i
++) {
107 # if !defined(VGO_darwin)
108 r
= sem_post(&sem
); assert(!r
);
110 r
= sem_post(sem
); assert(!r
);
115 for (i
= 0; i
< NTHREADS
; i
++) {
116 r
= pthread_join(child
[i
], NULL
); assert(!r
);
121 fprintf(stderr
, "\n-------- Letting %d threads make an error "
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
);
133 for (i
= 0; i
< NTHREADS
; i
++) {
134 # if !defined(VGO_darwin)
135 r
= sem_post(&sem
); assert(!r
);
137 r
= sem_post(sem
); assert(!r
);
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" );