kthread.c 30.9 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 327 328 329 330 331 332 333 334
/***********************************************************************
 *           pthread_functions
 */
const struct wine_pthread_functions pthread_functions =
{
    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 343 344 345
/* 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). */

346
#if defined(HAVE_PTHREAD_H) && (defined(__GLIBC__) || defined(__FreeBSD__))
347

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

353 354
struct fork_block;

355 356
/* pthread functions redirection */

357 358 359 360 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
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);
401
  int (*ptr___pthread_cond_timedwait) (pthread_cond_t *, pthread_mutex_t *, const struct timespec *);
402 403
  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);
404 405
};

406 407
static pid_t (*libc_fork)(void);
static int (*libc_sigaction)(int signum, const struct sigaction *act, struct sigaction *oldact);
408
static int *(*libc_pthread_init)( const struct pthread_functions *funcs );
409

410 411 412
static struct pthread_functions libc_pthread_functions;

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

414 415 416 417 418
/* 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
419

420 421 422 423 424
typedef struct _wine_cleanup {
  void (*routine)(void *);
  void *arg;
} *wine_cleanup;

425 426 427
int pthread_create(pthread_t* thread, const pthread_attr_t* attr, void*
        (*start_routine)(void *), void* arg)
{
428 429
    assert( funcs.ptr_pthread_create );
    return funcs.ptr_pthread_create( thread, attr, start_routine, arg );
430
}
431

432 433
int pthread_cancel(pthread_t thread)
{
434 435
    assert( funcs.ptr_pthread_cancel );
    return funcs.ptr_pthread_cancel( thread );
436
}
437 438 439

int pthread_join(pthread_t thread, void **value_ptr)
{
440 441
    assert( funcs.ptr_pthread_join );
    return funcs.ptr_pthread_join( thread, value_ptr );
442
}
443 444 445

int pthread_detach(pthread_t thread)
{
446 447
    assert( funcs.ptr_pthread_detach );
    return funcs.ptr_pthread_detach( thread );
448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463
}

/* 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 */
}
464

465 466 467 468 469 470 471 472
/* 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 */
}

473 474 475 476 477 478
/* FIXME */
int pthread_attr_setstack(pthread_attr_t *attr, void *addr, size_t size)
{
  return 0; /* return success */
}

479 480
int __pthread_once(pthread_once_t *once_control, void (*init_routine)(void))
{
481
    static pthread_once_t the_once = PTHREAD_ONCE_INIT;
482
    int once_now;
483

484
    memcpy(&once_now,&the_once,sizeof(once_now));
485
    if (interlocked_cmpxchg((int*)once_control, once_now+1, once_now) == once_now)
486 487
        (*init_routine)();
    return 0;
488 489 490
}
strong_alias(__pthread_once, pthread_once);

491 492
void __pthread_kill_other_threads_np(void)
{
493
    /* we don't need to do anything here */
494 495 496
}
strong_alias(__pthread_kill_other_threads_np, pthread_kill_other_threads_np);

497 498 499 500
/***** atfork *****/

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

501
static pthread_mutex_t atfork_mutex = PTHREAD_MUTEX_INITIALIZER;
502

503
typedef void (*atfork_handler)(void);
504 505 506 507 508
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;

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

522
pid_t __fork(void)
Ove Kaaven's avatar
Ove Kaaven committed
523
{
524 525 526
    pid_t pid;
    int i;

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

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

551
int __pthread_mutex_init(pthread_mutex_t *mutex, const pthread_mutexattr_t *mutexattr)
552
{
553 554
    if (!funcs.ptr_pthread_mutex_init) return 0;
    return funcs.ptr_pthread_mutex_init( mutex, mutexattr );
555 556 557 558 559
}
strong_alias(__pthread_mutex_init, pthread_mutex_init);

int __pthread_mutex_lock(pthread_mutex_t *mutex)
{
560 561
    if (!funcs.ptr_pthread_mutex_lock) return 0;
    return funcs.ptr_pthread_mutex_lock( mutex );
562 563 564 565 566
}
strong_alias(__pthread_mutex_lock, pthread_mutex_lock);

int __pthread_mutex_trylock(pthread_mutex_t *mutex)
{
567 568
    if (!funcs.ptr_pthread_mutex_trylock) return 0;
    return funcs.ptr_pthread_mutex_trylock( mutex );
569 570 571 572 573
}
strong_alias(__pthread_mutex_trylock, pthread_mutex_trylock);

int __pthread_mutex_unlock(pthread_mutex_t *mutex)
{
574 575
    if (!funcs.ptr_pthread_mutex_unlock) return 0;
    return funcs.ptr_pthread_mutex_unlock( mutex );
576 577 578 579 580
}
strong_alias(__pthread_mutex_unlock, pthread_mutex_unlock);

int __pthread_mutex_destroy(pthread_mutex_t *mutex)
{
581 582
    if (!funcs.ptr_pthread_mutex_destroy) return 0;
    return funcs.ptr_pthread_mutex_destroy( mutex );
583 584 585
}
strong_alias(__pthread_mutex_destroy, pthread_mutex_destroy);

586 587 588

/***** MUTEX ATTRIBUTES *****/
/* just dummies, since critical sections are always recursive */
589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609

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)
{
610
  *kind = PTHREAD_MUTEX_RECURSIVE;
611 612 613 614 615 616 617 618 619 620
  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);

621
int __pthread_mutexattr_gettype(const pthread_mutexattr_t *attr, int *kind)
622
{
623
  *kind = PTHREAD_MUTEX_RECURSIVE;
624 625 626 627
  return 0;
}
strong_alias(__pthread_mutexattr_gettype, pthread_mutexattr_gettype);

628 629 630

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

631 632
int __pthread_key_create(pthread_key_t *key, void (*destr_function)(void *))
{
633
    static int keycnt = FIRST_KEY;
634 635
    *key = interlocked_xchg_add(&keycnt, 1);
    return 0;
636 637 638 639 640 641 642 643 644 645 646
}
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)
{
647 648 649
    pthread_descr descr = __pthread_thread_self();
    descr->key_data[key] = pointer;
    return 0;
650 651 652 653 654
}
strong_alias(__pthread_setspecific, pthread_setspecific);

void *__pthread_getspecific(pthread_key_t key)
{
655 656
    pthread_descr descr = __pthread_thread_self();
    return (void *)descr->key_data[key];
657 658 659
}
strong_alias(__pthread_getspecific, pthread_getspecific);

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

static void *pthread_internal_tsd_get( int key )
{
    pthread_descr descr = __pthread_thread_self();
    return (void *)descr->tsd_data[key];
}
673
void* (*__libc_internal_tsd_get)(int) = pthread_internal_tsd_get;
674 675 676 677 678 679

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

682 683 684
/***** "EXCEPTION" FRAMES *****/
/* not implemented right now */

685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705
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);
}

706 707 708 709
void __pthread_cleanup_upto(jmp_buf target, char *frame)
{
    /* FIXME */
}
710 711 712

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

713
int __pthread_cond_init(pthread_cond_t *cond, const pthread_condattr_t *cond_attr)
714
{
715 716
    if (!funcs.ptr_pthread_cond_init) return 0;
    return funcs.ptr_pthread_cond_init(cond, cond_attr);
717
}
718
strong_alias(__pthread_cond_init, pthread_cond_init);
719

720
int __pthread_cond_destroy(pthread_cond_t *cond)
721
{
722 723
    if (!funcs.ptr_pthread_cond_destroy) return 0;
    return funcs.ptr_pthread_cond_destroy(cond);
724
}
725
strong_alias(__pthread_cond_destroy, pthread_cond_destroy);
726

727
int __pthread_cond_signal(pthread_cond_t *cond)
728
{
729 730
    if (!funcs.ptr_pthread_cond_signal) return 0;
    return funcs.ptr_pthread_cond_signal(cond);
731
}
732
strong_alias(__pthread_cond_signal, pthread_cond_signal);
733

734
int __pthread_cond_broadcast(pthread_cond_t *cond)
735
{
736 737
    if (!funcs.ptr_pthread_cond_broadcast) return 0;
    return funcs.ptr_pthread_cond_broadcast(cond);
738
}
739
strong_alias(__pthread_cond_broadcast, pthread_cond_broadcast);
740

741
int __pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex)
742
{
743 744
    if (!funcs.ptr_pthread_cond_wait) return 0;
    return funcs.ptr_pthread_cond_wait(cond, mutex);
745
}
746
strong_alias(__pthread_cond_wait, pthread_cond_wait);
747

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

/**** 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;
}

768
/***** READ-WRITE LOCKS *****/
769

770 771
int __pthread_rwlock_init(pthread_rwlock_t *rwlock, const pthread_rwlockattr_t *rwlock_attr)
{
772 773
    assert( funcs.ptr_pthread_rwlock_init );
    return funcs.ptr_pthread_rwlock_init( rwlock, rwlock_attr );
774 775 776 777 778
}
strong_alias(__pthread_rwlock_init, pthread_rwlock_init);

int __pthread_rwlock_destroy(pthread_rwlock_t *rwlock)
{
779 780
    assert( funcs.ptr_pthread_rwlock_destroy );
    return funcs.ptr_pthread_rwlock_destroy( rwlock );
781 782 783 784 785
}
strong_alias(__pthread_rwlock_destroy, pthread_rwlock_destroy);

int __pthread_rwlock_rdlock(pthread_rwlock_t *rwlock)
{
786 787
    if (!funcs.ptr_pthread_rwlock_rdlock) return 0;
    return funcs.ptr_pthread_rwlock_rdlock( rwlock );
788 789 790 791 792
}
strong_alias(__pthread_rwlock_rdlock, pthread_rwlock_rdlock);

int __pthread_rwlock_tryrdlock(pthread_rwlock_t *rwlock)
{
793 794
    assert( funcs.ptr_pthread_rwlock_tryrdlock );
    return funcs.ptr_pthread_rwlock_tryrdlock( rwlock );
795 796 797 798 799
}
strong_alias(__pthread_rwlock_tryrdlock, pthread_rwlock_tryrdlock);

int __pthread_rwlock_wrlock(pthread_rwlock_t *rwlock)
{
800 801
    assert( funcs.ptr_pthread_rwlock_wrlock );
    return funcs.ptr_pthread_rwlock_wrlock( rwlock );
802 803 804 805 806
}
strong_alias(__pthread_rwlock_wrlock, pthread_rwlock_wrlock);

int __pthread_rwlock_trywrlock(pthread_rwlock_t *rwlock)
{
807 808
    assert( funcs.ptr_pthread_rwlock_trywrlock );
    return funcs.ptr_pthread_rwlock_trywrlock( rwlock );
809 810 811 812 813
}
strong_alias(__pthread_rwlock_trywrlock, pthread_rwlock_trywrlock);

int __pthread_rwlock_unlock(pthread_rwlock_t *rwlock)
{
814
    if (!funcs.ptr_pthread_rwlock_unlock) return 0;
815
    return funcs.ptr_pthread_rwlock_unlock( rwlock );
816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843
}
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;
}

844 845
/***** MISC *****/

846 847
pthread_t pthread_self(void)
{
848 849
    assert( funcs.ptr_pthread_self );
    return funcs.ptr_pthread_self();
850 851 852 853
}

int pthread_equal(pthread_t thread1, pthread_t thread2)
{
854 855
    assert( funcs.ptr_pthread_equal );
    return funcs.ptr_pthread_equal( thread1, thread2 );
856 857
}

858
void __pthread_do_exit(void *retval, char *currentframe)
859
{
860 861
    assert( funcs.ptr_pthread_exit );
    return funcs.ptr_pthread_exit( retval, currentframe );
862 863
}

864 865 866 867 868 869
void __pthread_exit(void *retval)
{
    __pthread_do_exit( retval, NULL );
}
strong_alias(__pthread_exit, pthread_exit);

870 871 872 873 874 875 876 877
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;
}

878 879
int pthread_setcanceltype(int type, int *oldtype)
{
880 881 882 883
    pthread_descr descr = __pthread_thread_self();
    if (oldtype) *oldtype = descr->cancel_type;
    descr->cancel_type = type;
    return 0;
884 885
}

886 887 888 889 890
/***** ANTI-OVERRIDES *****/
/* pthreads tries to override these, point them back to libc */

int sigaction(int signum, const struct sigaction *act, struct sigaction *oldact)
{
891 892
    if (!libc_sigaction)
    {
893
        libc_sigaction = wine_dlsym( RTLD_NEXT, "sigaction", NULL, 0 );
894 895 896 897 898
        assert( libc_sigaction );
    }
    return libc_sigaction(signum, act, oldact);
}

899 900 901 902 903 904 905
void __pthread_initialize(void)
{
    static int done;

    if (!done)
    {
        done = 1;
906 907 908 909 910 911 912 913
        /* 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 );
        }
914 915 916 917
        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 );
918 919 920
        if (libc_pthread_init) libc_multiple_threads = libc_pthread_init( &libc_pthread_functions );
    }
}
921 922 923 924 925 926 927 928

#ifdef __GNUC__
static void init(void) __attribute__((constructor));
static void init(void)
{
    __pthread_initialize();
}
#endif
929 930

static struct pthread_functions libc_pthread_functions =
931 932 933 934 935 936 937 938 939 940 941
{
    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 */
942 943 944 945
    NULL, /* FIXME */              /* ptr_pthread_attr_getschedpolicy */
    NULL, /* FIXME */              /* ptr_pthread_attr_setschedpolicy */
    NULL, /* FIXME */              /* ptr_pthread_attr_getscope */
    NULL, /* FIXME */              /* ptr_pthread_attr_setscope */
946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962
    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 */
963
    pthread_setcancelstate,        /* ptr_pthread_setcancelstate */
964 965 966 967 968 969 970 971 972
    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 */
973
    NULL,                          /* ptr_pthread_raise */
974 975 976
    __pthread_cond_timedwait,      /* ptr___pthread_cond_timedwait */
    _pthread_cleanup_push,         /* ptr__pthread_cleanup_push */
    _pthread_cleanup_pop           /* ptr__pthread_cleanup_pop */
977 978
};

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