Add support for CLS variables with user-defined types#1024
Merged
kevinaboos merged 8 commits intotheseus-os:theseus_mainfrom Aug 4, 2023
Merged
Add support for CLS variables with user-defined types#1024kevinaboos merged 8 commits intotheseus-os:theseus_mainfrom
kevinaboos merged 8 commits intotheseus-os:theseus_mainfrom
Conversation
Signed-off-by: Klimenty Tsoutsman <klim@tsoutsman.com>
Signed-off-by: Klimenty Tsoutsman <klim@tsoutsman.com>
Signed-off-by: Klimenty Tsoutsman <klim@tsoutsman.com>
kevinaboos
requested changes
Aug 3, 2023
Member
kevinaboos
left a comment
There was a problem hiding this comment.
Very nice! love the API and design decisions. I left a few comments, mostly questions and nitpicky shit.
Signed-off-by: Klimenty Tsoutsman <klim@tsoutsman.com>
Signed-off-by: Klimenty Tsoutsman <klim@tsoutsman.com>
Signed-off-by: Klimenty Tsoutsman <klim@tsoutsman.com>
Signed-off-by: Klimenty Tsoutsman <klim@tsoutsman.com>
kevinaboos
approved these changes
Aug 4, 2023
Member
kevinaboos
left a comment
There was a problem hiding this comment.
Looks great, thanks as always! Tested and working for me.
github-actions bot
pushed a commit
that referenced
this pull request
Aug 4, 2023
* The `cpu_local` macro now generates four functions for user-defined types:
```rust
pub fn replace(&self, value: #ty) -> #ty;
pub fn replace_guarded<G>(&self, mut value: #ty, guard: &G) -> #ty
where
G: CpuAtomicGuard
pub fn set(&self, value: #ty);
pub fn set_guarded<G>(&self, mut value: #ty, guard: &G)
where
G: CpuAtomicGuard
```
* The new `CpuAtomicGuard` trait is sealed, but implemented for
`preemption::PreemptionGuard` and `irq_safety::HeldInterrupts`.
Passing a reference to one of those guard types into either `set_guarded()`
or `replace_guarded()` can efficiently ensure that either preemption or
interrupts are disabled, meaning that the CPU-local variable can be
safely accessed in an atomic manner across multiple assembly instructions.
* However, this doesn't cover all use cases, so we also add two optional
arguments to the `cpu_local` macro:
1. `cls_dep`: a boolean that defaults to true, but can be set to false to
prevent the macro from generating functions that depend on `cls`.
This is only used by the `preemption` crate to avoid a circular dependency.
2. `stores_guard`: accepts a type denoting that the CLS variable stores an
`Option<impl cls::CpuAtomicGuard>`, such as the task switch preemption
guard. This argument modifies the signatures of `replace` and `set` to accept
the guard type by value, because the guard type obviates the need to pass in
a reference to another redundant guard (normally used to ensure atomicity).
Signed-off-by: Klimenty Tsoutsman <klim@tsoutsman.com> 8209f16
github-actions bot
pushed a commit
to tsoutsman/Theseus
that referenced
this pull request
Aug 4, 2023
* The `cpu_local` macro now generates four functions for user-defined types:
```rust
pub fn replace(&self, value: #ty) -> #ty;
pub fn replace_guarded<G>(&self, mut value: #ty, guard: &G) -> #ty
where
G: CpuAtomicGuard
pub fn set(&self, value: #ty);
pub fn set_guarded<G>(&self, mut value: #ty, guard: &G)
where
G: CpuAtomicGuard
```
* The new `CpuAtomicGuard` trait is sealed, but implemented for
`preemption::PreemptionGuard` and `irq_safety::HeldInterrupts`.
Passing a reference to one of those guard types into either `set_guarded()`
or `replace_guarded()` can efficiently ensure that either preemption or
interrupts are disabled, meaning that the CPU-local variable can be
safely accessed in an atomic manner across multiple assembly instructions.
* However, this doesn't cover all use cases, so we also add two optional
arguments to the `cpu_local` macro:
1. `cls_dep`: a boolean that defaults to true, but can be set to false to
prevent the macro from generating functions that depend on `cls`.
This is only used by the `preemption` crate to avoid a circular dependency.
2. `stores_guard`: accepts a type denoting that the CLS variable stores an
`Option<impl cls::CpuAtomicGuard>`, such as the task switch preemption
guard. This argument modifies the signatures of `replace` and `set` to accept
the guard type by value, because the guard type obviates the need to pass in
a reference to another redundant guard (normally used to ensure atomicity).
Signed-off-by: Klimenty Tsoutsman <klim@tsoutsman.com> 8209f16
tsoutsman
added a commit
to tsoutsman/Theseus
that referenced
this pull request
Sep 6, 2023
* The `cpu_local` macro now generates four functions for user-defined types:
```rust
pub fn replace(&self, value: #ty) -> #ty;
pub fn replace_guarded<G>(&self, mut value: #ty, guard: &G) -> #ty
where
G: CpuAtomicGuard
pub fn set(&self, value: #ty);
pub fn set_guarded<G>(&self, mut value: #ty, guard: &G)
where
G: CpuAtomicGuard
```
* The new `CpuAtomicGuard` trait is sealed, but implemented for
`preemption::PreemptionGuard` and `irq_safety::HeldInterrupts`.
Passing a reference to one of those guard types into either `set_guarded()`
or `replace_guarded()` can efficiently ensure that either preemption or
interrupts are disabled, meaning that the CPU-local variable can be
safely accessed in an atomic manner across multiple assembly instructions.
* However, this doesn't cover all use cases, so we also add two optional
arguments to the `cpu_local` macro:
1. `cls_dep`: a boolean that defaults to true, but can be set to false to
prevent the macro from generating functions that depend on `cls`.
This is only used by the `preemption` crate to avoid a circular dependency.
2. `stores_guard`: accepts a type denoting that the CLS variable stores an
`Option<impl cls::CpuAtomicGuard>`, such as the task switch preemption
guard. This argument modifies the signatures of `replace` and `set` to accept
the guard type by value, because the guard type obviates the need to pass in
a reference to another redundant guard (normally used to ensure atomicity).
Signed-off-by: Klimenty Tsoutsman <klim@tsoutsman.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
The
cpu_localmacro now generates four functions for user-defined types:cls::Guardis implemented forpreemption::PreemptionGuardandirq_safety::HeldInterrupts. Passing a reference ensures that one or the other is disabled and so it is safe to access the CLS variable across multiple assembly instructions.However, this doesn't work for all use cases so the PR also adds two optional args to the
cpu_localmacro:cls_dep: Prevents generating functions that depend oncls. Used by thepreemptioncrate to avoid a circular dependency.stores_guard: Used for CLS variables that store anOption<impl cls::Guard>(i.e.TASK_SWITCH_PREEMPTION_GUARD). Modifies the signatures ofreplaceandset:Pain points
cpu_localwill generate a different API for integers, custom-types, andOption<impl cls::Guard>which can cause some confusion. In practice this shouldn't be a major problem becauseOption<impl cls::Guard>is a niche workaround used for a specific CLS variable, andcargo docworks as you'd expect, but still... Currently, the macro isn't actually necessary as we could recreate all of the functionality usingCpuLocalU*/CpuLocalCelltypes which would dramatically improve the unpredictable API. But (I'm pretty sure) the macro is necessary for when we implement dynamic CLS sections so there's no point removing it now.