wutnewlib: Implement the new __syscalls from upcoming devkitPPC release.

This commit is contained in:
James Benton 2018-05-28 11:40:22 +01:00
parent 35d05358c4
commit f7a698388c
11 changed files with 302 additions and 202 deletions

View File

@ -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

View File

@ -1,16 +0,0 @@
#include <coreinit/thread.h>
#include <coreinit/systeminfo.h>
#include <coreinit/time.h>
#include <unistd.h>
unsigned sleep(unsigned seconds)
{
OSSleepTicks(OSSeconds(seconds));
return 0;
}
int usleep(useconds_t microseconds)
{
OSSleepTicks(OSMicroseconds(microseconds));
return 0;
}

View File

@ -1,184 +0,0 @@
#include <wut.h>
#include <coreinit/atomic.h>
#include <coreinit/baseheap.h>
#include <coreinit/exit.h>
#include <coreinit/expandedheap.h>
#include <coreinit/mutex.h>
#include <coreinit/time.h>
#include <malloc.h>
#include <sys/errno.h>
#include <sys/iosupport.h>
#include <sys/reent.h>
#include <sys/time.h>
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();
}

View File

@ -0,0 +1,66 @@
#include "wut_newlib.h"
#include <coreinit/systeminfo.h>
#include <coreinit/time.h>
// 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;
}

View File

@ -0,0 +1,24 @@
#include "wut_newlib.h"
#include <coreinit/time.h>
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;
}

View File

@ -0,0 +1,59 @@
#include "wut_newlib.h"
#include <coreinit/mutex.h>
#include <malloc.h>
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;
}

View File

@ -0,0 +1,23 @@
#include "wut_newlib.h"
#include <coreinit/mutex.h>
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);
}

View File

@ -0,0 +1,16 @@
#include "wut_newlib.h"
#include <coreinit/thread.h>
#include <coreinit/systeminfo.h>
#include <coreinit/time.h>
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;
}

View File

@ -0,0 +1,34 @@
#include "wut_newlib.h"
#include <coreinit/exit.h>
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();
}

View File

@ -0,0 +1,27 @@
#ifndef __WUT_NEWLIB_H
#define __WUT_NEWLIB_H
#include <sys/errno.h>
#include <sys/reent.h>
#include <sys/time.h>
#include <sys/iosupport.h>
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

View File

@ -0,0 +1,46 @@
#include "wut_newlib.h"
#include <coreinit/atomic.h>
#include <coreinit/baseheap.h>
#include <coreinit/expandedheap.h>
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);
}