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