kthread.c 31 KB
Newer Older
1
/*
2
 * pthread emulation based on kernel threads
3 4
 *
 * We can't use pthreads directly, so why not let libcs
5
 * that want pthreads use Wine's own threading instead...
6
 *
7
 * Copyright 1999 Ove Kåven
8
 * Copyright 2003 Alexandre Julliard
9 10 11 12 13 14 15 16 17 18 19 20 21
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
22
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
23 24 25
 */

#include "config.h"
26 27
#include "wine/port.h"

28 29
struct _pthread_cleanup_buffer;

30
#include <assert.h>
31 32
#include <errno.h>
#include <stdlib.h>
33
#include <signal.h>
34
#include <setjmp.h>
35 36 37
#ifdef HAVE_UNISTD_H
# include <unistd.h>
#endif
38
#include <string.h>
39
#include <sys/types.h>
40
#ifdef HAVE_SYS_SOCKET_H
41 42 43 44 45 46 47 48
# include <sys/socket.h>
#endif
#ifdef HAVE_SYS_MMAN_H
#include <sys/mman.h>
#endif
#ifdef HAVE_NETINET_IN_H
# include <netinet/in.h>
#endif
49 50 51
#ifdef HAVE_ARPA_NAMESER_H
# include <arpa/nameser.h>
#endif
52 53 54
#ifdef HAVE_RESOLV_H
# include <resolv.h>
#endif
55 56
#ifdef HAVE_VALGRIND_VALGRIND_H
#include <valgrind/valgrind.h>
57
#endif
58 59 60 61 62 63
#ifdef HAVE_SYS_SYSCALL_H
# include <sys/syscall.h>
#endif
#ifdef HAVE_SCHED_H
#include <sched.h>
#endif
64

65
#include "wine/library.h"
66
#include "wine/pthread.h"
67

68
#define P_OUTPUT(stuff) write(2,stuff,strlen(stuff))
69

70 71
#define PSTR(str) __ASM_NAME(#str)

72
static struct wine_pthread_callbacks funcs;
73 74 75 76 77 78

/* thread descriptor */

#define FIRST_KEY 0
#define MAX_KEYS 16 /* libc6 doesn't use that many, but... */
#define MAX_TSD  16
79

80
struct pthread_descr_struct
81
{
82 83 84 85 86 87 88 89 90
    char               dummy[2048];
    int                thread_errno;
    int                thread_h_errno;
    int                cancel_state;
    int                cancel_type;
    struct __res_state res_state;
    const void        *key_data[MAX_KEYS];  /* for normal pthread keys */
    const void        *tsd_data[MAX_TSD];   /* for libc internal tsd variables */
};
91

92 93 94 95 96
typedef struct pthread_descr_struct *pthread_descr;

static struct pthread_descr_struct initial_descr;

pthread_descr __pthread_thread_self(void)
97
{
98 99 100 101 102
    struct pthread_descr_struct *descr;
    if (!funcs.ptr_get_thread_data) return &initial_descr;
    descr = funcs.ptr_get_thread_data();
    if (!descr) return &initial_descr;
    return descr;
103 104
}

105 106
static int (*libc_uselocale)(int set);
static int *libc_multiple_threads;
107 108 109 110 111 112

/***********************************************************************
 *           __errno_location/__error/__errno/___errno/__thr_errno
 *
 * Get the per-thread errno location.
 */
113 114 115 116 117 118 119 120 121
int *__errno_location(void)                            /* Linux */
{
    pthread_descr descr = __pthread_thread_self();
    return &descr->thread_errno;
}
int *__error(void)     { return __errno_location(); }  /* FreeBSD */
int *__errno(void)     { return __errno_location(); }  /* NetBSD */
int *___errno(void)    { return __errno_location(); }  /* Solaris */
int *__thr_errno(void) { return __errno_location(); }  /* UnixWare */
122 123 124 125 126 127 128 129

/***********************************************************************
 *           __h_errno_location
 *
 * Get the per-thread h_errno location.
 */
int *__h_errno_location(void)
{
130 131 132 133
    pthread_descr descr = __pthread_thread_self();
    return &descr->thread_h_errno;
}

134 135 136 137 138
struct __res_state *__res_state(void)
{
    pthread_descr descr = __pthread_thread_self();
    return &descr->res_state;
}
139 140 141 142

static inline void writejump( const char *symbol, void *dest )
{
#if defined(__GLIBC__) && defined(__i386__)
143
    unsigned char *addr = wine_dlsym( RTLD_NEXT, symbol, NULL, 0 );
144 145 146 147 148 149 150 151 152

    if (!addr) return;

    /* write a relative jump at the function address */
    mprotect((void*)((unsigned int)addr & ~(getpagesize()-1)), 5, PROT_READ|PROT_EXEC|PROT_WRITE);
    addr[0] = 0xe9;
    *(int *)(addr+1) = (unsigned char *)dest - (addr + 5);
    mprotect((void*)((unsigned int)addr & ~(getpagesize()-1)), 5, PROT_READ|PROT_EXEC);

153
# ifdef VALGRIND_DISCARD_TRANSLATIONS
154 155 156 157 158
    VALGRIND_DISCARD_TRANSLATIONS( addr, 5 );
# endif
#endif  /* __GLIBC__ && __i386__ */
}

159 160 161 162
/* temporary stacks used on thread exit */
#define TEMP_STACK_SIZE 1024
#define NB_TEMP_STACKS  8
static char temp_stacks[NB_TEMP_STACKS][TEMP_STACK_SIZE];
163
static int next_temp_stack;  /* next temp stack to use */
164 165 166 167 168 169

/***********************************************************************
 *           get_temp_stack
 *
 * Get a temporary stack address to run the thread exit code on.
 */
170
static inline char *get_temp_stack(void)
171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186
{
    unsigned int next = interlocked_xchg_add( &next_temp_stack, 1 );
    return temp_stacks[next % NB_TEMP_STACKS] + TEMP_STACK_SIZE;
}


/***********************************************************************
 *           cleanup_thread
 *
 * Cleanup the remains of a thread. Runs on a temporary stack.
 */
static void cleanup_thread( void *ptr )
{
    /* copy the info structure since it is on the stack we will free */
    struct wine_pthread_thread_info info = *(struct wine_pthread_thread_info *)ptr;
    wine_ldt_free_fs( info.teb_sel );
187 188
    if (info.stack_size) munmap( info.stack_base, info.stack_size );
    if (info.teb_size) munmap( info.teb_base, info.teb_size );
189 190 191 192
    _exit( info.exit_status );
}


193
/***********************************************************************
194
 *           init_process
195 196 197
 *
 * Initialization for a newly created process.
 */
198
static void init_process( const struct wine_pthread_callbacks *callbacks, size_t size )
199
{
200
    memcpy( &funcs, callbacks, min( size, sizeof(funcs) ));
201 202 203 204 205
    funcs.ptr_set_thread_data( &initial_descr );
}


/***********************************************************************
206
 *           init_thread
207 208 209
 *
 * Initialization for a newly created thread.
 */
210
static void init_thread( struct wine_pthread_thread_info *info )
211
{
212 213
    struct pthread_descr_struct *descr;

214 215
    if (funcs.ptr_set_thread_data)
    {
216
        descr = calloc( 1, sizeof(*descr) );
217 218 219
        funcs.ptr_set_thread_data( descr );
        if (libc_multiple_threads) *libc_multiple_threads = 1;
    }
220 221 222 223 224 225 226 227 228 229
    else  /* first thread */
    {
        descr = &initial_descr;
        writejump( "__errno_location", __errno_location );
        writejump( "__h_errno_location", __h_errno_location );
        writejump( "__res_state", __res_state );
    }
    descr->cancel_state = PTHREAD_CANCEL_ENABLE;
    descr->cancel_type  = PTHREAD_CANCEL_ASYNCHRONOUS;
    if (libc_uselocale) libc_uselocale( -1 /*LC_GLOBAL_LOCALE*/ );
230 231 232
}


233
/***********************************************************************
234
 *           create_thread
235
 */
236
static int create_thread( struct wine_pthread_thread_info *info )
237 238 239
{
    if (!info->stack_base)
    {
240
        info->stack_base = wine_anon_mmap( NULL, info->stack_size, PROT_READ | PROT_WRITE, 0 );
241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264
        if (info->stack_base == (void *)-1) return -1;
    }
#ifdef HAVE_CLONE
    if (clone( (int (*)(void *))info->entry, (char *)info->stack_base + info->stack_size,
               CLONE_VM | CLONE_FS | CLONE_FILES | SIGCHLD, info ) < 0)
        return -1;
    return 0;
#elif defined(HAVE_RFORK)
    {
        void **sp = (void **)((char *)info->stack_base + info->stack_size);
        *--sp = info;
        *--sp = 0;
        *--sp = info->entry;
        __asm__ __volatile__(
            "pushl %2;\n\t"             /* flags */
            "pushl $0;\n\t"             /* 0 ? */
            "movl %1,%%eax;\n\t"        /* SYS_rfork */
            ".byte 0x9a; .long 0; .word 7;\n\t" /* lcall 7:0... FreeBSD syscall */
            "cmpl $0, %%edx;\n\t"
            "je 1f;\n\t"
            "movl %0,%%esp;\n\t"        /* child -> new thread */
            "ret;\n"
            "1:\n\t"                    /* parent -> caller thread */
            "addl $8,%%esp" :
265
            : "r" (sp), "r" (SYS_rfork), "r" (RFPROC | RFMEM | RFTHREAD)
266 267 268 269 270 271 272 273
            : "eax", "edx");
        return 0;
    }
#endif
    return -1;
}


274
/***********************************************************************
275
 *           init_current_teb
276 277 278
 *
 * Set the current TEB for a new thread.
 */
279
static void init_current_teb( struct wine_pthread_thread_info *info )
280 281 282 283 284 285 286 287 288 289 290 291 292 293 294
{
    /* On the i386, the current thread is in the %fs register */
    LDT_ENTRY fs_entry;

    wine_ldt_set_base( &fs_entry, info->teb_base );
    wine_ldt_set_limit( &fs_entry, info->teb_size - 1 );
    wine_ldt_set_flags( &fs_entry, WINE_LDT_FLAGS_DATA|WINE_LDT_FLAGS_32BIT );
    wine_ldt_init_fs( info->teb_sel, &fs_entry );

    /* set pid and tid */
    info->pid = getpid();
    info->tid = -1;
}


295
/***********************************************************************
296
 *           get_current_teb
297
 */
298
static void *get_current_teb(void)
299 300 301 302 303 304 305
{
    void *ret;
    __asm__( ".byte 0x64\n\tmovl 0x18,%0" : "=r" (ret) );
    return ret;
}


306
/***********************************************************************
307
 *           exit_thread
308
 */
309
static void DECLSPEC_NORETURN exit_thread( struct wine_pthread_thread_info *info )
310 311 312 313 314 315
{
    wine_switch_to_stack( cleanup_thread, info, get_temp_stack() );
}


/***********************************************************************
316
 *           abort_thread
317
 */
318
static void DECLSPEC_NORETURN abort_thread( long status )
319 320 321 322 323
{
    _exit( status );
}


324 325 326
/***********************************************************************
 *           pthread_functions
 */
327
static const struct wine_pthread_functions pthread_functions =
328 329 330 331 332 333 334
{
    init_process,
    init_thread,
    create_thread,
    init_current_teb,
    get_current_teb,
    exit_thread,
335 336
    abort_thread,
    sigprocmask
337 338
};

339 340 341 342
void init_pthread_functions(void)
{
    wine_pthread_set_functions( &pthread_functions, sizeof(pthread_functions) );
}
343

344 345 346 347 348 349
/* Currently this probably works only for glibc2,
 * which checks for the presence of double-underscore-prepended
 * pthread primitives, and use them if available.
 * If they are not available, the libc defaults to
 * non-threadsafe operation (not good). */

350
#if defined(HAVE_PTHREAD_H) && (defined(__GLIBC__) || defined(__FreeBSD__))
351

352 353
/* adapt as necessary (a construct like this is used in glibc sources) */
#define strong_alias(orig, alias) \
354 355
 asm(".globl " PSTR(alias) "\n" \
     "\t.set " PSTR(alias) "," PSTR(orig))
356

357 358
struct fork_block;

359 360
/* pthread functions redirection */

361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404
struct pthread_functions
{
  pid_t (*ptr_pthread_fork) (struct fork_block *);
  int (*ptr_pthread_attr_destroy) (pthread_attr_t *);
  int (*ptr___pthread_attr_init_2_0) (pthread_attr_t *);
  int (*ptr___pthread_attr_init_2_1) (pthread_attr_t *);
  int (*ptr_pthread_attr_getdetachstate) (const pthread_attr_t *, int *);
  int (*ptr_pthread_attr_setdetachstate) (pthread_attr_t *, int);
  int (*ptr_pthread_attr_getinheritsched) (const pthread_attr_t *, int *);
  int (*ptr_pthread_attr_setinheritsched) (pthread_attr_t *, int);
  int (*ptr_pthread_attr_getschedparam) (const pthread_attr_t *, struct sched_param *);
  int (*ptr_pthread_attr_setschedparam) (pthread_attr_t *, const struct sched_param *);
  int (*ptr_pthread_attr_getschedpolicy) (const pthread_attr_t *, int *);
  int (*ptr_pthread_attr_setschedpolicy) (pthread_attr_t *, int);
  int (*ptr_pthread_attr_getscope) (const pthread_attr_t *, int *);
  int (*ptr_pthread_attr_setscope) (pthread_attr_t *, int);
  int (*ptr_pthread_condattr_destroy) (pthread_condattr_t *);
  int (*ptr_pthread_condattr_init) (pthread_condattr_t *);
  int (*ptr___pthread_cond_broadcast) (pthread_cond_t *);
  int (*ptr___pthread_cond_destroy) (pthread_cond_t *);
  int (*ptr___pthread_cond_init) (pthread_cond_t *, const pthread_condattr_t *);
  int (*ptr___pthread_cond_signal) (pthread_cond_t *);
  int (*ptr___pthread_cond_wait) (pthread_cond_t *, pthread_mutex_t *);
  int (*ptr_pthread_equal) (pthread_t, pthread_t);
  void (*ptr___pthread_exit) (void *);
  int (*ptr_pthread_getschedparam) (pthread_t, int *, struct sched_param *);
  int (*ptr_pthread_setschedparam) (pthread_t, int, const struct sched_param *);
  int (*ptr_pthread_mutex_destroy) (pthread_mutex_t *);
  int (*ptr_pthread_mutex_init) (pthread_mutex_t *, const pthread_mutexattr_t *);
  int (*ptr_pthread_mutex_lock) (pthread_mutex_t *);
  int (*ptr_pthread_mutex_trylock) (pthread_mutex_t *);
  int (*ptr_pthread_mutex_unlock) (pthread_mutex_t *);
  pthread_t (*ptr_pthread_self) (void);
  int (*ptr_pthread_setcancelstate) (int, int *);
  int (*ptr_pthread_setcanceltype) (int, int *);
  void (*ptr_pthread_do_exit) (void *retval, char *currentframe);
  void (*ptr_pthread_cleanup_upto) (jmp_buf target, char *targetframe);
  pthread_descr (*ptr_pthread_thread_self) (void);
  int (*ptr_pthread_internal_tsd_set) (int key, const void *pointer);
  void * (*ptr_pthread_internal_tsd_get) (int key);
  void ** __attribute__ ((__const__)) (*ptr_pthread_internal_tsd_address) (int key);
  int (*ptr_pthread_sigaction) (int sig, const struct sigaction * act, struct sigaction *oact);
  int (*ptr_pthread_sigwait) (const sigset_t *set, int *sig);
  int (*ptr_pthread_raise) (int sig);
405
  int (*ptr___pthread_cond_timedwait) (pthread_cond_t *, pthread_mutex_t *, const struct timespec *);
406 407
  void (*ptr__pthread_cleanup_push) (struct _pthread_cleanup_buffer * buffer, void (*routine)(void *), void * arg);
  void (*ptr__pthread_cleanup_pop) (struct _pthread_cleanup_buffer * buffer, int execute);
408 409
};

410 411
static pid_t (*libc_fork)(void);
static int (*libc_sigaction)(int signum, const struct sigaction *act, struct sigaction *oldact);
412
static int *(*libc_pthread_init)( const struct pthread_functions *funcs );
413

414 415 416
static struct pthread_functions libc_pthread_functions;

strong_alias(__pthread_thread_self, pthread_thread_self);
Ove Kaaven's avatar
Ove Kaaven committed
417

418 419 420 421 422
/* redefine this to prevent libpthread from overriding our function pointers */
int *__libc_pthread_init( const struct pthread_functions *funcs )
{
    return libc_multiple_threads;
}
Ove Kaaven's avatar
Ove Kaaven committed
423

424 425 426 427 428
typedef struct _wine_cleanup {
  void (*routine)(void *);
  void *arg;
} *wine_cleanup;

429 430 431
int pthread_create(pthread_t* thread, const pthread_attr_t* attr, void*
        (*start_routine)(void *), void* arg)
{
432 433
    assert( funcs.ptr_pthread_create );
    return funcs.ptr_pthread_create( thread, attr, start_routine, arg );
434
}
435

436 437
int pthread_cancel(pthread_t thread)
{
438 439
    assert( funcs.ptr_pthread_cancel );
    return funcs.ptr_pthread_cancel( thread );
440
}
441 442 443

int pthread_join(pthread_t thread, void **value_ptr)
{
444 445
    assert( funcs.ptr_pthread_join );
    return funcs.ptr_pthread_join( thread, value_ptr );
446
}
447 448 449

int pthread_detach(pthread_t thread)
{
450 451
    assert( funcs.ptr_pthread_detach );
    return funcs.ptr_pthread_detach( thread );
452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467
}

/* FIXME: we have no equivalents in win32 for the policys */
/* so just keep this as a stub */
int pthread_attr_setschedpolicy(pthread_attr_t *attr, int policy)
{
  P_OUTPUT("FIXME:pthread_attr_setschedpolicy\n");
  return 0;
}

/* FIXME: no win32 equivalent for scope */
int pthread_attr_setscope(pthread_attr_t *attr, int scope)
{
  P_OUTPUT("FIXME:pthread_attr_setscope\n");
  return 0; /* return success */
}
468

469 470 471 472 473 474 475 476
/* FIXME: no win32 equivalent for schedule param */
int pthread_attr_setschedparam(pthread_attr_t *attr,
    const struct sched_param *param)
{
  P_OUTPUT("FIXME:pthread_attr_setschedparam\n");
  return 0; /* return success */
}

477 478 479 480 481 482
/* FIXME */
int pthread_attr_setstack(pthread_attr_t *attr, void *addr, size_t size)
{
  return 0; /* return success */
}

483 484
int __pthread_once(pthread_once_t *once_control, void (*init_routine)(void))
{
485
    static pthread_once_t the_once = PTHREAD_ONCE_INIT;
486
    int once_now;
487

488
    memcpy(&once_now,&the_once,sizeof(once_now));
489
    if (interlocked_cmpxchg((int*)once_control, once_now+1, once_now) == once_now)
490 491
        (*init_routine)();
    return 0;
492 493 494
}
strong_alias(__pthread_once, pthread_once);

495 496
void __pthread_kill_other_threads_np(void)
{
497
    /* we don't need to do anything here */
498 499 500
}
strong_alias(__pthread_kill_other_threads_np, pthread_kill_other_threads_np);

501 502 503 504
/***** atfork *****/

#define MAX_ATFORK 8  /* libc doesn't need that many anyway */

505
static pthread_mutex_t atfork_mutex = PTHREAD_MUTEX_INITIALIZER;
506

507
typedef void (*atfork_handler)(void);
508 509 510 511 512
static atfork_handler atfork_prepare[MAX_ATFORK];
static atfork_handler atfork_parent[MAX_ATFORK];
static atfork_handler atfork_child[MAX_ATFORK];
static int atfork_count;

513
int __pthread_atfork(void (*prepare)(void), void (*parent)(void), void (*child)(void))
514
{
515
    pthread_mutex_lock( &atfork_mutex );
516 517 518 519 520
    assert( atfork_count < MAX_ATFORK );
    atfork_prepare[atfork_count] = prepare;
    atfork_parent[atfork_count] = parent;
    atfork_child[atfork_count] = child;
    atfork_count++;
521
    pthread_mutex_unlock( &atfork_mutex );
522
    return 0;
523 524 525
}
strong_alias(__pthread_atfork, pthread_atfork);

526
pid_t __fork(void)
Ove Kaaven's avatar
Ove Kaaven committed
527
{
528 529 530
    pid_t pid;
    int i;

531 532
    if (!libc_fork)
    {
533
        libc_fork = wine_dlsym( RTLD_NEXT, "fork", NULL, 0 );
534 535
        assert( libc_fork );
    }
536
    pthread_mutex_lock( &atfork_mutex );
537
    /* prepare handlers are called in reverse insertion order */
538
    for (i = atfork_count - 1; i >= 0; i--) if (atfork_prepare[i]) atfork_prepare[i]();
539
    if (!(pid = libc_fork()))
540
    {
541
        pthread_mutex_init( &atfork_mutex, NULL );
542
        for (i = 0; i < atfork_count; i++) if (atfork_child[i]) atfork_child[i]();
543 544 545
    }
    else
    {
546
        for (i = 0; i < atfork_count; i++) if (atfork_parent[i]) atfork_parent[i]();
547
        pthread_mutex_unlock( &atfork_mutex );
548 549
    }
    return pid;
Ove Kaaven's avatar
Ove Kaaven committed
550
}
551
strong_alias(__fork, fork);
552 553 554

/***** MUTEXES *****/

555
int __pthread_mutex_init(pthread_mutex_t *mutex, const pthread_mutexattr_t *mutexattr)
556
{
557 558
    if (!funcs.ptr_pthread_mutex_init) return 0;
    return funcs.ptr_pthread_mutex_init( mutex, mutexattr );
559 560 561 562 563
}
strong_alias(__pthread_mutex_init, pthread_mutex_init);

int __pthread_mutex_lock(pthread_mutex_t *mutex)
{
564 565
    if (!funcs.ptr_pthread_mutex_lock) return 0;
    return funcs.ptr_pthread_mutex_lock( mutex );
566 567 568 569 570
}
strong_alias(__pthread_mutex_lock, pthread_mutex_lock);

int __pthread_mutex_trylock(pthread_mutex_t *mutex)
{
571 572
    if (!funcs.ptr_pthread_mutex_trylock) return 0;
    return funcs.ptr_pthread_mutex_trylock( mutex );
573 574 575 576 577
}
strong_alias(__pthread_mutex_trylock, pthread_mutex_trylock);

int __pthread_mutex_unlock(pthread_mutex_t *mutex)
{
578 579
    if (!funcs.ptr_pthread_mutex_unlock) return 0;
    return funcs.ptr_pthread_mutex_unlock( mutex );
580 581 582 583 584
}
strong_alias(__pthread_mutex_unlock, pthread_mutex_unlock);

int __pthread_mutex_destroy(pthread_mutex_t *mutex)
{
585 586
    if (!funcs.ptr_pthread_mutex_destroy) return 0;
    return funcs.ptr_pthread_mutex_destroy( mutex );
587 588 589
}
strong_alias(__pthread_mutex_destroy, pthread_mutex_destroy);

590 591 592

/***** MUTEX ATTRIBUTES *****/
/* just dummies, since critical sections are always recursive */
593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613

int __pthread_mutexattr_init(pthread_mutexattr_t *attr)
{
  return 0;
}
strong_alias(__pthread_mutexattr_init, pthread_mutexattr_init);

int __pthread_mutexattr_destroy(pthread_mutexattr_t *attr)
{
  return 0;
}
strong_alias(__pthread_mutexattr_destroy, pthread_mutexattr_destroy);

int __pthread_mutexattr_setkind_np(pthread_mutexattr_t *attr, int kind)
{
  return 0;
}
strong_alias(__pthread_mutexattr_setkind_np, pthread_mutexattr_setkind_np);

int __pthread_mutexattr_getkind_np(pthread_mutexattr_t *attr, int *kind)
{
614
  *kind = PTHREAD_MUTEX_RECURSIVE;
615 616 617 618 619 620 621 622 623 624
  return 0;
}
strong_alias(__pthread_mutexattr_getkind_np, pthread_mutexattr_getkind_np);

int __pthread_mutexattr_settype(pthread_mutexattr_t *attr, int kind)
{
  return 0;
}
strong_alias(__pthread_mutexattr_settype, pthread_mutexattr_settype);

625
int __pthread_mutexattr_gettype(const pthread_mutexattr_t *attr, int *kind)
626
{
627
  *kind = PTHREAD_MUTEX_RECURSIVE;
628 629 630 631
  return 0;
}
strong_alias(__pthread_mutexattr_gettype, pthread_mutexattr_gettype);

632 633 634

/***** THREAD-SPECIFIC VARIABLES (KEYS) *****/

635 636
int __pthread_key_create(pthread_key_t *key, void (*destr_function)(void *))
{
637
    static int keycnt = FIRST_KEY;
638 639
    *key = interlocked_xchg_add(&keycnt, 1);
    return 0;
640 641 642 643 644 645 646 647 648 649 650
}
strong_alias(__pthread_key_create, pthread_key_create);

int __pthread_key_delete(pthread_key_t key)
{
  return 0;
}
strong_alias(__pthread_key_delete, pthread_key_delete);

int __pthread_setspecific(pthread_key_t key, const void *pointer)
{
651 652 653
    pthread_descr descr = __pthread_thread_self();
    descr->key_data[key] = pointer;
    return 0;
654 655 656 657 658
}
strong_alias(__pthread_setspecific, pthread_setspecific);

void *__pthread_getspecific(pthread_key_t key)
{
659 660
    pthread_descr descr = __pthread_thread_self();
    return (void *)descr->key_data[key];
661 662 663
}
strong_alias(__pthread_getspecific, pthread_getspecific);

664 665 666 667 668 669
static int pthread_internal_tsd_set( int key, const void *pointer )
{
    pthread_descr descr = __pthread_thread_self();
    descr->tsd_data[key] = pointer;
    return 0;
}
670
int (*__libc_internal_tsd_set)(int, const void *) = pthread_internal_tsd_set;
671 672 673 674 675 676

static void *pthread_internal_tsd_get( int key )
{
    pthread_descr descr = __pthread_thread_self();
    return (void *)descr->tsd_data[key];
}
677
void* (*__libc_internal_tsd_get)(int) = pthread_internal_tsd_get;
678 679 680 681 682 683

static void ** __attribute__((const)) pthread_internal_tsd_address( int key )
{
    pthread_descr descr = __pthread_thread_self();
    return (void **)&descr->tsd_data[key];
}
684
void** (*__libc_internal_tsd_address)(int) = pthread_internal_tsd_address;
685

686 687 688
/***** "EXCEPTION" FRAMES *****/
/* not implemented right now */

689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709
void _pthread_cleanup_push(struct _pthread_cleanup_buffer *buffer, void (*routine)(void *), void *arg)
{
  ((wine_cleanup)buffer)->routine = routine;
  ((wine_cleanup)buffer)->arg = arg;
}

void _pthread_cleanup_pop(struct _pthread_cleanup_buffer *buffer, int execute)
{
  if (execute) (*(((wine_cleanup)buffer)->routine))(((wine_cleanup)buffer)->arg);
}

void _pthread_cleanup_push_defer(struct _pthread_cleanup_buffer *buffer, void (*routine)(void *), void *arg)
{
  _pthread_cleanup_push(buffer, routine, arg);
}

void _pthread_cleanup_pop_restore(struct _pthread_cleanup_buffer *buffer, int execute)
{
  _pthread_cleanup_pop(buffer, execute);
}

710 711 712 713
void __pthread_cleanup_upto(jmp_buf target, char *frame)
{
    /* FIXME */
}
714 715 716

/***** CONDITIONS *****/

717
int __pthread_cond_init(pthread_cond_t *cond, const pthread_condattr_t *cond_attr)
718
{
719 720
    if (!funcs.ptr_pthread_cond_init) return 0;
    return funcs.ptr_pthread_cond_init(cond, cond_attr);
721
}
722
strong_alias(__pthread_cond_init, pthread_cond_init);
723

724
int __pthread_cond_destroy(pthread_cond_t *cond)
725
{
726 727
    if (!funcs.ptr_pthread_cond_destroy) return 0;
    return funcs.ptr_pthread_cond_destroy(cond);
728
}
729
strong_alias(__pthread_cond_destroy, pthread_cond_destroy);
730

731
int __pthread_cond_signal(pthread_cond_t *cond)
732
{
733 734
    if (!funcs.ptr_pthread_cond_signal) return 0;
    return funcs.ptr_pthread_cond_signal(cond);
735
}
736
strong_alias(__pthread_cond_signal, pthread_cond_signal);
737

738
int __pthread_cond_broadcast(pthread_cond_t *cond)
739
{
740 741
    if (!funcs.ptr_pthread_cond_broadcast) return 0;
    return funcs.ptr_pthread_cond_broadcast(cond);
742
}
743
strong_alias(__pthread_cond_broadcast, pthread_cond_broadcast);
744

745
int __pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex)
746
{
747 748
    if (!funcs.ptr_pthread_cond_wait) return 0;
    return funcs.ptr_pthread_cond_wait(cond, mutex);
749
}
750
strong_alias(__pthread_cond_wait, pthread_cond_wait);
751

752
int __pthread_cond_timedwait(pthread_cond_t *cond, pthread_mutex_t *mutex, const struct timespec *abstime)
753
{
754 755
    if (!funcs.ptr_pthread_cond_timedwait) return 0;
    return funcs.ptr_pthread_cond_timedwait(cond, mutex, abstime);
756
}
757
strong_alias(__pthread_cond_timedwait, pthread_cond_timedwait);
758 759 760 761 762 763 764 765 766 767 768 769 770 771

/**** CONDITION ATTRIBUTES *****/
/* not implemented right now */

int pthread_condattr_init(pthread_condattr_t *attr)
{
  return 0;
}

int pthread_condattr_destroy(pthread_condattr_t *attr)
{
  return 0;
}

772
/***** READ-WRITE LOCKS *****/
773

774 775
int __pthread_rwlock_init(pthread_rwlock_t *rwlock, const pthread_rwlockattr_t *rwlock_attr)
{
776 777
    assert( funcs.ptr_pthread_rwlock_init );
    return funcs.ptr_pthread_rwlock_init( rwlock, rwlock_attr );
778 779 780 781 782
}
strong_alias(__pthread_rwlock_init, pthread_rwlock_init);

int __pthread_rwlock_destroy(pthread_rwlock_t *rwlock)
{
783 784
    assert( funcs.ptr_pthread_rwlock_destroy );
    return funcs.ptr_pthread_rwlock_destroy( rwlock );
785 786 787 788 789
}
strong_alias(__pthread_rwlock_destroy, pthread_rwlock_destroy);

int __pthread_rwlock_rdlock(pthread_rwlock_t *rwlock)
{
790 791
    if (!funcs.ptr_pthread_rwlock_rdlock) return 0;
    return funcs.ptr_pthread_rwlock_rdlock( rwlock );
792 793 794 795 796
}
strong_alias(__pthread_rwlock_rdlock, pthread_rwlock_rdlock);

int __pthread_rwlock_tryrdlock(pthread_rwlock_t *rwlock)
{
797 798
    assert( funcs.ptr_pthread_rwlock_tryrdlock );
    return funcs.ptr_pthread_rwlock_tryrdlock( rwlock );
799 800 801 802 803
}
strong_alias(__pthread_rwlock_tryrdlock, pthread_rwlock_tryrdlock);

int __pthread_rwlock_wrlock(pthread_rwlock_t *rwlock)
{
804 805
    assert( funcs.ptr_pthread_rwlock_wrlock );
    return funcs.ptr_pthread_rwlock_wrlock( rwlock );
806 807 808 809 810
}
strong_alias(__pthread_rwlock_wrlock, pthread_rwlock_wrlock);

int __pthread_rwlock_trywrlock(pthread_rwlock_t *rwlock)
{
811 812
    assert( funcs.ptr_pthread_rwlock_trywrlock );
    return funcs.ptr_pthread_rwlock_trywrlock( rwlock );
813 814 815 816 817
}
strong_alias(__pthread_rwlock_trywrlock, pthread_rwlock_trywrlock);

int __pthread_rwlock_unlock(pthread_rwlock_t *rwlock)
{
818
    if (!funcs.ptr_pthread_rwlock_unlock) return 0;
819
    return funcs.ptr_pthread_rwlock_unlock( rwlock );
820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847
}
strong_alias(__pthread_rwlock_unlock, pthread_rwlock_unlock);

/**** READ-WRITE LOCK ATTRIBUTES *****/
/* not implemented right now */

int pthread_rwlockattr_init(pthread_rwlockattr_t *attr)
{
  return 0;
}

int __pthread_rwlockattr_destroy(pthread_rwlockattr_t *attr)
{
  return 0;
}
strong_alias(__pthread_rwlockattr_destroy, pthread_rwlockattr_destroy);

int pthread_rwlockattr_getkind_np(const pthread_rwlockattr_t *attr, int *pref)
{
  *pref = 0;
  return 0;
}

int pthread_rwlockattr_setkind_np(pthread_rwlockattr_t *attr, int pref)
{
  return 0;
}

848 849
/***** MISC *****/

850 851
pthread_t pthread_self(void)
{
852 853
    assert( funcs.ptr_pthread_self );
    return funcs.ptr_pthread_self();
854 855 856 857
}

int pthread_equal(pthread_t thread1, pthread_t thread2)
{
858 859
    assert( funcs.ptr_pthread_equal );
    return funcs.ptr_pthread_equal( thread1, thread2 );
860 861
}

862
void __pthread_do_exit(void *retval, char *currentframe)
863
{
864 865
    assert( funcs.ptr_pthread_exit );
    return funcs.ptr_pthread_exit( retval, currentframe );
866 867
}

868 869 870 871 872 873
void __pthread_exit(void *retval)
{
    __pthread_do_exit( retval, NULL );
}
strong_alias(__pthread_exit, pthread_exit);

874 875 876 877 878 879 880 881
int pthread_setcancelstate(int state, int *oldstate)
{
    pthread_descr descr = __pthread_thread_self();
    if (oldstate) *oldstate = descr->cancel_state;
    descr->cancel_state = state;
    return 0;
}

882 883
int pthread_setcanceltype(int type, int *oldtype)
{
884 885 886 887
    pthread_descr descr = __pthread_thread_self();
    if (oldtype) *oldtype = descr->cancel_type;
    descr->cancel_type = type;
    return 0;
888 889
}

890 891 892 893 894
/***** ANTI-OVERRIDES *****/
/* pthreads tries to override these, point them back to libc */

int sigaction(int signum, const struct sigaction *act, struct sigaction *oldact)
{
895 896
    if (!libc_sigaction)
    {
897
        libc_sigaction = wine_dlsym( RTLD_NEXT, "sigaction", NULL, 0 );
898 899 900 901 902
        assert( libc_sigaction );
    }
    return libc_sigaction(signum, act, oldact);
}

903 904 905 906 907 908 909
void __pthread_initialize(void)
{
    static int done;

    if (!done)
    {
        done = 1;
910 911 912 913 914 915 916 917
        /* check for exported epoll_create to detect glibc versions that we cannot support */
        if (wine_dlsym( RTLD_DEFAULT, "epoll_create", NULL, 0 ))
        {
            static const char warning[] =
                "wine: glibc >= 2.3 without NPTL or TLS is not a supported combination.\n"
                "      It will most likely crash. Please upgrade to a glibc with NPTL support.\n";
            write( 2, warning, sizeof(warning)-1 );
        }
918 919 920 921
        libc_fork = wine_dlsym( RTLD_NEXT, "fork", NULL, 0 );
        libc_sigaction = wine_dlsym( RTLD_NEXT, "sigaction", NULL, 0 );
        libc_uselocale = wine_dlsym( RTLD_DEFAULT, "uselocale", NULL, 0 );
        libc_pthread_init = wine_dlsym( RTLD_NEXT, "__libc_pthread_init", NULL, 0 );
922 923 924
        if (libc_pthread_init) libc_multiple_threads = libc_pthread_init( &libc_pthread_functions );
    }
}
925 926 927 928 929 930 931 932

#ifdef __GNUC__
static void init(void) __attribute__((constructor));
static void init(void)
{
    __pthread_initialize();
}
#endif
933 934

static struct pthread_functions libc_pthread_functions =
935 936 937 938 939 940 941 942 943 944 945
{
    NULL,                          /* ptr_pthread_fork */
    NULL, /* FIXME */              /* ptr_pthread_attr_destroy */
    NULL, /* FIXME */              /* ptr___pthread_attr_init_2_0 */
    NULL, /* FIXME */              /* ptr___pthread_attr_init_2_1 */
    NULL, /* FIXME */              /* ptr_pthread_attr_getdetachstate */
    NULL, /* FIXME */              /* ptr_pthread_attr_setdetachstate */
    NULL, /* FIXME */              /* ptr_pthread_attr_getinheritsched */
    NULL, /* FIXME */              /* ptr_pthread_attr_setinheritsched */
    NULL, /* FIXME */              /* ptr_pthread_attr_getschedparam */
    pthread_attr_setschedparam,    /* ptr_pthread_attr_setschedparam */
946 947 948 949
    NULL, /* FIXME */              /* ptr_pthread_attr_getschedpolicy */
    NULL, /* FIXME */              /* ptr_pthread_attr_setschedpolicy */
    NULL, /* FIXME */              /* ptr_pthread_attr_getscope */
    NULL, /* FIXME */              /* ptr_pthread_attr_setscope */
950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966
    pthread_condattr_destroy,      /* ptr_pthread_condattr_destroy */
    pthread_condattr_init,         /* ptr_pthread_condattr_init */
    __pthread_cond_broadcast,      /* ptr___pthread_cond_broadcast */
    __pthread_cond_destroy,        /* ptr___pthread_cond_destroy */
    __pthread_cond_init,           /* ptr___pthread_cond_init */
    __pthread_cond_signal,         /* ptr___pthread_cond_signal */
    __pthread_cond_wait,           /* ptr___pthread_cond_wait */
    pthread_equal,                 /* ptr_pthread_equal */
    __pthread_exit,                /* ptr___pthread_exit */
    NULL, /* FIXME */              /* ptr_pthread_getschedparam */
    NULL, /* FIXME */              /* ptr_pthread_setschedparam */
    __pthread_mutex_destroy,       /* ptr_pthread_mutex_destroy */
    __pthread_mutex_init,          /* ptr_pthread_mutex_init */
    __pthread_mutex_lock,          /* ptr_pthread_mutex_lock */
    __pthread_mutex_trylock,       /* ptr_pthread_mutex_trylock */
    __pthread_mutex_unlock,        /* ptr_pthread_mutex_unlock */
    pthread_self,                  /* ptr_pthread_self */
967
    pthread_setcancelstate,        /* ptr_pthread_setcancelstate */
968 969 970 971 972 973 974 975 976
    pthread_setcanceltype,         /* ptr_pthread_setcanceltype */
    __pthread_do_exit,             /* ptr_pthread_do_exit */
    __pthread_cleanup_upto,        /* ptr_pthread_cleanup_upto */
    __pthread_thread_self,         /* ptr_pthread_thread_self */
    pthread_internal_tsd_set,      /* ptr_pthread_internal_tsd_set */
    pthread_internal_tsd_get,      /* ptr_pthread_internal_tsd_get */
    pthread_internal_tsd_address,  /* ptr_pthread_internal_tsd_address */
    NULL,                          /* ptr_pthread_sigaction */
    NULL,                          /* ptr_pthread_sigwait */
977
    NULL,                          /* ptr_pthread_raise */
978 979 980
    __pthread_cond_timedwait,      /* ptr___pthread_cond_timedwait */
    _pthread_cleanup_push,         /* ptr__pthread_cleanup_push */
    _pthread_cleanup_pop           /* ptr__pthread_cleanup_pop */
981 982
};

983
#endif /* HAVE_PTHREAD_H && (__GLIBC__ || __FREEBSD__) */