fix race in thread_yield, cpu_switch_context_exit

call *context only with interrupts disabled, use isr trampoline for
this if necessary
This commit is contained in:
Ludwig Ortmann 2013-11-08 13:12:15 +01:00
parent 7b9d199ec8
commit 9f080c54c6
2 changed files with 49 additions and 22 deletions

View File

@ -292,7 +292,6 @@ void native_irq_handler()
} }
DEBUG("native_irq_handler(): return"); DEBUG("native_irq_handler(): return");
_native_in_isr = 0;
cpu_switch_context_exit(); cpu_switch_context_exit();
} }

View File

@ -104,7 +104,7 @@ char *thread_stack_init(void (*task_func)(void), void *stack_start, int stacksiz
return (char *) p; return (char *) p;
} }
void cpu_switch_context_exit(void) void isr_cpu_switch_context_exit(void)
{ {
ucontext_t *ctx; ucontext_t *ctx;
@ -119,36 +119,64 @@ void cpu_switch_context_exit(void)
/* the next context will have interrupts enabled due to ucontext */ /* the next context will have interrupts enabled due to ucontext */
DEBUG("XXX: cpu_switch_context_exit: native_interrupts_enabled = 1;\n"); DEBUG("XXX: cpu_switch_context_exit: native_interrupts_enabled = 1;\n");
native_interrupts_enabled = 1; native_interrupts_enabled = 1;
_native_in_isr = 0;
if (setcontext(ctx) == -1) { if (setcontext(ctx) == -1) {
err(1, "cpu_switch_context_exit(): setcontext():"); err(1, "cpu_switch_context_exit(): setcontext():");
} }
} }
void thread_yield() void cpu_switch_context_exit()
{ {
/** if (_native_in_isr == 0) {
* XXX: check whether it is advisable to switch context for sched_run() dINT();
*/ _native_in_isr = 1;
ucontext_t *oc, *nc; native_isr_context.uc_stack.ss_sp = __isr_stack;
native_isr_context.uc_stack.ss_size = SIGSTKSZ;
DEBUG("thread_yield()\n"); native_isr_context.uc_stack.ss_flags = 0;
makecontext(&native_isr_context, isr_cpu_switch_context_exit, 0);
oc = (ucontext_t *)(active_thread->sp); if (setcontext(&native_isr_context) == -1) {
err(1, "cpu_switch_context_exit: swapcontext");
sched_run();
nc = (ucontext_t *)(active_thread->sp);
if (nc != oc) {
DEBUG("thread_yield(): calling swapcontext(%s)\n\n", active_thread->name);
if (swapcontext(oc, nc) == -1) {
err(1, "thread_yield(): swapcontext()");
} }
} }
else { else {
DEBUG("thread_yield(): old = new, returning to context (%s)\n\n", active_thread->name); isr_cpu_switch_context_exit();
}
errx(EXIT_FAILURE, "this should have never been reached!!");
}
void isr_thread_yield()
{
DEBUG("isr_thread_yield()\n");
sched_run();
ucontext_t *ctx = (ucontext_t *)(active_thread->sp);
DEBUG("isr_thread_yield(): switching to(%s)\n\n", active_thread->name);
native_interrupts_enabled = 1;
_native_in_isr = 0;
if (setcontext(ctx) == -1) {
err(1, "isr_thread_yield(): setcontext()");
}
}
void thread_yield()
{
ucontext_t *ctx = (ucontext_t *)(active_thread->sp);
if (_native_in_isr == 0) {
_native_in_isr = 1;
dINT();
native_isr_context.uc_stack.ss_sp = __isr_stack;
native_isr_context.uc_stack.ss_size = SIGSTKSZ;
native_isr_context.uc_stack.ss_flags = 0;
makecontext(&native_isr_context, isr_thread_yield, 0);
if (swapcontext(ctx, &native_isr_context) == -1) {
err(1, "thread_yield: swapcontext");
}
eINT();
}
else {
isr_thread_yield();
} }
} }