starry_api/imp/task/
thread.rs

1use axerrno::LinuxResult;
2use axtask::{TaskExtRef, current};
3use num_enum::TryFromPrimitive;
4
5pub fn sys_getpid() -> LinuxResult<isize> {
6    Ok(axtask::current().task_ext().thread.process().pid() as _)
7}
8
9pub fn sys_getppid() -> LinuxResult<isize> {
10    Ok(axtask::current()
11        .task_ext()
12        .thread
13        .process()
14        .parent()
15        .unwrap()
16        .pid() as _)
17}
18
19pub fn sys_gettid() -> LinuxResult<isize> {
20    Ok(axtask::current().id().as_u64() as _)
21}
22
23/// ARCH_PRCTL codes
24///
25/// It is only avaliable on x86_64, and is not convenient
26/// to generate automatically via c_to_rust binding.
27#[derive(Debug, Eq, PartialEq, TryFromPrimitive)]
28#[repr(i32)]
29enum ArchPrctlCode {
30    /// Set the GS segment base
31    SetGs = 0x1001,
32    /// Set the FS segment base
33    SetFs = 0x1002,
34    /// Get the FS segment base
35    GetFs = 0x1003,
36    /// Get the GS segment base
37    GetGs = 0x1004,
38    /// The setting of the flag manipulated by ARCH_SET_CPUID
39    GetCpuid = 0x1011,
40    /// Enable (addr != 0) or disable (addr == 0) the cpuid instruction for the calling thread.
41    SetCpuid = 0x1012,
42}
43
44/// To set the clear_child_tid field in the task extended data.
45///
46/// The set_tid_address() always succeeds
47pub fn sys_set_tid_address(clear_child_tid: usize) -> LinuxResult<isize> {
48    let curr = current();
49    curr.task_ext()
50        .thread_data()
51        .set_clear_child_tid(clear_child_tid);
52    Ok(curr.id().as_u64() as isize)
53}
54
55#[cfg(target_arch = "x86_64")]
56pub fn sys_arch_prctl(
57    tf: &mut axhal::arch::TrapFrame,
58    code: i32,
59    addr: usize,
60) -> LinuxResult<isize> {
61    use crate::ptr::UserPtr;
62
63    let code = ArchPrctlCode::try_from(code).map_err(|_| axerrno::LinuxError::EINVAL)?;
64    debug!("sys_arch_prctl: code = {:?}, addr = {:#x}", code, addr);
65
66    match code {
67        // According to Linux implementation, SetFs & SetGs does not return
68        // error at all
69        ArchPrctlCode::GetFs => {
70            *UserPtr::from(addr).get_as_mut()? = tf.tls();
71            Ok(0)
72        }
73        ArchPrctlCode::SetFs => {
74            tf.set_tls(addr);
75            Ok(0)
76        }
77        ArchPrctlCode::GetGs => {
78            *UserPtr::from(addr).get_as_mut()? =
79                unsafe { x86::msr::rdmsr(x86::msr::IA32_KERNEL_GSBASE) };
80            Ok(0)
81        }
82        ArchPrctlCode::SetGs => {
83            unsafe {
84                x86::msr::wrmsr(x86::msr::IA32_KERNEL_GSBASE, addr as _);
85            }
86            Ok(0)
87        }
88        ArchPrctlCode::GetCpuid => Ok(0),
89        ArchPrctlCode::SetCpuid => Err(axerrno::LinuxError::ENODEV),
90    }
91}