SimpleOS

LXR

Navigation



Site hébergé par : enix

The LXR Cross Referencer for SOS

source navigation ]
diff markup ]
identifier search ]
general search ]
 
 
Article:1 ] [ 2 ] [ 3 ] [ 4 ] [ 5 ] [ 6 ] [ 6.5 ] [ 7 ] [ 7.5 ] [ 8 ] [ 9 ] [ 9.5 ]

Diff markup

Differences between /sos/time.c (Article 7.5) and /sos/time.c (Article 7)


001 /* Copyright (C) 2004 David Decotigny             001 /* Copyright (C) 2004 David Decotigny
002                                                   002 
003    This program is free software; you can redi    003    This program is free software; you can redistribute it and/or
004    modify it under the terms of the GNU Genera    004    modify it under the terms of the GNU General Public License
005    as published by the Free Software Foundatio    005    as published by the Free Software Foundation; either version 2
006    of the License, or (at your option) any lat    006    of the License, or (at your option) any later version.
007                                                   007    
008    This program is distributed in the hope tha    008    This program is distributed in the hope that it will be useful,
009    but WITHOUT ANY WARRANTY; without even the     009    but WITHOUT ANY WARRANTY; without even the implied warranty of
010    MERCHANTABILITY or FITNESS FOR A PARTICULAR    010    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
011    GNU General Public License for more details    011    GNU General Public License for more details.
012                                                   012    
013    You should have received a copy of the GNU     013    You should have received a copy of the GNU General Public License
014    along with this program; if not, write to t    014    along with this program; if not, write to the Free Software
015    Foundation, Inc., 59 Temple Place - Suite 3    015    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
016    USA.                                           016    USA. 
017 */                                                017 */
018                                                   018 
019 #include <sos/assert.h>                           019 #include <sos/assert.h>
020 #include <sos/klibc.h>                            020 #include <sos/klibc.h>
021 #include <hwcore/irq.h>                           021 #include <hwcore/irq.h>
022 #include <sos/list.h>                             022 #include <sos/list.h>
023                                                   023 
024 #include "time.h"                                 024 #include "time.h"
025                                                   025 
026                                                   026 
027 /**                                               027 /**
028  * Number of nanoseconds in 1 second              028  * Number of nanoseconds in 1 second
029  */                                               029  */
030 #define NS_IN_SEC 1000000000UL                    030 #define NS_IN_SEC 1000000000UL
031                                                   031 
032                                                   032 
033 /**                                               033 /**
034  * The list of timeout actions waiting for a t    034  * The list of timeout actions waiting for a timeout. The timeout
035  * actions are stored in the list in increasin    035  * actions are stored in the list in increasing initial timeout
036  * order. Actually, the "timeout" field won't     036  * order. Actually, the "timeout" field won't reflect this initial
037  * timeout: for each element in the list, it s    037  * timeout: for each element in the list, it stores the timeout
038  * _difference_ between the timeout action and    038  * _difference_ between the timeout action and the previous in the
039  * list.                                          039  * list.
040  */                                               040  */
041 static struct sos_timeout_action *timeout_acti    041 static struct sos_timeout_action *timeout_action_list;
042                                                   042 
043                                                   043 
044 /**                                               044 /**
045  * Current resolution of a time tick              045  * Current resolution of a time tick
046  */                                               046  */
047 static struct sos_time tick_resolution;           047 static struct sos_time tick_resolution;
048                                                   048 
049                                                   049 
050 /**                                               050 /**
051  * Time elapsed between boot and last timer ti    051  * Time elapsed between boot and last timer tick
052  *                                                052  *
053  * @note No 'volatile' here because the tick v    053  * @note No 'volatile' here because the tick value is NEVER modified
054  * while in any of the functions below: it is     054  * while in any of the functions below: it is modified only out of
055  * these functions by the IRQ timer handler be    055  * these functions by the IRQ timer handler because these functions
056  * are protected against timer IRQ and are "on    056  * are protected against timer IRQ and are "one shot" (no busy waiting
057  * for a change in the tick's value).             057  * for a change in the tick's value).
058  */                                               058  */
059 static struct sos_time last_tick_time;            059 static struct sos_time last_tick_time;
060                                                   060 
061                                                   061 
062 sos_ret_t sos_time_inc(struct sos_time *dest,     062 sos_ret_t sos_time_inc(struct sos_time *dest,
063                        const struct sos_time *    063                        const struct sos_time *to_add)
064 {                                                 064 {
065   /* nanosec is always < 1e9 so that their sum    065   /* nanosec is always < 1e9 so that their sum is always < 2e9, which
066      is smaller than 2^32-1 */                    066      is smaller than 2^32-1 */
067   sos_ui32_t sigma_ns = dest->nanosec + to_add    067   sos_ui32_t sigma_ns = dest->nanosec + to_add->nanosec;
068                                                   068   
069   dest->sec     += to_add->sec;                   069   dest->sec     += to_add->sec;
070   dest->sec     += sigma_ns / NS_IN_SEC;          070   dest->sec     += sigma_ns / NS_IN_SEC;
071   dest->nanosec  = sigma_ns % NS_IN_SEC;          071   dest->nanosec  = sigma_ns % NS_IN_SEC;
072   return SOS_OK;                                  072   return SOS_OK;
073 }                                                 073 }
074                                                   074 
075                                                   075 
076 sos_ret_t sos_time_dec(struct sos_time *dest,     076 sos_ret_t sos_time_dec(struct sos_time *dest,
077                        const struct sos_time *    077                        const struct sos_time *to_dec)
078 {                                                 078 {
079   /* nanosec is always < 1e9 so that their dif    079   /* nanosec is always < 1e9 so that their difference is always in
080      (-1e9, 1e9), which is compatible with the    080      (-1e9, 1e9), which is compatible with the (-2^31, 2^31 - 1)
081      cpacity of a signed dword */                 081      cpacity of a signed dword */
082   sos_si32_t diff_ns = ((sos_si32_t)dest->nano    082   sos_si32_t diff_ns = ((sos_si32_t)dest->nanosec)
083                         - ((sos_si32_t)to_dec-    083                         - ((sos_si32_t)to_dec->nanosec);
084                                                   084 
085   /* Make sure substraction is possible */        085   /* Make sure substraction is possible */
086   SOS_ASSERT_FATAL(dest->sec >= to_dec->sec);     086   SOS_ASSERT_FATAL(dest->sec >= to_dec->sec);
087   if (dest->sec == to_dec->sec)                   087   if (dest->sec == to_dec->sec)
088     SOS_ASSERT_FATAL(dest->nanosec >= to_dec->    088     SOS_ASSERT_FATAL(dest->nanosec >= to_dec->nanosec);
089                                                   089 
090   dest->sec     -= to_dec->sec;                   090   dest->sec     -= to_dec->sec;
091   if (diff_ns > 0)                                091   if (diff_ns > 0)
092     dest->sec     += diff_ns / NS_IN_SEC;         092     dest->sec     += diff_ns / NS_IN_SEC;
093   else                                            093   else
094     dest->sec     -= ((-diff_ns) / NS_IN_SEC);    094     dest->sec     -= ((-diff_ns) / NS_IN_SEC);
095   dest->nanosec  = (NS_IN_SEC + diff_ns) % NS_    095   dest->nanosec  = (NS_IN_SEC + diff_ns) % NS_IN_SEC;
096   if (diff_ns < 0)                                096   if (diff_ns < 0)
097     dest->sec --;                                 097     dest->sec --;
098   return SOS_OK;                                  098   return SOS_OK;
099 }                                                 099 }
100                                                   100 
101                                                   101 
102 int sos_time_cmp(const struct sos_time *t1,       102 int sos_time_cmp(const struct sos_time *t1,
103                  const struct sos_time *t2)       103                  const struct sos_time *t2)
104 {                                                 104 {
105   /* Compare seconds */                           105   /* Compare seconds */
106   if (t1->sec < t2->sec)                          106   if (t1->sec < t2->sec)
107     return -1;                                    107     return -1;
108   else if (t1->sec > t2->sec)                     108   else if (t1->sec > t2->sec)
109     return 1;                                     109     return 1;
110                                                   110 
111   /* seconds are equal => compare nanoseconds     111   /* seconds are equal => compare nanoseconds */
112   else if (t1->nanosec < t2->nanosec)             112   else if (t1->nanosec < t2->nanosec)
113     return -1;                                    113     return -1;
114   else if (t1->nanosec > t2->nanosec)             114   else if (t1->nanosec > t2->nanosec)
115     return 1;                                     115     return 1;
116                                                   116 
117   /* else: sec and nanosecs are equal */          117   /* else: sec and nanosecs are equal */
118   return 0;                                       118   return 0;
119 }                                                 119 }
120                                                   120 
121                                                   121 
122 sos_bool_t sos_time_is_zero(const struct sos_t    122 sos_bool_t sos_time_is_zero(const struct sos_time *tm)
123 {                                                 123 {
124   return ( (0 == tm->sec) && (0 == tm->nanosec    124   return ( (0 == tm->sec) && (0 == tm->nanosec) );
125 }                                                 125 }
126                                                   126 
127                                                   127 
128 sos_ret_t sos_time_subsysem_setup(const struct    128 sos_ret_t sos_time_subsysem_setup(const struct sos_time *initial_resolution)
129 {                                                 129 {
130   timeout_action_list = NULL;                     130   timeout_action_list = NULL;
131   last_tick_time = (struct sos_time) { .sec =     131   last_tick_time = (struct sos_time) { .sec = 0, .nanosec = 0 };
132   memcpy(& tick_resolution, initial_resolution    132   memcpy(& tick_resolution, initial_resolution, sizeof(struct sos_time));
133                                                   133 
134   return SOS_OK;                                  134   return SOS_OK;
135 }                                                 135 }
136                                                   136 
137                                                   137 
138 sos_ret_t sos_time_get_tick_resolution(struct     138 sos_ret_t sos_time_get_tick_resolution(struct sos_time *resolution)
139 {                                                 139 {
140   sos_ui32_t flags;                               140   sos_ui32_t flags;
141   sos_disable_IRQs(flags);                        141   sos_disable_IRQs(flags);
142                                                   142 
143   memcpy(resolution, & tick_resolution, sizeof    143   memcpy(resolution, & tick_resolution, sizeof(struct sos_time));
144                                                   144 
145   sos_restore_IRQs(flags);                        145   sos_restore_IRQs(flags);
146   return SOS_OK;                                  146   return SOS_OK; 
147 }                                                 147 }
148                                                   148 
149                                                   149 
150 sos_ret_t sos_time_set_tick_resolution(const s    150 sos_ret_t sos_time_set_tick_resolution(const struct sos_time *resolution)
151 {                                                 151 {
152   sos_ui32_t flags;                               152   sos_ui32_t flags;
153                                                   153 
154   sos_disable_IRQs(flags);                        154   sos_disable_IRQs(flags);
155   memcpy(& tick_resolution, resolution, sizeof    155   memcpy(& tick_resolution, resolution, sizeof(struct sos_time));
156   sos_restore_IRQs(flags);                        156   sos_restore_IRQs(flags);
157                                                   157 
158   return SOS_OK;                                  158   return SOS_OK;
159 }                                                 159 }
160                                                   160 
161                                                   161 
162 sos_ret_t sos_time_get_now(struct sos_time *no    162 sos_ret_t sos_time_get_now(struct sos_time *now)
163 {                                                 163 {
164   sos_ui32_t flags;                               164   sos_ui32_t flags;
165   sos_disable_IRQs(flags);                        165   sos_disable_IRQs(flags);
166                                                   166 
167   memcpy(now, & last_tick_time, sizeof(struct     167   memcpy(now, & last_tick_time, sizeof(struct sos_time));
168                                                   168 
169   sos_restore_IRQs(flags);                        169   sos_restore_IRQs(flags);
170   return SOS_OK;                                  170   return SOS_OK;  
171 }                                                 171 }
172                                                   172 
173                                                   173 
174 /**                                               174 /**
175  * Helper routine to add the action in the lis    175  * Helper routine to add the action in the list. MUST be called with
176  * interrupts disabled !                          176  * interrupts disabled !
177  */                                               177  */
178 static sos_ret_t _add_action(struct sos_timeou    178 static sos_ret_t _add_action(struct sos_timeout_action *act,
179                              const struct sos_    179                              const struct sos_time *due_date,
180                              sos_bool_t is_rel    180                              sos_bool_t is_relative_due_date,
181                              sos_timeout_routi    181                              sos_timeout_routine_t *routine,
182                              void *routine_dat    182                              void *routine_data)
183 {                                                 183 {
184   struct sos_timeout_action *other, *insert_be    184   struct sos_timeout_action *other, *insert_before;
185   int nb_act;                                     185   int nb_act;
186                                                   186 
187   /* Delay must be specified */                   187   /* Delay must be specified */
188   if (due_date == NULL)                           188   if (due_date == NULL)
189     return -SOS_EINVAL;                           189     return -SOS_EINVAL;
190                                                   190 
191   /* Action container MUST be specified */        191   /* Action container MUST be specified */
192   if (act == NULL)                                192   if (act == NULL)
193     return -SOS_EINVAL;                           193     return -SOS_EINVAL;
194                                                   194 
195   /* Refuse to add an empty action */             195   /* Refuse to add an empty action */
196   if (NULL == routine)                            196   if (NULL == routine)
197     return -SOS_EINVAL;                           197     return -SOS_EINVAL;
198                                                   198 
199   /* Refuse to add the action if it is already    199   /* Refuse to add the action if it is already added */
200   if (NULL != act->tmo_next)                      200   if (NULL != act->tmo_next)
201     return -SOS_EBUSY;                            201     return -SOS_EBUSY;
202                                                   202 
203   /* Compute action absolute due date */          203   /* Compute action absolute due date */
204   if (is_relative_due_date)                       204   if (is_relative_due_date)
205     {                                             205     {
206       /* The provided due_date is relative to     206       /* The provided due_date is relative to the current time */
207       memcpy(& act->timeout, & last_tick_time,    207       memcpy(& act->timeout, & last_tick_time, sizeof(struct sos_time));
208       sos_time_inc(& act->timeout, due_date);     208       sos_time_inc(& act->timeout, due_date);
209     }                                             209     }
210   else                                            210   else
211     {                                             211     {
212       /* The provided due_date is absolute (ie    212       /* The provided due_date is absolute (ie relative to the system
213          boot instant) */                         213          boot instant) */
214                                                   214 
215       if (sos_time_cmp(due_date, & last_tick_t    215       if (sos_time_cmp(due_date, & last_tick_time) < 0)
216         /* Refuse to add a past action ! */       216         /* Refuse to add a past action ! */
217         return -SOS_EINVAL;                       217         return -SOS_EINVAL;
218                                                   218 
219       memcpy(& act->timeout, due_date, sizeof(    219       memcpy(& act->timeout, due_date, sizeof(struct sos_time));
220     }                                             220     }    
221                                                   221 
222   /* Prepare the action data structure */         222   /* Prepare the action data structure */
223   act->routine      = routine;                    223   act->routine      = routine;
224   act->routine_data = routine_data;               224   act->routine_data = routine_data;
225                                                   225 
226   /* Find the right place in the list of the t    226   /* Find the right place in the list of the timeout action. */
227   insert_before = NULL;                           227   insert_before = NULL;
228   list_foreach_forward_named(timeout_action_li    228   list_foreach_forward_named(timeout_action_list,
229                              other, nb_act,       229                              other, nb_act,
230                              tmo_prev, tmo_nex    230                              tmo_prev, tmo_next)
231     {                                             231     {
232       if (sos_time_cmp(& act->timeout, & other    232       if (sos_time_cmp(& act->timeout, & other->timeout) < 0)
233         {                                         233         {
234           insert_before = other;                  234           insert_before = other;
235           break;                                  235           break;
236         }                                         236         }
237                                                   237 
238       /* Loop over to next timeout */             238       /* Loop over to next timeout */
239     }                                             239     }
240                                                   240 
241   /* Now insert the action in the list */         241   /* Now insert the action in the list */
242   if (insert_before != NULL)                      242   if (insert_before != NULL)
243     list_insert_before_named(timeout_action_li    243     list_insert_before_named(timeout_action_list, insert_before, act,
244                             tmo_prev, tmo_next    244                             tmo_prev, tmo_next);
245   else                                            245   else
246     list_add_tail_named(timeout_action_list, a    246     list_add_tail_named(timeout_action_list, act,
247                         tmo_prev, tmo_next);      247                         tmo_prev, tmo_next);
248                                                   248 
249   return SOS_OK;                                  249   return SOS_OK;  
250 }                                                 250 }
251                                                   251 
252                                                   252 
253 sos_ret_t                                         253 sos_ret_t
254 sos_time_register_action_relative(struct sos_t    254 sos_time_register_action_relative(struct sos_timeout_action *act,
255                                   const struct    255                                   const struct sos_time *delay,
256                                   sos_timeout_    256                                   sos_timeout_routine_t *routine,
257                                   void *routin    257                                   void *routine_data)
258 {                                                 258 {
259   sos_ui32_t flags;                               259   sos_ui32_t flags;
260   sos_ret_t retval;                               260   sos_ret_t retval;
261                                                   261 
262   sos_disable_IRQs(flags);                        262   sos_disable_IRQs(flags);
263   retval = _add_action(act, delay, TRUE, routi    263   retval = _add_action(act, delay, TRUE, routine, routine_data);
264   sos_restore_IRQs(flags);                        264   sos_restore_IRQs(flags);
265                                                   265 
266   return retval;                                  266   return retval;
267 }                                                 267 }
268                                                   268 
269                                                   269 
270 sos_ret_t                                         270 sos_ret_t
271 sos_time_register_action_absolute(struct sos_t    271 sos_time_register_action_absolute(struct sos_timeout_action *act,
272                                   const struct    272                                   const struct sos_time *date,
273                                   sos_timeout_    273                                   sos_timeout_routine_t *routine,
274                                   void *routin    274                                   void *routine_data)
275 {                                                 275 {
276   sos_ui32_t flags;                               276   sos_ui32_t flags;
277   sos_ret_t retval;                               277   sos_ret_t retval;
278                                                   278 
279   sos_disable_IRQs(flags);                        279   sos_disable_IRQs(flags);
280   retval = _add_action(act, date, FALSE, routi    280   retval = _add_action(act, date, FALSE, routine, routine_data);
281   sos_restore_IRQs(flags);                        281   sos_restore_IRQs(flags);
282                                                   282 
283   return retval;                                  283   return retval;
284 }                                                 284 }
285                                                   285 
286                                                   286 
287 /**                                               287 /**
288  * Helper routine to remove the action from th    288  * Helper routine to remove the action from the list. MUST be called
289  * with interrupts disabled !                     289  * with interrupts disabled !
290  */                                               290  */
291 static sos_ret_t _remove_action(struct sos_tim    291 static sos_ret_t _remove_action(struct sos_timeout_action *act)
292 {                                                 292 {
293   /* Don't do anything if action is not in tim    293   /* Don't do anything if action is not in timeout list */
294   if (NULL == act->tmo_next)                      294   if (NULL == act->tmo_next)
295     return -SOS_EINVAL;                           295     return -SOS_EINVAL;
296                                                   296 
297   /* Update the action's remaining timeout */     297   /* Update the action's remaining timeout */
298   if (sos_time_cmp(& act->timeout, & last_tick    298   if (sos_time_cmp(& act->timeout, & last_tick_time) <= 0)
299     act->timeout = (struct sos_time){ .sec=0,     299     act->timeout = (struct sos_time){ .sec=0, .nanosec=0 };
300   else                                            300   else
301     sos_time_dec(& act->timeout, & last_tick_t    301     sos_time_dec(& act->timeout, & last_tick_time);
302                                                   302 
303   /* Actually remove the action from the list     303   /* Actually remove the action from the list */
304   list_delete_named(timeout_action_list, act,     304   list_delete_named(timeout_action_list, act,
305                     tmo_prev, tmo_next);          305                     tmo_prev, tmo_next);
306   act->tmo_prev = act->tmo_next = NULL;           306   act->tmo_prev = act->tmo_next = NULL;
307                                                   307 
308   return SOS_OK;                                  308   return SOS_OK;  
309 }                                                 309 }
310                                                   310 
311                                                   311 
312 sos_ret_t sos_time_unregister_action(struct so    312 sos_ret_t sos_time_unregister_action(struct sos_timeout_action *act)
313 {                                                 313 {
314   sos_ret_t retval;                               314   sos_ret_t retval;
315   sos_ui32_t flags;                               315   sos_ui32_t flags;
316                                                   316 
317   sos_disable_IRQs(flags);                        317   sos_disable_IRQs(flags);
318   retval = _remove_action(act);                   318   retval = _remove_action(act);
319   sos_restore_IRQs(flags);                        319   sos_restore_IRQs(flags);
320                                                   320 
321   return SOS_OK;                                  321   return SOS_OK;  
322 }                                                 322 }
323                                                   323 
324                                                   324 
325 sos_ret_t sos_time_do_tick()                      325 sos_ret_t sos_time_do_tick()
326 {                                                 326 {
327   sos_ui32_t flags;                               327   sos_ui32_t flags;
328                                                   328   
329   sos_disable_IRQs(flags);                        329   sos_disable_IRQs(flags);
330                                                   330 
331   /* Update kernel time */                        331   /* Update kernel time */
332   sos_time_inc(& last_tick_time, & tick_resolu    332   sos_time_inc(& last_tick_time, & tick_resolution);
333                                                   333 
334   while (! list_is_empty_named(timeout_action_    334   while (! list_is_empty_named(timeout_action_list, tmo_prev, tmo_next))
335     {                                             335     {
336       struct sos_timeout_action *act;             336       struct sos_timeout_action *act;
337       act = list_get_head_named(timeout_action    337       act = list_get_head_named(timeout_action_list, tmo_prev, tmo_next);
338                                                   338 
339       /* Did we go too far in the actions' lis    339       /* Did we go too far in the actions' list ? */
340       if (sos_time_cmp(& last_tick_time, & act    340       if (sos_time_cmp(& last_tick_time, & act->timeout) < 0)
341         {                                         341         {
342           /* Yes: No need to look further. */     342           /* Yes: No need to look further. */
343           break;                                  343           break;
344         }                                         344         }
345                                                   345 
346       /* Remove the action from the list */       346       /* Remove the action from the list */
347       _remove_action(act);                        347       _remove_action(act);
348                                                   348 
349       /* Call the action's routine */             349       /* Call the action's routine */
350       act->routine(act);                          350       act->routine(act);
351     }                                             351     }
352                                                   352 
353   sos_restore_IRQs(flags);                        353   sos_restore_IRQs(flags);
354   return SOS_OK;                                  354   return SOS_OK;
355 }                                                 355 }
                                                      

source navigation ] diff markup ] identifier search ] general search ]