wutnewlib: implement new unified threading syscalls (replaces wutstdc++) (#434)
Some checks failed
C/C++ CI / ubuntu-latest (push) Has been cancelled

This commit is contained in:
fincs 2026-01-25 19:33:25 +01:00 committed by GitHub
parent 26ed8f3b39
commit afa43f676d
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
16 changed files with 300 additions and 924 deletions

View File

@ -16,7 +16,6 @@ TARGET := wut
SOURCES := cafe \
libraries/wutcrt \
libraries/wutnewlib \
libraries/wutstdc++ \
libraries/wutmalloc \
libraries/wutdevoptab \
libraries/wutsocket \

View File

@ -2,8 +2,6 @@
void
__init_wut_newlib();
void
__init_wut_stdcpp();
void
__init_wut_devoptab();
void __attribute__((weak))
__init_wut_socket();
@ -11,8 +9,6 @@ __init_wut_socket();
void
__fini_wut_newlib();
void
__fini_wut_stdcpp();
void
__fini_wut_devoptab();
void __attribute__((weak))
__fini_wut_socket();
@ -21,7 +17,6 @@ void __attribute__((weak))
__init_wut()
{
__init_wut_newlib();
__init_wut_stdcpp();
__init_wut_devoptab();
if (&__init_wut_socket) __init_wut_socket();
}
@ -31,6 +26,5 @@ __fini_wut()
{
if (&__fini_wut_socket) __fini_wut_socket();
__fini_wut_devoptab();
__fini_wut_stdcpp();
__fini_wut_newlib();
}

View File

@ -3,7 +3,7 @@
void
__init_wut_sbrk_heap(MEMHeapHandle heapHandle);
void
__init_wut_malloc_lock();
__init_wut_thread();
void
__init_wut_defaultheap();
@ -13,6 +13,6 @@ __preinit_user(MEMHeapHandle *mem1,
MEMHeapHandle *mem2)
{
__init_wut_sbrk_heap(*mem2);
__init_wut_malloc_lock();
__init_wut_thread();
__init_wut_defaultheap();
}

View File

@ -1,80 +0,0 @@
#include "wut_newlib.h"
#include <coreinit/atomic.h>
#include <coreinit/mutex.h>
#define MAX_LOCKS 16
static OSMutex sLibcLocks[MAX_LOCKS];
static volatile uint32_t sLibcLockUsedMask = 0;
static inline bool
__wut_is_lock_valid(int *lock)
{
return lock && *lock >= 0 && *lock < MAX_LOCKS;
}
int
__wut_lock_init(int *lock,
int recursive)
{
if (!lock) {
return -1;
}
int slot;
uint32_t new_mask;
uint32_t cur_mask = sLibcLockUsedMask;
do {
slot = __builtin_ffs(~cur_mask) - 1;
if (slot < 0 || slot >= MAX_LOCKS) break;
new_mask = cur_mask | (1U << slot);
} while (!OSCompareAndSwapAtomicEx(&sLibcLockUsedMask, cur_mask, new_mask, &cur_mask));
if (slot < 0 || slot >= MAX_LOCKS) {
return -1;
}
*lock = slot;
OSInitMutex(&sLibcLocks[*lock]);
return 0;
}
int
__wut_lock_close(int *lock)
{
if (!__wut_is_lock_valid(lock)) {
return -1;
}
uint32_t new_mask;
uint32_t cur_mask = sLibcLockUsedMask;
do {
new_mask = cur_mask & ~(1U << *lock);
} while (!OSCompareAndSwapAtomicEx(&sLibcLockUsedMask, cur_mask, new_mask, &cur_mask));
*lock = -1;
return 0;
}
int
__wut_lock_acquire(int *lock)
{
if (!__wut_is_lock_valid(lock)) {
return -1;
}
OSLockMutex(&sLibcLocks[*lock]);
return 0;
}
int
__wut_lock_release(int *lock)
{
if (!__wut_is_lock_valid(lock)) {
return -1;
}
OSUnlockMutex(&sLibcLocks[*lock]);
return 0;
}

View File

@ -1,23 +0,0 @@
#include "wut_newlib.h"
#include <coreinit/spinlock.h>
static OSSpinLock sMallocSpinLock;
void
__wut_malloc_lock(struct _reent *r)
{
OSUninterruptibleSpinLock_Acquire(&sMallocSpinLock);
}
void
__wut_malloc_unlock(struct _reent *r)
{
OSUninterruptibleSpinLock_Release(&sMallocSpinLock);
}
void
__init_wut_malloc_lock()
{
OSInitSpinLock(&sMallocSpinLock);
}

View File

@ -71,65 +71,6 @@ _sbrk_r(struct _reent *ptr, ptrdiff_t incr)
return __wut_sbrk_r(ptr, incr);
}
void
__syscall_lock_init(int *lock)
{
__wut_lock_init(lock, 0);
}
void
__syscall_lock_acquire(int *lock)
{
__wut_lock_acquire(lock);
}
void
__syscall_lock_release(int *lock)
{
__wut_lock_release(lock);
}
void
__syscall_lock_close(int *lock)
{
__wut_lock_close(lock);
}
void
__syscall_lock_init_recursive(_LOCK_T *lock)
{
__wut_lock_init(lock, 1);
}
void
__syscall_lock_acquire_recursive(int *lock)
{
__wut_lock_acquire(lock);
}
void
__syscall_lock_release_recursive(int *lock)
{
__wut_lock_release(lock);
}
void
__syscall_lock_close_recursive(int *lock)
{
__wut_lock_close(lock);
}
void
__syscall_malloc_lock(struct _reent *ptr)
{
return __wut_malloc_lock(ptr);
}
void
__syscall_malloc_unlock(struct _reent *ptr)
{
return __wut_malloc_unlock(ptr);
}
struct _reent *
__syscall_getreent(void)
{

View File

@ -6,21 +6,14 @@
#include <sys/reent.h>
#include <sys/time.h>
#define __WUT_MAX_KEYS (128)
#define __WUT_STACK_SIZE (128 * 1024)
#define __WUT_KEY_THREAD_SPECIFIC_ID WUT_THREAD_SPECIFIC_0
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);

View File

@ -0,0 +1,293 @@
#include "wut_newlib.h"
#include <string.h>
#include <coreinit/atomic.h>
#include <coreinit/core.h>
#include <coreinit/fastcondition.h>
#include <coreinit/fastmutex.h>
#include <coreinit/memdefaultheap.h>
#include <coreinit/spinlock.h>
#include <coreinit/thread.h>
static OSSpinLock sSyncSpinLock;
static OSSpinLock sMallocSpinLock;
void
__init_wut_thread()
{
OSInitSpinLock(&sSyncSpinLock);
OSInitSpinLock(&sMallocSpinLock);
}
static OSFastMutex *
__wut_get_mutex(_LOCK_T *lock)
{
if (*lock) {
return (OSFastMutex *)*lock;
}
OSUninterruptibleSpinLock_Acquire(&sSyncSpinLock);
OSFastMutex *m = (OSFastMutex *)*lock;
if (!m) {
m = MEMAllocFromDefaultHeap(sizeof(OSFastMutex));
OSFastMutex_Init(m, NULL);
*lock = (uint32_t)m;
}
OSUninterruptibleSpinLock_Release(&sSyncSpinLock);
return m;
}
static OSFastCondition *
__wut_get_cond(_COND_T *cond)
{
if (*cond) {
return (OSFastCondition *)*cond;
}
OSUninterruptibleSpinLock_Acquire(&sSyncSpinLock);
OSFastCondition *c = (OSFastCondition *)*cond;
if (!c) {
c = MEMAllocFromDefaultHeap(sizeof(OSFastCondition));
OSFastCond_Init(c, NULL);
*cond = (uint32_t)c;
}
OSUninterruptibleSpinLock_Release(&sSyncSpinLock);
return c;
}
void
__SYSCALL(malloc_lock)(struct _reent *ptr)
{
OSUninterruptibleSpinLock_Acquire(&sMallocSpinLock);
}
void
__SYSCALL(malloc_unlock)(struct _reent *ptr)
{
OSUninterruptibleSpinLock_Release(&sMallocSpinLock);
}
void
__SYSCALL(lock_close)(_LOCK_T *lock)
{
if (*lock) {
MEMFreeToDefaultHeap((void *)*lock);
*lock = 0;
}
}
void
__SYSCALL(lock_acquire)(_LOCK_T *lock)
{
OSFastMutex_Lock(__wut_get_mutex(lock));
}
int
__SYSCALL(lock_try_acquire)(_LOCK_T *lock)
{
return OSFastMutex_TryLock(__wut_get_mutex(lock));
}
void
__SYSCALL(lock_release)(_LOCK_T *lock)
{
OSFastMutex_Unlock(__wut_get_mutex(lock));
}
void
__SYSCALL(lock_close_recursive)(_LOCK_RECURSIVE_T *lock)
{
__SYSCALL(lock_close)
(&lock->lock);
}
void
__SYSCALL(lock_acquire_recursive)(_LOCK_RECURSIVE_T *lock)
{
__SYSCALL(lock_acquire)
(&lock->lock);
}
int32_t
__SYSCALL(lock_try_acquire_recursive)(_LOCK_RECURSIVE_T *lock)
{
return __SYSCALL(lock_try_acquire)(&lock->lock);
}
void
__SYSCALL(lock_release_recursive)(_LOCK_RECURSIVE_T *lock)
{
__SYSCALL(lock_release)
(&lock->lock);
}
void
__SYSCALL(cond_close)(_COND_T *cond)
{
if (*cond) {
MEMFreeToDefaultHeap((void *)*cond);
*cond = 0;
}
}
int
__SYSCALL(cond_signal)(_COND_T *cond)
{
OSFastCond_Signal(__wut_get_cond(cond)); // XX: this is broadcast
return 0;
}
int
__SYSCALL(cond_broadcast)(_COND_T *cond)
{
OSFastCond_Signal(__wut_get_cond(cond));
return 0;
}
typedef struct
{
OSFastCondition *cond;
bool timed_out;
} __wut_condwait_t;
static void
__wut_cond_alarmcb(OSAlarm *alarm, OSContext *context)
{
__wut_condwait_t *data = OSGetAlarmUserData(alarm);
data->timed_out = true;
OSFastCond_Signal(data->cond);
}
int
__SYSCALL(cond_wait)(_COND_T *cond, _LOCK_T *lock, uint64_t timeout_ns)
{
if (timeout_ns == UINT64_MAX) {
OSFastCond_Wait(__wut_get_cond(cond), __wut_get_mutex(lock));
return 0;
}
__wut_condwait_t data;
data.cond = __wut_get_cond(cond);
data.timed_out = false;
OSAlarm alarm;
OSCreateAlarm(&alarm);
OSSetAlarmUserData(&alarm, &data);
OSSetAlarm(&alarm, OSNanosecondsToTicks(timeout_ns), __wut_cond_alarmcb);
OSFastCond_Wait(data.cond, __wut_get_mutex(lock));
OSCancelAlarm(&alarm);
return data.timed_out ? ETIMEDOUT : 0;
}
int
__SYSCALL(cond_wait_recursive)(_COND_T *cond, _LOCK_RECURSIVE_T *lock, uint64_t timeout_ns)
{
return __SYSCALL(cond_wait)(cond, &lock->lock, timeout_ns);
}
struct __pthread_t
{
OSThread base;
};
int
__SYSCALL(thread_create)(struct __pthread_t **thread, void *(*func)(void *), void *arg, void *stack_addr, size_t stack_size)
{
if (!stack_size) {
stack_size = __WUT_STACK_SIZE;
}
uint32_t alloc_size = sizeof(struct __pthread_t);
alloc_size = (alloc_size + 15) & ~15;
stack_size = stack_size & ~15;
if (!stack_addr) {
alloc_size += stack_size;
}
struct __pthread_t *t = MEMAllocFromDefaultHeapEx(alloc_size, 0x10);
if (!t) {
return ENOMEM;
}
memset(t, 0, sizeof(*t));
if (!stack_addr) {
stack_addr = (char *)t + alloc_size;
} else {
stack_addr = (char *)stack_addr + stack_size;
}
BOOL ok = OSCreateThread(
&t->base,
(OSThreadEntryPointFn)func,
(int32_t)arg,
NULL,
stack_addr,
stack_size,
16,
OS_THREAD_ATTRIB_AFFINITY_ANY);
if (!ok) {
MEMFreeToDefaultHeap(t);
return EINVAL;
}
*thread = t;
OSSetThreadDeallocator(&t->base, (OSThreadDeallocatorFn)MEMFreeToDefaultHeap);
//XX: OSSetThreadCleanupCallback: use to free TLS slots
// Enable timeslicing, using 1ms as the thread run quantum
OSSetThreadRunQuantum(&t->base, 1000);
OSResumeThread(&t->base);
return 0;
}
void *
__SYSCALL(thread_join)(struct __pthread_t *thread)
{
int res = 0;
OSJoinThread(&thread->base, &res); // XX: assert?
return (void *)res;
}
int
__SYSCALL(thread_detach)(struct __pthread_t *thread)
{
OSDetachThread(&thread->base);
return 0;
}
void
__SYSCALL(thread_exit)(void *value)
{
OSExitThread((int)value);
}
struct __pthread_t *
__SYSCALL(thread_self)(void)
{
return (struct __pthread_t *)OSGetCurrentThread();
}
int
sched_yield(void)
{
OSYieldThread();
return 0;
}
int
sched_getcpu(void)
{
return OSGetCoreId();
}

View File

@ -1,197 +0,0 @@
#include "wut_gthread.h"
#include <bit>
#include <bits/gthr-default.h>
static constexpr __wut_key_t
gthread_key_to_wut(__gthread_key_t key)
{
__wut_key_t dst = {};
static_assert(sizeof(__wut_key_t) == sizeof(__gthread_key_t), "Incompatible definition of thread local key type");
__builtin_memcpy(&dst, &key, sizeof(dst));
return dst;
}
extern "C" {
int
__gthr_impl_active(void)
{
return 1;
}
int
__gthr_impl_create(__gthread_t *__threadid, void *(*__func)(void *), void *__args)
{
return __wut_thread_create((OSThread **)__threadid, __func, __args);
}
int
__gthr_impl_join(__gthread_t __threadid, void **__value_ptr)
{
return __wut_thread_join((OSThread *)__threadid, __value_ptr);
}
int
__gthr_impl_detach(__gthread_t __threadid)
{
return __wut_thread_detach((OSThread *)__threadid);
}
int
__gthr_impl_equal(__gthread_t __t1, __gthread_t __t2)
{
return __wut_thread_equal((OSThread *)__t1, (OSThread *)__t2);
}
__gthread_t
__gthr_impl_self(void)
{
return __wut_thread_self();
}
int
__gthr_impl_yield(void)
{
return __wut_thread_yield();
}
int
__gthr_impl_once(__gthread_once_t *__once, void (*__func)(void))
{
return __wut_once((__wut_once_t *)__once, __func);
}
int
__gth_impl_key_create(__gthread_key_t *__key, void (*__dtor)(void *))
{
return __wut_key_create((__wut_key_t *)__key, __dtor);
}
int
__gthr_impl_key_delete(__gthread_key_t __key)
{
return __wut_key_delete(gthread_key_to_wut(__key));
}
void *
__gthr_impl_getspecific(__gthread_key_t __key)
{
return __wut_getspecific(gthread_key_to_wut(__key));
}
int
__gthr_impl_setspecific(__gthread_key_t __key, const void *__ptr)
{
return __wut_setspecific(gthread_key_to_wut(__key), __ptr);
}
void
__gthr_impl_mutex_init_function(__gthread_mutex_t *__mutex)
{
return __wut_mutex_init_function((OSMutex *)__mutex);
}
int
__gthr_impl_mutex_destroy(__gthread_mutex_t *__mutex)
{
return __wut_mutex_destroy((OSMutex *)__mutex);
}
int
__gthr_impl_mutex_lock(__gthread_mutex_t *__mutex)
{
return __wut_mutex_lock((OSMutex *)__mutex);
}
int
__gthr_impl_mutex_trylock(__gthread_mutex_t *__mutex)
{
return __wut_mutex_trylock((OSMutex *)__mutex);
}
int
__gthr_impl_mutex_unlock(__gthread_mutex_t *__mutex)
{
return __wut_mutex_unlock((OSMutex *)__mutex);
}
int
__gthr_impl_recursive_mutex_init_function(__gthread_recursive_mutex_t *__mutex)
{
return __wut_recursive_mutex_init_function((OSMutex *)__mutex);
}
int
__gthr_impl_recursive_mutex_lock(__gthread_recursive_mutex_t *__mutex)
{
return __wut_recursive_mutex_lock((OSMutex *)__mutex);
}
int
__gthr_impl_recursive_mutex_trylock(__gthread_recursive_mutex_t *__mutex)
{
return __wut_recursive_mutex_trylock((OSMutex *)__mutex);
}
int
__gthr_impl_recursive_mutex_unlock(__gthread_recursive_mutex_t *__mutex)
{
return __wut_recursive_mutex_unlock((OSMutex *)__mutex);
}
int
__gthr_impl_recursive_mutex_destroy(__gthread_recursive_mutex_t *__mutex)
{
return __wut_recursive_mutex_destroy((OSMutex *)__mutex);
}
void
__gthr_impl_cond_init_function(__gthread_cond_t *__cond)
{
return __wut_cond_init_function((OSCondition *)__cond);
}
int
__gthr_impl_cond_broadcast(__gthread_cond_t *__cond)
{
return __wut_cond_broadcast((OSCondition *)__cond);
}
int
__gthr_impl_cond_signal(__gthread_cond_t *__cond)
{
return __wut_cond_signal((OSCondition *)__cond);
}
int
__gthr_impl_cond_wait(__gthread_cond_t *__cond, __gthread_mutex_t *__mutex)
{
return __wut_cond_wait((OSCondition *)__cond, (OSMutex *)__mutex);
}
int
__gthr_impl_cond_timedwait(__gthread_cond_t *__cond, __gthread_mutex_t *__mutex, const __gthread_time_t *__abs_timeout)
{
return __wut_cond_timedwait((OSCondition *)__cond, (OSMutex *)__mutex, __abs_timeout);
}
int
__gthr_impl_cond_wait_recursive(__gthread_cond_t *__cond, __gthread_recursive_mutex_t *__mutex)
{
return __wut_cond_wait_recursive((OSCondition *)__cond, (OSMutex *)__mutex);
}
int
__gthr_impl_cond_destroy(__gthread_cond_t *__cond)
{
return __wut_cond_destroy((OSCondition *)__cond);
}
void
__init_wut_stdcpp()
{
}
void
__fini_wut_stdcpp()
{
}
}

View File

@ -1,128 +0,0 @@
#pragma once
#include <bits/gthr-default.h>
#include <coreinit/atomic.h>
#include <coreinit/condition.h>
#include <coreinit/mutex.h>
#include <coreinit/thread.h>
#include "../wutnewlib/wut_thread_specific.h"
#define __WUT_MAX_KEYS (128)
#define __WUT_STACK_SIZE (128 * 1024)
#define __WUT_ONCE_VALUE_INIT (0)
#define __WUT_ONCE_VALUE_STARTED (1)
#define __WUT_ONCE_VALUE_DONE (2)
#define __WUT_KEY_THREAD_SPECIFIC_ID WUT_THREAD_SPECIFIC_0
typedef volatile uint32_t __wut_once_t;
typedef struct
{
uint32_t index;
} __wut_key_t;
void
__init_wut_gthread();
int
__wut_active_p();
int
__wut_thread_create(OSThread **outThread,
void *(*func)(void *),
void *args);
int
__wut_thread_join(OSThread *thread,
void **outValue);
int
__wut_thread_detach(OSThread *thread);
int
__wut_thread_equal(OSThread *thread1,
OSThread *thread2);
OSThread *
__wut_thread_self();
int
__wut_thread_yield();
int
__wut_once(__wut_once_t *once,
void (*func)(void));
void
__wut_key_cleanup(OSThread *thread);
int
__wut_key_create(__wut_key_t *key,
void (*dtor)(void *));
int
__wut_key_delete(__wut_key_t key);
void *
__wut_getspecific(__wut_key_t key);
int
__wut_setspecific(__wut_key_t key,
const void *ptr);
void
__wut_mutex_init_function(OSMutex *mutex);
int
__wut_mutex_destroy(OSMutex *mutex);
int
__wut_mutex_lock(OSMutex *mutex);
int
__wut_mutex_trylock(OSMutex *mutex);
int
__wut_mutex_unlock(OSMutex *mutex);
int
__wut_recursive_mutex_init_function(OSMutex *mutex);
int
__wut_recursive_mutex_lock(OSMutex *mutex);
int
__wut_recursive_mutex_trylock(OSMutex *mutex);
int
__wut_recursive_mutex_unlock(OSMutex *mutex);
int
__wut_recursive_mutex_destroy(OSMutex *mutex);
void
__wut_cond_init_function(OSCondition *cond);
int
__wut_cond_broadcast(OSCondition *cond);
int
__wut_cond_signal(OSCondition *cond);
int
__wut_cond_wait(OSCondition *cond,
OSMutex *mutex);
int
__wut_cond_timedwait(OSCondition *cond,
OSMutex *mutex,
const __gthread_time_t *abs_timeout);
int
__wut_cond_wait_recursive(OSCondition *cond,
OSMutex *mutex);
int
__wut_cond_destroy(OSCondition *cond);

View File

@ -1,97 +0,0 @@
#include "wut_gthread.h"
#include "../wutnewlib/wut_clock.h"
#include <sys/errno.h>
#include <sys/time.h>
#include <coreinit/alarm.h>
#include <coreinit/systeminfo.h>
#include <coreinit/time.h>
void
__wut_cond_init_function(OSCondition *cond)
{
OSInitCond(cond);
}
int
__wut_cond_broadcast(OSCondition *cond)
{
OSSignalCond(cond);
return 0;
}
int
__wut_cond_signal(OSCondition *cond)
{
OSSignalCond(cond);
return 0;
}
int
__wut_cond_wait(OSCondition *cond,
OSMutex *mutex)
{
OSWaitCond(cond, mutex);
return 0;
}
struct __wut_cond_timedwait_data_t
{
OSCondition *cond;
bool timed_out;
};
static void
__wut_cond_timedwait_alarm_callback(OSAlarm *alarm,
OSContext *context)
{
__wut_cond_timedwait_data_t *data = (__wut_cond_timedwait_data_t *)OSGetAlarmUserData(alarm);
data->timed_out = true;
OSSignalCond(data->cond);
}
int
__wut_cond_timedwait(OSCondition *cond, OSMutex *mutex, const __gthread_time_t *abs_timeout)
{
__wut_cond_timedwait_data_t data;
data.timed_out = false;
data.cond = cond;
OSTime time = OSGetTime();
OSTime timeout =
OSSecondsToTicks(abs_timeout->tv_sec - EPOCH_DIFF_SECS(WIIU_OSTIME_EPOCH_YEAR)) +
OSNanosecondsToTicks(abs_timeout->tv_nsec);
// Already timed out!
if (timeout <= time) {
return ETIMEDOUT;
}
// Set an alarm
OSAlarm alarm;
OSCreateAlarm(&alarm);
OSSetAlarmUserData(&alarm, &data);
OSSetAlarm(&alarm, timeout - time,
&__wut_cond_timedwait_alarm_callback);
// Wait on the condition
OSWaitCond(cond, mutex);
OSCancelAlarm(&alarm);
return data.timed_out ? ETIMEDOUT : 0;
}
int
__wut_cond_wait_recursive(OSCondition *cond,
OSMutex *mutex)
{
OSWaitCond(cond, mutex);
return 0;
}
int
__wut_cond_destroy(OSCondition *cond)
{
return 0;
}

View File

@ -1,119 +0,0 @@
#include "wut_gthread.h"
#include <malloc.h>
#include <string.h>
#include <sys/errno.h>
struct __wut_key_table_entry
{
bool in_use;
void (*dtor)(void *);
};
static __wut_key_table_entry key_table[__WUT_MAX_KEYS];
static OSMutex key_mutex;
static __wut_once_t init_once_control = __WUT_ONCE_VALUE_INIT;
static void
init()
{
__wut_mutex_init_function(&key_mutex);
memset(key_table, 0, sizeof(key_table));
}
int
__wut_key_create(__wut_key_t *key,
void (*dtor)(void *))
{
int res = EAGAIN;
__wut_once(&init_once_control, init);
__wut_mutex_lock(&key_mutex);
for (uint32_t i = 0; i < __WUT_MAX_KEYS; ++i) {
if (key_table[i].in_use) {
continue;
}
key_table[i].in_use = 1;
key_table[i].dtor = dtor;
res = 0;
key->index = i;
break;
}
__wut_mutex_unlock(&key_mutex);
return res;
}
int
__wut_key_delete(__wut_key_t key)
{
__wut_mutex_lock(&key_mutex);
key_table[key.index].in_use = 0;
key_table[key.index].dtor = NULL;
__wut_mutex_unlock(&key_mutex);
return -1;
}
static const void **
__wut_get_thread_keys()
{
const void **keys = (const void **)wut_get_thread_specific(__WUT_KEY_THREAD_SPECIFIC_ID);
if (!keys) {
keys = (const void **)malloc(sizeof(void *) * sizeof(__WUT_MAX_KEYS));
if (!keys) {
return NULL;
}
memset(keys, 0, sizeof(void *) * sizeof(__WUT_MAX_KEYS));
wut_set_thread_specific(__WUT_KEY_THREAD_SPECIFIC_ID, keys);
}
return keys;
}
void *
__wut_getspecific(__wut_key_t key)
{
const void **keys = __wut_get_thread_keys();
if (!keys) {
return NULL;
}
return (void *)(keys[key.index]);
}
int
__wut_setspecific(__wut_key_t key,
const void *ptr)
{
const void **keys = __wut_get_thread_keys();
if (!keys) {
return -1;
}
keys[key.index] = ptr;
return 0;
}
void
__wut_key_cleanup(OSThread *thread)
{
void **keys = (void **)wut_get_thread_specific(__WUT_KEY_THREAD_SPECIFIC_ID);
if (!keys) {
return;
}
__wut_mutex_lock(&key_mutex);
for (int i = 0; i < __WUT_MAX_KEYS; ++i) {
if (key_table[i].in_use && key_table[i].dtor && keys[i]) {
key_table[i].dtor(keys[i]);
}
}
__wut_mutex_unlock(&key_mutex);
free(keys);
}

View File

@ -1,37 +0,0 @@
#include "wut_gthread.h"
void
__wut_mutex_init_function(OSMutex *mutex)
{
OSInitMutex(mutex);
}
int
__wut_mutex_lock(OSMutex *mutex)
{
OSLockMutex(mutex);
return 0;
}
int
__wut_mutex_trylock(OSMutex *mutex)
{
if (!OSTryLockMutex(mutex)) {
return -1;
}
return 0;
}
int
__wut_mutex_unlock(OSMutex *mutex)
{
OSUnlockMutex(mutex);
return 0;
}
int
__wut_mutex_destroy(OSMutex *mutex)
{
return 0;
}

View File

@ -1,23 +0,0 @@
#include "wut_gthread.h"
int
__wut_once(__wut_once_t *once,
void (*func)(void))
{
uint32_t value = 0;
if (OSCompareAndSwapAtomicEx(once,
__WUT_ONCE_VALUE_INIT,
__WUT_ONCE_VALUE_STARTED,
&value)) {
func();
OSSwapAtomic(once,
__WUT_ONCE_VALUE_DONE);
} else if (value != __WUT_ONCE_VALUE_DONE) {
while (!OSCompareAndSwapAtomic(once,
__WUT_ONCE_VALUE_DONE,
__WUT_ONCE_VALUE_DONE));
}
return 0;
}

View File

@ -1,38 +0,0 @@
#include "wut_gthread.h"
int
__wut_recursive_mutex_init_function(OSMutex *mutex)
{
OSInitMutex(mutex);
return 0;
}
int
__wut_recursive_mutex_lock(OSMutex *mutex)
{
OSLockMutex(mutex);
return 0;
}
int
__wut_recursive_mutex_trylock(OSMutex *mutex)
{
if (!OSTryLockMutex(mutex)) {
return -1;
}
return 0;
}
int
__wut_recursive_mutex_unlock(OSMutex *mutex)
{
OSUnlockMutex(mutex);
return 0;
}
int
__wut_recursive_mutex_destroy(OSMutex *mutex)
{
return 0;
}

View File

@ -1,102 +0,0 @@
#include "wut_gthread.h"
#include <malloc.h>
#include <stdint.h>
#include <string.h>
#include <sys/errno.h>
uint32_t __attribute__((weak)) __wut_thread_default_stack_size = __WUT_STACK_SIZE;
static void
__wut_thread_deallocator(OSThread *thread,
void *stack)
{
free(thread);
free(stack);
}
static void
__wut_thread_cleanup(OSThread *thread, void *stack)
{
__wut_key_cleanup(thread);
}
int
__wut_thread_create(OSThread **outThread,
void *(*entryPoint)(void *),
void *entryArgs)
{
OSThread *thread = (OSThread *)memalign(16, sizeof(OSThread));
if (!thread) {
return ENOMEM;
}
memset(thread, 0, sizeof(OSThread));
char *stack = (char *)memalign(16, __wut_thread_default_stack_size);
if (!stack) {
free(thread);
return ENOMEM;
}
if (!OSCreateThread(thread,
(OSThreadEntryPointFn)entryPoint,
(int)entryArgs,
NULL,
stack + __wut_thread_default_stack_size,
__wut_thread_default_stack_size,
16,
OS_THREAD_ATTRIB_AFFINITY_ANY)) {
free(thread);
free(stack);
return EINVAL;
}
*outThread = thread;
OSSetThreadDeallocator(thread, &__wut_thread_deallocator);
OSSetThreadCleanupCallback(thread, &__wut_thread_cleanup);
// Set a thread run quantum to 1 millisecond, to force the threads to
// behave more like pre-emptive scheduling rather than co-operative.
OSSetThreadRunQuantum(thread, 1000);
OSResumeThread(thread);
return 0;
}
int
__wut_thread_join(OSThread *thread,
void **outValue)
{
if (!OSJoinThread(thread, (int *)outValue)) {
return EINVAL;
}
return 0;
}
int
__wut_thread_detach(OSThread *thread)
{
OSDetachThread(thread);
return 0;
}
int
__wut_thread_equal(OSThread *thread1,
OSThread *thread2)
{
return thread1 == thread2;
}
OSThread *
__wut_thread_self()
{
return OSGetCurrentThread();
}
int
__wut_thread_yield()
{
OSYieldThread();
return 0;
}