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;
}