]> rtime.felk.cvut.cz Git - frescor/fosa.git/blob - include/fosa_time_timespec.h
Fixing license header
[frescor/fosa.git] / include / fosa_time_timespec.h
1 // -----------------------------------------------------------------------
2 //  Copyright (C) 2006 - 2008 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
89 #define add_timespec(sum, t1, t2) \
90 do { \
91     (sum).tv_sec = (t1).tv_sec + (t2).tv_sec; \
92     (sum).tv_nsec = (t1).tv_nsec + (t2).tv_nsec; \
93     normalize_timespec(sum); \
94 } while(0)
95
96
97
98 // -------------------------------------------------------------------
99
100 /* TODO:  Test that for past > future we obtain a correct negative
101  * interval */
102 #define substract_timespec(diff, base, interval) \
103 do { \
104     if ((base).tv_nsec < (interval).tv_nsec) \
105     { \
106         (diff).tv_sec = (base).tv_sec - (interval).tv_sec + 1; \
107         (diff).tv_nsec = (base).tv_nsec + 1000000000 - (interval).tv_nsec; \
108     } \
109     else \
110     { \
111         (diff).tv_sec = (base).tv_sec - (interval).tv_sec; \
112         (diff).tv_nsec = (base).tv_nsec - (interval).tv_nsec; \
113     } \
114 } while(0) 
115
116
117 // ---------------------------------------------------------
118
119 #define smaller_timespec(t1, t2) \
120    ((t1).tv_sec < (t2).tv_sec || ((t1).tv_sec == (t2).tv_sec && (t1).tv_nsec < (t2).tv_nsec) )
121
122 // ---------------------------------------------------------
123
124 #define smaller_or_equal_timespec(t1, t2) \
125    ((t1).tv_sec < (t2).tv_sec || ((t1).tv_sec == (t2).tv_sec && (t1).tv_nsec <= (t2).tv_nsec) )
126
127 // ---------------------------------------------------------
128
129 #define msec_to_timespec(tspec, msec) \
130 do { \
131     if ((msec) >= 1000) { \
132         (tspec).tv_sec = (msec)/1000; \
133         (tspec).tv_nsec = ((msec) % 1000) * 1000000; \
134     } else { \
135         (tspec).tv_sec = 0; \
136         (tspec).tv_nsec = (msec) * 1000000; \
137     } \
138 } while (0)
139
140 // ---------------------------------------------------------
141
142 #define timespec_to_msec(t1) \
143    ( ((t1).tv_sec % 2147482) * 1000 + (t1).tv_nsec/1000000 ) 
144
145
146 // ---------------------------------------------------------
147
148 #define usec_to_timespec(tspec, usec) \
149 do { \
150     if ((usec) >= 1000000) { \
151         (tspec).tv_sec = (usec)/1000000; \
152         (tspec).tv_nsec = ((usec) % 1000000) * 1000; \
153     } else { \
154         (tspec).tv_sec = 0; \
155         (tspec).tv_nsec = (usec) * 1000; \
156     } \
157 } while(0)
158
159 // ---------------------------------------------------------
160
161 #define timespec_to_usec(t1) \
162    ( ((t1).tv_sec % 2148) * 1000000 + (t1).tv_nsec/1000 )
163
164
165 // ---------------------------------------------------------
166
167 #define nsec_to_timespec(tspec, nsec) \
168 do { \
169     if ((nsec) >= 1000000000) { \
170         (tspec).tv_sec = (nsec)/1000000000; \
171         (tspec).tv_nsec = (nsec) % 1000000000; \
172     } else { \
173         (tspec).tv_sec = 0; \
174         (tspec).tv_nsec = (nsec); \
175     } \
176 } while(0)
177
178 // ---------------------------------------------------------
179
180 #define timespec_to_nsec(t1) \
181    ( ((t1).tv_sec % 2) * 1000000000 + (t1).tv_nsec )
182
183
184
185 // ---------------------------------------------------------
186
187 #define timespec_equal(t1, t2) ( (t1).tv_sec == (t2).tv_sec ) && ( (t1).tv_nsec == (t2).tv_nsec )
188
189 #define timespec_is_null(t1) ( (t1).tv_sec == 0 ) && ( (t1).tv_nsec == 0 )
190
191
192   
193 /***************************************/
194 /* T I M E S P E C   F U N C T I O N S */
195 /***************************************/
196
197
198 static inline fosa_abs_time_t fosa_abs_time_incr(fosa_abs_time_t base, fosa_rel_time_t interval)
199 {
200     fosa_abs_time_t result;
201     
202     add_timespec(result, base, interval);
203
204     return result;
205 }
206
207
208 // ---------------------------------------------------------
209
210 static inline fosa_abs_time_t fosa_abs_time_decr(fosa_abs_time_t base, fosa_rel_time_t interval)
211 {
212     fosa_abs_time_t result;
213
214     substract_timespec(result, base, interval);
215
216     return result;
217 }
218
219
220
221 // ---------------------------------------------------------
222
223 static inline fosa_rel_time_t fosa_abs_time_extract_interval(fosa_abs_time_t past, fosa_abs_time_t future)
224 {
225     fosa_rel_time_t result;
226
227     substract_timespec(result, future, past);
228
229     return result;
230 }
231
232
233 // ---------------------------------------------------------
234
235 static inline fosa_rel_time_t fosa_rel_time_add(fosa_rel_time_t relt1, fosa_rel_time_t relt2)
236 {
237     fosa_rel_time_t result;
238
239     add_timespec(result, relt1, relt2);
240
241     return result;
242 }
243     
244
245 // ---------------------------------------------------------
246
247 static inline fosa_rel_time_t fosa_rel_time_decr(fosa_rel_time_t total, fosa_rel_time_t part)
248 {
249     fosa_rel_time_t result;
250
251     substract_timespec(result, total, part);
252
253     return result;
254 }
255
256 // ---------------------------------------------------------
257
258 /**
259  * exact_long_multiply_smaller_10e5()
260  *
261  * Same as below but with operands smaller than 10000 which allows
262  * to perform all component multiplications without an overflow risk. 
263  **/
264 static inline struct timespec exact_long_multiply_smaller_10e5(long t, long k)
265 {
266     /* Since operands are smaller than 10e5 we can use 1000 */
267     /* the base without risking to cause overflows in the   */
268     /* operations.                                          */
269     /********************************************************/
270     assert(t < 10000);
271     assert(k < 10000);
272
273     struct timespec result;
274
275     long base = 1000;
276
277     long t_high = t / base;
278     long t_low = t % base;
279     long k_high = k / base;
280     long k_low = k % base;
281
282     long thkh = t_high * k_high;
283     long thkl = t_high * k_low;
284     long tlkh = t_low * k_high;
285     long tlkl = t_low * k_low;
286
287     long thkl_high = thkl / base;
288     long tlkh_high = tlkh / base;
289     long thkl_low = thkl % base;
290     long tlkh_low = tlkh % base;
291
292     long c2 = thkh + thkl_high + tlkh_high; // Normalized at 10^6
293     long c1 = thkl_low + tlkh_low;  // Normalized at 10^3
294     long c0 = tlkl;
295
296     result.tv_sec = c2/1000 + c1/1000000;
297     result.tv_nsec = (c2 % 1000) * 1000000 + (c1 % 1000000) * 1000 + c0;
298
299     result.tv_sec += (result.tv_nsec / 1000000000);
300     result.tv_nsec %= 1000000000;
301
302     return result;
303 }
304
305     
306 // -------------------------------------------------------------    
307
308     
309
310 /**
311  * exact_long_multiply()
312  *
313  * This function performs an exact long * long operations on operands
314  * lower than 1e9 without using more than 32bit (1e9) arithmetic.
315  *
316  * To achieve this we decompose the operands in high and low:
317  *
318  * num = (num/base) * base + (num % base)
319  *        ^^^^^^^^           ^^^^^^^^^^^^
320  *        high component     low component
321  *
322  * t * k = (th*kh + th*kl/base + tl*kh/base  )*base^2
323  *         +  (th*kl % base)*base + (tl*kh % base) * base + tl*kl
324  *
325  * The problem is that we cannot use an exact base because sqrt(1e9)
326  * is not a multiple of 1e9 (in fact it is not even integer).
327  *
328  * So we use as a base 100000 which means that the last term tl*kl may
329  * need another exact calculation with a lower base (100)
330  **/
331 static inline struct timespec exact_long_multiply(long t, long k)
332 {
333     struct timespec result;
334
335     long t_high;
336     long t_low;
337     long k_high;
338     long k_low;
339
340     long base = 100000;  /* Power of 10 closest to sqrt(1e9) from
341                           * above */
342
343     t_high = t / base;
344     t_low = t % base;  // Between 0 99999
345     k_high = k / base;
346     k_low = k % base;  // Between 0 99999
347
348     /* These numbers are always lower than 1e9 */
349     long thkh = t_high * k_high;
350     long thkl = t_high * k_low;
351     long tlkh = t_low * k_high;
352
353     long thkl_high = thkl / base;
354     long thkl_low = thkl % base;
355     long tlkh_high = tlkh / base;
356     long tlkh_low = tlkh % base;
357
358     /* We can calculate the base^2 term (note however that this is 10
359      * times the tv_sec component because it is multiplied by 10^10 */
360     long c2 = thkh + thkl_high + tlkh_high;  // scaled to 10^10
361     long c1 = thkl_low + tlkh_low;  // scaled to 10^5
362
363     struct timespec c0;
364
365     /* Now we can write the initial values of result */
366     result.tv_sec = c2*10 + c1/10000;
367     result.tv_nsec = (c1 % 10000) * 100000;
368
369     normalize_timespec(result);
370
371     /* To calculate c0 we must check if there is a risk of overflow */
372     /* Remember operands cannot be larger than 99999 and result     */
373     /* larger than 1e9.                                             */
374     /****************************************************************/
375     bool overflow_risk;
376     overflow_risk = false;
377
378     if (
379         ( (t_low > 31622) && (k_low >= 10000) ) ||
380         ( (k_low > 31622) && (t_low >= 10000) )
381         )
382     {
383         overflow_risk = true;
384     }
385     
386     if (! overflow_risk)
387     {
388         c0.tv_sec = 0;
389         c0.tv_nsec = t_low * k_low;
390         normalize_timespec(c0);
391     }
392     else
393     {
394         c0 = exact_long_multiply_smaller_10e5(t_low, k_low);
395     }
396     add_timespec(result, result, c0);
397
398     return result;
399 }
400     
401 // -------------------------------------------------------------    
402
403
404 static inline fosa_rel_time_t fosa_rel_time_times_integer(fosa_rel_time_t time, long multiplier)
405 {
406     struct timespec result;
407     struct timespec intermediate;
408
409     result.tv_sec = time.tv_sec * multiplier;  // No overflow check here
410     result.tv_nsec = 0;
411
412     intermediate = exact_long_multiply(time.tv_nsec, multiplier);
413
414     add_timespec(result, result, intermediate);
415     
416     return result;
417 }
418
419 // ---------------------------------------------------------
420
421 static inline fosa_rel_time_t fosa_rel_time_divided_by_integer(fosa_rel_time_t time, long divider)
422 {
423     struct timespec result;
424     long reminder;
425
426
427     result.tv_sec = time.tv_sec / divider;
428     result.tv_nsec = 0;
429
430     /* We iterate until the reminder is lower than 2 (to later fit in
431      * a 32 bit signed integer multiplied by 1e9 */
432
433     reminder = time.tv_sec % divider;
434
435
436     if (reminder == 0)
437     {
438         /* We are lucky no reminder so no need to transfer it to the
439            nsec scale.
440         */
441         result.tv_nsec = time.tv_nsec/divider;
442         return result;
443     }
444
445     long enhacer;
446     long back_enhacer;
447     long next_dividend;
448     int next_numeral; /* Between 0 and 9 */
449     enhacer = 1;
450     do
451     {
452         enhacer *= 10;
453         back_enhacer = 1000000000 / enhacer;
454         next_numeral = (time.tv_nsec / back_enhacer) % 10;
455         
456         // Note:  a possible overflow may happen here with large denominators
457         if (reminder > 200000000)
458         {
459             /* An overflow is going to be produced */
460             abort();
461         }
462         next_dividend = reminder * 10 + next_numeral;
463         
464         result.tv_nsec += (next_dividend / divider) * back_enhacer;
465         reminder = next_dividend % divider;
466     } while (back_enhacer > 1);
467
468     
469     return result;
470 }
471
472 // ---------------------------------------------------------
473
474
475 /* Comparison */
476 /**************/
477 static inline bool fosa_abs_time_smaller(fosa_abs_time_t abst1, fosa_abs_time_t abst2)
478 {
479     bool result;
480
481     result = smaller_timespec(abst1, abst2);
482
483     return result;
484 }
485
486 // -----------------------------------------------------------
487
488 static inline bool fosa_rel_time_smaller(fosa_rel_time_t relt1, fosa_rel_time_t relt2)
489 {
490     bool result;
491
492     result = smaller_timespec(relt1, relt2);
493
494     return result;
495 }
496
497
498 // -----------------------------------------------------------
499
500 static inline bool fosa_abs_time_smaller_or_equal(fosa_abs_time_t abst1, fosa_abs_time_t abst2)
501 {
502     bool result;
503
504     result = smaller_or_equal_timespec(abst1, abst2);
505
506     return result;
507 }
508
509
510 // -----------------------------------------------------------
511
512 static inline bool fosa_rel_time_smaller_or_equal(fosa_rel_time_t relt1, fosa_rel_time_t relt2)
513 {
514     bool result;
515
516     result = smaller_or_equal_timespec(relt1, relt2);
517
518     return result;
519 }
520
521
522 // -----------------------------------------------------------
523
524 static inline bool fosa_rel_time_equal(fosa_rel_time_t relt1, fosa_rel_time_t relt2)
525 {
526     bool result;
527
528     result = timespec_equal(relt1, relt2);
529
530     return result;
531 }
532
533
534 // -----------------------------------------------------------
535
536 static inline bool fosa_abs_time_equal(fosa_abs_time_t abst1, fosa_abs_time_t abst2)
537 {
538     bool result;
539
540     result = timespec_equal(abst1, abst2);
541
542     return result;
543 }
544
545 // -----------------------------------------------------------
546
547 static inline bool fosa_rel_time_is_null(fosa_rel_time_t relt)
548 {
549     bool result;
550
551     result = timespec_is_null(relt);
552
553     return result;
554 }
555
556
557 // -----------------------------------------------------------
558
559 static inline bool fosa_abs_time_is_null(fosa_abs_time_t abst)
560 {
561     bool result;
562
563     result = timespec_is_null(abst);
564
565     return result;
566 }
567
568
569
570
571 /* Conversion */
572 /**************/
573 static inline fosa_rel_time_t fosa_msec_to_rel_time(long msec)
574 {
575     fosa_rel_time_t result;
576
577     msec_to_timespec(result, msec);
578
579     return result;
580
581
582 }
583
584 // --------------------------------------------------
585
586 static inline long fosa_rel_time_to_msec(fosa_rel_time_t relt)
587 {
588     long result;
589
590     result = timespec_to_msec(relt);
591
592     return result;
593 }
594
595
596 // --------------------------------------------------
597
598
599 static inline fosa_rel_time_t fosa_msec_to_abs_time(long msec)
600 {
601     fosa_abs_time_t result;
602
603     msec_to_timespec(result, msec);
604
605     return result;
606 }
607
608 // --------------------------------------------------
609
610 static inline long fosa_abs_time_to_msec(fosa_abs_time_t abst)
611 {
612     long result;
613
614     result = timespec_to_msec(abst);
615
616     return result;
617 }
618
619
620 // --------------------------------------------------
621
622 static inline fosa_rel_time_t fosa_usec_to_rel_time(long usec)
623 {
624     fosa_rel_time_t result;
625
626     usec_to_timespec(result, usec);
627
628     return result;
629 }
630
631 // --------------------------------------------------
632
633 static inline long fosa_rel_time_to_usec(fosa_rel_time_t relt)
634 {
635     long result;
636
637     result = timespec_to_usec(relt);
638
639     return result;
640 }
641
642
643 // --------------------------------------------------
644
645 static inline fosa_abs_time_t fosa_usec_to_abs_time(long usec)
646 {
647     fosa_abs_time_t result;
648
649     usec_to_timespec(result, usec);
650
651     return result;
652 }
653
654 // --------------------------------------------------
655
656 static inline long fosa_abs_time_to_usec(fosa_abs_time_t abst)
657 {
658     long result;
659
660     result = timespec_to_usec(abst);
661
662     return result;
663 }
664
665 // --------------------------------------------------
666
667 static inline fosa_rel_time_t fosa_nsec_to_rel_time(long nsec)
668 {
669     fosa_rel_time_t result;
670
671     nsec_to_timespec(result, nsec);
672
673     return result;
674 }
675
676 // --------------------------------------------------
677
678 static inline long fosa_rel_time_to_nsec(fosa_rel_time_t relt)
679 {
680     long result;
681
682     result = timespec_to_nsec(relt);
683
684     return result;
685 }
686
687
688 // --------------------------------------------------
689
690 static inline fosa_abs_time_t fosa_nsec_to_abs_time(long nsec)
691 {
692     fosa_abs_time_t result;
693
694     nsec_to_timespec(result, nsec);
695
696     return result;
697 }
698
699 // --------------------------------------------------
700
701 static inline long fosa_abs_time_to_nsec(fosa_abs_time_t abst)
702 {
703     long result;
704
705     result = timespec_to_nsec(abst);
706
707     return result;
708 }
709
710
711 // --------------------------------------------------
712
713 static inline fosa_rel_time_t fosa_timespec_to_rel_time(struct timespec time_tspec)
714 {
715     return (fosa_rel_time_t) time_tspec;
716 }
717
718 // --------------------------------------------------
719
720 static inline struct timespec fosa_rel_time_to_timespec(fosa_rel_time_t relt)
721 {
722     return (struct timespec) relt;
723 }
724
725 // --------------------------------------------------
726
727 static inline fosa_abs_time_t fosa_timespec_to_abs_time(struct timespec time_tspec)
728 {
729     return (fosa_abs_time_t) time_tspec;
730 }
731
732 // --------------------------------------------------
733
734 static inline struct timespec fosa_abs_time_to_timespec(fosa_abs_time_t abst)
735 {
736     return (struct timespec) abst;
737 }
738
739 // --------------------------------------------------
740
741 static inline double fosa_rel_time_to_double(fosa_rel_time_t relt)
742 {
743     double result;
744
745     result = relt.tv_nsec*0.000000001 + (double)relt.tv_sec;
746
747     return result;
748 }
749
750 // --------------------------------------------------
751
752 static inline fosa_rel_time_t fosa_double_to_rel_time(double time)
753 {
754     fosa_rel_time_t result;
755
756     result.tv_sec = (long) time;
757     result.tv_nsec = (long) ( (time - (double)result.tv_sec) * 1e9 );
758
759     return result;
760 }
761
762 #endif      /* !FOSA_TIME_TIMESPEC_H_ */