Skip to content

Commit

Permalink
Backport of managarm#311
Browse files Browse the repository at this point in the history
  • Loading branch information
mintsuki committed Feb 20, 2022
1 parent 096fe31 commit 3f3d9e2
Show file tree
Hide file tree
Showing 21 changed files with 503 additions and 132 deletions.
1 change: 1 addition & 0 deletions abis/dripos/errno.h
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,7 @@
#define EFTYPE 79 /* Inappropriate file type or format */
#define EOVERFLOW 80
#define EILSEQ 81
#define ENOTSUP 82

#define EBADMSG 82
#define ECANCELED 83
Expand Down
8 changes: 4 additions & 4 deletions options/ansi/generic/stdio-stubs.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -499,10 +499,10 @@ static int do_scanf(H &handler, const char *fmt, __gnuc_va_list args) {
res = res * 16 + (c - '0');
} else if (c >= 'a' && c <= 'f') {
handler.consume();
res = res * 16 + (c - 'a');
res = res * 16 + (c - 'a' + 10);
} else if (c >= 'A' && c <= 'F') {
handler.consume();
res = res * 16 + (c - 'A');
res = res * 16 + (c - 'A' + 10);
} else {
break;
}
Expand Down Expand Up @@ -551,10 +551,10 @@ static int do_scanf(H &handler, const char *fmt, __gnuc_va_list args) {
res = res * 16 + (c - '0');
} else if (c >= 'a' && c <= 'f') {
handler.consume();
res = res * 16 + (c - 'a');
res = res * 16 + (c - 'a' + 10);
} else if (c >= 'A' && c <= 'F') {
handler.consume();
res = res * 16 + (c - 'A');
res = res * 16 + (c - 'A' + 10);
} else {
break;
}
Expand Down
1 change: 1 addition & 0 deletions options/ansi/include/inttypes.h
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,7 @@
#define SCNx32 "x"
#define SCNx64 "lx"
#define SCNxMAX "lx"
#define SCNxPTR "lx"

#define SCNd64 "ld"

Expand Down
3 changes: 3 additions & 0 deletions options/internal/include/mlibc/tcb.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -107,5 +107,8 @@ struct Tcb {
CleanupHandler *cleanupBegin;
CleanupHandler *cleanupEnd;
int isJoinable;
size_t stackSize;
void *stackAddr;
size_t guardSize;
};

2 changes: 2 additions & 0 deletions options/internal/include/mlibc/thread.hpp
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
#pragma once

#include <mlibc/tcb.hpp>
#include <stdint.h>

namespace mlibc {

Tcb *get_current_tcb();
uintptr_t get_sp();

} // namespace mlibc
6 changes: 6 additions & 0 deletions options/internal/x86_64/thread.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,4 +10,10 @@ Tcb *get_current_tcb() {
return reinterpret_cast<Tcb *>(ptr);
}

uintptr_t get_sp() {
uintptr_t rsp;
asm ("mov %%rsp, %0" : "=r"(rsp));
return rsp;
}

} // namespace mlibc
220 changes: 160 additions & 60 deletions options/posix/generic/pthread-stubs.cpp
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@

#include <stddef.h>
#include <stdint.h>
#include <stdio.h>
#include <string.h>
#include <pthread.h>
#include <unistd.h>
#include <errno.h>
#include <inttypes.h>

#include <bits/ensure.h>
#include <frg/allocation.hpp>
Expand Down Expand Up @@ -63,97 +65,210 @@ static constexpr unsigned int mutex_excl_bit = static_cast<uint32_t>(1) << 30;
static constexpr unsigned int rc_count_mask = (static_cast<uint32_t>(1) << 31) - 1;
static constexpr unsigned int rc_waiters_bit = static_cast<uint32_t>(1) << 31;

static constexpr size_t default_stacksize = 0x200000;
static constexpr size_t default_guardsize = 4096;

// ----------------------------------------------------------------------------
// pthread_attr and pthread functions.
// ----------------------------------------------------------------------------

// pthread_attr functions.
int pthread_attr_init(pthread_attr_t *) {
int pthread_attr_init(pthread_attr_t *attr) {
*attr = pthread_attr_t{};
attr->__mlibc_stacksize = default_stacksize;
attr->__mlibc_guardsize = default_guardsize;
attr->__mlibc_detachstate = PTHREAD_CREATE_JOINABLE;
return 0;
}

int pthread_attr_destroy(pthread_attr_t *) {
return 0;
}

int pthread_attr_getdetachstate(const pthread_attr_t *, int *) {
__ensure(!"Not implemented");
__builtin_unreachable();
int pthread_attr_getdetachstate(const pthread_attr_t *attr, int *detachstate) {
*detachstate = attr->__mlibc_detachstate;
return 0;
}
int pthread_attr_setdetachstate(pthread_attr_t *attr, int detachstate) {
if (detachstate != PTHREAD_CREATE_DETACHED &&
detachstate != PTHREAD_CREATE_JOINABLE)
return EINVAL;

int pthread_attr_setdetachstate(pthread_attr_t *, int) {
__ensure(!"Not implemented");
__builtin_unreachable();
attr->__mlibc_detachstate = detachstate;
return 0;
}

int pthread_attr_getstacksize(const pthread_attr_t *__restrict, size_t *__restrict) {
__ensure(!"Not implemented");
__builtin_unreachable();
int pthread_attr_getstacksize(const pthread_attr_t *__restrict attr, size_t *__restrict stacksize) {
*stacksize = attr->__mlibc_stacksize;
return 0;
}

int pthread_attr_setstacksize(pthread_attr_t *, size_t) {
mlibc::infoLogger() << "mlibc: pthread_attr_setstacksize() is not implemented correctly" << frg::endlog;
int pthread_attr_setstacksize(pthread_attr_t *attr, size_t stacksize) {
if (stacksize < PTHREAD_STACK_MIN)
return EINVAL;
attr->__mlibc_stacksize = stacksize;
return 0;
}

int pthread_attr_getguardsize(const pthread_attr_t *__restrict, size_t *__restrict) {
__ensure(!"Not implemented");
__builtin_unreachable();
int pthread_attr_getstackaddr(const pthread_attr_t *attr, void **stackaddr) {
*stackaddr = attr->__mlibc_stackaddr;
return 0;
}

int pthread_attr_setguardsize(pthread_attr_t *, size_t) {
__ensure(!"Not implemented");
__builtin_unreachable();
int pthread_attr_setstackaddr(pthread_attr_t *attr, void *stackaddr) {
attr->__mlibc_stackaddr = stackaddr;
return 0;
}

int pthread_attr_getscope(const pthread_attr_t *, int) {
__ensure(!"Not implemented");
__builtin_unreachable();
int pthread_attr_getstack(const pthread_attr_t *attr, void **stackaddr, size_t *stacksize) {
*stackaddr = attr->__mlibc_stackaddr;
*stacksize = attr->__mlibc_stacksize;
return 0;
}
int pthread_attr_setstack(pthread_attr_t *attr, void *stackaddr, size_t stacksize) {
if (stacksize < PTHREAD_STACK_MIN)
return EINVAL;
attr->__mlibc_stacksize = stacksize;
attr->__mlibc_stackaddr = stackaddr;
return 0;
}

int pthread_attr_setscope(pthread_attr_t *, int) {
__ensure(!"Not implemented");
__builtin_unreachable();
int pthread_attr_getguardsize(const pthread_attr_t *__restrict attr, size_t *__restrict guardsize) {
*guardsize = attr->__mlibc_guardsize;
return 0;
}
int pthread_attr_setguardsize(pthread_attr_t *attr, size_t guardsize) {
attr->__mlibc_guardsize = guardsize;
return 0;
}

int pthread_attr_getschedpolicy(const pthread_attr_t *__restrict, int *__restrict) {
__ensure(!"Not implemented");
__builtin_unreachable();
int pthread_attr_getscope(const pthread_attr_t *attr, int *scope) {
*scope = attr->__mlibc_scope;
return 0;
}
int pthread_attr_setscope(pthread_attr_t *attr, int scope) {
if (scope != PTHREAD_SCOPE_SYSTEM &&
scope != PTHREAD_SCOPE_PROCESS)
return EINVAL;
if (scope == PTHREAD_SCOPE_PROCESS)
return ENOTSUP;
attr->__mlibc_scope = scope;
return 0;
}

int pthread_attr_setschedpolicy(pthread_attr_t *, int) {
__ensure(!"Not implemented");
__builtin_unreachable();
int pthread_attr_getinheritsched(const pthread_attr_t *attr, int *inheritsched) {
*inheritsched = attr->__mlibc_inheritsched;
return 0;
}
int pthread_attr_setinheritsched(pthread_attr_t *attr, int inheritsched) {
if (inheritsched != PTHREAD_INHERIT_SCHED &&
inheritsched != PTHREAD_EXPLICIT_SCHED)
return EINVAL;
attr->__mlibc_inheritsched = inheritsched;
return 0;
}

int pthread_attr_getschedparam(const pthread_attr_t *__restrict, struct sched_param *__restrict) {
__ensure(!"Not implemented");
__builtin_unreachable();
int pthread_attr_getschedparam(const pthread_attr_t *__restrict attr, struct sched_param *__restrict schedparam) {
*schedparam = attr->__mlibc_schedparam;
return 0;
}
int pthread_attr_setschedparam(pthread_attr_t *__restrict attr, const struct sched_param *__restrict schedparam) {
// TODO: this is supposed to return EINVAL for when the schedparam doesn't make sense
// for the given schedpolicy.
attr->__mlibc_schedparam = *schedparam;
return 0;
}

int pthread_attr_setschedparam(pthread_attr_t *__restrict, const struct sched_param *__restrict) {
__ensure(!"Not implemented");
__builtin_unreachable();
int pthread_attr_getschedpolicy(const pthread_attr_t *__restrict attr, int *__restrict policy) {
*policy = attr->__mlibc_schedpolicy;
return 0;
}
int pthread_attr_setschedpolicy(pthread_attr_t *__restrict attr, int policy) {
if (policy != SCHED_FIFO && policy != SCHED_RR &&
policy != SCHED_OTHER)
return EINVAL;
attr->__mlibc_schedpolicy = policy;
return 0;
}

int pthread_attr_getinheritsched(const pthread_attr_t *__restrict, int *__restrict) {
__ensure(!"Not implemented");
__builtin_unreachable();
namespace {
void get_own_stackinfo(void **stack_addr, size_t *stack_size) {
auto fp = fopen("/proc/self/maps", "r");
if (!fp) {
mlibc::infoLogger() << "mlibc pthreads: /proc/self/maps does not exist! Producing incorrect"
" stack results!" << frg::endlog;
return;
}

char line[256];
auto sp = mlibc::get_sp();
while (fgets(line, 128, fp)) {
uintptr_t from, to;
if(sscanf(line, "%lx-%lx", &from, &to) != 2)
continue;
if (sp < to && sp > from) {
// We need to return the lowest byte of the stack.
*stack_addr = reinterpret_cast<void*>(from);
*stack_size = to - from;
fclose(fp);
return;
}
}

fclose(fp);
}
}

int pthread_attr_setinheritsched(pthread_attr_t *, int) {
__ensure(!"Not implemented");
__builtin_unreachable();
int pthread_getattr_np(pthread_t thread, pthread_attr_t *attr) {
auto tcb = reinterpret_cast<Tcb*>(thread);
*attr = pthread_attr_t{};

if (!tcb->stackAddr || !tcb->stackSize) {
get_own_stackinfo(&attr->__mlibc_stackaddr, &attr->__mlibc_stacksize);
} else {
attr->__mlibc_stacksize = tcb->stackSize;
attr->__mlibc_stackaddr = tcb->stackAddr;
}

attr->__mlibc_guardsize = tcb->guardSize;
attr->__mlibc_detachstate = tcb->isJoinable ? PTHREAD_CREATE_JOINABLE : PTHREAD_CREATE_DETACHED;
mlibc::infoLogger() << "pthread_getattr_np(): Implementation is incomplete!" << frg::endlog;
return 0;
}

extern "C" Tcb *__rtdl_allocateTcb();

// pthread functions.
int pthread_create(pthread_t *__restrict thread, const pthread_attr_t *__restrict,
int pthread_create(pthread_t *__restrict thread, const pthread_attr_t *__restrict attrp,
void *(*entry) (void *), void *__restrict user_arg) {
auto new_tcb = __rtdl_allocateTcb();
pid_t tid;
mlibc::sys_clone(reinterpret_cast<void *>(entry), user_arg, new_tcb, &tid);
pthread_attr_t attr = {};
if (!attrp)
pthread_attr_init(&attr);
else
attr = *attrp;

// TODO: due to alignment guarantees, the stackaddr and stacksize might change
// when the stack is allocated. Currently this isn't propagated to the TCB,
// but it should be.
void *stack = attr.__mlibc_stackaddr;
if (!mlibc::sys_prepare_stack) {
MLIBC_MISSING_SYSDEP();
return ENOSYS;
}
int ret = mlibc::sys_prepare_stack(&stack, reinterpret_cast<void*>(entry),
user_arg, new_tcb, &attr.__mlibc_stacksize, &attr.__mlibc_guardsize);
if (ret)
return ret;

if (!mlibc::sys_clone) {
MLIBC_MISSING_SYSDEP();
return ENOSYS;
}
new_tcb->stackSize = attr.__mlibc_stacksize;
new_tcb->guardSize = attr.__mlibc_guardsize;
new_tcb->stackAddr = stack - attr.__mlibc_stacksize - attr.__mlibc_guardsize;
mlibc::sys_clone(new_tcb, &tid, stack);
*thread = reinterpret_cast<pthread_t>(new_tcb);

__atomic_store_n(&new_tcb->tid, tid, __ATOMIC_RELAXED);
Expand Down Expand Up @@ -312,21 +427,6 @@ int pthread_getname_np(pthread_t, char *, size_t) {
__builtin_unreachable();
}

int pthread_attr_setstack(pthread_attr_t *, void *, size_t) {
__ensure(!"Not implemented");
__builtin_unreachable();
}

int pthread_attr_getstack(const pthread_attr_t *, void **, size_t *) {
__ensure(!"Not implemented");
__builtin_unreachable();
}

int pthread_getattr_np(pthread_t, pthread_attr_t *) {
__ensure(!"Not implemented");
__builtin_unreachable();
}

int pthread_setschedparam(pthread_t, int, const struct sched_param *) {
__ensure(!"Not implemented");
__builtin_unreachable();
Expand Down
3 changes: 2 additions & 1 deletion options/posix/include/mlibc/posix-sysdeps.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,8 @@ int sys_close(int fd);
[[gnu::weak]] void sys_yield();
[[gnu::weak]] int sys_sleep(time_t *secs, long *nanos);
[[gnu::weak]] int sys_fork(pid_t *child);
[[gnu::weak]] int sys_clone(void *entry, void *user_arg, void *tcb, pid_t *pid_out);
[[gnu::weak]] int sys_clone(void *tcb, pid_t *pid_out, void *stack);
[[gnu::weak]] int sys_prepare_stack(void **stack, void *entry, void *user_arg, void* tcb, size_t *stack_size, size_t *guard_size);
[[gnu::weak]] int sys_execve(const char *path, char *const argv[], char *const envp[]);
[[gnu::weak]] int sys_pselect(int num_fds, fd_set *read_set, fd_set *write_set,
fd_set *except_set, const struct timespec *timeout, const sigset_t *sigmask, int *num_events);
Expand Down
Loading

0 comments on commit 3f3d9e2

Please sign in to comment.