- HandlerMinelayerData: BUILD_RTI Guards für RTI-Abhängigkeiten - svcTabCommon: Export-Header-Fix via Fallback-Target - TrainingAreaBase: Stub-Header für BUILD_RTI=OFF - ddsfts: Include-Pfad und Dependency-Fixes - BUILD_RTI=OFF Compilation vollständig unterstützt Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Entire-Checkpoint: 01M0JNZA586SACX1PRZ2DJAE5S
959 lines
29 KiB
C
959 lines
29 KiB
C
/*
|
|
* (c) Copyright, Real-Time Innovations, 2005-2024.
|
|
* All rights reserved.
|
|
*
|
|
* No duplications, whole or partial, manual or electronic, may be made
|
|
* without express written permission. Any such copies, or
|
|
* revisions thereof, must display this notice unaltered.
|
|
* This code contains trade secrets of Real-Time Innovations, Inc.
|
|
*/
|
|
|
|
#ifndef osapi_ntptime_h
|
|
#define osapi_ntptime_h
|
|
|
|
#include "osapi/osapi_type.h"
|
|
#include "osapi/osapi_dll.h"
|
|
|
|
#if defined(RTI_VXWORKS)
|
|
#include "osapi/osapi_vxVersions.h"
|
|
#if VXWORKS_VERSION_6_3_OR_BETTER
|
|
#include <sys/time.h>
|
|
#endif
|
|
#elif defined(RTI_WIN32)
|
|
#include <sys/timeb.h>
|
|
#elif defined(RTI_UNIX) || defined(RTI_LYNX) || defined(RTI_QNX) \
|
|
|| defined(RTI_INTIME)
|
|
#if defined(RTI_LYNX) && !defined(RTI_LYNXOS_SE) && !defined(RTI_LYNX500)
|
|
#include <time.h>
|
|
#else
|
|
#include <sys/time.h>
|
|
#endif
|
|
#elif defined(RTI_INTY)
|
|
#include <INTEGRITY.h>
|
|
#endif
|
|
|
|
#ifdef RTI_64BIT_TIME_T
|
|
#define RTI_TIME_T time_t
|
|
#else
|
|
#define RTI_TIME_T RTI_INT64
|
|
#endif
|
|
|
|
#ifdef __cplusplus
|
|
extern "C" {
|
|
#endif
|
|
|
|
/** @internal \file
|
|
* \brief NTP time API
|
|
*/
|
|
|
|
/** @internal \defgroup RTINtpTimeClass RTINtpTime
|
|
* \ingroup RTIOsapiModule
|
|
*
|
|
* @brief NTP Time representation.
|
|
*
|
|
* Expresses time in NTP format. The second field is simply an integer
|
|
* expressing seconds. The fraction field expresses 1/2^32 of a second.
|
|
* We strongly urge customers to use our provided macros to convert this
|
|
* format to and from human readable form.
|
|
*
|
|
* When working with RTINtpTime there isn't a concrete INFINITY value defined.
|
|
* For all practical purposes, we consider the maximum value, and every other
|
|
* value above this maximum as INFINITY. To check for INFINITY, use the
|
|
* RTINtpTime_isInfinite macro. Never check for a specific value.
|
|
*
|
|
* \b Example:
|
|
*
|
|
* The following is a simple example on how to prepare a RTINtpTime structure
|
|
* to be 1.5 seconds.
|
|
*
|
|
* \verbatim
|
|
* RTINtpTime ntpTime;
|
|
*
|
|
* RTINtpTime_packFromMillisec(ntpTime, 1, 500);
|
|
* \endverbatim
|
|
*
|
|
* @see RTINtpTime_packFromMillisec RTINtpTime_packFromMicrosec
|
|
* @see RTINtpTime_packFromNanosec
|
|
* @see RtiNtpTimeUnpackFromMillisec RtiNtpTimeUnpackFromMicrosec
|
|
* @see RtiNtpTimeUnpackFromNanosec
|
|
*/
|
|
typedef struct RTINtpTime {
|
|
/** @internal Seconds.**/
|
|
RTI_INT64 sec;
|
|
/** @internal fraction of a second in 1/2^32 form.*/
|
|
RTI_UINT32 frac;
|
|
} RTINtpTime;
|
|
|
|
/** @internal \ingroup RTINtpTimeClass
|
|
* \brief The size of a serialized RTINtpTime.
|
|
*/
|
|
#define RTI_OSAPI_NTPTIME_SERIALIZED_SIZE \
|
|
(sizeof(RTI_INT64) + sizeof(RTI_UINT32))
|
|
|
|
/** @internal \ingroup RTINtpTimeClass
|
|
|
|
Represents infinite time value. Handy for specifying no timeout or
|
|
sleeping forever.
|
|
*/
|
|
#define RTI_NTP_TIME_INFINITE ((RTINtpTime *) NULL)
|
|
|
|
/** @internal \ingroup RTINtpTimeClass
|
|
|
|
@brief Zero time.
|
|
|
|
This global variable is for convenience. This allows users to
|
|
check and see if a RTITime variable is negative or positive by comparing
|
|
against this.
|
|
|
|
@see RtiTimeCompare
|
|
*/
|
|
#define RTI_NTP_TIME_ZERO \
|
|
{ \
|
|
0, 0 \
|
|
}
|
|
|
|
/** @internal \ingroup RTINtpTimeClass
|
|
|
|
Represents maximum timevalue that can be represented using the
|
|
NTP time format. For all practical purposes, can be considered
|
|
equivalent to infinity.
|
|
|
|
*/
|
|
#define RTI_NTP_TIME_MAX \
|
|
{ \
|
|
RTI_NTP_TIME_SEC_MAX, RTI_NTP_TIME_FRAC_MAX \
|
|
}
|
|
|
|
/** @internal \ingroup RTINtpTimeClass
|
|
The maximum number of seconds, 4294967295, that can be represented using NTP
|
|
time. This value is the maximum range of an unsigned 32-bit.
|
|
*/
|
|
#define RTI_NTP_TIME_SEC_MAX 0x00000000FFFFFFFFLL
|
|
|
|
/** @internal
|
|
* \ingroup RTINtpTimeClass
|
|
* The minimum number of seconds that can be represented using NTP time.
|
|
* This value, 0xFFFFFFFF00000001 represent the -4294967295 in two's complement.
|
|
*/
|
|
#define RTI_NTP_TIME_SEC_MIN ((RTI_INT64) 0xFFFFFFFF00000001)
|
|
|
|
/** @internal \ingroup RTINtpTimeClass
|
|
The largest possible value of the fraction field in NTP time.
|
|
*/
|
|
#define RTI_NTP_TIME_FRAC_MAX ((RTI_UINT32) 0xffffffff)
|
|
|
|
/** @internal \ingroup RTINtpTimeClass
|
|
|
|
The AUTO value semantic depends on the usage.
|
|
|
|
*/
|
|
#define RTI_NTP_TIME_AUTO \
|
|
{ \
|
|
RTI_NTP_TIME_SEC_AUTO, RTI_NTP_TIME_FRAC_AUTO \
|
|
}
|
|
|
|
/** @internal \ingroup RTINtpTimeClass
|
|
The number of seconds corresponding to RTI_NTP_TIME_AUTO.
|
|
*/
|
|
#define RTI_NTP_TIME_SEC_AUTO ((RTI_INT64) 0xffffffffffffffff)
|
|
|
|
/** @internal \ingroup RTINtpTimeClass
|
|
The fraction of seconds corresponding to RTI_NTP_TIME_AUTO.
|
|
*/
|
|
#define RTI_NTP_TIME_FRAC_AUTO 0U
|
|
|
|
/** @internal \ingroup RTINtpTimeClass
|
|
The number of seconds corresponding to RTI_NTP_TIME_INVALID.
|
|
*/
|
|
#define RTI_NTP_TIME_SEC_INVALID ((RTI_INT64) 0xffffffffffffffff)
|
|
|
|
/** @internal \ingroup RTINtpTimeClass
|
|
The fraction of seconds corresponding to RTI_NTP_TIME_INVALID.
|
|
*/
|
|
#define RTI_NTP_TIME_FRAC_INVALID RTI_NTP_TIME_FRAC_MAX
|
|
|
|
/** @internal
|
|
* \ingroup RTINtpTimeClass
|
|
*
|
|
* @brief Invalid time.
|
|
*
|
|
* Represents an invalid timevalue that can be represented using the NTP time
|
|
* format.
|
|
*/
|
|
#define RTI_NTP_TIME_INVALID \
|
|
{ \
|
|
RTI_NTP_TIME_SEC_INVALID, RTI_NTP_TIME_FRAC_INVALID \
|
|
}
|
|
|
|
/** @internal
|
|
* @brief This define represents the maximum size of a string containing an
|
|
* NTP Time. So since the NTP Time structure contains an RTI_INT64, and a
|
|
* RTI_UINT32 attribute, the value result of the following:
|
|
* - RTI_INT64: 1 - 19 bytes
|
|
* - RTI_UINT32: 1 - 9 bytes
|
|
* - 4 extra characters: '{' + ',' + '}'' + '\0'
|
|
* 19 + 9 + 4 = 32
|
|
*/
|
|
#define RTI_NTP_TIME_STRING_LEN (32)
|
|
|
|
/** @internal \ingroup RTINtpTimeClass
|
|
* @brief Set RTINtpTime time to zero.
|
|
*
|
|
* @param time (RTINtpTime*) Pointer to RTINtpTime struct that needs to be
|
|
* set to zero.
|
|
*/
|
|
extern RTIOsapiDllExport void RTINtpTime_setZero(struct RTINtpTime *time);
|
|
|
|
/** @internal \ingroup RTINtpTimeClass
|
|
* @brief Set RTINtpTime time to maximum value.
|
|
*
|
|
* @param time (RTINtpTime*) Pointer to RTINtpTime struct that needs to be
|
|
* set to its maximum possible value.
|
|
*
|
|
* The maximum possible value equals:
|
|
*
|
|
* (time).sec = RTI_NTP_TIME_SEC_MAX
|
|
* (time).frac = RTI_NTP_TIME_FRAC_MAX
|
|
*/
|
|
extern RTIOsapiDllExport void RTINtpTime_setMax(struct RTINtpTime *time);
|
|
|
|
/** @internal
|
|
* \ingroup RTINtpTimeClass
|
|
*
|
|
* @brief convert to double
|
|
*
|
|
* "t" cannot exceed the maximum value supported by an unsigned 32 bit integer
|
|
* 4294967295. If the value exceeded the limit it will be capped to the maximum.
|
|
*/
|
|
extern RTIOsapiDllExport void RTINtpTime_toDouble(
|
|
const struct RTINtpTime *t,
|
|
RTI_DOUBLE64 *value);
|
|
|
|
/** @internal
|
|
* \ingroup RTINtpTimeClass
|
|
*
|
|
* @brief convert to RTI_UINT64
|
|
*
|
|
* This functions convert t into an RTIRtpsTime to not overflow.
|
|
*/
|
|
extern RTIOsapiDllExport void RTINtpTime_toUInt64(
|
|
const struct RTINtpTime *t,
|
|
RTI_UINT64 *value);
|
|
|
|
/** @internal
|
|
* \ingroup RTINtpTimeClass
|
|
*
|
|
* @brief convert to RTINtpTime from an RTI_UINT64
|
|
*
|
|
* This functions first convert value into an RTIRtpsTime and then into an
|
|
* RTINtpTime.
|
|
*/
|
|
extern RTIOsapiDllExport void RTINtpTime_fromUInt64(
|
|
struct RTINtpTime *t,
|
|
RTI_UINT64 value);
|
|
|
|
/** @internal \ingroup RTINtpTimeClass
|
|
* @brief Copy an RTINtpTime struct.
|
|
*
|
|
* @param out. The destination of the copy.
|
|
* @param in. The source of the copy.
|
|
*/
|
|
extern RTIOsapiDllExport void RTINtpTime_copy(
|
|
struct RTINtpTime *out,
|
|
const struct RTINtpTime *in);
|
|
|
|
/** @internal \ingroup RTINtpTimeClass
|
|
*
|
|
* @brief Macro to convert from sec and milli-seconds to RTINtpTime format.
|
|
*
|
|
* @param time (RTINtpTime) contains the answer.
|
|
* @param s (long long) Second to convert.
|
|
* @param msec (millisecond) fraction portion (less than 1000).
|
|
*
|
|
* \verbatim
|
|
* RTINtpTime time;
|
|
* RTI_INT64 sec;
|
|
* RTI_INT32 msec;
|
|
* sec = 10;
|
|
* msec = 577;
|
|
*
|
|
* RTINtpTime_packFromMillisec(time, sec, msec);
|
|
* \endverbatim
|
|
*
|
|
* After the above call is made, the variable time will contain the equivalent
|
|
* time stamp in RTINtpTime representation.
|
|
*
|
|
* This macro assumes that msec<1000. It is the callers responsibility
|
|
* to ensure this. This is done for performance reasons, the extra check slows
|
|
* the execution a factor of 5! If msec may be greater than 1000, you can invoke
|
|
* the macro as follows:
|
|
* \verbatim
|
|
* RTINtpTime_packFromMillisec(time, sec + msec/1000, msec%1000);
|
|
* \endverbatim
|
|
*
|
|
* This macro only evaluates its arguments once, so it is safe to invoke it
|
|
* with an argument that has side effects, that is. if you write:
|
|
* \verbatim
|
|
* RTI_UINT32 count = 10;
|
|
* RTINtpTime_packFromMillisec(time, sec, count++)
|
|
* \endverbatim
|
|
* After the macro count is guaranteed to be 11.
|
|
*
|
|
* The accuracy of this conversion over the whole range of millisecond values
|
|
* is 0.013 milli-seconds.
|
|
*
|
|
* This is a fairly efficient macro. On a 400MHz Pentium-II linux box
|
|
* the execute time is about 0.06 usec.
|
|
*
|
|
* \verbatim
|
|
* 2^22*time.frac = ms + ms/2^6 + ms/2^7 + ms/2^11 + ms/2^14 + 1.3e-5
|
|
* = ms + ms*393/2^14;
|
|
* time.frac = (ms<<22) + (ms<<16) + (ms<<15) + (ms<<11) + (ms<<8)
|
|
* = (ms<<22) + ((ms*393)<<8)
|
|
* \endverbatim
|
|
*
|
|
* @see RTINtpTime RTINtpTime_unpackToMillisec
|
|
*/
|
|
extern RTIOsapiDllExport void RTINtpTime_packFromMillisec(
|
|
struct RTINtpTime time,
|
|
long long s,
|
|
RTI_UINT32 msec);
|
|
|
|
/** @internal \ingroup RTINtpTimeClass
|
|
*
|
|
* @brief Macro to convert from RTINtpTime to sec and milli-seconds.
|
|
*
|
|
* @param s (long long) Holds the seconds answer.
|
|
* @param msec (integer) Holds the millisecond answer.
|
|
* @param time (RTINtpTime) The time to convert to seconds and milliseconds.
|
|
*
|
|
* This macro does not check for overflow, so for a near infinite time value,
|
|
* the conversion result may end up being negative. It is the responsibility
|
|
* of the user to avoid passing these large time values.
|
|
*
|
|
* Use as indicated by the following code:
|
|
* \verbatim}
|
|
* RTINtpTime time;
|
|
* RTI_INT64 sec;
|
|
* RTI_INT32 msec;
|
|
*
|
|
* time.sec = 10;
|
|
* time.frac = 577;
|
|
*
|
|
* RTINtpTime_unpackToMillisec(sec, msec, time);
|
|
* \endverbatim
|
|
*
|
|
* After the above call is made, the variables "sec" and "msec" will
|
|
* contain the equivalent time stamp.
|
|
*
|
|
* The accuracy of this conversion is approx. 0.5 milli-seconds.
|
|
*
|
|
* This is a fairly efficient macro. On a 400MHz Pentium-II linux box
|
|
* the execute time is about 0.08 usec
|
|
*
|
|
* \verbatim
|
|
* ms/2^22 = frac*1000/1024 = frac*(1 - 24/1024) = frac*(1 - 3/2^7) =
|
|
* frac*(1 - 1/2^6 - 1/2^7)
|
|
* \endverbatim
|
|
*
|
|
* @see RTINtpTime RTINtpTime_packFromMillisec
|
|
* @todo arguments don't make sense because this is implemented as a macro
|
|
*/
|
|
extern RTIOsapiDllExport void RTINtpTime_unpackToMillisec(
|
|
long long s,
|
|
unsigned msec,
|
|
struct RTINtpTime time);
|
|
|
|
/** @internal \ingroup RTINtpTimeClass
|
|
*
|
|
* @brief Macro to convert from sec and micro-seconds to RTINtpTime format.
|
|
*
|
|
* @param time (RTINtpTime) to contain the answer.
|
|
* @param s (long long) second of the time to covert.
|
|
* @param usec (integer) microsecond fraction to convert from.
|
|
*
|
|
* This macro does not check for overflow, so for a near infinite time value,
|
|
* the conversion result may end up being negative. It is the responsibility
|
|
* of the user to avoid passing these large time values.
|
|
*
|
|
* Use as indicated by the following code:
|
|
* \verbatim
|
|
* RTINtpTime ntp;
|
|
* RTI_INT64 sec;
|
|
* RTI_INT32 usec;
|
|
* sec = 10;
|
|
* usec = 577;
|
|
*
|
|
* RTINtpTime_packFromMicrosec(ntp, sec, usec);
|
|
* \endverbatim
|
|
*
|
|
* After the above call is made, the variable ntp will contain the equivalent
|
|
* time stamp in RTINtpTime representation.
|
|
*
|
|
* This macro assumes that msec<1000000. It is the callers responsibility
|
|
* to ensure this. This is done for performance reasons, the extra check
|
|
* slows the execution a factor of 5! If msec may be greater than 1000000,
|
|
* you can invoke the macro as follows:
|
|
* \verbatim
|
|
* RTINtpTime_packFromMicrosec(ntp, sec + usec/1000000, usec%1000000);
|
|
* \endverbatim
|
|
*
|
|
* This macro only evaluates its arguments once, so it is safe to invoke it
|
|
* with an argument that has side effects, that is. if you write:
|
|
* \verbatim
|
|
* RTI_UINT32 count = 10;
|
|
* RTINtpTime_packFromMicrosec(ntp, sec, count++)
|
|
* \endverbatim
|
|
*
|
|
* After the macro count is guaranteed to be 11.
|
|
*
|
|
* The accuracy of this conversion over the whole range of microsecond values
|
|
* is 0.0028 micro-seconds.
|
|
*
|
|
* This is a fairly efficient macro. On a 400MHz Pentium-II linux box
|
|
* the execute time is about 0.08 usec
|
|
*
|
|
* \verbatim
|
|
* 2^12 * ntp.frac = us + us/2^5 + us/2^6 + us/2^10 + us/2^11
|
|
* + us/2^13 + us/2^14 + us/2^15 + us/2^16
|
|
* + us/2^18 + us/2^19 + us/2^20 + us/2^21
|
|
* + us/2^23 + 3e-9
|
|
* = us + us*99/2^11 + us*15/2^16 + us*61/2^23
|
|
* ntp.frac = (us<<12) + (us<<7) + (us<<6) + (us<<2) + (us<<1)
|
|
* + (us>>1) + (us>>2) + (us>>3) + (us>>4)
|
|
* + (us>>6) + (us>>7) + (us>>8) + (us>>9) +
|
|
* (us>>11) = (us<<12) + ((us*99)<<1)+ ((us*15)>>4)+ ((us*61)>>11) \endverbatim
|
|
*/
|
|
extern RTIOsapiDllExport void RTINtpTime_packFromMicrosec(
|
|
struct RTINtpTime time,
|
|
long long s,
|
|
RTI_UINT32 usec);
|
|
|
|
/** @internal \ingroup RTINtpTimeClass
|
|
*
|
|
* @brief Macro to convert from RTINtpTime to sec and micro-seconds.
|
|
*
|
|
* @param s (long long) Holds the second portion.
|
|
* @param usec (integer) holds the microsecond fraction.
|
|
* @param time (RTINtpTime) to be converted.
|
|
*
|
|
* This macro does not check for overflow, so for a near infinite time value,
|
|
* the conversion result may end up being negative. It is the responsibility
|
|
* of the user to avoid passing these large time values.
|
|
*
|
|
* Use as indicated by the following code:
|
|
* \verbatim
|
|
* RTINtpTime ntp;
|
|
* RTI_INT64 sec;
|
|
* RTI_INT32 usec;
|
|
*
|
|
* ntp.sec = 10;
|
|
* ntp.frac = 577;
|
|
*
|
|
* RTINtpTime_unpackToMicrosec(sec, usec, ntp);
|
|
* \endverbatim
|
|
*
|
|
* After the above call is made, the variables "sec" and "usec" will
|
|
* contain the equivalent time stamp.
|
|
*
|
|
* The accuracy of this conversion is approx 0.5 nano-seconds.
|
|
*
|
|
* This is a fairly efficient macro. On a 400MHz Pentium-II linux box
|
|
* the execute time is about 0.12 usec
|
|
*
|
|
* \verbatim
|
|
* us = frac*1000000/2^20 = frac*( 1 - 48576/2^20 )
|
|
* = frac*(1 - 47/2^10 - 7/2^14)
|
|
* = frac - ((47*frac)>>10) - ((7*frac)>>14)
|
|
* = frac - (frac>>5)-(frac>>7)-(frac>>8)-(frac>>9)-(frac>>10)
|
|
* - (frac>>12)-(frac>>13)-(frac>>14)
|
|
* \endverbatim
|
|
* @todo arguments don't make sense because this is implemented as a macro
|
|
*/
|
|
extern RTIOsapiDllExport void RTINtpTime_unpackToMicrosec(
|
|
long long s,
|
|
unsigned usec,
|
|
struct RTINtpTime time);
|
|
|
|
/** @internal \ingroup RTINtpTimeClass
|
|
*
|
|
* @brief Macro to convert from sec and nano-seconds to RTINtpTime format.
|
|
*
|
|
* @param time (RTINtpTime) Holds the answer.
|
|
* @param s (long long) Seconds to convert from.
|
|
* @param nsec (integer) nanosecond fraction to convert from.
|
|
*
|
|
* Use as indicated by the following code:
|
|
* \verbatim
|
|
* RTINtpTime time;
|
|
* RTI_INT64 sec;
|
|
* RTI_INT32 nsec;
|
|
* sec = 10;
|
|
* nsec = 577;
|
|
*
|
|
* RTINtpTime_packFromNanosec(time, sec, msec);
|
|
* \endverbatim
|
|
*
|
|
* After the above call is made, the variable time will contain the equivalent
|
|
* time stamp in RTINtpTime representation.
|
|
*
|
|
* This macro assumes that nsec<1000000000. It is the callers responsibility
|
|
* to ensure this. This is done for performance reasons. If nsec may be greater
|
|
* or equal to 1000000000, you can invoke the macro as follows:
|
|
* \verbatim}
|
|
* RTINtpTime_packFromNanosec(time, sec + nsec/1000000000, nsec%1000000000);
|
|
* \endverbatim
|
|
*
|
|
* This macro only evaluates its arguments once, so it is safe to invoke it
|
|
* with an argument that has side effects, that is. if you write:
|
|
* \verbatim
|
|
* RTI_UINT32 count = 10;
|
|
* RTINtpTime_packFromNanosec(time, sec, count++)
|
|
* \endverbatim
|
|
* After the macro count is guaranteed to be 11.
|
|
*
|
|
* The accuracy of this conversion over the whole range of nanosecond values
|
|
* is 0.25 nano-second,
|
|
*/
|
|
extern RTIOsapiDllExport void RTINtpTime_packFromNanosec(
|
|
struct RTINtpTime time,
|
|
long long s,
|
|
RTI_UINT32 nsec);
|
|
|
|
/** @internal \ingroup RTINtpTimeClass
|
|
*
|
|
* @brief Macro to convert from RTINtpTime to sec and nano-seconds.
|
|
*
|
|
* @param s (long long) Second of the time to covert
|
|
* @param usec (integer) Microsecond fraction to convert.
|
|
* @param time (RTINtpTime) to convert from.
|
|
*
|
|
* Use as indicated by the following code:
|
|
* \verbatim
|
|
* RTINtpTime time;
|
|
* RTI_INT64 sec;
|
|
* RTI_INT32 nsec;
|
|
* time.sec = 10;
|
|
* time.frac = 577;
|
|
*
|
|
* RTINtpTime_unpackToNanosec(sec, nsec, time);
|
|
* \endverbatim
|
|
* After the above call is made, the variables "sec" and "nsec" will
|
|
* contain the equivalent time stamp.
|
|
*
|
|
* The accuracy of this conversion is approx. 1 nsec.
|
|
*
|
|
* @todo arguments don't make sense because this is implemented as a macro
|
|
*/
|
|
extern RTIOsapiDllExport void RTINtpTime_unpackToNanosec(
|
|
long long s,
|
|
unsigned nsec,
|
|
struct RTINtpTime time);
|
|
|
|
/** @internal \ingroup RTINtpTimeClass
|
|
*
|
|
* @brief Macro to convert numerator/denom_per_sec into the ntp time.
|
|
*
|
|
* @param time RTINtpTime to contain the result. The existing
|
|
* content of time does not affect the result, as it should not.
|
|
*
|
|
* @param numerator May be larger than denominator. Since this is a macro
|
|
* and numerator is evaluated multiple times, you shouldn't specify things
|
|
* like (i++).
|
|
*
|
|
* @param denominator_per_sec Denominator.
|
|
* Physically, this means ticks per sec. Since this is a macro and
|
|
* denominator is evaluated multiple times, you shouldn't specify things
|
|
* like (i++).
|
|
*/
|
|
extern RTIOsapiDllExport void RTINtpTime_packFromFraction(
|
|
struct RTINtpTime time,
|
|
RTI_UINT32 numerator,
|
|
RTI_UINT32 denominator_per_sec);
|
|
|
|
/** @internal \ingroup RTINtpTimeClass
|
|
*
|
|
* @brief Transforms from RTINtpTime to any integral fraction of second without
|
|
* using floating point operations.
|
|
*
|
|
* @param numerator RTI_UINT32 where to put the result of the conversion.
|
|
*
|
|
* @param denominator_per_sec the number of units of the fraction contained in
|
|
* a second. Should be 1000 to convert to millisec, or 60 if using default
|
|
* Vx clock rate, or whatever.
|
|
*
|
|
* @param time RTINtpTime to unpack
|
|
*
|
|
* The algorithm is based on the observation that the time.frac looked
|
|
* as a sequence of bits: b[1], b[2], b[3], ... represents the
|
|
* following expansion
|
|
*
|
|
* time_in_sec = b[1]*1/2 + b[1]*1/4 +...+ b[2]*1/8
|
|
* = Sum{i=1..32} b[i]*1/2^i
|
|
*
|
|
* So given that what we want to obtain is the time in units of which
|
|
* there are denominator_per_sec units in a second, the arithmetic is:
|
|
*
|
|
* time_in_units = denominator_per_sec*time_in_sec
|
|
* = denominator_per_sec*time.sec+denominator_per_sec*time.frac
|
|
*
|
|
* And denominator_per_sec*time.frac =
|
|
* Sum{i=1..32} b[i]*(denominator_per_sec/2^i)
|
|
* the key here is that b[i] is easily computed as (1<<31)>>(i-1)
|
|
* and (denominator_per_sec/2^i) is easily computed as denominator_per_sec>>i
|
|
*
|
|
* Note that each time we compute (denominator_per_sec/2^i) to add it we may
|
|
* be off by one unit. Therefore at the end of the computation we may
|
|
* be off by log2(denominator_per_sec) units which means we should in fact
|
|
* perform each step with an accuracy of log2(2*denominator_per_sec)
|
|
* greater. In other words, we should use units a factor
|
|
* log2(2*denominator_per_sec) greater than the ones we require at the end
|
|
* of the conversion.
|
|
*
|
|
* The other key observation is that the computation can end as soon
|
|
* as (denominator_per_sec<<RTI_NTP_TIME_PRECISION_BITS_DEFAULT)>>i becomes
|
|
* zero because that means that what is left has a significance of
|
|
* less than one unit>>RTI_NTP_TIME_PRECISION_BITS_DEFAULT. This will give a
|
|
* conversion that is strictly
|
|
* smaller than the NTP timestamp. For example, for millisecond
|
|
* conversion log2(1000) = 10 so we will do 10 operations so we need a
|
|
* precision 1/20 or 5 bits (4 bits gives 1/16, 5 gives 1/32).
|
|
*
|
|
* The final operation:
|
|
* (precision_units + (1<<RTI_NTP_TIME_PRECISION_BITS_DEFAULT-1))>>
|
|
* RTI_NTP_TIME_PRECISION_BITS_DEFAULT;
|
|
* makes sure that the integer division by
|
|
* 2^(RTI_NTP_TIME_PRECISION_BITS_DEFAULT) is
|
|
* rounded off to the closest number.
|
|
*
|
|
* @todo arguments don't make sense because this is implemented as a macro
|
|
*/
|
|
extern RTIOsapiDllExport void RTINtpTime_unpackToFraction(
|
|
unsigned numerator,
|
|
unsigned denominator_per_sec,
|
|
struct RTINtpTime time);
|
|
|
|
/* \ingroup RTINtpTimeClass
|
|
* @todo arguments don't make sense because this is implemented as a macro
|
|
*/
|
|
extern RTIOsapiDllExport void RTINtpTime_unpackToFractionPrecise(
|
|
unsigned numerator,
|
|
unsigned denominator_per_sec,
|
|
struct RTINtpTime time,
|
|
unsigned precisionBits);
|
|
|
|
/** @internal \ingroup RTINtpTimeClass
|
|
*
|
|
* @brief Function to convert from sec (expressed as a double) to RTINtpTime
|
|
* format.
|
|
*
|
|
* @param time (RTINtpTime) to contain the answer.
|
|
* @param num (double) seconds to convert, e.g. 3.14
|
|
*
|
|
* After the above call is made, the variable time will contain the equivalent
|
|
* timestamp in RTINtpTime representation.
|
|
*
|
|
* Note: this is not implemented in a header file because math.h's log may
|
|
* collide with the log defined in another RTI header file.
|
|
*/
|
|
extern RTIOsapiDllExport void RTINtpTime_packFromDouble(
|
|
struct RTINtpTime *time,
|
|
double num);
|
|
|
|
/** @internal \ingroup RTINtpTimeClass
|
|
*
|
|
* @brief Compare two RTINtpTimes.
|
|
*
|
|
* @param time1 RTINtpTime, NOT NULL.
|
|
* @param time2 RTINtpTime, NOT NULL.
|
|
*
|
|
* @return If time1 > time2 then return 1. If time1 < time2 then return -1.
|
|
* If time1 == time2 then return 0.
|
|
*/
|
|
extern RTIOsapiDllExport int RTINtpTime_compare(
|
|
const struct RTINtpTime time1,
|
|
const struct RTINtpTime time2);
|
|
|
|
/** @internal \ingroup RTINtpTimeClass
|
|
*
|
|
* @brief Get the min of two RTINtpTimes.
|
|
*/
|
|
extern RTIOsapiDllExport void RTINtpTime_min(
|
|
struct RTINtpTime answer,
|
|
const struct RTINtpTime time1,
|
|
const struct RTINtpTime time2);
|
|
|
|
/** @internal \ingroup RTINtpTimeClass
|
|
*
|
|
* @brief Get the max of two RTINtpTimes.
|
|
*/
|
|
extern RTIOsapiDllExport void RTINtpTime_max(
|
|
struct RTINtpTime answer,
|
|
const struct RTINtpTime time1,
|
|
const struct RTINtpTime time2);
|
|
|
|
/** @internal \ingroup RTINtpTimeClass
|
|
*
|
|
* @brief answer = t1 + t2.
|
|
*
|
|
* This macro does not check for overflow (faster).
|
|
*
|
|
* @param answer RTINtpTime
|
|
* @param t1 RTINtpTime
|
|
* @param t2 RTINtpTime
|
|
*/
|
|
extern RTIOsapiDllExport void RTINtpTime_add(
|
|
struct RTINtpTime answer,
|
|
struct RTINtpTime t1,
|
|
struct RTINtpTime t2);
|
|
|
|
/** @internal \ingroup RTINtpTimeClass
|
|
*
|
|
* @brief answer = t1 - t2.
|
|
*
|
|
* @param answer RTINtpTime
|
|
* @param t1 RTINtpTime
|
|
* @param t2 RTINtpTime
|
|
*/
|
|
extern RTIOsapiDllExport void RTINtpTime_subtract(
|
|
struct RTINtpTime answer,
|
|
struct RTINtpTime t1,
|
|
struct RTINtpTime t2);
|
|
|
|
/** @internal \ingroup RTINtpTimeClass
|
|
*
|
|
* @brief answer = time << shift.
|
|
*
|
|
* To use this macro for multiplying by a num, shift can be calculated
|
|
* as log10(num)/log10(2).
|
|
*
|
|
* This macro only support shifting 32 bits.
|
|
*
|
|
* @param answer RTINtpTime
|
|
* @param time RTINtpTime
|
|
* @param shift int Cannot exceeds 32 bits.
|
|
*/
|
|
extern RTIOsapiDllExport void RTINtpTime_shiftLeft(
|
|
struct RTINtpTime answer,
|
|
struct RTINtpTime time,
|
|
int shift);
|
|
|
|
/** @internal \ingroup RTINtpTimeClass
|
|
*
|
|
* @brief answer = time >> shift.
|
|
*
|
|
* To use this macro for dividing by a num, shift can be calculated
|
|
* as log10(num)/log10(2).
|
|
*
|
|
* This macro only support shifting 32 bits.
|
|
*
|
|
* @param answer RTINtpTime
|
|
* @param time RTINtpTime
|
|
* @param shift int Cannot exceeds 32 bits.
|
|
*/
|
|
extern RTIOsapiDllExport void RTINtpTime_shiftRight(
|
|
struct RTINtpTime answer,
|
|
struct RTINtpTime time,
|
|
int shift);
|
|
|
|
/** @internal \ingroup RTINtpTimeClass
|
|
*
|
|
* @brief answer = time * (percentScaler / 100).
|
|
*
|
|
* Scales time by a percentage-factor.
|
|
*
|
|
* This operation assumes that seconds cannot be greater than
|
|
* RTI_NTP_TIME_SEC_MAX.
|
|
*
|
|
* @param answer RTINtpTime
|
|
* @param time RTINtpTime
|
|
* @param percentScaler RTI_INT32
|
|
*/
|
|
extern RTIOsapiDllExport void RTINtpTime_scale(
|
|
struct RTINtpTime *answer,
|
|
struct RTINtpTime *time,
|
|
RTI_INT32 percentScaler);
|
|
|
|
/** @internal \ingroup RTINtpTimeClass
|
|
*
|
|
* @brief answer = time / divisor.
|
|
*
|
|
* Divides time by an integral divisor. Answer resolution limited to 16.16
|
|
*
|
|
* This operation assumes that seconds cannot be greater than
|
|
* RTI_NTP_TIME_SEC_MAX.
|
|
*
|
|
* @param answer RTINtpTime
|
|
* @param time RTINtpTime
|
|
* @param divisor RTI_INT64
|
|
*/
|
|
extern RTIOsapiDllExport void RTINtpTime_divide(
|
|
struct RTINtpTime *answer,
|
|
struct RTINtpTime *time,
|
|
RTI_INT64 divisor);
|
|
|
|
/** @internal \ingroup
|
|
*
|
|
* @brief answer += time.
|
|
*
|
|
* This macro does not check for overflow.
|
|
*
|
|
* @param answer RTINtpTime
|
|
* @param time RTINtpTime
|
|
*/
|
|
extern RTIOsapiDllExport void RTINtpTime_increment(
|
|
struct RTINtpTime answer,
|
|
struct RTINtpTime time);
|
|
|
|
/** @internal \ingroup RTINtpTimeClass
|
|
*
|
|
* @brief Decrement one RTINtpTime value by another RTINtpTime value.
|
|
*
|
|
* Precondition:
|
|
* Postcondition: answer -= time.
|
|
*
|
|
* @param answer RTINtpTime
|
|
* @param time RTINtpTime
|
|
*/
|
|
extern RTIOsapiDllExport void RTINtpTime_decrement(
|
|
struct RTINtpTime answer,
|
|
struct RTINtpTime time);
|
|
|
|
/** @internal \ingroup RTINtpTimeClass
|
|
*
|
|
* @brief time = time + 1 fraction (~200 picoseconds).
|
|
*
|
|
* This macro does not check for overflow, so time cannot be infinite.
|
|
*
|
|
* @param time
|
|
* @return NO RETURN VALUE => do NOT evaluate this expression; simply call it.
|
|
*/
|
|
extern RTIOsapiDllExport void RTINtpTime_incrementInfinitesimally(
|
|
struct RTINtpTime time);
|
|
|
|
/** @internal
|
|
* \ingroup RTINtpTimeClass
|
|
*
|
|
* NULL RTINtpTime pointer is considered infinity. This is consistent
|
|
* with the concept of infinite time on UNIX.
|
|
*
|
|
* In addition, if the seconds field equals, or is above RTI_NTP_TIME_SEC_MAX,
|
|
* the time value is also considered infinite.
|
|
*
|
|
* @param time Pointer to RTINtpTime.
|
|
*
|
|
* @return RTI_TRUE if time is infinite, RTI_FALSE otherwise.
|
|
*/
|
|
extern RTIOsapiDllExport RTIBool
|
|
RTINtpTime_isInfinite(const struct RTINtpTime *time);
|
|
|
|
/** @internal \ingroup RTINtpTimeClass
|
|
*
|
|
* @param time Pointer to RTINtpTime.
|
|
* @return RTI_TRUE if time is AUTO, RTI_FALSE otherwise.
|
|
*/
|
|
extern RTIOsapiDllExport RTIBool
|
|
RTINtpTime_isAuto(const struct RTINtpTime *time);
|
|
|
|
/** @internal
|
|
* \ingroup RTINtpTimeClass
|
|
*
|
|
* Checks if the time structure represents an invalid time.
|
|
*
|
|
* @param time Pointer to RTINtpTime.
|
|
*
|
|
* @return RTI_TRUE if time is invalid, RTI_FALSE otherwise.
|
|
*/
|
|
extern RTIOsapiDllExport RTIBool
|
|
RTINtpTime_isInvalid(const struct RTINtpTime *time);
|
|
|
|
/** @internal \ingroup RTINtpTimeClass
|
|
*
|
|
* Checks if the time structure represents zero time. Zero time may be useful
|
|
* when getting the sign of the time quantity.
|
|
* @param time Pointer to RTINtpTime. Must not be NULL.
|
|
* @return positive if greater, 0 if equal, negative if less
|
|
*/
|
|
extern RTIOsapiDllExport int RTINtpTime_compareToZero(
|
|
const struct RTINtpTime *time);
|
|
|
|
/** @internal \ingroup RTINtpTimeClass
|
|
*
|
|
* Converts the RTINtpTime structure "time" into a string format
|
|
*
|
|
* @param time In. The RTINtpTime structure to convert into a string.
|
|
* @param str In. The string within which to store the result. The buffer should
|
|
* be sized to RTI_NTP_TIME_STRING_LEN.
|
|
*
|
|
* @returns The string.
|
|
*/
|
|
extern RTIOsapiDllExport char *RTINtpTime_toString(
|
|
const struct RTINtpTime *time,
|
|
char *str);
|
|
|
|
/** @internal
|
|
* \ingroup RTINtpTimeClass
|
|
*
|
|
* Converts the RTINtpTime structure "time" into a timeval format
|
|
*
|
|
* @param time In. The RTINtpTime structure to convert into a timeval.
|
|
* @param timeval Out. The timeval within which to store the result.
|
|
*/
|
|
extern RTIOsapiDllExport void RTINtpTime_toTimeval(
|
|
const struct RTINtpTime *time,
|
|
struct timeval *timeval);
|
|
|
|
/** @internal
|
|
* \ingroup RTINtpTimeClass
|
|
*
|
|
* Converts the RTINtpTime structure "time" into a calendar time format
|
|
*
|
|
* @param time In. The RTINtpTime structure to convert into a calendar time.
|
|
* @param calendarTime Out. The calendar time within which to store the result.
|
|
* @param roundUp In. Whether to round up the time to the closest second. If set
|
|
* to RTI_TRUE, the calendar time will be rounded up to the next seconds once
|
|
* the fractional part of the RTINtpTime represents a value greater than 500000
|
|
* microseconds. It should only be set if the caller is not going to use the
|
|
* microseconds. If the calendar time is going to be compared with another
|
|
* calendar time, the value used should be the same for both calendar times.
|
|
*/
|
|
extern RTIOsapiDllExport void RTINtpTime_toCalendarTime(
|
|
const struct RTINtpTime *time,
|
|
RTI_TIME_T *calendarTime,
|
|
RTIBool roundUp);
|
|
|
|
/** @internal
|
|
* \ingroup RTINtpTimeClass
|
|
*
|
|
* Converts the RTINtpTime structure "time" into a timespec format
|
|
*
|
|
* @param time In. The RTINtpTime structure to convert into a timespec.
|
|
* @param calendarTime Out. The timespec within which to store the result.
|
|
*/
|
|
extern RTIOsapiDllExport void RTINtpTime_toTimespec(
|
|
const struct RTINtpTime *time,
|
|
struct timespec *calendarTime);
|
|
|
|
/** @internal \ingroup RTINtpTimeClass
|
|
*
|
|
* Copies the RTINtpTime structure "time" into a buffer
|
|
*
|
|
* @param time In. The RTINtpTime structure to copy into a buffer.
|
|
* @param buffer Out. The buffer where the RTINtpTime structure is going to be
|
|
* copied. The size of the buffer should be at least
|
|
* RTI_OSAPI_NTPTIME_SERIALIZED_SIZE.
|
|
*/
|
|
extern RTIOsapiDllExport void RTINtpTime_toBuffer(
|
|
const struct RTINtpTime *time,
|
|
char *buffer);
|
|
|
|
|
|
#ifdef __cplusplus
|
|
} /* extern "C" */
|
|
#endif
|
|
|
|
#include "osapi/osapi_ntptime_impl.h"
|
|
|
|
|
|
#endif /* osapi_ntptime_h */
|