From: Tulio A M Mendes Date: Sat, 14 Mar 2026 07:54:46 +0000 (-0300) Subject: feat: Phase 2 — getrusage syscall, FIONREAD ioctl, libgen.h, misc ulibc X-Git-Url: https://projects.tadryanom.me/sitemap.xml?a=commitdiff_plain;h=9973ac67819a59249977ab4a6cb4b08357614b52;p=AdrOS.git feat: Phase 2 — getrusage syscall, FIONREAD ioctl, libgen.h, misc ulibc Kernel: - Add SYSCALL_GETRUSAGE (137) returning process utime/stime as struct rusage - Add FIONREAD (0x541B) ioctl to TTY (returns canon_buf available bytes) - Add FIONREAD (0x541B) ioctl to pipe (returns pipe buffer count) ulibc: - sys/resource.h: Add RUSAGE_SELF/CHILDREN, struct rusage, getrusage() - resource.c: Add getrusage() syscall wrapper - libgen.h + libgen.c: basename() and dirname() implementations - misc.c: gethostname() (returns 'adros'), ttyname(), pipe2() wrapper - syscall.h: Add SYS_GETRUSAGE (137) Tests: 101/101 smoke, 64/64 host utils, cppcheck clean --- diff --git a/include/syscall.h b/include/syscall.h index 2ddca80..2b998d6 100644 --- a/include/syscall.h +++ b/include/syscall.h @@ -167,6 +167,7 @@ enum { SYSCALL_GETPEERNAME = 134, SYSCALL_GETSOCKNAME = 135, SYSCALL_UNAME = 136, + SYSCALL_GETRUSAGE = 137, }; #endif diff --git a/src/kernel/syscall.c b/src/kernel/syscall.c index 98e6066..64b40bb 100644 --- a/src/kernel/syscall.c +++ b/src/kernel/syscall.c @@ -1644,16 +1644,30 @@ static int pipe_poll(fs_node_t* n, int events) { return revents; } +static int pipe_ioctl(fs_node_t* n, uint32_t cmd, void* user_arg) { + struct pipe_node* pn = (struct pipe_node*)n; + if (!pn || !pn->ps) return -EBADF; + if (cmd == 0x541B /* FIONREAD */) { + if (!user_arg || user_range_ok(user_arg, sizeof(int)) == 0) return -EFAULT; + int avail = (int)pn->ps->count; + if (copy_to_user(user_arg, &avail, sizeof(avail)) < 0) return -EFAULT; + return 0; + } + return -ENOTTY; +} + static const struct file_operations pipe_read_fops = { .read = pipe_read, .close = pipe_close, .poll = pipe_poll, + .ioctl = pipe_ioctl, }; static const struct file_operations pipe_write_fops = { .write = pipe_write, .close = pipe_close, .poll = pipe_poll, + .ioctl = pipe_ioctl, }; static int pipe_node_create(struct pipe_state* ps, int is_read_end, fs_node_t** out_node) { @@ -4866,6 +4880,33 @@ static void socket_syscall_dispatch(struct registers* regs, uint32_t syscall_no) return; } + if (syscall_no == SYSCALL_GETRUSAGE) { + int who = (int)sc_arg0(regs); + void* user_buf = (void*)sc_arg1(regs); + if (!user_buf || user_range_ok(user_buf, 64) == 0) { + sc_ret(regs) = (uint32_t)-EFAULT; return; + } + /* struct rusage: we fill ru_utime and ru_stime (2 x struct timeval = 16 bytes) + * then zero the rest (total 64 bytes to be safe) */ + struct { + uint32_t ru_utime_sec; uint32_t ru_utime_usec; + uint32_t ru_stime_sec; uint32_t ru_stime_usec; + uint32_t padding[12]; /* remaining fields zero */ + } ru; + memset(&ru, 0, sizeof(ru)); + (void)who; /* RUSAGE_SELF=0, RUSAGE_CHILDREN=-1 — we only report self */ + uint32_t hz = 100; /* tick rate */ + ru.ru_utime_sec = current_process->utime / hz; + ru.ru_utime_usec = (current_process->utime % hz) * (1000000 / hz); + ru.ru_stime_sec = current_process->stime / hz; + ru.ru_stime_usec = (current_process->stime % hz) * (1000000 / hz); + if (copy_to_user(user_buf, &ru, sizeof(ru)) < 0) { + sc_ret(regs) = (uint32_t)-EFAULT; return; + } + sc_ret(regs) = 0; + return; + } + if (syscall_no == SYSCALL_UNAME) { /* struct utsname: 5 fields of 65 bytes each = 325 bytes */ void* user_buf = (void*)sc_arg0(regs); diff --git a/src/kernel/tty.c b/src/kernel/tty.c index e9e9fc6..91e281c 100644 --- a/src/kernel/tty.c +++ b/src/kernel/tty.c @@ -235,6 +235,7 @@ enum { TTY_TIOCSPGRP = 0x5410, TTY_TIOCGWINSZ = 0x5413, TTY_TIOCSWINSZ = 0x5414, + TTY_FIONREAD = 0x541B, }; int tty_ioctl(uint32_t cmd, void* user_arg) { @@ -311,6 +312,15 @@ int tty_ioctl(uint32_t cmd, void* user_arg) { return 0; } + if (cmd == TTY_FIONREAD) { + if (user_range_ok(user_arg, sizeof(int)) == 0) return -EFAULT; + uintptr_t flags = spin_lock_irqsave(&tty_lock); + int avail = (int)((canon_head - canon_tail) & (TTY_CANON_BUF - 1)); + spin_unlock_irqrestore(&tty_lock, flags); + if (copy_to_user(user_arg, &avail, sizeof(avail)) < 0) return -EFAULT; + return 0; + } + return -EINVAL; } diff --git a/user/ulibc/include/libgen.h b/user/ulibc/include/libgen.h new file mode 100644 index 0000000..f666f9e --- /dev/null +++ b/user/ulibc/include/libgen.h @@ -0,0 +1,7 @@ +#ifndef ULIBC_LIBGEN_H +#define ULIBC_LIBGEN_H + +char* basename(char* path); +char* dirname(char* path); + +#endif diff --git a/user/ulibc/include/sys/resource.h b/user/ulibc/include/sys/resource.h index 071211b..f4b9793 100644 --- a/user/ulibc/include/sys/resource.h +++ b/user/ulibc/include/sys/resource.h @@ -2,6 +2,7 @@ #define ULIBC_SYS_RESOURCE_H #include +#include #define RLIMIT_CPU 0 #define RLIMIT_FSIZE 1 @@ -23,4 +24,28 @@ struct rlimit { int getrlimit(int resource, struct rlimit *rlim); int setrlimit(int resource, const struct rlimit *rlim); +#define RUSAGE_SELF 0 +#define RUSAGE_CHILDREN (-1) + +struct rusage { + struct timeval ru_utime; + struct timeval ru_stime; + long ru_maxrss; + long ru_ixrss; + long ru_idrss; + long ru_isrss; + long ru_minflt; + long ru_majflt; + long ru_nswap; + long ru_inblock; + long ru_oublock; + long ru_msgsnd; + long ru_msgrcv; + long ru_nsignals; + long ru_nvcsw; + long ru_nivcsw; +}; + +int getrusage(int who, struct rusage *usage); + #endif diff --git a/user/ulibc/include/syscall.h b/user/ulibc/include/syscall.h index e47d199..5c517eb 100644 --- a/user/ulibc/include/syscall.h +++ b/user/ulibc/include/syscall.h @@ -91,6 +91,7 @@ enum { SYS_GETPEERNAME = 134, SYS_GETSOCKNAME = 135, SYS_UNAME = 136, + SYS_GETRUSAGE = 137, }; /* Raw syscall wrappers — up to 5 args via INT 0x80 */ diff --git a/user/ulibc/src/libgen.c b/user/ulibc/src/libgen.c new file mode 100644 index 0000000..0c63a47 --- /dev/null +++ b/user/ulibc/src/libgen.c @@ -0,0 +1,24 @@ +#include "libgen.h" +#include "string.h" + +char* basename(char* path) { + if (!path || !*path) return "."; + size_t len = strlen(path); + /* Remove trailing slashes */ + while (len > 1 && path[len - 1] == '/') path[--len] = '\0'; + char* p = strrchr(path, '/'); + return p ? p + 1 : path; +} + +char* dirname(char* path) { + static char dot[] = "."; + if (!path || !*path) return dot; + size_t len = strlen(path); + /* Remove trailing slashes */ + while (len > 1 && path[len - 1] == '/') path[--len] = '\0'; + char* p = strrchr(path, '/'); + if (!p) return dot; + if (p == path) { path[1] = '\0'; return path; } + *p = '\0'; + return path; +} diff --git a/user/ulibc/src/misc.c b/user/ulibc/src/misc.c new file mode 100644 index 0000000..0f70fe2 --- /dev/null +++ b/user/ulibc/src/misc.c @@ -0,0 +1,26 @@ +#include "unistd.h" +#include "string.h" +#include "syscall.h" +#include "errno.h" + +int gethostname(char* name, size_t len) { + if (!name || len == 0) { errno = EINVAL; return -1; } + const char* hostname = "adros"; + size_t hlen = strlen(hostname); + if (hlen + 1 > len) { errno = ENAMETOOLONG; return -1; } + memcpy(name, hostname, hlen + 1); + return 0; +} + +static char ttyname_buf[32]; + +char* ttyname(int fd) { + if (!isatty(fd)) return (char*)0; + strcpy(ttyname_buf, "/dev/tty"); + return ttyname_buf; +} + +int pipe2(int fds[2], int flags) { + int r = _syscall2(SYS_PIPE2, (int)fds, flags); + return __syscall_ret(r); +} diff --git a/user/ulibc/src/resource.c b/user/ulibc/src/resource.c index 0236b00..1dd6aba 100644 --- a/user/ulibc/src/resource.c +++ b/user/ulibc/src/resource.c @@ -9,3 +9,7 @@ int getrlimit(int resource, struct rlimit *rlim) { int setrlimit(int resource, const struct rlimit *rlim) { return __syscall_ret(_syscall2(SYS_SETRLIMIT, resource, (int)rlim)); } + +int getrusage(int who, struct rusage *usage) { + return __syscall_ret(_syscall2(SYS_GETRUSAGE, who, (int)usage)); +}