Kernel/LibC: Rework userspace syscall interface
Kernel syscall API no longer zeros all unused argument registers and libc now uses inlined syscall macro internally. This significantly cleans up generated code for basic syscall wrapper functions.
This commit is contained in:
@@ -74,7 +74,7 @@ set(LIBC_SOURCES
|
||||
)
|
||||
|
||||
add_library(objlibc OBJECT ${LIBC_SOURCES})
|
||||
target_compile_definitions(objlibc PRIVATE __arch=${BANAN_ARCH})
|
||||
target_compile_definitions(objlibc PRIVATE __arch=${BANAN_ARCH} __is_libc)
|
||||
|
||||
target_compile_options(objlibc PRIVATE -O2 -g -Wstack-usage=512 -fno-exceptions -fno-rtti -fpic)
|
||||
target_compile_options(objlibc PUBLIC -Wall -Wextra -Werror -Wno-error=stack-usage=)
|
||||
|
||||
@@ -608,6 +608,22 @@ char* getpass(const char* prompt);
|
||||
|
||||
long syscall(long syscall, ...);
|
||||
|
||||
#ifdef __is_libc
|
||||
#include <kernel/API/Syscall.h>
|
||||
#include <errno.h>
|
||||
#define _syscall(...) ({ \
|
||||
long _ret = -ERESTART; \
|
||||
while (_ret == -ERESTART) \
|
||||
_ret = _kas_syscall(__VA_ARGS__); \
|
||||
if (_ret < 0) { \
|
||||
errno = -_ret; \
|
||||
_ret = -1; \
|
||||
} \
|
||||
_ret; \
|
||||
})
|
||||
#define syscall _syscall
|
||||
#endif
|
||||
|
||||
extern char** environ;
|
||||
|
||||
__END_DECLS
|
||||
|
||||
@@ -254,32 +254,21 @@ void _exit(int status)
|
||||
ASSERT_NOT_REACHED();
|
||||
}
|
||||
|
||||
#undef syscall
|
||||
long syscall(long syscall, ...)
|
||||
{
|
||||
va_list args;
|
||||
va_start(args, syscall);
|
||||
|
||||
uintptr_t arg1 = va_arg(args, uintptr_t);
|
||||
uintptr_t arg2 = va_arg(args, uintptr_t);
|
||||
uintptr_t arg3 = va_arg(args, uintptr_t);
|
||||
uintptr_t arg4 = va_arg(args, uintptr_t);
|
||||
uintptr_t arg5 = va_arg(args, uintptr_t);
|
||||
|
||||
va_end(args);
|
||||
|
||||
long ret;
|
||||
do
|
||||
ret = Kernel::syscall(syscall, arg1, arg2, arg3, arg4, arg5);
|
||||
while (ret == -ERESTART);
|
||||
|
||||
if (ret < 0)
|
||||
{
|
||||
errno = -ret;
|
||||
return -1;
|
||||
}
|
||||
|
||||
return ret;
|
||||
return _syscall(syscall, arg1, arg2, arg3, arg4, arg5);
|
||||
}
|
||||
#define syscall _syscall
|
||||
|
||||
int close(int fd)
|
||||
{
|
||||
|
||||
@@ -223,14 +223,14 @@ constexpr uintptr_t SYM_NOT_FOUND = -1;
|
||||
|
||||
static void lock_global_lock()
|
||||
{
|
||||
const pthread_t tid = syscall<>(SYS_PTHREAD_SELF);
|
||||
const pthread_t tid = syscall(SYS_PTHREAD_SELF);
|
||||
|
||||
pthread_t expected = 0;
|
||||
while (!s_global_locker.compare_exchange(expected, tid))
|
||||
{
|
||||
if (expected == tid)
|
||||
break;
|
||||
syscall<>(SYS_YIELD);
|
||||
syscall(SYS_YIELD);
|
||||
expected = 0;
|
||||
}
|
||||
|
||||
@@ -1393,7 +1393,7 @@ static void initialize_tls(MasterTLS master_tls)
|
||||
.master_tls_module_count = master_tls.module_count,
|
||||
.dynamic_tls = s_dynamic_tls,
|
||||
.cleanup_stack = nullptr,
|
||||
.id = static_cast<pthread_t>(syscall<>(SYS_PTHREAD_SELF)),
|
||||
.id = static_cast<pthread_t>(syscall(SYS_PTHREAD_SELF)),
|
||||
.errno_ = 0,
|
||||
.cancel_type = PTHREAD_CANCEL_DEFERRED,
|
||||
.cancel_state = PTHREAD_CANCEL_ENABLE,
|
||||
@@ -1565,7 +1565,7 @@ static void load_dynamic_tls(LoadedElf& elf)
|
||||
int expected = 0;
|
||||
while (!BAN::atomic_compare_exchange(s_dynamic_tls->lock, expected, 1))
|
||||
{
|
||||
syscall<>(SYS_YIELD);
|
||||
syscall(SYS_YIELD);
|
||||
expected = 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys/syscall.h>
|
||||
#include <unistd.h>
|
||||
|
||||
void print(int fd, const char* buffer)
|
||||
|
||||
@@ -1,10 +1,18 @@
|
||||
#pragma once
|
||||
|
||||
#include <BAN/Traits.h>
|
||||
|
||||
#include <unistd.h> // make sure syscall function is declared before defining it
|
||||
|
||||
#include <errno.h>
|
||||
#include <kernel/API/Syscall.h>
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#define syscall(...) ({ \
|
||||
long _ret = -ERESTART; \
|
||||
while (_ret == -ERESTART) \
|
||||
_ret = _kas_syscall(__VA_ARGS__); \
|
||||
_ret; \
|
||||
})
|
||||
|
||||
template<typename T>
|
||||
inline constexpr T min(T a, T b)
|
||||
@@ -18,12 +26,6 @@ inline constexpr T max(T a, T b)
|
||||
return a > b ? a : b;
|
||||
}
|
||||
|
||||
template<typename... Ts> requires (sizeof...(Ts) <= 5) && ((BAN::is_integral_v<Ts> || BAN::is_pointer_v<Ts>) && ...)
|
||||
inline auto syscall(long syscall, Ts... args)
|
||||
{
|
||||
return Kernel::syscall(syscall, (uintptr_t)args...);
|
||||
}
|
||||
|
||||
void print(int fd, const char* buffer);
|
||||
|
||||
[[noreturn]] void print_error_and_exit(const char* message, int error);
|
||||
|
||||
Reference in New Issue
Block a user