| #define _GNU_SOURCE |
| |
| #include <pthread.h> |
| #include <sched.h> |
| #include <stdio.h> |
| #include <stdlib.h> |
| #include <unistd.h> |
| #include <config.h> |
| |
| /* test based on code from Jeffrey Yasskin, slightly modified. */ |
| /* Reproduces a false positive leak when a pointer is (only) in a live |
| thread register, and another thread calls exit */ |
| |
| pthread_mutex_t mu = PTHREAD_MUTEX_INITIALIZER; |
| int cont = 1; |
| |
| void* helper(void* v_bar) { |
| pthread_barrier_t* bar = (pthread_barrier_t*)v_bar; |
| register int* i = malloc(sizeof(*i)); |
| // Try hard to have i allocated in a register. |
| *i = 3; |
| pthread_barrier_wait(bar); |
| pthread_mutex_lock(&mu); |
| while (cont) { |
| #if defined(VGA_x86) || defined(VGA_amd64) |
| // Below helps to have i really in a register. |
| asm volatile("test %0, %0" : : "S"(i)); |
| #else |
| // Not clear that for other archs, i is in a register. |
| if (*i) // should do better for other archs. |
| // "then" part after the #endif |
| #endif |
| pthread_mutex_unlock(&mu); |
| sched_yield(); |
| pthread_mutex_lock(&mu); |
| } |
| pthread_mutex_unlock(&mu); |
| free((void *)i); |
| fprintf(stderr, "Quitting the helper.\n"); |
| return NULL; |
| } |
| |
| int main() { |
| pthread_barrier_t bar; |
| pthread_barrier_init(&bar, NULL, 2); |
| pthread_t thr; |
| pthread_create(&thr, NULL, &helper, &bar); |
| pthread_barrier_wait(&bar); |
| pthread_barrier_destroy(&bar); |
| fprintf(stderr, "Abandoning the helper.\n"); |
| pthread_detach(thr); |
| return 0; |
| } |