blob: 6b066f3062fa6cc143982469337e0b0b27e2aa89 [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 {
sewardj3665ded2002-05-16 16:57:25 +00001305 errno = retcode;
1306 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
1341 * (__errno_location()) = EINTR;
1342 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
sewardj68b2dd92002-05-10 21:03:56 +00001503 if (res != 0) {
sewardj89d3d852002-04-24 19:21:39 +00001504 barf("pthread_once: Looks like your program's "
1505 "init routine calls back to pthread_once() ?!");
sewardj68b2dd92002-05-10 21:03:56 +00001506 }
sewardj89d3d852002-04-24 19:21:39 +00001507
1508 if (*once_control == 0) {
1509 *once_control = 1;
1510 init_routine();
1511 }
1512
sewardj68b2dd92002-05-10 21:03:56 +00001513 __pthread_mutex_unlock(&once_masterlock);
sewardj89d3d852002-04-24 19:21:39 +00001514
1515 return 0;
1516}
1517
1518
1519/* ---------------------------------------------------
sewardj853f55d2002-04-26 00:27:53 +00001520 MISC
1521 ------------------------------------------------ */
1522
sewardj2cb00342002-06-28 01:46:26 +00001523static pthread_mutex_t pthread_atfork_lock
1524 = PTHREAD_MUTEX_INITIALIZER;
1525
sewardj5905fae2002-04-26 13:25:00 +00001526int __pthread_atfork ( void (*prepare)(void),
1527 void (*parent)(void),
1528 void (*child)(void) )
sewardj853f55d2002-04-26 00:27:53 +00001529{
sewardj2cb00342002-06-28 01:46:26 +00001530 int n, res;
1531 ForkHandlerEntry entry;
1532
1533 ensure_valgrind("pthread_atfork");
1534 __pthread_mutex_lock(&pthread_atfork_lock);
1535
1536 /* Fetch old counter */
1537 VALGRIND_MAGIC_SEQUENCE(n, -2 /* default */,
1538 VG_USERREQ__GET_FHSTACK_USED,
1539 0, 0, 0, 0);
1540 my_assert(n >= 0 && n < VG_N_FORKHANDLERSTACK);
1541 if (n == VG_N_FORKHANDLERSTACK-1)
1542 barf("pthread_atfork: VG_N_FORKHANDLERSTACK is too low; "
1543 "increase and recompile");
1544
1545 /* Add entry */
1546 entry.prepare = *prepare;
1547 entry.parent = *parent;
1548 entry.child = *child;
1549 VALGRIND_MAGIC_SEQUENCE(res, -2 /* default */,
1550 VG_USERREQ__SET_FHSTACK_ENTRY,
1551 n, &entry, 0, 0);
1552 my_assert(res == 0);
1553
1554 /* Bump counter */
1555 VALGRIND_MAGIC_SEQUENCE(res, -2 /* default */,
1556 VG_USERREQ__SET_FHSTACK_USED,
1557 n+1, 0, 0, 0);
1558 my_assert(res == 0);
1559
1560 __pthread_mutex_unlock(&pthread_atfork_lock);
1561 return 0;
sewardj853f55d2002-04-26 00:27:53 +00001562}
1563
1564
sewardj11f0bb42003-04-26 20:11:15 +00001565WEAK
sewardjbb990782002-05-08 02:01:14 +00001566void __pthread_initialize ( void )
1567{
sewardjbea1caa2002-05-10 23:20:58 +00001568 ensure_valgrind("__pthread_initialize");
sewardjbb990782002-05-08 02:01:14 +00001569}
1570
1571
sewardj853f55d2002-04-26 00:27:53 +00001572/* ---------------------------------------------------
sewardj3b13f0e2002-04-25 20:17:29 +00001573 LIBRARY-PRIVATE THREAD SPECIFIC STATE
sewardjf8f819e2002-04-17 23:21:37 +00001574 ------------------------------------------------ */
1575
sewardj3b13f0e2002-04-25 20:17:29 +00001576#include <resolv.h>
1577static int thread_specific_errno[VG_N_THREADS];
1578static int thread_specific_h_errno[VG_N_THREADS];
1579static struct __res_state
1580 thread_specific_res_state[VG_N_THREADS];
sewardjf8f819e2002-04-17 23:21:37 +00001581
sewardj3b13f0e2002-04-25 20:17:29 +00001582int* __errno_location ( void )
sewardjf8f819e2002-04-17 23:21:37 +00001583{
1584 int tid;
sewardj3b13f0e2002-04-25 20:17:29 +00001585 /* ensure_valgrind("__errno_location"); */
1586 VALGRIND_MAGIC_SEQUENCE(tid, 1 /* default */,
sewardjf8f819e2002-04-17 23:21:37 +00001587 VG_USERREQ__PTHREAD_GET_THREADID,
1588 0, 0, 0, 0);
sewardj3b13f0e2002-04-25 20:17:29 +00001589 /* 'cos I'm paranoid ... */
sewardj439d45e2002-05-03 20:43:10 +00001590 if (tid < 1 || tid >= VG_N_THREADS)
sewardj3b13f0e2002-04-25 20:17:29 +00001591 barf("__errno_location: invalid ThreadId");
1592 return & thread_specific_errno[tid];
1593}
1594
1595int* __h_errno_location ( void )
1596{
1597 int tid;
1598 /* ensure_valgrind("__h_errno_location"); */
1599 VALGRIND_MAGIC_SEQUENCE(tid, 1 /* default */,
1600 VG_USERREQ__PTHREAD_GET_THREADID,
1601 0, 0, 0, 0);
1602 /* 'cos I'm paranoid ... */
sewardj439d45e2002-05-03 20:43:10 +00001603 if (tid < 1 || tid >= VG_N_THREADS)
sewardj3b13f0e2002-04-25 20:17:29 +00001604 barf("__h_errno_location: invalid ThreadId");
1605 return & thread_specific_h_errno[tid];
1606}
1607
sewardjb0ff1032002-08-06 09:02:53 +00001608
1609#undef _res
1610extern struct __res_state _res;
1611
sewardj3b13f0e2002-04-25 20:17:29 +00001612struct __res_state* __res_state ( void )
1613{
1614 int tid;
1615 /* ensure_valgrind("__res_state"); */
1616 VALGRIND_MAGIC_SEQUENCE(tid, 1 /* default */,
1617 VG_USERREQ__PTHREAD_GET_THREADID,
1618 0, 0, 0, 0);
1619 /* 'cos I'm paranoid ... */
sewardj439d45e2002-05-03 20:43:10 +00001620 if (tid < 1 || tid >= VG_N_THREADS)
sewardj3b13f0e2002-04-25 20:17:29 +00001621 barf("__res_state: invalid ThreadId");
sewardjb0ff1032002-08-06 09:02:53 +00001622 if (tid == 1)
1623 return & _res;
sewardj3b13f0e2002-04-25 20:17:29 +00001624 return & thread_specific_res_state[tid];
sewardjf8f819e2002-04-17 23:21:37 +00001625}
1626
1627
sewardj5716dbb2002-04-26 03:28:18 +00001628/* ---------------------------------------------------
1629 LIBC-PRIVATE SPECIFIC DATA
1630 ------------------------------------------------ */
1631
1632/* Relies on assumption that initial private data is NULL. This
1633 should be fixed somehow. */
1634
njn25e49d8e72002-09-23 09:36:25 +00001635/* The allowable keys (indices) (all 3 of them).
sewardj5716dbb2002-04-26 03:28:18 +00001636 From sysdeps/pthread/bits/libc-tsd.h
1637*/
sewardjcb7f08a2002-10-02 09:41:49 +00001638/* as per glibc anoncvs HEAD of 20021001. */
sewardj5716dbb2002-04-26 03:28:18 +00001639enum __libc_tsd_key_t { _LIBC_TSD_KEY_MALLOC = 0,
1640 _LIBC_TSD_KEY_DL_ERROR,
njn25e49d8e72002-09-23 09:36:25 +00001641 _LIBC_TSD_KEY_RPC_VARS,
sewardjcb7f08a2002-10-02 09:41:49 +00001642 _LIBC_TSD_KEY_LOCALE,
1643 _LIBC_TSD_KEY_CTYPE_B,
1644 _LIBC_TSD_KEY_CTYPE_TOLOWER,
1645 _LIBC_TSD_KEY_CTYPE_TOUPPER,
sewardj5716dbb2002-04-26 03:28:18 +00001646 _LIBC_TSD_KEY_N };
1647
1648/* Auto-initialising subsystem. libc_specifics_inited is set
1649 after initialisation. libc_specifics_inited_mx guards it. */
1650static int libc_specifics_inited = 0;
1651static pthread_mutex_t libc_specifics_inited_mx = PTHREAD_MUTEX_INITIALIZER;
1652
sewardj00a66b12002-10-12 16:42:35 +00001653
sewardj5716dbb2002-04-26 03:28:18 +00001654/* These are the keys we must initialise the first time. */
sewardjcb7f08a2002-10-02 09:41:49 +00001655static pthread_key_t libc_specifics_keys[_LIBC_TSD_KEY_N];
sewardj5716dbb2002-04-26 03:28:18 +00001656
sewardj00a66b12002-10-12 16:42:35 +00001657
sewardjcb7f08a2002-10-02 09:41:49 +00001658/* Initialise the keys, if they are not already initialised. */
sewardj5716dbb2002-04-26 03:28:18 +00001659static
1660void init_libc_tsd_keys ( void )
1661{
1662 int res, i;
1663 pthread_key_t k;
1664
sewardj08c7f012002-10-07 23:56:55 +00001665 /* Don't fall into deadlock if we get called again whilst we still
1666 hold the lock, via the __uselocale() call herein. */
1667 if (libc_specifics_inited != 0)
1668 return;
1669
1670 /* Take the lock. */
sewardj00a66b12002-10-12 16:42:35 +00001671 res = __pthread_mutex_lock(&libc_specifics_inited_mx);
sewardj5716dbb2002-04-26 03:28:18 +00001672 if (res != 0) barf("init_libc_tsd_keys: lock");
1673
sewardj08c7f012002-10-07 23:56:55 +00001674 /* Now test again, to be sure there is no mistake. */
1675 if (libc_specifics_inited != 0) {
sewardj00a66b12002-10-12 16:42:35 +00001676 res = __pthread_mutex_unlock(&libc_specifics_inited_mx);
sewardj08c7f012002-10-07 23:56:55 +00001677 if (res != 0) barf("init_libc_tsd_keys: unlock(1)");
1678 return;
sewardj5716dbb2002-04-26 03:28:18 +00001679 }
1680
sewardj08c7f012002-10-07 23:56:55 +00001681 /* Actually do the initialisation. */
1682 /* printf("INIT libc specifics\n"); */
1683 for (i = 0; i < _LIBC_TSD_KEY_N; i++) {
sewardj00a66b12002-10-12 16:42:35 +00001684 res = __pthread_key_create(&k, NULL);
sewardj08c7f012002-10-07 23:56:55 +00001685 if (res != 0) barf("init_libc_tsd_keys: create");
1686 libc_specifics_keys[i] = k;
1687 }
1688
1689 /* Signify init done. */
1690 libc_specifics_inited = 1;
1691
1692# ifdef GLIBC_2_3
1693 /* Set the initialising thread's locale to the global (default)
sewardj00a66b12002-10-12 16:42:35 +00001694 locale. A hack in support of glibc-2.3. This does the biz for
1695 the root thread. For all other threads we run this in
1696 thread_wrapper(), which does the real work of
1697 pthread_create(). */
1698 /* assert that we are the root thread. I don't know if this is
1699 really a valid assertion to make; if it breaks I'll reconsider
1700 it. */
1701 my_assert(pthread_self() == 1);
sewardj08c7f012002-10-07 23:56:55 +00001702 __uselocale(LC_GLOBAL_LOCALE);
1703# endif
1704
1705 /* Unlock and return. */
sewardj00a66b12002-10-12 16:42:35 +00001706 res = __pthread_mutex_unlock(&libc_specifics_inited_mx);
sewardj5716dbb2002-04-26 03:28:18 +00001707 if (res != 0) barf("init_libc_tsd_keys: unlock");
1708}
1709
1710
1711static int
1712libc_internal_tsd_set ( enum __libc_tsd_key_t key,
1713 const void * pointer )
1714{
sewardjcb7f08a2002-10-02 09:41:49 +00001715 int res;
sewardj5716dbb2002-04-26 03:28:18 +00001716 /* printf("SET SET SET key %d ptr %p\n", key, pointer); */
sewardjcb7f08a2002-10-02 09:41:49 +00001717 if (key < _LIBC_TSD_KEY_MALLOC || key >= _LIBC_TSD_KEY_N)
sewardj5716dbb2002-04-26 03:28:18 +00001718 barf("libc_internal_tsd_set: invalid key");
1719 init_libc_tsd_keys();
sewardj00a66b12002-10-12 16:42:35 +00001720 res = __pthread_setspecific(libc_specifics_keys[key], pointer);
sewardj5716dbb2002-04-26 03:28:18 +00001721 if (res != 0) barf("libc_internal_tsd_set: setspecific failed");
1722 return 0;
1723}
1724
1725static void *
1726libc_internal_tsd_get ( enum __libc_tsd_key_t key )
1727{
sewardjcb7f08a2002-10-02 09:41:49 +00001728 void* v;
sewardj5716dbb2002-04-26 03:28:18 +00001729 /* printf("GET GET GET key %d\n", key); */
sewardjcb7f08a2002-10-02 09:41:49 +00001730 if (key < _LIBC_TSD_KEY_MALLOC || key >= _LIBC_TSD_KEY_N)
sewardj5716dbb2002-04-26 03:28:18 +00001731 barf("libc_internal_tsd_get: invalid key");
1732 init_libc_tsd_keys();
sewardj00a66b12002-10-12 16:42:35 +00001733 v = __pthread_getspecific(libc_specifics_keys[key]);
sewardj5716dbb2002-04-26 03:28:18 +00001734 /* if (v == NULL) barf("libc_internal_tsd_set: getspecific failed"); */
1735 return v;
1736}
1737
1738
sewardj70adeb22002-04-27 01:35:38 +00001739int (*__libc_internal_tsd_set)
1740 (enum __libc_tsd_key_t key, const void * pointer)
1741 = libc_internal_tsd_set;
sewardj5716dbb2002-04-26 03:28:18 +00001742
sewardj70adeb22002-04-27 01:35:38 +00001743void* (*__libc_internal_tsd_get)
1744 (enum __libc_tsd_key_t key)
1745 = libc_internal_tsd_get;
sewardj5716dbb2002-04-26 03:28:18 +00001746
1747
sewardj00a66b12002-10-12 16:42:35 +00001748#ifdef GLIBC_2_3
1749/* This one was first spotted be me in the glibc-2.2.93 sources. */
1750static void**
1751libc_internal_tsd_address ( enum __libc_tsd_key_t key )
1752{
1753 void** v;
1754 /* printf("ADDR ADDR ADDR key %d\n", key); */
1755 if (key < _LIBC_TSD_KEY_MALLOC || key >= _LIBC_TSD_KEY_N)
1756 barf("libc_internal_tsd_address: invalid key");
1757 init_libc_tsd_keys();
1758 v = __pthread_getspecific_addr(libc_specifics_keys[key]);
1759 return v;
1760}
1761
1762void ** (*__libc_internal_tsd_address)
1763 (enum __libc_tsd_key_t key)
1764 = libc_internal_tsd_address;
1765#endif
1766
1767
sewardje663cb92002-04-12 10:26:32 +00001768/* ---------------------------------------------------------------------
1769 These are here (I think) because they are deemed cancellation
1770 points by POSIX. For the moment we'll simply pass the call along
1771 to the corresponding thread-unaware (?) libc routine.
1772 ------------------------------------------------------------------ */
1773
sewardjd529a442002-05-04 19:49:21 +00001774#ifdef GLIBC_2_1
1775extern
1776int __sigaction
1777 (int signum,
1778 const struct sigaction *act,
1779 struct sigaction *oldact);
1780#else
sewardje663cb92002-04-12 10:26:32 +00001781extern
1782int __libc_sigaction
1783 (int signum,
1784 const struct sigaction *act,
1785 struct sigaction *oldact);
sewardjd529a442002-05-04 19:49:21 +00001786#endif
sewardje663cb92002-04-12 10:26:32 +00001787int sigaction(int signum,
1788 const struct sigaction *act,
1789 struct sigaction *oldact)
1790{
sewardjd140e442002-05-29 01:21:19 +00001791 __my_pthread_testcancel();
sewardj2a1dcce2002-04-22 12:45:25 +00001792# ifdef GLIBC_2_1
1793 return __sigaction(signum, act, oldact);
1794# else
sewardj45b4b372002-04-16 22:50:32 +00001795 return __libc_sigaction(signum, act, oldact);
sewardj2a1dcce2002-04-22 12:45:25 +00001796# endif
sewardje663cb92002-04-12 10:26:32 +00001797}
1798
1799
1800extern
1801int __libc_connect(int sockfd,
1802 const struct sockaddr *serv_addr,
1803 socklen_t addrlen);
sewardj11f0bb42003-04-26 20:11:15 +00001804WEAK
sewardje663cb92002-04-12 10:26:32 +00001805int connect(int sockfd,
1806 const struct sockaddr *serv_addr,
1807 socklen_t addrlen)
1808{
sewardjd140e442002-05-29 01:21:19 +00001809 __my_pthread_testcancel();
sewardj45b4b372002-04-16 22:50:32 +00001810 return __libc_connect(sockfd, serv_addr, addrlen);
sewardje663cb92002-04-12 10:26:32 +00001811}
1812
1813
1814extern
1815int __libc_fcntl(int fd, int cmd, long arg);
sewardj11f0bb42003-04-26 20:11:15 +00001816WEAK
sewardje663cb92002-04-12 10:26:32 +00001817int fcntl(int fd, int cmd, long arg)
1818{
sewardjd140e442002-05-29 01:21:19 +00001819 __my_pthread_testcancel();
sewardj45b4b372002-04-16 22:50:32 +00001820 return __libc_fcntl(fd, cmd, arg);
sewardje663cb92002-04-12 10:26:32 +00001821}
1822
1823
1824extern
1825ssize_t __libc_write(int fd, const void *buf, size_t count);
sewardj11f0bb42003-04-26 20:11:15 +00001826WEAK
sewardje663cb92002-04-12 10:26:32 +00001827ssize_t write(int fd, const void *buf, size_t count)
1828{
sewardjd140e442002-05-29 01:21:19 +00001829 __my_pthread_testcancel();
sewardj45b4b372002-04-16 22:50:32 +00001830 return __libc_write(fd, buf, count);
sewardje663cb92002-04-12 10:26:32 +00001831}
1832
1833
1834extern
1835ssize_t __libc_read(int fd, void *buf, size_t count);
sewardj11f0bb42003-04-26 20:11:15 +00001836WEAK
sewardje663cb92002-04-12 10:26:32 +00001837ssize_t read(int fd, void *buf, size_t count)
1838{
sewardjd140e442002-05-29 01:21:19 +00001839 __my_pthread_testcancel();
sewardj45b4b372002-04-16 22:50:32 +00001840 return __libc_read(fd, buf, count);
sewardje663cb92002-04-12 10:26:32 +00001841}
1842
sewardjf912dfc2002-11-13 21:51:10 +00001843/*
1844 * Ugh, this is horrible but here goes:
1845 *
1846 * Open of a named pipe (fifo file) can block. In a threaded program,
1847 * this means that the whole thing can block. We therefore need to
1848 * make the open appear to block to the caller, but still keep polling
1849 * for everyone else.
1850 *
1851 * There are four cases:
1852 *
1853 * - the caller asked for O_NONBLOCK. The easy one: we just do it.
1854 *
1855 * - the caller asked for a blocking O_RDONLY open. We open it with
1856 * O_NONBLOCK and then use poll to wait for it to become ready.
1857 *
1858 * - the caller asked for a blocking O_WRONLY open. Unfortunately, this
1859 * will fail with ENXIO when we make it non-blocking. Doubly
1860 * unfortunate is that we can only rely on these semantics if it is
1861 * actually a fifo file; the hack is that if we see that it is a
1862 * O_WRONLY open and we get ENXIO, then stat the path and see if it
1863 * actually is a fifo. This is racy, but it is the best we can do.
1864 * If it is a fifo, then keep trying the open until it works; if not
1865 * just return the error.
1866 *
1867 * - the caller asked for a blocking O_RDWR open. Well, under Linux,
1868 * this never blocks, so we just clear the non-blocking flag and
1869 * return.
1870 *
1871 * This code assumes that for whatever we open, O_NONBLOCK followed by
1872 * a fcntl clearing O_NONBLOCK is the same as opening without
1873 * O_NONBLOCK. Also assumes that stat and fstat have no side-effects.
1874 *
1875 * XXX Should probably put in special cases for some devices as well,
1876 * like serial ports. Unfortunately they don't work like fifos, so
1877 * this logic will become even more tortured. Wait until we really
1878 * need it.
1879 */
1880static inline int _open(const char *pathname, int flags, mode_t mode,
1881 int (*openp)(const char *, int, mode_t))
sewardjbe32e452002-04-24 20:29:58 +00001882{
sewardjf912dfc2002-11-13 21:51:10 +00001883 int fd;
1884 struct stat st;
1885 struct vki_timespec nanosleep_interval;
1886 int saved_errno;
1887
sewardjd140e442002-05-29 01:21:19 +00001888 __my_pthread_testcancel();
sewardjf912dfc2002-11-13 21:51:10 +00001889
1890 /* Assume we can only get O_RDONLY, O_WRONLY or O_RDWR */
1891 my_assert((flags & VKI_O_ACCMODE) != VKI_O_ACCMODE);
1892
1893 for(;;) {
1894 fd = (*openp)(pathname, flags | VKI_O_NONBLOCK, mode);
1895
1896 /* return immediately if caller wanted nonblocking anyway */
1897 if (flags & VKI_O_NONBLOCK)
1898 return fd;
1899
1900 saved_errno = errno;
1901
1902 if (fd != -1)
1903 break; /* open worked */
1904
1905 /* If we got ENXIO and we're opening WRONLY, and it turns out
1906 to really be a FIFO, then poll waiting for open to succeed */
1907 if (errno == ENXIO &&
1908 (flags & VKI_O_ACCMODE) == VKI_O_WRONLY &&
1909 (stat(pathname, &st) == 0 && S_ISFIFO(st.st_mode))) {
1910
1911 /* OK, we're opening a FIFO for writing; sleep and spin */
1912 nanosleep_interval.tv_sec = 0;
1913 nanosleep_interval.tv_nsec = 13 * 1000 * 1000; /* 13 milliseconds */
1914 /* It's critical here that valgrind's nanosleep implementation
1915 is nonblocking. */
1916 (void)my_do_syscall2(__NR_nanosleep,
1917 (int)(&nanosleep_interval), (int)NULL);
1918 } else {
1919 /* it was just an error */
1920 errno = saved_errno;
1921 return -1;
1922 }
1923 }
1924
1925 /* OK, we've got a nonblocking FD for a caller who wants blocking;
1926 reset the flags to what they asked for */
1927 fcntl(fd, VKI_F_SETFL, flags);
1928
1929 /* Return now if one of:
1930 - we were opening O_RDWR (never blocks)
1931 - we opened with O_WRONLY (polling already done)
1932 - the thing we opened wasn't a FIFO after all (or fstat failed)
1933 */
1934 if ((flags & VKI_O_ACCMODE) != VKI_O_RDONLY ||
1935 (fstat(fd, &st) == -1 || !S_ISFIFO(st.st_mode))) {
1936 errno = saved_errno;
1937 return fd;
1938 }
1939
1940 /* OK, drop into the poll loop looking for something to read on the fd */
1941 my_assert((flags & VKI_O_ACCMODE) == VKI_O_RDONLY);
1942 for(;;) {
1943 struct pollfd pollfd;
1944 int res;
1945
1946 pollfd.fd = fd;
1947 pollfd.events = POLLIN;
1948 pollfd.revents = 0;
1949
1950 res = my_do_syscall3(__NR_poll, (int)&pollfd, 1, 0);
1951
1952 my_assert(res == 0 || res == 1);
1953
1954 if (res == 1) {
1955 /* OK, got it.
1956
1957 XXX This is wrong: we're waiting for either something to
1958 read or a HUP on the file descriptor, but the semantics of
1959 fifo open are that we should unblock as soon as someone
1960 simply opens the other end, not that they write something.
1961 With luck this won't matter in practice.
1962 */
1963 my_assert(pollfd.revents & (POLLIN|POLLHUP));
1964 break;
1965 }
1966
1967 /* Still nobody home; sleep and spin */
1968 nanosleep_interval.tv_sec = 0;
1969 nanosleep_interval.tv_nsec = 13 * 1000 * 1000; /* 13 milliseconds */
1970 /* It's critical here that valgrind's nanosleep implementation
1971 is nonblocking. */
1972 (void)my_do_syscall2(__NR_nanosleep,
1973 (int)(&nanosleep_interval), (int)NULL);
1974 }
1975
1976 errno = saved_errno;
1977 return fd;
sewardjbe32e452002-04-24 20:29:58 +00001978}
1979
sewardjf912dfc2002-11-13 21:51:10 +00001980extern
1981int __libc_open64(const char *pathname, int flags, mode_t mode);
sewardj11f0bb42003-04-26 20:11:15 +00001982/* WEAK */
sewardjf912dfc2002-11-13 21:51:10 +00001983int open64(const char *pathname, int flags, mode_t mode)
1984{
1985 return _open(pathname, flags, mode, __libc_open64);
1986}
sewardje663cb92002-04-12 10:26:32 +00001987
1988extern
sewardj853f55d2002-04-26 00:27:53 +00001989int __libc_open(const char *pathname, int flags, mode_t mode);
sewardj11f0bb42003-04-26 20:11:15 +00001990/* WEAK */
sewardj853f55d2002-04-26 00:27:53 +00001991int open(const char *pathname, int flags, mode_t mode)
sewardje663cb92002-04-12 10:26:32 +00001992{
sewardjf912dfc2002-11-13 21:51:10 +00001993 return _open(pathname, flags, mode, __libc_open);
sewardje663cb92002-04-12 10:26:32 +00001994}
1995
sewardje663cb92002-04-12 10:26:32 +00001996extern
1997int __libc_close(int fd);
sewardj11f0bb42003-04-26 20:11:15 +00001998WEAK
sewardje663cb92002-04-12 10:26:32 +00001999int close(int fd)
2000{
sewardjd140e442002-05-29 01:21:19 +00002001 __my_pthread_testcancel();
sewardj45b4b372002-04-16 22:50:32 +00002002 return __libc_close(fd);
sewardje663cb92002-04-12 10:26:32 +00002003}
2004
2005
sewardj11f0bb42003-04-26 20:11:15 +00002006WEAK
2007int accept(int s, struct sockaddr *addr, socklen_t *addrlen)
sewardje663cb92002-04-12 10:26:32 +00002008{
sewardj11f0bb42003-04-26 20:11:15 +00002009 return VGR_(accept)(s, addr, addrlen);
sewardje663cb92002-04-12 10:26:32 +00002010}
2011
sewardj11f0bb42003-04-26 20:11:15 +00002012WEAK
2013int recv(int s, void *buf, size_t len, int flags)
sewardj0c573af92002-10-23 21:55:01 +00002014{
sewardj11f0bb42003-04-26 20:11:15 +00002015 return VGR_(recv)(s, buf, len, flags);
sewardj0c573af92002-10-23 21:55:01 +00002016}
2017
sewardj11f0bb42003-04-26 20:11:15 +00002018WEAK
2019int readv(int fd, const struct iovec *iov, int count)
sewardj2a68e7e2002-11-16 11:04:18 +00002020{
sewardj11f0bb42003-04-26 20:11:15 +00002021 return VGR_(readv)(fd, iov, count);
sewardj2a68e7e2002-11-16 11:04:18 +00002022}
2023
sewardj11f0bb42003-04-26 20:11:15 +00002024WEAK
2025int writev(int fd, const struct iovec *iov, int count)
sewardj2a68e7e2002-11-16 11:04:18 +00002026{
sewardj11f0bb42003-04-26 20:11:15 +00002027 return VGR_(writev)(fd, iov, count);
sewardj2a68e7e2002-11-16 11:04:18 +00002028}
sewardje663cb92002-04-12 10:26:32 +00002029
2030extern
sewardje663cb92002-04-12 10:26:32 +00002031pid_t __libc_waitpid(pid_t pid, int *status, int options);
sewardj11f0bb42003-04-26 20:11:15 +00002032WEAK
sewardje663cb92002-04-12 10:26:32 +00002033pid_t waitpid(pid_t pid, int *status, int options)
2034{
sewardjd140e442002-05-29 01:21:19 +00002035 __my_pthread_testcancel();
sewardj45b4b372002-04-16 22:50:32 +00002036 return __libc_waitpid(pid, status, options);
sewardje663cb92002-04-12 10:26:32 +00002037}
2038
2039
2040extern
2041int __libc_nanosleep(const struct timespec *req, struct timespec *rem);
sewardj11f0bb42003-04-26 20:11:15 +00002042WEAK
sewardje663cb92002-04-12 10:26:32 +00002043int nanosleep(const struct timespec *req, struct timespec *rem)
2044{
sewardjd140e442002-05-29 01:21:19 +00002045 __my_pthread_testcancel();
sewardje663cb92002-04-12 10:26:32 +00002046 return __libc_nanosleep(req, rem);
2047}
2048
sewardjbe32e452002-04-24 20:29:58 +00002049
sewardje663cb92002-04-12 10:26:32 +00002050extern
2051int __libc_fsync(int fd);
sewardj11f0bb42003-04-26 20:11:15 +00002052WEAK
sewardje663cb92002-04-12 10:26:32 +00002053int fsync(int fd)
2054{
sewardjd140e442002-05-29 01:21:19 +00002055 __my_pthread_testcancel();
sewardj45b4b372002-04-16 22:50:32 +00002056 return __libc_fsync(fd);
sewardje663cb92002-04-12 10:26:32 +00002057}
2058
sewardjbe32e452002-04-24 20:29:58 +00002059
sewardj70c75362002-04-13 04:18:32 +00002060extern
2061off_t __libc_lseek(int fildes, off_t offset, int whence);
sewardj11f0bb42003-04-26 20:11:15 +00002062WEAK
sewardj70c75362002-04-13 04:18:32 +00002063off_t lseek(int fildes, off_t offset, int whence)
2064{
sewardjd140e442002-05-29 01:21:19 +00002065 __my_pthread_testcancel();
sewardj45b4b372002-04-16 22:50:32 +00002066 return __libc_lseek(fildes, offset, whence);
sewardj70c75362002-04-13 04:18:32 +00002067}
2068
sewardjbe32e452002-04-24 20:29:58 +00002069
2070extern
2071__off64_t __libc_lseek64(int fildes, __off64_t offset, int whence);
sewardj11f0bb42003-04-26 20:11:15 +00002072WEAK
sewardjbe32e452002-04-24 20:29:58 +00002073__off64_t lseek64(int fildes, __off64_t offset, int whence)
2074{
sewardjd140e442002-05-29 01:21:19 +00002075 __my_pthread_testcancel();
sewardjbe32e452002-04-24 20:29:58 +00002076 return __libc_lseek64(fildes, offset, whence);
2077}
2078
2079
sewardj726c4122002-05-16 23:39:10 +00002080extern
2081ssize_t __libc_pread64 (int __fd, void *__buf, size_t __nbytes,
2082 __off64_t __offset);
2083ssize_t __pread64 (int __fd, void *__buf, size_t __nbytes,
2084 __off64_t __offset)
2085{
sewardjd140e442002-05-29 01:21:19 +00002086 __my_pthread_testcancel();
sewardj726c4122002-05-16 23:39:10 +00002087 return __libc_pread64(__fd, __buf, __nbytes, __offset);
2088}
2089
2090
sewardja18e2102002-05-18 10:43:22 +00002091extern
2092ssize_t __libc_pwrite64 (int __fd, const void *__buf, size_t __nbytes,
2093 __off64_t __offset);
2094ssize_t __pwrite64 (int __fd, const void *__buf, size_t __nbytes,
2095 __off64_t __offset)
2096{
sewardjd140e442002-05-29 01:21:19 +00002097 __my_pthread_testcancel();
sewardja18e2102002-05-18 10:43:22 +00002098 return __libc_pwrite64(__fd, __buf, __nbytes, __offset);
2099}
2100
sewardj726c4122002-05-16 23:39:10 +00002101
sewardj39b93b12002-05-18 10:56:27 +00002102extern
2103ssize_t __libc_pwrite(int fd, const void *buf, size_t count, off_t offset);
sewardj11f0bb42003-04-26 20:11:15 +00002104WEAK
sewardj39b93b12002-05-18 10:56:27 +00002105ssize_t pwrite(int fd, const void *buf, size_t count, off_t offset)
2106{
sewardjd140e442002-05-29 01:21:19 +00002107 __my_pthread_testcancel();
sewardj39b93b12002-05-18 10:56:27 +00002108 return __libc_pwrite(fd, buf, count, offset);
2109}
2110
2111
2112extern
2113ssize_t __libc_pread(int fd, void *buf, size_t count, off_t offset);
sewardj11f0bb42003-04-26 20:11:15 +00002114WEAK
sewardj39b93b12002-05-18 10:56:27 +00002115ssize_t pread(int fd, void *buf, size_t count, off_t offset)
2116{
sewardjd140e442002-05-29 01:21:19 +00002117 __my_pthread_testcancel();
sewardj39b93b12002-05-18 10:56:27 +00002118 return __libc_pread(fd, buf, count, offset);
2119}
2120
2121
sewardj6af4b5d2002-04-16 04:40:49 +00002122extern
2123void __libc_longjmp(jmp_buf env, int val) __attribute((noreturn));
sewardj11f0bb42003-04-26 20:11:15 +00002124/* not weak: WEAK */
sewardj6af4b5d2002-04-16 04:40:49 +00002125void longjmp(jmp_buf env, int val)
2126{
2127 __libc_longjmp(env, val);
2128}
2129
sewardjbe32e452002-04-24 20:29:58 +00002130
sewardj436c2db2002-06-18 09:07:54 +00002131extern void __libc_siglongjmp (sigjmp_buf env, int val)
2132 __attribute__ ((noreturn));
2133void siglongjmp(sigjmp_buf env, int val)
2134{
2135 kludged("siglongjmp (cleanup handlers are ignored)");
2136 __libc_siglongjmp(env, val);
2137}
2138
2139
sewardj6af4b5d2002-04-16 04:40:49 +00002140extern
2141int __libc_send(int s, const void *msg, size_t len, int flags);
sewardj11f0bb42003-04-26 20:11:15 +00002142WEAK
sewardj6af4b5d2002-04-16 04:40:49 +00002143int send(int s, const void *msg, size_t len, int flags)
2144{
sewardjd140e442002-05-29 01:21:19 +00002145 __my_pthread_testcancel();
sewardj6af4b5d2002-04-16 04:40:49 +00002146 return __libc_send(s, msg, len, flags);
2147}
2148
sewardjbe32e452002-04-24 20:29:58 +00002149
sewardj3665ded2002-05-16 16:57:25 +00002150extern
2151int __libc_sendmsg(int s, const struct msghdr *msg, int flags);
sewardj11f0bb42003-04-26 20:11:15 +00002152WEAK
sewardj3665ded2002-05-16 16:57:25 +00002153int sendmsg(int s, const struct msghdr *msg, int flags)
2154{
sewardjd140e442002-05-29 01:21:19 +00002155 __my_pthread_testcancel();
sewardj3665ded2002-05-16 16:57:25 +00002156 return __libc_sendmsg(s, msg, flags);
2157}
2158
2159
sewardj796d6a22002-04-24 02:28:34 +00002160extern
sewardj59da27a2002-06-06 08:33:54 +00002161int __libc_recvmsg(int s, struct msghdr *msg, int flags);
sewardj11f0bb42003-04-26 20:11:15 +00002162WEAK
sewardj59da27a2002-06-06 08:33:54 +00002163int recvmsg(int s, struct msghdr *msg, int flags)
2164{
2165 __my_pthread_testcancel();
2166 return __libc_recvmsg(s, msg, flags);
2167}
2168
2169
2170extern
sewardj436e0582002-04-26 14:31:40 +00002171int __libc_recvfrom(int s, void *buf, size_t len, int flags,
2172 struct sockaddr *from, socklen_t *fromlen);
sewardj11f0bb42003-04-26 20:11:15 +00002173WEAK
sewardj436e0582002-04-26 14:31:40 +00002174int recvfrom(int s, void *buf, size_t len, int flags,
2175 struct sockaddr *from, socklen_t *fromlen)
2176{
sewardjd140e442002-05-29 01:21:19 +00002177 __my_pthread_testcancel();
sewardj11f0bb42003-04-26 20:11:15 +00002178 VGR_(wait_for_fd_to_be_readable_or_erring)(s);
sewardj2e207632002-06-13 17:29:53 +00002179 __my_pthread_testcancel();
sewardj436e0582002-04-26 14:31:40 +00002180 return __libc_recvfrom(s, buf, len, flags, from, fromlen);
2181}
2182
2183
2184extern
sewardj796d6a22002-04-24 02:28:34 +00002185int __libc_sendto(int s, const void *msg, size_t len, int flags,
2186 const struct sockaddr *to, socklen_t tolen);
sewardj11f0bb42003-04-26 20:11:15 +00002187WEAK
sewardj796d6a22002-04-24 02:28:34 +00002188int sendto(int s, const void *msg, size_t len, int flags,
2189 const struct sockaddr *to, socklen_t tolen)
2190{
sewardjd140e442002-05-29 01:21:19 +00002191 __my_pthread_testcancel();
sewardj796d6a22002-04-24 02:28:34 +00002192 return __libc_sendto(s, msg, len, flags, to, tolen);
2193}
2194
sewardjbe32e452002-04-24 20:29:58 +00002195
sewardj369b1702002-04-24 13:28:15 +00002196extern
2197int __libc_system(const char* str);
sewardj11f0bb42003-04-26 20:11:15 +00002198WEAK
sewardj369b1702002-04-24 13:28:15 +00002199int system(const char* str)
2200{
sewardjd140e442002-05-29 01:21:19 +00002201 __my_pthread_testcancel();
sewardj369b1702002-04-24 13:28:15 +00002202 return __libc_system(str);
2203}
2204
sewardjbe32e452002-04-24 20:29:58 +00002205
sewardjab0b1c32002-04-24 19:26:47 +00002206extern
2207pid_t __libc_wait(int *status);
sewardj11f0bb42003-04-26 20:11:15 +00002208WEAK
sewardjab0b1c32002-04-24 19:26:47 +00002209pid_t wait(int *status)
2210{
sewardjd140e442002-05-29 01:21:19 +00002211 __my_pthread_testcancel();
sewardjab0b1c32002-04-24 19:26:47 +00002212 return __libc_wait(status);
2213}
2214
sewardj45b4b372002-04-16 22:50:32 +00002215
sewardj67f1d582002-05-24 02:11:32 +00002216extern
2217int __libc_msync(const void *start, size_t length, int flags);
sewardj11f0bb42003-04-26 20:11:15 +00002218WEAK
sewardj67f1d582002-05-24 02:11:32 +00002219int msync(const void *start, size_t length, int flags)
2220{
sewardjd140e442002-05-29 01:21:19 +00002221 __my_pthread_testcancel();
sewardj67f1d582002-05-24 02:11:32 +00002222 return __libc_msync(start, length, flags);
2223}
2224
sewardj5905fae2002-04-26 13:25:00 +00002225
sewardj2cb00342002-06-28 01:46:26 +00002226/*--- fork and its helper ---*/
2227
2228static
2229void run_fork_handlers ( int what )
2230{
2231 ForkHandlerEntry entry;
2232 int n_h, n_handlers, i, res;
2233
2234 my_assert(what == 0 || what == 1 || what == 2);
2235
2236 /* Fetch old counter */
2237 VALGRIND_MAGIC_SEQUENCE(n_handlers, -2 /* default */,
2238 VG_USERREQ__GET_FHSTACK_USED,
2239 0, 0, 0, 0);
2240 my_assert(n_handlers >= 0 && n_handlers < VG_N_FORKHANDLERSTACK);
2241
2242 /* Prepare handlers (what == 0) are called in opposite order of
2243 calls to pthread_atfork. Parent and child handlers are called
2244 in the same order as calls to pthread_atfork. */
2245 if (what == 0)
2246 n_h = n_handlers - 1;
2247 else
2248 n_h = 0;
2249
2250 for (i = 0; i < n_handlers; i++) {
2251 VALGRIND_MAGIC_SEQUENCE(res, -2 /* default */,
2252 VG_USERREQ__GET_FHSTACK_ENTRY,
2253 n_h, &entry, 0, 0);
2254 my_assert(res == 0);
2255 switch (what) {
2256 case 0: if (entry.prepare) entry.prepare();
2257 n_h--; break;
2258 case 1: if (entry.parent) entry.parent();
2259 n_h++; break;
2260 case 2: if (entry.child) entry.child();
2261 n_h++; break;
2262 default: barf("run_fork_handlers: invalid what");
2263 }
2264 }
2265
2266 if (what != 0 /* prepare */) {
2267 /* Empty out the stack. */
2268 VALGRIND_MAGIC_SEQUENCE(res, -2 /* default */,
2269 VG_USERREQ__SET_FHSTACK_USED,
2270 0, 0, 0, 0);
2271 my_assert(res == 0);
2272 }
2273}
2274
2275extern
2276pid_t __libc_fork(void);
2277pid_t __fork(void)
2278{
2279 pid_t pid;
2280 __my_pthread_testcancel();
2281 __pthread_mutex_lock(&pthread_atfork_lock);
2282
2283 run_fork_handlers(0 /* prepare */);
2284 pid = __libc_fork();
2285 if (pid == 0) {
2286 /* I am the child */
2287 run_fork_handlers(2 /* child */);
sewardjd8acdf22002-11-13 21:57:52 +00002288 __pthread_mutex_unlock(&pthread_atfork_lock);
sewardj2cb00342002-06-28 01:46:26 +00002289 __pthread_mutex_init(&pthread_atfork_lock, NULL);
2290 } else {
2291 /* I am the parent */
2292 run_fork_handlers(1 /* parent */);
2293 __pthread_mutex_unlock(&pthread_atfork_lock);
2294 }
2295 return pid;
2296}
2297
2298
njn25e49d8e72002-09-23 09:36:25 +00002299pid_t __vfork(void)
2300{
2301 return __fork();
2302}
sewardj2cb00342002-06-28 01:46:26 +00002303
2304
sewardj08a4c3f2002-04-13 03:45:44 +00002305static
sewardj08a4c3f2002-04-13 03:45:44 +00002306int my_do_syscall1 ( int syscallno, int arg1 )
2307{
2308 int __res;
2309 __asm__ volatile ("pushl %%ebx; movl %%edx,%%ebx ; int $0x80 ; popl %%ebx"
2310 : "=a" (__res)
2311 : "0" (syscallno),
2312 "d" (arg1) );
2313 return __res;
2314}
2315
2316static
2317int my_do_syscall2 ( int syscallno,
sewardjf854f472002-04-21 12:19:41 +00002318 int arg1, int arg2 )
sewardj08a4c3f2002-04-13 03:45:44 +00002319{
2320 int __res;
2321 __asm__ volatile ("pushl %%ebx; movl %%edx,%%ebx ; int $0x80 ; popl %%ebx"
2322 : "=a" (__res)
2323 : "0" (syscallno),
2324 "d" (arg1),
2325 "c" (arg2) );
2326 return __res;
2327}
2328
2329static
sewardjf854f472002-04-21 12:19:41 +00002330int my_do_syscall3 ( int syscallno,
2331 int arg1, int arg2, int arg3 )
2332{
2333 int __res;
2334 __asm__ volatile ("pushl %%ebx; movl %%esi,%%ebx ; int $0x80 ; popl %%ebx"
2335 : "=a" (__res)
2336 : "0" (syscallno),
2337 "S" (arg1),
2338 "c" (arg2),
2339 "d" (arg3) );
2340 return __res;
2341}
2342
sewardjd5bef572002-10-23 21:49:33 +00002343static inline
2344int my_do_syscall5 ( int syscallno,
2345 int arg1, int arg2, int arg3, int arg4, int arg5 )
2346{
2347 int __res;
2348 __asm__ volatile ("int $0x80"
2349 : "=a" (__res)
2350 : "0" (syscallno),
2351 "b" (arg1),
2352 "c" (arg2),
2353 "d" (arg3),
2354 "S" (arg4),
2355 "D" (arg5));
2356 return __res;
2357}
2358
sewardj11f0bb42003-04-26 20:11:15 +00002359
2360WEAK
2361int select ( int n,
2362 fd_set *rfds,
2363 fd_set *wfds,
2364 fd_set *xfds,
2365 struct timeval *timeout )
sewardj08a4c3f2002-04-13 03:45:44 +00002366{
sewardj11f0bb42003-04-26 20:11:15 +00002367 return VGR_(select)(n, rfds, wfds, xfds, timeout);
sewardj08a4c3f2002-04-13 03:45:44 +00002368}
2369
2370
sewardj3b13f0e2002-04-25 20:17:29 +00002371/* ---------------------------------------------------------------------
sewardj8f253ff2002-05-19 00:13:34 +00002372 Hacky implementation of semaphores.
2373 ------------------------------------------------------------------ */
2374
2375#include <semaphore.h>
2376
2377/* This is a terrible way to do the remapping. Plan is to import an
2378 AVL tree at some point. */
sewardj8f253ff2002-05-19 00:13:34 +00002379
2380typedef
2381 struct {
2382 pthread_mutex_t se_mx;
2383 pthread_cond_t se_cv;
2384 int count;
2385 }
2386 vg_sem_t;
2387
2388static pthread_mutex_t se_remap_mx = PTHREAD_MUTEX_INITIALIZER;
2389
2390static int se_remap_used = 0;
2391static sem_t* se_remap_orig[VG_N_SEMAPHORES];
2392static vg_sem_t se_remap_new[VG_N_SEMAPHORES];
2393
2394static vg_sem_t* se_remap ( sem_t* orig )
2395{
2396 int res, i;
2397 res = __pthread_mutex_lock(&se_remap_mx);
sewardj2d94c112002-06-03 01:25:54 +00002398 my_assert(res == 0);
sewardj8f253ff2002-05-19 00:13:34 +00002399
2400 for (i = 0; i < se_remap_used; i++) {
2401 if (se_remap_orig[i] == orig)
2402 break;
2403 }
2404 if (i == se_remap_used) {
2405 if (se_remap_used == VG_N_SEMAPHORES) {
2406 res = pthread_mutex_unlock(&se_remap_mx);
sewardj2d94c112002-06-03 01:25:54 +00002407 my_assert(res == 0);
sewardja1ac5cb2002-05-27 13:00:05 +00002408 barf("VG_N_SEMAPHORES is too low. Increase and recompile.");
sewardj8f253ff2002-05-19 00:13:34 +00002409 }
2410 se_remap_used++;
2411 se_remap_orig[i] = orig;
2412 /* printf("allocated semaphore %d\n", i); */
2413 }
2414 res = __pthread_mutex_unlock(&se_remap_mx);
sewardj2d94c112002-06-03 01:25:54 +00002415 my_assert(res == 0);
sewardj8f253ff2002-05-19 00:13:34 +00002416 return &se_remap_new[i];
2417}
2418
2419
2420int sem_init(sem_t *sem, int pshared, unsigned int value)
2421{
2422 int res;
2423 vg_sem_t* vg_sem;
2424 ensure_valgrind("sem_init");
2425 if (pshared != 0) {
sewardj4dced352002-06-04 22:54:20 +00002426 pthread_error("sem_init: unsupported pshared value");
sewardj8f253ff2002-05-19 00:13:34 +00002427 errno = ENOSYS;
2428 return -1;
2429 }
2430 vg_sem = se_remap(sem);
2431 res = pthread_mutex_init(&vg_sem->se_mx, NULL);
sewardj2d94c112002-06-03 01:25:54 +00002432 my_assert(res == 0);
sewardj8f253ff2002-05-19 00:13:34 +00002433 res = pthread_cond_init(&vg_sem->se_cv, NULL);
sewardj2d94c112002-06-03 01:25:54 +00002434 my_assert(res == 0);
sewardj8f253ff2002-05-19 00:13:34 +00002435 vg_sem->count = value;
2436 return 0;
2437}
2438
2439
2440int sem_wait ( sem_t* sem )
2441{
2442 int res;
2443 vg_sem_t* vg_sem;
2444 ensure_valgrind("sem_wait");
2445 vg_sem = se_remap(sem);
2446 res = __pthread_mutex_lock(&vg_sem->se_mx);
sewardj2d94c112002-06-03 01:25:54 +00002447 my_assert(res == 0);
sewardj8f253ff2002-05-19 00:13:34 +00002448 while (vg_sem->count == 0) {
2449 res = pthread_cond_wait(&vg_sem->se_cv, &vg_sem->se_mx);
sewardj2d94c112002-06-03 01:25:54 +00002450 my_assert(res == 0);
sewardj8f253ff2002-05-19 00:13:34 +00002451 }
2452 vg_sem->count--;
2453 res = __pthread_mutex_unlock(&vg_sem->se_mx);
sewardj2d94c112002-06-03 01:25:54 +00002454 my_assert(res == 0);
sewardj8f253ff2002-05-19 00:13:34 +00002455 return 0;
2456}
2457
2458int sem_post ( sem_t* sem )
2459{
2460 int res;
2461 vg_sem_t* vg_sem;
2462 ensure_valgrind("sem_post");
2463 vg_sem = se_remap(sem);
2464 res = __pthread_mutex_lock(&vg_sem->se_mx);
sewardj2d94c112002-06-03 01:25:54 +00002465 my_assert(res == 0);
sewardj8f253ff2002-05-19 00:13:34 +00002466 if (vg_sem->count == 0) {
2467 vg_sem->count++;
2468 res = pthread_cond_broadcast(&vg_sem->se_cv);
sewardj2d94c112002-06-03 01:25:54 +00002469 my_assert(res == 0);
sewardj8f253ff2002-05-19 00:13:34 +00002470 } else {
2471 vg_sem->count++;
2472 }
2473 res = __pthread_mutex_unlock(&vg_sem->se_mx);
sewardj2d94c112002-06-03 01:25:54 +00002474 my_assert(res == 0);
sewardj8f253ff2002-05-19 00:13:34 +00002475 return 0;
2476}
2477
2478
2479int sem_trywait ( sem_t* sem )
2480{
2481 int ret, res;
2482 vg_sem_t* vg_sem;
2483 ensure_valgrind("sem_trywait");
2484 vg_sem = se_remap(sem);
2485 res = __pthread_mutex_lock(&vg_sem->se_mx);
sewardj2d94c112002-06-03 01:25:54 +00002486 my_assert(res == 0);
sewardj8f253ff2002-05-19 00:13:34 +00002487 if (vg_sem->count > 0) {
2488 vg_sem->count--;
2489 ret = 0;
2490 } else {
2491 ret = -1;
2492 errno = EAGAIN;
2493 }
2494 res = __pthread_mutex_unlock(&vg_sem->se_mx);
sewardj2d94c112002-06-03 01:25:54 +00002495 my_assert(res == 0);
sewardj8f253ff2002-05-19 00:13:34 +00002496 return ret;
2497}
2498
2499
2500int sem_getvalue(sem_t* sem, int * sval)
2501{
2502 vg_sem_t* vg_sem;
2503 ensure_valgrind("sem_trywait");
2504 vg_sem = se_remap(sem);
2505 *sval = vg_sem->count;
2506 return 0;
2507}
2508
2509
2510int sem_destroy(sem_t * sem)
2511{
2512 kludged("sem_destroy");
2513 /* if someone waiting on this semaphore, errno = EBUSY, return -1 */
2514 return 0;
2515}
2516
sewardj9ad92d92002-10-16 19:45:06 +00002517
2518int sem_timedwait(sem_t* sem, const struct timespec *abstime)
2519{
2520 int res;
2521 vg_sem_t* vg_sem;
2522 ensure_valgrind("sem_timedwait");
2523 vg_sem = se_remap(sem);
2524 res = __pthread_mutex_lock(&vg_sem->se_mx);
2525 my_assert(res == 0);
2526 while ( vg_sem->count == 0 && res != ETIMEDOUT ) {
2527 res = pthread_cond_timedwait(&vg_sem->se_cv, &vg_sem->se_mx, abstime);
2528 }
2529 if ( vg_sem->count > 0 ) {
2530 vg_sem->count--;
2531 res = __pthread_mutex_unlock(&vg_sem->se_mx);
2532 my_assert(res == 0 );
2533 return 0;
2534 } else {
2535 res = __pthread_mutex_unlock(&vg_sem->se_mx);
2536 my_assert(res == 0 );
2537 *(__errno_location()) = ETIMEDOUT;
2538 return -1;
2539 }
2540}
2541
sewardj8f253ff2002-05-19 00:13:34 +00002542
2543/* ---------------------------------------------------------------------
sewardj2d8b3f02002-06-01 14:14:19 +00002544 Reader-writer locks.
sewardja1ac5cb2002-05-27 13:00:05 +00002545 ------------------------------------------------------------------ */
2546
sewardj2d8b3f02002-06-01 14:14:19 +00002547typedef
2548 struct {
2549 int initted; /* != 0 --> in use; sanity check only */
2550 int prefer_w; /* != 0 --> prefer writer */
2551 int nwait_r; /* # of waiting readers */
2552 int nwait_w; /* # of waiting writers */
2553 pthread_cond_t cv_r; /* for signalling readers */
2554 pthread_cond_t cv_w; /* for signalling writers */
2555 pthread_mutex_t mx;
2556 int status;
2557 /* allowed range for status: >= -1. -1 means 1 writer currently
2558 active, >= 0 means N readers currently active. */
2559 }
2560 vg_rwlock_t;
sewardja1ac5cb2002-05-27 13:00:05 +00002561
2562
2563static pthread_mutex_t rw_remap_mx = PTHREAD_MUTEX_INITIALIZER;
2564
2565static int rw_remap_used = 0;
2566static pthread_rwlock_t* rw_remap_orig[VG_N_RWLOCKS];
2567static vg_rwlock_t rw_remap_new[VG_N_RWLOCKS];
2568
sewardj2d8b3f02002-06-01 14:14:19 +00002569
2570static
2571void init_vg_rwlock ( vg_rwlock_t* vg_rwl )
2572{
2573 int res = 0;
2574 vg_rwl->initted = 1;
2575 vg_rwl->prefer_w = 1;
2576 vg_rwl->nwait_r = 0;
2577 vg_rwl->nwait_w = 0;
2578 vg_rwl->status = 0;
2579 res = pthread_mutex_init(&vg_rwl->mx, NULL);
2580 res |= pthread_cond_init(&vg_rwl->cv_r, NULL);
2581 res |= pthread_cond_init(&vg_rwl->cv_w, NULL);
sewardj2d94c112002-06-03 01:25:54 +00002582 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002583}
2584
2585
sewardja1ac5cb2002-05-27 13:00:05 +00002586/* Take the address of a LinuxThreads rwlock_t and return the shadow
2587 address of our version. Further, if the LinuxThreads version
2588 appears to have been statically initialised, do the same to the one
2589 we allocate here. The pthread_rwlock_t.__rw_readers field is set
2590 to zero by PTHREAD_RWLOCK_INITIALIZER, so we take zero as meaning
2591 uninitialised and non-zero meaning initialised.
2592*/
2593static vg_rwlock_t* rw_remap ( pthread_rwlock_t* orig )
2594{
2595 int res, i;
2596 vg_rwlock_t* vg_rwl;
2597 res = __pthread_mutex_lock(&rw_remap_mx);
sewardj2d94c112002-06-03 01:25:54 +00002598 my_assert(res == 0);
sewardja1ac5cb2002-05-27 13:00:05 +00002599
2600 for (i = 0; i < rw_remap_used; i++) {
2601 if (rw_remap_orig[i] == orig)
2602 break;
2603 }
2604 if (i == rw_remap_used) {
2605 if (rw_remap_used == VG_N_RWLOCKS) {
sewardj2d8b3f02002-06-01 14:14:19 +00002606 res = __pthread_mutex_unlock(&rw_remap_mx);
sewardj2d94c112002-06-03 01:25:54 +00002607 my_assert(res == 0);
sewardja1ac5cb2002-05-27 13:00:05 +00002608 barf("VG_N_RWLOCKS is too low. Increase and recompile.");
2609 }
2610 rw_remap_used++;
2611 rw_remap_orig[i] = orig;
sewardj2d8b3f02002-06-01 14:14:19 +00002612 rw_remap_new[i].initted = 0;
sewardja1ac5cb2002-05-27 13:00:05 +00002613 if (0) printf("allocated rwlock %d\n", i);
2614 }
2615 res = __pthread_mutex_unlock(&rw_remap_mx);
sewardj2d94c112002-06-03 01:25:54 +00002616 my_assert(res == 0);
sewardja1ac5cb2002-05-27 13:00:05 +00002617 vg_rwl = &rw_remap_new[i];
2618
sewardj2d8b3f02002-06-01 14:14:19 +00002619 /* Initialise the shadow, if required. */
sewardja1ac5cb2002-05-27 13:00:05 +00002620 if (orig->__rw_readers == 0) {
sewardja1ac5cb2002-05-27 13:00:05 +00002621 orig->__rw_readers = 1;
sewardj2d8b3f02002-06-01 14:14:19 +00002622 init_vg_rwlock(vg_rwl);
sewardja1ac5cb2002-05-27 13:00:05 +00002623 if (orig->__rw_kind == PTHREAD_RWLOCK_PREFER_READER_NP)
sewardj2d8b3f02002-06-01 14:14:19 +00002624 vg_rwl->prefer_w = 0;
sewardja1ac5cb2002-05-27 13:00:05 +00002625 }
2626
2627 return vg_rwl;
2628}
2629
2630
sewardja1ac5cb2002-05-27 13:00:05 +00002631int pthread_rwlock_init ( pthread_rwlock_t* orig,
2632 const pthread_rwlockattr_t* attr )
2633{
sewardja1ac5cb2002-05-27 13:00:05 +00002634 vg_rwlock_t* rwl;
2635 if (0) printf ("pthread_rwlock_init\n");
2636 /* Force the remapper to initialise the shadow. */
2637 orig->__rw_readers = 0;
2638 /* Install the lock preference; the remapper needs to know it. */
2639 orig->__rw_kind = PTHREAD_RWLOCK_DEFAULT_NP;
2640 if (attr)
2641 orig->__rw_kind = attr->__lockkind;
2642 rwl = rw_remap ( orig );
sewardj2d8b3f02002-06-01 14:14:19 +00002643 return 0;
sewardja1ac5cb2002-05-27 13:00:05 +00002644}
2645
sewardj2d8b3f02002-06-01 14:14:19 +00002646
2647static
2648void pthread_rwlock_rdlock_CANCEL_HDLR ( void* rwl_v )
sewardja1ac5cb2002-05-27 13:00:05 +00002649{
sewardj2d8b3f02002-06-01 14:14:19 +00002650 vg_rwlock_t* rwl = (vg_rwlock_t*)rwl_v;
2651 rwl->nwait_r--;
2652 pthread_mutex_unlock (&rwl->mx);
sewardja1ac5cb2002-05-27 13:00:05 +00002653}
2654
sewardj2d8b3f02002-06-01 14:14:19 +00002655
sewardja1ac5cb2002-05-27 13:00:05 +00002656int pthread_rwlock_rdlock ( pthread_rwlock_t* orig )
2657{
2658 int res;
2659 vg_rwlock_t* rwl;
2660 if (0) printf ("pthread_rwlock_rdlock\n");
2661 rwl = rw_remap ( orig );
sewardj2d8b3f02002-06-01 14:14:19 +00002662 res = __pthread_mutex_lock(&rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00002663 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002664 if (!rwl->initted) {
2665 res = __pthread_mutex_unlock(&rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00002666 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002667 return EINVAL;
2668 }
2669 if (rwl->status < 0) {
sewardj2d94c112002-06-03 01:25:54 +00002670 my_assert(rwl->status == -1);
sewardj2d8b3f02002-06-01 14:14:19 +00002671 rwl->nwait_r++;
2672 pthread_cleanup_push( pthread_rwlock_rdlock_CANCEL_HDLR, rwl );
2673 while (1) {
2674 if (rwl->status == 0) break;
2675 res = pthread_cond_wait(&rwl->cv_r, &rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00002676 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002677 }
2678 pthread_cleanup_pop(0);
2679 rwl->nwait_r--;
2680 }
sewardj2d94c112002-06-03 01:25:54 +00002681 my_assert(rwl->status >= 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002682 rwl->status++;
2683 res = __pthread_mutex_unlock(&rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00002684 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002685 return 0;
sewardja1ac5cb2002-05-27 13:00:05 +00002686}
2687
sewardj2d8b3f02002-06-01 14:14:19 +00002688
sewardja1ac5cb2002-05-27 13:00:05 +00002689int pthread_rwlock_tryrdlock ( pthread_rwlock_t* orig )
2690{
2691 int res;
2692 vg_rwlock_t* rwl;
2693 if (0) printf ("pthread_rwlock_tryrdlock\n");
2694 rwl = rw_remap ( orig );
sewardj2d8b3f02002-06-01 14:14:19 +00002695 res = __pthread_mutex_lock(&rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00002696 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002697 if (!rwl->initted) {
2698 res = __pthread_mutex_unlock(&rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00002699 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002700 return EINVAL;
2701 }
2702 if (rwl->status == -1) {
2703 /* Writer active; we have to give up. */
2704 res = __pthread_mutex_unlock(&rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00002705 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002706 return EBUSY;
2707 }
2708 /* Success */
sewardj2d94c112002-06-03 01:25:54 +00002709 my_assert(rwl->status >= 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002710 rwl->status++;
2711 res = __pthread_mutex_unlock(&rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00002712 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002713 return 0;
sewardja1ac5cb2002-05-27 13:00:05 +00002714}
2715
sewardj2d8b3f02002-06-01 14:14:19 +00002716
2717static
2718void pthread_rwlock_wrlock_CANCEL_HDLR ( void* rwl_v )
2719{
2720 vg_rwlock_t* rwl = (vg_rwlock_t*)rwl_v;
2721 rwl->nwait_w--;
2722 pthread_mutex_unlock (&rwl->mx);
2723}
2724
2725
sewardja1ac5cb2002-05-27 13:00:05 +00002726int pthread_rwlock_wrlock ( pthread_rwlock_t* orig )
2727{
2728 int res;
2729 vg_rwlock_t* rwl;
2730 if (0) printf ("pthread_rwlock_wrlock\n");
2731 rwl = rw_remap ( orig );
sewardj2d8b3f02002-06-01 14:14:19 +00002732 res = __pthread_mutex_lock(&rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00002733 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002734 if (!rwl->initted) {
2735 res = __pthread_mutex_unlock(&rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00002736 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002737 return EINVAL;
2738 }
2739 if (rwl->status != 0) {
2740 rwl->nwait_w++;
2741 pthread_cleanup_push( pthread_rwlock_wrlock_CANCEL_HDLR, rwl );
2742 while (1) {
2743 if (rwl->status == 0) break;
2744 res = pthread_cond_wait(&rwl->cv_w, &rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00002745 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002746 }
2747 pthread_cleanup_pop(0);
2748 rwl->nwait_w--;
2749 }
sewardj2d94c112002-06-03 01:25:54 +00002750 my_assert(rwl->status == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002751 rwl->status = -1;
2752 res = __pthread_mutex_unlock(&rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00002753 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002754 return 0;
sewardja1ac5cb2002-05-27 13:00:05 +00002755}
2756
sewardj2d8b3f02002-06-01 14:14:19 +00002757
sewardja1ac5cb2002-05-27 13:00:05 +00002758int pthread_rwlock_trywrlock ( pthread_rwlock_t* orig )
2759{
2760 int res;
2761 vg_rwlock_t* rwl;
sewardj2d8b3f02002-06-01 14:14:19 +00002762 if (0) printf ("pthread_wrlock_trywrlock\n");
sewardja1ac5cb2002-05-27 13:00:05 +00002763 rwl = rw_remap ( orig );
sewardj2d8b3f02002-06-01 14:14:19 +00002764 res = __pthread_mutex_lock(&rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00002765 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002766 if (!rwl->initted) {
2767 res = __pthread_mutex_unlock(&rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00002768 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002769 return EINVAL;
2770 }
2771 if (rwl->status != 0) {
2772 /* Reader(s) or a writer active; we have to give up. */
2773 res = __pthread_mutex_unlock(&rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00002774 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002775 return EBUSY;
2776 }
2777 /* Success */
sewardj2d94c112002-06-03 01:25:54 +00002778 my_assert(rwl->status == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002779 rwl->status = -1;
2780 res = __pthread_mutex_unlock(&rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00002781 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002782 return 0;
sewardja1ac5cb2002-05-27 13:00:05 +00002783}
2784
sewardj2d8b3f02002-06-01 14:14:19 +00002785
sewardja1ac5cb2002-05-27 13:00:05 +00002786int pthread_rwlock_unlock ( pthread_rwlock_t* orig )
2787{
2788 int res;
2789 vg_rwlock_t* rwl;
2790 if (0) printf ("pthread_rwlock_unlock\n");
2791 rwl = rw_remap ( orig );
sewardj2d8b3f02002-06-01 14:14:19 +00002792 rwl = rw_remap ( orig );
2793 res = __pthread_mutex_lock(&rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00002794 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002795 if (!rwl->initted) {
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 EINVAL;
2799 }
2800 if (rwl->status == 0) {
2801 res = __pthread_mutex_unlock(&rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00002802 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002803 return EPERM;
2804 }
sewardj2d94c112002-06-03 01:25:54 +00002805 my_assert(rwl->status != 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002806 if (rwl->status == -1) {
2807 rwl->status = 0;
2808 } else {
sewardj2d94c112002-06-03 01:25:54 +00002809 my_assert(rwl->status > 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002810 rwl->status--;
2811 }
2812
sewardj2d94c112002-06-03 01:25:54 +00002813 my_assert(rwl->status >= 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002814
2815 if (rwl->prefer_w) {
2816
2817 /* Favour waiting writers, if any. */
2818 if (rwl->nwait_w > 0) {
2819 /* Writer(s) are waiting. */
2820 if (rwl->status == 0) {
2821 /* We can let a writer in. */
2822 res = pthread_cond_signal(&rwl->cv_w);
sewardj2d94c112002-06-03 01:25:54 +00002823 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002824 } else {
2825 /* There are still readers active. Do nothing; eventually
2826 they will disappear, at which point a writer will be
2827 admitted. */
2828 }
2829 }
2830 else
2831 /* No waiting writers. */
2832 if (rwl->nwait_r > 0) {
2833 /* Let in a waiting reader. */
2834 res = pthread_cond_signal(&rwl->cv_r);
sewardj2d94c112002-06-03 01:25:54 +00002835 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002836 }
2837
2838 } else {
2839
2840 /* Favour waiting readers, if any. */
2841 if (rwl->nwait_r > 0) {
2842 /* Reader(s) are waiting; let one in. */
2843 res = pthread_cond_signal(&rwl->cv_r);
sewardj2d94c112002-06-03 01:25:54 +00002844 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002845 }
2846 else
2847 /* No waiting readers. */
2848 if (rwl->nwait_w > 0 && rwl->status == 0) {
2849 /* We have waiting writers and no active readers; let a
2850 writer in. */
2851 res = pthread_cond_signal(&rwl->cv_w);
sewardj2d94c112002-06-03 01:25:54 +00002852 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002853 }
2854 }
2855
2856 res = __pthread_mutex_unlock(&rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00002857 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002858 return 0;
2859}
2860
2861
2862int pthread_rwlock_destroy ( pthread_rwlock_t *orig )
2863{
2864 int res;
2865 vg_rwlock_t* rwl;
2866 if (0) printf ("pthread_rwlock_destroy\n");
2867 rwl = rw_remap ( orig );
2868 res = __pthread_mutex_lock(&rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00002869 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002870 if (!rwl->initted) {
2871 res = __pthread_mutex_unlock(&rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00002872 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002873 return EINVAL;
2874 }
2875 if (rwl->status != 0 || rwl->nwait_r > 0 || rwl->nwait_w > 0) {
2876 res = __pthread_mutex_unlock(&rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00002877 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002878 return EBUSY;
2879 }
2880 rwl->initted = 0;
2881 res = __pthread_mutex_unlock(&rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00002882 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002883 return 0;
sewardja1ac5cb2002-05-27 13:00:05 +00002884}
2885
2886
sewardj47e4e312002-06-18 09:24:34 +00002887/* Copied directly from LinuxThreads. */
2888int
2889pthread_rwlockattr_init (pthread_rwlockattr_t *attr)
2890{
2891 attr->__lockkind = 0;
2892 attr->__pshared = PTHREAD_PROCESS_PRIVATE;
2893
2894 return 0;
2895}
2896
sewardjfe18eb82002-07-13 12:58:44 +00002897/* Copied directly from LinuxThreads. */
2898int
sewardj5706bfa2002-12-08 23:42:17 +00002899pthread_rwlockattr_destroy (pthread_rwlockattr_t *attr)
2900{
2901 return 0;
2902}
2903
2904/* Copied directly from LinuxThreads. */
2905int
sewardjfe18eb82002-07-13 12:58:44 +00002906pthread_rwlockattr_setpshared (pthread_rwlockattr_t *attr, int pshared)
2907{
2908 if (pshared != PTHREAD_PROCESS_PRIVATE && pshared != PTHREAD_PROCESS_SHARED)
2909 return EINVAL;
2910
2911 /* For now it is not possible to shared a conditional variable. */
2912 if (pshared != PTHREAD_PROCESS_PRIVATE)
2913 return ENOSYS;
2914
2915 attr->__pshared = pshared;
2916
2917 return 0;
2918}
2919
sewardj47e4e312002-06-18 09:24:34 +00002920
sewardja1ac5cb2002-05-27 13:00:05 +00002921/* ---------------------------------------------------------------------
sewardj11f0bb42003-04-26 20:11:15 +00002922 Make SYSV IPC not block everything -- pass to vg_intercept.c.
sewardjd5bef572002-10-23 21:49:33 +00002923 ------------------------------------------------------------------ */
2924
sewardj11f0bb42003-04-26 20:11:15 +00002925WEAK
2926int msgsnd(int msgid, const void *msgp, size_t msgsz, int msgflg)
sewardjd5bef572002-10-23 21:49:33 +00002927{
sewardj11f0bb42003-04-26 20:11:15 +00002928 return VGR_(msgsnd)(msgid, msgp, msgsz, msgflg);
sewardjd5bef572002-10-23 21:49:33 +00002929}
2930
sewardj11f0bb42003-04-26 20:11:15 +00002931WEAK
2932int msgrcv(int msqid, void* msgp, size_t msgsz,
2933 long msgtyp, int msgflg )
sewardjd5bef572002-10-23 21:49:33 +00002934{
sewardj11f0bb42003-04-26 20:11:15 +00002935 return VGR_(msgrcv)(msqid, msgp, msgsz, msgtyp, msgflg );
sewardjd5bef572002-10-23 21:49:33 +00002936}
2937
sewardj262b5be2003-04-26 21:19:53 +00002938
2939/* ---------------------------------------------------------------------
2940 The glibc sources say that returning -1 in these 3 functions
2941 causes real time signals not to be used.
2942 ------------------------------------------------------------------ */
2943
2944int __libc_current_sigrtmin (void)
2945{
2946 static int moans = N_MOANS;
2947 if (moans-- > 0)
2948 kludged("__libc_current_sigrtmin");
2949 return -1;
2950}
2951
2952int __libc_current_sigrtmax (void)
2953{
2954 static int moans = N_MOANS;
2955 if (moans-- > 0)
2956 kludged("__libc_current_sigrtmax");
2957 return -1;
2958}
2959
2960int __libc_allocate_rtsig (int high)
2961{
2962 static int moans = N_MOANS;
2963 if (moans-- > 0)
2964 kludged("__libc_allocate_rtsig");
2965 return -1;
2966}
2967
2968
sewardjd5bef572002-10-23 21:49:33 +00002969/* ---------------------------------------------------------------------
sewardj3b13f0e2002-04-25 20:17:29 +00002970 B'stard.
2971 ------------------------------------------------------------------ */
2972
2973# define strong_alias(name, aliasname) \
2974 extern __typeof (name) aliasname __attribute__ ((alias (#name)));
2975
sewardj5905fae2002-04-26 13:25:00 +00002976# define weak_alias(name, aliasname) \
2977 extern __typeof (name) aliasname __attribute__ ((weak, alias (#name)));
sewardj3b13f0e2002-04-25 20:17:29 +00002978
sewardj5905fae2002-04-26 13:25:00 +00002979strong_alias(__pthread_mutex_lock, pthread_mutex_lock)
2980strong_alias(__pthread_mutex_trylock, pthread_mutex_trylock)
2981strong_alias(__pthread_mutex_unlock, pthread_mutex_unlock)
2982strong_alias(__pthread_mutexattr_init, pthread_mutexattr_init)
2983 weak_alias(__pthread_mutexattr_settype, pthread_mutexattr_settype)
2984strong_alias(__pthread_mutex_init, pthread_mutex_init)
2985strong_alias(__pthread_mutexattr_destroy, pthread_mutexattr_destroy)
2986strong_alias(__pthread_mutex_destroy, pthread_mutex_destroy)
2987strong_alias(__pthread_once, pthread_once)
2988strong_alias(__pthread_atfork, pthread_atfork)
2989strong_alias(__pthread_key_create, pthread_key_create)
2990strong_alias(__pthread_getspecific, pthread_getspecific)
2991strong_alias(__pthread_setspecific, pthread_setspecific)
2992
sewardjd529a442002-05-04 19:49:21 +00002993#ifndef GLIBC_2_1
sewardj3b13f0e2002-04-25 20:17:29 +00002994strong_alias(sigaction, __sigaction)
sewardjd529a442002-05-04 19:49:21 +00002995#endif
2996
sewardj5905fae2002-04-26 13:25:00 +00002997strong_alias(close, __close)
sewardj3b13f0e2002-04-25 20:17:29 +00002998strong_alias(fcntl, __fcntl)
sewardj5905fae2002-04-26 13:25:00 +00002999strong_alias(lseek, __lseek)
3000strong_alias(open, __open)
3001strong_alias(open64, __open64)
sewardj5905fae2002-04-26 13:25:00 +00003002strong_alias(read, __read)
3003strong_alias(wait, __wait)
3004strong_alias(write, __write)
sewardj3b13f0e2002-04-25 20:17:29 +00003005strong_alias(connect, __connect)
sewardj5905fae2002-04-26 13:25:00 +00003006strong_alias(send, __send)
3007
sewardj726c4122002-05-16 23:39:10 +00003008weak_alias (__pread64, pread64)
sewardja18e2102002-05-18 10:43:22 +00003009weak_alias (__pwrite64, pwrite64)
sewardj5905fae2002-04-26 13:25:00 +00003010weak_alias(__fork, fork)
njn25e49d8e72002-09-23 09:36:25 +00003011weak_alias(__vfork, vfork)
sewardj7f6456d2002-05-21 00:51:21 +00003012
sewardjf0b06452002-06-04 08:38:04 +00003013weak_alias (__pthread_kill_other_threads_np, pthread_kill_other_threads_np)
sewardj3b13f0e2002-04-25 20:17:29 +00003014
3015/*--------------------------------------------------*/
3016
sewardj5905fae2002-04-26 13:25:00 +00003017weak_alias(pthread_rwlock_rdlock, __pthread_rwlock_rdlock)
sewardj5905fae2002-04-26 13:25:00 +00003018weak_alias(pthread_rwlock_unlock, __pthread_rwlock_unlock)
sewardj262b0292002-05-01 00:03:16 +00003019weak_alias(pthread_rwlock_wrlock, __pthread_rwlock_wrlock)
sewardj060b04f2002-04-26 21:01:13 +00003020
sewardja1ac5cb2002-05-27 13:00:05 +00003021weak_alias(pthread_rwlock_destroy, __pthread_rwlock_destroy)
3022weak_alias(pthread_rwlock_init, __pthread_rwlock_init)
3023weak_alias(pthread_rwlock_tryrdlock, __pthread_rwlock_tryrdlock)
3024weak_alias(pthread_rwlock_trywrlock, __pthread_rwlock_trywrlock)
3025
sewardj060b04f2002-04-26 21:01:13 +00003026
sewardj3b13f0e2002-04-25 20:17:29 +00003027/* I've no idea what these are, but they get called quite a lot.
3028 Anybody know? */
3029
3030#undef _IO_flockfile
3031void _IO_flockfile ( _IO_FILE * file )
3032{
sewardj853f55d2002-04-26 00:27:53 +00003033 pthread_mutex_lock(file->_lock);
sewardj3b13f0e2002-04-25 20:17:29 +00003034}
sewardj5905fae2002-04-26 13:25:00 +00003035weak_alias(_IO_flockfile, flockfile);
3036
sewardj3b13f0e2002-04-25 20:17:29 +00003037
3038#undef _IO_funlockfile
3039void _IO_funlockfile ( _IO_FILE * file )
3040{
sewardj853f55d2002-04-26 00:27:53 +00003041 pthread_mutex_unlock(file->_lock);
sewardj3b13f0e2002-04-25 20:17:29 +00003042}
sewardj5905fae2002-04-26 13:25:00 +00003043weak_alias(_IO_funlockfile, funlockfile);
3044
sewardj3b13f0e2002-04-25 20:17:29 +00003045
sewardjd4f2c712002-04-30 10:20:10 +00003046/* This doesn't seem to be needed to simulate libpthread.so's external
3047 interface, but many people complain about its absence. */
3048
3049strong_alias(__pthread_mutexattr_settype, __pthread_mutexattr_setkind_np)
3050weak_alias(__pthread_mutexattr_setkind_np, pthread_mutexattr_setkind_np)
sewardj439d45e2002-05-03 20:43:10 +00003051
3052
3053/*--------------------------------------------------------------------*/
3054/*--- end vg_libpthread.c ---*/
3055/*--------------------------------------------------------------------*/