wined3d: Const correctness fixes for glsl_shader.c.
[wine] / loader / kthread.c
1 /*
2  * pthread emulation based on kernel threads
3  *
4  * We can't use pthreads directly, so why not let libcs
5  * that want pthreads use Wine's own threading instead...
6  *
7  * Copyright 1999 Ove Kåven
8  * Copyright 2003 Alexandre Julliard
9  *
10  * This library is free software; you can redistribute it and/or
11  * modify it under the terms of the GNU Lesser General Public
12  * License as published by the Free Software Foundation; either
13  * version 2.1 of the License, or (at your option) any later version.
14  *
15  * This library is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
18  * Lesser General Public License for more details.
19  *
20  * You should have received a copy of the GNU Lesser General Public
21  * License along with this library; if not, write to the Free Software
22  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
23  */
24
25 #include "config.h"
26 #include "wine/port.h"
27
28 struct _pthread_cleanup_buffer;
29
30 #include <assert.h>
31 #include <errno.h>
32 #include <stdlib.h>
33 #include <signal.h>
34 #include <setjmp.h>
35 #ifdef HAVE_UNISTD_H
36 # include <unistd.h>
37 #endif
38 #include <string.h>
39 #include <sys/types.h>
40 #ifdef HAVE_SYS_SOCKET_H
41 # include <sys/socket.h>
42 #endif
43 #ifdef HAVE_SYS_MMAN_H
44 #include <sys/mman.h>
45 #endif
46 #ifdef HAVE_NETINET_IN_H
47 # include <netinet/in.h>
48 #endif
49 #ifdef HAVE_ARPA_NAMESER_H
50 # include <arpa/nameser.h>
51 #endif
52 #ifdef HAVE_RESOLV_H
53 # include <resolv.h>
54 #endif
55 #ifdef HAVE_VALGRIND_VALGRIND_H
56 #include <valgrind/valgrind.h>
57 #endif
58 #ifdef HAVE_SYS_SYSCALL_H
59 # include <sys/syscall.h>
60 #endif
61 #ifdef HAVE_SCHED_H
62 #include <sched.h>
63 #endif
64
65 #include "wine/library.h"
66 #include "wine/pthread.h"
67
68 #define P_OUTPUT(stuff) write(2,stuff,strlen(stuff))
69
70 #define PSTR(str) __ASM_NAME(#str)
71
72 static struct wine_pthread_callbacks funcs;
73
74 /* thread descriptor */
75
76 #define FIRST_KEY 0
77 #define MAX_KEYS 16 /* libc6 doesn't use that many, but... */
78 #define MAX_TSD  16
79
80 struct pthread_descr_struct
81 {
82     char               dummy[2048];
83     int                thread_errno;
84     int                thread_h_errno;
85     int                cancel_state;
86     int                cancel_type;
87     struct __res_state res_state;
88     const void        *key_data[MAX_KEYS];  /* for normal pthread keys */
89     const void        *tsd_data[MAX_TSD];   /* for libc internal tsd variables */
90 };
91
92 typedef struct pthread_descr_struct *pthread_descr;
93
94 static struct pthread_descr_struct initial_descr;
95
96 pthread_descr __pthread_thread_self(void)
97 {
98     struct pthread_descr_struct *descr;
99     if (!funcs.ptr_get_thread_data) return &initial_descr;
100     descr = funcs.ptr_get_thread_data();
101     if (!descr) return &initial_descr;
102     return descr;
103 }
104
105 static int (*libc_uselocale)(int set);
106 static int *libc_multiple_threads;
107
108 /***********************************************************************
109  *           __errno_location/__error/__errno/___errno/__thr_errno
110  *
111  * Get the per-thread errno location.
112  */
113 int *__errno_location(void)                            /* Linux */
114 {
115     pthread_descr descr = __pthread_thread_self();
116     return &descr->thread_errno;
117 }
118 int *__error(void)     { return __errno_location(); }  /* FreeBSD */
119 int *__errno(void)     { return __errno_location(); }  /* NetBSD */
120 int *___errno(void)    { return __errno_location(); }  /* Solaris */
121 int *__thr_errno(void) { return __errno_location(); }  /* UnixWare */
122
123 /***********************************************************************
124  *           __h_errno_location
125  *
126  * Get the per-thread h_errno location.
127  */
128 int *__h_errno_location(void)
129 {
130     pthread_descr descr = __pthread_thread_self();
131     return &descr->thread_h_errno;
132 }
133
134 struct __res_state *__res_state(void)
135 {
136     pthread_descr descr = __pthread_thread_self();
137     return &descr->res_state;
138 }
139
140 static inline void writejump( const char *symbol, void *dest )
141 {
142 #if defined(__GLIBC__) && defined(__i386__)
143     unsigned char *addr = wine_dlsym( RTLD_NEXT, symbol, NULL, 0 );
144
145     if (!addr) return;
146
147     /* write a relative jump at the function address */
148     mprotect((void*)((unsigned int)addr & ~(getpagesize()-1)), 5, PROT_READ|PROT_EXEC|PROT_WRITE);
149     addr[0] = 0xe9;
150     *(int *)(addr+1) = (unsigned char *)dest - (addr + 5);
151     mprotect((void*)((unsigned int)addr & ~(getpagesize()-1)), 5, PROT_READ|PROT_EXEC);
152
153 # ifdef VALGRIND_DISCARD_TRANSLATIONS
154     VALGRIND_DISCARD_TRANSLATIONS( addr, 5 );
155 # endif
156 #endif  /* __GLIBC__ && __i386__ */
157 }
158
159 /* temporary stacks used on thread exit */
160 #define TEMP_STACK_SIZE 1024
161 #define NB_TEMP_STACKS  8
162 static char temp_stacks[NB_TEMP_STACKS][TEMP_STACK_SIZE];
163 static int next_temp_stack;  /* next temp stack to use */
164
165 /***********************************************************************
166  *           get_temp_stack
167  *
168  * Get a temporary stack address to run the thread exit code on.
169  */
170 static inline char *get_temp_stack(void)
171 {
172     unsigned int next = interlocked_xchg_add( &next_temp_stack, 1 );
173     return temp_stacks[next % NB_TEMP_STACKS] + TEMP_STACK_SIZE;
174 }
175
176
177 /***********************************************************************
178  *           cleanup_thread
179  *
180  * Cleanup the remains of a thread. Runs on a temporary stack.
181  */
182 static void cleanup_thread( void *ptr )
183 {
184     /* copy the info structure since it is on the stack we will free */
185     struct wine_pthread_thread_info info = *(struct wine_pthread_thread_info *)ptr;
186     wine_ldt_free_fs( info.teb_sel );
187     if (info.stack_size) munmap( info.stack_base, info.stack_size );
188     if (info.teb_size) munmap( info.teb_base, info.teb_size );
189     _exit( info.exit_status );
190 }
191
192
193 /***********************************************************************
194  *           init_process
195  *
196  * Initialization for a newly created process.
197  */
198 static void init_process( const struct wine_pthread_callbacks *callbacks, size_t size )
199 {
200     memcpy( &funcs, callbacks, min( size, sizeof(funcs) ));
201     funcs.ptr_set_thread_data( &initial_descr );
202 }
203
204
205 /***********************************************************************
206  *           init_thread
207  *
208  * Initialization for a newly created thread.
209  */
210 static void init_thread( struct wine_pthread_thread_info *info )
211 {
212     struct pthread_descr_struct *descr;
213
214     if (funcs.ptr_set_thread_data)
215     {
216         descr = calloc( 1, sizeof(*descr) );
217         funcs.ptr_set_thread_data( descr );
218         if (libc_multiple_threads) *libc_multiple_threads = 1;
219     }
220     else  /* first thread */
221     {
222         descr = &initial_descr;
223         writejump( "__errno_location", __errno_location );
224         writejump( "__h_errno_location", __h_errno_location );
225         writejump( "__res_state", __res_state );
226     }
227     descr->cancel_state = PTHREAD_CANCEL_ENABLE;
228     descr->cancel_type  = PTHREAD_CANCEL_ASYNCHRONOUS;
229     if (libc_uselocale) libc_uselocale( -1 /*LC_GLOBAL_LOCALE*/ );
230 }
231
232
233 /***********************************************************************
234  *           create_thread
235  */
236 static int create_thread( struct wine_pthread_thread_info *info )
237 {
238     if (!info->stack_base)
239     {
240         info->stack_base = wine_anon_mmap( NULL, info->stack_size, PROT_READ | PROT_WRITE, 0 );
241         if (info->stack_base == (void *)-1) return -1;
242     }
243 #ifdef HAVE_CLONE
244     if (clone( (int (*)(void *))info->entry, (char *)info->stack_base + info->stack_size,
245                CLONE_VM | CLONE_FS | CLONE_FILES | SIGCHLD, info ) < 0)
246         return -1;
247     return 0;
248 #elif defined(HAVE_RFORK)
249     {
250         void **sp = (void **)((char *)info->stack_base + info->stack_size);
251         *--sp = info;
252         *--sp = 0;
253         *--sp = info->entry;
254         __asm__ __volatile__(
255             "pushl %2;\n\t"             /* flags */
256             "pushl $0;\n\t"             /* 0 ? */
257             "movl %1,%%eax;\n\t"        /* SYS_rfork */
258             ".byte 0x9a; .long 0; .word 7;\n\t" /* lcall 7:0... FreeBSD syscall */
259             "cmpl $0, %%edx;\n\t"
260             "je 1f;\n\t"
261             "movl %0,%%esp;\n\t"        /* child -> new thread */
262             "ret;\n"
263             "1:\n\t"                    /* parent -> caller thread */
264             "addl $8,%%esp" :
265             : "r" (sp), "r" (SYS_rfork), "r" (RFPROC | RFMEM | RFTHREAD)
266             : "eax", "edx");
267         return 0;
268     }
269 #endif
270     return -1;
271 }
272
273
274 /***********************************************************************
275  *           init_current_teb
276  *
277  * Set the current TEB for a new thread.
278  */
279 static void init_current_teb( struct wine_pthread_thread_info *info )
280 {
281     /* On the i386, the current thread is in the %fs register */
282     LDT_ENTRY fs_entry;
283
284     wine_ldt_set_base( &fs_entry, info->teb_base );
285     wine_ldt_set_limit( &fs_entry, info->teb_size - 1 );
286     wine_ldt_set_flags( &fs_entry, WINE_LDT_FLAGS_DATA|WINE_LDT_FLAGS_32BIT );
287     wine_ldt_init_fs( info->teb_sel, &fs_entry );
288
289     /* set pid and tid */
290     info->pid = getpid();
291     info->tid = -1;
292 }
293
294
295 /***********************************************************************
296  *           get_current_teb
297  */
298 static void *get_current_teb(void)
299 {
300     void *ret;
301     __asm__( ".byte 0x64\n\tmovl 0x18,%0" : "=r" (ret) );
302     return ret;
303 }
304
305
306 /***********************************************************************
307  *           exit_thread
308  */
309 static void DECLSPEC_NORETURN exit_thread( struct wine_pthread_thread_info *info )
310 {
311     wine_switch_to_stack( cleanup_thread, info, get_temp_stack() );
312 }
313
314
315 /***********************************************************************
316  *           abort_thread
317  */
318 static void DECLSPEC_NORETURN abort_thread( long status )
319 {
320     _exit( status );
321 }
322
323
324 /***********************************************************************
325  *           pthread_functions
326  */
327 static const struct wine_pthread_functions pthread_functions =
328 {
329     init_process,
330     init_thread,
331     create_thread,
332     init_current_teb,
333     get_current_teb,
334     exit_thread,
335     abort_thread,
336     sigprocmask
337 };
338
339 void init_pthread_functions(void)
340 {
341     wine_pthread_set_functions( &pthread_functions, sizeof(pthread_functions) );
342 }
343
344 /* Currently this probably works only for glibc2,
345  * which checks for the presence of double-underscore-prepended
346  * pthread primitives, and use them if available.
347  * If they are not available, the libc defaults to
348  * non-threadsafe operation (not good). */
349
350 #if defined(HAVE_PTHREAD_H) && (defined(__GLIBC__) || defined(__FreeBSD__))
351
352 /* adapt as necessary (a construct like this is used in glibc sources) */
353 #define strong_alias(orig, alias) \
354  asm(".globl " PSTR(alias) "\n" \
355      "\t.set " PSTR(alias) "," PSTR(orig))
356
357 struct fork_block;
358
359 /* pthread functions redirection */
360
361 struct pthread_functions
362 {
363   pid_t (*ptr_pthread_fork) (struct fork_block *);
364   int (*ptr_pthread_attr_destroy) (pthread_attr_t *);
365   int (*ptr___pthread_attr_init_2_0) (pthread_attr_t *);
366   int (*ptr___pthread_attr_init_2_1) (pthread_attr_t *);
367   int (*ptr_pthread_attr_getdetachstate) (const pthread_attr_t *, int *);
368   int (*ptr_pthread_attr_setdetachstate) (pthread_attr_t *, int);
369   int (*ptr_pthread_attr_getinheritsched) (const pthread_attr_t *, int *);
370   int (*ptr_pthread_attr_setinheritsched) (pthread_attr_t *, int);
371   int (*ptr_pthread_attr_getschedparam) (const pthread_attr_t *, struct sched_param *);
372   int (*ptr_pthread_attr_setschedparam) (pthread_attr_t *, const struct sched_param *);
373   int (*ptr_pthread_attr_getschedpolicy) (const pthread_attr_t *, int *);
374   int (*ptr_pthread_attr_setschedpolicy) (pthread_attr_t *, int);
375   int (*ptr_pthread_attr_getscope) (const pthread_attr_t *, int *);
376   int (*ptr_pthread_attr_setscope) (pthread_attr_t *, int);
377   int (*ptr_pthread_condattr_destroy) (pthread_condattr_t *);
378   int (*ptr_pthread_condattr_init) (pthread_condattr_t *);
379   int (*ptr___pthread_cond_broadcast) (pthread_cond_t *);
380   int (*ptr___pthread_cond_destroy) (pthread_cond_t *);
381   int (*ptr___pthread_cond_init) (pthread_cond_t *, const pthread_condattr_t *);
382   int (*ptr___pthread_cond_signal) (pthread_cond_t *);
383   int (*ptr___pthread_cond_wait) (pthread_cond_t *, pthread_mutex_t *);
384   int (*ptr_pthread_equal) (pthread_t, pthread_t);
385   void (*ptr___pthread_exit) (void *);
386   int (*ptr_pthread_getschedparam) (pthread_t, int *, struct sched_param *);
387   int (*ptr_pthread_setschedparam) (pthread_t, int, const struct sched_param *);
388   int (*ptr_pthread_mutex_destroy) (pthread_mutex_t *);
389   int (*ptr_pthread_mutex_init) (pthread_mutex_t *, const pthread_mutexattr_t *);
390   int (*ptr_pthread_mutex_lock) (pthread_mutex_t *);
391   int (*ptr_pthread_mutex_trylock) (pthread_mutex_t *);
392   int (*ptr_pthread_mutex_unlock) (pthread_mutex_t *);
393   pthread_t (*ptr_pthread_self) (void);
394   int (*ptr_pthread_setcancelstate) (int, int *);
395   int (*ptr_pthread_setcanceltype) (int, int *);
396   void (*ptr_pthread_do_exit) (void *retval, char *currentframe);
397   void (*ptr_pthread_cleanup_upto) (jmp_buf target, char *targetframe);
398   pthread_descr (*ptr_pthread_thread_self) (void);
399   int (*ptr_pthread_internal_tsd_set) (int key, const void *pointer);
400   void * (*ptr_pthread_internal_tsd_get) (int key);
401   void ** __attribute__ ((__const__)) (*ptr_pthread_internal_tsd_address) (int key);
402   int (*ptr_pthread_sigaction) (int sig, const struct sigaction * act, struct sigaction *oact);
403   int (*ptr_pthread_sigwait) (const sigset_t *set, int *sig);
404   int (*ptr_pthread_raise) (int sig);
405   int (*ptr___pthread_cond_timedwait) (pthread_cond_t *, pthread_mutex_t *, const struct timespec *);
406   void (*ptr__pthread_cleanup_push) (struct _pthread_cleanup_buffer * buffer, void (*routine)(void *), void * arg);
407   void (*ptr__pthread_cleanup_pop) (struct _pthread_cleanup_buffer * buffer, int execute);
408 };
409
410 static pid_t (*libc_fork)(void);
411 static int (*libc_sigaction)(int signum, const struct sigaction *act, struct sigaction *oldact);
412 static int *(*libc_pthread_init)( const struct pthread_functions *funcs );
413
414 static struct pthread_functions libc_pthread_functions;
415
416 strong_alias(__pthread_thread_self, pthread_thread_self);
417
418 /* redefine this to prevent libpthread from overriding our function pointers */
419 int *__libc_pthread_init( const struct pthread_functions *funcs )
420 {
421     return libc_multiple_threads;
422 }
423
424 typedef struct _wine_cleanup {
425   void (*routine)(void *);
426   void *arg;
427 } *wine_cleanup;
428
429 int pthread_create(pthread_t* thread, const pthread_attr_t* attr, void*
430         (*start_routine)(void *), void* arg)
431 {
432     assert( funcs.ptr_pthread_create );
433     return funcs.ptr_pthread_create( thread, attr, start_routine, arg );
434 }
435
436 int pthread_cancel(pthread_t thread)
437 {
438     assert( funcs.ptr_pthread_cancel );
439     return funcs.ptr_pthread_cancel( thread );
440 }
441
442 int pthread_join(pthread_t thread, void **value_ptr)
443 {
444     assert( funcs.ptr_pthread_join );
445     return funcs.ptr_pthread_join( thread, value_ptr );
446 }
447
448 int pthread_detach(pthread_t thread)
449 {
450     assert( funcs.ptr_pthread_detach );
451     return funcs.ptr_pthread_detach( thread );
452 }
453
454 /* FIXME: we have no equivalents in win32 for the policys */
455 /* so just keep this as a stub */
456 int pthread_attr_setschedpolicy(pthread_attr_t *attr, int policy)
457 {
458   P_OUTPUT("FIXME:pthread_attr_setschedpolicy\n");
459   return 0;
460 }
461
462 /* FIXME: no win32 equivalent for scope */
463 int pthread_attr_setscope(pthread_attr_t *attr, int scope)
464 {
465   P_OUTPUT("FIXME:pthread_attr_setscope\n");
466   return 0; /* return success */
467 }
468
469 /* FIXME: no win32 equivalent for schedule param */
470 int pthread_attr_setschedparam(pthread_attr_t *attr,
471     const struct sched_param *param)
472 {
473   P_OUTPUT("FIXME:pthread_attr_setschedparam\n");
474   return 0; /* return success */
475 }
476
477 /* FIXME */
478 int pthread_attr_setstack(pthread_attr_t *attr, void *addr, size_t size)
479 {
480   return 0; /* return success */
481 }
482
483 int __pthread_once(pthread_once_t *once_control, void (*init_routine)(void))
484 {
485     static pthread_once_t the_once = PTHREAD_ONCE_INIT;
486     int once_now;
487
488     memcpy(&once_now,&the_once,sizeof(once_now));
489     if (interlocked_cmpxchg((int*)once_control, once_now+1, once_now) == once_now)
490         (*init_routine)();
491     return 0;
492 }
493 strong_alias(__pthread_once, pthread_once);
494
495 void __pthread_kill_other_threads_np(void)
496 {
497     /* we don't need to do anything here */
498 }
499 strong_alias(__pthread_kill_other_threads_np, pthread_kill_other_threads_np);
500
501 /***** atfork *****/
502
503 #define MAX_ATFORK 8  /* libc doesn't need that many anyway */
504
505 static pthread_mutex_t atfork_mutex = PTHREAD_MUTEX_INITIALIZER;
506
507 typedef void (*atfork_handler)(void);
508 static atfork_handler atfork_prepare[MAX_ATFORK];
509 static atfork_handler atfork_parent[MAX_ATFORK];
510 static atfork_handler atfork_child[MAX_ATFORK];
511 static int atfork_count;
512
513 int __pthread_atfork(void (*prepare)(void), void (*parent)(void), void (*child)(void))
514 {
515     pthread_mutex_lock( &atfork_mutex );
516     assert( atfork_count < MAX_ATFORK );
517     atfork_prepare[atfork_count] = prepare;
518     atfork_parent[atfork_count] = parent;
519     atfork_child[atfork_count] = child;
520     atfork_count++;
521     pthread_mutex_unlock( &atfork_mutex );
522     return 0;
523 }
524 strong_alias(__pthread_atfork, pthread_atfork);
525
526 pid_t __fork(void)
527 {
528     pid_t pid;
529     int i;
530
531     if (!libc_fork)
532     {
533         libc_fork = wine_dlsym( RTLD_NEXT, "fork", NULL, 0 );
534         assert( libc_fork );
535     }
536     pthread_mutex_lock( &atfork_mutex );
537     /* prepare handlers are called in reverse insertion order */
538     for (i = atfork_count - 1; i >= 0; i--) if (atfork_prepare[i]) atfork_prepare[i]();
539     if (!(pid = libc_fork()))
540     {
541         pthread_mutex_init( &atfork_mutex, NULL );
542         for (i = 0; i < atfork_count; i++) if (atfork_child[i]) atfork_child[i]();
543     }
544     else
545     {
546         for (i = 0; i < atfork_count; i++) if (atfork_parent[i]) atfork_parent[i]();
547         pthread_mutex_unlock( &atfork_mutex );
548     }
549     return pid;
550 }
551 strong_alias(__fork, fork);
552
553 /***** MUTEXES *****/
554
555 int __pthread_mutex_init(pthread_mutex_t *mutex, const pthread_mutexattr_t *mutexattr)
556 {
557     if (!funcs.ptr_pthread_mutex_init) return 0;
558     return funcs.ptr_pthread_mutex_init( mutex, mutexattr );
559 }
560 strong_alias(__pthread_mutex_init, pthread_mutex_init);
561
562 int __pthread_mutex_lock(pthread_mutex_t *mutex)
563 {
564     if (!funcs.ptr_pthread_mutex_lock) return 0;
565     return funcs.ptr_pthread_mutex_lock( mutex );
566 }
567 strong_alias(__pthread_mutex_lock, pthread_mutex_lock);
568
569 int __pthread_mutex_trylock(pthread_mutex_t *mutex)
570 {
571     if (!funcs.ptr_pthread_mutex_trylock) return 0;
572     return funcs.ptr_pthread_mutex_trylock( mutex );
573 }
574 strong_alias(__pthread_mutex_trylock, pthread_mutex_trylock);
575
576 int __pthread_mutex_unlock(pthread_mutex_t *mutex)
577 {
578     if (!funcs.ptr_pthread_mutex_unlock) return 0;
579     return funcs.ptr_pthread_mutex_unlock( mutex );
580 }
581 strong_alias(__pthread_mutex_unlock, pthread_mutex_unlock);
582
583 int __pthread_mutex_destroy(pthread_mutex_t *mutex)
584 {
585     if (!funcs.ptr_pthread_mutex_destroy) return 0;
586     return funcs.ptr_pthread_mutex_destroy( mutex );
587 }
588 strong_alias(__pthread_mutex_destroy, pthread_mutex_destroy);
589
590
591 /***** MUTEX ATTRIBUTES *****/
592 /* just dummies, since critical sections are always recursive */
593
594 int __pthread_mutexattr_init(pthread_mutexattr_t *attr)
595 {
596   return 0;
597 }
598 strong_alias(__pthread_mutexattr_init, pthread_mutexattr_init);
599
600 int __pthread_mutexattr_destroy(pthread_mutexattr_t *attr)
601 {
602   return 0;
603 }
604 strong_alias(__pthread_mutexattr_destroy, pthread_mutexattr_destroy);
605
606 int __pthread_mutexattr_setkind_np(pthread_mutexattr_t *attr, int kind)
607 {
608   return 0;
609 }
610 strong_alias(__pthread_mutexattr_setkind_np, pthread_mutexattr_setkind_np);
611
612 int __pthread_mutexattr_getkind_np(pthread_mutexattr_t *attr, int *kind)
613 {
614   *kind = PTHREAD_MUTEX_RECURSIVE;
615   return 0;
616 }
617 strong_alias(__pthread_mutexattr_getkind_np, pthread_mutexattr_getkind_np);
618
619 int __pthread_mutexattr_settype(pthread_mutexattr_t *attr, int kind)
620 {
621   return 0;
622 }
623 strong_alias(__pthread_mutexattr_settype, pthread_mutexattr_settype);
624
625 int __pthread_mutexattr_gettype(const pthread_mutexattr_t *attr, int *kind)
626 {
627   *kind = PTHREAD_MUTEX_RECURSIVE;
628   return 0;
629 }
630 strong_alias(__pthread_mutexattr_gettype, pthread_mutexattr_gettype);
631
632
633 /***** THREAD-SPECIFIC VARIABLES (KEYS) *****/
634
635 int __pthread_key_create(pthread_key_t *key, void (*destr_function)(void *))
636 {
637     static int keycnt = FIRST_KEY;
638     *key = interlocked_xchg_add(&keycnt, 1);
639     return 0;
640 }
641 strong_alias(__pthread_key_create, pthread_key_create);
642
643 int __pthread_key_delete(pthread_key_t key)
644 {
645   return 0;
646 }
647 strong_alias(__pthread_key_delete, pthread_key_delete);
648
649 int __pthread_setspecific(pthread_key_t key, const void *pointer)
650 {
651     pthread_descr descr = __pthread_thread_self();
652     descr->key_data[key] = pointer;
653     return 0;
654 }
655 strong_alias(__pthread_setspecific, pthread_setspecific);
656
657 void *__pthread_getspecific(pthread_key_t key)
658 {
659     pthread_descr descr = __pthread_thread_self();
660     return (void *)descr->key_data[key];
661 }
662 strong_alias(__pthread_getspecific, pthread_getspecific);
663
664 static int pthread_internal_tsd_set( int key, const void *pointer )
665 {
666     pthread_descr descr = __pthread_thread_self();
667     descr->tsd_data[key] = pointer;
668     return 0;
669 }
670 int (*__libc_internal_tsd_set)(int, const void *) = pthread_internal_tsd_set;
671
672 static void *pthread_internal_tsd_get( int key )
673 {
674     pthread_descr descr = __pthread_thread_self();
675     return (void *)descr->tsd_data[key];
676 }
677 void* (*__libc_internal_tsd_get)(int) = pthread_internal_tsd_get;
678
679 static void ** __attribute__((const)) pthread_internal_tsd_address( int key )
680 {
681     pthread_descr descr = __pthread_thread_self();
682     return (void **)&descr->tsd_data[key];
683 }
684 void** (*__libc_internal_tsd_address)(int) = pthread_internal_tsd_address;
685
686 /***** "EXCEPTION" FRAMES *****/
687 /* not implemented right now */
688
689 void _pthread_cleanup_push(struct _pthread_cleanup_buffer *buffer, void (*routine)(void *), void *arg)
690 {
691   ((wine_cleanup)buffer)->routine = routine;
692   ((wine_cleanup)buffer)->arg = arg;
693 }
694
695 void _pthread_cleanup_pop(struct _pthread_cleanup_buffer *buffer, int execute)
696 {
697   if (execute) (*(((wine_cleanup)buffer)->routine))(((wine_cleanup)buffer)->arg);
698 }
699
700 void _pthread_cleanup_push_defer(struct _pthread_cleanup_buffer *buffer, void (*routine)(void *), void *arg)
701 {
702   _pthread_cleanup_push(buffer, routine, arg);
703 }
704
705 void _pthread_cleanup_pop_restore(struct _pthread_cleanup_buffer *buffer, int execute)
706 {
707   _pthread_cleanup_pop(buffer, execute);
708 }
709
710 void __pthread_cleanup_upto(jmp_buf target, char *frame)
711 {
712     /* FIXME */
713 }
714
715 /***** CONDITIONS *****/
716
717 int __pthread_cond_init(pthread_cond_t *cond, const pthread_condattr_t *cond_attr)
718 {
719     if (!funcs.ptr_pthread_cond_init) return 0;
720     return funcs.ptr_pthread_cond_init(cond, cond_attr);
721 }
722 strong_alias(__pthread_cond_init, pthread_cond_init);
723
724 int __pthread_cond_destroy(pthread_cond_t *cond)
725 {
726     if (!funcs.ptr_pthread_cond_destroy) return 0;
727     return funcs.ptr_pthread_cond_destroy(cond);
728 }
729 strong_alias(__pthread_cond_destroy, pthread_cond_destroy);
730
731 int __pthread_cond_signal(pthread_cond_t *cond)
732 {
733     if (!funcs.ptr_pthread_cond_signal) return 0;
734     return funcs.ptr_pthread_cond_signal(cond);
735 }
736 strong_alias(__pthread_cond_signal, pthread_cond_signal);
737
738 int __pthread_cond_broadcast(pthread_cond_t *cond)
739 {
740     if (!funcs.ptr_pthread_cond_broadcast) return 0;
741     return funcs.ptr_pthread_cond_broadcast(cond);
742 }
743 strong_alias(__pthread_cond_broadcast, pthread_cond_broadcast);
744
745 int __pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex)
746 {
747     if (!funcs.ptr_pthread_cond_wait) return 0;
748     return funcs.ptr_pthread_cond_wait(cond, mutex);
749 }
750 strong_alias(__pthread_cond_wait, pthread_cond_wait);
751
752 int __pthread_cond_timedwait(pthread_cond_t *cond, pthread_mutex_t *mutex, const struct timespec *abstime)
753 {
754     if (!funcs.ptr_pthread_cond_timedwait) return 0;
755     return funcs.ptr_pthread_cond_timedwait(cond, mutex, abstime);
756 }
757 strong_alias(__pthread_cond_timedwait, pthread_cond_timedwait);
758
759 /**** CONDITION ATTRIBUTES *****/
760 /* not implemented right now */
761
762 int pthread_condattr_init(pthread_condattr_t *attr)
763 {
764   return 0;
765 }
766
767 int pthread_condattr_destroy(pthread_condattr_t *attr)
768 {
769   return 0;
770 }
771
772 /***** READ-WRITE LOCKS *****/
773
774 int __pthread_rwlock_init(pthread_rwlock_t *rwlock, const pthread_rwlockattr_t *rwlock_attr)
775 {
776     assert( funcs.ptr_pthread_rwlock_init );
777     return funcs.ptr_pthread_rwlock_init( rwlock, rwlock_attr );
778 }
779 strong_alias(__pthread_rwlock_init, pthread_rwlock_init);
780
781 int __pthread_rwlock_destroy(pthread_rwlock_t *rwlock)
782 {
783     assert( funcs.ptr_pthread_rwlock_destroy );
784     return funcs.ptr_pthread_rwlock_destroy( rwlock );
785 }
786 strong_alias(__pthread_rwlock_destroy, pthread_rwlock_destroy);
787
788 int __pthread_rwlock_rdlock(pthread_rwlock_t *rwlock)
789 {
790     if (!funcs.ptr_pthread_rwlock_rdlock) return 0;
791     return funcs.ptr_pthread_rwlock_rdlock( rwlock );
792 }
793 strong_alias(__pthread_rwlock_rdlock, pthread_rwlock_rdlock);
794
795 int __pthread_rwlock_tryrdlock(pthread_rwlock_t *rwlock)
796 {
797     assert( funcs.ptr_pthread_rwlock_tryrdlock );
798     return funcs.ptr_pthread_rwlock_tryrdlock( rwlock );
799 }
800 strong_alias(__pthread_rwlock_tryrdlock, pthread_rwlock_tryrdlock);
801
802 int __pthread_rwlock_wrlock(pthread_rwlock_t *rwlock)
803 {
804     assert( funcs.ptr_pthread_rwlock_wrlock );
805     return funcs.ptr_pthread_rwlock_wrlock( rwlock );
806 }
807 strong_alias(__pthread_rwlock_wrlock, pthread_rwlock_wrlock);
808
809 int __pthread_rwlock_trywrlock(pthread_rwlock_t *rwlock)
810 {
811     assert( funcs.ptr_pthread_rwlock_trywrlock );
812     return funcs.ptr_pthread_rwlock_trywrlock( rwlock );
813 }
814 strong_alias(__pthread_rwlock_trywrlock, pthread_rwlock_trywrlock);
815
816 int __pthread_rwlock_unlock(pthread_rwlock_t *rwlock)
817 {
818     if (!funcs.ptr_pthread_rwlock_unlock) return 0;
819     return funcs.ptr_pthread_rwlock_unlock( rwlock );
820 }
821 strong_alias(__pthread_rwlock_unlock, pthread_rwlock_unlock);
822
823 /**** READ-WRITE LOCK ATTRIBUTES *****/
824 /* not implemented right now */
825
826 int pthread_rwlockattr_init(pthread_rwlockattr_t *attr)
827 {
828   return 0;
829 }
830
831 int __pthread_rwlockattr_destroy(pthread_rwlockattr_t *attr)
832 {
833   return 0;
834 }
835 strong_alias(__pthread_rwlockattr_destroy, pthread_rwlockattr_destroy);
836
837 int pthread_rwlockattr_getkind_np(const pthread_rwlockattr_t *attr, int *pref)
838 {
839   *pref = 0;
840   return 0;
841 }
842
843 int pthread_rwlockattr_setkind_np(pthread_rwlockattr_t *attr, int pref)
844 {
845   return 0;
846 }
847
848 /***** MISC *****/
849
850 pthread_t pthread_self(void)
851 {
852     assert( funcs.ptr_pthread_self );
853     return funcs.ptr_pthread_self();
854 }
855
856 int pthread_equal(pthread_t thread1, pthread_t thread2)
857 {
858     assert( funcs.ptr_pthread_equal );
859     return funcs.ptr_pthread_equal( thread1, thread2 );
860 }
861
862 void __pthread_do_exit(void *retval, char *currentframe)
863 {
864     assert( funcs.ptr_pthread_exit );
865     return funcs.ptr_pthread_exit( retval, currentframe );
866 }
867
868 void __pthread_exit(void *retval)
869 {
870     __pthread_do_exit( retval, NULL );
871 }
872 strong_alias(__pthread_exit, pthread_exit);
873
874 int pthread_setcancelstate(int state, int *oldstate)
875 {
876     pthread_descr descr = __pthread_thread_self();
877     if (oldstate) *oldstate = descr->cancel_state;
878     descr->cancel_state = state;
879     return 0;
880 }
881
882 int pthread_setcanceltype(int type, int *oldtype)
883 {
884     pthread_descr descr = __pthread_thread_self();
885     if (oldtype) *oldtype = descr->cancel_type;
886     descr->cancel_type = type;
887     return 0;
888 }
889
890 /***** ANTI-OVERRIDES *****/
891 /* pthreads tries to override these, point them back to libc */
892
893 int sigaction(int signum, const struct sigaction *act, struct sigaction *oldact)
894 {
895     if (!libc_sigaction)
896     {
897         libc_sigaction = wine_dlsym( RTLD_NEXT, "sigaction", NULL, 0 );
898         assert( libc_sigaction );
899     }
900     return libc_sigaction(signum, act, oldact);
901 }
902
903 void __pthread_initialize(void)
904 {
905     static int done;
906
907     if (!done)
908     {
909         done = 1;
910         /* check for exported epoll_create to detect glibc versions that we cannot support */
911         if (wine_dlsym( RTLD_DEFAULT, "epoll_create", NULL, 0 ))
912         {
913             static const char warning[] =
914                 "wine: glibc >= 2.3 without NPTL or TLS is not a supported combination.\n"
915                 "      It will most likely crash. Please upgrade to a glibc with NPTL support.\n";
916             write( 2, warning, sizeof(warning)-1 );
917         }
918         libc_fork = wine_dlsym( RTLD_NEXT, "fork", NULL, 0 );
919         libc_sigaction = wine_dlsym( RTLD_NEXT, "sigaction", NULL, 0 );
920         libc_uselocale = wine_dlsym( RTLD_DEFAULT, "uselocale", NULL, 0 );
921         libc_pthread_init = wine_dlsym( RTLD_NEXT, "__libc_pthread_init", NULL, 0 );
922         if (libc_pthread_init) libc_multiple_threads = libc_pthread_init( &libc_pthread_functions );
923     }
924 }
925
926 #ifdef __GNUC__
927 static void init(void) __attribute__((constructor));
928 static void init(void)
929 {
930     __pthread_initialize();
931 }
932 #endif
933
934 static struct pthread_functions libc_pthread_functions =
935 {
936     NULL,                          /* ptr_pthread_fork */
937     NULL, /* FIXME */              /* ptr_pthread_attr_destroy */
938     NULL, /* FIXME */              /* ptr___pthread_attr_init_2_0 */
939     NULL, /* FIXME */              /* ptr___pthread_attr_init_2_1 */
940     NULL, /* FIXME */              /* ptr_pthread_attr_getdetachstate */
941     NULL, /* FIXME */              /* ptr_pthread_attr_setdetachstate */
942     NULL, /* FIXME */              /* ptr_pthread_attr_getinheritsched */
943     NULL, /* FIXME */              /* ptr_pthread_attr_setinheritsched */
944     NULL, /* FIXME */              /* ptr_pthread_attr_getschedparam */
945     pthread_attr_setschedparam,    /* ptr_pthread_attr_setschedparam */
946     NULL, /* FIXME */              /* ptr_pthread_attr_getschedpolicy */
947     NULL, /* FIXME */              /* ptr_pthread_attr_setschedpolicy */
948     NULL, /* FIXME */              /* ptr_pthread_attr_getscope */
949     NULL, /* FIXME */              /* ptr_pthread_attr_setscope */
950     pthread_condattr_destroy,      /* ptr_pthread_condattr_destroy */
951     pthread_condattr_init,         /* ptr_pthread_condattr_init */
952     __pthread_cond_broadcast,      /* ptr___pthread_cond_broadcast */
953     __pthread_cond_destroy,        /* ptr___pthread_cond_destroy */
954     __pthread_cond_init,           /* ptr___pthread_cond_init */
955     __pthread_cond_signal,         /* ptr___pthread_cond_signal */
956     __pthread_cond_wait,           /* ptr___pthread_cond_wait */
957     pthread_equal,                 /* ptr_pthread_equal */
958     __pthread_exit,                /* ptr___pthread_exit */
959     NULL, /* FIXME */              /* ptr_pthread_getschedparam */
960     NULL, /* FIXME */              /* ptr_pthread_setschedparam */
961     __pthread_mutex_destroy,       /* ptr_pthread_mutex_destroy */
962     __pthread_mutex_init,          /* ptr_pthread_mutex_init */
963     __pthread_mutex_lock,          /* ptr_pthread_mutex_lock */
964     __pthread_mutex_trylock,       /* ptr_pthread_mutex_trylock */
965     __pthread_mutex_unlock,        /* ptr_pthread_mutex_unlock */
966     pthread_self,                  /* ptr_pthread_self */
967     pthread_setcancelstate,        /* ptr_pthread_setcancelstate */
968     pthread_setcanceltype,         /* ptr_pthread_setcanceltype */
969     __pthread_do_exit,             /* ptr_pthread_do_exit */
970     __pthread_cleanup_upto,        /* ptr_pthread_cleanup_upto */
971     __pthread_thread_self,         /* ptr_pthread_thread_self */
972     pthread_internal_tsd_set,      /* ptr_pthread_internal_tsd_set */
973     pthread_internal_tsd_get,      /* ptr_pthread_internal_tsd_get */
974     pthread_internal_tsd_address,  /* ptr_pthread_internal_tsd_address */
975     NULL,                          /* ptr_pthread_sigaction */
976     NULL,                          /* ptr_pthread_sigwait */
977     NULL,                          /* ptr_pthread_raise */
978     __pthread_cond_timedwait,      /* ptr___pthread_cond_timedwait */
979     _pthread_cleanup_push,         /* ptr__pthread_cleanup_push */
980     _pthread_cleanup_pop           /* ptr__pthread_cleanup_pop */
981 };
982
983 #endif /* HAVE_PTHREAD_H && (__GLIBC__ || __FREEBSD__) */