2013-11-27 16:28:31 +01:00
|
|
|
/*
|
2014-04-01 11:46:21 +02:00
|
|
|
* Copyright (C) 2014 Freie Universität Berlin
|
2013-11-27 16:28:31 +01:00
|
|
|
*
|
2014-08-23 15:43:13 +02:00
|
|
|
* This file is subject to the terms and conditions of the GNU Lesser
|
|
|
|
* General Public License v2.1. See the file LICENSE in the top level
|
|
|
|
* directory for more details.
|
2010-09-22 15:10:42 +02:00
|
|
|
*/
|
|
|
|
|
|
|
|
/**
|
2013-11-27 16:28:31 +01:00
|
|
|
* @defgroup core_thread Threading
|
|
|
|
* @ingroup core
|
|
|
|
* @brief Support for multi-threading
|
2014-10-19 23:05:36 +02:00
|
|
|
*
|
2016-10-11 09:01:16 +02:00
|
|
|
* Priorities
|
|
|
|
* ==========
|
|
|
|
*
|
|
|
|
* As RIOT is using a fixed priority @ref core_sched "scheduling algorithm",
|
|
|
|
* threads are scheduled based on their priority. The priority is fixed for
|
|
|
|
* every thread and specified during the thread's creation by the `priority`
|
|
|
|
* parameter.
|
|
|
|
*
|
|
|
|
* The lower the priority value, the higher the priority of the thread,
|
|
|
|
* with 0 being the highest possible priority.
|
|
|
|
*
|
|
|
|
* The lowest possible priority is @ref THREAD_PRIORITY_IDLE - 1.
|
|
|
|
*
|
|
|
|
* @note Assigning the same priority to two or more threads is usually not a
|
|
|
|
* good idea. A thread in RIOT may run until it yields (@ref
|
|
|
|
* thread_yield) or another thread with higher priority is runnable (@ref
|
|
|
|
* STATUS_ON_RUNQUEUE) again. Multiple threads with the same priority
|
|
|
|
* will therefore be scheduled cooperatively: when one of them is running,
|
|
|
|
* all others with the same priority depend on it to yield (or be interrupted
|
|
|
|
* by a thread with higher priority).
|
|
|
|
* This may make it difficult to determine when which of them gets
|
|
|
|
* scheduled and how much CPU time they will get. In most applications,
|
|
|
|
* the number of threads in application is significantly smaller than the
|
|
|
|
* number of available priorities, so assigning distinct priorities per
|
|
|
|
* thread should not be a problem. Only assign the same priority to
|
|
|
|
* multiple threads if you know what you are doing!
|
|
|
|
*
|
|
|
|
* Thread Behavior
|
|
|
|
* ===============
|
|
|
|
* In addition to the priority, flags can be used when creating a thread to
|
|
|
|
* alter the thread's behavior after creation. The following flags are available:
|
|
|
|
*
|
2024-07-18 16:42:52 +02:00
|
|
|
* Flags | Description
|
|
|
|
* ------------------------------ | --------------------------------------------------
|
|
|
|
* @ref THREAD_CREATE_SLEEPING | the thread will sleep until woken up manually
|
|
|
|
* @ref THREAD_CREATE_WOUT_YIELD | the thread might not run immediately after creation
|
|
|
|
* @ref THREAD_CREATE_NO_STACKTEST| never measure the stack's memory usage
|
2016-10-11 09:01:16 +02:00
|
|
|
*
|
|
|
|
* Thread creation
|
|
|
|
* ===============
|
|
|
|
* Creating a new thread is internally done in two steps:
|
|
|
|
* 1. the new thread's stack is initialized depending on the platform
|
|
|
|
* 2. the new thread is added to the scheduler and the scheduler is run (if not
|
|
|
|
* indicated otherwise)
|
|
|
|
*
|
|
|
|
* @note Creating threads from within an ISR is currently supported, however it
|
|
|
|
* is considered to be a bad programming practice and we strongly
|
|
|
|
* discourage you from doing so.
|
|
|
|
*
|
|
|
|
* Usage
|
|
|
|
* -----
|
|
|
|
* ~~~~~~~~~~~~~~~~~~~~~~~~ {.c}
|
2017-05-30 16:13:43 +02:00
|
|
|
* #include "thread.h"
|
|
|
|
*
|
2016-10-11 09:01:16 +02:00
|
|
|
* char rcv_thread_stack[THREAD_STACKSIZE_MAIN];
|
|
|
|
*
|
|
|
|
* void *rcv_thread(void *arg)
|
|
|
|
* {
|
2017-05-30 16:13:43 +02:00
|
|
|
* (void) arg;
|
2016-10-11 09:01:16 +02:00
|
|
|
* msg_t m;
|
|
|
|
*
|
|
|
|
* while (1) {
|
|
|
|
* msg_receive(&m);
|
|
|
|
* printf("Got msg from %" PRIkernel_pid "\n", m.sender_pid);
|
|
|
|
* }
|
|
|
|
*
|
|
|
|
* return NULL;
|
|
|
|
* }
|
|
|
|
*
|
|
|
|
* int main(void)
|
|
|
|
* {
|
|
|
|
* thread_create(rcv_thread_stack, sizeof(rcv_thread_stack),
|
2024-03-07 15:43:01 +01:00
|
|
|
* THREAD_PRIORITY_MAIN - 1, 0,
|
2016-10-11 09:01:16 +02:00
|
|
|
* rcv_thread, NULL, "rcv_thread");
|
|
|
|
* }
|
|
|
|
* ~~~~~~~~~~~~~~~~~~~~~~~~
|
|
|
|
*
|
|
|
|
* Reading from the top down, you can see that first, stack memory for our thread
|
|
|
|
* `rcv_thread` is preallocated, followed by an implementation of the thread's
|
2017-01-15 12:04:43 +01:00
|
|
|
* function. Communication between threads is done using @ref core_msg. In this
|
2016-10-11 09:01:16 +02:00
|
|
|
* case, `rcv_thread` will print the process id of each thread that sent a
|
|
|
|
* message to `rcv_thread`.
|
|
|
|
*
|
|
|
|
* After it has been properly defined, `rcv_thread` is created with a call to
|
|
|
|
* @ref thread_create() in `main()`. It is assigned a priority of
|
|
|
|
* `THREAD_PRIORITY_MAIN - 1`, i.e. a slightly *higher* priority than the main
|
|
|
|
* thread. Since neither the `THREAD_CREATE_SLEEPING` nor the
|
|
|
|
* `THREAD_CREATE_WOUT_YIELD` flag is set, `rcv_thread` will be executed
|
|
|
|
* immediately.
|
|
|
|
*
|
|
|
|
* @note If the messages to the thread are sent using @ref msg_try_send() or
|
|
|
|
* from an ISR, activate your thread's message queue by calling
|
|
|
|
* @ref msg_init_queue() to prevent messages from being dropped when
|
|
|
|
* they can't be handled right away. The same applies if you'd like
|
|
|
|
* msg_send() to your thread to be non-blocking. For more details, see
|
|
|
|
* @ref core_msg "the Messaging documentation".
|
|
|
|
*
|
2013-11-27 16:28:31 +01:00
|
|
|
* @{
|
|
|
|
*
|
2015-05-22 07:34:41 +02:00
|
|
|
* @file
|
2013-11-27 16:28:31 +01:00
|
|
|
* @brief Threading API
|
|
|
|
*
|
2010-09-22 15:10:42 +02:00
|
|
|
* @author Kaspar Schleiser <kaspar@schleiser.de>
|
|
|
|
*/
|
|
|
|
|
2015-03-26 17:07:04 +01:00
|
|
|
#ifndef THREAD_H
|
|
|
|
#define THREAD_H
|
2013-11-27 16:28:31 +01:00
|
|
|
|
2016-01-04 22:29:34 +01:00
|
|
|
#include "clist.h"
|
|
|
|
#include "cib.h"
|
|
|
|
#include "msg.h"
|
2016-02-27 01:12:02 +01:00
|
|
|
#include "sched.h"
|
2020-11-26 15:15:02 +01:00
|
|
|
#include "thread_config.h"
|
2010-09-30 15:08:50 +02:00
|
|
|
|
2016-02-24 23:21:56 +01:00
|
|
|
#ifdef MODULE_CORE_THREAD_FLAGS
|
|
|
|
#include "thread_flags.h"
|
|
|
|
#endif
|
|
|
|
|
2024-04-14 14:26:05 +02:00
|
|
|
#include "thread_arch.h" /* IWYU pragma: export */
|
2021-01-18 17:07:09 +01:00
|
|
|
|
2014-10-13 14:44:28 +02:00
|
|
|
#ifdef __cplusplus
|
2020-03-30 17:02:08 +02:00
|
|
|
extern "C" {
|
2014-10-13 14:44:28 +02:00
|
|
|
#endif
|
|
|
|
|
2021-01-18 17:07:09 +01:00
|
|
|
/**
|
|
|
|
* @brief Macro definition to inline some of the platform specific
|
|
|
|
* implementations
|
|
|
|
*
|
|
|
|
* Should be enabled when advantageous by CPU's in their thread_arch.h header
|
|
|
|
*/
|
|
|
|
#ifdef THREAD_API_INLINED
|
|
|
|
#define THREAD_MAYBE_INLINE static inline __attribute__((always_inline))
|
|
|
|
#else
|
|
|
|
#define THREAD_MAYBE_INLINE
|
|
|
|
#endif /* THREAD_API_INLINED */
|
|
|
|
|
2019-11-24 16:19:48 +01:00
|
|
|
#if defined(DEVELHELP) && !defined(CONFIG_THREAD_NAMES)
|
|
|
|
/**
|
|
|
|
* @brief This global macro enable storage of thread names to help developers.
|
|
|
|
*
|
|
|
|
* To activate it set environment variable `THREAD_NAMES=1`, or use Kconfig.
|
|
|
|
* It is automatically enabled if `DEVELHELP` is.
|
|
|
|
*/
|
|
|
|
#define CONFIG_THREAD_NAMES
|
|
|
|
#endif
|
|
|
|
|
2017-10-20 17:03:46 +02:00
|
|
|
/**
|
|
|
|
* @brief Prototype for a thread entry function
|
|
|
|
*/
|
|
|
|
typedef void *(*thread_task_func_t)(void *arg);
|
|
|
|
|
2016-01-04 22:29:34 +01:00
|
|
|
/**
|
|
|
|
* @brief @c thread_t holds thread's context data.
|
|
|
|
*/
|
|
|
|
struct _thread {
|
|
|
|
char *sp; /**< thread's stack pointer */
|
2019-05-11 12:25:07 +02:00
|
|
|
thread_status_t status; /**< thread's status */
|
2016-02-29 01:37:26 +01:00
|
|
|
uint8_t priority; /**< thread's priority */
|
2016-01-04 22:29:34 +01:00
|
|
|
|
|
|
|
kernel_pid_t pid; /**< thread's process id */
|
|
|
|
|
2017-03-05 16:25:09 +01:00
|
|
|
#if defined(MODULE_CORE_THREAD_FLAGS) || defined(DOXYGEN)
|
2016-02-24 23:21:56 +01:00
|
|
|
thread_flags_t flags; /**< currently set flags */
|
|
|
|
#endif
|
|
|
|
|
2016-01-04 22:29:34 +01:00
|
|
|
clist_node_t rq_entry; /**< run queue entry */
|
|
|
|
|
2015-12-30 15:39:43 +01:00
|
|
|
#if defined(MODULE_CORE_MSG) || defined(MODULE_CORE_THREAD_FLAGS) \
|
2017-03-05 16:25:09 +01:00
|
|
|
|| defined(MODULE_CORE_MBOX) || defined(DOXYGEN)
|
2015-12-30 15:39:43 +01:00
|
|
|
void *wait_data; /**< used by msg, mbox and thread
|
|
|
|
flags */
|
2016-02-26 22:19:31 +01:00
|
|
|
#endif
|
2017-03-05 16:25:09 +01:00
|
|
|
#if defined(MODULE_CORE_MSG) || defined(DOXYGEN)
|
|
|
|
list_node_t msg_waiters; /**< threads waiting for their message
|
|
|
|
to be delivered to this thread
|
|
|
|
(i.e. all blocked sends) */
|
|
|
|
cib_t msg_queue; /**< index of this [thread's message queue]
|
|
|
|
(thread_t::msg_array), if any */
|
|
|
|
msg_t *msg_array; /**< memory holding messages sent
|
|
|
|
to this thread's message queue */
|
2016-02-26 22:19:31 +01:00
|
|
|
#endif
|
2021-11-03 21:38:22 +01:00
|
|
|
#if defined(DEVELHELP) || IS_ACTIVE(SCHED_TEST_STACK) \
|
2017-03-05 16:25:09 +01:00
|
|
|
|| defined(MODULE_MPU_STACK_GUARD) || defined(DOXYGEN)
|
2016-01-04 22:29:34 +01:00
|
|
|
char *stack_start; /**< thread's stack start address */
|
|
|
|
#endif
|
2019-11-24 16:19:48 +01:00
|
|
|
#if defined(CONFIG_THREAD_NAMES) || defined(DOXYGEN)
|
2016-01-04 22:29:34 +01:00
|
|
|
const char *name; /**< thread's name */
|
2019-11-24 16:19:48 +01:00
|
|
|
#endif
|
|
|
|
#if defined(DEVELHELP) || defined(DOXYGEN)
|
2016-01-04 22:29:34 +01:00
|
|
|
int stack_size; /**< thread's stack size */
|
|
|
|
#endif
|
2020-07-02 08:29:49 +02:00
|
|
|
/* enable TLS only when Picolibc is compiled with TLS enabled */
|
|
|
|
#ifdef PICOLIBC_TLS
|
|
|
|
void *tls; /**< thread local storage ptr */
|
|
|
|
#endif
|
2018-07-05 09:22:38 +02:00
|
|
|
};
|
2014-02-17 12:28:54 +01:00
|
|
|
|
2015-12-02 11:35:34 +01:00
|
|
|
/**
|
|
|
|
* @name Optional flags for controlling a threads initial state
|
|
|
|
* @{
|
|
|
|
*/
|
|
|
|
/**
|
2016-10-11 09:01:16 +02:00
|
|
|
* @brief Set the new thread to sleeping. It must be woken up manually.
|
2015-12-02 11:35:34 +01:00
|
|
|
**/
|
2015-12-02 11:36:48 +01:00
|
|
|
#define THREAD_CREATE_SLEEPING (1)
|
2015-12-02 11:35:34 +01:00
|
|
|
|
|
|
|
/**
|
|
|
|
* @brief Currently not implemented
|
|
|
|
*/
|
2015-12-02 11:36:48 +01:00
|
|
|
#define THREAD_AUTO_FREE (2)
|
2015-12-02 11:35:34 +01:00
|
|
|
|
|
|
|
/**
|
2016-10-11 09:01:16 +02:00
|
|
|
* @brief Do not automatically call thread_yield() after creation: the newly
|
|
|
|
* created thread might not run immediately. Purely for optimization.
|
|
|
|
* Any other context switch (i.e. an interrupt) can still start the
|
|
|
|
* thread at any time!
|
2015-12-02 11:35:34 +01:00
|
|
|
*/
|
2015-12-02 11:36:48 +01:00
|
|
|
#define THREAD_CREATE_WOUT_YIELD (4)
|
2015-12-02 11:35:34 +01:00
|
|
|
|
2024-07-18 16:42:52 +02:00
|
|
|
/**
|
|
|
|
* @brief Never write markers into the thread's stack to measure stack usage
|
|
|
|
*
|
|
|
|
* This flag is ignored when DEVELHELP or SCHED_TEST_STACK is not enabled
|
|
|
|
*/
|
|
|
|
#define THREAD_CREATE_NO_STACKTEST (8)
|
|
|
|
|
2020-03-30 17:02:08 +02:00
|
|
|
/**
|
2024-03-07 15:43:01 +01:00
|
|
|
* @brief Legacy flag kept for compatibility.
|
|
|
|
*
|
|
|
|
* @deprecated will be removed after 2025.07 release
|
|
|
|
*
|
|
|
|
* This is always enabled with `DEVELHELP=1` or `SCHED_TEST_STACK`.
|
2020-03-30 17:02:08 +02:00
|
|
|
*/
|
2024-03-07 15:43:01 +01:00
|
|
|
#define THREAD_CREATE_STACKTEST (0)
|
2015-12-02 11:35:34 +01:00
|
|
|
/** @} */
|
|
|
|
|
2010-09-22 15:10:42 +02:00
|
|
|
/**
|
2016-10-11 09:01:16 +02:00
|
|
|
* @brief Creates a new thread.
|
2010-09-22 15:10:42 +02:00
|
|
|
*
|
2016-10-11 09:01:16 +02:00
|
|
|
* For an in-depth discussion of thread priorities, behavior and and flags,
|
|
|
|
* see @ref core_thread.
|
2014-04-01 11:46:21 +02:00
|
|
|
*
|
2016-10-11 09:01:16 +02:00
|
|
|
* @note Avoid assigning the same priority to two or more threads.
|
|
|
|
* @note Creating threads from within an ISR is currently supported, however it
|
|
|
|
* is considered to be a bad programming practice and we strongly
|
|
|
|
* discourage you from doing so.
|
2015-03-12 22:31:33 +01:00
|
|
|
*
|
2014-04-01 11:46:21 +02:00
|
|
|
* @param[out] stack start address of the preallocated stack memory
|
|
|
|
* @param[in] stacksize the size of the thread's stack in bytes
|
|
|
|
* @param[in] priority priority of the new thread, lower mean higher priority
|
|
|
|
* @param[in] flags optional flags for the creation of the new thread
|
2014-11-30 22:34:50 +01:00
|
|
|
* @param[in] task_func pointer to the code that is executed in the new thread
|
2014-03-04 20:20:01 +01:00
|
|
|
* @param[in] arg the argument to the function
|
2014-04-01 11:46:21 +02:00
|
|
|
* @param[in] name a human readable descriptor for the thread
|
|
|
|
*
|
2015-02-13 16:47:19 +01:00
|
|
|
* @return PID of newly created task on success
|
|
|
|
* @return -EINVAL, if @p priority is greater than or equal to
|
|
|
|
* @ref SCHED_PRIO_LEVELS
|
|
|
|
* @return -EOVERFLOW, if there are too many threads running already
|
2020-03-30 17:02:08 +02:00
|
|
|
*/
|
2014-07-06 22:57:56 +02:00
|
|
|
kernel_pid_t thread_create(char *stack,
|
2020-03-30 17:02:08 +02:00
|
|
|
int stacksize,
|
|
|
|
uint8_t priority,
|
|
|
|
int flags,
|
|
|
|
thread_task_func_t task_func,
|
|
|
|
void *arg,
|
|
|
|
const char *name);
|
2014-08-13 09:26:27 +02:00
|
|
|
|
2020-08-05 22:09:38 +02:00
|
|
|
/**
|
|
|
|
* @brief Retrieve a thread control block by PID.
|
|
|
|
* @pre @p pid is valid
|
|
|
|
* @param[in] pid Thread to retrieve.
|
|
|
|
* @return `NULL` if the PID is invalid or there is no such thread.
|
|
|
|
*/
|
|
|
|
static inline thread_t *thread_get_unchecked(kernel_pid_t pid)
|
|
|
|
{
|
|
|
|
return (thread_t *)sched_threads[pid];
|
|
|
|
}
|
|
|
|
|
2014-08-13 09:26:27 +02:00
|
|
|
/**
|
2019-09-14 15:47:10 +02:00
|
|
|
* @brief Retrieve a thread control block by PID.
|
2014-08-13 09:26:27 +02:00
|
|
|
* @details This is a bound-checked variant of accessing `sched_threads[pid]` directly.
|
|
|
|
* If you know that the PID is valid, then don't use this function.
|
2019-09-14 15:47:10 +02:00
|
|
|
* @param[in] pid Thread to retrieve.
|
2014-08-13 09:26:27 +02:00
|
|
|
* @return `NULL` if the PID is invalid or there is no such thread.
|
|
|
|
*/
|
2020-08-05 22:09:38 +02:00
|
|
|
static inline thread_t *thread_get(kernel_pid_t pid)
|
2020-08-05 10:51:16 +02:00
|
|
|
{
|
|
|
|
if (pid_is_valid(pid)) {
|
2020-08-05 22:09:38 +02:00
|
|
|
return thread_get_unchecked(pid);
|
2020-08-05 10:51:16 +02:00
|
|
|
}
|
|
|
|
return NULL;
|
|
|
|
}
|
2014-08-13 09:26:27 +02:00
|
|
|
|
2010-09-22 15:10:42 +02:00
|
|
|
/**
|
2014-04-01 11:46:21 +02:00
|
|
|
* @brief Returns the status of a process
|
|
|
|
*
|
|
|
|
* @param[in] pid the PID of the thread to get the status from
|
|
|
|
*
|
|
|
|
* @return status of the thread
|
|
|
|
* @return `STATUS_NOT_FOUND` if pid is unknown
|
2010-09-22 15:10:42 +02:00
|
|
|
*/
|
2019-10-15 15:48:27 +02:00
|
|
|
thread_status_t thread_getstatus(kernel_pid_t pid);
|
2010-09-22 15:10:42 +02:00
|
|
|
|
|
|
|
/**
|
2014-04-01 11:46:21 +02:00
|
|
|
* @brief Puts the current thread into sleep mode. Has to be woken up externally.
|
2010-09-22 15:10:42 +02:00
|
|
|
*/
|
2013-02-06 13:20:21 +01:00
|
|
|
void thread_sleep(void);
|
2010-09-22 15:10:42 +02:00
|
|
|
|
2013-12-18 17:34:42 +01:00
|
|
|
/**
|
2014-10-18 01:24:49 +02:00
|
|
|
* @brief Lets current thread yield.
|
2014-04-01 11:46:21 +02:00
|
|
|
*
|
2014-10-18 01:24:49 +02:00
|
|
|
* @details The current thread will resume operation immediately,
|
|
|
|
* if there is no other ready thread with the same or a higher priority.
|
|
|
|
*
|
|
|
|
* Differently from thread_yield_higher() the current thread will be put to the
|
2016-10-11 09:01:16 +02:00
|
|
|
* end of the thread's in its priority class.
|
2014-10-18 01:24:49 +02:00
|
|
|
*
|
|
|
|
* @see thread_yield_higher()
|
2013-12-18 17:34:42 +01:00
|
|
|
*/
|
2021-12-10 15:43:51 +01:00
|
|
|
#if defined(MODULE_CORE_THREAD) || DOXYGEN
|
2013-12-18 17:34:42 +01:00
|
|
|
void thread_yield(void);
|
2021-12-10 15:43:51 +01:00
|
|
|
#else
|
|
|
|
static inline void thread_yield(void)
|
|
|
|
{
|
|
|
|
/* NO-OP */
|
|
|
|
}
|
|
|
|
#endif
|
2013-12-18 17:34:42 +01:00
|
|
|
|
2014-10-28 00:49:02 +01:00
|
|
|
/**
|
|
|
|
* @brief Lets current thread yield in favor of a higher prioritized thread.
|
|
|
|
*
|
|
|
|
* @details The current thread will resume operation immediately,
|
|
|
|
* if there is no other ready thread with a higher priority.
|
|
|
|
*
|
|
|
|
* Differently from thread_yield() the current thread will be scheduled next
|
|
|
|
* in its own priority class, i.e. it stays the first thread in its
|
|
|
|
* priority class.
|
|
|
|
*
|
|
|
|
* @see thread_yield()
|
|
|
|
*/
|
2021-01-18 17:07:09 +01:00
|
|
|
THREAD_MAYBE_INLINE void thread_yield_higher(void);
|
2014-10-28 00:49:02 +01:00
|
|
|
|
2019-10-11 17:49:51 +02:00
|
|
|
/**
|
|
|
|
* @brief Puts the current thread into zombie state.
|
|
|
|
*
|
|
|
|
* @details Does nothing when in ISR.
|
|
|
|
* A thread in zombie state will never be scheduled again,
|
|
|
|
* but its scheduler entry and stack will be kept.
|
|
|
|
* A zombie state thread is supposed to be cleaned up
|
|
|
|
* by @ref thread_kill_zombie().
|
|
|
|
*/
|
|
|
|
void thread_zombify(void);
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @brief Terminates zombie thread.
|
|
|
|
*
|
|
|
|
* @param[in] pid the PID of the thread to terminate
|
|
|
|
*
|
|
|
|
* @return `1` on success
|
|
|
|
* @return `STATUS_NOT_FOUND` if pid is unknown or not a zombie
|
|
|
|
*/
|
|
|
|
int thread_kill_zombie(kernel_pid_t pid);
|
|
|
|
|
2010-09-22 15:10:42 +02:00
|
|
|
/**
|
2014-04-01 11:46:21 +02:00
|
|
|
* @brief Wakes up a sleeping thread.
|
|
|
|
*
|
|
|
|
* @param[in] pid the PID of the thread to be woken up
|
|
|
|
*
|
|
|
|
* @return `1` on success
|
|
|
|
* @return `STATUS_NOT_FOUND` if pid is unknown or not sleeping
|
2010-09-22 15:10:42 +02:00
|
|
|
*/
|
2014-07-06 22:57:56 +02:00
|
|
|
int thread_wakeup(kernel_pid_t pid);
|
2010-09-22 15:10:42 +02:00
|
|
|
|
|
|
|
/**
|
2014-04-01 11:46:21 +02:00
|
|
|
* @brief Returns the process ID of the currently running thread
|
|
|
|
*
|
|
|
|
* @return obviously you are not a golfer.
|
2010-09-22 15:10:42 +02:00
|
|
|
*/
|
2014-08-13 09:13:32 +02:00
|
|
|
static inline kernel_pid_t thread_getpid(void)
|
|
|
|
{
|
2016-01-04 22:29:34 +01:00
|
|
|
extern volatile kernel_pid_t sched_active_pid;
|
2020-03-30 17:02:08 +02:00
|
|
|
|
2014-08-13 09:13:32 +02:00
|
|
|
return sched_active_pid;
|
|
|
|
}
|
2010-09-22 15:10:42 +02:00
|
|
|
|
2020-08-05 22:09:38 +02:00
|
|
|
/**
|
|
|
|
* @brief Returns a pointer to the Thread Control Block of the currently
|
|
|
|
* running thread
|
|
|
|
*
|
|
|
|
* @return Pointer to the TCB of the currently running thread, or `NULL` if
|
|
|
|
* no thread is running
|
|
|
|
*/
|
|
|
|
static inline thread_t *thread_get_active(void)
|
|
|
|
{
|
|
|
|
extern volatile thread_t *sched_active_thread;
|
|
|
|
|
|
|
|
return (thread_t *)sched_active_thread;
|
|
|
|
}
|
|
|
|
|
2016-02-27 01:12:02 +01:00
|
|
|
/**
|
|
|
|
* @brief Gets called upon thread creation to set CPU registers
|
|
|
|
*
|
|
|
|
* @param[in] task_func First function to call within the thread
|
|
|
|
* @param[in] arg Argument to supply to task_func
|
|
|
|
* @param[in] stack_start Start address of the stack
|
|
|
|
* @param[in] stack_size Stack size
|
|
|
|
*
|
|
|
|
* @return stack pointer
|
|
|
|
*/
|
2020-03-30 17:02:08 +02:00
|
|
|
char *thread_stack_init(thread_task_func_t task_func, void *arg,
|
|
|
|
void *stack_start, int stack_size);
|
2016-02-27 01:12:02 +01:00
|
|
|
|
2015-01-17 15:17:19 +01:00
|
|
|
/**
|
|
|
|
* @brief Add thread to list, sorted by priority (internal)
|
|
|
|
*
|
|
|
|
* This will add @p thread to @p list sorted by the thread priority.
|
|
|
|
* It reuses the thread's rq_entry field.
|
|
|
|
* Used internally by msg and mutex implementations.
|
|
|
|
*
|
|
|
|
* @note Only use for threads *not on any runqueue* and with interrupts
|
|
|
|
* disabled.
|
|
|
|
*
|
|
|
|
* @param[in] list ptr to list root node
|
|
|
|
* @param[in] thread thread to add
|
|
|
|
*/
|
|
|
|
void thread_add_to_list(list_node_t *list, thread_t *thread);
|
|
|
|
|
2014-10-15 00:04:58 +02:00
|
|
|
/**
|
|
|
|
* @brief Returns the name of a process
|
|
|
|
*
|
2017-10-20 23:10:20 +02:00
|
|
|
* @note when compiling without DEVELHELP, this *always* returns NULL!
|
|
|
|
*
|
2014-10-15 00:04:58 +02:00
|
|
|
* @param[in] pid the PID of the thread to get the name from
|
|
|
|
*
|
|
|
|
* @return the threads name
|
|
|
|
* @return `NULL` if pid is unknown
|
|
|
|
*/
|
2021-12-10 15:43:51 +01:00
|
|
|
#if defined(MODULE_CORE_THREAD) || DOXYGEN
|
2014-10-15 00:04:58 +02:00
|
|
|
const char *thread_getname(kernel_pid_t pid);
|
2021-12-10 15:43:51 +01:00
|
|
|
#else
|
|
|
|
static inline const char *thread_getname(kernel_pid_t pid)
|
|
|
|
{
|
|
|
|
(void)pid;
|
|
|
|
return "(none)";
|
|
|
|
}
|
|
|
|
#endif
|
2014-10-15 00:04:58 +02:00
|
|
|
|
2010-09-22 15:10:42 +02:00
|
|
|
/**
|
2024-05-31 10:59:14 +02:00
|
|
|
* @brief Measures the stack usage of a stack
|
|
|
|
* @internal Should not be used externally
|
2014-04-01 11:46:21 +02:00
|
|
|
*
|
2024-05-31 10:59:14 +02:00
|
|
|
* Only works if the stack is filled with canaries
|
|
|
|
* (`*((uintptr_t *)ptr) == (uintptr_t)ptr` for naturally aligned `ptr` within
|
|
|
|
* the stack).
|
2024-03-07 15:43:01 +01:00
|
|
|
* This is enabled if `DEVELHELP` or `SCHED_TEST_STACK` is set.
|
2010-09-22 15:10:42 +02:00
|
|
|
*
|
2024-05-31 10:59:14 +02:00
|
|
|
* @param[in] stack the stack you want to measure. Try
|
|
|
|
* `thread_get_stackstart(thread_get_active())`
|
|
|
|
* @param[in] size size of @p stack in bytes
|
2014-04-01 11:46:21 +02:00
|
|
|
*
|
2024-05-31 10:59:14 +02:00
|
|
|
* @return the amount of unused space of the thread's stack
|
2010-09-22 15:10:42 +02:00
|
|
|
*/
|
2024-05-31 10:59:14 +02:00
|
|
|
uintptr_t measure_stack_free_internal(const char *stack, size_t size);
|
2016-02-27 01:12:02 +01:00
|
|
|
|
2017-10-20 17:03:46 +02:00
|
|
|
/**
|
|
|
|
* @brief Get the number of bytes used on the ISR stack
|
|
|
|
*/
|
|
|
|
int thread_isr_stack_usage(void);
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @brief Get the current ISR stack pointer
|
|
|
|
*/
|
|
|
|
void *thread_isr_stack_pointer(void);
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @brief Get the start of the ISR stack
|
|
|
|
*/
|
|
|
|
void *thread_isr_stack_start(void);
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @brief Print the current stack to stdout
|
|
|
|
*/
|
|
|
|
void thread_stack_print(void);
|
|
|
|
|
2016-02-27 01:12:02 +01:00
|
|
|
/**
|
|
|
|
* @brief Prints human readable, ps-like thread information for debugging purposes
|
|
|
|
*/
|
|
|
|
void thread_print_stack(void);
|
2010-09-22 15:10:42 +02:00
|
|
|
|
2018-11-15 13:53:27 +01:00
|
|
|
/**
|
|
|
|
* @brief Checks if a thread has an initialized message queue
|
|
|
|
*
|
|
|
|
* @see @ref msg_init_queue()
|
|
|
|
*
|
|
|
|
* @param[in] thread The thread to check for
|
|
|
|
*
|
|
|
|
* @return `== 0`, if @p thread has no initialized message queue
|
|
|
|
* @return `!= 0`, if @p thread has its message queue initialized
|
|
|
|
*/
|
|
|
|
static inline int thread_has_msg_queue(const volatile struct _thread *thread)
|
|
|
|
{
|
|
|
|
#if defined(MODULE_CORE_MSG) || defined(DOXYGEN)
|
|
|
|
return (thread->msg_array != NULL);
|
|
|
|
#else
|
|
|
|
(void)thread;
|
|
|
|
return 0;
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
2020-11-25 14:39:22 +01:00
|
|
|
/**
|
|
|
|
* Get a thread's status
|
|
|
|
*
|
|
|
|
* @param thread thread to work on
|
|
|
|
* @returns status of thread
|
|
|
|
*/
|
2021-01-19 10:28:31 +01:00
|
|
|
static inline thread_status_t thread_get_status(const thread_t *thread)
|
|
|
|
{
|
2020-11-25 14:39:22 +01:00
|
|
|
return thread->status;
|
|
|
|
}
|
|
|
|
|
2021-09-06 13:22:22 +02:00
|
|
|
/**
|
|
|
|
* Get a thread's priority
|
|
|
|
*
|
|
|
|
* @param thread thread to work on
|
|
|
|
* @returns priority of thread
|
|
|
|
*/
|
2021-11-03 21:50:28 +01:00
|
|
|
static inline uint8_t thread_get_priority(const thread_t *thread)
|
2021-09-06 13:22:22 +02:00
|
|
|
{
|
|
|
|
return thread->priority;
|
|
|
|
}
|
|
|
|
|
2020-11-25 14:46:43 +01:00
|
|
|
/**
|
|
|
|
* Returns if a thread is active (currently running or waiting to be scheduled)
|
|
|
|
*
|
|
|
|
* @param thread thread to work on
|
|
|
|
* @returns true if thread is active, false otherwise
|
|
|
|
*/
|
2021-01-19 10:28:31 +01:00
|
|
|
static inline bool thread_is_active(const thread_t *thread)
|
|
|
|
{
|
2020-11-25 14:46:43 +01:00
|
|
|
return thread->status >= STATUS_ON_RUNQUEUE;
|
|
|
|
}
|
|
|
|
|
2020-11-25 14:34:03 +01:00
|
|
|
/**
|
|
|
|
* Convert a thread state code to a human readable string.
|
|
|
|
*
|
|
|
|
* @param state thread state to convert
|
|
|
|
* @returns ptr to string representation of thread state (or to "unknown")
|
|
|
|
*/
|
|
|
|
const char *thread_state_to_string(thread_status_t state);
|
|
|
|
|
2021-09-06 13:22:22 +02:00
|
|
|
/**
|
|
|
|
* Get start address (lowest) of a thread's stack.
|
|
|
|
*
|
|
|
|
* @param thread thread to work on
|
|
|
|
* @returns current stack pointer, or NULL if not available
|
|
|
|
*/
|
|
|
|
static inline void *thread_get_stackstart(const thread_t *thread)
|
|
|
|
{
|
2021-11-03 21:38:22 +01:00
|
|
|
#if defined(DEVELHELP) || IS_ACTIVE(SCHED_TEST_STACK) \
|
2021-09-06 13:22:22 +02:00
|
|
|
|| defined(MODULE_MPU_STACK_GUARD)
|
|
|
|
return thread->stack_start;
|
|
|
|
#else
|
|
|
|
(void)thread;
|
|
|
|
return NULL;
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Get stored Stack Pointer of thread.
|
|
|
|
*
|
|
|
|
* *Only provides meaningful value if the thread is not currently running!*.
|
|
|
|
*
|
|
|
|
* @param thread thread to work on
|
|
|
|
* @returns current stack pointer
|
|
|
|
*/
|
|
|
|
static inline void *thread_get_sp(const thread_t *thread)
|
|
|
|
{
|
|
|
|
return thread->sp;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Get size of a thread's stack.
|
|
|
|
*
|
|
|
|
* @param thread thread to work on
|
|
|
|
* @returns thread stack size, or 0 if not available
|
|
|
|
*/
|
|
|
|
static inline size_t thread_get_stacksize(const thread_t *thread)
|
|
|
|
{
|
|
|
|
#if defined(DEVELHELP)
|
|
|
|
return thread->stack_size;
|
|
|
|
#else
|
|
|
|
(void)thread;
|
|
|
|
return 0;
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Get PID of thread.
|
|
|
|
*
|
|
|
|
* This is a simple getter for thread->pid.
|
|
|
|
*
|
|
|
|
* @param thread thread to work on
|
|
|
|
* @returns thread pid
|
|
|
|
*/
|
|
|
|
static inline kernel_pid_t thread_getpid_of(const thread_t *thread)
|
|
|
|
{
|
|
|
|
return thread->pid;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Get name of thread.
|
|
|
|
*
|
|
|
|
* @param thread thread to work on
|
|
|
|
* @returns thread name or NULL if not available
|
|
|
|
*/
|
|
|
|
static inline const char *thread_get_name(const thread_t *thread)
|
|
|
|
{
|
|
|
|
#if defined(CONFIG_THREAD_NAMES)
|
|
|
|
return thread->name;
|
|
|
|
#else
|
|
|
|
(void)thread;
|
|
|
|
return NULL;
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
2024-05-31 10:59:14 +02:00
|
|
|
/**
|
|
|
|
* @brief Measures the stack usage of a stack
|
|
|
|
*
|
2024-10-07 17:31:31 +02:00
|
|
|
* @pre Does not work if the thread was created with the flag
|
|
|
|
* `THREAD_CREATE_NO_STACKTEST`.
|
2024-05-31 10:59:14 +02:00
|
|
|
*
|
|
|
|
* @param[in] thread The thread to measure the stack of
|
|
|
|
*
|
|
|
|
* @return the amount of unused space of the thread's stack
|
|
|
|
*/
|
|
|
|
static inline uintptr_t thread_measure_stack_free(const thread_t *thread)
|
|
|
|
{
|
|
|
|
/* explicitly casting void pointers is bad code style, but needed for C++
|
|
|
|
* compatibility */
|
|
|
|
return measure_stack_free_internal((const char *)thread_get_stackstart(thread),
|
|
|
|
thread_get_stacksize(thread));
|
|
|
|
}
|
|
|
|
|
2014-10-09 01:18:16 +02:00
|
|
|
#ifdef __cplusplus
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2014-10-19 23:05:36 +02:00
|
|
|
/** @} */
|
2015-03-26 17:07:04 +01:00
|
|
|
#endif /* THREAD_H */
|