4 * Implementation of the clock_gettime() element of the POSIX clock API.
8 * Written by Keith Marshall <keithmarshall@users.sourceforge.net>
9 * Copyright (C) 2017, 2018, MinGW.org Project
12 * Permission is hereby granted, free of charge, to any person obtaining a
13 * copy of this software and associated documentation files (the "Software"),
14 * to deal in the Software without restriction, including without limitation
15 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
16 * and/or sell copies of the Software, and to permit persons to whom the
17 * Software is furnished to do so, subject to the following conditions:
19 * The above copyright notice and this permission notice (including the next
20 * paragraph) shall be included in all copies or substantial portions of the
23 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
24 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
25 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
26 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
27 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
28 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
29 * DEALINGS IN THE SOFTWARE.
34 int clock_gettime( clockid_t clock_id, struct timespec *current )
36 /* Standard API function, first implemented in POSIX.1b-1993, to
37 * read the current time indicated by a specified clock; it first
38 * initializes the clock, if necessary, then reads its currently
39 * indicated time, and encodes it for return, in the specified
40 * "current" timespec structure, together with a "validity check"
43 * Note that, unlike the clock_getres() API, it is NOT permitted
44 * to specify NULL for the timespec parameter here; doing so will
45 * cause the call to fail, irrespective of the clock validity.
48 return clock_api_invalid_error();
50 if( __clock_api_is_valid( clock_id ) )
52 /* We must be prepared to retrieve clock frequencies from Windows
53 * APIs, which report either LARGE_INTEGER or FILETIME values, but
54 * we prefer to interpret them as scalar int64_t values.
56 union { uint64_t value; LARGE_INTEGER qpc_value; FILETIME rtc_value; } ct;
57 switch( clock_id->type )
59 case CLOCK_TYPE_REALTIME:
60 /* The counter for CLOCK_REALTIME, and any derived clock, is
61 * represented by system time, expressed as a count of 100ns
62 * intervals since the start of the Windows FILETIME epoch.
64 GetSystemTimeAsFileTime( &ct.rtc_value );
67 case CLOCK_TYPE_MONOTONIC:
68 /* Conversely, the counter for CLOCK_MONOTIME and derivatives
69 * is obtained from the Windows QPC API, if supported...
71 if( QueryPerformanceCounter( &ct.qpc_value ) > 0 )
74 /* ...or otherwise, fall through, to force an "invalid status"
75 * return, as we do for any other clock type designation, (which
76 * implicitly includes CLOCK_TYPE_UNIMPLEMENTED; note that this
77 * is incorporated into a default case handler, to suppress any
78 * GCC -Wswitch warnings which might otherwise be diagnosed).
80 default: return clock_api_invalid_error();
82 /* In either case, once we have a valid count of clock ticks, we
83 * must adjust it, relative to the timebase for the clock, (which
84 * is recorded within the clock's implementation data structure),
85 * then scale it, and break it down into seconds and nanoseconds
86 * components, (again based on scaling factors which are similarly
87 * recorded within the implementation data)...
89 ct.value -= clock_id->timebase;
90 current->tv_nsec = (ct.value % clock_id->frequency)
91 * NANOSECONDS_PER_SECOND / clock_id->frequency;
92 current->tv_sec = ct.value / clock_id->frequency;
94 /* ...before returning zero, as "successful completion" status...
98 /* ...or -1, indicating failure.
103 /* $RCSfile$: end of file */