12#ifndef CMSIS_PLUS_RTOS_OS_THREAD_H_
13#define CMSIS_PLUS_RTOS_OS_THREAD_H_
17#if defined(__cplusplus)
21#if defined(OS_USE_OS_APP_CONFIG_H)
22#include <cmsis-plus/os-app-config.h>
29#if !defined(__ARM_EABI__)
35#pragma GCC diagnostic push
37#pragma clang diagnostic ignored "-Wc++98-compat"
38#pragma clang diagnostic ignored "-Wdocumentation-unknown-command"
50 using _func_args_t =
void*;
56#pragma GCC diagnostic push
58#pragma clang diagnostic ignored "-Wc++98-compat"
63#pragma GCC diagnostic pop
121 exit (
void* exit_ptr =
nullptr);
209#pragma GCC diagnostic push
210#if defined(__clang__)
211#pragma clang diagnostic ignored "-Wreserved-identifier"
219#pragma GCC diagnostic pop
231#pragma GCC diagnostic push
232#if defined(__clang__)
233#pragma clang diagnostic ignored "-Wpadded"
234#elif defined(__GNUC__)
235#pragma GCC diagnostic ignored "-Wpadded"
244#pragma GCC diagnostic push
245#if defined(__clang__)
246#elif defined(__GNUC__)
247#pragma GCC diagnostic ignored "-Wsuggest-final-methods"
248#pragma GCC diagnostic ignored "-Wsuggest-final-types"
299 static constexpr uint32_t
range = 4;
452 = os::rtos::port::stack::allocation_element_t;
474 operator= (
const stack&)
643 std::size_t size_bytes_;
645 static std::size_t min_size_bytes_;
646 static std::size_t default_size_bytes_;
736#if !defined(OS_USE_RTOS_PORT_SCHEDULER)
740 friend port::stack::element_t*
767#if !defined(OS_USE_RTOS_PORT_SCHEDULER)
772 port::thread_context_t port_;
787#pragma GCC diagnostic push
788#if defined(__clang__)
789#pragma clang diagnostic ignored "-Wpadded"
790#elif defined(__GNUC__)
791#pragma GCC diagnostic ignored "-Wpadded"
885#if defined(OS_INCLUDE_RTOS_STATISTICS_THREAD_CONTEXT_SWITCHES) \
886 || defined(OS_INCLUDE_RTOS_STATISTICS_THREAD_CPU_CYCLES)
941#if defined(OS_INCLUDE_RTOS_STATISTICS_THREAD_CONTEXT_SWITCHES)
955#if defined(OS_INCLUDE_RTOS_STATISTICS_THREAD_CPU_CYCLES)
988 rtos::scheduler::internal_switch_threads (
void);
990#if defined(OS_INCLUDE_RTOS_STATISTICS_THREAD_CONTEXT_SWITCHES)
994#if defined(OS_INCLUDE_RTOS_STATISTICS_THREAD_CPU_CYCLES)
1006#pragma GCC diagnostic pop
1072 operator= (
const thread&)
1150 join (
void** exit_ptr =
nullptr);
1197 set_cancel_state (
int,
int*);
1199 set_cancel_type (
int,
int*);
1202 get_sched_param (
int*,
struct sched_param*);
1204 set_sched_param (
int,
const struct sched_param*);
1256#if defined(OS_INCLUDE_RTOS_CUSTOM_THREAD_USER_STORAGE) || defined(__DOXYGEN__)
1264 os_thread_user_storage_t*
1281#if defined(OS_INCLUDE_RTOS_THREAD_PUBLIC_FLAGS_CLEAR)
1308#if defined(OS_INCLUDE_RTOS_STATISTICS_THREAD_CONTEXT_SWITCHES) \
1309 || defined(OS_INCLUDE_RTOS_STATISTICS_THREAD_CPU_CYCLES)
1368 scheduler::internal_link_node (
1375 scheduler::internal_unlink_node (
1380 scheduler::internal_switch_threads (
void);
1388 friend port::stack::element_t*
1391 friend void ::os_rtos_idle_actions (
void);
1432 std::size_t stack_size_bytes);
1442 internal_suspend_ (
void);
1452 internal_exit_ (
void* exit_ptr =
nullptr);
1570 internal_destroy_ (
void);
1579 internal_relink_running_ (
void);
1588 internal_check_stack_ (
void);
1613 void* func_result_ =
nullptr;
1616 thread* parent_ =
nullptr;
1624 &thread::child_links_>;
1627 threads_list children_{
true };
1634 thread* joiner_ =
nullptr;
1637 internal::waiting_thread_node* waiting_node_ =
nullptr;
1640 internal::timeout_thread_node* clock_node_ =
nullptr;
1645 clock* clock_ =
nullptr;
1650 const void* allocator_ =
nullptr;
1654 std::size_t allocated_stack_size_elements_ = 0;
1657 std::size_t
volatile acquired_mutexes_ = 0;
1686 bool volatile interrupted_ =
false;
1688 internal::event_flags event_flags_;
1690#if defined(OS_INCLUDE_RTOS_CUSTOM_THREAD_USER_STORAGE) || defined(__DOXYGEN__)
1691 os_thread_user_storage_t user_storage_;
1694#if defined(OS_INCLUDE_RTOS_STATISTICS_THREAD_CONTEXT_SWITCHES)
1696 class statistics statistics_;
1703#if defined(OS_USE_RTOS_PORT_SCHEDULER)
1704 friend class port::thread;
1705 os_thread_port_data_t port_;
1720#pragma GCC diagnostic pop
1729 template <
typename Allocator = memory::allocator<
void*>>
1805 internal_destroy_ (
void)
override;
1823 template <std::
size_t N = port::stack::default_size_
bytes>
1888 stack::allocation_element_t
1890 /
sizeof (stack::allocation_element_t)];
1897#pragma GCC diagnostic pop
2022 mask, timeout, oflags, mode);
2105 inline int* __attribute__ ((always_inline))
2133 bottom_address_ =
nullptr;
2143 assert (size_bytes >= min_size_bytes_);
2144 bottom_address_ = address;
2145 size_bytes_ = size_bytes;
2154 return bottom_address_;
2163#pragma GCC diagnostic push
2164#if defined(__clang__)
2165#pragma clang diagnostic ignored "-Wunsafe-buffer-usage"
2167 return bottom_address_ + (size_bytes_ /
sizeof (
element_t));
2168#pragma GCC diagnostic pop
2204 return min_size_bytes_;
2213 std::size_t tmp = min_size_bytes_;
2214 min_size_bytes_ = size_bytes;
2224 return default_size_bytes_;
2233 assert (size_bytes != 0);
2234 assert (size_bytes >= min_size_bytes_);
2236 std::size_t tmp = default_size_bytes_;
2237 default_size_bytes_ = size_bytes;
2261#if defined(OS_INCLUDE_RTOS_STATISTICS_THREAD_CONTEXT_SWITCHES)
2280 return context_switches_;
2285#if defined(OS_INCLUDE_RTOS_STATISTICS_THREAD_CPU_CYCLES)
2306#if defined(OS_INCLUDE_RTOS_STATISTICS_THREAD_CONTEXT_SWITCHES) \
2307 || defined(OS_INCLUDE_RTOS_STATISTICS_THREAD_CPU_CYCLES)
2324#if defined(OS_INCLUDE_RTOS_STATISTICS_THREAD_CONTEXT_SWITCHES)
2325 context_switches_ = 0;
2328#if defined(OS_INCLUDE_RTOS_STATISTICS_THREAD_CPU_CYCLES)
2348 return this == &rhs;
2375 return interrupted_;
2378#if defined(OS_INCLUDE_RTOS_CUSTOM_THREAD_USER_STORAGE) || defined(__DOXYGEN__)
2397 inline os_thread_user_storage_t*
2400 return &user_storage_;
2405#if !defined(OS_USE_RTOS_PORT_SCHEDULER)
2415 thread::internal_relink_running_ (
void)
2422 if (crt_node.
next () ==
nullptr)
2424 rtos::scheduler::ready_threads_list_.link (crt_node);
2430 if (!stack ().check_bottom_magic ())
2435 assert (stack ().check_bottom_magic ());
2450 inline class thread::stack&
2453 return context_.stack_;
2456#if defined(OS_INCLUDE_RTOS_STATISTICS_THREAD_CONTEXT_SWITCHES)
2469#if defined(OS_INCLUDE_RTOS_THREAD_PUBLIC_FLAGS_CLEAR)
2474 return internal_flags_clear_ (mask, oflags);
2525 template <
typename Allocator>
2577 template <
typename Allocator>
2583#if defined(OS_TRACE_RTOS_THREAD)
2584 trace::printf (
"%s @%p %s\n", __func__,
this, this->name ());
2589 internal_construct_ (function, args, attr,
nullptr, 0);
2593 allocator_ = &allocator;
2597 allocated_stack_size_elements_
2599 +
sizeof (
typename allocator_type::value_type) - 1)
2600 /
sizeof (
typename allocator_type::value_type);
2604 allocated_stack_size_elements_
2605 = (stack::default_size ()
2606 +
sizeof (
typename allocator_type::value_type) - 1)
2607 /
sizeof (
typename allocator_type::value_type);
2612 allocated_stack_address_ =
reinterpret_cast<stack::element_t*
> (
2614 .allocate (allocated_stack_size_elements_));
2616 assert (allocated_stack_address_ !=
nullptr);
2618 internal_construct_ (
2619 function, args, attr, allocated_stack_address_,
2620 allocated_stack_size_elements_
2621 *
sizeof (
typename allocator_type::value_type));
2629 template <
typename Allocator>
2633#if defined(OS_TRACE_RTOS_THREAD)
2634 trace::printf (
"thread_allocated::%s() @%p %s\n", __func__,
this,
2638 if (allocated_stack_address_ !=
nullptr)
2640 internal_check_stack_ ();
2643 typename std::allocator_traits<allocator_type>::pointer pointer;
2645#pragma GCC diagnostic push
2646#pragma GCC diagnostic ignored "-Wcast-align"
2647 static_cast<allocator_type*
> (
const_cast<void*
> (allocator_))
2649 reinterpret_cast<pointer
> (allocated_stack_address_),
2650 allocated_stack_size_elements_);
2651#pragma GCC diagnostic pop
2653 allocated_stack_address_ =
nullptr;
2656 thread::internal_destroy_ ();
2676 template <
typename Allocator>
2679#if defined(OS_TRACE_RTOS_THREAD)
2735 template <std::
size_t N>
2792 template <std::
size_t N>
2798#if defined(OS_TRACE_RTOS_THREAD)
2799 trace::printf (
"%s @%p %s\n", __func__,
this, this->name ());
2815 template <std::
size_t N>
2818#if defined(OS_TRACE_RTOS_THREAD)
2826#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.
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.
void *(*)(func_args_t args) func_t
Type of thread function.
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.
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.