9os

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

commit 1f846556907895e491d5dfeea711b93dc4d38787
parent 11d57f50f23ea8fffe3bdabd37f9ecf8c9e1b3f4
Author: Roberto E. Vargas Caballero <k0ga@shike2.com>
Date:   Sun, 25 Oct 2020 22:47:38 +0100

os9/proc: Add rfork()

Change-Id: I627931dd9348c0d212ca046b87702c30b7f9564f

Diffstat:
Minclude/os9/os9.h | 20+++++++++++++++-----
Msrc/os9/proc.c | 108+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 123 insertions(+), 5 deletions(-)

diff --git a/include/os9/os9.h b/include/os9/os9.h @@ -48,6 +48,15 @@ typedef struct nspace Nspace; typedef struct fdset Fdset; typedef struct ref Ref; +enum rforkflags { + RFPROC = 1 << 0, + RFNAMEG = 1 << 1, + RFCNAMEG = 1 << 2, + RFFDG = 1 << 3, + RFCFDG = 1 << 4, + RFMEM = 1 << 5, +}; + enum barrier_type { CODE, DATA, @@ -98,7 +107,13 @@ enum map_attr { MD = 1 << 3, }; +struct ref { + mutex_t m; + int cnt; +}; + struct map { + Ref ref; char *name; unsigned perm; @@ -144,11 +159,6 @@ struct chan { mutex_t mutex; }; -struct ref { - mutex_t m; - int cnt; -}; - struct mpoint { Chan *new; Chan *old; diff --git a/src/os9/proc.c b/src/os9/proc.c @@ -1,5 +1,6 @@ #include <os9/os9.h> +#include <errno.h> #include <limits.h> struct nspace { @@ -8,6 +9,12 @@ struct nspace { struct mpoint mpoints[NR_MPOINTS]; }; +struct fdset { + Ref ref; + mutex_t m; + Chan fdset[NR_CHANS]; +}; + static Task tasktab[NR_TASKS]; static void @@ -108,3 +115,104 @@ newspace(Nspace *from) return ns; } + +static Fdset * +newfds(Fdset *from) +{ + Fdset *fds; + + fds = alloc(sizeof(*fds)); + if (from) + *fds = *from; + initref(&fds->ref); + + return fds; +} + +static Map * +newmap(Map *from) +{ + Map *mp; + + mp = alloc(sizeof(*mp)); + if (from) + *mp = *from; + initref(&mp->ref); + + return mp; +} + +int +rfork(int flags) +{ + Task *tp, *parent; + int tid; + + tp = parent = task; + + if ((flags & (RFPROC|RFMEM)) == RFPROC|RFMEM + || (flags & (RFNAMEG|RFCNAMEG)) == RFNAMEG|RFCNAMEG + || (flags & (RFFDG|RFCFDG)) == RFFDG|RFCFDG) { + errno = EINVAL; + return -1; + } + + if ((flags & RFPROC) != 0) { + if ((tp = newslot()) == NULL) + return -1; + + for (tp = tasktab; tp < &tasktab[NR_TASKS]; ++tp) { + if (tp->mode == PDISABLED) + break; + } + + if (tp == &tasktab[NR_TASKS] || (tid = newtid()) < 0) { + errno = ENOMEM; + return -1; + } + tp->tid = tid; + + incref(&parent->text->ref); + tp->text = parent->text; + + incref(&parent->data->ref); + tp->data = parent->data; + + incref(&parent->stack->ref); + tp->stack = parent->stack; + + incref(&parent->ns->ref); + tp->ns = parent->ns; + + incref(&parent->fds->ref); + tp->fds = parent->fds; + } + + if ((flags & RFCNAMEG) != 0) { + decref(&tp->ns->ref); + tp->ns = newspace(NULL); + incref(&tp->ns->ref); + } + if ((flags & RFNAMEG) != 0) { + decref(&tp->ns->ref); + tp->ns = newspace(parent->ns); + incref(&tp->ns->ref); + } + if ((flags & RFCFDG) != 0) { + decref(&tp->fds->ref); + tp->fds = newfds(NULL); + incref(&tp->fds->ref); + } + if ((flags & RFFDG) != 0) { + decref(&tp->fds->ref); + tp->fds = newfds(parent->fds); + incref(&tp->fds->ref); + } + if ((flags & RFCFDG) != 0) { + decref(&tp->data->ref); + tp->data = newmap(parent->data); + incref(&tp->data->ref); + } + + return (flags & RFPROC) ? tp->tid : 0; +}