proc: spawn_thread/exit_thread/wait_thread
This commit is contained in:
parent
58008d8704
commit
3383d0350c
1
Cargo.lock
generated
1
Cargo.lock
generated
@ -2115,7 +2115,6 @@ dependencies = [
|
||||
"atomic_enum",
|
||||
"bitflags 2.4.2",
|
||||
"bytemuck",
|
||||
"cfg-if",
|
||||
"crossbeam-queue",
|
||||
"device-api",
|
||||
"device-api-macros",
|
||||
|
@ -40,7 +40,6 @@ bitflags = "2.3.3"
|
||||
spinning_top = "0.2.5"
|
||||
static_assertions = "1.1.0"
|
||||
tock-registers = "0.8.1"
|
||||
cfg-if = "1.0.0"
|
||||
git-version = "0.3.5"
|
||||
log = "0.4.20"
|
||||
futures-util = { version = "0.3.28", default-features = false, features = ["alloc", "async-await"] }
|
||||
@ -70,6 +69,12 @@ kernel-arch-x86_64 = { path = "arch/x86_64" }
|
||||
prettyplease = "0.2.15"
|
||||
abi-generator = { path = "../tool/abi-generator" }
|
||||
|
||||
# To make rust-analyzer recognize those
|
||||
[dev-dependencies]
|
||||
aarch64-cpu = "9.3.1"
|
||||
device-tree = { path = "lib/device-tree" }
|
||||
kernel-arch-aarch64 = { path = "arch/aarch64" }
|
||||
|
||||
[features]
|
||||
default = ["fb_console"]
|
||||
fb_console = []
|
||||
|
@ -128,7 +128,7 @@ pub fn load(file: FileRef) -> Result<LoadedModule, Error> {
|
||||
let name = dynstr.get(sym.st_name as _).unwrap();
|
||||
|
||||
if sym.st_shndx == elf::abi::SHN_UNDEF && sym.st_bind() != elf::abi::STB_LOCAL {
|
||||
let Some(value) = lookup_symbol(&name) else {
|
||||
let Some(value) = lookup_symbol(name) else {
|
||||
log::warn!("Could not load module: undefined reference to {:?} (possibly compiled against a different libk?)", name);
|
||||
return Err(Error::InvalidArgument);
|
||||
};
|
||||
|
@ -132,6 +132,7 @@ pub fn open_elf_file<F: Read + Seek>(file: Arc<F>) -> Result<ElfKind<F>, Error>
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(clippy::type_complexity)]
|
||||
pub fn open_elf_direct<F: Read + Seek>(
|
||||
file: Arc<F>,
|
||||
) -> Result<(ElfStream<AnyEndian, FileReader<Arc<F>>>, FileReader<Arc<F>>), Error> {
|
||||
|
@ -7,10 +7,13 @@ use alloc::{
|
||||
sync::{Arc, Weak},
|
||||
vec::Vec,
|
||||
};
|
||||
use kernel_arch::KernelTableManagerImpl;
|
||||
use kernel_arch::{
|
||||
task::{TaskContext, UserContextInfo},
|
||||
KernelTableManagerImpl,
|
||||
};
|
||||
use libk_mm::{phys::GlobalPhysicalAllocator, process::ProcessAddressSpace};
|
||||
use libk_util::{
|
||||
event::OneTimeEvent,
|
||||
event::{BoolEvent, OneTimeEvent},
|
||||
sync::{
|
||||
spin_rwlock::{IrqSafeRwLock, IrqSafeRwLockWriteGuard},
|
||||
IrqSafeSpinlock,
|
||||
@ -23,6 +26,7 @@ use yggdrasil_abi::{
|
||||
|
||||
use crate::{
|
||||
task::{
|
||||
binary,
|
||||
futex::UserspaceMutex,
|
||||
thread::Thread,
|
||||
types::{AllocateProcessId, ProcessTlsInfo},
|
||||
@ -62,6 +66,8 @@ pub struct ProcessInner {
|
||||
mutexes: BTreeMap<usize, Arc<UserspaceMutex>>,
|
||||
space: Option<Arc<ProcessAddressSpace>>,
|
||||
image: Option<ProcessImage>,
|
||||
|
||||
thread_exits: BTreeMap<ThreadId, Arc<BoolEvent>>,
|
||||
}
|
||||
|
||||
/// Describes a process within the system
|
||||
@ -106,7 +112,7 @@ impl Process {
|
||||
|
||||
// Create "main" thread
|
||||
let thread = Thread::new_uthread(process.id, space, context);
|
||||
process.inner.write().threads.push(thread.clone());
|
||||
process.inner.write().register_thread(thread.clone());
|
||||
|
||||
MANAGER.register_process(process.clone());
|
||||
|
||||
@ -123,33 +129,33 @@ impl Process {
|
||||
/// Spawns a new child thread within the process
|
||||
pub fn spawn_thread(self: &Arc<Self>, options: &ThreadSpawnOptions) -> Result<ThreadId, Error> {
|
||||
log::debug!("Spawn thread in {} with options: {:#x?}", self.id, options);
|
||||
// let mut inner = self.inner.write();
|
||||
let mut inner = self.inner.write();
|
||||
|
||||
// let space = inner.space.clone().unwrap();
|
||||
let space = inner.space.clone().unwrap();
|
||||
|
||||
todo!()
|
||||
// XXX
|
||||
// let tls_address = if let Some(image) = inner.image.as_ref() {
|
||||
// proc::elf::clone_tls(&space, image)?
|
||||
// } else {
|
||||
// 0
|
||||
// };
|
||||
let tls_address = if let Some(image) = inner.image.as_ref() {
|
||||
binary::elf::clone_tls(&space, image)?
|
||||
} else {
|
||||
0
|
||||
};
|
||||
|
||||
// let context = TaskContextImpl::user(
|
||||
// options.entry as _,
|
||||
// options.argument as _,
|
||||
// space.as_address_with_asid(),
|
||||
// options.stack_top,
|
||||
// tls_address,
|
||||
// )?;
|
||||
// let thread = Thread::new_uthread(self.clone(), space.clone(), context);
|
||||
// let id = thread.id;
|
||||
let info = UserContextInfo {
|
||||
entry: options.entry as _,
|
||||
argument: options.argument as _,
|
||||
address_space: space.as_address_with_asid(),
|
||||
stack_pointer: options.stack_top,
|
||||
single_step: false,
|
||||
tls: tls_address,
|
||||
};
|
||||
let context = TaskContextImpl::user(info)?;
|
||||
let thread = Thread::new_uthread(self.id, space.clone(), context);
|
||||
let id = thread.id;
|
||||
|
||||
// inner.add_thread(thread.clone());
|
||||
inner.register_thread(thread.clone());
|
||||
|
||||
// thread.enqueue();
|
||||
thread.enqueue();
|
||||
|
||||
// Ok(id)
|
||||
Ok(id)
|
||||
}
|
||||
|
||||
unsafe fn fork_inner<F: ForkFrame<Context = TaskContextImpl>>(
|
||||
@ -367,6 +373,20 @@ impl Process {
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn wait_for_thread(&self, thread: ThreadId) -> Result<(), Error> {
|
||||
let exit = {
|
||||
let inner = self.inner.read();
|
||||
inner
|
||||
.thread_exits
|
||||
.get(&thread)
|
||||
.cloned()
|
||||
.ok_or(Error::DoesNotExist)?
|
||||
};
|
||||
|
||||
exit.wait().await;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub async fn terminate_others(&self, except: ThreadId) {
|
||||
let mut inner = self.inner.write();
|
||||
|
||||
@ -399,10 +419,13 @@ impl ProcessInner {
|
||||
mutexes: BTreeMap::new(),
|
||||
image,
|
||||
space: space.clone(),
|
||||
|
||||
thread_exits: BTreeMap::new(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn add_thread(&mut self, thread: Arc<Thread>) {
|
||||
pub fn register_thread(&mut self, thread: Arc<Thread>) {
|
||||
self.thread_exits.insert(thread.id, thread.exit.clone());
|
||||
self.threads.push(thread);
|
||||
}
|
||||
|
||||
|
@ -75,7 +75,8 @@ pub struct Thread {
|
||||
inner: IrqSafeSpinlock<ThreadInner>,
|
||||
signal_queue: SegQueue<Signal>,
|
||||
|
||||
pub exit: BoolEvent,
|
||||
pub exit: Arc<BoolEvent>,
|
||||
|
||||
/// CPU scheduling affinity mask
|
||||
pub affinity: ThreadAffinity,
|
||||
}
|
||||
@ -125,7 +126,7 @@ impl Thread {
|
||||
|
||||
inner: IrqSafeSpinlock::new(ThreadInner { signal_entry: None }),
|
||||
signal_queue: SegQueue::new(),
|
||||
exit: BoolEvent::new(),
|
||||
exit: Arc::new(BoolEvent::new()),
|
||||
|
||||
affinity: ThreadAffinity::any_cpu(),
|
||||
});
|
||||
|
@ -25,7 +25,7 @@ pub struct ArmTimer {
|
||||
}
|
||||
|
||||
/// ARM timer tick interval (in some time units?)
|
||||
pub const TICK_INTERVAL: u64 = 1000000;
|
||||
pub const TICK_INTERVAL: u64 = 250000;
|
||||
|
||||
impl InterruptHandler for ArmTimer {
|
||||
fn handle_irq(&self, _vector: Option<usize>) -> bool {
|
||||
@ -76,36 +76,6 @@ impl Device for ArmTimer {
|
||||
}
|
||||
}
|
||||
|
||||
// impl TimestampSource for ArmTimer {
|
||||
// fn timestamp(&self) -> Result<Duration, Error> {
|
||||
// }
|
||||
// }
|
||||
|
||||
// impl InterruptSource for ArmTimer {
|
||||
// fn handle_irq(&self) -> Result<bool, Error> {
|
||||
// CNTP_TVAL_EL0.set(TICK_INTERVAL);
|
||||
// let t = self.timestamp()?;
|
||||
//
|
||||
// wait::tick(t);
|
||||
// tasklet::tick(t);
|
||||
//
|
||||
// unsafe {
|
||||
// Cpu::local().queue().yield_cpu();
|
||||
// }
|
||||
//
|
||||
// Ok(true)
|
||||
// }
|
||||
//
|
||||
// unsafe fn init_irq(&'static self) -> Result<(), Error> {
|
||||
// let intc = PLATFORM.interrupt_controller();
|
||||
//
|
||||
// intc.register_handler(self.irq, self)?;
|
||||
// intc.enable_irq(self.irq)?;
|
||||
//
|
||||
// Ok(())
|
||||
// }
|
||||
// }
|
||||
|
||||
impl ArmTimer {
|
||||
/// Constructs an instance of ARM generic timer.
|
||||
///
|
||||
|
@ -2,7 +2,6 @@
|
||||
|
||||
use abi::error::Error;
|
||||
|
||||
use cfg_if::cfg_if;
|
||||
use device_api::{
|
||||
interrupt::{IpiDeliveryTarget, IpiMessage},
|
||||
ResetDevice,
|
||||
@ -10,19 +9,18 @@ use device_api::{
|
||||
use kernel_arch::{Architecture, ArchitectureImpl};
|
||||
use libk_mm::table::EntryLevel;
|
||||
|
||||
cfg_if! {
|
||||
if #[cfg(target_arch = "aarch64")] {
|
||||
pub mod aarch64;
|
||||
#[cfg(any(target_arch = "aarch64", rust_analyzer))]
|
||||
pub mod aarch64;
|
||||
#[cfg(any(target_arch = "aarch64", rust_analyzer))]
|
||||
pub use aarch64::{AArch64 as PlatformImpl, PLATFORM};
|
||||
|
||||
pub use aarch64::{AArch64 as PlatformImpl, PLATFORM};
|
||||
} else if #[cfg(target_arch = "x86_64")] {
|
||||
pub mod x86_64;
|
||||
#[cfg(any(target_arch = "x86_64", rust_analyzer))]
|
||||
pub mod x86_64;
|
||||
#[cfg(any(target_arch = "x86_64", rust_analyzer))]
|
||||
pub use x86_64::{PLATFORM, X86_64 as PlatformImpl};
|
||||
|
||||
pub use x86_64::{X86_64 as PlatformImpl, PLATFORM};
|
||||
} else {
|
||||
compile_error!("Architecture is not supported");
|
||||
}
|
||||
}
|
||||
#[cfg(not(any(target_arch = "x86_64", target_arch = "aarch64")))]
|
||||
compile_error!("Unsupported architecture");
|
||||
|
||||
/// Architecture-specific lowest level of page mapping
|
||||
pub type L3 = <PlatformImpl as Platform>::L3;
|
||||
|
@ -1,10 +1,4 @@
|
||||
//! Power-management related device drivers
|
||||
|
||||
use cfg_if::cfg_if;
|
||||
|
||||
cfg_if! {
|
||||
if #[cfg(target_arch = "aarch64")] {
|
||||
pub mod arm_psci;
|
||||
// pub mod sunxi_rwdog;
|
||||
}
|
||||
}
|
||||
#[cfg(any(target_arch = "aarch64", rust_analyzer))]
|
||||
pub mod arm_psci;
|
||||
|
@ -1,10 +1,4 @@
|
||||
//! Serial device interfaces
|
||||
|
||||
use cfg_if::cfg_if;
|
||||
|
||||
cfg_if! {
|
||||
if #[cfg(target_arch = "aarch64")] {
|
||||
pub mod pl011;
|
||||
// pub mod sunxi_uart;
|
||||
}
|
||||
}
|
||||
#[cfg(any(target_arch = "aarch64", rust_analyzer))]
|
||||
pub mod pl011;
|
||||
|
@ -219,7 +219,7 @@ impl Device for Pl011 {
|
||||
|
||||
self.inner.init(IrqSafeSpinlock::new(inner));
|
||||
|
||||
debug::add_sink(self, LogLevel::Info);
|
||||
debug::add_sink(self, LogLevel::Debug);
|
||||
devfs::add_char_device(self, CharDeviceType::TtySerial)?;
|
||||
|
||||
Ok(())
|
||||
|
@ -2,14 +2,14 @@
|
||||
|
||||
use core::sync::atomic::Ordering;
|
||||
|
||||
use abi::{error::Error, io::OpenOptions};
|
||||
use alloc::{format, string::String, sync::Arc};
|
||||
use abi::error::Error;
|
||||
use alloc::{format, string::String};
|
||||
use git_version::git_version;
|
||||
use libk::{
|
||||
task::{cpu_count, process::Process, sched},
|
||||
task::{cpu_count, sched},
|
||||
vfs::{
|
||||
impls::{const_value_node, mdir, read_fn_node, ReadOnlyFnValueNode},
|
||||
CommonImpl, InstanceData, NodeRef, RegularImpl,
|
||||
NodeRef,
|
||||
},
|
||||
};
|
||||
use libk_mm::phys;
|
||||
|
@ -6,12 +6,13 @@ use abi::{
|
||||
mem::MappingSource,
|
||||
process::{
|
||||
ExitCode, MutexOperation, ProcessGroupId, ProcessId, Signal, SpawnOption, SpawnOptions,
|
||||
ThreadSpawnOptions,
|
||||
},
|
||||
};
|
||||
use alloc::sync::Arc;
|
||||
use libk::{
|
||||
block,
|
||||
task::{debug::ThreadDebugger, process::Process, runtime, thread::Thread},
|
||||
task::{debug::ThreadDebugger, process::Process, runtime, thread::Thread, ThreadId},
|
||||
vfs::IoContext,
|
||||
};
|
||||
use libk_mm::{
|
||||
@ -236,3 +237,28 @@ pub(crate) fn start_session() -> Result<(), Error> {
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub(crate) fn spawn_thread(options: &ThreadSpawnOptions) -> Result<u32, Error> {
|
||||
let thread = Thread::current();
|
||||
let process = thread.process();
|
||||
|
||||
process
|
||||
.spawn_thread(options)
|
||||
.map(|tid| tid.as_user() as u32)
|
||||
}
|
||||
|
||||
pub(crate) fn exit_thread() -> ! {
|
||||
let thread = Thread::current();
|
||||
// TODO exit codes are not supported in here
|
||||
thread.exit(ExitCode::SUCCESS)
|
||||
}
|
||||
|
||||
pub(crate) fn wait_thread(id: u32) -> Result<(), Error> {
|
||||
let tid = ThreadId::User(id as u64);
|
||||
let this_thread = Thread::current();
|
||||
let process = this_thread.process();
|
||||
|
||||
block!(process.wait_for_thread(tid).await)??;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
@ -39,7 +39,7 @@ mod generated {
|
||||
|
||||
use abi::{
|
||||
io::ChannelPublisherId,
|
||||
process::{ExecveOptions, ProcessId},
|
||||
process::{ExecveOptions, ProcessId, ThreadSpawnOptions},
|
||||
SyscallFunction,
|
||||
};
|
||||
use abi_lib::SyscallRegister;
|
||||
|
@ -63,6 +63,11 @@ syscall spawn_process(options: &SpawnOptions<'_>) -> Result<ProcessId>;
|
||||
syscall wait_process(pid: ProcessId, status: &mut ExitCode) -> Result<()>;
|
||||
syscall get_pid() -> ProcessId;
|
||||
|
||||
// TODO use ThreadId
|
||||
syscall spawn_thread(options: &ThreadSpawnOptions) -> Result<u32>;
|
||||
syscall exit_thread() -> !;
|
||||
syscall wait_thread(tid: u32) -> Result<()>;
|
||||
|
||||
syscall nanosleep(dur: &Duration) -> Result<()>;
|
||||
|
||||
syscall exit_signal(frame: &SignalEntryData) -> !;
|
||||
|
@ -20,6 +20,7 @@ mod generated {
|
||||
net::SocketType,
|
||||
process::{
|
||||
ExecveOptions, ProcessGroupId, ProcessId, Signal, SignalEntryData, SpawnOptions,
|
||||
ThreadSpawnOptions,
|
||||
},
|
||||
SyscallFunction,
|
||||
};
|
||||
|
Loading…
x
Reference in New Issue
Block a user