Skip to content
This repository has been archived by the owner on Sep 21, 2021. It is now read-only.

[WIP] pthread support #48

Open
wants to merge 28 commits into
base: development
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
89253e7
Support multiple context version (between 2 and latest)
roblabla Dec 20, 2017
e8ab45b
Add pthread support
roblabla Dec 6, 2017
0b14593
Various small fixes
roblabla Dec 6, 2017
f12f698
Remove two useless files, fix PHONY
roblabla Dec 7, 2017
abcc4a0
various changes
roblabla Dec 8, 2017
e288f9f
More fixes
roblabla Dec 8, 2017
d84e329
Return enosys when using shared semaphore. Fix semaphores
roblabla Dec 9, 2017
e813293
Set guard_size to 0 for now
roblabla Dec 9, 2017
3116576
Fix various tests
roblabla Dec 9, 2017
c05bbcc
Fix pthread under mephisto
roblabla Dec 9, 2017
fd75d19
Properly handle timeout in semaphores
roblabla Dec 11, 2017
139e943
Properly figure out if the thread has died already
roblabla Dec 11, 2017
378b315
Set the default priority to 0x1F for new threads
roblabla Dec 11, 2017
73e8366
Close handle on thread release
roblabla Dec 11, 2017
ff8c3d5
Implement assert_eq
roblabla Dec 20, 2017
0dd01fb
Use gettimeofday, and sweeping fixes to pthread pointer tests
roblabla Dec 20, 2017
68746b4
Implement mutex with semaphores
roblabla Dec 20, 2017
b8a905b
Properly dealloc thread, closing handles and freeing stack
roblabla Dec 20, 2017
06bf3ce
Implement condvars using semaphores
roblabla Dec 20, 2017
ae44eba
Implement sem_timedwait
roblabla Dec 20, 2017
5254fc9
Fix up some mutex tests
roblabla Dec 20, 2017
97927b9
Activate a lot more tests
roblabla Dec 20, 2017
fbb5c6a
Super debugging redux
roblabla Dec 20, 2017
1cfa2ca
Implement pthread_setcancelstate
roblabla Dec 28, 2017
21e1b86
Fix syscalls signatures
roblabla Jan 6, 2018
8099b79
Implement __getreent
roblabla Jan 6, 2018
3867c1e
Various fixes in pthread test suite
roblabla Jan 6, 2018
191a901
Properly bubble errors in _rthread_cond_timedwait
roblabla Jan 6, 2018
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 17 additions & 3 deletions Makefile
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
include libtransistor.mk

libtransistor_TESTS := malloc bsd_ai_packing bsd sfdnsres nv helloworld hid hexdump args ssp stdin multiple_set_heap_size vi gpu display am sdl audio_output init_fini_arrays
libtransistor_TESTS := malloc bsd_ai_packing bsd sfdnsres nv helloworld hid hexdump args ssp stdin multiple_set_heap_size vi gpu display am sdl audio_output init_fini_arrays pthread getthreadid
libtransistor_OBJECT_NAMES := crt0_common.o svc.o ipc.o tls.o util.o ipc/sm.o ipc/bsd.o ipc/nv.o ipc/hid.o ipc/ro.o ipc/nifm.o hid.o context.o ipc/vi.o display/binder.o display/parcel.o display/surface.o gpu/gpu.o ipc/am.o display/graphic_buffer_queue.o display/display.o gfx/blit.o ipc/time.o syscalls/syscalls.o syscalls/fd.o syscalls/sched.o syscalls/socket.o ipc/audio.o ipc/bpc.o
libtransistor_OBJECT_FILES := $(addprefix $(LIBTRANSISTOR_HOME)/build/lib/,$(libtransistor_OBJECT_NAMES))

Expand All @@ -17,9 +17,12 @@ export AR_FOR_TARGET = $(AR)
export RANLIB_FOR_TARGET = llvm-ranlib$(LLVM_POSTFIX)
export CFLAGS_FOR_TARGET = $(CC_FLAGS) -Wno-unused-command-line-argument

# Everyone needs their cflags.
export CC_FLAGS

.SUFFIXES: # disable built-in rules

.PHONY: clean, clean_newlib, clean_compiler-rt, distclean
.PHONY: clean, clean_newlib, clean_compiler-rt, distclean

all: $(LIBTRANSISTOR_HOME)/build/lib/libtransistor.nro.a \
$(LIBTRANSISTOR_HOME)/build/lib/libtransistor.nso.a \
Expand Down Expand Up @@ -48,12 +51,17 @@ $(LIBTRANSISTOR_HOME)/build/test/%.o: $(LIBTRANSISTOR_HOME)/test/%.c

# Disable stack protector for crt0_common
$(LIBTRANSISTOR_HOME)/build/lib/crt0_common.o: $(LIBTRANSISTOR_HOME)/lib/crt0_common.c
mkdir -p $(@D)
$(CC) $(CC_FLAGS) $(WARNINGS) -fno-stack-protector -Ipthread/ -Ipthread/sys/switch -c -o $@ $<

# Don't instrument ipc.c, it might mess up the state
$(LIBTRANSISTOR_HOME)/build/lib/ipc.o: $(LIBTRANSISTOR_HOME)/lib/ipc.c
mkdir -p $(@D)
$(CC) $(CC_FLAGS) $(WARNINGS) -fno-stack-protector -c -o $@ $<

$(LIBTRANSISTOR_HOME)/build/lib/%.o: $(LIBTRANSISTOR_HOME)/lib/%.c
mkdir -p $(@D)
$(CC) $(CC_FLAGS) $(WARNINGS) -c -o $@ $<
$(CC) $(CC_FLAGS) $(WARNINGS) -finstrument-functions -c -o $@ $<

$(LIBTRANSISTOR_HOME)/build/lib/%.o: $(LIBTRANSISTOR_HOME)/lib/%.S
mkdir -p $(@D)
Expand Down Expand Up @@ -84,6 +92,11 @@ $(LIBTRANSISTOR_HOME)/build/newlib/Makefile:
$(LIBTRANSISTOR_HOME)/build/newlib/aarch64-none-switch/newlib/libc.a: $(LIBTRANSISTOR_HOME)/build/newlib/Makefile
$(MAKE) -C $(LIBTRANSISTOR_HOME)/build/newlib/

$(LIBTRANSISTOR_HOME)/pthread/libpthread.a:
$(MAKE) -C $(LIBTRANSISTOR_HOME)/pthread

.PHONY: $(LIBTRANSISTOR_HOME)/pthread/libpthread.a

$(COMPILER_RT_BUILTINS_LIB): $(LIBTRANSISTOR_HOME)/build/compiler-rt/Makefile
$(MAKE) -C $(LIBTRANSISTOR_HOME)/build/compiler-rt/

Expand Down Expand Up @@ -114,6 +127,7 @@ $(LIBTRANSISTOR_HOME)/build/sdl2/Makefile:

clean:
rm -rf $(LIBTRANSISTOR_HOME)/build/lib/* $(LIBTRANSISTOR_HOME)/build/test/*
$(MAKE) -C pthread clean

clean_newlib:
rm -rf build/newlib
Expand Down
15 changes: 14 additions & 1 deletion include/libtransistor/tls.h
Original file line number Diff line number Diff line change
@@ -1,3 +1,16 @@
#pragma once

void *get_tls();
#include <reent.h>

struct thread_ctx {
struct _reent reent;
void *pthread; // Pointer to pthread internal structure
};

struct tls {
char ipc_buffer[0x100];
char _unk1[0xF8];
struct thread_ctx *ctx;
};

struct tls *get_tls();
102 changes: 89 additions & 13 deletions lib/crt0_common.c
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
#include<unistd.h>
#include<errno.h>
#include<stdlib.h>
#include<rthread.h>

int main(int argc, char **argv);

Expand Down Expand Up @@ -158,7 +159,7 @@ static int bsslog_write(struct _reent *reent, void *v, const char *ptr, int len)

static jmp_buf exit_jmpbuf;
static int exit_value;

static void *global_aslr_base;
int _libtransistor_start(libtransistor_context_t *ctx, void *aslr_base) {
if(relocate(aslr_base)) {
return -4;
Expand All @@ -169,6 +170,7 @@ int _libtransistor_start(libtransistor_context_t *ctx, void *aslr_base) {

char *argv_default[] = {"contextless", NULL};
char **argv = argv_default;
global_aslr_base = aslr_base;
int argc = 1;

if(ctx != NULL) {
Expand All @@ -181,34 +183,39 @@ int _libtransistor_start(libtransistor_context_t *ctx, void *aslr_base) {
dbg_printf("invalid context magic");
return -2;
}


if(ctx->version < 2 || ctx->version > LIBTRANSISTOR_CONTEXT_VERSION) {
dbg_printf("mismatched context version");
return -2;
}

ctx->log_buffer = log_buffer;
ctx->log_length = &log_length;
ctx->return_flags = 0;

argv = ctx->argv;
argc = (int) ctx->argc;

if(ctx->version != LIBTRANSISTOR_CONTEXT_VERSION) {
dbg_printf("mismatched context version");
return -2;
}

if(ctx->size != sizeof(libtransistor_context_t)) {
dbg_printf("mismatched context size");
return -3;
}
memcpy(&libtransistor_context, ctx, ctx->size);

if (ctx->version == 2)
libtransistor_context.main_thread = 0;
} else {
dbg_printf("no context");

// Temporary fix to run this in Mephisto.
libtransistor_context.main_thread = 0xde00;
if(svcSetHeapSize(&libtransistor_context.mem_base, DEFAULT_NOCONTEXT_HEAP_SIZE) != RESULT_OK) {
dbg_printf("failed to set heap size");
return -5;
}
libtransistor_context.mem_size = DEFAULT_NOCONTEXT_HEAP_SIZE;
}

dbg_printf("init threads");
phal_tid tid = { .id = libtransistor_context.main_thread, .stack = NULL };
_rthread_internal_init(tid);

dbg_printf("init stdio");
bsslog_stdout._write = bsslog_write;
bsslog_stdout._flags = __SWR | __SNBF;
Expand Down Expand Up @@ -238,7 +245,9 @@ int _libtransistor_start(libtransistor_context_t *ctx, void *aslr_base) {
stdout = &bsslog_stdout;
stderr = &bsslog_stdout;
}

dbg_printf("set up stdout");
printf("ASLR base %p\n", aslr_base);

if(init_array != NULL) {
if(init_array_size == -1) {
Expand All @@ -248,7 +257,16 @@ int _libtransistor_start(libtransistor_context_t *ctx, void *aslr_base) {
init_array[i]();
}
}


dbg_printf("init threads");
if (libtransistor_context.main_thread != 0) {
phal_tid maintid;
maintid.id = libtransistor_context.main_thread;
maintid.stack = NULL;
_rthread_internal_init(maintid);
} else
dbg_printf("Ctx version doesn't support threading.");

int ret;
if (setjmp(exit_jmpbuf) == 0) {
ret = main(argc, argv);
Expand Down Expand Up @@ -281,3 +299,61 @@ void _exit(int ret) {
exit_value = ret;
longjmp(exit_jmpbuf, 1);
}

char *ft_itoa(char buf[16], uintmax_t n, char *base)
{
int i;
size_t base_len;

i = 0;
base_len = strlen(base);
while (n > 0)
{
buf[i++] = base[n % base_len];
n /= base_len;
}
i = 0;
while (i < 16 / 2) {
char c = buf[i];
buf[i] = buf[15 - i];
buf[15 - i] = c;
i++;
}
return (buf);
}

static int in_cyg = 0;
void __cyg_profile_func_enter(void *des, void *src_call) {
if (in_cyg)
return;
in_cyg = 1;


char msg[] = "\nThread 0x0000000000000000 Entering function 0x0000000000000000 from 0x0000000000000000\n";

void *tid = get_tls();
ft_itoa(msg + strlen("\nThread 0x"), tid, "0123456789ABCDEF");
ft_itoa(msg + strlen("\nThread 0x0000000000000000 Entering function 0x"), des - global_aslr_base, "0123456789ABCDEF");
ft_itoa(msg + strlen("\nThread 0x0000000000000000 Entering function 0x0000000000000000 from 0x"), src_call - global_aslr_base, "0123456789ABCDEF");
if (bsd_get_object().object_id != 0 && libtransistor_context.has_bsd && libtransistor_context.std_socket > 0) {
bsd_send(libtransistor_context.std_socket, msg, strlen(msg), 0);
}
in_cyg = 0;
}

void __cyg_profile_func_exit(void *des, void *src_call) {
if (in_cyg)
return;
in_cyg = 1;

char msg[] = "\nThread 0x0000000000000000 Exit function 0x0000000000000000 to 0x0000000000000000\n";

void *tid = get_tls();
ft_itoa(msg + strlen("\nThread 0x"), tid, "0123456789ABCDEF");
ft_itoa(msg + strlen("\nThread 0x0000000000000000 Exit function 0x"), des - global_aslr_base, "0123456789ABCDEF");
ft_itoa(msg + strlen("\nThread 0x0000000000000000 Exit function 0x0000000000000000 to 0x"), src_call - global_aslr_base, "0123456789ABCDEF");
if (bsd_get_object().object_id != 0 && libtransistor_context.has_bsd && libtransistor_context.std_socket > 0) {
bsd_send(libtransistor_context.std_socket, msg, strlen(msg), 0);
}
in_cyg = 0;
}
30 changes: 20 additions & 10 deletions lib/syscalls/syscalls.c
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,23 @@
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <reent.h>

#include <libtransistor/tls.h>
#include<libtransistor/context.h>
#include<libtransistor/fd.h>
#include<libtransistor/ipc/time.h>

void _exit(); // implemented in libtransistor crt0

struct _reent *__getreent() {
struct tls *tls = get_tls();
if (tls == NULL || tls->ctx == NULL)
return NULL;
else
return &tls->ctx->reent;
}

int _close_r(struct _reent *reent, int file) {
int res = fd_close(file);
if (res < 0) {
Expand All @@ -26,7 +36,7 @@ int _close_r(struct _reent *reent, int file) {

char *_environ[] = {NULL};

int _execve_r(struct _reent *reent, char *name, char **argv, char **env) {
int _execve_r(struct _reent *reent, const char *name, char *const *argv, char *const *env) {
reent->_errno = ENOSYS;
return -1;
}
Expand Down Expand Up @@ -56,12 +66,12 @@ int _kill_r(struct _reent *reent, int pid, int sig) {
return -1;
}

int _link_r(struct _reent *reent, char *old, char *new) {
int _link_r(struct _reent *reent, const char *old, const char *new) {
reent->_errno = ENOSYS;
return -1;
}

int _lseek_r(struct _reent *reent, int file, int pos, int whence) {
off_t _lseek_r(struct _reent *reent, int file, off_t pos, int whence) {
ssize_t res = 0;

struct file *f = fd_file_get(file);
Expand All @@ -84,12 +94,12 @@ int _lseek_r(struct _reent *reent, int file, int pos, int whence) {
return res;
}

int _open_r(struct _reent *reent, const char *name, int flags, ...) {
int _open_r(struct _reent *reent, const char *name, int flags, int mode) {
reent->_errno = ENOSYS;
return -1;
}

int _read_r(struct _reent *reent, int file, char *ptr, int len) {
ssize_t _read_r(struct _reent *reent, int file, void *ptr, size_t len) {
ssize_t res = 0;

struct file *f = fd_file_get(file);
Expand All @@ -102,7 +112,7 @@ int _read_r(struct _reent *reent, int file, char *ptr, int len) {
res = -ENOSYS;
goto finalize;
}
res = f->ops->read(f->data, ptr, len);
res = f->ops->read(f->data, (char*)ptr, len);
finalize:
fd_file_put(f);
if (res < 0) {
Expand All @@ -114,7 +124,7 @@ int _read_r(struct _reent *reent, int file, char *ptr, int len) {

static size_t data_size = 0;

caddr_t _sbrk_r(struct _reent *reent, int incr) {
void *_sbrk_r(struct _reent *reent, ptrdiff_t incr) {
if(data_size + incr > libtransistor_context.mem_size) {
reent->_errno = ENOMEM;
return (void*) -1;
Expand All @@ -136,7 +146,7 @@ clock_t _times_r(struct _reent *reent, struct tms *buf) {
return (clock_t) -1;
}

int _unlink_r(struct _reent *reent, char *name) {
int _unlink_r(struct _reent *reent, const char *name) {
reent->_errno = ENOSYS;
return -1;
}
Expand All @@ -146,7 +156,7 @@ int _wait_r(struct _reent *reent, int *status) {
return -1;
}

int _write_r(struct _reent *reent, int file, char *ptr, int len) {
ssize_t _write_r(struct _reent *reent, int file, const void *ptr, size_t len) {
ssize_t res = 0;

struct file *f = fd_file_get(file);
Expand All @@ -159,7 +169,7 @@ int _write_r(struct _reent *reent, int file, char *ptr, int len) {
res = -ENOSYS;
goto finalize;
}
res = f->ops->write(f->data, ptr, len);
res = f->ops->write(f->data, (char*)ptr, len);
finalize:
fd_file_put(f);
if (res < 0) {
Expand Down
4 changes: 2 additions & 2 deletions libtransistor.mk
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ else
LIBTRANSISTOR_HOME := $(realpath $(LIBTRANSISTOR_HOME))
endif

SYS_INCLUDES := -isystem $(LIBTRANSISTOR_HOME)/newlib/newlib/libc/include/ -isystem $(LIBTRANSISTOR_HOME)/newlib/newlib/libc/sys/switch/include/
SYS_INCLUDES := -isystem $(LIBTRANSISTOR_HOME)/pthread/include -isystem $(LIBTRANSISTOR_HOME)/newlib/newlib/libc/include/ -isystem $(LIBTRANSISTOR_HOME)/newlib/newlib/libc/sys/switch/include/
INCLUDES := $(SYS_INCLUDES) -I$(LIBTRANSISTOR_HOME)/include/ -I $(LIBTRANSISTOR_HOME)/build/sdl2_install/include/
WARNINGS := -Wall -Wextra -Werror-implicit-function-declaration -Wno-unused-parameter -Wno-unused-command-line-argument

Expand All @@ -23,7 +23,7 @@ PYTHON2 := python2
MEPHISTO := ctu
RUBY := ruby
COMPILER_RT_BUILTINS_LIB := $(LIBTRANSISTOR_HOME)/build/compiler-rt/lib/linux/libclang_rt.builtins-aarch64.a
LIBTRANSISTOR_COMMON_LIBS := $(LIBTRANSISTOR_HOME)/build/newlib/aarch64-none-switch/newlib/libc.a $(COMPILER_RT_BUILTINS_LIB) $(LIBTRANSISTOR_HOME)/build/sdl2_install/lib/libSDL2.a
LIBTRANSISTOR_COMMON_LIBS := $(LIBTRANSISTOR_HOME)/build/newlib/aarch64-none-switch/newlib/libc.a $(COMPILER_RT_BUILTINS_LIB) $(LIBTRANSISTOR_HOME)/build/sdl2_install/lib/libSDL2.a $(LIBTRANSISTOR_HOME)/pthread/libpthread.a
LIBTRANSISTOR_NRO_LIB := $(LIBTRANSISTOR_HOME)/build/lib/libtransistor.nro.a
LIBTRANSISTOR_NSO_LIB := $(LIBTRANSISTOR_HOME)/build/lib/libtransistor.nso.a
LIBTRANSISTOR_NRO_LDFLAGS := --whole-archive $(LIBTRANSISTOR_NRO_LIB) --no-whole-archive $(LIBTRANSISTOR_COMMON_LIBS)
Expand Down
Loading