blob: 1191b35a05bd90a9b82b526d3cf1123fdc2db51b [file] [log] [blame]
Ove Kaavenf19f07d2000-04-14 14:47:02 +00001/*
2 * pthread emulation for re-entrant libcs
3 *
4 * We can't use pthreads directly, so why not let libcs
Andreas Mohr9cef2d02001-11-19 02:30:01 +00005 * that want pthreads use Wine's own threading instead...
Ove Kaavenf19f07d2000-04-14 14:47:02 +00006 *
7 * Copyright 1999 Ove Kåven
Alexandre Julliard80e34db2003-09-03 00:26:08 +00008 * Copyright 2003 Alexandre Julliard
Alexandre Julliard0799c1a2002-03-09 23:29:33 +00009 *
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.
14 *
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.
19 *
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
Ove Kaavenf19f07d2000-04-14 14:47:02 +000023 */
24
25#include "config.h"
Alexandre Julliard5769d1d2002-04-26 19:05:15 +000026#include "wine/port.h"
27
Alexandre Julliard03d79982003-08-15 03:55:06 +000028#ifndef HAVE_NPTL
29
30struct _pthread_cleanup_buffer;
31
Alexandre Julliard95a43322000-05-01 16:19:40 +000032#include <assert.h>
Ove Kaavenf19f07d2000-04-14 14:47:02 +000033#include <errno.h>
34#include <stdlib.h>
Alexandre Julliard80e34db2003-09-03 00:26:08 +000035#include <signal.h>
Alexandre Julliard97d862c2003-08-12 18:59:13 +000036#include <setjmp.h>
Patrik Stridvalld016f812002-08-17 00:43:16 +000037#ifdef HAVE_UNISTD_H
38# include <unistd.h>
39#endif
Jeff Garzikf46eb1d2001-03-21 20:30:46 +000040#include <string.h>
Alexandre Julliard03d79982003-08-15 03:55:06 +000041#include <sys/types.h>
Daniel Marmiera613de22003-09-30 00:33:47 +000042#ifdef HAVE_SYS_SOCKET_H
Alexandre Julliard03d79982003-08-15 03:55:06 +000043# include <sys/socket.h>
44#endif
45#ifdef HAVE_SYS_MMAN_H
46#include <sys/mman.h>
47#endif
48#ifdef HAVE_NETINET_IN_H
49# include <netinet/in.h>
50#endif
51#ifdef HAVE_RESOLV_H
52# include <resolv.h>
53#endif
54#ifdef HAVE_VALGRIND_MEMCHECK_H
55#include <valgrind/memcheck.h>
56#endif
Ove Kaavenf19f07d2000-04-14 14:47:02 +000057
Alexandre Julliard80e34db2003-09-03 00:26:08 +000058#include "wine/pthread.h"
Ove Kaavenf19f07d2000-04-14 14:47:02 +000059
Alexandre Julliard80e34db2003-09-03 00:26:08 +000060#define P_OUTPUT(stuff) write(2,stuff,strlen(stuff))
61
62#define PSTR(str) __ASM_NAME(#str)
63
64static struct wine_pthread_functions funcs;
65
66/* thread descriptor */
67
68#define FIRST_KEY 0
69#define MAX_KEYS 16 /* libc6 doesn't use that many, but... */
70#define MAX_TSD 16
71
72struct pthread_descr_struct
Alexandre Julliard03d79982003-08-15 03:55:06 +000073{
Alexandre Julliard80e34db2003-09-03 00:26:08 +000074 char dummy[2048];
75 int thread_errno;
76 int thread_h_errno;
77 int cancel_state;
78 int cancel_type;
79 struct __res_state res_state;
80 const void *key_data[MAX_KEYS]; /* for normal pthread keys */
81 const void *tsd_data[MAX_TSD]; /* for libc internal tsd variables */
82};
83
84typedef struct pthread_descr_struct *pthread_descr;
85
86static struct pthread_descr_struct initial_descr;
87
88pthread_descr __pthread_thread_self(void)
89{
90 struct pthread_descr_struct *descr;
91 if (!funcs.ptr_get_thread_data) return &initial_descr;
92 descr = funcs.ptr_get_thread_data();
93 if (!descr) return &initial_descr;
94 return descr;
Alexandre Julliard03d79982003-08-15 03:55:06 +000095}
96
Alexandre Julliard80e34db2003-09-03 00:26:08 +000097static int (*libc_uselocale)(int set);
98static int *libc_multiple_threads;
Alexandre Julliard03d79982003-08-15 03:55:06 +000099
100/***********************************************************************
101 * __errno_location/__error/__errno/___errno/__thr_errno
102 *
103 * Get the per-thread errno location.
104 */
Alexandre Julliard80e34db2003-09-03 00:26:08 +0000105int *__errno_location(void) /* Linux */
106{
107 pthread_descr descr = __pthread_thread_self();
108 return &descr->thread_errno;
109}
110int *__error(void) { return __errno_location(); } /* FreeBSD */
111int *__errno(void) { return __errno_location(); } /* NetBSD */
112int *___errno(void) { return __errno_location(); } /* Solaris */
113int *__thr_errno(void) { return __errno_location(); } /* UnixWare */
Alexandre Julliard03d79982003-08-15 03:55:06 +0000114
115/***********************************************************************
116 * __h_errno_location
117 *
118 * Get the per-thread h_errno location.
119 */
120int *__h_errno_location(void)
121{
Alexandre Julliard80e34db2003-09-03 00:26:08 +0000122 pthread_descr descr = __pthread_thread_self();
123 return &descr->thread_h_errno;
124}
125
Gabriele Giorgetti59b2ad62003-09-18 20:52:24 +0000126struct __res_state *__res_state(void)
127{
128 pthread_descr descr = __pthread_thread_self();
129 return &descr->res_state;
130}
Alexandre Julliard80e34db2003-09-03 00:26:08 +0000131
132static inline void writejump( const char *symbol, void *dest )
133{
134#if defined(__GLIBC__) && defined(__i386__)
135 unsigned char *addr = dlsym( RTLD_NEXT, symbol );
136
137 if (!addr) return;
138
139 /* write a relative jump at the function address */
140 mprotect((void*)((unsigned int)addr & ~(getpagesize()-1)), 5, PROT_READ|PROT_EXEC|PROT_WRITE);
141 addr[0] = 0xe9;
142 *(int *)(addr+1) = (unsigned char *)dest - (addr + 5);
143 mprotect((void*)((unsigned int)addr & ~(getpagesize()-1)), 5, PROT_READ|PROT_EXEC);
144
145# ifdef HAVE_VALGRIND_MEMCHECK_H
146 VALGRIND_DISCARD_TRANSLATIONS( addr, 5 );
147# endif
148#endif /* __GLIBC__ && __i386__ */
149}
150
151/***********************************************************************
152 * wine_pthread_init_process
153 *
154 * Initialization for a newly created process.
155 */
156void wine_pthread_init_process( const struct wine_pthread_functions *functions )
157{
158 memcpy( &funcs, functions, sizeof(funcs) );
159 funcs.ptr_set_thread_data( &initial_descr );
Alexandre Julliard80e34db2003-09-03 00:26:08 +0000160}
161
162
163/***********************************************************************
164 * wine_pthread_init_thread
165 *
166 * Initialization for a newly created thread.
167 */
168void wine_pthread_init_thread(void)
169{
Alexandre Julliardcf4ca4e2003-10-12 02:26:20 +0000170 struct pthread_descr_struct *descr;
171
Alexandre Julliard80e34db2003-09-03 00:26:08 +0000172 if (funcs.ptr_set_thread_data)
173 {
Alexandre Julliardcf4ca4e2003-10-12 02:26:20 +0000174 descr = calloc( 1, sizeof(*descr) );
Alexandre Julliard80e34db2003-09-03 00:26:08 +0000175 funcs.ptr_set_thread_data( descr );
Alexandre Julliard80e34db2003-09-03 00:26:08 +0000176 if (libc_multiple_threads) *libc_multiple_threads = 1;
Alexandre Julliard80e34db2003-09-03 00:26:08 +0000177 }
Alexandre Julliardcf4ca4e2003-10-12 02:26:20 +0000178 else /* first thread */
179 {
180 descr = &initial_descr;
181 writejump( "__errno_location", __errno_location );
182 writejump( "__h_errno_location", __h_errno_location );
183 writejump( "__res_state", __res_state );
184 }
185 descr->cancel_state = PTHREAD_CANCEL_ENABLE;
186 descr->cancel_type = PTHREAD_CANCEL_ASYNCHRONOUS;
187 if (libc_uselocale) libc_uselocale( -1 /*LC_GLOBAL_LOCALE*/ );
Alexandre Julliard03d79982003-08-15 03:55:06 +0000188}
189
190
Ove Kaavenf19f07d2000-04-14 14:47:02 +0000191/* Currently this probably works only for glibc2,
192 * which checks for the presence of double-underscore-prepended
193 * pthread primitives, and use them if available.
194 * If they are not available, the libc defaults to
195 * non-threadsafe operation (not good). */
196
Alexandre Julliard03d79982003-08-15 03:55:06 +0000197#if defined(__GLIBC__) || defined(__FreeBSD__)
Patrik Stridvall6caeb722002-11-25 21:12:26 +0000198
199#ifndef __USE_UNIX98
200#define __USE_UNIX98
201#endif
202
Ove Kaavenf19f07d2000-04-14 14:47:02 +0000203#include <pthread.h>
Ove Kaaven1abdb6f2000-04-28 14:44:05 +0000204
Ove Kaavenf19f07d2000-04-14 14:47:02 +0000205/* adapt as necessary (a construct like this is used in glibc sources) */
206#define strong_alias(orig, alias) \
Ove Kaavend2937312000-05-09 22:32:25 +0000207 asm(".globl " PSTR(alias) "\n" \
208 "\t.set " PSTR(alias) "," PSTR(orig))
Ove Kaavenf19f07d2000-04-14 14:47:02 +0000209
Alexandre Julliard97d862c2003-08-12 18:59:13 +0000210struct fork_block;
211
Alexandre Julliard03d79982003-08-15 03:55:06 +0000212/* pthread functions redirection */
213
Alexandre Julliard97d862c2003-08-12 18:59:13 +0000214struct pthread_functions
215{
216 pid_t (*ptr_pthread_fork) (struct fork_block *);
217 int (*ptr_pthread_attr_destroy) (pthread_attr_t *);
218 int (*ptr___pthread_attr_init_2_0) (pthread_attr_t *);
219 int (*ptr___pthread_attr_init_2_1) (pthread_attr_t *);
220 int (*ptr_pthread_attr_getdetachstate) (const pthread_attr_t *, int *);
221 int (*ptr_pthread_attr_setdetachstate) (pthread_attr_t *, int);
222 int (*ptr_pthread_attr_getinheritsched) (const pthread_attr_t *, int *);
223 int (*ptr_pthread_attr_setinheritsched) (pthread_attr_t *, int);
224 int (*ptr_pthread_attr_getschedparam) (const pthread_attr_t *, struct sched_param *);
225 int (*ptr_pthread_attr_setschedparam) (pthread_attr_t *, const struct sched_param *);
226 int (*ptr_pthread_attr_getschedpolicy) (const pthread_attr_t *, int *);
227 int (*ptr_pthread_attr_setschedpolicy) (pthread_attr_t *, int);
228 int (*ptr_pthread_attr_getscope) (const pthread_attr_t *, int *);
229 int (*ptr_pthread_attr_setscope) (pthread_attr_t *, int);
230 int (*ptr_pthread_condattr_destroy) (pthread_condattr_t *);
231 int (*ptr_pthread_condattr_init) (pthread_condattr_t *);
232 int (*ptr___pthread_cond_broadcast) (pthread_cond_t *);
233 int (*ptr___pthread_cond_destroy) (pthread_cond_t *);
234 int (*ptr___pthread_cond_init) (pthread_cond_t *, const pthread_condattr_t *);
235 int (*ptr___pthread_cond_signal) (pthread_cond_t *);
236 int (*ptr___pthread_cond_wait) (pthread_cond_t *, pthread_mutex_t *);
237 int (*ptr_pthread_equal) (pthread_t, pthread_t);
238 void (*ptr___pthread_exit) (void *);
239 int (*ptr_pthread_getschedparam) (pthread_t, int *, struct sched_param *);
240 int (*ptr_pthread_setschedparam) (pthread_t, int, const struct sched_param *);
241 int (*ptr_pthread_mutex_destroy) (pthread_mutex_t *);
242 int (*ptr_pthread_mutex_init) (pthread_mutex_t *, const pthread_mutexattr_t *);
243 int (*ptr_pthread_mutex_lock) (pthread_mutex_t *);
244 int (*ptr_pthread_mutex_trylock) (pthread_mutex_t *);
245 int (*ptr_pthread_mutex_unlock) (pthread_mutex_t *);
246 pthread_t (*ptr_pthread_self) (void);
247 int (*ptr_pthread_setcancelstate) (int, int *);
248 int (*ptr_pthread_setcanceltype) (int, int *);
249 void (*ptr_pthread_do_exit) (void *retval, char *currentframe);
250 void (*ptr_pthread_cleanup_upto) (jmp_buf target, char *targetframe);
251 pthread_descr (*ptr_pthread_thread_self) (void);
252 int (*ptr_pthread_internal_tsd_set) (int key, const void *pointer);
253 void * (*ptr_pthread_internal_tsd_get) (int key);
254 void ** __attribute__ ((__const__)) (*ptr_pthread_internal_tsd_address) (int key);
255 int (*ptr_pthread_sigaction) (int sig, const struct sigaction * act, struct sigaction *oact);
256 int (*ptr_pthread_sigwait) (const sigset_t *set, int *sig);
257 int (*ptr_pthread_raise) (int sig);
Alexandre Julliarddbb2b802003-09-11 01:09:09 +0000258 int (*ptr___pthread_cond_timedwait) (pthread_cond_t *, pthread_mutex_t *, const struct timespec *);
Alexandre Julliarde8bd1102003-10-03 03:39:29 +0000259 void (*ptr__pthread_cleanup_push) (struct _pthread_cleanup_buffer * buffer, void (*routine)(void *), void * arg);
260 void (*ptr__pthread_cleanup_pop) (struct _pthread_cleanup_buffer * buffer, int execute);
Alexandre Julliard97d862c2003-08-12 18:59:13 +0000261};
262
Alexandre Julliard26fd7402002-10-22 00:44:24 +0000263static pid_t (*libc_fork)(void);
264static int (*libc_sigaction)(int signum, const struct sigaction *act, struct sigaction *oldact);
Alexandre Julliard97d862c2003-08-12 18:59:13 +0000265static int *(*libc_pthread_init)( const struct pthread_functions *funcs );
Ove Kaaven1abdb6f2000-04-28 14:44:05 +0000266
Alexandre Julliard80e34db2003-09-03 00:26:08 +0000267static struct pthread_functions libc_pthread_functions;
268
269strong_alias(__pthread_thread_self, pthread_thread_self);
Alexandre Julliard26fd7402002-10-22 00:44:24 +0000270
Alexandre Julliard97d862c2003-08-12 18:59:13 +0000271/* redefine this to prevent libpthread from overriding our function pointers */
272int *__libc_pthread_init( const struct pthread_functions *funcs )
273{
274 return libc_multiple_threads;
275}
Ove Kaaven1abdb6f2000-04-28 14:44:05 +0000276
Ove Kaavenf19f07d2000-04-14 14:47:02 +0000277typedef struct _wine_cleanup {
278 void (*routine)(void *);
279 void *arg;
280} *wine_cleanup;
281
Chris Morgan417296c2002-04-02 00:49:05 +0000282int pthread_create(pthread_t* thread, const pthread_attr_t* attr, void*
283 (*start_routine)(void *), void* arg)
284{
Alexandre Julliard80e34db2003-09-03 00:26:08 +0000285 assert( funcs.ptr_pthread_create );
286 return funcs.ptr_pthread_create( thread, attr, start_routine, arg );
Chris Morgan417296c2002-04-02 00:49:05 +0000287}
Vincent Béron9a624912002-05-31 23:06:46 +0000288
Chris Morgan417296c2002-04-02 00:49:05 +0000289int pthread_cancel(pthread_t thread)
290{
Alexandre Julliard80e34db2003-09-03 00:26:08 +0000291 assert( funcs.ptr_pthread_cancel );
292 return funcs.ptr_pthread_cancel( thread );
Vincent Béron9a624912002-05-31 23:06:46 +0000293}
Chris Morgan417296c2002-04-02 00:49:05 +0000294
295int pthread_join(pthread_t thread, void **value_ptr)
296{
Alexandre Julliard80e34db2003-09-03 00:26:08 +0000297 assert( funcs.ptr_pthread_join );
298 return funcs.ptr_pthread_join( thread, value_ptr );
Vincent Béron9a624912002-05-31 23:06:46 +0000299}
Chris Morgan417296c2002-04-02 00:49:05 +0000300
Chris Morgan417296c2002-04-02 00:49:05 +0000301int pthread_detach(pthread_t thread)
302{
Alexandre Julliard80e34db2003-09-03 00:26:08 +0000303 assert( funcs.ptr_pthread_detach );
304 return funcs.ptr_pthread_detach( thread );
Chris Morgan417296c2002-04-02 00:49:05 +0000305}
306
307/* FIXME: we have no equivalents in win32 for the policys */
308/* so just keep this as a stub */
309int pthread_attr_setschedpolicy(pthread_attr_t *attr, int policy)
310{
311 P_OUTPUT("FIXME:pthread_attr_setschedpolicy\n");
312 return 0;
313}
314
315/* FIXME: no win32 equivalent for scope */
316int pthread_attr_setscope(pthread_attr_t *attr, int scope)
317{
318 P_OUTPUT("FIXME:pthread_attr_setscope\n");
319 return 0; /* return success */
320}
Vincent Béron9a624912002-05-31 23:06:46 +0000321
Chris Morgan417296c2002-04-02 00:49:05 +0000322/* FIXME: no win32 equivalent for schedule param */
323int pthread_attr_setschedparam(pthread_attr_t *attr,
324 const struct sched_param *param)
325{
326 P_OUTPUT("FIXME:pthread_attr_setschedparam\n");
327 return 0; /* return success */
328}
329
Alexandre Julliard80e34db2003-09-03 00:26:08 +0000330/* FIXME */
331int pthread_attr_setstack(pthread_attr_t *attr, void *addr, size_t size)
332{
333 return 0; /* return success */
334}
335
Ove Kaavenf19f07d2000-04-14 14:47:02 +0000336int __pthread_once(pthread_once_t *once_control, void (*init_routine)(void))
337{
Alexandre Julliard80e34db2003-09-03 00:26:08 +0000338 static pthread_once_t the_once = PTHREAD_ONCE_INIT;
339 long once_now;
Ove Kaavenf19f07d2000-04-14 14:47:02 +0000340
Alexandre Julliard80e34db2003-09-03 00:26:08 +0000341 memcpy(&once_now,&the_once,sizeof(once_now));
342 if (interlocked_cmpxchg((long*)once_control, once_now+1, once_now) == once_now)
343 (*init_routine)();
344 return 0;
Ove Kaavenf19f07d2000-04-14 14:47:02 +0000345}
346strong_alias(__pthread_once, pthread_once);
347
Ove Kaaven166209a2000-04-23 20:01:45 +0000348void __pthread_kill_other_threads_np(void)
349{
Alexandre Julliardde70b832001-10-09 21:59:16 +0000350 /* we don't need to do anything here */
Ove Kaaven166209a2000-04-23 20:01:45 +0000351}
352strong_alias(__pthread_kill_other_threads_np, pthread_kill_other_threads_np);
353
Alexandre Julliard95a43322000-05-01 16:19:40 +0000354/***** atfork *****/
355
356#define MAX_ATFORK 8 /* libc doesn't need that many anyway */
357
Alexandre Julliard80e34db2003-09-03 00:26:08 +0000358static pthread_mutex_t atfork_mutex = PTHREAD_MUTEX_INITIALIZER;
Alexandre Julliard19b6a492003-08-12 23:50:54 +0000359
Alexandre Julliard95a43322000-05-01 16:19:40 +0000360typedef void (*atfork_handler)();
361static atfork_handler atfork_prepare[MAX_ATFORK];
362static atfork_handler atfork_parent[MAX_ATFORK];
363static atfork_handler atfork_child[MAX_ATFORK];
364static int atfork_count;
365
Alexandre Julliard80e34db2003-09-03 00:26:08 +0000366int __pthread_atfork(void (*prepare)(void), void (*parent)(void), void (*child)(void))
Ove Kaaven166209a2000-04-23 20:01:45 +0000367{
Alexandre Julliard80e34db2003-09-03 00:26:08 +0000368 pthread_mutex_lock( &atfork_mutex );
Alexandre Julliard95a43322000-05-01 16:19:40 +0000369 assert( atfork_count < MAX_ATFORK );
370 atfork_prepare[atfork_count] = prepare;
371 atfork_parent[atfork_count] = parent;
372 atfork_child[atfork_count] = child;
373 atfork_count++;
Alexandre Julliard80e34db2003-09-03 00:26:08 +0000374 pthread_mutex_unlock( &atfork_mutex );
Alexandre Julliard95a43322000-05-01 16:19:40 +0000375 return 0;
Ove Kaaven166209a2000-04-23 20:01:45 +0000376}
377strong_alias(__pthread_atfork, pthread_atfork);
378
Alexandre Julliard26fd7402002-10-22 00:44:24 +0000379pid_t __fork(void)
Ove Kaaven1abdb6f2000-04-28 14:44:05 +0000380{
Alexandre Julliard95a43322000-05-01 16:19:40 +0000381 pid_t pid;
382 int i;
383
Alexandre Julliard26fd7402002-10-22 00:44:24 +0000384 if (!libc_fork)
385 {
386 libc_fork = dlsym( RTLD_NEXT, "fork" );
387 assert( libc_fork );
388 }
Alexandre Julliard80e34db2003-09-03 00:26:08 +0000389 pthread_mutex_lock( &atfork_mutex );
Alexandre Julliard95a43322000-05-01 16:19:40 +0000390 /* prepare handlers are called in reverse insertion order */
Bill Medland7a60dd02001-09-26 23:04:40 +0000391 for (i = atfork_count - 1; i >= 0; i--) if (atfork_prepare[i]) atfork_prepare[i]();
Alexandre Julliard26fd7402002-10-22 00:44:24 +0000392 if (!(pid = libc_fork()))
Alexandre Julliard95a43322000-05-01 16:19:40 +0000393 {
Alexandre Julliard80e34db2003-09-03 00:26:08 +0000394 pthread_mutex_init( &atfork_mutex, NULL );
Bill Medland7a60dd02001-09-26 23:04:40 +0000395 for (i = 0; i < atfork_count; i++) if (atfork_child[i]) atfork_child[i]();
Alexandre Julliard95a43322000-05-01 16:19:40 +0000396 }
397 else
398 {
Bill Medland7a60dd02001-09-26 23:04:40 +0000399 for (i = 0; i < atfork_count; i++) if (atfork_parent[i]) atfork_parent[i]();
Alexandre Julliard80e34db2003-09-03 00:26:08 +0000400 pthread_mutex_unlock( &atfork_mutex );
Alexandre Julliard95a43322000-05-01 16:19:40 +0000401 }
402 return pid;
Ove Kaaven1abdb6f2000-04-28 14:44:05 +0000403}
Alexandre Julliard26fd7402002-10-22 00:44:24 +0000404strong_alias(__fork, fork);
Ove Kaaven166209a2000-04-23 20:01:45 +0000405
406/***** MUTEXES *****/
407
Alexandre Julliard80e34db2003-09-03 00:26:08 +0000408int __pthread_mutex_init(pthread_mutex_t *mutex, const pthread_mutexattr_t *mutexattr)
Ove Kaavenf19f07d2000-04-14 14:47:02 +0000409{
Alexandre Julliard80e34db2003-09-03 00:26:08 +0000410 if (!funcs.ptr_pthread_mutex_init) return 0;
411 return funcs.ptr_pthread_mutex_init( mutex, mutexattr );
Ove Kaavenf19f07d2000-04-14 14:47:02 +0000412}
413strong_alias(__pthread_mutex_init, pthread_mutex_init);
414
Ove Kaavenf19f07d2000-04-14 14:47:02 +0000415int __pthread_mutex_lock(pthread_mutex_t *mutex)
416{
Alexandre Julliard80e34db2003-09-03 00:26:08 +0000417 if (!funcs.ptr_pthread_mutex_lock) return 0;
418 return funcs.ptr_pthread_mutex_lock( mutex );
Ove Kaavenf19f07d2000-04-14 14:47:02 +0000419}
420strong_alias(__pthread_mutex_lock, pthread_mutex_lock);
421
422int __pthread_mutex_trylock(pthread_mutex_t *mutex)
423{
Alexandre Julliard80e34db2003-09-03 00:26:08 +0000424 if (!funcs.ptr_pthread_mutex_trylock) return 0;
425 return funcs.ptr_pthread_mutex_trylock( mutex );
Ove Kaavenf19f07d2000-04-14 14:47:02 +0000426}
427strong_alias(__pthread_mutex_trylock, pthread_mutex_trylock);
428
429int __pthread_mutex_unlock(pthread_mutex_t *mutex)
430{
Alexandre Julliard80e34db2003-09-03 00:26:08 +0000431 if (!funcs.ptr_pthread_mutex_unlock) return 0;
432 return funcs.ptr_pthread_mutex_unlock( mutex );
Ove Kaavenf19f07d2000-04-14 14:47:02 +0000433}
434strong_alias(__pthread_mutex_unlock, pthread_mutex_unlock);
435
436int __pthread_mutex_destroy(pthread_mutex_t *mutex)
437{
Alexandre Julliard80e34db2003-09-03 00:26:08 +0000438 if (!funcs.ptr_pthread_mutex_destroy) return 0;
439 return funcs.ptr_pthread_mutex_destroy( mutex );
Ove Kaavenf19f07d2000-04-14 14:47:02 +0000440}
441strong_alias(__pthread_mutex_destroy, pthread_mutex_destroy);
442
Ove Kaaven166209a2000-04-23 20:01:45 +0000443
444/***** MUTEX ATTRIBUTES *****/
445/* just dummies, since critical sections are always recursive */
Ove Kaavenf19f07d2000-04-14 14:47:02 +0000446
447int __pthread_mutexattr_init(pthread_mutexattr_t *attr)
448{
449 return 0;
450}
451strong_alias(__pthread_mutexattr_init, pthread_mutexattr_init);
452
453int __pthread_mutexattr_destroy(pthread_mutexattr_t *attr)
454{
455 return 0;
456}
457strong_alias(__pthread_mutexattr_destroy, pthread_mutexattr_destroy);
458
459int __pthread_mutexattr_setkind_np(pthread_mutexattr_t *attr, int kind)
460{
461 return 0;
462}
463strong_alias(__pthread_mutexattr_setkind_np, pthread_mutexattr_setkind_np);
464
465int __pthread_mutexattr_getkind_np(pthread_mutexattr_t *attr, int *kind)
466{
Patrik Stridvall6caeb722002-11-25 21:12:26 +0000467 *kind = PTHREAD_MUTEX_RECURSIVE;
Ove Kaavenf19f07d2000-04-14 14:47:02 +0000468 return 0;
469}
470strong_alias(__pthread_mutexattr_getkind_np, pthread_mutexattr_getkind_np);
471
472int __pthread_mutexattr_settype(pthread_mutexattr_t *attr, int kind)
473{
474 return 0;
475}
476strong_alias(__pthread_mutexattr_settype, pthread_mutexattr_settype);
477
478int __pthread_mutexattr_gettype(pthread_mutexattr_t *attr, int *kind)
479{
Patrik Stridvall6caeb722002-11-25 21:12:26 +0000480 *kind = PTHREAD_MUTEX_RECURSIVE;
Ove Kaavenf19f07d2000-04-14 14:47:02 +0000481 return 0;
482}
483strong_alias(__pthread_mutexattr_gettype, pthread_mutexattr_gettype);
484
Ove Kaaven166209a2000-04-23 20:01:45 +0000485
486/***** THREAD-SPECIFIC VARIABLES (KEYS) *****/
487
Ove Kaavenf19f07d2000-04-14 14:47:02 +0000488int __pthread_key_create(pthread_key_t *key, void (*destr_function)(void *))
489{
Alexandre Julliard80e34db2003-09-03 00:26:08 +0000490 static long keycnt = FIRST_KEY;
491 *key = interlocked_xchg_add(&keycnt, 1);
492 return 0;
Ove Kaavenf19f07d2000-04-14 14:47:02 +0000493}
494strong_alias(__pthread_key_create, pthread_key_create);
495
496int __pthread_key_delete(pthread_key_t key)
497{
498 return 0;
499}
500strong_alias(__pthread_key_delete, pthread_key_delete);
501
502int __pthread_setspecific(pthread_key_t key, const void *pointer)
503{
Alexandre Julliard97d862c2003-08-12 18:59:13 +0000504 pthread_descr descr = __pthread_thread_self();
505 descr->key_data[key] = pointer;
506 return 0;
Ove Kaavenf19f07d2000-04-14 14:47:02 +0000507}
508strong_alias(__pthread_setspecific, pthread_setspecific);
509
510void *__pthread_getspecific(pthread_key_t key)
511{
Alexandre Julliard97d862c2003-08-12 18:59:13 +0000512 pthread_descr descr = __pthread_thread_self();
513 return (void *)descr->key_data[key];
Ove Kaavenf19f07d2000-04-14 14:47:02 +0000514}
515strong_alias(__pthread_getspecific, pthread_getspecific);
516
Alexandre Julliard97d862c2003-08-12 18:59:13 +0000517static int pthread_internal_tsd_set( int key, const void *pointer )
518{
519 pthread_descr descr = __pthread_thread_self();
520 descr->tsd_data[key] = pointer;
521 return 0;
522}
Alexandre Julliard80e34db2003-09-03 00:26:08 +0000523int (*__libc_internal_tsd_set)(int, const void *) = pthread_internal_tsd_set;
Alexandre Julliard97d862c2003-08-12 18:59:13 +0000524
525static void *pthread_internal_tsd_get( int key )
526{
527 pthread_descr descr = __pthread_thread_self();
528 return (void *)descr->tsd_data[key];
529}
Alexandre Julliard80e34db2003-09-03 00:26:08 +0000530void* (*__libc_internal_tsd_get)(int) = pthread_internal_tsd_get;
Alexandre Julliard97d862c2003-08-12 18:59:13 +0000531
532static void ** __attribute__((const)) pthread_internal_tsd_address( int key )
533{
534 pthread_descr descr = __pthread_thread_self();
535 return (void **)&descr->tsd_data[key];
536}
Alexandre Julliard80e34db2003-09-03 00:26:08 +0000537void** (*__libc_internal_tsd_address)(int) = pthread_internal_tsd_address;
Alexandre Julliard97d862c2003-08-12 18:59:13 +0000538
Ove Kaaven166209a2000-04-23 20:01:45 +0000539/***** "EXCEPTION" FRAMES *****/
540/* not implemented right now */
541
Ove Kaavenf19f07d2000-04-14 14:47:02 +0000542void _pthread_cleanup_push(struct _pthread_cleanup_buffer *buffer, void (*routine)(void *), void *arg)
543{
544 ((wine_cleanup)buffer)->routine = routine;
545 ((wine_cleanup)buffer)->arg = arg;
546}
547
548void _pthread_cleanup_pop(struct _pthread_cleanup_buffer *buffer, int execute)
549{
550 if (execute) (*(((wine_cleanup)buffer)->routine))(((wine_cleanup)buffer)->arg);
551}
552
553void _pthread_cleanup_push_defer(struct _pthread_cleanup_buffer *buffer, void (*routine)(void *), void *arg)
554{
555 _pthread_cleanup_push(buffer, routine, arg);
556}
557
558void _pthread_cleanup_pop_restore(struct _pthread_cleanup_buffer *buffer, int execute)
559{
560 _pthread_cleanup_pop(buffer, execute);
561}
562
Alexandre Julliard97d862c2003-08-12 18:59:13 +0000563void __pthread_cleanup_upto(jmp_buf target, char *frame)
564{
565 /* FIXME */
566}
Ove Kaaven166209a2000-04-23 20:01:45 +0000567
568/***** CONDITIONS *****/
Ove Kaaven166209a2000-04-23 20:01:45 +0000569
Alexandre Julliard97d862c2003-08-12 18:59:13 +0000570int __pthread_cond_init(pthread_cond_t *cond, const pthread_condattr_t *cond_attr)
Ove Kaaven166209a2000-04-23 20:01:45 +0000571{
Alexandre Julliard3bff2b32003-09-23 22:59:44 +0000572 if (!funcs.ptr_pthread_cond_init) return 0;
573 return funcs.ptr_pthread_cond_init(cond, cond_attr);
Ove Kaaven166209a2000-04-23 20:01:45 +0000574}
Alexandre Julliard97d862c2003-08-12 18:59:13 +0000575strong_alias(__pthread_cond_init, pthread_cond_init);
Ove Kaaven166209a2000-04-23 20:01:45 +0000576
Alexandre Julliard97d862c2003-08-12 18:59:13 +0000577int __pthread_cond_destroy(pthread_cond_t *cond)
Ove Kaaven166209a2000-04-23 20:01:45 +0000578{
Alexandre Julliard3bff2b32003-09-23 22:59:44 +0000579 if (!funcs.ptr_pthread_cond_destroy) return 0;
580 return funcs.ptr_pthread_cond_destroy(cond);
Ove Kaaven166209a2000-04-23 20:01:45 +0000581}
Alexandre Julliard97d862c2003-08-12 18:59:13 +0000582strong_alias(__pthread_cond_destroy, pthread_cond_destroy);
Ove Kaaven166209a2000-04-23 20:01:45 +0000583
Alexandre Julliard97d862c2003-08-12 18:59:13 +0000584int __pthread_cond_signal(pthread_cond_t *cond)
Ove Kaaven166209a2000-04-23 20:01:45 +0000585{
Alexandre Julliard3bff2b32003-09-23 22:59:44 +0000586 if (!funcs.ptr_pthread_cond_signal) return 0;
587 return funcs.ptr_pthread_cond_signal(cond);
Ove Kaaven166209a2000-04-23 20:01:45 +0000588}
Alexandre Julliard97d862c2003-08-12 18:59:13 +0000589strong_alias(__pthread_cond_signal, pthread_cond_signal);
Ove Kaaven166209a2000-04-23 20:01:45 +0000590
Alexandre Julliard97d862c2003-08-12 18:59:13 +0000591int __pthread_cond_broadcast(pthread_cond_t *cond)
Ove Kaaven166209a2000-04-23 20:01:45 +0000592{
Alexandre Julliard3bff2b32003-09-23 22:59:44 +0000593 if (!funcs.ptr_pthread_cond_broadcast) return 0;
594 return funcs.ptr_pthread_cond_broadcast(cond);
Ove Kaaven166209a2000-04-23 20:01:45 +0000595}
Alexandre Julliard97d862c2003-08-12 18:59:13 +0000596strong_alias(__pthread_cond_broadcast, pthread_cond_broadcast);
Ove Kaaven166209a2000-04-23 20:01:45 +0000597
Alexandre Julliard97d862c2003-08-12 18:59:13 +0000598int __pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex)
Ove Kaaven166209a2000-04-23 20:01:45 +0000599{
Alexandre Julliard3bff2b32003-09-23 22:59:44 +0000600 if (!funcs.ptr_pthread_cond_wait) return 0;
601 return funcs.ptr_pthread_cond_wait(cond, mutex);
Ove Kaaven166209a2000-04-23 20:01:45 +0000602}
Alexandre Julliard97d862c2003-08-12 18:59:13 +0000603strong_alias(__pthread_cond_wait, pthread_cond_wait);
Ove Kaaven166209a2000-04-23 20:01:45 +0000604
Alexandre Julliard97d862c2003-08-12 18:59:13 +0000605int __pthread_cond_timedwait(pthread_cond_t *cond, pthread_mutex_t *mutex, const struct timespec *abstime)
Ove Kaaven166209a2000-04-23 20:01:45 +0000606{
Alexandre Julliard3bff2b32003-09-23 22:59:44 +0000607 if (!funcs.ptr_pthread_cond_timedwait) return 0;
608 return funcs.ptr_pthread_cond_timedwait(cond, mutex, abstime);
Ove Kaaven166209a2000-04-23 20:01:45 +0000609}
Alexandre Julliard97d862c2003-08-12 18:59:13 +0000610strong_alias(__pthread_cond_timedwait, pthread_cond_timedwait);
Ove Kaaven166209a2000-04-23 20:01:45 +0000611
612/**** CONDITION ATTRIBUTES *****/
613/* not implemented right now */
614
615int pthread_condattr_init(pthread_condattr_t *attr)
616{
617 return 0;
618}
619
620int pthread_condattr_destroy(pthread_condattr_t *attr)
621{
622 return 0;
623}
624
Ove Kaavenccc538b2000-11-13 04:14:49 +0000625/***** READ-WRITE LOCKS *****/
Jukka Heinonen31b8b642001-12-11 00:20:18 +0000626
Ove Kaavenccc538b2000-11-13 04:14:49 +0000627int __pthread_rwlock_init(pthread_rwlock_t *rwlock, const pthread_rwlockattr_t *rwlock_attr)
628{
Alexandre Julliard80e34db2003-09-03 00:26:08 +0000629 assert( funcs.ptr_pthread_rwlock_init );
630 return funcs.ptr_pthread_rwlock_init( rwlock, rwlock_attr );
Ove Kaavenccc538b2000-11-13 04:14:49 +0000631}
632strong_alias(__pthread_rwlock_init, pthread_rwlock_init);
633
634int __pthread_rwlock_destroy(pthread_rwlock_t *rwlock)
635{
Alexandre Julliard80e34db2003-09-03 00:26:08 +0000636 assert( funcs.ptr_pthread_rwlock_destroy );
637 return funcs.ptr_pthread_rwlock_destroy( rwlock );
Ove Kaavenccc538b2000-11-13 04:14:49 +0000638}
639strong_alias(__pthread_rwlock_destroy, pthread_rwlock_destroy);
640
641int __pthread_rwlock_rdlock(pthread_rwlock_t *rwlock)
642{
Alexandre Julliard80e34db2003-09-03 00:26:08 +0000643 if (!funcs.ptr_pthread_rwlock_rdlock) return 0;
644 return funcs.ptr_pthread_rwlock_rdlock( rwlock );
Ove Kaavenccc538b2000-11-13 04:14:49 +0000645}
646strong_alias(__pthread_rwlock_rdlock, pthread_rwlock_rdlock);
647
648int __pthread_rwlock_tryrdlock(pthread_rwlock_t *rwlock)
649{
Alexandre Julliard80e34db2003-09-03 00:26:08 +0000650 assert( funcs.ptr_pthread_rwlock_tryrdlock );
651 return funcs.ptr_pthread_rwlock_tryrdlock( rwlock );
Ove Kaavenccc538b2000-11-13 04:14:49 +0000652}
653strong_alias(__pthread_rwlock_tryrdlock, pthread_rwlock_tryrdlock);
654
655int __pthread_rwlock_wrlock(pthread_rwlock_t *rwlock)
656{
Alexandre Julliard80e34db2003-09-03 00:26:08 +0000657 assert( funcs.ptr_pthread_rwlock_wrlock );
658 return funcs.ptr_pthread_rwlock_wrlock( rwlock );
Ove Kaavenccc538b2000-11-13 04:14:49 +0000659}
660strong_alias(__pthread_rwlock_wrlock, pthread_rwlock_wrlock);
661
662int __pthread_rwlock_trywrlock(pthread_rwlock_t *rwlock)
663{
Alexandre Julliard80e34db2003-09-03 00:26:08 +0000664 assert( funcs.ptr_pthread_rwlock_trywrlock );
665 return funcs.ptr_pthread_rwlock_trywrlock( rwlock );
Ove Kaavenccc538b2000-11-13 04:14:49 +0000666}
667strong_alias(__pthread_rwlock_trywrlock, pthread_rwlock_trywrlock);
668
669int __pthread_rwlock_unlock(pthread_rwlock_t *rwlock)
670{
Alexandre Julliard1d2eb372003-09-25 20:30:18 +0000671 if (!funcs.ptr_pthread_rwlock_unlock) return 0;
Alexandre Julliard80e34db2003-09-03 00:26:08 +0000672 return funcs.ptr_pthread_rwlock_unlock( rwlock );
Ove Kaavenccc538b2000-11-13 04:14:49 +0000673}
674strong_alias(__pthread_rwlock_unlock, pthread_rwlock_unlock);
675
676/**** READ-WRITE LOCK ATTRIBUTES *****/
677/* not implemented right now */
678
679int pthread_rwlockattr_init(pthread_rwlockattr_t *attr)
680{
681 return 0;
682}
683
684int __pthread_rwlockattr_destroy(pthread_rwlockattr_t *attr)
685{
686 return 0;
687}
688strong_alias(__pthread_rwlockattr_destroy, pthread_rwlockattr_destroy);
689
690int pthread_rwlockattr_getkind_np(const pthread_rwlockattr_t *attr, int *pref)
691{
692 *pref = 0;
693 return 0;
694}
695
696int pthread_rwlockattr_setkind_np(pthread_rwlockattr_t *attr, int pref)
697{
698 return 0;
699}
Ove Kaavenccc538b2000-11-13 04:14:49 +0000700
Ove Kaaven166209a2000-04-23 20:01:45 +0000701/***** MISC *****/
702
Ove Kaavenf19f07d2000-04-14 14:47:02 +0000703pthread_t pthread_self(void)
704{
Alexandre Julliard80e34db2003-09-03 00:26:08 +0000705 assert( funcs.ptr_pthread_self );
706 return funcs.ptr_pthread_self();
Ove Kaavenf19f07d2000-04-14 14:47:02 +0000707}
708
709int pthread_equal(pthread_t thread1, pthread_t thread2)
710{
Alexandre Julliard80e34db2003-09-03 00:26:08 +0000711 assert( funcs.ptr_pthread_equal );
712 return funcs.ptr_pthread_equal( thread1, thread2 );
Ove Kaavenf19f07d2000-04-14 14:47:02 +0000713}
714
Alexandre Julliard97d862c2003-08-12 18:59:13 +0000715void __pthread_do_exit(void *retval, char *currentframe)
Ove Kaaven166209a2000-04-23 20:01:45 +0000716{
Alexandre Julliard80e34db2003-09-03 00:26:08 +0000717 assert( funcs.ptr_pthread_exit );
718 return funcs.ptr_pthread_exit( retval, currentframe );
Ove Kaaven166209a2000-04-23 20:01:45 +0000719}
720
Alexandre Julliard97d862c2003-08-12 18:59:13 +0000721void __pthread_exit(void *retval)
722{
723 __pthread_do_exit( retval, NULL );
724}
725strong_alias(__pthread_exit, pthread_exit);
726
Alexandre Julliard80e34db2003-09-03 00:26:08 +0000727int pthread_setcancelstate(int state, int *oldstate)
728{
729 pthread_descr descr = __pthread_thread_self();
730 if (oldstate) *oldstate = descr->cancel_state;
731 descr->cancel_state = state;
732 return 0;
733}
734
Ove Kaavenf19f07d2000-04-14 14:47:02 +0000735int pthread_setcanceltype(int type, int *oldtype)
736{
Alexandre Julliard80e34db2003-09-03 00:26:08 +0000737 pthread_descr descr = __pthread_thread_self();
738 if (oldtype) *oldtype = descr->cancel_type;
739 descr->cancel_type = type;
740 return 0;
Ove Kaavenf19f07d2000-04-14 14:47:02 +0000741}
742
Ove Kaaven166209a2000-04-23 20:01:45 +0000743/***** ANTI-OVERRIDES *****/
744/* pthreads tries to override these, point them back to libc */
745
Ove Kaaven166209a2000-04-23 20:01:45 +0000746int sigaction(int signum, const struct sigaction *act, struct sigaction *oldact)
747{
Alexandre Julliard26fd7402002-10-22 00:44:24 +0000748 if (!libc_sigaction)
749 {
750 libc_sigaction = dlsym( RTLD_NEXT, "sigaction" );
751 assert( libc_sigaction );
752 }
753 return libc_sigaction(signum, act, oldact);
Ove Kaaven166209a2000-04-23 20:01:45 +0000754}
Alexandre Julliard26fd7402002-10-22 00:44:24 +0000755
Alexandre Julliard80e34db2003-09-03 00:26:08 +0000756void __pthread_initialize(void)
757{
758 static int done;
759
760 if (!done)
761 {
762 done = 1;
763 libc_fork = dlsym( RTLD_NEXT, "fork" );
764 libc_sigaction = dlsym( RTLD_NEXT, "sigaction" );
765 libc_uselocale = dlsym( RTLD_NEXT, "uselocale" );
766 libc_pthread_init = dlsym( RTLD_NEXT, "__libc_pthread_init" );
767 if (libc_pthread_init) libc_multiple_threads = libc_pthread_init( &libc_pthread_functions );
768 }
769}
770DECL_GLOBAL_CONSTRUCTOR(init) { __pthread_initialize(); }
771
772static struct pthread_functions libc_pthread_functions =
Alexandre Julliard97d862c2003-08-12 18:59:13 +0000773{
774 NULL, /* ptr_pthread_fork */
775 NULL, /* FIXME */ /* ptr_pthread_attr_destroy */
776 NULL, /* FIXME */ /* ptr___pthread_attr_init_2_0 */
777 NULL, /* FIXME */ /* ptr___pthread_attr_init_2_1 */
778 NULL, /* FIXME */ /* ptr_pthread_attr_getdetachstate */
779 NULL, /* FIXME */ /* ptr_pthread_attr_setdetachstate */
780 NULL, /* FIXME */ /* ptr_pthread_attr_getinheritsched */
781 NULL, /* FIXME */ /* ptr_pthread_attr_setinheritsched */
782 NULL, /* FIXME */ /* ptr_pthread_attr_getschedparam */
783 pthread_attr_setschedparam, /* ptr_pthread_attr_setschedparam */
784 NULL, /* FIXME */ /* ptr_pthread_attr_getschedpolicy) (const pthread_attr_t *, int *); */
785 NULL, /* FIXME */ /* ptr_pthread_attr_setschedpolicy) (pthread_attr_t *, int); */
786 NULL, /* FIXME */ /* ptr_pthread_attr_getscope) (const pthread_attr_t *, int *); */
787 NULL, /* FIXME */ /* ptr_pthread_attr_setscope) (pthread_attr_t *, int); */
788 pthread_condattr_destroy, /* ptr_pthread_condattr_destroy */
789 pthread_condattr_init, /* ptr_pthread_condattr_init */
790 __pthread_cond_broadcast, /* ptr___pthread_cond_broadcast */
791 __pthread_cond_destroy, /* ptr___pthread_cond_destroy */
792 __pthread_cond_init, /* ptr___pthread_cond_init */
793 __pthread_cond_signal, /* ptr___pthread_cond_signal */
794 __pthread_cond_wait, /* ptr___pthread_cond_wait */
795 pthread_equal, /* ptr_pthread_equal */
796 __pthread_exit, /* ptr___pthread_exit */
797 NULL, /* FIXME */ /* ptr_pthread_getschedparam */
798 NULL, /* FIXME */ /* ptr_pthread_setschedparam */
799 __pthread_mutex_destroy, /* ptr_pthread_mutex_destroy */
800 __pthread_mutex_init, /* ptr_pthread_mutex_init */
801 __pthread_mutex_lock, /* ptr_pthread_mutex_lock */
802 __pthread_mutex_trylock, /* ptr_pthread_mutex_trylock */
803 __pthread_mutex_unlock, /* ptr_pthread_mutex_unlock */
804 pthread_self, /* ptr_pthread_self */
Alexandre Julliard80e34db2003-09-03 00:26:08 +0000805 pthread_setcancelstate, /* ptr_pthread_setcancelstate */
Alexandre Julliard97d862c2003-08-12 18:59:13 +0000806 pthread_setcanceltype, /* ptr_pthread_setcanceltype */
807 __pthread_do_exit, /* ptr_pthread_do_exit */
808 __pthread_cleanup_upto, /* ptr_pthread_cleanup_upto */
809 __pthread_thread_self, /* ptr_pthread_thread_self */
810 pthread_internal_tsd_set, /* ptr_pthread_internal_tsd_set */
811 pthread_internal_tsd_get, /* ptr_pthread_internal_tsd_get */
812 pthread_internal_tsd_address, /* ptr_pthread_internal_tsd_address */
813 NULL, /* ptr_pthread_sigaction */
814 NULL, /* ptr_pthread_sigwait */
Alexandre Julliarddbb2b802003-09-11 01:09:09 +0000815 NULL, /* ptr_pthread_raise */
Alexandre Julliarde8bd1102003-10-03 03:39:29 +0000816 __pthread_cond_timedwait, /* ptr___pthread_cond_timedwait */
817 _pthread_cleanup_push, /* ptr__pthread_cleanup_push */
818 _pthread_cleanup_pop /* ptr__pthread_cleanup_pop */
Alexandre Julliard97d862c2003-08-12 18:59:13 +0000819};
820
Alexandre Julliard03d79982003-08-15 03:55:06 +0000821#endif /* __GLIBC__ || __FREEBSD__ */
822
823#else /* HAVE_NPTL */
Alexandre Julliard26fd7402002-10-22 00:44:24 +0000824
Alexandre Julliard80e34db2003-09-03 00:26:08 +0000825void wine_pthread_init_process( const struct wine_pthread_functions *functions )
826{
827}
828
829void wine_pthread_init_thread(void)
Alexandre Julliard26fd7402002-10-22 00:44:24 +0000830{
831}
Ove Kaaven166209a2000-04-23 20:01:45 +0000832
Alexandre Julliard03d79982003-08-15 03:55:06 +0000833#endif /* HAVE_NPTL */