From 6f2535876ff37db8a4a215f0e06a88b2671be0bc Mon Sep 17 00:00:00 2001 From: "H. Peter Anvin" Date: Wed, 9 Sep 2009 21:34:28 -0700 Subject: [PATCH] core: thread: move most thread state to stack; task switch errno Move most our thread state to the stack. Task switch the errno variable. Signed-off-by: H. Peter Anvin --- core/include/thread.h | 6 +----- core/thread/kill_thread.c | 5 ++++- core/thread/start_thread.c | 30 ++++++++++++++++++++++-------- core/thread/thread_asm.S | 22 ++++++++++++---------- 4 files changed, 39 insertions(+), 24 deletions(-) diff --git a/core/include/thread.h b/core/include/thread.h index 514c30b..e644b9f 100644 --- a/core/include/thread.h +++ b/core/include/thread.h @@ -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; diff --git a/core/thread/kill_thread.c b/core/thread/kill_thread.c index ed2e05f..83accee 100644 --- a/core/thread/kill_thread.c +++ b/core/thread/kill_thread.c @@ -1,6 +1,9 @@ #include "thread.h" #include +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; diff --git a/core/thread/start_thread.c b/core/thread/start_thread.c index afe7ecf..29e9972 100644 --- a/core/thread/start_thread.c +++ b/core/thread/start_thread.c @@ -2,7 +2,16 @@ #include #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(); diff --git a/core/thread/thread_asm.S b/core/thread/thread_asm.S index 64f9c9b..34843a5 100644 --- a/core/thread/thread_asm.S +++ b/core/thread/thread_asm.S @@ -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 -- 2.7.4