Update to lua 5.4 (#1174)

* update to lua 5.4.0-rc1

* remove LUA_ERRGCMM

* use age bits for shared

* remove unused lbitlib.c

* use luaV_fastget

* fix #1174

* suspend函数tailcall优化

* 防止没有session导致未调用suspend

* luaH_setint check shared (#1184)

* set LUA_GCGEN by default

* fix #1174 (#1186)

checkshared in sweeplist

* update to lua 5.4 rc2

* update to lua 5.4 rc4

* move skynet.profile into snlua

* Use lua_sethook to interrupt tight loops

* remove lua_checksig

* critical condition for signals

* update to lua 5.4 released

* lua 5.4 bugfix

* update lua bugfix

* fix lua_sharestring (#1224)

* update lua

* update lua 5.4

* update README

* add skynet.select

* add test

* test error & discard

* yield session

* request error has no error message

* add timeout to skynet.select

* bugfix

* for lua 5.4

* new version

* bugfix

* bugfix

* use if instead of while

* make local

* yield in select for

* update lua 5.4.1

* change lua version (#1245)

Co-authored-by: xiaojin <xiaojin@onemt.com.cn>

* update lua version number

Co-authored-by: hong <hongling0@gmail.com>
Co-authored-by: hong <hongling-0@qq.com>
Co-authored-by: 风---自由 <996442717qqcom@gmail.com>
Co-authored-by: xiaojin <xiaojin@onemt.com.cn>
This commit is contained in:
云风
2020-10-10 13:36:59 +08:00
committed by GitHub
parent eef2b1fc62
commit eaa60ca8dd
77 changed files with 11277 additions and 5962 deletions

View File

@@ -8,6 +8,17 @@
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <time.h>
#if defined(__APPLE__)
#include <mach/task.h>
#include <mach/mach.h>
#endif
#define NANOSEC 1000000000
#define MICROSEC 1000000
// #define DEBUG_LOG
#define MEMORY_WARNING_REPORT (1024 * 1024 * 32)
@@ -17,6 +28,8 @@ struct snlua {
size_t mem;
size_t mem_report;
size_t mem_limit;
lua_State * activeL;
volatile int trap;
};
// LUA_CACHELIB may defined in patched lua for shared proto
@@ -46,6 +59,295 @@ codecache(lua_State *L) {
#endif
static void
signal_hook(lua_State *L, lua_Debug *ar) {
void *ud = NULL;
lua_getallocf(L, &ud);
struct snlua *l = (struct snlua *)ud;
lua_sethook (L, NULL, 0, 0);
if (l->trap) {
l->trap = 0;
luaL_error(L, "signal 0");
}
}
static void
switchL(lua_State *L, struct snlua *l) {
l->activeL = L;
if (l->trap) {
lua_sethook(L, signal_hook, LUA_MASKCOUNT, 1);
}
}
static int
lua_resumeX(lua_State *L, lua_State *from, int nargs, int *nresults) {
void *ud = NULL;
lua_getallocf(L, &ud);
struct snlua *l = (struct snlua *)ud;
switchL(L, l);
int err = lua_resume(L, from, nargs, nresults);
switchL(from, l);
return err;
}
static double
get_time() {
#if !defined(__APPLE__)
struct timespec ti;
clock_gettime(CLOCK_THREAD_CPUTIME_ID, &ti);
int sec = ti.tv_sec & 0xffff;
int nsec = ti.tv_nsec;
return (double)sec + (double)nsec / NANOSEC;
#else
struct task_thread_times_info aTaskInfo;
mach_msg_type_number_t aTaskInfoCount = TASK_THREAD_TIMES_INFO_COUNT;
if (KERN_SUCCESS != task_info(mach_task_self(), TASK_THREAD_TIMES_INFO, (task_info_t )&aTaskInfo, &aTaskInfoCount)) {
return 0;
}
int sec = aTaskInfo.user_time.seconds & 0xffff;
int msec = aTaskInfo.user_time.microseconds;
return (double)sec + (double)msec / MICROSEC;
#endif
}
static inline double
diff_time(double start) {
double now = get_time();
if (now < start) {
return now + 0x10000 - start;
} else {
return now - start;
}
}
// coroutine lib, add profile
/*
** Resumes a coroutine. Returns the number of results for non-error
** cases or -1 for errors.
*/
static int auxresume (lua_State *L, lua_State *co, int narg) {
int status, nres;
if (!lua_checkstack(co, narg)) {
lua_pushliteral(L, "too many arguments to resume");
return -1; /* error flag */
}
lua_xmove(L, co, narg);
status = lua_resumeX(co, L, narg, &nres);
if (status == LUA_OK || status == LUA_YIELD) {
if (!lua_checkstack(L, nres + 1)) {
lua_pop(co, nres); /* remove results anyway */
lua_pushliteral(L, "too many results to resume");
return -1; /* error flag */
}
lua_xmove(co, L, nres); /* move yielded values */
return nres;
}
else {
lua_xmove(co, L, 1); /* move error message */
return -1; /* error flag */
}
}
static int
timing_enable(lua_State *L, int co_index, lua_Number *start_time) {
lua_pushvalue(L, co_index);
lua_rawget(L, lua_upvalueindex(1));
if (lua_isnil(L, -1)) { // check total time
lua_pop(L, 1);
return 0;
}
*start_time = lua_tonumber(L, -1);
lua_pop(L,1);
return 1;
}
static double
timing_total(lua_State *L, int co_index) {
lua_pushvalue(L, co_index);
lua_rawget(L, lua_upvalueindex(2));
double total_time = lua_tonumber(L, -1);
lua_pop(L,1);
return total_time;
}
static int
timing_resume(lua_State *L, int co_index, int n) {
lua_State *co = lua_tothread(L, co_index);
lua_Number start_time = 0;
if (timing_enable(L, co_index, &start_time)) {
start_time = get_time();
#ifdef DEBUG_LOG
fprintf(stderr, "PROFILE [%p] resume %lf\n", co, ti);
#endif
lua_pushvalue(L, co_index);
lua_pushnumber(L, start_time);
lua_rawset(L, lua_upvalueindex(1)); // set start time
}
int r = auxresume(L, co, lua_gettop(L) - 1);
if (timing_enable(L, co_index, &start_time)) {
double total_time = timing_total(L, co_index);
double diff = diff_time(start_time);
total_time += diff;
#ifdef DEBUG_LOG
fprintf(stderr, "PROFILE [%p] yield (%lf/%lf)\n", co, diff, total_time);
#endif
lua_pushvalue(L, co_index);
lua_pushnumber(L, total_time);
lua_rawset(L, lua_upvalueindex(2));
}
return r;
}
static int luaB_coresume (lua_State *L) {
luaL_checktype(L, 1, LUA_TTHREAD);
int r = timing_resume(L, 1, lua_gettop(L) - 1);
if (r < 0) {
lua_pushboolean(L, 0);
lua_insert(L, -2);
return 2; /* return false + error message */
}
else {
lua_pushboolean(L, 1);
lua_insert(L, -(r + 1));
return r + 1; /* return true + 'resume' returns */
}
}
static int luaB_auxwrap (lua_State *L) {
lua_State *co = lua_tothread(L, lua_upvalueindex(3));
int r = timing_resume(L, lua_upvalueindex(3), lua_gettop(L));
if (r < 0) {
int stat = lua_status(co);
if (stat != LUA_OK && stat != LUA_YIELD)
lua_resetthread(co); /* close variables in case of errors */
if (lua_type(L, -1) == LUA_TSTRING) { /* error object is a string? */
luaL_where(L, 1); /* add extra info, if available */
lua_insert(L, -2);
lua_concat(L, 2);
}
return lua_error(L); /* propagate error */
}
return r;
}
static int luaB_cocreate (lua_State *L) {
lua_State *NL;
luaL_checktype(L, 1, LUA_TFUNCTION);
NL = lua_newthread(L);
lua_pushvalue(L, 1); /* move function to top */
lua_xmove(L, NL, 1); /* move function from L to NL */
return 1;
}
static int luaB_cowrap (lua_State *L) {
lua_pushvalue(L, lua_upvalueindex(1));
lua_pushvalue(L, lua_upvalueindex(2));
luaB_cocreate(L);
lua_pushcclosure(L, luaB_auxwrap, 3);
return 1;
}
// profile lib
static int
lstart(lua_State *L) {
if (lua_gettop(L) != 0) {
lua_settop(L,1);
luaL_checktype(L, 1, LUA_TTHREAD);
} else {
lua_pushthread(L);
}
lua_Number start_time = 0;
if (timing_enable(L, 1, &start_time)) {
return luaL_error(L, "Thread %p start profile more than once", lua_topointer(L, 1));
}
// reset total time
lua_pushvalue(L, 1);
lua_pushnumber(L, 0);
lua_rawset(L, lua_upvalueindex(2));
// set start time
lua_pushvalue(L, 1);
start_time = get_time();
#ifdef DEBUG_LOG
fprintf(stderr, "PROFILE [%p] start\n", L);
#endif
lua_pushnumber(L, start_time);
lua_rawset(L, lua_upvalueindex(1));
return 0;
}
static int
lstop(lua_State *L) {
if (lua_gettop(L) != 0) {
lua_settop(L,1);
luaL_checktype(L, 1, LUA_TTHREAD);
} else {
lua_pushthread(L);
}
lua_Number start_time = 0;
if (!timing_enable(L, 1, &start_time)) {
return luaL_error(L, "Call profile.start() before profile.stop()");
}
double ti = diff_time(start_time);
double total_time = timing_total(L,1);
lua_pushvalue(L, 1); // push coroutine
lua_pushnil(L);
lua_rawset(L, lua_upvalueindex(1));
lua_pushvalue(L, 1); // push coroutine
lua_pushnil(L);
lua_rawset(L, lua_upvalueindex(2));
total_time += ti;
lua_pushnumber(L, total_time);
#ifdef DEBUG_LOG
fprintf(stderr, "PROFILE [%p] stop (%lf/%lf)\n", lua_tothread(L,1), ti, total_time);
#endif
return 1;
}
static int
init_profile(lua_State *L) {
luaL_Reg l[] = {
{ "start", lstart },
{ "stop", lstop },
{ "resume", luaB_coresume },
{ "wrap", luaB_cowrap },
{ NULL, NULL },
};
luaL_newlibtable(L,l);
lua_newtable(L); // table thread->start time
lua_newtable(L); // table thread->total time
lua_newtable(L); // weak table
lua_pushliteral(L, "kv");
lua_setfield(L, -2, "__mode");
lua_pushvalue(L, -1);
lua_setmetatable(L, -3);
lua_setmetatable(L, -3);
luaL_setfuncs(L,l,2);
return 1;
}
/// end of coroutine
static int
traceback (lua_State *L) {
const char *msg = lua_tostring(L, 1);
@@ -80,11 +382,25 @@ init_cb(struct snlua *l, struct skynet_context *ctx, const char * args, size_t s
lua_pushboolean(L, 1); /* signal for libraries to ignore env. vars. */
lua_setfield(L, LUA_REGISTRYINDEX, "LUA_NOENV");
luaL_openlibs(L);
luaL_requiref(L, "skynet.profile", init_profile, 0);
int profile_lib = lua_gettop(L);
// replace coroutine.resume / coroutine.wrap
lua_getglobal(L, "coroutine");
lua_getfield(L, profile_lib, "resume");
lua_setfield(L, -2, "resume");
lua_getfield(L, profile_lib, "wrap");
lua_setfield(L, -2, "wrap");
lua_settop(L, profile_lib-1);
lua_pushlightuserdata(L, ctx);
lua_setfield(L, LUA_REGISTRYINDEX, "skynet_context");
luaL_requiref(L, "skynet.codecache", codecache , 0);
lua_pop(L,1);
lua_gc(L, LUA_GCGEN, 0, 0);
const char *path = optstring(ctx, "lua_path","./lualib/?.lua;./lualib/?/init.lua");
lua_pushstring(L, path);
lua_setglobal(L, "LUA_PATH");
@@ -184,6 +500,8 @@ snlua_create(void) {
l->mem_report = MEMORY_WARNING_REPORT;
l->mem_limit = 0;
l->L = lua_newstate(lalloc, l);
l->activeL = NULL;
l->trap = 0;
return l;
}
@@ -197,10 +515,10 @@ void
snlua_signal(struct snlua *l, int signal) {
skynet_error(l->ctx, "recv a signal %d", signal);
if (signal == 0) {
#ifdef lua_checksig
// If our lua support signal (modified lua version by skynet), trigger it.
skynet_sig_L = l->L;
#endif
if (l->trap == 0) {
l->trap = 1;
lua_sethook (l->activeL, signal_hook, LUA_MASKCOUNT, 1);
}
} else if (signal == 1) {
skynet_error(l->ctx, "Current Memory %.3fK", (float)l->mem / 1024);
}