Commit 22eab1f5 authored by Russ Cox's avatar Russ Cox

sync/atomic: new package

Fixes #170.

R=gri, iant, r, r2
CC=golang-dev
https://golang.org/cl/4241041
parent 64f9e5a1
......@@ -131,6 +131,7 @@ DIRS=\
strconv\
strings\
sync\
sync/atomic\
syscall\
syslog\
tabwriter\
......
# Copyright 2011 The Go Authors. All rights reserved.
# Use of this source code is governed by a BSD-style
# license that can be found in the LICENSE file.
include ../../../Make.inc
TARG=sync/atomic
GOFILES=\
doc.go\
OFILES=\
asm_$(GOARCH).$O\
ifeq ($(GOARCH),arm)
OFILES+=asm_$(GOOS)_$(GOARCH).$O
endif
include ../../../Make.pkg
// Copyright 2011 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
TEXT ·CompareAndSwapInt32(SB),7,$0
JMP ·CompareAndSwapUint32(SB)
TEXT ·CompareAndSwapUint32(SB),7,$0
MOVL valptr+0(FP), BP
MOVL old+4(FP), AX
MOVL new+8(FP), CX
// CMPXCHGL was introduced on the 486.
LOCK
CMPXCHGL CX, 0(BP)
SETEQ ret+12(FP)
RET
TEXT ·CompareAndSwapUintptr(SB),7,$0
JMP ·CompareAndSwapUint32(SB)
TEXT ·CompareAndSwapInt64(SB),7,$0
JMP ·CompareAndSwapUint64(SB)
TEXT ·CompareAndSwapUint64(SB),7,$0
MOVL valptr+0(FP), BP
MOVL oldlo+4(FP), AX
MOVL oldhi+8(FP), DX
MOVL newlo+12(FP), BX
MOVL newhi+16(FP), CX
// CMPXCHG8B was introduced on the Pentium.
LOCK
CMPXCHG8B 0(BP)
SETEQ ret+20(FP)
RET
TEXT ·AddInt32(SB),7,$0
JMP ·AddUint32(SB)
TEXT ·AddUint32(SB),7,$0
MOVL valptr+0(FP), BP
MOVL delta+4(FP), AX
MOVL AX, CX
// XADD was introduced on the 486.
LOCK
XADDL AX, 0(BP)
ADDL AX, CX
MOVL CX, ret+8(FP)
RET
TEXT ·AddUintptr(SB),7,$0
JMP ·AddUint32(SB)
TEXT ·AddInt64(SB),7,$0
JMP ·AddUint64(SB)
TEXT ·AddUint64(SB),7,$0
// no XADDQ so use CMPXCHG8B loop
MOVL valptr+0(FP), BP
// DI:SI = delta
MOVL deltalo+4(FP), SI
MOVL deltahi+8(FP), DI
// DX:AX = *valptr
MOVL 0(BP), AX
MOVL 4(BP), DX
addloop:
// CX:BX = DX:AX (*valptr) + DI:SI (delta)
MOVL AX, BX
MOVL DX, CX
ADDL SI, BX
ADCL DI, CX
// if *valptr == DX:AX {
// *valptr = CX:BX
// } else {
// DX:AX = *valptr
// }
// all in one instruction
LOCK
CMPXCHG8B 0(BP)
JNZ addloop
// success
// return CX:BX
MOVL BX, retlo+12(FP)
MOVL CX, rethi+16(FP)
RET
// Copyright 2011 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
TEXT ·CompareAndSwapInt32(SB),7,$0
JMP ·CompareAndSwapUint32(SB)
TEXT ·CompareAndSwapUint32(SB),7,$0
MOVQ valptr+0(FP), BP
MOVL old+8(FP), AX
MOVL new+12(FP), CX
LOCK
CMPXCHGL CX, 0(BP)
SETEQ ret+16(FP)
RET
TEXT ·CompareAndSwapUintptr(SB),7,$0
JMP ·CompareAndSwapUint64(SB)
TEXT ·CompareAndSwapInt64(SB),7,$0
JMP ·CompareAndSwapUint64(SB)
TEXT ·CompareAndSwapUint64(SB),7,$0
MOVQ valptr+0(FP), BP
MOVQ old+8(FP), AX
MOVQ new+16(FP), CX
LOCK
CMPXCHGQ CX, 0(BP)
SETEQ ret+24(FP)
RET
TEXT ·AddInt32(SB),7,$0
JMP ·AddUint32(SB)
TEXT ·AddUint32(SB),7,$0
MOVQ valptr+0(FP), BP
MOVL delta+8(FP), AX
MOVL AX, CX
LOCK
XADDL AX, 0(BP)
ADDL AX, CX
MOVL CX, ret+16(FP)
RET
TEXT ·AddUintptr(SB),7,$0
JMP ·AddUint64(SB)
TEXT ·AddInt64(SB),7,$0
JMP ·AddUint64(SB)
TEXT ·AddUint64(SB),7,$0
MOVQ valptr+0(FP), BP
MOVQ delta+8(FP), AX
MOVQ AX, CX
LOCK
XADDQ AX, 0(BP)
ADDQ AX, CX
MOVQ CX, ret+16(FP)
RET
// Copyright 2011 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// ARM atomic operations, for use by asm_$(GOOS)_arm.s.
TEXT ·armCompareAndSwapUint32(SB),7,$0
MOVW valptr+0(FP), R1
MOVW old+4(FP), R2
MOVW new+8(FP), R3
casloop:
// LDREX and STREX were introduced in ARM 6.
LDREX (R1), R0
CMP R0, R2
BNE casfail
STREX R3, (R1), R0
CMP $0, R0
BNE casloop
MOVW $1, R0
MOVBU R0, ret+12(FP)
RET
casfail:
MOVW $0, R0
MOVBU R0, ret+12(FP)
RET
TEXT ·armCompareAndSwapUint64(SB),7,$0
MOVW valptr+0(FP), R1
MOVW oldlo+4(FP), R2
MOVW oldhi+8(FP), R3
MOVW newlo+12(FP), R4
MOVW newhi+16(FP), R5
cas64loop:
// LDREXD and STREXD were introduced in ARM 11.
LDREXD (R1), R6 // loads R6 and R7
CMP R2, R6
BNE cas64fail
CMP R3, R7
BNE cas64fail
STREXD R4, (R1), R0 // stores R4 and R5
CMP $0, R0
BNE cas64loop
MOVW $1, R0
MOVBU R0, ret+20(FP)
RET
cas64fail:
MOVW $0, R0
MOVBU R0, ret+20(FP)
RET
TEXT ·armAddUint32(SB),7,$0
MOVW valptr+0(FP), R1
MOVW delta+4(FP), R2
addloop:
// LDREX and STREX were introduced in ARM 6.
LDREX (R1), R3
ADD R2, R3
STREX R3, (R1), R0
CMP $0, R0
BNE addloop
MOVW R3, ret+8(FP)
RET
TEXT ·armAddUint64(SB),7,$0
MOVW valptr+0(FP), R1
MOVW deltalo+4(FP), R2
MOVW deltahi+8(FP), R3
add64loop:
// LDREXD and STREXD were introduced in ARM 11.
LDREXD (R1), R4 // loads R4 and R5
ADD.S R2, R4
ADC R3, R5
STREXD R4, (R1), R0 // stores R4 and R5
CMP $0, R0
BNE add64loop
MOVW R4, retlo+12(FP)
MOVW R5, rethi+16(FP)
RET
This diff is collapsed.
// Copyright 2011 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// Package atomic provides low-level atomic memory primitives
// useful for implementing synchronization algorithms.
//
// These functions require great care to be used correctly.
// Except for special, low-level applications, synchronization is better
// done with channels or the facilities of the sync package.
// Share memory by communicating;
// don't communicate by sharing memory.
//
// The compare-and-swap operation, implemented by the CompareAndSwapT
// functions, is the atomic equivalent of:
//
// if *val == old {
// *val = new
// return true
// }
// return false
//
package atomic
// BUG(rsc):
// On ARM, the 64-bit functions use instructions unavailable before ARM 11.
//
// On x86-32, the 64-bit functions use instructions unavailable before the Pentium.
// CompareAndSwapInt32 executes the compare-and-swap operation for an int32 value.
func CompareAndSwapInt32(val *int32, old, new int32) (swapped bool)
// CompareAndSwapInt64 executes the compare-and-swap operation for an int64 value.
func CompareAndSwapInt64(val *int64, old, new int64) (swapped bool)
// CompareAndSwapUint32 executes the compare-and-swap operation for a uint32 value.
func CompareAndSwapUint32(val *uint32, old, new uint32) (swapped bool)
// CompareAndSwapUint64 executes the compare-and-swap operation for a uint64 value.
func CompareAndSwapUint64(val *uint64, old, new uint64) (swapped bool)
// CompareAndSwapUintptr executes the compare-and-swap operation for a uintptr value.
func CompareAndSwapUintptr(val *uintptr, old, new uintptr) (swapped bool)
// AddInt32 atomically adds delta to *val and returns the new value.
func AddInt32(val *int32, delta int32) (new int32)
// AddUint32 atomically adds delta to *val and returns the new value.
func AddUint32(val *uint32, delta uint32) (new uint32)
// AddInt64 atomically adds delta to *val and returns the new value.
func AddInt64(val *int64, delta int64) (new int64)
// AddUint64 atomically adds delta to *val and returns the new value.
func AddUint64(val *uint64, delta uint64) (new uint64)
// AddUintptr atomically adds delta to *val and returns the new value.
func AddUintptr(val *uintptr, delta uintptr) (new uintptr)
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment