mirror of
https://github.com/flipperdevices/flipperzero-firmware.git
synced 2025-12-12 04:41:26 +04:00
[FL-3847, FL-3513] Thread Signals (#3730)
* Add signal API * Add signal support to loader * Add signal support to ViewDispatcher * Remove extra signal definitions * Fix typos Co-authored-by: Silent <CookiePLMonster@users.noreply.github.com> * scripts: runfap: close current app pre-launch * loader: enable backlight when starting an app * scripts: removed distfap.py * Do not expose signal API via ViewDispatcher * scripts: runfap: iterative retry to launch * Add a loader signal subcommand * Furi, Gui: move signal handling from View Dispatcher to Event Loop Co-authored-by: Silent <CookiePLMonster@users.noreply.github.com> Co-authored-by: hedger <hedger@nanode.su> Co-authored-by: Aleksandr Kutuzov <alleteam@gmail.com>
This commit is contained in:
@@ -40,6 +40,12 @@ typedef enum {
|
||||
FuriStatusReserved = 0x7FFFFFFF ///< Prevents enum down-size compiler optimization.
|
||||
} FuriStatus;
|
||||
|
||||
typedef enum {
|
||||
FuriSignalExit, /**< Request (graceful) exit. */
|
||||
// Other standard signals may be added in the future
|
||||
FuriSignalCustom = 100, /**< Custom signal values start from here. */
|
||||
} FuriSignal;
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -149,6 +149,9 @@ void furi_event_loop_run(FuriEventLoop* instance) {
|
||||
furi_check(instance);
|
||||
furi_check(instance->thread_id == furi_thread_get_current_id());
|
||||
|
||||
furi_thread_set_signal_callback(
|
||||
instance->thread_id, furi_event_loop_signal_callback, instance);
|
||||
|
||||
uint32_t timeout = instance->tick_callback ? instance->tick_interval : FuriWaitForever;
|
||||
|
||||
while(true) {
|
||||
@@ -194,11 +197,12 @@ void furi_event_loop_run(FuriEventLoop* instance) {
|
||||
}
|
||||
instance->state = FuriEventLoopStateIdle;
|
||||
}
|
||||
|
||||
furi_thread_set_signal_callback(instance->thread_id, NULL, NULL);
|
||||
}
|
||||
|
||||
void furi_event_loop_stop(FuriEventLoop* instance) {
|
||||
furi_check(instance);
|
||||
furi_check(instance->thread_id == furi_thread_get_current_id());
|
||||
|
||||
xTaskNotifyIndexed(
|
||||
instance->thread_id, FURI_EVENT_LOOP_FLAG_NOTIFY_INDEX, FuriEventLoopFlagStop, eSetBits);
|
||||
@@ -366,4 +370,19 @@ void furi_event_loop_link_notify(FuriEventLoopLink* instance, FuriEventLoopEvent
|
||||
}
|
||||
|
||||
FURI_CRITICAL_EXIT();
|
||||
}
|
||||
}
|
||||
|
||||
bool furi_event_loop_signal_callback(uint32_t signal, void* arg, void* context) {
|
||||
furi_assert(context);
|
||||
FuriEventLoop* instance = context;
|
||||
UNUSED(arg);
|
||||
|
||||
switch(signal) {
|
||||
case FuriSignalExit:
|
||||
furi_event_loop_stop(instance);
|
||||
return true;
|
||||
// Room for possible other standard signal handlers
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -28,6 +28,8 @@ typedef struct {
|
||||
const FuriEventLoopContractGetLevel get_level;
|
||||
} FuriEventLoopContract;
|
||||
|
||||
bool furi_event_loop_signal_callback(uint32_t signal, void* arg, void* context);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -42,6 +42,9 @@ struct FuriThread {
|
||||
FuriThreadStateCallback state_callback;
|
||||
void* state_context;
|
||||
|
||||
FuriThreadSignalCallback signal_callback;
|
||||
void* signal_context;
|
||||
|
||||
char* name;
|
||||
char* appid;
|
||||
|
||||
@@ -304,6 +307,29 @@ FuriThreadState furi_thread_get_state(FuriThread* thread) {
|
||||
return thread->state;
|
||||
}
|
||||
|
||||
void furi_thread_set_signal_callback(
|
||||
FuriThread* thread,
|
||||
FuriThreadSignalCallback callback,
|
||||
void* context) {
|
||||
furi_check(thread);
|
||||
furi_check(thread->state == FuriThreadStateStopped || thread == furi_thread_get_current());
|
||||
|
||||
thread->signal_callback = callback;
|
||||
thread->signal_context = context;
|
||||
}
|
||||
|
||||
bool furi_thread_signal(const FuriThread* thread, uint32_t signal, void* arg) {
|
||||
furi_check(thread);
|
||||
|
||||
bool is_consumed = false;
|
||||
|
||||
if(thread->signal_callback) {
|
||||
is_consumed = thread->signal_callback(signal, arg, thread->signal_context);
|
||||
}
|
||||
|
||||
return is_consumed;
|
||||
}
|
||||
|
||||
void furi_thread_start(FuriThread* thread) {
|
||||
furi_check(thread);
|
||||
furi_check(thread->callback);
|
||||
|
||||
@@ -86,6 +86,18 @@ typedef void (*FuriThreadStdoutWriteCallback)(const char* data, size_t size);
|
||||
*/
|
||||
typedef void (*FuriThreadStateCallback)(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.
|
||||
*
|
||||
@@ -255,6 +267,29 @@ void furi_thread_set_state_context(FuriThread* thread, void* context);
|
||||
*/
|
||||
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.
|
||||
*
|
||||
* @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 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.
|
||||
*
|
||||
|
||||
Reference in New Issue
Block a user