BarryServer : Git

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

// 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;
 }
diff --git a/task/exec.c b/task/exec.c
index ff80d21..8134a3d 100644
--- a/task/exec.c
+++ b/task/exec.c
@@ -216,9 +216,6 @@ execve(const char *file, char *argv[], char *envp[])
 	close(fd);
 
 	/* Stack area */
-	if (current->stack)
-		put(current->stack);
-	current->stack = vm_create_stack();
 	memcpy((void *) esp, istack, ssz);
 	kfree(istack);
 
diff --git a/task/kthread.c b/task/kthread.c
new file mode 100644
index 0000000..2c91f5a
--- /dev/null
+++ b/task/kthread.c
@@ -0,0 +1,34 @@
+/*
+ * This file implements kernel threads.  Each kernel thread has a stack
+ * allocated in kernel memory and will run a specified function within the
+ * kernel.  When that function completes, the thread will terminate.  The
+ * thread has no resources allocated and should only access the kernel.
+ */
+
+#include <stddef.h>
+#include <stdint.h>
+#include <nucleus/lib.h>
+#include <nucleus/task.h>
+
+#define PUSH(s,v) ({ \
+	s -= sizeof(uintptr_t); \
+	*(uintptr_t *) s = (uintptr_t) v; \
+})
+
+/* Create a new kernel thread */
+Task *
+create_kthread(void (*func)(void), enum Priority p)
+{
+	/* Create new task */
+	Task *task = new(&taskType);
+	task->priority = p;
+	task->eip = (uintptr_t) func;
+
+	/* Setup stack to return to terminate() */
+	task->esp = (uintptr_t) task + KERNEL_STACK_SIZE;
+	PUSH(task->esp, terminate);
+
+	/* Schedule the task */
+	enqueue_task(task);
+	return task;
+}
diff --git a/task/scheduler.c b/task/scheduler.c
index f3bf5b8..c927eb3 100644
--- a/task/scheduler.c
+++ b/task/scheduler.c
@@ -14,7 +14,7 @@
 
 static void scheduler_new(Object *);
 static void scheduler_delete(Object *);
-void context_switch(uintptr_t eip, page_dir_t pageDir, uintptr_t ebx,
+void context_switch(uintptr_t eip, uintptr_t ebx,
                     uintptr_t esi, uintptr_t edi,
                     uintptr_t ebp, uintptr_t esp);
 
@@ -54,8 +54,6 @@ scheduler_delete(Object *obj)
 static void
 switch_to_task(Task *task)
 {
-	page_dir_t pageDir = task->pageDir;
-
 	/* Save current task state */
 	if (__builtin_expect(!!current, 1)) {
 		lock(current);
@@ -66,15 +64,16 @@ switch_to_task(Task *task)
 		asm volatile("mov %%ebp, %0" : "=r" (current->ebp));
 		current->eip = (uintptr_t) &&end;
 		unlock(current);
-		if (pageDir == current->pageDir)
-			pageDir = 0;
 		put(current);
 	}
 
 	/* Switch to new context */
+	switch_to_mm(task->vm);
 	current = task; /* Given reference, so no get() */
-	context_switch(current->eip, pageDir, current->ebx,
-	               current->esi, current->edi, current->ebp, current->esp);
+	set_kernel_stack((uintptr_t) current + KERNEL_STACK_SIZE);
+	context_switch(current->eip, current->ebx,
+	               current->esi, current->edi,
+	               current->ebp, current->esp);
 end:
 	/* This prevents GCC from optimising the jump to be after the return */
 	asm volatile("":::"memory");
@@ -86,7 +85,7 @@ highest_priority_queue(Scheduler *s)
 {
 	enum Priority p;
 	for (p = PRIORITY_COUNT - 1; p > 0; p--) {
-		if (count(s->queue[p ]))
+		if (count(s->queue[p]))
 			return p;
 	}
 	return 0;
diff --git a/task/switch.S b/task/switch.S
index 07f1e56..7c6c09d 100644
--- a/task/switch.S
+++ b/task/switch.S
@@ -13,15 +13,10 @@ context_switch:
 .code32
 	cli
 	mov 4(%esp), %ecx
-	mov 8(%esp), %eax
-	mov 12(%esp), %ebx
-	mov 16(%esp), %esi
-	mov 20(%esp), %edi
-	mov 24(%esp), %ebp
-	mov 28(%esp), %esp
-	test %eax, %eax
-	je 1f
-	mov %eax, %cr3
-1:
+	mov 8(%esp), %ebx
+	mov 12(%esp), %esi
+	mov 16(%esp), %edi
+	mov 20(%esp), %ebp
+	mov 24(%esp), %esp
 	sti
 	jmp *%ecx
diff --git a/task/task.c b/task/task.c
index 539026a..c1e744e 100644
--- a/task/task.c
+++ b/task/task.c
@@ -21,7 +21,7 @@ static void task_delete(Object *);
 /* Task object type */
 ObjectType taskType = {
 	.name = "TASK",
-	.size = sizeof(Task),
+	.size = KERNEL_STACK_SIZE, //sizeof(Task),
 	.new = task_new,
 	.delete = task_delete,
 };
@@ -47,8 +47,6 @@ task_delete(Object *obj)
 	Task *task = (void *) obj;
 	if (task->executable)
 		put(task->executable);
-	if (task->stack)
-		put(task->stack);
 	if (task->target)
 		put(task->target);
 	if (task->wait)
@@ -63,44 +61,11 @@ task_delete(Object *obj)
 		put(task->signals);
 }
 
-/* Move the stack */
-static void
-move_stack(uintptr_t top, size_t size)
-{
-	size_t offset;
-	uintptr_t oldStack, oldBase;
-	uintptr_t newStack, newBase;
-	top -= sizeof(uintptr_t);
-	asm volatile("mov %%esp, %0" : "=r" (oldStack));
-	asm volatile("mov %%ebp, %0" : "=r" (oldBase));
-	offset = top - (uintptr_t) stackTop;
-	newStack = oldStack + offset;
-	newBase = oldBase + offset;
-
-	memcpy((void *) newStack, (void *) oldStack, (size_t) stackTop - oldStack);
-
-	/* Update pointers on the stack */
-	uintptr_t i, tmp;
-	for (i = top; i > top - size; i -= sizeof(uintptr_t)) {
-		tmp = *(uintptr_t *) i;
-		if (tmp > oldStack && tmp < (uintptr_t) stackTop) {
-			tmp += offset;
-			*(uintptr_t *) i = tmp;
-		}
-	}
-
-	asm volatile("mov %0, %%esp" :: "r" (newStack));
-	asm volatile("mov %0, %%ebp" :: "r" (newBase));
-}
-
 /* Initialise tasking */
 void
 init_tasking(void)
 {
-	move_stack(0xF0800000, 0x2000);
-
 	current = new(&taskType);
-	asm volatile("mov %%cr3, %0" : "=r" (current->pageDir));
 	current->state = RUNNING;
 
 	/* File System namespace */
@@ -115,6 +80,7 @@ init_tasking(void)
 	cpu->scheduler->tasks = 1;
 	register_interrupt(0, timer_handler);
 	register_exception(128, syscall_handler);
+	set_kernel_stack((uintptr_t) current + KERNEL_STACK_SIZE);
 }
 
 /* Get the current task's PID */