1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
// SPDX-License-Identifier: Apache-2.0

#![feature(naked_functions)]
#![feature(asm)]
#![no_std]
#![deny(clippy::all)]
#![deny(missing_docs)]

//! Welcome to frenetic!
//!
//! Frenetic is a crate that provides low-level context switch building blocks.
//! It can be used to build higher level primatives like coroutines.

mod arch;

/// A CPU context
///
/// This structure holds the non-volatile state in the platform's calling convention.
#[derive(Default)]
#[repr(transparent)]
pub struct Context(arch::Context);

impl Context {
    /// Clear all basic volatile registers and CPU flags
    #[inline(always)]
    pub fn wipe() {
        arch::Context::wipe()
    }

    /// Saves the non-volatile registers
    ///
    /// NOTE: This function can return more than once.
    ///
    /// This function returns `true` when returning locally from a `save()`
    /// operation and returns `false` when returning remotely from a `load()`
    /// operation.
    #[must_use]
    #[inline(always)]
    pub fn save(&mut self) -> bool {
        self.0.save()
    }

    /// Load a context
    ///
    /// This function stops executing at the current location and resumes
    /// execution wherever `Self::save()` was called (with a `false` return
    /// value).
    ///
    /// # Safety
    ///
    /// This is very unsafe. You MUST have called `Self::save()` before calling
    /// this function. Further, all the pointers in the non-volatile registers
    /// must still be valid.
    #[inline(always)]
    pub unsafe fn load(&self) -> ! {
        self.0.load()
    }
}