@@ -233,7 +233,7 @@ pub fn call(
233233 }
234234 return sent;
235235 }
236- let result = recv_blocking_for_thread ( caller, caller, reply_ptr, reply_len) ;
236+ let result = recv_blocking_reply_for_thread ( caller, caller, reply_ptr, reply_len) ;
237237 let mut boxes = MAILBOXES . lock ( ) ;
238238 if let Some ( ( idx, _) ) = crate :: task:: thread_slot_index_and_generation_by_u64 ( caller) {
239239 if idx < MAX_THREADS {
@@ -276,7 +276,210 @@ pub fn reply(dest_thread_id: u64, buf_ptr: u64, len: u64) -> u64 {
276276 None => return EINVAL ,
277277 } ;
278278 let _ = caller_handle;
279- send_to_thread_id ( target_thread, caller_handle, buf_ptr, len)
279+ send_to_thread_id_with_kind ( target_thread, caller_handle, buf_ptr, len, true )
280+ }
281+
282+ fn recv_blocking_from_sender_for_thread (
283+ sender_handle : u64 ,
284+ receiver_thread_id : u64 ,
285+ caller_thread_id : u64 ,
286+ buf_ptr : u64 ,
287+ max_len : u64 ,
288+ ) -> u64 {
289+ let ( idx, receiver_generation) =
290+ match crate :: task:: thread_slot_index_and_generation_by_u64 ( receiver_thread_id) {
291+ Some ( v) => v,
292+ None => return EINVAL ,
293+ } ;
294+
295+ if idx >= MAX_THREADS || idx > ( u16:: MAX as usize ) {
296+ return EINVAL ;
297+ }
298+
299+ let mut recv_buf = [ 0u8 ; MAX_MSG_SIZE ] ;
300+ loop {
301+ let max_copy = core:: cmp:: min ( max_len as usize , ipc_max_msg_size ( ) ) ;
302+ let recv = {
303+ let mut boxes = MAILBOXES . lock ( ) ;
304+ match boxes[ idx] . pop_from_sender_copy (
305+ sender_handle,
306+ receiver_thread_id,
307+ idx as u16 ,
308+ receiver_generation,
309+ & mut recv_buf[ ..max_copy] ,
310+ true ,
311+ ) {
312+ Some ( v) => {
313+ if let Some ( ( caller_idx, _) ) =
314+ crate :: task:: thread_slot_index_and_generation_by_u64 ( caller_thread_id)
315+ {
316+ if caller_idx < MAX_THREADS {
317+ boxes[ caller_idx] . reply_to = v. 0 ;
318+ }
319+ }
320+ Some ( v)
321+ }
322+ None => {
323+ boxes[ idx] . waiter = caller_thread_id;
324+ None
325+ }
326+ }
327+ } ;
328+
329+ match recv {
330+ Some ( ( from, copy_len) ) => {
331+ if copy_len > 0 && buf_ptr != 0 {
332+ if let Err ( err) = crate :: syscall:: copy_to_user ( buf_ptr, & recv_buf[ ..copy_len] ) {
333+ return err;
334+ }
335+ }
336+ return ( from << 32 ) | ( copy_len as u64 ) ;
337+ }
338+ None => {
339+ {
340+ let mut boxes = MAILBOXES . lock ( ) ;
341+ if let Some ( ( from, copy_len) ) = boxes[ idx] . pop_from_sender_copy (
342+ sender_handle,
343+ receiver_thread_id,
344+ idx as u16 ,
345+ receiver_generation,
346+ & mut recv_buf[ ..max_copy] ,
347+ true ,
348+ ) {
349+ if boxes[ idx] . waiter == caller_thread_id {
350+ boxes[ idx] . waiter = 0 ;
351+ }
352+ if let Some ( ( caller_idx, _) ) =
353+ crate :: task:: thread_slot_index_and_generation_by_u64 ( caller_thread_id)
354+ {
355+ if caller_idx < MAX_THREADS {
356+ boxes[ caller_idx] . reply_to = from;
357+ }
358+ }
359+ drop ( boxes) ;
360+ if copy_len > 0 && buf_ptr != 0 {
361+ if let Err ( err) =
362+ crate :: syscall:: copy_to_user ( buf_ptr, & recv_buf[ ..copy_len] )
363+ {
364+ return err;
365+ }
366+ }
367+ return ( from << 32 ) | ( copy_len as u64 ) ;
368+ }
369+ }
370+ if crate :: task:: sleep_thread_unless_woken ( crate :: task:: ThreadId :: from_u64 (
371+ caller_thread_id,
372+ ) ) {
373+ crate :: task:: yield_now ( ) ;
374+ } else {
375+ let mut boxes = MAILBOXES . lock ( ) ;
376+ if boxes[ idx] . waiter == caller_thread_id {
377+ boxes[ idx] . waiter = 0 ;
378+ }
379+ return EAGAIN ;
380+ }
381+ }
382+ }
383+ }
384+ }
385+
386+ fn recv_blocking_reply_for_thread (
387+ receiver_thread_id : u64 ,
388+ caller_thread_id : u64 ,
389+ buf_ptr : u64 ,
390+ max_len : u64 ,
391+ ) -> u64 {
392+ let ( idx, receiver_generation) =
393+ match crate :: task:: thread_slot_index_and_generation_by_u64 ( receiver_thread_id) {
394+ Some ( v) => v,
395+ None => return EINVAL ,
396+ } ;
397+
398+ if idx >= MAX_THREADS || idx > ( u16:: MAX as usize ) {
399+ return EINVAL ;
400+ }
401+
402+ let mut recv_buf = [ 0u8 ; MAX_MSG_SIZE ] ;
403+ loop {
404+ let max_copy = core:: cmp:: min ( max_len as usize , ipc_max_msg_size ( ) ) ;
405+ let recv = {
406+ let mut boxes = MAILBOXES . lock ( ) ;
407+ match boxes[ idx] . pop_reply_copy (
408+ receiver_thread_id,
409+ idx as u16 ,
410+ receiver_generation,
411+ & mut recv_buf[ ..max_copy] ,
412+ ) {
413+ Some ( v) => {
414+ if let Some ( ( caller_idx, _) ) =
415+ crate :: task:: thread_slot_index_and_generation_by_u64 ( caller_thread_id)
416+ {
417+ if caller_idx < MAX_THREADS {
418+ boxes[ caller_idx] . reply_to = v. 0 ;
419+ }
420+ }
421+ Some ( v)
422+ }
423+ None => {
424+ boxes[ idx] . waiter = caller_thread_id;
425+ None
426+ }
427+ }
428+ } ;
429+
430+ match recv {
431+ Some ( ( from, copy_len) ) => {
432+ if copy_len > 0 && buf_ptr != 0 {
433+ if let Err ( err) = crate :: syscall:: copy_to_user ( buf_ptr, & recv_buf[ ..copy_len] ) {
434+ return err;
435+ }
436+ }
437+ return ( from << 32 ) | ( copy_len as u64 ) ;
438+ }
439+ None => {
440+ {
441+ let mut boxes = MAILBOXES . lock ( ) ;
442+ if let Some ( ( from, copy_len) ) = boxes[ idx] . pop_reply_copy (
443+ receiver_thread_id,
444+ idx as u16 ,
445+ receiver_generation,
446+ & mut recv_buf[ ..max_copy] ,
447+ ) {
448+ if boxes[ idx] . waiter == caller_thread_id {
449+ boxes[ idx] . waiter = 0 ;
450+ }
451+ if let Some ( ( caller_idx, _) ) =
452+ crate :: task:: thread_slot_index_and_generation_by_u64 ( caller_thread_id)
453+ {
454+ if caller_idx < MAX_THREADS {
455+ boxes[ caller_idx] . reply_to = from;
456+ }
457+ }
458+ drop ( boxes) ;
459+ if copy_len > 0 && buf_ptr != 0 {
460+ if let Err ( err) =
461+ crate :: syscall:: copy_to_user ( buf_ptr, & recv_buf[ ..copy_len] )
462+ {
463+ return err;
464+ }
465+ }
466+ return ( from << 32 ) | ( copy_len as u64 ) ;
467+ }
468+ }
469+ if crate :: task:: sleep_thread_unless_woken ( crate :: task:: ThreadId :: from_u64 (
470+ caller_thread_id,
471+ ) ) {
472+ crate :: task:: yield_now ( ) ;
473+ } else {
474+ let mut boxes = MAILBOXES . lock ( ) ;
475+ if boxes[ idx] . waiter == caller_thread_id {
476+ boxes[ idx] . waiter = 0 ;
477+ }
478+ return EAGAIN ;
479+ }
480+ }
481+ }
482+ }
280483}
281484
282485pub fn wait ( buf_ptr : u64 , max_len : u64 , blocking : u64 ) -> u64 {
@@ -345,6 +548,7 @@ pub struct Message {
345548 to : u64 ,
346549 to_slot : u16 ,
347550 to_generation : u64 ,
551+ is_reply : bool ,
348552 len : usize ,
349553 data : [ u8 ; MAX_MSG_SIZE ] ,
350554 ext_pages_count : u16 ,
@@ -358,6 +562,7 @@ impl Message {
358562 to : 0 ,
359563 to_slot : 0 ,
360564 to_generation : 0 ,
565+ is_reply : false ,
361566 len : 0 ,
362567 data : [ 0 ; MAX_MSG_SIZE ] ,
363568 ext_pages_count : 0 ,
@@ -463,6 +668,7 @@ impl Mailbox {
463668 to_slot : u16 ,
464669 to_generation : u64 ,
465670 data : & [ u8 ] ,
671+ is_reply : bool ,
466672 ) -> Result < ( ) , ( ) > {
467673 if data. len ( ) > ipc_max_msg_size ( ) {
468674 return Err ( ( ) ) ;
@@ -476,6 +682,7 @@ impl Mailbox {
476682 msg. to = to;
477683 msg. to_slot = to_slot;
478684 msg. to_generation = to_generation;
685+ msg. is_reply = is_reply;
479686 msg. len = data. len ( ) ;
480687 msg. ext_pages_count = 0 ;
481688 if !data. is_empty ( ) {
@@ -538,6 +745,7 @@ impl Mailbox {
538745 receiver_slot : u16 ,
539746 receiver_generation : u64 ,
540747 out : & mut [ u8 ] ,
748+ reply_only : bool ,
541749 ) -> Option < ( u64 , usize ) > {
542750 if self . count == 0 {
543751 return None ;
@@ -551,6 +759,48 @@ impl Mailbox {
551759 || msg. to != receiver
552760 || msg. to_slot != receiver_slot
553761 || msg. to_generation != receiver_generation
762+ || ( reply_only && !msg. is_reply )
763+ {
764+ if self . enqueue_slot ( slot_idx) . is_err ( ) {
765+ let _ = self . free_slot ( slot_idx) ;
766+ return None ;
767+ }
768+ continue ;
769+ }
770+
771+ let copy_len = core:: cmp:: min ( msg. len , out. len ( ) ) ;
772+ if copy_len > 0 {
773+ out[ ..copy_len] . copy_from_slice ( & msg. data [ ..copy_len] ) ;
774+ }
775+ let from = msg. from ;
776+ if !self . free_slot ( slot_idx) {
777+ return None ;
778+ }
779+ return Some ( ( from, copy_len) ) ;
780+ }
781+
782+ None
783+ }
784+
785+ fn pop_reply_copy (
786+ & mut self ,
787+ receiver : u64 ,
788+ receiver_slot : u16 ,
789+ receiver_generation : u64 ,
790+ out : & mut [ u8 ] ,
791+ ) -> Option < ( u64 , usize ) > {
792+ if self . count == 0 {
793+ return None ;
794+ }
795+
796+ let original = self . count ;
797+ for _ in 0 ..original {
798+ let slot_idx = self . dequeue_slot ( ) ?;
799+ let msg = & self . slots [ slot_idx] ;
800+ if msg. to != receiver
801+ || msg. to_slot != receiver_slot
802+ || msg. to_generation != receiver_generation
803+ || !msg. is_reply
554804 {
555805 if self . enqueue_slot ( slot_idx) . is_err ( ) {
556806 let _ = self . free_slot ( slot_idx) ;
@@ -602,7 +852,14 @@ pub fn send_from_kernel(dest_thread_id: u64, data: &[u8]) -> bool {
602852 . unwrap_or ( 0 ) ;
603853 MAILBOXES . lock ( ) . get_mut ( idx) . map_or ( false , |mb| {
604854 if mb
605- . push_message ( sender, dest_thread_id, idx as u16 , dest_generation, data)
855+ . push_message (
856+ sender,
857+ dest_thread_id,
858+ idx as u16 ,
859+ dest_generation,
860+ data,
861+ false ,
862+ )
606863 . is_ok ( )
607864 {
608865 let waiter = mb. take_waiter ( ) ;
@@ -649,6 +906,7 @@ pub fn send_pages_from_kernel(
649906 msg. to = dest_thread_id;
650907 msg. to_slot = idx as u16 ;
651908 msg. to_generation = dest_generation;
909+ msg. is_reply = false ;
652910 // serialize map_start, total only.
653911 // 物理ページ配列は data に露出させず ext_pages 側だけに保持する。
654912 let mut off = 0usize ;
@@ -703,6 +961,7 @@ pub fn send_map_header_from_kernel(dest_thread_id: u64, map_start: u64, total: u
703961 msg. to = dest_thread_id;
704962 msg. to_slot = idx as u16 ;
705963 msg. to_generation = dest_generation;
964+ msg. is_reply = false ;
706965 // New format: [magic:u32][map_start:u64][total:u64] (20 bytes)
707966 let mut off = 0usize ;
708967 if 20 > ipc_max_msg_size ( ) {
@@ -748,6 +1007,16 @@ pub fn send_map_header_from_kernel(dest_thread_id: u64, map_start: u64, total: u
7481007}
7491008
7501009fn send_to_thread_id ( dest_thread_id : u64 , sender_handle : u64 , buf_ptr : u64 , len : u64 ) -> u64 {
1010+ send_to_thread_id_with_kind ( dest_thread_id, sender_handle, buf_ptr, len, false )
1011+ }
1012+
1013+ fn send_to_thread_id_with_kind (
1014+ dest_thread_id : u64 ,
1015+ sender_handle : u64 ,
1016+ buf_ptr : u64 ,
1017+ len : u64 ,
1018+ is_reply : bool ,
1019+ ) -> u64 {
7511020 if dest_thread_id == 0 {
7521021 return EINVAL ;
7531022 }
@@ -782,7 +1051,6 @@ fn send_to_thread_id(dest_thread_id: u64, sender_handle: u64, buf_ptr: u64, len:
7821051 return err;
7831052 }
7841053 }
785-
7861054 let mut boxes = MAILBOXES . lock ( ) ;
7871055 if boxes[ idx]
7881056 . push_message (
@@ -791,6 +1059,7 @@ fn send_to_thread_id(dest_thread_id: u64, sender_handle: u64, buf_ptr: u64, len:
7911059 idx as u16 ,
7921060 dest_generation,
7931061 & data[ ..len] ,
1062+ is_reply,
7941063 )
7951064 . is_err ( )
7961065 {
@@ -1353,6 +1622,7 @@ pub fn recv_from_sender_for_kernel_nonblocking(
13531622 idx as u16 ,
13541623 receiver_generation,
13551624 buf,
1625+ false ,
13561626 )
13571627 . map ( |( _, n) | n)
13581628 } ;
@@ -1392,6 +1662,7 @@ pub fn recv_blocking_from_sender_for_kernel(
13921662 idx as u16 ,
13931663 receiver_generation,
13941664 buf,
1665+ false ,
13951666 ) {
13961667 Some ( ( _, n) ) => Some ( n) ,
13971668 None => {
@@ -1412,6 +1683,7 @@ pub fn recv_blocking_from_sender_for_kernel(
14121683 idx as u16 ,
14131684 receiver_generation,
14141685 buf,
1686+ false ,
14151687 ) {
14161688 if boxes[ idx] . waiter == receiver_u64 {
14171689 boxes[ idx] . waiter = 0 ;
0 commit comments