mirror of
https://github.com/rdmsr/zag.git
synced 2026-11-01 15:48:21 +00:00
ke/sched: fix lock inversion in scheduler
Taking next's lock can be a lock inversion with the turnstile code. Use a switching field instead and spin on that.
This commit is contained in:
@@ -25,7 +25,7 @@ const ThreadFrame = extern struct {
|
||||
|
||||
extern fn asm_thread_entry() void;
|
||||
|
||||
extern fn do_context_switch(old: *ThreadContext, new: *ThreadContext, lock: *u8) callconv(.c) void;
|
||||
extern fn do_context_switch(old: *ThreadContext, new: *ThreadContext, lock: *u8, switching: *bool) callconv(.c) void;
|
||||
|
||||
pub const ThreadContext = extern struct {
|
||||
rsp: u64 align(1),
|
||||
@@ -60,7 +60,7 @@ pub const ThreadContext = extern struct {
|
||||
|
||||
pub fn switch_to(self: *ThreadContext, new: *ThreadContext) callconv(.c) void {
|
||||
const thread: *ke.Thread = @alignCast(@fieldParentPtr("context", self));
|
||||
do_context_switch(self, new, &thread.lock.inner.locked.raw);
|
||||
do_context_switch(self, new, &thread.lock.inner.locked.raw, &thread.switching.raw);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -149,9 +149,13 @@ do_context_switch:
|
||||
/* Load new stack pointer. */
|
||||
mov (%rsi), %rsp
|
||||
|
||||
/* Set switching to false. */
|
||||
xorl %eax, %eax
|
||||
xchgb %al, (%rcx)
|
||||
|
||||
/* Unlock passed lock. */
|
||||
xorl %ecx, %ecx
|
||||
xchgb %cl, (%rdx)
|
||||
xorl %eax, %eax
|
||||
xchgb %al, (%rdx)
|
||||
|
||||
/* Restore callee-saved registers. */
|
||||
pop %rbp
|
||||
|
||||
Reference in New Issue
Block a user