blob: 21646f3da8a0c96fceb734a9ffaafb85314503e9 [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 int res;
181 char buf[1000];
sewardje663cb92002-04-12 10:26:32 +0000182 buf[0] = 0;
sewardj439d45e2002-05-03 20:43:10 +0000183 strcat(buf, "\nvalgrind's libpthread.so: ");
sewardje663cb92002-04-12 10:26:32 +0000184 strcat(buf, str);
185 strcat(buf, "\n\n");
sewardj69a72a52002-11-03 13:41:41 +0000186 VALGRIND_MAGIC_SEQUENCE(res, 0, /* irrelevant default */
187 VG_USERREQ__LOGMESSAGE, buf, 0, 0, 0);
sewardj2d94c112002-06-03 01:25:54 +0000188 my_exit(1);
sewardj3b5d8862002-04-20 13:53:23 +0000189 /* We have to persuade gcc into believing this doesn't return. */
190 while (1) { };
sewardje663cb92002-04-12 10:26:32 +0000191}
192
193
sewardj69a72a52002-11-03 13:41:41 +0000194static void cat_n_send ( char* pre, char* msg )
sewardj2a3d28c2002-04-14 13:27:00 +0000195{
sewardj69a72a52002-11-03 13:41:41 +0000196 char buf[1000];
197 int res;
sewardj436e0582002-04-26 14:31:40 +0000198 if (get_pt_trace_level() >= 0) {
sewardj69a72a52002-11-03 13:41:41 +0000199 snprintf(buf, sizeof(buf), "%s%s", pre, msg );
200 buf[sizeof(buf)-1] = '\0';
201 VALGRIND_MAGIC_SEQUENCE(res, 0, /* irrelevant default */
202 VG_USERREQ__LOGMESSAGE, buf, 0, 0, 0);
sewardj45b4b372002-04-16 22:50:32 +0000203 }
sewardj2a3d28c2002-04-14 13:27:00 +0000204}
205
sewardj69a72a52002-11-03 13:41:41 +0000206static void ignored ( char* msg )
207{
208 cat_n_send ( "valgrind's libpthread.so: IGNORED call to: ", msg );
209}
210
211
sewardj30671ff2002-04-21 00:13:57 +0000212static void kludged ( char* msg )
213{
sewardj69a72a52002-11-03 13:41:41 +0000214 cat_n_send ( "valgrind's libpthread.so: KLUDGED call to: ", msg );
sewardj439d45e2002-05-03 20:43:10 +0000215}
216
sewardj69a72a52002-11-03 13:41:41 +0000217
sewardjccef2e62002-05-29 19:26:32 +0000218__attribute__((noreturn))
sewardj3b13f0e2002-04-25 20:17:29 +0000219void vgPlain_unimp ( char* what )
220{
sewardj69a72a52002-11-03 13:41:41 +0000221 cat_n_send (
222 "valgrind's libpthread.so: UNIMPLEMENTED FUNCTION: ", what );
sewardj3b13f0e2002-04-25 20:17:29 +0000223 barf("Please report this bug to me at: jseward@acm.org");
224}
225
sewardje663cb92002-04-12 10:26:32 +0000226
sewardj457cc472002-06-03 23:13:47 +0000227static
sewardj2d94c112002-06-03 01:25:54 +0000228void my_assert_fail ( Char* expr, Char* file, Int line, Char* fn )
229{
sewardj69a72a52002-11-03 13:41:41 +0000230 char buf[1000];
sewardj2d94c112002-06-03 01:25:54 +0000231 static Bool entered = False;
232 if (entered)
233 my_exit(2);
234 entered = True;
sewardj69a72a52002-11-03 13:41:41 +0000235 sprintf(buf, "\n%s: %s:%d (%s): Assertion `%s' failed.\n",
236 "valgrind", file, line, fn, expr );
237 cat_n_send ( "", buf );
238 sprintf(buf, "Please report this bug to me at: %s\n\n",
239 VG_EMAIL_ADDR);
240 cat_n_send ( "", buf );
sewardj2d94c112002-06-03 01:25:54 +0000241 my_exit(1);
242}
243
244#define MY__STRING(__str) #__str
245
246#define my_assert(expr) \
247 ((void) ((expr) ? 0 : \
248 (my_assert_fail (MY__STRING(expr), \
249 __FILE__, __LINE__, \
250 __PRETTY_FUNCTION__), 0)))
251
sewardj00a66b12002-10-12 16:42:35 +0000252static
253void my_free ( void* ptr )
254{
255 int res;
256 VALGRIND_MAGIC_SEQUENCE(res, (-1) /* default */,
257 VG_USERREQ__FREE, ptr, 0, 0, 0);
258 my_assert(res == 0);
259}
260
261
262static
263void* my_malloc ( int nbytes )
264{
265 void* res;
266 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
267 VG_USERREQ__MALLOC, nbytes, 0, 0, 0);
268 my_assert(res != (void*)0);
269 return res;
270}
271
272
sewardj2d94c112002-06-03 01:25:54 +0000273
sewardje663cb92002-04-12 10:26:32 +0000274/* ---------------------------------------------------------------------
275 Pass pthread_ calls to Valgrind's request mechanism.
276 ------------------------------------------------------------------ */
277
sewardjf8f819e2002-04-17 23:21:37 +0000278#include <errno.h>
sewardj5f07b662002-04-23 16:52:51 +0000279#include <sys/time.h> /* gettimeofday */
sewardjf8f819e2002-04-17 23:21:37 +0000280
sewardja1ac5cb2002-05-27 13:00:05 +0000281
sewardjf8f819e2002-04-17 23:21:37 +0000282/* ---------------------------------------------------
sewardj4dced352002-06-04 22:54:20 +0000283 Ummm ..
284 ------------------------------------------------ */
285
286static
287void pthread_error ( const char* msg )
288{
289 int res;
290 VALGRIND_MAGIC_SEQUENCE(res, 0,
291 VG_USERREQ__PTHREAD_ERROR,
292 msg, 0, 0, 0);
293}
294
295
296/* ---------------------------------------------------
sewardj00a66b12002-10-12 16:42:35 +0000297 Here so it can be inlined without complaint.
298 ------------------------------------------------ */
299
300__inline__
301pthread_t pthread_self(void)
302{
303 int tid;
304 ensure_valgrind("pthread_self");
305 VALGRIND_MAGIC_SEQUENCE(tid, 0 /* default */,
306 VG_USERREQ__PTHREAD_GET_THREADID,
307 0, 0, 0, 0);
308 if (tid < 1 || tid >= VG_N_THREADS)
309 barf("pthread_self: invalid ThreadId");
310 return tid;
311}
312
313
314/* ---------------------------------------------------
sewardjf8f819e2002-04-17 23:21:37 +0000315 THREAD ATTRIBUTES
316 ------------------------------------------------ */
317
sewardj6af4b5d2002-04-16 04:40:49 +0000318int pthread_attr_init(pthread_attr_t *attr)
319{
sewardj7989d0c2002-05-28 11:00:01 +0000320 /* Just initialise the fields which we might look at. */
321 attr->__detachstate = PTHREAD_CREATE_JOINABLE;
sewardj111b14c2002-10-20 16:22:57 +0000322 /* Linuxthreads sets this field to the value __getpagesize(), so I
323 guess the following is OK. */
324 attr->__guardsize = VKI_BYTES_PER_PAGE; return 0;
sewardj6af4b5d2002-04-16 04:40:49 +0000325}
326
327int pthread_attr_setdetachstate(pthread_attr_t *attr, int detachstate)
328{
sewardj7989d0c2002-05-28 11:00:01 +0000329 if (detachstate != PTHREAD_CREATE_JOINABLE
sewardj4dced352002-06-04 22:54:20 +0000330 && detachstate != PTHREAD_CREATE_DETACHED) {
331 pthread_error("pthread_attr_setdetachstate: "
332 "detachstate is invalid");
sewardj7989d0c2002-05-28 11:00:01 +0000333 return EINVAL;
sewardj4dced352002-06-04 22:54:20 +0000334 }
sewardj7989d0c2002-05-28 11:00:01 +0000335 attr->__detachstate = detachstate;
sewardj6af4b5d2002-04-16 04:40:49 +0000336 return 0;
337}
338
njn25e49d8e72002-09-23 09:36:25 +0000339int pthread_attr_getdetachstate(const pthread_attr_t *attr, int *detachstate)
340{
341 *detachstate = attr->__detachstate;
342 return 0;
343}
344
sewardj30671ff2002-04-21 00:13:57 +0000345int pthread_attr_setinheritsched(pthread_attr_t *attr, int inherit)
346{
sewardj436e0582002-04-26 14:31:40 +0000347 static int moans = N_MOANS;
348 if (moans-- > 0)
349 ignored("pthread_attr_setinheritsched");
sewardj30671ff2002-04-21 00:13:57 +0000350 return 0;
351}
sewardj6af4b5d2002-04-16 04:40:49 +0000352
sewardj11f0bb42003-04-26 20:11:15 +0000353WEAK
sewardj0286dd52002-05-16 20:51:15 +0000354int pthread_attr_setstacksize (pthread_attr_t *__attr,
355 size_t __stacksize)
356{
sewardja18e2102002-05-18 10:43:22 +0000357 size_t limit;
sewardj3d7c8d62002-06-04 20:59:16 +0000358 char buf[1024];
sewardj0286dd52002-05-16 20:51:15 +0000359 ensure_valgrind("pthread_attr_setstacksize");
sewardja18e2102002-05-18 10:43:22 +0000360 limit = VG_PTHREAD_STACK_SIZE - VG_AR_CLIENT_STACKBASE_REDZONE_SZB
361 - 1000; /* paranoia */
362 if (__stacksize < limit)
sewardj0286dd52002-05-16 20:51:15 +0000363 return 0;
sewardj3d7c8d62002-06-04 20:59:16 +0000364 snprintf(buf, sizeof(buf), "pthread_attr_setstacksize: "
365 "requested size %d >= VG_PTHREAD_STACK_SIZE\n "
366 "edit vg_include.h and rebuild.", __stacksize);
367 buf[sizeof(buf)-1] = '\0'; /* Make sure it is zero terminated */
368 barf(buf);
sewardj0286dd52002-05-16 20:51:15 +0000369}
370
371
sewardj30671ff2002-04-21 00:13:57 +0000372/* This is completely bogus. */
373int pthread_attr_getschedparam(const pthread_attr_t *attr,
374 struct sched_param *param)
375{
sewardj436e0582002-04-26 14:31:40 +0000376 static int moans = N_MOANS;
377 if (moans-- > 0)
378 kludged("pthread_attr_getschedparam");
sewardj3e909ce2002-06-03 13:27:15 +0000379# ifdef HAVE_SCHED_PRIORITY
sewardj72d58482002-04-24 02:20:20 +0000380 if (param) param->sched_priority = 0; /* who knows */
381# else
sewardj30671ff2002-04-21 00:13:57 +0000382 if (param) param->__sched_priority = 0; /* who knows */
sewardj72d58482002-04-24 02:20:20 +0000383# endif
sewardj30671ff2002-04-21 00:13:57 +0000384 return 0;
385}
386
387int pthread_attr_setschedparam(pthread_attr_t *attr,
388 const struct sched_param *param)
389{
sewardj436e0582002-04-26 14:31:40 +0000390 static int moans = N_MOANS;
391 if (moans-- > 0)
392 ignored("pthread_attr_setschedparam");
sewardj30671ff2002-04-21 00:13:57 +0000393 return 0;
394}
395
396int pthread_attr_destroy(pthread_attr_t *attr)
397{
sewardj436e0582002-04-26 14:31:40 +0000398 static int moans = N_MOANS;
399 if (moans-- > 0)
400 ignored("pthread_attr_destroy");
sewardj30671ff2002-04-21 00:13:57 +0000401 return 0;
402}
sewardjf8f819e2002-04-17 23:21:37 +0000403
sewardj0d844232002-06-02 09:29:31 +0000404/* These are no-ops, as with LinuxThreads. */
405int pthread_attr_setscope ( pthread_attr_t *attr, int scope )
406{
407 ensure_valgrind("pthread_attr_setscope");
408 if (scope == PTHREAD_SCOPE_SYSTEM)
409 return 0;
sewardj4dced352002-06-04 22:54:20 +0000410 pthread_error("pthread_attr_setscope: "
411 "invalid or unsupported scope");
sewardj0d844232002-06-02 09:29:31 +0000412 if (scope == PTHREAD_SCOPE_PROCESS)
413 return ENOTSUP;
414 return EINVAL;
415}
416
417int pthread_attr_getscope ( const pthread_attr_t *attr, int *scope )
418{
419 ensure_valgrind("pthread_attr_setscope");
420 if (scope)
421 *scope = PTHREAD_SCOPE_SYSTEM;
422 return 0;
423}
424
sewardj64039bb2002-06-03 00:58:18 +0000425
426/* Pretty bogus. Avoid if possible. */
427int pthread_getattr_np (pthread_t thread, pthread_attr_t *attr)
428{
429 int detached;
430 size_t limit;
431 ensure_valgrind("pthread_getattr_np");
432 kludged("pthread_getattr_np");
433 limit = VG_PTHREAD_STACK_SIZE - VG_AR_CLIENT_STACKBASE_REDZONE_SZB
434 - 1000; /* paranoia */
435 attr->__detachstate = PTHREAD_CREATE_JOINABLE;
436 attr->__schedpolicy = SCHED_OTHER;
437 attr->__schedparam.sched_priority = 0;
438 attr->__inheritsched = PTHREAD_EXPLICIT_SCHED;
439 attr->__scope = PTHREAD_SCOPE_SYSTEM;
440 attr->__guardsize = VKI_BYTES_PER_PAGE;
441 attr->__stackaddr = NULL;
442 attr->__stackaddr_set = 0;
443 attr->__stacksize = limit;
444 VALGRIND_MAGIC_SEQUENCE(detached, (-1) /* default */,
445 VG_USERREQ__SET_OR_GET_DETACH,
446 2 /* get */, thread, 0, 0);
sewardj2d94c112002-06-03 01:25:54 +0000447 my_assert(detached == 0 || detached == 1);
sewardj64039bb2002-06-03 00:58:18 +0000448 if (detached)
449 attr->__detachstate = PTHREAD_CREATE_DETACHED;
450 return 0;
451}
452
453
454/* Bogus ... */
sewardj11f0bb42003-04-26 20:11:15 +0000455WEAK
sewardj64039bb2002-06-03 00:58:18 +0000456int pthread_attr_getstackaddr ( const pthread_attr_t * attr,
457 void ** stackaddr )
458{
459 ensure_valgrind("pthread_attr_getstackaddr");
460 kludged("pthread_attr_getstackaddr");
461 if (stackaddr)
462 *stackaddr = NULL;
463 return 0;
464}
465
466/* Not bogus (!) */
sewardj11f0bb42003-04-26 20:11:15 +0000467WEAK
sewardj64039bb2002-06-03 00:58:18 +0000468int pthread_attr_getstacksize ( const pthread_attr_t * _attr,
469 size_t * __stacksize )
470{
471 size_t limit;
472 ensure_valgrind("pthread_attr_getstacksize");
473 limit = VG_PTHREAD_STACK_SIZE - VG_AR_CLIENT_STACKBASE_REDZONE_SZB
474 - 1000; /* paranoia */
475 if (__stacksize)
476 *__stacksize = limit;
477 return 0;
478}
479
sewardja3be12f2002-06-17 12:19:44 +0000480int pthread_attr_setschedpolicy(pthread_attr_t *attr, int policy)
481{
482 if (policy != SCHED_OTHER && policy != SCHED_FIFO && policy != SCHED_RR)
483 return EINVAL;
484 attr->__schedpolicy = policy;
485 return 0;
486}
487
488int pthread_attr_getschedpolicy(const pthread_attr_t *attr, int *policy)
489{
490 *policy = attr->__schedpolicy;
491 return 0;
492}
493
494
sewardj111b14c2002-10-20 16:22:57 +0000495/* This is completely bogus. We reject all attempts to change it from
496 VKI_BYTES_PER_PAGE. I don't have a clue what it's for so it seems
497 safest to be paranoid. */
sewardj11f0bb42003-04-26 20:11:15 +0000498WEAK
sewardj111b14c2002-10-20 16:22:57 +0000499int pthread_attr_setguardsize(pthread_attr_t *attr, size_t guardsize)
500{
501 static int moans = N_MOANS;
502
503 if (guardsize == VKI_BYTES_PER_PAGE)
504 return 0;
505
506 if (moans-- > 0)
507 ignored("pthread_attr_setguardsize: ignoring guardsize != 4096");
508
509 return 0;
510}
511
512/* A straight copy of the LinuxThreads code. */
sewardj11f0bb42003-04-26 20:11:15 +0000513WEAK
sewardj111b14c2002-10-20 16:22:57 +0000514int pthread_attr_getguardsize(const pthread_attr_t *attr, size_t *guardsize)
515{
516 *guardsize = attr->__guardsize;
517 return 0;
518}
519
sewardjab2e1232002-12-26 12:16:11 +0000520/* Again, like LinuxThreads. */
521
522static int concurrency_current_level = 0;
523
sewardj11f0bb42003-04-26 20:11:15 +0000524WEAK
sewardjb34e4db2002-12-08 23:51:32 +0000525int pthread_setconcurrency(int new_level)
526{
527 if (new_level < 0)
528 return EINVAL;
sewardjab2e1232002-12-26 12:16:11 +0000529 else {
530 concurrency_current_level = new_level;
sewardjb34e4db2002-12-08 23:51:32 +0000531 return 0;
sewardjab2e1232002-12-26 12:16:11 +0000532 }
sewardjb34e4db2002-12-08 23:51:32 +0000533}
534
sewardj11f0bb42003-04-26 20:11:15 +0000535WEAK
sewardjab2e1232002-12-26 12:16:11 +0000536int pthread_getconcurrency(void)
537{
538 return concurrency_current_level;
539}
540
541
sewardj111b14c2002-10-20 16:22:57 +0000542
sewardj20917d82002-05-28 01:36:45 +0000543/* ---------------------------------------------------
544 Helper functions for running a thread
545 and for clearing up afterwards.
546 ------------------------------------------------ */
547
548/* All exiting threads eventually pass through here, bearing the
549 return value, or PTHREAD_CANCELED, in ret_val. */
550static
551__attribute__((noreturn))
552void thread_exit_wrapper ( void* ret_val )
553{
sewardj870497a2002-05-29 01:06:47 +0000554 int detached, res;
555 CleanupEntry cu;
556 pthread_key_t key;
sewardj00a66b12002-10-12 16:42:35 +0000557 void** specifics_ptr;
sewardj870497a2002-05-29 01:06:47 +0000558
sewardj20917d82002-05-28 01:36:45 +0000559 /* Run this thread's cleanup handlers. */
sewardj8ad94e12002-05-29 00:10:20 +0000560 while (1) {
561 VALGRIND_MAGIC_SEQUENCE(res, (-1) /* default */,
562 VG_USERREQ__CLEANUP_POP,
563 &cu, 0, 0, 0);
564 if (res == -1) break; /* stack empty */
sewardj2d94c112002-06-03 01:25:54 +0000565 my_assert(res == 0);
sewardj8ad94e12002-05-29 00:10:20 +0000566 if (0) printf("running exit cleanup handler");
567 cu.fn ( cu.arg );
568 }
569
sewardj870497a2002-05-29 01:06:47 +0000570 /* Run this thread's key finalizers. Really this should be run
571 PTHREAD_DESTRUCTOR_ITERATIONS times. */
572 for (key = 0; key < VG_N_THREAD_KEYS; key++) {
573 VALGRIND_MAGIC_SEQUENCE(res, (-2) /* default */,
574 VG_USERREQ__GET_KEY_D_AND_S,
575 key, &cu, 0, 0 );
576 if (res == 0) {
577 /* valid key */
578 if (cu.fn && cu.arg)
579 cu.fn /* destructor for key */
580 ( cu.arg /* specific for key for this thread */ );
581 continue;
582 }
sewardj2d94c112002-06-03 01:25:54 +0000583 my_assert(res == -1);
sewardj870497a2002-05-29 01:06:47 +0000584 }
sewardj20917d82002-05-28 01:36:45 +0000585
sewardj00a66b12002-10-12 16:42:35 +0000586 /* Free up my specifics space, if any. */
587 VALGRIND_MAGIC_SEQUENCE(specifics_ptr, 3 /* default */,
588 VG_USERREQ__PTHREAD_GETSPECIFIC_PTR,
589 pthread_self(), 0, 0, 0);
590 my_assert(specifics_ptr != (void**)3);
591 my_assert(specifics_ptr != (void**)1); /* 1 means invalid thread */
592 if (specifics_ptr != NULL)
593 my_free(specifics_ptr);
594
sewardj20917d82002-05-28 01:36:45 +0000595 /* Decide on my final disposition. */
596 VALGRIND_MAGIC_SEQUENCE(detached, (-1) /* default */,
597 VG_USERREQ__SET_OR_GET_DETACH,
sewardj7989d0c2002-05-28 11:00:01 +0000598 2 /* get */, pthread_self(), 0, 0);
sewardj2d94c112002-06-03 01:25:54 +0000599 my_assert(detached == 0 || detached == 1);
sewardj20917d82002-05-28 01:36:45 +0000600
601 if (detached) {
602 /* Detached; I just quit right now. */
603 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
604 VG_USERREQ__QUIT, 0, 0, 0, 0);
605 } else {
606 /* Not detached; so I wait for a joiner. */
607 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
608 VG_USERREQ__WAIT_JOINER, ret_val, 0, 0, 0);
609 }
610 /* NOTREACHED */
611 barf("thread_exit_wrapper: still alive?!");
612}
613
614
615/* This function is a wrapper function for running a thread. It runs
616 the root function specified in pthread_create, and then, should the
617 root function return a value, it arranges to run the thread's
618 cleanup handlers and exit correctly. */
619
sewardj728a5272002-06-20 10:25:37 +0000620/* Struct used to convey info from pthread_create to thread_wrapper.
621 Must be careful not to pass to the child thread any pointers to
622 objects which might be on the parent's stack. */
sewardj20917d82002-05-28 01:36:45 +0000623typedef
624 struct {
sewardj728a5272002-06-20 10:25:37 +0000625 int attr__detachstate;
sewardj20917d82002-05-28 01:36:45 +0000626 void* (*root_fn) ( void* );
627 void* arg;
628 }
629 NewThreadInfo;
630
631
632/* This is passed to the VG_USERREQ__APPLY_IN_NEW_THREAD and so must
633 not return. Note that this runs in the new thread, not the
634 parent. */
635static
636__attribute__((noreturn))
637void thread_wrapper ( NewThreadInfo* info )
638{
sewardj728a5272002-06-20 10:25:37 +0000639 int attr__detachstate;
sewardj20917d82002-05-28 01:36:45 +0000640 void* (*root_fn) ( void* );
641 void* arg;
642 void* ret_val;
643
sewardj728a5272002-06-20 10:25:37 +0000644 attr__detachstate = info->attr__detachstate;
645 root_fn = info->root_fn;
646 arg = info->arg;
sewardj20917d82002-05-28 01:36:45 +0000647
sewardj20917d82002-05-28 01:36:45 +0000648 /* Free up the arg block that pthread_create malloced. */
sewardj00a66b12002-10-12 16:42:35 +0000649 my_free(info);
sewardj20917d82002-05-28 01:36:45 +0000650
sewardj7989d0c2002-05-28 11:00:01 +0000651 /* Minimally observe the attributes supplied. */
sewardj728a5272002-06-20 10:25:37 +0000652 if (attr__detachstate != PTHREAD_CREATE_DETACHED
653 && attr__detachstate != PTHREAD_CREATE_JOINABLE)
654 pthread_error("thread_wrapper: invalid attr->__detachstate");
655 if (attr__detachstate == PTHREAD_CREATE_DETACHED)
656 pthread_detach(pthread_self());
sewardj7989d0c2002-05-28 11:00:01 +0000657
sewardj00a66b12002-10-12 16:42:35 +0000658# ifdef GLIBC_2_3
659 /* Set this thread's locale to the global (default) locale. A hack
660 in support of glibc-2.3. This does the biz for the all new
661 threads; the root thread is done with a horrible hack in
662 init_libc_tsd_keys() below.
663 */
664 __uselocale(LC_GLOBAL_LOCALE);
665# endif
666
sewardj20917d82002-05-28 01:36:45 +0000667 /* The root function might not return. But if it does we simply
668 move along to thread_exit_wrapper. All other ways out for the
669 thread (cancellation, or calling pthread_exit) lead there
670 too. */
671 ret_val = root_fn(arg);
672 thread_exit_wrapper(ret_val);
673 /* NOTREACHED */
674}
675
676
sewardjf8f819e2002-04-17 23:21:37 +0000677/* ---------------------------------------------------
678 THREADs
679 ------------------------------------------------ */
680
sewardj11f0bb42003-04-26 20:11:15 +0000681WEAK
sewardjff42d1d2002-05-22 13:17:31 +0000682int pthread_yield ( void )
683{
684 int res;
685 ensure_valgrind("pthread_yield");
686 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
687 VG_USERREQ__PTHREAD_YIELD, 0, 0, 0, 0);
688 return 0;
689}
690
691
sewardj6072c362002-04-19 14:40:57 +0000692int pthread_equal(pthread_t thread1, pthread_t thread2)
693{
694 return thread1 == thread2 ? 1 : 0;
695}
696
697
sewardj20917d82002-05-28 01:36:45 +0000698/* Bundle up the args into a malloc'd block and create a new thread
699 consisting of thread_wrapper() applied to said malloc'd block. */
sewardje663cb92002-04-12 10:26:32 +0000700int
sewardj1462c8b2002-07-24 09:41:52 +0000701pthread_create (pthread_t *__restrict __thredd,
sewardje663cb92002-04-12 10:26:32 +0000702 __const pthread_attr_t *__restrict __attr,
703 void *(*__start_routine) (void *),
704 void *__restrict __arg)
705{
sewardj20917d82002-05-28 01:36:45 +0000706 int tid_child;
707 NewThreadInfo* info;
sewardje663cb92002-04-12 10:26:32 +0000708
sewardj20917d82002-05-28 01:36:45 +0000709 ensure_valgrind("pthread_create");
710
sewardj00a66b12002-10-12 16:42:35 +0000711 /* make sure the tsd keys, and hence locale info, are initialised
712 before we get into complications making new threads. */
713 init_libc_tsd_keys();
714
sewardj20917d82002-05-28 01:36:45 +0000715 /* Allocate space for the arg block. thread_wrapper will free
716 it. */
sewardj00a66b12002-10-12 16:42:35 +0000717 info = my_malloc(sizeof(NewThreadInfo));
sewardj2d94c112002-06-03 01:25:54 +0000718 my_assert(info != NULL);
sewardj20917d82002-05-28 01:36:45 +0000719
sewardj728a5272002-06-20 10:25:37 +0000720 if (__attr)
721 info->attr__detachstate = __attr->__detachstate;
722 else
723 info->attr__detachstate = PTHREAD_CREATE_JOINABLE;
724
sewardj20917d82002-05-28 01:36:45 +0000725 info->root_fn = __start_routine;
726 info->arg = __arg;
727 VALGRIND_MAGIC_SEQUENCE(tid_child, VG_INVALID_THREADID /* default */,
728 VG_USERREQ__APPLY_IN_NEW_THREAD,
729 &thread_wrapper, info, 0, 0);
sewardj2d94c112002-06-03 01:25:54 +0000730 my_assert(tid_child != VG_INVALID_THREADID);
sewardj20917d82002-05-28 01:36:45 +0000731
sewardj1462c8b2002-07-24 09:41:52 +0000732 if (__thredd)
733 *__thredd = tid_child;
sewardj20917d82002-05-28 01:36:45 +0000734 return 0; /* success */
735}
sewardje663cb92002-04-12 10:26:32 +0000736
737
738int
739pthread_join (pthread_t __th, void **__thread_return)
740{
741 int res;
742 ensure_valgrind("pthread_join");
743 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
744 VG_USERREQ__PTHREAD_JOIN,
745 __th, __thread_return, 0, 0);
746 return res;
747}
748
749
sewardj3b5d8862002-04-20 13:53:23 +0000750void pthread_exit(void *retval)
751{
sewardj3b5d8862002-04-20 13:53:23 +0000752 ensure_valgrind("pthread_exit");
sewardj20917d82002-05-28 01:36:45 +0000753 /* Simple! */
754 thread_exit_wrapper(retval);
sewardj3b5d8862002-04-20 13:53:23 +0000755}
756
sewardje663cb92002-04-12 10:26:32 +0000757
sewardj853f55d2002-04-26 00:27:53 +0000758int pthread_detach(pthread_t th)
759{
sewardj20917d82002-05-28 01:36:45 +0000760 int res;
761 ensure_valgrind("pthread_detach");
sewardj7989d0c2002-05-28 11:00:01 +0000762 /* First we enquire as to the current detach state. */
763 VALGRIND_MAGIC_SEQUENCE(res, (-2) /* default */,
sewardj20917d82002-05-28 01:36:45 +0000764 VG_USERREQ__SET_OR_GET_DETACH,
sewardj7989d0c2002-05-28 11:00:01 +0000765 2 /* get */, th, 0, 0);
sewardj4dced352002-06-04 22:54:20 +0000766 if (res == -1) {
767 /* not found */
768 pthread_error("pthread_detach: "
769 "invalid target thread");
sewardj7989d0c2002-05-28 11:00:01 +0000770 return ESRCH;
sewardj4dced352002-06-04 22:54:20 +0000771 }
772 if (res == 1) {
773 /* already detached */
774 pthread_error("pthread_detach: "
775 "target thread is already detached");
sewardj7989d0c2002-05-28 11:00:01 +0000776 return EINVAL;
sewardj4dced352002-06-04 22:54:20 +0000777 }
sewardj7989d0c2002-05-28 11:00:01 +0000778 if (res == 0) {
779 VALGRIND_MAGIC_SEQUENCE(res, (-2) /* default */,
780 VG_USERREQ__SET_OR_GET_DETACH,
781 1 /* set */, th, 0, 0);
sewardj2d94c112002-06-03 01:25:54 +0000782 my_assert(res == 0);
sewardj7989d0c2002-05-28 11:00:01 +0000783 return 0;
784 }
785 barf("pthread_detach");
sewardj853f55d2002-04-26 00:27:53 +0000786}
787
788
sewardjf8f819e2002-04-17 23:21:37 +0000789/* ---------------------------------------------------
sewardj8ad94e12002-05-29 00:10:20 +0000790 CLEANUP STACKS
791 ------------------------------------------------ */
792
793void _pthread_cleanup_push (struct _pthread_cleanup_buffer *__buffer,
794 void (*__routine) (void *),
795 void *__arg)
796{
797 int res;
798 CleanupEntry cu;
799 ensure_valgrind("_pthread_cleanup_push");
800 cu.fn = __routine;
801 cu.arg = __arg;
802 VALGRIND_MAGIC_SEQUENCE(res, (-1) /* default */,
803 VG_USERREQ__CLEANUP_PUSH,
804 &cu, 0, 0, 0);
sewardj2d94c112002-06-03 01:25:54 +0000805 my_assert(res == 0);
sewardj8ad94e12002-05-29 00:10:20 +0000806}
807
808
809void _pthread_cleanup_push_defer (struct _pthread_cleanup_buffer *__buffer,
810 void (*__routine) (void *),
811 void *__arg)
812{
813 /* As _pthread_cleanup_push, but first save the thread's original
814 cancellation type in __buffer and set it to Deferred. */
815 int orig_ctype;
816 ensure_valgrind("_pthread_cleanup_push_defer");
817 /* Set to Deferred, and put the old cancellation type in res. */
sewardj2d94c112002-06-03 01:25:54 +0000818 my_assert(-1 != PTHREAD_CANCEL_DEFERRED);
819 my_assert(-1 != PTHREAD_CANCEL_ASYNCHRONOUS);
820 my_assert(sizeof(struct _pthread_cleanup_buffer) >= sizeof(int));
sewardj8ad94e12002-05-29 00:10:20 +0000821 VALGRIND_MAGIC_SEQUENCE(orig_ctype, (-1) /* default */,
822 VG_USERREQ__SET_CANCELTYPE,
823 PTHREAD_CANCEL_DEFERRED, 0, 0, 0);
sewardj2d94c112002-06-03 01:25:54 +0000824 my_assert(orig_ctype != -1);
sewardj8ad94e12002-05-29 00:10:20 +0000825 *((int*)(__buffer)) = orig_ctype;
826 /* Now push the cleanup. */
827 _pthread_cleanup_push(NULL, __routine, __arg);
828}
829
830
831void _pthread_cleanup_pop (struct _pthread_cleanup_buffer *__buffer,
832 int __execute)
833{
834 int res;
835 CleanupEntry cu;
836 ensure_valgrind("_pthread_cleanup_push");
837 cu.fn = cu.arg = NULL; /* paranoia */
838 VALGRIND_MAGIC_SEQUENCE(res, (-1) /* default */,
839 VG_USERREQ__CLEANUP_POP,
840 &cu, 0, 0, 0);
841 if (res == 0) {
842 /* pop succeeded */
843 if (__execute) {
844 cu.fn ( cu.arg );
845 }
846 return;
847 }
848 if (res == -1) {
849 /* stack underflow */
850 return;
851 }
852 barf("_pthread_cleanup_pop");
853}
854
855
856void _pthread_cleanup_pop_restore (struct _pthread_cleanup_buffer *__buffer,
857 int __execute)
858{
859 int orig_ctype, fake_ctype;
860 /* As _pthread_cleanup_pop, but after popping/running the handler,
861 restore the thread's original cancellation type from the first
862 word of __buffer. */
863 _pthread_cleanup_pop(NULL, __execute);
864 orig_ctype = *((int*)(__buffer));
sewardj2d94c112002-06-03 01:25:54 +0000865 my_assert(orig_ctype == PTHREAD_CANCEL_DEFERRED
sewardj8ad94e12002-05-29 00:10:20 +0000866 || orig_ctype == PTHREAD_CANCEL_ASYNCHRONOUS);
sewardj2d94c112002-06-03 01:25:54 +0000867 my_assert(-1 != PTHREAD_CANCEL_DEFERRED);
868 my_assert(-1 != PTHREAD_CANCEL_ASYNCHRONOUS);
869 my_assert(sizeof(struct _pthread_cleanup_buffer) >= sizeof(int));
sewardj8ad94e12002-05-29 00:10:20 +0000870 VALGRIND_MAGIC_SEQUENCE(fake_ctype, (-1) /* default */,
871 VG_USERREQ__SET_CANCELTYPE,
872 orig_ctype, 0, 0, 0);
sewardj2d94c112002-06-03 01:25:54 +0000873 my_assert(fake_ctype == PTHREAD_CANCEL_DEFERRED);
sewardj8ad94e12002-05-29 00:10:20 +0000874}
875
876
877/* ---------------------------------------------------
sewardjf8f819e2002-04-17 23:21:37 +0000878 MUTEX ATTRIBUTES
879 ------------------------------------------------ */
880
sewardj5905fae2002-04-26 13:25:00 +0000881int __pthread_mutexattr_init(pthread_mutexattr_t *attr)
sewardje663cb92002-04-12 10:26:32 +0000882{
sewardjf8f819e2002-04-17 23:21:37 +0000883 attr->__mutexkind = PTHREAD_MUTEX_ERRORCHECK_NP;
sewardj8937c812002-04-12 20:12:20 +0000884 return 0;
sewardje663cb92002-04-12 10:26:32 +0000885}
886
sewardj5905fae2002-04-26 13:25:00 +0000887int __pthread_mutexattr_settype(pthread_mutexattr_t *attr, int type)
sewardjf8f819e2002-04-17 23:21:37 +0000888{
889 switch (type) {
sewardj3b13f0e2002-04-25 20:17:29 +0000890# ifndef GLIBC_2_1
sewardjf8f819e2002-04-17 23:21:37 +0000891 case PTHREAD_MUTEX_TIMED_NP:
sewardj2a1dcce2002-04-22 12:45:25 +0000892 case PTHREAD_MUTEX_ADAPTIVE_NP:
sewardj3b13f0e2002-04-25 20:17:29 +0000893# endif
sewardja1679dd2002-05-10 22:31:40 +0000894# ifdef GLIBC_2_1
sewardj68b2dd92002-05-10 21:03:56 +0000895 case PTHREAD_MUTEX_FAST_NP:
sewardja1679dd2002-05-10 22:31:40 +0000896# endif
sewardjf8f819e2002-04-17 23:21:37 +0000897 case PTHREAD_MUTEX_RECURSIVE_NP:
898 case PTHREAD_MUTEX_ERRORCHECK_NP:
sewardjf8f819e2002-04-17 23:21:37 +0000899 attr->__mutexkind = type;
900 return 0;
901 default:
sewardj4dced352002-06-04 22:54:20 +0000902 pthread_error("pthread_mutexattr_settype: "
903 "invalid type");
sewardjf8f819e2002-04-17 23:21:37 +0000904 return EINVAL;
905 }
906}
907
sewardj5905fae2002-04-26 13:25:00 +0000908int __pthread_mutexattr_destroy(pthread_mutexattr_t *attr)
sewardjf8f819e2002-04-17 23:21:37 +0000909{
910 return 0;
911}
912
913
914/* ---------------------------------------------------
915 MUTEXes
916 ------------------------------------------------ */
917
sewardj5905fae2002-04-26 13:25:00 +0000918int __pthread_mutex_init(pthread_mutex_t *mutex,
919 const pthread_mutexattr_t *mutexattr)
sewardje663cb92002-04-12 10:26:32 +0000920{
sewardj604ec3c2002-04-18 22:38:41 +0000921 mutex->__m_count = 0;
922 mutex->__m_owner = (_pthread_descr)VG_INVALID_THREADID;
923 mutex->__m_kind = PTHREAD_MUTEX_ERRORCHECK_NP;
924 if (mutexattr)
925 mutex->__m_kind = mutexattr->__mutexkind;
926 return 0;
sewardje663cb92002-04-12 10:26:32 +0000927}
928
sewardj439d45e2002-05-03 20:43:10 +0000929
sewardj5905fae2002-04-26 13:25:00 +0000930int __pthread_mutex_lock(pthread_mutex_t *mutex)
sewardje663cb92002-04-12 10:26:32 +0000931{
932 int res;
sewardjd8acdf22002-11-13 21:57:52 +0000933
sewardj439d45e2002-05-03 20:43:10 +0000934 if (RUNNING_ON_VALGRIND) {
sewardje663cb92002-04-12 10:26:32 +0000935 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
936 VG_USERREQ__PTHREAD_MUTEX_LOCK,
937 mutex, 0, 0, 0);
938 return res;
sewardj439d45e2002-05-03 20:43:10 +0000939 } else {
sewardjd8acdf22002-11-13 21:57:52 +0000940 /* Play at locking */
941 if (0)
942 kludged("prehistoric lock");
943 mutex->__m_owner = (_pthread_descr)1;
944 mutex->__m_count = 1;
945 mutex->__m_kind |= VG_PTHREAD_PREHISTORY;
sewardj439d45e2002-05-03 20:43:10 +0000946 return 0; /* success */
sewardje663cb92002-04-12 10:26:32 +0000947 }
948}
949
sewardj439d45e2002-05-03 20:43:10 +0000950
sewardj5905fae2002-04-26 13:25:00 +0000951int __pthread_mutex_trylock(pthread_mutex_t *mutex)
sewardj30671ff2002-04-21 00:13:57 +0000952{
953 int res;
sewardjd8acdf22002-11-13 21:57:52 +0000954
sewardj439d45e2002-05-03 20:43:10 +0000955 if (RUNNING_ON_VALGRIND) {
sewardj30671ff2002-04-21 00:13:57 +0000956 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
957 VG_USERREQ__PTHREAD_MUTEX_TRYLOCK,
958 mutex, 0, 0, 0);
959 return res;
sewardj439d45e2002-05-03 20:43:10 +0000960 } else {
sewardjd8acdf22002-11-13 21:57:52 +0000961 /* Play at locking */
962 if (0)
963 kludged("prehistoric trylock");
964 mutex->__m_owner = (_pthread_descr)1;
965 mutex->__m_count = 1;
966 mutex->__m_kind |= VG_PTHREAD_PREHISTORY;
967 return 0; /* success */
sewardj30671ff2002-04-21 00:13:57 +0000968 }
969}
970
sewardj439d45e2002-05-03 20:43:10 +0000971
sewardj5905fae2002-04-26 13:25:00 +0000972int __pthread_mutex_unlock(pthread_mutex_t *mutex)
sewardje663cb92002-04-12 10:26:32 +0000973{
974 int res;
sewardjd8acdf22002-11-13 21:57:52 +0000975
sewardj439d45e2002-05-03 20:43:10 +0000976 if (RUNNING_ON_VALGRIND) {
sewardje663cb92002-04-12 10:26:32 +0000977 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
978 VG_USERREQ__PTHREAD_MUTEX_UNLOCK,
979 mutex, 0, 0, 0);
980 return res;
sewardj439d45e2002-05-03 20:43:10 +0000981 } else {
sewardjd8acdf22002-11-13 21:57:52 +0000982 /* Play at locking */
983 if (0)
984 kludged("prehistoric unlock");
985 mutex->__m_owner = 0;
986 mutex->__m_count = 0;
987 mutex->__m_kind &= ~VG_PTHREAD_PREHISTORY;
988 return 0; /* success */
sewardje663cb92002-04-12 10:26:32 +0000989 }
990}
991
sewardj439d45e2002-05-03 20:43:10 +0000992
sewardj5905fae2002-04-26 13:25:00 +0000993int __pthread_mutex_destroy(pthread_mutex_t *mutex)
sewardje663cb92002-04-12 10:26:32 +0000994{
sewardj604ec3c2002-04-18 22:38:41 +0000995 /* Valgrind doesn't hold any resources on behalf of the mutex, so no
996 need to involve it. */
sewardj4dced352002-06-04 22:54:20 +0000997 if (mutex->__m_count > 0) {
sewardjd8acdf22002-11-13 21:57:52 +0000998 /* Oh, the horror. glibc's internal use of pthreads "knows"
999 that destroying a lock does an implicit unlock. Make it
1000 explicit. */
1001 __pthread_mutex_unlock(mutex);
1002 pthread_error("pthread_mutex_destroy: "
1003 "mutex is still in use");
1004 return EBUSY;
sewardj4dced352002-06-04 22:54:20 +00001005 }
1006 mutex->__m_count = 0;
1007 mutex->__m_owner = (_pthread_descr)VG_INVALID_THREADID;
1008 mutex->__m_kind = PTHREAD_MUTEX_ERRORCHECK_NP;
1009 return 0;
sewardje663cb92002-04-12 10:26:32 +00001010}
1011
1012
sewardjf8f819e2002-04-17 23:21:37 +00001013/* ---------------------------------------------------
sewardj6072c362002-04-19 14:40:57 +00001014 CONDITION VARIABLES
1015 ------------------------------------------------ */
1016
1017/* LinuxThreads supports no attributes for conditions. Hence ... */
1018
1019int pthread_condattr_init(pthread_condattr_t *attr)
1020{
1021 return 0;
1022}
1023
sewardj0738a592002-04-20 13:59:33 +00001024int pthread_condattr_destroy(pthread_condattr_t *attr)
1025{
1026 return 0;
1027}
sewardj6072c362002-04-19 14:40:57 +00001028
1029int pthread_cond_init( pthread_cond_t *cond,
1030 const pthread_condattr_t *cond_attr)
1031{
1032 cond->__c_waiting = (_pthread_descr)VG_INVALID_THREADID;
1033 return 0;
1034}
1035
sewardjf854f472002-04-21 12:19:41 +00001036int pthread_cond_destroy(pthread_cond_t *cond)
1037{
1038 /* should check that no threads are waiting on this CV */
sewardj436e0582002-04-26 14:31:40 +00001039 static int moans = N_MOANS;
1040 if (moans-- > 0)
1041 kludged("pthread_cond_destroy");
sewardjf854f472002-04-21 12:19:41 +00001042 return 0;
1043}
sewardj6072c362002-04-19 14:40:57 +00001044
1045/* ---------------------------------------------------
1046 SCHEDULING
1047 ------------------------------------------------ */
1048
1049/* This is completely bogus. */
1050int pthread_getschedparam(pthread_t target_thread,
1051 int *policy,
1052 struct sched_param *param)
1053{
sewardj436e0582002-04-26 14:31:40 +00001054 static int moans = N_MOANS;
1055 if (moans-- > 0)
1056 kludged("pthread_getschedparam");
sewardj6072c362002-04-19 14:40:57 +00001057 if (policy) *policy = SCHED_OTHER;
sewardj3e909ce2002-06-03 13:27:15 +00001058# ifdef HAVE_SCHED_PRIORITY
sewardj2a1dcce2002-04-22 12:45:25 +00001059 if (param) param->sched_priority = 0; /* who knows */
1060# else
sewardj6072c362002-04-19 14:40:57 +00001061 if (param) param->__sched_priority = 0; /* who knows */
sewardj2a1dcce2002-04-22 12:45:25 +00001062# endif
sewardj6072c362002-04-19 14:40:57 +00001063 return 0;
1064}
1065
1066int pthread_setschedparam(pthread_t target_thread,
1067 int policy,
1068 const struct sched_param *param)
1069{
sewardj436e0582002-04-26 14:31:40 +00001070 static int moans = N_MOANS;
1071 if (moans-- > 0)
1072 ignored("pthread_setschedparam");
sewardj6072c362002-04-19 14:40:57 +00001073 return 0;
1074}
1075
sewardj3b5d8862002-04-20 13:53:23 +00001076int pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex)
1077{
1078 int res;
1079 ensure_valgrind("pthread_cond_wait");
1080 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
1081 VG_USERREQ__PTHREAD_COND_WAIT,
1082 cond, mutex, 0, 0);
1083 return res;
1084}
1085
sewardj5f07b662002-04-23 16:52:51 +00001086int pthread_cond_timedwait ( pthread_cond_t *cond,
1087 pthread_mutex_t *mutex,
1088 const struct timespec *abstime )
1089{
1090 int res;
1091 unsigned int ms_now, ms_end;
1092 struct timeval timeval_now;
1093 unsigned long long int ull_ms_now_after_1970;
1094 unsigned long long int ull_ms_end_after_1970;
1095
1096 ensure_valgrind("pthread_cond_timedwait");
1097 VALGRIND_MAGIC_SEQUENCE(ms_now, 0xFFFFFFFF /* default */,
1098 VG_USERREQ__READ_MILLISECOND_TIMER,
1099 0, 0, 0, 0);
sewardj2d94c112002-06-03 01:25:54 +00001100 my_assert(ms_now != 0xFFFFFFFF);
sewardj5f07b662002-04-23 16:52:51 +00001101 res = gettimeofday(&timeval_now, NULL);
sewardj2d94c112002-06-03 01:25:54 +00001102 my_assert(res == 0);
sewardj5f07b662002-04-23 16:52:51 +00001103
1104 ull_ms_now_after_1970
1105 = 1000ULL * ((unsigned long long int)(timeval_now.tv_sec))
1106 + ((unsigned long long int)(timeval_now.tv_usec / 1000000));
1107 ull_ms_end_after_1970
1108 = 1000ULL * ((unsigned long long int)(abstime->tv_sec))
1109 + ((unsigned long long int)(abstime->tv_nsec / 1000000));
sewardjd8e919e2002-05-29 20:13:53 +00001110 if (ull_ms_end_after_1970 < ull_ms_now_after_1970)
1111 ull_ms_end_after_1970 = ull_ms_now_after_1970;
sewardj5f07b662002-04-23 16:52:51 +00001112 ms_end
1113 = ms_now + (unsigned int)(ull_ms_end_after_1970 - ull_ms_now_after_1970);
1114 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
1115 VG_USERREQ__PTHREAD_COND_TIMEDWAIT,
1116 cond, mutex, ms_end, 0);
1117 return res;
1118}
1119
1120
sewardj3b5d8862002-04-20 13:53:23 +00001121int pthread_cond_signal(pthread_cond_t *cond)
1122{
1123 int res;
1124 ensure_valgrind("pthread_cond_signal");
1125 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
1126 VG_USERREQ__PTHREAD_COND_SIGNAL,
1127 cond, 0, 0, 0);
1128 return res;
1129}
1130
1131int pthread_cond_broadcast(pthread_cond_t *cond)
1132{
1133 int res;
1134 ensure_valgrind("pthread_cond_broadcast");
1135 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
1136 VG_USERREQ__PTHREAD_COND_BROADCAST,
1137 cond, 0, 0, 0);
1138 return res;
1139}
1140
sewardj6072c362002-04-19 14:40:57 +00001141
1142/* ---------------------------------------------------
sewardjf8f819e2002-04-17 23:21:37 +00001143 CANCELLATION
1144 ------------------------------------------------ */
1145
sewardj853f55d2002-04-26 00:27:53 +00001146int pthread_setcancelstate(int state, int *oldstate)
1147{
sewardj20917d82002-05-28 01:36:45 +00001148 int res;
1149 ensure_valgrind("pthread_setcancelstate");
1150 if (state != PTHREAD_CANCEL_ENABLE
sewardj4dced352002-06-04 22:54:20 +00001151 && state != PTHREAD_CANCEL_DISABLE) {
1152 pthread_error("pthread_setcancelstate: "
1153 "invalid state");
sewardj20917d82002-05-28 01:36:45 +00001154 return EINVAL;
sewardj4dced352002-06-04 22:54:20 +00001155 }
sewardj2d94c112002-06-03 01:25:54 +00001156 my_assert(-1 != PTHREAD_CANCEL_ENABLE);
1157 my_assert(-1 != PTHREAD_CANCEL_DISABLE);
sewardj20917d82002-05-28 01:36:45 +00001158 VALGRIND_MAGIC_SEQUENCE(res, (-1) /* default */,
1159 VG_USERREQ__SET_CANCELSTATE,
1160 state, 0, 0, 0);
sewardj2d94c112002-06-03 01:25:54 +00001161 my_assert(res != -1);
sewardj20917d82002-05-28 01:36:45 +00001162 if (oldstate)
1163 *oldstate = res;
sewardj853f55d2002-04-26 00:27:53 +00001164 return 0;
1165}
1166
sewardje663cb92002-04-12 10:26:32 +00001167int pthread_setcanceltype(int type, int *oldtype)
1168{
sewardj20917d82002-05-28 01:36:45 +00001169 int res;
1170 ensure_valgrind("pthread_setcanceltype");
1171 if (type != PTHREAD_CANCEL_DEFERRED
sewardj4dced352002-06-04 22:54:20 +00001172 && type != PTHREAD_CANCEL_ASYNCHRONOUS) {
1173 pthread_error("pthread_setcanceltype: "
1174 "invalid type");
sewardj20917d82002-05-28 01:36:45 +00001175 return EINVAL;
sewardj4dced352002-06-04 22:54:20 +00001176 }
sewardj2d94c112002-06-03 01:25:54 +00001177 my_assert(-1 != PTHREAD_CANCEL_DEFERRED);
1178 my_assert(-1 != PTHREAD_CANCEL_ASYNCHRONOUS);
sewardj20917d82002-05-28 01:36:45 +00001179 VALGRIND_MAGIC_SEQUENCE(res, (-1) /* default */,
1180 VG_USERREQ__SET_CANCELTYPE,
1181 type, 0, 0, 0);
sewardj2d94c112002-06-03 01:25:54 +00001182 my_assert(res != -1);
sewardj20917d82002-05-28 01:36:45 +00001183 if (oldtype)
1184 *oldtype = res;
sewardje663cb92002-04-12 10:26:32 +00001185 return 0;
1186}
1187
sewardje663cb92002-04-12 10:26:32 +00001188int pthread_cancel(pthread_t thread)
1189{
1190 int res;
1191 ensure_valgrind("pthread_cancel");
sewardj20917d82002-05-28 01:36:45 +00001192 VALGRIND_MAGIC_SEQUENCE(res, (-1) /* default */,
1193 VG_USERREQ__SET_CANCELPEND,
1194 thread, &thread_exit_wrapper, 0, 0);
sewardj2d94c112002-06-03 01:25:54 +00001195 my_assert(res != -1);
sewardje663cb92002-04-12 10:26:32 +00001196 return res;
1197}
1198
sewardjd140e442002-05-29 01:21:19 +00001199static __inline__
1200void __my_pthread_testcancel(void)
sewardj853f55d2002-04-26 00:27:53 +00001201{
sewardj20917d82002-05-28 01:36:45 +00001202 int res;
njn25e49d8e72002-09-23 09:36:25 +00001203 ensure_valgrind("__my_pthread_testcancel");
sewardj20917d82002-05-28 01:36:45 +00001204 VALGRIND_MAGIC_SEQUENCE(res, (-1) /* default */,
1205 VG_USERREQ__TESTCANCEL,
1206 0, 0, 0, 0);
sewardj2d94c112002-06-03 01:25:54 +00001207 my_assert(res == 0);
sewardj853f55d2002-04-26 00:27:53 +00001208}
1209
sewardjd140e442002-05-29 01:21:19 +00001210void pthread_testcancel ( void )
1211{
1212 __my_pthread_testcancel();
1213}
1214
sewardj20917d82002-05-28 01:36:45 +00001215
sewardjef037c72002-05-30 00:40:03 +00001216/* Not really sure what this is for. I suspect for doing the POSIX
1217 requirements for fork() and exec(). We do this internally anyway
1218 whenever those syscalls are observed, so this could be superfluous,
1219 but hey ...
1220*/
sewardj853f55d2002-04-26 00:27:53 +00001221void __pthread_kill_other_threads_np ( void )
1222{
sewardjef037c72002-05-30 00:40:03 +00001223 int res;
1224 ensure_valgrind("__pthread_kill_other_threads_np");
1225 VALGRIND_MAGIC_SEQUENCE(res, (-1) /* default */,
1226 VG_USERREQ__NUKE_OTHER_THREADS,
1227 0, 0, 0, 0);
sewardj2d94c112002-06-03 01:25:54 +00001228 my_assert(res == 0);
sewardj853f55d2002-04-26 00:27:53 +00001229}
1230
sewardje663cb92002-04-12 10:26:32 +00001231
sewardjf8f819e2002-04-17 23:21:37 +00001232/* ---------------------------------------------------
sewardjb48e5002002-05-13 00:16:03 +00001233 SIGNALS
1234 ------------------------------------------------ */
1235
1236#include <signal.h>
1237
1238int pthread_sigmask(int how, const sigset_t *newmask,
1239 sigset_t *oldmask)
1240{
1241 int res;
1242
1243 /* A bit subtle, because the scheduler expects newmask and oldmask
1244 to be vki_sigset_t* rather than sigset_t*, and the two are
1245 different. Fortunately the first 64 bits of a sigset_t are
1246 exactly a vki_sigset_t, so we just pass the pointers through
1247 unmodified. Haaaack!
1248
1249 Also mash the how value so that the SIG_ constants from glibc
sewardj018f7622002-05-15 21:13:39 +00001250 constants to VKI_ constants, so that the former do not have to
1251 be included into vg_scheduler.c. */
sewardjb48e5002002-05-13 00:16:03 +00001252
1253 ensure_valgrind("pthread_sigmask");
1254
1255 switch (how) {
sewardj018f7622002-05-15 21:13:39 +00001256 case SIG_SETMASK: how = VKI_SIG_SETMASK; break;
1257 case SIG_BLOCK: how = VKI_SIG_BLOCK; break;
1258 case SIG_UNBLOCK: how = VKI_SIG_UNBLOCK; break;
sewardj4dced352002-06-04 22:54:20 +00001259 default: pthread_error("pthread_sigmask: invalid how");
1260 return EINVAL;
sewardjb48e5002002-05-13 00:16:03 +00001261 }
1262
1263 /* Crude check */
1264 if (newmask == NULL)
1265 return EFAULT;
1266
1267 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
1268 VG_USERREQ__PTHREAD_SIGMASK,
1269 how, newmask, oldmask, 0);
1270
1271 /* The scheduler tells us of any memory violations. */
1272 return res == 0 ? 0 : EFAULT;
1273}
1274
1275
1276int sigwait ( const sigset_t* set, int* sig )
1277{
1278 int res;
1279 ensure_valgrind("sigwait");
1280 /* As with pthread_sigmask we deliberately confuse sigset_t with
1281 vki_ksigset_t. */
1282 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
1283 VG_USERREQ__SIGWAIT,
1284 set, sig, 0, 0);
1285 return res;
1286}
1287
1288
sewardj018f7622002-05-15 21:13:39 +00001289int pthread_kill(pthread_t thread, int signo)
1290{
1291 int res;
1292 ensure_valgrind("pthread_kill");
1293 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
1294 VG_USERREQ__PTHREAD_KILL,
1295 thread, signo, 0, 0);
1296 return res;
1297}
1298
1299
sewardj3665ded2002-05-16 16:57:25 +00001300/* Copied verbatim from Linuxthreads */
1301/* Redefine raise() to send signal to calling thread only,
1302 as per POSIX 1003.1c */
1303int raise (int sig)
1304{
1305 int retcode = pthread_kill(pthread_self(), sig);
sewardj4dced352002-06-04 22:54:20 +00001306 if (retcode == 0) {
sewardj3665ded2002-05-16 16:57:25 +00001307 return 0;
sewardj4dced352002-06-04 22:54:20 +00001308 } else {
sewardj3665ded2002-05-16 16:57:25 +00001309 errno = retcode;
1310 return -1;
1311 }
1312}
1313
1314
sewardj9a2224b2002-06-19 10:17:40 +00001315int pause ( void )
1316{
1317 unsigned int n_orig, n_now;
1318 struct vki_timespec nanosleep_interval;
1319 ensure_valgrind("pause");
1320
1321 /* This is surely a cancellation point. */
1322 __my_pthread_testcancel();
1323
1324 VALGRIND_MAGIC_SEQUENCE(n_orig, 0xFFFFFFFF /* default */,
1325 VG_USERREQ__GET_N_SIGS_RETURNED,
1326 0, 0, 0, 0);
1327 my_assert(n_orig != 0xFFFFFFFF);
1328
1329 while (1) {
1330 VALGRIND_MAGIC_SEQUENCE(n_now, 0xFFFFFFFF /* default */,
1331 VG_USERREQ__GET_N_SIGS_RETURNED,
1332 0, 0, 0, 0);
1333 my_assert(n_now != 0xFFFFFFFF);
1334 my_assert(n_now >= n_orig);
1335 if (n_now != n_orig) break;
1336
1337 nanosleep_interval.tv_sec = 0;
njn25e49d8e72002-09-23 09:36:25 +00001338 nanosleep_interval.tv_nsec = 12 * 1000 * 1000; /* 12 milliseconds */
sewardj9a2224b2002-06-19 10:17:40 +00001339 /* It's critical here that valgrind's nanosleep implementation
1340 is nonblocking. */
1341 (void)my_do_syscall2(__NR_nanosleep,
1342 (int)(&nanosleep_interval), (int)NULL);
1343 }
1344
1345 * (__errno_location()) = EINTR;
1346 return -1;
1347}
1348
1349
sewardjb48e5002002-05-13 00:16:03 +00001350/* ---------------------------------------------------
sewardjf8f819e2002-04-17 23:21:37 +00001351 THREAD-SPECIFICs
1352 ------------------------------------------------ */
sewardj5e5fa512002-04-14 13:13:05 +00001353
sewardj00a66b12002-10-12 16:42:35 +00001354static
1355int key_is_valid (pthread_key_t key)
1356{
1357 int res;
1358 VALGRIND_MAGIC_SEQUENCE(res, 2 /* default */,
1359 VG_USERREQ__PTHREAD_KEY_VALIDATE,
1360 key, 0, 0, 0);
1361 my_assert(res != 2);
1362 return res;
1363}
1364
1365
1366/* Returns NULL if thread is invalid. Otherwise, if the thread
1367 already has a specifics area, return that. Otherwise allocate it
1368 one. */
1369static
1370void** get_or_allocate_specifics_ptr ( pthread_t thread )
1371{
1372 int res, i;
1373 void** specifics_ptr;
1374 ensure_valgrind("get_or_allocate_specifics_ptr");
1375
1376 /* Returns zero if the thread has no specific_ptr. One if thread
1377 is invalid. Otherwise, the specific_ptr value. This is
1378 allocated with my_malloc and so is aligned and cannot be
1379 confused with 1 or 3. */
1380 VALGRIND_MAGIC_SEQUENCE(specifics_ptr, 3 /* default */,
1381 VG_USERREQ__PTHREAD_GETSPECIFIC_PTR,
1382 thread, 0, 0, 0);
1383 my_assert(specifics_ptr != (void**)3);
1384
1385 if (specifics_ptr == (void**)1)
1386 return NULL; /* invalid thread */
1387
1388 if (specifics_ptr != NULL)
1389 return specifics_ptr; /* already has a specifics ptr. */
1390
1391 /* None yet ... allocate a new one. Should never fail. */
1392 specifics_ptr = my_malloc( VG_N_THREAD_KEYS * sizeof(void*) );
1393 my_assert(specifics_ptr != NULL);
1394
1395 VALGRIND_MAGIC_SEQUENCE(res, -1 /* default */,
1396 VG_USERREQ__PTHREAD_SETSPECIFIC_PTR,
1397 specifics_ptr, 0, 0, 0);
1398 my_assert(res == 0);
1399
1400 /* POSIX sez: "Upon thread creation, the value NULL shall be
1401 associated with all defined keys in the new thread." This
1402 allocation is in effect a delayed allocation of the specific
1403 data for a thread, at its first-use. Hence we initialise it
1404 here. */
1405 for (i = 0; i < VG_N_THREAD_KEYS; i++) {
1406 specifics_ptr[i] = NULL;
1407 }
1408
1409 return specifics_ptr;
1410}
1411
1412
sewardj5905fae2002-04-26 13:25:00 +00001413int __pthread_key_create(pthread_key_t *key,
1414 void (*destr_function) (void *))
sewardj5e5fa512002-04-14 13:13:05 +00001415{
sewardj00a66b12002-10-12 16:42:35 +00001416 void** specifics_ptr;
1417 int res, i;
sewardj5f07b662002-04-23 16:52:51 +00001418 ensure_valgrind("pthread_key_create");
sewardj00a66b12002-10-12 16:42:35 +00001419
1420 /* This writes *key if successful. It should never fail. */
1421 VALGRIND_MAGIC_SEQUENCE(res, 1 /* default */,
sewardj5f07b662002-04-23 16:52:51 +00001422 VG_USERREQ__PTHREAD_KEY_CREATE,
1423 key, destr_function, 0, 0);
sewardj00a66b12002-10-12 16:42:35 +00001424 my_assert(res == 0);
1425
1426 /* POSIX sez: "Upon key creation, the value NULL shall be
1427 associated with the new key in all active threads." */
1428 for (i = 0; i < VG_N_THREADS; i++) {
1429 specifics_ptr = get_or_allocate_specifics_ptr(i);
1430 /* we get NULL if i is an invalid thread. */
1431 if (specifics_ptr != NULL)
1432 specifics_ptr[*key] = NULL;
1433 }
1434
sewardj5f07b662002-04-23 16:52:51 +00001435 return res;
sewardj5e5fa512002-04-14 13:13:05 +00001436}
1437
1438int pthread_key_delete(pthread_key_t key)
1439{
sewardj00a66b12002-10-12 16:42:35 +00001440 int res;
1441 ensure_valgrind("pthread_key_create");
1442 if (!key_is_valid(key))
1443 return EINVAL;
1444 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
1445 VG_USERREQ__PTHREAD_KEY_DELETE,
1446 key, 0, 0, 0);
1447 my_assert(res == 0);
sewardj5e5fa512002-04-14 13:13:05 +00001448 return 0;
1449}
1450
sewardj5905fae2002-04-26 13:25:00 +00001451int __pthread_setspecific(pthread_key_t key, const void *pointer)
sewardj5e5fa512002-04-14 13:13:05 +00001452{
sewardj00a66b12002-10-12 16:42:35 +00001453 void** specifics_ptr;
sewardj5f07b662002-04-23 16:52:51 +00001454 ensure_valgrind("pthread_setspecific");
sewardj00a66b12002-10-12 16:42:35 +00001455
1456 if (!key_is_valid(key))
1457 return EINVAL;
1458
1459 specifics_ptr = get_or_allocate_specifics_ptr(pthread_self());
1460 specifics_ptr[key] = (void*)pointer;
1461 return 0;
sewardj5e5fa512002-04-14 13:13:05 +00001462}
1463
sewardj5905fae2002-04-26 13:25:00 +00001464void * __pthread_getspecific(pthread_key_t key)
sewardj5e5fa512002-04-14 13:13:05 +00001465{
sewardj00a66b12002-10-12 16:42:35 +00001466 void** specifics_ptr;
sewardj5f07b662002-04-23 16:52:51 +00001467 ensure_valgrind("pthread_getspecific");
sewardj00a66b12002-10-12 16:42:35 +00001468
1469 if (!key_is_valid(key))
1470 return NULL;
1471
1472 specifics_ptr = get_or_allocate_specifics_ptr(pthread_self());
1473 return specifics_ptr[key];
1474}
1475
1476
sewardj9aa918d2002-10-20 16:25:55 +00001477#ifdef GLIBC_2_3
sewardj00a66b12002-10-12 16:42:35 +00001478static
1479void ** __pthread_getspecific_addr(pthread_key_t key)
1480{
1481 void** specifics_ptr;
1482 ensure_valgrind("pthread_getspecific_addr");
1483
1484 if (!key_is_valid(key))
1485 return NULL;
1486
1487 specifics_ptr = get_or_allocate_specifics_ptr(pthread_self());
1488 return &(specifics_ptr[key]);
sewardj5e5fa512002-04-14 13:13:05 +00001489}
sewardj9aa918d2002-10-20 16:25:55 +00001490#endif
sewardjf8f819e2002-04-17 23:21:37 +00001491
1492/* ---------------------------------------------------
sewardj89d3d852002-04-24 19:21:39 +00001493 ONCEry
1494 ------------------------------------------------ */
1495
1496static pthread_mutex_t once_masterlock = PTHREAD_MUTEX_INITIALIZER;
1497
1498
sewardj5905fae2002-04-26 13:25:00 +00001499int __pthread_once ( pthread_once_t *once_control,
1500 void (*init_routine) (void) )
sewardj89d3d852002-04-24 19:21:39 +00001501{
1502 int res;
1503 ensure_valgrind("pthread_once");
1504
sewardj68b2dd92002-05-10 21:03:56 +00001505 res = __pthread_mutex_lock(&once_masterlock);
sewardj89d3d852002-04-24 19:21:39 +00001506
sewardj68b2dd92002-05-10 21:03:56 +00001507 if (res != 0) {
sewardj89d3d852002-04-24 19:21:39 +00001508 barf("pthread_once: Looks like your program's "
1509 "init routine calls back to pthread_once() ?!");
sewardj68b2dd92002-05-10 21:03:56 +00001510 }
sewardj89d3d852002-04-24 19:21:39 +00001511
1512 if (*once_control == 0) {
1513 *once_control = 1;
1514 init_routine();
1515 }
1516
sewardj68b2dd92002-05-10 21:03:56 +00001517 __pthread_mutex_unlock(&once_masterlock);
sewardj89d3d852002-04-24 19:21:39 +00001518
1519 return 0;
1520}
1521
1522
1523/* ---------------------------------------------------
sewardj853f55d2002-04-26 00:27:53 +00001524 MISC
1525 ------------------------------------------------ */
1526
sewardj2cb00342002-06-28 01:46:26 +00001527static pthread_mutex_t pthread_atfork_lock
1528 = PTHREAD_MUTEX_INITIALIZER;
1529
sewardj5905fae2002-04-26 13:25:00 +00001530int __pthread_atfork ( void (*prepare)(void),
1531 void (*parent)(void),
1532 void (*child)(void) )
sewardj853f55d2002-04-26 00:27:53 +00001533{
sewardj2cb00342002-06-28 01:46:26 +00001534 int n, res;
1535 ForkHandlerEntry entry;
1536
1537 ensure_valgrind("pthread_atfork");
1538 __pthread_mutex_lock(&pthread_atfork_lock);
1539
1540 /* Fetch old counter */
1541 VALGRIND_MAGIC_SEQUENCE(n, -2 /* default */,
1542 VG_USERREQ__GET_FHSTACK_USED,
1543 0, 0, 0, 0);
1544 my_assert(n >= 0 && n < VG_N_FORKHANDLERSTACK);
1545 if (n == VG_N_FORKHANDLERSTACK-1)
1546 barf("pthread_atfork: VG_N_FORKHANDLERSTACK is too low; "
1547 "increase and recompile");
1548
1549 /* Add entry */
1550 entry.prepare = *prepare;
1551 entry.parent = *parent;
1552 entry.child = *child;
1553 VALGRIND_MAGIC_SEQUENCE(res, -2 /* default */,
1554 VG_USERREQ__SET_FHSTACK_ENTRY,
1555 n, &entry, 0, 0);
1556 my_assert(res == 0);
1557
1558 /* Bump counter */
1559 VALGRIND_MAGIC_SEQUENCE(res, -2 /* default */,
1560 VG_USERREQ__SET_FHSTACK_USED,
1561 n+1, 0, 0, 0);
1562 my_assert(res == 0);
1563
1564 __pthread_mutex_unlock(&pthread_atfork_lock);
1565 return 0;
sewardj853f55d2002-04-26 00:27:53 +00001566}
1567
1568
sewardj11f0bb42003-04-26 20:11:15 +00001569WEAK
sewardjbb990782002-05-08 02:01:14 +00001570void __pthread_initialize ( void )
1571{
sewardjbea1caa2002-05-10 23:20:58 +00001572 ensure_valgrind("__pthread_initialize");
sewardjbb990782002-05-08 02:01:14 +00001573}
1574
1575
sewardj853f55d2002-04-26 00:27:53 +00001576/* ---------------------------------------------------
sewardj3b13f0e2002-04-25 20:17:29 +00001577 LIBRARY-PRIVATE THREAD SPECIFIC STATE
sewardjf8f819e2002-04-17 23:21:37 +00001578 ------------------------------------------------ */
1579
sewardj3b13f0e2002-04-25 20:17:29 +00001580#include <resolv.h>
1581static int thread_specific_errno[VG_N_THREADS];
1582static int thread_specific_h_errno[VG_N_THREADS];
1583static struct __res_state
1584 thread_specific_res_state[VG_N_THREADS];
sewardjf8f819e2002-04-17 23:21:37 +00001585
sewardj3b13f0e2002-04-25 20:17:29 +00001586int* __errno_location ( void )
sewardjf8f819e2002-04-17 23:21:37 +00001587{
1588 int tid;
sewardj3b13f0e2002-04-25 20:17:29 +00001589 /* ensure_valgrind("__errno_location"); */
1590 VALGRIND_MAGIC_SEQUENCE(tid, 1 /* default */,
sewardjf8f819e2002-04-17 23:21:37 +00001591 VG_USERREQ__PTHREAD_GET_THREADID,
1592 0, 0, 0, 0);
sewardj3b13f0e2002-04-25 20:17:29 +00001593 /* 'cos I'm paranoid ... */
sewardj439d45e2002-05-03 20:43:10 +00001594 if (tid < 1 || tid >= VG_N_THREADS)
sewardj3b13f0e2002-04-25 20:17:29 +00001595 barf("__errno_location: invalid ThreadId");
1596 return & thread_specific_errno[tid];
1597}
1598
1599int* __h_errno_location ( void )
1600{
1601 int tid;
1602 /* ensure_valgrind("__h_errno_location"); */
1603 VALGRIND_MAGIC_SEQUENCE(tid, 1 /* default */,
1604 VG_USERREQ__PTHREAD_GET_THREADID,
1605 0, 0, 0, 0);
1606 /* 'cos I'm paranoid ... */
sewardj439d45e2002-05-03 20:43:10 +00001607 if (tid < 1 || tid >= VG_N_THREADS)
sewardj3b13f0e2002-04-25 20:17:29 +00001608 barf("__h_errno_location: invalid ThreadId");
1609 return & thread_specific_h_errno[tid];
1610}
1611
sewardjb0ff1032002-08-06 09:02:53 +00001612
1613#undef _res
1614extern struct __res_state _res;
1615
sewardj3b13f0e2002-04-25 20:17:29 +00001616struct __res_state* __res_state ( void )
1617{
1618 int tid;
1619 /* ensure_valgrind("__res_state"); */
1620 VALGRIND_MAGIC_SEQUENCE(tid, 1 /* default */,
1621 VG_USERREQ__PTHREAD_GET_THREADID,
1622 0, 0, 0, 0);
1623 /* 'cos I'm paranoid ... */
sewardj439d45e2002-05-03 20:43:10 +00001624 if (tid < 1 || tid >= VG_N_THREADS)
sewardj3b13f0e2002-04-25 20:17:29 +00001625 barf("__res_state: invalid ThreadId");
sewardjb0ff1032002-08-06 09:02:53 +00001626 if (tid == 1)
1627 return & _res;
sewardj3b13f0e2002-04-25 20:17:29 +00001628 return & thread_specific_res_state[tid];
sewardjf8f819e2002-04-17 23:21:37 +00001629}
1630
1631
sewardj5716dbb2002-04-26 03:28:18 +00001632/* ---------------------------------------------------
1633 LIBC-PRIVATE SPECIFIC DATA
1634 ------------------------------------------------ */
1635
1636/* Relies on assumption that initial private data is NULL. This
1637 should be fixed somehow. */
1638
njn25e49d8e72002-09-23 09:36:25 +00001639/* The allowable keys (indices) (all 3 of them).
sewardj5716dbb2002-04-26 03:28:18 +00001640 From sysdeps/pthread/bits/libc-tsd.h
1641*/
sewardjcb7f08a2002-10-02 09:41:49 +00001642/* as per glibc anoncvs HEAD of 20021001. */
sewardj5716dbb2002-04-26 03:28:18 +00001643enum __libc_tsd_key_t { _LIBC_TSD_KEY_MALLOC = 0,
1644 _LIBC_TSD_KEY_DL_ERROR,
njn25e49d8e72002-09-23 09:36:25 +00001645 _LIBC_TSD_KEY_RPC_VARS,
sewardjcb7f08a2002-10-02 09:41:49 +00001646 _LIBC_TSD_KEY_LOCALE,
1647 _LIBC_TSD_KEY_CTYPE_B,
1648 _LIBC_TSD_KEY_CTYPE_TOLOWER,
1649 _LIBC_TSD_KEY_CTYPE_TOUPPER,
sewardj5716dbb2002-04-26 03:28:18 +00001650 _LIBC_TSD_KEY_N };
1651
1652/* Auto-initialising subsystem. libc_specifics_inited is set
1653 after initialisation. libc_specifics_inited_mx guards it. */
1654static int libc_specifics_inited = 0;
1655static pthread_mutex_t libc_specifics_inited_mx = PTHREAD_MUTEX_INITIALIZER;
1656
sewardj00a66b12002-10-12 16:42:35 +00001657
sewardj5716dbb2002-04-26 03:28:18 +00001658/* These are the keys we must initialise the first time. */
sewardjcb7f08a2002-10-02 09:41:49 +00001659static pthread_key_t libc_specifics_keys[_LIBC_TSD_KEY_N];
sewardj5716dbb2002-04-26 03:28:18 +00001660
sewardj00a66b12002-10-12 16:42:35 +00001661
sewardjcb7f08a2002-10-02 09:41:49 +00001662/* Initialise the keys, if they are not already initialised. */
sewardj5716dbb2002-04-26 03:28:18 +00001663static
1664void init_libc_tsd_keys ( void )
1665{
1666 int res, i;
1667 pthread_key_t k;
1668
sewardj08c7f012002-10-07 23:56:55 +00001669 /* Don't fall into deadlock if we get called again whilst we still
1670 hold the lock, via the __uselocale() call herein. */
1671 if (libc_specifics_inited != 0)
1672 return;
1673
1674 /* Take the lock. */
sewardj00a66b12002-10-12 16:42:35 +00001675 res = __pthread_mutex_lock(&libc_specifics_inited_mx);
sewardj5716dbb2002-04-26 03:28:18 +00001676 if (res != 0) barf("init_libc_tsd_keys: lock");
1677
sewardj08c7f012002-10-07 23:56:55 +00001678 /* Now test again, to be sure there is no mistake. */
1679 if (libc_specifics_inited != 0) {
sewardj00a66b12002-10-12 16:42:35 +00001680 res = __pthread_mutex_unlock(&libc_specifics_inited_mx);
sewardj08c7f012002-10-07 23:56:55 +00001681 if (res != 0) barf("init_libc_tsd_keys: unlock(1)");
1682 return;
sewardj5716dbb2002-04-26 03:28:18 +00001683 }
1684
sewardj08c7f012002-10-07 23:56:55 +00001685 /* Actually do the initialisation. */
1686 /* printf("INIT libc specifics\n"); */
1687 for (i = 0; i < _LIBC_TSD_KEY_N; i++) {
sewardj00a66b12002-10-12 16:42:35 +00001688 res = __pthread_key_create(&k, NULL);
sewardj08c7f012002-10-07 23:56:55 +00001689 if (res != 0) barf("init_libc_tsd_keys: create");
1690 libc_specifics_keys[i] = k;
1691 }
1692
1693 /* Signify init done. */
1694 libc_specifics_inited = 1;
1695
1696# ifdef GLIBC_2_3
1697 /* Set the initialising thread's locale to the global (default)
sewardj00a66b12002-10-12 16:42:35 +00001698 locale. A hack in support of glibc-2.3. This does the biz for
1699 the root thread. For all other threads we run this in
1700 thread_wrapper(), which does the real work of
1701 pthread_create(). */
1702 /* assert that we are the root thread. I don't know if this is
1703 really a valid assertion to make; if it breaks I'll reconsider
1704 it. */
1705 my_assert(pthread_self() == 1);
sewardj08c7f012002-10-07 23:56:55 +00001706 __uselocale(LC_GLOBAL_LOCALE);
1707# endif
1708
1709 /* Unlock and return. */
sewardj00a66b12002-10-12 16:42:35 +00001710 res = __pthread_mutex_unlock(&libc_specifics_inited_mx);
sewardj5716dbb2002-04-26 03:28:18 +00001711 if (res != 0) barf("init_libc_tsd_keys: unlock");
1712}
1713
1714
1715static int
1716libc_internal_tsd_set ( enum __libc_tsd_key_t key,
1717 const void * pointer )
1718{
sewardjcb7f08a2002-10-02 09:41:49 +00001719 int res;
sewardj5716dbb2002-04-26 03:28:18 +00001720 /* printf("SET SET SET key %d ptr %p\n", key, pointer); */
sewardjcb7f08a2002-10-02 09:41:49 +00001721 if (key < _LIBC_TSD_KEY_MALLOC || key >= _LIBC_TSD_KEY_N)
sewardj5716dbb2002-04-26 03:28:18 +00001722 barf("libc_internal_tsd_set: invalid key");
1723 init_libc_tsd_keys();
sewardj00a66b12002-10-12 16:42:35 +00001724 res = __pthread_setspecific(libc_specifics_keys[key], pointer);
sewardj5716dbb2002-04-26 03:28:18 +00001725 if (res != 0) barf("libc_internal_tsd_set: setspecific failed");
1726 return 0;
1727}
1728
1729static void *
1730libc_internal_tsd_get ( enum __libc_tsd_key_t key )
1731{
sewardjcb7f08a2002-10-02 09:41:49 +00001732 void* v;
sewardj5716dbb2002-04-26 03:28:18 +00001733 /* printf("GET GET GET key %d\n", key); */
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_get: invalid key");
1736 init_libc_tsd_keys();
sewardj00a66b12002-10-12 16:42:35 +00001737 v = __pthread_getspecific(libc_specifics_keys[key]);
sewardj5716dbb2002-04-26 03:28:18 +00001738 /* if (v == NULL) barf("libc_internal_tsd_set: getspecific failed"); */
1739 return v;
1740}
1741
1742
sewardj70adeb22002-04-27 01:35:38 +00001743int (*__libc_internal_tsd_set)
1744 (enum __libc_tsd_key_t key, const void * pointer)
1745 = libc_internal_tsd_set;
sewardj5716dbb2002-04-26 03:28:18 +00001746
sewardj70adeb22002-04-27 01:35:38 +00001747void* (*__libc_internal_tsd_get)
1748 (enum __libc_tsd_key_t key)
1749 = libc_internal_tsd_get;
sewardj5716dbb2002-04-26 03:28:18 +00001750
1751
sewardj00a66b12002-10-12 16:42:35 +00001752#ifdef GLIBC_2_3
1753/* This one was first spotted be me in the glibc-2.2.93 sources. */
1754static void**
1755libc_internal_tsd_address ( enum __libc_tsd_key_t key )
1756{
1757 void** v;
1758 /* printf("ADDR ADDR ADDR key %d\n", key); */
1759 if (key < _LIBC_TSD_KEY_MALLOC || key >= _LIBC_TSD_KEY_N)
1760 barf("libc_internal_tsd_address: invalid key");
1761 init_libc_tsd_keys();
1762 v = __pthread_getspecific_addr(libc_specifics_keys[key]);
1763 return v;
1764}
1765
1766void ** (*__libc_internal_tsd_address)
1767 (enum __libc_tsd_key_t key)
1768 = libc_internal_tsd_address;
1769#endif
1770
1771
sewardje663cb92002-04-12 10:26:32 +00001772/* ---------------------------------------------------------------------
1773 These are here (I think) because they are deemed cancellation
1774 points by POSIX. For the moment we'll simply pass the call along
1775 to the corresponding thread-unaware (?) libc routine.
1776 ------------------------------------------------------------------ */
1777
sewardjd529a442002-05-04 19:49:21 +00001778#ifdef GLIBC_2_1
1779extern
1780int __sigaction
1781 (int signum,
1782 const struct sigaction *act,
1783 struct sigaction *oldact);
1784#else
sewardje663cb92002-04-12 10:26:32 +00001785extern
1786int __libc_sigaction
1787 (int signum,
1788 const struct sigaction *act,
1789 struct sigaction *oldact);
sewardjd529a442002-05-04 19:49:21 +00001790#endif
sewardje663cb92002-04-12 10:26:32 +00001791int sigaction(int signum,
1792 const struct sigaction *act,
1793 struct sigaction *oldact)
1794{
sewardjd140e442002-05-29 01:21:19 +00001795 __my_pthread_testcancel();
sewardj2a1dcce2002-04-22 12:45:25 +00001796# ifdef GLIBC_2_1
1797 return __sigaction(signum, act, oldact);
1798# else
sewardj45b4b372002-04-16 22:50:32 +00001799 return __libc_sigaction(signum, act, oldact);
sewardj2a1dcce2002-04-22 12:45:25 +00001800# endif
sewardje663cb92002-04-12 10:26:32 +00001801}
1802
1803
1804extern
1805int __libc_connect(int sockfd,
1806 const struct sockaddr *serv_addr,
1807 socklen_t addrlen);
sewardj11f0bb42003-04-26 20:11:15 +00001808WEAK
sewardje663cb92002-04-12 10:26:32 +00001809int connect(int sockfd,
1810 const struct sockaddr *serv_addr,
1811 socklen_t addrlen)
1812{
sewardjd140e442002-05-29 01:21:19 +00001813 __my_pthread_testcancel();
sewardj45b4b372002-04-16 22:50:32 +00001814 return __libc_connect(sockfd, serv_addr, addrlen);
sewardje663cb92002-04-12 10:26:32 +00001815}
1816
1817
1818extern
1819int __libc_fcntl(int fd, int cmd, long arg);
sewardj11f0bb42003-04-26 20:11:15 +00001820WEAK
sewardje663cb92002-04-12 10:26:32 +00001821int fcntl(int fd, int cmd, long arg)
1822{
sewardjd140e442002-05-29 01:21:19 +00001823 __my_pthread_testcancel();
sewardj45b4b372002-04-16 22:50:32 +00001824 return __libc_fcntl(fd, cmd, arg);
sewardje663cb92002-04-12 10:26:32 +00001825}
1826
1827
1828extern
1829ssize_t __libc_write(int fd, const void *buf, size_t count);
sewardj11f0bb42003-04-26 20:11:15 +00001830WEAK
sewardje663cb92002-04-12 10:26:32 +00001831ssize_t write(int fd, const void *buf, size_t count)
1832{
sewardjd140e442002-05-29 01:21:19 +00001833 __my_pthread_testcancel();
sewardj45b4b372002-04-16 22:50:32 +00001834 return __libc_write(fd, buf, count);
sewardje663cb92002-04-12 10:26:32 +00001835}
1836
1837
1838extern
1839ssize_t __libc_read(int fd, void *buf, size_t count);
sewardj11f0bb42003-04-26 20:11:15 +00001840WEAK
sewardje663cb92002-04-12 10:26:32 +00001841ssize_t read(int fd, void *buf, size_t count)
1842{
sewardjd140e442002-05-29 01:21:19 +00001843 __my_pthread_testcancel();
sewardj45b4b372002-04-16 22:50:32 +00001844 return __libc_read(fd, buf, count);
sewardje663cb92002-04-12 10:26:32 +00001845}
1846
sewardjf912dfc2002-11-13 21:51:10 +00001847/*
1848 * Ugh, this is horrible but here goes:
1849 *
1850 * Open of a named pipe (fifo file) can block. In a threaded program,
1851 * this means that the whole thing can block. We therefore need to
1852 * make the open appear to block to the caller, but still keep polling
1853 * for everyone else.
1854 *
1855 * There are four cases:
1856 *
1857 * - the caller asked for O_NONBLOCK. The easy one: we just do it.
1858 *
1859 * - the caller asked for a blocking O_RDONLY open. We open it with
1860 * O_NONBLOCK and then use poll to wait for it to become ready.
1861 *
1862 * - the caller asked for a blocking O_WRONLY open. Unfortunately, this
1863 * will fail with ENXIO when we make it non-blocking. Doubly
1864 * unfortunate is that we can only rely on these semantics if it is
1865 * actually a fifo file; the hack is that if we see that it is a
1866 * O_WRONLY open and we get ENXIO, then stat the path and see if it
1867 * actually is a fifo. This is racy, but it is the best we can do.
1868 * If it is a fifo, then keep trying the open until it works; if not
1869 * just return the error.
1870 *
1871 * - the caller asked for a blocking O_RDWR open. Well, under Linux,
1872 * this never blocks, so we just clear the non-blocking flag and
1873 * return.
1874 *
1875 * This code assumes that for whatever we open, O_NONBLOCK followed by
1876 * a fcntl clearing O_NONBLOCK is the same as opening without
1877 * O_NONBLOCK. Also assumes that stat and fstat have no side-effects.
1878 *
1879 * XXX Should probably put in special cases for some devices as well,
1880 * like serial ports. Unfortunately they don't work like fifos, so
1881 * this logic will become even more tortured. Wait until we really
1882 * need it.
1883 */
1884static inline int _open(const char *pathname, int flags, mode_t mode,
1885 int (*openp)(const char *, int, mode_t))
sewardjbe32e452002-04-24 20:29:58 +00001886{
sewardjf912dfc2002-11-13 21:51:10 +00001887 int fd;
1888 struct stat st;
1889 struct vki_timespec nanosleep_interval;
1890 int saved_errno;
1891
sewardjd140e442002-05-29 01:21:19 +00001892 __my_pthread_testcancel();
sewardjf912dfc2002-11-13 21:51:10 +00001893
1894 /* Assume we can only get O_RDONLY, O_WRONLY or O_RDWR */
1895 my_assert((flags & VKI_O_ACCMODE) != VKI_O_ACCMODE);
1896
1897 for(;;) {
1898 fd = (*openp)(pathname, flags | VKI_O_NONBLOCK, mode);
1899
1900 /* return immediately if caller wanted nonblocking anyway */
1901 if (flags & VKI_O_NONBLOCK)
1902 return fd;
1903
1904 saved_errno = errno;
1905
1906 if (fd != -1)
1907 break; /* open worked */
1908
1909 /* If we got ENXIO and we're opening WRONLY, and it turns out
1910 to really be a FIFO, then poll waiting for open to succeed */
1911 if (errno == ENXIO &&
1912 (flags & VKI_O_ACCMODE) == VKI_O_WRONLY &&
1913 (stat(pathname, &st) == 0 && S_ISFIFO(st.st_mode))) {
1914
1915 /* OK, we're opening a FIFO for writing; sleep and spin */
1916 nanosleep_interval.tv_sec = 0;
1917 nanosleep_interval.tv_nsec = 13 * 1000 * 1000; /* 13 milliseconds */
1918 /* It's critical here that valgrind's nanosleep implementation
1919 is nonblocking. */
1920 (void)my_do_syscall2(__NR_nanosleep,
1921 (int)(&nanosleep_interval), (int)NULL);
1922 } else {
1923 /* it was just an error */
1924 errno = saved_errno;
1925 return -1;
1926 }
1927 }
1928
1929 /* OK, we've got a nonblocking FD for a caller who wants blocking;
1930 reset the flags to what they asked for */
1931 fcntl(fd, VKI_F_SETFL, flags);
1932
1933 /* Return now if one of:
1934 - we were opening O_RDWR (never blocks)
1935 - we opened with O_WRONLY (polling already done)
1936 - the thing we opened wasn't a FIFO after all (or fstat failed)
1937 */
1938 if ((flags & VKI_O_ACCMODE) != VKI_O_RDONLY ||
1939 (fstat(fd, &st) == -1 || !S_ISFIFO(st.st_mode))) {
1940 errno = saved_errno;
1941 return fd;
1942 }
1943
1944 /* OK, drop into the poll loop looking for something to read on the fd */
1945 my_assert((flags & VKI_O_ACCMODE) == VKI_O_RDONLY);
1946 for(;;) {
1947 struct pollfd pollfd;
1948 int res;
1949
1950 pollfd.fd = fd;
1951 pollfd.events = POLLIN;
1952 pollfd.revents = 0;
1953
1954 res = my_do_syscall3(__NR_poll, (int)&pollfd, 1, 0);
1955
1956 my_assert(res == 0 || res == 1);
1957
1958 if (res == 1) {
1959 /* OK, got it.
1960
1961 XXX This is wrong: we're waiting for either something to
1962 read or a HUP on the file descriptor, but the semantics of
1963 fifo open are that we should unblock as soon as someone
1964 simply opens the other end, not that they write something.
1965 With luck this won't matter in practice.
1966 */
1967 my_assert(pollfd.revents & (POLLIN|POLLHUP));
1968 break;
1969 }
1970
1971 /* Still nobody home; sleep and spin */
1972 nanosleep_interval.tv_sec = 0;
1973 nanosleep_interval.tv_nsec = 13 * 1000 * 1000; /* 13 milliseconds */
1974 /* It's critical here that valgrind's nanosleep implementation
1975 is nonblocking. */
1976 (void)my_do_syscall2(__NR_nanosleep,
1977 (int)(&nanosleep_interval), (int)NULL);
1978 }
1979
1980 errno = saved_errno;
1981 return fd;
sewardjbe32e452002-04-24 20:29:58 +00001982}
1983
sewardjf912dfc2002-11-13 21:51:10 +00001984extern
1985int __libc_open64(const char *pathname, int flags, mode_t mode);
sewardj11f0bb42003-04-26 20:11:15 +00001986/* WEAK */
sewardjf912dfc2002-11-13 21:51:10 +00001987int open64(const char *pathname, int flags, mode_t mode)
1988{
1989 return _open(pathname, flags, mode, __libc_open64);
1990}
sewardje663cb92002-04-12 10:26:32 +00001991
1992extern
sewardj853f55d2002-04-26 00:27:53 +00001993int __libc_open(const char *pathname, int flags, mode_t mode);
sewardj11f0bb42003-04-26 20:11:15 +00001994/* WEAK */
sewardj853f55d2002-04-26 00:27:53 +00001995int open(const char *pathname, int flags, mode_t mode)
sewardje663cb92002-04-12 10:26:32 +00001996{
sewardjf912dfc2002-11-13 21:51:10 +00001997 return _open(pathname, flags, mode, __libc_open);
sewardje663cb92002-04-12 10:26:32 +00001998}
1999
sewardje663cb92002-04-12 10:26:32 +00002000extern
2001int __libc_close(int fd);
sewardj11f0bb42003-04-26 20:11:15 +00002002WEAK
sewardje663cb92002-04-12 10:26:32 +00002003int close(int fd)
2004{
sewardjd140e442002-05-29 01:21:19 +00002005 __my_pthread_testcancel();
sewardj45b4b372002-04-16 22:50:32 +00002006 return __libc_close(fd);
sewardje663cb92002-04-12 10:26:32 +00002007}
2008
2009
sewardj11f0bb42003-04-26 20:11:15 +00002010WEAK
2011int accept(int s, struct sockaddr *addr, socklen_t *addrlen)
sewardje663cb92002-04-12 10:26:32 +00002012{
sewardj11f0bb42003-04-26 20:11:15 +00002013 return VGR_(accept)(s, addr, addrlen);
sewardje663cb92002-04-12 10:26:32 +00002014}
2015
sewardj11f0bb42003-04-26 20:11:15 +00002016WEAK
2017int recv(int s, void *buf, size_t len, int flags)
sewardj0c573af92002-10-23 21:55:01 +00002018{
sewardj11f0bb42003-04-26 20:11:15 +00002019 return VGR_(recv)(s, buf, len, flags);
sewardj0c573af92002-10-23 21:55:01 +00002020}
2021
sewardj11f0bb42003-04-26 20:11:15 +00002022WEAK
2023int readv(int fd, const struct iovec *iov, int count)
sewardj2a68e7e2002-11-16 11:04:18 +00002024{
sewardj11f0bb42003-04-26 20:11:15 +00002025 return VGR_(readv)(fd, iov, count);
sewardj2a68e7e2002-11-16 11:04:18 +00002026}
2027
sewardj11f0bb42003-04-26 20:11:15 +00002028WEAK
2029int writev(int fd, const struct iovec *iov, int count)
sewardj2a68e7e2002-11-16 11:04:18 +00002030{
sewardj11f0bb42003-04-26 20:11:15 +00002031 return VGR_(writev)(fd, iov, count);
sewardj2a68e7e2002-11-16 11:04:18 +00002032}
sewardje663cb92002-04-12 10:26:32 +00002033
2034extern
sewardje663cb92002-04-12 10:26:32 +00002035pid_t __libc_waitpid(pid_t pid, int *status, int options);
sewardj11f0bb42003-04-26 20:11:15 +00002036WEAK
sewardje663cb92002-04-12 10:26:32 +00002037pid_t waitpid(pid_t pid, int *status, int options)
2038{
sewardjd140e442002-05-29 01:21:19 +00002039 __my_pthread_testcancel();
sewardj45b4b372002-04-16 22:50:32 +00002040 return __libc_waitpid(pid, status, options);
sewardje663cb92002-04-12 10:26:32 +00002041}
2042
2043
2044extern
2045int __libc_nanosleep(const struct timespec *req, struct timespec *rem);
sewardj11f0bb42003-04-26 20:11:15 +00002046WEAK
sewardje663cb92002-04-12 10:26:32 +00002047int nanosleep(const struct timespec *req, struct timespec *rem)
2048{
sewardjd140e442002-05-29 01:21:19 +00002049 __my_pthread_testcancel();
sewardje663cb92002-04-12 10:26:32 +00002050 return __libc_nanosleep(req, rem);
2051}
2052
sewardjbe32e452002-04-24 20:29:58 +00002053
sewardje663cb92002-04-12 10:26:32 +00002054extern
2055int __libc_fsync(int fd);
sewardj11f0bb42003-04-26 20:11:15 +00002056WEAK
sewardje663cb92002-04-12 10:26:32 +00002057int fsync(int fd)
2058{
sewardjd140e442002-05-29 01:21:19 +00002059 __my_pthread_testcancel();
sewardj45b4b372002-04-16 22:50:32 +00002060 return __libc_fsync(fd);
sewardje663cb92002-04-12 10:26:32 +00002061}
2062
sewardjbe32e452002-04-24 20:29:58 +00002063
sewardj70c75362002-04-13 04:18:32 +00002064extern
2065off_t __libc_lseek(int fildes, off_t offset, int whence);
sewardj11f0bb42003-04-26 20:11:15 +00002066WEAK
sewardj70c75362002-04-13 04:18:32 +00002067off_t lseek(int fildes, off_t offset, int whence)
2068{
sewardjd140e442002-05-29 01:21:19 +00002069 __my_pthread_testcancel();
sewardj45b4b372002-04-16 22:50:32 +00002070 return __libc_lseek(fildes, offset, whence);
sewardj70c75362002-04-13 04:18:32 +00002071}
2072
sewardjbe32e452002-04-24 20:29:58 +00002073
2074extern
2075__off64_t __libc_lseek64(int fildes, __off64_t offset, int whence);
sewardj11f0bb42003-04-26 20:11:15 +00002076WEAK
sewardjbe32e452002-04-24 20:29:58 +00002077__off64_t lseek64(int fildes, __off64_t offset, int whence)
2078{
sewardjd140e442002-05-29 01:21:19 +00002079 __my_pthread_testcancel();
sewardjbe32e452002-04-24 20:29:58 +00002080 return __libc_lseek64(fildes, offset, whence);
2081}
2082
2083
sewardj726c4122002-05-16 23:39:10 +00002084extern
2085ssize_t __libc_pread64 (int __fd, void *__buf, size_t __nbytes,
2086 __off64_t __offset);
2087ssize_t __pread64 (int __fd, void *__buf, size_t __nbytes,
2088 __off64_t __offset)
2089{
sewardjd140e442002-05-29 01:21:19 +00002090 __my_pthread_testcancel();
sewardj726c4122002-05-16 23:39:10 +00002091 return __libc_pread64(__fd, __buf, __nbytes, __offset);
2092}
2093
2094
sewardja18e2102002-05-18 10:43:22 +00002095extern
2096ssize_t __libc_pwrite64 (int __fd, const void *__buf, size_t __nbytes,
2097 __off64_t __offset);
2098ssize_t __pwrite64 (int __fd, const void *__buf, size_t __nbytes,
2099 __off64_t __offset)
2100{
sewardjd140e442002-05-29 01:21:19 +00002101 __my_pthread_testcancel();
sewardja18e2102002-05-18 10:43:22 +00002102 return __libc_pwrite64(__fd, __buf, __nbytes, __offset);
2103}
2104
sewardj726c4122002-05-16 23:39:10 +00002105
sewardj39b93b12002-05-18 10:56:27 +00002106extern
2107ssize_t __libc_pwrite(int fd, const void *buf, size_t count, off_t offset);
sewardj11f0bb42003-04-26 20:11:15 +00002108WEAK
sewardj39b93b12002-05-18 10:56:27 +00002109ssize_t pwrite(int fd, const void *buf, size_t count, off_t offset)
2110{
sewardjd140e442002-05-29 01:21:19 +00002111 __my_pthread_testcancel();
sewardj39b93b12002-05-18 10:56:27 +00002112 return __libc_pwrite(fd, buf, count, offset);
2113}
2114
2115
2116extern
2117ssize_t __libc_pread(int fd, void *buf, size_t count, off_t offset);
sewardj11f0bb42003-04-26 20:11:15 +00002118WEAK
sewardj39b93b12002-05-18 10:56:27 +00002119ssize_t pread(int fd, void *buf, size_t count, off_t offset)
2120{
sewardjd140e442002-05-29 01:21:19 +00002121 __my_pthread_testcancel();
sewardj39b93b12002-05-18 10:56:27 +00002122 return __libc_pread(fd, buf, count, offset);
2123}
2124
2125
sewardj6af4b5d2002-04-16 04:40:49 +00002126extern
2127void __libc_longjmp(jmp_buf env, int val) __attribute((noreturn));
sewardj11f0bb42003-04-26 20:11:15 +00002128/* not weak: WEAK */
sewardj6af4b5d2002-04-16 04:40:49 +00002129void longjmp(jmp_buf env, int val)
2130{
2131 __libc_longjmp(env, val);
2132}
2133
sewardjbe32e452002-04-24 20:29:58 +00002134
sewardj436c2db2002-06-18 09:07:54 +00002135extern void __libc_siglongjmp (sigjmp_buf env, int val)
2136 __attribute__ ((noreturn));
2137void siglongjmp(sigjmp_buf env, int val)
2138{
2139 kludged("siglongjmp (cleanup handlers are ignored)");
2140 __libc_siglongjmp(env, val);
2141}
2142
2143
sewardj6af4b5d2002-04-16 04:40:49 +00002144extern
2145int __libc_send(int s, const void *msg, size_t len, int flags);
sewardj11f0bb42003-04-26 20:11:15 +00002146WEAK
sewardj6af4b5d2002-04-16 04:40:49 +00002147int send(int s, const void *msg, size_t len, int flags)
2148{
sewardjd140e442002-05-29 01:21:19 +00002149 __my_pthread_testcancel();
sewardj6af4b5d2002-04-16 04:40:49 +00002150 return __libc_send(s, msg, len, flags);
2151}
2152
sewardjbe32e452002-04-24 20:29:58 +00002153
sewardj3665ded2002-05-16 16:57:25 +00002154extern
2155int __libc_sendmsg(int s, const struct msghdr *msg, int flags);
sewardj11f0bb42003-04-26 20:11:15 +00002156WEAK
sewardj3665ded2002-05-16 16:57:25 +00002157int sendmsg(int s, const struct msghdr *msg, int flags)
2158{
sewardjd140e442002-05-29 01:21:19 +00002159 __my_pthread_testcancel();
sewardj3665ded2002-05-16 16:57:25 +00002160 return __libc_sendmsg(s, msg, flags);
2161}
2162
2163
sewardj796d6a22002-04-24 02:28:34 +00002164extern
sewardj59da27a2002-06-06 08:33:54 +00002165int __libc_recvmsg(int s, struct msghdr *msg, int flags);
sewardj11f0bb42003-04-26 20:11:15 +00002166WEAK
sewardj59da27a2002-06-06 08:33:54 +00002167int recvmsg(int s, struct msghdr *msg, int flags)
2168{
2169 __my_pthread_testcancel();
2170 return __libc_recvmsg(s, msg, flags);
2171}
2172
2173
2174extern
sewardj436e0582002-04-26 14:31:40 +00002175int __libc_recvfrom(int s, void *buf, size_t len, int flags,
2176 struct sockaddr *from, socklen_t *fromlen);
sewardj11f0bb42003-04-26 20:11:15 +00002177WEAK
sewardj436e0582002-04-26 14:31:40 +00002178int recvfrom(int s, void *buf, size_t len, int flags,
2179 struct sockaddr *from, socklen_t *fromlen)
2180{
sewardjd140e442002-05-29 01:21:19 +00002181 __my_pthread_testcancel();
sewardj11f0bb42003-04-26 20:11:15 +00002182 VGR_(wait_for_fd_to_be_readable_or_erring)(s);
sewardj2e207632002-06-13 17:29:53 +00002183 __my_pthread_testcancel();
sewardj436e0582002-04-26 14:31:40 +00002184 return __libc_recvfrom(s, buf, len, flags, from, fromlen);
2185}
2186
2187
2188extern
sewardj796d6a22002-04-24 02:28:34 +00002189int __libc_sendto(int s, const void *msg, size_t len, int flags,
2190 const struct sockaddr *to, socklen_t tolen);
sewardj11f0bb42003-04-26 20:11:15 +00002191WEAK
sewardj796d6a22002-04-24 02:28:34 +00002192int sendto(int s, const void *msg, size_t len, int flags,
2193 const struct sockaddr *to, socklen_t tolen)
2194{
sewardjd140e442002-05-29 01:21:19 +00002195 __my_pthread_testcancel();
sewardj796d6a22002-04-24 02:28:34 +00002196 return __libc_sendto(s, msg, len, flags, to, tolen);
2197}
2198
sewardjbe32e452002-04-24 20:29:58 +00002199
sewardj369b1702002-04-24 13:28:15 +00002200extern
2201int __libc_system(const char* str);
sewardj11f0bb42003-04-26 20:11:15 +00002202WEAK
sewardj369b1702002-04-24 13:28:15 +00002203int system(const char* str)
2204{
sewardjd140e442002-05-29 01:21:19 +00002205 __my_pthread_testcancel();
sewardj369b1702002-04-24 13:28:15 +00002206 return __libc_system(str);
2207}
2208
sewardjbe32e452002-04-24 20:29:58 +00002209
sewardjab0b1c32002-04-24 19:26:47 +00002210extern
2211pid_t __libc_wait(int *status);
sewardj11f0bb42003-04-26 20:11:15 +00002212WEAK
sewardjab0b1c32002-04-24 19:26:47 +00002213pid_t wait(int *status)
2214{
sewardjd140e442002-05-29 01:21:19 +00002215 __my_pthread_testcancel();
sewardjab0b1c32002-04-24 19:26:47 +00002216 return __libc_wait(status);
2217}
2218
sewardj45b4b372002-04-16 22:50:32 +00002219
sewardj67f1d582002-05-24 02:11:32 +00002220extern
2221int __libc_msync(const void *start, size_t length, int flags);
sewardj11f0bb42003-04-26 20:11:15 +00002222WEAK
sewardj67f1d582002-05-24 02:11:32 +00002223int msync(const void *start, size_t length, int flags)
2224{
sewardjd140e442002-05-29 01:21:19 +00002225 __my_pthread_testcancel();
sewardj67f1d582002-05-24 02:11:32 +00002226 return __libc_msync(start, length, flags);
2227}
2228
sewardj5905fae2002-04-26 13:25:00 +00002229
sewardj2cb00342002-06-28 01:46:26 +00002230/*--- fork and its helper ---*/
2231
2232static
2233void run_fork_handlers ( int what )
2234{
2235 ForkHandlerEntry entry;
2236 int n_h, n_handlers, i, res;
2237
2238 my_assert(what == 0 || what == 1 || what == 2);
2239
2240 /* Fetch old counter */
2241 VALGRIND_MAGIC_SEQUENCE(n_handlers, -2 /* default */,
2242 VG_USERREQ__GET_FHSTACK_USED,
2243 0, 0, 0, 0);
2244 my_assert(n_handlers >= 0 && n_handlers < VG_N_FORKHANDLERSTACK);
2245
2246 /* Prepare handlers (what == 0) are called in opposite order of
2247 calls to pthread_atfork. Parent and child handlers are called
2248 in the same order as calls to pthread_atfork. */
2249 if (what == 0)
2250 n_h = n_handlers - 1;
2251 else
2252 n_h = 0;
2253
2254 for (i = 0; i < n_handlers; i++) {
2255 VALGRIND_MAGIC_SEQUENCE(res, -2 /* default */,
2256 VG_USERREQ__GET_FHSTACK_ENTRY,
2257 n_h, &entry, 0, 0);
2258 my_assert(res == 0);
2259 switch (what) {
2260 case 0: if (entry.prepare) entry.prepare();
2261 n_h--; break;
2262 case 1: if (entry.parent) entry.parent();
2263 n_h++; break;
2264 case 2: if (entry.child) entry.child();
2265 n_h++; break;
2266 default: barf("run_fork_handlers: invalid what");
2267 }
2268 }
2269
2270 if (what != 0 /* prepare */) {
2271 /* Empty out the stack. */
2272 VALGRIND_MAGIC_SEQUENCE(res, -2 /* default */,
2273 VG_USERREQ__SET_FHSTACK_USED,
2274 0, 0, 0, 0);
2275 my_assert(res == 0);
2276 }
2277}
2278
2279extern
2280pid_t __libc_fork(void);
2281pid_t __fork(void)
2282{
2283 pid_t pid;
2284 __my_pthread_testcancel();
2285 __pthread_mutex_lock(&pthread_atfork_lock);
2286
2287 run_fork_handlers(0 /* prepare */);
2288 pid = __libc_fork();
2289 if (pid == 0) {
2290 /* I am the child */
2291 run_fork_handlers(2 /* child */);
sewardjd8acdf22002-11-13 21:57:52 +00002292 __pthread_mutex_unlock(&pthread_atfork_lock);
sewardj2cb00342002-06-28 01:46:26 +00002293 __pthread_mutex_init(&pthread_atfork_lock, NULL);
2294 } else {
2295 /* I am the parent */
2296 run_fork_handlers(1 /* parent */);
2297 __pthread_mutex_unlock(&pthread_atfork_lock);
2298 }
2299 return pid;
2300}
2301
2302
njn25e49d8e72002-09-23 09:36:25 +00002303pid_t __vfork(void)
2304{
2305 return __fork();
2306}
sewardj2cb00342002-06-28 01:46:26 +00002307
2308
sewardj08a4c3f2002-04-13 03:45:44 +00002309static
sewardj08a4c3f2002-04-13 03:45:44 +00002310int my_do_syscall1 ( int syscallno, int arg1 )
2311{
2312 int __res;
2313 __asm__ volatile ("pushl %%ebx; movl %%edx,%%ebx ; int $0x80 ; popl %%ebx"
2314 : "=a" (__res)
2315 : "0" (syscallno),
2316 "d" (arg1) );
2317 return __res;
2318}
2319
2320static
2321int my_do_syscall2 ( int syscallno,
sewardjf854f472002-04-21 12:19:41 +00002322 int arg1, int arg2 )
sewardj08a4c3f2002-04-13 03:45:44 +00002323{
2324 int __res;
2325 __asm__ volatile ("pushl %%ebx; movl %%edx,%%ebx ; int $0x80 ; popl %%ebx"
2326 : "=a" (__res)
2327 : "0" (syscallno),
2328 "d" (arg1),
2329 "c" (arg2) );
2330 return __res;
2331}
2332
2333static
sewardjf854f472002-04-21 12:19:41 +00002334int my_do_syscall3 ( int syscallno,
2335 int arg1, int arg2, int arg3 )
2336{
2337 int __res;
2338 __asm__ volatile ("pushl %%ebx; movl %%esi,%%ebx ; int $0x80 ; popl %%ebx"
2339 : "=a" (__res)
2340 : "0" (syscallno),
2341 "S" (arg1),
2342 "c" (arg2),
2343 "d" (arg3) );
2344 return __res;
2345}
2346
sewardjd5bef572002-10-23 21:49:33 +00002347static inline
2348int my_do_syscall5 ( int syscallno,
2349 int arg1, int arg2, int arg3, int arg4, int arg5 )
2350{
2351 int __res;
2352 __asm__ volatile ("int $0x80"
2353 : "=a" (__res)
2354 : "0" (syscallno),
2355 "b" (arg1),
2356 "c" (arg2),
2357 "d" (arg3),
2358 "S" (arg4),
2359 "D" (arg5));
2360 return __res;
2361}
2362
sewardj11f0bb42003-04-26 20:11:15 +00002363
2364WEAK
2365int select ( int n,
2366 fd_set *rfds,
2367 fd_set *wfds,
2368 fd_set *xfds,
2369 struct timeval *timeout )
sewardj08a4c3f2002-04-13 03:45:44 +00002370{
sewardj11f0bb42003-04-26 20:11:15 +00002371 return VGR_(select)(n, rfds, wfds, xfds, timeout);
sewardj08a4c3f2002-04-13 03:45:44 +00002372}
2373
2374
sewardj3b13f0e2002-04-25 20:17:29 +00002375/* ---------------------------------------------------------------------
sewardj8f253ff2002-05-19 00:13:34 +00002376 Hacky implementation of semaphores.
2377 ------------------------------------------------------------------ */
2378
2379#include <semaphore.h>
2380
2381/* This is a terrible way to do the remapping. Plan is to import an
2382 AVL tree at some point. */
sewardj8f253ff2002-05-19 00:13:34 +00002383
2384typedef
2385 struct {
2386 pthread_mutex_t se_mx;
2387 pthread_cond_t se_cv;
2388 int count;
2389 }
2390 vg_sem_t;
2391
2392static pthread_mutex_t se_remap_mx = PTHREAD_MUTEX_INITIALIZER;
2393
2394static int se_remap_used = 0;
2395static sem_t* se_remap_orig[VG_N_SEMAPHORES];
2396static vg_sem_t se_remap_new[VG_N_SEMAPHORES];
2397
2398static vg_sem_t* se_remap ( sem_t* orig )
2399{
2400 int res, i;
2401 res = __pthread_mutex_lock(&se_remap_mx);
sewardj2d94c112002-06-03 01:25:54 +00002402 my_assert(res == 0);
sewardj8f253ff2002-05-19 00:13:34 +00002403
2404 for (i = 0; i < se_remap_used; i++) {
2405 if (se_remap_orig[i] == orig)
2406 break;
2407 }
2408 if (i == se_remap_used) {
2409 if (se_remap_used == VG_N_SEMAPHORES) {
2410 res = pthread_mutex_unlock(&se_remap_mx);
sewardj2d94c112002-06-03 01:25:54 +00002411 my_assert(res == 0);
sewardja1ac5cb2002-05-27 13:00:05 +00002412 barf("VG_N_SEMAPHORES is too low. Increase and recompile.");
sewardj8f253ff2002-05-19 00:13:34 +00002413 }
2414 se_remap_used++;
2415 se_remap_orig[i] = orig;
2416 /* printf("allocated semaphore %d\n", i); */
2417 }
2418 res = __pthread_mutex_unlock(&se_remap_mx);
sewardj2d94c112002-06-03 01:25:54 +00002419 my_assert(res == 0);
sewardj8f253ff2002-05-19 00:13:34 +00002420 return &se_remap_new[i];
2421}
2422
2423
2424int sem_init(sem_t *sem, int pshared, unsigned int value)
2425{
2426 int res;
2427 vg_sem_t* vg_sem;
2428 ensure_valgrind("sem_init");
2429 if (pshared != 0) {
sewardj4dced352002-06-04 22:54:20 +00002430 pthread_error("sem_init: unsupported pshared value");
sewardj8f253ff2002-05-19 00:13:34 +00002431 errno = ENOSYS;
2432 return -1;
2433 }
2434 vg_sem = se_remap(sem);
2435 res = pthread_mutex_init(&vg_sem->se_mx, NULL);
sewardj2d94c112002-06-03 01:25:54 +00002436 my_assert(res == 0);
sewardj8f253ff2002-05-19 00:13:34 +00002437 res = pthread_cond_init(&vg_sem->se_cv, NULL);
sewardj2d94c112002-06-03 01:25:54 +00002438 my_assert(res == 0);
sewardj8f253ff2002-05-19 00:13:34 +00002439 vg_sem->count = value;
2440 return 0;
2441}
2442
2443
2444int sem_wait ( sem_t* sem )
2445{
2446 int res;
2447 vg_sem_t* vg_sem;
2448 ensure_valgrind("sem_wait");
2449 vg_sem = se_remap(sem);
2450 res = __pthread_mutex_lock(&vg_sem->se_mx);
sewardj2d94c112002-06-03 01:25:54 +00002451 my_assert(res == 0);
sewardj8f253ff2002-05-19 00:13:34 +00002452 while (vg_sem->count == 0) {
2453 res = pthread_cond_wait(&vg_sem->se_cv, &vg_sem->se_mx);
sewardj2d94c112002-06-03 01:25:54 +00002454 my_assert(res == 0);
sewardj8f253ff2002-05-19 00:13:34 +00002455 }
2456 vg_sem->count--;
2457 res = __pthread_mutex_unlock(&vg_sem->se_mx);
sewardj2d94c112002-06-03 01:25:54 +00002458 my_assert(res == 0);
sewardj8f253ff2002-05-19 00:13:34 +00002459 return 0;
2460}
2461
2462int sem_post ( sem_t* sem )
2463{
2464 int res;
2465 vg_sem_t* vg_sem;
2466 ensure_valgrind("sem_post");
2467 vg_sem = se_remap(sem);
2468 res = __pthread_mutex_lock(&vg_sem->se_mx);
sewardj2d94c112002-06-03 01:25:54 +00002469 my_assert(res == 0);
sewardj8f253ff2002-05-19 00:13:34 +00002470 if (vg_sem->count == 0) {
2471 vg_sem->count++;
2472 res = pthread_cond_broadcast(&vg_sem->se_cv);
sewardj2d94c112002-06-03 01:25:54 +00002473 my_assert(res == 0);
sewardj8f253ff2002-05-19 00:13:34 +00002474 } else {
2475 vg_sem->count++;
2476 }
2477 res = __pthread_mutex_unlock(&vg_sem->se_mx);
sewardj2d94c112002-06-03 01:25:54 +00002478 my_assert(res == 0);
sewardj8f253ff2002-05-19 00:13:34 +00002479 return 0;
2480}
2481
2482
2483int sem_trywait ( sem_t* sem )
2484{
2485 int ret, res;
2486 vg_sem_t* vg_sem;
2487 ensure_valgrind("sem_trywait");
2488 vg_sem = se_remap(sem);
2489 res = __pthread_mutex_lock(&vg_sem->se_mx);
sewardj2d94c112002-06-03 01:25:54 +00002490 my_assert(res == 0);
sewardj8f253ff2002-05-19 00:13:34 +00002491 if (vg_sem->count > 0) {
2492 vg_sem->count--;
2493 ret = 0;
2494 } else {
2495 ret = -1;
2496 errno = EAGAIN;
2497 }
2498 res = __pthread_mutex_unlock(&vg_sem->se_mx);
sewardj2d94c112002-06-03 01:25:54 +00002499 my_assert(res == 0);
sewardj8f253ff2002-05-19 00:13:34 +00002500 return ret;
2501}
2502
2503
2504int sem_getvalue(sem_t* sem, int * sval)
2505{
2506 vg_sem_t* vg_sem;
2507 ensure_valgrind("sem_trywait");
2508 vg_sem = se_remap(sem);
2509 *sval = vg_sem->count;
2510 return 0;
2511}
2512
2513
2514int sem_destroy(sem_t * sem)
2515{
2516 kludged("sem_destroy");
2517 /* if someone waiting on this semaphore, errno = EBUSY, return -1 */
2518 return 0;
2519}
2520
sewardj9ad92d92002-10-16 19:45:06 +00002521
2522int sem_timedwait(sem_t* sem, const struct timespec *abstime)
2523{
2524 int res;
2525 vg_sem_t* vg_sem;
2526 ensure_valgrind("sem_timedwait");
2527 vg_sem = se_remap(sem);
2528 res = __pthread_mutex_lock(&vg_sem->se_mx);
2529 my_assert(res == 0);
2530 while ( vg_sem->count == 0 && res != ETIMEDOUT ) {
2531 res = pthread_cond_timedwait(&vg_sem->se_cv, &vg_sem->se_mx, abstime);
2532 }
2533 if ( vg_sem->count > 0 ) {
2534 vg_sem->count--;
2535 res = __pthread_mutex_unlock(&vg_sem->se_mx);
2536 my_assert(res == 0 );
2537 return 0;
2538 } else {
2539 res = __pthread_mutex_unlock(&vg_sem->se_mx);
2540 my_assert(res == 0 );
2541 *(__errno_location()) = ETIMEDOUT;
2542 return -1;
2543 }
2544}
2545
sewardj8f253ff2002-05-19 00:13:34 +00002546
2547/* ---------------------------------------------------------------------
sewardj2d8b3f02002-06-01 14:14:19 +00002548 Reader-writer locks.
sewardja1ac5cb2002-05-27 13:00:05 +00002549 ------------------------------------------------------------------ */
2550
sewardj2d8b3f02002-06-01 14:14:19 +00002551typedef
2552 struct {
2553 int initted; /* != 0 --> in use; sanity check only */
2554 int prefer_w; /* != 0 --> prefer writer */
2555 int nwait_r; /* # of waiting readers */
2556 int nwait_w; /* # of waiting writers */
2557 pthread_cond_t cv_r; /* for signalling readers */
2558 pthread_cond_t cv_w; /* for signalling writers */
2559 pthread_mutex_t mx;
2560 int status;
2561 /* allowed range for status: >= -1. -1 means 1 writer currently
2562 active, >= 0 means N readers currently active. */
2563 }
2564 vg_rwlock_t;
sewardja1ac5cb2002-05-27 13:00:05 +00002565
2566
2567static pthread_mutex_t rw_remap_mx = PTHREAD_MUTEX_INITIALIZER;
2568
2569static int rw_remap_used = 0;
2570static pthread_rwlock_t* rw_remap_orig[VG_N_RWLOCKS];
2571static vg_rwlock_t rw_remap_new[VG_N_RWLOCKS];
2572
sewardj2d8b3f02002-06-01 14:14:19 +00002573
2574static
2575void init_vg_rwlock ( vg_rwlock_t* vg_rwl )
2576{
2577 int res = 0;
2578 vg_rwl->initted = 1;
2579 vg_rwl->prefer_w = 1;
2580 vg_rwl->nwait_r = 0;
2581 vg_rwl->nwait_w = 0;
2582 vg_rwl->status = 0;
2583 res = pthread_mutex_init(&vg_rwl->mx, NULL);
2584 res |= pthread_cond_init(&vg_rwl->cv_r, NULL);
2585 res |= pthread_cond_init(&vg_rwl->cv_w, NULL);
sewardj2d94c112002-06-03 01:25:54 +00002586 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002587}
2588
2589
sewardja1ac5cb2002-05-27 13:00:05 +00002590/* Take the address of a LinuxThreads rwlock_t and return the shadow
2591 address of our version. Further, if the LinuxThreads version
2592 appears to have been statically initialised, do the same to the one
2593 we allocate here. The pthread_rwlock_t.__rw_readers field is set
2594 to zero by PTHREAD_RWLOCK_INITIALIZER, so we take zero as meaning
2595 uninitialised and non-zero meaning initialised.
2596*/
2597static vg_rwlock_t* rw_remap ( pthread_rwlock_t* orig )
2598{
2599 int res, i;
2600 vg_rwlock_t* vg_rwl;
2601 res = __pthread_mutex_lock(&rw_remap_mx);
sewardj2d94c112002-06-03 01:25:54 +00002602 my_assert(res == 0);
sewardja1ac5cb2002-05-27 13:00:05 +00002603
2604 for (i = 0; i < rw_remap_used; i++) {
2605 if (rw_remap_orig[i] == orig)
2606 break;
2607 }
2608 if (i == rw_remap_used) {
2609 if (rw_remap_used == VG_N_RWLOCKS) {
sewardj2d8b3f02002-06-01 14:14:19 +00002610 res = __pthread_mutex_unlock(&rw_remap_mx);
sewardj2d94c112002-06-03 01:25:54 +00002611 my_assert(res == 0);
sewardja1ac5cb2002-05-27 13:00:05 +00002612 barf("VG_N_RWLOCKS is too low. Increase and recompile.");
2613 }
2614 rw_remap_used++;
2615 rw_remap_orig[i] = orig;
sewardj2d8b3f02002-06-01 14:14:19 +00002616 rw_remap_new[i].initted = 0;
sewardja1ac5cb2002-05-27 13:00:05 +00002617 if (0) printf("allocated rwlock %d\n", i);
2618 }
2619 res = __pthread_mutex_unlock(&rw_remap_mx);
sewardj2d94c112002-06-03 01:25:54 +00002620 my_assert(res == 0);
sewardja1ac5cb2002-05-27 13:00:05 +00002621 vg_rwl = &rw_remap_new[i];
2622
sewardj2d8b3f02002-06-01 14:14:19 +00002623 /* Initialise the shadow, if required. */
sewardja1ac5cb2002-05-27 13:00:05 +00002624 if (orig->__rw_readers == 0) {
sewardja1ac5cb2002-05-27 13:00:05 +00002625 orig->__rw_readers = 1;
sewardj2d8b3f02002-06-01 14:14:19 +00002626 init_vg_rwlock(vg_rwl);
sewardja1ac5cb2002-05-27 13:00:05 +00002627 if (orig->__rw_kind == PTHREAD_RWLOCK_PREFER_READER_NP)
sewardj2d8b3f02002-06-01 14:14:19 +00002628 vg_rwl->prefer_w = 0;
sewardja1ac5cb2002-05-27 13:00:05 +00002629 }
2630
2631 return vg_rwl;
2632}
2633
2634
sewardja1ac5cb2002-05-27 13:00:05 +00002635int pthread_rwlock_init ( pthread_rwlock_t* orig,
2636 const pthread_rwlockattr_t* attr )
2637{
sewardja1ac5cb2002-05-27 13:00:05 +00002638 vg_rwlock_t* rwl;
2639 if (0) printf ("pthread_rwlock_init\n");
2640 /* Force the remapper to initialise the shadow. */
2641 orig->__rw_readers = 0;
2642 /* Install the lock preference; the remapper needs to know it. */
2643 orig->__rw_kind = PTHREAD_RWLOCK_DEFAULT_NP;
2644 if (attr)
2645 orig->__rw_kind = attr->__lockkind;
2646 rwl = rw_remap ( orig );
sewardj2d8b3f02002-06-01 14:14:19 +00002647 return 0;
sewardja1ac5cb2002-05-27 13:00:05 +00002648}
2649
sewardj2d8b3f02002-06-01 14:14:19 +00002650
2651static
2652void pthread_rwlock_rdlock_CANCEL_HDLR ( void* rwl_v )
sewardja1ac5cb2002-05-27 13:00:05 +00002653{
sewardj2d8b3f02002-06-01 14:14:19 +00002654 vg_rwlock_t* rwl = (vg_rwlock_t*)rwl_v;
2655 rwl->nwait_r--;
2656 pthread_mutex_unlock (&rwl->mx);
sewardja1ac5cb2002-05-27 13:00:05 +00002657}
2658
sewardj2d8b3f02002-06-01 14:14:19 +00002659
sewardja1ac5cb2002-05-27 13:00:05 +00002660int pthread_rwlock_rdlock ( pthread_rwlock_t* orig )
2661{
2662 int res;
2663 vg_rwlock_t* rwl;
2664 if (0) printf ("pthread_rwlock_rdlock\n");
2665 rwl = rw_remap ( orig );
sewardj2d8b3f02002-06-01 14:14:19 +00002666 res = __pthread_mutex_lock(&rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00002667 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002668 if (!rwl->initted) {
2669 res = __pthread_mutex_unlock(&rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00002670 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002671 return EINVAL;
2672 }
2673 if (rwl->status < 0) {
sewardj2d94c112002-06-03 01:25:54 +00002674 my_assert(rwl->status == -1);
sewardj2d8b3f02002-06-01 14:14:19 +00002675 rwl->nwait_r++;
2676 pthread_cleanup_push( pthread_rwlock_rdlock_CANCEL_HDLR, rwl );
2677 while (1) {
2678 if (rwl->status == 0) break;
2679 res = pthread_cond_wait(&rwl->cv_r, &rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00002680 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002681 }
2682 pthread_cleanup_pop(0);
2683 rwl->nwait_r--;
2684 }
sewardj2d94c112002-06-03 01:25:54 +00002685 my_assert(rwl->status >= 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002686 rwl->status++;
2687 res = __pthread_mutex_unlock(&rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00002688 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002689 return 0;
sewardja1ac5cb2002-05-27 13:00:05 +00002690}
2691
sewardj2d8b3f02002-06-01 14:14:19 +00002692
sewardja1ac5cb2002-05-27 13:00:05 +00002693int pthread_rwlock_tryrdlock ( pthread_rwlock_t* orig )
2694{
2695 int res;
2696 vg_rwlock_t* rwl;
2697 if (0) printf ("pthread_rwlock_tryrdlock\n");
2698 rwl = rw_remap ( orig );
sewardj2d8b3f02002-06-01 14:14:19 +00002699 res = __pthread_mutex_lock(&rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00002700 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002701 if (!rwl->initted) {
2702 res = __pthread_mutex_unlock(&rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00002703 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002704 return EINVAL;
2705 }
2706 if (rwl->status == -1) {
2707 /* Writer active; we have to give up. */
2708 res = __pthread_mutex_unlock(&rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00002709 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002710 return EBUSY;
2711 }
2712 /* Success */
sewardj2d94c112002-06-03 01:25:54 +00002713 my_assert(rwl->status >= 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002714 rwl->status++;
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 0;
sewardja1ac5cb2002-05-27 13:00:05 +00002718}
2719
sewardj2d8b3f02002-06-01 14:14:19 +00002720
2721static
2722void pthread_rwlock_wrlock_CANCEL_HDLR ( void* rwl_v )
2723{
2724 vg_rwlock_t* rwl = (vg_rwlock_t*)rwl_v;
2725 rwl->nwait_w--;
2726 pthread_mutex_unlock (&rwl->mx);
2727}
2728
2729
sewardja1ac5cb2002-05-27 13:00:05 +00002730int pthread_rwlock_wrlock ( pthread_rwlock_t* orig )
2731{
2732 int res;
2733 vg_rwlock_t* rwl;
2734 if (0) printf ("pthread_rwlock_wrlock\n");
2735 rwl = rw_remap ( orig );
sewardj2d8b3f02002-06-01 14:14:19 +00002736 res = __pthread_mutex_lock(&rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00002737 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002738 if (!rwl->initted) {
2739 res = __pthread_mutex_unlock(&rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00002740 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002741 return EINVAL;
2742 }
2743 if (rwl->status != 0) {
2744 rwl->nwait_w++;
2745 pthread_cleanup_push( pthread_rwlock_wrlock_CANCEL_HDLR, rwl );
2746 while (1) {
2747 if (rwl->status == 0) break;
2748 res = pthread_cond_wait(&rwl->cv_w, &rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00002749 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002750 }
2751 pthread_cleanup_pop(0);
2752 rwl->nwait_w--;
2753 }
sewardj2d94c112002-06-03 01:25:54 +00002754 my_assert(rwl->status == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002755 rwl->status = -1;
2756 res = __pthread_mutex_unlock(&rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00002757 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002758 return 0;
sewardja1ac5cb2002-05-27 13:00:05 +00002759}
2760
sewardj2d8b3f02002-06-01 14:14:19 +00002761
sewardja1ac5cb2002-05-27 13:00:05 +00002762int pthread_rwlock_trywrlock ( pthread_rwlock_t* orig )
2763{
2764 int res;
2765 vg_rwlock_t* rwl;
sewardj2d8b3f02002-06-01 14:14:19 +00002766 if (0) printf ("pthread_wrlock_trywrlock\n");
sewardja1ac5cb2002-05-27 13:00:05 +00002767 rwl = rw_remap ( orig );
sewardj2d8b3f02002-06-01 14:14:19 +00002768 res = __pthread_mutex_lock(&rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00002769 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002770 if (!rwl->initted) {
2771 res = __pthread_mutex_unlock(&rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00002772 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002773 return EINVAL;
2774 }
2775 if (rwl->status != 0) {
2776 /* Reader(s) or a writer active; we have to give up. */
2777 res = __pthread_mutex_unlock(&rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00002778 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002779 return EBUSY;
2780 }
2781 /* Success */
sewardj2d94c112002-06-03 01:25:54 +00002782 my_assert(rwl->status == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002783 rwl->status = -1;
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 0;
sewardja1ac5cb2002-05-27 13:00:05 +00002787}
2788
sewardj2d8b3f02002-06-01 14:14:19 +00002789
sewardja1ac5cb2002-05-27 13:00:05 +00002790int pthread_rwlock_unlock ( pthread_rwlock_t* orig )
2791{
2792 int res;
2793 vg_rwlock_t* rwl;
2794 if (0) printf ("pthread_rwlock_unlock\n");
2795 rwl = rw_remap ( orig );
sewardj2d8b3f02002-06-01 14:14:19 +00002796 rwl = rw_remap ( orig );
2797 res = __pthread_mutex_lock(&rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00002798 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002799 if (!rwl->initted) {
2800 res = __pthread_mutex_unlock(&rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00002801 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002802 return EINVAL;
2803 }
2804 if (rwl->status == 0) {
2805 res = __pthread_mutex_unlock(&rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00002806 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002807 return EPERM;
2808 }
sewardj2d94c112002-06-03 01:25:54 +00002809 my_assert(rwl->status != 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002810 if (rwl->status == -1) {
2811 rwl->status = 0;
2812 } else {
sewardj2d94c112002-06-03 01:25:54 +00002813 my_assert(rwl->status > 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002814 rwl->status--;
2815 }
2816
sewardj2d94c112002-06-03 01:25:54 +00002817 my_assert(rwl->status >= 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002818
2819 if (rwl->prefer_w) {
2820
2821 /* Favour waiting writers, if any. */
2822 if (rwl->nwait_w > 0) {
2823 /* Writer(s) are waiting. */
2824 if (rwl->status == 0) {
2825 /* We can let a writer in. */
2826 res = pthread_cond_signal(&rwl->cv_w);
sewardj2d94c112002-06-03 01:25:54 +00002827 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002828 } else {
2829 /* There are still readers active. Do nothing; eventually
2830 they will disappear, at which point a writer will be
2831 admitted. */
2832 }
2833 }
2834 else
2835 /* No waiting writers. */
2836 if (rwl->nwait_r > 0) {
2837 /* Let in a waiting reader. */
2838 res = pthread_cond_signal(&rwl->cv_r);
sewardj2d94c112002-06-03 01:25:54 +00002839 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002840 }
2841
2842 } else {
2843
2844 /* Favour waiting readers, if any. */
2845 if (rwl->nwait_r > 0) {
2846 /* Reader(s) are waiting; let one in. */
2847 res = pthread_cond_signal(&rwl->cv_r);
sewardj2d94c112002-06-03 01:25:54 +00002848 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002849 }
2850 else
2851 /* No waiting readers. */
2852 if (rwl->nwait_w > 0 && rwl->status == 0) {
2853 /* We have waiting writers and no active readers; let a
2854 writer in. */
2855 res = pthread_cond_signal(&rwl->cv_w);
sewardj2d94c112002-06-03 01:25:54 +00002856 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002857 }
2858 }
2859
2860 res = __pthread_mutex_unlock(&rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00002861 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002862 return 0;
2863}
2864
2865
2866int pthread_rwlock_destroy ( pthread_rwlock_t *orig )
2867{
2868 int res;
2869 vg_rwlock_t* rwl;
2870 if (0) printf ("pthread_rwlock_destroy\n");
2871 rwl = rw_remap ( orig );
2872 res = __pthread_mutex_lock(&rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00002873 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002874 if (!rwl->initted) {
2875 res = __pthread_mutex_unlock(&rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00002876 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002877 return EINVAL;
2878 }
2879 if (rwl->status != 0 || rwl->nwait_r > 0 || rwl->nwait_w > 0) {
2880 res = __pthread_mutex_unlock(&rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00002881 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002882 return EBUSY;
2883 }
2884 rwl->initted = 0;
2885 res = __pthread_mutex_unlock(&rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00002886 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002887 return 0;
sewardja1ac5cb2002-05-27 13:00:05 +00002888}
2889
2890
sewardj47e4e312002-06-18 09:24:34 +00002891/* Copied directly from LinuxThreads. */
2892int
2893pthread_rwlockattr_init (pthread_rwlockattr_t *attr)
2894{
2895 attr->__lockkind = 0;
2896 attr->__pshared = PTHREAD_PROCESS_PRIVATE;
2897
2898 return 0;
2899}
2900
sewardjfe18eb82002-07-13 12:58:44 +00002901/* Copied directly from LinuxThreads. */
2902int
sewardj5706bfa2002-12-08 23:42:17 +00002903pthread_rwlockattr_destroy (pthread_rwlockattr_t *attr)
2904{
2905 return 0;
2906}
2907
2908/* Copied directly from LinuxThreads. */
2909int
sewardjfe18eb82002-07-13 12:58:44 +00002910pthread_rwlockattr_setpshared (pthread_rwlockattr_t *attr, int pshared)
2911{
2912 if (pshared != PTHREAD_PROCESS_PRIVATE && pshared != PTHREAD_PROCESS_SHARED)
2913 return EINVAL;
2914
2915 /* For now it is not possible to shared a conditional variable. */
2916 if (pshared != PTHREAD_PROCESS_PRIVATE)
2917 return ENOSYS;
2918
2919 attr->__pshared = pshared;
2920
2921 return 0;
2922}
2923
sewardj47e4e312002-06-18 09:24:34 +00002924
sewardja1ac5cb2002-05-27 13:00:05 +00002925/* ---------------------------------------------------------------------
sewardj11f0bb42003-04-26 20:11:15 +00002926 Make SYSV IPC not block everything -- pass to vg_intercept.c.
sewardjd5bef572002-10-23 21:49:33 +00002927 ------------------------------------------------------------------ */
2928
sewardj11f0bb42003-04-26 20:11:15 +00002929WEAK
2930int msgsnd(int msgid, const void *msgp, size_t msgsz, int msgflg)
sewardjd5bef572002-10-23 21:49:33 +00002931{
sewardj11f0bb42003-04-26 20:11:15 +00002932 return VGR_(msgsnd)(msgid, msgp, msgsz, msgflg);
sewardjd5bef572002-10-23 21:49:33 +00002933}
2934
sewardj11f0bb42003-04-26 20:11:15 +00002935WEAK
2936int msgrcv(int msqid, void* msgp, size_t msgsz,
2937 long msgtyp, int msgflg )
sewardjd5bef572002-10-23 21:49:33 +00002938{
sewardj11f0bb42003-04-26 20:11:15 +00002939 return VGR_(msgrcv)(msqid, msgp, msgsz, msgtyp, msgflg );
sewardjd5bef572002-10-23 21:49:33 +00002940}
2941
sewardj262b5be2003-04-26 21:19:53 +00002942
2943/* ---------------------------------------------------------------------
2944 The glibc sources say that returning -1 in these 3 functions
2945 causes real time signals not to be used.
2946 ------------------------------------------------------------------ */
2947
2948int __libc_current_sigrtmin (void)
2949{
2950 static int moans = N_MOANS;
2951 if (moans-- > 0)
2952 kludged("__libc_current_sigrtmin");
2953 return -1;
2954}
2955
2956int __libc_current_sigrtmax (void)
2957{
2958 static int moans = N_MOANS;
2959 if (moans-- > 0)
2960 kludged("__libc_current_sigrtmax");
2961 return -1;
2962}
2963
2964int __libc_allocate_rtsig (int high)
2965{
2966 static int moans = N_MOANS;
2967 if (moans-- > 0)
2968 kludged("__libc_allocate_rtsig");
2969 return -1;
2970}
2971
2972
sewardjd5bef572002-10-23 21:49:33 +00002973/* ---------------------------------------------------------------------
sewardj3b13f0e2002-04-25 20:17:29 +00002974 B'stard.
2975 ------------------------------------------------------------------ */
2976
2977# define strong_alias(name, aliasname) \
2978 extern __typeof (name) aliasname __attribute__ ((alias (#name)));
2979
sewardj5905fae2002-04-26 13:25:00 +00002980# define weak_alias(name, aliasname) \
2981 extern __typeof (name) aliasname __attribute__ ((weak, alias (#name)));
sewardj3b13f0e2002-04-25 20:17:29 +00002982
sewardj5905fae2002-04-26 13:25:00 +00002983strong_alias(__pthread_mutex_lock, pthread_mutex_lock)
2984strong_alias(__pthread_mutex_trylock, pthread_mutex_trylock)
2985strong_alias(__pthread_mutex_unlock, pthread_mutex_unlock)
2986strong_alias(__pthread_mutexattr_init, pthread_mutexattr_init)
2987 weak_alias(__pthread_mutexattr_settype, pthread_mutexattr_settype)
2988strong_alias(__pthread_mutex_init, pthread_mutex_init)
2989strong_alias(__pthread_mutexattr_destroy, pthread_mutexattr_destroy)
2990strong_alias(__pthread_mutex_destroy, pthread_mutex_destroy)
2991strong_alias(__pthread_once, pthread_once)
2992strong_alias(__pthread_atfork, pthread_atfork)
2993strong_alias(__pthread_key_create, pthread_key_create)
2994strong_alias(__pthread_getspecific, pthread_getspecific)
2995strong_alias(__pthread_setspecific, pthread_setspecific)
2996
sewardjd529a442002-05-04 19:49:21 +00002997#ifndef GLIBC_2_1
sewardj3b13f0e2002-04-25 20:17:29 +00002998strong_alias(sigaction, __sigaction)
sewardjd529a442002-05-04 19:49:21 +00002999#endif
3000
sewardj5905fae2002-04-26 13:25:00 +00003001strong_alias(close, __close)
sewardj3b13f0e2002-04-25 20:17:29 +00003002strong_alias(fcntl, __fcntl)
sewardj5905fae2002-04-26 13:25:00 +00003003strong_alias(lseek, __lseek)
3004strong_alias(open, __open)
3005strong_alias(open64, __open64)
sewardj5905fae2002-04-26 13:25:00 +00003006strong_alias(read, __read)
3007strong_alias(wait, __wait)
3008strong_alias(write, __write)
sewardj3b13f0e2002-04-25 20:17:29 +00003009strong_alias(connect, __connect)
sewardj5905fae2002-04-26 13:25:00 +00003010strong_alias(send, __send)
3011
sewardj726c4122002-05-16 23:39:10 +00003012weak_alias (__pread64, pread64)
sewardja18e2102002-05-18 10:43:22 +00003013weak_alias (__pwrite64, pwrite64)
sewardj5905fae2002-04-26 13:25:00 +00003014weak_alias(__fork, fork)
njn25e49d8e72002-09-23 09:36:25 +00003015weak_alias(__vfork, vfork)
sewardj7f6456d2002-05-21 00:51:21 +00003016
sewardjf0b06452002-06-04 08:38:04 +00003017weak_alias (__pthread_kill_other_threads_np, pthread_kill_other_threads_np)
sewardj3b13f0e2002-04-25 20:17:29 +00003018
3019/*--------------------------------------------------*/
3020
sewardj5905fae2002-04-26 13:25:00 +00003021weak_alias(pthread_rwlock_rdlock, __pthread_rwlock_rdlock)
sewardj5905fae2002-04-26 13:25:00 +00003022weak_alias(pthread_rwlock_unlock, __pthread_rwlock_unlock)
sewardj262b0292002-05-01 00:03:16 +00003023weak_alias(pthread_rwlock_wrlock, __pthread_rwlock_wrlock)
sewardj060b04f2002-04-26 21:01:13 +00003024
sewardja1ac5cb2002-05-27 13:00:05 +00003025weak_alias(pthread_rwlock_destroy, __pthread_rwlock_destroy)
3026weak_alias(pthread_rwlock_init, __pthread_rwlock_init)
3027weak_alias(pthread_rwlock_tryrdlock, __pthread_rwlock_tryrdlock)
3028weak_alias(pthread_rwlock_trywrlock, __pthread_rwlock_trywrlock)
3029
sewardj060b04f2002-04-26 21:01:13 +00003030
sewardj3b13f0e2002-04-25 20:17:29 +00003031/* I've no idea what these are, but they get called quite a lot.
3032 Anybody know? */
3033
3034#undef _IO_flockfile
3035void _IO_flockfile ( _IO_FILE * file )
3036{
sewardj853f55d2002-04-26 00:27:53 +00003037 pthread_mutex_lock(file->_lock);
sewardj3b13f0e2002-04-25 20:17:29 +00003038}
sewardj5905fae2002-04-26 13:25:00 +00003039weak_alias(_IO_flockfile, flockfile);
3040
sewardj3b13f0e2002-04-25 20:17:29 +00003041
3042#undef _IO_funlockfile
3043void _IO_funlockfile ( _IO_FILE * file )
3044{
sewardj853f55d2002-04-26 00:27:53 +00003045 pthread_mutex_unlock(file->_lock);
sewardj3b13f0e2002-04-25 20:17:29 +00003046}
sewardj5905fae2002-04-26 13:25:00 +00003047weak_alias(_IO_funlockfile, funlockfile);
3048
sewardj3b13f0e2002-04-25 20:17:29 +00003049
sewardjd4f2c712002-04-30 10:20:10 +00003050/* This doesn't seem to be needed to simulate libpthread.so's external
3051 interface, but many people complain about its absence. */
3052
3053strong_alias(__pthread_mutexattr_settype, __pthread_mutexattr_setkind_np)
3054weak_alias(__pthread_mutexattr_setkind_np, pthread_mutexattr_setkind_np)
sewardj439d45e2002-05-03 20:43:10 +00003055
3056
3057/*--------------------------------------------------------------------*/
3058/*--- end vg_libpthread.c ---*/
3059/*--------------------------------------------------------------------*/