tests/vg_regtest: Always evaluate prerequisite expressions with sh
[valgrind.git] / memcheck / tests / reach_thread_register.c
blobb70d7e1883869deb4682c8a8ec2b0a73b4d5930c
1 #define _GNU_SOURCE
3 #include <pthread.h>
4 #include <sched.h>
5 #include <stdio.h>
6 #include <stdlib.h>
7 #include <unistd.h>
8 #include <config.h>
10 /* test based on code from Jeffrey Yasskin, slightly modified. */
11 /* Reproduces a false positive leak when a pointer is (only) in a live
12 thread register, and another thread calls exit */
14 pthread_mutex_t mu = PTHREAD_MUTEX_INITIALIZER;
15 int cont = 1;
17 void* helper(void* v_bar) {
18 pthread_barrier_t* bar = (pthread_barrier_t*)v_bar;
19 register int* i = malloc(sizeof(*i));
20 // Try hard to have i allocated in a register.
21 *i = 3;
22 pthread_barrier_wait(bar);
23 pthread_mutex_lock(&mu);
24 while (cont) {
25 #if defined(VGA_x86) || defined(VGA_amd64)
26 // Below helps to have i really in a register.
27 asm volatile("test %0, %0" : : "S"(i));
28 #else
29 // Not clear that for other archs, i is in a register.
30 if (*i) // should do better for other archs.
31 // "then" part after the #endif
32 #endif
33 pthread_mutex_unlock(&mu);
34 sched_yield();
35 pthread_mutex_lock(&mu);
37 pthread_mutex_unlock(&mu);
38 free((void *)i);
39 fprintf(stderr, "Quitting the helper.\n");
40 return NULL;
43 int main() {
44 pthread_barrier_t bar;
45 pthread_barrier_init(&bar, NULL, 2);
46 pthread_t thr;
47 pthread_create(&thr, NULL, &helper, &bar);
48 pthread_barrier_wait(&bar);
49 pthread_barrier_destroy(&bar);
50 fprintf(stderr, "Abandoning the helper.\n");
51 pthread_detach(thr);
52 return 0;