--- /sys/src/ape/lib/ap/amd64/lock.c Thu Feb 28 18:46:30 2002 +++ /sys/src/ape/lib/ap/amd64/lock.c Wed Sep 18 22:50:12 2013 @@ -1,26 +1,36 @@ -#define _LOCK_EXTENSION +#include "../plan9/lib.h" #include "../plan9/sys9.h" +#define _LOCK_EXTENSION #include - -int tas(int*); +//#include void -lock(Lock *lk) +lock(Lock *l) { - while(tas(&lk->val)) - _SLEEP(0); + if(ainc(&l->key) == 1) + return; /* changed from 0 -> 1: we hold lock */ + /* otherwise wait in kernel */ + while(_SEMACQUIRE(&l->sem, 1) < 0){ + /* interrupted; try again */ + } } -int -canlock(Lock *lk) +void +unlock(Lock *l) { - if(tas(&lk->val)) - return 0; - return 1; + if(adec(&l->key) == 0) + return; /* changed from 1 -> 0: no contention */ + _SEMRELEASE(&l->sem, 1); } -void -unlock(Lock *lk) +int +canlock(Lock *l) { - lk->val = 0; + if(ainc(&l->key) == 1) + return 1; /* changed from 0 -> 1: success */ + /* Undo increment (but don't miss wakeup) */ + if(adec(&l->key) == 0) + return 0; /* changed from 1 -> 0: no contention */ + _SEMRELEASE(&l->sem, 1); + return 0; } --- /sys/src/ape/lib/ap/amd64/mkfile +++ /sys/src/ape/lib/ap/amd64/mkfile @@ -3,6 +3,7 @@ <$APE/config LIB=/$objtype/lib/ape/libap.a OFILES=\ + atom.$O\ _seek.$O\ cycles.$O\ lock.$O\ --- /sys/src/ape/lib/ap/amd64/atom.s +++ /sys/src/ape/lib/ap/amd64/atom.s @@ -0,0 +1,66 @@ +TEXT ainc(SB), 1, $0 /* long ainc(long *); */ +ainclp: + MOVL (RARG), AX /* exp */ + MOVL AX, BX + INCL BX /* new */ + LOCK; CMPXCHGL BX, (RARG) + JNZ ainclp + MOVL BX, AX + RET + +TEXT adec(SB), 1, $0 /* long adec(long*); */ +adeclp: + MOVL (RARG), AX + MOVL AX, BX + DECL BX + LOCK; CMPXCHGL BX, (RARG) + JNZ adeclp + MOVL BX, AX + RET + +/* + * int cas32(u32int *p, u32int ov, u32int nv); + * int cas(uint *p, int ov, int nv); + * int casul(ulong *p, ulong ov, ulong nv); + */ + +TEXT cas32(SB), 1, $0 +TEXT cas(SB), 1, $0 +TEXT casul(SB), 1, $0 +TEXT casl(SB), 1, $0 /* back compat */ + MOVL exp+8(FP), AX + MOVL new+16(FP), BX + LOCK; CMPXCHGL BX, (RARG) + MOVL $1, AX /* use CMOVLEQ etc. here? */ + JNZ _cas32r0 +_cas32r1: + RET +_cas32r0: + DECL AX + RET + +/* + * int cas64(u64int *p, u64int ov, u64int nv); + * int casp(void **p, void *ov, void *nv); + */ + +TEXT cas64(SB), 1, $0 +TEXT casp(SB), 1, $0 + MOVQ exp+8(FP), AX + MOVQ new+16(FP), BX + LOCK; CMPXCHGQ BX, (RARG) + MOVL $1, AX /* use CMOVLEQ etc. here? */ + JNZ _cas64r0 +_cas64r1: + RET +_cas64r0: + DECL AX + RET + +/* + * void mfence(void); + */ +TEXT mfence(SB),0,$0 + MFENCE + RET +