-
-
Notifications
You must be signed in to change notification settings - Fork 179
Implement basic per-CPU / CPU-local storage #917
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've proposed a slightly different API that would decrease the amount of unsafe syncing we have to do between PerCpuData
and FixedCpuLocal
.
Just to make sure we're on the same page gs
is a register that isn't used in regular code and so we can use it for a different purpose right?
Correct, the GS segment register is unused and is frequently used for CPU-local storage on x86. It's similar to how the FS segment register is used for thread-local storage. |
@tsoutsman I attempted a few different ways to use traits in the static PREEMPTION_COUNT: CpuLocal<CpuLocalPreemptionCount<PreemptionCount>> = unsafe { CpuLocal::new() }; The only other option I was able to get to work was to parameterize the pub trait CpuLocalVariable<T: Sized> { ... } which works, but you then need to have both pub struct CpuLocal<T: Sized, V: CpuLocalVariable<T>> {
_typ: PhantomData<T>,
_var: PhantomData<V<T>>,
}
impl<T: Sized, V: CpuLocalVariable<T>> CpuLocal<T, V> {
pub const unsafe fn new(_variable_marker: V) -> Self {
Self { _typ: PhantomData, _var: PhantomData }
} This is clearer but ergonomically worse, as you have to declare/instantiate it like so: static PREEMPTION_COUNT: CpuLocal<PreemptionCount, CpuLocalVariable<PreemptionCount>> = unsafe { CpuLocal::new(CpuLocalPreemptionCount) }; If you have any ideas on how to further simplify this, please do let me know. |
Signed-off-by: Klim Tsoutsman <[email protected]>
Apologies force push was because I pushed to the wrong remote repo. Here's a quick enum implementation I made: It removes size and alignment from |
right but that introduces a circular dependency hmm we could have the Field impls in the crated where the type is defined e.g. cpu for CpuId |
Thanks, that enum impl is similar to what I tried, but the addition of the unsafe trait with its associated const does help. I was trying to avoid an unsafe trait -- i wonder if there's a clever way to prevent other crates from implementing the
This is fine, but we should impl Deref+DerefMut on those wrappers so the crates that use
Yeah, i don't really have any other ideas for workarounds here, so I think this is fine. But we should expose it via a macro like I suppose you could also define a proc_macro that would implement hidden traits for a cpu-local type, but that might be too complex right now. My future idea for TLS-style CPU locals incorporates proc_macros for custom attributes, but we can discuss that later. Finally, you left this comment, which I agree with, but yes that's one of the many reasons why
|
Thanks, I have merged/included that commit into this PR branch, and am going from there.
Working on this now. I've also addressed some naming issues. Will re-request a review from you when done. |
that define the inner type being wrapped. * CpuId is a special case. * We can't yet impl CpuLocalField for PreemptionCount, as that requires merging the `cpu_local` and `preemption` crates.
Made the changes, thanks for the suggestion. Though not included in this changeset, I confirmed it's possible to instantiate a CPU-local task type, i.e., this works: static TASK_SWITCH_PREEMPTION_GUARD: cpu_local::CpuLocal<TaskSwitchPreemptionGuard> = cpu_local::CpuLocal::new(PerCpuField::TaskSwitchPreemptionGuard);
pub fn test_me() -> Option<PreemptionGuard> {
TASK_SWITCH_PREEMPTION_GUARD.with_mut(|t| t.0.take())
} see my latest commit msg for other details |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
One small doc change.
Co-authored-by: Klim Tsoutsman <[email protected]>
* Only supported on x86_64 currently; aarch64 support to come. * x86_64 implementation is based on the GS segment register and the GsBase MSR, as typically used on other OSes. * Tested working, but not yet used anywhere in Theseus. Co-authored-by: Klim Tsoutsman <[email protected]> fd5081a
* Only supported on x86_64 currently; aarch64 support to come. * x86_64 implementation is based on the GS segment register and the GsBase MSR, as typically used on other OSes. * Tested working, but not yet used anywhere in Theseus. Co-authored-by: Klim Tsoutsman <[email protected]> fd5081a
Reminder: remove temp tests and log statements before merging