Skip to content

Commit 438b359

Browse files
committed
Summary
When async_context_threadsafe_background_execute_sync() is invoked from the non‑owner core, the helper worker used to be queued as a async_when_pending_worker_t. Under heavy IRQ load the “pending” flag could be lost, leaving the semaphore unreleased and the caller blocked indefinitely (issue earlephilhower#2433). Changes Replace the helper’s worker field with async_at_time_worker_t and adapt handle_sync_func_call() accordingly. Queue the helper via async_context_add_at_time_worker_in_ms(..., 0) instead of the previous add_when_pending_worker/set_work_pending pair. Drop the now‑unnecessary async_context_remove_when_pending_worker() call inside the handler; at‑time workers self‑remove after execution. .gitignore: ignore .qodo workspace directory. Impact The execute‑sync path is now race‑free: the helper worker is guaranteed to run once, release the semaphore, and return the result to the caller, eliminating the sporadic deadlock observed in multicore scenarios. Co‑authored‑by: Goran Miskovic <schkovich@users.noreply.github.com> Fix contributed for raspberrypi/pico-sdk/issues/2433
1 parent 9fdfe11 commit 438b359

File tree

1 file changed

+3
-5
lines changed

1 file changed

+3
-5
lines changed

src/rp2_common/pico_async_context/async_context_threadsafe_background.c

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -88,18 +88,17 @@ static void async_context_threadsafe_background_lock_check(async_context_t *self
8888

8989
#if ASYNC_CONTEXT_THREADSAFE_BACKGROUND_MULTI_CORE
9090
typedef struct sync_func_call{
91-
async_when_pending_worker_t worker;
91+
async_at_time_worker_t worker;
9292
semaphore_t sem;
9393
uint32_t (*func)(void *param);
9494
void *param;
9595
uint32_t rc;
9696
} sync_func_call_t;
9797

98-
static void handle_sync_func_call(async_context_t *context, async_when_pending_worker_t *worker) {
98+
static void handle_sync_func_call(async_context_t *context, async_at_time_worker_t *worker) {
9999
sync_func_call_t *call = (sync_func_call_t *)worker;
100100
call->rc = call->func(call->param);
101101
sem_release(&call->sem);
102-
async_context_remove_when_pending_worker(context, worker);
103102
}
104103
#endif
105104

@@ -145,8 +144,7 @@ uint32_t async_context_threadsafe_background_execute_sync(async_context_t *self_
145144
call.func = func;
146145
call.param = param;
147146
sem_init(&call.sem, 0, 1);
148-
async_context_add_when_pending_worker(self_base, &call.worker);
149-
async_context_set_work_pending(self_base, &call.worker);
147+
async_context_add_at_time_worker_in_ms(self_base, &call.worker, 0);
150148
sem_acquire_blocking(&call.sem);
151149
return call.rc;
152150
}

0 commit comments

Comments
 (0)