mirror of
https://github.com/DarkFlippers/unleashed-firmware.git
synced 2025-12-12 04:34:43 +04:00
State callbacks assumed they were invoked from the thread that changed its state, but this wasn't true for FuriThreadStateStarting in the past, and now it's not true for FuriThreadStateStopped either. Now it is safe to release the thread memory form the state callback once it switches to FuriThreadStateStopped. Therefore, pending deletion calls can be removed. Co-authored-by: Aleksandr Kutuzov <alleteam@gmail.com>
516 lines
16 KiB
C
516 lines
16 KiB
C
/**
|
|
* @file thread.h
|
|
* @brief Furi: Furi Thread API
|
|
*/
|
|
|
|
#pragma once
|
|
|
|
#include "base.h"
|
|
#include "common_defines.h"
|
|
|
|
#include <stdint.h>
|
|
#include <stddef.h>
|
|
|
|
#ifdef __cplusplus
|
|
extern "C" {
|
|
#endif
|
|
|
|
/**
|
|
* @brief Enumeration of possible FuriThread states.
|
|
*
|
|
* Many of the FuriThread functions MUST ONLY be called when the thread is STOPPED.
|
|
*/
|
|
typedef enum {
|
|
FuriThreadStateStopped, /**< Thread is stopped and is safe to release */
|
|
FuriThreadStateStopping, /**< Thread is stopping */
|
|
FuriThreadStateStarting, /**< Thread is starting */
|
|
FuriThreadStateRunning, /**< Thread is running */
|
|
} FuriThreadState;
|
|
|
|
/**
|
|
* @brief Enumeration of possible FuriThread priorities.
|
|
*/
|
|
typedef enum {
|
|
FuriThreadPriorityIdle = 0, /**< Idle priority */
|
|
FuriThreadPriorityLowest = 14, /**< Lowest */
|
|
FuriThreadPriorityLow = 15, /**< Low */
|
|
FuriThreadPriorityNormal = 16, /**< Normal, system default */
|
|
FuriThreadPriorityHigh = 17, /**< High */
|
|
FuriThreadPriorityHighest = 18, /**< Highest */
|
|
FuriThreadPriorityIsr =
|
|
(FURI_CONFIG_THREAD_MAX_PRIORITIES - 1), /**< Deferred ISR (highest possible) */
|
|
} FuriThreadPriority;
|
|
|
|
/**
|
|
* @brief FuriThread opaque type.
|
|
*/
|
|
typedef struct FuriThread FuriThread;
|
|
|
|
/** FuriThreadList type */
|
|
typedef struct FuriThreadList FuriThreadList;
|
|
|
|
/**
|
|
* @brief Unique thread identifier type (used by the OS kernel).
|
|
*/
|
|
typedef void* FuriThreadId;
|
|
|
|
/**
|
|
* @brief Thread callback function pointer type.
|
|
*
|
|
* The function to be used as a thread callback MUST follow this signature.
|
|
*
|
|
* @param[in,out] context pointer to a user-specified object
|
|
* @return value to be used as the thread return code
|
|
*/
|
|
typedef int32_t (*FuriThreadCallback)(void* context);
|
|
|
|
/**
|
|
* @brief Standard output callback function pointer type.
|
|
*
|
|
* The function to be used as a standard output callback MUST follow this signature.
|
|
*
|
|
* @warning The handler MUST process ALL of the provided data before returning.
|
|
*
|
|
* @param[in] data pointer to the data to be written to the standard out
|
|
* @param[in] size size of the data in bytes
|
|
*/
|
|
typedef void (*FuriThreadStdoutWriteCallback)(const char* data, size_t size);
|
|
|
|
/**
|
|
* @brief State change callback function pointer type.
|
|
*
|
|
* The function to be used as a state callback MUST follow this signature.
|
|
*
|
|
* @param[in] pointer to the FuriThread instance that changed the state
|
|
* @param[in] state identifier of the state the thread has transitioned to
|
|
* @param[in,out] context pointer to a user-specified object
|
|
*/
|
|
typedef void (*FuriThreadStateCallback)(FuriThread* thread, FuriThreadState state, void* context);
|
|
|
|
/**
|
|
* @brief Signal handler callback function pointer type.
|
|
*
|
|
* The function to be used as a signal handler callback MUS follow this signature.
|
|
*
|
|
* @param[in] signal value of the signal to be handled by the recipient
|
|
* @param[in,out] arg optional argument (can be of any value, including NULL)
|
|
* @param[in,out] context pointer to a user-specified object
|
|
* @returns true if the signal was handled, false otherwise
|
|
*/
|
|
typedef bool (*FuriThreadSignalCallback)(uint32_t signal, void* arg, void* context);
|
|
|
|
/**
|
|
* @brief Create a FuriThread instance.
|
|
*
|
|
* @return pointer to the created FuriThread instance
|
|
*/
|
|
FuriThread* furi_thread_alloc(void);
|
|
|
|
/**
|
|
* @brief Create a FuriThread instance (service mode).
|
|
*
|
|
* Service threads are more memory efficient, but have
|
|
* the following limitations:
|
|
*
|
|
* - Cannot return from the callback
|
|
* - Cannot be joined or freed
|
|
* - Stack size cannot be altered
|
|
*
|
|
* @param[in] name human-readable thread name (can be NULL)
|
|
* @param[in] stack_size stack size in bytes (cannot be changed later)
|
|
* @param[in] callback pointer to a function to be executed in this thread
|
|
* @param[in] context pointer to a user-specified object (will be passed to the callback)
|
|
* @return pointer to the created FuriThread instance
|
|
*/
|
|
FuriThread* furi_thread_alloc_service(
|
|
const char* name,
|
|
uint32_t stack_size,
|
|
FuriThreadCallback callback,
|
|
void* context);
|
|
|
|
/**
|
|
* @brief Create a FuriThread instance w/ extra parameters.
|
|
*
|
|
* @param[in] name human-readable thread name (can be NULL)
|
|
* @param[in] stack_size stack size in bytes (can be changed later)
|
|
* @param[in] callback pointer to a function to be executed in this thread
|
|
* @param[in] context pointer to a user-specified object (will be passed to the callback)
|
|
* @return pointer to the created FuriThread instance
|
|
*/
|
|
FuriThread* furi_thread_alloc_ex(
|
|
const char* name,
|
|
uint32_t stack_size,
|
|
FuriThreadCallback callback,
|
|
void* context);
|
|
|
|
/**
|
|
* @brief Delete a FuriThread instance.
|
|
*
|
|
* The thread MUST be stopped when calling this function.
|
|
*
|
|
* @warning see furi_thread_join for caveats on stopping a thread.
|
|
*
|
|
* @param[in,out] thread pointer to the FuriThread instance to be deleted
|
|
*/
|
|
void furi_thread_free(FuriThread* thread);
|
|
|
|
/**
|
|
* @brief Set the name of a FuriThread instance.
|
|
*
|
|
* The thread MUST be stopped when calling this function.
|
|
*
|
|
* @param[in,out] thread pointer to the FuriThread instance to be modified
|
|
* @param[in] name human-readable thread name (can be NULL)
|
|
*/
|
|
void furi_thread_set_name(FuriThread* thread, const char* name);
|
|
|
|
/**
|
|
* @brief Set the application ID of a FuriThread instance.
|
|
*
|
|
* The thread MUST be stopped when calling this function.
|
|
*
|
|
* Technically, it is like a "process id", but it is not a system-wide unique identifier.
|
|
* All threads spawned by the same app will have the same appid.
|
|
*
|
|
* @param[in,out] thread pointer to the FuriThread instance to be modified
|
|
* @param[in] appid thread application ID (can be NULL)
|
|
*/
|
|
void furi_thread_set_appid(FuriThread* thread, const char* appid);
|
|
|
|
/**
|
|
* @brief Set the stack size of a FuriThread instance.
|
|
*
|
|
* The thread MUST be stopped when calling this function. Additionally, it is NOT possible
|
|
* to change the stack size of a service thread under any circumstances.
|
|
*
|
|
* @param[in,out] thread pointer to the FuriThread instance to be modified
|
|
* @param[in] stack_size stack size in bytes
|
|
*/
|
|
void furi_thread_set_stack_size(FuriThread* thread, size_t stack_size);
|
|
|
|
/**
|
|
* @brief Set the user callback function to be executed in a FuriThread.
|
|
*
|
|
* The thread MUST be stopped when calling this function.
|
|
*
|
|
* @param[in,out] thread pointer to the FuriThread instance to be modified
|
|
* @param[in] callback pointer to a user-specified function to be executed in this thread
|
|
*/
|
|
void furi_thread_set_callback(FuriThread* thread, FuriThreadCallback callback);
|
|
|
|
/**
|
|
* @brief Set the callback function context.
|
|
*
|
|
* The thread MUST be stopped when calling this function.
|
|
*
|
|
* @param[in,out] thread pointer to the FuriThread instance to be modified
|
|
* @param[in] context pointer to a user-specified object (will be passed to the callback, can be NULL)
|
|
*/
|
|
void furi_thread_set_context(FuriThread* thread, void* context);
|
|
|
|
/**
|
|
* @brief Set the priority of a FuriThread.
|
|
*
|
|
* The thread MUST be stopped when calling this function.
|
|
*
|
|
* @param[in,out] thread pointer to the FuriThread instance to be modified
|
|
* @param[in] priority priority level value
|
|
*/
|
|
void furi_thread_set_priority(FuriThread* thread, FuriThreadPriority priority);
|
|
|
|
/**
|
|
* @brief Get the priority of a FuriThread.
|
|
*
|
|
* @param[in] thread pointer to the FuriThread instance to be queried
|
|
* @return priority level value
|
|
*/
|
|
FuriThreadPriority furi_thread_get_priority(FuriThread* thread);
|
|
|
|
/**
|
|
* @brief Set the priority of the current FuriThread.
|
|
*
|
|
* @param priority priority level value
|
|
*/
|
|
void furi_thread_set_current_priority(FuriThreadPriority priority);
|
|
|
|
/**
|
|
* @brief Get the priority of the current FuriThread.
|
|
*
|
|
* @return priority level value
|
|
*/
|
|
FuriThreadPriority furi_thread_get_current_priority(void);
|
|
|
|
/**
|
|
* Set the callback function to be executed upon a state thransition of a FuriThread.
|
|
*
|
|
* The thread MUST be stopped when calling this function.
|
|
*
|
|
* @param[in,out] thread pointer to the FuriThread instance to be modified
|
|
* @param[in] callback pointer to a user-specified callback function
|
|
*/
|
|
void furi_thread_set_state_callback(FuriThread* thread, FuriThreadStateCallback callback);
|
|
|
|
/**
|
|
* @brief Set the state change callback context.
|
|
*
|
|
* The thread MUST be stopped when calling this function.
|
|
*
|
|
* @param[in,out] thread pointer to the FuriThread instance to be modified
|
|
* @param[in] context pointer to a user-specified object (will be passed to the callback, can be NULL)
|
|
*/
|
|
void furi_thread_set_state_context(FuriThread* thread, void* context);
|
|
|
|
/**
|
|
* @brief Get the state of a FuriThread isntance.
|
|
*
|
|
* @param[in] thread pointer to the FuriThread instance to be queried
|
|
* @return thread state value
|
|
*/
|
|
FuriThreadState furi_thread_get_state(FuriThread* thread);
|
|
|
|
/**
|
|
* @brief Set a signal handler callback for a FuriThread instance.
|
|
*
|
|
* The thread MUST be stopped when calling this function if calling it from another thread.
|
|
*
|
|
* @param[in,out] thread pointer to the FuriThread instance to be modified
|
|
* @param[in] callback pointer to a user-specified callback function
|
|
* @param[in] context pointer to a user-specified object (will be passed to the callback, can be NULL)
|
|
*/
|
|
void furi_thread_set_signal_callback(
|
|
FuriThread* thread,
|
|
FuriThreadSignalCallback callback,
|
|
void* context);
|
|
|
|
/**
|
|
* @brief Get a signal callback for a FuriThread instance.
|
|
*
|
|
* @param[in] thread pointer to the FuriThread instance to be queried
|
|
* @return pointer to the callback function or NULL if none has been set
|
|
*/
|
|
FuriThreadSignalCallback furi_thread_get_signal_callback(const FuriThread* thread);
|
|
|
|
/**
|
|
* @brief Send a signal to a FuriThread instance.
|
|
*
|
|
* @param[in] thread pointer to the FuriThread instance to be signaled
|
|
* @param[in] signal signal value to be sent
|
|
* @param[in,out] arg optional argument (can be of any value, including NULL)
|
|
*/
|
|
bool furi_thread_signal(const FuriThread* thread, uint32_t signal, void* arg);
|
|
|
|
/**
|
|
* @brief Start a FuriThread instance.
|
|
*
|
|
* The thread MUST be stopped when calling this function.
|
|
*
|
|
* @param[in,out] thread pointer to the FuriThread instance to be started
|
|
*/
|
|
void furi_thread_start(FuriThread* thread);
|
|
|
|
/**
|
|
* @brief Wait for a FuriThread to exit.
|
|
*
|
|
* The thread callback function must return in order for the FuriThread instance to become joinable.
|
|
*
|
|
* @warning Use this method only when the CPU is not busy (i.e. when the
|
|
* Idle task receives control), otherwise it will wait forever.
|
|
*
|
|
* @param[in] thread pointer to the FuriThread instance to be joined
|
|
* @return always true
|
|
*/
|
|
bool furi_thread_join(FuriThread* thread);
|
|
|
|
/**
|
|
* @brief Get the unique identifier of a FuriThread instance.
|
|
*
|
|
* @param[in] thread pointer to the FuriThread instance to be queried
|
|
* @return unique identifier value or NULL if thread is not running
|
|
*/
|
|
FuriThreadId furi_thread_get_id(FuriThread* thread);
|
|
|
|
/**
|
|
* @brief Enable heap usage tracing for a FuriThread.
|
|
*
|
|
* The thread MUST be stopped when calling this function.
|
|
*
|
|
* @param[in,out] thread pointer to the FuriThread instance to be modified
|
|
*/
|
|
void furi_thread_enable_heap_trace(FuriThread* thread);
|
|
|
|
/**
|
|
* @brief Disable heap usage tracing for a FuriThread.
|
|
*
|
|
* The thread MUST be stopped when calling this function.
|
|
*
|
|
* @param[in,out] thread pointer to the FuriThread instance to be modified
|
|
*/
|
|
void furi_thread_disable_heap_trace(FuriThread* thread);
|
|
|
|
/**
|
|
* @brief Get heap usage by a FuriThread instance.
|
|
*
|
|
* The heap trace MUST be enabled before callgin this function.
|
|
*
|
|
* @param[in] thread pointer to the FuriThread instance to be queried
|
|
* @return heap usage in bytes
|
|
*/
|
|
size_t furi_thread_get_heap_size(FuriThread* thread);
|
|
|
|
/**
|
|
* @brief Get the return code of a FuriThread instance.
|
|
*
|
|
* This value is equal to the return value of the thread callback function.
|
|
*
|
|
* The thread MUST be stopped when calling this function.
|
|
*
|
|
* @param[in] thread pointer to the FuriThread instance to be queried
|
|
* @return return code value
|
|
*/
|
|
int32_t furi_thread_get_return_code(FuriThread* thread);
|
|
|
|
/**
|
|
* @brief Get the unique identifier of the current FuriThread.
|
|
*
|
|
* @return unique identifier value
|
|
*/
|
|
FuriThreadId furi_thread_get_current_id(void);
|
|
|
|
/**
|
|
* @brief Get the FuriThread instance associated with the current thread.
|
|
*
|
|
* @return pointer to a FuriThread instance or NULL if this thread does not belong to Furi
|
|
*/
|
|
FuriThread* furi_thread_get_current(void);
|
|
|
|
/**
|
|
* @brief Return control to the scheduler.
|
|
*/
|
|
void furi_thread_yield(void);
|
|
|
|
/**
|
|
* @brief Set the thread flags of a FuriThread.
|
|
*
|
|
* Can be used as a simple inter-thread communication mechanism.
|
|
*
|
|
* @param[in] thread_id unique identifier of the thread to be notified
|
|
* @param[in] flags bitmask of thread flags to set
|
|
* @return bitmask combination of previous and newly set flags
|
|
*/
|
|
uint32_t furi_thread_flags_set(FuriThreadId thread_id, uint32_t flags);
|
|
|
|
/**
|
|
* @brief Clear the thread flags of the current FuriThread.
|
|
*
|
|
* @param[in] flags bitmask of thread flags to clear
|
|
* @return bitmask of thread flags before clearing
|
|
*/
|
|
uint32_t furi_thread_flags_clear(uint32_t flags);
|
|
|
|
/**
|
|
* @brief Get the thread flags of the current FuriThread.
|
|
* @return current bitmask of thread flags
|
|
*/
|
|
uint32_t furi_thread_flags_get(void);
|
|
|
|
/**
|
|
* @brief Wait for some thread flags to be set.
|
|
*
|
|
* @see FuriFlag for option and error flags.
|
|
*
|
|
* @param[in] flags bitmask of thread flags to wait for
|
|
* @param[in] options combination of option flags determining the behavior of the function
|
|
* @param[in] timeout maximum time to wait in milliseconds (use FuriWaitForever to wait forever)
|
|
* @return bitmask combination of received thread and error flags
|
|
*/
|
|
uint32_t furi_thread_flags_wait(uint32_t flags, uint32_t options, uint32_t timeout);
|
|
|
|
/**
|
|
* @brief Enumerate all threads.
|
|
*
|
|
* @param[out] thread_list pointer to the FuriThreadList container
|
|
*
|
|
* @return true on success, false otherwise
|
|
*/
|
|
bool furi_thread_enumerate(FuriThreadList* thread_list);
|
|
|
|
/**
|
|
* @brief Get the name of a thread based on its unique identifier.
|
|
*
|
|
* @param[in] thread_id unique identifier of the thread to be queried
|
|
* @return pointer to a zero-terminated string or NULL
|
|
*/
|
|
const char* furi_thread_get_name(FuriThreadId thread_id);
|
|
|
|
/**
|
|
* @brief Get the application id of a thread based on its unique identifier.
|
|
*
|
|
* @param[in] thread_id unique identifier of the thread to be queried
|
|
* @return pointer to a zero-terminated string
|
|
*/
|
|
const char* furi_thread_get_appid(FuriThreadId thread_id);
|
|
|
|
/**
|
|
* @brief Get thread stack watermark.
|
|
*
|
|
* @param[in] thread_id unique identifier of the thread to be queried
|
|
* @return stack watermark value
|
|
*/
|
|
uint32_t furi_thread_get_stack_space(FuriThreadId thread_id);
|
|
|
|
/**
|
|
* @brief Get the standard output callback for the current thead.
|
|
*
|
|
* @return pointer to the standard out callback function
|
|
*/
|
|
FuriThreadStdoutWriteCallback furi_thread_get_stdout_callback(void);
|
|
|
|
/** Set standard output callback for the current thread.
|
|
*
|
|
* @param[in] callback pointer to the callback function or NULL to clear
|
|
*/
|
|
void furi_thread_set_stdout_callback(FuriThreadStdoutWriteCallback callback);
|
|
|
|
/** Write data to buffered standard output.
|
|
*
|
|
* @param[in] data pointer to the data to be written
|
|
* @param[in] size data size in bytes
|
|
* @return number of bytes that was actually written
|
|
*/
|
|
size_t furi_thread_stdout_write(const char* data, size_t size);
|
|
|
|
/**
|
|
* @brief Flush buffered data to standard output.
|
|
*
|
|
* @return error code value
|
|
*/
|
|
int32_t furi_thread_stdout_flush(void);
|
|
|
|
/**
|
|
* @brief Suspend a thread.
|
|
*
|
|
* Suspended threads are no more receiving any of the processor time.
|
|
*
|
|
* @param[in] thread_id unique identifier of the thread to be suspended
|
|
*/
|
|
void furi_thread_suspend(FuriThreadId thread_id);
|
|
|
|
/**
|
|
* @brief Resume a thread.
|
|
*
|
|
* @param[in] thread_id unique identifier of the thread to be resumed
|
|
*/
|
|
void furi_thread_resume(FuriThreadId thread_id);
|
|
|
|
/**
|
|
* @brief Test if a thread is suspended.
|
|
*
|
|
* @param[in] thread_id unique identifier of the thread to be queried
|
|
* @return true if thread is suspended, false otherwise
|
|
*/
|
|
bool furi_thread_is_suspended(FuriThreadId thread_id);
|
|
|
|
#ifdef __cplusplus
|
|
}
|
|
#endif
|