source: golgotha/src/i4/threads/win32_threads.cc @ 608

Last change on this file since 608 was 80, checked in by Sam Hocevar, 15 years ago
  • Adding the Golgotha source code. Not sure what's going to be interesting in there, but since it's all public domain, there's certainly stuff to pick up.
File size: 7.0 KB
Line 
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
9#include "threads/threads.hh"
10#include "error/error.hh"
11#include "init/init.hh"
12#include "main/main.hh"
13
14#include <stdio.h>
15#include <windows.h>
16#include <process.h>
17
18static w32 i4_thread_count=0;
19static i4_critical_section_class i4_thread_lock;
20static i4_critical_section_class thread_list_lock;
21
22struct thread_node
23{
24  HANDLE h;
25  w32 thread_id;
26  thread_node *next;
27  void *base, *top;
28
29  thread_node(HANDLE h, w32 thread_id, void *base, void *top, thread_node *next)
30    : h(h), thread_id(thread_id), next(next), base(base), top(top) {}
31
32};
33
34static thread_node *thread_list=0;
35
36int i4_main_thread_id;
37
38void i4_wait_threads()  // waits for all threads to terminate (don't call from a thread!)
39{
40  while (i4_thread_count!=0)
41    i4_thread_yield();
42}
43
44
45
46static i4_thread_func_type i4_thread_to_start=0;
47static int i4_thread_size;
48
49void remove_thread(int id)
50{
51  thread_list_lock.lock();
52
53  thread_node *p=0;
54  if (thread_list->thread_id==id)
55  {
56    p=thread_list;
57    thread_list=thread_list->next;
58  }
59  else
60  {
61    for (thread_node *q=thread_list; q->next->thread_id!=id; q=q->next);
62    p=q->next;
63    q->next=p->next;
64  }
65
66  CloseHandle(p->h);
67  delete p;
68  thread_list_lock.unlock();
69}
70
71
72void i4_thread_starter(void *arg)
73{
74  i4_thread_func_type start=i4_thread_to_start;
75  int size=i4_thread_size;
76  size-=200;
77  i4_thread_to_start=0;
78
79  thread_list_lock.lock();
80  w32 thread_id=GetCurrentThreadId();
81
82  HANDLE h;
83  DuplicateHandle(GetCurrentProcess(),
84                  GetCurrentThread(),
85                  GetCurrentProcess(),
86                  &h,
87                  DUPLICATE_SAME_ACCESS,
88                  FALSE,
89                  DUPLICATE_SAME_ACCESS);
90
91                         
92  thread_node *p=new thread_node(h, thread_id,
93                                 (void *)&size,
94                                 (void *)(((char *)&size)-size),
95                                 thread_list);
96
97
98  thread_list=p;
99  thread_list_lock.unlock();
100
101
102
103  start(arg);
104
105  remove_thread(p->thread_id);
106
107  i4_thread_lock.lock();
108  i4_thread_count--;
109  i4_thread_lock.unlock();
110
111  _endthread();
112}
113
114void i4_add_thread(i4_thread_func_type fun, w32 stack_size, void *arg_list)
115
116{
117  while (i4_thread_to_start!=0)
118    i4_thread_yield();
119
120  i4_thread_to_start=fun;
121  i4_thread_size=stack_size;
122 
123  i4_thread_lock.lock();
124  i4_thread_count++;
125  i4_thread_lock.unlock();
126
127  _beginthread(i4_thread_starter, stack_size, arg_list);
128}
129
130void i4_thread_yield()
131{
132  Sleep(0);
133}
134
135
136int i4_get_thread_id()
137{
138  return GetCurrentThreadId();
139}
140
141
142
143
144void i4_suspend_other_threads()
145{
146  thread_list_lock.lock();
147
148  w32 thread_id=GetCurrentThreadId();
149  for (thread_node *p=thread_list; p; p=p->next)
150    if (p->thread_id!=thread_id)     
151      SuspendThread(p->h);
152
153  thread_list_lock.unlock();
154}
155
156void i4_resume_other_threads()
157{
158  thread_list_lock.lock();
159
160  w32 thread_id=GetCurrentThreadId();
161  for (thread_node *p=thread_list; p; p=p->next)
162    if (p->thread_id!=thread_id)     
163      ResumeThread(p->h);
164
165  thread_list_lock.unlock();
166}
167
168
169int i4_get_main_thread_id()
170{
171  return i4_main_thread_id;
172}
173
174i4_bool i4_get_first_thread_id(int &id);
175i4_bool i4_get_next_thread_id(int last_id, int &id);
176
177int i4_get_first_thread_id() { return thread_list->thread_id; }
178
179i4_bool i4_get_next_thread_id(int last_id, int &id)
180{
181  for (thread_node *p=thread_list; p; p=p->next)
182    if (p->thread_id==last_id)
183      if (p->next)
184      {
185        id=p->next->thread_id;
186        return i4_T;
187      }
188      else
189        return i4_F;
190  return i4_F;
191}
192
193
194void i4_get_thread_stack(int thread_id, void *&base, void *&top)
195{
196  base=0;
197  top=0;
198
199  if (thread_id==i4_main_thread_id)
200  {
201    base=i4_stack_base;
202    if (i4_get_thread_id()!=i4_main_thread_id)
203      i4_error("Can't get main thread stack from thread");
204   
205    int t;
206    top=(void *)(&t);     
207  }
208  else
209  {
210    for (thread_node *p=thread_list; p; p=p->next)
211      if (p->thread_id==thread_id)
212      {
213        base=p->base;
214        top=p->top;
215      }
216  }
217}
218
219
220
221class thread_initer : public i4_init_class
222{
223public:
224  virtual int init_type() { return I4_INIT_TYPE_THREADS; }
225  void init()
226  {
227    i4_main_thread_id=i4_get_thread_id();     
228    HANDLE h;
229    DuplicateHandle(GetCurrentProcess(),
230                    GetCurrentThread(),
231                    GetCurrentProcess(),
232                    &h,
233                    DUPLICATE_SAME_ACCESS,
234                    FALSE,
235                    DUPLICATE_SAME_ACCESS);
236                         
237    thread_list=new thread_node(h, i4_main_thread_id,
238                                i4_stack_base, i4_stack_base, 0);
239  }
240
241  void uninit()
242  {
243    remove_thread(i4_main_thread_id);
244  }
245
246};
247
248static thread_initer thread_initer_instance;
249
250
251
252////////////// Critical section stuff
253i4_critical_section_class::i4_critical_section_class()
254{
255  data[0]=0;
256}
257
258void I4_FAST_CALL i4_critical_section_class::lock()
259{
260  __asm
261  {
262    start:     
263      bts [ecx], 0
264      jnc success
265      call i4_thread_yield   // give up our time-slice
266      jmp start
267    success:
268  }
269}
270
271void I4_FAST_CALL i4_critical_section_class::unlock()
272{
273  __asm mov [ecx], 0
274}
275
276i4_critical_section_class::~i4_critical_section_class()
277{
278
279}
280
281
282///////////// signal stuff
283i4_signal_object::i4_signal_object(char *name)
284{
285  char buf[100];
286  sprintf(buf,"%s-%d",name,_getpid());     // make sure name doesn't interfere with other
287  *((HANDLE *)data)=CreateSemaphore(0, 0, 1, buf); // processes using this library
288}
289
290void i4_signal_object::wait_signal()           
291{
292  WaitForSingleObject(*((HANDLE *)data), INFINITE); 
293}
294
295
296void i4_signal_object::signal()               
297{
298  ReleaseSemaphore(*((HANDLE *)data), 1, 0); 
299}
300
301i4_signal_object::~i4_signal_object()         
302{
303  CloseHandle(*((HANDLE *)data));
304}
305
306i4_bool i4_threads_supported() { return i4_T; }
307
308
309void i4_set_thread_priority(int thread_id, i4_thread_priority_type priority)
310{
311  thread_list_lock.lock();
312
313  for (thread_node *p=thread_list; p && p->thread_id!=thread_id; p=p->next);
314  if (p)
315  {
316    switch (priority)
317    {
318      case I4_THREAD_PRIORITY_HIGH :
319        SetThreadPriority(p->h, THREAD_PRIORITY_HIGHEST);
320        break;
321
322      case I4_THREAD_PRIORITY_NORMAL :
323        SetThreadPriority(p->h, THREAD_PRIORITY_NORMAL);
324        break;
325
326      case I4_THREAD_PRIORITY_LOW :
327        SetThreadPriority(p->h, THREAD_PRIORITY_BELOW_NORMAL);
328    }
329  }
330
331  thread_list_lock.unlock();
332}
333
334
Note: See TracBrowser for help on using the repository browser.