Skip to main content

starnix_core/task/
task_running_state.rs

1// Copyright 2026 The Fuchsia Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5use crate::mm::MemoryManager;
6use crate::task::{AbstractUnixSocketNamespace, AbstractVsockSocketNamespace};
7use crate::vfs::{FdTable, FsContext, FsNodeHandle};
8use fuchsia_rcu::{RcuArc, RcuOptionArc, RcuOptionBox};
9use starnix_uapi::errno;
10use starnix_uapi::errors::Errno;
11use std::ops::Deref;
12use std::sync::{Arc, OnceLock};
13
14/// The running state of a task.
15///
16/// This structure contains the state of a task that is only relevant while the task is running. It
17/// is dropped when the task enters an exited state.
18pub struct TaskRunningState {
19    /// A handle to the underlying Zircon thread object.
20    ///
21    /// Some tasks lack an underlying Zircon thread. These tasks are used internally by the
22    /// Starnix kernel to track background work, typically on a `kthread`.
23    pub thread: OnceLock<ZirconThread>,
24
25    /// The file descriptor table for this task.
26    ///
27    /// This table can be share by many tasks.
28    pub files: FdTable,
29
30    /// The memory manager for this task.  This is `None` only for system tasks.
31    pub mm: RcuOptionArc<MemoryManager>,
32
33    /// The file system for this task.
34    pub fs: RcuArc<FsContext>,
35
36    /// The namespace for abstract AF_UNIX sockets for this task.
37    pub abstract_socket_namespace: Arc<AbstractUnixSocketNamespace>,
38
39    /// The namespace for AF_VSOCK for this task.
40    pub abstract_vsock_namespace: Arc<AbstractVsockSocketNamespace>,
41
42    /// The pid directory, so it doesn't have to be generated and thrown away on every access.
43    /// See https://fxbug.dev/291962828 for details.
44    pub proc_pid_directory_cache: RcuOptionBox<FsNodeHandle>,
45}
46
47impl TaskRunningState {
48    pub fn mm(&self) -> Result<Arc<MemoryManager>, Errno> {
49        self.mm.to_option_arc().ok_or_else(|| errno!(EINVAL))
50    }
51
52    pub fn fs(&self) -> Arc<FsContext> {
53        self.fs.to_arc()
54    }
55}
56
57/// A synchronized container for a Zircon thread and its cached KOID.
58#[derive(Debug, Clone)]
59pub struct ZirconThread {
60    /// The underlying Zircon thread.
61    ///
62    /// # Thread Safety
63    ///
64    /// Blocking operations are unsafe while holding RCU read locks. However, references to this
65    /// thread must be held across blocking operations (e.g., futex waits). The [`ZirconThread`]
66    /// container as a whole is guarded by RCU because it is a member of the RCU-guarded
67    /// [`TaskRunningState`]. This field is reference counted so it can be accessed outside of RCU
68    /// locks through a strong reference.
69    ///
70    /// Holding a reference to the thread does not guarantee that the task to which it belongs will
71    /// continue running. The task may exit at any time. The thread will continue to exist in memory
72    /// until all references are dropped. When the task exits and execution stops, reference holders
73    /// will observe the thread transition to [`zx::ThreadState::Dead`] normally.
74    pub thread: Arc<zx::Thread>,
75    pub koid: zx::Koid,
76}
77
78impl ZirconThread {
79    pub fn new(thread: Arc<zx::Thread>) -> Self {
80        let koid = thread.koid().expect("Failed to get thread koid");
81        Self { thread, koid }
82    }
83}
84
85impl Deref for ZirconThread {
86    type Target = Arc<zx::Thread>;
87    fn deref(&self) -> &Self::Target {
88        &self.thread
89    }
90}