SimpleKernel 1.17.0
Loading...
Searching...
No Matches
TaskManager Class Reference

任务管理器 More...

#include <task_manager.hpp>

Collaboration diagram for TaskManager:
Collaboration graph

Classes

struct  InterruptWork
 中断线程处理结构体 More...
 

Public Member Functions

auto InitCurrentCore () -> void
 初始化 per cpu 的调度数据,创建 idle 线程
 
auto AddTask (etl::unique_ptr< TaskControlBlock > task) -> void
 添加任务(接管所有权)
 
auto Schedule () -> void
 调度函数 选择下一个任务并切换上下文
 
auto GetCurrentTask () const -> TaskControlBlock *
 获取当前任务
 
auto TickUpdate () -> void
 更新系统 tick
 
auto Sleep (uint64_t ms) -> void
 线程睡眠
 
auto Exit (int exit_code=0) -> void
 退出当前线程
 
auto Block (ResourceId resource_id) -> void
 阻塞当前任务
 
auto Wakeup (ResourceId resource_id) -> void
 唤醒等待指定资源的所有任务
 
auto Clone (uint64_t flags, void *user_stack, int *parent_tid, int *child_tid, void *tls, cpu_io::TrapContext &parent_context) -> Expected< Pid >
 克隆当前任务 (fork/clone 系统调用)
 
auto Wait (Pid pid, int *status, bool no_hang=false, bool untraced=false) -> Expected< Pid >
 等待子进程退出
 
auto FindTask (Pid pid) -> TaskControlBlock *
 按 PID 查找任务
 
构造/析构函数
 TaskManager ()=default
 
 TaskManager (const TaskManager &)=delete
 
 TaskManager (TaskManager &&)=delete
 
auto operator= (const TaskManager &) -> TaskManager &=delete
 
auto operator= (TaskManager &&) -> TaskManager &=delete
 
 ~TaskManager ()
 

Private Types

using InterruptWorkQueue = mpmc_queue::MPMCQueue< InterruptWork, kInterruptQueueCapacity >
 中断工作队列
 

Private Member Functions

auto AllocatePid () -> size_t
 分配新的 PID
 
auto Balance () -> void
 负载均衡 (空闲 core 窃取任务)
 
auto GetCurrentCpuSched () -> CpuSchedData &
 获取当前核心的调度数据
 
auto GetThreadGroup (Pid tgid) -> etl::vector< TaskControlBlock *, kernel::config::kMaxReadyTasks >
 获取线程组的所有线程
 
auto SignalThreadGroup (Pid tgid, int signal) -> void
 向线程组中的所有线程发送信号
 
auto ReapTask (TaskControlBlock *task) -> void
 回收僵尸进程资源
 
auto ReparentChildren (TaskControlBlock *parent) -> void
 将孤儿进程过继给 init 进程
 

Private Attributes

std::array< CpuSchedData, SIMPLEKERNEL_MAX_CORE_COUNT > cpu_schedulers_ {}
 每个核心的调度数据
 
SpinLock task_table_lock_ {"task_table_lock"}
 全局任务表 (PID -> TCB 映射)
 
etl::unordered_map< Pid, etl::unique_ptr< TaskControlBlock >, kernel::config::kMaxTasks, kernel::config::kMaxTasksBucketstask_table_
 
SpinLock interrupt_threads_lock_ {"interrupt_threads_lock"}
 中断线程相关数据保护锁
 
etl::unordered_map< uint64_t, TaskControlBlock *, kernel::config::kMaxInterruptThreads, kernel::config::kMaxInterruptThreadsBucketsinterrupt_threads_
 中断号 -> 中断线程映射
 
etl::unordered_map< uint64_t, InterruptWorkQueue *, kernel::config::kMaxInterruptThreads, kernel::config::kMaxInterruptThreadsBucketsinterrupt_work_queues_
 中断号 -> 工作队列映射
 
std::atomic< size_t > pid_allocator_ {1}
 PID 分配器
 

Static Private Attributes

static constexpr size_t kInterruptQueueCapacity = 256
 中断工作队列容量
 

Detailed Description

任务管理器

负责管理系统中的所有任务,包括任务的创建、调度、切换等。

Definition at line 84 of file task_manager.hpp.

Member Typedef Documentation

◆ InterruptWorkQueue

中断工作队列

Definition at line 220 of file task_manager.hpp.

Constructor & Destructor Documentation

◆ TaskManager() [1/3]

TaskManager::TaskManager ( )
default

◆ TaskManager() [2/3]

TaskManager::TaskManager ( const TaskManager )
delete

◆ TaskManager() [3/3]

TaskManager::TaskManager ( TaskManager &&  )
delete

◆ ~TaskManager()

TaskManager::~TaskManager ( )

Definition at line 262 of file task_manager.cpp.

262 {
263 // unique_ptr in cpu_schedulers_.schedulers[] auto-deletes on destruction
264}

Member Function Documentation

◆ AddTask()

auto TaskManager::AddTask ( etl::unique_ptr< TaskControlBlock task) -> void

添加任务(接管所有权)

根据任务的调度策略,将其添加到对应的调度器中。

Parameters
task任务控制块,所有权转移给 TaskManager
Precondition
task 非空,状态为 kUnInit

Definition at line 94 of file task_manager.cpp.

94 {
95 assert(task.get() != nullptr && "AddTask: task must not be null");
96 assert(task->GetStatus() == TaskStatus::kUnInit &&
97 "AddTask: task status must be kUnInit");
98 // 分配 PID
99 if (task->pid == 0) {
100 task->pid = AllocatePid();
101 }
102
103 // 如果 tgid 未设置,则将其设为自己的 pid (单线程进程或线程组的主线程)
104 if (task->aux->tgid == 0) {
105 task->aux->tgid = task->pid;
106 }
107
108 auto* task_ptr = task.get();
109 Pid pid = task_ptr->pid;
110
111 // 加入全局任务表
112 {
113 LockGuard lock_guard{task_table_lock_};
114 if (task_table_.full()) {
115 klog::Err("AddTask: task_table_ full, cannot add task (pid={})", pid);
116 return;
117 }
118 task_table_[pid] = std::move(task);
119 }
120
121 // 设置任务状态为 kReady
122 // Transition: kUnInit -> kReady
123 task_ptr->fsm.Receive(MsgSchedule{});
124
125 // 简单的负载均衡:如果指定了亲和性,放入对应核心,否则放入当前核心
126 // 更复杂的逻辑可以是:寻找最空闲的核心
127 size_t target_core = cpu_io::GetCurrentCoreId();
128
129 if (task_ptr->aux->cpu_affinity.value() != UINT64_MAX) {
130 // 寻找第一个允许的核心
131 for (size_t core_id = 0; core_id < SIMPLEKERNEL_MAX_CORE_COUNT; ++core_id) {
132 if (task_ptr->aux->cpu_affinity.value() & (1UL << core_id)) {
133 target_core = core_id;
134 break;
135 }
136 }
137 }
138
139 auto& cpu_sched = cpu_schedulers_[target_core];
140
141 {
142 LockGuard<SpinLock> lock_guard(cpu_sched.lock);
143 if (task_ptr->policy < SchedPolicy::kPolicyCount) {
144 if (cpu_sched.schedulers[static_cast<uint8_t>(task_ptr->policy)]) {
145 cpu_sched.schedulers[static_cast<uint8_t>(task_ptr->policy)]->Enqueue(
146 task_ptr);
147 }
148 }
149 }
150
151 // 如果是当前核心,且添加了比当前任务优先级更高的任务,触发抢占
152 if (target_core == cpu_io::GetCurrentCoreId()) {
153 auto& cpu_data = per_cpu::GetCurrentCore();
154 TaskControlBlock* current = cpu_data.running_task;
155 // 如果当前是 idle 任务,或新任务的策略优先级更高,触发调度
156 if (current == cpu_data.idle_task ||
157 (current && task_ptr->policy < current->policy)) {
158 // 注意:这里不能直接调用 Schedule(),因为可能在中断上下文中
159 // 实际应该设置一个 need_resched 标志,在中断返回前检查
160 // 为简化,这里暂时不做抢占,只在时间片耗尽时调度
161 }
162 }
163}
RAII 风格的锁守卫模板类
Definition spinlock.hpp:131
auto AllocatePid() -> size_t
分配新的 PID
etl::unordered_map< Pid, etl::unique_ptr< TaskControlBlock >, kernel::config::kMaxTasks, kernel::config::kMaxTasksBuckets > task_table_
std::array< CpuSchedData, SIMPLEKERNEL_MAX_CORE_COUNT > cpu_schedulers_
每个核心的调度数据
SpinLock task_table_lock_
全局任务表 (PID -> TCB 映射)
constexpr etl::fsm_state_id_t kUnInit
Definition task_fsm.hpp:14
auto GetCurrentCoreId() -> size_t
Definition cpu_io.h:26
auto Err(etl::format_string< Args... > fmt, Args &&... args) -> void
以 ERROR 级别记录日志
static __always_inline auto GetCurrentCore() -> PerCpu &
获取当前核心的 PerCpu 数据
Definition per_cpu.hpp:55
size_t core_id
核心 ID
Definition per_cpu.hpp:1
调度消息(无负载,用作事件)
任务控制块,管理进程/线程的核心数据结构
SchedPolicy policy
调度策略
@ kPolicyCount
策略数量
size_t Pid
进程 ID 类型
Here is the call graph for this function:

◆ AllocatePid()

auto TaskManager::AllocatePid ( ) -> size_t
private

分配新的 PID

Returns
size_t 新的 PID
Note
当前 PID 分配器为简单的原子自增,存在以下限制:
  1. 不支持 PID 回收与重用(已退出的任务的 PID 不会被回收)
  2. 不检测溢出(size_t 耗尽后回绕为 0,可能与现有 PID 冲突)
  3. 不保证全局唯一性(依赖 size_t 足够大 + 系统生命周期内不会耗尽) 对于教学内核而言,size_t 的范围(2^64)在实际使用中不会溢出。 生产级实现应使用位图或 ID 分配器(如 Linux 的 IDR/IDA)。

Definition at line 165 of file task_manager.cpp.

165 {
172 return pid_allocator_.fetch_add(1);
173}
std::atomic< size_t > pid_allocator_
PID 分配器

◆ Balance()

auto TaskManager::Balance ( ) -> void
private

负载均衡 (空闲 core 窃取任务)

Definition at line 181 of file task_manager.cpp.

181 {
182 // 算法留空
183 // TODO: 检查其他核心的运行队列长度,如果比当前核心长,则窃取任务
184}

◆ Block()

auto TaskManager::Block ( ResourceId  resource_id) -> void

阻塞当前任务

Parameters
resource_id等待的资源 ID

Definition at line 12 of file block.cpp.

12 {
13 auto& cpu_sched = GetCurrentCpuSched();
14
15 auto* current = GetCurrentTask();
16 assert(current != nullptr && "Block: No current task to block");
17 assert(current->GetStatus() == TaskStatus::kRunning &&
18 "Block: current task status must be kRunning");
19
20 {
21 LockGuard<SpinLock> lock_guard(cpu_sched.lock);
22
23 // Check capacity before transitioning FSM
24 auto& list = cpu_sched.blocked_tasks[resource_id];
25 if (list.full()) {
27 "Block: blocked_tasks list full for resource, cannot block task {}",
28 current->pid);
29 // Rollback: task stays kRunning, do not transition FSM
30 return;
31 }
32
33 // Transition: kRunning -> kBlocked
34 current->fsm.Receive(MsgBlock{resource_id});
35 // Record blocked resource
36 current->aux->blocked_on = resource_id;
37 list.push_back(current);
38
39 klog::Debug("Block: pid={} blocked on resource={}, data={:#x}",
40 current->pid, resource_id.GetTypeName(),
41 static_cast<uint64_t>(resource_id.GetData()));
42 }
43
44 // 调度到其他任务
45 Schedule();
46
47 // 任务被唤醒后会从这里继续执行
48}
constexpr auto GetTypeName() const -> const char *
获取类型名称(用于调试)
constexpr auto GetData() const -> uint64_t
获取资源数据
auto Schedule() -> void
调度函数 选择下一个任务并切换上下文
Definition schedule.cpp:26
auto GetCurrentTask() const -> TaskControlBlock *
获取当前任务
auto GetCurrentCpuSched() -> CpuSchedData &
获取当前核心的调度数据
constexpr etl::fsm_state_id_t kRunning
Definition task_fsm.hpp:16
auto Debug(etl::format_string< Args... > fmt, Args &&... args) -> void
以 DEBUG 级别记录日志(SIMPLEKERNEL_MIN_LOG_LEVEL > 0 时编译期消除)
阻塞消息,携带资源 ID
Here is the call graph for this function:

◆ Clone()

auto TaskManager::Clone ( uint64_t  flags,
void *  user_stack,
int *  parent_tid,
int *  child_tid,
void *  tls,
cpu_io::TrapContext parent_context 
) -> Expected<Pid>

克隆当前任务 (fork/clone 系统调用)

Parameters
flags克隆标志位
  • kCloneVm: 共享地址空间
  • kCloneThread: 共享线程组
  • kCloneFiles: 共享文件描述符表
  • kCloneSighand: 共享信号处理器
  • 0: 完全复制 (fork)
user_stack用户栈指针 (nullptr 表示复制父进程栈)
parent_tid父进程 TID 存储地址
child_tid子进程 TID 存储地址
tls线程局部存储指针
parent_context父进程的 trap 上下文 (用于复制寄存器)
Returns
Expected<Pid> 父进程返回子进程 PID,子进程返回 0,失败返回错误
Todo:
当前未实现文件系统,此标志暂时仅记录
Todo:
当前未实现信号机制,此标志暂时仅记录
Todo:
当前未实现文件系统,此标志暂时仅记录

Definition at line 13 of file clone.cpp.

15 {
16 auto* parent = GetCurrentTask();
17 if (!parent) {
18 klog::Err("Clone: No current task");
19 return std::unexpected(Error(ErrorCode::kTaskNoCurrentTask));
20 }
21
22 // 验证克隆标志的合法性
23 // 如果设置了 kCloneThread,必须同时设置 kCloneVm, kCloneFiles, kCloneSighand
24 if ((flags & clone_flag::kThread) &&
25 (!(flags & clone_flag::kVm) || !(flags & clone_flag::kFiles) ||
26 !(flags & clone_flag::kSighand))) {
28 "Clone: kCloneThread requires kCloneVm, kCloneFiles, kCloneSighand");
29 // 自动补全必需的标志
31 }
32
33 // 分配新的 PID
34 Pid new_pid = AllocatePid();
35 if (new_pid == 0) {
36 klog::Err("Clone: Failed to allocate PID");
37 return std::unexpected(Error(ErrorCode::kTaskPidAllocationFailed));
38 }
39
40 // 创建子任务控制块
41 auto child_ptr = kstd::make_unique<TaskControlBlock>();
42 if (!child_ptr) {
43 klog::Err("Clone: Failed to allocate child task");
44 return std::unexpected(Error(ErrorCode::kTaskAllocationFailed));
45 }
46 auto* child = child_ptr.get();
47 // Default ctor leaves FSM in set_states-but-not-started state.
48 // Start it so get_state_id() returns kUnInit instead of deref null.
49 child->fsm.Start();
50
51 // 基本字段设置
52 child->pid = new_pid;
53 child->name = parent->name;
54 child->policy = parent->policy;
55 child->sched_info = parent->sched_info;
56
57 // 设置父进程 ID
58 if (flags & clone_flag::kParent) {
59 // 保持与父进程相同的父进程
60 child->aux->parent_pid = parent->aux->parent_pid;
61 } else {
62 child->aux->parent_pid = parent->pid;
63 }
64
65 // 处理线程组 ID (TGID)
66 if (flags & clone_flag::kThread) {
67 // 创建线程: 共享线程组
68 child->aux->tgid = parent->aux->tgid;
69 child->aux->pgid = parent->aux->pgid;
70 child->aux->sid = parent->aux->sid;
71
72 // 将子线程加入父线程的线程组
73 if (parent->IsThreadGroupLeader()) {
74 child->JoinThreadGroup(parent);
75 } else {
76 // 找到线程组的主线程
77 TaskControlBlock* leader = FindTask(parent->aux->tgid);
78 if (leader) {
79 child->JoinThreadGroup(leader);
80 } else {
81 klog::Warn("Clone: Thread group leader not found for tgid={}",
82 parent->aux->tgid);
83 }
84 }
85 } else {
86 // 创建进程: 新的线程组
87 // 新进程的 tgid 是自己的 pid
88 child->aux->tgid = new_pid;
89 child->aux->pgid = parent->aux->pgid;
90 child->aux->sid = parent->aux->sid;
91 }
92
93 // 克隆标志位
94 child->aux->clone_flags = CloneFlags(flags);
95
96 // 处理文件描述符表 (kCloneFiles)
98 if (flags & clone_flag::kFiles) {
99 klog::Debug("Clone: sharing file descriptor table (not implemented)");
100 } else {
101 klog::Debug("Clone: copying file descriptor table (not implemented)");
102 }
103
104 // 处理信号处理器 (kCloneSighand)
106 if (flags & clone_flag::kSighand) {
107 klog::Debug("Clone: sharing signal handlers (not implemented)");
108 } else {
109 klog::Debug("Clone: copying signal handlers (not implemented)");
110 }
111
112 // 处理文件系统信息 (kCloneFs)
114 if (flags & clone_flag::kFs) {
115 klog::Debug("Clone: sharing filesystem info (not implemented)");
116 } else {
117 klog::Debug("Clone: copying filesystem info (not implemented)");
118 }
119
120 // 处理地址空间
121 if (flags & clone_flag::kVm) {
122 // 共享地址空间(线程)
123 child->page_table = parent->page_table;
124 klog::Debug("Clone: sharing page table {:#x}",
125 reinterpret_cast<uintptr_t>(child->page_table));
126 } else {
127 // 复制地址空间(进程)
128 if (parent->page_table) {
129 // copy_mappings=true 表示复制用户空间映射
130 auto result = VirtualMemorySingleton::instance().ClonePageDirectory(
131 parent->page_table, true);
132 if (!result.has_value()) {
133 klog::Err("Clone: Failed to clone page table: {}",
134 result.error().message());
135 // 独立页表已由 unique_ptr 在作用域结束时自动释放
136 // 仅需清理页表
137 if (child->page_table && !(flags & clone_flag::kVm)) {
138 VirtualMemorySingleton::instance().DestroyPageDirectory(
139 child->page_table, false);
140 child->page_table = nullptr;
141 }
142 return std::unexpected(Error(ErrorCode::kTaskAllocationFailed));
143 }
144 child->page_table = reinterpret_cast<uint64_t*>(result.value());
145 klog::Debug("Clone: cloned page table from {:#x} to {:#x}",
146 reinterpret_cast<uintptr_t>(parent->page_table),
147 reinterpret_cast<uintptr_t>(child->page_table));
148 } else {
149 // 父进程没有页表(内核线程),子进程也不需要
150 child->page_table = nullptr;
151 }
152 }
153
154 // 分配内核栈
155 child->kernel_stack = static_cast<uint8_t*>(
158 if (!child->kernel_stack) {
159 klog::Err("Clone: Failed to allocate kernel stack");
160 // 清理已分配的资源
161 if (child->page_table && !(flags & clone_flag::kVm)) {
162 VirtualMemorySingleton::instance().DestroyPageDirectory(child->page_table,
163 false);
164 child->page_table = nullptr;
165 }
166 return std::unexpected(Error(ErrorCode::kTaskKernelStackAllocationFailed));
167 }
168
169 // 初始化内核栈内容
170 kstd::memset(child->kernel_stack, 0,
172
173 // 复制 trap context
174 child->trap_context_ptr = reinterpret_cast<cpu_io::TrapContext*>(
175 child->kernel_stack + TaskControlBlock::kDefaultKernelStackSize -
176 sizeof(cpu_io::TrapContext));
177 kstd::memcpy(child->trap_context_ptr, &parent_context,
178 sizeof(cpu_io::TrapContext));
179
180 // 设置用户栈
181 if (user_stack) {
182 child->trap_context_ptr->UserStackPointer() =
183 reinterpret_cast<uint64_t>(user_stack);
184 }
185
186 // 设置 TLS (Thread Local Storage)
187 if (tls) {
188 child->trap_context_ptr->ThreadPointer() = reinterpret_cast<uint64_t>(tls);
189 }
190
191 // 父进程返回子进程 PID
192 parent_context.ReturnValue() = new_pid;
193 // 子进程返回 0
194 child->trap_context_ptr->ReturnValue() = 0;
195
196 // 写入 TID
197 if (parent_tid) {
198 *parent_tid = new_pid;
199 }
200 if (child_tid) {
201 *child_tid = new_pid;
202 }
203
204 // 将子任务添加到调度器
205 AddTask(std::move(child_ptr));
206
207 // 打印详细的 clone 信息
208 const char* clone_type = (flags & clone_flag::kThread) ? "thread" : "process";
209 const char* vm_type = (flags & clone_flag::kVm) ? "shared" : "copied";
211 "Clone: created {} - parent={}, child={}, tgid={}, vm={}, flags={:#x}",
212 clone_type, parent->pid, new_pid, child->aux->tgid, vm_type,
213 static_cast<uint64_t>(flags));
214 return new_pid;
215}
auto AddTask(etl::unique_ptr< TaskControlBlock > task) -> void
添加任务(接管所有权)
auto FindTask(Pid pid) -> TaskControlBlock *
按 PID 查找任务
@ kTaskNoCurrentTask
@ kTaskAllocationFailed
@ kTaskPidAllocationFailed
@ kTaskKernelStackAllocationFailed
constexpr uint64_t kFiles
共享文件描述符表
constexpr uint64_t kSighand
共享信号处理器
constexpr uint64_t kParent
保持相同父进程
constexpr uint64_t kThread
同一线程组
constexpr uint64_t kFs
共享文件系统信息
constexpr uint64_t kVm
共享地址空间
static constexpr size_t kPageSize
Definition cpu_io.h:63
auto Warn(etl::format_string< Args... > fmt, Args &&... args) -> void
以 WARN 级别记录日志
void * aligned_alloc(size_t alignment, size_t size)
Definition memory.cpp:58
错误类型,用于 std::expected
Definition expected.hpp:343
static constexpr size_t kDefaultKernelStackSize
默认内核栈大小 (16 KB)
__always_inline uint64_t & ReturnValue()
Definition cpu_io.h:196
etl::flags< uint64_t, clone_flag::kAllMask > CloneFlags
克隆标志位
Here is the call graph for this function:

◆ Exit()

auto TaskManager::Exit ( int  exit_code = 0) -> void

退出当前线程

Parameters
exit_code退出码
Todo:
通知父进程 (发送 SIGCHLD)

Definition at line 12 of file exit.cpp.

12 {
13 auto& cpu_sched = GetCurrentCpuSched();
14 auto* current = GetCurrentTask();
15 assert(current != nullptr && "Exit: No current task to exit");
16 assert(current->GetStatus() == TaskStatus::kRunning &&
17 "Exit: current task status must be kRunning");
18
19 {
20 LockGuard<SpinLock> lock_guard(cpu_sched.lock);
21
22 // 设置退出码
23 current->aux->exit_code = exit_code;
24
25 // 检查是否是线程组的主线程
26 bool is_group_leader = current->IsThreadGroupLeader();
27
28 // 如果是线程组的主线程,需要检查是否还有其他线程
29 if (is_group_leader && current->GetThreadGroupSize() > 1) {
31 "Exit: Thread group leader (pid={}, tgid={}) exiting, but group "
32 "still has {} threads",
33 current->pid, current->aux->tgid, current->GetThreadGroupSize());
34 }
35
36 // 从线程组中移除
37 current->LeaveThreadGroup();
38
39 // 将子进程过继给 init 进程 (仅当是进程时)
40 if (is_group_leader) {
41 ReparentChildren(current);
42 }
43
44 if (current->aux->parent_pid != 0) {
45 // 有父进程,进入僵尸状态等待回收
46 // Transition: kRunning -> kZombie
47 current->fsm.Receive(MsgExit{exit_code, true});
48
49 // 唤醒等待此进程退出的父进程
50 // 父进程会阻塞在 ChildExit 类型的资源上,数据是父进程自己的 PID
51 auto wait_resource_id =
52 ResourceId(ResourceType::kChildExit, current->aux->parent_pid);
53 Wakeup(wait_resource_id);
54
56
57 klog::Debug("Exit: pid={} waking up parent={} on resource={}",
58 current->pid, current->aux->parent_pid,
59 wait_resource_id.GetTypeName());
60 } else {
61 // 没有父进程,直接退出并释放资源
62 // Transition: kRunning -> kExited
63 current->fsm.Receive(MsgExit{exit_code, false});
64 // No parent to call wait(), reap immediately to free TCB + stack
65 ReapTask(current);
66 }
67 }
68
69 Schedule();
70
71 klog::Err("Exit: Task {} should not return from Schedule()", current->pid);
72
73 // UNREACHABLE: 任务退出后 Schedule() 不应返回
74 __builtin_unreachable();
75}
资源 ID
auto ReapTask(TaskControlBlock *task) -> void
回收僵尸进程资源
auto ReparentChildren(TaskControlBlock *parent) -> void
将孤儿进程过继给 init 进程
auto Wakeup(ResourceId resource_id) -> void
唤醒等待指定资源的所有任务
Definition wakeup.cpp:12
@ kChildExit
等待子进程退出
退出消息,携带退出码与父任务标志
Here is the call graph for this function:

◆ FindTask()

auto TaskManager::FindTask ( Pid  pid) -> TaskControlBlock*

按 PID 查找任务

Parameters
pid进程 ID
Returns
TaskControlBlock* 找到的任务,未找到返回 nullptr

Definition at line 175 of file task_manager.cpp.

175 {
176 LockGuard lock_guard{task_table_lock_};
177 auto it = task_table_.find(pid);
178 return (it != task_table_.end()) ? it->second.get() : nullptr;
179}

◆ GetCurrentCpuSched()

auto TaskManager::GetCurrentCpuSched ( ) -> CpuSchedData&
inlineprivate

获取当前核心的调度数据

Returns
CpuSchedData& 当前核心的调度数据引用

Definition at line 264 of file task_manager.hpp.

264 {
266 }
Here is the call graph for this function:

◆ GetCurrentTask()

auto TaskManager::GetCurrentTask ( ) const -> TaskControlBlock*
inline

获取当前任务

Returns
TaskControlBlock* 当前正在运行的任务

Definition at line 116 of file task_manager.hpp.

116 {
117 return per_cpu::GetCurrentCore().running_task;
118 }
Here is the call graph for this function:

◆ GetThreadGroup()

auto TaskManager::GetThreadGroup ( Pid  tgid) -> etl::vector<TaskControlBlock*, kernel::config::kMaxReadyTasks>
private

获取线程组的所有线程

Parameters
tgid线程组 ID
Returns
etl::vector<TaskControlBlock*, kernel::config::kMaxReadyTasks> 线程组中的所有线程

Definition at line 234 of file task_manager.cpp.

235 {
236 etl::vector<TaskControlBlock*, kernel::config::kMaxReadyTasks> result;
237
238 LockGuard lock_guard(task_table_lock_);
239
240 // 遍历任务表,找到所有 tgid 匹配的线程
241 for (auto& [pid, task] : task_table_) {
242 if (task && task->aux->tgid == tgid) {
243 result.push_back(task.get());
244 }
245 }
246
247 return result;
248}

◆ InitCurrentCore()

auto TaskManager::InitCurrentCore ( ) -> void

初始化 per cpu 的调度数据,创建 idle 线程

Definition at line 39 of file task_manager.cpp.

39 {
41 auto& cpu_sched = cpu_schedulers_[core_id];
42
43 LockGuard lock_guard{cpu_sched.lock};
44
45 if (!cpu_sched.schedulers[static_cast<uint8_t>(SchedPolicy::kNormal)]) {
46 cpu_sched.schedulers[static_cast<uint8_t>(SchedPolicy::kRealTime)] =
47 kstd::make_unique<FifoScheduler>();
48 cpu_sched.schedulers[static_cast<uint8_t>(SchedPolicy::kNormal)] =
49 kstd::make_unique<RoundRobinScheduler>();
50 cpu_sched.schedulers[static_cast<uint8_t>(SchedPolicy::kIdle)] =
51 kstd::make_unique<IdleScheduler>();
52 }
53
54 // 关联 PerCpu
55 auto& cpu_data = per_cpu::GetCurrentCore();
56 cpu_data.sched_data = &cpu_sched;
57
58 // 创建 boot 任务作为当前执行上下文的占位符
59 // 首次 Schedule():
60 // current(boot_task) != next(idle_task) -> switch_to -> idle_thread
61 auto boot_task_ptr = kstd::make_unique<TaskControlBlock>(
62 "Boot",
63 std::numeric_limits<
65 nullptr, nullptr);
66 auto* boot_task = boot_task_ptr.release();
67 // kUnInit -> kReady
68 boot_task->fsm.Receive(MsgSchedule{});
69 // kReady -> kRunning
70 boot_task->fsm.Receive(MsgSchedule{});
71 boot_task->policy = SchedPolicy::kIdle;
72 cpu_data.running_task = boot_task;
73
74 // 创建独立的 Idle 线程
75 auto idle_task_ptr = kstd::make_unique<TaskControlBlock>(
76 "Idle",
77 std::numeric_limits<
79 IdleThread, nullptr);
80 auto* idle_task = idle_task_ptr.release();
81 // kUnInit -> kReady
84
85 // 将 idle 任务加入 Idle 调度器
86 if (cpu_sched.schedulers[static_cast<uint8_t>(SchedPolicy::kIdle)]) {
87 cpu_sched.schedulers[static_cast<uint8_t>(SchedPolicy::kIdle)]->Enqueue(
88 idle_task);
89 }
90
91 cpu_data.idle_task = idle_task;
92}
auto Receive(const etl::imessage &msg) -> void
向 FSM 发送消息
Definition task_fsm.hpp:163
TaskControlBlock * idle_task
空闲任务
Definition per_cpu.hpp:6
int priority
优先级 (数字越小优先级越高)
TaskFsm fsm
任务状态机
@ kNormal
普通任务
@ kRealTime
实时任务 (最高优先级)
@ kIdle
空闲任务 (最低优先级)
Here is the call graph for this function:

◆ operator=() [1/2]

auto TaskManager::operator= ( const TaskManager ) -> TaskManager &=delete
delete

◆ operator=() [2/2]

auto TaskManager::operator= ( TaskManager &&  ) -> TaskManager &=delete
delete

◆ ReapTask()

auto TaskManager::ReapTask ( TaskControlBlock task) -> void
private

回收僵尸进程资源

Parameters
task要回收的任务 (必须处于 kZombie 状态)
Note
释放内核栈、页表、TCB,回收 PID

Definition at line 186 of file task_manager.cpp.

186 {
187 if (!task) {
188 return;
189 }
190
191 // 确保任务处于僵尸或退出状态
192 if (task->GetStatus() != TaskStatus::kZombie &&
193 task->GetStatus() != TaskStatus::kExited) {
194 klog::Warn("ReapTask: Task {} is not in zombie/exited state", task->pid);
195 return;
196 }
197
198 // Capture pid before erase (unique_ptr deletes on erase)
199 Pid pid = task->pid;
200
201 // 从全局任务表中移除 (unique_ptr auto-deletes TCB)
202 {
203 LockGuard lock_guard{task_table_lock_};
204 task_table_.erase(pid);
205 }
206
207 klog::Debug("ReapTask: Task {} resources freed", pid);
208}
constexpr etl::fsm_state_id_t kExited
Definition task_fsm.hpp:19
constexpr etl::fsm_state_id_t kZombie
Definition task_fsm.hpp:20
auto GetStatus() const -> etl::fsm_state_id_t
获取当前任务状态
Pid pid
线程 ID (Task ID)
Here is the call graph for this function:

◆ ReparentChildren()

auto TaskManager::ReparentChildren ( TaskControlBlock parent) -> void
private

将孤儿进程过继给 init 进程

Parameters
parent退出的父进程
Note
在父进程退出时调用,防止子进程变成僵尸无人回收
Todo:
当前的 pid 是自增的,需要考虑多核情况
Todo:
实现向 init 进程发送 SIGCHLD 信号

Definition at line 210 of file task_manager.cpp.

210 {
211 if (!parent) {
212 return;
213 }
214
215 // init 进程的 PID 通常是 1
217 static constexpr Pid kInitPid = 1;
218
219 LockGuard lock_guard{task_table_lock_};
220
221 // 遍历所有任务,找到父进程是当前任务的子进程
222 for (auto& [pid, task] : task_table_) {
223 if (task && task->aux->parent_pid == parent->pid) {
224 // 将子进程过继给 init 进程
225 task->aux->parent_pid = kInitPid;
226 klog::Debug("ReparentChildren: Task {} reparented to init (PID {})",
227 task->pid, kInitPid);
228 // 如果子进程已经是僵尸状态,通知 init 进程回收
230 }
231 }
232}
Here is the call graph for this function:

◆ Schedule()

auto TaskManager::Schedule ( ) -> void

调度函数 选择下一个任务并切换上下文

Note
被调用意味着需要调度决策,可能是 时间片耗尽(TickUpdate 检测到需要抢占) 主动让出 CPU (yield) 任务阻塞、睡眠或退出

Definition at line 26 of file schedule.cpp.

26 {
27 auto& cpu_sched = GetCurrentCpuSched();
28 cpu_sched.scheduler_started = true;
29 cpu_sched.lock.Lock().or_else([](auto&& err) {
30 klog::Err("Schedule: Failed to acquire lock: {}", err.message());
31 while (true) {
33 }
34 return Expected<void>{};
35 });
36
37 auto* current = GetCurrentTask();
38 assert(current != nullptr && "Schedule: No current task to schedule");
39
40 // 处理当前任务状态
41 if (current->GetStatus() == TaskStatus::kRunning) {
42 // 将当前任务标记为就绪并重新入队(如果它还能运行)
43 current->fsm.Receive(MsgYield{});
44 auto* scheduler =
45 cpu_sched.schedulers[static_cast<uint8_t>(current->policy)].get();
46
47 if (scheduler) {
48 scheduler->OnPreempted(current);
49 // 调度器决定如何处理被抢占的任务
50 // 大多数情况下需要重新入队,除非是特殊策略
51 if (scheduler->OnTimeSliceExpired(current)) {
52 scheduler->Enqueue(current);
53 }
54 }
55 }
56
57 // 选择下一个任务 (按策略优先级: RealTime > Normal > Idle)
58 TaskControlBlock* next = nullptr;
59 for (auto& scheduler : cpu_sched.schedulers) {
60 if (scheduler && !scheduler->IsEmpty()) {
61 next = scheduler->PickNext();
62 if (next) {
63 break;
64 }
65 }
66 }
67
68 // 如果没有任务可运行
69 if (!next) {
70 // 如果当前任务仍然可以运行,继续运行它
71 if (current->GetStatus() == TaskStatus::kReady) {
72 next = current;
73 } else {
74 // 否则统计空闲时间并返回
75 cpu_sched.idle_time++;
76 cpu_sched.lock.UnLock().or_else([](auto&& err) {
77 klog::Err("Schedule: Failed to release lock: {}", err.message());
78 while (true) {
80 }
81 return Expected<void>{};
82 });
83 return;
84 }
85 }
86
87 // 切换到下一个任务
88 assert(next != nullptr && "Schedule: next task must not be null");
89 assert((next->GetStatus() == TaskStatus::kReady ||
90 next->policy == SchedPolicy::kIdle) &&
91 "Schedule: next task must be kReady or kIdle policy");
92
93 next->fsm.Receive(MsgSchedule{});
94 // 重置时间片(对于 RR 和 FIFO 有效,CFS 使用 vruntime 不依赖此字段)
97 cpu_sched.total_schedules++;
98
99 // 调用调度器钩子
100 auto* scheduler =
101 cpu_sched.schedulers[static_cast<uint8_t>(next->policy)].get();
102 if (scheduler) {
103 scheduler->OnScheduled(next);
104 }
105
106 // 更新 per-CPU running_task
107 per_cpu::GetCurrentCore().running_task = next;
108
109 cpu_sched.lock.UnLock().or_else([](auto&& err) {
110 klog::Err("Schedule: Failed to release lock: {}", err.message());
111 while (true) {
113 }
114 return Expected<void>{};
115 });
116
117 // 上下文切换
118 if (current != next) {
119 switch_to(&current->task_context, &next->task_context);
120 }
121}
auto switch_to(cpu_io::CalleeSavedContext *prev, cpu_io::CalleeSavedContext *next) -> void
Definition arch.cpp:15
std::expected< T, Error > Expected
std::expected 别名模板
Definition expected.hpp:365
constexpr etl::fsm_state_id_t kReady
Definition task_fsm.hpp:15
void Pause()
Definition cpu_io.h:20
让出消息(无负载,用作事件)
uint64_t time_slice_default
默认时间片
uint64_t context_switches
上下文切换次数
uint64_t time_slice_remaining
剩余时间片
struct TaskControlBlock::SchedInfo sched_info
cpu_io::CalleeSavedContext task_context
任务上下文
Here is the call graph for this function:

◆ SignalThreadGroup()

auto TaskManager::SignalThreadGroup ( Pid  tgid,
int  signal 
) -> void
private

向线程组中的所有线程发送信号

Parameters
tgid线程组 ID
signal信号编号
Note
暂未实现信号机制,预留接口
Todo:
实现信号机制后,向线程组中的所有线程发送信号

Definition at line 250 of file task_manager.cpp.

250 {
252 klog::Debug("SignalThreadGroup: tgid={}, signal={} (not implemented)", tgid,
253 signal);
254
255 // 预期实现:
256 // auto threads = GetThreadGroup(tgid);
257 // for (auto* thread : threads) {
258 // SendSignal(thread, signal);
259 // }
260}
Here is the call graph for this function:

◆ Sleep()

auto TaskManager::Sleep ( uint64_t  ms) -> void

线程睡眠

Parameters
ms睡眠毫秒数

Definition at line 14 of file sleep.cpp.

14 {
15 auto& cpu_sched = GetCurrentCpuSched();
16
17 auto* current = GetCurrentTask();
18 assert(current != nullptr && "Sleep: No current task to sleep");
19 assert(current->GetStatus() == TaskStatus::kRunning &&
20 "Sleep: current task status must be kRunning");
21
22 // 如果睡眠时间为 0,仅让出 CPU(相当于 yield)
23 if (ms == 0) {
24 Schedule();
25 return;
26 }
27
28 {
29 LockGuard<SpinLock> lock_guard(cpu_sched.lock);
30
31 // 计算唤醒时间 (当前 tick + 睡眠时间)
32 uint64_t sleep_ticks = (ms * SIMPLEKERNEL_TICK) / kMillisecondsPerSecond;
33 current->sched_info.wake_tick = cpu_sched.local_tick + sleep_ticks;
34
35 // Check capacity before transitioning FSM
36
37 // 将任务加入睡眠队列(优先队列会自动按 wake_tick 排序)
38 if (cpu_sched.sleeping_tasks.full()) {
39 klog::Err("Sleep: sleeping_tasks full, cannot sleep task {}",
40 current->pid);
41 return;
42 }
43 current->fsm.Receive(MsgSleep{current->sched_info.wake_tick});
44 cpu_sched.sleeping_tasks.push(current);
45 }
46
47 // 调度到其他任务
48 Schedule();
49
50 // 任务被唤醒后会从这里继续执行
51}
static constexpr uint64_t kMillisecondsPerSecond
每秒的毫秒数
Definition sleep.cpp:12
睡眠消息,携带唤醒时钟
uint64_t wake_tick
唤醒时钟
Here is the call graph for this function:

◆ TickUpdate()

auto TaskManager::TickUpdate ( ) -> void

更新系统 tick

Definition at line 9 of file tick_update.cpp.

9 {
10 auto& cpu_sched = GetCurrentCpuSched();
11
12 bool need_preempt = false;
13
14 {
15 LockGuard<SpinLock> lock_guard(cpu_sched.lock);
16
17 // 递增本核心的 tick 计数
18 cpu_sched.local_tick++;
19
20 auto* current = GetCurrentTask();
21
22 // 唤醒睡眠队列中到时间的任务
23 while (!cpu_sched.sleeping_tasks.empty()) {
24 auto* task = cpu_sched.sleeping_tasks.top();
25
26 // 检查是否到达唤醒时间
27 if (task->sched_info.wake_tick > cpu_sched.local_tick) {
28 // sleeping_tasks 是一个 priority_queue,只需要检查队首元素
29 break;
30 }
31
32 // 唤醒任务
33 cpu_sched.sleeping_tasks.pop();
34 task->fsm.Receive(MsgWakeup{});
35
36 // 将任务重新加入对应调度器的就绪队列
37 auto* scheduler =
38 cpu_sched.schedulers[static_cast<uint8_t>(task->policy)].get();
39 if (scheduler) {
40 scheduler->Enqueue(task);
41 }
42 }
43
44 // 更新当前任务的统计信息
45 if (current && current->GetStatus() == TaskStatus::kRunning) {
46 // 更新总运行时间
47 current->sched_info.total_runtime++;
48
49 // 减少剩余时间片
50 if (current->sched_info.time_slice_remaining > 0) {
51 current->sched_info.time_slice_remaining--;
52 }
53
54 // 调用调度器的 OnTick,检查是否需要抢占
55 auto* scheduler =
56 cpu_sched.schedulers[static_cast<uint8_t>(current->policy)].get();
57
58 if (scheduler) {
59 // 调度器可能基于自己的策略决定是否抢占
60 need_preempt = scheduler->OnTick(current);
61 }
62
63 // 检查时间片是否耗尽(对于基于时间片的调度器)
64 if (!need_preempt && current->sched_info.time_slice_remaining == 0) {
65 need_preempt = true;
66 }
67 }
68 }
69
70 if (need_preempt && cpu_sched.scheduler_started) {
71 Schedule();
72 }
73}
唤醒消息(无负载,用作事件)

◆ Wait()

auto TaskManager::Wait ( Pid  pid,
int *  status,
bool  no_hang = false,
bool  untraced = false 
) -> Expected<Pid>

等待子进程退出

Parameters
pid子进程 PID (-1 表示任意子进程,0 表示同组,>0 表示指定进程)
status退出状态存储位置 (可为 nullptr)
no_hang非阻塞等待,立即返回 (类似 WNOHANG)
untraced报告已停止的子进程 (类似 WUNTRACED)
Returns
Expected<Pid> 成功返回子进程 PID,无子进程或被中断返回错误

Definition at line 13 of file wait.cpp.

14 {
15 auto* current = GetCurrentTask();
16 assert(current != nullptr && "Wait: No current task");
17 assert(current->GetStatus() == TaskStatus::kRunning &&
18 "Wait: current task status must be kRunning");
19
20 while (true) {
21 TaskControlBlock* target = nullptr;
22
23 {
24 LockGuard lock_guard(task_table_lock_);
25
26 // 遍历任务表寻找符合条件的子进程
27 for (auto& [task_pid, task] : task_table_) {
28 // 检查是否是当前进程的子进程
29 bool is_child = (task->aux->parent_pid == current->pid);
30
31 // 检查 PID 匹配条件
32 bool pid_match = false;
33 if (pid == static_cast<Pid>(-1)) {
34 // 等待任意子进程
35 pid_match = is_child;
36 } else if (pid == 0) {
37 // 等待同进程组的任意子进程
38 pid_match = is_child && (task->aux->pgid == current->aux->pgid);
39 } else if (pid > 0) {
40 // 等待指定 PID 的子进程
41 pid_match = is_child && (task->pid == pid);
42 } else {
43 // pid < -1: 等待进程组 ID 为 |pid| 的任意子进程
44 pid_match = is_child && (task->aux->pgid == static_cast<Pid>(-pid));
45 }
46
47 if (!pid_match) {
48 continue;
49 }
50
51 // 检查任务状态
52 if (task->GetStatus() == TaskStatus::kZombie ||
53 task->GetStatus() == TaskStatus::kExited) {
54 target = task.get();
55 break;
56 }
57
58 // untraced: 报告已停止的子进程
59 if (untraced && task->GetStatus() == TaskStatus::kBlocked) {
60 if (status) {
61 // 表示停止状态
62 *status = 0;
63 }
64 return task->pid;
65 }
66 }
67 }
68
69 // 找到了退出的子进程
70 if (target) {
71 assert((target->GetStatus() == TaskStatus::kZombie ||
72 target->GetStatus() == TaskStatus::kExited) &&
73 "Wait: target task must be kZombie or kExited");
74 assert(target->aux->parent_pid == current->pid &&
75 "Wait: target parent_pid must match current pid");
76
77 Pid result_pid = target->pid;
78
79 // 返回退出状态
80 if (status) {
81 *status = target->aux->exit_code;
82 }
83
84 // 清理僵尸进程
85 {
86 LockGuard lock_guard(task_table_lock_);
87 auto it = task_table_.find(target->pid);
88 assert(it != task_table_.end() &&
89 "Wait: target must exist in task_table");
90 task_table_.erase(it->first);
91 }
92
93 klog::Debug("Wait: pid={} reaped child={}", current->pid, result_pid);
94 return result_pid;
95 }
96
97 // 如果设置了 no_hang,立即返回
98 if (no_hang) {
99 return 0;
100 }
101
102 // 没有找到符合条件的子进程,阻塞等待
103 // 使用 ChildExit 类型的资源 ID,数据部分是当前进程的 PID
104 auto wait_resource_id = ResourceId(ResourceType::kChildExit, current->pid);
105
106 Block(wait_resource_id);
107
108 klog::Debug("Wait: pid={} blocked on resource={}, data={}", current->pid,
109 wait_resource_id.GetTypeName(),
110 static_cast<uint64_t>(wait_resource_id.GetData()));
111 // 被唤醒后重新检查
112 }
113}
auto Block(ResourceId resource_id) -> void
阻塞当前任务
Definition block.cpp:12
constexpr etl::fsm_state_id_t kBlocked
Definition task_fsm.hpp:18
Pid parent_pid
父线程 ID
int exit_code
退出码
TaskAuxData * aux
非调度热路径的辅助数据
Here is the call graph for this function:

◆ Wakeup()

auto TaskManager::Wakeup ( ResourceId  resource_id) -> void

唤醒等待指定资源的所有任务

Parameters
resource_id资源 ID
Note
会唤醒所有阻塞在此资源上的任务

Definition at line 12 of file wakeup.cpp.

12 {
13 auto& cpu_sched = GetCurrentCpuSched();
14
15 LockGuard<SpinLock> lock_guard(cpu_sched.lock);
16
17 // 查找等待该资源的任务列表
18 auto it = cpu_sched.blocked_tasks.find(resource_id);
19
20 if (it == cpu_sched.blocked_tasks.end()) {
21 // 没有任务等待该资源
22 klog::Debug("Wakeup: No tasks waiting on resource={}, data={:#x}",
23 resource_id.GetTypeName(),
24 static_cast<uint64_t>(resource_id.GetData()));
25 return;
26 }
27
28 // 唤醒所有等待该资源的任务
29 auto& waiting_tasks = it->second;
30 size_t wakeup_count = 0;
31
32 while (!waiting_tasks.empty()) {
33 auto* task = waiting_tasks.front();
34 waiting_tasks.pop_front();
35
36 assert(task->GetStatus() == TaskStatus::kBlocked &&
37 "Wakeup: task status must be kBlocked");
38 assert(task->aux->blocked_on == resource_id &&
39 "Wakeup: task blocked_on must match resource_id");
40
41 // 将任务标记为就绪
42 task->fsm.Receive(MsgWakeup{});
43 task->aux->blocked_on = ResourceId{};
44
45 // 将任务重新加入对应调度器的就绪队列
46 auto* scheduler =
47 cpu_sched.schedulers[static_cast<uint8_t>(task->policy)].get();
48 assert(scheduler != nullptr && "Wakeup: scheduler must not be null");
49 scheduler->Enqueue(task);
50 wakeup_count++;
51 }
52
53 // 移除空的资源队列
54 cpu_sched.blocked_tasks.erase(resource_id);
55
56 klog::Debug("Wakeup: Woke up {} tasks from resource={}, data={:#x}",
57 wakeup_count, resource_id.GetTypeName(),
58 static_cast<uint64_t>(resource_id.GetData()));
59}
Here is the call graph for this function:

Member Data Documentation

◆ cpu_schedulers_

std::array<CpuSchedData, SIMPLEKERNEL_MAX_CORE_COUNT> TaskManager::cpu_schedulers_ {}
private

每个核心的调度数据

Definition at line 224 of file task_manager.hpp.

224{};

◆ interrupt_threads_

etl::unordered_map<uint64_t, TaskControlBlock*, kernel::config::kMaxInterruptThreads, kernel::config::kMaxInterruptThreadsBuckets> TaskManager::interrupt_threads_
private

中断号 -> 中断线程映射

Definition at line 239 of file task_manager.hpp.

◆ interrupt_threads_lock_

SpinLock TaskManager::interrupt_threads_lock_ {"interrupt_threads_lock"}
private

中断线程相关数据保护锁

Definition at line 234 of file task_manager.hpp.

234{"interrupt_threads_lock"};

◆ interrupt_work_queues_

etl::unordered_map<uint64_t, InterruptWorkQueue*, kernel::config::kMaxInterruptThreads, kernel::config::kMaxInterruptThreadsBuckets> TaskManager::interrupt_work_queues_
private

中断号 -> 工作队列映射

Definition at line 244 of file task_manager.hpp.

◆ kInterruptQueueCapacity

constexpr size_t TaskManager::kInterruptQueueCapacity = 256
staticconstexprprivate

中断工作队列容量

Definition at line 200 of file task_manager.hpp.

◆ pid_allocator_

std::atomic<size_t> TaskManager::pid_allocator_ {1}
private

PID 分配器

Definition at line 247 of file task_manager.hpp.

247{1};

◆ task_table_

etl::unordered_map<Pid, etl::unique_ptr<TaskControlBlock>, kernel::config::kMaxTasks, kernel::config::kMaxTasksBuckets> TaskManager::task_table_
private

Definition at line 231 of file task_manager.hpp.

◆ task_table_lock_

SpinLock TaskManager::task_table_lock_ {"task_table_lock"}
private

全局任务表 (PID -> TCB 映射)

Definition at line 227 of file task_manager.hpp.

227{"task_table_lock"};

The documentation for this class was generated from the following files: