Added check for pthread.h (reported by Steven Edwards).
[wine] / dlls / kernel / pthread.c
1 /*
2  * pthread emulation for re-entrant libcs
3  *
4  * Copyright 1999 Ove Kåven
5  * Copyright 2003 Alexandre Julliard
6  *
7  * This library is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Lesser General Public
9  * License as published by the Free Software Foundation; either
10  * version 2.1 of the License, or (at your option) any later version.
11  *
12  * This library is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public
18  * License along with this library; if not, write to the Free Software
19  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
20  */
21
22 #include "config.h"
23 #include "wine/port.h"
24
25 #ifdef HAVE_PTHREAD_H
26
27 #define _GNU_SOURCE /* we may need to override some GNU extensions */
28
29 #include <assert.h>
30 #include <errno.h>
31 #include <stdarg.h>
32 #include <stdlib.h>
33 #include <setjmp.h>
34 #ifdef HAVE_UNISTD_H
35 # include <unistd.h>
36 #endif
37 #include <string.h>
38 #include <sys/types.h>
39 #ifdef HAVE_SYS_SOCKET_H
40 # include <sys/socket.h>
41 #endif
42 #ifdef HAVE_SYS_MMAN_H
43 #include <sys/mman.h>
44 #endif
45
46 #include "windef.h"
47 #include "winbase.h"
48 #include "thread.h"
49 #include "winternl.h"
50 #include "wine/pthread.h"
51
52 #define P_OUTPUT(stuff) write(2,stuff,strlen(stuff))
53
54 static const struct wine_pthread_functions functions;
55
56 DECL_GLOBAL_CONSTRUCTOR(pthread_init) { wine_pthread_init_process( &functions ); }
57
58 /* NOTE: This is a truly extremely incredibly ugly hack!
59  * But it does seem to work... */
60
61 /* assume that pthread_mutex_t has room for at least one pointer,
62  * and hope that the users of pthread_mutex_t considers it opaque
63  * (never checks what's in it)
64  * also: assume that static initializer sets pointer to NULL
65  */
66 typedef struct
67 {
68 #ifdef __GLIBC__
69   int reserved;
70 #endif
71   CRITICAL_SECTION *critsect;
72 } *wine_mutex;
73
74 /* see wine_mutex above for comments */
75 typedef struct {
76   RTL_RWLOCK *lock;
77 } *wine_rwlock;
78
79 struct pthread_thread_init
80 {
81     void* (*start_routine)(void*);
82     void* arg;
83 };
84
85 static DWORD CALLBACK pthread_thread_start(LPVOID data)
86 {
87   struct pthread_thread_init init = *(struct pthread_thread_init*)data;
88   HeapFree(GetProcessHeap(),0,data);
89   return (DWORD)init.start_routine(init.arg);
90 }
91
92 static int wine_pthread_create(pthread_t* thread, const pthread_attr_t* attr, void*
93                                (*start_routine)(void *), void* arg)
94 {
95   HANDLE hThread;
96   struct pthread_thread_init* idata = HeapAlloc(GetProcessHeap(), 0, sizeof(struct pthread_thread_init));
97
98   idata->start_routine = start_routine;
99   idata->arg = arg;
100   hThread = CreateThread( NULL, 0, pthread_thread_start, idata, 0, (LPDWORD)thread);
101
102   if(hThread)
103     CloseHandle(hThread);
104   else
105   {
106     HeapFree(GetProcessHeap(),0,idata); /* free idata struct on failure */
107     return EAGAIN;
108   }
109
110   return 0;
111 }
112
113 static int wine_pthread_cancel(pthread_t thread)
114 {
115   HANDLE hThread = OpenThread(THREAD_ALL_ACCESS, FALSE, (DWORD)thread);
116
117   if(!TerminateThread(hThread, 0))
118   {
119     CloseHandle(hThread);
120     return EINVAL;      /* return error */
121   }
122
123   CloseHandle(hThread);
124
125   return 0;             /* return success */
126 }
127
128 static int wine_pthread_join(pthread_t thread, void **value_ptr)
129 {
130   HANDLE hThread = OpenThread(THREAD_ALL_ACCESS, FALSE, (DWORD)thread);
131
132   WaitForSingleObject(hThread, INFINITE);
133   if(!GetExitCodeThread(hThread, (LPDWORD)value_ptr))
134   {
135     CloseHandle(hThread);
136     return EINVAL; /* FIXME: make this more correctly match */
137   }                /* windows errors */
138
139   CloseHandle(hThread);
140   return 0;
141 }
142
143 /*FIXME: not sure what to do with this one... */
144 static int wine_pthread_detach(pthread_t thread)
145 {
146   P_OUTPUT("FIXME:pthread_detach\n");
147   return 0;
148 }
149
150 /***** MUTEXES *****/
151
152 static int wine_pthread_mutex_init(pthread_mutex_t *mutex,
153                                    const pthread_mutexattr_t *mutexattr)
154 {
155   /* glibc has a tendency to initialize mutexes very often, even
156      in situations where they are not really used later on.
157
158      As for us, initializing a mutex is very expensive, we postpone
159      the real initialization until the time the mutex is first used. */
160
161   ((wine_mutex)mutex)->critsect = NULL;
162   return 0;
163 }
164
165 static void mutex_real_init( pthread_mutex_t *mutex )
166 {
167   CRITICAL_SECTION *critsect = HeapAlloc(GetProcessHeap(), 0, sizeof(CRITICAL_SECTION));
168   RtlInitializeCriticalSection(critsect);
169
170   if (InterlockedCompareExchangePointer((void**)&(((wine_mutex)mutex)->critsect),critsect,NULL) != NULL) {
171     /* too late, some other thread already did it */
172     RtlDeleteCriticalSection(critsect);
173     HeapFree(GetProcessHeap(), 0, critsect);
174   }
175 }
176
177 static int wine_pthread_mutex_lock(pthread_mutex_t *mutex)
178 {
179   if (!((wine_mutex)mutex)->critsect)
180     mutex_real_init( mutex );
181
182   RtlEnterCriticalSection(((wine_mutex)mutex)->critsect);
183   return 0;
184 }
185
186 static int wine_pthread_mutex_trylock(pthread_mutex_t *mutex)
187 {
188   if (!((wine_mutex)mutex)->critsect)
189     mutex_real_init( mutex );
190
191   if (!RtlTryEnterCriticalSection(((wine_mutex)mutex)->critsect)) {
192     errno = EBUSY;
193     return -1;
194   }
195   return 0;
196 }
197
198 static int wine_pthread_mutex_unlock(pthread_mutex_t *mutex)
199 {
200   if (!((wine_mutex)mutex)->critsect) return 0;
201   RtlLeaveCriticalSection(((wine_mutex)mutex)->critsect);
202   return 0;
203 }
204
205 static int wine_pthread_mutex_destroy(pthread_mutex_t *mutex)
206 {
207   if (!((wine_mutex)mutex)->critsect) return 0;
208   if (((wine_mutex)mutex)->critsect->RecursionCount) {
209 #if 0 /* there seems to be a bug in libc6 that makes this a bad idea */
210     return EBUSY;
211 #else
212     while (((wine_mutex)mutex)->critsect->RecursionCount)
213       RtlLeaveCriticalSection(((wine_mutex)mutex)->critsect);
214 #endif
215   }
216   RtlDeleteCriticalSection(((wine_mutex)mutex)->critsect);
217   HeapFree(GetProcessHeap(), 0, ((wine_mutex)mutex)->critsect);
218   ((wine_mutex)mutex)->critsect = NULL;
219   return 0;
220 }
221
222 /***** READ-WRITE LOCKS *****/
223
224 static void rwlock_real_init(pthread_rwlock_t *rwlock)
225 {
226   RTL_RWLOCK *lock = HeapAlloc(GetProcessHeap(), 0, sizeof(RTL_RWLOCK));
227   RtlInitializeResource(lock);
228
229   if (InterlockedCompareExchangePointer((void**)&(((wine_rwlock)rwlock)->lock),lock,NULL) != NULL) {
230     /* too late, some other thread already did it */
231     RtlDeleteResource(lock);
232     HeapFree(GetProcessHeap(), 0, lock);
233   }
234 }
235
236 static int wine_pthread_rwlock_init(pthread_rwlock_t *rwlock, const pthread_rwlockattr_t *rwlock_attr)
237 {
238   ((wine_rwlock)rwlock)->lock = NULL;
239   return 0;
240 }
241
242 static int wine_pthread_rwlock_destroy(pthread_rwlock_t *rwlock)
243 {
244   if (!((wine_rwlock)rwlock)->lock) return 0;
245   RtlDeleteResource(((wine_rwlock)rwlock)->lock);
246   HeapFree(GetProcessHeap(), 0, ((wine_rwlock)rwlock)->lock);
247   return 0;
248 }
249
250 static int wine_pthread_rwlock_rdlock(pthread_rwlock_t *rwlock)
251 {
252   if (!((wine_rwlock)rwlock)->lock)
253     rwlock_real_init( rwlock );
254
255   while(TRUE)
256     if (RtlAcquireResourceShared(((wine_rwlock)rwlock)->lock, TRUE))
257       return 0;
258 }
259
260 static int wine_pthread_rwlock_tryrdlock(pthread_rwlock_t *rwlock)
261 {
262   if (!((wine_rwlock)rwlock)->lock)
263     rwlock_real_init( rwlock );
264
265   if (!RtlAcquireResourceShared(((wine_rwlock)rwlock)->lock, FALSE)) {
266     errno = EBUSY;
267     return -1;
268   }
269   return 0;
270 }
271
272 static int wine_pthread_rwlock_wrlock(pthread_rwlock_t *rwlock)
273 {
274   if (!((wine_rwlock)rwlock)->lock)
275     rwlock_real_init( rwlock );
276
277   while(TRUE)
278     if (RtlAcquireResourceExclusive(((wine_rwlock)rwlock)->lock, TRUE))
279       return 0;
280 }
281
282 static int wine_pthread_rwlock_trywrlock(pthread_rwlock_t *rwlock)
283 {
284   if (!((wine_rwlock)rwlock)->lock)
285     rwlock_real_init( rwlock );
286
287   if (!RtlAcquireResourceExclusive(((wine_rwlock)rwlock)->lock, FALSE)) {
288     errno = EBUSY;
289     return -1;
290   }
291   return 0;
292 }
293
294 static int wine_pthread_rwlock_unlock(pthread_rwlock_t *rwlock)
295 {
296   if (!((wine_rwlock)rwlock)->lock) return 0;
297   RtlReleaseResource( ((wine_rwlock)rwlock)->lock );
298   return 0;
299 }
300
301 /***** CONDITIONS *****/
302
303 /* The condition code is basically cut-and-pasted from Douglas
304  * Schmidt's paper:
305  *   "Strategies for Implementing POSIX Condition Variables on Win32",
306  * at http://www.cs.wustl.edu/~schmidt/win32-cv-1.html and
307  * http://www.cs.wustl.edu/~schmidt/win32-cv-2.html.
308  * This paper formed the basis for the condition variable
309  * impementation used in the ACE library.
310  */
311
312 /* Possible problems with ACE:
313  * - unimplemented pthread_mutexattr_init
314  */
315 typedef struct {
316   /* Number of waiting threads. */
317   int waiters_count;
318
319   /* Serialize access to <waiters_count>. */
320   CRITICAL_SECTION waiters_count_lock;
321
322   /*
323    * Semaphore used to queue up threads waiting for the condition to
324    * become signaled.
325    */
326   HANDLE sema;
327
328   /*
329    * An auto-reset event used by the broadcast/signal thread to wait
330    * for all the waiting thread(s) to wake up and be released from the
331    * semaphore.
332    */
333   HANDLE waiters_done;
334
335   /*
336    * Keeps track of whether we were broadcasting or signaling.  This
337    * allows us to optimize the code if we're just signaling.
338    */
339   size_t was_broadcast;
340 } wine_cond_detail;
341
342 /* see wine_mutex above for comments */
343 typedef struct {
344   wine_cond_detail *cond;
345 } *wine_cond;
346
347 static void wine_cond_real_init(pthread_cond_t *cond)
348 {
349   wine_cond_detail *detail = HeapAlloc(GetProcessHeap(), 0, sizeof(wine_cond_detail));
350   detail->waiters_count = 0;
351   detail->was_broadcast = 0;
352   detail->sema = CreateSemaphoreW( NULL, 0, 0x7fffffff, NULL );
353   detail->waiters_done = CreateEventW( NULL, FALSE, FALSE, NULL );
354   RtlInitializeCriticalSection (&detail->waiters_count_lock);
355
356   if (InterlockedCompareExchangePointer((void**)&(((wine_cond)cond)->cond), detail, NULL) != NULL)
357   {
358     /* too late, some other thread already did it */
359     P_OUTPUT("FIXME:pthread_cond_init:expect troubles...\n");
360     CloseHandle(detail->sema);
361     RtlDeleteCriticalSection(&detail->waiters_count_lock);
362     CloseHandle(detail->waiters_done);
363     HeapFree(GetProcessHeap(), 0, detail);
364   }
365 }
366
367 int wine_pthread_cond_init(pthread_cond_t *cond, const pthread_condattr_t *cond_attr)
368 {
369   /* The same as for wine_pthread_mutex_init, we postpone initialization
370      until condition is really used.*/
371   ((wine_cond)cond)->cond = NULL;
372   return 0;
373 }
374
375 int wine_pthread_cond_destroy(pthread_cond_t *cond)
376 {
377   wine_cond_detail *detail = ((wine_cond)cond)->cond;
378
379   if (!detail) return 0;
380   CloseHandle(detail->sema);
381   RtlDeleteCriticalSection(&detail->waiters_count_lock);
382   CloseHandle(detail->waiters_done);
383   HeapFree(GetProcessHeap(), 0, detail);
384   ((wine_cond)cond)->cond = NULL;
385   return 0;
386 }
387
388 int wine_pthread_cond_signal(pthread_cond_t *cond)
389 {
390   int have_waiters;
391   wine_cond_detail *detail;
392
393   if ( !((wine_cond)cond)->cond ) wine_cond_real_init(cond);
394   detail = ((wine_cond)cond)->cond;
395
396   RtlEnterCriticalSection (&detail->waiters_count_lock);
397   have_waiters = detail->waiters_count > 0;
398   RtlLeaveCriticalSection (&detail->waiters_count_lock);
399
400   /* If there aren't any waiters, then this is a no-op. */
401   if (have_waiters)
402     ReleaseSemaphore(detail->sema, 1, NULL);
403
404   return 0;
405 }
406
407 int wine_pthread_cond_broadcast(pthread_cond_t *cond)
408 {
409   int have_waiters = 0;
410   wine_cond_detail *detail;
411
412   if ( !((wine_cond)cond)->cond ) wine_cond_real_init(cond);
413   detail = ((wine_cond)cond)->cond;
414
415   /*
416    * This is needed to ensure that <waiters_count> and <was_broadcast> are
417    * consistent relative to each other.
418    */
419   RtlEnterCriticalSection (&detail->waiters_count_lock);
420
421   if (detail->waiters_count > 0) {
422     /*
423      * We are broadcasting, even if there is just one waiter...
424      * Record that we are broadcasting, which helps optimize
425      * <pthread_cond_wait> for the non-broadcast case.
426      */
427     detail->was_broadcast = 1;
428     have_waiters = 1;
429   }
430
431   if (have_waiters) {
432     /* Wake up all the waiters atomically. */
433     ReleaseSemaphore(detail->sema, detail->waiters_count, NULL);
434
435     RtlLeaveCriticalSection (&detail->waiters_count_lock);
436
437     /* Wait for all the awakened threads to acquire the counting semaphore. */
438     WaitForSingleObject (detail->waiters_done, INFINITE);
439
440     /*
441      * This assignment is okay, even without the <waiters_count_lock> held
442      * because no other waiter threads can wake up to access it.
443      */
444     detail->was_broadcast = 0;
445   }
446   else
447     RtlLeaveCriticalSection (&detail->waiters_count_lock);
448   return 0;
449 }
450
451 int wine_pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex)
452 {
453   wine_cond_detail *detail;
454   int last_waiter;
455
456   if ( !((wine_cond)cond)->cond ) wine_cond_real_init(cond);
457   detail = ((wine_cond)cond)->cond;
458
459   /* Avoid race conditions. */
460   RtlEnterCriticalSection (&detail->waiters_count_lock);
461   detail->waiters_count++;
462   RtlLeaveCriticalSection (&detail->waiters_count_lock);
463
464   RtlLeaveCriticalSection ( ((wine_mutex)mutex)->critsect );
465   WaitForSingleObject(detail->sema, INFINITE);
466
467   /* Reacquire lock to avoid race conditions. */
468   RtlEnterCriticalSection (&detail->waiters_count_lock);
469
470   /* We're no longer waiting... */
471   detail->waiters_count--;
472
473   /* Check to see if we're the last waiter after <pthread_cond_broadcast>. */
474   last_waiter = detail->was_broadcast && detail->waiters_count == 0;
475
476   RtlLeaveCriticalSection (&detail->waiters_count_lock);
477
478   /*
479    * If we're the last waiter thread during this particular broadcast
480    * then let all the other threads proceed.
481    */
482   if (last_waiter) SetEvent(detail->waiters_done);
483   RtlEnterCriticalSection (((wine_mutex)mutex)->critsect);
484   return 0;
485 }
486
487 int wine_pthread_cond_timedwait(pthread_cond_t *cond, pthread_mutex_t *mutex,
488                                 const struct timespec *abstime)
489 {
490   DWORD ms = abstime->tv_sec * 1000 + abstime->tv_nsec / 1000000;
491   int last_waiter;
492   wine_cond_detail *detail;
493
494   if ( !((wine_cond)cond)->cond ) wine_cond_real_init(cond);
495   detail = ((wine_cond)cond)->cond;
496
497   /* Avoid race conditions. */
498   RtlEnterCriticalSection (&detail->waiters_count_lock);
499   detail->waiters_count++;
500   RtlLeaveCriticalSection (&detail->waiters_count_lock);
501
502   RtlLeaveCriticalSection (((wine_mutex)mutex)->critsect);
503   WaitForSingleObject (detail->sema, ms);
504
505   /* Reacquire lock to avoid race conditions. */
506   RtlEnterCriticalSection (&detail->waiters_count_lock);
507
508   /* We're no longer waiting... */
509   detail->waiters_count--;
510
511   /* Check to see if we're the last waiter after <pthread_cond_broadcast>. */
512   last_waiter = detail->was_broadcast && detail->waiters_count == 0;
513
514   RtlLeaveCriticalSection (&detail->waiters_count_lock);
515
516   /*
517    * If we're the last waiter thread during this particular broadcast
518    * then let all the other threads proceed.
519    */
520   if (last_waiter) SetEvent (detail->waiters_done);
521   RtlEnterCriticalSection (((wine_mutex)mutex)->critsect);
522   return 0;
523 }
524
525 /***** MISC *****/
526
527 static pthread_t wine_pthread_self(void)
528 {
529   return (pthread_t)GetCurrentThreadId();
530 }
531
532 static int wine_pthread_equal(pthread_t thread1, pthread_t thread2)
533 {
534   return (DWORD)thread1 == (DWORD)thread2;
535 }
536
537 static void wine_pthread_exit(void *retval, char *currentframe)
538 {
539     ExitThread((DWORD)retval);
540 }
541
542 static void *wine_get_thread_data(void)
543 {
544     return NtCurrentTeb()->pthread_data;
545 }
546
547 static void wine_set_thread_data( void *data )
548 {
549     NtCurrentTeb()->pthread_data = data;
550 }
551
552 static const struct wine_pthread_functions functions =
553 {
554     wine_get_thread_data,           /* ptr_get_thread_data */
555     wine_set_thread_data,           /* ptr_set_thread_data */
556     wine_pthread_self,              /* ptr_pthread_self */
557     wine_pthread_equal,             /* ptr_pthread_equal */
558     wine_pthread_create,            /* ptr_pthread_create */
559     wine_pthread_cancel,            /* ptr_pthread_cancel */
560     wine_pthread_join,              /* ptr_pthread_join */
561     wine_pthread_detach,            /* ptr_pthread_detach */
562     wine_pthread_exit,              /* ptr_pthread_exit */
563     wine_pthread_mutex_init,        /* ptr_pthread_mutex_init */
564     wine_pthread_mutex_lock,        /* ptr_pthread_mutex_lock */
565     wine_pthread_mutex_trylock,     /* ptr_pthread_mutex_trylock */
566     wine_pthread_mutex_unlock,      /* ptr_pthread_mutex_unlock */
567     wine_pthread_mutex_destroy,     /* ptr_pthread_mutex_destroy */
568     wine_pthread_rwlock_init,       /* ptr_pthread_rwlock_init */
569     wine_pthread_rwlock_destroy,    /* ptr_pthread_rwlock_destroy */
570     wine_pthread_rwlock_rdlock,     /* ptr_pthread_rwlock_rdlock */
571     wine_pthread_rwlock_tryrdlock,  /* ptr_pthread_rwlock_tryrdlock */
572     wine_pthread_rwlock_wrlock,     /* ptr_pthread_rwlock_wrlock */
573     wine_pthread_rwlock_trywrlock,  /* ptr_pthread_rwlock_trywrlock */
574     wine_pthread_rwlock_unlock,     /* ptr_pthread_rwlock_unlock */
575     wine_pthread_cond_init,         /* ptr_pthread_cond_init */
576     wine_pthread_cond_destroy,      /* ptr_pthread_cond_destroy */
577     wine_pthread_cond_signal,       /* ptr_pthread_cond_signal */
578     wine_pthread_cond_broadcast,    /* ptr_pthread_cond_broadcast */
579     wine_pthread_cond_wait,         /* ptr_pthread_cond_wait */
580     wine_pthread_cond_timedwait     /* ptr_pthread_cond_timedwait */
581 };
582
583 #endif /* HAVE_PTHREAD_H */