Fix the case of product and company names.
[wine] / scheduler / pthread.c
1 /*
2  * pthread emulation for re-entrant libcs
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 #ifndef HAVE_NPTL
29
30 struct _pthread_cleanup_buffer;
31
32 #include <assert.h>
33 #include <errno.h>
34 #include <stdlib.h>
35 #include <signal.h>
36 #include <setjmp.h>
37 #ifdef HAVE_UNISTD_H
38 # include <unistd.h>
39 #endif
40 #include <string.h>
41 #include <sys/types.h>
42 #if HAVE_SYS_SOCKET_H
43 # include <sys/socket.h>
44 #endif
45 #ifdef HAVE_SYS_MMAN_H
46 #include <sys/mman.h>
47 #endif
48 #ifdef HAVE_NETINET_IN_H
49 # include <netinet/in.h>
50 #endif
51 #ifdef HAVE_RESOLV_H
52 # include <resolv.h>
53 #endif
54 #ifdef HAVE_VALGRIND_MEMCHECK_H
55 #include <valgrind/memcheck.h>
56 #endif
57
58 #include "wine/pthread.h"
59
60 #define P_OUTPUT(stuff) write(2,stuff,strlen(stuff))
61
62 #define PSTR(str) __ASM_NAME(#str)
63
64 static struct wine_pthread_functions funcs;
65
66 /* thread descriptor */
67
68 #define FIRST_KEY 0
69 #define MAX_KEYS 16 /* libc6 doesn't use that many, but... */
70 #define MAX_TSD  16
71
72 struct pthread_descr_struct
73 {
74     char               dummy[2048];
75     int                thread_errno;
76     int                thread_h_errno;
77     int                cancel_state;
78     int                cancel_type;
79     struct __res_state res_state;
80     const void        *key_data[MAX_KEYS];  /* for normal pthread keys */
81     const void        *tsd_data[MAX_TSD];   /* for libc internal tsd variables */
82 };
83
84 typedef struct pthread_descr_struct *pthread_descr;
85
86 static struct pthread_descr_struct initial_descr;
87
88 pthread_descr __pthread_thread_self(void)
89 {
90     struct pthread_descr_struct *descr;
91     if (!funcs.ptr_get_thread_data) return &initial_descr;
92     descr = funcs.ptr_get_thread_data();
93     if (!descr) return &initial_descr;
94     return descr;
95 }
96
97 static int (*libc_uselocale)(int set);
98 static int *libc_multiple_threads;
99
100 /***********************************************************************
101  *           __errno_location/__error/__errno/___errno/__thr_errno
102  *
103  * Get the per-thread errno location.
104  */
105 int *__errno_location(void)                            /* Linux */
106 {
107     pthread_descr descr = __pthread_thread_self();
108     return &descr->thread_errno;
109 }
110 int *__error(void)     { return __errno_location(); }  /* FreeBSD */
111 int *__errno(void)     { return __errno_location(); }  /* NetBSD */
112 int *___errno(void)    { return __errno_location(); }  /* Solaris */
113 int *__thr_errno(void) { return __errno_location(); }  /* UnixWare */
114
115 /***********************************************************************
116  *           __h_errno_location
117  *
118  * Get the per-thread h_errno location.
119  */
120 int *__h_errno_location(void)
121 {
122     pthread_descr descr = __pthread_thread_self();
123     return &descr->thread_h_errno;
124 }
125
126
127 static inline void writejump( const char *symbol, void *dest )
128 {
129 #if defined(__GLIBC__) && defined(__i386__)
130     unsigned char *addr = dlsym( RTLD_NEXT, symbol );
131
132     if (!addr) return;
133
134     /* write a relative jump at the function address */
135     mprotect((void*)((unsigned int)addr & ~(getpagesize()-1)), 5, PROT_READ|PROT_EXEC|PROT_WRITE);
136     addr[0] = 0xe9;
137     *(int *)(addr+1) = (unsigned char *)dest - (addr + 5);
138     mprotect((void*)((unsigned int)addr & ~(getpagesize()-1)), 5, PROT_READ|PROT_EXEC);
139
140 # ifdef HAVE_VALGRIND_MEMCHECK_H
141     VALGRIND_DISCARD_TRANSLATIONS( addr, 5 );
142 # endif
143 #endif  /* __GLIBC__ && __i386__ */
144 }
145
146 /***********************************************************************
147  *           wine_pthread_init_process
148  *
149  * Initialization for a newly created process.
150  */
151 void wine_pthread_init_process( const struct wine_pthread_functions *functions )
152 {
153     memcpy( &funcs, functions, sizeof(funcs) );
154     funcs.ptr_set_thread_data( &initial_descr );
155     initial_descr.cancel_state = PTHREAD_CANCEL_ENABLE;
156     initial_descr.cancel_type  = PTHREAD_CANCEL_ASYNCHRONOUS;
157     writejump( "__errno_location", __errno_location );
158     writejump( "__h_errno_location", __h_errno_location );
159     writejump( "__res_state", __res_state );
160     if (libc_uselocale) libc_uselocale( -1 /*LC_GLOBAL_LOCALE*/ );
161 }
162
163
164 /***********************************************************************
165  *           wine_pthread_init_thread
166  *
167  * Initialization for a newly created thread.
168  */
169 void wine_pthread_init_thread(void)
170 {
171     if (funcs.ptr_set_thread_data)
172     {
173         struct pthread_descr_struct *descr = calloc( 1, sizeof(*descr) );
174
175         funcs.ptr_set_thread_data( descr );
176         descr->cancel_state = PTHREAD_CANCEL_ENABLE;
177         descr->cancel_type  = PTHREAD_CANCEL_ASYNCHRONOUS;
178         if (libc_multiple_threads) *libc_multiple_threads = 1;
179         if (libc_uselocale) libc_uselocale( -1 /*LC_GLOBAL_LOCALE*/ );
180     }
181     /* else it's the first thread, init will be done in wine_pthread_init_process */
182 }
183
184
185 /* Currently this probably works only for glibc2,
186  * which checks for the presence of double-underscore-prepended
187  * pthread primitives, and use them if available.
188  * If they are not available, the libc defaults to
189  * non-threadsafe operation (not good). */
190
191 #if defined(__GLIBC__) || defined(__FreeBSD__)
192
193 #ifndef __USE_UNIX98
194 #define __USE_UNIX98
195 #endif
196
197 #include <pthread.h>
198
199 /* adapt as necessary (a construct like this is used in glibc sources) */
200 #define strong_alias(orig, alias) \
201  asm(".globl " PSTR(alias) "\n" \
202      "\t.set " PSTR(alias) "," PSTR(orig))
203
204 struct fork_block;
205
206 /* pthread functions redirection */
207
208 struct pthread_functions
209 {
210   pid_t (*ptr_pthread_fork) (struct fork_block *);
211   int (*ptr_pthread_attr_destroy) (pthread_attr_t *);
212   int (*ptr___pthread_attr_init_2_0) (pthread_attr_t *);
213   int (*ptr___pthread_attr_init_2_1) (pthread_attr_t *);
214   int (*ptr_pthread_attr_getdetachstate) (const pthread_attr_t *, int *);
215   int (*ptr_pthread_attr_setdetachstate) (pthread_attr_t *, int);
216   int (*ptr_pthread_attr_getinheritsched) (const pthread_attr_t *, int *);
217   int (*ptr_pthread_attr_setinheritsched) (pthread_attr_t *, int);
218   int (*ptr_pthread_attr_getschedparam) (const pthread_attr_t *, struct sched_param *);
219   int (*ptr_pthread_attr_setschedparam) (pthread_attr_t *, const struct sched_param *);
220   int (*ptr_pthread_attr_getschedpolicy) (const pthread_attr_t *, int *);
221   int (*ptr_pthread_attr_setschedpolicy) (pthread_attr_t *, int);
222   int (*ptr_pthread_attr_getscope) (const pthread_attr_t *, int *);
223   int (*ptr_pthread_attr_setscope) (pthread_attr_t *, int);
224   int (*ptr_pthread_condattr_destroy) (pthread_condattr_t *);
225   int (*ptr_pthread_condattr_init) (pthread_condattr_t *);
226   int (*ptr___pthread_cond_broadcast) (pthread_cond_t *);
227   int (*ptr___pthread_cond_destroy) (pthread_cond_t *);
228   int (*ptr___pthread_cond_init) (pthread_cond_t *, const pthread_condattr_t *);
229   int (*ptr___pthread_cond_signal) (pthread_cond_t *);
230   int (*ptr___pthread_cond_wait) (pthread_cond_t *, pthread_mutex_t *);
231   int (*ptr_pthread_equal) (pthread_t, pthread_t);
232   void (*ptr___pthread_exit) (void *);
233   int (*ptr_pthread_getschedparam) (pthread_t, int *, struct sched_param *);
234   int (*ptr_pthread_setschedparam) (pthread_t, int, const struct sched_param *);
235   int (*ptr_pthread_mutex_destroy) (pthread_mutex_t *);
236   int (*ptr_pthread_mutex_init) (pthread_mutex_t *, const pthread_mutexattr_t *);
237   int (*ptr_pthread_mutex_lock) (pthread_mutex_t *);
238   int (*ptr_pthread_mutex_trylock) (pthread_mutex_t *);
239   int (*ptr_pthread_mutex_unlock) (pthread_mutex_t *);
240   pthread_t (*ptr_pthread_self) (void);
241   int (*ptr_pthread_setcancelstate) (int, int *);
242   int (*ptr_pthread_setcanceltype) (int, int *);
243   void (*ptr_pthread_do_exit) (void *retval, char *currentframe);
244   void (*ptr_pthread_cleanup_upto) (jmp_buf target, char *targetframe);
245   pthread_descr (*ptr_pthread_thread_self) (void);
246   int (*ptr_pthread_internal_tsd_set) (int key, const void *pointer);
247   void * (*ptr_pthread_internal_tsd_get) (int key);
248   void ** __attribute__ ((__const__)) (*ptr_pthread_internal_tsd_address) (int key);
249   int (*ptr_pthread_sigaction) (int sig, const struct sigaction * act, struct sigaction *oact);
250   int (*ptr_pthread_sigwait) (const sigset_t *set, int *sig);
251   int (*ptr_pthread_raise) (int sig);
252 };
253
254 static pid_t (*libc_fork)(void);
255 static int (*libc_sigaction)(int signum, const struct sigaction *act, struct sigaction *oldact);
256 static int *(*libc_pthread_init)( const struct pthread_functions *funcs );
257
258 static struct pthread_functions libc_pthread_functions;
259
260 strong_alias(__pthread_thread_self, pthread_thread_self);
261
262 struct __res_state *__res_state(void)
263 {
264     pthread_descr descr = __pthread_thread_self();
265     return &descr->res_state;
266 }
267
268 /* redefine this to prevent libpthread from overriding our function pointers */
269 int *__libc_pthread_init( const struct pthread_functions *funcs )
270 {
271     return libc_multiple_threads;
272 }
273
274 typedef struct _wine_cleanup {
275   void (*routine)(void *);
276   void *arg;
277 } *wine_cleanup;
278
279 int pthread_create(pthread_t* thread, const pthread_attr_t* attr, void*
280         (*start_routine)(void *), void* arg)
281 {
282     assert( funcs.ptr_pthread_create );
283     return funcs.ptr_pthread_create( thread, attr, start_routine, arg );
284 }
285
286 int pthread_cancel(pthread_t thread)
287 {
288     assert( funcs.ptr_pthread_cancel );
289     return funcs.ptr_pthread_cancel( thread );
290 }
291
292 int pthread_join(pthread_t thread, void **value_ptr)
293 {
294     assert( funcs.ptr_pthread_join );
295     return funcs.ptr_pthread_join( thread, value_ptr );
296 }
297
298 int pthread_detach(pthread_t thread)
299 {
300     assert( funcs.ptr_pthread_detach );
301     return funcs.ptr_pthread_detach( thread );
302 }
303
304 /* FIXME: we have no equivalents in win32 for the policys */
305 /* so just keep this as a stub */
306 int pthread_attr_setschedpolicy(pthread_attr_t *attr, int policy)
307 {
308   P_OUTPUT("FIXME:pthread_attr_setschedpolicy\n");
309   return 0;
310 }
311
312 /* FIXME: no win32 equivalent for scope */
313 int pthread_attr_setscope(pthread_attr_t *attr, int scope)
314 {
315   P_OUTPUT("FIXME:pthread_attr_setscope\n");
316   return 0; /* return success */
317 }
318
319 /* FIXME: no win32 equivalent for schedule param */
320 int pthread_attr_setschedparam(pthread_attr_t *attr,
321     const struct sched_param *param)
322 {
323   P_OUTPUT("FIXME:pthread_attr_setschedparam\n");
324   return 0; /* return success */
325 }
326
327 /* FIXME */
328 int pthread_attr_setstack(pthread_attr_t *attr, void *addr, size_t size)
329 {
330   return 0; /* return success */
331 }
332
333 int __pthread_once(pthread_once_t *once_control, void (*init_routine)(void))
334 {
335     static pthread_once_t the_once = PTHREAD_ONCE_INIT;
336     long once_now;
337
338     memcpy(&once_now,&the_once,sizeof(once_now));
339     if (interlocked_cmpxchg((long*)once_control, once_now+1, once_now) == once_now)
340         (*init_routine)();
341     return 0;
342 }
343 strong_alias(__pthread_once, pthread_once);
344
345 void __pthread_kill_other_threads_np(void)
346 {
347     /* we don't need to do anything here */
348 }
349 strong_alias(__pthread_kill_other_threads_np, pthread_kill_other_threads_np);
350
351 /***** atfork *****/
352
353 #define MAX_ATFORK 8  /* libc doesn't need that many anyway */
354
355 static pthread_mutex_t atfork_mutex = PTHREAD_MUTEX_INITIALIZER;
356
357 typedef void (*atfork_handler)();
358 static atfork_handler atfork_prepare[MAX_ATFORK];
359 static atfork_handler atfork_parent[MAX_ATFORK];
360 static atfork_handler atfork_child[MAX_ATFORK];
361 static int atfork_count;
362
363 int __pthread_atfork(void (*prepare)(void), void (*parent)(void), void (*child)(void))
364 {
365     pthread_mutex_lock( &atfork_mutex );
366     assert( atfork_count < MAX_ATFORK );
367     atfork_prepare[atfork_count] = prepare;
368     atfork_parent[atfork_count] = parent;
369     atfork_child[atfork_count] = child;
370     atfork_count++;
371     pthread_mutex_unlock( &atfork_mutex );
372     return 0;
373 }
374 strong_alias(__pthread_atfork, pthread_atfork);
375
376 pid_t __fork(void)
377 {
378     pid_t pid;
379     int i;
380
381     if (!libc_fork)
382     {
383         libc_fork = dlsym( RTLD_NEXT, "fork" );
384         assert( libc_fork );
385     }
386     pthread_mutex_lock( &atfork_mutex );
387     /* prepare handlers are called in reverse insertion order */
388     for (i = atfork_count - 1; i >= 0; i--) if (atfork_prepare[i]) atfork_prepare[i]();
389     if (!(pid = libc_fork()))
390     {
391         pthread_mutex_init( &atfork_mutex, NULL );
392         for (i = 0; i < atfork_count; i++) if (atfork_child[i]) atfork_child[i]();
393     }
394     else
395     {
396         for (i = 0; i < atfork_count; i++) if (atfork_parent[i]) atfork_parent[i]();
397         pthread_mutex_unlock( &atfork_mutex );
398     }
399     return pid;
400 }
401 strong_alias(__fork, fork);
402
403 /***** MUTEXES *****/
404
405 int __pthread_mutex_init(pthread_mutex_t *mutex, const pthread_mutexattr_t *mutexattr)
406 {
407     if (!funcs.ptr_pthread_mutex_init) return 0;
408     return funcs.ptr_pthread_mutex_init( mutex, mutexattr );
409 }
410 strong_alias(__pthread_mutex_init, pthread_mutex_init);
411
412 int __pthread_mutex_lock(pthread_mutex_t *mutex)
413 {
414     if (!funcs.ptr_pthread_mutex_lock) return 0;
415     return funcs.ptr_pthread_mutex_lock( mutex );
416 }
417 strong_alias(__pthread_mutex_lock, pthread_mutex_lock);
418
419 int __pthread_mutex_trylock(pthread_mutex_t *mutex)
420 {
421     if (!funcs.ptr_pthread_mutex_trylock) return 0;
422     return funcs.ptr_pthread_mutex_trylock( mutex );
423 }
424 strong_alias(__pthread_mutex_trylock, pthread_mutex_trylock);
425
426 int __pthread_mutex_unlock(pthread_mutex_t *mutex)
427 {
428     if (!funcs.ptr_pthread_mutex_unlock) return 0;
429     return funcs.ptr_pthread_mutex_unlock( mutex );
430 }
431 strong_alias(__pthread_mutex_unlock, pthread_mutex_unlock);
432
433 int __pthread_mutex_destroy(pthread_mutex_t *mutex)
434 {
435     if (!funcs.ptr_pthread_mutex_destroy) return 0;
436     return funcs.ptr_pthread_mutex_destroy( mutex );
437 }
438 strong_alias(__pthread_mutex_destroy, pthread_mutex_destroy);
439
440
441 /***** MUTEX ATTRIBUTES *****/
442 /* just dummies, since critical sections are always recursive */
443
444 int __pthread_mutexattr_init(pthread_mutexattr_t *attr)
445 {
446   return 0;
447 }
448 strong_alias(__pthread_mutexattr_init, pthread_mutexattr_init);
449
450 int __pthread_mutexattr_destroy(pthread_mutexattr_t *attr)
451 {
452   return 0;
453 }
454 strong_alias(__pthread_mutexattr_destroy, pthread_mutexattr_destroy);
455
456 int __pthread_mutexattr_setkind_np(pthread_mutexattr_t *attr, int kind)
457 {
458   return 0;
459 }
460 strong_alias(__pthread_mutexattr_setkind_np, pthread_mutexattr_setkind_np);
461
462 int __pthread_mutexattr_getkind_np(pthread_mutexattr_t *attr, int *kind)
463 {
464   *kind = PTHREAD_MUTEX_RECURSIVE;
465   return 0;
466 }
467 strong_alias(__pthread_mutexattr_getkind_np, pthread_mutexattr_getkind_np);
468
469 int __pthread_mutexattr_settype(pthread_mutexattr_t *attr, int kind)
470 {
471   return 0;
472 }
473 strong_alias(__pthread_mutexattr_settype, pthread_mutexattr_settype);
474
475 int __pthread_mutexattr_gettype(pthread_mutexattr_t *attr, int *kind)
476 {
477   *kind = PTHREAD_MUTEX_RECURSIVE;
478   return 0;
479 }
480 strong_alias(__pthread_mutexattr_gettype, pthread_mutexattr_gettype);
481
482
483 /***** THREAD-SPECIFIC VARIABLES (KEYS) *****/
484
485 int __pthread_key_create(pthread_key_t *key, void (*destr_function)(void *))
486 {
487     static long keycnt = FIRST_KEY;
488     *key = interlocked_xchg_add(&keycnt, 1);
489     return 0;
490 }
491 strong_alias(__pthread_key_create, pthread_key_create);
492
493 int __pthread_key_delete(pthread_key_t key)
494 {
495   return 0;
496 }
497 strong_alias(__pthread_key_delete, pthread_key_delete);
498
499 int __pthread_setspecific(pthread_key_t key, const void *pointer)
500 {
501     pthread_descr descr = __pthread_thread_self();
502     descr->key_data[key] = pointer;
503     return 0;
504 }
505 strong_alias(__pthread_setspecific, pthread_setspecific);
506
507 void *__pthread_getspecific(pthread_key_t key)
508 {
509     pthread_descr descr = __pthread_thread_self();
510     return (void *)descr->key_data[key];
511 }
512 strong_alias(__pthread_getspecific, pthread_getspecific);
513
514 static int pthread_internal_tsd_set( int key, const void *pointer )
515 {
516     pthread_descr descr = __pthread_thread_self();
517     descr->tsd_data[key] = pointer;
518     return 0;
519 }
520 int (*__libc_internal_tsd_set)(int, const void *) = pthread_internal_tsd_set;
521
522 static void *pthread_internal_tsd_get( int key )
523 {
524     pthread_descr descr = __pthread_thread_self();
525     return (void *)descr->tsd_data[key];
526 }
527 void* (*__libc_internal_tsd_get)(int) = pthread_internal_tsd_get;
528
529 static void ** __attribute__((const)) pthread_internal_tsd_address( int key )
530 {
531     pthread_descr descr = __pthread_thread_self();
532     return (void **)&descr->tsd_data[key];
533 }
534 void** (*__libc_internal_tsd_address)(int) = pthread_internal_tsd_address;
535
536 /***** "EXCEPTION" FRAMES *****/
537 /* not implemented right now */
538
539 void _pthread_cleanup_push(struct _pthread_cleanup_buffer *buffer, void (*routine)(void *), void *arg)
540 {
541   ((wine_cleanup)buffer)->routine = routine;
542   ((wine_cleanup)buffer)->arg = arg;
543 }
544
545 void _pthread_cleanup_pop(struct _pthread_cleanup_buffer *buffer, int execute)
546 {
547   if (execute) (*(((wine_cleanup)buffer)->routine))(((wine_cleanup)buffer)->arg);
548 }
549
550 void _pthread_cleanup_push_defer(struct _pthread_cleanup_buffer *buffer, void (*routine)(void *), void *arg)
551 {
552   _pthread_cleanup_push(buffer, routine, arg);
553 }
554
555 void _pthread_cleanup_pop_restore(struct _pthread_cleanup_buffer *buffer, int execute)
556 {
557   _pthread_cleanup_pop(buffer, execute);
558 }
559
560 void __pthread_cleanup_upto(jmp_buf target, char *frame)
561 {
562     /* FIXME */
563 }
564
565 /***** CONDITIONS *****/
566 /* not implemented right now */
567
568 int __pthread_cond_init(pthread_cond_t *cond, const pthread_condattr_t *cond_attr)
569 {
570   P_OUTPUT("FIXME:pthread_cond_init\n");
571   return 0;
572 }
573 strong_alias(__pthread_cond_init, pthread_cond_init);
574
575 int __pthread_cond_destroy(pthread_cond_t *cond)
576 {
577   P_OUTPUT("FIXME:pthread_cond_destroy\n");
578   return 0;
579 }
580 strong_alias(__pthread_cond_destroy, pthread_cond_destroy);
581
582 int __pthread_cond_signal(pthread_cond_t *cond)
583 {
584   P_OUTPUT("FIXME:pthread_cond_signal\n");
585   return 0;
586 }
587 strong_alias(__pthread_cond_signal, pthread_cond_signal);
588
589 int __pthread_cond_broadcast(pthread_cond_t *cond)
590 {
591   P_OUTPUT("FIXME:pthread_cond_broadcast\n");
592   return 0;
593 }
594 strong_alias(__pthread_cond_broadcast, pthread_cond_broadcast);
595
596 int __pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex)
597 {
598   P_OUTPUT("FIXME:pthread_cond_wait\n");
599   return 0;
600 }
601 strong_alias(__pthread_cond_wait, pthread_cond_wait);
602
603 int __pthread_cond_timedwait(pthread_cond_t *cond, pthread_mutex_t *mutex, const struct timespec *abstime)
604 {
605   P_OUTPUT("FIXME:pthread_cond_timedwait\n");
606   return 0;
607 }
608 strong_alias(__pthread_cond_timedwait, pthread_cond_timedwait);
609
610 /**** CONDITION ATTRIBUTES *****/
611 /* not implemented right now */
612
613 int pthread_condattr_init(pthread_condattr_t *attr)
614 {
615   return 0;
616 }
617
618 int pthread_condattr_destroy(pthread_condattr_t *attr)
619 {
620   return 0;
621 }
622
623 /***** READ-WRITE LOCKS *****/
624
625 int __pthread_rwlock_init(pthread_rwlock_t *rwlock, const pthread_rwlockattr_t *rwlock_attr)
626 {
627     assert( funcs.ptr_pthread_rwlock_init );
628     return funcs.ptr_pthread_rwlock_init( rwlock, rwlock_attr );
629 }
630 strong_alias(__pthread_rwlock_init, pthread_rwlock_init);
631
632 int __pthread_rwlock_destroy(pthread_rwlock_t *rwlock)
633 {
634     assert( funcs.ptr_pthread_rwlock_destroy );
635     return funcs.ptr_pthread_rwlock_destroy( rwlock );
636 }
637 strong_alias(__pthread_rwlock_destroy, pthread_rwlock_destroy);
638
639 int __pthread_rwlock_rdlock(pthread_rwlock_t *rwlock)
640 {
641     if (!funcs.ptr_pthread_rwlock_rdlock) return 0;
642     return funcs.ptr_pthread_rwlock_rdlock( rwlock );
643 }
644 strong_alias(__pthread_rwlock_rdlock, pthread_rwlock_rdlock);
645
646 int __pthread_rwlock_tryrdlock(pthread_rwlock_t *rwlock)
647 {
648     assert( funcs.ptr_pthread_rwlock_tryrdlock );
649     return funcs.ptr_pthread_rwlock_tryrdlock( rwlock );
650 }
651 strong_alias(__pthread_rwlock_tryrdlock, pthread_rwlock_tryrdlock);
652
653 int __pthread_rwlock_wrlock(pthread_rwlock_t *rwlock)
654 {
655     assert( funcs.ptr_pthread_rwlock_wrlock );
656     return funcs.ptr_pthread_rwlock_wrlock( rwlock );
657 }
658 strong_alias(__pthread_rwlock_wrlock, pthread_rwlock_wrlock);
659
660 int __pthread_rwlock_trywrlock(pthread_rwlock_t *rwlock)
661 {
662     assert( funcs.ptr_pthread_rwlock_trywrlock );
663     return funcs.ptr_pthread_rwlock_trywrlock( rwlock );
664 }
665 strong_alias(__pthread_rwlock_trywrlock, pthread_rwlock_trywrlock);
666
667 int __pthread_rwlock_unlock(pthread_rwlock_t *rwlock)
668 {
669     assert( funcs.ptr_pthread_rwlock_unlock );
670     return funcs.ptr_pthread_rwlock_unlock( rwlock );
671 }
672 strong_alias(__pthread_rwlock_unlock, pthread_rwlock_unlock);
673
674 /**** READ-WRITE LOCK ATTRIBUTES *****/
675 /* not implemented right now */
676
677 int pthread_rwlockattr_init(pthread_rwlockattr_t *attr)
678 {
679   return 0;
680 }
681
682 int __pthread_rwlockattr_destroy(pthread_rwlockattr_t *attr)
683 {
684   return 0;
685 }
686 strong_alias(__pthread_rwlockattr_destroy, pthread_rwlockattr_destroy);
687
688 int pthread_rwlockattr_getkind_np(const pthread_rwlockattr_t *attr, int *pref)
689 {
690   *pref = 0;
691   return 0;
692 }
693
694 int pthread_rwlockattr_setkind_np(pthread_rwlockattr_t *attr, int pref)
695 {
696   return 0;
697 }
698
699 /***** MISC *****/
700
701 pthread_t pthread_self(void)
702 {
703     assert( funcs.ptr_pthread_self );
704     return funcs.ptr_pthread_self();
705 }
706
707 int pthread_equal(pthread_t thread1, pthread_t thread2)
708 {
709     assert( funcs.ptr_pthread_equal );
710     return funcs.ptr_pthread_equal( thread1, thread2 );
711 }
712
713 void __pthread_do_exit(void *retval, char *currentframe)
714 {
715     assert( funcs.ptr_pthread_exit );
716     return funcs.ptr_pthread_exit( retval, currentframe );
717 }
718
719 void __pthread_exit(void *retval)
720 {
721     __pthread_do_exit( retval, NULL );
722 }
723 strong_alias(__pthread_exit, pthread_exit);
724
725 int pthread_setcancelstate(int state, int *oldstate)
726 {
727     pthread_descr descr = __pthread_thread_self();
728     if (oldstate) *oldstate = descr->cancel_state;
729     descr->cancel_state = state;
730     return 0;
731 }
732
733 int pthread_setcanceltype(int type, int *oldtype)
734 {
735     pthread_descr descr = __pthread_thread_self();
736     if (oldtype) *oldtype = descr->cancel_type;
737     descr->cancel_type = type;
738     return 0;
739 }
740
741 /***** ANTI-OVERRIDES *****/
742 /* pthreads tries to override these, point them back to libc */
743
744 int sigaction(int signum, const struct sigaction *act, struct sigaction *oldact)
745 {
746     if (!libc_sigaction)
747     {
748         libc_sigaction = dlsym( RTLD_NEXT, "sigaction" );
749         assert( libc_sigaction );
750     }
751     return libc_sigaction(signum, act, oldact);
752 }
753
754 void __pthread_initialize(void)
755 {
756     static int done;
757
758     if (!done)
759     {
760         done = 1;
761         libc_fork = dlsym( RTLD_NEXT, "fork" );
762         libc_sigaction = dlsym( RTLD_NEXT, "sigaction" );
763         libc_uselocale = dlsym( RTLD_NEXT, "uselocale" );
764         libc_pthread_init = dlsym( RTLD_NEXT, "__libc_pthread_init" );
765         if (libc_pthread_init) libc_multiple_threads = libc_pthread_init( &libc_pthread_functions );
766     }
767 }
768 DECL_GLOBAL_CONSTRUCTOR(init) { __pthread_initialize(); }
769
770 static struct pthread_functions libc_pthread_functions =
771 {
772     NULL,                          /* ptr_pthread_fork */
773     NULL, /* FIXME */              /* ptr_pthread_attr_destroy */
774     NULL, /* FIXME */              /* ptr___pthread_attr_init_2_0 */
775     NULL, /* FIXME */              /* ptr___pthread_attr_init_2_1 */
776     NULL, /* FIXME */              /* ptr_pthread_attr_getdetachstate */
777     NULL, /* FIXME */              /* ptr_pthread_attr_setdetachstate */
778     NULL, /* FIXME */              /* ptr_pthread_attr_getinheritsched */
779     NULL, /* FIXME */              /* ptr_pthread_attr_setinheritsched */
780     NULL, /* FIXME */              /* ptr_pthread_attr_getschedparam */
781     pthread_attr_setschedparam,    /* ptr_pthread_attr_setschedparam */
782     NULL, /* FIXME */              /* ptr_pthread_attr_getschedpolicy) (const pthread_attr_t *, int *); */
783     NULL, /* FIXME */              /* ptr_pthread_attr_setschedpolicy) (pthread_attr_t *, int); */
784     NULL, /* FIXME */              /* ptr_pthread_attr_getscope) (const pthread_attr_t *, int *); */
785     NULL, /* FIXME */              /* ptr_pthread_attr_setscope) (pthread_attr_t *, int); */
786     pthread_condattr_destroy,      /* ptr_pthread_condattr_destroy */
787     pthread_condattr_init,         /* ptr_pthread_condattr_init */
788     __pthread_cond_broadcast,      /* ptr___pthread_cond_broadcast */
789     __pthread_cond_destroy,        /* ptr___pthread_cond_destroy */
790     __pthread_cond_init,           /* ptr___pthread_cond_init */
791     __pthread_cond_signal,         /* ptr___pthread_cond_signal */
792     __pthread_cond_wait,           /* ptr___pthread_cond_wait */
793     pthread_equal,                 /* ptr_pthread_equal */
794     __pthread_exit,                /* ptr___pthread_exit */
795     NULL, /* FIXME */              /* ptr_pthread_getschedparam */
796     NULL, /* FIXME */              /* ptr_pthread_setschedparam */
797     __pthread_mutex_destroy,       /* ptr_pthread_mutex_destroy */
798     __pthread_mutex_init,          /* ptr_pthread_mutex_init */
799     __pthread_mutex_lock,          /* ptr_pthread_mutex_lock */
800     __pthread_mutex_trylock,       /* ptr_pthread_mutex_trylock */
801     __pthread_mutex_unlock,        /* ptr_pthread_mutex_unlock */
802     pthread_self,                  /* ptr_pthread_self */
803     pthread_setcancelstate,        /* ptr_pthread_setcancelstate */
804     pthread_setcanceltype,         /* ptr_pthread_setcanceltype */
805     __pthread_do_exit,             /* ptr_pthread_do_exit */
806     __pthread_cleanup_upto,        /* ptr_pthread_cleanup_upto */
807     __pthread_thread_self,         /* ptr_pthread_thread_self */
808     pthread_internal_tsd_set,      /* ptr_pthread_internal_tsd_set */
809     pthread_internal_tsd_get,      /* ptr_pthread_internal_tsd_get */
810     pthread_internal_tsd_address,  /* ptr_pthread_internal_tsd_address */
811     NULL,                          /* ptr_pthread_sigaction */
812     NULL,                          /* ptr_pthread_sigwait */
813     NULL                           /* ptr_pthread_raise */
814 };
815
816 #endif /* __GLIBC__ || __FREEBSD__ */
817
818 #else  /* HAVE_NPTL */
819
820 void wine_pthread_init_process( const struct wine_pthread_functions *functions )
821 {
822 }
823
824 void wine_pthread_init_thread(void)
825 {
826 }
827
828 #endif  /* HAVE_NPTL */