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