blob: 8e4cb3697867b5fca544feb20e0f3ca7f27826ec [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#ifdef GLIBC_2_1
70#include <sys/time.h>
71#endif
sewardjf912dfc2002-11-13 21:51:10 +000072#include <sys/stat.h>
73#include <sys/poll.h>
sewardj2d94c112002-06-03 01:25:54 +000074#include <stdio.h>
75
sewardj705d3cb2002-05-23 13:13:12 +000076
77/* ---------------------------------------------------------------------
78 Forwardses.
79 ------------------------------------------------------------------ */
80
sewardj11f0bb42003-04-26 20:11:15 +000081#define WEAK __attribute__((weak))
82
sewardj705d3cb2002-05-23 13:13:12 +000083
sewardj9a2224b2002-06-19 10:17:40 +000084static
sewardj08c7f012002-10-07 23:56:55 +000085int my_do_syscall1 ( int syscallno, int arg1 );
86
87static
sewardj9a2224b2002-06-19 10:17:40 +000088int my_do_syscall2 ( int syscallno,
89 int arg1, int arg2 );
90
sewardj08c7f012002-10-07 23:56:55 +000091static
92int my_do_syscall3 ( int syscallno,
93 int arg1, int arg2, int arg3 );
94
sewardjfd7747b2002-12-01 10:25:53 +000095static
96__inline__
97int is_kerror ( int res )
98{
99 if (res >= -4095 && res <= -1)
100 return 1;
101 else
102 return 0;
103}
104
sewardj08c7f012002-10-07 23:56:55 +0000105
106#ifdef GLIBC_2_3
107 /* kludge by JRS (not from glibc) ... */
108 typedef void* __locale_t;
109
110 /* Copied from locale/locale.h in glibc-2.2.93 sources */
111 /* This value can be passed to `uselocale' and may be returned by
112 it. Passing this value to any other function has undefined
113 behavior. */
114# define LC_GLOBAL_LOCALE ((__locale_t) -1L)
115 extern __locale_t __uselocale ( __locale_t );
116#endif
117
sewardj00a66b12002-10-12 16:42:35 +0000118static
119void init_libc_tsd_keys ( void );
120
sewardj705d3cb2002-05-23 13:13:12 +0000121
sewardje663cb92002-04-12 10:26:32 +0000122/* ---------------------------------------------------------------------
123 Helpers. We have to be pretty self-sufficient.
124 ------------------------------------------------------------------ */
125
sewardj436e0582002-04-26 14:31:40 +0000126/* Number of times any given error message is printed. */
127#define N_MOANS 3
128
sewardj45b4b372002-04-16 22:50:32 +0000129/* Extract from Valgrind the value of VG_(clo_trace_pthread_level).
130 Returns 0 (none) if not running on Valgrind. */
131static
132int get_pt_trace_level ( void )
133{
134 int res;
135 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
136 VG_USERREQ__GET_PTHREAD_TRACE_LEVEL,
137 0, 0, 0, 0);
138 return res;
139}
140
sewardje663cb92002-04-12 10:26:32 +0000141static
sewardj2d94c112002-06-03 01:25:54 +0000142void my_exit ( int arg )
sewardje663cb92002-04-12 10:26:32 +0000143{
sewardj08c7f012002-10-07 23:56:55 +0000144 my_do_syscall1(__NR_exit, arg);
145 /*NOTREACHED*/
sewardje663cb92002-04-12 10:26:32 +0000146}
147
sewardje0cfe2a2002-11-30 14:04:45 +0000148/* Apparently unused.
sewardj08c7f012002-10-07 23:56:55 +0000149static
150void my_write ( int fd, const void *buf, int count )
151{
152 my_do_syscall3(__NR_write, fd, (int)buf, count );
153}
sewardje0cfe2a2002-11-30 14:04:45 +0000154*/
sewardje663cb92002-04-12 10:26:32 +0000155
sewardj68b2dd92002-05-10 21:03:56 +0000156/* We need this guy -- it's in valgrind.so. */
157extern void VG_(startup) ( void );
158
159
160/* Just start up Valgrind if it's not already going. VG_(startup)()
161 detects and ignores second and subsequent calls. */
sewardj604ec3c2002-04-18 22:38:41 +0000162static __inline__
sewardje663cb92002-04-12 10:26:32 +0000163void ensure_valgrind ( char* caller )
164{
sewardj68b2dd92002-05-10 21:03:56 +0000165 VG_(startup)();
sewardje663cb92002-04-12 10:26:32 +0000166}
167
sewardjbea1caa2002-05-10 23:20:58 +0000168/* While we're at it ... hook our own startup function into this
169 game. */
170__asm__ (
171 ".section .init\n"
172 "\tcall vgPlain_startup"
173);
174
sewardje663cb92002-04-12 10:26:32 +0000175
176static
sewardj3b5d8862002-04-20 13:53:23 +0000177__attribute__((noreturn))
sewardje663cb92002-04-12 10:26:32 +0000178void barf ( char* str )
179{
sewardj69a72a52002-11-03 13:41:41 +0000180 char buf[1000];
sewardje663cb92002-04-12 10:26:32 +0000181 buf[0] = 0;
sewardj439d45e2002-05-03 20:43:10 +0000182 strcat(buf, "\nvalgrind's libpthread.so: ");
sewardje663cb92002-04-12 10:26:32 +0000183 strcat(buf, str);
184 strcat(buf, "\n\n");
njn4c791212003-05-02 17:53:54 +0000185 VALGRIND_NON_SIMD_CALL2(VG_(message), Vg_UserMsg, buf);
sewardj2d94c112002-06-03 01:25:54 +0000186 my_exit(1);
sewardj3b5d8862002-04-20 13:53:23 +0000187 /* We have to persuade gcc into believing this doesn't return. */
188 while (1) { };
sewardje663cb92002-04-12 10:26:32 +0000189}
190
191
sewardj69a72a52002-11-03 13:41:41 +0000192static void cat_n_send ( char* pre, char* msg )
sewardj2a3d28c2002-04-14 13:27:00 +0000193{
sewardj69a72a52002-11-03 13:41:41 +0000194 char buf[1000];
sewardj436e0582002-04-26 14:31:40 +0000195 if (get_pt_trace_level() >= 0) {
sewardj69a72a52002-11-03 13:41:41 +0000196 snprintf(buf, sizeof(buf), "%s%s", pre, msg );
197 buf[sizeof(buf)-1] = '\0';
njn4c791212003-05-02 17:53:54 +0000198 VALGRIND_NON_SIMD_CALL2(VG_(message), Vg_UserMsg, buf);
sewardj45b4b372002-04-16 22:50:32 +0000199 }
sewardj2a3d28c2002-04-14 13:27:00 +0000200}
201
sewardj69a72a52002-11-03 13:41:41 +0000202static void ignored ( char* msg )
203{
204 cat_n_send ( "valgrind's libpthread.so: IGNORED call to: ", msg );
205}
206
207
sewardj30671ff2002-04-21 00:13:57 +0000208static void kludged ( char* msg )
209{
sewardj69a72a52002-11-03 13:41:41 +0000210 cat_n_send ( "valgrind's libpthread.so: KLUDGED call to: ", msg );
sewardj439d45e2002-05-03 20:43:10 +0000211}
212
sewardj69a72a52002-11-03 13:41:41 +0000213
sewardjccef2e62002-05-29 19:26:32 +0000214__attribute__((noreturn))
sewardj3b13f0e2002-04-25 20:17:29 +0000215void vgPlain_unimp ( char* what )
216{
sewardj69a72a52002-11-03 13:41:41 +0000217 cat_n_send (
218 "valgrind's libpthread.so: UNIMPLEMENTED FUNCTION: ", what );
sewardj3b13f0e2002-04-25 20:17:29 +0000219 barf("Please report this bug to me at: jseward@acm.org");
220}
221
sewardje663cb92002-04-12 10:26:32 +0000222
sewardj457cc472002-06-03 23:13:47 +0000223static
sewardj2d94c112002-06-03 01:25:54 +0000224void my_assert_fail ( Char* expr, Char* file, Int line, Char* fn )
225{
sewardj69a72a52002-11-03 13:41:41 +0000226 char buf[1000];
sewardj2d94c112002-06-03 01:25:54 +0000227 static Bool entered = False;
228 if (entered)
229 my_exit(2);
230 entered = True;
sewardj69a72a52002-11-03 13:41:41 +0000231 sprintf(buf, "\n%s: %s:%d (%s): Assertion `%s' failed.\n",
232 "valgrind", file, line, fn, expr );
233 cat_n_send ( "", buf );
234 sprintf(buf, "Please report this bug to me at: %s\n\n",
235 VG_EMAIL_ADDR);
236 cat_n_send ( "", buf );
sewardj2d94c112002-06-03 01:25:54 +0000237 my_exit(1);
238}
239
240#define MY__STRING(__str) #__str
241
242#define my_assert(expr) \
243 ((void) ((expr) ? 0 : \
244 (my_assert_fail (MY__STRING(expr), \
245 __FILE__, __LINE__, \
246 __PRETTY_FUNCTION__), 0)))
247
sewardj00a66b12002-10-12 16:42:35 +0000248static
249void my_free ( void* ptr )
250{
251 int res;
252 VALGRIND_MAGIC_SEQUENCE(res, (-1) /* default */,
253 VG_USERREQ__FREE, ptr, 0, 0, 0);
254 my_assert(res == 0);
255}
256
257
258static
259void* my_malloc ( int nbytes )
260{
261 void* res;
262 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
263 VG_USERREQ__MALLOC, nbytes, 0, 0, 0);
264 my_assert(res != (void*)0);
265 return res;
266}
267
268
sewardj2d94c112002-06-03 01:25:54 +0000269
sewardje663cb92002-04-12 10:26:32 +0000270/* ---------------------------------------------------------------------
271 Pass pthread_ calls to Valgrind's request mechanism.
272 ------------------------------------------------------------------ */
273
sewardjf8f819e2002-04-17 23:21:37 +0000274#include <errno.h>
sewardj5f07b662002-04-23 16:52:51 +0000275#include <sys/time.h> /* gettimeofday */
sewardjf8f819e2002-04-17 23:21:37 +0000276
sewardja1ac5cb2002-05-27 13:00:05 +0000277
sewardjf8f819e2002-04-17 23:21:37 +0000278/* ---------------------------------------------------
sewardj4dced352002-06-04 22:54:20 +0000279 Ummm ..
280 ------------------------------------------------ */
281
282static
283void pthread_error ( const char* msg )
284{
285 int res;
286 VALGRIND_MAGIC_SEQUENCE(res, 0,
287 VG_USERREQ__PTHREAD_ERROR,
288 msg, 0, 0, 0);
289}
290
291
292/* ---------------------------------------------------
sewardj00a66b12002-10-12 16:42:35 +0000293 Here so it can be inlined without complaint.
294 ------------------------------------------------ */
295
296__inline__
297pthread_t pthread_self(void)
298{
299 int tid;
300 ensure_valgrind("pthread_self");
301 VALGRIND_MAGIC_SEQUENCE(tid, 0 /* default */,
302 VG_USERREQ__PTHREAD_GET_THREADID,
303 0, 0, 0, 0);
304 if (tid < 1 || tid >= VG_N_THREADS)
305 barf("pthread_self: invalid ThreadId");
306 return tid;
307}
308
309
310/* ---------------------------------------------------
sewardjf8f819e2002-04-17 23:21:37 +0000311 THREAD ATTRIBUTES
312 ------------------------------------------------ */
313
sewardj6af4b5d2002-04-16 04:40:49 +0000314int pthread_attr_init(pthread_attr_t *attr)
315{
sewardj7989d0c2002-05-28 11:00:01 +0000316 /* Just initialise the fields which we might look at. */
317 attr->__detachstate = PTHREAD_CREATE_JOINABLE;
sewardj111b14c2002-10-20 16:22:57 +0000318 /* Linuxthreads sets this field to the value __getpagesize(), so I
319 guess the following is OK. */
320 attr->__guardsize = VKI_BYTES_PER_PAGE; return 0;
sewardj6af4b5d2002-04-16 04:40:49 +0000321}
322
323int pthread_attr_setdetachstate(pthread_attr_t *attr, int detachstate)
324{
sewardj7989d0c2002-05-28 11:00:01 +0000325 if (detachstate != PTHREAD_CREATE_JOINABLE
sewardj4dced352002-06-04 22:54:20 +0000326 && detachstate != PTHREAD_CREATE_DETACHED) {
327 pthread_error("pthread_attr_setdetachstate: "
328 "detachstate is invalid");
sewardj7989d0c2002-05-28 11:00:01 +0000329 return EINVAL;
sewardj4dced352002-06-04 22:54:20 +0000330 }
sewardj7989d0c2002-05-28 11:00:01 +0000331 attr->__detachstate = detachstate;
sewardj6af4b5d2002-04-16 04:40:49 +0000332 return 0;
333}
334
njn25e49d8e72002-09-23 09:36:25 +0000335int pthread_attr_getdetachstate(const pthread_attr_t *attr, int *detachstate)
336{
337 *detachstate = attr->__detachstate;
338 return 0;
339}
340
sewardj30671ff2002-04-21 00:13:57 +0000341int pthread_attr_setinheritsched(pthread_attr_t *attr, int inherit)
342{
sewardj436e0582002-04-26 14:31:40 +0000343 static int moans = N_MOANS;
344 if (moans-- > 0)
345 ignored("pthread_attr_setinheritsched");
sewardj30671ff2002-04-21 00:13:57 +0000346 return 0;
347}
sewardj6af4b5d2002-04-16 04:40:49 +0000348
sewardj11f0bb42003-04-26 20:11:15 +0000349WEAK
sewardj0286dd52002-05-16 20:51:15 +0000350int pthread_attr_setstacksize (pthread_attr_t *__attr,
351 size_t __stacksize)
352{
sewardja18e2102002-05-18 10:43:22 +0000353 size_t limit;
sewardj3d7c8d62002-06-04 20:59:16 +0000354 char buf[1024];
sewardj0286dd52002-05-16 20:51:15 +0000355 ensure_valgrind("pthread_attr_setstacksize");
sewardja18e2102002-05-18 10:43:22 +0000356 limit = VG_PTHREAD_STACK_SIZE - VG_AR_CLIENT_STACKBASE_REDZONE_SZB
357 - 1000; /* paranoia */
358 if (__stacksize < limit)
sewardj0286dd52002-05-16 20:51:15 +0000359 return 0;
sewardj3d7c8d62002-06-04 20:59:16 +0000360 snprintf(buf, sizeof(buf), "pthread_attr_setstacksize: "
361 "requested size %d >= VG_PTHREAD_STACK_SIZE\n "
362 "edit vg_include.h and rebuild.", __stacksize);
363 buf[sizeof(buf)-1] = '\0'; /* Make sure it is zero terminated */
364 barf(buf);
sewardj0286dd52002-05-16 20:51:15 +0000365}
366
367
sewardj30671ff2002-04-21 00:13:57 +0000368/* This is completely bogus. */
369int pthread_attr_getschedparam(const pthread_attr_t *attr,
370 struct sched_param *param)
371{
sewardj436e0582002-04-26 14:31:40 +0000372 static int moans = N_MOANS;
373 if (moans-- > 0)
374 kludged("pthread_attr_getschedparam");
sewardj3e909ce2002-06-03 13:27:15 +0000375# ifdef HAVE_SCHED_PRIORITY
sewardj72d58482002-04-24 02:20:20 +0000376 if (param) param->sched_priority = 0; /* who knows */
377# else
sewardj30671ff2002-04-21 00:13:57 +0000378 if (param) param->__sched_priority = 0; /* who knows */
sewardj72d58482002-04-24 02:20:20 +0000379# endif
sewardj30671ff2002-04-21 00:13:57 +0000380 return 0;
381}
382
383int pthread_attr_setschedparam(pthread_attr_t *attr,
384 const struct sched_param *param)
385{
sewardj436e0582002-04-26 14:31:40 +0000386 static int moans = N_MOANS;
387 if (moans-- > 0)
388 ignored("pthread_attr_setschedparam");
sewardj30671ff2002-04-21 00:13:57 +0000389 return 0;
390}
391
392int pthread_attr_destroy(pthread_attr_t *attr)
393{
sewardj436e0582002-04-26 14:31:40 +0000394 static int moans = N_MOANS;
395 if (moans-- > 0)
396 ignored("pthread_attr_destroy");
sewardj30671ff2002-04-21 00:13:57 +0000397 return 0;
398}
sewardjf8f819e2002-04-17 23:21:37 +0000399
sewardj0d844232002-06-02 09:29:31 +0000400/* These are no-ops, as with LinuxThreads. */
401int pthread_attr_setscope ( pthread_attr_t *attr, int scope )
402{
403 ensure_valgrind("pthread_attr_setscope");
404 if (scope == PTHREAD_SCOPE_SYSTEM)
405 return 0;
sewardj4dced352002-06-04 22:54:20 +0000406 pthread_error("pthread_attr_setscope: "
407 "invalid or unsupported scope");
sewardj0d844232002-06-02 09:29:31 +0000408 if (scope == PTHREAD_SCOPE_PROCESS)
409 return ENOTSUP;
410 return EINVAL;
411}
412
413int pthread_attr_getscope ( const pthread_attr_t *attr, int *scope )
414{
415 ensure_valgrind("pthread_attr_setscope");
416 if (scope)
417 *scope = PTHREAD_SCOPE_SYSTEM;
418 return 0;
419}
420
sewardj64039bb2002-06-03 00:58:18 +0000421
422/* Pretty bogus. Avoid if possible. */
423int pthread_getattr_np (pthread_t thread, pthread_attr_t *attr)
424{
425 int detached;
426 size_t limit;
427 ensure_valgrind("pthread_getattr_np");
428 kludged("pthread_getattr_np");
429 limit = VG_PTHREAD_STACK_SIZE - VG_AR_CLIENT_STACKBASE_REDZONE_SZB
430 - 1000; /* paranoia */
431 attr->__detachstate = PTHREAD_CREATE_JOINABLE;
432 attr->__schedpolicy = SCHED_OTHER;
433 attr->__schedparam.sched_priority = 0;
434 attr->__inheritsched = PTHREAD_EXPLICIT_SCHED;
435 attr->__scope = PTHREAD_SCOPE_SYSTEM;
436 attr->__guardsize = VKI_BYTES_PER_PAGE;
437 attr->__stackaddr = NULL;
438 attr->__stackaddr_set = 0;
439 attr->__stacksize = limit;
440 VALGRIND_MAGIC_SEQUENCE(detached, (-1) /* default */,
441 VG_USERREQ__SET_OR_GET_DETACH,
442 2 /* get */, thread, 0, 0);
sewardj2d94c112002-06-03 01:25:54 +0000443 my_assert(detached == 0 || detached == 1);
sewardj64039bb2002-06-03 00:58:18 +0000444 if (detached)
445 attr->__detachstate = PTHREAD_CREATE_DETACHED;
446 return 0;
447}
448
449
450/* Bogus ... */
sewardj11f0bb42003-04-26 20:11:15 +0000451WEAK
sewardj64039bb2002-06-03 00:58:18 +0000452int pthread_attr_getstackaddr ( const pthread_attr_t * attr,
453 void ** stackaddr )
454{
455 ensure_valgrind("pthread_attr_getstackaddr");
456 kludged("pthread_attr_getstackaddr");
457 if (stackaddr)
458 *stackaddr = NULL;
459 return 0;
460}
461
462/* Not bogus (!) */
sewardj11f0bb42003-04-26 20:11:15 +0000463WEAK
sewardj64039bb2002-06-03 00:58:18 +0000464int pthread_attr_getstacksize ( const pthread_attr_t * _attr,
465 size_t * __stacksize )
466{
467 size_t limit;
468 ensure_valgrind("pthread_attr_getstacksize");
469 limit = VG_PTHREAD_STACK_SIZE - VG_AR_CLIENT_STACKBASE_REDZONE_SZB
470 - 1000; /* paranoia */
471 if (__stacksize)
472 *__stacksize = limit;
473 return 0;
474}
475
sewardja3be12f2002-06-17 12:19:44 +0000476int pthread_attr_setschedpolicy(pthread_attr_t *attr, int policy)
477{
478 if (policy != SCHED_OTHER && policy != SCHED_FIFO && policy != SCHED_RR)
479 return EINVAL;
480 attr->__schedpolicy = policy;
481 return 0;
482}
483
484int pthread_attr_getschedpolicy(const pthread_attr_t *attr, int *policy)
485{
486 *policy = attr->__schedpolicy;
487 return 0;
488}
489
490
sewardj111b14c2002-10-20 16:22:57 +0000491/* This is completely bogus. We reject all attempts to change it from
492 VKI_BYTES_PER_PAGE. I don't have a clue what it's for so it seems
493 safest to be paranoid. */
sewardj11f0bb42003-04-26 20:11:15 +0000494WEAK
sewardj111b14c2002-10-20 16:22:57 +0000495int pthread_attr_setguardsize(pthread_attr_t *attr, size_t guardsize)
496{
497 static int moans = N_MOANS;
498
499 if (guardsize == VKI_BYTES_PER_PAGE)
500 return 0;
501
502 if (moans-- > 0)
503 ignored("pthread_attr_setguardsize: ignoring guardsize != 4096");
504
505 return 0;
506}
507
508/* A straight copy of the LinuxThreads code. */
sewardj11f0bb42003-04-26 20:11:15 +0000509WEAK
sewardj111b14c2002-10-20 16:22:57 +0000510int pthread_attr_getguardsize(const pthread_attr_t *attr, size_t *guardsize)
511{
512 *guardsize = attr->__guardsize;
513 return 0;
514}
515
sewardjab2e1232002-12-26 12:16:11 +0000516/* Again, like LinuxThreads. */
517
518static int concurrency_current_level = 0;
519
sewardj11f0bb42003-04-26 20:11:15 +0000520WEAK
sewardjb34e4db2002-12-08 23:51:32 +0000521int pthread_setconcurrency(int new_level)
522{
523 if (new_level < 0)
524 return EINVAL;
sewardjab2e1232002-12-26 12:16:11 +0000525 else {
526 concurrency_current_level = new_level;
sewardjb34e4db2002-12-08 23:51:32 +0000527 return 0;
sewardjab2e1232002-12-26 12:16:11 +0000528 }
sewardjb34e4db2002-12-08 23:51:32 +0000529}
530
sewardj11f0bb42003-04-26 20:11:15 +0000531WEAK
sewardjab2e1232002-12-26 12:16:11 +0000532int pthread_getconcurrency(void)
533{
534 return concurrency_current_level;
535}
536
537
sewardj111b14c2002-10-20 16:22:57 +0000538
sewardj20917d82002-05-28 01:36:45 +0000539/* ---------------------------------------------------
540 Helper functions for running a thread
541 and for clearing up afterwards.
542 ------------------------------------------------ */
543
544/* All exiting threads eventually pass through here, bearing the
545 return value, or PTHREAD_CANCELED, in ret_val. */
546static
547__attribute__((noreturn))
548void thread_exit_wrapper ( void* ret_val )
549{
sewardj870497a2002-05-29 01:06:47 +0000550 int detached, res;
551 CleanupEntry cu;
552 pthread_key_t key;
sewardj00a66b12002-10-12 16:42:35 +0000553 void** specifics_ptr;
sewardj870497a2002-05-29 01:06:47 +0000554
sewardj20917d82002-05-28 01:36:45 +0000555 /* Run this thread's cleanup handlers. */
sewardj8ad94e12002-05-29 00:10:20 +0000556 while (1) {
557 VALGRIND_MAGIC_SEQUENCE(res, (-1) /* default */,
558 VG_USERREQ__CLEANUP_POP,
559 &cu, 0, 0, 0);
560 if (res == -1) break; /* stack empty */
sewardj2d94c112002-06-03 01:25:54 +0000561 my_assert(res == 0);
sewardj8ad94e12002-05-29 00:10:20 +0000562 if (0) printf("running exit cleanup handler");
563 cu.fn ( cu.arg );
564 }
565
sewardj870497a2002-05-29 01:06:47 +0000566 /* Run this thread's key finalizers. Really this should be run
567 PTHREAD_DESTRUCTOR_ITERATIONS times. */
568 for (key = 0; key < VG_N_THREAD_KEYS; key++) {
569 VALGRIND_MAGIC_SEQUENCE(res, (-2) /* default */,
570 VG_USERREQ__GET_KEY_D_AND_S,
571 key, &cu, 0, 0 );
572 if (res == 0) {
573 /* valid key */
574 if (cu.fn && cu.arg)
575 cu.fn /* destructor for key */
576 ( cu.arg /* specific for key for this thread */ );
577 continue;
578 }
sewardj2d94c112002-06-03 01:25:54 +0000579 my_assert(res == -1);
sewardj870497a2002-05-29 01:06:47 +0000580 }
sewardj20917d82002-05-28 01:36:45 +0000581
sewardj00a66b12002-10-12 16:42:35 +0000582 /* Free up my specifics space, if any. */
583 VALGRIND_MAGIC_SEQUENCE(specifics_ptr, 3 /* default */,
584 VG_USERREQ__PTHREAD_GETSPECIFIC_PTR,
585 pthread_self(), 0, 0, 0);
586 my_assert(specifics_ptr != (void**)3);
587 my_assert(specifics_ptr != (void**)1); /* 1 means invalid thread */
588 if (specifics_ptr != NULL)
589 my_free(specifics_ptr);
590
sewardj20917d82002-05-28 01:36:45 +0000591 /* Decide on my final disposition. */
592 VALGRIND_MAGIC_SEQUENCE(detached, (-1) /* default */,
593 VG_USERREQ__SET_OR_GET_DETACH,
sewardj7989d0c2002-05-28 11:00:01 +0000594 2 /* get */, pthread_self(), 0, 0);
sewardj2d94c112002-06-03 01:25:54 +0000595 my_assert(detached == 0 || detached == 1);
sewardj20917d82002-05-28 01:36:45 +0000596
597 if (detached) {
598 /* Detached; I just quit right now. */
599 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
600 VG_USERREQ__QUIT, 0, 0, 0, 0);
601 } else {
602 /* Not detached; so I wait for a joiner. */
603 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
604 VG_USERREQ__WAIT_JOINER, ret_val, 0, 0, 0);
605 }
606 /* NOTREACHED */
607 barf("thread_exit_wrapper: still alive?!");
608}
609
610
611/* This function is a wrapper function for running a thread. It runs
612 the root function specified in pthread_create, and then, should the
613 root function return a value, it arranges to run the thread's
614 cleanup handlers and exit correctly. */
615
sewardj728a5272002-06-20 10:25:37 +0000616/* Struct used to convey info from pthread_create to thread_wrapper.
617 Must be careful not to pass to the child thread any pointers to
618 objects which might be on the parent's stack. */
sewardj20917d82002-05-28 01:36:45 +0000619typedef
620 struct {
sewardj728a5272002-06-20 10:25:37 +0000621 int attr__detachstate;
sewardj20917d82002-05-28 01:36:45 +0000622 void* (*root_fn) ( void* );
623 void* arg;
624 }
625 NewThreadInfo;
626
627
628/* This is passed to the VG_USERREQ__APPLY_IN_NEW_THREAD and so must
629 not return. Note that this runs in the new thread, not the
630 parent. */
631static
632__attribute__((noreturn))
633void thread_wrapper ( NewThreadInfo* info )
634{
sewardj728a5272002-06-20 10:25:37 +0000635 int attr__detachstate;
sewardj20917d82002-05-28 01:36:45 +0000636 void* (*root_fn) ( void* );
637 void* arg;
638 void* ret_val;
639
sewardj728a5272002-06-20 10:25:37 +0000640 attr__detachstate = info->attr__detachstate;
641 root_fn = info->root_fn;
642 arg = info->arg;
sewardj20917d82002-05-28 01:36:45 +0000643
sewardj20917d82002-05-28 01:36:45 +0000644 /* Free up the arg block that pthread_create malloced. */
sewardj00a66b12002-10-12 16:42:35 +0000645 my_free(info);
sewardj20917d82002-05-28 01:36:45 +0000646
sewardj7989d0c2002-05-28 11:00:01 +0000647 /* Minimally observe the attributes supplied. */
sewardj728a5272002-06-20 10:25:37 +0000648 if (attr__detachstate != PTHREAD_CREATE_DETACHED
649 && attr__detachstate != PTHREAD_CREATE_JOINABLE)
650 pthread_error("thread_wrapper: invalid attr->__detachstate");
651 if (attr__detachstate == PTHREAD_CREATE_DETACHED)
652 pthread_detach(pthread_self());
sewardj7989d0c2002-05-28 11:00:01 +0000653
sewardj00a66b12002-10-12 16:42:35 +0000654# ifdef GLIBC_2_3
655 /* Set this thread's locale to the global (default) locale. A hack
656 in support of glibc-2.3. This does the biz for the all new
657 threads; the root thread is done with a horrible hack in
658 init_libc_tsd_keys() below.
659 */
660 __uselocale(LC_GLOBAL_LOCALE);
661# endif
662
sewardj20917d82002-05-28 01:36:45 +0000663 /* The root function might not return. But if it does we simply
664 move along to thread_exit_wrapper. All other ways out for the
665 thread (cancellation, or calling pthread_exit) lead there
666 too. */
667 ret_val = root_fn(arg);
668 thread_exit_wrapper(ret_val);
669 /* NOTREACHED */
670}
671
672
sewardjf8f819e2002-04-17 23:21:37 +0000673/* ---------------------------------------------------
674 THREADs
675 ------------------------------------------------ */
676
sewardj11f0bb42003-04-26 20:11:15 +0000677WEAK
sewardjff42d1d2002-05-22 13:17:31 +0000678int pthread_yield ( void )
679{
680 int res;
681 ensure_valgrind("pthread_yield");
682 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
683 VG_USERREQ__PTHREAD_YIELD, 0, 0, 0, 0);
684 return 0;
685}
686
687
sewardj6072c362002-04-19 14:40:57 +0000688int pthread_equal(pthread_t thread1, pthread_t thread2)
689{
690 return thread1 == thread2 ? 1 : 0;
691}
692
693
sewardj20917d82002-05-28 01:36:45 +0000694/* Bundle up the args into a malloc'd block and create a new thread
695 consisting of thread_wrapper() applied to said malloc'd block. */
sewardje663cb92002-04-12 10:26:32 +0000696int
sewardj1462c8b2002-07-24 09:41:52 +0000697pthread_create (pthread_t *__restrict __thredd,
sewardje663cb92002-04-12 10:26:32 +0000698 __const pthread_attr_t *__restrict __attr,
699 void *(*__start_routine) (void *),
700 void *__restrict __arg)
701{
sewardj20917d82002-05-28 01:36:45 +0000702 int tid_child;
703 NewThreadInfo* info;
sewardje663cb92002-04-12 10:26:32 +0000704
sewardj20917d82002-05-28 01:36:45 +0000705 ensure_valgrind("pthread_create");
706
sewardj00a66b12002-10-12 16:42:35 +0000707 /* make sure the tsd keys, and hence locale info, are initialised
708 before we get into complications making new threads. */
709 init_libc_tsd_keys();
710
sewardj20917d82002-05-28 01:36:45 +0000711 /* Allocate space for the arg block. thread_wrapper will free
712 it. */
sewardj00a66b12002-10-12 16:42:35 +0000713 info = my_malloc(sizeof(NewThreadInfo));
sewardj2d94c112002-06-03 01:25:54 +0000714 my_assert(info != NULL);
sewardj20917d82002-05-28 01:36:45 +0000715
sewardj728a5272002-06-20 10:25:37 +0000716 if (__attr)
717 info->attr__detachstate = __attr->__detachstate;
718 else
719 info->attr__detachstate = PTHREAD_CREATE_JOINABLE;
720
sewardj20917d82002-05-28 01:36:45 +0000721 info->root_fn = __start_routine;
722 info->arg = __arg;
723 VALGRIND_MAGIC_SEQUENCE(tid_child, VG_INVALID_THREADID /* default */,
724 VG_USERREQ__APPLY_IN_NEW_THREAD,
725 &thread_wrapper, info, 0, 0);
sewardj2d94c112002-06-03 01:25:54 +0000726 my_assert(tid_child != VG_INVALID_THREADID);
sewardj20917d82002-05-28 01:36:45 +0000727
sewardj1462c8b2002-07-24 09:41:52 +0000728 if (__thredd)
729 *__thredd = tid_child;
sewardj20917d82002-05-28 01:36:45 +0000730 return 0; /* success */
731}
sewardje663cb92002-04-12 10:26:32 +0000732
733
734int
735pthread_join (pthread_t __th, void **__thread_return)
736{
737 int res;
738 ensure_valgrind("pthread_join");
739 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
740 VG_USERREQ__PTHREAD_JOIN,
741 __th, __thread_return, 0, 0);
742 return res;
743}
744
745
sewardj3b5d8862002-04-20 13:53:23 +0000746void pthread_exit(void *retval)
747{
sewardj3b5d8862002-04-20 13:53:23 +0000748 ensure_valgrind("pthread_exit");
sewardj20917d82002-05-28 01:36:45 +0000749 /* Simple! */
750 thread_exit_wrapper(retval);
sewardj3b5d8862002-04-20 13:53:23 +0000751}
752
sewardje663cb92002-04-12 10:26:32 +0000753
sewardj853f55d2002-04-26 00:27:53 +0000754int pthread_detach(pthread_t th)
755{
sewardj20917d82002-05-28 01:36:45 +0000756 int res;
757 ensure_valgrind("pthread_detach");
sewardj7989d0c2002-05-28 11:00:01 +0000758 /* First we enquire as to the current detach state. */
759 VALGRIND_MAGIC_SEQUENCE(res, (-2) /* default */,
sewardj20917d82002-05-28 01:36:45 +0000760 VG_USERREQ__SET_OR_GET_DETACH,
sewardj7989d0c2002-05-28 11:00:01 +0000761 2 /* get */, th, 0, 0);
sewardj4dced352002-06-04 22:54:20 +0000762 if (res == -1) {
763 /* not found */
764 pthread_error("pthread_detach: "
765 "invalid target thread");
sewardj7989d0c2002-05-28 11:00:01 +0000766 return ESRCH;
sewardj4dced352002-06-04 22:54:20 +0000767 }
768 if (res == 1) {
769 /* already detached */
770 pthread_error("pthread_detach: "
771 "target thread is already detached");
sewardj7989d0c2002-05-28 11:00:01 +0000772 return EINVAL;
sewardj4dced352002-06-04 22:54:20 +0000773 }
sewardj7989d0c2002-05-28 11:00:01 +0000774 if (res == 0) {
775 VALGRIND_MAGIC_SEQUENCE(res, (-2) /* default */,
776 VG_USERREQ__SET_OR_GET_DETACH,
777 1 /* set */, th, 0, 0);
sewardj2d94c112002-06-03 01:25:54 +0000778 my_assert(res == 0);
sewardj7989d0c2002-05-28 11:00:01 +0000779 return 0;
780 }
781 barf("pthread_detach");
sewardj853f55d2002-04-26 00:27:53 +0000782}
783
784
sewardjf8f819e2002-04-17 23:21:37 +0000785/* ---------------------------------------------------
sewardj8ad94e12002-05-29 00:10:20 +0000786 CLEANUP STACKS
787 ------------------------------------------------ */
788
789void _pthread_cleanup_push (struct _pthread_cleanup_buffer *__buffer,
790 void (*__routine) (void *),
791 void *__arg)
792{
793 int res;
794 CleanupEntry cu;
795 ensure_valgrind("_pthread_cleanup_push");
796 cu.fn = __routine;
797 cu.arg = __arg;
798 VALGRIND_MAGIC_SEQUENCE(res, (-1) /* default */,
799 VG_USERREQ__CLEANUP_PUSH,
800 &cu, 0, 0, 0);
sewardj2d94c112002-06-03 01:25:54 +0000801 my_assert(res == 0);
sewardj8ad94e12002-05-29 00:10:20 +0000802}
803
804
805void _pthread_cleanup_push_defer (struct _pthread_cleanup_buffer *__buffer,
806 void (*__routine) (void *),
807 void *__arg)
808{
809 /* As _pthread_cleanup_push, but first save the thread's original
810 cancellation type in __buffer and set it to Deferred. */
811 int orig_ctype;
812 ensure_valgrind("_pthread_cleanup_push_defer");
813 /* Set to Deferred, and put the old cancellation type in res. */
sewardj2d94c112002-06-03 01:25:54 +0000814 my_assert(-1 != PTHREAD_CANCEL_DEFERRED);
815 my_assert(-1 != PTHREAD_CANCEL_ASYNCHRONOUS);
816 my_assert(sizeof(struct _pthread_cleanup_buffer) >= sizeof(int));
sewardj8ad94e12002-05-29 00:10:20 +0000817 VALGRIND_MAGIC_SEQUENCE(orig_ctype, (-1) /* default */,
818 VG_USERREQ__SET_CANCELTYPE,
819 PTHREAD_CANCEL_DEFERRED, 0, 0, 0);
sewardj2d94c112002-06-03 01:25:54 +0000820 my_assert(orig_ctype != -1);
sewardj8ad94e12002-05-29 00:10:20 +0000821 *((int*)(__buffer)) = orig_ctype;
822 /* Now push the cleanup. */
823 _pthread_cleanup_push(NULL, __routine, __arg);
824}
825
826
827void _pthread_cleanup_pop (struct _pthread_cleanup_buffer *__buffer,
828 int __execute)
829{
830 int res;
831 CleanupEntry cu;
832 ensure_valgrind("_pthread_cleanup_push");
833 cu.fn = cu.arg = NULL; /* paranoia */
834 VALGRIND_MAGIC_SEQUENCE(res, (-1) /* default */,
835 VG_USERREQ__CLEANUP_POP,
836 &cu, 0, 0, 0);
837 if (res == 0) {
838 /* pop succeeded */
839 if (__execute) {
840 cu.fn ( cu.arg );
841 }
842 return;
843 }
844 if (res == -1) {
845 /* stack underflow */
846 return;
847 }
848 barf("_pthread_cleanup_pop");
849}
850
851
852void _pthread_cleanup_pop_restore (struct _pthread_cleanup_buffer *__buffer,
853 int __execute)
854{
855 int orig_ctype, fake_ctype;
856 /* As _pthread_cleanup_pop, but after popping/running the handler,
857 restore the thread's original cancellation type from the first
858 word of __buffer. */
859 _pthread_cleanup_pop(NULL, __execute);
860 orig_ctype = *((int*)(__buffer));
sewardj2d94c112002-06-03 01:25:54 +0000861 my_assert(orig_ctype == PTHREAD_CANCEL_DEFERRED
sewardj8ad94e12002-05-29 00:10:20 +0000862 || orig_ctype == PTHREAD_CANCEL_ASYNCHRONOUS);
sewardj2d94c112002-06-03 01:25:54 +0000863 my_assert(-1 != PTHREAD_CANCEL_DEFERRED);
864 my_assert(-1 != PTHREAD_CANCEL_ASYNCHRONOUS);
865 my_assert(sizeof(struct _pthread_cleanup_buffer) >= sizeof(int));
sewardj8ad94e12002-05-29 00:10:20 +0000866 VALGRIND_MAGIC_SEQUENCE(fake_ctype, (-1) /* default */,
867 VG_USERREQ__SET_CANCELTYPE,
868 orig_ctype, 0, 0, 0);
sewardj2d94c112002-06-03 01:25:54 +0000869 my_assert(fake_ctype == PTHREAD_CANCEL_DEFERRED);
sewardj8ad94e12002-05-29 00:10:20 +0000870}
871
872
873/* ---------------------------------------------------
sewardjf8f819e2002-04-17 23:21:37 +0000874 MUTEX ATTRIBUTES
875 ------------------------------------------------ */
876
sewardj5905fae2002-04-26 13:25:00 +0000877int __pthread_mutexattr_init(pthread_mutexattr_t *attr)
sewardje663cb92002-04-12 10:26:32 +0000878{
sewardjf8f819e2002-04-17 23:21:37 +0000879 attr->__mutexkind = PTHREAD_MUTEX_ERRORCHECK_NP;
sewardj8937c812002-04-12 20:12:20 +0000880 return 0;
sewardje663cb92002-04-12 10:26:32 +0000881}
882
sewardj5905fae2002-04-26 13:25:00 +0000883int __pthread_mutexattr_settype(pthread_mutexattr_t *attr, int type)
sewardjf8f819e2002-04-17 23:21:37 +0000884{
885 switch (type) {
sewardj3b13f0e2002-04-25 20:17:29 +0000886# ifndef GLIBC_2_1
sewardjf8f819e2002-04-17 23:21:37 +0000887 case PTHREAD_MUTEX_TIMED_NP:
sewardj2a1dcce2002-04-22 12:45:25 +0000888 case PTHREAD_MUTEX_ADAPTIVE_NP:
sewardj3b13f0e2002-04-25 20:17:29 +0000889# endif
sewardja1679dd2002-05-10 22:31:40 +0000890# ifdef GLIBC_2_1
sewardj68b2dd92002-05-10 21:03:56 +0000891 case PTHREAD_MUTEX_FAST_NP:
sewardja1679dd2002-05-10 22:31:40 +0000892# endif
sewardjf8f819e2002-04-17 23:21:37 +0000893 case PTHREAD_MUTEX_RECURSIVE_NP:
894 case PTHREAD_MUTEX_ERRORCHECK_NP:
sewardjf8f819e2002-04-17 23:21:37 +0000895 attr->__mutexkind = type;
896 return 0;
897 default:
sewardj4dced352002-06-04 22:54:20 +0000898 pthread_error("pthread_mutexattr_settype: "
899 "invalid type");
sewardjf8f819e2002-04-17 23:21:37 +0000900 return EINVAL;
901 }
902}
903
sewardj5905fae2002-04-26 13:25:00 +0000904int __pthread_mutexattr_destroy(pthread_mutexattr_t *attr)
sewardjf8f819e2002-04-17 23:21:37 +0000905{
906 return 0;
907}
908
909
910/* ---------------------------------------------------
911 MUTEXes
912 ------------------------------------------------ */
913
sewardj5905fae2002-04-26 13:25:00 +0000914int __pthread_mutex_init(pthread_mutex_t *mutex,
915 const pthread_mutexattr_t *mutexattr)
sewardje663cb92002-04-12 10:26:32 +0000916{
sewardj604ec3c2002-04-18 22:38:41 +0000917 mutex->__m_count = 0;
918 mutex->__m_owner = (_pthread_descr)VG_INVALID_THREADID;
919 mutex->__m_kind = PTHREAD_MUTEX_ERRORCHECK_NP;
920 if (mutexattr)
921 mutex->__m_kind = mutexattr->__mutexkind;
922 return 0;
sewardje663cb92002-04-12 10:26:32 +0000923}
924
sewardj439d45e2002-05-03 20:43:10 +0000925
sewardj5905fae2002-04-26 13:25:00 +0000926int __pthread_mutex_lock(pthread_mutex_t *mutex)
sewardje663cb92002-04-12 10:26:32 +0000927{
928 int res;
sewardjd8acdf22002-11-13 21:57:52 +0000929
sewardj439d45e2002-05-03 20:43:10 +0000930 if (RUNNING_ON_VALGRIND) {
sewardje663cb92002-04-12 10:26:32 +0000931 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
932 VG_USERREQ__PTHREAD_MUTEX_LOCK,
933 mutex, 0, 0, 0);
934 return res;
sewardj439d45e2002-05-03 20:43:10 +0000935 } else {
sewardjd8acdf22002-11-13 21:57:52 +0000936 /* Play at locking */
937 if (0)
938 kludged("prehistoric lock");
939 mutex->__m_owner = (_pthread_descr)1;
940 mutex->__m_count = 1;
941 mutex->__m_kind |= VG_PTHREAD_PREHISTORY;
sewardj439d45e2002-05-03 20:43:10 +0000942 return 0; /* success */
sewardje663cb92002-04-12 10:26:32 +0000943 }
944}
945
sewardj439d45e2002-05-03 20:43:10 +0000946
sewardj5905fae2002-04-26 13:25:00 +0000947int __pthread_mutex_trylock(pthread_mutex_t *mutex)
sewardj30671ff2002-04-21 00:13:57 +0000948{
949 int res;
sewardjd8acdf22002-11-13 21:57:52 +0000950
sewardj439d45e2002-05-03 20:43:10 +0000951 if (RUNNING_ON_VALGRIND) {
sewardj30671ff2002-04-21 00:13:57 +0000952 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
953 VG_USERREQ__PTHREAD_MUTEX_TRYLOCK,
954 mutex, 0, 0, 0);
955 return res;
sewardj439d45e2002-05-03 20:43:10 +0000956 } else {
sewardjd8acdf22002-11-13 21:57:52 +0000957 /* Play at locking */
958 if (0)
959 kludged("prehistoric trylock");
960 mutex->__m_owner = (_pthread_descr)1;
961 mutex->__m_count = 1;
962 mutex->__m_kind |= VG_PTHREAD_PREHISTORY;
963 return 0; /* success */
sewardj30671ff2002-04-21 00:13:57 +0000964 }
965}
966
sewardj439d45e2002-05-03 20:43:10 +0000967
sewardj5905fae2002-04-26 13:25:00 +0000968int __pthread_mutex_unlock(pthread_mutex_t *mutex)
sewardje663cb92002-04-12 10:26:32 +0000969{
970 int res;
sewardjd8acdf22002-11-13 21:57:52 +0000971
sewardj439d45e2002-05-03 20:43:10 +0000972 if (RUNNING_ON_VALGRIND) {
sewardje663cb92002-04-12 10:26:32 +0000973 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
974 VG_USERREQ__PTHREAD_MUTEX_UNLOCK,
975 mutex, 0, 0, 0);
976 return res;
sewardj439d45e2002-05-03 20:43:10 +0000977 } else {
sewardjd8acdf22002-11-13 21:57:52 +0000978 /* Play at locking */
979 if (0)
980 kludged("prehistoric unlock");
981 mutex->__m_owner = 0;
982 mutex->__m_count = 0;
983 mutex->__m_kind &= ~VG_PTHREAD_PREHISTORY;
984 return 0; /* success */
sewardje663cb92002-04-12 10:26:32 +0000985 }
986}
987
sewardj439d45e2002-05-03 20:43:10 +0000988
sewardj5905fae2002-04-26 13:25:00 +0000989int __pthread_mutex_destroy(pthread_mutex_t *mutex)
sewardje663cb92002-04-12 10:26:32 +0000990{
sewardj604ec3c2002-04-18 22:38:41 +0000991 /* Valgrind doesn't hold any resources on behalf of the mutex, so no
992 need to involve it. */
sewardj4dced352002-06-04 22:54:20 +0000993 if (mutex->__m_count > 0) {
sewardjd8acdf22002-11-13 21:57:52 +0000994 /* Oh, the horror. glibc's internal use of pthreads "knows"
995 that destroying a lock does an implicit unlock. Make it
996 explicit. */
997 __pthread_mutex_unlock(mutex);
998 pthread_error("pthread_mutex_destroy: "
999 "mutex is still in use");
1000 return EBUSY;
sewardj4dced352002-06-04 22:54:20 +00001001 }
1002 mutex->__m_count = 0;
1003 mutex->__m_owner = (_pthread_descr)VG_INVALID_THREADID;
1004 mutex->__m_kind = PTHREAD_MUTEX_ERRORCHECK_NP;
1005 return 0;
sewardje663cb92002-04-12 10:26:32 +00001006}
1007
1008
sewardjf8f819e2002-04-17 23:21:37 +00001009/* ---------------------------------------------------
sewardj6072c362002-04-19 14:40:57 +00001010 CONDITION VARIABLES
1011 ------------------------------------------------ */
1012
1013/* LinuxThreads supports no attributes for conditions. Hence ... */
1014
1015int pthread_condattr_init(pthread_condattr_t *attr)
1016{
1017 return 0;
1018}
1019
sewardj0738a592002-04-20 13:59:33 +00001020int pthread_condattr_destroy(pthread_condattr_t *attr)
1021{
1022 return 0;
1023}
sewardj6072c362002-04-19 14:40:57 +00001024
1025int pthread_cond_init( pthread_cond_t *cond,
1026 const pthread_condattr_t *cond_attr)
1027{
1028 cond->__c_waiting = (_pthread_descr)VG_INVALID_THREADID;
1029 return 0;
1030}
1031
sewardjf854f472002-04-21 12:19:41 +00001032int pthread_cond_destroy(pthread_cond_t *cond)
1033{
1034 /* should check that no threads are waiting on this CV */
sewardj436e0582002-04-26 14:31:40 +00001035 static int moans = N_MOANS;
1036 if (moans-- > 0)
1037 kludged("pthread_cond_destroy");
sewardjf854f472002-04-21 12:19:41 +00001038 return 0;
1039}
sewardj6072c362002-04-19 14:40:57 +00001040
1041/* ---------------------------------------------------
1042 SCHEDULING
1043 ------------------------------------------------ */
1044
1045/* This is completely bogus. */
1046int pthread_getschedparam(pthread_t target_thread,
1047 int *policy,
1048 struct sched_param *param)
1049{
sewardj436e0582002-04-26 14:31:40 +00001050 static int moans = N_MOANS;
1051 if (moans-- > 0)
1052 kludged("pthread_getschedparam");
sewardj6072c362002-04-19 14:40:57 +00001053 if (policy) *policy = SCHED_OTHER;
sewardj3e909ce2002-06-03 13:27:15 +00001054# ifdef HAVE_SCHED_PRIORITY
sewardj2a1dcce2002-04-22 12:45:25 +00001055 if (param) param->sched_priority = 0; /* who knows */
1056# else
sewardj6072c362002-04-19 14:40:57 +00001057 if (param) param->__sched_priority = 0; /* who knows */
sewardj2a1dcce2002-04-22 12:45:25 +00001058# endif
sewardj6072c362002-04-19 14:40:57 +00001059 return 0;
1060}
1061
1062int pthread_setschedparam(pthread_t target_thread,
1063 int policy,
1064 const struct sched_param *param)
1065{
sewardj436e0582002-04-26 14:31:40 +00001066 static int moans = N_MOANS;
1067 if (moans-- > 0)
1068 ignored("pthread_setschedparam");
sewardj6072c362002-04-19 14:40:57 +00001069 return 0;
1070}
1071
sewardj3b5d8862002-04-20 13:53:23 +00001072int pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex)
1073{
1074 int res;
1075 ensure_valgrind("pthread_cond_wait");
1076 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
1077 VG_USERREQ__PTHREAD_COND_WAIT,
1078 cond, mutex, 0, 0);
1079 return res;
1080}
1081
sewardj5f07b662002-04-23 16:52:51 +00001082int pthread_cond_timedwait ( pthread_cond_t *cond,
1083 pthread_mutex_t *mutex,
1084 const struct timespec *abstime )
1085{
1086 int res;
1087 unsigned int ms_now, ms_end;
1088 struct timeval timeval_now;
1089 unsigned long long int ull_ms_now_after_1970;
1090 unsigned long long int ull_ms_end_after_1970;
1091
1092 ensure_valgrind("pthread_cond_timedwait");
1093 VALGRIND_MAGIC_SEQUENCE(ms_now, 0xFFFFFFFF /* default */,
1094 VG_USERREQ__READ_MILLISECOND_TIMER,
1095 0, 0, 0, 0);
sewardj2d94c112002-06-03 01:25:54 +00001096 my_assert(ms_now != 0xFFFFFFFF);
sewardj5f07b662002-04-23 16:52:51 +00001097 res = gettimeofday(&timeval_now, NULL);
sewardj2d94c112002-06-03 01:25:54 +00001098 my_assert(res == 0);
sewardj5f07b662002-04-23 16:52:51 +00001099
1100 ull_ms_now_after_1970
1101 = 1000ULL * ((unsigned long long int)(timeval_now.tv_sec))
1102 + ((unsigned long long int)(timeval_now.tv_usec / 1000000));
1103 ull_ms_end_after_1970
1104 = 1000ULL * ((unsigned long long int)(abstime->tv_sec))
1105 + ((unsigned long long int)(abstime->tv_nsec / 1000000));
sewardjd8e919e2002-05-29 20:13:53 +00001106 if (ull_ms_end_after_1970 < ull_ms_now_after_1970)
1107 ull_ms_end_after_1970 = ull_ms_now_after_1970;
sewardj5f07b662002-04-23 16:52:51 +00001108 ms_end
1109 = ms_now + (unsigned int)(ull_ms_end_after_1970 - ull_ms_now_after_1970);
1110 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
1111 VG_USERREQ__PTHREAD_COND_TIMEDWAIT,
1112 cond, mutex, ms_end, 0);
1113 return res;
1114}
1115
1116
sewardj3b5d8862002-04-20 13:53:23 +00001117int pthread_cond_signal(pthread_cond_t *cond)
1118{
1119 int res;
1120 ensure_valgrind("pthread_cond_signal");
1121 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
1122 VG_USERREQ__PTHREAD_COND_SIGNAL,
1123 cond, 0, 0, 0);
1124 return res;
1125}
1126
1127int pthread_cond_broadcast(pthread_cond_t *cond)
1128{
1129 int res;
1130 ensure_valgrind("pthread_cond_broadcast");
1131 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
1132 VG_USERREQ__PTHREAD_COND_BROADCAST,
1133 cond, 0, 0, 0);
1134 return res;
1135}
1136
sewardj6072c362002-04-19 14:40:57 +00001137
1138/* ---------------------------------------------------
sewardjf8f819e2002-04-17 23:21:37 +00001139 CANCELLATION
1140 ------------------------------------------------ */
1141
sewardj853f55d2002-04-26 00:27:53 +00001142int pthread_setcancelstate(int state, int *oldstate)
1143{
sewardj20917d82002-05-28 01:36:45 +00001144 int res;
1145 ensure_valgrind("pthread_setcancelstate");
1146 if (state != PTHREAD_CANCEL_ENABLE
sewardj4dced352002-06-04 22:54:20 +00001147 && state != PTHREAD_CANCEL_DISABLE) {
1148 pthread_error("pthread_setcancelstate: "
1149 "invalid state");
sewardj20917d82002-05-28 01:36:45 +00001150 return EINVAL;
sewardj4dced352002-06-04 22:54:20 +00001151 }
sewardj2d94c112002-06-03 01:25:54 +00001152 my_assert(-1 != PTHREAD_CANCEL_ENABLE);
1153 my_assert(-1 != PTHREAD_CANCEL_DISABLE);
sewardj20917d82002-05-28 01:36:45 +00001154 VALGRIND_MAGIC_SEQUENCE(res, (-1) /* default */,
1155 VG_USERREQ__SET_CANCELSTATE,
1156 state, 0, 0, 0);
sewardj2d94c112002-06-03 01:25:54 +00001157 my_assert(res != -1);
sewardj20917d82002-05-28 01:36:45 +00001158 if (oldstate)
1159 *oldstate = res;
sewardj853f55d2002-04-26 00:27:53 +00001160 return 0;
1161}
1162
sewardje663cb92002-04-12 10:26:32 +00001163int pthread_setcanceltype(int type, int *oldtype)
1164{
sewardj20917d82002-05-28 01:36:45 +00001165 int res;
1166 ensure_valgrind("pthread_setcanceltype");
1167 if (type != PTHREAD_CANCEL_DEFERRED
sewardj4dced352002-06-04 22:54:20 +00001168 && type != PTHREAD_CANCEL_ASYNCHRONOUS) {
1169 pthread_error("pthread_setcanceltype: "
1170 "invalid type");
sewardj20917d82002-05-28 01:36:45 +00001171 return EINVAL;
sewardj4dced352002-06-04 22:54:20 +00001172 }
sewardj2d94c112002-06-03 01:25:54 +00001173 my_assert(-1 != PTHREAD_CANCEL_DEFERRED);
1174 my_assert(-1 != PTHREAD_CANCEL_ASYNCHRONOUS);
sewardj20917d82002-05-28 01:36:45 +00001175 VALGRIND_MAGIC_SEQUENCE(res, (-1) /* default */,
1176 VG_USERREQ__SET_CANCELTYPE,
1177 type, 0, 0, 0);
sewardj2d94c112002-06-03 01:25:54 +00001178 my_assert(res != -1);
sewardj20917d82002-05-28 01:36:45 +00001179 if (oldtype)
1180 *oldtype = res;
sewardje663cb92002-04-12 10:26:32 +00001181 return 0;
1182}
1183
sewardje663cb92002-04-12 10:26:32 +00001184int pthread_cancel(pthread_t thread)
1185{
1186 int res;
1187 ensure_valgrind("pthread_cancel");
sewardj20917d82002-05-28 01:36:45 +00001188 VALGRIND_MAGIC_SEQUENCE(res, (-1) /* default */,
1189 VG_USERREQ__SET_CANCELPEND,
1190 thread, &thread_exit_wrapper, 0, 0);
sewardj2d94c112002-06-03 01:25:54 +00001191 my_assert(res != -1);
sewardje663cb92002-04-12 10:26:32 +00001192 return res;
1193}
1194
sewardjd140e442002-05-29 01:21:19 +00001195static __inline__
1196void __my_pthread_testcancel(void)
sewardj853f55d2002-04-26 00:27:53 +00001197{
sewardj20917d82002-05-28 01:36:45 +00001198 int res;
njn25e49d8e72002-09-23 09:36:25 +00001199 ensure_valgrind("__my_pthread_testcancel");
sewardj20917d82002-05-28 01:36:45 +00001200 VALGRIND_MAGIC_SEQUENCE(res, (-1) /* default */,
1201 VG_USERREQ__TESTCANCEL,
1202 0, 0, 0, 0);
sewardj2d94c112002-06-03 01:25:54 +00001203 my_assert(res == 0);
sewardj853f55d2002-04-26 00:27:53 +00001204}
1205
sewardjd140e442002-05-29 01:21:19 +00001206void pthread_testcancel ( void )
1207{
1208 __my_pthread_testcancel();
1209}
1210
sewardj20917d82002-05-28 01:36:45 +00001211
sewardjef037c72002-05-30 00:40:03 +00001212/* Not really sure what this is for. I suspect for doing the POSIX
1213 requirements for fork() and exec(). We do this internally anyway
1214 whenever those syscalls are observed, so this could be superfluous,
1215 but hey ...
1216*/
sewardj853f55d2002-04-26 00:27:53 +00001217void __pthread_kill_other_threads_np ( void )
1218{
sewardjef037c72002-05-30 00:40:03 +00001219 int res;
1220 ensure_valgrind("__pthread_kill_other_threads_np");
1221 VALGRIND_MAGIC_SEQUENCE(res, (-1) /* default */,
1222 VG_USERREQ__NUKE_OTHER_THREADS,
1223 0, 0, 0, 0);
sewardj2d94c112002-06-03 01:25:54 +00001224 my_assert(res == 0);
sewardj853f55d2002-04-26 00:27:53 +00001225}
1226
sewardje663cb92002-04-12 10:26:32 +00001227
sewardjf8f819e2002-04-17 23:21:37 +00001228/* ---------------------------------------------------
sewardjb48e5002002-05-13 00:16:03 +00001229 SIGNALS
1230 ------------------------------------------------ */
1231
1232#include <signal.h>
1233
1234int pthread_sigmask(int how, const sigset_t *newmask,
1235 sigset_t *oldmask)
1236{
1237 int res;
1238
1239 /* A bit subtle, because the scheduler expects newmask and oldmask
1240 to be vki_sigset_t* rather than sigset_t*, and the two are
1241 different. Fortunately the first 64 bits of a sigset_t are
1242 exactly a vki_sigset_t, so we just pass the pointers through
1243 unmodified. Haaaack!
1244
1245 Also mash the how value so that the SIG_ constants from glibc
sewardj018f7622002-05-15 21:13:39 +00001246 constants to VKI_ constants, so that the former do not have to
1247 be included into vg_scheduler.c. */
sewardjb48e5002002-05-13 00:16:03 +00001248
1249 ensure_valgrind("pthread_sigmask");
1250
1251 switch (how) {
sewardj018f7622002-05-15 21:13:39 +00001252 case SIG_SETMASK: how = VKI_SIG_SETMASK; break;
1253 case SIG_BLOCK: how = VKI_SIG_BLOCK; break;
1254 case SIG_UNBLOCK: how = VKI_SIG_UNBLOCK; break;
sewardj4dced352002-06-04 22:54:20 +00001255 default: pthread_error("pthread_sigmask: invalid how");
1256 return EINVAL;
sewardjb48e5002002-05-13 00:16:03 +00001257 }
1258
1259 /* Crude check */
1260 if (newmask == NULL)
1261 return EFAULT;
1262
1263 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
1264 VG_USERREQ__PTHREAD_SIGMASK,
1265 how, newmask, oldmask, 0);
1266
1267 /* The scheduler tells us of any memory violations. */
1268 return res == 0 ? 0 : EFAULT;
1269}
1270
1271
1272int sigwait ( const sigset_t* set, int* sig )
1273{
1274 int res;
1275 ensure_valgrind("sigwait");
1276 /* As with pthread_sigmask we deliberately confuse sigset_t with
1277 vki_ksigset_t. */
1278 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
1279 VG_USERREQ__SIGWAIT,
1280 set, sig, 0, 0);
1281 return res;
1282}
1283
1284
sewardj018f7622002-05-15 21:13:39 +00001285int pthread_kill(pthread_t thread, int signo)
1286{
1287 int res;
1288 ensure_valgrind("pthread_kill");
1289 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
1290 VG_USERREQ__PTHREAD_KILL,
1291 thread, signo, 0, 0);
1292 return res;
1293}
1294
1295
sewardj3665ded2002-05-16 16:57:25 +00001296/* Copied verbatim from Linuxthreads */
1297/* Redefine raise() to send signal to calling thread only,
1298 as per POSIX 1003.1c */
1299int raise (int sig)
1300{
1301 int retcode = pthread_kill(pthread_self(), sig);
sewardj4dced352002-06-04 22:54:20 +00001302 if (retcode == 0) {
sewardj3665ded2002-05-16 16:57:25 +00001303 return 0;
sewardj4dced352002-06-04 22:54:20 +00001304 } else {
sewardj25418ae2003-05-09 23:40:34 +00001305 *(__errno_location()) = retcode;
sewardj3665ded2002-05-16 16:57:25 +00001306 return -1;
1307 }
1308}
1309
1310
sewardj9a2224b2002-06-19 10:17:40 +00001311int pause ( void )
1312{
1313 unsigned int n_orig, n_now;
1314 struct vki_timespec nanosleep_interval;
1315 ensure_valgrind("pause");
1316
1317 /* This is surely a cancellation point. */
1318 __my_pthread_testcancel();
1319
1320 VALGRIND_MAGIC_SEQUENCE(n_orig, 0xFFFFFFFF /* default */,
1321 VG_USERREQ__GET_N_SIGS_RETURNED,
1322 0, 0, 0, 0);
1323 my_assert(n_orig != 0xFFFFFFFF);
1324
1325 while (1) {
1326 VALGRIND_MAGIC_SEQUENCE(n_now, 0xFFFFFFFF /* default */,
1327 VG_USERREQ__GET_N_SIGS_RETURNED,
1328 0, 0, 0, 0);
1329 my_assert(n_now != 0xFFFFFFFF);
1330 my_assert(n_now >= n_orig);
1331 if (n_now != n_orig) break;
1332
1333 nanosleep_interval.tv_sec = 0;
njn25e49d8e72002-09-23 09:36:25 +00001334 nanosleep_interval.tv_nsec = 12 * 1000 * 1000; /* 12 milliseconds */
sewardj9a2224b2002-06-19 10:17:40 +00001335 /* It's critical here that valgrind's nanosleep implementation
1336 is nonblocking. */
1337 (void)my_do_syscall2(__NR_nanosleep,
1338 (int)(&nanosleep_interval), (int)NULL);
1339 }
1340
sewardj25418ae2003-05-09 23:40:34 +00001341 *(__errno_location()) = EINTR;
sewardj9a2224b2002-06-19 10:17:40 +00001342 return -1;
1343}
1344
1345
sewardjb48e5002002-05-13 00:16:03 +00001346/* ---------------------------------------------------
sewardjf8f819e2002-04-17 23:21:37 +00001347 THREAD-SPECIFICs
1348 ------------------------------------------------ */
sewardj5e5fa512002-04-14 13:13:05 +00001349
sewardj00a66b12002-10-12 16:42:35 +00001350static
1351int key_is_valid (pthread_key_t key)
1352{
1353 int res;
1354 VALGRIND_MAGIC_SEQUENCE(res, 2 /* default */,
1355 VG_USERREQ__PTHREAD_KEY_VALIDATE,
1356 key, 0, 0, 0);
1357 my_assert(res != 2);
1358 return res;
1359}
1360
1361
1362/* Returns NULL if thread is invalid. Otherwise, if the thread
1363 already has a specifics area, return that. Otherwise allocate it
1364 one. */
1365static
1366void** get_or_allocate_specifics_ptr ( pthread_t thread )
1367{
1368 int res, i;
1369 void** specifics_ptr;
1370 ensure_valgrind("get_or_allocate_specifics_ptr");
1371
1372 /* Returns zero if the thread has no specific_ptr. One if thread
1373 is invalid. Otherwise, the specific_ptr value. This is
1374 allocated with my_malloc and so is aligned and cannot be
1375 confused with 1 or 3. */
1376 VALGRIND_MAGIC_SEQUENCE(specifics_ptr, 3 /* default */,
1377 VG_USERREQ__PTHREAD_GETSPECIFIC_PTR,
1378 thread, 0, 0, 0);
1379 my_assert(specifics_ptr != (void**)3);
1380
1381 if (specifics_ptr == (void**)1)
1382 return NULL; /* invalid thread */
1383
1384 if (specifics_ptr != NULL)
1385 return specifics_ptr; /* already has a specifics ptr. */
1386
1387 /* None yet ... allocate a new one. Should never fail. */
1388 specifics_ptr = my_malloc( VG_N_THREAD_KEYS * sizeof(void*) );
1389 my_assert(specifics_ptr != NULL);
1390
1391 VALGRIND_MAGIC_SEQUENCE(res, -1 /* default */,
1392 VG_USERREQ__PTHREAD_SETSPECIFIC_PTR,
1393 specifics_ptr, 0, 0, 0);
1394 my_assert(res == 0);
1395
1396 /* POSIX sez: "Upon thread creation, the value NULL shall be
1397 associated with all defined keys in the new thread." This
1398 allocation is in effect a delayed allocation of the specific
1399 data for a thread, at its first-use. Hence we initialise it
1400 here. */
1401 for (i = 0; i < VG_N_THREAD_KEYS; i++) {
1402 specifics_ptr[i] = NULL;
1403 }
1404
1405 return specifics_ptr;
1406}
1407
1408
sewardj5905fae2002-04-26 13:25:00 +00001409int __pthread_key_create(pthread_key_t *key,
1410 void (*destr_function) (void *))
sewardj5e5fa512002-04-14 13:13:05 +00001411{
sewardj00a66b12002-10-12 16:42:35 +00001412 void** specifics_ptr;
1413 int res, i;
sewardj5f07b662002-04-23 16:52:51 +00001414 ensure_valgrind("pthread_key_create");
sewardj00a66b12002-10-12 16:42:35 +00001415
1416 /* This writes *key if successful. It should never fail. */
1417 VALGRIND_MAGIC_SEQUENCE(res, 1 /* default */,
sewardj5f07b662002-04-23 16:52:51 +00001418 VG_USERREQ__PTHREAD_KEY_CREATE,
1419 key, destr_function, 0, 0);
sewardj00a66b12002-10-12 16:42:35 +00001420 my_assert(res == 0);
1421
1422 /* POSIX sez: "Upon key creation, the value NULL shall be
1423 associated with the new key in all active threads." */
1424 for (i = 0; i < VG_N_THREADS; i++) {
1425 specifics_ptr = get_or_allocate_specifics_ptr(i);
1426 /* we get NULL if i is an invalid thread. */
1427 if (specifics_ptr != NULL)
1428 specifics_ptr[*key] = NULL;
1429 }
1430
sewardj5f07b662002-04-23 16:52:51 +00001431 return res;
sewardj5e5fa512002-04-14 13:13:05 +00001432}
1433
1434int pthread_key_delete(pthread_key_t key)
1435{
sewardj00a66b12002-10-12 16:42:35 +00001436 int res;
1437 ensure_valgrind("pthread_key_create");
1438 if (!key_is_valid(key))
1439 return EINVAL;
1440 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
1441 VG_USERREQ__PTHREAD_KEY_DELETE,
1442 key, 0, 0, 0);
1443 my_assert(res == 0);
sewardj5e5fa512002-04-14 13:13:05 +00001444 return 0;
1445}
1446
sewardj5905fae2002-04-26 13:25:00 +00001447int __pthread_setspecific(pthread_key_t key, const void *pointer)
sewardj5e5fa512002-04-14 13:13:05 +00001448{
sewardj00a66b12002-10-12 16:42:35 +00001449 void** specifics_ptr;
sewardj5f07b662002-04-23 16:52:51 +00001450 ensure_valgrind("pthread_setspecific");
sewardj00a66b12002-10-12 16:42:35 +00001451
1452 if (!key_is_valid(key))
1453 return EINVAL;
1454
1455 specifics_ptr = get_or_allocate_specifics_ptr(pthread_self());
1456 specifics_ptr[key] = (void*)pointer;
1457 return 0;
sewardj5e5fa512002-04-14 13:13:05 +00001458}
1459
sewardj5905fae2002-04-26 13:25:00 +00001460void * __pthread_getspecific(pthread_key_t key)
sewardj5e5fa512002-04-14 13:13:05 +00001461{
sewardj00a66b12002-10-12 16:42:35 +00001462 void** specifics_ptr;
sewardj5f07b662002-04-23 16:52:51 +00001463 ensure_valgrind("pthread_getspecific");
sewardj00a66b12002-10-12 16:42:35 +00001464
1465 if (!key_is_valid(key))
1466 return NULL;
1467
1468 specifics_ptr = get_or_allocate_specifics_ptr(pthread_self());
1469 return specifics_ptr[key];
1470}
1471
1472
sewardj9aa918d2002-10-20 16:25:55 +00001473#ifdef GLIBC_2_3
sewardj00a66b12002-10-12 16:42:35 +00001474static
1475void ** __pthread_getspecific_addr(pthread_key_t key)
1476{
1477 void** specifics_ptr;
1478 ensure_valgrind("pthread_getspecific_addr");
1479
1480 if (!key_is_valid(key))
1481 return NULL;
1482
1483 specifics_ptr = get_or_allocate_specifics_ptr(pthread_self());
1484 return &(specifics_ptr[key]);
sewardj5e5fa512002-04-14 13:13:05 +00001485}
sewardj9aa918d2002-10-20 16:25:55 +00001486#endif
sewardjf8f819e2002-04-17 23:21:37 +00001487
1488/* ---------------------------------------------------
sewardj89d3d852002-04-24 19:21:39 +00001489 ONCEry
1490 ------------------------------------------------ */
1491
1492static pthread_mutex_t once_masterlock = PTHREAD_MUTEX_INITIALIZER;
1493
1494
sewardj5905fae2002-04-26 13:25:00 +00001495int __pthread_once ( pthread_once_t *once_control,
1496 void (*init_routine) (void) )
sewardj89d3d852002-04-24 19:21:39 +00001497{
1498 int res;
1499 ensure_valgrind("pthread_once");
1500
sewardj68b2dd92002-05-10 21:03:56 +00001501 res = __pthread_mutex_lock(&once_masterlock);
sewardj89d3d852002-04-24 19:21:39 +00001502
daywalkerfd7c2312003-06-13 12:24:41 +00001503 /* init routine called us again ? */
1504 if (res != 0)
1505 return 0;
sewardj89d3d852002-04-24 19:21:39 +00001506
1507 if (*once_control == 0) {
1508 *once_control = 1;
1509 init_routine();
1510 }
1511
sewardj68b2dd92002-05-10 21:03:56 +00001512 __pthread_mutex_unlock(&once_masterlock);
sewardj89d3d852002-04-24 19:21:39 +00001513
1514 return 0;
1515}
1516
1517
1518/* ---------------------------------------------------
sewardj853f55d2002-04-26 00:27:53 +00001519 MISC
1520 ------------------------------------------------ */
1521
sewardj2cb00342002-06-28 01:46:26 +00001522static pthread_mutex_t pthread_atfork_lock
1523 = PTHREAD_MUTEX_INITIALIZER;
1524
sewardj5905fae2002-04-26 13:25:00 +00001525int __pthread_atfork ( void (*prepare)(void),
1526 void (*parent)(void),
1527 void (*child)(void) )
sewardj853f55d2002-04-26 00:27:53 +00001528{
sewardj2cb00342002-06-28 01:46:26 +00001529 int n, res;
1530 ForkHandlerEntry entry;
1531
1532 ensure_valgrind("pthread_atfork");
1533 __pthread_mutex_lock(&pthread_atfork_lock);
1534
1535 /* Fetch old counter */
1536 VALGRIND_MAGIC_SEQUENCE(n, -2 /* default */,
1537 VG_USERREQ__GET_FHSTACK_USED,
1538 0, 0, 0, 0);
1539 my_assert(n >= 0 && n < VG_N_FORKHANDLERSTACK);
1540 if (n == VG_N_FORKHANDLERSTACK-1)
1541 barf("pthread_atfork: VG_N_FORKHANDLERSTACK is too low; "
1542 "increase and recompile");
1543
1544 /* Add entry */
1545 entry.prepare = *prepare;
1546 entry.parent = *parent;
1547 entry.child = *child;
1548 VALGRIND_MAGIC_SEQUENCE(res, -2 /* default */,
1549 VG_USERREQ__SET_FHSTACK_ENTRY,
1550 n, &entry, 0, 0);
1551 my_assert(res == 0);
1552
1553 /* Bump counter */
1554 VALGRIND_MAGIC_SEQUENCE(res, -2 /* default */,
1555 VG_USERREQ__SET_FHSTACK_USED,
1556 n+1, 0, 0, 0);
1557 my_assert(res == 0);
1558
1559 __pthread_mutex_unlock(&pthread_atfork_lock);
1560 return 0;
sewardj853f55d2002-04-26 00:27:53 +00001561}
1562
1563
sewardj9df78832003-05-04 12:35:54 +00001564#ifdef GLIBC_2_3
1565/* This seems to be a hook which appeared in glibc-2.3.2. */
1566int __register_atfork ( void (*prepare)(void),
1567 void (*parent)(void),
1568 void (*child)(void) )
1569{
1570 return __pthread_atfork(prepare,parent,child);
1571}
1572#endif
1573
sewardj11f0bb42003-04-26 20:11:15 +00001574WEAK
sewardjbb990782002-05-08 02:01:14 +00001575void __pthread_initialize ( void )
1576{
sewardjbea1caa2002-05-10 23:20:58 +00001577 ensure_valgrind("__pthread_initialize");
sewardjbb990782002-05-08 02:01:14 +00001578}
1579
1580
sewardj853f55d2002-04-26 00:27:53 +00001581/* ---------------------------------------------------
sewardj3b13f0e2002-04-25 20:17:29 +00001582 LIBRARY-PRIVATE THREAD SPECIFIC STATE
sewardjf8f819e2002-04-17 23:21:37 +00001583 ------------------------------------------------ */
1584
sewardj3b13f0e2002-04-25 20:17:29 +00001585#include <resolv.h>
1586static int thread_specific_errno[VG_N_THREADS];
1587static int thread_specific_h_errno[VG_N_THREADS];
1588static struct __res_state
1589 thread_specific_res_state[VG_N_THREADS];
sewardjf8f819e2002-04-17 23:21:37 +00001590
sewardj25418ae2003-05-09 23:40:34 +00001591#undef errno
1592extern int errno;
sewardj3b13f0e2002-04-25 20:17:29 +00001593int* __errno_location ( void )
sewardjf8f819e2002-04-17 23:21:37 +00001594{
1595 int tid;
sewardj3b13f0e2002-04-25 20:17:29 +00001596 /* ensure_valgrind("__errno_location"); */
1597 VALGRIND_MAGIC_SEQUENCE(tid, 1 /* default */,
sewardjf8f819e2002-04-17 23:21:37 +00001598 VG_USERREQ__PTHREAD_GET_THREADID,
1599 0, 0, 0, 0);
sewardj3b13f0e2002-04-25 20:17:29 +00001600 /* 'cos I'm paranoid ... */
sewardj439d45e2002-05-03 20:43:10 +00001601 if (tid < 1 || tid >= VG_N_THREADS)
sewardj3b13f0e2002-04-25 20:17:29 +00001602 barf("__errno_location: invalid ThreadId");
sewardj25418ae2003-05-09 23:40:34 +00001603 if (tid == 1)
1604 return &errno;
sewardj3b13f0e2002-04-25 20:17:29 +00001605 return & thread_specific_errno[tid];
1606}
1607
sewardj25418ae2003-05-09 23:40:34 +00001608#undef h_errno
1609extern int h_errno;
sewardj3b13f0e2002-04-25 20:17:29 +00001610int* __h_errno_location ( void )
1611{
1612 int tid;
1613 /* ensure_valgrind("__h_errno_location"); */
1614 VALGRIND_MAGIC_SEQUENCE(tid, 1 /* default */,
1615 VG_USERREQ__PTHREAD_GET_THREADID,
1616 0, 0, 0, 0);
1617 /* 'cos I'm paranoid ... */
sewardj439d45e2002-05-03 20:43:10 +00001618 if (tid < 1 || tid >= VG_N_THREADS)
sewardj3b13f0e2002-04-25 20:17:29 +00001619 barf("__h_errno_location: invalid ThreadId");
sewardj25418ae2003-05-09 23:40:34 +00001620 if (tid == 1)
1621 return &h_errno;
sewardj3b13f0e2002-04-25 20:17:29 +00001622 return & thread_specific_h_errno[tid];
1623}
1624
sewardjb0ff1032002-08-06 09:02:53 +00001625
1626#undef _res
1627extern struct __res_state _res;
sewardj3b13f0e2002-04-25 20:17:29 +00001628struct __res_state* __res_state ( void )
1629{
1630 int tid;
1631 /* ensure_valgrind("__res_state"); */
1632 VALGRIND_MAGIC_SEQUENCE(tid, 1 /* default */,
1633 VG_USERREQ__PTHREAD_GET_THREADID,
1634 0, 0, 0, 0);
1635 /* 'cos I'm paranoid ... */
sewardj439d45e2002-05-03 20:43:10 +00001636 if (tid < 1 || tid >= VG_N_THREADS)
sewardj3b13f0e2002-04-25 20:17:29 +00001637 barf("__res_state: invalid ThreadId");
sewardjb0ff1032002-08-06 09:02:53 +00001638 if (tid == 1)
1639 return & _res;
sewardj3b13f0e2002-04-25 20:17:29 +00001640 return & thread_specific_res_state[tid];
sewardjf8f819e2002-04-17 23:21:37 +00001641}
1642
1643
sewardj5716dbb2002-04-26 03:28:18 +00001644/* ---------------------------------------------------
1645 LIBC-PRIVATE SPECIFIC DATA
1646 ------------------------------------------------ */
1647
1648/* Relies on assumption that initial private data is NULL. This
1649 should be fixed somehow. */
1650
njn25e49d8e72002-09-23 09:36:25 +00001651/* The allowable keys (indices) (all 3 of them).
sewardj5716dbb2002-04-26 03:28:18 +00001652 From sysdeps/pthread/bits/libc-tsd.h
1653*/
sewardjcb7f08a2002-10-02 09:41:49 +00001654/* as per glibc anoncvs HEAD of 20021001. */
sewardj5716dbb2002-04-26 03:28:18 +00001655enum __libc_tsd_key_t { _LIBC_TSD_KEY_MALLOC = 0,
1656 _LIBC_TSD_KEY_DL_ERROR,
njn25e49d8e72002-09-23 09:36:25 +00001657 _LIBC_TSD_KEY_RPC_VARS,
sewardjcb7f08a2002-10-02 09:41:49 +00001658 _LIBC_TSD_KEY_LOCALE,
1659 _LIBC_TSD_KEY_CTYPE_B,
1660 _LIBC_TSD_KEY_CTYPE_TOLOWER,
1661 _LIBC_TSD_KEY_CTYPE_TOUPPER,
sewardj5716dbb2002-04-26 03:28:18 +00001662 _LIBC_TSD_KEY_N };
1663
1664/* Auto-initialising subsystem. libc_specifics_inited is set
1665 after initialisation. libc_specifics_inited_mx guards it. */
1666static int libc_specifics_inited = 0;
1667static pthread_mutex_t libc_specifics_inited_mx = PTHREAD_MUTEX_INITIALIZER;
1668
sewardj00a66b12002-10-12 16:42:35 +00001669
sewardj5716dbb2002-04-26 03:28:18 +00001670/* These are the keys we must initialise the first time. */
sewardjcb7f08a2002-10-02 09:41:49 +00001671static pthread_key_t libc_specifics_keys[_LIBC_TSD_KEY_N];
sewardj5716dbb2002-04-26 03:28:18 +00001672
sewardj00a66b12002-10-12 16:42:35 +00001673
sewardjcb7f08a2002-10-02 09:41:49 +00001674/* Initialise the keys, if they are not already initialised. */
sewardj5716dbb2002-04-26 03:28:18 +00001675static
1676void init_libc_tsd_keys ( void )
1677{
1678 int res, i;
1679 pthread_key_t k;
1680
sewardj08c7f012002-10-07 23:56:55 +00001681 /* Don't fall into deadlock if we get called again whilst we still
1682 hold the lock, via the __uselocale() call herein. */
1683 if (libc_specifics_inited != 0)
1684 return;
1685
1686 /* Take the lock. */
sewardj00a66b12002-10-12 16:42:35 +00001687 res = __pthread_mutex_lock(&libc_specifics_inited_mx);
sewardj5716dbb2002-04-26 03:28:18 +00001688 if (res != 0) barf("init_libc_tsd_keys: lock");
1689
sewardj08c7f012002-10-07 23:56:55 +00001690 /* Now test again, to be sure there is no mistake. */
1691 if (libc_specifics_inited != 0) {
sewardj00a66b12002-10-12 16:42:35 +00001692 res = __pthread_mutex_unlock(&libc_specifics_inited_mx);
sewardj08c7f012002-10-07 23:56:55 +00001693 if (res != 0) barf("init_libc_tsd_keys: unlock(1)");
1694 return;
sewardj5716dbb2002-04-26 03:28:18 +00001695 }
1696
sewardj08c7f012002-10-07 23:56:55 +00001697 /* Actually do the initialisation. */
1698 /* printf("INIT libc specifics\n"); */
1699 for (i = 0; i < _LIBC_TSD_KEY_N; i++) {
sewardj00a66b12002-10-12 16:42:35 +00001700 res = __pthread_key_create(&k, NULL);
sewardj08c7f012002-10-07 23:56:55 +00001701 if (res != 0) barf("init_libc_tsd_keys: create");
1702 libc_specifics_keys[i] = k;
1703 }
1704
1705 /* Signify init done. */
1706 libc_specifics_inited = 1;
1707
1708# ifdef GLIBC_2_3
1709 /* Set the initialising thread's locale to the global (default)
sewardj00a66b12002-10-12 16:42:35 +00001710 locale. A hack in support of glibc-2.3. This does the biz for
1711 the root thread. For all other threads we run this in
1712 thread_wrapper(), which does the real work of
1713 pthread_create(). */
1714 /* assert that we are the root thread. I don't know if this is
1715 really a valid assertion to make; if it breaks I'll reconsider
1716 it. */
1717 my_assert(pthread_self() == 1);
sewardj08c7f012002-10-07 23:56:55 +00001718 __uselocale(LC_GLOBAL_LOCALE);
1719# endif
1720
1721 /* Unlock and return. */
sewardj00a66b12002-10-12 16:42:35 +00001722 res = __pthread_mutex_unlock(&libc_specifics_inited_mx);
sewardj5716dbb2002-04-26 03:28:18 +00001723 if (res != 0) barf("init_libc_tsd_keys: unlock");
1724}
1725
1726
1727static int
1728libc_internal_tsd_set ( enum __libc_tsd_key_t key,
1729 const void * pointer )
1730{
sewardjcb7f08a2002-10-02 09:41:49 +00001731 int res;
sewardj5716dbb2002-04-26 03:28:18 +00001732 /* printf("SET SET SET key %d ptr %p\n", key, pointer); */
sewardjcb7f08a2002-10-02 09:41:49 +00001733 if (key < _LIBC_TSD_KEY_MALLOC || key >= _LIBC_TSD_KEY_N)
sewardj5716dbb2002-04-26 03:28:18 +00001734 barf("libc_internal_tsd_set: invalid key");
1735 init_libc_tsd_keys();
sewardj00a66b12002-10-12 16:42:35 +00001736 res = __pthread_setspecific(libc_specifics_keys[key], pointer);
sewardj5716dbb2002-04-26 03:28:18 +00001737 if (res != 0) barf("libc_internal_tsd_set: setspecific failed");
1738 return 0;
1739}
1740
1741static void *
1742libc_internal_tsd_get ( enum __libc_tsd_key_t key )
1743{
sewardjcb7f08a2002-10-02 09:41:49 +00001744 void* v;
sewardj5716dbb2002-04-26 03:28:18 +00001745 /* printf("GET GET GET key %d\n", key); */
sewardjcb7f08a2002-10-02 09:41:49 +00001746 if (key < _LIBC_TSD_KEY_MALLOC || key >= _LIBC_TSD_KEY_N)
sewardj5716dbb2002-04-26 03:28:18 +00001747 barf("libc_internal_tsd_get: invalid key");
1748 init_libc_tsd_keys();
sewardj00a66b12002-10-12 16:42:35 +00001749 v = __pthread_getspecific(libc_specifics_keys[key]);
sewardj5716dbb2002-04-26 03:28:18 +00001750 /* if (v == NULL) barf("libc_internal_tsd_set: getspecific failed"); */
1751 return v;
1752}
1753
1754
sewardj70adeb22002-04-27 01:35:38 +00001755int (*__libc_internal_tsd_set)
1756 (enum __libc_tsd_key_t key, const void * pointer)
1757 = libc_internal_tsd_set;
sewardj5716dbb2002-04-26 03:28:18 +00001758
sewardj70adeb22002-04-27 01:35:38 +00001759void* (*__libc_internal_tsd_get)
1760 (enum __libc_tsd_key_t key)
1761 = libc_internal_tsd_get;
sewardj5716dbb2002-04-26 03:28:18 +00001762
1763
sewardj00a66b12002-10-12 16:42:35 +00001764#ifdef GLIBC_2_3
1765/* This one was first spotted be me in the glibc-2.2.93 sources. */
1766static void**
1767libc_internal_tsd_address ( enum __libc_tsd_key_t key )
1768{
1769 void** v;
1770 /* printf("ADDR ADDR ADDR key %d\n", key); */
1771 if (key < _LIBC_TSD_KEY_MALLOC || key >= _LIBC_TSD_KEY_N)
1772 barf("libc_internal_tsd_address: invalid key");
1773 init_libc_tsd_keys();
1774 v = __pthread_getspecific_addr(libc_specifics_keys[key]);
1775 return v;
1776}
1777
1778void ** (*__libc_internal_tsd_address)
1779 (enum __libc_tsd_key_t key)
1780 = libc_internal_tsd_address;
1781#endif
1782
1783
sewardje663cb92002-04-12 10:26:32 +00001784/* ---------------------------------------------------------------------
1785 These are here (I think) because they are deemed cancellation
1786 points by POSIX. For the moment we'll simply pass the call along
1787 to the corresponding thread-unaware (?) libc routine.
1788 ------------------------------------------------------------------ */
1789
sewardjd529a442002-05-04 19:49:21 +00001790#ifdef GLIBC_2_1
1791extern
1792int __sigaction
1793 (int signum,
1794 const struct sigaction *act,
1795 struct sigaction *oldact);
1796#else
sewardje663cb92002-04-12 10:26:32 +00001797extern
1798int __libc_sigaction
1799 (int signum,
1800 const struct sigaction *act,
1801 struct sigaction *oldact);
sewardjd529a442002-05-04 19:49:21 +00001802#endif
sewardje663cb92002-04-12 10:26:32 +00001803int sigaction(int signum,
1804 const struct sigaction *act,
1805 struct sigaction *oldact)
1806{
sewardjd140e442002-05-29 01:21:19 +00001807 __my_pthread_testcancel();
sewardj2a1dcce2002-04-22 12:45:25 +00001808# ifdef GLIBC_2_1
1809 return __sigaction(signum, act, oldact);
1810# else
sewardj45b4b372002-04-16 22:50:32 +00001811 return __libc_sigaction(signum, act, oldact);
sewardj2a1dcce2002-04-22 12:45:25 +00001812# endif
sewardje663cb92002-04-12 10:26:32 +00001813}
1814
1815
1816extern
1817int __libc_connect(int sockfd,
1818 const struct sockaddr *serv_addr,
1819 socklen_t addrlen);
sewardj11f0bb42003-04-26 20:11:15 +00001820WEAK
sewardje663cb92002-04-12 10:26:32 +00001821int connect(int sockfd,
1822 const struct sockaddr *serv_addr,
1823 socklen_t addrlen)
1824{
sewardjd140e442002-05-29 01:21:19 +00001825 __my_pthread_testcancel();
sewardj45b4b372002-04-16 22:50:32 +00001826 return __libc_connect(sockfd, serv_addr, addrlen);
sewardje663cb92002-04-12 10:26:32 +00001827}
1828
1829
1830extern
1831int __libc_fcntl(int fd, int cmd, long arg);
sewardj11f0bb42003-04-26 20:11:15 +00001832WEAK
sewardje663cb92002-04-12 10:26:32 +00001833int fcntl(int fd, int cmd, long arg)
1834{
sewardjd140e442002-05-29 01:21:19 +00001835 __my_pthread_testcancel();
sewardj45b4b372002-04-16 22:50:32 +00001836 return __libc_fcntl(fd, cmd, arg);
sewardje663cb92002-04-12 10:26:32 +00001837}
1838
1839
1840extern
1841ssize_t __libc_write(int fd, const void *buf, size_t count);
sewardj11f0bb42003-04-26 20:11:15 +00001842WEAK
sewardje663cb92002-04-12 10:26:32 +00001843ssize_t write(int fd, const void *buf, size_t count)
1844{
sewardjd140e442002-05-29 01:21:19 +00001845 __my_pthread_testcancel();
sewardj45b4b372002-04-16 22:50:32 +00001846 return __libc_write(fd, buf, count);
sewardje663cb92002-04-12 10:26:32 +00001847}
1848
1849
1850extern
1851ssize_t __libc_read(int fd, void *buf, size_t count);
sewardj11f0bb42003-04-26 20:11:15 +00001852WEAK
sewardje663cb92002-04-12 10:26:32 +00001853ssize_t read(int fd, void *buf, size_t count)
1854{
sewardjd140e442002-05-29 01:21:19 +00001855 __my_pthread_testcancel();
sewardj45b4b372002-04-16 22:50:32 +00001856 return __libc_read(fd, buf, count);
sewardje663cb92002-04-12 10:26:32 +00001857}
1858
sewardjf912dfc2002-11-13 21:51:10 +00001859/*
1860 * Ugh, this is horrible but here goes:
1861 *
1862 * Open of a named pipe (fifo file) can block. In a threaded program,
1863 * this means that the whole thing can block. We therefore need to
1864 * make the open appear to block to the caller, but still keep polling
1865 * for everyone else.
1866 *
1867 * There are four cases:
1868 *
1869 * - the caller asked for O_NONBLOCK. The easy one: we just do it.
1870 *
1871 * - the caller asked for a blocking O_RDONLY open. We open it with
1872 * O_NONBLOCK and then use poll to wait for it to become ready.
1873 *
1874 * - the caller asked for a blocking O_WRONLY open. Unfortunately, this
1875 * will fail with ENXIO when we make it non-blocking. Doubly
1876 * unfortunate is that we can only rely on these semantics if it is
1877 * actually a fifo file; the hack is that if we see that it is a
1878 * O_WRONLY open and we get ENXIO, then stat the path and see if it
1879 * actually is a fifo. This is racy, but it is the best we can do.
1880 * If it is a fifo, then keep trying the open until it works; if not
1881 * just return the error.
1882 *
1883 * - the caller asked for a blocking O_RDWR open. Well, under Linux,
1884 * this never blocks, so we just clear the non-blocking flag and
1885 * return.
1886 *
1887 * This code assumes that for whatever we open, O_NONBLOCK followed by
1888 * a fcntl clearing O_NONBLOCK is the same as opening without
1889 * O_NONBLOCK. Also assumes that stat and fstat have no side-effects.
1890 *
1891 * XXX Should probably put in special cases for some devices as well,
1892 * like serial ports. Unfortunately they don't work like fifos, so
1893 * this logic will become even more tortured. Wait until we really
1894 * need it.
1895 */
1896static inline int _open(const char *pathname, int flags, mode_t mode,
1897 int (*openp)(const char *, int, mode_t))
sewardjbe32e452002-04-24 20:29:58 +00001898{
sewardjf912dfc2002-11-13 21:51:10 +00001899 int fd;
1900 struct stat st;
1901 struct vki_timespec nanosleep_interval;
1902 int saved_errno;
1903
sewardjd140e442002-05-29 01:21:19 +00001904 __my_pthread_testcancel();
sewardjf912dfc2002-11-13 21:51:10 +00001905
1906 /* Assume we can only get O_RDONLY, O_WRONLY or O_RDWR */
1907 my_assert((flags & VKI_O_ACCMODE) != VKI_O_ACCMODE);
1908
1909 for(;;) {
1910 fd = (*openp)(pathname, flags | VKI_O_NONBLOCK, mode);
1911
1912 /* return immediately if caller wanted nonblocking anyway */
1913 if (flags & VKI_O_NONBLOCK)
1914 return fd;
1915
sewardj25418ae2003-05-09 23:40:34 +00001916 saved_errno = *(__errno_location());
sewardjf912dfc2002-11-13 21:51:10 +00001917
1918 if (fd != -1)
1919 break; /* open worked */
1920
1921 /* If we got ENXIO and we're opening WRONLY, and it turns out
1922 to really be a FIFO, then poll waiting for open to succeed */
sewardj25418ae2003-05-09 23:40:34 +00001923 if (*(__errno_location()) == ENXIO &&
sewardjf912dfc2002-11-13 21:51:10 +00001924 (flags & VKI_O_ACCMODE) == VKI_O_WRONLY &&
1925 (stat(pathname, &st) == 0 && S_ISFIFO(st.st_mode))) {
1926
1927 /* OK, we're opening a FIFO for writing; sleep and spin */
1928 nanosleep_interval.tv_sec = 0;
1929 nanosleep_interval.tv_nsec = 13 * 1000 * 1000; /* 13 milliseconds */
1930 /* It's critical here that valgrind's nanosleep implementation
1931 is nonblocking. */
1932 (void)my_do_syscall2(__NR_nanosleep,
1933 (int)(&nanosleep_interval), (int)NULL);
1934 } else {
1935 /* it was just an error */
sewardj25418ae2003-05-09 23:40:34 +00001936 *(__errno_location()) = saved_errno;
sewardjf912dfc2002-11-13 21:51:10 +00001937 return -1;
1938 }
1939 }
1940
1941 /* OK, we've got a nonblocking FD for a caller who wants blocking;
1942 reset the flags to what they asked for */
1943 fcntl(fd, VKI_F_SETFL, flags);
1944
1945 /* Return now if one of:
1946 - we were opening O_RDWR (never blocks)
1947 - we opened with O_WRONLY (polling already done)
1948 - the thing we opened wasn't a FIFO after all (or fstat failed)
1949 */
1950 if ((flags & VKI_O_ACCMODE) != VKI_O_RDONLY ||
1951 (fstat(fd, &st) == -1 || !S_ISFIFO(st.st_mode))) {
sewardj25418ae2003-05-09 23:40:34 +00001952 *(__errno_location()) = saved_errno;
sewardjf912dfc2002-11-13 21:51:10 +00001953 return fd;
1954 }
1955
1956 /* OK, drop into the poll loop looking for something to read on the fd */
1957 my_assert((flags & VKI_O_ACCMODE) == VKI_O_RDONLY);
1958 for(;;) {
1959 struct pollfd pollfd;
1960 int res;
1961
1962 pollfd.fd = fd;
1963 pollfd.events = POLLIN;
1964 pollfd.revents = 0;
1965
1966 res = my_do_syscall3(__NR_poll, (int)&pollfd, 1, 0);
1967
1968 my_assert(res == 0 || res == 1);
1969
1970 if (res == 1) {
1971 /* OK, got it.
1972
1973 XXX This is wrong: we're waiting for either something to
1974 read or a HUP on the file descriptor, but the semantics of
1975 fifo open are that we should unblock as soon as someone
1976 simply opens the other end, not that they write something.
1977 With luck this won't matter in practice.
1978 */
1979 my_assert(pollfd.revents & (POLLIN|POLLHUP));
1980 break;
1981 }
1982
1983 /* Still nobody home; sleep and spin */
1984 nanosleep_interval.tv_sec = 0;
1985 nanosleep_interval.tv_nsec = 13 * 1000 * 1000; /* 13 milliseconds */
1986 /* It's critical here that valgrind's nanosleep implementation
1987 is nonblocking. */
1988 (void)my_do_syscall2(__NR_nanosleep,
1989 (int)(&nanosleep_interval), (int)NULL);
1990 }
1991
sewardj25418ae2003-05-09 23:40:34 +00001992 *(__errno_location()) = saved_errno;
sewardjf912dfc2002-11-13 21:51:10 +00001993 return fd;
sewardjbe32e452002-04-24 20:29:58 +00001994}
1995
sewardjf912dfc2002-11-13 21:51:10 +00001996extern
1997int __libc_open64(const char *pathname, int flags, mode_t mode);
sewardj11f0bb42003-04-26 20:11:15 +00001998/* WEAK */
sewardjf912dfc2002-11-13 21:51:10 +00001999int open64(const char *pathname, int flags, mode_t mode)
2000{
2001 return _open(pathname, flags, mode, __libc_open64);
2002}
sewardje663cb92002-04-12 10:26:32 +00002003
2004extern
sewardj853f55d2002-04-26 00:27:53 +00002005int __libc_open(const char *pathname, int flags, mode_t mode);
sewardj11f0bb42003-04-26 20:11:15 +00002006/* WEAK */
sewardj853f55d2002-04-26 00:27:53 +00002007int open(const char *pathname, int flags, mode_t mode)
sewardje663cb92002-04-12 10:26:32 +00002008{
sewardjf912dfc2002-11-13 21:51:10 +00002009 return _open(pathname, flags, mode, __libc_open);
sewardje663cb92002-04-12 10:26:32 +00002010}
2011
sewardje663cb92002-04-12 10:26:32 +00002012extern
2013int __libc_close(int fd);
sewardj11f0bb42003-04-26 20:11:15 +00002014WEAK
sewardje663cb92002-04-12 10:26:32 +00002015int close(int fd)
2016{
sewardjd140e442002-05-29 01:21:19 +00002017 __my_pthread_testcancel();
sewardj45b4b372002-04-16 22:50:32 +00002018 return __libc_close(fd);
sewardje663cb92002-04-12 10:26:32 +00002019}
2020
2021
sewardj11f0bb42003-04-26 20:11:15 +00002022WEAK
2023int accept(int s, struct sockaddr *addr, socklen_t *addrlen)
sewardje663cb92002-04-12 10:26:32 +00002024{
sewardj11f0bb42003-04-26 20:11:15 +00002025 return VGR_(accept)(s, addr, addrlen);
sewardje663cb92002-04-12 10:26:32 +00002026}
2027
sewardj11f0bb42003-04-26 20:11:15 +00002028WEAK
2029int recv(int s, void *buf, size_t len, int flags)
sewardj0c573af92002-10-23 21:55:01 +00002030{
sewardj11f0bb42003-04-26 20:11:15 +00002031 return VGR_(recv)(s, buf, len, flags);
sewardj0c573af92002-10-23 21:55:01 +00002032}
2033
sewardj11f0bb42003-04-26 20:11:15 +00002034WEAK
2035int readv(int fd, const struct iovec *iov, int count)
sewardj2a68e7e2002-11-16 11:04:18 +00002036{
sewardj11f0bb42003-04-26 20:11:15 +00002037 return VGR_(readv)(fd, iov, count);
sewardj2a68e7e2002-11-16 11:04:18 +00002038}
2039
sewardj11f0bb42003-04-26 20:11:15 +00002040WEAK
2041int writev(int fd, const struct iovec *iov, int count)
sewardj2a68e7e2002-11-16 11:04:18 +00002042{
sewardj11f0bb42003-04-26 20:11:15 +00002043 return VGR_(writev)(fd, iov, count);
sewardj2a68e7e2002-11-16 11:04:18 +00002044}
sewardje663cb92002-04-12 10:26:32 +00002045
2046extern
sewardje663cb92002-04-12 10:26:32 +00002047pid_t __libc_waitpid(pid_t pid, int *status, int options);
sewardj11f0bb42003-04-26 20:11:15 +00002048WEAK
sewardje663cb92002-04-12 10:26:32 +00002049pid_t waitpid(pid_t pid, int *status, int options)
2050{
sewardjd140e442002-05-29 01:21:19 +00002051 __my_pthread_testcancel();
sewardj45b4b372002-04-16 22:50:32 +00002052 return __libc_waitpid(pid, status, options);
sewardje663cb92002-04-12 10:26:32 +00002053}
2054
2055
2056extern
2057int __libc_nanosleep(const struct timespec *req, struct timespec *rem);
sewardj11f0bb42003-04-26 20:11:15 +00002058WEAK
sewardje663cb92002-04-12 10:26:32 +00002059int nanosleep(const struct timespec *req, struct timespec *rem)
2060{
sewardjd140e442002-05-29 01:21:19 +00002061 __my_pthread_testcancel();
sewardje663cb92002-04-12 10:26:32 +00002062 return __libc_nanosleep(req, rem);
2063}
2064
sewardjbe32e452002-04-24 20:29:58 +00002065
sewardje663cb92002-04-12 10:26:32 +00002066extern
2067int __libc_fsync(int fd);
sewardj11f0bb42003-04-26 20:11:15 +00002068WEAK
sewardje663cb92002-04-12 10:26:32 +00002069int fsync(int fd)
2070{
sewardjd140e442002-05-29 01:21:19 +00002071 __my_pthread_testcancel();
sewardj45b4b372002-04-16 22:50:32 +00002072 return __libc_fsync(fd);
sewardje663cb92002-04-12 10:26:32 +00002073}
2074
sewardjbe32e452002-04-24 20:29:58 +00002075
sewardj70c75362002-04-13 04:18:32 +00002076extern
2077off_t __libc_lseek(int fildes, off_t offset, int whence);
sewardj11f0bb42003-04-26 20:11:15 +00002078WEAK
sewardj70c75362002-04-13 04:18:32 +00002079off_t lseek(int fildes, off_t offset, int whence)
2080{
sewardjd140e442002-05-29 01:21:19 +00002081 __my_pthread_testcancel();
sewardj45b4b372002-04-16 22:50:32 +00002082 return __libc_lseek(fildes, offset, whence);
sewardj70c75362002-04-13 04:18:32 +00002083}
2084
sewardjbe32e452002-04-24 20:29:58 +00002085
2086extern
2087__off64_t __libc_lseek64(int fildes, __off64_t offset, int whence);
sewardj11f0bb42003-04-26 20:11:15 +00002088WEAK
sewardjbe32e452002-04-24 20:29:58 +00002089__off64_t lseek64(int fildes, __off64_t offset, int whence)
2090{
sewardjd140e442002-05-29 01:21:19 +00002091 __my_pthread_testcancel();
sewardjbe32e452002-04-24 20:29:58 +00002092 return __libc_lseek64(fildes, offset, whence);
2093}
2094
2095
sewardj726c4122002-05-16 23:39:10 +00002096extern
2097ssize_t __libc_pread64 (int __fd, void *__buf, size_t __nbytes,
2098 __off64_t __offset);
2099ssize_t __pread64 (int __fd, void *__buf, size_t __nbytes,
2100 __off64_t __offset)
2101{
sewardjd140e442002-05-29 01:21:19 +00002102 __my_pthread_testcancel();
sewardj726c4122002-05-16 23:39:10 +00002103 return __libc_pread64(__fd, __buf, __nbytes, __offset);
2104}
2105
2106
sewardja18e2102002-05-18 10:43:22 +00002107extern
2108ssize_t __libc_pwrite64 (int __fd, const void *__buf, size_t __nbytes,
2109 __off64_t __offset);
2110ssize_t __pwrite64 (int __fd, const void *__buf, size_t __nbytes,
2111 __off64_t __offset)
2112{
sewardjd140e442002-05-29 01:21:19 +00002113 __my_pthread_testcancel();
sewardja18e2102002-05-18 10:43:22 +00002114 return __libc_pwrite64(__fd, __buf, __nbytes, __offset);
2115}
2116
sewardj726c4122002-05-16 23:39:10 +00002117
sewardj39b93b12002-05-18 10:56:27 +00002118extern
2119ssize_t __libc_pwrite(int fd, const void *buf, size_t count, off_t offset);
sewardj11f0bb42003-04-26 20:11:15 +00002120WEAK
sewardj39b93b12002-05-18 10:56:27 +00002121ssize_t pwrite(int fd, const void *buf, size_t count, off_t offset)
2122{
sewardjd140e442002-05-29 01:21:19 +00002123 __my_pthread_testcancel();
sewardj39b93b12002-05-18 10:56:27 +00002124 return __libc_pwrite(fd, buf, count, offset);
2125}
2126
2127
2128extern
2129ssize_t __libc_pread(int fd, void *buf, size_t count, off_t offset);
sewardj11f0bb42003-04-26 20:11:15 +00002130WEAK
sewardj39b93b12002-05-18 10:56:27 +00002131ssize_t pread(int fd, void *buf, size_t count, off_t offset)
2132{
sewardjd140e442002-05-29 01:21:19 +00002133 __my_pthread_testcancel();
sewardj39b93b12002-05-18 10:56:27 +00002134 return __libc_pread(fd, buf, count, offset);
2135}
2136
2137
sewardj6af4b5d2002-04-16 04:40:49 +00002138extern
2139void __libc_longjmp(jmp_buf env, int val) __attribute((noreturn));
sewardj11f0bb42003-04-26 20:11:15 +00002140/* not weak: WEAK */
sewardj6af4b5d2002-04-16 04:40:49 +00002141void longjmp(jmp_buf env, int val)
2142{
2143 __libc_longjmp(env, val);
2144}
2145
sewardjbe32e452002-04-24 20:29:58 +00002146
sewardj436c2db2002-06-18 09:07:54 +00002147extern void __libc_siglongjmp (sigjmp_buf env, int val)
2148 __attribute__ ((noreturn));
2149void siglongjmp(sigjmp_buf env, int val)
2150{
2151 kludged("siglongjmp (cleanup handlers are ignored)");
2152 __libc_siglongjmp(env, val);
2153}
2154
2155
sewardj6af4b5d2002-04-16 04:40:49 +00002156extern
2157int __libc_send(int s, const void *msg, size_t len, int flags);
sewardj11f0bb42003-04-26 20:11:15 +00002158WEAK
sewardj6af4b5d2002-04-16 04:40:49 +00002159int send(int s, const void *msg, size_t len, int flags)
2160{
sewardjd140e442002-05-29 01:21:19 +00002161 __my_pthread_testcancel();
sewardj6af4b5d2002-04-16 04:40:49 +00002162 return __libc_send(s, msg, len, flags);
2163}
2164
sewardjbe32e452002-04-24 20:29:58 +00002165
sewardj3665ded2002-05-16 16:57:25 +00002166extern
2167int __libc_sendmsg(int s, const struct msghdr *msg, int flags);
sewardj11f0bb42003-04-26 20:11:15 +00002168WEAK
sewardj3665ded2002-05-16 16:57:25 +00002169int sendmsg(int s, const struct msghdr *msg, int flags)
2170{
sewardjd140e442002-05-29 01:21:19 +00002171 __my_pthread_testcancel();
sewardj3665ded2002-05-16 16:57:25 +00002172 return __libc_sendmsg(s, msg, flags);
2173}
2174
2175
sewardj796d6a22002-04-24 02:28:34 +00002176extern
sewardj59da27a2002-06-06 08:33:54 +00002177int __libc_recvmsg(int s, struct msghdr *msg, int flags);
sewardj11f0bb42003-04-26 20:11:15 +00002178WEAK
sewardj59da27a2002-06-06 08:33:54 +00002179int recvmsg(int s, struct msghdr *msg, int flags)
2180{
2181 __my_pthread_testcancel();
2182 return __libc_recvmsg(s, msg, flags);
2183}
2184
2185
2186extern
sewardj436e0582002-04-26 14:31:40 +00002187int __libc_recvfrom(int s, void *buf, size_t len, int flags,
2188 struct sockaddr *from, socklen_t *fromlen);
sewardj11f0bb42003-04-26 20:11:15 +00002189WEAK
sewardj436e0582002-04-26 14:31:40 +00002190int recvfrom(int s, void *buf, size_t len, int flags,
2191 struct sockaddr *from, socklen_t *fromlen)
2192{
sewardjd140e442002-05-29 01:21:19 +00002193 __my_pthread_testcancel();
sewardj11f0bb42003-04-26 20:11:15 +00002194 VGR_(wait_for_fd_to_be_readable_or_erring)(s);
sewardj2e207632002-06-13 17:29:53 +00002195 __my_pthread_testcancel();
sewardj436e0582002-04-26 14:31:40 +00002196 return __libc_recvfrom(s, buf, len, flags, from, fromlen);
2197}
2198
2199
2200extern
sewardj796d6a22002-04-24 02:28:34 +00002201int __libc_sendto(int s, const void *msg, size_t len, int flags,
2202 const struct sockaddr *to, socklen_t tolen);
sewardj11f0bb42003-04-26 20:11:15 +00002203WEAK
sewardj796d6a22002-04-24 02:28:34 +00002204int sendto(int s, const void *msg, size_t len, int flags,
2205 const struct sockaddr *to, socklen_t tolen)
2206{
sewardjd140e442002-05-29 01:21:19 +00002207 __my_pthread_testcancel();
sewardj796d6a22002-04-24 02:28:34 +00002208 return __libc_sendto(s, msg, len, flags, to, tolen);
2209}
2210
sewardjbe32e452002-04-24 20:29:58 +00002211
sewardj369b1702002-04-24 13:28:15 +00002212extern
2213int __libc_system(const char* str);
sewardj11f0bb42003-04-26 20:11:15 +00002214WEAK
sewardj369b1702002-04-24 13:28:15 +00002215int system(const char* str)
2216{
sewardjd140e442002-05-29 01:21:19 +00002217 __my_pthread_testcancel();
sewardj369b1702002-04-24 13:28:15 +00002218 return __libc_system(str);
2219}
2220
sewardjbe32e452002-04-24 20:29:58 +00002221
sewardjab0b1c32002-04-24 19:26:47 +00002222extern
2223pid_t __libc_wait(int *status);
sewardj11f0bb42003-04-26 20:11:15 +00002224WEAK
sewardjab0b1c32002-04-24 19:26:47 +00002225pid_t wait(int *status)
2226{
sewardjd140e442002-05-29 01:21:19 +00002227 __my_pthread_testcancel();
sewardjab0b1c32002-04-24 19:26:47 +00002228 return __libc_wait(status);
2229}
2230
sewardj45b4b372002-04-16 22:50:32 +00002231
sewardj67f1d582002-05-24 02:11:32 +00002232extern
2233int __libc_msync(const void *start, size_t length, int flags);
sewardj11f0bb42003-04-26 20:11:15 +00002234WEAK
sewardj67f1d582002-05-24 02:11:32 +00002235int msync(const void *start, size_t length, int flags)
2236{
sewardjd140e442002-05-29 01:21:19 +00002237 __my_pthread_testcancel();
sewardj67f1d582002-05-24 02:11:32 +00002238 return __libc_msync(start, length, flags);
2239}
2240
sewardj5905fae2002-04-26 13:25:00 +00002241
sewardj2cb00342002-06-28 01:46:26 +00002242/*--- fork and its helper ---*/
2243
2244static
2245void run_fork_handlers ( int what )
2246{
2247 ForkHandlerEntry entry;
2248 int n_h, n_handlers, i, res;
2249
2250 my_assert(what == 0 || what == 1 || what == 2);
2251
2252 /* Fetch old counter */
2253 VALGRIND_MAGIC_SEQUENCE(n_handlers, -2 /* default */,
2254 VG_USERREQ__GET_FHSTACK_USED,
2255 0, 0, 0, 0);
2256 my_assert(n_handlers >= 0 && n_handlers < VG_N_FORKHANDLERSTACK);
2257
2258 /* Prepare handlers (what == 0) are called in opposite order of
2259 calls to pthread_atfork. Parent and child handlers are called
2260 in the same order as calls to pthread_atfork. */
2261 if (what == 0)
2262 n_h = n_handlers - 1;
2263 else
2264 n_h = 0;
2265
2266 for (i = 0; i < n_handlers; i++) {
2267 VALGRIND_MAGIC_SEQUENCE(res, -2 /* default */,
2268 VG_USERREQ__GET_FHSTACK_ENTRY,
2269 n_h, &entry, 0, 0);
2270 my_assert(res == 0);
2271 switch (what) {
2272 case 0: if (entry.prepare) entry.prepare();
2273 n_h--; break;
2274 case 1: if (entry.parent) entry.parent();
2275 n_h++; break;
2276 case 2: if (entry.child) entry.child();
2277 n_h++; break;
2278 default: barf("run_fork_handlers: invalid what");
2279 }
2280 }
2281
2282 if (what != 0 /* prepare */) {
2283 /* Empty out the stack. */
2284 VALGRIND_MAGIC_SEQUENCE(res, -2 /* default */,
2285 VG_USERREQ__SET_FHSTACK_USED,
2286 0, 0, 0, 0);
2287 my_assert(res == 0);
2288 }
2289}
2290
2291extern
2292pid_t __libc_fork(void);
2293pid_t __fork(void)
2294{
2295 pid_t pid;
2296 __my_pthread_testcancel();
2297 __pthread_mutex_lock(&pthread_atfork_lock);
2298
2299 run_fork_handlers(0 /* prepare */);
2300 pid = __libc_fork();
2301 if (pid == 0) {
2302 /* I am the child */
2303 run_fork_handlers(2 /* child */);
sewardjd8acdf22002-11-13 21:57:52 +00002304 __pthread_mutex_unlock(&pthread_atfork_lock);
sewardj2cb00342002-06-28 01:46:26 +00002305 __pthread_mutex_init(&pthread_atfork_lock, NULL);
2306 } else {
2307 /* I am the parent */
2308 run_fork_handlers(1 /* parent */);
2309 __pthread_mutex_unlock(&pthread_atfork_lock);
2310 }
2311 return pid;
2312}
2313
2314
njn25e49d8e72002-09-23 09:36:25 +00002315pid_t __vfork(void)
2316{
2317 return __fork();
2318}
sewardj2cb00342002-06-28 01:46:26 +00002319
2320
sewardj08a4c3f2002-04-13 03:45:44 +00002321static
sewardj08a4c3f2002-04-13 03:45:44 +00002322int my_do_syscall1 ( int syscallno, int arg1 )
2323{
2324 int __res;
2325 __asm__ volatile ("pushl %%ebx; movl %%edx,%%ebx ; int $0x80 ; popl %%ebx"
2326 : "=a" (__res)
2327 : "0" (syscallno),
2328 "d" (arg1) );
2329 return __res;
2330}
2331
2332static
2333int my_do_syscall2 ( int syscallno,
sewardjf854f472002-04-21 12:19:41 +00002334 int arg1, int arg2 )
sewardj08a4c3f2002-04-13 03:45:44 +00002335{
2336 int __res;
2337 __asm__ volatile ("pushl %%ebx; movl %%edx,%%ebx ; int $0x80 ; popl %%ebx"
2338 : "=a" (__res)
2339 : "0" (syscallno),
2340 "d" (arg1),
2341 "c" (arg2) );
2342 return __res;
2343}
2344
2345static
sewardjf854f472002-04-21 12:19:41 +00002346int my_do_syscall3 ( int syscallno,
2347 int arg1, int arg2, int arg3 )
2348{
2349 int __res;
2350 __asm__ volatile ("pushl %%ebx; movl %%esi,%%ebx ; int $0x80 ; popl %%ebx"
2351 : "=a" (__res)
2352 : "0" (syscallno),
2353 "S" (arg1),
2354 "c" (arg2),
2355 "d" (arg3) );
2356 return __res;
2357}
2358
sewardjd5bef572002-10-23 21:49:33 +00002359static inline
2360int my_do_syscall5 ( int syscallno,
2361 int arg1, int arg2, int arg3, int arg4, int arg5 )
2362{
2363 int __res;
2364 __asm__ volatile ("int $0x80"
2365 : "=a" (__res)
2366 : "0" (syscallno),
2367 "b" (arg1),
2368 "c" (arg2),
2369 "d" (arg3),
2370 "S" (arg4),
2371 "D" (arg5));
2372 return __res;
2373}
2374
sewardj11f0bb42003-04-26 20:11:15 +00002375
2376WEAK
2377int select ( int n,
2378 fd_set *rfds,
2379 fd_set *wfds,
2380 fd_set *xfds,
2381 struct timeval *timeout )
sewardj08a4c3f2002-04-13 03:45:44 +00002382{
sewardj11f0bb42003-04-26 20:11:15 +00002383 return VGR_(select)(n, rfds, wfds, xfds, timeout);
sewardj08a4c3f2002-04-13 03:45:44 +00002384}
2385
2386
sewardj3b13f0e2002-04-25 20:17:29 +00002387/* ---------------------------------------------------------------------
sewardj8f253ff2002-05-19 00:13:34 +00002388 Hacky implementation of semaphores.
2389 ------------------------------------------------------------------ */
2390
2391#include <semaphore.h>
2392
2393/* This is a terrible way to do the remapping. Plan is to import an
2394 AVL tree at some point. */
sewardj8f253ff2002-05-19 00:13:34 +00002395
2396typedef
2397 struct {
2398 pthread_mutex_t se_mx;
2399 pthread_cond_t se_cv;
2400 int count;
2401 }
2402 vg_sem_t;
2403
2404static pthread_mutex_t se_remap_mx = PTHREAD_MUTEX_INITIALIZER;
2405
2406static int se_remap_used = 0;
2407static sem_t* se_remap_orig[VG_N_SEMAPHORES];
2408static vg_sem_t se_remap_new[VG_N_SEMAPHORES];
2409
2410static vg_sem_t* se_remap ( sem_t* orig )
2411{
2412 int res, i;
2413 res = __pthread_mutex_lock(&se_remap_mx);
sewardj2d94c112002-06-03 01:25:54 +00002414 my_assert(res == 0);
sewardj8f253ff2002-05-19 00:13:34 +00002415
2416 for (i = 0; i < se_remap_used; i++) {
2417 if (se_remap_orig[i] == orig)
2418 break;
2419 }
2420 if (i == se_remap_used) {
2421 if (se_remap_used == VG_N_SEMAPHORES) {
2422 res = pthread_mutex_unlock(&se_remap_mx);
sewardj2d94c112002-06-03 01:25:54 +00002423 my_assert(res == 0);
sewardja1ac5cb2002-05-27 13:00:05 +00002424 barf("VG_N_SEMAPHORES is too low. Increase and recompile.");
sewardj8f253ff2002-05-19 00:13:34 +00002425 }
2426 se_remap_used++;
2427 se_remap_orig[i] = orig;
2428 /* printf("allocated semaphore %d\n", i); */
2429 }
2430 res = __pthread_mutex_unlock(&se_remap_mx);
sewardj2d94c112002-06-03 01:25:54 +00002431 my_assert(res == 0);
sewardj8f253ff2002-05-19 00:13:34 +00002432 return &se_remap_new[i];
2433}
2434
2435
2436int sem_init(sem_t *sem, int pshared, unsigned int value)
2437{
2438 int res;
2439 vg_sem_t* vg_sem;
2440 ensure_valgrind("sem_init");
2441 if (pshared != 0) {
sewardj4dced352002-06-04 22:54:20 +00002442 pthread_error("sem_init: unsupported pshared value");
sewardj25418ae2003-05-09 23:40:34 +00002443 *(__errno_location()) = ENOSYS;
sewardj8f253ff2002-05-19 00:13:34 +00002444 return -1;
2445 }
2446 vg_sem = se_remap(sem);
2447 res = pthread_mutex_init(&vg_sem->se_mx, NULL);
sewardj2d94c112002-06-03 01:25:54 +00002448 my_assert(res == 0);
sewardj8f253ff2002-05-19 00:13:34 +00002449 res = pthread_cond_init(&vg_sem->se_cv, NULL);
sewardj2d94c112002-06-03 01:25:54 +00002450 my_assert(res == 0);
sewardj8f253ff2002-05-19 00:13:34 +00002451 vg_sem->count = value;
2452 return 0;
2453}
2454
2455
2456int sem_wait ( sem_t* sem )
2457{
2458 int res;
2459 vg_sem_t* vg_sem;
2460 ensure_valgrind("sem_wait");
2461 vg_sem = se_remap(sem);
2462 res = __pthread_mutex_lock(&vg_sem->se_mx);
sewardj2d94c112002-06-03 01:25:54 +00002463 my_assert(res == 0);
sewardj8f253ff2002-05-19 00:13:34 +00002464 while (vg_sem->count == 0) {
2465 res = pthread_cond_wait(&vg_sem->se_cv, &vg_sem->se_mx);
sewardj2d94c112002-06-03 01:25:54 +00002466 my_assert(res == 0);
sewardj8f253ff2002-05-19 00:13:34 +00002467 }
2468 vg_sem->count--;
2469 res = __pthread_mutex_unlock(&vg_sem->se_mx);
sewardj2d94c112002-06-03 01:25:54 +00002470 my_assert(res == 0);
sewardj8f253ff2002-05-19 00:13:34 +00002471 return 0;
2472}
2473
2474int sem_post ( sem_t* sem )
2475{
2476 int res;
2477 vg_sem_t* vg_sem;
2478 ensure_valgrind("sem_post");
2479 vg_sem = se_remap(sem);
2480 res = __pthread_mutex_lock(&vg_sem->se_mx);
sewardj2d94c112002-06-03 01:25:54 +00002481 my_assert(res == 0);
sewardj8f253ff2002-05-19 00:13:34 +00002482 if (vg_sem->count == 0) {
2483 vg_sem->count++;
2484 res = pthread_cond_broadcast(&vg_sem->se_cv);
sewardj2d94c112002-06-03 01:25:54 +00002485 my_assert(res == 0);
sewardj8f253ff2002-05-19 00:13:34 +00002486 } else {
2487 vg_sem->count++;
2488 }
2489 res = __pthread_mutex_unlock(&vg_sem->se_mx);
sewardj2d94c112002-06-03 01:25:54 +00002490 my_assert(res == 0);
sewardj8f253ff2002-05-19 00:13:34 +00002491 return 0;
2492}
2493
2494
2495int sem_trywait ( sem_t* sem )
2496{
2497 int ret, res;
2498 vg_sem_t* vg_sem;
2499 ensure_valgrind("sem_trywait");
2500 vg_sem = se_remap(sem);
2501 res = __pthread_mutex_lock(&vg_sem->se_mx);
sewardj2d94c112002-06-03 01:25:54 +00002502 my_assert(res == 0);
sewardj8f253ff2002-05-19 00:13:34 +00002503 if (vg_sem->count > 0) {
2504 vg_sem->count--;
2505 ret = 0;
2506 } else {
2507 ret = -1;
sewardj25418ae2003-05-09 23:40:34 +00002508 *(__errno_location()) = EAGAIN;
sewardj8f253ff2002-05-19 00:13:34 +00002509 }
2510 res = __pthread_mutex_unlock(&vg_sem->se_mx);
sewardj2d94c112002-06-03 01:25:54 +00002511 my_assert(res == 0);
sewardj8f253ff2002-05-19 00:13:34 +00002512 return ret;
2513}
2514
2515
2516int sem_getvalue(sem_t* sem, int * sval)
2517{
2518 vg_sem_t* vg_sem;
2519 ensure_valgrind("sem_trywait");
2520 vg_sem = se_remap(sem);
2521 *sval = vg_sem->count;
2522 return 0;
2523}
2524
2525
2526int sem_destroy(sem_t * sem)
2527{
2528 kludged("sem_destroy");
2529 /* if someone waiting on this semaphore, errno = EBUSY, return -1 */
2530 return 0;
2531}
2532
sewardj9ad92d92002-10-16 19:45:06 +00002533
2534int sem_timedwait(sem_t* sem, const struct timespec *abstime)
2535{
2536 int res;
2537 vg_sem_t* vg_sem;
2538 ensure_valgrind("sem_timedwait");
2539 vg_sem = se_remap(sem);
2540 res = __pthread_mutex_lock(&vg_sem->se_mx);
2541 my_assert(res == 0);
2542 while ( vg_sem->count == 0 && res != ETIMEDOUT ) {
2543 res = pthread_cond_timedwait(&vg_sem->se_cv, &vg_sem->se_mx, abstime);
2544 }
2545 if ( vg_sem->count > 0 ) {
2546 vg_sem->count--;
2547 res = __pthread_mutex_unlock(&vg_sem->se_mx);
2548 my_assert(res == 0 );
2549 return 0;
2550 } else {
2551 res = __pthread_mutex_unlock(&vg_sem->se_mx);
2552 my_assert(res == 0 );
2553 *(__errno_location()) = ETIMEDOUT;
2554 return -1;
2555 }
2556}
2557
sewardj8f253ff2002-05-19 00:13:34 +00002558
2559/* ---------------------------------------------------------------------
sewardj2d8b3f02002-06-01 14:14:19 +00002560 Reader-writer locks.
sewardja1ac5cb2002-05-27 13:00:05 +00002561 ------------------------------------------------------------------ */
2562
sewardj2d8b3f02002-06-01 14:14:19 +00002563typedef
2564 struct {
2565 int initted; /* != 0 --> in use; sanity check only */
2566 int prefer_w; /* != 0 --> prefer writer */
2567 int nwait_r; /* # of waiting readers */
2568 int nwait_w; /* # of waiting writers */
2569 pthread_cond_t cv_r; /* for signalling readers */
2570 pthread_cond_t cv_w; /* for signalling writers */
2571 pthread_mutex_t mx;
2572 int status;
2573 /* allowed range for status: >= -1. -1 means 1 writer currently
2574 active, >= 0 means N readers currently active. */
2575 }
2576 vg_rwlock_t;
sewardja1ac5cb2002-05-27 13:00:05 +00002577
2578
2579static pthread_mutex_t rw_remap_mx = PTHREAD_MUTEX_INITIALIZER;
2580
2581static int rw_remap_used = 0;
2582static pthread_rwlock_t* rw_remap_orig[VG_N_RWLOCKS];
2583static vg_rwlock_t rw_remap_new[VG_N_RWLOCKS];
2584
sewardj2d8b3f02002-06-01 14:14:19 +00002585
2586static
2587void init_vg_rwlock ( vg_rwlock_t* vg_rwl )
2588{
2589 int res = 0;
2590 vg_rwl->initted = 1;
2591 vg_rwl->prefer_w = 1;
2592 vg_rwl->nwait_r = 0;
2593 vg_rwl->nwait_w = 0;
2594 vg_rwl->status = 0;
2595 res = pthread_mutex_init(&vg_rwl->mx, NULL);
2596 res |= pthread_cond_init(&vg_rwl->cv_r, NULL);
2597 res |= pthread_cond_init(&vg_rwl->cv_w, NULL);
sewardj2d94c112002-06-03 01:25:54 +00002598 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002599}
2600
2601
sewardja1ac5cb2002-05-27 13:00:05 +00002602/* Take the address of a LinuxThreads rwlock_t and return the shadow
2603 address of our version. Further, if the LinuxThreads version
2604 appears to have been statically initialised, do the same to the one
2605 we allocate here. The pthread_rwlock_t.__rw_readers field is set
2606 to zero by PTHREAD_RWLOCK_INITIALIZER, so we take zero as meaning
2607 uninitialised and non-zero meaning initialised.
2608*/
2609static vg_rwlock_t* rw_remap ( pthread_rwlock_t* orig )
2610{
2611 int res, i;
2612 vg_rwlock_t* vg_rwl;
2613 res = __pthread_mutex_lock(&rw_remap_mx);
sewardj2d94c112002-06-03 01:25:54 +00002614 my_assert(res == 0);
sewardja1ac5cb2002-05-27 13:00:05 +00002615
2616 for (i = 0; i < rw_remap_used; i++) {
2617 if (rw_remap_orig[i] == orig)
2618 break;
2619 }
2620 if (i == rw_remap_used) {
2621 if (rw_remap_used == VG_N_RWLOCKS) {
sewardj2d8b3f02002-06-01 14:14:19 +00002622 res = __pthread_mutex_unlock(&rw_remap_mx);
sewardj2d94c112002-06-03 01:25:54 +00002623 my_assert(res == 0);
sewardja1ac5cb2002-05-27 13:00:05 +00002624 barf("VG_N_RWLOCKS is too low. Increase and recompile.");
2625 }
2626 rw_remap_used++;
2627 rw_remap_orig[i] = orig;
sewardj2d8b3f02002-06-01 14:14:19 +00002628 rw_remap_new[i].initted = 0;
sewardja1ac5cb2002-05-27 13:00:05 +00002629 if (0) printf("allocated rwlock %d\n", i);
2630 }
2631 res = __pthread_mutex_unlock(&rw_remap_mx);
sewardj2d94c112002-06-03 01:25:54 +00002632 my_assert(res == 0);
sewardja1ac5cb2002-05-27 13:00:05 +00002633 vg_rwl = &rw_remap_new[i];
2634
sewardj2d8b3f02002-06-01 14:14:19 +00002635 /* Initialise the shadow, if required. */
sewardja1ac5cb2002-05-27 13:00:05 +00002636 if (orig->__rw_readers == 0) {
sewardja1ac5cb2002-05-27 13:00:05 +00002637 orig->__rw_readers = 1;
sewardj2d8b3f02002-06-01 14:14:19 +00002638 init_vg_rwlock(vg_rwl);
sewardja1ac5cb2002-05-27 13:00:05 +00002639 if (orig->__rw_kind == PTHREAD_RWLOCK_PREFER_READER_NP)
sewardj2d8b3f02002-06-01 14:14:19 +00002640 vg_rwl->prefer_w = 0;
sewardja1ac5cb2002-05-27 13:00:05 +00002641 }
2642
2643 return vg_rwl;
2644}
2645
2646
sewardja1ac5cb2002-05-27 13:00:05 +00002647int pthread_rwlock_init ( pthread_rwlock_t* orig,
2648 const pthread_rwlockattr_t* attr )
2649{
sewardja1ac5cb2002-05-27 13:00:05 +00002650 vg_rwlock_t* rwl;
2651 if (0) printf ("pthread_rwlock_init\n");
2652 /* Force the remapper to initialise the shadow. */
2653 orig->__rw_readers = 0;
2654 /* Install the lock preference; the remapper needs to know it. */
2655 orig->__rw_kind = PTHREAD_RWLOCK_DEFAULT_NP;
2656 if (attr)
2657 orig->__rw_kind = attr->__lockkind;
2658 rwl = rw_remap ( orig );
sewardj2d8b3f02002-06-01 14:14:19 +00002659 return 0;
sewardja1ac5cb2002-05-27 13:00:05 +00002660}
2661
sewardj2d8b3f02002-06-01 14:14:19 +00002662
2663static
2664void pthread_rwlock_rdlock_CANCEL_HDLR ( void* rwl_v )
sewardja1ac5cb2002-05-27 13:00:05 +00002665{
sewardj2d8b3f02002-06-01 14:14:19 +00002666 vg_rwlock_t* rwl = (vg_rwlock_t*)rwl_v;
2667 rwl->nwait_r--;
2668 pthread_mutex_unlock (&rwl->mx);
sewardja1ac5cb2002-05-27 13:00:05 +00002669}
2670
sewardj2d8b3f02002-06-01 14:14:19 +00002671
sewardja1ac5cb2002-05-27 13:00:05 +00002672int pthread_rwlock_rdlock ( pthread_rwlock_t* orig )
2673{
2674 int res;
2675 vg_rwlock_t* rwl;
2676 if (0) printf ("pthread_rwlock_rdlock\n");
2677 rwl = rw_remap ( orig );
sewardj2d8b3f02002-06-01 14:14:19 +00002678 res = __pthread_mutex_lock(&rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00002679 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002680 if (!rwl->initted) {
2681 res = __pthread_mutex_unlock(&rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00002682 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002683 return EINVAL;
2684 }
2685 if (rwl->status < 0) {
sewardj2d94c112002-06-03 01:25:54 +00002686 my_assert(rwl->status == -1);
sewardj2d8b3f02002-06-01 14:14:19 +00002687 rwl->nwait_r++;
2688 pthread_cleanup_push( pthread_rwlock_rdlock_CANCEL_HDLR, rwl );
2689 while (1) {
2690 if (rwl->status == 0) break;
2691 res = pthread_cond_wait(&rwl->cv_r, &rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00002692 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002693 }
2694 pthread_cleanup_pop(0);
2695 rwl->nwait_r--;
2696 }
sewardj2d94c112002-06-03 01:25:54 +00002697 my_assert(rwl->status >= 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002698 rwl->status++;
2699 res = __pthread_mutex_unlock(&rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00002700 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002701 return 0;
sewardja1ac5cb2002-05-27 13:00:05 +00002702}
2703
sewardj2d8b3f02002-06-01 14:14:19 +00002704
sewardja1ac5cb2002-05-27 13:00:05 +00002705int pthread_rwlock_tryrdlock ( pthread_rwlock_t* orig )
2706{
2707 int res;
2708 vg_rwlock_t* rwl;
2709 if (0) printf ("pthread_rwlock_tryrdlock\n");
2710 rwl = rw_remap ( orig );
sewardj2d8b3f02002-06-01 14:14:19 +00002711 res = __pthread_mutex_lock(&rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00002712 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002713 if (!rwl->initted) {
2714 res = __pthread_mutex_unlock(&rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00002715 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002716 return EINVAL;
2717 }
2718 if (rwl->status == -1) {
2719 /* Writer active; we have to give up. */
2720 res = __pthread_mutex_unlock(&rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00002721 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002722 return EBUSY;
2723 }
2724 /* Success */
sewardj2d94c112002-06-03 01:25:54 +00002725 my_assert(rwl->status >= 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002726 rwl->status++;
2727 res = __pthread_mutex_unlock(&rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00002728 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002729 return 0;
sewardja1ac5cb2002-05-27 13:00:05 +00002730}
2731
sewardj2d8b3f02002-06-01 14:14:19 +00002732
2733static
2734void pthread_rwlock_wrlock_CANCEL_HDLR ( void* rwl_v )
2735{
2736 vg_rwlock_t* rwl = (vg_rwlock_t*)rwl_v;
2737 rwl->nwait_w--;
2738 pthread_mutex_unlock (&rwl->mx);
2739}
2740
2741
sewardja1ac5cb2002-05-27 13:00:05 +00002742int pthread_rwlock_wrlock ( pthread_rwlock_t* orig )
2743{
2744 int res;
2745 vg_rwlock_t* rwl;
2746 if (0) printf ("pthread_rwlock_wrlock\n");
2747 rwl = rw_remap ( orig );
sewardj2d8b3f02002-06-01 14:14:19 +00002748 res = __pthread_mutex_lock(&rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00002749 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002750 if (!rwl->initted) {
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 EINVAL;
2754 }
2755 if (rwl->status != 0) {
2756 rwl->nwait_w++;
2757 pthread_cleanup_push( pthread_rwlock_wrlock_CANCEL_HDLR, rwl );
2758 while (1) {
2759 if (rwl->status == 0) break;
2760 res = pthread_cond_wait(&rwl->cv_w, &rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00002761 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002762 }
2763 pthread_cleanup_pop(0);
2764 rwl->nwait_w--;
2765 }
sewardj2d94c112002-06-03 01:25:54 +00002766 my_assert(rwl->status == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002767 rwl->status = -1;
2768 res = __pthread_mutex_unlock(&rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00002769 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002770 return 0;
sewardja1ac5cb2002-05-27 13:00:05 +00002771}
2772
sewardj2d8b3f02002-06-01 14:14:19 +00002773
sewardja1ac5cb2002-05-27 13:00:05 +00002774int pthread_rwlock_trywrlock ( pthread_rwlock_t* orig )
2775{
2776 int res;
2777 vg_rwlock_t* rwl;
sewardj2d8b3f02002-06-01 14:14:19 +00002778 if (0) printf ("pthread_wrlock_trywrlock\n");
sewardja1ac5cb2002-05-27 13:00:05 +00002779 rwl = rw_remap ( orig );
sewardj2d8b3f02002-06-01 14:14:19 +00002780 res = __pthread_mutex_lock(&rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00002781 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002782 if (!rwl->initted) {
2783 res = __pthread_mutex_unlock(&rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00002784 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002785 return EINVAL;
2786 }
2787 if (rwl->status != 0) {
2788 /* Reader(s) or a writer active; we have to give up. */
2789 res = __pthread_mutex_unlock(&rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00002790 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002791 return EBUSY;
2792 }
2793 /* Success */
sewardj2d94c112002-06-03 01:25:54 +00002794 my_assert(rwl->status == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002795 rwl->status = -1;
2796 res = __pthread_mutex_unlock(&rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00002797 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002798 return 0;
sewardja1ac5cb2002-05-27 13:00:05 +00002799}
2800
sewardj2d8b3f02002-06-01 14:14:19 +00002801
sewardja1ac5cb2002-05-27 13:00:05 +00002802int pthread_rwlock_unlock ( pthread_rwlock_t* orig )
2803{
2804 int res;
2805 vg_rwlock_t* rwl;
2806 if (0) printf ("pthread_rwlock_unlock\n");
2807 rwl = rw_remap ( orig );
sewardj2d8b3f02002-06-01 14:14:19 +00002808 rwl = rw_remap ( orig );
2809 res = __pthread_mutex_lock(&rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00002810 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002811 if (!rwl->initted) {
2812 res = __pthread_mutex_unlock(&rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00002813 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002814 return EINVAL;
2815 }
2816 if (rwl->status == 0) {
2817 res = __pthread_mutex_unlock(&rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00002818 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002819 return EPERM;
2820 }
sewardj2d94c112002-06-03 01:25:54 +00002821 my_assert(rwl->status != 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002822 if (rwl->status == -1) {
2823 rwl->status = 0;
2824 } else {
sewardj2d94c112002-06-03 01:25:54 +00002825 my_assert(rwl->status > 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002826 rwl->status--;
2827 }
2828
sewardj2d94c112002-06-03 01:25:54 +00002829 my_assert(rwl->status >= 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002830
2831 if (rwl->prefer_w) {
2832
2833 /* Favour waiting writers, if any. */
2834 if (rwl->nwait_w > 0) {
2835 /* Writer(s) are waiting. */
2836 if (rwl->status == 0) {
2837 /* We can let a writer in. */
2838 res = pthread_cond_signal(&rwl->cv_w);
sewardj2d94c112002-06-03 01:25:54 +00002839 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002840 } else {
2841 /* There are still readers active. Do nothing; eventually
2842 they will disappear, at which point a writer will be
2843 admitted. */
2844 }
2845 }
2846 else
2847 /* No waiting writers. */
2848 if (rwl->nwait_r > 0) {
2849 /* Let in a waiting reader. */
2850 res = pthread_cond_signal(&rwl->cv_r);
sewardj2d94c112002-06-03 01:25:54 +00002851 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002852 }
2853
2854 } else {
2855
2856 /* Favour waiting readers, if any. */
2857 if (rwl->nwait_r > 0) {
2858 /* Reader(s) are waiting; let one in. */
2859 res = pthread_cond_signal(&rwl->cv_r);
sewardj2d94c112002-06-03 01:25:54 +00002860 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002861 }
2862 else
2863 /* No waiting readers. */
2864 if (rwl->nwait_w > 0 && rwl->status == 0) {
2865 /* We have waiting writers and no active readers; let a
2866 writer in. */
2867 res = pthread_cond_signal(&rwl->cv_w);
sewardj2d94c112002-06-03 01:25:54 +00002868 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002869 }
2870 }
2871
2872 res = __pthread_mutex_unlock(&rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00002873 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002874 return 0;
2875}
2876
2877
2878int pthread_rwlock_destroy ( pthread_rwlock_t *orig )
2879{
2880 int res;
2881 vg_rwlock_t* rwl;
2882 if (0) printf ("pthread_rwlock_destroy\n");
2883 rwl = rw_remap ( orig );
2884 res = __pthread_mutex_lock(&rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00002885 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002886 if (!rwl->initted) {
2887 res = __pthread_mutex_unlock(&rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00002888 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002889 return EINVAL;
2890 }
2891 if (rwl->status != 0 || rwl->nwait_r > 0 || rwl->nwait_w > 0) {
2892 res = __pthread_mutex_unlock(&rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00002893 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002894 return EBUSY;
2895 }
2896 rwl->initted = 0;
2897 res = __pthread_mutex_unlock(&rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00002898 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002899 return 0;
sewardja1ac5cb2002-05-27 13:00:05 +00002900}
2901
2902
sewardj47e4e312002-06-18 09:24:34 +00002903/* Copied directly from LinuxThreads. */
2904int
2905pthread_rwlockattr_init (pthread_rwlockattr_t *attr)
2906{
2907 attr->__lockkind = 0;
2908 attr->__pshared = PTHREAD_PROCESS_PRIVATE;
2909
2910 return 0;
2911}
2912
sewardjfe18eb82002-07-13 12:58:44 +00002913/* Copied directly from LinuxThreads. */
2914int
sewardj5706bfa2002-12-08 23:42:17 +00002915pthread_rwlockattr_destroy (pthread_rwlockattr_t *attr)
2916{
2917 return 0;
2918}
2919
2920/* Copied directly from LinuxThreads. */
2921int
sewardjfe18eb82002-07-13 12:58:44 +00002922pthread_rwlockattr_setpshared (pthread_rwlockattr_t *attr, int pshared)
2923{
2924 if (pshared != PTHREAD_PROCESS_PRIVATE && pshared != PTHREAD_PROCESS_SHARED)
2925 return EINVAL;
2926
2927 /* For now it is not possible to shared a conditional variable. */
2928 if (pshared != PTHREAD_PROCESS_PRIVATE)
2929 return ENOSYS;
2930
2931 attr->__pshared = pshared;
2932
2933 return 0;
2934}
2935
sewardj47e4e312002-06-18 09:24:34 +00002936
sewardja1ac5cb2002-05-27 13:00:05 +00002937/* ---------------------------------------------------------------------
sewardj11f0bb42003-04-26 20:11:15 +00002938 Make SYSV IPC not block everything -- pass to vg_intercept.c.
sewardjd5bef572002-10-23 21:49:33 +00002939 ------------------------------------------------------------------ */
2940
sewardj11f0bb42003-04-26 20:11:15 +00002941WEAK
2942int msgsnd(int msgid, const void *msgp, size_t msgsz, int msgflg)
sewardjd5bef572002-10-23 21:49:33 +00002943{
sewardj11f0bb42003-04-26 20:11:15 +00002944 return VGR_(msgsnd)(msgid, msgp, msgsz, msgflg);
sewardjd5bef572002-10-23 21:49:33 +00002945}
2946
sewardj11f0bb42003-04-26 20:11:15 +00002947WEAK
2948int msgrcv(int msqid, void* msgp, size_t msgsz,
2949 long msgtyp, int msgflg )
sewardjd5bef572002-10-23 21:49:33 +00002950{
sewardj11f0bb42003-04-26 20:11:15 +00002951 return VGR_(msgrcv)(msqid, msgp, msgsz, msgtyp, msgflg );
sewardjd5bef572002-10-23 21:49:33 +00002952}
2953
sewardj262b5be2003-04-26 21:19:53 +00002954
2955/* ---------------------------------------------------------------------
2956 The glibc sources say that returning -1 in these 3 functions
2957 causes real time signals not to be used.
2958 ------------------------------------------------------------------ */
2959
2960int __libc_current_sigrtmin (void)
2961{
2962 static int moans = N_MOANS;
2963 if (moans-- > 0)
2964 kludged("__libc_current_sigrtmin");
2965 return -1;
2966}
2967
2968int __libc_current_sigrtmax (void)
2969{
2970 static int moans = N_MOANS;
2971 if (moans-- > 0)
2972 kludged("__libc_current_sigrtmax");
2973 return -1;
2974}
2975
2976int __libc_allocate_rtsig (int high)
2977{
2978 static int moans = N_MOANS;
2979 if (moans-- > 0)
2980 kludged("__libc_allocate_rtsig");
2981 return -1;
2982}
2983
2984
sewardjd5bef572002-10-23 21:49:33 +00002985/* ---------------------------------------------------------------------
sewardj3b13f0e2002-04-25 20:17:29 +00002986 B'stard.
2987 ------------------------------------------------------------------ */
2988
2989# define strong_alias(name, aliasname) \
2990 extern __typeof (name) aliasname __attribute__ ((alias (#name)));
2991
sewardj5905fae2002-04-26 13:25:00 +00002992# define weak_alias(name, aliasname) \
2993 extern __typeof (name) aliasname __attribute__ ((weak, alias (#name)));
sewardj3b13f0e2002-04-25 20:17:29 +00002994
sewardj5905fae2002-04-26 13:25:00 +00002995strong_alias(__pthread_mutex_lock, pthread_mutex_lock)
2996strong_alias(__pthread_mutex_trylock, pthread_mutex_trylock)
2997strong_alias(__pthread_mutex_unlock, pthread_mutex_unlock)
2998strong_alias(__pthread_mutexattr_init, pthread_mutexattr_init)
2999 weak_alias(__pthread_mutexattr_settype, pthread_mutexattr_settype)
3000strong_alias(__pthread_mutex_init, pthread_mutex_init)
3001strong_alias(__pthread_mutexattr_destroy, pthread_mutexattr_destroy)
3002strong_alias(__pthread_mutex_destroy, pthread_mutex_destroy)
3003strong_alias(__pthread_once, pthread_once)
3004strong_alias(__pthread_atfork, pthread_atfork)
3005strong_alias(__pthread_key_create, pthread_key_create)
3006strong_alias(__pthread_getspecific, pthread_getspecific)
3007strong_alias(__pthread_setspecific, pthread_setspecific)
3008
sewardjd529a442002-05-04 19:49:21 +00003009#ifndef GLIBC_2_1
sewardj3b13f0e2002-04-25 20:17:29 +00003010strong_alias(sigaction, __sigaction)
sewardjd529a442002-05-04 19:49:21 +00003011#endif
3012
sewardj5905fae2002-04-26 13:25:00 +00003013strong_alias(close, __close)
sewardj3b13f0e2002-04-25 20:17:29 +00003014strong_alias(fcntl, __fcntl)
sewardj5905fae2002-04-26 13:25:00 +00003015strong_alias(lseek, __lseek)
3016strong_alias(open, __open)
3017strong_alias(open64, __open64)
sewardj5905fae2002-04-26 13:25:00 +00003018strong_alias(read, __read)
3019strong_alias(wait, __wait)
3020strong_alias(write, __write)
sewardj3b13f0e2002-04-25 20:17:29 +00003021strong_alias(connect, __connect)
sewardj5905fae2002-04-26 13:25:00 +00003022strong_alias(send, __send)
3023
sewardj726c4122002-05-16 23:39:10 +00003024weak_alias (__pread64, pread64)
sewardja18e2102002-05-18 10:43:22 +00003025weak_alias (__pwrite64, pwrite64)
sewardj5905fae2002-04-26 13:25:00 +00003026weak_alias(__fork, fork)
njn25e49d8e72002-09-23 09:36:25 +00003027weak_alias(__vfork, vfork)
sewardj7f6456d2002-05-21 00:51:21 +00003028
sewardjf0b06452002-06-04 08:38:04 +00003029weak_alias (__pthread_kill_other_threads_np, pthread_kill_other_threads_np)
sewardj3b13f0e2002-04-25 20:17:29 +00003030
3031/*--------------------------------------------------*/
3032
sewardj5905fae2002-04-26 13:25:00 +00003033weak_alias(pthread_rwlock_rdlock, __pthread_rwlock_rdlock)
sewardj5905fae2002-04-26 13:25:00 +00003034weak_alias(pthread_rwlock_unlock, __pthread_rwlock_unlock)
sewardj262b0292002-05-01 00:03:16 +00003035weak_alias(pthread_rwlock_wrlock, __pthread_rwlock_wrlock)
sewardj060b04f2002-04-26 21:01:13 +00003036
sewardja1ac5cb2002-05-27 13:00:05 +00003037weak_alias(pthread_rwlock_destroy, __pthread_rwlock_destroy)
3038weak_alias(pthread_rwlock_init, __pthread_rwlock_init)
3039weak_alias(pthread_rwlock_tryrdlock, __pthread_rwlock_tryrdlock)
3040weak_alias(pthread_rwlock_trywrlock, __pthread_rwlock_trywrlock)
3041
sewardj060b04f2002-04-26 21:01:13 +00003042
sewardj3b13f0e2002-04-25 20:17:29 +00003043/* I've no idea what these are, but they get called quite a lot.
3044 Anybody know? */
3045
3046#undef _IO_flockfile
3047void _IO_flockfile ( _IO_FILE * file )
3048{
sewardj853f55d2002-04-26 00:27:53 +00003049 pthread_mutex_lock(file->_lock);
sewardj3b13f0e2002-04-25 20:17:29 +00003050}
sewardj5905fae2002-04-26 13:25:00 +00003051weak_alias(_IO_flockfile, flockfile);
3052
sewardj3b13f0e2002-04-25 20:17:29 +00003053
3054#undef _IO_funlockfile
3055void _IO_funlockfile ( _IO_FILE * file )
3056{
sewardj853f55d2002-04-26 00:27:53 +00003057 pthread_mutex_unlock(file->_lock);
sewardj3b13f0e2002-04-25 20:17:29 +00003058}
sewardj5905fae2002-04-26 13:25:00 +00003059weak_alias(_IO_funlockfile, funlockfile);
3060
sewardj3b13f0e2002-04-25 20:17:29 +00003061
sewardjd4f2c712002-04-30 10:20:10 +00003062/* This doesn't seem to be needed to simulate libpthread.so's external
3063 interface, but many people complain about its absence. */
3064
3065strong_alias(__pthread_mutexattr_settype, __pthread_mutexattr_setkind_np)
3066weak_alias(__pthread_mutexattr_setkind_np, pthread_mutexattr_setkind_np)
sewardj439d45e2002-05-03 20:43:10 +00003067
3068
3069/*--------------------------------------------------------------------*/
3070/*--- end vg_libpthread.c ---*/
3071/*--------------------------------------------------------------------*/