(file) Return to thread.c CVS log (file) (dir) Up to [OMI] / omi / pal

  1 krisbash 1.1 #include "thread.h"
  2              #include "atomic.h"
  3              #include <pal/palcommon.h>
  4              
  5              #if defined(PAL_HAVE_PTHREADS)
  6              # include <sched.h>
  7              #endif
  8              
  9              /*
 10              **==============================================================================
 11              **
 12              ** Windows version
 13              **
 14              **==============================================================================
 15              */
 16              
 17              #if defined(_MSC_VER)
 18              
 19              #pragma warning(disable:4057)
 20              
 21              typedef struct _ThreadWork 
 22 krisbash 1.1 {
 23                  ThreadProc threadProcCallback;
 24                  ThreadProc threadProcDestructor;
 25                  void* threadProcParam;
 26                  TP_WORK *tpWork;
 27                  PAL_Uint32 returnCode;
 28                  ptrdiff_t refcount;
 29              }
 30              ThreadWork;
 31              
 32              VOID CALLBACK PAL_ThreadPoolCallback(
 33                _Inout_      PTP_CALLBACK_INSTANCE tpInstance,
 34                _In_         PVOID context,
 35                _Inout_      PTP_WORK tpWork
 36              )
 37              {
 38                  ThreadWork* self = (ThreadWork*) context;
 39                  HMODULE newHModule;
 40              
 41                  GetModuleHandleExW(
 42                      GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS ,
 43 krisbash 1.1         (LPCWSTR) self->threadProcCallback,
 44                      &newHModule);
 45              
 46                  CallbackMayRunLong(tpInstance);
 47                  FreeLibraryWhenCallbackReturns(tpInstance, newHModule);
 48              
 49                  self->returnCode = self->threadProcCallback(self->threadProcParam);
 50              
 51                  if (self->threadProcDestructor)
 52                      self->threadProcDestructor(self->threadProcParam);
 53              
 54                  if (Atomic_Dec(&self->refcount) == 0)
 55                  {
 56                      CloseThreadpoolWork(tpWork);
 57                      PAL_Free(self);
 58                  }
 59              }
 60              
 61              
 62              _Return_type_success_(return == 0) int Thread_CreateDetached_Injected(
 63                  _In_ ThreadProc threadProcCallback,
 64 krisbash 1.1     _In_opt_ ThreadProc threadProcDestructor,
 65                  _In_ void* threadProcParam,
 66                  _In_ NitsCallSite cs)
 67              {
 68                  ThreadWork *thread = NULL;
 69              
 70              #if !defined(USE_ALLOCATOR)
 71                  if (NitsShouldFault(cs, NitsAutomatic))
 72                      return -1;
 73              
 74                  thread = PAL_Calloc(1, sizeof(ThreadWork));
 75              #else
 76                  thread = __PAL_Calloc(cs.file, cs.line, cs.function, 1, sizeof(ThreadWork));
 77              #endif
 78              
 79                  if (thread == NULL)
 80                      return -1;
 81              
 82                  thread->threadProcCallback = threadProcCallback;
 83                  thread->threadProcDestructor = threadProcDestructor;
 84                  thread->threadProcParam = threadProcParam;
 85 krisbash 1.1     thread->refcount = 1;
 86              
 87                  /* Create the thread */
 88                  thread->tpWork = CreateThreadpoolWork(PAL_ThreadPoolCallback, thread, NULL);
 89                  if (thread->tpWork == NULL)
 90                  {
 91                      PAL_Free(thread);
 92                      return -1;
 93                  }
 94              
 95                  SubmitThreadpoolWork(thread->tpWork);
 96              
 97                  return 0;
 98              }
 99              
100              _Return_type_success_(return == 0) int Thread_CreateJoinable_Injected(
101                  _Out_ Thread* self,
102                  _In_ ThreadProc threadProcCallback,
103                  _In_opt_ ThreadProc threadProcDestructor,
104                  _In_ void* threadProcParam,
105                  NitsCallSite cs)
106 krisbash 1.1 {
107                  ThreadWork *thread = NULL;
108              
109              #if !defined(USE_ALLOCATOR)
110                  if (NitsShouldFault(cs, NitsAutomatic))
111                      return -1;
112              
113                  thread = PAL_Calloc(1, sizeof(ThreadWork));
114              #else
115                  thread = __PAL_Calloc(
116                      cs.file, cs.line, cs.function, 1, sizeof(ThreadWork));
117              #endif
118              
119                  if (thread == NULL)
120                      return -1;
121              
122                  thread->threadProcCallback = threadProcCallback;
123                  thread->threadProcDestructor = threadProcDestructor;
124                  thread->threadProcParam = threadProcParam;
125                  thread->refcount = 2;
126              
127 krisbash 1.1     /* Create the thread */
128                  thread->tpWork = CreateThreadpoolWork(PAL_ThreadPoolCallback, thread, NULL);
129                  if (thread->tpWork == NULL)
130                  {
131                      PAL_Free(thread);
132                      return -1;
133                  }
134              
135                  self->__impl = (ptrdiff_t) thread;
136              
137                  SubmitThreadpoolWork(thread->tpWork);
138                  
139                  return 0;
140              }
141              
142              _Return_type_success_(return == 0) int Thread_Join(
143                  _In_ Thread* self,
144                  _Out_ PAL_Uint32* returnValue)
145              {
146                  ThreadWork *thread;
147                  if (self->__impl == 0)
148 krisbash 1.1     {
149                      *returnValue = 0;
150                      return 0;
151                  }
152              
153                  thread = (ThreadWork*) self->__impl;
154              
155                  /* Wait for thread to exit */
156                  WaitForThreadpoolWorkCallbacks(thread->tpWork,FALSE);
157              
158                  /*  return code from called thread */
159                  *returnValue = thread->returnCode;
160              
161                  return 0;
162              }
163              
164              void Thread_Destroy(
165                  _Inout_ Thread* self)
166              {
167                  ThreadWork *thread;
168                  if (self->__impl == 0)
169 krisbash 1.1         return;
170                  thread = (ThreadWork*) self->__impl;
171              
172                  if (Atomic_Dec(&thread->refcount) == 0)
173                  {
174                      CloseThreadpoolWork(thread->tpWork);
175                      PAL_Free(thread);
176                  }
177              
178                  memset(self, 0, sizeof(*self));
179              }
180              
181              void Thread_Yield()
182              {
183                  SwitchToThread();
184              }
185              
186              
187              #endif /* defined(_MSC_VER) */
188              
189              /*
190 krisbash 1.1 **==============================================================================
191              **
192              ** POSIX threads version
193              **
194              **==============================================================================
195              */
196              
197              #if defined(PAL_HAVE_PTHREADS)
198              
199              typedef struct _ThreadData
200              {
201                  ThreadProc proc;
202                  ThreadProc destructor;
203                  void* param;
204              }
205              ThreadData;
206              
207              static void* _Wrapper(void* param) 
208              {
209                  ThreadData* data = (ThreadData*)param;
210                  void* result;
211 krisbash 1.1 
212                  result = (void*)(ptrdiff_t)(*data->proc)(data->param);
213              
214                  if (data->destructor)
215                      data->destructor(data->param);
216              
217                  PAL_Free(data);
218              
219                  return result;
220              }
221              
222              int Thread_CreateDetached_Injected(
223                  _In_ ThreadProc threadProcCallback,
224                  _In_opt_ ThreadProc threadProcDestructor,
225                  _In_ void* threadProcParam,
226                  NitsCallSite cs)
227              {
228                  pthread_attr_t attr;
229                  pthread_t thread;
230                  int r;
231              
232 krisbash 1.1 #if !defined(USE_ALLOCATOR)
233                  if (NitsShouldFault(cs, NitsAutomatic))
234                      return -1;
235              #endif
236              
237                  /* Create the thread attributes and set the detached flag */
238              
239                  pthread_attr_init(&attr);
240                  pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
241              
242                  /* Create the thread */
243                  {
244              #if !defined(USE_ALLOCATOR)
245                      ThreadData* data = (ThreadData*)PAL_Malloc(sizeof(ThreadData));
246              #else
247                      ThreadData* data = (ThreadData*)__PAL_Malloc( 
248                          cs.file, cs.line, cs.function, sizeof(ThreadData));
249              #endif
250              
251              
252                      if (!data)
253 krisbash 1.1         {
254                          pthread_attr_destroy(&attr);
255                          return -1;
256                      }
257              
258                      data->proc = threadProcCallback;
259                      data->destructor = threadProcDestructor;
260                      data->param = threadProcParam;
261                      r = pthread_create(&thread, &attr, _Wrapper, data);
262                      if (r != 0)
263                      {
264                          PAL_Free(data);
265                      }
266                  }
267              
268                  /* Destroy thread attributes */
269                  pthread_attr_destroy(&attr);
270              
271                  return r == 0 ? 0 : -1;
272              }
273              
274 krisbash 1.1 int Thread_CreateJoinable_Injected(
275                  _Out_ Thread* self,
276                  _In_ ThreadProc threadProcCallback,
277                  _In_opt_ ThreadProc threadProcDestructor,
278                  _In_ void* threadProcParam,
279                  NitsCallSite cs)
280              {
281                  int r;
282              
283              #if !defined(USE_ALLOCATOR)
284                  if (NitsShouldFault(cs, NitsAutomatic))
285                      return -1;
286              #endif
287              
288                  /* Create the thread */
289                  {
290              #if !defined(USE_ALLOCATOR)
291                      ThreadData* data = (ThreadData*)PAL_Malloc(sizeof(ThreadData));
292              #else
293                      ThreadData* data = (ThreadData*)__PAL_Malloc(
294                          cs.file, cs.line, cs.function, sizeof(ThreadData));
295 krisbash 1.1 #endif
296              
297                      if (!data)
298                          return -1;
299              
300                      data->proc = threadProcCallback;
301                      data->destructor = threadProcDestructor;
302                      data->param = threadProcParam;
303                      r = pthread_create(&self->__impl, NULL, _Wrapper, data);
304                      if (r != 0)
305                      {
306                          PAL_Free(data);
307                      }
308                  }
309              
310                  return r == 0 ? 0 : -1;
311              }
312              
313              int Thread_Join(
314                  _In_ Thread* self,
315                  _Out_ PAL_Uint32* returnValue)
316 krisbash 1.1 {
317                  int r;
318                  void* returnValuePtr;
319                  
320                  r = pthread_join(self->__impl, &returnValuePtr);
321              
322                  if (r == 0 && returnValue)
323                  {
324                      *returnValue = (PAL_Uint32)(ptrdiff_t)returnValuePtr;
325                      return 0;
326                  }
327              
328                  return -1;
329              }
330              
331              int Thread_Equal(
332                  _In_ ThreadID* thread1,
333                  _In_ ThreadID* thread2)
334              {
335                  return pthread_equal(thread1->__impl, thread2->__impl) == 0 ? 0 : -1;
336              }
337 krisbash 1.1 
338              ThreadID Thread_ID()
339              {
340                  ThreadID self;
341                  self.__impl = pthread_self();
342                  return self;
343              }
344              
345              void Thread_Yield()
346              {
347                  sched_yield();
348              }
349              
350              
351              #endif /* defined(PAL_HAVE_PTHREADS) */

ViewCVS 0.9.2