Ove Kaaven | f19f07d | 2000-04-14 14:47:02 +0000 | [diff] [blame] | 1 | /* |
| 2 | * pthread emulation for re-entrant libcs |
| 3 | * |
| 4 | * We can't use pthreads directly, so why not let libcs |
Andreas Mohr | 9cef2d0 | 2001-11-19 02:30:01 +0000 | [diff] [blame] | 5 | * that want pthreads use Wine's own threading instead... |
Ove Kaaven | f19f07d | 2000-04-14 14:47:02 +0000 | [diff] [blame] | 6 | * |
| 7 | * Copyright 1999 Ove Kåven |
Alexandre Julliard | 80e34db | 2003-09-03 00:26:08 +0000 | [diff] [blame] | 8 | * Copyright 2003 Alexandre Julliard |
Alexandre Julliard | 0799c1a | 2002-03-09 23:29:33 +0000 | [diff] [blame] | 9 | * |
| 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 Kaaven | f19f07d | 2000-04-14 14:47:02 +0000 | [diff] [blame] | 23 | */ |
| 24 | |
| 25 | #include "config.h" |
Alexandre Julliard | 5769d1d | 2002-04-26 19:05:15 +0000 | [diff] [blame] | 26 | #include "wine/port.h" |
| 27 | |
Alexandre Julliard | 03d7998 | 2003-08-15 03:55:06 +0000 | [diff] [blame] | 28 | #ifndef HAVE_NPTL |
| 29 | |
| 30 | struct _pthread_cleanup_buffer; |
| 31 | |
Alexandre Julliard | 95a4332 | 2000-05-01 16:19:40 +0000 | [diff] [blame] | 32 | #include <assert.h> |
Ove Kaaven | f19f07d | 2000-04-14 14:47:02 +0000 | [diff] [blame] | 33 | #include <errno.h> |
| 34 | #include <stdlib.h> |
Alexandre Julliard | 80e34db | 2003-09-03 00:26:08 +0000 | [diff] [blame] | 35 | #include <signal.h> |
Alexandre Julliard | 97d862c | 2003-08-12 18:59:13 +0000 | [diff] [blame] | 36 | #include <setjmp.h> |
Patrik Stridvall | d016f81 | 2002-08-17 00:43:16 +0000 | [diff] [blame] | 37 | #ifdef HAVE_UNISTD_H |
| 38 | # include <unistd.h> |
| 39 | #endif |
Jeff Garzik | f46eb1d | 2001-03-21 20:30:46 +0000 | [diff] [blame] | 40 | #include <string.h> |
Alexandre Julliard | 03d7998 | 2003-08-15 03:55:06 +0000 | [diff] [blame] | 41 | #include <sys/types.h> |
Daniel Marmier | a613de2 | 2003-09-30 00:33:47 +0000 | [diff] [blame] | 42 | #ifdef HAVE_SYS_SOCKET_H |
Alexandre Julliard | 03d7998 | 2003-08-15 03:55:06 +0000 | [diff] [blame] | 43 | # 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 Kaaven | f19f07d | 2000-04-14 14:47:02 +0000 | [diff] [blame] | 57 | |
Alexandre Julliard | 80e34db | 2003-09-03 00:26:08 +0000 | [diff] [blame] | 58 | #include "wine/pthread.h" |
Ove Kaaven | f19f07d | 2000-04-14 14:47:02 +0000 | [diff] [blame] | 59 | |
Alexandre Julliard | 80e34db | 2003-09-03 00:26:08 +0000 | [diff] [blame] | 60 | #define P_OUTPUT(stuff) write(2,stuff,strlen(stuff)) |
| 61 | |
| 62 | #define PSTR(str) __ASM_NAME(#str) |
| 63 | |
| 64 | static 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 | |
| 72 | struct pthread_descr_struct |
Alexandre Julliard | 03d7998 | 2003-08-15 03:55:06 +0000 | [diff] [blame] | 73 | { |
Alexandre Julliard | 80e34db | 2003-09-03 00:26:08 +0000 | [diff] [blame] | 74 | 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 | |
| 84 | typedef struct pthread_descr_struct *pthread_descr; |
| 85 | |
| 86 | static struct pthread_descr_struct initial_descr; |
| 87 | |
| 88 | pthread_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 Julliard | 03d7998 | 2003-08-15 03:55:06 +0000 | [diff] [blame] | 95 | } |
| 96 | |
Alexandre Julliard | 80e34db | 2003-09-03 00:26:08 +0000 | [diff] [blame] | 97 | static int (*libc_uselocale)(int set); |
| 98 | static int *libc_multiple_threads; |
Alexandre Julliard | 03d7998 | 2003-08-15 03:55:06 +0000 | [diff] [blame] | 99 | |
| 100 | /*********************************************************************** |
| 101 | * __errno_location/__error/__errno/___errno/__thr_errno |
| 102 | * |
| 103 | * Get the per-thread errno location. |
| 104 | */ |
Alexandre Julliard | 80e34db | 2003-09-03 00:26:08 +0000 | [diff] [blame] | 105 | int *__errno_location(void) /* Linux */ |
| 106 | { |
| 107 | pthread_descr descr = __pthread_thread_self(); |
| 108 | return &descr->thread_errno; |
| 109 | } |
| 110 | int *__error(void) { return __errno_location(); } /* FreeBSD */ |
| 111 | int *__errno(void) { return __errno_location(); } /* NetBSD */ |
| 112 | int *___errno(void) { return __errno_location(); } /* Solaris */ |
| 113 | int *__thr_errno(void) { return __errno_location(); } /* UnixWare */ |
Alexandre Julliard | 03d7998 | 2003-08-15 03:55:06 +0000 | [diff] [blame] | 114 | |
| 115 | /*********************************************************************** |
| 116 | * __h_errno_location |
| 117 | * |
| 118 | * Get the per-thread h_errno location. |
| 119 | */ |
| 120 | int *__h_errno_location(void) |
| 121 | { |
Alexandre Julliard | 80e34db | 2003-09-03 00:26:08 +0000 | [diff] [blame] | 122 | pthread_descr descr = __pthread_thread_self(); |
| 123 | return &descr->thread_h_errno; |
| 124 | } |
| 125 | |
Gabriele Giorgetti | 59b2ad6 | 2003-09-18 20:52:24 +0000 | [diff] [blame] | 126 | struct __res_state *__res_state(void) |
| 127 | { |
| 128 | pthread_descr descr = __pthread_thread_self(); |
| 129 | return &descr->res_state; |
| 130 | } |
Alexandre Julliard | 80e34db | 2003-09-03 00:26:08 +0000 | [diff] [blame] | 131 | |
| 132 | static 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 | */ |
| 156 | void 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 Julliard | 80e34db | 2003-09-03 00:26:08 +0000 | [diff] [blame] | 160 | } |
| 161 | |
| 162 | |
| 163 | /*********************************************************************** |
| 164 | * wine_pthread_init_thread |
| 165 | * |
| 166 | * Initialization for a newly created thread. |
| 167 | */ |
| 168 | void wine_pthread_init_thread(void) |
| 169 | { |
Alexandre Julliard | cf4ca4e | 2003-10-12 02:26:20 +0000 | [diff] [blame] | 170 | struct pthread_descr_struct *descr; |
| 171 | |
Alexandre Julliard | 80e34db | 2003-09-03 00:26:08 +0000 | [diff] [blame] | 172 | if (funcs.ptr_set_thread_data) |
| 173 | { |
Alexandre Julliard | cf4ca4e | 2003-10-12 02:26:20 +0000 | [diff] [blame] | 174 | descr = calloc( 1, sizeof(*descr) ); |
Alexandre Julliard | 80e34db | 2003-09-03 00:26:08 +0000 | [diff] [blame] | 175 | funcs.ptr_set_thread_data( descr ); |
Alexandre Julliard | 80e34db | 2003-09-03 00:26:08 +0000 | [diff] [blame] | 176 | if (libc_multiple_threads) *libc_multiple_threads = 1; |
Alexandre Julliard | 80e34db | 2003-09-03 00:26:08 +0000 | [diff] [blame] | 177 | } |
Alexandre Julliard | cf4ca4e | 2003-10-12 02:26:20 +0000 | [diff] [blame] | 178 | 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 Julliard | 03d7998 | 2003-08-15 03:55:06 +0000 | [diff] [blame] | 188 | } |
| 189 | |
| 190 | |
Ove Kaaven | f19f07d | 2000-04-14 14:47:02 +0000 | [diff] [blame] | 191 | /* 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 Julliard | 03d7998 | 2003-08-15 03:55:06 +0000 | [diff] [blame] | 197 | #if defined(__GLIBC__) || defined(__FreeBSD__) |
Patrik Stridvall | 6caeb72 | 2002-11-25 21:12:26 +0000 | [diff] [blame] | 198 | |
| 199 | #ifndef __USE_UNIX98 |
| 200 | #define __USE_UNIX98 |
| 201 | #endif |
| 202 | |
Ove Kaaven | f19f07d | 2000-04-14 14:47:02 +0000 | [diff] [blame] | 203 | #include <pthread.h> |
Ove Kaaven | 1abdb6f | 2000-04-28 14:44:05 +0000 | [diff] [blame] | 204 | |
Ove Kaaven | f19f07d | 2000-04-14 14:47:02 +0000 | [diff] [blame] | 205 | /* adapt as necessary (a construct like this is used in glibc sources) */ |
| 206 | #define strong_alias(orig, alias) \ |
Ove Kaaven | d293731 | 2000-05-09 22:32:25 +0000 | [diff] [blame] | 207 | asm(".globl " PSTR(alias) "\n" \ |
| 208 | "\t.set " PSTR(alias) "," PSTR(orig)) |
Ove Kaaven | f19f07d | 2000-04-14 14:47:02 +0000 | [diff] [blame] | 209 | |
Alexandre Julliard | 97d862c | 2003-08-12 18:59:13 +0000 | [diff] [blame] | 210 | struct fork_block; |
| 211 | |
Alexandre Julliard | 03d7998 | 2003-08-15 03:55:06 +0000 | [diff] [blame] | 212 | /* pthread functions redirection */ |
| 213 | |
Alexandre Julliard | 97d862c | 2003-08-12 18:59:13 +0000 | [diff] [blame] | 214 | struct 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 Julliard | dbb2b80 | 2003-09-11 01:09:09 +0000 | [diff] [blame] | 258 | int (*ptr___pthread_cond_timedwait) (pthread_cond_t *, pthread_mutex_t *, const struct timespec *); |
Alexandre Julliard | e8bd110 | 2003-10-03 03:39:29 +0000 | [diff] [blame] | 259 | 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 Julliard | 97d862c | 2003-08-12 18:59:13 +0000 | [diff] [blame] | 261 | }; |
| 262 | |
Alexandre Julliard | 26fd740 | 2002-10-22 00:44:24 +0000 | [diff] [blame] | 263 | static pid_t (*libc_fork)(void); |
| 264 | static int (*libc_sigaction)(int signum, const struct sigaction *act, struct sigaction *oldact); |
Alexandre Julliard | 97d862c | 2003-08-12 18:59:13 +0000 | [diff] [blame] | 265 | static int *(*libc_pthread_init)( const struct pthread_functions *funcs ); |
Ove Kaaven | 1abdb6f | 2000-04-28 14:44:05 +0000 | [diff] [blame] | 266 | |
Alexandre Julliard | 80e34db | 2003-09-03 00:26:08 +0000 | [diff] [blame] | 267 | static struct pthread_functions libc_pthread_functions; |
| 268 | |
| 269 | strong_alias(__pthread_thread_self, pthread_thread_self); |
Alexandre Julliard | 26fd740 | 2002-10-22 00:44:24 +0000 | [diff] [blame] | 270 | |
Alexandre Julliard | 97d862c | 2003-08-12 18:59:13 +0000 | [diff] [blame] | 271 | /* redefine this to prevent libpthread from overriding our function pointers */ |
| 272 | int *__libc_pthread_init( const struct pthread_functions *funcs ) |
| 273 | { |
| 274 | return libc_multiple_threads; |
| 275 | } |
Ove Kaaven | 1abdb6f | 2000-04-28 14:44:05 +0000 | [diff] [blame] | 276 | |
Ove Kaaven | f19f07d | 2000-04-14 14:47:02 +0000 | [diff] [blame] | 277 | typedef struct _wine_cleanup { |
| 278 | void (*routine)(void *); |
| 279 | void *arg; |
| 280 | } *wine_cleanup; |
| 281 | |
Chris Morgan | 417296c | 2002-04-02 00:49:05 +0000 | [diff] [blame] | 282 | int pthread_create(pthread_t* thread, const pthread_attr_t* attr, void* |
| 283 | (*start_routine)(void *), void* arg) |
| 284 | { |
Alexandre Julliard | 80e34db | 2003-09-03 00:26:08 +0000 | [diff] [blame] | 285 | assert( funcs.ptr_pthread_create ); |
| 286 | return funcs.ptr_pthread_create( thread, attr, start_routine, arg ); |
Chris Morgan | 417296c | 2002-04-02 00:49:05 +0000 | [diff] [blame] | 287 | } |
Vincent Béron | 9a62491 | 2002-05-31 23:06:46 +0000 | [diff] [blame] | 288 | |
Chris Morgan | 417296c | 2002-04-02 00:49:05 +0000 | [diff] [blame] | 289 | int pthread_cancel(pthread_t thread) |
| 290 | { |
Alexandre Julliard | 80e34db | 2003-09-03 00:26:08 +0000 | [diff] [blame] | 291 | assert( funcs.ptr_pthread_cancel ); |
| 292 | return funcs.ptr_pthread_cancel( thread ); |
Vincent Béron | 9a62491 | 2002-05-31 23:06:46 +0000 | [diff] [blame] | 293 | } |
Chris Morgan | 417296c | 2002-04-02 00:49:05 +0000 | [diff] [blame] | 294 | |
| 295 | int pthread_join(pthread_t thread, void **value_ptr) |
| 296 | { |
Alexandre Julliard | 80e34db | 2003-09-03 00:26:08 +0000 | [diff] [blame] | 297 | assert( funcs.ptr_pthread_join ); |
| 298 | return funcs.ptr_pthread_join( thread, value_ptr ); |
Vincent Béron | 9a62491 | 2002-05-31 23:06:46 +0000 | [diff] [blame] | 299 | } |
Chris Morgan | 417296c | 2002-04-02 00:49:05 +0000 | [diff] [blame] | 300 | |
Chris Morgan | 417296c | 2002-04-02 00:49:05 +0000 | [diff] [blame] | 301 | int pthread_detach(pthread_t thread) |
| 302 | { |
Alexandre Julliard | 80e34db | 2003-09-03 00:26:08 +0000 | [diff] [blame] | 303 | assert( funcs.ptr_pthread_detach ); |
| 304 | return funcs.ptr_pthread_detach( thread ); |
Chris Morgan | 417296c | 2002-04-02 00:49:05 +0000 | [diff] [blame] | 305 | } |
| 306 | |
| 307 | /* FIXME: we have no equivalents in win32 for the policys */ |
| 308 | /* so just keep this as a stub */ |
| 309 | int 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 */ |
| 316 | int 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éron | 9a62491 | 2002-05-31 23:06:46 +0000 | [diff] [blame] | 321 | |
Chris Morgan | 417296c | 2002-04-02 00:49:05 +0000 | [diff] [blame] | 322 | /* FIXME: no win32 equivalent for schedule param */ |
| 323 | int 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 Julliard | 80e34db | 2003-09-03 00:26:08 +0000 | [diff] [blame] | 330 | /* FIXME */ |
| 331 | int pthread_attr_setstack(pthread_attr_t *attr, void *addr, size_t size) |
| 332 | { |
| 333 | return 0; /* return success */ |
| 334 | } |
| 335 | |
Ove Kaaven | f19f07d | 2000-04-14 14:47:02 +0000 | [diff] [blame] | 336 | int __pthread_once(pthread_once_t *once_control, void (*init_routine)(void)) |
| 337 | { |
Alexandre Julliard | 80e34db | 2003-09-03 00:26:08 +0000 | [diff] [blame] | 338 | static pthread_once_t the_once = PTHREAD_ONCE_INIT; |
| 339 | long once_now; |
Ove Kaaven | f19f07d | 2000-04-14 14:47:02 +0000 | [diff] [blame] | 340 | |
Alexandre Julliard | 80e34db | 2003-09-03 00:26:08 +0000 | [diff] [blame] | 341 | 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 Kaaven | f19f07d | 2000-04-14 14:47:02 +0000 | [diff] [blame] | 345 | } |
| 346 | strong_alias(__pthread_once, pthread_once); |
| 347 | |
Ove Kaaven | 166209a | 2000-04-23 20:01:45 +0000 | [diff] [blame] | 348 | void __pthread_kill_other_threads_np(void) |
| 349 | { |
Alexandre Julliard | de70b83 | 2001-10-09 21:59:16 +0000 | [diff] [blame] | 350 | /* we don't need to do anything here */ |
Ove Kaaven | 166209a | 2000-04-23 20:01:45 +0000 | [diff] [blame] | 351 | } |
| 352 | strong_alias(__pthread_kill_other_threads_np, pthread_kill_other_threads_np); |
| 353 | |
Alexandre Julliard | 95a4332 | 2000-05-01 16:19:40 +0000 | [diff] [blame] | 354 | /***** atfork *****/ |
| 355 | |
| 356 | #define MAX_ATFORK 8 /* libc doesn't need that many anyway */ |
| 357 | |
Alexandre Julliard | 80e34db | 2003-09-03 00:26:08 +0000 | [diff] [blame] | 358 | static pthread_mutex_t atfork_mutex = PTHREAD_MUTEX_INITIALIZER; |
Alexandre Julliard | 19b6a49 | 2003-08-12 23:50:54 +0000 | [diff] [blame] | 359 | |
Alexandre Julliard | 95a4332 | 2000-05-01 16:19:40 +0000 | [diff] [blame] | 360 | typedef void (*atfork_handler)(); |
| 361 | static atfork_handler atfork_prepare[MAX_ATFORK]; |
| 362 | static atfork_handler atfork_parent[MAX_ATFORK]; |
| 363 | static atfork_handler atfork_child[MAX_ATFORK]; |
| 364 | static int atfork_count; |
| 365 | |
Alexandre Julliard | 80e34db | 2003-09-03 00:26:08 +0000 | [diff] [blame] | 366 | int __pthread_atfork(void (*prepare)(void), void (*parent)(void), void (*child)(void)) |
Ove Kaaven | 166209a | 2000-04-23 20:01:45 +0000 | [diff] [blame] | 367 | { |
Alexandre Julliard | 80e34db | 2003-09-03 00:26:08 +0000 | [diff] [blame] | 368 | pthread_mutex_lock( &atfork_mutex ); |
Alexandre Julliard | 95a4332 | 2000-05-01 16:19:40 +0000 | [diff] [blame] | 369 | 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 Julliard | 80e34db | 2003-09-03 00:26:08 +0000 | [diff] [blame] | 374 | pthread_mutex_unlock( &atfork_mutex ); |
Alexandre Julliard | 95a4332 | 2000-05-01 16:19:40 +0000 | [diff] [blame] | 375 | return 0; |
Ove Kaaven | 166209a | 2000-04-23 20:01:45 +0000 | [diff] [blame] | 376 | } |
| 377 | strong_alias(__pthread_atfork, pthread_atfork); |
| 378 | |
Alexandre Julliard | 26fd740 | 2002-10-22 00:44:24 +0000 | [diff] [blame] | 379 | pid_t __fork(void) |
Ove Kaaven | 1abdb6f | 2000-04-28 14:44:05 +0000 | [diff] [blame] | 380 | { |
Alexandre Julliard | 95a4332 | 2000-05-01 16:19:40 +0000 | [diff] [blame] | 381 | pid_t pid; |
| 382 | int i; |
| 383 | |
Alexandre Julliard | 26fd740 | 2002-10-22 00:44:24 +0000 | [diff] [blame] | 384 | if (!libc_fork) |
| 385 | { |
| 386 | libc_fork = dlsym( RTLD_NEXT, "fork" ); |
| 387 | assert( libc_fork ); |
| 388 | } |
Alexandre Julliard | 80e34db | 2003-09-03 00:26:08 +0000 | [diff] [blame] | 389 | pthread_mutex_lock( &atfork_mutex ); |
Alexandre Julliard | 95a4332 | 2000-05-01 16:19:40 +0000 | [diff] [blame] | 390 | /* prepare handlers are called in reverse insertion order */ |
Bill Medland | 7a60dd0 | 2001-09-26 23:04:40 +0000 | [diff] [blame] | 391 | for (i = atfork_count - 1; i >= 0; i--) if (atfork_prepare[i]) atfork_prepare[i](); |
Alexandre Julliard | 26fd740 | 2002-10-22 00:44:24 +0000 | [diff] [blame] | 392 | if (!(pid = libc_fork())) |
Alexandre Julliard | 95a4332 | 2000-05-01 16:19:40 +0000 | [diff] [blame] | 393 | { |
Alexandre Julliard | 80e34db | 2003-09-03 00:26:08 +0000 | [diff] [blame] | 394 | pthread_mutex_init( &atfork_mutex, NULL ); |
Bill Medland | 7a60dd0 | 2001-09-26 23:04:40 +0000 | [diff] [blame] | 395 | for (i = 0; i < atfork_count; i++) if (atfork_child[i]) atfork_child[i](); |
Alexandre Julliard | 95a4332 | 2000-05-01 16:19:40 +0000 | [diff] [blame] | 396 | } |
| 397 | else |
| 398 | { |
Bill Medland | 7a60dd0 | 2001-09-26 23:04:40 +0000 | [diff] [blame] | 399 | for (i = 0; i < atfork_count; i++) if (atfork_parent[i]) atfork_parent[i](); |
Alexandre Julliard | 80e34db | 2003-09-03 00:26:08 +0000 | [diff] [blame] | 400 | pthread_mutex_unlock( &atfork_mutex ); |
Alexandre Julliard | 95a4332 | 2000-05-01 16:19:40 +0000 | [diff] [blame] | 401 | } |
| 402 | return pid; |
Ove Kaaven | 1abdb6f | 2000-04-28 14:44:05 +0000 | [diff] [blame] | 403 | } |
Alexandre Julliard | 26fd740 | 2002-10-22 00:44:24 +0000 | [diff] [blame] | 404 | strong_alias(__fork, fork); |
Ove Kaaven | 166209a | 2000-04-23 20:01:45 +0000 | [diff] [blame] | 405 | |
| 406 | /***** MUTEXES *****/ |
| 407 | |
Alexandre Julliard | 80e34db | 2003-09-03 00:26:08 +0000 | [diff] [blame] | 408 | int __pthread_mutex_init(pthread_mutex_t *mutex, const pthread_mutexattr_t *mutexattr) |
Ove Kaaven | f19f07d | 2000-04-14 14:47:02 +0000 | [diff] [blame] | 409 | { |
Alexandre Julliard | 80e34db | 2003-09-03 00:26:08 +0000 | [diff] [blame] | 410 | if (!funcs.ptr_pthread_mutex_init) return 0; |
| 411 | return funcs.ptr_pthread_mutex_init( mutex, mutexattr ); |
Ove Kaaven | f19f07d | 2000-04-14 14:47:02 +0000 | [diff] [blame] | 412 | } |
| 413 | strong_alias(__pthread_mutex_init, pthread_mutex_init); |
| 414 | |
Ove Kaaven | f19f07d | 2000-04-14 14:47:02 +0000 | [diff] [blame] | 415 | int __pthread_mutex_lock(pthread_mutex_t *mutex) |
| 416 | { |
Alexandre Julliard | 80e34db | 2003-09-03 00:26:08 +0000 | [diff] [blame] | 417 | if (!funcs.ptr_pthread_mutex_lock) return 0; |
| 418 | return funcs.ptr_pthread_mutex_lock( mutex ); |
Ove Kaaven | f19f07d | 2000-04-14 14:47:02 +0000 | [diff] [blame] | 419 | } |
| 420 | strong_alias(__pthread_mutex_lock, pthread_mutex_lock); |
| 421 | |
| 422 | int __pthread_mutex_trylock(pthread_mutex_t *mutex) |
| 423 | { |
Alexandre Julliard | 80e34db | 2003-09-03 00:26:08 +0000 | [diff] [blame] | 424 | if (!funcs.ptr_pthread_mutex_trylock) return 0; |
| 425 | return funcs.ptr_pthread_mutex_trylock( mutex ); |
Ove Kaaven | f19f07d | 2000-04-14 14:47:02 +0000 | [diff] [blame] | 426 | } |
| 427 | strong_alias(__pthread_mutex_trylock, pthread_mutex_trylock); |
| 428 | |
| 429 | int __pthread_mutex_unlock(pthread_mutex_t *mutex) |
| 430 | { |
Alexandre Julliard | 80e34db | 2003-09-03 00:26:08 +0000 | [diff] [blame] | 431 | if (!funcs.ptr_pthread_mutex_unlock) return 0; |
| 432 | return funcs.ptr_pthread_mutex_unlock( mutex ); |
Ove Kaaven | f19f07d | 2000-04-14 14:47:02 +0000 | [diff] [blame] | 433 | } |
| 434 | strong_alias(__pthread_mutex_unlock, pthread_mutex_unlock); |
| 435 | |
| 436 | int __pthread_mutex_destroy(pthread_mutex_t *mutex) |
| 437 | { |
Alexandre Julliard | 80e34db | 2003-09-03 00:26:08 +0000 | [diff] [blame] | 438 | if (!funcs.ptr_pthread_mutex_destroy) return 0; |
| 439 | return funcs.ptr_pthread_mutex_destroy( mutex ); |
Ove Kaaven | f19f07d | 2000-04-14 14:47:02 +0000 | [diff] [blame] | 440 | } |
| 441 | strong_alias(__pthread_mutex_destroy, pthread_mutex_destroy); |
| 442 | |
Ove Kaaven | 166209a | 2000-04-23 20:01:45 +0000 | [diff] [blame] | 443 | |
| 444 | /***** MUTEX ATTRIBUTES *****/ |
| 445 | /* just dummies, since critical sections are always recursive */ |
Ove Kaaven | f19f07d | 2000-04-14 14:47:02 +0000 | [diff] [blame] | 446 | |
| 447 | int __pthread_mutexattr_init(pthread_mutexattr_t *attr) |
| 448 | { |
| 449 | return 0; |
| 450 | } |
| 451 | strong_alias(__pthread_mutexattr_init, pthread_mutexattr_init); |
| 452 | |
| 453 | int __pthread_mutexattr_destroy(pthread_mutexattr_t *attr) |
| 454 | { |
| 455 | return 0; |
| 456 | } |
| 457 | strong_alias(__pthread_mutexattr_destroy, pthread_mutexattr_destroy); |
| 458 | |
| 459 | int __pthread_mutexattr_setkind_np(pthread_mutexattr_t *attr, int kind) |
| 460 | { |
| 461 | return 0; |
| 462 | } |
| 463 | strong_alias(__pthread_mutexattr_setkind_np, pthread_mutexattr_setkind_np); |
| 464 | |
| 465 | int __pthread_mutexattr_getkind_np(pthread_mutexattr_t *attr, int *kind) |
| 466 | { |
Patrik Stridvall | 6caeb72 | 2002-11-25 21:12:26 +0000 | [diff] [blame] | 467 | *kind = PTHREAD_MUTEX_RECURSIVE; |
Ove Kaaven | f19f07d | 2000-04-14 14:47:02 +0000 | [diff] [blame] | 468 | return 0; |
| 469 | } |
| 470 | strong_alias(__pthread_mutexattr_getkind_np, pthread_mutexattr_getkind_np); |
| 471 | |
| 472 | int __pthread_mutexattr_settype(pthread_mutexattr_t *attr, int kind) |
| 473 | { |
| 474 | return 0; |
| 475 | } |
| 476 | strong_alias(__pthread_mutexattr_settype, pthread_mutexattr_settype); |
| 477 | |
| 478 | int __pthread_mutexattr_gettype(pthread_mutexattr_t *attr, int *kind) |
| 479 | { |
Patrik Stridvall | 6caeb72 | 2002-11-25 21:12:26 +0000 | [diff] [blame] | 480 | *kind = PTHREAD_MUTEX_RECURSIVE; |
Ove Kaaven | f19f07d | 2000-04-14 14:47:02 +0000 | [diff] [blame] | 481 | return 0; |
| 482 | } |
| 483 | strong_alias(__pthread_mutexattr_gettype, pthread_mutexattr_gettype); |
| 484 | |
Ove Kaaven | 166209a | 2000-04-23 20:01:45 +0000 | [diff] [blame] | 485 | |
| 486 | /***** THREAD-SPECIFIC VARIABLES (KEYS) *****/ |
| 487 | |
Ove Kaaven | f19f07d | 2000-04-14 14:47:02 +0000 | [diff] [blame] | 488 | int __pthread_key_create(pthread_key_t *key, void (*destr_function)(void *)) |
| 489 | { |
Alexandre Julliard | 80e34db | 2003-09-03 00:26:08 +0000 | [diff] [blame] | 490 | static long keycnt = FIRST_KEY; |
| 491 | *key = interlocked_xchg_add(&keycnt, 1); |
| 492 | return 0; |
Ove Kaaven | f19f07d | 2000-04-14 14:47:02 +0000 | [diff] [blame] | 493 | } |
| 494 | strong_alias(__pthread_key_create, pthread_key_create); |
| 495 | |
| 496 | int __pthread_key_delete(pthread_key_t key) |
| 497 | { |
| 498 | return 0; |
| 499 | } |
| 500 | strong_alias(__pthread_key_delete, pthread_key_delete); |
| 501 | |
| 502 | int __pthread_setspecific(pthread_key_t key, const void *pointer) |
| 503 | { |
Alexandre Julliard | 97d862c | 2003-08-12 18:59:13 +0000 | [diff] [blame] | 504 | pthread_descr descr = __pthread_thread_self(); |
| 505 | descr->key_data[key] = pointer; |
| 506 | return 0; |
Ove Kaaven | f19f07d | 2000-04-14 14:47:02 +0000 | [diff] [blame] | 507 | } |
| 508 | strong_alias(__pthread_setspecific, pthread_setspecific); |
| 509 | |
| 510 | void *__pthread_getspecific(pthread_key_t key) |
| 511 | { |
Alexandre Julliard | 97d862c | 2003-08-12 18:59:13 +0000 | [diff] [blame] | 512 | pthread_descr descr = __pthread_thread_self(); |
| 513 | return (void *)descr->key_data[key]; |
Ove Kaaven | f19f07d | 2000-04-14 14:47:02 +0000 | [diff] [blame] | 514 | } |
| 515 | strong_alias(__pthread_getspecific, pthread_getspecific); |
| 516 | |
Alexandre Julliard | 97d862c | 2003-08-12 18:59:13 +0000 | [diff] [blame] | 517 | static 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 Julliard | 80e34db | 2003-09-03 00:26:08 +0000 | [diff] [blame] | 523 | int (*__libc_internal_tsd_set)(int, const void *) = pthread_internal_tsd_set; |
Alexandre Julliard | 97d862c | 2003-08-12 18:59:13 +0000 | [diff] [blame] | 524 | |
| 525 | static void *pthread_internal_tsd_get( int key ) |
| 526 | { |
| 527 | pthread_descr descr = __pthread_thread_self(); |
| 528 | return (void *)descr->tsd_data[key]; |
| 529 | } |
Alexandre Julliard | 80e34db | 2003-09-03 00:26:08 +0000 | [diff] [blame] | 530 | void* (*__libc_internal_tsd_get)(int) = pthread_internal_tsd_get; |
Alexandre Julliard | 97d862c | 2003-08-12 18:59:13 +0000 | [diff] [blame] | 531 | |
| 532 | static 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 Julliard | 80e34db | 2003-09-03 00:26:08 +0000 | [diff] [blame] | 537 | void** (*__libc_internal_tsd_address)(int) = pthread_internal_tsd_address; |
Alexandre Julliard | 97d862c | 2003-08-12 18:59:13 +0000 | [diff] [blame] | 538 | |
Ove Kaaven | 166209a | 2000-04-23 20:01:45 +0000 | [diff] [blame] | 539 | /***** "EXCEPTION" FRAMES *****/ |
| 540 | /* not implemented right now */ |
| 541 | |
Ove Kaaven | f19f07d | 2000-04-14 14:47:02 +0000 | [diff] [blame] | 542 | void _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 | |
| 548 | void _pthread_cleanup_pop(struct _pthread_cleanup_buffer *buffer, int execute) |
| 549 | { |
| 550 | if (execute) (*(((wine_cleanup)buffer)->routine))(((wine_cleanup)buffer)->arg); |
| 551 | } |
| 552 | |
| 553 | void _pthread_cleanup_push_defer(struct _pthread_cleanup_buffer *buffer, void (*routine)(void *), void *arg) |
| 554 | { |
| 555 | _pthread_cleanup_push(buffer, routine, arg); |
| 556 | } |
| 557 | |
| 558 | void _pthread_cleanup_pop_restore(struct _pthread_cleanup_buffer *buffer, int execute) |
| 559 | { |
| 560 | _pthread_cleanup_pop(buffer, execute); |
| 561 | } |
| 562 | |
Alexandre Julliard | 97d862c | 2003-08-12 18:59:13 +0000 | [diff] [blame] | 563 | void __pthread_cleanup_upto(jmp_buf target, char *frame) |
| 564 | { |
| 565 | /* FIXME */ |
| 566 | } |
Ove Kaaven | 166209a | 2000-04-23 20:01:45 +0000 | [diff] [blame] | 567 | |
| 568 | /***** CONDITIONS *****/ |
Ove Kaaven | 166209a | 2000-04-23 20:01:45 +0000 | [diff] [blame] | 569 | |
Alexandre Julliard | 97d862c | 2003-08-12 18:59:13 +0000 | [diff] [blame] | 570 | int __pthread_cond_init(pthread_cond_t *cond, const pthread_condattr_t *cond_attr) |
Ove Kaaven | 166209a | 2000-04-23 20:01:45 +0000 | [diff] [blame] | 571 | { |
Alexandre Julliard | 3bff2b3 | 2003-09-23 22:59:44 +0000 | [diff] [blame] | 572 | if (!funcs.ptr_pthread_cond_init) return 0; |
| 573 | return funcs.ptr_pthread_cond_init(cond, cond_attr); |
Ove Kaaven | 166209a | 2000-04-23 20:01:45 +0000 | [diff] [blame] | 574 | } |
Alexandre Julliard | 97d862c | 2003-08-12 18:59:13 +0000 | [diff] [blame] | 575 | strong_alias(__pthread_cond_init, pthread_cond_init); |
Ove Kaaven | 166209a | 2000-04-23 20:01:45 +0000 | [diff] [blame] | 576 | |
Alexandre Julliard | 97d862c | 2003-08-12 18:59:13 +0000 | [diff] [blame] | 577 | int __pthread_cond_destroy(pthread_cond_t *cond) |
Ove Kaaven | 166209a | 2000-04-23 20:01:45 +0000 | [diff] [blame] | 578 | { |
Alexandre Julliard | 3bff2b3 | 2003-09-23 22:59:44 +0000 | [diff] [blame] | 579 | if (!funcs.ptr_pthread_cond_destroy) return 0; |
| 580 | return funcs.ptr_pthread_cond_destroy(cond); |
Ove Kaaven | 166209a | 2000-04-23 20:01:45 +0000 | [diff] [blame] | 581 | } |
Alexandre Julliard | 97d862c | 2003-08-12 18:59:13 +0000 | [diff] [blame] | 582 | strong_alias(__pthread_cond_destroy, pthread_cond_destroy); |
Ove Kaaven | 166209a | 2000-04-23 20:01:45 +0000 | [diff] [blame] | 583 | |
Alexandre Julliard | 97d862c | 2003-08-12 18:59:13 +0000 | [diff] [blame] | 584 | int __pthread_cond_signal(pthread_cond_t *cond) |
Ove Kaaven | 166209a | 2000-04-23 20:01:45 +0000 | [diff] [blame] | 585 | { |
Alexandre Julliard | 3bff2b3 | 2003-09-23 22:59:44 +0000 | [diff] [blame] | 586 | if (!funcs.ptr_pthread_cond_signal) return 0; |
| 587 | return funcs.ptr_pthread_cond_signal(cond); |
Ove Kaaven | 166209a | 2000-04-23 20:01:45 +0000 | [diff] [blame] | 588 | } |
Alexandre Julliard | 97d862c | 2003-08-12 18:59:13 +0000 | [diff] [blame] | 589 | strong_alias(__pthread_cond_signal, pthread_cond_signal); |
Ove Kaaven | 166209a | 2000-04-23 20:01:45 +0000 | [diff] [blame] | 590 | |
Alexandre Julliard | 97d862c | 2003-08-12 18:59:13 +0000 | [diff] [blame] | 591 | int __pthread_cond_broadcast(pthread_cond_t *cond) |
Ove Kaaven | 166209a | 2000-04-23 20:01:45 +0000 | [diff] [blame] | 592 | { |
Alexandre Julliard | 3bff2b3 | 2003-09-23 22:59:44 +0000 | [diff] [blame] | 593 | if (!funcs.ptr_pthread_cond_broadcast) return 0; |
| 594 | return funcs.ptr_pthread_cond_broadcast(cond); |
Ove Kaaven | 166209a | 2000-04-23 20:01:45 +0000 | [diff] [blame] | 595 | } |
Alexandre Julliard | 97d862c | 2003-08-12 18:59:13 +0000 | [diff] [blame] | 596 | strong_alias(__pthread_cond_broadcast, pthread_cond_broadcast); |
Ove Kaaven | 166209a | 2000-04-23 20:01:45 +0000 | [diff] [blame] | 597 | |
Alexandre Julliard | 97d862c | 2003-08-12 18:59:13 +0000 | [diff] [blame] | 598 | int __pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex) |
Ove Kaaven | 166209a | 2000-04-23 20:01:45 +0000 | [diff] [blame] | 599 | { |
Alexandre Julliard | 3bff2b3 | 2003-09-23 22:59:44 +0000 | [diff] [blame] | 600 | if (!funcs.ptr_pthread_cond_wait) return 0; |
| 601 | return funcs.ptr_pthread_cond_wait(cond, mutex); |
Ove Kaaven | 166209a | 2000-04-23 20:01:45 +0000 | [diff] [blame] | 602 | } |
Alexandre Julliard | 97d862c | 2003-08-12 18:59:13 +0000 | [diff] [blame] | 603 | strong_alias(__pthread_cond_wait, pthread_cond_wait); |
Ove Kaaven | 166209a | 2000-04-23 20:01:45 +0000 | [diff] [blame] | 604 | |
Alexandre Julliard | 97d862c | 2003-08-12 18:59:13 +0000 | [diff] [blame] | 605 | int __pthread_cond_timedwait(pthread_cond_t *cond, pthread_mutex_t *mutex, const struct timespec *abstime) |
Ove Kaaven | 166209a | 2000-04-23 20:01:45 +0000 | [diff] [blame] | 606 | { |
Alexandre Julliard | 3bff2b3 | 2003-09-23 22:59:44 +0000 | [diff] [blame] | 607 | if (!funcs.ptr_pthread_cond_timedwait) return 0; |
| 608 | return funcs.ptr_pthread_cond_timedwait(cond, mutex, abstime); |
Ove Kaaven | 166209a | 2000-04-23 20:01:45 +0000 | [diff] [blame] | 609 | } |
Alexandre Julliard | 97d862c | 2003-08-12 18:59:13 +0000 | [diff] [blame] | 610 | strong_alias(__pthread_cond_timedwait, pthread_cond_timedwait); |
Ove Kaaven | 166209a | 2000-04-23 20:01:45 +0000 | [diff] [blame] | 611 | |
| 612 | /**** CONDITION ATTRIBUTES *****/ |
| 613 | /* not implemented right now */ |
| 614 | |
| 615 | int pthread_condattr_init(pthread_condattr_t *attr) |
| 616 | { |
| 617 | return 0; |
| 618 | } |
| 619 | |
| 620 | int pthread_condattr_destroy(pthread_condattr_t *attr) |
| 621 | { |
| 622 | return 0; |
| 623 | } |
| 624 | |
Ove Kaaven | ccc538b | 2000-11-13 04:14:49 +0000 | [diff] [blame] | 625 | /***** READ-WRITE LOCKS *****/ |
Jukka Heinonen | 31b8b64 | 2001-12-11 00:20:18 +0000 | [diff] [blame] | 626 | |
Ove Kaaven | ccc538b | 2000-11-13 04:14:49 +0000 | [diff] [blame] | 627 | int __pthread_rwlock_init(pthread_rwlock_t *rwlock, const pthread_rwlockattr_t *rwlock_attr) |
| 628 | { |
Alexandre Julliard | 80e34db | 2003-09-03 00:26:08 +0000 | [diff] [blame] | 629 | assert( funcs.ptr_pthread_rwlock_init ); |
| 630 | return funcs.ptr_pthread_rwlock_init( rwlock, rwlock_attr ); |
Ove Kaaven | ccc538b | 2000-11-13 04:14:49 +0000 | [diff] [blame] | 631 | } |
| 632 | strong_alias(__pthread_rwlock_init, pthread_rwlock_init); |
| 633 | |
| 634 | int __pthread_rwlock_destroy(pthread_rwlock_t *rwlock) |
| 635 | { |
Alexandre Julliard | 80e34db | 2003-09-03 00:26:08 +0000 | [diff] [blame] | 636 | assert( funcs.ptr_pthread_rwlock_destroy ); |
| 637 | return funcs.ptr_pthread_rwlock_destroy( rwlock ); |
Ove Kaaven | ccc538b | 2000-11-13 04:14:49 +0000 | [diff] [blame] | 638 | } |
| 639 | strong_alias(__pthread_rwlock_destroy, pthread_rwlock_destroy); |
| 640 | |
| 641 | int __pthread_rwlock_rdlock(pthread_rwlock_t *rwlock) |
| 642 | { |
Alexandre Julliard | 80e34db | 2003-09-03 00:26:08 +0000 | [diff] [blame] | 643 | if (!funcs.ptr_pthread_rwlock_rdlock) return 0; |
| 644 | return funcs.ptr_pthread_rwlock_rdlock( rwlock ); |
Ove Kaaven | ccc538b | 2000-11-13 04:14:49 +0000 | [diff] [blame] | 645 | } |
| 646 | strong_alias(__pthread_rwlock_rdlock, pthread_rwlock_rdlock); |
| 647 | |
| 648 | int __pthread_rwlock_tryrdlock(pthread_rwlock_t *rwlock) |
| 649 | { |
Alexandre Julliard | 80e34db | 2003-09-03 00:26:08 +0000 | [diff] [blame] | 650 | assert( funcs.ptr_pthread_rwlock_tryrdlock ); |
| 651 | return funcs.ptr_pthread_rwlock_tryrdlock( rwlock ); |
Ove Kaaven | ccc538b | 2000-11-13 04:14:49 +0000 | [diff] [blame] | 652 | } |
| 653 | strong_alias(__pthread_rwlock_tryrdlock, pthread_rwlock_tryrdlock); |
| 654 | |
| 655 | int __pthread_rwlock_wrlock(pthread_rwlock_t *rwlock) |
| 656 | { |
Alexandre Julliard | 80e34db | 2003-09-03 00:26:08 +0000 | [diff] [blame] | 657 | assert( funcs.ptr_pthread_rwlock_wrlock ); |
| 658 | return funcs.ptr_pthread_rwlock_wrlock( rwlock ); |
Ove Kaaven | ccc538b | 2000-11-13 04:14:49 +0000 | [diff] [blame] | 659 | } |
| 660 | strong_alias(__pthread_rwlock_wrlock, pthread_rwlock_wrlock); |
| 661 | |
| 662 | int __pthread_rwlock_trywrlock(pthread_rwlock_t *rwlock) |
| 663 | { |
Alexandre Julliard | 80e34db | 2003-09-03 00:26:08 +0000 | [diff] [blame] | 664 | assert( funcs.ptr_pthread_rwlock_trywrlock ); |
| 665 | return funcs.ptr_pthread_rwlock_trywrlock( rwlock ); |
Ove Kaaven | ccc538b | 2000-11-13 04:14:49 +0000 | [diff] [blame] | 666 | } |
| 667 | strong_alias(__pthread_rwlock_trywrlock, pthread_rwlock_trywrlock); |
| 668 | |
| 669 | int __pthread_rwlock_unlock(pthread_rwlock_t *rwlock) |
| 670 | { |
Alexandre Julliard | 1d2eb37 | 2003-09-25 20:30:18 +0000 | [diff] [blame] | 671 | if (!funcs.ptr_pthread_rwlock_unlock) return 0; |
Alexandre Julliard | 80e34db | 2003-09-03 00:26:08 +0000 | [diff] [blame] | 672 | return funcs.ptr_pthread_rwlock_unlock( rwlock ); |
Ove Kaaven | ccc538b | 2000-11-13 04:14:49 +0000 | [diff] [blame] | 673 | } |
| 674 | strong_alias(__pthread_rwlock_unlock, pthread_rwlock_unlock); |
| 675 | |
| 676 | /**** READ-WRITE LOCK ATTRIBUTES *****/ |
| 677 | /* not implemented right now */ |
| 678 | |
| 679 | int pthread_rwlockattr_init(pthread_rwlockattr_t *attr) |
| 680 | { |
| 681 | return 0; |
| 682 | } |
| 683 | |
| 684 | int __pthread_rwlockattr_destroy(pthread_rwlockattr_t *attr) |
| 685 | { |
| 686 | return 0; |
| 687 | } |
| 688 | strong_alias(__pthread_rwlockattr_destroy, pthread_rwlockattr_destroy); |
| 689 | |
| 690 | int pthread_rwlockattr_getkind_np(const pthread_rwlockattr_t *attr, int *pref) |
| 691 | { |
| 692 | *pref = 0; |
| 693 | return 0; |
| 694 | } |
| 695 | |
| 696 | int pthread_rwlockattr_setkind_np(pthread_rwlockattr_t *attr, int pref) |
| 697 | { |
| 698 | return 0; |
| 699 | } |
Ove Kaaven | ccc538b | 2000-11-13 04:14:49 +0000 | [diff] [blame] | 700 | |
Ove Kaaven | 166209a | 2000-04-23 20:01:45 +0000 | [diff] [blame] | 701 | /***** MISC *****/ |
| 702 | |
Ove Kaaven | f19f07d | 2000-04-14 14:47:02 +0000 | [diff] [blame] | 703 | pthread_t pthread_self(void) |
| 704 | { |
Alexandre Julliard | 80e34db | 2003-09-03 00:26:08 +0000 | [diff] [blame] | 705 | assert( funcs.ptr_pthread_self ); |
| 706 | return funcs.ptr_pthread_self(); |
Ove Kaaven | f19f07d | 2000-04-14 14:47:02 +0000 | [diff] [blame] | 707 | } |
| 708 | |
| 709 | int pthread_equal(pthread_t thread1, pthread_t thread2) |
| 710 | { |
Alexandre Julliard | 80e34db | 2003-09-03 00:26:08 +0000 | [diff] [blame] | 711 | assert( funcs.ptr_pthread_equal ); |
| 712 | return funcs.ptr_pthread_equal( thread1, thread2 ); |
Ove Kaaven | f19f07d | 2000-04-14 14:47:02 +0000 | [diff] [blame] | 713 | } |
| 714 | |
Alexandre Julliard | 97d862c | 2003-08-12 18:59:13 +0000 | [diff] [blame] | 715 | void __pthread_do_exit(void *retval, char *currentframe) |
Ove Kaaven | 166209a | 2000-04-23 20:01:45 +0000 | [diff] [blame] | 716 | { |
Alexandre Julliard | 80e34db | 2003-09-03 00:26:08 +0000 | [diff] [blame] | 717 | assert( funcs.ptr_pthread_exit ); |
| 718 | return funcs.ptr_pthread_exit( retval, currentframe ); |
Ove Kaaven | 166209a | 2000-04-23 20:01:45 +0000 | [diff] [blame] | 719 | } |
| 720 | |
Alexandre Julliard | 97d862c | 2003-08-12 18:59:13 +0000 | [diff] [blame] | 721 | void __pthread_exit(void *retval) |
| 722 | { |
| 723 | __pthread_do_exit( retval, NULL ); |
| 724 | } |
| 725 | strong_alias(__pthread_exit, pthread_exit); |
| 726 | |
Alexandre Julliard | 80e34db | 2003-09-03 00:26:08 +0000 | [diff] [blame] | 727 | int 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 Kaaven | f19f07d | 2000-04-14 14:47:02 +0000 | [diff] [blame] | 735 | int pthread_setcanceltype(int type, int *oldtype) |
| 736 | { |
Alexandre Julliard | 80e34db | 2003-09-03 00:26:08 +0000 | [diff] [blame] | 737 | pthread_descr descr = __pthread_thread_self(); |
| 738 | if (oldtype) *oldtype = descr->cancel_type; |
| 739 | descr->cancel_type = type; |
| 740 | return 0; |
Ove Kaaven | f19f07d | 2000-04-14 14:47:02 +0000 | [diff] [blame] | 741 | } |
| 742 | |
Ove Kaaven | 166209a | 2000-04-23 20:01:45 +0000 | [diff] [blame] | 743 | /***** ANTI-OVERRIDES *****/ |
| 744 | /* pthreads tries to override these, point them back to libc */ |
| 745 | |
Ove Kaaven | 166209a | 2000-04-23 20:01:45 +0000 | [diff] [blame] | 746 | int sigaction(int signum, const struct sigaction *act, struct sigaction *oldact) |
| 747 | { |
Alexandre Julliard | 26fd740 | 2002-10-22 00:44:24 +0000 | [diff] [blame] | 748 | if (!libc_sigaction) |
| 749 | { |
| 750 | libc_sigaction = dlsym( RTLD_NEXT, "sigaction" ); |
| 751 | assert( libc_sigaction ); |
| 752 | } |
| 753 | return libc_sigaction(signum, act, oldact); |
Ove Kaaven | 166209a | 2000-04-23 20:01:45 +0000 | [diff] [blame] | 754 | } |
Alexandre Julliard | 26fd740 | 2002-10-22 00:44:24 +0000 | [diff] [blame] | 755 | |
Alexandre Julliard | 80e34db | 2003-09-03 00:26:08 +0000 | [diff] [blame] | 756 | void __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 | } |
| 770 | DECL_GLOBAL_CONSTRUCTOR(init) { __pthread_initialize(); } |
| 771 | |
| 772 | static struct pthread_functions libc_pthread_functions = |
Alexandre Julliard | 97d862c | 2003-08-12 18:59:13 +0000 | [diff] [blame] | 773 | { |
| 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 Julliard | 80e34db | 2003-09-03 00:26:08 +0000 | [diff] [blame] | 805 | pthread_setcancelstate, /* ptr_pthread_setcancelstate */ |
Alexandre Julliard | 97d862c | 2003-08-12 18:59:13 +0000 | [diff] [blame] | 806 | 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 Julliard | dbb2b80 | 2003-09-11 01:09:09 +0000 | [diff] [blame] | 815 | NULL, /* ptr_pthread_raise */ |
Alexandre Julliard | e8bd110 | 2003-10-03 03:39:29 +0000 | [diff] [blame] | 816 | __pthread_cond_timedwait, /* ptr___pthread_cond_timedwait */ |
| 817 | _pthread_cleanup_push, /* ptr__pthread_cleanup_push */ |
| 818 | _pthread_cleanup_pop /* ptr__pthread_cleanup_pop */ |
Alexandre Julliard | 97d862c | 2003-08-12 18:59:13 +0000 | [diff] [blame] | 819 | }; |
| 820 | |
Alexandre Julliard | 03d7998 | 2003-08-15 03:55:06 +0000 | [diff] [blame] | 821 | #endif /* __GLIBC__ || __FREEBSD__ */ |
| 822 | |
| 823 | #else /* HAVE_NPTL */ |
Alexandre Julliard | 26fd740 | 2002-10-22 00:44:24 +0000 | [diff] [blame] | 824 | |
Alexandre Julliard | 80e34db | 2003-09-03 00:26:08 +0000 | [diff] [blame] | 825 | void wine_pthread_init_process( const struct wine_pthread_functions *functions ) |
| 826 | { |
| 827 | } |
| 828 | |
| 829 | void wine_pthread_init_thread(void) |
Alexandre Julliard | 26fd740 | 2002-10-22 00:44:24 +0000 | [diff] [blame] | 830 | { |
| 831 | } |
Ove Kaaven | 166209a | 2000-04-23 20:01:45 +0000 | [diff] [blame] | 832 | |
Alexandre Julliard | 03d7998 | 2003-08-15 03:55:06 +0000 | [diff] [blame] | 833 | #endif /* HAVE_NPTL */ |