fonts: Add a Tahoma replacement. Almost entirely based on a patch by Larry Snyder.
[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_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_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 HAVE_VALGRIND_MEMCHECK_H
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 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
340 /* Currently this probably works only for glibc2,
341  * which checks for the presence of double-underscore-prepended
342  * pthread primitives, and use them if available.
343  * If they are not available, the libc defaults to
344  * non-threadsafe operation (not good). */
345
346 #if defined(HAVE_PTHREAD_H) && (defined(__GLIBC__) || defined(__FreeBSD__))
347
348 /* adapt as necessary (a construct like this is used in glibc sources) */
349 #define strong_alias(orig, alias) \
350  asm(".globl " PSTR(alias) "\n" \
351      "\t.set " PSTR(alias) "," PSTR(orig))
352
353 struct fork_block;
354
355 /* pthread functions redirection */
356
357 struct pthread_functions
358 {
359   pid_t (*ptr_pthread_fork) (struct fork_block *);
360   int (*ptr_pthread_attr_destroy) (pthread_attr_t *);
361   int (*ptr___pthread_attr_init_2_0) (pthread_attr_t *);
362   int (*ptr___pthread_attr_init_2_1) (pthread_attr_t *);
363   int (*ptr_pthread_attr_getdetachstate) (const pthread_attr_t *, int *);
364   int (*ptr_pthread_attr_setdetachstate) (pthread_attr_t *, int);
365   int (*ptr_pthread_attr_getinheritsched) (const pthread_attr_t *, int *);
366   int (*ptr_pthread_attr_setinheritsched) (pthread_attr_t *, int);
367   int (*ptr_pthread_attr_getschedparam) (const pthread_attr_t *, struct sched_param *);
368   int (*ptr_pthread_attr_setschedparam) (pthread_attr_t *, const struct sched_param *);
369   int (*ptr_pthread_attr_getschedpolicy) (const pthread_attr_t *, int *);
370   int (*ptr_pthread_attr_setschedpolicy) (pthread_attr_t *, int);
371   int (*ptr_pthread_attr_getscope) (const pthread_attr_t *, int *);
372   int (*ptr_pthread_attr_setscope) (pthread_attr_t *, int);
373   int (*ptr_pthread_condattr_destroy) (pthread_condattr_t *);
374   int (*ptr_pthread_condattr_init) (pthread_condattr_t *);
375   int (*ptr___pthread_cond_broadcast) (pthread_cond_t *);
376   int (*ptr___pthread_cond_destroy) (pthread_cond_t *);
377   int (*ptr___pthread_cond_init) (pthread_cond_t *, const pthread_condattr_t *);
378   int (*ptr___pthread_cond_signal) (pthread_cond_t *);
379   int (*ptr___pthread_cond_wait) (pthread_cond_t *, pthread_mutex_t *);
380   int (*ptr_pthread_equal) (pthread_t, pthread_t);
381   void (*ptr___pthread_exit) (void *);
382   int (*ptr_pthread_getschedparam) (pthread_t, int *, struct sched_param *);
383   int (*ptr_pthread_setschedparam) (pthread_t, int, const struct sched_param *);
384   int (*ptr_pthread_mutex_destroy) (pthread_mutex_t *);
385   int (*ptr_pthread_mutex_init) (pthread_mutex_t *, const pthread_mutexattr_t *);
386   int (*ptr_pthread_mutex_lock) (pthread_mutex_t *);
387   int (*ptr_pthread_mutex_trylock) (pthread_mutex_t *);
388   int (*ptr_pthread_mutex_unlock) (pthread_mutex_t *);
389   pthread_t (*ptr_pthread_self) (void);
390   int (*ptr_pthread_setcancelstate) (int, int *);
391   int (*ptr_pthread_setcanceltype) (int, int *);
392   void (*ptr_pthread_do_exit) (void *retval, char *currentframe);
393   void (*ptr_pthread_cleanup_upto) (jmp_buf target, char *targetframe);
394   pthread_descr (*ptr_pthread_thread_self) (void);
395   int (*ptr_pthread_internal_tsd_set) (int key, const void *pointer);
396   void * (*ptr_pthread_internal_tsd_get) (int key);
397   void ** __attribute__ ((__const__)) (*ptr_pthread_internal_tsd_address) (int key);
398   int (*ptr_pthread_sigaction) (int sig, const struct sigaction * act, struct sigaction *oact);
399   int (*ptr_pthread_sigwait) (const sigset_t *set, int *sig);
400   int (*ptr_pthread_raise) (int sig);
401   int (*ptr___pthread_cond_timedwait) (pthread_cond_t *, pthread_mutex_t *, const struct timespec *);
402   void (*ptr__pthread_cleanup_push) (struct _pthread_cleanup_buffer * buffer, void (*routine)(void *), void * arg);
403   void (*ptr__pthread_cleanup_pop) (struct _pthread_cleanup_buffer * buffer, int execute);
404 };
405
406 static pid_t (*libc_fork)(void);
407 static int (*libc_sigaction)(int signum, const struct sigaction *act, struct sigaction *oldact);
408 static int *(*libc_pthread_init)( const struct pthread_functions *funcs );
409
410 static struct pthread_functions libc_pthread_functions;
411
412 strong_alias(__pthread_thread_self, pthread_thread_self);
413
414 /* redefine this to prevent libpthread from overriding our function pointers */
415 int *__libc_pthread_init( const struct pthread_functions *funcs )
416 {
417     return libc_multiple_threads;
418 }
419
420 typedef struct _wine_cleanup {
421   void (*routine)(void *);
422   void *arg;
423 } *wine_cleanup;
424
425 int pthread_create(pthread_t* thread, const pthread_attr_t* attr, void*
426         (*start_routine)(void *), void* arg)
427 {
428     assert( funcs.ptr_pthread_create );
429     return funcs.ptr_pthread_create( thread, attr, start_routine, arg );
430 }
431
432 int pthread_cancel(pthread_t thread)
433 {
434     assert( funcs.ptr_pthread_cancel );
435     return funcs.ptr_pthread_cancel( thread );
436 }
437
438 int pthread_join(pthread_t thread, void **value_ptr)
439 {
440     assert( funcs.ptr_pthread_join );
441     return funcs.ptr_pthread_join( thread, value_ptr );
442 }
443
444 int pthread_detach(pthread_t thread)
445 {
446     assert( funcs.ptr_pthread_detach );
447     return funcs.ptr_pthread_detach( thread );
448 }
449
450 /* FIXME: we have no equivalents in win32 for the policys */
451 /* so just keep this as a stub */
452 int pthread_attr_setschedpolicy(pthread_attr_t *attr, int policy)
453 {
454   P_OUTPUT("FIXME:pthread_attr_setschedpolicy\n");
455   return 0;
456 }
457
458 /* FIXME: no win32 equivalent for scope */
459 int pthread_attr_setscope(pthread_attr_t *attr, int scope)
460 {
461   P_OUTPUT("FIXME:pthread_attr_setscope\n");
462   return 0; /* return success */
463 }
464
465 /* FIXME: no win32 equivalent for schedule param */
466 int pthread_attr_setschedparam(pthread_attr_t *attr,
467     const struct sched_param *param)
468 {
469   P_OUTPUT("FIXME:pthread_attr_setschedparam\n");
470   return 0; /* return success */
471 }
472
473 /* FIXME */
474 int pthread_attr_setstack(pthread_attr_t *attr, void *addr, size_t size)
475 {
476   return 0; /* return success */
477 }
478
479 int __pthread_once(pthread_once_t *once_control, void (*init_routine)(void))
480 {
481     static pthread_once_t the_once = PTHREAD_ONCE_INIT;
482     int once_now;
483
484     memcpy(&once_now,&the_once,sizeof(once_now));
485     if (interlocked_cmpxchg((int*)once_control, once_now+1, once_now) == once_now)
486         (*init_routine)();
487     return 0;
488 }
489 strong_alias(__pthread_once, pthread_once);
490
491 void __pthread_kill_other_threads_np(void)
492 {
493     /* we don't need to do anything here */
494 }
495 strong_alias(__pthread_kill_other_threads_np, pthread_kill_other_threads_np);
496
497 /***** atfork *****/
498
499 #define MAX_ATFORK 8  /* libc doesn't need that many anyway */
500
501 static pthread_mutex_t atfork_mutex = PTHREAD_MUTEX_INITIALIZER;
502
503 typedef void (*atfork_handler)(void);
504 static atfork_handler atfork_prepare[MAX_ATFORK];
505 static atfork_handler atfork_parent[MAX_ATFORK];
506 static atfork_handler atfork_child[MAX_ATFORK];
507 static int atfork_count;
508
509 int __pthread_atfork(void (*prepare)(void), void (*parent)(void), void (*child)(void))
510 {
511     pthread_mutex_lock( &atfork_mutex );
512     assert( atfork_count < MAX_ATFORK );
513     atfork_prepare[atfork_count] = prepare;
514     atfork_parent[atfork_count] = parent;
515     atfork_child[atfork_count] = child;
516     atfork_count++;
517     pthread_mutex_unlock( &atfork_mutex );
518     return 0;
519 }
520 strong_alias(__pthread_atfork, pthread_atfork);
521
522 pid_t __fork(void)
523 {
524     pid_t pid;
525     int i;
526
527     if (!libc_fork)
528     {
529         libc_fork = wine_dlsym( RTLD_NEXT, "fork", NULL, 0 );
530         assert( libc_fork );
531     }
532     pthread_mutex_lock( &atfork_mutex );
533     /* prepare handlers are called in reverse insertion order */
534     for (i = atfork_count - 1; i >= 0; i--) if (atfork_prepare[i]) atfork_prepare[i]();
535     if (!(pid = libc_fork()))
536     {
537         pthread_mutex_init( &atfork_mutex, NULL );
538         for (i = 0; i < atfork_count; i++) if (atfork_child[i]) atfork_child[i]();
539     }
540     else
541     {
542         for (i = 0; i < atfork_count; i++) if (atfork_parent[i]) atfork_parent[i]();
543         pthread_mutex_unlock( &atfork_mutex );
544     }
545     return pid;
546 }
547 strong_alias(__fork, fork);
548
549 /***** MUTEXES *****/
550
551 int __pthread_mutex_init(pthread_mutex_t *mutex, const pthread_mutexattr_t *mutexattr)
552 {
553     if (!funcs.ptr_pthread_mutex_init) return 0;
554     return funcs.ptr_pthread_mutex_init( mutex, mutexattr );
555 }
556 strong_alias(__pthread_mutex_init, pthread_mutex_init);
557
558 int __pthread_mutex_lock(pthread_mutex_t *mutex)
559 {
560     if (!funcs.ptr_pthread_mutex_lock) return 0;
561     return funcs.ptr_pthread_mutex_lock( mutex );
562 }
563 strong_alias(__pthread_mutex_lock, pthread_mutex_lock);
564
565 int __pthread_mutex_trylock(pthread_mutex_t *mutex)
566 {
567     if (!funcs.ptr_pthread_mutex_trylock) return 0;
568     return funcs.ptr_pthread_mutex_trylock( mutex );
569 }
570 strong_alias(__pthread_mutex_trylock, pthread_mutex_trylock);
571
572 int __pthread_mutex_unlock(pthread_mutex_t *mutex)
573 {
574     if (!funcs.ptr_pthread_mutex_unlock) return 0;
575     return funcs.ptr_pthread_mutex_unlock( mutex );
576 }
577 strong_alias(__pthread_mutex_unlock, pthread_mutex_unlock);
578
579 int __pthread_mutex_destroy(pthread_mutex_t *mutex)
580 {
581     if (!funcs.ptr_pthread_mutex_destroy) return 0;
582     return funcs.ptr_pthread_mutex_destroy( mutex );
583 }
584 strong_alias(__pthread_mutex_destroy, pthread_mutex_destroy);
585
586
587 /***** MUTEX ATTRIBUTES *****/
588 /* just dummies, since critical sections are always recursive */
589
590 int __pthread_mutexattr_init(pthread_mutexattr_t *attr)
591 {
592   return 0;
593 }
594 strong_alias(__pthread_mutexattr_init, pthread_mutexattr_init);
595
596 int __pthread_mutexattr_destroy(pthread_mutexattr_t *attr)
597 {
598   return 0;
599 }
600 strong_alias(__pthread_mutexattr_destroy, pthread_mutexattr_destroy);
601
602 int __pthread_mutexattr_setkind_np(pthread_mutexattr_t *attr, int kind)
603 {
604   return 0;
605 }
606 strong_alias(__pthread_mutexattr_setkind_np, pthread_mutexattr_setkind_np);
607
608 int __pthread_mutexattr_getkind_np(pthread_mutexattr_t *attr, int *kind)
609 {
610   *kind = PTHREAD_MUTEX_RECURSIVE;
611   return 0;
612 }
613 strong_alias(__pthread_mutexattr_getkind_np, pthread_mutexattr_getkind_np);
614
615 int __pthread_mutexattr_settype(pthread_mutexattr_t *attr, int kind)
616 {
617   return 0;
618 }
619 strong_alias(__pthread_mutexattr_settype, pthread_mutexattr_settype);
620
621 int __pthread_mutexattr_gettype(const pthread_mutexattr_t *attr, int *kind)
622 {
623   *kind = PTHREAD_MUTEX_RECURSIVE;
624   return 0;
625 }
626 strong_alias(__pthread_mutexattr_gettype, pthread_mutexattr_gettype);
627
628
629 /***** THREAD-SPECIFIC VARIABLES (KEYS) *****/
630
631 int __pthread_key_create(pthread_key_t *key, void (*destr_function)(void *))
632 {
633     static int keycnt = FIRST_KEY;
634     *key = interlocked_xchg_add(&keycnt, 1);
635     return 0;
636 }
637 strong_alias(__pthread_key_create, pthread_key_create);
638
639 int __pthread_key_delete(pthread_key_t key)
640 {
641   return 0;
642 }
643 strong_alias(__pthread_key_delete, pthread_key_delete);
644
645 int __pthread_setspecific(pthread_key_t key, const void *pointer)
646 {
647     pthread_descr descr = __pthread_thread_self();
648     descr->key_data[key] = pointer;
649     return 0;
650 }
651 strong_alias(__pthread_setspecific, pthread_setspecific);
652
653 void *__pthread_getspecific(pthread_key_t key)
654 {
655     pthread_descr descr = __pthread_thread_self();
656     return (void *)descr->key_data[key];
657 }
658 strong_alias(__pthread_getspecific, pthread_getspecific);
659
660 static int pthread_internal_tsd_set( int key, const void *pointer )
661 {
662     pthread_descr descr = __pthread_thread_self();
663     descr->tsd_data[key] = pointer;
664     return 0;
665 }
666 int (*__libc_internal_tsd_set)(int, const void *) = pthread_internal_tsd_set;
667
668 static void *pthread_internal_tsd_get( int key )
669 {
670     pthread_descr descr = __pthread_thread_self();
671     return (void *)descr->tsd_data[key];
672 }
673 void* (*__libc_internal_tsd_get)(int) = pthread_internal_tsd_get;
674
675 static void ** __attribute__((const)) pthread_internal_tsd_address( int key )
676 {
677     pthread_descr descr = __pthread_thread_self();
678     return (void **)&descr->tsd_data[key];
679 }
680 void** (*__libc_internal_tsd_address)(int) = pthread_internal_tsd_address;
681
682 /***** "EXCEPTION" FRAMES *****/
683 /* not implemented right now */
684
685 void _pthread_cleanup_push(struct _pthread_cleanup_buffer *buffer, void (*routine)(void *), void *arg)
686 {
687   ((wine_cleanup)buffer)->routine = routine;
688   ((wine_cleanup)buffer)->arg = arg;
689 }
690
691 void _pthread_cleanup_pop(struct _pthread_cleanup_buffer *buffer, int execute)
692 {
693   if (execute) (*(((wine_cleanup)buffer)->routine))(((wine_cleanup)buffer)->arg);
694 }
695
696 void _pthread_cleanup_push_defer(struct _pthread_cleanup_buffer *buffer, void (*routine)(void *), void *arg)
697 {
698   _pthread_cleanup_push(buffer, routine, arg);
699 }
700
701 void _pthread_cleanup_pop_restore(struct _pthread_cleanup_buffer *buffer, int execute)
702 {
703   _pthread_cleanup_pop(buffer, execute);
704 }
705
706 void __pthread_cleanup_upto(jmp_buf target, char *frame)
707 {
708     /* FIXME */
709 }
710
711 /***** CONDITIONS *****/
712
713 int __pthread_cond_init(pthread_cond_t *cond, const pthread_condattr_t *cond_attr)
714 {
715     if (!funcs.ptr_pthread_cond_init) return 0;
716     return funcs.ptr_pthread_cond_init(cond, cond_attr);
717 }
718 strong_alias(__pthread_cond_init, pthread_cond_init);
719
720 int __pthread_cond_destroy(pthread_cond_t *cond)
721 {
722     if (!funcs.ptr_pthread_cond_destroy) return 0;
723     return funcs.ptr_pthread_cond_destroy(cond);
724 }
725 strong_alias(__pthread_cond_destroy, pthread_cond_destroy);
726
727 int __pthread_cond_signal(pthread_cond_t *cond)
728 {
729     if (!funcs.ptr_pthread_cond_signal) return 0;
730     return funcs.ptr_pthread_cond_signal(cond);
731 }
732 strong_alias(__pthread_cond_signal, pthread_cond_signal);
733
734 int __pthread_cond_broadcast(pthread_cond_t *cond)
735 {
736     if (!funcs.ptr_pthread_cond_broadcast) return 0;
737     return funcs.ptr_pthread_cond_broadcast(cond);
738 }
739 strong_alias(__pthread_cond_broadcast, pthread_cond_broadcast);
740
741 int __pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex)
742 {
743     if (!funcs.ptr_pthread_cond_wait) return 0;
744     return funcs.ptr_pthread_cond_wait(cond, mutex);
745 }
746 strong_alias(__pthread_cond_wait, pthread_cond_wait);
747
748 int __pthread_cond_timedwait(pthread_cond_t *cond, pthread_mutex_t *mutex, const struct timespec *abstime)
749 {
750     if (!funcs.ptr_pthread_cond_timedwait) return 0;
751     return funcs.ptr_pthread_cond_timedwait(cond, mutex, abstime);
752 }
753 strong_alias(__pthread_cond_timedwait, pthread_cond_timedwait);
754
755 /**** CONDITION ATTRIBUTES *****/
756 /* not implemented right now */
757
758 int pthread_condattr_init(pthread_condattr_t *attr)
759 {
760   return 0;
761 }
762
763 int pthread_condattr_destroy(pthread_condattr_t *attr)
764 {
765   return 0;
766 }
767
768 /***** READ-WRITE LOCKS *****/
769
770 int __pthread_rwlock_init(pthread_rwlock_t *rwlock, const pthread_rwlockattr_t *rwlock_attr)
771 {
772     assert( funcs.ptr_pthread_rwlock_init );
773     return funcs.ptr_pthread_rwlock_init( rwlock, rwlock_attr );
774 }
775 strong_alias(__pthread_rwlock_init, pthread_rwlock_init);
776
777 int __pthread_rwlock_destroy(pthread_rwlock_t *rwlock)
778 {
779     assert( funcs.ptr_pthread_rwlock_destroy );
780     return funcs.ptr_pthread_rwlock_destroy( rwlock );
781 }
782 strong_alias(__pthread_rwlock_destroy, pthread_rwlock_destroy);
783
784 int __pthread_rwlock_rdlock(pthread_rwlock_t *rwlock)
785 {
786     if (!funcs.ptr_pthread_rwlock_rdlock) return 0;
787     return funcs.ptr_pthread_rwlock_rdlock( rwlock );
788 }
789 strong_alias(__pthread_rwlock_rdlock, pthread_rwlock_rdlock);
790
791 int __pthread_rwlock_tryrdlock(pthread_rwlock_t *rwlock)
792 {
793     assert( funcs.ptr_pthread_rwlock_tryrdlock );
794     return funcs.ptr_pthread_rwlock_tryrdlock( rwlock );
795 }
796 strong_alias(__pthread_rwlock_tryrdlock, pthread_rwlock_tryrdlock);
797
798 int __pthread_rwlock_wrlock(pthread_rwlock_t *rwlock)
799 {
800     assert( funcs.ptr_pthread_rwlock_wrlock );
801     return funcs.ptr_pthread_rwlock_wrlock( rwlock );
802 }
803 strong_alias(__pthread_rwlock_wrlock, pthread_rwlock_wrlock);
804
805 int __pthread_rwlock_trywrlock(pthread_rwlock_t *rwlock)
806 {
807     assert( funcs.ptr_pthread_rwlock_trywrlock );
808     return funcs.ptr_pthread_rwlock_trywrlock( rwlock );
809 }
810 strong_alias(__pthread_rwlock_trywrlock, pthread_rwlock_trywrlock);
811
812 int __pthread_rwlock_unlock(pthread_rwlock_t *rwlock)
813 {
814     if (!funcs.ptr_pthread_rwlock_unlock) return 0;
815     return funcs.ptr_pthread_rwlock_unlock( rwlock );
816 }
817 strong_alias(__pthread_rwlock_unlock, pthread_rwlock_unlock);
818
819 /**** READ-WRITE LOCK ATTRIBUTES *****/
820 /* not implemented right now */
821
822 int pthread_rwlockattr_init(pthread_rwlockattr_t *attr)
823 {
824   return 0;
825 }
826
827 int __pthread_rwlockattr_destroy(pthread_rwlockattr_t *attr)
828 {
829   return 0;
830 }
831 strong_alias(__pthread_rwlockattr_destroy, pthread_rwlockattr_destroy);
832
833 int pthread_rwlockattr_getkind_np(const pthread_rwlockattr_t *attr, int *pref)
834 {
835   *pref = 0;
836   return 0;
837 }
838
839 int pthread_rwlockattr_setkind_np(pthread_rwlockattr_t *attr, int pref)
840 {
841   return 0;
842 }
843
844 /***** MISC *****/
845
846 pthread_t pthread_self(void)
847 {
848     assert( funcs.ptr_pthread_self );
849     return funcs.ptr_pthread_self();
850 }
851
852 int pthread_equal(pthread_t thread1, pthread_t thread2)
853 {
854     assert( funcs.ptr_pthread_equal );
855     return funcs.ptr_pthread_equal( thread1, thread2 );
856 }
857
858 void __pthread_do_exit(void *retval, char *currentframe)
859 {
860     assert( funcs.ptr_pthread_exit );
861     return funcs.ptr_pthread_exit( retval, currentframe );
862 }
863
864 void __pthread_exit(void *retval)
865 {
866     __pthread_do_exit( retval, NULL );
867 }
868 strong_alias(__pthread_exit, pthread_exit);
869
870 int pthread_setcancelstate(int state, int *oldstate)
871 {
872     pthread_descr descr = __pthread_thread_self();
873     if (oldstate) *oldstate = descr->cancel_state;
874     descr->cancel_state = state;
875     return 0;
876 }
877
878 int pthread_setcanceltype(int type, int *oldtype)
879 {
880     pthread_descr descr = __pthread_thread_self();
881     if (oldtype) *oldtype = descr->cancel_type;
882     descr->cancel_type = type;
883     return 0;
884 }
885
886 /***** ANTI-OVERRIDES *****/
887 /* pthreads tries to override these, point them back to libc */
888
889 int sigaction(int signum, const struct sigaction *act, struct sigaction *oldact)
890 {
891     if (!libc_sigaction)
892     {
893         libc_sigaction = wine_dlsym( RTLD_NEXT, "sigaction", NULL, 0 );
894         assert( libc_sigaction );
895     }
896     return libc_sigaction(signum, act, oldact);
897 }
898
899 void __pthread_initialize(void)
900 {
901     static int done;
902
903     if (!done)
904     {
905         done = 1;
906         /* check for exported epoll_create to detect glibc versions that we cannot support */
907         if (wine_dlsym( RTLD_DEFAULT, "epoll_create", NULL, 0 ))
908         {
909             static const char warning[] =
910                 "wine: glibc >= 2.3 without NPTL or TLS is not a supported combination.\n"
911                 "      It will most likely crash. Please upgrade to a glibc with NPTL support.\n";
912             write( 2, warning, sizeof(warning)-1 );
913         }
914         libc_fork = wine_dlsym( RTLD_NEXT, "fork", NULL, 0 );
915         libc_sigaction = wine_dlsym( RTLD_NEXT, "sigaction", NULL, 0 );
916         libc_uselocale = wine_dlsym( RTLD_DEFAULT, "uselocale", NULL, 0 );
917         libc_pthread_init = wine_dlsym( RTLD_NEXT, "__libc_pthread_init", NULL, 0 );
918         if (libc_pthread_init) libc_multiple_threads = libc_pthread_init( &libc_pthread_functions );
919     }
920 }
921
922 #ifdef __GNUC__
923 static void init(void) __attribute__((constructor));
924 static void init(void)
925 {
926     __pthread_initialize();
927 }
928 #endif
929
930 static struct pthread_functions libc_pthread_functions =
931 {
932     NULL,                          /* ptr_pthread_fork */
933     NULL, /* FIXME */              /* ptr_pthread_attr_destroy */
934     NULL, /* FIXME */              /* ptr___pthread_attr_init_2_0 */
935     NULL, /* FIXME */              /* ptr___pthread_attr_init_2_1 */
936     NULL, /* FIXME */              /* ptr_pthread_attr_getdetachstate */
937     NULL, /* FIXME */              /* ptr_pthread_attr_setdetachstate */
938     NULL, /* FIXME */              /* ptr_pthread_attr_getinheritsched */
939     NULL, /* FIXME */              /* ptr_pthread_attr_setinheritsched */
940     NULL, /* FIXME */              /* ptr_pthread_attr_getschedparam */
941     pthread_attr_setschedparam,    /* ptr_pthread_attr_setschedparam */
942     NULL, /* FIXME */              /* ptr_pthread_attr_getschedpolicy */
943     NULL, /* FIXME */              /* ptr_pthread_attr_setschedpolicy */
944     NULL, /* FIXME */              /* ptr_pthread_attr_getscope */
945     NULL, /* FIXME */              /* ptr_pthread_attr_setscope */
946     pthread_condattr_destroy,      /* ptr_pthread_condattr_destroy */
947     pthread_condattr_init,         /* ptr_pthread_condattr_init */
948     __pthread_cond_broadcast,      /* ptr___pthread_cond_broadcast */
949     __pthread_cond_destroy,        /* ptr___pthread_cond_destroy */
950     __pthread_cond_init,           /* ptr___pthread_cond_init */
951     __pthread_cond_signal,         /* ptr___pthread_cond_signal */
952     __pthread_cond_wait,           /* ptr___pthread_cond_wait */
953     pthread_equal,                 /* ptr_pthread_equal */
954     __pthread_exit,                /* ptr___pthread_exit */
955     NULL, /* FIXME */              /* ptr_pthread_getschedparam */
956     NULL, /* FIXME */              /* ptr_pthread_setschedparam */
957     __pthread_mutex_destroy,       /* ptr_pthread_mutex_destroy */
958     __pthread_mutex_init,          /* ptr_pthread_mutex_init */
959     __pthread_mutex_lock,          /* ptr_pthread_mutex_lock */
960     __pthread_mutex_trylock,       /* ptr_pthread_mutex_trylock */
961     __pthread_mutex_unlock,        /* ptr_pthread_mutex_unlock */
962     pthread_self,                  /* ptr_pthread_self */
963     pthread_setcancelstate,        /* ptr_pthread_setcancelstate */
964     pthread_setcanceltype,         /* ptr_pthread_setcanceltype */
965     __pthread_do_exit,             /* ptr_pthread_do_exit */
966     __pthread_cleanup_upto,        /* ptr_pthread_cleanup_upto */
967     __pthread_thread_self,         /* ptr_pthread_thread_self */
968     pthread_internal_tsd_set,      /* ptr_pthread_internal_tsd_set */
969     pthread_internal_tsd_get,      /* ptr_pthread_internal_tsd_get */
970     pthread_internal_tsd_address,  /* ptr_pthread_internal_tsd_address */
971     NULL,                          /* ptr_pthread_sigaction */
972     NULL,                          /* ptr_pthread_sigwait */
973     NULL,                          /* ptr_pthread_raise */
974     __pthread_cond_timedwait,      /* ptr___pthread_cond_timedwait */
975     _pthread_cleanup_push,         /* ptr__pthread_cleanup_push */
976     _pthread_cleanup_pop           /* ptr__pthread_cleanup_pop */
977 };
978
979 #endif /* HAVE_PTHREAD_H && (__GLIBC__ || __FREEBSD__) */