summaryrefslogtreecommitdiff
path: root/src/kernel
diff options
context:
space:
mode:
authordzwdz2022-08-18 14:11:31 +0200
committerdzwdz2022-08-18 14:11:31 +0200
commit0ed2f796d7723af8321f35d4ef5e6781ea41e36d (patch)
treec4b64981d0d2bfddd597eb05e84cd1a781d253e1 /src/kernel
parent7a3f292c8316239182f30fa8f3a5e5a14cca587c (diff)
syscall/fork: FORK_SHAREMEM for primitive "threads"
Diffstat (limited to 'src/kernel')
-rw-r--r--src/kernel/proc.c23
-rw-r--r--src/kernel/proc.h3
2 files changed, 24 insertions, 2 deletions
diff --git a/src/kernel/proc.c b/src/kernel/proc.c
index 2e765c7..906fc29 100644
--- a/src/kernel/proc.c
+++ b/src/kernel/proc.c
@@ -50,7 +50,17 @@ struct process *process_fork(struct process *parent, int flags) {
struct process *child = kmalloc(sizeof *child);
memset(child, 0, sizeof *child);
- child->pages = pagedir_copy(parent->pages);
+ if (flags & FORK_SHAREMEM) {
+ if (!parent->pages_refcount) {
+ parent->pages_refcount = kmalloc(sizeof *parent->pages_refcount);
+ *parent->pages_refcount = 1;
+ }
+ *parent->pages_refcount += 1;
+ child->pages_refcount = parent->pages_refcount;
+ child->pages = parent->pages;
+ } else {
+ child->pages = pagedir_copy(parent->pages);
+ }
child->regs = parent->regs;
child->state = parent->state;
assert(child->state == PS_RUNNING); // not copying the state union
@@ -152,7 +162,16 @@ void process_kill(struct process *p, int ret) {
p->execbuf.buf = NULL;
}
- pagedir_free(p->pages);
+ if (p->pages_refcount) {
+ assert(*p->pages_refcount != 0);
+ *p->pages_refcount -= 1;
+ if (*p->pages_refcount == 0) {
+ kfree(p->pages_refcount);
+ pagedir_free(p->pages);
+ }
+ } else {
+ pagedir_free(p->pages);
+ }
// TODO VULN unbounded recursion
struct process *c2;
diff --git a/src/kernel/proc.h b/src/kernel/proc.h
index 27327c4..e7946b2 100644
--- a/src/kernel/proc.h
+++ b/src/kernel/proc.h
@@ -20,6 +20,9 @@ enum process_state {
struct process {
struct pagedir *pages;
+ /* if NULL, refcount == 1. kmalloc'd */
+ uint64_t *pages_refcount;
+
struct registers regs;
struct process *sibling, *child, *parent;