diff options
Diffstat (limited to 'embassy-executor')
| -rw-r--r-- | embassy-executor/Cargo.toml | 95 | ||||
| -rw-r--r-- | embassy-executor/README.md | 27 | ||||
| -rw-r--r-- | embassy-executor/build.rs | 92 | ||||
| -rw-r--r-- | embassy-executor/src/lib.rs | 178 |
4 files changed, 104 insertions, 288 deletions
diff --git a/embassy-executor/Cargo.toml b/embassy-executor/Cargo.toml index d6f24ce84..79d899c61 100644 --- a/embassy-executor/Cargo.toml +++ b/embassy-executor/Cargo.toml | |||
| @@ -108,98 +108,3 @@ timer-item-payload-size-2 = ["_timer-item-payload"] | |||
| 108 | timer-item-payload-size-4 = ["_timer-item-payload"] | 108 | timer-item-payload-size-4 = ["_timer-item-payload"] |
| 109 | ## 8 bytes | 109 | ## 8 bytes |
| 110 | timer-item-payload-size-8 = ["_timer-item-payload"] | 110 | timer-item-payload-size-8 = ["_timer-item-payload"] |
| 111 | |||
| 112 | #! ### Task Arena Size | ||
| 113 | #! Sets the [task arena](#task-arena) size. Necessary if you’re not using `nightly`. | ||
| 114 | #! | ||
| 115 | #! <details> | ||
| 116 | #! <summary>Preconfigured Task Arena Sizes:</summary> | ||
| 117 | #! <!-- rustdoc requires the following blank line for the feature list to render correctly! --> | ||
| 118 | #! | ||
| 119 | |||
| 120 | # BEGIN AUTOGENERATED CONFIG FEATURES | ||
| 121 | # Generated by gen_config.py. DO NOT EDIT. | ||
| 122 | ## 64 | ||
| 123 | task-arena-size-64 = [] | ||
| 124 | ## 128 | ||
| 125 | task-arena-size-128 = [] | ||
| 126 | ## 192 | ||
| 127 | task-arena-size-192 = [] | ||
| 128 | ## 256 | ||
| 129 | task-arena-size-256 = [] | ||
| 130 | ## 320 | ||
| 131 | task-arena-size-320 = [] | ||
| 132 | ## 384 | ||
| 133 | task-arena-size-384 = [] | ||
| 134 | ## 512 | ||
| 135 | task-arena-size-512 = [] | ||
| 136 | ## 640 | ||
| 137 | task-arena-size-640 = [] | ||
| 138 | ## 768 | ||
| 139 | task-arena-size-768 = [] | ||
| 140 | ## 1024 | ||
| 141 | task-arena-size-1024 = [] | ||
| 142 | ## 1280 | ||
| 143 | task-arena-size-1280 = [] | ||
| 144 | ## 1536 | ||
| 145 | task-arena-size-1536 = [] | ||
| 146 | ## 2048 | ||
| 147 | task-arena-size-2048 = [] | ||
| 148 | ## 2560 | ||
| 149 | task-arena-size-2560 = [] | ||
| 150 | ## 3072 | ||
| 151 | task-arena-size-3072 = [] | ||
| 152 | ## 4096 (default) | ||
| 153 | task-arena-size-4096 = [] # Default | ||
| 154 | ## 5120 | ||
| 155 | task-arena-size-5120 = [] | ||
| 156 | ## 6144 | ||
| 157 | task-arena-size-6144 = [] | ||
| 158 | ## 8192 | ||
| 159 | task-arena-size-8192 = [] | ||
| 160 | ## 10240 | ||
| 161 | task-arena-size-10240 = [] | ||
| 162 | ## 12288 | ||
| 163 | task-arena-size-12288 = [] | ||
| 164 | ## 16384 | ||
| 165 | task-arena-size-16384 = [] | ||
| 166 | ## 20480 | ||
| 167 | task-arena-size-20480 = [] | ||
| 168 | ## 24576 | ||
| 169 | task-arena-size-24576 = [] | ||
| 170 | ## 32768 | ||
| 171 | task-arena-size-32768 = [] | ||
| 172 | ## 40960 | ||
| 173 | task-arena-size-40960 = [] | ||
| 174 | ## 49152 | ||
| 175 | task-arena-size-49152 = [] | ||
| 176 | ## 65536 | ||
| 177 | task-arena-size-65536 = [] | ||
| 178 | ## 81920 | ||
| 179 | task-arena-size-81920 = [] | ||
| 180 | ## 98304 | ||
| 181 | task-arena-size-98304 = [] | ||
| 182 | ## 131072 | ||
| 183 | task-arena-size-131072 = [] | ||
| 184 | ## 163840 | ||
| 185 | task-arena-size-163840 = [] | ||
| 186 | ## 196608 | ||
| 187 | task-arena-size-196608 = [] | ||
| 188 | ## 262144 | ||
| 189 | task-arena-size-262144 = [] | ||
| 190 | ## 327680 | ||
| 191 | task-arena-size-327680 = [] | ||
| 192 | ## 393216 | ||
| 193 | task-arena-size-393216 = [] | ||
| 194 | ## 524288 | ||
| 195 | task-arena-size-524288 = [] | ||
| 196 | ## 655360 | ||
| 197 | task-arena-size-655360 = [] | ||
| 198 | ## 786432 | ||
| 199 | task-arena-size-786432 = [] | ||
| 200 | ## 1048576 | ||
| 201 | task-arena-size-1048576 = [] | ||
| 202 | |||
| 203 | # END AUTOGENERATED CONFIG FEATURES | ||
| 204 | |||
| 205 | #! </details> | ||
diff --git a/embassy-executor/README.md b/embassy-executor/README.md index 074c73555..85f15edbb 100644 --- a/embassy-executor/README.md +++ b/embassy-executor/README.md | |||
| @@ -3,35 +3,10 @@ | |||
| 3 | An async/await executor designed for embedded usage. | 3 | An async/await executor designed for embedded usage. |
| 4 | 4 | ||
| 5 | - No `alloc`, no heap needed. | 5 | - No `alloc`, no heap needed. |
| 6 | - With nightly Rust, task futures can be fully statically allocated. | 6 | - Tasks are statically allocated. Each task gets its own `static`, with the exact size to hold the task (or multiple instances of it, if using `pool_size`) calculated automatically at compile time. If tasks don't fit in RAM, this is detected at compile time by the linker. Runtime panics due to running out of memory are not possible. |
| 7 | - No "fixed capacity" data structures, executor works with 1 or 1000 tasks without needing config/tuning. | 7 | - No "fixed capacity" data structures, executor works with 1 or 1000 tasks without needing config/tuning. |
| 8 | - Integrated timer queue: sleeping is easy, just do `Timer::after_secs(1).await;`. | 8 | - Integrated timer queue: sleeping is easy, just do `Timer::after_secs(1).await;`. |
| 9 | - No busy-loop polling: CPU sleeps when there's no work to do, using interrupts or `WFE/SEV`. | 9 | - No busy-loop polling: CPU sleeps when there's no work to do, using interrupts or `WFE/SEV`. |
| 10 | - Efficient polling: a wake will only poll the woken task, not all of them. | 10 | - Efficient polling: a wake will only poll the woken task, not all of them. |
| 11 | - Fair: a task can't monopolize CPU time even if it's constantly being woken. All other tasks get a chance to run before a given task gets polled for the second time. | 11 | - Fair: a task can't monopolize CPU time even if it's constantly being woken. All other tasks get a chance to run before a given task gets polled for the second time. |
| 12 | - Creating multiple executor instances is supported, to run tasks with multiple priority levels. This allows higher-priority tasks to preempt lower-priority tasks. | 12 | - Creating multiple executor instances is supported, to run tasks with multiple priority levels. This allows higher-priority tasks to preempt lower-priority tasks. |
| 13 | |||
| 14 | ## Task arena | ||
| 15 | |||
| 16 | When the `nightly` Cargo feature is not enabled, `embassy-executor` allocates tasks out of an arena (a very simple bump allocator). | ||
| 17 | |||
| 18 | If the task arena gets full, the program will panic at runtime. To guarantee this doesn't happen, you must set the size to the sum of sizes of all tasks. | ||
| 19 | |||
| 20 | Tasks are allocated from the arena when spawned for the first time. If the task exits, the allocation is not released to the arena, but can be reused to spawn the task again. For multiple-instance tasks (like `#[embassy_executor::task(pool_size = 4)]`), the first spawn will allocate memory for all instances. This is done for performance and to increase predictability (for example, spawning at least 1 instance of every task at boot guarantees an immediate panic if the arena is too small, while allocating instances on-demand could delay the panic to only when the program is under load). | ||
| 21 | |||
| 22 | The arena size can be configured in two ways: | ||
| 23 | |||
| 24 | - Via Cargo features: enable a Cargo feature like `task-arena-size-8192`. Only a selection of values | ||
| 25 | is available, see [Task Area Sizes](#task-arena-size) for reference. | ||
| 26 | - Via environment variables at build time: set the variable named `EMBASSY_EXECUTOR_TASK_ARENA_SIZE`. For example | ||
| 27 | `EMBASSY_EXECUTOR_TASK_ARENA_SIZE=4321 cargo build`. You can also set them in the `[env]` section of `.cargo/config.toml`. | ||
| 28 | Any value can be set, unlike with Cargo features. | ||
| 29 | |||
| 30 | Environment variables take precedence over Cargo features. If two Cargo features are enabled for the same setting | ||
| 31 | with different values, compilation fails. | ||
| 32 | |||
| 33 | ## Statically allocating tasks | ||
| 34 | |||
| 35 | When using nightly Rust, enable the `nightly` Cargo feature. This will make `embassy-executor` use the `type_alias_impl_trait` feature to allocate all tasks in `static`s. Each task gets its own `static`, with the exact size to hold the task (or multiple instances of it, if using `pool_size`) calculated automatically at compile time. If tasks don't fit in RAM, this is detected at compile time by the linker. Runtime panics due to running out of memory are not possible. | ||
| 36 | |||
| 37 | The configured arena size is ignored, no arena is used at all. | ||
diff --git a/embassy-executor/build.rs b/embassy-executor/build.rs index 8a41d7503..37becde3e 100644 --- a/embassy-executor/build.rs +++ b/embassy-executor/build.rs | |||
| @@ -1,99 +1,7 @@ | |||
| 1 | use std::collections::HashMap; | ||
| 2 | use std::fmt::Write; | ||
| 3 | use std::path::PathBuf; | ||
| 4 | use std::{env, fs}; | ||
| 5 | |||
| 6 | #[path = "./build_common.rs"] | 1 | #[path = "./build_common.rs"] |
| 7 | mod common; | 2 | mod common; |
| 8 | 3 | ||
| 9 | static CONFIGS: &[(&str, usize)] = &[ | ||
| 10 | // BEGIN AUTOGENERATED CONFIG FEATURES | ||
| 11 | // Generated by gen_config.py. DO NOT EDIT. | ||
| 12 | ("TASK_ARENA_SIZE", 4096), | ||
| 13 | // END AUTOGENERATED CONFIG FEATURES | ||
| 14 | ]; | ||
| 15 | |||
| 16 | struct ConfigState { | ||
| 17 | value: usize, | ||
| 18 | seen_feature: bool, | ||
| 19 | seen_env: bool, | ||
| 20 | } | ||
| 21 | |||
| 22 | fn main() { | 4 | fn main() { |
| 23 | let crate_name = env::var("CARGO_PKG_NAME") | ||
| 24 | .unwrap() | ||
| 25 | .to_ascii_uppercase() | ||
| 26 | .replace('-', "_"); | ||
| 27 | |||
| 28 | // only rebuild if build.rs changed. Otherwise Cargo will rebuild if any | ||
| 29 | // other file changed. | ||
| 30 | println!("cargo:rerun-if-changed=build.rs"); | ||
| 31 | |||
| 32 | // Rebuild if config envvar changed. | ||
| 33 | for (name, _) in CONFIGS { | ||
| 34 | println!("cargo:rerun-if-env-changed={crate_name}_{name}"); | ||
| 35 | } | ||
| 36 | |||
| 37 | let mut configs = HashMap::new(); | ||
| 38 | for (name, default) in CONFIGS { | ||
| 39 | configs.insert( | ||
| 40 | *name, | ||
| 41 | ConfigState { | ||
| 42 | value: *default, | ||
| 43 | seen_env: false, | ||
| 44 | seen_feature: false, | ||
| 45 | }, | ||
| 46 | ); | ||
| 47 | } | ||
| 48 | |||
| 49 | let prefix = format!("{crate_name}_"); | ||
| 50 | for (var, value) in env::vars() { | ||
| 51 | if let Some(name) = var.strip_prefix(&prefix) { | ||
| 52 | let Some(cfg) = configs.get_mut(name) else { | ||
| 53 | panic!("Unknown env var {name}") | ||
| 54 | }; | ||
| 55 | |||
| 56 | let Ok(value) = value.parse::<usize>() else { | ||
| 57 | panic!("Invalid value for env var {name}: {value}") | ||
| 58 | }; | ||
| 59 | |||
| 60 | cfg.value = value; | ||
| 61 | cfg.seen_env = true; | ||
| 62 | } | ||
| 63 | |||
| 64 | if let Some(feature) = var.strip_prefix("CARGO_FEATURE_") { | ||
| 65 | if let Some(i) = feature.rfind('_') { | ||
| 66 | let name = &feature[..i]; | ||
| 67 | let value = &feature[i + 1..]; | ||
| 68 | if let Some(cfg) = configs.get_mut(name) { | ||
| 69 | let Ok(value) = value.parse::<usize>() else { | ||
| 70 | panic!("Invalid value for feature {name}: {value}") | ||
| 71 | }; | ||
| 72 | |||
| 73 | // envvars take priority. | ||
| 74 | if !cfg.seen_env { | ||
| 75 | if cfg.seen_feature { | ||
| 76 | panic!("multiple values set for feature {}: {} and {}", name, cfg.value, value); | ||
| 77 | } | ||
| 78 | |||
| 79 | cfg.value = value; | ||
| 80 | cfg.seen_feature = true; | ||
| 81 | } | ||
| 82 | } | ||
| 83 | } | ||
| 84 | } | ||
| 85 | } | ||
| 86 | |||
| 87 | let mut data = String::new(); | ||
| 88 | |||
| 89 | for (name, cfg) in &configs { | ||
| 90 | writeln!(&mut data, "pub const {}: usize = {};", name, cfg.value).unwrap(); | ||
| 91 | } | ||
| 92 | |||
| 93 | let out_dir = PathBuf::from(env::var_os("OUT_DIR").unwrap()); | ||
| 94 | let out_file = out_dir.join("config.rs").to_string_lossy().to_string(); | ||
| 95 | fs::write(out_file, data).unwrap(); | ||
| 96 | |||
| 97 | let mut rustc_cfgs = common::CfgSet::new(); | 5 | let mut rustc_cfgs = common::CfgSet::new(); |
| 98 | common::set_target_cfgs(&mut rustc_cfgs); | 6 | common::set_target_cfgs(&mut rustc_cfgs); |
| 99 | } | 7 | } |
diff --git a/embassy-executor/src/lib.rs b/embassy-executor/src/lib.rs index d816539ac..5485f6a6a 100644 --- a/embassy-executor/src/lib.rs +++ b/embassy-executor/src/lib.rs | |||
| @@ -50,101 +50,129 @@ pub mod raw; | |||
| 50 | mod spawner; | 50 | mod spawner; |
| 51 | pub use spawner::*; | 51 | pub use spawner::*; |
| 52 | 52 | ||
| 53 | mod config { | ||
| 54 | #![allow(unused)] | ||
| 55 | include!(concat!(env!("OUT_DIR"), "/config.rs")); | ||
| 56 | } | ||
| 57 | |||
| 58 | /// Implementation details for embassy macros. | 53 | /// Implementation details for embassy macros. |
| 59 | /// Do not use. Used for macros and HALs only. Not covered by semver guarantees. | 54 | /// Do not use. Used for macros and HALs only. Not covered by semver guarantees. |
| 60 | #[doc(hidden)] | 55 | #[doc(hidden)] |
| 61 | #[cfg(not(feature = "nightly"))] | 56 | #[cfg(not(feature = "nightly"))] |
| 62 | pub mod _export { | 57 | pub mod _export { |
| 63 | use core::alloc::Layout; | 58 | use core::cell::UnsafeCell; |
| 64 | use core::cell::{Cell, UnsafeCell}; | ||
| 65 | use core::future::Future; | 59 | use core::future::Future; |
| 66 | use core::mem::MaybeUninit; | 60 | use core::mem::MaybeUninit; |
| 67 | use core::ptr::null_mut; | ||
| 68 | |||
| 69 | use critical_section::{CriticalSection, Mutex}; | ||
| 70 | 61 | ||
| 71 | use crate::raw::TaskPool; | 62 | pub trait TaskFn<Args>: Copy { |
| 72 | 63 | type Fut: Future + 'static; | |
| 73 | struct Arena<const N: usize> { | ||
| 74 | buf: UnsafeCell<MaybeUninit<[u8; N]>>, | ||
| 75 | ptr: Mutex<Cell<*mut u8>>, | ||
| 76 | } | 64 | } |
| 77 | 65 | ||
| 78 | unsafe impl<const N: usize> Sync for Arena<N> {} | 66 | macro_rules! task_fn_impl { |
| 79 | unsafe impl<const N: usize> Send for Arena<N> {} | 67 | ($($Tn:ident),*) => { |
| 80 | 68 | impl<F, Fut, $($Tn,)*> TaskFn<($($Tn,)*)> for F | |
| 81 | impl<const N: usize> Arena<N> { | 69 | where |
| 82 | const fn new() -> Self { | 70 | F: Copy + FnOnce($($Tn,)*) -> Fut, |
| 83 | Self { | 71 | Fut: Future + 'static, |
| 84 | buf: UnsafeCell::new(MaybeUninit::uninit()), | 72 | { |
| 85 | ptr: Mutex::new(Cell::new(null_mut())), | 73 | type Fut = Fut; |
| 86 | } | ||
| 87 | } | ||
| 88 | |||
| 89 | fn alloc<T>(&'static self, cs: CriticalSection) -> &'static mut MaybeUninit<T> { | ||
| 90 | let layout = Layout::new::<T>(); | ||
| 91 | |||
| 92 | let start = self.buf.get().cast::<u8>(); | ||
| 93 | let end = unsafe { start.add(N) }; | ||
| 94 | |||
| 95 | let mut ptr = self.ptr.borrow(cs).get(); | ||
| 96 | if ptr.is_null() { | ||
| 97 | ptr = self.buf.get().cast::<u8>(); | ||
| 98 | } | ||
| 99 | |||
| 100 | let bytes_left = (end as usize) - (ptr as usize); | ||
| 101 | let align_offset = (ptr as usize).next_multiple_of(layout.align()) - (ptr as usize); | ||
| 102 | |||
| 103 | if align_offset + layout.size() > bytes_left { | ||
| 104 | panic!("embassy-executor: task arena is full. You must increase the arena size, see the documentation for details: https://docs.embassy.dev/embassy-executor/"); | ||
| 105 | } | 74 | } |
| 75 | }; | ||
| 76 | } | ||
| 106 | 77 | ||
| 107 | let res = unsafe { ptr.add(align_offset) }; | 78 | task_fn_impl!(); |
| 108 | let ptr = unsafe { ptr.add(align_offset + layout.size()) }; | 79 | task_fn_impl!(T0); |
| 80 | task_fn_impl!(T0, T1); | ||
| 81 | task_fn_impl!(T0, T1, T2); | ||
| 82 | task_fn_impl!(T0, T1, T2, T3); | ||
| 83 | task_fn_impl!(T0, T1, T2, T3, T4); | ||
| 84 | task_fn_impl!(T0, T1, T2, T3, T4, T5); | ||
| 85 | task_fn_impl!(T0, T1, T2, T3, T4, T5, T6); | ||
| 86 | task_fn_impl!(T0, T1, T2, T3, T4, T5, T6, T7); | ||
| 87 | task_fn_impl!(T0, T1, T2, T3, T4, T5, T6, T7, T8); | ||
| 88 | task_fn_impl!(T0, T1, T2, T3, T4, T5, T6, T7, T8, T9); | ||
| 89 | task_fn_impl!(T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10); | ||
| 90 | task_fn_impl!(T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11); | ||
| 91 | task_fn_impl!(T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12); | ||
| 92 | task_fn_impl!(T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13); | ||
| 93 | task_fn_impl!(T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14); | ||
| 94 | task_fn_impl!(T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15); | ||
| 95 | |||
| 96 | #[allow(private_bounds)] | ||
| 97 | #[repr(C)] | ||
| 98 | pub struct TaskPoolHolder<const SIZE: usize, const ALIGN: usize> | ||
| 99 | where | ||
| 100 | Align<ALIGN>: Alignment, | ||
| 101 | { | ||
| 102 | data: UnsafeCell<[MaybeUninit<u8>; SIZE]>, | ||
| 103 | align: Align<ALIGN>, | ||
| 104 | } | ||
| 109 | 105 | ||
| 110 | self.ptr.borrow(cs).set(ptr); | 106 | unsafe impl<const SIZE: usize, const ALIGN: usize> Send for TaskPoolHolder<SIZE, ALIGN> where Align<ALIGN>: Alignment {} |
| 107 | unsafe impl<const SIZE: usize, const ALIGN: usize> Sync for TaskPoolHolder<SIZE, ALIGN> where Align<ALIGN>: Alignment {} | ||
| 111 | 108 | ||
| 112 | unsafe { &mut *(res as *mut MaybeUninit<T>) } | 109 | #[allow(private_bounds)] |
| 110 | impl<const SIZE: usize, const ALIGN: usize> TaskPoolHolder<SIZE, ALIGN> | ||
| 111 | where | ||
| 112 | Align<ALIGN>: Alignment, | ||
| 113 | { | ||
| 114 | pub const fn get(&self) -> *const u8 { | ||
| 115 | self.data.get().cast() | ||
| 113 | } | 116 | } |
| 114 | } | 117 | } |
| 115 | 118 | ||
| 116 | static ARENA: Arena<{ crate::config::TASK_ARENA_SIZE }> = Arena::new(); | 119 | #[allow(private_bounds)] |
| 120 | #[repr(transparent)] | ||
| 121 | pub struct Align<const N: usize>([<Self as Alignment>::Archetype; 0]) | ||
| 122 | where | ||
| 123 | Self: Alignment; | ||
| 117 | 124 | ||
| 118 | pub struct TaskPoolRef { | 125 | trait Alignment { |
| 119 | // type-erased `&'static mut TaskPool<F, N>` | 126 | /// A zero-sized type of particular alignment. |
| 120 | // Needed because statics can't have generics. | 127 | type Archetype: Copy + Eq + PartialEq + Send + Sync + Unpin; |
| 121 | ptr: Mutex<Cell<*mut ()>>, | ||
| 122 | } | 128 | } |
| 123 | unsafe impl Sync for TaskPoolRef {} | ||
| 124 | unsafe impl Send for TaskPoolRef {} | ||
| 125 | |||
| 126 | impl TaskPoolRef { | ||
| 127 | pub const fn new() -> Self { | ||
| 128 | Self { | ||
| 129 | ptr: Mutex::new(Cell::new(null_mut())), | ||
| 130 | } | ||
| 131 | } | ||
| 132 | 129 | ||
| 133 | /// Get the pool for this ref, allocating it from the arena the first time. | 130 | macro_rules! aligns { |
| 134 | /// | 131 | ($($AlignX:ident: $n:literal,)*) => { |
| 135 | /// safety: for a given TaskPoolRef instance, must always call with the exact | 132 | $( |
| 136 | /// same generic params. | 133 | #[derive(Copy, Clone, Eq, PartialEq)] |
| 137 | pub unsafe fn get<F: Future, const N: usize>(&'static self) -> &'static TaskPool<F, N> { | 134 | #[repr(align($n))] |
| 138 | critical_section::with(|cs| { | 135 | struct $AlignX {} |
| 139 | let ptr = self.ptr.borrow(cs); | 136 | impl Alignment for Align<$n> { |
| 140 | if ptr.get().is_null() { | 137 | type Archetype = $AlignX; |
| 141 | let pool = ARENA.alloc::<TaskPool<F, N>>(cs); | ||
| 142 | pool.write(TaskPool::new()); | ||
| 143 | ptr.set(pool as *mut _ as _); | ||
| 144 | } | 138 | } |
| 145 | 139 | )* | |
| 146 | unsafe { &*(ptr.get() as *const _) } | 140 | }; |
| 147 | }) | ||
| 148 | } | ||
| 149 | } | 141 | } |
| 142 | |||
| 143 | aligns!( | ||
| 144 | Align1: 1, | ||
| 145 | Align2: 2, | ||
| 146 | Align4: 4, | ||
| 147 | Align8: 8, | ||
| 148 | Align16: 16, | ||
| 149 | Align32: 32, | ||
| 150 | Align64: 64, | ||
| 151 | Align128: 128, | ||
| 152 | Align256: 256, | ||
| 153 | Align512: 512, | ||
| 154 | Align1024: 1024, | ||
| 155 | Align2048: 2048, | ||
| 156 | Align4096: 4096, | ||
| 157 | Align8192: 8192, | ||
| 158 | Align16384: 16384, | ||
| 159 | ); | ||
| 160 | #[cfg(any(target_pointer_width = "32", target_pointer_width = "64"))] | ||
| 161 | aligns!( | ||
| 162 | Align32768: 32768, | ||
| 163 | Align65536: 65536, | ||
| 164 | Align131072: 131072, | ||
| 165 | Align262144: 262144, | ||
| 166 | Align524288: 524288, | ||
| 167 | Align1048576: 1048576, | ||
| 168 | Align2097152: 2097152, | ||
| 169 | Align4194304: 4194304, | ||
| 170 | Align8388608: 8388608, | ||
| 171 | Align16777216: 16777216, | ||
| 172 | Align33554432: 33554432, | ||
| 173 | Align67108864: 67108864, | ||
| 174 | Align134217728: 134217728, | ||
| 175 | Align268435456: 268435456, | ||
| 176 | Align536870912: 536870912, | ||
| 177 | ); | ||
| 150 | } | 178 | } |
