diff options
author | Kevin O'Connor <kevin@koconnor.net> | 2009-12-10 21:35:49 -0500 |
---|---|---|
committer | Kevin O'Connor <kevin@koconnor.net> | 2009-12-10 21:35:49 -0500 |
commit | 7cefbfa227fdfb961e3b10535fbc151e5652014c (patch) | |
tree | 8a36c32b4f172a10377e922e83129616fbab3908 /src/util.c | |
parent | 752151b58e216fc15ae63997c8d9057b148a1e36 (diff) | |
download | seabios-hppa-7cefbfa227fdfb961e3b10535fbc151e5652014c.zip seabios-hppa-7cefbfa227fdfb961e3b10535fbc151e5652014c.tar.gz seabios-hppa-7cefbfa227fdfb961e3b10535fbc151e5652014c.tar.bz2 |
Move stack manipulation code from util.c to new file stacks.c.
Move the threading and stack_hop code to a new file.
Diffstat (limited to 'src/util.c')
-rw-r--r-- | src/util.c | 195 |
1 files changed, 16 insertions, 179 deletions
@@ -6,14 +6,7 @@ #include "util.h" // call16 #include "bregs.h" // struct bregs -#include "farptr.h" // GET_FLATPTR -#include "biosvar.h" // get_ebda_seg - -static inline u32 getesp() { - u32 esp; - asm("movl %%esp, %0" : "=rm"(esp)); - return esp; -} +#include "config.h" // BUILD_STACK_ADDR /**************************************************************** @@ -64,33 +57,6 @@ __call16_int(struct bregs *callregs, u16 offset) call16(callregs); } -// Switch to the extra stack in ebda and call a function. -inline u32 -stack_hop(u32 eax, u32 edx, u32 ecx, void *func) -{ - ASSERT16(); - u16 ebda_seg = get_ebda_seg(), bkup_ss; - u32 bkup_esp; - asm volatile( - // Backup current %ss/%esp values. - "movw %%ss, %w3\n" - "movl %%esp, %4\n" - // Copy ebda seg to %ds/%ss and set %esp - "movw %w6, %%ds\n" - "movw %w6, %%ss\n" - "movl %5, %%esp\n" - // Call func - "calll %7\n" - // Restore segments and stack - "movw %w3, %%ds\n" - "movw %w3, %%ss\n" - "movl %4, %%esp" - : "+a" (eax), "+d" (edx), "+c" (ecx), "=&r" (bkup_ss), "=&r" (bkup_esp) - : "i" (EBDA_OFFSET_TOP_STACK), "r" (ebda_seg), "m" (*(u8*)func) - : "cc", "memory"); - return eax; -} - // 16bit trampoline for enabling irqs from 32bit mode. ASM16( " .global trampoline_checkirqs\n" @@ -99,154 +65,25 @@ ASM16( " lretw" ); -static void -check_irqs32() -{ - extern void trampoline_checkirqs(); - struct bregs br; - br.flags = F_IF; - br.code.seg = SEG_BIOS; - br.code.offset = (u32)&trampoline_checkirqs; - call16big(&br); -} - -static void -check_irqs16() -{ - asm volatile( - "sti\n" - "nop\n" - "rep ; nop\n" - "cli\n" - "cld\n" - : : :"memory"); -} - - -/**************************************************************** - * Threads - ****************************************************************/ - -#define THREADSTACKSIZE 4096 - -struct thread_info { - struct thread_info *next; - void *stackpos; -}; - -struct thread_info MainThread; - void -thread_setup() -{ - MainThread.next = &MainThread; - MainThread.stackpos = NULL; -} - -struct thread_info * -getCurThread() -{ - u32 esp = getesp(); - if (esp <= BUILD_STACK_ADDR) - return &MainThread; - return (void*)ALIGN_DOWN(esp, THREADSTACKSIZE); -} - -// Briefly permit irqs to occur. -void -yield() +check_irqs() { if (MODE16) { - // In 16bit mode, just directly check irqs. - check_irqs16(); - return; - } - if (! CONFIG_THREADS) { - check_irqs32(); - return; + asm volatile( + "sti\n" + "nop\n" + "rep ; nop\n" + "cli\n" + "cld\n" + : : :"memory"); + } else { + extern void trampoline_checkirqs(); + struct bregs br; + br.flags = F_IF; + br.code.seg = SEG_BIOS; + br.code.offset = (u32)&trampoline_checkirqs; + call16big(&br); } - struct thread_info *cur = getCurThread(); - if (cur == &MainThread) - // Permit irqs to fire - check_irqs32(); - - // Switch to the next thread - struct thread_info *next = cur->next; - asm volatile( - " pushl $1f\n" // store return pc - " pushl %%ebp\n" // backup %ebp - " movl %%esp, 4(%%eax)\n" // cur->stackpos = %esp - " movl 4(%%ecx), %%esp\n" // %esp = next->stackpos - " popl %%ebp\n" // restore %ebp - " retl\n" // restore pc - "1:\n" - : "+a"(cur), "+c"(next) - : - : "ebx", "edx", "esi", "edi", "cc", "memory"); -} - -// Last thing called from a thread (called on "next" stack). -static void -__end_thread(struct thread_info *old) -{ - struct thread_info *pos = &MainThread; - while (pos->next != old) - pos = pos->next; - pos->next = old->next; - free(old); - dprintf(DEBUG_thread, "\\%08x/ End thread\n", (u32)old); -} - -void -run_thread(void (*func)(void*), void *data) -{ - ASSERT32(); - if (! CONFIG_THREADS) - goto fail; - struct thread_info *thread; - thread = memalign_tmphigh(THREADSTACKSIZE, THREADSTACKSIZE); - if (!thread) - goto fail; - - thread->stackpos = (void*)thread + THREADSTACKSIZE; - struct thread_info *cur = getCurThread(); - thread->next = cur->next; - cur->next = thread; - - dprintf(DEBUG_thread, "/%08x\\ Start thread\n", (u32)thread); - asm volatile( - // Start thread - " pushl $1f\n" // store return pc - " pushl %%ebp\n" // backup %ebp - " movl %%esp, 4(%%edx)\n" // cur->stackpos = %esp - " movl 4(%%ebx), %%esp\n" // %esp = thread->stackpos - " calll *%%ecx\n" // Call func - - // End thread - " movl (%%ebx), %%ecx\n" // %ecx = thread->next - " movl 4(%%ecx), %%esp\n" // %esp = next->stackpos - " movl %%ebx, %%eax\n" - " calll %4\n" // call __end_thread(thread) - " popl %%ebp\n" // restore %ebp - " retl\n" // restore pc - "1:\n" - : "+a"(data), "+c"(func), "+b"(thread), "+d"(cur) - : "m"(*(u8*)__end_thread) - : "esi", "edi", "cc", "memory"); - return; - -fail: - func(data); -} - -void -wait_threads() -{ - ASSERT32(); - if (! CONFIG_THREADS) - return; - while (MainThread.next != &MainThread) - yield(); } |