]> rtime.felk.cvut.cz Git - frescor/fosa.git/blob - include/fosa_time_timespec.h
Updating header text in FOSA files for the incoming final project
[frescor/fosa.git] / include / fosa_time_timespec.h
1 // -----------------------------------------------------------------------
2 //  Copyright (C) 2006 - 2009 FRESCOR consortium partners:
3 //
4 //    Universidad de Cantabria,              SPAIN
5 //    University of York,                    UK
6 //    Scuola Superiore Sant'Anna,            ITALY
7 //    Kaiserslautern University,             GERMANY
8 //    Univ. Politécnica  Valencia,           SPAIN
9 //    Czech Technical University in Prague,  CZECH REPUBLIC
10 //    ENEA                                   SWEDEN
11 //    Thales Communication S.A.              FRANCE
12 //    Visual Tools S.A.                      SPAIN
13 //    Rapita Systems Ltd                     UK
14 //    Evidence                               ITALY
15 //
16 //    See http://www.frescor.org for a link to partners' websites
17 //
18 //           FRESCOR project (FP6/2005/IST/5-034026) is funded
19 //        in part by the European Union Sixth Framework Programme
20 //        The European Union is not liable of any use that may be
21 //        made of this code.
22 //
23 //
24 //  based on previous work (FSF) done in the FIRST project
25 //
26 //   Copyright (C) 2005  Mälardalen University, SWEDEN
27 //                       Scuola Superiore S.Anna, ITALY
28 //                       Universidad de Cantabria, SPAIN
29 //                       University of York, UK
30 //
31 //   FSF API web pages: http://marte.unican.es/fsf/docs
32 //                      http://shark.sssup.it/contrib/first/docs/
33 //
34 //   This file is part of FOSA (Frsh Operating System Adaption)
35 //
36 //  FOSA is free software; you can redistribute it and/or modify it
37 //  under terms of the GNU General Public License as published by the
38 //  Free Software Foundation; either version 2, or (at your option) any
39 //  later version.  FOSA is distributed in the hope that it will be
40 //  useful, but WITHOUT ANY WARRANTY; without even the implied warranty
41 //  of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
42 //  General Public License for more details. You should have received a
43 //  copy of the GNU General Public License along with FOSA; see file
44 //  COPYING. If not, write to the Free Software Foundation, 675 Mass Ave,
45 //  Cambridge, MA 02139, USA.
46 //
47 //  As a special exception, including FOSA header files in a file,
48 //  instantiating FOSA generics or templates, or linking other files
49 //  with FOSA objects to produce an executable application, does not
50 //  by itself cause the resulting executable application to be covered
51 //  by the GNU General Public License. This exception does not
52 //  however invalidate any other reasons why the executable file might be
53 //  covered by the GNU Public License.
54 // -----------------------------------------------------------------------
55 //fosa_time_timespec.h
56 //==============================================
57 //  ********  ******    ********  **********
58 //  **///// /**    **  **//////  /**     /**
59 //  **      /**    ** /**        /**     /**
60 //  ******* /**    ** /********* /**********
61 //  **////  /**    ** ////////** /**//////**
62 //  **      /**    **        /** /**     /**
63 //  **      /**    **  ********  /**     /**
64 //  //       /******/  ////////   //      //
65 //
66 // FOSA(Frescor Operating System Adaptation layer)
67 //================================================
68 #ifndef         FOSA_TIME_TIMESPEC_H_
69 #define         FOSA_TIME_TIMESPEC_H_
70
71 #include <stdlib.h>
72 #include <assert.h>
73
74 /**********************************/
75 /* T I M E S P E C   M A C R O S  */
76 /**********************************/
77
78 #define normalize_timespec(t1) \
79 do \
80 { \
81     if ((t1).tv_nsec >= 1000000000) \
82     { \
83         (t1).tv_sec++; \
84         (t1).tv_nsec -= 1000000000; \
85     } \
86 } while(0)
87
88 #define add_timespec(sum, t1, t2) \
89 do { \
90     (sum).tv_sec = (t1).tv_sec + (t2).tv_sec; \
91     (sum).tv_nsec = (t1).tv_nsec + (t2).tv_nsec; \
92     normalize_timespec(sum); \
93 } while(0)
94
95 #define incr_timespec(t1, t2) \
96 do { \
97         (t1).tv_sec += (t2).tv_sec; \
98         (t1).tv_nsec += (t2).tv_nsec; \
99         normalize_timespec(t1); \
100 } while(0)
101
102 // -------------------------------------------------------------------
103
104 /* TODO:  Test that for past > future we obtain a correct negative
105  * interval */
106 #define substract_timespec(diff, base, interval) \
107 do { \
108     if ((base).tv_nsec < (interval).tv_nsec) \
109     { \
110         (diff).tv_sec = (base).tv_sec - (interval).tv_sec - 1; \
111         (diff).tv_nsec = (base).tv_nsec + 1000000000 - (interval).tv_nsec; \
112     } \
113     else \
114     { \
115         (diff).tv_sec = (base).tv_sec - (interval).tv_sec; \
116         (diff).tv_nsec = (base).tv_nsec - (interval).tv_nsec; \
117     } \
118 } while(0)
119
120
121 // ---------------------------------------------------------
122
123 #define smaller_timespec(t1, t2) \
124    ((t1).tv_sec < (t2).tv_sec || ((t1).tv_sec == (t2).tv_sec && (t1).tv_nsec < (t2).tv_nsec) )
125
126 // ---------------------------------------------------------
127
128 #define smaller_or_equal_timespec(t1, t2) \
129    ((t1).tv_sec < (t2).tv_sec || ((t1).tv_sec == (t2).tv_sec && (t1).tv_nsec <= (t2).tv_nsec) )
130
131 // ---------------------------------------------------------
132
133 #define msec_to_timespec(tspec, msec) \
134 do { \
135     if ((msec) >= 1000) { \
136         (tspec).tv_sec = (msec)/1000; \
137         (tspec).tv_nsec = ((msec) % 1000) * 1000000; \
138     } else { \
139         (tspec).tv_sec = 0; \
140         (tspec).tv_nsec = (msec) * 1000000; \
141     } \
142 } while (0)
143
144 // ---------------------------------------------------------
145
146 #define timespec_to_msec(t1) \
147    ( ((t1).tv_sec % 2147482) * 1000 + (t1).tv_nsec/1000000 )
148
149
150 // ---------------------------------------------------------
151
152 #define usec_to_timespec(tspec, usec) \
153 do { \
154     if ((usec) >= 1000000) { \
155         (tspec).tv_sec = (usec)/1000000; \
156         (tspec).tv_nsec = ((usec) % 1000000) * 1000; \
157     } else { \
158         (tspec).tv_sec = 0; \
159         (tspec).tv_nsec = (usec) * 1000; \
160     } \
161 } while(0)
162
163 // ---------------------------------------------------------
164
165 #define timespec_to_usec(t1) \
166    ( ((t1).tv_sec % 2148) * 1000000 + (t1).tv_nsec/1000 )
167
168
169 // ---------------------------------------------------------
170
171 #define nsec_to_timespec(tspec, nsec) \
172 do { \
173     if ((nsec) >= 1000000000) { \
174         (tspec).tv_sec = (nsec)/1000000000; \
175         (tspec).tv_nsec = (nsec) % 1000000000; \
176     } else { \
177         (tspec).tv_sec = 0; \
178         (tspec).tv_nsec = (nsec); \
179     } \
180 } while(0)
181
182 // ---------------------------------------------------------
183
184 #define timespec_to_nsec(t1) \
185    ( ((t1).tv_sec % 2) * 1000000000 + (t1).tv_nsec )
186
187
188
189 // ---------------------------------------------------------
190
191 #define timespec_equal(t1, t2) ( (t1).tv_sec == (t2).tv_sec ) && ( (t1).tv_nsec == (t2).tv_nsec )
192
193 #define timespec_is_null(t1) ( (t1).tv_sec == 0 ) && ( (t1).tv_nsec == 0 )
194
195
196
197 /***************************************/
198 /* T I M E S P E C   F U N C T I O N S */
199 /***************************************/
200
201
202 static inline fosa_abs_time_t fosa_abs_time_incr(fosa_abs_time_t base, fosa_rel_time_t interval)
203 {
204     fosa_abs_time_t result;
205
206     add_timespec(result, base, interval);
207
208     return result;
209 }
210
211
212 // ---------------------------------------------------------
213
214 static inline fosa_abs_time_t fosa_abs_time_decr(fosa_abs_time_t base, fosa_rel_time_t interval)
215 {
216     fosa_abs_time_t result;
217
218     substract_timespec(result, base, interval);
219
220     return result;
221 }
222
223
224
225 // ---------------------------------------------------------
226
227 static inline fosa_rel_time_t fosa_abs_time_extract_interval(fosa_abs_time_t past, fosa_abs_time_t future)
228 {
229     fosa_rel_time_t result;
230
231     substract_timespec(result, future, past);
232
233     return result;
234 }
235
236
237 // ---------------------------------------------------------
238
239 static inline fosa_rel_time_t fosa_rel_time_add(fosa_rel_time_t relt1, fosa_rel_time_t relt2)
240 {
241     fosa_rel_time_t result;
242
243     add_timespec(result, relt1, relt2);
244
245     return result;
246 }
247
248
249 // ---------------------------------------------------------
250
251 static inline fosa_rel_time_t fosa_rel_time_decr(fosa_rel_time_t total, fosa_rel_time_t part)
252 {
253     fosa_rel_time_t result;
254
255     substract_timespec(result, total, part);
256
257     return result;
258 }
259
260 // ---------------------------------------------------------
261
262 /**
263  * exact_long_multiply_smaller_10e5()
264  *
265  * Same as below but with operands smaller than 10000 which allows
266  * to perform all component multiplications without an overflow risk.
267  **/
268 static inline struct timespec exact_long_multiply_smaller_10e5(long t, long k)
269 {
270     /* Since operands are smaller than 10e5 we can use 1000 */
271     /* the base without risking to cause overflows in the   */
272     /* operations.                                          */
273     /********************************************************/
274     assert(t < 10000);
275     assert(k < 10000);
276
277     struct timespec result;
278
279     long base = 1000;
280
281     long t_high = t / base;
282     long t_low = t % base;
283     long k_high = k / base;
284     long k_low = k % base;
285
286     long thkh = t_high * k_high;
287     long thkl = t_high * k_low;
288     long tlkh = t_low * k_high;
289     long tlkl = t_low * k_low;
290
291     long thkl_high = thkl / base;
292     long tlkh_high = tlkh / base;
293     long thkl_low = thkl % base;
294     long tlkh_low = tlkh % base;
295
296     long c2 = thkh + thkl_high + tlkh_high; // Normalized at 10^6
297     long c1 = thkl_low + tlkh_low;  // Normalized at 10^3
298     long c0 = tlkl;
299
300     result.tv_sec = c2/1000 + c1/1000000;
301     result.tv_nsec = (c2 % 1000) * 1000000 + (c1 % 1000000) * 1000 + c0;
302
303     result.tv_sec += (result.tv_nsec / 1000000000);
304     result.tv_nsec %= 1000000000;
305
306     return result;
307 }
308
309
310 // -------------------------------------------------------------
311
312
313
314 /**
315  * exact_long_multiply()
316  *
317  * This function performs an exact long * long operations on operands
318  * lower than 1e9 without using more than 32bit (1e9) arithmetic.
319  *
320  * To achieve this we decompose the operands in high and low:
321  *
322  * num = (num/base) * base + (num % base)
323  *        ^^^^^^^^           ^^^^^^^^^^^^
324  *        high component     low component
325  *
326  * t * k = (th*kh + th*kl/base + tl*kh/base  )*base^2
327  *         +  (th*kl % base)*base + (tl*kh % base) * base + tl*kl
328  *
329  * The problem is that we cannot use an exact base because sqrt(1e9)
330  * is not a multiple of 1e9 (in fact it is not even integer).
331  *
332  * So we use as a base 100000 which means that the last term tl*kl may
333  * need another exact calculation with a lower base (100)
334  **/
335 static inline struct timespec exact_long_multiply(long t, long k)
336 {
337     struct timespec result;
338
339     long t_high;
340     long t_low;
341     long k_high;
342     long k_low;
343
344     long base = 100000;  /* Power of 10 closest to sqrt(1e9) from
345                           * above */
346
347     t_high = t / base;
348     t_low = t % base;  // Between 0 99999
349     k_high = k / base;
350     k_low = k % base;  // Between 0 99999
351
352     /* These numbers are always lower than 1e9 */
353     long thkh = t_high * k_high;
354     long thkl = t_high * k_low;
355     long tlkh = t_low * k_high;
356
357     long thkl_high = thkl / base;
358     long thkl_low = thkl % base;
359     long tlkh_high = tlkh / base;
360     long tlkh_low = tlkh % base;
361
362     /* We can calculate the base^2 term (note however that this is 10
363      * times the tv_sec component because it is multiplied by 10^10 */
364     long c2 = thkh + thkl_high + tlkh_high;  // scaled to 10^10
365     long c1 = thkl_low + tlkh_low;  // scaled to 10^5
366
367     struct timespec c0;
368
369     /* Now we can write the initial values of result */
370     result.tv_sec = c2*10 + c1/10000;
371     result.tv_nsec = (c1 % 10000) * 100000;
372
373     normalize_timespec(result);
374
375     /* To calculate c0 we must check if there is a risk of overflow */
376     /* Remember operands cannot be larger than 99999 and result     */
377     /* larger than 1e9.                                             */
378     /****************************************************************/
379     bool overflow_risk;
380     overflow_risk = false;
381
382     if (
383         ( (t_low > 31622) && (k_low >= 10000) ) ||
384         ( (k_low > 31622) && (t_low >= 10000) )
385         )
386     {
387         overflow_risk = true;
388     }
389
390     if (! overflow_risk)
391     {
392         c0.tv_sec = 0;
393         c0.tv_nsec = t_low * k_low;
394         normalize_timespec(c0);
395     }
396     else
397     {
398         c0 = exact_long_multiply_smaller_10e5(t_low, k_low);
399     }
400     add_timespec(result, result, c0);
401
402     return result;
403 }
404
405 // -------------------------------------------------------------
406
407
408 static inline fosa_rel_time_t fosa_rel_time_times_integer(fosa_rel_time_t time, long multiplier)
409 {
410     struct timespec result;
411     struct timespec intermediate;
412
413     result.tv_sec = time.tv_sec * multiplier;  // No overflow check here
414     result.tv_nsec = 0;
415
416     intermediate = exact_long_multiply(time.tv_nsec, multiplier);
417
418     add_timespec(result, result, intermediate);
419
420     return result;
421 }
422
423 // ---------------------------------------------------------
424
425 static inline fosa_rel_time_t fosa_rel_time_divided_by_integer(fosa_rel_time_t time, long divider)
426 {
427     struct timespec result;
428     long reminder;
429
430
431     result.tv_sec = time.tv_sec / divider;
432     result.tv_nsec = 0;
433
434     /* We iterate until the reminder is lower than 2 (to later fit in
435      * a 32 bit signed integer multiplied by 1e9 */
436
437     reminder = time.tv_sec % divider;
438
439
440     if (reminder == 0)
441     {
442         /* We are lucky no reminder so no need to transfer it to the
443            nsec scale.
444         */
445         result.tv_nsec = time.tv_nsec/divider;
446         return result;
447     }
448
449     long enhacer;
450     long back_enhacer;
451     long next_dividend;
452     int next_numeral; /* Between 0 and 9 */
453     enhacer = 1;
454     do
455     {
456         enhacer *= 10;
457         back_enhacer = 1000000000 / enhacer;
458         next_numeral = (time.tv_nsec / back_enhacer) % 10;
459
460         // Note:  a possible overflow may happen here with large denominators
461         if (reminder > 200000000)
462         {
463             /* An overflow is going to be produced */
464             abort();
465         }
466         next_dividend = reminder * 10 + next_numeral;
467
468         result.tv_nsec += (next_dividend / divider) * back_enhacer;
469         reminder = next_dividend % divider;
470     } while (back_enhacer > 1);
471
472
473     return result;
474 }
475
476 // ---------------------------------------------------------
477
478
479 /* Comparison */
480 /**************/
481 static inline bool fosa_abs_time_smaller(fosa_abs_time_t abst1, fosa_abs_time_t abst2)
482 {
483     bool result;
484
485     result = smaller_timespec(abst1, abst2);
486
487     return result;
488 }
489
490 // -----------------------------------------------------------
491
492 static inline bool fosa_rel_time_smaller(fosa_rel_time_t relt1, fosa_rel_time_t relt2)
493 {
494     bool result;
495
496     result = smaller_timespec(relt1, relt2);
497
498     return result;
499 }
500
501
502 // -----------------------------------------------------------
503
504 static inline bool fosa_abs_time_smaller_or_equal(fosa_abs_time_t abst1, fosa_abs_time_t abst2)
505 {
506     bool result;
507
508     result = smaller_or_equal_timespec(abst1, abst2);
509
510     return result;
511 }
512
513
514 // -----------------------------------------------------------
515
516 static inline bool fosa_rel_time_smaller_or_equal(fosa_rel_time_t relt1, fosa_rel_time_t relt2)
517 {
518     bool result;
519
520     result = smaller_or_equal_timespec(relt1, relt2);
521
522     return result;
523 }
524
525
526 // -----------------------------------------------------------
527
528 static inline bool fosa_rel_time_equal(fosa_rel_time_t relt1, fosa_rel_time_t relt2)
529 {
530     bool result;
531
532     result = timespec_equal(relt1, relt2);
533
534     return result;
535 }
536
537
538 // -----------------------------------------------------------
539
540 static inline bool fosa_abs_time_equal(fosa_abs_time_t abst1, fosa_abs_time_t abst2)
541 {
542     bool result;
543
544     result = timespec_equal(abst1, abst2);
545
546     return result;
547 }
548
549 // -----------------------------------------------------------
550
551 static inline bool fosa_rel_time_is_null(fosa_rel_time_t relt)
552 {
553     bool result;
554
555     result = timespec_is_null(relt);
556
557     return result;
558 }
559
560
561 // -----------------------------------------------------------
562
563 static inline bool fosa_abs_time_is_null(fosa_abs_time_t abst)
564 {
565     bool result;
566
567     result = timespec_is_null(abst);
568
569     return result;
570 }
571
572
573
574
575 /* Conversion */
576 /**************/
577 static inline fosa_rel_time_t fosa_msec_to_rel_time(long msec)
578 {
579     fosa_rel_time_t result;
580
581     msec_to_timespec(result, msec);
582
583     return result;
584
585
586 }
587
588 // --------------------------------------------------
589
590 static inline long fosa_rel_time_to_msec(fosa_rel_time_t relt)
591 {
592     long result;
593
594     result = timespec_to_msec(relt);
595
596     return result;
597 }
598
599
600 // --------------------------------------------------
601
602
603 static inline fosa_rel_time_t fosa_msec_to_abs_time(long msec)
604 {
605     fosa_abs_time_t result;
606
607     msec_to_timespec(result, msec);
608
609     return result;
610 }
611
612 // --------------------------------------------------
613
614 static inline long fosa_abs_time_to_msec(fosa_abs_time_t abst)
615 {
616     long result;
617
618     result = timespec_to_msec(abst);
619
620     return result;
621 }
622
623
624 // --------------------------------------------------
625
626 static inline fosa_rel_time_t fosa_usec_to_rel_time(long usec)
627 {
628     fosa_rel_time_t result;
629
630     usec_to_timespec(result, usec);
631
632     return result;
633 }
634
635 // --------------------------------------------------
636
637 static inline long fosa_rel_time_to_usec(fosa_rel_time_t relt)
638 {
639     long result;
640
641     result = timespec_to_usec(relt);
642
643     return result;
644 }
645
646
647 // --------------------------------------------------
648
649 static inline fosa_abs_time_t fosa_usec_to_abs_time(long usec)
650 {
651     fosa_abs_time_t result;
652
653     usec_to_timespec(result, usec);
654
655     return result;
656 }
657
658 // --------------------------------------------------
659
660 static inline long fosa_abs_time_to_usec(fosa_abs_time_t abst)
661 {
662     long result;
663
664     result = timespec_to_usec(abst);
665
666     return result;
667 }
668
669 // --------------------------------------------------
670
671 static inline fosa_rel_time_t fosa_nsec_to_rel_time(long nsec)
672 {
673     fosa_rel_time_t result;
674
675     nsec_to_timespec(result, nsec);
676
677     return result;
678 }
679
680 // --------------------------------------------------
681
682 static inline long fosa_rel_time_to_nsec(fosa_rel_time_t relt)
683 {
684     long result;
685
686     result = timespec_to_nsec(relt);
687
688     return result;
689 }
690
691
692 // --------------------------------------------------
693
694 static inline fosa_abs_time_t fosa_nsec_to_abs_time(long nsec)
695 {
696     fosa_abs_time_t result;
697
698     nsec_to_timespec(result, nsec);
699
700     return result;
701 }
702
703 // --------------------------------------------------
704
705 static inline long fosa_abs_time_to_nsec(fosa_abs_time_t abst)
706 {
707     long result;
708
709     result = timespec_to_nsec(abst);
710
711     return result;
712 }
713
714
715 // --------------------------------------------------
716
717 static inline fosa_rel_time_t fosa_timespec_to_rel_time(struct timespec time_tspec)
718 {
719     return (fosa_rel_time_t) time_tspec;
720 }
721
722 // --------------------------------------------------
723
724 static inline struct timespec fosa_rel_time_to_timespec(fosa_rel_time_t relt)
725 {
726     return (struct timespec) relt;
727 }
728
729 // --------------------------------------------------
730
731 static inline fosa_abs_time_t fosa_timespec_to_abs_time(struct timespec time_tspec)
732 {
733     return (fosa_abs_time_t) time_tspec;
734 }
735
736 // --------------------------------------------------
737
738 static inline struct timespec fosa_abs_time_to_timespec(fosa_abs_time_t abst)
739 {
740     return (struct timespec) abst;
741 }
742
743 // --------------------------------------------------
744
745 static inline double fosa_rel_time_to_double(fosa_rel_time_t relt)
746 {
747     double result;
748
749     result = relt.tv_nsec*0.000000001 + (double)relt.tv_sec;
750
751     return result;
752 }
753
754 // --------------------------------------------------
755
756 static inline fosa_rel_time_t fosa_double_to_rel_time(double time)
757 {
758     fosa_rel_time_t result;
759
760     result.tv_sec = (long) time;
761     result.tv_nsec = (long) ( (time - (double)result.tv_sec) * 1e9 );
762
763     return result;
764 }
765
766 #endif      /* !FOSA_TIME_TIMESPEC_H_ */