From c79d43273769d88f7129a3d53c80b85a6dc1946c Mon Sep 17 00:00:00 2001 From: Vasilii Chernov Date: Thu, 3 Mar 2016 15:38:32 +0100 Subject: 1. Pcipywrap: add persistent locking wrappings 2. html-server: - add scripts tab - change tab view to jQuery tabs --- pywrap/CMakeLists.txt | 1 + pywrap/pcilib.py | 2 ++ pywrap/pcipywrap.c | 43 +++++++++++++++++++++++++++++++++++++------ pywrap/pcipywrap.h | 4 +++- pywrap/pcipywrap.i | 3 +++ 5 files changed, 46 insertions(+), 7 deletions(-) (limited to 'pywrap') diff --git a/pywrap/CMakeLists.txt b/pywrap/CMakeLists.txt index 033298e..933d2ff 100644 --- a/pywrap/CMakeLists.txt +++ b/pywrap/CMakeLists.txt @@ -23,4 +23,5 @@ install(FILES ${CMAKE_CURRENT_BINARY_DIR}/pcilib.py DESTINATION ${PYTHON_INSTALL if (NOT CMAKE_SOURCE_DIR STREQUAL CMAKE_BINARY_DIR) file(COPY ${CMAKE_CURRENT_SOURCE_DIR}/test_pcilib.py DESTINATION ${CMAKE_CURRENT_BINARY_DIR}) + configure_file(pcilib.py pcilib.py) endif(NOT CMAKE_SOURCE_DIR STREQUAL CMAKE_BINARY_DIR) diff --git a/pywrap/pcilib.py b/pywrap/pcilib.py index f4976bf..a72c79b 100644 --- a/pywrap/pcilib.py +++ b/pywrap/pcilib.py @@ -28,6 +28,8 @@ class pcilib(pcipywrap): curr_script['name'] = script if 'description' in dir(s.__scipts[script]): curr_script['description'] = s.__scipts[script].description + if 'run' in dir(s.__scipts[script]): + curr_script['valid'] = True scripts.append(curr_script) return scripts diff --git a/pywrap/pcipywrap.c b/pywrap/pcipywrap.c index cb99ce2..7431604 100644 --- a/pywrap/pcipywrap.c +++ b/pywrap/pcipywrap.c @@ -552,10 +552,10 @@ void pcipywrap_unlock_global(pcipywrap *self) return; } -PyObject* pcipywrap_lock(pcipywrap *self, const char *lock_id) +PyObject* lock(pcipywrap *self, const char *lock_id, pcilib_lock_flags_t flags) { pcilib_lock_t* lock = pcilib_get_lock(self->ctx, - PCILIB_LOCK_FLAG_PERSISTENT, + flags, lock_id); if(!lock) { @@ -574,10 +574,21 @@ PyObject* pcipywrap_lock(pcipywrap *self, const char *lock_id) return PyLong_FromLong((long)1); } -PyObject* pcipywrap_try_lock(pcipywrap *self, const char *lock_id) +PyObject* pcipywrap_lock(pcipywrap *self, const char *lock_id) +{ + return lock(self, lock_id, PCILIB_LOCK_FLAGS_DEFAULT); +} + +PyObject* pcipywrap_lock_persistent(pcipywrap *self, const char *lock_id) +{ + return lock(self, lock_id, PCILIB_LOCK_FLAG_PERSISTENT); +} + + +PyObject* try_lock(pcipywrap *self, const char *lock_id, pcilib_lock_flags_t flags) { pcilib_lock_t* lock = pcilib_get_lock(self->ctx, - PCILIB_LOCK_FLAG_PERSISTENT, + flags, lock_id); if(!lock) { @@ -595,10 +606,20 @@ PyObject* pcipywrap_try_lock(pcipywrap *self, const char *lock_id) return PyLong_FromLong((long)1); } -PyObject* pcipywrap_unlock(pcipywrap *self, const char *lock_id) +PyObject* pcipywrap_try_lock(pcipywrap *self, const char *lock_id) +{ + return try_lock(self, lock_id, PCILIB_LOCK_FLAGS_DEFAULT); +} + +PyObject* pcipywrap_try_lock_persistent(pcipywrap *self, const char *lock_id) +{ + return try_lock(self, lock_id, PCILIB_LOCK_FLAG_PERSISTENT); +} + +PyObject* unlock(pcipywrap *self, const char *lock_id, pcilib_lock_flags_t flags) { pcilib_lock_t* lock = pcilib_get_lock(self->ctx, - PCILIB_LOCK_FLAG_PERSISTENT, + flags, lock_id); if(!lock) { @@ -610,4 +631,14 @@ PyObject* pcipywrap_unlock(pcipywrap *self, const char *lock_id) return PyLong_FromLong((long)1); } +PyObject* pcipywrap_unlock(pcipywrap *self, const char *lock_id) +{ + return unlock(self, lock_id, PCILIB_LOCK_FLAGS_DEFAULT); +} + +PyObject* pcipywrap_unlock_persistent(pcipywrap *self, const char *lock_id) +{ + return unlock(self, lock_id, PCILIB_LOCK_FLAG_PERSISTENT); +} + diff --git a/pywrap/pcipywrap.h b/pywrap/pcipywrap.h index 1b71a56..1992e07 100644 --- a/pywrap/pcipywrap.h +++ b/pywrap/pcipywrap.h @@ -79,8 +79,10 @@ void pcipywrap_unlock_global(pcipywrap *self); * \return 1, serialized to PyObject or NULL with exeption text, if failed. */ PyObject* pcipywrap_lock(pcipywrap *self, const char *lock_id); - +PyObject* pcipywrap_lock_persistent(pcipywrap *self, const char *lock_id); PyObject* pcipywrap_try_lock(pcipywrap *self, const char *lock_id); +PyObject* pcipywrap_try_lock_persistent(pcipywrap *self, const char *lock_id); PyObject* pcipywrap_unlock(pcipywrap *self, const char *lock_id); +PyObject* pcipywrap_unlock_persistent(pcipywrap *self, const char *lock_id); #endif /* PCIPYWRAP_H */ diff --git a/pywrap/pcipywrap.i b/pywrap/pcipywrap.i index 5ee1bd1..b8f5bdb 100644 --- a/pywrap/pcipywrap.i +++ b/pywrap/pcipywrap.i @@ -27,7 +27,10 @@ typedef struct { void unlock_global(); PyObject* lock(const char *lock_id); + PyObject* lock_persistent(const char *lock_id); PyObject* try_lock(const char *lock_id); + PyObject* try_lock_persistent(const char *lock_id); PyObject* unlock(const char *lock_id); + PyObject* unlock_persistent(const char *lock_id); } } pcipywrap; -- cgit v1.2.3 From 4b4dc3c70ef19a29386c2b3e8284687851094eb9 Mon Sep 17 00:00:00 2001 From: Vasilii Chernov Date: Fri, 4 Mar 2016 09:31:42 +0100 Subject: Fix python3 initialization from pcilib_t --- apps/test_multithread.c | 2 + pcilib/py.c | 150 ++++++++++++++++++++++++++++++++++++++++++------ pywrap/test_pcilib.py | 2 +- 3 files changed, 135 insertions(+), 19 deletions(-) (limited to 'pywrap') diff --git a/apps/test_multithread.c b/apps/test_multithread.c index f6afae7..a041655 100644 --- a/apps/test_multithread.c +++ b/apps/test_multithread.c @@ -9,6 +9,7 @@ const char* prop = "/registers/fpga/reg1"; char* reg; int stop = 0; +/* void *get_prop(void *arg) { pcilib_t *ctx = (pcilib_t*)arg; @@ -34,6 +35,7 @@ void *get_prop(void *arg) } return NULL; } +*/ void *read_reg(void *arg) { diff --git a/pcilib/py.c b/pcilib/py.c index bec7d08..94d7ed8 100644 --- a/pcilib/py.c +++ b/pcilib/py.c @@ -2,6 +2,11 @@ #ifdef HAVE_PYTHON # include + +#if PY_MAJOR_VERSION >= 3 +#include +#endif /* PY_MAJOR_VERSION >= 3 */ + #endif /* HAVE_PYTHON */ #include @@ -27,12 +32,24 @@ struct pcilib_script_s { UT_hash_handle hh; /**< hash */ }; +#if PY_MAJOR_VERSION >= 3 +typedef struct pcilib_py_s_thread_control { + pthread_t pth; + pthread_cond_t cond_finished; + pthread_mutex_t cond_finished_lock; +} pcilib_py_s_thread_control; +#endif /* PY_MAJOR_VERSION < 3 */ + struct pcilib_py_s { int finalyze; /**< Indicates, that we are initialized from wrapper and should not destroy Python resources in destructor */ PyObject *main_module; /**< Main interpreter */ PyObject *global_dict; /**< Dictionary of main interpreter */ PyObject *pcilib_pywrap; /**< pcilib wrapper module */ pcilib_script_t *script_hash; /**< Hash with loaded scripts */ + +#if PY_MAJOR_VERSION >= 3 + pcilib_py_s_thread_control *thr_ctl; /**< Controller for Python main loop thread for Python 3 */ +#endif /* PY_MAJOR_VERSION < 3 */ }; #endif /* HAVE_PYTHON */ @@ -55,7 +72,7 @@ void pcilib_log_python_error(const char *file, int line, pcilib_log_flags_t flag PyErr_NormalizeException(&pytype, &pyval, &pytraceback); if (pyval) pystr = PyObject_Str(pyval); -# if PY_MAJOR_VERSION >= 3 +#if PY_MAJOR_VERSION >= 3 if (pytype) { if (PyUnicode_Check(pytype)) type = PyUnicode_AsUTF8(pytype); @@ -65,7 +82,7 @@ void pcilib_log_python_error(const char *file, int line, pcilib_log_flags_t flag if (pystr) { val = PyUnicode_AsUTF8(pystr); } -# else /* PY_MAJOR_VERSION >= 3 */ +#else /* PY_MAJOR_VERSION >= 3 */ if (pytype) { if (PyString_Check(pytype)) type = PyString_AsString(pytype); @@ -75,7 +92,7 @@ void pcilib_log_python_error(const char *file, int line, pcilib_log_flags_t flag if (pystr) { val = PyString_AsString(pystr); } -# endif /*PY_MAJOR_VERSION >= 3*/ +#endif /*PY_MAJOR_VERSION >= 3*/ } PyGILState_Release(gstate); #endif /* HAVE_PYTHON */ @@ -115,39 +132,80 @@ void pcilib_log_python_error(const char *file, int line, pcilib_log_flags_t flag #endif /* HAVE_PYTHON */ } - +#ifdef HAVE_PYTHON +#if PY_MAJOR_VERSION >= 3 +void *pcilib_py_run_side_thread(void *arg) { + pcilib_t *ctx = (pcilib_t*)(arg); + //Initializing python + Py_Initialize(); + PyEval_InitThreads(); + PyEval_ReleaseLock(); + + //send initialization finish signal + pthread_cond_signal(&(ctx->py->thr_ctl->cond_finished)); + pthread_mutex_unlock(&(ctx->py->thr_ctl->cond_finished_lock)); + pthread_mutex_destroy(&(ctx->py->thr_ctl->cond_finished_lock)); + + //wait untill finish signal + pthread_mutex_lock(&(ctx->py->thr_ctl->cond_finished_lock)); + pthread_cond_wait(&(ctx->py->thr_ctl->cond_finished), + &(ctx->py->thr_ctl->cond_finished_lock)); + return NULL; +} +#endif /* PY_MAJOR_VERSION < 3 */ +#endif /* HAVE_PYTHON */ int pcilib_init_py(pcilib_t *ctx) { #ifdef HAVE_PYTHON ctx->py = (pcilib_py_t*)malloc(sizeof(pcilib_py_t)); if (!ctx->py) return PCILIB_ERROR_MEMORY; - memset(ctx->py, 0, sizeof(pcilib_py_t)); if(!Py_IsInitialized()) { - Py_Initialize(); - - // Since python is being initializing from c programm, it needs to initialize threads to work properly with c threads - PyEval_InitThreads(); - PyEval_ReleaseLock(); - ctx->py->finalyze = 1; - } - +#if PY_MAJOR_VERSION >= 3 + //create thread controller + ctx->py->thr_ctl = malloc(sizeof(pcilib_py_s_thread_control)); + if(!ctx->py->thr_ctl) return PCILIB_ERROR_MEMORY; + memset(ctx->py->thr_ctl, 0, sizeof(pcilib_py_s_thread_control)); + + //create side thread with python main loop + pthread_create(&(ctx->py->thr_ctl->pth), NULL, pcilib_py_run_side_thread, ctx); + pthread_mutex_lock(&(ctx->py->thr_ctl->cond_finished_lock)); + + //wait until Python initializes + pthread_cond_wait(&(ctx->py->thr_ctl->cond_finished), + &(ctx->py->thr_ctl->cond_finished_lock)); + +#else /* PY_MAJOR_VERSION < 3 */ + Py_Initialize(); + // Since python is being initializing from c programm, it needs to initialize threads to work properly with c threads + PyEval_InitThreads(); + PyEval_ReleaseLock(); +#endif /* PY_MAJOR_VERSION < 3 */ + ctx->py->finalyze = 1; + } + + + PyGILState_STATE gstate = PyGILState_Ensure(); + ctx->py->main_module = PyImport_AddModule("__parser__"); if (!ctx->py->main_module) { pcilib_python_warning("Error importing python parser"); + PyGILState_Release(gstate); return PCILIB_ERROR_FAILED; } ctx->py->global_dict = PyModule_GetDict(ctx->py->main_module); if (!ctx->py->global_dict) { pcilib_python_warning("Error locating global python dictionary"); + PyGILState_Release(gstate); return PCILIB_ERROR_FAILED; } PyObject *pywrap = PyImport_ImportModule(PCILIB_PYTHON_WRAPPER); if (!pywrap) { pcilib_python_warning("Error importing pcilib python wrapper"); + PyGILState_Release(gstate); return PCILIB_ERROR_FAILED; } @@ -159,8 +217,11 @@ int pcilib_init_py(pcilib_t *ctx) { if (!ctx->py->pcilib_pywrap) { pcilib_python_warning("Error initializing python wrapper"); + PyGILState_Release(gstate); return PCILIB_ERROR_FAILED; } + + PyGILState_Release(gstate); #endif /* HAVE_PYTHON */ return 0; @@ -187,20 +248,24 @@ int pcilib_py_add_script_dir(pcilib_t *ctx, const char *dir) { if (!script_dir) return PCILIB_ERROR_MEMORY; sprintf(script_dir, "%s/%s", model_dir, dir); } + + PyGILState_STATE gstate = PyGILState_Ensure(); pypath = PySys_GetObject("path"); if (!pypath) { pcilib_python_warning("Can't get python path"); + PyGILState_Release(gstate); return PCILIB_ERROR_FAILED; } pynewdir = PyUnicode_FromString(script_dir); if (!pynewdir) { pcilib_python_warning("Can't create python string"); + PyGILState_Release(gstate); return PCILIB_ERROR_MEMORY; } - // Checking if the directory already in the path? + // Checking if the directory already in the path? pydict = PyDict_New(); if (pydict) { pystr = PyUnicode_FromString("cur"); @@ -227,8 +292,11 @@ int pcilib_py_add_script_dir(pcilib_t *ctx, const char *dir) { if (err) { pcilib_python_warning("Can't add directory (%s) to python path", script_dir); + PyGILState_Release(gstate); return err; } + + PyGILState_Release(gstate); #endif /* HAVE_PYTHON */ return 0; @@ -237,7 +305,12 @@ int pcilib_py_add_script_dir(pcilib_t *ctx, const char *dir) { void pcilib_free_py(pcilib_t *ctx) { #ifdef HAVE_PYTHON int finalyze = 0; - + PyGILState_STATE gstate; + +#if PY_MAJOR_VERSION >= 3 + pcilib_py_s_thread_control *thr_ctl = ctx->py->thr_ctl; +#endif /* PY_MAJOR_VERSION < 3 */ + if (ctx->py) { if (ctx->py->finalyze) finalyze = 1; @@ -252,15 +325,44 @@ void pcilib_free_py(pcilib_t *ctx) { ctx->py->script_hash = NULL; } - if (ctx->py->pcilib_pywrap) + if (ctx->py->pcilib_pywrap) { + gstate = PyGILState_Ensure(); Py_DECREF(ctx->py->pcilib_pywrap); + PyGILState_Release(gstate); + } + free(ctx->py); ctx->py = NULL; } - if (finalyze) - Py_Finalize(); + + if (finalyze) { +#if PY_MAJOR_VERSION >= 3 + + //stop python side thread + pthread_cond_signal(&(thr_ctl->cond_finished)); + pthread_mutex_unlock(&(thr_ctl->cond_finished_lock)); + pthread_join(thr_ctl->pth, NULL); + + //free python + //must be finalized in main thread to correctly stop python threading + PyGILState_Ensure(); + Py_Finalize(); + + //destroy thread controllers + pthread_mutex_destroy(&(thr_ctl->cond_finished_lock)); + pthread_cond_destroy(&(thr_ctl->cond_finished)); + free(thr_ctl); + +#else /* PY_MAJOR_VERSION < 3 */ + + Py_Finalize(); + +#endif /* PY_MAJOR_VERSION < 3 */ + } + + #endif /* HAVE_PYTHON */ } @@ -268,6 +370,7 @@ int pcilib_py_load_script(pcilib_t *ctx, const char *script_name) { #ifdef HAVE_PYTHON PyObject* pymodule; pcilib_script_t *module = NULL; + PyGILState_STATE gstate; if (!ctx->py) return 0; @@ -284,11 +387,16 @@ int pcilib_py_load_script(pcilib_t *ctx, const char *script_name) { HASH_FIND_STR(ctx->py->script_hash, script_name, module); if (module) return 0; + gstate = PyGILState_Ensure(); + pymodule = PyImport_ImportModule(module_name); if (!pymodule) { pcilib_python_error("Error importing script (%s)", script_name); + PyGILState_Release(gstate); return PCILIB_ERROR_FAILED; } + + PyGILState_Release(gstate); module = (pcilib_script_t*)malloc(sizeof(pcilib_script_t)); if (!module) return PCILIB_ERROR_MEMORY; @@ -307,6 +415,7 @@ int pcilib_py_get_transform_script_properties(pcilib_t *ctx, const char *script_ PyObject *dict; PyObject *pystr; pcilib_script_t *module; + PyGILState_STATE gstate; if (!ctx->py) { if (mode_ret) *mode_ret = mode; @@ -319,10 +428,13 @@ int pcilib_py_get_transform_script_properties(pcilib_t *ctx, const char *script_ pcilib_error("Script (%s) is not loaded yet", script_name); return PCILIB_ERROR_NOTFOUND; } + + gstate = PyGILState_Ensure(); dict = PyModule_GetDict(module->module); if (!dict) { pcilib_python_error("Error getting dictionary for script (%s)", script_name); + PyGILState_Release(gstate); return PCILIB_ERROR_FAILED; } @@ -337,6 +449,8 @@ int pcilib_py_get_transform_script_properties(pcilib_t *ctx, const char *script_ if (PyDict_Contains(dict, pystr)) mode |= PCILIB_ACCESS_W; Py_DECREF(pystr); } + + PyGILState_Release(gstate); #endif /* HAVE_PYTHON */ if (mode_ret) *mode_ret = mode; diff --git a/pywrap/test_pcilib.py b/pywrap/test_pcilib.py index 398d975..74eee4a 100644 --- a/pywrap/test_pcilib.py +++ b/pywrap/test_pcilib.py @@ -82,7 +82,7 @@ class test_pcilib(): def testMemoryLeak(self): try: while(1): - val = long(random.randint(0, 8096)) + val = random.randint(0, 8096) self.pcilib = pcilib.pcilib(self.device, self.model) print(self.pcilib.get_property_list(self.branch)) print(self.pcilib.get_register_info(self.register)) -- cgit v1.2.3