win32_threads.cc 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335
  1. /********************************************************************** <BR>
  2. This file is part of Crack dot Com's free source code release of
  3. Golgotha. <a href="http://www.crack.com/golgotha_release"> <BR> for
  4. information about compiling & licensing issues visit this URL</a>
  5. <PRE> If that doesn't help, contact Jonathan Clark at
  6. golgotha_source@usa.net (Subject should have "GOLG" in it)
  7. ***********************************************************************/
  8. #include "threads/threads.hh"
  9. #include "error/error.hh"
  10. #include "init/init.hh"
  11. #include "main/main.hh"
  12. #include <stdio.h>
  13. #include <windows.h>
  14. #include <process.h>
  15. static w32 i4_thread_count=0;
  16. static i4_critical_section_class i4_thread_lock;
  17. static i4_critical_section_class thread_list_lock;
  18. struct thread_node
  19. {
  20. HANDLE h;
  21. w32 thread_id;
  22. thread_node *next;
  23. void *base, *top;
  24. thread_node(HANDLE h, w32 thread_id, void *base, void *top, thread_node *next)
  25. : h(h), thread_id(thread_id), next(next), base(base), top(top) {}
  26. };
  27. static thread_node *thread_list=0;
  28. int i4_main_thread_id;
  29. void i4_wait_threads() // waits for all threads to terminate (don't call from a thread!)
  30. {
  31. while (i4_thread_count!=0)
  32. i4_thread_yield();
  33. }
  34. static i4_thread_func_type i4_thread_to_start=0;
  35. static int i4_thread_size;
  36. void remove_thread(int id)
  37. {
  38. thread_list_lock.lock();
  39. thread_node *p=0;
  40. if (thread_list->thread_id==id)
  41. {
  42. p=thread_list;
  43. thread_list=thread_list->next;
  44. }
  45. else
  46. {
  47. for (thread_node *q=thread_list; q->next->thread_id!=id; q=q->next);
  48. p=q->next;
  49. q->next=p->next;
  50. }
  51. CloseHandle(p->h);
  52. delete p;
  53. thread_list_lock.unlock();
  54. }
  55. void i4_thread_starter(void *arg)
  56. {
  57. i4_thread_func_type start=i4_thread_to_start;
  58. int size=i4_thread_size;
  59. size-=200;
  60. i4_thread_to_start=0;
  61. thread_list_lock.lock();
  62. w32 thread_id=GetCurrentThreadId();
  63. HANDLE h;
  64. DuplicateHandle(GetCurrentProcess(),
  65. GetCurrentThread(),
  66. GetCurrentProcess(),
  67. &h,
  68. DUPLICATE_SAME_ACCESS,
  69. FALSE,
  70. DUPLICATE_SAME_ACCESS);
  71. thread_node *p=new thread_node(h, thread_id,
  72. (void *)&size,
  73. (void *)(((char *)&size)-size),
  74. thread_list);
  75. thread_list=p;
  76. thread_list_lock.unlock();
  77. start(arg);
  78. remove_thread(p->thread_id);
  79. i4_thread_lock.lock();
  80. i4_thread_count--;
  81. i4_thread_lock.unlock();
  82. _endthread();
  83. }
  84. void i4_add_thread(i4_thread_func_type fun, w32 stack_size, void *arg_list)
  85. {
  86. while (i4_thread_to_start!=0)
  87. i4_thread_yield();
  88. i4_thread_to_start=fun;
  89. i4_thread_size=stack_size;
  90. i4_thread_lock.lock();
  91. i4_thread_count++;
  92. i4_thread_lock.unlock();
  93. _beginthread(i4_thread_starter, stack_size, arg_list);
  94. }
  95. void i4_thread_yield()
  96. {
  97. Sleep(0);
  98. }
  99. int i4_get_thread_id()
  100. {
  101. return GetCurrentThreadId();
  102. }
  103. void i4_suspend_other_threads()
  104. {
  105. thread_list_lock.lock();
  106. w32 thread_id=GetCurrentThreadId();
  107. for (thread_node *p=thread_list; p; p=p->next)
  108. if (p->thread_id!=thread_id)
  109. SuspendThread(p->h);
  110. thread_list_lock.unlock();
  111. }
  112. void i4_resume_other_threads()
  113. {
  114. thread_list_lock.lock();
  115. w32 thread_id=GetCurrentThreadId();
  116. for (thread_node *p=thread_list; p; p=p->next)
  117. if (p->thread_id!=thread_id)
  118. ResumeThread(p->h);
  119. thread_list_lock.unlock();
  120. }
  121. int i4_get_main_thread_id()
  122. {
  123. return i4_main_thread_id;
  124. }
  125. i4_bool i4_get_first_thread_id(int &id);
  126. i4_bool i4_get_next_thread_id(int last_id, int &id);
  127. int i4_get_first_thread_id() { return thread_list->thread_id; }
  128. i4_bool i4_get_next_thread_id(int last_id, int &id)
  129. {
  130. for (thread_node *p=thread_list; p; p=p->next)
  131. if (p->thread_id==last_id)
  132. if (p->next)
  133. {
  134. id=p->next->thread_id;
  135. return i4_T;
  136. }
  137. else
  138. return i4_F;
  139. return i4_F;
  140. }
  141. void i4_get_thread_stack(int thread_id, void *&base, void *&top)
  142. {
  143. base=0;
  144. top=0;
  145. if (thread_id==i4_main_thread_id)
  146. {
  147. base=i4_stack_base;
  148. if (i4_get_thread_id()!=i4_main_thread_id)
  149. i4_error("Can't get main thread stack from thread");
  150. int t;
  151. top=(void *)(&t);
  152. }
  153. else
  154. {
  155. for (thread_node *p=thread_list; p; p=p->next)
  156. if (p->thread_id==thread_id)
  157. {
  158. base=p->base;
  159. top=p->top;
  160. }
  161. }
  162. }
  163. class thread_initer : public i4_init_class
  164. {
  165. public:
  166. virtual int init_type() { return I4_INIT_TYPE_THREADS; }
  167. void init()
  168. {
  169. i4_main_thread_id=i4_get_thread_id();
  170. HANDLE h;
  171. DuplicateHandle(GetCurrentProcess(),
  172. GetCurrentThread(),
  173. GetCurrentProcess(),
  174. &h,
  175. DUPLICATE_SAME_ACCESS,
  176. FALSE,
  177. DUPLICATE_SAME_ACCESS);
  178. thread_list=new thread_node(h, i4_main_thread_id,
  179. i4_stack_base, i4_stack_base, 0);
  180. }
  181. void uninit()
  182. {
  183. remove_thread(i4_main_thread_id);
  184. }
  185. };
  186. static thread_initer thread_initer_instance;
  187. ////////////// Critical section stuff
  188. i4_critical_section_class::i4_critical_section_class()
  189. {
  190. data[0]=0;
  191. }
  192. void I4_FAST_CALL i4_critical_section_class::lock()
  193. {
  194. __asm
  195. {
  196. start:
  197. bts [ecx], 0
  198. jnc success
  199. call i4_thread_yield // give up our time-slice
  200. jmp start
  201. success:
  202. }
  203. }
  204. void I4_FAST_CALL i4_critical_section_class::unlock()
  205. {
  206. __asm mov [ecx], 0
  207. }
  208. i4_critical_section_class::~i4_critical_section_class()
  209. {
  210. }
  211. ///////////// signal stuff
  212. i4_signal_object::i4_signal_object(char *name)
  213. {
  214. char buf[100];
  215. sprintf(buf,"%s-%d",name,_getpid()); // make sure name doesn't interfere with other
  216. *((HANDLE *)data)=CreateSemaphore(0, 0, 1, buf); // processes using this library
  217. }
  218. void i4_signal_object::wait_signal()
  219. {
  220. WaitForSingleObject(*((HANDLE *)data), INFINITE);
  221. }
  222. void i4_signal_object::signal()
  223. {
  224. ReleaseSemaphore(*((HANDLE *)data), 1, 0);
  225. }
  226. i4_signal_object::~i4_signal_object()
  227. {
  228. CloseHandle(*((HANDLE *)data));
  229. }
  230. i4_bool i4_threads_supported() { return i4_T; }
  231. void i4_set_thread_priority(int thread_id, i4_thread_priority_type priority)
  232. {
  233. thread_list_lock.lock();
  234. for (thread_node *p=thread_list; p && p->thread_id!=thread_id; p=p->next);
  235. if (p)
  236. {
  237. switch (priority)
  238. {
  239. case I4_THREAD_PRIORITY_HIGH :
  240. SetThreadPriority(p->h, THREAD_PRIORITY_HIGHEST);
  241. break;
  242. case I4_THREAD_PRIORITY_NORMAL :
  243. SetThreadPriority(p->h, THREAD_PRIORITY_NORMAL);
  244. break;
  245. case I4_THREAD_PRIORITY_LOW :
  246. SetThreadPriority(p->h, THREAD_PRIORITY_BELOW_NORMAL);
  247. }
  248. }
  249. thread_list_lock.unlock();
  250. }