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