28#ifndef CMSIS_PLUS_RTOS_OS_THREAD_H_
29#define CMSIS_PLUS_RTOS_OS_THREAD_H_
33#if defined(__cplusplus)
41#if !defined(__ARM_EABI__)
47#pragma GCC diagnostic push
50#pragma clang diagnostic ignored "-Wc++98-compat"
51#pragma clang diagnostic ignored "-Wdocumentation-unknown-command"
63 using _func_args_t =
void*;
69#pragma GCC diagnostic push
71#pragma clang diagnostic ignored "-Wc++98-compat"
76#pragma GCC diagnostic pop
134 exit (
void* exit_ptr =
nullptr);
237#pragma GCC diagnostic push
238#pragma GCC diagnostic ignored "-Wpadded"
294 static constexpr uint32_t
range = 4;
466 operator= (
const stack&) =
delete;
468 operator= (
stack&&) =
delete;
636 std::size_t size_bytes_;
638 static std::size_t min_size_bytes_;
639 static std::size_t default_size_bytes_;
675 operator= (
const context&) =
delete;
677 operator= (
context&&) =
delete;
730#if !defined(OS_USE_RTOS_PORT_SCHEDULER)
734 friend port::stack::element_t*
762#if !defined(OS_USE_RTOS_PORT_SCHEDULER)
767 port::thread_context_t port_;
782#pragma GCC diagnostic push
783#pragma GCC diagnostic ignored "-Wpadded"
874#if defined(OS_INCLUDE_RTOS_STATISTICS_THREAD_CONTEXT_SWITCHES) \
875 || defined(OS_INCLUDE_RTOS_STATISTICS_THREAD_CPU_CYCLES)
929#if defined(OS_INCLUDE_RTOS_STATISTICS_THREAD_CONTEXT_SWITCHES)
943#if defined(OS_INCLUDE_RTOS_STATISTICS_THREAD_CPU_CYCLES)
977 rtos::scheduler::internal_switch_threads (
void);
979#if defined(OS_INCLUDE_RTOS_STATISTICS_THREAD_CONTEXT_SWITCHES)
983#if defined(OS_INCLUDE_RTOS_STATISTICS_THREAD_CPU_CYCLES)
995#pragma GCC diagnostic pop
1061 operator= (
const thread&) =
delete;
1063 operator= (
thread&&) =
delete;
1138 join (
void** exit_ptr =
nullptr);
1185 set_cancel_state (
int,
int*);
1187 set_cancel_type (
int,
int*);
1190 get_sched_param (
int*,
struct sched_param*);
1192 set_sched_param (
int,
const struct sched_param*);
1244#if defined(OS_INCLUDE_RTOS_CUSTOM_THREAD_USER_STORAGE) || defined(__DOXYGEN__)
1252 os_thread_user_storage_t*
1269#if defined(OS_INCLUDE_RTOS_THREAD_PUBLIC_FLAGS_CLEAR)
1296#if defined(OS_INCLUDE_RTOS_STATISTICS_THREAD_CONTEXT_SWITCHES) \
1297 || defined(OS_INCLUDE_RTOS_STATISTICS_THREAD_CPU_CYCLES)
1356 scheduler::internal_link_node (
1363 scheduler::internal_unlink_node (
1368 scheduler::internal_switch_threads (
void);
1376 friend port::stack::element_t*
1380 ::os_rtos_idle_actions (
void);
1422 std::size_t stack_size_bytes);
1432 internal_suspend_ (
void);
1442 internal_exit_ (
void* exit_ptr =
nullptr);
1557 internal_destroy_ (
void);
1566 internal_relink_running_ (
void);
1575 internal_check_stack_ (
void);
1602 void* func_result_ =
nullptr;
1605 thread* parent_ =
nullptr;
1616 threads_list children_
1625 thread* joiner_ =
nullptr;
1628 internal::waiting_thread_node* waiting_node_ =
nullptr;
1631 internal::timeout_thread_node* clock_node_ =
nullptr;
1636 clock* clock_ =
nullptr;
1641 const void* allocator_ =
nullptr;
1645 std::size_t allocated_stack_size_elements_ = 0;
1648 std::size_t
volatile acquired_mutexes_ = 0;
1677 bool volatile interrupted_ =
false;
1679 internal::event_flags event_flags_;
1681#if defined(OS_INCLUDE_RTOS_CUSTOM_THREAD_USER_STORAGE) || defined(__DOXYGEN__)
1682 os_thread_user_storage_t user_storage_;
1685#if defined(OS_INCLUDE_RTOS_STATISTICS_THREAD_CONTEXT_SWITCHES)
1687 class statistics statistics_;
1694#if defined(OS_USE_RTOS_PORT_SCHEDULER)
1695 friend class port::thread;
1696 os_thread_port_data_t port_;
1719 template<
typename Allocator = memory::allocator<
void*>>
1795 internal_destroy_ (
void)
override;
1814 template<std::
size_t N = port::stack::default_size_
bytes>
1881 +
sizeof(stack::allocation_element_t) - 1)
1882 /
sizeof(stack::allocation_element_t)];
1890#pragma GCC diagnostic pop
2094 __attribute__ ((always_inline))
2125 bottom_address_ =
nullptr;
2135 assert (size_bytes >= min_size_bytes_);
2136 bottom_address_ = address;
2137 size_bytes_ = size_bytes;
2146 return bottom_address_;
2155 return bottom_address_ + (size_bytes_ /
sizeof(
element_t));
2191 return min_size_bytes_;
2200 std::size_t tmp = min_size_bytes_;
2201 min_size_bytes_ = size_bytes;
2211 return default_size_bytes_;
2220 assert (size_bytes != 0);
2221 assert (size_bytes >= min_size_bytes_);
2223 std::size_t tmp = default_size_bytes_;
2224 default_size_bytes_ = size_bytes;
2250#if defined(OS_INCLUDE_RTOS_STATISTICS_THREAD_CONTEXT_SWITCHES)
2269 return context_switches_;
2274#if defined(OS_INCLUDE_RTOS_STATISTICS_THREAD_CPU_CYCLES)
2295#if defined(OS_INCLUDE_RTOS_STATISTICS_THREAD_CONTEXT_SWITCHES) \
2296 || defined(OS_INCLUDE_RTOS_STATISTICS_THREAD_CPU_CYCLES)
2312#if defined(OS_INCLUDE_RTOS_STATISTICS_THREAD_CONTEXT_SWITCHES)
2313 context_switches_ = 0;
2316#if defined(OS_INCLUDE_RTOS_STATISTICS_THREAD_CPU_CYCLES)
2336 return this == &rhs;
2363 return interrupted_;
2366#if defined(OS_INCLUDE_RTOS_CUSTOM_THREAD_USER_STORAGE) || defined(__DOXYGEN__)
2385 inline os_thread_user_storage_t*
2388 return &user_storage_;
2393#if !defined(OS_USE_RTOS_PORT_SCHEDULER)
2403 thread::internal_relink_running_ (
void)
2410 if (crt_node.
next () ==
nullptr)
2412 rtos::scheduler::ready_threads_list_.link (crt_node);
2418 if (!stack ().check_bottom_magic ())
2423 assert (stack ().check_bottom_magic ());
2437 inline class thread::stack&
2440 return context_.stack_;
2443#if defined(OS_INCLUDE_RTOS_STATISTICS_THREAD_CONTEXT_SWITCHES)
2456#if defined(OS_INCLUDE_RTOS_THREAD_PUBLIC_FLAGS_CLEAR)
2461 return internal_flags_clear_ (mask, oflags);
2509 template<
typename Allocator>
2515 {
nullptr, function, args, attr, allocator }
2561 template<
typename Allocator>
2568#if defined(OS_TRACE_RTOS_THREAD)
2569 trace::printf (
"%s @%p %s\n", __func__,
this, this->name ());
2571 if (attr.th_stack_address !=
nullptr
2572 && attr.th_stack_size_bytes > stack::min_size ())
2574 internal_construct_ (function, args, attr,
nullptr, 0);
2578 allocator_ = &allocator;
2580 if (attr.th_stack_size_bytes > stack::min_size ())
2582 allocated_stack_size_elements_ = (attr.th_stack_size_bytes
2583 +
sizeof(
typename allocator_type::value_type) - 1)
2584 /
sizeof(
typename allocator_type::value_type);
2588 allocated_stack_size_elements_ = (stack::default_size ()
2589 +
sizeof(
typename allocator_type::value_type) - 1)
2590 /
sizeof(
typename allocator_type::value_type);
2595 allocated_stack_address_ =
2596 reinterpret_cast<stack::element_t*
> ((
const_cast<allocator_type&
> (
allocator)).allocate (
2597 allocated_stack_size_elements_));
2599 assert (allocated_stack_address_ !=
nullptr);
2601 internal_construct_ (
2605 allocated_stack_address_,
2606 allocated_stack_size_elements_
2607 *
sizeof(
typename allocator_type::value_type));
2615 template<
typename Allocator>
2617 thread_allocated<Allocator>::internal_destroy_ (
void)
2619#if defined(OS_TRACE_RTOS_THREAD)
2620 trace::printf (
"thread_allocated::%s() @%p %s\n", __func__,
this,
2624 if (allocated_stack_address_ !=
nullptr)
2626 internal_check_stack_ ();
2628 typedef typename std::allocator_traits<allocator_type>::pointer pointer;
2630 static_cast<allocator_type*
> (
const_cast<void*
> (allocator_))->deallocate (
2631 reinterpret_cast<pointer
> (allocated_stack_address_),
2632 allocated_stack_size_elements_);
2634 allocated_stack_address_ =
nullptr;
2637 thread::internal_destroy_ ();
2657 template<
typename Allocator>
2660#if defined(OS_TRACE_RTOS_THREAD)
2713 template<std::
size_t N>
2718 {
nullptr, function, args, attr }
2769 template<std::
size_t N>
2776#if defined(OS_TRACE_RTOS_THREAD)
2777 trace::printf (
"%s @%p %s\n", __func__,
this, this->name ());
2779 internal_construct_ (function, args, attr, &stack_, stack_size_bytes);
2793 template<std::
size_t N>
2796#if defined(OS_TRACE_RTOS_THREAD)
2804#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.