1 /*=========================================================================*\
2 * Timeout management functions
4 \*=========================================================================*/
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 \*-------------------------------------------------------------------------*/
191 int timeout_lua_sleep(lua_State
*L
)
193 double n
= luaL_checknumber(L
, 1);
194 if (n
< 0.0) n
= 0.0;
195 if (n
< DBL_MAX
/1000.0) n
*= 1000.0;
196 if (n
> INT_MAX
) n
= INT_MAX
;
201 int timeout_lua_sleep(lua_State
*L
)
203 double n
= luaL_checknumber(L
, 1);
204 struct timespec t
, r
;
205 if (n
< 0.0) n
= 0.0;
206 if (n
> INT_MAX
) n
= INT_MAX
;
209 t
.tv_nsec
= (int) (n
* 1000000000);
210 if (t
.tv_nsec
>= 1000000000) t
.tv_nsec
= 999999999;
211 while (nanosleep(&t
, &r
) != 0) {
213 t
.tv_nsec
= r
.tv_nsec
;