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.

267 lines
5.7 KiB

  1. /* This code implemented by cvale@netcom.com */
  2. #define INCL_DOSPROCESS
  3. #define INCL_DOSSEMAPHORES
  4. #include "os2.h"
  5. #include "limits.h"
  6. #include "process.h"
  7. #if defined(PYCC_GCC)
  8. #include <sys/builtin.h>
  9. #include <sys/fmutex.h>
  10. #else
  11. long PyThread_get_thread_ident(void);
  12. #endif
  13. /* default thread stack size of 64kB */
  14. #if !defined(THREAD_STACK_SIZE)
  15. #define THREAD_STACK_SIZE 0x10000
  16. #endif
  17. #define OS2_STACKSIZE(x) (x ? x : THREAD_STACK_SIZE)
  18. /*
  19. * Initialization of the C package, should not be needed.
  20. */
  21. static void
  22. PyThread__init_thread(void)
  23. {
  24. }
  25. /*
  26. * Thread support.
  27. */
  28. long
  29. PyThread_start_new_thread(void (*func)(void *), void *arg)
  30. {
  31. int thread_id;
  32. thread_id = _beginthread(func,
  33. NULL,
  34. OS2_STACKSIZE(_pythread_stacksize),
  35. arg);
  36. if (thread_id == -1) {
  37. dprintf(("_beginthread failed. return %ld\n", errno));
  38. }
  39. return thread_id;
  40. }
  41. long
  42. PyThread_get_thread_ident(void)
  43. {
  44. #if !defined(PYCC_GCC)
  45. PPIB pib;
  46. PTIB tib;
  47. #endif
  48. if (!initialized)
  49. PyThread_init_thread();
  50. #if defined(PYCC_GCC)
  51. return _gettid();
  52. #else
  53. DosGetInfoBlocks(&tib, &pib);
  54. return tib->tib_ptib2->tib2_ultid;
  55. #endif
  56. }
  57. void
  58. PyThread_exit_thread(void)
  59. {
  60. dprintf(("%ld: PyThread_exit_thread called\n",
  61. PyThread_get_thread_ident()));
  62. if (!initialized)
  63. exit(0);
  64. _endthread();
  65. }
  66. /*
  67. * Lock support. This is implemented with an event semaphore and critical
  68. * sections to make it behave more like a posix mutex than its OS/2
  69. * counterparts.
  70. */
  71. typedef struct os2_lock_t {
  72. int is_set;
  73. HEV changed;
  74. } *type_os2_lock;
  75. PyThread_type_lock
  76. PyThread_allocate_lock(void)
  77. {
  78. #if defined(PYCC_GCC)
  79. _fmutex *sem = malloc(sizeof(_fmutex));
  80. if (!initialized)
  81. PyThread_init_thread();
  82. dprintf(("%ld: PyThread_allocate_lock() -> %lx\n",
  83. PyThread_get_thread_ident(),
  84. (long)sem));
  85. if (_fmutex_create(sem, 0)) {
  86. free(sem);
  87. sem = NULL;
  88. }
  89. return (PyThread_type_lock)sem;
  90. #else
  91. APIRET rc;
  92. type_os2_lock lock = (type_os2_lock)malloc(sizeof(struct os2_lock_t));
  93. dprintf(("PyThread_allocate_lock called\n"));
  94. if (!initialized)
  95. PyThread_init_thread();
  96. lock->is_set = 0;
  97. DosCreateEventSem(NULL, &lock->changed, 0, 0);
  98. dprintf(("%ld: PyThread_allocate_lock() -> %p\n",
  99. PyThread_get_thread_ident(),
  100. lock->changed));
  101. return (PyThread_type_lock)lock;
  102. #endif
  103. }
  104. void
  105. PyThread_free_lock(PyThread_type_lock aLock)
  106. {
  107. #if !defined(PYCC_GCC)
  108. type_os2_lock lock = (type_os2_lock)aLock;
  109. #endif
  110. dprintf(("%ld: PyThread_free_lock(%p) called\n",
  111. PyThread_get_thread_ident(),aLock));
  112. #if defined(PYCC_GCC)
  113. if (aLock) {
  114. _fmutex_close((_fmutex *)aLock);
  115. free((_fmutex *)aLock);
  116. }
  117. #else
  118. DosCloseEventSem(lock->changed);
  119. free(aLock);
  120. #endif
  121. }
  122. /*
  123. * Return 1 on success if the lock was acquired
  124. *
  125. * and 0 if the lock was not acquired.
  126. */
  127. int
  128. PyThread_acquire_lock(PyThread_type_lock aLock, int waitflag)
  129. {
  130. #if !defined(PYCC_GCC)
  131. int done = 0;
  132. ULONG count;
  133. PID pid = 0;
  134. TID tid = 0;
  135. type_os2_lock lock = (type_os2_lock)aLock;
  136. #endif
  137. dprintf(("%ld: PyThread_acquire_lock(%p, %d) called\n",
  138. PyThread_get_thread_ident(),
  139. aLock,
  140. waitflag));
  141. #if defined(PYCC_GCC)
  142. /* always successful if the lock doesn't exist */
  143. if (aLock &&
  144. _fmutex_request((_fmutex *)aLock, waitflag ? 0 : _FMR_NOWAIT))
  145. return 0;
  146. #else
  147. while (!done) {
  148. /* if the lock is currently set, we have to wait for
  149. * the state to change
  150. */
  151. if (lock->is_set) {
  152. if (!waitflag)
  153. return 0;
  154. DosWaitEventSem(lock->changed, SEM_INDEFINITE_WAIT);
  155. }
  156. /* enter a critical section and try to get the semaphore. If
  157. * it is still locked, we will try again.
  158. */
  159. if (DosEnterCritSec())
  160. return 0;
  161. if (!lock->is_set) {
  162. lock->is_set = 1;
  163. DosResetEventSem(lock->changed, &count);
  164. done = 1;
  165. }
  166. DosExitCritSec();
  167. }
  168. #endif
  169. return 1;
  170. }
  171. void
  172. PyThread_release_lock(PyThread_type_lock aLock)
  173. {
  174. #if !defined(PYCC_GCC)
  175. type_os2_lock lock = (type_os2_lock)aLock;
  176. #endif
  177. dprintf(("%ld: PyThread_release_lock(%p) called\n",
  178. PyThread_get_thread_ident(),
  179. aLock));
  180. #if defined(PYCC_GCC)
  181. if (aLock)
  182. _fmutex_release((_fmutex *)aLock);
  183. #else
  184. if (!lock->is_set) {
  185. dprintf(("%ld: Could not PyThread_release_lock(%p) error: %l\n",
  186. PyThread_get_thread_ident(),
  187. aLock,
  188. GetLastError()));
  189. return;
  190. }
  191. if (DosEnterCritSec()) {
  192. dprintf(("%ld: Could not PyThread_release_lock(%p) error: %l\n",
  193. PyThread_get_thread_ident(),
  194. aLock,
  195. GetLastError()));
  196. return;
  197. }
  198. lock->is_set = 0;
  199. DosPostEventSem(lock->changed);
  200. DosExitCritSec();
  201. #endif
  202. }
  203. /* minimum/maximum thread stack sizes supported */
  204. #define THREAD_MIN_STACKSIZE 0x8000 /* 32kB */
  205. #define THREAD_MAX_STACKSIZE 0x2000000 /* 32MB */
  206. /* set the thread stack size.
  207. * Return 0 if size is valid, -1 otherwise.
  208. */
  209. static int
  210. _pythread_os2_set_stacksize(size_t size)
  211. {
  212. /* set to default */
  213. if (size == 0) {
  214. _pythread_stacksize = 0;
  215. return 0;
  216. }
  217. /* valid range? */
  218. if (size >= THREAD_MIN_STACKSIZE && size < THREAD_MAX_STACKSIZE) {
  219. _pythread_stacksize = size;
  220. return 0;
  221. }
  222. return -1;
  223. }
  224. #define THREAD_SET_STACKSIZE(x) _pythread_os2_set_stacksize(x)