diff options
author | H. Peter Anvin <hpa@zytor.com> | 2011-04-21 22:16:14 -0700 |
---|---|---|
committer | H. Peter Anvin <hpa@zytor.com> | 2011-04-21 22:16:14 -0700 |
commit | f5203bfa11fde88d16f471b4050ed1da73387c7a (patch) | |
tree | 1240d92a993cf49fe1b92ad3d564596009b45794 /core | |
parent | 3f6823a63c7f153421bbca343423a5fddc1a4ec1 (diff) | |
download | syslinux-f5203bfa11fde88d16f471b4050ed1da73387c7a.tar.gz syslinux-f5203bfa11fde88d16f471b4050ed1da73387c7a.tar.xz syslinux-f5203bfa11fde88d16f471b4050ed1da73387c7a.zip |
thread: thread-switch the real-mode stack, too
When this code was originally written, we didn't have lmalloc(). Now
when lmalloc() is implemented, let each real-mode task have its own
stack.
Note that this means we absolutely have to continue to support the
SS != CS, DS model in the real-mode code, which should already be the
case, but...
Signed-off-by: H. Peter Anvin <hpa@zytor.com>
Diffstat (limited to 'core')
-rw-r--r-- | core/include/thread.h | 1 | ||||
-rw-r--r-- | core/pm.inc | 1 | ||||
-rw-r--r-- | core/thread/exit_thread.c | 7 | ||||
-rw-r--r-- | core/thread/start_thread.c | 19 | ||||
-rw-r--r-- | core/thread/thread_asm.S | 2 |
5 files changed, 27 insertions, 3 deletions
diff --git a/core/include/thread.h b/core/include/thread.h index 704962e1..b283424d 100644 --- a/core/include/thread.h +++ b/core/include/thread.h @@ -26,6 +26,7 @@ struct thread { const char *name; /* Name (for debugging) */ struct thread_list list; struct thread_block *blocked; + void *stack, *rmstack; /* Stacks, iff allocated by malloc/lmalloc */ void *pvt; /* For the benefit of lwIP */ int prio; }; diff --git a/core/pm.inc b/core/pm.inc index 8690cabe..ddeca25c 100644 --- a/core/pm.inc +++ b/core/pm.inc @@ -459,6 +459,7 @@ pm_init: section .earlybss alignb 8 IDT: resq 256 + global RealModeSSSP RealModeSSSP resd 1 ; Real-mode SS:SP section .gentextnr ; Autogenerated 32-bit code diff --git a/core/thread/exit_thread.c b/core/thread/exit_thread.c index 0aadfb6c..444f9e27 100644 --- a/core/thread/exit_thread.c +++ b/core/thread/exit_thread.c @@ -1,5 +1,6 @@ #include "thread.h" #include <limits.h> +#include <stdlib.h> #include <klibc/compiler.h> __noreturn __exit_thread(void) @@ -13,6 +14,12 @@ __noreturn __exit_thread(void) curr->list.prev->next = curr->list.next; curr->list.next->prev = curr->list.prev; + /* Free allocated stacks */ + if (curr->stack) + free(curr->stack); + if (curr->rmstack) + free(curr->stack); + /* * Note: __schedule() can explictly handle the case where * curr isn't part of the linked list anymore, as long as diff --git a/core/thread/start_thread.c b/core/thread/start_thread.c index 52cc7dfb..77dc0ea8 100644 --- a/core/thread/start_thread.c +++ b/core/thread/start_thread.c @@ -1,7 +1,11 @@ #include <string.h> #include <stdlib.h> +#include <com32.h> +#include "core.h" #include "thread.h" +#define REAL_MODE_STACK_SIZE 4096 + extern void __start_thread(void); /* @@ -9,6 +13,7 @@ extern void __start_thread(void); */ struct thread_stack { int errno; + uint16_t rmsp, rmss; uint32_t edi, esi, ebp, ebx; void (*eip)(void); }; @@ -18,7 +23,7 @@ struct thread *start_thread(const char *name, size_t stack_size, int prio, { irq_state_t irq; struct thread *curr, *t; - char *stack; + char *stack, *rmstack; const size_t thread_mask = 31; /* Alignment mask */ struct thread_stack *sp; @@ -26,17 +31,25 @@ struct thread *start_thread(const char *name, size_t stack_size, int prio, stack = malloc(stack_size + sizeof(struct thread)); if (!stack) return NULL; + rmstack = lmalloc(REAL_MODE_STACK_SIZE); + if (!rmstack) { + free(stack); + return NULL; + } t = (struct thread *)stack; - stack += sizeof(struct thread); - memset(t, 0, sizeof *t); + t->stack = stack; + t->rmstack = rmstack; + stack += sizeof(struct thread); /* sp allocated from the end of the stack */ sp = (struct thread_stack *)(stack + stack_size) - 1; t->esp = sp; sp->errno = 0; + sp->rmss = SEG(rmstack); + sp->rmsp = OFFS_WRT(rmstack + REAL_MODE_STACK_SIZE, sp->rmss); sp->esi = (size_t)start_func; sp->edi = (size_t)func_arg; sp->ebx = irq_state(); /* Inherit the IRQ state from the spawner */ diff --git a/core/thread/thread_asm.S b/core/thread/thread_asm.S index 34843a51..ec3e0add 100644 --- a/core/thread/thread_asm.S +++ b/core/thread/thread_asm.S @@ -6,12 +6,14 @@ __switch_to: pushl %ebp pushl %esi pushl %edi + pushl RealModeSSSP pushl errno /* Hack! */ movl %esp, (%edx) movl %eax, __current movl (%eax), %esp popl errno + popl RealModeSSSP popl %edi popl %esi popl %ebp |