#include #include #include #include #include #include #include "../internal.h" #include "types.h" #include "runtime/env.h" #include "kernel/mutex.h" #include "services/fatal.h" #include "services/time.h" #include "result.h" void __attribute__((weak)) NORETURN __libnx_exit(int rc); extern const u8 __tdata_lma[]; extern const u8 __tdata_lma_end[]; extern u8 __tls_start[]; /// TimeType passed to timeGetCurrentTime() by __libnx_gtod(). __attribute__((weak)) TimeType __nx_time_type = TimeType_Default; static struct _reent* __libnx_get_reent(void) { ThreadVars* tv = getThreadVars(); if (tv->magic != THREADVARS_MAGIC) fatalSimple(MAKERESULT(Module_Libnx, LibnxError_BadReent)); return tv->reent; } //TODO: timeGetCurrentTime() returns UTC time. How to handle timezones? int __libnx_gtod(struct _reent *ptr, struct timeval *tp, struct timezone *tz) { if (tp != NULL) { u64 now=0; Result rc=0; rc = timeGetCurrentTime(__nx_time_type, &now); if (R_FAILED(rc)) { ptr->_errno = EINVAL; return -1; } tp->tv_sec = now; tp->tv_usec = now*1000000;//timeGetCurrentTime() only returns seconds. } if (tz != NULL) { tz->tz_minuteswest = 0; tz->tz_dsttime = 0; } return 0; } int usleep(useconds_t useconds) { svcSleepThread(useconds * 1000ull); return 0; } void newlibSetup(void) { // Register newlib syscalls __syscalls.exit = __libnx_exit; __syscalls.gettod_r = __libnx_gtod; __syscalls.getreent = __libnx_get_reent; // Register locking syscalls __syscalls.lock_init = mutexInit; __syscalls.lock_acquire = mutexLock; __syscalls.lock_release = mutexUnlock; __syscalls.lock_init_recursive = rmutexInit; __syscalls.lock_acquire_recursive = rmutexLock; __syscalls.lock_release_recursive = rmutexUnlock; // Initialize thread vars for the main thread ThreadVars* tv = getThreadVars(); tv->magic = THREADVARS_MAGIC; tv->thread_ptr = NULL; tv->reent = _impure_ptr; tv->tls_tp = __tls_start-2*sizeof(void*); // subtract size of Thread Control Block (TCB) tv->handle = envGetMainThreadHandle(); u32 tls_size = __tdata_lma_end - __tdata_lma; if (tls_size) memcpy(__tls_start, __tdata_lma, tls_size); }