From ac8a42fa7c67a518b7055f7b0c6ffcf947ad5ca5 Mon Sep 17 00:00:00 2001 From: James Benton Date: Sat, 26 May 2018 18:25:36 +0100 Subject: [PATCH] Change to using new gthreads implementation. Assuming that --enable-threads=dkp gets merged into devkitPPC r31... :) --- libraries/wutnewlib/sleep.c | 6 +- libraries/wutnewlib/syscalls.c | 6 + libraries/wutstdc++/CMakeLists.txt | 19 +- libraries/wutstdc++/condition_variable.cc | 158 ------------- libraries/wutstdc++/future.cc | 62 ----- libraries/wutstdc++/gthread.cc | 78 ------- libraries/wutstdc++/gthread_cond.cc | 96 -------- libraries/wutstdc++/gthread_keys.cc | 98 -------- libraries/wutstdc++/gthread_mutex.cc | 37 --- libraries/wutstdc++/gthread_once.cc | 23 -- .../wutstdc++/gthread_recursive_mutex.cc | 38 --- .../wutstdc++/include/bits/gthr-default.h | 165 ------------- libraries/wutstdc++/mutex.cc | 97 -------- libraries/wutstdc++/shared_ptr.cc | 88 ------- libraries/wutstdc++/thread.cc | 218 ------------------ libraries/wutstdc++/wut_gthread.cc | 78 +++++++ libraries/wutstdc++/wut_gthread.h | 122 ++++++++++ libraries/wutstdc++/wut_gthread_cond.cc | 100 ++++++++ libraries/wutstdc++/wut_gthread_keys.cc | 102 ++++++++ libraries/wutstdc++/wut_gthread_mutex.cc | 37 +++ libraries/wutstdc++/wut_gthread_once.cc | 24 ++ .../wutstdc++/wut_gthread_recursive_mutex.cc | 38 +++ libraries/wutstdc++/wut_gthread_thread.cc | 86 +++++++ share/wut.cmake | 9 +- 24 files changed, 608 insertions(+), 1177 deletions(-) delete mode 100644 libraries/wutstdc++/condition_variable.cc delete mode 100644 libraries/wutstdc++/future.cc delete mode 100644 libraries/wutstdc++/gthread.cc delete mode 100644 libraries/wutstdc++/gthread_cond.cc delete mode 100644 libraries/wutstdc++/gthread_keys.cc delete mode 100644 libraries/wutstdc++/gthread_mutex.cc delete mode 100644 libraries/wutstdc++/gthread_once.cc delete mode 100644 libraries/wutstdc++/gthread_recursive_mutex.cc delete mode 100644 libraries/wutstdc++/include/bits/gthr-default.h delete mode 100644 libraries/wutstdc++/mutex.cc delete mode 100644 libraries/wutstdc++/shared_ptr.cc delete mode 100644 libraries/wutstdc++/thread.cc create mode 100644 libraries/wutstdc++/wut_gthread.cc create mode 100644 libraries/wutstdc++/wut_gthread.h create mode 100644 libraries/wutstdc++/wut_gthread_cond.cc create mode 100644 libraries/wutstdc++/wut_gthread_keys.cc create mode 100644 libraries/wutstdc++/wut_gthread_mutex.cc create mode 100644 libraries/wutstdc++/wut_gthread_once.cc create mode 100644 libraries/wutstdc++/wut_gthread_recursive_mutex.cc create mode 100644 libraries/wutstdc++/wut_gthread_thread.cc diff --git a/libraries/wutnewlib/sleep.c b/libraries/wutnewlib/sleep.c index 7dd1b23..b35e932 100644 --- a/libraries/wutnewlib/sleep.c +++ b/libraries/wutnewlib/sleep.c @@ -3,12 +3,14 @@ #include #include -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; } diff --git a/libraries/wutnewlib/syscalls.c b/libraries/wutnewlib/syscalls.c index 3acf34c..b6755d2 100644 --- a/libraries/wutnewlib/syscalls.c +++ b/libraries/wutnewlib/syscalls.c @@ -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(); + } } diff --git a/libraries/wutstdc++/CMakeLists.txt b/libraries/wutstdc++/CMakeLists.txt index 98311a6..9989ddf 100644 --- a/libraries/wutstdc++/CMakeLists.txt +++ b/libraries/wutstdc++/CMakeLists.txt @@ -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) diff --git a/libraries/wutstdc++/condition_variable.cc b/libraries/wutstdc++/condition_variable.cc deleted file mode 100644 index a302354..0000000 --- a/libraries/wutstdc++/condition_variable.cc +++ /dev/null @@ -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 -// . - -#include -#include - -#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& __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& 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(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 l) - { - (void) new notifier{cv, l}; - } - -_GLIBCXX_END_NAMESPACE_VERSION -} // namespace - -#endif // _GLIBCXX_HAS_GTHREADS && _GLIBCXX_USE_C99_STDINT_TR1 diff --git a/libraries/wutstdc++/future.cc b/libraries/wutstdc++/future.cc deleted file mode 100644 index f3b877a..0000000 --- a/libraries/wutstdc++/future.cc +++ /dev/null @@ -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 -// . - -#include -#include - -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 diff --git a/libraries/wutstdc++/gthread.cc b/libraries/wutstdc++/gthread.cc deleted file mode 100644 index 2aa0c3b..0000000 --- a/libraries/wutstdc++/gthread.cc +++ /dev/null @@ -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; -} diff --git a/libraries/wutstdc++/gthread_cond.cc b/libraries/wutstdc++/gthread_cond.cc deleted file mode 100644 index ad85293..0000000 --- a/libraries/wutstdc++/gthread_cond.cc +++ /dev/null @@ -1,96 +0,0 @@ -#include "include/bits/gthr-default.h" - -#include -#include -#include -#include - -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(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; -} diff --git a/libraries/wutstdc++/gthread_keys.cc b/libraries/wutstdc++/gthread_keys.cc deleted file mode 100644 index 6d654c3..0000000 --- a/libraries/wutstdc++/gthread_keys.cc +++ /dev/null @@ -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); -} diff --git a/libraries/wutstdc++/gthread_mutex.cc b/libraries/wutstdc++/gthread_mutex.cc deleted file mode 100644 index 266250f..0000000 --- a/libraries/wutstdc++/gthread_mutex.cc +++ /dev/null @@ -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; -} diff --git a/libraries/wutstdc++/gthread_once.cc b/libraries/wutstdc++/gthread_once.cc deleted file mode 100644 index 7823dfe..0000000 --- a/libraries/wutstdc++/gthread_once.cc +++ /dev/null @@ -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; -} diff --git a/libraries/wutstdc++/gthread_recursive_mutex.cc b/libraries/wutstdc++/gthread_recursive_mutex.cc deleted file mode 100644 index 8a1011e..0000000 --- a/libraries/wutstdc++/gthread_recursive_mutex.cc +++ /dev/null @@ -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; -} diff --git a/libraries/wutstdc++/include/bits/gthr-default.h b/libraries/wutstdc++/include/bits/gthr-default.h deleted file mode 100644 index 684097e..0000000 --- a/libraries/wutstdc++/include/bits/gthr-default.h +++ /dev/null @@ -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 -. */ - -#ifndef _GLIBCXX_GCC_GTHR_SINGLE_H -#define _GLIBCXX_GCC_GTHR_SINGLE_H - -#define __GTHREADS 1 -#define __GTHREADS_CXX0X 1 - -#include -#include -#include -#include -#include -#include - -#include -#include - -#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 */ diff --git a/libraries/wutstdc++/mutex.cc b/libraries/wutstdc++/mutex.cc deleted file mode 100644 index b62bf87..0000000 --- a/libraries/wutstdc++/mutex.cc +++ /dev/null @@ -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 -// . - -#include - -#if defined(_GLIBCXX_HAS_GTHREADS) && defined(_GLIBCXX_USE_C99_STDINT_TR1) -#ifndef _GLIBCXX_HAVE_TLS -namespace -{ - inline std::unique_lock*& - __get_once_functor_lock_ptr() - { - static std::unique_lock* __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; - function __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* __ptr) - { - __get_once_functor_lock_ptr() = __ptr; - } - - // unsafe - retained for compatibility with ABI 3.4.11 - unique_lock& - __get_once_functor_lock() - { - static unique_lock once_functor_lock(__get_once_mutex(), defer_lock); - return once_functor_lock; - } -#endif - - extern "C" - { - void __once_proxy() - { -#ifndef _GLIBCXX_HAVE_TLS - function __once_call = std::move(__once_functor); - if (unique_lock* __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 diff --git a/libraries/wutstdc++/shared_ptr.cc b/libraries/wutstdc++/shared_ptr.cc deleted file mode 100644 index 426839e..0000000 --- a/libraries/wutstdc++/shared_ptr.cc +++ /dev/null @@ -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 -// . - -#include - -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 diff --git a/libraries/wutstdc++/thread.cc b/libraries/wutstdc++/thread.cc deleted file mode 100644 index c282935..0000000 --- a/libraries/wutstdc++/thread.cc +++ /dev/null @@ -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 -// . - - -#define _GLIBCXX_THREAD_ABI_COMPAT 1 -#include -#include -#include -#include - -#if defined(_GLIBCXX_HAS_GTHREADS) && defined(_GLIBCXX_USE_C99_STDINT_TR1) - -#if defined(_GLIBCXX_USE_GET_NPROCS) -# include -# 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 -# include -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 -# define _GLIBCXX_NPROCS sysconf(_SC_NPROCESSORS_ONLN) -#elif defined(_GLIBCXX_USE_SC_NPROC_ONLN) -# include -# define _GLIBCXX_NPROCS sysconf(_SC_NPROC_ONLN) -#else -# define _GLIBCXX_NPROCS 0 -#endif - -#ifndef _GLIBCXX_USE_NANOSLEEP -# ifdef _GLIBCXX_HAVE_SLEEP -# include -# elif defined(_GLIBCXX_HAVE_WIN32_SLEEP) -# include -# 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(__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(__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(__s.count()), - static_cast(__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 diff --git a/libraries/wutstdc++/wut_gthread.cc b/libraries/wutstdc++/wut_gthread.cc new file mode 100644 index 0000000..176f9ad --- /dev/null +++ b/libraries/wutstdc++/wut_gthread.cc @@ -0,0 +1,78 @@ +#include "wut_gthread.h" +#include + +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" diff --git a/libraries/wutstdc++/wut_gthread.h b/libraries/wutstdc++/wut_gthread.h new file mode 100644 index 0000000..d4f53fc --- /dev/null +++ b/libraries/wutstdc++/wut_gthread.h @@ -0,0 +1,122 @@ +#pragma once +#include + +#include +#include +#include +#include +#include +#include + +#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); diff --git a/libraries/wutstdc++/wut_gthread_cond.cc b/libraries/wutstdc++/wut_gthread_cond.cc new file mode 100644 index 0000000..6032a14 --- /dev/null +++ b/libraries/wutstdc++/wut_gthread_cond.cc @@ -0,0 +1,100 @@ +#include "wut_gthread.h" + +#include + +#include +#include +#include +#include + +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(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; +} diff --git a/libraries/wutstdc++/wut_gthread_keys.cc b/libraries/wutstdc++/wut_gthread_keys.cc new file mode 100644 index 0000000..5db4642 --- /dev/null +++ b/libraries/wutstdc++/wut_gthread_keys.cc @@ -0,0 +1,102 @@ +#include "wut_gthread.h" +#include +#include + +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); +} diff --git a/libraries/wutstdc++/wut_gthread_mutex.cc b/libraries/wutstdc++/wut_gthread_mutex.cc new file mode 100644 index 0000000..1dae3f8 --- /dev/null +++ b/libraries/wutstdc++/wut_gthread_mutex.cc @@ -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; +} diff --git a/libraries/wutstdc++/wut_gthread_once.cc b/libraries/wutstdc++/wut_gthread_once.cc new file mode 100644 index 0000000..5e7a03c --- /dev/null +++ b/libraries/wutstdc++/wut_gthread_once.cc @@ -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; +} diff --git a/libraries/wutstdc++/wut_gthread_recursive_mutex.cc b/libraries/wutstdc++/wut_gthread_recursive_mutex.cc new file mode 100644 index 0000000..7664b47 --- /dev/null +++ b/libraries/wutstdc++/wut_gthread_recursive_mutex.cc @@ -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; +} diff --git a/libraries/wutstdc++/wut_gthread_thread.cc b/libraries/wutstdc++/wut_gthread_thread.cc new file mode 100644 index 0000000..4bccdd8 --- /dev/null +++ b/libraries/wutstdc++/wut_gthread_thread.cc @@ -0,0 +1,86 @@ +#include "wut_gthread.h" + +#include +#include + +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; +} diff --git a/share/wut.cmake b/share/wut.cmake index 172a90a..9237bd4 100644 --- a/share/wut.cmake +++ b/share/wut.cmake @@ -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)