2 * pthread emulation based on kernel threads
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"
28 struct _pthread_cleanup_buffer
;
39 #include <sys/types.h>
40 #ifdef HAVE_SYS_SOCKET_H
41 # include <sys/socket.h>
43 #ifdef HAVE_SYS_MMAN_H
46 #ifdef HAVE_NETINET_IN_H
47 # include <netinet/in.h>
49 #ifdef HAVE_ARPA_NAMESER_H
50 # include <arpa/nameser.h>
55 #ifdef HAVE_VALGRIND_MEMCHECK_H
56 #include <valgrind/memcheck.h>
58 #ifdef HAVE_SYS_SYSCALL_H
59 # include <sys/syscall.h>
64 #ifdef HAVE_UCONTEXT_H
65 # include <ucontext.h>
71 #include "wine/library.h"
72 #include "wine/pthread.h"
74 #define P_OUTPUT(stuff) write(2,stuff,strlen(stuff))
76 #define PSTR(str) __ASM_NAME(#str)
78 static struct wine_pthread_functions funcs
;
80 /* thread descriptor */
83 #define MAX_KEYS 16 /* libc6 doesn't use that many, but... */
86 struct pthread_descr_struct
93 struct __res_state res_state
;
94 const void *key_data
[MAX_KEYS
]; /* for normal pthread keys */
95 const void *tsd_data
[MAX_TSD
]; /* for libc internal tsd variables */
98 typedef struct pthread_descr_struct
*pthread_descr
;
100 static struct pthread_descr_struct initial_descr
;
102 pthread_descr
__pthread_thread_self(void)
104 struct pthread_descr_struct
*descr
;
105 if (!funcs
.ptr_get_thread_data
) return &initial_descr
;
106 descr
= funcs
.ptr_get_thread_data();
107 if (!descr
) return &initial_descr
;
111 static int (*libc_uselocale
)(int set
);
112 static int *libc_multiple_threads
;
114 /***********************************************************************
115 * __errno_location/__error/__errno/___errno/__thr_errno
117 * Get the per-thread errno location.
119 int *__errno_location(void) /* Linux */
121 pthread_descr descr
= __pthread_thread_self();
122 return &descr
->thread_errno
;
124 int *__error(void) { return __errno_location(); } /* FreeBSD */
125 int *__errno(void) { return __errno_location(); } /* NetBSD */
126 int *___errno(void) { return __errno_location(); } /* Solaris */
127 int *__thr_errno(void) { return __errno_location(); } /* UnixWare */
129 /***********************************************************************
132 * Get the per-thread h_errno location.
134 int *__h_errno_location(void)
136 pthread_descr descr
= __pthread_thread_self();
137 return &descr
->thread_h_errno
;
140 struct __res_state
*__res_state(void)
142 pthread_descr descr
= __pthread_thread_self();
143 return &descr
->res_state
;
146 static inline void writejump( const char *symbol
, void *dest
)
148 #if defined(__GLIBC__) && defined(__i386__)
149 unsigned char *addr
= wine_dlsym( RTLD_NEXT
, symbol
, NULL
, 0 );
153 /* write a relative jump at the function address */
154 mprotect((void*)((unsigned int)addr
& ~(getpagesize()-1)), 5, PROT_READ
|PROT_EXEC
|PROT_WRITE
);
156 *(int *)(addr
+1) = (unsigned char *)dest
- (addr
+ 5);
157 mprotect((void*)((unsigned int)addr
& ~(getpagesize()-1)), 5, PROT_READ
|PROT_EXEC
);
159 # ifdef HAVE_VALGRIND_MEMCHECK_H
160 VALGRIND_DISCARD_TRANSLATIONS( addr
, 5 );
162 #endif /* __GLIBC__ && __i386__ */
165 /* temporary stacks used on thread exit */
166 #define TEMP_STACK_SIZE 1024
167 #define NB_TEMP_STACKS 8
168 static char temp_stacks
[NB_TEMP_STACKS
][TEMP_STACK_SIZE
];
169 static LONG next_temp_stack
; /* next temp stack to use */
171 /***********************************************************************
174 * Get a temporary stack address to run the thread exit code on.
176 inline static char *get_temp_stack(void)
178 unsigned int next
= interlocked_xchg_add( &next_temp_stack
, 1 );
179 return temp_stacks
[next
% NB_TEMP_STACKS
] + TEMP_STACK_SIZE
;
183 /***********************************************************************
186 * Cleanup the remains of a thread. Runs on a temporary stack.
188 static void cleanup_thread( void *ptr
)
190 /* copy the info structure since it is on the stack we will free */
191 struct wine_pthread_thread_info info
= *(struct wine_pthread_thread_info
*)ptr
;
192 wine_ldt_free_fs( info
.teb_sel
);
193 munmap( info
.stack_base
, info
.stack_size
);
194 munmap( info
.teb_base
, info
.teb_size
);
195 #ifdef HAVE__LWP_CREATE
198 _exit( info
.exit_status
);
202 /***********************************************************************
203 * wine_pthread_init_process
205 * Initialization for a newly created process.
207 void wine_pthread_init_process( const struct wine_pthread_functions
*functions
)
209 memcpy( &funcs
, functions
, min(functions
->size
,sizeof(funcs
)) );
210 funcs
.ptr_set_thread_data( &initial_descr
);
214 /***********************************************************************
215 * wine_pthread_init_thread
217 * Initialization for a newly created thread.
219 void wine_pthread_init_thread( struct wine_pthread_thread_info
*info
)
221 struct pthread_descr_struct
*descr
;
223 if (funcs
.ptr_set_thread_data
)
225 descr
= calloc( 1, sizeof(*descr
) );
226 funcs
.ptr_set_thread_data( descr
);
227 if (libc_multiple_threads
) *libc_multiple_threads
= 1;
229 else /* first thread */
231 descr
= &initial_descr
;
232 writejump( "__errno_location", __errno_location
);
233 writejump( "__h_errno_location", __h_errno_location
);
234 writejump( "__res_state", __res_state
);
236 descr
->cancel_state
= PTHREAD_CANCEL_ENABLE
;
237 descr
->cancel_type
= PTHREAD_CANCEL_ASYNCHRONOUS
;
238 if (libc_uselocale
) libc_uselocale( -1 /*LC_GLOBAL_LOCALE*/ );
242 /***********************************************************************
243 * wine_pthread_create_thread
245 int wine_pthread_create_thread( struct wine_pthread_thread_info
*info
)
247 if (!info
->stack_base
)
249 info
->stack_base
= wine_anon_mmap( NULL
, info
->stack_size
,
250 PROT_READ
| PROT_WRITE
| PROT_EXEC
, 0 );
251 if (info
->stack_base
== (void *)-1) return -1;
254 if (clone( (int (*)(void *))info
->entry
, (char *)info
->stack_base
+ info
->stack_size
,
255 CLONE_VM
| CLONE_FS
| CLONE_FILES
| SIGCHLD
, info
) < 0)
258 #elif defined(HAVE_RFORK)
260 void **sp
= (void **)((char *)info
->stack_base
+ info
->stack_size
);
264 __asm__
__volatile__(
265 "pushl %2;\n\t" /* flags */
266 "pushl $0;\n\t" /* 0 ? */
267 "movl %1,%%eax;\n\t" /* SYS_rfork */
268 ".byte 0x9a; .long 0; .word 7;\n\t" /* lcall 7:0... FreeBSD syscall */
269 "cmpl $0, %%edx;\n\t"
271 "movl %0,%%esp;\n\t" /* child -> new thread */
273 "1:\n\t" /* parent -> caller thread */
275 : "r" (sp
), "g" (SYS_rfork
), "g" (RFPROC
| RFMEM
| RFTHREAD
)
279 #elif defined(HAVE__LWP_CREATE)
282 _lwp_makecontext( &context
, (void(*)(void *))info
->entry
, info
,
283 NULL
, info
->stack_base
, info
->stack_size
);
284 if ( _lwp_create( &context
, 0, NULL
) )
293 /***********************************************************************
294 * wine_pthread_init_current_teb
296 * Set the current TEB for a new thread.
298 void wine_pthread_init_current_teb( struct wine_pthread_thread_info
*info
)
301 /* On the i386, the current thread is in the %fs register */
304 wine_ldt_set_base( &fs_entry
, info
->teb_base
);
305 wine_ldt_set_limit( &fs_entry
, info
->teb_size
- 1 );
306 wine_ldt_set_flags( &fs_entry
, WINE_LDT_FLAGS_DATA
|WINE_LDT_FLAGS_32BIT
);
307 wine_ldt_init_fs( info
->teb_sel
, &fs_entry
);
308 #elif defined(HAVE__LWP_CREATE)
309 /* On non-i386 Solaris, we use the LWP private pointer */
310 _lwp_setprivate( info
->teb_base
);
311 #elif defined(__powerpc__)
312 /* On PowerPC, the current TEB is in the gpr13 register */
314 __asm__
__volatile__("mr r13, %0" : : "r" (info
->teb_base
));
316 __asm__
__volatile__("mr 2, %0" : : "r" (info
->teb_base
));
318 #elif defined(__ALPHA__)
319 /* FIXME: On Alpha, the current TEB is not accessible to user-space */
320 /* __asm__ __volatile__();*/
322 # error You must implement wine_pthread_init_current_teb for your platform
325 /* set pid and tid */
326 info
->pid
= getpid();
327 #ifdef HAVE__LWP_SELF
328 info
->tid
= _lwp_self();
335 /***********************************************************************
336 * wine_pthread_get_current_teb
338 void *wine_pthread_get_current_teb(void)
343 __asm__( ".byte 0x64\n\tmovl 0x18,%0" : "=r" (ret
) );
344 #elif defined(HAVE__LWP_CREATE)
345 ret
= _lwp_getprivate();
346 #elif defined(__powerpc__)
348 __asm__( "mr %0,r13" : "=r" (ret
) );
350 __asm__( "mr %0,2" : "=r" (ret
) );
352 #elif defined(__ALPHA__)
353 /* 0x00ab is the PAL opcode for rdteb */
354 __asm__( "lda $30,8($30)\n\t"
356 "call_pal 0x00ab\n\t"
359 "lda $30,-8($30)" : "=r" (ret
) );
361 # error wine_pthread_get_current_teb not defined for this architecture
362 #endif /* __i386__ */
368 /***********************************************************************
369 * wine_pthread_exit_thread
371 void wine_pthread_exit_thread( struct wine_pthread_thread_info
*info
)
373 wine_switch_to_stack( cleanup_thread
, info
, get_temp_stack() );
377 /***********************************************************************
378 * wine_pthread_abort_thread
380 void wine_pthread_abort_thread( int status
)
382 #ifdef HAVE__LWP_CREATE
389 /* Currently this probably works only for glibc2,
390 * which checks for the presence of double-underscore-prepended
391 * pthread primitives, and use them if available.
392 * If they are not available, the libc defaults to
393 * non-threadsafe operation (not good). */
395 #if defined(HAVE_PTHREAD_H) && (defined(__GLIBC__) || defined(__FreeBSD__))
397 /* adapt as necessary (a construct like this is used in glibc sources) */
398 #define strong_alias(orig, alias) \
399 asm(".globl " PSTR(alias) "\n" \
400 "\t.set " PSTR(alias) "," PSTR(orig))
404 /* pthread functions redirection */
406 struct pthread_functions
408 pid_t (*ptr_pthread_fork
) (struct fork_block
*);
409 int (*ptr_pthread_attr_destroy
) (pthread_attr_t
*);
410 int (*ptr___pthread_attr_init_2_0
) (pthread_attr_t
*);
411 int (*ptr___pthread_attr_init_2_1
) (pthread_attr_t
*);
412 int (*ptr_pthread_attr_getdetachstate
) (const pthread_attr_t
*, int *);
413 int (*ptr_pthread_attr_setdetachstate
) (pthread_attr_t
*, int);
414 int (*ptr_pthread_attr_getinheritsched
) (const pthread_attr_t
*, int *);
415 int (*ptr_pthread_attr_setinheritsched
) (pthread_attr_t
*, int);
416 int (*ptr_pthread_attr_getschedparam
) (const pthread_attr_t
*, struct sched_param
*);
417 int (*ptr_pthread_attr_setschedparam
) (pthread_attr_t
*, const struct sched_param
*);
418 int (*ptr_pthread_attr_getschedpolicy
) (const pthread_attr_t
*, int *);
419 int (*ptr_pthread_attr_setschedpolicy
) (pthread_attr_t
*, int);
420 int (*ptr_pthread_attr_getscope
) (const pthread_attr_t
*, int *);
421 int (*ptr_pthread_attr_setscope
) (pthread_attr_t
*, int);
422 int (*ptr_pthread_condattr_destroy
) (pthread_condattr_t
*);
423 int (*ptr_pthread_condattr_init
) (pthread_condattr_t
*);
424 int (*ptr___pthread_cond_broadcast
) (pthread_cond_t
*);
425 int (*ptr___pthread_cond_destroy
) (pthread_cond_t
*);
426 int (*ptr___pthread_cond_init
) (pthread_cond_t
*, const pthread_condattr_t
*);
427 int (*ptr___pthread_cond_signal
) (pthread_cond_t
*);
428 int (*ptr___pthread_cond_wait
) (pthread_cond_t
*, pthread_mutex_t
*);
429 int (*ptr_pthread_equal
) (pthread_t
, pthread_t
);
430 void (*ptr___pthread_exit
) (void *);
431 int (*ptr_pthread_getschedparam
) (pthread_t
, int *, struct sched_param
*);
432 int (*ptr_pthread_setschedparam
) (pthread_t
, int, const struct sched_param
*);
433 int (*ptr_pthread_mutex_destroy
) (pthread_mutex_t
*);
434 int (*ptr_pthread_mutex_init
) (pthread_mutex_t
*, const pthread_mutexattr_t
*);
435 int (*ptr_pthread_mutex_lock
) (pthread_mutex_t
*);
436 int (*ptr_pthread_mutex_trylock
) (pthread_mutex_t
*);
437 int (*ptr_pthread_mutex_unlock
) (pthread_mutex_t
*);
438 pthread_t (*ptr_pthread_self
) (void);
439 int (*ptr_pthread_setcancelstate
) (int, int *);
440 int (*ptr_pthread_setcanceltype
) (int, int *);
441 void (*ptr_pthread_do_exit
) (void *retval
, char *currentframe
);
442 void (*ptr_pthread_cleanup_upto
) (jmp_buf target
, char *targetframe
);
443 pthread_descr (*ptr_pthread_thread_self
) (void);
444 int (*ptr_pthread_internal_tsd_set
) (int key
, const void *pointer
);
445 void * (*ptr_pthread_internal_tsd_get
) (int key
);
446 void ** __attribute__ ((__const__
)) (*ptr_pthread_internal_tsd_address
) (int key
);
447 int (*ptr_pthread_sigaction
) (int sig
, const struct sigaction
* act
, struct sigaction
*oact
);
448 int (*ptr_pthread_sigwait
) (const sigset_t
*set
, int *sig
);
449 int (*ptr_pthread_raise
) (int sig
);
450 int (*ptr___pthread_cond_timedwait
) (pthread_cond_t
*, pthread_mutex_t
*, const struct timespec
*);
451 void (*ptr__pthread_cleanup_push
) (struct _pthread_cleanup_buffer
* buffer
, void (*routine
)(void *), void * arg
);
452 void (*ptr__pthread_cleanup_pop
) (struct _pthread_cleanup_buffer
* buffer
, int execute
);
455 static pid_t (*libc_fork
)(void);
456 static int (*libc_sigaction
)(int signum
, const struct sigaction
*act
, struct sigaction
*oldact
);
457 static int *(*libc_pthread_init
)( const struct pthread_functions
*funcs
);
459 static struct pthread_functions libc_pthread_functions
;
461 strong_alias(__pthread_thread_self
, pthread_thread_self
);
463 /* redefine this to prevent libpthread from overriding our function pointers */
464 int *__libc_pthread_init( const struct pthread_functions
*funcs
)
466 return libc_multiple_threads
;
469 typedef struct _wine_cleanup
{
470 void (*routine
)(void *);
474 int pthread_create(pthread_t
* thread
, const pthread_attr_t
* attr
, void*
475 (*start_routine
)(void *), void* arg
)
477 assert( funcs
.ptr_pthread_create
);
478 return funcs
.ptr_pthread_create( thread
, attr
, start_routine
, arg
);
481 int pthread_cancel(pthread_t thread
)
483 assert( funcs
.ptr_pthread_cancel
);
484 return funcs
.ptr_pthread_cancel( thread
);
487 int pthread_join(pthread_t thread
, void **value_ptr
)
489 assert( funcs
.ptr_pthread_join
);
490 return funcs
.ptr_pthread_join( thread
, value_ptr
);
493 int pthread_detach(pthread_t thread
)
495 assert( funcs
.ptr_pthread_detach
);
496 return funcs
.ptr_pthread_detach( thread
);
499 /* FIXME: we have no equivalents in win32 for the policys */
500 /* so just keep this as a stub */
501 int pthread_attr_setschedpolicy(pthread_attr_t
*attr
, int policy
)
503 P_OUTPUT("FIXME:pthread_attr_setschedpolicy\n");
507 /* FIXME: no win32 equivalent for scope */
508 int pthread_attr_setscope(pthread_attr_t
*attr
, int scope
)
510 P_OUTPUT("FIXME:pthread_attr_setscope\n");
511 return 0; /* return success */
514 /* FIXME: no win32 equivalent for schedule param */
515 int pthread_attr_setschedparam(pthread_attr_t
*attr
,
516 const struct sched_param
*param
)
518 P_OUTPUT("FIXME:pthread_attr_setschedparam\n");
519 return 0; /* return success */
523 int pthread_attr_setstack(pthread_attr_t
*attr
, void *addr
, size_t size
)
525 return 0; /* return success */
528 int __pthread_once(pthread_once_t
*once_control
, void (*init_routine
)(void))
530 static pthread_once_t the_once
= PTHREAD_ONCE_INIT
;
533 memcpy(&once_now
,&the_once
,sizeof(once_now
));
534 if (interlocked_cmpxchg((long*)once_control
, once_now
+1, once_now
) == once_now
)
538 strong_alias(__pthread_once
, pthread_once
);
540 void __pthread_kill_other_threads_np(void)
542 /* we don't need to do anything here */
544 strong_alias(__pthread_kill_other_threads_np
, pthread_kill_other_threads_np
);
548 #define MAX_ATFORK 8 /* libc doesn't need that many anyway */
550 static pthread_mutex_t atfork_mutex
= PTHREAD_MUTEX_INITIALIZER
;
552 typedef void (*atfork_handler
)();
553 static atfork_handler atfork_prepare
[MAX_ATFORK
];
554 static atfork_handler atfork_parent
[MAX_ATFORK
];
555 static atfork_handler atfork_child
[MAX_ATFORK
];
556 static int atfork_count
;
558 int __pthread_atfork(void (*prepare
)(void), void (*parent
)(void), void (*child
)(void))
560 pthread_mutex_lock( &atfork_mutex
);
561 assert( atfork_count
< MAX_ATFORK
);
562 atfork_prepare
[atfork_count
] = prepare
;
563 atfork_parent
[atfork_count
] = parent
;
564 atfork_child
[atfork_count
] = child
;
566 pthread_mutex_unlock( &atfork_mutex
);
569 strong_alias(__pthread_atfork
, pthread_atfork
);
578 libc_fork
= wine_dlsym( RTLD_NEXT
, "fork", NULL
, 0 );
581 pthread_mutex_lock( &atfork_mutex
);
582 /* prepare handlers are called in reverse insertion order */
583 for (i
= atfork_count
- 1; i
>= 0; i
--) if (atfork_prepare
[i
]) atfork_prepare
[i
]();
584 if (!(pid
= libc_fork()))
586 pthread_mutex_init( &atfork_mutex
, NULL
);
587 for (i
= 0; i
< atfork_count
; i
++) if (atfork_child
[i
]) atfork_child
[i
]();
591 for (i
= 0; i
< atfork_count
; i
++) if (atfork_parent
[i
]) atfork_parent
[i
]();
592 pthread_mutex_unlock( &atfork_mutex
);
596 strong_alias(__fork
, fork
);
598 /***** MUTEXES *****/
600 int __pthread_mutex_init(pthread_mutex_t
*mutex
, const pthread_mutexattr_t
*mutexattr
)
602 if (!funcs
.ptr_pthread_mutex_init
) return 0;
603 return funcs
.ptr_pthread_mutex_init( mutex
, mutexattr
);
605 strong_alias(__pthread_mutex_init
, pthread_mutex_init
);
607 int __pthread_mutex_lock(pthread_mutex_t
*mutex
)
609 if (!funcs
.ptr_pthread_mutex_lock
) return 0;
610 return funcs
.ptr_pthread_mutex_lock( mutex
);
612 strong_alias(__pthread_mutex_lock
, pthread_mutex_lock
);
614 int __pthread_mutex_trylock(pthread_mutex_t
*mutex
)
616 if (!funcs
.ptr_pthread_mutex_trylock
) return 0;
617 return funcs
.ptr_pthread_mutex_trylock( mutex
);
619 strong_alias(__pthread_mutex_trylock
, pthread_mutex_trylock
);
621 int __pthread_mutex_unlock(pthread_mutex_t
*mutex
)
623 if (!funcs
.ptr_pthread_mutex_unlock
) return 0;
624 return funcs
.ptr_pthread_mutex_unlock( mutex
);
626 strong_alias(__pthread_mutex_unlock
, pthread_mutex_unlock
);
628 int __pthread_mutex_destroy(pthread_mutex_t
*mutex
)
630 if (!funcs
.ptr_pthread_mutex_destroy
) return 0;
631 return funcs
.ptr_pthread_mutex_destroy( mutex
);
633 strong_alias(__pthread_mutex_destroy
, pthread_mutex_destroy
);
636 /***** MUTEX ATTRIBUTES *****/
637 /* just dummies, since critical sections are always recursive */
639 int __pthread_mutexattr_init(pthread_mutexattr_t
*attr
)
643 strong_alias(__pthread_mutexattr_init
, pthread_mutexattr_init
);
645 int __pthread_mutexattr_destroy(pthread_mutexattr_t
*attr
)
649 strong_alias(__pthread_mutexattr_destroy
, pthread_mutexattr_destroy
);
651 int __pthread_mutexattr_setkind_np(pthread_mutexattr_t
*attr
, int kind
)
655 strong_alias(__pthread_mutexattr_setkind_np
, pthread_mutexattr_setkind_np
);
657 int __pthread_mutexattr_getkind_np(pthread_mutexattr_t
*attr
, int *kind
)
659 *kind
= PTHREAD_MUTEX_RECURSIVE
;
662 strong_alias(__pthread_mutexattr_getkind_np
, pthread_mutexattr_getkind_np
);
664 int __pthread_mutexattr_settype(pthread_mutexattr_t
*attr
, int kind
)
668 strong_alias(__pthread_mutexattr_settype
, pthread_mutexattr_settype
);
670 int __pthread_mutexattr_gettype(const pthread_mutexattr_t
*attr
, int *kind
)
672 *kind
= PTHREAD_MUTEX_RECURSIVE
;
675 strong_alias(__pthread_mutexattr_gettype
, pthread_mutexattr_gettype
);
678 /***** THREAD-SPECIFIC VARIABLES (KEYS) *****/
680 int __pthread_key_create(pthread_key_t
*key
, void (*destr_function
)(void *))
682 static long keycnt
= FIRST_KEY
;
683 *key
= interlocked_xchg_add(&keycnt
, 1);
686 strong_alias(__pthread_key_create
, pthread_key_create
);
688 int __pthread_key_delete(pthread_key_t key
)
692 strong_alias(__pthread_key_delete
, pthread_key_delete
);
694 int __pthread_setspecific(pthread_key_t key
, const void *pointer
)
696 pthread_descr descr
= __pthread_thread_self();
697 descr
->key_data
[key
] = pointer
;
700 strong_alias(__pthread_setspecific
, pthread_setspecific
);
702 void *__pthread_getspecific(pthread_key_t key
)
704 pthread_descr descr
= __pthread_thread_self();
705 return (void *)descr
->key_data
[key
];
707 strong_alias(__pthread_getspecific
, pthread_getspecific
);
709 static int pthread_internal_tsd_set( int key
, const void *pointer
)
711 pthread_descr descr
= __pthread_thread_self();
712 descr
->tsd_data
[key
] = pointer
;
715 int (*__libc_internal_tsd_set
)(int, const void *) = pthread_internal_tsd_set
;
717 static void *pthread_internal_tsd_get( int key
)
719 pthread_descr descr
= __pthread_thread_self();
720 return (void *)descr
->tsd_data
[key
];
722 void* (*__libc_internal_tsd_get
)(int) = pthread_internal_tsd_get
;
724 static void ** __attribute__((const)) pthread_internal_tsd_address( int key
)
726 pthread_descr descr
= __pthread_thread_self();
727 return (void **)&descr
->tsd_data
[key
];
729 void** (*__libc_internal_tsd_address
)(int) = pthread_internal_tsd_address
;
731 /***** "EXCEPTION" FRAMES *****/
732 /* not implemented right now */
734 void _pthread_cleanup_push(struct _pthread_cleanup_buffer
*buffer
, void (*routine
)(void *), void *arg
)
736 ((wine_cleanup
)buffer
)->routine
= routine
;
737 ((wine_cleanup
)buffer
)->arg
= arg
;
740 void _pthread_cleanup_pop(struct _pthread_cleanup_buffer
*buffer
, int execute
)
742 if (execute
) (*(((wine_cleanup
)buffer
)->routine
))(((wine_cleanup
)buffer
)->arg
);
745 void _pthread_cleanup_push_defer(struct _pthread_cleanup_buffer
*buffer
, void (*routine
)(void *), void *arg
)
747 _pthread_cleanup_push(buffer
, routine
, arg
);
750 void _pthread_cleanup_pop_restore(struct _pthread_cleanup_buffer
*buffer
, int execute
)
752 _pthread_cleanup_pop(buffer
, execute
);
755 void __pthread_cleanup_upto(jmp_buf target
, char *frame
)
760 /***** CONDITIONS *****/
762 int __pthread_cond_init(pthread_cond_t
*cond
, const pthread_condattr_t
*cond_attr
)
764 if (!funcs
.ptr_pthread_cond_init
) return 0;
765 return funcs
.ptr_pthread_cond_init(cond
, cond_attr
);
767 strong_alias(__pthread_cond_init
, pthread_cond_init
);
769 int __pthread_cond_destroy(pthread_cond_t
*cond
)
771 if (!funcs
.ptr_pthread_cond_destroy
) return 0;
772 return funcs
.ptr_pthread_cond_destroy(cond
);
774 strong_alias(__pthread_cond_destroy
, pthread_cond_destroy
);
776 int __pthread_cond_signal(pthread_cond_t
*cond
)
778 if (!funcs
.ptr_pthread_cond_signal
) return 0;
779 return funcs
.ptr_pthread_cond_signal(cond
);
781 strong_alias(__pthread_cond_signal
, pthread_cond_signal
);
783 int __pthread_cond_broadcast(pthread_cond_t
*cond
)
785 if (!funcs
.ptr_pthread_cond_broadcast
) return 0;
786 return funcs
.ptr_pthread_cond_broadcast(cond
);
788 strong_alias(__pthread_cond_broadcast
, pthread_cond_broadcast
);
790 int __pthread_cond_wait(pthread_cond_t
*cond
, pthread_mutex_t
*mutex
)
792 if (!funcs
.ptr_pthread_cond_wait
) return 0;
793 return funcs
.ptr_pthread_cond_wait(cond
, mutex
);
795 strong_alias(__pthread_cond_wait
, pthread_cond_wait
);
797 int __pthread_cond_timedwait(pthread_cond_t
*cond
, pthread_mutex_t
*mutex
, const struct timespec
*abstime
)
799 if (!funcs
.ptr_pthread_cond_timedwait
) return 0;
800 return funcs
.ptr_pthread_cond_timedwait(cond
, mutex
, abstime
);
802 strong_alias(__pthread_cond_timedwait
, pthread_cond_timedwait
);
804 /**** CONDITION ATTRIBUTES *****/
805 /* not implemented right now */
807 int pthread_condattr_init(pthread_condattr_t
*attr
)
812 int pthread_condattr_destroy(pthread_condattr_t
*attr
)
817 /***** READ-WRITE LOCKS *****/
819 int __pthread_rwlock_init(pthread_rwlock_t
*rwlock
, const pthread_rwlockattr_t
*rwlock_attr
)
821 assert( funcs
.ptr_pthread_rwlock_init
);
822 return funcs
.ptr_pthread_rwlock_init( rwlock
, rwlock_attr
);
824 strong_alias(__pthread_rwlock_init
, pthread_rwlock_init
);
826 int __pthread_rwlock_destroy(pthread_rwlock_t
*rwlock
)
828 assert( funcs
.ptr_pthread_rwlock_destroy
);
829 return funcs
.ptr_pthread_rwlock_destroy( rwlock
);
831 strong_alias(__pthread_rwlock_destroy
, pthread_rwlock_destroy
);
833 int __pthread_rwlock_rdlock(pthread_rwlock_t
*rwlock
)
835 if (!funcs
.ptr_pthread_rwlock_rdlock
) return 0;
836 return funcs
.ptr_pthread_rwlock_rdlock( rwlock
);
838 strong_alias(__pthread_rwlock_rdlock
, pthread_rwlock_rdlock
);
840 int __pthread_rwlock_tryrdlock(pthread_rwlock_t
*rwlock
)
842 assert( funcs
.ptr_pthread_rwlock_tryrdlock
);
843 return funcs
.ptr_pthread_rwlock_tryrdlock( rwlock
);
845 strong_alias(__pthread_rwlock_tryrdlock
, pthread_rwlock_tryrdlock
);
847 int __pthread_rwlock_wrlock(pthread_rwlock_t
*rwlock
)
849 assert( funcs
.ptr_pthread_rwlock_wrlock
);
850 return funcs
.ptr_pthread_rwlock_wrlock( rwlock
);
852 strong_alias(__pthread_rwlock_wrlock
, pthread_rwlock_wrlock
);
854 int __pthread_rwlock_trywrlock(pthread_rwlock_t
*rwlock
)
856 assert( funcs
.ptr_pthread_rwlock_trywrlock
);
857 return funcs
.ptr_pthread_rwlock_trywrlock( rwlock
);
859 strong_alias(__pthread_rwlock_trywrlock
, pthread_rwlock_trywrlock
);
861 int __pthread_rwlock_unlock(pthread_rwlock_t
*rwlock
)
863 if (!funcs
.ptr_pthread_rwlock_unlock
) return 0;
864 return funcs
.ptr_pthread_rwlock_unlock( rwlock
);
866 strong_alias(__pthread_rwlock_unlock
, pthread_rwlock_unlock
);
868 /**** READ-WRITE LOCK ATTRIBUTES *****/
869 /* not implemented right now */
871 int pthread_rwlockattr_init(pthread_rwlockattr_t
*attr
)
876 int __pthread_rwlockattr_destroy(pthread_rwlockattr_t
*attr
)
880 strong_alias(__pthread_rwlockattr_destroy
, pthread_rwlockattr_destroy
);
882 int pthread_rwlockattr_getkind_np(const pthread_rwlockattr_t
*attr
, int *pref
)
888 int pthread_rwlockattr_setkind_np(pthread_rwlockattr_t
*attr
, int pref
)
895 pthread_t
pthread_self(void)
897 assert( funcs
.ptr_pthread_self
);
898 return funcs
.ptr_pthread_self();
901 int pthread_equal(pthread_t thread1
, pthread_t thread2
)
903 assert( funcs
.ptr_pthread_equal
);
904 return funcs
.ptr_pthread_equal( thread1
, thread2
);
907 void __pthread_do_exit(void *retval
, char *currentframe
)
909 assert( funcs
.ptr_pthread_exit
);
910 return funcs
.ptr_pthread_exit( retval
, currentframe
);
913 void __pthread_exit(void *retval
)
915 __pthread_do_exit( retval
, NULL
);
917 strong_alias(__pthread_exit
, pthread_exit
);
919 int pthread_setcancelstate(int state
, int *oldstate
)
921 pthread_descr descr
= __pthread_thread_self();
922 if (oldstate
) *oldstate
= descr
->cancel_state
;
923 descr
->cancel_state
= state
;
927 int pthread_setcanceltype(int type
, int *oldtype
)
929 pthread_descr descr
= __pthread_thread_self();
930 if (oldtype
) *oldtype
= descr
->cancel_type
;
931 descr
->cancel_type
= type
;
935 /***** ANTI-OVERRIDES *****/
936 /* pthreads tries to override these, point them back to libc */
938 int sigaction(int signum
, const struct sigaction
*act
, struct sigaction
*oldact
)
942 libc_sigaction
= wine_dlsym( RTLD_NEXT
, "sigaction", NULL
, 0 );
943 assert( libc_sigaction
);
945 return libc_sigaction(signum
, act
, oldact
);
948 void __pthread_initialize(void)
955 libc_fork
= wine_dlsym( RTLD_NEXT
, "fork", NULL
, 0 );
956 libc_sigaction
= wine_dlsym( RTLD_NEXT
, "sigaction", NULL
, 0 );
957 libc_uselocale
= wine_dlsym( RTLD_DEFAULT
, "uselocale", NULL
, 0 );
958 libc_pthread_init
= wine_dlsym( RTLD_NEXT
, "__libc_pthread_init", NULL
, 0 );
959 if (libc_pthread_init
) libc_multiple_threads
= libc_pthread_init( &libc_pthread_functions
);
962 DECL_GLOBAL_CONSTRUCTOR(init
) { __pthread_initialize(); }
964 static struct pthread_functions libc_pthread_functions
=
966 NULL
, /* ptr_pthread_fork */
967 NULL
, /* FIXME */ /* ptr_pthread_attr_destroy */
968 NULL
, /* FIXME */ /* ptr___pthread_attr_init_2_0 */
969 NULL
, /* FIXME */ /* ptr___pthread_attr_init_2_1 */
970 NULL
, /* FIXME */ /* ptr_pthread_attr_getdetachstate */
971 NULL
, /* FIXME */ /* ptr_pthread_attr_setdetachstate */
972 NULL
, /* FIXME */ /* ptr_pthread_attr_getinheritsched */
973 NULL
, /* FIXME */ /* ptr_pthread_attr_setinheritsched */
974 NULL
, /* FIXME */ /* ptr_pthread_attr_getschedparam */
975 pthread_attr_setschedparam
, /* ptr_pthread_attr_setschedparam */
976 NULL
, /* FIXME */ /* ptr_pthread_attr_getschedpolicy */
977 NULL
, /* FIXME */ /* ptr_pthread_attr_setschedpolicy */
978 NULL
, /* FIXME */ /* ptr_pthread_attr_getscope */
979 NULL
, /* FIXME */ /* ptr_pthread_attr_setscope */
980 pthread_condattr_destroy
, /* ptr_pthread_condattr_destroy */
981 pthread_condattr_init
, /* ptr_pthread_condattr_init */
982 __pthread_cond_broadcast
, /* ptr___pthread_cond_broadcast */
983 __pthread_cond_destroy
, /* ptr___pthread_cond_destroy */
984 __pthread_cond_init
, /* ptr___pthread_cond_init */
985 __pthread_cond_signal
, /* ptr___pthread_cond_signal */
986 __pthread_cond_wait
, /* ptr___pthread_cond_wait */
987 pthread_equal
, /* ptr_pthread_equal */
988 __pthread_exit
, /* ptr___pthread_exit */
989 NULL
, /* FIXME */ /* ptr_pthread_getschedparam */
990 NULL
, /* FIXME */ /* ptr_pthread_setschedparam */
991 __pthread_mutex_destroy
, /* ptr_pthread_mutex_destroy */
992 __pthread_mutex_init
, /* ptr_pthread_mutex_init */
993 __pthread_mutex_lock
, /* ptr_pthread_mutex_lock */
994 __pthread_mutex_trylock
, /* ptr_pthread_mutex_trylock */
995 __pthread_mutex_unlock
, /* ptr_pthread_mutex_unlock */
996 pthread_self
, /* ptr_pthread_self */
997 pthread_setcancelstate
, /* ptr_pthread_setcancelstate */
998 pthread_setcanceltype
, /* ptr_pthread_setcanceltype */
999 __pthread_do_exit
, /* ptr_pthread_do_exit */
1000 __pthread_cleanup_upto
, /* ptr_pthread_cleanup_upto */
1001 __pthread_thread_self
, /* ptr_pthread_thread_self */
1002 pthread_internal_tsd_set
, /* ptr_pthread_internal_tsd_set */
1003 pthread_internal_tsd_get
, /* ptr_pthread_internal_tsd_get */
1004 pthread_internal_tsd_address
, /* ptr_pthread_internal_tsd_address */
1005 NULL
, /* ptr_pthread_sigaction */
1006 NULL
, /* ptr_pthread_sigwait */
1007 NULL
, /* ptr_pthread_raise */
1008 __pthread_cond_timedwait
, /* ptr___pthread_cond_timedwait */
1009 _pthread_cleanup_push
, /* ptr__pthread_cleanup_push */
1010 _pthread_cleanup_pop
/* ptr__pthread_cleanup_pop */
1013 #endif /* HAVE_PTHREAD_H && (__GLIBC__ || __FREEBSD__) */