TEXT ainc(SB), 1, $-4 /* int ainc(int*); */ MOVL arg+0(FP), BX MOVL $1, AX LOCK; BYTE $0x0f; BYTE $0xc1; BYTE $0x03/* XADDL AX, (BX) */ ADDL $1, AX /* overflow if -ve or 0 */ RET TEXT adec(SB), 1, $-4 /* int adec(int*); */ MOVL arg+0(FP), BX MOVL $-1, AX LOCK; BYTE $0x0f; BYTE $0xc1; BYTE $0x03/* XADDL AX, (BX) */ SUBL $1, AX /* underflow if -ve */ RET /* * int cas32(u32int *p, u32int ov, u32int nv); * int cas(uint *p, int ov, int nv); * int casp(void **p, void *ov, void *nv); * int casl(ulong *p, ulong ov, ulong nv); */ /* * CMPXCHG (CX), DX: 0000 1111 1011 000w oorr rmmm, * mmm = CX = 001; rrr = DX = 010 */ #define CMPXCHG BYTE $0x0F; BYTE $0xB1; BYTE $0x11 TEXT cas32+0(SB),0,$0 TEXT cas+0(SB),0,$0 TEXT casp+0(SB),0,$0 TEXT casl+0(SB),0,$0 MOVL p+0(FP), CX MOVL ov+4(FP), AX MOVL nv+8(FP), DX LOCK CMPXCHG JNE fail MOVL $1,AX RET fail: MOVL $0,AX RET /* * int cas64(u64int *p, u64int ov, u64int nv); */ /* * CMPXCHG64 (DI): 0000 1111 1100 0111 0000 1110, */ #define CMPXCHG64 BYTE $0x0F; BYTE $0xC7; BYTE $0x0F TEXT cas64+0(SB),0,$0 MOVL p+0(FP), DI MOVL ov+0x4(FP), AX MOVL ov+0x8(FP), DX MOVL nv+0xc(FP), BX MOVL nv+0x10(FP), CX LOCK CMPXCHG64 JNE fail MOVL $1,AX RET /* * Versions of compare-and-swap that return the old value * (i.e., the value of *p at the time of the operation * xcas(p, o, n) == o * yields the same value as * cas(p, o, n) * xcas can be used in constructs like * for(o = *p; (oo = xcas(p, o, o+1)) != o; o = oo) * ; * to avoid the extra dereference of *p (the example is a silly * way to increment *p atomically) * * u32int xcas32(u32int *p, u32int ov, u32int nv); * u64int xcas64(u64int *p, u64int ov, u64int nv); * int xcas(int *p, int ov, int nv); * void* xcasp(void **p, void *ov, void *nv); * ulong xcasl(ulong *p, ulong ov, ulong nv); */ TEXT xcas32+0(SB),0,$0 TEXT xcas+0(SB),0,$0 TEXT xcasp+0(SB),0,$0 TEXT xcasl+0(SB),0,$0 MOVL p+0(FP), CX MOVL ov+4(FP), AX /* accumulator */ MOVL nv+8(FP), DX LOCK CMPXCHG RET /* * The CMPXCHG8B instruction also requires three operands: * a 64-bit value in EDX:EAX, a 64-bit value in ECX:EBX, * and a destination operand in memory. The instruction compar * es the 64-bit value in the EDX:EAX registers with the * destination operand. If they are equal, the 64-bit value * in the ECX:EBX register is stored in the destination * operand. If the EDX:EAX register and the destination ar * e not equal, the destination is loaded in the EDX:EAX * register. The CMPXCHG8B instruction can be combined with * the LOCK prefix to perform the operation atomically */ TEXT xcas64+0(SB),0,$0 MOVL p+4(FP), DI MOVL ov+0x8(FP), AX MOVL ov+0xc(FP), DX MOVL nv+0x10(FP), BX MOVL nv+0x14(FP), CX LOCK CMPXCHG64 MOVL .ret+0x0(FP),CX /* pointer to return value */ MOVL AX,0x0(CX) MOVL DX,0x4(CX) RET