Implement basic per-CPU / CPU-local storage#917
Implement basic per-CPU / CPU-local storage#917kevinaboos merged 15 commits intotheseus-os:theseus_mainfrom
Conversation
tsoutsman
left a comment
There was a problem hiding this comment.
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. |
|
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 |
* 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 <klim@tsoutsman.com> 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 <klim@tsoutsman.com> fd5081a
Reminder: remove temp tests and log statements before merging