Commit fb9a941d authored by Nifou's avatar Nifou

Create a global `exit` function which can be used to do the job of the

syscalls `exit` and `exit_group`
parent b68a4aab
Pipeline #163574038 passed with stages
in 8 minutes and 58 seconds
......@@ -120,6 +120,7 @@ const SIGPROCMASK: usize = 14;
const EXIT: usize = 60;
const ARCH_PRCTL: usize = 158;
const TKILL: usize = 200;
const EXIT_GROUP: usize = 231;
/// A structure used to call the right handler for each syscall
pub struct Syscall {
......@@ -146,8 +147,9 @@ impl Syscall {
EXIT => self.exit(args[0]),
SIGACTION => self.sigaction(args[0], args[1], args[2]),
SIGPROCMASK => self.sigprocmask(args[0], args[1], args[2], args[3]),
TKILL => self.tkill(args[0], args[1]),
ARCH_PRCTL => self.arch_prctl(args[0], args[1]),
TKILL => self.tkill(args[0], args[1]),
EXIT_GROUP => self.exit_group(args[0]),
_ => {
println!("Unknown syscall: {}", num);
Err(Error::ENOSYS)
......
......@@ -15,7 +15,7 @@
* along with this program. If not, see https://www.gnu.org/licenses.
*/
//! Syscalls used for tasking (exit, ...)
use crate::tasking::scheduler::SCHEDULER;
use crate::tasking::scheduler::exit;
use super::{Syscall, error::{Result, Error}};
// --- Signals (from libc) ---
......@@ -66,7 +66,22 @@ impl Syscall {
// Use the kernel's page table
crate::memory::switch_to_kernel_page_table();
SCHEDULER.get().remove_current();
exit(false);
unreachable!();
}
/// Exit from the current thread by switching to the next thread
pub fn exit_group(&self, code: usize) -> Result {
// TODO: Only exit the process, use exit_group to remove all threads
match code {
0 => println!("Exit success"),
_ => println!("Error"),
}
// Use the kernel's page table
crate::memory::switch_to_kernel_page_table();
exit(true);
unreachable!();
}
......@@ -79,7 +94,7 @@ impl Syscall {
// Use the kernel's page table
crate::memory::switch_to_kernel_page_table();
SCHEDULER.get().remove_current();
exit(true);
unreachable!();
}
......
......@@ -22,12 +22,6 @@ pub trait SchedulerAlgo {
/// Add a new thread in the list of threads
fn add(&mut self, thread: Thread);
/// Remove the current thread in the list of threads
fn remove_current(&mut self) {
self.remove(self.current().expect("No current process").tid);
self.switch();
}
/// Remove the thread with tid `tid` in the list of threads
fn remove(&mut self, tid: Tid);
......
......@@ -121,6 +121,9 @@ impl ProcessMemory {
}
#[derive(PartialEq, Eq, Clone)]
/// The representation of an area of a process' memory
///
/// It is used to keep track of memory allocations for each process
pub struct MemoryArea {
start: u64,
end: u64,
......@@ -147,6 +150,8 @@ impl Ord for MemoryArea {
}
impl MemoryArea {
/// Create a new Area of memory which can be used with `ProcessMemory::map` for map a new area of
/// memory
pub fn new(start: u64, end: u64, flags: Flags) -> Self {
Self {
start,
......@@ -156,6 +161,9 @@ impl MemoryArea {
}
}
/// Set the mappings of this area
///
/// If this array is not empty, these mappings will be used during the mapping of the new area
pub fn mappings(&mut self, mappings: memory::Mappings) {
self.mappings = mappings;
}
......
......@@ -33,7 +33,7 @@ use super::scheduler::round_robin::RoundRobinScheduler;
pub mod round_robin;
lazy_static! {
/// A global Processor
/// A global scheduler
pub static ref SCHEDULER: SchedulerCurrentAlgo = SchedulerCurrentAlgo(UnsafeCell::new(Box::new(RoundRobinScheduler::new())));
}
......@@ -57,3 +57,36 @@ impl SchedulerCurrentAlgo {
unsafe impl Sync for SchedulerCurrentAlgo {}
unsafe impl Send for SchedulerCurrentAlgo {}
/// If `all_threads` is false, remove the current thread and switch to the next thread
/// (do the job of the `exit` syscall)
///
/// Else, remove all threads of the process of the current thread and switch to the next thread ()
/// (do the job of the `exit_group` syscall)
pub fn exit(all_threads: bool) {
let mut processes = PROCESSES.write();
let tid = SCHEDULER.get().current().expect("No current process").tid;
let pid = SCHEDULER.get().current().expect("No current process").process;
// Remove the current thread
SCHEDULER.get().remove(tid);
// Remove the thread in the process
if all_threads {
processes.get_mut(&pid).unwrap().threads.clear();
} else {
processes.get_mut(&pid).unwrap().threads.retain(|thread| thread != &tid);
}
// If there is no other threads, remove the process
if processes.get(&pid).unwrap().threads.is_empty() {
processes.remove(&pid);
}
// Drop the lock because this function will never return
drop(processes);
// Switch to the next thread
SCHEDULER.get().switch();
unreachable!();
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment