[syslinux:lwip] thread: thread-switch the real-mode stack, too

syslinux-bot for H. Peter Anvin hpa at zytor.com
Fri Apr 22 20:06:22 PDT 2011


Commit-ID:  f5203bfa11fde88d16f471b4050ed1da73387c7a
Gitweb:     http://syslinux.zytor.com/commit/f5203bfa11fde88d16f471b4050ed1da73387c7a
Author:     H. Peter Anvin <hpa at zytor.com>
AuthorDate: Thu, 21 Apr 2011 22:16:14 -0700
Committer:  H. Peter Anvin <hpa at zytor.com>
CommitDate: Thu, 21 Apr 2011 22:16:14 -0700

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 at zytor.com>


---
 core/include/thread.h      |    1 +
 core/pm.inc                |    1 +
 core/thread/exit_thread.c  |    7 +++++++
 core/thread/start_thread.c |   19 ++++++++++++++++---
 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 704962e..b283424 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 8690cab..ddeca25 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 0aadfb6..444f9e2 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 52cc7df..77dc0ea 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 34843a5..ec3e0ad 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



More information about the Syslinux-commits mailing list