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.
This commit is contained in:
cinap_lenrek 2013-09-21 19:53:27 +02:00
parent 041e4852d2
commit 3d05e77ca1
21 changed files with 201 additions and 286 deletions

View file

@ -409,12 +409,19 @@ enum {
}; /* what */
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*);
@ -701,9 +708,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--;\
argv[0] && argv[0][0]=='-' && argv[0][1];\

View file

@ -24,7 +24,6 @@ SFILES=\
strlen.s\
CFILES=\
cycles.c\
notejmp.c\
vlrt.c\

41
sys/src/libc/68020/lock.c Normal file
View file

@ -0,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;
}

View file

@ -26,7 +26,7 @@ SFILES=\
vlop.s\
CFILES=\
cycles.c\
lock.c\
notejmp.c\
vlrt.c\

View file

@ -1,7 +0,0 @@
#include <u.h>
#include <libc.h>
void cycles(uvlong*u)
{
*u = 0LL;
}

41
sys/src/libc/alpha/lock.c Normal file
View file

@ -0,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;
}

View file

@ -18,7 +18,7 @@ SFILES=\
CFILES=\
_seek.c\
cycles.c\
lock.c\
notejmp.c\
HFILES=/sys/include/libc.h

View file

@ -1,10 +0,0 @@
#include <u.h>
#include <libc.h>
#pragma profile off
void
cycles(uvlong*u)
{
*u = 0LL;
}

View file

@ -20,7 +20,6 @@ SFILES=\
vlop.s\
CFILES=\
cycles.c\
notejmp.c\
vlrt.c\

View file

@ -12,7 +12,8 @@ TEXT _xinc(SB), 1, $-4 /* void _xinc(long *); */
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 @@ TEXT _xdec(SB), 1, $-4 /* long _xdec(long *); */
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
@ -49,9 +50,3 @@ spincas:
fail:
MOVW $0, R1
RET
/* general-purpose abort */
_trap:
MOVD $0, R0
MOVD 0(R0), R0
RET

View file

@ -1,171 +0,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;
}

View file

@ -23,7 +23,6 @@ SFILES=\
CFILES=\
cycles.c\
lock.c\
notejmp.c\
sqrt.c\
vlrt.c\

View file

@ -17,6 +17,7 @@ btas:
BLTZ R1, btas
RET
TEXT _tas(SB),$0
TEXT C_4ktas(SB), $0
MOVW R1, R2 /* address of key */
tas1:

View file

@ -37,7 +37,7 @@ update:V:
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

View file

@ -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)
{
if(_tas(&lk->val))
return 0;
return 1;
}
void
unlock(Lock *lk)
unlock(Lock *l)
{
lk->val = 0;
if(adec(&l->key) == 0)
return; /* changed from 1 -> 0: no contention */
semrelease(&l->sem, 1);
}
int
canlock(Lock *l)
{
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;
}

View file

@ -122,16 +122,18 @@ Profuser = 1;
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 @@ QLp(addr) {
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 @@ QLock(addr) {
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 @@ Tos(addr) {
};
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

View file

@ -19,6 +19,7 @@ CFILES=\
cleanname.c\
crypt.c\
ctype.c\
cycles.c\
encodefmt.c\
execl.c\
exp.c\

View file

@ -122,16 +122,18 @@ Profuser = 1;
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 @@ QLp(addr) {
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 @@ QLock(addr) {
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 @@ MINBLOCKSIZE = 32;
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;

41
sys/src/libc/sparc/lock.c Normal file
View file

@ -0,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;
}

View file

@ -22,7 +22,7 @@ SFILES=\
vlop.s
CFILES=\
cycles.c\
lock.c\
notejmp.c\
sqrt.c\
vlrt.c\