Add thread_sleep and mutex_lock_timeout syscalls
This commit is contained in:
parent
a4a8bf0152
commit
f81452f431
@ -1,12 +1,18 @@
|
|||||||
use crate::{
|
use crate::{
|
||||||
bootinfo::BOOTINFO, pit::NUM_INTERRUPTS, print, println, tasking::{InvalidPid, IpcMessage, SleepReason}, virtual_memory::{ASpaceMutex, AddressSpace, PagingError, ACTIVE_SPACE, KERNEL_SPACE}, TASKING
|
bootinfo::BOOTINFO,
|
||||||
|
pit::NUM_INTERRUPTS,
|
||||||
|
print, println,
|
||||||
|
tasking::{InvalidPid, IpcMessage, SleepReason},
|
||||||
|
virtual_memory::{ASpaceMutex, AddressSpace, PagingError, ACTIVE_SPACE, KERNEL_SPACE},
|
||||||
|
TASKING,
|
||||||
};
|
};
|
||||||
use alloc::{boxed::Box, vec::Vec};
|
use alloc::{boxed::Box, vec::Vec};
|
||||||
use az::WrappingCast;
|
use az::WrappingCast;
|
||||||
use cast::{u64, usize};
|
use cast::{u64, usize};
|
||||||
use core::{
|
use core::{
|
||||||
arch::{asm, naked_asm},
|
arch::{asm, naked_asm},
|
||||||
ptr, slice, sync::atomic::Ordering,
|
ptr, slice,
|
||||||
|
sync::atomic::Ordering,
|
||||||
};
|
};
|
||||||
use hashbrown::HashMap;
|
use hashbrown::HashMap;
|
||||||
use pic8259::ChainedPics;
|
use pic8259::ChainedPics;
|
||||||
@ -812,6 +818,10 @@ extern "C" fn syscall_handler() {
|
|||||||
38 => {
|
38 => {
|
||||||
retval = NUM_INTERRUPTS.load(Ordering::Relaxed);
|
retval = NUM_INTERRUPTS.load(Ordering::Relaxed);
|
||||||
}
|
}
|
||||||
|
39 => TASKING.time_sleep(regs.rcx),
|
||||||
|
40 => {
|
||||||
|
retval = u64::from(TASKING.lock_mutex_timeout(usize(regs.rcx), regs.rdx));
|
||||||
|
}
|
||||||
_ => (),
|
_ => (),
|
||||||
};
|
};
|
||||||
unsafe { SYSCALL_REGS = regs };
|
unsafe { SYSCALL_REGS = regs };
|
||||||
|
29
src/pit.rs
29
src/pit.rs
@ -1,9 +1,12 @@
|
|||||||
use core::sync::atomic::{AtomicU64, Ordering};
|
use core::sync::atomic::{AtomicBool, AtomicU64, Ordering};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
interrupts::{self, EoiGuard},
|
interrupts::{self, EoiGuard},
|
||||||
println, TASKING,
|
println,
|
||||||
|
tasking::SleepReason,
|
||||||
|
TASKING,
|
||||||
};
|
};
|
||||||
|
use alloc::collections::vec_deque::VecDeque;
|
||||||
use spin::Mutex;
|
use spin::Mutex;
|
||||||
use x86_64::instructions::port::{Port, PortWriteOnly};
|
use x86_64::instructions::port::{Port, PortWriteOnly};
|
||||||
|
|
||||||
@ -14,6 +17,9 @@ const MAX_FREQ: u32 = 1_193_180;
|
|||||||
|
|
||||||
pub static NUM_INTERRUPTS: AtomicU64 = AtomicU64::new(0);
|
pub static NUM_INTERRUPTS: AtomicU64 = AtomicU64::new(0);
|
||||||
|
|
||||||
|
pub static THREAD_SLEEP_LIST: Mutex<VecDeque<(u64, usize, usize)>> = Mutex::new(VecDeque::new());
|
||||||
|
pub static CHECK_SLEEP_LIST: AtomicBool = AtomicBool::new(false);
|
||||||
|
|
||||||
pub fn init(mut freq: u32) {
|
pub fn init(mut freq: u32) {
|
||||||
assert_ne!(freq, 0);
|
assert_ne!(freq, 0);
|
||||||
#[expect(
|
#[expect(
|
||||||
@ -48,12 +54,29 @@ pub fn init(mut freq: u32) {
|
|||||||
unsafe { CMD.lock().write(0b0011_0110_u8) };
|
unsafe { CMD.lock().write(0b0011_0110_u8) };
|
||||||
unsafe { DATA.lock().write(div_bytes[0]) };
|
unsafe { DATA.lock().write(div_bytes[0]) };
|
||||||
unsafe { DATA.lock().write(div_bytes[1]) };
|
unsafe { DATA.lock().write(div_bytes[1]) };
|
||||||
|
CHECK_SLEEP_LIST.store(true, Ordering::Relaxed);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn handler(_irq: u8, eoi_guard: EoiGuard) {
|
fn handler(_irq: u8, eoi_guard: EoiGuard) {
|
||||||
NUM_INTERRUPTS.fetch_add(1, Ordering::Relaxed);
|
let ticks = NUM_INTERRUPTS.fetch_add(1, Ordering::Relaxed) + 1;
|
||||||
|
if CHECK_SLEEP_LIST.load(Ordering::Relaxed) {
|
||||||
|
let mut list = THREAD_SLEEP_LIST.lock();
|
||||||
|
while list.front().is_some_and(|x| x.0 <= ticks) {
|
||||||
|
let entry = list.pop_front().unwrap();
|
||||||
|
TASKING.force_wake(entry.1, entry.2).unwrap();
|
||||||
|
}
|
||||||
|
}
|
||||||
drop(eoi_guard);
|
drop(eoi_guard);
|
||||||
if TASKING.ok_to_yield() {
|
if TASKING.ok_to_yield() {
|
||||||
TASKING.task_yield();
|
TASKING.task_yield();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn thread_sleeping(pid: usize, tid: usize, duration: u64) {
|
||||||
|
let end = NUM_INTERRUPTS.load(Ordering::Relaxed) + duration;
|
||||||
|
THREAD_SLEEP_LIST.lock().push_back((end, pid, tid));
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn cancel_sleep(pid: usize, tid: usize) {
|
||||||
|
THREAD_SLEEP_LIST.lock().retain(|x| x.1 != pid && x.2 != tid);
|
||||||
|
}
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
use crate::{
|
use crate::{
|
||||||
gdt,
|
gdt,
|
||||||
interrupts::{send_ipc_to, REGISTERD_PIDS},
|
interrupts::{send_ipc_to, REGISTERD_PIDS},
|
||||||
println,
|
pit, println,
|
||||||
virtual_memory::{ASpaceMutex, AddressSpace, PagingError, ACTIVE_SPACE, KERNEL_SPACE},
|
virtual_memory::{ASpaceMutex, AddressSpace, PagingError, ACTIVE_SPACE, KERNEL_SPACE},
|
||||||
};
|
};
|
||||||
use alloc::{boxed::Box, collections::VecDeque, vec, vec::Vec};
|
use alloc::{boxed::Box, collections::VecDeque, vec, vec::Vec};
|
||||||
@ -13,7 +13,7 @@ use core::{
|
|||||||
};
|
};
|
||||||
use crossbeam_queue::SegQueue;
|
use crossbeam_queue::SegQueue;
|
||||||
use slab::Slab;
|
use slab::Slab;
|
||||||
use spin::{mutex, Lazy, Mutex, RwLock};
|
use spin::{Lazy, Mutex, RwLock};
|
||||||
use x86_64::{
|
use x86_64::{
|
||||||
structures::paging::{Page, PageTableFlags},
|
structures::paging::{Page, PageTableFlags},
|
||||||
VirtAddr,
|
VirtAddr,
|
||||||
@ -85,6 +85,7 @@ pub enum SleepReason {
|
|||||||
Exited,
|
Exited,
|
||||||
JoinThread(usize),
|
JoinThread(usize),
|
||||||
LockedMutex(usize),
|
LockedMutex(usize),
|
||||||
|
TimeSleep,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
@ -613,6 +614,22 @@ impl Tasking {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn force_wake(&self, pid: usize, tid: usize) -> Result<(), InvalidPid> {
|
||||||
|
let processes = self.processes.read();
|
||||||
|
let process = processes.get(pid).ok_or(InvalidPid)?;
|
||||||
|
let threads = process.threads.read();
|
||||||
|
let thread = threads.get(tid).ok_or(InvalidPid)?;
|
||||||
|
let mut sleeping = thread.sleeping.write();
|
||||||
|
if *sleeping != Some(SleepReason::Exited) {
|
||||||
|
// only thing we cannot force a wakeup from
|
||||||
|
if Some(pid) != self.current_pid() || Some(tid) != self.current_tid() {
|
||||||
|
self.ready_to_run.lock().push_back((pid, tid));
|
||||||
|
}
|
||||||
|
*sleeping = None;
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
pub fn new_tls_key(&self) -> usize {
|
pub fn new_tls_key(&self) -> usize {
|
||||||
self.current_process_mut(|process| {
|
self.current_process_mut(|process| {
|
||||||
let id = process.num_tls;
|
let id = process.num_tls;
|
||||||
@ -647,6 +664,16 @@ impl Tasking {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn lock_mutex_timeout(&self, mutex: usize, duration: u64) -> bool {
|
||||||
|
if self.try_lock_mutex(mutex) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
pit::thread_sleeping(self.current_pid().unwrap(), self.current_tid().unwrap(), duration);
|
||||||
|
self.sleep(SleepReason::LockedMutex(mutex));
|
||||||
|
pit::cancel_sleep(self.current_pid().unwrap(), self.current_tid().unwrap());
|
||||||
|
self.try_lock_mutex(mutex)
|
||||||
|
}
|
||||||
|
|
||||||
pub fn try_lock_mutex(&self, mutex: usize) -> bool {
|
pub fn try_lock_mutex(&self, mutex: usize) -> bool {
|
||||||
self.current_process(|process| {
|
self.current_process(|process| {
|
||||||
let mut mutexes = process.mutexes.lock();
|
let mut mutexes = process.mutexes.lock();
|
||||||
@ -665,7 +692,8 @@ impl Tasking {
|
|||||||
mutexes[mutex] = false;
|
mutexes[mutex] = false;
|
||||||
for (tid, thread) in &*process.threads().read() {
|
for (tid, thread) in &*process.threads().read() {
|
||||||
if *thread.sleeping.read() == Some(SleepReason::LockedMutex(mutex)) {
|
if *thread.sleeping.read() == Some(SleepReason::LockedMutex(mutex)) {
|
||||||
self.wake(self.current_pid().unwrap(), tid, SleepReason::LockedMutex(mutex));
|
self.wake(self.current_pid().unwrap(), tid, SleepReason::LockedMutex(mutex))
|
||||||
|
.unwrap();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -676,6 +704,11 @@ impl Tasking {
|
|||||||
self.current_process(|process| process.mutexes.lock().remove(mutex));
|
self.current_process(|process| process.mutexes.lock().remove(mutex));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn time_sleep(&self, timeout: u64) {
|
||||||
|
pit::thread_sleeping(self.current_pid().unwrap(), self.current_tid().unwrap(), timeout);
|
||||||
|
self.sleep(SleepReason::TimeSleep);
|
||||||
|
}
|
||||||
|
|
||||||
//pub fn print_stats(&self) {
|
//pub fn print_stats(&self) {
|
||||||
// let mut total = KERNEL_SPACE.lock().get_bytes_allocated();
|
// let mut total = KERNEL_SPACE.lock().get_bytes_allocated();
|
||||||
// println!(
|
// println!(
|
||||||
|
Loading…
Reference in New Issue
Block a user