Note: I've just migrated to a different physical server to run Spivey's Corner,
with a new architecture, a new operating system, a new version of PHP, and an updated version of MediaWiki.
Please let me know if anything needs adjustment! – Mike

Timeout API for micro:bian

Copyright © 2024 J. M. Spivey
Jump to navigation Jump to search

The idea is to provide a new version of receive that takes a timeout value in milliseconds:

void receive_t(int type, message *msg, int timeout)

If no other message is received before the timeout happens, then a message is delivered with source HARDWARE and type TIMEOUT. The timeout is automatically cancelled on delivery of a genuine message, whether from HARDWARE (i.e., an interrupt) or from a normal process. The type filter type may have any value, not just ANY; any timeout message is delivered even if the receive call is specific to a different message type, so it's necessary for the receiving process to check on the message type.

A timer process can periodically invoke a new system call,

void tick(int ms)

where ms is the number of milliseconds since the last invocation of tick. This decrements all active timeout countdowns by the specified amount, and delivers TIMEOUT messages to any that have gone off, making the corresponding processes ready to run. There is no need for an immediate context switch, since responding to a timeout presumably has a low priority.

Any micro:bian program that uses timeouts will need a timer process to trigger them, but programs that do not use timeouts can still be written with no need for a timer process. The guarantees are weak: a receive_t will time out eventually (providing there is a timer process continually calling tick), and it will do so in a time that is at least the one specified. In order to prevent premature timeouts, it will be best to deliver the message on the tick following the one where the timeout value is reached: that way, the message cannot be delivered early because of an initial short tick. We might allow timeout=0 as a special case, meaning to deliver a message if one it waiting, otherwise to deliver an immediate timeout.

Ticks can be relatively infrequent, so it is OK to implement tick() by looping over all processes checking for timeouts. Note that (depending on the device) an interrupt can arrive after the timeout message has been delivered, either before the process has been scheduled, or afterwards while it is dealing with the timeout; in either case, the interrupt will be queued and delivered on the next receive. So it might be necessary to write the device driver carefully, so that unexpected interrupts are ignored.