BarryServer : Git

All the code for all my projects
// BarryServer : Git / Nucleus / commit / 6217f0db2c8f2513994f4cc773aaa4171a049963 / task / clone.c

// Related

Nucleus

Barry Kernel threads + threads share address space 6217f0d (3 years, 1 month ago)
diff --git a/task/clone.c b/task/clone.c
index 377b869..5fdcfef 100644
--- a/task/clone.c
+++ b/task/clone.c
@@ -6,12 +6,39 @@
 #include <sys/sched.h>
 #include <sys/types.h>
 #include <nucleus/io.h>
+#include <nucleus/lib.h>
 #include <nucleus/task.h>
 #include <nucleus/vfs.h>
 
+/* Copy the stack */
+static void
+copy_kernel_stack(Task *parent, Task *child)
+{
+        size_t offset = (size_t) child - (uintptr_t) parent;
+	uintptr_t oldTop = (uintptr_t) parent + KERNEL_STACK_SIZE,
+	          oldStack = child->esp;
+	uintptr_t newTop = (uintptr_t) child + KERNEL_STACK_SIZE,
+	          newStack = child->esp + offset;
+
+	/* Copy contents and change stack */
+	memcpy((void *) newStack, (void *) oldStack,
+	       (size_t) oldTop - oldStack);
+        child->esp += offset;
+        child->ebp += offset;
+
+        /* Update pointers on the stack */
+        uintptr_t i, tmp;
+        for (i = newStack & ~(sizeof(uintptr_t) - 1);
+             i < newTop; i += sizeof(uintptr_t)) {
+                tmp = *(uintptr_t *) i;
+                if (tmp > oldStack && tmp < (uintptr_t) oldTop)
+                        *(uintptr_t *) i = tmp + offset;
+        }
+}
+
 /* Clone a task */
 pid_t
-clone(int flags)
+clone(int flags, void *stack)
 {
 	enter_critical_section();
 
@@ -23,6 +50,21 @@ clone(int flags)
 		flags |= CLONE_VM;
 	}
 
+	/* Copy thread information */
+	if (flags & CLONE_THREAD)
+		child->tgid = parent->tgid;
+	child->uid  = parent->uid;
+	child->euid = parent->euid;
+	child->suid = parent->suid;
+	child->gid  = parent->gid;
+	child->egid = parent->egid;
+	child->sgid = parent->sgid;
+	child->inSyscall = parent->inSyscall;
+
+	/* Get executable file */
+	if (parent->executable)
+		child->executable = get(parent->executable);
+
 	/* Clone parent's file system namespace */
 	if (flags & CLONE_FS)
 		child->fs = get(parent->fs);
@@ -40,9 +82,6 @@ clone(int flags)
 		child->vm = get(parent->vm);
 	else
 		child->vm = copy(parent->vm);
-	/* Copy stack */
-	if (parent->stack)
-		child->stack = copy(parent->stack);
 
 	/* Clone parent's signals namespace */
 	if (flags & CLONE_SIGHAND)
@@ -50,26 +89,23 @@ clone(int flags)
 	else
 		child->signals = copy(parent->signals);
 
-	/* Get executable file */
-	if (parent->executable)
-		child->executable = get(parent->executable);
-
-	child->inSyscall = parent->inSyscall;
-
-	/* After this, anything on the stack is desynchronised */
-	child->pageDir = clone_dir();
-
 	/* Split tasks here */
 	asm volatile("mov %%esi, %0" : "=r" (child->esi));
 	asm volatile("mov %%edi, %0" : "=r" (child->edi));
 	asm volatile("mov %%ebx, %0" : "=r" (child->ebx));
 	asm volatile("mov %%esp, %0" : "=r" (child->esp));
 	asm volatile("mov %%ebp, %0" : "=r" (child->ebp));
+	copy_kernel_stack(parent, child);
 	child->eip = (uintptr_t) &&end;
 	enqueue_task(child);
 	tid = child->tid;
 	put(child);
 	exit_critical_section();
+
 end:
+	if ((flags & CLONE_VM) && current == child) {
+		/* Set the child's user stack */
+		cpu->frame->esp = (uintptr_t) stack;
+	}
 	return tid;
 }