blob: c04f15c646b8dea5815b1896a853d15fb919c9fe [file] [log] [blame]
sewardje663cb92002-04-12 10:26:32 +00001
sewardj439d45e2002-05-03 20:43:10 +00002/*--------------------------------------------------------------------*/
3/*--- A replacement for the standard libpthread.so. ---*/
4/*--- vg_libpthread.c ---*/
5/*--------------------------------------------------------------------*/
6
7/*
njnc9539842002-10-02 13:26:35 +00008 This file is part of Valgrind, an extensible x86 protected-mode
9 emulator for monitoring program execution on x86-Unixes.
sewardj439d45e2002-05-03 20:43:10 +000010
njn0e1b5142003-04-15 14:58:06 +000011 Copyright (C) 2000-2003 Julian Seward
sewardj439d45e2002-05-03 20:43:10 +000012 jseward@acm.org
13
14 This program is free software; you can redistribute it and/or
15 modify it under the terms of the GNU General Public License as
16 published by the Free Software Foundation; either version 2 of the
17 License, or (at your option) any later version.
18
19 This program is distributed in the hope that it will be useful, but
20 WITHOUT ANY WARRANTY; without even the implied warranty of
21 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
22 General Public License for more details.
23
24 You should have received a copy of the GNU General Public License
25 along with this program; if not, write to the Free Software
26 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
27 02111-1307, USA.
28
njn25e49d8e72002-09-23 09:36:25 +000029 The GNU General Public License is contained in the file COPYING.
sewardj439d45e2002-05-03 20:43:10 +000030*/
31
32/* ALL THIS CODE RUNS ON THE SIMULATED CPU.
33
34 This is a replacement for the standard libpthread.so. It is loaded
sewardje663cb92002-04-12 10:26:32 +000035 as part of the client's image (if required) and directs pthread
36 calls through to Valgrind's request mechanism.
37
38 A couple of caveats.
39
40 1. Since it's a binary-compatible replacement for an existing library,
41 we must take care to used exactly the same data layouts, etc, as
42 the standard pthread.so does.
43
44 2. Since this runs as part of the client, there are no specific
45 restrictions on what headers etc we can include, so long as
46 this libpthread.so does not end up having dependencies on .so's
47 which the real one doesn't.
48
49 Later ... it appears we cannot call file-related stuff in libc here,
50 perhaps fair enough. Be careful what you call from here. Even exit()
51 doesn't work (gives infinite recursion and then stack overflow); hence
52 myexit(). Also fprintf doesn't seem safe.
53*/
54
sewardje12a45f2003-03-15 20:03:33 +000055/* Sidestep the normal check which disallows using valgrind.h
56 directly. */
57#define __VALGRIND_SOMESKIN_H
sewardje663cb92002-04-12 10:26:32 +000058#include "valgrind.h" /* For the request-passing mechanism */
sewardje12a45f2003-03-15 20:03:33 +000059
sewardje663cb92002-04-12 10:26:32 +000060#include "vg_include.h" /* For the VG_USERREQ__* constants */
61
sewardja1ac5cb2002-05-27 13:00:05 +000062#define __USE_UNIX98
63#include <sys/types.h>
64#include <pthread.h>
65#undef __USE_UNIX98
66
sewardje663cb92002-04-12 10:26:32 +000067#include <unistd.h>
68#include <string.h>
sewardj2a1dcce2002-04-22 12:45:25 +000069#ifdef GLIBC_2_1
70#include <sys/time.h>
71#endif
sewardjf912dfc2002-11-13 21:51:10 +000072#include <sys/stat.h>
73#include <sys/poll.h>
sewardj2d94c112002-06-03 01:25:54 +000074#include <stdio.h>
75
sewardj705d3cb2002-05-23 13:13:12 +000076
77/* ---------------------------------------------------------------------
78 Forwardses.
79 ------------------------------------------------------------------ */
80
sewardj11f0bb42003-04-26 20:11:15 +000081#define WEAK __attribute__((weak))
82
sewardj705d3cb2002-05-23 13:13:12 +000083
sewardj9a2224b2002-06-19 10:17:40 +000084static
sewardj08c7f012002-10-07 23:56:55 +000085int my_do_syscall1 ( int syscallno, int arg1 );
86
87static
sewardj9a2224b2002-06-19 10:17:40 +000088int my_do_syscall2 ( int syscallno,
89 int arg1, int arg2 );
90
sewardj08c7f012002-10-07 23:56:55 +000091static
92int my_do_syscall3 ( int syscallno,
93 int arg1, int arg2, int arg3 );
94
sewardjfd7747b2002-12-01 10:25:53 +000095static
96__inline__
97int is_kerror ( int res )
98{
99 if (res >= -4095 && res <= -1)
100 return 1;
101 else
102 return 0;
103}
104
sewardj08c7f012002-10-07 23:56:55 +0000105
106#ifdef GLIBC_2_3
107 /* kludge by JRS (not from glibc) ... */
108 typedef void* __locale_t;
109
110 /* Copied from locale/locale.h in glibc-2.2.93 sources */
111 /* This value can be passed to `uselocale' and may be returned by
112 it. Passing this value to any other function has undefined
113 behavior. */
114# define LC_GLOBAL_LOCALE ((__locale_t) -1L)
115 extern __locale_t __uselocale ( __locale_t );
116#endif
117
sewardj00a66b12002-10-12 16:42:35 +0000118static
119void init_libc_tsd_keys ( void );
120
sewardj705d3cb2002-05-23 13:13:12 +0000121
sewardje663cb92002-04-12 10:26:32 +0000122/* ---------------------------------------------------------------------
123 Helpers. We have to be pretty self-sufficient.
124 ------------------------------------------------------------------ */
125
sewardj436e0582002-04-26 14:31:40 +0000126/* Number of times any given error message is printed. */
127#define N_MOANS 3
128
sewardj45b4b372002-04-16 22:50:32 +0000129/* Extract from Valgrind the value of VG_(clo_trace_pthread_level).
130 Returns 0 (none) if not running on Valgrind. */
131static
132int get_pt_trace_level ( void )
133{
134 int res;
135 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
136 VG_USERREQ__GET_PTHREAD_TRACE_LEVEL,
137 0, 0, 0, 0);
138 return res;
139}
140
sewardje663cb92002-04-12 10:26:32 +0000141static
sewardj2d94c112002-06-03 01:25:54 +0000142void my_exit ( int arg )
sewardje663cb92002-04-12 10:26:32 +0000143{
sewardj08c7f012002-10-07 23:56:55 +0000144 my_do_syscall1(__NR_exit, arg);
145 /*NOTREACHED*/
sewardje663cb92002-04-12 10:26:32 +0000146}
147
sewardje0cfe2a2002-11-30 14:04:45 +0000148/* Apparently unused.
sewardj08c7f012002-10-07 23:56:55 +0000149static
150void my_write ( int fd, const void *buf, int count )
151{
152 my_do_syscall3(__NR_write, fd, (int)buf, count );
153}
sewardje0cfe2a2002-11-30 14:04:45 +0000154*/
sewardje663cb92002-04-12 10:26:32 +0000155
sewardj68b2dd92002-05-10 21:03:56 +0000156/* We need this guy -- it's in valgrind.so. */
157extern void VG_(startup) ( void );
158
159
160/* Just start up Valgrind if it's not already going. VG_(startup)()
161 detects and ignores second and subsequent calls. */
sewardj604ec3c2002-04-18 22:38:41 +0000162static __inline__
sewardje663cb92002-04-12 10:26:32 +0000163void ensure_valgrind ( char* caller )
164{
sewardj68b2dd92002-05-10 21:03:56 +0000165 VG_(startup)();
sewardje663cb92002-04-12 10:26:32 +0000166}
167
sewardjbea1caa2002-05-10 23:20:58 +0000168/* While we're at it ... hook our own startup function into this
169 game. */
170__asm__ (
171 ".section .init\n"
172 "\tcall vgPlain_startup"
173);
174
sewardje663cb92002-04-12 10:26:32 +0000175
176static
sewardj3b5d8862002-04-20 13:53:23 +0000177__attribute__((noreturn))
sewardje663cb92002-04-12 10:26:32 +0000178void barf ( char* str )
179{
sewardj69a72a52002-11-03 13:41:41 +0000180 char buf[1000];
sewardje663cb92002-04-12 10:26:32 +0000181 buf[0] = 0;
sewardj439d45e2002-05-03 20:43:10 +0000182 strcat(buf, "\nvalgrind's libpthread.so: ");
sewardje663cb92002-04-12 10:26:32 +0000183 strcat(buf, str);
184 strcat(buf, "\n\n");
njn4c791212003-05-02 17:53:54 +0000185 VALGRIND_NON_SIMD_CALL2(VG_(message), Vg_UserMsg, buf);
sewardj2d94c112002-06-03 01:25:54 +0000186 my_exit(1);
sewardj3b5d8862002-04-20 13:53:23 +0000187 /* We have to persuade gcc into believing this doesn't return. */
188 while (1) { };
sewardje663cb92002-04-12 10:26:32 +0000189}
190
191
sewardj69a72a52002-11-03 13:41:41 +0000192static void cat_n_send ( char* pre, char* msg )
sewardj2a3d28c2002-04-14 13:27:00 +0000193{
sewardj69a72a52002-11-03 13:41:41 +0000194 char buf[1000];
sewardj436e0582002-04-26 14:31:40 +0000195 if (get_pt_trace_level() >= 0) {
sewardj69a72a52002-11-03 13:41:41 +0000196 snprintf(buf, sizeof(buf), "%s%s", pre, msg );
197 buf[sizeof(buf)-1] = '\0';
njn4c791212003-05-02 17:53:54 +0000198 VALGRIND_NON_SIMD_CALL2(VG_(message), Vg_UserMsg, buf);
sewardj45b4b372002-04-16 22:50:32 +0000199 }
sewardj2a3d28c2002-04-14 13:27:00 +0000200}
201
sewardj69a72a52002-11-03 13:41:41 +0000202static void ignored ( char* msg )
203{
204 cat_n_send ( "valgrind's libpthread.so: IGNORED call to: ", msg );
205}
206
207
sewardj30671ff2002-04-21 00:13:57 +0000208static void kludged ( char* msg )
209{
sewardj69a72a52002-11-03 13:41:41 +0000210 cat_n_send ( "valgrind's libpthread.so: KLUDGED call to: ", msg );
sewardj439d45e2002-05-03 20:43:10 +0000211}
212
sewardj69a72a52002-11-03 13:41:41 +0000213
sewardjccef2e62002-05-29 19:26:32 +0000214__attribute__((noreturn))
sewardj3b13f0e2002-04-25 20:17:29 +0000215void vgPlain_unimp ( char* what )
216{
sewardj69a72a52002-11-03 13:41:41 +0000217 cat_n_send (
218 "valgrind's libpthread.so: UNIMPLEMENTED FUNCTION: ", what );
sewardj3b13f0e2002-04-25 20:17:29 +0000219 barf("Please report this bug to me at: jseward@acm.org");
220}
221
sewardje663cb92002-04-12 10:26:32 +0000222
sewardj457cc472002-06-03 23:13:47 +0000223static
sewardj2d94c112002-06-03 01:25:54 +0000224void my_assert_fail ( Char* expr, Char* file, Int line, Char* fn )
225{
sewardj69a72a52002-11-03 13:41:41 +0000226 char buf[1000];
sewardj2d94c112002-06-03 01:25:54 +0000227 static Bool entered = False;
228 if (entered)
229 my_exit(2);
230 entered = True;
sewardj69a72a52002-11-03 13:41:41 +0000231 sprintf(buf, "\n%s: %s:%d (%s): Assertion `%s' failed.\n",
232 "valgrind", file, line, fn, expr );
233 cat_n_send ( "", buf );
234 sprintf(buf, "Please report this bug to me at: %s\n\n",
235 VG_EMAIL_ADDR);
236 cat_n_send ( "", buf );
sewardj2d94c112002-06-03 01:25:54 +0000237 my_exit(1);
238}
239
240#define MY__STRING(__str) #__str
241
242#define my_assert(expr) \
243 ((void) ((expr) ? 0 : \
244 (my_assert_fail (MY__STRING(expr), \
245 __FILE__, __LINE__, \
246 __PRETTY_FUNCTION__), 0)))
247
sewardj00a66b12002-10-12 16:42:35 +0000248static
249void my_free ( void* ptr )
250{
251 int res;
252 VALGRIND_MAGIC_SEQUENCE(res, (-1) /* default */,
253 VG_USERREQ__FREE, ptr, 0, 0, 0);
254 my_assert(res == 0);
255}
256
257
258static
259void* my_malloc ( int nbytes )
260{
261 void* res;
262 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
263 VG_USERREQ__MALLOC, nbytes, 0, 0, 0);
264 my_assert(res != (void*)0);
265 return res;
266}
267
268
sewardj2d94c112002-06-03 01:25:54 +0000269
sewardje663cb92002-04-12 10:26:32 +0000270/* ---------------------------------------------------------------------
271 Pass pthread_ calls to Valgrind's request mechanism.
272 ------------------------------------------------------------------ */
273
sewardjf8f819e2002-04-17 23:21:37 +0000274#include <errno.h>
sewardj5f07b662002-04-23 16:52:51 +0000275#include <sys/time.h> /* gettimeofday */
sewardjf8f819e2002-04-17 23:21:37 +0000276
sewardja1ac5cb2002-05-27 13:00:05 +0000277
sewardjf8f819e2002-04-17 23:21:37 +0000278/* ---------------------------------------------------
sewardj4dced352002-06-04 22:54:20 +0000279 Ummm ..
280 ------------------------------------------------ */
281
282static
283void pthread_error ( const char* msg )
284{
285 int res;
286 VALGRIND_MAGIC_SEQUENCE(res, 0,
287 VG_USERREQ__PTHREAD_ERROR,
288 msg, 0, 0, 0);
289}
290
291
292/* ---------------------------------------------------
sewardj00a66b12002-10-12 16:42:35 +0000293 Here so it can be inlined without complaint.
294 ------------------------------------------------ */
295
296__inline__
297pthread_t pthread_self(void)
298{
299 int tid;
300 ensure_valgrind("pthread_self");
301 VALGRIND_MAGIC_SEQUENCE(tid, 0 /* default */,
302 VG_USERREQ__PTHREAD_GET_THREADID,
303 0, 0, 0, 0);
304 if (tid < 1 || tid >= VG_N_THREADS)
305 barf("pthread_self: invalid ThreadId");
306 return tid;
307}
308
309
310/* ---------------------------------------------------
sewardjf8f819e2002-04-17 23:21:37 +0000311 THREAD ATTRIBUTES
312 ------------------------------------------------ */
313
sewardj6af4b5d2002-04-16 04:40:49 +0000314int pthread_attr_init(pthread_attr_t *attr)
315{
sewardj7989d0c2002-05-28 11:00:01 +0000316 /* Just initialise the fields which we might look at. */
317 attr->__detachstate = PTHREAD_CREATE_JOINABLE;
sewardj111b14c2002-10-20 16:22:57 +0000318 /* Linuxthreads sets this field to the value __getpagesize(), so I
319 guess the following is OK. */
320 attr->__guardsize = VKI_BYTES_PER_PAGE; return 0;
sewardj6af4b5d2002-04-16 04:40:49 +0000321}
322
323int pthread_attr_setdetachstate(pthread_attr_t *attr, int detachstate)
324{
sewardj7989d0c2002-05-28 11:00:01 +0000325 if (detachstate != PTHREAD_CREATE_JOINABLE
sewardj4dced352002-06-04 22:54:20 +0000326 && detachstate != PTHREAD_CREATE_DETACHED) {
327 pthread_error("pthread_attr_setdetachstate: "
328 "detachstate is invalid");
sewardj7989d0c2002-05-28 11:00:01 +0000329 return EINVAL;
sewardj4dced352002-06-04 22:54:20 +0000330 }
sewardj7989d0c2002-05-28 11:00:01 +0000331 attr->__detachstate = detachstate;
sewardj6af4b5d2002-04-16 04:40:49 +0000332 return 0;
333}
334
njn25e49d8e72002-09-23 09:36:25 +0000335int pthread_attr_getdetachstate(const pthread_attr_t *attr, int *detachstate)
336{
337 *detachstate = attr->__detachstate;
338 return 0;
339}
340
sewardj30671ff2002-04-21 00:13:57 +0000341int pthread_attr_setinheritsched(pthread_attr_t *attr, int inherit)
342{
sewardj436e0582002-04-26 14:31:40 +0000343 static int moans = N_MOANS;
344 if (moans-- > 0)
345 ignored("pthread_attr_setinheritsched");
sewardj30671ff2002-04-21 00:13:57 +0000346 return 0;
347}
sewardj6af4b5d2002-04-16 04:40:49 +0000348
sewardj11f0bb42003-04-26 20:11:15 +0000349WEAK
sewardj0286dd52002-05-16 20:51:15 +0000350int pthread_attr_setstacksize (pthread_attr_t *__attr,
351 size_t __stacksize)
352{
sewardja18e2102002-05-18 10:43:22 +0000353 size_t limit;
sewardj3d7c8d62002-06-04 20:59:16 +0000354 char buf[1024];
sewardj0286dd52002-05-16 20:51:15 +0000355 ensure_valgrind("pthread_attr_setstacksize");
sewardja18e2102002-05-18 10:43:22 +0000356 limit = VG_PTHREAD_STACK_SIZE - VG_AR_CLIENT_STACKBASE_REDZONE_SZB
357 - 1000; /* paranoia */
358 if (__stacksize < limit)
sewardj0286dd52002-05-16 20:51:15 +0000359 return 0;
sewardj3d7c8d62002-06-04 20:59:16 +0000360 snprintf(buf, sizeof(buf), "pthread_attr_setstacksize: "
361 "requested size %d >= VG_PTHREAD_STACK_SIZE\n "
362 "edit vg_include.h and rebuild.", __stacksize);
363 buf[sizeof(buf)-1] = '\0'; /* Make sure it is zero terminated */
364 barf(buf);
sewardj0286dd52002-05-16 20:51:15 +0000365}
366
367
sewardj30671ff2002-04-21 00:13:57 +0000368/* This is completely bogus. */
369int pthread_attr_getschedparam(const pthread_attr_t *attr,
370 struct sched_param *param)
371{
sewardj436e0582002-04-26 14:31:40 +0000372 static int moans = N_MOANS;
373 if (moans-- > 0)
374 kludged("pthread_attr_getschedparam");
sewardj3e909ce2002-06-03 13:27:15 +0000375# ifdef HAVE_SCHED_PRIORITY
sewardj72d58482002-04-24 02:20:20 +0000376 if (param) param->sched_priority = 0; /* who knows */
377# else
sewardj30671ff2002-04-21 00:13:57 +0000378 if (param) param->__sched_priority = 0; /* who knows */
sewardj72d58482002-04-24 02:20:20 +0000379# endif
sewardj30671ff2002-04-21 00:13:57 +0000380 return 0;
381}
382
383int pthread_attr_setschedparam(pthread_attr_t *attr,
384 const struct sched_param *param)
385{
sewardj436e0582002-04-26 14:31:40 +0000386 static int moans = N_MOANS;
387 if (moans-- > 0)
388 ignored("pthread_attr_setschedparam");
sewardj30671ff2002-04-21 00:13:57 +0000389 return 0;
390}
391
392int pthread_attr_destroy(pthread_attr_t *attr)
393{
sewardj436e0582002-04-26 14:31:40 +0000394 static int moans = N_MOANS;
395 if (moans-- > 0)
396 ignored("pthread_attr_destroy");
sewardj30671ff2002-04-21 00:13:57 +0000397 return 0;
398}
sewardjf8f819e2002-04-17 23:21:37 +0000399
sewardj0d844232002-06-02 09:29:31 +0000400/* These are no-ops, as with LinuxThreads. */
401int pthread_attr_setscope ( pthread_attr_t *attr, int scope )
402{
403 ensure_valgrind("pthread_attr_setscope");
404 if (scope == PTHREAD_SCOPE_SYSTEM)
405 return 0;
sewardj4dced352002-06-04 22:54:20 +0000406 pthread_error("pthread_attr_setscope: "
407 "invalid or unsupported scope");
sewardj0d844232002-06-02 09:29:31 +0000408 if (scope == PTHREAD_SCOPE_PROCESS)
409 return ENOTSUP;
410 return EINVAL;
411}
412
413int pthread_attr_getscope ( const pthread_attr_t *attr, int *scope )
414{
415 ensure_valgrind("pthread_attr_setscope");
416 if (scope)
417 *scope = PTHREAD_SCOPE_SYSTEM;
418 return 0;
419}
420
sewardj64039bb2002-06-03 00:58:18 +0000421
422/* Pretty bogus. Avoid if possible. */
423int pthread_getattr_np (pthread_t thread, pthread_attr_t *attr)
424{
425 int detached;
426 size_t limit;
427 ensure_valgrind("pthread_getattr_np");
428 kludged("pthread_getattr_np");
429 limit = VG_PTHREAD_STACK_SIZE - VG_AR_CLIENT_STACKBASE_REDZONE_SZB
430 - 1000; /* paranoia */
431 attr->__detachstate = PTHREAD_CREATE_JOINABLE;
432 attr->__schedpolicy = SCHED_OTHER;
433 attr->__schedparam.sched_priority = 0;
434 attr->__inheritsched = PTHREAD_EXPLICIT_SCHED;
435 attr->__scope = PTHREAD_SCOPE_SYSTEM;
436 attr->__guardsize = VKI_BYTES_PER_PAGE;
437 attr->__stackaddr = NULL;
438 attr->__stackaddr_set = 0;
439 attr->__stacksize = limit;
440 VALGRIND_MAGIC_SEQUENCE(detached, (-1) /* default */,
441 VG_USERREQ__SET_OR_GET_DETACH,
442 2 /* get */, thread, 0, 0);
sewardj2d94c112002-06-03 01:25:54 +0000443 my_assert(detached == 0 || detached == 1);
sewardj64039bb2002-06-03 00:58:18 +0000444 if (detached)
445 attr->__detachstate = PTHREAD_CREATE_DETACHED;
446 return 0;
447}
448
449
450/* Bogus ... */
sewardj11f0bb42003-04-26 20:11:15 +0000451WEAK
sewardj64039bb2002-06-03 00:58:18 +0000452int pthread_attr_getstackaddr ( const pthread_attr_t * attr,
453 void ** stackaddr )
454{
455 ensure_valgrind("pthread_attr_getstackaddr");
456 kludged("pthread_attr_getstackaddr");
457 if (stackaddr)
458 *stackaddr = NULL;
459 return 0;
460}
461
462/* Not bogus (!) */
sewardj11f0bb42003-04-26 20:11:15 +0000463WEAK
sewardj64039bb2002-06-03 00:58:18 +0000464int pthread_attr_getstacksize ( const pthread_attr_t * _attr,
465 size_t * __stacksize )
466{
467 size_t limit;
468 ensure_valgrind("pthread_attr_getstacksize");
469 limit = VG_PTHREAD_STACK_SIZE - VG_AR_CLIENT_STACKBASE_REDZONE_SZB
470 - 1000; /* paranoia */
471 if (__stacksize)
472 *__stacksize = limit;
473 return 0;
474}
475
sewardja3be12f2002-06-17 12:19:44 +0000476int pthread_attr_setschedpolicy(pthread_attr_t *attr, int policy)
477{
478 if (policy != SCHED_OTHER && policy != SCHED_FIFO && policy != SCHED_RR)
479 return EINVAL;
480 attr->__schedpolicy = policy;
481 return 0;
482}
483
484int pthread_attr_getschedpolicy(const pthread_attr_t *attr, int *policy)
485{
486 *policy = attr->__schedpolicy;
487 return 0;
488}
489
490
sewardj111b14c2002-10-20 16:22:57 +0000491/* This is completely bogus. We reject all attempts to change it from
492 VKI_BYTES_PER_PAGE. I don't have a clue what it's for so it seems
493 safest to be paranoid. */
sewardj11f0bb42003-04-26 20:11:15 +0000494WEAK
sewardj111b14c2002-10-20 16:22:57 +0000495int pthread_attr_setguardsize(pthread_attr_t *attr, size_t guardsize)
496{
497 static int moans = N_MOANS;
498
499 if (guardsize == VKI_BYTES_PER_PAGE)
500 return 0;
501
502 if (moans-- > 0)
503 ignored("pthread_attr_setguardsize: ignoring guardsize != 4096");
504
505 return 0;
506}
507
508/* A straight copy of the LinuxThreads code. */
sewardj11f0bb42003-04-26 20:11:15 +0000509WEAK
sewardj111b14c2002-10-20 16:22:57 +0000510int pthread_attr_getguardsize(const pthread_attr_t *attr, size_t *guardsize)
511{
512 *guardsize = attr->__guardsize;
513 return 0;
514}
515
sewardjab2e1232002-12-26 12:16:11 +0000516/* Again, like LinuxThreads. */
517
518static int concurrency_current_level = 0;
519
sewardj11f0bb42003-04-26 20:11:15 +0000520WEAK
sewardjb34e4db2002-12-08 23:51:32 +0000521int pthread_setconcurrency(int new_level)
522{
523 if (new_level < 0)
524 return EINVAL;
sewardjab2e1232002-12-26 12:16:11 +0000525 else {
526 concurrency_current_level = new_level;
sewardjb34e4db2002-12-08 23:51:32 +0000527 return 0;
sewardjab2e1232002-12-26 12:16:11 +0000528 }
sewardjb34e4db2002-12-08 23:51:32 +0000529}
530
sewardj11f0bb42003-04-26 20:11:15 +0000531WEAK
sewardjab2e1232002-12-26 12:16:11 +0000532int pthread_getconcurrency(void)
533{
534 return concurrency_current_level;
535}
536
537
sewardj111b14c2002-10-20 16:22:57 +0000538
sewardj20917d82002-05-28 01:36:45 +0000539/* ---------------------------------------------------
540 Helper functions for running a thread
541 and for clearing up afterwards.
542 ------------------------------------------------ */
543
544/* All exiting threads eventually pass through here, bearing the
545 return value, or PTHREAD_CANCELED, in ret_val. */
546static
547__attribute__((noreturn))
548void thread_exit_wrapper ( void* ret_val )
549{
sewardj870497a2002-05-29 01:06:47 +0000550 int detached, res;
551 CleanupEntry cu;
552 pthread_key_t key;
sewardj00a66b12002-10-12 16:42:35 +0000553 void** specifics_ptr;
sewardj870497a2002-05-29 01:06:47 +0000554
sewardj20917d82002-05-28 01:36:45 +0000555 /* Run this thread's cleanup handlers. */
sewardj8ad94e12002-05-29 00:10:20 +0000556 while (1) {
557 VALGRIND_MAGIC_SEQUENCE(res, (-1) /* default */,
558 VG_USERREQ__CLEANUP_POP,
559 &cu, 0, 0, 0);
560 if (res == -1) break; /* stack empty */
sewardj2d94c112002-06-03 01:25:54 +0000561 my_assert(res == 0);
sewardj8ad94e12002-05-29 00:10:20 +0000562 if (0) printf("running exit cleanup handler");
563 cu.fn ( cu.arg );
564 }
565
sewardj870497a2002-05-29 01:06:47 +0000566 /* Run this thread's key finalizers. Really this should be run
567 PTHREAD_DESTRUCTOR_ITERATIONS times. */
568 for (key = 0; key < VG_N_THREAD_KEYS; key++) {
569 VALGRIND_MAGIC_SEQUENCE(res, (-2) /* default */,
570 VG_USERREQ__GET_KEY_D_AND_S,
571 key, &cu, 0, 0 );
572 if (res == 0) {
573 /* valid key */
574 if (cu.fn && cu.arg)
575 cu.fn /* destructor for key */
576 ( cu.arg /* specific for key for this thread */ );
577 continue;
578 }
sewardj2d94c112002-06-03 01:25:54 +0000579 my_assert(res == -1);
sewardj870497a2002-05-29 01:06:47 +0000580 }
sewardj20917d82002-05-28 01:36:45 +0000581
sewardj00a66b12002-10-12 16:42:35 +0000582 /* Free up my specifics space, if any. */
583 VALGRIND_MAGIC_SEQUENCE(specifics_ptr, 3 /* default */,
584 VG_USERREQ__PTHREAD_GETSPECIFIC_PTR,
585 pthread_self(), 0, 0, 0);
586 my_assert(specifics_ptr != (void**)3);
587 my_assert(specifics_ptr != (void**)1); /* 1 means invalid thread */
588 if (specifics_ptr != NULL)
589 my_free(specifics_ptr);
590
sewardj20917d82002-05-28 01:36:45 +0000591 /* Decide on my final disposition. */
592 VALGRIND_MAGIC_SEQUENCE(detached, (-1) /* default */,
593 VG_USERREQ__SET_OR_GET_DETACH,
sewardj7989d0c2002-05-28 11:00:01 +0000594 2 /* get */, pthread_self(), 0, 0);
sewardj2d94c112002-06-03 01:25:54 +0000595 my_assert(detached == 0 || detached == 1);
sewardj20917d82002-05-28 01:36:45 +0000596
597 if (detached) {
598 /* Detached; I just quit right now. */
599 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
600 VG_USERREQ__QUIT, 0, 0, 0, 0);
601 } else {
602 /* Not detached; so I wait for a joiner. */
603 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
604 VG_USERREQ__WAIT_JOINER, ret_val, 0, 0, 0);
605 }
606 /* NOTREACHED */
607 barf("thread_exit_wrapper: still alive?!");
608}
609
610
611/* This function is a wrapper function for running a thread. It runs
612 the root function specified in pthread_create, and then, should the
613 root function return a value, it arranges to run the thread's
614 cleanup handlers and exit correctly. */
615
sewardj728a5272002-06-20 10:25:37 +0000616/* Struct used to convey info from pthread_create to thread_wrapper.
617 Must be careful not to pass to the child thread any pointers to
618 objects which might be on the parent's stack. */
sewardj20917d82002-05-28 01:36:45 +0000619typedef
620 struct {
sewardj728a5272002-06-20 10:25:37 +0000621 int attr__detachstate;
sewardj20917d82002-05-28 01:36:45 +0000622 void* (*root_fn) ( void* );
623 void* arg;
624 }
625 NewThreadInfo;
626
627
628/* This is passed to the VG_USERREQ__APPLY_IN_NEW_THREAD and so must
629 not return. Note that this runs in the new thread, not the
630 parent. */
631static
632__attribute__((noreturn))
633void thread_wrapper ( NewThreadInfo* info )
634{
sewardj728a5272002-06-20 10:25:37 +0000635 int attr__detachstate;
sewardj20917d82002-05-28 01:36:45 +0000636 void* (*root_fn) ( void* );
637 void* arg;
638 void* ret_val;
639
sewardj728a5272002-06-20 10:25:37 +0000640 attr__detachstate = info->attr__detachstate;
641 root_fn = info->root_fn;
642 arg = info->arg;
sewardj20917d82002-05-28 01:36:45 +0000643
sewardj20917d82002-05-28 01:36:45 +0000644 /* Free up the arg block that pthread_create malloced. */
sewardj00a66b12002-10-12 16:42:35 +0000645 my_free(info);
sewardj20917d82002-05-28 01:36:45 +0000646
sewardj7989d0c2002-05-28 11:00:01 +0000647 /* Minimally observe the attributes supplied. */
sewardj728a5272002-06-20 10:25:37 +0000648 if (attr__detachstate != PTHREAD_CREATE_DETACHED
649 && attr__detachstate != PTHREAD_CREATE_JOINABLE)
650 pthread_error("thread_wrapper: invalid attr->__detachstate");
651 if (attr__detachstate == PTHREAD_CREATE_DETACHED)
652 pthread_detach(pthread_self());
sewardj7989d0c2002-05-28 11:00:01 +0000653
sewardj00a66b12002-10-12 16:42:35 +0000654# ifdef GLIBC_2_3
655 /* Set this thread's locale to the global (default) locale. A hack
656 in support of glibc-2.3. This does the biz for the all new
657 threads; the root thread is done with a horrible hack in
658 init_libc_tsd_keys() below.
659 */
660 __uselocale(LC_GLOBAL_LOCALE);
661# endif
662
sewardj20917d82002-05-28 01:36:45 +0000663 /* The root function might not return. But if it does we simply
664 move along to thread_exit_wrapper. All other ways out for the
665 thread (cancellation, or calling pthread_exit) lead there
666 too. */
667 ret_val = root_fn(arg);
668 thread_exit_wrapper(ret_val);
669 /* NOTREACHED */
670}
671
672
sewardjf8f819e2002-04-17 23:21:37 +0000673/* ---------------------------------------------------
674 THREADs
675 ------------------------------------------------ */
676
sewardj11f0bb42003-04-26 20:11:15 +0000677WEAK
sewardjff42d1d2002-05-22 13:17:31 +0000678int pthread_yield ( void )
679{
680 int res;
681 ensure_valgrind("pthread_yield");
682 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
683 VG_USERREQ__PTHREAD_YIELD, 0, 0, 0, 0);
684 return 0;
685}
686
687
sewardj6072c362002-04-19 14:40:57 +0000688int pthread_equal(pthread_t thread1, pthread_t thread2)
689{
690 return thread1 == thread2 ? 1 : 0;
691}
692
693
sewardj20917d82002-05-28 01:36:45 +0000694/* Bundle up the args into a malloc'd block and create a new thread
695 consisting of thread_wrapper() applied to said malloc'd block. */
sewardje663cb92002-04-12 10:26:32 +0000696int
sewardj1462c8b2002-07-24 09:41:52 +0000697pthread_create (pthread_t *__restrict __thredd,
sewardje663cb92002-04-12 10:26:32 +0000698 __const pthread_attr_t *__restrict __attr,
699 void *(*__start_routine) (void *),
700 void *__restrict __arg)
701{
sewardj20917d82002-05-28 01:36:45 +0000702 int tid_child;
703 NewThreadInfo* info;
sewardje663cb92002-04-12 10:26:32 +0000704
sewardj20917d82002-05-28 01:36:45 +0000705 ensure_valgrind("pthread_create");
706
sewardj00a66b12002-10-12 16:42:35 +0000707 /* make sure the tsd keys, and hence locale info, are initialised
708 before we get into complications making new threads. */
709 init_libc_tsd_keys();
710
sewardj20917d82002-05-28 01:36:45 +0000711 /* Allocate space for the arg block. thread_wrapper will free
712 it. */
sewardj00a66b12002-10-12 16:42:35 +0000713 info = my_malloc(sizeof(NewThreadInfo));
sewardj2d94c112002-06-03 01:25:54 +0000714 my_assert(info != NULL);
sewardj20917d82002-05-28 01:36:45 +0000715
sewardj728a5272002-06-20 10:25:37 +0000716 if (__attr)
717 info->attr__detachstate = __attr->__detachstate;
718 else
719 info->attr__detachstate = PTHREAD_CREATE_JOINABLE;
720
sewardj20917d82002-05-28 01:36:45 +0000721 info->root_fn = __start_routine;
722 info->arg = __arg;
723 VALGRIND_MAGIC_SEQUENCE(tid_child, VG_INVALID_THREADID /* default */,
724 VG_USERREQ__APPLY_IN_NEW_THREAD,
725 &thread_wrapper, info, 0, 0);
sewardj2d94c112002-06-03 01:25:54 +0000726 my_assert(tid_child != VG_INVALID_THREADID);
sewardj20917d82002-05-28 01:36:45 +0000727
sewardj1462c8b2002-07-24 09:41:52 +0000728 if (__thredd)
729 *__thredd = tid_child;
sewardj20917d82002-05-28 01:36:45 +0000730 return 0; /* success */
731}
sewardje663cb92002-04-12 10:26:32 +0000732
733
734int
735pthread_join (pthread_t __th, void **__thread_return)
736{
737 int res;
738 ensure_valgrind("pthread_join");
739 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
740 VG_USERREQ__PTHREAD_JOIN,
741 __th, __thread_return, 0, 0);
742 return res;
743}
744
745
sewardj3b5d8862002-04-20 13:53:23 +0000746void pthread_exit(void *retval)
747{
sewardj3b5d8862002-04-20 13:53:23 +0000748 ensure_valgrind("pthread_exit");
sewardj20917d82002-05-28 01:36:45 +0000749 /* Simple! */
750 thread_exit_wrapper(retval);
sewardj3b5d8862002-04-20 13:53:23 +0000751}
752
sewardje663cb92002-04-12 10:26:32 +0000753
sewardj853f55d2002-04-26 00:27:53 +0000754int pthread_detach(pthread_t th)
755{
sewardj20917d82002-05-28 01:36:45 +0000756 int res;
757 ensure_valgrind("pthread_detach");
sewardj7989d0c2002-05-28 11:00:01 +0000758 /* First we enquire as to the current detach state. */
759 VALGRIND_MAGIC_SEQUENCE(res, (-2) /* default */,
sewardj20917d82002-05-28 01:36:45 +0000760 VG_USERREQ__SET_OR_GET_DETACH,
sewardj7989d0c2002-05-28 11:00:01 +0000761 2 /* get */, th, 0, 0);
sewardj4dced352002-06-04 22:54:20 +0000762 if (res == -1) {
763 /* not found */
764 pthread_error("pthread_detach: "
765 "invalid target thread");
sewardj7989d0c2002-05-28 11:00:01 +0000766 return ESRCH;
sewardj4dced352002-06-04 22:54:20 +0000767 }
768 if (res == 1) {
769 /* already detached */
770 pthread_error("pthread_detach: "
771 "target thread is already detached");
sewardj7989d0c2002-05-28 11:00:01 +0000772 return EINVAL;
sewardj4dced352002-06-04 22:54:20 +0000773 }
sewardj7989d0c2002-05-28 11:00:01 +0000774 if (res == 0) {
775 VALGRIND_MAGIC_SEQUENCE(res, (-2) /* default */,
776 VG_USERREQ__SET_OR_GET_DETACH,
777 1 /* set */, th, 0, 0);
sewardj2d94c112002-06-03 01:25:54 +0000778 my_assert(res == 0);
sewardj7989d0c2002-05-28 11:00:01 +0000779 return 0;
780 }
781 barf("pthread_detach");
sewardj853f55d2002-04-26 00:27:53 +0000782}
783
784
sewardjf8f819e2002-04-17 23:21:37 +0000785/* ---------------------------------------------------
sewardj8ad94e12002-05-29 00:10:20 +0000786 CLEANUP STACKS
787 ------------------------------------------------ */
788
789void _pthread_cleanup_push (struct _pthread_cleanup_buffer *__buffer,
790 void (*__routine) (void *),
791 void *__arg)
792{
793 int res;
794 CleanupEntry cu;
795 ensure_valgrind("_pthread_cleanup_push");
796 cu.fn = __routine;
797 cu.arg = __arg;
798 VALGRIND_MAGIC_SEQUENCE(res, (-1) /* default */,
799 VG_USERREQ__CLEANUP_PUSH,
800 &cu, 0, 0, 0);
sewardj2d94c112002-06-03 01:25:54 +0000801 my_assert(res == 0);
sewardj8ad94e12002-05-29 00:10:20 +0000802}
803
804
805void _pthread_cleanup_push_defer (struct _pthread_cleanup_buffer *__buffer,
806 void (*__routine) (void *),
807 void *__arg)
808{
809 /* As _pthread_cleanup_push, but first save the thread's original
810 cancellation type in __buffer and set it to Deferred. */
811 int orig_ctype;
812 ensure_valgrind("_pthread_cleanup_push_defer");
813 /* Set to Deferred, and put the old cancellation type in res. */
sewardj2d94c112002-06-03 01:25:54 +0000814 my_assert(-1 != PTHREAD_CANCEL_DEFERRED);
815 my_assert(-1 != PTHREAD_CANCEL_ASYNCHRONOUS);
816 my_assert(sizeof(struct _pthread_cleanup_buffer) >= sizeof(int));
sewardj8ad94e12002-05-29 00:10:20 +0000817 VALGRIND_MAGIC_SEQUENCE(orig_ctype, (-1) /* default */,
818 VG_USERREQ__SET_CANCELTYPE,
819 PTHREAD_CANCEL_DEFERRED, 0, 0, 0);
sewardj2d94c112002-06-03 01:25:54 +0000820 my_assert(orig_ctype != -1);
sewardj8ad94e12002-05-29 00:10:20 +0000821 *((int*)(__buffer)) = orig_ctype;
822 /* Now push the cleanup. */
823 _pthread_cleanup_push(NULL, __routine, __arg);
824}
825
826
827void _pthread_cleanup_pop (struct _pthread_cleanup_buffer *__buffer,
828 int __execute)
829{
830 int res;
831 CleanupEntry cu;
832 ensure_valgrind("_pthread_cleanup_push");
833 cu.fn = cu.arg = NULL; /* paranoia */
834 VALGRIND_MAGIC_SEQUENCE(res, (-1) /* default */,
835 VG_USERREQ__CLEANUP_POP,
836 &cu, 0, 0, 0);
837 if (res == 0) {
838 /* pop succeeded */
839 if (__execute) {
840 cu.fn ( cu.arg );
841 }
842 return;
843 }
844 if (res == -1) {
845 /* stack underflow */
846 return;
847 }
848 barf("_pthread_cleanup_pop");
849}
850
851
852void _pthread_cleanup_pop_restore (struct _pthread_cleanup_buffer *__buffer,
853 int __execute)
854{
855 int orig_ctype, fake_ctype;
856 /* As _pthread_cleanup_pop, but after popping/running the handler,
857 restore the thread's original cancellation type from the first
858 word of __buffer. */
859 _pthread_cleanup_pop(NULL, __execute);
860 orig_ctype = *((int*)(__buffer));
sewardj2d94c112002-06-03 01:25:54 +0000861 my_assert(orig_ctype == PTHREAD_CANCEL_DEFERRED
sewardj8ad94e12002-05-29 00:10:20 +0000862 || orig_ctype == PTHREAD_CANCEL_ASYNCHRONOUS);
sewardj2d94c112002-06-03 01:25:54 +0000863 my_assert(-1 != PTHREAD_CANCEL_DEFERRED);
864 my_assert(-1 != PTHREAD_CANCEL_ASYNCHRONOUS);
865 my_assert(sizeof(struct _pthread_cleanup_buffer) >= sizeof(int));
sewardj8ad94e12002-05-29 00:10:20 +0000866 VALGRIND_MAGIC_SEQUENCE(fake_ctype, (-1) /* default */,
867 VG_USERREQ__SET_CANCELTYPE,
868 orig_ctype, 0, 0, 0);
sewardj2d94c112002-06-03 01:25:54 +0000869 my_assert(fake_ctype == PTHREAD_CANCEL_DEFERRED);
sewardj8ad94e12002-05-29 00:10:20 +0000870}
871
872
873/* ---------------------------------------------------
sewardjf8f819e2002-04-17 23:21:37 +0000874 MUTEX ATTRIBUTES
875 ------------------------------------------------ */
876
sewardj5905fae2002-04-26 13:25:00 +0000877int __pthread_mutexattr_init(pthread_mutexattr_t *attr)
sewardje663cb92002-04-12 10:26:32 +0000878{
sewardjf8f819e2002-04-17 23:21:37 +0000879 attr->__mutexkind = PTHREAD_MUTEX_ERRORCHECK_NP;
sewardj8937c812002-04-12 20:12:20 +0000880 return 0;
sewardje663cb92002-04-12 10:26:32 +0000881}
882
sewardj5905fae2002-04-26 13:25:00 +0000883int __pthread_mutexattr_settype(pthread_mutexattr_t *attr, int type)
sewardjf8f819e2002-04-17 23:21:37 +0000884{
885 switch (type) {
sewardj3b13f0e2002-04-25 20:17:29 +0000886# ifndef GLIBC_2_1
sewardjf8f819e2002-04-17 23:21:37 +0000887 case PTHREAD_MUTEX_TIMED_NP:
sewardj2a1dcce2002-04-22 12:45:25 +0000888 case PTHREAD_MUTEX_ADAPTIVE_NP:
sewardj3b13f0e2002-04-25 20:17:29 +0000889# endif
sewardja1679dd2002-05-10 22:31:40 +0000890# ifdef GLIBC_2_1
sewardj68b2dd92002-05-10 21:03:56 +0000891 case PTHREAD_MUTEX_FAST_NP:
sewardja1679dd2002-05-10 22:31:40 +0000892# endif
sewardjf8f819e2002-04-17 23:21:37 +0000893 case PTHREAD_MUTEX_RECURSIVE_NP:
894 case PTHREAD_MUTEX_ERRORCHECK_NP:
sewardjf8f819e2002-04-17 23:21:37 +0000895 attr->__mutexkind = type;
896 return 0;
897 default:
sewardj4dced352002-06-04 22:54:20 +0000898 pthread_error("pthread_mutexattr_settype: "
899 "invalid type");
sewardjf8f819e2002-04-17 23:21:37 +0000900 return EINVAL;
901 }
902}
903
sewardj5905fae2002-04-26 13:25:00 +0000904int __pthread_mutexattr_destroy(pthread_mutexattr_t *attr)
sewardjf8f819e2002-04-17 23:21:37 +0000905{
906 return 0;
907}
908
909
910/* ---------------------------------------------------
911 MUTEXes
912 ------------------------------------------------ */
913
sewardj5905fae2002-04-26 13:25:00 +0000914int __pthread_mutex_init(pthread_mutex_t *mutex,
915 const pthread_mutexattr_t *mutexattr)
sewardje663cb92002-04-12 10:26:32 +0000916{
sewardj604ec3c2002-04-18 22:38:41 +0000917 mutex->__m_count = 0;
918 mutex->__m_owner = (_pthread_descr)VG_INVALID_THREADID;
919 mutex->__m_kind = PTHREAD_MUTEX_ERRORCHECK_NP;
920 if (mutexattr)
921 mutex->__m_kind = mutexattr->__mutexkind;
922 return 0;
sewardje663cb92002-04-12 10:26:32 +0000923}
924
sewardj439d45e2002-05-03 20:43:10 +0000925
sewardj5905fae2002-04-26 13:25:00 +0000926int __pthread_mutex_lock(pthread_mutex_t *mutex)
sewardje663cb92002-04-12 10:26:32 +0000927{
928 int res;
sewardjd8acdf22002-11-13 21:57:52 +0000929
sewardj439d45e2002-05-03 20:43:10 +0000930 if (RUNNING_ON_VALGRIND) {
sewardje663cb92002-04-12 10:26:32 +0000931 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
932 VG_USERREQ__PTHREAD_MUTEX_LOCK,
933 mutex, 0, 0, 0);
934 return res;
sewardj439d45e2002-05-03 20:43:10 +0000935 } else {
sewardjd8acdf22002-11-13 21:57:52 +0000936 /* Play at locking */
937 if (0)
938 kludged("prehistoric lock");
939 mutex->__m_owner = (_pthread_descr)1;
940 mutex->__m_count = 1;
941 mutex->__m_kind |= VG_PTHREAD_PREHISTORY;
sewardj439d45e2002-05-03 20:43:10 +0000942 return 0; /* success */
sewardje663cb92002-04-12 10:26:32 +0000943 }
944}
945
sewardj439d45e2002-05-03 20:43:10 +0000946
sewardj5905fae2002-04-26 13:25:00 +0000947int __pthread_mutex_trylock(pthread_mutex_t *mutex)
sewardj30671ff2002-04-21 00:13:57 +0000948{
949 int res;
sewardjd8acdf22002-11-13 21:57:52 +0000950
sewardj439d45e2002-05-03 20:43:10 +0000951 if (RUNNING_ON_VALGRIND) {
sewardj30671ff2002-04-21 00:13:57 +0000952 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
953 VG_USERREQ__PTHREAD_MUTEX_TRYLOCK,
954 mutex, 0, 0, 0);
955 return res;
sewardj439d45e2002-05-03 20:43:10 +0000956 } else {
sewardjd8acdf22002-11-13 21:57:52 +0000957 /* Play at locking */
958 if (0)
959 kludged("prehistoric trylock");
960 mutex->__m_owner = (_pthread_descr)1;
961 mutex->__m_count = 1;
962 mutex->__m_kind |= VG_PTHREAD_PREHISTORY;
963 return 0; /* success */
sewardj30671ff2002-04-21 00:13:57 +0000964 }
965}
966
sewardj439d45e2002-05-03 20:43:10 +0000967
sewardj5905fae2002-04-26 13:25:00 +0000968int __pthread_mutex_unlock(pthread_mutex_t *mutex)
sewardje663cb92002-04-12 10:26:32 +0000969{
970 int res;
sewardjd8acdf22002-11-13 21:57:52 +0000971
sewardj439d45e2002-05-03 20:43:10 +0000972 if (RUNNING_ON_VALGRIND) {
sewardje663cb92002-04-12 10:26:32 +0000973 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
974 VG_USERREQ__PTHREAD_MUTEX_UNLOCK,
975 mutex, 0, 0, 0);
976 return res;
sewardj439d45e2002-05-03 20:43:10 +0000977 } else {
sewardjd8acdf22002-11-13 21:57:52 +0000978 /* Play at locking */
979 if (0)
980 kludged("prehistoric unlock");
981 mutex->__m_owner = 0;
982 mutex->__m_count = 0;
983 mutex->__m_kind &= ~VG_PTHREAD_PREHISTORY;
984 return 0; /* success */
sewardje663cb92002-04-12 10:26:32 +0000985 }
986}
987
sewardj439d45e2002-05-03 20:43:10 +0000988
sewardj5905fae2002-04-26 13:25:00 +0000989int __pthread_mutex_destroy(pthread_mutex_t *mutex)
sewardje663cb92002-04-12 10:26:32 +0000990{
sewardj604ec3c2002-04-18 22:38:41 +0000991 /* Valgrind doesn't hold any resources on behalf of the mutex, so no
992 need to involve it. */
sewardj4dced352002-06-04 22:54:20 +0000993 if (mutex->__m_count > 0) {
sewardjd8acdf22002-11-13 21:57:52 +0000994 /* Oh, the horror. glibc's internal use of pthreads "knows"
995 that destroying a lock does an implicit unlock. Make it
996 explicit. */
997 __pthread_mutex_unlock(mutex);
998 pthread_error("pthread_mutex_destroy: "
999 "mutex is still in use");
1000 return EBUSY;
sewardj4dced352002-06-04 22:54:20 +00001001 }
1002 mutex->__m_count = 0;
1003 mutex->__m_owner = (_pthread_descr)VG_INVALID_THREADID;
1004 mutex->__m_kind = PTHREAD_MUTEX_ERRORCHECK_NP;
1005 return 0;
sewardje663cb92002-04-12 10:26:32 +00001006}
1007
1008
sewardjf8f819e2002-04-17 23:21:37 +00001009/* ---------------------------------------------------
sewardj6072c362002-04-19 14:40:57 +00001010 CONDITION VARIABLES
1011 ------------------------------------------------ */
1012
1013/* LinuxThreads supports no attributes for conditions. Hence ... */
1014
1015int pthread_condattr_init(pthread_condattr_t *attr)
1016{
1017 return 0;
1018}
1019
sewardj0738a592002-04-20 13:59:33 +00001020int pthread_condattr_destroy(pthread_condattr_t *attr)
1021{
1022 return 0;
1023}
sewardj6072c362002-04-19 14:40:57 +00001024
1025int pthread_cond_init( pthread_cond_t *cond,
1026 const pthread_condattr_t *cond_attr)
1027{
1028 cond->__c_waiting = (_pthread_descr)VG_INVALID_THREADID;
1029 return 0;
1030}
1031
sewardjf854f472002-04-21 12:19:41 +00001032int pthread_cond_destroy(pthread_cond_t *cond)
1033{
1034 /* should check that no threads are waiting on this CV */
sewardj436e0582002-04-26 14:31:40 +00001035 static int moans = N_MOANS;
1036 if (moans-- > 0)
1037 kludged("pthread_cond_destroy");
sewardjf854f472002-04-21 12:19:41 +00001038 return 0;
1039}
sewardj6072c362002-04-19 14:40:57 +00001040
1041/* ---------------------------------------------------
1042 SCHEDULING
1043 ------------------------------------------------ */
1044
1045/* This is completely bogus. */
1046int pthread_getschedparam(pthread_t target_thread,
1047 int *policy,
1048 struct sched_param *param)
1049{
sewardj436e0582002-04-26 14:31:40 +00001050 static int moans = N_MOANS;
1051 if (moans-- > 0)
1052 kludged("pthread_getschedparam");
sewardj6072c362002-04-19 14:40:57 +00001053 if (policy) *policy = SCHED_OTHER;
sewardj3e909ce2002-06-03 13:27:15 +00001054# ifdef HAVE_SCHED_PRIORITY
sewardj2a1dcce2002-04-22 12:45:25 +00001055 if (param) param->sched_priority = 0; /* who knows */
1056# else
sewardj6072c362002-04-19 14:40:57 +00001057 if (param) param->__sched_priority = 0; /* who knows */
sewardj2a1dcce2002-04-22 12:45:25 +00001058# endif
sewardj6072c362002-04-19 14:40:57 +00001059 return 0;
1060}
1061
1062int pthread_setschedparam(pthread_t target_thread,
1063 int policy,
1064 const struct sched_param *param)
1065{
sewardj436e0582002-04-26 14:31:40 +00001066 static int moans = N_MOANS;
1067 if (moans-- > 0)
1068 ignored("pthread_setschedparam");
sewardj6072c362002-04-19 14:40:57 +00001069 return 0;
1070}
1071
sewardj3b5d8862002-04-20 13:53:23 +00001072int pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex)
1073{
1074 int res;
1075 ensure_valgrind("pthread_cond_wait");
1076 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
1077 VG_USERREQ__PTHREAD_COND_WAIT,
1078 cond, mutex, 0, 0);
1079 return res;
1080}
1081
sewardj5f07b662002-04-23 16:52:51 +00001082int pthread_cond_timedwait ( pthread_cond_t *cond,
1083 pthread_mutex_t *mutex,
1084 const struct timespec *abstime )
1085{
1086 int res;
1087 unsigned int ms_now, ms_end;
1088 struct timeval timeval_now;
1089 unsigned long long int ull_ms_now_after_1970;
1090 unsigned long long int ull_ms_end_after_1970;
1091
1092 ensure_valgrind("pthread_cond_timedwait");
1093 VALGRIND_MAGIC_SEQUENCE(ms_now, 0xFFFFFFFF /* default */,
1094 VG_USERREQ__READ_MILLISECOND_TIMER,
1095 0, 0, 0, 0);
sewardj2d94c112002-06-03 01:25:54 +00001096 my_assert(ms_now != 0xFFFFFFFF);
sewardj5f07b662002-04-23 16:52:51 +00001097 res = gettimeofday(&timeval_now, NULL);
sewardj2d94c112002-06-03 01:25:54 +00001098 my_assert(res == 0);
sewardj5f07b662002-04-23 16:52:51 +00001099
1100 ull_ms_now_after_1970
1101 = 1000ULL * ((unsigned long long int)(timeval_now.tv_sec))
1102 + ((unsigned long long int)(timeval_now.tv_usec / 1000000));
1103 ull_ms_end_after_1970
1104 = 1000ULL * ((unsigned long long int)(abstime->tv_sec))
1105 + ((unsigned long long int)(abstime->tv_nsec / 1000000));
sewardjd8e919e2002-05-29 20:13:53 +00001106 if (ull_ms_end_after_1970 < ull_ms_now_after_1970)
1107 ull_ms_end_after_1970 = ull_ms_now_after_1970;
sewardj5f07b662002-04-23 16:52:51 +00001108 ms_end
1109 = ms_now + (unsigned int)(ull_ms_end_after_1970 - ull_ms_now_after_1970);
1110 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
1111 VG_USERREQ__PTHREAD_COND_TIMEDWAIT,
1112 cond, mutex, ms_end, 0);
1113 return res;
1114}
1115
1116
sewardj3b5d8862002-04-20 13:53:23 +00001117int pthread_cond_signal(pthread_cond_t *cond)
1118{
1119 int res;
1120 ensure_valgrind("pthread_cond_signal");
1121 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
1122 VG_USERREQ__PTHREAD_COND_SIGNAL,
1123 cond, 0, 0, 0);
1124 return res;
1125}
1126
1127int pthread_cond_broadcast(pthread_cond_t *cond)
1128{
1129 int res;
1130 ensure_valgrind("pthread_cond_broadcast");
1131 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
1132 VG_USERREQ__PTHREAD_COND_BROADCAST,
1133 cond, 0, 0, 0);
1134 return res;
1135}
1136
sewardj6072c362002-04-19 14:40:57 +00001137
1138/* ---------------------------------------------------
sewardjf8f819e2002-04-17 23:21:37 +00001139 CANCELLATION
1140 ------------------------------------------------ */
1141
sewardj853f55d2002-04-26 00:27:53 +00001142int pthread_setcancelstate(int state, int *oldstate)
1143{
sewardj20917d82002-05-28 01:36:45 +00001144 int res;
1145 ensure_valgrind("pthread_setcancelstate");
1146 if (state != PTHREAD_CANCEL_ENABLE
sewardj4dced352002-06-04 22:54:20 +00001147 && state != PTHREAD_CANCEL_DISABLE) {
1148 pthread_error("pthread_setcancelstate: "
1149 "invalid state");
sewardj20917d82002-05-28 01:36:45 +00001150 return EINVAL;
sewardj4dced352002-06-04 22:54:20 +00001151 }
sewardj2d94c112002-06-03 01:25:54 +00001152 my_assert(-1 != PTHREAD_CANCEL_ENABLE);
1153 my_assert(-1 != PTHREAD_CANCEL_DISABLE);
sewardj20917d82002-05-28 01:36:45 +00001154 VALGRIND_MAGIC_SEQUENCE(res, (-1) /* default */,
1155 VG_USERREQ__SET_CANCELSTATE,
1156 state, 0, 0, 0);
sewardj2d94c112002-06-03 01:25:54 +00001157 my_assert(res != -1);
sewardj20917d82002-05-28 01:36:45 +00001158 if (oldstate)
1159 *oldstate = res;
sewardj853f55d2002-04-26 00:27:53 +00001160 return 0;
1161}
1162
sewardje663cb92002-04-12 10:26:32 +00001163int pthread_setcanceltype(int type, int *oldtype)
1164{
sewardj20917d82002-05-28 01:36:45 +00001165 int res;
1166 ensure_valgrind("pthread_setcanceltype");
1167 if (type != PTHREAD_CANCEL_DEFERRED
sewardj4dced352002-06-04 22:54:20 +00001168 && type != PTHREAD_CANCEL_ASYNCHRONOUS) {
1169 pthread_error("pthread_setcanceltype: "
1170 "invalid type");
sewardj20917d82002-05-28 01:36:45 +00001171 return EINVAL;
sewardj4dced352002-06-04 22:54:20 +00001172 }
sewardj2d94c112002-06-03 01:25:54 +00001173 my_assert(-1 != PTHREAD_CANCEL_DEFERRED);
1174 my_assert(-1 != PTHREAD_CANCEL_ASYNCHRONOUS);
sewardj20917d82002-05-28 01:36:45 +00001175 VALGRIND_MAGIC_SEQUENCE(res, (-1) /* default */,
1176 VG_USERREQ__SET_CANCELTYPE,
1177 type, 0, 0, 0);
sewardj2d94c112002-06-03 01:25:54 +00001178 my_assert(res != -1);
sewardj20917d82002-05-28 01:36:45 +00001179 if (oldtype)
1180 *oldtype = res;
sewardje663cb92002-04-12 10:26:32 +00001181 return 0;
1182}
1183
sewardje663cb92002-04-12 10:26:32 +00001184int pthread_cancel(pthread_t thread)
1185{
1186 int res;
1187 ensure_valgrind("pthread_cancel");
sewardj20917d82002-05-28 01:36:45 +00001188 VALGRIND_MAGIC_SEQUENCE(res, (-1) /* default */,
1189 VG_USERREQ__SET_CANCELPEND,
1190 thread, &thread_exit_wrapper, 0, 0);
sewardj2d94c112002-06-03 01:25:54 +00001191 my_assert(res != -1);
sewardje663cb92002-04-12 10:26:32 +00001192 return res;
1193}
1194
sewardjd140e442002-05-29 01:21:19 +00001195static __inline__
1196void __my_pthread_testcancel(void)
sewardj853f55d2002-04-26 00:27:53 +00001197{
sewardj20917d82002-05-28 01:36:45 +00001198 int res;
njn25e49d8e72002-09-23 09:36:25 +00001199 ensure_valgrind("__my_pthread_testcancel");
sewardj20917d82002-05-28 01:36:45 +00001200 VALGRIND_MAGIC_SEQUENCE(res, (-1) /* default */,
1201 VG_USERREQ__TESTCANCEL,
1202 0, 0, 0, 0);
sewardj2d94c112002-06-03 01:25:54 +00001203 my_assert(res == 0);
sewardj853f55d2002-04-26 00:27:53 +00001204}
1205
sewardjd140e442002-05-29 01:21:19 +00001206void pthread_testcancel ( void )
1207{
1208 __my_pthread_testcancel();
1209}
1210
sewardj20917d82002-05-28 01:36:45 +00001211
sewardjef037c72002-05-30 00:40:03 +00001212/* Not really sure what this is for. I suspect for doing the POSIX
1213 requirements for fork() and exec(). We do this internally anyway
1214 whenever those syscalls are observed, so this could be superfluous,
1215 but hey ...
1216*/
sewardj853f55d2002-04-26 00:27:53 +00001217void __pthread_kill_other_threads_np ( void )
1218{
sewardjef037c72002-05-30 00:40:03 +00001219 int res;
1220 ensure_valgrind("__pthread_kill_other_threads_np");
1221 VALGRIND_MAGIC_SEQUENCE(res, (-1) /* default */,
1222 VG_USERREQ__NUKE_OTHER_THREADS,
1223 0, 0, 0, 0);
sewardj2d94c112002-06-03 01:25:54 +00001224 my_assert(res == 0);
sewardj853f55d2002-04-26 00:27:53 +00001225}
1226
sewardje663cb92002-04-12 10:26:32 +00001227
sewardjf8f819e2002-04-17 23:21:37 +00001228/* ---------------------------------------------------
sewardjb48e5002002-05-13 00:16:03 +00001229 SIGNALS
1230 ------------------------------------------------ */
1231
1232#include <signal.h>
1233
1234int pthread_sigmask(int how, const sigset_t *newmask,
1235 sigset_t *oldmask)
1236{
1237 int res;
1238
1239 /* A bit subtle, because the scheduler expects newmask and oldmask
1240 to be vki_sigset_t* rather than sigset_t*, and the two are
1241 different. Fortunately the first 64 bits of a sigset_t are
1242 exactly a vki_sigset_t, so we just pass the pointers through
1243 unmodified. Haaaack!
1244
1245 Also mash the how value so that the SIG_ constants from glibc
sewardj018f7622002-05-15 21:13:39 +00001246 constants to VKI_ constants, so that the former do not have to
1247 be included into vg_scheduler.c. */
sewardjb48e5002002-05-13 00:16:03 +00001248
1249 ensure_valgrind("pthread_sigmask");
1250
1251 switch (how) {
sewardj018f7622002-05-15 21:13:39 +00001252 case SIG_SETMASK: how = VKI_SIG_SETMASK; break;
1253 case SIG_BLOCK: how = VKI_SIG_BLOCK; break;
1254 case SIG_UNBLOCK: how = VKI_SIG_UNBLOCK; break;
sewardj4dced352002-06-04 22:54:20 +00001255 default: pthread_error("pthread_sigmask: invalid how");
1256 return EINVAL;
sewardjb48e5002002-05-13 00:16:03 +00001257 }
1258
1259 /* Crude check */
1260 if (newmask == NULL)
1261 return EFAULT;
1262
1263 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
1264 VG_USERREQ__PTHREAD_SIGMASK,
1265 how, newmask, oldmask, 0);
1266
1267 /* The scheduler tells us of any memory violations. */
1268 return res == 0 ? 0 : EFAULT;
1269}
1270
1271
1272int sigwait ( const sigset_t* set, int* sig )
1273{
1274 int res;
1275 ensure_valgrind("sigwait");
1276 /* As with pthread_sigmask we deliberately confuse sigset_t with
1277 vki_ksigset_t. */
1278 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
1279 VG_USERREQ__SIGWAIT,
1280 set, sig, 0, 0);
1281 return res;
1282}
1283
1284
sewardj018f7622002-05-15 21:13:39 +00001285int pthread_kill(pthread_t thread, int signo)
1286{
1287 int res;
1288 ensure_valgrind("pthread_kill");
1289 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
1290 VG_USERREQ__PTHREAD_KILL,
1291 thread, signo, 0, 0);
1292 return res;
1293}
1294
1295
sewardj3665ded2002-05-16 16:57:25 +00001296/* Copied verbatim from Linuxthreads */
1297/* Redefine raise() to send signal to calling thread only,
1298 as per POSIX 1003.1c */
1299int raise (int sig)
1300{
1301 int retcode = pthread_kill(pthread_self(), sig);
sewardj4dced352002-06-04 22:54:20 +00001302 if (retcode == 0) {
sewardj3665ded2002-05-16 16:57:25 +00001303 return 0;
sewardj4dced352002-06-04 22:54:20 +00001304 } else {
sewardj25418ae2003-05-09 23:40:34 +00001305 *(__errno_location()) = retcode;
sewardj3665ded2002-05-16 16:57:25 +00001306 return -1;
1307 }
1308}
1309
1310
sewardj9a2224b2002-06-19 10:17:40 +00001311int pause ( void )
1312{
1313 unsigned int n_orig, n_now;
1314 struct vki_timespec nanosleep_interval;
1315 ensure_valgrind("pause");
1316
1317 /* This is surely a cancellation point. */
1318 __my_pthread_testcancel();
1319
1320 VALGRIND_MAGIC_SEQUENCE(n_orig, 0xFFFFFFFF /* default */,
1321 VG_USERREQ__GET_N_SIGS_RETURNED,
1322 0, 0, 0, 0);
1323 my_assert(n_orig != 0xFFFFFFFF);
1324
1325 while (1) {
1326 VALGRIND_MAGIC_SEQUENCE(n_now, 0xFFFFFFFF /* default */,
1327 VG_USERREQ__GET_N_SIGS_RETURNED,
1328 0, 0, 0, 0);
1329 my_assert(n_now != 0xFFFFFFFF);
1330 my_assert(n_now >= n_orig);
1331 if (n_now != n_orig) break;
1332
1333 nanosleep_interval.tv_sec = 0;
njn25e49d8e72002-09-23 09:36:25 +00001334 nanosleep_interval.tv_nsec = 12 * 1000 * 1000; /* 12 milliseconds */
sewardj9a2224b2002-06-19 10:17:40 +00001335 /* It's critical here that valgrind's nanosleep implementation
1336 is nonblocking. */
1337 (void)my_do_syscall2(__NR_nanosleep,
1338 (int)(&nanosleep_interval), (int)NULL);
1339 }
1340
sewardj25418ae2003-05-09 23:40:34 +00001341 *(__errno_location()) = EINTR;
sewardj9a2224b2002-06-19 10:17:40 +00001342 return -1;
1343}
1344
1345
sewardjb48e5002002-05-13 00:16:03 +00001346/* ---------------------------------------------------
sewardjf8f819e2002-04-17 23:21:37 +00001347 THREAD-SPECIFICs
1348 ------------------------------------------------ */
sewardj5e5fa512002-04-14 13:13:05 +00001349
sewardj00a66b12002-10-12 16:42:35 +00001350static
1351int key_is_valid (pthread_key_t key)
1352{
1353 int res;
1354 VALGRIND_MAGIC_SEQUENCE(res, 2 /* default */,
1355 VG_USERREQ__PTHREAD_KEY_VALIDATE,
1356 key, 0, 0, 0);
1357 my_assert(res != 2);
1358 return res;
1359}
1360
1361
1362/* Returns NULL if thread is invalid. Otherwise, if the thread
1363 already has a specifics area, return that. Otherwise allocate it
1364 one. */
1365static
1366void** get_or_allocate_specifics_ptr ( pthread_t thread )
1367{
1368 int res, i;
1369 void** specifics_ptr;
1370 ensure_valgrind("get_or_allocate_specifics_ptr");
1371
1372 /* Returns zero if the thread has no specific_ptr. One if thread
1373 is invalid. Otherwise, the specific_ptr value. This is
1374 allocated with my_malloc and so is aligned and cannot be
1375 confused with 1 or 3. */
1376 VALGRIND_MAGIC_SEQUENCE(specifics_ptr, 3 /* default */,
1377 VG_USERREQ__PTHREAD_GETSPECIFIC_PTR,
1378 thread, 0, 0, 0);
1379 my_assert(specifics_ptr != (void**)3);
1380
1381 if (specifics_ptr == (void**)1)
1382 return NULL; /* invalid thread */
1383
1384 if (specifics_ptr != NULL)
1385 return specifics_ptr; /* already has a specifics ptr. */
1386
1387 /* None yet ... allocate a new one. Should never fail. */
1388 specifics_ptr = my_malloc( VG_N_THREAD_KEYS * sizeof(void*) );
1389 my_assert(specifics_ptr != NULL);
1390
1391 VALGRIND_MAGIC_SEQUENCE(res, -1 /* default */,
1392 VG_USERREQ__PTHREAD_SETSPECIFIC_PTR,
1393 specifics_ptr, 0, 0, 0);
1394 my_assert(res == 0);
1395
1396 /* POSIX sez: "Upon thread creation, the value NULL shall be
1397 associated with all defined keys in the new thread." This
1398 allocation is in effect a delayed allocation of the specific
1399 data for a thread, at its first-use. Hence we initialise it
1400 here. */
1401 for (i = 0; i < VG_N_THREAD_KEYS; i++) {
1402 specifics_ptr[i] = NULL;
1403 }
1404
1405 return specifics_ptr;
1406}
1407
1408
sewardj5905fae2002-04-26 13:25:00 +00001409int __pthread_key_create(pthread_key_t *key,
1410 void (*destr_function) (void *))
sewardj5e5fa512002-04-14 13:13:05 +00001411{
sewardj00a66b12002-10-12 16:42:35 +00001412 void** specifics_ptr;
1413 int res, i;
sewardj5f07b662002-04-23 16:52:51 +00001414 ensure_valgrind("pthread_key_create");
sewardj00a66b12002-10-12 16:42:35 +00001415
1416 /* This writes *key if successful. It should never fail. */
1417 VALGRIND_MAGIC_SEQUENCE(res, 1 /* default */,
sewardj5f07b662002-04-23 16:52:51 +00001418 VG_USERREQ__PTHREAD_KEY_CREATE,
1419 key, destr_function, 0, 0);
sewardj00a66b12002-10-12 16:42:35 +00001420 my_assert(res == 0);
1421
1422 /* POSIX sez: "Upon key creation, the value NULL shall be
1423 associated with the new key in all active threads." */
1424 for (i = 0; i < VG_N_THREADS; i++) {
1425 specifics_ptr = get_or_allocate_specifics_ptr(i);
1426 /* we get NULL if i is an invalid thread. */
1427 if (specifics_ptr != NULL)
1428 specifics_ptr[*key] = NULL;
1429 }
1430
sewardj5f07b662002-04-23 16:52:51 +00001431 return res;
sewardj5e5fa512002-04-14 13:13:05 +00001432}
1433
1434int pthread_key_delete(pthread_key_t key)
1435{
sewardj00a66b12002-10-12 16:42:35 +00001436 int res;
1437 ensure_valgrind("pthread_key_create");
1438 if (!key_is_valid(key))
1439 return EINVAL;
1440 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
1441 VG_USERREQ__PTHREAD_KEY_DELETE,
1442 key, 0, 0, 0);
1443 my_assert(res == 0);
sewardj5e5fa512002-04-14 13:13:05 +00001444 return 0;
1445}
1446
sewardj5905fae2002-04-26 13:25:00 +00001447int __pthread_setspecific(pthread_key_t key, const void *pointer)
sewardj5e5fa512002-04-14 13:13:05 +00001448{
sewardj00a66b12002-10-12 16:42:35 +00001449 void** specifics_ptr;
sewardj5f07b662002-04-23 16:52:51 +00001450 ensure_valgrind("pthread_setspecific");
sewardj00a66b12002-10-12 16:42:35 +00001451
1452 if (!key_is_valid(key))
1453 return EINVAL;
1454
1455 specifics_ptr = get_or_allocate_specifics_ptr(pthread_self());
1456 specifics_ptr[key] = (void*)pointer;
1457 return 0;
sewardj5e5fa512002-04-14 13:13:05 +00001458}
1459
sewardj5905fae2002-04-26 13:25:00 +00001460void * __pthread_getspecific(pthread_key_t key)
sewardj5e5fa512002-04-14 13:13:05 +00001461{
sewardj00a66b12002-10-12 16:42:35 +00001462 void** specifics_ptr;
sewardj5f07b662002-04-23 16:52:51 +00001463 ensure_valgrind("pthread_getspecific");
sewardj00a66b12002-10-12 16:42:35 +00001464
1465 if (!key_is_valid(key))
1466 return NULL;
1467
1468 specifics_ptr = get_or_allocate_specifics_ptr(pthread_self());
1469 return specifics_ptr[key];
1470}
1471
1472
sewardj9aa918d2002-10-20 16:25:55 +00001473#ifdef GLIBC_2_3
sewardj00a66b12002-10-12 16:42:35 +00001474static
1475void ** __pthread_getspecific_addr(pthread_key_t key)
1476{
1477 void** specifics_ptr;
1478 ensure_valgrind("pthread_getspecific_addr");
1479
1480 if (!key_is_valid(key))
1481 return NULL;
1482
1483 specifics_ptr = get_or_allocate_specifics_ptr(pthread_self());
1484 return &(specifics_ptr[key]);
sewardj5e5fa512002-04-14 13:13:05 +00001485}
sewardj9aa918d2002-10-20 16:25:55 +00001486#endif
sewardjf8f819e2002-04-17 23:21:37 +00001487
1488/* ---------------------------------------------------
sewardj89d3d852002-04-24 19:21:39 +00001489 ONCEry
1490 ------------------------------------------------ */
1491
1492static pthread_mutex_t once_masterlock = PTHREAD_MUTEX_INITIALIZER;
1493
1494
sewardj5905fae2002-04-26 13:25:00 +00001495int __pthread_once ( pthread_once_t *once_control,
1496 void (*init_routine) (void) )
sewardj89d3d852002-04-24 19:21:39 +00001497{
1498 int res;
1499 ensure_valgrind("pthread_once");
1500
sewardj68b2dd92002-05-10 21:03:56 +00001501 res = __pthread_mutex_lock(&once_masterlock);
sewardj89d3d852002-04-24 19:21:39 +00001502
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
sewardj25418ae2003-05-09 23:40:34 +00001592#undef errno
1593extern int errno;
sewardj3b13f0e2002-04-25 20:17:29 +00001594int* __errno_location ( void )
sewardjf8f819e2002-04-17 23:21:37 +00001595{
1596 int tid;
sewardj3b13f0e2002-04-25 20:17:29 +00001597 /* ensure_valgrind("__errno_location"); */
1598 VALGRIND_MAGIC_SEQUENCE(tid, 1 /* default */,
sewardjf8f819e2002-04-17 23:21:37 +00001599 VG_USERREQ__PTHREAD_GET_THREADID,
1600 0, 0, 0, 0);
sewardj3b13f0e2002-04-25 20:17:29 +00001601 /* 'cos I'm paranoid ... */
sewardj439d45e2002-05-03 20:43:10 +00001602 if (tid < 1 || tid >= VG_N_THREADS)
sewardj3b13f0e2002-04-25 20:17:29 +00001603 barf("__errno_location: invalid ThreadId");
sewardj25418ae2003-05-09 23:40:34 +00001604 if (tid == 1)
1605 return &errno;
sewardj3b13f0e2002-04-25 20:17:29 +00001606 return & thread_specific_errno[tid];
1607}
1608
sewardj25418ae2003-05-09 23:40:34 +00001609#undef h_errno
1610extern int h_errno;
sewardj3b13f0e2002-04-25 20:17:29 +00001611int* __h_errno_location ( void )
1612{
1613 int tid;
1614 /* ensure_valgrind("__h_errno_location"); */
1615 VALGRIND_MAGIC_SEQUENCE(tid, 1 /* default */,
1616 VG_USERREQ__PTHREAD_GET_THREADID,
1617 0, 0, 0, 0);
1618 /* 'cos I'm paranoid ... */
sewardj439d45e2002-05-03 20:43:10 +00001619 if (tid < 1 || tid >= VG_N_THREADS)
sewardj3b13f0e2002-04-25 20:17:29 +00001620 barf("__h_errno_location: invalid ThreadId");
sewardj25418ae2003-05-09 23:40:34 +00001621 if (tid == 1)
1622 return &h_errno;
sewardj3b13f0e2002-04-25 20:17:29 +00001623 return & thread_specific_h_errno[tid];
1624}
1625
sewardjb0ff1032002-08-06 09:02:53 +00001626
1627#undef _res
1628extern struct __res_state _res;
sewardj3b13f0e2002-04-25 20:17:29 +00001629struct __res_state* __res_state ( void )
1630{
1631 int tid;
1632 /* ensure_valgrind("__res_state"); */
1633 VALGRIND_MAGIC_SEQUENCE(tid, 1 /* default */,
1634 VG_USERREQ__PTHREAD_GET_THREADID,
1635 0, 0, 0, 0);
1636 /* 'cos I'm paranoid ... */
sewardj439d45e2002-05-03 20:43:10 +00001637 if (tid < 1 || tid >= VG_N_THREADS)
sewardj3b13f0e2002-04-25 20:17:29 +00001638 barf("__res_state: invalid ThreadId");
sewardjb0ff1032002-08-06 09:02:53 +00001639 if (tid == 1)
1640 return & _res;
sewardj3b13f0e2002-04-25 20:17:29 +00001641 return & thread_specific_res_state[tid];
sewardjf8f819e2002-04-17 23:21:37 +00001642}
1643
1644
sewardj5716dbb2002-04-26 03:28:18 +00001645/* ---------------------------------------------------
1646 LIBC-PRIVATE SPECIFIC DATA
1647 ------------------------------------------------ */
1648
1649/* Relies on assumption that initial private data is NULL. This
1650 should be fixed somehow. */
1651
njn25e49d8e72002-09-23 09:36:25 +00001652/* The allowable keys (indices) (all 3 of them).
sewardj5716dbb2002-04-26 03:28:18 +00001653 From sysdeps/pthread/bits/libc-tsd.h
1654*/
sewardjcb7f08a2002-10-02 09:41:49 +00001655/* as per glibc anoncvs HEAD of 20021001. */
sewardj5716dbb2002-04-26 03:28:18 +00001656enum __libc_tsd_key_t { _LIBC_TSD_KEY_MALLOC = 0,
1657 _LIBC_TSD_KEY_DL_ERROR,
njn25e49d8e72002-09-23 09:36:25 +00001658 _LIBC_TSD_KEY_RPC_VARS,
sewardjcb7f08a2002-10-02 09:41:49 +00001659 _LIBC_TSD_KEY_LOCALE,
1660 _LIBC_TSD_KEY_CTYPE_B,
1661 _LIBC_TSD_KEY_CTYPE_TOLOWER,
1662 _LIBC_TSD_KEY_CTYPE_TOUPPER,
sewardj5716dbb2002-04-26 03:28:18 +00001663 _LIBC_TSD_KEY_N };
1664
1665/* Auto-initialising subsystem. libc_specifics_inited is set
1666 after initialisation. libc_specifics_inited_mx guards it. */
1667static int libc_specifics_inited = 0;
1668static pthread_mutex_t libc_specifics_inited_mx = PTHREAD_MUTEX_INITIALIZER;
1669
sewardj00a66b12002-10-12 16:42:35 +00001670
sewardj5716dbb2002-04-26 03:28:18 +00001671/* These are the keys we must initialise the first time. */
sewardjcb7f08a2002-10-02 09:41:49 +00001672static pthread_key_t libc_specifics_keys[_LIBC_TSD_KEY_N];
sewardj5716dbb2002-04-26 03:28:18 +00001673
sewardj00a66b12002-10-12 16:42:35 +00001674
sewardjcb7f08a2002-10-02 09:41:49 +00001675/* Initialise the keys, if they are not already initialised. */
sewardj5716dbb2002-04-26 03:28:18 +00001676static
1677void init_libc_tsd_keys ( void )
1678{
1679 int res, i;
1680 pthread_key_t k;
1681
sewardj08c7f012002-10-07 23:56:55 +00001682 /* Don't fall into deadlock if we get called again whilst we still
1683 hold the lock, via the __uselocale() call herein. */
1684 if (libc_specifics_inited != 0)
1685 return;
1686
1687 /* Take the lock. */
sewardj00a66b12002-10-12 16:42:35 +00001688 res = __pthread_mutex_lock(&libc_specifics_inited_mx);
sewardj5716dbb2002-04-26 03:28:18 +00001689 if (res != 0) barf("init_libc_tsd_keys: lock");
1690
sewardj08c7f012002-10-07 23:56:55 +00001691 /* Now test again, to be sure there is no mistake. */
1692 if (libc_specifics_inited != 0) {
sewardj00a66b12002-10-12 16:42:35 +00001693 res = __pthread_mutex_unlock(&libc_specifics_inited_mx);
sewardj08c7f012002-10-07 23:56:55 +00001694 if (res != 0) barf("init_libc_tsd_keys: unlock(1)");
1695 return;
sewardj5716dbb2002-04-26 03:28:18 +00001696 }
1697
sewardj08c7f012002-10-07 23:56:55 +00001698 /* Actually do the initialisation. */
1699 /* printf("INIT libc specifics\n"); */
1700 for (i = 0; i < _LIBC_TSD_KEY_N; i++) {
sewardj00a66b12002-10-12 16:42:35 +00001701 res = __pthread_key_create(&k, NULL);
sewardj08c7f012002-10-07 23:56:55 +00001702 if (res != 0) barf("init_libc_tsd_keys: create");
1703 libc_specifics_keys[i] = k;
1704 }
1705
1706 /* Signify init done. */
1707 libc_specifics_inited = 1;
1708
1709# ifdef GLIBC_2_3
1710 /* Set the initialising thread's locale to the global (default)
sewardj00a66b12002-10-12 16:42:35 +00001711 locale. A hack in support of glibc-2.3. This does the biz for
1712 the root thread. For all other threads we run this in
1713 thread_wrapper(), which does the real work of
1714 pthread_create(). */
1715 /* assert that we are the root thread. I don't know if this is
1716 really a valid assertion to make; if it breaks I'll reconsider
1717 it. */
1718 my_assert(pthread_self() == 1);
sewardj08c7f012002-10-07 23:56:55 +00001719 __uselocale(LC_GLOBAL_LOCALE);
1720# endif
1721
1722 /* Unlock and return. */
sewardj00a66b12002-10-12 16:42:35 +00001723 res = __pthread_mutex_unlock(&libc_specifics_inited_mx);
sewardj5716dbb2002-04-26 03:28:18 +00001724 if (res != 0) barf("init_libc_tsd_keys: unlock");
1725}
1726
1727
1728static int
1729libc_internal_tsd_set ( enum __libc_tsd_key_t key,
1730 const void * pointer )
1731{
sewardjcb7f08a2002-10-02 09:41:49 +00001732 int res;
sewardj5716dbb2002-04-26 03:28:18 +00001733 /* printf("SET SET SET key %d ptr %p\n", key, pointer); */
sewardjcb7f08a2002-10-02 09:41:49 +00001734 if (key < _LIBC_TSD_KEY_MALLOC || key >= _LIBC_TSD_KEY_N)
sewardj5716dbb2002-04-26 03:28:18 +00001735 barf("libc_internal_tsd_set: invalid key");
1736 init_libc_tsd_keys();
sewardj00a66b12002-10-12 16:42:35 +00001737 res = __pthread_setspecific(libc_specifics_keys[key], pointer);
sewardj5716dbb2002-04-26 03:28:18 +00001738 if (res != 0) barf("libc_internal_tsd_set: setspecific failed");
1739 return 0;
1740}
1741
1742static void *
1743libc_internal_tsd_get ( enum __libc_tsd_key_t key )
1744{
sewardjcb7f08a2002-10-02 09:41:49 +00001745 void* v;
sewardj5716dbb2002-04-26 03:28:18 +00001746 /* printf("GET GET GET key %d\n", key); */
sewardjcb7f08a2002-10-02 09:41:49 +00001747 if (key < _LIBC_TSD_KEY_MALLOC || key >= _LIBC_TSD_KEY_N)
sewardj5716dbb2002-04-26 03:28:18 +00001748 barf("libc_internal_tsd_get: invalid key");
1749 init_libc_tsd_keys();
sewardj00a66b12002-10-12 16:42:35 +00001750 v = __pthread_getspecific(libc_specifics_keys[key]);
sewardj5716dbb2002-04-26 03:28:18 +00001751 /* if (v == NULL) barf("libc_internal_tsd_set: getspecific failed"); */
1752 return v;
1753}
1754
1755
sewardj70adeb22002-04-27 01:35:38 +00001756int (*__libc_internal_tsd_set)
1757 (enum __libc_tsd_key_t key, const void * pointer)
1758 = libc_internal_tsd_set;
sewardj5716dbb2002-04-26 03:28:18 +00001759
sewardj70adeb22002-04-27 01:35:38 +00001760void* (*__libc_internal_tsd_get)
1761 (enum __libc_tsd_key_t key)
1762 = libc_internal_tsd_get;
sewardj5716dbb2002-04-26 03:28:18 +00001763
1764
sewardj00a66b12002-10-12 16:42:35 +00001765#ifdef GLIBC_2_3
1766/* This one was first spotted be me in the glibc-2.2.93 sources. */
1767static void**
1768libc_internal_tsd_address ( enum __libc_tsd_key_t key )
1769{
1770 void** v;
1771 /* printf("ADDR ADDR ADDR key %d\n", key); */
1772 if (key < _LIBC_TSD_KEY_MALLOC || key >= _LIBC_TSD_KEY_N)
1773 barf("libc_internal_tsd_address: invalid key");
1774 init_libc_tsd_keys();
1775 v = __pthread_getspecific_addr(libc_specifics_keys[key]);
1776 return v;
1777}
1778
1779void ** (*__libc_internal_tsd_address)
1780 (enum __libc_tsd_key_t key)
1781 = libc_internal_tsd_address;
1782#endif
1783
1784
sewardje663cb92002-04-12 10:26:32 +00001785/* ---------------------------------------------------------------------
1786 These are here (I think) because they are deemed cancellation
1787 points by POSIX. For the moment we'll simply pass the call along
1788 to the corresponding thread-unaware (?) libc routine.
1789 ------------------------------------------------------------------ */
1790
sewardjd529a442002-05-04 19:49:21 +00001791#ifdef GLIBC_2_1
1792extern
1793int __sigaction
1794 (int signum,
1795 const struct sigaction *act,
1796 struct sigaction *oldact);
1797#else
sewardje663cb92002-04-12 10:26:32 +00001798extern
1799int __libc_sigaction
1800 (int signum,
1801 const struct sigaction *act,
1802 struct sigaction *oldact);
sewardjd529a442002-05-04 19:49:21 +00001803#endif
sewardje663cb92002-04-12 10:26:32 +00001804int sigaction(int signum,
1805 const struct sigaction *act,
1806 struct sigaction *oldact)
1807{
sewardjd140e442002-05-29 01:21:19 +00001808 __my_pthread_testcancel();
sewardj2a1dcce2002-04-22 12:45:25 +00001809# ifdef GLIBC_2_1
1810 return __sigaction(signum, act, oldact);
1811# else
sewardj45b4b372002-04-16 22:50:32 +00001812 return __libc_sigaction(signum, act, oldact);
sewardj2a1dcce2002-04-22 12:45:25 +00001813# endif
sewardje663cb92002-04-12 10:26:32 +00001814}
1815
1816
1817extern
1818int __libc_connect(int sockfd,
1819 const struct sockaddr *serv_addr,
1820 socklen_t addrlen);
sewardj11f0bb42003-04-26 20:11:15 +00001821WEAK
sewardje663cb92002-04-12 10:26:32 +00001822int connect(int sockfd,
1823 const struct sockaddr *serv_addr,
1824 socklen_t addrlen)
1825{
sewardjd140e442002-05-29 01:21:19 +00001826 __my_pthread_testcancel();
sewardj45b4b372002-04-16 22:50:32 +00001827 return __libc_connect(sockfd, serv_addr, addrlen);
sewardje663cb92002-04-12 10:26:32 +00001828}
1829
1830
1831extern
1832int __libc_fcntl(int fd, int cmd, long arg);
sewardj11f0bb42003-04-26 20:11:15 +00001833WEAK
sewardje663cb92002-04-12 10:26:32 +00001834int fcntl(int fd, int cmd, long arg)
1835{
sewardjd140e442002-05-29 01:21:19 +00001836 __my_pthread_testcancel();
sewardj45b4b372002-04-16 22:50:32 +00001837 return __libc_fcntl(fd, cmd, arg);
sewardje663cb92002-04-12 10:26:32 +00001838}
1839
1840
1841extern
1842ssize_t __libc_write(int fd, const void *buf, size_t count);
sewardj11f0bb42003-04-26 20:11:15 +00001843WEAK
sewardje663cb92002-04-12 10:26:32 +00001844ssize_t write(int fd, const void *buf, size_t count)
1845{
sewardjd140e442002-05-29 01:21:19 +00001846 __my_pthread_testcancel();
sewardj45b4b372002-04-16 22:50:32 +00001847 return __libc_write(fd, buf, count);
sewardje663cb92002-04-12 10:26:32 +00001848}
1849
1850
1851extern
1852ssize_t __libc_read(int fd, void *buf, size_t count);
sewardj11f0bb42003-04-26 20:11:15 +00001853WEAK
sewardje663cb92002-04-12 10:26:32 +00001854ssize_t read(int fd, void *buf, size_t count)
1855{
sewardjd140e442002-05-29 01:21:19 +00001856 __my_pthread_testcancel();
sewardj45b4b372002-04-16 22:50:32 +00001857 return __libc_read(fd, buf, count);
sewardje663cb92002-04-12 10:26:32 +00001858}
1859
sewardjf912dfc2002-11-13 21:51:10 +00001860/*
1861 * Ugh, this is horrible but here goes:
1862 *
1863 * Open of a named pipe (fifo file) can block. In a threaded program,
1864 * this means that the whole thing can block. We therefore need to
1865 * make the open appear to block to the caller, but still keep polling
1866 * for everyone else.
1867 *
1868 * There are four cases:
1869 *
1870 * - the caller asked for O_NONBLOCK. The easy one: we just do it.
1871 *
1872 * - the caller asked for a blocking O_RDONLY open. We open it with
1873 * O_NONBLOCK and then use poll to wait for it to become ready.
1874 *
1875 * - the caller asked for a blocking O_WRONLY open. Unfortunately, this
1876 * will fail with ENXIO when we make it non-blocking. Doubly
1877 * unfortunate is that we can only rely on these semantics if it is
1878 * actually a fifo file; the hack is that if we see that it is a
1879 * O_WRONLY open and we get ENXIO, then stat the path and see if it
1880 * actually is a fifo. This is racy, but it is the best we can do.
1881 * If it is a fifo, then keep trying the open until it works; if not
1882 * just return the error.
1883 *
1884 * - the caller asked for a blocking O_RDWR open. Well, under Linux,
1885 * this never blocks, so we just clear the non-blocking flag and
1886 * return.
1887 *
1888 * This code assumes that for whatever we open, O_NONBLOCK followed by
1889 * a fcntl clearing O_NONBLOCK is the same as opening without
1890 * O_NONBLOCK. Also assumes that stat and fstat have no side-effects.
1891 *
1892 * XXX Should probably put in special cases for some devices as well,
1893 * like serial ports. Unfortunately they don't work like fifos, so
1894 * this logic will become even more tortured. Wait until we really
1895 * need it.
1896 */
1897static inline int _open(const char *pathname, int flags, mode_t mode,
1898 int (*openp)(const char *, int, mode_t))
sewardjbe32e452002-04-24 20:29:58 +00001899{
sewardjf912dfc2002-11-13 21:51:10 +00001900 int fd;
1901 struct stat st;
1902 struct vki_timespec nanosleep_interval;
1903 int saved_errno;
1904
sewardjd140e442002-05-29 01:21:19 +00001905 __my_pthread_testcancel();
sewardjf912dfc2002-11-13 21:51:10 +00001906
1907 /* Assume we can only get O_RDONLY, O_WRONLY or O_RDWR */
1908 my_assert((flags & VKI_O_ACCMODE) != VKI_O_ACCMODE);
1909
1910 for(;;) {
1911 fd = (*openp)(pathname, flags | VKI_O_NONBLOCK, mode);
1912
1913 /* return immediately if caller wanted nonblocking anyway */
1914 if (flags & VKI_O_NONBLOCK)
1915 return fd;
1916
sewardj25418ae2003-05-09 23:40:34 +00001917 saved_errno = *(__errno_location());
sewardjf912dfc2002-11-13 21:51:10 +00001918
1919 if (fd != -1)
1920 break; /* open worked */
1921
1922 /* If we got ENXIO and we're opening WRONLY, and it turns out
1923 to really be a FIFO, then poll waiting for open to succeed */
sewardj25418ae2003-05-09 23:40:34 +00001924 if (*(__errno_location()) == ENXIO &&
sewardjf912dfc2002-11-13 21:51:10 +00001925 (flags & VKI_O_ACCMODE) == VKI_O_WRONLY &&
1926 (stat(pathname, &st) == 0 && S_ISFIFO(st.st_mode))) {
1927
1928 /* OK, we're opening a FIFO for writing; sleep and spin */
1929 nanosleep_interval.tv_sec = 0;
1930 nanosleep_interval.tv_nsec = 13 * 1000 * 1000; /* 13 milliseconds */
1931 /* It's critical here that valgrind's nanosleep implementation
1932 is nonblocking. */
1933 (void)my_do_syscall2(__NR_nanosleep,
1934 (int)(&nanosleep_interval), (int)NULL);
1935 } else {
1936 /* it was just an error */
sewardj25418ae2003-05-09 23:40:34 +00001937 *(__errno_location()) = saved_errno;
sewardjf912dfc2002-11-13 21:51:10 +00001938 return -1;
1939 }
1940 }
1941
1942 /* OK, we've got a nonblocking FD for a caller who wants blocking;
1943 reset the flags to what they asked for */
1944 fcntl(fd, VKI_F_SETFL, flags);
1945
1946 /* Return now if one of:
1947 - we were opening O_RDWR (never blocks)
1948 - we opened with O_WRONLY (polling already done)
1949 - the thing we opened wasn't a FIFO after all (or fstat failed)
1950 */
1951 if ((flags & VKI_O_ACCMODE) != VKI_O_RDONLY ||
1952 (fstat(fd, &st) == -1 || !S_ISFIFO(st.st_mode))) {
sewardj25418ae2003-05-09 23:40:34 +00001953 *(__errno_location()) = saved_errno;
sewardjf912dfc2002-11-13 21:51:10 +00001954 return fd;
1955 }
1956
1957 /* OK, drop into the poll loop looking for something to read on the fd */
1958 my_assert((flags & VKI_O_ACCMODE) == VKI_O_RDONLY);
1959 for(;;) {
1960 struct pollfd pollfd;
1961 int res;
1962
1963 pollfd.fd = fd;
1964 pollfd.events = POLLIN;
1965 pollfd.revents = 0;
1966
1967 res = my_do_syscall3(__NR_poll, (int)&pollfd, 1, 0);
1968
1969 my_assert(res == 0 || res == 1);
1970
1971 if (res == 1) {
1972 /* OK, got it.
1973
1974 XXX This is wrong: we're waiting for either something to
1975 read or a HUP on the file descriptor, but the semantics of
1976 fifo open are that we should unblock as soon as someone
1977 simply opens the other end, not that they write something.
1978 With luck this won't matter in practice.
1979 */
1980 my_assert(pollfd.revents & (POLLIN|POLLHUP));
1981 break;
1982 }
1983
1984 /* Still nobody home; sleep and spin */
1985 nanosleep_interval.tv_sec = 0;
1986 nanosleep_interval.tv_nsec = 13 * 1000 * 1000; /* 13 milliseconds */
1987 /* It's critical here that valgrind's nanosleep implementation
1988 is nonblocking. */
1989 (void)my_do_syscall2(__NR_nanosleep,
1990 (int)(&nanosleep_interval), (int)NULL);
1991 }
1992
sewardj25418ae2003-05-09 23:40:34 +00001993 *(__errno_location()) = saved_errno;
sewardjf912dfc2002-11-13 21:51:10 +00001994 return fd;
sewardjbe32e452002-04-24 20:29:58 +00001995}
1996
sewardjf912dfc2002-11-13 21:51:10 +00001997extern
1998int __libc_open64(const char *pathname, int flags, mode_t mode);
sewardj11f0bb42003-04-26 20:11:15 +00001999/* WEAK */
sewardjf912dfc2002-11-13 21:51:10 +00002000int open64(const char *pathname, int flags, mode_t mode)
2001{
2002 return _open(pathname, flags, mode, __libc_open64);
2003}
sewardje663cb92002-04-12 10:26:32 +00002004
2005extern
sewardj853f55d2002-04-26 00:27:53 +00002006int __libc_open(const char *pathname, int flags, mode_t mode);
sewardj11f0bb42003-04-26 20:11:15 +00002007/* WEAK */
sewardj853f55d2002-04-26 00:27:53 +00002008int open(const char *pathname, int flags, mode_t mode)
sewardje663cb92002-04-12 10:26:32 +00002009{
sewardjf912dfc2002-11-13 21:51:10 +00002010 return _open(pathname, flags, mode, __libc_open);
sewardje663cb92002-04-12 10:26:32 +00002011}
2012
sewardje663cb92002-04-12 10:26:32 +00002013extern
2014int __libc_close(int fd);
sewardj11f0bb42003-04-26 20:11:15 +00002015WEAK
sewardje663cb92002-04-12 10:26:32 +00002016int close(int fd)
2017{
sewardjd140e442002-05-29 01:21:19 +00002018 __my_pthread_testcancel();
sewardj45b4b372002-04-16 22:50:32 +00002019 return __libc_close(fd);
sewardje663cb92002-04-12 10:26:32 +00002020}
2021
2022
sewardj11f0bb42003-04-26 20:11:15 +00002023WEAK
2024int accept(int s, struct sockaddr *addr, socklen_t *addrlen)
sewardje663cb92002-04-12 10:26:32 +00002025{
sewardj11f0bb42003-04-26 20:11:15 +00002026 return VGR_(accept)(s, addr, addrlen);
sewardje663cb92002-04-12 10:26:32 +00002027}
2028
sewardj11f0bb42003-04-26 20:11:15 +00002029WEAK
2030int recv(int s, void *buf, size_t len, int flags)
sewardj0c573af92002-10-23 21:55:01 +00002031{
sewardj11f0bb42003-04-26 20:11:15 +00002032 return VGR_(recv)(s, buf, len, flags);
sewardj0c573af92002-10-23 21:55:01 +00002033}
2034
sewardj11f0bb42003-04-26 20:11:15 +00002035WEAK
2036int readv(int fd, const struct iovec *iov, int count)
sewardj2a68e7e2002-11-16 11:04:18 +00002037{
sewardj11f0bb42003-04-26 20:11:15 +00002038 return VGR_(readv)(fd, iov, count);
sewardj2a68e7e2002-11-16 11:04:18 +00002039}
2040
sewardj11f0bb42003-04-26 20:11:15 +00002041WEAK
2042int writev(int fd, const struct iovec *iov, int count)
sewardj2a68e7e2002-11-16 11:04:18 +00002043{
sewardj11f0bb42003-04-26 20:11:15 +00002044 return VGR_(writev)(fd, iov, count);
sewardj2a68e7e2002-11-16 11:04:18 +00002045}
sewardje663cb92002-04-12 10:26:32 +00002046
2047extern
sewardje663cb92002-04-12 10:26:32 +00002048pid_t __libc_waitpid(pid_t pid, int *status, int options);
sewardj11f0bb42003-04-26 20:11:15 +00002049WEAK
sewardje663cb92002-04-12 10:26:32 +00002050pid_t waitpid(pid_t pid, int *status, int options)
2051{
sewardjd140e442002-05-29 01:21:19 +00002052 __my_pthread_testcancel();
sewardj45b4b372002-04-16 22:50:32 +00002053 return __libc_waitpid(pid, status, options);
sewardje663cb92002-04-12 10:26:32 +00002054}
2055
2056
2057extern
2058int __libc_nanosleep(const struct timespec *req, struct timespec *rem);
sewardj11f0bb42003-04-26 20:11:15 +00002059WEAK
sewardje663cb92002-04-12 10:26:32 +00002060int nanosleep(const struct timespec *req, struct timespec *rem)
2061{
sewardjd140e442002-05-29 01:21:19 +00002062 __my_pthread_testcancel();
sewardje663cb92002-04-12 10:26:32 +00002063 return __libc_nanosleep(req, rem);
2064}
2065
sewardjbe32e452002-04-24 20:29:58 +00002066
sewardje663cb92002-04-12 10:26:32 +00002067extern
2068int __libc_fsync(int fd);
sewardj11f0bb42003-04-26 20:11:15 +00002069WEAK
sewardje663cb92002-04-12 10:26:32 +00002070int fsync(int fd)
2071{
sewardjd140e442002-05-29 01:21:19 +00002072 __my_pthread_testcancel();
sewardj45b4b372002-04-16 22:50:32 +00002073 return __libc_fsync(fd);
sewardje663cb92002-04-12 10:26:32 +00002074}
2075
sewardjbe32e452002-04-24 20:29:58 +00002076
sewardj70c75362002-04-13 04:18:32 +00002077extern
2078off_t __libc_lseek(int fildes, off_t offset, int whence);
sewardj11f0bb42003-04-26 20:11:15 +00002079WEAK
sewardj70c75362002-04-13 04:18:32 +00002080off_t lseek(int fildes, off_t offset, int whence)
2081{
sewardjd140e442002-05-29 01:21:19 +00002082 __my_pthread_testcancel();
sewardj45b4b372002-04-16 22:50:32 +00002083 return __libc_lseek(fildes, offset, whence);
sewardj70c75362002-04-13 04:18:32 +00002084}
2085
sewardjbe32e452002-04-24 20:29:58 +00002086
2087extern
2088__off64_t __libc_lseek64(int fildes, __off64_t offset, int whence);
sewardj11f0bb42003-04-26 20:11:15 +00002089WEAK
sewardjbe32e452002-04-24 20:29:58 +00002090__off64_t lseek64(int fildes, __off64_t offset, int whence)
2091{
sewardjd140e442002-05-29 01:21:19 +00002092 __my_pthread_testcancel();
sewardjbe32e452002-04-24 20:29:58 +00002093 return __libc_lseek64(fildes, offset, whence);
2094}
2095
2096
sewardj726c4122002-05-16 23:39:10 +00002097extern
2098ssize_t __libc_pread64 (int __fd, void *__buf, size_t __nbytes,
2099 __off64_t __offset);
2100ssize_t __pread64 (int __fd, void *__buf, size_t __nbytes,
2101 __off64_t __offset)
2102{
sewardjd140e442002-05-29 01:21:19 +00002103 __my_pthread_testcancel();
sewardj726c4122002-05-16 23:39:10 +00002104 return __libc_pread64(__fd, __buf, __nbytes, __offset);
2105}
2106
2107
sewardja18e2102002-05-18 10:43:22 +00002108extern
2109ssize_t __libc_pwrite64 (int __fd, const void *__buf, size_t __nbytes,
2110 __off64_t __offset);
2111ssize_t __pwrite64 (int __fd, const void *__buf, size_t __nbytes,
2112 __off64_t __offset)
2113{
sewardjd140e442002-05-29 01:21:19 +00002114 __my_pthread_testcancel();
sewardja18e2102002-05-18 10:43:22 +00002115 return __libc_pwrite64(__fd, __buf, __nbytes, __offset);
2116}
2117
sewardj726c4122002-05-16 23:39:10 +00002118
sewardj39b93b12002-05-18 10:56:27 +00002119extern
2120ssize_t __libc_pwrite(int fd, const void *buf, size_t count, off_t offset);
sewardj11f0bb42003-04-26 20:11:15 +00002121WEAK
sewardj39b93b12002-05-18 10:56:27 +00002122ssize_t pwrite(int fd, const void *buf, size_t count, off_t offset)
2123{
sewardjd140e442002-05-29 01:21:19 +00002124 __my_pthread_testcancel();
sewardj39b93b12002-05-18 10:56:27 +00002125 return __libc_pwrite(fd, buf, count, offset);
2126}
2127
2128
2129extern
2130ssize_t __libc_pread(int fd, void *buf, size_t count, off_t offset);
sewardj11f0bb42003-04-26 20:11:15 +00002131WEAK
sewardj39b93b12002-05-18 10:56:27 +00002132ssize_t pread(int fd, void *buf, size_t count, off_t offset)
2133{
sewardjd140e442002-05-29 01:21:19 +00002134 __my_pthread_testcancel();
sewardj39b93b12002-05-18 10:56:27 +00002135 return __libc_pread(fd, buf, count, offset);
2136}
2137
2138
sewardj6af4b5d2002-04-16 04:40:49 +00002139extern
2140void __libc_longjmp(jmp_buf env, int val) __attribute((noreturn));
sewardj11f0bb42003-04-26 20:11:15 +00002141/* not weak: WEAK */
sewardj6af4b5d2002-04-16 04:40:49 +00002142void longjmp(jmp_buf env, int val)
2143{
2144 __libc_longjmp(env, val);
2145}
2146
sewardjbe32e452002-04-24 20:29:58 +00002147
sewardj436c2db2002-06-18 09:07:54 +00002148extern void __libc_siglongjmp (sigjmp_buf env, int val)
2149 __attribute__ ((noreturn));
2150void siglongjmp(sigjmp_buf env, int val)
2151{
2152 kludged("siglongjmp (cleanup handlers are ignored)");
2153 __libc_siglongjmp(env, val);
2154}
2155
2156
sewardj6af4b5d2002-04-16 04:40:49 +00002157extern
2158int __libc_send(int s, const void *msg, size_t len, int flags);
sewardj11f0bb42003-04-26 20:11:15 +00002159WEAK
sewardj6af4b5d2002-04-16 04:40:49 +00002160int send(int s, const void *msg, size_t len, int flags)
2161{
sewardjd140e442002-05-29 01:21:19 +00002162 __my_pthread_testcancel();
sewardj6af4b5d2002-04-16 04:40:49 +00002163 return __libc_send(s, msg, len, flags);
2164}
2165
sewardjbe32e452002-04-24 20:29:58 +00002166
sewardj3665ded2002-05-16 16:57:25 +00002167extern
2168int __libc_sendmsg(int s, const struct msghdr *msg, int flags);
sewardj11f0bb42003-04-26 20:11:15 +00002169WEAK
sewardj3665ded2002-05-16 16:57:25 +00002170int sendmsg(int s, const struct msghdr *msg, int flags)
2171{
sewardjd140e442002-05-29 01:21:19 +00002172 __my_pthread_testcancel();
sewardj3665ded2002-05-16 16:57:25 +00002173 return __libc_sendmsg(s, msg, flags);
2174}
2175
2176
sewardj796d6a22002-04-24 02:28:34 +00002177extern
sewardj59da27a2002-06-06 08:33:54 +00002178int __libc_recvmsg(int s, struct msghdr *msg, int flags);
sewardj11f0bb42003-04-26 20:11:15 +00002179WEAK
sewardj59da27a2002-06-06 08:33:54 +00002180int recvmsg(int s, struct msghdr *msg, int flags)
2181{
2182 __my_pthread_testcancel();
2183 return __libc_recvmsg(s, msg, flags);
2184}
2185
2186
2187extern
sewardj436e0582002-04-26 14:31:40 +00002188int __libc_recvfrom(int s, void *buf, size_t len, int flags,
2189 struct sockaddr *from, socklen_t *fromlen);
sewardj11f0bb42003-04-26 20:11:15 +00002190WEAK
sewardj436e0582002-04-26 14:31:40 +00002191int recvfrom(int s, void *buf, size_t len, int flags,
2192 struct sockaddr *from, socklen_t *fromlen)
2193{
sewardjd140e442002-05-29 01:21:19 +00002194 __my_pthread_testcancel();
sewardj11f0bb42003-04-26 20:11:15 +00002195 VGR_(wait_for_fd_to_be_readable_or_erring)(s);
sewardj2e207632002-06-13 17:29:53 +00002196 __my_pthread_testcancel();
sewardj436e0582002-04-26 14:31:40 +00002197 return __libc_recvfrom(s, buf, len, flags, from, fromlen);
2198}
2199
2200
2201extern
sewardj796d6a22002-04-24 02:28:34 +00002202int __libc_sendto(int s, const void *msg, size_t len, int flags,
2203 const struct sockaddr *to, socklen_t tolen);
sewardj11f0bb42003-04-26 20:11:15 +00002204WEAK
sewardj796d6a22002-04-24 02:28:34 +00002205int sendto(int s, const void *msg, size_t len, int flags,
2206 const struct sockaddr *to, socklen_t tolen)
2207{
sewardjd140e442002-05-29 01:21:19 +00002208 __my_pthread_testcancel();
sewardj796d6a22002-04-24 02:28:34 +00002209 return __libc_sendto(s, msg, len, flags, to, tolen);
2210}
2211
sewardjbe32e452002-04-24 20:29:58 +00002212
sewardj369b1702002-04-24 13:28:15 +00002213extern
2214int __libc_system(const char* str);
sewardj11f0bb42003-04-26 20:11:15 +00002215WEAK
sewardj369b1702002-04-24 13:28:15 +00002216int system(const char* str)
2217{
sewardjd140e442002-05-29 01:21:19 +00002218 __my_pthread_testcancel();
sewardj369b1702002-04-24 13:28:15 +00002219 return __libc_system(str);
2220}
2221
sewardjbe32e452002-04-24 20:29:58 +00002222
sewardjab0b1c32002-04-24 19:26:47 +00002223extern
2224pid_t __libc_wait(int *status);
sewardj11f0bb42003-04-26 20:11:15 +00002225WEAK
sewardjab0b1c32002-04-24 19:26:47 +00002226pid_t wait(int *status)
2227{
sewardjd140e442002-05-29 01:21:19 +00002228 __my_pthread_testcancel();
sewardjab0b1c32002-04-24 19:26:47 +00002229 return __libc_wait(status);
2230}
2231
sewardj45b4b372002-04-16 22:50:32 +00002232
sewardj67f1d582002-05-24 02:11:32 +00002233extern
2234int __libc_msync(const void *start, size_t length, int flags);
sewardj11f0bb42003-04-26 20:11:15 +00002235WEAK
sewardj67f1d582002-05-24 02:11:32 +00002236int msync(const void *start, size_t length, int flags)
2237{
sewardjd140e442002-05-29 01:21:19 +00002238 __my_pthread_testcancel();
sewardj67f1d582002-05-24 02:11:32 +00002239 return __libc_msync(start, length, flags);
2240}
2241
sewardj5905fae2002-04-26 13:25:00 +00002242
sewardj2cb00342002-06-28 01:46:26 +00002243/*--- fork and its helper ---*/
2244
2245static
2246void run_fork_handlers ( int what )
2247{
2248 ForkHandlerEntry entry;
2249 int n_h, n_handlers, i, res;
2250
2251 my_assert(what == 0 || what == 1 || what == 2);
2252
2253 /* Fetch old counter */
2254 VALGRIND_MAGIC_SEQUENCE(n_handlers, -2 /* default */,
2255 VG_USERREQ__GET_FHSTACK_USED,
2256 0, 0, 0, 0);
2257 my_assert(n_handlers >= 0 && n_handlers < VG_N_FORKHANDLERSTACK);
2258
2259 /* Prepare handlers (what == 0) are called in opposite order of
2260 calls to pthread_atfork. Parent and child handlers are called
2261 in the same order as calls to pthread_atfork. */
2262 if (what == 0)
2263 n_h = n_handlers - 1;
2264 else
2265 n_h = 0;
2266
2267 for (i = 0; i < n_handlers; i++) {
2268 VALGRIND_MAGIC_SEQUENCE(res, -2 /* default */,
2269 VG_USERREQ__GET_FHSTACK_ENTRY,
2270 n_h, &entry, 0, 0);
2271 my_assert(res == 0);
2272 switch (what) {
2273 case 0: if (entry.prepare) entry.prepare();
2274 n_h--; break;
2275 case 1: if (entry.parent) entry.parent();
2276 n_h++; break;
2277 case 2: if (entry.child) entry.child();
2278 n_h++; break;
2279 default: barf("run_fork_handlers: invalid what");
2280 }
2281 }
2282
2283 if (what != 0 /* prepare */) {
2284 /* Empty out the stack. */
2285 VALGRIND_MAGIC_SEQUENCE(res, -2 /* default */,
2286 VG_USERREQ__SET_FHSTACK_USED,
2287 0, 0, 0, 0);
2288 my_assert(res == 0);
2289 }
2290}
2291
2292extern
2293pid_t __libc_fork(void);
2294pid_t __fork(void)
2295{
2296 pid_t pid;
2297 __my_pthread_testcancel();
2298 __pthread_mutex_lock(&pthread_atfork_lock);
2299
2300 run_fork_handlers(0 /* prepare */);
2301 pid = __libc_fork();
2302 if (pid == 0) {
2303 /* I am the child */
2304 run_fork_handlers(2 /* child */);
sewardjd8acdf22002-11-13 21:57:52 +00002305 __pthread_mutex_unlock(&pthread_atfork_lock);
sewardj2cb00342002-06-28 01:46:26 +00002306 __pthread_mutex_init(&pthread_atfork_lock, NULL);
2307 } else {
2308 /* I am the parent */
2309 run_fork_handlers(1 /* parent */);
2310 __pthread_mutex_unlock(&pthread_atfork_lock);
2311 }
2312 return pid;
2313}
2314
2315
njn25e49d8e72002-09-23 09:36:25 +00002316pid_t __vfork(void)
2317{
2318 return __fork();
2319}
sewardj2cb00342002-06-28 01:46:26 +00002320
2321
sewardj08a4c3f2002-04-13 03:45:44 +00002322static
sewardj08a4c3f2002-04-13 03:45:44 +00002323int my_do_syscall1 ( int syscallno, int arg1 )
2324{
2325 int __res;
2326 __asm__ volatile ("pushl %%ebx; movl %%edx,%%ebx ; int $0x80 ; popl %%ebx"
2327 : "=a" (__res)
2328 : "0" (syscallno),
2329 "d" (arg1) );
2330 return __res;
2331}
2332
2333static
2334int my_do_syscall2 ( int syscallno,
sewardjf854f472002-04-21 12:19:41 +00002335 int arg1, int arg2 )
sewardj08a4c3f2002-04-13 03:45:44 +00002336{
2337 int __res;
2338 __asm__ volatile ("pushl %%ebx; movl %%edx,%%ebx ; int $0x80 ; popl %%ebx"
2339 : "=a" (__res)
2340 : "0" (syscallno),
2341 "d" (arg1),
2342 "c" (arg2) );
2343 return __res;
2344}
2345
2346static
sewardjf854f472002-04-21 12:19:41 +00002347int my_do_syscall3 ( int syscallno,
2348 int arg1, int arg2, int arg3 )
2349{
2350 int __res;
2351 __asm__ volatile ("pushl %%ebx; movl %%esi,%%ebx ; int $0x80 ; popl %%ebx"
2352 : "=a" (__res)
2353 : "0" (syscallno),
2354 "S" (arg1),
2355 "c" (arg2),
2356 "d" (arg3) );
2357 return __res;
2358}
2359
sewardjd5bef572002-10-23 21:49:33 +00002360static inline
2361int my_do_syscall5 ( int syscallno,
2362 int arg1, int arg2, int arg3, int arg4, int arg5 )
2363{
2364 int __res;
2365 __asm__ volatile ("int $0x80"
2366 : "=a" (__res)
2367 : "0" (syscallno),
2368 "b" (arg1),
2369 "c" (arg2),
2370 "d" (arg3),
2371 "S" (arg4),
2372 "D" (arg5));
2373 return __res;
2374}
2375
sewardj11f0bb42003-04-26 20:11:15 +00002376
2377WEAK
2378int select ( int n,
2379 fd_set *rfds,
2380 fd_set *wfds,
2381 fd_set *xfds,
2382 struct timeval *timeout )
sewardj08a4c3f2002-04-13 03:45:44 +00002383{
sewardj11f0bb42003-04-26 20:11:15 +00002384 return VGR_(select)(n, rfds, wfds, xfds, timeout);
sewardj08a4c3f2002-04-13 03:45:44 +00002385}
2386
2387
sewardj3b13f0e2002-04-25 20:17:29 +00002388/* ---------------------------------------------------------------------
sewardj8f253ff2002-05-19 00:13:34 +00002389 Hacky implementation of semaphores.
2390 ------------------------------------------------------------------ */
2391
2392#include <semaphore.h>
2393
2394/* This is a terrible way to do the remapping. Plan is to import an
2395 AVL tree at some point. */
sewardj8f253ff2002-05-19 00:13:34 +00002396
2397typedef
2398 struct {
2399 pthread_mutex_t se_mx;
2400 pthread_cond_t se_cv;
2401 int count;
2402 }
2403 vg_sem_t;
2404
2405static pthread_mutex_t se_remap_mx = PTHREAD_MUTEX_INITIALIZER;
2406
2407static int se_remap_used = 0;
2408static sem_t* se_remap_orig[VG_N_SEMAPHORES];
2409static vg_sem_t se_remap_new[VG_N_SEMAPHORES];
2410
2411static vg_sem_t* se_remap ( sem_t* orig )
2412{
2413 int res, i;
2414 res = __pthread_mutex_lock(&se_remap_mx);
sewardj2d94c112002-06-03 01:25:54 +00002415 my_assert(res == 0);
sewardj8f253ff2002-05-19 00:13:34 +00002416
2417 for (i = 0; i < se_remap_used; i++) {
2418 if (se_remap_orig[i] == orig)
2419 break;
2420 }
2421 if (i == se_remap_used) {
2422 if (se_remap_used == VG_N_SEMAPHORES) {
2423 res = pthread_mutex_unlock(&se_remap_mx);
sewardj2d94c112002-06-03 01:25:54 +00002424 my_assert(res == 0);
sewardja1ac5cb2002-05-27 13:00:05 +00002425 barf("VG_N_SEMAPHORES is too low. Increase and recompile.");
sewardj8f253ff2002-05-19 00:13:34 +00002426 }
2427 se_remap_used++;
2428 se_remap_orig[i] = orig;
2429 /* printf("allocated semaphore %d\n", i); */
2430 }
2431 res = __pthread_mutex_unlock(&se_remap_mx);
sewardj2d94c112002-06-03 01:25:54 +00002432 my_assert(res == 0);
sewardj8f253ff2002-05-19 00:13:34 +00002433 return &se_remap_new[i];
2434}
2435
2436
2437int sem_init(sem_t *sem, int pshared, unsigned int value)
2438{
2439 int res;
2440 vg_sem_t* vg_sem;
2441 ensure_valgrind("sem_init");
2442 if (pshared != 0) {
sewardj4dced352002-06-04 22:54:20 +00002443 pthread_error("sem_init: unsupported pshared value");
sewardj25418ae2003-05-09 23:40:34 +00002444 *(__errno_location()) = ENOSYS;
sewardj8f253ff2002-05-19 00:13:34 +00002445 return -1;
2446 }
2447 vg_sem = se_remap(sem);
2448 res = pthread_mutex_init(&vg_sem->se_mx, NULL);
sewardj2d94c112002-06-03 01:25:54 +00002449 my_assert(res == 0);
sewardj8f253ff2002-05-19 00:13:34 +00002450 res = pthread_cond_init(&vg_sem->se_cv, NULL);
sewardj2d94c112002-06-03 01:25:54 +00002451 my_assert(res == 0);
sewardj8f253ff2002-05-19 00:13:34 +00002452 vg_sem->count = value;
2453 return 0;
2454}
2455
2456
2457int sem_wait ( sem_t* sem )
2458{
2459 int res;
2460 vg_sem_t* vg_sem;
2461 ensure_valgrind("sem_wait");
2462 vg_sem = se_remap(sem);
2463 res = __pthread_mutex_lock(&vg_sem->se_mx);
sewardj2d94c112002-06-03 01:25:54 +00002464 my_assert(res == 0);
sewardj8f253ff2002-05-19 00:13:34 +00002465 while (vg_sem->count == 0) {
2466 res = pthread_cond_wait(&vg_sem->se_cv, &vg_sem->se_mx);
sewardj2d94c112002-06-03 01:25:54 +00002467 my_assert(res == 0);
sewardj8f253ff2002-05-19 00:13:34 +00002468 }
2469 vg_sem->count--;
2470 res = __pthread_mutex_unlock(&vg_sem->se_mx);
sewardj2d94c112002-06-03 01:25:54 +00002471 my_assert(res == 0);
sewardj8f253ff2002-05-19 00:13:34 +00002472 return 0;
2473}
2474
2475int sem_post ( sem_t* sem )
2476{
2477 int res;
2478 vg_sem_t* vg_sem;
2479 ensure_valgrind("sem_post");
2480 vg_sem = se_remap(sem);
2481 res = __pthread_mutex_lock(&vg_sem->se_mx);
sewardj2d94c112002-06-03 01:25:54 +00002482 my_assert(res == 0);
sewardj8f253ff2002-05-19 00:13:34 +00002483 if (vg_sem->count == 0) {
2484 vg_sem->count++;
2485 res = pthread_cond_broadcast(&vg_sem->se_cv);
sewardj2d94c112002-06-03 01:25:54 +00002486 my_assert(res == 0);
sewardj8f253ff2002-05-19 00:13:34 +00002487 } else {
2488 vg_sem->count++;
2489 }
2490 res = __pthread_mutex_unlock(&vg_sem->se_mx);
sewardj2d94c112002-06-03 01:25:54 +00002491 my_assert(res == 0);
sewardj8f253ff2002-05-19 00:13:34 +00002492 return 0;
2493}
2494
2495
2496int sem_trywait ( sem_t* sem )
2497{
2498 int ret, res;
2499 vg_sem_t* vg_sem;
2500 ensure_valgrind("sem_trywait");
2501 vg_sem = se_remap(sem);
2502 res = __pthread_mutex_lock(&vg_sem->se_mx);
sewardj2d94c112002-06-03 01:25:54 +00002503 my_assert(res == 0);
sewardj8f253ff2002-05-19 00:13:34 +00002504 if (vg_sem->count > 0) {
2505 vg_sem->count--;
2506 ret = 0;
2507 } else {
2508 ret = -1;
sewardj25418ae2003-05-09 23:40:34 +00002509 *(__errno_location()) = EAGAIN;
sewardj8f253ff2002-05-19 00:13:34 +00002510 }
2511 res = __pthread_mutex_unlock(&vg_sem->se_mx);
sewardj2d94c112002-06-03 01:25:54 +00002512 my_assert(res == 0);
sewardj8f253ff2002-05-19 00:13:34 +00002513 return ret;
2514}
2515
2516
2517int sem_getvalue(sem_t* sem, int * sval)
2518{
2519 vg_sem_t* vg_sem;
2520 ensure_valgrind("sem_trywait");
2521 vg_sem = se_remap(sem);
2522 *sval = vg_sem->count;
2523 return 0;
2524}
2525
2526
2527int sem_destroy(sem_t * sem)
2528{
2529 kludged("sem_destroy");
2530 /* if someone waiting on this semaphore, errno = EBUSY, return -1 */
2531 return 0;
2532}
2533
sewardj9ad92d92002-10-16 19:45:06 +00002534
2535int sem_timedwait(sem_t* sem, const struct timespec *abstime)
2536{
2537 int res;
2538 vg_sem_t* vg_sem;
2539 ensure_valgrind("sem_timedwait");
2540 vg_sem = se_remap(sem);
2541 res = __pthread_mutex_lock(&vg_sem->se_mx);
2542 my_assert(res == 0);
2543 while ( vg_sem->count == 0 && res != ETIMEDOUT ) {
2544 res = pthread_cond_timedwait(&vg_sem->se_cv, &vg_sem->se_mx, abstime);
2545 }
2546 if ( vg_sem->count > 0 ) {
2547 vg_sem->count--;
2548 res = __pthread_mutex_unlock(&vg_sem->se_mx);
2549 my_assert(res == 0 );
2550 return 0;
2551 } else {
2552 res = __pthread_mutex_unlock(&vg_sem->se_mx);
2553 my_assert(res == 0 );
2554 *(__errno_location()) = ETIMEDOUT;
2555 return -1;
2556 }
2557}
2558
sewardj8f253ff2002-05-19 00:13:34 +00002559
2560/* ---------------------------------------------------------------------
sewardj2d8b3f02002-06-01 14:14:19 +00002561 Reader-writer locks.
sewardja1ac5cb2002-05-27 13:00:05 +00002562 ------------------------------------------------------------------ */
2563
sewardj2d8b3f02002-06-01 14:14:19 +00002564typedef
2565 struct {
2566 int initted; /* != 0 --> in use; sanity check only */
2567 int prefer_w; /* != 0 --> prefer writer */
2568 int nwait_r; /* # of waiting readers */
2569 int nwait_w; /* # of waiting writers */
2570 pthread_cond_t cv_r; /* for signalling readers */
2571 pthread_cond_t cv_w; /* for signalling writers */
2572 pthread_mutex_t mx;
2573 int status;
2574 /* allowed range for status: >= -1. -1 means 1 writer currently
2575 active, >= 0 means N readers currently active. */
2576 }
2577 vg_rwlock_t;
sewardja1ac5cb2002-05-27 13:00:05 +00002578
2579
2580static pthread_mutex_t rw_remap_mx = PTHREAD_MUTEX_INITIALIZER;
2581
2582static int rw_remap_used = 0;
2583static pthread_rwlock_t* rw_remap_orig[VG_N_RWLOCKS];
2584static vg_rwlock_t rw_remap_new[VG_N_RWLOCKS];
2585
sewardj2d8b3f02002-06-01 14:14:19 +00002586
2587static
2588void init_vg_rwlock ( vg_rwlock_t* vg_rwl )
2589{
2590 int res = 0;
2591 vg_rwl->initted = 1;
2592 vg_rwl->prefer_w = 1;
2593 vg_rwl->nwait_r = 0;
2594 vg_rwl->nwait_w = 0;
2595 vg_rwl->status = 0;
2596 res = pthread_mutex_init(&vg_rwl->mx, NULL);
2597 res |= pthread_cond_init(&vg_rwl->cv_r, NULL);
2598 res |= pthread_cond_init(&vg_rwl->cv_w, NULL);
sewardj2d94c112002-06-03 01:25:54 +00002599 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002600}
2601
2602
sewardja1ac5cb2002-05-27 13:00:05 +00002603/* Take the address of a LinuxThreads rwlock_t and return the shadow
2604 address of our version. Further, if the LinuxThreads version
2605 appears to have been statically initialised, do the same to the one
2606 we allocate here. The pthread_rwlock_t.__rw_readers field is set
2607 to zero by PTHREAD_RWLOCK_INITIALIZER, so we take zero as meaning
2608 uninitialised and non-zero meaning initialised.
2609*/
2610static vg_rwlock_t* rw_remap ( pthread_rwlock_t* orig )
2611{
2612 int res, i;
2613 vg_rwlock_t* vg_rwl;
2614 res = __pthread_mutex_lock(&rw_remap_mx);
sewardj2d94c112002-06-03 01:25:54 +00002615 my_assert(res == 0);
sewardja1ac5cb2002-05-27 13:00:05 +00002616
2617 for (i = 0; i < rw_remap_used; i++) {
2618 if (rw_remap_orig[i] == orig)
2619 break;
2620 }
2621 if (i == rw_remap_used) {
2622 if (rw_remap_used == VG_N_RWLOCKS) {
sewardj2d8b3f02002-06-01 14:14:19 +00002623 res = __pthread_mutex_unlock(&rw_remap_mx);
sewardj2d94c112002-06-03 01:25:54 +00002624 my_assert(res == 0);
sewardja1ac5cb2002-05-27 13:00:05 +00002625 barf("VG_N_RWLOCKS is too low. Increase and recompile.");
2626 }
2627 rw_remap_used++;
2628 rw_remap_orig[i] = orig;
sewardj2d8b3f02002-06-01 14:14:19 +00002629 rw_remap_new[i].initted = 0;
sewardja1ac5cb2002-05-27 13:00:05 +00002630 if (0) printf("allocated rwlock %d\n", i);
2631 }
2632 res = __pthread_mutex_unlock(&rw_remap_mx);
sewardj2d94c112002-06-03 01:25:54 +00002633 my_assert(res == 0);
sewardja1ac5cb2002-05-27 13:00:05 +00002634 vg_rwl = &rw_remap_new[i];
2635
sewardj2d8b3f02002-06-01 14:14:19 +00002636 /* Initialise the shadow, if required. */
sewardja1ac5cb2002-05-27 13:00:05 +00002637 if (orig->__rw_readers == 0) {
sewardja1ac5cb2002-05-27 13:00:05 +00002638 orig->__rw_readers = 1;
sewardj2d8b3f02002-06-01 14:14:19 +00002639 init_vg_rwlock(vg_rwl);
sewardja1ac5cb2002-05-27 13:00:05 +00002640 if (orig->__rw_kind == PTHREAD_RWLOCK_PREFER_READER_NP)
sewardj2d8b3f02002-06-01 14:14:19 +00002641 vg_rwl->prefer_w = 0;
sewardja1ac5cb2002-05-27 13:00:05 +00002642 }
2643
2644 return vg_rwl;
2645}
2646
2647
sewardja1ac5cb2002-05-27 13:00:05 +00002648int pthread_rwlock_init ( pthread_rwlock_t* orig,
2649 const pthread_rwlockattr_t* attr )
2650{
sewardja1ac5cb2002-05-27 13:00:05 +00002651 vg_rwlock_t* rwl;
2652 if (0) printf ("pthread_rwlock_init\n");
2653 /* Force the remapper to initialise the shadow. */
2654 orig->__rw_readers = 0;
2655 /* Install the lock preference; the remapper needs to know it. */
2656 orig->__rw_kind = PTHREAD_RWLOCK_DEFAULT_NP;
2657 if (attr)
2658 orig->__rw_kind = attr->__lockkind;
2659 rwl = rw_remap ( orig );
sewardj2d8b3f02002-06-01 14:14:19 +00002660 return 0;
sewardja1ac5cb2002-05-27 13:00:05 +00002661}
2662
sewardj2d8b3f02002-06-01 14:14:19 +00002663
2664static
2665void pthread_rwlock_rdlock_CANCEL_HDLR ( void* rwl_v )
sewardja1ac5cb2002-05-27 13:00:05 +00002666{
sewardj2d8b3f02002-06-01 14:14:19 +00002667 vg_rwlock_t* rwl = (vg_rwlock_t*)rwl_v;
2668 rwl->nwait_r--;
2669 pthread_mutex_unlock (&rwl->mx);
sewardja1ac5cb2002-05-27 13:00:05 +00002670}
2671
sewardj2d8b3f02002-06-01 14:14:19 +00002672
sewardja1ac5cb2002-05-27 13:00:05 +00002673int pthread_rwlock_rdlock ( pthread_rwlock_t* orig )
2674{
2675 int res;
2676 vg_rwlock_t* rwl;
2677 if (0) printf ("pthread_rwlock_rdlock\n");
2678 rwl = rw_remap ( orig );
sewardj2d8b3f02002-06-01 14:14:19 +00002679 res = __pthread_mutex_lock(&rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00002680 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002681 if (!rwl->initted) {
2682 res = __pthread_mutex_unlock(&rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00002683 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002684 return EINVAL;
2685 }
2686 if (rwl->status < 0) {
sewardj2d94c112002-06-03 01:25:54 +00002687 my_assert(rwl->status == -1);
sewardj2d8b3f02002-06-01 14:14:19 +00002688 rwl->nwait_r++;
2689 pthread_cleanup_push( pthread_rwlock_rdlock_CANCEL_HDLR, rwl );
2690 while (1) {
2691 if (rwl->status == 0) break;
2692 res = pthread_cond_wait(&rwl->cv_r, &rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00002693 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002694 }
2695 pthread_cleanup_pop(0);
2696 rwl->nwait_r--;
2697 }
sewardj2d94c112002-06-03 01:25:54 +00002698 my_assert(rwl->status >= 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002699 rwl->status++;
2700 res = __pthread_mutex_unlock(&rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00002701 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002702 return 0;
sewardja1ac5cb2002-05-27 13:00:05 +00002703}
2704
sewardj2d8b3f02002-06-01 14:14:19 +00002705
sewardja1ac5cb2002-05-27 13:00:05 +00002706int pthread_rwlock_tryrdlock ( pthread_rwlock_t* orig )
2707{
2708 int res;
2709 vg_rwlock_t* rwl;
2710 if (0) printf ("pthread_rwlock_tryrdlock\n");
2711 rwl = rw_remap ( orig );
sewardj2d8b3f02002-06-01 14:14:19 +00002712 res = __pthread_mutex_lock(&rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00002713 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002714 if (!rwl->initted) {
2715 res = __pthread_mutex_unlock(&rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00002716 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002717 return EINVAL;
2718 }
2719 if (rwl->status == -1) {
2720 /* Writer active; we have to give up. */
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 EBUSY;
2724 }
2725 /* Success */
sewardj2d94c112002-06-03 01:25:54 +00002726 my_assert(rwl->status >= 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002727 rwl->status++;
2728 res = __pthread_mutex_unlock(&rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00002729 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002730 return 0;
sewardja1ac5cb2002-05-27 13:00:05 +00002731}
2732
sewardj2d8b3f02002-06-01 14:14:19 +00002733
2734static
2735void pthread_rwlock_wrlock_CANCEL_HDLR ( void* rwl_v )
2736{
2737 vg_rwlock_t* rwl = (vg_rwlock_t*)rwl_v;
2738 rwl->nwait_w--;
2739 pthread_mutex_unlock (&rwl->mx);
2740}
2741
2742
sewardja1ac5cb2002-05-27 13:00:05 +00002743int pthread_rwlock_wrlock ( pthread_rwlock_t* orig )
2744{
2745 int res;
2746 vg_rwlock_t* rwl;
2747 if (0) printf ("pthread_rwlock_wrlock\n");
2748 rwl = rw_remap ( orig );
sewardj2d8b3f02002-06-01 14:14:19 +00002749 res = __pthread_mutex_lock(&rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00002750 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002751 if (!rwl->initted) {
2752 res = __pthread_mutex_unlock(&rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00002753 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002754 return EINVAL;
2755 }
2756 if (rwl->status != 0) {
2757 rwl->nwait_w++;
2758 pthread_cleanup_push( pthread_rwlock_wrlock_CANCEL_HDLR, rwl );
2759 while (1) {
2760 if (rwl->status == 0) break;
2761 res = pthread_cond_wait(&rwl->cv_w, &rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00002762 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002763 }
2764 pthread_cleanup_pop(0);
2765 rwl->nwait_w--;
2766 }
sewardj2d94c112002-06-03 01:25:54 +00002767 my_assert(rwl->status == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002768 rwl->status = -1;
2769 res = __pthread_mutex_unlock(&rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00002770 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002771 return 0;
sewardja1ac5cb2002-05-27 13:00:05 +00002772}
2773
sewardj2d8b3f02002-06-01 14:14:19 +00002774
sewardja1ac5cb2002-05-27 13:00:05 +00002775int pthread_rwlock_trywrlock ( pthread_rwlock_t* orig )
2776{
2777 int res;
2778 vg_rwlock_t* rwl;
sewardj2d8b3f02002-06-01 14:14:19 +00002779 if (0) printf ("pthread_wrlock_trywrlock\n");
sewardja1ac5cb2002-05-27 13:00:05 +00002780 rwl = rw_remap ( orig );
sewardj2d8b3f02002-06-01 14:14:19 +00002781 res = __pthread_mutex_lock(&rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00002782 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002783 if (!rwl->initted) {
2784 res = __pthread_mutex_unlock(&rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00002785 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002786 return EINVAL;
2787 }
2788 if (rwl->status != 0) {
2789 /* Reader(s) or a writer active; we have to give up. */
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 EBUSY;
2793 }
2794 /* Success */
sewardj2d94c112002-06-03 01:25:54 +00002795 my_assert(rwl->status == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002796 rwl->status = -1;
2797 res = __pthread_mutex_unlock(&rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00002798 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002799 return 0;
sewardja1ac5cb2002-05-27 13:00:05 +00002800}
2801
sewardj2d8b3f02002-06-01 14:14:19 +00002802
sewardja1ac5cb2002-05-27 13:00:05 +00002803int pthread_rwlock_unlock ( pthread_rwlock_t* orig )
2804{
2805 int res;
2806 vg_rwlock_t* rwl;
2807 if (0) printf ("pthread_rwlock_unlock\n");
2808 rwl = rw_remap ( orig );
sewardj2d8b3f02002-06-01 14:14:19 +00002809 rwl = rw_remap ( orig );
2810 res = __pthread_mutex_lock(&rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00002811 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002812 if (!rwl->initted) {
2813 res = __pthread_mutex_unlock(&rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00002814 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002815 return EINVAL;
2816 }
2817 if (rwl->status == 0) {
2818 res = __pthread_mutex_unlock(&rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00002819 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002820 return EPERM;
2821 }
sewardj2d94c112002-06-03 01:25:54 +00002822 my_assert(rwl->status != 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002823 if (rwl->status == -1) {
2824 rwl->status = 0;
2825 } else {
sewardj2d94c112002-06-03 01:25:54 +00002826 my_assert(rwl->status > 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002827 rwl->status--;
2828 }
2829
sewardj2d94c112002-06-03 01:25:54 +00002830 my_assert(rwl->status >= 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002831
2832 if (rwl->prefer_w) {
2833
2834 /* Favour waiting writers, if any. */
2835 if (rwl->nwait_w > 0) {
2836 /* Writer(s) are waiting. */
2837 if (rwl->status == 0) {
2838 /* We can let a writer in. */
2839 res = pthread_cond_signal(&rwl->cv_w);
sewardj2d94c112002-06-03 01:25:54 +00002840 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002841 } else {
2842 /* There are still readers active. Do nothing; eventually
2843 they will disappear, at which point a writer will be
2844 admitted. */
2845 }
2846 }
2847 else
2848 /* No waiting writers. */
2849 if (rwl->nwait_r > 0) {
2850 /* Let in a waiting reader. */
2851 res = pthread_cond_signal(&rwl->cv_r);
sewardj2d94c112002-06-03 01:25:54 +00002852 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002853 }
2854
2855 } else {
2856
2857 /* Favour waiting readers, if any. */
2858 if (rwl->nwait_r > 0) {
2859 /* Reader(s) are waiting; let one in. */
2860 res = pthread_cond_signal(&rwl->cv_r);
sewardj2d94c112002-06-03 01:25:54 +00002861 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002862 }
2863 else
2864 /* No waiting readers. */
2865 if (rwl->nwait_w > 0 && rwl->status == 0) {
2866 /* We have waiting writers and no active readers; let a
2867 writer in. */
2868 res = pthread_cond_signal(&rwl->cv_w);
sewardj2d94c112002-06-03 01:25:54 +00002869 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002870 }
2871 }
2872
2873 res = __pthread_mutex_unlock(&rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00002874 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002875 return 0;
2876}
2877
2878
2879int pthread_rwlock_destroy ( pthread_rwlock_t *orig )
2880{
2881 int res;
2882 vg_rwlock_t* rwl;
2883 if (0) printf ("pthread_rwlock_destroy\n");
2884 rwl = rw_remap ( orig );
2885 res = __pthread_mutex_lock(&rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00002886 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002887 if (!rwl->initted) {
2888 res = __pthread_mutex_unlock(&rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00002889 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002890 return EINVAL;
2891 }
2892 if (rwl->status != 0 || rwl->nwait_r > 0 || rwl->nwait_w > 0) {
2893 res = __pthread_mutex_unlock(&rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00002894 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002895 return EBUSY;
2896 }
2897 rwl->initted = 0;
2898 res = __pthread_mutex_unlock(&rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00002899 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002900 return 0;
sewardja1ac5cb2002-05-27 13:00:05 +00002901}
2902
2903
sewardj47e4e312002-06-18 09:24:34 +00002904/* Copied directly from LinuxThreads. */
2905int
2906pthread_rwlockattr_init (pthread_rwlockattr_t *attr)
2907{
2908 attr->__lockkind = 0;
2909 attr->__pshared = PTHREAD_PROCESS_PRIVATE;
2910
2911 return 0;
2912}
2913
sewardjfe18eb82002-07-13 12:58:44 +00002914/* Copied directly from LinuxThreads. */
2915int
sewardj5706bfa2002-12-08 23:42:17 +00002916pthread_rwlockattr_destroy (pthread_rwlockattr_t *attr)
2917{
2918 return 0;
2919}
2920
2921/* Copied directly from LinuxThreads. */
2922int
sewardjfe18eb82002-07-13 12:58:44 +00002923pthread_rwlockattr_setpshared (pthread_rwlockattr_t *attr, int pshared)
2924{
2925 if (pshared != PTHREAD_PROCESS_PRIVATE && pshared != PTHREAD_PROCESS_SHARED)
2926 return EINVAL;
2927
2928 /* For now it is not possible to shared a conditional variable. */
2929 if (pshared != PTHREAD_PROCESS_PRIVATE)
2930 return ENOSYS;
2931
2932 attr->__pshared = pshared;
2933
2934 return 0;
2935}
2936
sewardj47e4e312002-06-18 09:24:34 +00002937
sewardja1ac5cb2002-05-27 13:00:05 +00002938/* ---------------------------------------------------------------------
sewardj11f0bb42003-04-26 20:11:15 +00002939 Make SYSV IPC not block everything -- pass to vg_intercept.c.
sewardjd5bef572002-10-23 21:49:33 +00002940 ------------------------------------------------------------------ */
2941
sewardj11f0bb42003-04-26 20:11:15 +00002942WEAK
2943int msgsnd(int msgid, const void *msgp, size_t msgsz, int msgflg)
sewardjd5bef572002-10-23 21:49:33 +00002944{
sewardj11f0bb42003-04-26 20:11:15 +00002945 return VGR_(msgsnd)(msgid, msgp, msgsz, msgflg);
sewardjd5bef572002-10-23 21:49:33 +00002946}
2947
sewardj11f0bb42003-04-26 20:11:15 +00002948WEAK
2949int msgrcv(int msqid, void* msgp, size_t msgsz,
2950 long msgtyp, int msgflg )
sewardjd5bef572002-10-23 21:49:33 +00002951{
sewardj11f0bb42003-04-26 20:11:15 +00002952 return VGR_(msgrcv)(msqid, msgp, msgsz, msgtyp, msgflg );
sewardjd5bef572002-10-23 21:49:33 +00002953}
2954
sewardj262b5be2003-04-26 21:19:53 +00002955
2956/* ---------------------------------------------------------------------
2957 The glibc sources say that returning -1 in these 3 functions
2958 causes real time signals not to be used.
2959 ------------------------------------------------------------------ */
2960
2961int __libc_current_sigrtmin (void)
2962{
2963 static int moans = N_MOANS;
2964 if (moans-- > 0)
2965 kludged("__libc_current_sigrtmin");
2966 return -1;
2967}
2968
2969int __libc_current_sigrtmax (void)
2970{
2971 static int moans = N_MOANS;
2972 if (moans-- > 0)
2973 kludged("__libc_current_sigrtmax");
2974 return -1;
2975}
2976
2977int __libc_allocate_rtsig (int high)
2978{
2979 static int moans = N_MOANS;
2980 if (moans-- > 0)
2981 kludged("__libc_allocate_rtsig");
2982 return -1;
2983}
2984
2985
sewardjd5bef572002-10-23 21:49:33 +00002986/* ---------------------------------------------------------------------
sewardj3b13f0e2002-04-25 20:17:29 +00002987 B'stard.
2988 ------------------------------------------------------------------ */
2989
2990# define strong_alias(name, aliasname) \
2991 extern __typeof (name) aliasname __attribute__ ((alias (#name)));
2992
sewardj5905fae2002-04-26 13:25:00 +00002993# define weak_alias(name, aliasname) \
2994 extern __typeof (name) aliasname __attribute__ ((weak, alias (#name)));
sewardj3b13f0e2002-04-25 20:17:29 +00002995
sewardj5905fae2002-04-26 13:25:00 +00002996strong_alias(__pthread_mutex_lock, pthread_mutex_lock)
2997strong_alias(__pthread_mutex_trylock, pthread_mutex_trylock)
2998strong_alias(__pthread_mutex_unlock, pthread_mutex_unlock)
2999strong_alias(__pthread_mutexattr_init, pthread_mutexattr_init)
3000 weak_alias(__pthread_mutexattr_settype, pthread_mutexattr_settype)
3001strong_alias(__pthread_mutex_init, pthread_mutex_init)
3002strong_alias(__pthread_mutexattr_destroy, pthread_mutexattr_destroy)
3003strong_alias(__pthread_mutex_destroy, pthread_mutex_destroy)
3004strong_alias(__pthread_once, pthread_once)
3005strong_alias(__pthread_atfork, pthread_atfork)
3006strong_alias(__pthread_key_create, pthread_key_create)
3007strong_alias(__pthread_getspecific, pthread_getspecific)
3008strong_alias(__pthread_setspecific, pthread_setspecific)
3009
sewardjd529a442002-05-04 19:49:21 +00003010#ifndef GLIBC_2_1
sewardj3b13f0e2002-04-25 20:17:29 +00003011strong_alias(sigaction, __sigaction)
sewardjd529a442002-05-04 19:49:21 +00003012#endif
3013
sewardj5905fae2002-04-26 13:25:00 +00003014strong_alias(close, __close)
sewardj3b13f0e2002-04-25 20:17:29 +00003015strong_alias(fcntl, __fcntl)
sewardj5905fae2002-04-26 13:25:00 +00003016strong_alias(lseek, __lseek)
3017strong_alias(open, __open)
3018strong_alias(open64, __open64)
sewardj5905fae2002-04-26 13:25:00 +00003019strong_alias(read, __read)
3020strong_alias(wait, __wait)
3021strong_alias(write, __write)
sewardj3b13f0e2002-04-25 20:17:29 +00003022strong_alias(connect, __connect)
sewardj5905fae2002-04-26 13:25:00 +00003023strong_alias(send, __send)
3024
sewardj726c4122002-05-16 23:39:10 +00003025weak_alias (__pread64, pread64)
sewardja18e2102002-05-18 10:43:22 +00003026weak_alias (__pwrite64, pwrite64)
sewardj5905fae2002-04-26 13:25:00 +00003027weak_alias(__fork, fork)
njn25e49d8e72002-09-23 09:36:25 +00003028weak_alias(__vfork, vfork)
sewardj7f6456d2002-05-21 00:51:21 +00003029
sewardjf0b06452002-06-04 08:38:04 +00003030weak_alias (__pthread_kill_other_threads_np, pthread_kill_other_threads_np)
sewardj3b13f0e2002-04-25 20:17:29 +00003031
3032/*--------------------------------------------------*/
3033
sewardj5905fae2002-04-26 13:25:00 +00003034weak_alias(pthread_rwlock_rdlock, __pthread_rwlock_rdlock)
sewardj5905fae2002-04-26 13:25:00 +00003035weak_alias(pthread_rwlock_unlock, __pthread_rwlock_unlock)
sewardj262b0292002-05-01 00:03:16 +00003036weak_alias(pthread_rwlock_wrlock, __pthread_rwlock_wrlock)
sewardj060b04f2002-04-26 21:01:13 +00003037
sewardja1ac5cb2002-05-27 13:00:05 +00003038weak_alias(pthread_rwlock_destroy, __pthread_rwlock_destroy)
3039weak_alias(pthread_rwlock_init, __pthread_rwlock_init)
3040weak_alias(pthread_rwlock_tryrdlock, __pthread_rwlock_tryrdlock)
3041weak_alias(pthread_rwlock_trywrlock, __pthread_rwlock_trywrlock)
3042
sewardj060b04f2002-04-26 21:01:13 +00003043
sewardj3b13f0e2002-04-25 20:17:29 +00003044/* I've no idea what these are, but they get called quite a lot.
3045 Anybody know? */
3046
3047#undef _IO_flockfile
3048void _IO_flockfile ( _IO_FILE * file )
3049{
sewardj853f55d2002-04-26 00:27:53 +00003050 pthread_mutex_lock(file->_lock);
sewardj3b13f0e2002-04-25 20:17:29 +00003051}
sewardj5905fae2002-04-26 13:25:00 +00003052weak_alias(_IO_flockfile, flockfile);
3053
sewardj3b13f0e2002-04-25 20:17:29 +00003054
3055#undef _IO_funlockfile
3056void _IO_funlockfile ( _IO_FILE * file )
3057{
sewardj853f55d2002-04-26 00:27:53 +00003058 pthread_mutex_unlock(file->_lock);
sewardj3b13f0e2002-04-25 20:17:29 +00003059}
sewardj5905fae2002-04-26 13:25:00 +00003060weak_alias(_IO_funlockfile, funlockfile);
3061
sewardj3b13f0e2002-04-25 20:17:29 +00003062
sewardjd4f2c712002-04-30 10:20:10 +00003063/* This doesn't seem to be needed to simulate libpthread.so's external
3064 interface, but many people complain about its absence. */
3065
3066strong_alias(__pthread_mutexattr_settype, __pthread_mutexattr_setkind_np)
3067weak_alias(__pthread_mutexattr_setkind_np, pthread_mutexattr_setkind_np)
sewardj439d45e2002-05-03 20:43:10 +00003068
3069
3070/*--------------------------------------------------------------------*/
3071/*--- end vg_libpthread.c ---*/
3072/*--------------------------------------------------------------------*/