mirror of
https://github.com/wiiu-env/wut.git
synced 2025-01-06 14:18:15 +01:00
Change to using new gthreads implementation.
Assuming that --enable-threads=dkp gets merged into devkitPPC r31... :)
This commit is contained in:
parent
37228a095d
commit
ac8a42fa7c
@ -3,12 +3,14 @@
|
||||
#include <coreinit/time.h>
|
||||
#include <unistd.h>
|
||||
|
||||
unsigned sleep(unsigned seconds) {
|
||||
unsigned sleep(unsigned seconds)
|
||||
{
|
||||
OSSleepTicks(OSSeconds(seconds));
|
||||
return 0;
|
||||
}
|
||||
|
||||
int usleep(useconds_t microseconds) {
|
||||
int usleep(useconds_t microseconds)
|
||||
{
|
||||
OSSleepTicks(OSMicroseconds(microseconds));
|
||||
return 0;
|
||||
}
|
||||
|
@ -172,10 +172,16 @@ __init_syscall_array()
|
||||
__syscalls.gettod_r = __libwut_gettod_r;
|
||||
}
|
||||
|
||||
extern void __init_wut_gthread() __attribute__((weak));
|
||||
|
||||
void
|
||||
__init_wut_newlibc()
|
||||
{
|
||||
__init_libc_heap();
|
||||
__init_malloc_lock();
|
||||
__init_syscall_array();
|
||||
|
||||
if (__init_wut_gthread) {
|
||||
__init_wut_gthread();
|
||||
}
|
||||
}
|
||||
|
@ -2,18 +2,13 @@ cmake_minimum_required(VERSION 3.2)
|
||||
project(wutstdc++ CXX)
|
||||
|
||||
add_library(wutstdc++
|
||||
condition_variable.cc
|
||||
future.cc
|
||||
gthread.cc
|
||||
gthread_cond.cc
|
||||
gthread_keys.cc
|
||||
gthread_mutex.cc
|
||||
gthread_once.cc
|
||||
gthread_recursive_mutex.cc
|
||||
mutex.cc
|
||||
shared_ptr.cc
|
||||
thread.cc
|
||||
include/bits/gthr-default.h)
|
||||
wut_gthread.cc
|
||||
wut_gthread_cond.cc
|
||||
wut_gthread_keys.cc
|
||||
wut_gthread_mutex.cc
|
||||
wut_gthread_once.cc
|
||||
wut_gthread_recursive_mutex.cc
|
||||
wut_gthread_thread.cc)
|
||||
|
||||
target_compile_definitions(wutstdc++
|
||||
PRIVATE _GLIBCXX_HAS_GTHREADS)
|
||||
|
@ -1,158 +0,0 @@
|
||||
// condition_variable -*- C++ -*-
|
||||
|
||||
// Copyright (C) 2008-2018 Free Software Foundation, Inc.
|
||||
//
|
||||
// This file is part of the GNU ISO C++ Library. This library is free
|
||||
// software; you can redistribute it and/or modify it under the
|
||||
// terms of the GNU General Public License as published by the
|
||||
// Free Software Foundation; either version 3, or (at your option)
|
||||
// any later version.
|
||||
|
||||
// This library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
|
||||
// Under Section 7 of GPL version 3, you are granted additional
|
||||
// permissions described in the GCC Runtime Library Exception, version
|
||||
// 3.1, as published by the Free Software Foundation.
|
||||
|
||||
// You should have received a copy of the GNU General Public License and
|
||||
// a copy of the GCC Runtime Library Exception along with this program;
|
||||
// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
|
||||
// <http://www.gnu.org/licenses/>.
|
||||
|
||||
#include <condition_variable>
|
||||
#include <cstdlib>
|
||||
|
||||
#if defined(_GLIBCXX_HAS_GTHREADS) && defined(_GLIBCXX_USE_C99_STDINT_TR1)
|
||||
|
||||
namespace std _GLIBCXX_VISIBILITY(default)
|
||||
{
|
||||
_GLIBCXX_BEGIN_NAMESPACE_VERSION
|
||||
|
||||
#ifdef __GTHREAD_COND_INIT
|
||||
condition_variable::condition_variable() noexcept = default;
|
||||
#else
|
||||
condition_variable::condition_variable() noexcept
|
||||
{
|
||||
__GTHREAD_COND_INIT_FUNCTION(&_M_cond);
|
||||
}
|
||||
#endif
|
||||
|
||||
condition_variable::~condition_variable() noexcept
|
||||
{
|
||||
// XXX no thread blocked
|
||||
/* int __e = */ __gthread_cond_destroy(&_M_cond);
|
||||
// if __e == EBUSY then blocked
|
||||
}
|
||||
|
||||
void
|
||||
condition_variable::wait(unique_lock<mutex>& __lock) noexcept
|
||||
{
|
||||
int __e = __gthread_cond_wait(&_M_cond, __lock.mutex()->native_handle());
|
||||
|
||||
if (__e)
|
||||
std::terminate();
|
||||
}
|
||||
|
||||
void
|
||||
condition_variable::notify_one() noexcept
|
||||
{
|
||||
int __e = __gthread_cond_signal(&_M_cond);
|
||||
|
||||
// XXX not in spec
|
||||
// EINVAL
|
||||
if (__e)
|
||||
__throw_system_error(__e);
|
||||
}
|
||||
|
||||
void
|
||||
condition_variable::notify_all() noexcept
|
||||
{
|
||||
int __e = __gthread_cond_broadcast(&_M_cond);
|
||||
|
||||
// XXX not in spec
|
||||
// EINVAL
|
||||
if (__e)
|
||||
__throw_system_error(__e);
|
||||
}
|
||||
|
||||
extern void
|
||||
__at_thread_exit(__at_thread_exit_elt*);
|
||||
|
||||
namespace
|
||||
{
|
||||
__gthread_key_t key;
|
||||
|
||||
void run(void* p)
|
||||
{
|
||||
auto elt = (__at_thread_exit_elt*)p;
|
||||
while (elt)
|
||||
{
|
||||
auto next = elt->_M_next;
|
||||
elt->_M_cb(elt);
|
||||
elt = next;
|
||||
}
|
||||
}
|
||||
|
||||
void run()
|
||||
{
|
||||
auto elt = (__at_thread_exit_elt*)__gthread_getspecific(key);
|
||||
__gthread_setspecific(key, nullptr);
|
||||
run(elt);
|
||||
}
|
||||
|
||||
struct notifier final : __at_thread_exit_elt
|
||||
{
|
||||
notifier(condition_variable& cv, unique_lock<mutex>& l)
|
||||
: cv(&cv), mx(l.release())
|
||||
{
|
||||
_M_cb = ¬ifier::run;
|
||||
__at_thread_exit(this);
|
||||
}
|
||||
|
||||
~notifier()
|
||||
{
|
||||
mx->unlock();
|
||||
cv->notify_all();
|
||||
}
|
||||
|
||||
condition_variable* cv;
|
||||
mutex* mx;
|
||||
|
||||
static void run(void* p) { delete static_cast<notifier*>(p); }
|
||||
};
|
||||
|
||||
|
||||
void key_init() {
|
||||
struct key_s {
|
||||
key_s() { __gthread_key_create (&key, run); }
|
||||
~key_s() { __gthread_key_delete (key); }
|
||||
};
|
||||
static key_s ks;
|
||||
// Also make sure the callbacks are run by std::exit.
|
||||
std::atexit (run);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
__at_thread_exit(__at_thread_exit_elt* elt)
|
||||
{
|
||||
static __gthread_once_t once = __GTHREAD_ONCE_INIT;
|
||||
__gthread_once (&once, key_init);
|
||||
|
||||
elt->_M_next = (__at_thread_exit_elt*)__gthread_getspecific(key);
|
||||
__gthread_setspecific(key, elt);
|
||||
}
|
||||
|
||||
void
|
||||
notify_all_at_thread_exit(condition_variable& cv, unique_lock<mutex> l)
|
||||
{
|
||||
(void) new notifier{cv, l};
|
||||
}
|
||||
|
||||
_GLIBCXX_END_NAMESPACE_VERSION
|
||||
} // namespace
|
||||
|
||||
#endif // _GLIBCXX_HAS_GTHREADS && _GLIBCXX_USE_C99_STDINT_TR1
|
@ -1,62 +0,0 @@
|
||||
// future -*- C++ -*-
|
||||
|
||||
// Copyright (C) 2009-2018 Free Software Foundation, Inc.
|
||||
//
|
||||
// This file is part of the GNU ISO C++ Library. This library is free
|
||||
// software; you can redistribute it and/or modify it under the
|
||||
// terms of the GNU General Public License as published by the
|
||||
// Free Software Foundation; either version 3, or (at your option)
|
||||
// any later version.
|
||||
|
||||
// This library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
|
||||
// Under Section 7 of GPL version 3, you are granted additional
|
||||
// permissions described in the GCC Runtime Library Exception, version
|
||||
// 3.1, as published by the Free Software Foundation.
|
||||
|
||||
// You should have received a copy of the GNU General Public License and
|
||||
// a copy of the GCC Runtime Library Exception along with this program;
|
||||
// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
|
||||
// <http://www.gnu.org/licenses/>.
|
||||
|
||||
#include <future>
|
||||
#include <bits/functexcept.h>
|
||||
|
||||
namespace std _GLIBCXX_VISIBILITY(default)
|
||||
{
|
||||
_GLIBCXX_BEGIN_NAMESPACE_VERSION
|
||||
|
||||
#if defined(_GLIBCXX_HAS_GTHREADS) && defined(_GLIBCXX_USE_C99_STDINT_TR1)
|
||||
__future_base::_Result_base::_Result_base() = default;
|
||||
|
||||
__future_base::_Result_base::~_Result_base() = default;
|
||||
|
||||
void
|
||||
__future_base::_State_baseV2::_Make_ready::_S_run(void* p)
|
||||
{
|
||||
unique_ptr<_Make_ready> mr{static_cast<_Make_ready*>(p)};
|
||||
if (auto state = mr->_M_shared_state.lock())
|
||||
{
|
||||
// Use release MO to synchronize with observers of the ready state.
|
||||
state->_M_status._M_store_notify_all(_Status::__ready,
|
||||
memory_order_release);
|
||||
}
|
||||
}
|
||||
|
||||
// defined in src/c++11/condition_variable.cc
|
||||
extern void
|
||||
__at_thread_exit(__at_thread_exit_elt* elt);
|
||||
|
||||
void
|
||||
__future_base::_State_baseV2::_Make_ready::_M_set()
|
||||
{
|
||||
_M_cb = &_Make_ready::_S_run;
|
||||
__at_thread_exit(this);
|
||||
}
|
||||
#endif
|
||||
|
||||
_GLIBCXX_END_NAMESPACE_VERSION
|
||||
} // namespace std
|
@ -1,78 +0,0 @@
|
||||
#include "include/bits/gthr-default.h"
|
||||
|
||||
static void
|
||||
__gthread_thread_deallocator(OSThread *thread, void *stack)
|
||||
{
|
||||
MEMExpandedHeap *heap = (MEMExpandedHeap *)MEMGetBaseHeapHandle(MEM_BASE_HEAP_MEM2);
|
||||
MEMFreeToExpHeap(heap, thread);
|
||||
MEMFreeToExpHeap(heap, stack);
|
||||
}
|
||||
|
||||
static void
|
||||
__gthread_thread_cleanup(OSThread *thread, void *stack)
|
||||
{
|
||||
__gthread_key_cleanup(thread);
|
||||
}
|
||||
|
||||
int
|
||||
__gthread_create (__gthread_t *__threadid, void *(*__func) (void*), void *__args)
|
||||
{
|
||||
MEMExpandedHeap *heap = (MEMExpandedHeap *)MEMGetBaseHeapHandle(MEM_BASE_HEAP_MEM2);
|
||||
OSThread *thread = (OSThread *)MEMAllocFromExpHeapEx(heap, sizeof(OSThread), 8);
|
||||
char *stack = (char *)MEMAllocFromExpHeapEx(heap, __GTHREAD_STACK_SIZE, 8);
|
||||
memset(thread, 0, sizeof(OSThread));
|
||||
|
||||
if (!OSCreateThread(thread,
|
||||
(OSThreadEntryPointFn)__func,
|
||||
(int)__args,
|
||||
NULL,
|
||||
stack + __GTHREAD_STACK_SIZE,
|
||||
__GTHREAD_STACK_SIZE,
|
||||
16,
|
||||
OS_THREAD_ATTRIB_AFFINITY_ANY)) {
|
||||
MEMFreeToExpHeap((MEMExpandedHeap*)MEMGetBaseHeapHandle(MEM_BASE_HEAP_MEM2), thread);
|
||||
return EINVAL;
|
||||
}
|
||||
|
||||
*__threadid = thread;
|
||||
OSSetThreadDeallocator(thread, &__gthread_thread_deallocator);
|
||||
OSSetThreadCleanupCallback(thread, &__gthread_thread_cleanup);
|
||||
OSResumeThread(thread);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
__gthread_join (__gthread_t __threadid, void **__value_ptr)
|
||||
{
|
||||
if (!OSJoinThread(__threadid, (int *)__value_ptr)) {
|
||||
return EINVAL;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
__gthread_detach (__gthread_t __threadid)
|
||||
{
|
||||
OSDetachThread(__threadid);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
__gthread_equal (__gthread_t __t1, __gthread_t __t2)
|
||||
{
|
||||
return __t1 == __t2;
|
||||
}
|
||||
|
||||
__gthread_t
|
||||
__gthread_self (void)
|
||||
{
|
||||
return OSGetCurrentThread();
|
||||
}
|
||||
|
||||
int
|
||||
__gthread_yield (void)
|
||||
{
|
||||
OSYieldThread();
|
||||
return 0;
|
||||
}
|
@ -1,96 +0,0 @@
|
||||
#include "include/bits/gthr-default.h"
|
||||
|
||||
#include <coreinit/alarm.h>
|
||||
#include <coreinit/systeminfo.h>
|
||||
#include <coreinit/time.h>
|
||||
#include <chrono>
|
||||
|
||||
void
|
||||
__gthread_cond_init_function (__gthread_cond_t *__cond)
|
||||
{
|
||||
OSInitCond(__cond);
|
||||
}
|
||||
|
||||
int
|
||||
__gthread_cond_broadcast (__gthread_cond_t *__cond)
|
||||
{
|
||||
OSSignalCond(__cond);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
__gthread_cond_signal (__gthread_cond_t *__cond)
|
||||
{
|
||||
OSSignalCond(__cond);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
__gthread_cond_wait (__gthread_cond_t *__cond, __gthread_mutex_t *__mutex)
|
||||
{
|
||||
OSWaitCond(__cond, __mutex);
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct TimedWaitData
|
||||
{
|
||||
__gthread_cond_t *cond;
|
||||
bool timed_out;
|
||||
};
|
||||
|
||||
static void
|
||||
__gthread_timedwait_alarm_callback(OSAlarm *alarm, OSContext *context)
|
||||
{
|
||||
TimedWaitData *data = (TimedWaitData *)OSGetAlarmUserData(alarm);
|
||||
data->timed_out = true;
|
||||
OSSignalCond(data->cond);
|
||||
}
|
||||
|
||||
int
|
||||
__gthread_cond_timedwait (__gthread_cond_t *__cond, __gthread_mutex_t *__mutex,
|
||||
const __gthread_time_t *__abs_timeout)
|
||||
{
|
||||
auto time = std::chrono::system_clock::now();
|
||||
auto timeout = std::chrono::system_clock::time_point(
|
||||
std::chrono::seconds(__abs_timeout->tv_sec) +
|
||||
std::chrono::nanoseconds(__abs_timeout->tv_nsec));
|
||||
|
||||
// Already timed out!
|
||||
if (timeout <= time) {
|
||||
return ETIMEDOUT;
|
||||
}
|
||||
|
||||
auto duration =
|
||||
std::chrono::duration_cast<std::chrono::nanoseconds>(timeout - time);
|
||||
|
||||
// Set an alarm
|
||||
OSAlarm alarm;
|
||||
TimedWaitData data;
|
||||
data.timed_out = false;
|
||||
data.cond = __cond;
|
||||
|
||||
OSCreateAlarm(&alarm);
|
||||
OSSetAlarmUserData(&alarm, &data);
|
||||
OSSetAlarm(&alarm, OSNanoseconds(duration.count()),
|
||||
&__gthread_timedwait_alarm_callback);
|
||||
|
||||
// Wait on the condition
|
||||
OSWaitCond(__cond, __mutex);
|
||||
|
||||
OSCancelAlarm(&alarm);
|
||||
return data.timed_out ? ETIMEDOUT : 0;
|
||||
}
|
||||
|
||||
int
|
||||
__gthread_cond_wait_recursive (__gthread_cond_t *__cond,
|
||||
__gthread_recursive_mutex_t *__mutex)
|
||||
{
|
||||
OSWaitCond(__cond, __mutex);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
__gthread_cond_destroy (__gthread_cond_t* __cond)
|
||||
{
|
||||
return 0;
|
||||
}
|
@ -1,98 +0,0 @@
|
||||
#include "include/bits/gthr-default.h"
|
||||
|
||||
struct gthread_key
|
||||
{
|
||||
bool in_use;
|
||||
void (*dtor) (void *);
|
||||
};
|
||||
|
||||
static gthread_key key_table[__GTHREAD_MAX_KEYS];
|
||||
|
||||
static __gthread_mutex_t key_mutex;
|
||||
static __gthread_once_t init_once_control = __GTHREAD_ONCE_INIT;
|
||||
|
||||
static void init()
|
||||
{
|
||||
__GTHREAD_MUTEX_INIT_FUNCTION(&key_mutex);
|
||||
memset(key_table, 0, sizeof(key_table));
|
||||
}
|
||||
|
||||
int
|
||||
__gthread_key_create (__gthread_key_t *__key, void (*__dtor) (void *))
|
||||
{
|
||||
int res = EAGAIN;
|
||||
__gthread_once(&init_once_control, init);
|
||||
__gthread_mutex_lock(&key_mutex);
|
||||
|
||||
for (int i = 0; i < __GTHREAD_MAX_KEYS; ++i) {
|
||||
if (key_table[i].in_use) {
|
||||
continue;
|
||||
}
|
||||
|
||||
key_table[i].in_use = 1;
|
||||
key_table[i].dtor = __dtor;
|
||||
|
||||
res = 0;
|
||||
*__key = (__gthread_key_t)i;
|
||||
break;
|
||||
}
|
||||
|
||||
__gthread_mutex_unlock(&key_mutex);
|
||||
return res;
|
||||
}
|
||||
|
||||
int
|
||||
__gthread_key_delete (__gthread_key_t __key)
|
||||
{
|
||||
__gthread_mutex_lock(&key_mutex);
|
||||
key_table[__key].in_use = 0;
|
||||
key_table[__key].dtor = NULL;
|
||||
__gthread_mutex_unlock(&key_mutex);
|
||||
return -1;
|
||||
}
|
||||
|
||||
static const void **
|
||||
__gthread_get_thread_keys()
|
||||
{
|
||||
const void **keys = (const void **)OSGetThreadSpecific(__GTHREAD_THREAD_SPECIFIC_ID);
|
||||
if (!keys) {
|
||||
MEMExpandedHeap *heap = (MEMExpandedHeap *)MEMGetBaseHeapHandle(MEM_BASE_HEAP_MEM2);
|
||||
keys = (const void **)MEMAllocFromExpHeapEx(heap, sizeof(void *) * sizeof(__GTHREAD_MAX_KEYS), 4);
|
||||
memset(keys, 0, sizeof(void *) * sizeof(__GTHREAD_MAX_KEYS));
|
||||
OSSetThreadSpecific(__GTHREAD_THREAD_SPECIFIC_ID, keys);
|
||||
}
|
||||
|
||||
return keys;
|
||||
}
|
||||
|
||||
void *
|
||||
__gthread_getspecific (__gthread_key_t __key)
|
||||
{
|
||||
return (void *)__gthread_get_thread_keys()[__key];
|
||||
}
|
||||
|
||||
int
|
||||
__gthread_setspecific (__gthread_key_t __key, const void *__ptr)
|
||||
{
|
||||
__gthread_get_thread_keys()[__key] = __ptr;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
__gthread_key_cleanup (OSThread *thread)
|
||||
{
|
||||
void **keys = (void **)OSGetThreadSpecific(__GTHREAD_THREAD_SPECIFIC_ID);
|
||||
if (!keys) {
|
||||
return;
|
||||
}
|
||||
|
||||
__gthread_mutex_lock(&key_mutex);
|
||||
|
||||
for (int i = 0; i < __GTHREAD_MAX_KEYS; ++i) {
|
||||
if (key_table[i].in_use && key_table[i].dtor && keys[i]) {
|
||||
key_table[i].dtor(keys[i]);
|
||||
}
|
||||
}
|
||||
|
||||
__gthread_mutex_unlock(&key_mutex);
|
||||
}
|
@ -1,37 +0,0 @@
|
||||
#include "include/bits/gthr-default.h"
|
||||
|
||||
void
|
||||
__gthread_mutex_init_function (__gthread_mutex_t *__mutex)
|
||||
{
|
||||
OSInitMutex(__mutex);
|
||||
}
|
||||
|
||||
int
|
||||
__gthread_mutex_lock (__gthread_mutex_t *__mutex)
|
||||
{
|
||||
OSLockMutex(__mutex);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
__gthread_mutex_trylock (__gthread_mutex_t *__mutex)
|
||||
{
|
||||
if (!OSTryLockMutex(__mutex)) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
__gthread_mutex_unlock (__gthread_mutex_t *__mutex)
|
||||
{
|
||||
OSUnlockMutex(__mutex);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
__gthread_mutex_destroy (__gthread_mutex_t *__mutex)
|
||||
{
|
||||
return 0;
|
||||
}
|
@ -1,23 +0,0 @@
|
||||
#include "include/bits/gthr-default.h"
|
||||
|
||||
int
|
||||
__gthread_once (__gthread_once_t *__once, void (*__func) (void))
|
||||
{
|
||||
uint32_t value = 0;
|
||||
|
||||
if (OSCompareAndSwapAtomicEx(__once,
|
||||
__GTHREAD_ONCE_VALUE_INIT,
|
||||
__GTHREAD_ONCE_VALUE_STARTED,
|
||||
&value)) {
|
||||
__func();
|
||||
OSCompareAndSwapAtomic(__once,
|
||||
__GTHREAD_ONCE_VALUE_STARTED,
|
||||
__GTHREAD_ONCE_VALUE_DONE);
|
||||
} else if (value != __GTHREAD_ONCE_VALUE_DONE) {
|
||||
while (!OSCompareAndSwapAtomic(__once,
|
||||
__GTHREAD_ONCE_VALUE_DONE,
|
||||
__GTHREAD_ONCE_VALUE_DONE));
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
@ -1,38 +0,0 @@
|
||||
#include "include/bits/gthr-default.h"
|
||||
|
||||
int
|
||||
__gthread_recursive_mutex_init_function (__gthread_recursive_mutex_t *__mutex)
|
||||
{
|
||||
OSInitMutex(__mutex);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
__gthread_recursive_mutex_lock (__gthread_recursive_mutex_t *__mutex)
|
||||
{
|
||||
OSLockMutex(__mutex);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
__gthread_recursive_mutex_trylock (__gthread_recursive_mutex_t *__mutex)
|
||||
{
|
||||
if (!OSTryLockMutex(__mutex)) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
__gthread_recursive_mutex_unlock (__gthread_recursive_mutex_t *__mutex)
|
||||
{
|
||||
OSUnlockMutex(__mutex);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
__gthread_recursive_mutex_destroy (__gthread_recursive_mutex_t *__mutex)
|
||||
{
|
||||
return 0;
|
||||
}
|
@ -1,165 +0,0 @@
|
||||
/* Threads compatibility routines for libgcc2 and libobjc. */
|
||||
/* Compile this one with gcc. */
|
||||
/* Copyright (C) 1997-2016 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GCC.
|
||||
|
||||
GCC is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU General Public License as published by the Free
|
||||
Software Foundation; either version 3, or (at your option) any later
|
||||
version.
|
||||
|
||||
GCC is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
for more details.
|
||||
|
||||
Under Section 7 of GPL version 3, you are granted additional
|
||||
permissions described in the GCC Runtime Library Exception, version
|
||||
3.1, as published by the Free Software Foundation.
|
||||
|
||||
You should have received a copy of the GNU General Public License and
|
||||
a copy of the GCC Runtime Library Exception along with this program;
|
||||
see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
|
||||
<http://www.gnu.org/licenses/>. */
|
||||
|
||||
#ifndef _GLIBCXX_GCC_GTHR_SINGLE_H
|
||||
#define _GLIBCXX_GCC_GTHR_SINGLE_H
|
||||
|
||||
#define __GTHREADS 1
|
||||
#define __GTHREADS_CXX0X 1
|
||||
|
||||
#include <coreinit/atomic.h>
|
||||
#include <coreinit/condition.h>
|
||||
#include <coreinit/thread.h>
|
||||
#include <coreinit/mutex.h>
|
||||
#include <coreinit/baseheap.h>
|
||||
#include <coreinit/expandedheap.h>
|
||||
|
||||
#include <string.h>
|
||||
#include <sys/errno.h>
|
||||
|
||||
#define _GTHREAD_USE_MUTEX_TIMEDLOCK 0
|
||||
|
||||
typedef OSThread *__gthread_t;
|
||||
typedef volatile uint32_t __gthread_once_t;
|
||||
typedef OSMutex __gthread_mutex_t;
|
||||
typedef OSMutex __gthread_recursive_mutex_t;
|
||||
typedef OSCondition __gthread_cond_t;
|
||||
typedef struct timespec __gthread_time_t;
|
||||
typedef uint32_t __gthread_key_t;
|
||||
|
||||
#define __GTHREAD_HAS_COND 1
|
||||
#define __GTHREAD_MAX_KEYS (128)
|
||||
|
||||
#define __GTHREAD_ONCE_VALUE_INIT (0)
|
||||
#define __GTHREAD_ONCE_VALUE_STARTED (1)
|
||||
#define __GTHREAD_ONCE_VALUE_DONE (2)
|
||||
|
||||
#define __GTHREAD_ONCE_INIT __GTHREAD_ONCE_VALUE_INIT
|
||||
#define __GTHREAD_MUTEX_INIT_FUNCTION __gthread_mutex_init_function
|
||||
#define __GTHREAD_RECURSIVE_MUTEX_INIT_FUNCTION __gthread_recursive_mutex_init_function
|
||||
#define __GTHREAD_COND_INIT_FUNCTION __gthread_cond_init_function
|
||||
#define __GTHREAD_TIME_INIT { 0, 0 }
|
||||
|
||||
#define __GTHREAD_STACK_SIZE (4096*1024)
|
||||
|
||||
#define __GTHREAD_THREAD_SPECIFIC_ID (0)
|
||||
|
||||
static inline int
|
||||
__gthread_active_p (void)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
int
|
||||
__gthread_create (__gthread_t *__threadid, void *(*__func) (void*),
|
||||
void *__args);
|
||||
|
||||
int
|
||||
__gthread_join (__gthread_t __threadid, void **__value_ptr);
|
||||
|
||||
int
|
||||
__gthread_detach (__gthread_t __threadid);
|
||||
|
||||
int
|
||||
__gthread_equal (__gthread_t __t1, __gthread_t __t2);
|
||||
|
||||
__gthread_t
|
||||
__gthread_self (void);
|
||||
|
||||
int
|
||||
__gthread_yield (void);
|
||||
|
||||
int
|
||||
__gthread_once (__gthread_once_t *__once, void (*__func) (void));
|
||||
|
||||
void
|
||||
__gthread_key_cleanup (OSThread *thread);
|
||||
|
||||
int
|
||||
__gthread_key_create (__gthread_key_t *__key, void (*__dtor) (void *));
|
||||
|
||||
int
|
||||
__gthread_key_delete (__gthread_key_t __key);
|
||||
|
||||
void *
|
||||
__gthread_getspecific (__gthread_key_t __key);
|
||||
|
||||
int
|
||||
__gthread_setspecific (__gthread_key_t __key, const void *__ptr);
|
||||
|
||||
void
|
||||
__gthread_mutex_init_function (__gthread_mutex_t *__mutex);
|
||||
|
||||
int
|
||||
__gthread_mutex_destroy (__gthread_mutex_t *__mutex);
|
||||
|
||||
int
|
||||
__gthread_mutex_lock (__gthread_mutex_t *__mutex);
|
||||
|
||||
int
|
||||
__gthread_mutex_trylock (__gthread_mutex_t *__mutex);
|
||||
|
||||
int
|
||||
__gthread_mutex_unlock (__gthread_mutex_t *__mutex);
|
||||
|
||||
int
|
||||
__gthread_recursive_mutex_init_function (__gthread_recursive_mutex_t *__mutex);
|
||||
|
||||
int
|
||||
__gthread_recursive_mutex_lock (__gthread_recursive_mutex_t *__mutex);
|
||||
|
||||
int
|
||||
__gthread_recursive_mutex_trylock (__gthread_recursive_mutex_t *__mutex);
|
||||
|
||||
int
|
||||
__gthread_recursive_mutex_unlock (__gthread_recursive_mutex_t *__mutex);
|
||||
|
||||
int
|
||||
__gthread_recursive_mutex_destroy (__gthread_recursive_mutex_t *__mutex);
|
||||
|
||||
void
|
||||
__gthread_cond_init_function (__gthread_cond_t *__cond);
|
||||
|
||||
int
|
||||
__gthread_cond_broadcast (__gthread_cond_t *__cond);
|
||||
|
||||
int
|
||||
__gthread_cond_signal (__gthread_cond_t *__cond);
|
||||
|
||||
int
|
||||
__gthread_cond_wait (__gthread_cond_t *__cond, __gthread_mutex_t *__mutex);
|
||||
|
||||
int
|
||||
__gthread_cond_timedwait (__gthread_cond_t *__cond, __gthread_mutex_t *__mutex,
|
||||
const __gthread_time_t *__abs_timeout);
|
||||
|
||||
int
|
||||
__gthread_cond_wait_recursive (__gthread_cond_t *__cond,
|
||||
__gthread_recursive_mutex_t *__mutex);
|
||||
|
||||
int
|
||||
__gthread_cond_destroy (__gthread_cond_t* __cond);
|
||||
|
||||
#endif /* ! _GLIBCXX_GCC_GTHR_SINGLE_H */
|
@ -1,97 +0,0 @@
|
||||
// mutex -*- C++ -*-
|
||||
|
||||
// Copyright (C) 2008-2018 Free Software Foundation, Inc.
|
||||
//
|
||||
// This file is part of the GNU ISO C++ Library. This library is free
|
||||
// software; you can redistribute it and/or modify it under the
|
||||
// terms of the GNU General Public License as published by the
|
||||
// Free Software Foundation; either version 3, or (at your option)
|
||||
// any later version.
|
||||
|
||||
// This library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
|
||||
// Under Section 7 of GPL version 3, you are granted additional
|
||||
// permissions described in the GCC Runtime Library Exception, version
|
||||
// 3.1, as published by the Free Software Foundation.
|
||||
|
||||
// You should have received a copy of the GNU General Public License and
|
||||
// a copy of the GCC Runtime Library Exception along with this program;
|
||||
// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
|
||||
// <http://www.gnu.org/licenses/>.
|
||||
|
||||
#include <mutex>
|
||||
|
||||
#if defined(_GLIBCXX_HAS_GTHREADS) && defined(_GLIBCXX_USE_C99_STDINT_TR1)
|
||||
#ifndef _GLIBCXX_HAVE_TLS
|
||||
namespace
|
||||
{
|
||||
inline std::unique_lock<std::mutex>*&
|
||||
__get_once_functor_lock_ptr()
|
||||
{
|
||||
static std::unique_lock<std::mutex>* __once_functor_lock_ptr = 0;
|
||||
return __once_functor_lock_ptr;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
namespace std _GLIBCXX_VISIBILITY(default)
|
||||
{
|
||||
_GLIBCXX_BEGIN_NAMESPACE_VERSION
|
||||
|
||||
#ifdef _GLIBCXX_HAVE_TLS
|
||||
__thread void* __once_callable;
|
||||
__thread void (*__once_call)();
|
||||
#else
|
||||
// Explicit instantiation due to -fno-implicit-instantiation.
|
||||
template class function<void()>;
|
||||
function<void()> __once_functor;
|
||||
|
||||
mutex&
|
||||
__get_once_mutex()
|
||||
{
|
||||
static mutex once_mutex;
|
||||
return once_mutex;
|
||||
}
|
||||
|
||||
// code linked against ABI 3.4.12 and later uses this
|
||||
void
|
||||
__set_once_functor_lock_ptr(unique_lock<mutex>* __ptr)
|
||||
{
|
||||
__get_once_functor_lock_ptr() = __ptr;
|
||||
}
|
||||
|
||||
// unsafe - retained for compatibility with ABI 3.4.11
|
||||
unique_lock<mutex>&
|
||||
__get_once_functor_lock()
|
||||
{
|
||||
static unique_lock<mutex> once_functor_lock(__get_once_mutex(), defer_lock);
|
||||
return once_functor_lock;
|
||||
}
|
||||
#endif
|
||||
|
||||
extern "C"
|
||||
{
|
||||
void __once_proxy()
|
||||
{
|
||||
#ifndef _GLIBCXX_HAVE_TLS
|
||||
function<void()> __once_call = std::move(__once_functor);
|
||||
if (unique_lock<mutex>* __lock = __get_once_functor_lock_ptr())
|
||||
{
|
||||
// caller is using new ABI and provided lock ptr
|
||||
__get_once_functor_lock_ptr() = 0;
|
||||
__lock->unlock();
|
||||
}
|
||||
else
|
||||
__get_once_functor_lock().unlock(); // global lock
|
||||
#endif
|
||||
__once_call();
|
||||
}
|
||||
}
|
||||
|
||||
_GLIBCXX_END_NAMESPACE_VERSION
|
||||
} // namespace std
|
||||
|
||||
#endif // _GLIBCXX_HAS_GTHREADS && _GLIBCXX_USE_C99_STDINT_TR1
|
@ -1,88 +0,0 @@
|
||||
// Support for pointer abstractions -*- C++ -*-
|
||||
|
||||
// Copyright (C) 2011-2018 Free Software Foundation, Inc.
|
||||
//
|
||||
// This file is part of the GNU ISO C++ Library. This library is free
|
||||
// software; you can redistribute it and/or modify it under the
|
||||
// terms of the GNU General Public License as published by the
|
||||
// Free Software Foundation; either version 3, or (at your option)
|
||||
// any later version.
|
||||
|
||||
// This library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
|
||||
// Under Section 7 of GPL version 3, you are granted additional
|
||||
// permissions described in the GCC Runtime Library Exception, version
|
||||
// 3.1, as published by the Free Software Foundation.
|
||||
|
||||
// You should have received a copy of the GNU General Public License and
|
||||
// a copy of the GCC Runtime Library Exception along with this program;
|
||||
// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
|
||||
// <http://www.gnu.org/licenses/>.
|
||||
|
||||
#include <memory>
|
||||
|
||||
namespace __gnu_internal _GLIBCXX_VISIBILITY(hidden)
|
||||
{
|
||||
const unsigned char mask = 0xf;
|
||||
const unsigned char invalid = mask + 1;
|
||||
|
||||
/* Returns different instances of __mutex depending on the passed index
|
||||
* in order to limit contention.
|
||||
*/
|
||||
__gnu_cxx::__mutex& get_mutex(unsigned char i);
|
||||
}
|
||||
|
||||
namespace std _GLIBCXX_VISIBILITY(default)
|
||||
{
|
||||
_GLIBCXX_BEGIN_NAMESPACE_VERSION
|
||||
|
||||
#ifdef __GTHREADS
|
||||
namespace
|
||||
{
|
||||
inline unsigned char key(const void* addr)
|
||||
{ return _Hash_impl::hash(addr) & __gnu_internal::mask; }
|
||||
}
|
||||
|
||||
_Sp_locker::_Sp_locker(const void* p) noexcept
|
||||
{
|
||||
if (__gthread_active_p())
|
||||
{
|
||||
_M_key1 = _M_key2 = key(p);
|
||||
__gnu_internal::get_mutex(_M_key1).lock();
|
||||
}
|
||||
else
|
||||
_M_key1 = _M_key2 = __gnu_internal::invalid;
|
||||
}
|
||||
|
||||
_Sp_locker::_Sp_locker(const void* p1, const void* p2) noexcept
|
||||
{
|
||||
if (__gthread_active_p())
|
||||
{
|
||||
_M_key1 = key(p1);
|
||||
_M_key2 = key(p2);
|
||||
if (_M_key2 < _M_key1)
|
||||
__gnu_internal::get_mutex(_M_key2).lock();
|
||||
__gnu_internal::get_mutex(_M_key1).lock();
|
||||
if (_M_key2 > _M_key1)
|
||||
__gnu_internal::get_mutex(_M_key2).lock();
|
||||
}
|
||||
else
|
||||
_M_key1 = _M_key2 = __gnu_internal::invalid;
|
||||
}
|
||||
|
||||
_Sp_locker::~_Sp_locker()
|
||||
{
|
||||
if (_M_key1 != __gnu_internal::invalid)
|
||||
{
|
||||
__gnu_internal::get_mutex(_M_key1).unlock();
|
||||
if (_M_key2 != _M_key1)
|
||||
__gnu_internal::get_mutex(_M_key2).unlock();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
_GLIBCXX_END_NAMESPACE_VERSION
|
||||
} // namespace
|
@ -1,218 +0,0 @@
|
||||
// thread -*- C++ -*-
|
||||
|
||||
// Copyright (C) 2008-2018 Free Software Foundation, Inc.
|
||||
//
|
||||
// This file is part of the GNU ISO C++ Library. This library is free
|
||||
// software; you can redistribute it and/or modify it under the
|
||||
// terms of the GNU General Public License as published by the
|
||||
// Free Software Foundation; either version 3, or (at your option)
|
||||
// any later version.
|
||||
|
||||
// This library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
|
||||
// Under Section 7 of GPL version 3, you are granted additional
|
||||
// permissions described in the GCC Runtime Library Exception, version
|
||||
// 3.1, as published by the Free Software Foundation.
|
||||
|
||||
// You should have received a copy of the GNU General Public License and
|
||||
// a copy of the GCC Runtime Library Exception along with this program;
|
||||
// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
|
||||
// <http://www.gnu.org/licenses/>.
|
||||
|
||||
|
||||
#define _GLIBCXX_THREAD_ABI_COMPAT 1
|
||||
#include <thread>
|
||||
#include <system_error>
|
||||
#include <cerrno>
|
||||
#include <bits/cxxabi_forced.h>
|
||||
|
||||
#if defined(_GLIBCXX_HAS_GTHREADS) && defined(_GLIBCXX_USE_C99_STDINT_TR1)
|
||||
|
||||
#if defined(_GLIBCXX_USE_GET_NPROCS)
|
||||
# include <sys/sysinfo.h>
|
||||
# define _GLIBCXX_NPROCS get_nprocs()
|
||||
#elif defined(_GLIBCXX_USE_PTHREADS_NUM_PROCESSORS_NP)
|
||||
# define _GLIBCXX_NPROCS pthread_num_processors_np()
|
||||
#elif defined(_GLIBCXX_USE_SYSCTL_HW_NCPU)
|
||||
# include <stddef.h>
|
||||
# include <sys/sysctl.h>
|
||||
static inline int get_nprocs()
|
||||
{
|
||||
int count;
|
||||
size_t size = sizeof(count);
|
||||
int mib[] = { CTL_HW, HW_NCPU };
|
||||
if (!sysctl(mib, 2, &count, &size, NULL, 0))
|
||||
return count;
|
||||
return 0;
|
||||
}
|
||||
# define _GLIBCXX_NPROCS get_nprocs()
|
||||
#elif defined(_GLIBCXX_USE_SC_NPROCESSORS_ONLN)
|
||||
# include <unistd.h>
|
||||
# define _GLIBCXX_NPROCS sysconf(_SC_NPROCESSORS_ONLN)
|
||||
#elif defined(_GLIBCXX_USE_SC_NPROC_ONLN)
|
||||
# include <unistd.h>
|
||||
# define _GLIBCXX_NPROCS sysconf(_SC_NPROC_ONLN)
|
||||
#else
|
||||
# define _GLIBCXX_NPROCS 0
|
||||
#endif
|
||||
|
||||
#ifndef _GLIBCXX_USE_NANOSLEEP
|
||||
# ifdef _GLIBCXX_HAVE_SLEEP
|
||||
# include <unistd.h>
|
||||
# elif defined(_GLIBCXX_HAVE_WIN32_SLEEP)
|
||||
# include <windows.h>
|
||||
# else
|
||||
# error "No sleep function known for this target"
|
||||
# endif
|
||||
#endif
|
||||
|
||||
namespace std _GLIBCXX_VISIBILITY(default)
|
||||
{
|
||||
extern "C"
|
||||
{
|
||||
static void*
|
||||
execute_native_thread_routine(void* __p)
|
||||
{
|
||||
thread::_State_ptr __t{ static_cast<thread::_State*>(__p) };
|
||||
__t->_M_run();
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
#if _GLIBCXX_THREAD_ABI_COMPAT
|
||||
static void*
|
||||
execute_native_thread_routine_compat(void* __p)
|
||||
{
|
||||
thread::_Impl_base* __t = static_cast<thread::_Impl_base*>(__p);
|
||||
thread::__shared_base_type __local;
|
||||
// Now that a new thread has been created we can transfer ownership of
|
||||
// the thread state to a local object, breaking the reference cycle
|
||||
// created in thread::_M_start_thread.
|
||||
__local.swap(__t->_M_this_ptr);
|
||||
__t->_M_run();
|
||||
return nullptr;
|
||||
}
|
||||
#endif
|
||||
} // extern "C"
|
||||
|
||||
_GLIBCXX_BEGIN_NAMESPACE_VERSION
|
||||
|
||||
thread::_State::~_State() = default;
|
||||
|
||||
void
|
||||
thread::join()
|
||||
{
|
||||
int __e = EINVAL;
|
||||
|
||||
if (_M_id != id())
|
||||
__e = __gthread_join(_M_id._M_thread, 0);
|
||||
|
||||
if (__e)
|
||||
__throw_system_error(__e);
|
||||
|
||||
_M_id = id();
|
||||
}
|
||||
|
||||
void
|
||||
thread::detach()
|
||||
{
|
||||
int __e = EINVAL;
|
||||
|
||||
if (_M_id != id())
|
||||
__e = __gthread_detach(_M_id._M_thread);
|
||||
|
||||
if (__e)
|
||||
__throw_system_error(__e);
|
||||
|
||||
_M_id = id();
|
||||
}
|
||||
|
||||
void
|
||||
thread::_M_start_thread(_State_ptr state, void (*)())
|
||||
{
|
||||
const int err = __gthread_create(&_M_id._M_thread,
|
||||
&execute_native_thread_routine,
|
||||
state.get());
|
||||
if (err)
|
||||
__throw_system_error(err);
|
||||
state.release();
|
||||
}
|
||||
|
||||
#if _GLIBCXX_THREAD_ABI_COMPAT
|
||||
void
|
||||
thread::_M_start_thread(__shared_base_type __b)
|
||||
{
|
||||
if (!__gthread_active_p())
|
||||
#if __cpp_exceptions
|
||||
throw system_error(make_error_code(errc::operation_not_permitted),
|
||||
"Enable multithreading to use std::thread");
|
||||
#else
|
||||
__throw_system_error(int(errc::operation_not_permitted));
|
||||
#endif
|
||||
|
||||
_M_start_thread(std::move(__b), nullptr);
|
||||
}
|
||||
|
||||
void
|
||||
thread::_M_start_thread(__shared_base_type __b, void (*)())
|
||||
{
|
||||
auto ptr = __b.get();
|
||||
// Create a reference cycle that will be broken in the new thread.
|
||||
ptr->_M_this_ptr = std::move(__b);
|
||||
int __e = __gthread_create(&_M_id._M_thread,
|
||||
&execute_native_thread_routine_compat, ptr);
|
||||
if (__e)
|
||||
{
|
||||
ptr->_M_this_ptr.reset(); // break reference cycle, destroying *ptr.
|
||||
__throw_system_error(__e);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
unsigned int
|
||||
thread::hardware_concurrency() noexcept
|
||||
{
|
||||
return 3;
|
||||
}
|
||||
|
||||
namespace this_thread
|
||||
{
|
||||
void
|
||||
__sleep_for(chrono::seconds __s, chrono::nanoseconds __ns)
|
||||
{
|
||||
#ifdef _GLIBCXX_USE_NANOSLEEP
|
||||
__gthread_time_t __ts =
|
||||
{
|
||||
static_cast<std::time_t>(__s.count()),
|
||||
static_cast<long>(__ns.count())
|
||||
};
|
||||
while (::nanosleep(&__ts, &__ts) == -1 && errno == EINTR)
|
||||
{ }
|
||||
#elif defined(_GLIBCXX_HAVE_SLEEP)
|
||||
# ifdef _GLIBCXX_HAVE_USLEEP
|
||||
::sleep(__s.count());
|
||||
if (__ns.count() > 0)
|
||||
{
|
||||
long __us = __ns.count() / 1000;
|
||||
if (__us == 0)
|
||||
__us = 1;
|
||||
::usleep(__us);
|
||||
}
|
||||
# else
|
||||
::sleep(__s.count() + (__ns.count() >= 1000000));
|
||||
# endif
|
||||
#elif defined(_GLIBCXX_HAVE_WIN32_SLEEP)
|
||||
unsigned long ms = __ns.count() / 1000000;
|
||||
if (__ns.count() > 0 && ms == 0)
|
||||
ms = 1;
|
||||
::Sleep(chrono::milliseconds(__s).count() + ms);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
_GLIBCXX_END_NAMESPACE_VERSION
|
||||
} // namespace std
|
||||
|
||||
#endif // _GLIBCXX_HAS_GTHREADS && _GLIBCXX_USE_C99_STDINT_TR1
|
78
libraries/wutstdc++/wut_gthread.cc
Normal file
78
libraries/wutstdc++/wut_gthread.cc
Normal file
@ -0,0 +1,78 @@
|
||||
#include "wut_gthread.h"
|
||||
#include <bits/gthr-default.h>
|
||||
|
||||
typedef int (* __gthread_fn_active) (void);
|
||||
typedef int (* __gthread_fn_create) (__gthread_t *__threadid, void *(*__func) (void*), void *__args);
|
||||
typedef int (* __gthread_fn_join) (__gthread_t __threadid, void **__value_ptr);
|
||||
typedef int (* __gthread_fn_detach) (__gthread_t __threadid);
|
||||
typedef int (* __gthread_fn_equal) (__gthread_t __t1, __gthread_t __t2);
|
||||
typedef __gthread_t (* __gthread_fn_self) (void);
|
||||
typedef int (* __gthread_fn_yield) (void);
|
||||
typedef int (* __gthread_fn_once) (__gthread_once_t *__once, void (*__func) (void));
|
||||
typedef int (* __gthread_fn_key_create) (__gthread_key_t *__key, void (*__dtor) (void *));
|
||||
typedef int (* __gthread_fn_key_delete) (__gthread_key_t __key);
|
||||
typedef void *(* __gthread_fn_getspecific) (__gthread_key_t __key);
|
||||
typedef int (* __gthread_fn_setspecific) (__gthread_key_t __key, const void *__ptr);
|
||||
typedef void (* __gthread_fn_mutex_init_function) (__gthread_mutex_t *__mutex);
|
||||
typedef int (* __gthread_fn_mutex_destroy) (__gthread_mutex_t *__mutex);
|
||||
typedef int (* __gthread_fn_mutex_lock) (__gthread_mutex_t *__mutex);
|
||||
typedef int (* __gthread_fn_mutex_trylock) (__gthread_mutex_t *__mutex);
|
||||
typedef int (* __gthread_fn_mutex_unlock) (__gthread_mutex_t *__mutex);
|
||||
typedef int (* __gthread_fn_recursive_mutex_init_function) (__gthread_recursive_mutex_t *__mutex);
|
||||
typedef int (* __gthread_fn_recursive_mutex_lock) (__gthread_recursive_mutex_t *__mutex);
|
||||
typedef int (* __gthread_fn_recursive_mutex_trylock) (__gthread_recursive_mutex_t *__mutex);
|
||||
typedef int (* __gthread_fn_recursive_mutex_unlock) (__gthread_recursive_mutex_t *__mutex);
|
||||
typedef int (* __gthread_fn_recursive_mutex_destroy) (__gthread_recursive_mutex_t *__mutex);
|
||||
typedef void (* __gthread_fn_cond_init_function) (__gthread_cond_t *__cond);
|
||||
typedef int (* __gthread_fn_cond_broadcast) (__gthread_cond_t *__cond);
|
||||
typedef int (* __gthread_fn_cond_signal) (__gthread_cond_t *__cond);
|
||||
typedef int (* __gthread_fn_cond_wait) (__gthread_cond_t *__cond, __gthread_mutex_t *__mutex);
|
||||
typedef int (* __gthread_fn_cond_timedwait) (__gthread_cond_t *__cond, __gthread_mutex_t *__mutex, const __gthread_time_t *__abs_timeout);
|
||||
typedef int (* __gthread_fn_cond_wait_recursive) (__gthread_cond_t *__cond, __gthread_recursive_mutex_t *__mutex);
|
||||
typedef int (* __gthread_fn_cond_destroy) (__gthread_cond_t* __cond);
|
||||
|
||||
int
|
||||
__wut_active_p()
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
extern "C"
|
||||
{
|
||||
|
||||
void
|
||||
__init_wut_gthread()
|
||||
{
|
||||
__gthread_impl.active = &__wut_active_p;
|
||||
__gthread_impl.active = (__gthread_fn_active)__wut_active_p;
|
||||
__gthread_impl.create = (__gthread_fn_create)__wut_thread_create;
|
||||
__gthread_impl.join = (__gthread_fn_join)__wut_thread_join;
|
||||
__gthread_impl.detach = (__gthread_fn_detach)__wut_thread_detach;
|
||||
__gthread_impl.equal = (__gthread_fn_equal)__wut_thread_equal;
|
||||
__gthread_impl.self = (__gthread_fn_self)__wut_thread_self;
|
||||
__gthread_impl.yield = (__gthread_fn_yield)__wut_thread_yield;
|
||||
__gthread_impl.once = (__gthread_fn_once)__wut_once;
|
||||
__gthread_impl.key_create = (__gthread_fn_key_create)__wut_key_create;
|
||||
__gthread_impl.key_delete = (__gthread_fn_key_delete)__wut_key_delete;
|
||||
__gthread_impl.getspecific = (__gthread_fn_getspecific)__wut_getspecific;
|
||||
__gthread_impl.setspecific = (__gthread_fn_setspecific)__wut_setspecific;
|
||||
__gthread_impl.mutex_init_function = (__gthread_fn_mutex_init_function)__wut_mutex_init_function;
|
||||
__gthread_impl.mutex_destroy = (__gthread_fn_mutex_destroy)__wut_mutex_destroy;
|
||||
__gthread_impl.mutex_lock = (__gthread_fn_mutex_lock)__wut_mutex_lock;
|
||||
__gthread_impl.mutex_trylock = (__gthread_fn_mutex_trylock)__wut_mutex_trylock;
|
||||
__gthread_impl.mutex_unlock = (__gthread_fn_mutex_unlock)__wut_mutex_unlock;
|
||||
__gthread_impl.recursive_mutex_init_function = (__gthread_fn_recursive_mutex_init_function)__wut_recursive_mutex_init_function;
|
||||
__gthread_impl.recursive_mutex_lock = (__gthread_fn_recursive_mutex_lock)__wut_recursive_mutex_lock;
|
||||
__gthread_impl.recursive_mutex_trylock = (__gthread_fn_recursive_mutex_trylock)__wut_recursive_mutex_trylock;
|
||||
__gthread_impl.recursive_mutex_unlock = (__gthread_fn_recursive_mutex_unlock)__wut_recursive_mutex_unlock;
|
||||
__gthread_impl.recursive_mutex_destroy = (__gthread_fn_recursive_mutex_destroy)__wut_recursive_mutex_destroy;
|
||||
__gthread_impl.cond_init_function = (__gthread_fn_cond_init_function)__wut_cond_init_function;
|
||||
__gthread_impl.cond_broadcast = (__gthread_fn_cond_broadcast)__wut_cond_broadcast;
|
||||
__gthread_impl.cond_signal = (__gthread_fn_cond_signal)__wut_cond_signal;
|
||||
__gthread_impl.cond_wait = (__gthread_fn_cond_wait)__wut_cond_wait;
|
||||
__gthread_impl.cond_timedwait = (__gthread_fn_cond_timedwait)__wut_cond_timedwait;
|
||||
__gthread_impl.cond_wait_recursive = (__gthread_fn_cond_wait_recursive)__wut_cond_wait_recursive;
|
||||
__gthread_impl.cond_destroy = (__gthread_fn_cond_destroy)__wut_cond_destroy;
|
||||
}
|
||||
|
||||
} // extern "c"
|
122
libraries/wutstdc++/wut_gthread.h
Normal file
122
libraries/wutstdc++/wut_gthread.h
Normal file
@ -0,0 +1,122 @@
|
||||
#pragma once
|
||||
#include <bits/gthr-default.h>
|
||||
|
||||
#include <coreinit/atomic.h>
|
||||
#include <coreinit/condition.h>
|
||||
#include <coreinit/thread.h>
|
||||
#include <coreinit/mutex.h>
|
||||
#include <coreinit/baseheap.h>
|
||||
#include <coreinit/expandedheap.h>
|
||||
|
||||
#define __WUT_MAX_KEYS (128)
|
||||
#define __WUT_STACK_SIZE (4096*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 (0)
|
||||
|
||||
typedef volatile uint32_t __wut_once_t;
|
||||
typedef uint32_t __wut_key_t;
|
||||
|
||||
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);
|
100
libraries/wutstdc++/wut_gthread_cond.cc
Normal file
100
libraries/wutstdc++/wut_gthread_cond.cc
Normal file
@ -0,0 +1,100 @@
|
||||
#include "wut_gthread.h"
|
||||
|
||||
#include <sys/errno.h>
|
||||
|
||||
#include <coreinit/alarm.h>
|
||||
#include <coreinit/systeminfo.h>
|
||||
#include <coreinit/time.h>
|
||||
#include <chrono>
|
||||
|
||||
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;
|
||||
|
||||
auto time = std::chrono::system_clock::now();
|
||||
auto timeout = std::chrono::system_clock::time_point(
|
||||
std::chrono::seconds(abs_timeout->tv_sec) +
|
||||
std::chrono::nanoseconds(abs_timeout->tv_nsec));
|
||||
|
||||
// Already timed out!
|
||||
if (timeout <= time) {
|
||||
return ETIMEDOUT;
|
||||
}
|
||||
|
||||
auto duration =
|
||||
std::chrono::duration_cast<std::chrono::nanoseconds>(timeout - time);
|
||||
|
||||
// Set an alarm
|
||||
OSAlarm alarm;
|
||||
OSCreateAlarm(&alarm);
|
||||
OSSetAlarmUserData(&alarm, &data);
|
||||
OSSetAlarm(&alarm, OSNanoseconds(duration.count()),
|
||||
&__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;
|
||||
}
|
102
libraries/wutstdc++/wut_gthread_keys.cc
Normal file
102
libraries/wutstdc++/wut_gthread_keys.cc
Normal file
@ -0,0 +1,102 @@
|
||||
#include "wut_gthread.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 (int 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 = (__wut_key_t)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].in_use = 0;
|
||||
key_table[key].dtor = NULL;
|
||||
__wut_mutex_unlock(&key_mutex);
|
||||
return -1;
|
||||
}
|
||||
|
||||
static const void **
|
||||
__wut_get_thread_keys()
|
||||
{
|
||||
const void **keys = (const void **)OSGetThreadSpecific(__WUT_KEY_THREAD_SPECIFIC_ID);
|
||||
if (!keys) {
|
||||
MEMExpandedHeap *heap = (MEMExpandedHeap *)MEMGetBaseHeapHandle(MEM_BASE_HEAP_MEM2);
|
||||
keys = (const void **)MEMAllocFromExpHeapEx(heap, sizeof(void *) * sizeof(__WUT_MAX_KEYS), 4);
|
||||
memset(keys, 0, sizeof(void *) * sizeof(__WUT_MAX_KEYS));
|
||||
OSSetThreadSpecific(__WUT_KEY_THREAD_SPECIFIC_ID, keys);
|
||||
}
|
||||
|
||||
return keys;
|
||||
}
|
||||
|
||||
void *
|
||||
__wut_getspecific(__wut_key_t key)
|
||||
{
|
||||
return (void *)__wut_get_thread_keys()[key];
|
||||
}
|
||||
|
||||
int
|
||||
__wut_setspecific(__wut_key_t key,
|
||||
const void *ptr)
|
||||
{
|
||||
__wut_get_thread_keys()[key] = ptr;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
__wut_key_cleanup(OSThread *thread)
|
||||
{
|
||||
void **keys = (void **)OSGetThreadSpecific(__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);
|
||||
}
|
37
libraries/wutstdc++/wut_gthread_mutex.cc
Normal file
37
libraries/wutstdc++/wut_gthread_mutex.cc
Normal file
@ -0,0 +1,37 @@
|
||||
#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;
|
||||
}
|
24
libraries/wutstdc++/wut_gthread_once.cc
Normal file
24
libraries/wutstdc++/wut_gthread_once.cc
Normal file
@ -0,0 +1,24 @@
|
||||
#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();
|
||||
OSCompareAndSwapAtomic(once,
|
||||
__WUT_ONCE_VALUE_STARTED,
|
||||
__WUT_ONCE_VALUE_DONE);
|
||||
} else if (value != __WUT_ONCE_VALUE_DONE) {
|
||||
while (!OSCompareAndSwapAtomic(once,
|
||||
__WUT_ONCE_VALUE_DONE,
|
||||
__WUT_ONCE_VALUE_DONE));
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
38
libraries/wutstdc++/wut_gthread_recursive_mutex.cc
Normal file
38
libraries/wutstdc++/wut_gthread_recursive_mutex.cc
Normal file
@ -0,0 +1,38 @@
|
||||
#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;
|
||||
}
|
86
libraries/wutstdc++/wut_gthread_thread.cc
Normal file
86
libraries/wutstdc++/wut_gthread_thread.cc
Normal file
@ -0,0 +1,86 @@
|
||||
#include "wut_gthread.h"
|
||||
|
||||
#include <string.h>
|
||||
#include <sys/errno.h>
|
||||
|
||||
static void
|
||||
__wut_thread_deallocator(OSThread *thread,
|
||||
void *stack)
|
||||
{
|
||||
MEMExpandedHeap *heap = (MEMExpandedHeap *)MEMGetBaseHeapHandle(MEM_BASE_HEAP_MEM2);
|
||||
MEMFreeToExpHeap(heap, thread);
|
||||
MEMFreeToExpHeap(heap, 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)
|
||||
{
|
||||
MEMExpandedHeap *heap = (MEMExpandedHeap *)MEMGetBaseHeapHandle(MEM_BASE_HEAP_MEM2);
|
||||
OSThread *thread = (OSThread *)MEMAllocFromExpHeapEx(heap, sizeof(OSThread), 8);
|
||||
char *stack = (char *)MEMAllocFromExpHeapEx(heap, __WUT_STACK_SIZE, 8);
|
||||
memset(thread, 0, sizeof(OSThread));
|
||||
|
||||
if (!OSCreateThread(thread,
|
||||
(OSThreadEntryPointFn)entryPoint,
|
||||
(int)entryArgs,
|
||||
NULL,
|
||||
stack + __WUT_STACK_SIZE,
|
||||
__WUT_STACK_SIZE,
|
||||
16,
|
||||
OS_THREAD_ATTRIB_AFFINITY_ANY)) {
|
||||
MEMFreeToExpHeap((MEMExpandedHeap*)MEMGetBaseHeapHandle(MEM_BASE_HEAP_MEM2), thread);
|
||||
return EINVAL;
|
||||
}
|
||||
|
||||
*outThread = thread;
|
||||
OSSetThreadDeallocator(thread, &__wut_thread_deallocator);
|
||||
OSSetThreadCleanupCallback(thread, &__wut_thread_cleanup);
|
||||
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;
|
||||
}
|
@ -2,13 +2,12 @@ cmake_minimum_required(VERSION 3.2)
|
||||
|
||||
macro(wut_enable_stdcpp target)
|
||||
target_link_libraries(${target}
|
||||
wutstdc++)
|
||||
|
||||
target_compile_definitions(${target}
|
||||
PRIVATE _GLIBCXX_HAS_GTHREADS)
|
||||
wutnewlib
|
||||
stdc++)
|
||||
|
||||
set_target_properties(${target} PROPERTIES
|
||||
COMPILE_FLAGS "-std=c++17")
|
||||
COMPILE_FLAGS "-std=c++17"
|
||||
LINK_FLAGS "-Wl,--whole-archive -lwutstdc++ -Wl,--no-whole-archive")
|
||||
endmacro(wut_enable_stdcpp)
|
||||
|
||||
macro(wut_create_rpx target source)
|
||||
|
Loading…
Reference in New Issue
Block a user