Rev 58 | Rev 127 | Go to most recent revision | Show entire file | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed
| Rev 58 | Rev 85 | ||
|---|---|---|---|
| Line 142... | Line 142... | ||
| 142 | 142 | ||
| 143 | <section> |
143 | <section> |
| 144 | <title>Time source for userspace</title> |
144 | <title>Time source for userspace</title> |
| 145 | 145 | ||
| 146 | <para>In HelenOS, userspace tasks don't communicate with the kernel in |
146 | <para>In HelenOS, userspace tasks don't communicate with the kernel in |
| 147 | order to read system time. Instead, a mechanism that shares kernel time of |
147 | order to read the system time. Instead, a mechanism that shares kernel |
| 148 | the day counters with userspace address spaces is deployed. On the kernel |
148 | time of the the day counters with userspace address spaces is deployed. On |
| 149 | side, during system initialization, HelenOS allocates a frame of physical |
149 | the kernel side, during system initialization, HelenOS allocates a frame |
| 150 | memory and stores the time of the day counters there. The counters have |
150 | of physical memory and stores the time of the day counters there. The |
| 151 | the following structure:</para> |
151 | counters have the following structure:</para> |
| 152 | 152 | ||
| 153 | <itemizedlist> |
153 | <itemizedlist> |
| 154 | <listitem> |
154 | <listitem> |
| 155 | <para>first 32-bit counter for seconds,</para> |
155 | <para>first 32-bit counter for seconds,</para> |
| 156 | </listitem> |
156 | </listitem> |
| Line 163... | Line 163... | ||
| 163 | <para>second 32-bit counter for seconds.</para> |
163 | <para>second 32-bit counter for seconds.</para> |
| 164 | </listitem> |
164 | </listitem> |
| 165 | </itemizedlist> |
165 | </itemizedlist> |
| 166 | 166 | ||
| 167 | <para>One of the userspace tasks with capabilities of memory manager (e.g. |
167 | <para>One of the userspace tasks with capabilities of memory manager (e.g. |
| 168 | ns) asks the kernel to map this frame into its address space. Other, |
168 | ns) asks the kernel to map this frame into its address space. Other |
| 169 | non-privileged, tasks then use IPC to communicate read-only sharing of |
169 | non-privileged tasks then use IPC to receive read-only share of this |
| 170 | this memory. Reading time in a userspace task is therefore just a matter |
170 | memory. Reading time in a userspace task is therefore just a matter of |
| 171 | of reading memory.</para> |
171 | reading memory.</para> |
| 172 | 172 | ||
| 173 | <para>There are two interesting points about this. First, the counters are |
173 | <para>There are two interesting points about this. First, the counters are |
| 174 | 32-bit even on 64-bit machines. The goal is to provide subsecond precision |
174 | 32-bit even on 64-bit machines. The goal is to provide subsecond precision |
| 175 | with the possibility to span roughly 136 years. Note that a single 64-bit |
175 | with the possibility to span roughly 136 years. Note that a single 64-bit |
| 176 | microsecond counter could not be usually read atomically on 32-bit |
176 | microsecond counter could not be usually read atomically on 32-bit |
| 177 | platforms. Now the second point is that 32-bit platforms cannot atomically |
177 | platforms. Unfortunately, on 32-bit platforms it is usually impossible to |
| 178 | read two 32-bit counters either. However, a generic protocol is used to |
178 | read atomically two 32-bit counters either. However, a generic protocol is |
| 179 | guarantee that sequentially read times will create a non-decreasing |
179 | used to guarantee that sequentially read times will create a |
| 180 | sequence.</para> |
180 | non-decreasing sequence.</para> |
| 181 | 181 | ||
| 182 | <para>The problematic part is updating both seconds and microseconds once |
182 | <para>The problematic part is incrementing seconds counter and clearing |
| 183 | in a second. Seconds must be incremented and microseconds must be reset. |
183 | microseconds counter together once every second. Seconds must be |
| - | 184 | incremented and microseconds must be reset. However, without any |
|
| 184 | However, without any synchronization, the two kernel stores and the two |
185 | synchronization, the two kernel stores and the two userspace reads can |
| 185 | userspace reads can arbitrarily interleave. Furthemore, the reader has no |
186 | arbitrarily interleave. Furthemore, the reader has no chance to detect |
| 186 | chance to detect that the counters were updated only from half. Therefore |
187 | that the counters were updated only paritally. Therefore three counters |
| 187 | three counters are used in HelenOS.</para> |
188 | are used in HelenOS.</para> |
| 188 | 189 | ||
| 189 | <para>If seconds need to be updated, the kernel increments the first |
190 | <para>If seconds need to be updated, the kernel increments the first |
| 190 | second counter, issues a write memory barrier operation, updates the |
191 | second counter, issues a write memory barrier operation, updates the |
| 191 | microsecond counter, issues another write memory barrier operation and |
192 | microsecond counter, issues another write memory barrier operation and |
| 192 | increments the second second counter. When only microseconds need to be |
193 | increments the second second counter. When only microseconds needs to be |
| 193 | updated, no special action is taken by the kernel. On the other hand, the |
194 | updated, no special action is taken by the kernel. On the other hand, the |
| 194 | userspace task must always read all three counters and in reversed order. |
195 | userspace task must always read all three counters in reversed order. A |
| 195 | A read memory barrier operation must be issued between each two reads. A |
196 | read memory barrier operation must be issued between each two reads. A |
| 196 | non-atomic read is detected when the two second counters differ. The |
197 | non-atomic read is detected when the two second counters differ. The |
| 197 | userspace library solves this situation by returning zero instead of the |
198 | userspace library solves this situation by returning higher of them with |
| 198 | value read from the microsecond counter.</para> |
199 | microseconds set to zero.</para> |
| 199 | </section> |
200 | </section> |
| 200 | </chapter> |
201 | </chapter> |
| 201 | 202 | ||