While body is executing, all interrupts (for example, preemption, keyboard break etc.) are queued. They are executed when body exits.
To ensure that the seconds and milliseconds slots are always consistent, you can use mp:without-interrupts
within the function which sets them.
(defstruct elapsed-time
seconds
milliseconds)
(defun update-elapsed-time-atomically
(elapsed-time seconds milliseconds)
(mp:without-interrupts
(setf (elapsed-time-seconds elapsed-time) seconds
(elapsed-time-milliseconds elapsed-time)
milliseconds)))