1 //===-- test.c ------------------------------------------------------------===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 // 10 // Sanity test for Go runtime. 11 // 12 //===----------------------------------------------------------------------===// 13 14 #include <sys/mman.h> 15 #include <errno.h> 16 #include <stdio.h> 17 #include <stdlib.h> 18 19 void __tsan_init(void **thr, void **proc, void (*cb)(long, void*)); 20 void __tsan_fini(); 21 void __tsan_map_shadow(void *addr, unsigned long size); 22 void __tsan_go_start(void *thr, void **chthr, void *pc); 23 void __tsan_go_end(void *thr); 24 void __tsan_proc_create(void **pproc); 25 void __tsan_proc_destroy(void *proc); 26 void __tsan_proc_wire(void *proc, void *thr); 27 void __tsan_proc_unwire(void *proc, void *thr); 28 void __tsan_read(void *thr, void *addr, void *pc); 29 void __tsan_write(void *thr, void *addr, void *pc); 30 void __tsan_func_enter(void *thr, void *pc); 31 void __tsan_func_exit(void *thr); 32 void __tsan_malloc(void *thr, void *pc, void *p, unsigned long sz); 33 void __tsan_free(void *p, unsigned long sz); 34 void __tsan_acquire(void *thr, void *addr); 35 void __tsan_release(void *thr, void *addr); 36 void __tsan_release_merge(void *thr, void *addr); 37 38 void *current_proc; 39 40 void symbolize_cb(long cmd, void *ctx) { 41 switch (cmd) { 42 case 0: 43 if (current_proc == 0) 44 abort(); 45 *(void**)ctx = current_proc; 46 } 47 } 48 49 /* 50 * See lib/tsan/rtl/tsan_platform.h for details of what the memory layout 51 * of Go programs looks like. To prevent running over existing mappings, 52 * we pick an address slightly inside the Go heap region. 53 */ 54 void *go_heap = (void *)0xC011110000; 55 char *buf0; 56 57 void foobar() {} 58 void barfoo() {} 59 60 int main(void) { 61 void *thr0 = 0; 62 void *proc0 = 0; 63 __tsan_init(&thr0, &proc0, symbolize_cb); 64 current_proc = proc0; 65 66 // Allocate something resembling a heap in Go. 67 buf0 = mmap(go_heap, 16384, PROT_READ | PROT_WRITE, 68 MAP_PRIVATE | MAP_FIXED | MAP_ANON, -1, 0); 69 if (buf0 == MAP_FAILED) { 70 fprintf(stderr, "failed to allocate Go-like heap at %p; errno %d\n", 71 go_heap, errno); 72 return 1; 73 } 74 char *buf = (char*)((unsigned long)buf0 + (64<<10) - 1 & ~((64<<10) - 1)); 75 __tsan_map_shadow(buf, 4096); 76 __tsan_malloc(thr0, (char*)&barfoo + 1, buf, 10); 77 __tsan_free(buf, 10); 78 __tsan_func_enter(thr0, (char*)&main + 1); 79 __tsan_malloc(thr0, (char*)&barfoo + 1, buf, 10); 80 __tsan_release(thr0, buf); 81 __tsan_release_merge(thr0, buf); 82 void *thr1 = 0; 83 __tsan_go_start(thr0, &thr1, (char*)&barfoo + 1); 84 void *thr2 = 0; 85 __tsan_go_start(thr0, &thr2, (char*)&barfoo + 1); 86 __tsan_func_exit(thr0); 87 __tsan_func_enter(thr1, (char*)&foobar + 1); 88 __tsan_func_enter(thr1, (char*)&foobar + 1); 89 __tsan_write(thr1, buf, (char*)&barfoo + 1); 90 __tsan_acquire(thr1, buf); 91 __tsan_func_exit(thr1); 92 __tsan_func_exit(thr1); 93 __tsan_go_end(thr1); 94 void *proc1 = 0; 95 __tsan_proc_create(&proc1); 96 current_proc = proc1; 97 __tsan_func_enter(thr2, (char*)&foobar + 1); 98 __tsan_read(thr2, buf, (char*)&barfoo + 1); 99 __tsan_free(buf, 10); 100 __tsan_func_exit(thr2); 101 __tsan_go_end(thr2); 102 __tsan_proc_destroy(proc1); 103 current_proc = proc0; 104 __tsan_fini(); 105 return 0; 106 } 107