0% found this document useful (0 votes)
95 views

Domain Time Interface Software Development Kit Documentation

This document provides documentation for the Domain Time Interface Software Development Kit (SDK). The SDK allows programs to access high-resolution timekeeping capabilities beyond what the operating system normally provides. It uses two DLL files (32-bit and 64-bit versions) that export functions for getting the time with microsecond precision. The API is documented in a header file and allows applications to retrieve time information with greater accuracy than the standard GetSystemTimeAsFileTime function.

Uploaded by

Anil
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as DOC, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
95 views

Domain Time Interface Software Development Kit Documentation

This document provides documentation for the Domain Time Interface Software Development Kit (SDK). The SDK allows programs to access high-resolution timekeeping capabilities beyond what the operating system normally provides. It uses two DLL files (32-bit and 64-bit versions) that export functions for getting the time with microsecond precision. The API is documented in a header file and allows applications to retrieve time information with greater accuracy than the standard GetSystemTimeAsFileTime function.

Uploaded by

Anil
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as DOC, PDF, TXT or read online on Scribd
You are on page 1/ 16

Domain Time Interface SDK Documentation Page 1 of 16

Domain Time Interface Software Development Kit Documentation


Last revision: 12 April 2019

I. Introduction

The Windows operating system only allows setting the time to the nearest
millisecond (0.001 seconds). The theoretical accuracy of available time
protocols can go to microseconds (0.0000001 second) or nanoseconds
(0.000000001 second).

The actual performance of software-based timekeeping rarely reaches the


microsecond level due to the non-realtime nature of the operating system,
network performance variations, misbehaved hardware interrupt handlers,
and lack of good hardware timing support. Nevertheless, Domain Time’s
practical accuracy usually meets the one-millisecond level, and often
exceeds it by several orders of magnitude. Using PTP, Domain Time
normally achieves synchronization within a handful of microseconds from
the grandmaster. Using NTP with a local appliance, Domain Time
normally achieves synchronization to within a quarter-millisecond.

Obtaining the time to the nearest microsecond doesn’t do much good if the
system clock can only be set to the nearest millisecond. For this reason,
Domain Time only “sets” the clock when stepping. The rest of the time,
Domain Time slews the clock (adjusts the frequency) so that time passing
on a wall clock and time passing within the computer come into
conformance with a high degree of accuracy.

The theoretical granularity of the operating system’s API to retrieve the


time of day is in hectonanoseconds (0.00000001 second, or a tenth of a
microsecond). However, while Domain Time can adjust the system’s
clock to this level, the operating system cannot report it. The actual
granularity of the operating system’s API is the base interrupt frequency
for the machine. This is usually 1, 10, or 15 milliseconds. Rapid
successive queries of the system time via GetSystemTimeAsFileTime will
show the clock holding still for 1, 10, or 15 milliseconds, then jumping
forward, then holding still again, and so forth. The operating system
simply calculates the number of hectonanoseconds per interrupt, and adds
that quantity at each interrupt.

Domain Time uses the performance counter in combination with the


system clock to interpolate the points between clock jumps. Thus, while
the operating system sees the time moving forward in large discrete jumps,
Domain Time sees it moving forward in very small increments. (The size
of increment Domain Time can track depends on the hardware of the
Domain Time Interface SDK Documentation Page 2 of 16

individual machine, but usually ranges from a few microseconds to a few


hundred microseconds.)

This interpolation allows Domain Time to compare time received from the
network with the computer’s time at a level far below the operating
system’s native capacity, yielding more accurate corrections and more
precise time.

The SDK allows other user-mode programs or services to take advantage


of Domain Time’s internal clock. By using the supplied DLL, other
programs can have access to the same high-resolution clock used for
maintaining the time. This allows true sub-millisecond precision for
timing loops or time of day retrieval. While any program can do its own
interpolation to get sub-millisecond timing, they cannot marry the elapsed
time counter to the time of day without Domain Time.

When running on operating systems Windows 8/Windows Server 2012 or


newer, Domain Time uses the kernel’s interpolator instead of its own. In
these cases, Domain Time forwards calls for GetSystemTimeAsFileTime
to GetSystemTimePreciseAsFileTime. If your only reason for using the
SDK DLLs is to obtain a finer granularity than GetSystem-
TimeAsFileTime, you should consider rewriting your program to call
GetSystemTimePreciseAsFileTime directly. Since the counters used by
the operating system’s interpolator are mapped into each process’s address
space, access is as fast as a memory read, as opposed to calling the same
function indirectly through a DLL.

If your application must run on multiple platforms, for example XP and


2012r2, then using the SDK gives you a single interface to obtain high-
resolution time without changing your application based on the operating
system version. Domain Time will either run its own interpolator, or use
the kernel’s, depending on the operating system.

II. Interface Details and Requirements

The SDK requires Domain Time Client or Domain Time Server version
5.1 or later. Earlier versions of Domain Time do not export the shared
memory needed by the SDK. Windows XP, Windows 2003r2, Vista,
Windows 2008, Windows 7, Windows 2008r2, Windows 8, Windows
2012, Windows 8.1, Windows 2012r2, Windows 10, Windows 2016,
Windows Server 2019, Nanoserver, and Server Core are currently
supported.

The SDK uses two DLL files, DTHRes32.dll and DTHRes64.dll.


Domain Time Interface SDK Documentation Page 3 of 16

To run a 32-bit program using 32-bit Domain Time on an x86 operating


system, link with DTHRes32.dll. You must copy DTHRes32.dll to the
system32 directory or your application’s folder.

To run a 64-bit program using 64-bit Domain Time on an x64 operating


system, link with DTHRes64.dll. You must copy DTHRes64.dll to the
system32 directory or your application’s folder.

The x64 operating system allows you to run 32-bit programs in Windows-
on-Windows (WoW) mode. In WoW mode, your programs cannot see the
real system32 directory; instead, they are transparently redirected to the
syswow64 directory when they try to access the system32 directory.
Domain Time itself does not run under WoW, although the SDK will
support your programs in this configuration.

To run a 32-bit program using 64-bit Domain Time on an x64 operating


system, link with DTHRes32.dll. You will need to copy DTHRes32.dll
into your application directory or into the syswow64 directory.
DTHRes32.dll will run in your application’s 32-bit address space, but
communicate with Domain Time in the 64-bit address space.

The DLLs export C-style functions for your program’s use. The demo
programs show a variety of methods for interfacing with the DLLs
(VB.NET, C#, and plain C). C-style functions are necessary to avoid the
overhead of marshalling across process boundaries. A COM or DCOM
server would suffer so much latency that it would lose the extra precision
available from Domain Time.

If your project is 32-bit, you should link against the DTHRes32.dll; if


your project is 64-bit, use DTHRes64.dll.

For C or C++ programs, DTHRes32.lib and DTHRes64.lib are provided


for static linking (you may also link dynamically, of course). For other
languages, you will need to P/Invoke or dynamically load the individual
functions after declaring them. Refer to the demo programs for general
guidelines.

III. API

The API is documented primarily in the dthres.h file, which is a C-style


header appropriate for inclusion in your C or C++ programs. For other
languages, you may derive your declarations by translating the C types as
appropriate.

BOOL WINAPI GetDomainTimeAsFileTime(PFILETIME pFT);


Domain Time Interface SDK Documentation Page 4 of 16

This is a drop-in replacement for GetSystemTimeAsFileTime (or


GetSystemTimePreciseAsFileTime on Win8/2012 and newer).
The only difference is that GetSystemTimeAsFileTime and
GetSystemTimePreciseAsFileTime are void functions, while
GetDomainTimeAsFileTime returns a BOOL indicating whether the
returned time is high-definition or not.

If GetDomainTimeAsFileTime returns FALSE, the time is valid, but


only to the resolution of the system clock (i.e., it is not high-
definition time). Your program should call GetLastError to
determine the reason high-definition time is not available (see
Section IV below).

DWORD WINAPI GetDomainTimeAsFileTimeMonotonic(PFILETIME


pFT);

void WINAPI GetMonotinicityLimits(PLARGE_INTEGER


signedMaxHectos, PDWORD maxLoops);

void WINAPI SetMonotonicityLimits(PLARGE_INTEGER


signedMaxHectos, DWORD maxLoops);

These three APIs have no direct equivalents in the Win32 API.


They are available with any version of the SDK DLLs after
1/1/2012. The GetDomainTimeAsFileTimeMonotonic function
tries to return monotonically incrementing time-of-day. This is not
always possible, because the time-of-day is not absolute at
resolutions below the timer tick (and not even then, since it’s
possible to have the clock stepped backward, either by Domain
Time, at system startup, by another process, or by the foreground
user). Note: If you are using GetDomainTimeAsFileTime-
Monotonic, you should ensure that your version of the SDK DLLs
is 5.2.b.20190331 or later.

Most performance counters run at a fixed frequency which does


not divide evenly into an integral number of ticks per
hectonanosecond. For example, if the QPC runs at 1.01
seconds/second, the system will be ahead of the tick by a handful
of hectonanoseconds just before the tick, resolving back down just
after the tick. The amount of drift is very small (typically a few
hectonanoseconds deviation every few million samples), but
unavoidable without being willing to wait. This is a generic
problem with HPET and APIC and their clocks not dividing down
to an integral PerfFrequency for the divisor. The QPC timer, which
may be based on RDSTC or motherboard timer (the basis for the
timer is chosen by the HAL), is suitable for measuring very tiny
intervals, but not for measuring wall clock time. We are marrying
the GSTAFT and QPC, using the QPC to interpolate between
Domain Time Interface SDK Documentation Page 5 of 16

proper clock ticks. This should be a small enough interval, but isn’t
– in practice, the derived wall clock will move slightly ahead, then
rewind, then move slightly ahead again, all based on how much the
divisor doesn’t match reality and when the various ticks happen.

If your program requires monotonicity, you should either use


GetDomainTimeAsFileTimeMonotonic or employ your own
comparison routine and simply call GetDomainTimeAsFileTime
more than once if the returned value is unexpected. The overhead
for monotonicity is small, but measurable, so do not use the
monotonic function if your program does not require it.

The GetDomainTimeAsFileTimeMonotonic function keeps track


of the last-delivered timestamp, and if the currently-derived wall
clock time is earlier than the last known value, waits a very tiny
amount of time and tries again. If the backward swing is very
small, the system is probably right before the next tick, and waiting
to make the time monotonic won’t cost much. If it’s a large swing,
then either the performance counter is broken or the time actually
has gone backward. Domain Time tries to identify these two
conditions without delaying the return from the function.

Two variables, signedMaxHectos and maxLoops, let you control


how the monotonic calculator performs. The default for
signedMaxHectos is -10,000 (one millisecond). Anything over
this amount is considered "large," and probably represents a real
backward movement of the wall clock. Anything less than this is
worth waiting for, up to maxLoops (default 1000).

If GetDomainTimeAsFileTimeMonotonic returns NO_ERROR, the


returned time of day is both high-definition and monotonic. The
function returns ERROR_BAD_FORMAT if the performance counter
does not increment monotonically (i.e. goes backward or wraps
unexpectedly), and ERROR_TIME_SKEW if the returned time is not
monotonic with respect to the last call to the function. The function
may also return ERROR_SERVICE_NOT_ACTIVE if Domain Time
isn’t running. When the function returns anything other than
NO_ERROR, the returned time will be valid, but not necessarily high-
definition or monotonic.

BOOL WINAPI GetDomainTime (LPSYSTEMTIME pST);

This function is a drop-in replacement for GetSystemTime. It fills


in the SYSTEMTIME structure with the current UTC time, valid to
the nearest millisecond. As with GetDomainTimeAsFileTime, this
Domain Time Interface SDK Documentation Page 6 of 16

function returns a BOOL to indicate whether the returned time is


high-definition or not.

If GetDomainTime returns FALSE, the time is valid, but only to the


resolution of the system clock (i.e., it is not high-definition time).
Your program should call GetLastError to determine the reason
high-definition time is not available (see Section IV below).

BOOL WINAPI GetLocalDomainTime(LPSYSTEMTIME pST);

This function is a drop-in replacement for GetLocalTime. It fills in


the SYSTEMTIME structure with the current local time. All other
details are identical to GetDomainTime.
DWORD WINAPI GetPTPStats(PPTP_STATISTICS pStats);

This function is available with DLL version 5.2.b.20190401 (01


April 2019) or later. A sample program, APITest, demonstrates
using this function. The definition of PTP_STATISTICS is in the
dthres.h file, along with an example of calling the function and
defines for PTPPortIdentity, IP_AGNOSTIC_ADDRESS, PTP port
states, and PTP profile identifiers.

You must set the cbSize member to sizeof(PTP_STATISTICS)


before calling GetPTPStats().

Example:
PTP_STATISTICS stats;
stats.cbSize = sizeof(PTP_STATISTICS);
DWORD error = GetPTPStats(&stats);

if (NO_ERROR == error) // results are valid


else // handle error

GetPTPStats() returns an error code directly. If the


return code is
zero (NO_ERROR), then the pStats structure will befilled in with
the current PTP statistics. If the return code is non-zero the
contents of the pStats structure are undefined.
BOOL WINAPI FTime32(struct __timeb32 *timeptr);
BOOL WINAPI FTime64(struct __timeb64 *timeptr);

These functions are replacements for the C runtime functions


_ftime32() and _ftime64().

The .dstflag and .timezone members are always set to zero by


these functions. If you need the time zone information, you may
obtain it by calling the existing C runtime functions or the
Domain Time Interface SDK Documentation Page 7 of 16

Windows API directly. Since time zone information is relevant


only for local time displays, and since retrieving or calculating it is
expensive in terms of processor overhead and therefore affects the
precision of the returned time information, FTime32 and FTime64
do not provide it.

The remaining members of *timeptr are set with the current UTC
time of day in seconds and milliseconds since midnight January 1st
1970 UTC.

NOTE: The 32 and 64 in the function and parameter names refer to


the size of the timeptr parameter you supply, not the bittedness of
the function or in which DLL it may be found. Both FTime32 and
FTime64 are available in either the 32-bit or 64-bit DLL. The
__timeb64 structure uses a __time64_t member (a signed 64-bit
integer) to hold the number of seconds, while the __timeb32
structure uses a __time32_t member. Since __time32_t is a
signed 32-bit integer, it may yield unexpected results after January
18, 2038.

If FTime32 or FTime64 return FALSE, the time is valid, but only to


the resolution of the system clock (i.e., it is not high-definition
time). Your program should call GetLastError to determine the
reason high-definition time is not available (see Section IV below).

HANDLE WINAPI GetDomainTimeNotifyHandle();

This function has no corresponding function in the Win32 API. It


returns a handle (either 32-bits or 64-bits wide, depending on
which version of the SDK DLL you use) to an event your program
can monitor for changes to Domain Time’s status.

This function will operate even when Domain Time is not running,
allowing your program to monitor startup events and the initial
time check. All other functions in the SDK fail if the Domain Time
service isn’t running (although the get time functions will return
the time according to the operating system’s native resolution).

The returned handle may be used in any of the standard Win32


handle wait functions (e.g., WaitForSingleObject or
WaitForMultipleObjects). When signaled, your program may
call GetDomainTimeStatus (see below) to determine what has
changed. The handle will remain signaled for approximately 55
milliseconds, so your program should compare the current status
with the last-known status to determine if a change has actually
occurred.
Domain Time Interface SDK Documentation Page 8 of 16

When you are finished with the handle, your program must call the
Win32 API function CloseHandle to release the resources.

If GetDomainTimeNotifyHandle returns NULL, your program


should call GetLastError to determine the reason for the failure.
The most likely cause of failure is being denied access on Vista or
subsequent operating systems (see ERROR_ACCESS_DENIED in
Section IV below). Vista imposes security restrictions on creating
objects in the Global namespace. No special privileges are required
to open the notify handle if Domain Time is already running, but
Vista may deny access if your program attempts to open the handle
first. Programs running with elevated privileges (not necessarily
administrator, but this depends on your system’s security
configuration) may usually create or open the notify handle.

BOOL WINAPI IsDomainTimeRunning();

This function returns a BOOL indicating whether or not the Domain


Time service is running. If it returns FALSE, use GetLastError to
determine the reason for the failure. ERROR_SUCCESS means that
the service isn’t running; any other error (see Section IV below)
means that the status was not able to be determined.

BOOL WINAPI GetDomainTimeVersion(PDWORD pdwMajor,PDWORD


pdwMinor,PDWORD pdwDate);

This function fills in the data members with the version number of
the Domain Time Client or Server running on the machine. The
major and minor versions are simple integers. The date member is
a packed DWORD, with the high word holding the year, and the low
word holding the month and day. For example, 31 March 2019
would be represented as MAKELONG(331,2019). You can use the
HIWORD and LOWORD macros to extract the individual fields:

dwYear = HIWORD(dwDate);
dwMonthDay = LOWORD(dwDate);

printf("Version is %u.%u.b.%04u%04u",
dwMajor,
dwMinor,
dwYear,
dwMonthDay);

Output: Version is 5.2.b.20190331

Note: Previous versions of this documentation showed incorrect


usage of HIWORD and LOWORD to extract the month and day. The
error has been corrected in the current version of this document.
Domain Time Interface SDK Documentation Page 9 of 16

If this function returns FALSE, call GetLastError to determine the


reason for failure (the service is probably not running).

BOOL WINAPI GetSDKDLLVersion(PDWORD pdwMajor,PDWORD


pdwMinor,PDWORD pdwDate);

This function is available with DLL version 5.2.b.20190401 (01


April 2019) or later. This function fills in the data members with
the version number of the SDK DLL itself. Unpack the
information as shown in the GetDomainTimeVersion() function
above. This function will never return FALSE.

BOOL WINAPI GetDomainTimeRole(PDWORD pdwRole);

This function fills in the pdwRole member with one of the


constants listed below:

ROLE_UNKNOWN = 0
ROLE_MASTER = 1 (Server in the domain master role)
ROLE_SLAVE = 2 (Server in the domain slave role)
ROLE_INDIE = 3 (Server acting independently)
ROLE_CLIENT = 4 (Domain Time Full Client)

If this function returns FALSE, call GetLastError to determine the


reason (the service is probably not running).

BOOL WINAPI GetDomainTimeStatus(PDWORD pdwStatus);

This function returns the current synchronization status of Domain


Time. The status will be one of the following constants:

SYNC_STATUS_INVALID = 0

This value represents either that the service has


died, or is unable to determine its own status.
Except for brief transitions during service startup or
when the service has been stopped while you are
monitoring, this indicates a failure condition. Check
the results with IsDomainTimeRunning to
determine if the service has stopped or encountered
an error.

SYNC_STATUS_UNKNOWN = 1

This value represents a working service that has yet


to determine its status, or is transitioning between
one state and another. This value also represents a
service that has shut down normally. Check the
Domain Time Interface SDK Documentation Page 10 of 16

results against IsDomainTimeRunning to determine


if you should retry.

SYNC_STATUS_CHECKING = 2

This value means the service is either querying its


time sources or is in the process of correcting the
time (there is no way to distinguish between the two
with this API). This state will appear every time the
service checks its time, and will resolve into either
SYNC_STATUS_SYNCED or SYNC_STATUS_UNSYNCED.

SYNC_STATUS_SYNCED = 3

This value means the service has verified the time


against its designated time sources and has
completed any required time corrections.
SYNC_STATUS_SYNCED means the time on the
machine can be trusted to match the designated time
sources within the level of accuracy of the selected
protocol.

SYNC_STATUS_UNSYNCED = 4

This value means the service was unable to


synchronize the machine, either because it was not
able to verify the time or because of some other
failure. SYNC_STATUS_UNSYNCED means the time on
the machine should not be trusted.

If this function returns FALSE, call GetLastError to determine the


reason (the service is probably not running).

IV. Error Codes

The GetDomainTimeAsFileTimeMonotonic() function (available in


versions after 1/1/2012), returns an error code directly. A return of zero
(NO_ERROR) means the returned time is both high-definition and
monotonic. Other possible return codes are ERROR_SERVICE_NOT_ACTIVE,
ERROR_TIME_SKEW, and ERROR_BAD_FORMAT. See the remarks by the
function definitions for more information. The two monotonic support
functions are void, and neither return a value or set the last error.

The GetPTPStats() function (available in versions after 01 April 2019),


returns an error code directly. If the return code is zero (NO_ERROR), then
the function executed successfully. If the return code is non-zero, an error
Domain Time Interface SDK Documentation Page 11 of 16

occurred and the values of the PTP_STATISTICS structure are undefined. If


you do not set the cbSize member of the PTP_STATISTICS structure
before calling GetPTPStats(), the return code will be ERROR_
INVALID_PARAMETER. Other possible return codes are ERROR_SERVICE_
NOT_ACTIVE, ERROR_FILE_NOT_FOUND, and ERROR_ACCESS_DENIED.

Each of the other API functions sets the Win32 last error. Use the
GetLastError() function to obtain the error code for any API call that
returns a BOOL whose value is FALSE. Any normal system error (such as
being out of memory) may occur, but, commonly, only the following
errors will be seen (see the Windows Platform SDK for numbers
corresponding to the defines):

ERROR_FILE_NOT_FOUND: This error occurs when your program calls a


function in the DLL before Domain Time has started. The “file” in this
case refers to the shared memory section where Domain Time keeps its
counters. When you receive this error, you should retry your function call
after Domain Time starts.

ERROR_ACCESS_DENIED: This error occurs on Vista or later operating


systems with User Access Control enabled if (a) Domain Time hasn’t
started yet, or (b) your program is running without administrator
privileges. In most cases, ERROR_ACCESS_DENIED means that Domain
Time is not running, and your program does not have sufficient privileges
to interrogate or create the shared memory section. Once Domain Time is
running, your program is allowed to access the shared memory without
having any special privileges.

ERROR_SERVICE_NOT_ACTIVE: This error occurs when the DLL is able to


load the shared memory section and determine that Domain Time is not
running. You will see this error only when the Domain Time service is
stopped while your program is still running. Restarting the Domain Time
service will resume normal operations.

ERROR_BAD_ENVIRONMENT: This error occurs when there is a mismatch


between the DLL’s version and the version of the Domain Time service
running on your machine. There is currently no situation where this can
happen, but the error code is reserved for future use. If Domain Time’s
exported structures change such that a newer version of the DLL is
required, this error will be returned by the DLL.

ERROR_INVALID_TIME: This error occurs when Domain Time’s internal


operations have invalidated the interpolation counters (typically only when
the time zone is changed or a significant time correction is required). The
time returned by your function call will be valid to the limit of the
operating system’s granularity, but will not be high-resolution. The
Domain Time Interface SDK Documentation Page 12 of 16

situation will clear itself as soon as Domain Time has recalibrated the
interpolation counters (typically a few hundred milliseconds).

V. Technical Support

We regret that we cannot provide technical support for your programs.


The DLLs are fairly simple, and the demo programs show how to use
them. The only documentation available is this file, the dthres.h file, and
the code in the demo programs.

If the demo programs work on your machine, but your own programs do
not, check your syntax (especially if you are writing your own declarations
in a non-C language). Each of the API functions sets the Win32 last error
instead of throwing an exception. If you are using C++ or C#, common
practice is to wrap C-style APIs in a class where you check the last error
and throw your own exceptions as needed.
Domain Time Interface SDK Documentation Page 13 of 16

Appendix
Global Named Events

As of version 5.2.b.20140101 (January 1st, 2014), Domain Time exposes several named
events of potential interest to external applications. These events will exist whenever
Domain Time is running. Your code should use OpenEvent with SYNCHRONIZE access,
and then WaitForSingleObject (or any of the other handle-waiting functions) with a
timeout of zero to query status (see example code below). Do not try to use CreateEvent
if OpenEvent fails. You may open the events of interest once at the beginning of your
program and then close them at the end, but be sure to check for valid handles before
passing them to any of the wait functions. If Domain Time has not started yet when your
program starts, the OpenEvent call(s) will fail. However, if you have successfully opened
the event(s), they will remain valid even if the Domain Time service is restarted.

Global\domtime-sync-status-notify-event

This is the same event returned by GetDomainTimeNotifyHandle(). Its use is described


above in the main document. This event is signaled when PTP status changes as well as
when any other Domain Time status changes.

Global\domtime-sync-status-synchronized

This event will be set (signaled) when Domain Time has successfully synchronized the
clock, and remain set unless Domain Time encounters an error synchronizing the clock.
Under normal conditions, it will be clear (unsignaled) from the moment Domain Time
starts up until after the first successful synchronization. It will then transition to signaled,
and any transition back to unsignaled indicates a problem has occurred or that the service
has been restarted.

Global\domtime-sync-status-interphase-active

This event will be set (signaled) during the application of interphase corrections. It will
be clear (unsignaled) at all other times.

Global\domtime-sync-status-ptpv2-enabled

This event will be set (signaled) if Domain Time has PTP enabled. It will be clear
(unsignaled) otherwise.

Global\domtime-sync-status-ptpv2-slave

This event will be set (signaled) if Domain Time has PTP enabled and is currently
operating as a PTP slave. It will be clear (unsignaled) otherwise.
Domain Time Interface SDK Documentation Page 14 of 16

Global\domtime-sync-status-ptpv2-master

This event will be set (signaled) if Domain Time has PTP enabled and is currently
operating as a PTP master. It will be clear (unsignaled) otherwise.

Example Code

For clarity, error handling is omitted. This sample should demonstrate how to use the
events named above in your own programs. Note that in the C language, backslashes
must be escaped (doubled) as shown.

BOOL IsPTPv2Slave()
{
BOOL bIsSlave = FALSE;

HANDLE hEvent = OpenEventW(


SYNCHRONIZE,FALSE,
L"Global\\domtime-sync-status-ptpv2-slave");

if (hEvent)
{
bIsSlave = (WAIT_OBJECT_0 == WaitForSingleObject(hEvent,0));
//
// WAIT_OBJECT_0 means event is set (signaled)
// WAIT_TIMEOUT means event is clear (unsignaled)
// any other return code is an error
//
// Don't forget to close the handle
//
CloseHandle(hEvent);
}
else
{
// use GetLastError() to find out why the open failed
//
// ERROR_FILE_NOT_FOUND means Domain Time isn't running yet
//
// ERROR_ACCESS_DENIED may happen if you try anything other
// than SYNCHRONIZE access
}
return bIsSlave;
}

As of version 5.2.20160415 (15 April 2016), Domain Time stores some extra information
in the registry for use by third-party programs, and has two new global events you can
monitor. The registry values must be treated as read-only (Domain Time never reads the
variables; it only overwrites them as conditions change.)

Global\domtime-sync-status-ptpv2-status-change
Domain Time Interface SDK Documentation Page 15 of 16

This event is auto-reset. Domain Time will set it upon a status change (change from
Listening to Slave, etc., change in Master, or change in TAI-UTC offset). When you
check the event’s status, it will change (if signaled) to unsignaled. You may therefore
wait on this event to know when to read the registry for new information.

NOTE: As of version 5.2.b.20190401, you should use the GetPTPStats() function


instead of reading the registry.

Global\domtime-sync-status-ptpv2-offset-change

This event is auto-reset and is meaningful only if PTP is a slave. Domain Time will set it
every time a new PTP offset is calculated. When you check the event’s status, it will
change (if signaled) to unsignaled. You may therefore wait on this event to know when to
call GetPTPStats() or read the registry for new information. As of 20 September 2016,
this event will only fire if Current Offset Enabled is set to True (see below).

The PTP registry key for Domain Time Server is:

HKLM\Software\Greyware\Domain Time Server\Time Sources\PTPv2 (IEEE 1588)

For Domain Client, the registry key is:

HKLM\Software\Greyware\Domain Time Client\Time Sources\PTPv2 (IEEE 1588)

The values of interest are:

Current PortState (REG_SZ string). If not present, either PTP is not running, or you
have a version prior to 5.2.b.20160415. If present, it will be one of Initializing, Faulty,
Disabled, Listening, Pre-Master, Passive, Calibrating, or Slave. Other values are reserved
for future use. The status-change event will fire when this value changes.

Current Master (REG_SZ string): If not present or blank, then PTP is not a slave, and
therefore has no master. If present, it will be in the form of 00a154-fffe-125c71:1
(192.168.1.3), which is the master’s PortIdentity (clockIdentity:port) followed by the
IP address in parentheses. The status-change event will fire when this value changes.

Current Offset Enabled (REG_SZ string): Deprecated; do not use. Added 20


September 2016. This value is a boolean, either the English word “True” or “False”
(without the quotation marks). It controls whether or not Current Offset (signed 64-bit) is
written to the registry, and whether the offset-change event is fired. The default value is
false, and you should generally leave it that way. If you change the value to true and
reload parameters, Domain Time will begin recording and signaling each offset change.

NOTE: As of version 5.2.b.20190401, you should use the GetPTPStats() function


instead of changing Current Offset Enabled to True and then reading the registry.
Current Offset Enabled is retained solely for backward-compatibility. Enabling
Domain Time Interface SDK Documentation Page 16 of 16

Current Offset in the registry incurs a significant performance penalty, and may severely
impact Domain Time’s ability to keep the clock in sync with the grandmaster.

Current Offset (signed 64-bit) (REG_QWORD): This value is the offset (delta) in
hectonanoseconds (tenths of a microsecond), and must be treated as a signed value. A
positive number represents the master being ahead of the slave; a negative number
represents the slave being ahead of the master. The offset-change event will fire when
this value changes. The value is only meaningful if PTP is currently a slave. To convert
hectonanoseconds to a more friendly display format, use code like this:

signed __int64 hectos = (signed __int64) [value read from registry];


double seconds = (double)hectos / 10000000.0;
printf(“Offset is %+1.7f seconds”,seconds);

You might also like