SimpleKernel 1.17.0
Loading...
Searching...
No Matches
syscall.cpp
Go to the documentation of this file.
1
5#include "syscall.hpp"
6
7#include "kernel.h"
8#include "kernel_log.hpp"
9#include "spinlock.hpp"
10#include "task_manager.hpp"
11
12namespace {
14SpinLock futex_lock_;
15} // namespace
16
17auto syscall_dispatcher(int64_t syscall_id, uint64_t args[6]) -> int {
18 int64_t ret = 0;
19 switch (syscall_id) {
20 case kSyscallWrite:
21 ret = sys_write(static_cast<int>(args[0]),
22 reinterpret_cast<const char*>(args[1]),
23 static_cast<size_t>(args[2]));
24 break;
25 case kSyscallExit:
26 ret = sys_exit(static_cast<int>(args[0]));
27 break;
28 case kSyscallYield:
29 ret = sys_yield();
30 break;
31 case kSyscallClone:
32 ret = sys_clone(args[0], reinterpret_cast<void*>(args[1]),
33 reinterpret_cast<int*>(args[2]),
34 reinterpret_cast<int*>(args[3]),
35 reinterpret_cast<void*>(args[4]));
36 break;
37 case kSyscallFork:
38 ret = sys_fork();
39 break;
40 case kSyscallGettid:
41 ret = sys_gettid();
42 break;
43 case kSyscallSetTidAddress:
44 ret = sys_set_tid_address(reinterpret_cast<int*>(args[0]));
45 break;
46 case kSyscallFutex:
47 ret = sys_futex(
48 reinterpret_cast<int*>(args[0]), static_cast<int>(args[1]),
49 static_cast<int>(args[2]), reinterpret_cast<const void*>(args[3]),
50 reinterpret_cast<int*>(args[4]), static_cast<int>(args[5]));
51 break;
52 case kSyscallSleep:
53 ret = sys_sleep(args[0]);
54 break;
55 default:
56 klog::Err("[Syscall] Unknown syscall id: {}", syscall_id);
57 ret = -1;
58 break;
59 }
60 return ret;
61}
62
63[[nodiscard]] auto sys_write(int fd, const char* buf, size_t len) -> int {
64 // 简单实现:仅支持向标准输出(1)和错误输出(2)打印
65 if (fd == 1 || fd == 2) {
67 for (size_t i = 0; i < len; ++i) {
68 etl_putchar(buf[i]);
69 }
70 return static_cast<int>(len);
71 }
72 return -1;
73}
74
75auto sys_exit(int code) -> int {
76 klog::Info("[Syscall] Process {} exited with code {}",
77 TaskManagerSingleton::instance().GetCurrentTask()->pid, code);
78 // 调用 TaskManager 的 Exit 方法处理线程退出
79 TaskManagerSingleton::instance().Exit(code);
80 // 不会执行到这里,因为 Exit 会触发调度切换
81 klog::Err("[Syscall] sys_exit should not return!");
82 return 0;
83}
84
85[[nodiscard]] auto sys_yield() -> int {
86 TaskManagerSingleton::instance().Schedule();
87 return 0;
88}
89
90[[nodiscard]] auto sys_sleep(uint64_t ms) -> int {
91 TaskManagerSingleton::instance().Sleep(ms);
92 return 0;
93}
94
95[[nodiscard]] auto sys_clone(uint64_t flags, void* stack, int* parent_tid,
96 int* child_tid, void* tls) -> int {
97 auto& task_manager = TaskManagerSingleton::instance();
98 auto current = task_manager.GetCurrentTask();
99
100 if (!current || !current->trap_context_ptr) {
101 klog::Err("[Syscall] sys_clone: Invalid current task or trap context");
102 return -1;
103 }
104
105 // 调用 TaskManager 的 Clone 方法
106 auto result = task_manager.Clone(flags, stack, parent_tid, child_tid, tls,
107 *current->trap_context_ptr);
108
109 if (!result.has_value()) {
110 // 失败返回 -1
111 klog::Err("[Syscall] sys_clone failed: {}", result.error().message());
112 return -1;
113 }
114
115 Pid child_pid = result.value();
116 if (child_pid == 0) {
117 // 子进程/线程返回 0
118 return 0;
119 } else {
120 // 父进程返回子进程 PID
121 return static_cast<int>(child_pid);
122 }
123}
124
125[[nodiscard]] auto sys_fork() -> int {
126 auto& task_manager = TaskManagerSingleton::instance();
127 auto current = task_manager.GetCurrentTask();
128
129 if (!current || !current->trap_context_ptr) {
130 klog::Err("[Syscall] sys_fork: Invalid current task or trap context");
131 return -1;
132 }
133
134 // fork = clone with flags=0 (完全复制,不共享任何资源)
135 auto result = task_manager.Clone(0, nullptr, nullptr, nullptr, nullptr,
136 *current->trap_context_ptr);
137
138 if (!result.has_value()) {
139 // 失败返回 -1
140 klog::Err("[Syscall] sys_fork failed: {}", result.error().message());
141 return -1;
142 }
143
144 Pid child_pid = result.value();
145 if (child_pid == 0) {
146 // 子进程返回 0
147 return 0;
148 } else {
149 // 父进程返回子进程 PID
150 return static_cast<int>(child_pid);
151 }
152}
153
154[[nodiscard]] auto sys_gettid() -> int {
155 auto current = TaskManagerSingleton::instance().GetCurrentTask();
156 if (!current) {
157 klog::Err("[Syscall] sys_gettid: No current task");
158 return -1;
159 }
160 return static_cast<int>(current->pid);
161}
162
163[[nodiscard]] auto sys_set_tid_address([[maybe_unused]] int* tidptr) -> int {
164 auto current = TaskManagerSingleton::instance().GetCurrentTask();
165 if (!current) {
166 klog::Err("[Syscall] sys_set_tid_address: No current task");
167 return -1;
168 }
169
170 // 保存 tidptr,在线程退出时会清零该地址并执行 futex wake
172 // current->clear_child_tid = tidptr;
173
174 // 返回当前线程的 TID
175 return static_cast<int>(current->pid);
176}
177
178[[nodiscard]] auto sys_futex(int* uaddr, int op, int val,
179 [[maybe_unused]] const void* timeout,
180 [[maybe_unused]] int* uaddr2,
181 [[maybe_unused]] int val3) -> int {
182 // Futex 常量定义
183 static constexpr int kFutexWait = 0;
184 static constexpr int kFutexWake = 1;
185 static constexpr int kFutexRequeue = 3;
186
187 // 提取操作类型(低位)
188 int cmd = op & 0x7F;
189
190 auto& task_manager = TaskManagerSingleton::instance();
191
192 switch (cmd) {
193 case kFutexWait: {
194 klog::Debug("[Syscall] FUTEX_WAIT on {:#x} (val={})",
195 static_cast<uint64_t>(reinterpret_cast<uintptr_t>(uaddr)),
196 val);
197
199 reinterpret_cast<uintptr_t>(uaddr));
200 {
201 LockGuard<SpinLock> guard(futex_lock_);
202 if (*uaddr != val) {
203 return 0;
204 }
205 }
206 // futex_lock_ released before Block() — SpinLock must NOT be held
207 // across context switch boundaries (Block → Schedule → switch_to).
208 // A narrow race exists: FUTEX_WAKE between lock release and Block()
209 // can miss this thread. Production kernels solve this with a two-phase
210 // API (add-to-waitqueue under lock, schedule after release). This is
211 // still far safer than the original completely-unprotected check.
212 task_manager.Block(futex_id);
213 return 0;
214 }
215
216 case kFutexWake: {
217 klog::Debug("[Syscall] FUTEX_WAKE on {:#x} (count={})",
218 static_cast<uint64_t>(reinterpret_cast<uintptr_t>(uaddr)),
219 val);
220
222 reinterpret_cast<uintptr_t>(uaddr));
223 {
224 LockGuard<SpinLock> guard(futex_lock_);
225 task_manager.Wakeup(futex_id);
226 }
227
229 return val;
230 }
231
232 case kFutexRequeue: {
233 // 将等待 uaddr 的线程重新排队到 uaddr2
235 klog::Warn("[Syscall] FUTEX_REQUEUE not implemented");
236 return -1;
237 }
238
239 default:
240 klog::Err("[Syscall] Unknown futex operation: {}", cmd);
241 return -1;
242 }
243}
244
245[[nodiscard]] auto sys_sched_getaffinity(int pid, size_t cpusetsize,
246 uint64_t* mask) -> int {
247 auto& task_manager = TaskManagerSingleton::instance();
248
249 TaskControlBlock* target;
250 if (pid == 0) {
251 // pid=0 表示当前线程
252 target = task_manager.GetCurrentTask();
253 } else {
254 // 查找指定 PID 的任务
255 target = task_manager.FindTask(static_cast<Pid>(pid));
256 if (!target) {
257 klog::Err("[Syscall] sys_sched_getaffinity: Task {} not found", pid);
258 return -1;
259 }
260 }
261
262 if (!target) {
263 return -1;
264 }
265
266 // 简单实现:将 cpu_affinity 复制到用户空间
267 if (cpusetsize < sizeof(uint64_t)) {
268 return -1;
269 }
270
271 *mask = target->aux->cpu_affinity;
272 return 0;
273}
274
275[[nodiscard]] auto sys_sched_setaffinity(int pid, size_t cpusetsize,
276 const uint64_t* mask) -> int {
277 auto& task_manager = TaskManagerSingleton::instance();
278
279 TaskControlBlock* target;
280 if (pid == 0) {
281 target = task_manager.GetCurrentTask();
282 } else {
283 // 查找指定 PID 的任务
284 target = task_manager.FindTask(static_cast<Pid>(pid));
285 if (!target) {
286 klog::Err("[Syscall] sys_sched_setaffinity: Task {} not found", pid);
287 return -1;
288 }
289 }
290
291 if (!target) {
292 return -1;
293 }
294
295 // 简单实现:更新 cpu_affinity
296 if (cpusetsize < sizeof(uint64_t)) {
297 return -1;
298 }
299
300 target->aux->cpu_affinity = *mask;
301
302 klog::Debug("[Syscall] Set CPU affinity for task {} to {:#x}", target->pid,
303 *mask);
304
306
307 return 0;
308}
auto etl_putchar(int c) -> void
早期控制台字符输出
RAII 风格的锁守卫模板类
Definition spinlock.hpp:131
资源 ID
自旋锁
Definition spinlock.hpp:27
auto Err(etl::format_string< Args... > fmt, Args &&... args) -> void
以 ERROR 级别记录日志
auto Info(etl::format_string< Args... > fmt, Args &&... args) -> void
以 INFO 级别记录日志
auto Debug(etl::format_string< Args... > fmt, Args &&... args) -> void
以 DEBUG 级别记录日志(SIMPLEKERNEL_MIN_LOG_LEVEL > 0 时编译期消除)
auto Warn(etl::format_string< Args... > fmt, Args &&... args) -> void
以 WARN 级别记录日志
@ kFutex
Futex (快速用户空间互斥锁)
CpuAffinity cpu_affinity
CPU 亲和性位掩码
任务控制块,管理进程/线程的核心数据结构
Pid pid
线程 ID (Task ID)
TaskAuxData * aux
非调度热路径的辅助数据
auto sys_sleep(uint64_t ms) -> int
休眠指定毫秒数
Definition syscall.cpp:90
auto sys_set_tid_address(int *tidptr) -> int
设置线程ID地址(用于线程退出时的清理)
Definition syscall.cpp:163
auto sys_sched_getaffinity(int pid, size_t cpusetsize, uint64_t *mask) -> int
获取线程的CPU亲和性
Definition syscall.cpp:245
auto sys_exit(int code) -> int
退出当前进程或线程
Definition syscall.cpp:75
auto sys_sched_setaffinity(int pid, size_t cpusetsize, const uint64_t *mask) -> int
设置线程的CPU亲和性
Definition syscall.cpp:275
auto sys_futex(int *uaddr, int op, int val, const void *timeout, int *uaddr2, int val3) -> int
快速用户空间互斥锁操作(futex)
Definition syscall.cpp:178
auto sys_gettid() -> int
获取当前线程ID
Definition syscall.cpp:154
auto sys_fork() -> int
创建新进程(fork)
Definition syscall.cpp:125
auto sys_yield() -> int
主动放弃CPU,让出时间片
Definition syscall.cpp:85
auto sys_write(int fd, const char *buf, size_t len) -> int
向文件描述符写入数据
Definition syscall.cpp:63
auto sys_clone(uint64_t flags, void *stack, int *parent_tid, int *child_tid, void *tls) -> int
创建新线程(或进程)
Definition syscall.cpp:95
auto syscall_dispatcher(int64_t syscall_id, uint64_t args[6]) -> int
Definition syscall.cpp:17
size_t Pid
进程 ID 类型