diff options
-rw-r--r-- | cffi/_embedding.h | 26 | ||||
-rw-r--r-- | demo/embedding.py | 2 |
2 files changed, 20 insertions, 8 deletions
diff --git a/cffi/_embedding.h b/cffi/_embedding.h index c6acd70..5e7cddc 100644 --- a/cffi/_embedding.h +++ b/cffi/_embedding.h @@ -147,6 +147,10 @@ static int _cffi_initialize_python(void) if (pycode == NULL) goto error; global_dict = PyModule_GetDict(m); + if (PyDict_GetItemString(global_dict, "__builtins__") == NULL && + PyDict_SetItemString(global_dict, "__builtins__", + PyThreadState_GET()->interp->builtins) < 0) + goto error; x = PyEval_EvalCode((PyCodeObject *)pycode, global_dict, global_dict); if (x == NULL) goto error; @@ -205,6 +209,8 @@ static int _cffi_initialize_python(void) goto done; } +PyAPI_DATA(char *) _PyParser_TokenNames[]; /* from CPython */ + static void _cffi_carefully_make_gil(void) { /* This initializes the GIL. It can be called completely @@ -217,21 +223,25 @@ static void _cffi_carefully_make_gil(void) variable must be from 'libpythonX.Y.so', not from this cffi-based extension module, because it must be shared from different cffi-based extension modules. We choose - PyEllipsis_Type.tp_dealloc as a completely arbitrary, - never-used word for this lock. (Yes, I know it's really + _PyParser_TokenNames[0] as a completely arbitrary pointer value + that is never written to. The default is to point to the + string "ENDMARKER". We change it temporarily to point to the + next character in that string. (Yes, I know it's REALLY obscure.) */ #ifdef WITH_THREAD - void *volatile *lock = (void *volatile *)&PyEllipsis_Type.tp_dealloc; + char *volatile *lock = (char *volatile *)_PyParser_TokenNames; + char *old_value; while (1) { /* spin loop */ - void *current = *lock; - if (current == NULL) { - if (compare_and_swap(lock, NULL, (void *)42)) + old_value = *lock; + if (old_value[0] == 'E') { + assert(old_value[1] == 'N'); + if (compare_and_swap(lock, old_value, old_value + 1)) break; } else { - assert(current == (void *)42); + assert(old_value[0] == 'N'); /* should ideally do a spin loop instruction here, but hard to do it portably and doesn't really matter I think: PyEval_InitThreads() should be very fast, and @@ -247,7 +257,7 @@ static void _cffi_carefully_make_gil(void) spinlock dance to make sure that we see it as fully ready */ /* release the lock */ - while (!compare_and_swap(lock, (void *)42, NULL)) + while (!compare_and_swap(lock, old_value + 1, old_value)) ; #endif } diff --git a/demo/embedding.py b/demo/embedding.py index 365238d..1f95b40 100644 --- a/demo/embedding.py +++ b/demo/embedding.py @@ -9,6 +9,8 @@ ffi.cdef(""" ffi.embedding_init_code(""" print "preparing" + intern("foo") + @ffi.def_extern() def add(x, y): print "adding", x, "and", y |