Stop using #[thread_local] on x86_*.
This commit is contained in:
+1
-2
@@ -1,7 +1,6 @@
|
||||
use alloc::sync::Arc;
|
||||
use alloc::collections::BTreeMap;
|
||||
use core::{iter, mem};
|
||||
use core::sync::atomic::Ordering;
|
||||
|
||||
use spin::RwLock;
|
||||
|
||||
@@ -39,7 +38,7 @@ impl ContextList {
|
||||
|
||||
/// Get the current context.
|
||||
pub fn current(&self) -> Option<&Arc<RwLock<Context>>> {
|
||||
self.map.get(&super::CONTEXT_ID.load(Ordering::SeqCst))
|
||||
self.map.get(&super::context_id())
|
||||
}
|
||||
|
||||
pub fn iter(&self) -> ::alloc::collections::btree_map::Iter<ContextId, Arc<RwLock<Context>>> {
|
||||
|
||||
+6
-12
@@ -1,7 +1,6 @@
|
||||
//! # Context management
|
||||
//!
|
||||
//! For resources on contexts, please consult [wikipedia](https://en.wikipedia.org/wiki/Context_switch) and [osdev](https://wiki.osdev.org/Context_Switching)
|
||||
use core::sync::atomic::Ordering;
|
||||
|
||||
use alloc::borrow::Cow;
|
||||
use alloc::sync::Arc;
|
||||
@@ -9,6 +8,7 @@ use alloc::sync::Arc;
|
||||
use spin::{RwLock, RwLockReadGuard, RwLockWriteGuard};
|
||||
|
||||
use crate::paging::{RmmA, RmmArch, TableKind};
|
||||
use crate::percpu::PercpuBlock;
|
||||
use crate::syscall::error::{Error, ESRCH, Result};
|
||||
|
||||
pub use self::context::{BorrowedHtBuf, Context, ContextId, ContextSnapshot, Status, WaitpidKey};
|
||||
@@ -59,9 +59,6 @@ pub const CONTEXT_MAX_FILES: usize = 65_536;
|
||||
/// Contexts list
|
||||
static CONTEXTS: RwLock<ContextList> = RwLock::new(ContextList::new());
|
||||
|
||||
#[thread_local]
|
||||
static CONTEXT_ID: context::AtomicContextId = context::AtomicContextId::default();
|
||||
|
||||
pub use self::arch::empty_cr3;
|
||||
|
||||
pub fn init() {
|
||||
@@ -77,7 +74,10 @@ pub fn init() {
|
||||
context.status = Status::Runnable;
|
||||
context.running = true;
|
||||
context.cpu_id = Some(crate::cpu_id());
|
||||
CONTEXT_ID.store(context.id, Ordering::SeqCst);
|
||||
|
||||
unsafe {
|
||||
PercpuBlock::current().switch_internals.set_context_id(context.id);
|
||||
}
|
||||
}
|
||||
|
||||
/// Get the global schemes list, const
|
||||
@@ -91,13 +91,7 @@ pub fn contexts_mut() -> RwLockWriteGuard<'static, ContextList> {
|
||||
}
|
||||
|
||||
pub fn context_id() -> ContextId {
|
||||
// Thread local variables can and should only be modified using Relaxed. This is to prevent a
|
||||
// hardware thread from racing with itself, for example if there is an interrupt. Orderings
|
||||
// stronger than Relaxed are only necessary for inter-processor synchronization.
|
||||
let id = CONTEXT_ID.load(Ordering::Relaxed);
|
||||
// Prevent the compiler from reordering subsequent loads and stores to before this load.
|
||||
core::sync::atomic::compiler_fence(Ordering::Acquire);
|
||||
id
|
||||
PercpuBlock::current().switch_internals.context_id()
|
||||
}
|
||||
|
||||
pub fn current() -> Result<Arc<RwLock<Context>>> {
|
||||
|
||||
+33
-15
@@ -7,13 +7,15 @@ use alloc::sync::Arc;
|
||||
use spin::{RwLock, RwLockWriteGuard};
|
||||
|
||||
use crate::context::signal::signal_handler;
|
||||
use crate::context::{arch, contexts, Context, CONTEXT_ID};
|
||||
#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
|
||||
use crate::context::{arch, contexts, Context};
|
||||
use crate::gdt;
|
||||
use crate::interrupt;
|
||||
use crate::percpu::PercpuBlock;
|
||||
use crate::ptrace;
|
||||
use crate::time;
|
||||
|
||||
use super::ContextId;
|
||||
|
||||
unsafe fn update_runnable(context: &mut Context, cpu_id: usize) -> bool {
|
||||
// Ignore already running contexts
|
||||
if context.running {
|
||||
@@ -87,16 +89,12 @@ struct SwitchResult {
|
||||
next_lock: Arc<RwLock<Context>>,
|
||||
}
|
||||
|
||||
#[thread_local]
|
||||
static SWITCH_RESULT: Cell<Option<SwitchResult>> = Cell::new(None);
|
||||
|
||||
//resets to 0 in context::switch()
|
||||
#[thread_local]
|
||||
pub static PIT_TICKS: Cell<usize> = Cell::new(0);
|
||||
|
||||
pub fn tick() {
|
||||
let new_ticks = PIT_TICKS.get() + 1;
|
||||
PIT_TICKS.set(new_ticks);
|
||||
let ticks_cell = &PercpuBlock::current().switch_internals.pit_ticks;
|
||||
|
||||
let new_ticks = ticks_cell.get() + 1;
|
||||
ticks_cell.set(new_ticks);
|
||||
|
||||
// Switch after 3 ticks (about 6.75 ms)
|
||||
if new_ticks >= 3 {
|
||||
@@ -105,7 +103,7 @@ pub fn tick() {
|
||||
}
|
||||
|
||||
pub unsafe extern "C" fn switch_finish_hook() {
|
||||
if let Some(SwitchResult { prev_lock, next_lock }) = SWITCH_RESULT.take() {
|
||||
if let Some(SwitchResult { prev_lock, next_lock }) = PercpuBlock::current().switch_internals.switch_result.take() {
|
||||
prev_lock.force_write_unlock();
|
||||
next_lock.force_write_unlock();
|
||||
} else {
|
||||
@@ -121,11 +119,13 @@ pub unsafe extern "C" fn switch_finish_hook() {
|
||||
///
|
||||
/// Do not call this while holding locks!
|
||||
pub unsafe fn switch() -> bool {
|
||||
// TODO: Better memory orderings?
|
||||
let percpu = PercpuBlock::current();
|
||||
|
||||
//set PIT Interrupt counter to 0, giving each process same amount of PIT ticks
|
||||
PIT_TICKS.set(0);
|
||||
percpu.switch_internals.pit_ticks.set(0);
|
||||
|
||||
// Set the global lock to avoid the unsafe operations below from causing issues
|
||||
// TODO: Better memory orderings?
|
||||
while arch::CONTEXT_SWITCH_LOCK.compare_exchange_weak(false, true, Ordering::SeqCst, Ordering::Relaxed).is_err() {
|
||||
interrupt::pause();
|
||||
}
|
||||
@@ -190,7 +190,8 @@ pub unsafe fn switch() -> bool {
|
||||
gdt::set_tss_stack(stack.as_ptr() as usize + stack.len());
|
||||
}
|
||||
}
|
||||
CONTEXT_ID.store(next_context.id, Ordering::SeqCst);
|
||||
let percpu = PercpuBlock::current();
|
||||
percpu.switch_internals.context_id.set(next_context.id);
|
||||
|
||||
if next_context.ksig.is_none() {
|
||||
//TODO: Allow nested signals
|
||||
@@ -204,7 +205,7 @@ pub unsafe fn switch() -> bool {
|
||||
}
|
||||
}
|
||||
|
||||
SWITCH_RESULT.set(Some(SwitchResult {
|
||||
percpu.switch_internals.switch_result.set(Some(SwitchResult {
|
||||
prev_lock: prev_context_lock,
|
||||
next_lock: next_context_lock,
|
||||
}));
|
||||
@@ -223,3 +224,20 @@ pub unsafe fn switch() -> bool {
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Default)]
|
||||
pub struct ContextSwitchPercpu {
|
||||
switch_result: Cell<Option<SwitchResult>>,
|
||||
pit_ticks: Cell<usize>,
|
||||
|
||||
/// Unique ID of the currently running context.
|
||||
context_id: Cell<ContextId>,
|
||||
}
|
||||
impl ContextSwitchPercpu {
|
||||
pub fn context_id(&self) -> ContextId {
|
||||
self.context_id.get()
|
||||
}
|
||||
pub unsafe fn set_context_id(&self, new: ContextId) {
|
||||
self.context_id.set(new)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user