1
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:
Georgii Surkov
2024-06-21 23:44:36 +03:00
committed by GitHub
parent a0036d10fc
commit 4cf98867a0
16 changed files with 291 additions and 109 deletions

View File

@@ -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

View File

@@ -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;
}
}

View File

@@ -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

View File

@@ -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);

View File

@@ -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.
*