diff --git a/kernel/src/syscall/invocation/invoke_sched.rs b/kernel/src/syscall/invocation/invoke_sched.rs index d54acca..be06c0d 100644 --- a/kernel/src/syscall/invocation/invoke_sched.rs +++ b/kernel/src/syscall/invocation/invoke_sched.rs @@ -4,7 +4,10 @@ use sel4_common::{ structures_gen::{cap, cap_tag}, utils::convert_to_mut_type_ref, }; -use sel4_task::{sched_context::sched_context, tcb_t}; +use sel4_task::{ + checkBudget, commitTime, ksCurSC, ksCurThread, possible_switch_to, rescheduleRequired, + sched_context::sched_context, sched_context::MIN_REFILLS, seL4_SchedContext_Sporadic, tcb_t, +}; pub fn invokeSchedContext_UnbindObject(sc: &mut sched_context, capability: cap) -> exception_t { match capability.get_tag() { @@ -38,7 +41,7 @@ pub fn invokeSchedContext_YieldTo(sc: &mut sched_context) -> exception_t { exception_t::EXCEPTION_NONE } pub fn invokeSchedControl_ConfigureFlags( - sc: &mut sched_context, + target: &mut sched_context, core: usize, budget: ticks_t, period: ticks_t, @@ -46,6 +49,44 @@ pub fn invokeSchedControl_ConfigureFlags( badge: usize, flags: usize, ) -> exception_t { - // TODO: MCS + target.scBadge = badge; + target.scSporadic = (flags & seL4_SchedContext_Sporadic) != 0; + + if target.scTcb != 0 { + /* remove from scheduler */ + convert_to_mut_type_ref::(target.scTcb).Release_Remove(); + convert_to_mut_type_ref::(target.scTcb).sched_dequeue(); + /* bill the current consumed amount before adjusting the params */ + if unsafe { ksCurSC } == target.get_ptr() { + assert!(checkBudget()); + commitTime(); + } + } + + if budget == period { + target.refill_new(MIN_REFILLS, budget, 0); + } else if target.scRefillMax > 0 + && target.scTcb != 0 + && convert_to_mut_type_ref::(target.scTcb).is_runnable() + { + target.refill_update(period, budget, max_refills); + } else { + /* the scheduling context isn't active - it's budget is not being used, so + * we can just populate the parameters from now */ + target.refill_new(max_refills, budget, period); + } + + assert!(target.scRefillMax > 0); + if target.scTcb != 0 { + target.schedContext_resume(); + if convert_to_mut_type_ref::(target.scTcb).is_runnable() + && target.scTcb != unsafe { ksCurThread } + { + possible_switch_to(convert_to_mut_type_ref::(target.scTcb)); + } + if target.scTcb == unsafe { ksCurThread } { + rescheduleRequired(); + } + } exception_t::EXCEPTION_NONE } diff --git a/sel4_task/src/sched_context.rs b/sel4_task/src/sched_context.rs index e2228c2..6f980bc 100644 --- a/sel4_task/src/sched_context.rs +++ b/sel4_task/src/sched_context.rs @@ -213,6 +213,44 @@ impl sched_context { self.refill_capacity(usage) >= MIN_BUDGET() } #[inline] + pub fn refill_update( + &mut self, + new_period: ticks_t, + new_budget: ticks_t, + new_max_refills: usize, + ) { + /* refill must be initialised in order to be updated - otherwise refill_new should be used */ + assert!(self.scRefillMax > 0); + + unsafe { + (*self.refill_index(0)).rAmount = (*self.refill_head()).rAmount; + (*self.refill_index(0)).rTime = (*self.refill_head()).rTime; + self.scRefillHead = 0; + /* truncate refill list to size 1 */ + self.scRefillTail = self.scRefillHead; + /* update max refills */ + self.scRefillMax = new_max_refills; + /* update period */ + self.scPeriod = new_period; + + if self.refill_ready() { + (*self.refill_head()).rTime = ksCurTime; + } + + if (*self.refill_head()).rAmount >= new_budget { + /* if the heads budget exceeds the new budget just trim it */ + (*self.refill_head()).rAmount = new_budget; + self.maybe_add_empty_tail(); + } else { + /* otherwise schedule the rest for the next period */ + self.refill_add_tail( + (*self.refill_head()).rTime + new_period, + new_budget - (*self.refill_head()).rAmount, + ); + } + } + } + #[inline] pub fn schedule_used(&mut self, new_rTime: ticks_t, new_rAmount: ticks_t) { // TODO: MCS unsafe { diff --git a/sel4_task/src/scheduler.rs b/sel4_task/src/scheduler.rs index aebc141..daf9f0f 100644 --- a/sel4_task/src/scheduler.rs +++ b/sel4_task/src/scheduler.rs @@ -89,6 +89,8 @@ pub const SchedulerAction_ResumeCurrentThread: usize = 0; pub const SchedulerAction_ChooseNewThread: usize = 1; pub const ksDomScheduleLength: usize = 1; +pub const seL4_SchedContext_NoFlag: usize = 0; +pub const seL4_SchedContext_Sporadic: usize = 1; #[no_mangle] pub static mut ksDomainTime: usize = 0;