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+
110140static 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
447526uint32_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}
0 commit comments