commit 19116b28b91316cf3b2c8cc8b3864bf06fad6b2e
parent 186b917a8d3a79d58afd3f7ae1e4b0eccaae52bc
Author: Roberto E. Vargas Caballero <k0ga@shike2.com>
Date: Fri, 2 Dec 2022 07:44:52 +0100
Merge remote-tracking branch 'simple-cc/master'
Diffstat:
29 files changed, 1085 insertions(+), 438 deletions(-)
diff --git a/include/bits/amd64/arch/types.h b/include/bits/amd64/arch/types.h
@@ -11,6 +11,7 @@
typedef int atomic_t;
typedef unsigned long mutex_t;
+typedef unsigned long spinlock_t;
typedef unsigned long long phyaddr_t;
typedef struct context Context;
diff --git a/include/bits/arm64/arch/types.h b/include/bits/arm64/arch/types.h
@@ -61,6 +61,7 @@ enum regidx {
typedef int atomic_t;
typedef unsigned long mutex_t;
+typedef unsigned long splinlock_t;
typedef unsigned long long pte_t;
typedef unsigned long long phyaddr_t;
typedef struct context Context;
diff --git a/include/os9/os9.h b/include/os9/os9.h
@@ -42,15 +42,17 @@
typedef struct ptable Ptable;
typedef struct context Context;
typedef struct task Task;
-typedef struct win Win;
typedef struct chan Chan;
typedef struct qid Qid;
typedef struct dir Dir;
typedef struct mach Mach;
typedef struct map Map;
+typedef struct page Page;
+typedef struct mpoint Mpoint;
typedef struct nspace Nspace;
typedef struct fdset Fdset;
typedef struct ref Ref;
+typedef struct rendez Rendez;
enum rforkflags {
RFPROC = 1 << 0,
@@ -99,11 +101,23 @@ enum map_attr {
MD = 1 << 3,
};
+enum sysnumbers {
+ SYSOPEN,
+ NR_SYSCALLS,
+};
+
struct ref {
mutex_t m;
int cnt;
};
+struct page {
+ int allocated;
+ uintptr_t va;
+ phyaddr_t pa;
+ struct page *next;
+};
+
struct map {
Ref ref;
char *name;
@@ -112,6 +126,10 @@ struct map {
phyaddr_t pa;
uintptr_t va;
size_t siz;
+
+ Page *pages;
+
+ Map *next;
};
/*
@@ -142,6 +160,7 @@ struct dir {
};
struct chan {
+ Ref ref;
long offset;
int index;
Qid qid;
@@ -149,25 +168,39 @@ struct chan {
unsigned char dev;
unsigned char mode;
mutex_t mutex;
+ Chan *next;
};
struct mpoint {
+ Ref ref;
Chan *new;
Chan *old;
mutex_t m;
+ Mpoint *next;
};
-
struct nspace {
Ref ref;
mutex_t m;
- struct mpoint mpoints[NR_MPOINTS];
+ Mpoint *mpoints[NR_MPOINTS];
+ Nspace *next;
};
struct fdset {
Ref ref;
mutex_t m;
- Chan fdset[NR_CHANS];
+ Chan *fdset[NR_CHANS];
+ Fdset *next;
+};
+
+struct rendez {
+ spinlock_t s;
+ Task *task;
+};
+
+struct syscall {
+ int nargs;
+ int (*fn)(int, ...);
};
/**
@@ -201,6 +234,8 @@ struct task {
void *entry;
+ int errno;
+
int prio;
int baseprio;
int retainprio;
@@ -249,21 +284,46 @@ extern Map *newstack(Task *);
extern void sched(void);
extern void locktask(Task *);
extern void unlocktask(Task *);
+extern void sleep(Rendez *, int (*cond)(void *), void *);
+extern void wakeup(Rendez *);
+extern void seterror(int);
/* alloc.c */
extern void *alloc(size_t);
-extern void *allocb(int);
+extern void *allocb(void);
+extern Page *allocp(phyaddr_t);
+extern Nspace *allocspace(void);
+extern Map *allocmap(void);
+extern Fdset *allocfds(void);
+extern Chan *allocchan(void);
+extern Mpoint *allocmpoint(void);
+
extern void freeb(void *);
+extern void freep(Page *);
+extern void freespace(Nspace *);
+extern void freemap(Map *);
+extern void freefds(Fdset *);
+extern void freechan(Chan *);
+extern void freempoint(Mpoint *);
+extern void ialloc(void);
+
+/* map.c */
+extern Map *newstack(Task *);
+extern Map *newkstack(Task *);
+extern int unmapseg(Map *);
+extern int mapseg(Map *);
+extern void delmap(Map *);
+extern Map *newmap(Map *);
/* sys.c */
extern void isys(void);
-extern void info(void);
/* dlang.c */
extern int debug(void);
/* arch mmu.c */
extern int vmap(phyaddr_t, uintptr_t, int);
+extern int vunmap(phyaddr_t, uintptr_t);
/* arch functions */
extern Context *getctx(Context *ctx);
@@ -277,6 +337,8 @@ extern uint32_t outm32(uint32_t, void *addr);
extern void lock(mutex_t *m);
extern void unlock(mutex_t *m);
extern int trylock(mutex_t *m);
+extern void lockspin(spinlock_t *);
+extern void unlockspin(spinlock_t *);
extern void barrier(int);
extern noreturn void halt(void);
extern noreturn void panic(const char *msg);
@@ -291,19 +353,23 @@ extern void idle(void);
/* dev functions */
extern void idev(void);
-extern Chan *devopen(char *name, int mode);
-extern int devwrite(Chan *c, void *buf, int n);
-extern int devread(Chan *c, void *buf, int n);
-extern int devclose(Chan *c);
+extern Chan *namec(char *, int mode);
+extern int chanwrite(Chan *c, void *buf, int n);
+extern int chanread(Chan *c, void *buf, int n);
+extern int chanclose(Chan *c);
extern int mount(char *, char *, char *);
extern int bind(char *, char *);
-
-/* sched.c */
+extern Nspace *newspace(Nspace *);
+extern Fdset *newfds(Fdset *);
+extern void delspace(Nspace *);
+extern void delfds(Fdset *);
/* globals */
extern Chan *console;
extern Mach mach;
extern char buffertab[NR_BUFFERS][PAGESIZE];
+extern char bufto[], buffrom[];
+extern struct syscall systab[];
/* per cpu globals */
extern Task *proc;
diff --git a/src/libk/getline.c b/src/libk/getline.c
@@ -9,7 +9,7 @@ getline(Chan *c, char *line, int size)
char ch;
for (ch = n = 0; n < size-1 && ch != '\n'; ++n) {
- if ((r = devread(c, &ch, 1)) < 0)
+ if ((r = chanread(c, &ch, 1)) < 0)
return -1;
if (r == 0)
break;
diff --git a/src/os9/Makefile b/src/os9/Makefile
@@ -11,13 +11,16 @@ include $(PROJECTDIR)/scripts/rules.mk
OBJS =\
alloc.o\
dlang.o\
+ map.o\
proc.o\
+ ref.o\
+ syscall.o\
sys.o\
dev/builtin.o\
all: image
-version.h:
+version.h: FORCE
./mkver
sys.o: version.h
diff --git a/src/os9/alloc.c b/src/os9/alloc.c
@@ -1,76 +1,323 @@
#include <os9/os9.h>
+#include <libk.h>
+
#include <errno.h>
#include <string.h>
union bucket {
long long ll;
uintptr_t up;
+ union bucket *next;
+};
+
+struct pool {
+ void *list;
+ mutex_t m;
};
+static union bucket *heap;
+static struct pool bufpool;
+static struct pool pagepool;
+static struct pool nspool;
+static struct pool mappool;
+static struct pool fdspool;
+static struct pool chanpool;
+static struct pool mpointpool;
void
freeb(void *bp)
{
- if (!bp)
+ union bucket *p = bp;
+
+ if (!p)
return;
- /* TODO */
+
+ lock(&bufpool.m);
+ p->next = bufpool.list;
+ bufpool.list = p;
+ unlock(&bufpool.m);
}
void *
-allocb(int n)
+allocb(void)
{
- void *addr = NULL;
- static unsigned long npages;
- static mutex_t m;
+ union bucket *bp = NULL;
- lock(&m);
- if (n >= NR_BUFFERS - npages) {
- errno = ENOMEM;
- goto end;
+ lock(&bufpool.m);
+ if (!bufpool.list) {
+ seterror(ENOMEM);
+ } else {
+ bp = bufpool.list;
+ bufpool.list = bp->next;
}
- addr= buffertab[npages];
- npages += n;
-end:
- unlock(&m);
+ unlock(&bufpool.m);
- return addr;
+ return bp;
}
void *
alloc(size_t size)
{
- static int lockalloc;
size_t n;
static size_t used;
- static union bucket *heap;
static mutex_t m;
- union bucket *bp = NULL;
+ void *bp;
- lock(&m);
if (size == 0) {
- lockalloc = 1;
- goto end;
+ seterror(EINVAL);
+ return NULL;
}
- if (lockalloc) {
- errno = 1; /* TODO: What can I do here???? */
- goto end;
- }
-
- if (!heap)
- heap = allocb(HEAPSIZ);
-
+ lock(&m);
n = (size-1) / sizeof(union bucket) + 1;
size = n * sizeof(union bucket);
- if (used > SIZE_MAX - size) {
- errno = ENOMEM;
- goto end;
+
+ if (used > PAGESIZE*HEAPSIZ - size) {
+ bp = NULL;
+ seterror(ENOMEM);
+ } else {
+ bp = (char *) heap + used;
+ used += size;
}
- bp = heap + used;
- used += size;
-end:
unlock(&m);
return bp;
}
+
+Nspace *
+allocspace(void)
+{
+ Nspace *ns;
+
+ lock(&nspool.m);
+ if (nspool.list) {
+ ns = nspool.list;
+ nspool.list = ns->next;
+ } else {
+ if ((ns = alloc(sizeof(*ns))) == NULL)
+ return NULL;
+ }
+ unlock(&nspool.m);
+
+ return ns;
+}
+
+void
+freespace(Nspace *ns)
+{
+ lock(&nspool.m);
+ ns->next = nspool.list;
+ nspool.list = ns;
+ unlock(&nspool.m);
+}
+
+Map *
+allocmap(void)
+{
+ Map *mp;
+
+ lock(&mappool.m);
+ if (mappool.list) {
+ mp = mappool.list;
+ mappool.list = mp->next;
+ } else {
+ if ((mp = alloc(sizeof(*mp))) == NULL)
+ return NULL;
+ }
+ unlock(&mappool.m);
+
+ return mp;
+}
+
+void
+freemap(Map *mp)
+{
+ lock(&mappool.m);
+ mp->next = mappool.list;
+ mappool.list = mp;
+ unlock(&mappool.m);
+}
+
+Fdset *
+allocfds(void)
+{
+ Fdset *fds;
+
+ lock(&fdspool.m);
+ if (fdspool.list) {
+ fds = fdspool.list;
+ fdspool.list = fds->next;
+ } else {
+ if ((fds = alloc(sizeof(*fds))) == NULL)
+ return NULL;
+ }
+ unlock(&fdspool.m);
+
+ return fds;
+}
+
+void
+freefds(Fdset *fds)
+{
+ if (!fds)
+ return;
+
+ lock(&fdspool.m);
+ fds->next = fdspool.list;
+ fdspool.list = fds;
+ unlock(&fdspool.m);
+}
+
+/*
+ * This functions is always called with the page pool locked
+ */
+static int
+morepages(void)
+{
+ Page *p, *bp;
+
+ if (pagepool.list)
+ return 1;
+
+ if ((bp = allocb()) == NULL)
+ return 0;
+
+ for (p = bp; p < &bp[PAGESIZE/sizeof(Page)]; ++p)
+ p->next = p+1;
+ p->next = NULL;
+
+ pagepool.list = bp;
+
+ return 1;
+}
+
+Page *
+allocp(phyaddr_t pa)
+{
+ int alloc = 0;
+ void *bp = NULL;
+ Page *p;
+
+ if (pa == -1) {
+ if ((bp = allocb()) == NULL)
+ return NULL;
+ pa = (phyaddr_t) PMEM(bp);
+ alloc = 1;
+ }
+
+ lock(&pagepool.m);
+
+ if (!morepages()) {
+ freeb(bp);
+ unlock(&pagepool.m);
+ return NULL;
+ }
+
+ p = pagepool.list;
+ pagepool.list = p->next;
+
+ unlock(&pagepool.m);
+
+ p->pa = pa;
+ p->va = -1;
+ p->allocated = alloc;
+ p->next = NULL;
+
+ return p;
+}
+
+void
+freep(Page *p)
+{
+ if (!p)
+ return;
+
+ if (p->allocated)
+ freeb(VMEM(p->pa));
+
+ lock(&pagepool.m);
+ p->next = pagepool.list;
+ pagepool.list = p;
+ unlock(&pagepool.m);
+}
+
+Chan *
+allocchan(void)
+{
+ Chan *c;
+
+ lock(&chanpool.m);
+ if (chanpool.list) {
+ c = chanpool.list;
+ chanpool.list = c->next;
+ } else {
+ if ((c = alloc(sizeof(*c))) == NULL)
+ return NULL;
+ }
+ unlock(&chanpool.m);
+
+ return c;
+}
+
+void
+freechan(Chan *c)
+{
+ if (!c)
+ return;
+
+ lock(&chanpool.m);
+ c->next = chanpool.list;
+ chanpool.list = c;
+ unlock(&chanpool.m);
+}
+
+Mpoint *
+allocmpoint(void)
+{
+ Mpoint *mp;
+
+ lock(&mpointpool.m);
+ if (mpointpool.list) {
+ mp = mpointpool.list;
+ mpointpool.list = mp->next;
+ } else {
+ if ((mp = alloc(sizeof(*mp))) == NULL)
+ return NULL;
+ }
+ unlock(&mpointpool.m);
+
+ return mp;
+}
+
+void
+freempoint(Mpoint *mp)
+{
+ if (!mp)
+ return;
+
+ lock(&mpointpool.m);
+ mp->next = mpointpool.list;
+ mpointpool.list = mp;
+ unlock(&mpointpool.m);
+}
+
+void
+ialloc(void)
+{
+ int i;
+ union bucket *bp, *prev;
+
+ heap = (union bucket *) buffertab;
+
+ prev = NULL;
+ for (i = HEAPSIZ; i < NR_BUFFERS; i++) {
+ bp = (union bucket *) buffertab[i];
+ bp->next = prev;
+ prev = bp;
+ }
+ bufpool.list = bp;
+
+ kprint("%d available buffers: %d heap, %d buffer pool\n",
+ NR_BUFFERS, HEAPSIZ, NR_BUFFERS - HEAPSIZ);
+}
diff --git a/src/os9/arch/arm64/main.c b/src/os9/arch/arm64/main.c
@@ -13,7 +13,7 @@ getch(void)
if (!console)
panic("getch out of sync");
- devread(console, &ch, 1);
+ chanread(console, &ch, 1);
return ch;
}
@@ -58,7 +58,6 @@ imach(void)
void
main(Mach *m)
{
- info();
ifpu();
igic();
isys();
diff --git a/src/os9/arch/arm64/mmu.c b/src/os9/arch/arm64/mmu.c
@@ -261,6 +261,16 @@ vmap(phyaddr_t pa, uintptr_t va, int perm)
return 0;
}
+
+int
+vunmap(phyaddr_t pa, uintptr_t va))
+{
+ /& TODO */
+ return 0;
+}
+
+
+
void
taskmap(void)
{
diff --git a/src/os9/arch/arm64/trap.c b/src/os9/arch/arm64/trap.c
@@ -8,8 +8,30 @@
#include "arch.h"
static void
-svc(int numsvc)
+syscall(Context *ctx)
{
+ int nsys, r;
+ struct syscall *sys;
+ uintmax_t arg1, arg2, arg3, arg4;
+
+ nsys = ctx->r[X0];
+ if (nsys < 0 || nsys >= NR_SYSCALLS) {
+ kprint("trap: %llu: invalid syscall %d number\n",
+ ctx->r[X29], nsys);
+ seterrno(EINVAL);
+ return;
+ }
+
+ arg1 = ctx->r[X1];
+ arg2 = ctx->r[X2];
+ arg3 = ctx->r[X3];
+ arg4 = ctx->r[X4];
+
+ sys = systab[n];
+ if (!sys->fn)
+ panic("null syscall entry");
+ r = (*fn)(sys->narg, arg1, arg2, arg3, arg4);
+ setret(r);
}
void
@@ -17,7 +39,7 @@ trap(Context *ctx)
{
enum ecvals ec;
const char *msg;
- int numsvc;
+ int numsvc, nsyscall;
ec = (ctx->r[ESR] >> 26) & 0x3f;
@@ -29,7 +51,17 @@ trap(Context *ctx)
}
numsvc = ctx->r[ESR] & 0xff;
+ if (numsvc == 0) {
+ syscall(ctx);
+ } else {
+ kprint("trap: %llu: invalid svc %d number\n",
+ ctx->r[X29], numsvc);
+ seterror(EINVAL);
+ setret(-1);
+ }
+
+ ctx->r[X0] = proc->ret;
+ ctx->r[X1] = proc->errno;
- svc(numsvc);
swtch(ctx);
}
diff --git a/src/os9/dev/dev.c b/src/os9/dev/dev.c
@@ -9,7 +9,7 @@
#include "dev.h"
/*
- * Lock policy: TODO: Change the lock policy because it generates problems
+ * Lock policy:
* The channels are locked when accessed from the raw fdset array, which is
* currently done by newchan() and fd2chan().
* The channels are propagated through the functions in a locked state.
@@ -26,84 +26,180 @@ sameqid(Qid q1, Qid q2)
return q1.type == q2.type && q1.vers == q2.vers && q1.path == q2.path;
}
-Chan *
+static Chan *
newchan(unsigned char type)
{
- int i;
- Chan *c = NULL;
- Chan *fdset = proc->fds->fdset;
+ Chan *c, **bp;
+ Fdset *fds = proc->fds;
- for (i = 0; i < NR_CHANS; i++) {
- c = &fdset[i];
- if (!trylock(&c->mutex))
- continue;
- if (c->type == NODEV) {
- c->type = type;
+ lock(&fds->m);
+ for (bp = fds->fdset; bp < &fds->fdset[NR_CHANS]; ++bp) {
+ if (*bp == NULL)
break;
- }
- unlock(&c->mutex);
}
- if (!c)
- errno = ENOMEM;
+ if (bp == &fds->fdset[NR_CHANS])
+ goto err1;
+ if ((c = allocchan()) == NULL)
+ goto err2;
+ memset(c, 0, sizeof(*c));
+ initref(&c->ref);
+ c->type = type;
+
+ lock(&c->mutex);
+ *bp = c;
+ unlock(&fds->m);
+
return c;
+
+err1:
+ seterror(ENOMEM);
+err2:
+ unlock(&fds->m);
+ return NULL;
}
-void
-delchan(Chan *c)
+Nspace *
+newspace(Nspace *from)
{
- c->qid = QID(0, 0, 0);
- c->dev = 0;
- c->offset = 0;
- c->index = 0;
- c->type = NODEV;
- unlock(&c->mutex);
+ int i;
+ Mpoint *mp;
+ Nspace *ns;
+
+ if ((ns = allocspace()) == NULL)
+ return NULL;
+ memset(ns, 0, sizeof(*ns));
+ initref(&ns->ref);
+
+ if (!from)
+ return ns;
+
+ lock(&from->m);
+ for (i = 0; i <NR_MPOINTS; i++) {
+ mp = ns->mpoints[i] = from->mpoints[i];
+ if (mp)
+ incref(&mp->ref);
+ }
+ unlock(&from->m);
+
+ return ns;
}
-static Chan *
-fd2chan(int fd)
+Fdset *
+newfds(Fdset *from)
{
+ int i;
Chan *c;
- Chan *fdset = proc->fds->fdset;
+ Fdset *fds;
- if (fd < 0 || fd >= NR_CHANS)
- goto badfd;
+ if ((fds = allocfds()) == NULL)
+ return NULL;
+ memset(fds, 0, sizeof(*fds));
+ initref(&fds->ref);
- c = &fdset[fd];
- lock(&c->mutex);
- if (c->type == NODEV)
- goto ubadfd;
- return c;
+ if (!from)
+ return fds;
-ubadfd:
+ lock(&from->m);
+ for (i = 0; i < NR_CHANS; ++i) {
+ c = fds->fdset[i] = from->fdset[i];
+ if (c)
+ incref(&c->ref);
+ }
+ unlock(&from->m);
+
+ return fds;
+}
+
+static void
+delchan(Chan *c)
+{
+ Chan **bp;
+ Fdset *fds = proc->fds;
+
+ if (!decref(&c->ref))
+ return;
+
+ lock(&fds->m);
+ for (bp = fds->fdset; bp < &fds->fdset[NR_CHANS]; ++bp) {
+ if (*bp == c)
+ break;
+ }
+ if (bp == &fds->fdset[NR_CHANS])
+ panic("corrupted channel");
+
+ *bp = NULL;
+ unlock(&fds->m);
unlock(&c->mutex);
-badfd:
- errno = EBADF;
- return NULL;
+
+ freechan(c);
}
-static int
-chan2fd(Chan *c)
+static void
+delmpoint(Mpoint *mp)
+{
+ if (!decref(&mp->ref))
+ return;
+ delchan(mp->new);
+ delchan(mp->old);
+ freempoint(mp);
+}
+
+void
+delspace(Nspace *ns)
{
- Chan *fdset = proc->fds->fdset;
+ int i;
+ Mpoint *mp;
+
+ if (!decref(&ns->ref))
+ return;
- return (c == NULL) ? -1 : (c - fdset);
+ for (i = 0; i < NR_MPOINTS; ++i) {
+ mp = ns->mpoints[i];
+ if (!mp)
+ continue;
+ delmpoint(mp);
+ }
+ freespace(ns);
}
-static int
-validmode(int mode)
+void
+delfds(Fdset *fds)
{
- if ((mode & O_READ) && (mode & (O_WRITE | O_RDWR)))
- goto err;
- if ((mode & O_WRITE) && (mode & (O_READ | O_RDWR)))
+ int i;
+ Chan *c;
+
+ if (!decref(&fds->ref))
+ return;
+
+ for (i = 0; i < NR_CHANS; ++i) {
+ c = fds->fdset[i];
+ if (!c)
+ continue;
+ lock(&c->mutex);
+ chanclose(c);
+ }
+ freefds(fds);
+}
+
+static Chan *
+fd2chan(int fd)
+{
+ Chan *c;
+
+ if (fd < 0 || fd >= NR_CHANS)
goto err;
- if ((mode & O_RDWR) && (mode & (O_READ | O_WRITE)))
+
+ c = proc->fds->fdset[fd];
+ if (!c)
goto err;
- return 1;
+ lock(&c->mutex);
+
+ return c;
err:
- errno = EINVAL;
- return 0;
+ seterror(EBADF);
+ return NULL;
}
static char *
@@ -120,7 +216,7 @@ next(char *s, char *elem)
if (*s != '\0') {
while (*t != '/' && *t != '\0') {
if (n == NAMELEN) {
- errno = EINVAL;
+ seterror(EINVAL);
return NULL;
}
elem[n++] = *t++;
@@ -140,7 +236,7 @@ devtype(int c)
for (i = 0, dp = devtab; *dp && (*dp)->id != c; ++dp)
i++;
if (*dp == NULL) {
- errno = ENODEV;
+ seterror(ENODEV);
return -1;
}
return i;
@@ -167,11 +263,15 @@ buf2chan(Chan *c, void *dst, void *src, int nbytes, long len)
static Chan *
mntpoint(int type, Qid qid)
{
+ int i;
Chan *cn;
- struct mpoint *mp;
- struct mpoint *mpoints = proc->ns->mpoints;
+ Mpoint *mp;
+ Nspace *ns = proc->ns;
- for (mp = mpoints; mp < &mpoints[NR_MPOINTS]; mp++) {
+ lock(&ns->m);
+ for (i = 0; i < NR_MPOINTS; ++i) {
+ if ((mp = ns->mpoints[i]) == NULL)
+ continue;
lock(&mp->m);
if ((cn = mp->new) == NULL) {
unlock(&mp->m);
@@ -179,10 +279,12 @@ mntpoint(int type, Qid qid)
}
if (cn->type == type && sameqid(cn->qid, qid)) {
unlock(&mp->m);
+ unlock(&ns->m);
return mp->old;
}
unlock(&mp->m);
}
+ unlock(&ns->m);
return NULL;
}
@@ -263,7 +365,7 @@ namec(char *name, int mode)
return c;
noent:
- errno = ENOENT;
+ seterror(ENOENT);
err:
if (c)
delchan(c);
@@ -304,7 +406,7 @@ devwalk(Chan *c, char *name, Dirtab *tab, int ntab, Devgen *gen)
case 0:
continue;
case -1:
- errno = ENOENT;
+ seterror(ENOENT);
return -1;
case 1:
if (strcmp(name, dir.name))
@@ -336,7 +438,7 @@ dirread(Chan *c,
c->offset += DIRLEN;
n = dirtop9(&dir, buf + cnt, nbytes);
if (n < 0) {
- errno = EINVAL;
+ seterror(EINVAL);
return (cnt > 0) ? cnt : -1;
}
nbytes -= n;
@@ -374,26 +476,10 @@ devgen(Chan *c, Dirtab *tab, int ntab, int n, Dir *dir)
return 1;
}
-Chan *
-devopen(char *fname, int mode)
-{
- if (!validmode(mode))
- return NULL;
- return namec(fname, mode);
-}
-
int
-open(char *fname, int mode)
+chanclose(Chan *c)
{
- int r;
- Chan *c;
-
- if ((c = devopen(fname, mode)) == NULL)
- return -1;
- r = chan2fd(c);
- unlock(&c->mutex);
-
- return r;
+ return devtab[c->type]->close(c);
}
int
@@ -410,7 +496,7 @@ close(int fd)
if ((c = fd2chan(fd)) == NULL)
return -1;
- return devclose(c);
+ return chanclose(c);
}
int
@@ -429,7 +515,7 @@ devstat(Chan *dirc, char *file,
for (i = 0; ; i++) {
switch ((*gen)(dirc, tab, ntab, i, &dir)) {
case 0:
- errno = ENOENT;
+ seterror(ENOENT);
case -1:
r = -1;
goto leave;
@@ -460,13 +546,13 @@ stat(char *path, void *buf, int n)
char *p, dirname[PATHLEN];
if (n < DIRLEN) {
- errno = EINVAL;
+ seterror(EINVAL);
return -1;
}
len = strlen(path);
if (len + 1 > sizeof(dirname)) {
- errno = ENAMETOOLONG;
+ seterror(ENAMETOOLONG);
return -1;
}
memcpy(dirname, path, len);
@@ -477,7 +563,7 @@ stat(char *path, void *buf, int n)
p = memrchr(dirname, '/', p - dirname);
if (!p) {
- errno = ENOENT;
+ seterror(ENOENT);
return -1;
}
dirname[p - dirname + 1] = '\0';
@@ -492,13 +578,13 @@ stat(char *path, void *buf, int n)
}
int
-devread(Chan *c, void *buf, int n)
+chanread(Chan *c, void *buf, int n)
{
int r = -1;
if (c->qid.type == CHDIR && n < DIRLEN) {
r = -1;
- errno = EINVAL;
+ seterror(EINVAL);
} else {
r = devtab[c->type]->read(c, buf, n);
}
@@ -514,20 +600,20 @@ read(int fd, void *buf, int n)
if ((c = fd2chan(fd)) == NULL)
return -1;
- r = devread(c, buf, n);
+ r = chanread(c, buf, n);
unlock(&c->mutex);
return r;
}
int
-devwrite(Chan *c, void *buf, int n)
+chanwrite(Chan *c, void *buf, int n)
{
int r = -1;
if (c->qid.type == CHDIR) {
r = -1;
- errno = EISDIR;
+ seterror(EISDIR);
} else {
r = devtab[c->type]->write(c, buf, n);
}
@@ -543,7 +629,7 @@ write(int fd, void *buf, int n)
if ((c = fd2chan(fd)) == NULL)
return -1;
- r = devwrite(c, buf, n);
+ r = chanwrite(c, buf, n);
unlock(&c->mutex);
return r;
@@ -559,7 +645,7 @@ seek(int fd, long off, int whence)
return -1;
if (c->qid.type == CHDIR)
- errno = EISDIR;
+ seterror(EISDIR);
else
r = devtab[c->type]->seek(c, off, whence);
@@ -577,7 +663,7 @@ fsync(int fd)
return -1;
if (c->qid.type == CHDIR)
- errno = EISDIR;
+ seterror(EISDIR);
else
r = devtab[c->type]->sync(c, SYNCDEV);
@@ -601,20 +687,20 @@ sync(void)
Chan *
deverrmount(Chan *c, char *spec)
{
- errno = EINVAL;
+ seterror(EINVAL);
return NULL;
}
int
deverrwrite(Chan *c, void *buf, int n)
{
- errno = EINVAL;
+ seterror(EINVAL);
return -1;
}
int deverrseek(Chan *c, long off, int whence)
{
- errno = EINVAL;
+ seterror(EINVAL);
return -1;
}
@@ -647,39 +733,40 @@ addmntpoint(Chan *c, char *new)
{
int i;
Chan *cn;
- struct mpoint *mp;
- struct mpoint *mpoints = proc->ns->mpoints;
+ Mpoint *mp;
+ Nspace *ns = proc->ns;
+
+ if ((mp = allocmpoint()) == NULL)
+ return -1;
if ((cn = namec(new, O_READ)) == NULL)
goto err0;
if (cn->qid.type != CHDIR) {
- errno = ENOTDIR;
+ seterror(ENOTDIR);
goto err1;
}
- for (i = NR_MPOINTS-1; i >= 0; i--) {
- mp = &mpoints[i];
- lock(&mp->m);
- if (!mp->new)
- break;
- unlock(&mp->m);
- }
-
- if (i < 0) {
- errno = ENOMEM;
- goto err1;
- }
+ lock(&ns->m);
+ for (i = NR_MPOINTS-1; i >= 0 && ns->mpoints[i]; i--)
+ ;
+ if (i < 0)
+ goto err2;
+ ns->mpoints[i] = mp;
mp->new = cn;
mp->old = c;
- unlock(&mp->m);
+ unlock(&ns->m);
return 0;
+err2:
+ seterror(ENOMEM);
+ unlock(&ns->m);
err1:
delchan(cn);
err0:
+ delmpoint(mp);
return -1;
}
@@ -729,10 +816,6 @@ void
idev(void)
{
Chan *c;
- Chan *fdset = proc->fds->fdset;
-
- for (c = fdset; c < &fdset[NR_CHANS]; c++)
- c->type = NODEV;
if ((c = attach('/', 0)) == NULL)
panic("idev:attach");
diff --git a/src/os9/dev/dev.h b/src/os9/dev/dev.h
@@ -1,7 +1,6 @@
#include <stddef.h>
#define NR_FILES 20
-#define NODEV 255
#define CHDIR 0x80
#define CHFILE 0x00
@@ -29,9 +28,10 @@ struct dev {
int (*write)(Chan *c, void *buf, int n);
int (*seek)(Chan *c, long off, int whence);
int (*sync)(Chan *c, int what);
+ int (*close)(Chan *c);
Chan *(*clone)(Chan *c, Chan *nc);
Chan *(*attach)(int id, int dev);
- Chan *(*mount)(Chan *c, char *spec);
+ Chan *(*mount)(Chan *c, char *spec);
};
struct attr {
@@ -40,11 +40,8 @@ struct attr {
};
extern int sameqid(Qid q1, Qid qid2);
-extern Chan *namec(char *name, int mode);
extern Chan *clone(Chan *c, Chan *nc);
extern Chan *attach(int id, int dev);
-extern Chan *newchan(unsigned char type);
-extern void delchan(Chan *c);
extern int buf2chan(Chan *c,
void *dst, void *src,
int nbytes, long len);
@@ -53,6 +50,7 @@ extern void mkentry(Chan *c, Dir *dir,
long length, Qid qid, unsigned mode);
extern void devlink(void);
+extern int devclose(Chan *);
extern Chan *devattach(int id, int dev);
extern int devseek(Chan *c, long off, int whence);
extern int devsync(Chan *c, int what);
diff --git a/src/os9/dev/devar.c b/src/os9/dev/devar.c
@@ -44,7 +44,7 @@ gethdr(Chan *c, struct ar_hdr *hdr)
return n;
if (n != sizeof(*hdr) || strncmp(hdr->ar_fmag, ARFMAG, 2) != 0) {
- errno = EINVAL;
+ seterror(EINVAL);
return -1;
}
@@ -83,7 +83,7 @@ argen(Chan *c, Dirtab *tab, int ntab, int n, Dir *dir)
}
if ((len = strlen(hdr.ar_name)) >= NAMELEN) {
- errno = ENAMETOOLONG;
+ seterror(ENAMETOOLONG);
return -1;
}
@@ -133,7 +133,7 @@ arread(Chan *c, void *buf, int n)
return 0;
if (n < 0) {
- errno = EINVAL;
+ seterror(EINVAL);
return -1;
}
if (n > size - c->offset)
@@ -161,7 +161,7 @@ armount(Chan *c, char *spec)
struct arfile *ar;
if (nars == NR_ARS) {
- errno = ENOMEM;
+ seterror(ENOMEM);
return NULL;
}
ar = &archives[nars];
@@ -177,7 +177,7 @@ armount(Chan *c, char *spec)
if (r < 0)
goto err;
if (r != SARMAG || strncmp(buf, ARMAG, SARMAG)) {
- errno = EINVAL;
+ seterror(EINVAL);
goto err;
}
@@ -201,10 +201,10 @@ armount(Chan *c, char *spec)
break;
}
}
- errno = ENOMEM;
+ seterror(ENOMEM);
err:
- delchan(cspec);
+ chanclose(cspec);
return NULL;
}
@@ -219,4 +219,5 @@ Dev ardevtab = {
.mount = armount,
.seek = devseek,
.sync = devsync,
+ .close = devclose,
};
diff --git a/src/os9/dev/devblk.c b/src/os9/dev/devblk.c
@@ -75,7 +75,7 @@ repeat:
if (bp->flags & BDIRTY) {
dev = blks[bp->devno];
if (dev->phy->bwrite(dev, bp->block, bp->ptr) < 0) {
- errno = EIO;
+ seterror(EIO);
bp->flags |= BERROR;
goto return_buffer;
}
@@ -118,7 +118,7 @@ brelse(Buffer *bp)
if ((bp->flags & BDIRTY) != 0) {
dev = blks[bp->devno];
if (dev->phy->bwrite(dev, bp->block, bp->ptr) < 0) {
- errno = EIO;
+ seterror(EIO);
bp->flags |= BERROR;
r = -1;
}
@@ -194,7 +194,7 @@ rawwrite(Chan *c, void *buf, int nbytes)
bp = getblk(c->dev, blk);
switch (bp->flags & (BVALID | BERROR)) {
case 0:
- errno = EFBIG;
+ seterror(EFBIG);
case BVALID|BERROR:
case BERROR:
brelse(bp);
@@ -242,7 +242,7 @@ blksync(Chan *c, int what)
dev = blks[bp->devno];
if (dev->phy->bwrite(dev, bp->block, bp->ptr) < 0) {
r = -1;
- errno = EIO;
+ seterror(EIO);
bp->flags |= BERROR;
} else {
bp->flags &= BDIRTY;
@@ -296,4 +296,5 @@ Dev blkdevtab = {
.mount = deverrmount,
.seek = devseek,
.sync = blksync,
+ .close = devclose,
};
diff --git a/src/os9/dev/devcons.c b/src/os9/dev/devcons.c
@@ -96,7 +96,7 @@ flushraw(char *buf, int n)
if (w < 0) {
r = -1;
} else if (w != n) {
- errno = EIO;
+ seterror(EIO);
r = -1;
}
}
@@ -135,7 +135,7 @@ static int
consaddin(struct conscmd *cmd, char *s)
{
if (in) {
- errno = ENOMEM;
+ seterror(ENOMEM);
return -1;
}
@@ -156,7 +156,7 @@ consaddout(struct conscmd *cmd, char *s)
return 0;
}
}
- errno = ENOMEM;
+ seterror(ENOMEM);
return -1;
}
@@ -164,11 +164,11 @@ static int
consdelin(struct conscmd *cmd, char *s)
{
if (!in || strcmp(s, inname)) {
- errno = ENOENT;
+ seterror(ENOENT);
return -1;
}
- delchan(in);
+ chanclose(in);
in = NULL;
inname[0] = '\0';
return 0;
@@ -181,13 +181,13 @@ consdelout(struct conscmd *cmd, char *s)
for (i = 0; i < CONSOUT; i++) {
if (out[i] && !strcmp(s, outname[i])) {
- delchan(out[i]);
+ chanclose(out[i]);
out[i] = NULL;
outname[i][0] = '\0';
return 0;
}
}
- errno = ENOENT;
+ seterror(ENOENT);
return -1;
}
@@ -201,7 +201,7 @@ consmode(struct conscmd *cmd, char *s)
} else if(!strcmp(s, "off")) {
mode = 0;
} else {
- errno = EINVAL;
+ seterror(EINVAL);
return -1;
}
@@ -210,7 +210,7 @@ consmode(struct conscmd *cmd, char *s)
} else if (!strcmp(cmd->name, "echo")) {
echof = mode;
} else {
- errno = EINVAL;
+ seterror(EINVAL);
return -1;
}
@@ -228,7 +228,7 @@ conswrite(Chan *c, void *buf, int n)
return conswriteraw(buf, n);
case Qctl:
if (tokenize(buf, n, tokens, 2) != 2) {
- errno = EINVAL;
+ seterror(EINVAL);
return -1;
}
@@ -237,7 +237,7 @@ conswrite(Chan *c, void *buf, int n)
return (*cmd->fn)(cmd, tokens[1]);
}
- errno = EINVAL;
+ seterror(EINVAL);
return -1;
default:
panic("conswrite");
@@ -342,7 +342,7 @@ fillbuffer(void)
break;
}
if (ch == EOF && head == 0) {
- errno = EIO;
+ seterror(EIO);
return -1;
}
@@ -374,7 +374,7 @@ consread(Chan *c, void *buf, int n)
return dirread(c, buf, n, dirtab, NELEM(dirtab), devgen);
case Qraw:
if (!in) {
- errno = ENOENT;
+ seterror(ENOENT);
return -1;
}
if (head == 0) {
@@ -410,4 +410,5 @@ Dev consdevtab = {
.write = conswrite,
.seek = deverrseek,
.sync = devsync,
+ .close = devclose,
};
diff --git a/src/os9/dev/devfip.c b/src/os9/dev/devfip.c
@@ -53,7 +53,7 @@ getntry(Chan *c, struct fipntry *ntry)
return n;
if (n != sizeof(buf)) {
- errno = EINVAL;
+ seterror(EINVAL);
return -1;
}
@@ -73,7 +73,7 @@ getntry(Chan *c, struct fipntry *ntry)
LLONG(ntry->flags, buf, n, sizeof(buf));
if (ntry->size > LONG_MAX || ntry->offset_address > LONG_MAX) {
- errno = EINVAL;
+ seterror(EINVAL);
return -1;
}
@@ -221,7 +221,7 @@ fipread(Chan *c, void *buf, int n)
return 0;
if (n < 0) {
- errno = EINVAL;
+ seterror(EINVAL);
return -1;
}
if (n > size - c->offset)
@@ -249,7 +249,7 @@ fipmount(Chan *c, char *spec)
struct fipfile *fip;
if (nfips == NR_FIPS) {
- errno = ENOMEM;
+ seterror(ENOMEM);
return NULL;
}
fip = &archives[nfips];
@@ -267,7 +267,7 @@ fipmount(Chan *c, char *spec)
n = 0;
LONG(name, buf, n, sizeof(buf));
if (r != STOC_HEADER_NAME || name != TOC_HEADER_NAME) {
- errno = EINVAL;
+ seterror(EINVAL);
goto err;
}
@@ -286,10 +286,10 @@ fipmount(Chan *c, char *spec)
break;
}
}
- errno = ENOMEM;
+ seterror(ENOMEM);
err:
- delchan(cspec);
+ chanclose(cspec);
return NULL;
}
@@ -304,4 +304,5 @@ Dev fipdevtab = {
.mount = fipmount,
.seek = devseek,
.sync = devsync,
+ .close = devclose,
};
diff --git a/src/os9/dev/devproc.c b/src/os9/dev/devproc.c
@@ -98,6 +98,7 @@ taskattrread(Chan *c, void *buf, int n)
sizeof(tmp),
"pid: %d\n"
"entry: %p\n"
+ "errno: %d\n"
"stack size: %zd\n"
"base prio: %d\n"
"period: %ld\n"
@@ -105,6 +106,7 @@ taskattrread(Chan *c, void *buf, int n)
"deadline: %ld\n",
tp->pid,
tp->entry,
+ tp->errno,
tp->stack,
tp->prio,
tp->period,
@@ -188,4 +190,5 @@ Dev procdevtab = {
.mount = deverrmount,
.seek = devseek,
.sync = devsync,
+ .close = devclose,
};
diff --git a/src/os9/dev/devroot.c b/src/os9/dev/devroot.c
@@ -123,4 +123,5 @@ Dev rootdevtab = {
.mount = deverrmount,
.seek = devseek,
.sync = devsync,
+ .close = devclose,
};
diff --git a/src/os9/dev/devuart.c b/src/os9/dev/devuart.c
@@ -259,4 +259,5 @@ Dev uartdevtab = {
.mount = deverrmount,
.seek = deverrseek,
.sync = devsync,
+ .close = devclose,
};
diff --git a/src/os9/dlang.c b/src/os9/dlang.c
@@ -89,12 +89,12 @@ do_read(const struct cmd *cmd, struct args *args)
Chan *c;
char buf[100], *bp;
- if ((c = devopen(args->argv[1], O_READ)) == NULL)
+ if ((c = namec(args->argv[1], O_READ)) == NULL)
goto err;
ch = -1;
kprint(PREFIX2);
- while ((n = devread(c, buf, sizeof(buf))) > 0) {
+ while ((n = chanread(c, buf, sizeof(buf))) > 0) {
for (bp = buf; bp < &buf[n]; bp++) {
if (ch == '\n')
kprint(PREFIX2);
@@ -105,7 +105,7 @@ do_read(const struct cmd *cmd, struct args *args)
if (ch != '\n')
kprint("\n");
- if (devclose(c) < 0 || n < 0)
+ if (chanclose(c) < 0 || n < 0)
goto err;
return 0;
@@ -123,16 +123,16 @@ do_ls(const struct cmd *cmd, struct args *args)
Dir dentry;
unsigned char buf[DIRLEN];
- if ((c = devopen(args->argv[1], O_READ)) == NULL)
+ if ((c = namec(args->argv[1], O_READ)) == NULL)
goto err;
- while ((n = devread(c, buf, DIRLEN)) > 0) {
+ while ((n = chanread(c, buf, DIRLEN)) > 0) {
if (p9todir(&dentry, buf, n) < 0)
goto err;
kprint(PREFIX2 "%s\n", dentry.name);
}
- if (devclose(c) || n < 0)
+ if (chanclose(c) || n < 0)
goto err;
return 0;
@@ -149,7 +149,7 @@ do_write(const struct cmd *cmd, struct args *args)
Chan *c;
char *s, buffer[LINELEN];
- if ((c = devopen(args->argv[1], O_WRITE)) == NULL)
+ if ((c = namec(args->argv[1], O_WRITE)) == NULL)
goto err;
offset = 0;
@@ -163,9 +163,9 @@ do_write(const struct cmd *cmd, struct args *args)
buffer[offset++] = ' ';
}
buffer[offset] = '\n';
- n = devwrite(c, buffer, offset);
+ n = chanwrite(c, buffer, offset);
- if (devclose(c) < 0 || n < 0)
+ if (chanclose(c) < 0 || n < 0)
goto err;
return 0;
diff --git a/src/os9/hosted/arch.c b/src/os9/hosted/arch.c
@@ -11,6 +11,13 @@ jmp_buf recover;
noreturn void abort(void);
noreturn void longjmp(jmp_buf env, int val);
+char bufto[PAGESIZE], buffrom[PAGESIZE];
+
+void
+barrier(int what)
+{
+}
+
void
halt(void)
{
diff --git a/src/os9/hosted/lock.c b/src/os9/hosted/lock.c
@@ -1,6 +1,18 @@
#include <os9/os9.h>
void
+unlockspin(spinlock_t *s)
+{
+ unlock(s);
+}
+
+void
+lockspin(spinlock_t *s)
+{
+ lock(s);
+}
+
+void
lock(mutex_t *mutex)
{
if (!mutex)
diff --git a/src/os9/hosted/main.c b/src/os9/hosted/main.c
@@ -19,7 +19,7 @@ getch(void)
char ch;
if (console) {
- devread(console, &ch, 1);
+ chanread(console, &ch, 1);
} else {
_read(0, &ch, 1);
}
@@ -33,7 +33,7 @@ putch(int c)
char ch = c;
if (console) {
- devwrite(console, &ch, 1);
+ chanwrite(console, &ch, 1);
} else {
_write(1, &ch, 1);
}
@@ -56,7 +56,6 @@ imach(void)
int
main(int argc, char *argv[])
{
- info();
imach();
isys();
diff --git a/src/os9/hosted/mmu.c b/src/os9/hosted/mmu.c
@@ -1,8 +1,18 @@
#include <os9/os9.h>
+#include <libk.h>
+
int
vmap(phyaddr_t pa, uintptr_t va, int flags)
{
+ dbg("vmap %llx -> %llx\n", (long long) pa, (long long) va);
+ return 0;
+}
+
+int
+vunmap(phyaddr_t pa, uintptr_t va)
+{
+ dbg("vunmap %llx -> %llx\n", (long long) pa, (long long) va);
return 0;
}
diff --git a/src/os9/map.c b/src/os9/map.c
@@ -0,0 +1,151 @@
+#include <os9/os9.h>
+
+#include <libk.h>
+
+#include <string.h>
+
+Map *
+newstack(Task *tp)
+{
+ Map *mp = &tp->stack;
+
+ initref(&mp->ref);
+ mp->name = "stack";
+ mp->perm = MW | MR;
+
+ mp->pa = -1;
+ mp->va = STACKADDR & (STACKADDR-1);
+ mp->siz = PAGESIZE;
+
+ if (mapseg(mp) < 0)
+ return NULL;
+
+ return mp;
+}
+
+Map *
+newkstack(Task *tp)
+{
+ Map *mp = &tp->kstack;
+
+ initref(&mp->ref);
+ mp->name = "kstack";
+ mp->perm = MW | MR;
+
+ mp->pa = -1;
+ mp->va = KSTACKADDR & (STACKADDR-1);
+ mp->siz = PAGESIZE;
+
+ if (mapseg(mp) < 0)
+ return NULL;
+
+ return mp;
+}
+
+int
+unmapseg(Map *mp)
+{
+ Page *p;
+
+ dbg("unmap %s: %llx -> %llx\n",
+ (mp->name) ? mp->name : "unnamed",
+ mp->va, mp->pa);
+
+ for (p = mp->pages; p; p = p->next) {
+ vunmap(p->pa, p->va);
+ freep(p);
+ }
+
+ mp->pages = NULL;
+
+ return 0;
+}
+
+int
+mapseg(Map *mp)
+{
+ phyaddr_t pa;
+ uintptr_t va;
+ unsigned long i, n;
+ Page *p;
+
+ assert(mp->perm & MR);
+
+ dbg("map %s: %llx -> %llx %c %c%c%c (%llu)\n",
+ (mp->name) ? mp->name : "unnamed",
+ mp->va, mp->pa,
+ (mp->perm & MD) ? 'd' : 'n',
+ (mp->perm & MR) ? 'r' : '-',
+ (mp->perm & MW) ? 'w' : '-',
+ (mp->perm & MX) ? 'x' : '-',
+ mp->siz);
+
+ n = (mp->siz + PAGESIZE-1)/PAGESIZE;
+ va = mp->va;
+ pa = mp->pa;
+
+ for (i = 0; i < n; i++) {
+ if (mp->pa == -1)
+ pa = -1;
+
+ if ((p = allocp(pa)) == NULL)
+ goto err;
+ p->va = va;
+ p->next = mp->pages;
+
+ if (vmap(p->pa, va, mp->perm) < 0) {
+ freep(p);
+ goto err;
+ }
+
+ mp->pages = p;
+ pa += PAGESIZE;
+ va += PAGESIZE;
+ }
+
+ return 0;
+
+err:
+ unmapseg(mp);
+ return -1;
+}
+
+void
+delmap(Map *mp)
+{
+ if (!decref(&mp->ref))
+ return;
+ unmapseg(mp);
+ freemap(mp);
+}
+
+Map *
+newmap(Map *from)
+{
+ Map *mp;
+ Page *pfrom, *pto;
+
+ if ((mp = allocmap()) == NULL)
+ return NULL;
+
+ *mp = *from;
+ mp->pages = NULL;
+ mp->next = NULL;
+ initref(&mp->ref);
+ mapseg(mp);
+
+ pto = mp->pages;
+ for (pfrom = from->pages; pfrom; pfrom = pfrom->next) {
+ assert(pfrom->va == pto->va);
+
+ vmap(pto->pa, (uintptr_t) bufto, MW);
+ vmap(pfrom->pa, (uintptr_t) buffrom, MR);
+
+ memcpy(bufto, buffrom, PAGESIZE);
+ barrier(DATA);
+
+ pto = pto->next;
+ }
+
+ return mp;
+}
diff --git a/src/os9/mkver b/src/os9/mkver
@@ -1,9 +1,16 @@
#!/bin/sh
-set -e
trap 'rm -f $$.tmp' EXIT HUP INT QUIT TERM
-git show-ref HEAD |
-awk '{printf("#define OS9VERSION \"%s\"\n",
- substr($1, 1, 8))
-}' > $$.tmp && mv $$.tmp version.h
+git=`git show-ref --head | awk '$2 == "HEAD" {print substr($1, 1, 8)}'`
+ver=`sed -n '/OS9VERSION/ s/.*"\(.*\)"/\1/p' version.h 2>/dev/null`
+
+if test "$ver" = "$git"
+then
+ exit
+fi
+
+rm -f version.h
+
+echo '#define OS9VERSION "'$git'"' > $$.tmp &&
+mv $$.tmp version.h
diff --git a/src/os9/proc.c b/src/os9/proc.c
@@ -6,7 +6,6 @@
#include <libk.h>
static Task tasktab[NR_TASKS];
-static mutex_t procm;
/* per cpu globals */
Task *proc;
@@ -14,33 +13,6 @@ long long now;
int cpuid;
void
-initref(Ref *rp)
-{
- rp->m = 0;
- rp->cnt = 1;
-}
-
-void
-incref(Ref *rp)
-{
- lock(&rp->m);
- rp->cnt++;
- unlock(&rp->m);
-}
-
-int
-decref(Ref *rp)
-{
- int r;
-
- lock(&rp->m);
- r = --rp->cnt == 0;
- unlock(&rp->m);
-
- return r;
-}
-
-void
locktask(Task *tp)
{
if (tp != proc)
@@ -60,7 +32,7 @@ getntask(int n, Task **tpp)
Task *tp;
if (n >= NR_TASKS) {
- errno = EINVAL;
+ seterror(EINVAL);
return -1;
}
tp = &tasktab[n];
@@ -81,7 +53,6 @@ gettask(int pid)
Task *tp, *p;
tp = NULL;
- lock(&procm);
for (p = tasktab; p < &tasktab[NR_TASKS]; ++p) {
locktask(p);
if (p->pid == pid && p->state != TFREE) {
@@ -90,106 +61,24 @@ gettask(int pid)
}
unlocktask(p);
}
- unlock(&procm);
return tp;
}
-int
-mapseg(Map *mp)
-{
- phyaddr_t pa;
- uintptr_t va;
- void *bp;
- unsigned long i, n;
-
- assert(mp->perm & MR);
-
- dbg("map %s: %llx -> %llx %c %c%c%c (%llu)\n",
- (mp->name) ? mp->name : "unnamed",
- mp->va, mp->pa,
- (mp->perm & MD) ? 'd' : 'n',
- (mp->perm & MR) ? 'r' : '-',
- (mp->perm & MW) ? 'w' : '-',
- (mp->perm & MX) ? 'x' : '-',
- mp->siz);
-
- bp = NULL;
- n = (mp->siz + PAGESIZE-1)/PAGESIZE;
- va = mp->va;
- pa = mp->pa;
- if (pa == -1) {
- if ((bp = allocb(n)) == NULL)
- return -1;
- pa = (phyaddr_t) PMEM(bp);
- }
-
- for (i = 0; i < n; i++) {
- if (vmap(pa, va, mp->perm) < 0) {
- freeb(bp);
- return -1;
- }
- pa += PAGESIZE;
- va += PAGESIZE;
- }
-
- return 0;
-}
-
-Map *
-newstack(Task *tp)
-{
- Map *mp = &tp->stack;
-
- initref(&mp->ref);
- mp->name = "stack";
- mp->perm = MW | MR;
-
- mp->pa = -1;
- mp->va = STACKADDR & (STACKADDR-1);
- mp->siz = PAGESIZE;
-
- if (mapseg(mp) < 0)
- return NULL;
-
- return mp;
-}
-
-Map *
-newkstack(Task *tp)
-{
- Map *mp = &tp->kstack;
-
- initref(&mp->ref);
- mp->name = "kstack";
- mp->perm = MW | MR;
-
- mp->pa = -1;
- mp->va = KSTACKADDR & (STACKADDR-1);
- mp->siz = PAGESIZE;
-
- if (mapseg(mp) < 0)
- return NULL;
-
- return mp;
-}
-
static Task *
newslot(void)
{
Task *tp;
- lock(&procm);
for (tp = tasktab; tp < &tasktab[NR_TASKS]; tp++) {
locktask(tp);
if (tp->state == TFREE)
break;
unlocktask(tp);
}
- unlock(&procm);
if (tp == &tasktab[NR_TASKS]) {
- errno = ENOMEM;
+ seterror(ENOMEM);
return NULL;
}
@@ -201,7 +90,7 @@ newtask(void)
{
int pid;
Task *tp;
- static int last;
+ static int last = -1;
static mutex_t m;
assert(NR_TASKS < MAXTID);
@@ -212,7 +101,7 @@ newtask(void)
for (;;) {
if (pid == MAXTID)
- pid = 0;
+ pid = -1;
pid++;
if (pid == last)
goto err;
@@ -236,75 +125,22 @@ newtask(void)
return tp;
err:
unlock(&m);
- errno = ENOMEM;
+ seterror(ENOMEM);
return NULL;
}
-static Nspace *
-newspace(Nspace *from)
-{
- Nspace *ns;
-
- if ((ns = alloc(sizeof(*ns))) == NULL)
- return NULL;
-
- *ns = (from) ? *from : (Nspace) {0};
- initref(&ns->ref);
-
- return ns;
-}
-
-static Fdset *
-newfds(Fdset *from)
-{
- Fdset *fds;
-
- if ((fds = alloc(sizeof(*fds))) == NULL)
- return NULL;
-
- *fds = (from) ? *from : (Fdset) {0};
- initref(&fds->ref);
-
- return fds;
-}
-
-static Map *
-newmap(Map *from)
-{
- Map *mp;
-
- if ((mp = alloc(sizeof(*mp))) == NULL)
- return NULL;
-
- *mp = *from;
- initref(&mp->ref);
- mapseg(mp); /* FIXME: we have to duplicate the pages */
-
- return mp;
-}
-
-static void
-freespace(Nspace *ns)
-{
- /* TODO */
-}
-
-static void
-freefds(Fdset *fds)
-{
- /* TODO */
-}
-
-static void
-freemap(Map *mp)
-{
- /* TODO */
-}
-
+/*
+ * tp must be blocked when this function is called
+ */
static void
deltask(Task *tp)
{
+ delmap(tp->text);
+ delmap(tp->data);
+ delspace(tp->ns);
+ delfds(tp->fds);
+ unlocktask(tp);
}
static Task *
@@ -342,24 +178,23 @@ clone(Task *parent)
tp->text = parent->text;
if (tp->text)
- incref(&parent->text->ref);
+ incref(&tp->text->ref);
tp->data = parent->data;
if (tp->data)
- incref(&parent->data->ref);
+ incref(&tp->data->ref);
tp->ns = parent->ns;
if (tp->ns)
- incref(&parent->ns->ref);
+ incref(&tp->ns->ref);
tp->fds = parent->fds;
if (tp->fds)
- incref(&parent->fds->ref);
+ incref(&tp->fds->ref);
return tp;
err:
- unlocktask(tp);
deltask(tp);
return NULL;
}
@@ -367,6 +202,7 @@ err:
int
rfork(int flags)
{
+ int pid;
Task *tp;
Nspace *ns;
Fdset *fds;
@@ -375,7 +211,7 @@ rfork(int flags)
if ((flags & (RFMEM|RFPROC)) == 0
|| (flags & (RFNAMEG|RFCNAMEG)) == (RFNAMEG|RFCNAMEG)
|| (flags & (RFFDG|RFCFDG)) == (RFFDG|RFCFDG)) {
- errno = EINVAL;
+ seterror(EINVAL);
return -1;
}
@@ -416,38 +252,34 @@ rfork(int flags)
}
if (tp->ns != ns) {
- if (decref(&tp->ns->ref))
- freespace(tp->ns);
+ delspace(tp->ns);
tp->ns = ns;
}
if (tp->fds != fds) {
- if (decref(&tp->fds->ref))
- freefds(tp->fds);
+ delfds(tp->fds);
tp->fds = fds;
}
if (tp->data != data) {
- if (decref(&tp->data->ref))
- freemap(tp->data);
+ delmap(tp->data);
tp->data = data;
}
+ pid = tp->pid;
if (flags & RFPROC)
unlocktask(tp);
- return 0;
+ return pid;
err:
if (data)
- freemap(data);
+ delmap(data);
if (fds)
- freefds(fds);
+ delfds(fds);
if (ns)
- freespace(ns);
+ delspace(ns);
- if (flags & RFPROC) {
- unlocktask(tp);
+ if (flags & RFPROC)
deltask(tp);
- }
return -1;
}
@@ -475,10 +307,11 @@ sched(void)
Task *new, *tp;
int prio;
long long wait, mask;
+ static mutex_t m;
if (proc->state == TRUNNING) {
if (proc->flags&TLOCK_PREEMP)
- swtch(&proc->ctx);
+ return;
proc->state = TREADY;
}
unlock(&proc->m);
@@ -489,7 +322,7 @@ repeat:
wait = -1;
mask = 1ul << cpuid;
- lock(&procm);
+ lock(&m);
for (tp = tasktab; tp < &tasktab[NR_TASKS]; ++tp) {
lock(&tp->m);
@@ -506,7 +339,7 @@ repeat:
}
if (!new) {
- unlock(&procm);
+ unlock(&m);
idle();
goto repeat;
}
@@ -514,7 +347,7 @@ repeat:
proc = new;
lock(&proc->m);
proc->state = TRUNNING;
- unlock(&procm);
+ unlock(&m);
swtch(&proc->ctx);
}
@@ -522,7 +355,15 @@ repeat:
static void
initfn(void)
{
- debug();
+ switch (rfork(RFPROC|RFMEM)) {
+ case 0:
+ /* exec("/blobs/init"); */
+ case -1:
+ panic("out of sync");
+ default:
+ debug();
+ break;
+ }
}
static Task *
@@ -532,7 +373,6 @@ inittask(void)
if ((tp = newtask()) == NULL)
return NULL;
- tp->pid = 0;
tp->text = NULL;
tp->data = NULL;
@@ -565,6 +405,51 @@ inittask(void)
}
void
+seterror(int n)
+{
+ proc->errno = n;
+}
+
+/*
+ * sleep() and wakeup() are highly inspired in
+ * the paper 'Process Sleep and Wakeup on a
+ * Shared-memory Multiprocessor'
+ */
+void
+sleep(Rendez *r, int (*cond)(void *), void *arg)
+{
+ lockspin(&r->s);
+
+ if (!(*cond)(arg)) {
+ unlockspin(&r->s);
+ return;
+ }
+
+ proc->state = TWAITING;
+ proc->next = r->task;
+ r->task = proc;
+ unlockspin(&r->s);
+ sched();
+}
+
+void
+wakeup(Rendez *r)
+{
+ Task *tp, *next;
+
+ lockspin(&r->s);
+ for (tp = r->task; tp; tp = next) {
+ if (tp->state != TWAITING)
+ panic("wakeup: not sleeping");
+ next = tp->next;
+ tp->next = NULL;
+ tp->state = TREADY;
+ }
+ r->task = NULL;
+ unlockspin(&r->s);
+}
+
+void
iproc(void)
{
Task *tp;
@@ -577,4 +462,6 @@ iproc(void)
if ((tp = inittask()) == NULL)
panic("init task failed");
proc = tp;
+
+ kprint("%d availabe task slots\n", NR_TASKS);
}
diff --git a/src/os9/ref.c b/src/os9/ref.c
@@ -0,0 +1,28 @@
+#include <os9/os9.h>
+
+void
+initref(Ref *rp)
+{
+ rp->m = 0;
+ rp->cnt = 1;
+}
+
+void
+incref(Ref *rp)
+{
+ lock(&rp->m);
+ rp->cnt++;
+ unlock(&rp->m);
+}
+
+int
+decref(Ref *rp)
+{
+ int r;
+
+ lock(&rp->m);
+ r = --rp->cnt == 0;
+ unlock(&rp->m);
+
+ return r;
+}
diff --git a/src/os9/sys.c b/src/os9/sys.c
@@ -12,7 +12,7 @@ Chan *console;
static void
icons(void)
{
- if ((console = devopen("#c/raw", O_RDWR)) == NULL)
+ if ((console = namec("#c/raw", O_RDWR)) == NULL)
panic("icons:#c/raw open");
}
@@ -29,11 +29,11 @@ writeline(char *line)
*p++ = '\0';
data = p;
- if ((c = devopen(file, O_WRITE)) < 0)
+ if ((c = namec(file, O_WRITE)) < 0)
panic("writeline:open");
- if (devwrite(c, data, strlen(data)) < 0)
+ if (chanwrite(c, data, strlen(data)) < 0)
panic("writeline:write");
- devclose(c);
+ chanclose(c);
}
static void
@@ -68,8 +68,17 @@ iconf(void)
int n;
Chan *c;
char line[80], *s, *p;
-
- if ((c = devopen("/blobs/conf", O_READ)) == NULL) {
+ static struct {
+ char *verb;
+ void (*fn)(char *);
+ } words[] = {
+ "write", writeline,
+ "bind", bindline,
+ "mount", mountline,
+ NULL
+ }, *bp;
+
+ if ((c = namec("/blobs/conf", O_READ)) == NULL) {
kprint("missed kernel namespace configuration\n");
return;
}
@@ -87,24 +96,24 @@ iconf(void)
while (isspace(*p))
*p++ = '\0';
- if (strcmp(s, "write") == 0) {
- writeline(p);
- } else if (strcmp(s, "bind") == 0) {
- bindline(p);
- } else if (strcmp(s, "mount") == 0) {
- mountline(p);
- } else {
- kprint("iconf: incorrect verb '%s'\n", s);
- continue;
+ for (bp = words; bp->verb; ++bp) {
+ if (strcmp(s, bp->verb) == 0) {
+ (*bp->fn)(p);
+ break;
+ }
}
+
+ if (!bp->verb)
+ kprint("iconf: incorrect verb '%s'\n", s);
}
+
if (n < 0)
kprint("iconf: error reading configuration:%r\n");
- devclose(c);
+ chanclose(c);
}
-void
+static void
info(void)
{
kprint("Booting os9\n");
@@ -114,6 +123,8 @@ info(void)
void
isys(void)
{
+ info();
+ ialloc();
iproc();
idev();
iconf();
diff --git a/src/os9/syscall.c b/src/os9/syscall.c
@@ -0,0 +1,86 @@
+#include <os9/os9.h>
+
+#include <stdarg.h>
+#include <errno.h>
+
+#include "version.h"
+
+
+static int
+validmode(int mode)
+{
+ if ((mode & O_READ) && (mode & (O_WRITE | O_RDWR)))
+ goto err;
+ if ((mode & O_WRITE) && (mode & (O_READ | O_RDWR)))
+ goto err;
+ if ((mode & O_RDWR) && (mode & (O_READ | O_WRITE)))
+ goto err;
+ if (mode == 0)
+ goto err;
+ return 1;
+
+err:
+ seterror(EINVAL);
+ return 0;
+}
+
+static int
+newfd(Chan *c, int mode)
+{
+ int fd;
+ Chan **bp;
+ Fdset *fds = proc->fds;
+
+ lock(&fds->m);
+ for (bp = fds->fdset; bp < &fds->fdset[NR_CHANS]; ++bp) {
+ if (*bp == c)
+ break;
+ }
+ if (bp == &fds->fdset[NR_CHANS]) {
+ seterror(EMFILE);
+ unlock(&fds->m);
+ return -1;
+ }
+
+ fd = bp - fds->fdset;
+ fds->fdset[fd] = c;
+ unlock(&fds->m);
+
+ return fd;
+}
+
+static int
+validaddr(void *addr, int len, int write)
+{
+ /* TODO */
+ return 1;
+}
+
+static int
+sysopen(int nargs, ...)
+{
+ char *fname;
+ int mode, flags, fd;
+ va_list va;
+ Chan *c;
+
+ va_start(va, nargs);
+ fname = (char *) va_arg(va, uintptr_t);
+ mode = va_arg(va, uintptr_t);
+ flags = va_arg(va, uintptr_t);
+ va_end(va);
+
+ if (!validmode(mode))
+ return -1;
+ if (!validaddr(fname, 1, 0))
+ return -1;
+ if ((c = namec(fname, mode)) == NULL)
+ return -1;
+ if ((fd = newfd(c, mode)) < 0)
+ return -1;
+ return fd;
+}
+
+struct syscall systab[] = {
+ [SYSOPEN] = 3, sysopen,
+};