aboutsummaryrefslogtreecommitdiffstats
path: root/framework/src/suricata/src/util-cuda-handlers.c
diff options
context:
space:
mode:
authorAshlee Young <ashlee@onosfw.com>2015-09-09 22:21:41 -0700
committerAshlee Young <ashlee@onosfw.com>2015-09-09 22:21:41 -0700
commit8879b125d26e8db1a5633de5a9c692eb2d1c4f83 (patch)
treec7259d85a991b83dfa85ab2e339360669fc1f58e /framework/src/suricata/src/util-cuda-handlers.c
parent13d05bc8458758ee39cb829098241e89616717ee (diff)
suricata checkin based on commit id a4bce14770beee46a537eda3c3f6e8e8565d5d0a
Change-Id: I9a214fa0ee95e58fc640e50bd604dac7f42db48f
Diffstat (limited to 'framework/src/suricata/src/util-cuda-handlers.c')
-rw-r--r--framework/src/suricata/src/util-cuda-handlers.c363
1 files changed, 363 insertions, 0 deletions
diff --git a/framework/src/suricata/src/util-cuda-handlers.c b/framework/src/suricata/src/util-cuda-handlers.c
new file mode 100644
index 00000000..a6cbeec9
--- /dev/null
+++ b/framework/src/suricata/src/util-cuda-handlers.c
@@ -0,0 +1,363 @@
+/* Copyright (C) 2007-2013 Open Information Security Foundation
+ *
+ * You can copy, redistribute or modify this Program under the terms of
+ * the GNU General Public License version 2 as published by the Free
+ * Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * version 2 along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+/**
+ * \file
+ *
+ * \author Anoop Saldanha <anoopsaldanha@gmail.com>
+ */
+
+/* compile in, only if we have a CUDA enabled device on the machine, with the
+ * toolkit and the driver installed */
+#ifdef __SC_CUDA_SUPPORT__
+
+#include "suricata-common.h"
+
+#include "util-error.h"
+#include "util-debug.h"
+#include "conf.h"
+#include "util-cuda.h"
+#include "util-cuda-handlers.h"
+
+/* file only exists if cuda is enabled */
+#include "cuda-ptxdump.h"
+
+/************************conf file profile section**********************/
+
+typedef struct CudaHandlerConfProfile_ {
+ char *name;
+ void *ctx;
+ void (*Free)(void *);
+
+ struct CudaHandlerConfProfile_ *next;
+} CudaHandlerConfProfile;
+
+static CudaHandlerConfProfile *conf_profiles = NULL;
+/* protects above var */
+static SCMutex mutex = SCMUTEX_INITIALIZER;
+
+void CudaHandlerAddCudaProfileFromConf(const char *name,
+ void *(*Callback)(ConfNode *node),
+ void (*Free)(void *))
+{
+ /* we don't do data validation */
+ SCMutexLock(&mutex);
+
+ CudaHandlerConfProfile *tmp_cp = conf_profiles;
+ while (tmp_cp != NULL && strcasecmp(name, tmp_cp->name) != 0)
+ tmp_cp = tmp_cp->next;
+
+ if (tmp_cp != NULL) {
+ SCLogError(SC_ERR_INVALID_ARGUMENT, "We already have a cuda conf "
+ "profile by the name \"%s\" registered.", name);
+ exit(EXIT_FAILURE);
+ }
+
+ char tmp[200];
+ int r = snprintf(tmp, sizeof(tmp), "%s%s", "cuda.", name);
+ if (r < 0) {
+ SCLogError(SC_ERR_FATAL, "snprintf failure.");
+ exit(EXIT_FAILURE);
+ } else if (r > (int)sizeof(tmp)) {
+ SCLogError(SC_ERR_FATAL, "buffer not big enough to write param.");
+ exit(EXIT_FAILURE);
+ }
+ void *ctx = Callback(ConfGetNode(tmp));
+ if (ctx == NULL) {
+ SCMutexUnlock(&mutex);
+ return;
+ }
+
+ CudaHandlerConfProfile *new_cp = SCMalloc(sizeof(CudaHandlerConfProfile));
+ if (unlikely(new_cp == NULL))
+ exit(EXIT_FAILURE);
+ memset(new_cp, 0, sizeof(CudaHandlerConfProfile));
+ new_cp->name = SCStrdup(name);
+ if (new_cp->name == NULL)
+ exit(EXIT_FAILURE);
+ new_cp->ctx = ctx;
+ new_cp->Free = Free;
+
+ if (conf_profiles == NULL) {
+ conf_profiles = new_cp;
+ } else {
+ new_cp->next = conf_profiles;
+ conf_profiles = new_cp;
+ }
+
+ SCMutexUnlock(&mutex);
+ return;
+}
+
+void *CudaHandlerGetCudaProfile(const char *name)
+{
+ SCMutexLock(&mutex);
+
+ CudaHandlerConfProfile *tmp_cp = conf_profiles;
+ while (tmp_cp != NULL && strcasecmp(name, tmp_cp->name) != 0)
+ tmp_cp = tmp_cp->next;
+
+ if (tmp_cp == NULL) {
+ SCMutexUnlock(&mutex);
+ return NULL;
+ }
+
+ SCMutexUnlock(&mutex);
+ return tmp_cp->ctx;
+}
+
+void CudaHandlerFreeProfiles(void)
+{
+ SCMutexLock(&mutex);
+
+ CudaHandlerConfProfile *tmp = conf_profiles;
+ while (tmp != NULL) {
+ CudaHandlerConfProfile *curr = tmp;
+ tmp = tmp->next;
+ SCFree(curr->name);
+ if (curr->Free != NULL)
+ curr->Free(curr->ctx);
+ SCFree(curr);
+ }
+
+ SCMutexUnlock(&mutex);
+ return;
+}
+
+/*******************cuda context related data section*******************/
+
+/* we use a concept where every device on the gpu has only 1 context. If
+ * a section in the engine wants to use a device and tries to open a context
+ * on it, we first check if a context is already created for the device and if
+ * so we return it. If not we create a new one and update with the entry */
+
+static CUcontext *cuda_contexts = NULL;
+static int no_of_cuda_contexts = 0;
+
+typedef struct CudaHandlerModuleData_ {
+ char *name;
+ void *data;
+
+ struct CudaHandlerModuleData_ *next;
+} CudaHandlerModuleData;
+
+typedef struct CudaHandlerModule_ {
+ char *name;
+
+ /* the context used by this module */
+ CUcontext context;
+ /* the device on which the above context was created */
+ int device_id;
+ CudaHandlerModuleData *module_data;
+
+ struct CudaHandlerModule_ *next;
+} CudaHandlerModule;
+
+static CudaHandlerModule *cudahl_modules = NULL;
+
+CUcontext CudaHandlerModuleGetContext(const char *name, int device_id)
+{
+ void *ptmp;
+ SCMutexLock(&mutex);
+
+ CudaHandlerModule *module = cudahl_modules;
+ while (module != NULL && strcasecmp(module->name, name) != 0)
+ module = module->next;
+ if (module != NULL) {
+ if (module->device_id != device_id) {
+ SCLogError(SC_ERR_CUDA_HANDLER_ERROR, "Module already "
+ "registered, but the new device_id is different "
+ "from the already registered device_id.");
+ exit(EXIT_FAILURE);
+ }
+ SCMutexUnlock(&mutex);
+ return module->context;
+ }
+
+ CudaHandlerModule *new_module = SCMalloc(sizeof(CudaHandlerModule));
+ if (unlikely(new_module == NULL))
+ exit(EXIT_FAILURE);
+ memset(new_module, 0, sizeof(CudaHandlerModule));
+ new_module->device_id = device_id;
+ new_module->name = SCStrdup(name);
+ if (new_module->name == NULL)
+ exit(EXIT_FAILURE);
+ if (cudahl_modules == NULL) {
+ cudahl_modules = new_module;
+ } else {
+ new_module->next = cudahl_modules;
+ cudahl_modules = new_module;
+ }
+
+ if (no_of_cuda_contexts <= device_id) {
+ ptmp = SCRealloc(cuda_contexts, sizeof(CUcontext) * (device_id + 1));
+ if (unlikely(ptmp == NULL)) {
+ SCFree(cuda_contexts);
+ cuda_contexts = NULL;
+ exit(EXIT_FAILURE);
+ }
+ cuda_contexts = ptmp;
+
+ memset(cuda_contexts + no_of_cuda_contexts, 0,
+ sizeof(CUcontext) * ((device_id + 1) - no_of_cuda_contexts));
+ no_of_cuda_contexts = device_id + 1;
+ }
+
+ if (cuda_contexts[device_id] == 0) {
+ SCCudaDevices *devices = SCCudaGetDeviceList();
+ if (SCCudaCtxCreate(&cuda_contexts[device_id], CU_CTX_SCHED_BLOCKING_SYNC,
+ devices->devices[device_id]->device) == -1) {
+ SCLogDebug("ctxcreate failure.");
+ exit(EXIT_FAILURE);
+ }
+ }
+ new_module->context = cuda_contexts[device_id];
+
+ SCMutexUnlock(&mutex);
+ return cuda_contexts[device_id];
+}
+
+void CudaHandlerModuleStoreData(const char *module_name,
+ const char *data_name, void *data_ptr)
+{
+ SCMutexLock(&mutex);
+
+ CudaHandlerModule *module = cudahl_modules;
+ while (module != NULL && strcasecmp(module->name, module_name) != 0)
+ module = module->next;
+ if (module == NULL) {
+ SCLogError(SC_ERR_CUDA_HANDLER_ERROR, "Trying to retrieve data "
+ "\"%s\" from module \"%s\" that hasn't been registered "
+ "yet.", module_name, data_name);
+ exit(EXIT_FAILURE);
+ }
+
+ CudaHandlerModuleData *data = module->module_data;
+ while (data != NULL && (strcasecmp(data_name, data->name) != 0)) {
+ data = data->next;
+ }
+ if (data != NULL) {
+ SCLogWarning(SC_ERR_CUDA_HANDLER_ERROR, "Data \"%s\" already "
+ "registered for this module \"%s\".", data_name,
+ module_name);
+ SCMutexUnlock(&mutex);
+ goto end;
+ }
+
+ CudaHandlerModuleData *new_data = SCMalloc(sizeof(CudaHandlerModuleData));
+ if (unlikely(new_data == NULL))
+ exit(EXIT_FAILURE);
+ memset(new_data, 0, sizeof(CudaHandlerModuleData));
+ new_data->name = SCStrdup(data_name);
+ if (new_data->name == NULL)
+ exit(EXIT_FAILURE);
+ new_data->data = data_ptr;
+
+ if (module->module_data == NULL) {
+ module->module_data = new_data;
+ } else {
+ new_data->next = module->module_data;
+ module->module_data = new_data;
+ }
+
+ SCMutexUnlock(&mutex);
+
+ end:
+ return;
+}
+
+void *CudaHandlerModuleGetData(const char *module_name, const char *data_name)
+{
+ SCMutexLock(&mutex);
+
+ CudaHandlerModule *module = cudahl_modules;
+ while (module != NULL && strcasecmp(module->name, module_name) != 0)
+ module = module->next;
+ if (module == NULL) {
+ SCLogError(SC_ERR_CUDA_HANDLER_ERROR, "Trying to retrieve data "
+ "\"%s\" from module \"%s\" that hasn't been registered "
+ "yet.", module_name, data_name);
+ SCMutexUnlock(&mutex);
+ return NULL;
+ }
+
+ CudaHandlerModuleData *data = module->module_data;
+ while (data != NULL && (strcasecmp(data_name, data->name) != 0)) {
+ data = data->next;
+ }
+ if (data == NULL) {
+ SCLogInfo("Data \"%s\" already registered for this module \"%s\". "
+ "Returning it.", data_name, module_name);
+ SCMutexUnlock(&mutex);
+ return NULL;
+ }
+
+ SCMutexUnlock(&mutex);
+ return data->data;
+}
+
+int CudaHandlerGetCudaModule(CUmodule *p_module, const char *ptx_image)
+{
+#define CUDA_HANDLER_GET_CUDA_MODULE_BUFFER_EXTRA_SPACE 15
+
+ int i = 0;
+
+ /* select the ptx image based on the compute capability supported by all
+ * devices (i.e. the lowest) */
+ char *image = SCMalloc(strlen(ptx_image) + CUDA_HANDLER_GET_CUDA_MODULE_BUFFER_EXTRA_SPACE);
+ if (unlikely(image == NULL)) {
+ exit(EXIT_FAILURE);
+ }
+ memset(image, 0x00, strlen(ptx_image) + CUDA_HANDLER_GET_CUDA_MODULE_BUFFER_EXTRA_SPACE);
+
+ int major = INT_MAX;
+ int minor = INT_MAX;
+ SCCudaDevices *devices = SCCudaGetDeviceList();
+ for (i = 0; i < devices->count; i++){
+ if (devices->devices[i]->major_rev < major){
+ major = devices->devices[i]->major_rev;
+ minor = devices->devices[i]->minor_rev;
+ }
+ if (devices->devices[i]->major_rev == major &&
+ devices->devices[i]->minor_rev < minor){
+ minor = devices->devices[i]->minor_rev;
+ }
+ }
+ snprintf(image,
+ strlen(ptx_image) + CUDA_HANDLER_GET_CUDA_MODULE_BUFFER_EXTRA_SPACE,
+ "%s_sm_%u%u",
+ ptx_image, major, minor);
+
+ /* we don't have a cuda module associated with this module. Create a
+ * cuda module, update the module with this cuda module reference and
+ * then return the module refernce back to the calling function using
+ * the argument */
+ SCLogDebug("Loading kernel module: %s\n",image);
+ if (SCCudaModuleLoadData(p_module, (void *)SCCudaPtxDumpGetModule(image)) == -1)
+ goto error;
+ SCFree(image);
+
+ return 0;
+ error:
+ SCFree(image);
+ return -1;
+
+#undef CUDA_HANDLER_GET_CUDA_MODULE_BUFFER_EXTRA_SPACE
+}
+
+
+#endif /* __SC_CUDA_SUPPORT__ */