diff options
| author | Kacper <kacper@mail.openlinux.dev> | 2025-12-22 23:27:56 +0100 |
|---|---|---|
| committer | Kacper <kacper@mail.openlinux.dev> | 2025-12-22 23:30:32 +0100 |
| commit | 0f30d227497418c6d3bef7d52244407e30454504 (patch) | |
| tree | 0e1ac19623d3268380cf74328cdf643648a2f43c /lib/libc/internal/init | |
| parent | 90dad97fc07f049383903a166631e2c257f9b8c1 (diff) | |
Added c11 threads, fixed some locks and add *_unlocked functions
Diffstat (limited to 'lib/libc/internal/init')
| -rw-r--r-- | lib/libc/internal/init/Kbuild | 1 | ||||
| -rw-r--r-- | lib/libc/internal/init/init.c | 35 | ||||
| -rw-r--r-- | lib/libc/internal/init/io.c | 42 | ||||
| -rw-r--r-- | lib/libc/internal/init/tls.c | 43 | ||||
| -rw-r--r-- | lib/libc/internal/init/vdso.c | 13 |
5 files changed, 112 insertions, 22 deletions
diff --git a/lib/libc/internal/init/Kbuild b/lib/libc/internal/init/Kbuild index 361f220a..3c1bab0b 100644 --- a/lib/libc/internal/init/Kbuild +++ b/lib/libc/internal/init/Kbuild @@ -1,3 +1,4 @@ obj-y += init.o +obj-y += io.o obj-y += tls.o obj-y += vdso.o diff --git a/lib/libc/internal/init/init.c b/lib/libc/internal/init/init.c index b2dd8487..62678dce 100644 --- a/lib/libc/internal/init/init.c +++ b/lib/libc/internal/init/init.c @@ -1,11 +1,15 @@ +#include <alloca.h> #include <libc.h> #include <stddef.h> #include <stdint.h> #include <stdlib.h> #include <sys/cdefs.h> -extern void __init_vdso(void); -extern void __init_tls(void); +#define BUFSIZ 4096 + +extern void __libc_init_vdso(void) __attribute__((weak)); +extern void __libc_init_tls(void) __attribute__((weak)); +extern void __libc_init_io(void) __attribute__((weak)); extern int main(int, char **, char **); @@ -13,10 +17,9 @@ struct libc __libc = { 0 }; char **environ; char *__progname; -__used void __init(uintptr_t *rsp) +__used void __libc_init(uintptr_t *rsp) { char **argv; - size_t *auxv; int argc; argc = (int)(*rsp); @@ -30,13 +33,27 @@ __used void __init(uintptr_t *rsp) while (*rsp) rsp++; - auxv = (size_t *)++rsp; + __libc.auxv = (size_t *)++rsp; + + if (__libc_init_io) { + __libc_init_io(); + + __libc.stdout.buf = alloca(BUFSIZ); + __libc.stdout.buf_size = BUFSIZ; + __libc.stdout.buf_len = 0; + __libc.stdout.buf_pos = 0; + + __libc.stdin.buf = alloca(BUFSIZ); + __libc.stdin.buf_size = BUFSIZ; + __libc.stdin.buf_len = 0; + __libc.stdin.buf_pos = 0; + } - for (size_t i = 0; auxv[i]; i += 2) - __libc.auxv[auxv[i]] = auxv[i + 1]; + if (__libc_init_tls) + __libc_init_tls(); - __init_tls(); - __init_vdso(); + if (__libc_init_vdso) + __libc_init_vdso(); exit(main(argc, argv, environ)); } diff --git a/lib/libc/internal/init/io.c b/lib/libc/internal/init/io.c new file mode 100644 index 00000000..4790af89 --- /dev/null +++ b/lib/libc/internal/init/io.c @@ -0,0 +1,42 @@ +#include <atomic.h> +#include <fcntl.h> +#include <libc.h> +#include <stdio.h> +#include <unistd.h> + +struct __FILE *const stdout = (struct __FILE *)&__libc.stdout; +struct __FILE *const stdin = (struct __FILE *)&__libc.stdin; +struct __FILE *const stderr = (struct __FILE *)&__libc.stderr; + +void __libc_init_io(void) +{ + /* stdout */ + memset(&__libc.stdout, 0, sizeof(struct __FILE)); + __libc.stdout.fd = STDOUT_FILENO; + __libc.stdout.flags = O_WRONLY; + __libc.stdout.type = _IOLBF; + __libc.stdout.buf = NULL; + __libc.stdout.buf_size = 0; + __libc.stdout.buf_len = 0; + __libc.stdout.buf_pos = 0; + + /* stdin */ + memset(&__libc.stdin, 0, sizeof(struct __FILE)); + __libc.stdin.fd = STDIN_FILENO; + __libc.stdin.flags = O_RDONLY; + __libc.stdin.type = _IONBF; + __libc.stdin.buf = NULL; + __libc.stdin.buf_size = 0; + __libc.stdin.buf_len = 0; + __libc.stdin.buf_pos = 0; + + /* stderr */ + memset(&__libc.stderr, 0, sizeof(struct __FILE)); + __libc.stderr.fd = STDERR_FILENO; + __libc.stderr.flags = O_WRONLY; + __libc.stderr.type = _IONBF; + __libc.stderr.buf = NULL; + __libc.stderr.buf_size = 0; + __libc.stderr.buf_len = 0; + __libc.stderr.buf_pos = 0; +} diff --git a/lib/libc/internal/init/tls.c b/lib/libc/internal/init/tls.c index f6ccde35..302edd9d 100644 --- a/lib/libc/internal/init/tls.c +++ b/lib/libc/internal/init/tls.c @@ -6,14 +6,31 @@ #include <sys/mman.h> #include <syscall.h> -#define ALIGN_DOWN(x, a) ((x) & ~((a) - 1)) -#define ALIGN_UP(x, a) (((x) + (a) - 1) & ~((a) - 1)) +#include <libc/tcb.h> +#include <stdio.h> + +// TODO: remove this thing static struct tls __libc_tls = { 0 }; + static struct __thread_self __libc_thread; volatile int __libc_tid; -void __init_tls(void) +void __libc_tls_copy(void *dest) +{ + if (__libc_tls.size == 0) + return; + + if (__libc_tls.length > 0) { + memcpy(dest, __libc_tls.data, __libc_tls.length); + + memset((unsigned char *)dest + __libc_tls.length, 0, __libc_tls.size - __libc_tls.length); + } else { + memset(dest, 0, __libc_tls.size); + } +} + +void __libc_init_tls(void) { int r; void *mem; @@ -40,6 +57,7 @@ void __init_tls(void) __libc_tls.length = tls_phdr->p_filesz; __libc_tls.size = tls_phdr->p_memsz; __libc_tls.align = tls_phdr->p_align; + __libc.tls.align = __libc_tls.align; } if (__libc_tls.size != 0) { @@ -56,21 +74,22 @@ void __init_tls(void) thrd = (struct __thread_self *)mem; tls_mem = (unsigned char *)mem + sizeof(struct __thread_self); - if (tls_phdr->p_filesz > 0) { - memcpy(tls_mem, (void *)tls_phdr->p_vaddr, tls_phdr->p_filesz); - memset(tls_mem + tls_phdr->p_filesz, 0, tls_phdr->p_memsz - tls_phdr->p_filesz); - } else { - memset(tls_mem, 0, tls_phdr->p_memsz); - } + __libc_tls_copy(tls_mem); - r = syscall(arch_prctl, ARCH_SET_FS, mem + sizeof(struct __thread_self)); - panic_if(r < 0, "arch_prctl(SET_FS) failed"); + __libc.tls.base = tls_mem; + __libc.tls.size = __libc_tls.size; } else { - __libc.tls.base = NULL; thrd = &__libc_thread; + __libc.tls.base = &__libc_thread; + __libc.tls.size = 0; } r = syscall(set_tid_address, &__libc_tid); panic_if(r < 0, "set_tid_address failed"); + + thrd->self = thrd; thrd->tid = r; + thrd->dtv = NULL; + + __libc_tcb_set((uint64_t)thrd); } diff --git a/lib/libc/internal/init/vdso.c b/lib/libc/internal/init/vdso.c index de8d0e2f..73bfb46b 100644 --- a/lib/libc/internal/init/vdso.c +++ b/lib/libc/internal/init/vdso.c @@ -3,7 +3,18 @@ #include <string.h> #include <sys/auxv.h> -void __init_vdso(void) +int (*__vdso_clock_gettime)(int, struct timespec *) = 0; +int (*__vdso_getcpu)(unsigned *, unsigned *, void *) = 0; +int (*__vdso_time)(long *) = 0; + +struct __vdso_sym __vdso_symtab[] = { + { "__vdso_clock_gettime", (void *)&__vdso_clock_gettime }, + { "__vdso_getcpu", (void *)&__vdso_getcpu }, + { "__vdso_time", (void *)&__vdso_time }, + { 0, 0 }, +}; + +void __libc_init_vdso(void) { Elf64_Ehdr *ehdr = (Elf64_Ehdr *)getauxval(AT_SYSINFO_EHDR); |
