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