From f7a698388ccf62a2ccd26765584c26eb098b3897 Mon Sep 17 00:00:00 2001 From: James Benton Date: Mon, 28 May 2018 11:40:22 +0100 Subject: [PATCH] wutnewlib: Implement the new __syscalls from upcoming devkitPPC release. --- libraries/wutnewlib/CMakeLists.txt | 9 +- libraries/wutnewlib/sleep.c | 16 --- libraries/wutnewlib/syscalls.c | 184 -------------------------- libraries/wutnewlib/wut_clock.c | 66 +++++++++ libraries/wutnewlib/wut_gettod_r.c | 24 ++++ libraries/wutnewlib/wut_lock.c | 59 +++++++++ libraries/wutnewlib/wut_malloc_lock.c | 23 ++++ libraries/wutnewlib/wut_nanosleep.c | 16 +++ libraries/wutnewlib/wut_newlib.c | 34 +++++ libraries/wutnewlib/wut_newlib.h | 27 ++++ libraries/wutnewlib/wut_sbrk.c | 46 +++++++ 11 files changed, 302 insertions(+), 202 deletions(-) delete mode 100644 libraries/wutnewlib/sleep.c delete mode 100644 libraries/wutnewlib/syscalls.c create mode 100644 libraries/wutnewlib/wut_clock.c create mode 100644 libraries/wutnewlib/wut_gettod_r.c create mode 100644 libraries/wutnewlib/wut_lock.c create mode 100644 libraries/wutnewlib/wut_malloc_lock.c create mode 100644 libraries/wutnewlib/wut_nanosleep.c create mode 100644 libraries/wutnewlib/wut_newlib.c create mode 100644 libraries/wutnewlib/wut_newlib.h create mode 100644 libraries/wutnewlib/wut_sbrk.c diff --git a/libraries/wutnewlib/CMakeLists.txt b/libraries/wutnewlib/CMakeLists.txt index 3c4652d..9b011d9 100644 --- a/libraries/wutnewlib/CMakeLists.txt +++ b/libraries/wutnewlib/CMakeLists.txt @@ -2,8 +2,13 @@ cmake_minimum_required(VERSION 3.2) project(wutnewlib C) add_library(wutnewlib - sleep.c - syscalls.c) + wut_clock.c + wut_gettod_r.c + wut_lock.c + wut_malloc_lock.c + wut_nanosleep.c + wut_newlib.c + wut_sbrk.c) target_include_directories(wutnewlib PRIVATE "${WUT_ROOT}/include") install(TARGETS wutnewlib diff --git a/libraries/wutnewlib/sleep.c b/libraries/wutnewlib/sleep.c deleted file mode 100644 index b35e932..0000000 --- a/libraries/wutnewlib/sleep.c +++ /dev/null @@ -1,16 +0,0 @@ -#include -#include -#include -#include - -unsigned sleep(unsigned seconds) -{ - OSSleepTicks(OSSeconds(seconds)); - return 0; -} - -int usleep(useconds_t microseconds) -{ - OSSleepTicks(OSMicroseconds(microseconds)); - return 0; -} diff --git a/libraries/wutnewlib/syscalls.c b/libraries/wutnewlib/syscalls.c deleted file mode 100644 index 8559d98..0000000 --- a/libraries/wutnewlib/syscalls.c +++ /dev/null @@ -1,184 +0,0 @@ -#include - -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include - -static OSMutex sMallocMutex; -static uint8_t *sHeapBase = NULL; -static uint32_t sHeapMaxSize = 0; -static volatile uint32_t sHeapSize = 0; - -static void * -__libwut_sbrk_r(struct _reent *r, - ptrdiff_t incr) -{ - uint32_t oldSize, newSize; - - do { - oldSize = sHeapSize; - newSize = oldSize + incr; - - if (newSize > sHeapMaxSize) { - r->_errno = ENOMEM; - return (void *)-1; - } - } while (!OSCompareAndSwapAtomic(&sHeapSize, oldSize, newSize)); - - return sHeapBase + oldSize; -} - -static int -__libwut_lock_init(int *lock, - int recursive) -{ - OSMutex *mutex = NULL; - if (!lock) { - return -1; - } - - mutex = (OSMutex *)malloc(sizeof(OSMutex)); - if (!mutex) { - return -1; - } - - OSInitMutex(mutex); - *lock = (int)mutex; - return 0; -} - -static int -__libwut_lock_close(int *lock) -{ - if (!lock || *lock == 0) { - return -1; - } - - free((void *)*lock); - *lock = 0; - return 0; -} - -static int -__libwut_lock_acquire(int *lock) -{ - OSMutex *mutex = (OSMutex *)*lock; - if (!lock || *lock == 0) { - return -1; - } - - OSLockMutex(mutex); - return 0; -} - -static int -__libwut_lock_release(int *lock) -{ - OSMutex *mutex = (OSMutex *)*lock; - if (!lock || *lock == 0) { - return -1; - } - - OSUnlockMutex(mutex); - return 0; -} - -static void -__libwut_malloc_lock(struct _reent *r) -{ - OSLockMutex(&sMallocMutex); -} - -static void -__libwut_malloc_unlock(struct _reent *r) -{ - OSUnlockMutex(&sMallocMutex); -} - -static void -__libwut_exit(int code) -{ - exit(code); -} - -static int -__libwut_gettod_r(struct _reent *ptr, - struct timeval *tp, - struct timezone *tz) -{ - OSCalendarTime tm; - OSTicksToCalendarTime(OSGetTime(), &tm); - - if (tp != NULL) { - tp->tv_sec = tm.tm_sec; - tp->tv_usec = tm.tm_usec + tm.tm_msec * 1000; - } - - if (tz != NULL) { - tz->tz_minuteswest = 0; - tz->tz_dsttime = 0; - } - - return 0; -} - -static void -__init_malloc_lock() -{ - OSInitMutex(&sMallocMutex); -} - -static void -__init_libc_heap() -{ - MEMExpandedHeap *heap = (MEMExpandedHeap *)MEMGetBaseHeapHandle(MEM_BASE_HEAP_MEM2); - uint32_t freeSize = MEMGetAllocatableSizeForExpHeapEx(heap, 0x1000); - - sHeapMaxSize = (uint32_t)(0.9f * (float)freeSize) & ~0xFFF; - sHeapBase = (uint8_t *)MEMAllocFromExpHeapEx(heap, sHeapMaxSize, 0x1000); - sHeapSize = 0; -} - -static void -__free_libc_heap() -{ - MEMExpandedHeap *heap = (MEMExpandedHeap *)MEMGetBaseHeapHandle(MEM_BASE_HEAP_MEM2); - MEMFreeToExpHeap(heap, sHeapBase); -} - -static void -__init_syscall_array() -{ - __syscalls.sbrk_r = __libwut_sbrk_r; - __syscalls.lock_init = __libwut_lock_init; - __syscalls.lock_close = __libwut_lock_close; - __syscalls.lock_acquire = __libwut_lock_acquire; - __syscalls.lock_release = __libwut_lock_release; - __syscalls.malloc_lock = __libwut_malloc_lock; - __syscalls.malloc_unlock = __libwut_malloc_unlock; - __syscalls.exit = __libwut_exit; - __syscalls.gettod_r = __libwut_gettod_r; -} - -void -__init_wut_newlib() -{ - __init_libc_heap(); - __init_malloc_lock(); - __init_syscall_array(); -} - -void -__fini_wut_newlib() -{ - __free_libc_heap(); -} diff --git a/libraries/wutnewlib/wut_clock.c b/libraries/wutnewlib/wut_clock.c new file mode 100644 index 0000000..5c7e03e --- /dev/null +++ b/libraries/wutnewlib/wut_clock.c @@ -0,0 +1,66 @@ +#include "wut_newlib.h" + +#include +#include + +// The Wii U epoch is at 2000, so we must map it to 1970 for gettime +#define WIIU_EPOCH_YEAR (2000) + +#define EPOCH_YEAR (1970) +#define EPOCH_YEARS_SINCE_LEAP 2 +#define EPOCH_YEARS_SINCE_CENTURY 70 +#define EPOCH_YEARS_SINCE_LEAP_CENTURY 370 + +#define EPOCH_DIFF_YEARS (2000 - EPOCH_YEAR) +#define EPOCH_DIFF_DAYS \ + ((EPOCH_DIFF_YEARS * 365) + \ + (EPOCH_DIFF_YEARS - 1 + EPOCH_YEARS_SINCE_LEAP) / 4 - \ + (EPOCH_DIFF_YEARS - 1 + EPOCH_YEARS_SINCE_CENTURY) / 100 + \ + (EPOCH_DIFF_YEARS - 1 + EPOCH_YEARS_SINCE_LEAP_CENTURY) / 400) +#define EPOCH_DIFF_SECS (60ull * 60ull * 24ull * (uint64_t)EPOCH_DIFF_DAYS) + +int +__wut_clock_gettime(clockid_t clock_id, + struct timespec *tp) +{ + if (clock_id == CLOCK_MONOTONIC) { + OSTime time = OSGetSystemTime(); + tp->tv_sec = (time_t)OSTicksToSeconds(time); + + time -= OSSecondsToTicks(tp->tv_sec); + tp->tv_nsec = (long)OSTicksToNanoseconds(time); + } else if (clock_id == CLOCK_REALTIME) { + OSTime time = OSGetTime(); + tp->tv_sec = (time_t)OSTicksToSeconds(time); + + time -= OSSecondsToTicks(tp->tv_sec); + tp->tv_nsec = (long)OSTicksToNanoseconds(time); + + tp->tv_sec += EPOCH_DIFF_SECS; + } else { + return EINVAL; + } + + return 0; +} + +int +__wut_clock_settime(clockid_t clock_id, + const struct timespec *tp) +{ + return EPERM; +} + +int +__wut_clock_getres(clockid_t clock_id, + struct timespec *res) +{ + if (clock_id != CLOCK_MONOTONIC && + clock_id != CLOCK_REALTIME) { + return EINVAL; + } + + res->tv_sec = 0; + res->tv_nsec = (long)((1000000000ull + (uint64_t)OSTimerClockSpeed) / (uint64_t)OSTimerClockSpeed); + return 0; +} diff --git a/libraries/wutnewlib/wut_gettod_r.c b/libraries/wutnewlib/wut_gettod_r.c new file mode 100644 index 0000000..8767d40 --- /dev/null +++ b/libraries/wutnewlib/wut_gettod_r.c @@ -0,0 +1,24 @@ +#include "wut_newlib.h" + +#include + +int +__wut_gettod_r(struct _reent *ptr, + struct timeval *tp, + struct timezone *tz) +{ + OSCalendarTime tm; + OSTicksToCalendarTime(OSGetTime(), &tm); + + if (tp != NULL) { + tp->tv_sec = tm.tm_sec; + tp->tv_usec = tm.tm_usec + tm.tm_msec * 1000; + } + + if (tz != NULL) { + tz->tz_minuteswest = 0; + tz->tz_dsttime = 0; + } + + return 0; +} diff --git a/libraries/wutnewlib/wut_lock.c b/libraries/wutnewlib/wut_lock.c new file mode 100644 index 0000000..4b9f0a2 --- /dev/null +++ b/libraries/wutnewlib/wut_lock.c @@ -0,0 +1,59 @@ +#include "wut_newlib.h" + +#include +#include + +int +__wut_lock_init(int *lock, + int recursive) +{ + OSMutex *mutex = NULL; + if (!lock) { + return -1; + } + + mutex = (OSMutex *)malloc(sizeof(OSMutex)); + if (!mutex) { + return -1; + } + + OSInitMutex(mutex); + *lock = (int)mutex; + return 0; +} + +int +__wut_lock_close(int *lock) +{ + if (!lock || *lock == 0) { + return -1; + } + + free((void *)*lock); + *lock = 0; + return 0; +} + +int +__wut_lock_acquire(int *lock) +{ + OSMutex *mutex = (OSMutex *)*lock; + if (!lock || *lock == 0) { + return -1; + } + + OSLockMutex(mutex); + return 0; +} + +int +__wut_lock_release(int *lock) +{ + OSMutex *mutex = (OSMutex *)*lock; + if (!lock || *lock == 0) { + return -1; + } + + OSUnlockMutex(mutex); + return 0; +} diff --git a/libraries/wutnewlib/wut_malloc_lock.c b/libraries/wutnewlib/wut_malloc_lock.c new file mode 100644 index 0000000..5a7244d --- /dev/null +++ b/libraries/wutnewlib/wut_malloc_lock.c @@ -0,0 +1,23 @@ +#include "wut_newlib.h" + +#include + +static OSMutex sMallocMutex; + +void +__wut_malloc_lock(struct _reent *r) +{ + OSLockMutex(&sMallocMutex); +} + +void +__wut_malloc_unlock(struct _reent *r) +{ + OSUnlockMutex(&sMallocMutex); +} + +void +__init_wut_malloc_lock() +{ + OSInitMutex(&sMallocMutex); +} diff --git a/libraries/wutnewlib/wut_nanosleep.c b/libraries/wutnewlib/wut_nanosleep.c new file mode 100644 index 0000000..3fa6991 --- /dev/null +++ b/libraries/wutnewlib/wut_nanosleep.c @@ -0,0 +1,16 @@ +#include "wut_newlib.h" + +#include +#include +#include + +int +__wut_nanosleep(const struct timespec *req, + struct timespec *rem) +{ + OSSleepTicks(OSSecondsToTicks(req->tv_sec) + + OSNanosecondsToTicks(req->tv_nsec)); + rem->tv_sec = 0; + rem->tv_nsec = 0; + return 0; +} diff --git a/libraries/wutnewlib/wut_newlib.c b/libraries/wutnewlib/wut_newlib.c new file mode 100644 index 0000000..70fd641 --- /dev/null +++ b/libraries/wutnewlib/wut_newlib.c @@ -0,0 +1,34 @@ +#include "wut_newlib.h" +#include + +static void +__init_wut_syscall_array() +{ + __syscalls.sbrk_r = __wut_sbrk_r; + __syscalls.lock_init = __wut_lock_init; + __syscalls.lock_close = __wut_lock_close; + __syscalls.lock_acquire = __wut_lock_acquire; + __syscalls.lock_release = __wut_lock_release; + __syscalls.malloc_lock = __wut_malloc_lock; + __syscalls.malloc_unlock = __wut_malloc_unlock; + __syscalls.exit = exit; + __syscalls.gettod_r = __wut_gettod_r; + __syscalls.clock_gettime = __wut_clock_gettime; + __syscalls.clock_settime = __wut_clock_settime; + __syscalls.clock_getres = __wut_clock_getres; + __syscalls.nanosleep = __wut_nanosleep; +} + +void +__init_wut_newlib() +{ + __init_wut_sbrk_heap(); + __init_wut_malloc_lock(); + __init_wut_syscall_array(); +} + +void +__fini_wut_newlib() +{ + __fini_wut_sbrk_heap(); +} diff --git a/libraries/wutnewlib/wut_newlib.h b/libraries/wutnewlib/wut_newlib.h new file mode 100644 index 0000000..eb93019 --- /dev/null +++ b/libraries/wutnewlib/wut_newlib.h @@ -0,0 +1,27 @@ +#ifndef __WUT_NEWLIB_H +#define __WUT_NEWLIB_H + +#include +#include +#include +#include + +void * __wut_sbrk_r(struct _reent *r, ptrdiff_t incr); +int __wut_lock_init(int *lock, int recursive); +int __wut_lock_close(int *lock); +int __wut_lock_acquire(int *lock); +int __wut_lock_release(int *lock); +void __wut_malloc_lock(struct _reent *r); +void __wut_malloc_unlock(struct _reent *r); +int __wut_gettod_r(struct _reent *ptr, struct timeval *tp, + struct timezone *tz); +int __wut_clock_gettime(clockid_t clock_id, struct timespec *tp); +int __wut_clock_settime(clockid_t clock_id, const struct timespec *tp); +int __wut_clock_getres(clockid_t clock_id, struct timespec *res); +int __wut_nanosleep(const struct timespec *req, struct timespec *rem); + +void __init_wut_malloc_lock(); +void __init_wut_sbrk_heap(); +void __fini_wut_sbrk_heap(); + +#endif // ifndef __WUT_NEWLIB_H diff --git a/libraries/wutnewlib/wut_sbrk.c b/libraries/wutnewlib/wut_sbrk.c new file mode 100644 index 0000000..359f9b0 --- /dev/null +++ b/libraries/wutnewlib/wut_sbrk.c @@ -0,0 +1,46 @@ +#include "wut_newlib.h" + +#include +#include +#include + +static uint8_t *sHeapBase = NULL; +static uint32_t sHeapMaxSize = 0; +static volatile uint32_t sHeapSize = 0; + +void * +__wut_sbrk_r(struct _reent *r, + ptrdiff_t incr) +{ + uint32_t oldSize, newSize; + + do { + oldSize = sHeapSize; + newSize = oldSize + incr; + + if (newSize > sHeapMaxSize) { + r->_errno = ENOMEM; + return (void *)-1; + } + } while (!OSCompareAndSwapAtomic(&sHeapSize, oldSize, newSize)); + + return sHeapBase + oldSize; +} + +void +__init_wut_sbrk_heap() +{ + MEMExpandedHeap *heap = (MEMExpandedHeap *)MEMGetBaseHeapHandle(MEM_BASE_HEAP_MEM2); + uint32_t freeSize = MEMGetAllocatableSizeForExpHeapEx(heap, 0x1000); + + sHeapMaxSize = (uint32_t)(0.9f * (float)freeSize) & ~0xFFF; + sHeapBase = (uint8_t *)MEMAllocFromExpHeapEx(heap, sHeapMaxSize, 0x1000); + sHeapSize = 0; +} + +void +__fini_wut_sbrk_heap() +{ + MEMExpandedHeap *heap = (MEMExpandedHeap *)MEMGetBaseHeapHandle(MEM_BASE_HEAP_MEM2); + MEMFreeToExpHeap(heap, sHeapBase); +}