aboutsummaryrefslogtreecommitdiff
path: root/src/stacks.c
diff options
context:
space:
mode:
authorKevin O'Connor <kevin@koconnor.net>2010-04-02 13:13:23 -0400
committerKevin O'Connor <kevin@koconnor.net>2010-04-02 13:13:23 -0400
commita7eb8fcf812c69c32d430b6fc79806256921f75e (patch)
treec9438ff81b88bd8a92e4d2b249442f802e07ec3c /src/stacks.c
parentd28b0fe8db0b5af2f4ddeeb48c01fa0c1ed7a920 (diff)
downloadseabios-hppa-a7eb8fcf812c69c32d430b6fc79806256921f75e.zip
seabios-hppa-a7eb8fcf812c69c32d430b6fc79806256921f75e.tar.gz
seabios-hppa-a7eb8fcf812c69c32d430b6fc79806256921f75e.tar.bz2
Some improvements to optionrom preemption support.
Enable preemption during VGA mode switch call - this call can take several milliseconds on real hardware. Call yield() in finish_preempt() - when preemption is configured it allows threads in wait_preempt() to run; when not configured it gives an opportunity for threads to execute after the implicit delay from optionrom execution. Don't penalize priority in run_thread(). The run_thread() code would implicitly yield because it created the new thread on the list after the current thread and then jumped to it. When in a preemption event, a yield effectively waits approximately one millisecond (to the next rtc irq). The implicit yielding in run_thread thus limited the number of threads one could launch during preemption to 1 per millisecond. So, change the code so that the new thread is created prior to the current thread - thus eliminating the effective yield from run_thread().
Diffstat (limited to 'src/stacks.c')
-rw-r--r--src/stacks.c21
1 files changed, 14 insertions, 7 deletions
diff --git a/src/stacks.c b/src/stacks.c
index 570948a..92d91a0 100644
--- a/src/stacks.c
+++ b/src/stacks.c
@@ -116,9 +116,12 @@ stack_hop(u32 eax, u32 edx, void *func)
#define THREADSTACKSIZE 4096
+// Thread info - stored at bottom of each thread stack - don't change
+// without also updating the inline assembler below.
struct thread_info {
struct thread_info *next;
void *stackpos;
+ struct thread_info **pprev;
};
struct thread_info VAR16VISIBLE MainThread;
@@ -128,6 +131,7 @@ void
thread_setup(void)
{
MainThread.next = &MainThread;
+ MainThread.pprev = &MainThread.next;
MainThread.stackpos = NULL;
CanPreempt = 0;
}
@@ -185,10 +189,8 @@ yield(void)
static void
__end_thread(struct thread_info *old)
{
- struct thread_info *pos = &MainThread;
- while (pos->next != old)
- pos = pos->next;
- pos->next = old->next;
+ old->next->pprev = old->pprev;
+ *old->pprev = old->next;
free(old);
dprintf(DEBUG_thread, "\\%08x/ End thread\n", (u32)old);
}
@@ -207,8 +209,10 @@ run_thread(void (*func)(void*), void *data)
thread->stackpos = (void*)thread + THREADSTACKSIZE;
struct thread_info *cur = getCurThread();
- thread->next = cur->next;
- cur->next = thread;
+ thread->next = cur;
+ thread->pprev = cur->pprev;
+ cur->pprev = &thread->next;
+ *thread->pprev = thread;
dprintf(DEBUG_thread, "/%08x\\ Start thread\n", (u32)thread);
asm volatile(
@@ -289,11 +293,14 @@ start_preempt(void)
void
finish_preempt(void)
{
- if (! CONFIG_THREADS || ! CONFIG_THREAD_OPTIONROMS)
+ if (! CONFIG_THREADS || ! CONFIG_THREAD_OPTIONROMS) {
+ yield();
return;
+ }
CanPreempt = 0;
releaseRTC();
dprintf(1, "Done preempt - %d checks\n", PreemptCount);
+ yield();
}
// Check if preemption is on, and wait for it to complete if so.