1
/* $Id: time.c,v 1.9 2005/07/29 16:40:52 soyt Exp $
2
******************************************************************************
4
platform abstraction of time related functions.
6
Copyright (C) 2004 Brian S. Julin [skids@users.sourceforge.net]
8
Permission is hereby granted, free of charge, to any person obtaining a
9
copy of this software and associated documentation files (the "Software"),
10
to deal in the Software without restriction, including without limitation
11
the rights to use, copy, modify, merge, publish, distribute, sublicense,
12
and/or sell copies of the Software, and to permit persons to whom the
13
Software is furnished to do so, subject to the following conditions:
15
The above copyright notice and this permission notice shall be included in
16
all copies or substantial portions of the Software.
18
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
21
THE AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
22
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
23
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25
******************************************************************************
30
#include <ggi/system.h>
36
#ifdef GG_CURTIME_USE_GETSYSTEMTIMEASFILETIME
44
/* Subtract timeval tv1 from timeval tv2, leaving the result in tv2. */
45
#define TVDIF(tv1, tv2) \
46
tv2.tv_sec -= tv1.tv_sec; \
47
if (tv2.tv_usec < tv1.tv_usec) { \
49
tv2.tv_usec += 1000000 - tv1.tv_usec; \
50
} else tv2.tv_usec -= tv1.tv_usec;
53
/* Only one of the GG_USLEEP_USE_* macros will be defined by autoconf */
55
#ifdef GG_USLEEP_USE_USLEEP
57
/* LibC usleep implementation -- we must deal with different flavors */
61
#ifdef GG_USLEEP_999999
63
/* We have a pedantic usleep, so we have to split up calls into 1 sec chunks */
65
int ggUSleep (int32_t usecs) {
66
struct timeval tv1, tv2;
71
/* We could check each call for interrupt, but why bother,
72
* since ggUSleep is interruptible. Plus we don't have to
73
* care about GG_USLEEP_VOID this way.
75
while (usecs2 >= 1000000) {
84
if (tv2.tv_sec < usecs / 1000000) return -1;
85
if (tv2.tv_usec < usecs % 1000000) return -1;
89
#else /* not GG_USLEEP 999999 -- still have to adjust return type/value. */
93
int ggUSleep (int32_t usecs) {
94
struct timeval tv1, tv2;
102
if (tv2.tv_sec < usecs / 1000000) return -1;
103
if (tv2.tv_usec < usecs % 1000000) return -1;
107
#else /* not GG_USLEEP_VOID -- simple C typecasting should suffice. */
109
int ggUSleep (int32_t usecs) {
110
return (int)usleep(usecs);
113
#endif /* not GG_USLEEP_VOID */
114
#endif /* not GG_USLEEP_999999 */
115
#endif /* GG_USLEEP_USE_USLEEP */
118
#ifdef GG_USLEEP_USE_W32SLEEP
120
/* Win32 implementation, when no usleep() is available i.e. mingw */
124
/* windows.h is included above */
126
int ggUSleep (int32_t usecs) {
127
Sleep((usecs + 999) / 1000);
133
#ifdef GG_USLEEP_USE_SELECT
135
/* Unix select used as sleep -- when select doesn't choke on an empty fdset. */
139
#ifdef HAVE_SYS_TYPES_H
140
#include <sys/types.h>
143
int ggUSleep(int32_t usecs) {
145
tv.tv_sec = usecs / 1000000;
146
tv.tv_usec = usecs % 1000000;
147
select(0, NULL, NULL, NULL, &tv);
148
if (tv.tv_usec || tv.tv_sec) return -1;
152
#endif /* GG_USLEEP_USE_SELECT */
155
#error You need to implement ggUSleep on this platform!
160
/* Only one of the GG_CURTIME_USE_* macros will be defined by autoconf */
162
#ifdef GG_CURTIME_USE_GETTIMEOFDAY
164
/* Headers already included by gg.h since struct timeval needed there */
166
#define GG_CURTIME_OK
167
int ggCurTime(struct timeval *tv) {
168
return(gettimeofday((tv), NULL));
173
#ifdef GG_CURTIME_USE_GETSYSTEMTIMEASFILETIME
175
/* windows.h included above on w32.
176
* Other headers already included by gg.h since struct timeval needed there.
179
#define GG_CURTIME_OK
180
int ggCurTime(struct timeval *tv) {
183
GetSystemTimeAsFileTime(&ftim);
185
(tv)->tv_sec = (((LARGE_INTEGER *)(void *)(&ftim))->QuadPart
186
- GG_UINT64_C(116444736000000000)) / 10000000;
187
(tv)->tv_usec = (((LARGE_INTEGER *)(void *)(&ftim))->QuadPart
195
#ifndef GG_CURTIME_OK
196
#error You need to implement ggCurTime() for this system
200
/* Uninterruptible sleep is now easily implemented based on the above work. */
201
void ggUSlumber(int32_t usecs) {
202
struct timeval tv1, tv2;
206
while (ggUSleep(usecs)) {
209
if (tv2.tv_sec > usecs / 1000000) return;
210
if (tv2.tv_sec) usecs -= 1000000 * tv2.tv_sec;
211
if (tv2.tv_usec > usecs) return;
212
usecs -= tv2.tv_usec;