*/
#include "suricata-common.h"
+#include "conf.h"
+
#include "threads.h"
#include "debug.h"
#include "decode.h"
#else /* HAVE_LUAJIT */
+#include "util-pool.h"
+
static int DetectLuajitMatch (ThreadVars *, DetectEngineThreadCtx *,
Packet *, Signature *, SigMatch *);
static int DetectLuajitSetup (DetectEngineCtx *, Signature *, char *);
return;
}
+/** \brief lua_State pool
+ *
+ * Luajit requires states to be alloc'd in memory <2GB. For this reason we
+ * prealloc the states early during engine startup so we have a better chance
+ * of getting the states. We protect the pool with a lock as the detect
+ * threads access it during their init and cleanup.
+ *
+ * Pool size is automagically determined based on number of keyword occurences,
+ * cpus/cores and rule reloads being enabled or not.
+ *
+ * Alternatively, the "detect-engine.luajit-states" var can be set.
+ */
+static Pool *luajit_states = NULL;
+static pthread_mutex_t luajit_states_lock = PTHREAD_MUTEX_INITIALIZER;
+
#define DATATYPE_PACKET (1<<0)
#define DATATYPE_PAYLOAD (1<<1)
#define DATATYPE_STREAM (1<<2)
#define DATATYPE_HTTP_RESPONSE_COOKIE (1<<11)
#define DATATYPE_HTTP_RESPONSE_BODY (1<<12)
+static void *LuaStatePoolAlloc(void) {
+ return luaL_newstate();
+}
+
+static void LuaStatePoolClean(void *d) {
+ lua_State *s = (lua_State *)d;
+ if (s != NULL)
+ lua_close(s);
+}
+
+/** \brief Populate lua states pool
+ *
+ * \param num keyword instances
+ * \param reloads bool indicating we have rule reloads enabled
+ */
+int DetectLuajitSetupStatesPool(int num, int reloads) {
+ int retval = 0;
+ pthread_mutex_lock(&luajit_states_lock);
+
+ if (luajit_states == NULL) {
+ int cnt = 0;
+ char *conf_val = NULL;
+
+ if ((ConfGet("detect-engine.luajit-states", &conf_val)) == 1) {
+ cnt = (int)atoi(conf_val);
+ } else {
+ int cpus = UtilCpuGetNumProcessorsOnline();
+ if (cpus == 0) {
+ cpus = 10;
+ }
+ cnt = num * cpus;
+
+ /* alloc a bunch extra so reload can add new rules/instances */
+ if (reloads)
+ cnt *= 5;
+ }
+
+ luajit_states = PoolInit(0, cnt, 0, LuaStatePoolAlloc, NULL, NULL, LuaStatePoolClean);
+ if (luajit_states == NULL) {
+ SCLogError(SC_ERR_LUAJIT_ERROR, "luastate pool init failed, luajit keywords won't work");
+ retval = -1;
+ }
+ }
+
+ pthread_mutex_unlock(&luajit_states_lock);
+ return retval;
+}
+
+static lua_State *DetectLuajitGetState(void) {
+
+ lua_State *s = NULL;
+ pthread_mutex_lock(&luajit_states_lock);
+ if (luajit_states != NULL)
+ s = (lua_State *)PoolGet(luajit_states);
+ pthread_mutex_unlock(&luajit_states_lock);
+ return s;
+}
+
+static void DetectLuajitReturnState(lua_State *s) {
+ pthread_mutex_lock(&luajit_states_lock);
+ PoolReturn(luajit_states, (void *)s);
+ pthread_mutex_unlock(&luajit_states_lock);
+}
/** \brief dump stack from lua state to screen */
void LuaDumpStack(lua_State *state) {
t->alproto = luajit->alproto;
t->flags = luajit->flags;
- t->luastate = luaL_newstate();
-
+ t->luastate = DetectLuajitGetState();
if (t->luastate == NULL) {
- SCLogError(SC_ERR_LUAJIT_ERROR, "couldn't set up luastate");
+ SCLogError(SC_ERR_LUAJIT_ERROR, "luastate pool depleted");
goto error;
}
return (void *)t;
error:
- if (t->luastate)
- lua_close(t->luastate);
+ if (t->luastate != NULL)
+ DetectLuajitReturnState(t->luastate);
SCFree(t);
return NULL;
}
static void DetectLuajitThreadFree(void *ctx) {
if (ctx != NULL) {
DetectLuajitThreadData *t = (DetectLuajitThreadData *)ctx;
- lua_close(t->luastate);
+ if (t->luastate != NULL)
+ DetectLuajitReturnState(t->luastate);
SCFree(t);
}
}
else
SigMatchAppendSMToList(s, sm, DETECT_SM_LIST_AMATCH);
}
+
+ de_ctx->detect_luajit_instances++;
return 0;
error: