ref: 3d05e77ca1f743e5b4091c6bfe311460175ed9ae
parent: 041e4852d258f05fe5f60964a76c99714905774e
author: cinap_lenrek <[email protected]>
date: Sat Sep 21 15:53:27 EDT 2013
libc: change tas/sleep locks to cas/semacquire/semrelease locks (from sources) spinlocks have been changed to use the new semacquire/semrelease syscalls in combination with atomic compare and swap operations.
--- a/sys/include/libc.h
+++ b/sys/include/libc.h
@@ -410,11 +410,18 @@
extern void prof(void (*fn)(void*), void *arg, int entries, int what);
/*
+ * atomic
+ */
+extern long ainc(long*);
+extern long adec(long*);
+
+/*
* synchronization
*/
typedef
struct Lock {
- int val;
+ long key;
+ long sem;
} Lock;
extern int _tas(int*);
@@ -700,9 +707,6 @@
extern char* sysname(void);
extern void werrstr(char*, ...);
#pragma varargck argpos werrstr 1
-
-extern long ainc(long*);
-extern long adec(long*);
extern char *argv0;
#define ARGBEGIN for((argv0||(argv0=*argv)),argv++,argc--;\
--- a/sys/src/libc/68000/cycles.c
+++ /dev/null
@@ -1,7 +1,0 @@
-#include <u.h>
-#include <libc.h>
-
-void cycles(uvlong*u)
-{
- *u = 0LL;
-}
--- a/sys/src/libc/68000/mkfile
+++ b/sys/src/libc/68000/mkfile
@@ -24,7 +24,6 @@
strlen.s\
CFILES=\
- cycles.c\
notejmp.c\
vlrt.c\
--- /dev/null
+++ b/sys/src/libc/68020/lock.c
@@ -1,0 +1,41 @@
+#include <u.h>
+#include <libc.h>
+
+void
+lock(Lock *lk)
+{
+ int i;
+
+ /* once fast */
+ if(!_tas((int*)&lk->key))
+ return;
+ /* a thousand times pretty fast */
+ for(i=0; i<1000; i++){
+ if(!_tas((int*)&lk->key))
+ return;
+ sleep(0);
+ }
+ /* now nice and slow */
+ for(i=0; i<1000; i++){
+ if(!_tas((int*)&lk->key))
+ return;
+ sleep(100);
+ }
+ /* take your time */
+ while(_tas((int*)&lk->key))
+ sleep(1000);
+}
+
+int
+canlock(Lock *lk)
+{
+ if(_tas((int*)&lk->key))
+ return 0;
+ return 1;
+}
+
+void
+unlock(Lock *lk)
+{
+ lk->key = 0;
+}
--- a/sys/src/libc/68020/mkfile
+++ b/sys/src/libc/68020/mkfile
@@ -26,7 +26,7 @@
vlop.s\
CFILES=\
- cycles.c\
+ lock.c\
notejmp.c\
vlrt.c\
--- a/sys/src/libc/alpha/cycles.c
+++ /dev/null
@@ -1,7 +1,0 @@
-#include <u.h>
-#include <libc.h>
-
-void cycles(uvlong*u)
-{
- *u = 0LL;
-}
--- /dev/null
+++ b/sys/src/libc/alpha/lock.c
@@ -1,0 +1,41 @@
+#include <u.h>
+#include <libc.h>
+
+void
+lock(Lock *lk)
+{
+ int i;
+
+ /* once fast */
+ if(!_tas((int*)&lk->key))
+ return;
+ /* a thousand times pretty fast */
+ for(i=0; i<1000; i++){
+ if(!_tas((int*)&lk->key))
+ return;
+ sleep(0);
+ }
+ /* now nice and slow */
+ for(i=0; i<1000; i++){
+ if(!_tas((int*)&lk->key))
+ return;
+ sleep(100);
+ }
+ /* take your time */
+ while(_tas((int*)&lk->key))
+ sleep(1000);
+}
+
+int
+canlock(Lock *lk)
+{
+ if(_tas((int*)&lk->key))
+ return 0;
+ return 1;
+}
+
+void
+unlock(Lock *lk)
+{
+ lk->key = 0;
+}
--- a/sys/src/libc/alpha/mkfile
+++ b/sys/src/libc/alpha/mkfile
@@ -18,7 +18,7 @@
CFILES=\
_seek.c\
- cycles.c\
+ lock.c\
notejmp.c\
HFILES=/sys/include/libc.h
--- a/sys/src/libc/arm/cycles.c
+++ /dev/null
@@ -1,10 +1,0 @@
-#include <u.h>
-#include <libc.h>
-
-#pragma profile off
-
-void
-cycles(uvlong*u)
-{
- *u = 0LL;
-}
--- a/sys/src/libc/arm/mkfile
+++ b/sys/src/libc/arm/mkfile
@@ -20,7 +20,6 @@
vlop.s\
CFILES=\
- cycles.c\
notejmp.c\
vlrt.c\
--- a/sys/src/libc/mips/atom.s
+++ b/sys/src/libc/mips/atom.s
@@ -12,7 +12,8 @@
loop: MOVW $1, R3
LL(2, 1)
NOOP
- ADD R1,R3,R3
+ ADDU R1, R3
+ MOVW R3, R1 /* return new value */
SC(2, 3)
NOOP
BEQ R3,loop
@@ -24,8 +25,8 @@
loop1: MOVW $-1, R3
LL(2, 1)
NOOP
- ADD R1,R3,R3
- MOVW R3, R1
+ ADDU R1, R3
+ MOVW R3, R1 /* return new value */
SC(2, 3)
NOOP
BEQ R3,loop1
@@ -48,10 +49,4 @@
RET
fail:
MOVW $0, R1
- RET
-
-/* general-purpose abort */
-_trap:
- MOVD $0, R0
- MOVD 0(R0), R0
RET
--- a/sys/src/libc/mips/lock.c
+++ /dev/null
@@ -1,171 +1,0 @@
-#include <u.h>
-#include <libc.h>
-
-enum
-{
- Pagesize = 4096,
- Semperpg = Pagesize/(16*sizeof(uint)),
- Lockaddr = 0x60000000,
-
- POWER = 0x320,
- MAGNUM = 0x330,
- MAGNUMII = 0x340,
- R4K = 0x500,
-};
-
-static int arch;
-extern int C_3ktas(int*);
-extern int C_4ktas(int*);
-extern int C_fcr0(void);
-
-static void
-lockinit(void)
-{
- void *v;
-
- if(arch != 0)
- return; /* allow multiple calls */
- arch = C_fcr0();
- switch(arch) {
- case POWER:
- v = (void*)Lockaddr;
- if(segattach(SG_CEXEC, "lock", v, Pagesize) == (void*)-1) {
- arch = MAGNUM;
- break;
- }
- memset(v, 0, Pagesize);
- break;
- case MAGNUM:
- case MAGNUMII:
- case R4K:
- break;
- default:
- arch = R4K;
- break;
- }
-}
-
-void
-lock(Lock *lk)
-{
- int *hwsem;
- int hash;
-
-retry:
- switch(arch) {
- case 0:
- lockinit();
- goto retry;
- case MAGNUM:
- case MAGNUMII:
- while(C_3ktas(&lk->val))
- sleep(0);
- return;
- case R4K:
- for(;;){
- while(lk->val)
- ;
- if(C_4ktas(&lk->val) == 0)
- return;
- }
- break;
- case POWER:
- /* Use low order lock bits to generate hash */
- hash = ((int)lk/sizeof(int)) & (Semperpg-1);
- hwsem = (int*)Lockaddr+hash;
-
- for(;;) {
- if((*hwsem & 1) == 0) {
- if(lk->val)
- *hwsem = 0;
- else {
- lk->val = 1;
- *hwsem = 0;
- return;
- }
- }
- while(lk->val)
- ;
- }
- }
-}
-
-int
-canlock(Lock *lk)
-{
- int *hwsem;
- int hash;
-
-retry:
- switch(arch) {
- case 0:
- lockinit();
- goto retry;
- case MAGNUM:
- case MAGNUMII:
- if(C_3ktas(&lk->val))
- return 0;
- return 1;
- case R4K:
- if(C_4ktas(&lk->val))
- return 0;
- return 1;
- case POWER:
- /* Use low order lock bits to generate hash */
- hash = ((int)lk/sizeof(int)) & (Semperpg-1);
- hwsem = (int*)Lockaddr+hash;
-
- if((*hwsem & 1) == 0) {
- if(lk->val)
- *hwsem = 0;
- else {
- lk->val = 1;
- *hwsem = 0;
- return 1;
- }
- }
- break;
- }
- return 0;
-}
-
-void
-unlock(Lock *lk)
-{
- lk->val = 0;
-}
-
-int
-_tas(int *p)
-{
- int *hwsem;
- int hash;
-
-retry:
- switch(arch) {
- case 0:
- lockinit();
- goto retry;
- case MAGNUM:
- case MAGNUMII:
- return C_3ktas(p);
- case R4K:
- return C_4ktas(p);
- case POWER:
- /* Use low order lock bits to generate hash */
- hash = ((int)p/sizeof(int)) & (Semperpg-1);
- hwsem = (int*)Lockaddr+hash;
-
- if((*hwsem & 1) == 0) {
- if(*p)
- *hwsem = 0;
- else {
- *p = 1;
- *hwsem = 0;
- return 0;
- }
- }
- break;
- }
- return 1;
-}
--- a/sys/src/libc/mips/mkfile
+++ b/sys/src/libc/mips/mkfile
@@ -23,7 +23,6 @@
CFILES=\
cycles.c\
- lock.c\
notejmp.c\
sqrt.c\
vlrt.c\
--- a/sys/src/libc/mips/tas.s
+++ b/sys/src/libc/mips/tas.s
@@ -17,6 +17,7 @@
BLTZ R1, btas
RET
+ TEXT _tas(SB),$0
TEXT C_4ktas(SB), $0
MOVW R1, R2 /* address of key */
tas1:
--- a/sys/src/libc/mkfile
+++ b/sys/src/libc/mkfile
@@ -37,7 +37,7 @@
cd $i
mk $MKFLAGS update
}
- update $UPDATEFLAGS /386/lib/libc.a
+ update $UPDATEFLAGS /$objtype/lib/libc.a
installall:V:
for(objtype in $CPUS) mk $MKFLAGS install
--- /dev/null
+++ b/sys/src/libc/port/cycles.c
@@ -1,0 +1,7 @@
+#include <u.h>
+#include <libc.h>
+
+void cycles(uvlong*u)
+{
+ *u = 0LL;
+}
--- a/sys/src/libc/port/lock.c
+++ b/sys/src/libc/port/lock.c
@@ -2,40 +2,32 @@
#include <libc.h>
void
-lock(Lock *lk)
+lock(Lock *l)
{
- int i;
-
- /* once fast */
- if(!_tas(&lk->val))
- return;
- /* a thousand times pretty fast */
- for(i=0; i<1000; i++){
- if(!_tas(&lk->val))
- return;
- 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 */
}
- /* now nice and slow */
- for(i=0; i<1000; i++){
- if(!_tas(&lk->val))
- return;
- sleep(100);
- }
- /* take your time */
- while(_tas(&lk->val))
- sleep(1000);
}
-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;
}
--- a/sys/src/libc/port/malloc.acid
+++ b/sys/src/libc/port/malloc.acid
@@ -122,16 +122,18 @@
Profkernel = 2;
Proftime = 3;
Profsample = 4;
-sizeofLock = 4;
+sizeofLock = 8;
aggr Lock
{
- 'D' 0 val;
+ 'D' 0 key;
+ 'D' 4 sem;
};
defn
Lock(addr) {
complex Lock addr;
- print(" val ", addr.val, "\n");
+ print(" key ", addr.key, "\n");
+ print(" sem ", addr.sem, "\n");
};
sizeofQLp = 12;
@@ -150,13 +152,13 @@
print(" state ", addr.state, "\n");
};
-sizeofQLock = 16;
+sizeofQLock = 20;
aggr QLock
{
Lock 0 lock;
- 'D' 4 locked;
- 'A' QLp 8 $head;
- 'A' QLp 12 $tail;
+ 'D' 8 locked;
+ 'A' QLp 12 $head;
+ 'A' QLp 16 $tail;
};
defn
@@ -170,14 +172,14 @@
print(" $tail ", addr.$tail\X, "\n");
};
-sizeofRWLock = 20;
+sizeofRWLock = 24;
aggr RWLock
{
Lock 0 lock;
- 'D' 4 readers;
- 'D' 8 writer;
- 'A' QLp 12 $head;
- 'A' QLp 16 $tail;
+ 'D' 8 readers;
+ 'D' 12 writer;
+ 'A' QLp 16 $head;
+ 'A' QLp 20 $tail;
};
defn
@@ -438,12 +440,12 @@
};
complex Tos _tos;
-sizeofPrivate = 12;
+sizeofPrivate = 16;
aggr Private
{
Lock 0 lk;
- 'D' 4 pid;
- 'D' 8 printfd;
+ 'D' 8 pid;
+ 'D' 12 printfd;
};
defn
--- a/sys/src/libc/port/mkfile
+++ b/sys/src/libc/port/mkfile
@@ -19,6 +19,7 @@
cleanname.c\
crypt.c\
ctype.c\
+ cycles.c\
encodefmt.c\
execl.c\
exp.c\
--- a/sys/src/libc/port/pool.acid
+++ b/sys/src/libc/port/pool.acid
@@ -122,16 +122,18 @@
Profkernel = 2;
Proftime = 3;
Profsample = 4;
-sizeofLock = 4;
+sizeofLock = 8;
aggr Lock
{
- 'D' 0 val;
+ 'D' 0 key;
+ 'D' 4 sem;
};
defn
Lock(addr) {
complex Lock addr;
- print(" val ", addr.val, "\n");
+ print(" key ", addr.key, "\n");
+ print(" sem ", addr.sem, "\n");
};
sizeofQLp = 12;
@@ -150,13 +152,13 @@
print(" state ", addr.state, "\n");
};
-sizeofQLock = 16;
+sizeofQLock = 20;
aggr QLock
{
Lock 0 lock;
- 'D' 4 locked;
- 'A' QLp 8 $head;
- 'A' QLp 12 $tail;
+ 'D' 8 locked;
+ 'A' QLp 12 $head;
+ 'A' QLp 16 $tail;
};
defn
@@ -170,14 +172,14 @@
print(" $tail ", addr.$tail\X, "\n");
};
-sizeofRWLock = 20;
+sizeofRWLock = 24;
aggr RWLock
{
Lock 0 lock;
- 'D' 4 readers;
- 'D' 8 writer;
- 'A' QLp 12 $head;
- 'A' QLp 16 $tail;
+ 'D' 8 readers;
+ 'D' 12 writer;
+ 'A' QLp 16 $head;
+ 'A' QLp 20 $tail;
};
defn
@@ -504,34 +506,20 @@
complex Free checklist:t;
complex Free checklist:q;
complex Free checktree:t;
-complex Free ltreewalk:t;
-complex Free ltreewalk:f;
-complex Free treeinsert:tree;
-complex Free treeinsert:node;
-complex Free treeinsert:loc;
-complex Free treeinsert:repl;
-complex Free treedelete:tree;
-complex Free treedelete:node;
-complex Free treedelete:loc;
-complex Free treedelete:lsucc;
-complex Free treedelete:succ;
complex Free treelookupgt:t;
complex Free treelookupgt:lastgood;
-complex Free listadd:list;
-complex Free listadd:node;
-complex Free listdelete:list;
-complex Free listdelete:node;
+complex Free treesplay:t;
+complex Free treesplay:N;
+complex Free treesplay:l;
+complex Free treesplay:r;
+complex Free treesplay:y;
complex Pool pooladd:p;
complex Alloc pooladd:anode;
-complex Free pooladd:lst;
-complex Free pooladd:olst;
complex Free pooladd:node;
-complex Free pooladd:parent;
+complex Free pooladd:root;
complex Pool pooldel:p;
complex Free pooldel:node;
-complex Free pooldel:lst;
-complex Free pooldel:olst;
-complex Free pooldel:parent;
+complex Free pooldel:root;
complex Pool dsize2bsize:p;
complex Pool bsize2asize:p;
complex Pool blockmerge:pool;
--- /dev/null
+++ b/sys/src/libc/sparc/lock.c
@@ -1,0 +1,41 @@
+#include <u.h>
+#include <libc.h>
+
+void
+lock(Lock *lk)
+{
+ int i;
+
+ /* once fast */
+ if(!_tas((int*)&lk->key))
+ return;
+ /* a thousand times pretty fast */
+ for(i=0; i<1000; i++){
+ if(!_tas((int*)&lk->key))
+ return;
+ sleep(0);
+ }
+ /* now nice and slow */
+ for(i=0; i<1000; i++){
+ if(!_tas((int*)&lk->key))
+ return;
+ sleep(100);
+ }
+ /* take your time */
+ while(_tas((int*)&lk->key))
+ sleep(1000);
+}
+
+int
+canlock(Lock *lk)
+{
+ if(_tas((int*)&lk->key))
+ return 0;
+ return 1;
+}
+
+void
+unlock(Lock *lk)
+{
+ lk->key = 0;
+}
--- a/sys/src/libc/sparc/mkfile
+++ b/sys/src/libc/sparc/mkfile
@@ -22,7 +22,7 @@
vlop.s
CFILES=\
- cycles.c\
+ lock.c\
notejmp.c\
sqrt.c\
vlrt.c\