Nothing to see here, move along meow
0

Configure Feed

Select the types of activity you want to include in your feed.

at main 5.9 kB View raw
1use crate::cap::cnode; 2use crate::cap::object::ObjectTag; 3use crate::cap::pool::POOL; 4use crate::cap::table::Rights; 5use crate::error::KernelError; 6use crate::proc::PROCESSES; 7use crate::proc::context::CpuContext; 8use crate::syscall::{SyscallResult, try_syscall}; 9use crate::types::{Pid, Priority}; 10use lancer_core::header::NONE_SENTINEL; 11use lancer_core::object_layout::SchedContextObject; 12 13pub fn sys_sched_attach(ctx: &mut CpuContext) { 14 let sched_addr = ctx.rdi; 15 let target_pid_raw = try_syscall!(ctx, super::u32_from_reg(ctx.rsi)); 16 let pid = crate::arch::syscall::current_pid(); 17 18 let target_pid = match Pid::try_new(target_pid_raw) { 19 Some(p) => p, 20 None => { 21 ctx.rax = SyscallResult::error(KernelError::InvalidParameter).raw(); 22 return; 23 } 24 }; 25 26 let mut ptable = PROCESSES.lock(); 27 let cap = { 28 let pool = POOL.lock_after(&ptable); 29 try_syscall!( 30 ctx, 31 cnode::resolve_caller_validate( 32 pid, 33 sched_addr, 34 ObjectTag::SchedContext, 35 Rights::WRITE, 36 &ptable, 37 &pool 38 ) 39 ) 40 }; 41 42 if target_pid != pid { 43 let pool = POOL.lock_after(&ptable); 44 let has_proc_cap = { 45 let (cnode_id, cnode_gen, _, _, _) = 46 try_syscall!(ctx, cnode::cnode_coords(pid, &ptable)); 47 let mut found = false; 48 let _ = cnode::walk_cnode_slots(&pool, cnode_id, cnode_gen, |slot| { 49 if let crate::cap::table::CapSlot::Active(cap) = slot 50 && cap.tag() == ObjectTag::Process 51 && cap.rights().contains(Rights::WRITE) 52 && pool 53 .read_as::<lancer_core::object_layout::ProcessObject>( 54 cap.phys(), 55 cap.generation(), 56 ) 57 .ok() 58 .and_then(|p| Pid::try_new(p.pid)) 59 .is_some_and(|p| p == target_pid) 60 { 61 found = true; 62 } 63 }); 64 found 65 }; 66 if !has_proc_cap { 67 ctx.rax = SyscallResult::error(KernelError::PermissionDenied).raw(); 68 return; 69 } 70 } 71 72 let priority = { 73 let mut pool = POOL.lock_after(&ptable); 74 match pool.write_as::<SchedContextObject>(cap.phys(), cap.generation()) { 75 Ok(sc) => { 76 let old_attached = Pid::try_new(sc.attached_pid); 77 match old_attached { 78 Some(old_pid) if old_pid != target_pid => { 79 if old_pid != pid { 80 ctx.rax = SyscallResult::error(KernelError::PermissionDenied).raw(); 81 return; 82 } 83 if let Some(old_proc) = ptable.get_mut(old_pid) { 84 old_proc.detach_sched_context(); 85 } 86 } 87 _ => {} 88 } 89 sc.attached_pid = target_pid.raw(); 90 let now_us = crate::wcet::tsc::cycles_to_ns(crate::wcet::tsc::read_tsc()) / 1000; 91 sc.remaining_us = sc.budget_us; 92 sc.replenish_at = now_us.saturating_add(sc.period_us); 93 Priority::new(sc.priority) 94 } 95 Err(e) => { 96 ctx.rax = SyscallResult::error(e).raw(); 97 return; 98 } 99 } 100 }; 101 102 ctx.rax = match ptable.get_mut(target_pid) { 103 Some(target) => { 104 let old_sc = target.sched_context(); 105 target.attach_sched_context(cap.phys(), cap.generation(), priority); 106 107 if let Some((old_id, old_gen)) = old_sc { 108 let mut pool = POOL.lock_after(&ptable); 109 if let Ok(sc) = pool.write_as::<SchedContextObject>(old_id, old_gen) { 110 sc.attached_pid = NONE_SENTINEL; 111 } 112 } 113 SyscallResult::ok().raw() 114 } 115 None => SyscallResult::error(KernelError::InvalidObject).raw(), 116 }; 117} 118 119pub fn sys_sched_configure(ctx: &mut CpuContext) { 120 let sched_addr = ctx.rdi; 121 let budget_us = ctx.rsi; 122 let period_us = ctx.rdx; 123 let priority_raw = try_syscall!(ctx, super::u8_from_reg(ctx.r10)); 124 let pid = crate::arch::syscall::current_pid(); 125 126 const MIN_PERIOD_US: u64 = 1_000; 127 const MAX_PERIOD_US: u64 = 3_600_000_000; 128 129 let priority = match Priority::new_user(priority_raw) { 130 Some(p) => p, 131 None => { 132 ctx.rax = SyscallResult::error(KernelError::InvalidParameter).raw(); 133 return; 134 } 135 }; 136 137 if budget_us == 0 138 || period_us < MIN_PERIOD_US 139 || budget_us > period_us 140 || period_us > MAX_PERIOD_US 141 { 142 ctx.rax = SyscallResult::error(KernelError::InvalidParameter).raw(); 143 return; 144 } 145 146 let ptable = PROCESSES.lock(); 147 let cap = { 148 let pool = POOL.lock_after(&ptable); 149 try_syscall!( 150 ctx, 151 cnode::resolve_caller_validate( 152 pid, 153 sched_addr, 154 ObjectTag::SchedContext, 155 Rights::WRITE, 156 &ptable, 157 &pool, 158 ) 159 ) 160 }; 161 162 let mut pool = POOL.lock_after(&ptable); 163 ctx.rax = match pool.write_as::<SchedContextObject>(cap.phys(), cap.generation()) { 164 Ok(sc) => { 165 sc.budget_us = budget_us; 166 sc.period_us = period_us; 167 sc.remaining_us = budget_us; 168 sc.priority = priority.raw(); 169 SyscallResult::ok().raw() 170 } 171 Err(e) => SyscallResult::error(e).raw(), 172 }; 173} 174 175pub fn sys_sched_yield(ctx: &mut CpuContext) { 176 ctx.rax = SyscallResult::ok().raw(); 177 crate::sched::schedule(ctx); 178}