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
26 #include "wine/port.h"
30 struct _pthread_cleanup_buffer
;
41 #include <sys/types.h>
42 #ifdef HAVE_SYS_SOCKET_H
43 # include <sys/socket.h>
45 #ifdef HAVE_SYS_MMAN_H
48 #ifdef HAVE_NETINET_IN_H
49 # include <netinet/in.h>
51 #ifdef HAVE_ARPA_NAMESER_H
52 # include <arpa/nameser.h>
57 #ifdef HAVE_VALGRIND_MEMCHECK_H
58 #include <valgrind/memcheck.h>
61 #include "wine/pthread.h"
63 #define P_OUTPUT(stuff) write(2,stuff,strlen(stuff))
65 #define PSTR(str) __ASM_NAME(#str)
67 static struct wine_pthread_functions funcs
;
69 /* thread descriptor */
72 #define MAX_KEYS 16 /* libc6 doesn't use that many, but... */
75 struct pthread_descr_struct
82 struct __res_state res_state
;
83 const void *key_data
[MAX_KEYS
]; /* for normal pthread keys */
84 const void *tsd_data
[MAX_TSD
]; /* for libc internal tsd variables */
87 typedef struct pthread_descr_struct
*pthread_descr
;
89 static struct pthread_descr_struct initial_descr
;
91 pthread_descr
__pthread_thread_self(void)
93 struct pthread_descr_struct
*descr
;
94 if (!funcs
.ptr_get_thread_data
) return &initial_descr
;
95 descr
= funcs
.ptr_get_thread_data();
96 if (!descr
) return &initial_descr
;
100 static int (*libc_uselocale
)(int set
);
101 static int *libc_multiple_threads
;
103 /***********************************************************************
104 * __errno_location/__error/__errno/___errno/__thr_errno
106 * Get the per-thread errno location.
108 int *__errno_location(void) /* Linux */
110 pthread_descr descr
= __pthread_thread_self();
111 return &descr
->thread_errno
;
113 int *__error(void) { return __errno_location(); } /* FreeBSD */
114 int *__errno(void) { return __errno_location(); } /* NetBSD */
115 int *___errno(void) { return __errno_location(); } /* Solaris */
116 int *__thr_errno(void) { return __errno_location(); } /* UnixWare */
118 /***********************************************************************
121 * Get the per-thread h_errno location.
123 int *__h_errno_location(void)
125 pthread_descr descr
= __pthread_thread_self();
126 return &descr
->thread_h_errno
;
129 struct __res_state
*__res_state(void)
131 pthread_descr descr
= __pthread_thread_self();
132 return &descr
->res_state
;
135 static inline void writejump( const char *symbol
, void *dest
)
137 #if defined(__GLIBC__) && defined(__i386__)
138 unsigned char *addr
= dlsym( RTLD_NEXT
, symbol
);
142 /* write a relative jump at the function address */
143 mprotect((void*)((unsigned int)addr
& ~(getpagesize()-1)), 5, PROT_READ
|PROT_EXEC
|PROT_WRITE
);
145 *(int *)(addr
+1) = (unsigned char *)dest
- (addr
+ 5);
146 mprotect((void*)((unsigned int)addr
& ~(getpagesize()-1)), 5, PROT_READ
|PROT_EXEC
);
148 # ifdef HAVE_VALGRIND_MEMCHECK_H
149 VALGRIND_DISCARD_TRANSLATIONS( addr
, 5 );
151 #endif /* __GLIBC__ && __i386__ */
154 /***********************************************************************
155 * wine_pthread_init_process
157 * Initialization for a newly created process.
159 void wine_pthread_init_process( const struct wine_pthread_functions
*functions
)
161 memcpy( &funcs
, functions
, sizeof(funcs
) );
162 funcs
.ptr_set_thread_data( &initial_descr
);
166 /***********************************************************************
167 * wine_pthread_init_thread
169 * Initialization for a newly created thread.
171 void wine_pthread_init_thread(void)
173 struct pthread_descr_struct
*descr
;
175 if (funcs
.ptr_set_thread_data
)
177 descr
= calloc( 1, sizeof(*descr
) );
178 funcs
.ptr_set_thread_data( descr
);
179 if (libc_multiple_threads
) *libc_multiple_threads
= 1;
181 else /* first thread */
183 descr
= &initial_descr
;
184 writejump( "__errno_location", __errno_location
);
185 writejump( "__h_errno_location", __h_errno_location
);
186 writejump( "__res_state", __res_state
);
188 descr
->cancel_state
= PTHREAD_CANCEL_ENABLE
;
189 descr
->cancel_type
= PTHREAD_CANCEL_ASYNCHRONOUS
;
190 if (libc_uselocale
) libc_uselocale( -1 /*LC_GLOBAL_LOCALE*/ );
194 /* Currently this probably works only for glibc2,
195 * which checks for the presence of double-underscore-prepended
196 * pthread primitives, and use them if available.
197 * If they are not available, the libc defaults to
198 * non-threadsafe operation (not good). */
200 #if defined(__GLIBC__) || defined(__FreeBSD__)
208 /* adapt as necessary (a construct like this is used in glibc sources) */
209 #define strong_alias(orig, alias) \
210 asm(".globl " PSTR(alias) "\n" \
211 "\t.set " PSTR(alias) "," PSTR(orig))
215 /* pthread functions redirection */
217 struct pthread_functions
219 pid_t (*ptr_pthread_fork
) (struct fork_block
*);
220 int (*ptr_pthread_attr_destroy
) (pthread_attr_t
*);
221 int (*ptr___pthread_attr_init_2_0
) (pthread_attr_t
*);
222 int (*ptr___pthread_attr_init_2_1
) (pthread_attr_t
*);
223 int (*ptr_pthread_attr_getdetachstate
) (const pthread_attr_t
*, int *);
224 int (*ptr_pthread_attr_setdetachstate
) (pthread_attr_t
*, int);
225 int (*ptr_pthread_attr_getinheritsched
) (const pthread_attr_t
*, int *);
226 int (*ptr_pthread_attr_setinheritsched
) (pthread_attr_t
*, int);
227 int (*ptr_pthread_attr_getschedparam
) (const pthread_attr_t
*, struct sched_param
*);
228 int (*ptr_pthread_attr_setschedparam
) (pthread_attr_t
*, const struct sched_param
*);
229 int (*ptr_pthread_attr_getschedpolicy
) (const pthread_attr_t
*, int *);
230 int (*ptr_pthread_attr_setschedpolicy
) (pthread_attr_t
*, int);
231 int (*ptr_pthread_attr_getscope
) (const pthread_attr_t
*, int *);
232 int (*ptr_pthread_attr_setscope
) (pthread_attr_t
*, int);
233 int (*ptr_pthread_condattr_destroy
) (pthread_condattr_t
*);
234 int (*ptr_pthread_condattr_init
) (pthread_condattr_t
*);
235 int (*ptr___pthread_cond_broadcast
) (pthread_cond_t
*);
236 int (*ptr___pthread_cond_destroy
) (pthread_cond_t
*);
237 int (*ptr___pthread_cond_init
) (pthread_cond_t
*, const pthread_condattr_t
*);
238 int (*ptr___pthread_cond_signal
) (pthread_cond_t
*);
239 int (*ptr___pthread_cond_wait
) (pthread_cond_t
*, pthread_mutex_t
*);
240 int (*ptr_pthread_equal
) (pthread_t
, pthread_t
);
241 void (*ptr___pthread_exit
) (void *);
242 int (*ptr_pthread_getschedparam
) (pthread_t
, int *, struct sched_param
*);
243 int (*ptr_pthread_setschedparam
) (pthread_t
, int, const struct sched_param
*);
244 int (*ptr_pthread_mutex_destroy
) (pthread_mutex_t
*);
245 int (*ptr_pthread_mutex_init
) (pthread_mutex_t
*, const pthread_mutexattr_t
*);
246 int (*ptr_pthread_mutex_lock
) (pthread_mutex_t
*);
247 int (*ptr_pthread_mutex_trylock
) (pthread_mutex_t
*);
248 int (*ptr_pthread_mutex_unlock
) (pthread_mutex_t
*);
249 pthread_t (*ptr_pthread_self
) (void);
250 int (*ptr_pthread_setcancelstate
) (int, int *);
251 int (*ptr_pthread_setcanceltype
) (int, int *);
252 void (*ptr_pthread_do_exit
) (void *retval
, char *currentframe
);
253 void (*ptr_pthread_cleanup_upto
) (jmp_buf target
, char *targetframe
);
254 pthread_descr (*ptr_pthread_thread_self
) (void);
255 int (*ptr_pthread_internal_tsd_set
) (int key
, const void *pointer
);
256 void * (*ptr_pthread_internal_tsd_get
) (int key
);
257 void ** __attribute__ ((__const__
)) (*ptr_pthread_internal_tsd_address
) (int key
);
258 int (*ptr_pthread_sigaction
) (int sig
, const struct sigaction
* act
, struct sigaction
*oact
);
259 int (*ptr_pthread_sigwait
) (const sigset_t
*set
, int *sig
);
260 int (*ptr_pthread_raise
) (int sig
);
261 int (*ptr___pthread_cond_timedwait
) (pthread_cond_t
*, pthread_mutex_t
*, const struct timespec
*);
262 void (*ptr__pthread_cleanup_push
) (struct _pthread_cleanup_buffer
* buffer
, void (*routine
)(void *), void * arg
);
263 void (*ptr__pthread_cleanup_pop
) (struct _pthread_cleanup_buffer
* buffer
, int execute
);
266 static pid_t (*libc_fork
)(void);
267 static int (*libc_sigaction
)(int signum
, const struct sigaction
*act
, struct sigaction
*oldact
);
268 static int *(*libc_pthread_init
)( const struct pthread_functions
*funcs
);
270 static struct pthread_functions libc_pthread_functions
;
272 strong_alias(__pthread_thread_self
, pthread_thread_self
);
274 /* redefine this to prevent libpthread from overriding our function pointers */
275 int *__libc_pthread_init( const struct pthread_functions
*funcs
)
277 return libc_multiple_threads
;
280 typedef struct _wine_cleanup
{
281 void (*routine
)(void *);
285 int pthread_create(pthread_t
* thread
, const pthread_attr_t
* attr
, void*
286 (*start_routine
)(void *), void* arg
)
288 assert( funcs
.ptr_pthread_create
);
289 return funcs
.ptr_pthread_create( thread
, attr
, start_routine
, arg
);
292 int pthread_cancel(pthread_t thread
)
294 assert( funcs
.ptr_pthread_cancel
);
295 return funcs
.ptr_pthread_cancel( thread
);
298 int pthread_join(pthread_t thread
, void **value_ptr
)
300 assert( funcs
.ptr_pthread_join
);
301 return funcs
.ptr_pthread_join( thread
, value_ptr
);
304 int pthread_detach(pthread_t thread
)
306 assert( funcs
.ptr_pthread_detach
);
307 return funcs
.ptr_pthread_detach( thread
);
310 /* FIXME: we have no equivalents in win32 for the policys */
311 /* so just keep this as a stub */
312 int pthread_attr_setschedpolicy(pthread_attr_t
*attr
, int policy
)
314 P_OUTPUT("FIXME:pthread_attr_setschedpolicy\n");
318 /* FIXME: no win32 equivalent for scope */
319 int pthread_attr_setscope(pthread_attr_t
*attr
, int scope
)
321 P_OUTPUT("FIXME:pthread_attr_setscope\n");
322 return 0; /* return success */
325 /* FIXME: no win32 equivalent for schedule param */
326 int pthread_attr_setschedparam(pthread_attr_t
*attr
,
327 const struct sched_param
*param
)
329 P_OUTPUT("FIXME:pthread_attr_setschedparam\n");
330 return 0; /* return success */
334 int pthread_attr_setstack(pthread_attr_t
*attr
, void *addr
, size_t size
)
336 return 0; /* return success */
339 int __pthread_once(pthread_once_t
*once_control
, void (*init_routine
)(void))
341 static pthread_once_t the_once
= PTHREAD_ONCE_INIT
;
344 memcpy(&once_now
,&the_once
,sizeof(once_now
));
345 if (interlocked_cmpxchg((long*)once_control
, once_now
+1, once_now
) == once_now
)
349 strong_alias(__pthread_once
, pthread_once
);
351 void __pthread_kill_other_threads_np(void)
353 /* we don't need to do anything here */
355 strong_alias(__pthread_kill_other_threads_np
, pthread_kill_other_threads_np
);
359 #define MAX_ATFORK 8 /* libc doesn't need that many anyway */
361 static pthread_mutex_t atfork_mutex
= PTHREAD_MUTEX_INITIALIZER
;
363 typedef void (*atfork_handler
)();
364 static atfork_handler atfork_prepare
[MAX_ATFORK
];
365 static atfork_handler atfork_parent
[MAX_ATFORK
];
366 static atfork_handler atfork_child
[MAX_ATFORK
];
367 static int atfork_count
;
369 int __pthread_atfork(void (*prepare
)(void), void (*parent
)(void), void (*child
)(void))
371 pthread_mutex_lock( &atfork_mutex
);
372 assert( atfork_count
< MAX_ATFORK
);
373 atfork_prepare
[atfork_count
] = prepare
;
374 atfork_parent
[atfork_count
] = parent
;
375 atfork_child
[atfork_count
] = child
;
377 pthread_mutex_unlock( &atfork_mutex
);
380 strong_alias(__pthread_atfork
, pthread_atfork
);
389 libc_fork
= dlsym( RTLD_NEXT
, "fork" );
392 pthread_mutex_lock( &atfork_mutex
);
393 /* prepare handlers are called in reverse insertion order */
394 for (i
= atfork_count
- 1; i
>= 0; i
--) if (atfork_prepare
[i
]) atfork_prepare
[i
]();
395 if (!(pid
= libc_fork()))
397 pthread_mutex_init( &atfork_mutex
, NULL
);
398 for (i
= 0; i
< atfork_count
; i
++) if (atfork_child
[i
]) atfork_child
[i
]();
402 for (i
= 0; i
< atfork_count
; i
++) if (atfork_parent
[i
]) atfork_parent
[i
]();
403 pthread_mutex_unlock( &atfork_mutex
);
407 strong_alias(__fork
, fork
);
409 /***** MUTEXES *****/
411 int __pthread_mutex_init(pthread_mutex_t
*mutex
, const pthread_mutexattr_t
*mutexattr
)
413 if (!funcs
.ptr_pthread_mutex_init
) return 0;
414 return funcs
.ptr_pthread_mutex_init( mutex
, mutexattr
);
416 strong_alias(__pthread_mutex_init
, pthread_mutex_init
);
418 int __pthread_mutex_lock(pthread_mutex_t
*mutex
)
420 if (!funcs
.ptr_pthread_mutex_lock
) return 0;
421 return funcs
.ptr_pthread_mutex_lock( mutex
);
423 strong_alias(__pthread_mutex_lock
, pthread_mutex_lock
);
425 int __pthread_mutex_trylock(pthread_mutex_t
*mutex
)
427 if (!funcs
.ptr_pthread_mutex_trylock
) return 0;
428 return funcs
.ptr_pthread_mutex_trylock( mutex
);
430 strong_alias(__pthread_mutex_trylock
, pthread_mutex_trylock
);
432 int __pthread_mutex_unlock(pthread_mutex_t
*mutex
)
434 if (!funcs
.ptr_pthread_mutex_unlock
) return 0;
435 return funcs
.ptr_pthread_mutex_unlock( mutex
);
437 strong_alias(__pthread_mutex_unlock
, pthread_mutex_unlock
);
439 int __pthread_mutex_destroy(pthread_mutex_t
*mutex
)
441 if (!funcs
.ptr_pthread_mutex_destroy
) return 0;
442 return funcs
.ptr_pthread_mutex_destroy( mutex
);
444 strong_alias(__pthread_mutex_destroy
, pthread_mutex_destroy
);
447 /***** MUTEX ATTRIBUTES *****/
448 /* just dummies, since critical sections are always recursive */
450 int __pthread_mutexattr_init(pthread_mutexattr_t
*attr
)
454 strong_alias(__pthread_mutexattr_init
, pthread_mutexattr_init
);
456 int __pthread_mutexattr_destroy(pthread_mutexattr_t
*attr
)
460 strong_alias(__pthread_mutexattr_destroy
, pthread_mutexattr_destroy
);
462 int __pthread_mutexattr_setkind_np(pthread_mutexattr_t
*attr
, int kind
)
466 strong_alias(__pthread_mutexattr_setkind_np
, pthread_mutexattr_setkind_np
);
468 int __pthread_mutexattr_getkind_np(pthread_mutexattr_t
*attr
, int *kind
)
470 *kind
= PTHREAD_MUTEX_RECURSIVE
;
473 strong_alias(__pthread_mutexattr_getkind_np
, pthread_mutexattr_getkind_np
);
475 int __pthread_mutexattr_settype(pthread_mutexattr_t
*attr
, int kind
)
479 strong_alias(__pthread_mutexattr_settype
, pthread_mutexattr_settype
);
481 int __pthread_mutexattr_gettype(pthread_mutexattr_t
*attr
, int *kind
)
483 *kind
= PTHREAD_MUTEX_RECURSIVE
;
486 strong_alias(__pthread_mutexattr_gettype
, pthread_mutexattr_gettype
);
489 /***** THREAD-SPECIFIC VARIABLES (KEYS) *****/
491 int __pthread_key_create(pthread_key_t
*key
, void (*destr_function
)(void *))
493 static long keycnt
= FIRST_KEY
;
494 *key
= interlocked_xchg_add(&keycnt
, 1);
497 strong_alias(__pthread_key_create
, pthread_key_create
);
499 int __pthread_key_delete(pthread_key_t key
)
503 strong_alias(__pthread_key_delete
, pthread_key_delete
);
505 int __pthread_setspecific(pthread_key_t key
, const void *pointer
)
507 pthread_descr descr
= __pthread_thread_self();
508 descr
->key_data
[key
] = pointer
;
511 strong_alias(__pthread_setspecific
, pthread_setspecific
);
513 void *__pthread_getspecific(pthread_key_t key
)
515 pthread_descr descr
= __pthread_thread_self();
516 return (void *)descr
->key_data
[key
];
518 strong_alias(__pthread_getspecific
, pthread_getspecific
);
520 static int pthread_internal_tsd_set( int key
, const void *pointer
)
522 pthread_descr descr
= __pthread_thread_self();
523 descr
->tsd_data
[key
] = pointer
;
526 int (*__libc_internal_tsd_set
)(int, const void *) = pthread_internal_tsd_set
;
528 static void *pthread_internal_tsd_get( int key
)
530 pthread_descr descr
= __pthread_thread_self();
531 return (void *)descr
->tsd_data
[key
];
533 void* (*__libc_internal_tsd_get
)(int) = pthread_internal_tsd_get
;
535 static void ** __attribute__((const)) pthread_internal_tsd_address( int key
)
537 pthread_descr descr
= __pthread_thread_self();
538 return (void **)&descr
->tsd_data
[key
];
540 void** (*__libc_internal_tsd_address
)(int) = pthread_internal_tsd_address
;
542 /***** "EXCEPTION" FRAMES *****/
543 /* not implemented right now */
545 void _pthread_cleanup_push(struct _pthread_cleanup_buffer
*buffer
, void (*routine
)(void *), void *arg
)
547 ((wine_cleanup
)buffer
)->routine
= routine
;
548 ((wine_cleanup
)buffer
)->arg
= arg
;
551 void _pthread_cleanup_pop(struct _pthread_cleanup_buffer
*buffer
, int execute
)
553 if (execute
) (*(((wine_cleanup
)buffer
)->routine
))(((wine_cleanup
)buffer
)->arg
);
556 void _pthread_cleanup_push_defer(struct _pthread_cleanup_buffer
*buffer
, void (*routine
)(void *), void *arg
)
558 _pthread_cleanup_push(buffer
, routine
, arg
);
561 void _pthread_cleanup_pop_restore(struct _pthread_cleanup_buffer
*buffer
, int execute
)
563 _pthread_cleanup_pop(buffer
, execute
);
566 void __pthread_cleanup_upto(jmp_buf target
, char *frame
)
571 /***** CONDITIONS *****/
573 int __pthread_cond_init(pthread_cond_t
*cond
, const pthread_condattr_t
*cond_attr
)
575 if (!funcs
.ptr_pthread_cond_init
) return 0;
576 return funcs
.ptr_pthread_cond_init(cond
, cond_attr
);
578 strong_alias(__pthread_cond_init
, pthread_cond_init
);
580 int __pthread_cond_destroy(pthread_cond_t
*cond
)
582 if (!funcs
.ptr_pthread_cond_destroy
) return 0;
583 return funcs
.ptr_pthread_cond_destroy(cond
);
585 strong_alias(__pthread_cond_destroy
, pthread_cond_destroy
);
587 int __pthread_cond_signal(pthread_cond_t
*cond
)
589 if (!funcs
.ptr_pthread_cond_signal
) return 0;
590 return funcs
.ptr_pthread_cond_signal(cond
);
592 strong_alias(__pthread_cond_signal
, pthread_cond_signal
);
594 int __pthread_cond_broadcast(pthread_cond_t
*cond
)
596 if (!funcs
.ptr_pthread_cond_broadcast
) return 0;
597 return funcs
.ptr_pthread_cond_broadcast(cond
);
599 strong_alias(__pthread_cond_broadcast
, pthread_cond_broadcast
);
601 int __pthread_cond_wait(pthread_cond_t
*cond
, pthread_mutex_t
*mutex
)
603 if (!funcs
.ptr_pthread_cond_wait
) return 0;
604 return funcs
.ptr_pthread_cond_wait(cond
, mutex
);
606 strong_alias(__pthread_cond_wait
, pthread_cond_wait
);
608 int __pthread_cond_timedwait(pthread_cond_t
*cond
, pthread_mutex_t
*mutex
, const struct timespec
*abstime
)
610 if (!funcs
.ptr_pthread_cond_timedwait
) return 0;
611 return funcs
.ptr_pthread_cond_timedwait(cond
, mutex
, abstime
);
613 strong_alias(__pthread_cond_timedwait
, pthread_cond_timedwait
);
615 /**** CONDITION ATTRIBUTES *****/
616 /* not implemented right now */
618 int pthread_condattr_init(pthread_condattr_t
*attr
)
623 int pthread_condattr_destroy(pthread_condattr_t
*attr
)
628 /***** READ-WRITE LOCKS *****/
630 int __pthread_rwlock_init(pthread_rwlock_t
*rwlock
, const pthread_rwlockattr_t
*rwlock_attr
)
632 assert( funcs
.ptr_pthread_rwlock_init
);
633 return funcs
.ptr_pthread_rwlock_init( rwlock
, rwlock_attr
);
635 strong_alias(__pthread_rwlock_init
, pthread_rwlock_init
);
637 int __pthread_rwlock_destroy(pthread_rwlock_t
*rwlock
)
639 assert( funcs
.ptr_pthread_rwlock_destroy
);
640 return funcs
.ptr_pthread_rwlock_destroy( rwlock
);
642 strong_alias(__pthread_rwlock_destroy
, pthread_rwlock_destroy
);
644 int __pthread_rwlock_rdlock(pthread_rwlock_t
*rwlock
)
646 if (!funcs
.ptr_pthread_rwlock_rdlock
) return 0;
647 return funcs
.ptr_pthread_rwlock_rdlock( rwlock
);
649 strong_alias(__pthread_rwlock_rdlock
, pthread_rwlock_rdlock
);
651 int __pthread_rwlock_tryrdlock(pthread_rwlock_t
*rwlock
)
653 assert( funcs
.ptr_pthread_rwlock_tryrdlock
);
654 return funcs
.ptr_pthread_rwlock_tryrdlock( rwlock
);
656 strong_alias(__pthread_rwlock_tryrdlock
, pthread_rwlock_tryrdlock
);
658 int __pthread_rwlock_wrlock(pthread_rwlock_t
*rwlock
)
660 assert( funcs
.ptr_pthread_rwlock_wrlock
);
661 return funcs
.ptr_pthread_rwlock_wrlock( rwlock
);
663 strong_alias(__pthread_rwlock_wrlock
, pthread_rwlock_wrlock
);
665 int __pthread_rwlock_trywrlock(pthread_rwlock_t
*rwlock
)
667 assert( funcs
.ptr_pthread_rwlock_trywrlock
);
668 return funcs
.ptr_pthread_rwlock_trywrlock( rwlock
);
670 strong_alias(__pthread_rwlock_trywrlock
, pthread_rwlock_trywrlock
);
672 int __pthread_rwlock_unlock(pthread_rwlock_t
*rwlock
)
674 if (!funcs
.ptr_pthread_rwlock_unlock
) return 0;
675 return funcs
.ptr_pthread_rwlock_unlock( rwlock
);
677 strong_alias(__pthread_rwlock_unlock
, pthread_rwlock_unlock
);
679 /**** READ-WRITE LOCK ATTRIBUTES *****/
680 /* not implemented right now */
682 int pthread_rwlockattr_init(pthread_rwlockattr_t
*attr
)
687 int __pthread_rwlockattr_destroy(pthread_rwlockattr_t
*attr
)
691 strong_alias(__pthread_rwlockattr_destroy
, pthread_rwlockattr_destroy
);
693 int pthread_rwlockattr_getkind_np(const pthread_rwlockattr_t
*attr
, int *pref
)
699 int pthread_rwlockattr_setkind_np(pthread_rwlockattr_t
*attr
, int pref
)
706 pthread_t
pthread_self(void)
708 assert( funcs
.ptr_pthread_self
);
709 return funcs
.ptr_pthread_self();
712 int pthread_equal(pthread_t thread1
, pthread_t thread2
)
714 assert( funcs
.ptr_pthread_equal
);
715 return funcs
.ptr_pthread_equal( thread1
, thread2
);
718 void __pthread_do_exit(void *retval
, char *currentframe
)
720 assert( funcs
.ptr_pthread_exit
);
721 return funcs
.ptr_pthread_exit( retval
, currentframe
);
724 void __pthread_exit(void *retval
)
726 __pthread_do_exit( retval
, NULL
);
728 strong_alias(__pthread_exit
, pthread_exit
);
730 int pthread_setcancelstate(int state
, int *oldstate
)
732 pthread_descr descr
= __pthread_thread_self();
733 if (oldstate
) *oldstate
= descr
->cancel_state
;
734 descr
->cancel_state
= state
;
738 int pthread_setcanceltype(int type
, int *oldtype
)
740 pthread_descr descr
= __pthread_thread_self();
741 if (oldtype
) *oldtype
= descr
->cancel_type
;
742 descr
->cancel_type
= type
;
746 /***** ANTI-OVERRIDES *****/
747 /* pthreads tries to override these, point them back to libc */
749 int sigaction(int signum
, const struct sigaction
*act
, struct sigaction
*oldact
)
753 libc_sigaction
= dlsym( RTLD_NEXT
, "sigaction" );
754 assert( libc_sigaction
);
756 return libc_sigaction(signum
, act
, oldact
);
759 void __pthread_initialize(void)
766 libc_fork
= dlsym( RTLD_NEXT
, "fork" );
767 libc_sigaction
= dlsym( RTLD_NEXT
, "sigaction" );
768 libc_uselocale
= dlsym( RTLD_NEXT
, "uselocale" );
769 libc_pthread_init
= dlsym( RTLD_NEXT
, "__libc_pthread_init" );
770 if (libc_pthread_init
) libc_multiple_threads
= libc_pthread_init( &libc_pthread_functions
);
773 DECL_GLOBAL_CONSTRUCTOR(init
) { __pthread_initialize(); }
775 static struct pthread_functions libc_pthread_functions
=
777 NULL
, /* ptr_pthread_fork */
778 NULL
, /* FIXME */ /* ptr_pthread_attr_destroy */
779 NULL
, /* FIXME */ /* ptr___pthread_attr_init_2_0 */
780 NULL
, /* FIXME */ /* ptr___pthread_attr_init_2_1 */
781 NULL
, /* FIXME */ /* ptr_pthread_attr_getdetachstate */
782 NULL
, /* FIXME */ /* ptr_pthread_attr_setdetachstate */
783 NULL
, /* FIXME */ /* ptr_pthread_attr_getinheritsched */
784 NULL
, /* FIXME */ /* ptr_pthread_attr_setinheritsched */
785 NULL
, /* FIXME */ /* ptr_pthread_attr_getschedparam */
786 pthread_attr_setschedparam
, /* ptr_pthread_attr_setschedparam */
787 NULL
, /* FIXME */ /* ptr_pthread_attr_getschedpolicy) (const pthread_attr_t *, int *); */
788 NULL
, /* FIXME */ /* ptr_pthread_attr_setschedpolicy) (pthread_attr_t *, int); */
789 NULL
, /* FIXME */ /* ptr_pthread_attr_getscope) (const pthread_attr_t *, int *); */
790 NULL
, /* FIXME */ /* ptr_pthread_attr_setscope) (pthread_attr_t *, int); */
791 pthread_condattr_destroy
, /* ptr_pthread_condattr_destroy */
792 pthread_condattr_init
, /* ptr_pthread_condattr_init */
793 __pthread_cond_broadcast
, /* ptr___pthread_cond_broadcast */
794 __pthread_cond_destroy
, /* ptr___pthread_cond_destroy */
795 __pthread_cond_init
, /* ptr___pthread_cond_init */
796 __pthread_cond_signal
, /* ptr___pthread_cond_signal */
797 __pthread_cond_wait
, /* ptr___pthread_cond_wait */
798 pthread_equal
, /* ptr_pthread_equal */
799 __pthread_exit
, /* ptr___pthread_exit */
800 NULL
, /* FIXME */ /* ptr_pthread_getschedparam */
801 NULL
, /* FIXME */ /* ptr_pthread_setschedparam */
802 __pthread_mutex_destroy
, /* ptr_pthread_mutex_destroy */
803 __pthread_mutex_init
, /* ptr_pthread_mutex_init */
804 __pthread_mutex_lock
, /* ptr_pthread_mutex_lock */
805 __pthread_mutex_trylock
, /* ptr_pthread_mutex_trylock */
806 __pthread_mutex_unlock
, /* ptr_pthread_mutex_unlock */
807 pthread_self
, /* ptr_pthread_self */
808 pthread_setcancelstate
, /* ptr_pthread_setcancelstate */
809 pthread_setcanceltype
, /* ptr_pthread_setcanceltype */
810 __pthread_do_exit
, /* ptr_pthread_do_exit */
811 __pthread_cleanup_upto
, /* ptr_pthread_cleanup_upto */
812 __pthread_thread_self
, /* ptr_pthread_thread_self */
813 pthread_internal_tsd_set
, /* ptr_pthread_internal_tsd_set */
814 pthread_internal_tsd_get
, /* ptr_pthread_internal_tsd_get */
815 pthread_internal_tsd_address
, /* ptr_pthread_internal_tsd_address */
816 NULL
, /* ptr_pthread_sigaction */
817 NULL
, /* ptr_pthread_sigwait */
818 NULL
, /* ptr_pthread_raise */
819 __pthread_cond_timedwait
, /* ptr___pthread_cond_timedwait */
820 _pthread_cleanup_push
, /* ptr__pthread_cleanup_push */
821 _pthread_cleanup_pop
/* ptr__pthread_cleanup_pop */
824 #endif /* __GLIBC__ || __FREEBSD__ */
826 #else /* HAVE_NPTL */
828 void wine_pthread_init_process( const struct wine_pthread_functions
*functions
)
832 void wine_pthread_init_thread(void)
836 #endif /* HAVE_NPTL */