Skip to content

Commit 3b90c1b

Browse files
committed
kernel: wake IPC and notif waiters on destroy and kill
- Endpoint/notif destroy and thread kill now unblock waiters with errors instead of leaving orphaned rendezvous - Extend unit coverage for destroy-with-waiters and kill-during-IPC paths
1 parent 5a66af2 commit 3b90c1b

8 files changed

Lines changed: 284 additions & 50 deletions

File tree

kernel/include/ulmk_ep_internal.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,5 +43,6 @@ int ep_reply_recv_impl(ulmk_ep_t ep_id, ulmk_tid_t sender_tid,
4343
int ep_grant_impl(ulmk_ep_t ep_id, ulmk_tid_t target_tid);
4444
int ep_recv_or_notif_impl(ulmk_ep_t ep_id, ulmk_notif_t notif_id,
4545
uint32_t mask, ulmk_recv_or_notif_result_t *res);
46+
int ep_destroy_impl(ulmk_ep_t ep_id);
4647

4748
#endif /* UL_EP_INTERNAL_H */

kernel/include/ulmk_notif_internal.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,5 +30,6 @@ ulmk_notif_obj_t *ulmk_notif_by_id(ulmk_notif_t id);
3030
int notif_signal_impl(ulmk_notif_t id, uint32_t bits);
3131
int notif_wait_impl(ulmk_notif_t id, uint32_t mask, uint32_t *out);
3232
uint32_t notif_poll_impl(ulmk_notif_t id, uint32_t mask);
33+
int notif_destroy_impl(ulmk_notif_t id);
3334

3435
#endif /* UL_NOTIF_INTERNAL_H */

kernel/include/ulmk_thread_internal.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,11 @@ typedef struct ulmk_thread {
6565
ulmk_recv_or_notif_result_t *rn_result_outptr;
6666
uint32_t notif_wait_mask;
6767
uint32_t notif_received; /* bits consumed on notif wakeup */
68+
/*
69+
* Status returned by a blocking syscall after wakeup.
70+
* 0 = normal completion; ULMK_EINVAL = object destroyed under us.
71+
*/
72+
int32_t block_status;
6873
/* MPU regions owned by this thread (configured by mpu_switch on dispatch) */
6974
ulmk_arch_region_t regions[ULMK_ARCH_MAX_REGIONS];
7075
uint8_t region_count;

kernel/ipc/ep.c

Lines changed: 88 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,10 @@
1212
* - ep_reply_recv: atomic reply + re-block for next message (fast path).
1313
*
1414
* Priority inheritance:
15-
* When ep_call wakes a server, the server's priority is temporarily raised
16-
* to the caller's priority if the caller is higher-priority.
17-
* ep_reply restores the server's original priority before waking the caller.
15+
* On rendezvous, the server's priority is temporarily raised to the
16+
* caller's if the caller is higher-priority (lower numeric value).
17+
* Applies on both paths: ep_call waking a waiting server, and ep_recv
18+
* taking a waiting caller. ep_reply restores saved_prio before wake.
1819
*
1920
* Two-layer design:
2021
* ep_*_impl() — core logic with native C pointer types; testable on host.
@@ -107,15 +108,42 @@ static void ipc_enqueue_tail(sys_dlist_t *queue, ulmk_thread_t *th)
107108
sys_dlist_append(queue, &th->ipc_node);
108109
}
109110

111+
static void apply_prio_inherit(ulmk_thread_t *server, ulmk_thread_t *caller)
112+
{
113+
server->saved_prio = server->priority;
114+
if (caller->priority < server->priority)
115+
server->priority = caller->priority;
116+
}
117+
118+
static void wake_blocked_on_destroy(ulmk_thread_t *th, int status)
119+
{
120+
if (sys_dnode_is_linked(&th->ipc_node)) {
121+
sys_dlist_remove(&th->ipc_node);
122+
sys_dnode_init(&th->ipc_node);
123+
}
124+
125+
if (th->blocked_notif != ULMK_NOTIF_INVALID) {
126+
ulmk_notif_obj_t *n = ulmk_notif_by_id(th->blocked_notif);
127+
128+
if (n && n->waiter == th)
129+
n->waiter = NULL;
130+
th->blocked_notif = ULMK_NOTIF_INVALID;
131+
}
132+
133+
th->block_status = status;
134+
th->blocked_reason = UL_BLOCKED_NONE;
135+
th->blocked_ep = ULMK_EP_INVALID;
136+
th->state = UL_THREAD_STATE_READY;
137+
ulmk_sched_enqueue(th);
138+
}
139+
110140
static void deliver_to_server(ulmk_thread_t *server, ulmk_thread_t *caller,
111141
const ulmk_msg_t *msg)
112142
{
113143
server->ipc_msg = *msg;
114144
server->ipc_sender = caller->tid;
115145

116-
server->saved_prio = server->priority;
117-
if (caller->priority < server->priority)
118-
server->priority = caller->priority;
146+
apply_prio_inherit(server, caller);
119147

120148
server->state = UL_THREAD_STATE_READY;
121149
server->blocked_reason = UL_BLOCKED_NONE;
@@ -157,6 +185,7 @@ int ep_call_impl(ulmk_ep_t ep_id, ulmk_msg_t *msg)
157185
cur->blocked_reason = UL_BLOCKED_IPC_CALL;
158186
cur->blocked_ep = ep_id;
159187
cur->ipc_msg_outptr = msg;
188+
cur->block_status = 0;
160189

161190
if (!sys_dlist_is_empty(&ep->recv_queue)) {
162191
ulmk_thread_t *srv = ipc_pop_head(&ep->recv_queue);
@@ -172,7 +201,16 @@ int ep_call_impl(ulmk_ep_t ep_id, ulmk_msg_t *msg)
172201

173202
/* Re-fetch cur: local var may be stale after context switch. */
174203
cur = ulmk_sched_current();
175-
if (cur && cur->ipc_msg_outptr) {
204+
if (!cur)
205+
return -ULMK_EINVAL;
206+
if (cur->block_status != 0) {
207+
int st = cur->block_status;
208+
209+
cur->block_status = 0;
210+
cur->ipc_msg_outptr = NULL;
211+
return st;
212+
}
213+
if (cur->ipc_msg_outptr) {
176214
*cur->ipc_msg_outptr = cur->ipc_msg;
177215
cur->ipc_msg_outptr = NULL;
178216
}
@@ -200,6 +238,7 @@ int ep_recv_impl(ulmk_ep_t ep_id, ulmk_msg_t *msg, ulmk_tid_t *sender)
200238

201239
*msg = caller->ipc_msg;
202240
cur->ipc_sender = caller->tid;
241+
apply_prio_inherit(cur, caller);
203242

204243
if (sender)
205244
*sender = caller->tid;
@@ -211,6 +250,7 @@ int ep_recv_impl(ulmk_ep_t ep_id, ulmk_msg_t *msg, ulmk_tid_t *sender)
211250
cur->ipc_sender_outptr = sender;
212251
cur->blocked_reason = UL_BLOCKED_IPC_RECV;
213252
cur->blocked_ep = ep_id;
253+
cur->block_status = 0;
214254
ipc_enqueue_tail(&ep->recv_queue, cur);
215255

216256
cur->state = UL_THREAD_STATE_BLOCKED;
@@ -220,6 +260,14 @@ int ep_recv_impl(ulmk_ep_t ep_id, ulmk_msg_t *msg, ulmk_tid_t *sender)
220260
cur = ulmk_sched_current();
221261
if (!cur)
222262
return -ULMK_EINVAL;
263+
if (cur->block_status != 0) {
264+
int st = cur->block_status;
265+
266+
cur->block_status = 0;
267+
cur->ipc_msg_outptr = NULL;
268+
cur->ipc_sender_outptr = NULL;
269+
return st;
270+
}
223271

224272
if (cur->ipc_msg_outptr) {
225273
*cur->ipc_msg_outptr = cur->ipc_msg;
@@ -313,6 +361,7 @@ int ep_recv_or_notif_impl(ulmk_ep_t ep_id, ulmk_notif_t notif_id,
313361
if (!sys_dlist_is_empty(&ep->send_queue)) {
314362
ulmk_thread_t *caller = ipc_pop_head(&ep->send_queue);
315363

364+
apply_prio_inherit(cur, caller);
316365
cur->ipc_sender = caller->tid;
317366
cur->ipc_msg = caller->ipc_msg;
318367

@@ -330,6 +379,7 @@ int ep_recv_or_notif_impl(ulmk_ep_t ep_id, ulmk_notif_t notif_id,
330379
cur->ipc_msg_outptr = NULL;
331380
cur->ipc_sender_outptr = NULL;
332381
cur->rn_result_outptr = res;
382+
cur->block_status = 0;
333383

334384
ipc_enqueue_tail(&ep->recv_queue, cur);
335385
n->waiter = cur;
@@ -343,6 +393,13 @@ int ep_recv_or_notif_impl(ulmk_ep_t ep_id, ulmk_notif_t notif_id,
343393
cur = ulmk_sched_current();
344394
if (!cur)
345395
return -ULMK_EINVAL;
396+
if (cur->block_status != 0) {
397+
int st = cur->block_status;
398+
399+
cur->block_status = 0;
400+
cur->rn_result_outptr = NULL;
401+
return st;
402+
}
346403

347404
res = cur->rn_result_outptr;
348405
cur->rn_result_outptr = NULL;
@@ -364,6 +421,28 @@ int ep_recv_or_notif_impl(ulmk_ep_t ep_id, ulmk_notif_t notif_id,
364421
}
365422
}
366423

424+
int ep_destroy_impl(ulmk_ep_t ep_id)
425+
{
426+
ulmk_endpoint_t *ep;
427+
ulmk_thread_t *th;
428+
429+
ep = ulmk_ep_by_id(ep_id);
430+
if (!ep)
431+
return -ULMK_EINVAL;
432+
433+
while ((th = ipc_pop_head(&ep->send_queue)) != NULL)
434+
wake_blocked_on_destroy(th, ULMK_EINVAL);
435+
436+
while ((th = ipc_pop_head(&ep->recv_queue)) != NULL)
437+
wake_blocked_on_destroy(th, ULMK_EINVAL);
438+
439+
ep->active = false;
440+
#ifndef UL_UNIT_TEST
441+
ulmk_heap_free(ep);
442+
#endif
443+
return 0;
444+
}
445+
367446
/* =========================================================================
368447
* Syscall ABI wrappers — cast uint32_t args, delegate to _impl.
369448
* ========================================================================= */
@@ -384,7 +463,7 @@ uint32_t ulmk_kern_ep_create(void)
384463
ulmk_endpoint_t *ep = (ulmk_endpoint_t *)ulmk_heap_alloc(sizeof(ulmk_endpoint_t));
385464

386465
if (!ep)
387-
return (uint32_t)(int32_t)(-ULMK_ENOMEM);
466+
return (uint32_t)ULMK_EP_INVALID;
388467
ulmk_ep_init(ep, (ulmk_ep_t)(uintptr_t)ep);
389468
return (uint32_t)(uintptr_t)ep;
390469
#endif
@@ -446,20 +525,5 @@ uint32_t ulmk_kern_ep_recv_or_notif(uint32_t ep_id, uint32_t notif_id,
446525

447526
uint32_t ulmk_kern_ep_destroy(uint32_t ep_id)
448527
{
449-
#ifdef UL_UNIT_TEST
450-
uint32_t i = (uint32_t)ep_id;
451-
452-
if (i >= ULMK_CONFIG_MAX_ENDPOINTS || !ep_pool[i].active)
453-
return (uint32_t)(int32_t)(-ULMK_EINVAL);
454-
ep_pool[i].active = false;
455-
return 0u;
456-
#else
457-
ulmk_endpoint_t *ep = (ulmk_endpoint_t *)(uintptr_t)ep_id;
458-
459-
if (!ep || !ep->active)
460-
return (uint32_t)(int32_t)(-ULMK_EINVAL);
461-
ep->active = false;
462-
ulmk_heap_free(ep);
463-
return 0u;
464-
#endif
528+
return (uint32_t)(int32_t)ep_destroy_impl((ulmk_ep_t)ep_id);
465529
}

kernel/notif/notif.c

Lines changed: 39 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -133,6 +133,7 @@ int notif_wait_impl(ulmk_notif_t notif_id, uint32_t mask, uint32_t *out)
133133
cur->notif_wait_mask = mask;
134134
cur->blocked_notif = notif_id;
135135
cur->notif_bits_outptr = out;
136+
cur->block_status = 0;
136137

137138
cur->state = UL_THREAD_STATE_BLOCKED;
138139
ulmk_sched_dequeue(cur);
@@ -161,6 +162,13 @@ int notif_wait_impl(ulmk_notif_t notif_id, uint32_t mask, uint32_t *out)
161162
cur = ulmk_sched_current();
162163
if (!cur)
163164
return -ULMK_EINVAL;
165+
if (cur->block_status != 0) {
166+
int st = cur->block_status;
167+
168+
cur->block_status = 0;
169+
cur->notif_bits_outptr = NULL;
170+
return st;
171+
}
164172

165173
if (cur->notif_bits_outptr) {
166174
*cur->notif_bits_outptr = cur->notif_received;
@@ -186,6 +194,35 @@ uint32_t notif_poll_impl(ulmk_notif_t notif_id, uint32_t mask)
186194
return matched;
187195
}
188196

197+
int notif_destroy_impl(ulmk_notif_t notif_id)
198+
{
199+
ulmk_notif_obj_t *n = ulmk_notif_by_id(notif_id);
200+
ulmk_thread_t *w;
201+
202+
if (!n)
203+
return -ULMK_EINVAL;
204+
205+
w = n->waiter;
206+
n->waiter = NULL;
207+
if (w) {
208+
if (w->blocked_reason == UL_BLOCKED_IPC_OR_NOTIF)
209+
ulmk_ep_recv_queue_remove(w);
210+
211+
w->blocked_notif = ULMK_NOTIF_INVALID;
212+
w->blocked_ep = ULMK_EP_INVALID;
213+
w->block_status = ULMK_EINVAL;
214+
w->blocked_reason = UL_BLOCKED_NONE;
215+
w->state = UL_THREAD_STATE_READY;
216+
ulmk_sched_enqueue(w);
217+
}
218+
219+
n->active = false;
220+
#ifndef UL_UNIT_TEST
221+
ulmk_heap_free(n);
222+
#endif
223+
return 0;
224+
}
225+
189226
/* =========================================================================
190227
* Syscall ABI wrappers
191228
* ========================================================================= */
@@ -206,30 +243,15 @@ uint32_t ulmk_kern_notif_create(void)
206243
ulmk_notif_obj_t *n = (ulmk_notif_obj_t *)ulmk_heap_alloc(sizeof(ulmk_notif_obj_t));
207244

208245
if (!n)
209-
return (uint32_t)(int32_t)(-ULMK_ENOMEM);
246+
return (uint32_t)ULMK_NOTIF_INVALID;
210247
ulmk_notif_obj_init(n, (ulmk_notif_t)(uintptr_t)n);
211248
return (uint32_t)(uintptr_t)n;
212249
#endif
213250
}
214251

215252
uint32_t ulmk_kern_notif_destroy(uint32_t notif_id)
216253
{
217-
#ifdef UL_UNIT_TEST
218-
uint32_t i = notif_id;
219-
220-
if (i >= ULMK_CONFIG_MAX_NOTIFS || !notif_pool[i].active)
221-
return (uint32_t)(int32_t)(-ULMK_EINVAL);
222-
notif_pool[i].active = false;
223-
return 0u;
224-
#else
225-
ulmk_notif_obj_t *n = (ulmk_notif_obj_t *)(uintptr_t)notif_id;
226-
227-
if (!n || !n->active)
228-
return (uint32_t)(int32_t)(-ULMK_EINVAL);
229-
n->active = false;
230-
ulmk_heap_free(n);
231-
return 0u;
232-
#endif
254+
return (uint32_t)(int32_t)notif_destroy_impl((ulmk_notif_t)notif_id);
233255
}
234256

235257
uint32_t ulmk_kern_notif_signal(uint32_t notif_id, uint32_t bits)

0 commit comments

Comments
 (0)