Skip to content

Commit b5bd0b7

Browse files
committed
sync/atomic: public And/Or apis
Fixes [reserved]
1 parent 0c7e5d3 commit b5bd0b7

File tree

11 files changed

+954
-10
lines changed

11 files changed

+954
-10
lines changed

api/next/61335.txt

+21
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
pkg sync/atomic, func AndInt32(*int32, int32) int32 #61395
2+
pkg sync/atomic, func AndInt64(*int64, int64) int64 #61395
3+
pkg sync/atomic, func AndUint32(*uint32, uint32) uint32 #61395
4+
pkg sync/atomic, func AndUint64(*uint64, uint64) uint64 #61395
5+
pkg sync/atomic, func AndUintptr(*uintptr, uintptr) uintptr #61395
6+
pkg sync/atomic, func OrInt32(*int32, int32) int32 #61395
7+
pkg sync/atomic, func OrInt64(*int64, int64) int64 #61395
8+
pkg sync/atomic, func OrUint32(*uint32, uint32) uint32 #61395
9+
pkg sync/atomic, func OrUint64(*uint64, uint64) uint64 #61395
10+
pkg sync/atomic, func OrUintptr(*uintptr, uintptr) uintptr #61395
11+
pkg sync/atomic, method (*Int32) And(int32) int32 #61395
12+
pkg sync/atomic, method (*Int64) And(int64) int64 #61395
13+
pkg sync/atomic, method (*Uint32) And(uint32) uint32 #61395
14+
pkg sync/atomic, method (*Uint64) And(uint64) uint64 #61395
15+
pkg sync/atomic, method (*Uintptr) And(uintptr) uintptr #61395
16+
pkg sync/atomic, method (*Int32) Or(int32) int32 #61395
17+
pkg sync/atomic, method (*Int64) Or(int64) int64 #61395
18+
pkg sync/atomic, method (*Uint32) Or(uint32) uint32 #61395
19+
pkg sync/atomic, method (*Uint64) Or(uint64) uint64 #61395
20+
pkg sync/atomic, method (*Uintptr) Or(uintptr) uintptr #61395
21+

src/runtime/race.go

+34
Original file line numberDiff line numberDiff line change
@@ -323,6 +323,10 @@ var __tsan_report_count byte
323323
//go:cgo_import_static __tsan_go_atomic64_exchange
324324
//go:cgo_import_static __tsan_go_atomic32_fetch_add
325325
//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
326330
//go:cgo_import_static __tsan_go_atomic32_compare_exchange
327331
//go:cgo_import_static __tsan_go_atomic64_compare_exchange
328332

@@ -642,6 +646,36 @@ func abigen_sync_atomic_AddUint64(addr *uint64, delta uint64) (new uint64)
642646
//go:linkname abigen_sync_atomic_AddUintptr sync/atomic.AddUintptr
643647
func abigen_sync_atomic_AddUintptr(addr *uintptr, delta uintptr) (new uintptr)
644648

649+
//go:linkname abigen_sync_atomic_AndInt32 sync/atomic.AndInt32
650+
func abigen_sync_atomic_AndInt32(addr *int32, mask int32) (old int32)
651+
652+
//go:linkname abigen_sync_atomic_AndUint32 sync/atomic.AndUint32
653+
func abigen_sync_atomic_AndUint32(addr *uint32, mask uint32) (old uint32)
654+
655+
//go:linkname abigen_sync_atomic_AndInt64 sync/atomic.AndInt64
656+
func abigen_sync_atomic_AndInt64(addr *int64, mask int64) (old int64)
657+
658+
//go:linkname abigen_sync_atomic_AndUint64 sync/atomic.AndUint64
659+
func abigen_sync_atomic_AndUint64(addr *uint64, mask uint64) (old uint64)
660+
661+
//go:linkname abigen_sync_atomic_AndUintptr sync/atomic.AndUintptr
662+
func abigen_sync_atomic_AndUintptr(addr *uintptr, mask uintptr) (old uintptr)
663+
664+
//go:linkname abigen_sync_atomic_OrInt32 sync/atomic.OrInt32
665+
func abigen_sync_atomic_OrInt32(addr *int32, mask int32) (old int32)
666+
667+
//go:linkname abigen_sync_atomic_OrUint32 sync/atomic.OrUint32
668+
func abigen_sync_atomic_OrUint32(addr *uint32, mask uint32) (old uint32)
669+
670+
//go:linkname abigen_sync_atomic_OrInt64 sync/atomic.OrInt64
671+
func abigen_sync_atomic_OrInt64(addr *int64, mask int64) (old int64)
672+
673+
//go:linkname abigen_sync_atomic_OrUint64 sync/atomic.OrUint64
674+
func abigen_sync_atomic_OrUint64(addr *uint64, mask uint64) (old uint64)
675+
676+
//go:linkname abigen_sync_atomic_OrUintptr sync/atomic.OrUintptr
677+
func abigen_sync_atomic_OrUintptr(addr *uintptr, mask uintptr) (old uintptr)
678+
645679
//go:linkname abigen_sync_atomic_CompareAndSwapInt32 sync/atomic.CompareAndSwapInt32
646680
func abigen_sync_atomic_CompareAndSwapInt32(addr *int32, old, new int32) (swapped bool)
647681

src/runtime/race_amd64.s

+63-10
Original file line numberDiff line numberDiff line change
@@ -162,7 +162,7 @@ data:
162162
JAE ret
163163
call:
164164
MOVQ AX, AX // w/o this 6a miscompiles this function
165-
JMP racecall<>(SB)
165+
JMP racecall(SB)
166166
ret:
167167
RET
168168

@@ -180,8 +180,8 @@ TEXT racefuncenter<>(SB), NOSPLIT|NOFRAME, $0-0
180180
MOVQ R11, RARG1
181181
// void __tsan_func_enter(ThreadState *thr, void *pc);
182182
MOVQ $__tsan_func_enter(SB), AX
183-
// racecall<> preserves BX
184-
CALL racecall<>(SB)
183+
// racecall preserves BX
184+
CALL racecall(SB)
185185
MOVQ BX, DX // restore function entry context
186186
RET
187187

@@ -191,7 +191,7 @@ TEXT runtime·racefuncexit(SB), NOSPLIT, $0-0
191191
MOVQ g_racectx(R14), RARG0 // goroutine context
192192
// void __tsan_func_exit(ThreadState *thr);
193193
MOVQ $__tsan_func_exit(SB), AX
194-
JMP racecall<>(SB)
194+
JMP racecall(SB)
195195

196196
// Atomic operations for sync/atomic package.
197197

@@ -303,6 +303,59 @@ TEXT sync∕atomic·AddUintptr(SB), NOSPLIT, $0-24
303303
GO_ARGS
304304
JMP sync∕atomic·AddInt64(SB)
305305

306+
307+
// For OpenBSD, see race_openbsd_amd64.s for implementation.
308+
#ifndef GOOS_openbsd
309+
// And
310+
TEXT sync∕atomic·AndInt32(SB), NOSPLIT|NOFRAME, $0-20
311+
GO_ARGS
312+
MOVQ $__tsan_go_atomic32_fetch_and(SB), AX
313+
CALL racecallatomic<>(SB)
314+
RET
315+
316+
TEXT sync∕atomic·AndInt64(SB), NOSPLIT|NOFRAME, $0-24
317+
GO_ARGS
318+
MOVQ $__tsan_go_atomic64_fetch_and(SB), AX
319+
CALL racecallatomic<>(SB)
320+
RET
321+
// Or
322+
TEXT sync∕atomic·OrInt32(SB), NOSPLIT|NOFRAME, $0-20
323+
GO_ARGS
324+
MOVQ $__tsan_go_atomic32_fetch_or(SB), AX
325+
CALL racecallatomic<>(SB)
326+
RET
327+
328+
TEXT sync∕atomic·OrInt64(SB), NOSPLIT|NOFRAME, $0-24
329+
GO_ARGS
330+
MOVQ $__tsan_go_atomic64_fetch_or(SB), AX
331+
CALL racecallatomic<>(SB)
332+
RET
333+
#endif
334+
335+
TEXT sync∕atomic·AndUint32(SB), NOSPLIT, $0-20
336+
GO_ARGS
337+
JMP sync∕atomic·AndInt32(SB)
338+
339+
TEXT sync∕atomic·AndUint64(SB), NOSPLIT, $0-24
340+
GO_ARGS
341+
JMP sync∕atomic·AndInt64(SB)
342+
343+
TEXT sync∕atomic·AndUintptr(SB), NOSPLIT, $0-24
344+
GO_ARGS
345+
JMP sync∕atomic·AndInt64(SB)
346+
347+
TEXT sync∕atomic·OrUint32(SB), NOSPLIT, $0-20
348+
GO_ARGS
349+
JMP sync∕atomic·OrInt32(SB)
350+
351+
TEXT sync∕atomic·OrUint64(SB), NOSPLIT, $0-24
352+
GO_ARGS
353+
JMP sync∕atomic·OrInt64(SB)
354+
355+
TEXT sync∕atomic·OrUintptr(SB), NOSPLIT, $0-24
356+
GO_ARGS
357+
JMP sync∕atomic·OrInt64(SB)
358+
306359
// CompareAndSwap
307360
TEXT sync∕atomic·CompareAndSwapInt32(SB), NOSPLIT|NOFRAME, $0-17
308361
GO_ARGS
@@ -350,26 +403,26 @@ racecallatomic_ok:
350403
MOVQ 8(SP), RARG1 // caller pc
351404
MOVQ (SP), RARG2 // pc
352405
LEAQ 16(SP), RARG3 // arguments
353-
JMP racecall<>(SB) // does not return
406+
JMP racecall(SB) // does not return
354407
racecallatomic_ignore:
355408
// Addr is outside the good range.
356409
// Call __tsan_go_ignore_sync_begin to ignore synchronization during the atomic op.
357410
// An attempt to synchronize on the address would cause crash.
358411
MOVQ AX, BX // remember the original function
359412
MOVQ $__tsan_go_ignore_sync_begin(SB), AX
360413
MOVQ g_racectx(R14), RARG0 // goroutine context
361-
CALL racecall<>(SB)
414+
CALL racecall(SB)
362415
MOVQ BX, AX // restore the original function
363416
// Call the atomic function.
364417
MOVQ g_racectx(R14), RARG0 // goroutine context
365418
MOVQ 8(SP), RARG1 // caller pc
366419
MOVQ (SP), RARG2 // pc
367420
LEAQ 16(SP), RARG3 // arguments
368-
CALL racecall<>(SB)
421+
CALL racecall(SB)
369422
// Call __tsan_go_ignore_sync_end.
370423
MOVQ $__tsan_go_ignore_sync_end(SB), AX
371424
MOVQ g_racectx(R14), RARG0 // goroutine context
372-
JMP racecall<>(SB)
425+
JMP racecall(SB)
373426

374427
// void runtime·racecall(void(*f)(...), ...)
375428
// Calls C function f from race runtime and passes up to 4 arguments to it.
@@ -380,10 +433,10 @@ TEXT runtime·racecall(SB), NOSPLIT, $0-0
380433
MOVQ arg1+16(FP), RARG1
381434
MOVQ arg2+24(FP), RARG2
382435
MOVQ arg3+32(FP), RARG3
383-
JMP racecall<>(SB)
436+
JMP racecall(SB)
384437

385438
// Switches SP to g0 stack and calls (AX). Arguments already set.
386-
TEXT racecall<>(SB), NOSPLIT|NOFRAME, $0-0
439+
TEXT racecall(SB), NOSPLIT|NOFRAME, $0-0
387440
MOVQ g_m(R14), R13
388441
// Switch to g0 stack.
389442
MOVQ SP, R12 // callee-saved, preserved across the CALL

src/runtime/race_arm64.s

+50
Original file line numberDiff line numberDiff line change
@@ -312,6 +312,56 @@ TEXT sync∕atomic·AddUintptr(SB), NOSPLIT, $0-24
312312
GO_ARGS
313313
JMP sync∕atomic·AddInt64(SB)
314314

315+
// And
316+
TEXT sync∕atomic·AndInt32(SB), NOSPLIT|NOFRAME, $0-20
317+
GO_ARGS
318+
MOVD $__tsan_go_atomic32_fetch_and(SB), R9
319+
BL racecallatomic<>(SB)
320+
RET
321+
322+
TEXT sync∕atomic·AndInt64(SB), NOSPLIT|NOFRAME, $0-24
323+
GO_ARGS
324+
MOVD $__tsan_go_atomic64_fetch_and(SB), R9
325+
BL racecallatomic<>(SB)
326+
RET
327+
328+
TEXT sync∕atomic·AndUint32(SB), NOSPLIT, $0-20
329+
GO_ARGS
330+
JMP sync∕atomic·AndInt32(SB)
331+
332+
TEXT sync∕atomic·AndUint64(SB), NOSPLIT, $0-24
333+
GO_ARGS
334+
JMP sync∕atomic·AndInt64(SB)
335+
336+
TEXT sync∕atomic·AndUintptr(SB), NOSPLIT, $0-24
337+
GO_ARGS
338+
JMP sync∕atomic·AndInt64(SB)
339+
340+
// Or
341+
TEXT sync∕atomic·OrInt32(SB), NOSPLIT|NOFRAME, $0-20
342+
GO_ARGS
343+
MOVD $__tsan_go_atomic32_fetch_or(SB), R9
344+
BL racecallatomic<>(SB)
345+
RET
346+
347+
TEXT sync∕atomic·OrInt64(SB), NOSPLIT|NOFRAME, $0-24
348+
GO_ARGS
349+
MOVD $__tsan_go_atomic64_fetch_or(SB), R9
350+
BL racecallatomic<>(SB)
351+
RET
352+
353+
TEXT sync∕atomic·OrUint32(SB), NOSPLIT, $0-20
354+
GO_ARGS
355+
JMP sync∕atomic·OrInt32(SB)
356+
357+
TEXT sync∕atomic·OrUint64(SB), NOSPLIT, $0-24
358+
GO_ARGS
359+
JMP sync∕atomic·OrInt64(SB)
360+
361+
TEXT sync∕atomic·OrUintptr(SB), NOSPLIT, $0-24
362+
GO_ARGS
363+
JMP sync∕atomic·OrInt64(SB)
364+
315365
// CompareAndSwap
316366
TEXT sync∕atomic·CompareAndSwapInt32(SB), NOSPLIT, $0-17
317367
GO_ARGS

src/runtime/race_openbsd_amd64.s

+110
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,110 @@
1+
// Copyright 2023 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+
7+
// OpenBSD uses tsan v2, which don't have access to the tsan v3 apis.
8+
// This file implements the missing operations on top of the v2 apis.
9+
10+
#include "go_asm.h"
11+
#include "funcdata.h"
12+
#include "textflag.h"
13+
14+
#define RARG0 DI
15+
#define RARG1 SI
16+
#define RARG2 DX
17+
#define RARG3 CX
18+
19+
TEXT sync∕atomic·AndInt64(SB), NOSPLIT, $0-24
20+
GO_ARGS
21+
22+
MOVQ addr+0(FP), R12
23+
MOVQ mask+8(FP), R13
24+
MOVQ (R12), R15
25+
ANDQ R15, R13
26+
27+
// args for tsan cas
28+
MOVQ R12, 16(SP) // addr
29+
MOVQ R15, 24(SP) // old
30+
MOVQ R13, 32(SP) // new
31+
32+
MOVQ g_racectx(R14), RARG0 // goroutine context
33+
MOVQ 8(SP), RARG1 // caller pc
34+
MOVQ (SP), RARG2 // pc
35+
LEAQ 16(SP), RARG3 // arguments
36+
MOVQ $__tsan_go_atomic64_compare_exchange(SB), AX
37+
CALL racecall(SB)
38+
39+
MOVQ R15, ret+16(FP)
40+
41+
RET
42+
43+
TEXT sync∕atomic·AndInt32(SB), NOSPLIT, $0-20
44+
GO_ARGS
45+
46+
MOVQ addr+0(FP), R12
47+
MOVL mask+8(FP), R13
48+
MOVL (R12), R15
49+
ANDL R15, R13
50+
51+
// args for tsan cas
52+
MOVQ R12, 16(SP) // addr
53+
MOVL R15, 24(SP) // old
54+
MOVL R13, 28(SP) // new
55+
56+
MOVQ g_racectx(R14), RARG0 // goroutine context
57+
MOVQ 8(SP), RARG1 // caller pc
58+
MOVQ (SP), RARG2 // pc
59+
LEAQ 16(SP), RARG3 // arguments
60+
MOVQ $__tsan_go_atomic32_compare_exchange(SB), AX
61+
CALL racecall(SB)
62+
63+
MOVQ R15, ret+16(FP)
64+
RET
65+
66+
// Or
67+
TEXT sync∕atomic·OrInt32(SB), NOSPLIT, $0-20
68+
GO_ARGS
69+
70+
MOVQ addr+0(FP), R12
71+
MOVL mask+8(FP), R13
72+
MOVL (R12), R15
73+
ORL R15, R13
74+
75+
MOVQ R12, 16(SP) // addr
76+
MOVL R15, 24(SP) // old
77+
MOVL R13, 28(SP) // new
78+
79+
MOVQ g_racectx(R14), RARG0 // goroutine context
80+
MOVQ 8(SP), RARG1 // caller pc
81+
MOVQ (SP), RARG2 // pc
82+
LEAQ 16(SP), RARG3 // arguments
83+
MOVQ $__tsan_go_atomic32_compare_exchange(SB), AX
84+
CALL racecall(SB)
85+
86+
MOVQ R15, ret+16(FP)
87+
RET
88+
89+
TEXT sync∕atomic·OrInt64(SB), NOSPLIT, $0-24
90+
GO_ARGS
91+
92+
MOVQ addr+0(FP), R12
93+
MOVQ mask+8(FP), R13
94+
MOVQ (R12), R15
95+
ORQ R15, R13
96+
97+
// args for tsan cas
98+
MOVQ R12, 16(SP) // addr
99+
MOVQ R15, 24(SP) // old
100+
MOVQ R13, 32(SP) // new
101+
102+
MOVQ g_racectx(R14), RARG0 // goroutine context
103+
MOVQ 8(SP), RARG1 // caller pc
104+
MOVQ (SP), RARG2 // pc
105+
LEAQ 16(SP), RARG3 // arguments
106+
MOVQ $__tsan_go_atomic64_compare_exchange(SB), AX
107+
CALL racecall(SB)
108+
109+
MOVQ R15, ret+16(FP)
110+
RET

0 commit comments

Comments
 (0)