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 EXPORT_ALIAS (times
, _times
)
96 /* settimeofday: BSD */
98 settimeofday (const struct timeval
*tv
, const struct timezone
*tz
)
106 if (tv
->tv_usec
< 0 || tv
->tv_usec
>= USPERSEC
)
112 ptm
= gmtime (&tv
->tv_sec
);
113 st
.wYear
= ptm
->tm_year
+ 1900;
114 st
.wMonth
= ptm
->tm_mon
+ 1;
115 st
.wDayOfWeek
= ptm
->tm_wday
;
116 st
.wDay
= ptm
->tm_mday
;
117 st
.wHour
= ptm
->tm_hour
;
118 st
.wMinute
= ptm
->tm_min
;
119 st
.wSecond
= ptm
->tm_sec
;
120 st
.wMilliseconds
= tv
->tv_usec
/ (USPERSEC
/ MSPERSEC
);
122 res
= -!SetSystemTime (&st
);
131 syscall_printf ("%R = settimeofday(%p, %p)", res
, tv
, tz
);
137 stime (const time_t *t
)
139 struct timeval tv
= { *t
, 0 };
140 return settimeofday(&tv
, NULL
);
143 /* timezone: standards? */
147 char *b
= _my_tls
.locals
.timezone_buf
;
150 __small_sprintf (b
,"GMT%+d:%02d", (int) (-_timezone
/ 3600), (int) (abs (_timezone
/ 60) % 60));
154 /* Cygwin internal */
156 totimeval (struct timeval
*dst
, PLARGE_INTEGER src
, int sub
, int flag
)
158 int64_t x
= __to_clock_t (src
, flag
);
160 x
*= (int64_t) USPERSEC
/ CLOCKS_PER_SEC
; /* Turn x into usecs */
161 x
-= (int64_t) sub
* USPERSEC
;
163 dst
->tv_usec
= x
% USPERSEC
; /* And split */
164 dst
->tv_sec
= x
/ USPERSEC
;
167 /* FIXME: Make thread safe */
169 gettimeofday (struct timeval
*__restrict tv
, void *__restrict tzvp
)
171 struct timezone
*tz
= (struct timezone
*) tzvp
;
173 LONGLONG now
= get_clock (CLOCK_REALTIME
)->usecs ();
177 tv
->tv_sec
= now
/ USPERSEC
;
178 tv
->tv_usec
= now
% USPERSEC
;
188 tz
->tz_minuteswest
= _timezone
/ 60;
189 tz
->tz_dsttime
= _daylight
;
195 EXPORT_ALIAS (gettimeofday
, _gettimeofday
)
197 /* Cygwin internal */
199 timespec_to_filetime (const struct timespec
*time_in
, PLARGE_INTEGER out
)
201 if (time_in
->tv_nsec
== UTIME_OMIT
)
204 out
->QuadPart
= time_in
->tv_sec
* NS100PERSEC
205 + time_in
->tv_nsec
/ (NSPERSEC
/NS100PERSEC
) + FACTOR
;
208 /* Cygwin internal */
210 timeval_to_filetime (const struct timeval
*time_in
, PLARGE_INTEGER out
)
212 out
->QuadPart
= time_in
->tv_sec
* NS100PERSEC
213 + time_in
->tv_usec
* (NS100PERSEC
/USPERSEC
) + FACTOR
;
216 /* Cygwin internal */
218 timeval_to_ms (const struct timeval
*time_in
, DWORD
&ms
)
220 if (time_in
->tv_sec
< 0 || time_in
->tv_usec
< 0
221 || time_in
->tv_usec
>= USPERSEC
)
223 if ((time_in
->tv_sec
== 0 && time_in
->tv_usec
== 0)
224 || time_in
->tv_sec
>= (time_t) (INFINITE
/ MSPERSEC
))
227 ms
= time_in
->tv_sec
* MSPERSEC
228 + (time_in
->tv_usec
+ (USPERSEC
/ MSPERSEC
) - 1)
229 / (USPERSEC
/ MSPERSEC
);
233 /* Cygwin internal */
235 time_t_to_timeval (time_t in
)
243 /* Cygwin internal */
244 static const struct timespec
*
245 timeval_to_timespec (const struct timeval
*tvp
, struct timespec
*tmp
)
250 tmp
[0].tv_sec
= tvp
[0].tv_sec
;
251 tmp
[0].tv_nsec
= tvp
[0].tv_usec
* (NSPERSEC
/USPERSEC
);
252 if (tmp
[0].tv_nsec
< 0)
254 else if (tmp
[0].tv_nsec
>= NSPERSEC
)
255 tmp
[0].tv_nsec
= NSPERSEC
- 1;
257 tmp
[1].tv_sec
= tvp
[1].tv_sec
;
258 tmp
[1].tv_nsec
= tvp
[1].tv_usec
* (NSPERSEC
/USPERSEC
);
259 if (tmp
[1].tv_nsec
< 0)
261 else if (tmp
[1].tv_nsec
>= NSPERSEC
)
262 tmp
[1].tv_nsec
= NSPERSEC
- 1;
267 /* Cygwin internal */
268 /* Convert a Win32 time to "UNIX" format. */
270 to_time_t (PLARGE_INTEGER ptr
)
272 /* A file time is the number of 100ns since jan 1 1601
273 stuffed into two long words.
274 A time_t is the number of seconds since jan 1 1970. */
276 int64_t x
= ptr
->QuadPart
;
278 /* pass "no time" as epoch */
282 x
-= FACTOR
; /* number of 100ns between 1601 and 1970 */
283 x
/= NS100PERSEC
; /* number of 100ns in a second */
287 /* Cygwin internal */
288 /* Convert a Win32 time to "UNIX" timestruc_t format. */
290 to_timestruc_t (PLARGE_INTEGER ptr
, timestruc_t
*out
)
292 /* A file time is the number of 100ns since jan 1 1601
293 stuffed into two long words.
294 A timestruc_t is the number of seconds and microseconds since jan 1 1970
295 stuffed into a time_t and a long. */
296 int64_t x
= ptr
->QuadPart
;
298 /* pass "no time" as epoch */
306 x
-= FACTOR
; /* number of 100ns between 1601 and 1970 */
307 out
->tv_sec
= x
/ NS100PERSEC
;
308 out
->tv_nsec
= (x
% NS100PERSEC
) * (NSPERSEC
/NS100PERSEC
);
311 /* Cygwin internal */
312 /* Get the current time as a "UNIX" timestruc_t format. */
314 time_as_timestruc_t (timestruc_t
* out
)
316 LARGE_INTEGER systime
;
318 get_system_time (&systime
);
319 to_timestruc_t (&systime
, out
);
322 /* time: POSIX 4.5.1.1, C 4.12.2.4 */
323 /* Return number of seconds since 00:00 UTC on jan 1, 1970 */
328 LARGE_INTEGER systime
;
330 get_system_time (&systime
);
331 res
= to_time_t (&systime
);
335 syscall_printf ("%d = time(%p)", res
, ptr
);
341 utimens_worker (path_conv
&win32
, const struct timespec
*tvp
)
346 set_errno (win32
.error
);
349 fhandler_base
*fh
= NULL
;
352 cygheap_fdenum
cfd (true);
353 while (cfd
.next () >= 0)
354 if (cfd
->get_access () & (FILE_WRITE_ATTRIBUTES
| GENERIC_WRITE
)
355 && RtlEqualUnicodeString (cfd
->pc
.get_nt_native_path (),
356 win32
.get_nt_native_path (),
357 cfd
->pc
.objcaseinsensitive ()))
366 if (!(fh
= build_fh_pc (win32
)))
371 debug_printf ("got %d error from build_fh_pc", fh
->error ());
372 set_errno (fh
->error ());
376 res
= fh
->utimens (tvp
);
383 syscall_printf ("%R = utimes(%S, %p)", res
, win32
.get_nt_native_path (), tvp
);
387 /* utimes: POSIX/SUSv3 */
389 utimes (const char *path
, const struct timeval tvp
[2])
391 path_conv
win32 (path
, PC_POSIX
| PC_SYM_FOLLOW
, stat_suffixes
);
392 struct timespec tmp
[2];
393 return utimens_worker (win32
, timeval_to_timespec (tvp
, tmp
));
398 lutimes (const char *path
, const struct timeval tvp
[2])
400 path_conv
win32 (path
, PC_POSIX
| PC_SYM_NOFOLLOW
, stat_suffixes
);
401 struct timespec tmp
[2];
402 return utimens_worker (win32
, timeval_to_timespec (tvp
, tmp
));
405 /* futimens: POSIX/SUSv4 */
407 futimens (int fd
, const struct timespec tvp
[2])
411 cygheap_fdget
cfd (fd
);
414 else if (cfd
->get_access () & (FILE_WRITE_ATTRIBUTES
| GENERIC_WRITE
))
415 res
= cfd
->utimens (tvp
);
417 res
= utimens_worker (cfd
->pc
, tvp
);
418 syscall_printf ("%d = futimens(%d, %p)", res
, fd
, tvp
);
424 futimes (int fd
, const struct timeval tvp
[2])
426 struct timespec tmp
[2];
427 return futimens (fd
, timeval_to_timespec (tvp
, tmp
));
430 /* utime: POSIX 5.6.6.1 */
432 utime (const char *path
, const struct utimbuf
*buf
)
434 struct timeval tmp
[2];
437 return utimes (path
, 0);
439 debug_printf ("incoming utime act %lx", buf
->actime
);
440 tmp
[0] = time_t_to_timeval (buf
->actime
);
441 tmp
[1] = time_t_to_timeval (buf
->modtime
);
443 return utimes (path
, tmp
);
446 /* ftime: standards? */
448 ftime (struct timeb
*tp
)
453 if (gettimeofday (&tv
, &tz
) < 0)
456 tp
->time
= tv
.tv_sec
;
457 tp
->millitm
= tv
.tv_usec
/ 1000;
458 tp
->timezone
= tz
.tz_minuteswest
;
459 tp
->dstflag
= tz
.tz_dsttime
;
465 clock_gettime (clockid_t clk_id
, struct timespec
*tp
)
467 clk_t
*clock
= get_clock (clk_id
);
476 return clock
->nsecs (clk_id
, tp
);
484 clock_settime (clockid_t clk_id
, const struct timespec
*tp
)
488 if (CLOCKID_IS_PROCESS (clk_id
) || CLOCKID_IS_THREAD (clk_id
))
489 /* According to POSIX, the privileges to set a particular clock
490 * are implementation-defined. On Linux, CPU-time clocks are not
491 * settable; do the same here.
498 if (clk_id
!= CLOCK_REALTIME_COARSE
&& clk_id
!= CLOCK_REALTIME
)
506 tv
.tv_sec
= tp
->tv_sec
;
507 tv
.tv_usec
= tp
->tv_nsec
/ 1000;
515 return settimeofday (&tv
, NULL
);
519 clock_getres (clockid_t clk_id
, struct timespec
*tp
)
521 clk_t
*clock
= get_clock (clk_id
);
530 clock
->resolution (tp
);
541 clock_setres (clockid_t clk_id
, struct timespec
*tp
)
543 /* Don't use this function. It only exists in QNX. Just return
544 success on CLOCK_REALTIME for backward compat. */
545 if (clk_id
!= CLOCK_REALTIME
)
554 clock_getcpuclockid (pid_t pid
, clockid_t
*clk_id
)
559 if (!p
|| !p
->exists ())
562 *clk_id
= (clockid_t
) PID_TO_CLOCKID (pid
);
567 timespec_get (struct timespec
*ts
, int base
)
569 if (base
!= TIME_UTC
)
571 clock_gettime (CLOCK_REALTIME
, ts
);