1
/*=========================================================================*\
2
* Timeout management functions
5
* RCS ID: $Id: timeout.c,v 1.30 2005/10/07 04:40:59 diego Exp $
6
\*=========================================================================*/
22
/* min and max macros */
24
#define MIN(x, y) ((x) < (y) ? x : y)
27
#define MAX(x, y) ((x) > (y) ? x : y)
30
/*=========================================================================*\
31
* Internal function prototypes
32
\*=========================================================================*/
33
static int timeout_lua_gettime(lua_State *L);
34
static int timeout_lua_sleep(lua_State *L);
36
static luaL_reg func[] = {
37
{ "gettime", timeout_lua_gettime },
38
{ "sleep", timeout_lua_sleep },
42
/*=========================================================================*\
44
\*=========================================================================*/
45
/*-------------------------------------------------------------------------*\
46
* Initialize structure
47
\*-------------------------------------------------------------------------*/
48
void timeout_init(p_timeout tm, double block, double total) {
53
/*-------------------------------------------------------------------------*\
54
* Determines how much time we have left for the next system call,
55
* if the previous call was successful
57
* tm: timeout control structure
59
* the number of ms left or -1 if there is no time limit
60
\*-------------------------------------------------------------------------*/
61
double timeout_get(p_timeout tm) {
62
if (tm->block < 0.0 && tm->total < 0.0) {
64
} else if (tm->block < 0.0) {
65
double t = tm->total - timeout_gettime() + tm->start;
67
} else if (tm->total < 0.0) {
70
double t = tm->total - timeout_gettime() + tm->start;
71
return MIN(tm->block, MAX(t, 0.0));
75
/*-------------------------------------------------------------------------*\
76
* Returns time since start of operation
78
* tm: timeout control structure
80
* start field of structure
81
\*-------------------------------------------------------------------------*/
82
double timeout_getstart(p_timeout tm) {
86
/*-------------------------------------------------------------------------*\
87
* Determines how much time we have left for the next system call,
88
* if the previous call was a failure
90
* tm: timeout control structure
92
* the number of ms left or -1 if there is no time limit
93
\*-------------------------------------------------------------------------*/
94
double timeout_getretry(p_timeout tm) {
95
if (tm->block < 0.0 && tm->total < 0.0) {
97
} else if (tm->block < 0.0) {
98
double t = tm->total - timeout_gettime() + tm->start;
100
} else if (tm->total < 0.0) {
101
double t = tm->block - timeout_gettime() + tm->start;
104
double t = tm->total - timeout_gettime() + tm->start;
105
return MIN(tm->block, MAX(t, 0.0));
109
/*-------------------------------------------------------------------------*\
110
* Marks the operation start time in structure
112
* tm: timeout control structure
113
\*-------------------------------------------------------------------------*/
114
p_timeout timeout_markstart(p_timeout tm) {
115
tm->start = timeout_gettime();
119
/*-------------------------------------------------------------------------*\
120
* Gets time in s, relative to January 1, 1970 (UTC)
123
\*-------------------------------------------------------------------------*/
125
double timeout_gettime(void) {
128
GetSystemTimeAsFileTime(&ft);
129
/* Windows file time (time since January 1, 1601 (UTC)) */
130
t = ft.dwLowDateTime/1.0e7 + ft.dwHighDateTime*(4294967296.0/1.0e7);
131
/* convert to Unix Epoch time (time since January 1, 1970 (UTC)) */
132
return (t - 11644473600.0);
135
double timeout_gettime(void) {
137
gettimeofday(&v, (struct timezone *) NULL);
138
/* Unix Epoch time (time since January 1, 1970 (UTC)) */
139
return v.tv_sec + v.tv_usec/1.0e6;
143
/*-------------------------------------------------------------------------*\
145
\*-------------------------------------------------------------------------*/
146
int timeout_open(lua_State *L) {
147
luaL_openlib(L, NULL, func, 0);
151
/*-------------------------------------------------------------------------*\
152
* Sets timeout values for IO operations
153
* Lua Input: base, time [, mode]
154
* time: time out value in seconds
155
* mode: "b" for block timeout, "t" for total timeout. (default: b)
156
\*-------------------------------------------------------------------------*/
157
int timeout_meth_settimeout(lua_State *L, p_timeout tm) {
158
double t = luaL_optnumber(L, 2, -1);
159
const char *mode = luaL_optstring(L, 3, "b");
168
luaL_argcheck(L, 0, 3, "invalid timeout mode");
171
lua_pushnumber(L, 1);
175
/*=========================================================================*\
176
* Test support functions
177
\*=========================================================================*/
178
/*-------------------------------------------------------------------------*\
179
* Returns the time the system has been up, in secconds.
180
\*-------------------------------------------------------------------------*/
181
static int timeout_lua_gettime(lua_State *L)
183
lua_pushnumber(L, timeout_gettime());
187
/*-------------------------------------------------------------------------*\
188
* Sleep for n seconds.
189
\*-------------------------------------------------------------------------*/
190
int timeout_lua_sleep(lua_State *L)
192
double n = luaL_checknumber(L, 1);
194
Sleep((int)(n*1000));
196
struct timespec t, r;
199
t.tv_nsec = (int) (n * 1000000000);
200
if (t.tv_nsec >= 1000000000) t.tv_nsec = 999999999;
201
while (nanosleep(&t, &r) != 0) {
203
t.tv_nsec = r.tv_nsec;