blob: 4161fe7f2c2c90cf4a1c1b6b5b86b2bd82d905c5 [file] [log] [blame]
sewardje663cb92002-04-12 10:26:32 +00001
sewardj439d45e2002-05-03 20:43:10 +00002/*--------------------------------------------------------------------*/
3/*--- A replacement for the standard libpthread.so. ---*/
4/*--- vg_libpthread.c ---*/
5/*--------------------------------------------------------------------*/
6
7/*
njnc9539842002-10-02 13:26:35 +00008 This file is part of Valgrind, an extensible x86 protected-mode
9 emulator for monitoring program execution on x86-Unixes.
sewardj439d45e2002-05-03 20:43:10 +000010
njn0e1b5142003-04-15 14:58:06 +000011 Copyright (C) 2000-2003 Julian Seward
sewardj439d45e2002-05-03 20:43:10 +000012 jseward@acm.org
13
14 This program is free software; you can redistribute it and/or
15 modify it under the terms of the GNU General Public License as
16 published by the Free Software Foundation; either version 2 of the
17 License, or (at your option) any later version.
18
19 This program is distributed in the hope that it will be useful, but
20 WITHOUT ANY WARRANTY; without even the implied warranty of
21 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
22 General Public License for more details.
23
24 You should have received a copy of the GNU General Public License
25 along with this program; if not, write to the Free Software
26 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
27 02111-1307, USA.
28
njn25e49d8e72002-09-23 09:36:25 +000029 The GNU General Public License is contained in the file COPYING.
sewardj439d45e2002-05-03 20:43:10 +000030*/
31
32/* ALL THIS CODE RUNS ON THE SIMULATED CPU.
33
34 This is a replacement for the standard libpthread.so. It is loaded
sewardje663cb92002-04-12 10:26:32 +000035 as part of the client's image (if required) and directs pthread
36 calls through to Valgrind's request mechanism.
37
38 A couple of caveats.
39
40 1. Since it's a binary-compatible replacement for an existing library,
41 we must take care to used exactly the same data layouts, etc, as
42 the standard pthread.so does.
43
44 2. Since this runs as part of the client, there are no specific
45 restrictions on what headers etc we can include, so long as
46 this libpthread.so does not end up having dependencies on .so's
47 which the real one doesn't.
48
49 Later ... it appears we cannot call file-related stuff in libc here,
50 perhaps fair enough. Be careful what you call from here. Even exit()
51 doesn't work (gives infinite recursion and then stack overflow); hence
52 myexit(). Also fprintf doesn't seem safe.
53*/
54
sewardje12a45f2003-03-15 20:03:33 +000055/* Sidestep the normal check which disallows using valgrind.h
56 directly. */
57#define __VALGRIND_SOMESKIN_H
sewardje663cb92002-04-12 10:26:32 +000058#include "valgrind.h" /* For the request-passing mechanism */
sewardje12a45f2003-03-15 20:03:33 +000059
sewardje663cb92002-04-12 10:26:32 +000060#include "vg_include.h" /* For the VG_USERREQ__* constants */
61
sewardja1ac5cb2002-05-27 13:00:05 +000062#define __USE_UNIX98
63#include <sys/types.h>
64#include <pthread.h>
65#undef __USE_UNIX98
66
sewardje663cb92002-04-12 10:26:32 +000067#include <unistd.h>
68#include <string.h>
sewardj2a1dcce2002-04-22 12:45:25 +000069#include <sys/time.h>
sewardjf912dfc2002-11-13 21:51:10 +000070#include <sys/stat.h>
71#include <sys/poll.h>
sewardj2d94c112002-06-03 01:25:54 +000072#include <stdio.h>
daywalker005e7c12003-10-16 16:14:13 +000073#include <errno.h>
sewardj2d94c112002-06-03 01:25:54 +000074
sewardj705d3cb2002-05-23 13:13:12 +000075
jsgf855d93d2003-10-13 22:26:55 +000076# define strong_alias(name, aliasname) \
77 extern __typeof (name) aliasname __attribute__ ((alias (#name)));
78
79# define weak_alias(name, aliasname) \
80 extern __typeof (name) aliasname __attribute__ ((weak, alias (#name)));
81
82
sewardj705d3cb2002-05-23 13:13:12 +000083/* ---------------------------------------------------------------------
84 Forwardses.
85 ------------------------------------------------------------------ */
86
sewardj11f0bb42003-04-26 20:11:15 +000087#define WEAK __attribute__((weak))
88
sewardjfd7747b2002-12-01 10:25:53 +000089static
90__inline__
91int is_kerror ( int res )
92{
93 if (res >= -4095 && res <= -1)
94 return 1;
95 else
96 return 0;
97}
98
sewardj08c7f012002-10-07 23:56:55 +000099
100#ifdef GLIBC_2_3
101 /* kludge by JRS (not from glibc) ... */
102 typedef void* __locale_t;
103
104 /* Copied from locale/locale.h in glibc-2.2.93 sources */
105 /* This value can be passed to `uselocale' and may be returned by
106 it. Passing this value to any other function has undefined
107 behavior. */
108# define LC_GLOBAL_LOCALE ((__locale_t) -1L)
109 extern __locale_t __uselocale ( __locale_t );
110#endif
111
sewardj00a66b12002-10-12 16:42:35 +0000112static
113void init_libc_tsd_keys ( void );
114
sewardj705d3cb2002-05-23 13:13:12 +0000115
sewardje663cb92002-04-12 10:26:32 +0000116/* ---------------------------------------------------------------------
117 Helpers. We have to be pretty self-sufficient.
118 ------------------------------------------------------------------ */
119
sewardj436e0582002-04-26 14:31:40 +0000120/* Number of times any given error message is printed. */
121#define N_MOANS 3
122
sewardj45b4b372002-04-16 22:50:32 +0000123/* Extract from Valgrind the value of VG_(clo_trace_pthread_level).
124 Returns 0 (none) if not running on Valgrind. */
125static
126int get_pt_trace_level ( void )
127{
128 int res;
129 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
130 VG_USERREQ__GET_PTHREAD_TRACE_LEVEL,
131 0, 0, 0, 0);
132 return res;
133}
134
sewardje663cb92002-04-12 10:26:32 +0000135static
sewardj2d94c112002-06-03 01:25:54 +0000136void my_exit ( int arg )
sewardje663cb92002-04-12 10:26:32 +0000137{
jsgf855d93d2003-10-13 22:26:55 +0000138 VG_(do_syscall)(__NR_exit, arg);
sewardj08c7f012002-10-07 23:56:55 +0000139 /*NOTREACHED*/
sewardje663cb92002-04-12 10:26:32 +0000140}
141
sewardje0cfe2a2002-11-30 14:04:45 +0000142/* Apparently unused.
sewardj08c7f012002-10-07 23:56:55 +0000143static
144void my_write ( int fd, const void *buf, int count )
145{
jsgf855d93d2003-10-13 22:26:55 +0000146 VG_(do_syscall)(__NR_write, fd, (int)buf, count );
sewardj08c7f012002-10-07 23:56:55 +0000147}
sewardje0cfe2a2002-11-30 14:04:45 +0000148*/
sewardje663cb92002-04-12 10:26:32 +0000149
sewardj68b2dd92002-05-10 21:03:56 +0000150/* We need this guy -- it's in valgrind.so. */
151extern void VG_(startup) ( void );
152
153
154/* Just start up Valgrind if it's not already going. VG_(startup)()
155 detects and ignores second and subsequent calls. */
sewardj604ec3c2002-04-18 22:38:41 +0000156static __inline__
sewardje663cb92002-04-12 10:26:32 +0000157void ensure_valgrind ( char* caller )
158{
sewardj68b2dd92002-05-10 21:03:56 +0000159 VG_(startup)();
sewardje663cb92002-04-12 10:26:32 +0000160}
161
sewardjbea1caa2002-05-10 23:20:58 +0000162/* While we're at it ... hook our own startup function into this
163 game. */
164__asm__ (
165 ".section .init\n"
166 "\tcall vgPlain_startup"
167);
168
sewardje663cb92002-04-12 10:26:32 +0000169
170static
sewardj3b5d8862002-04-20 13:53:23 +0000171__attribute__((noreturn))
daywalker3222e0a2003-09-18 01:39:50 +0000172void barf ( const char* str )
sewardje663cb92002-04-12 10:26:32 +0000173{
sewardj69a72a52002-11-03 13:41:41 +0000174 char buf[1000];
daywalker3222e0a2003-09-18 01:39:50 +0000175 strcpy(buf, "\nvalgrind's libpthread.so: ");
sewardje663cb92002-04-12 10:26:32 +0000176 strcat(buf, str);
177 strcat(buf, "\n\n");
njn4c791212003-05-02 17:53:54 +0000178 VALGRIND_NON_SIMD_CALL2(VG_(message), Vg_UserMsg, buf);
sewardj2d94c112002-06-03 01:25:54 +0000179 my_exit(1);
sewardj3b5d8862002-04-20 13:53:23 +0000180 /* We have to persuade gcc into believing this doesn't return. */
181 while (1) { };
sewardje663cb92002-04-12 10:26:32 +0000182}
183
184
sewardj69a72a52002-11-03 13:41:41 +0000185static void cat_n_send ( char* pre, char* msg )
sewardj2a3d28c2002-04-14 13:27:00 +0000186{
sewardj69a72a52002-11-03 13:41:41 +0000187 char buf[1000];
sewardj436e0582002-04-26 14:31:40 +0000188 if (get_pt_trace_level() >= 0) {
sewardj69a72a52002-11-03 13:41:41 +0000189 snprintf(buf, sizeof(buf), "%s%s", pre, msg );
190 buf[sizeof(buf)-1] = '\0';
njn4c791212003-05-02 17:53:54 +0000191 VALGRIND_NON_SIMD_CALL2(VG_(message), Vg_UserMsg, buf);
sewardj45b4b372002-04-16 22:50:32 +0000192 }
sewardj2a3d28c2002-04-14 13:27:00 +0000193}
194
sewardj69a72a52002-11-03 13:41:41 +0000195static void ignored ( char* msg )
196{
197 cat_n_send ( "valgrind's libpthread.so: IGNORED call to: ", msg );
198}
199
200
sewardj30671ff2002-04-21 00:13:57 +0000201static void kludged ( char* msg )
202{
sewardj69a72a52002-11-03 13:41:41 +0000203 cat_n_send ( "valgrind's libpthread.so: KLUDGED call to: ", msg );
sewardj439d45e2002-05-03 20:43:10 +0000204}
205
sewardj69a72a52002-11-03 13:41:41 +0000206
sewardjccef2e62002-05-29 19:26:32 +0000207__attribute__((noreturn))
sewardj3b13f0e2002-04-25 20:17:29 +0000208void vgPlain_unimp ( char* what )
209{
sewardj69a72a52002-11-03 13:41:41 +0000210 cat_n_send (
211 "valgrind's libpthread.so: UNIMPLEMENTED FUNCTION: ", what );
sewardj3b13f0e2002-04-25 20:17:29 +0000212 barf("Please report this bug to me at: jseward@acm.org");
213}
214
sewardje663cb92002-04-12 10:26:32 +0000215
sewardj457cc472002-06-03 23:13:47 +0000216static
daywalker3222e0a2003-09-18 01:39:50 +0000217void my_assert_fail ( const Char* expr, const Char* file, Int line, const Char* fn )
sewardj2d94c112002-06-03 01:25:54 +0000218{
sewardj69a72a52002-11-03 13:41:41 +0000219 char buf[1000];
sewardj2d94c112002-06-03 01:25:54 +0000220 static Bool entered = False;
221 if (entered)
222 my_exit(2);
223 entered = True;
sewardj69a72a52002-11-03 13:41:41 +0000224 sprintf(buf, "\n%s: %s:%d (%s): Assertion `%s' failed.\n",
225 "valgrind", file, line, fn, expr );
226 cat_n_send ( "", buf );
227 sprintf(buf, "Please report this bug to me at: %s\n\n",
228 VG_EMAIL_ADDR);
229 cat_n_send ( "", buf );
sewardj2d94c112002-06-03 01:25:54 +0000230 my_exit(1);
231}
232
233#define MY__STRING(__str) #__str
234
235#define my_assert(expr) \
236 ((void) ((expr) ? 0 : \
237 (my_assert_fail (MY__STRING(expr), \
238 __FILE__, __LINE__, \
239 __PRETTY_FUNCTION__), 0)))
240
sewardj00a66b12002-10-12 16:42:35 +0000241static
242void my_free ( void* ptr )
243{
244 int res;
245 VALGRIND_MAGIC_SEQUENCE(res, (-1) /* default */,
246 VG_USERREQ__FREE, ptr, 0, 0, 0);
247 my_assert(res == 0);
248}
249
250
251static
252void* my_malloc ( int nbytes )
253{
254 void* res;
255 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
256 VG_USERREQ__MALLOC, nbytes, 0, 0, 0);
257 my_assert(res != (void*)0);
258 return res;
259}
260
261
sewardj2d94c112002-06-03 01:25:54 +0000262
sewardje663cb92002-04-12 10:26:32 +0000263/* ---------------------------------------------------------------------
264 Pass pthread_ calls to Valgrind's request mechanism.
265 ------------------------------------------------------------------ */
266
sewardja1ac5cb2002-05-27 13:00:05 +0000267
sewardjf8f819e2002-04-17 23:21:37 +0000268/* ---------------------------------------------------
sewardj4dced352002-06-04 22:54:20 +0000269 Ummm ..
270 ------------------------------------------------ */
271
272static
273void pthread_error ( const char* msg )
274{
275 int res;
276 VALGRIND_MAGIC_SEQUENCE(res, 0,
277 VG_USERREQ__PTHREAD_ERROR,
278 msg, 0, 0, 0);
279}
280
281
282/* ---------------------------------------------------
sewardj00a66b12002-10-12 16:42:35 +0000283 Here so it can be inlined without complaint.
284 ------------------------------------------------ */
285
286__inline__
287pthread_t pthread_self(void)
288{
289 int tid;
290 ensure_valgrind("pthread_self");
291 VALGRIND_MAGIC_SEQUENCE(tid, 0 /* default */,
292 VG_USERREQ__PTHREAD_GET_THREADID,
293 0, 0, 0, 0);
294 if (tid < 1 || tid >= VG_N_THREADS)
295 barf("pthread_self: invalid ThreadId");
296 return tid;
297}
298
299
300/* ---------------------------------------------------
sewardjf8f819e2002-04-17 23:21:37 +0000301 THREAD ATTRIBUTES
302 ------------------------------------------------ */
303
sewardj6af4b5d2002-04-16 04:40:49 +0000304int pthread_attr_init(pthread_attr_t *attr)
305{
sewardj7989d0c2002-05-28 11:00:01 +0000306 /* Just initialise the fields which we might look at. */
307 attr->__detachstate = PTHREAD_CREATE_JOINABLE;
sewardj111b14c2002-10-20 16:22:57 +0000308 /* Linuxthreads sets this field to the value __getpagesize(), so I
309 guess the following is OK. */
310 attr->__guardsize = VKI_BYTES_PER_PAGE; return 0;
sewardj6af4b5d2002-04-16 04:40:49 +0000311}
312
313int pthread_attr_setdetachstate(pthread_attr_t *attr, int detachstate)
314{
sewardj7989d0c2002-05-28 11:00:01 +0000315 if (detachstate != PTHREAD_CREATE_JOINABLE
sewardj4dced352002-06-04 22:54:20 +0000316 && detachstate != PTHREAD_CREATE_DETACHED) {
317 pthread_error("pthread_attr_setdetachstate: "
318 "detachstate is invalid");
sewardj7989d0c2002-05-28 11:00:01 +0000319 return EINVAL;
sewardj4dced352002-06-04 22:54:20 +0000320 }
sewardj7989d0c2002-05-28 11:00:01 +0000321 attr->__detachstate = detachstate;
sewardj6af4b5d2002-04-16 04:40:49 +0000322 return 0;
323}
324
njn25e49d8e72002-09-23 09:36:25 +0000325int pthread_attr_getdetachstate(const pthread_attr_t *attr, int *detachstate)
326{
327 *detachstate = attr->__detachstate;
328 return 0;
329}
330
sewardj30671ff2002-04-21 00:13:57 +0000331int pthread_attr_setinheritsched(pthread_attr_t *attr, int inherit)
332{
sewardj436e0582002-04-26 14:31:40 +0000333 static int moans = N_MOANS;
334 if (moans-- > 0)
335 ignored("pthread_attr_setinheritsched");
sewardj30671ff2002-04-21 00:13:57 +0000336 return 0;
337}
sewardj6af4b5d2002-04-16 04:40:49 +0000338
sewardj11f0bb42003-04-26 20:11:15 +0000339WEAK
sewardj0286dd52002-05-16 20:51:15 +0000340int pthread_attr_setstacksize (pthread_attr_t *__attr,
341 size_t __stacksize)
342{
sewardja18e2102002-05-18 10:43:22 +0000343 size_t limit;
sewardj3d7c8d62002-06-04 20:59:16 +0000344 char buf[1024];
sewardj0286dd52002-05-16 20:51:15 +0000345 ensure_valgrind("pthread_attr_setstacksize");
sewardja18e2102002-05-18 10:43:22 +0000346 limit = VG_PTHREAD_STACK_SIZE - VG_AR_CLIENT_STACKBASE_REDZONE_SZB
347 - 1000; /* paranoia */
348 if (__stacksize < limit)
sewardj0286dd52002-05-16 20:51:15 +0000349 return 0;
sewardj3d7c8d62002-06-04 20:59:16 +0000350 snprintf(buf, sizeof(buf), "pthread_attr_setstacksize: "
351 "requested size %d >= VG_PTHREAD_STACK_SIZE\n "
352 "edit vg_include.h and rebuild.", __stacksize);
353 buf[sizeof(buf)-1] = '\0'; /* Make sure it is zero terminated */
354 barf(buf);
sewardj0286dd52002-05-16 20:51:15 +0000355}
356
357
sewardj30671ff2002-04-21 00:13:57 +0000358/* This is completely bogus. */
359int pthread_attr_getschedparam(const pthread_attr_t *attr,
360 struct sched_param *param)
361{
sewardj436e0582002-04-26 14:31:40 +0000362 static int moans = N_MOANS;
363 if (moans-- > 0)
364 kludged("pthread_attr_getschedparam");
sewardj3e909ce2002-06-03 13:27:15 +0000365# ifdef HAVE_SCHED_PRIORITY
sewardj72d58482002-04-24 02:20:20 +0000366 if (param) param->sched_priority = 0; /* who knows */
367# else
sewardj30671ff2002-04-21 00:13:57 +0000368 if (param) param->__sched_priority = 0; /* who knows */
sewardj72d58482002-04-24 02:20:20 +0000369# endif
sewardj30671ff2002-04-21 00:13:57 +0000370 return 0;
371}
372
373int pthread_attr_setschedparam(pthread_attr_t *attr,
374 const struct sched_param *param)
375{
sewardj436e0582002-04-26 14:31:40 +0000376 static int moans = N_MOANS;
377 if (moans-- > 0)
378 ignored("pthread_attr_setschedparam");
sewardj30671ff2002-04-21 00:13:57 +0000379 return 0;
380}
381
382int pthread_attr_destroy(pthread_attr_t *attr)
383{
sewardj436e0582002-04-26 14:31:40 +0000384 static int moans = N_MOANS;
385 if (moans-- > 0)
386 ignored("pthread_attr_destroy");
sewardj30671ff2002-04-21 00:13:57 +0000387 return 0;
388}
sewardjf8f819e2002-04-17 23:21:37 +0000389
sewardj0d844232002-06-02 09:29:31 +0000390/* These are no-ops, as with LinuxThreads. */
391int pthread_attr_setscope ( pthread_attr_t *attr, int scope )
392{
393 ensure_valgrind("pthread_attr_setscope");
394 if (scope == PTHREAD_SCOPE_SYSTEM)
395 return 0;
sewardj4dced352002-06-04 22:54:20 +0000396 pthread_error("pthread_attr_setscope: "
397 "invalid or unsupported scope");
sewardj0d844232002-06-02 09:29:31 +0000398 if (scope == PTHREAD_SCOPE_PROCESS)
399 return ENOTSUP;
400 return EINVAL;
401}
402
403int pthread_attr_getscope ( const pthread_attr_t *attr, int *scope )
404{
405 ensure_valgrind("pthread_attr_setscope");
406 if (scope)
407 *scope = PTHREAD_SCOPE_SYSTEM;
408 return 0;
409}
410
sewardj64039bb2002-06-03 00:58:18 +0000411
412/* Pretty bogus. Avoid if possible. */
413int pthread_getattr_np (pthread_t thread, pthread_attr_t *attr)
414{
415 int detached;
416 size_t limit;
417 ensure_valgrind("pthread_getattr_np");
418 kludged("pthread_getattr_np");
419 limit = VG_PTHREAD_STACK_SIZE - VG_AR_CLIENT_STACKBASE_REDZONE_SZB
420 - 1000; /* paranoia */
421 attr->__detachstate = PTHREAD_CREATE_JOINABLE;
422 attr->__schedpolicy = SCHED_OTHER;
423 attr->__schedparam.sched_priority = 0;
424 attr->__inheritsched = PTHREAD_EXPLICIT_SCHED;
425 attr->__scope = PTHREAD_SCOPE_SYSTEM;
426 attr->__guardsize = VKI_BYTES_PER_PAGE;
427 attr->__stackaddr = NULL;
428 attr->__stackaddr_set = 0;
429 attr->__stacksize = limit;
430 VALGRIND_MAGIC_SEQUENCE(detached, (-1) /* default */,
431 VG_USERREQ__SET_OR_GET_DETACH,
432 2 /* get */, thread, 0, 0);
sewardj2d94c112002-06-03 01:25:54 +0000433 my_assert(detached == 0 || detached == 1);
sewardj64039bb2002-06-03 00:58:18 +0000434 if (detached)
435 attr->__detachstate = PTHREAD_CREATE_DETACHED;
436 return 0;
437}
438
439
440/* Bogus ... */
sewardj11f0bb42003-04-26 20:11:15 +0000441WEAK
sewardj64039bb2002-06-03 00:58:18 +0000442int pthread_attr_getstackaddr ( const pthread_attr_t * attr,
443 void ** stackaddr )
444{
445 ensure_valgrind("pthread_attr_getstackaddr");
446 kludged("pthread_attr_getstackaddr");
447 if (stackaddr)
448 *stackaddr = NULL;
449 return 0;
450}
451
452/* Not bogus (!) */
sewardj11f0bb42003-04-26 20:11:15 +0000453WEAK
sewardj64039bb2002-06-03 00:58:18 +0000454int pthread_attr_getstacksize ( const pthread_attr_t * _attr,
455 size_t * __stacksize )
456{
457 size_t limit;
458 ensure_valgrind("pthread_attr_getstacksize");
459 limit = VG_PTHREAD_STACK_SIZE - VG_AR_CLIENT_STACKBASE_REDZONE_SZB
460 - 1000; /* paranoia */
461 if (__stacksize)
462 *__stacksize = limit;
463 return 0;
464}
465
sewardja3be12f2002-06-17 12:19:44 +0000466int pthread_attr_setschedpolicy(pthread_attr_t *attr, int policy)
467{
468 if (policy != SCHED_OTHER && policy != SCHED_FIFO && policy != SCHED_RR)
469 return EINVAL;
470 attr->__schedpolicy = policy;
471 return 0;
472}
473
474int pthread_attr_getschedpolicy(const pthread_attr_t *attr, int *policy)
475{
476 *policy = attr->__schedpolicy;
477 return 0;
478}
479
480
sewardj111b14c2002-10-20 16:22:57 +0000481/* This is completely bogus. We reject all attempts to change it from
482 VKI_BYTES_PER_PAGE. I don't have a clue what it's for so it seems
483 safest to be paranoid. */
sewardj11f0bb42003-04-26 20:11:15 +0000484WEAK
sewardj111b14c2002-10-20 16:22:57 +0000485int pthread_attr_setguardsize(pthread_attr_t *attr, size_t guardsize)
486{
487 static int moans = N_MOANS;
488
489 if (guardsize == VKI_BYTES_PER_PAGE)
490 return 0;
491
492 if (moans-- > 0)
493 ignored("pthread_attr_setguardsize: ignoring guardsize != 4096");
494
495 return 0;
496}
497
498/* A straight copy of the LinuxThreads code. */
sewardj11f0bb42003-04-26 20:11:15 +0000499WEAK
sewardj111b14c2002-10-20 16:22:57 +0000500int pthread_attr_getguardsize(const pthread_attr_t *attr, size_t *guardsize)
501{
502 *guardsize = attr->__guardsize;
503 return 0;
504}
505
sewardjab2e1232002-12-26 12:16:11 +0000506/* Again, like LinuxThreads. */
507
508static int concurrency_current_level = 0;
509
sewardj11f0bb42003-04-26 20:11:15 +0000510WEAK
sewardjb34e4db2002-12-08 23:51:32 +0000511int pthread_setconcurrency(int new_level)
512{
513 if (new_level < 0)
514 return EINVAL;
sewardjab2e1232002-12-26 12:16:11 +0000515 else {
516 concurrency_current_level = new_level;
sewardjb34e4db2002-12-08 23:51:32 +0000517 return 0;
sewardjab2e1232002-12-26 12:16:11 +0000518 }
sewardjb34e4db2002-12-08 23:51:32 +0000519}
520
sewardj11f0bb42003-04-26 20:11:15 +0000521WEAK
sewardjab2e1232002-12-26 12:16:11 +0000522int pthread_getconcurrency(void)
523{
524 return concurrency_current_level;
525}
526
527
sewardj111b14c2002-10-20 16:22:57 +0000528
sewardj20917d82002-05-28 01:36:45 +0000529/* ---------------------------------------------------
530 Helper functions for running a thread
531 and for clearing up afterwards.
532 ------------------------------------------------ */
533
534/* All exiting threads eventually pass through here, bearing the
535 return value, or PTHREAD_CANCELED, in ret_val. */
536static
537__attribute__((noreturn))
538void thread_exit_wrapper ( void* ret_val )
539{
sewardj870497a2002-05-29 01:06:47 +0000540 int detached, res;
541 CleanupEntry cu;
542 pthread_key_t key;
sewardj00a66b12002-10-12 16:42:35 +0000543 void** specifics_ptr;
sewardj870497a2002-05-29 01:06:47 +0000544
sewardj20917d82002-05-28 01:36:45 +0000545 /* Run this thread's cleanup handlers. */
sewardj8ad94e12002-05-29 00:10:20 +0000546 while (1) {
547 VALGRIND_MAGIC_SEQUENCE(res, (-1) /* default */,
548 VG_USERREQ__CLEANUP_POP,
549 &cu, 0, 0, 0);
550 if (res == -1) break; /* stack empty */
sewardj2d94c112002-06-03 01:25:54 +0000551 my_assert(res == 0);
sewardj8ad94e12002-05-29 00:10:20 +0000552 if (0) printf("running exit cleanup handler");
553 cu.fn ( cu.arg );
554 }
555
sewardj870497a2002-05-29 01:06:47 +0000556 /* Run this thread's key finalizers. Really this should be run
557 PTHREAD_DESTRUCTOR_ITERATIONS times. */
558 for (key = 0; key < VG_N_THREAD_KEYS; key++) {
559 VALGRIND_MAGIC_SEQUENCE(res, (-2) /* default */,
560 VG_USERREQ__GET_KEY_D_AND_S,
561 key, &cu, 0, 0 );
562 if (res == 0) {
563 /* valid key */
564 if (cu.fn && cu.arg)
565 cu.fn /* destructor for key */
566 ( cu.arg /* specific for key for this thread */ );
567 continue;
568 }
sewardj2d94c112002-06-03 01:25:54 +0000569 my_assert(res == -1);
sewardj870497a2002-05-29 01:06:47 +0000570 }
sewardj20917d82002-05-28 01:36:45 +0000571
sewardj00a66b12002-10-12 16:42:35 +0000572 /* Free up my specifics space, if any. */
573 VALGRIND_MAGIC_SEQUENCE(specifics_ptr, 3 /* default */,
574 VG_USERREQ__PTHREAD_GETSPECIFIC_PTR,
575 pthread_self(), 0, 0, 0);
576 my_assert(specifics_ptr != (void**)3);
577 my_assert(specifics_ptr != (void**)1); /* 1 means invalid thread */
578 if (specifics_ptr != NULL)
579 my_free(specifics_ptr);
580
sewardj20917d82002-05-28 01:36:45 +0000581 /* Decide on my final disposition. */
582 VALGRIND_MAGIC_SEQUENCE(detached, (-1) /* default */,
583 VG_USERREQ__SET_OR_GET_DETACH,
sewardj7989d0c2002-05-28 11:00:01 +0000584 2 /* get */, pthread_self(), 0, 0);
sewardj2d94c112002-06-03 01:25:54 +0000585 my_assert(detached == 0 || detached == 1);
sewardj20917d82002-05-28 01:36:45 +0000586
587 if (detached) {
588 /* Detached; I just quit right now. */
589 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
590 VG_USERREQ__QUIT, 0, 0, 0, 0);
591 } else {
592 /* Not detached; so I wait for a joiner. */
593 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
594 VG_USERREQ__WAIT_JOINER, ret_val, 0, 0, 0);
595 }
596 /* NOTREACHED */
597 barf("thread_exit_wrapper: still alive?!");
598}
599
600
601/* This function is a wrapper function for running a thread. It runs
602 the root function specified in pthread_create, and then, should the
603 root function return a value, it arranges to run the thread's
604 cleanup handlers and exit correctly. */
605
sewardj728a5272002-06-20 10:25:37 +0000606/* Struct used to convey info from pthread_create to thread_wrapper.
607 Must be careful not to pass to the child thread any pointers to
608 objects which might be on the parent's stack. */
sewardj20917d82002-05-28 01:36:45 +0000609typedef
610 struct {
sewardj728a5272002-06-20 10:25:37 +0000611 int attr__detachstate;
sewardj20917d82002-05-28 01:36:45 +0000612 void* (*root_fn) ( void* );
613 void* arg;
614 }
615 NewThreadInfo;
616
617
618/* This is passed to the VG_USERREQ__APPLY_IN_NEW_THREAD and so must
619 not return. Note that this runs in the new thread, not the
620 parent. */
621static
622__attribute__((noreturn))
623void thread_wrapper ( NewThreadInfo* info )
624{
sewardj728a5272002-06-20 10:25:37 +0000625 int attr__detachstate;
sewardj20917d82002-05-28 01:36:45 +0000626 void* (*root_fn) ( void* );
627 void* arg;
628 void* ret_val;
629
sewardj728a5272002-06-20 10:25:37 +0000630 attr__detachstate = info->attr__detachstate;
631 root_fn = info->root_fn;
632 arg = info->arg;
sewardj20917d82002-05-28 01:36:45 +0000633
sewardj20917d82002-05-28 01:36:45 +0000634 /* Free up the arg block that pthread_create malloced. */
sewardj00a66b12002-10-12 16:42:35 +0000635 my_free(info);
sewardj20917d82002-05-28 01:36:45 +0000636
sewardj7989d0c2002-05-28 11:00:01 +0000637 /* Minimally observe the attributes supplied. */
sewardj728a5272002-06-20 10:25:37 +0000638 if (attr__detachstate != PTHREAD_CREATE_DETACHED
639 && attr__detachstate != PTHREAD_CREATE_JOINABLE)
640 pthread_error("thread_wrapper: invalid attr->__detachstate");
641 if (attr__detachstate == PTHREAD_CREATE_DETACHED)
642 pthread_detach(pthread_self());
sewardj7989d0c2002-05-28 11:00:01 +0000643
sewardj00a66b12002-10-12 16:42:35 +0000644# ifdef GLIBC_2_3
645 /* Set this thread's locale to the global (default) locale. A hack
646 in support of glibc-2.3. This does the biz for the all new
647 threads; the root thread is done with a horrible hack in
648 init_libc_tsd_keys() below.
649 */
650 __uselocale(LC_GLOBAL_LOCALE);
651# endif
652
sewardj20917d82002-05-28 01:36:45 +0000653 /* The root function might not return. But if it does we simply
654 move along to thread_exit_wrapper. All other ways out for the
655 thread (cancellation, or calling pthread_exit) lead there
656 too. */
657 ret_val = root_fn(arg);
658 thread_exit_wrapper(ret_val);
659 /* NOTREACHED */
660}
661
662
sewardjf8f819e2002-04-17 23:21:37 +0000663/* ---------------------------------------------------
664 THREADs
665 ------------------------------------------------ */
666
sewardjc91a4ff2003-07-11 00:12:58 +0000667static void __valgrind_pthread_yield ( void )
sewardjff42d1d2002-05-22 13:17:31 +0000668{
669 int res;
670 ensure_valgrind("pthread_yield");
671 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
672 VG_USERREQ__PTHREAD_YIELD, 0, 0, 0, 0);
sewardjc91a4ff2003-07-11 00:12:58 +0000673}
674
675WEAK
676int pthread_yield ( void )
677{
678 __valgrind_pthread_yield();
sewardjff42d1d2002-05-22 13:17:31 +0000679 return 0;
680}
681
682
sewardj6072c362002-04-19 14:40:57 +0000683int pthread_equal(pthread_t thread1, pthread_t thread2)
684{
685 return thread1 == thread2 ? 1 : 0;
686}
687
688
sewardj20917d82002-05-28 01:36:45 +0000689/* Bundle up the args into a malloc'd block and create a new thread
690 consisting of thread_wrapper() applied to said malloc'd block. */
sewardje663cb92002-04-12 10:26:32 +0000691int
sewardj1462c8b2002-07-24 09:41:52 +0000692pthread_create (pthread_t *__restrict __thredd,
sewardje663cb92002-04-12 10:26:32 +0000693 __const pthread_attr_t *__restrict __attr,
694 void *(*__start_routine) (void *),
695 void *__restrict __arg)
696{
sewardj20917d82002-05-28 01:36:45 +0000697 int tid_child;
698 NewThreadInfo* info;
sewardje663cb92002-04-12 10:26:32 +0000699
sewardj20917d82002-05-28 01:36:45 +0000700 ensure_valgrind("pthread_create");
701
sewardj00a66b12002-10-12 16:42:35 +0000702 /* make sure the tsd keys, and hence locale info, are initialised
703 before we get into complications making new threads. */
704 init_libc_tsd_keys();
705
sewardj20917d82002-05-28 01:36:45 +0000706 /* Allocate space for the arg block. thread_wrapper will free
707 it. */
sewardj00a66b12002-10-12 16:42:35 +0000708 info = my_malloc(sizeof(NewThreadInfo));
sewardj2d94c112002-06-03 01:25:54 +0000709 my_assert(info != NULL);
sewardj20917d82002-05-28 01:36:45 +0000710
sewardj728a5272002-06-20 10:25:37 +0000711 if (__attr)
712 info->attr__detachstate = __attr->__detachstate;
713 else
714 info->attr__detachstate = PTHREAD_CREATE_JOINABLE;
715
sewardj20917d82002-05-28 01:36:45 +0000716 info->root_fn = __start_routine;
717 info->arg = __arg;
718 VALGRIND_MAGIC_SEQUENCE(tid_child, VG_INVALID_THREADID /* default */,
719 VG_USERREQ__APPLY_IN_NEW_THREAD,
720 &thread_wrapper, info, 0, 0);
sewardj2d94c112002-06-03 01:25:54 +0000721 my_assert(tid_child != VG_INVALID_THREADID);
sewardj20917d82002-05-28 01:36:45 +0000722
sewardj1462c8b2002-07-24 09:41:52 +0000723 if (__thredd)
724 *__thredd = tid_child;
sewardj20917d82002-05-28 01:36:45 +0000725 return 0; /* success */
726}
sewardje663cb92002-04-12 10:26:32 +0000727
728
729int
730pthread_join (pthread_t __th, void **__thread_return)
731{
732 int res;
733 ensure_valgrind("pthread_join");
734 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
735 VG_USERREQ__PTHREAD_JOIN,
736 __th, __thread_return, 0, 0);
737 return res;
738}
739
740
sewardj3b5d8862002-04-20 13:53:23 +0000741void pthread_exit(void *retval)
742{
sewardj3b5d8862002-04-20 13:53:23 +0000743 ensure_valgrind("pthread_exit");
sewardj20917d82002-05-28 01:36:45 +0000744 /* Simple! */
745 thread_exit_wrapper(retval);
sewardj3b5d8862002-04-20 13:53:23 +0000746}
747
sewardje663cb92002-04-12 10:26:32 +0000748
sewardj853f55d2002-04-26 00:27:53 +0000749int pthread_detach(pthread_t th)
750{
sewardj20917d82002-05-28 01:36:45 +0000751 int res;
752 ensure_valgrind("pthread_detach");
sewardj7989d0c2002-05-28 11:00:01 +0000753 /* First we enquire as to the current detach state. */
754 VALGRIND_MAGIC_SEQUENCE(res, (-2) /* default */,
sewardj20917d82002-05-28 01:36:45 +0000755 VG_USERREQ__SET_OR_GET_DETACH,
sewardj7989d0c2002-05-28 11:00:01 +0000756 2 /* get */, th, 0, 0);
sewardj4dced352002-06-04 22:54:20 +0000757 if (res == -1) {
758 /* not found */
759 pthread_error("pthread_detach: "
760 "invalid target thread");
sewardj7989d0c2002-05-28 11:00:01 +0000761 return ESRCH;
sewardj4dced352002-06-04 22:54:20 +0000762 }
763 if (res == 1) {
764 /* already detached */
765 pthread_error("pthread_detach: "
766 "target thread is already detached");
sewardj7989d0c2002-05-28 11:00:01 +0000767 return EINVAL;
sewardj4dced352002-06-04 22:54:20 +0000768 }
sewardj7989d0c2002-05-28 11:00:01 +0000769 if (res == 0) {
770 VALGRIND_MAGIC_SEQUENCE(res, (-2) /* default */,
771 VG_USERREQ__SET_OR_GET_DETACH,
772 1 /* set */, th, 0, 0);
sewardj2d94c112002-06-03 01:25:54 +0000773 my_assert(res == 0);
sewardj7989d0c2002-05-28 11:00:01 +0000774 return 0;
775 }
776 barf("pthread_detach");
sewardj853f55d2002-04-26 00:27:53 +0000777}
778
779
sewardjf8f819e2002-04-17 23:21:37 +0000780/* ---------------------------------------------------
sewardj8ad94e12002-05-29 00:10:20 +0000781 CLEANUP STACKS
782 ------------------------------------------------ */
783
784void _pthread_cleanup_push (struct _pthread_cleanup_buffer *__buffer,
785 void (*__routine) (void *),
786 void *__arg)
787{
788 int res;
789 CleanupEntry cu;
790 ensure_valgrind("_pthread_cleanup_push");
791 cu.fn = __routine;
792 cu.arg = __arg;
793 VALGRIND_MAGIC_SEQUENCE(res, (-1) /* default */,
794 VG_USERREQ__CLEANUP_PUSH,
795 &cu, 0, 0, 0);
sewardj2d94c112002-06-03 01:25:54 +0000796 my_assert(res == 0);
sewardj8ad94e12002-05-29 00:10:20 +0000797}
798
799
800void _pthread_cleanup_push_defer (struct _pthread_cleanup_buffer *__buffer,
801 void (*__routine) (void *),
802 void *__arg)
803{
804 /* As _pthread_cleanup_push, but first save the thread's original
805 cancellation type in __buffer and set it to Deferred. */
806 int orig_ctype;
807 ensure_valgrind("_pthread_cleanup_push_defer");
808 /* Set to Deferred, and put the old cancellation type in res. */
sewardj2d94c112002-06-03 01:25:54 +0000809 my_assert(-1 != PTHREAD_CANCEL_DEFERRED);
810 my_assert(-1 != PTHREAD_CANCEL_ASYNCHRONOUS);
811 my_assert(sizeof(struct _pthread_cleanup_buffer) >= sizeof(int));
sewardj8ad94e12002-05-29 00:10:20 +0000812 VALGRIND_MAGIC_SEQUENCE(orig_ctype, (-1) /* default */,
813 VG_USERREQ__SET_CANCELTYPE,
814 PTHREAD_CANCEL_DEFERRED, 0, 0, 0);
sewardj2d94c112002-06-03 01:25:54 +0000815 my_assert(orig_ctype != -1);
sewardj8ad94e12002-05-29 00:10:20 +0000816 *((int*)(__buffer)) = orig_ctype;
817 /* Now push the cleanup. */
818 _pthread_cleanup_push(NULL, __routine, __arg);
819}
820
821
822void _pthread_cleanup_pop (struct _pthread_cleanup_buffer *__buffer,
823 int __execute)
824{
825 int res;
826 CleanupEntry cu;
827 ensure_valgrind("_pthread_cleanup_push");
828 cu.fn = cu.arg = NULL; /* paranoia */
829 VALGRIND_MAGIC_SEQUENCE(res, (-1) /* default */,
830 VG_USERREQ__CLEANUP_POP,
831 &cu, 0, 0, 0);
832 if (res == 0) {
833 /* pop succeeded */
834 if (__execute) {
835 cu.fn ( cu.arg );
836 }
837 return;
838 }
839 if (res == -1) {
840 /* stack underflow */
841 return;
842 }
843 barf("_pthread_cleanup_pop");
844}
845
846
847void _pthread_cleanup_pop_restore (struct _pthread_cleanup_buffer *__buffer,
848 int __execute)
849{
850 int orig_ctype, fake_ctype;
851 /* As _pthread_cleanup_pop, but after popping/running the handler,
852 restore the thread's original cancellation type from the first
853 word of __buffer. */
854 _pthread_cleanup_pop(NULL, __execute);
855 orig_ctype = *((int*)(__buffer));
sewardj2d94c112002-06-03 01:25:54 +0000856 my_assert(orig_ctype == PTHREAD_CANCEL_DEFERRED
sewardj8ad94e12002-05-29 00:10:20 +0000857 || orig_ctype == PTHREAD_CANCEL_ASYNCHRONOUS);
sewardj2d94c112002-06-03 01:25:54 +0000858 my_assert(-1 != PTHREAD_CANCEL_DEFERRED);
859 my_assert(-1 != PTHREAD_CANCEL_ASYNCHRONOUS);
860 my_assert(sizeof(struct _pthread_cleanup_buffer) >= sizeof(int));
sewardj8ad94e12002-05-29 00:10:20 +0000861 VALGRIND_MAGIC_SEQUENCE(fake_ctype, (-1) /* default */,
862 VG_USERREQ__SET_CANCELTYPE,
863 orig_ctype, 0, 0, 0);
sewardj2d94c112002-06-03 01:25:54 +0000864 my_assert(fake_ctype == PTHREAD_CANCEL_DEFERRED);
sewardj8ad94e12002-05-29 00:10:20 +0000865}
866
867
868/* ---------------------------------------------------
sewardjf8f819e2002-04-17 23:21:37 +0000869 MUTEX ATTRIBUTES
870 ------------------------------------------------ */
871
sewardj5905fae2002-04-26 13:25:00 +0000872int __pthread_mutexattr_init(pthread_mutexattr_t *attr)
sewardje663cb92002-04-12 10:26:32 +0000873{
sewardjf8f819e2002-04-17 23:21:37 +0000874 attr->__mutexkind = PTHREAD_MUTEX_ERRORCHECK_NP;
sewardj8937c812002-04-12 20:12:20 +0000875 return 0;
sewardje663cb92002-04-12 10:26:32 +0000876}
877
sewardj5905fae2002-04-26 13:25:00 +0000878int __pthread_mutexattr_settype(pthread_mutexattr_t *attr, int type)
sewardjf8f819e2002-04-17 23:21:37 +0000879{
880 switch (type) {
sewardj3b13f0e2002-04-25 20:17:29 +0000881# ifndef GLIBC_2_1
sewardjf8f819e2002-04-17 23:21:37 +0000882 case PTHREAD_MUTEX_TIMED_NP:
sewardj2a1dcce2002-04-22 12:45:25 +0000883 case PTHREAD_MUTEX_ADAPTIVE_NP:
sewardj3b13f0e2002-04-25 20:17:29 +0000884# endif
sewardja1679dd2002-05-10 22:31:40 +0000885# ifdef GLIBC_2_1
sewardj68b2dd92002-05-10 21:03:56 +0000886 case PTHREAD_MUTEX_FAST_NP:
sewardja1679dd2002-05-10 22:31:40 +0000887# endif
sewardjf8f819e2002-04-17 23:21:37 +0000888 case PTHREAD_MUTEX_RECURSIVE_NP:
889 case PTHREAD_MUTEX_ERRORCHECK_NP:
sewardjf8f819e2002-04-17 23:21:37 +0000890 attr->__mutexkind = type;
891 return 0;
892 default:
sewardj4dced352002-06-04 22:54:20 +0000893 pthread_error("pthread_mutexattr_settype: "
894 "invalid type");
sewardjf8f819e2002-04-17 23:21:37 +0000895 return EINVAL;
896 }
897}
898
sewardj5905fae2002-04-26 13:25:00 +0000899int __pthread_mutexattr_destroy(pthread_mutexattr_t *attr)
sewardjf8f819e2002-04-17 23:21:37 +0000900{
901 return 0;
902}
903
sewardjf0995512003-07-06 01:29:49 +0000904int __pthread_mutexattr_setpshared ( pthread_mutexattr_t* attr, int pshared)
sewardj7685cae2003-07-06 01:23:11 +0000905{
906 if (pshared != PTHREAD_PROCESS_PRIVATE && pshared != PTHREAD_PROCESS_SHARED)
907 return EINVAL;
908
909 /* For now it is not possible to shared a conditional variable. */
910 if (pshared != PTHREAD_PROCESS_PRIVATE)
911 return ENOSYS;
912
913 return 0;
914}
915
sewardjf8f819e2002-04-17 23:21:37 +0000916
917/* ---------------------------------------------------
918 MUTEXes
919 ------------------------------------------------ */
920
sewardj5905fae2002-04-26 13:25:00 +0000921int __pthread_mutex_init(pthread_mutex_t *mutex,
922 const pthread_mutexattr_t *mutexattr)
sewardje663cb92002-04-12 10:26:32 +0000923{
sewardj604ec3c2002-04-18 22:38:41 +0000924 mutex->__m_count = 0;
925 mutex->__m_owner = (_pthread_descr)VG_INVALID_THREADID;
926 mutex->__m_kind = PTHREAD_MUTEX_ERRORCHECK_NP;
927 if (mutexattr)
928 mutex->__m_kind = mutexattr->__mutexkind;
929 return 0;
sewardje663cb92002-04-12 10:26:32 +0000930}
931
sewardj439d45e2002-05-03 20:43:10 +0000932
sewardj5905fae2002-04-26 13:25:00 +0000933int __pthread_mutex_lock(pthread_mutex_t *mutex)
sewardje663cb92002-04-12 10:26:32 +0000934{
935 int res;
sewardjd8acdf22002-11-13 21:57:52 +0000936
sewardj439d45e2002-05-03 20:43:10 +0000937 if (RUNNING_ON_VALGRIND) {
sewardje663cb92002-04-12 10:26:32 +0000938 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
939 VG_USERREQ__PTHREAD_MUTEX_LOCK,
940 mutex, 0, 0, 0);
941 return res;
sewardj439d45e2002-05-03 20:43:10 +0000942 } else {
sewardjd8acdf22002-11-13 21:57:52 +0000943 /* Play at locking */
944 if (0)
945 kludged("prehistoric lock");
946 mutex->__m_owner = (_pthread_descr)1;
947 mutex->__m_count = 1;
948 mutex->__m_kind |= VG_PTHREAD_PREHISTORY;
sewardj439d45e2002-05-03 20:43:10 +0000949 return 0; /* success */
sewardje663cb92002-04-12 10:26:32 +0000950 }
951}
952
sewardj439d45e2002-05-03 20:43:10 +0000953
sewardj5905fae2002-04-26 13:25:00 +0000954int __pthread_mutex_trylock(pthread_mutex_t *mutex)
sewardj30671ff2002-04-21 00:13:57 +0000955{
956 int res;
sewardjd8acdf22002-11-13 21:57:52 +0000957
sewardj439d45e2002-05-03 20:43:10 +0000958 if (RUNNING_ON_VALGRIND) {
sewardj30671ff2002-04-21 00:13:57 +0000959 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
960 VG_USERREQ__PTHREAD_MUTEX_TRYLOCK,
961 mutex, 0, 0, 0);
962 return res;
sewardj439d45e2002-05-03 20:43:10 +0000963 } else {
sewardjd8acdf22002-11-13 21:57:52 +0000964 /* Play at locking */
965 if (0)
966 kludged("prehistoric trylock");
967 mutex->__m_owner = (_pthread_descr)1;
968 mutex->__m_count = 1;
969 mutex->__m_kind |= VG_PTHREAD_PREHISTORY;
970 return 0; /* success */
sewardj30671ff2002-04-21 00:13:57 +0000971 }
972}
973
sewardj439d45e2002-05-03 20:43:10 +0000974
sewardj5905fae2002-04-26 13:25:00 +0000975int __pthread_mutex_unlock(pthread_mutex_t *mutex)
sewardje663cb92002-04-12 10:26:32 +0000976{
977 int res;
sewardjd8acdf22002-11-13 21:57:52 +0000978
sewardj439d45e2002-05-03 20:43:10 +0000979 if (RUNNING_ON_VALGRIND) {
sewardje663cb92002-04-12 10:26:32 +0000980 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
981 VG_USERREQ__PTHREAD_MUTEX_UNLOCK,
982 mutex, 0, 0, 0);
983 return res;
sewardj439d45e2002-05-03 20:43:10 +0000984 } else {
sewardjd8acdf22002-11-13 21:57:52 +0000985 /* Play at locking */
986 if (0)
987 kludged("prehistoric unlock");
988 mutex->__m_owner = 0;
989 mutex->__m_count = 0;
990 mutex->__m_kind &= ~VG_PTHREAD_PREHISTORY;
991 return 0; /* success */
sewardje663cb92002-04-12 10:26:32 +0000992 }
993}
994
sewardj439d45e2002-05-03 20:43:10 +0000995
sewardj5905fae2002-04-26 13:25:00 +0000996int __pthread_mutex_destroy(pthread_mutex_t *mutex)
sewardje663cb92002-04-12 10:26:32 +0000997{
sewardj604ec3c2002-04-18 22:38:41 +0000998 /* Valgrind doesn't hold any resources on behalf of the mutex, so no
999 need to involve it. */
sewardj4dced352002-06-04 22:54:20 +00001000 if (mutex->__m_count > 0) {
sewardjd8acdf22002-11-13 21:57:52 +00001001 /* Oh, the horror. glibc's internal use of pthreads "knows"
1002 that destroying a lock does an implicit unlock. Make it
1003 explicit. */
1004 __pthread_mutex_unlock(mutex);
1005 pthread_error("pthread_mutex_destroy: "
1006 "mutex is still in use");
1007 return EBUSY;
sewardj4dced352002-06-04 22:54:20 +00001008 }
1009 mutex->__m_count = 0;
1010 mutex->__m_owner = (_pthread_descr)VG_INVALID_THREADID;
1011 mutex->__m_kind = PTHREAD_MUTEX_ERRORCHECK_NP;
1012 return 0;
sewardje663cb92002-04-12 10:26:32 +00001013}
1014
1015
sewardjf8f819e2002-04-17 23:21:37 +00001016/* ---------------------------------------------------
sewardj6072c362002-04-19 14:40:57 +00001017 CONDITION VARIABLES
1018 ------------------------------------------------ */
1019
1020/* LinuxThreads supports no attributes for conditions. Hence ... */
1021
1022int pthread_condattr_init(pthread_condattr_t *attr)
1023{
1024 return 0;
1025}
1026
sewardj0738a592002-04-20 13:59:33 +00001027int pthread_condattr_destroy(pthread_condattr_t *attr)
1028{
1029 return 0;
1030}
sewardj6072c362002-04-19 14:40:57 +00001031
1032int pthread_cond_init( pthread_cond_t *cond,
1033 const pthread_condattr_t *cond_attr)
1034{
1035 cond->__c_waiting = (_pthread_descr)VG_INVALID_THREADID;
1036 return 0;
1037}
1038
sewardjf854f472002-04-21 12:19:41 +00001039int pthread_cond_destroy(pthread_cond_t *cond)
1040{
1041 /* should check that no threads are waiting on this CV */
sewardj436e0582002-04-26 14:31:40 +00001042 static int moans = N_MOANS;
1043 if (moans-- > 0)
1044 kludged("pthread_cond_destroy");
sewardjf854f472002-04-21 12:19:41 +00001045 return 0;
1046}
sewardj6072c362002-04-19 14:40:57 +00001047
1048/* ---------------------------------------------------
1049 SCHEDULING
1050 ------------------------------------------------ */
1051
1052/* This is completely bogus. */
1053int pthread_getschedparam(pthread_t target_thread,
1054 int *policy,
1055 struct sched_param *param)
1056{
sewardj436e0582002-04-26 14:31:40 +00001057 static int moans = N_MOANS;
1058 if (moans-- > 0)
1059 kludged("pthread_getschedparam");
sewardj6072c362002-04-19 14:40:57 +00001060 if (policy) *policy = SCHED_OTHER;
sewardj3e909ce2002-06-03 13:27:15 +00001061# ifdef HAVE_SCHED_PRIORITY
sewardj2a1dcce2002-04-22 12:45:25 +00001062 if (param) param->sched_priority = 0; /* who knows */
1063# else
sewardj6072c362002-04-19 14:40:57 +00001064 if (param) param->__sched_priority = 0; /* who knows */
sewardj2a1dcce2002-04-22 12:45:25 +00001065# endif
sewardj6072c362002-04-19 14:40:57 +00001066 return 0;
1067}
1068
1069int pthread_setschedparam(pthread_t target_thread,
1070 int policy,
1071 const struct sched_param *param)
1072{
sewardj436e0582002-04-26 14:31:40 +00001073 static int moans = N_MOANS;
1074 if (moans-- > 0)
1075 ignored("pthread_setschedparam");
sewardj6072c362002-04-19 14:40:57 +00001076 return 0;
1077}
1078
sewardj3b5d8862002-04-20 13:53:23 +00001079int pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex)
1080{
1081 int res;
1082 ensure_valgrind("pthread_cond_wait");
1083 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
1084 VG_USERREQ__PTHREAD_COND_WAIT,
1085 cond, mutex, 0, 0);
1086 return res;
1087}
1088
sewardj5f07b662002-04-23 16:52:51 +00001089int pthread_cond_timedwait ( pthread_cond_t *cond,
1090 pthread_mutex_t *mutex,
1091 const struct timespec *abstime )
1092{
1093 int res;
1094 unsigned int ms_now, ms_end;
1095 struct timeval timeval_now;
1096 unsigned long long int ull_ms_now_after_1970;
1097 unsigned long long int ull_ms_end_after_1970;
1098
1099 ensure_valgrind("pthread_cond_timedwait");
1100 VALGRIND_MAGIC_SEQUENCE(ms_now, 0xFFFFFFFF /* default */,
1101 VG_USERREQ__READ_MILLISECOND_TIMER,
1102 0, 0, 0, 0);
sewardj2d94c112002-06-03 01:25:54 +00001103 my_assert(ms_now != 0xFFFFFFFF);
sewardj5f07b662002-04-23 16:52:51 +00001104 res = gettimeofday(&timeval_now, NULL);
sewardj2d94c112002-06-03 01:25:54 +00001105 my_assert(res == 0);
sewardj5f07b662002-04-23 16:52:51 +00001106
1107 ull_ms_now_after_1970
1108 = 1000ULL * ((unsigned long long int)(timeval_now.tv_sec))
1109 + ((unsigned long long int)(timeval_now.tv_usec / 1000000));
1110 ull_ms_end_after_1970
1111 = 1000ULL * ((unsigned long long int)(abstime->tv_sec))
1112 + ((unsigned long long int)(abstime->tv_nsec / 1000000));
sewardjd8e919e2002-05-29 20:13:53 +00001113 if (ull_ms_end_after_1970 < ull_ms_now_after_1970)
1114 ull_ms_end_after_1970 = ull_ms_now_after_1970;
sewardj5f07b662002-04-23 16:52:51 +00001115 ms_end
1116 = ms_now + (unsigned int)(ull_ms_end_after_1970 - ull_ms_now_after_1970);
1117 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
1118 VG_USERREQ__PTHREAD_COND_TIMEDWAIT,
1119 cond, mutex, ms_end, 0);
1120 return res;
1121}
1122
1123
sewardj3b5d8862002-04-20 13:53:23 +00001124int pthread_cond_signal(pthread_cond_t *cond)
1125{
1126 int res;
1127 ensure_valgrind("pthread_cond_signal");
1128 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
1129 VG_USERREQ__PTHREAD_COND_SIGNAL,
1130 cond, 0, 0, 0);
1131 return res;
1132}
1133
1134int pthread_cond_broadcast(pthread_cond_t *cond)
1135{
1136 int res;
1137 ensure_valgrind("pthread_cond_broadcast");
1138 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
1139 VG_USERREQ__PTHREAD_COND_BROADCAST,
1140 cond, 0, 0, 0);
1141 return res;
1142}
1143
sewardj6072c362002-04-19 14:40:57 +00001144
1145/* ---------------------------------------------------
sewardjf8f819e2002-04-17 23:21:37 +00001146 CANCELLATION
1147 ------------------------------------------------ */
1148
sewardj853f55d2002-04-26 00:27:53 +00001149int pthread_setcancelstate(int state, int *oldstate)
1150{
sewardj20917d82002-05-28 01:36:45 +00001151 int res;
1152 ensure_valgrind("pthread_setcancelstate");
1153 if (state != PTHREAD_CANCEL_ENABLE
sewardj4dced352002-06-04 22:54:20 +00001154 && state != PTHREAD_CANCEL_DISABLE) {
1155 pthread_error("pthread_setcancelstate: "
1156 "invalid state");
sewardj20917d82002-05-28 01:36:45 +00001157 return EINVAL;
sewardj4dced352002-06-04 22:54:20 +00001158 }
sewardj2d94c112002-06-03 01:25:54 +00001159 my_assert(-1 != PTHREAD_CANCEL_ENABLE);
1160 my_assert(-1 != PTHREAD_CANCEL_DISABLE);
sewardj20917d82002-05-28 01:36:45 +00001161 VALGRIND_MAGIC_SEQUENCE(res, (-1) /* default */,
1162 VG_USERREQ__SET_CANCELSTATE,
1163 state, 0, 0, 0);
sewardj2d94c112002-06-03 01:25:54 +00001164 my_assert(res != -1);
sewardj20917d82002-05-28 01:36:45 +00001165 if (oldstate)
1166 *oldstate = res;
sewardj853f55d2002-04-26 00:27:53 +00001167 return 0;
1168}
1169
sewardje663cb92002-04-12 10:26:32 +00001170int pthread_setcanceltype(int type, int *oldtype)
1171{
sewardj20917d82002-05-28 01:36:45 +00001172 int res;
1173 ensure_valgrind("pthread_setcanceltype");
1174 if (type != PTHREAD_CANCEL_DEFERRED
sewardj4dced352002-06-04 22:54:20 +00001175 && type != PTHREAD_CANCEL_ASYNCHRONOUS) {
1176 pthread_error("pthread_setcanceltype: "
1177 "invalid type");
sewardj20917d82002-05-28 01:36:45 +00001178 return EINVAL;
sewardj4dced352002-06-04 22:54:20 +00001179 }
sewardj2d94c112002-06-03 01:25:54 +00001180 my_assert(-1 != PTHREAD_CANCEL_DEFERRED);
1181 my_assert(-1 != PTHREAD_CANCEL_ASYNCHRONOUS);
sewardj20917d82002-05-28 01:36:45 +00001182 VALGRIND_MAGIC_SEQUENCE(res, (-1) /* default */,
1183 VG_USERREQ__SET_CANCELTYPE,
1184 type, 0, 0, 0);
sewardj2d94c112002-06-03 01:25:54 +00001185 my_assert(res != -1);
sewardj20917d82002-05-28 01:36:45 +00001186 if (oldtype)
1187 *oldtype = res;
sewardje663cb92002-04-12 10:26:32 +00001188 return 0;
1189}
1190
sewardje663cb92002-04-12 10:26:32 +00001191int pthread_cancel(pthread_t thread)
1192{
1193 int res;
1194 ensure_valgrind("pthread_cancel");
sewardj20917d82002-05-28 01:36:45 +00001195 VALGRIND_MAGIC_SEQUENCE(res, (-1) /* default */,
1196 VG_USERREQ__SET_CANCELPEND,
1197 thread, &thread_exit_wrapper, 0, 0);
sewardj2d94c112002-06-03 01:25:54 +00001198 my_assert(res != -1);
sewardje663cb92002-04-12 10:26:32 +00001199 return res;
1200}
1201
jsgf855d93d2003-10-13 22:26:55 +00001202static
sewardjd140e442002-05-29 01:21:19 +00001203void __my_pthread_testcancel(void)
sewardj853f55d2002-04-26 00:27:53 +00001204{
sewardj20917d82002-05-28 01:36:45 +00001205 int res;
njn25e49d8e72002-09-23 09:36:25 +00001206 ensure_valgrind("__my_pthread_testcancel");
sewardj20917d82002-05-28 01:36:45 +00001207 VALGRIND_MAGIC_SEQUENCE(res, (-1) /* default */,
1208 VG_USERREQ__TESTCANCEL,
1209 0, 0, 0, 0);
sewardj2d94c112002-06-03 01:25:54 +00001210 my_assert(res == 0);
sewardj853f55d2002-04-26 00:27:53 +00001211}
1212
sewardjd140e442002-05-29 01:21:19 +00001213void pthread_testcancel ( void )
1214{
1215 __my_pthread_testcancel();
1216}
1217
sewardj20917d82002-05-28 01:36:45 +00001218
sewardjef037c72002-05-30 00:40:03 +00001219/* Not really sure what this is for. I suspect for doing the POSIX
1220 requirements for fork() and exec(). We do this internally anyway
1221 whenever those syscalls are observed, so this could be superfluous,
1222 but hey ...
1223*/
sewardj853f55d2002-04-26 00:27:53 +00001224void __pthread_kill_other_threads_np ( void )
1225{
sewardjef037c72002-05-30 00:40:03 +00001226 int res;
1227 ensure_valgrind("__pthread_kill_other_threads_np");
1228 VALGRIND_MAGIC_SEQUENCE(res, (-1) /* default */,
1229 VG_USERREQ__NUKE_OTHER_THREADS,
1230 0, 0, 0, 0);
sewardj2d94c112002-06-03 01:25:54 +00001231 my_assert(res == 0);
sewardj853f55d2002-04-26 00:27:53 +00001232}
1233
sewardje663cb92002-04-12 10:26:32 +00001234
sewardjf8f819e2002-04-17 23:21:37 +00001235/* ---------------------------------------------------
sewardjb48e5002002-05-13 00:16:03 +00001236 SIGNALS
1237 ------------------------------------------------ */
1238
1239#include <signal.h>
1240
1241int pthread_sigmask(int how, const sigset_t *newmask,
1242 sigset_t *oldmask)
1243{
1244 int res;
1245
1246 /* A bit subtle, because the scheduler expects newmask and oldmask
1247 to be vki_sigset_t* rather than sigset_t*, and the two are
1248 different. Fortunately the first 64 bits of a sigset_t are
1249 exactly a vki_sigset_t, so we just pass the pointers through
1250 unmodified. Haaaack!
1251
1252 Also mash the how value so that the SIG_ constants from glibc
sewardj018f7622002-05-15 21:13:39 +00001253 constants to VKI_ constants, so that the former do not have to
1254 be included into vg_scheduler.c. */
sewardjb48e5002002-05-13 00:16:03 +00001255
1256 ensure_valgrind("pthread_sigmask");
1257
1258 switch (how) {
sewardj018f7622002-05-15 21:13:39 +00001259 case SIG_SETMASK: how = VKI_SIG_SETMASK; break;
1260 case SIG_BLOCK: how = VKI_SIG_BLOCK; break;
1261 case SIG_UNBLOCK: how = VKI_SIG_UNBLOCK; break;
sewardj4dced352002-06-04 22:54:20 +00001262 default: pthread_error("pthread_sigmask: invalid how");
1263 return EINVAL;
sewardjb48e5002002-05-13 00:16:03 +00001264 }
1265
sewardjb48e5002002-05-13 00:16:03 +00001266 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
1267 VG_USERREQ__PTHREAD_SIGMASK,
1268 how, newmask, oldmask, 0);
1269
1270 /* The scheduler tells us of any memory violations. */
1271 return res == 0 ? 0 : EFAULT;
1272}
1273
sewardjb48e5002002-05-13 00:16:03 +00001274int sigwait ( const sigset_t* set, int* sig )
1275{
1276 int res;
jsgf855d93d2003-10-13 22:26:55 +00001277 vki_ksiginfo_t si;
1278
1279 __my_pthread_testcancel();
1280
sewardjb48e5002002-05-13 00:16:03 +00001281 /* As with pthread_sigmask we deliberately confuse sigset_t with
1282 vki_ksigset_t. */
jsgf855d93d2003-10-13 22:26:55 +00001283 si.si_signo = 0;
1284 res = VG_(ksigtimedwait)((const vki_ksigset_t *)set, &si, NULL);
1285 *sig = si.si_signo;
1286
1287 return 0; /* always returns 0 */
sewardjb48e5002002-05-13 00:16:03 +00001288}
1289
1290
sewardj018f7622002-05-15 21:13:39 +00001291int pthread_kill(pthread_t thread, int signo)
1292{
1293 int res;
1294 ensure_valgrind("pthread_kill");
1295 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
1296 VG_USERREQ__PTHREAD_KILL,
1297 thread, signo, 0, 0);
1298 return res;
1299}
1300
1301
sewardj3665ded2002-05-16 16:57:25 +00001302/* Copied verbatim from Linuxthreads */
1303/* Redefine raise() to send signal to calling thread only,
1304 as per POSIX 1003.1c */
1305int raise (int sig)
1306{
1307 int retcode = pthread_kill(pthread_self(), sig);
sewardj4dced352002-06-04 22:54:20 +00001308 if (retcode == 0) {
sewardj3665ded2002-05-16 16:57:25 +00001309 return 0;
sewardj4dced352002-06-04 22:54:20 +00001310 } else {
sewardj25418ae2003-05-09 23:40:34 +00001311 *(__errno_location()) = retcode;
sewardj3665ded2002-05-16 16:57:25 +00001312 return -1;
1313 }
1314}
1315
1316
sewardj9a2224b2002-06-19 10:17:40 +00001317
sewardjb48e5002002-05-13 00:16:03 +00001318/* ---------------------------------------------------
sewardjf8f819e2002-04-17 23:21:37 +00001319 THREAD-SPECIFICs
1320 ------------------------------------------------ */
sewardj5e5fa512002-04-14 13:13:05 +00001321
sewardj00a66b12002-10-12 16:42:35 +00001322static
1323int key_is_valid (pthread_key_t key)
1324{
1325 int res;
1326 VALGRIND_MAGIC_SEQUENCE(res, 2 /* default */,
1327 VG_USERREQ__PTHREAD_KEY_VALIDATE,
1328 key, 0, 0, 0);
1329 my_assert(res != 2);
1330 return res;
1331}
1332
1333
1334/* Returns NULL if thread is invalid. Otherwise, if the thread
1335 already has a specifics area, return that. Otherwise allocate it
1336 one. */
1337static
1338void** get_or_allocate_specifics_ptr ( pthread_t thread )
1339{
1340 int res, i;
1341 void** specifics_ptr;
1342 ensure_valgrind("get_or_allocate_specifics_ptr");
1343
1344 /* Returns zero if the thread has no specific_ptr. One if thread
1345 is invalid. Otherwise, the specific_ptr value. This is
1346 allocated with my_malloc and so is aligned and cannot be
1347 confused with 1 or 3. */
1348 VALGRIND_MAGIC_SEQUENCE(specifics_ptr, 3 /* default */,
1349 VG_USERREQ__PTHREAD_GETSPECIFIC_PTR,
1350 thread, 0, 0, 0);
1351 my_assert(specifics_ptr != (void**)3);
1352
1353 if (specifics_ptr == (void**)1)
1354 return NULL; /* invalid thread */
1355
1356 if (specifics_ptr != NULL)
1357 return specifics_ptr; /* already has a specifics ptr. */
1358
1359 /* None yet ... allocate a new one. Should never fail. */
1360 specifics_ptr = my_malloc( VG_N_THREAD_KEYS * sizeof(void*) );
1361 my_assert(specifics_ptr != NULL);
1362
1363 VALGRIND_MAGIC_SEQUENCE(res, -1 /* default */,
1364 VG_USERREQ__PTHREAD_SETSPECIFIC_PTR,
1365 specifics_ptr, 0, 0, 0);
1366 my_assert(res == 0);
1367
1368 /* POSIX sez: "Upon thread creation, the value NULL shall be
1369 associated with all defined keys in the new thread." This
1370 allocation is in effect a delayed allocation of the specific
1371 data for a thread, at its first-use. Hence we initialise it
1372 here. */
1373 for (i = 0; i < VG_N_THREAD_KEYS; i++) {
1374 specifics_ptr[i] = NULL;
1375 }
1376
1377 return specifics_ptr;
1378}
1379
1380
sewardj5905fae2002-04-26 13:25:00 +00001381int __pthread_key_create(pthread_key_t *key,
1382 void (*destr_function) (void *))
sewardj5e5fa512002-04-14 13:13:05 +00001383{
sewardj00a66b12002-10-12 16:42:35 +00001384 void** specifics_ptr;
1385 int res, i;
sewardj5f07b662002-04-23 16:52:51 +00001386 ensure_valgrind("pthread_key_create");
sewardj00a66b12002-10-12 16:42:35 +00001387
1388 /* This writes *key if successful. It should never fail. */
1389 VALGRIND_MAGIC_SEQUENCE(res, 1 /* default */,
sewardj5f07b662002-04-23 16:52:51 +00001390 VG_USERREQ__PTHREAD_KEY_CREATE,
1391 key, destr_function, 0, 0);
jsgf855d93d2003-10-13 22:26:55 +00001392
1393 if (res == 0) {
1394 /* POSIX sez: "Upon key creation, the value NULL shall be
1395 associated with the new key in all active threads." */
1396 for (i = 0; i < VG_N_THREADS; i++) {
1397 specifics_ptr = get_or_allocate_specifics_ptr(i);
1398 /* we get NULL if i is an invalid thread. */
1399 if (specifics_ptr != NULL)
1400 specifics_ptr[*key] = NULL;
1401 }
sewardj00a66b12002-10-12 16:42:35 +00001402 }
1403
sewardj5f07b662002-04-23 16:52:51 +00001404 return res;
sewardj5e5fa512002-04-14 13:13:05 +00001405}
1406
1407int pthread_key_delete(pthread_key_t key)
1408{
sewardj00a66b12002-10-12 16:42:35 +00001409 int res;
njndfc9b8c2003-09-29 12:58:37 +00001410 ensure_valgrind("pthread_key_delete");
sewardj00a66b12002-10-12 16:42:35 +00001411 if (!key_is_valid(key))
1412 return EINVAL;
1413 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
1414 VG_USERREQ__PTHREAD_KEY_DELETE,
1415 key, 0, 0, 0);
1416 my_assert(res == 0);
sewardj5e5fa512002-04-14 13:13:05 +00001417 return 0;
1418}
1419
sewardj5905fae2002-04-26 13:25:00 +00001420int __pthread_setspecific(pthread_key_t key, const void *pointer)
sewardj5e5fa512002-04-14 13:13:05 +00001421{
sewardj00a66b12002-10-12 16:42:35 +00001422 void** specifics_ptr;
sewardj5f07b662002-04-23 16:52:51 +00001423 ensure_valgrind("pthread_setspecific");
sewardj00a66b12002-10-12 16:42:35 +00001424
1425 if (!key_is_valid(key))
1426 return EINVAL;
1427
1428 specifics_ptr = get_or_allocate_specifics_ptr(pthread_self());
1429 specifics_ptr[key] = (void*)pointer;
1430 return 0;
sewardj5e5fa512002-04-14 13:13:05 +00001431}
1432
sewardj5905fae2002-04-26 13:25:00 +00001433void * __pthread_getspecific(pthread_key_t key)
sewardj5e5fa512002-04-14 13:13:05 +00001434{
sewardj00a66b12002-10-12 16:42:35 +00001435 void** specifics_ptr;
sewardj5f07b662002-04-23 16:52:51 +00001436 ensure_valgrind("pthread_getspecific");
sewardj00a66b12002-10-12 16:42:35 +00001437
1438 if (!key_is_valid(key))
1439 return NULL;
1440
1441 specifics_ptr = get_or_allocate_specifics_ptr(pthread_self());
1442 return specifics_ptr[key];
1443}
1444
1445
sewardj9aa918d2002-10-20 16:25:55 +00001446#ifdef GLIBC_2_3
sewardj00a66b12002-10-12 16:42:35 +00001447static
1448void ** __pthread_getspecific_addr(pthread_key_t key)
1449{
1450 void** specifics_ptr;
1451 ensure_valgrind("pthread_getspecific_addr");
1452
1453 if (!key_is_valid(key))
1454 return NULL;
1455
1456 specifics_ptr = get_or_allocate_specifics_ptr(pthread_self());
1457 return &(specifics_ptr[key]);
sewardj5e5fa512002-04-14 13:13:05 +00001458}
sewardj9aa918d2002-10-20 16:25:55 +00001459#endif
sewardjf8f819e2002-04-17 23:21:37 +00001460
sewardjc91a4ff2003-07-11 00:12:58 +00001461
sewardjf8f819e2002-04-17 23:21:37 +00001462/* ---------------------------------------------------
sewardj89d3d852002-04-24 19:21:39 +00001463 ONCEry
1464 ------------------------------------------------ */
1465
sewardjc91a4ff2003-07-11 00:12:58 +00001466/* This protects reads and writes of the once_control variable
1467 supplied. It is never held whilst any particular initialiser is
1468 running. */
sewardj89d3d852002-04-24 19:21:39 +00001469static pthread_mutex_t once_masterlock = PTHREAD_MUTEX_INITIALIZER;
1470
sewardjc91a4ff2003-07-11 00:12:58 +00001471/* Initialiser needs to be run. */
1472#define P_ONCE_NOT_DONE ((PTHREAD_ONCE_INIT) + 0)
1473
1474/* Initialiser currently running. */
1475#define P_ONCE_RUNNING ((PTHREAD_ONCE_INIT) + 1)
1476
1477/* Initialiser has completed. */
1478#define P_ONCE_COMPLETED ((PTHREAD_ONCE_INIT) + 2)
sewardj89d3d852002-04-24 19:21:39 +00001479
sewardj5905fae2002-04-26 13:25:00 +00001480int __pthread_once ( pthread_once_t *once_control,
1481 void (*init_routine) (void) )
sewardj89d3d852002-04-24 19:21:39 +00001482{
1483 int res;
sewardjc91a4ff2003-07-11 00:12:58 +00001484 int done;
sewardj89d3d852002-04-24 19:21:39 +00001485
sewardjc91a4ff2003-07-11 00:12:58 +00001486# define TAKE_LOCK \
1487 res = __pthread_mutex_lock(&once_masterlock); \
1488 my_assert(res == 0);
sewardj89d3d852002-04-24 19:21:39 +00001489
sewardjc91a4ff2003-07-11 00:12:58 +00001490# define RELEASE_LOCK \
1491 res = __pthread_mutex_unlock(&once_masterlock); \
1492 my_assert(res == 0);
sewardj89d3d852002-04-24 19:21:39 +00001493
jsgf855d93d2003-10-13 22:26:55 +00001494 void cleanup(void *v) {
1495 TAKE_LOCK;
1496 *once_control = P_ONCE_NOT_DONE;
1497 RELEASE_LOCK;
1498 }
1499
1500 ensure_valgrind("pthread_once");
1501
sewardjc91a4ff2003-07-11 00:12:58 +00001502 /* Grab the lock transiently, so we can safely see what state this
1503 once_control is in. */
1504
1505 TAKE_LOCK;
1506
1507 switch (*once_control) {
1508
1509 case P_ONCE_NOT_DONE:
1510 /* Not started. Change state to indicate running, drop the
1511 lock and run. */
1512 *once_control = P_ONCE_RUNNING;
jsgf855d93d2003-10-13 22:26:55 +00001513 _pthread_cleanup_push(NULL, cleanup, NULL);
sewardjc91a4ff2003-07-11 00:12:58 +00001514 RELEASE_LOCK;
1515 init_routine();
1516 /* re-take the lock, and set state to indicate done. */
1517 TAKE_LOCK;
jsgf855d93d2003-10-13 22:26:55 +00001518 _pthread_cleanup_pop(NULL, False);
sewardjc91a4ff2003-07-11 00:12:58 +00001519 *once_control = P_ONCE_COMPLETED;
1520 RELEASE_LOCK;
1521 break;
1522
1523 case P_ONCE_RUNNING:
1524 /* This is the tricky case. The initialiser is running in
1525 some other thread, but we have to delay this thread till
1526 the other one completes. So we sort-of busy wait. In
1527 fact it makes sense to yield now, because what we want to
1528 happen is for the thread running the initialiser to
1529 complete ASAP. */
1530 RELEASE_LOCK;
1531 done = 0;
1532 while (1) {
1533 /* Let others run for a while. */
1534 __valgrind_pthread_yield();
1535 /* Grab the lock and see if we're done waiting. */
1536 TAKE_LOCK;
1537 if (*once_control == P_ONCE_COMPLETED)
1538 done = 1;
1539 RELEASE_LOCK;
1540 if (done)
1541 break;
1542 }
1543 break;
1544
1545 case P_ONCE_COMPLETED:
1546 default:
1547 /* Easy. It's already done. Just drop the lock. */
1548 RELEASE_LOCK;
1549 break;
sewardj89d3d852002-04-24 19:21:39 +00001550 }
1551
sewardj89d3d852002-04-24 19:21:39 +00001552 return 0;
sewardjc91a4ff2003-07-11 00:12:58 +00001553
1554# undef TAKE_LOCK
1555# undef RELEASE_LOCK
sewardj89d3d852002-04-24 19:21:39 +00001556}
1557
sewardjc91a4ff2003-07-11 00:12:58 +00001558#undef P_ONCE_NOT_DONE
1559#undef P_ONCE_RUNNING
1560#undef P_ONCE_COMPLETED
1561
sewardj89d3d852002-04-24 19:21:39 +00001562
1563/* ---------------------------------------------------
sewardj853f55d2002-04-26 00:27:53 +00001564 MISC
1565 ------------------------------------------------ */
1566
sewardj2cb00342002-06-28 01:46:26 +00001567static pthread_mutex_t pthread_atfork_lock
1568 = PTHREAD_MUTEX_INITIALIZER;
1569
sewardj5905fae2002-04-26 13:25:00 +00001570int __pthread_atfork ( void (*prepare)(void),
1571 void (*parent)(void),
1572 void (*child)(void) )
sewardj853f55d2002-04-26 00:27:53 +00001573{
sewardj2cb00342002-06-28 01:46:26 +00001574 int n, res;
1575 ForkHandlerEntry entry;
1576
1577 ensure_valgrind("pthread_atfork");
1578 __pthread_mutex_lock(&pthread_atfork_lock);
1579
1580 /* Fetch old counter */
1581 VALGRIND_MAGIC_SEQUENCE(n, -2 /* default */,
1582 VG_USERREQ__GET_FHSTACK_USED,
1583 0, 0, 0, 0);
1584 my_assert(n >= 0 && n < VG_N_FORKHANDLERSTACK);
1585 if (n == VG_N_FORKHANDLERSTACK-1)
1586 barf("pthread_atfork: VG_N_FORKHANDLERSTACK is too low; "
1587 "increase and recompile");
1588
1589 /* Add entry */
1590 entry.prepare = *prepare;
1591 entry.parent = *parent;
1592 entry.child = *child;
1593 VALGRIND_MAGIC_SEQUENCE(res, -2 /* default */,
1594 VG_USERREQ__SET_FHSTACK_ENTRY,
1595 n, &entry, 0, 0);
1596 my_assert(res == 0);
1597
1598 /* Bump counter */
1599 VALGRIND_MAGIC_SEQUENCE(res, -2 /* default */,
1600 VG_USERREQ__SET_FHSTACK_USED,
1601 n+1, 0, 0, 0);
1602 my_assert(res == 0);
1603
1604 __pthread_mutex_unlock(&pthread_atfork_lock);
1605 return 0;
sewardj853f55d2002-04-26 00:27:53 +00001606}
1607
1608
sewardj9df78832003-05-04 12:35:54 +00001609#ifdef GLIBC_2_3
1610/* This seems to be a hook which appeared in glibc-2.3.2. */
1611int __register_atfork ( void (*prepare)(void),
1612 void (*parent)(void),
1613 void (*child)(void) )
1614{
1615 return __pthread_atfork(prepare,parent,child);
1616}
1617#endif
1618
sewardj11f0bb42003-04-26 20:11:15 +00001619WEAK
sewardjbb990782002-05-08 02:01:14 +00001620void __pthread_initialize ( void )
1621{
sewardjbea1caa2002-05-10 23:20:58 +00001622 ensure_valgrind("__pthread_initialize");
sewardjbb990782002-05-08 02:01:14 +00001623}
1624
1625
sewardj853f55d2002-04-26 00:27:53 +00001626/* ---------------------------------------------------
sewardj3b13f0e2002-04-25 20:17:29 +00001627 LIBRARY-PRIVATE THREAD SPECIFIC STATE
sewardjf8f819e2002-04-17 23:21:37 +00001628 ------------------------------------------------ */
1629
sewardj3b13f0e2002-04-25 20:17:29 +00001630#include <resolv.h>
1631static int thread_specific_errno[VG_N_THREADS];
1632static int thread_specific_h_errno[VG_N_THREADS];
1633static struct __res_state
1634 thread_specific_res_state[VG_N_THREADS];
sewardjf8f819e2002-04-17 23:21:37 +00001635
sewardj25418ae2003-05-09 23:40:34 +00001636#undef errno
1637extern int errno;
sewardj3b13f0e2002-04-25 20:17:29 +00001638int* __errno_location ( void )
sewardjf8f819e2002-04-17 23:21:37 +00001639{
1640 int tid;
sewardj3b13f0e2002-04-25 20:17:29 +00001641 /* ensure_valgrind("__errno_location"); */
1642 VALGRIND_MAGIC_SEQUENCE(tid, 1 /* default */,
sewardjf8f819e2002-04-17 23:21:37 +00001643 VG_USERREQ__PTHREAD_GET_THREADID,
1644 0, 0, 0, 0);
sewardj3b13f0e2002-04-25 20:17:29 +00001645 /* 'cos I'm paranoid ... */
sewardj439d45e2002-05-03 20:43:10 +00001646 if (tid < 1 || tid >= VG_N_THREADS)
sewardj3b13f0e2002-04-25 20:17:29 +00001647 barf("__errno_location: invalid ThreadId");
sewardj25418ae2003-05-09 23:40:34 +00001648 if (tid == 1)
1649 return &errno;
sewardj3b13f0e2002-04-25 20:17:29 +00001650 return & thread_specific_errno[tid];
1651}
1652
sewardj25418ae2003-05-09 23:40:34 +00001653#undef h_errno
1654extern int h_errno;
sewardj3b13f0e2002-04-25 20:17:29 +00001655int* __h_errno_location ( void )
1656{
1657 int tid;
1658 /* ensure_valgrind("__h_errno_location"); */
1659 VALGRIND_MAGIC_SEQUENCE(tid, 1 /* default */,
1660 VG_USERREQ__PTHREAD_GET_THREADID,
1661 0, 0, 0, 0);
1662 /* 'cos I'm paranoid ... */
sewardj439d45e2002-05-03 20:43:10 +00001663 if (tid < 1 || tid >= VG_N_THREADS)
sewardj3b13f0e2002-04-25 20:17:29 +00001664 barf("__h_errno_location: invalid ThreadId");
sewardj25418ae2003-05-09 23:40:34 +00001665 if (tid == 1)
1666 return &h_errno;
sewardj3b13f0e2002-04-25 20:17:29 +00001667 return & thread_specific_h_errno[tid];
1668}
1669
sewardjb0ff1032002-08-06 09:02:53 +00001670
1671#undef _res
1672extern struct __res_state _res;
sewardj3b13f0e2002-04-25 20:17:29 +00001673struct __res_state* __res_state ( void )
1674{
1675 int tid;
1676 /* ensure_valgrind("__res_state"); */
1677 VALGRIND_MAGIC_SEQUENCE(tid, 1 /* default */,
1678 VG_USERREQ__PTHREAD_GET_THREADID,
1679 0, 0, 0, 0);
1680 /* 'cos I'm paranoid ... */
sewardj439d45e2002-05-03 20:43:10 +00001681 if (tid < 1 || tid >= VG_N_THREADS)
sewardj3b13f0e2002-04-25 20:17:29 +00001682 barf("__res_state: invalid ThreadId");
sewardjb0ff1032002-08-06 09:02:53 +00001683 if (tid == 1)
1684 return & _res;
sewardj3b13f0e2002-04-25 20:17:29 +00001685 return & thread_specific_res_state[tid];
sewardjf8f819e2002-04-17 23:21:37 +00001686}
1687
1688
sewardj5716dbb2002-04-26 03:28:18 +00001689/* ---------------------------------------------------
1690 LIBC-PRIVATE SPECIFIC DATA
1691 ------------------------------------------------ */
1692
1693/* Relies on assumption that initial private data is NULL. This
1694 should be fixed somehow. */
1695
njn25e49d8e72002-09-23 09:36:25 +00001696/* The allowable keys (indices) (all 3 of them).
sewardj5716dbb2002-04-26 03:28:18 +00001697 From sysdeps/pthread/bits/libc-tsd.h
1698*/
sewardjcb7f08a2002-10-02 09:41:49 +00001699/* as per glibc anoncvs HEAD of 20021001. */
sewardj5716dbb2002-04-26 03:28:18 +00001700enum __libc_tsd_key_t { _LIBC_TSD_KEY_MALLOC = 0,
1701 _LIBC_TSD_KEY_DL_ERROR,
njn25e49d8e72002-09-23 09:36:25 +00001702 _LIBC_TSD_KEY_RPC_VARS,
sewardjcb7f08a2002-10-02 09:41:49 +00001703 _LIBC_TSD_KEY_LOCALE,
1704 _LIBC_TSD_KEY_CTYPE_B,
1705 _LIBC_TSD_KEY_CTYPE_TOLOWER,
1706 _LIBC_TSD_KEY_CTYPE_TOUPPER,
sewardj5716dbb2002-04-26 03:28:18 +00001707 _LIBC_TSD_KEY_N };
1708
1709/* Auto-initialising subsystem. libc_specifics_inited is set
1710 after initialisation. libc_specifics_inited_mx guards it. */
1711static int libc_specifics_inited = 0;
1712static pthread_mutex_t libc_specifics_inited_mx = PTHREAD_MUTEX_INITIALIZER;
1713
sewardj00a66b12002-10-12 16:42:35 +00001714
sewardj5716dbb2002-04-26 03:28:18 +00001715/* These are the keys we must initialise the first time. */
sewardjcb7f08a2002-10-02 09:41:49 +00001716static pthread_key_t libc_specifics_keys[_LIBC_TSD_KEY_N];
sewardj5716dbb2002-04-26 03:28:18 +00001717
sewardj00a66b12002-10-12 16:42:35 +00001718
sewardjcb7f08a2002-10-02 09:41:49 +00001719/* Initialise the keys, if they are not already initialised. */
sewardj5716dbb2002-04-26 03:28:18 +00001720static
1721void init_libc_tsd_keys ( void )
1722{
1723 int res, i;
1724 pthread_key_t k;
1725
sewardj08c7f012002-10-07 23:56:55 +00001726 /* Don't fall into deadlock if we get called again whilst we still
1727 hold the lock, via the __uselocale() call herein. */
1728 if (libc_specifics_inited != 0)
1729 return;
1730
1731 /* Take the lock. */
sewardj00a66b12002-10-12 16:42:35 +00001732 res = __pthread_mutex_lock(&libc_specifics_inited_mx);
sewardj5716dbb2002-04-26 03:28:18 +00001733 if (res != 0) barf("init_libc_tsd_keys: lock");
1734
sewardj08c7f012002-10-07 23:56:55 +00001735 /* Now test again, to be sure there is no mistake. */
1736 if (libc_specifics_inited != 0) {
sewardj00a66b12002-10-12 16:42:35 +00001737 res = __pthread_mutex_unlock(&libc_specifics_inited_mx);
sewardj08c7f012002-10-07 23:56:55 +00001738 if (res != 0) barf("init_libc_tsd_keys: unlock(1)");
1739 return;
sewardj5716dbb2002-04-26 03:28:18 +00001740 }
1741
sewardj08c7f012002-10-07 23:56:55 +00001742 /* Actually do the initialisation. */
1743 /* printf("INIT libc specifics\n"); */
1744 for (i = 0; i < _LIBC_TSD_KEY_N; i++) {
sewardj00a66b12002-10-12 16:42:35 +00001745 res = __pthread_key_create(&k, NULL);
sewardj08c7f012002-10-07 23:56:55 +00001746 if (res != 0) barf("init_libc_tsd_keys: create");
1747 libc_specifics_keys[i] = k;
1748 }
1749
1750 /* Signify init done. */
1751 libc_specifics_inited = 1;
1752
1753# ifdef GLIBC_2_3
1754 /* Set the initialising thread's locale to the global (default)
sewardj00a66b12002-10-12 16:42:35 +00001755 locale. A hack in support of glibc-2.3. This does the biz for
1756 the root thread. For all other threads we run this in
1757 thread_wrapper(), which does the real work of
1758 pthread_create(). */
1759 /* assert that we are the root thread. I don't know if this is
1760 really a valid assertion to make; if it breaks I'll reconsider
1761 it. */
1762 my_assert(pthread_self() == 1);
sewardj08c7f012002-10-07 23:56:55 +00001763 __uselocale(LC_GLOBAL_LOCALE);
1764# endif
1765
1766 /* Unlock and return. */
sewardj00a66b12002-10-12 16:42:35 +00001767 res = __pthread_mutex_unlock(&libc_specifics_inited_mx);
sewardj5716dbb2002-04-26 03:28:18 +00001768 if (res != 0) barf("init_libc_tsd_keys: unlock");
1769}
1770
1771
1772static int
1773libc_internal_tsd_set ( enum __libc_tsd_key_t key,
1774 const void * pointer )
1775{
sewardjcb7f08a2002-10-02 09:41:49 +00001776 int res;
sewardj5716dbb2002-04-26 03:28:18 +00001777 /* printf("SET SET SET key %d ptr %p\n", key, pointer); */
sewardjcb7f08a2002-10-02 09:41:49 +00001778 if (key < _LIBC_TSD_KEY_MALLOC || key >= _LIBC_TSD_KEY_N)
sewardj5716dbb2002-04-26 03:28:18 +00001779 barf("libc_internal_tsd_set: invalid key");
1780 init_libc_tsd_keys();
sewardj00a66b12002-10-12 16:42:35 +00001781 res = __pthread_setspecific(libc_specifics_keys[key], pointer);
sewardj5716dbb2002-04-26 03:28:18 +00001782 if (res != 0) barf("libc_internal_tsd_set: setspecific failed");
1783 return 0;
1784}
1785
1786static void *
1787libc_internal_tsd_get ( enum __libc_tsd_key_t key )
1788{
sewardjcb7f08a2002-10-02 09:41:49 +00001789 void* v;
sewardj5716dbb2002-04-26 03:28:18 +00001790 /* printf("GET GET GET key %d\n", key); */
sewardjcb7f08a2002-10-02 09:41:49 +00001791 if (key < _LIBC_TSD_KEY_MALLOC || key >= _LIBC_TSD_KEY_N)
sewardj5716dbb2002-04-26 03:28:18 +00001792 barf("libc_internal_tsd_get: invalid key");
1793 init_libc_tsd_keys();
sewardj00a66b12002-10-12 16:42:35 +00001794 v = __pthread_getspecific(libc_specifics_keys[key]);
sewardj5716dbb2002-04-26 03:28:18 +00001795 /* if (v == NULL) barf("libc_internal_tsd_set: getspecific failed"); */
1796 return v;
1797}
1798
1799
sewardj70adeb22002-04-27 01:35:38 +00001800int (*__libc_internal_tsd_set)
1801 (enum __libc_tsd_key_t key, const void * pointer)
1802 = libc_internal_tsd_set;
sewardj5716dbb2002-04-26 03:28:18 +00001803
sewardj70adeb22002-04-27 01:35:38 +00001804void* (*__libc_internal_tsd_get)
1805 (enum __libc_tsd_key_t key)
1806 = libc_internal_tsd_get;
sewardj5716dbb2002-04-26 03:28:18 +00001807
1808
sewardj00a66b12002-10-12 16:42:35 +00001809#ifdef GLIBC_2_3
1810/* This one was first spotted be me in the glibc-2.2.93 sources. */
1811static void**
1812libc_internal_tsd_address ( enum __libc_tsd_key_t key )
1813{
1814 void** v;
1815 /* printf("ADDR ADDR ADDR key %d\n", key); */
1816 if (key < _LIBC_TSD_KEY_MALLOC || key >= _LIBC_TSD_KEY_N)
1817 barf("libc_internal_tsd_address: invalid key");
1818 init_libc_tsd_keys();
1819 v = __pthread_getspecific_addr(libc_specifics_keys[key]);
1820 return v;
1821}
1822
1823void ** (*__libc_internal_tsd_address)
1824 (enum __libc_tsd_key_t key)
1825 = libc_internal_tsd_address;
1826#endif
1827
1828
sewardje663cb92002-04-12 10:26:32 +00001829/* ---------------------------------------------------------------------
1830 These are here (I think) because they are deemed cancellation
1831 points by POSIX. For the moment we'll simply pass the call along
1832 to the corresponding thread-unaware (?) libc routine.
1833 ------------------------------------------------------------------ */
1834
sewardjd529a442002-05-04 19:49:21 +00001835#ifdef GLIBC_2_1
1836extern
1837int __sigaction
1838 (int signum,
1839 const struct sigaction *act,
1840 struct sigaction *oldact);
1841#else
sewardje663cb92002-04-12 10:26:32 +00001842extern
1843int __libc_sigaction
1844 (int signum,
1845 const struct sigaction *act,
1846 struct sigaction *oldact);
sewardjd529a442002-05-04 19:49:21 +00001847#endif
sewardje663cb92002-04-12 10:26:32 +00001848int sigaction(int signum,
1849 const struct sigaction *act,
1850 struct sigaction *oldact)
1851{
sewardjd140e442002-05-29 01:21:19 +00001852 __my_pthread_testcancel();
sewardj2a1dcce2002-04-22 12:45:25 +00001853# ifdef GLIBC_2_1
1854 return __sigaction(signum, act, oldact);
1855# else
sewardj45b4b372002-04-16 22:50:32 +00001856 return __libc_sigaction(signum, act, oldact);
sewardj2a1dcce2002-04-22 12:45:25 +00001857# endif
sewardje663cb92002-04-12 10:26:32 +00001858}
1859
jsgf855d93d2003-10-13 22:26:55 +00001860extern
1861int __libc_accept(int fd, struct sockaddr *addr, socklen_t *len);
1862
1863WEAK int __accept(int fd, struct sockaddr *addr, socklen_t *len)
1864{
1865 __my_pthread_testcancel();
1866 return __libc_accept(fd, addr, len);
1867}
1868strong_alias(__accept, accept);
sewardje663cb92002-04-12 10:26:32 +00001869
1870extern
1871int __libc_connect(int sockfd,
1872 const struct sockaddr *serv_addr,
1873 socklen_t addrlen);
sewardj11f0bb42003-04-26 20:11:15 +00001874WEAK
sewardje663cb92002-04-12 10:26:32 +00001875int connect(int sockfd,
1876 const struct sockaddr *serv_addr,
1877 socklen_t addrlen)
1878{
sewardjd140e442002-05-29 01:21:19 +00001879 __my_pthread_testcancel();
sewardj45b4b372002-04-16 22:50:32 +00001880 return __libc_connect(sockfd, serv_addr, addrlen);
sewardje663cb92002-04-12 10:26:32 +00001881}
1882
1883
1884extern
1885int __libc_fcntl(int fd, int cmd, long arg);
sewardj11f0bb42003-04-26 20:11:15 +00001886WEAK
sewardje663cb92002-04-12 10:26:32 +00001887int fcntl(int fd, int cmd, long arg)
1888{
sewardjd140e442002-05-29 01:21:19 +00001889 __my_pthread_testcancel();
sewardj45b4b372002-04-16 22:50:32 +00001890 return __libc_fcntl(fd, cmd, arg);
sewardje663cb92002-04-12 10:26:32 +00001891}
1892
1893
1894extern
1895ssize_t __libc_write(int fd, const void *buf, size_t count);
sewardj11f0bb42003-04-26 20:11:15 +00001896WEAK
sewardje663cb92002-04-12 10:26:32 +00001897ssize_t write(int fd, const void *buf, size_t count)
1898{
sewardjd140e442002-05-29 01:21:19 +00001899 __my_pthread_testcancel();
sewardj45b4b372002-04-16 22:50:32 +00001900 return __libc_write(fd, buf, count);
sewardje663cb92002-04-12 10:26:32 +00001901}
1902
1903
1904extern
1905ssize_t __libc_read(int fd, void *buf, size_t count);
sewardj11f0bb42003-04-26 20:11:15 +00001906WEAK
sewardje663cb92002-04-12 10:26:32 +00001907ssize_t read(int fd, void *buf, size_t count)
1908{
sewardjd140e442002-05-29 01:21:19 +00001909 __my_pthread_testcancel();
sewardj45b4b372002-04-16 22:50:32 +00001910 return __libc_read(fd, buf, count);
sewardje663cb92002-04-12 10:26:32 +00001911}
1912
sewardjf912dfc2002-11-13 21:51:10 +00001913extern
1914int __libc_open64(const char *pathname, int flags, mode_t mode);
sewardj11f0bb42003-04-26 20:11:15 +00001915/* WEAK */
sewardjf912dfc2002-11-13 21:51:10 +00001916int open64(const char *pathname, int flags, mode_t mode)
1917{
jsgf855d93d2003-10-13 22:26:55 +00001918 return __libc_open64(pathname, flags, mode);
sewardjf912dfc2002-11-13 21:51:10 +00001919}
sewardje663cb92002-04-12 10:26:32 +00001920
1921extern
sewardj853f55d2002-04-26 00:27:53 +00001922int __libc_open(const char *pathname, int flags, mode_t mode);
sewardj11f0bb42003-04-26 20:11:15 +00001923/* WEAK */
sewardj853f55d2002-04-26 00:27:53 +00001924int open(const char *pathname, int flags, mode_t mode)
sewardje663cb92002-04-12 10:26:32 +00001925{
jsgf855d93d2003-10-13 22:26:55 +00001926 return __libc_open(pathname, flags, mode);
sewardje663cb92002-04-12 10:26:32 +00001927}
1928
sewardje663cb92002-04-12 10:26:32 +00001929extern
1930int __libc_close(int fd);
sewardj11f0bb42003-04-26 20:11:15 +00001931WEAK
sewardje663cb92002-04-12 10:26:32 +00001932int close(int fd)
1933{
sewardjd140e442002-05-29 01:21:19 +00001934 __my_pthread_testcancel();
sewardj45b4b372002-04-16 22:50:32 +00001935 return __libc_close(fd);
sewardje663cb92002-04-12 10:26:32 +00001936}
1937
1938
sewardje663cb92002-04-12 10:26:32 +00001939extern
sewardje663cb92002-04-12 10:26:32 +00001940pid_t __libc_waitpid(pid_t pid, int *status, int options);
sewardj11f0bb42003-04-26 20:11:15 +00001941WEAK
sewardje663cb92002-04-12 10:26:32 +00001942pid_t waitpid(pid_t pid, int *status, int options)
1943{
sewardjd140e442002-05-29 01:21:19 +00001944 __my_pthread_testcancel();
sewardj45b4b372002-04-16 22:50:32 +00001945 return __libc_waitpid(pid, status, options);
sewardje663cb92002-04-12 10:26:32 +00001946}
1947
1948
1949extern
1950int __libc_nanosleep(const struct timespec *req, struct timespec *rem);
sewardj11f0bb42003-04-26 20:11:15 +00001951WEAK
jsgf855d93d2003-10-13 22:26:55 +00001952int __nanosleep(const struct timespec *req, struct timespec *rem)
sewardje663cb92002-04-12 10:26:32 +00001953{
sewardjd140e442002-05-29 01:21:19 +00001954 __my_pthread_testcancel();
sewardje663cb92002-04-12 10:26:32 +00001955 return __libc_nanosleep(req, rem);
1956}
1957
jsgf855d93d2003-10-13 22:26:55 +00001958extern
1959int __libc_pause(void);
1960WEAK
1961int __pause(void)
1962{
1963 __my_pthread_testcancel();
1964 return __libc_pause();
1965}
1966
sewardjbe32e452002-04-24 20:29:58 +00001967
sewardje663cb92002-04-12 10:26:32 +00001968extern
1969int __libc_fsync(int fd);
sewardj11f0bb42003-04-26 20:11:15 +00001970WEAK
sewardje663cb92002-04-12 10:26:32 +00001971int fsync(int fd)
1972{
sewardjd140e442002-05-29 01:21:19 +00001973 __my_pthread_testcancel();
sewardj45b4b372002-04-16 22:50:32 +00001974 return __libc_fsync(fd);
sewardje663cb92002-04-12 10:26:32 +00001975}
1976
sewardjbe32e452002-04-24 20:29:58 +00001977
sewardj70c75362002-04-13 04:18:32 +00001978extern
1979off_t __libc_lseek(int fildes, off_t offset, int whence);
sewardj11f0bb42003-04-26 20:11:15 +00001980WEAK
sewardj70c75362002-04-13 04:18:32 +00001981off_t lseek(int fildes, off_t offset, int whence)
1982{
sewardjd140e442002-05-29 01:21:19 +00001983 __my_pthread_testcancel();
sewardj45b4b372002-04-16 22:50:32 +00001984 return __libc_lseek(fildes, offset, whence);
sewardj70c75362002-04-13 04:18:32 +00001985}
1986
sewardjbe32e452002-04-24 20:29:58 +00001987
1988extern
1989__off64_t __libc_lseek64(int fildes, __off64_t offset, int whence);
sewardj11f0bb42003-04-26 20:11:15 +00001990WEAK
sewardjbe32e452002-04-24 20:29:58 +00001991__off64_t lseek64(int fildes, __off64_t offset, int whence)
1992{
sewardjd140e442002-05-29 01:21:19 +00001993 __my_pthread_testcancel();
sewardjbe32e452002-04-24 20:29:58 +00001994 return __libc_lseek64(fildes, offset, whence);
1995}
1996
1997
sewardj726c4122002-05-16 23:39:10 +00001998extern
1999ssize_t __libc_pread64 (int __fd, void *__buf, size_t __nbytes,
2000 __off64_t __offset);
2001ssize_t __pread64 (int __fd, void *__buf, size_t __nbytes,
2002 __off64_t __offset)
2003{
sewardjd140e442002-05-29 01:21:19 +00002004 __my_pthread_testcancel();
sewardj726c4122002-05-16 23:39:10 +00002005 return __libc_pread64(__fd, __buf, __nbytes, __offset);
2006}
2007
2008
sewardja18e2102002-05-18 10:43:22 +00002009extern
2010ssize_t __libc_pwrite64 (int __fd, const void *__buf, size_t __nbytes,
2011 __off64_t __offset);
2012ssize_t __pwrite64 (int __fd, const void *__buf, size_t __nbytes,
2013 __off64_t __offset)
2014{
sewardjd140e442002-05-29 01:21:19 +00002015 __my_pthread_testcancel();
sewardja18e2102002-05-18 10:43:22 +00002016 return __libc_pwrite64(__fd, __buf, __nbytes, __offset);
2017}
2018
sewardj726c4122002-05-16 23:39:10 +00002019
sewardj39b93b12002-05-18 10:56:27 +00002020extern
2021ssize_t __libc_pwrite(int fd, const void *buf, size_t count, off_t offset);
sewardj11f0bb42003-04-26 20:11:15 +00002022WEAK
sewardj39b93b12002-05-18 10:56:27 +00002023ssize_t pwrite(int fd, const void *buf, size_t count, off_t offset)
2024{
sewardjd140e442002-05-29 01:21:19 +00002025 __my_pthread_testcancel();
sewardj39b93b12002-05-18 10:56:27 +00002026 return __libc_pwrite(fd, buf, count, offset);
2027}
2028
2029
2030extern
2031ssize_t __libc_pread(int fd, void *buf, size_t count, off_t offset);
sewardj11f0bb42003-04-26 20:11:15 +00002032WEAK
sewardj39b93b12002-05-18 10:56:27 +00002033ssize_t pread(int fd, void *buf, size_t count, off_t offset)
2034{
sewardjd140e442002-05-29 01:21:19 +00002035 __my_pthread_testcancel();
sewardj39b93b12002-05-18 10:56:27 +00002036 return __libc_pread(fd, buf, count, offset);
2037}
2038
jsgf855d93d2003-10-13 22:26:55 +00002039extern
2040int __libc_recv(int s, void *msg, size_t len, int flags);
2041WEAK
2042int recv(int s, void *msg, size_t len, int flags)
sewardj6af4b5d2002-04-16 04:40:49 +00002043{
jsgf855d93d2003-10-13 22:26:55 +00002044 __my_pthread_testcancel();
2045 return __libc_recv(s, msg, len, flags);
sewardj6af4b5d2002-04-16 04:40:49 +00002046}
2047
2048extern
2049int __libc_send(int s, const void *msg, size_t len, int flags);
sewardj11f0bb42003-04-26 20:11:15 +00002050WEAK
sewardj6af4b5d2002-04-16 04:40:49 +00002051int send(int s, const void *msg, size_t len, int flags)
2052{
sewardjd140e442002-05-29 01:21:19 +00002053 __my_pthread_testcancel();
sewardj6af4b5d2002-04-16 04:40:49 +00002054 return __libc_send(s, msg, len, flags);
2055}
2056
sewardjbe32e452002-04-24 20:29:58 +00002057
sewardj3665ded2002-05-16 16:57:25 +00002058extern
2059int __libc_sendmsg(int s, const struct msghdr *msg, int flags);
sewardj11f0bb42003-04-26 20:11:15 +00002060WEAK
sewardj3665ded2002-05-16 16:57:25 +00002061int sendmsg(int s, const struct msghdr *msg, int flags)
2062{
sewardjd140e442002-05-29 01:21:19 +00002063 __my_pthread_testcancel();
sewardj3665ded2002-05-16 16:57:25 +00002064 return __libc_sendmsg(s, msg, flags);
2065}
2066
2067
sewardj796d6a22002-04-24 02:28:34 +00002068extern
sewardj59da27a2002-06-06 08:33:54 +00002069int __libc_recvmsg(int s, struct msghdr *msg, int flags);
sewardj11f0bb42003-04-26 20:11:15 +00002070WEAK
sewardj59da27a2002-06-06 08:33:54 +00002071int recvmsg(int s, struct msghdr *msg, int flags)
2072{
2073 __my_pthread_testcancel();
2074 return __libc_recvmsg(s, msg, flags);
2075}
2076
2077
2078extern
sewardj436e0582002-04-26 14:31:40 +00002079int __libc_recvfrom(int s, void *buf, size_t len, int flags,
2080 struct sockaddr *from, socklen_t *fromlen);
sewardj11f0bb42003-04-26 20:11:15 +00002081WEAK
sewardj436e0582002-04-26 14:31:40 +00002082int recvfrom(int s, void *buf, size_t len, int flags,
2083 struct sockaddr *from, socklen_t *fromlen)
2084{
sewardjd140e442002-05-29 01:21:19 +00002085 __my_pthread_testcancel();
sewardj436e0582002-04-26 14:31:40 +00002086 return __libc_recvfrom(s, buf, len, flags, from, fromlen);
2087}
2088
2089
2090extern
sewardj796d6a22002-04-24 02:28:34 +00002091int __libc_sendto(int s, const void *msg, size_t len, int flags,
2092 const struct sockaddr *to, socklen_t tolen);
sewardj11f0bb42003-04-26 20:11:15 +00002093WEAK
sewardj796d6a22002-04-24 02:28:34 +00002094int sendto(int s, const void *msg, size_t len, int flags,
2095 const struct sockaddr *to, socklen_t tolen)
2096{
sewardjd140e442002-05-29 01:21:19 +00002097 __my_pthread_testcancel();
sewardj796d6a22002-04-24 02:28:34 +00002098 return __libc_sendto(s, msg, len, flags, to, tolen);
2099}
2100
sewardjbe32e452002-04-24 20:29:58 +00002101
sewardj369b1702002-04-24 13:28:15 +00002102extern
2103int __libc_system(const char* str);
sewardj11f0bb42003-04-26 20:11:15 +00002104WEAK
sewardj369b1702002-04-24 13:28:15 +00002105int system(const char* str)
2106{
sewardjd140e442002-05-29 01:21:19 +00002107 __my_pthread_testcancel();
sewardj369b1702002-04-24 13:28:15 +00002108 return __libc_system(str);
2109}
2110
sewardjbe32e452002-04-24 20:29:58 +00002111
sewardjab0b1c32002-04-24 19:26:47 +00002112extern
2113pid_t __libc_wait(int *status);
sewardj11f0bb42003-04-26 20:11:15 +00002114WEAK
sewardjab0b1c32002-04-24 19:26:47 +00002115pid_t wait(int *status)
2116{
sewardjd140e442002-05-29 01:21:19 +00002117 __my_pthread_testcancel();
sewardjab0b1c32002-04-24 19:26:47 +00002118 return __libc_wait(status);
2119}
2120
sewardj45b4b372002-04-16 22:50:32 +00002121
sewardj67f1d582002-05-24 02:11:32 +00002122extern
2123int __libc_msync(const void *start, size_t length, int flags);
sewardj11f0bb42003-04-26 20:11:15 +00002124WEAK
sewardj67f1d582002-05-24 02:11:32 +00002125int msync(const void *start, size_t length, int flags)
2126{
sewardjd140e442002-05-29 01:21:19 +00002127 __my_pthread_testcancel();
sewardj67f1d582002-05-24 02:11:32 +00002128 return __libc_msync(start, length, flags);
2129}
2130
jsgf855d93d2003-10-13 22:26:55 +00002131strong_alias(close, __close)
2132strong_alias(fcntl, __fcntl)
2133strong_alias(lseek, __lseek)
2134strong_alias(open, __open)
2135strong_alias(open64, __open64)
2136strong_alias(read, __read)
2137strong_alias(wait, __wait)
2138strong_alias(write, __write)
2139strong_alias(connect, __connect)
2140strong_alias(send, __send)
2141
2142weak_alias (__pread64, pread64)
2143weak_alias (__pwrite64, pwrite64)
2144weak_alias(__nanosleep, nanosleep)
2145weak_alias(__pause, pause)
2146
2147
2148extern
2149void __libc_longjmp(jmp_buf env, int val) __attribute((noreturn));
2150/* not weak: WEAK */
2151void longjmp(jmp_buf env, int val)
2152{
2153 __libc_longjmp(env, val);
2154}
2155
2156
2157extern void __libc_siglongjmp (sigjmp_buf env, int val)
2158 __attribute__ ((noreturn));
2159void siglongjmp(sigjmp_buf env, int val)
2160{
2161 kludged("siglongjmp (cleanup handlers are ignored)");
2162 __libc_siglongjmp(env, val);
2163}
2164
sewardj5905fae2002-04-26 13:25:00 +00002165
sewardj2cb00342002-06-28 01:46:26 +00002166/*--- fork and its helper ---*/
2167
2168static
2169void run_fork_handlers ( int what )
2170{
2171 ForkHandlerEntry entry;
2172 int n_h, n_handlers, i, res;
2173
2174 my_assert(what == 0 || what == 1 || what == 2);
2175
2176 /* Fetch old counter */
2177 VALGRIND_MAGIC_SEQUENCE(n_handlers, -2 /* default */,
2178 VG_USERREQ__GET_FHSTACK_USED,
2179 0, 0, 0, 0);
2180 my_assert(n_handlers >= 0 && n_handlers < VG_N_FORKHANDLERSTACK);
2181
2182 /* Prepare handlers (what == 0) are called in opposite order of
2183 calls to pthread_atfork. Parent and child handlers are called
2184 in the same order as calls to pthread_atfork. */
2185 if (what == 0)
2186 n_h = n_handlers - 1;
2187 else
2188 n_h = 0;
2189
2190 for (i = 0; i < n_handlers; i++) {
2191 VALGRIND_MAGIC_SEQUENCE(res, -2 /* default */,
2192 VG_USERREQ__GET_FHSTACK_ENTRY,
2193 n_h, &entry, 0, 0);
2194 my_assert(res == 0);
2195 switch (what) {
2196 case 0: if (entry.prepare) entry.prepare();
2197 n_h--; break;
2198 case 1: if (entry.parent) entry.parent();
2199 n_h++; break;
2200 case 2: if (entry.child) entry.child();
2201 n_h++; break;
2202 default: barf("run_fork_handlers: invalid what");
2203 }
2204 }
2205
2206 if (what != 0 /* prepare */) {
2207 /* Empty out the stack. */
2208 VALGRIND_MAGIC_SEQUENCE(res, -2 /* default */,
2209 VG_USERREQ__SET_FHSTACK_USED,
2210 0, 0, 0, 0);
2211 my_assert(res == 0);
2212 }
2213}
2214
2215extern
2216pid_t __libc_fork(void);
2217pid_t __fork(void)
2218{
2219 pid_t pid;
2220 __my_pthread_testcancel();
2221 __pthread_mutex_lock(&pthread_atfork_lock);
2222
2223 run_fork_handlers(0 /* prepare */);
2224 pid = __libc_fork();
2225 if (pid == 0) {
2226 /* I am the child */
2227 run_fork_handlers(2 /* child */);
sewardjd8acdf22002-11-13 21:57:52 +00002228 __pthread_mutex_unlock(&pthread_atfork_lock);
sewardj2cb00342002-06-28 01:46:26 +00002229 __pthread_mutex_init(&pthread_atfork_lock, NULL);
2230 } else {
2231 /* I am the parent */
2232 run_fork_handlers(1 /* parent */);
2233 __pthread_mutex_unlock(&pthread_atfork_lock);
2234 }
2235 return pid;
2236}
2237
2238
njn25e49d8e72002-09-23 09:36:25 +00002239pid_t __vfork(void)
2240{
2241 return __fork();
2242}
sewardj2cb00342002-06-28 01:46:26 +00002243
2244
sewardj08a4c3f2002-04-13 03:45:44 +00002245
sewardj3b13f0e2002-04-25 20:17:29 +00002246/* ---------------------------------------------------------------------
sewardj8f253ff2002-05-19 00:13:34 +00002247 Hacky implementation of semaphores.
2248 ------------------------------------------------------------------ */
2249
2250#include <semaphore.h>
2251
2252/* This is a terrible way to do the remapping. Plan is to import an
2253 AVL tree at some point. */
sewardj8f253ff2002-05-19 00:13:34 +00002254
2255typedef
2256 struct {
2257 pthread_mutex_t se_mx;
2258 pthread_cond_t se_cv;
2259 int count;
2260 }
2261 vg_sem_t;
2262
2263static pthread_mutex_t se_remap_mx = PTHREAD_MUTEX_INITIALIZER;
2264
2265static int se_remap_used = 0;
2266static sem_t* se_remap_orig[VG_N_SEMAPHORES];
2267static vg_sem_t se_remap_new[VG_N_SEMAPHORES];
2268
2269static vg_sem_t* se_remap ( sem_t* orig )
2270{
2271 int res, i;
2272 res = __pthread_mutex_lock(&se_remap_mx);
sewardj2d94c112002-06-03 01:25:54 +00002273 my_assert(res == 0);
sewardj8f253ff2002-05-19 00:13:34 +00002274
2275 for (i = 0; i < se_remap_used; i++) {
2276 if (se_remap_orig[i] == orig)
2277 break;
2278 }
2279 if (i == se_remap_used) {
2280 if (se_remap_used == VG_N_SEMAPHORES) {
2281 res = pthread_mutex_unlock(&se_remap_mx);
sewardj2d94c112002-06-03 01:25:54 +00002282 my_assert(res == 0);
sewardja1ac5cb2002-05-27 13:00:05 +00002283 barf("VG_N_SEMAPHORES is too low. Increase and recompile.");
sewardj8f253ff2002-05-19 00:13:34 +00002284 }
2285 se_remap_used++;
2286 se_remap_orig[i] = orig;
2287 /* printf("allocated semaphore %d\n", i); */
2288 }
2289 res = __pthread_mutex_unlock(&se_remap_mx);
sewardj2d94c112002-06-03 01:25:54 +00002290 my_assert(res == 0);
sewardj8f253ff2002-05-19 00:13:34 +00002291 return &se_remap_new[i];
2292}
2293
2294
2295int sem_init(sem_t *sem, int pshared, unsigned int value)
2296{
2297 int res;
2298 vg_sem_t* vg_sem;
2299 ensure_valgrind("sem_init");
2300 if (pshared != 0) {
sewardj4dced352002-06-04 22:54:20 +00002301 pthread_error("sem_init: unsupported pshared value");
sewardj25418ae2003-05-09 23:40:34 +00002302 *(__errno_location()) = ENOSYS;
sewardj8f253ff2002-05-19 00:13:34 +00002303 return -1;
2304 }
2305 vg_sem = se_remap(sem);
2306 res = pthread_mutex_init(&vg_sem->se_mx, NULL);
sewardj2d94c112002-06-03 01:25:54 +00002307 my_assert(res == 0);
sewardj8f253ff2002-05-19 00:13:34 +00002308 res = pthread_cond_init(&vg_sem->se_cv, NULL);
sewardj2d94c112002-06-03 01:25:54 +00002309 my_assert(res == 0);
sewardj8f253ff2002-05-19 00:13:34 +00002310 vg_sem->count = value;
2311 return 0;
2312}
2313
2314
2315int sem_wait ( sem_t* sem )
2316{
2317 int res;
2318 vg_sem_t* vg_sem;
2319 ensure_valgrind("sem_wait");
2320 vg_sem = se_remap(sem);
2321 res = __pthread_mutex_lock(&vg_sem->se_mx);
sewardj2d94c112002-06-03 01:25:54 +00002322 my_assert(res == 0);
sewardj8f253ff2002-05-19 00:13:34 +00002323 while (vg_sem->count == 0) {
2324 res = pthread_cond_wait(&vg_sem->se_cv, &vg_sem->se_mx);
sewardj2d94c112002-06-03 01:25:54 +00002325 my_assert(res == 0);
sewardj8f253ff2002-05-19 00:13:34 +00002326 }
2327 vg_sem->count--;
2328 res = __pthread_mutex_unlock(&vg_sem->se_mx);
sewardj2d94c112002-06-03 01:25:54 +00002329 my_assert(res == 0);
sewardj8f253ff2002-05-19 00:13:34 +00002330 return 0;
2331}
2332
2333int sem_post ( sem_t* sem )
2334{
2335 int res;
2336 vg_sem_t* vg_sem;
2337 ensure_valgrind("sem_post");
2338 vg_sem = se_remap(sem);
2339 res = __pthread_mutex_lock(&vg_sem->se_mx);
sewardj2d94c112002-06-03 01:25:54 +00002340 my_assert(res == 0);
sewardj8f253ff2002-05-19 00:13:34 +00002341 if (vg_sem->count == 0) {
2342 vg_sem->count++;
2343 res = pthread_cond_broadcast(&vg_sem->se_cv);
sewardj2d94c112002-06-03 01:25:54 +00002344 my_assert(res == 0);
sewardj8f253ff2002-05-19 00:13:34 +00002345 } else {
2346 vg_sem->count++;
2347 }
2348 res = __pthread_mutex_unlock(&vg_sem->se_mx);
sewardj2d94c112002-06-03 01:25:54 +00002349 my_assert(res == 0);
sewardj8f253ff2002-05-19 00:13:34 +00002350 return 0;
2351}
2352
2353
2354int sem_trywait ( sem_t* sem )
2355{
2356 int ret, res;
2357 vg_sem_t* vg_sem;
2358 ensure_valgrind("sem_trywait");
2359 vg_sem = se_remap(sem);
2360 res = __pthread_mutex_lock(&vg_sem->se_mx);
sewardj2d94c112002-06-03 01:25:54 +00002361 my_assert(res == 0);
sewardj8f253ff2002-05-19 00:13:34 +00002362 if (vg_sem->count > 0) {
2363 vg_sem->count--;
2364 ret = 0;
2365 } else {
2366 ret = -1;
sewardj25418ae2003-05-09 23:40:34 +00002367 *(__errno_location()) = EAGAIN;
sewardj8f253ff2002-05-19 00:13:34 +00002368 }
2369 res = __pthread_mutex_unlock(&vg_sem->se_mx);
sewardj2d94c112002-06-03 01:25:54 +00002370 my_assert(res == 0);
sewardj8f253ff2002-05-19 00:13:34 +00002371 return ret;
2372}
2373
2374
2375int sem_getvalue(sem_t* sem, int * sval)
2376{
2377 vg_sem_t* vg_sem;
2378 ensure_valgrind("sem_trywait");
2379 vg_sem = se_remap(sem);
2380 *sval = vg_sem->count;
2381 return 0;
2382}
2383
2384
2385int sem_destroy(sem_t * sem)
2386{
2387 kludged("sem_destroy");
2388 /* if someone waiting on this semaphore, errno = EBUSY, return -1 */
2389 return 0;
2390}
2391
sewardj9ad92d92002-10-16 19:45:06 +00002392
2393int sem_timedwait(sem_t* sem, const struct timespec *abstime)
2394{
2395 int res;
2396 vg_sem_t* vg_sem;
2397 ensure_valgrind("sem_timedwait");
2398 vg_sem = se_remap(sem);
2399 res = __pthread_mutex_lock(&vg_sem->se_mx);
2400 my_assert(res == 0);
2401 while ( vg_sem->count == 0 && res != ETIMEDOUT ) {
2402 res = pthread_cond_timedwait(&vg_sem->se_cv, &vg_sem->se_mx, abstime);
2403 }
2404 if ( vg_sem->count > 0 ) {
2405 vg_sem->count--;
2406 res = __pthread_mutex_unlock(&vg_sem->se_mx);
2407 my_assert(res == 0 );
2408 return 0;
2409 } else {
2410 res = __pthread_mutex_unlock(&vg_sem->se_mx);
2411 my_assert(res == 0 );
2412 *(__errno_location()) = ETIMEDOUT;
2413 return -1;
2414 }
2415}
2416
sewardj8f253ff2002-05-19 00:13:34 +00002417
2418/* ---------------------------------------------------------------------
sewardj2d8b3f02002-06-01 14:14:19 +00002419 Reader-writer locks.
sewardja1ac5cb2002-05-27 13:00:05 +00002420 ------------------------------------------------------------------ */
2421
sewardj2d8b3f02002-06-01 14:14:19 +00002422typedef
2423 struct {
2424 int initted; /* != 0 --> in use; sanity check only */
2425 int prefer_w; /* != 0 --> prefer writer */
2426 int nwait_r; /* # of waiting readers */
2427 int nwait_w; /* # of waiting writers */
2428 pthread_cond_t cv_r; /* for signalling readers */
2429 pthread_cond_t cv_w; /* for signalling writers */
2430 pthread_mutex_t mx;
2431 int status;
2432 /* allowed range for status: >= -1. -1 means 1 writer currently
2433 active, >= 0 means N readers currently active. */
2434 }
2435 vg_rwlock_t;
sewardja1ac5cb2002-05-27 13:00:05 +00002436
2437
2438static pthread_mutex_t rw_remap_mx = PTHREAD_MUTEX_INITIALIZER;
2439
2440static int rw_remap_used = 0;
2441static pthread_rwlock_t* rw_remap_orig[VG_N_RWLOCKS];
2442static vg_rwlock_t rw_remap_new[VG_N_RWLOCKS];
2443
sewardj2d8b3f02002-06-01 14:14:19 +00002444
2445static
2446void init_vg_rwlock ( vg_rwlock_t* vg_rwl )
2447{
2448 int res = 0;
2449 vg_rwl->initted = 1;
2450 vg_rwl->prefer_w = 1;
2451 vg_rwl->nwait_r = 0;
2452 vg_rwl->nwait_w = 0;
2453 vg_rwl->status = 0;
2454 res = pthread_mutex_init(&vg_rwl->mx, NULL);
2455 res |= pthread_cond_init(&vg_rwl->cv_r, NULL);
2456 res |= pthread_cond_init(&vg_rwl->cv_w, NULL);
sewardj2d94c112002-06-03 01:25:54 +00002457 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002458}
2459
2460
sewardja1ac5cb2002-05-27 13:00:05 +00002461/* Take the address of a LinuxThreads rwlock_t and return the shadow
2462 address of our version. Further, if the LinuxThreads version
2463 appears to have been statically initialised, do the same to the one
2464 we allocate here. The pthread_rwlock_t.__rw_readers field is set
2465 to zero by PTHREAD_RWLOCK_INITIALIZER, so we take zero as meaning
2466 uninitialised and non-zero meaning initialised.
2467*/
2468static vg_rwlock_t* rw_remap ( pthread_rwlock_t* orig )
2469{
2470 int res, i;
2471 vg_rwlock_t* vg_rwl;
2472 res = __pthread_mutex_lock(&rw_remap_mx);
sewardj2d94c112002-06-03 01:25:54 +00002473 my_assert(res == 0);
sewardja1ac5cb2002-05-27 13:00:05 +00002474
2475 for (i = 0; i < rw_remap_used; i++) {
2476 if (rw_remap_orig[i] == orig)
2477 break;
2478 }
2479 if (i == rw_remap_used) {
2480 if (rw_remap_used == VG_N_RWLOCKS) {
sewardj2d8b3f02002-06-01 14:14:19 +00002481 res = __pthread_mutex_unlock(&rw_remap_mx);
sewardj2d94c112002-06-03 01:25:54 +00002482 my_assert(res == 0);
sewardja1ac5cb2002-05-27 13:00:05 +00002483 barf("VG_N_RWLOCKS is too low. Increase and recompile.");
2484 }
2485 rw_remap_used++;
2486 rw_remap_orig[i] = orig;
sewardj2d8b3f02002-06-01 14:14:19 +00002487 rw_remap_new[i].initted = 0;
sewardja1ac5cb2002-05-27 13:00:05 +00002488 if (0) printf("allocated rwlock %d\n", i);
2489 }
2490 res = __pthread_mutex_unlock(&rw_remap_mx);
sewardj2d94c112002-06-03 01:25:54 +00002491 my_assert(res == 0);
sewardja1ac5cb2002-05-27 13:00:05 +00002492 vg_rwl = &rw_remap_new[i];
2493
sewardj2d8b3f02002-06-01 14:14:19 +00002494 /* Initialise the shadow, if required. */
sewardja1ac5cb2002-05-27 13:00:05 +00002495 if (orig->__rw_readers == 0) {
sewardja1ac5cb2002-05-27 13:00:05 +00002496 orig->__rw_readers = 1;
sewardj2d8b3f02002-06-01 14:14:19 +00002497 init_vg_rwlock(vg_rwl);
sewardja1ac5cb2002-05-27 13:00:05 +00002498 if (orig->__rw_kind == PTHREAD_RWLOCK_PREFER_READER_NP)
sewardj2d8b3f02002-06-01 14:14:19 +00002499 vg_rwl->prefer_w = 0;
sewardja1ac5cb2002-05-27 13:00:05 +00002500 }
2501
2502 return vg_rwl;
2503}
2504
2505
sewardja1ac5cb2002-05-27 13:00:05 +00002506int pthread_rwlock_init ( pthread_rwlock_t* orig,
2507 const pthread_rwlockattr_t* attr )
2508{
sewardja1ac5cb2002-05-27 13:00:05 +00002509 vg_rwlock_t* rwl;
2510 if (0) printf ("pthread_rwlock_init\n");
2511 /* Force the remapper to initialise the shadow. */
2512 orig->__rw_readers = 0;
2513 /* Install the lock preference; the remapper needs to know it. */
2514 orig->__rw_kind = PTHREAD_RWLOCK_DEFAULT_NP;
2515 if (attr)
2516 orig->__rw_kind = attr->__lockkind;
2517 rwl = rw_remap ( orig );
sewardj2d8b3f02002-06-01 14:14:19 +00002518 return 0;
sewardja1ac5cb2002-05-27 13:00:05 +00002519}
2520
sewardj2d8b3f02002-06-01 14:14:19 +00002521
2522static
2523void pthread_rwlock_rdlock_CANCEL_HDLR ( void* rwl_v )
sewardja1ac5cb2002-05-27 13:00:05 +00002524{
sewardj2d8b3f02002-06-01 14:14:19 +00002525 vg_rwlock_t* rwl = (vg_rwlock_t*)rwl_v;
2526 rwl->nwait_r--;
2527 pthread_mutex_unlock (&rwl->mx);
sewardja1ac5cb2002-05-27 13:00:05 +00002528}
2529
sewardj2d8b3f02002-06-01 14:14:19 +00002530
sewardja1ac5cb2002-05-27 13:00:05 +00002531int pthread_rwlock_rdlock ( pthread_rwlock_t* orig )
2532{
2533 int res;
2534 vg_rwlock_t* rwl;
2535 if (0) printf ("pthread_rwlock_rdlock\n");
2536 rwl = rw_remap ( orig );
sewardj2d8b3f02002-06-01 14:14:19 +00002537 res = __pthread_mutex_lock(&rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00002538 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002539 if (!rwl->initted) {
2540 res = __pthread_mutex_unlock(&rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00002541 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002542 return EINVAL;
2543 }
2544 if (rwl->status < 0) {
sewardj2d94c112002-06-03 01:25:54 +00002545 my_assert(rwl->status == -1);
sewardj2d8b3f02002-06-01 14:14:19 +00002546 rwl->nwait_r++;
2547 pthread_cleanup_push( pthread_rwlock_rdlock_CANCEL_HDLR, rwl );
2548 while (1) {
2549 if (rwl->status == 0) break;
2550 res = pthread_cond_wait(&rwl->cv_r, &rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00002551 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002552 }
2553 pthread_cleanup_pop(0);
2554 rwl->nwait_r--;
2555 }
sewardj2d94c112002-06-03 01:25:54 +00002556 my_assert(rwl->status >= 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002557 rwl->status++;
2558 res = __pthread_mutex_unlock(&rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00002559 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002560 return 0;
sewardja1ac5cb2002-05-27 13:00:05 +00002561}
2562
sewardj2d8b3f02002-06-01 14:14:19 +00002563
sewardja1ac5cb2002-05-27 13:00:05 +00002564int pthread_rwlock_tryrdlock ( pthread_rwlock_t* orig )
2565{
2566 int res;
2567 vg_rwlock_t* rwl;
2568 if (0) printf ("pthread_rwlock_tryrdlock\n");
2569 rwl = rw_remap ( orig );
sewardj2d8b3f02002-06-01 14:14:19 +00002570 res = __pthread_mutex_lock(&rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00002571 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002572 if (!rwl->initted) {
2573 res = __pthread_mutex_unlock(&rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00002574 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002575 return EINVAL;
2576 }
2577 if (rwl->status == -1) {
2578 /* Writer active; we have to give up. */
2579 res = __pthread_mutex_unlock(&rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00002580 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002581 return EBUSY;
2582 }
2583 /* Success */
sewardj2d94c112002-06-03 01:25:54 +00002584 my_assert(rwl->status >= 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002585 rwl->status++;
2586 res = __pthread_mutex_unlock(&rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00002587 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002588 return 0;
sewardja1ac5cb2002-05-27 13:00:05 +00002589}
2590
sewardj2d8b3f02002-06-01 14:14:19 +00002591
2592static
2593void pthread_rwlock_wrlock_CANCEL_HDLR ( void* rwl_v )
2594{
2595 vg_rwlock_t* rwl = (vg_rwlock_t*)rwl_v;
2596 rwl->nwait_w--;
2597 pthread_mutex_unlock (&rwl->mx);
2598}
2599
2600
sewardja1ac5cb2002-05-27 13:00:05 +00002601int pthread_rwlock_wrlock ( pthread_rwlock_t* orig )
2602{
2603 int res;
2604 vg_rwlock_t* rwl;
2605 if (0) printf ("pthread_rwlock_wrlock\n");
2606 rwl = rw_remap ( orig );
sewardj2d8b3f02002-06-01 14:14:19 +00002607 res = __pthread_mutex_lock(&rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00002608 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002609 if (!rwl->initted) {
2610 res = __pthread_mutex_unlock(&rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00002611 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002612 return EINVAL;
2613 }
2614 if (rwl->status != 0) {
2615 rwl->nwait_w++;
2616 pthread_cleanup_push( pthread_rwlock_wrlock_CANCEL_HDLR, rwl );
2617 while (1) {
2618 if (rwl->status == 0) break;
2619 res = pthread_cond_wait(&rwl->cv_w, &rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00002620 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002621 }
2622 pthread_cleanup_pop(0);
2623 rwl->nwait_w--;
2624 }
sewardj2d94c112002-06-03 01:25:54 +00002625 my_assert(rwl->status == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002626 rwl->status = -1;
2627 res = __pthread_mutex_unlock(&rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00002628 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002629 return 0;
sewardja1ac5cb2002-05-27 13:00:05 +00002630}
2631
sewardj2d8b3f02002-06-01 14:14:19 +00002632
sewardja1ac5cb2002-05-27 13:00:05 +00002633int pthread_rwlock_trywrlock ( pthread_rwlock_t* orig )
2634{
2635 int res;
2636 vg_rwlock_t* rwl;
sewardj2d8b3f02002-06-01 14:14:19 +00002637 if (0) printf ("pthread_wrlock_trywrlock\n");
sewardja1ac5cb2002-05-27 13:00:05 +00002638 rwl = rw_remap ( orig );
sewardj2d8b3f02002-06-01 14:14:19 +00002639 res = __pthread_mutex_lock(&rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00002640 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002641 if (!rwl->initted) {
2642 res = __pthread_mutex_unlock(&rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00002643 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002644 return EINVAL;
2645 }
2646 if (rwl->status != 0) {
2647 /* Reader(s) or a writer active; we have to give up. */
2648 res = __pthread_mutex_unlock(&rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00002649 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002650 return EBUSY;
2651 }
2652 /* Success */
sewardj2d94c112002-06-03 01:25:54 +00002653 my_assert(rwl->status == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002654 rwl->status = -1;
2655 res = __pthread_mutex_unlock(&rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00002656 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002657 return 0;
sewardja1ac5cb2002-05-27 13:00:05 +00002658}
2659
sewardj2d8b3f02002-06-01 14:14:19 +00002660
sewardja1ac5cb2002-05-27 13:00:05 +00002661int pthread_rwlock_unlock ( pthread_rwlock_t* orig )
2662{
2663 int res;
2664 vg_rwlock_t* rwl;
2665 if (0) printf ("pthread_rwlock_unlock\n");
2666 rwl = rw_remap ( orig );
sewardj2d8b3f02002-06-01 14:14:19 +00002667 rwl = rw_remap ( orig );
2668 res = __pthread_mutex_lock(&rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00002669 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002670 if (!rwl->initted) {
2671 res = __pthread_mutex_unlock(&rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00002672 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002673 return EINVAL;
2674 }
2675 if (rwl->status == 0) {
2676 res = __pthread_mutex_unlock(&rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00002677 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002678 return EPERM;
2679 }
sewardj2d94c112002-06-03 01:25:54 +00002680 my_assert(rwl->status != 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002681 if (rwl->status == -1) {
2682 rwl->status = 0;
2683 } else {
sewardj2d94c112002-06-03 01:25:54 +00002684 my_assert(rwl->status > 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002685 rwl->status--;
2686 }
2687
sewardj2d94c112002-06-03 01:25:54 +00002688 my_assert(rwl->status >= 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002689
2690 if (rwl->prefer_w) {
2691
2692 /* Favour waiting writers, if any. */
2693 if (rwl->nwait_w > 0) {
2694 /* Writer(s) are waiting. */
2695 if (rwl->status == 0) {
2696 /* We can let a writer in. */
2697 res = pthread_cond_signal(&rwl->cv_w);
sewardj2d94c112002-06-03 01:25:54 +00002698 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002699 } else {
2700 /* There are still readers active. Do nothing; eventually
2701 they will disappear, at which point a writer will be
2702 admitted. */
2703 }
2704 }
2705 else
2706 /* No waiting writers. */
2707 if (rwl->nwait_r > 0) {
2708 /* Let in a waiting reader. */
2709 res = pthread_cond_signal(&rwl->cv_r);
sewardj2d94c112002-06-03 01:25:54 +00002710 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002711 }
2712
2713 } else {
2714
2715 /* Favour waiting readers, if any. */
2716 if (rwl->nwait_r > 0) {
2717 /* Reader(s) are waiting; let one in. */
2718 res = pthread_cond_signal(&rwl->cv_r);
sewardj2d94c112002-06-03 01:25:54 +00002719 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002720 }
2721 else
2722 /* No waiting readers. */
2723 if (rwl->nwait_w > 0 && rwl->status == 0) {
2724 /* We have waiting writers and no active readers; let a
2725 writer in. */
2726 res = pthread_cond_signal(&rwl->cv_w);
sewardj2d94c112002-06-03 01:25:54 +00002727 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002728 }
2729 }
2730
2731 res = __pthread_mutex_unlock(&rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00002732 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002733 return 0;
2734}
2735
2736
2737int pthread_rwlock_destroy ( pthread_rwlock_t *orig )
2738{
2739 int res;
2740 vg_rwlock_t* rwl;
2741 if (0) printf ("pthread_rwlock_destroy\n");
2742 rwl = rw_remap ( orig );
2743 res = __pthread_mutex_lock(&rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00002744 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002745 if (!rwl->initted) {
2746 res = __pthread_mutex_unlock(&rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00002747 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002748 return EINVAL;
2749 }
2750 if (rwl->status != 0 || rwl->nwait_r > 0 || rwl->nwait_w > 0) {
2751 res = __pthread_mutex_unlock(&rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00002752 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002753 return EBUSY;
2754 }
2755 rwl->initted = 0;
2756 res = __pthread_mutex_unlock(&rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00002757 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002758 return 0;
sewardja1ac5cb2002-05-27 13:00:05 +00002759}
2760
2761
sewardj47e4e312002-06-18 09:24:34 +00002762/* Copied directly from LinuxThreads. */
2763int
2764pthread_rwlockattr_init (pthread_rwlockattr_t *attr)
2765{
2766 attr->__lockkind = 0;
2767 attr->__pshared = PTHREAD_PROCESS_PRIVATE;
2768
2769 return 0;
2770}
2771
sewardjfe18eb82002-07-13 12:58:44 +00002772/* Copied directly from LinuxThreads. */
2773int
sewardj5706bfa2002-12-08 23:42:17 +00002774pthread_rwlockattr_destroy (pthread_rwlockattr_t *attr)
2775{
2776 return 0;
2777}
2778
2779/* Copied directly from LinuxThreads. */
2780int
sewardjfe18eb82002-07-13 12:58:44 +00002781pthread_rwlockattr_setpshared (pthread_rwlockattr_t *attr, int pshared)
2782{
2783 if (pshared != PTHREAD_PROCESS_PRIVATE && pshared != PTHREAD_PROCESS_SHARED)
2784 return EINVAL;
2785
2786 /* For now it is not possible to shared a conditional variable. */
2787 if (pshared != PTHREAD_PROCESS_PRIVATE)
2788 return ENOSYS;
2789
2790 attr->__pshared = pshared;
2791
2792 return 0;
2793}
2794
sewardj47e4e312002-06-18 09:24:34 +00002795
sewardj262b5be2003-04-26 21:19:53 +00002796
2797/* ---------------------------------------------------------------------
jsgf855d93d2003-10-13 22:26:55 +00002798 Manage the allocation and use of RT signals. The Valgrind core
2799 uses one. glibc needs us to implement this to make RT signals
2800 work; things just seem to crash if we don't.
sewardj262b5be2003-04-26 21:19:53 +00002801 ------------------------------------------------------------------ */
sewardj262b5be2003-04-26 21:19:53 +00002802int __libc_current_sigrtmin (void)
2803{
jsgf855d93d2003-10-13 22:26:55 +00002804 return VG_(sig_rtmin);
sewardj262b5be2003-04-26 21:19:53 +00002805}
2806
2807int __libc_current_sigrtmax (void)
2808{
jsgf855d93d2003-10-13 22:26:55 +00002809 return VG_(sig_rtmax);
sewardj262b5be2003-04-26 21:19:53 +00002810}
2811
2812int __libc_allocate_rtsig (int high)
2813{
jsgf855d93d2003-10-13 22:26:55 +00002814 return VG_(sig_alloc_rtsig)(high);
sewardj262b5be2003-04-26 21:19:53 +00002815}
2816
sewardjd5bef572002-10-23 21:49:33 +00002817/* ---------------------------------------------------------------------
sewardj3b13f0e2002-04-25 20:17:29 +00002818 B'stard.
2819 ------------------------------------------------------------------ */
sewardj5905fae2002-04-26 13:25:00 +00002820strong_alias(__pthread_mutex_lock, pthread_mutex_lock)
2821strong_alias(__pthread_mutex_trylock, pthread_mutex_trylock)
2822strong_alias(__pthread_mutex_unlock, pthread_mutex_unlock)
2823strong_alias(__pthread_mutexattr_init, pthread_mutexattr_init)
2824 weak_alias(__pthread_mutexattr_settype, pthread_mutexattr_settype)
sewardjf0995512003-07-06 01:29:49 +00002825 weak_alias(__pthread_mutexattr_setpshared, pthread_mutexattr_setpshared)
sewardj5905fae2002-04-26 13:25:00 +00002826strong_alias(__pthread_mutex_init, pthread_mutex_init)
2827strong_alias(__pthread_mutexattr_destroy, pthread_mutexattr_destroy)
2828strong_alias(__pthread_mutex_destroy, pthread_mutex_destroy)
2829strong_alias(__pthread_once, pthread_once)
2830strong_alias(__pthread_atfork, pthread_atfork)
2831strong_alias(__pthread_key_create, pthread_key_create)
2832strong_alias(__pthread_getspecific, pthread_getspecific)
2833strong_alias(__pthread_setspecific, pthread_setspecific)
2834
sewardjd529a442002-05-04 19:49:21 +00002835#ifndef GLIBC_2_1
sewardj3b13f0e2002-04-25 20:17:29 +00002836strong_alias(sigaction, __sigaction)
sewardjd529a442002-05-04 19:49:21 +00002837#endif
2838
sewardj5905fae2002-04-26 13:25:00 +00002839weak_alias(__fork, fork)
njn25e49d8e72002-09-23 09:36:25 +00002840weak_alias(__vfork, vfork)
sewardjf0b06452002-06-04 08:38:04 +00002841weak_alias (__pthread_kill_other_threads_np, pthread_kill_other_threads_np)
sewardj3b13f0e2002-04-25 20:17:29 +00002842
2843/*--------------------------------------------------*/
2844
sewardj5905fae2002-04-26 13:25:00 +00002845weak_alias(pthread_rwlock_rdlock, __pthread_rwlock_rdlock)
sewardj5905fae2002-04-26 13:25:00 +00002846weak_alias(pthread_rwlock_unlock, __pthread_rwlock_unlock)
sewardj262b0292002-05-01 00:03:16 +00002847weak_alias(pthread_rwlock_wrlock, __pthread_rwlock_wrlock)
sewardj060b04f2002-04-26 21:01:13 +00002848
sewardja1ac5cb2002-05-27 13:00:05 +00002849weak_alias(pthread_rwlock_destroy, __pthread_rwlock_destroy)
2850weak_alias(pthread_rwlock_init, __pthread_rwlock_init)
2851weak_alias(pthread_rwlock_tryrdlock, __pthread_rwlock_tryrdlock)
2852weak_alias(pthread_rwlock_trywrlock, __pthread_rwlock_trywrlock)
2853
sewardj060b04f2002-04-26 21:01:13 +00002854
sewardj3b13f0e2002-04-25 20:17:29 +00002855/* I've no idea what these are, but they get called quite a lot.
2856 Anybody know? */
2857
njnff28df92003-10-12 17:26:04 +00002858#ifndef __UCLIBC__
sewardj3b13f0e2002-04-25 20:17:29 +00002859#undef _IO_flockfile
2860void _IO_flockfile ( _IO_FILE * file )
2861{
sewardj853f55d2002-04-26 00:27:53 +00002862 pthread_mutex_lock(file->_lock);
sewardj3b13f0e2002-04-25 20:17:29 +00002863}
sewardj5905fae2002-04-26 13:25:00 +00002864weak_alias(_IO_flockfile, flockfile);
2865
sewardj3b13f0e2002-04-25 20:17:29 +00002866#undef _IO_funlockfile
2867void _IO_funlockfile ( _IO_FILE * file )
2868{
sewardj853f55d2002-04-26 00:27:53 +00002869 pthread_mutex_unlock(file->_lock);
sewardj3b13f0e2002-04-25 20:17:29 +00002870}
sewardj5905fae2002-04-26 13:25:00 +00002871weak_alias(_IO_funlockfile, funlockfile);
njnff28df92003-10-12 17:26:04 +00002872#endif
sewardj5905fae2002-04-26 13:25:00 +00002873
sewardj3b13f0e2002-04-25 20:17:29 +00002874
sewardjd4f2c712002-04-30 10:20:10 +00002875/* This doesn't seem to be needed to simulate libpthread.so's external
2876 interface, but many people complain about its absence. */
2877
2878strong_alias(__pthread_mutexattr_settype, __pthread_mutexattr_setkind_np)
2879weak_alias(__pthread_mutexattr_setkind_np, pthread_mutexattr_setkind_np)
sewardj439d45e2002-05-03 20:43:10 +00002880
sewardj5e657c32003-10-12 08:33:30 +00002881/* POSIX spinlocks, taken from glibc linuxthreads/sysdeps/i386 */
2882
2883typedef volatile int pthread_spinlock_t; /* Huh? Guarded by __USE_XOPEN2K */
2884
2885int pthread_spin_init(pthread_spinlock_t *lock, int pshared)
2886{
2887 /* We can ignore the `pshared' parameter. Since we are busy-waiting
2888 all processes which can access the memory location `lock' points
2889 to can use the spinlock. */
2890 *lock = 1;
2891 return 0;
2892}
2893
2894int pthread_spin_lock(pthread_spinlock_t *lock)
2895{
2896 asm volatile
2897 ("\n"
2898 "1:\n\t"
2899 "lock; decl %0\n\t"
2900 "js 2f\n\t"
2901 ".section .text.spinlock,\"ax\"\n"
2902 "2:\n\t"
2903 "cmpl $0,%0\n\t"
2904 "rep; nop\n\t"
2905 "jle 2b\n\t"
2906 "jmp 1b\n\t"
2907 ".previous"
2908 : "=m" (*lock));
2909 return 0;
2910}
2911
2912int pthread_spin_unlock(pthread_spinlock_t *lock)
2913{
2914 asm volatile
2915 ("movl $1,%0"
2916 : "=m" (*lock));
2917 return 0;
2918}
2919
2920int pthread_spin_destroy(pthread_spinlock_t *lock)
2921{
2922 /* Nothing to do. */
2923 return 0;
2924}
2925
2926int pthread_spin_trylock(pthread_spinlock_t *lock)
2927{
2928 int oldval;
2929
2930 asm volatile
2931 ("xchgl %0,%1"
2932 : "=r" (oldval), "=m" (*lock)
2933 : "0" (0));
2934 return oldval > 0 ? 0 : EBUSY;
2935}
sewardj439d45e2002-05-03 20:43:10 +00002936
2937/*--------------------------------------------------------------------*/
2938/*--- end vg_libpthread.c ---*/
2939/*--------------------------------------------------------------------*/