1 /* 2 Logic for a better replacement of PyGILState_Ensure(). 3 4 This version is ready to handle the case of a non-Python-started 5 thread in which we do a large number of calls to CFFI callbacks. If 6 we were to rely on PyGILState_Ensure() for that, we would constantly 7 be creating and destroying PyThreadStates---it is slow, and 8 PyThreadState_Delete() will actually walk the list of all thread 9 states, making it O(n). :-( 10 11 This version only creates one PyThreadState object the first time we 12 see a given thread, and keep it alive until the thread is really 13 shut down, using a destructor on the tls key. 14 */ 15 16 #include <pthread.h> 17 #include "misc_thread_common.h" 18 19 20 static pthread_key_t cffi_tls_key; 21 init_cffi_tls(void)22static void init_cffi_tls(void) 23 { 24 if (pthread_key_create(&cffi_tls_key, &cffi_thread_shutdown) != 0) 25 PyErr_SetString(PyExc_OSError, "pthread_key_create() failed"); 26 } 27 _make_cffi_tls(void)28static struct cffi_tls_s *_make_cffi_tls(void) 29 { 30 void *p = calloc(1, sizeof(struct cffi_tls_s)); 31 if (p == NULL) 32 return NULL; 33 if (pthread_setspecific(cffi_tls_key, p) != 0) { 34 free(p); 35 return NULL; 36 } 37 return p; 38 } 39 get_cffi_tls(void)40static struct cffi_tls_s *get_cffi_tls(void) 41 { 42 void *p = pthread_getspecific(cffi_tls_key); 43 if (p == NULL) 44 p = _make_cffi_tls(); 45 return (struct cffi_tls_s *)p; 46 } 47 48 #define save_errno save_errno_only 49 #define restore_errno restore_errno_only 50