mirror of
https://github.com/obhq/obliteration.git
synced 2024-11-27 05:00:24 +00:00
Implements idle process (#887)
This commit is contained in:
parent
bf704b5311
commit
6ca06469d9
@ -51,8 +51,8 @@ impl MachDep {
|
||||
// kernel.
|
||||
let v = unsafe { std::ptr::read_unaligned(parms as _) };
|
||||
|
||||
pcb.set_fsbase(v);
|
||||
*pcb.flags_mut() |= PcbFlags::PCB_FULL_IRET;
|
||||
pcb.fsbase = v;
|
||||
pcb.flags |= PcbFlags::PCB_FULL_IRET;
|
||||
|
||||
info!("FS segment has been changed to {v:#x}.");
|
||||
}
|
||||
|
@ -590,7 +590,7 @@ impl NativeEngine {
|
||||
/// # Safety
|
||||
/// This method cannot be called from Rust.
|
||||
unsafe extern "sysv64" fn resolve_fs(&self, disp: usize) -> usize {
|
||||
std::ptr::read_unaligned((VThread::current().unwrap().pcb().fsbase() + disp) as _)
|
||||
std::ptr::read_unaligned((VThread::current().unwrap().pcb().fsbase + disp) as _)
|
||||
}
|
||||
|
||||
/// # Safety
|
||||
|
@ -22,6 +22,19 @@ impl<A: 'static> EventType for fn(A) {
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(coherence_leak_check)] // https://github.com/rust-lang/rust/issues/56105#issuecomment-606379619
|
||||
impl<A: 'static> EventType for for<'a> fn(&'a A) {
|
||||
type Handler<S: 'static> = fn(&Arc<S>, &A);
|
||||
type Wrapper = Box<dyn Fn(&A) + Send + Sync>;
|
||||
|
||||
fn wrap_handler<S>(s: Arc<S>, h: Self::Handler<S>) -> Self::Wrapper
|
||||
where
|
||||
S: Send + Sync + 'static,
|
||||
{
|
||||
Box::new(move |arg| h(&s, arg))
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(coherence_leak_check)] // https://github.com/rust-lang/rust/issues/56105#issuecomment-606379619
|
||||
impl<A: 'static> EventType for for<'a> fn(&'a mut A) {
|
||||
type Handler<S: 'static> = fn(&Arc<S>, &mut A);
|
||||
|
@ -425,7 +425,7 @@ fn run(args: Args) -> Result<(), KernelError> {
|
||||
let sys = Arc::new(sys);
|
||||
let budget_id = budget.create(Budget::new("big app", ProcType::BigApp));
|
||||
let proc_root = fs.lookup(proc_root, true, None).unwrap();
|
||||
let proc = pmgr
|
||||
let main = pmgr
|
||||
.spawn(
|
||||
ProcAbi::new(Some(sys)),
|
||||
auth,
|
||||
@ -437,6 +437,7 @@ fn run(args: Args) -> Result<(), KernelError> {
|
||||
true, // TODO: Change to false when we switched to run /mini-syscore.elf.
|
||||
)
|
||||
.map_err(KernelError::CreateProcessFailed)?;
|
||||
let proc = main.proc();
|
||||
|
||||
info!(
|
||||
"Application stack: {:p}:{:p}",
|
||||
@ -446,7 +447,6 @@ fn run(args: Args) -> Result<(), KernelError> {
|
||||
|
||||
// Load eboot.bin.
|
||||
let path = vpath!("/app0/eboot.bin");
|
||||
let main = VThread::new(proc.clone());
|
||||
let app = ld
|
||||
.exec(path, &main)
|
||||
.map_err(|e| KernelError::ExecFailed(path, e))?;
|
||||
@ -527,14 +527,14 @@ fn run(args: Args) -> Result<(), KernelError> {
|
||||
std::thread::scope(|s| {
|
||||
let (tx, rx) = channel();
|
||||
|
||||
for _ in 0..Hypervisor::VCPU {
|
||||
for id in 0..Hypervisor::VCPU {
|
||||
let tx = tx.clone();
|
||||
let exit = &exit;
|
||||
let hv = hv.as_ref();
|
||||
let sched = sched.as_ref();
|
||||
let pmgr = pmgr.as_ref();
|
||||
|
||||
s.spawn(move || tx.send(cpu(exit, hv, sched, pmgr)));
|
||||
s.spawn(move || tx.send(cpu(id, exit, hv, sched, pmgr)));
|
||||
}
|
||||
|
||||
drop(tx);
|
||||
@ -554,6 +554,7 @@ fn run(args: Args) -> Result<(), KernelError> {
|
||||
}
|
||||
|
||||
fn cpu(
|
||||
id: usize,
|
||||
exit: &AtomicBool,
|
||||
hv: &Hypervisor,
|
||||
sched: &Scheduler,
|
||||
@ -563,7 +564,10 @@ fn cpu(
|
||||
let cpu = hv
|
||||
.create_cpu()
|
||||
.map_err(|e| CpuError::CreateCpuFailed(Box::new(e)))?;
|
||||
let idle = Arc::new(VThread::new(pmgr.proc0().clone())); // TODO: Use a proper implementation.
|
||||
let idle = pmgr.spawn_kthread(
|
||||
Some(pmgr.idle()),
|
||||
format!("SceIdleCpu{}", 7u8.wrapping_sub(id as u8)),
|
||||
);
|
||||
let mut cx = Pcpu::new(cpu.id(), Arc::downgrade(&idle));
|
||||
|
||||
// Enter dispatch loop.
|
||||
|
@ -20,7 +20,7 @@ use std::collections::HashMap;
|
||||
use std::ffi::{c_char, c_int};
|
||||
use std::mem::{size_of, transmute, zeroed};
|
||||
use std::num::NonZeroI32;
|
||||
use std::sync::atomic::AtomicI32;
|
||||
use std::sync::atomic::{AtomicI32, Ordering};
|
||||
use std::sync::{Arc, RwLockWriteGuard, Weak};
|
||||
use thiserror::Error;
|
||||
|
||||
@ -30,6 +30,7 @@ pub use self::binary::*;
|
||||
pub use self::cpuset::*;
|
||||
pub use self::filedesc::*;
|
||||
pub use self::group::*;
|
||||
pub use self::pcb::*;
|
||||
pub use self::pid::*;
|
||||
pub use self::proc::*;
|
||||
pub use self::rlimit::*;
|
||||
@ -44,6 +45,7 @@ mod binary;
|
||||
mod cpuset;
|
||||
mod filedesc;
|
||||
mod group;
|
||||
mod pcb;
|
||||
mod pid;
|
||||
mod proc;
|
||||
mod rlimit;
|
||||
@ -56,7 +58,9 @@ mod zombie;
|
||||
pub struct ProcManager {
|
||||
fs: Arc<Fs>,
|
||||
rc: Arc<RcMgr>,
|
||||
proc0: Arc<VProc>, // proc0
|
||||
proc0: Arc<VProc>, // proc0
|
||||
thread0: Arc<VThread>, // thread0
|
||||
idle: Arc<VProc>,
|
||||
procs: Gutex<HashMap<Pid, Weak<VProc>>>, // allproc + pidhashtbl + zombproc
|
||||
sessions: Gutex<HashMap<Pid, Weak<VSession>>>,
|
||||
groups: Gutex<HashMap<Pid, Weak<VProcGroup>>>, // pgrphashtbl
|
||||
@ -75,28 +79,49 @@ impl ProcManager {
|
||||
sys: &mut Syscalls,
|
||||
) -> Result<Arc<Self>, ProcManagerError> {
|
||||
// Setup proc0.
|
||||
let root = fs.root();
|
||||
let events = Arc::default();
|
||||
let proc0 = VProc::new(
|
||||
Pid::KERNEL,
|
||||
"kernel",
|
||||
kern.clone(),
|
||||
ProcAbi::new(None),
|
||||
None,
|
||||
None,
|
||||
DmemContainer::Zero,
|
||||
fs.root(),
|
||||
root.clone(),
|
||||
"",
|
||||
&events,
|
||||
)
|
||||
.map_err(ProcManagerError::CreateProc0Failed)?;
|
||||
|
||||
// Setup thread0.
|
||||
let thread0 = VThread::new(&proc0, NonZeroI32::new(Self::PID_MAX + 1).unwrap(), &events);
|
||||
|
||||
proc0.threads_mut().push(thread0.clone());
|
||||
|
||||
// Create idle process.
|
||||
let idle = VProc::new(
|
||||
Pid::IDLE,
|
||||
"idle",
|
||||
kern.clone(),
|
||||
ProcAbi::new(None),
|
||||
None,
|
||||
None,
|
||||
DmemContainer::Zero,
|
||||
root.clone(),
|
||||
"",
|
||||
&events,
|
||||
)
|
||||
.map_err(ProcManagerError::CreateIdleFailed)?;
|
||||
|
||||
// Setup process list.
|
||||
let proc0 = Arc::new(proc0);
|
||||
let mut list = HashMap::new();
|
||||
let last_pid = 0;
|
||||
let id = proc0.id();
|
||||
|
||||
assert_eq!(id, last_pid);
|
||||
assert!(list.insert(id, Arc::downgrade(&proc0)).is_none());
|
||||
assert_eq!(proc0.id(), last_pid);
|
||||
assert!(list.insert(proc0.id(), Arc::downgrade(&proc0)).is_none());
|
||||
assert!(list.insert(idle.id(), Arc::downgrade(&idle)).is_none());
|
||||
|
||||
// Register syscalls.
|
||||
let gg = GutexGroup::new();
|
||||
@ -104,6 +129,8 @@ impl ProcManager {
|
||||
fs: fs.clone(),
|
||||
rc: rc.clone(),
|
||||
proc0,
|
||||
thread0,
|
||||
idle,
|
||||
procs: gg.spawn(list),
|
||||
sessions: gg.spawn(HashMap::new()),
|
||||
groups: gg.spawn(HashMap::new()),
|
||||
@ -134,6 +161,14 @@ impl ProcManager {
|
||||
&self.proc0
|
||||
}
|
||||
|
||||
pub fn thread0(&self) -> &Arc<VThread> {
|
||||
&self.thread0
|
||||
}
|
||||
|
||||
pub fn idle(&self) -> &Arc<VProc> {
|
||||
&self.idle
|
||||
}
|
||||
|
||||
pub fn events(&self) -> RwLockWriteGuard<ProcEvents> {
|
||||
self.events.lock()
|
||||
}
|
||||
@ -149,7 +184,7 @@ impl ProcManager {
|
||||
root: Arc<Vnode>,
|
||||
system_path: impl Into<String>,
|
||||
kernel: bool,
|
||||
) -> Result<Arc<VProc>, SpawnError> {
|
||||
) -> Result<Arc<VThread>, SpawnError> {
|
||||
use std::collections::hash_map::Entry;
|
||||
|
||||
// Get credential.
|
||||
@ -165,6 +200,7 @@ impl ProcManager {
|
||||
let pid = self.alloc_pid(kernel);
|
||||
let proc = VProc::new(
|
||||
pid,
|
||||
"", // TODO: Copy from parent process.
|
||||
Arc::new(cred),
|
||||
abi,
|
||||
Some(budget_id),
|
||||
@ -175,14 +211,22 @@ impl ProcManager {
|
||||
&self.events,
|
||||
)?;
|
||||
|
||||
// Create main thread.
|
||||
let td = VThread::new(
|
||||
&proc,
|
||||
NonZeroI32::new(NEXT_TID.fetch_add(1, Ordering::Relaxed)).unwrap(),
|
||||
&self.events,
|
||||
);
|
||||
|
||||
proc.threads_mut().push(td.clone());
|
||||
|
||||
// Add to list.
|
||||
let proc = Arc::new(proc);
|
||||
let weak = Arc::downgrade(&proc);
|
||||
let mut list = self.procs.write();
|
||||
|
||||
match list.entry(proc.id()) {
|
||||
Entry::Occupied(mut e) => {
|
||||
assert!(e.insert(weak).upgrade().is_none());
|
||||
assert_eq!(e.insert(weak).strong_count(), 0);
|
||||
}
|
||||
Entry::Vacant(e) => {
|
||||
e.insert(weak);
|
||||
@ -191,7 +235,26 @@ impl ProcManager {
|
||||
|
||||
drop(list);
|
||||
|
||||
Ok(proc)
|
||||
Ok(td)
|
||||
}
|
||||
|
||||
/// See `kthread_add` on the PS4 for a reference.
|
||||
pub fn spawn_kthread(
|
||||
&self,
|
||||
proc: Option<&Arc<VProc>>,
|
||||
name: impl Into<String>,
|
||||
) -> Arc<VThread> {
|
||||
let proc = proc.unwrap_or(&self.proc0);
|
||||
let td = VThread::new(
|
||||
proc,
|
||||
NonZeroI32::new(NEXT_TID.fetch_add(1, Ordering::Relaxed)).unwrap(),
|
||||
&self.events,
|
||||
);
|
||||
|
||||
proc.threads_mut().push(td.clone());
|
||||
|
||||
// TODO: Implement remaining logics.
|
||||
td
|
||||
}
|
||||
|
||||
fn sys_getpid(self: &Arc<Self>, td: &Arc<VThread>, _: &SysIn) -> Result<SysOut, SysErr> {
|
||||
@ -403,11 +466,11 @@ impl ProcManager {
|
||||
|
||||
fn sys_thr_set_name(self: &Arc<Self>, td: &Arc<VThread>, i: &SysIn) -> Result<SysOut, SysErr> {
|
||||
let tid: i64 = i.args[0].into();
|
||||
let name: Option<&str> = unsafe { i.args[1].to_str(32) }?;
|
||||
let name = unsafe { i.args[1].to_str(32)?.unwrap_or("") };
|
||||
let proc = td.proc();
|
||||
|
||||
if tid == -1 {
|
||||
info!("Setting process name to '{}'.", name.unwrap_or("NULL"));
|
||||
info!("Setting process name to '{name}'.");
|
||||
|
||||
proc.set_name(name);
|
||||
} else {
|
||||
@ -417,13 +480,9 @@ impl ProcManager {
|
||||
.find(|t| t.id().get() == tid as i32)
|
||||
.ok_or(SysErr::Raw(ESRCH))?;
|
||||
|
||||
info!(
|
||||
"Setting name of thread {} to '{}'.",
|
||||
thr.id(),
|
||||
name.unwrap_or("NULL")
|
||||
);
|
||||
info!("Setting name of thread {} to '{}'.", thr.id(), name);
|
||||
|
||||
thr.set_name(name);
|
||||
thr.set_name(Some(name));
|
||||
}
|
||||
|
||||
Ok(SysOut::ZERO)
|
||||
@ -795,7 +854,10 @@ impl ProcManager {
|
||||
/// Events that related to a process.
|
||||
#[derive(Default)]
|
||||
pub struct ProcEvents {
|
||||
pub init: Event<fn(&mut VProc)>, // process_init
|
||||
pub process_init: Event<fn(&mut VProc)>,
|
||||
pub process_ctor: Event<fn(&Weak<VProc>)>,
|
||||
pub thread_init: Event<fn(&mut VThread)>,
|
||||
pub thread_ctor: Event<fn(&Weak<VThread>)>,
|
||||
}
|
||||
|
||||
/// Implementation of `thr_param` structure.
|
||||
@ -882,6 +944,9 @@ bitflags! {
|
||||
pub enum ProcManagerError {
|
||||
#[error("couldn't create proc0")]
|
||||
CreateProc0Failed(#[source] SpawnError),
|
||||
|
||||
#[error("couldn't create idle proc")]
|
||||
CreateIdleFailed(#[source] SpawnError),
|
||||
}
|
||||
|
||||
/// Represents an error when [`ProcManager::spawn()`] fails.
|
||||
@ -894,4 +959,5 @@ pub enum SpawnError {
|
||||
VmInitFailed(#[from] MemoryManagerError),
|
||||
}
|
||||
|
||||
static NEXT_ID: AtomicI32 = AtomicI32::new(123);
|
||||
// TODO: Use a proper implementation.
|
||||
static NEXT_TID: AtomicI32 = AtomicI32::new(ProcManager::PID_MAX + 2);
|
||||
|
24
src/kernel/src/process/pcb.rs
Normal file
24
src/kernel/src/process/pcb.rs
Normal file
@ -0,0 +1,24 @@
|
||||
use bitflags::bitflags;
|
||||
|
||||
/// Implementation of `pcb` structure.
|
||||
#[derive(Default)]
|
||||
pub struct Pcb {
|
||||
pub r15: usize, // pcb_r15
|
||||
pub r14: usize, // pcb_r14
|
||||
pub r13: usize, // pcb_r13
|
||||
pub r12: usize, // pcb_r12
|
||||
pub rbp: usize, // pcb_rbp
|
||||
pub rsp: usize, // pcb_rsp
|
||||
pub rbx: usize, // pcb_rbx
|
||||
pub rip: usize, // pcb_rip
|
||||
pub fsbase: usize, // pcb_fsbase
|
||||
pub flags: PcbFlags, // pcb_flags
|
||||
}
|
||||
|
||||
bitflags! {
|
||||
/// Flags of [`Pcb`].
|
||||
#[derive(Default)]
|
||||
pub struct PcbFlags: u32 {
|
||||
const PCB_FULL_IRET = 0x01;
|
||||
}
|
||||
}
|
@ -8,6 +8,7 @@ pub struct Pid(i32);
|
||||
|
||||
impl Pid {
|
||||
pub const KERNEL: Self = Self(0);
|
||||
pub const IDLE: Self = Self(10);
|
||||
|
||||
/// Returns [`None`] if `v` is negative.
|
||||
pub const fn new(v: i32) -> Option<Self> {
|
||||
|
@ -17,9 +17,9 @@ use std::sync::atomic::AtomicPtr;
|
||||
use std::sync::Arc;
|
||||
|
||||
/// An implementation of `proc` structure.
|
||||
#[derive(Debug)]
|
||||
pub struct VProc {
|
||||
id: Pid, // p_pid
|
||||
name: Gutex<String>, // p_comm
|
||||
state: Gutex<ProcState>, // p_state
|
||||
threads: Gutex<Vec<Arc<VThread>>>, // p_threads
|
||||
cred: Arc<Ucred>, // p_ucred
|
||||
@ -30,7 +30,6 @@ pub struct VProc {
|
||||
files: Arc<FileDesc>, // p_fd
|
||||
system_path: String, // p_randomized_path
|
||||
limits: Limits, // p_limit
|
||||
comm: Gutex<Option<String>>, // p_comm
|
||||
bin: Gutex<Option<Binaries>>, // p_dynlib?
|
||||
objects: Gutex<Idt<Arc<dyn Any + Send + Sync>>>,
|
||||
budget_id: Option<usize>,
|
||||
@ -42,8 +41,9 @@ pub struct VProc {
|
||||
}
|
||||
|
||||
impl VProc {
|
||||
pub fn new(
|
||||
pub(super) fn new(
|
||||
id: Pid,
|
||||
name: impl Into<String>,
|
||||
cred: Arc<Ucred>,
|
||||
abi: ProcAbi,
|
||||
budget_id: Option<usize>,
|
||||
@ -52,12 +52,13 @@ impl VProc {
|
||||
root: Arc<Vnode>,
|
||||
system_path: impl Into<String>,
|
||||
events: &Arc<EventSet<ProcEvents>>,
|
||||
) -> Result<Self, SpawnError> {
|
||||
) -> Result<Arc<Self>, SpawnError> {
|
||||
let gg = GutexGroup::new();
|
||||
let limits = Limits::load()?;
|
||||
let vm_space = VmSpace::new()?;
|
||||
let mut vp = Self {
|
||||
let mut proc = Self {
|
||||
id,
|
||||
name: gg.spawn(name.into()),
|
||||
state: gg.spawn(ProcState::Active(ActiveProc::new())),
|
||||
threads: gg.spawn(Vec::new()),
|
||||
cred,
|
||||
@ -72,18 +73,30 @@ impl VProc {
|
||||
budget_ptype,
|
||||
dmem_container: gg.spawn(dmem_container),
|
||||
limits,
|
||||
comm: gg.spawn(None), //TODO: Find out how this is actually set
|
||||
bin: gg.spawn(None),
|
||||
app_info: AppInfo::new(),
|
||||
ptc: 0,
|
||||
uptc: AtomicPtr::new(null_mut()),
|
||||
};
|
||||
|
||||
for h in events.trigger().select(|s| &s.init) {
|
||||
h(&mut vp);
|
||||
// Trigger process_init event.
|
||||
let mut et = events.trigger();
|
||||
|
||||
for h in et.select(|s| &s.process_init) {
|
||||
h(&mut proc);
|
||||
}
|
||||
|
||||
Ok(vp)
|
||||
// Trigger process_ctor event.
|
||||
let proc = Arc::new(proc);
|
||||
let weak = Arc::downgrade(&proc);
|
||||
|
||||
for h in et.select(|s| &s.process_ctor) {
|
||||
h(&weak);
|
||||
}
|
||||
|
||||
drop(et);
|
||||
|
||||
Ok(proc)
|
||||
}
|
||||
|
||||
pub fn id(&self) -> Pid {
|
||||
@ -130,8 +143,8 @@ impl VProc {
|
||||
&self.limits[ty]
|
||||
}
|
||||
|
||||
pub fn set_name(&self, name: Option<&str>) {
|
||||
*self.comm.write() = name.map(|n| n.to_owned());
|
||||
pub fn set_name(&self, name: impl Into<String>) {
|
||||
*self.name.write() = name.into();
|
||||
}
|
||||
|
||||
pub fn bin(&self) -> GutexReadGuard<Option<Binaries>> {
|
||||
|
@ -1,22 +1,18 @@
|
||||
use super::{CpuMask, CpuSet, VProc, NEXT_ID};
|
||||
use super::{CpuMask, CpuSet, Pcb, ProcEvents, VProc};
|
||||
use crate::errno::Errno;
|
||||
use crate::event::EventSet;
|
||||
use crate::fs::VFile;
|
||||
use crate::signal::SignalSet;
|
||||
use crate::ucred::{CanSeeError, Privilege, PrivilegeError, Ucred};
|
||||
use bitflags::bitflags;
|
||||
use gmtx::{Gutex, GutexGroup, GutexReadGuard, GutexWriteGuard};
|
||||
use llt::{OsThread, SpawnError};
|
||||
use macros::Errno;
|
||||
use std::num::NonZeroI32;
|
||||
use std::sync::atomic::Ordering;
|
||||
use std::sync::Arc;
|
||||
use thiserror::Error;
|
||||
use tls::{Local, Tls};
|
||||
|
||||
/// An implementation of `thread` structure for the main application.
|
||||
///
|
||||
/// See [`super::VProc`] for more information.
|
||||
#[derive(Debug)]
|
||||
/// An implementation of `thread` structure.
|
||||
pub struct VThread {
|
||||
proc: Arc<VProc>, // td_proc
|
||||
id: NonZeroI32, // td_tid
|
||||
@ -31,26 +27,44 @@ pub struct VThread {
|
||||
}
|
||||
|
||||
impl VThread {
|
||||
pub fn new(proc: Arc<VProc>) -> Self {
|
||||
// TODO: Check how the PS4 actually allocate the thread ID.
|
||||
pub(super) fn new(
|
||||
proc: &Arc<VProc>,
|
||||
id: NonZeroI32,
|
||||
events: &Arc<EventSet<ProcEvents>>,
|
||||
) -> Arc<Self> {
|
||||
let gg = GutexGroup::new();
|
||||
let cred = proc.cred().clone();
|
||||
|
||||
Self {
|
||||
proc,
|
||||
id: NonZeroI32::new(NEXT_ID.fetch_add(1, Ordering::Relaxed)).unwrap(),
|
||||
let mut td = Self {
|
||||
proc: proc.clone(),
|
||||
id,
|
||||
cred,
|
||||
sigmask: gg.spawn(SignalSet::default()),
|
||||
pri_class: 3, // TODO: Check the actual value on the PS4 when a thread is created.
|
||||
base_user_pri: 700, // TODO: Same here.
|
||||
pcb: gg.spawn(Pcb {
|
||||
fsbase: 0,
|
||||
flags: PcbFlags::empty(),
|
||||
}),
|
||||
pcb: gg.spawn(Pcb::default()),
|
||||
cpuset: CpuSet::new(CpuMask::default()), // TODO: Same here.
|
||||
name: gg.spawn(None), // TODO: Same here
|
||||
fpop: gg.spawn(None),
|
||||
};
|
||||
|
||||
// Trigger thread_init event.
|
||||
let mut et = events.trigger();
|
||||
|
||||
for h in et.select(|s| &s.thread_init) {
|
||||
h(&mut td);
|
||||
}
|
||||
|
||||
// Trigger thread_ctor event.
|
||||
let td = Arc::new(td);
|
||||
let weak = Arc::downgrade(&td);
|
||||
|
||||
for h in et.select(|s| &s.thread_ctor) {
|
||||
h(&weak);
|
||||
}
|
||||
|
||||
drop(et);
|
||||
|
||||
td
|
||||
}
|
||||
|
||||
/// Return [`None`] if the calling thread is not a PS4 thread.
|
||||
@ -133,7 +147,7 @@ impl VThread {
|
||||
/// The range of memory specified by `stack` and `stack_size` must be valid throughout lifetime
|
||||
/// of the thread. Specify an unaligned stack will cause undefined behavior.
|
||||
pub unsafe fn start<F>(
|
||||
self,
|
||||
self: &Arc<Self>,
|
||||
stack: *mut u8,
|
||||
stack_size: usize,
|
||||
mut routine: F,
|
||||
@ -141,12 +155,7 @@ impl VThread {
|
||||
where
|
||||
F: FnMut() + Send + 'static,
|
||||
{
|
||||
let proc = self.proc.clone();
|
||||
let td = Arc::new(self);
|
||||
let running = Running(td.clone());
|
||||
// Lock the list before spawn the thread to prevent race condition if the new thread run
|
||||
// too fast and found out they is not in our list.
|
||||
let mut threads = proc.threads_mut();
|
||||
let running = Running(self.clone());
|
||||
let raw = llt::spawn(stack, stack_size, move || {
|
||||
// This closure must not have any variables that need to be dropped on the stack. The
|
||||
// reason is because this thread will be exited without returning from the routine. That
|
||||
@ -155,42 +164,10 @@ impl VThread {
|
||||
routine();
|
||||
})?;
|
||||
|
||||
// Add to the list.
|
||||
threads.push(td);
|
||||
|
||||
Ok(raw)
|
||||
}
|
||||
}
|
||||
|
||||
/// An implementation of `pcb` structure.
|
||||
#[derive(Debug)]
|
||||
pub struct Pcb {
|
||||
fsbase: usize, // pcb_fsbase
|
||||
flags: PcbFlags, // pcb_flags
|
||||
}
|
||||
|
||||
impl Pcb {
|
||||
pub fn fsbase(&self) -> usize {
|
||||
self.fsbase
|
||||
}
|
||||
|
||||
pub fn set_fsbase(&mut self, v: usize) {
|
||||
self.fsbase = v;
|
||||
}
|
||||
|
||||
pub fn flags_mut(&mut self) -> &mut PcbFlags {
|
||||
&mut self.flags
|
||||
}
|
||||
}
|
||||
|
||||
bitflags! {
|
||||
/// Flags of [`Pcb`].
|
||||
#[derive(Debug)]
|
||||
pub struct PcbFlags: u32 {
|
||||
const PCB_FULL_IRET = 0x01;
|
||||
}
|
||||
}
|
||||
|
||||
// An object for removing the thread from the list when dropped.
|
||||
struct Running(Arc<VThread>);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user