diff options
Diffstat (limited to 'src/kernel/proc.c')
-rw-r--r-- | src/kernel/proc.c | 119 |
1 files changed, 114 insertions, 5 deletions
diff --git a/src/kernel/proc.c b/src/kernel/proc.c index 65cbd81..108a006 100644 --- a/src/kernel/proc.c +++ b/src/kernel/proc.c @@ -30,10 +30,12 @@ Proc *proc_seed(void *data, size_t datalen) { proc_first->pages = pagedir_new(); proc_first->mount = vfs_mount_seed(); proc_first->globalid = next_pid++; - proc_first->cid = 1; - proc_first->nextcid = 1; proc_first->_handles = kzalloc(sizeof(Handle) * HANDLE_MAX); + proc_first->pns = proc_first; + proc_first->localid = 1; + proc_first->nextlid = 2; + // map .shared extern char _shared_len; for (size_t p = 0; p < (size_t)&_shared_len; p += PAGE_SIZE) @@ -74,12 +76,18 @@ Proc *proc_fork(Proc *parent, int flags) { child->parent = parent; parent->child = child; - if (parent->nextcid == 0) + if (next_pid == 0) { panic_unimplemented(); - child->cid = parent->nextcid++; - child->nextcid = 1; + } child->globalid = next_pid++; + child->pns = parent->pns; + if (child->pns->nextlid == 0) { + panic_unimplemented(); + } + child->localid = child->pns->nextlid++; + + if ((flags & FORK_NEWFS) == 0 && parent->controlled) { child->controlled = parent->controlled; assert(child->controlled->provhcnt); @@ -110,6 +118,106 @@ Proc *proc_fork(Proc *parent, int flags) { return child; } +bool proc_ns_contains(Proc *ns, Proc *proc) { + /* a namespace contains all the processes with ->ns == ns and all their + * direct children */ + if (ns == proc) return true; + if (proc->parent == NULL) return false; + return proc->parent->pns == ns; +} + +uint32_t proc_ns_id(Proc *ns, Proc *proc) { + if (proc == ns) { + return 1; + } else { + if (proc->pns == proc) { + assert(proc->parent->pns == ns); + } else { + assert(proc->pns == ns); + } + return proc->localid; + } +} + +Proc *proc_ns_byid(Proc *ns, uint32_t id) { + assert(ns->pns == ns); + for (Proc *it = ns; it; it = proc_ns_next(ns, it)) { + if (proc_ns_id(ns, it) == id) { + return it; + } + } + return NULL; +} + +Proc *proc_ns_next(Proc *ns, Proc *p) { + Proc *ret = NULL; + /* see comments in proc_next */ + + if (!p) goto end; + /* descend into children who own their own namespace, but no further */ + if (p->child && proc_ns_contains(ns, p->child)) { + ret = p->child; + goto end; + } + // TODO diverged from proc_next, integrate this fix into it + // also once you do that do regression tests - this behaviour is buggy + if (p == ns) { + /* don't escape the root */ + goto end; + } + while (!p->sibling) { + p = p->parent; + assert(p); + if (p == ns) goto end; + } + ret = p->sibling; + +end: + if (ret != NULL) { + assert(proc_ns_contains(ns, ret)); + } + return ret; +} + +void proc_ns_create(Proc *proc) { + // TODO test this. lots of fucky behaviour can happen here + // TODO document process namespaces + Proc *old = proc->pns; + if (old == proc) return; + proc->pns = proc; + proc->nextlid = 2; + for (Proc *it = proc; it; ) { + if (it != proc) { + if (proc->nextlid < it->localid + 1) { + proc->nextlid = it->localid + 1; + } + if (it->pns == old) { + it->pns = proc; + } else { + assert(it->pns == it); + } + } + + /* analogous to proc_ns_next - which can't be used directly as it gets + * confused by changing namespaces */ + + /* descend into children who own their own namespace, but no further */ + if (it->child && (proc_ns_contains(proc, it->child) || proc_ns_contains(old, it->child))) { + it = it->child; + continue; + } + if (it == proc) { + break; + } + while (!it->sibling) { + it = it->parent; + if (it == proc) break; + assert(it); + } + it = it->sibling; + } +} + /* meant to be used with p->*_refcount */ static bool unref(uint64_t *refcount) { if (!refcount) return true; @@ -394,6 +502,7 @@ Handle *proc_handle_get(Proc *p, hid_t id) { } else if (id == HANDLE_PROCFS) { if (!p->specialh.procfs) { Handle *h = kmalloc(sizeof *h); + proc_ns_create(p); *h = (Handle){ .type = HANDLE_FS_FRONT, .backend = procfs_backend(p), |