0.3.0: converge kernel onto upstream master
- Rebase all Red Bear kernel changes onto upstream master (4d5d36d4).
- Update version to 0.5.12+rb0.3.0 and add Red Bear author attribution.
- Switch redox_syscall direct dependency to local fork path (../syscall).
- Bump rust-toolchain.toml to nightly-2026-05-24.
- Regenerate Cargo.lock for +rb0.3.0 suffixes and path deps.
This commit is contained in:
+112
-304
@@ -4,24 +4,20 @@
|
||||
|
||||
use crate::{
|
||||
context::{
|
||||
self, arch, idle_contexts, idle_contexts_try, memory::AddrSpaceSwitchReadGuard,
|
||||
run_contexts, ArcContextLockWriteGuard, Context, ContextLock, WeakContextRef,
|
||||
self, arch, idle_contexts, idle_contexts_try, run_contexts, ArcContextLockWriteGuard,
|
||||
Context, ContextLock, WeakContextRef,
|
||||
},
|
||||
cpu_set::LogicalCpuId,
|
||||
cpu_stats::{self, CpuState},
|
||||
percpu::PercpuBlock,
|
||||
sync::{ArcRwLockWriteGuard, CleanLockToken, L4},
|
||||
};
|
||||
use alloc::sync::Arc;
|
||||
use alloc::{sync::Arc, vec::Vec};
|
||||
use core::{
|
||||
cell::{Cell, RefCell},
|
||||
cmp::Reverse,
|
||||
hint, matches, mem,
|
||||
option::Option::{None, Some},
|
||||
hint, mem,
|
||||
sync::atomic::Ordering,
|
||||
u64,
|
||||
};
|
||||
use smallvec::SmallVec;
|
||||
use syscall::PtraceFlags;
|
||||
|
||||
enum UpdateResult {
|
||||
@@ -30,18 +26,13 @@ enum UpdateResult {
|
||||
Blocked,
|
||||
}
|
||||
|
||||
// A simple geometric series where value[i] ~= value[i + 1] * 1.25
|
||||
// A simple geometric series where value[i] ~= value[i - 1] * 1.25
|
||||
const SCHED_PRIO_TO_WEIGHT: [usize; 40] = [
|
||||
88761, 71755, 56483, 46273, 36291, 29154, 23254, 18705, 14949, 11916, 9548, 7620, 6100, 4904,
|
||||
3906, 3121, 2501, 1991, 1586, 1277, 1024, 820, 655, 526, 423, 335, 272, 215, 172, 137, 110, 87,
|
||||
70, 56, 45, 36, 29, 23, 18, 15,
|
||||
];
|
||||
|
||||
const SCALE: u128 = 1 << 40;
|
||||
const TICK_INTERVAL: u64 = 3; // Approx 6.75 ms
|
||||
const BASE_SLICE_TICKS: u64 = TICK_INTERVAL * 3; // Approx 20.25 ms
|
||||
const NANOS_PER_TICK: u128 = 2_250_000; // 2.25 ms
|
||||
|
||||
/// Determines if a given context is eligible to be scheduled on a given CPU (in
|
||||
/// principle, the current CPU).
|
||||
///
|
||||
@@ -105,9 +96,7 @@ pub fn tick(token: &mut CleanLockToken) {
|
||||
ticks_cell.set(new_ticks);
|
||||
|
||||
// Trigger a context switch after every 3 ticks (approx. 6.75 ms).
|
||||
if new_ticks >= TICK_INTERVAL as usize
|
||||
&& arch::CONTEXT_SWITCH_LOCK.load(Ordering::Relaxed) == false
|
||||
{
|
||||
if new_ticks >= 3 {
|
||||
switch(token);
|
||||
crate::context::signal::signal_handler(token);
|
||||
}
|
||||
@@ -187,68 +176,14 @@ pub fn switch(token: &mut CleanLockToken) -> SwitchResult {
|
||||
|
||||
// Alarm (previously in update_runnable)
|
||||
let wakeups = wakeup_contexts(token, switch_time);
|
||||
let wakeups_len = wakeups.len();
|
||||
let mut push_idle: SmallVec<[WeakContextRef; 16]> = SmallVec::new();
|
||||
|
||||
if wakeups_len > 0 {
|
||||
if wakeups.len() > 0 {
|
||||
let mut run_contexts = run_contexts(token.token());
|
||||
|
||||
for context_ref in wakeups {
|
||||
let Some(context_lock) = context_ref.upgrade() else {
|
||||
continue;
|
||||
};
|
||||
|
||||
let Some(mut guard) = (unsafe { context_lock.try_write_arc() }) else {
|
||||
push_idle.push(context_ref);
|
||||
continue;
|
||||
};
|
||||
|
||||
let new_vtime = guard.vtime.max(run_contexts.v);
|
||||
guard.vtime = new_vtime;
|
||||
|
||||
let weight = SCHED_PRIO_TO_WEIGHT[guard.prio] as u64;
|
||||
let scaled_slice = (BASE_SLICE_TICKS as u128 * SCALE) / weight as u128;
|
||||
|
||||
if !guard.is_active {
|
||||
guard.is_active = true;
|
||||
run_contexts.total_weight += weight;
|
||||
}
|
||||
|
||||
guard.vd = new_vtime + scaled_slice as u64;
|
||||
guard.rem_slice = BASE_SLICE_TICKS * SCALE as u64;
|
||||
let key = (guard.vd, Reverse(guard.rem_slice), guard.debug_id);
|
||||
guard.queue_key = Some(key);
|
||||
drop(guard);
|
||||
|
||||
run_contexts
|
||||
.queue
|
||||
.insert(key, (new_vtime, weight, context_ref));
|
||||
for (prio, context_lock) in wakeups {
|
||||
run_contexts.set[prio].push_back(context_lock);
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
let mut idle_list = idle_contexts(token.downgrade());
|
||||
for context_ref in push_idle {
|
||||
idle_list.push_back(context_ref);
|
||||
}
|
||||
}
|
||||
|
||||
/* // uncomment to debug contexts count
|
||||
let cpu_count = crate::cpu_count() as usize;
|
||||
let len_idle = idle_contexts(token.downgrade()).len();
|
||||
let all_contexts = context::contexts(token.downgrade())
|
||||
.len()
|
||||
.saturating_sub(cpu_count); // ignore kmain
|
||||
print!(
|
||||
"\r TIME {}.{} IDLE {} WAKEUPS {} ALL {} ",
|
||||
switch_time / 1000_000_000,
|
||||
(switch_time / 100_000_000) % 10,
|
||||
len_idle,
|
||||
wakeups_len,
|
||||
all_contexts
|
||||
);
|
||||
*/
|
||||
|
||||
let cpu_id = crate::cpu_id();
|
||||
|
||||
// Update per-cpu times
|
||||
@@ -257,19 +192,21 @@ pub fn switch(token: &mut CleanLockToken) -> SwitchResult {
|
||||
let was_idle = percpu.stats.add_time(percpu_ms) == CpuState::Idle as u8;
|
||||
percpu.switch_internals.switch_time.set(switch_time);
|
||||
|
||||
let switch_context_opt = select_next_context(
|
||||
let switch_context_opt = match select_next_context(
|
||||
token,
|
||||
percpu,
|
||||
cpu_id,
|
||||
switch_time,
|
||||
percpu_nanos,
|
||||
was_idle,
|
||||
&mut prev_context_guard,
|
||||
);
|
||||
) {
|
||||
Ok(opt) => opt,
|
||||
Err(early_ret) => return early_ret,
|
||||
};
|
||||
|
||||
// Switch process states, TSS stack pointer, and store new context ID
|
||||
match switch_context_opt {
|
||||
Some((mut next_context_guard, addr_space_guard)) => {
|
||||
Some(mut next_context_guard) => {
|
||||
// Update context states and prepare for the switch.
|
||||
let prev_context = &mut *prev_context_guard;
|
||||
let next_context = &mut *next_context_guard;
|
||||
@@ -329,14 +266,6 @@ pub fn switch(token: &mut CleanLockToken) -> SwitchResult {
|
||||
prev_context.inside_syscall =
|
||||
percpu.inside_syscall.replace(next_context.inside_syscall);
|
||||
|
||||
#[cfg(feature = "profiling")]
|
||||
{
|
||||
percpu
|
||||
.switch_internals
|
||||
.current_dbg_id
|
||||
.store(next_context.debug_id, Ordering::Relaxed);
|
||||
}
|
||||
|
||||
#[cfg(feature = "syscall_debug")]
|
||||
{
|
||||
prev_context.syscall_debug_info = percpu
|
||||
@@ -351,11 +280,7 @@ pub fn switch(token: &mut CleanLockToken) -> SwitchResult {
|
||||
.being_sigkilled
|
||||
.set(next_context.being_sigkilled);
|
||||
|
||||
// Anything implement Drop must be manually dropped now
|
||||
drop(prev_context_lock);
|
||||
|
||||
unsafe {
|
||||
percpu.new_addrsp_guard.set(addr_space_guard);
|
||||
arch::switch_to(prev_context, next_context);
|
||||
}
|
||||
|
||||
@@ -377,12 +302,9 @@ pub fn switch(token: &mut CleanLockToken) -> SwitchResult {
|
||||
}
|
||||
}
|
||||
|
||||
fn wakeup_contexts(
|
||||
token: &mut CleanLockToken,
|
||||
switch_time: u128,
|
||||
) -> SmallVec<[WeakContextRef; 16]> {
|
||||
fn wakeup_contexts(token: &mut CleanLockToken, switch_time: u128) -> Vec<(usize, WeakContextRef)> {
|
||||
// TODO: Optimise this somehow. Perhaps using a separate timer queue?
|
||||
let mut wakeups = SmallVec::new();
|
||||
let mut wakeups = Vec::new();
|
||||
let current_context = context::current();
|
||||
let Some(idle_contexts) = idle_contexts_try(token.downgrade()) else {
|
||||
// other cpus may spawning or killing contexts so let's skip wakeups to avoid contention
|
||||
@@ -408,19 +330,18 @@ fn wakeup_contexts(
|
||||
if guard.status.is_soft_blocked() {
|
||||
if let Some(wake) = guard.wake {
|
||||
if switch_time >= wake {
|
||||
let prio = guard.prio;
|
||||
drop(guard);
|
||||
wakeups.push(context_ref);
|
||||
wakeups.push((prio, context_ref));
|
||||
continue;
|
||||
}
|
||||
}
|
||||
} else if guard.status.is_dead() {
|
||||
// TODO: who hold this dead context?
|
||||
continue;
|
||||
}
|
||||
|
||||
if guard.status.is_runnable() && !guard.running {
|
||||
let prio = guard.prio;
|
||||
drop(guard);
|
||||
wakeups.push(context_ref);
|
||||
wakeups.push((prio, context_ref));
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -430,243 +351,137 @@ fn wakeup_contexts(
|
||||
wakeups
|
||||
}
|
||||
|
||||
/// This is the scheduler function which currently utilises EEVDF Scheduler
|
||||
/// This is the scheduler function which currently utilises Deficit Weighted Round Robin Scheduler
|
||||
fn select_next_context(
|
||||
token: &mut CleanLockToken,
|
||||
percpu: &PercpuBlock,
|
||||
cpu_id: LogicalCpuId,
|
||||
switch_time: u128,
|
||||
elapsed_time: u64,
|
||||
was_idle: bool,
|
||||
prev_context_guard: &mut ArcRwLockWriteGuard<L4, Context>,
|
||||
) -> Option<(ArcContextLockWriteGuard, Option<AddrSpaceSwitchReadGuard>)> {
|
||||
) -> Result<Option<ArcContextLockWriteGuard>, SwitchResult> {
|
||||
let contexts_data = run_contexts(token.token());
|
||||
let (mut contexts_data, mut token) = contexts_data.into_split();
|
||||
let contexts_list = &mut contexts_data.set;
|
||||
let idle_context = percpu.switch_internals.idle_context();
|
||||
let mut balance = percpu.balance.get();
|
||||
let mut i = percpu.last_queue.get() % 40;
|
||||
|
||||
// Lock the previous context.
|
||||
let prev_context_lock = crate::context::current();
|
||||
let is_idle = Arc::ptr_eq(&prev_context_lock, &idle_context);
|
||||
let prev_runnable = !is_idle && prev_context_guard.status.is_runnable();
|
||||
|
||||
let elapsed_ticks = elapsed_time as u128 * SCALE / NANOS_PER_TICK;
|
||||
let mut empty_queues = 0;
|
||||
let mut total_iters = 0;
|
||||
let mut next_context_guard_opt = None;
|
||||
|
||||
if prev_runnable {
|
||||
let weight = SCHED_PRIO_TO_WEIGHT[prev_context_guard.prio] as u64;
|
||||
prev_context_guard.rem_slice = prev_context_guard
|
||||
.rem_slice
|
||||
.saturating_sub((elapsed_ticks) as u64);
|
||||
let scaled_task = elapsed_ticks / weight as u128;
|
||||
prev_context_guard.vtime += scaled_task as u64;
|
||||
let total_contexts: usize = contexts_list.iter().map(|q| q.len()).sum();
|
||||
let mut skipped_contexts = 0;
|
||||
|
||||
if prev_context_guard.vtime < contexts_data.v {
|
||||
prev_context_guard.vtime = contexts_data.v;
|
||||
'priority: loop {
|
||||
i = (i + 1) % 40;
|
||||
total_iters += 1;
|
||||
|
||||
// The least prioritised queue takes <5000 iters to build up
|
||||
// balance = sched_prio_to_weight[20], if we have already spent
|
||||
// that many iters and not found any context, it is better to just
|
||||
// skip for now
|
||||
if total_iters >= 5000 {
|
||||
break 'priority;
|
||||
}
|
||||
|
||||
let is_yield = (elapsed_time as u128) < (TICK_INTERVAL as u128 * NANOS_PER_TICK) / 2;
|
||||
|
||||
if is_yield {
|
||||
let unconsumed = prev_context_guard.rem_slice as u128;
|
||||
let penalty = unconsumed / weight as u128;
|
||||
prev_context_guard.vtime += penalty as u64;
|
||||
prev_context_guard.rem_slice = 0;
|
||||
if skipped_contexts > total_contexts && total_contexts > 0 {
|
||||
break 'priority;
|
||||
}
|
||||
|
||||
if prev_context_guard.rem_slice == 0 {
|
||||
prev_context_guard.rem_slice = BASE_SLICE_TICKS * SCALE as u64;
|
||||
let scaled_slice = (BASE_SLICE_TICKS as u128 * SCALE) / weight as u128;
|
||||
prev_context_guard.vd = prev_context_guard.vtime + scaled_slice as u64;
|
||||
}
|
||||
} else if !is_idle {
|
||||
if prev_context_guard.is_active {
|
||||
prev_context_guard.is_active = false;
|
||||
let weight = SCHED_PRIO_TO_WEIGHT[prev_context_guard.prio] as u64;
|
||||
contexts_data.total_weight = contexts_data.total_weight.saturating_sub(weight);
|
||||
}
|
||||
prev_context_guard.rem_slice = 0;
|
||||
}
|
||||
let contexts = contexts_list
|
||||
.get_mut(i)
|
||||
.expect("i should be between [0, 39]!");
|
||||
|
||||
let mut eligible_best = None;
|
||||
let mut prev_is_eligible = false;
|
||||
|
||||
let mut ineligible_best = None;
|
||||
let mut ineligible_min_vtime = u64::MAX;
|
||||
let mut ineligible_vd = u64::MAX;
|
||||
|
||||
if prev_runnable {
|
||||
if prev_context_guard.vtime <= contexts_data.v {
|
||||
prev_is_eligible = true;
|
||||
} else {
|
||||
ineligible_min_vtime = prev_context_guard.vtime;
|
||||
ineligible_vd = prev_context_guard.vd;
|
||||
}
|
||||
}
|
||||
|
||||
// New BTreeMap based walk
|
||||
let mut weight_change: u64 = 0;
|
||||
let mut contexts_to_remove: SmallVec<[(u64, Reverse<u64>, u32); 16]> = SmallVec::new();
|
||||
for ((vd, rem_slice, ctxt_id), (vtime, context_weight, context_ref)) in
|
||||
contexts_data.queue.iter()
|
||||
{
|
||||
if *vtime > ineligible_min_vtime && *vtime > contexts_data.v {
|
||||
continue;
|
||||
}
|
||||
|
||||
let Some(context_lock) = context_ref.upgrade() else {
|
||||
weight_change += *context_weight as u64;
|
||||
contexts_to_remove.push((*vd, *rem_slice, *ctxt_id));
|
||||
continue;
|
||||
};
|
||||
|
||||
if Arc::ptr_eq(&context_lock, &idle_context)
|
||||
|| Arc::ptr_eq(&context_lock, &prev_context_lock)
|
||||
{
|
||||
//weight_change += *context_weight as u64;
|
||||
//contexts_to_remove.push((*vd, *rem_slice, *ctxt_id));
|
||||
continue;
|
||||
}
|
||||
|
||||
let Some(mut guard) = (unsafe { context_lock.try_write_arc() }) else {
|
||||
continue;
|
||||
};
|
||||
|
||||
let sw = unsafe { update_runnable(&mut guard, cpu_id, switch_time) };
|
||||
|
||||
if matches!(sw, UpdateResult::Blocked) {
|
||||
if guard.is_active {
|
||||
guard.is_active = false;
|
||||
weight_change += context_weight;
|
||||
if contexts.is_empty() {
|
||||
empty_queues += 1;
|
||||
if empty_queues >= 40 {
|
||||
// If all queues are empty, just break out
|
||||
break 'priority;
|
||||
}
|
||||
guard.rem_slice = 0;
|
||||
guard.queue_key = None;
|
||||
continue;
|
||||
} else {
|
||||
empty_queues = 0;
|
||||
}
|
||||
|
||||
contexts_to_remove.push((*vd, *rem_slice, *ctxt_id));
|
||||
drop(guard);
|
||||
// Reenqueue should be handled by unblock
|
||||
idle_contexts(token.token()).push_back(context_ref.clone());
|
||||
if balance[i] < SCHED_PRIO_TO_WEIGHT[20] {
|
||||
// This queue does not have enough balance to run,
|
||||
// increment the balance!
|
||||
balance[i] += SCHED_PRIO_TO_WEIGHT[i];
|
||||
continue;
|
||||
}
|
||||
|
||||
if !matches!(sw, UpdateResult::CanSwitch) {
|
||||
continue;
|
||||
}
|
||||
let len = contexts.len();
|
||||
for _ in 0..len {
|
||||
let (next_context_ref, next_context_lock) = match contexts.pop_front() {
|
||||
Some(lock) => match lock.upgrade() {
|
||||
Some(new_lock) => (lock, new_lock),
|
||||
None => {
|
||||
skipped_contexts += 1;
|
||||
continue; // Ghost Process, just continue
|
||||
}
|
||||
},
|
||||
None => break, // Empty Queue
|
||||
};
|
||||
|
||||
let mut best_addr_space = None;
|
||||
if let Some(addr_space) = &guard.addr_space {
|
||||
let mut t = unsafe { CleanLockToken::new() };
|
||||
if let Some(addr) = addr_space.inner.try_read(t.token()) {
|
||||
best_addr_space = Some(AddrSpaceSwitchReadGuard::new(addr));
|
||||
} else {
|
||||
if Arc::ptr_eq(&next_context_lock, &prev_context_lock) {
|
||||
contexts.push_back(next_context_ref);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if *vtime <= contexts_data.v {
|
||||
// Eligible
|
||||
eligible_best = Some((guard, best_addr_space));
|
||||
break;
|
||||
} else {
|
||||
// Ineligible
|
||||
if *vtime < ineligible_min_vtime {
|
||||
ineligible_min_vtime = *vtime;
|
||||
ineligible_vd = *vd;
|
||||
if let Some((old_guard, old_addr_space)) = ineligible_best {
|
||||
drop(old_guard);
|
||||
drop(old_addr_space);
|
||||
}
|
||||
ineligible_best = Some((guard, best_addr_space));
|
||||
if Arc::ptr_eq(&next_context_lock, &idle_context) {
|
||||
contexts.push_back(next_context_ref);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
let mut next_context_guard = unsafe { next_context_lock.write_arc() };
|
||||
|
||||
contexts_data.total_weight = contexts_data.total_weight.saturating_sub(weight_change);
|
||||
|
||||
for old_key in contexts_to_remove {
|
||||
contexts_data.queue.remove(&old_key);
|
||||
}
|
||||
|
||||
// No eligible context was found
|
||||
if !(prev_is_eligible || eligible_best.is_some()) && ineligible_min_vtime != u64::MAX {
|
||||
contexts_data.v = ineligible_min_vtime; // Advance V
|
||||
|
||||
let prev_is_earliest = prev_runnable && prev_context_guard.vtime <= ineligible_min_vtime;
|
||||
|
||||
if prev_is_earliest {
|
||||
eligible_best = None;
|
||||
} else if ineligible_best.is_some() {
|
||||
let prev_has_slice = prev_runnable && prev_context_guard.rem_slice > 0;
|
||||
|
||||
if prev_has_slice && prev_context_guard.vd <= ineligible_vd {
|
||||
eligible_best = None;
|
||||
// Is this context runnable on this CPU?
|
||||
let sw = unsafe { update_runnable(&mut next_context_guard, cpu_id, switch_time) };
|
||||
if let UpdateResult::CanSwitch = sw {
|
||||
next_context_guard_opt = Some(next_context_guard);
|
||||
balance[i] -= SCHED_PRIO_TO_WEIGHT[20];
|
||||
break 'priority;
|
||||
} else {
|
||||
eligible_best = ineligible_best.take();
|
||||
}
|
||||
}
|
||||
} else if prev_is_eligible && eligible_best.is_some() {
|
||||
if let Some((ref guard, _)) = eligible_best {
|
||||
if prev_context_guard.vd < guard.vd
|
||||
|| (prev_context_guard.vd == guard.vd
|
||||
&& prev_context_guard.rem_slice > guard.rem_slice)
|
||||
{
|
||||
eligible_best = None;
|
||||
if matches!(sw, UpdateResult::Blocked) {
|
||||
idle_contexts(token.token()).push_back(next_context_ref);
|
||||
} else {
|
||||
contexts.push_back(next_context_ref);
|
||||
};
|
||||
skipped_contexts += 1;
|
||||
|
||||
if skipped_contexts >= total_contexts {
|
||||
break 'priority;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
percpu.balance.set(balance);
|
||||
percpu.last_queue.set(i);
|
||||
|
||||
let mut final_winner = None;
|
||||
|
||||
if let Some((mut chosen_guard, addr_space)) = eligible_best {
|
||||
if let Some(key) = chosen_guard.queue_key.take() {
|
||||
contexts_data.queue.remove(&key);
|
||||
}
|
||||
final_winner = Some((chosen_guard, addr_space));
|
||||
}
|
||||
|
||||
if final_winner.is_some() || prev_runnable {
|
||||
if contexts_data.total_weight > 0 {
|
||||
let v_advance = elapsed_ticks as u128 / contexts_data.total_weight as u128;
|
||||
contexts_data.v += v_advance as u64;
|
||||
}
|
||||
|
||||
if let Some((chosen_guard, addr_space)) = final_winner {
|
||||
if prev_runnable {
|
||||
let (vd, rem_slice, ctxt_id, vtime) = (
|
||||
prev_context_guard.vd,
|
||||
prev_context_guard.rem_slice,
|
||||
prev_context_guard.debug_id,
|
||||
prev_context_guard.vtime,
|
||||
);
|
||||
prev_context_guard.queue_key = Some((vd, Reverse(rem_slice), ctxt_id));
|
||||
|
||||
let weight = SCHED_PRIO_TO_WEIGHT[prev_context_guard.prio] as u64;
|
||||
contexts_data.queue.insert(
|
||||
(vd, Reverse(rem_slice), ctxt_id),
|
||||
(
|
||||
vtime,
|
||||
weight,
|
||||
WeakContextRef(Arc::downgrade(&prev_context_lock)),
|
||||
),
|
||||
);
|
||||
} else if !is_idle {
|
||||
idle_contexts(token.token())
|
||||
.push_back(WeakContextRef(Arc::downgrade(&prev_context_lock)));
|
||||
}
|
||||
|
||||
return Some((chosen_guard, addr_space));
|
||||
if !Arc::ptr_eq(&prev_context_lock, &idle_context) {
|
||||
// Send the old process to the back of the line (if it is still runnable)
|
||||
let prev_ctx = WeakContextRef(Arc::downgrade(&prev_context_lock));
|
||||
if prev_context_guard.status.is_runnable() {
|
||||
let prio = prev_context_guard.prio;
|
||||
contexts_list[prio].push_back(prev_ctx);
|
||||
} else {
|
||||
return None;
|
||||
idle_contexts(token.token()).push_back(prev_ctx);
|
||||
}
|
||||
}
|
||||
|
||||
if let Some(next_context_guard) = next_context_guard_opt {
|
||||
// We found a new process!
|
||||
return Ok(Some(next_context_guard));
|
||||
} else {
|
||||
if !is_idle {
|
||||
idle_contexts(token.token())
|
||||
.push_back(WeakContextRef(Arc::downgrade(&prev_context_lock)));
|
||||
}
|
||||
|
||||
let prev_is_dead = !is_idle && !prev_context_guard.status.is_runnable();
|
||||
if (!was_idle || prev_is_dead) && !is_idle {
|
||||
return Some(unsafe { (idle_context.write_arc(), None) });
|
||||
if !was_idle && !Arc::ptr_eq(&prev_context_lock, &idle_context) {
|
||||
// We switch into the idle context
|
||||
Ok(Some(unsafe { idle_context.write_arc() }))
|
||||
} else {
|
||||
return None;
|
||||
// We found no other process to run.
|
||||
Ok(None)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -682,10 +497,6 @@ pub struct ContextSwitchPercpu {
|
||||
|
||||
current_ctxt: RefCell<Option<Arc<ContextLock>>>,
|
||||
|
||||
// TODO: just access current_ctxt directly?
|
||||
#[cfg(feature = "profiling")]
|
||||
pub(crate) current_dbg_id: core::sync::atomic::AtomicU32,
|
||||
|
||||
/// The idle process.
|
||||
idle_ctxt: RefCell<Option<Arc<ContextLock>>>,
|
||||
pub(crate) being_sigkilled: Cell<bool>,
|
||||
@@ -700,9 +511,6 @@ impl ContextSwitchPercpu {
|
||||
current_ctxt: RefCell::new(None),
|
||||
idle_ctxt: RefCell::new(None),
|
||||
being_sigkilled: Cell::new(false),
|
||||
|
||||
#[cfg(feature = "profiling")]
|
||||
current_dbg_id: core::sync::atomic::AtomicU32::new(!0),
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user