@@ -23,7 +23,11 @@ use zerocopy::{AsBytes, U16, U64};
2323#[ derive( Debug , PartialEq ) ]
2424enum State {
2525 Initialized ,
26- Kicked ,
26+ Kicked {
27+ kick_time : Instant ,
28+ prev_requests_count : u32 ,
29+ prev_errors_count : u32 ,
30+ } ,
2731 ResultsReady ,
2832 ResultsConsumed ,
2933}
@@ -39,8 +43,6 @@ pub struct HiffyContext<'a> {
3943 errors : & ' a HubrisVariable ,
4044 failure : & ' a HubrisVariable ,
4145 scratch_size : usize ,
42- cached : Option < ( u32 , u32 ) > ,
43- kicked : Option < Instant > ,
4446 timeout : u32 ,
4547 state : State ,
4648 functions : HiffyFunctions ,
@@ -351,8 +353,6 @@ impl<'a> HiffyContext<'a> {
351353 errors : Self :: variable ( hubris, "HIFFY_ERRORS" , true ) ?,
352354 failure : Self :: variable ( hubris, "HIFFY_FAILURE" , false ) ?,
353355 scratch_size,
354- cached : None ,
355- kicked : None ,
356356 timeout,
357357 state : State :: Initialized ,
358358 functions : HiffyFunctions ( function_map) ,
@@ -687,7 +687,6 @@ impl<'a> HiffyContext<'a> {
687687 }
688688 assert_eq ! ( self . rpc_results. len( ) , 0 ) ;
689689
690- self . state = State :: Kicked ;
691690 HIFFY_SEND_WORKSPACE . with ( |workspace| {
692691 let workspace = workspace. borrow ( ) ;
693692 if let Some ( e) = workspace. errors . first ( ) {
@@ -744,7 +743,12 @@ impl<'a> HiffyContext<'a> {
744743 self . rpc_results . push ( Err ( IpcError :: from ( rval) ) ) ;
745744 }
746745 }
747- self . state = State :: Kicked ;
746+ // Dummy values for errors and requests, since we'll instantly return
747+ self . state = State :: Kicked {
748+ kick_time : Instant :: now ( ) ,
749+ prev_errors_count : 0 ,
750+ prev_requests_count : 0 ,
751+ } ;
748752 Ok ( ( ) )
749753 } )
750754 }
@@ -1064,16 +1068,16 @@ impl<'a> HiffyContext<'a> {
10641068 core. write_8 ( self . data . addr , data) ?;
10651069 }
10661070
1067- self . cached = Some ( (
1068- core. read_word_32 ( self . requests . addr ) ?,
1069- core. read_word_32 ( self . errors . addr ) ?,
1070- ) ) ;
1071+ let prev_errors_count = core. read_word_32 ( self . errors . addr ) ?;
1072+ let prev_requests_count = core. read_word_32 ( self . requests . addr ) ?;
10711073
10721074 core. write_word_32 ( self . kick . addr , 1 ) ?;
10731075
1074- self . kicked = Some ( Instant :: now ( ) ) ;
1075-
1076- self . state = State :: Kicked ;
1076+ self . state = State :: Kicked {
1077+ kick_time : Instant :: now ( ) ,
1078+ prev_requests_count,
1079+ prev_errors_count,
1080+ } ;
10771081
10781082 core. op_done ( ) ?;
10791083
@@ -1095,9 +1099,11 @@ impl<'a> HiffyContext<'a> {
10951099 }
10961100
10971101 pub fn done ( & mut self , core : & mut dyn Core ) -> Result < bool > {
1098- if self . state != State :: Kicked {
1102+ let State :: Kicked { kick_time, prev_errors_count, prev_requests_count } =
1103+ self . state
1104+ else {
10991105 bail ! ( "invalid state for waiting: {:?}" , self . state) ;
1100- }
1106+ } ;
11011107
11021108 //
11031109 // If this is over the network, our calls are already done by the
@@ -1110,88 +1116,79 @@ impl<'a> HiffyContext<'a> {
11101116
11111117 core. op_start ( ) ?;
11121118
1113- let vars = (
1114- core. read_word_32 ( self . requests . addr ) ?,
1115- core. read_word_32 ( self . errors . addr ) ?,
1116- ) ;
1119+ let new_requests_count = core. read_word_32 ( self . requests . addr ) ?;
1120+ let new_errors_count = core. read_word_32 ( self . errors . addr ) ?;
11171121
11181122 core. op_done ( ) ?;
11191123
1120- if let Some ( kicked) = self . kicked
1121- && kicked. elapsed ( ) . as_millis ( ) > self . timeout . into ( )
1122- {
1124+ if kick_time. elapsed ( ) . as_millis ( ) > self . timeout . into ( ) {
11231125 bail ! ( "operation timed out" ) ;
11241126 }
11251127
1126- if let Some ( cached) = self . cached {
1127- if vars. 0 != cached. 0 {
1128- self . state = State :: ResultsReady ;
1129- Ok ( true )
1130- } else if vars. 1 != cached. 1 {
1131- //
1132- // If we have died because our HIF failed fatally (which we
1133- // only expect due to programmer error), we want to print
1134- // HIFFY_FAILURE to provide some additional context.
1135- //
1136- let mut buf: Vec < u8 > = vec ! [ ] ;
1137- buf. resize_with ( self . failure . size , Default :: default) ;
1128+ if new_requests_count != prev_requests_count {
1129+ self . state = State :: ResultsReady ;
1130+ Ok ( true )
1131+ } else if new_errors_count != prev_errors_count {
1132+ //
1133+ // If we have died because our HIF failed fatally (which we
1134+ // only expect due to programmer error), we want to print
1135+ // HIFFY_FAILURE to provide some additional context.
1136+ //
1137+ let mut buf: Vec < u8 > = vec ! [ ] ;
1138+ buf. resize_with ( self . failure . size , Default :: default) ;
11381139
1139- core. op_start ( ) ?;
1140- let r = core. read_8 ( self . failure . addr , buf. as_mut_slice ( ) ) ;
1141- core. op_done ( ) ?;
1140+ core. op_start ( ) ?;
1141+ let r = core. read_8 ( self . failure . addr , buf. as_mut_slice ( ) ) ;
1142+ core. op_done ( ) ?;
11421143
1143- match r {
1144- Ok ( _) => {
1145- let fmt = HubrisPrintFormat {
1146- hex : true ,
1147- ..HubrisPrintFormat :: default ( )
1148- } ;
1149-
1150- let hubris = self . hubris ;
1151- let f =
1152- hubris. printfmt ( & buf, self . failure . goff , fmt) ?;
1153-
1154- // If Hiffy reports `Invalid`, this could be due to a
1155- // patch version mismatch, i.e. Humility trying to use
1156- // HIF operations that the target does not know about.
1157- if f == "Some(Invalid)" {
1158- let patch = Self :: read_word (
1159- hubris,
1160- core,
1161- "HIFFY_VERSION_PATCH" ,
1162- ) ;
1163- match patch {
1164- Ok ( patch) => {
1165- if patch != HIF_VERSION_PATCH {
1166- bail ! (
1167- "request failed: {0}. Perhaps due \
1144+ match r {
1145+ Ok ( _) => {
1146+ let fmt = HubrisPrintFormat {
1147+ hex : true ,
1148+ ..HubrisPrintFormat :: default ( )
1149+ } ;
1150+
1151+ let hubris = self . hubris ;
1152+ let f = hubris. printfmt ( & buf, self . failure . goff , fmt) ?;
1153+
1154+ // If Hiffy reports `Invalid`, this could be due to a
1155+ // patch version mismatch, i.e. Humility trying to use
1156+ // HIF operations that the target does not know about.
1157+ if f == "Some(Invalid)" {
1158+ let patch = Self :: read_word (
1159+ hubris,
1160+ core,
1161+ "HIFFY_VERSION_PATCH" ,
1162+ ) ;
1163+ match patch {
1164+ Ok ( patch) => {
1165+ if patch != HIF_VERSION_PATCH {
1166+ bail ! (
1167+ "request failed: {0}. Perhaps due \
11681168 to HIF version mismatch? \
11691169 ({1}.{2}.{3} on host, \
11701170 {1}.{2}.{4} on device)",
1171- f,
1172- HIF_VERSION_MAJOR ,
1173- HIF_VERSION_MINOR ,
1174- HIF_VERSION_PATCH ,
1175- patch
1176- ) ;
1177- }
1171+ f,
1172+ HIF_VERSION_MAJOR ,
1173+ HIF_VERSION_MINOR ,
1174+ HIF_VERSION_PATCH ,
1175+ patch
1176+ ) ;
11781177 }
1179- Err ( e) => bail ! (
1180- "request failed: {}; failed to read HIF \
1181- patch version: {:?}",
1182- f,
1183- e
1184- ) ,
11851178 }
1179+ Err ( e) => bail ! (
1180+ "request failed: {}; failed to read HIF \
1181+ patch version: {:?}",
1182+ f,
1183+ e
1184+ ) ,
11861185 }
1187- bail ! ( "request failed: {}" , f) ;
1188- }
1189- _ => {
1190- bail ! ( "request failed" ) ;
11911186 }
1187+ bail ! ( "request failed: {}" , f) ;
1188+ }
1189+ _ => {
1190+ bail ! ( "request failed" ) ;
11921191 }
1193- } else {
1194- Ok ( false )
11951192 }
11961193 } else {
11971194 Ok ( false )
0 commit comments