@@ -92,6 +92,7 @@ enum CrossDomainJob {
9292 AddReadPipe ( u32 ) ,
9393 Finish ,
9494 AddAtomicMemorySentinel ( u32 , Event ) ,
95+ AddReadEvent ( u32 ) ,
9596}
9697
9798enum RingWrite < ' a , T > {
@@ -395,18 +396,18 @@ impl CrossDomainWorker {
395396 _ => {
396397 let mut items = self . item_state . lock ( ) . unwrap ( ) ;
397398 let mut cmd_read: CrossDomainReadWrite = Default :: default ( ) ;
398- let pipe_id : u32 = event
399+ let item_id : u32 = event
399400 . connection_id
400401 . try_into ( )
401402 . map_err ( MesaError :: TryFromIntError ) ?;
402403 let bytes_read;
403404
404405 cmd_read. hdr . cmd = CROSS_DOMAIN_CMD_READ ;
405- cmd_read. identifier = pipe_id ;
406+ cmd_read. identifier = item_id ;
406407
407408 let item = items
408409 . table
409- . get_mut ( & pipe_id )
410+ . get_mut ( & item_id )
410411 . ok_or ( RutabagaError :: InvalidCrossDomainItemId ) ?;
411412
412413 match item {
@@ -423,11 +424,18 @@ impl CrossDomainWorker {
423424 self . wait_ctx . delete ( readpipe. as_borrowed_descriptor ( ) ) ?;
424425 }
425426 }
427+ CrossDomainItem :: Event ( ref evt) => {
428+ // For eventfd, we can use wait() to consume the event
429+ if event. readable {
430+ let _ = evt. wait ( ) ;
431+ }
432+ bytes_read = 0 ; // eventfd doesn't have data to read like pipes
433+ }
426434 _ => return Err ( RutabagaError :: InvalidCrossDomainItemType ) ,
427435 }
428436
429437 if event. hung_up && bytes_read == 0 {
430- items. table . remove ( & pipe_id ) ;
438+ items. table . remove ( & item_id ) ;
431439 }
432440
433441 self . fence_handler . call ( fence) ;
@@ -547,6 +555,20 @@ impl CrossDomainWorker {
547555 _ => return Err ( RutabagaError :: InvalidCrossDomainItemType ) ,
548556 }
549557 }
558+ CrossDomainJob :: AddReadEvent ( efd_id) => {
559+ let items = self . item_state . lock ( ) . unwrap ( ) ;
560+ let item = items
561+ . table
562+ . get ( & efd_id)
563+ . ok_or ( RutabagaError :: InvalidCrossDomainItemId ) ?;
564+
565+ match item {
566+ CrossDomainItem :: Event ( event) => self
567+ . wait_ctx
568+ . add ( efd_id as u64 , event. as_borrowed_descriptor ( ) ) ?,
569+ _ => return Err ( RutabagaError :: InvalidCrossDomainItemType ) ,
570+ }
571+ }
550572 CrossDomainJob :: AddAtomicMemorySentinel ( id, recv) => {
551573 self . wait_ctx
552574 . add ( id as u64 , recv. as_borrowed_descriptor ( ) ) ?;
@@ -720,29 +742,28 @@ impl CrossDomainContext {
720742
721743 fn send (
722744 & mut self ,
723- cmd_send : & CrossDomainSendReceive ,
745+ cmd_send : & mut CrossDomainSendReceive ,
724746 opaque_data : & [ u8 ] ,
725747 ) -> RutabagaResult < ( ) > {
726748 let mut descriptors: Vec < OwnedDescriptor > = vec ! [ ] ;
727749 let mut write_pipe_opt: Option < WritePipe > = None ;
728750 let mut read_pipe_id_opt: Option < u32 > = None ;
729751
730- let num_identifiers = cmd_send
731- . num_identifiers
732- . try_into ( )
733- . map_err ( MesaError :: TryFromIntError ) ?;
752+ let num_identifiers = cmd_send. num_identifiers as usize ;
734753
735754 if num_identifiers > CROSS_DOMAIN_MAX_IDENTIFIERS {
736755 return Err ( MesaError :: WithContext ( "max cross domain identifiers exceeded" ) . into ( ) ) ;
737756 }
738757
739758 let iter = cmd_send
740759 . identifiers
741- . iter ( )
742- . zip ( cmd_send. identifier_types . iter ( ) )
760+ . iter_mut ( )
761+ . zip ( cmd_send. identifier_types . iter_mut ( ) )
762+ . zip ( cmd_send. identifier_sizes . iter_mut ( ) )
763+ . map ( |( ( i, it) , is) | ( i, it, is) )
743764 . take ( num_identifiers) ;
744765
745- for ( identifier, identifier_type) in iter {
766+ for ( identifier, identifier_type, _identifier_size ) in iter {
746767 if * identifier_type == CROSS_DOMAIN_ID_TYPE_VIRTGPU_BLOB {
747768 let context_resources = self . context_resources . lock ( ) . unwrap ( ) ;
748769
@@ -853,6 +874,25 @@ impl CrossDomainContext {
853874 Ok ( ( ) )
854875 }
855876
877+ fn read_event_new ( & mut self , cmd_event_new : & CrossDomainCreateEvent ) -> RutabagaResult < ( ) > {
878+ let items = self . item_state . lock ( ) . unwrap ( ) ;
879+
880+ if let Some ( item) = items. table . get ( & cmd_event_new. id ) {
881+ if let CrossDomainItem :: Event ( _) = item {
882+ self . state
883+ . as_ref ( )
884+ . unwrap ( )
885+ . add_job ( CrossDomainJob :: AddReadEvent ( cmd_event_new. id ) ) ;
886+ self . resample_evt . as_mut ( ) . unwrap ( ) . signal ( ) ?;
887+ Ok ( ( ) )
888+ } else {
889+ Err ( RutabagaError :: InvalidCrossDomainItemType )
890+ }
891+ } else {
892+ Err ( RutabagaError :: InvalidCrossDomainItemId )
893+ }
894+ }
895+
856896 fn write ( & self , cmd_write : & CrossDomainReadWrite , opaque_data : & [ u8 ] ) -> RutabagaResult < ( ) > {
857897 let mut items = self . item_state . lock ( ) . unwrap ( ) ;
858898
@@ -886,6 +926,21 @@ impl CrossDomainContext {
886926 _ => Err ( RutabagaError :: InvalidCrossDomainItemType ) ,
887927 }
888928 }
929+
930+ fn process_cmd_send ( & mut self , commands : & mut [ u8 ] ) -> RutabagaResult < ( ) > {
931+ let opaque_data_offset = size_of :: < CrossDomainSendReceive > ( ) ;
932+ let ( mut cmd_send, _) = CrossDomainSendReceive :: read_from_prefix ( commands. as_bytes ( ) )
933+ . map_err ( |_| RutabagaError :: InvalidCommandBuffer ) ?;
934+
935+ let opaque_data = commands
936+ . get_mut ( opaque_data_offset..opaque_data_offset + cmd_send. opaque_data_size as usize )
937+ . ok_or ( RutabagaError :: InvalidCommandSize (
938+ cmd_send. opaque_data_size as usize ,
939+ ) ) ?;
940+
941+ self . send ( & mut cmd_send, opaque_data) ?;
942+ Ok ( ( ) )
943+ }
889944}
890945
891946impl Drop for CrossDomainContext {
@@ -911,13 +966,24 @@ impl Drop for CrossDomainContext {
911966}
912967
913968#[ repr( C ) ]
914- #[ derive( Copy , Clone , Debug , Default , FromBytes , IntoBytes , Immutable ) ]
969+ #[ derive( Copy , Clone , Default , FromBytes , IntoBytes , Immutable ) ]
915970struct CrossDomainInitLegacy {
916971 hdr : CrossDomainHeader ,
917972 query_ring_id : u32 ,
918973 channel_type : u32 ,
919974}
920975
976+ impl CrossDomainInitLegacy {
977+ pub ( crate ) fn upgrade ( & self ) -> CrossDomainInit {
978+ CrossDomainInit {
979+ hdr : self . hdr ,
980+ query_ring_id : self . query_ring_id ,
981+ channel_ring_id : self . query_ring_id ,
982+ channel_type : self . channel_type ,
983+ }
984+ }
985+ }
986+
921987impl RutabagaContext for CrossDomainContext {
922988 fn context_create_blob (
923989 & mut self ,
@@ -1025,24 +1091,13 @@ impl RutabagaContext for CrossDomainContext {
10251091
10261092 match hdr. cmd {
10271093 CROSS_DOMAIN_CMD_INIT => {
1028- let cmd_init = match CrossDomainInit :: read_from_prefix ( commands) {
1029- Ok ( ( cmd_init, _) ) => cmd_init,
1030- _ => {
1031- if let Ok ( ( cmd_init, _) ) =
1032- CrossDomainInitLegacy :: read_from_prefix ( commands)
1033- {
1034- CrossDomainInit {
1035- hdr : cmd_init. hdr ,
1036- query_ring_id : cmd_init. query_ring_id ,
1037- channel_ring_id : cmd_init. query_ring_id ,
1038- channel_type : cmd_init. channel_type ,
1039- }
1040- } else {
1041- return Err ( RutabagaError :: InvalidCommandBuffer ) ;
1042- }
1043- }
1044- } ;
1045-
1094+ let cmd_init = CrossDomainInit :: read_from_prefix ( commands)
1095+ . map ( |( v, _) | v)
1096+ . or_else ( |_| {
1097+ CrossDomainInitLegacy :: read_from_prefix ( commands)
1098+ . map ( |( v, _) | v. upgrade ( ) )
1099+ } )
1100+ . map_err ( |_| RutabagaError :: InvalidCommandBuffer ) ?;
10461101 self . initialize ( & cmd_init) ?;
10471102 }
10481103 CROSS_DOMAIN_CMD_GET_IMAGE_REQUIREMENTS => {
@@ -1053,20 +1108,7 @@ impl RutabagaContext for CrossDomainContext {
10531108 self . get_image_requirements ( & cmd_get_reqs) ?;
10541109 }
10551110 CROSS_DOMAIN_CMD_SEND => {
1056- let opaque_data_offset = size_of :: < CrossDomainSendReceive > ( ) ;
1057- let ( cmd_send, _) = CrossDomainSendReceive :: read_from_prefix ( commands)
1058- . map_err ( |_e| RutabagaError :: InvalidCommandBuffer ) ?;
1059-
1060- let opaque_data = commands
1061- . get_mut (
1062- opaque_data_offset
1063- ..opaque_data_offset + cmd_send. opaque_data_size as usize ,
1064- )
1065- . ok_or ( RutabagaError :: InvalidCommandSize (
1066- cmd_send. opaque_data_size as usize ,
1067- ) ) ?;
1068-
1069- self . send ( & cmd_send, opaque_data) ?;
1111+ self . process_cmd_send ( commands) ?;
10701112 }
10711113 CROSS_DOMAIN_CMD_POLL => {
10721114 // Actual polling is done in the subsequent when creating a fence.
@@ -1105,6 +1147,11 @@ impl RutabagaContext for CrossDomainContext {
11051147 . map_err ( |_e| RutabagaError :: InvalidCommandBuffer ) ?;
11061148 self . atomic_memory_sentinel_destroy ( & cmd_atomic_memory_sentinel_destroy) ?;
11071149 }
1150+ CROSS_DOMAIN_CMD_READ_CREATE_EVENT => {
1151+ let ( cmd_new_evt, _) = CrossDomainCreateEvent :: read_from_prefix ( commands)
1152+ . map_err ( |_| RutabagaError :: InvalidCommandBuffer ) ?;
1153+ self . read_event_new ( & cmd_new_evt) ?;
1154+ }
11081155 _ => return Err ( MesaError :: WithContext ( "invalid cross domain command" ) . into ( ) ) ,
11091156 }
11101157
0 commit comments