perf(context): pass actor sp through registers, not TLS
switch_to_actor takes the target sp in rdi and returns the actor's next saved sp in rax (handed over by switch_to_scheduler's shim). Deletes the ACTOR_SP thread-local and halves the helper calls per one-way switch (2 -> 1); the scheduler loop also drops its set_actor_sp/get_actor_sp TLS round-trips. SCHEDULER_SP stays: a yielding actor at arbitrary call depth has no argument channel back. asm before/after in outputs/history.md session 1-2. Tests: 354 pass.
This commit is contained in:
+10
-22
@@ -1,9 +1,7 @@
|
||||
//! Low-level context-switch tests. These poke `init_actor_stack` and the
|
||||
//! naked asm shims directly — no scheduler involved.
|
||||
|
||||
use smarm::context::{
|
||||
get_actor_sp, init_actor_stack, set_actor_sp, switch_to_actor, switch_to_scheduler,
|
||||
};
|
||||
use smarm::context::{init_actor_stack, switch_to_actor, switch_to_scheduler};
|
||||
use smarm::stack::Stack;
|
||||
use std::cell::Cell;
|
||||
|
||||
@@ -31,8 +29,7 @@ fn actor_runs_and_returns_to_scheduler() {
|
||||
reset_log();
|
||||
let stack = Stack::new(64 * 1024, 4096).unwrap();
|
||||
let sp = init_actor_stack(stack.top(), actor_simple);
|
||||
set_actor_sp(sp);
|
||||
unsafe { switch_to_actor() };
|
||||
let _ = unsafe { switch_to_actor(sp) };
|
||||
assert_eq!(get_log(), 0x1);
|
||||
}
|
||||
|
||||
@@ -48,12 +45,11 @@ fn actor_yields_and_resumes() {
|
||||
reset_log();
|
||||
let stack = Stack::new(64 * 1024, 4096).unwrap();
|
||||
let sp = init_actor_stack(stack.top(), actor_two_steps);
|
||||
set_actor_sp(sp);
|
||||
|
||||
unsafe { switch_to_actor() };
|
||||
let sp = unsafe { switch_to_actor(sp) };
|
||||
assert_eq!(get_log(), 0x1, "after first resume");
|
||||
|
||||
unsafe { switch_to_actor() };
|
||||
let _ = unsafe { switch_to_actor(sp) };
|
||||
assert_eq!(get_log(), 0x1 | 0x2, "after second resume");
|
||||
}
|
||||
|
||||
@@ -96,10 +92,9 @@ extern "C-unwind" fn actor_reg_check() {
|
||||
fn callee_saved_registers_survive_yield() {
|
||||
let stack = Stack::new(64 * 1024, 4096).unwrap();
|
||||
let sp = init_actor_stack(stack.top(), actor_reg_check);
|
||||
set_actor_sp(sp);
|
||||
unsafe {
|
||||
switch_to_actor();
|
||||
switch_to_actor();
|
||||
let sp = switch_to_actor(sp);
|
||||
let _ = switch_to_actor(sp);
|
||||
}
|
||||
assert_eq!(
|
||||
REG_BEFORE.get().copied().unwrap(),
|
||||
@@ -138,18 +133,11 @@ fn two_actors_dont_corrupt_each_other() {
|
||||
let sp_a = init_actor_stack(stack_a.top(), actor_a);
|
||||
let sp_b = init_actor_stack(stack_b.top(), actor_b);
|
||||
|
||||
set_actor_sp(sp_a);
|
||||
unsafe { switch_to_actor() };
|
||||
let sp_a = get_actor_sp();
|
||||
let sp_a = unsafe { switch_to_actor(sp_a) };
|
||||
let sp_b = unsafe { switch_to_actor(sp_b) };
|
||||
|
||||
set_actor_sp(sp_b);
|
||||
unsafe { switch_to_actor() };
|
||||
let sp_b = get_actor_sp();
|
||||
|
||||
set_actor_sp(sp_a);
|
||||
unsafe { switch_to_actor() };
|
||||
set_actor_sp(sp_b);
|
||||
unsafe { switch_to_actor() };
|
||||
let _ = unsafe { switch_to_actor(sp_a) };
|
||||
let _ = unsafe { switch_to_actor(sp_b) };
|
||||
|
||||
assert_eq!(A_VAL.with(|c| c.get()), 0xA00D);
|
||||
assert_eq!(B_VAL.with(|c| c.get()), 0xB00D);
|
||||
|
||||
Reference in New Issue
Block a user