Created
November 6, 2022 20:57
-
-
Save fxn/4e41a11ebefb2cc3c56fc93c9fead3bc to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
module Simulation | |
# Clocks in a Linux system | |
# ======================== | |
# | |
# A Linux system has two clocks: The hardware clock, and the system clock. | |
# | |
# The hardware clock, also known as RTC or real-time clock, is a physical | |
# clock. This clock runs always, even when the system is shut down or | |
# unplugged the clock keeps running because it has an independent source of | |
# power, normally a lithium battery. See | |
# | |
# https://en.wikipedia.org/wiki/Real-time_clock | |
# | |
# You manage the RTC with the command `hwclock`. | |
# | |
# The system clock is a counter maintained by the kernel and driven by a | |
# periodic timer interrupt: | |
# | |
# http://www.science.unitn.it/~fiorella/guidelinux/tlk/node121.html | |
# | |
# Each time an interrupt happens, the kernel increments a variable called | |
# _jiffies_. This stores the number of clock ticks since last boot: | |
# | |
# http://www.makelinux.net/ldd3/chp-7-sect-1 | |
# | |
# At boot time the hardware clock is checked to set the system time and from | |
# then on it can be changed without affecting the hardware clock. The command | |
# `date` allows management of the system clock. See: | |
# | |
# https://en.wikipedia.org/wiki/System_time | |
# | |
# The Linux kernel has a mode called "11 minutes mode" wherein it copies the | |
# system time to the hardware clock every 11 minutes. This needs a compile | |
# time option to be supported, and in such case the system has to be put in a | |
# synchronized state. The NTP daemon for example does this. It can also be | |
# turned off by running anything that sets the time the old-fashioned way, | |
# like `hwclock --hctosys`, but if `ntpd(1)` is running it will set the flag | |
# back the next time it synchronizes. | |
# | |
# Time wrapping in the simulator | |
# ============================== | |
# | |
# The simulator executes events and sets the system time to their | |
# corresponding timestamp. That way all external services are going to have a | |
# consistent time. If we emulated this only in Ruby with Timecop, for example | |
# any call to `NOW()` or default timestamp values set by the database would | |
# not match. | |
# | |
# For this reason, machines using the simulator cannot run ntpd(1). | |
# Moreover, Vagrant synchronizes the time of the guest with the one of the | |
# host, to run the simulator within Vagrant you need to execute | |
# | |
# VBoxManage setextradata $vm_name VBoxInternal/Devices/VMMDev/0/Config/GetHostTimeDisabled 1 | |
# | |
# The runner wraps its main look in `wrap_time`, to ensure that no matter what | |
# we restore the system time after the simulation has finished (either | |
# successfully or aborted). | |
# | |
# The method `set_system_time` encapsulates the way the system time is set. | |
# | |
# Sleeping | |
# ======== | |
# | |
# To have in mind. | |
# | |
# Sleeping is apparently implemented by a decreasing counter of CPU jiffies | |
# (the quantum of CPU time) and this ignores altogether system time. Because | |
# of this, if a process sleeps for 2 seconds and the simulation moves the | |
# system clock, the `sleep` call will wake up in two seconds of wall-clock | |
# time no matter where the system time is at that moment. | |
class TimeWrapper | |
def self.wrap_time | |
yield | |
ensure | |
# We reset the hardware clock to get a shell back with the current time. | |
# | |
# This doesn't work on the Docker containers of the simulator dedicated | |
# environment, but since they are ephemeral that is fine. That is why we | |
# redirect stderr, it is fine to err, and we want a clean output. | |
system "sudo hwclock -s 2>/dev/null" | |
end | |
def self.set_system_time(epoch) | |
system "sudo date -s '@#{epoch}' > /dev/null" | |
end | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment