1// Copyright 2012 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//go:build race 6 7package runtime 8 9import ( 10 "internal/abi" 11 "unsafe" 12) 13 14// Public race detection API, present iff build with -race. 15 16func RaceRead(addr unsafe.Pointer) 17func RaceWrite(addr unsafe.Pointer) 18func RaceReadRange(addr unsafe.Pointer, len int) 19func RaceWriteRange(addr unsafe.Pointer, len int) 20 21func RaceErrors() int { 22 var n uint64 23 racecall(&__tsan_report_count, uintptr(unsafe.Pointer(&n)), 0, 0, 0) 24 return int(n) 25} 26 27// RaceAcquire/RaceRelease/RaceReleaseMerge establish happens-before relations 28// between goroutines. These inform the race detector about actual synchronization 29// that it can't see for some reason (e.g. synchronization within RaceDisable/RaceEnable 30// sections of code). 31// RaceAcquire establishes a happens-before relation with the preceding 32// RaceReleaseMerge on addr up to and including the last RaceRelease on addr. 33// In terms of the C memory model (C11 §5.1.2.4, §7.17.3), 34// RaceAcquire is equivalent to atomic_load(memory_order_acquire). 35// 36//go:nosplit 37func RaceAcquire(addr unsafe.Pointer) { 38 raceacquire(addr) 39} 40 41// RaceRelease performs a release operation on addr that 42// can synchronize with a later RaceAcquire on addr. 43// 44// In terms of the C memory model, RaceRelease is equivalent to 45// atomic_store(memory_order_release). 46// 47//go:nosplit 48func RaceRelease(addr unsafe.Pointer) { 49 racerelease(addr) 50} 51 52// RaceReleaseMerge is like RaceRelease, but also establishes a happens-before 53// relation with the preceding RaceRelease or RaceReleaseMerge on addr. 54// 55// In terms of the C memory model, RaceReleaseMerge is equivalent to 56// atomic_exchange(memory_order_release). 57// 58//go:nosplit 59func RaceReleaseMerge(addr unsafe.Pointer) { 60 racereleasemerge(addr) 61} 62 63// RaceDisable disables handling of race synchronization events in the current goroutine. 64// Handling is re-enabled with RaceEnable. RaceDisable/RaceEnable can be nested. 65// Non-synchronization events (memory accesses, function entry/exit) still affect 66// the race detector. 67// 68//go:nosplit 69func RaceDisable() { 70 gp := getg() 71 if gp.raceignore == 0 { 72 racecall(&__tsan_go_ignore_sync_begin, gp.racectx, 0, 0, 0) 73 } 74 gp.raceignore++ 75} 76 77// RaceEnable re-enables handling of race events in the current goroutine. 78// 79//go:nosplit 80func RaceEnable() { 81 gp := getg() 82 gp.raceignore-- 83 if gp.raceignore == 0 { 84 racecall(&__tsan_go_ignore_sync_end, gp.racectx, 0, 0, 0) 85 } 86} 87 88// Private interface for the runtime. 89 90const raceenabled = true 91 92// For all functions accepting callerpc and pc, 93// callerpc is a return PC of the function that calls this function, 94// pc is start PC of the function that calls this function. 95func raceReadObjectPC(t *_type, addr unsafe.Pointer, callerpc, pc uintptr) { 96 kind := t.Kind_ & abi.KindMask 97 if kind == abi.Array || kind == abi.Struct { 98 // for composite objects we have to read every address 99 // because a write might happen to any subobject. 100 racereadrangepc(addr, t.Size_, callerpc, pc) 101 } else { 102 // for non-composite objects we can read just the start 103 // address, as any write must write the first byte. 104 racereadpc(addr, callerpc, pc) 105 } 106} 107 108func raceWriteObjectPC(t *_type, addr unsafe.Pointer, callerpc, pc uintptr) { 109 kind := t.Kind_ & abi.KindMask 110 if kind == abi.Array || kind == abi.Struct { 111 // for composite objects we have to write every address 112 // because a write might happen to any subobject. 113 racewriterangepc(addr, t.Size_, callerpc, pc) 114 } else { 115 // for non-composite objects we can write just the start 116 // address, as any write must write the first byte. 117 racewritepc(addr, callerpc, pc) 118 } 119} 120 121//go:noescape 122func racereadpc(addr unsafe.Pointer, callpc, pc uintptr) 123 124//go:noescape 125func racewritepc(addr unsafe.Pointer, callpc, pc uintptr) 126 127type symbolizeCodeContext struct { 128 pc uintptr 129 fn *byte 130 file *byte 131 line uintptr 132 off uintptr 133 res uintptr 134} 135 136var qq = [...]byte{'?', '?', 0} 137var dash = [...]byte{'-', 0} 138 139const ( 140 raceGetProcCmd = iota 141 raceSymbolizeCodeCmd 142 raceSymbolizeDataCmd 143) 144 145// Callback from C into Go, runs on g0. 146func racecallback(cmd uintptr, ctx unsafe.Pointer) { 147 switch cmd { 148 case raceGetProcCmd: 149 throw("should have been handled by racecallbackthunk") 150 case raceSymbolizeCodeCmd: 151 raceSymbolizeCode((*symbolizeCodeContext)(ctx)) 152 case raceSymbolizeDataCmd: 153 raceSymbolizeData((*symbolizeDataContext)(ctx)) 154 default: 155 throw("unknown command") 156 } 157} 158 159// raceSymbolizeCode reads ctx.pc and populates the rest of *ctx with 160// information about the code at that pc. 161// 162// The race detector has already subtracted 1 from pcs, so they point to the last 163// byte of call instructions (including calls to runtime.racewrite and friends). 164// 165// If the incoming pc is part of an inlined function, *ctx is populated 166// with information about the inlined function, and on return ctx.pc is set 167// to a pc in the logically containing function. (The race detector should call this 168// function again with that pc.) 169// 170// If the incoming pc is not part of an inlined function, the return pc is unchanged. 171func raceSymbolizeCode(ctx *symbolizeCodeContext) { 172 pc := ctx.pc 173 fi := findfunc(pc) 174 if fi.valid() { 175 u, uf := newInlineUnwinder(fi, pc) 176 for ; uf.valid(); uf = u.next(uf) { 177 sf := u.srcFunc(uf) 178 if sf.funcID == abi.FuncIDWrapper && u.isInlined(uf) { 179 // Ignore wrappers, unless we're at the outermost frame of u. 180 // A non-inlined wrapper frame always means we have a physical 181 // frame consisting entirely of wrappers, in which case we'll 182 // take an outermost wrapper over nothing. 183 continue 184 } 185 186 name := sf.name() 187 file, line := u.fileLine(uf) 188 if line == 0 { 189 // Failure to symbolize 190 continue 191 } 192 ctx.fn = &bytes(name)[0] // assume NUL-terminated 193 ctx.line = uintptr(line) 194 ctx.file = &bytes(file)[0] // assume NUL-terminated 195 ctx.off = pc - fi.entry() 196 ctx.res = 1 197 if u.isInlined(uf) { 198 // Set ctx.pc to the "caller" so the race detector calls this again 199 // to further unwind. 200 uf = u.next(uf) 201 ctx.pc = uf.pc 202 } 203 return 204 } 205 } 206 ctx.fn = &qq[0] 207 ctx.file = &dash[0] 208 ctx.line = 0 209 ctx.off = ctx.pc 210 ctx.res = 1 211} 212 213type symbolizeDataContext struct { 214 addr uintptr 215 heap uintptr 216 start uintptr 217 size uintptr 218 name *byte 219 file *byte 220 line uintptr 221 res uintptr 222} 223 224func raceSymbolizeData(ctx *symbolizeDataContext) { 225 if base, span, _ := findObject(ctx.addr, 0, 0); base != 0 { 226 // TODO: Does this need to handle malloc headers? 227 ctx.heap = 1 228 ctx.start = base 229 ctx.size = span.elemsize 230 ctx.res = 1 231 } 232} 233 234// Race runtime functions called via runtime·racecall. 235// 236//go:linkname __tsan_init __tsan_init 237var __tsan_init byte 238 239//go:linkname __tsan_fini __tsan_fini 240var __tsan_fini byte 241 242//go:linkname __tsan_proc_create __tsan_proc_create 243var __tsan_proc_create byte 244 245//go:linkname __tsan_proc_destroy __tsan_proc_destroy 246var __tsan_proc_destroy byte 247 248//go:linkname __tsan_map_shadow __tsan_map_shadow 249var __tsan_map_shadow byte 250 251//go:linkname __tsan_finalizer_goroutine __tsan_finalizer_goroutine 252var __tsan_finalizer_goroutine byte 253 254//go:linkname __tsan_go_start __tsan_go_start 255var __tsan_go_start byte 256 257//go:linkname __tsan_go_end __tsan_go_end 258var __tsan_go_end byte 259 260//go:linkname __tsan_malloc __tsan_malloc 261var __tsan_malloc byte 262 263//go:linkname __tsan_free __tsan_free 264var __tsan_free byte 265 266//go:linkname __tsan_acquire __tsan_acquire 267var __tsan_acquire byte 268 269//go:linkname __tsan_release __tsan_release 270var __tsan_release byte 271 272//go:linkname __tsan_release_acquire __tsan_release_acquire 273var __tsan_release_acquire byte 274 275//go:linkname __tsan_release_merge __tsan_release_merge 276var __tsan_release_merge byte 277 278//go:linkname __tsan_go_ignore_sync_begin __tsan_go_ignore_sync_begin 279var __tsan_go_ignore_sync_begin byte 280 281//go:linkname __tsan_go_ignore_sync_end __tsan_go_ignore_sync_end 282var __tsan_go_ignore_sync_end byte 283 284//go:linkname __tsan_report_count __tsan_report_count 285var __tsan_report_count byte 286 287// Mimic what cmd/cgo would do. 288// 289//go:cgo_import_static __tsan_init 290//go:cgo_import_static __tsan_fini 291//go:cgo_import_static __tsan_proc_create 292//go:cgo_import_static __tsan_proc_destroy 293//go:cgo_import_static __tsan_map_shadow 294//go:cgo_import_static __tsan_finalizer_goroutine 295//go:cgo_import_static __tsan_go_start 296//go:cgo_import_static __tsan_go_end 297//go:cgo_import_static __tsan_malloc 298//go:cgo_import_static __tsan_free 299//go:cgo_import_static __tsan_acquire 300//go:cgo_import_static __tsan_release 301//go:cgo_import_static __tsan_release_acquire 302//go:cgo_import_static __tsan_release_merge 303//go:cgo_import_static __tsan_go_ignore_sync_begin 304//go:cgo_import_static __tsan_go_ignore_sync_end 305//go:cgo_import_static __tsan_report_count 306 307// These are called from race_amd64.s. 308// 309//go:cgo_import_static __tsan_read 310//go:cgo_import_static __tsan_read_pc 311//go:cgo_import_static __tsan_read_range 312//go:cgo_import_static __tsan_write 313//go:cgo_import_static __tsan_write_pc 314//go:cgo_import_static __tsan_write_range 315//go:cgo_import_static __tsan_func_enter 316//go:cgo_import_static __tsan_func_exit 317 318//go:cgo_import_static __tsan_go_atomic32_load 319//go:cgo_import_static __tsan_go_atomic64_load 320//go:cgo_import_static __tsan_go_atomic32_store 321//go:cgo_import_static __tsan_go_atomic64_store 322//go:cgo_import_static __tsan_go_atomic32_exchange 323//go:cgo_import_static __tsan_go_atomic64_exchange 324//go:cgo_import_static __tsan_go_atomic32_fetch_add 325//go:cgo_import_static __tsan_go_atomic64_fetch_add 326//go:cgo_import_static __tsan_go_atomic32_fetch_and 327//go:cgo_import_static __tsan_go_atomic64_fetch_and 328//go:cgo_import_static __tsan_go_atomic32_fetch_or 329//go:cgo_import_static __tsan_go_atomic64_fetch_or 330//go:cgo_import_static __tsan_go_atomic32_compare_exchange 331//go:cgo_import_static __tsan_go_atomic64_compare_exchange 332 333// start/end of global data (data+bss). 334var racedatastart uintptr 335var racedataend uintptr 336 337// start/end of heap for race_amd64.s 338var racearenastart uintptr 339var racearenaend uintptr 340 341func racefuncenter(callpc uintptr) 342func racefuncenterfp(fp uintptr) 343func racefuncexit() 344func raceread(addr uintptr) 345func racewrite(addr uintptr) 346func racereadrange(addr, size uintptr) 347func racewriterange(addr, size uintptr) 348func racereadrangepc1(addr, size, pc uintptr) 349func racewriterangepc1(addr, size, pc uintptr) 350func racecallbackthunk(uintptr) 351 352// racecall allows calling an arbitrary function fn from C race runtime 353// with up to 4 uintptr arguments. 354func racecall(fn *byte, arg0, arg1, arg2, arg3 uintptr) 355 356// checks if the address has shadow (i.e. heap or data/bss). 357// 358//go:nosplit 359func isvalidaddr(addr unsafe.Pointer) bool { 360 return racearenastart <= uintptr(addr) && uintptr(addr) < racearenaend || 361 racedatastart <= uintptr(addr) && uintptr(addr) < racedataend 362} 363 364//go:nosplit 365func raceinit() (gctx, pctx uintptr) { 366 lockInit(&raceFiniLock, lockRankRaceFini) 367 368 // On most machines, cgo is required to initialize libc, which is used by race runtime. 369 if !iscgo && GOOS != "darwin" { 370 throw("raceinit: race build must use cgo") 371 } 372 373 racecall(&__tsan_init, uintptr(unsafe.Pointer(&gctx)), uintptr(unsafe.Pointer(&pctx)), abi.FuncPCABI0(racecallbackthunk), 0) 374 375 // Round data segment to page boundaries, because it's used in mmap(). 376 start := ^uintptr(0) 377 end := uintptr(0) 378 if start > firstmoduledata.noptrdata { 379 start = firstmoduledata.noptrdata 380 } 381 if start > firstmoduledata.data { 382 start = firstmoduledata.data 383 } 384 if start > firstmoduledata.noptrbss { 385 start = firstmoduledata.noptrbss 386 } 387 if start > firstmoduledata.bss { 388 start = firstmoduledata.bss 389 } 390 if end < firstmoduledata.enoptrdata { 391 end = firstmoduledata.enoptrdata 392 } 393 if end < firstmoduledata.edata { 394 end = firstmoduledata.edata 395 } 396 if end < firstmoduledata.enoptrbss { 397 end = firstmoduledata.enoptrbss 398 } 399 if end < firstmoduledata.ebss { 400 end = firstmoduledata.ebss 401 } 402 size := alignUp(end-start, _PageSize) 403 racecall(&__tsan_map_shadow, start, size, 0, 0) 404 racedatastart = start 405 racedataend = start + size 406 407 return 408} 409 410//go:nosplit 411func racefini() { 412 // racefini() can only be called once to avoid races. 413 // This eventually (via __tsan_fini) calls C.exit which has 414 // undefined behavior if called more than once. If the lock is 415 // already held it's assumed that the first caller exits the program 416 // so other calls can hang forever without an issue. 417 lock(&raceFiniLock) 418 419 // __tsan_fini will run C atexit functions and C++ destructors, 420 // which can theoretically call back into Go. 421 // Tell the scheduler we entering external code. 422 entersyscall() 423 424 // We're entering external code that may call ExitProcess on 425 // Windows. 426 osPreemptExtEnter(getg().m) 427 428 racecall(&__tsan_fini, 0, 0, 0, 0) 429} 430 431//go:nosplit 432func raceproccreate() uintptr { 433 var ctx uintptr 434 racecall(&__tsan_proc_create, uintptr(unsafe.Pointer(&ctx)), 0, 0, 0) 435 return ctx 436} 437 438//go:nosplit 439func raceprocdestroy(ctx uintptr) { 440 racecall(&__tsan_proc_destroy, ctx, 0, 0, 0) 441} 442 443//go:nosplit 444func racemapshadow(addr unsafe.Pointer, size uintptr) { 445 if racearenastart == 0 { 446 racearenastart = uintptr(addr) 447 } 448 if racearenaend < uintptr(addr)+size { 449 racearenaend = uintptr(addr) + size 450 } 451 racecall(&__tsan_map_shadow, uintptr(addr), size, 0, 0) 452} 453 454//go:nosplit 455func racemalloc(p unsafe.Pointer, sz uintptr) { 456 racecall(&__tsan_malloc, 0, 0, uintptr(p), sz) 457} 458 459//go:nosplit 460func racefree(p unsafe.Pointer, sz uintptr) { 461 racecall(&__tsan_free, uintptr(p), sz, 0, 0) 462} 463 464//go:nosplit 465func racegostart(pc uintptr) uintptr { 466 gp := getg() 467 var spawng *g 468 if gp.m.curg != nil { 469 spawng = gp.m.curg 470 } else { 471 spawng = gp 472 } 473 474 var racectx uintptr 475 racecall(&__tsan_go_start, spawng.racectx, uintptr(unsafe.Pointer(&racectx)), pc, 0) 476 return racectx 477} 478 479//go:nosplit 480func racegoend() { 481 racecall(&__tsan_go_end, getg().racectx, 0, 0, 0) 482} 483 484//go:nosplit 485func racectxend(racectx uintptr) { 486 racecall(&__tsan_go_end, racectx, 0, 0, 0) 487} 488 489//go:nosplit 490func racewriterangepc(addr unsafe.Pointer, sz, callpc, pc uintptr) { 491 gp := getg() 492 if gp != gp.m.curg { 493 // The call is coming from manual instrumentation of Go code running on g0/gsignal. 494 // Not interesting. 495 return 496 } 497 if callpc != 0 { 498 racefuncenter(callpc) 499 } 500 racewriterangepc1(uintptr(addr), sz, pc) 501 if callpc != 0 { 502 racefuncexit() 503 } 504} 505 506//go:nosplit 507func racereadrangepc(addr unsafe.Pointer, sz, callpc, pc uintptr) { 508 gp := getg() 509 if gp != gp.m.curg { 510 // The call is coming from manual instrumentation of Go code running on g0/gsignal. 511 // Not interesting. 512 return 513 } 514 if callpc != 0 { 515 racefuncenter(callpc) 516 } 517 racereadrangepc1(uintptr(addr), sz, pc) 518 if callpc != 0 { 519 racefuncexit() 520 } 521} 522 523//go:nosplit 524func raceacquire(addr unsafe.Pointer) { 525 raceacquireg(getg(), addr) 526} 527 528//go:nosplit 529func raceacquireg(gp *g, addr unsafe.Pointer) { 530 if getg().raceignore != 0 || !isvalidaddr(addr) { 531 return 532 } 533 racecall(&__tsan_acquire, gp.racectx, uintptr(addr), 0, 0) 534} 535 536//go:nosplit 537func raceacquirectx(racectx uintptr, addr unsafe.Pointer) { 538 if !isvalidaddr(addr) { 539 return 540 } 541 racecall(&__tsan_acquire, racectx, uintptr(addr), 0, 0) 542} 543 544//go:nosplit 545func racerelease(addr unsafe.Pointer) { 546 racereleaseg(getg(), addr) 547} 548 549//go:nosplit 550func racereleaseg(gp *g, addr unsafe.Pointer) { 551 if getg().raceignore != 0 || !isvalidaddr(addr) { 552 return 553 } 554 racecall(&__tsan_release, gp.racectx, uintptr(addr), 0, 0) 555} 556 557//go:nosplit 558func racereleaseacquire(addr unsafe.Pointer) { 559 racereleaseacquireg(getg(), addr) 560} 561 562//go:nosplit 563func racereleaseacquireg(gp *g, addr unsafe.Pointer) { 564 if getg().raceignore != 0 || !isvalidaddr(addr) { 565 return 566 } 567 racecall(&__tsan_release_acquire, gp.racectx, uintptr(addr), 0, 0) 568} 569 570//go:nosplit 571func racereleasemerge(addr unsafe.Pointer) { 572 racereleasemergeg(getg(), addr) 573} 574 575//go:nosplit 576func racereleasemergeg(gp *g, addr unsafe.Pointer) { 577 if getg().raceignore != 0 || !isvalidaddr(addr) { 578 return 579 } 580 racecall(&__tsan_release_merge, gp.racectx, uintptr(addr), 0, 0) 581} 582 583//go:nosplit 584func racefingo() { 585 racecall(&__tsan_finalizer_goroutine, getg().racectx, 0, 0, 0) 586} 587 588// The declarations below generate ABI wrappers for functions 589// implemented in assembly in this package but declared in another 590// package. 591 592//go:linkname abigen_sync_atomic_LoadInt32 sync/atomic.LoadInt32 593func abigen_sync_atomic_LoadInt32(addr *int32) (val int32) 594 595//go:linkname abigen_sync_atomic_LoadInt64 sync/atomic.LoadInt64 596func abigen_sync_atomic_LoadInt64(addr *int64) (val int64) 597 598//go:linkname abigen_sync_atomic_LoadUint32 sync/atomic.LoadUint32 599func abigen_sync_atomic_LoadUint32(addr *uint32) (val uint32) 600 601//go:linkname abigen_sync_atomic_LoadUint64 sync/atomic.LoadUint64 602func abigen_sync_atomic_LoadUint64(addr *uint64) (val uint64) 603 604//go:linkname abigen_sync_atomic_LoadUintptr sync/atomic.LoadUintptr 605func abigen_sync_atomic_LoadUintptr(addr *uintptr) (val uintptr) 606 607//go:linkname abigen_sync_atomic_LoadPointer sync/atomic.LoadPointer 608func abigen_sync_atomic_LoadPointer(addr *unsafe.Pointer) (val unsafe.Pointer) 609 610//go:linkname abigen_sync_atomic_StoreInt32 sync/atomic.StoreInt32 611func abigen_sync_atomic_StoreInt32(addr *int32, val int32) 612 613//go:linkname abigen_sync_atomic_StoreInt64 sync/atomic.StoreInt64 614func abigen_sync_atomic_StoreInt64(addr *int64, val int64) 615 616//go:linkname abigen_sync_atomic_StoreUint32 sync/atomic.StoreUint32 617func abigen_sync_atomic_StoreUint32(addr *uint32, val uint32) 618 619//go:linkname abigen_sync_atomic_StoreUint64 sync/atomic.StoreUint64 620func abigen_sync_atomic_StoreUint64(addr *uint64, val uint64) 621 622//go:linkname abigen_sync_atomic_SwapInt32 sync/atomic.SwapInt32 623func abigen_sync_atomic_SwapInt32(addr *int32, new int32) (old int32) 624 625//go:linkname abigen_sync_atomic_SwapInt64 sync/atomic.SwapInt64 626func abigen_sync_atomic_SwapInt64(addr *int64, new int64) (old int64) 627 628//go:linkname abigen_sync_atomic_SwapUint32 sync/atomic.SwapUint32 629func abigen_sync_atomic_SwapUint32(addr *uint32, new uint32) (old uint32) 630 631//go:linkname abigen_sync_atomic_SwapUint64 sync/atomic.SwapUint64 632func abigen_sync_atomic_SwapUint64(addr *uint64, new uint64) (old uint64) 633 634//go:linkname abigen_sync_atomic_AddInt32 sync/atomic.AddInt32 635func abigen_sync_atomic_AddInt32(addr *int32, delta int32) (new int32) 636 637//go:linkname abigen_sync_atomic_AddUint32 sync/atomic.AddUint32 638func abigen_sync_atomic_AddUint32(addr *uint32, delta uint32) (new uint32) 639 640//go:linkname abigen_sync_atomic_AddInt64 sync/atomic.AddInt64 641func abigen_sync_atomic_AddInt64(addr *int64, delta int64) (new int64) 642 643//go:linkname abigen_sync_atomic_AddUint64 sync/atomic.AddUint64 644func abigen_sync_atomic_AddUint64(addr *uint64, delta uint64) (new uint64) 645 646//go:linkname abigen_sync_atomic_AddUintptr sync/atomic.AddUintptr 647func abigen_sync_atomic_AddUintptr(addr *uintptr, delta uintptr) (new uintptr) 648 649//go:linkname abigen_sync_atomic_AndInt32 sync/atomic.AndInt32 650func abigen_sync_atomic_AndInt32(addr *int32, mask int32) (old int32) 651 652//go:linkname abigen_sync_atomic_AndUint32 sync/atomic.AndUint32 653func abigen_sync_atomic_AndUint32(addr *uint32, mask uint32) (old uint32) 654 655//go:linkname abigen_sync_atomic_AndInt64 sync/atomic.AndInt64 656func abigen_sync_atomic_AndInt64(addr *int64, mask int64) (old int64) 657 658//go:linkname abigen_sync_atomic_AndUint64 sync/atomic.AndUint64 659func abigen_sync_atomic_AndUint64(addr *uint64, mask uint64) (old uint64) 660 661//go:linkname abigen_sync_atomic_AndUintptr sync/atomic.AndUintptr 662func abigen_sync_atomic_AndUintptr(addr *uintptr, mask uintptr) (old uintptr) 663 664//go:linkname abigen_sync_atomic_OrInt32 sync/atomic.OrInt32 665func abigen_sync_atomic_OrInt32(addr *int32, mask int32) (old int32) 666 667//go:linkname abigen_sync_atomic_OrUint32 sync/atomic.OrUint32 668func abigen_sync_atomic_OrUint32(addr *uint32, mask uint32) (old uint32) 669 670//go:linkname abigen_sync_atomic_OrInt64 sync/atomic.OrInt64 671func abigen_sync_atomic_OrInt64(addr *int64, mask int64) (old int64) 672 673//go:linkname abigen_sync_atomic_OrUint64 sync/atomic.OrUint64 674func abigen_sync_atomic_OrUint64(addr *uint64, mask uint64) (old uint64) 675 676//go:linkname abigen_sync_atomic_OrUintptr sync/atomic.OrUintptr 677func abigen_sync_atomic_OrUintptr(addr *uintptr, mask uintptr) (old uintptr) 678 679//go:linkname abigen_sync_atomic_CompareAndSwapInt32 sync/atomic.CompareAndSwapInt32 680func abigen_sync_atomic_CompareAndSwapInt32(addr *int32, old, new int32) (swapped bool) 681 682//go:linkname abigen_sync_atomic_CompareAndSwapInt64 sync/atomic.CompareAndSwapInt64 683func abigen_sync_atomic_CompareAndSwapInt64(addr *int64, old, new int64) (swapped bool) 684 685//go:linkname abigen_sync_atomic_CompareAndSwapUint32 sync/atomic.CompareAndSwapUint32 686func abigen_sync_atomic_CompareAndSwapUint32(addr *uint32, old, new uint32) (swapped bool) 687 688//go:linkname abigen_sync_atomic_CompareAndSwapUint64 sync/atomic.CompareAndSwapUint64 689func abigen_sync_atomic_CompareAndSwapUint64(addr *uint64, old, new uint64) (swapped bool) 690