Skip to content

Commit db437ff

Browse files
committed
Improve hiffy state
1 parent 5ae7e0b commit db437ff

1 file changed

Lines changed: 79 additions & 82 deletions

File tree

humility-hiffy/src/lib.rs

Lines changed: 79 additions & 82 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,11 @@ use zerocopy::{AsBytes, U16, U64};
2323
#[derive(Debug, PartialEq)]
2424
enum 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

Comments
 (0)