Explorar el Código

sys/src/ape/lib/ap: synchronize amd64 lock implementation with current Plan 9 code

David du Colombier hace 3 años
padre
commit
0c5edebd3f
Se han modificado 3 ficheros con 91 adiciones y 14 borrados
  1. 66 0
      sys/src/ape/lib/ap/amd64/atom.s
  2. 24 14
      sys/src/ape/lib/ap/amd64/lock.c
  3. 1 0
      sys/src/ape/lib/ap/amd64/mkfile

+ 66 - 0
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
+

+ 24 - 14
sys/src/ape/lib/ap/amd64/lock.c

@@ -1,26 +1,36 @@
-#define _LOCK_EXTENSION
+#include "../plan9/lib.h"
 #include "../plan9/sys9.h"
+#define _LOCK_EXTENSION
 #include <lock.h>
-
-int	tas(int*);
+//#include <lib9.h>
 
 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;
 }

+ 1 - 0
sys/src/ape/lib/ap/amd64/mkfile

@@ -3,6 +3,7 @@ objtype=amd64
 <$APE/config
 LIB=/$objtype/lib/ape/libap.a
 OFILES=\
+	atom.$O\
 	_seek.$O\
 	cycles.$O\
 	lock.$O\