context.rs 1.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051
  1. use core::{cell::UnsafeCell, mem::transmute};
  2. #[derive(Debug)]
  3. pub struct ExecutionContext(UnsafeCell<arch::TaskContext>);
  4. unsafe impl Sync for ExecutionContext {}
  5. impl ExecutionContext {
  6. pub const fn new() -> Self {
  7. Self(UnsafeCell::new(arch::TaskContext::new()))
  8. }
  9. pub fn set_ip(&mut self, ip: usize) {
  10. let Self(context) = self;
  11. context.get_mut().ip(ip);
  12. }
  13. pub fn set_sp(&mut self, sp: usize) {
  14. let Self(context) = self;
  15. context.get_mut().sp(sp);
  16. }
  17. pub fn set_interrupt(&mut self, is_enabled: bool) {
  18. let Self(context) = self;
  19. context.get_mut().interrupt(is_enabled);
  20. }
  21. pub fn call1<T>(&mut self, func: unsafe extern "C" fn(T) -> !, arg: usize) {
  22. let Self(context) = self;
  23. context
  24. .get_mut()
  25. .call1(unsafe { transmute(func as *mut ()) }, [arg]);
  26. }
  27. pub fn switch_to(&self, to: &Self) {
  28. let Self(from_ctx) = self;
  29. let Self(to_ctx) = to;
  30. unsafe {
  31. arch::TaskContext::switch(&mut *from_ctx.get(), &mut *to_ctx.get());
  32. }
  33. }
  34. pub fn switch_noreturn(&self) -> ! {
  35. let mut from_ctx = arch::TaskContext::new();
  36. let Self(to_ctx) = self;
  37. unsafe {
  38. arch::TaskContext::switch(&mut from_ctx, &mut *to_ctx.get());
  39. }
  40. unreachable!("We should never return from switch_to_noreturn");
  41. }
  42. }