11624be93SDmitry Vyukov // RUN: %clang_tsan -O1 %s -o %t && %run %t 2>&1 | FileCheck %s
21624be93SDmitry Vyukov // REQUIRES: linux
31624be93SDmitry Vyukov #include "test.h"
41624be93SDmitry Vyukov
51624be93SDmitry Vyukov #include <pthread.h>
61624be93SDmitry Vyukov #include <sys/types.h>
71624be93SDmitry Vyukov #include <unistd.h>
81624be93SDmitry Vyukov
count_memory_mappings()91624be93SDmitry Vyukov long count_memory_mappings() {
101624be93SDmitry Vyukov pid_t my_pid = getpid();
111624be93SDmitry Vyukov char proc_file_name[128];
12*d78782f6SDmitry Vyukov snprintf(proc_file_name, sizeof(proc_file_name), "/proc/%d/maps", my_pid);
131624be93SDmitry Vyukov
141624be93SDmitry Vyukov FILE *proc_file = fopen(proc_file_name, "r");
151624be93SDmitry Vyukov long line_count = 0;
167cc6d0ccSNemanja Ivanovic int c;
171624be93SDmitry Vyukov do {
181624be93SDmitry Vyukov c = fgetc(proc_file);
191624be93SDmitry Vyukov if (c == '\n') {
201624be93SDmitry Vyukov line_count++;
211624be93SDmitry Vyukov }
221624be93SDmitry Vyukov } while (c != EOF);
231624be93SDmitry Vyukov fclose(proc_file);
241624be93SDmitry Vyukov
251624be93SDmitry Vyukov return line_count;
261624be93SDmitry Vyukov }
271624be93SDmitry Vyukov
fiber_iteration()281624be93SDmitry Vyukov void fiber_iteration() {
291624be93SDmitry Vyukov void *orig_fiber = __tsan_get_current_fiber();
301624be93SDmitry Vyukov void *fiber = __tsan_create_fiber(0);
311624be93SDmitry Vyukov
321624be93SDmitry Vyukov pthread_mutex_t mutex;
331624be93SDmitry Vyukov pthread_mutex_init(&mutex, NULL);
341624be93SDmitry Vyukov
351624be93SDmitry Vyukov // Running some code on the fiber that triggers handling of pending signals.
361624be93SDmitry Vyukov __tsan_switch_to_fiber(fiber, 0);
371624be93SDmitry Vyukov pthread_mutex_lock(&mutex);
381624be93SDmitry Vyukov pthread_mutex_unlock(&mutex);
391624be93SDmitry Vyukov __tsan_switch_to_fiber(orig_fiber, 0);
401624be93SDmitry Vyukov
411624be93SDmitry Vyukov // We expect the fiber to clean up all resources (here the sigcontext) when destroyed.
421624be93SDmitry Vyukov __tsan_destroy_fiber(fiber);
431624be93SDmitry Vyukov }
441624be93SDmitry Vyukov
451624be93SDmitry Vyukov // Magic-Number for some warmup iterations,
461624be93SDmitry Vyukov // as tsan maps some memory for the first runs.
471624be93SDmitry Vyukov const size_t num_warmup = 100;
481624be93SDmitry Vyukov
main()491624be93SDmitry Vyukov int main() {
501624be93SDmitry Vyukov for (size_t i = 0; i < num_warmup; i++) {
511624be93SDmitry Vyukov fiber_iteration();
521624be93SDmitry Vyukov }
531624be93SDmitry Vyukov
541624be93SDmitry Vyukov long memory_mappings_before = count_memory_mappings();
551624be93SDmitry Vyukov fiber_iteration();
561624be93SDmitry Vyukov fiber_iteration();
571624be93SDmitry Vyukov long memory_mappings_after = count_memory_mappings();
581624be93SDmitry Vyukov
591624be93SDmitry Vyukov // Is there a better way to detect a resource leak in the
601624be93SDmitry Vyukov // ThreadState object? (i.e. a mmap not being freed)
611624be93SDmitry Vyukov if (memory_mappings_before == memory_mappings_after) {
621624be93SDmitry Vyukov fprintf(stderr, "PASS\n");
631624be93SDmitry Vyukov } else {
641624be93SDmitry Vyukov fprintf(stderr, "FAILED\n");
651624be93SDmitry Vyukov }
661624be93SDmitry Vyukov
671624be93SDmitry Vyukov return 0;
681624be93SDmitry Vyukov }
691624be93SDmitry Vyukov
701624be93SDmitry Vyukov // CHECK-NOT: WARNING: ThreadSanitizer:
711624be93SDmitry Vyukov // CHECK: PASS
72