core: thread: move most thread state to stack; task switch errno
authorH. Peter Anvin <hpa@zytor.com>
Thu, 10 Sep 2009 04:34:28 +0000 (21:34 -0700)
committerEric W. Biederman <ebiederm@xmission.com>
Sun, 10 Apr 2011 01:27:06 +0000 (18:27 -0700)
Move most our thread state to the stack.  Task switch the errno
variable.

Signed-off-by: H. Peter Anvin <hpa@zytor.com>
core/include/thread.h
core/thread/kill_thread.c
core/thread/start_thread.c
core/thread/thread_asm.S

index 514c30b..e644b9f 100644 (file)
@@ -7,10 +7,6 @@
 
 struct semaphore;
 
-struct thread_state {
-    uint32_t ebx, esp, ebp, esi, edi;
-};
-
 struct thread_list {
     struct thread_list *next, *prev;
 };
@@ -25,7 +21,7 @@ struct thread_block {
 };
 
 struct thread {
-    struct thread_state state;
+    void *esp;                 /* Must be first; stack pointer */
     struct thread_list  list;
     struct thread_block *blocked;
     int prio;
index ed2e05f..83accee 100644 (file)
@@ -1,6 +1,9 @@
 #include "thread.h"
 #include <limits.h>
 
+extern void __exit_thread(void);
+typedef void (*func_ptr)(void);
+
 void kill_thread(struct thread *thread)
 {
     irq_state_t irq;
@@ -15,7 +18,7 @@ void kill_thread(struct thread *thread)
      * Muck with the stack so that the next time the thread is run then
      * we end up going to __exit_thread.
      */
-    *(size_t *)thread->state.esp = (size_t)__exit_thread;
+    *(func_ptr *)thread->esp = __exit_thread;
     thread->prio = INT_MIN;
 
     block = thread->blocked;
index afe7ecf..29e9972 100644 (file)
@@ -2,7 +2,16 @@
 #include <stdlib.h>
 #include "thread.h"
 
-extern void (*__start_thread)(void);
+extern void __start_thread(void);
+
+/*
+ * Stack frame used by __switch_to, see thread_asm.S
+ */
+struct thread_stack {
+    int errno;
+    uint32_t edi, esi, ebp, ebx;
+    void (*eip)(void);
+};
 
 struct thread *start_thread(size_t stack_size, int prio,
                            void (*start_func)(void *), void *func_arg)
@@ -10,23 +19,28 @@ struct thread *start_thread(size_t stack_size, int prio,
     irq_state_t irq;
     struct thread *curr, *t;
     char *stack;
-    const size_t thread_mask = __alignof__(struct thread)-1;
+    const size_t thread_mask = 31; /* Alignment mask */
+    struct thread_stack *sp;
 
     stack_size = (stack_size + thread_mask) & ~thread_mask;
     stack = malloc(stack_size + sizeof(struct thread));
     if (!stack)
        return NULL;
 
-    t = (struct thread *)(stack + stack_size);
+    t = (struct thread *)stack;
+    stack = (char *)(t + 1);   /* After the thread structure */
 
     memset(t, 0, sizeof *t);
 
-    t->state.esp = (((size_t)stack + stack_size) & ~3) - 4;
-    *(size_t *)t->state.esp = (size_t)&__start_thread;
+    /* sp allocated from the end of the stack */
+    sp = (struct thread_stack *)(stack + stack_size) - 1;
+    t->esp = sp;
 
-    t->state.esi = (size_t)start_func;
-    t->state.edi = (size_t)func_arg;
-    t->state.ebx = irq_state();        /* Inherit the IRQ state from the spawner */
+    sp->errno = 0;
+    sp->esi = (size_t)start_func;
+    sp->edi = (size_t)func_arg;
+    sp->ebx = irq_state();     /* Inherit the IRQ state from the spawner */
+    sp->eip = __start_thread;
     t->prio = prio;
 
     irq = irq_save();
index 64f9c9b..34843a5 100644 (file)
@@ -2,18 +2,20 @@
        .type   __switch_to, @function
 __switch_to:
        movl    __current, %edx
-       movl    %ebx,   (%edx)
-       movl    %esp,  4(%edx)
-       movl    %ebp,  8(%edx)
-       movl    %esi, 12(%edx)
-       movl    %edi, 16(%edx)
+       pushl   %ebx
+       pushl   %ebp
+       pushl   %esi
+       pushl   %edi
+       pushl   errno                   /* Hack! */
+       movl    %esp, (%edx)
 
-       movl      (%eax), %ebx
-       movl     4(%eax), %esp
-       movl     8(%eax), %ebp
-       movl    12(%eax), %esi
-       movl    16(%eax), %edi
        movl    %eax, __current
+       movl    (%eax), %esp
+       popl    errno
+       popl    %edi
+       popl    %esi
+       popl    %ebp
+       popl    %ebx
        ret
        .size   __switch_to, .-__switch_to