You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

177 lines
4.6 KiB

  1. /* GNU pth threads interface
  2. http://www.gnu.org/software/pth
  3. 2000-05-03 Andy Dustman <andy@dustman.net>
  4. Adapted from Posix threads interface
  5. 12 May 1997 -- david arnold <davida@pobox.com>
  6. */
  7. #include <stdlib.h>
  8. #include <string.h>
  9. #include <pth.h>
  10. /* A pth mutex isn't sufficient to model the Python lock type
  11. * because pth mutexes can be acquired multiple times by the
  12. * same thread.
  13. *
  14. * The pth_lock struct implements a Python lock as a "locked?" bit
  15. * and a <condition, mutex> pair. In general, if the bit can be acquired
  16. * instantly, it is, else the pair is used to block the thread until the
  17. * bit is cleared.
  18. */
  19. typedef struct {
  20. char locked; /* 0=unlocked, 1=locked */
  21. /* a <cond, mutex> pair to handle an acquire of a locked lock */
  22. pth_cond_t lock_released;
  23. pth_mutex_t mut;
  24. } pth_lock;
  25. #define CHECK_STATUS(name) if (status == -1) { printf("%d ", status); perror(name); error = 1; }
  26. pth_attr_t PyThread_attr;
  27. /*
  28. * Initialization.
  29. */
  30. static void PyThread__init_thread(void)
  31. {
  32. pth_init();
  33. PyThread_attr = pth_attr_new();
  34. pth_attr_set(PyThread_attr, PTH_ATTR_STACK_SIZE, 1<<18);
  35. pth_attr_set(PyThread_attr, PTH_ATTR_JOINABLE, FALSE);
  36. }
  37. /*
  38. * Thread support.
  39. */
  40. long PyThread_start_new_thread(void (*func)(void *), void *arg)
  41. {
  42. pth_t th;
  43. dprintf(("PyThread_start_new_thread called\n"));
  44. if (!initialized)
  45. PyThread_init_thread();
  46. th = pth_spawn(PyThread_attr,
  47. (void* (*)(void *))func,
  48. (void *)arg
  49. );
  50. return th;
  51. }
  52. long PyThread_get_thread_ident(void)
  53. {
  54. volatile pth_t threadid;
  55. if (!initialized)
  56. PyThread_init_thread();
  57. threadid = pth_self();
  58. return (long) threadid;
  59. }
  60. void PyThread_exit_thread(void)
  61. {
  62. dprintf(("PyThread_exit_thread called\n"));
  63. if (!initialized) {
  64. exit(0);
  65. }
  66. }
  67. /*
  68. * Lock support.
  69. */
  70. PyThread_type_lock PyThread_allocate_lock(void)
  71. {
  72. pth_lock *lock;
  73. int status, error = 0;
  74. dprintf(("PyThread_allocate_lock called\n"));
  75. if (!initialized)
  76. PyThread_init_thread();
  77. lock = (pth_lock *) malloc(sizeof(pth_lock));
  78. memset((void *)lock, '\0', sizeof(pth_lock));
  79. if (lock) {
  80. lock->locked = 0;
  81. status = pth_mutex_init(&lock->mut);
  82. CHECK_STATUS("pth_mutex_init");
  83. status = pth_cond_init(&lock->lock_released);
  84. CHECK_STATUS("pth_cond_init");
  85. if (error) {
  86. free((void *)lock);
  87. lock = NULL;
  88. }
  89. }
  90. dprintf(("PyThread_allocate_lock() -> %p\n", lock));
  91. return (PyThread_type_lock) lock;
  92. }
  93. void PyThread_free_lock(PyThread_type_lock lock)
  94. {
  95. pth_lock *thelock = (pth_lock *)lock;
  96. dprintf(("PyThread_free_lock(%p) called\n", lock));
  97. free((void *)thelock);
  98. }
  99. int PyThread_acquire_lock(PyThread_type_lock lock, int waitflag)
  100. {
  101. int success;
  102. pth_lock *thelock = (pth_lock *)lock;
  103. int status, error = 0;
  104. dprintf(("PyThread_acquire_lock(%p, %d) called\n", lock, waitflag));
  105. status = pth_mutex_acquire(&thelock->mut, !waitflag, NULL);
  106. CHECK_STATUS("pth_mutex_acquire[1]");
  107. success = thelock->locked == 0;
  108. if (success) thelock->locked = 1;
  109. status = pth_mutex_release( &thelock->mut );
  110. CHECK_STATUS("pth_mutex_release[1]");
  111. if ( !success && waitflag ) {
  112. /* continue trying until we get the lock */
  113. /* mut must be locked by me -- part of the condition
  114. * protocol */
  115. status = pth_mutex_acquire( &thelock->mut, !waitflag, NULL );
  116. CHECK_STATUS("pth_mutex_acquire[2]");
  117. while ( thelock->locked ) {
  118. status = pth_cond_await(&thelock->lock_released,
  119. &thelock->mut, NULL);
  120. CHECK_STATUS("pth_cond_await");
  121. }
  122. thelock->locked = 1;
  123. status = pth_mutex_release( &thelock->mut );
  124. CHECK_STATUS("pth_mutex_release[2]");
  125. success = 1;
  126. }
  127. if (error) success = 0;
  128. dprintf(("PyThread_acquire_lock(%p, %d) -> %d\n", lock, waitflag, success));
  129. return success;
  130. }
  131. void PyThread_release_lock(PyThread_type_lock lock)
  132. {
  133. pth_lock *thelock = (pth_lock *)lock;
  134. int status, error = 0;
  135. dprintf(("PyThread_release_lock(%p) called\n", lock));
  136. status = pth_mutex_acquire( &thelock->mut, 0, NULL );
  137. CHECK_STATUS("pth_mutex_acquire[3]");
  138. thelock->locked = 0;
  139. status = pth_mutex_release( &thelock->mut );
  140. CHECK_STATUS("pth_mutex_release[3]");
  141. /* wake up someone (anyone, if any) waiting on the lock */
  142. status = pth_cond_notify( &thelock->lock_released, 0 );
  143. CHECK_STATUS("pth_cond_notify");
  144. }