Fixed DOS EXE loader for the case where we realy have only 4 bytes on
[wine/multimedia.git] / loader / kthread.c
blob7255f6b68233e8ca88340e19e223a3c27e2e1edb
1 /*
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
25 #include "config.h"
26 #include "wine/port.h"
28 struct _pthread_cleanup_buffer;
30 #include <assert.h>
31 #include <errno.h>
32 #include <stdlib.h>
33 #include <signal.h>
34 #include <setjmp.h>
35 #ifdef HAVE_UNISTD_H
36 # include <unistd.h>
37 #endif
38 #include <string.h>
39 #include <sys/types.h>
40 #ifdef HAVE_SYS_SOCKET_H
41 # include <sys/socket.h>
42 #endif
43 #ifdef HAVE_SYS_MMAN_H
44 #include <sys/mman.h>
45 #endif
46 #ifdef HAVE_NETINET_IN_H
47 # include <netinet/in.h>
48 #endif
49 #ifdef HAVE_ARPA_NAMESER_H
50 # include <arpa/nameser.h>
51 #endif
52 #ifdef HAVE_RESOLV_H
53 # include <resolv.h>
54 #endif
55 #ifdef HAVE_VALGRIND_MEMCHECK_H
56 #include <valgrind/memcheck.h>
57 #endif
58 #ifdef HAVE_SYS_SYSCALL_H
59 # include <sys/syscall.h>
60 #endif
61 #ifdef HAVE_SYS_LWP_H
62 # include <sys/lwp.h>
63 #endif
64 #ifdef HAVE_UCONTEXT_H
65 # include <ucontext.h>
66 #endif
67 #ifdef HAVE_SCHED_H
68 #include <sched.h>
69 #endif
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 */
82 #define FIRST_KEY 0
83 #define MAX_KEYS 16 /* libc6 doesn't use that many, but... */
84 #define MAX_TSD 16
86 struct pthread_descr_struct
88 char dummy[2048];
89 int thread_errno;
90 int thread_h_errno;
91 int cancel_state;
92 int cancel_type;
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;
108 return 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 /***********************************************************************
130 * __h_errno_location
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 = dlsym( RTLD_NEXT, symbol );
151 if (!addr) return;
153 /* write a relative jump at the function address */
154 mprotect((void*)((unsigned int)addr & ~(getpagesize()-1)), 5, PROT_READ|PROT_EXEC|PROT_WRITE);
155 addr[0] = 0xe9;
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 );
161 # endif
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 /***********************************************************************
172 * get_temp_stack
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 /***********************************************************************
184 * cleanup_thread
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
196 _lwp_exit();
197 #endif
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 #ifdef __i386__
224 /* On the i386, the current thread is in the %fs register */
225 LDT_ENTRY fs_entry;
227 wine_ldt_set_base( &fs_entry, info->teb_base );
228 wine_ldt_set_limit( &fs_entry, info->teb_size - 1 );
229 wine_ldt_set_flags( &fs_entry, WINE_LDT_FLAGS_DATA|WINE_LDT_FLAGS_32BIT );
230 wine_ldt_init_fs( info->teb_sel, &fs_entry );
231 #elif defined(__powerpc__)
232 /* On PowerPC, the current TEB is in the gpr13 register */
233 # ifdef __APPLE__
234 __asm__ __volatile__("mr r13, %0" : : "r" (info->teb_base));
235 # else
236 __asm__ __volatile__("mr 2, %0" : : "r" (info->teb_base));
237 # endif
238 #elif defined(HAVE__LWP_CREATE)
239 /* On non-i386 Solaris, we use the LWP private pointer */
240 _lwp_setprivate( info->teb_base );
241 #endif
243 /* set pid and tid */
244 info->pid = getpid();
245 #ifdef HAVE__LWP_SELF
246 info->tid = _lwp_self();
247 #else
248 info->tid = -1;
249 #endif
251 if (funcs.ptr_set_thread_data)
253 descr = calloc( 1, sizeof(*descr) );
254 funcs.ptr_set_thread_data( descr );
255 if (libc_multiple_threads) *libc_multiple_threads = 1;
257 else /* first thread */
259 descr = &initial_descr;
260 writejump( "__errno_location", __errno_location );
261 writejump( "__h_errno_location", __h_errno_location );
262 writejump( "__res_state", __res_state );
264 descr->cancel_state = PTHREAD_CANCEL_ENABLE;
265 descr->cancel_type = PTHREAD_CANCEL_ASYNCHRONOUS;
266 if (libc_uselocale) libc_uselocale( -1 /*LC_GLOBAL_LOCALE*/ );
270 /***********************************************************************
271 * wine_pthread_create_thread
273 int wine_pthread_create_thread( struct wine_pthread_thread_info *info )
275 if (!info->stack_base)
277 info->stack_base = wine_anon_mmap( NULL, info->stack_size,
278 PROT_READ | PROT_WRITE | PROT_EXEC, 0 );
279 if (info->stack_base == (void *)-1) return -1;
281 #ifdef HAVE_CLONE
282 if (clone( (int (*)(void *))info->entry, (char *)info->stack_base + info->stack_size,
283 CLONE_VM | CLONE_FS | CLONE_FILES | SIGCHLD, info ) < 0)
284 return -1;
285 return 0;
286 #elif defined(HAVE_RFORK)
288 void **sp = (void **)((char *)info->stack_base + info->stack_size);
289 *--sp = info;
290 *--sp = 0;
291 *--sp = info->entry;
292 __asm__ __volatile__(
293 "pushl %2;\n\t" /* flags */
294 "pushl $0;\n\t" /* 0 ? */
295 "movl %1,%%eax;\n\t" /* SYS_rfork */
296 ".byte 0x9a; .long 0; .word 7;\n\t" /* lcall 7:0... FreeBSD syscall */
297 "cmpl $0, %%edx;\n\t"
298 "je 1f;\n\t"
299 "movl %0,%%esp;\n\t" /* child -> new thread */
300 "ret;\n"
301 "1:\n\t" /* parent -> caller thread */
302 "addl $8,%%esp" :
303 : "r" (sp), "g" (SYS_rfork), "g" (RFPROC | RFMEM | RFTHREAD)
304 : "eax", "edx");
305 return 0;
307 #elif defined(HAVE__LWP_CREATE)
309 ucontext_t context;
310 _lwp_makecontext( &context, (void(*)(void *))info->entry, info,
311 NULL, info->stack_base, info->stack_size );
312 if ( _lwp_create( &context, 0, NULL ) )
313 return -1;
314 return 0;
316 #endif
317 return -1;
321 /***********************************************************************
322 * wine_pthread_get_current_teb
324 void *wine_pthread_get_current_teb(void)
326 void *ret;
328 #ifdef __i386__
329 __asm__( ".byte 0x64\n\tmovl 0x18,%0" : "=r" (ret) );
330 #elif defined(HAVE__LWP_CREATE)
331 ret = _lwp_getprivate();
332 #elif defined(__powerpc__)
333 # ifdef __APPLE__
334 __asm__( "mr %0,r13" : "=r" (ret) );
335 # else
336 __asm__( "mr %0,2" : "=r" (ret) );
337 # endif
338 #else
339 # error wine_pthread_get_current_teb not defined for this architecture
340 #endif /* __i386__ */
342 return ret;
346 /***********************************************************************
347 * wine_pthread_exit_thread
349 void wine_pthread_exit_thread( struct wine_pthread_thread_info *info )
351 wine_switch_to_stack( cleanup_thread, info, get_temp_stack() );
355 /***********************************************************************
356 * wine_pthread_abort_thread
358 void wine_pthread_abort_thread( int status )
360 #ifdef HAVE__LWP_CREATE
361 _lwp_exit();
362 #endif
363 _exit( status );
367 /* Currently this probably works only for glibc2,
368 * which checks for the presence of double-underscore-prepended
369 * pthread primitives, and use them if available.
370 * If they are not available, the libc defaults to
371 * non-threadsafe operation (not good). */
373 #if defined(__GLIBC__) || defined(__FreeBSD__)
375 /* adapt as necessary (a construct like this is used in glibc sources) */
376 #define strong_alias(orig, alias) \
377 asm(".globl " PSTR(alias) "\n" \
378 "\t.set " PSTR(alias) "," PSTR(orig))
380 struct fork_block;
382 /* pthread functions redirection */
384 struct pthread_functions
386 pid_t (*ptr_pthread_fork) (struct fork_block *);
387 int (*ptr_pthread_attr_destroy) (pthread_attr_t *);
388 int (*ptr___pthread_attr_init_2_0) (pthread_attr_t *);
389 int (*ptr___pthread_attr_init_2_1) (pthread_attr_t *);
390 int (*ptr_pthread_attr_getdetachstate) (const pthread_attr_t *, int *);
391 int (*ptr_pthread_attr_setdetachstate) (pthread_attr_t *, int);
392 int (*ptr_pthread_attr_getinheritsched) (const pthread_attr_t *, int *);
393 int (*ptr_pthread_attr_setinheritsched) (pthread_attr_t *, int);
394 int (*ptr_pthread_attr_getschedparam) (const pthread_attr_t *, struct sched_param *);
395 int (*ptr_pthread_attr_setschedparam) (pthread_attr_t *, const struct sched_param *);
396 int (*ptr_pthread_attr_getschedpolicy) (const pthread_attr_t *, int *);
397 int (*ptr_pthread_attr_setschedpolicy) (pthread_attr_t *, int);
398 int (*ptr_pthread_attr_getscope) (const pthread_attr_t *, int *);
399 int (*ptr_pthread_attr_setscope) (pthread_attr_t *, int);
400 int (*ptr_pthread_condattr_destroy) (pthread_condattr_t *);
401 int (*ptr_pthread_condattr_init) (pthread_condattr_t *);
402 int (*ptr___pthread_cond_broadcast) (pthread_cond_t *);
403 int (*ptr___pthread_cond_destroy) (pthread_cond_t *);
404 int (*ptr___pthread_cond_init) (pthread_cond_t *, const pthread_condattr_t *);
405 int (*ptr___pthread_cond_signal) (pthread_cond_t *);
406 int (*ptr___pthread_cond_wait) (pthread_cond_t *, pthread_mutex_t *);
407 int (*ptr_pthread_equal) (pthread_t, pthread_t);
408 void (*ptr___pthread_exit) (void *);
409 int (*ptr_pthread_getschedparam) (pthread_t, int *, struct sched_param *);
410 int (*ptr_pthread_setschedparam) (pthread_t, int, const struct sched_param *);
411 int (*ptr_pthread_mutex_destroy) (pthread_mutex_t *);
412 int (*ptr_pthread_mutex_init) (pthread_mutex_t *, const pthread_mutexattr_t *);
413 int (*ptr_pthread_mutex_lock) (pthread_mutex_t *);
414 int (*ptr_pthread_mutex_trylock) (pthread_mutex_t *);
415 int (*ptr_pthread_mutex_unlock) (pthread_mutex_t *);
416 pthread_t (*ptr_pthread_self) (void);
417 int (*ptr_pthread_setcancelstate) (int, int *);
418 int (*ptr_pthread_setcanceltype) (int, int *);
419 void (*ptr_pthread_do_exit) (void *retval, char *currentframe);
420 void (*ptr_pthread_cleanup_upto) (jmp_buf target, char *targetframe);
421 pthread_descr (*ptr_pthread_thread_self) (void);
422 int (*ptr_pthread_internal_tsd_set) (int key, const void *pointer);
423 void * (*ptr_pthread_internal_tsd_get) (int key);
424 void ** __attribute__ ((__const__)) (*ptr_pthread_internal_tsd_address) (int key);
425 int (*ptr_pthread_sigaction) (int sig, const struct sigaction * act, struct sigaction *oact);
426 int (*ptr_pthread_sigwait) (const sigset_t *set, int *sig);
427 int (*ptr_pthread_raise) (int sig);
428 int (*ptr___pthread_cond_timedwait) (pthread_cond_t *, pthread_mutex_t *, const struct timespec *);
429 void (*ptr__pthread_cleanup_push) (struct _pthread_cleanup_buffer * buffer, void (*routine)(void *), void * arg);
430 void (*ptr__pthread_cleanup_pop) (struct _pthread_cleanup_buffer * buffer, int execute);
433 static pid_t (*libc_fork)(void);
434 static int (*libc_sigaction)(int signum, const struct sigaction *act, struct sigaction *oldact);
435 static int *(*libc_pthread_init)( const struct pthread_functions *funcs );
437 static struct pthread_functions libc_pthread_functions;
439 strong_alias(__pthread_thread_self, pthread_thread_self);
441 /* redefine this to prevent libpthread from overriding our function pointers */
442 int *__libc_pthread_init( const struct pthread_functions *funcs )
444 return libc_multiple_threads;
447 typedef struct _wine_cleanup {
448 void (*routine)(void *);
449 void *arg;
450 } *wine_cleanup;
452 int pthread_create(pthread_t* thread, const pthread_attr_t* attr, void*
453 (*start_routine)(void *), void* arg)
455 assert( funcs.ptr_pthread_create );
456 return funcs.ptr_pthread_create( thread, attr, start_routine, arg );
459 int pthread_cancel(pthread_t thread)
461 assert( funcs.ptr_pthread_cancel );
462 return funcs.ptr_pthread_cancel( thread );
465 int pthread_join(pthread_t thread, void **value_ptr)
467 assert( funcs.ptr_pthread_join );
468 return funcs.ptr_pthread_join( thread, value_ptr );
471 int pthread_detach(pthread_t thread)
473 assert( funcs.ptr_pthread_detach );
474 return funcs.ptr_pthread_detach( thread );
477 /* FIXME: we have no equivalents in win32 for the policys */
478 /* so just keep this as a stub */
479 int pthread_attr_setschedpolicy(pthread_attr_t *attr, int policy)
481 P_OUTPUT("FIXME:pthread_attr_setschedpolicy\n");
482 return 0;
485 /* FIXME: no win32 equivalent for scope */
486 int pthread_attr_setscope(pthread_attr_t *attr, int scope)
488 P_OUTPUT("FIXME:pthread_attr_setscope\n");
489 return 0; /* return success */
492 /* FIXME: no win32 equivalent for schedule param */
493 int pthread_attr_setschedparam(pthread_attr_t *attr,
494 const struct sched_param *param)
496 P_OUTPUT("FIXME:pthread_attr_setschedparam\n");
497 return 0; /* return success */
500 /* FIXME */
501 int pthread_attr_setstack(pthread_attr_t *attr, void *addr, size_t size)
503 return 0; /* return success */
506 int __pthread_once(pthread_once_t *once_control, void (*init_routine)(void))
508 static pthread_once_t the_once = PTHREAD_ONCE_INIT;
509 long once_now;
511 memcpy(&once_now,&the_once,sizeof(once_now));
512 if (interlocked_cmpxchg((long*)once_control, once_now+1, once_now) == once_now)
513 (*init_routine)();
514 return 0;
516 strong_alias(__pthread_once, pthread_once);
518 void __pthread_kill_other_threads_np(void)
520 /* we don't need to do anything here */
522 strong_alias(__pthread_kill_other_threads_np, pthread_kill_other_threads_np);
524 /***** atfork *****/
526 #define MAX_ATFORK 8 /* libc doesn't need that many anyway */
528 static pthread_mutex_t atfork_mutex = PTHREAD_MUTEX_INITIALIZER;
530 typedef void (*atfork_handler)();
531 static atfork_handler atfork_prepare[MAX_ATFORK];
532 static atfork_handler atfork_parent[MAX_ATFORK];
533 static atfork_handler atfork_child[MAX_ATFORK];
534 static int atfork_count;
536 int __pthread_atfork(void (*prepare)(void), void (*parent)(void), void (*child)(void))
538 pthread_mutex_lock( &atfork_mutex );
539 assert( atfork_count < MAX_ATFORK );
540 atfork_prepare[atfork_count] = prepare;
541 atfork_parent[atfork_count] = parent;
542 atfork_child[atfork_count] = child;
543 atfork_count++;
544 pthread_mutex_unlock( &atfork_mutex );
545 return 0;
547 strong_alias(__pthread_atfork, pthread_atfork);
549 pid_t __fork(void)
551 pid_t pid;
552 int i;
554 if (!libc_fork)
556 libc_fork = dlsym( RTLD_NEXT, "fork" );
557 assert( libc_fork );
559 pthread_mutex_lock( &atfork_mutex );
560 /* prepare handlers are called in reverse insertion order */
561 for (i = atfork_count - 1; i >= 0; i--) if (atfork_prepare[i]) atfork_prepare[i]();
562 if (!(pid = libc_fork()))
564 pthread_mutex_init( &atfork_mutex, NULL );
565 for (i = 0; i < atfork_count; i++) if (atfork_child[i]) atfork_child[i]();
567 else
569 for (i = 0; i < atfork_count; i++) if (atfork_parent[i]) atfork_parent[i]();
570 pthread_mutex_unlock( &atfork_mutex );
572 return pid;
574 strong_alias(__fork, fork);
576 /***** MUTEXES *****/
578 int __pthread_mutex_init(pthread_mutex_t *mutex, const pthread_mutexattr_t *mutexattr)
580 if (!funcs.ptr_pthread_mutex_init) return 0;
581 return funcs.ptr_pthread_mutex_init( mutex, mutexattr );
583 strong_alias(__pthread_mutex_init, pthread_mutex_init);
585 int __pthread_mutex_lock(pthread_mutex_t *mutex)
587 if (!funcs.ptr_pthread_mutex_lock) return 0;
588 return funcs.ptr_pthread_mutex_lock( mutex );
590 strong_alias(__pthread_mutex_lock, pthread_mutex_lock);
592 int __pthread_mutex_trylock(pthread_mutex_t *mutex)
594 if (!funcs.ptr_pthread_mutex_trylock) return 0;
595 return funcs.ptr_pthread_mutex_trylock( mutex );
597 strong_alias(__pthread_mutex_trylock, pthread_mutex_trylock);
599 int __pthread_mutex_unlock(pthread_mutex_t *mutex)
601 if (!funcs.ptr_pthread_mutex_unlock) return 0;
602 return funcs.ptr_pthread_mutex_unlock( mutex );
604 strong_alias(__pthread_mutex_unlock, pthread_mutex_unlock);
606 int __pthread_mutex_destroy(pthread_mutex_t *mutex)
608 if (!funcs.ptr_pthread_mutex_destroy) return 0;
609 return funcs.ptr_pthread_mutex_destroy( mutex );
611 strong_alias(__pthread_mutex_destroy, pthread_mutex_destroy);
614 /***** MUTEX ATTRIBUTES *****/
615 /* just dummies, since critical sections are always recursive */
617 int __pthread_mutexattr_init(pthread_mutexattr_t *attr)
619 return 0;
621 strong_alias(__pthread_mutexattr_init, pthread_mutexattr_init);
623 int __pthread_mutexattr_destroy(pthread_mutexattr_t *attr)
625 return 0;
627 strong_alias(__pthread_mutexattr_destroy, pthread_mutexattr_destroy);
629 int __pthread_mutexattr_setkind_np(pthread_mutexattr_t *attr, int kind)
631 return 0;
633 strong_alias(__pthread_mutexattr_setkind_np, pthread_mutexattr_setkind_np);
635 int __pthread_mutexattr_getkind_np(pthread_mutexattr_t *attr, int *kind)
637 *kind = PTHREAD_MUTEX_RECURSIVE;
638 return 0;
640 strong_alias(__pthread_mutexattr_getkind_np, pthread_mutexattr_getkind_np);
642 int __pthread_mutexattr_settype(pthread_mutexattr_t *attr, int kind)
644 return 0;
646 strong_alias(__pthread_mutexattr_settype, pthread_mutexattr_settype);
648 int __pthread_mutexattr_gettype(pthread_mutexattr_t *attr, int *kind)
650 *kind = PTHREAD_MUTEX_RECURSIVE;
651 return 0;
653 strong_alias(__pthread_mutexattr_gettype, pthread_mutexattr_gettype);
656 /***** THREAD-SPECIFIC VARIABLES (KEYS) *****/
658 int __pthread_key_create(pthread_key_t *key, void (*destr_function)(void *))
660 static long keycnt = FIRST_KEY;
661 *key = interlocked_xchg_add(&keycnt, 1);
662 return 0;
664 strong_alias(__pthread_key_create, pthread_key_create);
666 int __pthread_key_delete(pthread_key_t key)
668 return 0;
670 strong_alias(__pthread_key_delete, pthread_key_delete);
672 int __pthread_setspecific(pthread_key_t key, const void *pointer)
674 pthread_descr descr = __pthread_thread_self();
675 descr->key_data[key] = pointer;
676 return 0;
678 strong_alias(__pthread_setspecific, pthread_setspecific);
680 void *__pthread_getspecific(pthread_key_t key)
682 pthread_descr descr = __pthread_thread_self();
683 return (void *)descr->key_data[key];
685 strong_alias(__pthread_getspecific, pthread_getspecific);
687 static int pthread_internal_tsd_set( int key, const void *pointer )
689 pthread_descr descr = __pthread_thread_self();
690 descr->tsd_data[key] = pointer;
691 return 0;
693 int (*__libc_internal_tsd_set)(int, const void *) = pthread_internal_tsd_set;
695 static void *pthread_internal_tsd_get( int key )
697 pthread_descr descr = __pthread_thread_self();
698 return (void *)descr->tsd_data[key];
700 void* (*__libc_internal_tsd_get)(int) = pthread_internal_tsd_get;
702 static void ** __attribute__((const)) pthread_internal_tsd_address( int key )
704 pthread_descr descr = __pthread_thread_self();
705 return (void **)&descr->tsd_data[key];
707 void** (*__libc_internal_tsd_address)(int) = pthread_internal_tsd_address;
709 /***** "EXCEPTION" FRAMES *****/
710 /* not implemented right now */
712 void _pthread_cleanup_push(struct _pthread_cleanup_buffer *buffer, void (*routine)(void *), void *arg)
714 ((wine_cleanup)buffer)->routine = routine;
715 ((wine_cleanup)buffer)->arg = arg;
718 void _pthread_cleanup_pop(struct _pthread_cleanup_buffer *buffer, int execute)
720 if (execute) (*(((wine_cleanup)buffer)->routine))(((wine_cleanup)buffer)->arg);
723 void _pthread_cleanup_push_defer(struct _pthread_cleanup_buffer *buffer, void (*routine)(void *), void *arg)
725 _pthread_cleanup_push(buffer, routine, arg);
728 void _pthread_cleanup_pop_restore(struct _pthread_cleanup_buffer *buffer, int execute)
730 _pthread_cleanup_pop(buffer, execute);
733 void __pthread_cleanup_upto(jmp_buf target, char *frame)
735 /* FIXME */
738 /***** CONDITIONS *****/
740 int __pthread_cond_init(pthread_cond_t *cond, const pthread_condattr_t *cond_attr)
742 if (!funcs.ptr_pthread_cond_init) return 0;
743 return funcs.ptr_pthread_cond_init(cond, cond_attr);
745 strong_alias(__pthread_cond_init, pthread_cond_init);
747 int __pthread_cond_destroy(pthread_cond_t *cond)
749 if (!funcs.ptr_pthread_cond_destroy) return 0;
750 return funcs.ptr_pthread_cond_destroy(cond);
752 strong_alias(__pthread_cond_destroy, pthread_cond_destroy);
754 int __pthread_cond_signal(pthread_cond_t *cond)
756 if (!funcs.ptr_pthread_cond_signal) return 0;
757 return funcs.ptr_pthread_cond_signal(cond);
759 strong_alias(__pthread_cond_signal, pthread_cond_signal);
761 int __pthread_cond_broadcast(pthread_cond_t *cond)
763 if (!funcs.ptr_pthread_cond_broadcast) return 0;
764 return funcs.ptr_pthread_cond_broadcast(cond);
766 strong_alias(__pthread_cond_broadcast, pthread_cond_broadcast);
768 int __pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex)
770 if (!funcs.ptr_pthread_cond_wait) return 0;
771 return funcs.ptr_pthread_cond_wait(cond, mutex);
773 strong_alias(__pthread_cond_wait, pthread_cond_wait);
775 int __pthread_cond_timedwait(pthread_cond_t *cond, pthread_mutex_t *mutex, const struct timespec *abstime)
777 if (!funcs.ptr_pthread_cond_timedwait) return 0;
778 return funcs.ptr_pthread_cond_timedwait(cond, mutex, abstime);
780 strong_alias(__pthread_cond_timedwait, pthread_cond_timedwait);
782 /**** CONDITION ATTRIBUTES *****/
783 /* not implemented right now */
785 int pthread_condattr_init(pthread_condattr_t *attr)
787 return 0;
790 int pthread_condattr_destroy(pthread_condattr_t *attr)
792 return 0;
795 /***** READ-WRITE LOCKS *****/
797 int __pthread_rwlock_init(pthread_rwlock_t *rwlock, const pthread_rwlockattr_t *rwlock_attr)
799 assert( funcs.ptr_pthread_rwlock_init );
800 return funcs.ptr_pthread_rwlock_init( rwlock, rwlock_attr );
802 strong_alias(__pthread_rwlock_init, pthread_rwlock_init);
804 int __pthread_rwlock_destroy(pthread_rwlock_t *rwlock)
806 assert( funcs.ptr_pthread_rwlock_destroy );
807 return funcs.ptr_pthread_rwlock_destroy( rwlock );
809 strong_alias(__pthread_rwlock_destroy, pthread_rwlock_destroy);
811 int __pthread_rwlock_rdlock(pthread_rwlock_t *rwlock)
813 if (!funcs.ptr_pthread_rwlock_rdlock) return 0;
814 return funcs.ptr_pthread_rwlock_rdlock( rwlock );
816 strong_alias(__pthread_rwlock_rdlock, pthread_rwlock_rdlock);
818 int __pthread_rwlock_tryrdlock(pthread_rwlock_t *rwlock)
820 assert( funcs.ptr_pthread_rwlock_tryrdlock );
821 return funcs.ptr_pthread_rwlock_tryrdlock( rwlock );
823 strong_alias(__pthread_rwlock_tryrdlock, pthread_rwlock_tryrdlock);
825 int __pthread_rwlock_wrlock(pthread_rwlock_t *rwlock)
827 assert( funcs.ptr_pthread_rwlock_wrlock );
828 return funcs.ptr_pthread_rwlock_wrlock( rwlock );
830 strong_alias(__pthread_rwlock_wrlock, pthread_rwlock_wrlock);
832 int __pthread_rwlock_trywrlock(pthread_rwlock_t *rwlock)
834 assert( funcs.ptr_pthread_rwlock_trywrlock );
835 return funcs.ptr_pthread_rwlock_trywrlock( rwlock );
837 strong_alias(__pthread_rwlock_trywrlock, pthread_rwlock_trywrlock);
839 int __pthread_rwlock_unlock(pthread_rwlock_t *rwlock)
841 if (!funcs.ptr_pthread_rwlock_unlock) return 0;
842 return funcs.ptr_pthread_rwlock_unlock( rwlock );
844 strong_alias(__pthread_rwlock_unlock, pthread_rwlock_unlock);
846 /**** READ-WRITE LOCK ATTRIBUTES *****/
847 /* not implemented right now */
849 int pthread_rwlockattr_init(pthread_rwlockattr_t *attr)
851 return 0;
854 int __pthread_rwlockattr_destroy(pthread_rwlockattr_t *attr)
856 return 0;
858 strong_alias(__pthread_rwlockattr_destroy, pthread_rwlockattr_destroy);
860 int pthread_rwlockattr_getkind_np(const pthread_rwlockattr_t *attr, int *pref)
862 *pref = 0;
863 return 0;
866 int pthread_rwlockattr_setkind_np(pthread_rwlockattr_t *attr, int pref)
868 return 0;
871 /***** MISC *****/
873 pthread_t pthread_self(void)
875 assert( funcs.ptr_pthread_self );
876 return funcs.ptr_pthread_self();
879 int pthread_equal(pthread_t thread1, pthread_t thread2)
881 assert( funcs.ptr_pthread_equal );
882 return funcs.ptr_pthread_equal( thread1, thread2 );
885 void __pthread_do_exit(void *retval, char *currentframe)
887 assert( funcs.ptr_pthread_exit );
888 return funcs.ptr_pthread_exit( retval, currentframe );
891 void __pthread_exit(void *retval)
893 __pthread_do_exit( retval, NULL );
895 strong_alias(__pthread_exit, pthread_exit);
897 int pthread_setcancelstate(int state, int *oldstate)
899 pthread_descr descr = __pthread_thread_self();
900 if (oldstate) *oldstate = descr->cancel_state;
901 descr->cancel_state = state;
902 return 0;
905 int pthread_setcanceltype(int type, int *oldtype)
907 pthread_descr descr = __pthread_thread_self();
908 if (oldtype) *oldtype = descr->cancel_type;
909 descr->cancel_type = type;
910 return 0;
913 /***** ANTI-OVERRIDES *****/
914 /* pthreads tries to override these, point them back to libc */
916 int sigaction(int signum, const struct sigaction *act, struct sigaction *oldact)
918 if (!libc_sigaction)
920 libc_sigaction = dlsym( RTLD_NEXT, "sigaction" );
921 assert( libc_sigaction );
923 return libc_sigaction(signum, act, oldact);
926 void __pthread_initialize(void)
928 static int done;
930 if (!done)
932 done = 1;
933 libc_fork = dlsym( RTLD_NEXT, "fork" );
934 libc_sigaction = dlsym( RTLD_NEXT, "sigaction" );
935 libc_uselocale = dlsym( RTLD_NEXT, "uselocale" );
936 libc_pthread_init = dlsym( RTLD_NEXT, "__libc_pthread_init" );
937 if (libc_pthread_init) libc_multiple_threads = libc_pthread_init( &libc_pthread_functions );
940 DECL_GLOBAL_CONSTRUCTOR(init) { __pthread_initialize(); }
942 static struct pthread_functions libc_pthread_functions =
944 NULL, /* ptr_pthread_fork */
945 NULL, /* FIXME */ /* ptr_pthread_attr_destroy */
946 NULL, /* FIXME */ /* ptr___pthread_attr_init_2_0 */
947 NULL, /* FIXME */ /* ptr___pthread_attr_init_2_1 */
948 NULL, /* FIXME */ /* ptr_pthread_attr_getdetachstate */
949 NULL, /* FIXME */ /* ptr_pthread_attr_setdetachstate */
950 NULL, /* FIXME */ /* ptr_pthread_attr_getinheritsched */
951 NULL, /* FIXME */ /* ptr_pthread_attr_setinheritsched */
952 NULL, /* FIXME */ /* ptr_pthread_attr_getschedparam */
953 pthread_attr_setschedparam, /* ptr_pthread_attr_setschedparam */
954 NULL, /* FIXME */ /* ptr_pthread_attr_getschedpolicy */
955 NULL, /* FIXME */ /* ptr_pthread_attr_setschedpolicy */
956 NULL, /* FIXME */ /* ptr_pthread_attr_getscope */
957 NULL, /* FIXME */ /* ptr_pthread_attr_setscope */
958 pthread_condattr_destroy, /* ptr_pthread_condattr_destroy */
959 pthread_condattr_init, /* ptr_pthread_condattr_init */
960 __pthread_cond_broadcast, /* ptr___pthread_cond_broadcast */
961 __pthread_cond_destroy, /* ptr___pthread_cond_destroy */
962 __pthread_cond_init, /* ptr___pthread_cond_init */
963 __pthread_cond_signal, /* ptr___pthread_cond_signal */
964 __pthread_cond_wait, /* ptr___pthread_cond_wait */
965 pthread_equal, /* ptr_pthread_equal */
966 __pthread_exit, /* ptr___pthread_exit */
967 NULL, /* FIXME */ /* ptr_pthread_getschedparam */
968 NULL, /* FIXME */ /* ptr_pthread_setschedparam */
969 __pthread_mutex_destroy, /* ptr_pthread_mutex_destroy */
970 __pthread_mutex_init, /* ptr_pthread_mutex_init */
971 __pthread_mutex_lock, /* ptr_pthread_mutex_lock */
972 __pthread_mutex_trylock, /* ptr_pthread_mutex_trylock */
973 __pthread_mutex_unlock, /* ptr_pthread_mutex_unlock */
974 pthread_self, /* ptr_pthread_self */
975 pthread_setcancelstate, /* ptr_pthread_setcancelstate */
976 pthread_setcanceltype, /* ptr_pthread_setcanceltype */
977 __pthread_do_exit, /* ptr_pthread_do_exit */
978 __pthread_cleanup_upto, /* ptr_pthread_cleanup_upto */
979 __pthread_thread_self, /* ptr_pthread_thread_self */
980 pthread_internal_tsd_set, /* ptr_pthread_internal_tsd_set */
981 pthread_internal_tsd_get, /* ptr_pthread_internal_tsd_get */
982 pthread_internal_tsd_address, /* ptr_pthread_internal_tsd_address */
983 NULL, /* ptr_pthread_sigaction */
984 NULL, /* ptr_pthread_sigwait */
985 NULL, /* ptr_pthread_raise */
986 __pthread_cond_timedwait, /* ptr___pthread_cond_timedwait */
987 _pthread_cleanup_push, /* ptr__pthread_cleanup_push */
988 _pthread_cleanup_pop /* ptr__pthread_cleanup_pop */
991 #endif /* __GLIBC__ || __FREEBSD__ */