[PATCH RFC 04/11] um: Handle UM_TIMETRAVEL_RUN only in idle loop, signal success in ACK

Benjamin Beichler
2023-11-03T16:42:20Z

The Timetravel socket can be read from the SIGIO handler, which may
catch a RUN message that was expected to be received in the wait loop.

It can happen that the device simulation only "created" one interrupt,
but an uncertain (i.e., hard to predict by the calendar/device
simulation) number of SIGIOs are emitted, with each SIGIO interrupt
producing a GET message. The calendar might try to send a RUN message
after the first GET message, which is then processed in the SIGIO
handler, waiting for the response to a subsequent GET message. However,
time is advanced by the received RUN message. Typically, this doesn't
pose problems because the interrupt implies that the next RUN message
should be at the current time (as sent by the calendar with the GET
message). But there are corner cases, such as simultaneous other
interrupts, which may desynchronize the current time in the UML instance
from the expected time from the calendar. Since there is no real use
case for advancing time in the SIGIO handler with RUN messages (in
contrast to UPDATE messages), we logically only expect time to advance
in the idle loop in TT-ext mode. Therefore, with this patch, we restrict
time changes to the idle loop.

Additionally, since both the idle loop and the signal/interrupt handlers
do blocking reads from the TT socket, a deadlock can occur if a RUN
message intended for the idle loop is received in the SIGIO handler. In
this situation, the calendar expects the UML instance to run, but it
actually waits for another message, either in the SIGIO handler (e.g.,
a second interrupt) or in a poll in the idle loop, as the previous
message was handled by the signal handler, which returned execution to
the main loop and ultimately entered the idle loop.

Therefore, this patch also allows checking whether the current RUN
message was handled by the idle loop or by the signal/interrupt handlers
in the ACK of the RUN.

With the information in the ACK of the RUN message, the calendar knows
whether the RUN was answered in a signal handler and can act
accordingly.

Signed-off-by: Benjamin Beichler <benjamin.beichler@uni-rostock.de>
---
arch/um/kernel/time.c | 7 +++++--
1 file changed, 5 insertions(+), 2 deletions(-)

diff --git a/arch/um/kernel/time.c b/arch/um/kernel/time.c
index fddd1dec27e6..ff5ef75bbb94 100644
--- a/arch/um/kernel/time.c
+++ b/arch/um/kernel/time.c
@@ -94,7 +94,10 @@ static void time_travel_handle_message(struct um_timetravel_msg *msg,
case UM_TIMETRAVEL_ACK:
return;
case UM_TIMETRAVEL_RUN:
- time_travel_set_time(msg->time);
+ // the caller time_travel_handle_message will do the appropriate time advance
+ // return here 0, if we got RUN, but are not in idle/ext_wait, to
+ // actually do anything with the run
+ resp.time = (mode != TTMH_READ) ? 1 : 0;
break;
case UM_TIMETRAVEL_FREE_UNTIL:
time_travel_ext_free_until_valid = true;
@@ -238,7 +241,7 @@ static void time_travel_ext_wait(bool idle)
*/
while (msg.op != UM_TIMETRAVEL_RUN)
time_travel_handle_message(&msg, idle ? TTMH_IDLE : TTMH_POLL);
-
+ time_travel_set_time(msg.time);
time_travel_ext_waiting--;

/* we might request more stuff while polling - reset when we run */

--
2.34.1