diff options
author | Taru Karttunen <taruti@taruti.net> | 2011-03-30 15:46:40 +0300 |
---|---|---|
committer | Taru Karttunen <taruti@taruti.net> | 2011-03-30 15:46:40 +0300 |
commit | e5888a1ffdae813d7575f5fb02275c6bb07e5199 (patch) | |
tree | d8d51eac403f07814b9e936eed0c9a79195e2450 /sys/src/cmd/execnet |
Import sources from 2011-03-30 iso image
Diffstat (limited to 'sys/src/cmd/execnet')
-rwxr-xr-x | sys/src/cmd/execnet/client.c | 432 | ||||
-rwxr-xr-x | sys/src/cmd/execnet/dat.h | 63 | ||||
-rwxr-xr-x | sys/src/cmd/execnet/fs.c | 451 | ||||
-rwxr-xr-x | sys/src/cmd/execnet/main.c | 51 | ||||
-rwxr-xr-x | sys/src/cmd/execnet/mkfile | 20 | ||||
-rwxr-xr-x | sys/src/cmd/execnet/note.c | 144 |
6 files changed, 1161 insertions, 0 deletions
diff --git a/sys/src/cmd/execnet/client.c b/sys/src/cmd/execnet/client.c new file mode 100755 index 000000000..57414966d --- /dev/null +++ b/sys/src/cmd/execnet/client.c @@ -0,0 +1,432 @@ +#include <u.h> +#include <libc.h> +#include <fcall.h> +#include <thread.h> +#include <9p.h> +#include "dat.h" + +int nclient; +Client **client; +#define Zmsg ((Msg*)~0) +char nocmd[] = ""; + +static void readthread(void*); +static void writethread(void*); +static void kickwriter(Client*); + +int +newclient(void) +{ + int i; + Client *c; + + for(i=0; i<nclient; i++) + if(client[i]->ref==0 && !client[i]->moribund) + return i; + + c = emalloc(sizeof(Client)); + c->writerkick = chancreate(sizeof(void*), 1); + c->execpid = chancreate(sizeof(ulong), 0); + c->cmd = nocmd; + + c->readerproc = ioproc(); + c->writerproc = ioproc(); + c->num = nclient; + if(nclient%16 == 0) + client = erealloc(client, (nclient+16)*sizeof(client[0])); + client[nclient++] = c; + return nclient-1; +} + +void +die(Client *c) +{ + Msg *m, *next; + Req *r, *rnext; + + c->moribund = 1; + kickwriter(c); + iointerrupt(c->readerproc); + iointerrupt(c->writerproc); + if(--c->activethread == 0){ + if(c->cmd != nocmd){ + free(c->cmd); + c->cmd = nocmd; + } + c->pid = 0; + c->moribund = 0; + c->status = Closed; + for(m=c->mq; m && m != Zmsg; m=next){ + next = m->link; + free(m); + } + c->mq = nil; + if(c->rq != nil){ + for(r=c->rq; r; r=rnext){ + rnext = r->aux; + respond(r, "hangup"); + } + c->rq = nil; + } + if(c->wq != nil){ + for(r=c->wq; r; r=rnext){ + rnext = r->aux; + respond(r, "hangup"); + } + c->wq = nil; + } + c->rq = nil; + c->wq = nil; + c->emq = nil; + c->erq = nil; + c->ewq = nil; + } +} + +void +closeclient(Client *c) +{ + if(--c->ref == 0){ + if(c->pid > 0) + postnote(PNPROC, c->pid, "kill"); + c->status = Hangup; + close(c->fd[0]); + c->fd[0] = c->fd[1] = -1; + c->moribund = 1; + kickwriter(c); + iointerrupt(c->readerproc); + iointerrupt(c->writerproc); + c->activethread++; + die(c); + } +} + +void +queuerdreq(Client *c, Req *r) +{ + if(c->rq==nil) + c->erq = &c->rq; + *c->erq = r; + r->aux = nil; + c->erq = (Req**)&r->aux; +} + +void +queuewrreq(Client *c, Req *r) +{ + if(c->wq==nil) + c->ewq = &c->wq; + *c->ewq = r; + r->aux = nil; + c->ewq = (Req**)&r->aux; +} + +void +queuemsg(Client *c, Msg *m) +{ + if(c->mq==nil) + c->emq = &c->mq; + *c->emq = m; + if(m != Zmsg){ + m->link = nil; + c->emq = (Msg**)&m->link; + }else + c->emq = nil; +} + +void +matchmsgs(Client *c) +{ + Req *r; + Msg *m; + int n, rm; + + while(c->rq && c->mq){ + r = c->rq; + c->rq = r->aux; + + rm = 0; + m = c->mq; + if(m == Zmsg){ + respond(r, "execnet: no more data"); + break; + } + n = r->ifcall.count; + if(n >= m->ep - m->rp){ + n = m->ep - m->rp; + c->mq = m->link; + rm = 1; + } + if(n) + memmove(r->ofcall.data, m->rp, n); + if(rm) + free(m); + else + m->rp += n; + r->ofcall.count = n; + respond(r, nil); + } +} + +void +findrdreq(Client *c, Req *r) +{ + Req **l; + + for(l=&c->rq; *l; l=(Req**)&(*l)->aux){ + if(*l == r){ + *l = r->aux; + if(*l == nil) + c->erq = l; + respond(r, "flushed"); + break; + } + } +} + +void +findwrreq(Client *c, Req *r) +{ + Req **l; + + for(l=&c->wq; *l; l=(Req**)&(*l)->aux){ + if(*l == r){ + *l = r->aux; + if(*l == nil) + c->ewq = l; + respond(r, "flushed"); + return; + } + } +} + +void +dataread(Req *r, Client *c) +{ + queuerdreq(c, r); + matchmsgs(c); +} + +static void +readthread(void *a) +{ + uchar *buf; + int n; + Client *c; + Ioproc *io; + Msg *m; + char tmp[32]; + + c = a; + snprint(tmp, sizeof tmp, "read%d", c->num); + threadsetname(tmp); + + buf = emalloc(8192); + io = c->readerproc; + while((n = ioread(io, c->fd[0], buf, 8192)) >= 0){ + m = emalloc(sizeof(Msg)+n); + m->rp = (uchar*)&m[1]; + m->ep = m->rp + n; + if(n) + memmove(m->rp, buf, n); + queuemsg(c, m); + matchmsgs(c); + } + queuemsg(c, Zmsg); + free(buf); + die(c); +} + +static void +kickwriter(Client *c) +{ + nbsendp(c->writerkick, nil); +} + +void +clientflush(Req *or, Client *c) +{ + if(or->ifcall.type == Tread) + findrdreq(c, or); + else{ + if(c->execreq == or){ + c->execreq = nil; + iointerrupt(c->writerproc); + } + findwrreq(c, or); + if(c->curw == or){ + c->curw = nil; + iointerrupt(c->writerproc); + kickwriter(c); + } + } +} + +void +datawrite(Req *r, Client *c) +{ + queuewrreq(c, r); + kickwriter(c); +} + +static void +writethread(void *a) +{ + char e[ERRMAX]; + uchar *buf; + int n; + Ioproc *io; + Req *r; + Client *c; + char tmp[32]; + + c = a; + snprint(tmp, sizeof tmp, "write%d", c->num); + threadsetname(tmp); + + buf = emalloc(8192); + io = c->writerproc; + for(;;){ + while(c->wq == nil){ + if(c->moribund) + goto Out; + recvp(c->writerkick); + if(c->moribund) + goto Out; + } + r = c->wq; + c->wq = r->aux; + c->curw = r; + n = iowrite(io, c->fd[1], r->ifcall.data, r->ifcall.count); + if(chatty9p) + fprint(2, "io->write returns %d\n", n); + if(n >= 0){ + r->ofcall.count = n; + respond(r, nil); + }else{ + rerrstr(e, sizeof e); + respond(r, e); + } + } +Out: + free(buf); + die(c); +} + +static void +execproc(void *a) +{ + int i, fd; + Client *c; + char tmp[32]; + + c = a; + snprint(tmp, sizeof tmp, "execproc%d", c->num); + threadsetname(tmp); + if(pipe(c->fd) < 0){ + rerrstr(c->err, sizeof c->err); + sendul(c->execpid, -1); + return; + } + rfork(RFFDG); + fd = c->fd[1]; + close(c->fd[0]); + dup(fd, 0); + dup(fd, 1); + for(i=3; i<100; i++) /* should do better */ + close(i); + strcpy(c->err, "exec failed"); + procexecl(c->execpid, "/bin/rc", "rc", "-c", c->cmd, nil); +} + +static void +execthread(void *a) +{ + Client *c; + int p; + char tmp[32]; + + c = a; + snprint(tmp, sizeof tmp, "exec%d", c->num); + threadsetname(tmp); + c->execpid = chancreate(sizeof(ulong), 0); + proccreate(execproc, c, STACK); + p = recvul(c->execpid); + chanfree(c->execpid); + c->execpid = nil; + close(c->fd[1]); + c->fd[1] = c->fd[0]; + if(p != -1){ + c->pid = p; + c->activethread = 2; + threadcreate(readthread, c, STACK); + threadcreate(writethread, c, STACK); + if(c->execreq) + respond(c->execreq, nil); + }else{ + if(c->execreq) + respond(c->execreq, c->err); + } +} + +void +ctlwrite(Req *r, Client *c) +{ + char *f[3], *s, *p; + int nf; + + s = emalloc(r->ifcall.count+1); + memmove(s, r->ifcall.data, r->ifcall.count); + s[r->ifcall.count] = '\0'; + + f[0] = s; + p = strchr(s, ' '); + if(p == nil) + nf = 1; + else{ + *p++ = '\0'; + f[1] = p; + nf = 2; + } + + if(f[0][0] == '\0'){ + free(s); + respond(r, nil); + return; + } + + r->ofcall.count = r->ifcall.count; + if(strcmp(f[0], "hangup") == 0){ + if(c->pid == 0){ + respond(r, "connection already hung up"); + goto Out; + } + postnote(PNPROC, c->pid, "kill"); + respond(r, nil); + goto Out; + } + + if(strcmp(f[0], "connect") == 0){ + if(c->cmd != nocmd){ + respond(r, "already have connection"); + goto Out; + } + if(nf == 1){ + respond(r, "need argument to connect"); + goto Out; + } + c->status = Exec; + if(p = strrchr(f[1], '!')) + *p = '\0'; + c->cmd = emalloc(4+1+strlen(f[1])+1); + strcpy(c->cmd, "exec "); + strcat(c->cmd, f[1]); + c->execreq = r; + threadcreate(execthread, c, STACK); + goto Out; + } + + respond(r, "bad or inappropriate control message"); +Out: + free(s); +} diff --git a/sys/src/cmd/execnet/dat.h b/sys/src/cmd/execnet/dat.h new file mode 100755 index 000000000..8c9c17db3 --- /dev/null +++ b/sys/src/cmd/execnet/dat.h @@ -0,0 +1,63 @@ +typedef struct Msg Msg; +struct Msg +{ + Msg *link; + uchar *rp; + uchar *ep; +}; + +typedef struct Client Client; +struct Client +{ + int moribund; + int activethread; + int num; + int ref; + int status; + int pid; + char *cmd; + int fd[2]; + char err[ERRMAX]; + + Req *execreq; + Channel *execpid; + + Req *rq, **erq; /* reading */ + Msg *mq, **emq; + Ioproc *readerproc; + + Channel *writerkick; + Req *wq, **ewq; /* writing */ + Req *curw; /* currently writing */ + Ioproc *writerproc; /* writing */ +}; +extern int nclient; +extern Client **client; +extern void dataread(Req*, Client*); +extern int newclient(void); +extern void closeclient(Client*); +extern void datawrite(Req*, Client*); +extern void ctlwrite(Req*, Client*); +extern void clientflush(Req*, Client*); + +#define emalloc emalloc9p +#define estrdup estrdup9p +#define erealloc erealloc9p + +extern Srv fs; +extern void initfs(void); +extern void setexecname(char*); + +enum +{ + STACK = 8192, +}; + +enum /* Client.status */ +{ + Closed, + Exec, + Established, + Hangup, +}; + diff --git a/sys/src/cmd/execnet/fs.c b/sys/src/cmd/execnet/fs.c new file mode 100755 index 000000000..7f734358b --- /dev/null +++ b/sys/src/cmd/execnet/fs.c @@ -0,0 +1,451 @@ +/* + * ``Exec'' network device. Mounted on net, provides /net/exec. + * + * exec protocol directory + * n connection directory + * ctl control messages (like connect) + * data data + * err errors + * local local address (pid of command) + * remote remote address (command) + * status status + */ + +#include <u.h> +#include <libc.h> +#include <fcall.h> +#include <thread.h> +#include <9p.h> +#include "dat.h" + +int fsdebug; + +enum +{ + Qroot, + Qexec, + Qclone, + Qn, + Qctl, + Qdata, + Qlocal, + Qremote, + Qstatus, +}; + +#define PATH(type, n) ((type)|((n)<<8)) +#define TYPE(path) ((int)(path) & 0xFF) +#define NUM(path) ((uint)(path)>>8) + +typedef struct Tab Tab; +struct Tab +{ + char *name; + ulong mode; +}; + +Tab tab[] = +{ + "/", DMDIR|0555, + "exec", DMDIR|0555, + "clone", 0666, + nil, DMDIR|0555, + "ctl", 0666, + "data", 0666, + "local", 0444, + "remote", 0444, + "status", 0444, +}; + +void +setexecname(char *s) +{ + tab[Qexec].name = s; +} + +ulong time0; + +static void +fillstat(Dir *d, ulong path) +{ + Tab *t; + int type; + char buf[32]; + + memset(d, 0, sizeof(*d)); + d->uid = estrdup("exec"); + d->gid = estrdup("exec"); + d->qid.path = path; + d->atime = d->mtime = time0; + d->length = 0; + + type = TYPE(path); + t = &tab[type]; + if(t->name) + d->name = estrdup(t->name); + else{ + snprint(buf, sizeof buf, "%ud", NUM(path)); + d->name = estrdup(buf); + } + d->qid.type = t->mode>>24; + d->mode = t->mode; +} + +static void +fsstat(Req *r) +{ + fillstat(&r->d, r->fid->qid.path); + respond(r, nil); +} + +static int +rootgen(int i, Dir *d, void*) +{ + if(i < 1){ + fillstat(d, PATH(Qexec, 0)); + return 0; + } + return -1; +} + +static int +execgen(int i, Dir *d, void*) +{ + if(i < 1){ + fillstat(d, PATH(Qclone, 0)); + return 0; + } + i -= 1; + + if(i < nclient){ + fillstat(d, PATH(Qn, i)); + return 0; + } + return -1; +} + +static int +conngen(int i, Dir *d, void *aux) +{ + Client *c; + + c = aux; + i += Qn+1; + if(i <= Qstatus){ + fillstat(d, PATH(i, c->num)); + return 0; + } + return -1; +} + +char *statusstr[] = +{ + "Closed", + "Exec", + "Established", + "Hangup", +}; + +static void +fsread(Req *r) +{ + char e[ERRMAX], *s; + ulong path; + + path = r->fid->qid.path; + switch(TYPE(path)){ + default: + snprint(e, sizeof e, "bug in execnet path=%lux", path); + respond(r, e); + break; + + case Qroot: + dirread9p(r, rootgen, nil); + respond(r, nil); + break; + + case Qexec: + dirread9p(r, execgen, nil); + respond(r, nil); + break; + + case Qn: + dirread9p(r, conngen, client[NUM(path)]); + respond(r, nil); + break; + + case Qctl: + snprint(e, sizeof e, "%ud", NUM(path)); + readstr(r, e); + respond(r, nil); + break; + + case Qdata: + dataread(r, client[NUM(path)]); + break; + + case Qlocal: + snprint(e, sizeof e, "%d", client[NUM(path)]->pid); + readstr(r, e); + respond(r, nil); + break; + + case Qremote: + s = client[NUM(path)]->cmd; + if(strlen(s) >= 5) /* "exec " */ + readstr(r, s+5); + else + readstr(r, s); + respond(r, nil); + break; + + case Qstatus: + readstr(r, statusstr[client[NUM(path)]->status]); + respond(r, nil); + break; + } +} + +static void +fswrite(Req *r) +{ + char e[ERRMAX]; + ulong path; + + path = r->fid->qid.path; + switch(TYPE(path)){ + default: + snprint(e, sizeof e, "bug in execnet path=%lux", path); + respond(r, e); + break; + + case Qctl: + ctlwrite(r, client[NUM(path)]); + break; + + case Qdata: + datawrite(r, client[NUM(path)]); + break; + } +} + + +static void +fsflush(Req *r) +{ + ulong path; + Req *or; + + for(or=r; or->ifcall.type==Tflush; or=or->oldreq) + ; + + if(or->ifcall.type != Tread && or->ifcall.type != Twrite) + abort(); + + path = or->fid->qid.path; + if(TYPE(path) != Qdata) + abort(); + + clientflush(or, client[NUM(path)]); + respond(r, nil); +} + +static void +fsattach(Req *r) +{ + if(r->ifcall.aname && r->ifcall.aname[0]){ + respond(r, "invalid attach specifier"); + return; + } + r->fid->qid.path = PATH(Qroot, 0); + r->fid->qid.type = QTDIR; + r->fid->qid.vers = 0; + r->ofcall.qid = r->fid->qid; + respond(r, nil); +} + +static char* +fswalk1(Fid *fid, char *name, Qid *qid) +{ + char buf[32]; + int i, n; + ulong path; + + if(!(fid->qid.type&QTDIR)) + return "walk in non-directory"; + + path = fid->qid.path; + if(strcmp(name, "..") == 0){ + switch(TYPE(path)){ + case Qn: + qid->path = PATH(Qexec, 0); + qid->type = QTDIR; + return nil; + case Qroot: + case Qexec: + qid->path = PATH(Qroot, 0); + qid->type = QTDIR; + return nil; + default: + return "bug in fswalk1"; + } + } + + i = TYPE(path)+1; + for(; i<nelem(tab); i++){ + if(i==Qn){ + n = atoi(name); + snprint(buf, sizeof buf, "%d", n); + if(n < nclient && strcmp(buf, name) == 0){ + qid->path = PATH(Qn, n); + qid->type = QTDIR; + return nil; + } + break; + } + if(strcmp(tab[i].name, name) == 0){ + qid->path = PATH(i, NUM(path)); + qid->type = tab[i].mode>>24; + return nil; + } + if(tab[i].mode&DMDIR) + break; + } + return "directory entry not found"; +} + +static void +fsopen(Req *r) +{ + static int need[4] = { 4, 2, 6, 1 }; + ulong path; + int n; + Tab *t; + + /* + * lib9p already handles the blatantly obvious. + * we just have to enforce the permissions we have set. + */ + path = r->fid->qid.path; + t = &tab[TYPE(path)]; + n = need[r->ifcall.mode&3]; + if((n&t->mode) != n){ + respond(r, "permission denied"); + return; + } + + switch(TYPE(path)){ + case Qclone: + n = newclient(); + path = PATH(Qctl, n); + r->fid->qid.path = path; + r->ofcall.qid.path = path; + if(fsdebug) + fprint(2, "open clone => path=%lux\n", path); + t = &tab[Qctl]; + /* fall through */ + default: + if(t-tab >= Qn) + client[NUM(path)]->ref++; + respond(r, nil); + break; + } +} + +Channel *cclunk; +Channel *cclunkwait; +Channel *creq; +Channel *creqwait; + +static void +fsthread(void*) +{ + ulong path; + Alt a[3]; + Fid *fid; + Req *r; + + threadsetname("fsthread"); + + a[0].op = CHANRCV; + a[0].c = cclunk; + a[0].v = &fid; + a[1].op = CHANRCV; + a[1].c = creq; + a[1].v = &r; + a[2].op = CHANEND; + + for(;;){ + switch(alt(a)){ + case 0: + path = fid->qid.path; + if(fid->omode != -1 && TYPE(path) >= Qn) + closeclient(client[NUM(path)]); + sendp(cclunkwait, nil); + break; + case 1: + switch(r->ifcall.type){ + case Tattach: + fsattach(r); + break; + case Topen: + fsopen(r); + break; + case Tread: + fsread(r); + break; + case Twrite: + fswrite(r); + break; + case Tstat: + fsstat(r); + break; + case Tflush: + fsflush(r); + break; + default: + respond(r, "bug in fsthread"); + break; + } + sendp(creqwait, 0); + break; + } + } +} + +static void +fsdestroyfid(Fid *fid) +{ + sendp(cclunk, fid); + recvp(cclunkwait); +} + +static void +fssend(Req *r) +{ + sendp(creq, r); + recvp(creqwait); /* avoids need to deal with spurious flushes */ +} + +void +initfs(void) +{ + time0 = time(0); + creq = chancreate(sizeof(void*), 0); + creqwait = chancreate(sizeof(void*), 0); + cclunk = chancreate(sizeof(void*), 0); + cclunkwait = chancreate(sizeof(void*), 0); + procrfork(fsthread, nil, STACK, RFNAMEG); +} + +Srv fs = +{ +.attach= fssend, +.destroyfid= fsdestroyfid, +.walk1= fswalk1, +.open= fssend, +.read= fssend, +.write= fssend, +.stat= fssend, +.flush= fssend, +}; diff --git a/sys/src/cmd/execnet/main.c b/sys/src/cmd/execnet/main.c new file mode 100755 index 000000000..e24f63ccc --- /dev/null +++ b/sys/src/cmd/execnet/main.c @@ -0,0 +1,51 @@ +#include <u.h> +#include <libc.h> +#include <fcall.h> +#include <thread.h> +#include <9p.h> +#include "dat.h" + +void +usage(void) +{ + fprint(2, "usage: execnet [-n exec] [/net]\n"); + exits("usage"); +} + +void +threadmain(int argc, char **argv) +{ + char *net; + +//extern long _threaddebuglevel; +//_threaddebuglevel = 1<<20; /* DBGNOTE */ + + rfork(RFNOTEG); + ARGBEGIN{ + case 'D': + chatty9p++; + break; + case 'n': + setexecname(EARGF(usage())); + break; + }ARGEND + + switch(argc){ + default: + usage(); + case 0: + net = "/net"; + break; + case 1: + net = argv[0]; + break; + } + + quotefmtinstall(); + + initfs(); + threadpostmountsrv(&fs, nil, net, MBEFORE); + threadexits(nil); +} + + diff --git a/sys/src/cmd/execnet/mkfile b/sys/src/cmd/execnet/mkfile new file mode 100755 index 000000000..10724b83f --- /dev/null +++ b/sys/src/cmd/execnet/mkfile @@ -0,0 +1,20 @@ +</$objtype/mkfile + +TARG=execnet + +OFILES=\ + client.$O\ + fs.$O\ + main.$O\ + note.$O\ + +HFILES=dat.h + +BIN=/$objtype/bin +UPDATE=\ + mkfile\ + $HFILES\ + ${OFILES:%.$O=%.c}\ + ${TARG:%=/386/bin/%}\ + +</sys/src/cmd/mkone diff --git a/sys/src/cmd/execnet/note.c b/sys/src/cmd/execnet/note.c new file mode 100755 index 000000000..be968f50b --- /dev/null +++ b/sys/src/cmd/execnet/note.c @@ -0,0 +1,144 @@ +/* BUG BUG BUG */ + +#include <u.h> +#include <libc.h> +#include <thread.h> +#include "/sys/src/libthread/threadimpl.h" + +int _threadnopasser; + +#define NFN 33 +#define ERRLEN 48 +typedef struct Note Note; +struct Note +{ + Lock inuse; + Proc *proc; /* recipient */ + char s[ERRMAX]; /* arg2 */ +}; + +static Note notes[128]; +static Note *enotes = notes+nelem(notes); +static int (*onnote[NFN])(void*, char*); +static int onnotepid[NFN]; +static Lock onnotelock; + +int +threadnotify(int (*f)(void*, char*), int in) +{ + int i, topid; + int (*from)(void*, char*), (*to)(void*, char*); + + if(in){ + from = nil; + to = f; + topid = _threadgetproc()->pid; + }else{ + from = f; + to = nil; + topid = 0; + } + lock(&onnotelock); + for(i=0; i<NFN; i++) + if(onnote[i]==from){ + onnote[i] = to; + onnotepid[i] = topid; + break; + } + unlock(&onnotelock); + return i<NFN; +} + +static void +delayednotes(Proc *p, void *v) +{ + int i; + Note *n; + int (*fn)(void*, char*); + + if(!p->pending) + return; + + p->pending = 0; + for(n=notes; n<enotes; n++){ + if(n->proc == p){ + for(i=0; i<NFN; i++){ + if(onnotepid[i]!=p->pid || (fn = onnote[i])==nil) + continue; + if((*fn)(v, n->s)) + break; + } + if(i==NFN){ + _threaddebug(DBGNOTE, "Unhandled note %s, proc %p\n", n->s, p); + if(v != nil) + noted(NDFLT); + else if(strncmp(n->s, "sys:", 4)==0) + abort(); + threadexitsall(n->s); + } + n->proc = nil; + unlock(&n->inuse); + } + } +} + +void +_threadnote(void *v, char *s) +{ + Proc *p; + Note *n; + + _threaddebug(DBGNOTE, "Got note %s", s); +// if(strncmp(s, "sys:", 4) == 0) +// noted(NDFLT); + +// if(_threadexitsallstatus){ +// _threaddebug(DBGNOTE, "Threadexitsallstatus = '%s'\n", _threadexitsallstatus); +// _exits(_threadexitsallstatus); +// } + + if(strcmp(s, "threadint")==0) + noted(NCONT); + + p = _threadgetproc(); + if(p == nil) + noted(NDFLT); + + for(n=notes; n<enotes; n++) + if(canlock(&n->inuse)) + break; + if(n==enotes) + sysfatal("libthread: too many delayed notes"); + utfecpy(n->s, n->s+ERRMAX, s); + n->proc = p; + p->pending = 1; + if(!p->splhi) + delayednotes(p, v); + noted(NCONT); +} + +int +_procsplhi(void) +{ + int s; + Proc *p; + + p = _threadgetproc(); + s = p->splhi; + p->splhi = 1; + return s; +} + +void +_procsplx(int s) +{ + Proc *p; + + p = _threadgetproc(); + p->splhi = s; + if(s) + return; + if(p->pending) + delayednotes(p, nil); +} + |