mirror of
https://github.com/wiiu-env/wut.git
synced 2025-01-08 00:10:44 +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 <coreinit/time.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|
||||||
unsigned sleep(unsigned seconds) {
|
unsigned sleep(unsigned seconds)
|
||||||
|
{
|
||||||
OSSleepTicks(OSSeconds(seconds));
|
OSSleepTicks(OSSeconds(seconds));
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int usleep(useconds_t microseconds) {
|
int usleep(useconds_t microseconds)
|
||||||
|
{
|
||||||
OSSleepTicks(OSMicroseconds(microseconds));
|
OSSleepTicks(OSMicroseconds(microseconds));
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -172,10 +172,16 @@ __init_syscall_array()
|
|||||||
__syscalls.gettod_r = __libwut_gettod_r;
|
__syscalls.gettod_r = __libwut_gettod_r;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
extern void __init_wut_gthread() __attribute__((weak));
|
||||||
|
|
||||||
void
|
void
|
||||||
__init_wut_newlibc()
|
__init_wut_newlibc()
|
||||||
{
|
{
|
||||||
__init_libc_heap();
|
__init_libc_heap();
|
||||||
__init_malloc_lock();
|
__init_malloc_lock();
|
||||||
__init_syscall_array();
|
__init_syscall_array();
|
||||||
|
|
||||||
|
if (__init_wut_gthread) {
|
||||||
|
__init_wut_gthread();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,18 +2,13 @@ cmake_minimum_required(VERSION 3.2)
|
|||||||
project(wutstdc++ CXX)
|
project(wutstdc++ CXX)
|
||||||
|
|
||||||
add_library(wutstdc++
|
add_library(wutstdc++
|
||||||
condition_variable.cc
|
wut_gthread.cc
|
||||||
future.cc
|
wut_gthread_cond.cc
|
||||||
gthread.cc
|
wut_gthread_keys.cc
|
||||||
gthread_cond.cc
|
wut_gthread_mutex.cc
|
||||||
gthread_keys.cc
|
wut_gthread_once.cc
|
||||||
gthread_mutex.cc
|
wut_gthread_recursive_mutex.cc
|
||||||
gthread_once.cc
|
wut_gthread_thread.cc)
|
||||||
gthread_recursive_mutex.cc
|
|
||||||
mutex.cc
|
|
||||||
shared_ptr.cc
|
|
||||||
thread.cc
|
|
||||||
include/bits/gthr-default.h)
|
|
||||||
|
|
||||||
target_compile_definitions(wutstdc++
|
target_compile_definitions(wutstdc++
|
||||||
PRIVATE _GLIBCXX_HAS_GTHREADS)
|
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)
|
macro(wut_enable_stdcpp target)
|
||||||
target_link_libraries(${target}
|
target_link_libraries(${target}
|
||||||
wutstdc++)
|
wutnewlib
|
||||||
|
stdc++)
|
||||||
target_compile_definitions(${target}
|
|
||||||
PRIVATE _GLIBCXX_HAS_GTHREADS)
|
|
||||||
|
|
||||||
set_target_properties(${target} PROPERTIES
|
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)
|
endmacro(wut_enable_stdcpp)
|
||||||
|
|
||||||
macro(wut_create_rpx target source)
|
macro(wut_create_rpx target source)
|
||||||
|
Loading…
Reference in New Issue
Block a user