summaryrefslogtreecommitdiffstats
path: root/src/hlua.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/hlua.c')
-rw-r--r--src/hlua.c112
1 files changed, 77 insertions, 35 deletions
diff --git a/src/hlua.c b/src/hlua.c
index 0a81e7a..098107f 100644
--- a/src/hlua.c
+++ b/src/hlua.c
@@ -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);