9os

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs | README | LICENSE

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:
Minclude/bits/amd64/arch/types.h | 1+
Minclude/bits/arm64/arch/types.h | 1+
Minclude/os9/os9.h | 90++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-----------
Msrc/libk/getline.c | 2+-
Msrc/os9/Makefile | 5++++-
Msrc/os9/alloc.c | 317++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++---------
Msrc/os9/arch/arm64/main.c | 3+--
Msrc/os9/arch/arm64/mmu.c | 10++++++++++
Msrc/os9/arch/arm64/trap.c | 38+++++++++++++++++++++++++++++++++++---
Msrc/os9/dev/dev.c | 307++++++++++++++++++++++++++++++++++++++++++++++++++-----------------------------
Msrc/os9/dev/dev.h | 8+++-----
Msrc/os9/dev/devar.c | 15++++++++-------
Msrc/os9/dev/devblk.c | 9+++++----
Msrc/os9/dev/devcons.c | 27++++++++++++++-------------
Msrc/os9/dev/devfip.c | 15++++++++-------
Msrc/os9/dev/devproc.c | 3+++
Msrc/os9/dev/devroot.c | 1+
Msrc/os9/dev/devuart.c | 1+
Msrc/os9/dlang.c | 18+++++++++---------
Msrc/os9/hosted/arch.c | 7+++++++
Msrc/os9/hosted/lock.c | 12++++++++++++
Msrc/os9/hosted/main.c | 5++---
Msrc/os9/hosted/mmu.c | 10++++++++++
Asrc/os9/map.c | 151++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Msrc/os9/mkver | 17++++++++++++-----
Msrc/os9/proc.c | 291++++++++++++++++++++++++-------------------------------------------------------
Asrc/os9/ref.c | 28++++++++++++++++++++++++++++
Msrc/os9/sys.c | 45++++++++++++++++++++++++++++-----------------
Asrc/os9/syscall.c | 86+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
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, +};