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 #if !defined(VGO_freebsd)
98 r
= pthread_attr_setstacksize(&attr
, PTHREAD_STACK_MIN
);
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
);
108 for (i
= 0; i
< NTHREADS
; i
++) {
109 # if !defined(VGO_darwin)
110 r
= sem_post(&sem
); assert(!r
);
112 r
= sem_post(sem
); assert(!r
);
117 for (i
= 0; i
< NTHREADS
; i
++) {
118 r
= pthread_join(child
[i
], NULL
); assert(!r
);
123 fprintf(stderr
, "\n-------- Letting %d threads make an error "
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
);
135 for (i
= 0; i
< NTHREADS
; i
++) {
136 # if !defined(VGO_darwin)
137 r
= sem_post(&sem
); assert(!r
);
139 r
= sem_post(sem
); assert(!r
);
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" );