Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Furi: A Lot of Fixes #3942

Merged
merged 3 commits into from
Oct 14, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 10 additions & 10 deletions applications/services/bt/bt_service/bt.c
Original file line number Diff line number Diff line change
Expand Up @@ -430,13 +430,11 @@ static void bt_change_profile(Bt* bt, BtMessage* message) {
*message->profile_instance = NULL;
}
}
if(message->lock) api_lock_unlock(message->lock);
}

static void bt_close_connection(Bt* bt, BtMessage* message) {
static void bt_close_connection(Bt* bt) {
bt_close_rpc_connection(bt);
furi_hal_bt_stop_advertising();
if(message->lock) api_lock_unlock(message->lock);
}

static void bt_apply_settings(Bt* bt) {
Expand Down Expand Up @@ -484,19 +482,13 @@ static void bt_load_settings(Bt* bt) {
}

static void bt_handle_get_settings(Bt* bt, BtMessage* message) {
furi_assert(message->lock);
*message->data.settings = bt->bt_settings;
api_lock_unlock(message->lock);
}

static void bt_handle_set_settings(Bt* bt, BtMessage* message) {
furi_assert(message->lock);
bt->bt_settings = *message->data.csettings;

bt_apply_settings(bt);
bt_settings_save(&bt->bt_settings);

api_lock_unlock(message->lock);
}

static void bt_handle_reload_keys_settings(Bt* bt) {
Expand Down Expand Up @@ -548,6 +540,12 @@ int32_t bt_srv(void* p) {
while(1) {
furi_check(
furi_message_queue_get(bt->message_queue, &message, FuriWaitForever) == FuriStatusOk);
FURI_LOG_D(
TAG,
"call %d, lock 0x%p, result 0x%p",
message.type,
(void*)message.lock,
(void*)message.result);
if(message.type == BtMessageTypeUpdateStatus) {
// Update view ports
bt_statusbar_update(bt);
Expand All @@ -571,7 +569,7 @@ int32_t bt_srv(void* p) {
} else if(message.type == BtMessageTypeSetProfile) {
bt_change_profile(bt, &message);
} else if(message.type == BtMessageTypeDisconnect) {
bt_close_connection(bt, &message);
bt_close_connection(bt);
} else if(message.type == BtMessageTypeForgetBondedDevices) {
bt_keys_storage_delete(bt->keys_storage);
} else if(message.type == BtMessageTypeGetSettings) {
Expand All @@ -581,6 +579,8 @@ int32_t bt_srv(void* p) {
} else if(message.type == BtMessageTypeReloadKeysSettings) {
bt_handle_reload_keys_settings(bt);
}

if(message.lock) api_lock_unlock(message.lock);
}

return 0;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -54,11 +54,14 @@ bool dialogs_app_process_module_file_browser(const DialogsAppMessageDataFileBrow
ret = file_browser_context->result;

view_holder_set_view(view_holder, NULL);
view_holder_free(view_holder);
file_browser_stop(file_browser);

file_browser_free(file_browser);
view_holder_free(view_holder);

api_lock_free(file_browser_context->lock);
free(file_browser_context);

furi_record_close(RECORD_GUI);

return ret;
Expand Down
69 changes: 36 additions & 33 deletions applications/services/rpc/rpc.c
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ static RpcSystemCallbacks rpc_systems[] = {
struct RpcSession {
Rpc* rpc;

FuriThreadId thread_id;
FuriThread* thread;

RpcHandlerDict_t handlers;
FuriStreamBuffer* stream;
Expand Down Expand Up @@ -172,7 +172,7 @@ size_t rpc_session_feed(

size_t bytes_sent = furi_stream_buffer_send(session->stream, encoded_bytes, size, timeout);

furi_thread_flags_set(session->thread_id, RpcEvtNewData);
furi_thread_flags_set(furi_thread_get_id(session->thread), RpcEvtNewData);

return bytes_sent;
}
Expand Down Expand Up @@ -220,7 +220,7 @@ bool rpc_pb_stream_read(pb_istream_t* istream, pb_byte_t* buf, size_t count) {
break;
} else {
/* Save disconnect flag and continue reading buffer */
furi_thread_flags_set(session->thread_id, RpcEvtDisconnect);
furi_thread_flags_set(furi_thread_get_id(session->thread), RpcEvtDisconnect);
}
} else if(flags & RpcEvtNewData) {
// Just wake thread up
Expand Down Expand Up @@ -347,32 +347,37 @@ static int32_t rpc_session_worker(void* context) {
return 0;
}

static void rpc_session_thread_release_callback(
FuriThread* thread,
FuriThreadState thread_state,
void* context) {
if(thread_state == FuriThreadStateStopped) {
RpcSession* session = (RpcSession*)context;
static void rpc_session_thread_pending_callback(void* context, uint32_t arg) {
UNUSED(arg);
RpcSession* session = (RpcSession*)context;

for(size_t i = 0; i < COUNT_OF(rpc_systems); ++i) {
if(rpc_systems[i].free) {
(rpc_systems[i].free)(session->system_contexts[i]);
}
}
free(session->system_contexts);
free(session->decoded_message);
RpcHandlerDict_clear(session->handlers);
furi_stream_buffer_free(session->stream);

furi_mutex_acquire(session->callbacks_mutex, FuriWaitForever);
if(session->terminated_callback) {
session->terminated_callback(session->context);
for(size_t i = 0; i < COUNT_OF(rpc_systems); ++i) {
if(rpc_systems[i].free) {
(rpc_systems[i].free)(session->system_contexts[i]);
}
furi_mutex_release(session->callbacks_mutex);
}
free(session->system_contexts);
free(session->decoded_message);
RpcHandlerDict_clear(session->handlers);
furi_stream_buffer_free(session->stream);

furi_mutex_acquire(session->callbacks_mutex, FuriWaitForever);
if(session->terminated_callback) {
session->terminated_callback(session->context);
}
furi_mutex_release(session->callbacks_mutex);

furi_mutex_free(session->callbacks_mutex);
furi_thread_join(session->thread);
furi_thread_free(session->thread);
free(session);
}

furi_mutex_free(session->callbacks_mutex);
furi_thread_free(thread);
free(session);
static void
rpc_session_thread_state_callback(FuriThread* thread, FuriThreadState state, void* context) {
UNUSED(thread);
if(state == FuriThreadStateStopped) {
furi_timer_pending_callback(rpc_session_thread_pending_callback, context, 0);
}
}

Expand Down Expand Up @@ -404,14 +409,12 @@ RpcSession* rpc_session_open(Rpc* rpc, RpcOwner owner) {
};
rpc_add_handler(session, PB_Main_stop_session_tag, &rpc_handler);

FuriThread* thread =
furi_thread_alloc_ex("RpcSessionWorker", 3072, rpc_session_worker, session);
session->thread_id = furi_thread_get_id(thread);
session->thread = furi_thread_alloc_ex("RpcSessionWorker", 3072, rpc_session_worker, session);

furi_thread_set_state_context(thread, session);
furi_thread_set_state_callback(thread, rpc_session_thread_release_callback);
furi_thread_set_state_context(session->thread, session);
furi_thread_set_state_callback(session->thread, rpc_session_thread_state_callback);

furi_thread_start(thread);
furi_thread_start(session->thread);

return session;
}
Expand All @@ -423,7 +426,7 @@ void rpc_session_close(RpcSession* session) {
rpc_session_set_send_bytes_callback(session, NULL);
rpc_session_set_close_callback(session, NULL);
rpc_session_set_buffer_is_empty_callback(session, NULL);
furi_thread_flags_set(session->thread_id, RpcEvtDisconnect);
furi_thread_flags_set(furi_thread_get_id(session->thread), RpcEvtDisconnect);
}

void rpc_on_system_start(void* p) {
Expand Down
5 changes: 4 additions & 1 deletion furi/core/kernel.c
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ bool furi_kernel_is_irq_or_masked(void) {
}

bool furi_kernel_is_running(void) {
return xTaskGetSchedulerState() != taskSCHEDULER_RUNNING;
return xTaskGetSchedulerState() == taskSCHEDULER_RUNNING;
}

int32_t furi_kernel_lock(void) {
Expand Down Expand Up @@ -129,6 +129,8 @@ uint32_t furi_kernel_get_tick_frequency(void) {

void furi_delay_tick(uint32_t ticks) {
furi_check(!furi_kernel_is_irq_or_masked());
furi_check(furi_thread_get_current_id() != xTaskGetIdleTaskHandle());

if(ticks == 0U) {
taskYIELD();
} else {
Expand All @@ -138,6 +140,7 @@ void furi_delay_tick(uint32_t ticks) {

FuriStatus furi_delay_until_tick(uint32_t tick) {
furi_check(!furi_kernel_is_irq_or_masked());
furi_check(furi_thread_get_current_id() != xTaskGetIdleTaskHandle());

TickType_t tcnt, delay;
FuriStatus stat;
Expand Down
17 changes: 12 additions & 5 deletions furi/core/log.c
Original file line number Diff line number Diff line change
Expand Up @@ -108,10 +108,17 @@ void furi_log_puts(const char* data) {
}

void furi_log_print_format(FuriLogLevel level, const char* tag, const char* format, ...) {
if(level <= furi_log.log_level &&
furi_mutex_acquire(furi_log.mutex, FuriWaitForever) == FuriStatusOk) {
FuriString* string;
string = furi_string_alloc();
do {
if(level > furi_log.log_level) {
break;
}

if(furi_mutex_acquire(furi_log.mutex, furi_kernel_is_running() ? FuriWaitForever : 0) !=
FuriStatusOk) {
break;
}

FuriString* string = furi_string_alloc();

const char* color = _FURI_LOG_CLR_RESET;
const char* log_letter = " ";
Expand Down Expand Up @@ -157,7 +164,7 @@ void furi_log_print_format(FuriLogLevel level, const char* tag, const char* form
furi_log_puts("\r\n");

furi_mutex_release(furi_log.mutex);
}
} while(0);
}

void furi_log_print_raw_format(FuriLogLevel level, const char* format, ...) {
Expand Down
44 changes: 32 additions & 12 deletions furi/core/thread.c
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#include "thread.h"
#include "thread_i.h"
#include "thread_list_i.h"
#include "kernel.h"
#include "message_queue.h"
#include "memmgr.h"
#include "memmgr_heap.h"
#include "check.h"
Expand Down Expand Up @@ -67,6 +68,8 @@ static_assert(offsetof(FuriThread, container) == 0);
// Our idle priority should be equal to the one from FreeRTOS
static_assert(FuriThreadPriorityIdle == tskIDLE_PRIORITY);

static FuriMessageQueue* furi_thread_scrub_message_queue = NULL;

static size_t __furi_thread_stdout_write(FuriThread* thread, const char* data, size_t size);
static int32_t __furi_thread_stdout_flush(FuriThread* thread);

Expand Down Expand Up @@ -125,7 +128,9 @@ static void furi_thread_body(void* context) {

furi_thread_set_state(thread, FuriThreadStateStopping);

vTaskDelete(NULL);
furi_message_queue_put(furi_thread_scrub_message_queue, &thread, FuriWaitForever);

vTaskSuspend(NULL);
furi_thread_catch();
}

Expand Down Expand Up @@ -159,6 +164,31 @@ static void furi_thread_init_common(FuriThread* thread) {
}
}

void furi_thread_init(void) {
furi_thread_scrub_message_queue = furi_message_queue_alloc(8, sizeof(FuriThread*));
}

void furi_thread_scrub(void) {
FuriThread* thread_to_scrub = NULL;
while(true) {
furi_check(
furi_message_queue_get(
furi_thread_scrub_message_queue, &thread_to_scrub, FuriWaitForever) ==
FuriStatusOk);

TaskHandle_t task = (TaskHandle_t)thread_to_scrub;

// Delete task: FreeRTOS will remove task from all lists where it may be
vTaskDelete(task);
// Sanity check: ensure that local storage is ours and clear it
furi_check(pvTaskGetThreadLocalStoragePointer(task, 0) == thread_to_scrub);
vTaskSetThreadLocalStoragePointer(task, 0, NULL);

// Deliver thread stopped callback
furi_thread_set_state(thread_to_scrub, FuriThreadStateStopped);
}
}

FuriThread* furi_thread_alloc(void) {
FuriThread* thread = malloc(sizeof(FuriThread));

Expand Down Expand Up @@ -358,16 +388,6 @@ void furi_thread_start(FuriThread* thread) {
&thread->container) == (TaskHandle_t)thread);
}

void furi_thread_cleanup_tcb_event(TaskHandle_t task) {
FuriThread* thread = pvTaskGetThreadLocalStoragePointer(task, 0);
if(thread) {
// clear thread local storage
vTaskSetThreadLocalStoragePointer(task, 0, NULL);
furi_check(thread == (FuriThread*)task);
furi_thread_set_state(thread, FuriThreadStateStopped);
}
}

bool furi_thread_join(FuriThread* thread) {
furi_check(thread);
// Cannot join a service thread
Expand Down
21 changes: 12 additions & 9 deletions furi/core/thread.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,17 +21,18 @@ extern "C" {
* 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 */
FuriThreadStateStopped, /**< Thread is stopped and is safe to release. Event delivered from system init thread(TCB cleanup routine). It is safe to release thread instance. */
FuriThreadStateStopping, /**< Thread is stopping. Event delivered from child thread. */
FuriThreadStateStarting, /**< Thread is starting. Event delivered from parent(self) thread. */
FuriThreadStateRunning, /**< Thread is running. Event delivered from child thread. */
} FuriThreadState;

/**
* @brief Enumeration of possible FuriThread priorities.
*/
typedef enum {
FuriThreadPriorityIdle = 0, /**< Idle priority */
FuriThreadPriorityInit = 4, /**< Init System Thread Priority */
FuriThreadPriorityLowest = 14, /**< Lowest */
FuriThreadPriorityLow = 15, /**< Low */
FuriThreadPriorityNormal = 16, /**< Normal, system default */
Expand Down Expand Up @@ -77,13 +78,15 @@ typedef int32_t (*FuriThreadCallback)(void* context);
typedef void (*FuriThreadStdoutWriteCallback)(const char* data, size_t size);

/**
* @brief State change callback function pointer type.
* @brief State change callback function pointer type.
*
* The function to be used as a state callback MUST follow this signature.
* 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
* @param[in] thread 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);

Expand Down
7 changes: 7 additions & 0 deletions furi/core/thread_i.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
#pragma once

#include "thread.h"

void furi_thread_init(void);

void furi_thread_scrub(void);
Loading
Loading