From a8a64863c8ad3377fc7dbdf0d6ac17e4417b505c Mon Sep 17 00:00:00 2001 From: apio Date: Sat, 7 Jan 2023 00:21:08 +0100 Subject: [PATCH] kernel, libc: Add clock_gettime() --- apps/CMakeLists.txt | 1 + apps/app.c | 7 +++++++ kernel/CMakeLists.txt | 2 ++ kernel/src/arch/Timer.cpp | 1 + kernel/src/sys/clock_gettime.cpp | 34 ++++++++++++++++++++++++++++++++ libc/CMakeLists.txt | 3 ++- libc/include/bits/clockid.h | 12 +++++++++++ libc/include/bits/timespec.h | 12 +++++++++++ libc/include/sys/types.h | 2 ++ libc/include/time.h | 15 ++++++++++++++ libc/src/stdlib.cpp | 1 + libc/src/time.cpp | 13 ++++++++++++ luna/CMakeLists.txt | 2 +- luna/include/luna/Syscall.h | 2 +- 14 files changed, 104 insertions(+), 3 deletions(-) create mode 100644 kernel/src/sys/clock_gettime.cpp create mode 100644 libc/include/bits/clockid.h create mode 100644 libc/include/bits/timespec.h create mode 100644 libc/src/time.cpp diff --git a/apps/CMakeLists.txt b/apps/CMakeLists.txt index 4c4a143a..8f0cdef2 100644 --- a/apps/CMakeLists.txt +++ b/apps/CMakeLists.txt @@ -1,6 +1,7 @@ function(luna_app SOURCE_FILE APP_NAME) add_executable(${APP_NAME} ${SOURCE_FILE}) add_dependencies(${APP_NAME} libc) + target_include_directories(${APP_NAME} PRIVATE ${LUNA_BASE}/usr/include) install(TARGETS ${APP_NAME} DESTINATION ${LUNA_ROOT}/initrd/bin) endfunction() diff --git a/apps/app.c b/apps/app.c index 9caf3a4d..73a9dbff 100644 --- a/apps/app.c +++ b/apps/app.c @@ -1,5 +1,6 @@ #include #include +#include void bye() { @@ -15,6 +16,12 @@ int main() console_print(buffer); + struct timespec ts; + clock_gettime(CLOCK_REALTIME, &ts); + snprintf(buffer, sizeof(buffer), "Realtime clock: %ld s, %ld ns\n", ts.tv_sec, ts.tv_nsec); + + console_print(buffer); + for (int i = 0; i < atoi("8"); i++) { console_print("."); } console_print("\n"); diff --git a/kernel/CMakeLists.txt b/kernel/CMakeLists.txt index d8498225..edaa76f0 100644 --- a/kernel/CMakeLists.txt +++ b/kernel/CMakeLists.txt @@ -18,6 +18,7 @@ set(SOURCES src/sys/Syscall.cpp src/sys/exit.cpp src/sys/console_print.cpp + src/sys/clock_gettime.cpp src/InitRD.cpp src/ELF.cpp ) @@ -78,6 +79,7 @@ target_link_options(moon PRIVATE -lgcc -Wl,--build-id=none -z max-page-size=0x10 set_target_properties(moon PROPERTIES CXX_STANDARD 20) target_include_directories(moon PRIVATE ${CMAKE_CURRENT_LIST_DIR}/src) +target_include_directories(moon PRIVATE ${LUNA_BASE}/usr/include) configure_file(src/config.h.in ${CMAKE_CURRENT_BINARY_DIR}/gen/config.h @ONLY) diff --git a/kernel/src/arch/Timer.cpp b/kernel/src/arch/Timer.cpp index 6314427b..8df3c058 100644 --- a/kernel/src/arch/Timer.cpp +++ b/kernel/src/arch/Timer.cpp @@ -3,6 +3,7 @@ #include "arch/Serial.h" #include "boot/bootboot.h" +// FIXME: Storing these values as unsigned integers doesn't allow for pre-epoch times. static u64 timer_ticks = 0; static u64 boot_timestamp; diff --git a/kernel/src/sys/clock_gettime.cpp b/kernel/src/sys/clock_gettime.cpp new file mode 100644 index 00000000..d46a388d --- /dev/null +++ b/kernel/src/sys/clock_gettime.cpp @@ -0,0 +1,34 @@ +#include "arch/Timer.h" +#include "memory/MemoryManager.h" +#include "sys/Syscall.h" +#include +#include + +Result sys_clock_gettime(Registers*, SyscallArgs args) +{ + clockid_t id = (clockid_t)args[0]; + struct timespec* ts = (struct timespec*)args[1]; + + switch (id) + { + case CLOCK_MONOTONIC: { + usize ticks = Timer::ticks_ns(); + struct timespec kernel_ts; + kernel_ts.tv_sec = (time_t)(ticks / NS_PER_SECOND); + kernel_ts.tv_nsec = (long)(ticks % NS_PER_SECOND); + if (!MemoryManager::copy_to_user_typed(ts, &kernel_ts)) return err(EFAULT); + break; + } + case CLOCK_REALTIME: { + usize clock = Timer::clock_ns(); + struct timespec kernel_ts; + kernel_ts.tv_sec = (time_t)(clock / NS_PER_SECOND); + kernel_ts.tv_nsec = (long)(clock % NS_PER_SECOND); + if (!MemoryManager::copy_to_user_typed(ts, &kernel_ts)) return err(EFAULT); + break; + } + default: return err(EINVAL); + } + + return 0; +} diff --git a/libc/CMakeLists.txt b/libc/CMakeLists.txt index 11823c69..270ecf41 100644 --- a/libc/CMakeLists.txt +++ b/libc/CMakeLists.txt @@ -9,6 +9,7 @@ set(SOURCES src/string.cpp src/atexit.cpp src/ctype.cpp + src/time.cpp ) if(${ARCH} STREQUAL "x86_64") @@ -30,7 +31,7 @@ target_link_libraries(bare_libc PUBLIC luna) target_include_directories(bare_libc PUBLIC include/) -target_compile_options(bare_libc PRIVATE -Wall -Wextra -Werror -pedantic -nostdlib) +target_compile_options(bare_libc PRIVATE -Wall -Wextra -Werror -pedantic -nostdlib -fno-exceptions -fno-rtti) target_link_options(bare_libc PRIVATE -nostdlib) diff --git a/libc/include/bits/clockid.h b/libc/include/bits/clockid.h new file mode 100644 index 00000000..110886fb --- /dev/null +++ b/libc/include/bits/clockid.h @@ -0,0 +1,12 @@ +#ifndef _BITS_CLOCKID_H +#define _BITS_CLOCKID_H + +typedef int clockid_t; + +enum __clockid +{ + CLOCK_REALTIME, + CLOCK_MONOTONIC +}; + +#endif diff --git a/libc/include/bits/timespec.h b/libc/include/bits/timespec.h new file mode 100644 index 00000000..c171d708 --- /dev/null +++ b/libc/include/bits/timespec.h @@ -0,0 +1,12 @@ +#ifndef _BITS_TIMESPEC_H +#define _BITS_TIMESPEC_H + +#include + +struct timespec +{ + time_t tv_sec; + long tv_nsec; +}; + +#endif diff --git a/libc/include/sys/types.h b/libc/include/sys/types.h index 25b16927..e4768a32 100644 --- a/libc/include/sys/types.h +++ b/libc/include/sys/types.h @@ -6,4 +6,6 @@ typedef int pid_t; +typedef long time_t; + #endif diff --git a/libc/include/time.h b/libc/include/time.h index 4c01e32c..9a951da0 100644 --- a/libc/include/time.h +++ b/libc/include/time.h @@ -1,4 +1,19 @@ #ifndef _TIME_H #define _TIME_H +#include +#include + +#ifdef __cplusplus +extern "C" +{ +#endif + + /* Get the current value of a system clock. */ + int clock_gettime(clockid_t id, struct timespec* ts); + +#ifdef __cplusplus +} +#endif + #endif diff --git a/libc/src/stdlib.cpp b/libc/src/stdlib.cpp index b84dda9c..d92a45bf 100644 --- a/libc/src/stdlib.cpp +++ b/libc/src/stdlib.cpp @@ -101,6 +101,7 @@ extern "C" __builtin_unreachable(); } + // FIXME: This is walking a UTF-8 string twice. Once to decode, and another to count code points. size_t mbstowcs(wchar_t* buf, const char* src, size_t max) { if (max == 0) return 0; diff --git a/libc/src/time.cpp b/libc/src/time.cpp new file mode 100644 index 00000000..aaa33f57 --- /dev/null +++ b/libc/src/time.cpp @@ -0,0 +1,13 @@ +#include +#include +#include +#include + +extern "C" +{ + int clock_gettime(clockid_t id, struct timespec* ts) + { + long rc = syscall(SYS_clock_gettime, id, ts); + __errno_return(rc, int); + } +} diff --git a/luna/CMakeLists.txt b/luna/CMakeLists.txt index 9e301eb1..4fbc5114 100644 --- a/luna/CMakeLists.txt +++ b/luna/CMakeLists.txt @@ -41,7 +41,7 @@ target_compile_options(luna PRIVATE -Wall -Wextra -Werror -Wvla) target_compile_options(luna PRIVATE -Wdisabled-optimization -Wformat=2 -Winit-self) target_compile_options(luna PRIVATE -Wmissing-include-dirs -Wswitch-default -Wcast-qual -Wundef) target_compile_options(luna PRIVATE -Wcast-align -Wwrite-strings -Wlogical-op -Wredundant-decls -Wshadow -Wconversion) -target_compile_options(luna PRIVATE -fno-asynchronous-unwind-tables -fno-omit-frame-pointer -std=c++20) +target_compile_options(luna PRIVATE -fno-asynchronous-unwind-tables -fno-omit-frame-pointer -std=c++20 -fno-rtti -fno-exceptions) target_include_directories(luna PUBLIC include/) target_include_directories(luna PUBLIC ${LUNA_BASE}/usr/include) diff --git a/luna/include/luna/Syscall.h b/luna/include/luna/Syscall.h index 30551cfa..aeb98f95 100644 --- a/luna/include/luna/Syscall.h +++ b/luna/include/luna/Syscall.h @@ -1,6 +1,6 @@ #pragma once -#define enumerate_syscalls(_e) _e(exit) _e(console_print) +#define enumerate_syscalls(_e) _e(exit) _e(console_print) _e(clock_gettime) enum Syscalls {