Compare commits

..

3 Commits

Author SHA1 Message Date
7fb2807d0c
libc: Implement time() using clock_gettime().
All checks were successful
continuous-integration/drone/push Build is passing
The cool POSIX kids use clock_gettime() now because it has NANOSECONDS (and different clocks!),
but ANSI C prefers this function.

We can still implement it based on clock_gettime(), we just have to discard the NANOSECONDS.
2023-01-07 00:27:23 +01:00
a8a64863c8
kernel, libc: Add clock_gettime() 2023-01-07 00:21:08 +01:00
6e9b4491a6
MemoryManager: Add copy_to_user() and copy_to_user_typed() 2023-01-07 00:17:16 +01:00
16 changed files with 152 additions and 3 deletions

View File

@ -1,6 +1,7 @@
function(luna_app SOURCE_FILE APP_NAME) function(luna_app SOURCE_FILE APP_NAME)
add_executable(${APP_NAME} ${SOURCE_FILE}) add_executable(${APP_NAME} ${SOURCE_FILE})
add_dependencies(${APP_NAME} libc) add_dependencies(${APP_NAME} libc)
target_include_directories(${APP_NAME} PRIVATE ${LUNA_BASE}/usr/include)
install(TARGETS ${APP_NAME} DESTINATION ${LUNA_ROOT}/initrd/bin) install(TARGETS ${APP_NAME} DESTINATION ${LUNA_ROOT}/initrd/bin)
endfunction() endfunction()

View File

@ -1,5 +1,6 @@
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <time.h>
void bye() void bye()
{ {
@ -15,6 +16,11 @@ int main()
console_print(buffer); console_print(buffer);
time_t now = time(NULL);
snprintf(buffer, sizeof(buffer), "Realtime clock: %ld s\n", now);
console_print(buffer);
for (int i = 0; i < atoi("8"); i++) { console_print("."); } for (int i = 0; i < atoi("8"); i++) { console_print("."); }
console_print("\n"); console_print("\n");

View File

@ -18,6 +18,7 @@ set(SOURCES
src/sys/Syscall.cpp src/sys/Syscall.cpp
src/sys/exit.cpp src/sys/exit.cpp
src/sys/console_print.cpp src/sys/console_print.cpp
src/sys/clock_gettime.cpp
src/InitRD.cpp src/InitRD.cpp
src/ELF.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) set_target_properties(moon PROPERTIES CXX_STANDARD 20)
target_include_directories(moon PRIVATE ${CMAKE_CURRENT_LIST_DIR}/src) 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) configure_file(src/config.h.in ${CMAKE_CURRENT_BINARY_DIR}/gen/config.h @ONLY)

View File

@ -3,6 +3,7 @@
#include "arch/Serial.h" #include "arch/Serial.h"
#include "boot/bootboot.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 timer_ticks = 0;
static u64 boot_timestamp; static u64 boot_timestamp;

View File

@ -364,6 +364,35 @@ namespace MemoryManager
return true; return true;
} }
bool copy_to_user(void* user, const void* kernel, usize size)
{
uintptr_t user_ptr = (uintptr_t)user;
uintptr_t user_page = align_down<ARCH_PAGE_SIZE>(user_ptr);
const char* kernel_ptr = (const char*)kernel;
// Userspace pointer not aligned on page boundary
if (user_ptr != user_page)
{
// FIXME: Validate that this page is writable by the user, not just the kernel.
if (!validate_writable_page(user_page)) return false;
}
while (size--)
{
// Crossed a page boundary, gotta check the page tables again before touching any memory!!
if (user_ptr % ARCH_PAGE_SIZE)
{
if (!validate_writable_page(user_ptr)) return false;
}
*(char*)user_ptr = *kernel_ptr++;
user_ptr++;
}
return true;
}
usize free() usize free()
{ {
return free_mem; return free_mem;

View File

@ -22,6 +22,13 @@ namespace MemoryManager
bool validate_userspace_string(u64 address); bool validate_userspace_string(u64 address);
bool copy_to_user(void* user, const void* kernel, usize size);
template <typename T> bool copy_to_user_typed(T* user, const T* kernel)
{
return copy_to_user(user, kernel, sizeof(T));
}
Result<void> map_frames_at(u64 virt, u64 phys, usize count, int flags); Result<void> map_frames_at(u64 virt, u64 phys, usize count, int flags);
Result<u64> alloc_at(u64 virt, usize count, int flags); Result<u64> alloc_at(u64 virt, usize count, int flags);

View File

@ -0,0 +1,34 @@
#include "arch/Timer.h"
#include "memory/MemoryManager.h"
#include "sys/Syscall.h"
#include <bits/clockid.h>
#include <bits/timespec.h>
Result<u64> 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;
}

View File

@ -9,6 +9,7 @@ set(SOURCES
src/string.cpp src/string.cpp
src/atexit.cpp src/atexit.cpp
src/ctype.cpp src/ctype.cpp
src/time.cpp
) )
if(${ARCH} STREQUAL "x86_64") if(${ARCH} STREQUAL "x86_64")
@ -30,7 +31,7 @@ target_link_libraries(bare_libc PUBLIC luna)
target_include_directories(bare_libc PUBLIC include/) 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) target_link_options(bare_libc PRIVATE -nostdlib)

View File

@ -0,0 +1,12 @@
#ifndef _BITS_CLOCKID_H
#define _BITS_CLOCKID_H
typedef int clockid_t;
enum __clockid
{
CLOCK_REALTIME,
CLOCK_MONOTONIC
};
#endif

View File

@ -0,0 +1,12 @@
#ifndef _BITS_TIMESPEC_H
#define _BITS_TIMESPEC_H
#include <sys/types.h>
struct timespec
{
time_t tv_sec;
long tv_nsec;
};
#endif

View File

@ -6,4 +6,6 @@
typedef int pid_t; typedef int pid_t;
typedef long time_t;
#endif #endif

View File

@ -1,4 +1,22 @@
#ifndef _TIME_H #ifndef _TIME_H
#define _TIME_H #define _TIME_H
#include <bits/clockid.h>
#include <bits/timespec.h>
#ifdef __cplusplus
extern "C"
{
#endif
/* Get the current value of a system clock. */
int clock_gettime(clockid_t id, struct timespec* ts);
/* Get the current wall clock time. */
time_t time(time_t* tp);
#ifdef __cplusplus
}
#endif
#endif #endif

View File

@ -101,6 +101,7 @@ extern "C"
__builtin_unreachable(); __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) size_t mbstowcs(wchar_t* buf, const char* src, size_t max)
{ {
if (max == 0) return 0; if (max == 0) return 0;

23
libc/src/time.cpp Normal file
View File

@ -0,0 +1,23 @@
#include <bits/errno-return.h>
#include <sys/syscall.h>
#include <time.h>
#include <unistd.h>
extern "C"
{
int clock_gettime(clockid_t id, struct timespec* ts)
{
long rc = syscall(SYS_clock_gettime, id, ts);
__errno_return(rc, int);
}
time_t time(time_t* tp)
{
struct timespec ts;
if (clock_gettime(CLOCK_REALTIME, &ts) < 0) return (time_t)-1;
if (tp) *tp = ts.tv_sec;
return ts.tv_sec;
}
}

View File

@ -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 -Wdisabled-optimization -Wformat=2 -Winit-self)
target_compile_options(luna PRIVATE -Wmissing-include-dirs -Wswitch-default -Wcast-qual -Wundef) 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 -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 include/)
target_include_directories(luna PUBLIC ${LUNA_BASE}/usr/include) target_include_directories(luna PUBLIC ${LUNA_BASE}/usr/include)

View File

@ -1,6 +1,6 @@
#pragma once #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 enum Syscalls
{ {