RTI Connext Micro  Version 2.4.4.0
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
osapi_time.h
Go to the documentation of this file.
1 /*
2  * FILE: osapi_time.h - Definition of Time API
3  *
4  * Copyright 2005-2015 Real-Time Innovations, Inc.
5  *
6  * No duplications, whole or partial, manual or electronic, may be made
7  * without express written permission. Any such copies, or
8  * revisions thereof, must display this notice unaltered.
9  * This code contains trade secrets of Real-Time Innovations, Inc.
10  *
11  * Modification History
12  * --------------------
13  * 16mar2015,tk MICRO-1084 Changed comment for to/from_ntp_time to state
14  * resolution is at least 1ns.
15  * 20mar2013,tk Updated
16  * 06dec2005,rh Created
17  */
18 /*e \file
19  * \brief Time API definition
20  */
21 #ifndef osapi_time_h
22 #define osapi_time_h
23 
24 #include "osapi/osapi_dll.h"
25 #ifndef osapi_types_h
26 #include "osapi/osapi_types.h"
27 #endif
28 
29 #ifdef __cplusplus
30 extern "C"
31 {
32 #endif
33 
34 /*e \defgroup OSAPITimeClass OSAPI Time
35  * \ingroup OSAPIModule
36 */
37 
38 /*e \ingroup OSAPITimeClass
39 
40  \brief NtpTime API.
41 */
42 
43 /* ================================================================= */
44 /* Definition: Time */
45 /* ----------------------------------------------------------------- */
46 
47 /*e \ingroup OSAPITimeClass
48 
49  @brief NTP Time representation.
50 
51  Expresses time in NTP format. The second field is simply an integer
52  expressing seconds. The fraction field expresses 1/2^32 of a second.
53  We strongly urge customers to use our provided macros to convert this
54  format to and from human readable form.
55 
56  OSAPI_NtpTime_init must be called before OSAPI_NtpTime_get. Creating a domain
57  has the side-effect of calling OSAPI_NtpTime_init.
58 
59  \b Example:
60 
61  The following is a simple example on how to prepare a struct OSAPI_NtpTime structure
62  to be 1.5 seconds.
63 
64  \verbatim
65  struct OSAPI_NtpTime ntpTime;
66 
67  OSAPI_NtpTime_packFromMillisec(ntpTime, 1, 500);
68  \endverbatim
69 
70  @see OSAPI_NtpTime_packFromMillisec OSAPI_NtpTime_packFromMicrosec
71  @see OSAPI_NtpTime_packFromNanosec
72  @see OSAPI_NtpTime_unpackFromMillisec OSAPI_NtpTime_unpackFromMicrosec
73  @see OSAPI_NtpTime_unpackFromNanosec
74  */
75 typedef struct OSAPI_NtpTime
76 {
77  /* e Seconds.* */
78  RTI_INT32 sec;
79  /* e fraction of a second in 1/2^32 form. */
80  RTI_UINT32 frac;
82 
83 /*e \ingroup OSAPITimeClass
84  The maximum number of seconds that can be represented using NTP time.
85  */
86 #define OSAPI_NTP_TIME_SEC_MAX ((RTI_INT32)0x7fffffff)
87 
88 /*e \ingroup OSAPITimeClass
89  The largest possible value of the fraction field in NTP time.
90  */
91 #define OSAPI_NTP_TIME_FRAC_MAX ((RTI_UINT32)0xffffffff)
92 
93 
94 /*e \ingroup OSAPITimeClass
95 
96  @brief Macro to convert from seconds and milliseconds to struct OSAPI_NtpTime format.
97 
98  @param time (struct OSAPI_NtpTime) contains the answer.
99  @param s (integer) Seconds to convert.
100  @param msec (millisecond) Fraction portion (less than 1000).
101 
102  \verbatim
103  struct OSAPI_NtpTime time;
104  long sec, msec;
105  sec = 10;
106  msec = 577;
107 
108  OSAPI_NtpTime_packFromMillisec(time, sec, msec);
109  \endverbatim
110 
111  After the above call is made, the variable time will contain the equivalent
112  timestamp in struct OSAPI_NtpTime representation.
113 
114  This macro assumes that msec<1000. It is the caller's responsibility
115  to ensure this. This is done for performance reasons (the extra check slows
116  the execution by a factor of 5). If msec may be greater than 1000, you can invoke
117  the macro as follows:
118  \verbatim
119  OSAPI_NtpTime_packFromMillisec(time, sec + msec/1000, msec%1000);
120  \endverbatim
121 
122  This macro only evaluates its arguments once, so it is safe to invoke it
123  with an argument that has side effects; that is, if you write:
124  \verbatim
125  RTI_UINT32 count = 10;
126  OSAPI_NtpTime_packFromMillisec(time, sec, count++)
127  \endverbatim
128  After the macro count is guaranteed to be 11.
129 
130  The accuracy of this conversion over the whole range of millisecond values
131  is 0.013 milliseconds.
132 
133  This is a fairly efficient macro. On a 400MHz Pentium-II Linux box
134  the execution time is about 0.06 usec.
135 
136  \verbatim
137  2^22*time.frac = ms + ms/2^6 + ms/2^7 + ms/2^11 + ms/2^14 + 1.3e-5
138  = ms + ms*393/2^14;
139  time.frac = (ms<<22) + (ms<<16) + (ms<<15) + (ms<<11) + (ms<<8)
140  = (ms<<22) + ((ms*393)<<8)
141  \endverbatim
142 
143  @see struct OSAPI_NtpTime OSAPI_NtpTime_unpackToMillisec
144 */
145 OSAPIDllExport void
146 OSAPI_NtpTime_from_millisec(struct OSAPI_NtpTime *const time, RTI_INT32 s, RTI_UINT32 msec);
147 
148 /*e \ingroup OSAPITimeClass
149 
150  @brief Macro to convert from struct OSAPI_NtpTime to seconds and milliseconds.
151 
152  @param s (integer) Holds the seconds answer.
153  @param msec (integer) Holds the millisecond answer.
154  @param time (struct OSAPI_NtpTime) The time to convert to seconds and milliseconds.
155 
156  This macro does not check for overflow, so for a near-infinite time value,
157  the conversion result may end up being negative. It is the responsibility
158  of the user to avoid passing these large time values.
159 
160  Use as indicated by the following code:
161  \verbatim}
162  struct OSAPI_NtpTime time;
163  long sec, msec;
164 
165  time.sec = 10;
166  time.frac = 577;
167 
168  OSAPI_NtpTime_unpackToMillisec(sec, msec, time);
169  \endverbatim
170 
171  After the above call is made, the variables "sec" and "msec" will
172  contain the equivalent timestamp.
173 
174  The accuracy of this conversion over the whole range of struct OSAPI_NtpTime values
175  is 0.5 milliseconds, except for ntp values above {0x7fffffff, 0x7fffffff},
176  accuracy is up to nearly 1 millisecond.
177 
178  This is a fairly efficient macro. On a 400MHz Pentium-II Linux box
179  the execution time is about 0.08 usec.
180 
181  \verbatim
182  ms/2^22 = frac*1000/1024 = frac*(1 - 24/1024) = frac*(1 - 3/2^7) =
183  frac*(1 - 1/2^6 - 1/2^7)
184  \endverbatim
185 
186  @see struct OSAPI_NtpTime OSAPI_NtpTime_packFromMillisec
187 */
188 OSAPIDllExport void
189 OSAPI_NtpTime_to_millisec(RTI_INT32 *const s, RTI_UINT32 *const msec,
190  const struct OSAPI_NtpTime *const time);
191 
192 
193 /*e \ingroup OSAPITimeClass
194 
195  @brief Macro to convert from seconds and microseconds to struct OSAPI_NtpTime format.
196 
197  @param time (struct OSAPI_NtpTime) to contain the answer.
198  @param s (integer) seconds of the time to covert.
199  @param usec (integer) microseconds fraction to convert from.
200 
201  This macro does not check for overflow, so for a near-infinite time value,
202  the conversion result may end up being negative. It is the caller's
203  responsibility to avoid passing these large time values.
204 
205  Use as indicated by the following code:
206  \verbatim
207  struct OSAPI_NtpTime ntp;
208  long sec, usec;
209  sec = 10;
210  usec = 577;
211 
212  OSAPI_NtpTime_packFromMicrosec(ntp, sec, usec);
213  \endverbatim
214 
215  After the above call is made, the variable ntp will contain the equivalent
216  time stamp in struct OSAPI_NtpTime representation.
217 
218  This macro assumes that msec<1000000. It is the caller's responsibility
219  to ensure this. This is done for performance reasons, the extra check
220  slows the execution a factor of 5! If msec may be greater than 1000000,
221  you can invoke the macro as follows:
222  \verbatim
223  OSAPI_NtpTime_packFromMicrosec(ntp, sec + usec/1000000, usec%1000000);
224  \endverbatim
225 
226  This macro only evaluates its arguments once, so it is safe to invoke it
227  with an argument that has side effects; that is, if you write:
228  \verbatim
229  RTI_UINT32 count = 10;
230  OSAPI_NtpTime_packFromMicrosec(ntp, sec, count++)
231  \endverbatim
232 
233  After the macro, count is guaranteed to be 11.
234 
235  The accuracy of this conversion over the whole range of microsecond values
236  is 0.0028 microseconds.
237 
238  This is a fairly efficient macro. On a 400MHz Pentium-II Linux box
239  the execution time is about 0.08 usec.
240 
241  \verbatim
242  2^12 * ntp.frac = us + us/2^5 + us/2^6 + us/2^10 + us/2^11
243  + us/2^13 + us/2^14 + us/2^15 + us/2^16
244  + us/2^18 + us/2^19 + us/2^20 + us/2^21
245  + us/2^23 + 3e-9
246  = us + us*99/2^11 + us*15/2^16 + us*61/2^23
247  ntp.frac = (us<<12) + (us<<7) + (us<<6) + (us<<2) + (us<<1)
248  + (us>>1) + (us>>2) + (us>>3) + (us>>4)
249  + (us>>6) + (us>>7) + (us>>8) + (us>>9) + (us>>11)
250  = (us<<12) + ((us*99)<<1)+ ((us*15)>>4)+ ((us*61)>>11)
251  \endverbatim
252 */
253 OSAPIDllExport void
254 OSAPI_NtpTime_from_microsec(struct OSAPI_NtpTime *const time, RTI_INT32 s, RTI_UINT32 usec);
255 
256 /*e \ingroup OSAPITimeClass
257 
258  @brief Macro to convert from struct OSAPI_NtpTime to seconds and microseconds.
259 
260  @param s (integer) Holds the second portion.
261  @param usec (integer) holds the microsecond fraction.
262  @param time (struct OSAPI_NtpTime) to be converted.
263 
264  This macro does not check for overflow, so for a near-infinite time value,
265  the conversion result may end up being negative. It is the caller's
266  responsibility to avoid passing these large time values.
267 
268  Use as indicated by the following code:
269  \verbatim
270  struct OSAPI_NtpTime ntp;
271  long sec, usec;
272 
273  ntp.sec = 10;
274  ntp.frac = 577;
275 
276  OSAPI_NtpTime_unpackToMicrosec(sec, usec, ntp);
277  \endverbatim
278 
279  After the above call is made, the variables "sec" and "usec" will
280  contain the equivalent timestamp.
281 
282  The accuracy of this conversion over the whole range of struct OSAPI_NtpTime values
283  is 0.5 microseconds, except for ntp value above {0x7fffffff, 0x7fffffff},
284  accuracy is up to nearly 1 millisecond.
285 
286  This is a fairly efficient macro. On a 400MHz Pentium-II Linux box
287  the execution time is about 0.12 usec.
288 
289  \verbatim
290  us = frac*1000000/2^20 = frac*( 1 - 48576/2^20 )
291  = frac*(1 - 47/2^10 - 7/2^14)
292  = frac - ((47*frac)>>10) - ((7*frac)>>14)
293  = frac - (frac>>5)-(frac>>7)-(frac>>8)-(frac>>9)-(frac>>10)
294  - (frac>>12)-(frac>>13)-(frac>>14)
295  \endverbatim
296 */
297 OSAPIDllExport void
298 OSAPI_NtpTime_to_microsec(RTI_INT32 *const s, RTI_UINT32 *const msec,
299  const struct OSAPI_NtpTime *const time);
300 
301 /*e \ingroup OSAPITimeClass
302 
303  @brief Macro to convert from seconds and nanoseconds to struct OSAPI_NtpTime format.
304 
305  @param time (struct OSAPI_NtpTime) Holds the answer.
306  @param s (integer) Seconds to convert from.
307  @param nsec (integer) Nanosecond fraction to convert from.
308 
309  Use as indicated by the following code:
310  \verbatim
311  struct OSAPI_NtpTime time;
312  long sec, nsec;
313  sec = 10;
314  nsec = 577;
315 
316  OSAPI_NtpTime_packFromNanosec(time, sec, msec);
317  \endverbatim
318 
319  After the above call is made, the variable time will contain the equivalent
320  timestamp in struct OSAPI_NtpTime representation.
321 
322  This macro assumes that nsec<1000000000. It is the caller's responsibility
323  to ensure this. This is done for performance reasons (the extra check
324  slows the execution a factor of 5). If msec may be greater than 1000000, you
325  can invoke the macro as follows:
326  \verbatim}
327  OSAPI_NtpTime_packFromNanosec(time, sec + nsec/1000000000, nsec%1000000000);
328  \endverbatim
329 
330  This macro only evaluates its arguments once, so it is safe to invoke it
331  with an argument that has side effects; that is, if you write:
332  \verbatim
333  RTI_UINT32 count = 10;
334  OSAPI_NtpTime_packFromNanosec(time, sec, count++)
335  \endverbatim
336  After the macro, count is guaranteed to be 11.
337 
338  The accuracy of this conversion over the whole range of nanosecond values
339  is at least 1 nanosecond.
340 */
341 OSAPIDllExport void
342 OSAPI_NtpTime_from_nanosec(struct OSAPI_NtpTime *const time, RTI_INT32 s, RTI_UINT32 nsec);
343 
344 
345 /*e \ingroup OSAPITimeClass
346 
347  @brief Macro to convert from struct OSAPI_NtpTime to seconds and nanoseconds.
348 
349  @param s (integer) Second of the time to covert.
350  @param nsec (integer) Nanosecond fraction to convert.
351  @param time (struct OSAPI_NtpTime) to convert from.
352 
353  Use as indicated by the following code:
354  \verbatim
355  struct OSAPI_NtpTime time;
356  long sec, nsec;
357  time.sec = 10;
358  time.frac = 577;
359 
360  OSAPI_NtpTime_unpackToNanosec(sec, nsec, time);
361  \endverbatim
362  After the above call is made, the variables "sec" and "nsec" will
363  contain the equivalent timestamp.
364 
365  The accuracy of this conversion over the whole range of
366  struct OSAPI_NtpTime values is at least 1 nanosecond.
367 */
368 OSAPIDllExport void
369 OSAPI_NtpTime_to_nanosec(RTI_INT32 *const s, RTI_UINT32 *const nsec,
370  const struct OSAPI_NtpTime *const time);
371 
372 /*e \ingroup OSAPITimeClass
373 
374  A NULL struct OSAPI_NtpTime pointer is considered infinity. This is consistent
375  with the concept of infinite time on UNIX systems.
376 
377  In addition, if the seconds field equals OSAPI_NTP_TIME_SEC_MAX, the
378  time value is also considered infinite.
379 
380  @param time Pointer to RTITime.
381  @return RTI_TRUE if time is infinite, RTI_FALSE otherwise.
382 */
383 OSAPIDllExport RTI_BOOL
384 OSAPI_NtpTime_is_infinite(const struct OSAPI_NtpTime *const time);
385 
386 /*e \ingroup OSAPITimeClass
387 
388  @brief answer = t1 - t2.
389 
390  @param answer struct OSAPI_NtpTime
391  @param t1 struct OSAPI_NtpTime`
392  @param t2 struct OSAPI_NtpTime
393  */
394 OSAPIDllExport void
395 OSAPI_NtpTime_subtract(struct OSAPI_NtpTime *const answer,
396  const struct OSAPI_NtpTime *const t1,
397  const struct OSAPI_NtpTime *const t2);
398 
399 /*e \ingroup OSAPITimeClass
400 
401  @brief answer += time.
402 
403  This macro does not check for overflow.
404 
405  @param answer struct OSAPI_NtpTime
406  @param time struct OSAPI_NtpTime
407 */
408 #define OSAPI_NtpTime_increment(answer, time) \
409 { \
410  register RTI_UINT32 currentFrac = (answer)->frac; \
411  (answer)->sec += (time)->sec; \
412  (answer)->frac += (time)->frac; \
413  if (((answer)->frac < (time)->frac) || ((answer)->frac < currentFrac)) { \
414  (answer)->sec++; \
415  } \
416 }
417 
418 /*e \ingroup OSAPITimeClass
419 
420  @brief Decrement one struct OSAPI_NtpTime value by another struct OSAPI_NtpTime value.
421 
422  Precondition:
423  Postcondition: answer -= time.
424 
425  @param answer struct OSAPI_NtpTime
426  @param time struct OSAPI_NtpTime
427 
428 */
429 #define OSAPI_NtpTime_decrement(answer, time) \
430 { \
431  register RTI_UINT32 currentFrac = (answer)->frac; \
432  (answer)->sec -= (time)->sec; \
433  (answer)->frac -= (time)->frac; \
434  if (((answer)->frac > currentFrac)) { (answer)->sec--; } \
435 }
436 
437 /*e \ingroup OSAPITimeClass
438 
439  @brief Zero time.
440 
441  This global variable is for convenience. It allows you to see if a
442  RTITime variable is negative or positive by comparing against this.
443 
444  @see RtiTimeCompare
445 */
446 #define OSAPI_NTP_TIME_ZERO {0,0}
447 
448 /*e \ingroup OSAPITimeClass
449 
450  Represents the maximum timevalue that can be represented using the
451  NTP time format. For all practical purposes, it can be considered
452  equivalent to infinity.
453 
454 */
455 #define OSAPI_NTP_TIME_MAX {OSAPI_NTP_TIME_SEC_MAX,OSAPI_NTP_TIME_FRAC_MAX}
456 
457 /*e \ingroup OSAPITimeClass
458  The number of nanoseconds per second. 1e9.
459  @see RtiTimePack RtiTimeUnpack
460 */
461 #define OSAPI_NTP_TIME_NSEC_PER_SEC (1000000000)
462 /*e \ingroup OSAPITimeClass
463  The number of microseconds per second. 1e6.
464  @see RtiTimePack RtiTimeUnpack
465 */
466 #define OSAPI_NTP_TIME_USEC_PER_SEC (1000000)
467 /*e \ingroup OSAPITimeClass
468  The number of milliseconds per second. 1e3.
469  @see RtiTimePack RtiTimeUnpack
470  */
471 #define OSAPI_NTP_TIME_MSEC_PER_SEC (1000)
472 /*e \ingroup OSAPITimeClass
473  The number of microseconds per milliseconds. 1e3.
474  @see RtiTimePack RtiTimeUnpack
475  */
476 #define OSAPI_NTP_TIME_NSEC_PER_USEC (1000)
477 /*e \ingroup OSAPITimeClass
478  The number of microseconds per milliseconds. 1e3.
479  @see RtiTimePack RtiTimeUnpack
480 */
481 #define OSAPI_NTP_TIME_USEC_PER_MSEC (1000)
482 /*e \ingroup OSAPITimeClass
483  The number of seconds per second. 1.
484  @see RtiTimePack RtiTimeUnpack
485  */
486 #define OSAPI_NTP_TIME_SEC_PER_SEC (1)
487 
488 /*e \ingroup OSAPITimeClass
489  The number of nano seconds per milli second. 1e6.
490  @see RtiTimePack RtiTimeUnpack
491  */
492 #define OSAPI_NTP_TIME_NSEC_PER_MSEC (1000000)
493 
494 #ifdef __cplusplus
495 } /* extern "C" */
496 #endif
497 
498 #endif /* osapi_time_h */

RTI Connext Micro Version 2.4.4.0 Copyright © Thu Apr 30 2015 Real-Time Innovations, Inc