From a514b3bd16e4f21202cc001d9294ac2c2f206c3d Mon Sep 17 00:00:00 2001 From: "Man, Jianting (Meco)" <920369182@qq.com> Date: Fri, 25 Mar 2022 11:07:18 -0400 Subject: [components][kconfig] 整理Kconfig目录名称和结构 (#5698) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- components/Kconfig | 16 +- components/cplusplus/Kconfig | 19 - components/cplusplus/README.md | 52 --- components/cplusplus/SConscript | 23 - components/cplusplus/cpp11/README.md | 49 -- components/cplusplus/cpp11/README_ZH.md | 48 -- components/cplusplus/cpp11/armclang/clock.cpp | 29 -- components/cplusplus/cpp11/armclang/condvar.cpp | 178 ------- .../cplusplus/cpp11/armclang/miscellaneous.cpp | 22 - components/cplusplus/cpp11/armclang/mutex.cpp | 108 ----- components/cplusplus/cpp11/armclang/thread.cpp | 120 ----- components/cplusplus/cpp11/armclang/tpl.h | 56 --- components/cplusplus/cpp11/atomic_8.c | 88 ---- components/cplusplus/cpp11/emutls.c | 216 --------- .../cpp11/figures/Snipaste_2021-09-02_16-00-09.png | Bin 24214 -> 0 bytes components/cplusplus/cpp11/gcc/__utils.h | 59 --- components/cplusplus/cpp11/gcc/condition_variable | 222 --------- .../cplusplus/cpp11/gcc/condition_variable.cpp | 34 -- components/cplusplus/cpp11/gcc/future | 336 -------------- components/cplusplus/cpp11/gcc/mutex | 512 --------------------- components/cplusplus/cpp11/gcc/mutex.cpp | 52 --- components/cplusplus/cpp11/gcc/thread | 239 ---------- components/cplusplus/cpp11/gcc/thread.cpp | 94 ---- components/cplusplus/cpp11/gcc/utils.cpp | 29 -- components/cplusplus/cpp11/thread_local_impl.cpp | 34 -- components/cplusplus/cxx_Mutex.cpp | 44 -- components/cplusplus/cxx_Semaphore.cpp | 39 -- components/cplusplus/cxx_Thread.cpp | 117 ----- components/cplusplus/cxx_crt.cpp | 37 -- components/cplusplus/cxx_crt.h | 26 -- components/cplusplus/cxx_crt_init.c | 68 --- components/cplusplus/cxx_lock.h | 28 -- components/cplusplus/cxx_mail.h | 81 ---- components/cplusplus/cxx_mutex.h | 46 -- components/cplusplus/cxx_queue.h | 74 --- components/cplusplus/cxx_semaphore.h | 42 -- components/cplusplus/cxx_thread.h | 67 --- components/dfs/Kconfig | 8 +- components/fal/Kconfig | 2 +- components/finsh/Kconfig | 17 +- components/libc/Kconfig | 3 +- components/libc/cplusplus/Kconfig | 15 + components/libc/cplusplus/README.md | 52 +++ components/libc/cplusplus/SConscript | 23 + components/libc/cplusplus/cpp11/README.md | 49 ++ components/libc/cplusplus/cpp11/README_ZH.md | 48 ++ components/libc/cplusplus/cpp11/armclang/clock.cpp | 29 ++ .../libc/cplusplus/cpp11/armclang/condvar.cpp | 178 +++++++ .../cplusplus/cpp11/armclang/miscellaneous.cpp | 22 + components/libc/cplusplus/cpp11/armclang/mutex.cpp | 108 +++++ .../libc/cplusplus/cpp11/armclang/thread.cpp | 120 +++++ components/libc/cplusplus/cpp11/armclang/tpl.h | 56 +++ components/libc/cplusplus/cpp11/atomic_8.c | 88 ++++ components/libc/cplusplus/cpp11/emutls.c | 216 +++++++++ .../cpp11/figures/Snipaste_2021-09-02_16-00-09.png | Bin 0 -> 24214 bytes components/libc/cplusplus/cpp11/gcc/__utils.h | 59 +++ .../libc/cplusplus/cpp11/gcc/condition_variable | 222 +++++++++ .../cplusplus/cpp11/gcc/condition_variable.cpp | 34 ++ components/libc/cplusplus/cpp11/gcc/future | 336 ++++++++++++++ components/libc/cplusplus/cpp11/gcc/mutex | 512 +++++++++++++++++++++ components/libc/cplusplus/cpp11/gcc/mutex.cpp | 52 +++ components/libc/cplusplus/cpp11/gcc/thread | 239 ++++++++++ components/libc/cplusplus/cpp11/gcc/thread.cpp | 94 ++++ components/libc/cplusplus/cpp11/gcc/utils.cpp | 29 ++ .../libc/cplusplus/cpp11/thread_local_impl.cpp | 34 ++ components/libc/cplusplus/cxx_Mutex.cpp | 44 ++ components/libc/cplusplus/cxx_Semaphore.cpp | 39 ++ components/libc/cplusplus/cxx_Thread.cpp | 117 +++++ components/libc/cplusplus/cxx_crt.cpp | 37 ++ components/libc/cplusplus/cxx_crt.h | 26 ++ components/libc/cplusplus/cxx_crt_init.c | 68 +++ components/libc/cplusplus/cxx_lock.h | 28 ++ components/libc/cplusplus/cxx_mail.h | 81 ++++ components/libc/cplusplus/cxx_mutex.h | 46 ++ components/libc/cplusplus/cxx_queue.h | 74 +++ components/libc/cplusplus/cxx_semaphore.h | 42 ++ components/libc/cplusplus/cxx_thread.h | 67 +++ components/libc/posix/Kconfig | 6 +- components/lwp/Kconfig | 2 +- components/net/lwip/Kconfig | 2 +- components/net/sal/Kconfig | 2 +- components/vbus/Kconfig | 24 +- 82 files changed, 3314 insertions(+), 3340 deletions(-) delete mode 100644 components/cplusplus/Kconfig delete mode 100644 components/cplusplus/README.md delete mode 100644 components/cplusplus/SConscript delete mode 100644 components/cplusplus/cpp11/README.md delete mode 100644 components/cplusplus/cpp11/README_ZH.md delete mode 100644 components/cplusplus/cpp11/armclang/clock.cpp delete mode 100644 components/cplusplus/cpp11/armclang/condvar.cpp delete mode 100644 components/cplusplus/cpp11/armclang/miscellaneous.cpp delete mode 100644 components/cplusplus/cpp11/armclang/mutex.cpp delete mode 100644 components/cplusplus/cpp11/armclang/thread.cpp delete mode 100644 components/cplusplus/cpp11/armclang/tpl.h delete mode 100644 components/cplusplus/cpp11/atomic_8.c delete mode 100644 components/cplusplus/cpp11/emutls.c delete mode 100644 components/cplusplus/cpp11/figures/Snipaste_2021-09-02_16-00-09.png delete mode 100644 components/cplusplus/cpp11/gcc/__utils.h delete mode 100644 components/cplusplus/cpp11/gcc/condition_variable delete mode 100644 components/cplusplus/cpp11/gcc/condition_variable.cpp delete mode 100644 components/cplusplus/cpp11/gcc/future delete mode 100644 components/cplusplus/cpp11/gcc/mutex delete mode 100644 components/cplusplus/cpp11/gcc/mutex.cpp delete mode 100644 components/cplusplus/cpp11/gcc/thread delete mode 100644 components/cplusplus/cpp11/gcc/thread.cpp delete mode 100644 components/cplusplus/cpp11/gcc/utils.cpp delete mode 100644 components/cplusplus/cpp11/thread_local_impl.cpp delete mode 100644 components/cplusplus/cxx_Mutex.cpp delete mode 100644 components/cplusplus/cxx_Semaphore.cpp delete mode 100644 components/cplusplus/cxx_Thread.cpp delete mode 100644 components/cplusplus/cxx_crt.cpp delete mode 100644 components/cplusplus/cxx_crt.h delete mode 100644 components/cplusplus/cxx_crt_init.c delete mode 100644 components/cplusplus/cxx_lock.h delete mode 100644 components/cplusplus/cxx_mail.h delete mode 100644 components/cplusplus/cxx_mutex.h delete mode 100644 components/cplusplus/cxx_queue.h delete mode 100644 components/cplusplus/cxx_semaphore.h delete mode 100644 components/cplusplus/cxx_thread.h create mode 100644 components/libc/cplusplus/Kconfig create mode 100644 components/libc/cplusplus/README.md create mode 100644 components/libc/cplusplus/SConscript create mode 100644 components/libc/cplusplus/cpp11/README.md create mode 100644 components/libc/cplusplus/cpp11/README_ZH.md create mode 100644 components/libc/cplusplus/cpp11/armclang/clock.cpp create mode 100644 components/libc/cplusplus/cpp11/armclang/condvar.cpp create mode 100644 components/libc/cplusplus/cpp11/armclang/miscellaneous.cpp create mode 100644 components/libc/cplusplus/cpp11/armclang/mutex.cpp create mode 100644 components/libc/cplusplus/cpp11/armclang/thread.cpp create mode 100644 components/libc/cplusplus/cpp11/armclang/tpl.h create mode 100644 components/libc/cplusplus/cpp11/atomic_8.c create mode 100644 components/libc/cplusplus/cpp11/emutls.c create mode 100644 components/libc/cplusplus/cpp11/figures/Snipaste_2021-09-02_16-00-09.png create mode 100644 components/libc/cplusplus/cpp11/gcc/__utils.h create mode 100644 components/libc/cplusplus/cpp11/gcc/condition_variable create mode 100644 components/libc/cplusplus/cpp11/gcc/condition_variable.cpp create mode 100644 components/libc/cplusplus/cpp11/gcc/future create mode 100644 components/libc/cplusplus/cpp11/gcc/mutex create mode 100644 components/libc/cplusplus/cpp11/gcc/mutex.cpp create mode 100644 components/libc/cplusplus/cpp11/gcc/thread create mode 100644 components/libc/cplusplus/cpp11/gcc/thread.cpp create mode 100644 components/libc/cplusplus/cpp11/gcc/utils.cpp create mode 100644 components/libc/cplusplus/cpp11/thread_local_impl.cpp create mode 100644 components/libc/cplusplus/cxx_Mutex.cpp create mode 100644 components/libc/cplusplus/cxx_Semaphore.cpp create mode 100644 components/libc/cplusplus/cxx_Thread.cpp create mode 100644 components/libc/cplusplus/cxx_crt.cpp create mode 100644 components/libc/cplusplus/cxx_crt.h create mode 100644 components/libc/cplusplus/cxx_crt_init.c create mode 100644 components/libc/cplusplus/cxx_lock.h create mode 100644 components/libc/cplusplus/cxx_mail.h create mode 100644 components/libc/cplusplus/cxx_mutex.h create mode 100644 components/libc/cplusplus/cxx_queue.h create mode 100644 components/libc/cplusplus/cxx_semaphore.h create mode 100644 components/libc/cplusplus/cxx_thread.h diff --git a/components/Kconfig b/components/Kconfig index cd222c933b..893858c733 100644 --- a/components/Kconfig +++ b/components/Kconfig @@ -23,24 +23,14 @@ config RT_USING_LEGACY bool "Support legacy version for compatibility" default n -source "$RTT_DIR/components/cplusplus/Kconfig" - -source "$RTT_DIR/components/fal/Kconfig" - source "$RTT_DIR/components/finsh/Kconfig" - source "$RTT_DIR/components/dfs/Kconfig" - +source "$RTT_DIR/components/fal/Kconfig" +source "$RTT_DIR/components/lwp/Kconfig" source "$RTT_DIR/components/drivers/Kconfig" - source "$RTT_DIR/components/libc/Kconfig" - source "$RTT_DIR/components/net/Kconfig" - -source "$RTT_DIR/components/vbus/Kconfig" - source "$RTT_DIR/components/utilities/Kconfig" - -source "$RTT_DIR/components/lwp/Kconfig" +source "$RTT_DIR/components/vbus/Kconfig" endmenu diff --git a/components/cplusplus/Kconfig b/components/cplusplus/Kconfig deleted file mode 100644 index 0877ff9938..0000000000 --- a/components/cplusplus/Kconfig +++ /dev/null @@ -1,19 +0,0 @@ -menu "C++ features" - -config RT_USING_CPLUSPLUS - bool "Support C++ features" - default n - -if RT_USING_CPLUSPLUS - - config RT_USING_CPLUSPLUS11 - bool "Enable c++11 threading feature support" - default n - select RT_USING_POSIX_FS - select RT_USING_POSIX_STDIO - select RT_USING_PTHREADS - select RT_USING_RTC - -endif - -endmenu diff --git a/components/cplusplus/README.md b/components/cplusplus/README.md deleted file mode 100644 index 46c8c78a69..0000000000 --- a/components/cplusplus/README.md +++ /dev/null @@ -1,52 +0,0 @@ -# C++ support for RT-Thread # - -This is the C++ component in RT-Thread RTOS. In order to support C++ language, this component -implement a basic environment, such as new/delete operators. - -Because RT-Thread RTOS is used in embedded system mostly, there are some rules for C++ applications: - -1. DOES NOT use exception. -2. DOES NOT use Run-Time Type Information (RTTI). -3. Template is discouraged and it easily causes code text large. -4. Static class variables are discouraged. The time and place to call their constructor function could not be precisely controlled and make multi-threaded programming a nightmare. -5. Multiple inheritance is strongly discouraged, as it can cause intolerable confusion. - -About GNU GCC compiler - -please add following string in your ld link script: - - // in your .text section - PROVIDE(__ctors_start__ = .); - /* old GCC version uses .ctors */ - KEEP(*(SORT(.ctors.*))) - KEEP(*(.ctors)) - /* new GCC version uses .init_array */ - KEEP (*(SORT(.init_array.*))) - KEEP (*(.init_array)) - PROVIDE(__ctors_end__ = .); - - . = ALIGN(4); - - // as a standalone section if you use ARM target. - - /* The .ARM.exidx section is used for C++ exception handling. */ - /* .ARM.exidx is sorted, so has to go in its own output section. */ - __exidx_start = .; - ARM.exidx : - { - *(.ARM.exidx* .gnu.linkonce.armexidx.*) - - /* This is used by the startup in order to initialize the .data secion */ - _sidata = .; - } > CODE - __exidx_end = .; - - /* .data section which is used for initialized data */ - - // in your .data section - PROVIDE(__dtors_start__ = .); - KEEP(*(SORT(.dtors.*))) - KEEP(*(.dtors)) - PROVIDE(__dtors_end__ = .); - - . = ALIGN(4); diff --git a/components/cplusplus/SConscript b/components/cplusplus/SConscript deleted file mode 100644 index 325a27f65f..0000000000 --- a/components/cplusplus/SConscript +++ /dev/null @@ -1,23 +0,0 @@ -# RT-Thread building script for component - -from building import * -Import('rtconfig') - -cwd = GetCurrentDir() -src = Glob('*.cpp') + Glob('*.c') - -if GetDepend('RT_USING_CPLUSPLUS11'): - src += Glob('cpp11/*.cpp') + Glob('cpp11/*.c') - -CPPPATH = [cwd] - -if rtconfig.PLATFORM == 'armclang' and GetDepend('RT_USING_CPLUSPLUS11'): - src += Glob('cpp11/armclang/*.cpp') + Glob('cpp11/armclang/*.c') - CPPPATH += [cwd + '/cpp11/armclang'] -elif rtconfig.PLATFORM == 'gcc' and GetDepend('RT_USING_CPLUSPLUS11'): - src += Glob('cpp11/gcc/*.cpp') + Glob('cpp11/gcc/*.c') - CPPPATH += [cwd + '/cpp11/gcc'] - -group = DefineGroup('CPlusPlus', src, depend = ['RT_USING_CPLUSPLUS'], CPPPATH = CPPPATH) - -Return('group') \ No newline at end of file diff --git a/components/cplusplus/cpp11/README.md b/components/cplusplus/cpp11/README.md deleted file mode 100644 index a292051608..0000000000 --- a/components/cplusplus/cpp11/README.md +++ /dev/null @@ -1,49 +0,0 @@ -# C++ 11 support for RT-Thread - -## Features - -Here are some features about rt-thread c++11 threading futures. - -- Atomic. -- Conditional variables. -- Clocks. -- Future. -- Mutexes. -- Threads. -- TLS. - -## How To Use - -Note that using C++ 11 in rt-thread requires modifying some of the files in the toolchain. Before modifying the tool, back up the tool chain. - -1. Enable c++11 support - - ![](figures/Snipaste_2021-09-02_16-00-09.png) - -2. Download toolchain GCC 10.2.1: - - ```shell - gcc version 10.2.1 20201103 (release) (GNU Arm Embedded Toolchain 10-2020-q4-major) - ``` - -3. Delete the following files: - - ```shell - rm -f toolchain/arm-none-eabi/include/c++/10.2.1/thread - rm -f toolchain/arm-none-eabi/include/c++/10.2.1/mutex - rm -f toolchain/arm-none-eabi/include/c++/10.2.1/condition_variable - rm -f toolchain/arm-none-eabi/include/c++/10.2.1/future - rm -f toolchain/arm-none-eabi/include/pthread.h - ``` - -4. Clear the contents of the following files and keep them to prevent compilation failures: - - ```shell - toolchain/arm-none-eabi/include/sys/_pthreadtypes.h - ``` - -5. Update `rtconfig.py` file. add compilation parameters: - - ```shell - CXXFLAGS = CFLAGS + ' -std=c++11 -fabi-version=0 -MMD -MP -MF' - ``` diff --git a/components/cplusplus/cpp11/README_ZH.md b/components/cplusplus/cpp11/README_ZH.md deleted file mode 100644 index e46bcb90c4..0000000000 --- a/components/cplusplus/cpp11/README_ZH.md +++ /dev/null @@ -1,48 +0,0 @@ -# cpp 11 support for rt-thread - -## 特性 - -下面是 RT-Thread 支持的 C++ 11 线程特性。 - -- Atomic. -- Conditional variables. -- Clocks. -- Future. -- Mutexes. -- Threads. -- TLS. - -## 如何使用 - -请注意,在 RT-Thread 中使用 C++ 11,需要修改工具链中的部分文件。请在修改之前,备份好工具链。 - -1. 使能 c++11 - ![](figures/Snipaste_2021-09-02_16-00-09.png) - -2. 下载 GCC 工具链 - - ```shell - gcc version 10.2.1 20201103 (release) (GNU Arm Embedded Toolchain 10-2020-q4-major) - ``` - -3. 删除下面的文件 - - ```shell - rm -f toolchain/arm-none-eabi/include/c++/10.2.1/thread - rm -f toolchain/arm-none-eabi/include/c++/10.2.1/mutex - rm -f toolchain/arm-none-eabi/include/c++/10.2.1/condition_variable - rm -f toolchain/arm-none-eabi/include/c++/10.2.1/future - rm -f toolchain/arm-none-eabi/include/pthread.h - ``` - -4. 请清除下面文件的内容,保留文件避免编译失败 - - ```shell - toolchain/arm-none-eabi/include/sys/_pthreadtypes.h - ``` - -5. 更新 `rtconfig.py` 文件,添加 c++ 编译参数: - - ```shell - CXXFLAGS = CFLAGS + ' -std=c++11 -fabi-version=0 -MMD -MP -MF' - ``` diff --git a/components/cplusplus/cpp11/armclang/clock.cpp b/components/cplusplus/cpp11/armclang/clock.cpp deleted file mode 100644 index 137af393b0..0000000000 --- a/components/cplusplus/cpp11/armclang/clock.cpp +++ /dev/null @@ -1,29 +0,0 @@ -/* - * Copyright (c) 2006-2021, RT-Thread Development Team - * - * SPDX-License-Identifier: Apache-2.0 - * - * Change Logs: - * Date Author Notes - * 2021-04-27 flybreak the first version. - */ - -#include -#include -#include - -extern "C" int __ARM_TPL_clock_realtime(__ARM_TPL_timespec_t* __ts) -{ - unsigned int t = std::time(nullptr); - __ts->tv_sec = t; - __ts->tv_nsec = 0; - return 0; -} - -extern "C" int __ARM_TPL_clock_monotonic(__ARM_TPL_timespec_t* __ts) -{ - unsigned int t = rt_tick_get(); - __ts->tv_sec = t / RT_TICK_PER_SECOND; - __ts->tv_nsec = (t %RT_TICK_PER_SECOND) * NANOSECOND_PER_TICK ; - return 0; -} diff --git a/components/cplusplus/cpp11/armclang/condvar.cpp b/components/cplusplus/cpp11/armclang/condvar.cpp deleted file mode 100644 index 7943ccee60..0000000000 --- a/components/cplusplus/cpp11/armclang/condvar.cpp +++ /dev/null @@ -1,178 +0,0 @@ -/* - * Copyright (c) 2006-2021, RT-Thread Development Team - * - * SPDX-License-Identifier: Apache-2.0 - * - * Change Logs: - * Date Author Notes - * 2021-04-27 flybreak the first version. - */ - -#include -#include "tpl.h" -#include -#include -#include - -arm_tpl_cv::arm_tpl_cv() -{ - s = rt_sem_create("semxs", 0, RT_IPC_FLAG_PRIO); - if (s == nullptr) - RT_ASSERT(0); - h = rt_sem_create("semxh", 0, RT_IPC_FLAG_PRIO); - if (h == nullptr) - { - rt_sem_delete(s); - RT_ASSERT(0); - } - x = rt_mutex_create("mutx", RT_IPC_FLAG_PRIO); - if (x == nullptr) - { - rt_sem_delete(s); - rt_sem_delete(h); - RT_ASSERT(0); - } -} - -arm_tpl_cv::~arm_tpl_cv() -{ - rt_mutex_delete(x); - rt_sem_delete(h); - rt_sem_delete(s); -} - -void arm_tpl_cv::wait(rt_mutex_t lock, bool recursive) -{ - while (rt_mutex_take(x, ARM_TPL_MAX_DELAY) != 0); - rt_sem_release(s); - rt_mutex_release(x); - if (recursive) - rt_mutex_release(lock); - else - rt_mutex_release(lock); - while (rt_sem_take(h, ARM_TPL_MAX_DELAY) != 0); - if (recursive) - while (rt_mutex_take(lock, ARM_TPL_MAX_DELAY) != 0); - else - while (rt_mutex_take(lock, ARM_TPL_MAX_DELAY) != 0); -} - -int arm_tpl_cv::timedwait(rt_mutex_t lock, bool recursive, unsigned int timeout_ms) -{ - int result = 0; - while (rt_mutex_take(x, ARM_TPL_MAX_DELAY) != 0); - rt_sem_release(s); - rt_mutex_release(x); - if (recursive) - rt_mutex_release(lock); - else - rt_mutex_release(lock); - if (rt_sem_take(h, rt_tick_from_millisecond(timeout_ms)) != 0) - { - while (rt_mutex_take(x, ARM_TPL_MAX_DELAY) != 0); - if (rt_sem_take(h, 0) != 0) - { - if (rt_sem_take(s, 0) != 0) - result = -1; - else - result = 1; - } - rt_mutex_release(x); - } - if (recursive) - while (rt_mutex_take(lock, ARM_TPL_MAX_DELAY) != 0); - else - while (rt_mutex_take(lock, ARM_TPL_MAX_DELAY) != 0); - return result; -} - -void arm_tpl_cv::signal() -{ - while (rt_mutex_take(x, ARM_TPL_MAX_DELAY) != 0); - if (rt_sem_take(s, 0) == 0) - rt_sem_release(h); - rt_mutex_release(x); -} - -void arm_tpl_cv::broadcast() -{ - while (rt_mutex_take(x, ARM_TPL_MAX_DELAY) != 0); - auto count = s->value; - for (auto i = 0; i < count; i++) - { - while (rt_sem_take(s, ARM_TPL_MAX_DELAY) != 0); - rt_sem_release(h); - } - rt_mutex_release(x); -} - -static int check_create(volatile __ARM_TPL_condvar_t *__vcv) -{ - if (__vcv->data == 0) - { - uintptr_t cv_new; - cv_new = reinterpret_cast(new arm_tpl_cv()); - if (cv_new == 0) - { - return -1; - } - uintptr_t cv_null = 0; - if (!atomic_compare_exchange_strong(&__vcv->data, &cv_null, cv_new)) - delete reinterpret_cast(cv_new); - } - return 0; -} - -extern "C" int __ARM_TPL_condvar_wait(__ARM_TPL_condvar_t *__cv, __ARM_TPL_mutex_t *__m) -{ - volatile __ARM_TPL_condvar_t *__vcv = __cv; - if (check_create(__vcv) != 0) - return -1; - struct arm_tpl_mutex_struct *tmutex = (struct arm_tpl_mutex_struct *)(__m->data); - ((arm_tpl_cv *) __vcv->data)->wait(tmutex->mutex, tmutex->type == RECURSIVE); - return 0; -} - -extern "C" int __ARM_TPL_condvar_timedwait(__ARM_TPL_condvar_t *__cv, - __ARM_TPL_mutex_t *__m, - __ARM_TPL_timespec_t *__ts) -{ - volatile __ARM_TPL_condvar_t *__vcv = __cv; - if (check_create(__vcv) != 0) - return -1; - __ARM_TPL_timespec_t now; - if (__ARM_TPL_clock_realtime(&now) != 0) - return -1; - struct arm_tpl_mutex_struct *tmutex = (struct arm_tpl_mutex_struct *)(__m->data); - unsigned int timeout_ms = (__ts->tv_sec - now.tv_sec) * 1000 + (__ts->tv_nsec - now.tv_nsec) / 1000000; - if (((arm_tpl_cv *) __vcv->data)->timedwait(tmutex->mutex, tmutex->type == RECURSIVE, timeout_ms) < 0) - return -1; - return 0; -} - -extern "C" int __ARM_TPL_condvar_signal(__ARM_TPL_condvar_t *__cv) -{ - volatile __ARM_TPL_condvar_t *__vcv = __cv; - if (__vcv->data != 0) - ((arm_tpl_cv *) __vcv->data)->signal(); - return 0; -} - -extern "C" int __ARM_TPL_condvar_broadcast(__ARM_TPL_condvar_t *__cv) -{ - volatile __ARM_TPL_condvar_t *__vcv = __cv; - if (__vcv->data != 0) - ((arm_tpl_cv *) __vcv->data)->broadcast(); - return 0; -} - -extern "C" int __ARM_TPL_condvar_destroy(__ARM_TPL_condvar_t *__cv) -{ - volatile __ARM_TPL_condvar_t *__vcv = __cv; - if (__vcv->data != 0) - { - delete (arm_tpl_cv *) __vcv->data; - __vcv->data = 0; - } - return 0; -} diff --git a/components/cplusplus/cpp11/armclang/miscellaneous.cpp b/components/cplusplus/cpp11/armclang/miscellaneous.cpp deleted file mode 100644 index a084eda8c8..0000000000 --- a/components/cplusplus/cpp11/armclang/miscellaneous.cpp +++ /dev/null @@ -1,22 +0,0 @@ -/* - * Copyright (c) 2006-2021, RT-Thread Development Team - * - * SPDX-License-Identifier: Apache-2.0 - * - * Change Logs: - * Date Author Notes - * 2021-04-27 flybreak the first version. - */ - -#include - -extern "C" int __ARM_TPL_execute_once(__ARM_TPL_exec_once_flag *__flag, - void (*__init_routine)(void)) -{ - if (*__flag == 0) - { - __init_routine(); - *__flag = 1; - } - return 0; -} diff --git a/components/cplusplus/cpp11/armclang/mutex.cpp b/components/cplusplus/cpp11/armclang/mutex.cpp deleted file mode 100644 index 44a70efcf7..0000000000 --- a/components/cplusplus/cpp11/armclang/mutex.cpp +++ /dev/null @@ -1,108 +0,0 @@ -/* - * Copyright (c) 2006-2021, RT-Thread Development Team - * - * SPDX-License-Identifier: Apache-2.0 - * - * Change Logs: - * Date Author Notes - * 2021-04-27 flybreak the first version. - */ - -#include -#include -#include -#include "tpl.h" - -static int check_create(volatile __ARM_TPL_mutex_t *__vm, bool recursive = false) -{ - if (__vm->data == 0) - { - uintptr_t mut_null = 0; - arm_tpl_mutex_struct *mutex_p = (arm_tpl_mutex_struct *)rt_malloc(sizeof(arm_tpl_mutex_struct)); - if (mutex_p == nullptr) return -1; - - if (recursive) - mutex_p->mutex = rt_mutex_create("mutexx", RT_IPC_FLAG_PRIO); - else - mutex_p->mutex = rt_mutex_create("mutexx", RT_IPC_FLAG_PRIO); - - if (mutex_p->mutex == nullptr) - { - rt_free(mutex_p); - return -1; - } - mutex_p->type = recursive ? RECURSIVE : NORMAL; - uintptr_t mut_new = reinterpret_cast(mutex_p); - if (!atomic_compare_exchange_strong(&__vm->data, &mut_null, mut_new)) - { - rt_mutex_delete(mutex_p->mutex); - rt_free(mutex_p); - } - } - return 0; -} - -static int mutexLock(arm_tpl_mutex_struct *mutex_p, rt_tick_t timeOut) -{ - if (mutex_p->type == RECURSIVE) - { - if (rt_mutex_take(mutex_p->mutex, timeOut) == 0) - return 0; - } - else - { - if (rt_mutex_take(mutex_p->mutex, timeOut) == 0) - return 0; - } - return -1; -} - -static int mutexUnlock(arm_tpl_mutex_struct *mutex_p) -{ - if (mutex_p->type == RECURSIVE) - rt_mutex_release(mutex_p->mutex); - else - rt_mutex_release(mutex_p->mutex); - return 0; -} - -extern "C" int __ARM_TPL_recursive_mutex_init(__ARM_TPL_mutex_t *__m) -{ - volatile __ARM_TPL_mutex_t *__vm = __m; - return check_create(__vm, true); -} - -extern "C" int __ARM_TPL_mutex_lock(__ARM_TPL_mutex_t *__m) -{ - volatile __ARM_TPL_mutex_t *__vm = __m; - if (check_create(__vm)) - return -1; - while (mutexLock((arm_tpl_mutex_struct *)(__vm->data), ARM_TPL_MAX_DELAY) != 0); - return 0; -} - -extern "C" int __ARM_TPL_mutex_trylock(__ARM_TPL_mutex_t *__m) -{ - volatile __ARM_TPL_mutex_t *__vm = __m; - if (check_create(__vm)) - return -1; - return mutexLock((arm_tpl_mutex_struct *)(__vm->data), 0); -} - -extern "C" int __ARM_TPL_mutex_unlock(__ARM_TPL_mutex_t *__m) -{ - volatile __ARM_TPL_mutex_t *__vm = __m; - return mutexUnlock((arm_tpl_mutex_struct *)(__vm->data)); -} - -extern "C" int __ARM_TPL_mutex_destroy(__ARM_TPL_mutex_t *__m) -{ - volatile __ARM_TPL_mutex_t *__vm = __m; - if (__vm->data != 0) - { - rt_mutex_delete(((arm_tpl_mutex_struct *)(__vm->data))->mutex); - rt_free((void *)(__vm->data)); - __vm->data = 0; - } - return 0; -} diff --git a/components/cplusplus/cpp11/armclang/thread.cpp b/components/cplusplus/cpp11/armclang/thread.cpp deleted file mode 100644 index e10ffb9cfe..0000000000 --- a/components/cplusplus/cpp11/armclang/thread.cpp +++ /dev/null @@ -1,120 +0,0 @@ -/* - * Copyright (c) 2006-2021, RT-Thread Development Team - * - * SPDX-License-Identifier: Apache-2.0 - * - * Change Logs: - * Date Author Notes - * 2021-04-27 flybreak the first version. - */ - -#include -#include "tpl.h" -#include -#include - -#define CPP11_DEFAULT_ID_OFFSET 1 - -extern "C" int __ARM_TPL_thread_create(__ARM_TPL_thread_t *__t, - void *(*__func)(void *), - void *__arg) -{ - int ret = 0; - pthread_t pid; - ret = pthread_create(&pid, RT_NULL, __func, __arg); - if (ret == 0) - { - __t->data = (std::uintptr_t)pid + CPP11_DEFAULT_ID_OFFSET; - return 0; - } - return -1; -} - -extern "C" int __ARM_TPL_thread_id_compare(__ARM_TPL_thread_id __tid1, - __ARM_TPL_thread_id __tid2) -{ - if (__tid1 > __tid2) - return 1; - else if (__tid1 < __tid2) - return -1; - else - return 0; -} - -extern "C" __ARM_TPL_thread_id __ARM_TPL_thread_get_current_id() -{ - return (__ARM_TPL_thread_id)pthread_self(); -} - -extern "C" __ARM_TPL_thread_id __ARM_TPL_thread_get_id( - const __ARM_TPL_thread_t *__t) -{ - return (__ARM_TPL_thread_id)(((pthread_t)__t->data - CPP11_DEFAULT_ID_OFFSET)); -} - -extern "C" int __ARM_TPL_thread_join(__ARM_TPL_thread_t *__t) -{ - pthread_join(((pthread_t)__t->data - CPP11_DEFAULT_ID_OFFSET), RT_NULL); - return 0; -} - -extern "C" int __ARM_TPL_thread_detach(__ARM_TPL_thread_t *__t) -{ - pthread_detach(((pthread_t)__t->data - CPP11_DEFAULT_ID_OFFSET)); - return 0; -} - -extern "C" void __ARM_TPL_thread_yield() -{ - rt_thread_yield(); -} - -extern "C" int __ARM_TPL_thread_nanosleep(const __ARM_TPL_timespec_t *__req, - __ARM_TPL_timespec_t *__rem) -{ - rt_tick_t tick; - - tick = __req->tv_sec * RT_TICK_PER_SECOND + (__req->tv_nsec * RT_TICK_PER_SECOND)/ 1000000000; - rt_thread_delay(tick); - - if (__rem) - { - tick = rt_tick_get() - tick; - /* get the passed time */ - __rem->tv_sec = tick/RT_TICK_PER_SECOND; - __rem->tv_nsec = (tick%RT_TICK_PER_SECOND) * (1000000000/RT_TICK_PER_SECOND); - } - return 0; -} - -extern "C" unsigned __ARM_TPL_thread_hw_concurrency() -{ - return 1; -} - -extern "C" int __ARM_TPL_tls_create(__ARM_TPL_tls_key *__key, - void (*__at_exit)(void *)) -{ - pthread_key_t key; - - if (pthread_key_create(&key, __at_exit) == 0) - { - *__key = key; - return 0; - } - return -1; -} - -extern "C" void *__ARM_TPL_tls_get(__ARM_TPL_tls_key __key) -{ - return pthread_getspecific(__key); -} - -extern "C" int __ARM_TPL_tls_set(__ARM_TPL_tls_key __key, void *__p) -{ - if (pthread_setspecific(__key, (void*)__p) != 0) - { - return -1; - } - return 0; -} diff --git a/components/cplusplus/cpp11/armclang/tpl.h b/components/cplusplus/cpp11/armclang/tpl.h deleted file mode 100644 index 70c9503cec..0000000000 --- a/components/cplusplus/cpp11/armclang/tpl.h +++ /dev/null @@ -1,56 +0,0 @@ -/* - * Copyright (c) 2006-2021, RT-Thread Development Team - * - * SPDX-License-Identifier: Apache-2.0 - * - * Change Logs: - * Date Author Notes - * 2021-04-27 flybreak the first version. - */ - -#pragma once -#ifndef __cplusplus -void ARMTPLInit(); -#else -#include - -#define ARM_TPL_MAX_DELAY 1000 -#define ARM_TPL_THREAD_STACK_SIZE 4096 - -enum arm_tpl_mutex_type -{ - NORMAL, - RECURSIVE, -}; - -struct arm_tpl_mutex_struct -{ - rt_mutex_t mutex; - arm_tpl_mutex_type type; -}; - -struct arm_tpl_thread_struct -{ - rt_thread_t task; - void *(*func)(void *); - void *arg; - rt_sem_t join_sem; - rt_sem_t detach_sem; -}; - -class arm_tpl_cv -{ -public: - arm_tpl_cv(); - ~arm_tpl_cv(); - void wait(rt_mutex_t lock, bool recursive); - int timedwait(rt_mutex_t lock, bool recursive, unsigned int timeout_ms); - void signal(); - void broadcast(); -private: - rt_sem_t s; - rt_sem_t h; - rt_mutex_t x; -}; - -#endif diff --git a/components/cplusplus/cpp11/atomic_8.c b/components/cplusplus/cpp11/atomic_8.c deleted file mode 100644 index 64d3311b4a..0000000000 --- a/components/cplusplus/cpp11/atomic_8.c +++ /dev/null @@ -1,88 +0,0 @@ -/* - * Copyright (c) 2006-2021, RT-Thread Development Team - * - * SPDX-License-Identifier: Apache-2.0 - * - * Change Logs: - * Date Author Notes - * 2021-04-27 peterfan Add copyright header. - */ - -#include -#include -#include - -/* -* override gcc builtin atomic function for std::atomic, std::atomic -* @see https://gcc.gnu.org/onlinedocs/gcc/_005f_005fatomic-Builtins.html -*/ -uint64_t __atomic_load_8(volatile void *ptr, int memorder) -{ - volatile uint64_t *val_ptr = (volatile uint64_t *)ptr; - register rt_base_t level; - uint64_t tmp; - level = rt_hw_interrupt_disable(); - tmp = *val_ptr; - rt_hw_interrupt_enable(level); - return tmp; -} - -void __atomic_store_8(volatile void *ptr, uint64_t val, int memorder) -{ - volatile uint64_t *val_ptr = (volatile uint64_t *)ptr; - register rt_base_t level; - level = rt_hw_interrupt_disable(); - *val_ptr = val; - rt_hw_interrupt_enable(level); -} - -uint64_t __atomic_exchange_8(volatile void *ptr, uint64_t val, int memorder) -{ - volatile uint64_t *val_ptr = (volatile uint64_t *)ptr; - register rt_base_t level; - uint64_t tmp; - level = rt_hw_interrupt_disable(); - tmp = *val_ptr; - *val_ptr = val; - rt_hw_interrupt_enable(level); - return tmp; -} - -bool __atomic_compare_exchange_8(volatile void *ptr, volatile void *expected, uint64_t desired, bool weak, int success_memorder, int failure_memorder) -{ - volatile uint64_t *val_ptr = (volatile uint64_t *)ptr; - volatile uint64_t *expected_ptr = (volatile uint64_t *)expected; - register rt_base_t level; - bool exchanged; - level = rt_hw_interrupt_disable(); - if (*val_ptr == *expected_ptr) - { - *val_ptr = desired; - exchanged = true; - } - else - { - *expected_ptr = *val_ptr; - exchanged = false; - } - rt_hw_interrupt_enable(level); - return exchanged; -} - -#define __atomic_fetch_op_8(OPNAME, OP) \ -uint64_t __atomic_fetch_##OPNAME##_8(volatile void *ptr, uint64_t val, int memorder) {\ - volatile uint64_t* val_ptr = (volatile uint64_t*)ptr;\ - register rt_base_t level;\ - uint64_t tmp;\ - level = rt_hw_interrupt_disable();\ - tmp = *val_ptr;\ - *val_ptr OP##= val;\ - rt_hw_interrupt_enable(level);\ - return tmp;\ -} - -__atomic_fetch_op_8(add, +) -__atomic_fetch_op_8(sub, -) -__atomic_fetch_op_8( and, &) -__atomic_fetch_op_8( or, |) -__atomic_fetch_op_8(xor, ^) diff --git a/components/cplusplus/cpp11/emutls.c b/components/cplusplus/cpp11/emutls.c deleted file mode 100644 index 576888f16f..0000000000 --- a/components/cplusplus/cpp11/emutls.c +++ /dev/null @@ -1,216 +0,0 @@ -/* - * Copyright (c) 2006-2021, RT-Thread Development Team - * - * SPDX-License-Identifier: Apache-2.0 - * - * Change Logs: - * Date Author Notes - * 2021-04-27 peterfan Add copyright header. - */ - -/* ===---------- emutls.c - Implements __emutls_get_address ---------------=== - * - * The LLVM Compiler Infrastructure - * - * This file is dual licensed under the MIT and the University of Illinois Open - * Source Licenses. See LICENSE.TXT for details. - * - * ===----------------------------------------------------------------------=== - */ - -#include -#include -#include -#include - -#define COMPILE_TIME_ASSERT(x) - -extern int pthread_key_create(pthread_key_t *key, void (*destructor)(void *)); -extern int pthread_key_delete(pthread_key_t key); -extern void *pthread_getspecific(pthread_key_t key); -extern int pthread_setspecific(pthread_key_t key, const void *value); - -/* Default is not to use posix_memalign, so systems like Android - * can use thread local data without heavier POSIX memory allocators. - */ -#ifndef EMUTLS_USE_POSIX_MEMALIGN -#define EMUTLS_USE_POSIX_MEMALIGN 0 -#endif - -/* For every TLS variable xyz, - * there is one __emutls_control variable named __emutls_v.xyz. - * If xyz has non-zero initial value, __emutls_v.xyz's "value" - * will point to __emutls_t.xyz, which has the initial value. - */ -typedef struct __emutls_control -{ - size_t size; /* size of the object in bytes */ - size_t align; /* alignment of the object in bytes */ - union - { - uintptr_t index; /* data[index-1] is the object address */ - void *address; /* object address, when in single thread env */ - } object; - void *value; /* null or non-zero initial value for the object */ -} __emutls_control; - -static __inline void *emutls_memalign_alloc(size_t align, size_t size) -{ - void *base; -#if EMUTLS_USE_POSIX_MEMALIGN - if (posix_memalign(&base, align, size) != 0) - abort(); -#else -#define EXTRA_ALIGN_PTR_BYTES (align - 1 + sizeof(void *)) - char *object; - if ((object = malloc(EXTRA_ALIGN_PTR_BYTES + size)) == NULL) - abort(); - base = (void *)(((uintptr_t)(object + EXTRA_ALIGN_PTR_BYTES)) & ~(uintptr_t)(align - 1)); - - ((void **)base)[-1] = object; -#endif - return base; -} - -static __inline void emutls_memalign_free(void *base) -{ -#if EMUTLS_USE_POSIX_MEMALIGN - free(base); -#else - /* The mallocated address is in ((void**)base)[-1] */ - free(((void **)base)[-1]); -#endif -} - -/* Emulated TLS objects are always allocated at run-time. */ -static __inline void *emutls_allocate_object(__emutls_control *control) -{ - /* Use standard C types, check with gcc's emutls.o. */ - typedef unsigned int gcc_word __attribute__((mode(word))); - typedef unsigned int gcc_pointer __attribute__((mode(pointer))); - COMPILE_TIME_ASSERT(sizeof(size_t) == sizeof(gcc_word)); - COMPILE_TIME_ASSERT(sizeof(uintptr_t) == sizeof(gcc_pointer)); - COMPILE_TIME_ASSERT(sizeof(uintptr_t) == sizeof(void *)); - - size_t size = control->size; - size_t align = control->align; - if (align < sizeof(void *)) - align = sizeof(void *); - /* Make sure that align is power of 2. */ - if ((align & (align - 1)) != 0) - abort(); - - void *base = emutls_memalign_alloc(align, size); - if (control->value) - memcpy(base, control->value, size); - else - memset(base, 0, size); - return base; -} - -static pthread_mutex_t emutls_mutex = PTHREAD_MUTEX_INITIALIZER; - -static size_t emutls_num_object = 0; /* number of allocated TLS objects */ - -typedef struct emutls_address_array -{ - uintptr_t size; /* number of elements in the 'data' array */ - void *data[]; -} emutls_address_array; - -static pthread_key_t emutls_pthread_key; - -static void emutls_key_destructor(void *ptr) -{ - emutls_address_array *array = (emutls_address_array *)ptr; - uintptr_t i; - for (i = 0; i < array->size; ++i) - { - if (array->data[i]) - emutls_memalign_free(array->data[i]); - } - free(ptr); -} - -static void emutls_init(void) -{ - if (pthread_key_create(&emutls_pthread_key, emutls_key_destructor) != 0) - abort(); -} - -/* Returns control->object.index; set index if not allocated yet. */ -static __inline uintptr_t emutls_get_index(__emutls_control *control) -{ - uintptr_t index = __atomic_load_n(&control->object.index, __ATOMIC_ACQUIRE); - if (!index) - { - static pthread_once_t once = PTHREAD_ONCE_INIT; - pthread_once(&once, emutls_init); - pthread_mutex_lock(&emutls_mutex); - index = control->object.index; - if (!index) - { - index = ++emutls_num_object; - __atomic_store_n(&control->object.index, index, __ATOMIC_RELEASE); - } - pthread_mutex_unlock(&emutls_mutex); - } - return index; -} - -/* Updates newly allocated thread local emutls_address_array. */ -static __inline void emutls_check_array_set_size(emutls_address_array *array, - uintptr_t size) -{ - if (array == NULL) - abort(); - array->size = size; - pthread_setspecific(emutls_pthread_key, (void *)array); -} - -/* Returns the new 'data' array size, number of elements, - * which must be no smaller than the given index. - */ -static __inline uintptr_t emutls_new_data_array_size(uintptr_t index) -{ - /* Need to allocate emutls_address_array with one extra slot - * to store the data array size. - * Round up the emutls_address_array size to multiple of 16. - */ - return ((index + 1 + 15) & ~((uintptr_t)15)) - 1; -} - -/* Returns the thread local emutls_address_array. - * Extends its size if necessary to hold address at index. - */ -static __inline emutls_address_array * -emutls_get_address_array(uintptr_t index) -{ - emutls_address_array *array = pthread_getspecific(emutls_pthread_key); - if (array == NULL) - { - uintptr_t new_size = emutls_new_data_array_size(index); - array = calloc(new_size + 1, sizeof(void *)); - emutls_check_array_set_size(array, new_size); - } - else if (index > array->size) - { - uintptr_t orig_size = array->size; - uintptr_t new_size = emutls_new_data_array_size(index); - array = realloc(array, (new_size + 1) * sizeof(void *)); - if (array) - memset(array->data + orig_size, 0, - (new_size - orig_size) * sizeof(void *)); - emutls_check_array_set_size(array, new_size); - } - return array; -} - -void *__emutls_get_address(void *control) -{ - uintptr_t index = emutls_get_index((__emutls_control *)control); - emutls_address_array *array = emutls_get_address_array(index); - if (array->data[index - 1] == NULL) - array->data[index - 1] = emutls_allocate_object((__emutls_control *)control); - return array->data[index - 1]; -} diff --git a/components/cplusplus/cpp11/figures/Snipaste_2021-09-02_16-00-09.png b/components/cplusplus/cpp11/figures/Snipaste_2021-09-02_16-00-09.png deleted file mode 100644 index 0e2381b5d9..0000000000 Binary files a/components/cplusplus/cpp11/figures/Snipaste_2021-09-02_16-00-09.png and /dev/null differ diff --git a/components/cplusplus/cpp11/gcc/__utils.h b/components/cplusplus/cpp11/gcc/__utils.h deleted file mode 100644 index f9a3c93796..0000000000 --- a/components/cplusplus/cpp11/gcc/__utils.h +++ /dev/null @@ -1,59 +0,0 @@ -/* - * Copyright (c) 2006-2021, RT-Thread Development Team - * - * SPDX-License-Identifier: Apache-2.0 - * - * Change Logs: - * Date Author Notes - * 2021-04-27 flybreak the first version. - */ - -#pragma once - -#include -#include -#include -#include - -#include - -#define RT_USING_CPP_EXCEPTION - -inline void throw_system_error(int err, const char *what_msg) -{ -#ifdef RT_USING_CPP_EXCEPTION - throw std::system_error(std::error_code(err, std::system_category()), what_msg); -#else - (void)err; - (void)what_msg; - ::abort(); -#endif -} - -class tick_clock -{ -public: - typedef clock_t rep; - typedef std::ratio<1, RT_TICK_PER_SECOND> period; - - typedef std::chrono::duration duration; - typedef std::chrono::time_point time_point; - - constexpr static bool is_ready = true; - - static time_point now(); -}; - -class real_time_clock -{ -public: - typedef std::chrono::nanoseconds duration; - typedef duration::rep rep; - typedef duration::period period; - typedef std::chrono::time_point time_point; - - static constexpr bool is_steady = true; - - static time_point - now() noexcept; -}; diff --git a/components/cplusplus/cpp11/gcc/condition_variable b/components/cplusplus/cpp11/gcc/condition_variable deleted file mode 100644 index f2d48dd5b5..0000000000 --- a/components/cplusplus/cpp11/gcc/condition_variable +++ /dev/null @@ -1,222 +0,0 @@ -#pragma once - -#if __cplusplus < 201103L -#error "C++ version lower than C++11" -#endif - -#include - -#include -#include -#include -#include -#include - -#include "__utils.h" -#include "mutex" - -#define rt_cpp_cond_var pthread_cond_t - -namespace std -{ - - enum class cv_status - { - no_timeout, - timeout - }; - - class condition_variable - { - public: - typedef rt_cpp_cond_var *native_handle_type; - - condition_variable(const condition_variable &) = delete; - condition_variable &operator=(const condition_variable &) = delete; - - condition_variable() = default; - - ~condition_variable() - { - pthread_cond_destroy(&_m_cond); - } - - void wait(unique_lock &lock); - - void notify_one() noexcept - { - pthread_cond_signal(&_m_cond); - } - - void notify_all() noexcept - { - pthread_cond_broadcast(&_m_cond); - } - - template - void wait(unique_lock &lock, Predicate pred) - { - while (!pred()) - wait(lock); - } - - template - cv_status wait_until(unique_lock &lock, - const chrono::time_point &abs_time) - { - if (!lock.owns_lock()) - throw_system_error((int)errc::operation_not_permitted, - "condition_variable::wailt_until: waiting on unlocked lock"); - auto secs = chrono::time_point_cast(abs_time); - auto nano_secs = chrono::duration_cast(abs_time - secs); - - struct timespec c_abs_time = {static_cast(secs.time_since_epoch().count()), - static_cast(nano_secs.count())}; - - pthread_cond_timedwait(&_m_cond, lock.mutex()->native_handle(), &c_abs_time); - - return (Clock::now() < abs_time) ? cv_status::no_timeout : cv_status::timeout; - } - - template - bool wait_until(unique_lock &lock, - const chrono::time_point &abs_time, - Predicate pred) - { - while (!pred()) - if (wait_until(lock, abs_time) == cv_status::timeout) - return pred(); - return true; - } - - template - cv_status wait_for(unique_lock &lock, - const chrono::duration &rel_time) - { - return wait_until(lock, real_time_clock::now() + rel_time); - } - - template - bool wait_for(unique_lock &lock, - const chrono::duration &rel_time, - Predicate pred) - { - return wait_until(lock, real_time_clock::now() + rel_time, std::move(pred)); - } - - native_handle_type native_handle() - { - return &_m_cond; - } - - private: - rt_cpp_cond_var _m_cond = PTHREAD_COND_INITIALIZER; - }; - - // Lockable is only required to have `lock()` and `unlock()` - class condition_variable_any - { - private: - condition_variable _m_cond; - shared_ptr _m_mtx; - - // so that Lockable automatically unlocks when waiting and locks after waiting - template - struct unlocker - { - Lockable &_m_lock; - - explicit unlocker(Lockable &lk) - : _m_lock(lk) - { - _m_lock.unlock(); - } - - ~unlocker() - { - _m_lock.lock(); - } - - unlocker(const unlocker &) = delete; - unlocker &operator=(const unlocker &) = delete; - }; - - public: - condition_variable_any() : _m_mtx(std::make_shared()) {} - ~condition_variable_any() = default; - - condition_variable_any(const condition_variable_any &) = delete; - condition_variable_any &operator=(const condition_variable_any &) = delete; - - void notify_one() noexcept - { - lock_guard lk(*_m_mtx); - _m_cond.notify_one(); - } - - void notify_all() noexcept - { - lock_guard lk(*_m_mtx); - _m_cond.notify_all(); - } - - template - void wait(Lock &lock) - { - shared_ptr mut = _m_mtx; - unique_lock lk(*mut); - unlocker auto_lk(lock); // unlock here - - unique_lock lk2(std::move(lk)); - _m_cond.wait(lk2); - } // mut.unlock(); lock.lock(); - - template - void wait(Lock &lock, Predicate pred) - { - while (!pred()) - wait(lock); - } - - template - cv_status wait_until(Lock &lock, - const chrono::time_point &abs_time) - { - shared_ptr mut = _m_mtx; - unique_lock lk(*mut); - unlocker auto_lk(lock); // unlock here - - unique_lock lk2(std::move(lk)); - return _m_cond.wait_until(lk2, abs_time); - } - - template - bool wait_until(Lock &lock, - const chrono::time_point &abs_time, - Predicate pred) - { - while (!pred()) - if (wait_until(lock, abs_time) == cv_status::timeout) - return pred(); - return true; - } - - template - cv_status wait_for(Lock &lock, - const chrono::duration &rel_time) - { - return wait_until(lock, real_time_clock::now() + rel_time); - } - - template - bool wait_for(Lock &lock, - const chrono::duration &rel_time, - Predicate pred) - { - return wait_until(lock, real_time_clock::now() + rel_time, std::move(pred)); - } - }; - - void notify_all_at_thread_exit(condition_variable &cond, unique_lock lk); - -} // namespace std diff --git a/components/cplusplus/cpp11/gcc/condition_variable.cpp b/components/cplusplus/cpp11/gcc/condition_variable.cpp deleted file mode 100644 index 2860dd9161..0000000000 --- a/components/cplusplus/cpp11/gcc/condition_variable.cpp +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Copyright (c) 2006-2021, RT-Thread Development Team - * - * SPDX-License-Identifier: Apache-2.0 - * - * Change Logs: - * Date Author Notes - * 2021-04-27 flybreak the first version. - */ - -#include "condition_variable" - -namespace std -{ - void condition_variable::wait(unique_lock& lock) - { - int err = pthread_cond_wait(&_m_cond, lock.mutex()->native_handle()); - - if (err) - { - throw_system_error(err, "condition_variable::wait: failed to wait on a condition"); - } - } - - void notify_all_at_thread_exit(condition_variable& cond, unique_lock lk) - { - // TLS currently not available - mutex* mut = lk.release(); - mut->unlock(); - cond.notify_all(); - } - - -} // namespace std diff --git a/components/cplusplus/cpp11/gcc/future b/components/cplusplus/cpp11/gcc/future deleted file mode 100644 index 6a686063fb..0000000000 --- a/components/cplusplus/cpp11/gcc/future +++ /dev/null @@ -1,336 +0,0 @@ -#pragma once - -#if __cplusplus < 201103L -#error "C++ version lower than C++11" -#endif - -#include -#include -#include -#include -#include - -namespace std { - -enum class future_status { - ready, - timeout, - deferred -}; - -namespace detail { - -class shared_state_base { -protected: - typedef void (*deleter_fn)(void *v); - - using scoped_lock = std::lock_guard; - using unique_lock = std::unique_lock; -public: - explicit shared_state_base(deleter_fn d) : v_(nullptr), d_(d), valid_(true) {} - - ~shared_state_base() { d_(v_); } - - shared_state_base(shared_state_base &&other) = delete; - - shared_state_base(const shared_state_base &other) = delete; - - shared_state_base &operator=(shared_state_base &&other) = delete; - - shared_state_base &operator=(const shared_state_base &other) = delete; - - void wait() { - unique_lock lock(m_); - c_.wait(lock, [this] { return has_value(); }); - } - - template - std::future_status - wait_for(const std::chrono::duration &rel_time) { - unique_lock lock(m_); - if (c_.wait_for(lock, rel_time, [this] { return has_value(); })) { - return std::future_status::ready; - } - return std::future_status::timeout; - } - - template - std::future_status - wait_until(const std::chrono::time_point &abs_time) { - unique_lock lock(m_); - if (c_.wait_until(lock, abs_time, [this] { return has_value(); })) { - return std::future_status::ready; - } - return std::future_status::timeout; - } - -protected: - bool has_value() { return v_ != nullptr; } - -protected: - std::mutex m_; - std::condition_variable c_; - void *v_; - deleter_fn d_; - bool valid_; -}; - - -template -class shared_state: public shared_state_base { -public: - shared_state() :shared_state_base(default_deleter_) {} - - ~shared_state() {} - - R &get() { - wait(); - scoped_lock lock(m_); - assert(valid_); - valid_ = false; - return *(static_cast(v_)); - } - - void set(const R &v) { - scoped_lock lock(m_); - assert(!has_value()); - v_ = new R(v); - valid_ = true; - c_.notify_one(); - } - - void set(R &&v) { - scoped_lock lock(m_); - assert(!has_value()); - v_ = new R(std::move(v)); - valid_ = true; - c_.notify_one(); - } - - bool valid() { - scoped_lock lock(m_); - return valid_; - } - -private: - static void default_deleter_(void *v) { delete static_cast(v); } -}; - -} // namespace detail - -template -class shared_future { -}; - - -template -class future { - using state_type = std::shared_ptr>; -public: - future() {} - - explicit future(const state_type &state) : state_(state) {} - - future(future &&other) noexcept: state_(std::move(other.state_)) { - other.state_.reset(); - } - - future(const future &other) = delete; - - ~future() {} - - future &operator=(future &&other) noexcept { - if (&other != this) { - state_ = std::move(other.state_); - other.state_.reset(); - } - return *this; - } - - future &operator=(const future &other) = delete; - - void swap(future &other) noexcept { - std::swap(state_, other.state_); - } - - std::shared_future share() noexcept { return std::shared_future(); } - - R get() { return state_->get(); } - - bool valid() const noexcept { return state_->valid(); } - - void wait() const { state_->wait(); } - - template - std::future_status - wait_for(const std::chrono::duration &rel_time) const { - return state_->wait_for(rel_time); - } - - template - std::future_status - wait_until(const std::chrono::time_point &abs_time) const { - return state_->wait_until(abs_time); - } - -private: - state_type state_; -}; - - -template <> -class future { - using state_type = std::shared_ptr>; -public: - future() {} - - explicit future(const state_type &state) : state_(state) {} - - future(future &&other) noexcept: state_(std::move(other.state_)) { - other.state_.reset(); - } - - future(const future &other) = delete; - - ~future() {} - - future &operator=(future &&other) noexcept { - if (&other != this) { - state_ = std::move(other.state_); - other.state_.reset(); - } - return *this; - } - - future &operator=(const future &other) = delete; - - void swap(future &other) noexcept { - std::swap(state_, other.state_); - } - - std::shared_future share() noexcept { return std::shared_future(); } - - void get() { state_->get(); } - - bool valid() const noexcept { return state_->valid(); } - - void wait() const { state_->wait(); } - - template - std::future_status - wait_for(const std::chrono::duration &rel_time) const { - return state_->wait_for(rel_time); - } - - template - std::future_status - wait_until(const std::chrono::time_point &abs_time) const { - return state_->wait_until(abs_time); - } - -private: - state_type state_; -}; - - -template -class promise { - using state_type = std::shared_ptr>; -public: - promise() : state_(new detail::shared_state()) {} - - promise(promise &&other) noexcept: state_(std::move(other.state_)) { - other.state_.reset(); - } - - promise(const promise &other) = delete; - - ~promise() {} - - promise &operator=(promise &&other) noexcept { - if (&other != this) { - state_ = std::move(other.state_); - other.state_.reset(); - } - return *this; - } - - promise &operator=(const promise &other) = delete; - - void swap(promise &other) noexcept { - std::swap(state_, other.state_); - } - - std::future get_future() { return std::future(state_); } - - void set_value(const R &value) { state_->set(value); } - - void set_value(R &&value) { state_->set(std::move(value)); } - - void set_value_at_thread_exit(const R &value); - - void set_value_at_thread_exit(R &&value); - - void set_exception(std::exception_ptr p); - - void set_exception_at_thread_exit(std::exception_ptr p); - -private: - state_type state_; -}; - - -template <> -class promise { - using state_type = std::shared_ptr>; -public: - promise() : state_(new detail::shared_state()) {} - - promise(promise &&other) noexcept: state_(std::move(other.state_)) { - other.state_.reset(); - } - - promise(const promise &other) = delete; - - ~promise() {} - - promise &operator=(promise &&other) noexcept { - if (&other != this) { - state_ = std::move(other.state_); - other.state_.reset(); - } - return *this; - } - - promise &operator=(const promise &other) = delete; - - void swap(promise &other) noexcept { - std::swap(state_, other.state_); - } - - std::future get_future() { return std::future(state_); } - - void set_value() { state_->set(0); } - - void set_value_at_thread_exit(); - - void set_exception(std::exception_ptr p); - - void set_exception_at_thread_exit(std::exception_ptr p); - -private: - state_type state_; -}; - - -template -void swap(std::future &lhs, std::future &rhs) noexcept { - lhs.swap(rhs); -} - -template -void swap(std::promise &lhs, std::promise &rhs) noexcept { - lhs.swap(rhs); -} - -} // namespace std diff --git a/components/cplusplus/cpp11/gcc/mutex b/components/cplusplus/cpp11/gcc/mutex deleted file mode 100644 index 3fdf86632b..0000000000 --- a/components/cplusplus/cpp11/gcc/mutex +++ /dev/null @@ -1,512 +0,0 @@ -#pragma once - -#if __cplusplus < 201103L -#error "C++ version lower than C++11" -#endif - -//#if defined(RT_USING_PTHREADS) - -#include - -#include -#include -#include -#include - -#include "__utils.h" - -#define rt_cpp_mutex_t pthread_mutex_t - -namespace std -{ - // Base class on which to build std::mutex and std::timed_mutex - class __mutex_base - { - protected: - typedef rt_cpp_mutex_t __native_type; - - __native_type _m_mutex = PTHREAD_MUTEX_INITIALIZER; - - constexpr __mutex_base() noexcept = default; - __mutex_base(const __mutex_base&) = delete; - __mutex_base& operator=(const __mutex_base&) = delete; - }; - - - class mutex : private __mutex_base - { - public: - constexpr mutex() = default; - ~mutex() = default; - - mutex(const mutex&) = delete; - mutex& operator=(const mutex&) = delete; - - void lock() - { - int err = pthread_mutex_lock(&_m_mutex); - - if (err) - { - throw_system_error(err, "mutex:lock failed."); - } - } - - bool try_lock() noexcept - { - return !pthread_mutex_trylock(&_m_mutex); - } - - void unlock() noexcept - { - pthread_mutex_unlock(&_m_mutex); - } - - typedef __native_type* native_handle_type; - - native_handle_type native_handle() - { - return &_m_mutex; - }; - - }; - - inline int __rt_cpp_recursive_mutex_init(rt_cpp_mutex_t* m) - { - pthread_mutexattr_t attr; - int res; - - res = pthread_mutexattr_init(&attr); - if (res) - return res; - res = pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE); - if (res) - goto attr_cleanup; - res = pthread_mutex_init(m, &attr); - - attr_cleanup: - int err = pthread_mutexattr_destroy(&attr); - return res ? res : err; - } - - class __recursive_mutex_base - { - protected: - typedef rt_cpp_mutex_t __native_type; - - __native_type _m_recursive_mutex; - - __recursive_mutex_base(const __recursive_mutex_base&) = delete; - __recursive_mutex_base& operator=(const __recursive_mutex_base&) = delete; - - __recursive_mutex_base() - { - int err = __rt_cpp_recursive_mutex_init(&_m_recursive_mutex); - if (err) - throw_system_error(err, "Recursive mutex failed to construct"); - } - - ~__recursive_mutex_base() - { - pthread_mutex_destroy(&_m_recursive_mutex); - } - }; - - class recursive_mutex : private __recursive_mutex_base - { - public: - typedef __native_type* native_handle_type; - recursive_mutex() = default; - ~recursive_mutex() = default; - - recursive_mutex(const recursive_mutex&) = delete; - recursive_mutex& operator=(const recursive_mutex&) = delete; - void lock() - { - int err = pthread_mutex_lock(&_m_recursive_mutex); - - if (err) - throw_system_error(err, "recursive_mutex::lock failed"); - } - - bool try_lock() noexcept - { - return !pthread_mutex_trylock(&_m_recursive_mutex); - } - - void unlock() noexcept - { - pthread_mutex_unlock(&_m_recursive_mutex); - } - - native_handle_type native_handle() - { return &_m_recursive_mutex; } - }; - -#ifdef RT_PTHREAD_TIMED_MUTEX - - class timed_mutex; - - class recursive_timed_mutex; - -#endif // RT_PTHREAD_TIMED_MUTEX - - - struct defer_lock_t {}; - struct try_to_lock_t {}; - struct adopt_lock_t {}; // take ownership of a locked mtuex - - constexpr defer_lock_t defer_lock { }; - constexpr try_to_lock_t try_to_lock { }; - constexpr adopt_lock_t adopt_lock { }; - - template - class lock_guard - { - public: - typedef Mutex mutex_type; - - explicit lock_guard(mutex_type& m) : pm(m) { pm.lock(); } - lock_guard(mutex_type& m, adopt_lock_t) noexcept : pm(m) - { } - ~lock_guard() - { pm.unlock(); } - - lock_guard(lock_guard const&) = delete; - lock_guard& operator=(lock_guard const&) = delete; - - private: - mutex_type& pm; - - }; - - template - class unique_lock - { - public: - typedef Mutex mutex_type; - - unique_lock() noexcept : pm(nullptr), owns(false) { } - - explicit unique_lock(mutex_type& m) - : pm(std::addressof(m)), owns(false) - { - lock(); - owns = true; - } - - unique_lock(mutex_type& m, defer_lock_t) noexcept - : pm(std::addressof(m)), owns(false) - { } - - unique_lock(mutex_type& m, try_to_lock_t) noexcept - : pm(std::addressof(m)), owns(pm->try_lock()) - { } - - unique_lock(mutex_type& m, adopt_lock_t) noexcept - : pm(std::addressof(m)), owns(true) - { } - - // any lock-involving timed mutex API is currently only for custom implementations - // the standard ones are not available - template - unique_lock(mutex_type& m, const chrono::time_point& abs_time) noexcept - : pm(std::addressof(m)), owns(pm->try_lock_until(abs_time)) - { } - - template - unique_lock(mutex_type& m, const chrono::duration& rel_time) noexcept - : pm(std::addressof(m)), owns(pm->try_lock_for(rel_time)) - { } - - ~unique_lock() - { - if (owns) - unlock(); - } - - unique_lock(unique_lock const&) = delete; - unique_lock& operator=(unique_lock const&) = delete; - - unique_lock(unique_lock&& u) noexcept - : pm(u.pm), owns(u.owns) - { - u.pm = nullptr; - u.owns = false; - } - - unique_lock& operator=(unique_lock&& u) noexcept - { - if (owns) - unlock(); - - unique_lock(std::move(u)).swap(*this); - - u.pm = nullptr; - u.owns = false; - - return *this; - } - - void lock() - { - if (!pm) - throw_system_error(int(errc::operation_not_permitted), - "unique_lock::lock: references null mutex"); - else if (owns) - throw_system_error(int(errc::resource_deadlock_would_occur), - "unique_lock::lock: already locked" ); - else { - pm->lock(); - owns = true; - } - } - - bool try_lock() - { - if (!pm) - throw_system_error(int(errc::operation_not_permitted), - "unique_lock::try_lock: references null mutex"); - else if (owns) - throw_system_error(int(errc::resource_deadlock_would_occur), - "unique_lock::try_lock: already locked" ); - else { - owns = pm->try_lock(); - } - return owns; - } - - template - bool try_lock_for(const chrono::duration& rel_time) - { - if (!pm) - throw_system_error(int(errc::operation_not_permitted), - "unique_lock::try_lock_for: references null mutex"); - else if (owns) - throw_system_error(int(errc::resource_deadlock_would_occur), - "unique_lock::try_lock_for: already locked"); - else { - owns = pm->try_lock_for(rel_time); - } - return owns; - } - - template - bool try_lock_until(const chrono::time_point& abs_time) - { - if (!pm) - throw_system_error(int(errc::operation_not_permitted), - "unique_lock::try_lock_until: references null mutex"); - else if (owns) - throw_system_error(int(errc::resource_deadlock_would_occur), - "unique_lock::try_lock_until: already locked"); - else { - owns = pm->try_lock_until(abs_time); - } - return owns; - } - - void unlock() - { - if (!owns) - throw_system_error(int(errc::operation_not_permitted), - "unique_lock::unlock: not locked"); - else { - pm->unlock(); - owns = false; - } - } - - void swap(unique_lock& u) noexcept - { - std::swap(pm, u.pm); - std::swap(owns, u.owns); - } - - mutex_type *release() noexcept - { - mutex_type* ret_mutex = pm; - pm = nullptr; - owns = false; - - return ret_mutex; - } - - bool owns_lock() const noexcept - { return owns; } - - explicit operator bool() const noexcept - { return owns_lock(); } - - mutex_type* mutex() const noexcept - { return pm; } - - - private: - mutex_type *pm; - bool owns; - }; - - template - void swap(unique_lock& x, unique_lock& y) - { - x.swap(y); - } - - template - int try_lock(L0& l0, L1& l1) - { - unique_lock u0(l0, try_to_lock); // try to lock the first Lockable - // using unique_lock since we don't want to unlock l0 manually if l1 fails to lock - if (u0.owns_lock()) - { - if (l1.try_lock()) // lock the second one - { - u0.release(); // do not let RAII of a unique_lock unlock l0 - return -1; - } - else - return 1; - } - return 0; - } - - - template - int try_lock(L0& l0, L1& l1, L2& l2, L3&... l3) - { - int r = 0; - unique_lock u0(l0, try_to_lock); - // automatically unlock is done through RAII of unique_lock - if (u0.owns_lock()) - { - r = try_lock(l1, l2, l3...); - if (r == -1) - u0.release(); - else - ++r; - } - return r; - } - - template - void - __lock_first(int i, L0& l0, L1& l1, L2& l2, L3&... l3) - { - while (true) - { - // we first lock the one that is the most difficult to lock - switch (i) - { - case 0: - { - unique_lock u0(l0); - i = try_lock(l1, l2, l3...); - if (i == -1) - { - u0.release(); - return; - } - } - ++i; - sched_yield(); - break; - case 1: - { - unique_lock u1(l1); - i = try_lock(l2, l3..., l0); - if (i == -1) - { - u1.release(); - return; - } - } - if (i == sizeof...(L3) + 1) // all except l0 are locked - i = 0; - else - i += 2; // since i was two-based above - sched_yield(); - break; - default: - __lock_first(i - 2, l2, l3..., l0, l1); - return; - } - } - } - - - template - void lock(L0& l0, L1& l1) - { - while (true) - { - { - unique_lock u0(l0); - if (l1.try_lock()) - { - u0.release(); - break; - } - } - sched_yield(); - // wait and try the other way - { - unique_lock u1(l1); - if (l0.try_lock()) - { - u1.release(); - break; - } - } - sched_yield(); - } - } - - template - void lock(L0& l0, L1& l1, L2&... l2) - { - __lock_first(0, l0, l1, l2...); - } - - struct once_flag - { - constexpr once_flag() noexcept = default; - - once_flag(const once_flag&) = delete; - once_flag& operator=(const once_flag&) = delete; - - template - friend void call_once(once_flag& flag, Callable&& func, Args&&... args); - - private: - pthread_once_t _m_once = PTHREAD_ONCE_INIT; - }; - - mutex& get_once_mutex(); - extern function once_functor; - extern void set_once_functor_lock_ptr(unique_lock*); - - extern "C" void once_proxy(); // passed into pthread_once - - template - void call_once(once_flag& flag, Callable&& func, Args&&... args) - { - // use a lock to ensure the call to the functor - // is exclusive to only the first calling thread - unique_lock functor_lock(get_once_mutex()); - - auto call_wrapper = std::bind(std::forward(func), std::forward(args)...); - once_functor = [&]() { call_wrapper(); }; - - set_once_functor_lock_ptr(&functor_lock); // so as to unlock when actually calling - - int err = pthread_once(&flag._m_once, &once_proxy); - - if (functor_lock) - set_once_functor_lock_ptr(nullptr); - if (err) - throw_system_error(err, "call_once failed"); - } -} - -//#endif //(RT_USING_PTHREADS) \ No newline at end of file diff --git a/components/cplusplus/cpp11/gcc/mutex.cpp b/components/cplusplus/cpp11/gcc/mutex.cpp deleted file mode 100644 index e11f6d8990..0000000000 --- a/components/cplusplus/cpp11/gcc/mutex.cpp +++ /dev/null @@ -1,52 +0,0 @@ -/* - * Copyright (c) 2006-2021, RT-Thread Development Team - * - * SPDX-License-Identifier: Apache-2.0 - * - * Change Logs: - * Date Author Notes - * 2021-04-27 flybreak the first version. - */ - -#include "mutex" - -namespace std -{ - // use a set of global and static objects - // a proxy function to pthread_once - - function once_functor; - - mutex& get_once_mutex() - { - static mutex once_mutex; - return once_mutex; - } - - inline unique_lock*& get_once_functor_lock_ptr() - { - static unique_lock* once_functor_mutex_ptr = nullptr; - return once_functor_mutex_ptr; - } - - void set_once_functor_lock_ptr(unique_lock* m_ptr) - { - get_once_functor_lock_ptr() = m_ptr; - } - - extern "C" - { - void once_proxy() - { - // need to first transfer the functor's ownership so as to call it - function once_call = std::move(once_functor); - - // no need to hold the lock anymore - unique_lock* lock_ptr = get_once_functor_lock_ptr(); - get_once_functor_lock_ptr() = nullptr; - lock_ptr->unlock(); - - once_call(); - } - } -} diff --git a/components/cplusplus/cpp11/gcc/thread b/components/cplusplus/cpp11/gcc/thread deleted file mode 100644 index 60e3ec964c..0000000000 --- a/components/cplusplus/cpp11/gcc/thread +++ /dev/null @@ -1,239 +0,0 @@ -#pragma once - -#if __cplusplus < 201103L -#error "C++ version lower than C++11" -#endif - -//#if defined(RT_USING_PTHREADS) - -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include - -#define rt_cpp_thread_t pthread_t -#ifndef PTHREAD_NUM_MAX -#define PTHREAD_NUM_MAX 32 -#endif -#define CPP_UNJOINABLE_THREAD PTHREAD_NUM_MAX - -namespace std -{ - #define __STDCPP_THREADS__ __cplusplus - - - - class thread - { - public: - typedef rt_cpp_thread_t native_handle_type; - - struct invoker_base; - typedef shared_ptr invoker_base_ptr; - - class id - { - // basically a wrapper around native_handle_type - native_handle_type __cpp_thread_t; - - public: - id() noexcept : __cpp_thread_t(CPP_UNJOINABLE_THREAD) {} - - explicit id(native_handle_type hid) - : __cpp_thread_t(hid) {} - private: - friend class thread; - friend class hash; - - friend bool operator==(thread::id x, thread::id y) noexcept; - - friend bool operator<(thread::id x, thread::id y) noexcept; - - template - friend basic_ostream& - operator<<(basic_ostream& out, thread::id id); - }; - - thread() noexcept = default; - thread(const thread&) = delete; - thread& operator=(const thread&) = delete; - ~thread(); - - template - explicit thread(F&& f, Args&&... args) - { - start_thread(make_invoker_ptr(std::bind( - std::forward(f), - std::forward(args)... - ))); - } - - thread(thread&& t) noexcept - { - swap(t); - } - - thread& operator=(thread&& t) noexcept - { - if (joinable()) - terminate(); - swap(t); - return *this; - } - - // member functions - void swap(thread& t) noexcept - { - std::swap(_m_thr, t._m_thr); - } - - bool joinable() const noexcept - { - return (_m_thr.__cpp_thread_t < PTHREAD_NUM_MAX); - } - - void join(); - - void detach(); - - id get_id() const noexcept { return _m_thr; } - - native_handle_type native_handle() { return _m_thr.__cpp_thread_t; } - - // static members - static unsigned hardware_concurrency() noexcept; - - private: - id _m_thr; - - void start_thread(invoker_base_ptr b); - public: - struct invoker_base - { - invoker_base_ptr this_ptr; - - virtual ~invoker_base() = default; - - virtual void invoke() = 0; - }; - - - template - struct invoker : public invoker_base - { - Callable func; - - invoker(Callable&& F) : func(std::forward(F)) { } - - void invoke() { func(); } - }; - - template - shared_ptr> make_invoker_ptr(Callable&& F) - { - return std::make_shared>(std::forward(F)); - } - - - }; - - inline void swap(thread& x, thread& y) noexcept - { - x.swap(y); - } - - - inline bool operator==(thread::id x, thread::id y) noexcept - { - // From POSIX for pthread_equal: - //"If either t1 or t2 are not valid thread IDs, the behavior is undefined." - return x.__cpp_thread_t == y.__cpp_thread_t; - } - - inline bool operator!=(thread::id x, thread::id y) noexcept - { - return !(x == y); - } - - inline bool operator<(thread::id x, thread::id y) noexcept - { - return x.__cpp_thread_t < y.__cpp_thread_t; - } - - inline bool operator<=(thread::id x, thread::id y) noexcept - { - return !(y < x); - } - - inline bool operator>(thread::id x, thread::id y) noexcept - { - return !(x <= y); - } - - inline bool operator>=(thread::id x, thread::id y) noexcept - { - return !(x < y); - } - - template - inline basic_ostream& - operator<<(basic_ostream& out, thread::id id) - { - if (id == thread::id()) // id is invalid, representing no pthread - out << "thread::id of a non-executing thread"; - else - out << id.__cpp_thread_t; - return out; - } - - template <> - struct hash - { - typedef size_t result_type; - typedef thread::id argument_type; - size_t operator()(const thread::id& id) const noexcept - { - return hash()(id.__cpp_thread_t); - } - }; - - namespace this_thread - { - inline thread::id get_id() noexcept - { - return thread::id(pthread_self()); - } - - inline void yield() noexcept - { - sched_yield(); - } - - template - inline void sleep_for(const chrono::duration& rel_time) - { - if (rel_time <= rel_time.zero()) // less than zero, no need to sleep - return; - auto milli_secs = chrono::duration_cast(rel_time); - // the precision is limited by rt-thread thread API - rt_thread_mdelay(milli_secs.count()); - } - - template - inline void sleep_until(const chrono::time_point& abs_time) - { - auto now = Clock::now(); - if (abs_time > now) - sleep_for(abs_time - now); - } - - } -} diff --git a/components/cplusplus/cpp11/gcc/thread.cpp b/components/cplusplus/cpp11/gcc/thread.cpp deleted file mode 100644 index 3979da0dc4..0000000000 --- a/components/cplusplus/cpp11/gcc/thread.cpp +++ /dev/null @@ -1,94 +0,0 @@ -/* - * Copyright (c) 2006-2021, RT-Thread Development Team - * - * SPDX-License-Identifier: Apache-2.0 - * - * Change Logs: - * Date Author Notes - * 2021-04-27 flybreak the first version. - */ - -#include "thread" -#include "__utils.h" - - -#define _RT_NPROCS 0 - -namespace std -{ - - extern "C" - { - static void* execute_native_thread_routine(void *p) - { - thread::invoker_base* t = static_cast(p); - thread::invoker_base_ptr local; - local.swap(t->this_ptr); // tranfer the ownership of the invoker into the thread entry - - local->invoke(); - - return NULL; - } - } - - void thread::start_thread(invoker_base_ptr b) - { - auto raw_ptr = b.get(); - // transfer the ownership of the invoker to the new thread - raw_ptr->this_ptr = std::move(b); - int err = pthread_create(&_m_thr.__cpp_thread_t, NULL, - &execute_native_thread_routine, raw_ptr); - - if (err) - { - raw_ptr->this_ptr.reset(); - throw_system_error(err, "Failed to create a thread"); - } - - } - - thread::~thread() - { - if (joinable()) // when either not joined or not detached - terminate(); - } - - void thread::join() - { - int err = EINVAL; - - if (joinable()) - err = pthread_join(native_handle(), NULL); - - if (err) - { - throw_system_error(err, "thread::join failed"); - } - - _m_thr = id(); - } - - void thread::detach() - { - int err = EINVAL; - - if (joinable()) - err = pthread_detach(native_handle()); - if (err) - { - throw_system_error(err, "thread::detach failed"); - } - - _m_thr = id(); - } - - // TODO: not yet actually implemented. - // The standard states that the returned value should only be considered a hint. - unsigned thread::hardware_concurrency() noexcept - { - int __n = _RT_NPROCS; - if (__n < 0) - __n = 0; - return __n; - } -} diff --git a/components/cplusplus/cpp11/gcc/utils.cpp b/components/cplusplus/cpp11/gcc/utils.cpp deleted file mode 100644 index 1ec3b70cad..0000000000 --- a/components/cplusplus/cpp11/gcc/utils.cpp +++ /dev/null @@ -1,29 +0,0 @@ -/* - * Copyright (c) 2006-2021, RT-Thread Development Team - * - * SPDX-License-Identifier: Apache-2.0 - * - * Change Logs: - * Date Author Notes - * 2021-04-27 flybreak the first version. - */ - -#include "__utils.h" -#include - -tick_clock::time_point tick_clock::now() -{ - tick_clock::rep cur_tk = clock(); - tick_clock::duration cur_time(cur_tk); - - return tick_clock::time_point(cur_time); -} - -real_time_clock::time_point real_time_clock::now() noexcept -{ - timespec tp; - clock_gettime(CLOCK_REALTIME, &tp); - - return time_point(duration(std::chrono::seconds(tp.tv_sec)) - + std::chrono::nanoseconds(tp.tv_nsec)); -} diff --git a/components/cplusplus/cpp11/thread_local_impl.cpp b/components/cplusplus/cpp11/thread_local_impl.cpp deleted file mode 100644 index 43761c1e62..0000000000 --- a/components/cplusplus/cpp11/thread_local_impl.cpp +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Copyright (c) 2006-2021, RT-Thread Development Team - * - * SPDX-License-Identifier: Apache-2.0 - * - * Change Logs: - * Date Author Notes - * 2021-04-27 flybreak the first version. - */ - -#include -#include - -typedef void (*destructor) (void *); - -extern "C" -int __cxa_thread_atexit_impl(destructor dtor, void* obj, void* dso_symbol) -{ - pthread_key_t key_tmp; - if (pthread_key_create(&key_tmp, dtor) != 0) - abort(); - pthread_setspecific(key_tmp, obj); - return 0; -} - -#if defined(__GNUC__) && !defined(__ARMCC_VERSION)/*GCC*/ -#include - -extern"C" -int __cxxabiv1::__cxa_thread_atexit(destructor dtor, void *obj, void *dso_handle) -{ - return __cxa_thread_atexit_impl(dtor, obj, dso_handle); -} -#endif diff --git a/components/cplusplus/cxx_Mutex.cpp b/components/cplusplus/cxx_Mutex.cpp deleted file mode 100644 index da6f80985f..0000000000 --- a/components/cplusplus/cxx_Mutex.cpp +++ /dev/null @@ -1,44 +0,0 @@ -/* - * Copyright (c) 2006-2021, RT-Thread Development Team - * - * SPDX-License-Identifier: Apache-2.0 - * - * Change Logs: - * Date Author Notes - */ - -#include "cxx_mutex.h" - -using namespace rtthread; - -Mutex::Mutex(const char *name) -{ - rt_mutex_init(&mID, name, RT_IPC_FLAG_PRIO); -} - -bool Mutex::lock(int32_t millisec) -{ - rt_int32_t tick; - - if (millisec < 0) - tick = -1; - else - tick = rt_tick_from_millisecond(millisec); - - return rt_mutex_take(&mID, tick) == RT_EOK; -} - -bool Mutex::trylock() -{ - return lock(0); -} - -void Mutex::unlock() -{ - rt_mutex_release(&mID); -} - -Mutex::~Mutex() -{ - rt_mutex_detach(&mID); -} diff --git a/components/cplusplus/cxx_Semaphore.cpp b/components/cplusplus/cxx_Semaphore.cpp deleted file mode 100644 index 672eeb04af..0000000000 --- a/components/cplusplus/cxx_Semaphore.cpp +++ /dev/null @@ -1,39 +0,0 @@ -/* - * Copyright (c) 2006-2021, RT-Thread Development Team - * - * SPDX-License-Identifier: Apache-2.0 - * - * Change Logs: - * Date Author Notes - */ - -#include "cxx_semaphore.h" - -using namespace rtthread; - -Semaphore::Semaphore(const char *name, int32_t count) -{ - rt_sem_init(&mID, name, count, RT_IPC_FLAG_FIFO); -} - -bool Semaphore::wait(int32_t millisec) -{ - rt_int32_t tick; - - if (millisec < 0) - tick = -1; - else - tick = rt_tick_from_millisecond(millisec); - - return rt_sem_take(&mID, tick) == RT_EOK; -} - -void Semaphore::release(void) -{ - rt_sem_release(&mID); -} - -Semaphore::~Semaphore() -{ - rt_sem_detach(&mID); -} diff --git a/components/cplusplus/cxx_Thread.cpp b/components/cplusplus/cxx_Thread.cpp deleted file mode 100644 index f3484bb1f4..0000000000 --- a/components/cplusplus/cxx_Thread.cpp +++ /dev/null @@ -1,117 +0,0 @@ -/* - * Copyright (c) 2006-2021, RT-Thread Development Team - * - * SPDX-License-Identifier: Apache-2.0 - * - * Change Logs: - * Date Author Notes - */ - -#include "cxx_thread.h" - -using namespace rtthread; - -Thread::Thread(rt_uint32_t stack_size, - rt_uint8_t priority, - rt_uint32_t tick, - const char *name) - : _entry(RT_NULL), _param(RT_NULL), started(false) -{ - rt_event_init(&_event, name, 0); - - _thread = rt_thread_create(name, - (thread_func_t)func, - this, - stack_size, - priority, - tick); -} - -Thread::Thread(void (*entry)(void *p), - void *p, - rt_uint32_t stack_size, - rt_uint8_t priority, - rt_uint32_t tick, - const char *name) - : _entry(entry), _param(p), started(false) -{ - rt_event_init(&_event, name, 0); - - _thread = rt_thread_create(name, - (thread_func_t)func, - this, - stack_size, - priority, - tick); -} - -Thread::~Thread() -{ - rt_event_detach(&_event); - rt_thread_delete(_thread); -} - -bool Thread::start() -{ - if (rt_thread_startup(_thread) == RT_EOK) - { - started = true; - } - - return started; -} - -void Thread::sleep(int32_t millisec) -{ - rt_int32_t tick; - - if (millisec < 0) - tick = 1; - else - tick = rt_tick_from_millisecond(millisec); - - rt_thread_delay(tick); -} - -void Thread::func(Thread *pThis) -{ - if (pThis->_entry != RT_NULL) - { - pThis->_entry(pThis->_param); - } - else - { - pThis->run(pThis->_param); - } - - rt_event_send(&pThis->_event, 1); -} - -void Thread::run(void *parameter) -{ - /* please overload this method */ -} - -rt_err_t Thread::wait(int32_t millisec) -{ - return join(millisec); -} - -rt_err_t Thread::join(int32_t millisec) -{ - if (started) - { - rt_int32_t tick; - - if (millisec < 0) - tick = -1; - else - tick = rt_tick_from_millisecond(millisec); - - return rt_event_recv(&_event, 1, RT_EVENT_FLAG_OR | RT_EVENT_FLAG_CLEAR, tick, RT_NULL); - } - else - { - return -RT_ENOSYS; - } -} diff --git a/components/cplusplus/cxx_crt.cpp b/components/cplusplus/cxx_crt.cpp deleted file mode 100644 index de2fe3cd74..0000000000 --- a/components/cplusplus/cxx_crt.cpp +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Copyright (c) 2006-2021, RT-Thread Development Team - * - * SPDX-License-Identifier: Apache-2.0 - * - * Change Logs: - * Date Author Notes - * 2015-03-07 Bernard Add copyright header. - */ - -#include -#include "cxx_crt.h" - -void *operator new(size_t size) -{ - return rt_malloc(size); -} - -void *operator new[](size_t size) -{ - return rt_malloc(size); -} - -void operator delete(void *ptr) -{ - rt_free(ptr); -} - -void operator delete[](void *ptr) -{ - return rt_free(ptr); -} - -void __cxa_pure_virtual(void) -{ - rt_kprintf("Illegal to call a pure virtual function.\n"); -} diff --git a/components/cplusplus/cxx_crt.h b/components/cplusplus/cxx_crt.h deleted file mode 100644 index 903d4c86cd..0000000000 --- a/components/cplusplus/cxx_crt.h +++ /dev/null @@ -1,26 +0,0 @@ -/* - * Copyright (c) 2006-2021, RT-Thread Development Team - * - * SPDX-License-Identifier: Apache-2.0 - * -* Change Logs: -* Date Author Notes -* 2015-03-07 Bernard Add copyright header. -*/ - -#ifndef CRT_H_ -#define CRT_H_ - -#include -#include - -void *operator new(size_t size); -void *operator new[](size_t size); - -void operator delete(void * ptr); -void operator delete[](void *ptr); - -extern "C" void __cxa_pure_virtual(void); -extern "C" int cplusplus_system_init(void); - -#endif diff --git a/components/cplusplus/cxx_crt_init.c b/components/cplusplus/cxx_crt_init.c deleted file mode 100644 index 46946089ff..0000000000 --- a/components/cplusplus/cxx_crt_init.c +++ /dev/null @@ -1,68 +0,0 @@ -/* - * Copyright (c) 2006-2021, RT-Thread Development Team - * - * SPDX-License-Identifier: Apache-2.0 - * - * Change Logs: - * Date Author Notes - * 2014-12-03 Bernard Add copyright header. - * 2014-12-29 Bernard Add cplusplus initialization for ARMCC. - * 2016-06-28 Bernard Add _init/_fini routines for GCC. - * 2016-10-02 Bernard Add WEAK for cplusplus_system_init routine. - */ - -#include - -#if defined(__ARMCC_VERSION) -extern void $Super$$__cpp_initialize__aeabi_(void); -/* we need to change the cpp_initialize order */ -RT_WEAK void $Sub$$__cpp_initialize__aeabi_(void) -{ - /* empty */ -} -#elif defined(__GNUC__) && !defined(__CS_SOURCERYGXX_MAJ__) -/* The _init()/_fini() routines has been defined in codesourcery g++ lite */ -RT_WEAK void _init() -{ -} - -RT_WEAK void _fini() -{ -} - -RT_WEAK void *__dso_handle = 0; - -#endif - -RT_WEAK int cplusplus_system_init(void) -{ -#if defined(__ARMCC_VERSION) - /* If there is no SHT$$INIT_ARRAY, calling - * $Super$$__cpp_initialize__aeabi_() will cause fault. At least until Keil5.12 - * the problem still exists. So we have to initialize the C++ runtime by ourself. - */ - typedef void PROC(); - extern const unsigned long SHT$$INIT_ARRAY$$Base[]; - extern const unsigned long SHT$$INIT_ARRAY$$Limit[]; - - const unsigned long *base = SHT$$INIT_ARRAY$$Base; - const unsigned long *lim = SHT$$INIT_ARRAY$$Limit; - - for (; base != lim; base++) - { - PROC *proc = (PROC *)((const char *)base + *base); - (*proc)(); - } -#elif defined(__GNUC__) - typedef void(*pfunc)(); - extern pfunc __ctors_start__[]; - extern pfunc __ctors_end__[]; - pfunc *p; - - for (p = __ctors_start__; p < __ctors_end__; p++) - (*p)(); -#endif - - return 0; -} -INIT_COMPONENT_EXPORT(cplusplus_system_init); diff --git a/components/cplusplus/cxx_lock.h b/components/cplusplus/cxx_lock.h deleted file mode 100644 index c3cc1d2dae..0000000000 --- a/components/cplusplus/cxx_lock.h +++ /dev/null @@ -1,28 +0,0 @@ -/* - * Copyright (c) 2006-2021, RT-Thread Development Team - * - * SPDX-License-Identifier: Apache-2.0 - * - * Change Logs: - * Date Author Notes - * 2016/10/1 Bernard The first version - */ - -#pragma once - -#include -#include - -namespace rtthread { - -class Lock -{ -public: - Lock(Mutex& mutex) : m(mutex) {m.lock();} - ~Lock() {m.unlock();} - -protected: - Mutex &m; -}; - -} diff --git a/components/cplusplus/cxx_mail.h b/components/cplusplus/cxx_mail.h deleted file mode 100644 index 88770bdd94..0000000000 --- a/components/cplusplus/cxx_mail.h +++ /dev/null @@ -1,81 +0,0 @@ -/* - * Copyright (c) 2006-2021, RT-Thread Development Team - * - * SPDX-License-Identifier: Apache-2.0 - * - * Change Logs: - * Date Author Notes - * 2016/10/1 Bernard The first version - */ - -#pragma once - -#include -#include - -#include - -namespace rtthread { - -/** - * The Mail class allow to control, send, receive, or wait for mail. - * A mail is a memory block that is send to a thread or interrupt service routine. - * @param T data type of a single message element. - * @param queue_sz maximum number of messages in queue. - */ - -template -class Mail { -public: - /** Create and Initialise Mail queue. */ - Mail(const char *name = "") - { - rt_mb_init(&mID, name, mPool, queue_sz, RT_IPC_FLAG_FIFO); - } - - ~Mail() - { - rt_mb_detach(&mID); - } - - /** Put a mail in the queue. - @param mptr memory block previously allocated with Mail::alloc or Mail::calloc. - @return status code that indicates the execution status of the function. - */ - bool put(T *mptr, int32_t millisec = 0) - { - rt_int32_t tick; - - if (millisec < 0) - tick = -1; - else - tick = rt_tick_from_millisecond(millisec); - - return rt_mb_send_wait(&mID, (rt_ubase_t)mptr, tick) == RT_EOK; - } - - /** Get a mail from a queue. - @param millisec timeout value or 0 in case of no time-out. (default: osWaitForever). - @return event that contains mail information or error code. - */ - T* get(int32_t millisec = -1) - { - T *t = NULL; - rt_int32_t tick; - - if (millisec < 0) - tick = -1; - else - tick = rt_tick_from_millisecond(millisec); - - rt_mb_recv(&mID, &t, tick); - - return t; - } - -private: - struct rt_mailbox mID; - T* mPool[queue_sz]; -}; - -} diff --git a/components/cplusplus/cxx_mutex.h b/components/cplusplus/cxx_mutex.h deleted file mode 100644 index 63efb4a6ea..0000000000 --- a/components/cplusplus/cxx_mutex.h +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Copyright (c) 2006-2021, RT-Thread Development Team - * - * SPDX-License-Identifier: Apache-2.0 - * - * Change Logs: - * Date Author Notes - * 2016/10/1 Bernard The first version - */ - -#pragma once - -#include -#include - -namespace rtthread { - -/** The Mutex class is used to synchronise the execution of threads. - This is for example used to protect access to a shared resource. -*/ -class Mutex { -public: - /** Create and Initialize a Mutex object */ - Mutex(const char *name = "mutex"); - ~Mutex(); - - /** Wait until a Mutex becomes available. - @param millisec timeout value or 0 in case of no time-out. (default: WaitForever) - @return true if the mutex was acquired, false otherwise. - */ - bool lock(int32_t millisec = -1); - - /** Try to lock the mutex, and return immediately - @return true if the mutex was acquired, false otherwise. - */ - bool trylock(); - - /** Unlock the mutex that has previously been locked by the same thread - */ - void unlock(); - -private: - struct rt_mutex mID; -}; - -} diff --git a/components/cplusplus/cxx_queue.h b/components/cplusplus/cxx_queue.h deleted file mode 100644 index f6b91e1a21..0000000000 --- a/components/cplusplus/cxx_queue.h +++ /dev/null @@ -1,74 +0,0 @@ -/* - * Copyright (c) 2006-2021, RT-Thread Development Team - * - * SPDX-License-Identifier: Apache-2.0 - * - * Change Logs: - * Date Author Notes - * 2016/10/1 Bernard The first version - */ - -#pragma once - -#include -#include - -#include - -namespace rtthread { - -/** - * The Queue class allow to control, send, receive, or wait for messages. - * A message can be a integer or pointer value to a certain type T that is send - * to a thread or interrupt service routine. - * @param T data type of a single message element. - * @param queue_sz maximum number of messages in queue. - */ -template -class Queue -{ -public: - /** Create and initialise a message Queue. */ - Queue() - { - rt_mq_init(&mID, "mq", mPool, sizeof(T), sizeof(mPool), RT_IPC_FLAG_FIFO); - }; - - ~Queue() - { - rt_mq_detach(&mID); - }; - - /** Put a message in a Queue. - @param data message pointer. - @param millisec timeout value or 0 in case of no time-out. (default: 0) - @return status code that indicates the execution status of the function. - */ - rt_err_t put(T& data, int32_t millisec = 0) - { - return rt_mq_send(&mID, &data, sizeof(data)); - } - - /** Get a message or Wait for a message from a Queue. - @param millisec timeout value or 0 in case of no time-out. (default: osWaitForever). - @return bool . - */ - bool get(T& data, int32_t millisec = WAIT_FOREVER) - { - rt_int32_t tick; - - if (millisec < 0) - tick = -1; - else - tick = rt_tick_from_millisecond(millisec); - - return rt_mq_recv(&mID, &data, sizeof(data), tick) == RT_EOK; - } - -private: - struct rt_messagequeue mID; - - char mPool[(sizeof(void *) + RT_ALIGN(sizeof(T), RT_ALIGN_SIZE)) * queue_sz]; -}; - -} diff --git a/components/cplusplus/cxx_semaphore.h b/components/cplusplus/cxx_semaphore.h deleted file mode 100644 index 45c916e169..0000000000 --- a/components/cplusplus/cxx_semaphore.h +++ /dev/null @@ -1,42 +0,0 @@ -/* - * Copyright (c) 2006-2021, RT-Thread Development Team - * - * SPDX-License-Identifier: Apache-2.0 - * - * Change Logs: - * Date Author Notes - * 2016/10/1 Bernard The first version - */ - -#pragma once - -#include -#include - -namespace rtthread { - -/** The Semaphore class is used to manage and protect access to a set of shared resources. */ -class Semaphore -{ -public: - /** Create and Initialize a Semaphore object used for managing resources. - @param number of available resources; maximum index value is (count-1). - */ - Semaphore(const char *name = "sem", int32_t count = 0); - ~Semaphore(); - - /** Wait until a Semaphore resource becomes available. - @param millisec timeout value or 0 in case of no time-out. - @return true on success. - */ - bool wait(int32_t millisec = -1); - - /** Release a Semaphore resource that was obtain with Semaphore::wait. - */ - void release(void); - -private: - struct rt_semaphore mID; -}; - -} diff --git a/components/cplusplus/cxx_thread.h b/components/cplusplus/cxx_thread.h deleted file mode 100644 index 0e681e5c2a..0000000000 --- a/components/cplusplus/cxx_thread.h +++ /dev/null @@ -1,67 +0,0 @@ -/* - * Copyright (c) 2006-2021, RT-Thread Development Team - * - * SPDX-License-Identifier: Apache-2.0 - * - * Change Logs: - * Date Author Notes - * 2016/10/1 Bernard The first version - */ - -#pragma once - -#include -#include - -namespace rtthread -{ - -/** The Thread class allow defining, creating, and controlling thread functions in the system. */ -class Thread -{ -public: - typedef void (*thread_func_t)(void *param); - - /** Allocate a new thread without starting execution - @param priority initial priority of the thread function. (default: osPriorityNormal). - @param stack_size stack size (in bytes) requirements for the thread function. (default: DEFAULT_STACK_SIZE). - @param stack_pointer pointer to the stack area to be used by this thread (default: NULL). - */ - Thread(rt_uint32_t stack_size = 2048, - rt_uint8_t priority = (RT_THREAD_PRIORITY_MAX * 2) / 3, - rt_uint32_t tick = 20, - const char *name = "th"); - - Thread(void (*entry)(void *p), - void *p = RT_NULL, - rt_uint32_t stack_size = 2048, - rt_uint8_t priority = (RT_THREAD_PRIORITY_MAX * 2) / 3, - rt_uint32_t tick = 20, - const char *name = "th"); - - virtual ~Thread(); - - bool start(); - - static void sleep(int32_t millisec); - - rt_err_t wait(int32_t millisec); - rt_err_t join(int32_t millisec = -1); - -protected: - virtual void run(void *parameter); - -private: - static void func(Thread *pThis); - - rt_thread_t _thread; - - thread_func_t _entry; - void *_param; - - /* event for thread join */ - struct rt_event _event; - bool started; -}; - -} diff --git a/components/dfs/Kconfig b/components/dfs/Kconfig index b93c65512b..28cb892e3e 100644 --- a/components/dfs/Kconfig +++ b/components/dfs/Kconfig @@ -1,7 +1,5 @@ -menu "Device virtual file system" - -config RT_USING_DFS - bool "Using device virtual file system" +menuconfig RT_USING_DFS + bool "DFS: device virtual file system" select RT_USING_MUTEX default y help @@ -160,5 +158,3 @@ if RT_USING_DFS endif endif - -endmenu diff --git a/components/fal/Kconfig b/components/fal/Kconfig index 2ee0037184..4eb967b937 100644 --- a/components/fal/Kconfig +++ b/components/fal/Kconfig @@ -1,7 +1,7 @@ # Kconfig file for package fal menuconfig RT_USING_FAL - bool "fal: Flash Abstraction Layer implement. Manage flash device and partition." + bool "FAL: flash abstraction layer" default n if RT_USING_FAL diff --git a/components/finsh/Kconfig b/components/finsh/Kconfig index cc891e3951..2d9d768e23 100644 --- a/components/finsh/Kconfig +++ b/components/finsh/Kconfig @@ -1,16 +1,13 @@ -menu "Command shell" - -config RT_USING_FINSH - bool - default n - -config RT_USING_MSH - bool "msh shell" - select RT_USING_FINSH +menuconfig RT_USING_MSH + bool "MSH: command shell" default y if RT_USING_MSH + config RT_USING_FINSH + bool + default y + config FINSH_USING_MSH bool default y @@ -80,5 +77,3 @@ if RT_USING_MSH default 10 endif - -endmenu diff --git a/components/libc/Kconfig b/components/libc/Kconfig index 71547e7970..3cdaba4bcf 100644 --- a/components/libc/Kconfig +++ b/components/libc/Kconfig @@ -1,4 +1,4 @@ -menu "POSIX layer and C standard library" +menu "C/C++ and POSIX layer" config RT_LIBC_DEFAULT_TIMEZONE int "Set the default time zone (UTC+)" @@ -6,5 +6,6 @@ config RT_LIBC_DEFAULT_TIMEZONE default 8 source "$RTT_DIR/components/libc/posix/Kconfig" +source "$RTT_DIR/components/libc/cplusplus/Kconfig" endmenu diff --git a/components/libc/cplusplus/Kconfig b/components/libc/cplusplus/Kconfig new file mode 100644 index 0000000000..c7268e7b9a --- /dev/null +++ b/components/libc/cplusplus/Kconfig @@ -0,0 +1,15 @@ +menuconfig RT_USING_CPLUSPLUS + bool "Enable C++ features" + default n + +if RT_USING_CPLUSPLUS + + config RT_USING_CPLUSPLUS11 + bool "Enable c++11 threading feature support" + default n + select RT_USING_POSIX_FS + select RT_USING_POSIX_STDIO + select RT_USING_PTHREADS + select RT_USING_RTC + +endif diff --git a/components/libc/cplusplus/README.md b/components/libc/cplusplus/README.md new file mode 100644 index 0000000000..46c8c78a69 --- /dev/null +++ b/components/libc/cplusplus/README.md @@ -0,0 +1,52 @@ +# C++ support for RT-Thread # + +This is the C++ component in RT-Thread RTOS. In order to support C++ language, this component +implement a basic environment, such as new/delete operators. + +Because RT-Thread RTOS is used in embedded system mostly, there are some rules for C++ applications: + +1. DOES NOT use exception. +2. DOES NOT use Run-Time Type Information (RTTI). +3. Template is discouraged and it easily causes code text large. +4. Static class variables are discouraged. The time and place to call their constructor function could not be precisely controlled and make multi-threaded programming a nightmare. +5. Multiple inheritance is strongly discouraged, as it can cause intolerable confusion. + +About GNU GCC compiler + +please add following string in your ld link script: + + // in your .text section + PROVIDE(__ctors_start__ = .); + /* old GCC version uses .ctors */ + KEEP(*(SORT(.ctors.*))) + KEEP(*(.ctors)) + /* new GCC version uses .init_array */ + KEEP (*(SORT(.init_array.*))) + KEEP (*(.init_array)) + PROVIDE(__ctors_end__ = .); + + . = ALIGN(4); + + // as a standalone section if you use ARM target. + + /* The .ARM.exidx section is used for C++ exception handling. */ + /* .ARM.exidx is sorted, so has to go in its own output section. */ + __exidx_start = .; + ARM.exidx : + { + *(.ARM.exidx* .gnu.linkonce.armexidx.*) + + /* This is used by the startup in order to initialize the .data secion */ + _sidata = .; + } > CODE + __exidx_end = .; + + /* .data section which is used for initialized data */ + + // in your .data section + PROVIDE(__dtors_start__ = .); + KEEP(*(SORT(.dtors.*))) + KEEP(*(.dtors)) + PROVIDE(__dtors_end__ = .); + + . = ALIGN(4); diff --git a/components/libc/cplusplus/SConscript b/components/libc/cplusplus/SConscript new file mode 100644 index 0000000000..325a27f65f --- /dev/null +++ b/components/libc/cplusplus/SConscript @@ -0,0 +1,23 @@ +# RT-Thread building script for component + +from building import * +Import('rtconfig') + +cwd = GetCurrentDir() +src = Glob('*.cpp') + Glob('*.c') + +if GetDepend('RT_USING_CPLUSPLUS11'): + src += Glob('cpp11/*.cpp') + Glob('cpp11/*.c') + +CPPPATH = [cwd] + +if rtconfig.PLATFORM == 'armclang' and GetDepend('RT_USING_CPLUSPLUS11'): + src += Glob('cpp11/armclang/*.cpp') + Glob('cpp11/armclang/*.c') + CPPPATH += [cwd + '/cpp11/armclang'] +elif rtconfig.PLATFORM == 'gcc' and GetDepend('RT_USING_CPLUSPLUS11'): + src += Glob('cpp11/gcc/*.cpp') + Glob('cpp11/gcc/*.c') + CPPPATH += [cwd + '/cpp11/gcc'] + +group = DefineGroup('CPlusPlus', src, depend = ['RT_USING_CPLUSPLUS'], CPPPATH = CPPPATH) + +Return('group') \ No newline at end of file diff --git a/components/libc/cplusplus/cpp11/README.md b/components/libc/cplusplus/cpp11/README.md new file mode 100644 index 0000000000..a292051608 --- /dev/null +++ b/components/libc/cplusplus/cpp11/README.md @@ -0,0 +1,49 @@ +# C++ 11 support for RT-Thread + +## Features + +Here are some features about rt-thread c++11 threading futures. + +- Atomic. +- Conditional variables. +- Clocks. +- Future. +- Mutexes. +- Threads. +- TLS. + +## How To Use + +Note that using C++ 11 in rt-thread requires modifying some of the files in the toolchain. Before modifying the tool, back up the tool chain. + +1. Enable c++11 support + + ![](figures/Snipaste_2021-09-02_16-00-09.png) + +2. Download toolchain GCC 10.2.1: + + ```shell + gcc version 10.2.1 20201103 (release) (GNU Arm Embedded Toolchain 10-2020-q4-major) + ``` + +3. Delete the following files: + + ```shell + rm -f toolchain/arm-none-eabi/include/c++/10.2.1/thread + rm -f toolchain/arm-none-eabi/include/c++/10.2.1/mutex + rm -f toolchain/arm-none-eabi/include/c++/10.2.1/condition_variable + rm -f toolchain/arm-none-eabi/include/c++/10.2.1/future + rm -f toolchain/arm-none-eabi/include/pthread.h + ``` + +4. Clear the contents of the following files and keep them to prevent compilation failures: + + ```shell + toolchain/arm-none-eabi/include/sys/_pthreadtypes.h + ``` + +5. Update `rtconfig.py` file. add compilation parameters: + + ```shell + CXXFLAGS = CFLAGS + ' -std=c++11 -fabi-version=0 -MMD -MP -MF' + ``` diff --git a/components/libc/cplusplus/cpp11/README_ZH.md b/components/libc/cplusplus/cpp11/README_ZH.md new file mode 100644 index 0000000000..e46bcb90c4 --- /dev/null +++ b/components/libc/cplusplus/cpp11/README_ZH.md @@ -0,0 +1,48 @@ +# cpp 11 support for rt-thread + +## 特性 + +下面是 RT-Thread 支持的 C++ 11 线程特性。 + +- Atomic. +- Conditional variables. +- Clocks. +- Future. +- Mutexes. +- Threads. +- TLS. + +## 如何使用 + +请注意,在 RT-Thread 中使用 C++ 11,需要修改工具链中的部分文件。请在修改之前,备份好工具链。 + +1. 使能 c++11 + ![](figures/Snipaste_2021-09-02_16-00-09.png) + +2. 下载 GCC 工具链 + + ```shell + gcc version 10.2.1 20201103 (release) (GNU Arm Embedded Toolchain 10-2020-q4-major) + ``` + +3. 删除下面的文件 + + ```shell + rm -f toolchain/arm-none-eabi/include/c++/10.2.1/thread + rm -f toolchain/arm-none-eabi/include/c++/10.2.1/mutex + rm -f toolchain/arm-none-eabi/include/c++/10.2.1/condition_variable + rm -f toolchain/arm-none-eabi/include/c++/10.2.1/future + rm -f toolchain/arm-none-eabi/include/pthread.h + ``` + +4. 请清除下面文件的内容,保留文件避免编译失败 + + ```shell + toolchain/arm-none-eabi/include/sys/_pthreadtypes.h + ``` + +5. 更新 `rtconfig.py` 文件,添加 c++ 编译参数: + + ```shell + CXXFLAGS = CFLAGS + ' -std=c++11 -fabi-version=0 -MMD -MP -MF' + ``` diff --git a/components/libc/cplusplus/cpp11/armclang/clock.cpp b/components/libc/cplusplus/cpp11/armclang/clock.cpp new file mode 100644 index 0000000000..137af393b0 --- /dev/null +++ b/components/libc/cplusplus/cpp11/armclang/clock.cpp @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2006-2021, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2021-04-27 flybreak the first version. + */ + +#include +#include +#include + +extern "C" int __ARM_TPL_clock_realtime(__ARM_TPL_timespec_t* __ts) +{ + unsigned int t = std::time(nullptr); + __ts->tv_sec = t; + __ts->tv_nsec = 0; + return 0; +} + +extern "C" int __ARM_TPL_clock_monotonic(__ARM_TPL_timespec_t* __ts) +{ + unsigned int t = rt_tick_get(); + __ts->tv_sec = t / RT_TICK_PER_SECOND; + __ts->tv_nsec = (t %RT_TICK_PER_SECOND) * NANOSECOND_PER_TICK ; + return 0; +} diff --git a/components/libc/cplusplus/cpp11/armclang/condvar.cpp b/components/libc/cplusplus/cpp11/armclang/condvar.cpp new file mode 100644 index 0000000000..7943ccee60 --- /dev/null +++ b/components/libc/cplusplus/cpp11/armclang/condvar.cpp @@ -0,0 +1,178 @@ +/* + * Copyright (c) 2006-2021, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2021-04-27 flybreak the first version. + */ + +#include +#include "tpl.h" +#include +#include +#include + +arm_tpl_cv::arm_tpl_cv() +{ + s = rt_sem_create("semxs", 0, RT_IPC_FLAG_PRIO); + if (s == nullptr) + RT_ASSERT(0); + h = rt_sem_create("semxh", 0, RT_IPC_FLAG_PRIO); + if (h == nullptr) + { + rt_sem_delete(s); + RT_ASSERT(0); + } + x = rt_mutex_create("mutx", RT_IPC_FLAG_PRIO); + if (x == nullptr) + { + rt_sem_delete(s); + rt_sem_delete(h); + RT_ASSERT(0); + } +} + +arm_tpl_cv::~arm_tpl_cv() +{ + rt_mutex_delete(x); + rt_sem_delete(h); + rt_sem_delete(s); +} + +void arm_tpl_cv::wait(rt_mutex_t lock, bool recursive) +{ + while (rt_mutex_take(x, ARM_TPL_MAX_DELAY) != 0); + rt_sem_release(s); + rt_mutex_release(x); + if (recursive) + rt_mutex_release(lock); + else + rt_mutex_release(lock); + while (rt_sem_take(h, ARM_TPL_MAX_DELAY) != 0); + if (recursive) + while (rt_mutex_take(lock, ARM_TPL_MAX_DELAY) != 0); + else + while (rt_mutex_take(lock, ARM_TPL_MAX_DELAY) != 0); +} + +int arm_tpl_cv::timedwait(rt_mutex_t lock, bool recursive, unsigned int timeout_ms) +{ + int result = 0; + while (rt_mutex_take(x, ARM_TPL_MAX_DELAY) != 0); + rt_sem_release(s); + rt_mutex_release(x); + if (recursive) + rt_mutex_release(lock); + else + rt_mutex_release(lock); + if (rt_sem_take(h, rt_tick_from_millisecond(timeout_ms)) != 0) + { + while (rt_mutex_take(x, ARM_TPL_MAX_DELAY) != 0); + if (rt_sem_take(h, 0) != 0) + { + if (rt_sem_take(s, 0) != 0) + result = -1; + else + result = 1; + } + rt_mutex_release(x); + } + if (recursive) + while (rt_mutex_take(lock, ARM_TPL_MAX_DELAY) != 0); + else + while (rt_mutex_take(lock, ARM_TPL_MAX_DELAY) != 0); + return result; +} + +void arm_tpl_cv::signal() +{ + while (rt_mutex_take(x, ARM_TPL_MAX_DELAY) != 0); + if (rt_sem_take(s, 0) == 0) + rt_sem_release(h); + rt_mutex_release(x); +} + +void arm_tpl_cv::broadcast() +{ + while (rt_mutex_take(x, ARM_TPL_MAX_DELAY) != 0); + auto count = s->value; + for (auto i = 0; i < count; i++) + { + while (rt_sem_take(s, ARM_TPL_MAX_DELAY) != 0); + rt_sem_release(h); + } + rt_mutex_release(x); +} + +static int check_create(volatile __ARM_TPL_condvar_t *__vcv) +{ + if (__vcv->data == 0) + { + uintptr_t cv_new; + cv_new = reinterpret_cast(new arm_tpl_cv()); + if (cv_new == 0) + { + return -1; + } + uintptr_t cv_null = 0; + if (!atomic_compare_exchange_strong(&__vcv->data, &cv_null, cv_new)) + delete reinterpret_cast(cv_new); + } + return 0; +} + +extern "C" int __ARM_TPL_condvar_wait(__ARM_TPL_condvar_t *__cv, __ARM_TPL_mutex_t *__m) +{ + volatile __ARM_TPL_condvar_t *__vcv = __cv; + if (check_create(__vcv) != 0) + return -1; + struct arm_tpl_mutex_struct *tmutex = (struct arm_tpl_mutex_struct *)(__m->data); + ((arm_tpl_cv *) __vcv->data)->wait(tmutex->mutex, tmutex->type == RECURSIVE); + return 0; +} + +extern "C" int __ARM_TPL_condvar_timedwait(__ARM_TPL_condvar_t *__cv, + __ARM_TPL_mutex_t *__m, + __ARM_TPL_timespec_t *__ts) +{ + volatile __ARM_TPL_condvar_t *__vcv = __cv; + if (check_create(__vcv) != 0) + return -1; + __ARM_TPL_timespec_t now; + if (__ARM_TPL_clock_realtime(&now) != 0) + return -1; + struct arm_tpl_mutex_struct *tmutex = (struct arm_tpl_mutex_struct *)(__m->data); + unsigned int timeout_ms = (__ts->tv_sec - now.tv_sec) * 1000 + (__ts->tv_nsec - now.tv_nsec) / 1000000; + if (((arm_tpl_cv *) __vcv->data)->timedwait(tmutex->mutex, tmutex->type == RECURSIVE, timeout_ms) < 0) + return -1; + return 0; +} + +extern "C" int __ARM_TPL_condvar_signal(__ARM_TPL_condvar_t *__cv) +{ + volatile __ARM_TPL_condvar_t *__vcv = __cv; + if (__vcv->data != 0) + ((arm_tpl_cv *) __vcv->data)->signal(); + return 0; +} + +extern "C" int __ARM_TPL_condvar_broadcast(__ARM_TPL_condvar_t *__cv) +{ + volatile __ARM_TPL_condvar_t *__vcv = __cv; + if (__vcv->data != 0) + ((arm_tpl_cv *) __vcv->data)->broadcast(); + return 0; +} + +extern "C" int __ARM_TPL_condvar_destroy(__ARM_TPL_condvar_t *__cv) +{ + volatile __ARM_TPL_condvar_t *__vcv = __cv; + if (__vcv->data != 0) + { + delete (arm_tpl_cv *) __vcv->data; + __vcv->data = 0; + } + return 0; +} diff --git a/components/libc/cplusplus/cpp11/armclang/miscellaneous.cpp b/components/libc/cplusplus/cpp11/armclang/miscellaneous.cpp new file mode 100644 index 0000000000..a084eda8c8 --- /dev/null +++ b/components/libc/cplusplus/cpp11/armclang/miscellaneous.cpp @@ -0,0 +1,22 @@ +/* + * Copyright (c) 2006-2021, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2021-04-27 flybreak the first version. + */ + +#include + +extern "C" int __ARM_TPL_execute_once(__ARM_TPL_exec_once_flag *__flag, + void (*__init_routine)(void)) +{ + if (*__flag == 0) + { + __init_routine(); + *__flag = 1; + } + return 0; +} diff --git a/components/libc/cplusplus/cpp11/armclang/mutex.cpp b/components/libc/cplusplus/cpp11/armclang/mutex.cpp new file mode 100644 index 0000000000..44a70efcf7 --- /dev/null +++ b/components/libc/cplusplus/cpp11/armclang/mutex.cpp @@ -0,0 +1,108 @@ +/* + * Copyright (c) 2006-2021, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2021-04-27 flybreak the first version. + */ + +#include +#include +#include +#include "tpl.h" + +static int check_create(volatile __ARM_TPL_mutex_t *__vm, bool recursive = false) +{ + if (__vm->data == 0) + { + uintptr_t mut_null = 0; + arm_tpl_mutex_struct *mutex_p = (arm_tpl_mutex_struct *)rt_malloc(sizeof(arm_tpl_mutex_struct)); + if (mutex_p == nullptr) return -1; + + if (recursive) + mutex_p->mutex = rt_mutex_create("mutexx", RT_IPC_FLAG_PRIO); + else + mutex_p->mutex = rt_mutex_create("mutexx", RT_IPC_FLAG_PRIO); + + if (mutex_p->mutex == nullptr) + { + rt_free(mutex_p); + return -1; + } + mutex_p->type = recursive ? RECURSIVE : NORMAL; + uintptr_t mut_new = reinterpret_cast(mutex_p); + if (!atomic_compare_exchange_strong(&__vm->data, &mut_null, mut_new)) + { + rt_mutex_delete(mutex_p->mutex); + rt_free(mutex_p); + } + } + return 0; +} + +static int mutexLock(arm_tpl_mutex_struct *mutex_p, rt_tick_t timeOut) +{ + if (mutex_p->type == RECURSIVE) + { + if (rt_mutex_take(mutex_p->mutex, timeOut) == 0) + return 0; + } + else + { + if (rt_mutex_take(mutex_p->mutex, timeOut) == 0) + return 0; + } + return -1; +} + +static int mutexUnlock(arm_tpl_mutex_struct *mutex_p) +{ + if (mutex_p->type == RECURSIVE) + rt_mutex_release(mutex_p->mutex); + else + rt_mutex_release(mutex_p->mutex); + return 0; +} + +extern "C" int __ARM_TPL_recursive_mutex_init(__ARM_TPL_mutex_t *__m) +{ + volatile __ARM_TPL_mutex_t *__vm = __m; + return check_create(__vm, true); +} + +extern "C" int __ARM_TPL_mutex_lock(__ARM_TPL_mutex_t *__m) +{ + volatile __ARM_TPL_mutex_t *__vm = __m; + if (check_create(__vm)) + return -1; + while (mutexLock((arm_tpl_mutex_struct *)(__vm->data), ARM_TPL_MAX_DELAY) != 0); + return 0; +} + +extern "C" int __ARM_TPL_mutex_trylock(__ARM_TPL_mutex_t *__m) +{ + volatile __ARM_TPL_mutex_t *__vm = __m; + if (check_create(__vm)) + return -1; + return mutexLock((arm_tpl_mutex_struct *)(__vm->data), 0); +} + +extern "C" int __ARM_TPL_mutex_unlock(__ARM_TPL_mutex_t *__m) +{ + volatile __ARM_TPL_mutex_t *__vm = __m; + return mutexUnlock((arm_tpl_mutex_struct *)(__vm->data)); +} + +extern "C" int __ARM_TPL_mutex_destroy(__ARM_TPL_mutex_t *__m) +{ + volatile __ARM_TPL_mutex_t *__vm = __m; + if (__vm->data != 0) + { + rt_mutex_delete(((arm_tpl_mutex_struct *)(__vm->data))->mutex); + rt_free((void *)(__vm->data)); + __vm->data = 0; + } + return 0; +} diff --git a/components/libc/cplusplus/cpp11/armclang/thread.cpp b/components/libc/cplusplus/cpp11/armclang/thread.cpp new file mode 100644 index 0000000000..e10ffb9cfe --- /dev/null +++ b/components/libc/cplusplus/cpp11/armclang/thread.cpp @@ -0,0 +1,120 @@ +/* + * Copyright (c) 2006-2021, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2021-04-27 flybreak the first version. + */ + +#include +#include "tpl.h" +#include +#include + +#define CPP11_DEFAULT_ID_OFFSET 1 + +extern "C" int __ARM_TPL_thread_create(__ARM_TPL_thread_t *__t, + void *(*__func)(void *), + void *__arg) +{ + int ret = 0; + pthread_t pid; + ret = pthread_create(&pid, RT_NULL, __func, __arg); + if (ret == 0) + { + __t->data = (std::uintptr_t)pid + CPP11_DEFAULT_ID_OFFSET; + return 0; + } + return -1; +} + +extern "C" int __ARM_TPL_thread_id_compare(__ARM_TPL_thread_id __tid1, + __ARM_TPL_thread_id __tid2) +{ + if (__tid1 > __tid2) + return 1; + else if (__tid1 < __tid2) + return -1; + else + return 0; +} + +extern "C" __ARM_TPL_thread_id __ARM_TPL_thread_get_current_id() +{ + return (__ARM_TPL_thread_id)pthread_self(); +} + +extern "C" __ARM_TPL_thread_id __ARM_TPL_thread_get_id( + const __ARM_TPL_thread_t *__t) +{ + return (__ARM_TPL_thread_id)(((pthread_t)__t->data - CPP11_DEFAULT_ID_OFFSET)); +} + +extern "C" int __ARM_TPL_thread_join(__ARM_TPL_thread_t *__t) +{ + pthread_join(((pthread_t)__t->data - CPP11_DEFAULT_ID_OFFSET), RT_NULL); + return 0; +} + +extern "C" int __ARM_TPL_thread_detach(__ARM_TPL_thread_t *__t) +{ + pthread_detach(((pthread_t)__t->data - CPP11_DEFAULT_ID_OFFSET)); + return 0; +} + +extern "C" void __ARM_TPL_thread_yield() +{ + rt_thread_yield(); +} + +extern "C" int __ARM_TPL_thread_nanosleep(const __ARM_TPL_timespec_t *__req, + __ARM_TPL_timespec_t *__rem) +{ + rt_tick_t tick; + + tick = __req->tv_sec * RT_TICK_PER_SECOND + (__req->tv_nsec * RT_TICK_PER_SECOND)/ 1000000000; + rt_thread_delay(tick); + + if (__rem) + { + tick = rt_tick_get() - tick; + /* get the passed time */ + __rem->tv_sec = tick/RT_TICK_PER_SECOND; + __rem->tv_nsec = (tick%RT_TICK_PER_SECOND) * (1000000000/RT_TICK_PER_SECOND); + } + return 0; +} + +extern "C" unsigned __ARM_TPL_thread_hw_concurrency() +{ + return 1; +} + +extern "C" int __ARM_TPL_tls_create(__ARM_TPL_tls_key *__key, + void (*__at_exit)(void *)) +{ + pthread_key_t key; + + if (pthread_key_create(&key, __at_exit) == 0) + { + *__key = key; + return 0; + } + return -1; +} + +extern "C" void *__ARM_TPL_tls_get(__ARM_TPL_tls_key __key) +{ + return pthread_getspecific(__key); +} + +extern "C" int __ARM_TPL_tls_set(__ARM_TPL_tls_key __key, void *__p) +{ + if (pthread_setspecific(__key, (void*)__p) != 0) + { + return -1; + } + return 0; +} diff --git a/components/libc/cplusplus/cpp11/armclang/tpl.h b/components/libc/cplusplus/cpp11/armclang/tpl.h new file mode 100644 index 0000000000..70c9503cec --- /dev/null +++ b/components/libc/cplusplus/cpp11/armclang/tpl.h @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2006-2021, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2021-04-27 flybreak the first version. + */ + +#pragma once +#ifndef __cplusplus +void ARMTPLInit(); +#else +#include + +#define ARM_TPL_MAX_DELAY 1000 +#define ARM_TPL_THREAD_STACK_SIZE 4096 + +enum arm_tpl_mutex_type +{ + NORMAL, + RECURSIVE, +}; + +struct arm_tpl_mutex_struct +{ + rt_mutex_t mutex; + arm_tpl_mutex_type type; +}; + +struct arm_tpl_thread_struct +{ + rt_thread_t task; + void *(*func)(void *); + void *arg; + rt_sem_t join_sem; + rt_sem_t detach_sem; +}; + +class arm_tpl_cv +{ +public: + arm_tpl_cv(); + ~arm_tpl_cv(); + void wait(rt_mutex_t lock, bool recursive); + int timedwait(rt_mutex_t lock, bool recursive, unsigned int timeout_ms); + void signal(); + void broadcast(); +private: + rt_sem_t s; + rt_sem_t h; + rt_mutex_t x; +}; + +#endif diff --git a/components/libc/cplusplus/cpp11/atomic_8.c b/components/libc/cplusplus/cpp11/atomic_8.c new file mode 100644 index 0000000000..64d3311b4a --- /dev/null +++ b/components/libc/cplusplus/cpp11/atomic_8.c @@ -0,0 +1,88 @@ +/* + * Copyright (c) 2006-2021, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2021-04-27 peterfan Add copyright header. + */ + +#include +#include +#include + +/* +* override gcc builtin atomic function for std::atomic, std::atomic +* @see https://gcc.gnu.org/onlinedocs/gcc/_005f_005fatomic-Builtins.html +*/ +uint64_t __atomic_load_8(volatile void *ptr, int memorder) +{ + volatile uint64_t *val_ptr = (volatile uint64_t *)ptr; + register rt_base_t level; + uint64_t tmp; + level = rt_hw_interrupt_disable(); + tmp = *val_ptr; + rt_hw_interrupt_enable(level); + return tmp; +} + +void __atomic_store_8(volatile void *ptr, uint64_t val, int memorder) +{ + volatile uint64_t *val_ptr = (volatile uint64_t *)ptr; + register rt_base_t level; + level = rt_hw_interrupt_disable(); + *val_ptr = val; + rt_hw_interrupt_enable(level); +} + +uint64_t __atomic_exchange_8(volatile void *ptr, uint64_t val, int memorder) +{ + volatile uint64_t *val_ptr = (volatile uint64_t *)ptr; + register rt_base_t level; + uint64_t tmp; + level = rt_hw_interrupt_disable(); + tmp = *val_ptr; + *val_ptr = val; + rt_hw_interrupt_enable(level); + return tmp; +} + +bool __atomic_compare_exchange_8(volatile void *ptr, volatile void *expected, uint64_t desired, bool weak, int success_memorder, int failure_memorder) +{ + volatile uint64_t *val_ptr = (volatile uint64_t *)ptr; + volatile uint64_t *expected_ptr = (volatile uint64_t *)expected; + register rt_base_t level; + bool exchanged; + level = rt_hw_interrupt_disable(); + if (*val_ptr == *expected_ptr) + { + *val_ptr = desired; + exchanged = true; + } + else + { + *expected_ptr = *val_ptr; + exchanged = false; + } + rt_hw_interrupt_enable(level); + return exchanged; +} + +#define __atomic_fetch_op_8(OPNAME, OP) \ +uint64_t __atomic_fetch_##OPNAME##_8(volatile void *ptr, uint64_t val, int memorder) {\ + volatile uint64_t* val_ptr = (volatile uint64_t*)ptr;\ + register rt_base_t level;\ + uint64_t tmp;\ + level = rt_hw_interrupt_disable();\ + tmp = *val_ptr;\ + *val_ptr OP##= val;\ + rt_hw_interrupt_enable(level);\ + return tmp;\ +} + +__atomic_fetch_op_8(add, +) +__atomic_fetch_op_8(sub, -) +__atomic_fetch_op_8( and, &) +__atomic_fetch_op_8( or, |) +__atomic_fetch_op_8(xor, ^) diff --git a/components/libc/cplusplus/cpp11/emutls.c b/components/libc/cplusplus/cpp11/emutls.c new file mode 100644 index 0000000000..576888f16f --- /dev/null +++ b/components/libc/cplusplus/cpp11/emutls.c @@ -0,0 +1,216 @@ +/* + * Copyright (c) 2006-2021, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2021-04-27 peterfan Add copyright header. + */ + +/* ===---------- emutls.c - Implements __emutls_get_address ---------------=== + * + * The LLVM Compiler Infrastructure + * + * This file is dual licensed under the MIT and the University of Illinois Open + * Source Licenses. See LICENSE.TXT for details. + * + * ===----------------------------------------------------------------------=== + */ + +#include +#include +#include +#include + +#define COMPILE_TIME_ASSERT(x) + +extern int pthread_key_create(pthread_key_t *key, void (*destructor)(void *)); +extern int pthread_key_delete(pthread_key_t key); +extern void *pthread_getspecific(pthread_key_t key); +extern int pthread_setspecific(pthread_key_t key, const void *value); + +/* Default is not to use posix_memalign, so systems like Android + * can use thread local data without heavier POSIX memory allocators. + */ +#ifndef EMUTLS_USE_POSIX_MEMALIGN +#define EMUTLS_USE_POSIX_MEMALIGN 0 +#endif + +/* For every TLS variable xyz, + * there is one __emutls_control variable named __emutls_v.xyz. + * If xyz has non-zero initial value, __emutls_v.xyz's "value" + * will point to __emutls_t.xyz, which has the initial value. + */ +typedef struct __emutls_control +{ + size_t size; /* size of the object in bytes */ + size_t align; /* alignment of the object in bytes */ + union + { + uintptr_t index; /* data[index-1] is the object address */ + void *address; /* object address, when in single thread env */ + } object; + void *value; /* null or non-zero initial value for the object */ +} __emutls_control; + +static __inline void *emutls_memalign_alloc(size_t align, size_t size) +{ + void *base; +#if EMUTLS_USE_POSIX_MEMALIGN + if (posix_memalign(&base, align, size) != 0) + abort(); +#else +#define EXTRA_ALIGN_PTR_BYTES (align - 1 + sizeof(void *)) + char *object; + if ((object = malloc(EXTRA_ALIGN_PTR_BYTES + size)) == NULL) + abort(); + base = (void *)(((uintptr_t)(object + EXTRA_ALIGN_PTR_BYTES)) & ~(uintptr_t)(align - 1)); + + ((void **)base)[-1] = object; +#endif + return base; +} + +static __inline void emutls_memalign_free(void *base) +{ +#if EMUTLS_USE_POSIX_MEMALIGN + free(base); +#else + /* The mallocated address is in ((void**)base)[-1] */ + free(((void **)base)[-1]); +#endif +} + +/* Emulated TLS objects are always allocated at run-time. */ +static __inline void *emutls_allocate_object(__emutls_control *control) +{ + /* Use standard C types, check with gcc's emutls.o. */ + typedef unsigned int gcc_word __attribute__((mode(word))); + typedef unsigned int gcc_pointer __attribute__((mode(pointer))); + COMPILE_TIME_ASSERT(sizeof(size_t) == sizeof(gcc_word)); + COMPILE_TIME_ASSERT(sizeof(uintptr_t) == sizeof(gcc_pointer)); + COMPILE_TIME_ASSERT(sizeof(uintptr_t) == sizeof(void *)); + + size_t size = control->size; + size_t align = control->align; + if (align < sizeof(void *)) + align = sizeof(void *); + /* Make sure that align is power of 2. */ + if ((align & (align - 1)) != 0) + abort(); + + void *base = emutls_memalign_alloc(align, size); + if (control->value) + memcpy(base, control->value, size); + else + memset(base, 0, size); + return base; +} + +static pthread_mutex_t emutls_mutex = PTHREAD_MUTEX_INITIALIZER; + +static size_t emutls_num_object = 0; /* number of allocated TLS objects */ + +typedef struct emutls_address_array +{ + uintptr_t size; /* number of elements in the 'data' array */ + void *data[]; +} emutls_address_array; + +static pthread_key_t emutls_pthread_key; + +static void emutls_key_destructor(void *ptr) +{ + emutls_address_array *array = (emutls_address_array *)ptr; + uintptr_t i; + for (i = 0; i < array->size; ++i) + { + if (array->data[i]) + emutls_memalign_free(array->data[i]); + } + free(ptr); +} + +static void emutls_init(void) +{ + if (pthread_key_create(&emutls_pthread_key, emutls_key_destructor) != 0) + abort(); +} + +/* Returns control->object.index; set index if not allocated yet. */ +static __inline uintptr_t emutls_get_index(__emutls_control *control) +{ + uintptr_t index = __atomic_load_n(&control->object.index, __ATOMIC_ACQUIRE); + if (!index) + { + static pthread_once_t once = PTHREAD_ONCE_INIT; + pthread_once(&once, emutls_init); + pthread_mutex_lock(&emutls_mutex); + index = control->object.index; + if (!index) + { + index = ++emutls_num_object; + __atomic_store_n(&control->object.index, index, __ATOMIC_RELEASE); + } + pthread_mutex_unlock(&emutls_mutex); + } + return index; +} + +/* Updates newly allocated thread local emutls_address_array. */ +static __inline void emutls_check_array_set_size(emutls_address_array *array, + uintptr_t size) +{ + if (array == NULL) + abort(); + array->size = size; + pthread_setspecific(emutls_pthread_key, (void *)array); +} + +/* Returns the new 'data' array size, number of elements, + * which must be no smaller than the given index. + */ +static __inline uintptr_t emutls_new_data_array_size(uintptr_t index) +{ + /* Need to allocate emutls_address_array with one extra slot + * to store the data array size. + * Round up the emutls_address_array size to multiple of 16. + */ + return ((index + 1 + 15) & ~((uintptr_t)15)) - 1; +} + +/* Returns the thread local emutls_address_array. + * Extends its size if necessary to hold address at index. + */ +static __inline emutls_address_array * +emutls_get_address_array(uintptr_t index) +{ + emutls_address_array *array = pthread_getspecific(emutls_pthread_key); + if (array == NULL) + { + uintptr_t new_size = emutls_new_data_array_size(index); + array = calloc(new_size + 1, sizeof(void *)); + emutls_check_array_set_size(array, new_size); + } + else if (index > array->size) + { + uintptr_t orig_size = array->size; + uintptr_t new_size = emutls_new_data_array_size(index); + array = realloc(array, (new_size + 1) * sizeof(void *)); + if (array) + memset(array->data + orig_size, 0, + (new_size - orig_size) * sizeof(void *)); + emutls_check_array_set_size(array, new_size); + } + return array; +} + +void *__emutls_get_address(void *control) +{ + uintptr_t index = emutls_get_index((__emutls_control *)control); + emutls_address_array *array = emutls_get_address_array(index); + if (array->data[index - 1] == NULL) + array->data[index - 1] = emutls_allocate_object((__emutls_control *)control); + return array->data[index - 1]; +} diff --git a/components/libc/cplusplus/cpp11/figures/Snipaste_2021-09-02_16-00-09.png b/components/libc/cplusplus/cpp11/figures/Snipaste_2021-09-02_16-00-09.png new file mode 100644 index 0000000000..0e2381b5d9 Binary files /dev/null and b/components/libc/cplusplus/cpp11/figures/Snipaste_2021-09-02_16-00-09.png differ diff --git a/components/libc/cplusplus/cpp11/gcc/__utils.h b/components/libc/cplusplus/cpp11/gcc/__utils.h new file mode 100644 index 0000000000..f9a3c93796 --- /dev/null +++ b/components/libc/cplusplus/cpp11/gcc/__utils.h @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2006-2021, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2021-04-27 flybreak the first version. + */ + +#pragma once + +#include +#include +#include +#include + +#include + +#define RT_USING_CPP_EXCEPTION + +inline void throw_system_error(int err, const char *what_msg) +{ +#ifdef RT_USING_CPP_EXCEPTION + throw std::system_error(std::error_code(err, std::system_category()), what_msg); +#else + (void)err; + (void)what_msg; + ::abort(); +#endif +} + +class tick_clock +{ +public: + typedef clock_t rep; + typedef std::ratio<1, RT_TICK_PER_SECOND> period; + + typedef std::chrono::duration duration; + typedef std::chrono::time_point time_point; + + constexpr static bool is_ready = true; + + static time_point now(); +}; + +class real_time_clock +{ +public: + typedef std::chrono::nanoseconds duration; + typedef duration::rep rep; + typedef duration::period period; + typedef std::chrono::time_point time_point; + + static constexpr bool is_steady = true; + + static time_point + now() noexcept; +}; diff --git a/components/libc/cplusplus/cpp11/gcc/condition_variable b/components/libc/cplusplus/cpp11/gcc/condition_variable new file mode 100644 index 0000000000..f2d48dd5b5 --- /dev/null +++ b/components/libc/cplusplus/cpp11/gcc/condition_variable @@ -0,0 +1,222 @@ +#pragma once + +#if __cplusplus < 201103L +#error "C++ version lower than C++11" +#endif + +#include + +#include +#include +#include +#include +#include + +#include "__utils.h" +#include "mutex" + +#define rt_cpp_cond_var pthread_cond_t + +namespace std +{ + + enum class cv_status + { + no_timeout, + timeout + }; + + class condition_variable + { + public: + typedef rt_cpp_cond_var *native_handle_type; + + condition_variable(const condition_variable &) = delete; + condition_variable &operator=(const condition_variable &) = delete; + + condition_variable() = default; + + ~condition_variable() + { + pthread_cond_destroy(&_m_cond); + } + + void wait(unique_lock &lock); + + void notify_one() noexcept + { + pthread_cond_signal(&_m_cond); + } + + void notify_all() noexcept + { + pthread_cond_broadcast(&_m_cond); + } + + template + void wait(unique_lock &lock, Predicate pred) + { + while (!pred()) + wait(lock); + } + + template + cv_status wait_until(unique_lock &lock, + const chrono::time_point &abs_time) + { + if (!lock.owns_lock()) + throw_system_error((int)errc::operation_not_permitted, + "condition_variable::wailt_until: waiting on unlocked lock"); + auto secs = chrono::time_point_cast(abs_time); + auto nano_secs = chrono::duration_cast(abs_time - secs); + + struct timespec c_abs_time = {static_cast(secs.time_since_epoch().count()), + static_cast(nano_secs.count())}; + + pthread_cond_timedwait(&_m_cond, lock.mutex()->native_handle(), &c_abs_time); + + return (Clock::now() < abs_time) ? cv_status::no_timeout : cv_status::timeout; + } + + template + bool wait_until(unique_lock &lock, + const chrono::time_point &abs_time, + Predicate pred) + { + while (!pred()) + if (wait_until(lock, abs_time) == cv_status::timeout) + return pred(); + return true; + } + + template + cv_status wait_for(unique_lock &lock, + const chrono::duration &rel_time) + { + return wait_until(lock, real_time_clock::now() + rel_time); + } + + template + bool wait_for(unique_lock &lock, + const chrono::duration &rel_time, + Predicate pred) + { + return wait_until(lock, real_time_clock::now() + rel_time, std::move(pred)); + } + + native_handle_type native_handle() + { + return &_m_cond; + } + + private: + rt_cpp_cond_var _m_cond = PTHREAD_COND_INITIALIZER; + }; + + // Lockable is only required to have `lock()` and `unlock()` + class condition_variable_any + { + private: + condition_variable _m_cond; + shared_ptr _m_mtx; + + // so that Lockable automatically unlocks when waiting and locks after waiting + template + struct unlocker + { + Lockable &_m_lock; + + explicit unlocker(Lockable &lk) + : _m_lock(lk) + { + _m_lock.unlock(); + } + + ~unlocker() + { + _m_lock.lock(); + } + + unlocker(const unlocker &) = delete; + unlocker &operator=(const unlocker &) = delete; + }; + + public: + condition_variable_any() : _m_mtx(std::make_shared()) {} + ~condition_variable_any() = default; + + condition_variable_any(const condition_variable_any &) = delete; + condition_variable_any &operator=(const condition_variable_any &) = delete; + + void notify_one() noexcept + { + lock_guard lk(*_m_mtx); + _m_cond.notify_one(); + } + + void notify_all() noexcept + { + lock_guard lk(*_m_mtx); + _m_cond.notify_all(); + } + + template + void wait(Lock &lock) + { + shared_ptr mut = _m_mtx; + unique_lock lk(*mut); + unlocker auto_lk(lock); // unlock here + + unique_lock lk2(std::move(lk)); + _m_cond.wait(lk2); + } // mut.unlock(); lock.lock(); + + template + void wait(Lock &lock, Predicate pred) + { + while (!pred()) + wait(lock); + } + + template + cv_status wait_until(Lock &lock, + const chrono::time_point &abs_time) + { + shared_ptr mut = _m_mtx; + unique_lock lk(*mut); + unlocker auto_lk(lock); // unlock here + + unique_lock lk2(std::move(lk)); + return _m_cond.wait_until(lk2, abs_time); + } + + template + bool wait_until(Lock &lock, + const chrono::time_point &abs_time, + Predicate pred) + { + while (!pred()) + if (wait_until(lock, abs_time) == cv_status::timeout) + return pred(); + return true; + } + + template + cv_status wait_for(Lock &lock, + const chrono::duration &rel_time) + { + return wait_until(lock, real_time_clock::now() + rel_time); + } + + template + bool wait_for(Lock &lock, + const chrono::duration &rel_time, + Predicate pred) + { + return wait_until(lock, real_time_clock::now() + rel_time, std::move(pred)); + } + }; + + void notify_all_at_thread_exit(condition_variable &cond, unique_lock lk); + +} // namespace std diff --git a/components/libc/cplusplus/cpp11/gcc/condition_variable.cpp b/components/libc/cplusplus/cpp11/gcc/condition_variable.cpp new file mode 100644 index 0000000000..2860dd9161 --- /dev/null +++ b/components/libc/cplusplus/cpp11/gcc/condition_variable.cpp @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2006-2021, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2021-04-27 flybreak the first version. + */ + +#include "condition_variable" + +namespace std +{ + void condition_variable::wait(unique_lock& lock) + { + int err = pthread_cond_wait(&_m_cond, lock.mutex()->native_handle()); + + if (err) + { + throw_system_error(err, "condition_variable::wait: failed to wait on a condition"); + } + } + + void notify_all_at_thread_exit(condition_variable& cond, unique_lock lk) + { + // TLS currently not available + mutex* mut = lk.release(); + mut->unlock(); + cond.notify_all(); + } + + +} // namespace std diff --git a/components/libc/cplusplus/cpp11/gcc/future b/components/libc/cplusplus/cpp11/gcc/future new file mode 100644 index 0000000000..6a686063fb --- /dev/null +++ b/components/libc/cplusplus/cpp11/gcc/future @@ -0,0 +1,336 @@ +#pragma once + +#if __cplusplus < 201103L +#error "C++ version lower than C++11" +#endif + +#include +#include +#include +#include +#include + +namespace std { + +enum class future_status { + ready, + timeout, + deferred +}; + +namespace detail { + +class shared_state_base { +protected: + typedef void (*deleter_fn)(void *v); + + using scoped_lock = std::lock_guard; + using unique_lock = std::unique_lock; +public: + explicit shared_state_base(deleter_fn d) : v_(nullptr), d_(d), valid_(true) {} + + ~shared_state_base() { d_(v_); } + + shared_state_base(shared_state_base &&other) = delete; + + shared_state_base(const shared_state_base &other) = delete; + + shared_state_base &operator=(shared_state_base &&other) = delete; + + shared_state_base &operator=(const shared_state_base &other) = delete; + + void wait() { + unique_lock lock(m_); + c_.wait(lock, [this] { return has_value(); }); + } + + template + std::future_status + wait_for(const std::chrono::duration &rel_time) { + unique_lock lock(m_); + if (c_.wait_for(lock, rel_time, [this] { return has_value(); })) { + return std::future_status::ready; + } + return std::future_status::timeout; + } + + template + std::future_status + wait_until(const std::chrono::time_point &abs_time) { + unique_lock lock(m_); + if (c_.wait_until(lock, abs_time, [this] { return has_value(); })) { + return std::future_status::ready; + } + return std::future_status::timeout; + } + +protected: + bool has_value() { return v_ != nullptr; } + +protected: + std::mutex m_; + std::condition_variable c_; + void *v_; + deleter_fn d_; + bool valid_; +}; + + +template +class shared_state: public shared_state_base { +public: + shared_state() :shared_state_base(default_deleter_) {} + + ~shared_state() {} + + R &get() { + wait(); + scoped_lock lock(m_); + assert(valid_); + valid_ = false; + return *(static_cast(v_)); + } + + void set(const R &v) { + scoped_lock lock(m_); + assert(!has_value()); + v_ = new R(v); + valid_ = true; + c_.notify_one(); + } + + void set(R &&v) { + scoped_lock lock(m_); + assert(!has_value()); + v_ = new R(std::move(v)); + valid_ = true; + c_.notify_one(); + } + + bool valid() { + scoped_lock lock(m_); + return valid_; + } + +private: + static void default_deleter_(void *v) { delete static_cast(v); } +}; + +} // namespace detail + +template +class shared_future { +}; + + +template +class future { + using state_type = std::shared_ptr>; +public: + future() {} + + explicit future(const state_type &state) : state_(state) {} + + future(future &&other) noexcept: state_(std::move(other.state_)) { + other.state_.reset(); + } + + future(const future &other) = delete; + + ~future() {} + + future &operator=(future &&other) noexcept { + if (&other != this) { + state_ = std::move(other.state_); + other.state_.reset(); + } + return *this; + } + + future &operator=(const future &other) = delete; + + void swap(future &other) noexcept { + std::swap(state_, other.state_); + } + + std::shared_future share() noexcept { return std::shared_future(); } + + R get() { return state_->get(); } + + bool valid() const noexcept { return state_->valid(); } + + void wait() const { state_->wait(); } + + template + std::future_status + wait_for(const std::chrono::duration &rel_time) const { + return state_->wait_for(rel_time); + } + + template + std::future_status + wait_until(const std::chrono::time_point &abs_time) const { + return state_->wait_until(abs_time); + } + +private: + state_type state_; +}; + + +template <> +class future { + using state_type = std::shared_ptr>; +public: + future() {} + + explicit future(const state_type &state) : state_(state) {} + + future(future &&other) noexcept: state_(std::move(other.state_)) { + other.state_.reset(); + } + + future(const future &other) = delete; + + ~future() {} + + future &operator=(future &&other) noexcept { + if (&other != this) { + state_ = std::move(other.state_); + other.state_.reset(); + } + return *this; + } + + future &operator=(const future &other) = delete; + + void swap(future &other) noexcept { + std::swap(state_, other.state_); + } + + std::shared_future share() noexcept { return std::shared_future(); } + + void get() { state_->get(); } + + bool valid() const noexcept { return state_->valid(); } + + void wait() const { state_->wait(); } + + template + std::future_status + wait_for(const std::chrono::duration &rel_time) const { + return state_->wait_for(rel_time); + } + + template + std::future_status + wait_until(const std::chrono::time_point &abs_time) const { + return state_->wait_until(abs_time); + } + +private: + state_type state_; +}; + + +template +class promise { + using state_type = std::shared_ptr>; +public: + promise() : state_(new detail::shared_state()) {} + + promise(promise &&other) noexcept: state_(std::move(other.state_)) { + other.state_.reset(); + } + + promise(const promise &other) = delete; + + ~promise() {} + + promise &operator=(promise &&other) noexcept { + if (&other != this) { + state_ = std::move(other.state_); + other.state_.reset(); + } + return *this; + } + + promise &operator=(const promise &other) = delete; + + void swap(promise &other) noexcept { + std::swap(state_, other.state_); + } + + std::future get_future() { return std::future(state_); } + + void set_value(const R &value) { state_->set(value); } + + void set_value(R &&value) { state_->set(std::move(value)); } + + void set_value_at_thread_exit(const R &value); + + void set_value_at_thread_exit(R &&value); + + void set_exception(std::exception_ptr p); + + void set_exception_at_thread_exit(std::exception_ptr p); + +private: + state_type state_; +}; + + +template <> +class promise { + using state_type = std::shared_ptr>; +public: + promise() : state_(new detail::shared_state()) {} + + promise(promise &&other) noexcept: state_(std::move(other.state_)) { + other.state_.reset(); + } + + promise(const promise &other) = delete; + + ~promise() {} + + promise &operator=(promise &&other) noexcept { + if (&other != this) { + state_ = std::move(other.state_); + other.state_.reset(); + } + return *this; + } + + promise &operator=(const promise &other) = delete; + + void swap(promise &other) noexcept { + std::swap(state_, other.state_); + } + + std::future get_future() { return std::future(state_); } + + void set_value() { state_->set(0); } + + void set_value_at_thread_exit(); + + void set_exception(std::exception_ptr p); + + void set_exception_at_thread_exit(std::exception_ptr p); + +private: + state_type state_; +}; + + +template +void swap(std::future &lhs, std::future &rhs) noexcept { + lhs.swap(rhs); +} + +template +void swap(std::promise &lhs, std::promise &rhs) noexcept { + lhs.swap(rhs); +} + +} // namespace std diff --git a/components/libc/cplusplus/cpp11/gcc/mutex b/components/libc/cplusplus/cpp11/gcc/mutex new file mode 100644 index 0000000000..3fdf86632b --- /dev/null +++ b/components/libc/cplusplus/cpp11/gcc/mutex @@ -0,0 +1,512 @@ +#pragma once + +#if __cplusplus < 201103L +#error "C++ version lower than C++11" +#endif + +//#if defined(RT_USING_PTHREADS) + +#include + +#include +#include +#include +#include + +#include "__utils.h" + +#define rt_cpp_mutex_t pthread_mutex_t + +namespace std +{ + // Base class on which to build std::mutex and std::timed_mutex + class __mutex_base + { + protected: + typedef rt_cpp_mutex_t __native_type; + + __native_type _m_mutex = PTHREAD_MUTEX_INITIALIZER; + + constexpr __mutex_base() noexcept = default; + __mutex_base(const __mutex_base&) = delete; + __mutex_base& operator=(const __mutex_base&) = delete; + }; + + + class mutex : private __mutex_base + { + public: + constexpr mutex() = default; + ~mutex() = default; + + mutex(const mutex&) = delete; + mutex& operator=(const mutex&) = delete; + + void lock() + { + int err = pthread_mutex_lock(&_m_mutex); + + if (err) + { + throw_system_error(err, "mutex:lock failed."); + } + } + + bool try_lock() noexcept + { + return !pthread_mutex_trylock(&_m_mutex); + } + + void unlock() noexcept + { + pthread_mutex_unlock(&_m_mutex); + } + + typedef __native_type* native_handle_type; + + native_handle_type native_handle() + { + return &_m_mutex; + }; + + }; + + inline int __rt_cpp_recursive_mutex_init(rt_cpp_mutex_t* m) + { + pthread_mutexattr_t attr; + int res; + + res = pthread_mutexattr_init(&attr); + if (res) + return res; + res = pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE); + if (res) + goto attr_cleanup; + res = pthread_mutex_init(m, &attr); + + attr_cleanup: + int err = pthread_mutexattr_destroy(&attr); + return res ? res : err; + } + + class __recursive_mutex_base + { + protected: + typedef rt_cpp_mutex_t __native_type; + + __native_type _m_recursive_mutex; + + __recursive_mutex_base(const __recursive_mutex_base&) = delete; + __recursive_mutex_base& operator=(const __recursive_mutex_base&) = delete; + + __recursive_mutex_base() + { + int err = __rt_cpp_recursive_mutex_init(&_m_recursive_mutex); + if (err) + throw_system_error(err, "Recursive mutex failed to construct"); + } + + ~__recursive_mutex_base() + { + pthread_mutex_destroy(&_m_recursive_mutex); + } + }; + + class recursive_mutex : private __recursive_mutex_base + { + public: + typedef __native_type* native_handle_type; + recursive_mutex() = default; + ~recursive_mutex() = default; + + recursive_mutex(const recursive_mutex&) = delete; + recursive_mutex& operator=(const recursive_mutex&) = delete; + void lock() + { + int err = pthread_mutex_lock(&_m_recursive_mutex); + + if (err) + throw_system_error(err, "recursive_mutex::lock failed"); + } + + bool try_lock() noexcept + { + return !pthread_mutex_trylock(&_m_recursive_mutex); + } + + void unlock() noexcept + { + pthread_mutex_unlock(&_m_recursive_mutex); + } + + native_handle_type native_handle() + { return &_m_recursive_mutex; } + }; + +#ifdef RT_PTHREAD_TIMED_MUTEX + + class timed_mutex; + + class recursive_timed_mutex; + +#endif // RT_PTHREAD_TIMED_MUTEX + + + struct defer_lock_t {}; + struct try_to_lock_t {}; + struct adopt_lock_t {}; // take ownership of a locked mtuex + + constexpr defer_lock_t defer_lock { }; + constexpr try_to_lock_t try_to_lock { }; + constexpr adopt_lock_t adopt_lock { }; + + template + class lock_guard + { + public: + typedef Mutex mutex_type; + + explicit lock_guard(mutex_type& m) : pm(m) { pm.lock(); } + lock_guard(mutex_type& m, adopt_lock_t) noexcept : pm(m) + { } + ~lock_guard() + { pm.unlock(); } + + lock_guard(lock_guard const&) = delete; + lock_guard& operator=(lock_guard const&) = delete; + + private: + mutex_type& pm; + + }; + + template + class unique_lock + { + public: + typedef Mutex mutex_type; + + unique_lock() noexcept : pm(nullptr), owns(false) { } + + explicit unique_lock(mutex_type& m) + : pm(std::addressof(m)), owns(false) + { + lock(); + owns = true; + } + + unique_lock(mutex_type& m, defer_lock_t) noexcept + : pm(std::addressof(m)), owns(false) + { } + + unique_lock(mutex_type& m, try_to_lock_t) noexcept + : pm(std::addressof(m)), owns(pm->try_lock()) + { } + + unique_lock(mutex_type& m, adopt_lock_t) noexcept + : pm(std::addressof(m)), owns(true) + { } + + // any lock-involving timed mutex API is currently only for custom implementations + // the standard ones are not available + template + unique_lock(mutex_type& m, const chrono::time_point& abs_time) noexcept + : pm(std::addressof(m)), owns(pm->try_lock_until(abs_time)) + { } + + template + unique_lock(mutex_type& m, const chrono::duration& rel_time) noexcept + : pm(std::addressof(m)), owns(pm->try_lock_for(rel_time)) + { } + + ~unique_lock() + { + if (owns) + unlock(); + } + + unique_lock(unique_lock const&) = delete; + unique_lock& operator=(unique_lock const&) = delete; + + unique_lock(unique_lock&& u) noexcept + : pm(u.pm), owns(u.owns) + { + u.pm = nullptr; + u.owns = false; + } + + unique_lock& operator=(unique_lock&& u) noexcept + { + if (owns) + unlock(); + + unique_lock(std::move(u)).swap(*this); + + u.pm = nullptr; + u.owns = false; + + return *this; + } + + void lock() + { + if (!pm) + throw_system_error(int(errc::operation_not_permitted), + "unique_lock::lock: references null mutex"); + else if (owns) + throw_system_error(int(errc::resource_deadlock_would_occur), + "unique_lock::lock: already locked" ); + else { + pm->lock(); + owns = true; + } + } + + bool try_lock() + { + if (!pm) + throw_system_error(int(errc::operation_not_permitted), + "unique_lock::try_lock: references null mutex"); + else if (owns) + throw_system_error(int(errc::resource_deadlock_would_occur), + "unique_lock::try_lock: already locked" ); + else { + owns = pm->try_lock(); + } + return owns; + } + + template + bool try_lock_for(const chrono::duration& rel_time) + { + if (!pm) + throw_system_error(int(errc::operation_not_permitted), + "unique_lock::try_lock_for: references null mutex"); + else if (owns) + throw_system_error(int(errc::resource_deadlock_would_occur), + "unique_lock::try_lock_for: already locked"); + else { + owns = pm->try_lock_for(rel_time); + } + return owns; + } + + template + bool try_lock_until(const chrono::time_point& abs_time) + { + if (!pm) + throw_system_error(int(errc::operation_not_permitted), + "unique_lock::try_lock_until: references null mutex"); + else if (owns) + throw_system_error(int(errc::resource_deadlock_would_occur), + "unique_lock::try_lock_until: already locked"); + else { + owns = pm->try_lock_until(abs_time); + } + return owns; + } + + void unlock() + { + if (!owns) + throw_system_error(int(errc::operation_not_permitted), + "unique_lock::unlock: not locked"); + else { + pm->unlock(); + owns = false; + } + } + + void swap(unique_lock& u) noexcept + { + std::swap(pm, u.pm); + std::swap(owns, u.owns); + } + + mutex_type *release() noexcept + { + mutex_type* ret_mutex = pm; + pm = nullptr; + owns = false; + + return ret_mutex; + } + + bool owns_lock() const noexcept + { return owns; } + + explicit operator bool() const noexcept + { return owns_lock(); } + + mutex_type* mutex() const noexcept + { return pm; } + + + private: + mutex_type *pm; + bool owns; + }; + + template + void swap(unique_lock& x, unique_lock& y) + { + x.swap(y); + } + + template + int try_lock(L0& l0, L1& l1) + { + unique_lock u0(l0, try_to_lock); // try to lock the first Lockable + // using unique_lock since we don't want to unlock l0 manually if l1 fails to lock + if (u0.owns_lock()) + { + if (l1.try_lock()) // lock the second one + { + u0.release(); // do not let RAII of a unique_lock unlock l0 + return -1; + } + else + return 1; + } + return 0; + } + + + template + int try_lock(L0& l0, L1& l1, L2& l2, L3&... l3) + { + int r = 0; + unique_lock u0(l0, try_to_lock); + // automatically unlock is done through RAII of unique_lock + if (u0.owns_lock()) + { + r = try_lock(l1, l2, l3...); + if (r == -1) + u0.release(); + else + ++r; + } + return r; + } + + template + void + __lock_first(int i, L0& l0, L1& l1, L2& l2, L3&... l3) + { + while (true) + { + // we first lock the one that is the most difficult to lock + switch (i) + { + case 0: + { + unique_lock u0(l0); + i = try_lock(l1, l2, l3...); + if (i == -1) + { + u0.release(); + return; + } + } + ++i; + sched_yield(); + break; + case 1: + { + unique_lock u1(l1); + i = try_lock(l2, l3..., l0); + if (i == -1) + { + u1.release(); + return; + } + } + if (i == sizeof...(L3) + 1) // all except l0 are locked + i = 0; + else + i += 2; // since i was two-based above + sched_yield(); + break; + default: + __lock_first(i - 2, l2, l3..., l0, l1); + return; + } + } + } + + + template + void lock(L0& l0, L1& l1) + { + while (true) + { + { + unique_lock u0(l0); + if (l1.try_lock()) + { + u0.release(); + break; + } + } + sched_yield(); + // wait and try the other way + { + unique_lock u1(l1); + if (l0.try_lock()) + { + u1.release(); + break; + } + } + sched_yield(); + } + } + + template + void lock(L0& l0, L1& l1, L2&... l2) + { + __lock_first(0, l0, l1, l2...); + } + + struct once_flag + { + constexpr once_flag() noexcept = default; + + once_flag(const once_flag&) = delete; + once_flag& operator=(const once_flag&) = delete; + + template + friend void call_once(once_flag& flag, Callable&& func, Args&&... args); + + private: + pthread_once_t _m_once = PTHREAD_ONCE_INIT; + }; + + mutex& get_once_mutex(); + extern function once_functor; + extern void set_once_functor_lock_ptr(unique_lock*); + + extern "C" void once_proxy(); // passed into pthread_once + + template + void call_once(once_flag& flag, Callable&& func, Args&&... args) + { + // use a lock to ensure the call to the functor + // is exclusive to only the first calling thread + unique_lock functor_lock(get_once_mutex()); + + auto call_wrapper = std::bind(std::forward(func), std::forward(args)...); + once_functor = [&]() { call_wrapper(); }; + + set_once_functor_lock_ptr(&functor_lock); // so as to unlock when actually calling + + int err = pthread_once(&flag._m_once, &once_proxy); + + if (functor_lock) + set_once_functor_lock_ptr(nullptr); + if (err) + throw_system_error(err, "call_once failed"); + } +} + +//#endif //(RT_USING_PTHREADS) \ No newline at end of file diff --git a/components/libc/cplusplus/cpp11/gcc/mutex.cpp b/components/libc/cplusplus/cpp11/gcc/mutex.cpp new file mode 100644 index 0000000000..e11f6d8990 --- /dev/null +++ b/components/libc/cplusplus/cpp11/gcc/mutex.cpp @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2006-2021, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2021-04-27 flybreak the first version. + */ + +#include "mutex" + +namespace std +{ + // use a set of global and static objects + // a proxy function to pthread_once + + function once_functor; + + mutex& get_once_mutex() + { + static mutex once_mutex; + return once_mutex; + } + + inline unique_lock*& get_once_functor_lock_ptr() + { + static unique_lock* once_functor_mutex_ptr = nullptr; + return once_functor_mutex_ptr; + } + + void set_once_functor_lock_ptr(unique_lock* m_ptr) + { + get_once_functor_lock_ptr() = m_ptr; + } + + extern "C" + { + void once_proxy() + { + // need to first transfer the functor's ownership so as to call it + function once_call = std::move(once_functor); + + // no need to hold the lock anymore + unique_lock* lock_ptr = get_once_functor_lock_ptr(); + get_once_functor_lock_ptr() = nullptr; + lock_ptr->unlock(); + + once_call(); + } + } +} diff --git a/components/libc/cplusplus/cpp11/gcc/thread b/components/libc/cplusplus/cpp11/gcc/thread new file mode 100644 index 0000000000..60e3ec964c --- /dev/null +++ b/components/libc/cplusplus/cpp11/gcc/thread @@ -0,0 +1,239 @@ +#pragma once + +#if __cplusplus < 201103L +#error "C++ version lower than C++11" +#endif + +//#if defined(RT_USING_PTHREADS) + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#define rt_cpp_thread_t pthread_t +#ifndef PTHREAD_NUM_MAX +#define PTHREAD_NUM_MAX 32 +#endif +#define CPP_UNJOINABLE_THREAD PTHREAD_NUM_MAX + +namespace std +{ + #define __STDCPP_THREADS__ __cplusplus + + + + class thread + { + public: + typedef rt_cpp_thread_t native_handle_type; + + struct invoker_base; + typedef shared_ptr invoker_base_ptr; + + class id + { + // basically a wrapper around native_handle_type + native_handle_type __cpp_thread_t; + + public: + id() noexcept : __cpp_thread_t(CPP_UNJOINABLE_THREAD) {} + + explicit id(native_handle_type hid) + : __cpp_thread_t(hid) {} + private: + friend class thread; + friend class hash; + + friend bool operator==(thread::id x, thread::id y) noexcept; + + friend bool operator<(thread::id x, thread::id y) noexcept; + + template + friend basic_ostream& + operator<<(basic_ostream& out, thread::id id); + }; + + thread() noexcept = default; + thread(const thread&) = delete; + thread& operator=(const thread&) = delete; + ~thread(); + + template + explicit thread(F&& f, Args&&... args) + { + start_thread(make_invoker_ptr(std::bind( + std::forward(f), + std::forward(args)... + ))); + } + + thread(thread&& t) noexcept + { + swap(t); + } + + thread& operator=(thread&& t) noexcept + { + if (joinable()) + terminate(); + swap(t); + return *this; + } + + // member functions + void swap(thread& t) noexcept + { + std::swap(_m_thr, t._m_thr); + } + + bool joinable() const noexcept + { + return (_m_thr.__cpp_thread_t < PTHREAD_NUM_MAX); + } + + void join(); + + void detach(); + + id get_id() const noexcept { return _m_thr; } + + native_handle_type native_handle() { return _m_thr.__cpp_thread_t; } + + // static members + static unsigned hardware_concurrency() noexcept; + + private: + id _m_thr; + + void start_thread(invoker_base_ptr b); + public: + struct invoker_base + { + invoker_base_ptr this_ptr; + + virtual ~invoker_base() = default; + + virtual void invoke() = 0; + }; + + + template + struct invoker : public invoker_base + { + Callable func; + + invoker(Callable&& F) : func(std::forward(F)) { } + + void invoke() { func(); } + }; + + template + shared_ptr> make_invoker_ptr(Callable&& F) + { + return std::make_shared>(std::forward(F)); + } + + + }; + + inline void swap(thread& x, thread& y) noexcept + { + x.swap(y); + } + + + inline bool operator==(thread::id x, thread::id y) noexcept + { + // From POSIX for pthread_equal: + //"If either t1 or t2 are not valid thread IDs, the behavior is undefined." + return x.__cpp_thread_t == y.__cpp_thread_t; + } + + inline bool operator!=(thread::id x, thread::id y) noexcept + { + return !(x == y); + } + + inline bool operator<(thread::id x, thread::id y) noexcept + { + return x.__cpp_thread_t < y.__cpp_thread_t; + } + + inline bool operator<=(thread::id x, thread::id y) noexcept + { + return !(y < x); + } + + inline bool operator>(thread::id x, thread::id y) noexcept + { + return !(x <= y); + } + + inline bool operator>=(thread::id x, thread::id y) noexcept + { + return !(x < y); + } + + template + inline basic_ostream& + operator<<(basic_ostream& out, thread::id id) + { + if (id == thread::id()) // id is invalid, representing no pthread + out << "thread::id of a non-executing thread"; + else + out << id.__cpp_thread_t; + return out; + } + + template <> + struct hash + { + typedef size_t result_type; + typedef thread::id argument_type; + size_t operator()(const thread::id& id) const noexcept + { + return hash()(id.__cpp_thread_t); + } + }; + + namespace this_thread + { + inline thread::id get_id() noexcept + { + return thread::id(pthread_self()); + } + + inline void yield() noexcept + { + sched_yield(); + } + + template + inline void sleep_for(const chrono::duration& rel_time) + { + if (rel_time <= rel_time.zero()) // less than zero, no need to sleep + return; + auto milli_secs = chrono::duration_cast(rel_time); + // the precision is limited by rt-thread thread API + rt_thread_mdelay(milli_secs.count()); + } + + template + inline void sleep_until(const chrono::time_point& abs_time) + { + auto now = Clock::now(); + if (abs_time > now) + sleep_for(abs_time - now); + } + + } +} diff --git a/components/libc/cplusplus/cpp11/gcc/thread.cpp b/components/libc/cplusplus/cpp11/gcc/thread.cpp new file mode 100644 index 0000000000..3979da0dc4 --- /dev/null +++ b/components/libc/cplusplus/cpp11/gcc/thread.cpp @@ -0,0 +1,94 @@ +/* + * Copyright (c) 2006-2021, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2021-04-27 flybreak the first version. + */ + +#include "thread" +#include "__utils.h" + + +#define _RT_NPROCS 0 + +namespace std +{ + + extern "C" + { + static void* execute_native_thread_routine(void *p) + { + thread::invoker_base* t = static_cast(p); + thread::invoker_base_ptr local; + local.swap(t->this_ptr); // tranfer the ownership of the invoker into the thread entry + + local->invoke(); + + return NULL; + } + } + + void thread::start_thread(invoker_base_ptr b) + { + auto raw_ptr = b.get(); + // transfer the ownership of the invoker to the new thread + raw_ptr->this_ptr = std::move(b); + int err = pthread_create(&_m_thr.__cpp_thread_t, NULL, + &execute_native_thread_routine, raw_ptr); + + if (err) + { + raw_ptr->this_ptr.reset(); + throw_system_error(err, "Failed to create a thread"); + } + + } + + thread::~thread() + { + if (joinable()) // when either not joined or not detached + terminate(); + } + + void thread::join() + { + int err = EINVAL; + + if (joinable()) + err = pthread_join(native_handle(), NULL); + + if (err) + { + throw_system_error(err, "thread::join failed"); + } + + _m_thr = id(); + } + + void thread::detach() + { + int err = EINVAL; + + if (joinable()) + err = pthread_detach(native_handle()); + if (err) + { + throw_system_error(err, "thread::detach failed"); + } + + _m_thr = id(); + } + + // TODO: not yet actually implemented. + // The standard states that the returned value should only be considered a hint. + unsigned thread::hardware_concurrency() noexcept + { + int __n = _RT_NPROCS; + if (__n < 0) + __n = 0; + return __n; + } +} diff --git a/components/libc/cplusplus/cpp11/gcc/utils.cpp b/components/libc/cplusplus/cpp11/gcc/utils.cpp new file mode 100644 index 0000000000..1ec3b70cad --- /dev/null +++ b/components/libc/cplusplus/cpp11/gcc/utils.cpp @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2006-2021, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2021-04-27 flybreak the first version. + */ + +#include "__utils.h" +#include + +tick_clock::time_point tick_clock::now() +{ + tick_clock::rep cur_tk = clock(); + tick_clock::duration cur_time(cur_tk); + + return tick_clock::time_point(cur_time); +} + +real_time_clock::time_point real_time_clock::now() noexcept +{ + timespec tp; + clock_gettime(CLOCK_REALTIME, &tp); + + return time_point(duration(std::chrono::seconds(tp.tv_sec)) + + std::chrono::nanoseconds(tp.tv_nsec)); +} diff --git a/components/libc/cplusplus/cpp11/thread_local_impl.cpp b/components/libc/cplusplus/cpp11/thread_local_impl.cpp new file mode 100644 index 0000000000..43761c1e62 --- /dev/null +++ b/components/libc/cplusplus/cpp11/thread_local_impl.cpp @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2006-2021, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2021-04-27 flybreak the first version. + */ + +#include +#include + +typedef void (*destructor) (void *); + +extern "C" +int __cxa_thread_atexit_impl(destructor dtor, void* obj, void* dso_symbol) +{ + pthread_key_t key_tmp; + if (pthread_key_create(&key_tmp, dtor) != 0) + abort(); + pthread_setspecific(key_tmp, obj); + return 0; +} + +#if defined(__GNUC__) && !defined(__ARMCC_VERSION)/*GCC*/ +#include + +extern"C" +int __cxxabiv1::__cxa_thread_atexit(destructor dtor, void *obj, void *dso_handle) +{ + return __cxa_thread_atexit_impl(dtor, obj, dso_handle); +} +#endif diff --git a/components/libc/cplusplus/cxx_Mutex.cpp b/components/libc/cplusplus/cxx_Mutex.cpp new file mode 100644 index 0000000000..da6f80985f --- /dev/null +++ b/components/libc/cplusplus/cxx_Mutex.cpp @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2006-2021, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + */ + +#include "cxx_mutex.h" + +using namespace rtthread; + +Mutex::Mutex(const char *name) +{ + rt_mutex_init(&mID, name, RT_IPC_FLAG_PRIO); +} + +bool Mutex::lock(int32_t millisec) +{ + rt_int32_t tick; + + if (millisec < 0) + tick = -1; + else + tick = rt_tick_from_millisecond(millisec); + + return rt_mutex_take(&mID, tick) == RT_EOK; +} + +bool Mutex::trylock() +{ + return lock(0); +} + +void Mutex::unlock() +{ + rt_mutex_release(&mID); +} + +Mutex::~Mutex() +{ + rt_mutex_detach(&mID); +} diff --git a/components/libc/cplusplus/cxx_Semaphore.cpp b/components/libc/cplusplus/cxx_Semaphore.cpp new file mode 100644 index 0000000000..672eeb04af --- /dev/null +++ b/components/libc/cplusplus/cxx_Semaphore.cpp @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2006-2021, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + */ + +#include "cxx_semaphore.h" + +using namespace rtthread; + +Semaphore::Semaphore(const char *name, int32_t count) +{ + rt_sem_init(&mID, name, count, RT_IPC_FLAG_FIFO); +} + +bool Semaphore::wait(int32_t millisec) +{ + rt_int32_t tick; + + if (millisec < 0) + tick = -1; + else + tick = rt_tick_from_millisecond(millisec); + + return rt_sem_take(&mID, tick) == RT_EOK; +} + +void Semaphore::release(void) +{ + rt_sem_release(&mID); +} + +Semaphore::~Semaphore() +{ + rt_sem_detach(&mID); +} diff --git a/components/libc/cplusplus/cxx_Thread.cpp b/components/libc/cplusplus/cxx_Thread.cpp new file mode 100644 index 0000000000..f3484bb1f4 --- /dev/null +++ b/components/libc/cplusplus/cxx_Thread.cpp @@ -0,0 +1,117 @@ +/* + * Copyright (c) 2006-2021, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + */ + +#include "cxx_thread.h" + +using namespace rtthread; + +Thread::Thread(rt_uint32_t stack_size, + rt_uint8_t priority, + rt_uint32_t tick, + const char *name) + : _entry(RT_NULL), _param(RT_NULL), started(false) +{ + rt_event_init(&_event, name, 0); + + _thread = rt_thread_create(name, + (thread_func_t)func, + this, + stack_size, + priority, + tick); +} + +Thread::Thread(void (*entry)(void *p), + void *p, + rt_uint32_t stack_size, + rt_uint8_t priority, + rt_uint32_t tick, + const char *name) + : _entry(entry), _param(p), started(false) +{ + rt_event_init(&_event, name, 0); + + _thread = rt_thread_create(name, + (thread_func_t)func, + this, + stack_size, + priority, + tick); +} + +Thread::~Thread() +{ + rt_event_detach(&_event); + rt_thread_delete(_thread); +} + +bool Thread::start() +{ + if (rt_thread_startup(_thread) == RT_EOK) + { + started = true; + } + + return started; +} + +void Thread::sleep(int32_t millisec) +{ + rt_int32_t tick; + + if (millisec < 0) + tick = 1; + else + tick = rt_tick_from_millisecond(millisec); + + rt_thread_delay(tick); +} + +void Thread::func(Thread *pThis) +{ + if (pThis->_entry != RT_NULL) + { + pThis->_entry(pThis->_param); + } + else + { + pThis->run(pThis->_param); + } + + rt_event_send(&pThis->_event, 1); +} + +void Thread::run(void *parameter) +{ + /* please overload this method */ +} + +rt_err_t Thread::wait(int32_t millisec) +{ + return join(millisec); +} + +rt_err_t Thread::join(int32_t millisec) +{ + if (started) + { + rt_int32_t tick; + + if (millisec < 0) + tick = -1; + else + tick = rt_tick_from_millisecond(millisec); + + return rt_event_recv(&_event, 1, RT_EVENT_FLAG_OR | RT_EVENT_FLAG_CLEAR, tick, RT_NULL); + } + else + { + return -RT_ENOSYS; + } +} diff --git a/components/libc/cplusplus/cxx_crt.cpp b/components/libc/cplusplus/cxx_crt.cpp new file mode 100644 index 0000000000..de2fe3cd74 --- /dev/null +++ b/components/libc/cplusplus/cxx_crt.cpp @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2006-2021, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2015-03-07 Bernard Add copyright header. + */ + +#include +#include "cxx_crt.h" + +void *operator new(size_t size) +{ + return rt_malloc(size); +} + +void *operator new[](size_t size) +{ + return rt_malloc(size); +} + +void operator delete(void *ptr) +{ + rt_free(ptr); +} + +void operator delete[](void *ptr) +{ + return rt_free(ptr); +} + +void __cxa_pure_virtual(void) +{ + rt_kprintf("Illegal to call a pure virtual function.\n"); +} diff --git a/components/libc/cplusplus/cxx_crt.h b/components/libc/cplusplus/cxx_crt.h new file mode 100644 index 0000000000..903d4c86cd --- /dev/null +++ b/components/libc/cplusplus/cxx_crt.h @@ -0,0 +1,26 @@ +/* + * Copyright (c) 2006-2021, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * +* Change Logs: +* Date Author Notes +* 2015-03-07 Bernard Add copyright header. +*/ + +#ifndef CRT_H_ +#define CRT_H_ + +#include +#include + +void *operator new(size_t size); +void *operator new[](size_t size); + +void operator delete(void * ptr); +void operator delete[](void *ptr); + +extern "C" void __cxa_pure_virtual(void); +extern "C" int cplusplus_system_init(void); + +#endif diff --git a/components/libc/cplusplus/cxx_crt_init.c b/components/libc/cplusplus/cxx_crt_init.c new file mode 100644 index 0000000000..46946089ff --- /dev/null +++ b/components/libc/cplusplus/cxx_crt_init.c @@ -0,0 +1,68 @@ +/* + * Copyright (c) 2006-2021, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2014-12-03 Bernard Add copyright header. + * 2014-12-29 Bernard Add cplusplus initialization for ARMCC. + * 2016-06-28 Bernard Add _init/_fini routines for GCC. + * 2016-10-02 Bernard Add WEAK for cplusplus_system_init routine. + */ + +#include + +#if defined(__ARMCC_VERSION) +extern void $Super$$__cpp_initialize__aeabi_(void); +/* we need to change the cpp_initialize order */ +RT_WEAK void $Sub$$__cpp_initialize__aeabi_(void) +{ + /* empty */ +} +#elif defined(__GNUC__) && !defined(__CS_SOURCERYGXX_MAJ__) +/* The _init()/_fini() routines has been defined in codesourcery g++ lite */ +RT_WEAK void _init() +{ +} + +RT_WEAK void _fini() +{ +} + +RT_WEAK void *__dso_handle = 0; + +#endif + +RT_WEAK int cplusplus_system_init(void) +{ +#if defined(__ARMCC_VERSION) + /* If there is no SHT$$INIT_ARRAY, calling + * $Super$$__cpp_initialize__aeabi_() will cause fault. At least until Keil5.12 + * the problem still exists. So we have to initialize the C++ runtime by ourself. + */ + typedef void PROC(); + extern const unsigned long SHT$$INIT_ARRAY$$Base[]; + extern const unsigned long SHT$$INIT_ARRAY$$Limit[]; + + const unsigned long *base = SHT$$INIT_ARRAY$$Base; + const unsigned long *lim = SHT$$INIT_ARRAY$$Limit; + + for (; base != lim; base++) + { + PROC *proc = (PROC *)((const char *)base + *base); + (*proc)(); + } +#elif defined(__GNUC__) + typedef void(*pfunc)(); + extern pfunc __ctors_start__[]; + extern pfunc __ctors_end__[]; + pfunc *p; + + for (p = __ctors_start__; p < __ctors_end__; p++) + (*p)(); +#endif + + return 0; +} +INIT_COMPONENT_EXPORT(cplusplus_system_init); diff --git a/components/libc/cplusplus/cxx_lock.h b/components/libc/cplusplus/cxx_lock.h new file mode 100644 index 0000000000..c3cc1d2dae --- /dev/null +++ b/components/libc/cplusplus/cxx_lock.h @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2006-2021, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2016/10/1 Bernard The first version + */ + +#pragma once + +#include +#include + +namespace rtthread { + +class Lock +{ +public: + Lock(Mutex& mutex) : m(mutex) {m.lock();} + ~Lock() {m.unlock();} + +protected: + Mutex &m; +}; + +} diff --git a/components/libc/cplusplus/cxx_mail.h b/components/libc/cplusplus/cxx_mail.h new file mode 100644 index 0000000000..88770bdd94 --- /dev/null +++ b/components/libc/cplusplus/cxx_mail.h @@ -0,0 +1,81 @@ +/* + * Copyright (c) 2006-2021, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2016/10/1 Bernard The first version + */ + +#pragma once + +#include +#include + +#include + +namespace rtthread { + +/** + * The Mail class allow to control, send, receive, or wait for mail. + * A mail is a memory block that is send to a thread or interrupt service routine. + * @param T data type of a single message element. + * @param queue_sz maximum number of messages in queue. + */ + +template +class Mail { +public: + /** Create and Initialise Mail queue. */ + Mail(const char *name = "") + { + rt_mb_init(&mID, name, mPool, queue_sz, RT_IPC_FLAG_FIFO); + } + + ~Mail() + { + rt_mb_detach(&mID); + } + + /** Put a mail in the queue. + @param mptr memory block previously allocated with Mail::alloc or Mail::calloc. + @return status code that indicates the execution status of the function. + */ + bool put(T *mptr, int32_t millisec = 0) + { + rt_int32_t tick; + + if (millisec < 0) + tick = -1; + else + tick = rt_tick_from_millisecond(millisec); + + return rt_mb_send_wait(&mID, (rt_ubase_t)mptr, tick) == RT_EOK; + } + + /** Get a mail from a queue. + @param millisec timeout value or 0 in case of no time-out. (default: osWaitForever). + @return event that contains mail information or error code. + */ + T* get(int32_t millisec = -1) + { + T *t = NULL; + rt_int32_t tick; + + if (millisec < 0) + tick = -1; + else + tick = rt_tick_from_millisecond(millisec); + + rt_mb_recv(&mID, &t, tick); + + return t; + } + +private: + struct rt_mailbox mID; + T* mPool[queue_sz]; +}; + +} diff --git a/components/libc/cplusplus/cxx_mutex.h b/components/libc/cplusplus/cxx_mutex.h new file mode 100644 index 0000000000..63efb4a6ea --- /dev/null +++ b/components/libc/cplusplus/cxx_mutex.h @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2006-2021, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2016/10/1 Bernard The first version + */ + +#pragma once + +#include +#include + +namespace rtthread { + +/** The Mutex class is used to synchronise the execution of threads. + This is for example used to protect access to a shared resource. +*/ +class Mutex { +public: + /** Create and Initialize a Mutex object */ + Mutex(const char *name = "mutex"); + ~Mutex(); + + /** Wait until a Mutex becomes available. + @param millisec timeout value or 0 in case of no time-out. (default: WaitForever) + @return true if the mutex was acquired, false otherwise. + */ + bool lock(int32_t millisec = -1); + + /** Try to lock the mutex, and return immediately + @return true if the mutex was acquired, false otherwise. + */ + bool trylock(); + + /** Unlock the mutex that has previously been locked by the same thread + */ + void unlock(); + +private: + struct rt_mutex mID; +}; + +} diff --git a/components/libc/cplusplus/cxx_queue.h b/components/libc/cplusplus/cxx_queue.h new file mode 100644 index 0000000000..f6b91e1a21 --- /dev/null +++ b/components/libc/cplusplus/cxx_queue.h @@ -0,0 +1,74 @@ +/* + * Copyright (c) 2006-2021, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2016/10/1 Bernard The first version + */ + +#pragma once + +#include +#include + +#include + +namespace rtthread { + +/** + * The Queue class allow to control, send, receive, or wait for messages. + * A message can be a integer or pointer value to a certain type T that is send + * to a thread or interrupt service routine. + * @param T data type of a single message element. + * @param queue_sz maximum number of messages in queue. + */ +template +class Queue +{ +public: + /** Create and initialise a message Queue. */ + Queue() + { + rt_mq_init(&mID, "mq", mPool, sizeof(T), sizeof(mPool), RT_IPC_FLAG_FIFO); + }; + + ~Queue() + { + rt_mq_detach(&mID); + }; + + /** Put a message in a Queue. + @param data message pointer. + @param millisec timeout value or 0 in case of no time-out. (default: 0) + @return status code that indicates the execution status of the function. + */ + rt_err_t put(T& data, int32_t millisec = 0) + { + return rt_mq_send(&mID, &data, sizeof(data)); + } + + /** Get a message or Wait for a message from a Queue. + @param millisec timeout value or 0 in case of no time-out. (default: osWaitForever). + @return bool . + */ + bool get(T& data, int32_t millisec = WAIT_FOREVER) + { + rt_int32_t tick; + + if (millisec < 0) + tick = -1; + else + tick = rt_tick_from_millisecond(millisec); + + return rt_mq_recv(&mID, &data, sizeof(data), tick) == RT_EOK; + } + +private: + struct rt_messagequeue mID; + + char mPool[(sizeof(void *) + RT_ALIGN(sizeof(T), RT_ALIGN_SIZE)) * queue_sz]; +}; + +} diff --git a/components/libc/cplusplus/cxx_semaphore.h b/components/libc/cplusplus/cxx_semaphore.h new file mode 100644 index 0000000000..45c916e169 --- /dev/null +++ b/components/libc/cplusplus/cxx_semaphore.h @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2006-2021, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2016/10/1 Bernard The first version + */ + +#pragma once + +#include +#include + +namespace rtthread { + +/** The Semaphore class is used to manage and protect access to a set of shared resources. */ +class Semaphore +{ +public: + /** Create and Initialize a Semaphore object used for managing resources. + @param number of available resources; maximum index value is (count-1). + */ + Semaphore(const char *name = "sem", int32_t count = 0); + ~Semaphore(); + + /** Wait until a Semaphore resource becomes available. + @param millisec timeout value or 0 in case of no time-out. + @return true on success. + */ + bool wait(int32_t millisec = -1); + + /** Release a Semaphore resource that was obtain with Semaphore::wait. + */ + void release(void); + +private: + struct rt_semaphore mID; +}; + +} diff --git a/components/libc/cplusplus/cxx_thread.h b/components/libc/cplusplus/cxx_thread.h new file mode 100644 index 0000000000..0e681e5c2a --- /dev/null +++ b/components/libc/cplusplus/cxx_thread.h @@ -0,0 +1,67 @@ +/* + * Copyright (c) 2006-2021, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2016/10/1 Bernard The first version + */ + +#pragma once + +#include +#include + +namespace rtthread +{ + +/** The Thread class allow defining, creating, and controlling thread functions in the system. */ +class Thread +{ +public: + typedef void (*thread_func_t)(void *param); + + /** Allocate a new thread without starting execution + @param priority initial priority of the thread function. (default: osPriorityNormal). + @param stack_size stack size (in bytes) requirements for the thread function. (default: DEFAULT_STACK_SIZE). + @param stack_pointer pointer to the stack area to be used by this thread (default: NULL). + */ + Thread(rt_uint32_t stack_size = 2048, + rt_uint8_t priority = (RT_THREAD_PRIORITY_MAX * 2) / 3, + rt_uint32_t tick = 20, + const char *name = "th"); + + Thread(void (*entry)(void *p), + void *p = RT_NULL, + rt_uint32_t stack_size = 2048, + rt_uint8_t priority = (RT_THREAD_PRIORITY_MAX * 2) / 3, + rt_uint32_t tick = 20, + const char *name = "th"); + + virtual ~Thread(); + + bool start(); + + static void sleep(int32_t millisec); + + rt_err_t wait(int32_t millisec); + rt_err_t join(int32_t millisec = -1); + +protected: + virtual void run(void *parameter); + +private: + static void func(Thread *pThis); + + rt_thread_t _thread; + + thread_func_t _entry; + void *_param; + + /* event for thread join */ + struct rt_event _event; + bool started; +}; + +} diff --git a/components/libc/posix/Kconfig b/components/libc/posix/Kconfig index 5c766d9509..411289baf6 100644 --- a/components/libc/posix/Kconfig +++ b/components/libc/posix/Kconfig @@ -45,13 +45,13 @@ config RT_USING_POSIX_DELAY default n config RT_USING_POSIX_CLOCK - bool "Enable clock/time functions, clock_gettime()/clock_settime()/clock_getres() etc" + bool "Enable clock/time APIs, clock_gettime()/clock_settime() etc" select RT_USING_POSIX_DELAY default n config RT_USING_POSIX_TIMER select RT_USING_TIMER_SOFT - bool "Enable posix time functions, timer_create()/timer_gettime()/timer_settime() etc" + bool "Enable timer APIs, timer_create()/timer_gettime() etc" default n config RT_USING_PTHREADS @@ -66,7 +66,7 @@ if RT_USING_PTHREADS endif config RT_USING_MODULE - bool "Enable dynamic module with dlopen/dlsym/dlclose feature" + bool "Enable dynamic module APIs, dlopen()/dlsym()/dlclose() etc" default n if RT_USING_MODULE diff --git a/components/lwp/Kconfig b/components/lwp/Kconfig index fde442d235..5ea3017479 100644 --- a/components/lwp/Kconfig +++ b/components/lwp/Kconfig @@ -1,5 +1,5 @@ config RT_USING_LWP - bool "Using light-weight process" + bool "LWP: light-weight process" select RT_USING_POSIX_FS select RT_USING_POSIX_SELECT depends on ARCH_ARM_CORTEX_M || ARCH_ARM_ARM9 || ARCH_ARM_CORTEX_A diff --git a/components/net/lwip/Kconfig b/components/net/lwip/Kconfig index 42b48f4413..78fba33b91 100644 --- a/components/net/lwip/Kconfig +++ b/components/net/lwip/Kconfig @@ -1,5 +1,5 @@ menuconfig RT_USING_LWIP - bool "Enable light weight TCP/IP stack (lwIP)" + bool "LwIP: light weight TCP/IP stack" select RT_USING_DEVICE select RT_USING_DEVICE_IPC default n diff --git a/components/net/sal/Kconfig b/components/net/sal/Kconfig index 1274258ce6..3836049333 100644 --- a/components/net/sal/Kconfig +++ b/components/net/sal/Kconfig @@ -1,5 +1,5 @@ menuconfig RT_USING_SAL - bool "Enable socket abstraction layer (SAL)" + bool "SAL: socket abstraction layer" select RT_USING_NETDEV select RT_USING_SYSTEM_WORKQUEUE default n diff --git a/components/vbus/Kconfig b/components/vbus/Kconfig index cd30874e38..74a891d2a0 100644 --- a/components/vbus/Kconfig +++ b/components/vbus/Kconfig @@ -1,37 +1,35 @@ -menu "VBUS(Virtual Software BUS)" - -config RT_USING_VBUS - bool "Enable VBUS" +menuconfig RT_USING_VBUS + bool "VBus: virtual software bus" default n if RT_USING_VBUS config RT_USING_VBUS_RFS - bool "Enable Remote File System on VBUS" + bool "Enable Remote File System on VBus" default n help When enable remote file system, the application can visit the remote file system - through VBUS with POSIX file I/O. + through VBus with POSIX file I/O. config RT_USING_VBUS_RSHELL - bool "Enable Remote Shell on VBUS" + bool "Enable Remote Shell on VBus" default n help When enable remote shell, the finsh/msh of RT-Thread can be operated from another Operating System. config RT_VBUS_USING_TESTS - bool "Enable tests on VBUS " + bool "Enable tests on VBus " default n config _RT_VBUS_RING_BASE - hex "VBUS address" + hex "VBus address" help - VBUS ring buffer physical address. + VBus ring buffer physical address. config _RT_VBUS_RING_SZ - int "VBUS ring size" + int "VBus ring size" help - VBUS size of the ring buffer. + VBus size of the ring buffer. config RT_VBUS_GUEST_VIRQ int "RT_VBUS_GUEST_VIRQ" @@ -58,5 +56,3 @@ if RT_USING_VBUS The name of the UBUS rfs device. endif - -endmenu -- cgit v1.3.1