ref: b35328f248cab12ae0760c237d1544842200510c
parent: 82dc85253c9ab0f7b9925c69e4b065ca4347ab04
author: halfwit <michaelmisch1985@gmail.com>
date: Tue Aug 26 12:11:58 EDT 2025
Updates to support rc expectations, etc
--- a/include/lib.h
+++ b/include/lib.h
@@ -27,11 +27,11 @@
#define nil ((void*)0)
typedef unsigned char p9_uchar;
+typedef unsigned char p9_u8int;
typedef unsigned int p9_uint;
-typedef uint8_t p9_u8int;
typedef unsigned int p9_ulong;
-typedef int p9_long;
-typedef signed char p9_schar;
+typedef int p9_long;
+typedef signed char p9_schar;
typedef unsigned short p9_ushort;
typedef unsigned int Rune;
typedef unsigned int p9_u32int;
@@ -88,8 +88,8 @@
RFCNAMEG = (1<<10),
RFCENVG = (1<<11),
RFCFDG = (1<<12),
- /*RFREND - (1<<13),*/
- /*RFNOMNT = (1<<14),*/
+ RFREND = (1<<13),
+ RFNOMNT = (1<<14),
};
/*
--- a/kern/Makefile
+++ b/kern/Makefile
@@ -18,7 +18,6 @@
devip-$(OS).$O\
devip.$O\
devmnt.$O\
- devproc.$O\
devpipe.$O\
devroot.$O\
devssl.$O\
--- a/kern/arm.c
+++ b/kern/arm.c
@@ -111,7 +111,7 @@
Rn = up->R + ((instr >> 16) & 15);
Rd = up->R + ((instr >> 12) & 15);
if (debug)
- print("single: Rn=%d Rd=%d offset=%.8ux\n", ((instr >> 16) & 15), ((instr >> 12) & 15), offset);+ print("single: Rn=%d Rd=%d offset=%.8ux pid=%d\n", ((instr >> 16) & 15), ((instr >> 12) & 15), offset, up->pid);if((instr & (fW | fP)) == fW)
invalid(instr);
if(Rn == up->R + 15) {@@ -161,7 +161,7 @@
Rd = up->R + ((instr >> 12) & 15);
Rn = up->R + ((instr >> 16) & 15);
if(debug)
- print("swap: Rm=%d Rd=%d Rn=%d\n", (instr & 15), ((instr >> 12) & 15), ((instr >> 16) & 15));+ print("swap: Rm=%d Rd=%d Rn=%d pid=%d\n", (instr & 15), ((instr >> 12) & 15), ((instr >> 16) & 15), up->pid);if(Rm == up->R + 15 || Rd == up->R + 15 || Rn == up->R + 15)
invalid(instr);
addr = *Rn;
@@ -254,7 +254,7 @@
default: result = 0; /* never happens */
}
if(debug)
- print("alu: Rn=%d Rd=%d op=%d operand=%.8ux\n", ((instr >> 16) & 15), ((instr >> 12) & 15), ((instr >> 21) & 15), operand);+ print("alu: Rn=%d Rd=%d op=%d operand=%.8ux pid=%d\n", ((instr >> 16) & 15), ((instr >> 12) & 15), ((instr >> 21) & 15), operand, up->pid); if(instr & fS) {up->CPSR &= ~FLAGS;
if(result == 0)
@@ -280,7 +280,7 @@
offset |= ~((1 << 24) - 1);
offset *= 4;
if(debug)
- print("branch: offset=%.8ux\n", offset);+ print("branch: offset=%.8ux pid=%d\n", offset, up->pid);if(instr & fLi)
up->R[14] = up->R[15];
up->R[15] += offset + 4;
@@ -306,7 +306,7 @@
Rn = up->R + ((instr >> 16) & 15);
Rd = up->R + ((instr >> 12) & 15);
if(debug)
- print("halfword: Rn=%d, Rd=%d\n", ((instr >> 16) & 15), ((instr >> 12) & 15)); + print("halfword: Rn=%d, Rd=%d pid=%d\n", ((instr >> 16) & 15), ((instr >> 12) & 15), up->pid); target = *Rn;
if(instr & fP)
target += offset;
@@ -337,7 +337,7 @@
invalid(instr);
Rn = up->R +((instr >> 16) & 15);
if(debug)
- print("block: Rn=%d\n", ((instr >> 16) & 15)); + print("block: Rn=%d pid=%d\n", ((instr >> 16) & 15), up->pid); targ = evenaddr(*Rn, 3);
if(instr & fU) { for(i = 0; i < 16; i++) {@@ -382,7 +382,7 @@
Rn = up->R + ((instr >> 12) & 15);
Rd = up->R + ((instr >> 16) & 15);
if(debug)
- print("multiply: Rm=%d Rs=%d Rn=%d Rd=%d\n", (instr & 15), ((instr >> 8) & 15), ((instr >> 12) & 15), ((instr >> 16) & 15));+ print("multiply: Rm=%d Rs=%d Rn=%d Rd=%d pid=%d\n", (instr & 15), ((instr >> 8) & 15), ((instr >> 12) & 15), ((instr >> 16) & 15), up->pid);if(Rd == Rm || Rm == up->R + 15 || Rs == up->R + 15 || Rn == up->R + 15 || Rd == up->R + 15)
invalid(instr);
res = *Rm * *Rs;
@@ -438,7 +438,7 @@
u32int *Rn, *Rd, *Rm, *targ, addr;
Segment *seg;
if(debug)
- print("singleex: Rd=%d, Rn=%d\n", ((instr >> 12) & 15), ((instr >> 16) & 15));+ print("singleex: Rd=%d Rn=%d pid=%d\n", ((instr >> 12) & 15), ((instr >> 16) & 15), up->pid);Rd = up->R + ((instr >> 12) & 15);
Rn = up->R + ((instr >> 16) & 15);
if(Rd == up->R + 15 || Rn == up->R + 15)
--- a/kern/dat.h
+++ b/kern/dat.h
@@ -31,6 +31,7 @@
typedef struct Rgrp Rgrp;
typedef struct RWlock RWlock;
typedef struct Segment Segment;
+typedef struct Ureg Ureg;
typedef struct Waitq Waitq;
typedef struct Walkqid Walkqid;
typedef struct Kmesg Kmesg;
@@ -125,7 +126,6 @@
NSMAX = 1000,
NNOTE = 5,
NSLOG = 7,
- SEGNUM = 8,
Nfpregs = 16,
NSCACHE = (1<<NSLOG),
@@ -307,6 +307,33 @@
Mhead *mnthash[MNTHASH];
};
+typedef struct Ureg {+ ulong r0;
+ ulong r1;
+ ulong r2;
+ ulong r3;
+ ulong r4;
+ ulong r5;
+ ulong r6;
+ ulong r7;
+ ulong r8;
+ ulong r9;
+ ulong r10;
+ ulong r11;
+ ulong r12; /* sb */
+ union {+ ulong r13;
+ ulong sp;
+ };
+ union {+ ulong r14;
+ ulong link;
+ };
+ ulong type; /* of exception */
+ ulong psr;
+ ulong pc; /* interrupted addr */
+} Ureg;
+
struct Rgrp
{Ref ref;
@@ -348,13 +375,29 @@
NERR = 20
};
-typedef uvlong Ticks;
+/* Segment types */
+enum
+{+ SG_TYPE = 07, /* Mask type of segment */
+ SG_TEXT = 00,
+ SG_DATA = 01,
+ SG_BSS = 02,
+ SG_STACK = 03,
+ SG_SHARED = 04,
+ SG_PHYSICAL = 05,
+ SG_FIXED = 06,
+ SG_STICKY = 07,
+ SG_RONLY = 0040, /* Segment is read only */
+ SG_CEXEC = 0100, /* Detach at exec */
+ SG_FAULT = 0200, /* Fault on access */
+ SG_CACHED = 0400, /* Normal cached memory */
+ SG_DEVICE = 01000, /* Memory mapped device */
+ SG_NOEXEC = 02000, /* No execute */
+};
+
enum {- SEGTEXT,
- SEGDATA,
- SEGBSS,
- SEGSTACK,
+ TSEG, DSEG, BSEG, ESEG, LSEG, SEG1, SEG2, SEG3, NSEG,
SEGFLLOCK = 1,
};
@@ -365,6 +408,7 @@
Rendezvous,
Wakeme,
Dead,
+ Stopped,
};
struct Fd
@@ -381,6 +425,7 @@
uint mach;
ulong pid;
+ ulong procmode;
Pgrp *pgrp; /* Process group for namespace */
Fgrp *fgrp; /* File descriptor group */
@@ -387,6 +432,7 @@
Rgrp *rgrp;
Egrp *egrp;
+ QLock debug;
Lock rlock; /* sync sleep/wakeup with postnote */
Rendez *r; /* rendezvous point slept on */
Rendez rsleep; /* place for syssleep/debug */
@@ -411,9 +457,7 @@
u32int lladdr; /* LL/SC emulation */
u32int llval;
-
u32int CPSR; /* status register */
-
u32int FPSR;
double F[Nfpregs];
Fd *fd; /* fd for syscall emulation */
@@ -435,7 +479,10 @@
char oproc[1024]; /* reserved for os */
u32int R[16]; /* general purpose registers / PC (R15) */
- Segment *S[SEGNUM];
+ Ureg *ureg;
+ Ureg *dbgreg;
+ Segment *seg[NSEG];
+ QLock seglock;
};
struct Segment {@@ -445,6 +492,8 @@
u32int start, size;
void *data;
Ref *dref;
+
+ int type;
};
enum
--- a/kern/devlfd-posix.c
+++ b/kern/devlfd-posix.c
@@ -1,9 +1,9 @@
-#include "u.h"
-#include <errno.h>
-#include "lib.h"
-#include "dat.h"
-#include "fns.h"
-#include "error.h"
+#include "u.h"
+#include <errno.h>
+#include "lib.h"
+#include "dat.h"
+#include "fns.h"
+#include "error.h"
#undef read
#undef write
@@ -11,111 +11,224 @@
Chan*
lfdchan(void *fd)
{- Chan *c;
-
- c = newchan();
- c->type = devno('L', 0);- c->aux = fd;
- c->path = newpath("fd");- c->mode = ORDWR;
- c->qid.type = 0;
- c->qid.path = 0;
- c->qid.vers = 0;
- c->dev = 0;
- c->offset = 0;
- return c;
+ Chan *c;
+
+ c = newchan();
+ c->type = devno('L', 0);+ c->aux = fd;
+ c->path = newpath("/fd");+ c->mode = ORDWR;
+ c->qid.type = QTFILE;
+ c->qid.path = (uintptr)fd; /* Use fd number as qid.path */
+ c->qid.vers = 0;
+ c->dev = 0;
+ c->offset = 0;
+ return c;
}
int
lfdfd(int fd)
{- return newfd(lfdchan((void*)(uintptr)fd));
+ Fgrp *fg = up->fgrp;
+ Chan *c;
+
+ /* Check if fd is valid */
+ if(fd < 0 || fd >= fg->nfd || fg->fd[fd] == nil) {+ c = lfdchan((void*)(uintptr)fd);
+ lock(&fg->ref.lk);
+ if(fd >= fg->nfd) {+ int newnfd = fd + DELTAFD;
+ Chan **newfd = smalloc(newnfd * sizeof(Chan*));
+ if(fg->nfd > 0)
+ memmove(newfd, fg->fd, fg->nfd * sizeof(Chan*));
+ free(fg->fd);
+ fg->fd = newfd;
+ fg->nfd = newnfd;
+ }
+ fg->fd[fd] = c;
+ if(fd > fg->maxfd)
+ fg->maxfd = fd;
+ unlock(&fg->ref.lk);
+ } else {+ c = fg->fd[fd];
+ }
+ return newfd(c);
}
+static int
+fdgen(Chan *c, char *name, Dirtab *tab, int ntab, int s, Dir *dp)
+{+ Fgrp *fg = up->fgrp;
+ int fd;
+
+ if(s == DEVDOTDOT) {+ devdir(c, c->qid, "#L", 0, eve, DMDIR|0775, dp);
+ return 1;
+ }
+
+ lock(&fg->ref.lk);
+ if(name) {+ /* Look up by name (e.g., "0", "1", "2", etc.) */
+ char *end;
+ fd = strtol(name, &end, 10);
+ if(*end != '\0' || fd < 0 || fd >= fg->nfd || fg->fd[fd] == nil) {+ unlock(&fg->ref.lk);
+ return -1; /* Invalid or closed fd */
+ }
+ } else {+ /* Generate by index, starting with 0, 1, 2, then others up to maxfd */
+ for(fd = 0, s = s; fd <= fg->maxfd && s >= 0; fd++) {+ if(fd >= fg->nfd || fg->fd[fd] == nil)
+ continue;
+ if(s-- == 0)
+ break;
+ }
+ if(fd > fg->maxfd || fg->fd[fd] == nil) {+ unlock(&fg->ref.lk);
+ return -1;
+ }
+ }
+
+ sprint(up->genbuf, "%d", fd);
+ devdir(c, fg->fd[fd]->qid, up->genbuf, 0, eve, 0666, dp);
+ unlock(&fg->ref.lk);
+ return 1;
+}
+
static Chan*
-lfdattach(char *x)
+lfdattach(char *spec)
{- USED(x);
-
- error(Egreg);
- return nil;
+ Chan *c;
+
+ if(spec && *spec)
+ error(Ebadarg);
+ c = devattach('L', spec);+ c->qid.type = QTDIR;
+ c->qid.path = 0;
+ return c;
}
static Walkqid*
lfdwalk(Chan *c, Chan *nc, char **name, int nname)
{- USED(c);
- USED(nc);
- USED(name);
- USED(nname);
- error(Egreg);
- return nil;
+ return devwalk(c, nc, name, nname, nil, 0, fdgen);
}
static int
-lfdstat(Chan *c, uchar *dp, int n)
+lfdstat(Chan *c, uchar *db, int n)
{- USED(c);
- USED(dp);
- USED(n);
- error(Egreg);
- return -1;
+ return devstat(c, db, n, nil, 0, fdgen);
}
static Chan*
lfdopen(Chan *c, int omode)
{- USED(c);
- USED(omode);
- error(Egreg);
- return nil;
+ Fgrp *fg = up->fgrp;
+ int fd;
+
+ if(c->qid.type & QTDIR) {+ if(omode != OREAD)
+ error(Eperm);
+ c->mode = openmode(omode);
+ c->flag |= COPEN;
+ c->offset = 0;
+ return c;
+ }
+
+ lock(&fg->ref.lk);
+ fd = (int)c->qid.path; /* qid.path stores the fd number */
+ if(fd < 0 || fd >= fg->nfd || fg->fd[fd] == nil) {+ unlock(&fg->ref.lk);
+ error(Enonexist);
+ }
+
+ /* Enforce permissions based on fd */
+ switch(fd) {+ case 0: /* stdin */
+ if(omode != OREAD)
+ error(Eperm);
+ break;
+ case 1: /* stdout */
+ case 2: /* stderr */
+ if(omode != OWRITE)
+ error(Eperm);
+ break;
+ default:
+ if((omode & (OREAD|OWRITE)) == 0)
+ error(Eperm);
+ break;
+ }
+
+ c->mode = openmode(omode);
+ c->flag |= COPEN;
+ c->offset = 0;
+ c->aux = (void*)(uintptr)fd;
+ unlock(&fg->ref.lk);
+ return c;
}
static void
lfdclose(Chan *c)
{- close((int)(uintptr)c->aux);
+ Fgrp *fg = up->fgrp;
+ int fd;
+
+ if(c->qid.type & QTDIR)
+ return;
+
+ lock(&fg->ref.lk);
+ fd = (int)c->qid.path;
+ if(fd >= 0 && fd < fg->nfd && fg->fd[fd] != nil) {+ close(fd);
+ fg->fd[fd] = nil;
+ if(fd == fg->maxfd) {+ while(fg->maxfd > 0 && fg->fd[fg->maxfd] == nil)
+ fg->maxfd--;
+ }
+ }
+ unlock(&fg->ref.lk);
}
static long
lfdread(Chan *c, void *buf, long n, vlong off)
{- USED(off); /* can't pread on pipes */
+ USED(off); /* Can't pread on pipes */
+ if(c->qid.type & QTDIR)
+ return devdirread(c, buf, n, nil, 0, fdgen);
- n = read((int)(uintptr)c->aux, buf, n);
- if(n < 0)
- oserror();
- return n;
+ n = read((int)(uintptr)c->aux, buf, n);
+ if(n < 0)
+ oserror();
+ return n;
}
static long
lfdwrite(Chan *c, void *buf, long n, vlong off)
{- USED(off); /* can't pread on pipes */
-
- n = write((int)(uintptr)c->aux, buf, n);
- if(n < 0)
- oserror();
- return n;
+ USED(off); /* Can't pwrite on pipes */
+ n = write((int)(uintptr)c->aux, buf, n);
+ if(n < 0)
+ oserror();
+ return n;
}
Dev lfddevtab = {- 'L',
- "lfd",
-
- devreset,
- devinit,
- devshutdown,
- lfdattach,
- lfdwalk,
- lfdstat,
- lfdopen,
- devcreate,
- lfdclose,
- lfdread,
- devbread,
- lfdwrite,
- devbwrite,
- devremove,
- devwstat,
-};
+ 'L',
+ "lfd",
+
+ devreset,
+ devinit,
+ devshutdown,
+ lfdattach,
+ lfdwalk,
+ lfdstat,
+ lfdopen,
+ devcreate,
+ lfdclose,
+ lfdread,
+ devbread,
+ lfdwrite,
+ devbwrite,
+ devremove,
+ devwstat,
+};
\ No newline at end of file
--- a/kern/devlfd-win32.c
+++ b/kern/devlfd-win32.c
@@ -1,133 +1,273 @@
-#include <windows.h>
-#include "u.h"
-#include "lib.h"
-#include "dat.h"
-#include "fns.h"
-#include "error.h"
+#include <windows.h>
+#include "u.h"
+#include "lib.h"
+#include "dat.h"
+#include "fns.h"
+#include "error.h"
Chan*
lfdchan(void *fd)
{- Chan *c;
-
- c = newchan();
- c->type = devno('L', 0);- c->aux = fd;
- c->path = newpath("fd");- c->mode = ORDWR;
- c->qid.type = 0;
- c->qid.path = 0;
- c->qid.vers = 0;
- c->dev = 0;
- c->offset = 0;
- return c;
+ Chan *c;
+
+ c = newchan();
+ c->type = devno('L', 0);+ c->aux = fd;
+ c->path = newpath("/fd");+ c->mode = ORDWR;
+ c->qid.type = QTFILE;
+ c->qid.path = (uintptr)fd; /* Use handle as qid.path (index for std handles) */
+ c->qid.vers = 0;
+ c->dev = 0;
+ c->offset = 0;
+ return c;
}
/*
- * only good for stdin/stdout/stderr
+ * Initialize or retrieve a handle, supporting stdin/stdout/stderr and additional handles
*/
int
lfdfd(int fd)
{- HANDLE h;
+ Fgrp *fg = up->fgrp;
+ HANDLE h;
+ Chan *c;
- switch(fd){- case 0: h = GetStdHandle(STD_INPUT_HANDLE); break;
- case 1: h = GetStdHandle(STD_OUTPUT_HANDLE); break;
- case 2: h = GetStdHandle(STD_ERROR_HANDLE); break;
- default:
- return -1;
- }
- if(h == INVALID_HANDLE_VALUE)
- return -1;
- return newfd(lfdchan((void*)h));
+ /* Get handle for standard fds or validate custom handle */
+ switch(fd) {+ case 0: h = GetStdHandle(STD_INPUT_HANDLE); break;
+ case 1: h = GetStdHandle(STD_OUTPUT_HANDLE); break;
+ case 2: h = GetStdHandle(STD_ERROR_HANDLE); break;
+ default:
+ h = (HANDLE)(uintptr)fd; /* Assume fd is a valid HANDLE */
+ if(h == INVALID_HANDLE_VALUE || h == NULL)
+ return -1;
+ break;
+ }
+ if(h == INVALID_HANDLE_VALUE || h == NULL)
+ return -1;
+
+ lock(&fg->ref.lk);
+ if(fd >= fg->nfd) {+ int newnfd = fd + DELTAFD;
+ Chan **newfd = smalloc(newnfd * sizeof(Chan*));
+ if(fg->nfd > 0)
+ memmove(newfd, fg->fd, fg->nfd * sizeof(Chan*));
+ free(fg->fd);
+ fg->fd = newfd;
+ fg->nfd = newnfd;
+ }
+ if(fg->fd[fd] == nil) {+ c = lfdchan((void*)h);
+ fg->fd[fd] = c;
+ if(fd > fg->maxfd)
+ fg->maxfd = fd;
+ } else {+ c = fg->fd[fd];
+ }
+ unlock(&fg->ref.lk);
+ return newfd(c);
}
+static int
+fdgen(Chan *c, char *name, Dirtab *tab, int ntab, int s, Dir *dp)
+{+ Fgrp *fg = up->fgrp;
+ int fd;
+
+ if(s == DEVDOTDOT) {+ devdir(c, c->qid, "#L", 0, eve, DMDIR|0775, dp);
+ return 1;
+ }
+
+ lock(&fg->ref.lk);
+ if(name) {+ /* Look up by name (e.g., "0", "1", "2", etc.) */
+ char *end;
+ fd = strtol(name, &end, 10);
+ if(*end != '\0' || fd < 0 || fd >= fg->nfd || fg->fd[fd] == nil) {+ unlock(&fg->ref.lk);
+ return -1; /* Invalid or closed handle */
+ }
+ } else {+ /* Generate by index, starting with 0, 1, 2, then others up to maxfd */
+ for(fd = 0, s = s; fd <= fg->maxfd && s >= 0; fd++) {+ if(fd >= fg->nfd || fg->fd[fd] == nil)
+ continue;
+ if(s-- == 0)
+ break;
+ }
+ if(fd > fg->maxfd || fd >= fg->nfd || fg->fd[fd] == nil) {+ unlock(&fg->ref.lk);
+ return -1;
+ }
+ }
+
+ sprint(up->genbuf, "%d", fd);
+ devdir(c, fg->fd[fd]->qid, up->genbuf, 0, eve, 0666, dp);
+ unlock(&fg->ref.lk);
+ return 1;
+}
+
static Chan*
-lfdattach(char *x)
+lfdattach(char *spec)
{- USED(x);
-
- error(Egreg);
- return nil;
+ Chan *c;
+ Fgrp *fg = up->fgrp;
+
+ if(spec && *spec)
+ error(Ebadarg);
+
+ /* Ensure standard handles are initialized */
+ lock(&fg->ref.lk);
+ if(fg->nfd < 3) {+ int newnfd = 3 + DELTAFD;
+ Chan **newfd = smalloc(newnfd * sizeof(Chan*));
+ if(fg->nfd > 0)
+ memmove(newfd, fg->fd, fg->nfd * sizeof(Chan*));
+ free(fg->fd);
+ fg->fd = newfd;
+ fg->nfd = newnfd;
+ }
+ if(fg->fd[0] == nil)
+ fg->fd[0] = lfdchan((void*)GetStdHandle(STD_INPUT_HANDLE));
+ if(fg->fd[1] == nil)
+ fg->fd[1] = lfdchan((void*)GetStdHandle(STD_OUTPUT_HANDLE));
+ if(fg->fd[2] == nil)
+ fg->fd[2] = lfdchan((void*)GetStdHandle(STD_ERROR_HANDLE));
+ if(fg->maxfd < 2)
+ fg->maxfd = 2;
+ unlock(&fg->ref.lk);
+
+ c = devattach('L', spec);+ c->qid.type = QTDIR;
+ c->qid.path = 0;
+ return c;
}
static Walkqid*
lfdwalk(Chan *c, Chan *nc, char **name, int nname)
{- USED(c);
- USED(nc);
- USED(name);
- USED(nname);
-
- error(Egreg);
- return nil;
+ return devwalk(c, nc, name, nname, nil, 0, fdgen);
}
static int
-lfdstat(Chan *c, uchar *dp, int n)
+lfdstat(Chan *c, uchar *db, int n)
{- USED(c);
- USED(dp);
- USED(n);
- error(Egreg);
- return -1;
+ return devstat(c, db, n, nil, 0, fdgen);
}
static Chan*
lfdopen(Chan *c, int omode)
{- USED(c);
- USED(omode);
- error(Egreg);
- return nil;
+ Fgrp *fg = up->fgrp;
+ int fd;
+
+ if(c->qid.type & QTDIR) {+ if(omode != OREAD)
+ error(Eperm);
+ c->mode = openmode(omode);
+ c->flag |= COPEN;
+ c->offset = 0;
+ return c;
+ }
+
+ lock(&fg->ref.lk);
+ fd = (int)c->qid.path; /* qid.path stores the fd index */
+ if(fd < 0 || fd >= fg->nfd || fg->fd[fd] == nil) {+ unlock(&fg->ref.lk);
+ error(Enonexist);
+ }
+
+ /* Enforce permissions based on fd */
+ switch(fd) {+ case 0: /* stdin */
+ if(omode != OREAD)
+ error(Eperm);
+ break;
+ case 1: /* stdout */
+ case 2: /* stderr */
+ if(omode != OWRITE)
+ error(Eperm);
+ break;
+ default:
+ if((omode & (OREAD|OWRITE)) == 0)
+ error(Eperm);
+ break;
+ }
+
+ c->mode = openmode(omode);
+ c->flag |= COPEN;
+ c->offset = 0;
+ c->aux = fg->fd[fd]->aux; /* Use the HANDLE from the stored Chan */
+ unlock(&fg->ref.lk);
+ return c;
}
static void
lfdclose(Chan *c)
{- CloseHandle((HANDLE)c->aux);
+ Fgrp *fg = up->fgrp;
+ int fd;
+
+ if(c->qid.type & QTDIR)
+ return;
+
+ lock(&fg->ref.lk);
+ fd = (int)c->qid.path;
+ if(fd >= 0 && fd < fg->nfd && fg->fd[fd] != nil) {+ CloseHandle((HANDLE)fg->fd[fd]->aux);
+ fg->fd[fd] = nil;
+ if(fd == fg->maxfd) {+ while(fg->maxfd > 0 && fg->fd[fg->maxfd] == nil)
+ fg->maxfd--;
+ }
+ }
+ unlock(&fg->ref.lk);
}
static long
lfdread(Chan *c, void *buf, long n, vlong off)
{- DWORD r;
+ DWORD r;
- USED(off); /* can't pread on pipes */
- if(!ReadFile((HANDLE)c->aux, buf, (DWORD)n, &r, NULL))
- oserror();
- return r;
+ USED(off); /* Can't pread on pipes */
+ if(c->qid.type & QTDIR)
+ return devdirread(c, buf, n, nil, 0, fdgen);
+
+ if(!ReadFile((HANDLE)c->aux, buf, (DWORD)n, &r, NULL))
+ oserror();
+ return r;
}
static long
lfdwrite(Chan *c, void *buf, long n, vlong off)
{- DWORD r;
+ DWORD r;
- USED(off); /* can't pread on pipes */
- if(!WriteFile((HANDLE)c->aux, buf, (DWORD)n, &r, NULL))
- oserror();
- return r;
+ USED(off); /* Can't pwrite on pipes */
+ if(!WriteFile((HANDLE)c->aux, buf, (DWORD)n, &r, NULL))
+ oserror();
+ return r;
}
Dev lfddevtab = {- 'L',
- "lfd",
-
- devreset,
- devinit,
- devshutdown,
- lfdattach,
- lfdwalk,
- lfdstat,
- lfdopen,
- devcreate,
- lfdclose,
- lfdread,
- devbread,
- lfdwrite,
- devbwrite,
- devremove,
- devwstat,
-};
+ 'L',
+ "lfd",
+
+ devreset,
+ devinit,
+ devshutdown,
+ lfdattach,
+ lfdwalk,
+ lfdstat,
+ lfdopen,
+ devcreate,
+ lfdclose,
+ lfdread,
+ devbread,
+ lfdwrite,
+ devbwrite,
+ devremove,
+ devwstat,
+};
\ No newline at end of file
--- a/kern/devproc.c
+++ b/kern/devproc.c
@@ -14,13 +14,12 @@
Qargs,
Qctl,
Qfd,
- Qfpregs,
- Qkregs,
Qmem,
Qnote,
Qnoteid,
Qnotepg,
Qns,
+ Qppid,
Qproc,
Qregs,
Qsegment,
@@ -29,159 +28,210 @@
Qwait,
Qprofile,
Qsyscall,
+ Qwatchpt,
};
-#define TYPE(x) ((x).path & 0xf)
-typedef struct Aux Aux;
+enum
+{+ CMclose,
+ CMclosefiles,
+ CMfixedpri,
+ CMhang,
+ CMkill,
+ CMnohang,
+ CMnoswap,
+ CMpri,
+ CMprivate,
+ CMprofile,
+ CMstart,
+ CMstartstop,
+ CMstartsyscall,
+ CMstop,
+ CMwaitstop,
+ CMwired,
+ CMtrace,
+ CMinterrupt,
+ CMnointerrupt,
+};
-struct Aux {- Proc *p;
- int fd;
- Dirtab *d;
+enum{+ Nevents = 0x4000,
+ Emask = Nevents - 1,
};
+#define STATSIZE (2*28+12+9*12)
+#define REGSIZE (15*16) /* TODO */
+
+#define QSHIFT 5
+#define QID(q) ((((ulong)(q).path)&0x0000001F)>>0)
+#define SLOTMAX 0x4000000
+#define SLOT(q) (((((ulong)(q).path)>>QSHIFT)&(SLOTMAX-1))-1)
+#define PID(q) ((q).vers)
+#define NOTEID(q) ((q).vers)
+
+static void procctlreq(Proc*, char*, int);
+static long procctlmemio(Chan*, Proc*, uintptr, void*, long, int);
+static Chan* proctext(Chan*, Proc*);
+static int procstopped(void*);
+
+/*
+ * Status, fd, and ns are left fully readable (0444) because of their use in debugging,
+ * particularly on shared servers.
+ * Arguably, ns and fd shouldn't be readable; if you'd prefer, change them to 0000
+ */
Dirtab procdir[] =
{ "args", {Qargs}, 0, 0660,- "ctl", {Qctl}, 0, 0600,+ "ctl", {Qctl}, 0, 0000, "fd", {Qfd}, 0, 0444,- "fpregs", {Qfpregs}, 0, 0400,- "kregs", {Qkregs}, 18 * 4, 0400,- "mem", {Qmem}, 0, 0400,+ "mem", {Qmem}, 0, 0000, "note", {Qnote}, 0, 0000, "noteid", {Qnoteid}, 0, 0664, "notepg", {Qnotepg}, 0, 0000, "ns", {Qns}, 0, 0444,+ "ppid", {Qppid}, 0, 0444, "proc", {Qproc}, 0, 0400,- "regs", {Qregs}, 18 * 4, 0400,+ "regs", {Qregs}, REGSIZE, 0000, "segment", {Qsegment}, 0, 0444,- "status", {Qstatus}, 176, 0444,- "text", {Qtext}, 0, 0400,+ "status", {Qstatus}, STATSIZE, 0444,+ "text", {Qtext}, 0, 0000, "wait", {Qwait}, 0, 0400, "profile", {Qprofile}, 0, 0400, "syscall", {Qsyscall}, 0, 0400, + "watchpt", {Qwatchpt}, 0, 0600,};
+static
+Cmdtab proccmd[] = {+ CMclose, "close", 2,
+ CMclosefiles, "closefiles", 1,
+ CMfixedpri, "fixedpri", 2,
+ CMhang, "hang", 1,
+ CMnohang, "nohang", 1,
+ CMnoswap, "noswap", 1,
+ CMkill, "kill", 1,
+ CMpri, "pri", 2,
+ CMprivate, "private", 1,
+ CMprofile, "profile", 1,
+ CMstart, "start", 1,
+ CMstartstop, "startstop", 1,
+ CMstartsyscall, "startsyscall", 1,
+ CMstop, "stop", 1,
+ CMwaitstop, "waitstop", 1,
+ CMwired, "wired", 2,
+ CMtrace, "trace", 0,
+ CMinterrupt, "interrupt", 1,
+ CMnointerrupt, "nointerrupt", 1,
+};
+
+/* Segment type from dat.h */
+static char *sname[]={ "Text", "Data", "Bss", "Stack", "Shared", "Phys", "Fixed", "Sticky" };+
static int
-procgen(Chan *c, char *n, Dirtab *d, int nd, int s, Dir *dp)
+procgen(Chan *c, char *name, Dirtab *tab, int nd, int s, Dir *dp)
{- Qid q;
+ Qid qid;
Proc *p;
- int t;
+ char *ename;
+ Segment *q;
+ ulong pid, path, perm, len;
- q.vers = 0;
- q.type = QTFILE;
-
-}
+ if(s == DEVDOTDOT){+ mkqid(&qid, Qdir, 0, QTDIR);
+ devdir(c, qid, "#p", 0, eve, 0555, dp);
+ return 1;
+ }
-static void
-procinit(void)
-{+ if(c->qid.path == Qdir){+ if(s == 0){+ strcpy(up->genbuf, "trace");
+ mkqid(&qid, Qtrace, -1, QTFILE);
+ devdir(c, qid, up->genbuf, 0, eve, 0400, dp);
+ return 1;
+ }
-}
+ if(name != nil){+ /* ignore s and use name to find pid */
+ pid = strtol(name, &ename, 10);
+ if(pid==0 || ename[0]!='\0')
+ return -1;
+ s = procindex(pid);
+ if(s < 0)
+ return -1;
+ }
+ else if(--s >= conf.nproc)
+ return -1;
-static char *
-readin(int pid, char *file)
-{- char *name, *buf;
- int fd, rc;
-
- name = smprint("/proc/%d/%s", pid, file);- fd = open(name, OREAD);
- if(fd < 0){- free(name);
- return nil;
+ p = proctab(s);
+ if(p == nil)
+ return 0;
+ pid = p->pid;
+ if(pid == 0)
+ return 0;
+ /*
+ * String comparison is done in devwalk so name must match its formatted pid
+ */
+ snprint(up->genbuf, sizeof(up->genbuf), "%lud", pid);
+ if(name != nil && strcmp(name, up->genbuf) != 0)
+ return -1;
+ mkqid(&qid, (s+1)<<QSHIFT, pid, QTDIR);
+ devdir(c, qid, up->genbuf, 0, p->user, 0555, dp);
+ return 1;
}
- buf = malloc(1024);
- rc = read(fd, buf, 1023);
- if(rc < 0){- free(buf);
- free(name);
- close(fd);
- return nil;
+ if(c->qid.path == Qtrace){+ strcpy(up->genbuf, "trace");
+ mkqid(&qid, Qtrace, -1, QTFILE);
+ devdir(c, qid, up->genbuf, 0, eve, 0400, dp);
+ return 1;
}
- buf[rc] = 0;
- free(name);
- close(fd);
- return buf;
-}
+ if(s >= nelem(procdir))
+ return -1;
+ if(tab)
+ panic("procgen");-static int
-calcmem(Proc *p)
-{- int i, r;
-
- r = 0;
- for(i = 0; i < SEGNUM; i++) {- if(i == SEGSTACK)
- continue;
- if(p->S[i] == nil)
- continue;
- r += p->S[i]->size;
- }
- r = (r + 1023) / 1024;
- return r;
-}
+ tab = &procdir[s];
+ path = c->qid.path&~((1<<QSHIFT)-1); /* slot component */
-static int
-copymem(Proc *p, char *buf, u32int addr, int len)
-{- int i, n, r;
+ /* p->procmode determines default mode for files in /proc */
+ p = proctab(SLOT(c->qid));
+ perm = tab->perm;
+ if(perm == 0)
+ perm = p->procmode;
+ else /* just copy read bits */
+ perm |= p->procmode & 0444;
- r = len;
- while(len > 0) {- for(i = 0; i < SEGNUM; i++) {- if(p->S[i] == nil)
- continue;
- if(p->S[i]->start <= addr && p->S[i]->start + p->S[i]->size > addr)
- break;
+ len = tab->length;
+ switch(QID(c->qid)) {+ case Qwait:
+ len = p->nwait; /* incorrect size, but >0 means there's something to read */
+ break;
+ case Qprofile:
+ q = p->seg[TSEG];
+ if(q != nil && q->profile != nil) {+ len = (q->size-q->start)>>LRESPROF;
+ len *= sizeof(*q->profile);
}
- if(i == SEGNUM) {- up->errstr = "bad arg in syscall";
- return -1;
- }
- n = p->S[i]->start + p->S[i]->size - addr;
- if(n > len)
- n = len;
- memcpy(buf, (char*)p->S[i]->data + addr - p->S[i]->start, n);
- len -= n;
- buf += n;
+ break;
+ case Qwatchpt:
+ len = lenwatchpt(p);
+ break;
}
- return r;
+
+ mkqid(&qid, path|tab->qid.path, c->qid.vers, QTFILE);
+ devdir(c, qid, tab->name, len, p->user, perm, dp);
+ return 1;
}
-static char *
-segments(Proc *p)
+static void
+procinit(void)
{- char *r, *s;
- static char *names[] = {- [SEGTEXT] "Text",
- [SEGSTACK] "Stack",
- [SEGDATA] "Data",
- [SEGBSS] "Bss",
- };
- int i;
-
- r = malloc(1024);
- s = r;
- for(i = 0; i < SEGNUM; i++) {- if(p->S[i] == nil)
- continue;
- s += sprint(s, "%-7s%c %.8ux %.8ux %4ld\n", names[i], i == SEGTEXT ? 'R' : ' ', p->S[i]->start, p->S[i]->start + p->S[i]->size, p->S[i]->dref->ref);
- }
- return r;
+ return;
}
static Chan*
procattach(char *spec)
{- /*
- req->fid->qid = (Qid) {0, 0, 0x80};- req->fid->aux = emallocz(sizeof(Aux));
- ((Aux *) req->fid->aux)->fd = -1;
- req->ofcall.qid = req->fid->qid;
- respond(req, nil);
- */
+ return devattach('p', spec);}
static Walkqid*
@@ -191,209 +241,774 @@
}
static Chan*
-procopen(Chan *c, int omode)
+procopen(Chan *c, int omode0)
{- Aux *a;
- int t;
-/*
- t = TYPE(c->qid);
- //a = req->fid->aux;
- switch(t) {+ Proc *p;
+ Chan *tc;
+ int pid;
+ int omode;
+
+ if(c->qid.type & QTDIR)
+ return devopen(c, omode0, 0, 0, procgen);
+
+ if(QID(c->qid) == Qtrace){+ if (omode0 != OREAD || !iseve())
+ error(Eperm);
+ lock(&tlock);
+ if (waserror()){+ topens--;
+ unlock(&tlock);
+ nexterror();
+ }
+ if (topens++ > 0)
+ error("already open");+ if (tevents == nil){+ tevents = (Traceevent*)malloc(sizeof(Traceevent) * Nevents);
+ if(tevents == nil)
+ error(Enomem);
+ tproduced = tconsumed = 0;
+ }
+ proctrace = _proctrace;
+ unlock(&tlock);
+ poperror();
+
+ c->mode = openmode(omode0);
+ c->flag |= COPEN;
+ c->offset = 0;
+ return c;
+ }
+
+ p = proctab(SLOT(c->qid));
+ eqlock(&p->debug);
+ if(waserror()){+ qunlock(&p->debug);
+ nexterror();
+ }
+ pid = PID(c->qid);
+ if(p == nil || p->pid != pid)
+ error(Eprocdied);
+
+ omode = openmode(omode0);
+
+ switch(QID(c->qid)){case Qtext:
- a->fd = open((char*)(a->p->path + 1), OREAD);
+ if(omode != OREAD)
+ error(Eperm);
+ nonone(p);
+ qunlock(&p->debug);
+ poperror();
+ tc = proctext(c, p);
+ tc->offset = 0;
+ cclose(c);
+ return tc;
+
+ case Qstatus:
+ case Qppid:
+ case Qproc:
+ case Qsegment:
+ case Qns:
+ case Qfd:
+ if(omode != OREAD)
+ error(Eperm);
break;
+
+ case Qctl:
+ case Qargs:
+ case Qwait:
+ case Qnoteid:
+ if(omode == OREAD)
+ break;
+ case Qnote:
+ if(p->kp)
+ error(Eperm);
+ break;
+
+ case Qnotepg:
+ if(p->kp || omode != OWRITE)
+ error(Eperm);
+ pid = p->noteid;
+ break;
+
+ case Qmem:
+ case Qregs:
+ case Qprofile:
+ case Qsyscall:
+ case Qwatchpt:
+ break;
+
default:
- respond(req, nil);
- return;
+ print("procopen %#lux\n", QID(c->qid));+ error(Egreg);
}
-*/
-}
+ nonone(p);
-/*
-static int
-procgen(int n, Dir *d, void *)
-{- int i;
- Proc *p;
+ /* Affix pid to qid */
+ if(pid == 0)
+ error(Eprocdied);
+ c->qid.vers = pid;
+
+ tc = devopen(c, omode, 0, 0, procgen);
+ if(waserror()){+ cclose(tc);
+ nexterror();
+ }
- p = &plist;
- for(i = 0;; i++) {- p = p->next;
- if(p == &plist)
- return -1;
- if(i == n)
- break;
+ switch(QID(c->qid)){+ case Qwatchpt:
+ if((omode0 & OTRUNC) != 0)
+ clearwatchpt(p);
+ break;
}
- d->uid = estrdup9p(luser);
- d->gid = estrdup9p(luser);
- d->muid = estrdup9p(luser);
- d->name = smprint("%d", p->pid);- d->mode = DMDIR | 0555;
- d->qid = (Qid) {p->pid * NQid, 0, 0x80};- return 0;
-}
-
-static int
-procsubgen(int n, Dir *d, void *)
-{- Dirtab *di;
- if(n >= nelem(procdir) - 1)
- return -1;
-
- di = procdir + n;
- d->uid = estrdup9p(luser);
- d->gid = estrdup9p(luser);
- d->muid = estrdup9p(luser);
- d->name = estrdup9p(di->name);
- d->mode = di->perm;
- d->length = di->length;
- d->qid = di->qid;
- return 0;
-}
-*/
+ poperror();
+ qunlock(&p->debug);
+ poperror();
-static Block*
-procbread(Chan *c, long n, ulong o)
-{- //
+ return tc;
}
static long
-procread(Chan *c, void *a, long n, vlong offset)
+procread(Chan *c, void *va, long n, vlong off)
{+ char statbuf[1024], *sps;
+ ulong offset;
+ int i, j, rsize;
+ uchar *rptr;
+ uintptr addr;
+ Segment *s;
+ Waitq *wq;
Proc *p;
- char *buf;
- int rc;
+
+ offset = off;
+ if(c->qid.type & QTDIR)
+ return devdirread(c, va, n, 0, 0, procgen);
- /*
- a = req->fid->aux;
- if(a == nil) {- respond(req, "the front fell off");
- return;
+ if(QID(c->qid) == Qtrace){+ int navail, ne;
+
+ if(!eventsavailable(nil))
+ return 0;
+
+ rptr = (uchar*)va;
+ navail = tproduced - tconsumed;
+ if(navail > n / sizeof(Traceevent))
+ navail = n / sizeof(Traceevent);
+ while(navail > 0) {+ ne = ((tconsumed & Emask) + navail > Nevents)?
+ Nevents - (tconsumed & Emask): navail;
+ memmove(rptr, &tevents[tconsumed & Emask],
+ ne * sizeof(Traceevent));
+
+ tconsumed += ne;
+ rptr += ne * sizeof(Traceevent);
+ navail -= ne;
+ }
+ return rptr - (uchar*)va;
}
- if(req->fid->qid.path == 0) {- dirread9p(req, procgen, nil);
- respond(req, nil);
- return;
+
+ p = proctab(SLOT(c->qid));
+ if(p->pid != PID(c->qid))
+ error(Eprocdied);
+
+ switch(QID(c->qid)){+ case Qmem:
+ addr = off2addr(off);
+ if(addr < KZERO)
+ return procctlmemio(c, p, addr, va, n, 1);
+
+ if(!iseve() || poolisoverlap(secrmem, (uchar*)addr, n))
+ error(Eperm);
+
+ // validate kernel addresses
+ if(addr < (uintptr)end) {+ if(addr+n > (uintptr)end)
+ n = (uintptr)end - addr;
+ memmove(va, (char*)addr, n);
+ return n;
+ }
+ for(i=0; i<nelem(conf.mem); i++){+ Confmem *cm = &conf.mem[i];
+ // klimit-1 because klimit might be zero!
+ if(cm->kbase <= addr && addr <= cm->klimit-1){+ if(addr+n >= cm->klimit-1)
+ n = cm->klimit - addr;
+ memmove(va, (char*)addr, n);
+ return n;
+ }
+ }
+
+ error(Ebadarg);
+
+ case Qctl:
+ return readnum(offset, va, n, p->pid, NUMSIZE);
+
+ case Qnoteid:
+ return readnum(offset, va, n, p->noteid, NUMSIZE);
+
+ case Qppid:
+ return readnum(offset, va, n, p->parentpid, NUMSIZE);
+
+ case Qprofile:
+ s = p->seg[TSEG];
+ if(s == nil || s->profile == nil)
+ error("profile is off");+ i = (s->size-s->start)>>LRESPROF;
+ i *= sizeof(s->profile[0]);
+ if(i < 0 || offset >= i)
+ return 0;
+ if(offset+n > i)
+ n = i - offset;
+ memmove(va, ((char*)s->profile)+offset, n);
+ return n;
+
+ case Qproc:
+ rptr = (uchar*)p;
+ rsize = sizeof(Proc);
+ regread:
+ if(rptr == nil)
+ error(Enoreg);
+ if(offset >= rsize)
+ return 0;
+ if(offset+n > rsize)
+ n = rsize - offset;
+ memmove(va, rptr+offset, n);
+ return n;
+
+ case Qregs:
+ rptr = (uchar*)p->dbgreg;
+ rsize = REGSIZE;
+ goto regread;
+
+ case Qstatus:
+ sps = p->psstate;
+ if(sps == nil)
+ sps = statename[p->state];
+ /* NOTE: We don't have any p->time tracking
+ this is handled by the pthreads/windows
+ j = snprint(statbuf, sizeof(statbuf),
+ "%-27s %-27s %-11s "
+ "%11lud %11lud %11lud "
+ "%11lud %11lud %11lud "
+ "%11lud %11lud %11lud\n",
+ p->text, p->user, sps,
+ tk2ms(p->time[TUser]),
+ tk2ms(p->time[TSys]),
+ tk2ms(MACHP(0)->ticks - p->time[TReal]),
+ tk2ms(p->time[TCUser]),
+ tk2ms(p->time[TCSys]),
+ tk2ms(p->time[TCReal]),
+ (ulong)(procpagecount(p)*BY2PG/1024),
+ p->basepri, p->priority);
+ */
+ statbufread:
+ if(offset >= j)
+ return 0;
+ if(offset+n > j)
+ n = j - offset;
+ memmove(va, statbuf+offset, n);
+ return n;
+
+ case Qsegment:
+ j = 0;
+ for(i = 0; i < NSEG; i++) {+ s = p->seg[i];
+ if(s == nil)
+ continue;
+ j += snprint(statbuf+j, sizeof(statbuf)-j,
+ "%-6s %c%c %8p %8p %4ld\n",
+ sname[s->type&SG_TYPE],
+ s->type&SG_FAULT ? 'F' : (s->type&SG_RONLY ? 'R' : ' '),
+ s->profile ? 'P' : ' ',
+ s->start, s->size, s->ref);
+ }
+ goto statbufread;
+
+ case Qwait:
+ if(!canqlock(&p->qwaitr))
+ error(Einuse);
+
+ if(waserror()) {+ qunlock(&p->qwaitr);
+ nexterror();
+ }
+
+ lock(&p->exl);
+ while(p->waitq == nil && p->pid == PID(c->qid)) {+ if(up == p && p->nchild == 0) {+ unlock(&p->exl);
+ error(Enochild);
+ }
+ unlock(&p->exl);
+ sleep(&p->waitr, prochaswaitq, c);
+ lock(&p->exl);
+ }
+ if(p->pid != PID(c->qid)){+ unlock(&p->exl);
+ error(Eprocdied);
+ }
+ wq = p->waitq;
+ p->waitq = wq->next;
+ p->nwait--;
+ unlock(&p->exl);
+
+ qunlock(&p->qwaitr);
+ poperror();
+
+ j = snprint(statbuf, sizeof(statbuf), "%d %lud %lud %lud %q",
+ wq->w.pid,
+ wq->w.time[TUser], wq->w.time[TSys], wq->w.time[TReal],
+ wq->w.msg);
+ free(wq);
+ offset = 0;
+ goto statbufread;
}
- p = a->p;
+
+ eqlock(&p->debug);
+ if(waserror()){+ qunlock(&p->debug);
+ nexterror();
+ }
+ if(p->pid != PID(c->qid))
+ error(Eprocdied);
+
+ switch(QID(c->qid)){+ case Qns:
+ case Qfd:
+ if(offset == 0 || offset != c->mrock)
+ c->nrock = c->mrock = 0;
+ do {+ if(QID(c->qid) == Qns)
+ j = readns1(c, p, statbuf, sizeof(statbuf));
+ else
+ j = readfd1(c, p, statbuf, sizeof(statbuf));
+ if(j == 0)
+ break;
+ c->mrock += j;
+ } while(c->mrock <= offset);
+ i = c->mrock - offset;
+ qunlock(&p->debug);
+ poperror();
+ if(i <= 0 || i > j)
+ return 0;
+ if(i < n)
+ n = i;
+ offset = j - i;
+ goto statbufread;
- switch((int)(req->fid->qid.path % NQid)) {- case Qdir:
- dirread9p(req, procsubgen, nil);
- respond(req, nil);
+ case Qargs:
+ j = procargs(p, statbuf, sizeof(statbuf));
+ qunlock(&p->debug);
+ poperror();
+ goto statbufread;
+
+ case Qwatchpt:
+ j = readwatchpt(p, statbuf, sizeof(statbuf));
+ qunlock(&p->debug);
+ poperror();
+ goto statbufread;
+
+ case Qsyscall:
+ if(p->syscalltrace != nil)
+ n = readstr(offset, va, n, p->syscalltrace);
+ else
+ n = 0;
break;
- case Qstatus:
- buf = readin(p->pid, "status");
- if(buf == nil)
- responderror(req);
+
+ case Qnote:
+ if(n < 1) /* must accept at least the '\0' */
+ error(Etoosmall);
+ if(p->nnote == 0)
+ n = 0;
else {- memset(buf, ' ', 27);
- memcpy(buf, p->name, strlen(p->name));
- sprint(buf + 149, "%d", calcmem(p));
- buf[strlen(buf)] = ' ';
- readstr(req, buf);
- free(buf);
- respond(req, nil);
+ assert(p->note[0] != nil);
+ i = strlen(p->note[0]->msg) + 1;
+ if(i < n)
+ n = i;
+ memmove(va, p->note[0]->msg, n-1);
+ ((char*)va)[n-1] = '\0';
+ freenote(p->note[0]);
+ if(--p->nnote == 0)
+ p->notepending = 0;
+ else
+ memmove(&p->note[0], &p->note[1], p->nnote*sizeof(Note*));
+ p->note[p->nnote] = nil;
}
break;
- case Qsegment:
- buf = segments(p);
- readstr(req, buf);
- free(buf);
- respond(req, nil);
+
+ default:
+ print("unknown qid in procwread\n");+ error(Egreg);
+ }
+
+ qunlock(&p->debug);
+ poperror();
+ return n;
+}
+
+static long
+procwrite(Chan *c, void *va, long n, vlong off)
+{+ char buf[ERRMAX];
+ ulong offset;
+ uchar *rptr;
+ Proc *p;
+
+ offset = off;
+ if(c->qid.type & QTDIR)
+ error(Eisdir);
+
+ /* use the remembered noteid in the channel qid */
+ if(QID(c->qid) == Qnotepg) {+ if(n >= sizeof(buf))
+ error(Etoobig);
+ memmove(buf, va, n);
+ buf[n] = 0;
+ postnotepg(NOTEID(c->qid), buf, NUser);
+ return n;
+ }
+
+ p = proctab(SLOT(c->qid));
+ if(p->pid != PID(c->qid))
+ error(Eprocdied);
+
+ switch(QID(c->qid)){+ case Qargs:
+ if(offset != 0 || n >= sizeof(buf))
+ error(Etoobig);
+ memmove(buf, va, n);
+ buf[n] = 0;
+ kstrdup(&p->args, buf);
+ p->nargs = 0;
+ p->setargs = 1;
break;
- case Qtext:
- rc = pread(a->fd, req->ofcall.data, req->ifcall.count, req->ifcall.offset);
- if(rc >= 0) {- req->ofcall.count = rc;
- respond(req, nil);
- } else
- responderror(req);
- break;
+
case Qmem:
- rc = copymem(p, req->ofcall.data, req->ifcall.offset, req->ifcall.count);
- if(rc >= 0) {- req->ofcall.count = rc;
- respond(req, nil);
- } else
- responderror(req);
+ if(p->state != Stopped)
+ error(Ebadctl);
+ n = procctlmemio(c, p, off2addr(off), va, n, 0);
break;
+
case Qregs:
- buf = emallocz(18 * 4);
- memcpy(buf, p->R, 15 * 4);
- memcpy(buf + 16 * 4, &p->CPSR, 4);
- memcpy(buf + 17 * 4, p->R + 15, 4);
- readbuf(req, buf, 18 * 4);
- free(buf);
- respond(req, nil);
+ if(offset >= REGSIZE)
+ n = 0;
+ else if(offset+n > REGSIZE)
+ n = REGSIZE - offset;
+ if(p->dbgreg == nil)
+ error(Enoreg);
+ setregisters(p->dbgreg, (char*)(p->dbgreg)+offset, va, n);
break;
+ case Qctl:
+ procctlreq(p, va, n);
+ break;
+
+ case Qnote:
+ if(n >= sizeof(buf))
+ error(Etoobig);
+ memmove(buf, va, n);
+ buf[n] = 0;
+ if(!postnote(p, 0, buf, NUser))
+ error("note not posted");+ break;
+
+ case Qnoteid:
+ if(offset != 0 || n >= sizeof(buf))
+ error(Etoobig);
+ memmove(buf, va, n);
+ buf[n] = 0;
+ changenoteid(p, atoi(buf));
+ break;
+
default:
- respond(req, "the front fell off");
+ print("unknown qid in procwrite\n");+ error(Egreg);
}
- */
+ poperror();
+ return n;
}
-/*
static void
-writeto(Req *req, char *fmt, ...)
+procclose(Chan *c)
{- int fd, rc;
- va_list va;
- char *file;
-
- va_start(va, fmt);
- file = vsmprint(fmt, va);
- va_end(va);
- fd = open(file, OWRITE);
- free(file);
- if(fd < 0) {- responderror(req);
+ Segio *sio;
+
+ if((c->flag & COPEN) == 0)
return;
+
+ switch(QID(c->qid)){+ case Qtrace:
+ lock(&tlock);
+ if(topens > 0)
+ topens--;
+ if(topens == 0)
+ proctrace = nil;
+ unlock(&tlock);
+ return;
+ case Qmem:
+ sio = c->aux;
+ if(sio != nil){+ c->aux = nil;
+ segio(sio, nil, nil, 0, 0, 0);
+ free(sio);
+ }
+ return;
}
- rc = write(fd, req->ifcall.data, req->ifcall.count);
- req->ofcall.count = rc;
- if(rc < req->ifcall.count)
- responderror(req);
- else
- respond(req, nil);
- close(fd);
}
-*/
-static long
-procbwrite(Chan *c, Block *b, ulong o)
+static int
+procwstat(Chan *c, uchar *db, int n)
{- //
+ Dir *d;
+ Proc *p;
+
+ if(c->qid.type&QTDIR)
+ error(Eperm);
+
+ switch(QID(c->qid)){+ case Qnotepg:
+ case Qtrace:
+ return devwstat(c, db, n);
+ }
+
+ d = smalloc(sizeof(Dir)+n);
+ if(waserror()){+ free(d);
+ nexterror();
+ }
+ n = convM2D(db, n, &d[0], (char*)&d[1]);
+ if(n == 0)
+ error(Eshortstat);
+
+ p = proctab(SLOT(c->qid));
+ eqlock(&p->debug);
+ if(waserror()){+ qunlock(&p->debug);
+ nexterror();
+ }
+
+ if(p->pid != PID(c->qid))
+ error(Eprocdied);
+
+ nonone(p);
+ if(strcmp(up->user, p->user) != 0 && !iseve())
+ error(Eperm);
+
+ if(!emptystr(d->uid) && strcmp(d->uid, p->user) != 0){+ if(strcmp(d->uid, "none") != 0 && !iseve())
+ error(Eperm);
+ kstrdup(&p->user, d->uid);
+ }
+ /* p->procmode determines default mode for files in /proc */
+ if(d->mode != ~0UL)
+ p->procmode = d->mode&0777;
+
+ qunlock(&p->debug);
+ poperror();
+ poperror();
+ free(d);
+ return n;
}
-static long
-procwrite(Chan *c, void *va, long n, vlong offset)
+static int
+procstat(Chan *c, uchar *db, int n)
{- /*
- switch((int)(req->fid->qid.path % NQid)) {- case Qnote:
- writeto(req, "/proc/%lld/note", req->fid->qid.path / NQid);
- break;
- default:
- respond(req, "the front fell off");
- }
- */
+ return devstat(c, db, n, nil, 0, procgen);
}
+
static void
-procclose(Chan *c)
+procctlreq(Proc *p, char *va, int n)
{- // Any that we care about on close, basically
+ Segment *s;
+ uintptr npc;
+ int pri;
+ Cmdbuf *cb;
+ Cmdtab *ct;
+ vlong time;
+ char *e;
+ void (*pt)(Proc*, int, vlong);
+
+ cb = parsecmd(va, n);
+ if(waserror()){+ free(cb);
+ nexterror();
+ }
+
+ ct = lookupcmd(cb, proccmd, nelem(proccmd));
+
+ switch(ct->index){+ case CMclose:
+ procctlclosefiles(p, 0, atoi(cb->f[1]));
+ break;
+ case CMclosefiles:
+ procctlclosefiles(p, 1, 0);
+ break;
+ case CMhang:
+ p->hang = 1;
+ break;
+ case CMkill:
+ killproc(p, Proc_exitme);
+ break;
+ case CMnohang:
+ p->hang = 0;
+ break;
+ case CMnoswap:
+ p->noswap = 1;
+ break;
+ case CMpri:
+ pri = atoi(cb->f[1]);
+ if(pri > PriNormal && !iseve())
+ error(Eperm);
+ procpriority(p, pri, 0);
+ break;
+ case CMfixedpri:
+ pri = atoi(cb->f[1]);
+ if(pri > PriNormal && !iseve())
+ error(Eperm);
+ procpriority(p, pri, 1);
+ break;
+ case CMprivate:
+ p->privatemem = 1;
+ /*
+ * pages will now get marked private
+ * when faulted in for writing
+ * so force a tlb flush.
+ */
+ p->newtlb = 1;
+ if(p == up)
+ flushmmu();
+ break;
+ case CMprofile:
+ s = p->seg[TSEG];
+ if(s == nil || (s->type&SG_TYPE) != SG_TEXT) /* won't expand */
+ error(Egreg);
+ eqlock(s);
+ npc = (s->size-s->start)>>LRESPROF;
+ if(s->profile == nil){+ s->profile = malloc(npc*sizeof(*s->profile));
+ if(s->profile == nil){+ qunlock(s);
+ error(Enomem);
+ }
+ } else {+ memset(s->profile, 0, npc*sizeof(*s->profile));
+ }
+ qunlock(s);
+ break;
+ case CMstart:
+ if(p->state != Stopped)
+ error(Ebadctl);
+ ready(p);
+ break;
+ case CMstartstop:
+ if(p->state != Stopped)
+ error(Ebadctl);
+ p->procctl = Proc_traceme;
+ ready(p);
+ procstopwait(p, Proc_traceme);
+ break;
+ case CMstartsyscall:
+ if(p->state != Stopped)
+ error(Ebadctl);
+ p->procctl = Proc_tracesyscall;
+ ready(p);
+ procstopwait(p, Proc_tracesyscall);
+ break;
+ case CMstop:
+ procstopwait(p, Proc_stopme);
+ break;
+ case CMwaitstop:
+ procstopwait(p, 0);
+ break;
+ case CMwired:
+ procwired(p, atoi(cb->f[1]));
+ break;
+ case CMtrace:
+ switch(cb->nf){+ case 1:
+ p->trace ^= 1;
+ break;
+ case 2:
+ p->trace = (atoi(cb->f[1]) != 0);
+ break;
+ default:
+ error("args");+ }
+ break;
+ case CMinterrupt:
+ procinterrupt(p);
+ break;
+ case CMnointerrupt:
+ if(p->nnote == 0)
+ p->notepending = 0;
+ else
+ error("notes pending");+ break;
+ }
+
+ poperror();
+ free(cb);
}
static int
-procstat(Chan *c, uchar *db, int n)
+procstopped(void *a)
{- return devstat(c, db, n, nil, 0, procgen);
+ return ((Proc*)a)->state == Stopped;
}
+
+static long
+procctlmemio(Chan *c, Proc *p, uintptr offset, void *a, long n, int read)
+{+ Segment *s;
+ int i;
+
+ eqlock(&p->seglock);
+ if(waserror()) {+ qunlock(&p->seglock);
+ nexterror();
+ }
+ if(p->state <= New || p->pid != PID(c->qid))
+ error(Eprocdied);
+ s = seg(p, offset, 1);
+ if(s == nil)
+ error(Ebadarg);
+ if(waserror()){+ qunlock(s);
+ nexterror();
+ }
+ for(i = 0; i < NSEG; i++) {+ if(p->seg[i] == s)
+ break;
+ }
+ if(i == NSEG)
+ error(Egreg); /* segment gone */
+ if(!read && (s->type&SG_TYPE) == SG_TEXT) {+ p->seg[i] = txt2data(s);
+ qunlock(s);
+ putseg(s);
+ s = p->seg[i];
+ } else {+ qunlock(s);
+ }
+ poperror();
+ incref(s); /* for us while we copy */
+ qunlock(&p->seglock);
+ poperror();
+
+ if(waserror()) {+ putseg(s);
+ nexterror();
+ }
+ offset -= s->base;
+ putseg(s);
+ poperror();
+
+ if(!read)
+ p->newtlb = 1;
+
+ return n;
+}
+
Dev procdevtab = {'P',
"proc",
@@ -408,9 +1023,8 @@
devcreate,
procclose,
procread,
- procbread,
- procwrite,
- procbwrite,
+ devbread,
+ devbwrite,
devremove,
- devwstat,
+ procwstat,
};
--- a/kern/devroot.c
+++ b/kern/devroot.c
@@ -111,10 +111,12 @@
static void
rootreset(void)
{+ addrootdir("arm"); addrootdir("bin"); addrootdir("dev"); addrootdir("env"); addrootdir("fd");+ addrootdir("rc"); addrootdir("net"); addrootdir("net.alt"); addrootdir("proc");--- a/kern/devtab.c
+++ b/kern/devtab.c
@@ -16,7 +16,7 @@
extern Dev lfddevtab;
extern Dev cmddevtab;
extern Dev envdevtab;
-extern Dev procdevtab;
+//extern Dev procdevtab;
Dev *devtab[] = {&rootdevtab,
@@ -31,7 +31,7 @@
&lfddevtab,
&cmddevtab,
&envdevtab,
- &procdevtab,
+// &procdevtab,
0
};
--- a/kern/fns.h
+++ b/kern/fns.h
@@ -58,7 +58,9 @@
Dir* dirchanstat(Chan*);
void drawcmap(void);
void donote(char *, ulong);
+void dump(void);
Fgrp* dupfgrp(Fgrp*);
+Segment* dupseg(Segment**, int, int);
int emptystr(char*);
void envcpy(Egrp*, Egrp*);
int eqchan(Chan*, Chan*, int);
@@ -67,6 +69,8 @@
u32int evenaddr(u32int,u32int);
void exhausted(char*);
void exit(int);
+Fd* copyfd(Fd*);
+void fddecref(Fd*);
void fdclose(int, int);
Chan* fdtochan(int, int, int, int);
void fpatransfer(u32int);
--- a/kern/procinit.c
+++ b/kern/procinit.c
@@ -14,6 +14,7 @@
p->fgrp = dupfgrp(nil);
p->rgrp = newrgrp();
p->pgrp = newpgrp();
+ p->egrp = newegrp();
_setproc(p);
up->slash = namec("#/", Atodir, 0, 0);@@ -60,6 +61,9 @@
p->fgrp = up->fgrp;
if(p->fgrp != nil)
incref(&p->fgrp->ref);
+ p->egrp = up->egrp;
+ if(p->egrp != nil)
+ incref(&p->egrp->ref);
strecpy(p->text, p->text+sizeof p->text, name);
osproc(p);
--- a/kern/seg.c
+++ b/kern/seg.c
@@ -8,7 +8,7 @@
{Segment *s;
- if(debug)
+ if(debug > 1)
print("newseg: size=%.8ux start=%.8ux idx=%d\n", size, start, idx);s = malloc(sizeof *s);
if(s == nil)
@@ -21,9 +21,22 @@
memset(s->dref, 0, sizeof(Ref));
incref(s->dref);
s->data = s->dref + 1;
- if(idx == SEGBSS)
+ if(idx == BSEG)
s->flags = SEGFLLOCK;
- up->S[idx] = s;
+ if(idx == TSEG)
+ s->type = SG_TEXT | SG_RONLY;
+ else if(idx == DSEG)
+ s->type = SG_DATA;
+ else if(idx == BSEG)
+ s->type = SG_BSS;
+ else if(idx == ESEG)
+ s->type = SG_STACK;
+ else
+ panic("newseg: unexpected index %d", idx);+ if(debug > 1)
+ print("newseg: created idx=%d type=%d start=%.8ux size=%.8ux\n",+ idx, s->type, s->start, s->size);
+ up->seg[idx] = s;
return s;
}
@@ -32,12 +45,12 @@
{Segment **s, *ss;
- for(s = up->S; s < up->S + SEGNUM; s++) {+ for(s = up->seg; s < up->seg + NSEG; s++) {if(*s == nil)
continue;
ss = *s;
- if(decref((*s)->dref) == 0)
- free((*s)->dref);
+ if(decref(ss->dref) == 0)
+ free(ss->dref);
if(decref(&ss->ref) == 0)
free(*s);
*s = nil;
@@ -47,41 +60,117 @@
void *
vaddr(u32int addr, u32int len, Segment **seg)
{- Segment **ss, *s;
+ Segment **ss, *s;
int count = 0;
-
- for (ss = up->S; ss < up->S + SEGNUM; ss++) {+
+ qlock(&up->seglock);
+ for (ss = up->seg; ss < up->seg + NSEG; ss++) {count++;
- if (*ss == nil)
- continue;
- s = *ss;
- if (addr >= s->start && addr < s->start + s->size) {- if (addr + len > s->start + s->size)
- break;
- if (s->flags & SEGFLLOCK)
- rlock(&s->rw);
- *seg = s;
- if(debug)
- print("vaddr addr=%.8ux, (%d), PC=%.8ux index=%.8ux segment=%d\n", addr, len, up->R[15], s->start, count);- return (char *)s->data + (addr - s->start);
- }
- }
- panic("segfault addr=%.8ux, (%d), PC=%.8ux", addr, len, up->R[15]);- return nil;
+ if (*ss == nil)
+ continue;
+ s = *ss;
+ if (addr >= s->start && addr < s->start + s->size) {+ if (addr + len > s->start + s->size)
+ break;
+ if (s->flags & SEGFLLOCK)
+ rlock(&s->rw);
+ *seg = s;
+ if(debug > 1)
+ print("vaddr addr=%.8ux, len=%d, PC=%.8ux, index=%.8ux, segment=%d, type=%d, pid=%d\n",+ addr, len, up->R[15], s->start, count - 1, s->type, up->pid);
+ qunlock(&up->seglock);
+ return (char *)s->data + (addr - s->start);
+ }
+ }
+ qunlock(&up->seglock);
+ panic("segfault addr=%.8ux, len=%d, PC=%.8ux, pid=%d\n", addr, len, up->R[15], up->pid);+ return nil;
}
+Segment*
+data2txt(Segment *s)
+{+ Segment *ps;
+
+ if(debug > 1)
+ print("data2txt: converting start=%.8ux size=%.8ux\n", s->start, s->size);+ ps = newseg(s->start, s->size, TSEG);
+ ps->dref = s->dref;
+ memcpy(ps->data, s->data, s->size);
+ return ps;
+}
+
+Segment *
+dupseg(Segment **seg, int segno, int share)
+{+ Segment *n, *s;
+
+ if(segno < 0 || segno >= NSEG)
+ panic("dupseg: invalid segment index %d", segno);+ s = seg[segno];
+ if(s == nil) {+ if(debug > 1)
+ print("dupseg: null segment for segno=%d, skipping\n", segno);+ return nil;
+ }
+ if(debug > 1)
+ print("dupseg: segno=%d, type=%d, start=%.8ux, size=%.8ux, share=%d\n", segno, s->type, s->start, s->size, share);+ qlock(&s->rw);
+ if(waserror()) {+ qunlock(&s->rw);
+ nexterror();
+ }
+ switch(s->type&SG_TYPE) {+ case SG_TEXT: /* New segment shares pte set */
+ case SG_SHARED:
+ case SG_PHYSICAL:
+ case SG_FIXED:
+ case SG_STICKY:
+ default:
+ goto sameseg;
+ case SG_STACK:
+ n = newseg(s->start, s->size, s->type);
+ memcpy(n->data, s->data, s->size);
+ break;
+ case SG_BSS: /* Just copy on write */
+ if(share)
+ goto sameseg;
+ n = newseg(s->start, s->size, s->type);
+ break;
+ case SG_DATA: /* Copy on write plus demand load info */
+ if(segno == TSEG){+ n = data2txt(s);
+ qunlock(s);
+ poperror();
+ return n;
+ }
+ if(share)
+ goto sameseg;
+ n = newseg(s->start, s->size, s->type);
+ memcpy(n->dref, s->dref, s->size);
+ break;
+ }
+ qunlock(s);
+ poperror();
+ return n;
+sameseg:
+ incref(s);
+ qunlock(s);
+ poperror();
+ return s;
+}
+
void*
vaddrnol(u32int addr, u32int len)
{- Segment *seg;
+ Segment *seg;
void *ret;
- ret = vaddr(addr, len, &seg);
+ ret = vaddr(addr, len, &seg);
segunlock(seg);
return ret;
}
-/* might be made a macro for hurr durr performance */
void
segunlock(Segment *s)
{@@ -146,4 +235,4 @@
memmove(targ, data, len);
segunlock(seg);
free(data);
-}
\ No newline at end of file
+}
--- a/kern/syscall.c
+++ b/kern/syscall.c
@@ -300,11 +300,11 @@
v = v + 7 & -8;
if(debug)
print("sysbrk v=%#lux\n", v);- if(v >= up->S[SEGSTACK]->start)
+ if(v >= up->seg[ESEG]->start)
panic("bss > stack, wtf?");- if(v < up->S[SEGBSS]->start)
+ if(v < up->seg[BSEG]->start)
panic("bss length < 0, wtf?");- s = up->S[SEGBSS];
+ s = up->seg[BSEG];
wlock(&s->rw);
s->dref = realloc(s->dref, v - s->start + sizeof(Ref));
if(s->dref == nil)
@@ -382,17 +382,18 @@
u32int flags;
int rc, i;
Segment *s, *t;
- Proc *p;
- if(debug)
- print("sysrfork\n");+ Fd *old;
flags = arg(0);
+ if(debug)
+ print("rfork(%#o) for proc pid=%lud\n", flags, up->pid);if((flags & (RFFDG | RFCFDG)) == (RFFDG | RFCFDG) ||
(flags & (RFNAMEG | RFCNAMEG)) == (RFNAMEG | RFCNAMEG) ||
(flags & (RFENVG | RFCENVG)) == (RFENVG | RFCENVG)) {- werrstr("bad arg in rfork");up->R[0] = -1;
+ cherrstr("bad arg in syscall");return;
}
+
if((flags & RFPROC) == 0) { if(flags & RFFDG) {Fgrp *old = up->fgrp;
@@ -407,112 +408,43 @@
up->R[0] = noteerr(sysrfork(flags), 0);
return;
}
- p = newproc();
- if(p == nil) {- fprint(2, "rfork: malloc failed for Proc");
- werrstr("rfork: malloc failed");- up->R[0] = -1;
- return;
- }
- memset(p, 0, sizeof(Proc));
- memcpy(p, up, sizeof(Proc));
- for(i = 0; i < SEGNUM; i++) {- s = p->S[i];
- if(s == nil)
- continue;
- if((flags & RFMEM) == 0 && i != SEGTEXT || i == SEGSTACK) {- t = newseg(s->start, s->size, s->flags);
- if(t == nil) {- fprint(2, "rfork: newseg failed");
- werrstr("rfork: newseg failed");- up->R[0] = -1;
- return;
- }
- t->dref = mallocz(sizeof(Ref) + s->size, 1);
- if(t->dref == nil) {- fprint(2, "rfork: malloc failed for Segment data");
- werrstr("rfork: malloc failed");- up->R[0] = -1;
- return;
- }
- incref(t->dref);
- t->data = t->dref + 1;
- memcpy(t->data, s->data, s->size);
- p->S[i] = t;
- } else {- incref(s->dref);
- incref(&s->ref);
- }
- }
- if(flags & RFFDG)
- p->fgrp = dupfgrp(up->fgrp);
- else if(flags & RFCFDG)
- p->fgrp = dupfgrp(nil);
- else
- incref(&up->fgrp->ref);
- if(flags & RFNAMEG)
- p->pgrp = newpgrp();
- else
- incref(&up->pgrp->ref);
- if(flags & RFENVG)
- p->egrp = newegrp();
- else
- incref(&up->egrp->ref);
+
+ /* Seg could be being shared here, not useful */
rc = sysrfork(flags);
- if(rc < 0) {- fprint(2, "rfork: sysrfork failed: %r");
- werrstr("rfork: %r");- up->R[0] = -1;
- return;
- }
- if(rc == 0) {- _setproc(p);
- atexit((void(*)(void))pexit);
- p->pid = getpid();
- inittos();
- osproc(p);
- }
- up->R[0] = rc;
+ if(rc < 0) /* this should NEVER happen */
+ panic("rfork failed: %r");}
static void
_sysexec(void)
{- u32int name, argv;
- char *namet;
- char **argvv;
+ u32int name, argv, *argvt;
+ char *namet, **argvv;
int i, argc, rc;
- Segment *seg;
- u32int *argvt;
-
+ Segment *seg1, *seg2;
+
name = arg(0);
argv = arg(1);
- namet = estrdup((char*)vaddrnol(name, 0));
- argvt = vaddr(argv, 0, &seg);
+ namet = strdup(vaddr(name, 0, &seg1));
+ segunlock(seg1);
+ argvt = vaddr(argv, 0, &seg1);
if(debug)
- print("sysexec: name=%s", namet);+ fprint(2, "exec(%#ux=\"%s\", %#ux)\n", name, namet, argv);
for(argc = 0; argvt[argc]; argc++)
;
- argvv = mallocz(sizeof(char *) * (argc + 1), 1);
- if(argvv == nil) {- fprint(2, "exec: malloc failed for argv");
- werrstr("exec: malloc failed");- up->R[0] = -1;
- free(namet);
- return;
- }
+ argvv = emalloc(sizeof(char *) * argc);
for(i = 0; i < argc; i++) {- argvv[i] = estrdup((char*)vaddrnol(argvt[i], 0));
+ argvv[i] = strdup(vaddr(argvt[i], 0, &seg2));
+ segunlock(seg2);
}
- argvv[argc] = nil;
- segunlock(seg);
+ segunlock(seg1);
rc = loadtext(namet, argc, argvv);
for(i = 0; i < argc; i++)
free(argvv[i]);
free(argvv);
- free(namet);
if(rc < 0)
up->R[0] = noteerr(rc, 0);
+ free(namet);
}
static void
--- a/kern/sysproc.c
+++ b/kern/sysproc.c
@@ -12,7 +12,6 @@
#include <sys/mman.h>
#include <setjmp.h>
-#undef rfork
#undef read
jmp_buf exec_jmp;
#define pgsize 0x1000
@@ -163,110 +162,6 @@
wunlock(&fd->rw);
}
-int
-sysrfork(int flags)
-{- int pid, status;
- int p[2];
- int n;
- char buf[128], *q;
- extern char **environ;
- struct sigaction oldchld;
-
- memset(&oldchld, 0, sizeof oldchld);
-
- if((flags&(RFPROC|RFFDG|RFMEM)) == (RFPROC|RFFDG)){- flags &= ~(RFPROC|RFFDG|RFENVG);
- n = (flags & ~(RFNOTEG|RFNAMEG|RFNOWAIT|RFCENVG));
- if(n){- werrstr("unknown flags %08ux in rfork", n);- return -1;
- }
- if(flags&RFNOWAIT){- sigaction(SIGCHLD, nil, &oldchld);
- signal(SIGCHLD, nop);
- if(pipe(p) < 0)
- return -1;
- }
- pid = fork();
- if(pid == -1)
- return -1;
- if(flags&RFNOWAIT){- flags &= ~RFNOWAIT;
- if(pid){- close(p[1]);
- status = 0;
- if(wait4(pid, &status, 0, 0) < 0){- werrstr("pipe dance - wait4 - %r");- close(p[0]);
- return -1;
- }
- n = readn(p[0], buf, sizeof buf-1);
- close(p[0]);
- if(!WIFEXITED(status) || WEXITSTATUS(status)!=0 || n <= 0){- if(!WIFEXITED(status))
- werrstr("pipe dance - !exited 0x%ux", status);- else if(WEXITSTATUS(status) != 0)
- werrstr("pipe dance - non-zero status 0x%ux", status);- else if(n < 0)
- werrstr("pipe dance - pipe read error - %r");- else if(n == 0)
- werrstr("pipe dance - pipe read eof");- else
- werrstr("pipe dance - unknown failure");- return -1;
- }
- buf[n] = 0;
- if(buf[0] == 'x'){- werrstr("%s", buf+2);- return -1;
- }
- pid = strtol(buf, &q, 0);
- }else{- signal(SIGCHLD, SIG_IGN);
- close(p[0]);
- pid = fork();
- if(pid){- if(pid > 0)
- print("%d\n", pid);- else
- print("x %r\n");- close(p[1]);
- _exit(0);
- }else{- close(p[1]);
- }
- }
- sigaction(SIGCHLD, &oldchld, nil);
- }
- if(pid != 0)
- return pid;
- if(flags&RFCENVG)
- if(environ)
- *environ = nil;
- }
- if(flags&RFPROC){- werrstr("cannot use rfork for shared memory -- use libthread");- return -1;
- }
- if(flags&RFNAMEG){- flags &= ~RFNAMEG;
- }
- if(flags&RFNOTEG){- setpgid(0, getpid());
- flags &= ~RFNOTEG;
- }
- if(flags&RFNOWAIT){- werrstr("cannot use RFNOWAIT without RFPROC");- return -1;
- }
- if(flags){- werrstr("unknown flags %08ux in rfork", flags);- return -1;
- }
- return 0;
-}
-
ulong
beswal(ulong l)
{@@ -377,7 +272,7 @@
tos = (USTKTOP & ~7) - sizeof(Tos) * 2;
sp = tos;
- if(debug)
+ if(debug > 1)
print("initstack: tos=%.8ux tossz=%.8ux USTKTOP=%.8ux\n", tos, sizeof(Tos), USTKTOP);size = 8;
for(i = 0; i < argc; i++)
@@ -392,7 +287,7 @@
*(ulong *) vaddrnol(sp, 4) = argc;
sp += 4;
ap = sp + (argc + 1) * 4;
- if(debug)
+ if(debug > 1)
print("initstack: argc=%d sp=%.8ux ap=%.8ux\n", argc, sp, ap); for(i = 0; i < argc; i++) {*(ulong *) vaddrnol(sp, 4) = ap;
@@ -402,7 +297,7 @@
ap += len;
}
*(ulong *) vaddrnol(sp, 4) = 0;
- inittos();
+ inittos();
}
@@ -475,7 +370,7 @@
Exec hdr;
char buf[2];
int fd;
-
+
fd = open(file, OREAD);
if(fd < 0) return -1;
if(pread(fd, buf, 2, 0) == 2 && buf[0] == '#' && buf[1] == '!')
@@ -501,10 +396,10 @@
freesegs();
memset(up->R, 0, sizeof(up->R));
up->CPSR = 0;
- text = newseg(txtaddr - hdrsz, txtsz + hdrsz, SEGTEXT);
- data = newseg(dataddr, datsz, SEGDATA);
- bss = newseg(dataddr + datsz, bsssz, SEGBSS);
- newseg((USTKTOP & ~7) - USTKSIZE, USTKSIZE, SEGSTACK);
+ text = newseg(txtaddr - hdrsz, txtsz + hdrsz, TSEG);
+ data = newseg(dataddr, datsz, DSEG);
+ bss = newseg(dataddr + datsz, bsssz, BSEG);
+ newseg((USTKTOP & ~7) - USTKSIZE, USTKSIZE, ESEG);
seek(fd, txtoff - hdrsz, 0);
if(readn(fd, text->data, txtsz + hdrsz) < txtsz + hdrsz)
panic("%r");@@ -518,9 +413,198 @@
fdclear(up->fd);
initstack(argc, argv);
- if(debug)
+ if(debug > 1)
print("loadtext: PC=%.8ux, R1=%.8ux, R13=%.8ux\n", up->R[15], up->R[1], up->R[13]);resetvfp();
return 0;
-}
\ No newline at end of file
+}
+
+
+void
+procrun(void*)
+{+ for(;;) {+ if(debug > 2)
+ dump();
+ step();
+ while((up->notein - up->noteout) % NNOTE) {+ donote(up->notes[up->noteout % NNOTE], 0);
+ up->noteout++;
+ }
+ }
+}
+
+int
+sysrfork(int flag)
+{+ Proc *p;
+ Fgrp *ofg;
+ Pgrp *opg;
+ Rgrp *org;
+ Egrp *oeg;
+ ulong pid;
+ char *devs;
+ int i, n;
+
+ /* Check flags before we commit */
+ if((flag & (RFFDG|RFCFDG)) == (RFFDG|RFCFDG))
+ error(Ebadarg);
+ if((flag & (RFNAMEG|RFCNAMEG)) == (RFNAMEG|RFCNAMEG))
+ error(Ebadarg);
+ if((flag & (RFENVG|RFCENVG)) == (RFENVG|RFCENVG))
+ error(Ebadarg);
+ if((flag&RFPROC) == 0) {+ if(flag & (RFMEM|RFNOWAIT))
+ error(Ebadarg);
+ if(flag & (RFFDG|RFCFDG)) {+ ofg = up->fgrp;
+ if(flag & RFFDG)
+ up->fgrp = dupfgrp(ofg);
+ else
+ up->fgrp = dupfgrp(nil);
+ closefgrp(ofg);
+ }
+ if(flag & (RFNAMEG|RFCNAMEG)) {+ opg = up->pgrp;
+ up->pgrp = newpgrp();
+ if(flag & RFNAMEG)
+ pgrpcpy(up->pgrp, opg);
+ closepgrp(opg);
+ }
+ //if(flag & RFNOMNT)
+ // devmask(up->pgrp, 1, devs);
+ if(flag & RFREND) {+ org = up->rgrp;
+ up->rgrp = newrgrp();
+ closergrp(org);
+ }
+ if(flag & (RFENVG|RFCENVG)) {+ oeg = up->egrp;
+ up->egrp = smalloc(sizeof(Egrp));
+ up->egrp->ref.ref = 1;
+ if(flag & RFENVG)
+ envcpy(up->egrp, oeg);
+ closeegrp(oeg);
+ }
+ if(flag & RFNOTEG){+ qlock(&up->debug);
+ // TODO: Notegroups
+ //setnoteid(up, 0); /* can't error() with 0 argument */
+ qunlock(&up->debug);
+ }
+ return 0;
+ }
+
+ p = newproc();
+
+ qlock(&up->debug);
+ qlock(&p->debug);
+ p->slash = cclone(up->slash);
+ p->dot = cclone(up->dot);
+ strecpy(p->text, p->text+sizeof p->text, up->text);
+ p->kp = 0;
+
+ /* TODO: Notes */
+ //p->nnote = 0;
+ //p->notify = up->notify;
+ //p->notified = 0;
+ //p->notepending = 0;
+ //p->lastnote = nil;
+
+ //if((flag & RFNOTEG) == 0)
+ // p->noteid = up->noteid;
+
+ /* Copy regs over */
+ for(i = 0; i <= 15; i++)
+ p->R[i] = up->R[i];
+ p->R[0] = 0;
+ p->CPSR = up->CPSR;
+ p->FPSR = up->FPSR;
+
+ strcpy(&p->text, up->text);
+ strcpy(&p->user, up->user);
+ //strcpy(&p->args, "");
+ //p->nargs = 0;
+ //p->setargs = 0;
+ pid = getpid();
+
+ qunlock(&p->debug);
+ qunlock(&up->debug);
+ if(waserror()){+ p->kp = 1;
+ nexterror();
+ }
+
+ n = flag & RFMEM;
+ qlock(&p->seglock);
+ if(waserror()){+ qunlock(&p->seglock);
+ nexterror();
+ }
+
+ for(i = 0; i < NSEG; i++)
+ if(up->seg[i] != nil)
+ p->seg[i] = dupseg(up->seg, i, n);
+ qunlock(&p->seglock);
+ poperror();
+
+ if(flag & (RFFDG|RFCFDG)) {+ if(flag & RFFDG)
+ p->fgrp = dupfgrp(up->fgrp);
+ else
+ p->fgrp = dupfgrp(nil);
+ }
+ else {+ p->fgrp = up->fgrp;
+ incref(p->fgrp);
+ }
+
+ /* Process groups */
+ if(flag & (RFNAMEG|RFCNAMEG)) {+ p->pgrp = newpgrp();
+ if(flag & RFNAMEG)
+ pgrpcpy(p->pgrp, up->pgrp);
+ /* inherit notallowed */
+ //memmove(p->pgrp->notallowed, up->pgrp->notallowed, sizeof p->pgrp->notallowed);
+ }
+ else {+ p->pgrp = up->pgrp;
+ incref(p->pgrp);
+ }
+ /* TODO: devmask
+ if(flag & RFNOMNT)
+ devmask(p->pgrp, 1, devs);
+ */
+ if(flag & RFREND)
+ p->rgrp = newrgrp();
+ else {+ incref(up->rgrp);
+ p->rgrp = up->rgrp;
+ }
+
+ /* Environment group */
+ if(flag & (RFENVG|RFCENVG)) {+ p->egrp = smalloc(sizeof(Egrp));
+ p->egrp->ref.ref = 1;
+ if(flag & RFENVG)
+ envcpy(p->egrp, up->egrp);
+ }
+ else {+ p->egrp = up->egrp;
+ incref(p->egrp);
+ }
+ p->fn = procrun;
+ p->arg = 0;
+
+ poperror();
+ if((flag&RFNOWAIT) == 0){+ //p->parent = up;
+ //lock(&up->exl);
+ //up->nchild++;
+ //unlock(&up->exl);
+ }
+
+ osproc(p);
+ return 0;
+}
--- a/kern/vfp.c
+++ b/kern/vfp.c
@@ -19,7 +19,6 @@
{u32int *Rt;
double *Fn;
-
Rt = up->R + ((instr>>12)&0xF);
Fn = up->F + ((instr>>16)&0xF);
switch((instr>>20)&0xF){@@ -46,7 +45,6 @@
int n, d, off, sz;
void* ea;
Segment *seg;
-
n = (instr>>16) & 0xF;
d = (instr>>12) & 0xF;
off = (instr & 0xFF) << 2;
@@ -67,6 +65,13 @@
else
up->F[d] = *(float*)ea;
break;
+ case 2:
+ if(sz)
+ *(double*)ea = up->F[d];
+ else
+ *(float*)ea = up->F[d];
+ up->R[n] += off;
+ break;
default:
sysfatal("unimplemented VFP instruction %8ux @ %8ux", instr, up->R[15] - 4);}
--- a/main.c
+++ b/main.c
@@ -49,18 +49,6 @@
}
void
-dump(void)
-{- int i;
-
- for(i = 0; i < 16; i++) {- print("R%2d %.8ux", i, up->R[i]);- if((i % 4) == 3) print("\n");- else print("\t");- }
-}
-
-void
notehandler(void *d, char *note)
{USED(d);
@@ -74,6 +62,17 @@
return;
}
+void
+dump(void)
+{+ print("R00 %.8ux\tR01 %.8ux\tR02 %.8ux\tR03 %.8ux\tpid: %d\nR04 %.8ux\tR05 %.8ux\tR06 %.8ux\tR07 %.8ux\nR08 %.8ux\tR09 %.8ux\tR10 %.8ux\tR11 %.8ux\nR12 %.8ux\tR13 %.8ux\tR14 %.8ux\tR15 %.8ux\n", + up->R[0], up->R[1], up->R[2], up->R[3], up->pid,
+ up->R[4], up->R[5], up->R[6], up->R[7],
+ up->R[8], up->R[9], up->R[10], up->R[11],
+ up->R[12], up->R[13], up->R[14], up->R[15]
+ );
+}
+
int
main(int argc, char **argv)
{@@ -120,6 +119,9 @@
panic("bind #U: %r"); //if(bind("#P", "/proc", MBEFORE) < 0) // panic("bind #P: %r");+ if(bind("#L", "/fd", MAFTER) < 0)+ panic("bind #L");+
bind("#A", "/dev", MAFTER); bind("#N", "/dev", MAFTER); bind("#C", "/", MAFTER);@@ -127,7 +129,9 @@
if(bind("/root", "/", MAFTER) < 0) panic("bind /root: %r");- /* RC Main */
+ /* TODO: /path/to/root, root has /rc and /arm
+ * Bind in /arm/bin, /rc/bin/ and /rc/lib
+ */
if(rc != nil)
bind(rc, "/rc", MAFTER);
@@ -153,7 +157,7 @@
notify(notehandler);
for(;;) {- if(debug)
+ if(debug > 2)
dump();
step();
while((up->notein - up->noteout) % NNOTE) {@@ -161,5 +165,6 @@
up->noteout++;
}
}
+
exits(0);
}
--- /dev/null
+++ b/rc/lib/rcmain
@@ -1,0 +1,39 @@
+# rcmain: Plan 9 version
+if(~ $#home 0) home=/
+if(~ $#ifs 0) ifs='
+'
+switch($#prompt){+case 0
+ prompt=('% ' ' ')+case 1
+ prompt=($prompt ' ')
+}
+if(~ $rcname ?.out) prompt=('broken! ' ' ')+if(flag p) path=/bin
+if not{+ finit
+ if(~ $#path 0) path=(/bin .)
+}
+fn sigexit
+if(! ~ $#cflag 0){+ if(flag l){+ if(/bin/test -r /rc/lib/rcmain.local) . /rc/lib/rcmain.local
+ if(/bin/test -r $home/lib/profile) . $home/lib/profile
+ }
+ status=''
+ eval $cflag
+}
+if not if(flag i){+ if(flag l){+ if(/bin/test -r /rc/lib/rcmain.local) . /rc/lib/rcmain.local
+ if(/bin/test -r $home/lib/profile) . $home/lib/profile
+ }
+ status=''
+ if(! ~ $#* 0) . $*
+ . -i /fd/0
+}
+if not if(~ $#* 0) . /fd/0
+if not{+ status=''
+ . $*
+}
\ No newline at end of file
--
⑨