13#ifndef CMSIS_PLUS_RTOS_OS_THREAD_H_
14#define CMSIS_PLUS_RTOS_OS_THREAD_H_
18#if defined(__cplusplus)
22#if defined(OS_USE_OS_APP_CONFIG_H)
23#include <cmsis-plus/os-app-config.h>
30#if !defined(__ARM_EABI__)
36#pragma GCC diagnostic push
38#pragma clang diagnostic ignored "-Wc++98-compat"
39#pragma clang diagnostic ignored "-Wdocumentation-unknown-command"
51 using _func_args_t =
void*;
57#pragma GCC diagnostic push
59#pragma clang diagnostic ignored "-Wc++98-compat"
64#pragma GCC diagnostic pop
122 exit (
void* exit_ptr =
nullptr);
208#pragma GCC diagnostic push
209#if defined(__clang__)
210#pragma clang diagnostic ignored "-Wreserved-identifier"
218#pragma GCC diagnostic pop
230#pragma GCC diagnostic push
231#if defined(__clang__)
232#pragma clang diagnostic ignored "-Wpadded"
233#elif defined(__GNUC__)
234#pragma GCC diagnostic ignored "-Wpadded"
243#pragma GCC diagnostic push
244#if defined(__clang__)
245#elif defined(__GNUC__)
246#pragma GCC diagnostic ignored "-Wsuggest-final-methods"
247#pragma GCC diagnostic ignored "-Wsuggest-final-types"
297 static constexpr uint32_t
range = 4;
469 operator= (
const stack&) =
delete;
471 operator= (
stack&&) =
delete;
639 std::size_t size_bytes_;
641 static std::size_t min_size_bytes_;
642 static std::size_t default_size_bytes_;
678 operator= (
const context&) =
delete;
680 operator= (
context&&) =
delete;
733#if !defined(OS_USE_RTOS_PORT_SCHEDULER)
737 friend port::stack::element_t*
765#if !defined(OS_USE_RTOS_PORT_SCHEDULER)
770 port::thread_context_t port_;
785#pragma GCC diagnostic push
786#if defined(__clang__)
787#pragma clang diagnostic ignored "-Wpadded"
788#elif defined(__GNUC__)
789#pragma GCC diagnostic ignored "-Wpadded"
881#if defined(OS_INCLUDE_RTOS_STATISTICS_THREAD_CONTEXT_SWITCHES) \
882 || defined(OS_INCLUDE_RTOS_STATISTICS_THREAD_CPU_CYCLES)
936#if defined(OS_INCLUDE_RTOS_STATISTICS_THREAD_CONTEXT_SWITCHES)
950#if defined(OS_INCLUDE_RTOS_STATISTICS_THREAD_CPU_CYCLES)
984 rtos::scheduler::internal_switch_threads (
void);
986#if defined(OS_INCLUDE_RTOS_STATISTICS_THREAD_CONTEXT_SWITCHES)
990#if defined(OS_INCLUDE_RTOS_STATISTICS_THREAD_CPU_CYCLES)
1002#pragma GCC diagnostic pop
1068 operator= (
const thread&) =
delete;
1070 operator= (
thread&&) =
delete;
1145 join (
void** exit_ptr =
nullptr);
1192 set_cancel_state (
int,
int*);
1194 set_cancel_type (
int,
int*);
1197 get_sched_param (
int*,
struct sched_param*);
1199 set_sched_param (
int,
const struct sched_param*);
1251#if defined(OS_INCLUDE_RTOS_CUSTOM_THREAD_USER_STORAGE) || defined(__DOXYGEN__)
1259 os_thread_user_storage_t*
1276#if defined(OS_INCLUDE_RTOS_THREAD_PUBLIC_FLAGS_CLEAR)
1303#if defined(OS_INCLUDE_RTOS_STATISTICS_THREAD_CONTEXT_SWITCHES) \
1304 || defined(OS_INCLUDE_RTOS_STATISTICS_THREAD_CPU_CYCLES)
1363 scheduler::internal_link_node (
1370 scheduler::internal_unlink_node (
1375 scheduler::internal_switch_threads (
void);
1383 friend port::stack::element_t*
1387 ::os_rtos_idle_actions (
void);
1429 std::size_t stack_size_bytes);
1439 internal_suspend_ (
void);
1449 internal_exit_ (
void* exit_ptr =
nullptr);
1564 internal_destroy_ (
void);
1573 internal_relink_running_ (
void);
1582 internal_check_stack_ (
void);
1609 void* func_result_ =
nullptr;
1612 thread* parent_ =
nullptr;
1623 threads_list children_
1632 thread* joiner_ =
nullptr;
1635 internal::waiting_thread_node* waiting_node_ =
nullptr;
1638 internal::timeout_thread_node* clock_node_ =
nullptr;
1643 clock* clock_ =
nullptr;
1648 const void* allocator_ =
nullptr;
1652 std::size_t allocated_stack_size_elements_ = 0;
1655 std::size_t
volatile acquired_mutexes_ = 0;
1684 bool volatile interrupted_ =
false;
1686 internal::event_flags event_flags_;
1688#if defined(OS_INCLUDE_RTOS_CUSTOM_THREAD_USER_STORAGE) || defined(__DOXYGEN__)
1689 os_thread_user_storage_t user_storage_;
1692#if defined(OS_INCLUDE_RTOS_STATISTICS_THREAD_CONTEXT_SWITCHES)
1694 class statistics statistics_;
1701#if defined(OS_USE_RTOS_PORT_SCHEDULER)
1702 friend class port::thread;
1703 os_thread_port_data_t port_;
1718#pragma GCC diagnostic pop
1727 template<
typename Allocator = memory::allocator<
void*>>
1803 internal_destroy_ (
void)
override;
1822 template<std::
size_t N = port::stack::default_size_
bytes>
1889 +
sizeof(stack::allocation_element_t) - 1)
1890 /
sizeof(stack::allocation_element_t)];
1898#pragma GCC diagnostic pop
2102 __attribute__ ((always_inline))
2132 bottom_address_ =
nullptr;
2142 assert (size_bytes >= min_size_bytes_);
2143 bottom_address_ = address;
2144 size_bytes_ = size_bytes;
2153 return bottom_address_;
2162 return bottom_address_ + (size_bytes_ /
sizeof(
element_t));
2198 return min_size_bytes_;
2207 std::size_t tmp = min_size_bytes_;
2208 min_size_bytes_ = size_bytes;
2218 return default_size_bytes_;
2227 assert (size_bytes != 0);
2228 assert (size_bytes >= min_size_bytes_);
2230 std::size_t tmp = default_size_bytes_;
2231 default_size_bytes_ = size_bytes;
2256#if defined(OS_INCLUDE_RTOS_STATISTICS_THREAD_CONTEXT_SWITCHES)
2275 return context_switches_;
2280#if defined(OS_INCLUDE_RTOS_STATISTICS_THREAD_CPU_CYCLES)
2301#if defined(OS_INCLUDE_RTOS_STATISTICS_THREAD_CONTEXT_SWITCHES) \
2302 || defined(OS_INCLUDE_RTOS_STATISTICS_THREAD_CPU_CYCLES)
2318#if defined(OS_INCLUDE_RTOS_STATISTICS_THREAD_CONTEXT_SWITCHES)
2319 context_switches_ = 0;
2322#if defined(OS_INCLUDE_RTOS_STATISTICS_THREAD_CPU_CYCLES)
2342 return this == &rhs;
2369 return interrupted_;
2372#if defined(OS_INCLUDE_RTOS_CUSTOM_THREAD_USER_STORAGE) || defined(__DOXYGEN__)
2391 inline os_thread_user_storage_t*
2394 return &user_storage_;
2399#if !defined(OS_USE_RTOS_PORT_SCHEDULER)
2409 thread::internal_relink_running_ (
void)
2416 if (crt_node.
next () ==
nullptr)
2418 rtos::scheduler::ready_threads_list_.link (crt_node);
2424 if (!stack ().check_bottom_magic ())
2429 assert (stack ().check_bottom_magic ());
2444 inline class thread::stack&
2447 return context_.stack_;
2450#if defined(OS_INCLUDE_RTOS_STATISTICS_THREAD_CONTEXT_SWITCHES)
2463#if defined(OS_INCLUDE_RTOS_THREAD_PUBLIC_FLAGS_CLEAR)
2468 return internal_flags_clear_ (mask, oflags);
2516 template<
typename Allocator>
2522 {
nullptr, function, args, attr, allocator }
2567 template<
typename Allocator>
2574#if defined(OS_TRACE_RTOS_THREAD)
2575 trace::printf (
"%s @%p %s\n", __func__,
this, this->name ());
2577 if (attr.th_stack_address !=
nullptr
2578 && attr.th_stack_size_bytes > stack::min_size ())
2580 internal_construct_ (function, args, attr,
nullptr, 0);
2584 allocator_ = &allocator;
2586 if (attr.th_stack_size_bytes > stack::min_size ())
2588 allocated_stack_size_elements_ = (attr.th_stack_size_bytes
2589 +
sizeof(
typename allocator_type::value_type) - 1)
2590 /
sizeof(
typename allocator_type::value_type);
2594 allocated_stack_size_elements_ = (stack::default_size ()
2595 +
sizeof(
typename allocator_type::value_type) - 1)
2596 /
sizeof(
typename allocator_type::value_type);
2601 allocated_stack_address_ =
2602 reinterpret_cast<stack::element_t*
> ((
const_cast<allocator_type&
> (
allocator)).allocate (
2603 allocated_stack_size_elements_));
2605 assert (allocated_stack_address_ !=
nullptr);
2607 internal_construct_ (
2611 allocated_stack_address_,
2612 allocated_stack_size_elements_
2613 *
sizeof(
typename allocator_type::value_type));
2621 template<
typename Allocator>
2623 thread_allocated<Allocator>::internal_destroy_ (
void)
2625#if defined(OS_TRACE_RTOS_THREAD)
2626 trace::printf (
"thread_allocated::%s() @%p %s\n", __func__,
this,
2630 if (allocated_stack_address_ !=
nullptr)
2632 internal_check_stack_ ();
2634 typedef typename std::allocator_traits<allocator_type>::pointer pointer;
2636#pragma GCC diagnostic push
2637#pragma GCC diagnostic ignored "-Wcast-align"
2638 static_cast<allocator_type*
> (
const_cast<void*
> (allocator_))->deallocate (
2639 reinterpret_cast<pointer
> (allocated_stack_address_),
2640 allocated_stack_size_elements_);
2641#pragma GCC diagnostic pop
2643 allocated_stack_address_ =
nullptr;
2646 thread::internal_destroy_ ();
2666 template<
typename Allocator>
2669#if defined(OS_TRACE_RTOS_THREAD)
2722 template<std::
size_t N>
2727 {
nullptr, function, args, attr }
2777 template<std::
size_t N>
2784#if defined(OS_TRACE_RTOS_THREAD)
2785 trace::printf (
"%s @%p %s\n", __func__,
this, this->name ());
2787 internal_construct_ (function, args, attr, &stack_, stack_size_bytes);
2801 template<std::
size_t N>
2804#if defined(OS_TRACE_RTOS_THREAD)
2812#pragma GCC diagnostic pop
POSIX compliant condition variable.
Base class for attributes.
Ordered list of time stamp nodes.
Base class for named system objects.
const char * name(void) const
Get object name.
Priority ordered list of threads waiting too run.
Unordered list of threads.
List of children threads.
Double linked list node, with time stamp and thread.
Double linked list node, with thread reference.
Priority ordered list of threads.
Standard allocator based on the RTOS system default memory manager.
~attributes()=default
Destruct the thread attributes object instance.
std::size_t th_stack_size_bytes
Size of the user defined storage for the thread stack, in bytes.
priority_t th_priority
Thread initial priority.
bool th_enable_assert_reuse
constexpr attributes()
Construct a thread attributes object instance.
void * th_stack_address
Address of the user defined storage for the thread stack.
attributes & operator=(const attributes &)=default
attributes(attributes &&)=default
attributes(const attributes &)=default
context()
Construct a thread context object instance.
thread::stack & stack(void)
Get the associated stack.
~context()=default
Destruct the context object instance.
void initialize(void)
Align the pointers and initialise to a known pattern.
~stack()=default
Destruct the stack object instance.
bool check_top_magic(void)
Check if top magic word is still there.
stack()
Construct a thread stack object instance.
std::size_t size(void)
Get the stack size.
os::rtos::port::stack::element_t element_t
Type of a stack element.
stack::element_t * bottom(void)
Get the stack lowest reserved address.
bool check_bottom_magic(void)
Check if bottom magic word is still there.
static std::size_t default_size(void)
Get the default stack size.
static std::size_t min_size(void)
Get the min stack size.
os::rtos::port::stack::allocation_element_t allocation_element_t
Type of a stack allocation element.
void clear(void)
Clear the stack pointer and size.
std::size_t available(void)
Compute how much available stack remains.
static const element_t magic
stack::element_t * top(void)
Get the top stack address.
void set(stack::element_t *address, std::size_t size_bytes)
Set the stack address and size.
rtos::statistics::counter_t context_switches(void)
Get the number of thread context switches.
rtos::statistics::duration_t cpu_cycles(void)
Get the thread execution time.
statistics()=default
Construct a thread attributes object instance.
void clear(void)
Clear the thread statistic counters.
~statistics()=default
Destruct the thread attributes object instance.
Template of a POSIX compliant thread with allocator.
thread_allocated(func_t function, func_args_t args, const attributes &attr=initializer, const allocator_type &allocator=allocator_type())
Construct a thread object instance.
virtual ~thread_allocated() override
Destruct the thread object instance.
Allocator allocator_type
Standard allocator type definition.
Template of a POSIX compliant thread with local stack.
thread_inclusive(func_t function, func_args_t args, const attributes &attr=initializer)
Construct a thread object instance.
virtual ~thread_inclusive() override
Destruct the thread object instance.
static const std::size_t stack_size_bytes
Local constant based on template definition.
POSIX compliant thread, using the default RTOS allocator.
result_t flags_raise(flags::mask_t mask, flags::mask_t *oflags=nullptr)
Raise thread event flags.
result_t kill(void)
Force thread termination.
virtual ~thread()
Destruct the thread object instance.
void * function_args(void) const
Get the thread function arguments.
uint8_t state_t
Type of variables holding thread states.
void *(*)(func_args_t args) func_t
Type of thread function.
os_thread_user_storage_t * user_storage(void)
Get the user storage.
void resume(void)
Resume the thread.
static const attributes initializer
Default thread initialiser.
result_t join(void **exit_ptr=nullptr)
Wait for thread termination.
priority_t priority_inherited(void)
Get the inherited scheduling priority.
bool interrupted(void)
Check if interrupted.
result_t detach(void)
Detach a thread.
result_t cancel(void)
Cancel thread execution.
bool interrupt(bool interrupt=true)
Set the interrupt flag, possibly interrupting the thread.
_func_args_t func_args_t
Type of thread function arguments.
static bool is_constructed(const thread &thread)
Check if the thread is constructed.
bool operator==(const thread &rhs) const
Compare threads.
The core of a double linked list, pointers to next, previous.
Circular double linked list of nodes.
static_double_list_links * next(void) const
int printf(const char *format,...)
Write a formatted string to the trace device.
port::clock::duration_t duration_t
Type of variables holding clock durations.
allocator_stateless_default_resource< T > allocator
Type of allocator used by the system objects. Must be stateless.
uint8_t priority_t
Type of variables holding thread priorities.
@ all
Return when all flags are set.
@ clear
Ask for flags to be cleared after read.
uint32_t mode_t
Type of variables holding flags modes.
uint32_t mask_t
Type of variables holding flags masks.
stack::element_t * switch_stacks(stack::element_t *sp)
uint64_t duration_t
Type of variables holding durations in CPU cycles.
uint64_t counter_t
Type of variables holding context switches counters.
result_t flags_timed_wait(flags::mask_t mask, clock::duration_t timeout, flags::mask_t *oflags=nullptr, flags::mode_t mode=flags::mode::all|flags::mode::clear)
Timed wait for thread event flags.
void suspend(void)
Suspend the current running thread to wait for an event.
thread & thread(void)
Get the current running thread.
void yield(void)
Yield execution to the next ready thread.
result_t flags_try_wait(flags::mask_t mask, flags::mask_t *oflags=nullptr, flags::mode_t mode=flags::mode::all|flags::mode::clear)
Try to wait for thread event flags.
void exit(void *exit_ptr=nullptr)
Terminate the current running thread.
result_t flags_clear(flags::mask_t mask, flags::mask_t *oflags=nullptr)
Clear thread event flags.
flags::mask_t flags_get(flags::mask_t mask, flags::mode_t mode=flags::mode::all|flags::mode::clear)
Get/clear thread event flags.
result_t flags_wait(flags::mask_t mask, flags::mask_t *oflags=nullptr, flags::mode_t mode=flags::mode::all|flags::mode::clear)
Wait for thread event flags.
int * __errno(void)
Implementation of the library __errno() function.
uint32_t result_t
Type of values returned by RTOS functions.
A namespace for functions applying to the current thread.
void os_rtos_idle_actions(void)
static constexpr uint32_t range
Priorities pre-scaler.
@ running
Has the CPU and runs.
@ destroyed
Terminated and resources (like stack) released.
@ initializing
Used to check reused threads.
@ terminated
No longer usable, but resources not yet released.
@ ready
Present in the READY list and competing for CPU.
@ undefined
Used to catch uninitialised threads.
@ suspended
Not present in the READY list, waiting for an event.