Next Generation WASM Microkernel Operating System
at trap_handler 246 lines 8.3 kB view raw
1// Copyright 2025. Jonas Kruckenberg 2// 3// Licensed under the Apache License, Version 2.0, <LICENSE-APACHE or 4// http://apache.org/licenses/LICENSE-2.0> or the MIT license <LICENSE-MIT or 5// http://opensource.org/licenses/MIT>, at your option. This file may not be 6// copied, modified, or distributed except according to those terms. 7 8use crate::time::max_duration; 9use core::fmt; 10use core::time::Duration; 11 12pub struct Clock { 13 name: &'static str, 14 tick_duration: Duration, 15 clock: RawClock, 16} 17 18/// A virtual function pointer table (vtable) that specifies the behavior 19/// of a [`RawClock`]. 20/// 21/// The pointer passed to all functions inside the vtable is the `data` pointer 22/// from the enclosing [`RawClock`] object. 23/// 24/// The functions inside this struct are only intended to be called on the `data` 25/// pointer of a properly constructed [`RawClock`] object from inside the 26/// [`RawClock`] implementation. Calling one of the contained functions using 27/// any other `data` pointer will cause undefined behavior. 28/// 29/// # Thread safety 30/// 31/// All vtable functions must be thread-safe (even though [`RawClock`] is 32/// <code>\![Send] + \![Sync]</code>). This is because [`Clock`] is <code>[Send] + [Sync]</code>, 33/// and it *will* be moved to arbitrary threads or invoked by `&` reference. For example, 34/// this means that if the `clone` and `drop` functions manage a reference count, 35/// they must do so atomically. 36#[derive(Copy, Clone, Debug)] 37pub struct RawClockVTable { 38 clone: unsafe fn(*const ()) -> RawClock, 39 now: unsafe fn(*const ()) -> u64, 40 schedule_wakeup: unsafe fn(*const (), at: u64), 41 drop: unsafe fn(*const ()), 42} 43 44#[derive(Debug)] 45pub struct RawClock { 46 /// The `data` pointer can be used to store arbitrary data as required by the clock implementation. 47 data: *const (), 48 /// Virtual function pointer table that customizes the behavior of this clock. 49 vtable: &'static RawClockVTable, 50} 51 52// === impl Clock === 53 54impl Unpin for Clock {} 55 56// Safety: As part of the safety contract for RawClockVTable, the caller promised RawClock is Send 57// therefore Clock is Send too 58unsafe impl Send for Clock {} 59// Safety: As part of the safety contract for RawClockVTable, the caller promised RawClock is Sync 60// therefore Clock is Sync too 61unsafe impl Sync for Clock {} 62 63impl Clock { 64 /// Creates a new `Clock` from the provided `tick_duration`, `data` pointer and `vtable`. 65 /// 66 /// The `tick_duration` is the `Duration` of time represented by a single `u64` tick in this clock. 67 /// This is in effect the precision of the clock and should be set to the precision of the underlying 68 /// hardware timer. 69 /// 70 /// The `data` pointer can be used to store arbitrary data as required by the clock implementation. 71 /// This could be e.g. a type-erased pointer to an `Arc` that holds private implementation-specific state. 72 /// The value of this pointer will get passed to all functions that are part 73 /// of the `vtable` as the first parameter. 74 /// 75 /// It is important to consider that the `data` pointer must point to a 76 /// thread safe type such as an `Arc`. 77 /// 78 /// The `vtable` customizes the behavior of a `Clock`. For each operation 79 /// on the `Clock`, the associated function in the `vtable` will be called. 80 /// 81 /// # Safety 82 /// 83 /// The behavior of the returned `Clock` is undefined if the contract defined 84 /// in [`RawClockVTable`]'s documentation is not upheld. 85 #[inline] 86 #[must_use] 87 pub const unsafe fn new( 88 tick_duration: Duration, 89 data: *const (), 90 vtable: &'static RawClockVTable, 91 ) -> Clock { 92 // Safety: ensured by caller 93 unsafe { Self::from_raw(tick_duration, RawClock { data, vtable }) } 94 } 95 96 /// Creates a new `Clock` from a [`RawClock`]. 97 /// 98 /// # Safety 99 /// 100 /// The behavior of the returned `Waker` is undefined if the contract defined 101 /// in [`RawClock`]'s and [`RawClockVTable`]'s documentation is not upheld. 102 #[inline] 103 #[must_use] 104 pub const unsafe fn from_raw(tick_duration: Duration, clock: RawClock) -> Clock { 105 Self { 106 clock, 107 tick_duration, 108 name: "<unnamed mystery clock>", 109 } 110 } 111 112 /// Add an arbitrary user-defined name to this `Clock`. 113 /// 114 /// This is generally used to describe the hardware time source used by the 115 /// `now()` function for this `Clock`. 116 #[must_use] 117 pub const fn named(mut self, name: &'static str) -> Self { 118 self.name = name; 119 self 120 } 121 122 /// Returns this `Clock`'s name, if it was given one using the [`Clock::named`] 123 /// method. 124 #[must_use] 125 pub fn name(&self) -> &'static str { 126 self.name 127 } 128 129 /// Returns the [`Duration`] of one tick of this clock. 130 #[must_use] 131 pub const fn tick_duration(&self) -> Duration { 132 self.tick_duration 133 } 134 135 /// Returns the maximum duration of this clock. 136 #[must_use] 137 pub fn max_duration(&self) -> Duration { 138 max_duration(self.tick_duration()) 139 } 140 141 /// Gets the `data` pointer used to create this `Clock`. 142 #[inline] 143 #[must_use] 144 pub fn data(&self) -> *const () { 145 self.clock.data 146 } 147 148 /// Gets the `vtable` pointer used to create this `Clock`. 149 #[inline] 150 #[must_use] 151 pub fn vtable(&self) -> &'static RawClockVTable { 152 self.clock.vtable 153 } 154 155 #[inline] 156 pub fn now(&self) -> u64 { 157 // Safety: This is safe because `Clock::from_raw` is the only way 158 // to initialize `vtable` and `data` requiring the user to acknowledge 159 // that the contract of `RawClock` is upheld. 160 unsafe { (self.clock.vtable.now)(self.clock.data) } 161 } 162 163 #[inline] 164 pub fn schedule_wakeup(&self, at: u64) { 165 // Safety: see Clock::now 166 unsafe { (self.clock.vtable.schedule_wakeup)(self.clock.data, at) }; 167 } 168} 169 170impl Clone for Clock { 171 #[inline] 172 fn clone(&self) -> Self { 173 Clock { 174 // SAFETY: see Clock::now 175 clock: unsafe { (self.clock.vtable.clone)(self.clock.data) }, 176 tick_duration: self.tick_duration, 177 name: self.name, 178 } 179 } 180} 181 182impl Drop for Clock { 183 #[inline] 184 fn drop(&mut self) { 185 // SAFETY: see Clock::now 186 unsafe { (self.clock.vtable.drop)(self.clock.data) } 187 } 188} 189 190impl fmt::Debug for Clock { 191 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 192 let vtable_ptr = self.clock.vtable as *const RawClockVTable; 193 f.debug_struct("Waker") 194 .field("name", &self.name) 195 .field("tick_duration", &self.tick_duration) 196 .field("data", &self.clock.data) 197 .field("vtable", &vtable_ptr) 198 .finish() 199 } 200} 201 202impl fmt::Display for Clock { 203 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 204 write!(f, "{}, {:?} precision", self.name, self.tick_duration) 205 } 206} 207 208// === impl RawClock === 209 210impl RawClock { 211 /// Creates a new `Clock` from the provided `data` pointer and `vtable`. 212 /// 213 /// The `data` pointer can be used to store arbitrary data as required by the clock implementation. 214 /// his could be e.g. a type-erased pointer to an `Arc` that holds private implementation-specific state. 215 /// The value of this pointer will get passed to all functions that are part 216 /// of the `vtable` as the first parameter. 217 /// 218 /// It is important to consider that the `data` pointer must point to a 219 /// thread safe type such as an `Arc`. 220 /// 221 /// The `vtable` customizes the behavior of a `Clock`. For each operation 222 /// on the `Clock`, the associated function in the `vtable` will be called. 223 #[inline] 224 #[must_use] 225 pub const fn new(data: *const (), vtable: &'static RawClockVTable) -> RawClock { 226 Self { data, vtable } 227 } 228} 229 230// === impl RawClockVTable === 231 232impl RawClockVTable { 233 pub const fn new( 234 clone: unsafe fn(*const ()) -> RawClock, 235 now: unsafe fn(*const ()) -> u64, 236 schedule_wakeup: unsafe fn(*const (), at: u64), 237 drop: unsafe fn(*const ()), 238 ) -> Self { 239 Self { 240 clone, 241 now, 242 schedule_wakeup, 243 drop, 244 } 245 } 246}