From d241975ce104998ce537f67d28d6ee14a6925dd3 Mon Sep 17 00:00:00 2001 From: Bananymous Date: Tue, 30 Jun 2026 20:11:26 +0300 Subject: [PATCH] Kernel: Remove SYS_SLEEP and cleanup SYS_NANOSLEEP `sleep` is now implemented in terms of `nanosleep`. `nanosleep` is now more precise and handles overflow when calculating wakeup time. I don't think anything was depending on this, but I could see a program sleeping for max time to block until signal. --- kernel/arch/i686/Signal.S | 2 +- kernel/arch/x86_64/Signal.S | 2 +- kernel/include/kernel/Process.h | 1 - kernel/kernel/Process.cpp | 63 +++++++++---------- kernel/kernel/Thread.cpp | 2 +- .../libraries/LibC/include/sys/syscall.h | 1 - userspace/libraries/LibC/unistd.cpp | 22 ++++--- 7 files changed, 45 insertions(+), 48 deletions(-) diff --git a/kernel/arch/i686/Signal.S b/kernel/arch/i686/Signal.S index 47b08305..9552c355 100644 --- a/kernel/arch/i686/Signal.S +++ b/kernel/arch/i686/Signal.S @@ -59,7 +59,7 @@ signal_trampoline: addl $24, %esp // restore sigmask - movl $79, %eax // SYS_SIGPROCMASK + movl $78, %eax // SYS_SIGPROCMASK movl $3, %ebx // SIG_SETMASK leal 72(%esp), %ecx // set xorl %edx, %edx // oset diff --git a/kernel/arch/x86_64/Signal.S b/kernel/arch/x86_64/Signal.S index 27ca40de..07bd5e5e 100644 --- a/kernel/arch/x86_64/Signal.S +++ b/kernel/arch/x86_64/Signal.S @@ -61,7 +61,7 @@ signal_trampoline: addq $40, %rsp // restore sigmask - movq $79, %rdi // SYS_SIGPROCMASK + movq $78, %rdi // SYS_SIGPROCMASK movq $3, %rsi // SIG_SETMASK leaq 192(%rsp), %rdx // set xorq %r10, %r10 // oset diff --git a/kernel/include/kernel/Process.h b/kernel/include/kernel/Process.h index 531504b8..085a4c4b 100644 --- a/kernel/include/kernel/Process.h +++ b/kernel/include/kernel/Process.h @@ -68,7 +68,6 @@ namespace Kernel BAN::ErrorOr sys_exec(const char* path, const char* const* argv, const char* const* envp); BAN::ErrorOr sys_wait(pid_t pid, int* stat_loc, int options); - BAN::ErrorOr sys_sleep(int seconds); BAN::ErrorOr sys_nanosleep(const timespec* rqtp, timespec* rmtp); BAN::ErrorOr sys_setitimer(int which, const itimerval* value, itimerval* ovalue); diff --git a/kernel/kernel/Process.cpp b/kernel/kernel/Process.cpp index 5ee37c73..593e6b2a 100644 --- a/kernel/kernel/Process.cpp +++ b/kernel/kernel/Process.cpp @@ -1036,52 +1036,45 @@ namespace Kernel return child_pid; } - BAN::ErrorOr Process::sys_sleep(int seconds) - { - if (seconds == 0) - return 0; - - const uint64_t wake_time_ms = SystemTimer::get().ms_since_boot() + (seconds * 1000); - - while (!Thread::current().is_interrupted_by_signal()) - { - const uint64_t current_ms = SystemTimer::get().ms_since_boot(); - if (current_ms >= wake_time_ms) - break; - SystemTimer::get().sleep_until_ms(wake_time_ms); - } - - const uint64_t current_ms = SystemTimer::get().ms_since_boot(); - if (current_ms < wake_time_ms) - return BAN::Math::div_round_up(wake_time_ms - current_ms, 1000); - return 0; - } - BAN::ErrorOr Process::sys_nanosleep(const timespec* user_rqtp, timespec* user_rmtp) { + // take current timestamp ASAP + uint64_t current_ns = SystemTimer::get().ns_since_boot(); + timespec rqtp; TRY(read_from_user(user_rqtp, &rqtp, sizeof(timespec))); - if (rqtp.tv_nsec < 0 || rqtp.tv_nsec >= 1'000'000'000) + if (rqtp.tv_sec < 0 || rqtp.tv_nsec < 0 || rqtp.tv_nsec >= 1'000'000'000) return BAN::Error::from_errno(EINVAL); - const uint64_t sleep_ns = (rqtp.tv_sec * 1'000'000'000) + rqtp.tv_nsec; - if (sleep_ns == 0) - return 0; + const uint64_t waketime_ns = [&rqtp, current_ns]() -> uint64_t { + if (BAN::Math::will_multiplication_overflow(rqtp.tv_sec, 1'000'000'000)) + return BAN::numeric_limits::max(); + if (BAN::Math::will_addition_overflow(rqtp.tv_sec * 1'000'000'000, rqtp.tv_nsec)) + return BAN::numeric_limits::max(); + if (BAN::Math::will_addition_overflow(rqtp.tv_sec * 1'000'000'000 + rqtp.tv_nsec, current_ns)) + return BAN::numeric_limits::max(); + return rqtp.tv_sec * 1'000'000'000 + rqtp.tv_nsec + current_ns; + }(); - const uint64_t wake_time_ns = SystemTimer::get().ns_since_boot() + sleep_ns; - SystemTimer::get().sleep_until_ns(wake_time_ns); - - const uint64_t current_ns = SystemTimer::get().ns_since_boot(); - if (current_ns < wake_time_ns) + // NOTE: we shouldn't get woken up unless the thread is interrupted but there is no harm in looping + while (current_ns < waketime_ns && !Thread::current().is_interrupted_by_signal()) + { + SystemTimer::get().sleep_until_ns(waketime_ns); + current_ns = SystemTimer::get().ns_since_boot(); + } + + if (current_ns < waketime_ns) { - const uint64_t remaining_ns = wake_time_ns - current_ns; - const timespec remaining_ts = { - .tv_sec = static_cast(remaining_ns / 1'000'000'000), - .tv_nsec = static_cast(remaining_ns % 1'000'000'000), - }; if (user_rmtp != nullptr) + { + const uint64_t remaining_ns = waketime_ns - current_ns; + const timespec remaining_ts = { + .tv_sec = static_cast(remaining_ns / 1'000'000'000), + .tv_nsec = static_cast(remaining_ns % 1'000'000'000), + }; TRY(write_to_user(user_rmtp, &remaining_ts, sizeof(timespec))); + } return BAN::Error::from_errno(EINTR); } diff --git a/kernel/kernel/Thread.cpp b/kernel/kernel/Thread.cpp index abbfc563..c6b0c9be 100644 --- a/kernel/kernel/Thread.cpp +++ b/kernel/kernel/Thread.cpp @@ -15,7 +15,7 @@ namespace Kernel { - static_assert(SYS_SIGPROCMASK == 79, "this is hard coded in arch/*/Signal.S"); + static_assert(SYS_SIGPROCMASK == 78, "this is hard coded in arch/*/Signal.S"); static_assert(SIG_SETMASK == 3, "this is hard coded in arch/*/Signal.S"); #if ARCH(x86_64) diff --git a/userspace/libraries/LibC/include/sys/syscall.h b/userspace/libraries/LibC/include/sys/syscall.h index b759e896..307e9c4f 100644 --- a/userspace/libraries/LibC/include/sys/syscall.h +++ b/userspace/libraries/LibC/include/sys/syscall.h @@ -16,7 +16,6 @@ __BEGIN_DECLS O(SYS_RENAMEAT, renameat) \ O(SYS_FORK, fork) \ O(SYS_EXEC, exec) \ - O(SYS_SLEEP, sleep) \ O(SYS_WAIT, wait) \ O(SYS_READ_DIR, readdir) \ O(SYS_SET_UID, setuid) \ diff --git a/userspace/libraries/LibC/unistd.cpp b/userspace/libraries/LibC/unistd.cpp index cd0a804c..8eaa0dcd 100644 --- a/userspace/libraries/LibC/unistd.cpp +++ b/userspace/libraries/LibC/unistd.cpp @@ -622,18 +622,24 @@ int pipe(int fildes[2]) unsigned int sleep(unsigned int seconds) { - pthread_testcancel(); - unsigned int ret = syscall(SYS_SLEEP, seconds); - if (ret > 0) - errno = EINTR; - return ret; + const timespec rq_ts { + .tv_sec = seconds, + .tv_nsec = 0, + }; + timespec rm_ts; + if (nanosleep(&rq_ts, &rm_ts) == 0) + return 0; + if (errno != EINTR) + return seconds; + return rm_ts.tv_sec + !!rm_ts.tv_nsec; } int usleep(useconds_t usec) { - timespec ts; - ts.tv_sec = usec / 1'000'000; - ts.tv_nsec = (usec % 1'000'000) * 1000; + const timespec ts { + .tv_sec = static_cast(usec / 1'000'000), + .tv_nsec = static_cast((usec % 1'000'000) * 1000), + }; return nanosleep(&ts, nullptr); }