diff options
Diffstat (limited to '')
-rw-r--r-- | src/hlua.c | 112 |
1 files changed, 77 insertions, 35 deletions
@@ -516,7 +516,15 @@ static inline int hlua_timer_check(const struct hlua_timer *timer) /* Interrupts the Lua processing each "hlua_nb_instruction" instructions. * it is used for preventing infinite loops. + */ +static unsigned int hlua_nb_instruction = 0; + +/* Wrapper to retrieve the number of instructions between two interrupts + * depending on user settings and current hlua context. If not already + * explicitly set, we compute the ideal value using hard limits releaved + * by Thierry Fournier's work, whose original notes may be found below: * + * -- * I test the scheer with an infinite loop containing one incrementation * and one test. I run this loop between 10 seconds, I raise a ceil of * 710M loops from one interrupt each 9000 instructions, so I fix the value @@ -537,9 +545,42 @@ static inline int hlua_timer_check(const struct hlua_timer *timer) * 10000 | 710 * 100000 | 710 * 1000000 | 710 + * -- * + * Thanks to his work, we know we can safely use values between 500 and 10000 + * without a significant impact on performance. */ -static unsigned int hlua_nb_instruction = 10000; +static inline unsigned int hlua_get_nb_instruction(struct hlua *hlua) +{ + int ceil = 10000; /* above 10k, no significant performance gain */ + int floor = 500; /* below 500, significant performance loss */ + + if (hlua_nb_instruction) { + /* value enforced by user */ + return hlua_nb_instruction; + } + + /* not set, assign automatic value */ + if (hlua->state_id == 0) { + /* this function is expected to be called during runtime (after config + * parsing), thus global.nb_thread is expected to be set. + */ + BUG_ON(global.nbthread == 0); + + /* main lua stack (shared global lock), take number of threads into + * account in an attempt to reduce thread contention + */ + return MAX(floor, ceil / global.nbthread); + } + else { + /* per-thread lua stack, less contention is expected (no global lock), + * allow up to the maximum number of instructions and hope that the + * user manually yields after heavy (lock dependent) work from lua + * script (e.g.: map manipulation). + */ + return ceil; + } +} /* Descriptor for the memory allocation state. The limit is pre-initialised to * 0 until it is replaced by "tune.lua.maxmem" during the config parsing, or it @@ -1783,7 +1824,7 @@ void hlua_hook(lua_State *L, lua_Debug *ar) /* Try to interrupt the process at the end of the current * unyieldable function. */ - lua_sethook(hlua->T, hlua_hook, LUA_MASKRET|LUA_MASKCOUNT, hlua_nb_instruction); + lua_sethook(hlua->T, hlua_hook, LUA_MASKRET|LUA_MASKCOUNT, hlua_get_nb_instruction(hlua)); } /* This function start or resumes the Lua stack execution. If the flag @@ -1823,10 +1864,10 @@ static enum hlua_exec hlua_ctx_resume(struct hlua *lua, int yield_allowed) resume_execution: - /* This hook interrupts the Lua processing each 'hlua_nb_instruction' + /* This hook interrupts the Lua processing each 'hlua_get_nb_instruction() * instructions. it is used for preventing infinite loops. */ - lua_sethook(lua->T, hlua_hook, LUA_MASKCOUNT, hlua_nb_instruction); + lua_sethook(lua->T, hlua_hook, LUA_MASKCOUNT, hlua_get_nb_instruction(lua)); /* Remove all flags except the running flags. */ HLUA_SET_RUN(lua); @@ -2113,7 +2154,7 @@ static int hlua_set_map(lua_State *L) /* This function is an LUA binding. It provides a function * for retrieving a var from the proc scope in core. */ - static int hlua_core_get_var(lua_State *L) +__LJMP static int hlua_core_get_var(lua_State *L) { const char *name; size_t len; @@ -2135,7 +2176,6 @@ static int hlua_set_map(lua_State *L) } return MAY_LJMP(hlua_smp2lua(L, &smp)); - return 1; } /* This function disables the sending of email through the @@ -2415,7 +2455,7 @@ static void hlua_socket_handler(struct appctx *appctx) struct hlua_csk_ctx *ctx = appctx->svcctx; struct stconn *sc = appctx_sc(appctx); - if (unlikely(se_fl_test(appctx->sedesc, (SE_FL_EOS|SE_FL_ERROR|SE_FL_SHR|SE_FL_SHW)))) { + if (unlikely(se_fl_test(appctx->sedesc, (SE_FL_EOS|SE_FL_ERROR)))) { co_skip(sc_oc(sc), co_data(sc_oc(sc))); notification_wake(&ctx->wake_on_read); notification_wake(&ctx->wake_on_write); @@ -3574,7 +3614,7 @@ __LJMP static struct channel *hlua_checkchannel(lua_State *L, int ud) /* Pushes the channel onto the top of the stack. If the stask does not have a * free slots, the function fails and returns 0; */ -static int hlua_channel_new(lua_State *L, struct channel *channel) +__LJMP static int hlua_channel_new(lua_State *L, struct channel *channel) { /* Check stack size. */ if (!lua_checkstack(L, 3)) @@ -4592,7 +4632,7 @@ __LJMP static struct hlua_smp *hlua_checkfetches(lua_State *L, int ud) /* This function creates and push in the stack a fetch object according * with a current TXN. */ -static int hlua_fetches_new(lua_State *L, struct hlua_txn *txn, unsigned int flags) +__LJMP static int hlua_fetches_new(lua_State *L, struct hlua_txn *txn, unsigned int flags) { struct hlua_smp *hsmp; @@ -4714,7 +4754,7 @@ __LJMP static struct hlua_smp *hlua_checkconverters(lua_State *L, int ud) /* This function creates and push in the stack a Converters object * according with a current TXN. */ -static int hlua_converters_new(lua_State *L, struct hlua_txn *txn, unsigned int flags) +__LJMP static int hlua_converters_new(lua_State *L, struct hlua_txn *txn, unsigned int flags) { struct hlua_smp *hsmp; @@ -6095,7 +6135,7 @@ __LJMP static struct hlua_txn *hlua_checkhttp(lua_State *L, int ud) /* This function creates and push in the stack a HTTP object * according with a current TXN. */ -static int hlua_http_new(lua_State *L, struct hlua_txn *txn) +__LJMP static int hlua_http_new(lua_State *L, struct hlua_txn *txn) { struct hlua_txn *htxn; @@ -8131,7 +8171,7 @@ __LJMP static int hlua_get_priv(lua_State *L) * return 0 if the stack does not contains free slots, * otherwise it returns 1. */ -static int hlua_txn_new(lua_State *L, struct stream *s, struct proxy *p, int dir, int flags) +__LJMP static int hlua_txn_new(lua_State *L, struct stream *s, struct proxy *p, int dir, int flags) { struct hlua_txn *htxn; @@ -8311,30 +8351,25 @@ __LJMP static int hlua_txn_log_alert(lua_State *L) return 0; } -__LJMP static int hlua_txn_set_loglevel(lua_State *L) +__LJMP static int hlua_txn_set_fc_mark(lua_State *L) { struct hlua_txn *htxn; - int ll; + int mark; - MAY_LJMP(check_args(L, 2, "set_loglevel")); + MAY_LJMP(check_args(L, 2, "set_fc_mark")); htxn = MAY_LJMP(hlua_checktxn(L, 1)); - ll = MAY_LJMP(luaL_checkinteger(L, 2)); - - if (ll < -1 || ll > NB_LOG_LEVELS) - WILL_LJMP(luaL_argerror(L, 2, "Bad log level. It must be one of the following value:" - " core.silent(-1), core.emerg(0), core.alert(1), core.crit(2), core.error(3)," - " core.warning(4), core.notice(5), core.info(6) or core.debug(7)")); + mark = MAY_LJMP(luaL_checkinteger(L, 2)); - htxn->s->logs.level = (ll == -1) ? ll : ll + 1; + conn_set_mark(objt_conn(htxn->s->sess->origin), mark); return 0; } -__LJMP static int hlua_txn_set_tos(lua_State *L) +__LJMP static int hlua_txn_set_fc_tos(lua_State *L) { struct hlua_txn *htxn; int tos; - MAY_LJMP(check_args(L, 2, "set_tos")); + MAY_LJMP(check_args(L, 2, "set_fc_tos")); htxn = MAY_LJMP(hlua_checktxn(L, 1)); tos = MAY_LJMP(luaL_checkinteger(L, 2)); @@ -8342,16 +8377,21 @@ __LJMP static int hlua_txn_set_tos(lua_State *L) return 0; } -__LJMP static int hlua_txn_set_mark(lua_State *L) +__LJMP static int hlua_txn_set_loglevel(lua_State *L) { struct hlua_txn *htxn; - int mark; + int ll; - MAY_LJMP(check_args(L, 2, "set_mark")); + MAY_LJMP(check_args(L, 2, "set_loglevel")); htxn = MAY_LJMP(hlua_checktxn(L, 1)); - mark = MAY_LJMP(luaL_checkinteger(L, 2)); + ll = MAY_LJMP(luaL_checkinteger(L, 2)); - conn_set_mark(objt_conn(htxn->s->sess->origin), mark); + if (ll < -1 || ll > NB_LOG_LEVELS) + WILL_LJMP(luaL_argerror(L, 2, "Bad log level. It must be one of the following value:" + " core.silent(-1), core.emerg(0), core.alert(1), core.crit(2), core.error(3)," + " core.warning(4), core.notice(5), core.info(6) or core.debug(7)")); + + htxn->s->logs.level = (ll == -1) ? ll : ll + 1; return 0; } @@ -8617,7 +8657,7 @@ __LJMP static int hlua_txn_done(lua_State *L) /* Pushes the TXN reply onto the top of the stack. If the stask does not have a * free slots, the function fails and returns 0; */ -static int hlua_txn_reply_new(lua_State *L) +__LJMP static int hlua_txn_reply_new(lua_State *L) { struct hlua_txn *htxn; const char *reason, *body = NULL; @@ -9575,7 +9615,7 @@ __LJMP static void hlua_event_hdl_cb_push_args(struct hlua_event_sub *hlua_sub, */ px = proxy_find_by_id(e_server->safe.proxy_uuid, PR_CAP_BE, 0); BUG_ON(!px); - server = findserver_unique_id(px, e_server->safe.puid, e_server->safe.rid); + server = server_find_by_id_unique(px, e_server->safe.puid, e_server->safe.rid); if (server) { lua_pushstring(hlua->T, "reference"); hlua_fcn_new_server(hlua->T, server); @@ -9658,14 +9698,14 @@ static struct task *hlua_event_runner(struct task *task, void *context, unsigned error = hlua_tostring_safe(hlua_sub->hlua->T, -1); else error = "critical error"; - ha_alert("Lua event_hdl: %s.\n", error); + SEND_ERR(NULL, "Lua event_hdl: %s.\n", error); hlua_unlock(hlua_sub->hlua); goto skip_event; } /* Check stack available size. */ if (!lua_checkstack(hlua_sub->hlua->T, 5)) { - ha_alert("Lua event_hdl: full stack.\n"); + SEND_ERR(NULL, "Lua event_hdl: full stack.\n"); RESET_SAFE_LJMP(hlua_sub->hlua); goto skip_event; } @@ -13939,9 +13979,11 @@ lua_State *hlua_init_state(int thread_num) hlua_class_function(L, "get_var", hlua_get_var); hlua_class_function(L, "done", hlua_txn_done); hlua_class_function(L, "reply", hlua_txn_reply_new); + hlua_class_function(L, "set_fc_mark", hlua_txn_set_fc_mark); + hlua_class_function(L, "set_fc_tos", hlua_txn_set_fc_tos); hlua_class_function(L, "set_loglevel", hlua_txn_set_loglevel); - hlua_class_function(L, "set_tos", hlua_txn_set_tos); - hlua_class_function(L, "set_mark", hlua_txn_set_mark); + hlua_class_function(L, "set_mark", hlua_txn_set_fc_mark); // DEPRECATED, use set_fc_mark + hlua_class_function(L, "set_tos", hlua_txn_set_fc_tos); // DEPRECATED, use set_fc_tos hlua_class_function(L, "set_priority_class", hlua_txn_set_priority_class); hlua_class_function(L, "set_priority_offset", hlua_txn_set_priority_offset); hlua_class_function(L, "deflog", hlua_txn_deflog); |