gint: outline a Hardware Abstraction Layer (HAL) for use with gint

A standard libc would normally use the kernel's syscall interface to
connect with the lower level, and this interface would usually imitate
POSIX or a similar style. With the statically-linked unikernel design,
the syscalls would be functions, but the interface wouldn't change much.

However, there are some fundamental differences. For instance, in gint
there aren't separate kernel/userspace memory allocators, there's just a
unified allocator in the kernel. This makes malloc() conceptually a
direct syscall, which pushes the kernel/libc boundary at an unusual
location.

Having a clearly-marked HAL makes it easier to identify where the
boundary is. Code from <time.h> currently has an ad-hoc interface which
should be replaced with clock_gettime(2) in the future.

The HAL offers default implementations but these aren't used by gint
yet, because it's more practical to have undefined references than to
end up with the stubs in an executable. These are provided for future
completeness.

This change does not lift the requirement to recursively link gint with
the libc and the libc with gint.
This commit is contained in:
Lephenixnoir 2024-08-06 11:42:54 +02:00
parent e2f458fa3d
commit 8cedf411c4
No known key found for this signature in database
GPG key ID: 1BBA026E13FC0495
14 changed files with 141 additions and 94 deletions

View file

@ -269,13 +269,15 @@ endif()
if(gint IN_LIST TARGET_FOLDERS)
list(APPEND SOURCES
# stdlib
src/stdlib/target/gint/free.c
src/stdlib/target/gint/malloc.c
src/stdlib/target/gint/realloc.c
# time
src/time/target/gint/clock.c
src/time/target/gint/time.c)
# stdlib HAL
src/stdlib/fxlibc_hal_malloc.c
src/stdlib/free.c
src/stdlib/malloc.c
src/stdlib/realloc.c
# time HAL
src/time/fxlibc_hal_time.c
src/time/clock.c
src/time/time.c)
endif()

25
include/fxlibc/hal.h Normal file
View file

@ -0,0 +1,25 @@
#ifndef __FXLIBC_HAL_H__
# define __FXLIBC_HAL_H__
#ifdef __cplusplus
extern "C" {
#endif
#include <time.h>
#include <stddef.h>
extern void *fxlibc_hal_malloc(size_t __size);
extern void fxlibc_hal_free(void *__ptr);
extern void *fxlibc_hal_realloc(void *__ptr, size_t __size);
extern void fxlibc_hal_rawtime(struct tm *__tm);
extern clock_t fxlibc_hal_clock(void);
#ifdef __cplusplus
}
#endif
#endif /*__FXLIBC_HAL_H__*/

7
src/stdlib/free.c Normal file
View file

@ -0,0 +1,7 @@
#include <stdlib.h>
#include <fxlibc/hal.h>
void free(void *ptr)
{
return fxlibc_hal_free(ptr);
}

View file

@ -0,0 +1,30 @@
#include <fxlibc/hal.h>
#include <stdlib.h>
#include <errno.h>
#if FXLIBC_HAL_DEFAULT_MALLOC
__attribute__((weak))
void *fxlibc_hal_malloc(size_t size)
{
(void)size;
errno = ENOMEM;
return NULL;
}
__attribute__((weak))
void fxlibc_hal_free(void *ptr)
{
(void)ptr;
}
__attribute__((weak))
void *fxlibc_hal_realloc(void *ptr, size_t size)
{
(void)ptr;
(void)size;
errno = ENOMEM;
return NULL;
}
#endif /* FXLIBC_HAL_DEFAULT_MALLOC */

11
src/stdlib/malloc.c Normal file
View file

@ -0,0 +1,11 @@
#include <stdlib.h>
#include <errno.h>
#include <fxlibc/hal.h>
void *malloc(size_t size)
{
void *ptr = fxlibc_hal_malloc(size);
if(ptr == NULL)
errno = ENOMEM;
return ptr;
}

11
src/stdlib/realloc.c Normal file
View file

@ -0,0 +1,11 @@
#include <stdlib.h>
#include <errno.h>
#include <fxlibc/hal.h>
void *realloc(void *ptr, size_t size)
{
ptr = fxlibc_hal_realloc(ptr, size);
if(ptr == NULL)
errno = ENOMEM;
return ptr;
}

View file

@ -1,8 +0,0 @@
#include <stdlib.h>
extern void kfree(void *ptr);
void free(void *ptr)
{
return kfree(ptr);
}

View file

@ -1,12 +0,0 @@
#include <stdlib.h>
#include <errno.h>
extern void *kmalloc(size_t size, char const *arena_name);
void *malloc(size_t size)
{
void *ptr = kmalloc(size, NULL);
if(ptr == NULL)
errno = ENOMEM;
return ptr;
}

View file

@ -1,8 +0,0 @@
#include <stdlib.h>
extern void *krealloc(void *ptr, size_t size);
void *realloc(void *ptr, size_t size)
{
return krealloc(ptr, size);
}

15
src/time/clock.c Normal file
View file

@ -0,0 +1,15 @@
#include <time.h>
#include <fxlibc/hal.h>
static clock_t clock_init;
__attribute__((constructor))
static void clock_initialize(void)
{
clock_init = fxlibc_hal_clock();
}
clock_t clock(void)
{
return fxlibc_hal_clock() - clock_init;
}

View file

@ -0,0 +1,18 @@
#include <fxlibc/hal.h>
#include <time.h>
#if FXLIBC_HAL_DEFAULT_TIME
__attribute__((weak))
void fxlibc_hal_rawtime(struct tm *tm)
{
memset(tm, 0, sizeof *tm);
}
__attribute__((weak))
static clock_t fxlibc_hal_clock(void)
{
return 0;
}
#endif /* FXLIBC_HAL_DEFAULT_TIME */

View file

@ -1,22 +0,0 @@
#include <time.h>
#include <inttypes.h>
uint32_t rtc_ticks(void);
static clock_t clock_init;
static clock_t clock_abs(void)
{
return (CLOCKS_PER_SEC * (uint64_t)rtc_ticks()) / 128;
}
__attribute__((constructor))
static void clock_initialize(void)
{
clock_init = clock_abs();
}
clock_t clock(void)
{
return clock_abs() - clock_init;
}

View file

@ -1,37 +0,0 @@
#include <time.h>
typedef struct
{
uint16_t year;
uint8_t week_day;
uint8_t month;
uint8_t month_day;
uint8_t hours;
uint8_t minutes;
uint8_t seconds;
uint8_t ticks;
} rtc_time_t;
void rtc_get_time(rtc_time_t *time);
time_t time(time_t *timeptr)
{
rtc_time_t rtc;
struct tm tm;
time_t calendar;
rtc_get_time(&rtc);
tm.tm_sec = rtc.seconds;
tm.tm_min = rtc.minutes;
tm.tm_hour = rtc.hours;
tm.tm_mday = rtc.month_day;
tm.tm_mon = rtc.month;
tm.tm_year = rtc.year - 1900;
tm.tm_isdst = 0;
calendar = mktime(&tm);
if(timeptr != NULL)
*timeptr = calendar;
return calendar;
}

15
src/time/time.c Normal file
View file

@ -0,0 +1,15 @@
#include <time.h>
#include <fxlibc/hal.h>
time_t time(time_t *timeptr)
{
struct tm tm;
time_t calendar;
fxlibc_hal_rawtime(&tm);
calendar = mktime(&tm);
if(timeptr != NULL)
*timeptr = calendar;
return calendar;
}