Moved debug output up before calling the backend.
[wine/wine-kai.git] / scheduler / pthread.c
blob134fe5545047a75cf4ce605f4e93d4b0360df3c9
1 /*
2 * pthread emulation for re-entrant libcs
4 * We can't use pthreads directly, so why not let libcs
5 * that want pthreads use Wine's own threading instead...
7 * Copyright 1999 Ove Kåven
8 * Copyright 2003 Alexandre Julliard
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.
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.
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
25 #include "config.h"
26 #include "wine/port.h"
28 #ifndef HAVE_NPTL
30 struct _pthread_cleanup_buffer;
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 #ifdef 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
58 #include "wine/pthread.h"
60 #define P_OUTPUT(stuff) write(2,stuff,strlen(stuff))
62 #define PSTR(str) __ASM_NAME(#str)
64 static struct wine_pthread_functions funcs;
66 /* thread descriptor */
68 #define FIRST_KEY 0
69 #define MAX_KEYS 16 /* libc6 doesn't use that many, but... */
70 #define MAX_TSD 16
72 struct pthread_descr_struct
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 */
84 typedef struct pthread_descr_struct *pthread_descr;
86 static struct pthread_descr_struct initial_descr;
88 pthread_descr __pthread_thread_self(void)
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;
97 static int (*libc_uselocale)(int set);
98 static int *libc_multiple_threads;
100 /***********************************************************************
101 * __errno_location/__error/__errno/___errno/__thr_errno
103 * Get the per-thread errno location.
105 int *__errno_location(void) /* Linux */
107 pthread_descr descr = __pthread_thread_self();
108 return &descr->thread_errno;
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 */
115 /***********************************************************************
116 * __h_errno_location
118 * Get the per-thread h_errno location.
120 int *__h_errno_location(void)
122 pthread_descr descr = __pthread_thread_self();
123 return &descr->thread_h_errno;
126 struct __res_state *__res_state(void)
128 pthread_descr descr = __pthread_thread_self();
129 return &descr->res_state;
132 static inline void writejump( const char *symbol, void *dest )
134 #if defined(__GLIBC__) && defined(__i386__)
135 unsigned char *addr = dlsym( RTLD_NEXT, symbol );
137 if (!addr) return;
139 /* write a relative jump at the function address */
140 mprotect((void*)((unsigned int)addr & ~(getpagesize()-1)), 5, PROT_READ|PROT_EXEC|PROT_WRITE);
141 addr[0] = 0xe9;
142 *(int *)(addr+1) = (unsigned char *)dest - (addr + 5);
143 mprotect((void*)((unsigned int)addr & ~(getpagesize()-1)), 5, PROT_READ|PROT_EXEC);
145 # ifdef HAVE_VALGRIND_MEMCHECK_H
146 VALGRIND_DISCARD_TRANSLATIONS( addr, 5 );
147 # endif
148 #endif /* __GLIBC__ && __i386__ */
151 /***********************************************************************
152 * wine_pthread_init_process
154 * Initialization for a newly created process.
156 void wine_pthread_init_process( const struct wine_pthread_functions *functions )
158 memcpy( &funcs, functions, sizeof(funcs) );
159 funcs.ptr_set_thread_data( &initial_descr );
160 initial_descr.cancel_state = PTHREAD_CANCEL_ENABLE;
161 initial_descr.cancel_type = PTHREAD_CANCEL_ASYNCHRONOUS;
162 writejump( "__errno_location", __errno_location );
163 writejump( "__h_errno_location", __h_errno_location );
164 writejump( "__res_state", __res_state );
165 if (libc_uselocale) libc_uselocale( -1 /*LC_GLOBAL_LOCALE*/ );
169 /***********************************************************************
170 * wine_pthread_init_thread
172 * Initialization for a newly created thread.
174 void wine_pthread_init_thread(void)
176 if (funcs.ptr_set_thread_data)
178 struct pthread_descr_struct *descr = calloc( 1, sizeof(*descr) );
180 funcs.ptr_set_thread_data( descr );
181 descr->cancel_state = PTHREAD_CANCEL_ENABLE;
182 descr->cancel_type = PTHREAD_CANCEL_ASYNCHRONOUS;
183 if (libc_multiple_threads) *libc_multiple_threads = 1;
184 if (libc_uselocale) libc_uselocale( -1 /*LC_GLOBAL_LOCALE*/ );
186 /* else it's the first thread, init will be done in wine_pthread_init_process */
190 /* Currently this probably works only for glibc2,
191 * which checks for the presence of double-underscore-prepended
192 * pthread primitives, and use them if available.
193 * If they are not available, the libc defaults to
194 * non-threadsafe operation (not good). */
196 #if defined(__GLIBC__) || defined(__FreeBSD__)
198 #ifndef __USE_UNIX98
199 #define __USE_UNIX98
200 #endif
202 #include <pthread.h>
204 /* adapt as necessary (a construct like this is used in glibc sources) */
205 #define strong_alias(orig, alias) \
206 asm(".globl " PSTR(alias) "\n" \
207 "\t.set " PSTR(alias) "," PSTR(orig))
209 struct fork_block;
211 /* pthread functions redirection */
213 struct pthread_functions
215 pid_t (*ptr_pthread_fork) (struct fork_block *);
216 int (*ptr_pthread_attr_destroy) (pthread_attr_t *);
217 int (*ptr___pthread_attr_init_2_0) (pthread_attr_t *);
218 int (*ptr___pthread_attr_init_2_1) (pthread_attr_t *);
219 int (*ptr_pthread_attr_getdetachstate) (const pthread_attr_t *, int *);
220 int (*ptr_pthread_attr_setdetachstate) (pthread_attr_t *, int);
221 int (*ptr_pthread_attr_getinheritsched) (const pthread_attr_t *, int *);
222 int (*ptr_pthread_attr_setinheritsched) (pthread_attr_t *, int);
223 int (*ptr_pthread_attr_getschedparam) (const pthread_attr_t *, struct sched_param *);
224 int (*ptr_pthread_attr_setschedparam) (pthread_attr_t *, const struct sched_param *);
225 int (*ptr_pthread_attr_getschedpolicy) (const pthread_attr_t *, int *);
226 int (*ptr_pthread_attr_setschedpolicy) (pthread_attr_t *, int);
227 int (*ptr_pthread_attr_getscope) (const pthread_attr_t *, int *);
228 int (*ptr_pthread_attr_setscope) (pthread_attr_t *, int);
229 int (*ptr_pthread_condattr_destroy) (pthread_condattr_t *);
230 int (*ptr_pthread_condattr_init) (pthread_condattr_t *);
231 int (*ptr___pthread_cond_broadcast) (pthread_cond_t *);
232 int (*ptr___pthread_cond_destroy) (pthread_cond_t *);
233 int (*ptr___pthread_cond_init) (pthread_cond_t *, const pthread_condattr_t *);
234 int (*ptr___pthread_cond_signal) (pthread_cond_t *);
235 int (*ptr___pthread_cond_wait) (pthread_cond_t *, pthread_mutex_t *);
236 int (*ptr_pthread_equal) (pthread_t, pthread_t);
237 void (*ptr___pthread_exit) (void *);
238 int (*ptr_pthread_getschedparam) (pthread_t, int *, struct sched_param *);
239 int (*ptr_pthread_setschedparam) (pthread_t, int, const struct sched_param *);
240 int (*ptr_pthread_mutex_destroy) (pthread_mutex_t *);
241 int (*ptr_pthread_mutex_init) (pthread_mutex_t *, const pthread_mutexattr_t *);
242 int (*ptr_pthread_mutex_lock) (pthread_mutex_t *);
243 int (*ptr_pthread_mutex_trylock) (pthread_mutex_t *);
244 int (*ptr_pthread_mutex_unlock) (pthread_mutex_t *);
245 pthread_t (*ptr_pthread_self) (void);
246 int (*ptr_pthread_setcancelstate) (int, int *);
247 int (*ptr_pthread_setcanceltype) (int, int *);
248 void (*ptr_pthread_do_exit) (void *retval, char *currentframe);
249 void (*ptr_pthread_cleanup_upto) (jmp_buf target, char *targetframe);
250 pthread_descr (*ptr_pthread_thread_self) (void);
251 int (*ptr_pthread_internal_tsd_set) (int key, const void *pointer);
252 void * (*ptr_pthread_internal_tsd_get) (int key);
253 void ** __attribute__ ((__const__)) (*ptr_pthread_internal_tsd_address) (int key);
254 int (*ptr_pthread_sigaction) (int sig, const struct sigaction * act, struct sigaction *oact);
255 int (*ptr_pthread_sigwait) (const sigset_t *set, int *sig);
256 int (*ptr_pthread_raise) (int sig);
257 int (*ptr___pthread_cond_timedwait) (pthread_cond_t *, pthread_mutex_t *, const struct timespec *);
258 void (*ptr__pthread_cleanup_push) (struct _pthread_cleanup_buffer * buffer, void (*routine)(void *), void * arg);
259 void (*ptr__pthread_cleanup_pop) (struct _pthread_cleanup_buffer * buffer, int execute);
262 static pid_t (*libc_fork)(void);
263 static int (*libc_sigaction)(int signum, const struct sigaction *act, struct sigaction *oldact);
264 static int *(*libc_pthread_init)( const struct pthread_functions *funcs );
266 static struct pthread_functions libc_pthread_functions;
268 strong_alias(__pthread_thread_self, pthread_thread_self);
270 /* redefine this to prevent libpthread from overriding our function pointers */
271 int *__libc_pthread_init( const struct pthread_functions *funcs )
273 return libc_multiple_threads;
276 typedef struct _wine_cleanup {
277 void (*routine)(void *);
278 void *arg;
279 } *wine_cleanup;
281 int pthread_create(pthread_t* thread, const pthread_attr_t* attr, void*
282 (*start_routine)(void *), void* arg)
284 assert( funcs.ptr_pthread_create );
285 return funcs.ptr_pthread_create( thread, attr, start_routine, arg );
288 int pthread_cancel(pthread_t thread)
290 assert( funcs.ptr_pthread_cancel );
291 return funcs.ptr_pthread_cancel( thread );
294 int pthread_join(pthread_t thread, void **value_ptr)
296 assert( funcs.ptr_pthread_join );
297 return funcs.ptr_pthread_join( thread, value_ptr );
300 int pthread_detach(pthread_t thread)
302 assert( funcs.ptr_pthread_detach );
303 return funcs.ptr_pthread_detach( thread );
306 /* FIXME: we have no equivalents in win32 for the policys */
307 /* so just keep this as a stub */
308 int pthread_attr_setschedpolicy(pthread_attr_t *attr, int policy)
310 P_OUTPUT("FIXME:pthread_attr_setschedpolicy\n");
311 return 0;
314 /* FIXME: no win32 equivalent for scope */
315 int pthread_attr_setscope(pthread_attr_t *attr, int scope)
317 P_OUTPUT("FIXME:pthread_attr_setscope\n");
318 return 0; /* return success */
321 /* FIXME: no win32 equivalent for schedule param */
322 int pthread_attr_setschedparam(pthread_attr_t *attr,
323 const struct sched_param *param)
325 P_OUTPUT("FIXME:pthread_attr_setschedparam\n");
326 return 0; /* return success */
329 /* FIXME */
330 int pthread_attr_setstack(pthread_attr_t *attr, void *addr, size_t size)
332 return 0; /* return success */
335 int __pthread_once(pthread_once_t *once_control, void (*init_routine)(void))
337 static pthread_once_t the_once = PTHREAD_ONCE_INIT;
338 long once_now;
340 memcpy(&once_now,&the_once,sizeof(once_now));
341 if (interlocked_cmpxchg((long*)once_control, once_now+1, once_now) == once_now)
342 (*init_routine)();
343 return 0;
345 strong_alias(__pthread_once, pthread_once);
347 void __pthread_kill_other_threads_np(void)
349 /* we don't need to do anything here */
351 strong_alias(__pthread_kill_other_threads_np, pthread_kill_other_threads_np);
353 /***** atfork *****/
355 #define MAX_ATFORK 8 /* libc doesn't need that many anyway */
357 static pthread_mutex_t atfork_mutex = PTHREAD_MUTEX_INITIALIZER;
359 typedef void (*atfork_handler)();
360 static atfork_handler atfork_prepare[MAX_ATFORK];
361 static atfork_handler atfork_parent[MAX_ATFORK];
362 static atfork_handler atfork_child[MAX_ATFORK];
363 static int atfork_count;
365 int __pthread_atfork(void (*prepare)(void), void (*parent)(void), void (*child)(void))
367 pthread_mutex_lock( &atfork_mutex );
368 assert( atfork_count < MAX_ATFORK );
369 atfork_prepare[atfork_count] = prepare;
370 atfork_parent[atfork_count] = parent;
371 atfork_child[atfork_count] = child;
372 atfork_count++;
373 pthread_mutex_unlock( &atfork_mutex );
374 return 0;
376 strong_alias(__pthread_atfork, pthread_atfork);
378 pid_t __fork(void)
380 pid_t pid;
381 int i;
383 if (!libc_fork)
385 libc_fork = dlsym( RTLD_NEXT, "fork" );
386 assert( libc_fork );
388 pthread_mutex_lock( &atfork_mutex );
389 /* prepare handlers are called in reverse insertion order */
390 for (i = atfork_count - 1; i >= 0; i--) if (atfork_prepare[i]) atfork_prepare[i]();
391 if (!(pid = libc_fork()))
393 pthread_mutex_init( &atfork_mutex, NULL );
394 for (i = 0; i < atfork_count; i++) if (atfork_child[i]) atfork_child[i]();
396 else
398 for (i = 0; i < atfork_count; i++) if (atfork_parent[i]) atfork_parent[i]();
399 pthread_mutex_unlock( &atfork_mutex );
401 return pid;
403 strong_alias(__fork, fork);
405 /***** MUTEXES *****/
407 int __pthread_mutex_init(pthread_mutex_t *mutex, const pthread_mutexattr_t *mutexattr)
409 if (!funcs.ptr_pthread_mutex_init) return 0;
410 return funcs.ptr_pthread_mutex_init( mutex, mutexattr );
412 strong_alias(__pthread_mutex_init, pthread_mutex_init);
414 int __pthread_mutex_lock(pthread_mutex_t *mutex)
416 if (!funcs.ptr_pthread_mutex_lock) return 0;
417 return funcs.ptr_pthread_mutex_lock( mutex );
419 strong_alias(__pthread_mutex_lock, pthread_mutex_lock);
421 int __pthread_mutex_trylock(pthread_mutex_t *mutex)
423 if (!funcs.ptr_pthread_mutex_trylock) return 0;
424 return funcs.ptr_pthread_mutex_trylock( mutex );
426 strong_alias(__pthread_mutex_trylock, pthread_mutex_trylock);
428 int __pthread_mutex_unlock(pthread_mutex_t *mutex)
430 if (!funcs.ptr_pthread_mutex_unlock) return 0;
431 return funcs.ptr_pthread_mutex_unlock( mutex );
433 strong_alias(__pthread_mutex_unlock, pthread_mutex_unlock);
435 int __pthread_mutex_destroy(pthread_mutex_t *mutex)
437 if (!funcs.ptr_pthread_mutex_destroy) return 0;
438 return funcs.ptr_pthread_mutex_destroy( mutex );
440 strong_alias(__pthread_mutex_destroy, pthread_mutex_destroy);
443 /***** MUTEX ATTRIBUTES *****/
444 /* just dummies, since critical sections are always recursive */
446 int __pthread_mutexattr_init(pthread_mutexattr_t *attr)
448 return 0;
450 strong_alias(__pthread_mutexattr_init, pthread_mutexattr_init);
452 int __pthread_mutexattr_destroy(pthread_mutexattr_t *attr)
454 return 0;
456 strong_alias(__pthread_mutexattr_destroy, pthread_mutexattr_destroy);
458 int __pthread_mutexattr_setkind_np(pthread_mutexattr_t *attr, int kind)
460 return 0;
462 strong_alias(__pthread_mutexattr_setkind_np, pthread_mutexattr_setkind_np);
464 int __pthread_mutexattr_getkind_np(pthread_mutexattr_t *attr, int *kind)
466 *kind = PTHREAD_MUTEX_RECURSIVE;
467 return 0;
469 strong_alias(__pthread_mutexattr_getkind_np, pthread_mutexattr_getkind_np);
471 int __pthread_mutexattr_settype(pthread_mutexattr_t *attr, int kind)
473 return 0;
475 strong_alias(__pthread_mutexattr_settype, pthread_mutexattr_settype);
477 int __pthread_mutexattr_gettype(pthread_mutexattr_t *attr, int *kind)
479 *kind = PTHREAD_MUTEX_RECURSIVE;
480 return 0;
482 strong_alias(__pthread_mutexattr_gettype, pthread_mutexattr_gettype);
485 /***** THREAD-SPECIFIC VARIABLES (KEYS) *****/
487 int __pthread_key_create(pthread_key_t *key, void (*destr_function)(void *))
489 static long keycnt = FIRST_KEY;
490 *key = interlocked_xchg_add(&keycnt, 1);
491 return 0;
493 strong_alias(__pthread_key_create, pthread_key_create);
495 int __pthread_key_delete(pthread_key_t key)
497 return 0;
499 strong_alias(__pthread_key_delete, pthread_key_delete);
501 int __pthread_setspecific(pthread_key_t key, const void *pointer)
503 pthread_descr descr = __pthread_thread_self();
504 descr->key_data[key] = pointer;
505 return 0;
507 strong_alias(__pthread_setspecific, pthread_setspecific);
509 void *__pthread_getspecific(pthread_key_t key)
511 pthread_descr descr = __pthread_thread_self();
512 return (void *)descr->key_data[key];
514 strong_alias(__pthread_getspecific, pthread_getspecific);
516 static int pthread_internal_tsd_set( int key, const void *pointer )
518 pthread_descr descr = __pthread_thread_self();
519 descr->tsd_data[key] = pointer;
520 return 0;
522 int (*__libc_internal_tsd_set)(int, const void *) = pthread_internal_tsd_set;
524 static void *pthread_internal_tsd_get( int key )
526 pthread_descr descr = __pthread_thread_self();
527 return (void *)descr->tsd_data[key];
529 void* (*__libc_internal_tsd_get)(int) = pthread_internal_tsd_get;
531 static void ** __attribute__((const)) pthread_internal_tsd_address( int key )
533 pthread_descr descr = __pthread_thread_self();
534 return (void **)&descr->tsd_data[key];
536 void** (*__libc_internal_tsd_address)(int) = pthread_internal_tsd_address;
538 /***** "EXCEPTION" FRAMES *****/
539 /* not implemented right now */
541 void _pthread_cleanup_push(struct _pthread_cleanup_buffer *buffer, void (*routine)(void *), void *arg)
543 ((wine_cleanup)buffer)->routine = routine;
544 ((wine_cleanup)buffer)->arg = arg;
547 void _pthread_cleanup_pop(struct _pthread_cleanup_buffer *buffer, int execute)
549 if (execute) (*(((wine_cleanup)buffer)->routine))(((wine_cleanup)buffer)->arg);
552 void _pthread_cleanup_push_defer(struct _pthread_cleanup_buffer *buffer, void (*routine)(void *), void *arg)
554 _pthread_cleanup_push(buffer, routine, arg);
557 void _pthread_cleanup_pop_restore(struct _pthread_cleanup_buffer *buffer, int execute)
559 _pthread_cleanup_pop(buffer, execute);
562 void __pthread_cleanup_upto(jmp_buf target, char *frame)
564 /* FIXME */
567 /***** CONDITIONS *****/
569 int __pthread_cond_init(pthread_cond_t *cond, const pthread_condattr_t *cond_attr)
571 if (!funcs.ptr_pthread_cond_init) return 0;
572 return funcs.ptr_pthread_cond_init(cond, cond_attr);
574 strong_alias(__pthread_cond_init, pthread_cond_init);
576 int __pthread_cond_destroy(pthread_cond_t *cond)
578 if (!funcs.ptr_pthread_cond_destroy) return 0;
579 return funcs.ptr_pthread_cond_destroy(cond);
581 strong_alias(__pthread_cond_destroy, pthread_cond_destroy);
583 int __pthread_cond_signal(pthread_cond_t *cond)
585 if (!funcs.ptr_pthread_cond_signal) return 0;
586 return funcs.ptr_pthread_cond_signal(cond);
588 strong_alias(__pthread_cond_signal, pthread_cond_signal);
590 int __pthread_cond_broadcast(pthread_cond_t *cond)
592 if (!funcs.ptr_pthread_cond_broadcast) return 0;
593 return funcs.ptr_pthread_cond_broadcast(cond);
595 strong_alias(__pthread_cond_broadcast, pthread_cond_broadcast);
597 int __pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex)
599 if (!funcs.ptr_pthread_cond_wait) return 0;
600 return funcs.ptr_pthread_cond_wait(cond, mutex);
602 strong_alias(__pthread_cond_wait, pthread_cond_wait);
604 int __pthread_cond_timedwait(pthread_cond_t *cond, pthread_mutex_t *mutex, const struct timespec *abstime)
606 if (!funcs.ptr_pthread_cond_timedwait) return 0;
607 return funcs.ptr_pthread_cond_timedwait(cond, mutex, abstime);
609 strong_alias(__pthread_cond_timedwait, pthread_cond_timedwait);
611 /**** CONDITION ATTRIBUTES *****/
612 /* not implemented right now */
614 int pthread_condattr_init(pthread_condattr_t *attr)
616 return 0;
619 int pthread_condattr_destroy(pthread_condattr_t *attr)
621 return 0;
624 /***** READ-WRITE LOCKS *****/
626 int __pthread_rwlock_init(pthread_rwlock_t *rwlock, const pthread_rwlockattr_t *rwlock_attr)
628 assert( funcs.ptr_pthread_rwlock_init );
629 return funcs.ptr_pthread_rwlock_init( rwlock, rwlock_attr );
631 strong_alias(__pthread_rwlock_init, pthread_rwlock_init);
633 int __pthread_rwlock_destroy(pthread_rwlock_t *rwlock)
635 assert( funcs.ptr_pthread_rwlock_destroy );
636 return funcs.ptr_pthread_rwlock_destroy( rwlock );
638 strong_alias(__pthread_rwlock_destroy, pthread_rwlock_destroy);
640 int __pthread_rwlock_rdlock(pthread_rwlock_t *rwlock)
642 if (!funcs.ptr_pthread_rwlock_rdlock) return 0;
643 return funcs.ptr_pthread_rwlock_rdlock( rwlock );
645 strong_alias(__pthread_rwlock_rdlock, pthread_rwlock_rdlock);
647 int __pthread_rwlock_tryrdlock(pthread_rwlock_t *rwlock)
649 assert( funcs.ptr_pthread_rwlock_tryrdlock );
650 return funcs.ptr_pthread_rwlock_tryrdlock( rwlock );
652 strong_alias(__pthread_rwlock_tryrdlock, pthread_rwlock_tryrdlock);
654 int __pthread_rwlock_wrlock(pthread_rwlock_t *rwlock)
656 assert( funcs.ptr_pthread_rwlock_wrlock );
657 return funcs.ptr_pthread_rwlock_wrlock( rwlock );
659 strong_alias(__pthread_rwlock_wrlock, pthread_rwlock_wrlock);
661 int __pthread_rwlock_trywrlock(pthread_rwlock_t *rwlock)
663 assert( funcs.ptr_pthread_rwlock_trywrlock );
664 return funcs.ptr_pthread_rwlock_trywrlock( rwlock );
666 strong_alias(__pthread_rwlock_trywrlock, pthread_rwlock_trywrlock);
668 int __pthread_rwlock_unlock(pthread_rwlock_t *rwlock)
670 if (!funcs.ptr_pthread_rwlock_unlock) return 0;
671 return funcs.ptr_pthread_rwlock_unlock( rwlock );
673 strong_alias(__pthread_rwlock_unlock, pthread_rwlock_unlock);
675 /**** READ-WRITE LOCK ATTRIBUTES *****/
676 /* not implemented right now */
678 int pthread_rwlockattr_init(pthread_rwlockattr_t *attr)
680 return 0;
683 int __pthread_rwlockattr_destroy(pthread_rwlockattr_t *attr)
685 return 0;
687 strong_alias(__pthread_rwlockattr_destroy, pthread_rwlockattr_destroy);
689 int pthread_rwlockattr_getkind_np(const pthread_rwlockattr_t *attr, int *pref)
691 *pref = 0;
692 return 0;
695 int pthread_rwlockattr_setkind_np(pthread_rwlockattr_t *attr, int pref)
697 return 0;
700 /***** MISC *****/
702 pthread_t pthread_self(void)
704 assert( funcs.ptr_pthread_self );
705 return funcs.ptr_pthread_self();
708 int pthread_equal(pthread_t thread1, pthread_t thread2)
710 assert( funcs.ptr_pthread_equal );
711 return funcs.ptr_pthread_equal( thread1, thread2 );
714 void __pthread_do_exit(void *retval, char *currentframe)
716 assert( funcs.ptr_pthread_exit );
717 return funcs.ptr_pthread_exit( retval, currentframe );
720 void __pthread_exit(void *retval)
722 __pthread_do_exit( retval, NULL );
724 strong_alias(__pthread_exit, pthread_exit);
726 int pthread_setcancelstate(int state, int *oldstate)
728 pthread_descr descr = __pthread_thread_self();
729 if (oldstate) *oldstate = descr->cancel_state;
730 descr->cancel_state = state;
731 return 0;
734 int pthread_setcanceltype(int type, int *oldtype)
736 pthread_descr descr = __pthread_thread_self();
737 if (oldtype) *oldtype = descr->cancel_type;
738 descr->cancel_type = type;
739 return 0;
742 /***** ANTI-OVERRIDES *****/
743 /* pthreads tries to override these, point them back to libc */
745 int sigaction(int signum, const struct sigaction *act, struct sigaction *oldact)
747 if (!libc_sigaction)
749 libc_sigaction = dlsym( RTLD_NEXT, "sigaction" );
750 assert( libc_sigaction );
752 return libc_sigaction(signum, act, oldact);
755 void __pthread_initialize(void)
757 static int done;
759 if (!done)
761 done = 1;
762 libc_fork = dlsym( RTLD_NEXT, "fork" );
763 libc_sigaction = dlsym( RTLD_NEXT, "sigaction" );
764 libc_uselocale = dlsym( RTLD_NEXT, "uselocale" );
765 libc_pthread_init = dlsym( RTLD_NEXT, "__libc_pthread_init" );
766 if (libc_pthread_init) libc_multiple_threads = libc_pthread_init( &libc_pthread_functions );
769 DECL_GLOBAL_CONSTRUCTOR(init) { __pthread_initialize(); }
771 static struct pthread_functions libc_pthread_functions =
773 NULL, /* ptr_pthread_fork */
774 NULL, /* FIXME */ /* ptr_pthread_attr_destroy */
775 NULL, /* FIXME */ /* ptr___pthread_attr_init_2_0 */
776 NULL, /* FIXME */ /* ptr___pthread_attr_init_2_1 */
777 NULL, /* FIXME */ /* ptr_pthread_attr_getdetachstate */
778 NULL, /* FIXME */ /* ptr_pthread_attr_setdetachstate */
779 NULL, /* FIXME */ /* ptr_pthread_attr_getinheritsched */
780 NULL, /* FIXME */ /* ptr_pthread_attr_setinheritsched */
781 NULL, /* FIXME */ /* ptr_pthread_attr_getschedparam */
782 pthread_attr_setschedparam, /* ptr_pthread_attr_setschedparam */
783 NULL, /* FIXME */ /* ptr_pthread_attr_getschedpolicy) (const pthread_attr_t *, int *); */
784 NULL, /* FIXME */ /* ptr_pthread_attr_setschedpolicy) (pthread_attr_t *, int); */
785 NULL, /* FIXME */ /* ptr_pthread_attr_getscope) (const pthread_attr_t *, int *); */
786 NULL, /* FIXME */ /* ptr_pthread_attr_setscope) (pthread_attr_t *, int); */
787 pthread_condattr_destroy, /* ptr_pthread_condattr_destroy */
788 pthread_condattr_init, /* ptr_pthread_condattr_init */
789 __pthread_cond_broadcast, /* ptr___pthread_cond_broadcast */
790 __pthread_cond_destroy, /* ptr___pthread_cond_destroy */
791 __pthread_cond_init, /* ptr___pthread_cond_init */
792 __pthread_cond_signal, /* ptr___pthread_cond_signal */
793 __pthread_cond_wait, /* ptr___pthread_cond_wait */
794 pthread_equal, /* ptr_pthread_equal */
795 __pthread_exit, /* ptr___pthread_exit */
796 NULL, /* FIXME */ /* ptr_pthread_getschedparam */
797 NULL, /* FIXME */ /* ptr_pthread_setschedparam */
798 __pthread_mutex_destroy, /* ptr_pthread_mutex_destroy */
799 __pthread_mutex_init, /* ptr_pthread_mutex_init */
800 __pthread_mutex_lock, /* ptr_pthread_mutex_lock */
801 __pthread_mutex_trylock, /* ptr_pthread_mutex_trylock */
802 __pthread_mutex_unlock, /* ptr_pthread_mutex_unlock */
803 pthread_self, /* ptr_pthread_self */
804 pthread_setcancelstate, /* ptr_pthread_setcancelstate */
805 pthread_setcanceltype, /* ptr_pthread_setcanceltype */
806 __pthread_do_exit, /* ptr_pthread_do_exit */
807 __pthread_cleanup_upto, /* ptr_pthread_cleanup_upto */
808 __pthread_thread_self, /* ptr_pthread_thread_self */
809 pthread_internal_tsd_set, /* ptr_pthread_internal_tsd_set */
810 pthread_internal_tsd_get, /* ptr_pthread_internal_tsd_get */
811 pthread_internal_tsd_address, /* ptr_pthread_internal_tsd_address */
812 NULL, /* ptr_pthread_sigaction */
813 NULL, /* ptr_pthread_sigwait */
814 NULL, /* ptr_pthread_raise */
815 __pthread_cond_timedwait, /* ptr___pthread_cond_timedwait */
816 _pthread_cleanup_push, /* ptr__pthread_cleanup_push */
817 _pthread_cleanup_pop /* ptr__pthread_cleanup_pop */
820 #endif /* __GLIBC__ || __FREEBSD__ */
822 #else /* HAVE_NPTL */
824 void wine_pthread_init_process( const struct wine_pthread_functions *functions )
828 void wine_pthread_init_thread(void)
832 #endif /* HAVE_NPTL */