Subversion Repositories HelenOS-doc

Compare Revisions

Ignore whitespace Rev 55 → Rev 56

/design/trunk/src/ch_time.xml
88,9 → 88,8
to a timeout structure, a callback function, a parameter of the callback
function and a delay in microseconds as parameters. After the structure is
initialized with all these values, it is sorted into the processor's list
of active timeouts.Timeouts are sorted in this list according to the
number of clock interrupts remaining to their expiration and relative to
each other. </para>
of active timeouts, according to the number of clock interrupts remaining
to their expiration and relatively to already listed timeouts.</para>
 
<para>Timeouts can be unregistered via <code>timeout_unregister</code>.
This function can, as opposed to <code>timeout_register</code>, fail when
129,12 → 128,73
</listitem>
</itemizedlist>
 
<para>The first two goals are performed exactly one more times than is the
number of missed clock signals (i.e. at least once and possibly more
times, depending on the missed clock signals counter). The remaining
timeslice of the running thread is decremented also with respect to this
counter. By considering its value, the kernel performs actions that would
otherwise be lost due to an occasional excessive time drift described in
previous paragraphs.</para>
<para>The <code>clock</code> function checks for expired timeouts and
decrements unexpired timeout expiration counters exactly one more times
than is the number of missed clock signals (i.e. at least once and
possibly more times, depending on the missed clock signals counter). The
time of the day counters are also updated one more times than is the
number of missed clock signals. And finally, the remaining timeslice of
the running thread is decremented with respect to this counter as well. By
considering its value, the kernel performs actions that would otherwise be
lost due to an occasional excessive time drift described in previous
paragraphs.</para>
</section>
 
<section>
<title>Time source for userspace</title>
 
<para>In HelenOS, userspace tasks don't communicate with the kernel in
order to read system time. Instead, a mechanism that shares kernel time of
the day counters with userspace address spaces is deployed. On the kernel
side, during system initialization, HelenOS allocates a frame of physical
memory and stores the time of the day counters there. The counters have
the following structure:</para>
 
<itemizedlist>
<listitem>
<para>first 32-bit counter for seconds,</para>
</listitem>
 
<listitem>
<para>32-bit counter for microseconds and</para>
</listitem>
 
<listitem>
<para>second 32-bit counter for seconds.</para>
</listitem>
</itemizedlist>
 
<para>One of the userspace tasks with capabilities of memory manager (e.g.
ns) asks the kernel to map this frame into its address space. Other,
non-privileged, tasks then use IPC to communicate read-only sharing of
this memory. Reading time in a userspace task is therefore just a matter
of reading memory.</para>
 
<para>There are two interesting points about this. First, the counters are
32-bit even on 64-bit machines. The goal is to provide subsecond precision
with the possibility to span roughly 136 years. Note that a single 64-bit
microsecond counter could not be usually read atomically on 32-bit
platforms. Now the second point is that 32-bit platforms cannot atomically
read two 32-bit counters either. However, a generic protocol is used to
guarantee that sequentially read times will create a non-decreasing
sequence.</para>
 
<para>The problematic part is updating both seconds and microseconds once
in a second. Seconds must be incremented and microseconds must be reset.
However, without any synchronization, the two kernel stores and the two
userspace reads can arbitrarily interleave. Furthemore, the reader has no
chance to detect that the counters were updated only from half. Therefore
three counters are used in HelenOS.</para>
 
<para>If seconds need to be updated, the kernel increments the first
second counter, issues a write memory barrier operation, updates the
microsecond counter, issues another write memory barrier operation and
increments the second second counter. When only microseconds need to be
updated, no special action is taken by the kernel. On the other hand, the
userspace task must always read all three counters and in reversed order.
A read memory barrier operation must be issued between each two reads. A
non-atomic read is detected when the two second counters differ. The
userspace library solves this situation by returning zero instead of the
value read from the microsecond counter.</para>
</section>
</chapter>