diff --git a/sys/src/cmd/5e/5e.c b/sys/src/cmd/5e/5e.c index b2f23674c..fb589e54c 100644 --- a/sys/src/cmd/5e/5e.c +++ b/sys/src/cmd/5e/5e.c @@ -67,6 +67,19 @@ suicide(char *fmt, ...) abort(); } +int +notehandler(void *, char *note) +{ + if(strncmp(note, "sys:", 4) == 0) + return 0; + + if(strncmp(note, "emu:", 4) == 0) + exits(note); + + addnote(note); + return 1; +} + void main(int argc, char **argv) { @@ -90,9 +103,14 @@ main(int argc, char **argv) initproc(); if(loadtext(argv[0], argc, argv) < 0) sysfatal("%r"); + atnotify(notehandler, 1); for(;;) { if(ultraverbose) dump(); step(); + while((P->notein - P->noteout) % NNOTE) { + donote(P->notes[P->noteout % NNOTE], 0); + ainc(&P->noteout); + } } } diff --git a/sys/src/cmd/5e/dat.h b/sys/src/cmd/5e/dat.h index 63499bc97..153b99ee3 100644 --- a/sys/src/cmd/5e/dat.h +++ b/sys/src/cmd/5e/dat.h @@ -5,10 +5,8 @@ typedef struct Fd Fd; enum { STACKSIZE = 0x100000, - NAMEMAX = 27, - - FDBLOCK = 16, + NNOTE = 5, SEGNUM = 8, flN = 1<<31, @@ -26,15 +24,24 @@ enum { }; struct Process { - Segment *S[SEGNUM]; + Process *prev, *next; /* linked list (for fs) */ + int pid; + char name[NAMEMAX+1]; /* name for status file */ + Ref *path; /* Ref + string data */ + + Segment *S[SEGNUM]; /* memory */ u32int R[16]; /* general purpose registers / PC (R15) */ u32int CPSR; /* status register */ + char errbuf[ERRMAX]; - char name[NAMEMAX+1]; - Ref *path; /* Ref + string data */ - Fd *fd; - int pid; - Process *prev, *next; + Fd *fd; /* bitmap of OCEXEC files */ + + /* note handling */ + u32int notehandler; + int innote; + jmp_buf notejmp; + char notes[ERRMAX][NNOTE]; + long notein, noteout; }; extern void **_privates; @@ -69,4 +76,3 @@ struct Fd { #define havesymbols 0 #define ultraverbose 0 #define systrace 0 - diff --git a/sys/src/cmd/5e/fns.h b/sys/src/cmd/5e/fns.h index a28f5f433..e3966136f 100644 --- a/sys/src/cmd/5e/fns.h +++ b/sys/src/cmd/5e/fns.h @@ -27,3 +27,6 @@ void fdclear(Fd *); void addproc(Process *); void remproc(Process *); Process *findproc(int); +void donote(char *, ulong); +void addnote(char *); +void dump(void); diff --git a/sys/src/cmd/5e/proc.c b/sys/src/cmd/5e/proc.c index fa1dc9aad..2639ea696 100644 --- a/sys/src/cmd/5e/proc.c +++ b/sys/src/cmd/5e/proc.c @@ -181,6 +181,7 @@ loadtext(char *file, int argc, char **argv) return -1; } copyname(file); + P->notehandler = P->innote = P->notein = P->noteout = 0; freesegs(); memset(P->R, 0, sizeof(P->R)); P->CPSR = 0; @@ -315,3 +316,66 @@ fdclear(Fd *fd) fd->fds = nil; wunlock(fd); } + +/* call this from a notehandler if you don't want the front to fall off */ +void +addnote(char *msg) +{ + int new; + + new = P->notein + 1; + if((new - P->noteout) % NNOTE == 0) + return; + + strncpy(P->notes[P->notein % NNOTE], msg, ERRMAX - 1); + P->notein = new; +} + +/* the following code is not for the weak of heart */ +void +donote(char *msg, ulong type) +{ + int rc; + u32int *ureg, *sp, uregp, msgp; + char *msgb; + + if(P->notehandler == 0) + exits(msg); + + uregp = P->R[13] - 18 * 4; + ureg = vaddrnol(uregp, 18 * 4); + memcpy(ureg, P->R, 15 * 4); + ureg[15] = type; + ureg[16] = P->CPSR; + ureg[17] = P->R[15]; + P->R[13] = uregp; + msgp = P->R[13] -= strlen(msg) + 1; + msgb = vaddrnol(msgp, strlen(msg) + 1); + strcpy(msgb, msg); + P->R[13] -= 3 * 4; + sp = vaddrnol(P->R[13], 3 * 4); + sp[0] = 0; + sp[2] = msgp; + P->R[0] = uregp; + P->R[15] = P->notehandler; + P->innote = 1; + switch(rc = setjmp(P->notejmp) - 1) { + case -1: + for(;;) { + if(ultraverbose) + dump(); + step(); + } + case NDFLT: + exits(msg); + case NCONT: + break; + default: + sysfatal("unhandled noted argument %d", rc); + } + P->innote = 0; + ureg = vaddrnol(uregp, 18 * 4); /* just to be sure */ + memcpy(P->R, ureg, 15 * 4); + P->CPSR = ureg[16]; + P->R[15] = ureg[17]; +} diff --git a/sys/src/cmd/5e/seg.c b/sys/src/cmd/5e/seg.c index 1cde88241..66613baff 100644 --- a/sys/src/cmd/5e/seg.c +++ b/sys/src/cmd/5e/seg.c @@ -94,6 +94,7 @@ copyifnec(u32int addr, int len, int *copied) if(len < 0) len = strlen(targ) + 1; ret = emalloc(len); + setmalloctag(ret, getcallerpc(&addr)); memcpy(ret, targ, len); segunlock(seg); *copied = 1; @@ -103,7 +104,7 @@ copyifnec(u32int addr, int len, int *copied) void * bufifnec(u32int addr, int len, int *buffered) { - void *targ; + void *targ, *v; Segment *seg; targ = vaddr(addr, len, &seg); @@ -113,7 +114,9 @@ bufifnec(u32int addr, int len, int *buffered) } segunlock(seg); *buffered = 1; - return emalloc(len); + v = emalloc(len); + setmalloctag(v, getcallerpc(&addr)); + return v; } void @@ -122,8 +125,10 @@ copyback(u32int addr, int len, void *data) void *targ; Segment *seg; - if(len <= 0) + if(len <= 0) { + free(data); return; + } targ = vaddr(addr, len, &seg); memmove(targ, data, len); segunlock(seg); diff --git a/sys/src/cmd/5e/sys.c b/sys/src/cmd/5e/sys.c index daa02e0c7..0f9fb1c03 100644 --- a/sys/src/cmd/5e/sys.c +++ b/sys/src/cmd/5e/sys.c @@ -196,6 +196,46 @@ sysfstat(void) copyback(edir, P->R[0], edirt); } +static void +syswstat(void) +{ + u32int name, edir, nedir; + char *namet; + void *edirt; + int copied, copied2; + + name = arg(0); + namet = copyifnec(name, -1, &copied); + edir = arg(1); + nedir = arg(2); + edirt = copyifnec(edir, nedir, &copied2); + if(systrace) + fprint(2, "wstat(%#ux=\"%s\", %#ux, %ud)\n", name, namet, edir, nedir); + P->R[0] = noteerr(wstat(namet, edirt, nedir), nedir); + if(copied) + free(namet); + if(copied2) + free(edirt); +} + +static void +sysfwstat(void) +{ + u32int fd, edir, nedir; + void *edirt; + int copied; + + fd = arg(0); + edir = arg(1); + nedir = arg(2); + edirt = copyifnec(edir, nedir, &copied); + if(systrace) + fprint(2, "fwstat(%d, %#ux, %d)\n", fd, edir, nedir); + P->R[0] = noteerr(fwstat(fd, edirt, nedir), nedir); + if(copied) + free(edirt); +} + static void sysexits(void) { @@ -266,6 +306,27 @@ syschdir(void) static void sysnotify(void) { + u32int handler; + + handler = arg(0); + if(systrace) + fprint(2, "notify(%#ux)\n", handler); + P->notehandler = handler; + P->R[0] = 0; +} + +static void +sysnoted(void) +{ + u32int v; + + v = arg(0); + if(systrace) + fprint(2, "noted(%d)\n", v); + if(P->innote) + longjmp(P->notejmp, v + 1); + cherrstr("the front fell off"); + P->R[0] = -1; } static void @@ -541,6 +602,17 @@ sysremove(void) free(filet); } +static void +sysalarm(void) +{ + u32int msec; + + msec = arg(0); + if(systrace) + fprint(2, "alarm(%d)\n", msec); + P->R[0] = alarm(msec); +} + void syscall(void) { @@ -556,10 +628,13 @@ syscall(void) [ERRSTR] syserrstr, [STAT] sysstat, [FSTAT] sysfstat, + [WSTAT] syswstat, + [FWSTAT] sysfwstat, [SEEK] sysseek, [CHDIR] syschdir, [FD2PATH] sysfd2path, [NOTIFY] sysnotify, + [NOTED] sysnoted, [RFORK] sysrfork, [EXEC] sysexec, [AWAIT] sysawait, @@ -571,6 +646,7 @@ syscall(void) [DUP] sysdup, [MOUNT] sysmount, [REMOVE] sysremove, + [ALARM] sysalarm, }; n = P->R[0]; diff --git a/sys/src/cmd/5e/util.c b/sys/src/cmd/5e/util.c index dc9efa424..49818f907 100644 --- a/sys/src/cmd/5e/util.c +++ b/sys/src/cmd/5e/util.c @@ -12,6 +12,7 @@ emalloc(u32int size) v = malloc(size); if(v == nil) sysfatal("%r"); + setmalloctag(v, getcallerpc(&size)); return v; } @@ -22,6 +23,7 @@ emallocz(u32int size) v = emalloc(size); memset(v, 0, size); + setmalloctag(v, getcallerpc(&size)); return v; } @@ -33,5 +35,6 @@ erealloc(void *old, u32int size) v = realloc(old, size); if(v == nil) sysfatal("%r"); + setrealloctag(v, getcallerpc(&old)); return v; }