blob: b477077af28ebdce4e8fe277a2f337004442c9bf [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
sewardj9df78832003-05-04 12:35:54 +00001565#ifdef GLIBC_2_3
1566/* This seems to be a hook which appeared in glibc-2.3.2. */
1567int __register_atfork ( void (*prepare)(void),
1568 void (*parent)(void),
1569 void (*child)(void) )
1570{
1571 return __pthread_atfork(prepare,parent,child);
1572}
1573#endif
1574
sewardj11f0bb42003-04-26 20:11:15 +00001575WEAK
sewardjbb990782002-05-08 02:01:14 +00001576void __pthread_initialize ( void )
1577{
sewardjbea1caa2002-05-10 23:20:58 +00001578 ensure_valgrind("__pthread_initialize");
sewardjbb990782002-05-08 02:01:14 +00001579}
1580
1581
sewardj853f55d2002-04-26 00:27:53 +00001582/* ---------------------------------------------------
sewardj3b13f0e2002-04-25 20:17:29 +00001583 LIBRARY-PRIVATE THREAD SPECIFIC STATE
sewardjf8f819e2002-04-17 23:21:37 +00001584 ------------------------------------------------ */
1585
sewardj3b13f0e2002-04-25 20:17:29 +00001586#include <resolv.h>
1587static int thread_specific_errno[VG_N_THREADS];
1588static int thread_specific_h_errno[VG_N_THREADS];
1589static struct __res_state
1590 thread_specific_res_state[VG_N_THREADS];
sewardjf8f819e2002-04-17 23:21:37 +00001591
sewardj3b13f0e2002-04-25 20:17:29 +00001592int* __errno_location ( void )
sewardjf8f819e2002-04-17 23:21:37 +00001593{
1594 int tid;
sewardj3b13f0e2002-04-25 20:17:29 +00001595 /* ensure_valgrind("__errno_location"); */
1596 VALGRIND_MAGIC_SEQUENCE(tid, 1 /* default */,
sewardjf8f819e2002-04-17 23:21:37 +00001597 VG_USERREQ__PTHREAD_GET_THREADID,
1598 0, 0, 0, 0);
sewardj3b13f0e2002-04-25 20:17:29 +00001599 /* 'cos I'm paranoid ... */
sewardj439d45e2002-05-03 20:43:10 +00001600 if (tid < 1 || tid >= VG_N_THREADS)
sewardj3b13f0e2002-04-25 20:17:29 +00001601 barf("__errno_location: invalid ThreadId");
1602 return & thread_specific_errno[tid];
1603}
1604
1605int* __h_errno_location ( void )
1606{
1607 int tid;
1608 /* ensure_valgrind("__h_errno_location"); */
1609 VALGRIND_MAGIC_SEQUENCE(tid, 1 /* default */,
1610 VG_USERREQ__PTHREAD_GET_THREADID,
1611 0, 0, 0, 0);
1612 /* 'cos I'm paranoid ... */
sewardj439d45e2002-05-03 20:43:10 +00001613 if (tid < 1 || tid >= VG_N_THREADS)
sewardj3b13f0e2002-04-25 20:17:29 +00001614 barf("__h_errno_location: invalid ThreadId");
1615 return & thread_specific_h_errno[tid];
1616}
1617
sewardjb0ff1032002-08-06 09:02:53 +00001618
1619#undef _res
1620extern struct __res_state _res;
1621
sewardj3b13f0e2002-04-25 20:17:29 +00001622struct __res_state* __res_state ( void )
1623{
1624 int tid;
1625 /* ensure_valgrind("__res_state"); */
1626 VALGRIND_MAGIC_SEQUENCE(tid, 1 /* default */,
1627 VG_USERREQ__PTHREAD_GET_THREADID,
1628 0, 0, 0, 0);
1629 /* 'cos I'm paranoid ... */
sewardj439d45e2002-05-03 20:43:10 +00001630 if (tid < 1 || tid >= VG_N_THREADS)
sewardj3b13f0e2002-04-25 20:17:29 +00001631 barf("__res_state: invalid ThreadId");
sewardjb0ff1032002-08-06 09:02:53 +00001632 if (tid == 1)
1633 return & _res;
sewardj3b13f0e2002-04-25 20:17:29 +00001634 return & thread_specific_res_state[tid];
sewardjf8f819e2002-04-17 23:21:37 +00001635}
1636
1637
sewardj5716dbb2002-04-26 03:28:18 +00001638/* ---------------------------------------------------
1639 LIBC-PRIVATE SPECIFIC DATA
1640 ------------------------------------------------ */
1641
1642/* Relies on assumption that initial private data is NULL. This
1643 should be fixed somehow. */
1644
njn25e49d8e72002-09-23 09:36:25 +00001645/* The allowable keys (indices) (all 3 of them).
sewardj5716dbb2002-04-26 03:28:18 +00001646 From sysdeps/pthread/bits/libc-tsd.h
1647*/
sewardjcb7f08a2002-10-02 09:41:49 +00001648/* as per glibc anoncvs HEAD of 20021001. */
sewardj5716dbb2002-04-26 03:28:18 +00001649enum __libc_tsd_key_t { _LIBC_TSD_KEY_MALLOC = 0,
1650 _LIBC_TSD_KEY_DL_ERROR,
njn25e49d8e72002-09-23 09:36:25 +00001651 _LIBC_TSD_KEY_RPC_VARS,
sewardjcb7f08a2002-10-02 09:41:49 +00001652 _LIBC_TSD_KEY_LOCALE,
1653 _LIBC_TSD_KEY_CTYPE_B,
1654 _LIBC_TSD_KEY_CTYPE_TOLOWER,
1655 _LIBC_TSD_KEY_CTYPE_TOUPPER,
sewardj5716dbb2002-04-26 03:28:18 +00001656 _LIBC_TSD_KEY_N };
1657
1658/* Auto-initialising subsystem. libc_specifics_inited is set
1659 after initialisation. libc_specifics_inited_mx guards it. */
1660static int libc_specifics_inited = 0;
1661static pthread_mutex_t libc_specifics_inited_mx = PTHREAD_MUTEX_INITIALIZER;
1662
sewardj00a66b12002-10-12 16:42:35 +00001663
sewardj5716dbb2002-04-26 03:28:18 +00001664/* These are the keys we must initialise the first time. */
sewardjcb7f08a2002-10-02 09:41:49 +00001665static pthread_key_t libc_specifics_keys[_LIBC_TSD_KEY_N];
sewardj5716dbb2002-04-26 03:28:18 +00001666
sewardj00a66b12002-10-12 16:42:35 +00001667
sewardjcb7f08a2002-10-02 09:41:49 +00001668/* Initialise the keys, if they are not already initialised. */
sewardj5716dbb2002-04-26 03:28:18 +00001669static
1670void init_libc_tsd_keys ( void )
1671{
1672 int res, i;
1673 pthread_key_t k;
1674
sewardj08c7f012002-10-07 23:56:55 +00001675 /* Don't fall into deadlock if we get called again whilst we still
1676 hold the lock, via the __uselocale() call herein. */
1677 if (libc_specifics_inited != 0)
1678 return;
1679
1680 /* Take the lock. */
sewardj00a66b12002-10-12 16:42:35 +00001681 res = __pthread_mutex_lock(&libc_specifics_inited_mx);
sewardj5716dbb2002-04-26 03:28:18 +00001682 if (res != 0) barf("init_libc_tsd_keys: lock");
1683
sewardj08c7f012002-10-07 23:56:55 +00001684 /* Now test again, to be sure there is no mistake. */
1685 if (libc_specifics_inited != 0) {
sewardj00a66b12002-10-12 16:42:35 +00001686 res = __pthread_mutex_unlock(&libc_specifics_inited_mx);
sewardj08c7f012002-10-07 23:56:55 +00001687 if (res != 0) barf("init_libc_tsd_keys: unlock(1)");
1688 return;
sewardj5716dbb2002-04-26 03:28:18 +00001689 }
1690
sewardj08c7f012002-10-07 23:56:55 +00001691 /* Actually do the initialisation. */
1692 /* printf("INIT libc specifics\n"); */
1693 for (i = 0; i < _LIBC_TSD_KEY_N; i++) {
sewardj00a66b12002-10-12 16:42:35 +00001694 res = __pthread_key_create(&k, NULL);
sewardj08c7f012002-10-07 23:56:55 +00001695 if (res != 0) barf("init_libc_tsd_keys: create");
1696 libc_specifics_keys[i] = k;
1697 }
1698
1699 /* Signify init done. */
1700 libc_specifics_inited = 1;
1701
1702# ifdef GLIBC_2_3
1703 /* Set the initialising thread's locale to the global (default)
sewardj00a66b12002-10-12 16:42:35 +00001704 locale. A hack in support of glibc-2.3. This does the biz for
1705 the root thread. For all other threads we run this in
1706 thread_wrapper(), which does the real work of
1707 pthread_create(). */
1708 /* assert that we are the root thread. I don't know if this is
1709 really a valid assertion to make; if it breaks I'll reconsider
1710 it. */
1711 my_assert(pthread_self() == 1);
sewardj08c7f012002-10-07 23:56:55 +00001712 __uselocale(LC_GLOBAL_LOCALE);
1713# endif
1714
1715 /* Unlock and return. */
sewardj00a66b12002-10-12 16:42:35 +00001716 res = __pthread_mutex_unlock(&libc_specifics_inited_mx);
sewardj5716dbb2002-04-26 03:28:18 +00001717 if (res != 0) barf("init_libc_tsd_keys: unlock");
1718}
1719
1720
1721static int
1722libc_internal_tsd_set ( enum __libc_tsd_key_t key,
1723 const void * pointer )
1724{
sewardjcb7f08a2002-10-02 09:41:49 +00001725 int res;
sewardj5716dbb2002-04-26 03:28:18 +00001726 /* printf("SET SET SET key %d ptr %p\n", key, pointer); */
sewardjcb7f08a2002-10-02 09:41:49 +00001727 if (key < _LIBC_TSD_KEY_MALLOC || key >= _LIBC_TSD_KEY_N)
sewardj5716dbb2002-04-26 03:28:18 +00001728 barf("libc_internal_tsd_set: invalid key");
1729 init_libc_tsd_keys();
sewardj00a66b12002-10-12 16:42:35 +00001730 res = __pthread_setspecific(libc_specifics_keys[key], pointer);
sewardj5716dbb2002-04-26 03:28:18 +00001731 if (res != 0) barf("libc_internal_tsd_set: setspecific failed");
1732 return 0;
1733}
1734
1735static void *
1736libc_internal_tsd_get ( enum __libc_tsd_key_t key )
1737{
sewardjcb7f08a2002-10-02 09:41:49 +00001738 void* v;
sewardj5716dbb2002-04-26 03:28:18 +00001739 /* printf("GET GET GET key %d\n", key); */
sewardjcb7f08a2002-10-02 09:41:49 +00001740 if (key < _LIBC_TSD_KEY_MALLOC || key >= _LIBC_TSD_KEY_N)
sewardj5716dbb2002-04-26 03:28:18 +00001741 barf("libc_internal_tsd_get: invalid key");
1742 init_libc_tsd_keys();
sewardj00a66b12002-10-12 16:42:35 +00001743 v = __pthread_getspecific(libc_specifics_keys[key]);
sewardj5716dbb2002-04-26 03:28:18 +00001744 /* if (v == NULL) barf("libc_internal_tsd_set: getspecific failed"); */
1745 return v;
1746}
1747
1748
sewardj70adeb22002-04-27 01:35:38 +00001749int (*__libc_internal_tsd_set)
1750 (enum __libc_tsd_key_t key, const void * pointer)
1751 = libc_internal_tsd_set;
sewardj5716dbb2002-04-26 03:28:18 +00001752
sewardj70adeb22002-04-27 01:35:38 +00001753void* (*__libc_internal_tsd_get)
1754 (enum __libc_tsd_key_t key)
1755 = libc_internal_tsd_get;
sewardj5716dbb2002-04-26 03:28:18 +00001756
1757
sewardj00a66b12002-10-12 16:42:35 +00001758#ifdef GLIBC_2_3
1759/* This one was first spotted be me in the glibc-2.2.93 sources. */
1760static void**
1761libc_internal_tsd_address ( enum __libc_tsd_key_t key )
1762{
1763 void** v;
1764 /* printf("ADDR ADDR ADDR key %d\n", key); */
1765 if (key < _LIBC_TSD_KEY_MALLOC || key >= _LIBC_TSD_KEY_N)
1766 barf("libc_internal_tsd_address: invalid key");
1767 init_libc_tsd_keys();
1768 v = __pthread_getspecific_addr(libc_specifics_keys[key]);
1769 return v;
1770}
1771
1772void ** (*__libc_internal_tsd_address)
1773 (enum __libc_tsd_key_t key)
1774 = libc_internal_tsd_address;
1775#endif
1776
1777
sewardje663cb92002-04-12 10:26:32 +00001778/* ---------------------------------------------------------------------
1779 These are here (I think) because they are deemed cancellation
1780 points by POSIX. For the moment we'll simply pass the call along
1781 to the corresponding thread-unaware (?) libc routine.
1782 ------------------------------------------------------------------ */
1783
sewardjd529a442002-05-04 19:49:21 +00001784#ifdef GLIBC_2_1
1785extern
1786int __sigaction
1787 (int signum,
1788 const struct sigaction *act,
1789 struct sigaction *oldact);
1790#else
sewardje663cb92002-04-12 10:26:32 +00001791extern
1792int __libc_sigaction
1793 (int signum,
1794 const struct sigaction *act,
1795 struct sigaction *oldact);
sewardjd529a442002-05-04 19:49:21 +00001796#endif
sewardje663cb92002-04-12 10:26:32 +00001797int sigaction(int signum,
1798 const struct sigaction *act,
1799 struct sigaction *oldact)
1800{
sewardjd140e442002-05-29 01:21:19 +00001801 __my_pthread_testcancel();
sewardj2a1dcce2002-04-22 12:45:25 +00001802# ifdef GLIBC_2_1
1803 return __sigaction(signum, act, oldact);
1804# else
sewardj45b4b372002-04-16 22:50:32 +00001805 return __libc_sigaction(signum, act, oldact);
sewardj2a1dcce2002-04-22 12:45:25 +00001806# endif
sewardje663cb92002-04-12 10:26:32 +00001807}
1808
1809
1810extern
1811int __libc_connect(int sockfd,
1812 const struct sockaddr *serv_addr,
1813 socklen_t addrlen);
sewardj11f0bb42003-04-26 20:11:15 +00001814WEAK
sewardje663cb92002-04-12 10:26:32 +00001815int connect(int sockfd,
1816 const struct sockaddr *serv_addr,
1817 socklen_t addrlen)
1818{
sewardjd140e442002-05-29 01:21:19 +00001819 __my_pthread_testcancel();
sewardj45b4b372002-04-16 22:50:32 +00001820 return __libc_connect(sockfd, serv_addr, addrlen);
sewardje663cb92002-04-12 10:26:32 +00001821}
1822
1823
1824extern
1825int __libc_fcntl(int fd, int cmd, long arg);
sewardj11f0bb42003-04-26 20:11:15 +00001826WEAK
sewardje663cb92002-04-12 10:26:32 +00001827int fcntl(int fd, int cmd, long arg)
1828{
sewardjd140e442002-05-29 01:21:19 +00001829 __my_pthread_testcancel();
sewardj45b4b372002-04-16 22:50:32 +00001830 return __libc_fcntl(fd, cmd, arg);
sewardje663cb92002-04-12 10:26:32 +00001831}
1832
1833
1834extern
1835ssize_t __libc_write(int fd, const void *buf, size_t count);
sewardj11f0bb42003-04-26 20:11:15 +00001836WEAK
sewardje663cb92002-04-12 10:26:32 +00001837ssize_t write(int fd, const 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_write(fd, buf, count);
sewardje663cb92002-04-12 10:26:32 +00001841}
1842
1843
1844extern
1845ssize_t __libc_read(int fd, void *buf, size_t count);
sewardj11f0bb42003-04-26 20:11:15 +00001846WEAK
sewardje663cb92002-04-12 10:26:32 +00001847ssize_t read(int fd, void *buf, size_t count)
1848{
sewardjd140e442002-05-29 01:21:19 +00001849 __my_pthread_testcancel();
sewardj45b4b372002-04-16 22:50:32 +00001850 return __libc_read(fd, buf, count);
sewardje663cb92002-04-12 10:26:32 +00001851}
1852
sewardjf912dfc2002-11-13 21:51:10 +00001853/*
1854 * Ugh, this is horrible but here goes:
1855 *
1856 * Open of a named pipe (fifo file) can block. In a threaded program,
1857 * this means that the whole thing can block. We therefore need to
1858 * make the open appear to block to the caller, but still keep polling
1859 * for everyone else.
1860 *
1861 * There are four cases:
1862 *
1863 * - the caller asked for O_NONBLOCK. The easy one: we just do it.
1864 *
1865 * - the caller asked for a blocking O_RDONLY open. We open it with
1866 * O_NONBLOCK and then use poll to wait for it to become ready.
1867 *
1868 * - the caller asked for a blocking O_WRONLY open. Unfortunately, this
1869 * will fail with ENXIO when we make it non-blocking. Doubly
1870 * unfortunate is that we can only rely on these semantics if it is
1871 * actually a fifo file; the hack is that if we see that it is a
1872 * O_WRONLY open and we get ENXIO, then stat the path and see if it
1873 * actually is a fifo. This is racy, but it is the best we can do.
1874 * If it is a fifo, then keep trying the open until it works; if not
1875 * just return the error.
1876 *
1877 * - the caller asked for a blocking O_RDWR open. Well, under Linux,
1878 * this never blocks, so we just clear the non-blocking flag and
1879 * return.
1880 *
1881 * This code assumes that for whatever we open, O_NONBLOCK followed by
1882 * a fcntl clearing O_NONBLOCK is the same as opening without
1883 * O_NONBLOCK. Also assumes that stat and fstat have no side-effects.
1884 *
1885 * XXX Should probably put in special cases for some devices as well,
1886 * like serial ports. Unfortunately they don't work like fifos, so
1887 * this logic will become even more tortured. Wait until we really
1888 * need it.
1889 */
1890static inline int _open(const char *pathname, int flags, mode_t mode,
1891 int (*openp)(const char *, int, mode_t))
sewardjbe32e452002-04-24 20:29:58 +00001892{
sewardjf912dfc2002-11-13 21:51:10 +00001893 int fd;
1894 struct stat st;
1895 struct vki_timespec nanosleep_interval;
1896 int saved_errno;
1897
sewardjd140e442002-05-29 01:21:19 +00001898 __my_pthread_testcancel();
sewardjf912dfc2002-11-13 21:51:10 +00001899
1900 /* Assume we can only get O_RDONLY, O_WRONLY or O_RDWR */
1901 my_assert((flags & VKI_O_ACCMODE) != VKI_O_ACCMODE);
1902
1903 for(;;) {
1904 fd = (*openp)(pathname, flags | VKI_O_NONBLOCK, mode);
1905
1906 /* return immediately if caller wanted nonblocking anyway */
1907 if (flags & VKI_O_NONBLOCK)
1908 return fd;
1909
1910 saved_errno = errno;
1911
1912 if (fd != -1)
1913 break; /* open worked */
1914
1915 /* If we got ENXIO and we're opening WRONLY, and it turns out
1916 to really be a FIFO, then poll waiting for open to succeed */
1917 if (errno == ENXIO &&
1918 (flags & VKI_O_ACCMODE) == VKI_O_WRONLY &&
1919 (stat(pathname, &st) == 0 && S_ISFIFO(st.st_mode))) {
1920
1921 /* OK, we're opening a FIFO for writing; sleep and spin */
1922 nanosleep_interval.tv_sec = 0;
1923 nanosleep_interval.tv_nsec = 13 * 1000 * 1000; /* 13 milliseconds */
1924 /* It's critical here that valgrind's nanosleep implementation
1925 is nonblocking. */
1926 (void)my_do_syscall2(__NR_nanosleep,
1927 (int)(&nanosleep_interval), (int)NULL);
1928 } else {
1929 /* it was just an error */
1930 errno = saved_errno;
1931 return -1;
1932 }
1933 }
1934
1935 /* OK, we've got a nonblocking FD for a caller who wants blocking;
1936 reset the flags to what they asked for */
1937 fcntl(fd, VKI_F_SETFL, flags);
1938
1939 /* Return now if one of:
1940 - we were opening O_RDWR (never blocks)
1941 - we opened with O_WRONLY (polling already done)
1942 - the thing we opened wasn't a FIFO after all (or fstat failed)
1943 */
1944 if ((flags & VKI_O_ACCMODE) != VKI_O_RDONLY ||
1945 (fstat(fd, &st) == -1 || !S_ISFIFO(st.st_mode))) {
1946 errno = saved_errno;
1947 return fd;
1948 }
1949
1950 /* OK, drop into the poll loop looking for something to read on the fd */
1951 my_assert((flags & VKI_O_ACCMODE) == VKI_O_RDONLY);
1952 for(;;) {
1953 struct pollfd pollfd;
1954 int res;
1955
1956 pollfd.fd = fd;
1957 pollfd.events = POLLIN;
1958 pollfd.revents = 0;
1959
1960 res = my_do_syscall3(__NR_poll, (int)&pollfd, 1, 0);
1961
1962 my_assert(res == 0 || res == 1);
1963
1964 if (res == 1) {
1965 /* OK, got it.
1966
1967 XXX This is wrong: we're waiting for either something to
1968 read or a HUP on the file descriptor, but the semantics of
1969 fifo open are that we should unblock as soon as someone
1970 simply opens the other end, not that they write something.
1971 With luck this won't matter in practice.
1972 */
1973 my_assert(pollfd.revents & (POLLIN|POLLHUP));
1974 break;
1975 }
1976
1977 /* Still nobody home; sleep and spin */
1978 nanosleep_interval.tv_sec = 0;
1979 nanosleep_interval.tv_nsec = 13 * 1000 * 1000; /* 13 milliseconds */
1980 /* It's critical here that valgrind's nanosleep implementation
1981 is nonblocking. */
1982 (void)my_do_syscall2(__NR_nanosleep,
1983 (int)(&nanosleep_interval), (int)NULL);
1984 }
1985
1986 errno = saved_errno;
1987 return fd;
sewardjbe32e452002-04-24 20:29:58 +00001988}
1989
sewardjf912dfc2002-11-13 21:51:10 +00001990extern
1991int __libc_open64(const char *pathname, int flags, mode_t mode);
sewardj11f0bb42003-04-26 20:11:15 +00001992/* WEAK */
sewardjf912dfc2002-11-13 21:51:10 +00001993int open64(const char *pathname, int flags, mode_t mode)
1994{
1995 return _open(pathname, flags, mode, __libc_open64);
1996}
sewardje663cb92002-04-12 10:26:32 +00001997
1998extern
sewardj853f55d2002-04-26 00:27:53 +00001999int __libc_open(const char *pathname, int flags, mode_t mode);
sewardj11f0bb42003-04-26 20:11:15 +00002000/* WEAK */
sewardj853f55d2002-04-26 00:27:53 +00002001int open(const char *pathname, int flags, mode_t mode)
sewardje663cb92002-04-12 10:26:32 +00002002{
sewardjf912dfc2002-11-13 21:51:10 +00002003 return _open(pathname, flags, mode, __libc_open);
sewardje663cb92002-04-12 10:26:32 +00002004}
2005
sewardje663cb92002-04-12 10:26:32 +00002006extern
2007int __libc_close(int fd);
sewardj11f0bb42003-04-26 20:11:15 +00002008WEAK
sewardje663cb92002-04-12 10:26:32 +00002009int close(int fd)
2010{
sewardjd140e442002-05-29 01:21:19 +00002011 __my_pthread_testcancel();
sewardj45b4b372002-04-16 22:50:32 +00002012 return __libc_close(fd);
sewardje663cb92002-04-12 10:26:32 +00002013}
2014
2015
sewardj11f0bb42003-04-26 20:11:15 +00002016WEAK
2017int accept(int s, struct sockaddr *addr, socklen_t *addrlen)
sewardje663cb92002-04-12 10:26:32 +00002018{
sewardj11f0bb42003-04-26 20:11:15 +00002019 return VGR_(accept)(s, addr, addrlen);
sewardje663cb92002-04-12 10:26:32 +00002020}
2021
sewardj11f0bb42003-04-26 20:11:15 +00002022WEAK
2023int recv(int s, void *buf, size_t len, int flags)
sewardj0c573af92002-10-23 21:55:01 +00002024{
sewardj11f0bb42003-04-26 20:11:15 +00002025 return VGR_(recv)(s, buf, len, flags);
sewardj0c573af92002-10-23 21:55:01 +00002026}
2027
sewardj11f0bb42003-04-26 20:11:15 +00002028WEAK
2029int readv(int fd, const struct iovec *iov, int count)
sewardj2a68e7e2002-11-16 11:04:18 +00002030{
sewardj11f0bb42003-04-26 20:11:15 +00002031 return VGR_(readv)(fd, iov, count);
sewardj2a68e7e2002-11-16 11:04:18 +00002032}
2033
sewardj11f0bb42003-04-26 20:11:15 +00002034WEAK
2035int writev(int fd, const struct iovec *iov, int count)
sewardj2a68e7e2002-11-16 11:04:18 +00002036{
sewardj11f0bb42003-04-26 20:11:15 +00002037 return VGR_(writev)(fd, iov, count);
sewardj2a68e7e2002-11-16 11:04:18 +00002038}
sewardje663cb92002-04-12 10:26:32 +00002039
2040extern
sewardje663cb92002-04-12 10:26:32 +00002041pid_t __libc_waitpid(pid_t pid, int *status, int options);
sewardj11f0bb42003-04-26 20:11:15 +00002042WEAK
sewardje663cb92002-04-12 10:26:32 +00002043pid_t waitpid(pid_t pid, int *status, int options)
2044{
sewardjd140e442002-05-29 01:21:19 +00002045 __my_pthread_testcancel();
sewardj45b4b372002-04-16 22:50:32 +00002046 return __libc_waitpid(pid, status, options);
sewardje663cb92002-04-12 10:26:32 +00002047}
2048
2049
2050extern
2051int __libc_nanosleep(const struct timespec *req, struct timespec *rem);
sewardj11f0bb42003-04-26 20:11:15 +00002052WEAK
sewardje663cb92002-04-12 10:26:32 +00002053int nanosleep(const struct timespec *req, struct timespec *rem)
2054{
sewardjd140e442002-05-29 01:21:19 +00002055 __my_pthread_testcancel();
sewardje663cb92002-04-12 10:26:32 +00002056 return __libc_nanosleep(req, rem);
2057}
2058
sewardjbe32e452002-04-24 20:29:58 +00002059
sewardje663cb92002-04-12 10:26:32 +00002060extern
2061int __libc_fsync(int fd);
sewardj11f0bb42003-04-26 20:11:15 +00002062WEAK
sewardje663cb92002-04-12 10:26:32 +00002063int fsync(int fd)
2064{
sewardjd140e442002-05-29 01:21:19 +00002065 __my_pthread_testcancel();
sewardj45b4b372002-04-16 22:50:32 +00002066 return __libc_fsync(fd);
sewardje663cb92002-04-12 10:26:32 +00002067}
2068
sewardjbe32e452002-04-24 20:29:58 +00002069
sewardj70c75362002-04-13 04:18:32 +00002070extern
2071off_t __libc_lseek(int fildes, off_t offset, int whence);
sewardj11f0bb42003-04-26 20:11:15 +00002072WEAK
sewardj70c75362002-04-13 04:18:32 +00002073off_t lseek(int fildes, off_t offset, int whence)
2074{
sewardjd140e442002-05-29 01:21:19 +00002075 __my_pthread_testcancel();
sewardj45b4b372002-04-16 22:50:32 +00002076 return __libc_lseek(fildes, offset, whence);
sewardj70c75362002-04-13 04:18:32 +00002077}
2078
sewardjbe32e452002-04-24 20:29:58 +00002079
2080extern
2081__off64_t __libc_lseek64(int fildes, __off64_t offset, int whence);
sewardj11f0bb42003-04-26 20:11:15 +00002082WEAK
sewardjbe32e452002-04-24 20:29:58 +00002083__off64_t lseek64(int fildes, __off64_t offset, int whence)
2084{
sewardjd140e442002-05-29 01:21:19 +00002085 __my_pthread_testcancel();
sewardjbe32e452002-04-24 20:29:58 +00002086 return __libc_lseek64(fildes, offset, whence);
2087}
2088
2089
sewardj726c4122002-05-16 23:39:10 +00002090extern
2091ssize_t __libc_pread64 (int __fd, void *__buf, size_t __nbytes,
2092 __off64_t __offset);
2093ssize_t __pread64 (int __fd, void *__buf, size_t __nbytes,
2094 __off64_t __offset)
2095{
sewardjd140e442002-05-29 01:21:19 +00002096 __my_pthread_testcancel();
sewardj726c4122002-05-16 23:39:10 +00002097 return __libc_pread64(__fd, __buf, __nbytes, __offset);
2098}
2099
2100
sewardja18e2102002-05-18 10:43:22 +00002101extern
2102ssize_t __libc_pwrite64 (int __fd, const void *__buf, size_t __nbytes,
2103 __off64_t __offset);
2104ssize_t __pwrite64 (int __fd, const void *__buf, size_t __nbytes,
2105 __off64_t __offset)
2106{
sewardjd140e442002-05-29 01:21:19 +00002107 __my_pthread_testcancel();
sewardja18e2102002-05-18 10:43:22 +00002108 return __libc_pwrite64(__fd, __buf, __nbytes, __offset);
2109}
2110
sewardj726c4122002-05-16 23:39:10 +00002111
sewardj39b93b12002-05-18 10:56:27 +00002112extern
2113ssize_t __libc_pwrite(int fd, const void *buf, size_t count, off_t offset);
sewardj11f0bb42003-04-26 20:11:15 +00002114WEAK
sewardj39b93b12002-05-18 10:56:27 +00002115ssize_t pwrite(int fd, const 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_pwrite(fd, buf, count, offset);
2119}
2120
2121
2122extern
2123ssize_t __libc_pread(int fd, void *buf, size_t count, off_t offset);
sewardj11f0bb42003-04-26 20:11:15 +00002124WEAK
sewardj39b93b12002-05-18 10:56:27 +00002125ssize_t pread(int fd, void *buf, size_t count, off_t offset)
2126{
sewardjd140e442002-05-29 01:21:19 +00002127 __my_pthread_testcancel();
sewardj39b93b12002-05-18 10:56:27 +00002128 return __libc_pread(fd, buf, count, offset);
2129}
2130
2131
sewardj6af4b5d2002-04-16 04:40:49 +00002132extern
2133void __libc_longjmp(jmp_buf env, int val) __attribute((noreturn));
sewardj11f0bb42003-04-26 20:11:15 +00002134/* not weak: WEAK */
sewardj6af4b5d2002-04-16 04:40:49 +00002135void longjmp(jmp_buf env, int val)
2136{
2137 __libc_longjmp(env, val);
2138}
2139
sewardjbe32e452002-04-24 20:29:58 +00002140
sewardj436c2db2002-06-18 09:07:54 +00002141extern void __libc_siglongjmp (sigjmp_buf env, int val)
2142 __attribute__ ((noreturn));
2143void siglongjmp(sigjmp_buf env, int val)
2144{
2145 kludged("siglongjmp (cleanup handlers are ignored)");
2146 __libc_siglongjmp(env, val);
2147}
2148
2149
sewardj6af4b5d2002-04-16 04:40:49 +00002150extern
2151int __libc_send(int s, const void *msg, size_t len, int flags);
sewardj11f0bb42003-04-26 20:11:15 +00002152WEAK
sewardj6af4b5d2002-04-16 04:40:49 +00002153int send(int s, const void *msg, size_t len, int flags)
2154{
sewardjd140e442002-05-29 01:21:19 +00002155 __my_pthread_testcancel();
sewardj6af4b5d2002-04-16 04:40:49 +00002156 return __libc_send(s, msg, len, flags);
2157}
2158
sewardjbe32e452002-04-24 20:29:58 +00002159
sewardj3665ded2002-05-16 16:57:25 +00002160extern
2161int __libc_sendmsg(int s, const struct msghdr *msg, int flags);
sewardj11f0bb42003-04-26 20:11:15 +00002162WEAK
sewardj3665ded2002-05-16 16:57:25 +00002163int sendmsg(int s, const struct msghdr *msg, int flags)
2164{
sewardjd140e442002-05-29 01:21:19 +00002165 __my_pthread_testcancel();
sewardj3665ded2002-05-16 16:57:25 +00002166 return __libc_sendmsg(s, msg, flags);
2167}
2168
2169
sewardj796d6a22002-04-24 02:28:34 +00002170extern
sewardj59da27a2002-06-06 08:33:54 +00002171int __libc_recvmsg(int s, struct msghdr *msg, int flags);
sewardj11f0bb42003-04-26 20:11:15 +00002172WEAK
sewardj59da27a2002-06-06 08:33:54 +00002173int recvmsg(int s, struct msghdr *msg, int flags)
2174{
2175 __my_pthread_testcancel();
2176 return __libc_recvmsg(s, msg, flags);
2177}
2178
2179
2180extern
sewardj436e0582002-04-26 14:31:40 +00002181int __libc_recvfrom(int s, void *buf, size_t len, int flags,
2182 struct sockaddr *from, socklen_t *fromlen);
sewardj11f0bb42003-04-26 20:11:15 +00002183WEAK
sewardj436e0582002-04-26 14:31:40 +00002184int recvfrom(int s, void *buf, size_t len, int flags,
2185 struct sockaddr *from, socklen_t *fromlen)
2186{
sewardjd140e442002-05-29 01:21:19 +00002187 __my_pthread_testcancel();
sewardj11f0bb42003-04-26 20:11:15 +00002188 VGR_(wait_for_fd_to_be_readable_or_erring)(s);
sewardj2e207632002-06-13 17:29:53 +00002189 __my_pthread_testcancel();
sewardj436e0582002-04-26 14:31:40 +00002190 return __libc_recvfrom(s, buf, len, flags, from, fromlen);
2191}
2192
2193
2194extern
sewardj796d6a22002-04-24 02:28:34 +00002195int __libc_sendto(int s, const void *msg, size_t len, int flags,
2196 const struct sockaddr *to, socklen_t tolen);
sewardj11f0bb42003-04-26 20:11:15 +00002197WEAK
sewardj796d6a22002-04-24 02:28:34 +00002198int sendto(int s, const void *msg, size_t len, int flags,
2199 const struct sockaddr *to, socklen_t tolen)
2200{
sewardjd140e442002-05-29 01:21:19 +00002201 __my_pthread_testcancel();
sewardj796d6a22002-04-24 02:28:34 +00002202 return __libc_sendto(s, msg, len, flags, to, tolen);
2203}
2204
sewardjbe32e452002-04-24 20:29:58 +00002205
sewardj369b1702002-04-24 13:28:15 +00002206extern
2207int __libc_system(const char* str);
sewardj11f0bb42003-04-26 20:11:15 +00002208WEAK
sewardj369b1702002-04-24 13:28:15 +00002209int system(const char* str)
2210{
sewardjd140e442002-05-29 01:21:19 +00002211 __my_pthread_testcancel();
sewardj369b1702002-04-24 13:28:15 +00002212 return __libc_system(str);
2213}
2214
sewardjbe32e452002-04-24 20:29:58 +00002215
sewardjab0b1c32002-04-24 19:26:47 +00002216extern
2217pid_t __libc_wait(int *status);
sewardj11f0bb42003-04-26 20:11:15 +00002218WEAK
sewardjab0b1c32002-04-24 19:26:47 +00002219pid_t wait(int *status)
2220{
sewardjd140e442002-05-29 01:21:19 +00002221 __my_pthread_testcancel();
sewardjab0b1c32002-04-24 19:26:47 +00002222 return __libc_wait(status);
2223}
2224
sewardj45b4b372002-04-16 22:50:32 +00002225
sewardj67f1d582002-05-24 02:11:32 +00002226extern
2227int __libc_msync(const void *start, size_t length, int flags);
sewardj11f0bb42003-04-26 20:11:15 +00002228WEAK
sewardj67f1d582002-05-24 02:11:32 +00002229int msync(const void *start, size_t length, int flags)
2230{
sewardjd140e442002-05-29 01:21:19 +00002231 __my_pthread_testcancel();
sewardj67f1d582002-05-24 02:11:32 +00002232 return __libc_msync(start, length, flags);
2233}
2234
sewardj5905fae2002-04-26 13:25:00 +00002235
sewardj2cb00342002-06-28 01:46:26 +00002236/*--- fork and its helper ---*/
2237
2238static
2239void run_fork_handlers ( int what )
2240{
2241 ForkHandlerEntry entry;
2242 int n_h, n_handlers, i, res;
2243
2244 my_assert(what == 0 || what == 1 || what == 2);
2245
2246 /* Fetch old counter */
2247 VALGRIND_MAGIC_SEQUENCE(n_handlers, -2 /* default */,
2248 VG_USERREQ__GET_FHSTACK_USED,
2249 0, 0, 0, 0);
2250 my_assert(n_handlers >= 0 && n_handlers < VG_N_FORKHANDLERSTACK);
2251
2252 /* Prepare handlers (what == 0) are called in opposite order of
2253 calls to pthread_atfork. Parent and child handlers are called
2254 in the same order as calls to pthread_atfork. */
2255 if (what == 0)
2256 n_h = n_handlers - 1;
2257 else
2258 n_h = 0;
2259
2260 for (i = 0; i < n_handlers; i++) {
2261 VALGRIND_MAGIC_SEQUENCE(res, -2 /* default */,
2262 VG_USERREQ__GET_FHSTACK_ENTRY,
2263 n_h, &entry, 0, 0);
2264 my_assert(res == 0);
2265 switch (what) {
2266 case 0: if (entry.prepare) entry.prepare();
2267 n_h--; break;
2268 case 1: if (entry.parent) entry.parent();
2269 n_h++; break;
2270 case 2: if (entry.child) entry.child();
2271 n_h++; break;
2272 default: barf("run_fork_handlers: invalid what");
2273 }
2274 }
2275
2276 if (what != 0 /* prepare */) {
2277 /* Empty out the stack. */
2278 VALGRIND_MAGIC_SEQUENCE(res, -2 /* default */,
2279 VG_USERREQ__SET_FHSTACK_USED,
2280 0, 0, 0, 0);
2281 my_assert(res == 0);
2282 }
2283}
2284
2285extern
2286pid_t __libc_fork(void);
2287pid_t __fork(void)
2288{
2289 pid_t pid;
2290 __my_pthread_testcancel();
2291 __pthread_mutex_lock(&pthread_atfork_lock);
2292
2293 run_fork_handlers(0 /* prepare */);
2294 pid = __libc_fork();
2295 if (pid == 0) {
2296 /* I am the child */
2297 run_fork_handlers(2 /* child */);
sewardjd8acdf22002-11-13 21:57:52 +00002298 __pthread_mutex_unlock(&pthread_atfork_lock);
sewardj2cb00342002-06-28 01:46:26 +00002299 __pthread_mutex_init(&pthread_atfork_lock, NULL);
2300 } else {
2301 /* I am the parent */
2302 run_fork_handlers(1 /* parent */);
2303 __pthread_mutex_unlock(&pthread_atfork_lock);
2304 }
2305 return pid;
2306}
2307
2308
njn25e49d8e72002-09-23 09:36:25 +00002309pid_t __vfork(void)
2310{
2311 return __fork();
2312}
sewardj2cb00342002-06-28 01:46:26 +00002313
2314
sewardj08a4c3f2002-04-13 03:45:44 +00002315static
sewardj08a4c3f2002-04-13 03:45:44 +00002316int my_do_syscall1 ( int syscallno, int arg1 )
2317{
2318 int __res;
2319 __asm__ volatile ("pushl %%ebx; movl %%edx,%%ebx ; int $0x80 ; popl %%ebx"
2320 : "=a" (__res)
2321 : "0" (syscallno),
2322 "d" (arg1) );
2323 return __res;
2324}
2325
2326static
2327int my_do_syscall2 ( int syscallno,
sewardjf854f472002-04-21 12:19:41 +00002328 int arg1, int arg2 )
sewardj08a4c3f2002-04-13 03:45:44 +00002329{
2330 int __res;
2331 __asm__ volatile ("pushl %%ebx; movl %%edx,%%ebx ; int $0x80 ; popl %%ebx"
2332 : "=a" (__res)
2333 : "0" (syscallno),
2334 "d" (arg1),
2335 "c" (arg2) );
2336 return __res;
2337}
2338
2339static
sewardjf854f472002-04-21 12:19:41 +00002340int my_do_syscall3 ( int syscallno,
2341 int arg1, int arg2, int arg3 )
2342{
2343 int __res;
2344 __asm__ volatile ("pushl %%ebx; movl %%esi,%%ebx ; int $0x80 ; popl %%ebx"
2345 : "=a" (__res)
2346 : "0" (syscallno),
2347 "S" (arg1),
2348 "c" (arg2),
2349 "d" (arg3) );
2350 return __res;
2351}
2352
sewardjd5bef572002-10-23 21:49:33 +00002353static inline
2354int my_do_syscall5 ( int syscallno,
2355 int arg1, int arg2, int arg3, int arg4, int arg5 )
2356{
2357 int __res;
2358 __asm__ volatile ("int $0x80"
2359 : "=a" (__res)
2360 : "0" (syscallno),
2361 "b" (arg1),
2362 "c" (arg2),
2363 "d" (arg3),
2364 "S" (arg4),
2365 "D" (arg5));
2366 return __res;
2367}
2368
sewardj11f0bb42003-04-26 20:11:15 +00002369
2370WEAK
2371int select ( int n,
2372 fd_set *rfds,
2373 fd_set *wfds,
2374 fd_set *xfds,
2375 struct timeval *timeout )
sewardj08a4c3f2002-04-13 03:45:44 +00002376{
sewardj11f0bb42003-04-26 20:11:15 +00002377 return VGR_(select)(n, rfds, wfds, xfds, timeout);
sewardj08a4c3f2002-04-13 03:45:44 +00002378}
2379
2380
sewardj3b13f0e2002-04-25 20:17:29 +00002381/* ---------------------------------------------------------------------
sewardj8f253ff2002-05-19 00:13:34 +00002382 Hacky implementation of semaphores.
2383 ------------------------------------------------------------------ */
2384
2385#include <semaphore.h>
2386
2387/* This is a terrible way to do the remapping. Plan is to import an
2388 AVL tree at some point. */
sewardj8f253ff2002-05-19 00:13:34 +00002389
2390typedef
2391 struct {
2392 pthread_mutex_t se_mx;
2393 pthread_cond_t se_cv;
2394 int count;
2395 }
2396 vg_sem_t;
2397
2398static pthread_mutex_t se_remap_mx = PTHREAD_MUTEX_INITIALIZER;
2399
2400static int se_remap_used = 0;
2401static sem_t* se_remap_orig[VG_N_SEMAPHORES];
2402static vg_sem_t se_remap_new[VG_N_SEMAPHORES];
2403
2404static vg_sem_t* se_remap ( sem_t* orig )
2405{
2406 int res, i;
2407 res = __pthread_mutex_lock(&se_remap_mx);
sewardj2d94c112002-06-03 01:25:54 +00002408 my_assert(res == 0);
sewardj8f253ff2002-05-19 00:13:34 +00002409
2410 for (i = 0; i < se_remap_used; i++) {
2411 if (se_remap_orig[i] == orig)
2412 break;
2413 }
2414 if (i == se_remap_used) {
2415 if (se_remap_used == VG_N_SEMAPHORES) {
2416 res = pthread_mutex_unlock(&se_remap_mx);
sewardj2d94c112002-06-03 01:25:54 +00002417 my_assert(res == 0);
sewardja1ac5cb2002-05-27 13:00:05 +00002418 barf("VG_N_SEMAPHORES is too low. Increase and recompile.");
sewardj8f253ff2002-05-19 00:13:34 +00002419 }
2420 se_remap_used++;
2421 se_remap_orig[i] = orig;
2422 /* printf("allocated semaphore %d\n", i); */
2423 }
2424 res = __pthread_mutex_unlock(&se_remap_mx);
sewardj2d94c112002-06-03 01:25:54 +00002425 my_assert(res == 0);
sewardj8f253ff2002-05-19 00:13:34 +00002426 return &se_remap_new[i];
2427}
2428
2429
2430int sem_init(sem_t *sem, int pshared, unsigned int value)
2431{
2432 int res;
2433 vg_sem_t* vg_sem;
2434 ensure_valgrind("sem_init");
2435 if (pshared != 0) {
sewardj4dced352002-06-04 22:54:20 +00002436 pthread_error("sem_init: unsupported pshared value");
sewardj8f253ff2002-05-19 00:13:34 +00002437 errno = ENOSYS;
2438 return -1;
2439 }
2440 vg_sem = se_remap(sem);
2441 res = pthread_mutex_init(&vg_sem->se_mx, NULL);
sewardj2d94c112002-06-03 01:25:54 +00002442 my_assert(res == 0);
sewardj8f253ff2002-05-19 00:13:34 +00002443 res = pthread_cond_init(&vg_sem->se_cv, NULL);
sewardj2d94c112002-06-03 01:25:54 +00002444 my_assert(res == 0);
sewardj8f253ff2002-05-19 00:13:34 +00002445 vg_sem->count = value;
2446 return 0;
2447}
2448
2449
2450int sem_wait ( sem_t* sem )
2451{
2452 int res;
2453 vg_sem_t* vg_sem;
2454 ensure_valgrind("sem_wait");
2455 vg_sem = se_remap(sem);
2456 res = __pthread_mutex_lock(&vg_sem->se_mx);
sewardj2d94c112002-06-03 01:25:54 +00002457 my_assert(res == 0);
sewardj8f253ff2002-05-19 00:13:34 +00002458 while (vg_sem->count == 0) {
2459 res = pthread_cond_wait(&vg_sem->se_cv, &vg_sem->se_mx);
sewardj2d94c112002-06-03 01:25:54 +00002460 my_assert(res == 0);
sewardj8f253ff2002-05-19 00:13:34 +00002461 }
2462 vg_sem->count--;
2463 res = __pthread_mutex_unlock(&vg_sem->se_mx);
sewardj2d94c112002-06-03 01:25:54 +00002464 my_assert(res == 0);
sewardj8f253ff2002-05-19 00:13:34 +00002465 return 0;
2466}
2467
2468int sem_post ( sem_t* sem )
2469{
2470 int res;
2471 vg_sem_t* vg_sem;
2472 ensure_valgrind("sem_post");
2473 vg_sem = se_remap(sem);
2474 res = __pthread_mutex_lock(&vg_sem->se_mx);
sewardj2d94c112002-06-03 01:25:54 +00002475 my_assert(res == 0);
sewardj8f253ff2002-05-19 00:13:34 +00002476 if (vg_sem->count == 0) {
2477 vg_sem->count++;
2478 res = pthread_cond_broadcast(&vg_sem->se_cv);
sewardj2d94c112002-06-03 01:25:54 +00002479 my_assert(res == 0);
sewardj8f253ff2002-05-19 00:13:34 +00002480 } else {
2481 vg_sem->count++;
2482 }
2483 res = __pthread_mutex_unlock(&vg_sem->se_mx);
sewardj2d94c112002-06-03 01:25:54 +00002484 my_assert(res == 0);
sewardj8f253ff2002-05-19 00:13:34 +00002485 return 0;
2486}
2487
2488
2489int sem_trywait ( sem_t* sem )
2490{
2491 int ret, res;
2492 vg_sem_t* vg_sem;
2493 ensure_valgrind("sem_trywait");
2494 vg_sem = se_remap(sem);
2495 res = __pthread_mutex_lock(&vg_sem->se_mx);
sewardj2d94c112002-06-03 01:25:54 +00002496 my_assert(res == 0);
sewardj8f253ff2002-05-19 00:13:34 +00002497 if (vg_sem->count > 0) {
2498 vg_sem->count--;
2499 ret = 0;
2500 } else {
2501 ret = -1;
2502 errno = EAGAIN;
2503 }
2504 res = __pthread_mutex_unlock(&vg_sem->se_mx);
sewardj2d94c112002-06-03 01:25:54 +00002505 my_assert(res == 0);
sewardj8f253ff2002-05-19 00:13:34 +00002506 return ret;
2507}
2508
2509
2510int sem_getvalue(sem_t* sem, int * sval)
2511{
2512 vg_sem_t* vg_sem;
2513 ensure_valgrind("sem_trywait");
2514 vg_sem = se_remap(sem);
2515 *sval = vg_sem->count;
2516 return 0;
2517}
2518
2519
2520int sem_destroy(sem_t * sem)
2521{
2522 kludged("sem_destroy");
2523 /* if someone waiting on this semaphore, errno = EBUSY, return -1 */
2524 return 0;
2525}
2526
sewardj9ad92d92002-10-16 19:45:06 +00002527
2528int sem_timedwait(sem_t* sem, const struct timespec *abstime)
2529{
2530 int res;
2531 vg_sem_t* vg_sem;
2532 ensure_valgrind("sem_timedwait");
2533 vg_sem = se_remap(sem);
2534 res = __pthread_mutex_lock(&vg_sem->se_mx);
2535 my_assert(res == 0);
2536 while ( vg_sem->count == 0 && res != ETIMEDOUT ) {
2537 res = pthread_cond_timedwait(&vg_sem->se_cv, &vg_sem->se_mx, abstime);
2538 }
2539 if ( vg_sem->count > 0 ) {
2540 vg_sem->count--;
2541 res = __pthread_mutex_unlock(&vg_sem->se_mx);
2542 my_assert(res == 0 );
2543 return 0;
2544 } else {
2545 res = __pthread_mutex_unlock(&vg_sem->se_mx);
2546 my_assert(res == 0 );
2547 *(__errno_location()) = ETIMEDOUT;
2548 return -1;
2549 }
2550}
2551
sewardj8f253ff2002-05-19 00:13:34 +00002552
2553/* ---------------------------------------------------------------------
sewardj2d8b3f02002-06-01 14:14:19 +00002554 Reader-writer locks.
sewardja1ac5cb2002-05-27 13:00:05 +00002555 ------------------------------------------------------------------ */
2556
sewardj2d8b3f02002-06-01 14:14:19 +00002557typedef
2558 struct {
2559 int initted; /* != 0 --> in use; sanity check only */
2560 int prefer_w; /* != 0 --> prefer writer */
2561 int nwait_r; /* # of waiting readers */
2562 int nwait_w; /* # of waiting writers */
2563 pthread_cond_t cv_r; /* for signalling readers */
2564 pthread_cond_t cv_w; /* for signalling writers */
2565 pthread_mutex_t mx;
2566 int status;
2567 /* allowed range for status: >= -1. -1 means 1 writer currently
2568 active, >= 0 means N readers currently active. */
2569 }
2570 vg_rwlock_t;
sewardja1ac5cb2002-05-27 13:00:05 +00002571
2572
2573static pthread_mutex_t rw_remap_mx = PTHREAD_MUTEX_INITIALIZER;
2574
2575static int rw_remap_used = 0;
2576static pthread_rwlock_t* rw_remap_orig[VG_N_RWLOCKS];
2577static vg_rwlock_t rw_remap_new[VG_N_RWLOCKS];
2578
sewardj2d8b3f02002-06-01 14:14:19 +00002579
2580static
2581void init_vg_rwlock ( vg_rwlock_t* vg_rwl )
2582{
2583 int res = 0;
2584 vg_rwl->initted = 1;
2585 vg_rwl->prefer_w = 1;
2586 vg_rwl->nwait_r = 0;
2587 vg_rwl->nwait_w = 0;
2588 vg_rwl->status = 0;
2589 res = pthread_mutex_init(&vg_rwl->mx, NULL);
2590 res |= pthread_cond_init(&vg_rwl->cv_r, NULL);
2591 res |= pthread_cond_init(&vg_rwl->cv_w, NULL);
sewardj2d94c112002-06-03 01:25:54 +00002592 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002593}
2594
2595
sewardja1ac5cb2002-05-27 13:00:05 +00002596/* Take the address of a LinuxThreads rwlock_t and return the shadow
2597 address of our version. Further, if the LinuxThreads version
2598 appears to have been statically initialised, do the same to the one
2599 we allocate here. The pthread_rwlock_t.__rw_readers field is set
2600 to zero by PTHREAD_RWLOCK_INITIALIZER, so we take zero as meaning
2601 uninitialised and non-zero meaning initialised.
2602*/
2603static vg_rwlock_t* rw_remap ( pthread_rwlock_t* orig )
2604{
2605 int res, i;
2606 vg_rwlock_t* vg_rwl;
2607 res = __pthread_mutex_lock(&rw_remap_mx);
sewardj2d94c112002-06-03 01:25:54 +00002608 my_assert(res == 0);
sewardja1ac5cb2002-05-27 13:00:05 +00002609
2610 for (i = 0; i < rw_remap_used; i++) {
2611 if (rw_remap_orig[i] == orig)
2612 break;
2613 }
2614 if (i == rw_remap_used) {
2615 if (rw_remap_used == VG_N_RWLOCKS) {
sewardj2d8b3f02002-06-01 14:14:19 +00002616 res = __pthread_mutex_unlock(&rw_remap_mx);
sewardj2d94c112002-06-03 01:25:54 +00002617 my_assert(res == 0);
sewardja1ac5cb2002-05-27 13:00:05 +00002618 barf("VG_N_RWLOCKS is too low. Increase and recompile.");
2619 }
2620 rw_remap_used++;
2621 rw_remap_orig[i] = orig;
sewardj2d8b3f02002-06-01 14:14:19 +00002622 rw_remap_new[i].initted = 0;
sewardja1ac5cb2002-05-27 13:00:05 +00002623 if (0) printf("allocated rwlock %d\n", i);
2624 }
2625 res = __pthread_mutex_unlock(&rw_remap_mx);
sewardj2d94c112002-06-03 01:25:54 +00002626 my_assert(res == 0);
sewardja1ac5cb2002-05-27 13:00:05 +00002627 vg_rwl = &rw_remap_new[i];
2628
sewardj2d8b3f02002-06-01 14:14:19 +00002629 /* Initialise the shadow, if required. */
sewardja1ac5cb2002-05-27 13:00:05 +00002630 if (orig->__rw_readers == 0) {
sewardja1ac5cb2002-05-27 13:00:05 +00002631 orig->__rw_readers = 1;
sewardj2d8b3f02002-06-01 14:14:19 +00002632 init_vg_rwlock(vg_rwl);
sewardja1ac5cb2002-05-27 13:00:05 +00002633 if (orig->__rw_kind == PTHREAD_RWLOCK_PREFER_READER_NP)
sewardj2d8b3f02002-06-01 14:14:19 +00002634 vg_rwl->prefer_w = 0;
sewardja1ac5cb2002-05-27 13:00:05 +00002635 }
2636
2637 return vg_rwl;
2638}
2639
2640
sewardja1ac5cb2002-05-27 13:00:05 +00002641int pthread_rwlock_init ( pthread_rwlock_t* orig,
2642 const pthread_rwlockattr_t* attr )
2643{
sewardja1ac5cb2002-05-27 13:00:05 +00002644 vg_rwlock_t* rwl;
2645 if (0) printf ("pthread_rwlock_init\n");
2646 /* Force the remapper to initialise the shadow. */
2647 orig->__rw_readers = 0;
2648 /* Install the lock preference; the remapper needs to know it. */
2649 orig->__rw_kind = PTHREAD_RWLOCK_DEFAULT_NP;
2650 if (attr)
2651 orig->__rw_kind = attr->__lockkind;
2652 rwl = rw_remap ( orig );
sewardj2d8b3f02002-06-01 14:14:19 +00002653 return 0;
sewardja1ac5cb2002-05-27 13:00:05 +00002654}
2655
sewardj2d8b3f02002-06-01 14:14:19 +00002656
2657static
2658void pthread_rwlock_rdlock_CANCEL_HDLR ( void* rwl_v )
sewardja1ac5cb2002-05-27 13:00:05 +00002659{
sewardj2d8b3f02002-06-01 14:14:19 +00002660 vg_rwlock_t* rwl = (vg_rwlock_t*)rwl_v;
2661 rwl->nwait_r--;
2662 pthread_mutex_unlock (&rwl->mx);
sewardja1ac5cb2002-05-27 13:00:05 +00002663}
2664
sewardj2d8b3f02002-06-01 14:14:19 +00002665
sewardja1ac5cb2002-05-27 13:00:05 +00002666int pthread_rwlock_rdlock ( pthread_rwlock_t* orig )
2667{
2668 int res;
2669 vg_rwlock_t* rwl;
2670 if (0) printf ("pthread_rwlock_rdlock\n");
2671 rwl = rw_remap ( orig );
sewardj2d8b3f02002-06-01 14:14:19 +00002672 res = __pthread_mutex_lock(&rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00002673 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002674 if (!rwl->initted) {
2675 res = __pthread_mutex_unlock(&rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00002676 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002677 return EINVAL;
2678 }
2679 if (rwl->status < 0) {
sewardj2d94c112002-06-03 01:25:54 +00002680 my_assert(rwl->status == -1);
sewardj2d8b3f02002-06-01 14:14:19 +00002681 rwl->nwait_r++;
2682 pthread_cleanup_push( pthread_rwlock_rdlock_CANCEL_HDLR, rwl );
2683 while (1) {
2684 if (rwl->status == 0) break;
2685 res = pthread_cond_wait(&rwl->cv_r, &rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00002686 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002687 }
2688 pthread_cleanup_pop(0);
2689 rwl->nwait_r--;
2690 }
sewardj2d94c112002-06-03 01:25:54 +00002691 my_assert(rwl->status >= 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002692 rwl->status++;
2693 res = __pthread_mutex_unlock(&rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00002694 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002695 return 0;
sewardja1ac5cb2002-05-27 13:00:05 +00002696}
2697
sewardj2d8b3f02002-06-01 14:14:19 +00002698
sewardja1ac5cb2002-05-27 13:00:05 +00002699int pthread_rwlock_tryrdlock ( pthread_rwlock_t* orig )
2700{
2701 int res;
2702 vg_rwlock_t* rwl;
2703 if (0) printf ("pthread_rwlock_tryrdlock\n");
2704 rwl = rw_remap ( orig );
sewardj2d8b3f02002-06-01 14:14:19 +00002705 res = __pthread_mutex_lock(&rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00002706 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002707 if (!rwl->initted) {
2708 res = __pthread_mutex_unlock(&rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00002709 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002710 return EINVAL;
2711 }
2712 if (rwl->status == -1) {
2713 /* Writer active; we have to give up. */
2714 res = __pthread_mutex_unlock(&rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00002715 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002716 return EBUSY;
2717 }
2718 /* Success */
sewardj2d94c112002-06-03 01:25:54 +00002719 my_assert(rwl->status >= 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002720 rwl->status++;
2721 res = __pthread_mutex_unlock(&rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00002722 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002723 return 0;
sewardja1ac5cb2002-05-27 13:00:05 +00002724}
2725
sewardj2d8b3f02002-06-01 14:14:19 +00002726
2727static
2728void pthread_rwlock_wrlock_CANCEL_HDLR ( void* rwl_v )
2729{
2730 vg_rwlock_t* rwl = (vg_rwlock_t*)rwl_v;
2731 rwl->nwait_w--;
2732 pthread_mutex_unlock (&rwl->mx);
2733}
2734
2735
sewardja1ac5cb2002-05-27 13:00:05 +00002736int pthread_rwlock_wrlock ( pthread_rwlock_t* orig )
2737{
2738 int res;
2739 vg_rwlock_t* rwl;
2740 if (0) printf ("pthread_rwlock_wrlock\n");
2741 rwl = rw_remap ( orig );
sewardj2d8b3f02002-06-01 14:14:19 +00002742 res = __pthread_mutex_lock(&rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00002743 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002744 if (!rwl->initted) {
2745 res = __pthread_mutex_unlock(&rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00002746 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002747 return EINVAL;
2748 }
2749 if (rwl->status != 0) {
2750 rwl->nwait_w++;
2751 pthread_cleanup_push( pthread_rwlock_wrlock_CANCEL_HDLR, rwl );
2752 while (1) {
2753 if (rwl->status == 0) break;
2754 res = pthread_cond_wait(&rwl->cv_w, &rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00002755 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002756 }
2757 pthread_cleanup_pop(0);
2758 rwl->nwait_w--;
2759 }
sewardj2d94c112002-06-03 01:25:54 +00002760 my_assert(rwl->status == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002761 rwl->status = -1;
2762 res = __pthread_mutex_unlock(&rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00002763 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002764 return 0;
sewardja1ac5cb2002-05-27 13:00:05 +00002765}
2766
sewardj2d8b3f02002-06-01 14:14:19 +00002767
sewardja1ac5cb2002-05-27 13:00:05 +00002768int pthread_rwlock_trywrlock ( pthread_rwlock_t* orig )
2769{
2770 int res;
2771 vg_rwlock_t* rwl;
sewardj2d8b3f02002-06-01 14:14:19 +00002772 if (0) printf ("pthread_wrlock_trywrlock\n");
sewardja1ac5cb2002-05-27 13:00:05 +00002773 rwl = rw_remap ( orig );
sewardj2d8b3f02002-06-01 14:14:19 +00002774 res = __pthread_mutex_lock(&rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00002775 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002776 if (!rwl->initted) {
2777 res = __pthread_mutex_unlock(&rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00002778 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002779 return EINVAL;
2780 }
2781 if (rwl->status != 0) {
2782 /* Reader(s) or a writer active; we have to give up. */
2783 res = __pthread_mutex_unlock(&rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00002784 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002785 return EBUSY;
2786 }
2787 /* Success */
sewardj2d94c112002-06-03 01:25:54 +00002788 my_assert(rwl->status == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002789 rwl->status = -1;
2790 res = __pthread_mutex_unlock(&rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00002791 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002792 return 0;
sewardja1ac5cb2002-05-27 13:00:05 +00002793}
2794
sewardj2d8b3f02002-06-01 14:14:19 +00002795
sewardja1ac5cb2002-05-27 13:00:05 +00002796int pthread_rwlock_unlock ( pthread_rwlock_t* orig )
2797{
2798 int res;
2799 vg_rwlock_t* rwl;
2800 if (0) printf ("pthread_rwlock_unlock\n");
2801 rwl = rw_remap ( orig );
sewardj2d8b3f02002-06-01 14:14:19 +00002802 rwl = rw_remap ( orig );
2803 res = __pthread_mutex_lock(&rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00002804 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002805 if (!rwl->initted) {
2806 res = __pthread_mutex_unlock(&rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00002807 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002808 return EINVAL;
2809 }
2810 if (rwl->status == 0) {
2811 res = __pthread_mutex_unlock(&rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00002812 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002813 return EPERM;
2814 }
sewardj2d94c112002-06-03 01:25:54 +00002815 my_assert(rwl->status != 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002816 if (rwl->status == -1) {
2817 rwl->status = 0;
2818 } else {
sewardj2d94c112002-06-03 01:25:54 +00002819 my_assert(rwl->status > 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002820 rwl->status--;
2821 }
2822
sewardj2d94c112002-06-03 01:25:54 +00002823 my_assert(rwl->status >= 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002824
2825 if (rwl->prefer_w) {
2826
2827 /* Favour waiting writers, if any. */
2828 if (rwl->nwait_w > 0) {
2829 /* Writer(s) are waiting. */
2830 if (rwl->status == 0) {
2831 /* We can let a writer in. */
2832 res = pthread_cond_signal(&rwl->cv_w);
sewardj2d94c112002-06-03 01:25:54 +00002833 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002834 } else {
2835 /* There are still readers active. Do nothing; eventually
2836 they will disappear, at which point a writer will be
2837 admitted. */
2838 }
2839 }
2840 else
2841 /* No waiting writers. */
2842 if (rwl->nwait_r > 0) {
2843 /* Let in a waiting reader. */
2844 res = pthread_cond_signal(&rwl->cv_r);
sewardj2d94c112002-06-03 01:25:54 +00002845 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002846 }
2847
2848 } else {
2849
2850 /* Favour waiting readers, if any. */
2851 if (rwl->nwait_r > 0) {
2852 /* Reader(s) are waiting; let one in. */
2853 res = pthread_cond_signal(&rwl->cv_r);
sewardj2d94c112002-06-03 01:25:54 +00002854 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002855 }
2856 else
2857 /* No waiting readers. */
2858 if (rwl->nwait_w > 0 && rwl->status == 0) {
2859 /* We have waiting writers and no active readers; let a
2860 writer in. */
2861 res = pthread_cond_signal(&rwl->cv_w);
sewardj2d94c112002-06-03 01:25:54 +00002862 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002863 }
2864 }
2865
2866 res = __pthread_mutex_unlock(&rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00002867 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002868 return 0;
2869}
2870
2871
2872int pthread_rwlock_destroy ( pthread_rwlock_t *orig )
2873{
2874 int res;
2875 vg_rwlock_t* rwl;
2876 if (0) printf ("pthread_rwlock_destroy\n");
2877 rwl = rw_remap ( orig );
2878 res = __pthread_mutex_lock(&rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00002879 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002880 if (!rwl->initted) {
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 EINVAL;
2884 }
2885 if (rwl->status != 0 || rwl->nwait_r > 0 || rwl->nwait_w > 0) {
2886 res = __pthread_mutex_unlock(&rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00002887 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002888 return EBUSY;
2889 }
2890 rwl->initted = 0;
2891 res = __pthread_mutex_unlock(&rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00002892 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002893 return 0;
sewardja1ac5cb2002-05-27 13:00:05 +00002894}
2895
2896
sewardj47e4e312002-06-18 09:24:34 +00002897/* Copied directly from LinuxThreads. */
2898int
2899pthread_rwlockattr_init (pthread_rwlockattr_t *attr)
2900{
2901 attr->__lockkind = 0;
2902 attr->__pshared = PTHREAD_PROCESS_PRIVATE;
2903
2904 return 0;
2905}
2906
sewardjfe18eb82002-07-13 12:58:44 +00002907/* Copied directly from LinuxThreads. */
2908int
sewardj5706bfa2002-12-08 23:42:17 +00002909pthread_rwlockattr_destroy (pthread_rwlockattr_t *attr)
2910{
2911 return 0;
2912}
2913
2914/* Copied directly from LinuxThreads. */
2915int
sewardjfe18eb82002-07-13 12:58:44 +00002916pthread_rwlockattr_setpshared (pthread_rwlockattr_t *attr, int pshared)
2917{
2918 if (pshared != PTHREAD_PROCESS_PRIVATE && pshared != PTHREAD_PROCESS_SHARED)
2919 return EINVAL;
2920
2921 /* For now it is not possible to shared a conditional variable. */
2922 if (pshared != PTHREAD_PROCESS_PRIVATE)
2923 return ENOSYS;
2924
2925 attr->__pshared = pshared;
2926
2927 return 0;
2928}
2929
sewardj47e4e312002-06-18 09:24:34 +00002930
sewardja1ac5cb2002-05-27 13:00:05 +00002931/* ---------------------------------------------------------------------
sewardj11f0bb42003-04-26 20:11:15 +00002932 Make SYSV IPC not block everything -- pass to vg_intercept.c.
sewardjd5bef572002-10-23 21:49:33 +00002933 ------------------------------------------------------------------ */
2934
sewardj11f0bb42003-04-26 20:11:15 +00002935WEAK
2936int msgsnd(int msgid, const void *msgp, size_t msgsz, int msgflg)
sewardjd5bef572002-10-23 21:49:33 +00002937{
sewardj11f0bb42003-04-26 20:11:15 +00002938 return VGR_(msgsnd)(msgid, msgp, msgsz, msgflg);
sewardjd5bef572002-10-23 21:49:33 +00002939}
2940
sewardj11f0bb42003-04-26 20:11:15 +00002941WEAK
2942int msgrcv(int msqid, void* msgp, size_t msgsz,
2943 long msgtyp, int msgflg )
sewardjd5bef572002-10-23 21:49:33 +00002944{
sewardj11f0bb42003-04-26 20:11:15 +00002945 return VGR_(msgrcv)(msqid, msgp, msgsz, msgtyp, msgflg );
sewardjd5bef572002-10-23 21:49:33 +00002946}
2947
sewardj262b5be2003-04-26 21:19:53 +00002948
2949/* ---------------------------------------------------------------------
2950 The glibc sources say that returning -1 in these 3 functions
2951 causes real time signals not to be used.
2952 ------------------------------------------------------------------ */
2953
2954int __libc_current_sigrtmin (void)
2955{
2956 static int moans = N_MOANS;
2957 if (moans-- > 0)
2958 kludged("__libc_current_sigrtmin");
2959 return -1;
2960}
2961
2962int __libc_current_sigrtmax (void)
2963{
2964 static int moans = N_MOANS;
2965 if (moans-- > 0)
2966 kludged("__libc_current_sigrtmax");
2967 return -1;
2968}
2969
2970int __libc_allocate_rtsig (int high)
2971{
2972 static int moans = N_MOANS;
2973 if (moans-- > 0)
2974 kludged("__libc_allocate_rtsig");
2975 return -1;
2976}
2977
2978
sewardjd5bef572002-10-23 21:49:33 +00002979/* ---------------------------------------------------------------------
sewardj3b13f0e2002-04-25 20:17:29 +00002980 B'stard.
2981 ------------------------------------------------------------------ */
2982
2983# define strong_alias(name, aliasname) \
2984 extern __typeof (name) aliasname __attribute__ ((alias (#name)));
2985
sewardj5905fae2002-04-26 13:25:00 +00002986# define weak_alias(name, aliasname) \
2987 extern __typeof (name) aliasname __attribute__ ((weak, alias (#name)));
sewardj3b13f0e2002-04-25 20:17:29 +00002988
sewardj5905fae2002-04-26 13:25:00 +00002989strong_alias(__pthread_mutex_lock, pthread_mutex_lock)
2990strong_alias(__pthread_mutex_trylock, pthread_mutex_trylock)
2991strong_alias(__pthread_mutex_unlock, pthread_mutex_unlock)
2992strong_alias(__pthread_mutexattr_init, pthread_mutexattr_init)
2993 weak_alias(__pthread_mutexattr_settype, pthread_mutexattr_settype)
2994strong_alias(__pthread_mutex_init, pthread_mutex_init)
2995strong_alias(__pthread_mutexattr_destroy, pthread_mutexattr_destroy)
2996strong_alias(__pthread_mutex_destroy, pthread_mutex_destroy)
2997strong_alias(__pthread_once, pthread_once)
2998strong_alias(__pthread_atfork, pthread_atfork)
2999strong_alias(__pthread_key_create, pthread_key_create)
3000strong_alias(__pthread_getspecific, pthread_getspecific)
3001strong_alias(__pthread_setspecific, pthread_setspecific)
3002
sewardjd529a442002-05-04 19:49:21 +00003003#ifndef GLIBC_2_1
sewardj3b13f0e2002-04-25 20:17:29 +00003004strong_alias(sigaction, __sigaction)
sewardjd529a442002-05-04 19:49:21 +00003005#endif
3006
sewardj5905fae2002-04-26 13:25:00 +00003007strong_alias(close, __close)
sewardj3b13f0e2002-04-25 20:17:29 +00003008strong_alias(fcntl, __fcntl)
sewardj5905fae2002-04-26 13:25:00 +00003009strong_alias(lseek, __lseek)
3010strong_alias(open, __open)
3011strong_alias(open64, __open64)
sewardj5905fae2002-04-26 13:25:00 +00003012strong_alias(read, __read)
3013strong_alias(wait, __wait)
3014strong_alias(write, __write)
sewardj3b13f0e2002-04-25 20:17:29 +00003015strong_alias(connect, __connect)
sewardj5905fae2002-04-26 13:25:00 +00003016strong_alias(send, __send)
3017
sewardj726c4122002-05-16 23:39:10 +00003018weak_alias (__pread64, pread64)
sewardja18e2102002-05-18 10:43:22 +00003019weak_alias (__pwrite64, pwrite64)
sewardj5905fae2002-04-26 13:25:00 +00003020weak_alias(__fork, fork)
njn25e49d8e72002-09-23 09:36:25 +00003021weak_alias(__vfork, vfork)
sewardj7f6456d2002-05-21 00:51:21 +00003022
sewardjf0b06452002-06-04 08:38:04 +00003023weak_alias (__pthread_kill_other_threads_np, pthread_kill_other_threads_np)
sewardj3b13f0e2002-04-25 20:17:29 +00003024
3025/*--------------------------------------------------*/
3026
sewardj5905fae2002-04-26 13:25:00 +00003027weak_alias(pthread_rwlock_rdlock, __pthread_rwlock_rdlock)
sewardj5905fae2002-04-26 13:25:00 +00003028weak_alias(pthread_rwlock_unlock, __pthread_rwlock_unlock)
sewardj262b0292002-05-01 00:03:16 +00003029weak_alias(pthread_rwlock_wrlock, __pthread_rwlock_wrlock)
sewardj060b04f2002-04-26 21:01:13 +00003030
sewardja1ac5cb2002-05-27 13:00:05 +00003031weak_alias(pthread_rwlock_destroy, __pthread_rwlock_destroy)
3032weak_alias(pthread_rwlock_init, __pthread_rwlock_init)
3033weak_alias(pthread_rwlock_tryrdlock, __pthread_rwlock_tryrdlock)
3034weak_alias(pthread_rwlock_trywrlock, __pthread_rwlock_trywrlock)
3035
sewardj060b04f2002-04-26 21:01:13 +00003036
sewardj3b13f0e2002-04-25 20:17:29 +00003037/* I've no idea what these are, but they get called quite a lot.
3038 Anybody know? */
3039
3040#undef _IO_flockfile
3041void _IO_flockfile ( _IO_FILE * file )
3042{
sewardj853f55d2002-04-26 00:27:53 +00003043 pthread_mutex_lock(file->_lock);
sewardj3b13f0e2002-04-25 20:17:29 +00003044}
sewardj5905fae2002-04-26 13:25:00 +00003045weak_alias(_IO_flockfile, flockfile);
3046
sewardj3b13f0e2002-04-25 20:17:29 +00003047
3048#undef _IO_funlockfile
3049void _IO_funlockfile ( _IO_FILE * file )
3050{
sewardj853f55d2002-04-26 00:27:53 +00003051 pthread_mutex_unlock(file->_lock);
sewardj3b13f0e2002-04-25 20:17:29 +00003052}
sewardj5905fae2002-04-26 13:25:00 +00003053weak_alias(_IO_funlockfile, funlockfile);
3054
sewardj3b13f0e2002-04-25 20:17:29 +00003055
sewardjd4f2c712002-04-30 10:20:10 +00003056/* This doesn't seem to be needed to simulate libpthread.so's external
3057 interface, but many people complain about its absence. */
3058
3059strong_alias(__pthread_mutexattr_settype, __pthread_mutexattr_setkind_np)
3060weak_alias(__pthread_mutexattr_setkind_np, pthread_mutexattr_setkind_np)
sewardj439d45e2002-05-03 20:43:10 +00003061
3062
3063/*--------------------------------------------------------------------*/
3064/*--- end vg_libpthread.c ---*/
3065/*--------------------------------------------------------------------*/