1 // -----------------------------------------------------------------------
2 // Copyright (C) 2006 - 2009 FRESCOR consortium partners:
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
11 // Thales Communication S.A. FRANCE
12 // Visual Tools S.A. SPAIN
13 // Rapita Systems Ltd UK
16 // See http://www.frescor.org for a link to partners' websites
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
24 // based on previous work (FSF) done in the FIRST project
26 // Copyright (C) 2005 Mälardalen University, SWEDEN
27 // Scuola Superiore S.Anna, ITALY
28 // Universidad de Cantabria, SPAIN
29 // University of York, UK
31 // FSF API web pages: http://marte.unican.es/fsf/docs
32 // http://shark.sssup.it/contrib/first/docs/
34 // This file is part of FOSA (Frsh Operating System Adaption)
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.
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 // // /******/ //////// // //
66 // FOSA(Frescor Operating System Adaptation layer)
67 //================================================
68 #ifndef FOSA_TIME_TIMESPEC_H_
69 #define FOSA_TIME_TIMESPEC_H_
74 /**********************************/
75 /* T I M E S P E C M A C R O S */
76 /**********************************/
78 #define normalize_timespec(t1) \
81 if ((t1).tv_nsec >= 1000000000) \
84 (t1).tv_nsec -= 1000000000; \
88 #define add_timespec(sum, t1, t2) \
90 (sum).tv_sec = (t1).tv_sec + (t2).tv_sec; \
91 (sum).tv_nsec = (t1).tv_nsec + (t2).tv_nsec; \
92 normalize_timespec(sum); \
95 #define incr_timespec(t1, t2) \
97 (t1).tv_sec += (t2).tv_sec; \
98 (t1).tv_nsec += (t2).tv_nsec; \
99 normalize_timespec(t1); \
102 // -------------------------------------------------------------------
104 /* TODO: Test that for past > future we obtain a correct negative
106 #define substract_timespec(diff, base, interval) \
108 if ((base).tv_nsec < (interval).tv_nsec) \
110 (diff).tv_sec = (base).tv_sec - (interval).tv_sec - 1; \
111 (diff).tv_nsec = (base).tv_nsec + 1000000000 - (interval).tv_nsec; \
115 (diff).tv_sec = (base).tv_sec - (interval).tv_sec; \
116 (diff).tv_nsec = (base).tv_nsec - (interval).tv_nsec; \
121 // ---------------------------------------------------------
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) )
126 // ---------------------------------------------------------
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) )
131 // ---------------------------------------------------------
133 #define msec_to_timespec(tspec, msec) \
135 if ((msec) >= 1000) { \
136 (tspec).tv_sec = (msec)/1000; \
137 (tspec).tv_nsec = ((msec) % 1000) * 1000000; \
139 (tspec).tv_sec = 0; \
140 (tspec).tv_nsec = (msec) * 1000000; \
144 // ---------------------------------------------------------
146 #define timespec_to_msec(t1) \
147 ( ((t1).tv_sec % 2147482) * 1000 + (t1).tv_nsec/1000000 )
150 // ---------------------------------------------------------
152 #define usec_to_timespec(tspec, usec) \
154 if ((usec) >= 1000000) { \
155 (tspec).tv_sec = (usec)/1000000; \
156 (tspec).tv_nsec = ((usec) % 1000000) * 1000; \
158 (tspec).tv_sec = 0; \
159 (tspec).tv_nsec = (usec) * 1000; \
163 // ---------------------------------------------------------
165 #define timespec_to_usec(t1) \
166 ( ((t1).tv_sec % 2148) * 1000000 + (t1).tv_nsec/1000 )
169 // ---------------------------------------------------------
171 #define nsec_to_timespec(tspec, nsec) \
173 if ((nsec) >= 1000000000) { \
174 (tspec).tv_sec = (nsec)/1000000000; \
175 (tspec).tv_nsec = (nsec) % 1000000000; \
177 (tspec).tv_sec = 0; \
178 (tspec).tv_nsec = (nsec); \
182 // ---------------------------------------------------------
184 #define timespec_to_nsec(t1) \
185 ( ((t1).tv_sec % 2) * 1000000000 + (t1).tv_nsec )
189 // ---------------------------------------------------------
191 #define timespec_equal(t1, t2) ( (t1).tv_sec == (t2).tv_sec ) && ( (t1).tv_nsec == (t2).tv_nsec )
193 #define timespec_is_null(t1) ( (t1).tv_sec == 0 ) && ( (t1).tv_nsec == 0 )
197 /***************************************/
198 /* T I M E S P E C F U N C T I O N S */
199 /***************************************/
202 static inline fosa_abs_time_t fosa_abs_time_incr(fosa_abs_time_t base, fosa_rel_time_t interval)
204 fosa_abs_time_t result;
206 add_timespec(result, base, interval);
212 // ---------------------------------------------------------
214 static inline fosa_abs_time_t fosa_abs_time_decr(fosa_abs_time_t base, fosa_rel_time_t interval)
216 fosa_abs_time_t result;
218 substract_timespec(result, base, interval);
225 // ---------------------------------------------------------
227 static inline fosa_rel_time_t fosa_abs_time_extract_interval(fosa_abs_time_t past, fosa_abs_time_t future)
229 fosa_rel_time_t result;
231 substract_timespec(result, future, past);
237 // ---------------------------------------------------------
239 static inline fosa_rel_time_t fosa_rel_time_add(fosa_rel_time_t relt1, fosa_rel_time_t relt2)
241 fosa_rel_time_t result;
243 add_timespec(result, relt1, relt2);
249 // ---------------------------------------------------------
251 static inline fosa_rel_time_t fosa_rel_time_decr(fosa_rel_time_t total, fosa_rel_time_t part)
253 fosa_rel_time_t result;
255 substract_timespec(result, total, part);
260 // ---------------------------------------------------------
263 * exact_long_multiply_smaller_10e5()
265 * Same as below but with operands smaller than 10000 which allows
266 * to perform all component multiplications without an overflow risk.
268 static inline struct timespec exact_long_multiply_smaller_10e5(long t, long k)
270 /* Since operands are smaller than 10e5 we can use 1000 */
271 /* the base without risking to cause overflows in the */
273 /********************************************************/
277 struct timespec result;
281 long t_high = t / base;
282 long t_low = t % base;
283 long k_high = k / base;
284 long k_low = k % base;
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;
291 long thkl_high = thkl / base;
292 long tlkh_high = tlkh / base;
293 long thkl_low = thkl % base;
294 long tlkh_low = tlkh % base;
296 long c2 = thkh + thkl_high + tlkh_high; // Normalized at 10^6
297 long c1 = thkl_low + tlkh_low; // Normalized at 10^3
300 result.tv_sec = c2/1000 + c1/1000000;
301 result.tv_nsec = (c2 % 1000) * 1000000 + (c1 % 1000000) * 1000 + c0;
303 result.tv_sec += (result.tv_nsec / 1000000000);
304 result.tv_nsec %= 1000000000;
310 // -------------------------------------------------------------
315 * exact_long_multiply()
317 * This function performs an exact long * long operations on operands
318 * lower than 1e9 without using more than 32bit (1e9) arithmetic.
320 * To achieve this we decompose the operands in high and low:
322 * num = (num/base) * base + (num % base)
323 * ^^^^^^^^ ^^^^^^^^^^^^
324 * high component low component
326 * t * k = (th*kh + th*kl/base + tl*kh/base )*base^2
327 * + (th*kl % base)*base + (tl*kh % base) * base + tl*kl
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).
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)
335 static inline struct timespec exact_long_multiply(long t, long k)
337 struct timespec result;
344 long base = 100000; /* Power of 10 closest to sqrt(1e9) from
348 t_low = t % base; // Between 0 99999
350 k_low = k % base; // Between 0 99999
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;
357 long thkl_high = thkl / base;
358 long thkl_low = thkl % base;
359 long tlkh_high = tlkh / base;
360 long tlkh_low = tlkh % base;
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
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;
373 normalize_timespec(result);
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 /****************************************************************/
380 overflow_risk = false;
383 ( (t_low > 31622) && (k_low >= 10000) ) ||
384 ( (k_low > 31622) && (t_low >= 10000) )
387 overflow_risk = true;
393 c0.tv_nsec = t_low * k_low;
394 normalize_timespec(c0);
398 c0 = exact_long_multiply_smaller_10e5(t_low, k_low);
400 add_timespec(result, result, c0);
405 // -------------------------------------------------------------
408 static inline fosa_rel_time_t fosa_rel_time_times_integer(fosa_rel_time_t time, long multiplier)
410 struct timespec result;
411 struct timespec intermediate;
413 result.tv_sec = time.tv_sec * multiplier; // No overflow check here
416 intermediate = exact_long_multiply(time.tv_nsec, multiplier);
418 add_timespec(result, result, intermediate);
423 // ---------------------------------------------------------
425 static inline fosa_rel_time_t fosa_rel_time_divided_by_integer(fosa_rel_time_t time, long divider)
427 struct timespec result;
431 result.tv_sec = time.tv_sec / divider;
434 /* We iterate until the reminder is lower than 2 (to later fit in
435 * a 32 bit signed integer multiplied by 1e9 */
437 reminder = time.tv_sec % divider;
442 /* We are lucky no reminder so no need to transfer it to the
445 result.tv_nsec = time.tv_nsec/divider;
452 int next_numeral; /* Between 0 and 9 */
457 back_enhacer = 1000000000 / enhacer;
458 next_numeral = (time.tv_nsec / back_enhacer) % 10;
460 // Note: a possible overflow may happen here with large denominators
461 if (reminder > 200000000)
463 /* An overflow is going to be produced */
466 next_dividend = reminder * 10 + next_numeral;
468 result.tv_nsec += (next_dividend / divider) * back_enhacer;
469 reminder = next_dividend % divider;
470 } while (back_enhacer > 1);
476 // ---------------------------------------------------------
481 static inline bool fosa_abs_time_smaller(fosa_abs_time_t abst1, fosa_abs_time_t abst2)
485 result = smaller_timespec(abst1, abst2);
490 // -----------------------------------------------------------
492 static inline bool fosa_rel_time_smaller(fosa_rel_time_t relt1, fosa_rel_time_t relt2)
496 result = smaller_timespec(relt1, relt2);
502 // -----------------------------------------------------------
504 static inline bool fosa_abs_time_smaller_or_equal(fosa_abs_time_t abst1, fosa_abs_time_t abst2)
508 result = smaller_or_equal_timespec(abst1, abst2);
514 // -----------------------------------------------------------
516 static inline bool fosa_rel_time_smaller_or_equal(fosa_rel_time_t relt1, fosa_rel_time_t relt2)
520 result = smaller_or_equal_timespec(relt1, relt2);
526 // -----------------------------------------------------------
528 static inline bool fosa_rel_time_equal(fosa_rel_time_t relt1, fosa_rel_time_t relt2)
532 result = timespec_equal(relt1, relt2);
538 // -----------------------------------------------------------
540 static inline bool fosa_abs_time_equal(fosa_abs_time_t abst1, fosa_abs_time_t abst2)
544 result = timespec_equal(abst1, abst2);
549 // -----------------------------------------------------------
551 static inline bool fosa_rel_time_is_null(fosa_rel_time_t relt)
555 result = timespec_is_null(relt);
561 // -----------------------------------------------------------
563 static inline bool fosa_abs_time_is_null(fosa_abs_time_t abst)
567 result = timespec_is_null(abst);
577 static inline fosa_rel_time_t fosa_msec_to_rel_time(long msec)
579 fosa_rel_time_t result;
581 msec_to_timespec(result, msec);
588 // --------------------------------------------------
590 static inline long fosa_rel_time_to_msec(fosa_rel_time_t relt)
594 result = timespec_to_msec(relt);
600 // --------------------------------------------------
603 static inline fosa_rel_time_t fosa_msec_to_abs_time(long msec)
605 fosa_abs_time_t result;
607 msec_to_timespec(result, msec);
612 // --------------------------------------------------
614 static inline long fosa_abs_time_to_msec(fosa_abs_time_t abst)
618 result = timespec_to_msec(abst);
624 // --------------------------------------------------
626 static inline fosa_rel_time_t fosa_usec_to_rel_time(long usec)
628 fosa_rel_time_t result;
630 usec_to_timespec(result, usec);
635 // --------------------------------------------------
637 static inline long fosa_rel_time_to_usec(fosa_rel_time_t relt)
641 result = timespec_to_usec(relt);
647 // --------------------------------------------------
649 static inline fosa_abs_time_t fosa_usec_to_abs_time(long usec)
651 fosa_abs_time_t result;
653 usec_to_timespec(result, usec);
658 // --------------------------------------------------
660 static inline long fosa_abs_time_to_usec(fosa_abs_time_t abst)
664 result = timespec_to_usec(abst);
669 // --------------------------------------------------
671 static inline fosa_rel_time_t fosa_nsec_to_rel_time(long nsec)
673 fosa_rel_time_t result;
675 nsec_to_timespec(result, nsec);
680 // --------------------------------------------------
682 static inline long fosa_rel_time_to_nsec(fosa_rel_time_t relt)
686 result = timespec_to_nsec(relt);
692 // --------------------------------------------------
694 static inline fosa_abs_time_t fosa_nsec_to_abs_time(long nsec)
696 fosa_abs_time_t result;
698 nsec_to_timespec(result, nsec);
703 // --------------------------------------------------
705 static inline long fosa_abs_time_to_nsec(fosa_abs_time_t abst)
709 result = timespec_to_nsec(abst);
715 // --------------------------------------------------
717 static inline fosa_rel_time_t fosa_timespec_to_rel_time(struct timespec time_tspec)
719 return (fosa_rel_time_t) time_tspec;
722 // --------------------------------------------------
724 static inline struct timespec fosa_rel_time_to_timespec(fosa_rel_time_t relt)
726 return (struct timespec) relt;
729 // --------------------------------------------------
731 static inline fosa_abs_time_t fosa_timespec_to_abs_time(struct timespec time_tspec)
733 return (fosa_abs_time_t) time_tspec;
736 // --------------------------------------------------
738 static inline struct timespec fosa_abs_time_to_timespec(fosa_abs_time_t abst)
740 return (struct timespec) abst;
743 // --------------------------------------------------
745 static inline double fosa_rel_time_to_double(fosa_rel_time_t relt)
749 result = relt.tv_nsec*0.000000001 + (double)relt.tv_sec;
754 // --------------------------------------------------
756 static inline fosa_rel_time_t fosa_double_to_rel_time(double time)
758 fosa_rel_time_t result;
760 result.tv_sec = (long) time;
761 result.tv_nsec = (long) ( (time - (double)result.tv_sec) * 1e9 );
766 #endif /* !FOSA_TIME_TIMESPEC_H_ */