--- /sys/include/ape/lock.h Thu Apr 27 02:29:43 2006 +++ /sys/include/ape/lock.h Thu Sep 19 02:10:12 2013 @@ -10,7 +10,8 @@ typedef struct { - int val; + long key; + long sem; } Lock; #ifdef __cplusplus --- /sys/include/libc.h Wed May 1 00:18:56 2013 +++ /sys/include/libc.h Thu Sep 19 00:45:28 2013 @@ -80,7 +80,7 @@ extern Rune tolowerrune(Rune); extern Rune totitlerune(Rune); extern Rune toupperrune(Rune); -extern Rune tobaserune(Rune); +extern Rune tobaserune(Rune); extern int isalpharune(Rune); extern int isbaserune(Rune); extern int isdigitrune(Rune); @@ -412,11 +412,21 @@ extern void prof(void (*fn)(void*), void *arg, int entries, int what); /* + * atomic + */ +long ainc(long*); +long adec(long*); +int cas32(u32int*, u32int, u32int); +int casp(void**, void*, void*); +int casl(ulong*, ulong, ulong); + +/* * synchronization */ typedef struct Lock { - int val; + long key; + long sem; } Lock; extern int _tas(int*); @@ -540,6 +550,7 @@ #define OCEXEC 32 /* or'ed in, close on exec */ #define ORCLOSE 64 /* or'ed in, remove on close */ #define OEXCL 0x1000 /* or'ed in, exclusive use (create only) */ +// #define OBEHIND 0x2000 /* use write behind for writes [for 9n] */ #define AEXIST 0 /* accessible: exists */ #define AEXEC 1 /* execute access */ @@ -660,6 +671,7 @@ extern int notify(void(*)(void*, char*)); extern int open(char*, int); extern int fd2path(int, char*, int); +// extern int fdflush(int); extern int pipe(int*); extern long pread(int, void*, long, vlong); extern long preadv(int, IOchunk*, int, vlong); --- /sys/man/1/dd Wed May 4 23:23:23 2011 +++ /sys/man/1/dd Wed Sep 18 22:17:27 2013 @@ -16,8 +16,8 @@ The input and output block size may be specified to take advantage of raw physical I/O. The options are -.TF "quiet\ \ \fIn -.PD +.TF "quietb\ \ \fIn +.PD 0.2v .TP .BI -if\ f Open file @@ -54,47 +54,53 @@ .BI -skip\ n\^ Skip .I n -input records before copying. +input blocks before copying. .TP .BI -iseek\ n\^ Seek .I n -records forward on input file +blocks forward on input file before copying. .TP +.BI -iseekb\ n\^ +Seek +.I n +bytes forward on input file before copying. +.TP .BI -files\ n\^ Catenate -.I n +.I n input files (useful only for magnetic tape or similar input device). .TP .BI -oseek\ n\^ Seek .I n\^ -records from beginning of output file before copying. +blocks from beginning of output file before copying. +.TP +.BI -oseekb\ n\^ +Seek +.I n\^ +bytes from beginning of output file before copying. .TP .BI -count\ n\^ Copy only .I n -input records. +input blocks. .TP .BI -trunc\ n\^ -By default, -.I dd -truncates the output file when it opens it; -.B -trunc -.B 0 -opens it without truncation. +If +.I n +is +.BR 0 , +open the output file without truncating it. .TP .BI -quiet\ n\^ -By default, -.I dd -prints the number of blocks read and written -once it is finished. -.B -quiet -.B 1 -silences this summary. +If +.I n +is 1, +omit the summary of blocks transferred. .HP -\fL-conv\ ascii\ \ \ \ \fRConvert +\fL-conv\ ascii\ \ \ \fRConvert .SM EBCDIC to .SM ASCII. @@ -113,14 +119,14 @@ but with a slightly different character map. .TP .B block -Convert variable length +Convert variable-length .SM ASCII -records to fixed length. +records (lines) to fixed length blocks. .TP .B unblock Convert fixed length .SM ASCII -records to variable length. +blocks to variable-length lines. .TP .B lcase Map alphabetics to lower case. @@ -135,7 +141,7 @@ Do not stop processing on an error. .TP .B sync -Pad every input record to +Pad every input block to .I ibs\^ bytes. .RE @@ -173,7 +179,7 @@ before sending the line to the output. In the latter three cases, characters are read into the conversion buffer and blanks are added to make up an -output record of size +output block of size .IR n . If .L cbs\^ --- /sys/src/9/rb/l.s Tue Jul 23 03:29:03 2013 +++ /sys/src/9/rb/l.s Thu Sep 19 02:08:25 2013 @@ -842,7 +842,8 @@ MOVW $1, R3 LL(2, 1) NOP - ADDU R1, R3, R3 + ADDU R1, R3 + MOVW R3, R1 /* return new value */ SC(2, 3) NOP BEQ R3, loop @@ -856,14 +857,15 @@ MOVW $-1, R3 LL(2, 1) NOP - ADDU R1, R3, R3 - MOVW R3, R1 + ADDU R1, R3 + MOVW R3, R1 /* return new value */ SC(2, 3) NOP BEQ R3, loop1 NOP RETURN +/* used by the semaphore implementation */ TEXT cmpswap(SB), $0 MOVW R1, R2 /* address of key */ MOVW old+4(FP), R3 /* old value */ --- /sys/src/ape/lib/ap/386/atom.s Thu Jan 1 01:00:00 1970 +++ /sys/src/ape/lib/ap/386/atom.s Thu Sep 19 00:49:38 2013 @@ -0,0 +1,121 @@ +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 --- /sys/src/ape/lib/ap/386/lock.c Thu Feb 28 19:46:30 2002 +++ /sys/src/ape/lib/ap/386/lock.c Thu Sep 19 00: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/386/mkfile Wed May 29 03:49:38 2013 +++ /sys/src/ape/lib/ap/386/mkfile Thu Sep 19 00:50:05 2013 @@ -2,6 +2,7 @@ <$APE/config LIB=/$objtype/lib/ape/libap.a OFILES=\ + atom.$O\ cycles.$O\ lock.$O\ main9.$O\ --- /sys/src/ape/lib/ap/arm/atom.s Thu Jan 1 01:00:00 1970 +++ /sys/src/ape/lib/ap/arm/atom.s Thu Sep 19 00:49:38 2013 @@ -0,0 +1,58 @@ +#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 --- /sys/src/ape/lib/ap/arm/lock.c Thu Feb 28 19:46:32 2002 +++ /sys/src/ape/lib/ap/arm/lock.c Thu Sep 19 00: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/arm/mkfile Wed May 29 03:50:36 2013 +++ /sys/src/ape/lib/ap/arm/mkfile Thu Sep 19 00:50:05 2013 @@ -2,6 +2,7 @@ <$APE/config LIB=/$objtype/lib/ape/libap.a OFILES=\ + atom.$O\ cycles.$O\ div.$O\ getfcr.$O\ --- /sys/src/ape/lib/ap/mips/atom.s Thu Jan 1 01:00:00 1970 +++ /sys/src/ape/lib/ap/mips/atom.s Thu Sep 19 01:59:06 2013 @@ -0,0 +1,52 @@ +/* + * 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 --- /sys/src/ape/lib/ap/mips/lock.c Wed Jun 12 22:07:46 2013 +++ /sys/src/ape/lib/ap/mips/lock.c Thu Sep 19 00:48:44 2013 @@ -1,177 +1,36 @@ -#define _LOCK_EXTENSION -#include -#include +#include "../plan9/lib.h" #include "../plan9/sys9.h" +#define _LOCK_EXTENSION #include - -enum -{ - 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: - n = _SEGATTACH(0, "lock", (void*)Lockaddr, Pagesize); - if(n < 0) { - arch = MAGNUM; - break; - } - memset((void*)Lockaddr, 0, Pagesize); - break; - case MAGNUM: - case MAGNUMII: - case R4K: - break; - default: - arch = R4K; - break; - } - -} +//#include void -lock(Lock *lk) +lock(Lock *l) { - 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; - } - } - return 0; - default: - return 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 */ + } } 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 -tas(int *p) +canlock(Lock *l) { - 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; - default: - return 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/mips/lock.pre-sema.c Thu Jan 1 01:00:00 1970 +++ /sys/src/ape/lib/ap/mips/lock.pre-sema.c Thu Sep 19 00:48:44 2013 @@ -0,0 +1,177 @@ +#define _LOCK_EXTENSION +#include +#include +#include "../plan9/sys9.h" +#include + +enum +{ + 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: + n = _SEGATTACH(0, "lock", (void*)Lockaddr, Pagesize); + if(n < 0) { + arch = MAGNUM; + break; + } + memset((void*)Lockaddr, 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; + } + } + return 0; + default: + 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; + default: + return 0; + } +} --- /sys/src/ape/lib/ap/mips/mkfile Wed Jun 12 22:07:51 2013 +++ /sys/src/ape/lib/ap/mips/mkfile Thu Sep 19 00:48:30 2013 @@ -2,6 +2,7 @@ <$APE/config LIB=/$objtype/lib/ape/libap.a OFILES=\ + atom.$O\ c_fcr0.$O\ cycles.$O\ getfcr.$O\ --- /sys/src/ape/lib/ap/mips/tas.s Wed Jun 12 22:07:53 2013 +++ /sys/src/ape/lib/ap/mips/tas.s Thu Sep 19 00:48:33 2013 @@ -17,6 +17,7 @@ BLTZ R1, btas RET + TEXT tas(SB), $0 TEXT C_4ktas(SB), $0 MOVW R1, R2 /* address of key */ tas1: --- /sys/src/ape/lib/ap/plan9/sys9.h Wed Mar 26 03:05:36 2003 +++ /sys/src/ape/lib/ap/plan9/sys9.h Thu Sep 19 00:50:51 2013 @@ -106,9 +106,12 @@ 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 Waitmsg* _WAIT(void); +extern int _TSEMACQUIRE(long*, unsigned long); extern long _WRITE(int, const void*, long); extern int _WSTAT(const char*, unsigned char*, int); @@ -119,3 +122,12 @@ extern int __link(char *, int); extern int __stat(char *, struct stat *); extern int __unlink(char *); + +/* + * atomic + */ +long ainc(long*); +long adec(long*); +int cas32(unsigned long*, unsigned long, unsigned long); +int casp(void**, void*, void*); +int casl(unsigned long*, unsigned long, unsigned long); --- /sys/src/ape/lib/ap/power/atom.s Thu Jan 1 01:00:00 1970 +++ /sys/src/ape/lib/ap/power/atom.s Thu Sep 19 00:49:38 2013 @@ -0,0 +1,63 @@ +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 --- /sys/src/ape/lib/ap/power/lock.c Thu Feb 28 19:46:31 2002 +++ /sys/src/ape/lib/ap/power/lock.c Thu Sep 19 00:50:12 2013 @@ -2,44 +2,35 @@ #include "../plan9/sys9.h" #define _LOCK_EXTENSION #include - -int tas(int*); +//#include 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; } --- /sys/src/ape/lib/ap/power/mkfile Wed May 29 03:53:17 2013 +++ /sys/src/ape/lib/ap/power/mkfile Thu Sep 19 00:50:05 2013 @@ -2,6 +2,7 @@ <$APE/config LIB=/$objtype/lib/ape/libap.a OFILES=\ + atom.$O\ cycles.$O\ getfcr.$O\ lock.$O\ --- /sys/src/ape/lib/ap/sparc/lock.c Thu Feb 28 19:46:28 2002 +++ /sys/src/ape/lib/ap/sparc/lock.c Thu Sep 19 00: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/sparc/mkfile Wed May 29 03:49:12 2013 +++ /sys/src/ape/lib/ap/sparc/mkfile Thu Sep 19 00:50:05 2013 @@ -2,6 +2,7 @@ <$APE/config LIB=/$objtype/lib/ape/libap.a OFILES=\ +# atom.$O\ cycles.$O\ lock.$O\ main9.$O\ --- /sys/src/cmd/dd.c Thu Aug 9 01:26:20 2007 +++ /sys/src/cmd/dd.c Wed Sep 18 22:17:37 2013 @@ -21,6 +21,8 @@ vlong skip; vlong oseekn; vlong iseekn; +vlong oseekb; +vlong iseekb; vlong count; long files = 1; @@ -125,6 +127,14 @@ iseekn = number(VBIG); continue; } + if(iskey("iseekb")) { + iseekb = number(VBIG); + continue; + } + if(iskey("oseekb")) { + oseekb = number(VBIG); + continue; + } if(iskey("count")) { count = number(VBIG); continue; @@ -240,6 +250,10 @@ */ seek(obf, obs*oseekn, 1); seek(ibf, ibs*iseekn, 1); + if(iseekb) + seek(ibf, iseekb, 0); + if(oseekb) + seek(obf, oseekb, 0); while(skip) { read(ibf, ibuf, ibs); skip--; --- /sys/src/libc/mips/atom.s Wed Jun 12 22:19:01 2013 +++ /sys/src/libc/mips/atom.s Thu Sep 19 02:00:30 2013 @@ -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 --- /sys/src/libc/mips/lock.c Wed Dec 14 23:40:06 2011 +++ /sys/src/libc/mips/lock.c Thu Jan 1 01:00:00 1970 @@ -1,171 +0,0 @@ -#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: - default: /* silence compiler */ - 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: - default: /* silence compiler */ - 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; - } -} --- /sys/src/libc/mips/mkfile Mon Apr 8 20:17:25 2013 +++ /sys/src/libc/mips/mkfile Wed Sep 18 23:08:11 2013 @@ -24,7 +24,6 @@ CFILES=\ cycles.c\ - lock.c\ notejmp.c\ sqrt.c\ vlrt.c\ --- /sys/src/libc/mips/tas.s Mon Apr 8 20:17:25 2013 +++ /sys/src/libc/mips/tas.s Thu Sep 19 02:00:30 2013 @@ -17,6 +17,7 @@ BLTZ R1, btas RET + TEXT _tas(SB), $0 TEXT C_4ktas(SB), $0 MOVW R1, R2 /* address of key */ tas1: --- /sys/src/libc/port/lock.c Thu Feb 28 21:16:38 2002 +++ /sys/src/libc/port/lock.c Thu Sep 19 02:06:46 2013 @@ -2,40 +2,32 @@ #include 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); - } - /* now nice and slow */ - for(i=0; i<1000; i++){ - if(!_tas(&lk->val)) - return; - sleep(100); + 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 */ } - /* 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; }