144,11 → 144,11 |
<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> |
order to read the system time. Instead, a mechanism that shares kernel |
time of the 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> |
165,36 → 165,37 |
</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> |
ns) asks the kernel to map this frame into its address space. Other |
non-privileged tasks then use IPC to receive read-only share 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> |
platforms. Unfortunately, on 32-bit platforms it is usually impossible to |
read atomically 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>The problematic part is incrementing seconds counter and clearing |
microseconds counter together once every 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 paritally. 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 |
increments the second second counter. When only microseconds needs 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 |
userspace task must always read all three counters 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> |
userspace library solves this situation by returning higher of them with |
microseconds set to zero.</para> |
</section> |
</chapter> |