github.com/xushiwei/go@v0.0.0-20130601165731-2b9d83f45bc9/src/pkg/runtime/race.c (about) 1 // Copyright 2011 The Go Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 // Implementation of the race detector API. 6 // +build race 7 8 #include "runtime.h" 9 #include "arch_GOARCH.h" 10 #include "malloc.h" 11 #include "race.h" 12 13 void runtime∕race·Initialize(uintptr *racectx); 14 void runtime∕race·MapShadow(void *addr, uintptr size); 15 void runtime∕race·Finalize(void); 16 void runtime∕race·FinalizerGoroutine(uintptr racectx); 17 void runtime∕race·Read(uintptr racectx, void *addr, void *pc); 18 void runtime∕race·Write(uintptr racectx, void *addr, void *pc); 19 void runtime∕race·ReadRange(uintptr racectx, void *addr, uintptr sz, uintptr step, void *pc); 20 void runtime∕race·WriteRange(uintptr racectx, void *addr, uintptr sz, uintptr step, void *pc); 21 void runtime∕race·FuncEnter(uintptr racectx, void *pc); 22 void runtime∕race·FuncExit(uintptr racectx); 23 void runtime∕race·Malloc(uintptr racectx, void *p, uintptr sz, void *pc); 24 void runtime∕race·Free(void *p); 25 void runtime∕race·GoStart(uintptr racectx, uintptr *chracectx, void *pc); 26 void runtime∕race·GoEnd(uintptr racectx); 27 void runtime∕race·Acquire(uintptr racectx, void *addr); 28 void runtime∕race·Release(uintptr racectx, void *addr); 29 void runtime∕race·ReleaseMerge(uintptr racectx, void *addr); 30 31 extern byte noptrdata[]; 32 extern byte enoptrbss[]; 33 34 static bool onstack(uintptr argp); 35 36 uintptr 37 runtime·raceinit(void) 38 { 39 uintptr racectx, start, size; 40 41 m->racecall = true; 42 runtime∕race·Initialize(&racectx); 43 // Round data segment to page boundaries, because it's used in mmap(). 44 start = (uintptr)noptrdata & ~(PageSize-1); 45 size = ROUND((uintptr)enoptrbss - start, PageSize); 46 runtime∕race·MapShadow((void*)start, size); 47 m->racecall = false; 48 return racectx; 49 } 50 51 void 52 runtime·racefini(void) 53 { 54 m->racecall = true; 55 runtime∕race·Finalize(); 56 m->racecall = false; 57 } 58 59 void 60 runtime·racemapshadow(void *addr, uintptr size) 61 { 62 m->racecall = true; 63 runtime∕race·MapShadow(addr, size); 64 m->racecall = false; 65 } 66 67 // Called from instrumented code. 68 // If we split stack, getcallerpc() can return runtime·lessstack(). 69 #pragma textflag 7 70 void 71 runtime·racewrite(uintptr addr) 72 { 73 if(!onstack(addr)) { 74 m->racecall = true; 75 runtime∕race·Write(g->racectx, (void*)addr, runtime·getcallerpc(&addr)); 76 m->racecall = false; 77 } 78 } 79 80 // Called from instrumented code. 81 // If we split stack, getcallerpc() can return runtime·lessstack(). 82 #pragma textflag 7 83 void 84 runtime·raceread(uintptr addr) 85 { 86 if(!onstack(addr)) { 87 m->racecall = true; 88 runtime∕race·Read(g->racectx, (void*)addr, runtime·getcallerpc(&addr)); 89 m->racecall = false; 90 } 91 } 92 93 // Called from runtime·racefuncenter (assembly). 94 #pragma textflag 7 95 void 96 runtime·racefuncenter1(uintptr pc) 97 { 98 // If the caller PC is lessstack, use slower runtime·callers 99 // to walk across the stack split to find the real caller. 100 if(pc == (uintptr)runtime·lessstack) 101 runtime·callers(2, &pc, 1); 102 103 m->racecall = true; 104 runtime∕race·FuncEnter(g->racectx, (void*)pc); 105 m->racecall = false; 106 } 107 108 // Called from instrumented code. 109 #pragma textflag 7 110 void 111 runtime·racefuncexit(void) 112 { 113 m->racecall = true; 114 runtime∕race·FuncExit(g->racectx); 115 m->racecall = false; 116 } 117 118 void 119 runtime·racemalloc(void *p, uintptr sz, void *pc) 120 { 121 // use m->curg because runtime·stackalloc() is called from g0 122 if(m->curg == nil) 123 return; 124 m->racecall = true; 125 runtime∕race·Malloc(m->curg->racectx, p, sz, pc); 126 m->racecall = false; 127 } 128 129 void 130 runtime·racefree(void *p) 131 { 132 m->racecall = true; 133 runtime∕race·Free(p); 134 m->racecall = false; 135 } 136 137 uintptr 138 runtime·racegostart(void *pc) 139 { 140 uintptr racectx; 141 142 m->racecall = true; 143 runtime∕race·GoStart(g->racectx, &racectx, pc); 144 m->racecall = false; 145 return racectx; 146 } 147 148 void 149 runtime·racegoend(void) 150 { 151 m->racecall = true; 152 runtime∕race·GoEnd(g->racectx); 153 m->racecall = false; 154 } 155 156 static void 157 memoryaccess(void *addr, uintptr callpc, uintptr pc, bool write) 158 { 159 uintptr racectx; 160 161 if(!onstack((uintptr)addr)) { 162 m->racecall = true; 163 racectx = g->racectx; 164 if(callpc) { 165 if(callpc == (uintptr)runtime·lessstack) 166 runtime·callers(3, &callpc, 1); 167 runtime∕race·FuncEnter(racectx, (void*)callpc); 168 } 169 if(write) 170 runtime∕race·Write(racectx, addr, (void*)pc); 171 else 172 runtime∕race·Read(racectx, addr, (void*)pc); 173 if(callpc) 174 runtime∕race·FuncExit(racectx); 175 m->racecall = false; 176 } 177 } 178 179 void 180 runtime·racewritepc(void *addr, void *callpc, void *pc) 181 { 182 memoryaccess(addr, (uintptr)callpc, (uintptr)pc, true); 183 } 184 185 void 186 runtime·racereadpc(void *addr, void *callpc, void *pc) 187 { 188 memoryaccess(addr, (uintptr)callpc, (uintptr)pc, false); 189 } 190 191 static void 192 rangeaccess(void *addr, uintptr size, uintptr step, uintptr callpc, uintptr pc, bool write) 193 { 194 uintptr racectx; 195 196 if(!onstack((uintptr)addr)) { 197 m->racecall = true; 198 racectx = g->racectx; 199 if(callpc) { 200 if(callpc == (uintptr)runtime·lessstack) 201 runtime·callers(3, &callpc, 1); 202 runtime∕race·FuncEnter(racectx, (void*)callpc); 203 } 204 if(write) 205 runtime∕race·WriteRange(racectx, addr, size, step, (void*)pc); 206 else 207 runtime∕race·ReadRange(racectx, addr, size, step, (void*)pc); 208 if(callpc) 209 runtime∕race·FuncExit(racectx); 210 m->racecall = false; 211 } 212 } 213 214 void 215 runtime·racewriterangepc(void *addr, uintptr sz, uintptr step, void *callpc, void *pc) 216 { 217 rangeaccess(addr, sz, step, (uintptr)callpc, (uintptr)pc, true); 218 } 219 220 void 221 runtime·racereadrangepc(void *addr, uintptr sz, uintptr step, void *callpc, void *pc) 222 { 223 rangeaccess(addr, sz, step, (uintptr)callpc, (uintptr)pc, false); 224 } 225 226 void 227 runtime·raceacquire(void *addr) 228 { 229 runtime·raceacquireg(g, addr); 230 } 231 232 void 233 runtime·raceacquireg(G *gp, void *addr) 234 { 235 if(g->raceignore) 236 return; 237 m->racecall = true; 238 runtime∕race·Acquire(gp->racectx, addr); 239 m->racecall = false; 240 } 241 242 void 243 runtime·racerelease(void *addr) 244 { 245 runtime·racereleaseg(g, addr); 246 } 247 248 void 249 runtime·racereleaseg(G *gp, void *addr) 250 { 251 if(g->raceignore) 252 return; 253 m->racecall = true; 254 runtime∕race·Release(gp->racectx, addr); 255 m->racecall = false; 256 } 257 258 void 259 runtime·racereleasemerge(void *addr) 260 { 261 runtime·racereleasemergeg(g, addr); 262 } 263 264 void 265 runtime·racereleasemergeg(G *gp, void *addr) 266 { 267 if(g->raceignore) 268 return; 269 m->racecall = true; 270 runtime∕race·ReleaseMerge(gp->racectx, addr); 271 m->racecall = false; 272 } 273 274 void 275 runtime·racefingo(void) 276 { 277 m->racecall = true; 278 runtime∕race·FinalizerGoroutine(g->racectx); 279 m->racecall = false; 280 } 281 282 // func RaceAcquire(addr unsafe.Pointer) 283 void 284 runtime·RaceAcquire(void *addr) 285 { 286 runtime·raceacquire(addr); 287 } 288 289 // func RaceRelease(addr unsafe.Pointer) 290 void 291 runtime·RaceRelease(void *addr) 292 { 293 runtime·racerelease(addr); 294 } 295 296 // func RaceReleaseMerge(addr unsafe.Pointer) 297 void 298 runtime·RaceReleaseMerge(void *addr) 299 { 300 runtime·racereleasemerge(addr); 301 } 302 303 // func RaceSemacquire(s *uint32) 304 void runtime·RaceSemacquire(uint32 *s) 305 { 306 runtime·semacquire(s); 307 } 308 309 // func RaceSemrelease(s *uint32) 310 void runtime·RaceSemrelease(uint32 *s) 311 { 312 runtime·semrelease(s); 313 } 314 315 // func RaceRead(addr unsafe.Pointer) 316 #pragma textflag 7 317 void 318 runtime·RaceRead(void *addr) 319 { 320 memoryaccess(addr, 0, (uintptr)runtime·getcallerpc(&addr), false); 321 } 322 323 // func RaceWrite(addr unsafe.Pointer) 324 #pragma textflag 7 325 void 326 runtime·RaceWrite(void *addr) 327 { 328 memoryaccess(addr, 0, (uintptr)runtime·getcallerpc(&addr), true); 329 } 330 331 // func RaceDisable() 332 void runtime·RaceDisable(void) 333 { 334 g->raceignore++; 335 } 336 337 // func RaceEnable() 338 void runtime·RaceEnable(void) 339 { 340 g->raceignore--; 341 } 342 343 static bool 344 onstack(uintptr argp) 345 { 346 // noptrdata, data, bss, noptrbss 347 // the layout is in ../../cmd/ld/data.c 348 if((byte*)argp >= noptrdata && (byte*)argp < enoptrbss) 349 return false; 350 if((byte*)argp >= runtime·mheap->arena_start && (byte*)argp < runtime·mheap->arena_used) 351 return false; 352 return true; 353 }