Skip to content

Commit

Permalink
threads: Implement the concept of threads
Browse files Browse the repository at this point in the history
Each process has a list of threads. The main thread can be identified
with tid == pid.

The threads only contain a weak reference to their parents because
otherwise we would have a cyclic reference.
  • Loading branch information
sysheap committed Jan 26, 2025
1 parent cf99d16 commit 57a223a
Show file tree
Hide file tree
Showing 16 changed files with 575 additions and 227 deletions.
1 change: 1 addition & 0 deletions common/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,3 +23,4 @@ pub mod pointer;
pub mod runtime_initialized;
pub mod syscalls;
pub mod util;
pub mod weak_queue;
9 changes: 9 additions & 0 deletions common/src/pid.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,12 @@ impl core::fmt::Display for Pid {
write!(f, "{}", self.0)
}
}

#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord)]
pub struct Tid(pub u64);

impl core::fmt::Display for Tid {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
write!(f, "{}", self.0)
}
}
95 changes: 95 additions & 0 deletions common/src/weak_queue.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
extern crate alloc;

use alloc::{
collections::VecDeque,
sync::{Arc, Weak},
};

/// A data structure which keeps a list of weak references
/// When iterating over it, it tries to upgrade the reference.
/// If successful, the reference is returned. If not, it is removed.
pub struct WeakQueue<T> {
queue: VecDeque<Weak<T>>,
}

impl<T> Default for WeakQueue<T> {
fn default() -> Self {
Self {
queue: VecDeque::new(),
}
}
}

impl<T> WeakQueue<T> {
pub fn new() -> Self {
Self::default()
}

pub fn add(&mut self, reference: Weak<T>) {
self.queue.push_back(reference);
}

pub fn readonly_iter(&self) -> ReadonlyIter<'_, T> {
ReadonlyIter {
original_iter: self.queue.iter(),
}
}

pub fn iter(&mut self) -> Iter<'_, T> {
let left = self.queue.len();
Iter { weak: self, left }
}

pub fn len(&self) -> usize {
self.queue.len()
}

pub fn is_empty(&self) -> bool {
self.len() == 0
}
}

pub struct Iter<'a, T> {
weak: &'a mut WeakQueue<T>,
left: usize,
}

impl<T> Iterator for Iter<'_, T> {
type Item = Arc<T>;

fn next(&mut self) -> Option<Self::Item> {
if self.left == 0 {
return None;
}

while let Some(reference) = self.weak.queue.pop_front() {
self.left -= 1;
if let Some(strong) = reference.upgrade() {
self.weak.add(reference);
return Some(strong);
}
if self.left == 0 {
break;
}
}

None
}
}

pub struct ReadonlyIter<'a, T> {
original_iter: alloc::collections::vec_deque::Iter<'a, Weak<T>>,
}

impl<T> Iterator for ReadonlyIter<'_, T> {
type Item = Arc<T>;

fn next(&mut self) -> Option<Self::Item> {
for reference in self.original_iter.by_ref() {
if let Some(reference) = reference.upgrade() {
return Some(reference);
}
}
None
}
}
6 changes: 3 additions & 3 deletions kernel/src/cpu.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,8 @@ use crate::{
memory::page_tables::RootPageTableHolder,
processes::{
process::Process,
process_table::ProcessRef,
scheduler::{self, CpuScheduler},
thread::ThreadRef,
},
};

Expand Down Expand Up @@ -158,8 +158,8 @@ impl Cpu {
f(scheduler)
}

pub fn current_process() -> ProcessRef {
Self::with_scheduler(|s| s.get_current_process().clone())
pub fn current_thread() -> ThreadRef {
Self::with_scheduler(|s| s.get_current_thread().clone())
}

pub fn with_current_process<R>(mut f: impl FnMut(MutexGuard<'_, Process>) -> R) -> R {
Expand Down
9 changes: 2 additions & 7 deletions kernel/src/debugging/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,12 +21,7 @@ pub fn dump_current_state() {
);

process_table::THE.lock().dump();
Cpu::current_process().with_lock(|p| {
info!(
"Current Process: PID={} NAME={} STATE={:?}",
p.get_pid(),
p.get_name(),
p.get_state()
);
Cpu::current_thread().with_lock(|t| {
info!("Current Thread: {}", *t);
});
}
4 changes: 2 additions & 2 deletions kernel/src/interrupts/trap.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ use crate::{
debug,
interrupts::plic::{self, InterruptSource},
io::{stdin_buf::STDIN_BUFFER, uart},
processes::process::ProcessState,
processes::thread::ThreadState,
syscalls::{self},
};
use common::syscalls::trap_frame::Register;
Expand Down Expand Up @@ -64,7 +64,7 @@ fn handle_syscall() {
}

// In case our current process was set to waiting state we need to reschedule
if scheduler.get_current_process().lock().get_state() == ProcessState::Waiting {
if scheduler.get_current_thread().lock().get_state() == ThreadState::Waiting {
scheduler.schedule();
}
}
Expand Down
20 changes: 12 additions & 8 deletions kernel/src/io/stdin_buf.rs
Original file line number Diff line number Diff line change
@@ -1,15 +1,16 @@
use crate::{
cpu::Cpu,
debug,
processes::{process_table, timer},
};
use alloc::collections::{BTreeSet, VecDeque};
use common::{mutex::Mutex, pid::Pid};
use common::{mutex::Mutex, pid::Tid};

pub static STDIN_BUFFER: Mutex<StdinBuffer> = Mutex::new(StdinBuffer::new());

pub struct StdinBuffer {
data: VecDeque<u8>,
wakeup_queue: BTreeSet<Pid>,
wakeup_queue: BTreeSet<Tid>,
}

impl StdinBuffer {
Expand All @@ -20,23 +21,26 @@ impl StdinBuffer {
}
}

pub fn register_wakeup(&mut self, pid: Pid) {
self.wakeup_queue.insert(pid);
pub fn register_wakeup(&mut self, tid: Tid) {
self.wakeup_queue.insert(tid);
}

pub fn push(&mut self, byte: u8) {
let notified = !self.wakeup_queue.is_empty();
debug!("Waking up following tids={:?}", self.wakeup_queue);
process_table::THE.with_lock(|pt| {
for pid in &self.wakeup_queue {
if let Some(process) = pt.get_process(*pid) {
process.with_lock(|mut p| {
p.resume_on_syscall(byte);
for tid in &self.wakeup_queue {
if let Some(thread) = pt.get_thread(*tid) {
thread.with_lock(|mut t| {
debug!("Resume on syscall set on thread={}", *t);
t.resume_on_syscall(byte);
})
}
}
});
Cpu::with_scheduler(|s| {
if notified && s.is_current_process_energy_saver() {
debug!("notified process and current process is energy saver");
s.schedule();
}
});
Expand Down
1 change: 1 addition & 0 deletions kernel/src/processes/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,5 @@ mod loader;
pub mod process;
pub mod process_table;
pub mod scheduler;
pub mod thread;
pub mod timer;
Loading

0 comments on commit 57a223a

Please sign in to comment.