115
125
#endif /* HAVE_PYTHON */
129
# if PY_MAJOR_VERSION >= 3
131
* Python3 specially treats the main thread intializing Python. It crashes if
132
* the Lock is released and any Python code is executed under the GIL compaling
133
* that GIL is not locked. Python3 assumes that the main thread most of the time
134
* holds the Lock, only shortly giving it away to other threads and re-obtaining
135
* it hereafter. This is not possible to do with GILs, but instead (probably)
136
* PyEval_{Save,Restore}Thread() should be used. On other hand, the other threads
137
* are working fine with GILs. This makes things complicated as we need to know
138
* if we are running in main thread or not.
139
* To simplify matters, during initalization we start a new thread which will
140
* performa actual initialization of Python and, hence, act as main thread.
141
* We only intialize here. No python code is executed afterwards. So we don't
142
* need to care about special locking mechanisms in main thread. Instead all
143
* our user threads can use GILs normally.
144
* See more details here:
145
* http://stackoverflow.com/questions/24499393/cpython-locking-the-gil-in-the-main-thread
146
* http://stackoverflow.com/questions/15470367/pyeval-initthreads-in-python-3-how-when-to-call-it-the-saga-continues-ad-naus
148
static void *pcilib_py_run_init_thread(void *arg) {
149
pcilib_py_t *py = (pcilib_py_t*)(arg);
152
PyEval_InitThreads();
153
PyEval_ReleaseLock();
155
// Ensure that main thread waiting for our signal
156
pthread_lock(&(py->lock));
158
// Inform the parent thread that initialization is finished
159
pthread_cond_signal(&(py->cond));
161
// Wait untill cleanup is requested
162
pthread_cond_wait(&(py->cond), &(py->lock));
163
pthread_unlock(&(py->lock)));
169
# endif /* PY_MAJOR_VERSION < 3 */
170
#endif /* HAVE_PYTHON */
120
172
int pcilib_init_py(pcilib_t *ctx) {
121
173
#ifdef HAVE_PYTHON
122
174
ctx->py = (pcilib_py_t*)malloc(sizeof(pcilib_py_t));
123
175
if (!ctx->py) return PCILIB_ERROR_MEMORY;
125
176
memset(ctx->py, 0, sizeof(pcilib_py_t));
127
if(!Py_IsInitialized()) {
178
if (!Py_IsInitialized()) {
179
# if PY_MAJOR_VERSION < 3
130
181
// Since python is being initializing from c programm, it needs to initialize threads to work properly with c threads
131
182
PyEval_InitThreads();
132
183
PyEval_ReleaseLock();
184
# else /* PY_MAJOR_VERSION < 3 */
185
err = pthread_mutex_init(&(ctx->py.lock));
186
if (err) return PCILIB_ERROR_FAILED;
188
err = pthread_cond_init(&(ctx->py.cond));
190
pthread_mutex_destroy(&(ctx->py.lock));
191
return PCILIB_ERROR_FAILED;
194
err = pthread_mutex_lock(&(ctx->py.lock));
196
pthread_cond_destroy(&(ctx->py.lock));
197
pthread_mutex_destroy(&(ctx->py.lock));
198
return PCILIB_ERROR_FAILED;
201
// Create initalizer thread and wait until it releases the Lock
202
err = pthread_create(&(ctx->py.pth), NULL, pcilib_py_run_init_thread, &(ctx->py));
204
pthread_mutex_unlock(&(ctx->py.lock));
205
pthread_cond_destroy(&(ctx->py.cond));
206
pthread_mutex_destroy(&(ctx->py.lock));
207
return PCILIB_ERROR_FAILED;
210
// Wait until initialized and keep the lock afterwards until free executed
211
pthread_cond_wait(&(ctx->py.cond), (ctx->py.lock));
212
# endif /* PY_MAJOR_VERSION < 3 */
133
213
ctx->py->finalyze = 1;
217
PyGILState_STATE gstate = PyGILState_Ensure();
136
219
ctx->py->main_module = PyImport_AddModule("__parser__");
137
220
if (!ctx->py->main_module) {
221
PyGILState_Release(gstate);
138
222
pcilib_python_warning("Error importing python parser");
139
223
return PCILIB_ERROR_FAILED;
142
226
ctx->py->global_dict = PyModule_GetDict(ctx->py->main_module);
143
227
if (!ctx->py->global_dict) {
228
PyGILState_Release(gstate);
144
229
pcilib_python_warning("Error locating global python dictionary");
145
230
return PCILIB_ERROR_FAILED;
148
233
PyObject *pywrap = PyImport_ImportModule(PCILIB_PYTHON_WRAPPER);
235
PyGILState_Release(gstate);
150
236
pcilib_python_warning("Error importing pcilib python wrapper");
151
237
return PCILIB_ERROR_FAILED;
187
276
if (!script_dir) return PCILIB_ERROR_MEMORY;
188
277
sprintf(script_dir, "%s/%s", model_dir, dir);
280
PyGILState_STATE gstate = PyGILState_Ensure();
191
282
pypath = PySys_GetObject("path");
284
PyGILState_Release(gstate);
193
285
pcilib_python_warning("Can't get python path");
194
286
return PCILIB_ERROR_FAILED;
197
289
pynewdir = PyUnicode_FromString(script_dir);
291
PyGILState_Release(gstate);
199
292
pcilib_python_warning("Can't create python string");
200
293
return PCILIB_ERROR_MEMORY;
203
// Checking if the directory already in the path?
296
// Checking if the directory already in the path?
204
297
pydict = PyDict_New();
206
299
pystr = PyUnicode_FromString("cur");
255
354
if (ctx->py->pcilib_pywrap)
256
355
Py_DECREF(ctx->py->pcilib_pywrap);
357
PyGILState_Release(gstate);
366
#if PY_MAJOR_VERSION >= 3
367
// singal python init thread to stop and wait it to finish
368
pthread_cond_signal(&(ctx->py.cond));
369
pthread_mutex_unlock(&(ctx->py.lock));
370
pthread_join(ctx->py.pth, NULL);
372
// destroy synchronization primitives
373
pthread_cond_destroy(&(ctx->py.cond));
374
pthread_mutex_destroy(&(ctx->py.lock));
375
#else /* PY_MAJOR_VERSION < 3 */
377
#endif /* PY_MAJOR_VERSION < 3 */
264
381
#endif /* HAVE_PYTHON */