misc_thread_posix.h 1.4 KB

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