diff --git a/src/lj_api.c b/src/lj_api.c index 8b00436d9b..c9a714c8bc 100644 --- a/src/lj_api.c +++ b/src/lj_api.c @@ -26,6 +26,63 @@ #include "lj_strscan.h" #include "lj_strfmt.h" +#include +#if LJ_TARGET_POSIX +#include +#elif LJ_TARGET_WINDOWS +#define timercmp(a, b, CMP) \ + (((a)->tv_sec == (b)->tv_sec) ? \ + ((a)->tv_nsec CMP (b)->tv_nsec) : \ + ((a)->tv_sec CMP (b)->tv_sec)) +#define timeradd(a, b, result) \ + do { \ + (result)->tv_sec = (a)->tv_sec + (b)->tv_sec; \ + (result)->tv_nsec = (a)->tv_nsec + (b)->tv_nsec; \ + if ((result)->tv_nsec >= 1000000000) \ + { \ + ++(result)->tv_sec; \ + (result)->tv_nsec -= 1000000000; \ + } \ + } while (0) +#endif + +static void gc_step_timeout(lua_State *L, uint32_t timeout_usec) +{ +#if LJ_TARGET_POSIX + struct timeval tv_timeout; + tv_timeout.tv_sec = 0; + tv_timeout.tv_usec = timeout_usec; + + struct timeval tv_current; + gettimeofday(&tv_current, NULL); + + timeradd(&tv_current, &tv_timeout, &tv_timeout); + while (timercmp(&tv_current, &tv_timeout, <)) { + if (lj_gc_step(L) > 0) { + break; + } + + gettimeofday(&tv_current, NULL); + } +#elif LJ_TARGET_WINDOWS + struct timespec tv_timeout; + tv_timeout.tv_sec = 0; + tv_timeout.tv_nsec = timeout_usec * 1000; + + struct timespec tv_current; + timespec_get(&tv_current, TIME_UTC); + + timeradd(&tv_current, &tv_timeout, &tv_timeout); + while (timercmp(&tv_current, &tv_timeout, < )) { + if (lj_gc_step(L) > 0) { + break; + } + + timespec_get(&tv_current, TIME_UTC); + } +#endif +} + /* -- Common helper functions --------------------------------------------- */ #define lj_checkapi_slot(idx) \ @@ -1299,11 +1356,16 @@ LUA_API int lua_gc(lua_State *L, int what, int data) g->gc.threshold = (a <= g->gc.total) ? (g->gc.total - a) : 0; while (g->gc.total >= g->gc.threshold) if (lj_gc_step(L) > 0) { - res = 1; - break; + res = 1; + break; } break; } + case LUA_GCTIMEOUT: { + gc_step_timeout(L, (uint32_t)data); + g->gc.threshold = LJ_MAX_MEM; + break; + } case LUA_GCSETPAUSE: res = (int)(g->gc.pause); g->gc.pause = (MSize)data; diff --git a/src/lua.h b/src/lua.h index 6d1634d1ce..bc577ede51 100644 --- a/src/lua.h +++ b/src/lua.h @@ -228,6 +228,7 @@ LUA_API int (lua_status) (lua_State *L); #define LUA_GCSETPAUSE 6 #define LUA_GCSETSTEPMUL 7 #define LUA_GCISRUNNING 9 +#define LUA_GCTIMEOUT 10 LUA_API int (lua_gc) (lua_State *L, int what, int data);