ref: 10405d31c608fe9d448607545195b758b424e70c
parent: 2a3a8ae0c8cfdc57e4c6055493cc83d60dbfdf1b
author: 9ferno <[email protected]>
date: Thu Jan 27 11:09:37 EST 2022
more stuff from 9front to the forth console
--- a/Inferno/amd64/include/ureg.h
+++ b/Inferno/amd64/include/ureg.h
@@ -12,8 +12,8 @@
u64 r11;
u64 r12;
u64 r13;
- u64 r14;
- u64 r15;
+ u64 r14; /* up-> */
+ u64 r15; /* m-> */
u16 ds;
u16 es;
@@ -20,8 +20,14 @@
u16 fs;
u16 gs;
- u64 trap; /* trap type */
- u64 ecode; /* error code (or zero) */
+ union {
+ u64 trap; /* trap type */
+ u64 type;
+ };
+ union {
+ u64 ecode; /* error code (or zero) */
+ u64 error;
+ };
u64 pc; /* pc */
u64 cs; /* old context */
u64 flags; /* old flags */
--- a/os/ip/ipifc.c
+++ b/os/ip/ipifc.c
@@ -510,7 +510,7 @@
f = ifc->conv->p->f;
if(waserror()){
wunlock(ifc);
- return up->env->errstr;
+ return up->errstr;
}
if(mtu > 0)
@@ -1574,7 +1574,7 @@
ipifcregisteraddr(Fs *f, Ipifc *ifc, Iplifc *lifc, uchar *ip)
{
if(waserror()){
- print("ipifcregisteraddr %s %I %I: %s\n", ifc->dev, lifc->local, ip, up->env->errstr);
+ print("ipifcregisteraddr %s %I %I: %s\n", ifc->dev, lifc->local, ip, up->errstr);
return;
}
if(ifc->m != nil && ifc->m->areg != nil)
--- a/os/ip/plan9.c
+++ b/os/ip/plan9.c
@@ -13,17 +13,17 @@
char*
commonuser(void)
{
- return up->env->user;
+ return up->user;
}
Chan*
commonfdtochan(int fd, int mode, int a, int b)
{
- return fdtochan(up->env->fgrp, fd, mode, a, b);
+ return fdtochan(up->fgrp, fd, mode, a, b);
}
char*
commonerror(void)
{
- return up->env->errstr;
+ return up->errstr;
}
--- a/os/pc/devrtc.c
+++ b/os/pc/devrtc.c
@@ -85,11 +85,11 @@
omode = openmode(omode);
switch((u64)c->qid.path){
case Qrtc:
- if(strcmp(up->env->user, eve)!=0 && omode!=OREAD)
+ if(strcmp(up->user, eve)!=0 && omode!=OREAD)
error(Eperm);
break;
case Qnvram:
- if(strcmp(up->env->user, eve)!=0)
+ if(strcmp(up->user, eve)!=0)
error(Eperm);
}
return devopen(c, omode, rtcdir, nelem(rtcdir), devgen);
--- a/os/pc/devvga.c
+++ b/os/pc/devvga.c
@@ -270,7 +270,7 @@
if((u64)c->qid.path == Qvgaovlctl)
if(scr->dev && scr->dev->ovlctl){
if(waserror()){
- print("ovlctl error: %s\n", up->env->errstr);
+ print("ovlctl error: %s\n", up->errstr);
return;
}
scr->dev->ovlctl(scr, c, closectl, strlen(closectl));
--- a/os/pc/ether8169.c
+++ b/os/pc/ether8169.c
@@ -795,7 +795,7 @@
return;
}
if(waserror()){
- print("#l%d: rtl8169: %s\n", edev->ctlrno, up->env->errstr);
+ print("#l%d: rtl8169: %s\n", edev->ctlrno, up->errstr);
qunlock(&ctlr->alock);
nexterror();
}
--- a/os/pc64/fns.h
+++ b/os/pc64/fns.h
@@ -28,6 +28,7 @@
void dmaend(int);
int dmainit(int, int);
s32 dmasetup(int, void*, s32, s32);
+void dumpmcregs(void);
void dumpregs(Ureg*);
int ecinit(int cmdport, int dataport);
int ecread(uchar addr);
@@ -49,6 +50,7 @@
u64 getcr2(void);
u64 getcr3(void);
u64 getcr4(void);
+u64 getdr6(void);
char* getconf(char*);
void guesscpuhz(int);
void mwait(void*);
@@ -204,6 +206,7 @@
void upafree(uintptr, u32);
void upareserve(uintptr, u32);
u64 us2fastticks(u64);
+s32 userureg(Ureg*);
void vectortable(void);
void* vmap(uintptr, s32);
void vunmap(void*, s32);
@@ -214,7 +217,6 @@
void nmiscreen(void);
int kbdinready(void);
-#define userureg(ur) (((ur)->cs & 3) == 3)
#define getcallerpc(x) (((uintptr*)(x))[-1])
#define KADDR(a) ((void*)((uintptr)(a)|KZERO))
#define PADDR(a) ((uintptr)(a)&~(uintptr)KZERO)
--- a/os/pc64/forth.s
+++ b/os/pc64/forth.s
@@ -214,6 +214,12 @@
POP(TOP)
NEXT
+/*
+ TODO replace the CALL to validateaddress with a macro
+ using UM and UME masks or CMPQ with UM and UME in
+ fetch, store, cfetch and cstore to speed up these words
+ (a || UM) && ~UME
+ */
TEXT fetch(SB), 1, $-4 /* ( a -- n) */
PUSH(TOP)
CALL validateaddress(SB) /* a a -- a */
--- a/os/pc64/main.c
+++ b/os/pc64/main.c
@@ -285,23 +285,23 @@
void
init0(void)
{
- Osenv *o;
/*char buf[2*KNAMELEN];*/
up->nerrlab = 0;
spllo();
- if(waserror())
+ if(waserror()){
+ print("init0: waserror() loop\n");
panic("init0: %r");
+ }
/*
* These are o.k. because rootinit is null.
* Then early kproc's will have a root and dot.
*/
- o = up->env;
- o->pgrp->slash = namec("#/", Atodir, 0, 0);
- pathclose(o->pgrp->slash->path);
- o->pgrp->slash->path = newpath("/");
- o->pgrp->dot = cclone(o->pgrp->slash);
+ up->pgrp->slash = namec("#/", Atodir, 0, 0);
+ pathclose(up->pgrp->slash->path);
+ up->pgrp->slash->path = newpath("/");
+ up->pgrp->dot = cclone(up->pgrp->slash);
chandevinit();
/* print("devtab\n");
@@ -338,18 +338,16 @@
userinit(void)
{
Proc *p;
- Osenv *o;
up = nil;
if((p = newforthproc()) == nil){
panic("no procs for userinit");
}
- o = p->env;
- o->fgrp = newfgrp(nil);
- o->egrp = newegrp();
- o->pgrp = newpgrp();
- kstrdup(&o->user, eve);
+ p->fgrp = newfgrp(nil);
+ p->egrp = newegrp();
+ p->pgrp = newpgrp();
+ kstrdup(&p->user, eve);
strcpy(p->text, "*init*");
/*
--- a/os/pc64/mkfile
+++ b/os/pc64/mkfile
@@ -64,7 +64,7 @@
i$CONF: $OBJ $CONF.c $CONF.root.h $LIBNAMES
$CC $CFLAGS '-DKERNDATE='$KERNDATE $CONF.c
- $LD -v -a -o $target -T$KTZERO -R4096 -l $OBJ $CONF.$O $LIBFILES > $target.loader >[2=1]
+ $LD -v -a -o $target -T$KTZERO -R4096 -l $OBJ $CONF.$O $LIBFILES > $target.loader
$LD -o $target -T$KTZERO -R4096 -l $OBJ $CONF.$O $LIBFILES
$KSIZE $target
--- a/os/pc64/pc64
+++ b/os/pc64/pc64
@@ -8,12 +8,13 @@
mnt
pipe
proc
- prog
+# prog
rtc
- srv
+# srv
ssl
- dup
+# dup
cap
+ ready
shm
ether netif
@@ -46,14 +47,17 @@
# esp
# il
+# the order of the libraries here matters. If there is a library
+# with an undefined symbol at the end, the linker throws out an
+# undefined symbol error
lib
aml
fis
- interp
+# interp
keyring
- draw
memlayer
memdraw
+ draw
tk
sec
mp
@@ -117,11 +121,11 @@
# vgavmware +cur
mod
- sys
- draw
- tk
- keyring
- math
+# sys
+# draw
+# tk
+# keyring
+# math
init
disinit
@@ -140,15 +144,16 @@
alarm
alloc
allocb
+ auth
chan
dev
dial
- dis
- discall
+# dis
+# discall
edf
- exception
- exportfs
- inferno
+# exception
+# exportfs TODO for forth
+# inferno TODO for forth
iomap
irq
latin1
@@ -162,6 +167,7 @@
qlock
random
rdb
+# rebootcmd
swcursor
sysfile
taslock
--- a/os/pc64/trap.c
+++ b/os/pc64/trap.c
@@ -6,6 +6,7 @@
#include "io.h"
#include "ureg.h"
#include "../port/error.h"
+#include "tos.h"
Vctl *vctl[256]; /* defined in pc/irq.c */
@@ -19,7 +20,7 @@
static void doublefault(Ureg*, void*);
static void unexpected(Ureg*, void*);
static void _dumpstack(Ureg*);
-static void dumpureg(Ureg* ureg);
+void dumpureg(Ureg* ureg);
void
trapinit0(void)
@@ -100,7 +101,7 @@
"coprocessor error",
"alignment check",
"machine check",
- "19 (reserved)",
+ "simd error",
"20 (reserved)",
"21 (reserved)",
"22 (reserved)",
@@ -115,16 +116,7 @@
"31 (reserved)",
};
-/*
- * keep histogram of interrupt service times
- */
void
-intrtime(Mach*, int vno)
-{
- USED(vno);
-}
-
-void
dumprstack(intptr h, intptr rsp, intptr he)
{
intptr i;
@@ -173,113 +165,70 @@
* VectorSYSCALL.
* Trap is called with interrupts disabled via interrupt-gates.
*/
-void
-trap(Ureg* ureg)
+static int
+usertrap(int vno)
{
- int i, vno;
char buf[ERRMAX];
- Vctl *ctl, *v;
- Mach *mach;
- vno = ureg->trap;
- if(ctl = vctl[vno]){
- if(ctl->isintr){
- m->intr++;
- if(vno >= VectorPIC && vno != VectorSYSCALL)
- m->lastintr = ctl->irq;
- }
-
- if(ctl->isr)
- ctl->isr(vno);
- for(v = ctl; v != nil; v = v->next){
- if(v->f)
- v->f(ureg, v->a);
- }
- if(ctl->eoi)
- ctl->eoi(vno);
-
- if(ctl->isintr){
- if(up && ctl->irq != IrqTIMER && ctl->irq != IrqCLOCK)
- preempted();
- }
- }
- else if(vno <= nelem(excname) && up->type == Interp){
+ if(vno < nelem(excname)){
spllo();
- sprint(buf, "sys: trap: %s pc 0x%zx", excname[vno], ureg->pc);
- print(buf);
- dumpregs(ureg);
- _dumpstack(ureg);
- error(buf);
+ sprint(buf, "sys: trap: %s", excname[vno]);
+ postnote(up, 1, buf, NDebug);
+ return 1;
}
- else if(vno >= VectorPIC && vno != VectorSYSCALL){
- /*
- * An unknown interrupt.
- * Check for a default IRQ7. This can happen when
- * the IRQ input goes away before the acknowledge.
- * In this case, a 'default IRQ7' is generated, but
- * the corresponding bit in the ISR isn't set.
- * In fact, just ignore all such interrupts.
- */
+ return 0;
+}
- /* call all interrupt routines, just in case */
- for(i = VectorPIC; i <= MaxIrqLAPIC; i++){
- ctl = vctl[i];
- if(ctl == nil)
- continue;
- if(!ctl->isintr)
- continue;
- for(v = ctl; v != nil; v = v->next){
- if(v->f)
- v->f(ureg, v->a);
- }
- /* should we do this? */
- if(ctl->eoi)
- ctl->eoi(i);
- }
+/* go to user space */
+void
+trap(Ureg *ureg)
+{
+ int vno, user;
- /* clear the interrupt */
- i8259isr(vno);
-
- if(0)print("cpu%d: spurious interrupt %d, last %d",
- m->machno, vno, m->lastintr);
- if(0)if(conf.nmach > 1){
- for(i = 0; i < MAXMACH; i++){
- if(active.machs[i] == 0)
- continue;
- mach = MACHP(i);
- if(m->machno == mach->machno)
- continue;
- print(" cpu%d: last %d",
- mach->machno, mach->lastintr);
+ user = kenter(ureg);
+ vno = ureg->type;
+ if(!irqhandled(ureg, vno) && (!user || !usertrap(vno))){
+ if(!user){
+ void (*pc)(void);
+
+ extern void _rdmsrinst(void);
+ extern void _wrmsrinst(void);
+ extern void _peekinst(void);
+
+ pc = (void*)ureg->pc;
+ if(pc == _rdmsrinst || pc == _wrmsrinst){
+ if(vno == VectorGPF){
+ ureg->bp = -1;
+ ureg->pc += 2;
+ return;
+ }
+ } else if(pc == _peekinst){
+ if(vno == VectorGPF || vno == VectorPF){
+ ureg->pc += 2;
+ return;
+ }
}
- print("\n");
+
+ /* early fault before trapinit() */
+ if(vno == VectorPF)
+ faultamd64(ureg, 0);
}
- m->spuriousintr++;
- return;
- }
- else{
- if(vno == VectorNMI){
- nmienable();
- if(m->machno != 0){
- print("cpu%d: PC %8.8zuX\n",
- m->machno, ureg->pc);
- }
- }
- dumpureg(ureg);
+
dumpregs(ureg);
- if(vno < nelem(excname)){
- dumprstack(ureg->r11, ureg->r8, ureg->r12);
- dumppstack(ureg->r11, ureg->dx, ureg->r12);
+ if(!user){
+ ureg->sp = (uintptr)&ureg->sp;
_dumpstack(ureg);
- panic("%s", excname[vno]);
}
- panic("unknown trap/intr: %d\n", vno);
+ if(vno < nelem(excname))
+ panic("%s", excname[vno]);
+ panic("unknown trap/intr: %d", vno);
}
+ splhi();
- /* delaysched set because we held a lock or because our quantum ended */
- if(up && up->delaysched){
- sched();
- splhi();
+ if(user){
+ if(up->procctl || up->nnote)
+ notify(ureg);
+ kexit(ureg);
}
}
@@ -287,40 +236,29 @@
* dump registers
*/
void
-dumpregs2(Ureg* ureg)
+dumpregs(Ureg* ureg)
{
if(up)
- print("cpu%d: registers for %s %ud\n",
+ iprint("cpu%d: registers for %s %ud\n",
m->machno, up->text, up->pid);
else
- print("cpu%d: registers for kernel\n", m->machno);
- print("FLAGS=%zux TRAP=%zux ECODE=%zux PC=%zux",
- ureg->flags, ureg->trap, ureg->ecode, ureg->pc);
- print(" SS=%4.4zuX USP=%zux\n", ureg->ss & 0xFFFF, ureg->usp);
- print(" AX %8.8zuX BX TOP %8.8zuX CX %8.8zuX DX PSP %8.8zuX\n",
- ureg->ax, ureg->bx, ureg->cx, ureg->dx);
- print(" SI %8.8zuX DI %8.8zuX BP %8.8zuX\n",
- ureg->si, ureg->di, ureg->bp);
- print(" CS %4.4zux DS %4.4ux ES %4.4ux FS %4.4ux GS %4.4ux\n",
- ureg->cs & 0xFFFF, ureg->ds & 0xFFFF, ureg->es & 0xFFFF,
- ureg->fs & 0xFFFF, ureg->gs & 0xFFFF);
- print(" R8 RSP %8.8zux R9 IP %8.8zzux R10 W %8.8zux\n"
- " R11 UP %8.8zux R12 UPE %8.8zux R13 %8.8zux\n",
- ureg->r8, ureg->r9, ureg->r10,
- ureg->r11, ureg->r12, ureg->r13);
- print(" R14 up %8.8zux R15 m %8.8zux\n",
- ureg->r14, ureg->r15);
-}
+ iprint("cpu%d: registers for kernel\n", m->machno);
-void
-dumpregs(Ureg* ureg)
-{
- extern ulong etext;
- vlong mca, mct;
- intptr *i;
+ iprint(" AX %.16lluX BX TOP %.16lluX CX %.16lluX\n",
+ ureg->ax, ureg->bx, ureg->cx);
+ iprint(" DX PSP %.16lluX SI %.16lluX DI %.16lluX\n",
+ ureg->dx, ureg->si, ureg->di);
+ iprint(" BP %.16lluX R8 RSP %.16lluX R9 IP %.16lluX\n",
+ ureg->bp, ureg->r8, ureg->r9);
+ iprint(" R10 W %.16lluX R11 UM %.16lluX R12 UME %.16lluX\n",
+ ureg->r10, ureg->r11, ureg->r12);
+ iprint(" R13 %.16lluX R14 up %.16lluX R15 m %.16lluX\n",
+ ureg->r13, ureg->r14, ureg->r15);
+ iprint(" CS %.4lluX SS %.4lluX PC %.16lluX SP %.16lluX\n",
+ ureg->cs & 0xffff, ureg->ss & 0xffff, ureg->pc, ureg->sp);
+ iprint("TYPE %.2lluX ERROR %.4lluX FLAGS %.8lluX\n",
+ ureg->type & 0xff, ureg->error & 0xffff, ureg->flags & 0xffffffff);
- dumpregs2(ureg);
-
/*
* Processor control registers.
* If machine check exception, time stamp counter, page size extensions
@@ -328,26 +266,27 @@
* CR4. If there is a CR4 and machine check extensions, read the machine
* check address and machine check type registers if RDMSR supported.
*/
- print(" CR0 %8.8zux CR2 %8.8zux CR3 %8.8zux",
+ iprint(" CR0 %8.8llux CR2 %16.16llux CR3 %16.16llux",
getcr0(), getcr2(), getcr3());
- if(m->cpuiddx & 0x9A){
- print(" CR4 %8.8zux", getcr4());
- if((m->cpuiddx & 0xA0) == 0xA0){
- rdmsr(0x00, &mca);
- rdmsr(0x01, &mct);
- print("\n MCA %8.8zux MCT %8.8zux", mca, mct);
- }
+ if(m->cpuiddx & (Mce|Tsc|Pse|Vmex)){
+ iprint(" CR4 %16.16llux\n", getcr4());
+ if(ureg->type == 18)
+ dumpmcregs();
}
+ iprint(" ur %#p up %#p\n", ureg, up);
+
+ /* my stuff, not in 9front */
print("\n ur %lux up %lux ureg->bp & ~0xFFF %zx\n", ureg, up, ureg->bp & ~0xFFF);
if((ureg->bp & ~0xFFF) == FFSTART){
- for(i = (intptr*)FFSTART; i<=(intptr*)ureg->bp; i++){
+ for(intptr *i = (intptr*)FFSTART; i<=(intptr*)ureg->bp; i++){
print("0x%p: 0x%zx\n", i, *i);
}
- for(i = (intptr*)FFEND; i>=(intptr*)ureg->sp; i--){
+ for(intptr *i = (intptr*)FFEND; i>=(intptr*)ureg->sp; i--){
print("0x%p: 0x%zx\n", i, *i);
}
}
}
+
/* displays in the order pushed into the stack */
void
dumpureg(Ureg* ureg)
@@ -361,7 +300,7 @@
print("SS %4.4zuX SP %zux\n", ureg->ss & 0xFFFF, ureg->usp);
print(" FLAGS %zux CS %zux PC %zux ECODE %zux TRAP %zux\n",
ureg->flags, ureg->cs, ureg->pc, ureg->ecode, ureg->trap);
- print(" GS %4.4zux FS %4.4ux ES %4.4ux DS %4.4ux\n",
+ print(" GS %4.4ux FS %4.4ux ES %4.4ux DS %4.4ux\n",
ureg->gs & 0xFFFF, ureg->fs & 0xFFFF, ureg->es & 0xFFFF,
ureg->ds & 0xFFFF);
@@ -396,51 +335,64 @@
_dumpstack(Ureg *ureg)
{
uintptr l, v, i, estack;
- extern uintptr etext;
- int onlypc = 0;
+ extern ulong etext;
+ int x;
+ char *s;
- print("ktrace /kernel/path pc 0x%zux sp 0x%zux &l 0x%zux up 0x%p\n", ureg->pc, ureg->sp, &l, up);
+ if((s = getconf("*nodumpstack")) != nil && strcmp(s, "0") != 0){
+ iprint("dumpstack disabled\n");
+ return;
+ }
+ iprint("dumpstack\n");
+
+ x = 0;
+ x += iprint("ktrace /kernel/path %#p %#p <<EOF\n", ureg->pc, ureg->sp);
i = 0;
- if(up &&
- (uintptr)&l >= (uintptr)up->kstack &&
- (uintptr)&l <= (uintptr)up->kstack+KSTACK){
+ if(up
+ && (uintptr)&l >= (uintptr)up->kstack
+ && (uintptr)&l <= (uintptr)up->kstack+KSTACK)
estack = (uintptr)up->kstack+KSTACK;
- print("up->kstack 0x%zux estack 0x%zux\n",(uintptr)up->kstack, estack);
- }else if((uintptr)&l >= (uintptr)m->stack &&
- (uintptr)&l <= (uintptr)m+BY2PG){
+ else if((uintptr)&l >= (uintptr)m->stack
+ && (uintptr)&l <= (uintptr)m+MACHSIZE)
estack = (uintptr)m+MACHSIZE;
- print("m->stack 0x%zux estack 0x%zux\n",(uintptr)m->stack, estack);
- }else{
- if(up)
- print("up->kstack 0x%zux\n", (uintptr)up->kstack);
- else
- print("m->stack 0x%zux\n", (uintptr)m->stack);
+ else
return;
- }
+ x += iprint("estackx %p\n", estack);
- for(l=(uintptr)&l; l<estack; l+=sizeof(intptr)){
+ for(l = (uintptr)&l; l < estack; l += sizeof(uintptr)){
v = *(uintptr*)l;
- if(onlypc){
- if(KTZERO < v && v < (uintptr)&etext){
- /*
- * we could Pick off general CALL (((uchar*)v)[-5] == 0xE8)
- * and CALL indirect through AX (((uchar*)v)[-2] == 0xFF && ((uchar*)v)[-2] == 0xD0),
- * but this is too clever and misses faulting address.
- */
- print("%.8zux=%.8zux ", l, v);
- i++;
- }
- }else{
- print("%.8zux=%.8zux ", l, v);
- i++;
+ if((KTZERO < v && v < (uintptr)&etext) || estack-l < 32){
+ /*
+ * Could Pick off general CALL (((uchar*)v)[-5] == 0xE8)
+ * and CALL indirect through AX
+ * (((uchar*)v)[-2] == 0xFF && ((uchar*)v)[-2] == 0xD0),
+ * but this is too clever and misses faulting address.
+ */
+ x += iprint("%.8lux=%.8lux ", (ulong)l, (ulong)v);
+ i++;
}
if(i == 4){
i = 0;
- print("\n");
+ x += iprint("\n");
}
}
if(i)
- print("\n");
+ iprint("\n");
+ iprint("EOF\n");
+
+ if(ureg->type != VectorNMI)
+ return;
+
+ i = 0;
+ for(l = (uintptr)&l; l < estack; l += sizeof(uintptr)){
+ iprint("%.8p ", *(uintptr*)l);
+ if(++i == 8){
+ i = 0;
+ iprint("\n");
+ }
+ }
+ if(i)
+ iprint("\n");
}
void
@@ -450,20 +402,50 @@
}
static void
-debugbpt(Ureg* ureg, void*)
+debugexc(Ureg *ureg, void *)
{
+ u64int dr6, m;
char buf[ERRMAX];
+ char *p, *e;
+ int i;
- if(breakhandler != nil){
- breakhandler(ureg, up);
+ dr6 = getdr6();
+ if(up == nil)
+ panic("kernel debug exception dr6=%#.8ullx", dr6);
+ putdr6(up->dr[6]);
+ if(userureg(ureg))
+ qlock(&up->debug);
+ else if(!canqlock(&up->debug))
return;
+ m = up->dr[7];
+ m = (m >> 4 | m >> 3) & 8 | (m >> 3 | m >> 2) & 4 | (m >> 2 | m >> 1) & 2 | (m >> 1 | m) & 1;
+ m &= dr6;
+ if(m == 0){
+ sprint(buf, "sys: debug exception dr6=%#.8ullx", dr6);
+ postnote(up, 0, buf, NDebug);
+ }else{
+ p = buf;
+ e = buf + sizeof(buf);
+ p = seprint(p, e, "sys: watchpoint ");
+ for(i = 0; i < 4; i++)
+ if((m & 1<<i) != 0)
+ p = seprint(p, e, "%d%s", i, (m >> i + 1 != 0) ? "," : "");
+ postnote(up, 0, buf, NDebug);
}
+ qunlock(&up->debug);
+}
+
+static void
+debugbpt(Ureg* ureg, void*)
+{
+ char buf[ERRMAX];
+
if(up == 0)
panic("kernel bpt");
/* restore pc to instruction that caused the trap */
ureg->pc--;
sprint(buf, "sys: breakpoint");
- error(buf);
+ postnote(up, 1, buf, NDebug);
}
static void
@@ -482,28 +464,291 @@
faultamd64(Ureg* ureg, void*)
{
uintptr addr;
- int read, user;
+ int read, user, n, insyscall, f;
char buf[ERRMAX];
addr = getcr2();
- user = (ureg->cs & 0xFFFF) == KESEL;
- if(!user && mmukmapsync(addr))
- return;
- read = !(ureg->ecode & 2);
- spllo();
- snprint(buf, sizeof(buf), "trap: fault %s pc=0x%zux addr=0x%zux\n",
- read ? "read" : "write", ureg->pc, addr);
-print(buf);
- dumpregs(ureg);
+ read = !(ureg->error & 2);
+ user = userureg(ureg);
+ if(!user){
+ {
+ extern void _peekinst(void);
+
+ if((void(*)(void))ureg->pc == _peekinst){
+ ureg->pc += 2;
+ return;
+ }
+ }
+ if(addr >= (uintptr)USTKTOP)
+ panic("kernel fault: bad address pc=%#p addr=%#p", ureg->pc, addr);
+ if(up == nil)
+ panic("kernel fault: no user process pc=%#p addr=%#p", ureg->pc, addr);
+ }
+ if(up == nil)
+ panic("user fault: up=0 pc=%#p addr=%#p", ureg->pc, addr);
+
+ /* forth specific dump stack */
dumprstack(ureg->r11, ureg->r8, ureg->r12);
dumppstack(ureg->r11, ureg->dx, ureg->r12);
-dumpstack();
- if(up->type == Interp)
- disfault(ureg, buf);
- dumpregs(ureg);
- print("fault: %s\n", buf);
- panic("fault: %s\n", buf);
+
+ insyscall = up->insyscall;
+ up->insyscall = 1;
+ f = fpusave();
+ if(!user && waserror()){
+ if(up->nerrlab == 0){
+ pprint("suicide: sys: %s\n", up->errstr);
+ pexit(up->errstr, 1);
+ }
+ int s = splhi();
+ fpurestore(f);
+ up->insyscall = insyscall;
+ splx(s);
+ nexterror();
+ }
+ n = -1 /* fault(addr, ureg->pc, read) no paging for us*/;
+ if(n < 0){
+ if(!user){
+ dumpregs(ureg);
+ panic("fault: %#p", addr);
+ }
+ /* checkpages(); */
+ sprint(buf, "sys: trap: fault %s addr=%#p",
+ read ? "read" : "write", addr);
+ postnote(up, 1, buf, NDebug);
+ }
+ if(!user) poperror();
+ splhi();
+ fpurestore(f);
+ up->insyscall = insyscall;
}
+
+/*
+ * Call user, if necessary, with note.
+ * Pass user the Ureg struct and the note on his stack.
+ */
+int
+notify(Ureg* ureg)
+{
+ int l;
+ uintptr sp;
+ Note *n;
+
+ if(up->procctl)
+ procctl();
+ if(up->nnote == 0)
+ return 0;
+ spllo();
+ qlock(&up->debug);
+ up->notepending = 0;
+ n = &up->note[0];
+ if(strncmp(n->msg, "sys:", 4) == 0){
+ l = strlen(n->msg);
+ if(l > ERRMAX-15) /* " pc=0x12345678\0" */
+ l = ERRMAX-15;
+ sprint(n->msg+l, " pc=%#p", ureg->pc);
+ }
+
+ if(n->flag!=NUser && (up->notified || up->notify==0)){
+ qunlock(&up->debug);
+ if(n->flag == NDebug){
+ up->fpstate &= ~FPillegal;
+ pprint("suicide: %s\n", n->msg);
+ }
+ pexit(n->msg, n->flag!=NDebug);
+ }
+
+ if(up->notified){
+ qunlock(&up->debug);
+ splhi();
+ return 0;
+ }
+
+ if(!up->notify){
+ qunlock(&up->debug);
+ pexit(n->msg, n->flag!=NDebug);
+ }
+ sp = ureg->sp;
+ sp -= 256; /* debugging: preserve context causing problem */
+ sp -= sizeof(Ureg);
+if(0) print("%s %ud: notify %#p %#p %#p %s\n",
+ up->text, up->pid, ureg->pc, ureg->sp, sp, n->msg);
+
+ if(!okaddr((uintptr)up->notify, 1, 0)
+ || !okaddr(sp-ERRMAX-4*BY2WD, sizeof(Ureg)+ERRMAX+4*BY2WD, 1)){
+ qunlock(&up->debug);
+ up->fpstate &= ~FPillegal;
+ pprint("suicide: bad address in notify\n");
+ pexit("Suicide", 0);
+ }
+
+ memmove((Ureg*)sp, ureg, sizeof(Ureg));
+ *(Ureg**)(sp-BY2WD) = up->ureg; /* word under Ureg is old up->ureg */
+ up->ureg = (void*)sp;
+ sp -= BY2WD+ERRMAX;
+ memmove((char*)sp, up->note[0].msg, ERRMAX);
+ sp -= 3*BY2WD;
+ ((uintptr*)sp)[2] = sp + 3*BY2WD; /* arg2 string */
+ ((uintptr*)sp)[1] = (uintptr)up->ureg; /* arg1 is ureg* */
+ ((uintptr*)sp)[0] = 0; /* arg0 is pc */
+ ureg->sp = sp;
+ ureg->pc = (uintptr)up->notify;
+ ureg->bp = (uintptr)up->ureg; /* arg1 passed in RARG */
+ ureg->cs = UESEL;
+ ureg->ss = UDSEL;
+ up->notified = 1;
+ up->nnote--;
+ memmove(&up->lastnote, &up->note[0], sizeof(Note));
+ memmove(&up->note[0], &up->note[1], up->nnote*sizeof(Note));
+ qunlock(&up->debug);
+ splhi();
+ if(up->fpstate == FPactive){
+ fpsave(up->fpsave);
+ up->fpstate = FPinactive;
+ }
+ up->fpstate |= FPillegal;
+ return 1;
+}
+
+/* TODO include 9front port/fault.c */
+int
+okaddr(uintptr, u32, int)
+{
+ return 1;
+}
+void
+validaddr(uintptr addr, ulong len, int write)
+{
+ if(!okaddr(addr, len, write)){
+ pprint("suicide: invalid address %#p/%lud in sys call pc=%#p\n", addr, len, userpc());
+ postnote(up, 1, "sys: bad address in syscall", NDebug);
+ error(Ebadarg);
+ }
+}
+
+/*
+ * Return user to state before notify()
+ */
+void
+noted(Ureg* ureg, ulong arg0)
+{
+ Ureg *nureg;
+ uintptr oureg, sp;
+
+ up->fpstate &= ~FPillegal;
+ spllo();
+ qlock(&up->debug);
+ if(arg0!=NRSTR && !up->notified) {
+ qunlock(&up->debug);
+ pprint("call to noted() when not notified\n");
+ pexit("Suicide", 0);
+ }
+ up->notified = 0;
+
+ nureg = up->ureg; /* pointer to user returned Ureg struct */
+
+ /* sanity clause */
+ oureg = (uintptr)nureg;
+/* TODO we check that this register is within the kernel data segment
+ if(!okaddr(oureg-BY2WD, BY2WD+sizeof(Ureg), 0)){
+ qunlock(&up->debug);
+ pprint("bad ureg in noted or call to noted when not notified\n");
+ pexit("Suicide", 0);
+ }
+*/
+ /* don't let user change system flags or segment registers */
+ setregisters(ureg, (char*)ureg, (char*)nureg, sizeof(Ureg));
+
+ switch(arg0){
+ case NCONT:
+ case NRSTR:
+if(0) print("%s %ud: noted %#p %#p\n",
+ up->text, up->pid, nureg->pc, nureg->sp);
+ if(!okaddr(nureg->pc, 1, 0) || !okaddr(nureg->sp, BY2WD, 0)){
+ qunlock(&up->debug);
+ pprint("suicide: trap in noted\n");
+ pexit("Suicide", 0);
+ }
+ up->ureg = (Ureg*)(*(uintptr*)(oureg-BY2WD));
+ qunlock(&up->debug);
+ break;
+
+ case NSAVE:
+ if(!okaddr(nureg->pc, 1, 0)
+ || !okaddr(nureg->sp, BY2WD, 0)){
+ qunlock(&up->debug);
+ pprint("suicide: trap in noted\n");
+ pexit("Suicide", 0);
+ }
+ qunlock(&up->debug);
+ sp = oureg-4*BY2WD-ERRMAX;
+ splhi();
+ ureg->sp = sp;
+ ureg->bp = oureg; /* arg 1 passed in RARG */
+ ((uintptr*)sp)[1] = oureg; /* arg 1 0(FP) is ureg* */
+ ((uintptr*)sp)[0] = 0; /* arg 0 is pc */
+ break;
+
+ default:
+ up->lastnote.flag = NDebug;
+ /* fall through */
+
+ case NDFLT:
+ qunlock(&up->debug);
+ if(up->lastnote.flag == NDebug)
+ pprint("suicide: %s\n", up->lastnote.msg);
+ pexit(up->lastnote.msg, up->lastnote.flag!=NDebug);
+ }
+}
+
+/* the USTKTOP macro depends on up being populated
+ this function will double fault as up is being set to 0 before using USTKTOP
+ */
+uintptr
+execregs(uintptr entry, ulong ssize, ulong nargs)
+{
+ uintptr *sp, top;
+ Ureg *ureg;
+
+ top = (uintptr)(USTKTOP-sizeof(Tos)); /* address of kernel/user shared data */
+ sp = (uintptr*)(USTKTOP - ssize);
+ *--sp = nargs;
+ ureg = up->dbgreg;
+ ureg->sp = (uintptr)sp;
+ ureg->pc = entry;
+ ureg->cs = KESEL;
+ ureg->ss = KDSEL;
+ ureg->r14 = ureg->r15 = 0; /* extern user registers */
+ return top; /* address of kernel/user shared data */
+}
+
+/*
+ * return the userpc the last exception happened at
+ */
+uintptr
+userpc(void)
+{
+ Ureg *ureg;
+
+ ureg = (Ureg*)up->dbgreg;
+ return ureg->pc;
+}
+
+/* This routine must save the values of registers the user is not permitted
+ * to write from devproc and noted() and then restore the saved values before returning.
+ */
+void
+setregisters(Ureg* ureg, char* pureg, char* uva, int n)
+{
+ u64int flags;
+
+ flags = ureg->flags;
+ memmove(pureg, uva, n);
+ ureg->cs = KESEL;
+ ureg->ss = KDSEL;
+ ureg->flags = (ureg->flags & 0x00ff) | (flags & 0xff00);
+ /* ureg->pc &= UADDRMASK; */
+}
+
static void
linkproc(void)
--- a/os/port/alloc.c
+++ b/os/port/alloc.c
@@ -91,7 +91,7 @@
D2B(b, v);
b->magic = MAGIC_A;
- ((Heap*)v)->color = mutator;
+ /* ((Heap*)v)->color = mutator; */
}
char*
@@ -256,12 +256,12 @@
// if(asize >= 1024*1024*1024) /* for sanity and to avoid overflow */
// return nil;
- if(p->cursize > p->ressize &&
+/* if(p->cursize > p->ressize &&
(prog = currun()) != nil &&
prog->flags&Prestricted){
print("poolalloc exception\n");
return nil;
- }
+ }*/
size = asize;
osize = size;
size = (size + BHDRSIZE + p->quanta) & ~(p->quanta);
@@ -404,7 +404,7 @@
poolfree(Pool *p, void *v)
{
Bhdr *b, *c;
- extern Bhdr *ptr;
+ /* extern Bhdr *ptr; defined in libinterp/gc.c */
D2B(b, v);
@@ -414,8 +414,8 @@
c = B2NB(b);
if(c->magic == MAGIC_F) { /* Join forward */
- if(c == ptr)
- ptr = b;
+ /*if(c == ptr)
+ ptr = b; */
pooldel(p, c);
c->magic = 0;
b->size += c->size;
@@ -424,8 +424,8 @@
c = B2PT(b)->hdr;
if(c->magic == MAGIC_F) { /* Join backward */
- if(b == ptr)
- ptr = c;
+ /*if(b == ptr)
+ ptr = c; */
pooldel(p, c);
b->magic = 0;
c->size += b->size;
--- a/os/port/chan.c
+++ b/os/port/chan.c
@@ -726,7 +726,7 @@
poperror();
}
- pg = up->env->pgrp;
+ pg = up->pgrp;
wlock(&pg->ns);
l = &MOUNTH(pg, old->qid);
for(m = *l; m != nil; m = m->hash){
@@ -792,7 +792,7 @@
* cclose will take care of freeing the umh.
*/
- pg = up->env->pgrp;
+ pg = up->pgrp;
wlock(&pg->ns);
l = &MOUNTH(pg, mnt->qid);
@@ -869,7 +869,7 @@
Pgrp *pg;
Mhead *m;
- pg = up->env->pgrp;
+ pg = up->pgrp;
rlock(&pg->ns);
for(m = MOUNTH(pg, qid); m != nil; m = m->hash){
if(eqchantdqid(m->from, type, dev, qid, 1)){
@@ -1004,7 +1004,7 @@
*nerror = nhave;
pathclose(path);
cclose(c);
- kstrcpy(up->env->errstr, Enotdir, ERRMAX);
+ kstrcpy(up->errstr, Enotdir, ERRMAX);
putmhead(mh);
return -1;
}
@@ -1083,11 +1083,11 @@
if(wq->nqid == 0 || (wq->qid[wq->nqid-1].type&QTDIR) != 0){
if(nerror)
*nerror = nhave+wq->nqid+1;
- kstrcpy(up->env->errstr, Edoesnotexist, ERRMAX);
+ kstrcpy(up->errstr, Edoesnotexist, ERRMAX);
}else{
if(nerror)
*nerror = nhave+wq->nqid;
- kstrcpy(up->env->errstr, Enotdir, ERRMAX);
+ kstrcpy(up->errstr, Enotdir, ERRMAX);
}
free(wq);
putmhead(mh);
@@ -1264,7 +1264,7 @@
snprint(up->genbuf, sizeof up->genbuf, "...%.*s",
utfnlen(name, ename-name), name);
}
- snprint(up->env->errstr, ERRMAX, "%#q %s", up->genbuf, err);
+ snprint(up->errstr, ERRMAX, "%#q %s", up->genbuf, err);
nexterror();
}
@@ -1333,7 +1333,7 @@
nomount = 0;
switch(name[0]){
case '/':
- c = up->env->pgrp->slash;
+ c = up->pgrp->slash;
incref(c);
break;
@@ -1360,7 +1360,7 @@
* any others left unprotected)
*/
n = chartorune(&r, up->genbuf+1)+1;
- if(up->env->pgrp->noattach && utfrune("|decp", r)==nil)
+ if(up->pgrp->noattach && utfrune("|decp", r)==nil)
error(Enoattach);
t = devno(r, 1);
if(t == -1)
@@ -1369,7 +1369,7 @@
break;
default:
- c = up->env->pgrp->dot;
+ c = up->pgrp->dot;
incref(c);
break;
}
@@ -1382,7 +1382,6 @@
e.nelems = 0;
e.nerror = 0;
if(waserror()){
-print("namec: waserror() loop before parsename pid %d\n", up->pid);
cclose(c);
free(e.name);
free(e.elems);
@@ -1396,9 +1395,9 @@
e.nerror, e.off[e.nerror]);
len = e.prefix+e.off[e.nerror];
free(e.off);
- err = up->env->errstr;
- up->env->errstr = up->env->syserrstr;
- up->env->syserrstr = err;
+ err = up->errstr;
+ up->errstr = up->syserrstr;
+ up->syserrstr = err;
namelenerror(aname, len, err);
}
@@ -1414,17 +1413,20 @@
/* perm must have DMDIR if last element is / or /. */
if(e.mustbedir && !(perm&DMDIR)){
e.nerror = e.nelems;
+ print("namec: Acreate create without DMDIR pid %d\n", up->pid);
error("create without DMDIR");
}
/* don't try to walk the last path element just yet. */
- if(e.nelems == 0)
+ if(e.nelems == 0){
+ print("namec: Acreate Eexist pid %d\n", up->pid);
error(Eexist);
+ }
e.nelems--;
}
if(walk(&c, e.elems, e.nelems, nomount, &e.nerror) < 0){
-print("namec: walk < 0 e.nerror %d pid %d\n", e.nerror, up->pid);
+ print("namec: walk < 0 e.nerror %d pid %d\n", e.nerror, up->pid);
if(e.nerror < 0 || e.nerror > e.nelems){
print("namec %s walk error nerror=%d\n", aname, e.nerror);
e.nerror = 0;
@@ -1449,6 +1451,7 @@
if(!nomount)
domount(&c, &m, nil);
if(waserror()){
+ print("namec: Abind\n");
putmhead(m);
nexterror();
}
@@ -1465,6 +1468,7 @@
path = c->path;
incref(path);
if(waserror()){
+ print("namec: Aopen\n");
pathclose(path);
nexterror();
}
@@ -1472,6 +1476,7 @@
if(!nomount)
domount(&c, &m, &path);
if(waserror()){
+ print("namec: Aopen 1\n");
putmhead(m);
nexterror();
}
@@ -1509,8 +1514,8 @@
/* save registers else error() in open has wrong value of c saved */
saveregisters();
- DBG("namec walk c->type %d devtab[c->type]->name %s c->path %s\n",
- c->type, devtab[c->type]->name, chanpath(c));
+ DBG("namec walk pid %d c->type %d devtab[c->type]->name %s c->path %s\n",
+ up->pid, c->type, devtab[c->type]->name, chanpath(c));
c = devtab[c->type]->open(c, omode&~OCEXEC);
if(omode & ORCLOSE)
c->flag |= CRCLOSE;
@@ -1544,6 +1549,7 @@
e.nelems++;
e.nerror++;
if(walk(&c, e.elems+e.nelems-1, 1, nomount, nil) == 0){
+ print("namec: Acreate\n");
if(omode&OEXCL)
error(Eexist);
omode |= OTRUNC;
@@ -1628,16 +1634,16 @@
if(omode & OEXCL)
nexterror();
/* save error */
- err = up->env->errstr;
- up->env->errstr = up->env->syserrstr;
- up->env->syserrstr = err;
+ err = up->errstr;
+ up->errstr = up->syserrstr;
+ up->syserrstr = err;
/* note: we depend that walk does not error */
if(walk(&c, e.elems+e.nelems-1, 1, nomount, nil) < 0)
error(err); /* report true error */
/* restore error */
- err = up->env->syserrstr;
- up->env->syserrstr = up->env->errstr;
- up->env->errstr = err;
+ err = up->syserrstr;
+ up->syserrstr = up->errstr;
+ up->errstr = err;
omode |= OTRUNC;
goto Open;
--- a/os/port/dev.c
+++ b/os/port/dev.c
@@ -228,7 +228,7 @@
/* print("devwalk c %s nc %s n %s name %s caller 0x%p\n", chanpath(c), chanpath(nc), n, *name, getcallerpc(&c)); */
error(Enonexist);
}
- kstrcpy(up->env->errstr, Enonexist, ERRMAX);
+ kstrcpy(up->errstr, Enonexist, ERRMAX);
goto Done;
case 0:
continue;
@@ -285,7 +285,7 @@
return n;
}
print("%s %s: devstat %C %llux\n",
- up->text, up->env->user,
+ up->text, up->user,
devtab[c->type]->dc, c->qid.path);
error(Enonexist);
@@ -338,7 +338,7 @@
}
/*
- * error(Eperm) if open permission not granted for up->env->user.
+ * error(Eperm) if open permission not granted for up->user.
*/
void
devpermcheck(char *fileuid, u32 perm, s32 omode)
@@ -346,17 +346,19 @@
u32 t;
static int access[] = { 0400, 0200, 0600, 0100 };
- if(strcmp(up->env->user, fileuid) == 0)
+ if(strcmp(up->user, fileuid) == 0)
perm <<= 0;
else
- if(strcmp(up->env->user, eve) == 0)
+ if(strcmp(up->user, eve) == 0)
perm <<= 3;
else
perm <<= 6;
t = access[omode&3];
- if((t&perm) != t)
+ if((t&perm) != t){
+ print("devpermcheck Eperm up->user %s perm 0x%ux t 0x%ux\n", up->user, perm, t);
error(Eperm);
+ }
}
Chan*
@@ -381,8 +383,10 @@
}
Return:
c->offset = 0;
- if((c->qid.type&QTDIR) && omode!=OREAD)
+ if((c->qid.type&QTDIR) && omode!=OREAD){
+ print("devopen Eperm\n");
error(Eperm);
+ }
c->mode = openmode(omode);
c->flag |= COPEN;
return c;
--- a/os/port/devbridge.c
+++ b/os/port/devbridge.c
@@ -955,7 +955,7 @@
// release lock to read - error means it is time to quit
qunlock(b);
if(waserror()) {
- print("etherread read error: %s\n", up->env->errstr);
+ print("etherread read error: %s\n", up->errstr);
qlock(b);
break;
}
--- a/os/port/devcap.c
+++ b/os/port/devcap.c
@@ -191,9 +191,9 @@
*l = c->next;
qunlock(&allcaps.l);
free(c);
- if(n == 2 && strcmp(up->env->user, users[0]) != 0)
+ if(n == 2 && strcmp(up->user, users[0]) != 0)
return -1;
- kstrdup(&up->env->user, users[1]);
+ kstrdup(&up->user, users[1]);
return 0;
}
qunlock(&allcaps.l);
--- a/os/port/devcons.c
+++ b/os/port/devcons.c
@@ -10,8 +10,9 @@
#include "keyboard.h"
extern int cflag;
-extern int keepbroken;
+int keepbroken = 1;
extern int rdbstarted;
+extern u32 kerndate;
void (*serwrite)(char *, int);
@@ -47,8 +48,14 @@
/* above until kbdfs */
char* sysname;
-char* eve;
+char *sysname;
+vlong fasthz;
+static int readtime(ulong, char*, int);
+static int readbintime(char*, int);
+static int writetime(char*, int);
+static int writebintime(char*, int);
+
enum
{
CMreboot,
@@ -57,6 +64,7 @@
CMbroken,
CMnobroken,
CMconsole,
+ CMrdb,
};
static Cmdtab sysctlcmd[] =
@@ -67,25 +75,21 @@
CMconsole, "console", 1,
CMbroken, "broken", 0,
CMnobroken, "nobroken", 0,
+ CMrdb, "rdb", 0,
};
+Cmdtab rebootmsg[] =
+{
+ CMreboot, "reboot", 0,
+ CMpanic, "panic", 0,
+ CMrdb, "rdb", 0,
+};
+
void
printinit(void)
{
}
-/*
- * return true if current user is eve
- */
-int
-iseve(void)
-{
- Osenv *o;
-
- o = up->env;
- return strcmp(eve, o->user) == 0;
-}
-
static int
consactive(void)
{
@@ -361,10 +365,10 @@
va_list arg;
char buf[2*PRINTSIZE];
- if(up == nil || up->env->fgrp == nil)
+ if(up == nil || up->fgrp == nil)
return 0;
- c = up->env->fgrp->fd[2];
+ c = up->fgrp->fd[2];
if(c==nil || (c->flag&CMSG)!=0 || (c->mode!=OWRITE && c->mode!=ORDWR))
return 0;
n = snprint(buf, sizeof buf, "%s %ud: ", up->text, up->pid);
@@ -386,47 +390,71 @@
enum{
Qdir,
+ Qbintime,
Qcons,
- Qsysctl,
Qconsctl,
+ Qcputime,
Qdrivers,
+ Qhostdomain,
Qhostowner,
+ Qjit,
Qkeyboard,
- Qklog, /* same as 9front's kmesg */
+ Qkmesg,
Qkprint, /* tail of kprint's and cons. Why not just a tail of klog? Why is this needed? */
- Qscancode,
Qmemory,
- Qmsec,
Qnull,
+ Qosversion,
+ Qpid,
+ Qppid,
Qrandom,
- Qnotquiterandom,
+ Qreboot,
+ Qscancode,
+ Qsysctl,
Qsysname,
+ Qsysstat,
Qtime,
Quser,
- Qjit,
+ Qzero,
+ Qconfig,
+ Qmordor,
};
+enum
+{
+ DOMLEN= 48, /* authentication domain name length */
+ VLNUMSIZE= 22,
+};
+
static Dirtab consdir[]=
{
".", {Qdir, 0, QTDIR}, 0, DMDIR|0555,
+ "bintime", {Qbintime}, 24, 0664,
"cons", {Qcons}, 0, 0660,
"consctl", {Qconsctl}, 0, 0220,
- "sysctl", {Qsysctl}, 0, 0644,
+ "cputime", {Qcputime}, 6*NUMSIZE, 0444,
"drivers", {Qdrivers}, 0, 0444,
+ "hostdomain", {Qhostdomain}, DOMLEN, 0664,
"hostowner", {Qhostowner}, 0, 0644,
- "jit", {Qjit}, 0, 0666,
+ "jit", {Qjit}, 0, 0666, /* obsolete unless forth wants to use it */
"keyboard", {Qkeyboard}, 0, 0666,
- "klog", {Qklog}, 0, 0444,
+ "kmesg", {Qkmesg}, 0, 0440,
"kprint", {Qkprint}, 0, 0444,
- "scancode", {Qscancode}, 0, 0444,
- "memory", {Qmemory}, 0, 0444,
- "msec", {Qmsec}, NUMSIZE, 0444,
+ "memory", {Qmemory}, 0, 0444, /* not in 9front */
"null", {Qnull}, 0, 0666,
+ "osversion", {Qosversion}, 0, 0444,
+ "pid", {Qpid}, NUMSIZE, 0444,
+ "ppid", {Qppid}, NUMSIZE, 0444,
"random", {Qrandom}, 0, 0444,
- "notquiterandom", {Qnotquiterandom}, 0, 0444,
+ "reboot", {Qreboot}, 0, 0220,
+ "scancode", {Qscancode}, 0, 0444,
+ "sysctl", {Qsysctl}, 0, 0644, /* obsoleted by reboot and osversion */
"sysname", {Qsysname}, 0, 0664,
- "time", {Qtime}, 0, 0664,
- "user", {Quser}, 0, 0644,
+ "sysstat", {Qsysstat}, 0, 0664,
+ "time", {Qtime}, NUMSIZE+3*VLNUMSIZE, 0664,
+ "user", {Quser}, 0, 0666,
+ "zero", {Qzero}, 0, 0444,
+ "config", {Qconfig}, 0, 0444,
+ "mordor", {Qmordor}, 0, 0666,
};
ulong boottime; /* seconds since epoch at boot */
@@ -490,14 +518,12 @@
fddump()
{
Proc *p;
- Osenv *o;
int i;
Chan *c;
p = proctab(6);
- o = p->env;
- for(i = 0; i <= o->fgrp->maxfd; i++) {
- if((c = o->fgrp->fd[i]) == nil)
+ for(i = 0; i <= p->fgrp->maxfd; i++) {
+ if((c = p->fgrp->fd[i]) == nil)
continue;
print("%d: %s\n", i, c->path == nil? "???": c->path->s);
}
@@ -576,8 +602,10 @@
c = devopen(c, omode, consdir, nelem(consdir), devgen);
switch((u64)c->qid.path){
case Qconsctl:
- if(!iseve())
+ if(!iseve()){
+ print("consopen not eve\n");
error(Eperm);
+ }
qlock(&kbd);
kbd.ctl++;
qunlock(&kbd);
@@ -628,19 +656,25 @@
static s32
consread(Chan *c, void *buf, s32 n, s64 offset)
{
- int l;
- Osenv *o;
- int i;
- char *p, tmp[128];
+ Proc *o;
+ u32 l;
+ Mach *mp;
+ char *b, *bp;
+ char tmp[256];
+ int i, k, id;
+ extern char configfile[];
if(n <= 0)
return n;
- o = up->env;
+ o = up;
switch((u64)c->qid.path){
+
case Qdir:
return devdirread(c, buf, n, consdir, nelem(consdir), devgen);
+
case Qsysctl:
return readstr(offset, buf, n, VERSION);
+
case Qcons:
/* below belongs in kbdfs */
qlock(&kbd);
@@ -698,76 +732,154 @@
/* commented until the above is removed
error(Egreg); */
- case Qtime:
- snprint(tmp, sizeof(tmp), "%.lld", (vlong)mseconds()*1000);
+ case Qcputime:
+ k = offset;
+ if(k >= 6*NUMSIZE)
+ return 0;
+ if(k+n > 6*NUMSIZE)
+ n = 6*NUMSIZE - k;
+ /* easiest to format in a separate buffer and copy out */
+ for(i=0; i<6 && NUMSIZE*i<k+n; i++){
+ l = up->time[i];
+ if(i == TReal)
+ l = MACHP(0)->ticks - l;
+ readnum(0, tmp+NUMSIZE*i, NUMSIZE, tk2ms(l), NUMSIZE);
+ }
+ memmove(buf, tmp+k, n);
+ return n;
+
+ case Qjit:
+ snprint(tmp, sizeof(tmp), "%d", cflag);
return readstr(offset, buf, n, tmp);
+ case Qkmesg:
+ /*
+ * This is unlocked to avoid tying up a process
+ * that's writing to the buffer. kmesg.n never
+ * gets smaller, so worst case the reader will
+ * see a slurred buffer.
+ */
+ if(offset >= kmesg.n)
+ n = 0;
+ else{
+ if(offset+n > kmesg.n)
+ n = kmesg.n - offset;
+ memmove(buf, kmesg.buf+offset, n);
+ }
+ return n;
+
+ case Qkprint:
+ return qread(kprintoq, buf, n);
+
+ case Qpid:
+ return readnum((ulong)offset, buf, n, up->pid, NUMSIZE);
+
+ case Qppid:
+ return readnum((ulong)offset, buf, n, up->parentpid, NUMSIZE);
+
+ case Qtime:
+ return readtime((ulong)offset, buf, n);
+
+ case Qbintime:
+ return readbintime(buf, n);
+
case Qhostowner:
- return readstr(offset, buf, n, eve);
+ return readstr((ulong)offset, buf, n, eve);
+ case Qhostdomain:
+ return readstr((ulong)offset, buf, n, hostdomain);
+
case Quser:
- return readstr(offset, buf, n, o->user);
+ return readstr((ulong)offset, buf, n, up->user);
- case Qjit:
- snprint(tmp, sizeof(tmp), "%d", cflag);
- return readstr(offset, buf, n, tmp);
-
case Qnull:
return 0;
- case Qmsec:
- return readnum(offset, buf, n, TK2MS(MACHP(0)->ticks), NUMSIZE);
+ case Qconfig:
+ return readstr((ulong)offset, buf, n, conffile);
+ case Qsysstat:
+ b = smalloc(conf.nmach*(NUMSIZE*11+1) + 1); /* +1 for NUL */
+ bp = b;
+ for(id = 0; id < MAXMACH; id++) {
+ if(active.machs[id]) {
+ mp = MACHP(id);
+ readnum(0, bp, NUMSIZE, id, NUMSIZE);
+ bp += NUMSIZE;
+ readnum(0, bp, NUMSIZE, mp->cs, NUMSIZE);
+ bp += NUMSIZE;
+ readnum(0, bp, NUMSIZE, mp->intr, NUMSIZE);
+ bp += NUMSIZE;
+ readnum(0, bp, NUMSIZE, mp->syscall, NUMSIZE);
+ bp += NUMSIZE;
+ readnum(0, bp, NUMSIZE, mp->pfault, NUMSIZE);
+ bp += NUMSIZE;
+ readnum(0, bp, NUMSIZE, mp->tlbfault, NUMSIZE);
+ bp += NUMSIZE;
+ readnum(0, bp, NUMSIZE, mp->tlbpurge, NUMSIZE);
+ bp += NUMSIZE;
+ readnum(0, bp, NUMSIZE, mp->load, NUMSIZE);
+ bp += NUMSIZE;
+ l = mp->perf.period;
+ if(l == 0)
+ l = 1;
+ readnum(0, bp, NUMSIZE,
+ (mp->perf.avg_inidle*100)/l, NUMSIZE);
+ bp += NUMSIZE;
+ readnum(0, bp, NUMSIZE,
+ (mp->perf.avg_inintr*100)/l, NUMSIZE);
+ bp += NUMSIZE;
+ *bp++ = '\n';
+ }
+ }
+ if(waserror()){
+ free(b);
+ nexterror();
+ }
+ n = readstr((ulong)offset, buf, n, b);
+ free(b);
+ poperror();
+ return n;
+
case Qsysname:
if(sysname == nil)
return 0;
- return readstr(offset, buf, n, sysname);
+ return readstr((ulong)offset, buf, n, sysname);
- case Qnotquiterandom:
- genrandom(buf, n);
- return n;
-
case Qrandom:
return randomread(buf, n);
- case Qmemory:
- return poolread(buf, n, offset);
-
case Qdrivers:
- p = malloc(READSTR);
- if(p == nil)
- error(Enomem);
- l = 0;
+ b = smalloc(READSTR);
+ k = 0;
for(i = 0; devtab[i] != nil; i++)
- l += snprint(p+l, READSTR-l, "#%C %s\n", devtab[i]->dc, devtab[i]->name);
+ k += snprint(b+k, READSTR-k, "#%C %s\n",
+ devtab[i]->dc, devtab[i]->name);
if(waserror()){
- free(p);
+ free(b);
nexterror();
}
- n = readstr(offset, buf, n, p);
- free(p);
+ n = readstr((ulong)offset, buf, n, b);
poperror();
+ free(b);
return n;
- case Qklog:
- /*
- * This is unlocked to avoid tying up a process
- * that's writing to the buffer. kmesg.n never
- * gets smaller, so worst case the reader will
- * see a slurred buffer.
- */
- if(offset >= kmesg.n)
- n = 0;
- else{
- if(offset+n > kmesg.n)
- n = kmesg.n - offset;
- memmove(buf, kmesg.buf+offset, n);
- }
+ case Qzero:
+ memset(buf, 0, n);
return n;
- case Qkprint:
- return qread(kprintoq, buf, n);
+ case Qmemory:
+ return poolread(buf, n, offset);
+ case Qmordor:
+ error("one does not simply read from mordor");
+ return 0;
+
+ case Qosversion:
+ snprint(tmp, sizeof tmp, "2000 %ud", kerndate);
+ n = readstr((ulong)offset, buf, n, tmp);
+ return n;
+
default:
print("consread %llud\n", c->qid.path);
error(Egreg);
@@ -778,14 +890,17 @@
static s32
conswrite(Chan *c, void *va, s32 n, s64 offset)
{
- s64 t;
+ char buf[256];
long l, bp;
- char *a = va;
+ char *a;
+ Mach *mp;
+ int id;
Cmdbuf *cb;
Cmdtab *ct;
- char buf[256];
+ s64 t;
int x;
+ a = va;
switch((u64)c->qid.path){
case Qcons:
/*
@@ -827,45 +942,21 @@
case Qtime:
- if(n >= sizeof(buf))
- n = sizeof(buf)-1;
- strncpy(buf, a, n);
- buf[n] = 0;
- t = strtoll(buf, 0, 0)/1000000;
- boottime = t - TK2SEC(MACHP(0)->ticks);
- break;
-
- case Qhostowner:
if(!iseve())
error(Eperm);
- if(offset != 0 || n >= sizeof(buf))
- error(Ebadarg);
- memmove(buf, a, n);
- buf[n] = '\0';
- if(n > 0 && buf[n-1] == '\n')
- buf[--n] = 0;
- if(n <= 0)
- error(Ebadarg);
- renameuser(eve, buf);
- renameproguser(eve, buf);
- kstrdup(&eve, buf);
- kstrdup(&up->env->user, buf);
- break;
+ return writetime(a, n);
- case Quser:
+ case Qbintime:
if(!iseve())
error(Eperm);
- if(offset != 0)
- error(Ebadarg);
- if(n <= 0 || n >= sizeof(buf))
- error(Ebadarg);
- strncpy(buf, a, n);
- buf[n] = 0;
- if(buf[n-1] == '\n')
- buf[n-1] = 0;
- kstrdup(&up->env->user, buf);
- break;
+ return writebintime(a, n);
+ case Qhostowner:
+ return hostownerwrite(a, n);
+
+ case Qhostdomain:
+ return hostdomainwrite(a, n);
+
case Qjit:
if(n >= sizeof(buf))
n = sizeof(buf)-1;
@@ -877,13 +968,61 @@
cflag = x;
return n;
+ case Quser:
+ return userwrite(a, n);
+
case Qnull:
break;
+ case Qconfig:
+ error(Eperm);
+ break;
+
+ case Qreboot:
+ if(!iseve())
+ error(Eperm);
+ cb = parsecmd(a, n);
+
+ if(waserror()) {
+ free(cb);
+ nexterror();
+ }
+ ct = lookupcmd(cb, rebootmsg, nelem(rebootmsg));
+ switch(ct->index) {
+ case CMreboot:
+ /* TODO rebootcmd(cb->nf-1, cb->f+1); */
+ break;
+ case CMpanic:
+ *(ulong*)0=0;
+ panic("/dev/reboot");
+ case CMrdb:
+ if(consdebug == nil)
+ consdebug = rdb;
+ consdebug();
+ break;
+ }
+ poperror();
+ free(cb);
+ break;
+
+ case Qsysstat:
+ for(id = 0; id < MAXMACH; id++) {
+ if(active.machs[id]) {
+ mp = MACHP(id);
+ mp->cs = 0;
+ mp->intr = 0;
+ mp->syscall = 0;
+ mp->pfault = 0;
+ mp->tlbfault = 0;
+ mp->tlbpurge = 0;
+ }
+ }
+ break;
+
case Qsysname:
if(offset != 0)
error(Ebadarg);
- if(n <= 0 || n >= sizeof(buf))
+ if(n <= 0 || n >= sizeof buf)
error(Ebadarg);
strncpy(buf, a, n);
buf[n] = 0;
@@ -891,6 +1030,10 @@
buf[n-1] = 0;
kstrdup(&sysname, buf);
break;
+
+ case Qmordor:
+ error("one does not simply write into mordor");
+ return 0;
case Qsysctl:
if(!iseve())
@@ -983,6 +1126,203 @@
randomread(&x, sizeof(x));
return x;
+}
+
+static uvlong uvorder = 0x0001020304050607ULL;
+
+static uchar*
+le2vlong(vlong *to, uchar *f)
+{
+ uchar *t, *o;
+ int i;
+
+ t = (uchar*)to;
+ o = (uchar*)&uvorder;
+ for(i = 0; i < sizeof(vlong); i++)
+ t[o[i]] = f[i];
+ return f+sizeof(vlong);
+}
+
+static uchar*
+vlong2le(uchar *t, vlong from)
+{
+ uchar *f, *o;
+ int i;
+
+ f = (uchar*)&from;
+ o = (uchar*)&uvorder;
+ for(i = 0; i < sizeof(vlong); i++)
+ t[i] = f[o[i]];
+ return t+sizeof(vlong);
+}
+
+static long order = 0x00010203;
+
+static uchar*
+le2long(long *to, uchar *f)
+{
+ uchar *t, *o;
+ int i;
+
+ t = (uchar*)to;
+ o = (uchar*)ℴ
+ for(i = 0; i < sizeof(long); i++)
+ t[o[i]] = f[i];
+ return f+sizeof(long);
+}
+
+static uchar*
+long2le(uchar *t, long from)
+{
+ uchar *f, *o;
+ int i;
+
+ f = (uchar*)&from;
+ o = (uchar*)ℴ
+ for(i = 0; i < sizeof(long); i++)
+ t[i] = f[o[i]];
+ return t+sizeof(long);
+}
+
+char *Ebadtimectl = "bad time control";
+
+/*
+ * like the old #c/time but with added info. Return
+ *
+ * secs nanosecs fastticks fasthz
+ */
+static int
+readtime(ulong off, char *buf, int n)
+{
+ vlong nsec, ticks;
+ long sec;
+ char str[7*NUMSIZE];
+
+ nsec = todget(&ticks);
+ if(fasthz == 0LL)
+ fastticks((uvlong*)&fasthz);
+ sec = nsec/1000000000ULL;
+ snprint(str, sizeof(str), "%*lud %*llud %*llud %*llud ",
+ NUMSIZE-1, sec,
+ VLNUMSIZE-1, nsec,
+ VLNUMSIZE-1, ticks,
+ VLNUMSIZE-1, fasthz);
+ return readstr(off, buf, n, str);
+}
+
+/*
+ * set the time in seconds
+ */
+static int
+writetime(char *buf, int n)
+{
+ char b[13];
+ long i;
+ vlong now;
+
+ if(n >= sizeof(b))
+ error(Ebadtimectl);
+ strncpy(b, buf, n);
+ b[n] = 0;
+ i = strtol(b, 0, 0);
+ if(i <= 0)
+ error(Ebadtimectl);
+ now = i*1000000000LL;
+ todset(now, 0, 0);
+ return n;
+}
+
+/*
+ * read binary time info. all numbers are little endian.
+ * ticks and nsec are syncronized.
+ */
+static int
+readbintime(char *buf, int n)
+{
+ int i;
+ vlong nsec, ticks;
+ uchar *b = (uchar*)buf;
+
+ i = 0;
+ if(fasthz == 0LL)
+ fastticks((uvlong*)&fasthz);
+ nsec = todget(&ticks);
+ if(n >= 3*sizeof(uvlong)){
+ vlong2le(b+2*sizeof(uvlong), fasthz);
+ i += sizeof(uvlong);
+ }
+ if(n >= 2*sizeof(uvlong)){
+ vlong2le(b+sizeof(uvlong), ticks);
+ i += sizeof(uvlong);
+ }
+ if(n >= 8){
+ vlong2le(b, nsec);
+ i += sizeof(vlong);
+ }
+ return i;
+}
+
+/*
+ * set any of the following
+ * - time in nsec
+ * - nsec trim applied over some seconds
+ * - clock frequency
+ */
+static int
+writebintime(char *buf, int n)
+{
+ uchar *p;
+ vlong delta;
+ long period;
+
+ if(--n <= 0)
+ error(Ebadtimectl);
+ p = (uchar*)buf + 1;
+ switch(*buf){
+ case 'n':
+ if(n < sizeof(vlong))
+ error(Ebadtimectl);
+ le2vlong(&delta, p);
+ todset(delta, 0, 0);
+ break;
+ case 'd':
+ if(n < sizeof(vlong)+sizeof(long))
+ error(Ebadtimectl);
+ p = le2vlong(&delta, p);
+ le2long(&period, p);
+ todset(-1, delta, period);
+ break;
+ case 'f':
+ if(n < sizeof(uvlong))
+ error(Ebadtimectl);
+ le2vlong(&fasthz, p);
+ if(fasthz <= 0)
+ error(Ebadtimectl);
+ todsetfreq(fasthz);
+ break;
+ }
+ return n+1;
+}
+
+void
+cpushutdown(void)
+{
+ int ms, once;
+
+ once = active.machs[m->machno];
+ active.machs[m->machno] = 0;
+ active.exiting = 1;
+
+ if(once)
+ iprint("cpu%d: exiting\n", m->machno);
+
+ /* wait for any other processors to shutdown */
+ spllo();
+ for(ms = 5*1000; ms > 0; ms -= TK2MS(2)){
+ delay(TK2MS(2));
+ if(memchr(active.machs, 1, MAXMACH) == nil && consactive() == 0)
+ break;
+ }
}
/* all the below belongs in kbdfs */
--- a/os/port/devdup.c
+++ b/os/port/devdup.c
@@ -10,7 +10,7 @@
static int
dupgen(Chan *c, char *, Dirtab*, int, int s, Dir *dp)
{
- Fgrp *fgrp = up->env->fgrp;
+ Fgrp *fgrp = up->fgrp;
Chan *f;
static int perm[] = { 0400, 0200, 0600, 0 };
int p;
@@ -83,7 +83,7 @@
f->offset = 0;
}else{
/* fd file */
- f = fdtochan(up->env->fgrp, fd, openmode(omode), 0, 1);
+ f = fdtochan(up->fgrp, fd, openmode(omode), 0, 1);
cclose(c);
}
if(omode & OCEXEC)
@@ -108,7 +108,7 @@
twicefd = c->qid.path - 1;
fd = twicefd/2;
if(twicefd & 1){
- c = fdtochan(up->env->fgrp, fd, -1, 0, 1);
+ c = fdtochan(up->fgrp, fd, -1, 0, 1);
if(waserror()){
cclose(c);
nexterror();
--- a/os/port/devenv.c
+++ b/os/port/devenv.c
@@ -10,27 +10,53 @@
enum
{
+ Maxenvsize = 1*MB,
+ Maxvalsize = Maxenvsize/2,
+
DELTAENV = 32,
- Maxenvsize = 16300,
};
static Egrp *envgrp(Chan *c);
-static int envwriteable(Chan *c);
+static int envwritable(Chan *c);
static Egrp confegrp; /* global environment group containing the kernel configuration */
+#define PATH(p,i) ((uvlong)(p) << 32 | (i))
+#define QID(quidpath) ((uint)(quidpath) & 0x7FFFFFFF)
+
static Evalue*
-envlookup(Egrp *eg, char *name, ulong qidpath)
+envindex(Egrp *eg, uvlong qidpath)
{
- Evalue *e, *ee;
+ Evalue *e;
+ int i;
- e = eg->ent;
- for(ee = e + eg->nent; e < ee; e++){
- if(e->qid.path == qidpath
- || (name != nil && name[0] == e->name[0] && strcmp(e->name, name) == 0))
- return e;
+ i = QID(qidpath);
+ if(i >= eg->nent)
+ return nil;
+ e = eg->ent[i];
+ if(e != nil && e->path != qidpath)
+ return nil;
+ return e;
+}
+
+static Evalue**
+envhash(Egrp *eg, char *name)
+{
+ uint c, h = 0;
+ while(c = *name++)
+ h = h*131 + c;
+ return &eg->hash[h % ENVHASH];
+}
+
+static Evalue*
+lookupname(Evalue *e, char *name)
+{
+ while(e != nil){
+ if(strcmp(e->name, name) == 0)
+ break;
+ e = e->hash;
}
- return nil;
+ return e;
}
static int
@@ -38,29 +64,41 @@
{
Egrp *eg;
Evalue *e;
+ Qid q;
+ eg = envgrp(c);
if(s == DEVDOTDOT){
+ c->qid.vers = eg->vers;
devdir(c, c->qid, "#e", 0, eve, 0775, dp);
return 1;
}
-
- eg = envgrp(c);
rlock(eg);
- if(name != nil)
- e = envlookup(eg, name, -1);
- else if(s < eg->nent)
- e = &eg->ent[s];
- else
- e = nil;
- if(e == nil || name != nil && (strlen(e->name) >= sizeof(up->genbuf))) {
+ if((c->qid.type & QTDIR) == 0) {
+ e = envindex(eg, c->qid.path);
+ if(e == nil)
+ goto Notfound;
+ } else if(name != nil) {
+ if(strlen(name) >= sizeof(up->genbuf))
+ goto Notfound;
+ e = lookupname(*envhash(eg, name), name);
+ if(e == nil)
+ goto Notfound;
+ } else if(s < eg->nent) {
+ e = eg->ent[s];
+ if(e == nil) {
+ runlock(eg);
+ return 0; /* deleted, try next */
+ }
+ } else {
+Notfound:
runlock(eg);
return -1;
}
-
/* make sure name string continues to exist after we release lock */
- kstrcpy(up->genbuf, e->name, sizeof up->genbuf);
- devdir(c, e->qid, up->genbuf, e->len, eve,
- eg == &confegrp || eg != up->env->egrp ? 0664: 0666, dp);
+ kstrcpy(up->genbuf, e->name, sizeof(up->genbuf));
+ mkqid(&q, e->path, e->vers, QTFILE);
+ devdir(c, q, up->genbuf, e->len, eve,
+ eg == &confegrp || eg != up->egrp ? 0664: 0666, dp);
runlock(eg);
return 1;
}
@@ -85,23 +123,41 @@
static Walkqid*
envwalk(Chan *c, Chan *nc, char **name, int nname)
{
- return devwalk(c, nc, name, nname, 0, 0, envgen);
+ return devwalk(c, nc, name, nname, nil, 0, envgen);
}
static int
envstat(Chan *c, uchar *db, int n)
{
- if(c->qid.type & QTDIR)
- c->qid.vers = envgrp(c)->vers;
- return devstat(c, db, n, 0, 0, envgen);
+ return devstat(c, db, n, nil, 0, envgen);
}
+static void*
+envrealloc(Egrp *eg, void *old, int newsize)
+{
+ int oldsize = old != nil ? msize(old) : 0;
+ void *new;
+
+ if(newsize == 0){
+ eg->alloc -= oldsize;
+ free(old);
+ return nil;
+ }
+ if(newsize < 0 || eg != &confegrp && (eg->alloc + newsize) - oldsize > Maxenvsize)
+ error(Enomem);
+ new = realloc(old, newsize);
+ if(new == nil)
+ error(Enomem);
+ eg->alloc += msize(new) - oldsize;
+ setmalloctag(new, getcallerpc(&eg));
+ return new;
+}
+
static Chan*
envopen(Chan *c, u32 omode)
{
Egrp *eg;
Evalue *e;
- int trunc;
eg = envgrp(c);
if(c->qid.type & QTDIR) {
@@ -109,14 +165,14 @@
error(Eperm);
}
else {
- trunc = omode & OTRUNC;
- if(omode != OREAD && !envwriteable(c))
+ int trunc = omode & OTRUNC;
+ if(omode != OREAD && !envwritable(c))
error(Eperm);
if(trunc)
wlock(eg);
else
rlock(eg);
- e = envlookup(eg, nil, c->qid.path);
+ e = envindex(eg, c->qid.path);
if(e == nil) {
if(trunc)
wunlock(eg);
@@ -124,12 +180,12 @@
runlock(eg);
error(Enonexist);
}
- if(trunc && e->value != nil) {
- e->qid.vers++;
- free(e->value);
- e->value = nil;
+ if(trunc && e->len > 0) {
+ e->value = envrealloc(eg, e->value, 0); /* free */
e->len = 0;
+ e->vers++;
}
+ c->qid.vers = e->vers;
if(trunc)
wunlock(eg);
else
@@ -147,12 +203,14 @@
envcreate(Chan *c, char *name, u32 omode, u32)
{
Egrp *eg;
- Evalue *e;
+ Evalue *e, **h;
+ int n, i;
- if(c->qid.type != QTDIR || !envwriteable(c))
+ if(c->qid.type != QTDIR || !envwritable(c))
error(Eperm);
- if(strlen(name) >= sizeof(up->genbuf))
+ n = strlen(name)+1;
+ if(n > sizeof(up->genbuf))
error(Etoolong);
omode = openmode(omode);
@@ -163,28 +221,33 @@
nexterror();
}
- if(envlookup(eg, name, -1) != nil)
+ h = envhash(eg, name);
+ if(lookupname(*h, name) != nil)
error(Eexist);
- if(eg->nent == eg->ment){
- Evalue *tmp;
+ for(i = eg->low; i < eg->nent; i++)
+ if(eg->ent[i] == nil)
+ break;
- eg->ment += DELTAENV;
- if((tmp = realloc(eg->ent, sizeof(eg->ent[0])*eg->ment)) == nil){
- eg->ment -= DELTAENV;
- error(Enomem);
- }
- eg->ent = tmp;
+ if(i >= eg->nent){
+ if((eg->nent % DELTAENV) == 0)
+ eg->ent = envrealloc(eg, eg->ent, (eg->nent+DELTAENV) * sizeof(Evalue*));
+ i = eg->nent++;
+ eg->ent[i] = nil;
+ eg->low = i;
}
- eg->vers++;
- e = &eg->ent[eg->nent++];
+
+ e = envrealloc(eg, nil, sizeof(Evalue)+n);
+ memmove(e->name, name, n);
e->value = nil;
e->len = 0;
- e->name = smalloc(strlen(name)+1);
- strcpy(e->name, name);
- mkqid(&e->qid, ++eg->path, 0, QTFILE);
- c->qid = e->qid;
-
+ e->vers = 0;
+ e->path = PATH(++eg->path, i);
+ e->hash = *h, *h = e;
+ eg->ent[i] = e;
+ eg->low = i+1;
+ eg->vers++;
+ mkqid(&c->qid, e->path, e->vers, QTFILE);
wunlock(eg);
poperror();
incref(eg);
@@ -192,7 +255,7 @@
c->offset = 0;
c->mode = omode;
c->flag |= COPEN;
- return;
+ /* return c; */
}
static void
@@ -199,22 +262,35 @@
envremove(Chan *c)
{
Egrp *eg;
- Evalue *e;
+ Evalue *e, **h;
+ int i;
- if(c->qid.type & QTDIR || !envwriteable(c))
+ if(c->qid.type & QTDIR || !envwritable(c))
error(Eperm);
eg = envgrp(c);
wlock(eg);
- e = envlookup(eg, nil, c->qid.path);
+ e = envindex(eg, c->qid.path);
if(e == nil){
wunlock(eg);
error(Enonexist);
}
- free(e->name);
- free(e->value);
- *e = eg->ent[--eg->nent];
+ for(h = envhash(eg, e->name); *h != nil; h = &(*h)->hash){
+ if(*h == e){
+ *h = e->hash;
+ break;
+ }
+ }
+ i = QID(c->qid.path);
+ eg->ent[i] = nil;
+ if(i < eg->low)
+ eg->low = i;
eg->vers++;
+
+ /* free */
+ envrealloc(eg, e->value, 0);
+ envrealloc(eg, e, 0);
+
wunlock(eg);
}
@@ -241,10 +317,9 @@
{
Egrp *eg;
Evalue *e;
- ulong offset = off;
if(c->qid.type & QTDIR)
- return devdirread(c, a, n, 0, 0, envgen);
+ return devdirread(c, a, n, nil, 0, envgen);
eg = envgrp(c);
rlock(eg);
@@ -252,19 +327,17 @@
runlock(eg);
nexterror();
}
-
- e = envlookup(eg, nil, c->qid.path);
+ e = envindex(eg, c->qid.path);
if(e == nil)
error(Enonexist);
- if(offset >= e->len || e->value == nil)
+ if(off >= e->len)
n = 0;
- else if(offset + n > e->len)
- n = e->len - offset;
+ else if(off + n > e->len)
+ n = e->len - off;
if(n <= 0)
n = 0;
else
- memmove(a, e->value+offset, n);
-
+ memmove(a, e->value+off, n);
runlock(eg);
poperror();
return n;
@@ -273,17 +346,10 @@
static s32
envwrite(Chan *c, void *a, s32 n, s64 off)
{
- char *s;
- ulong len;
Egrp *eg;
Evalue *e;
- ulong offset = off;
+ int diff;
- if(n <= 0)
- return 0;
- if(offset > Maxenvsize || n > (Maxenvsize - offset))
- error(Etoobig);
-
eg = envgrp(c);
wlock(eg);
if(waserror()){
@@ -290,24 +356,22 @@
wunlock(eg);
nexterror();
}
-
- e = envlookup(eg, nil, c->qid.path);
+ e = envindex(eg, c->qid.path);
if(e == nil)
error(Enonexist);
-
- len = offset+n;
- if(len > e->len) {
- s = realloc(e->value, len);
- if(s == nil)
- error(Enomem);
- memset(s+offset, 0, n);
- e->value = s;
- e->len = len;
- }
- memmove(e->value+offset, a, n);
- e->qid.vers++;
+ if(off > Maxvalsize || n > (Maxvalsize - off))
+ error(Etoobig);
+ diff = (off+n) - e->len;
+ if(diff > 0)
+ e->value = envrealloc(eg, e->value, e->len+diff);
+ else
+ diff = 0;
+ memmove(e->value+off, a, n); /* might fault */
+ if(off > e->len)
+ memset(e->value+e->len, 0, off-e->len);
+ e->len += diff;
+ e->vers++;
eg->vers++;
-
wunlock(eg);
poperror();
return n;
@@ -331,38 +395,64 @@
envwrite,
devbwrite,
envremove,
- devwstat
+ devwstat,
};
-/*
- * kernel interface to environment variables
- */
-Egrp*
-newegrp(void)
+void
+envcpy(Egrp *to, Egrp *from)
{
- Egrp *e;
+ Evalue *e, *ne, **h;
+ int i, n;
- e = smalloc(sizeof(Egrp));
- incref(e);
- return e;
+ rlock(from);
+ if(waserror()){
+ runlock(from);
+ nexterror();
+ }
+ to->nent = 0;
+ to->ent = envrealloc(to, nil, ROUND(from->nent, DELTAENV) * sizeof(Evalue*));
+ for(i = 0; i < from->nent; i++){
+ e = from->ent[i];
+ if(e == nil)
+ continue;
+ h = envhash(to, e->name);
+ n = strlen(e->name)+1;
+ ne = envrealloc(to, nil, sizeof(Evalue)+n);
+ memmove(ne->name, e->name, n);
+ ne->value = nil;
+ ne->len = 0;
+ ne->vers = 0;
+ ne->path = PATH(++to->path, to->nent);
+ ne->hash = *h, *h = ne;
+ to->ent[to->nent++] = ne;
+ if(e->len > 0){
+ ne->value = envrealloc(to, ne->value, e->len);
+ memmove(ne->value, e->value, e->len);
+ ne->len = e->len;
+ }
+ }
+ to->low = to->nent;
+ runlock(from);
+ poperror();
}
void
closeegrp(Egrp *eg)
{
- Evalue *e, *ee;
+ Evalue *e;
+ int i;
- if(eg == nil)
+ if(decref(eg) || eg == &confegrp)
return;
- if(decref(eg) == 0 && eg != &confegrp){
- e = eg->ent;
- for(ee = e + eg->nent; e < ee; e++){
- free(e->name);
- free(e->value);
- }
- free(eg->ent);
- free(eg);
+ for(i = 0; i < eg->nent; i++){
+ e = eg->ent[i];
+ if(e == nil)
+ continue;
+ free(e->value);
+ free(e);
}
+ free(eg->ent);
+ free(eg);
}
static Egrp*
@@ -369,41 +459,16 @@
envgrp(Chan *c)
{
if(c->aux == nil)
- return up->env->egrp;
+ return up->egrp;
return c->aux;
}
static int
-envwriteable(Chan *c)
+envwritable(Chan *c)
{
- return c->aux == nil || c->aux == up->env->egrp || iseve();
+ return c->aux == nil || c->aux == up->egrp || iseve();
}
-/* same as envcpy() of 9front */
-void
-egrpcpy(Egrp *to, Egrp *from)
-{
- Evalue *e, *ee, *ne;
-
- rlock(from);
- to->ment = ROUND(from->nent, DELTAENV);
- to->ent = smalloc(to->ment*sizeof(to->ent[0]));
- ne = to->ent;
- e = from->ent;
- for(ee = e + from->nent; e < ee; e++, ne++){
- ne->name = smalloc(strlen(e->name)+1);
- strcpy(ne->name, e->name);
- if(e->value != nil){
- ne->value = smalloc(e->len);
- memmove(ne->value, e->value, e->len);
- ne->len = e->len;
- }
- mkqid(&ne->qid, ++to->path, 0, QTFILE);
- }
- to->nent = from->nent;
- runlock(from);
-}
-
/*
* to let the kernel set environment variables
*/
@@ -412,7 +477,7 @@
{
Chan *c;
char buf[2*KNAMELEN];
-
+
snprint(buf, sizeof(buf), "#e%s/%s", conf?"c":"", ename);
c = namec(buf, Acreate, OWRITE, 0666);
devtab[c->type]->write(c, eval, strlen(eval), 0);
@@ -428,30 +493,31 @@
getconfenv(void)
{
Egrp *eg = &confegrp;
- Evalue *e, *ee;
+ Evalue *e;
char *p, *q;
- int n;
+ int i, n;
rlock(eg);
- if(waserror()) {
- runlock(eg);
- nexterror();
+ n = 1;
+ for(i = 0; i < eg->nent; i++){
+ e = eg->ent[i];
+ if(e == nil)
+ continue;
+ n += strlen(e->name)+e->len+2;
}
-
- /* determine size */
- n = 0;
- e = eg->ent;
- for(ee = e + eg->nent; e < ee; e++)
- n += strlen(e->name) + e->len + 2;
-
- p = malloc(n + 1);
- if(p == nil)
+ p = malloc(n);
+ if(p == nil){
+ runlock(eg);
error(Enomem);
+ }
q = p;
- e = eg->ent;
- for(ee = e + eg->nent; e < ee; e++){
- strcpy(q, e->name);
- q += strlen(q) + 1;
+ for(i = 0; i < eg->nent; i++){
+ e = eg->ent[i];
+ if(e == nil)
+ continue;
+ n = strlen(e->name)+1;
+ memmove(q, e->name, n);
+ q += n;
memmove(q, e->value, e->len);
q[e->len] = 0;
/* move up to the first null */
@@ -458,8 +524,19 @@
q += strlen(q) + 1;
}
*q = '\0';
-
runlock(eg);
- poperror();
+
return p;
+}
+
+Egrp*
+newegrp(void)
+{
+ Egrp *e;
+
+ e = malloc(sizeof(Egrp));
+ if(e == nil)
+ panic("no memory for Egrp\n");
+ incref(e);
+ return e;
}
--- a/os/port/devforth.c
+++ b/os/port/devforth.c
@@ -161,9 +161,9 @@
}
}else if(cistrncmp("KEEPFDS", s, 7) == 0){
s += 7;
- p.keepfds = smalloc(up->env->fgrp->nfd*sizeof(s32));
+ p.keepfds = smalloc(up->fgrp->nfd*sizeof(s32));
for(i=0; ;i++,p.nkeepfds++){
- if(i>=up->env->fgrp->nfd){
+ if(i>=up->fgrp->nfd){
print("should not happen\n");
error(Etoobig);
}
@@ -174,9 +174,9 @@
}
}else if(cistrncmp("CLOSEFDS", s, 8) == 0){
s += 8;
- p.closefds = smalloc(up->env->fgrp->nfd*sizeof(s32));
+ p.closefds = smalloc(up->fgrp->nfd*sizeof(s32));
for(i=0; ;i++,p.nclosefds++){
- if(i>=up->env->fgrp->nfd){
+ if(i>=up->fgrp->nfd){
print("should not happen\n");
error(Etoobig);
}
@@ -330,8 +330,6 @@
void
goforth(void *fmem)
{
- up->type = Forth;
-
/* load dictionary */
loadforthdictionary((u8*)fmem);
print("goforth pid %d forthmem 0x%zx end 0x%zx forthmem+RSTACK 0x%zx\n",
@@ -376,24 +374,24 @@
p->fpsave = up->fpsave;
p->nerrlab = 0;
- kstrdup(&p->env->user, up->env->user);
+ kstrdup(&p->user, up->user);
if(params->newenv == 1)
eg = newegrp();
else{
- eg = up->env->egrp;
+ eg = up->egrp;
if(eg != nil)
incref(eg);
}
- p->env->egrp = eg;
+ p->egrp = eg;
pg = newpgrp();
if(params->newns == 0)
- pgrpcpy(pg, up->env->pgrp);
+ pgrpcpy(pg, up->pgrp);
if(pg == nil)
panic("newforthproc: nil process group\n");
pg->nodevs = params->nodevs;
- p->env->pgrp = pg;
+ p->pgrp = pg;
/*
shmem = 0, NOSHMEM no shared memory
@@ -410,10 +408,10 @@
incref(up->shm);
}
- fg = dupfgrp(up->env->fgrp);
+ fg = dupfgrp(up->fgrp);
if(fg == nil)
panic("newforthproc: nil file descriptor group\n");
- p->env->fgrp = fg;
+ p->fgrp = fg;
if(params->redirfds == 1){
/* similar to kdup() */
@@ -630,7 +628,7 @@
if(name != nil && strcmp(name, up->genbuf) != 0)
return -1;
mkqid(&q, Qfprocdir|((slot+1)<<QSHIFT), pid, QTDIR);
- devdir(c, q, up->genbuf, 0, p->env->user, 0555, dp);
+ devdir(c, q, up->genbuf, 0, p->user, 0555, dp);
DBG("forthgen Qforthdir s %d returning Dir\n"
" name %s qid.path 0x%zux slot %d qid %d qid.vers %d qid.type %d 0x%ux\n"
" mode 0x%ux type 0x%ux\n",
@@ -649,11 +647,11 @@
switch(s){
case 0:
mkqid(&q, path|Qctl, c->qid.vers, QTFILE);
- devdir(c, q, "ctl", 0, p->env->user, 0600, dp);
+ devdir(c, q, "ctl", 0, p->user, 0600, dp);
break;
case 1:
mkqid(&q, path|Qvars, c->qid.vers, QTFILE);
- devdir(c, q, "vars", 0, p->env->user, 0600, dp);
+ devdir(c, q, "vars", 0, p->user, 0600, dp);
break;
default:
return -1;
@@ -756,7 +754,7 @@
{
if(p == up)
return;
- if(strcmp(up->env->user, "none") != 0)
+ if(strcmp(up->user, "none") != 0)
return;
if(iseve())
return;
@@ -778,7 +776,7 @@
resrcwait("no procs for kproc");
}
p->fisgo = 0; /* until the pctl message comes through */
- kstrdup(&p->env->user, up->env->user);
+ kstrdup(&p->user, up->user);
if(fhead == nil){
fhead = ftail = p;
--- a/os/port/devmnt.c
+++ b/os/port/devmnt.c
@@ -283,7 +283,7 @@
r->request.type = Tauth;
r->request.afid = c->fid;
- r->request.uname = up->env->user;
+ r->request.uname = up->user;
r->request.aname = spec;
mountrpc(m, r);
@@ -340,7 +340,7 @@
r->request.afid = NOFID;
else
r->request.afid = ac->fid;
- r->request.uname = up->env->user;
+ r->request.uname = up->user;
r->request.aname = spec;
mountrpc(m, r);
@@ -396,6 +396,7 @@
alloc = 0;
wq = smalloc(sizeof(Walkqid)+(nname-1)*sizeof(Qid));
if(waserror()){
+print("mntwalk waserror() for mntralloc pid %ud %r\n", up->pid);
if(alloc && wq->clone!=nil)
cclose(wq->clone);
free(wq);
@@ -418,6 +419,7 @@
wq->clone = nc;
if(waserror()) {
+print("mntwalk waserror() for mountrpc pid %ud %r\n", up->pid);
mntfree(r);
nexterror();
}
@@ -994,13 +996,21 @@
t = r->reply.type;
switch(t) {
case Rerror:
+ print("mountrpc: Rerror %s proc %s pid %ud: mismatch from %s %s rep %#p tag %d fid %d T%d R%d rp %d\n",
+ r->reply.ename, up->text, up->pid, chanpath(m->c), chanpath(r->c),
+ r, r->request.tag, r->request.fid, r->request.type,
+ r->reply.type, r->reply.tag);
error(r->reply.ename);
case Rflush:
+ print("mountrpc: Rflush proc %s pid %ud: mismatch from %s %s rep %#p tag %d fid %d T%d R%d rp %d\n",
+ up->text, up->pid, chanpath(m->c), chanpath(r->c),
+ r, r->request.tag, r->request.fid, r->request.type,
+ r->reply.type, r->reply.tag);
error(Eintr);
default:
if(t == r->request.type+1)
break;
- print("mnt: proc %s %ud: mismatch from %s %s rep %#p tag %d fid %d T%d R%d rp %d\n",
+ print("mountrpc: default proc %s pid %ud: mismatch from %s %s rep %#p tag %d fid %d T%d R%d rp %d\n",
up->text, up->pid, chanpath(m->c), chanpath(r->c),
r, r->request.tag, r->request.fid, r->request.type,
r->reply.type, r->reply.tag);
@@ -1018,13 +1028,13 @@
print("mountio waserror() at the start pid %ud\n", up->pid);
if(m->rip == up)
mntgate(m);
- if(strcmp(up->env->errstr, Eintr) != 0 || waserror()){
+ if(strcmp(up->errstr, Eintr) != 0 || waserror()){
r = mntflushfree(m, r);
switch(r->request.type){
case Tremove:
case Tclunk:
/* botch, abandon fid */
- if(strcmp(up->env->errstr, Ehungup) != 0)
+ if(strcmp(up->errstr, Ehungup) != 0)
r->c->fid = 0;
}
nexterror();
@@ -1044,12 +1054,13 @@
n = sizeS2M(&r->request);
b = allocb(n);
if(waserror()){
+print("mountio waserror() convS2M pid %ud\n", up->pid);
freeb(b);
nexterror();
}
n = convS2M(&r->request, b->wp, n);
if(n <= 0 || n > m->msize) {
- print("mountio: proc %s %lud: convS2M returned %d for tag %d fid %d T%d\n",
+ print("mountio: proc %s pid %lud: convS2M returned %d for tag %d fid %d T%d\n",
up->text, up->pid, n, r->request.tag, r->request.fid, r->request.type);
error(Emountrpc);
}
--- a/os/port/devpipe.c
+++ b/os/port/devpipe.c
@@ -4,30 +4,25 @@
#include "dat.h"
#include "fns.h"
#include "../port/error.h"
-#include "interp.h"
-#define NETTYPE(x) ((ulong)(x)&0x1f)
-#define NETID(x) (((ulong)(x))>>5)
-#define NETQID(i,t) (((i)<<5)|(t))
+#include "netif.h"
typedef struct Pipe Pipe;
struct Pipe
{
QLock;
- Pipe* next;
+ Pipe *next;
int ref;
ulong path;
- Queue* q[2];
+ long perm;
+ Queue *q[2];
int qref[2];
- Dirtab *pipedir;
- char* user;
};
-static struct
+struct
{
Lock;
ulong path;
- int pipeqsize;
} pipealloc;
enum
@@ -37,32 +32,25 @@
Qdata1,
};
-static
Dirtab pipedir[] =
{
".", {Qdir,0,QTDIR}, 0, DMDIR|0500,
- "data", {Qdata0}, 0, 0660,
- "data1", {Qdata1}, 0, 0660,
+ "data", {Qdata0}, 0, 0600,
+ "data1", {Qdata1}, 0, 0600,
};
+#define NPIPEDIR 3
static void
-freepipe(Pipe *p)
+pipeinit(void)
{
- if(p != nil){
- free(p->user);
- free(p->q[0]);
- free(p->q[1]);
- free(p->pipedir);
- free(p);
+ if(conf.pipeqsize == 0){
+ if(conf.nmach > 1)
+ conf.pipeqsize = 256*1024;
+ else
+ conf.pipeqsize = 32*1024;
}
}
-static void
-pipeinit(void)
-{
- pipealloc.pipeqsize = 32*1024;
-}
-
/*
* create a pipe, no streams are created until an open
*/
@@ -73,35 +61,34 @@
Chan *c;
c = devattach('|', spec);
- p = malloc(sizeof(Pipe));
- if(p == 0)
- error(Enomem);
if(waserror()){
- freepipe(p);
+ chanfree(c);
nexterror();
}
- p->pipedir = malloc(sizeof(pipedir));
- if (p->pipedir == 0)
- error(Enomem);
- memmove(p->pipedir, pipedir, sizeof(pipedir));
- kstrdup(&p->user, up->env->user);
+ p = malloc(sizeof(Pipe));
+ if(p == 0)
+ exhausted("memory");
p->ref = 1;
- p->q[0] = qopen(pipealloc.pipeqsize, 0, 0, 0);
- if(p->q[0] == 0)
- error(Enomem);
- p->q[1] = qopen(pipealloc.pipeqsize, 0, 0, 0);
- if(p->q[1] == 0)
- error(Enomem);
+ p->q[0] = qopen(conf.pipeqsize, 0, 0, 0);
+ if(p->q[0] == 0){
+ free(p);
+ exhausted("memory");
+ }
+ p->q[1] = qopen(conf.pipeqsize, 0, 0, 0);
+ if(p->q[1] == 0){
+ qfree(p->q[0]);
+ free(p);
+ exhausted("memory");
+ }
poperror();
lock(&pipealloc);
p->path = ++pipealloc.path;
unlock(&pipealloc);
+ p->perm = pipedir[Qdata0].perm;
- c->qid.path = NETQID(2*p->path, Qdir);
- c->qid.vers = 0;
- c->qid.type = QTDIR;
+ mkqid(&c->qid, NETQID(2*p->path, Qdir), 0, QTDIR);
c->aux = p;
c->dev = 0;
return c;
@@ -108,10 +95,10 @@
}
static int
-pipegen(Chan *c, char *, Dirtab *tab, int ntab, int i, Dir *dp)
+pipegen(Chan *c, char*, Dirtab *tab, int ntab, int i, Dir *dp)
{
- int id, len;
- Qid qid;
+ Qid q;
+ int len;
Pipe *p;
if(i == DEVDOTDOT){
@@ -121,9 +108,10 @@
i++; /* skip . */
if(tab==0 || i>=ntab)
return -1;
+
tab += i;
p = c->aux;
- switch(NETTYPE(tab->qid.path)){
+ switch((ulong)tab->qid.path){
case Qdata0:
len = qlen(p->q[0]);
break;
@@ -134,27 +122,25 @@
len = tab->length;
break;
}
- id = NETID(c->qid.path);
- qid.path = NETQID(id, tab->qid.path);
- qid.vers = 0;
- qid.type = QTFILE;
- devdir(c, qid, tab->name, len, eve, tab->perm, dp);
+ mkqid(&q, NETQID(NETID(c->qid.path), tab->qid.path), 0, QTFILE);
+ devdir(c, q, tab->name, len, eve, p->perm, dp);
return 1;
}
static Walkqid*
-pipewalk(Chan *c, Chan *nc, char **name, s32 nname)
+pipewalk(Chan *c, Chan *nc, char **name, int nname)
{
Walkqid *wq;
Pipe *p;
- p = c->aux;
- wq = devwalk(c, nc, name, nname, p->pipedir, nelem(pipedir), pipegen);
+ wq = devwalk(c, nc, name, nname, pipedir, NPIPEDIR, pipegen);
if(wq != nil && wq->clone != nil && wq->clone != c){
+ p = c->aux;
qlock(p);
p->ref++;
if(c->flag & COPEN){
+ print("channel open in pipewalk\n");
switch(NETTYPE(c->qid.path)){
case Qdata0:
p->qref[0]++;
@@ -174,20 +160,18 @@
{
Pipe *p;
Dir dir;
- Dirtab *tab;
p = c->aux;
- tab = p->pipedir;
switch(NETTYPE(c->qid.path)){
case Qdir:
- devdir(c, c->qid, ".", 0, eve, DMDIR|0555, &dir);
+ devdir(c, c->qid, ".", 0, eve, 0555, &dir);
break;
case Qdata0:
- devdir(c, c->qid, tab[1].name, qlen(p->q[0]), eve, tab[1].perm, &dir);
+ devdir(c, c->qid, "data", qlen(p->q[0]), eve, p->perm, &dir);
break;
case Qdata1:
- devdir(c, c->qid, tab[2].name, qlen(p->q[1]), eve, tab[2].perm, &dir);
+ devdir(c, c->qid, "data1", qlen(p->q[1]), eve, p->perm, &dir);
break;
default:
panic("pipestat");
@@ -198,6 +182,36 @@
return n;
}
+static int
+pipewstat(Chan* c, uchar* db, int n)
+{
+ int m;
+ Dir *dir;
+ Pipe *p;
+
+ p = c->aux;
+ if(strcmp(up->user, eve) != 0)
+ error(Eperm);
+ if(NETTYPE(c->qid.path) == Qdir)
+ error(Eisdir);
+
+ dir = smalloc(sizeof(Dir)+n);
+ if(waserror()){
+ free(dir);
+ nexterror();
+ }
+ m = convM2D(db, n, &dir[0], (char*)&dir[1]);
+ if(m == 0)
+ error(Eshortstat);
+ if(!emptystr(dir[0].uid))
+ error("can't change owner");
+ if(dir[0].mode != ~0UL)
+ p->perm = dir[0].mode;
+ poperror();
+ free(dir);
+ return m;
+}
+
/*
* if the stream doesn't exist, create it
*/
@@ -215,25 +229,16 @@
return c;
}
- openmode(omode); /* check it */
-
p = c->aux;
qlock(p);
- if(waserror()){
- qunlock(p);
- nexterror();
- }
switch(NETTYPE(c->qid.path)){
case Qdata0:
- devpermcheck(p->user, p->pipedir[1].perm, omode);
p->qref[0]++;
break;
case Qdata1:
- devpermcheck(p->user, p->pipedir[2].perm, omode);
p->qref[1]++;
break;
}
- poperror();
qunlock(p);
c->mode = openmode(omode);
@@ -273,7 +278,7 @@
}
}
-
+
/*
* if both sides are closed, they are reusable
*/
@@ -288,7 +293,9 @@
p->ref--;
if(p->ref == 0){
qunlock(p);
- freepipe(p);
+ free(p->q[0]);
+ free(p->q[1]);
+ free(p);
} else
qunlock(p);
}
@@ -302,7 +309,7 @@
switch(NETTYPE(c->qid.path)){
case Qdir:
- return devdirread(c, va, n, p->pipedir, nelem(pipedir), pipegen);
+ return devdirread(c, va, n, pipedir, NPIPEDIR, pipegen);
case Qdata0:
return qread(p->q[0], va, n);
case Qdata1:
@@ -331,22 +338,20 @@
}
/*
- * a write to a closed pipe causes an exception to be sent to
- * the prog.
+ * a write to a closed pipe causes a note to be sent to
+ * the process.
*/
static s32
pipewrite(Chan *c, void *va, s32 n, s64)
{
Pipe *p;
- Prog *r;
+ if(!islo())
+ print("pipewrite hi %#p\n", getcallerpc(&c));
if(waserror()) {
- /* avoid exceptions when pipe is a mounted queue */
- if((c->flag & CMSG) == 0) {
- r = up->iprog;
- if(r != nil && r->kill == nil)
- r->kill = "write on closed pipe";
- }
+ /* avoid notes when pipe is a mounted queue */
+ if((c->flag & CMSG) == 0)
+ postnote(up, 1, "sys: write on closed pipe", NUser);
nexterror();
}
@@ -370,20 +375,15 @@
}
static s32
-pipebwrite(Chan *c, Block *bp, u32 junk)
+pipebwrite(Chan *c, Block *bp, u32)
{
long n;
Pipe *p;
- Prog *r;
- USED(junk);
if(waserror()) {
- /* avoid exceptions when pipe is a mounted queue */
- if((c->flag & CMSG) == 0) {
- r = up->iprog;
- if(r != nil && r->kill == nil)
- r->kill = "write on closed pipe";
- }
+ /* avoid notes when pipe is a mounted queue */
+ if((c->flag & CMSG) == 0)
+ postnote(up, 1, "sys: write on closed pipe", NUser);
nexterror();
}
@@ -403,42 +403,6 @@
}
poperror();
- return n;
-}
-
-static s32
-pipewstat(Chan *c, uchar *dp, s32 n)
-{
- Dir *d;
- Pipe *p;
- int d1;
-
- if (c->qid.type&QTDIR)
- error(Eperm);
- p = c->aux;
- if(strcmp(up->env->user, p->user) != 0)
- error(Eperm);
- d = smalloc(sizeof(*d)+n);
- if(waserror()){
- free(d);
- nexterror();
- }
- n = convM2D(dp, n, d, (char*)&d[1]);
- if(n == 0)
- error(Eshortstat);
- d1 = NETTYPE(c->qid.path) == Qdata1;
- if(!emptystr(d->name)){
- validwstatname(d->name);
- if(strlen(d->name) >= KNAMELEN)
- error(Efilename);
- if(strcmp(p->pipedir[1+!d1].name, d->name) == 0)
- error(Eexist);
- kstrcpy(p->pipedir[1+d1].name, d->name, KNAMELEN);
- }
- if(d->mode != ~0UL)
- p->pipedir[d1 + 1].perm = d->mode & 0777;
- poperror();
- free(d);
return n;
}
--- a/os/port/devproc.c
+++ b/os/port/devproc.c
@@ -210,7 +210,7 @@
if(name != nil && strcmp(name, up->genbuf) != 0)
return -1;
mkqid(&qid, (s+1)<<QSHIFT, pid, QTDIR);
- devdir(c, qid, up->genbuf, 0, p->env->user, 0555, dp);
+ devdir(c, qid, up->genbuf, 0, p->user, 0555, dp);
return 1;
}
if(c->qid.path == Qtrace){
@@ -254,7 +254,7 @@
}
mkqid(&qid, path|tab->qid.path, c->qid.vers, QTFILE);
- devdir(c, qid, tab->name, len, p->env->user, perm, dp);
+ devdir(c, qid, tab->name, len, p->user, perm, dp);
return 1;
}
@@ -313,7 +313,7 @@
{
if(p == up)
return;
- if(strcmp(up->env->user, "none") != 0)
+ if(strcmp(up->user, "none") != 0)
return;
if(iseve())
return;
@@ -338,7 +338,7 @@
pp = proctab(i);
if(pp->noteid != noteid || pp->kp)
continue;
- if(strcmp(pp->env->user, p->env->user) == 0){
+ if(strcmp(pp->user, p->user) == 0){
nonone(pp);
setnoteid(p, noteid);
return;
@@ -534,13 +534,13 @@
error(Eprocdied);
nonone(p);
- if(strcmp(up->env->user, p->env->user) != 0 && !iseve())
+ if(strcmp(up->user, p->user) != 0 && !iseve())
error(Eperm);
- if(!emptystr(d->uid) && strcmp(d->uid, p->env->user) != 0){
+ if(!emptystr(d->uid) && strcmp(d->uid, p->user) != 0){
if(strcmp(d->uid, "none") != 0 && !iseve())
error(Eperm);
- kstrdup(&p->env->user, d->uid);
+ kstrdup(&p->user, d->uid);
}
/* p->procmode determines default mode for files in /proc */
if(d->mode != ~0UL)
@@ -653,7 +653,7 @@
char flag[10], *srv;
int i;
- pg = p->env->pgrp;
+ pg = p->pgrp;
if(pg == nil || pg->dot == nil || p->pid != PID(c->qid))
error(Eprocdied);
@@ -1017,7 +1017,7 @@
"%11lud %11lud %11lud "
"%11lud %11lud %11lud\n",*/
"%11ud\n",
- p->text, p->env->user, sps,
+ p->text, p->user, sps,
/* tk2ms(p->time[TUser]),
tk2ms(p->time[TSys]),
tk2ms(MACHP(0)->ticks - p->time[TReal]),
@@ -1274,7 +1274,7 @@
}
Dev procdevtab = {
- 'o',
+ 'p',
"proc",
devreset,
@@ -1372,7 +1372,7 @@
if(fd < 0)
error(Ebadfd);
- f = p->env->fgrp;
+ f = p->fgrp;
if(f == nil)
error(Eprocdied);
--- a/os/port/devready.c
+++ b/os/port/devready.c
@@ -17,7 +17,7 @@
*/
enum
{
- NFD = 16,
+ NRFD = 16,
Qcanread = 0,
};
@@ -36,7 +36,7 @@
typedef struct Canread Canread;
struct Canread
{
- Readyfd rfd[NFD];
+ Readyfd rfd[NRFD];
s32 nrfd;
Queue *commq; /* queue for the different watcher kproc's to communicate */
};
@@ -206,7 +206,7 @@
break;
s = p;
nfd++;
- if(nfd > NFD)
+ if(nfd > NRFD)
error(Etoobig);
i = r->nrfd;
r->rfd[i].fd = fd;
--- a/os/port/devsd.c
+++ b/os/port/devsd.c
@@ -160,7 +160,7 @@
}
if(i >= unit->npart)
error(Ebadctl);
- if(strcmp(up->env->user, pp->user) && !iseve())
+ if(strcmp(up->user, pp->user) && !iseve())
error(Eperm);
pp->valid = 0;
pp->vers++;
@@ -793,7 +793,7 @@
qlock(&unit->ctl);
while(waserror()){
/* notification of media change; go around again */
- if(strcmp(up->env->errstr, Eio) == 0 && unit->sectors == 0 && nchange++ == 0){
+ if(strcmp(up->errstr, Eio) == 0 && unit->sectors == 0 && nchange++ == 0){
sdinitpart(unit);
continue;
}
@@ -1590,7 +1590,7 @@
break;
}
- if(strcmp(up->env->user, perm->user) && !iseve())
+ if(strcmp(up->user, perm->user) && !iseve())
error(Eperm);
d = smalloc(sizeof(Dir)+n);
--- a/os/port/devsrv.c
+++ b/os/port/devsrv.c
@@ -121,7 +121,7 @@
static int
srvcanattach(SrvFile *d)
{
- if(strcmp(d->user, up->env->user) == 0)
+ if(strcmp(d->user, up->user) == 0)
return 1;
/*
@@ -169,8 +169,8 @@
d->ref = 1;
kstrdup(&d->spec, spec);
- kstrdup(&d->user, up->env->user);
- snprint(srvname, sizeof(srvname), "srv%d", up->env->pgrp->pgrpid);
+ kstrdup(&d->user, up->user);
+ snprint(srvname, sizeof(srvname), "srv%d", up->pgrp->pgrpid);
kstrdup(&d->name, srvname);
d->perm = DMDIR|0770;
mkqid(&d->qid, dev.pathgen++, 0, QTDIR);
@@ -259,7 +259,7 @@
nexterror();
}
devpermcheck(sf->user, sf->perm, omode);
- if(omode&ORCLOSE && strcmp(sf->user, up->env->user) != 0)
+ if(omode&ORCLOSE && strcmp(sf->user, up->user) != 0)
error(Eperm);
if(sf->perm & DMEXCL && sf->opens != 0)
error(Einuse);
@@ -283,7 +283,7 @@
SrvFile *sf, *f;
sf = c->aux;
- if(strcmp(up->env->user, sf->user) != 0)
+ if(strcmp(up->user, sf->user) != 0)
error(Eperm);
d = smalloc(sizeof(*d)+n);
@@ -502,7 +502,7 @@
}
noperm = 0;
- if(remove && strcmp(sf->dir->user, up->env->user) != 0){
+ if(remove && strcmp(sf->dir->user, up->user) != 0){
noperm = 1;
remove = 0;
}
@@ -793,7 +793,7 @@
f->waitlist.prev = &f->waitlist;
kstrdup(&f->name, file);
- kstrdup(&f->user, up->env->user);
+ kstrdup(&f->user, up->user);
f->perm = 0666 & (~0666 | (s->perm & 0666));
f->length = 0;
f->ref = 2;
--- a/os/port/devssl.c
+++ b/os/port/devssl.c
@@ -276,7 +276,7 @@
dsnew(c, pp);
else {
if((perm & (s->perm>>6)) != perm
- && (strcmp(up->env->user, s->user) != 0
+ && (strcmp(up->user, s->user) != 0
|| (perm & s->perm) != perm))
error(Eperm);
@@ -307,7 +307,7 @@
s = dstate[CONV(c->qid)];
if(s == 0)
error(Ebadusefd);
- if(strcmp(s->user, up->env->user) != 0)
+ if(strcmp(s->user, up->user) != 0)
error(Eperm);
dir = smalloc(sizeof(Dir)+n);
@@ -1352,7 +1352,7 @@
fd = strtoul(p, 0, 0);
if(fd < 0)
error(Ebadarg);
- c = fdtochan(up->env->fgrp, fd, -1, 0, 1); /* error check and inc ref */
+ c = fdtochan(up->fgrp, fd, -1, 0, 1); /* error check and inc ref */
return c;
}
@@ -1421,7 +1421,7 @@
dshiwat++;
s->state = Sincomplete;
s->ref = 1;
- kstrdup(&s->user, up->env->user);
+ kstrdup(&s->user, up->user);
s->perm = 0660;
t = TYPE(ch->qid);
if(t == Qclonus)
--- a/os/port/dial.c
+++ b/os/port/dial.c
@@ -158,7 +158,7 @@
name[n] = 0;
for(p = name; *p == ' '; p++)
;
- sprint(name, "%d", strtoul(p, 0, 0));
+ sprint(name, "%lud", strtoul(p, 0, 0));
p = strrchr(clone, '/');
*p = 0;
if(ds->dir)
--- a/os/port/dis.c
+++ b/os/port/dis.c
@@ -310,11 +310,16 @@
swiprog(Prog *p)
{
Proc *q, *eq;
+ char c[ERRMAX];
+ snprint(c, ERRMAX, "interrupted by swiprog 0x%p\n", getcallerpc(&p));
+ /* print("swiprog: %s\n", c); */
q = proctab(0);
for(eq = q+conf.nproc; q < eq; q++) {
if(q->iprog == p) {
- postnote(q, 1, "interrupted", NUser);
+ /* postnote(q, 1, "interrupted by swiprog", NUser); */
+ postnote(q, 1, c, NUser);
+ /* dumpstack(); */
return;
}
}
@@ -954,12 +959,12 @@
Prog *r;
Module *m;
int broken;
- char *estr, msg[ERRMAX+2*KNAMELEN];
+ char *estr, msg[ERRMAX+2*KNAMELEN] = {'\0'};
estr = up->env->errstr;
broken = 0;
DBG("progexit estr %s\n", estr);
- if(estr[0] != '\0' && strcmp(estr, Eintr) != 0 && strncmp(estr, "fail:", 5) != 0)
+ if(emptystr(up->env->errstr) == 0 && strcmp(estr, Eintr) != 0 && strncmp(estr, "fail:", 5) != 0)
broken = 1;
r = up->iprog;
@@ -973,21 +978,13 @@
m = R.M->m;
if(broken){
- if(cflag){ /* only works on Plan9 for now */
- DBG("progexit cflag set\n");
- char *pc = strstr(estr, "pc=");
-
- if(pc != nil)
- R.PC = r->R.PC = (Inst*)strtol(pc+3, nil, 0); /* for debugging */
- }
- print("[%s] Broken: \"%s\" at 0x%p\n", m->name, estr, up->env->errpc);
+ print("[%s] Broken: \"%s\" at 0x%p pid %d\n", m->name, estr, up->env->errpc, up->pid);
+ if(1) dumpstack();
}
- if(r->exstr != nil)
+ if(r->exval != H)
DBG("progexit pid %d name %s estr %s exval %p exstr %s\n",
r->pid, m->name, estr, r->exval, r->exstr);
- else
- DBG("progexit pid %d name %s estr %s exval %p\n",
- r->pid, m->name, estr, r->exval);
+
// sh.b is matching on fail: not on "<pid> fail: "
snprint(msg, sizeof(msg), "%d \"%s\":%s", r->pid, m->name, estr);
// snprint(msg, sizeof(msg), "%s", estr);
@@ -1037,6 +1034,7 @@
panic("Interp faults with no dis prog");
/* cause an exception in the dis prog. */
+print("disfault caller 0x%p\n", getcallerpc(®));
error(msg);
}
@@ -1049,14 +1047,21 @@
startup();
+ /* cleans out the exception stack (error labels) */
while(waserror()) {
+ DBG("vmachine waserror() loop up->env->errstr %s\n", up->env->errstr);
if(up->type != Interp)
panic("vmachine: non-interp kproc");
- if(up->iprog != nil)
+ if(up->iprog != nil){
+ DBG("vmachine waserror() before acquire up->env->errstr %s\n", up->env->errstr);
acquire();
+ }
+ DBG("vmachine waserror() after acquire up->env->errstr %s\n", up->env->errstr);
if(handler(up->env->errstr) == 0) {
propex(currun(), up->env->errstr);
+ DBG("vmachine waserror() after propex up->env->errstr %s\n", up->env->errstr);
progexit();
+ DBG("vmachine waserror() after progexit\n");
}
up->env = &up->defenv;
}
--- a/os/port/exportfs.c
+++ b/os/port/exportfs.c
@@ -135,7 +135,7 @@
if(waserror())
return -1;
- c = fdtochan(up->env->fgrp, fd, ORDWR, 1, 1);
+ c = fdtochan(up->fgrp, fd, ORDWR, 1, 1);
poperror();
if(waserror()){
@@ -153,15 +153,15 @@
}
fs->r.ref = 1;
- pg = up->env->pgrp;
+ pg = up->pgrp;
fs->pgrp = pg;
incref(pg);
- eg = up->env->egrp;
+ eg = up->egrp;
fs->egrp = eg;
if(eg != nil)
incref(eg);
fs->fgrp = newfgrp(nil);
- kstrdup(&fs->user, up->env->user);
+ kstrdup(&fs->user, up->user);
fs->root = dc;
fs->io = c;
fs->pathgen = 0;
@@ -354,7 +354,7 @@
if(exdebug){
if(n < 0)
- print("exportproc %d shut down: %s\n", up->pid, up->env->errstr);
+ print("exportproc %d shut down: %s\n", up->pid, up->errstr);
else
print("exportproc %d shut down\n", up->pid);
}
@@ -550,17 +550,17 @@
unlock(fs);
unlock(&exq.l);
- up->env->pgrp = q->export->pgrp;
- up->env->egrp = q->export->egrp;
- up->env->fgrp = q->export->fgrp;
- kstrdup(&up->env->user, q->export->user);
+ up->pgrp = q->export->pgrp;
+ up->egrp = q->export->egrp;
+ up->fgrp = q->export->fgrp;
+ kstrdup(&up->user, q->export->user);
if(exdebug > 1)
print("exslave %d dispatch %F\n", up->pid, &q->in);
if(waserror()){
- print("exslave %d err %s\n", up->pid, up->env->errstr); /* shouldn't happen */
- err = up->env->errstr;
+ print("exslave %d err %s\n", up->pid, up->errstr); /* shouldn't happen */
+ err = up->errstr;
}else{
if(q->in.type >= Tmax || !fcalls[q->in.type]){
snprint(up->genbuf, sizeof(up->genbuf), "unknown message: %F", &q->in);
@@ -830,7 +830,7 @@
if(waserror()){
f->attached = 0;
Exputfid(fs, f);
- return up->env->errstr;
+ return up->errstr;
}
f->chan = cclone(fs->root);
f->qid = uqidalloc(fs, f->chan);
@@ -885,7 +885,7 @@
}
if(waserror())
- return up->env->errstr;
+ return up->errstr;
c = cclone(f->chan);
poperror();
qid = f->qid;
@@ -901,7 +901,7 @@
freeuqid(fs, qid);
Exputfid(fs, f);
if(i == 0)
- return up->env->errstr;
+ return up->errstr;
return nil;
}
freeuqid(fs, qid);
@@ -952,7 +952,7 @@
if(waserror()){
cclose(c);
Exputfid(fs, f);
- return up->env->errstr;
+ return up->errstr;
}
/* only save the mount head if it's a multiple element union */
@@ -996,7 +996,7 @@
}
if(waserror()){
Exputfid(fs, f);
- return up->env->errstr;
+ return up->errstr;
}
validname(t->name, 0);
if(t->name[0] == '.' && (t->name[1] == '\0' || t->name[1] == '.' && t->name[2] == '\0'))
@@ -1062,7 +1062,7 @@
if(waserror()) {
Exputfid(fs, f);
- return up->env->errstr;
+ return up->errstr;
}
c = f->chan;
if((c->flag & COPEN) == 0)
@@ -1127,7 +1127,7 @@
return Enofid;
if(waserror()){
Exputfid(fs, f);
- return up->env->errstr;
+ return up->errstr;
}
c = f->chan;
if((c->flag & COPEN) == 0)
@@ -1160,7 +1160,7 @@
if(waserror()){
cclose(c);
Exputfid(fs, f);
- return up->env->errstr;
+ return up->errstr;
}
n = devtab[c->type]->stat(c, r->stat, r->nstat);
if(n <= BIT16SZ)
@@ -1184,7 +1184,7 @@
return Enofid;
if(waserror()){
Exputfid(fs, f);
- return up->env->errstr;
+ return up->errstr;
}
validstat(t->stat, t->nstat); /* check name */
@@ -1215,7 +1215,7 @@
if(waserror()){
f->attached = 0;
Exputfid(fs, f);
- return up->env->errstr;
+ return up->errstr;
}
c = exmount(f->chan, nil, 0);
if(waserror()){
--- a/os/port/netif.c
+++ b/os/port/netif.c
@@ -184,7 +184,7 @@
case Ndataqid:
case Nctlqid:
f = nif->f[id];
- if(netown(f, up->env->user, omode&7) < 0)
+ if(netown(f, up->user, omode&7) < 0)
error(Eperm);
break;
}
@@ -216,9 +216,9 @@
p = malloc(READSTR);
if(p == nil)
return 0;
- j = snprint(p, READSTR, "in: %d\n", nif->inpackets);
+ j = snprint(p, READSTR, "in: %llud\n", nif->inpackets);
j += snprint(p+j, READSTR-j, "link: %d\n", nif->link);
- j += snprint(p+j, READSTR-j, "out: %d\n", nif->outpackets);
+ j += snprint(p+j, READSTR-j, "out: %llud\n", nif->outpackets);
j += snprint(p+j, READSTR-j, "crc errs: %d\n", nif->crcs);
j += snprint(p+j, READSTR-j, "overflows: %d\n", nif->overflows);
j += snprint(p+j, READSTR-j, "soft overflows: %d\n", nif->soverflows);
@@ -370,7 +370,7 @@
if(f == 0)
error(Enonexist);
- if(netown(f, up->env->user, OWRITE) < 0)
+ if(netown(f, up->user, OWRITE) < 0)
error(Eperm);
dir = smalloc(sizeof(Dir)+n);
@@ -530,7 +530,7 @@
}
f->inuse = 1;
qreopen(f->in);
- netown(f, up->env->user, 0);
+ netown(f, up->user, 0);
qunlock(f);
qunlock(nif);
poperror();
--- a/os/port/pgrp.c
+++ b/os/port/pgrp.c
@@ -283,13 +283,13 @@
* If we get into trouble, forceclosefgrp
* will bail us out.
*/
- up->env->closingfgrp = f;
+ up->closingfgrp = f;
for(i = 0; i <= f->maxfd; i++)
if((c = f->fd[i]) != nil){
f->fd[i] = nil;
cclose(c);
}
- up->env->closingfgrp = nil;
+ up->closingfgrp = nil;
free(f->fd);
free(f->flag);
@@ -313,12 +313,12 @@
Chan *c;
Fgrp *f;
- if(up->procctl != Proc_exitme || up->env->closingfgrp == nil){
+ if(up->procctl != Proc_exitme || up->closingfgrp == nil){
print("bad forceclosefgrp call");
return;
}
- f = up->env->closingfgrp;
+ f = up->closingfgrp;
for(i = 0; i <= f->maxfd; i++)
if((c = f->fd[i]) != nil){
f->fd[i] = nil;
@@ -406,3 +406,42 @@
(*key->pkfree)(key->pk);
free(key);
}
+
+/*
+ * kernel interface to shm
+ */
+Sgrp*
+shmgrpnew(void)
+{
+ Sgrp *e;
+
+ e = smalloc(sizeof(Sgrp));
+ incref(e);
+ return e;
+}
+
+void
+shmgrpclose(Sgrp *g)
+{
+ Svalue **ent, **eent;
+ s32 i;
+
+ if(g == nil)
+ return;
+ if(decref(g) <= 0){
+ ent = g->ent;
+ for(i = 0, eent = ent + g->nent; ent < eent; ent++, i++){
+ if(ent == nil)
+ continue;
+ wlock(*ent);
+ free((*ent)->name);
+ free((*ent)->value);
+ g->ent[i] = nil;
+ /* wunlock(ent); */
+ free(ent);
+ }
+ free(g->ent);
+ free(g);
+ }
+}
+
--- a/os/port/portdat.h
+++ b/os/port/portdat.h
@@ -27,7 +27,6 @@
typedef struct Mnt Mnt;
typedef struct Mhead Mhead;
typedef struct Note Note;
-typedef struct Osenv Osenv;
typedef struct Path Path;
typedef struct Perf Perf;
typedef struct Pgrp Pgrp;
@@ -94,31 +93,6 @@
void (*f)(void*); /* called with VM acquire()'d */
};
-struct Osenv
-{
- char *syserrstr; /* last error from a system call, errbuf0 or 1 - obsolete in inferno */
- intptr errpc;
- char *errstr; /* reason we're unwinding the error stack, errbuf1 or 0 */
- char errbuf0[ERRMAX];
- char errbuf1[ERRMAX];
- Pgrp *pgrp; /* Ref to namespace, working dir and root */
- Fgrp *fgrp; /* Ref to file descriptors */
- Egrp *egrp; /* Environment vars */
- Skeyset *sigs; /* Signed module keys */
- Rendez *rend; /* Synchro point */
- Queue *waitq; /* Info about dead children */
- Queue *childq; /* Info about children for debuggers */
- void *debug; /* Debugging master */
- s32 uid; /* Numeric user id for system */
- s32 gid; /* Numeric group id for system */
- char *user; /* Inferno user name */
- int fpuostate;
-
- /* from 9front */
- Rgrp *rgrp; /* Rendez group */
- Fgrp *closingfgrp; /* used during teardown */
-};
-
enum
{
Nopin = -1
@@ -397,6 +371,9 @@
DELTAFD= 20, /* allocation quantum for process file descriptors */
MAXNFD = 4000, /* max per process file descriptors */
MAXKEY = 8, /* keys for signed modules */
+ NFD = 100, /* per process file descriptors */
+ ENVLOG = 5,
+ ENVHASH = 1<<ENVLOG, /* Egrp hash for variable lookup */
};
#define REND(p,s) ((p)->rendhash[(s)&((1<<RENDLOG)-1)])
#define MOUNTH(p,qid) ((p)->mnthash[(qid).path&((1<<MNTLOG)-1)])
@@ -455,10 +432,12 @@
struct Evalue
{
- char *name;
char *value;
- s32 len;
- Qid qid;
+ int len;
+ ulong vers;
+ uvlong path; /* qid.path: Egrp.path << 32 | index (of Egrp.ent[]) */
+ Evalue *hash;
+ char name[];
};
struct Egrp
@@ -465,14 +444,13 @@
{
Ref;
RWlock;
- union{ /* array of Evalue's */
- Evalue *entries;
- Evalue *ent;
- };
- int nent;
- int ment;
- u32 path; /* qid.path of next Evalue to be allocated */
- u32 vers; /* of Egrp */
+ Evalue **ent;
+ int nent; /* numer of slots in ent[] */
+ int low; /* lowest free index in ent[] */
+ int alloc; /* bytes allocated for env */
+ ulong path; /* generator for qid path */
+ ulong vers; /* of Egrp */
+ Evalue *hash[ENVHASH]; /* hashtable for name lookup */
};
struct Signerkey
@@ -593,8 +571,7 @@
int n;
};
-/* inferno uses Osenv for environment information. It is cheaper to create
- * new processes with a default environment (spawn, not fork)
+/* Needs a default environment to create new processes (spawn, not fork)
*
* When using forth for the userspace, forth's stack is in fmem.
* The kstack is used for everything else. Hence, there is no
@@ -608,7 +585,7 @@
char *kstack; /* known to l.s in 9front to switch to the kernel stack on syscallentry */
Mach *mach; /* machine running this proc */
char *text;
- char *user; /* inferno uses Osenv.user */
+ char *user;
char *args;
int nargs; /* number of bytes of args */
@@ -632,15 +609,15 @@
QLock qwaitr;
Rendez waitr; /* Place to hang out in wait */
-/* QLock seglock; *//* locked whenever seg[] changes */
-/* Segment *seg[NSEG]; */
+/* QLock seglock; \/* locked whenever seg[] changes *\/
+ Segment *seg[NSEG];*/
-/* Pgrp *pgrp; */ /* Process group for namespace */
-/* Egrp *egrp; */ /* Environment group */
-/* Fgrp *fgrp; */ /* File descriptor group */
+ Pgrp *pgrp; /* Process group for namespace */
+ Egrp *egrp; /* Environment group */
+ Fgrp *fgrp; /* File descriptor group */
Rgrp *rgrp; /* Rendez group */
-/* Fgrp *closingfgrp;*/ /* used during teardown */
+ Fgrp *closingfgrp; /* used during teardown */
int insyscall;
u32 time[6]; /* User, Sys, Real; child U, S, R */
@@ -688,18 +665,17 @@
void (*kpfun)(void*);
void *kparg;
-/* Sargs s; *//* syscall arguments */
+/* Sargs s; *//* TODO uncomment this and scallnr syscall arguments */
/* int scallnr; *//* sys call number */
int nerrlab;
Label errlab[NERR];
- /* below fields are in Osenv */
-/* char *syserrstr; *//* last error from a system call, errbuf0 or 1 */
-/* char *errstr; *//* reason we're unwinding the error stack, errbuf1 or 0 */
-/* char errbuf0[ERRMAX];*/
-/* char errbuf1[ERRMAX];*/
- char genbuf[ERRMAX]; /* buffer used e.g. for last name element from namec */
-/* Chan *slash; part of Pgrp in inferno */
-/* Chan *dot; part of Pgrp in inferno */
+ char *syserrstr; /* last error from a system call, errbuf0 or 1 */
+ char *errstr; /* reason we're unwinding the error stack, errbuf1 or 0 */
+ char errbuf0[ERRMAX];
+ char errbuf1[ERRMAX];
+ char genbuf[128]; /* buffer used e.g. for last name element from namec */
+ Chan *slash;
+ Chan *dot;
Note note[NNOTE];
short nnote;
@@ -742,28 +718,15 @@
Watchpt *watchpt; /* watchpoints */
int nwatchpt;
- /* inferno specific fields */
- s32 type;
- void *prog; /* Dummy Prog for interp release */
- void *iprog;
- Osenv *env;
- Osenv defenv;
- s32 swipend; /* software interrupt pending for Prog TODO replace with notepending? */
- Lock sysio; /* note handler lock */
-
- /* inferno specific fields that are obsolete? */
- int fpstate;
- int killed; /* by swiproc */
- Proc *tlink;
- ulong movetime; /* next time process should switch processors */
- int dbgstop; /* don't run this kproc */
-
/* forth specific fields */
Proc *fprev, *fnext; /* forth processes linked list */
void *fmem; /* forth process memory - sandboxed except for macro primitives */
- void *shm; /* for devshm. move this into Osenv or maybe remove Osenv at some point to get more in sync with 9front */
+ void *shm; /* for devshm */
void *canread; /* for devready.c */
u8 fisgo; /* 0 while waiting for the pctl message */
+
+ /* not used by 9front. get rid of it at some point */
+ intptr errpc;
};
enum
@@ -812,6 +775,7 @@
extern int consoleprint;
extern Dev* devtab[];
extern char* eve;
+extern char hostdomain[];
extern int hwcurs;
extern Queue* kprintoq;
extern Queue *kbdq;
--- a/os/port/portfns.h
+++ b/os/port/portfns.h
@@ -129,6 +129,8 @@
void (*hwrandbuf)(void*, u32);
void hnputl(void*, u32);
void hnputs(void*, u16);
+long hostdomainwrite(char*, int);
+long hostownerwrite(char*, int);
void hzsched(void);
Block* iallocb(int);
void iallocsummary(void);
@@ -149,10 +151,12 @@
void kbdprocesschar(int); /* will go away with kbdfs */
int kbdputc(Queue*, int); /* will go away with kbdfs */
void kbdrepeat(int); /* will go away with kbdfs */
-void kproc(char*, void(*)(void*), void*, int);
+int kenter(Ureg*);
+void kexit(Ureg*);
int kfgrpclose(Fgrp*, int);
-void kprocchild(Proc*, void (*)(void*), void*);
int kprint(char*, ...);
+void kproc(char*, void(*)(void*), void*, int);
+void kprocchild(Proc*, void (*)(void*), void*);
void (*kproftick)(ulong);
void ksetenv(char*, char*, int);
void kstrcpy(char*, char*, int);
@@ -218,7 +222,7 @@
void notkilled(void);
int nrand(int);
uvlong ns2fastticks(uvlong);
-int okaddr(ulong, ulong, int);
+int okaddr(uintptr, u32, int);
u32 openmode(u32);
Block* packblock(Block*);
Block* padblock(Block*, int);
@@ -292,6 +296,7 @@
int readnum_vlong(ulong, char*, ulong, vlong, int);
int readstr(ulong, char*, ulong, char*);
void ready(Proc*);
+void rebootcmd(int, char**);
void reboot(void);
void renameproguser(char*, char*);
void renameuser(char*, char*);
@@ -310,6 +315,7 @@
ulong setnoteid(Proc*, ulong);
int setpri(int);
void setrealloctag(void*, uintptr);
+void setregisters(Ureg*, char*, char*, int);
void setupwatchpts(Proc*, Watchpt*, int);
Sgrp* shmgrpnew(void);
void shmgrpclose(Sgrp *g);
@@ -353,7 +359,8 @@
long unionread(Chan*, void*, long);
void unlock(Lock*);
void userinit(void);
-ulong userpc(void);
+uintptr userpc(void);
+long userwrite(char*, int);
void validname(char*, int);
char* validnamedup(char*, int);
void validstat(uchar*, int);
@@ -372,7 +379,7 @@
void* xspanalloc(uintptr, s32, uintptr);
void xsummary(void);
-void validaddr(void*, ulong, int);
+void validaddr(uintptr, ulong, int);
void* vmemchr(void*, int, int);
void hnputv(void*, u64);
u64 nhgetv(void*);
--- a/os/port/proc.c
+++ b/os/port/proc.c
@@ -153,7 +153,20 @@
}
/*
+ * in 9front, userureg() checks if the current code segment
+ * is the user's code segment. We use the same segment for
+ * the kernel and the user. Hence, return !Proc.kp. Proc.kp
+ * is true for a kernel process.
+ */
int
+userureg(Ureg *ur)
+{
+ if(ur == nil || ur->r14 == 0 || ((Proc*)(ur->r14))->kp == 0)
+ return 0;
+ return 1;
+}
+
+int
kenter(Ureg *ureg)
{
int user;
@@ -174,13 +187,12 @@
cycles(&t);
- \/* precise time accounting, kernel exit *\/
+ /* precise time accounting, kernel exit */
tos = (Tos*)(USTKTOP-sizeof(Tos));
tos->kcycles += t - up->kentry;
tos->pcycles = t + up->pcycles;
tos->pid = up->pid;
}
-*/
static void
procswitch(void)
@@ -687,16 +699,13 @@
p->ureg = nil;
p->dbgreg = nil;
p->nerrlab = 0;
- p->type = Unknown;
p->nlocks = 0;
p->delaysched = 0;
p->trace = 0;
- memset(&p->defenv, 0, sizeof(p->defenv));
- p->env = &p->defenv;
- kstrdup(&p->env->user, "*nouser");
- p->env->errstr = p->env->errbuf0;
- p->env->syserrstr = p->env->errbuf1;
+ kstrdup(&p->user, "*nouser");
+ p->errstr = p->errbuf0;
+ p->syserrstr = p->errbuf1;
/*
* a user process. kproc() can change it as it needs.
@@ -878,7 +887,7 @@
void
interrupted(void)
{
- if(up->procctl == Proc_exitme && up->env->closingfgrp != nil)
+ if(up->procctl == Proc_exitme && up->closingfgrp != nil)
forceclosefgrp();
error(Eintr);
}
@@ -1074,11 +1083,11 @@
break;
case Rendezvous:
/* Try and pull out of a rendezvous */
- lock(p->env->rgrp);
+ lock(p->rgrp);
if(p->state == Rendezvous) {
Proc *d, **l;
- l = &REND(p->env->rgrp, p->rendtag);
+ l = &REND(p->rgrp, p->rendtag);
for(d = *l; d != nil; d = d->rendhash) {
if(d == p) {
*l = p->rendhash;
@@ -1089,7 +1098,7 @@
l = &d->rendhash;
}
}
- unlock(p->env->rgrp);
+ unlock(p->rgrp);
break;
}
return ret;
@@ -1158,6 +1167,7 @@
}
+/*
void
notkilled(void)
{
@@ -1165,6 +1175,7 @@
up->killed = 0;
unlock(&up->rlock);
}
+*/
void
pexit(char *exitstr, int freemem)
@@ -1189,16 +1200,16 @@
/* nil out all the resources under lock (free later) */
qlock(&up->debug);
- fgrp = up->env->fgrp;
- up->env->fgrp = nil;
- egrp = up->env->egrp;
- up->env->egrp = nil;
- rgrp = up->env->rgrp;
- up->env->rgrp = nil;
-/* dot = up->env->pgrp->dot;
- up->env->pgrp->dot = nil;*/
- pgrp = up->env->pgrp;
- up->env->pgrp = nil;
+ fgrp = up->fgrp;
+ up->fgrp = nil;
+ egrp = up->egrp;
+ up->egrp = nil;
+ rgrp = up->rgrp;
+ up->rgrp = nil;
+/* dot = up->pgrp->dot;
+ up->pgrp->dot = nil;*/
+ pgrp = up->pgrp;
+ up->pgrp = nil;
qunlock(&up->debug);
if(fgrp != nil)
@@ -1395,7 +1406,7 @@
continue;
dumpaproc(p);
- dumppgrp(" ", p->env->pgrp);
+ dumppgrp(" ", p->pgrp);
}
}
@@ -1415,20 +1426,20 @@
qlock(&p->debug);
if(flags & KPDUPPG) {
- pg = up->env->pgrp;
+ pg = up->pgrp;
incref(pg);
- p->env->pgrp = pg;
+ p->pgrp = pg;
}
if(flags & KPDUPFDG) {
- fg = up->env->fgrp;
+ fg = up->fgrp;
incref(fg);
- p->env->fgrp = fg;
+ p->fgrp = fg;
}
if(flags & KPDUPENVG) {
- eg = up->env->egrp;
+ eg = up->egrp;
if(eg != nil)
incref(eg);
- p->env->egrp = eg;
+ p->egrp = eg;
}
p->nnote = 0;
@@ -1448,7 +1459,7 @@
/* this does all of the above 3 lines */
kprocchild(p, func, arg);
- kstrdup(&p->env->user, up->env->user);
+ kstrdup(&p->user, up->user);
kstrdup(&p->text, name);
kstrdup(&p->args, "");
p->nargs = 0;
@@ -1562,15 +1573,15 @@
panic("error stack too deep");
if(err == nil)
panic("error: nil parameter");
- kstrcpy(up->env->errstr, err, ERRMAX);
+ kstrcpy(up->errstr, err, ERRMAX);
setlabel(&up->errlab[NERR-1]);
if(emptystr(err) == 1){
DBG("error nil error err %s caller 0x%p up->pid %d\n", err, getcallerpc(&err), up->pid);
- up->env->errpc = 0;
+ up->errpc = 0;
/* showerrlabs("error == nil"); */
}else{
DBG("error err %s caller 0x%p up->pid %d\n", err, getcallerpc(&err), up->pid);
- up->env->errpc = getcallerpc(&err);
+ up->errpc = getcallerpc(&err);
/* proactively show issues */
/* print("up->nerrlab %d error %s raised by 0x%zx\n",
up->nerrlab, err, getcallerpc(&err)); */
@@ -1595,8 +1606,8 @@
char tmp[ERRMAX];
- kstrcpy(tmp, up->env->errstr, sizeof(tmp));
- kstrcpy(up->env->errstr, err, ERRMAX);
+ kstrcpy(tmp, up->errstr, sizeof(tmp));
+ kstrcpy(up->errstr, err, ERRMAX);
kstrcpy(err, tmp, size);
}
@@ -1606,8 +1617,8 @@
{
char tmp[ERRMAX];
- kstrcpy(tmp, up->env->errstr, sizeof(tmp));
- kstrcpy(up->env->errstr, err, ERRMAX);
+ kstrcpy(tmp, up->errstr, sizeof(tmp));
+ kstrcpy(up->errstr, err, ERRMAX);
kstrcpy(err, tmp, size);
}
@@ -1621,7 +1632,7 @@
va_start(arg, fmt);
vseprint(buf, buf+sizeof(buf), fmt, arg);
va_end(arg);
- kstrcpy(up->env->errstr, buf, ERRMAX);
+ kstrcpy(up->errstr, buf, ERRMAX);
}
void
@@ -1633,7 +1644,7 @@
va_start(arg, fmt);
vseprint(buf, buf+sizeof(buf), fmt, arg);
va_end(arg);
- kstrcpy(up->env->errstr, buf, ERRMAX);
+ kstrcpy(up->errstr, buf, ERRMAX);
}
/* for dynamic modules - functions not macros */
@@ -1654,7 +1665,7 @@
char*
enverror(void)
{
- return up->env->errstr;
+ return up->errstr;
}
void
@@ -1677,13 +1688,13 @@
setid(char *name, int owner)
{
if(!owner || iseve())
- kstrdup(&up->env->user, name);
+ kstrdup(&up->user, name);
}
/* TODO no idea what this rptproc() does
* something to do with repeat of tk actions
*/
-void
+/*void
rptwakeup(void *o, void *ar)
{
Rept *r;
@@ -1735,7 +1746,7 @@
poperror();
if(i == -1)
goto Wait;
- if(i == 0)
+ if(i == 0)
continue;
then = now;
acquire();
@@ -1766,7 +1777,7 @@
kproc(s, rproc, r, KPDUP);
return r;
}
-
+*/
s32
getpid(void)
{
--- a/os/port/sysfile.c
+++ b/os/port/sysfile.c
@@ -87,7 +87,7 @@
int fd, flag;
Fgrp *f;
- f = up->env->fgrp;
+ f = up->fgrp;
lock(f);
fd = findfreefd(f, 0);
if(fd < 0){
@@ -113,7 +113,7 @@
{
Fgrp *f;
- f = up->env->fgrp;
+ f = up->fgrp;
lock(f);
fd[0] = findfreefd(f, 0);
if(fd[0] < 0){
@@ -249,7 +249,7 @@
return -1;
c = namec(path, Atodir, 0, 0);
- pg = up->env->pgrp;
+ pg = up->pgrp;
cclose(pg->dot);
pg->dot = c;
poperror();
@@ -277,7 +277,7 @@
int
kclose(int fd)
{
- return kfgrpclose(up->env->fgrp, fd);
+ return kfgrpclose(up->fgrp, fd);
}
int
@@ -309,12 +309,12 @@
{
int fd;
Chan *c, *oc;
- Fgrp *f = up->env->fgrp;
+ Fgrp *f = up->fgrp;
if(waserror())
return -1;
- c = fdtochan(up->env->fgrp, old, -1, 0, 1);
+ c = fdtochan(up->fgrp, old, -1, 0, 1);
if(c->qid.type & QTAUTH)
error(Eperm);
fd = new;
@@ -355,7 +355,7 @@
if(waserror())
return -1;
- c = fdtochan(up->env->fgrp, fd, -1, 0, 1);
+ c = fdtochan(up->fgrp, fd, -1, 0, 1);
if(waserror()) {
cclose(c);
nexterror();
@@ -377,7 +377,7 @@
if(waserror())
return nil;
- c = fdtochan(up->env->fgrp, fd, -1, 0, 1);
+ c = fdtochan(up->fgrp, fd, -1, 0, 1);
s = nil;
if(c->path != nil){
s = malloc(c->path->len+1);
@@ -401,7 +401,7 @@
return -1;
validname(aname, 1);
- c = fdtochan(up->env->fgrp, fd, ORDWR, 0, 1);
+ c = fdtochan(up->fgrp, fd, ORDWR, 0, 1);
if(waserror()){
cclose(c);
nexterror();
@@ -441,7 +441,7 @@
if(arglen==0 || memchr(vers, 0, arglen)==0)
error(Ebadarg);
- c = fdtochan(up->env->fgrp, fd, ORDWR, 0, 1);
+ c = fdtochan(up->fgrp, fd, ORDWR, 0, 1);
if(waserror()){
cclose(c);
nexterror();
@@ -774,7 +774,7 @@
return -1;
validstat(buf, n);
- c = fdtochan(up->env->fgrp, fd, -1, 1, 1);
+ c = fdtochan(up->fgrp, fd, -1, 1, 1);
return (wstat(c, buf, n));
}
@@ -794,11 +794,11 @@
nexterror();
}
- if(up->env->pgrp->noattach)
+ if(up->pgrp->noattach)
error(Enoattach);
ac = nil;
- bc = fdtochan(up->env->fgrp, fd, ORDWR, 0, 1);
+ bc = fdtochan(up->fgrp, fd, ORDWR, 0, 1);
if(waserror()) {
if(ac != nil)
cclose(ac);
@@ -807,7 +807,7 @@
}
if(afd >= 0)
- ac = fdtochan(up->env->fgrp, afd, ORDWR, 0, 1);
+ ac = fdtochan(up->fgrp, afd, ORDWR, 0, 1);
c0 = mntattach(bc, ac, spec, flag&MCACHE);
poperror(); /* ac bc */
@@ -837,7 +837,7 @@
poperror();
cclose(c0);
if(ismount){
- fdclose(up->env->fgrp, fd, 0);
+ fdclose(up->fgrp, fd, 0);
poperror();
free(spec);
}
@@ -987,7 +987,7 @@
return -1;
}
- c = fdtochan(up->env->fgrp, fd, OREAD, 1, 1);
+ c = fdtochan(up->fgrp, fd, OREAD, 1, 1);
if(waserror()){
print("rread fd %d p 0x%p n %d fdtochan failed: %r\n", fd, p, n);
@@ -1122,7 +1122,7 @@
int n;
s64 off;
- c = fdtochan(up->env->fgrp, fd, -1, 1, 1);
+ c = fdtochan(up->fgrp, fd, -1, 1, 1);
if(waserror()){
cclose(c);
nexterror();
@@ -1261,7 +1261,7 @@
s64 off;
n = 0;
- c = fdtochan(up->env->fgrp, fd, OWRITE, 1, 1);
+ c = fdtochan(up->fgrp, fd, OWRITE, 1, 1);
if(c == nil)
print("rwrite fdtochan nil %r\n");
if(waserror()) {
@@ -1419,7 +1419,7 @@
if(waserror())
return nil;
- c = fdtochan(up->env->fgrp, fd, -1, 0, 1);
+ c = fdtochan(up->fgrp, fd, -1, 0, 1);
if(waserror()) {
cclose(c);
nexterror();
@@ -1540,7 +1540,7 @@
Chan *c;
int n;
- c = fdtochan(up->env->fgrp, fd, -1, 0, 1);
+ c = fdtochan(up->fgrp, fd, -1, 0, 1);
if(waserror()){
cclose(c);
return 0; /* n.b. */