# HG changeset patch # User Francisco J Ballesteros # Date 1316075837 -7200 # Node ID 8be5a2c78a6508ab1b15ba283ec3798dc4a67298 # Parent 986a76e92d0f2adb9293604acd67c8100b685262 cleanup. libraries and includes moved into place. some man pages still remain to be fixed due to renames of functions. some prints changed to %d because of Ref. R=nix-dev, rminnich, nemo CC=nix-dev http://codereview.appspot.com/5002047 diff -r 986a76e92d0f -r 8be5a2c78a65 sys/include/libc.h --- a/sys/include/libc.h Thu Sep 15 10:32:14 2011 +0200 +++ b/sys/include/libc.h Thu Sep 15 10:37:17 2011 +0200 @@ -363,6 +363,7 @@ extern void exits(char*); extern double frexp(double, int*); extern uintptr getcallerpc(void*); +extern int getcoreno(int*); extern char* getenv(char*); extern int getfields(char*, char**, int, int, char*); extern int gettokens(char *, char **, int, char *); @@ -585,7 +586,11 @@ RFCENVG = (1<<11), RFCFDG = (1<<12), RFREND = (1<<13), - RFNOMNT = (1<<14) + RFNOMNT = (1<<14), + RFPREPAGE = (1<<15), + RFCPREPAGE = (1<<16), + RFCORE = (1<<17), + RFCCORE = (1<<18), }; typedef @@ -698,6 +703,100 @@ extern void werrstr(char*, ...); #pragma varargck argpos werrstr 1 +extern int zp(int*); + +/* + * Atomics + */ +extern int casl(ulong *p, ulong ov, ulong nv); +extern int ainc(int *); +extern int adec(int *); +extern void mfence(void); + +/* + * Zero-copy I/O + */ + +typedef struct Zio Zio; +struct Zio +{ + void* data; + ulong size; +}; + +/* kernel interface */ +extern void zfree(Zio io[], int nio); +extern int zpread(int fd, Zio io[], int nio, usize count, vlong offset); +extern int zcwrite(int fd, Zio io[], int nio); +extern int zcread(int fd, Zio io[], int nio, usize count); +extern int zpwrite(int fd, Zio io[], int nio, vlong offset); + + +/* + * NIX core types + */ +enum +{ + NIXTC = 0, + NIXKC, + NIXAC, +}; + + +/* + * NIX system calls and library functions. + */ +extern int execac(int, char*, char*[]); + +extern int altsems(int *ss[], int n); +extern int downsem(int *s, int dontblock); +extern void semstats(void); +extern void upsem(int *s); +extern int semtrytimes; + +/* + * Internal NIX system calls, used by library functions. + */ +extern void semsleep(int*, int); +extern void semwakeup(int*); +extern int semalt(int*[], int); +extern void semstats(void); +extern int semdebug; + +/* + * NIX queue based system call mechanism + */ +typedef struct Nixcall Nixcall; +typedef struct Nixret Nixret; +#pragma incomplete Nixcall +#pragma incomplete Nixret + +extern void nixcall(Nixcall*,int); +extern void* nixret(Nixret*); +extern void nixsyscall(void); + +/* + * NIX threads using the queue based system call mechanism + */ +extern int newthr(char*, void (*f)(int, void*[]), int, void*[]); +extern int gettid(void); +extern int tsyscall(int nr, ...); +extern void texits(char *sts); + +/* + * Performance counters + */ +enum +{ + PmcOs = 1, + PmcUser = 2, + PmcEnable = 4, +}; + +extern int confpmc(int, int, int, char *); +extern uvlong rdpmc(int); + + extern char *argv0; #define ARGBEGIN for((argv0||(argv0=*argv)),argv++,argc--;\ argv[0] && argv[0][0]=='-' && argv[0][1];\ diff -r 986a76e92d0f -r 8be5a2c78a65 sys/include/seg.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sys/include/seg.h Thu Sep 15 10:37:17 2011 +0200 @@ -0,0 +1,10 @@ +#pragma lib "libseg.a" +#pragma src "/sys/src/libseg" + + +void* newseg(char*,uvlong, ulong); + + + + + diff -r 986a76e92d0f -r 8be5a2c78a65 sys/include/tos.h --- a/sys/include/tos.h Thu Sep 15 10:32:14 2011 +0200 +++ b/sys/include/tos.h Thu Sep 15 10:37:17 2011 +0200 @@ -1,9 +1,40 @@ +typedef struct Callq Callq; +typedef struct Nixcall Nixcall; +typedef struct Nixret Nixret; +typedef struct Plink Plink; typedef struct Tos Tos; -typedef struct Plink Plink; #pragma incomplete Plink -struct Tos { +#define CALLQSZ 512 + +struct Nixcall +{ + void* tag; + int scall; + va_list sarg; +}; + +struct Nixret +{ + void* tag; + int sret; + char* err; +}; + +struct Callq +{ + int ksleep; + unsigned int qr; /* don't use uint for ape */ + unsigned int qw; + unsigned int rr; + unsigned int rw; + Nixcall q[CALLQSZ]; + Nixret r[CALLQSZ]; +}; + +struct Tos +{ struct /* Per process profiling */ { Plink *pp; /* known to be 0(ptr) */ @@ -12,12 +43,16 @@ Plink *first; ulong pid; ulong what; - } prof; + } prof; uvlong cyclefreq; /* cycle clock frequency if there is one, 0 otherwise */ vlong kcycles; /* cycles spent in kernel */ vlong pcycles; /* cycles spent in process (kernel + user) */ ulong pid; /* might as well put the pid here */ ulong clock; + + int nixtype; /* role of the core we are running at */ + int core; /* core we are running at */ + Callq callq; /* NIX queue based system calls */ /* top of stack is here */ }; diff -r 986a76e92d0f -r 8be5a2c78a65 sys/include/tube.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sys/include/tube.h Thu Sep 15 10:37:17 2011 +0200 @@ -0,0 +1,47 @@ +#pragma lib "libtube.a" +#pragma src "/sys/src/libtube" + +typedef struct Tube Tube; +typedef struct Talt Talt; + +/* + * Talt.op + */ +enum +{ + TSND = 0x6666, /* weird numbers, for debugging */ + TRCV, + TNBSND, + TNBRCV, + TNOP +}; + +struct Tube +{ + int msz; /* message size */ + int tsz; /* tube size (# of messages) */ + int nmsg; /* semaphore: # of messages in tube */ + int nhole; /* semaphore: # of free slots in tube */ + int hd; + int tl; +}; + +struct Talt +{ + Tube* t; + void* m; + int op; +}; + + + +extern void freetube(Tube *t); +extern int nbtrecv(Tube *t, void *p); +extern int nbtsend(Tube *t, void *p); +extern Tube* newtube(ulong msz, ulong n); +extern int talt(Talt a[], int na); +extern void trecv(Tube *t, void *p); +extern void tsend(Tube *t, void *p); +extern Tube* namedtube(char*,ulong,int, int); + +extern int namedtubedebug; diff -r 986a76e92d0f -r 8be5a2c78a65 sys/src/cmd/usb/ether/ether.c --- a/sys/src/cmd/usb/ether/ether.c Thu Sep 15 10:32:14 2011 +0200 +++ b/sys/src/cmd/usb/ether/ether.c Thu Sep 15 10:37:17 2011 +0200 @@ -248,7 +248,7 @@ s = seprint(s, se, "input errs: %ld\n", e->nierrs); s = seprint(s, se, "output errs: %ld\n", e->noerrs); s = seprint(s, se, "mbps: %d\n", e->mbps); - s = seprint(s, se, "prom: %ld\n", e->prom.ref); + s = seprint(s, se, "prom: %d\n", e->prom.ref); s = seprint(s, se, "addr: "); s = seprintaddr(s, se, e->addr); s = seprint(s, se, "\n"); @@ -276,7 +276,7 @@ if(c->ref == 0) s = seprint(s, se, "c[%d]: free\n", i); else{ - s = seprint(s, se, "c[%d]: refs %ld t %#x h %d p %d\n", + s = seprint(s, se, "c[%d]: refs %d t %#x h %d p %d\n", c->nb, c->ref, c->type, c->headersonly, c->prom); } } @@ -1178,7 +1178,7 @@ proccreate(etherwriteproc, e, 16*1024); incref(e->dev); proccreate(etherreadproc, e, 16*1024); - deprint(2, "%s: dev ref %ld\n", argv0, dev->ref); + deprint(2, "%s: dev ref %d\n", argv0, dev->ref); incref(e->dev); usbfsadd(&e->fs); return 0; diff -r 986a76e92d0f -r 8be5a2c78a65 sys/src/cmd/usb/lib/dump.c --- a/sys/src/cmd/usb/lib/dump.c Thu Sep 15 10:32:14 2011 +0200 +++ b/sys/src/cmd/usb/lib/dump.c Thu Sep 15 10:37:17 2011 +0200 @@ -133,11 +133,11 @@ s = seprint(s, e, "%s", d->dir); ud = d->usb; if(ud == nil) - return fmtprint(f, "%s %ld refs\n", buf, d->ref); + return fmtprint(f, "%s %d refs\n", buf, d->ref); s = seprint(s, e, " csp %s.%uld.%uld", classname(Class(ud->csp)), Subclass(ud->csp), Proto(ud->csp)); s = seprint(s, e, " vid %#ux did %#ux", ud->vid, ud->did); - s = seprint(s, e, " refs %ld\n", d->ref); + s = seprint(s, e, " refs %d\n", d->ref); s = seprint(s, e, "\t%s %s %s\n", ud->vendor, ud->product, ud->serial); for(i = 0; i < Nconf; i++){ if(ud->conf[i] == nil) diff -r 986a76e92d0f -r 8be5a2c78a65 sys/src/cmd/usb/lib/fsdir.c --- a/sys/src/cmd/usb/lib/fsdir.c Thu Sep 15 10:32:14 2011 +0200 +++ b/sys/src/cmd/usb/lib/fsdir.c Thu Sep 15 10:37:17 2011 +0200 @@ -54,7 +54,7 @@ for(i = 1; i < nfs; i++) if(fs[i] != nil) if(fs[i]->dev != nil) - fprint(2, "%s\t%s dev %#p refs %ld\n", + fprint(2, "%s\t%s dev %#p refs %d\n", argv0, fs[i]->name, fs[i]->dev, fs[i]->dev->ref); else fprint(2, "%s:\t%s\n", argv0, fs[i]->name); @@ -95,7 +95,7 @@ if(fs[i] != nil){ dprint(2, "%s: fsdel %s", argv0, fs[i]->name); if(fs[i]->dev != nil){ - dprint(2, " dev %#p ref %ld\n", + dprint(2, " dev %#p ref %d\n", fs[i]->dev, fs[i]->dev->ref); }else dprint(2, "no dev\n"); diff -r 986a76e92d0f -r 8be5a2c78a65 sys/src/lib9p/req.c --- a/sys/src/lib9p/req.c Thu Sep 15 10:32:14 2011 +0200 +++ b/sys/src/lib9p/req.c Thu Sep 15 10:37:17 2011 +0200 @@ -13,7 +13,7 @@ r = v; if(r){ if(chatty9p > 1) - fprint(2, "increfreq %p %ld\n", r, r->ref.ref); + fprint(2, "increfreq %p %d\n", r, r->ref.ref); incref(&r->ref); } } @@ -73,7 +73,7 @@ return; if(chatty9p > 1) - fprint(2, "closereq %p %ld\n", r, r->ref.ref); + fprint(2, "closereq %p %d\n", r, r->ref.ref); if(decref(&r->ref) == 0){ if(r->fid) diff -r 986a76e92d0f -r 8be5a2c78a65 sys/src/libc/386/atom.s --- a/sys/src/libc/386/atom.s Thu Sep 15 10:32:14 2011 +0200 +++ b/sys/src/libc/386/atom.s Thu Sep 15 10:37:17 2011 +0200 @@ -73,3 +73,13 @@ JNE fail MOVL $1,AX RET + +/* + * void mfence(void); + */ +TEXT mfence(SB),0,$0 + BYTE $0x0f + BYTE $0xae + BYTE $0xf0 + RET + diff -r 986a76e92d0f -r 8be5a2c78a65 sys/src/libc/9sys/getcore.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sys/src/libc/9sys/getcore.c Thu Sep 15 10:37:17 2011 +0200 @@ -0,0 +1,14 @@ +#include +#include +#include + +/* + * getcore() conflicts with tbl source. + */ +int +getcoreno(int *type) +{ + if (type != nil) + *type = _tos->nixtype; + return _tos->core; +} diff -r 986a76e92d0f -r 8be5a2c78a65 sys/src/libc/9sys/mkfile --- a/sys/src/libc/9sys/mkfile Thu Sep 15 10:32:14 2011 +0200 +++ b/sys/src/libc/9sys/mkfile Thu Sep 15 10:37:17 2011 +0200 @@ -20,12 +20,14 @@ dirwstat.$O\ fcallfmt.$O\ fork.$O\ + getcore.$O\ + getenv.$O\ getnetconninfo.$O\ - getenv.$O\ getpid.$O\ getppid.$O\ getwd.$O\ iounit.$O\ + nixcall.$O\ nsec.$O\ nulldir.$O\ postnote.$O\ @@ -47,13 +49,19 @@ times.$O\ tm2sec.$O\ truerand.$O\ + upsem.$O\ wait.$O\ waitpid.$O\ werrstr.$O\ write.$O\ writev.$O\ + zcread.$O\ + zcwrite.$O\ + zp.$O\ -HFILES=/sys/include/libc.h +HFILES=\ + /sys/include/libc.h\ + /sys/include/tos.h\ UPDATE=\ mkfile\ diff -r 986a76e92d0f -r 8be5a2c78a65 sys/src/libc/9sys/nixcall.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sys/src/libc/9sys/nixcall.c Thu Sep 15 10:37:17 2011 +0200 @@ -0,0 +1,51 @@ +#include +#include +#include + +#define DBG if(nixcalldebug)print + +int nixcalldebug; + +#define NEXT(i) (((i)+1)%CALLQSZ) + +/* + * Issue the system call + */ +void +nixcall(Nixcall *nc, int wakekernel) +{ + Callq *callq; + + callq = &_tos->callq; + if(NEXT(callq->qw) == callq->qr) + sysfatal("bug: increase Ncalls"); + + memmove(&callq->q[callq->qw], nc, sizeof *nc); + mfence(); + callq->qw = NEXT(callq->qw); + DBG("libc: syscall qw %d\n", callq->qw); + if(wakekernel && callq->ksleep) + nixsyscall(); +} + +/* + * Receive the reply for the system call + * and return tag as given to its nixcall. + */ +void* +nixret(Nixret *nr) +{ + Callq *callq; + void *tag; + + callq = &_tos->callq; + + if(callq->rr == callq->rw) + return nil; + tag = callq->r[callq->rr].tag; + if(nr != nil) + *nr = callq->r[callq->rr]; + mfence(); + callq->rr = NEXT(callq->rr); + return tag; +} diff -r 986a76e92d0f -r 8be5a2c78a65 sys/src/libc/9sys/upsem.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sys/src/libc/9sys/upsem.c Thu Sep 15 10:37:17 2011 +0200 @@ -0,0 +1,124 @@ +#include +#include + +typedef struct Cnt Cnt; /* debug */ +struct Cnt +{ + int sleep; + int zsleep; + int wake; + int zwake; + int uup; + int kup; + int udown; + int kdown; + int ualt; + int kalt; +}; + +#define dprint if(semdebug)fprint + +int semtrytimes = 100; +int semdebug; + +static Cnt c; + +static void +typesok(void) +{ + /* + * The C library uses long*, but the kernel is + * going to use int*; f*ck. + */ + assert(sizeof(int) == sizeof(long)); +} + +void +upsem(int *s) +{ + int n; + + assert(s != nil); + typesok(); + n = ainc(s); + dprint(2, "upsem: %#p = %d\n", s, n); + if(n <= 0){ + ainc(&c.kup); + semwakeup(s); + }else + ainc(&c.uup); +} + +int +downsem(int *s, int dontblock) +{ + int n; + int i; + + + assert(s != nil); + typesok(); + /* busy wait */ + for(i = 0; *s <= 0 && i < semtrytimes; i++) + sleep(0); + + if(*s <= 0 && dontblock) + return -1; + n = adec(s); + dprint(2, "downsem: %#p = %d\n", s, n); + if(n < 0){ + ainc(&c.kdown); + semsleep(s, dontblock); + if(dontblock == 0) + dprint(2, "downsem: %#p awaken\n", s); + }else + ainc(&c.udown); + return 0; +} + +int +altsems(int *ss[], int n) +{ + int i, w, r; + + typesok(); + assert(ss != nil); + assert(n > 0); + + /* busy wait */ + for(w = 0; w < semtrytimes; w++){ + for(i = 0; i < n; i++) + if(ss[i] == nil) + sysfatal("altsems: nil sem"); + else if(*ss[i] > 0) + break; + if(i < n) + break; + } + + for(i = 0; i < n; i++) + if(downsem(ss[i], 1) != -1){ + ainc(&c.ualt); + return i; + } + + ainc(&c.kalt); + r = semalt(ss, n); + return r; +} + +void +semstats(void) +{ + print("sleep: %d\n", c.sleep); + print("zsleep: %d\n", c.zsleep); + print("wake: %d\n", c.wake); + print("zwake: %d\n", c.zwake); + print("uup: %d\n", c.uup); + print("kup: %d\n", c.kup); + print("udown: %d\n", c.udown); + print("kdown: %d\n", c.kdown); + print("ualt: %d\n", c.ualt); + print("kalt: %d\n", c.kalt); +} + diff -r 986a76e92d0f -r 8be5a2c78a65 sys/src/libc/9sys/zcread.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sys/src/libc/9sys/zcread.c Thu Sep 15 10:37:17 2011 +0200 @@ -0,0 +1,8 @@ +#include +#include + +int +zcread(int fd, Zio io[], int nio, usize count) +{ + return zpread(fd, io, nio, count, -1LL); +} diff -r 986a76e92d0f -r 8be5a2c78a65 sys/src/libc/9sys/zcwrite.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sys/src/libc/9sys/zcwrite.c Thu Sep 15 10:37:17 2011 +0200 @@ -0,0 +1,8 @@ +#include +#include + +int +zcwrite(int fd, Zio io[], int nio) +{ + return zpwrite(fd, io, nio, -1LL); +} diff -r 986a76e92d0f -r 8be5a2c78a65 sys/src/libc/9sys/zp.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sys/src/libc/9sys/zp.c Thu Sep 15 10:37:17 2011 +0200 @@ -0,0 +1,18 @@ +#include +#include + +int +zp(int fd[2]) +{ + if(bind("#∏", "/mnt/zp", MREPL|MCREATE) < 0) + return -1; + fd[0] = open("/mnt/zp/data", ORDWR); + if(fd[0] < 0) + return -1; + fd[1] = open("/mnt/zp/data1", ORDWR); + if(fd[1] < 0){ + close(fd[0]); + return -1; + } + return 0; +} diff -r 986a76e92d0f -r 8be5a2c78a65 sys/src/libc/9syscall/sys.h --- a/sys/src/libc/9syscall/sys.h Thu Sep 15 10:32:14 2011 +0200 +++ b/sys/src/libc/9syscall/sys.h Thu Sep 15 10:37:17 2011 +0200 @@ -48,3 +48,12 @@ #define AWAIT 47 #define PREAD 50 #define PWRITE 51 +#define SEMSLEEP 52 +#define SEMWAKEUP 53 +#define SEMALT 54 +#define EXECAC 55 +#define NIXSYSCALL 56 +#define ZPREAD 57 +#define ZPWRITE 58 +#define ZFREE 59 + diff -r 986a76e92d0f -r 8be5a2c78a65 sys/src/libc/amd64/atom.s --- a/sys/src/libc/amd64/atom.s Thu Sep 15 10:32:14 2011 +0200 +++ b/sys/src/libc/amd64/atom.s Thu Sep 15 10:37:17 2011 +0200 @@ -55,3 +55,11 @@ _cas64r0: DECL AX RET + +/* + * void mfence(void); + */ +TEXT mfence(SB),0,$0 + MFENCE + RET + diff -r 986a76e92d0f -r 8be5a2c78a65 sys/src/libc/amd64/mkfile --- a/sys/src/libc/amd64/mkfile Thu Sep 15 10:32:14 2011 +0200 +++ b/sys/src/libc/amd64/mkfile Thu Sep 15 10:37:17 2011 +0200 @@ -16,6 +16,7 @@ memmove.s\ memset.s\ muldiv.s\ + rdpmc.s\ setjmp.s\ sqrt.s\ strcat.s\ diff -r 986a76e92d0f -r 8be5a2c78a65 sys/src/libc/amd64/rdpmc.s --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sys/src/libc/amd64/rdpmc.s Thu Sep 15 10:37:17 2011 +0200 @@ -0,0 +1,9 @@ +MODE $64 + +TEXT rdpmc(SB), 1, $-4 /* performance monitor counter */ + MOVL RARG, CX + RDPMC /* read CX performance counter */ + XCHGL DX, AX /* swap lo/hi, zero-extend */ + SHLQ $32, AX /* hi<<32 */ + ORQ DX, AX /* (hi<<32)|lo */ + RET diff -r 986a76e92d0f -r 8be5a2c78a65 sys/src/libc/mkfile --- a/sys/src/libc/mkfile Thu Sep 15 10:32:14 2011 +0200 +++ b/sys/src/libc/mkfile Thu Sep 15 10:37:17 2011 +0200 @@ -1,6 +1,6 @@ +#include + +int +confpmc(int core, int index, int mode, char *desc) +{ + int fd; + char name[32]; + + if(core < 0) + core = getcoreno(nil); + snprint(name, sizeof(name), "/dev/core%4.4d/ctr%2.2dctl", core, index); + + fd = open(name, OWRITE); + if (fd < 0) + return -1; + + if (fprint(fd, "reset\n") < 0) { + close(fd); + return -1; + } + + if (mode&PmcOs) + if (fprint(fd, "os\n") < 0) { + close(fd); + return -1; + } + if (mode&PmcUser) + if (fprint(fd, "user\n") < 0) { + close(fd); + return -1; + } + + if (desc != nil) + if (fprint(fd, "set %s\n", desc) < 0) { + close(fd); + return -1; + } + if (mode&PmcEnable) + if (fprint(fd, "enable\n") < 0) { + close(fd); + return -1; + } + + close(fd); + return 0; +} diff -r 986a76e92d0f -r 8be5a2c78a65 sys/src/libc/port/mkfile --- a/sys/src/libc/port/mkfile Thu Sep 15 10:32:14 2011 +0200 +++ b/sys/src/libc/port/mkfile Thu Sep 15 10:37:17 2011 +0200 @@ -17,6 +17,7 @@ cistrstr.c\ charstod.c\ cleanname.c\ + confpmc.c\ crypt.c\ ctype.c\ encodefmt.c\ @@ -58,6 +59,7 @@ qsort.c\ quote.c\ rand.c\ + rdpmc.c\ readn.c\ rune.c\ runestrcat.c\ diff -r 986a76e92d0f -r 8be5a2c78a65 sys/src/libc/port/rdpmc.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sys/src/libc/port/rdpmc.c Thu Sep 15 10:37:17 2011 +0200 @@ -0,0 +1,25 @@ +#include +#include + + + +uvlong +rdpmc(int index) +{ + int fd, n, core; + char name[16+2+1]; /* 0x0000000000000000\0 */ + + core = getcoreno(nil); + + snprint(name, sizeof(name), "/dev/core%4.4d/ctr%2.2ud", core, index); + + fd = open(name, OREAD); + if (fd < 0) + return 0xcafebabe; + n = read(fd, name, sizeof(name) - 1); + if (n < 0) + return 0xcafebabe; + close(fd); + name[n] = '\0'; + return atoi(name); +} diff -r 986a76e92d0f -r 8be5a2c78a65 sys/src/libc/thr/dat.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sys/src/libc/thr/dat.h Thu Sep 15 10:37:17 2011 +0200 @@ -0,0 +1,32 @@ +typedef struct Thr Thr; + +enum +{ + Stack = 24 * 1024 +}; + +enum +{ + Trun, /* running */ + Trdy, /* ready */ + Tblk, /* issuing a system call */ + Tsys, /* waiting for a system call */ + Tdead, /* exiting */ +}; + +struct Thr +{ + Nixcall; + Nixret nr; + char* name; + int state; + int id; + uchar* stk; + jmp_buf label; + void (*main)(int, void *[]); + int argc; + void** argv; + Thr* next; /* in list */ + Thr* prev; /* only in sysq */ +}; + diff -r 986a76e92d0f -r 8be5a2c78a65 sys/src/libc/thr/mkfile --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sys/src/libc/thr/mkfile Thu Sep 15 10:37:17 2011 +0200 @@ -0,0 +1,19 @@ +objtype=amd64 + +#include +#include +#include "dat.h" + +#define DBG if(tdebug)print + +static Thr *runq0; /* head of ready queue */ +static Thr *runqn; /* tail of ready queue */ +static Thr *freeq; /* dead threads to recycle */ +static Thr *run; /* running thread */ +static Thr *sysq; /* threads waiting for system calls */ +static int tidgen; +static char *tstatus; /* exit status */ + +int tdebug; + +static void +dumpq(Thr *t, char *tag) +{ + print("%s:", tag); + if(t == nil){ + print(" none\n"); + return; + } + for(; t != nil; t = t->next) + print(" %s!%s(%d)", argv0, t->name, t->id); + print("\n"); +} + +static void +dump(void) +{ + if(run != nil) + print("run: %s!%s %d\n", argv0, run->name, run->id); + dumpq(runq0, "runq"); + dumpq(sysq, "sysq"); + dumpq(freeq, "freeq"); +} + +static void +tfree(Thr *t) +{ + t->next = freeq; + free(t->tag); + t->tag = nil; + freeq = t; +} + +static Thr* +trecycle(void) +{ + Thr *t; + + t = freeq; + if(t != nil){ + freeq = t->next; + t->next = nil; + } + return t; +} + +static Thr* +tnext(void) +{ + Thr *t; + + assert(runq0 != nil); + t = runq0; + runq0 = t->next; + if(runq0 == nil) + runqn = nil; + return t; +} + +static void +trdy(Thr *t) +{ + t->state = Trdy; + if(runqn == nil) + runq0 = t; + else + runqn->next = t; + runqn = t; +} + +static void +tunsys(Thr *t) +{ + if(t == sysq) + sysq = t->next; + if(t->next) + t->next->prev = t->prev; + if(t->prev) + t->prev->next = t->next; + t->next = t->prev = nil; +} + +static void +tsys(Thr *t) +{ + t->state = Tsys; + t->next = sysq; + if(sysq) + sysq->prev = t; + sysq = t; +} + +static void +syscalls(void) +{ + Thr *t; + Nixret nr; + + /* + * Collect replies for previous system calls + */ + while((t = nixret(&nr)) != nil){ + t->nr = nr; + DBG("nixret %s!%s %d: %d err %s\n", + argv0, t->name, t->id, t->nr.sret, t->nr.err); + tunsys(t); + trdy(t); + if(tdebug>1)dump(); + } +} + +static void +tsched(int state) +{ + if(run != nil){ + if(setjmp(run->label) != 0) + return; + switch(state){ + case Trdy: + trdy(run); + break; + case Tsys: + tsys(run); + break; + case Tdead: + tfree(run); + break; + default: + sysfatal("tsched: state %d", state); + } + run = nil; + } + + syscalls(); + while(runq0 == nil){ + syscalls(); + sleep(0); /* BUG: poll for a while, then block */ + if(sysq == nil && runq0 == nil){ + DBG("%s: tsched: none ready\n", argv0); + exits(tstatus); + } + } + + run = tnext(); + if(tdebug>1)dump(); + longjmp(run->label, 1); +} + +void +texits(char *sts) +{ + if(sts != nil) + tstatus = sts; + DBG("texits %s!%s %d%s\n", argv0, run->name, run->id, sts?sts:""); + tsched(Tdead); +} + +static void +thr0(void) +{ + run->main(run->argc, run->argv); + texits(nil); +} + +int +gettid(void) +{ + return run->id; +} + +int +newthr(char *tag, void (*f)(int, void*[]), int argc, void*argv[]) +{ + Thr *t; + static int once; + + t = trecycle(); + if(t == nil){ + t = mallocz(sizeof *t, 1); + if(t == nil) + sysfatal("newthr: no memory"); + t->tag = t; + t->stk = malloc(Stack); + if(t->stk == nil) + sysfatal("newthr: no memory"); + } + t->id = ++tidgen; + t->name = strdup(tag); + if(t->tag == nil) + sysfatal("newthr: no memory"); + t->state = Trdy; + t->main = f; + t->argc = argc; + t->argv = malloc(sizeof(void*)*argc); + if(t->argv == nil) + sysfatal("newthr: no memory"); + memmove(t->argv, argv, sizeof(void*)*argc); + t->label[JMPBUFPC] = (uintptr)thr0; + t->label[JMPBUFSP] = (uintptr)(t->stk + Stack - 2 * sizeof(ulong*)); + trdy(t); + DBG("newthr %s!%s %d\n", argv0, t->name, t->id); + /* + * The first call does not return, and jumps to the new thread. + */ + if(once == 0){ + once = 1; + tsched(Trdy); + } + return t->id; +} + +int +tsyscall(int nr, ...) +{ + run->scall = nr; + va_start(run->sarg, nr); + nixcall(run, 1); + tsched(Tsys); + va_end(run->sarg); + return run->nr.sret; +} diff -r 986a76e92d0f -r 8be5a2c78a65 sys/src/libc/thr/thr.c.batching --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sys/src/libc/thr/thr.c.batching Thu Sep 15 10:37:17 2011 +0200 @@ -0,0 +1,269 @@ +#include +#include +#include +#include "dat.h" + +#define DBG if(tdebug)print + +static Thr *runq0; /* head of ready queue */ +static Thr *runqn; /* tail of ready queue */ +static Thr *freeq; /* dead threads to recycle */ +static Thr *run; /* running thread */ +static Thr *blkq; /* threads that want to make a system call */ +static Thr *sysq; /* threads waiting for system calls */ +static int tidgen; +static char *tstatus; /* exit status */ + +int tdebug; + +static void +dumpq(Thr *t, char *tag) +{ + print("%s:", tag); + if(t == nil){ + print(" none\n"); + return; + } + for(; t != nil; t = t->next) + print(" %s!%s(%d)", argv0, t->name, t->id); + print("\n"); +} + +static void +dump(void) +{ + if(run != nil) + print("run: %s!%s %d\n", argv0, run->name, run->id); + dumpq(runq0, "runq"); + dumpq(sysq, "sysq"); + dumpq(freeq, "freeq"); +} + +static void +tfree(Thr *t) +{ + t->next = freeq; + free(t->tag); + t->tag = nil; + freeq = t; +} + +static Thr* +trecycle(void) +{ + Thr *t; + + t = freeq; + if(t != nil){ + freeq = t->next; + t->next = nil; + } + return t; +} + +static Thr* +tnext(void) +{ + Thr *t; + + assert(runq0 != nil); + t = runq0; + runq0 = t->next; + if(runq0 == nil) + runqn = nil; + return t; +} + +static void +trdy(Thr *t) +{ + t->state = Trdy; + if(runqn == nil) + runq0 = t; + else + runqn->next = t; + runqn = t; +} + +static Thr* +tunblk(void) +{ + Thr *t; + + t = blkq; + if(t != nil){ + blkq = blkq->next; + t->next = nil; + } + return t; +} + +static void +tblk(Thr *t) +{ + t->state = Tblk; + t->next = blkq; + blkq = t; +} + +static void +tunsys(Thr *t) +{ + if(t == sysq) + sysq = t->next; + if(t->next) + t->next->prev = t->prev; + if(t->prev) + t->prev->next = t->next; + t->next = t->prev = nil; +} + +static void +tsys(Thr *t) +{ + t->state = Tsys; + t->next = sysq; + if(sysq) + sysq->prev = t; + sysq = t; +} + +static void +syscalls(void) +{ + Thr *t; + Nixret nr; + + /* + * Make all pending system calls. + * Awake the kernel if aslept on the last one. + */ + while((t = tunblk()) != nil){ + nixcall(t, blkq == nil); + tsys(t); + } + /* + * Collect replies for previous system calls + */ + while((t = nixret(&nr)) != nil){ + t->nr = nr; + DBG("nixret %s!%s %d: %d err %s\n", + argv0, t->name, t->id, t->nr.sret, t->nr.err); + tunsys(t); + trdy(t); + if(tdebug>1)dump(); + } +} + +static void +tsched(int state) +{ + if(run != nil){ + if(setjmp(run->label) != 0) + return; + switch(state){ + case Trdy: + trdy(run); + break; + case Tblk: + tblk(run); + break; + case Tsys: + tsys(run); + break; + case Tdead: + tfree(run); + break; + default: + sysfatal("tsched: state %d", state); + } + run = nil; + } + + syscalls(); + while(runq0 == nil){ + syscalls(); + sleep(0); /* BUG: poll for a while, then block */ + if(sysq == nil && runq0 == nil){ + DBG("%s: tsched: none ready\n", argv0); + exits(tstatus); + } + } + + run = tnext(); + if(tdebug>1)dump(); + longjmp(run->label, 1); +} + +void +texits(char *sts) +{ + if(sts != nil) + tstatus = sts; + DBG("texits %s!%s %d%s\n", argv0, run->name, run->id, sts?sts:""); + tsched(Tdead); +} + +static void +thr0(void) +{ + run->main(run->argc, run->argv); + texits(nil); +} + +int +gettid(void) +{ + return run->id; +} + +int +newthr(char *tag, void (*f)(int, void*[]), int argc, void*argv[]) +{ + Thr *t; + static int once; + + t = trecycle(); + if(t == nil){ + t = mallocz(sizeof *t, 1); + if(t == nil) + sysfatal("newthr: no memory"); + t->tag = t; + t->stk = malloc(Stack); + if(t->stk == nil) + sysfatal("newthr: no memory"); + } + t->id = ++tidgen; + t->name = strdup(tag); + if(t->tag == nil) + sysfatal("newthr: no memory"); + t->state = Trdy; + t->main = f; + t->argc = argc; + t->argv = malloc(sizeof(void*)*argc); + if(t->argv == nil) + sysfatal("newthr: no memory"); + memmove(t->argv, argv, sizeof(void*)*argc); + t->label[JMPBUFPC] = (uintptr)thr0; + t->label[JMPBUFSP] = (uintptr)(t->stk + Stack - 2 * sizeof(ulong*)); + trdy(t); + DBG("newthr %s!%s %d\n", argv0, t->name, t->id); + /* + * The first call does not return, and jumps to the new thread. + */ + if(once == 0){ + once = 1; + tsched(Trdy); + } + return t->id; +} + +int +tsyscall(int nr, ...) +{ + run->scall = nr; + va_start(run->sarg, nr); + tsched(Tblk); + va_end(run->sarg); + return run->nr.sret; +} diff -r 986a76e92d0f -r 8be5a2c78a65 sys/src/libc/thr/thr.c.eager --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sys/src/libc/thr/thr.c.eager Thu Sep 15 10:37:17 2011 +0200 @@ -0,0 +1,237 @@ +#include +#include +#include +#include "dat.h" + +#define DBG if(tdebug)print + +static Thr *runq0; /* head of ready queue */ +static Thr *runqn; /* tail of ready queue */ +static Thr *freeq; /* dead threads to recycle */ +static Thr *run; /* running thread */ +static Thr *sysq; /* threads waiting for system calls */ +static int tidgen; +static char *tstatus; /* exit status */ + +int tdebug; + +static void +dumpq(Thr *t, char *tag) +{ + print("%s:", tag); + if(t == nil){ + print(" none\n"); + return; + } + for(; t != nil; t = t->next) + print(" %s!%s(%d)", argv0, t->name, t->id); + print("\n"); +} + +static void +dump(void) +{ + if(run != nil) + print("run: %s!%s %d\n", argv0, run->name, run->id); + dumpq(runq0, "runq"); + dumpq(sysq, "sysq"); + dumpq(freeq, "freeq"); +} + +static void +tfree(Thr *t) +{ + t->next = freeq; + free(t->tag); + t->tag = nil; + freeq = t; +} + +static Thr* +trecycle(void) +{ + Thr *t; + + t = freeq; + if(t != nil){ + freeq = t->next; + t->next = nil; + } + return t; +} + +static Thr* +tnext(void) +{ + Thr *t; + + assert(runq0 != nil); + t = runq0; + runq0 = t->next; + if(runq0 == nil) + runqn = nil; + return t; +} + +static void +trdy(Thr *t) +{ + t->state = Trdy; + if(runqn == nil) + runq0 = t; + else + runqn->next = t; + runqn = t; +} + +static void +tunsys(Thr *t) +{ + if(t == sysq) + sysq = t->next; + if(t->next) + t->next->prev = t->prev; + if(t->prev) + t->prev->next = t->next; + t->next = t->prev = nil; +} + +static void +tsys(Thr *t) +{ + t->state = Tsys; + t->next = sysq; + if(sysq) + sysq->prev = t; + sysq = t; +} + +static void +syscalls(void) +{ + Thr *t; + Nixret nr; + + /* + * Collect replies for previous system calls + */ + while((t = nixret(&nr)) != nil){ + t->nr = nr; + DBG("nixret %s!%s %d: %d err %s\n", + argv0, t->name, t->id, t->nr.sret, t->nr.err); + tunsys(t); + trdy(t); + if(tdebug>1)dump(); + } +} + +static void +tsched(int state) +{ + if(run != nil){ + if(setjmp(run->label) != 0) + return; + switch(state){ + case Trdy: + trdy(run); + break; + case Tsys: + tsys(run); + break; + case Tdead: + tfree(run); + break; + default: + sysfatal("tsched: state %d", state); + } + run = nil; + } + + syscalls(); + while(runq0 == nil){ + syscalls(); + sleep(0); /* BUG: poll for a while, then block */ + if(sysq == nil && runq0 == nil){ + DBG("%s: tsched: none ready\n", argv0); + exits(tstatus); + } + } + + run = tnext(); + if(tdebug>1)dump(); + longjmp(run->label, 1); +} + +void +texits(char *sts) +{ + if(sts != nil) + tstatus = sts; + DBG("texits %s!%s %d%s\n", argv0, run->name, run->id, sts?sts:""); + tsched(Tdead); +} + +static void +thr0(void) +{ + run->main(run->argc, run->argv); + texits(nil); +} + +int +gettid(void) +{ + return run->id; +} + +int +newthr(char *tag, void (*f)(int, void*[]), int argc, void*argv[]) +{ + Thr *t; + static int once; + + t = trecycle(); + if(t == nil){ + t = mallocz(sizeof *t, 1); + if(t == nil) + sysfatal("newthr: no memory"); + t->tag = t; + t->stk = malloc(Stack); + if(t->stk == nil) + sysfatal("newthr: no memory"); + } + t->id = ++tidgen; + t->name = strdup(tag); + if(t->tag == nil) + sysfatal("newthr: no memory"); + t->state = Trdy; + t->main = f; + t->argc = argc; + t->argv = malloc(sizeof(void*)*argc); + if(t->argv == nil) + sysfatal("newthr: no memory"); + memmove(t->argv, argv, sizeof(void*)*argc); + t->label[JMPBUFPC] = (uintptr)thr0; + t->label[JMPBUFSP] = (uintptr)(t->stk + Stack - 2 * sizeof(ulong*)); + trdy(t); + DBG("newthr %s!%s %d\n", argv0, t->name, t->id); + /* + * The first call does not return, and jumps to the new thread. + */ + if(once == 0){ + once = 1; + tsched(Trdy); + } + return t->id; +} + +int +tsyscall(int nr, ...) +{ + run->scall = nr; + va_start(run->sarg, nr); + nixcall(run, 1); + tsched(Tsys); + va_end(run->sarg); + return run->nr.sret; +} diff -r 986a76e92d0f -r 8be5a2c78a65 sys/src/libseg/mkfile --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sys/src/libseg/mkfile Thu Sep 15 10:37:17 2011 +0200 @@ -0,0 +1,16 @@ +objtype=amd64 + +#include +#include + +enum +{ + Maxname = 80, + Extra = 20, +}; + +void* +newseg(char *name, uvlong va, ulong len) +{ + static int once; + int fd, cfd; + char sname[Maxname+Extra], *s; + void *p; + +print("newseg %s %#llx %#lx\n", name, va, len); + /* race, but ok */ + if(once++ == 0) + if(bind("#g", "/mnt/seg", MREPL|MCREATE) < 0) + return nil; + s = seprint(sname, sname+Maxname, "/mnt/seg/%s", name); + if(s == sname+Maxname){ + werrstr("name too long"); + return nil; + } + if(access(sname, AEXIST) < 0){ + if(va & (va-1)){ + werrstr("unusual virtual address"); + return nil; + } + fd = create(sname, OREAD, 0640|DMDIR); + if(fd < 0) + return nil; + close(fd); + strecpy(s, sname+sizeof sname, "/ctl"); + cfd = open(sname, OWRITE); + *s = 0; + if(cfd < 0) + return nil; + if(fprint(cfd, "addr %#llux %#lux\n", va, len) < 0){ + close(cfd); +print("newseg %s ctl failed %r\n", name); + return nil; + } + } + p = segattach(SG_CEXEC, name, (void*)va, len); + if((uintptr)p == ~0) + sysfatal("segattach: %s %#llx, %r", name, va); + return p; +} + diff -r 986a76e92d0f -r 8be5a2c78a65 sys/src/libtube/mkfile --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sys/src/libtube/mkfile Thu Sep 15 10:37:17 2011 +0200 @@ -0,0 +1,17 @@ +objtype=amd64 + +#include +#include +#include + +enum +{ + Tnamelen = 16, + Tbufsz = 128, + Tsegsz = 64 * 1024, +}; + + +typedef struct Ntube Ntube; +typedef struct Tdir Tdir; + +struct Tdir +{ + Lock; + void *end; + long avail; + char name[Tnamelen]; + Ntube *t; + Tdir *next; +}; + +struct Ntube +{ + char name[Tnamelen]; + Tube* t; + Ntube* next; +}; + +static Tdir *dir; +static Lock tlck; + +int namedtubedebug; + +#define dprint if(namedtubedebug)print + +static void +dumpdir(char *s) +{ + Tdir *tl; + Ntube *nt; + + if(namedtubedebug == 0) + return; + if(s == nil) + print("named tubes:\n"); + else + print("%s:\n", s); + for(tl = dir; tl != nil; tl = tl->next){ + print("\t%s at %#p\n", tl->name, tl->t ? tl->t->t : nil); + for(nt = tl->t; nt != nil; nt = nt->next) + print("\t\t%s at %#p\n", nt->name, nt->t); + } +} + +static Tdir* +dirlookup(char *name, int mkit) +{ + Tdir *tl; + + dprint("dirlookup %s mk=%d\n", name, mkit); + lock(&tlck); + for(tl = dir; tl != nil; tl = tl->next) + if(strcmp(name, tl->name) == 0){ + break; + } + if(tl == nil && !mkit) + werrstr("segment not found"); + if(tl == nil && mkit){ + tl = newseg(name, 0, Tsegsz); + if(tl != nil){ + strncpy(tl->name, name, sizeof tl->name); + tl->end = &tl[1]; + tl->avail = Tsegsz; + tl->next = dir; + dir = tl; + } + dumpdir("after newseg"); + } + unlock(&tlck); + dprint("dirlookup %s: %#p\n", name, tl); + return tl; +} + +static Tube* +tubelookup(Tdir *dir, char *name, ulong elsz, ulong n, int mkit) +{ + Ntube *nt; + uchar *p; + + dprint("tubelookup %s elsz=%uld mk=%d\n", name, elsz, mkit); + if(elsz <= 0 || n <= 0){ + werrstr("bad argument"); + dprint("tubelookup %s: %r\n", name); + return nil; + } + lock(dir); + for(nt = dir->t; nt != nil; nt = nt->next) + if(strcmp(nt->name, name) == 0) + break; + if(nt == nil && !mkit){ + werrstr("tube not found"); + dprint("tubelookup %s: %r\n", name); + } + if(nt == nil && mkit){ + /* + * This may overflow the segment, and we'll trap in + * that case. + */ + dir->avail -= sizeof *nt + sizeof(Tube) + n*elsz; + if(dir->avail < 0){ + unlock(dir); + werrstr("segment exhausted"); + dprint("tubelookup %s: %r\n", name); + return nil; + } + p = dir->end; + nt = dir->end; + p += sizeof *nt; + dir->end = p; + strncpy(nt->name, name, sizeof nt->name); + nt->t = dir->end; + p += sizeof(Tube) + n*elsz; + dir->end = p; + nt->t->msz = elsz; + nt->t->tsz = n; + nt->t->nhole = n; + nt->next = dir->t; + dir->t = nt; + } + unlock(dir); + if(nt == nil) + return nil; + if(nt->t->msz != elsz){ + werrstr("wrong element size"); + dprint("tubelookup %s %r\n", name); + return nil; + } + dprint("tubelookup %s: found at %#p\n", name, nt->t); + return nt->t; +} + +/* + * Return a tube for name segmentname!tubename, + * creating any of them if mkit is true and it is not found. + */ +Tube* +namedtube(char *name, ulong msz, int n, int mkit) +{ + char *dir, *tname; + Tdir *tl; + Tube *t; + + dumpdir("dir before namedtube"); + name = strdup(name); + if(name == nil) + return nil; + tname = utfrune(name, '!'); + if(tname == nil){ + dir = "tubes"; + tname = name; + }else{ + dir = name; + *tname++ = 0; + } + t = nil; + tl = dirlookup(dir, mkit); + if(tl != nil) + t = tubelookup(tl, tname, msz, n, mkit); + free(name); + return t; +} diff -r 986a76e92d0f -r 8be5a2c78a65 sys/src/libtube/tube.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sys/src/libtube/tube.c Thu Sep 15 10:37:17 2011 +0200 @@ -0,0 +1,141 @@ +#include +#include +#include + +enum{Block, Dontblock, Already}; /* xsend() nb argument */ + +static void +coherence(void) +{ +} + +Tube* +newtube(ulong msz, ulong n) +{ + Tube *t; + + t = mallocz(sizeof *t + (msz+1) * n, 1); + t->msz = msz; + t->tsz = n; + t->nhole = n; + return t; +} + +void +freetube(Tube *t) +{ + free(t); +} + + +static int +xsend(Tube *t, void *p, int nb) +{ + int n; + uchar *c; + + assert(t != nil && p != nil); + if(nb != Already && downsem(&t->nhole, nb) < 0) + return -1; + n = ainc(&t->tl) - 1; + n %= t->tsz; + c = (uchar*)&t[1]; + c += (1+t->msz) * n; + memmove(c+1, p, t->msz); + coherence(); + *c = 1; + upsem(&t->nmsg); + return 0; +} + +static int +xrecv(Tube *t, void *p, int nb) +{ + int n; + uchar *c; + + assert(t != nil && p != nil); + if(nb != Already && downsem(&t->nmsg, nb) < 0) + return -1; + n = ainc(&t->hd) - 1; + n %= t->tsz; + c = (uchar*)&t[1]; + c += (1+t->msz) * n; + while(*c == 0) + sleep(0); + memmove(p, c+1, t->msz); + coherence(); + *c = 0; + upsem(&t->nhole); + return 0; +} + +void +tsend(Tube *t, void *p) +{ + xsend(t, p, Block); +} + +void +trecv(Tube *t, void *p) +{ + xrecv(t, p, Block); +} + +int +nbtsend(Tube *t, void *p) +{ + return xsend(t, p, Dontblock); +} + +int +nbtrecv(Tube *t, void *p) +{ + return xrecv(t, p, Dontblock); +} + +int +talt(Talt a[], int na) +{ + int i, n; + int **ss; + + assert(a != nil && na > 0); + ss = malloc(sizeof(int*) * na); + n = 0; + for(i = 0; i < na; i++) + switch(a[i].op){ + case TSND: + ss[n++] = &a[i].t->nhole; + break; + case TRCV: + ss[n++] = &a[i].t->nmsg; + break; + case TNBSND: + if(nbtsend(a[i].t, a[i].m) != -1) + return i; + break; + case TNBRCV: + if(nbtrecv(a[i].t, a[i].m) != -1) + return i; + break; + } + if(n == 0) + return -1; + i = altsems(ss, n); + free(ss); + if(i < 0) + return -1; + switch(a[i].op){ + case TSND: + xsend(a[i].t, a[i].m, Already); + break; + case TRCV: + xrecv(a[i].t, a[i].m, Already); + break; + default: + sysfatal("talt"); + } + return i; +} + diff -r 986a76e92d0f -r 8be5a2c78a65 sys/src/mkfile --- a/sys/src/mkfile Thu Sep 15 10:32:14 2011 +0200 +++ b/sys/src/mkfile Thu Sep 15 10:37:17 2011 +0200 @@ -30,9 +30,11 @@ libregexp\ libscribble\ libsec\ + libseg\ libstdio\ libsunrpc\ libthread\ + libtube\ libventi\ @@ -49,6 +51,7 @@ date for (i in $LIBS $SUBSYS $CMDS) @{ cd $i + echo cd $i mk $target } date