1 | // SPDX-License-Identifier: GPL-3.0-or-later |
2 | |
3 | #include "mos/device/timer.hpp" |
4 | #include "mos/ipc/ipc_io.hpp" |
5 | #include "mos/ipc/memfd.hpp" |
6 | #include "mos/ipc/pipe.hpp" |
7 | #include "mos/misc/power.hpp" |
8 | #include "mos/mm/dma.hpp" |
9 | #include "mos/tasks/signal.hpp" |
10 | |
11 | #include <bits/posix/iovec.h> |
12 | #include <errno.h> |
13 | #include <fcntl.h> |
14 | #include <mos/filesystem/fs_types.h> |
15 | #include <mos/filesystem/vfs.hpp> |
16 | #include <mos/io/io.hpp> |
17 | #include <mos/locks/futex.hpp> |
18 | #include <mos/mm/mmap.hpp> |
19 | #include <mos/mm/paging/paging.hpp> |
20 | #include <mos/platform/platform.hpp> |
21 | #include <mos/syscall/decl.h> |
22 | #include <mos/syscall/number.h> |
23 | #include <mos/syslog/printk.hpp> |
24 | #include <mos/tasks/elf.hpp> |
25 | #include <mos/tasks/process.hpp> |
26 | #include <mos/tasks/schedule.hpp> |
27 | #include <mos/tasks/task_types.hpp> |
28 | #include <mos/tasks/thread.hpp> |
29 | #include <mos/types.hpp> |
30 | #include <mos_stdlib.hpp> |
31 | #include <mos_string.hpp> |
32 | #include <sys/poll.h> |
33 | |
34 | MOS_ENUM_OPERATORS(fd_flags_t); |
35 | |
36 | #define DEFINE_SYSCALL(ret, name) \ |
37 | MOS_STATIC_ASSERT(SYSCALL_DEFINED(name)); \ |
38 | ret define_syscall(name) |
39 | |
40 | DEFINE_SYSCALL(void, poweroff)(bool reboot, u32 magic) |
41 | { |
42 | #define POWEROFF_MAGIC MOS_FOURCC('G', 'B', 'y', 'e') |
43 | if (magic != POWEROFF_MAGIC) |
44 | { |
45 | mos_warn("poweroff syscall called with wrong magic number (0x%x)" , magic); |
46 | return; |
47 | } |
48 | |
49 | if (!reboot) |
50 | { |
51 | pr_info("Meow, see ya~ :3" ); |
52 | power_shutdown(); |
53 | } |
54 | else |
55 | { |
56 | mos_warn("reboot is not implemented yet" ); |
57 | } |
58 | } |
59 | |
60 | DEFINE_SYSCALL(fd_t, vfs_openat)(fd_t dirfd, const char *path, open_flags flags) |
61 | { |
62 | if (path == NULL) |
63 | return -1; |
64 | |
65 | auto f = vfs_openat(fd: dirfd, path, flags); |
66 | if (f.isErr()) |
67 | return f.getErr(); |
68 | return process_attach_ref_fd(current_process, file: &f->io, flags: FD_FLAGS_NONE); |
69 | } |
70 | |
71 | DEFINE_SYSCALL(long, vfs_fstatat)(fd_t fd, const char *path, file_stat_t *stat_buf, fstatat_flags flags) |
72 | { |
73 | return vfs_fstatat(fd, path, stat: stat_buf, flags); |
74 | } |
75 | |
76 | DEFINE_SYSCALL(size_t, io_read)(fd_t fd, void *buf, size_t count) |
77 | { |
78 | if (buf == NULL) |
79 | return -EFAULT; |
80 | |
81 | io_t *io = process_get_fd(current_process, fd); |
82 | if (!io) |
83 | return -EBADF; |
84 | |
85 | return io_read(io, buf, count); |
86 | } |
87 | |
88 | DEFINE_SYSCALL(size_t, io_write)(fd_t fd, const void *buf, size_t count) |
89 | { |
90 | if (buf == NULL) |
91 | { |
92 | pr_warn("io_write called with invalid arguments (fd=%d, buf=%p, count=%zd)" , fd, buf, count); |
93 | return -EFAULT; |
94 | } |
95 | |
96 | io_t *io = process_get_fd(current_process, fd); |
97 | if (!io) |
98 | { |
99 | pr_warn("io_write called with invalid fd %d" , fd); |
100 | return -EBADF; |
101 | } |
102 | |
103 | return io_write(io, buf, count); |
104 | } |
105 | |
106 | DEFINE_SYSCALL(bool, io_close)(fd_t fd) |
107 | { |
108 | process_detach_fd(current_process, fd); |
109 | return true; |
110 | } |
111 | |
112 | DEFINE_SYSCALL([[noreturn]] void, exit)(u32 exit_code) |
113 | { |
114 | // only use the lower 8 bits |
115 | exit_code &= 0xff; |
116 | process_exit(proc: std::move(current_process), exit_code, signal: 0); |
117 | __builtin_unreachable(); |
118 | } |
119 | |
120 | DEFINE_SYSCALL(void, yield_cpu)(void) |
121 | { |
122 | spinlock_acquire(¤t_thread->state_lock); |
123 | reschedule(); |
124 | } |
125 | |
126 | DEFINE_SYSCALL(pid_t, fork)(void) |
127 | { |
128 | const auto parent = current_process; |
129 | const auto child = process_do_fork(process: parent); |
130 | if (unlikely(!child)) |
131 | return -1; |
132 | return child->pid; // return 0 for child, pid for parent |
133 | } |
134 | |
135 | DEFINE_SYSCALL(pid_t, get_pid)(void) |
136 | { |
137 | return current_process->pid; |
138 | } |
139 | |
140 | DEFINE_SYSCALL(pid_t, get_parent_pid)(void) |
141 | { |
142 | return current_process->parent->pid; |
143 | } |
144 | |
145 | DEFINE_SYSCALL(pid_t, spawn)(const char *path, const char *const argv[], const char *const envp[]) |
146 | { |
147 | const stdio_t stdio = current_stdio(); |
148 | const auto process = elf_create_process(path, current_process, argv, envp, ios: &stdio); |
149 | |
150 | if (!process) |
151 | return -1; |
152 | |
153 | return process->pid; |
154 | } |
155 | |
156 | DEFINE_SYSCALL(tid_t, create_thread)(const char *name, thread_entry_t entry, void *arg, size_t stack_size, void *stack) |
157 | { |
158 | const auto opt_thread = thread_new(current_process, mode: THREAD_MODE_USER, name, stack_size, stack); |
159 | if (opt_thread.isErr()) |
160 | return -1; |
161 | |
162 | const auto thread = opt_thread.get(); |
163 | |
164 | platform_context_setup_child_thread(thread, entry, arg); |
165 | thread_complete_init(thread); |
166 | scheduler_add_thread(thread); |
167 | return thread->tid; |
168 | } |
169 | |
170 | DEFINE_SYSCALL(tid_t, get_tid)(void) |
171 | { |
172 | return current_thread->tid; |
173 | } |
174 | |
175 | DEFINE_SYSCALL([[noreturn]] void, thread_exit)(void) |
176 | { |
177 | thread_exit(t: std::move(current_thread)); |
178 | __builtin_unreachable(); |
179 | } |
180 | |
181 | DEFINE_SYSCALL(bool, wait_for_thread)(tid_t tid) |
182 | { |
183 | return thread_wait_for_tid(tid); |
184 | } |
185 | |
186 | DEFINE_SYSCALL(bool, futex_wait)(futex_word_t *futex, u32 val) |
187 | { |
188 | return futex_wait(futex, expected: val); |
189 | } |
190 | |
191 | DEFINE_SYSCALL(bool, futex_wake)(futex_word_t *futex, size_t count) |
192 | { |
193 | return futex_wake(lock: futex, num_to_wake: count); |
194 | } |
195 | |
196 | DEFINE_SYSCALL(fd_t, ipc_create)(const char *name, size_t max_pending_connections) |
197 | { |
198 | auto io = ipc_create(name, max_pending_connections); |
199 | if (io.isErr()) |
200 | return io.getErr(); |
201 | return process_attach_ref_fd(current_process, file: io.get(), flags: FD_FLAGS_NONE); |
202 | } |
203 | |
204 | DEFINE_SYSCALL(fd_t, ipc_accept)(fd_t listen_fd) |
205 | { |
206 | io_t *server = process_get_fd(current_process, fd: listen_fd); |
207 | if (server == NULL) |
208 | return -1; |
209 | |
210 | auto client_io = ipc_accept(server); |
211 | if (client_io.isErr()) |
212 | return client_io.getErr(); |
213 | |
214 | return process_attach_ref_fd(current_process, file: client_io.get(), flags: FD_FLAGS_NONE); |
215 | } |
216 | |
217 | DEFINE_SYSCALL(fd_t, ipc_connect)(const char *server, size_t buffer_size) |
218 | { |
219 | auto io = ipc_connect(name: server, buffer_size); |
220 | if (io.isErr()) |
221 | return io.getErr(); |
222 | return process_attach_ref_fd(current_process, file: io.get(), flags: FD_FLAGS_NONE); |
223 | } |
224 | |
225 | DEFINE_SYSCALL(u64, arch_syscall)(u64 syscall, u64 arg1, u64 arg2, u64 arg3, u64 arg4) |
226 | { |
227 | return platform_arch_syscall(syscall, arg1, arg2, arg3, arg4); |
228 | } |
229 | |
230 | DEFINE_SYSCALL(long, vfs_mount)(const char *device, const char *mountpoint, const char *fs_type, const char *options) |
231 | { |
232 | return vfs_mount(device, path: mountpoint, fs: fs_type, options); |
233 | } |
234 | |
235 | DEFINE_SYSCALL(ssize_t, vfs_readlinkat)(fd_t dirfd, const char *path, char *buf, size_t buflen) |
236 | { |
237 | return vfs_readlinkat(dirfd, path, buf, size: buflen); |
238 | } |
239 | |
240 | DEFINE_SYSCALL(long, vfs_unlinkat)(fd_t dirfd, const char *path) |
241 | { |
242 | return vfs_unlinkat(dirfd, path); |
243 | } |
244 | |
245 | DEFINE_SYSCALL(long, vfs_symlink)(const char *target, const char *linkpath) |
246 | { |
247 | return vfs_symlink(path: target, target: linkpath); |
248 | } |
249 | |
250 | DEFINE_SYSCALL(long, vfs_mkdir)(const char *path) |
251 | { |
252 | return vfs_mkdir(path); |
253 | } |
254 | |
255 | DEFINE_SYSCALL(size_t, vfs_list_dir)(fd_t fd, char *buffer, size_t buffer_size) |
256 | { |
257 | io_t *io = process_get_fd(current_process, fd); |
258 | if (io == NULL) |
259 | return false; |
260 | return vfs_list_dir(io, buf: buffer, size: buffer_size); |
261 | } |
262 | |
263 | DEFINE_SYSCALL(long, fd_manipulate)(fd_t fd, u64 op, void *arg) |
264 | { |
265 | fd_type *fdt = ¤t_process->files[fd]; |
266 | if (fdt->io == NULL) |
267 | return -EBADF; |
268 | |
269 | switch (op) |
270 | { |
271 | case F_DUPFD: |
272 | { |
273 | fd_t fd2 = process_attach_ref_fd(current_process, file: fdt->io, flags: fdt->flags); |
274 | return fd2; |
275 | } |
276 | case F_DUPFD_CLOEXEC: |
277 | { |
278 | fd_t fd2 = process_attach_ref_fd(current_process, file: fdt->io, flags: fdt->flags | FD_FLAGS_CLOEXEC); |
279 | return fd2; |
280 | } |
281 | case F_GETFD: |
282 | { |
283 | return fdt->flags; |
284 | } |
285 | case F_SETFD: |
286 | { |
287 | // test if arg is a valid flag |
288 | const fd_flags_t flags = (fd_flags_t) (u64) arg; |
289 | if (flags & ~FD_FLAGS_CLOEXEC) |
290 | return -EINVAL; |
291 | fdt->flags = flags; |
292 | return 0; |
293 | } |
294 | case F_GETFL: |
295 | case F_SETFL: |
296 | { |
297 | return -ENOSYS; // not implemented |
298 | } |
299 | case F_GETLK: |
300 | case F_SETLK: |
301 | case F_SETLKW: |
302 | { |
303 | return -ENOSYS; // not implemented |
304 | } |
305 | case F_GETOWN: |
306 | case F_SETOWN: |
307 | case F_GETOWN_EX: |
308 | case F_SETOWN_EX: |
309 | case F_GETSIG: |
310 | case F_SETSIG: |
311 | case F_GETOWNER_UIDS: |
312 | case F_ADD_SEALS: |
313 | case F_GET_SEALS: |
314 | { |
315 | return -ENOSYS; // not implemented |
316 | } |
317 | } |
318 | |
319 | return -EINVAL; |
320 | } |
321 | |
322 | DEFINE_SYSCALL(void *, mmap_anonymous)(ptr_t hint_addr, size_t size, mem_perm_t perm, mmap_flags_t flags) |
323 | { |
324 | const vm_flags vmflags = VM_USER | (vm_flags) perm; // vm_flags shares the same values as mem_perm_t |
325 | const size_t n_pages = ALIGN_UP_TO_PAGE(size) / MOS_PAGE_SIZE; |
326 | |
327 | ptr_t result = mmap_anonymous(current_mm, hint_addr, flags, vm_flags: vmflags, n_pages); |
328 | return (void *) result; |
329 | } |
330 | |
331 | DEFINE_SYSCALL(void *, mmap_file)(ptr_t hint_addr, size_t size, mem_perm_t perm, mmap_flags_t mmap_flags, fd_t fd, off_t offset) |
332 | { |
333 | const vm_flags vmflags = VM_USER | (vm_flags) perm; // vm_flags shares the same values as mem_perm_t |
334 | const size_t n_pages = ALIGN_UP_TO_PAGE(size) / MOS_PAGE_SIZE; |
335 | |
336 | io_t *io = process_get_fd(current_process, fd); |
337 | if (io == NULL) |
338 | return NULL; |
339 | |
340 | ptr_t result = mmap_file(current_mm, hint_addr, flags: mmap_flags, vm_flags: vmflags, n_pages, io, offset); |
341 | return (void *) result; |
342 | } |
343 | |
344 | DEFINE_SYSCALL(pid_t, wait_for_process)(pid_t pid, u32 *exit_code, u32 flags) |
345 | { |
346 | return process_wait_for_pid(pid, exit_code, flags); |
347 | } |
348 | |
349 | DEFINE_SYSCALL(bool, munmap)(void *addr, size_t size) |
350 | { |
351 | return munmap(addr: (ptr_t) addr, size); |
352 | } |
353 | |
354 | DEFINE_SYSCALL(long, vfs_chdirat)(fd_t dirfd, const char *path) |
355 | { |
356 | return vfs_chdirat(dirfd, path); |
357 | } |
358 | |
359 | DEFINE_SYSCALL(ssize_t, vfs_getcwd)(char *buf, size_t size) |
360 | { |
361 | return vfs_getcwd(buf, size); |
362 | } |
363 | |
364 | DEFINE_SYSCALL(off_t, io_seek)(fd_t fd, off_t offset, io_seek_whence_t whence) |
365 | { |
366 | io_t *io = process_get_fd(current_process, fd); |
367 | if (io == NULL) |
368 | return -1; |
369 | return io_seek(io, offset, whence); |
370 | } |
371 | |
372 | DEFINE_SYSCALL(off_t, io_tell)(fd_t fd) |
373 | { |
374 | io_t *io = process_get_fd(current_process, fd); |
375 | if (io == NULL) |
376 | return -1; |
377 | return io_tell(io); |
378 | } |
379 | |
380 | DEFINE_SYSCALL(bool, signal_register)(signal_t sig, const sigaction_t *action) |
381 | { |
382 | return process_register_signal_handler(current_process, sig, sigaction: action); |
383 | } |
384 | |
385 | DEFINE_SYSCALL(long, signal_process)(pid_t pid, signal_t sig) |
386 | { |
387 | const auto process = process_get(pid); |
388 | if (!process) |
389 | return -ESRCH; |
390 | return signal_send_to_process(target: *process, signal: sig); |
391 | } |
392 | |
393 | DEFINE_SYSCALL(long, signal_thread)(tid_t tid, signal_t sig) |
394 | { |
395 | Thread *thread = thread_get(id: tid); |
396 | if (!thread) |
397 | return -ESRCH; |
398 | return signal_send_to_thread(target: thread, signal: sig); |
399 | } |
400 | |
401 | DEFINE_SYSCALL([[noreturn]] void, signal_return)(void *sp) |
402 | { |
403 | platform_restore_from_signal_handler(sp); |
404 | } |
405 | |
406 | DEFINE_SYSCALL(bool, vm_protect)(void *addr, size_t size, mem_perm_t perm) |
407 | { |
408 | return vm_protect(current_mm, addr: (ptr_t) addr, size, perm: (vm_flags) perm); |
409 | } |
410 | |
411 | DEFINE_SYSCALL(int, io_poll)(struct pollfd *fds, nfds_t nfds, int timeout) |
412 | { |
413 | if (timeout == 0) // poll with timeout 0 is just a check |
414 | return 0; |
415 | |
416 | if (!fds || nfds == 0) |
417 | return -1; |
418 | |
419 | for (nfds_t i = 0; i < nfds; i++) |
420 | { |
421 | if (fds[i].fd < 0) |
422 | fds[i].revents = 0; |
423 | pr_info2("io_poll: fd=%d, events=%d" , fds[i].fd, fds[i].events); |
424 | } |
425 | |
426 | pr_emerg("io_poll is not implemented yet\n" ); |
427 | signal_send_to_thread(current_thread, SIGKILL); // unimplemented |
428 | return 0; |
429 | } |
430 | |
431 | #ifndef FD_CLR |
432 | #define FD_CLR(__fd, __set) (__set->fds_bits[__fd / 8] &= ~(1 << (__fd % 8))) |
433 | #endif |
434 | |
435 | #ifndef FD_ISSET |
436 | #define FD_ISSET(__fd, __set) (__set->fds_bits[__fd / 8] & (1 << (__fd % 8))) |
437 | #endif |
438 | |
439 | #ifndef FD_SET |
440 | #define FD_SET(__fd, __set) (__set->fds_bits[__fd / 8] |= 1 << (__fd % 8)) |
441 | #endif |
442 | |
443 | #ifndef FD_ZERO |
444 | #define FD_ZERO(__set) memset(__set->fds_bits, 0, sizeof(fd_set)) |
445 | #endif |
446 | |
447 | DEFINE_SYSCALL(int, io_pselect)(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, const struct timespec *timeout, const sigset_t *sigmask) |
448 | { |
449 | MOS_UNUSED(timeout); |
450 | MOS_UNUSED(sigmask); |
451 | |
452 | for (int i = 0; i < nfds; i++) |
453 | { |
454 | if (readfds && FD_ISSET(i, readfds)) |
455 | { |
456 | // pr_info2("io_pselect: fd=%d, read", i); |
457 | } |
458 | if (writefds && FD_ISSET(i, writefds)) |
459 | { |
460 | // pr_info2("io_pselect: fd=%d, write", i); |
461 | } |
462 | if (exceptfds && FD_ISSET(i, exceptfds)) |
463 | { |
464 | // pr_info2("io_pselect: fd=%d, except", i); |
465 | } |
466 | } |
467 | |
468 | return 1; // stub |
469 | } |
470 | |
471 | DEFINE_SYSCALL(long, execveat)(fd_t dirfd, const char *path, const char *const argv[], const char *const envp[], u32 flags) |
472 | { |
473 | return process_do_execveat(dirfd, path, argv, envp, flags); |
474 | } |
475 | |
476 | DEFINE_SYSCALL(long, clock_msleep)(u64 ms) |
477 | { |
478 | timer_msleep(ms); |
479 | return 0; |
480 | } |
481 | |
482 | DEFINE_SYSCALL(fd_t, io_dup)(fd_t fd) |
483 | { |
484 | io_t *io = process_get_fd(current_process, fd); |
485 | if (io == NULL) |
486 | return -EBADF; // fd is not a valid file descriptor |
487 | return process_attach_ref_fd(current_process, file: io_ref(io), current_process->files[fd].flags); |
488 | } |
489 | |
490 | DEFINE_SYSCALL(fd_t, io_dup2)(fd_t oldfd, fd_t newfd) |
491 | { |
492 | fd_type *old = ¤t_process->files[oldfd]; |
493 | if (old->io == NULL) |
494 | return -EBADF; // oldfd is not a valid file descriptor |
495 | |
496 | if (oldfd == newfd) |
497 | return newfd; |
498 | |
499 | process_detach_fd(current_process, fd: newfd); |
500 | |
501 | current_process->files[newfd].io = io_ref(io: old->io); |
502 | current_process->files[newfd].flags = old->flags; |
503 | return newfd; |
504 | } |
505 | |
506 | DEFINE_SYSCALL(bool, dmabuf_alloc)(size_t n_pages, ptr_t *phys, ptr_t *virt) |
507 | { |
508 | pfn_t pfn = dmabuf_allocate(n_pages, pages: virt); |
509 | *phys = pfn * MOS_PAGE_SIZE; |
510 | return !IS_ERR_VALUE(pfn); |
511 | } |
512 | |
513 | DEFINE_SYSCALL(bool, dmabuf_free)(ptr_t vaddr, ptr_t paddr) |
514 | { |
515 | return dmabuf_free(vaddr, paddr); |
516 | } |
517 | |
518 | DEFINE_SYSCALL(bool, dmabuf_share)(void *buffer, size_t size, ptr_t *phyaddr) |
519 | { |
520 | pfn_t pfn = dmabuf_share(buffer, size); |
521 | |
522 | if (IS_ERR_VALUE(pfn)) |
523 | return false; |
524 | |
525 | *phyaddr = pfn * MOS_PAGE_SIZE; |
526 | return true; |
527 | } |
528 | |
529 | DEFINE_SYSCALL(bool, dmabuf_unshare)(ptr_t phys, size_t size, void *buf) |
530 | { |
531 | return dmabuf_unshare(phys, size, virt: buf); |
532 | } |
533 | |
534 | DEFINE_SYSCALL(long, pipe)(fd_t *reader, fd_t *writer, fd_flags_t flags) |
535 | { |
536 | auto pipe = pipe_create(MOS_PAGE_SIZE * 4); |
537 | if (pipe.isErr()) |
538 | return pipe.getErr(); |
539 | |
540 | auto pipeio = pipeio_create(pipe: pipe.get()); |
541 | *reader = process_attach_ref_fd(current_process, file: &pipeio->io_r, flags); |
542 | *writer = process_attach_ref_fd(current_process, file: &pipeio->io_w, flags); |
543 | return 0; |
544 | } |
545 | |
546 | DEFINE_SYSCALL(ssize_t, io_readv)(fd_t fd, const struct iovec *iov, int iovcnt) |
547 | { |
548 | if (fd < 0) |
549 | return -EBADF; |
550 | |
551 | if (iov == NULL) |
552 | return -EFAULT; |
553 | |
554 | io_t *io = process_get_fd(current_process, fd); |
555 | if (!io) |
556 | return -EBADF; |
557 | |
558 | for (int i = 0; i < iovcnt; i++) |
559 | { |
560 | if (iov[i].iov_base == NULL) |
561 | return -EFAULT; |
562 | } |
563 | |
564 | ssize_t bytes_read = 0; |
565 | |
566 | for (int i = 0; i < iovcnt; i++) |
567 | { |
568 | size_t ret = io_read(io, buf: iov[i].iov_base, count: iov[i].iov_len); |
569 | if (IS_ERR_VALUE(ret)) |
570 | return ret; |
571 | |
572 | bytes_read += ret; |
573 | |
574 | if (ret != iov[i].iov_len) |
575 | break; // short read, leave |
576 | } |
577 | |
578 | return bytes_read; |
579 | } |
580 | |
581 | DEFINE_SYSCALL(long, vfs_unmount)(const char *path) |
582 | { |
583 | return vfs_unmount(path); |
584 | } |
585 | |
586 | DEFINE_SYSCALL(long, clock_gettimeofday)(struct timespec *ts) |
587 | { |
588 | timeval_t tv; |
589 | platform_get_time(val: &tv); |
590 | ts->tv_sec = tv.hour * 3600 + tv.minute * 60 + tv.second; |
591 | ts->tv_nsec = 0; |
592 | return 0; |
593 | } |
594 | |
595 | DEFINE_SYSCALL(long, thread_setname)(tid_t tid, const char *name) |
596 | { |
597 | Thread *thread = thread_get(id: tid); |
598 | if (!thread) |
599 | return -ESRCH; |
600 | |
601 | thread->name = name; |
602 | return true; |
603 | } |
604 | |
605 | DEFINE_SYSCALL(ssize_t, thread_getname)(tid_t tid, char *buf, size_t buflen) |
606 | { |
607 | Thread *thread = thread_get(id: tid); |
608 | |
609 | if (!thread) |
610 | return -ESRCH; |
611 | |
612 | char *end = strncpy(dest: buf, src: thread->name.data(), n: buflen); |
613 | return end - buf; |
614 | } |
615 | |
616 | DEFINE_SYSCALL(long, vfs_fchmodat)(fd_t dirfd, const char *path, int mode, int flags) |
617 | { |
618 | return vfs_fchmodat(fd: dirfd, path, perm: mode, flags); |
619 | } |
620 | |
621 | DEFINE_SYSCALL(long, io_pread)(fd_t fd, void *buf, size_t count, off_t offset) |
622 | { |
623 | if (fd < 0) |
624 | return -EBADF; |
625 | |
626 | if (buf == NULL) |
627 | return -EFAULT; |
628 | |
629 | io_t *io = process_get_fd(current_process, fd); |
630 | if (!io) |
631 | return -EBADF; |
632 | |
633 | return io_pread(io, buf, count, offset); |
634 | } |
635 | |
636 | DEFINE_SYSCALL(fd_t, memfd_create)(const char *name, u32 flags) |
637 | { |
638 | auto io = memfd_create(name); |
639 | if (io.isErr()) |
640 | return io.getErr(); |
641 | |
642 | return process_attach_ref_fd(current_process, file: io.get(), flags: (fd_flags_t) flags); |
643 | } |
644 | |
645 | DEFINE_SYSCALL(long, signal_mask_op)(int how, const sigset_t *set, sigset_t *oldset) |
646 | { |
647 | if (oldset) |
648 | *oldset = current_thread->signal_info.mask; |
649 | |
650 | if (set) |
651 | { |
652 | switch (how) |
653 | { |
654 | case SIG_SETMASK: current_thread->signal_info.mask = *set; break; |
655 | case SIG_BLOCK: |
656 | { |
657 | char *ptr = (char *) set; |
658 | char *mask = (char *) ¤t_thread->signal_info.mask; |
659 | for (size_t i = 0; i < sizeof(sigset_t); i++) |
660 | mask[i] |= ptr[i]; |
661 | break; |
662 | } |
663 | case SIG_UNBLOCK: |
664 | { |
665 | char *ptr = (char *) set; |
666 | char *mask = (char *) ¤t_thread->signal_info.mask; |
667 | for (size_t i = 0; i < sizeof(sigset_t); i++) |
668 | mask[i] &= ~ptr[i]; |
669 | break; |
670 | } |
671 | default: return -EINVAL; |
672 | } |
673 | } |
674 | |
675 | return 0; |
676 | } |
677 | |
678 | DEFINE_SYSCALL(long, vfs_fsync)(fd_t fd, bool data_only) |
679 | { |
680 | io_t *io = process_get_fd(current_process, fd); |
681 | if (!io) |
682 | return -EBADF; |
683 | |
684 | if (io->type != IO_FILE) |
685 | return -EBADF; |
686 | |
687 | return vfs_fsync(io, sync_metadata: data_only, start: 0, end: (off_t) -1); |
688 | } |
689 | |