3 This file is part of Cygwin.
5 This software is a copyrighted work licensed under the terms of the
6 Cygwin license. Please consult the file "CYGWIN_LICENSE" for
9 #define __timezonefunc__
11 #include <sys/times.h>
12 #include <sys/timeb.h>
13 #include <sys/param.h>
29 static inline void __attribute__ ((always_inline
))
30 get_system_time (PLARGE_INTEGER systime
)
32 GetSystemTimePreciseAsFileTime ((LPFILETIME
) systime
);
37 __to_clock_t (PLARGE_INTEGER src
, int flag
)
39 uint64_t total
= src
->QuadPart
;
40 /* Convert into clock ticks - the total is in 10ths of a usec. */
44 total
/= NS100PERSEC
/ CLOCKS_PER_SEC
;
48 /* times: POSIX 4.5.2.1 */
50 times (struct tms
*buf
)
52 static SYSTEM_TIMEOFDAY_INFORMATION stodi
;
53 KERNEL_USER_TIMES kut
;
55 clock_t tc
= (clock_t) -1;
59 /* Fetch boot time if we haven't already. */
60 if (!stodi
.BootTime
.QuadPart
)
61 NtQuerySystemInformation (SystemTimeOfDayInformation
,
62 &stodi
, sizeof stodi
, NULL
);
64 NtQueryInformationProcess (NtCurrentProcess (), ProcessTimes
,
65 &kut
, sizeof kut
, NULL
);
66 get_system_time (&ticks
);
69 ticks
.QuadPart
-= stodi
.BootTime
.QuadPart
;
70 /* ticks is in in 100ns, convert to clock ticks. */
71 tc
= (clock_t) (ticks
.QuadPart
* CLOCKS_PER_SEC
/ NS100PERSEC
);
73 /* Linux allows a NULL buf and just returns tc in that case, so
77 buf
->tms_stime
= __to_clock_t (&kut
.KernelTime
, 0);
78 buf
->tms_utime
= __to_clock_t (&kut
.UserTime
, 0);
79 timeval_to_filetime (&myself
->rusage_children
.ru_stime
, &kut
.KernelTime
);
80 buf
->tms_cstime
= __to_clock_t (&kut
.KernelTime
, 1);
81 timeval_to_filetime (&myself
->rusage_children
.ru_utime
, &kut
.UserTime
);
82 buf
->tms_cutime
= __to_clock_t (&kut
.UserTime
, 1);
90 syscall_printf ("%D = times(%p)", tc
, buf
);
94 /* settimeofday: BSD */
96 settimeofday (const struct timeval
*tv
, const struct timezone
*tz
)
104 if (tv
->tv_usec
< 0 || tv
->tv_usec
>= USPERSEC
)
110 ptm
= gmtime (&tv
->tv_sec
);
111 st
.wYear
= ptm
->tm_year
+ 1900;
112 st
.wMonth
= ptm
->tm_mon
+ 1;
113 st
.wDayOfWeek
= ptm
->tm_wday
;
114 st
.wDay
= ptm
->tm_mday
;
115 st
.wHour
= ptm
->tm_hour
;
116 st
.wMinute
= ptm
->tm_min
;
117 st
.wSecond
= ptm
->tm_sec
;
118 st
.wMilliseconds
= tv
->tv_usec
/ (USPERSEC
/ MSPERSEC
);
120 res
= -!SetSystemTime (&st
);
129 syscall_printf ("%R = settimeofday(%p, %p)", res
, tv
, tz
);
135 stime (const time_t *t
)
137 struct timeval tv
= { *t
, 0 };
138 return settimeofday(&tv
, NULL
);
141 /* timezone: standards? */
145 char *b
= _my_tls
.locals
.timezone_buf
;
148 __small_sprintf (b
,"GMT%+d:%02d", (int) (-_timezone
/ 3600), (int) (abs (_timezone
/ 60) % 60));
152 /* Cygwin internal */
154 totimeval (struct timeval
*dst
, PLARGE_INTEGER src
, int sub
, int flag
)
156 int64_t x
= __to_clock_t (src
, flag
);
158 x
*= (int64_t) USPERSEC
/ CLOCKS_PER_SEC
; /* Turn x into usecs */
159 x
-= (int64_t) sub
* USPERSEC
;
161 dst
->tv_usec
= x
% USPERSEC
; /* And split */
162 dst
->tv_sec
= x
/ USPERSEC
;
165 /* FIXME: Make thread safe */
167 gettimeofday (struct timeval
*__restrict tv
, void *__restrict tzvp
)
169 struct timezone
*tz
= (struct timezone
*) tzvp
;
171 LONGLONG now
= get_clock (CLOCK_REALTIME
)->usecs ();
175 tv
->tv_sec
= now
/ USPERSEC
;
176 tv
->tv_usec
= now
% USPERSEC
;
186 tz
->tz_minuteswest
= _timezone
/ 60;
187 tz
->tz_dsttime
= _daylight
;
193 /* Cygwin internal */
195 timespec_to_filetime (const struct timespec
*time_in
, PLARGE_INTEGER out
)
197 if (time_in
->tv_nsec
== UTIME_OMIT
)
200 out
->QuadPart
= time_in
->tv_sec
* NS100PERSEC
201 + time_in
->tv_nsec
/ (NSPERSEC
/NS100PERSEC
) + FACTOR
;
204 /* Cygwin internal */
206 timeval_to_filetime (const struct timeval
*time_in
, PLARGE_INTEGER out
)
208 out
->QuadPart
= time_in
->tv_sec
* NS100PERSEC
209 + time_in
->tv_usec
* (NS100PERSEC
/USPERSEC
) + FACTOR
;
212 /* Cygwin internal */
214 timeval_to_ms (const struct timeval
*time_in
, DWORD
&ms
)
216 if (time_in
->tv_sec
< 0 || time_in
->tv_usec
< 0
217 || time_in
->tv_usec
>= USPERSEC
)
219 if ((time_in
->tv_sec
== 0 && time_in
->tv_usec
== 0)
220 || time_in
->tv_sec
>= (time_t) (INFINITE
/ MSPERSEC
))
223 ms
= time_in
->tv_sec
* MSPERSEC
224 + (time_in
->tv_usec
+ (USPERSEC
/ MSPERSEC
) - 1)
225 / (USPERSEC
/ MSPERSEC
);
229 /* Cygwin internal */
231 time_t_to_timeval (time_t in
)
239 /* Cygwin internal */
240 static const struct timespec
*
241 timeval_to_timespec (const struct timeval
*tvp
, struct timespec
*tmp
)
246 tmp
[0].tv_sec
= tvp
[0].tv_sec
;
247 tmp
[0].tv_nsec
= tvp
[0].tv_usec
* (NSPERSEC
/USPERSEC
);
248 if (tmp
[0].tv_nsec
< 0)
250 else if (tmp
[0].tv_nsec
>= NSPERSEC
)
251 tmp
[0].tv_nsec
= NSPERSEC
- 1;
253 tmp
[1].tv_sec
= tvp
[1].tv_sec
;
254 tmp
[1].tv_nsec
= tvp
[1].tv_usec
* (NSPERSEC
/USPERSEC
);
255 if (tmp
[1].tv_nsec
< 0)
257 else if (tmp
[1].tv_nsec
>= NSPERSEC
)
258 tmp
[1].tv_nsec
= NSPERSEC
- 1;
263 /* Cygwin internal */
264 /* Convert a Win32 time to "UNIX" format. */
266 to_time_t (PLARGE_INTEGER ptr
)
268 /* A file time is the number of 100ns since jan 1 1601
269 stuffed into two long words.
270 A time_t is the number of seconds since jan 1 1970. */
272 int64_t x
= ptr
->QuadPart
;
274 /* pass "no time" as epoch */
278 x
-= FACTOR
; /* number of 100ns between 1601 and 1970 */
279 x
/= NS100PERSEC
; /* number of 100ns in a second */
283 /* Cygwin internal */
284 /* Convert a Win32 time to "UNIX" timestruc_t format. */
286 to_timestruc_t (PLARGE_INTEGER ptr
, timestruc_t
*out
)
288 /* A file time is the number of 100ns since jan 1 1601
289 stuffed into two long words.
290 A timestruc_t is the number of seconds and microseconds since jan 1 1970
291 stuffed into a time_t and a long. */
292 int64_t x
= ptr
->QuadPart
;
294 /* pass "no time" as epoch */
302 x
-= FACTOR
; /* number of 100ns between 1601 and 1970 */
303 out
->tv_sec
= x
/ NS100PERSEC
;
304 out
->tv_nsec
= (x
% NS100PERSEC
) * (NSPERSEC
/NS100PERSEC
);
307 /* Cygwin internal */
308 /* Get the current time as a "UNIX" timestruc_t format. */
310 time_as_timestruc_t (timestruc_t
* out
)
312 LARGE_INTEGER systime
;
314 get_system_time (&systime
);
315 to_timestruc_t (&systime
, out
);
318 /* time: POSIX 4.5.1.1, C 4.12.2.4 */
319 /* Return number of seconds since 00:00 UTC on jan 1, 1970 */
324 LARGE_INTEGER systime
;
326 get_system_time (&systime
);
327 res
= to_time_t (&systime
);
331 syscall_printf ("%d = time(%p)", res
, ptr
);
337 utimens_worker (path_conv
&win32
, const struct timespec
*tvp
)
342 set_errno (win32
.error
);
345 fhandler_base
*fh
= NULL
;
348 cygheap_fdenum
cfd (true);
349 while (cfd
.next () >= 0)
350 if (cfd
->get_access () & (FILE_WRITE_ATTRIBUTES
| GENERIC_WRITE
)
351 && RtlEqualUnicodeString (cfd
->pc
.get_nt_native_path (),
352 win32
.get_nt_native_path (),
353 cfd
->pc
.objcaseinsensitive ()))
362 if (!(fh
= build_fh_pc (win32
)))
367 debug_printf ("got %d error from build_fh_pc", fh
->error ());
368 set_errno (fh
->error ());
372 res
= fh
->utimens (tvp
);
379 syscall_printf ("%R = utimes(%S, %p)", res
, win32
.get_nt_native_path (), tvp
);
383 /* utimes: POSIX/SUSv3 */
385 utimes (const char *path
, const struct timeval tvp
[2])
387 path_conv
win32 (path
, PC_POSIX
| PC_SYM_FOLLOW
, stat_suffixes
);
388 struct timespec tmp
[2];
389 return utimens_worker (win32
, timeval_to_timespec (tvp
, tmp
));
394 lutimes (const char *path
, const struct timeval tvp
[2])
396 path_conv
win32 (path
, PC_POSIX
| PC_SYM_NOFOLLOW
, stat_suffixes
);
397 struct timespec tmp
[2];
398 return utimens_worker (win32
, timeval_to_timespec (tvp
, tmp
));
401 /* futimens: POSIX/SUSv4 */
403 futimens (int fd
, const struct timespec tvp
[2])
407 cygheap_fdget
cfd (fd
);
410 else if (cfd
->get_access () & (FILE_WRITE_ATTRIBUTES
| GENERIC_WRITE
))
411 res
= cfd
->utimens (tvp
);
413 res
= utimens_worker (cfd
->pc
, tvp
);
414 syscall_printf ("%d = futimens(%d, %p)", res
, fd
, tvp
);
420 futimes (int fd
, const struct timeval tvp
[2])
422 struct timespec tmp
[2];
423 return futimens (fd
, timeval_to_timespec (tvp
, tmp
));
426 /* utime: POSIX 5.6.6.1 */
428 utime (const char *path
, const struct utimbuf
*buf
)
430 struct timeval tmp
[2];
433 return utimes (path
, 0);
435 debug_printf ("incoming utime act %lx", buf
->actime
);
436 tmp
[0] = time_t_to_timeval (buf
->actime
);
437 tmp
[1] = time_t_to_timeval (buf
->modtime
);
439 return utimes (path
, tmp
);
442 /* ftime: standards? */
444 ftime (struct timeb
*tp
)
449 if (gettimeofday (&tv
, &tz
) < 0)
452 tp
->time
= tv
.tv_sec
;
453 tp
->millitm
= tv
.tv_usec
/ 1000;
454 tp
->timezone
= tz
.tz_minuteswest
;
455 tp
->dstflag
= tz
.tz_dsttime
;
461 clock_gettime (clockid_t clk_id
, struct timespec
*tp
)
463 clk_t
*clock
= get_clock (clk_id
);
472 return clock
->nsecs (clk_id
, tp
);
480 clock_settime (clockid_t clk_id
, const struct timespec
*tp
)
484 if (CLOCKID_IS_PROCESS (clk_id
) || CLOCKID_IS_THREAD (clk_id
))
485 /* According to POSIX, the privileges to set a particular clock
486 * are implementation-defined. On Linux, CPU-time clocks are not
487 * settable; do the same here.
494 if (clk_id
!= CLOCK_REALTIME_COARSE
&& clk_id
!= CLOCK_REALTIME
)
502 tv
.tv_sec
= tp
->tv_sec
;
503 tv
.tv_usec
= tp
->tv_nsec
/ 1000;
511 return settimeofday (&tv
, NULL
);
515 clock_getres (clockid_t clk_id
, struct timespec
*tp
)
517 clk_t
*clock
= get_clock (clk_id
);
526 clock
->resolution (tp
);
537 clock_setres (clockid_t clk_id
, struct timespec
*tp
)
539 /* Don't use this function. It only exists in QNX. Just return
540 success on CLOCK_REALTIME for backward compat. */
541 if (clk_id
!= CLOCK_REALTIME
)
550 clock_getcpuclockid (pid_t pid
, clockid_t
*clk_id
)
555 if (!p
|| !p
->exists ())
558 *clk_id
= (clockid_t
) PID_TO_CLOCKID (pid
);
563 timespec_get (struct timespec
*ts
, int base
)
565 if (base
!= TIME_UTC
)
567 clock_gettime (CLOCK_REALTIME
, ts
);
571 EXPORT_ALIAS (gettimeofday
, _gettimeofday
)
572 EXPORT_ALIAS (times
, _times
)