diff --git a/sys/include/ape/lock.h b/sys/include/ape/lock.h index f2fd9a453..2f36f3b4f 100644 --- a/sys/include/ape/lock.h +++ b/sys/include/ape/lock.h @@ -10,8 +10,7 @@ typedef struct { - long key; - long sem; + int val; } Lock; #ifdef __cplusplus diff --git a/sys/include/libc.h b/sys/include/libc.h index c84acc0f5..a92e5680d 100644 --- a/sys/include/libc.h +++ b/sys/include/libc.h @@ -409,19 +409,12 @@ 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 { - long key; - long sem; + int val; } Lock; extern int _tas(int*); @@ -708,6 +701,9 @@ 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];\ diff --git a/sys/src/ape/lib/ap/386/atom.s b/sys/src/ape/lib/ap/386/atom.s deleted file mode 100755 index 5f51daf81..000000000 --- a/sys/src/ape/lib/ap/386/atom.s +++ /dev/null @@ -1,121 +0,0 @@ -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 diff --git a/sys/src/ape/lib/ap/386/lock.c b/sys/src/ape/lib/ap/386/lock.c index 65a65df7b..91c0ba233 100644 --- a/sys/src/ape/lib/ap/386/lock.c +++ b/sys/src/ape/lib/ap/386/lock.c @@ -1,35 +1,26 @@ -#include "../plan9/lib.h" -#include "../plan9/sys9.h" #define _LOCK_EXTENSION +#include "../plan9/sys9.h" #include -void -lock(Lock *l) -{ - 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 tas(int*); void -unlock(Lock *l) +lock(Lock *lk) { - if(adec(&l->key) == 0) - return; /* changed from 1 -> 0: no contention */ - _SEMRELEASE(&l->sem, 1); + while(tas(&lk->val)) + _SLEEP(0); } int -canlock(Lock *l) +canlock(Lock *lk) { - 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; + if(tas(&lk->val)) + return 0; + return 1; +} + +void +unlock(Lock *lk) +{ + lk->val = 0; } diff --git a/sys/src/ape/lib/ap/386/mkfile b/sys/src/ape/lib/ap/386/mkfile index 680c7b4e4..e19a4b852 100644 --- a/sys/src/ape/lib/ap/386/mkfile +++ b/sys/src/ape/lib/ap/386/mkfile @@ -2,7 +2,6 @@ APE=/sys/src/ape <$APE/config LIB=/$objtype/lib/ape/libap.a OFILES=\ - atom.$O\ cycles.$O\ lock.$O\ main9.$O\ diff --git a/sys/src/ape/lib/ap/68020/lock.c b/sys/src/ape/lib/ap/68020/lock.c index 5b1d72c46..91c0ba233 100644 --- a/sys/src/ape/lib/ap/68020/lock.c +++ b/sys/src/ape/lib/ap/68020/lock.c @@ -2,17 +2,19 @@ #include "../plan9/sys9.h" #include +int tas(int*); + void lock(Lock *lk) { - while(tas((int*)&lk->key)) + while(tas(&lk->val)) _SLEEP(0); } int canlock(Lock *lk) { - if(tas((int*)&lk->key)) + if(tas(&lk->val)) return 0; return 1; } @@ -20,5 +22,5 @@ canlock(Lock *lk) void unlock(Lock *lk) { - lk->key = 0; + lk->val = 0; } diff --git a/sys/src/ape/lib/ap/alpha/lock.c b/sys/src/ape/lib/ap/alpha/lock.c index 5b1d72c46..91c0ba233 100644 --- a/sys/src/ape/lib/ap/alpha/lock.c +++ b/sys/src/ape/lib/ap/alpha/lock.c @@ -2,17 +2,19 @@ #include "../plan9/sys9.h" #include +int tas(int*); + void lock(Lock *lk) { - while(tas((int*)&lk->key)) + while(tas(&lk->val)) _SLEEP(0); } int canlock(Lock *lk) { - if(tas((int*)&lk->key)) + if(tas(&lk->val)) return 0; return 1; } @@ -20,5 +22,5 @@ canlock(Lock *lk) void unlock(Lock *lk) { - lk->key = 0; + lk->val = 0; } diff --git a/sys/src/ape/lib/ap/arm/atom.s b/sys/src/ape/lib/ap/arm/atom.s deleted file mode 100644 index b59a89d90..000000000 --- a/sys/src/ape/lib/ap/arm/atom.s +++ /dev/null @@ -1,58 +0,0 @@ -#define CLREX WORD $0xf57ff01f -#define LDREX(a,r) WORD $(0xe<<28|0x01900f9f | (a)<<16 | (r)<<12) -/* `The order of operands is from left to right in dataflow order' - asm man */ -#define STREX(v,a,r) WORD $(0xe<<28|0x01800f90 | (a)<<16 | (r)<<12 | (v)<<0) - -/* - * int cas(ulong *p, ulong ov, ulong nv); - */ - -TEXT cas+0(SB),0,$0 /* r0 holds p */ -TEXT casp+0(SB),0,$0 /* r0 holds p */ - MOVW ov+4(FP), R1 - MOVW nv+8(FP), R2 -spincas: - LDREX(0,3) /* LDREX 0(R0),R3 */ - CMP.S R3, R1 - BNE fail - STREX(2,0,4) /* STREX 0(R0),R2,R4 */ - CMP.S $0, R4 - BNE spincas - MOVW $1, R0 - RET -fail: - CLREX - MOVW $0, R0 - RET - -TEXT _xinc(SB), $0 /* void _xinc(long *); */ -TEXT ainc(SB), $0 /* long ainc(long *); */ -spinainc: - LDREX(0,3) /* LDREX 0(R0),R3 */ - ADD $1,R3 - STREX(3,0,4) /* STREX 0(R0),R3,R4 */ - CMP.S $0, R4 - BNE spinainc - MOVW R3, R0 - RET - -TEXT _xdec(SB), $0 /* long _xdec(long *); */ -TEXT adec(SB), $0 /* long adec(long *); */ -spinadec: - LDREX(0,3) /* LDREX 0(R0),R3 */ - SUB $1,R3 - STREX(3,0,4) /* STREX 0(R0),R3,R4 */ - CMP.S $0, R4 - BNE spinadec - MOVW R3, R0 - RET - -TEXT loadlinked(SB), $0 /* long loadlinked(long *); */ - LDREX(0,0) /* LDREX 0(R0),R0 */ - RET - -TEXT storecond(SB), $0 /* int storecond(long *, long); */ - MOVW ov+4(FP), R3 - STREX(3,0,0) /* STREX 0(R0),R3,R0 */ - RSB $1, R0 - RET diff --git a/sys/src/ape/lib/ap/arm/lock.c b/sys/src/ape/lib/ap/arm/lock.c index 65a65df7b..91c0ba233 100644 --- a/sys/src/ape/lib/ap/arm/lock.c +++ b/sys/src/ape/lib/ap/arm/lock.c @@ -1,35 +1,26 @@ -#include "../plan9/lib.h" -#include "../plan9/sys9.h" #define _LOCK_EXTENSION +#include "../plan9/sys9.h" #include -void -lock(Lock *l) -{ - 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 tas(int*); void -unlock(Lock *l) +lock(Lock *lk) { - if(adec(&l->key) == 0) - return; /* changed from 1 -> 0: no contention */ - _SEMRELEASE(&l->sem, 1); + while(tas(&lk->val)) + _SLEEP(0); } int -canlock(Lock *l) +canlock(Lock *lk) { - 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; + if(tas(&lk->val)) + return 0; + return 1; +} + +void +unlock(Lock *lk) +{ + lk->val = 0; } diff --git a/sys/src/ape/lib/ap/arm/mkfile b/sys/src/ape/lib/ap/arm/mkfile index 97d0fa80b..f65e34395 100644 --- a/sys/src/ape/lib/ap/arm/mkfile +++ b/sys/src/ape/lib/ap/arm/mkfile @@ -2,7 +2,6 @@ APE=/sys/src/ape <$APE/config LIB=/$objtype/lib/ape/libap.a OFILES=\ - atom.$O\ cycles.$O\ div.$O\ getfcr.$O\ diff --git a/sys/src/ape/lib/ap/mips/atom.s b/sys/src/ape/lib/ap/mips/atom.s deleted file mode 100644 index b907f7f59..000000000 --- a/sys/src/ape/lib/ap/mips/atom.s +++ /dev/null @@ -1,52 +0,0 @@ -/* - * R4000 user-level atomic operations - */ - -#define LL(base, rt) WORD $((060<<26)|((base)<<21)|((rt)<<16)) -#define SC(base, rt) WORD $((070<<26)|((base)<<21)|((rt)<<16)) -#define NOOP WORD $0x27 - -TEXT ainc(SB), 1, $-4 /* long ainc(long *); */ -TEXT _xinc(SB), 1, $-4 /* void _xinc(long *); */ - MOVW R1, R2 /* address of counter */ -loop: MOVW $1, R3 - LL(2, 1) - NOOP - ADDU R1, R3 - MOVW R3, R1 /* return new value */ - SC(2, 3) - NOOP - BEQ R3,loop - RET - -TEXT adec(SB), 1, $-4 /* long adec(long*); */ -TEXT _xdec(SB), 1, $-4 /* long _xdec(long *); */ - MOVW R1, R2 /* address of counter */ -loop1: MOVW $-1, R3 - LL(2, 1) - NOOP - ADDU R1, R3 - MOVW R3, R1 /* return new value */ - SC(2, 3) - NOOP - BEQ R3,loop1 - RET - -/* - * int cas(uint* p, int ov, int nv); - */ -TEXT cas(SB), 1, $-4 - MOVW ov+4(FP), R2 - MOVW nv+8(FP), R3 -spincas: - LL(1, 4) /* R4 = *R1 */ - NOOP - BNE R2, R4, fail - SC(1, 3) /* *R1 = R3 */ - NOOP - BEQ R3, spincas /* R3 == 0 means store failed */ - MOVW $1, R1 - RET -fail: - MOVW $0, R1 - RET diff --git a/sys/src/ape/lib/ap/mips/lock.c b/sys/src/ape/lib/ap/mips/lock.c index 65a65df7b..866d074e9 100644 --- a/sys/src/ape/lib/ap/mips/lock.c +++ b/sys/src/ape/lib/ap/mips/lock.c @@ -1,35 +1,171 @@ -#include "../plan9/lib.h" -#include "../plan9/sys9.h" #define _LOCK_EXTENSION +#include +#include +#include "../plan9/sys9.h" #include -void -lock(Lock *l) +enum { - 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 */ + Pagesize = 4096, + Semperpg = Pagesize/(16*sizeof(unsigned int)), + 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) +{ + int n; + + if(arch != 0) + return; /* allow multiple calls */ + arch = C_fcr0(); + switch(arch) { + case POWER: + if(_SEGATTACH(0, "lock", (void*)Lockaddr, Pagesize) == (void*)-1) { + arch = MAGNUM; + break; + } + memset((void*)Lockaddr, 0, Pagesize); + break; + case MAGNUM: + case MAGNUMII: + case R4K: + break; + default: + abort(); } + } void -unlock(Lock *l) +lock(Lock *lk) { - if(adec(&l->key) == 0) - return; /* changed from 1 -> 0: no contention */ - _SEMRELEASE(&l->sem, 1); + 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 *l) +canlock(Lock *lk) { - 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; + 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; + } + } + 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; + } + } + return 1; + } } diff --git a/sys/src/ape/lib/ap/mips/mkfile b/sys/src/ape/lib/ap/mips/mkfile index 5d24b767f..0896229a6 100644 --- a/sys/src/ape/lib/ap/mips/mkfile +++ b/sys/src/ape/lib/ap/mips/mkfile @@ -2,7 +2,6 @@ APE=/sys/src/ape <$APE/config LIB=/$objtype/lib/ape/libap.a OFILES=\ - atom.$O\ cycles.$O\ getfcr.$O\ lock.$O\ diff --git a/sys/src/ape/lib/ap/mips/tas.s b/sys/src/ape/lib/ap/mips/tas.s index 448cbe068..d754b21f6 100644 --- a/sys/src/ape/lib/ap/mips/tas.s +++ b/sys/src/ape/lib/ap/mips/tas.s @@ -17,7 +17,6 @@ btas: BLTZ R1, btas RET - TEXT tas(SB),$0 TEXT C_4ktas(SB), $0 MOVW R1, R2 /* address of key */ tas1: diff --git a/sys/src/ape/lib/ap/plan9/sys9.h b/sys/src/ape/lib/ap/plan9/sys9.h index cb326e851..b9e5bbc04 100644 --- a/sys/src/ape/lib/ap/plan9/sys9.h +++ b/sys/src/ape/lib/ap/plan9/sys9.h @@ -106,11 +106,8 @@ extern int _SEGDETACH(void*); extern int _SEGFLUSH(void*, unsigned long); extern int _SEGFREE(void*, unsigned long); extern long long _SEEK(int, long long, int); -extern int _SEMACQUIRE(long*, int); -extern long _SEMRELEASE(long*, long); extern int _SLEEP(long); extern int _STAT(const char*, unsigned char*, int); -extern int _TSEMACQUIRE(long*, unsigned long); extern Waitmsg* _WAIT(void); extern long _WRITE(int, const void*, long); extern int _WSTAT(const char*, unsigned char*, int); @@ -122,9 +119,3 @@ extern int __creat(char *, int); extern int __link(char *, int); extern int __stat(char *, struct stat *); extern int __unlink(char *); - -/* - * atomic - */ -extern long ainc(long*); -extern long adec(long*); diff --git a/sys/src/ape/lib/ap/power/atom.s b/sys/src/ape/lib/ap/power/atom.s deleted file mode 100644 index b387300df..000000000 --- a/sys/src/ape/lib/ap/power/atom.s +++ /dev/null @@ -1,63 +0,0 @@ -TEXT _xinc(SB),$0 /* void _xinc(long *); */ -TEXT ainc(SB),$0 /* long ainc(long *); */ - MOVW R3, R4 -xincloop: - LWAR (R4), R3 - ADD $1, R3 - DCBT (R4) /* fix 405 errata cpu_210 */ - STWCCC R3, (R4) - BNE xincloop - RETURN - -TEXT _xdec(SB),$0 /* long _xdec(long *); */ -TEXT adec(SB),$0 /* long adec(long *); */ - MOVW R3, R4 -xdecloop: - LWAR (R4), R3 - ADD $-1, R3 - DCBT (R4) /* fix 405 errata cpu_210 */ - STWCCC R3, (R4) - BNE xdecloop - RETURN - -TEXT loadlink(SB), $0 - - LWAR (R3), R3 - RETURN - -TEXT storecond(SB), $0 - - MOVW val+4(FP), R4 - DCBT (R3) /* fix 405 errata cpu_210 */ - STWCCC R4, (R3) - BNE storecondfail - MOVW $1, R3 - RETURN -storecondfail: - MOVW $0, R3 - RETURN - -/* - * int cas(uint *p, int ov, int nv); - * int casp(void **p, void *ov, void *nv); - */ - -TEXT cas+0(SB),0,$0 -TEXT casp+0(SB),0,$0 - MOVW ov+4(FP),R4 - MOVW nv+8(FP),R8 - LWAR (R3),R5 - CMP R5,R4 - BNE fail - DCBT (R3) /* fix 405 errata cpu_210 */ - STWCCC R8,(R3) - BNE fail1 - MOVW $1,R3 - RETURN -fail: - DCBT (R3) /* fix 405 errata cpu_210 */ - STWCCC R5,(R3) /* give up exclusive access */ -fail1: - MOVW R0,R3 - RETURN - END diff --git a/sys/src/ape/lib/ap/power/lock.c b/sys/src/ape/lib/ap/power/lock.c index 65a65df7b..0d17c34d5 100644 --- a/sys/src/ape/lib/ap/power/lock.c +++ b/sys/src/ape/lib/ap/power/lock.c @@ -3,33 +3,43 @@ #define _LOCK_EXTENSION #include -void -lock(Lock *l) -{ - 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 tas(int*); void -unlock(Lock *l) +lock(Lock *lk) { - if(adec(&l->key) == 0) - return; /* changed from 1 -> 0: no contention */ - _SEMRELEASE(&l->sem, 1); + 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); + } + /* 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 *l) +canlock(Lock *lk) { - 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; + if(tas(&lk->val)) + return 0; + return 1; +} + +void +unlock(Lock *lk) +{ + lk->val = 0; } diff --git a/sys/src/ape/lib/ap/power/mkfile b/sys/src/ape/lib/ap/power/mkfile index ab4b35df6..cc546cd84 100644 --- a/sys/src/ape/lib/ap/power/mkfile +++ b/sys/src/ape/lib/ap/power/mkfile @@ -2,7 +2,6 @@ APE=/sys/src/ape <$APE/config LIB=/$objtype/lib/ape/libap.a OFILES=\ - atom.$O\ cycles.$O\ getfcr.$O\ lock.$O\ diff --git a/sys/src/ape/lib/ap/sparc/lock.c b/sys/src/ape/lib/ap/sparc/lock.c index 5b1d72c46..91c0ba233 100644 --- a/sys/src/ape/lib/ap/sparc/lock.c +++ b/sys/src/ape/lib/ap/sparc/lock.c @@ -2,17 +2,19 @@ #include "../plan9/sys9.h" #include +int tas(int*); + void lock(Lock *lk) { - while(tas((int*)&lk->key)) + while(tas(&lk->val)) _SLEEP(0); } int canlock(Lock *lk) { - if(tas((int*)&lk->key)) + if(tas(&lk->val)) return 0; return 1; } @@ -20,5 +22,5 @@ canlock(Lock *lk) void unlock(Lock *lk) { - lk->key = 0; + lk->val = 0; } diff --git a/sys/src/libc/port/cycles.c b/sys/src/libc/68000/cycles.c similarity index 100% rename from sys/src/libc/port/cycles.c rename to sys/src/libc/68000/cycles.c diff --git a/sys/src/libc/68000/mkfile b/sys/src/libc/68000/mkfile index cb049b6b0..573d49268 100644 --- a/sys/src/libc/68000/mkfile +++ b/sys/src/libc/68000/mkfile @@ -24,6 +24,7 @@ SFILES=\ strlen.s\ CFILES=\ + cycles.c\ notejmp.c\ vlrt.c\ diff --git a/sys/src/libc/68020/lock.c b/sys/src/libc/68020/lock.c deleted file mode 100644 index c0966fcac..000000000 --- a/sys/src/libc/68020/lock.c +++ /dev/null @@ -1,41 +0,0 @@ -#include -#include - -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; -} diff --git a/sys/src/libc/68020/mkfile b/sys/src/libc/68020/mkfile index d486d74f7..bdd359164 100644 --- a/sys/src/libc/68020/mkfile +++ b/sys/src/libc/68020/mkfile @@ -26,7 +26,7 @@ SFILES=\ vlop.s\ CFILES=\ - lock.c\ + cycles.c\ notejmp.c\ vlrt.c\ diff --git a/sys/src/libc/alpha/cycles.c b/sys/src/libc/alpha/cycles.c new file mode 100644 index 000000000..9bad3a989 --- /dev/null +++ b/sys/src/libc/alpha/cycles.c @@ -0,0 +1,7 @@ +#include +#include + +void cycles(uvlong*u) +{ + *u = 0LL; +} diff --git a/sys/src/libc/alpha/lock.c b/sys/src/libc/alpha/lock.c deleted file mode 100644 index c0966fcac..000000000 --- a/sys/src/libc/alpha/lock.c +++ /dev/null @@ -1,41 +0,0 @@ -#include -#include - -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; -} diff --git a/sys/src/libc/alpha/mkfile b/sys/src/libc/alpha/mkfile index 299a97c97..ef66ac423 100644 --- a/sys/src/libc/alpha/mkfile +++ b/sys/src/libc/alpha/mkfile @@ -18,7 +18,7 @@ SFILES=\ CFILES=\ _seek.c\ - lock.c\ + cycles.c\ notejmp.c\ HFILES=/sys/include/libc.h diff --git a/sys/src/libc/arm/cycles.c b/sys/src/libc/arm/cycles.c new file mode 100644 index 000000000..d03e827ce --- /dev/null +++ b/sys/src/libc/arm/cycles.c @@ -0,0 +1,10 @@ +#include +#include + +#pragma profile off + +void +cycles(uvlong*u) +{ + *u = 0LL; +} diff --git a/sys/src/libc/arm/mkfile b/sys/src/libc/arm/mkfile index 768bcdd46..14f81e1b8 100644 --- a/sys/src/libc/arm/mkfile +++ b/sys/src/libc/arm/mkfile @@ -20,6 +20,7 @@ SFILES=\ vlop.s\ CFILES=\ + cycles.c\ notejmp.c\ vlrt.c\ diff --git a/sys/src/libc/mips/atom.s b/sys/src/libc/mips/atom.s index b907f7f59..8975ac569 100644 --- a/sys/src/libc/mips/atom.s +++ b/sys/src/libc/mips/atom.s @@ -12,8 +12,7 @@ TEXT _xinc(SB), 1, $-4 /* void _xinc(long *); */ loop: MOVW $1, R3 LL(2, 1) NOOP - ADDU R1, R3 - MOVW R3, R1 /* return new value */ + ADD R1,R3,R3 SC(2, 3) NOOP BEQ R3,loop @@ -25,8 +24,8 @@ TEXT _xdec(SB), 1, $-4 /* long _xdec(long *); */ loop1: MOVW $-1, R3 LL(2, 1) NOOP - ADDU R1, R3 - MOVW R3, R1 /* return new value */ + ADD R1,R3,R3 + MOVW R3, R1 SC(2, 3) NOOP BEQ R3,loop1 @@ -50,3 +49,9 @@ spincas: fail: MOVW $0, R1 RET + +/* general-purpose abort */ +_trap: + MOVD $0, R0 + MOVD 0(R0), R0 + RET diff --git a/sys/src/libc/mips/lock.c b/sys/src/libc/mips/lock.c new file mode 100644 index 000000000..9c9bd2208 --- /dev/null +++ b/sys/src/libc/mips/lock.c @@ -0,0 +1,171 @@ +#include +#include + +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; +} diff --git a/sys/src/libc/mips/mkfile b/sys/src/libc/mips/mkfile index 460f7cd2f..3b902f6e3 100644 --- a/sys/src/libc/mips/mkfile +++ b/sys/src/libc/mips/mkfile @@ -23,6 +23,7 @@ SFILES=\ CFILES=\ cycles.c\ + lock.c\ notejmp.c\ sqrt.c\ vlrt.c\ diff --git a/sys/src/libc/mips/tas.s b/sys/src/libc/mips/tas.s index a9bf40721..d754b21f6 100644 --- a/sys/src/libc/mips/tas.s +++ b/sys/src/libc/mips/tas.s @@ -17,7 +17,6 @@ btas: BLTZ R1, btas RET - TEXT _tas(SB),$0 TEXT C_4ktas(SB), $0 MOVW R1, R2 /* address of key */ tas1: diff --git a/sys/src/libc/mkfile b/sys/src/libc/mkfile index 8f1593cc1..3634076f8 100644 --- a/sys/src/libc/mkfile +++ b/sys/src/libc/mkfile @@ -37,7 +37,7 @@ update:V: cd $i mk $MKFLAGS update } - update $UPDATEFLAGS /$objtype/lib/libc.a + update $UPDATEFLAGS /386/lib/libc.a installall:V: for(objtype in $CPUS) mk $MKFLAGS install diff --git a/sys/src/libc/port/lock.c b/sys/src/libc/port/lock.c index 213fcd778..af07b9cc7 100644 --- a/sys/src/libc/port/lock.c +++ b/sys/src/libc/port/lock.c @@ -2,32 +2,40 @@ #include void -lock(Lock *l) +lock(Lock *lk) { - 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 i; -void -unlock(Lock *l) -{ - if(adec(&l->key) == 0) - return; /* changed from 1 -> 0: no contention */ - semrelease(&l->sem, 1); + /* 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); + } + /* 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 *l) +canlock(Lock *lk) { - 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; + if(_tas(&lk->val)) + return 0; + return 1; +} + +void +unlock(Lock *lk) +{ + lk->val = 0; } diff --git a/sys/src/libc/port/malloc.acid b/sys/src/libc/port/malloc.acid index 5e7519ad4..ac3ca3a9e 100644 --- a/sys/src/libc/port/malloc.acid +++ b/sys/src/libc/port/malloc.acid @@ -122,18 +122,16 @@ Profuser = 1; Profkernel = 2; Proftime = 3; Profsample = 4; -sizeofLock = 8; +sizeofLock = 4; aggr Lock { - 'D' 0 key; - 'D' 4 sem; + 'D' 0 val; }; defn Lock(addr) { complex Lock addr; - print(" key ", addr.key, "\n"); - print(" sem ", addr.sem, "\n"); + print(" val ", addr.val, "\n"); }; sizeofQLp = 12; @@ -152,13 +150,13 @@ QLp(addr) { print(" state ", addr.state, "\n"); }; -sizeofQLock = 20; +sizeofQLock = 16; aggr QLock { Lock 0 lock; - 'D' 8 locked; - 'A' QLp 12 $head; - 'A' QLp 16 $tail; + 'D' 4 locked; + 'A' QLp 8 $head; + 'A' QLp 12 $tail; }; defn @@ -172,14 +170,14 @@ QLock(addr) { print(" $tail ", addr.$tail\X, "\n"); }; -sizeofRWLock = 24; +sizeofRWLock = 20; aggr RWLock { Lock 0 lock; - 'D' 8 readers; - 'D' 12 writer; - 'A' QLp 16 $head; - 'A' QLp 20 $tail; + 'D' 4 readers; + 'D' 8 writer; + 'A' QLp 12 $head; + 'A' QLp 16 $tail; }; defn @@ -440,12 +438,12 @@ Tos(addr) { }; complex Tos _tos; -sizeofPrivate = 16; +sizeofPrivate = 12; aggr Private { Lock 0 lk; - 'D' 8 pid; - 'D' 12 printfd; + 'D' 4 pid; + 'D' 8 printfd; }; defn diff --git a/sys/src/libc/port/mkfile b/sys/src/libc/port/mkfile index 6d1f1c583..dc2d93694 100644 --- a/sys/src/libc/port/mkfile +++ b/sys/src/libc/port/mkfile @@ -19,7 +19,6 @@ CFILES=\ cleanname.c\ crypt.c\ ctype.c\ - cycles.c\ encodefmt.c\ execl.c\ exp.c\ diff --git a/sys/src/libc/port/pool.acid b/sys/src/libc/port/pool.acid index d4bed5ef7..2ec6f99af 100644 --- a/sys/src/libc/port/pool.acid +++ b/sys/src/libc/port/pool.acid @@ -122,18 +122,16 @@ Profuser = 1; Profkernel = 2; Proftime = 3; Profsample = 4; -sizeofLock = 8; +sizeofLock = 4; aggr Lock { - 'D' 0 key; - 'D' 4 sem; + 'D' 0 val; }; defn Lock(addr) { complex Lock addr; - print(" key ", addr.key, "\n"); - print(" sem ", addr.sem, "\n"); + print(" val ", addr.val, "\n"); }; sizeofQLp = 12; @@ -152,13 +150,13 @@ QLp(addr) { print(" state ", addr.state, "\n"); }; -sizeofQLock = 20; +sizeofQLock = 16; aggr QLock { Lock 0 lock; - 'D' 8 locked; - 'A' QLp 12 $head; - 'A' QLp 16 $tail; + 'D' 4 locked; + 'A' QLp 8 $head; + 'A' QLp 12 $tail; }; defn @@ -172,14 +170,14 @@ QLock(addr) { print(" $tail ", addr.$tail\X, "\n"); }; -sizeofRWLock = 24; +sizeofRWLock = 20; aggr RWLock { Lock 0 lock; - 'D' 8 readers; - 'D' 12 writer; - 'A' QLp 16 $head; - 'A' QLp 20 $tail; + 'D' 4 readers; + 'D' 8 writer; + 'A' QLp 12 $head; + 'A' QLp 16 $tail; }; defn @@ -506,20 +504,34 @@ 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 treesplay:t; -complex Free treesplay:N; -complex Free treesplay:l; -complex Free treesplay:r; -complex Free treesplay:y; +complex Free listadd:list; +complex Free listadd:node; +complex Free listdelete:list; +complex Free listdelete:node; complex Pool pooladd:p; complex Alloc pooladd:anode; +complex Free pooladd:lst; +complex Free pooladd:olst; complex Free pooladd:node; -complex Free pooladd:root; +complex Free pooladd:parent; complex Pool pooldel:p; complex Free pooldel:node; -complex Free pooldel:root; +complex Free pooldel:lst; +complex Free pooldel:olst; +complex Free pooldel:parent; complex Pool dsize2bsize:p; complex Pool bsize2asize:p; complex Pool blockmerge:pool; diff --git a/sys/src/libc/sparc/lock.c b/sys/src/libc/sparc/lock.c deleted file mode 100644 index c0966fcac..000000000 --- a/sys/src/libc/sparc/lock.c +++ /dev/null @@ -1,41 +0,0 @@ -#include -#include - -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; -} diff --git a/sys/src/libc/sparc/mkfile b/sys/src/libc/sparc/mkfile index 6ef2cf55c..af2b18944 100644 --- a/sys/src/libc/sparc/mkfile +++ b/sys/src/libc/sparc/mkfile @@ -22,7 +22,7 @@ SFILES=\ vlop.s CFILES=\ - lock.c\ + cycles.c\ notejmp.c\ sqrt.c\ vlrt.c\