blob: e1dc7875fb49861d363eec8a87479a16e20b5629 [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
11 Copyright (C) 2000-2002 Julian Seward
12 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
55#include "valgrind.h" /* For the request-passing mechanism */
56#include "vg_include.h" /* For the VG_USERREQ__* constants */
57
sewardja1ac5cb2002-05-27 13:00:05 +000058#define __USE_UNIX98
59#include <sys/types.h>
60#include <pthread.h>
61#undef __USE_UNIX98
62
sewardje663cb92002-04-12 10:26:32 +000063#include <unistd.h>
64#include <string.h>
sewardj2a1dcce2002-04-22 12:45:25 +000065#ifdef GLIBC_2_1
66#include <sys/time.h>
67#endif
sewardjf912dfc2002-11-13 21:51:10 +000068#include <sys/stat.h>
69#include <sys/poll.h>
sewardj2d94c112002-06-03 01:25:54 +000070#include <stdio.h>
71
sewardj705d3cb2002-05-23 13:13:12 +000072
73/* ---------------------------------------------------------------------
74 Forwardses.
75 ------------------------------------------------------------------ */
76
77static void wait_for_fd_to_be_readable_or_erring ( int fd );
sewardj12a0e042002-11-30 14:02:53 +000078static void wait_for_fd_to_be_writable_or_erring ( int fd );
sewardj705d3cb2002-05-23 13:13:12 +000079
sewardj9a2224b2002-06-19 10:17:40 +000080static
sewardj08c7f012002-10-07 23:56:55 +000081int my_do_syscall1 ( int syscallno, int arg1 );
82
83static
sewardj9a2224b2002-06-19 10:17:40 +000084int my_do_syscall2 ( int syscallno,
85 int arg1, int arg2 );
86
sewardj08c7f012002-10-07 23:56:55 +000087static
88int my_do_syscall3 ( int syscallno,
89 int arg1, int arg2, int arg3 );
90
sewardjfd7747b2002-12-01 10:25:53 +000091static
92__inline__
93int is_kerror ( int res )
94{
95 if (res >= -4095 && res <= -1)
96 return 1;
97 else
98 return 0;
99}
100
sewardj08c7f012002-10-07 23:56:55 +0000101
102#ifdef GLIBC_2_3
103 /* kludge by JRS (not from glibc) ... */
104 typedef void* __locale_t;
105
106 /* Copied from locale/locale.h in glibc-2.2.93 sources */
107 /* This value can be passed to `uselocale' and may be returned by
108 it. Passing this value to any other function has undefined
109 behavior. */
110# define LC_GLOBAL_LOCALE ((__locale_t) -1L)
111 extern __locale_t __uselocale ( __locale_t );
112#endif
113
sewardj00a66b12002-10-12 16:42:35 +0000114static
115void init_libc_tsd_keys ( void );
116
sewardj705d3cb2002-05-23 13:13:12 +0000117
sewardje663cb92002-04-12 10:26:32 +0000118/* ---------------------------------------------------------------------
119 Helpers. We have to be pretty self-sufficient.
120 ------------------------------------------------------------------ */
121
sewardj436e0582002-04-26 14:31:40 +0000122/* Number of times any given error message is printed. */
123#define N_MOANS 3
124
sewardj45b4b372002-04-16 22:50:32 +0000125/* Extract from Valgrind the value of VG_(clo_trace_pthread_level).
126 Returns 0 (none) if not running on Valgrind. */
127static
128int get_pt_trace_level ( void )
129{
130 int res;
131 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
132 VG_USERREQ__GET_PTHREAD_TRACE_LEVEL,
133 0, 0, 0, 0);
134 return res;
135}
136
sewardje663cb92002-04-12 10:26:32 +0000137static
sewardj2d94c112002-06-03 01:25:54 +0000138void my_exit ( int arg )
sewardje663cb92002-04-12 10:26:32 +0000139{
sewardj08c7f012002-10-07 23:56:55 +0000140 my_do_syscall1(__NR_exit, arg);
141 /*NOTREACHED*/
sewardje663cb92002-04-12 10:26:32 +0000142}
143
sewardje0cfe2a2002-11-30 14:04:45 +0000144/* Apparently unused.
sewardj08c7f012002-10-07 23:56:55 +0000145static
146void my_write ( int fd, const void *buf, int count )
147{
148 my_do_syscall3(__NR_write, fd, (int)buf, count );
149}
sewardje0cfe2a2002-11-30 14:04:45 +0000150*/
sewardje663cb92002-04-12 10:26:32 +0000151
sewardj68b2dd92002-05-10 21:03:56 +0000152/* We need this guy -- it's in valgrind.so. */
153extern void VG_(startup) ( void );
154
155
156/* Just start up Valgrind if it's not already going. VG_(startup)()
157 detects and ignores second and subsequent calls. */
sewardj604ec3c2002-04-18 22:38:41 +0000158static __inline__
sewardje663cb92002-04-12 10:26:32 +0000159void ensure_valgrind ( char* caller )
160{
sewardj68b2dd92002-05-10 21:03:56 +0000161 VG_(startup)();
sewardje663cb92002-04-12 10:26:32 +0000162}
163
sewardjbea1caa2002-05-10 23:20:58 +0000164/* While we're at it ... hook our own startup function into this
165 game. */
166__asm__ (
167 ".section .init\n"
168 "\tcall vgPlain_startup"
169);
170
sewardje663cb92002-04-12 10:26:32 +0000171
172static
sewardj3b5d8862002-04-20 13:53:23 +0000173__attribute__((noreturn))
sewardje663cb92002-04-12 10:26:32 +0000174void barf ( char* str )
175{
sewardj69a72a52002-11-03 13:41:41 +0000176 int res;
177 char buf[1000];
sewardje663cb92002-04-12 10:26:32 +0000178 buf[0] = 0;
sewardj439d45e2002-05-03 20:43:10 +0000179 strcat(buf, "\nvalgrind's libpthread.so: ");
sewardje663cb92002-04-12 10:26:32 +0000180 strcat(buf, str);
181 strcat(buf, "\n\n");
sewardj69a72a52002-11-03 13:41:41 +0000182 VALGRIND_MAGIC_SEQUENCE(res, 0, /* irrelevant default */
183 VG_USERREQ__LOGMESSAGE, buf, 0, 0, 0);
sewardj2d94c112002-06-03 01:25:54 +0000184 my_exit(1);
sewardj3b5d8862002-04-20 13:53:23 +0000185 /* We have to persuade gcc into believing this doesn't return. */
186 while (1) { };
sewardje663cb92002-04-12 10:26:32 +0000187}
188
189
sewardj69a72a52002-11-03 13:41:41 +0000190static void cat_n_send ( char* pre, char* msg )
sewardj2a3d28c2002-04-14 13:27:00 +0000191{
sewardj69a72a52002-11-03 13:41:41 +0000192 char buf[1000];
193 int res;
sewardj436e0582002-04-26 14:31:40 +0000194 if (get_pt_trace_level() >= 0) {
sewardj69a72a52002-11-03 13:41:41 +0000195 snprintf(buf, sizeof(buf), "%s%s", pre, msg );
196 buf[sizeof(buf)-1] = '\0';
197 VALGRIND_MAGIC_SEQUENCE(res, 0, /* irrelevant default */
198 VG_USERREQ__LOGMESSAGE, buf, 0, 0, 0);
sewardj45b4b372002-04-16 22:50:32 +0000199 }
sewardj2a3d28c2002-04-14 13:27:00 +0000200}
201
sewardj69a72a52002-11-03 13:41:41 +0000202static void ignored ( char* msg )
203{
204 cat_n_send ( "valgrind's libpthread.so: IGNORED call to: ", msg );
205}
206
207
sewardj30671ff2002-04-21 00:13:57 +0000208static void kludged ( char* msg )
209{
sewardj69a72a52002-11-03 13:41:41 +0000210 cat_n_send ( "valgrind's libpthread.so: KLUDGED call to: ", msg );
sewardj439d45e2002-05-03 20:43:10 +0000211}
212
sewardj69a72a52002-11-03 13:41:41 +0000213
sewardjccef2e62002-05-29 19:26:32 +0000214__attribute__((noreturn))
sewardj3b13f0e2002-04-25 20:17:29 +0000215void vgPlain_unimp ( char* what )
216{
sewardj69a72a52002-11-03 13:41:41 +0000217 cat_n_send (
218 "valgrind's libpthread.so: UNIMPLEMENTED FUNCTION: ", what );
sewardj3b13f0e2002-04-25 20:17:29 +0000219 barf("Please report this bug to me at: jseward@acm.org");
220}
221
sewardje663cb92002-04-12 10:26:32 +0000222
sewardj457cc472002-06-03 23:13:47 +0000223static
sewardj2d94c112002-06-03 01:25:54 +0000224void my_assert_fail ( Char* expr, Char* file, Int line, Char* fn )
225{
sewardj69a72a52002-11-03 13:41:41 +0000226 char buf[1000];
sewardj2d94c112002-06-03 01:25:54 +0000227 static Bool entered = False;
228 if (entered)
229 my_exit(2);
230 entered = True;
sewardj69a72a52002-11-03 13:41:41 +0000231 sprintf(buf, "\n%s: %s:%d (%s): Assertion `%s' failed.\n",
232 "valgrind", file, line, fn, expr );
233 cat_n_send ( "", buf );
234 sprintf(buf, "Please report this bug to me at: %s\n\n",
235 VG_EMAIL_ADDR);
236 cat_n_send ( "", buf );
sewardj2d94c112002-06-03 01:25:54 +0000237 my_exit(1);
238}
239
240#define MY__STRING(__str) #__str
241
242#define my_assert(expr) \
243 ((void) ((expr) ? 0 : \
244 (my_assert_fail (MY__STRING(expr), \
245 __FILE__, __LINE__, \
246 __PRETTY_FUNCTION__), 0)))
247
sewardj00a66b12002-10-12 16:42:35 +0000248static
249void my_free ( void* ptr )
250{
251 int res;
252 VALGRIND_MAGIC_SEQUENCE(res, (-1) /* default */,
253 VG_USERREQ__FREE, ptr, 0, 0, 0);
254 my_assert(res == 0);
255}
256
257
258static
259void* my_malloc ( int nbytes )
260{
261 void* res;
262 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
263 VG_USERREQ__MALLOC, nbytes, 0, 0, 0);
264 my_assert(res != (void*)0);
265 return res;
266}
267
268
sewardj2d94c112002-06-03 01:25:54 +0000269
sewardje663cb92002-04-12 10:26:32 +0000270/* ---------------------------------------------------------------------
271 Pass pthread_ calls to Valgrind's request mechanism.
272 ------------------------------------------------------------------ */
273
sewardjf8f819e2002-04-17 23:21:37 +0000274#include <errno.h>
sewardj5f07b662002-04-23 16:52:51 +0000275#include <sys/time.h> /* gettimeofday */
sewardjf8f819e2002-04-17 23:21:37 +0000276
sewardja1ac5cb2002-05-27 13:00:05 +0000277
sewardjf8f819e2002-04-17 23:21:37 +0000278/* ---------------------------------------------------
sewardj4dced352002-06-04 22:54:20 +0000279 Ummm ..
280 ------------------------------------------------ */
281
282static
283void pthread_error ( const char* msg )
284{
285 int res;
286 VALGRIND_MAGIC_SEQUENCE(res, 0,
287 VG_USERREQ__PTHREAD_ERROR,
288 msg, 0, 0, 0);
289}
290
291
292/* ---------------------------------------------------
sewardj00a66b12002-10-12 16:42:35 +0000293 Here so it can be inlined without complaint.
294 ------------------------------------------------ */
295
296__inline__
297pthread_t pthread_self(void)
298{
299 int tid;
300 ensure_valgrind("pthread_self");
301 VALGRIND_MAGIC_SEQUENCE(tid, 0 /* default */,
302 VG_USERREQ__PTHREAD_GET_THREADID,
303 0, 0, 0, 0);
304 if (tid < 1 || tid >= VG_N_THREADS)
305 barf("pthread_self: invalid ThreadId");
306 return tid;
307}
308
309
310/* ---------------------------------------------------
sewardjf8f819e2002-04-17 23:21:37 +0000311 THREAD ATTRIBUTES
312 ------------------------------------------------ */
313
sewardj6af4b5d2002-04-16 04:40:49 +0000314int pthread_attr_init(pthread_attr_t *attr)
315{
sewardj7989d0c2002-05-28 11:00:01 +0000316 /* Just initialise the fields which we might look at. */
317 attr->__detachstate = PTHREAD_CREATE_JOINABLE;
sewardj111b14c2002-10-20 16:22:57 +0000318 /* Linuxthreads sets this field to the value __getpagesize(), so I
319 guess the following is OK. */
320 attr->__guardsize = VKI_BYTES_PER_PAGE; return 0;
sewardj6af4b5d2002-04-16 04:40:49 +0000321}
322
323int pthread_attr_setdetachstate(pthread_attr_t *attr, int detachstate)
324{
sewardj7989d0c2002-05-28 11:00:01 +0000325 if (detachstate != PTHREAD_CREATE_JOINABLE
sewardj4dced352002-06-04 22:54:20 +0000326 && detachstate != PTHREAD_CREATE_DETACHED) {
327 pthread_error("pthread_attr_setdetachstate: "
328 "detachstate is invalid");
sewardj7989d0c2002-05-28 11:00:01 +0000329 return EINVAL;
sewardj4dced352002-06-04 22:54:20 +0000330 }
sewardj7989d0c2002-05-28 11:00:01 +0000331 attr->__detachstate = detachstate;
sewardj6af4b5d2002-04-16 04:40:49 +0000332 return 0;
333}
334
njn25e49d8e72002-09-23 09:36:25 +0000335int pthread_attr_getdetachstate(const pthread_attr_t *attr, int *detachstate)
336{
337 *detachstate = attr->__detachstate;
338 return 0;
339}
340
sewardj30671ff2002-04-21 00:13:57 +0000341int pthread_attr_setinheritsched(pthread_attr_t *attr, int inherit)
342{
sewardj436e0582002-04-26 14:31:40 +0000343 static int moans = N_MOANS;
344 if (moans-- > 0)
345 ignored("pthread_attr_setinheritsched");
sewardj30671ff2002-04-21 00:13:57 +0000346 return 0;
347}
sewardj6af4b5d2002-04-16 04:40:49 +0000348
sewardj0286dd52002-05-16 20:51:15 +0000349__attribute__((weak))
350int pthread_attr_setstacksize (pthread_attr_t *__attr,
351 size_t __stacksize)
352{
sewardja18e2102002-05-18 10:43:22 +0000353 size_t limit;
sewardj3d7c8d62002-06-04 20:59:16 +0000354 char buf[1024];
sewardj0286dd52002-05-16 20:51:15 +0000355 ensure_valgrind("pthread_attr_setstacksize");
sewardja18e2102002-05-18 10:43:22 +0000356 limit = VG_PTHREAD_STACK_SIZE - VG_AR_CLIENT_STACKBASE_REDZONE_SZB
357 - 1000; /* paranoia */
358 if (__stacksize < limit)
sewardj0286dd52002-05-16 20:51:15 +0000359 return 0;
sewardj3d7c8d62002-06-04 20:59:16 +0000360 snprintf(buf, sizeof(buf), "pthread_attr_setstacksize: "
361 "requested size %d >= VG_PTHREAD_STACK_SIZE\n "
362 "edit vg_include.h and rebuild.", __stacksize);
363 buf[sizeof(buf)-1] = '\0'; /* Make sure it is zero terminated */
364 barf(buf);
sewardj0286dd52002-05-16 20:51:15 +0000365}
366
367
sewardj30671ff2002-04-21 00:13:57 +0000368/* This is completely bogus. */
369int pthread_attr_getschedparam(const pthread_attr_t *attr,
370 struct sched_param *param)
371{
sewardj436e0582002-04-26 14:31:40 +0000372 static int moans = N_MOANS;
373 if (moans-- > 0)
374 kludged("pthread_attr_getschedparam");
sewardj3e909ce2002-06-03 13:27:15 +0000375# ifdef HAVE_SCHED_PRIORITY
sewardj72d58482002-04-24 02:20:20 +0000376 if (param) param->sched_priority = 0; /* who knows */
377# else
sewardj30671ff2002-04-21 00:13:57 +0000378 if (param) param->__sched_priority = 0; /* who knows */
sewardj72d58482002-04-24 02:20:20 +0000379# endif
sewardj30671ff2002-04-21 00:13:57 +0000380 return 0;
381}
382
383int pthread_attr_setschedparam(pthread_attr_t *attr,
384 const struct sched_param *param)
385{
sewardj436e0582002-04-26 14:31:40 +0000386 static int moans = N_MOANS;
387 if (moans-- > 0)
388 ignored("pthread_attr_setschedparam");
sewardj30671ff2002-04-21 00:13:57 +0000389 return 0;
390}
391
392int pthread_attr_destroy(pthread_attr_t *attr)
393{
sewardj436e0582002-04-26 14:31:40 +0000394 static int moans = N_MOANS;
395 if (moans-- > 0)
396 ignored("pthread_attr_destroy");
sewardj30671ff2002-04-21 00:13:57 +0000397 return 0;
398}
sewardjf8f819e2002-04-17 23:21:37 +0000399
sewardj0d844232002-06-02 09:29:31 +0000400/* These are no-ops, as with LinuxThreads. */
401int pthread_attr_setscope ( pthread_attr_t *attr, int scope )
402{
403 ensure_valgrind("pthread_attr_setscope");
404 if (scope == PTHREAD_SCOPE_SYSTEM)
405 return 0;
sewardj4dced352002-06-04 22:54:20 +0000406 pthread_error("pthread_attr_setscope: "
407 "invalid or unsupported scope");
sewardj0d844232002-06-02 09:29:31 +0000408 if (scope == PTHREAD_SCOPE_PROCESS)
409 return ENOTSUP;
410 return EINVAL;
411}
412
413int pthread_attr_getscope ( const pthread_attr_t *attr, int *scope )
414{
415 ensure_valgrind("pthread_attr_setscope");
416 if (scope)
417 *scope = PTHREAD_SCOPE_SYSTEM;
418 return 0;
419}
420
sewardj64039bb2002-06-03 00:58:18 +0000421
422/* Pretty bogus. Avoid if possible. */
423int pthread_getattr_np (pthread_t thread, pthread_attr_t *attr)
424{
425 int detached;
426 size_t limit;
427 ensure_valgrind("pthread_getattr_np");
428 kludged("pthread_getattr_np");
429 limit = VG_PTHREAD_STACK_SIZE - VG_AR_CLIENT_STACKBASE_REDZONE_SZB
430 - 1000; /* paranoia */
431 attr->__detachstate = PTHREAD_CREATE_JOINABLE;
432 attr->__schedpolicy = SCHED_OTHER;
433 attr->__schedparam.sched_priority = 0;
434 attr->__inheritsched = PTHREAD_EXPLICIT_SCHED;
435 attr->__scope = PTHREAD_SCOPE_SYSTEM;
436 attr->__guardsize = VKI_BYTES_PER_PAGE;
437 attr->__stackaddr = NULL;
438 attr->__stackaddr_set = 0;
439 attr->__stacksize = limit;
440 VALGRIND_MAGIC_SEQUENCE(detached, (-1) /* default */,
441 VG_USERREQ__SET_OR_GET_DETACH,
442 2 /* get */, thread, 0, 0);
sewardj2d94c112002-06-03 01:25:54 +0000443 my_assert(detached == 0 || detached == 1);
sewardj64039bb2002-06-03 00:58:18 +0000444 if (detached)
445 attr->__detachstate = PTHREAD_CREATE_DETACHED;
446 return 0;
447}
448
449
450/* Bogus ... */
sewardj111b14c2002-10-20 16:22:57 +0000451__attribute__((weak))
sewardj64039bb2002-06-03 00:58:18 +0000452int pthread_attr_getstackaddr ( const pthread_attr_t * attr,
453 void ** stackaddr )
454{
455 ensure_valgrind("pthread_attr_getstackaddr");
456 kludged("pthread_attr_getstackaddr");
457 if (stackaddr)
458 *stackaddr = NULL;
459 return 0;
460}
461
462/* Not bogus (!) */
sewardj111b14c2002-10-20 16:22:57 +0000463__attribute__((weak))
sewardj64039bb2002-06-03 00:58:18 +0000464int pthread_attr_getstacksize ( const pthread_attr_t * _attr,
465 size_t * __stacksize )
466{
467 size_t limit;
468 ensure_valgrind("pthread_attr_getstacksize");
469 limit = VG_PTHREAD_STACK_SIZE - VG_AR_CLIENT_STACKBASE_REDZONE_SZB
470 - 1000; /* paranoia */
471 if (__stacksize)
472 *__stacksize = limit;
473 return 0;
474}
475
sewardja3be12f2002-06-17 12:19:44 +0000476int pthread_attr_setschedpolicy(pthread_attr_t *attr, int policy)
477{
478 if (policy != SCHED_OTHER && policy != SCHED_FIFO && policy != SCHED_RR)
479 return EINVAL;
480 attr->__schedpolicy = policy;
481 return 0;
482}
483
484int pthread_attr_getschedpolicy(const pthread_attr_t *attr, int *policy)
485{
486 *policy = attr->__schedpolicy;
487 return 0;
488}
489
490
sewardj111b14c2002-10-20 16:22:57 +0000491/* This is completely bogus. We reject all attempts to change it from
492 VKI_BYTES_PER_PAGE. I don't have a clue what it's for so it seems
493 safest to be paranoid. */
494__attribute__((weak))
495int pthread_attr_setguardsize(pthread_attr_t *attr, size_t guardsize)
496{
497 static int moans = N_MOANS;
498
499 if (guardsize == VKI_BYTES_PER_PAGE)
500 return 0;
501
502 if (moans-- > 0)
503 ignored("pthread_attr_setguardsize: ignoring guardsize != 4096");
504
505 return 0;
506}
507
508/* A straight copy of the LinuxThreads code. */
509__attribute__((weak))
510int pthread_attr_getguardsize(const pthread_attr_t *attr, size_t *guardsize)
511{
512 *guardsize = attr->__guardsize;
513 return 0;
514}
515
sewardjab2e1232002-12-26 12:16:11 +0000516/* Again, like LinuxThreads. */
517
518static int concurrency_current_level = 0;
519
sewardjb34e4db2002-12-08 23:51:32 +0000520__attribute__((weak))
521int pthread_setconcurrency(int new_level)
522{
523 if (new_level < 0)
524 return EINVAL;
sewardjab2e1232002-12-26 12:16:11 +0000525 else {
526 concurrency_current_level = new_level;
sewardjb34e4db2002-12-08 23:51:32 +0000527 return 0;
sewardjab2e1232002-12-26 12:16:11 +0000528 }
sewardjb34e4db2002-12-08 23:51:32 +0000529}
530
sewardjab2e1232002-12-26 12:16:11 +0000531__attribute__((weak))
532int pthread_getconcurrency(void)
533{
534 return concurrency_current_level;
535}
536
537
sewardj111b14c2002-10-20 16:22:57 +0000538
sewardj20917d82002-05-28 01:36:45 +0000539/* ---------------------------------------------------
540 Helper functions for running a thread
541 and for clearing up afterwards.
542 ------------------------------------------------ */
543
544/* All exiting threads eventually pass through here, bearing the
545 return value, or PTHREAD_CANCELED, in ret_val. */
546static
547__attribute__((noreturn))
548void thread_exit_wrapper ( void* ret_val )
549{
sewardj870497a2002-05-29 01:06:47 +0000550 int detached, res;
551 CleanupEntry cu;
552 pthread_key_t key;
sewardj00a66b12002-10-12 16:42:35 +0000553 void** specifics_ptr;
sewardj870497a2002-05-29 01:06:47 +0000554
sewardj20917d82002-05-28 01:36:45 +0000555 /* Run this thread's cleanup handlers. */
sewardj8ad94e12002-05-29 00:10:20 +0000556 while (1) {
557 VALGRIND_MAGIC_SEQUENCE(res, (-1) /* default */,
558 VG_USERREQ__CLEANUP_POP,
559 &cu, 0, 0, 0);
560 if (res == -1) break; /* stack empty */
sewardj2d94c112002-06-03 01:25:54 +0000561 my_assert(res == 0);
sewardj8ad94e12002-05-29 00:10:20 +0000562 if (0) printf("running exit cleanup handler");
563 cu.fn ( cu.arg );
564 }
565
sewardj870497a2002-05-29 01:06:47 +0000566 /* Run this thread's key finalizers. Really this should be run
567 PTHREAD_DESTRUCTOR_ITERATIONS times. */
568 for (key = 0; key < VG_N_THREAD_KEYS; key++) {
569 VALGRIND_MAGIC_SEQUENCE(res, (-2) /* default */,
570 VG_USERREQ__GET_KEY_D_AND_S,
571 key, &cu, 0, 0 );
572 if (res == 0) {
573 /* valid key */
574 if (cu.fn && cu.arg)
575 cu.fn /* destructor for key */
576 ( cu.arg /* specific for key for this thread */ );
577 continue;
578 }
sewardj2d94c112002-06-03 01:25:54 +0000579 my_assert(res == -1);
sewardj870497a2002-05-29 01:06:47 +0000580 }
sewardj20917d82002-05-28 01:36:45 +0000581
sewardj00a66b12002-10-12 16:42:35 +0000582 /* Free up my specifics space, if any. */
583 VALGRIND_MAGIC_SEQUENCE(specifics_ptr, 3 /* default */,
584 VG_USERREQ__PTHREAD_GETSPECIFIC_PTR,
585 pthread_self(), 0, 0, 0);
586 my_assert(specifics_ptr != (void**)3);
587 my_assert(specifics_ptr != (void**)1); /* 1 means invalid thread */
588 if (specifics_ptr != NULL)
589 my_free(specifics_ptr);
590
sewardj20917d82002-05-28 01:36:45 +0000591 /* Decide on my final disposition. */
592 VALGRIND_MAGIC_SEQUENCE(detached, (-1) /* default */,
593 VG_USERREQ__SET_OR_GET_DETACH,
sewardj7989d0c2002-05-28 11:00:01 +0000594 2 /* get */, pthread_self(), 0, 0);
sewardj2d94c112002-06-03 01:25:54 +0000595 my_assert(detached == 0 || detached == 1);
sewardj20917d82002-05-28 01:36:45 +0000596
597 if (detached) {
598 /* Detached; I just quit right now. */
599 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
600 VG_USERREQ__QUIT, 0, 0, 0, 0);
601 } else {
602 /* Not detached; so I wait for a joiner. */
603 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
604 VG_USERREQ__WAIT_JOINER, ret_val, 0, 0, 0);
605 }
606 /* NOTREACHED */
607 barf("thread_exit_wrapper: still alive?!");
608}
609
610
611/* This function is a wrapper function for running a thread. It runs
612 the root function specified in pthread_create, and then, should the
613 root function return a value, it arranges to run the thread's
614 cleanup handlers and exit correctly. */
615
sewardj728a5272002-06-20 10:25:37 +0000616/* Struct used to convey info from pthread_create to thread_wrapper.
617 Must be careful not to pass to the child thread any pointers to
618 objects which might be on the parent's stack. */
sewardj20917d82002-05-28 01:36:45 +0000619typedef
620 struct {
sewardj728a5272002-06-20 10:25:37 +0000621 int attr__detachstate;
sewardj20917d82002-05-28 01:36:45 +0000622 void* (*root_fn) ( void* );
623 void* arg;
624 }
625 NewThreadInfo;
626
627
628/* This is passed to the VG_USERREQ__APPLY_IN_NEW_THREAD and so must
629 not return. Note that this runs in the new thread, not the
630 parent. */
631static
632__attribute__((noreturn))
633void thread_wrapper ( NewThreadInfo* info )
634{
sewardj728a5272002-06-20 10:25:37 +0000635 int attr__detachstate;
sewardj20917d82002-05-28 01:36:45 +0000636 void* (*root_fn) ( void* );
637 void* arg;
638 void* ret_val;
639
sewardj728a5272002-06-20 10:25:37 +0000640 attr__detachstate = info->attr__detachstate;
641 root_fn = info->root_fn;
642 arg = info->arg;
sewardj20917d82002-05-28 01:36:45 +0000643
sewardj20917d82002-05-28 01:36:45 +0000644 /* Free up the arg block that pthread_create malloced. */
sewardj00a66b12002-10-12 16:42:35 +0000645 my_free(info);
sewardj20917d82002-05-28 01:36:45 +0000646
sewardj7989d0c2002-05-28 11:00:01 +0000647 /* Minimally observe the attributes supplied. */
sewardj728a5272002-06-20 10:25:37 +0000648 if (attr__detachstate != PTHREAD_CREATE_DETACHED
649 && attr__detachstate != PTHREAD_CREATE_JOINABLE)
650 pthread_error("thread_wrapper: invalid attr->__detachstate");
651 if (attr__detachstate == PTHREAD_CREATE_DETACHED)
652 pthread_detach(pthread_self());
sewardj7989d0c2002-05-28 11:00:01 +0000653
sewardj00a66b12002-10-12 16:42:35 +0000654# ifdef GLIBC_2_3
655 /* Set this thread's locale to the global (default) locale. A hack
656 in support of glibc-2.3. This does the biz for the all new
657 threads; the root thread is done with a horrible hack in
658 init_libc_tsd_keys() below.
659 */
660 __uselocale(LC_GLOBAL_LOCALE);
661# endif
662
sewardj20917d82002-05-28 01:36:45 +0000663 /* The root function might not return. But if it does we simply
664 move along to thread_exit_wrapper. All other ways out for the
665 thread (cancellation, or calling pthread_exit) lead there
666 too. */
667 ret_val = root_fn(arg);
668 thread_exit_wrapper(ret_val);
669 /* NOTREACHED */
670}
671
672
sewardjf8f819e2002-04-17 23:21:37 +0000673/* ---------------------------------------------------
674 THREADs
675 ------------------------------------------------ */
676
sewardjff42d1d2002-05-22 13:17:31 +0000677__attribute__((weak))
678int pthread_yield ( void )
679{
680 int res;
681 ensure_valgrind("pthread_yield");
682 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
683 VG_USERREQ__PTHREAD_YIELD, 0, 0, 0, 0);
684 return 0;
685}
686
687
sewardj6072c362002-04-19 14:40:57 +0000688int pthread_equal(pthread_t thread1, pthread_t thread2)
689{
690 return thread1 == thread2 ? 1 : 0;
691}
692
693
sewardj20917d82002-05-28 01:36:45 +0000694/* Bundle up the args into a malloc'd block and create a new thread
695 consisting of thread_wrapper() applied to said malloc'd block. */
sewardje663cb92002-04-12 10:26:32 +0000696int
sewardj1462c8b2002-07-24 09:41:52 +0000697pthread_create (pthread_t *__restrict __thredd,
sewardje663cb92002-04-12 10:26:32 +0000698 __const pthread_attr_t *__restrict __attr,
699 void *(*__start_routine) (void *),
700 void *__restrict __arg)
701{
sewardj20917d82002-05-28 01:36:45 +0000702 int tid_child;
703 NewThreadInfo* info;
sewardje663cb92002-04-12 10:26:32 +0000704
sewardj20917d82002-05-28 01:36:45 +0000705 ensure_valgrind("pthread_create");
706
sewardj00a66b12002-10-12 16:42:35 +0000707 /* make sure the tsd keys, and hence locale info, are initialised
708 before we get into complications making new threads. */
709 init_libc_tsd_keys();
710
sewardj20917d82002-05-28 01:36:45 +0000711 /* Allocate space for the arg block. thread_wrapper will free
712 it. */
sewardj00a66b12002-10-12 16:42:35 +0000713 info = my_malloc(sizeof(NewThreadInfo));
sewardj2d94c112002-06-03 01:25:54 +0000714 my_assert(info != NULL);
sewardj20917d82002-05-28 01:36:45 +0000715
sewardj728a5272002-06-20 10:25:37 +0000716 if (__attr)
717 info->attr__detachstate = __attr->__detachstate;
718 else
719 info->attr__detachstate = PTHREAD_CREATE_JOINABLE;
720
sewardj20917d82002-05-28 01:36:45 +0000721 info->root_fn = __start_routine;
722 info->arg = __arg;
723 VALGRIND_MAGIC_SEQUENCE(tid_child, VG_INVALID_THREADID /* default */,
724 VG_USERREQ__APPLY_IN_NEW_THREAD,
725 &thread_wrapper, info, 0, 0);
sewardj2d94c112002-06-03 01:25:54 +0000726 my_assert(tid_child != VG_INVALID_THREADID);
sewardj20917d82002-05-28 01:36:45 +0000727
sewardj1462c8b2002-07-24 09:41:52 +0000728 if (__thredd)
729 *__thredd = tid_child;
sewardj20917d82002-05-28 01:36:45 +0000730 return 0; /* success */
731}
sewardje663cb92002-04-12 10:26:32 +0000732
733
734int
735pthread_join (pthread_t __th, void **__thread_return)
736{
737 int res;
738 ensure_valgrind("pthread_join");
739 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
740 VG_USERREQ__PTHREAD_JOIN,
741 __th, __thread_return, 0, 0);
742 return res;
743}
744
745
sewardj3b5d8862002-04-20 13:53:23 +0000746void pthread_exit(void *retval)
747{
sewardj3b5d8862002-04-20 13:53:23 +0000748 ensure_valgrind("pthread_exit");
sewardj20917d82002-05-28 01:36:45 +0000749 /* Simple! */
750 thread_exit_wrapper(retval);
sewardj3b5d8862002-04-20 13:53:23 +0000751}
752
sewardje663cb92002-04-12 10:26:32 +0000753
sewardj853f55d2002-04-26 00:27:53 +0000754int pthread_detach(pthread_t th)
755{
sewardj20917d82002-05-28 01:36:45 +0000756 int res;
757 ensure_valgrind("pthread_detach");
sewardj7989d0c2002-05-28 11:00:01 +0000758 /* First we enquire as to the current detach state. */
759 VALGRIND_MAGIC_SEQUENCE(res, (-2) /* default */,
sewardj20917d82002-05-28 01:36:45 +0000760 VG_USERREQ__SET_OR_GET_DETACH,
sewardj7989d0c2002-05-28 11:00:01 +0000761 2 /* get */, th, 0, 0);
sewardj4dced352002-06-04 22:54:20 +0000762 if (res == -1) {
763 /* not found */
764 pthread_error("pthread_detach: "
765 "invalid target thread");
sewardj7989d0c2002-05-28 11:00:01 +0000766 return ESRCH;
sewardj4dced352002-06-04 22:54:20 +0000767 }
768 if (res == 1) {
769 /* already detached */
770 pthread_error("pthread_detach: "
771 "target thread is already detached");
sewardj7989d0c2002-05-28 11:00:01 +0000772 return EINVAL;
sewardj4dced352002-06-04 22:54:20 +0000773 }
sewardj7989d0c2002-05-28 11:00:01 +0000774 if (res == 0) {
775 VALGRIND_MAGIC_SEQUENCE(res, (-2) /* default */,
776 VG_USERREQ__SET_OR_GET_DETACH,
777 1 /* set */, th, 0, 0);
sewardj2d94c112002-06-03 01:25:54 +0000778 my_assert(res == 0);
sewardj7989d0c2002-05-28 11:00:01 +0000779 return 0;
780 }
781 barf("pthread_detach");
sewardj853f55d2002-04-26 00:27:53 +0000782}
783
784
sewardjf8f819e2002-04-17 23:21:37 +0000785/* ---------------------------------------------------
sewardj8ad94e12002-05-29 00:10:20 +0000786 CLEANUP STACKS
787 ------------------------------------------------ */
788
789void _pthread_cleanup_push (struct _pthread_cleanup_buffer *__buffer,
790 void (*__routine) (void *),
791 void *__arg)
792{
793 int res;
794 CleanupEntry cu;
795 ensure_valgrind("_pthread_cleanup_push");
796 cu.fn = __routine;
797 cu.arg = __arg;
798 VALGRIND_MAGIC_SEQUENCE(res, (-1) /* default */,
799 VG_USERREQ__CLEANUP_PUSH,
800 &cu, 0, 0, 0);
sewardj2d94c112002-06-03 01:25:54 +0000801 my_assert(res == 0);
sewardj8ad94e12002-05-29 00:10:20 +0000802}
803
804
805void _pthread_cleanup_push_defer (struct _pthread_cleanup_buffer *__buffer,
806 void (*__routine) (void *),
807 void *__arg)
808{
809 /* As _pthread_cleanup_push, but first save the thread's original
810 cancellation type in __buffer and set it to Deferred. */
811 int orig_ctype;
812 ensure_valgrind("_pthread_cleanup_push_defer");
813 /* Set to Deferred, and put the old cancellation type in res. */
sewardj2d94c112002-06-03 01:25:54 +0000814 my_assert(-1 != PTHREAD_CANCEL_DEFERRED);
815 my_assert(-1 != PTHREAD_CANCEL_ASYNCHRONOUS);
816 my_assert(sizeof(struct _pthread_cleanup_buffer) >= sizeof(int));
sewardj8ad94e12002-05-29 00:10:20 +0000817 VALGRIND_MAGIC_SEQUENCE(orig_ctype, (-1) /* default */,
818 VG_USERREQ__SET_CANCELTYPE,
819 PTHREAD_CANCEL_DEFERRED, 0, 0, 0);
sewardj2d94c112002-06-03 01:25:54 +0000820 my_assert(orig_ctype != -1);
sewardj8ad94e12002-05-29 00:10:20 +0000821 *((int*)(__buffer)) = orig_ctype;
822 /* Now push the cleanup. */
823 _pthread_cleanup_push(NULL, __routine, __arg);
824}
825
826
827void _pthread_cleanup_pop (struct _pthread_cleanup_buffer *__buffer,
828 int __execute)
829{
830 int res;
831 CleanupEntry cu;
832 ensure_valgrind("_pthread_cleanup_push");
833 cu.fn = cu.arg = NULL; /* paranoia */
834 VALGRIND_MAGIC_SEQUENCE(res, (-1) /* default */,
835 VG_USERREQ__CLEANUP_POP,
836 &cu, 0, 0, 0);
837 if (res == 0) {
838 /* pop succeeded */
839 if (__execute) {
840 cu.fn ( cu.arg );
841 }
842 return;
843 }
844 if (res == -1) {
845 /* stack underflow */
846 return;
847 }
848 barf("_pthread_cleanup_pop");
849}
850
851
852void _pthread_cleanup_pop_restore (struct _pthread_cleanup_buffer *__buffer,
853 int __execute)
854{
855 int orig_ctype, fake_ctype;
856 /* As _pthread_cleanup_pop, but after popping/running the handler,
857 restore the thread's original cancellation type from the first
858 word of __buffer. */
859 _pthread_cleanup_pop(NULL, __execute);
860 orig_ctype = *((int*)(__buffer));
sewardj2d94c112002-06-03 01:25:54 +0000861 my_assert(orig_ctype == PTHREAD_CANCEL_DEFERRED
sewardj8ad94e12002-05-29 00:10:20 +0000862 || orig_ctype == PTHREAD_CANCEL_ASYNCHRONOUS);
sewardj2d94c112002-06-03 01:25:54 +0000863 my_assert(-1 != PTHREAD_CANCEL_DEFERRED);
864 my_assert(-1 != PTHREAD_CANCEL_ASYNCHRONOUS);
865 my_assert(sizeof(struct _pthread_cleanup_buffer) >= sizeof(int));
sewardj8ad94e12002-05-29 00:10:20 +0000866 VALGRIND_MAGIC_SEQUENCE(fake_ctype, (-1) /* default */,
867 VG_USERREQ__SET_CANCELTYPE,
868 orig_ctype, 0, 0, 0);
sewardj2d94c112002-06-03 01:25:54 +0000869 my_assert(fake_ctype == PTHREAD_CANCEL_DEFERRED);
sewardj8ad94e12002-05-29 00:10:20 +0000870}
871
872
873/* ---------------------------------------------------
sewardjf8f819e2002-04-17 23:21:37 +0000874 MUTEX ATTRIBUTES
875 ------------------------------------------------ */
876
sewardj5905fae2002-04-26 13:25:00 +0000877int __pthread_mutexattr_init(pthread_mutexattr_t *attr)
sewardje663cb92002-04-12 10:26:32 +0000878{
sewardjf8f819e2002-04-17 23:21:37 +0000879 attr->__mutexkind = PTHREAD_MUTEX_ERRORCHECK_NP;
sewardj8937c812002-04-12 20:12:20 +0000880 return 0;
sewardje663cb92002-04-12 10:26:32 +0000881}
882
sewardj5905fae2002-04-26 13:25:00 +0000883int __pthread_mutexattr_settype(pthread_mutexattr_t *attr, int type)
sewardjf8f819e2002-04-17 23:21:37 +0000884{
885 switch (type) {
sewardj3b13f0e2002-04-25 20:17:29 +0000886# ifndef GLIBC_2_1
sewardjf8f819e2002-04-17 23:21:37 +0000887 case PTHREAD_MUTEX_TIMED_NP:
sewardj2a1dcce2002-04-22 12:45:25 +0000888 case PTHREAD_MUTEX_ADAPTIVE_NP:
sewardj3b13f0e2002-04-25 20:17:29 +0000889# endif
sewardja1679dd2002-05-10 22:31:40 +0000890# ifdef GLIBC_2_1
sewardj68b2dd92002-05-10 21:03:56 +0000891 case PTHREAD_MUTEX_FAST_NP:
sewardja1679dd2002-05-10 22:31:40 +0000892# endif
sewardjf8f819e2002-04-17 23:21:37 +0000893 case PTHREAD_MUTEX_RECURSIVE_NP:
894 case PTHREAD_MUTEX_ERRORCHECK_NP:
sewardjf8f819e2002-04-17 23:21:37 +0000895 attr->__mutexkind = type;
896 return 0;
897 default:
sewardj4dced352002-06-04 22:54:20 +0000898 pthread_error("pthread_mutexattr_settype: "
899 "invalid type");
sewardjf8f819e2002-04-17 23:21:37 +0000900 return EINVAL;
901 }
902}
903
sewardj5905fae2002-04-26 13:25:00 +0000904int __pthread_mutexattr_destroy(pthread_mutexattr_t *attr)
sewardjf8f819e2002-04-17 23:21:37 +0000905{
906 return 0;
907}
908
909
910/* ---------------------------------------------------
911 MUTEXes
912 ------------------------------------------------ */
913
sewardj5905fae2002-04-26 13:25:00 +0000914int __pthread_mutex_init(pthread_mutex_t *mutex,
915 const pthread_mutexattr_t *mutexattr)
sewardje663cb92002-04-12 10:26:32 +0000916{
sewardj604ec3c2002-04-18 22:38:41 +0000917 mutex->__m_count = 0;
918 mutex->__m_owner = (_pthread_descr)VG_INVALID_THREADID;
919 mutex->__m_kind = PTHREAD_MUTEX_ERRORCHECK_NP;
920 if (mutexattr)
921 mutex->__m_kind = mutexattr->__mutexkind;
922 return 0;
sewardje663cb92002-04-12 10:26:32 +0000923}
924
sewardj439d45e2002-05-03 20:43:10 +0000925
sewardj5905fae2002-04-26 13:25:00 +0000926int __pthread_mutex_lock(pthread_mutex_t *mutex)
sewardje663cb92002-04-12 10:26:32 +0000927{
928 int res;
sewardjd8acdf22002-11-13 21:57:52 +0000929
sewardj439d45e2002-05-03 20:43:10 +0000930 if (RUNNING_ON_VALGRIND) {
sewardje663cb92002-04-12 10:26:32 +0000931 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
932 VG_USERREQ__PTHREAD_MUTEX_LOCK,
933 mutex, 0, 0, 0);
934 return res;
sewardj439d45e2002-05-03 20:43:10 +0000935 } else {
sewardjd8acdf22002-11-13 21:57:52 +0000936 /* Play at locking */
937 if (0)
938 kludged("prehistoric lock");
939 mutex->__m_owner = (_pthread_descr)1;
940 mutex->__m_count = 1;
941 mutex->__m_kind |= VG_PTHREAD_PREHISTORY;
sewardj439d45e2002-05-03 20:43:10 +0000942 return 0; /* success */
sewardje663cb92002-04-12 10:26:32 +0000943 }
944}
945
sewardj439d45e2002-05-03 20:43:10 +0000946
sewardj5905fae2002-04-26 13:25:00 +0000947int __pthread_mutex_trylock(pthread_mutex_t *mutex)
sewardj30671ff2002-04-21 00:13:57 +0000948{
949 int res;
sewardjd8acdf22002-11-13 21:57:52 +0000950
sewardj439d45e2002-05-03 20:43:10 +0000951 if (RUNNING_ON_VALGRIND) {
sewardj30671ff2002-04-21 00:13:57 +0000952 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
953 VG_USERREQ__PTHREAD_MUTEX_TRYLOCK,
954 mutex, 0, 0, 0);
955 return res;
sewardj439d45e2002-05-03 20:43:10 +0000956 } else {
sewardjd8acdf22002-11-13 21:57:52 +0000957 /* Play at locking */
958 if (0)
959 kludged("prehistoric trylock");
960 mutex->__m_owner = (_pthread_descr)1;
961 mutex->__m_count = 1;
962 mutex->__m_kind |= VG_PTHREAD_PREHISTORY;
963 return 0; /* success */
sewardj30671ff2002-04-21 00:13:57 +0000964 }
965}
966
sewardj439d45e2002-05-03 20:43:10 +0000967
sewardj5905fae2002-04-26 13:25:00 +0000968int __pthread_mutex_unlock(pthread_mutex_t *mutex)
sewardje663cb92002-04-12 10:26:32 +0000969{
970 int res;
sewardjd8acdf22002-11-13 21:57:52 +0000971
sewardj439d45e2002-05-03 20:43:10 +0000972 if (RUNNING_ON_VALGRIND) {
sewardje663cb92002-04-12 10:26:32 +0000973 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
974 VG_USERREQ__PTHREAD_MUTEX_UNLOCK,
975 mutex, 0, 0, 0);
976 return res;
sewardj439d45e2002-05-03 20:43:10 +0000977 } else {
sewardjd8acdf22002-11-13 21:57:52 +0000978 /* Play at locking */
979 if (0)
980 kludged("prehistoric unlock");
981 mutex->__m_owner = 0;
982 mutex->__m_count = 0;
983 mutex->__m_kind &= ~VG_PTHREAD_PREHISTORY;
984 return 0; /* success */
sewardje663cb92002-04-12 10:26:32 +0000985 }
986}
987
sewardj439d45e2002-05-03 20:43:10 +0000988
sewardj5905fae2002-04-26 13:25:00 +0000989int __pthread_mutex_destroy(pthread_mutex_t *mutex)
sewardje663cb92002-04-12 10:26:32 +0000990{
sewardj604ec3c2002-04-18 22:38:41 +0000991 /* Valgrind doesn't hold any resources on behalf of the mutex, so no
992 need to involve it. */
sewardj4dced352002-06-04 22:54:20 +0000993 if (mutex->__m_count > 0) {
sewardjd8acdf22002-11-13 21:57:52 +0000994 /* Oh, the horror. glibc's internal use of pthreads "knows"
995 that destroying a lock does an implicit unlock. Make it
996 explicit. */
997 __pthread_mutex_unlock(mutex);
998 pthread_error("pthread_mutex_destroy: "
999 "mutex is still in use");
1000 return EBUSY;
sewardj4dced352002-06-04 22:54:20 +00001001 }
1002 mutex->__m_count = 0;
1003 mutex->__m_owner = (_pthread_descr)VG_INVALID_THREADID;
1004 mutex->__m_kind = PTHREAD_MUTEX_ERRORCHECK_NP;
1005 return 0;
sewardje663cb92002-04-12 10:26:32 +00001006}
1007
1008
sewardjf8f819e2002-04-17 23:21:37 +00001009/* ---------------------------------------------------
sewardj6072c362002-04-19 14:40:57 +00001010 CONDITION VARIABLES
1011 ------------------------------------------------ */
1012
1013/* LinuxThreads supports no attributes for conditions. Hence ... */
1014
1015int pthread_condattr_init(pthread_condattr_t *attr)
1016{
1017 return 0;
1018}
1019
sewardj0738a592002-04-20 13:59:33 +00001020int pthread_condattr_destroy(pthread_condattr_t *attr)
1021{
1022 return 0;
1023}
sewardj6072c362002-04-19 14:40:57 +00001024
1025int pthread_cond_init( pthread_cond_t *cond,
1026 const pthread_condattr_t *cond_attr)
1027{
1028 cond->__c_waiting = (_pthread_descr)VG_INVALID_THREADID;
1029 return 0;
1030}
1031
sewardjf854f472002-04-21 12:19:41 +00001032int pthread_cond_destroy(pthread_cond_t *cond)
1033{
1034 /* should check that no threads are waiting on this CV */
sewardj436e0582002-04-26 14:31:40 +00001035 static int moans = N_MOANS;
1036 if (moans-- > 0)
1037 kludged("pthread_cond_destroy");
sewardjf854f472002-04-21 12:19:41 +00001038 return 0;
1039}
sewardj6072c362002-04-19 14:40:57 +00001040
1041/* ---------------------------------------------------
1042 SCHEDULING
1043 ------------------------------------------------ */
1044
1045/* This is completely bogus. */
1046int pthread_getschedparam(pthread_t target_thread,
1047 int *policy,
1048 struct sched_param *param)
1049{
sewardj436e0582002-04-26 14:31:40 +00001050 static int moans = N_MOANS;
1051 if (moans-- > 0)
1052 kludged("pthread_getschedparam");
sewardj6072c362002-04-19 14:40:57 +00001053 if (policy) *policy = SCHED_OTHER;
sewardj3e909ce2002-06-03 13:27:15 +00001054# ifdef HAVE_SCHED_PRIORITY
sewardj2a1dcce2002-04-22 12:45:25 +00001055 if (param) param->sched_priority = 0; /* who knows */
1056# else
sewardj6072c362002-04-19 14:40:57 +00001057 if (param) param->__sched_priority = 0; /* who knows */
sewardj2a1dcce2002-04-22 12:45:25 +00001058# endif
sewardj6072c362002-04-19 14:40:57 +00001059 return 0;
1060}
1061
1062int pthread_setschedparam(pthread_t target_thread,
1063 int policy,
1064 const struct sched_param *param)
1065{
sewardj436e0582002-04-26 14:31:40 +00001066 static int moans = N_MOANS;
1067 if (moans-- > 0)
1068 ignored("pthread_setschedparam");
sewardj6072c362002-04-19 14:40:57 +00001069 return 0;
1070}
1071
sewardj3b5d8862002-04-20 13:53:23 +00001072int pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex)
1073{
1074 int res;
1075 ensure_valgrind("pthread_cond_wait");
1076 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
1077 VG_USERREQ__PTHREAD_COND_WAIT,
1078 cond, mutex, 0, 0);
1079 return res;
1080}
1081
sewardj5f07b662002-04-23 16:52:51 +00001082int pthread_cond_timedwait ( pthread_cond_t *cond,
1083 pthread_mutex_t *mutex,
1084 const struct timespec *abstime )
1085{
1086 int res;
1087 unsigned int ms_now, ms_end;
1088 struct timeval timeval_now;
1089 unsigned long long int ull_ms_now_after_1970;
1090 unsigned long long int ull_ms_end_after_1970;
1091
1092 ensure_valgrind("pthread_cond_timedwait");
1093 VALGRIND_MAGIC_SEQUENCE(ms_now, 0xFFFFFFFF /* default */,
1094 VG_USERREQ__READ_MILLISECOND_TIMER,
1095 0, 0, 0, 0);
sewardj2d94c112002-06-03 01:25:54 +00001096 my_assert(ms_now != 0xFFFFFFFF);
sewardj5f07b662002-04-23 16:52:51 +00001097 res = gettimeofday(&timeval_now, NULL);
sewardj2d94c112002-06-03 01:25:54 +00001098 my_assert(res == 0);
sewardj5f07b662002-04-23 16:52:51 +00001099
1100 ull_ms_now_after_1970
1101 = 1000ULL * ((unsigned long long int)(timeval_now.tv_sec))
1102 + ((unsigned long long int)(timeval_now.tv_usec / 1000000));
1103 ull_ms_end_after_1970
1104 = 1000ULL * ((unsigned long long int)(abstime->tv_sec))
1105 + ((unsigned long long int)(abstime->tv_nsec / 1000000));
sewardjd8e919e2002-05-29 20:13:53 +00001106 if (ull_ms_end_after_1970 < ull_ms_now_after_1970)
1107 ull_ms_end_after_1970 = ull_ms_now_after_1970;
sewardj5f07b662002-04-23 16:52:51 +00001108 ms_end
1109 = ms_now + (unsigned int)(ull_ms_end_after_1970 - ull_ms_now_after_1970);
1110 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
1111 VG_USERREQ__PTHREAD_COND_TIMEDWAIT,
1112 cond, mutex, ms_end, 0);
1113 return res;
1114}
1115
1116
sewardj3b5d8862002-04-20 13:53:23 +00001117int pthread_cond_signal(pthread_cond_t *cond)
1118{
1119 int res;
1120 ensure_valgrind("pthread_cond_signal");
1121 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
1122 VG_USERREQ__PTHREAD_COND_SIGNAL,
1123 cond, 0, 0, 0);
1124 return res;
1125}
1126
1127int pthread_cond_broadcast(pthread_cond_t *cond)
1128{
1129 int res;
1130 ensure_valgrind("pthread_cond_broadcast");
1131 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
1132 VG_USERREQ__PTHREAD_COND_BROADCAST,
1133 cond, 0, 0, 0);
1134 return res;
1135}
1136
sewardj6072c362002-04-19 14:40:57 +00001137
1138/* ---------------------------------------------------
sewardjf8f819e2002-04-17 23:21:37 +00001139 CANCELLATION
1140 ------------------------------------------------ */
1141
sewardj853f55d2002-04-26 00:27:53 +00001142int pthread_setcancelstate(int state, int *oldstate)
1143{
sewardj20917d82002-05-28 01:36:45 +00001144 int res;
1145 ensure_valgrind("pthread_setcancelstate");
1146 if (state != PTHREAD_CANCEL_ENABLE
sewardj4dced352002-06-04 22:54:20 +00001147 && state != PTHREAD_CANCEL_DISABLE) {
1148 pthread_error("pthread_setcancelstate: "
1149 "invalid state");
sewardj20917d82002-05-28 01:36:45 +00001150 return EINVAL;
sewardj4dced352002-06-04 22:54:20 +00001151 }
sewardj2d94c112002-06-03 01:25:54 +00001152 my_assert(-1 != PTHREAD_CANCEL_ENABLE);
1153 my_assert(-1 != PTHREAD_CANCEL_DISABLE);
sewardj20917d82002-05-28 01:36:45 +00001154 VALGRIND_MAGIC_SEQUENCE(res, (-1) /* default */,
1155 VG_USERREQ__SET_CANCELSTATE,
1156 state, 0, 0, 0);
sewardj2d94c112002-06-03 01:25:54 +00001157 my_assert(res != -1);
sewardj20917d82002-05-28 01:36:45 +00001158 if (oldstate)
1159 *oldstate = res;
sewardj853f55d2002-04-26 00:27:53 +00001160 return 0;
1161}
1162
sewardje663cb92002-04-12 10:26:32 +00001163int pthread_setcanceltype(int type, int *oldtype)
1164{
sewardj20917d82002-05-28 01:36:45 +00001165 int res;
1166 ensure_valgrind("pthread_setcanceltype");
1167 if (type != PTHREAD_CANCEL_DEFERRED
sewardj4dced352002-06-04 22:54:20 +00001168 && type != PTHREAD_CANCEL_ASYNCHRONOUS) {
1169 pthread_error("pthread_setcanceltype: "
1170 "invalid type");
sewardj20917d82002-05-28 01:36:45 +00001171 return EINVAL;
sewardj4dced352002-06-04 22:54:20 +00001172 }
sewardj2d94c112002-06-03 01:25:54 +00001173 my_assert(-1 != PTHREAD_CANCEL_DEFERRED);
1174 my_assert(-1 != PTHREAD_CANCEL_ASYNCHRONOUS);
sewardj20917d82002-05-28 01:36:45 +00001175 VALGRIND_MAGIC_SEQUENCE(res, (-1) /* default */,
1176 VG_USERREQ__SET_CANCELTYPE,
1177 type, 0, 0, 0);
sewardj2d94c112002-06-03 01:25:54 +00001178 my_assert(res != -1);
sewardj20917d82002-05-28 01:36:45 +00001179 if (oldtype)
1180 *oldtype = res;
sewardje663cb92002-04-12 10:26:32 +00001181 return 0;
1182}
1183
sewardje663cb92002-04-12 10:26:32 +00001184int pthread_cancel(pthread_t thread)
1185{
1186 int res;
1187 ensure_valgrind("pthread_cancel");
sewardj20917d82002-05-28 01:36:45 +00001188 VALGRIND_MAGIC_SEQUENCE(res, (-1) /* default */,
1189 VG_USERREQ__SET_CANCELPEND,
1190 thread, &thread_exit_wrapper, 0, 0);
sewardj2d94c112002-06-03 01:25:54 +00001191 my_assert(res != -1);
sewardje663cb92002-04-12 10:26:32 +00001192 return res;
1193}
1194
sewardjd140e442002-05-29 01:21:19 +00001195static __inline__
1196void __my_pthread_testcancel(void)
sewardj853f55d2002-04-26 00:27:53 +00001197{
sewardj20917d82002-05-28 01:36:45 +00001198 int res;
njn25e49d8e72002-09-23 09:36:25 +00001199 ensure_valgrind("__my_pthread_testcancel");
sewardj20917d82002-05-28 01:36:45 +00001200 VALGRIND_MAGIC_SEQUENCE(res, (-1) /* default */,
1201 VG_USERREQ__TESTCANCEL,
1202 0, 0, 0, 0);
sewardj2d94c112002-06-03 01:25:54 +00001203 my_assert(res == 0);
sewardj853f55d2002-04-26 00:27:53 +00001204}
1205
sewardjd140e442002-05-29 01:21:19 +00001206void pthread_testcancel ( void )
1207{
1208 __my_pthread_testcancel();
1209}
1210
sewardj20917d82002-05-28 01:36:45 +00001211
sewardjef037c72002-05-30 00:40:03 +00001212/* Not really sure what this is for. I suspect for doing the POSIX
1213 requirements for fork() and exec(). We do this internally anyway
1214 whenever those syscalls are observed, so this could be superfluous,
1215 but hey ...
1216*/
sewardj853f55d2002-04-26 00:27:53 +00001217void __pthread_kill_other_threads_np ( void )
1218{
sewardjef037c72002-05-30 00:40:03 +00001219 int res;
1220 ensure_valgrind("__pthread_kill_other_threads_np");
1221 VALGRIND_MAGIC_SEQUENCE(res, (-1) /* default */,
1222 VG_USERREQ__NUKE_OTHER_THREADS,
1223 0, 0, 0, 0);
sewardj2d94c112002-06-03 01:25:54 +00001224 my_assert(res == 0);
sewardj853f55d2002-04-26 00:27:53 +00001225}
1226
sewardje663cb92002-04-12 10:26:32 +00001227
sewardjf8f819e2002-04-17 23:21:37 +00001228/* ---------------------------------------------------
sewardjb48e5002002-05-13 00:16:03 +00001229 SIGNALS
1230 ------------------------------------------------ */
1231
1232#include <signal.h>
1233
1234int pthread_sigmask(int how, const sigset_t *newmask,
1235 sigset_t *oldmask)
1236{
1237 int res;
1238
1239 /* A bit subtle, because the scheduler expects newmask and oldmask
1240 to be vki_sigset_t* rather than sigset_t*, and the two are
1241 different. Fortunately the first 64 bits of a sigset_t are
1242 exactly a vki_sigset_t, so we just pass the pointers through
1243 unmodified. Haaaack!
1244
1245 Also mash the how value so that the SIG_ constants from glibc
sewardj018f7622002-05-15 21:13:39 +00001246 constants to VKI_ constants, so that the former do not have to
1247 be included into vg_scheduler.c. */
sewardjb48e5002002-05-13 00:16:03 +00001248
1249 ensure_valgrind("pthread_sigmask");
1250
1251 switch (how) {
sewardj018f7622002-05-15 21:13:39 +00001252 case SIG_SETMASK: how = VKI_SIG_SETMASK; break;
1253 case SIG_BLOCK: how = VKI_SIG_BLOCK; break;
1254 case SIG_UNBLOCK: how = VKI_SIG_UNBLOCK; break;
sewardj4dced352002-06-04 22:54:20 +00001255 default: pthread_error("pthread_sigmask: invalid how");
1256 return EINVAL;
sewardjb48e5002002-05-13 00:16:03 +00001257 }
1258
1259 /* Crude check */
1260 if (newmask == NULL)
1261 return EFAULT;
1262
1263 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
1264 VG_USERREQ__PTHREAD_SIGMASK,
1265 how, newmask, oldmask, 0);
1266
1267 /* The scheduler tells us of any memory violations. */
1268 return res == 0 ? 0 : EFAULT;
1269}
1270
1271
1272int sigwait ( const sigset_t* set, int* sig )
1273{
1274 int res;
1275 ensure_valgrind("sigwait");
1276 /* As with pthread_sigmask we deliberately confuse sigset_t with
1277 vki_ksigset_t. */
1278 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
1279 VG_USERREQ__SIGWAIT,
1280 set, sig, 0, 0);
1281 return res;
1282}
1283
1284
sewardj018f7622002-05-15 21:13:39 +00001285int pthread_kill(pthread_t thread, int signo)
1286{
1287 int res;
1288 ensure_valgrind("pthread_kill");
1289 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
1290 VG_USERREQ__PTHREAD_KILL,
1291 thread, signo, 0, 0);
1292 return res;
1293}
1294
1295
sewardj3665ded2002-05-16 16:57:25 +00001296/* Copied verbatim from Linuxthreads */
1297/* Redefine raise() to send signal to calling thread only,
1298 as per POSIX 1003.1c */
1299int raise (int sig)
1300{
1301 int retcode = pthread_kill(pthread_self(), sig);
sewardj4dced352002-06-04 22:54:20 +00001302 if (retcode == 0) {
sewardj3665ded2002-05-16 16:57:25 +00001303 return 0;
sewardj4dced352002-06-04 22:54:20 +00001304 } else {
sewardj3665ded2002-05-16 16:57:25 +00001305 errno = retcode;
1306 return -1;
1307 }
1308}
1309
1310
sewardj9a2224b2002-06-19 10:17:40 +00001311int pause ( void )
1312{
1313 unsigned int n_orig, n_now;
1314 struct vki_timespec nanosleep_interval;
1315 ensure_valgrind("pause");
1316
1317 /* This is surely a cancellation point. */
1318 __my_pthread_testcancel();
1319
1320 VALGRIND_MAGIC_SEQUENCE(n_orig, 0xFFFFFFFF /* default */,
1321 VG_USERREQ__GET_N_SIGS_RETURNED,
1322 0, 0, 0, 0);
1323 my_assert(n_orig != 0xFFFFFFFF);
1324
1325 while (1) {
1326 VALGRIND_MAGIC_SEQUENCE(n_now, 0xFFFFFFFF /* default */,
1327 VG_USERREQ__GET_N_SIGS_RETURNED,
1328 0, 0, 0, 0);
1329 my_assert(n_now != 0xFFFFFFFF);
1330 my_assert(n_now >= n_orig);
1331 if (n_now != n_orig) break;
1332
1333 nanosleep_interval.tv_sec = 0;
njn25e49d8e72002-09-23 09:36:25 +00001334 nanosleep_interval.tv_nsec = 12 * 1000 * 1000; /* 12 milliseconds */
sewardj9a2224b2002-06-19 10:17:40 +00001335 /* It's critical here that valgrind's nanosleep implementation
1336 is nonblocking. */
1337 (void)my_do_syscall2(__NR_nanosleep,
1338 (int)(&nanosleep_interval), (int)NULL);
1339 }
1340
1341 * (__errno_location()) = EINTR;
1342 return -1;
1343}
1344
1345
sewardjb48e5002002-05-13 00:16:03 +00001346/* ---------------------------------------------------
sewardjf8f819e2002-04-17 23:21:37 +00001347 THREAD-SPECIFICs
1348 ------------------------------------------------ */
sewardj5e5fa512002-04-14 13:13:05 +00001349
sewardj00a66b12002-10-12 16:42:35 +00001350static
1351int key_is_valid (pthread_key_t key)
1352{
1353 int res;
1354 VALGRIND_MAGIC_SEQUENCE(res, 2 /* default */,
1355 VG_USERREQ__PTHREAD_KEY_VALIDATE,
1356 key, 0, 0, 0);
1357 my_assert(res != 2);
1358 return res;
1359}
1360
1361
1362/* Returns NULL if thread is invalid. Otherwise, if the thread
1363 already has a specifics area, return that. Otherwise allocate it
1364 one. */
1365static
1366void** get_or_allocate_specifics_ptr ( pthread_t thread )
1367{
1368 int res, i;
1369 void** specifics_ptr;
1370 ensure_valgrind("get_or_allocate_specifics_ptr");
1371
1372 /* Returns zero if the thread has no specific_ptr. One if thread
1373 is invalid. Otherwise, the specific_ptr value. This is
1374 allocated with my_malloc and so is aligned and cannot be
1375 confused with 1 or 3. */
1376 VALGRIND_MAGIC_SEQUENCE(specifics_ptr, 3 /* default */,
1377 VG_USERREQ__PTHREAD_GETSPECIFIC_PTR,
1378 thread, 0, 0, 0);
1379 my_assert(specifics_ptr != (void**)3);
1380
1381 if (specifics_ptr == (void**)1)
1382 return NULL; /* invalid thread */
1383
1384 if (specifics_ptr != NULL)
1385 return specifics_ptr; /* already has a specifics ptr. */
1386
1387 /* None yet ... allocate a new one. Should never fail. */
1388 specifics_ptr = my_malloc( VG_N_THREAD_KEYS * sizeof(void*) );
1389 my_assert(specifics_ptr != NULL);
1390
1391 VALGRIND_MAGIC_SEQUENCE(res, -1 /* default */,
1392 VG_USERREQ__PTHREAD_SETSPECIFIC_PTR,
1393 specifics_ptr, 0, 0, 0);
1394 my_assert(res == 0);
1395
1396 /* POSIX sez: "Upon thread creation, the value NULL shall be
1397 associated with all defined keys in the new thread." This
1398 allocation is in effect a delayed allocation of the specific
1399 data for a thread, at its first-use. Hence we initialise it
1400 here. */
1401 for (i = 0; i < VG_N_THREAD_KEYS; i++) {
1402 specifics_ptr[i] = NULL;
1403 }
1404
1405 return specifics_ptr;
1406}
1407
1408
sewardj5905fae2002-04-26 13:25:00 +00001409int __pthread_key_create(pthread_key_t *key,
1410 void (*destr_function) (void *))
sewardj5e5fa512002-04-14 13:13:05 +00001411{
sewardj00a66b12002-10-12 16:42:35 +00001412 void** specifics_ptr;
1413 int res, i;
sewardj5f07b662002-04-23 16:52:51 +00001414 ensure_valgrind("pthread_key_create");
sewardj00a66b12002-10-12 16:42:35 +00001415
1416 /* This writes *key if successful. It should never fail. */
1417 VALGRIND_MAGIC_SEQUENCE(res, 1 /* default */,
sewardj5f07b662002-04-23 16:52:51 +00001418 VG_USERREQ__PTHREAD_KEY_CREATE,
1419 key, destr_function, 0, 0);
sewardj00a66b12002-10-12 16:42:35 +00001420 my_assert(res == 0);
1421
1422 /* POSIX sez: "Upon key creation, the value NULL shall be
1423 associated with the new key in all active threads." */
1424 for (i = 0; i < VG_N_THREADS; i++) {
1425 specifics_ptr = get_or_allocate_specifics_ptr(i);
1426 /* we get NULL if i is an invalid thread. */
1427 if (specifics_ptr != NULL)
1428 specifics_ptr[*key] = NULL;
1429 }
1430
sewardj5f07b662002-04-23 16:52:51 +00001431 return res;
sewardj5e5fa512002-04-14 13:13:05 +00001432}
1433
1434int pthread_key_delete(pthread_key_t key)
1435{
sewardj00a66b12002-10-12 16:42:35 +00001436 int res;
1437 ensure_valgrind("pthread_key_create");
1438 if (!key_is_valid(key))
1439 return EINVAL;
1440 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
1441 VG_USERREQ__PTHREAD_KEY_DELETE,
1442 key, 0, 0, 0);
1443 my_assert(res == 0);
sewardj5e5fa512002-04-14 13:13:05 +00001444 return 0;
1445}
1446
sewardj5905fae2002-04-26 13:25:00 +00001447int __pthread_setspecific(pthread_key_t key, const void *pointer)
sewardj5e5fa512002-04-14 13:13:05 +00001448{
sewardj00a66b12002-10-12 16:42:35 +00001449 void** specifics_ptr;
sewardj5f07b662002-04-23 16:52:51 +00001450 ensure_valgrind("pthread_setspecific");
sewardj00a66b12002-10-12 16:42:35 +00001451
1452 if (!key_is_valid(key))
1453 return EINVAL;
1454
1455 specifics_ptr = get_or_allocate_specifics_ptr(pthread_self());
1456 specifics_ptr[key] = (void*)pointer;
1457 return 0;
sewardj5e5fa512002-04-14 13:13:05 +00001458}
1459
sewardj5905fae2002-04-26 13:25:00 +00001460void * __pthread_getspecific(pthread_key_t key)
sewardj5e5fa512002-04-14 13:13:05 +00001461{
sewardj00a66b12002-10-12 16:42:35 +00001462 void** specifics_ptr;
sewardj5f07b662002-04-23 16:52:51 +00001463 ensure_valgrind("pthread_getspecific");
sewardj00a66b12002-10-12 16:42:35 +00001464
1465 if (!key_is_valid(key))
1466 return NULL;
1467
1468 specifics_ptr = get_or_allocate_specifics_ptr(pthread_self());
1469 return specifics_ptr[key];
1470}
1471
1472
sewardj9aa918d2002-10-20 16:25:55 +00001473#ifdef GLIBC_2_3
sewardj00a66b12002-10-12 16:42:35 +00001474static
1475void ** __pthread_getspecific_addr(pthread_key_t key)
1476{
1477 void** specifics_ptr;
1478 ensure_valgrind("pthread_getspecific_addr");
1479
1480 if (!key_is_valid(key))
1481 return NULL;
1482
1483 specifics_ptr = get_or_allocate_specifics_ptr(pthread_self());
1484 return &(specifics_ptr[key]);
sewardj5e5fa512002-04-14 13:13:05 +00001485}
sewardj9aa918d2002-10-20 16:25:55 +00001486#endif
sewardjf8f819e2002-04-17 23:21:37 +00001487
1488/* ---------------------------------------------------
sewardj89d3d852002-04-24 19:21:39 +00001489 ONCEry
1490 ------------------------------------------------ */
1491
1492static pthread_mutex_t once_masterlock = PTHREAD_MUTEX_INITIALIZER;
1493
1494
sewardj5905fae2002-04-26 13:25:00 +00001495int __pthread_once ( pthread_once_t *once_control,
1496 void (*init_routine) (void) )
sewardj89d3d852002-04-24 19:21:39 +00001497{
1498 int res;
1499 ensure_valgrind("pthread_once");
1500
sewardj68b2dd92002-05-10 21:03:56 +00001501 res = __pthread_mutex_lock(&once_masterlock);
sewardj89d3d852002-04-24 19:21:39 +00001502
sewardj68b2dd92002-05-10 21:03:56 +00001503 if (res != 0) {
sewardj89d3d852002-04-24 19:21:39 +00001504 barf("pthread_once: Looks like your program's "
1505 "init routine calls back to pthread_once() ?!");
sewardj68b2dd92002-05-10 21:03:56 +00001506 }
sewardj89d3d852002-04-24 19:21:39 +00001507
1508 if (*once_control == 0) {
1509 *once_control = 1;
1510 init_routine();
1511 }
1512
sewardj68b2dd92002-05-10 21:03:56 +00001513 __pthread_mutex_unlock(&once_masterlock);
sewardj89d3d852002-04-24 19:21:39 +00001514
1515 return 0;
1516}
1517
1518
1519/* ---------------------------------------------------
sewardj853f55d2002-04-26 00:27:53 +00001520 MISC
1521 ------------------------------------------------ */
1522
sewardj2cb00342002-06-28 01:46:26 +00001523static pthread_mutex_t pthread_atfork_lock
1524 = PTHREAD_MUTEX_INITIALIZER;
1525
sewardj5905fae2002-04-26 13:25:00 +00001526int __pthread_atfork ( void (*prepare)(void),
1527 void (*parent)(void),
1528 void (*child)(void) )
sewardj853f55d2002-04-26 00:27:53 +00001529{
sewardj2cb00342002-06-28 01:46:26 +00001530 int n, res;
1531 ForkHandlerEntry entry;
1532
1533 ensure_valgrind("pthread_atfork");
1534 __pthread_mutex_lock(&pthread_atfork_lock);
1535
1536 /* Fetch old counter */
1537 VALGRIND_MAGIC_SEQUENCE(n, -2 /* default */,
1538 VG_USERREQ__GET_FHSTACK_USED,
1539 0, 0, 0, 0);
1540 my_assert(n >= 0 && n < VG_N_FORKHANDLERSTACK);
1541 if (n == VG_N_FORKHANDLERSTACK-1)
1542 barf("pthread_atfork: VG_N_FORKHANDLERSTACK is too low; "
1543 "increase and recompile");
1544
1545 /* Add entry */
1546 entry.prepare = *prepare;
1547 entry.parent = *parent;
1548 entry.child = *child;
1549 VALGRIND_MAGIC_SEQUENCE(res, -2 /* default */,
1550 VG_USERREQ__SET_FHSTACK_ENTRY,
1551 n, &entry, 0, 0);
1552 my_assert(res == 0);
1553
1554 /* Bump counter */
1555 VALGRIND_MAGIC_SEQUENCE(res, -2 /* default */,
1556 VG_USERREQ__SET_FHSTACK_USED,
1557 n+1, 0, 0, 0);
1558 my_assert(res == 0);
1559
1560 __pthread_mutex_unlock(&pthread_atfork_lock);
1561 return 0;
sewardj853f55d2002-04-26 00:27:53 +00001562}
1563
1564
sewardjbb990782002-05-08 02:01:14 +00001565__attribute__((weak))
1566void __pthread_initialize ( void )
1567{
sewardjbea1caa2002-05-10 23:20:58 +00001568 ensure_valgrind("__pthread_initialize");
sewardjbb990782002-05-08 02:01:14 +00001569}
1570
1571
sewardj853f55d2002-04-26 00:27:53 +00001572/* ---------------------------------------------------
sewardj3b13f0e2002-04-25 20:17:29 +00001573 LIBRARY-PRIVATE THREAD SPECIFIC STATE
sewardjf8f819e2002-04-17 23:21:37 +00001574 ------------------------------------------------ */
1575
sewardj3b13f0e2002-04-25 20:17:29 +00001576#include <resolv.h>
1577static int thread_specific_errno[VG_N_THREADS];
1578static int thread_specific_h_errno[VG_N_THREADS];
1579static struct __res_state
1580 thread_specific_res_state[VG_N_THREADS];
sewardjf8f819e2002-04-17 23:21:37 +00001581
sewardj3b13f0e2002-04-25 20:17:29 +00001582int* __errno_location ( void )
sewardjf8f819e2002-04-17 23:21:37 +00001583{
1584 int tid;
sewardj3b13f0e2002-04-25 20:17:29 +00001585 /* ensure_valgrind("__errno_location"); */
1586 VALGRIND_MAGIC_SEQUENCE(tid, 1 /* default */,
sewardjf8f819e2002-04-17 23:21:37 +00001587 VG_USERREQ__PTHREAD_GET_THREADID,
1588 0, 0, 0, 0);
sewardj3b13f0e2002-04-25 20:17:29 +00001589 /* 'cos I'm paranoid ... */
sewardj439d45e2002-05-03 20:43:10 +00001590 if (tid < 1 || tid >= VG_N_THREADS)
sewardj3b13f0e2002-04-25 20:17:29 +00001591 barf("__errno_location: invalid ThreadId");
1592 return & thread_specific_errno[tid];
1593}
1594
1595int* __h_errno_location ( void )
1596{
1597 int tid;
1598 /* ensure_valgrind("__h_errno_location"); */
1599 VALGRIND_MAGIC_SEQUENCE(tid, 1 /* default */,
1600 VG_USERREQ__PTHREAD_GET_THREADID,
1601 0, 0, 0, 0);
1602 /* 'cos I'm paranoid ... */
sewardj439d45e2002-05-03 20:43:10 +00001603 if (tid < 1 || tid >= VG_N_THREADS)
sewardj3b13f0e2002-04-25 20:17:29 +00001604 barf("__h_errno_location: invalid ThreadId");
1605 return & thread_specific_h_errno[tid];
1606}
1607
sewardjb0ff1032002-08-06 09:02:53 +00001608
1609#undef _res
1610extern struct __res_state _res;
1611
sewardj3b13f0e2002-04-25 20:17:29 +00001612struct __res_state* __res_state ( void )
1613{
1614 int tid;
1615 /* ensure_valgrind("__res_state"); */
1616 VALGRIND_MAGIC_SEQUENCE(tid, 1 /* default */,
1617 VG_USERREQ__PTHREAD_GET_THREADID,
1618 0, 0, 0, 0);
1619 /* 'cos I'm paranoid ... */
sewardj439d45e2002-05-03 20:43:10 +00001620 if (tid < 1 || tid >= VG_N_THREADS)
sewardj3b13f0e2002-04-25 20:17:29 +00001621 barf("__res_state: invalid ThreadId");
sewardjb0ff1032002-08-06 09:02:53 +00001622 if (tid == 1)
1623 return & _res;
sewardj3b13f0e2002-04-25 20:17:29 +00001624 return & thread_specific_res_state[tid];
sewardjf8f819e2002-04-17 23:21:37 +00001625}
1626
1627
sewardj5716dbb2002-04-26 03:28:18 +00001628/* ---------------------------------------------------
1629 LIBC-PRIVATE SPECIFIC DATA
1630 ------------------------------------------------ */
1631
1632/* Relies on assumption that initial private data is NULL. This
1633 should be fixed somehow. */
1634
njn25e49d8e72002-09-23 09:36:25 +00001635/* The allowable keys (indices) (all 3 of them).
sewardj5716dbb2002-04-26 03:28:18 +00001636 From sysdeps/pthread/bits/libc-tsd.h
1637*/
sewardjcb7f08a2002-10-02 09:41:49 +00001638/* as per glibc anoncvs HEAD of 20021001. */
sewardj5716dbb2002-04-26 03:28:18 +00001639enum __libc_tsd_key_t { _LIBC_TSD_KEY_MALLOC = 0,
1640 _LIBC_TSD_KEY_DL_ERROR,
njn25e49d8e72002-09-23 09:36:25 +00001641 _LIBC_TSD_KEY_RPC_VARS,
sewardjcb7f08a2002-10-02 09:41:49 +00001642 _LIBC_TSD_KEY_LOCALE,
1643 _LIBC_TSD_KEY_CTYPE_B,
1644 _LIBC_TSD_KEY_CTYPE_TOLOWER,
1645 _LIBC_TSD_KEY_CTYPE_TOUPPER,
sewardj5716dbb2002-04-26 03:28:18 +00001646 _LIBC_TSD_KEY_N };
1647
1648/* Auto-initialising subsystem. libc_specifics_inited is set
1649 after initialisation. libc_specifics_inited_mx guards it. */
1650static int libc_specifics_inited = 0;
1651static pthread_mutex_t libc_specifics_inited_mx = PTHREAD_MUTEX_INITIALIZER;
1652
sewardj00a66b12002-10-12 16:42:35 +00001653
sewardj5716dbb2002-04-26 03:28:18 +00001654/* These are the keys we must initialise the first time. */
sewardjcb7f08a2002-10-02 09:41:49 +00001655static pthread_key_t libc_specifics_keys[_LIBC_TSD_KEY_N];
sewardj5716dbb2002-04-26 03:28:18 +00001656
sewardj00a66b12002-10-12 16:42:35 +00001657
sewardjcb7f08a2002-10-02 09:41:49 +00001658/* Initialise the keys, if they are not already initialised. */
sewardj5716dbb2002-04-26 03:28:18 +00001659static
1660void init_libc_tsd_keys ( void )
1661{
1662 int res, i;
1663 pthread_key_t k;
1664
sewardj08c7f012002-10-07 23:56:55 +00001665 /* Don't fall into deadlock if we get called again whilst we still
1666 hold the lock, via the __uselocale() call herein. */
1667 if (libc_specifics_inited != 0)
1668 return;
1669
1670 /* Take the lock. */
sewardj00a66b12002-10-12 16:42:35 +00001671 res = __pthread_mutex_lock(&libc_specifics_inited_mx);
sewardj5716dbb2002-04-26 03:28:18 +00001672 if (res != 0) barf("init_libc_tsd_keys: lock");
1673
sewardj08c7f012002-10-07 23:56:55 +00001674 /* Now test again, to be sure there is no mistake. */
1675 if (libc_specifics_inited != 0) {
sewardj00a66b12002-10-12 16:42:35 +00001676 res = __pthread_mutex_unlock(&libc_specifics_inited_mx);
sewardj08c7f012002-10-07 23:56:55 +00001677 if (res != 0) barf("init_libc_tsd_keys: unlock(1)");
1678 return;
sewardj5716dbb2002-04-26 03:28:18 +00001679 }
1680
sewardj08c7f012002-10-07 23:56:55 +00001681 /* Actually do the initialisation. */
1682 /* printf("INIT libc specifics\n"); */
1683 for (i = 0; i < _LIBC_TSD_KEY_N; i++) {
sewardj00a66b12002-10-12 16:42:35 +00001684 res = __pthread_key_create(&k, NULL);
sewardj08c7f012002-10-07 23:56:55 +00001685 if (res != 0) barf("init_libc_tsd_keys: create");
1686 libc_specifics_keys[i] = k;
1687 }
1688
1689 /* Signify init done. */
1690 libc_specifics_inited = 1;
1691
1692# ifdef GLIBC_2_3
1693 /* Set the initialising thread's locale to the global (default)
sewardj00a66b12002-10-12 16:42:35 +00001694 locale. A hack in support of glibc-2.3. This does the biz for
1695 the root thread. For all other threads we run this in
1696 thread_wrapper(), which does the real work of
1697 pthread_create(). */
1698 /* assert that we are the root thread. I don't know if this is
1699 really a valid assertion to make; if it breaks I'll reconsider
1700 it. */
1701 my_assert(pthread_self() == 1);
sewardj08c7f012002-10-07 23:56:55 +00001702 __uselocale(LC_GLOBAL_LOCALE);
1703# endif
1704
1705 /* Unlock and return. */
sewardj00a66b12002-10-12 16:42:35 +00001706 res = __pthread_mutex_unlock(&libc_specifics_inited_mx);
sewardj5716dbb2002-04-26 03:28:18 +00001707 if (res != 0) barf("init_libc_tsd_keys: unlock");
1708}
1709
1710
1711static int
1712libc_internal_tsd_set ( enum __libc_tsd_key_t key,
1713 const void * pointer )
1714{
sewardjcb7f08a2002-10-02 09:41:49 +00001715 int res;
sewardj5716dbb2002-04-26 03:28:18 +00001716 /* printf("SET SET SET key %d ptr %p\n", key, pointer); */
sewardjcb7f08a2002-10-02 09:41:49 +00001717 if (key < _LIBC_TSD_KEY_MALLOC || key >= _LIBC_TSD_KEY_N)
sewardj5716dbb2002-04-26 03:28:18 +00001718 barf("libc_internal_tsd_set: invalid key");
1719 init_libc_tsd_keys();
sewardj00a66b12002-10-12 16:42:35 +00001720 res = __pthread_setspecific(libc_specifics_keys[key], pointer);
sewardj5716dbb2002-04-26 03:28:18 +00001721 if (res != 0) barf("libc_internal_tsd_set: setspecific failed");
1722 return 0;
1723}
1724
1725static void *
1726libc_internal_tsd_get ( enum __libc_tsd_key_t key )
1727{
sewardjcb7f08a2002-10-02 09:41:49 +00001728 void* v;
sewardj5716dbb2002-04-26 03:28:18 +00001729 /* printf("GET GET GET key %d\n", key); */
sewardjcb7f08a2002-10-02 09:41:49 +00001730 if (key < _LIBC_TSD_KEY_MALLOC || key >= _LIBC_TSD_KEY_N)
sewardj5716dbb2002-04-26 03:28:18 +00001731 barf("libc_internal_tsd_get: invalid key");
1732 init_libc_tsd_keys();
sewardj00a66b12002-10-12 16:42:35 +00001733 v = __pthread_getspecific(libc_specifics_keys[key]);
sewardj5716dbb2002-04-26 03:28:18 +00001734 /* if (v == NULL) barf("libc_internal_tsd_set: getspecific failed"); */
1735 return v;
1736}
1737
1738
sewardj70adeb22002-04-27 01:35:38 +00001739int (*__libc_internal_tsd_set)
1740 (enum __libc_tsd_key_t key, const void * pointer)
1741 = libc_internal_tsd_set;
sewardj5716dbb2002-04-26 03:28:18 +00001742
sewardj70adeb22002-04-27 01:35:38 +00001743void* (*__libc_internal_tsd_get)
1744 (enum __libc_tsd_key_t key)
1745 = libc_internal_tsd_get;
sewardj5716dbb2002-04-26 03:28:18 +00001746
1747
sewardj00a66b12002-10-12 16:42:35 +00001748#ifdef GLIBC_2_3
1749/* This one was first spotted be me in the glibc-2.2.93 sources. */
1750static void**
1751libc_internal_tsd_address ( enum __libc_tsd_key_t key )
1752{
1753 void** v;
1754 /* printf("ADDR ADDR ADDR key %d\n", key); */
1755 if (key < _LIBC_TSD_KEY_MALLOC || key >= _LIBC_TSD_KEY_N)
1756 barf("libc_internal_tsd_address: invalid key");
1757 init_libc_tsd_keys();
1758 v = __pthread_getspecific_addr(libc_specifics_keys[key]);
1759 return v;
1760}
1761
1762void ** (*__libc_internal_tsd_address)
1763 (enum __libc_tsd_key_t key)
1764 = libc_internal_tsd_address;
1765#endif
1766
1767
sewardje663cb92002-04-12 10:26:32 +00001768/* ---------------------------------------------------------------------
1769 These are here (I think) because they are deemed cancellation
1770 points by POSIX. For the moment we'll simply pass the call along
1771 to the corresponding thread-unaware (?) libc routine.
1772 ------------------------------------------------------------------ */
1773
sewardje663cb92002-04-12 10:26:32 +00001774#include <stdlib.h>
sewardje663cb92002-04-12 10:26:32 +00001775#include <sys/types.h>
1776#include <sys/socket.h>
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);
sewardj5905fae2002-04-26 13:25:00 +00001808__attribute__((weak))
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);
sewardj5905fae2002-04-26 13:25:00 +00001820__attribute__((weak))
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);
sewardj5905fae2002-04-26 13:25:00 +00001830__attribute__((weak))
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);
sewardj5905fae2002-04-26 13:25:00 +00001840__attribute__((weak))
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);
1986/* __attribute__((weak)) */
1987int 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);
sewardjf912dfc2002-11-13 21:51:10 +00001994/* __attribute__((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);
sewardj5905fae2002-04-26 13:25:00 +00002002__attribute__((weak))
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
2010extern
2011int __libc_accept(int s, struct sockaddr *addr, socklen_t *addrlen);
sewardjf220ccc2002-10-23 21:53:49 +00002012
2013int VGL_(accept)(int s, struct sockaddr *addr, socklen_t *addrlen)
sewardje663cb92002-04-12 10:26:32 +00002014{
sewardjd140e442002-05-29 01:21:19 +00002015 __my_pthread_testcancel();
sewardj705d3cb2002-05-23 13:13:12 +00002016 wait_for_fd_to_be_readable_or_erring(s);
sewardjd140e442002-05-29 01:21:19 +00002017 __my_pthread_testcancel();
sewardj45b4b372002-04-16 22:50:32 +00002018 return __libc_accept(s, addr, addrlen);
sewardje663cb92002-04-12 10:26:32 +00002019}
2020
sewardj0c573af92002-10-23 21:55:01 +00002021extern
2022int __libc_recv(int s, void *buf, size_t len, int flags);
2023
2024int VGL_(recv)(int s, void *buf, size_t len, int flags)
2025{
2026 __my_pthread_testcancel();
2027 wait_for_fd_to_be_readable_or_erring(s);
2028 __my_pthread_testcancel();
2029 return __libc_recv(s, buf, len, flags);
2030}
2031
sewardj2a68e7e2002-11-16 11:04:18 +00002032int VGL_(readv)(int fd, const struct iovec *iov, int count)
2033{
sewardjfd7747b2002-12-01 10:25:53 +00002034 int res;
2035
sewardj2a68e7e2002-11-16 11:04:18 +00002036 __my_pthread_testcancel();
2037 wait_for_fd_to_be_readable_or_erring(fd);
2038 __my_pthread_testcancel();
sewardjfd7747b2002-12-01 10:25:53 +00002039 res = my_do_syscall3(__NR_readv, fd, (unsigned)iov, count);
2040
2041 if (is_kerror(res)) {
2042 *(__errno_location()) = -res;
2043 return -1;
2044 }
2045 return res;
sewardj2a68e7e2002-11-16 11:04:18 +00002046}
2047
2048int VGL_(writev)(int fd, struct iovec *iov, int count)
2049{
sewardjfd7747b2002-12-01 10:25:53 +00002050 int res;
2051
sewardj2a68e7e2002-11-16 11:04:18 +00002052 __my_pthread_testcancel();
2053 wait_for_fd_to_be_writable_or_erring(fd);
2054 __my_pthread_testcancel();
sewardjfd7747b2002-12-01 10:25:53 +00002055 res = my_do_syscall3(__NR_writev, fd, (unsigned)iov, count);
2056
2057 if (is_kerror(res)) {
2058 *(__errno_location()) = -res;
2059 return -1;
2060 }
2061 return res;
sewardj2a68e7e2002-11-16 11:04:18 +00002062}
sewardje663cb92002-04-12 10:26:32 +00002063
2064extern
sewardje663cb92002-04-12 10:26:32 +00002065pid_t __libc_waitpid(pid_t pid, int *status, int options);
sewardj5905fae2002-04-26 13:25:00 +00002066__attribute__((weak))
sewardje663cb92002-04-12 10:26:32 +00002067pid_t waitpid(pid_t pid, int *status, int options)
2068{
sewardjd140e442002-05-29 01:21:19 +00002069 __my_pthread_testcancel();
sewardj45b4b372002-04-16 22:50:32 +00002070 return __libc_waitpid(pid, status, options);
sewardje663cb92002-04-12 10:26:32 +00002071}
2072
2073
2074extern
2075int __libc_nanosleep(const struct timespec *req, struct timespec *rem);
sewardj5905fae2002-04-26 13:25:00 +00002076__attribute__((weak))
sewardje663cb92002-04-12 10:26:32 +00002077int nanosleep(const struct timespec *req, struct timespec *rem)
2078{
sewardjd140e442002-05-29 01:21:19 +00002079 __my_pthread_testcancel();
sewardje663cb92002-04-12 10:26:32 +00002080 return __libc_nanosleep(req, rem);
2081}
2082
sewardjbe32e452002-04-24 20:29:58 +00002083
sewardje663cb92002-04-12 10:26:32 +00002084extern
2085int __libc_fsync(int fd);
sewardj5905fae2002-04-26 13:25:00 +00002086__attribute__((weak))
sewardje663cb92002-04-12 10:26:32 +00002087int fsync(int fd)
2088{
sewardjd140e442002-05-29 01:21:19 +00002089 __my_pthread_testcancel();
sewardj45b4b372002-04-16 22:50:32 +00002090 return __libc_fsync(fd);
sewardje663cb92002-04-12 10:26:32 +00002091}
2092
sewardjbe32e452002-04-24 20:29:58 +00002093
sewardj70c75362002-04-13 04:18:32 +00002094extern
2095off_t __libc_lseek(int fildes, off_t offset, int whence);
sewardj5905fae2002-04-26 13:25:00 +00002096__attribute__((weak))
sewardj70c75362002-04-13 04:18:32 +00002097off_t lseek(int fildes, off_t offset, int whence)
2098{
sewardjd140e442002-05-29 01:21:19 +00002099 __my_pthread_testcancel();
sewardj45b4b372002-04-16 22:50:32 +00002100 return __libc_lseek(fildes, offset, whence);
sewardj70c75362002-04-13 04:18:32 +00002101}
2102
sewardjbe32e452002-04-24 20:29:58 +00002103
2104extern
2105__off64_t __libc_lseek64(int fildes, __off64_t offset, int whence);
sewardj5905fae2002-04-26 13:25:00 +00002106__attribute__((weak))
sewardjbe32e452002-04-24 20:29:58 +00002107__off64_t lseek64(int fildes, __off64_t offset, int whence)
2108{
sewardjd140e442002-05-29 01:21:19 +00002109 __my_pthread_testcancel();
sewardjbe32e452002-04-24 20:29:58 +00002110 return __libc_lseek64(fildes, offset, whence);
2111}
2112
2113
sewardj726c4122002-05-16 23:39:10 +00002114extern
2115ssize_t __libc_pread64 (int __fd, void *__buf, size_t __nbytes,
2116 __off64_t __offset);
2117ssize_t __pread64 (int __fd, void *__buf, size_t __nbytes,
2118 __off64_t __offset)
2119{
sewardjd140e442002-05-29 01:21:19 +00002120 __my_pthread_testcancel();
sewardj726c4122002-05-16 23:39:10 +00002121 return __libc_pread64(__fd, __buf, __nbytes, __offset);
2122}
2123
2124
sewardja18e2102002-05-18 10:43:22 +00002125extern
2126ssize_t __libc_pwrite64 (int __fd, const void *__buf, size_t __nbytes,
2127 __off64_t __offset);
2128ssize_t __pwrite64 (int __fd, const void *__buf, size_t __nbytes,
2129 __off64_t __offset)
2130{
sewardjd140e442002-05-29 01:21:19 +00002131 __my_pthread_testcancel();
sewardja18e2102002-05-18 10:43:22 +00002132 return __libc_pwrite64(__fd, __buf, __nbytes, __offset);
2133}
2134
sewardj726c4122002-05-16 23:39:10 +00002135
sewardj39b93b12002-05-18 10:56:27 +00002136extern
2137ssize_t __libc_pwrite(int fd, const void *buf, size_t count, off_t offset);
2138__attribute__((weak))
2139ssize_t pwrite(int fd, const void *buf, size_t count, off_t offset)
2140{
sewardjd140e442002-05-29 01:21:19 +00002141 __my_pthread_testcancel();
sewardj39b93b12002-05-18 10:56:27 +00002142 return __libc_pwrite(fd, buf, count, offset);
2143}
2144
2145
2146extern
2147ssize_t __libc_pread(int fd, void *buf, size_t count, off_t offset);
2148__attribute__((weak))
2149ssize_t pread(int fd, void *buf, size_t count, off_t offset)
2150{
sewardjd140e442002-05-29 01:21:19 +00002151 __my_pthread_testcancel();
sewardj39b93b12002-05-18 10:56:27 +00002152 return __libc_pread(fd, buf, count, offset);
2153}
2154
2155
sewardj6af4b5d2002-04-16 04:40:49 +00002156extern
2157void __libc_longjmp(jmp_buf env, int val) __attribute((noreturn));
sewardj5905fae2002-04-26 13:25:00 +00002158/* not weak: __attribute__((weak)) */
sewardj6af4b5d2002-04-16 04:40:49 +00002159void longjmp(jmp_buf env, int val)
2160{
2161 __libc_longjmp(env, val);
2162}
2163
sewardjbe32e452002-04-24 20:29:58 +00002164
sewardj436c2db2002-06-18 09:07:54 +00002165extern void __libc_siglongjmp (sigjmp_buf env, int val)
2166 __attribute__ ((noreturn));
2167void siglongjmp(sigjmp_buf env, int val)
2168{
2169 kludged("siglongjmp (cleanup handlers are ignored)");
2170 __libc_siglongjmp(env, val);
2171}
2172
2173
sewardj6af4b5d2002-04-16 04:40:49 +00002174extern
2175int __libc_send(int s, const void *msg, size_t len, int flags);
sewardj5905fae2002-04-26 13:25:00 +00002176__attribute__((weak))
sewardj6af4b5d2002-04-16 04:40:49 +00002177int send(int s, const void *msg, size_t len, int flags)
2178{
sewardjd140e442002-05-29 01:21:19 +00002179 __my_pthread_testcancel();
sewardj6af4b5d2002-04-16 04:40:49 +00002180 return __libc_send(s, msg, len, flags);
2181}
2182
sewardjbe32e452002-04-24 20:29:58 +00002183
sewardj1e8cdc92002-04-18 11:37:52 +00002184extern
2185int __libc_recv(int s, void *buf, size_t len, int flags);
sewardj5905fae2002-04-26 13:25:00 +00002186__attribute__((weak))
sewardj1e8cdc92002-04-18 11:37:52 +00002187int recv(int s, void *buf, size_t len, int flags)
2188{
sewardjd140e442002-05-29 01:21:19 +00002189 __my_pthread_testcancel();
sewardj1d6b3a22002-06-20 07:58:33 +00002190 wait_for_fd_to_be_readable_or_erring(s);
2191 __my_pthread_testcancel();
sewardj1e8cdc92002-04-18 11:37:52 +00002192 return __libc_recv(s, buf, len, flags);
2193}
2194
sewardjbe32e452002-04-24 20:29:58 +00002195
sewardj3665ded2002-05-16 16:57:25 +00002196extern
2197int __libc_sendmsg(int s, const struct msghdr *msg, int flags);
2198__attribute__((weak))
2199int sendmsg(int s, const struct msghdr *msg, int flags)
2200{
sewardjd140e442002-05-29 01:21:19 +00002201 __my_pthread_testcancel();
sewardj3665ded2002-05-16 16:57:25 +00002202 return __libc_sendmsg(s, msg, flags);
2203}
2204
2205
sewardj796d6a22002-04-24 02:28:34 +00002206extern
sewardj59da27a2002-06-06 08:33:54 +00002207int __libc_recvmsg(int s, struct msghdr *msg, int flags);
2208__attribute__((weak))
2209int recvmsg(int s, struct msghdr *msg, int flags)
2210{
2211 __my_pthread_testcancel();
2212 return __libc_recvmsg(s, msg, flags);
2213}
2214
2215
2216extern
sewardj436e0582002-04-26 14:31:40 +00002217int __libc_recvfrom(int s, void *buf, size_t len, int flags,
2218 struct sockaddr *from, socklen_t *fromlen);
2219__attribute__((weak))
2220int recvfrom(int s, void *buf, size_t len, int flags,
2221 struct sockaddr *from, socklen_t *fromlen)
2222{
sewardjd140e442002-05-29 01:21:19 +00002223 __my_pthread_testcancel();
sewardj2e207632002-06-13 17:29:53 +00002224 wait_for_fd_to_be_readable_or_erring(s);
2225 __my_pthread_testcancel();
sewardj436e0582002-04-26 14:31:40 +00002226 return __libc_recvfrom(s, buf, len, flags, from, fromlen);
2227}
2228
2229
2230extern
sewardj796d6a22002-04-24 02:28:34 +00002231int __libc_sendto(int s, const void *msg, size_t len, int flags,
2232 const struct sockaddr *to, socklen_t tolen);
sewardj5905fae2002-04-26 13:25:00 +00002233__attribute__((weak))
sewardj796d6a22002-04-24 02:28:34 +00002234int sendto(int s, const void *msg, size_t len, int flags,
2235 const struct sockaddr *to, socklen_t tolen)
2236{
sewardjd140e442002-05-29 01:21:19 +00002237 __my_pthread_testcancel();
sewardj796d6a22002-04-24 02:28:34 +00002238 return __libc_sendto(s, msg, len, flags, to, tolen);
2239}
2240
sewardjbe32e452002-04-24 20:29:58 +00002241
sewardj369b1702002-04-24 13:28:15 +00002242extern
2243int __libc_system(const char* str);
sewardj5905fae2002-04-26 13:25:00 +00002244__attribute__((weak))
sewardj369b1702002-04-24 13:28:15 +00002245int system(const char* str)
2246{
sewardjd140e442002-05-29 01:21:19 +00002247 __my_pthread_testcancel();
sewardj369b1702002-04-24 13:28:15 +00002248 return __libc_system(str);
2249}
2250
sewardjbe32e452002-04-24 20:29:58 +00002251
sewardjab0b1c32002-04-24 19:26:47 +00002252extern
2253pid_t __libc_wait(int *status);
sewardj5905fae2002-04-26 13:25:00 +00002254__attribute__((weak))
sewardjab0b1c32002-04-24 19:26:47 +00002255pid_t wait(int *status)
2256{
sewardjd140e442002-05-29 01:21:19 +00002257 __my_pthread_testcancel();
sewardjab0b1c32002-04-24 19:26:47 +00002258 return __libc_wait(status);
2259}
2260
sewardj45b4b372002-04-16 22:50:32 +00002261
sewardj67f1d582002-05-24 02:11:32 +00002262extern
2263int __libc_msync(const void *start, size_t length, int flags);
2264__attribute__((weak))
2265int msync(const void *start, size_t length, int flags)
2266{
sewardjd140e442002-05-29 01:21:19 +00002267 __my_pthread_testcancel();
sewardj67f1d582002-05-24 02:11:32 +00002268 return __libc_msync(start, length, flags);
2269}
2270
sewardj5905fae2002-04-26 13:25:00 +00002271
sewardj2cb00342002-06-28 01:46:26 +00002272/*--- fork and its helper ---*/
2273
2274static
2275void run_fork_handlers ( int what )
2276{
2277 ForkHandlerEntry entry;
2278 int n_h, n_handlers, i, res;
2279
2280 my_assert(what == 0 || what == 1 || what == 2);
2281
2282 /* Fetch old counter */
2283 VALGRIND_MAGIC_SEQUENCE(n_handlers, -2 /* default */,
2284 VG_USERREQ__GET_FHSTACK_USED,
2285 0, 0, 0, 0);
2286 my_assert(n_handlers >= 0 && n_handlers < VG_N_FORKHANDLERSTACK);
2287
2288 /* Prepare handlers (what == 0) are called in opposite order of
2289 calls to pthread_atfork. Parent and child handlers are called
2290 in the same order as calls to pthread_atfork. */
2291 if (what == 0)
2292 n_h = n_handlers - 1;
2293 else
2294 n_h = 0;
2295
2296 for (i = 0; i < n_handlers; i++) {
2297 VALGRIND_MAGIC_SEQUENCE(res, -2 /* default */,
2298 VG_USERREQ__GET_FHSTACK_ENTRY,
2299 n_h, &entry, 0, 0);
2300 my_assert(res == 0);
2301 switch (what) {
2302 case 0: if (entry.prepare) entry.prepare();
2303 n_h--; break;
2304 case 1: if (entry.parent) entry.parent();
2305 n_h++; break;
2306 case 2: if (entry.child) entry.child();
2307 n_h++; break;
2308 default: barf("run_fork_handlers: invalid what");
2309 }
2310 }
2311
2312 if (what != 0 /* prepare */) {
2313 /* Empty out the stack. */
2314 VALGRIND_MAGIC_SEQUENCE(res, -2 /* default */,
2315 VG_USERREQ__SET_FHSTACK_USED,
2316 0, 0, 0, 0);
2317 my_assert(res == 0);
2318 }
2319}
2320
2321extern
2322pid_t __libc_fork(void);
2323pid_t __fork(void)
2324{
2325 pid_t pid;
2326 __my_pthread_testcancel();
2327 __pthread_mutex_lock(&pthread_atfork_lock);
2328
2329 run_fork_handlers(0 /* prepare */);
2330 pid = __libc_fork();
2331 if (pid == 0) {
2332 /* I am the child */
2333 run_fork_handlers(2 /* child */);
sewardjd8acdf22002-11-13 21:57:52 +00002334 __pthread_mutex_unlock(&pthread_atfork_lock);
sewardj2cb00342002-06-28 01:46:26 +00002335 __pthread_mutex_init(&pthread_atfork_lock, NULL);
2336 } else {
2337 /* I am the parent */
2338 run_fork_handlers(1 /* parent */);
2339 __pthread_mutex_unlock(&pthread_atfork_lock);
2340 }
2341 return pid;
2342}
2343
2344
njn25e49d8e72002-09-23 09:36:25 +00002345pid_t __vfork(void)
2346{
2347 return __fork();
2348}
sewardj2cb00342002-06-28 01:46:26 +00002349
2350
sewardj3b13f0e2002-04-25 20:17:29 +00002351/* ---------------------------------------------------------------------
2352 Nonblocking implementations of select() and poll(). This stuff will
2353 surely rot your mind.
2354 ------------------------------------------------------------------ */
sewardje663cb92002-04-12 10:26:32 +00002355
sewardj08a4c3f2002-04-13 03:45:44 +00002356/*--------------------------------------------------*/
2357
2358#include "vg_kerneliface.h"
2359
2360static
sewardj08a4c3f2002-04-13 03:45:44 +00002361int my_do_syscall1 ( int syscallno, int arg1 )
2362{
2363 int __res;
2364 __asm__ volatile ("pushl %%ebx; movl %%edx,%%ebx ; int $0x80 ; popl %%ebx"
2365 : "=a" (__res)
2366 : "0" (syscallno),
2367 "d" (arg1) );
2368 return __res;
2369}
2370
2371static
2372int my_do_syscall2 ( int syscallno,
sewardjf854f472002-04-21 12:19:41 +00002373 int arg1, int arg2 )
sewardj08a4c3f2002-04-13 03:45:44 +00002374{
2375 int __res;
2376 __asm__ volatile ("pushl %%ebx; movl %%edx,%%ebx ; int $0x80 ; popl %%ebx"
2377 : "=a" (__res)
2378 : "0" (syscallno),
2379 "d" (arg1),
2380 "c" (arg2) );
2381 return __res;
2382}
2383
2384static
sewardjf854f472002-04-21 12:19:41 +00002385int my_do_syscall3 ( int syscallno,
2386 int arg1, int arg2, int arg3 )
2387{
2388 int __res;
2389 __asm__ volatile ("pushl %%ebx; movl %%esi,%%ebx ; int $0x80 ; popl %%ebx"
2390 : "=a" (__res)
2391 : "0" (syscallno),
2392 "S" (arg1),
2393 "c" (arg2),
2394 "d" (arg3) );
2395 return __res;
2396}
2397
sewardjd5bef572002-10-23 21:49:33 +00002398static inline
2399int my_do_syscall5 ( int syscallno,
2400 int arg1, int arg2, int arg3, int arg4, int arg5 )
2401{
2402 int __res;
2403 __asm__ volatile ("int $0x80"
2404 : "=a" (__res)
2405 : "0" (syscallno),
2406 "b" (arg1),
2407 "c" (arg2),
2408 "d" (arg3),
2409 "S" (arg4),
2410 "D" (arg5));
2411 return __res;
2412}
2413
sewardjf854f472002-04-21 12:19:41 +00002414static
sewardj08a4c3f2002-04-13 03:45:44 +00002415int do_syscall_select( int n,
2416 vki_fd_set* readfds,
2417 vki_fd_set* writefds,
2418 vki_fd_set* exceptfds,
2419 struct vki_timeval * timeout )
2420{
2421 int res;
2422 int args[5];
2423 args[0] = n;
2424 args[1] = (int)readfds;
2425 args[2] = (int)writefds;
2426 args[3] = (int)exceptfds;
2427 args[4] = (int)timeout;
2428 res = my_do_syscall1(__NR_select, (int)(&(args[0])) );
sewardj02535bc2002-04-21 01:08:26 +00002429 return res;
sewardj08a4c3f2002-04-13 03:45:44 +00002430}
2431
2432
2433/* This is a wrapper round select(), which makes it thread-safe,
2434 meaning that only this thread will block, rather than the entire
2435 process. This wrapper in turn depends on nanosleep() not to block
2436 the entire process, but I think (hope? suspect?) that POSIX
2437 pthreads guarantees that to be the case.
2438
2439 Basic idea is: modify the timeout parameter to select so that it
2440 returns immediately. Poll like this until select returns non-zero,
2441 indicating something interesting happened, or until our time is up.
njn25e49d8e72002-09-23 09:36:25 +00002442 Space out the polls with nanosleeps of say 11 milliseconds, which
sewardj08a4c3f2002-04-13 03:45:44 +00002443 is required to be nonblocking; this allows other threads to run.
sewardj02535bc2002-04-21 01:08:26 +00002444
2445 Assumes:
sewardj2d94c112002-06-03 01:25:54 +00002446 * (checked via my_assert) types fd_set and vki_fd_set are identical.
2447 * (checked via my_assert) types timeval and vki_timeval are identical.
sewardj02535bc2002-04-21 01:08:26 +00002448 * (unchecked) libc error numbers (EINTR etc) are the negation of the
2449 kernel's error numbers (VKI_EINTR etc).
sewardj08a4c3f2002-04-13 03:45:44 +00002450*/
sewardj08a4c3f2002-04-13 03:45:44 +00002451
sewardj7db011a2002-11-13 22:00:20 +00002452int VGL_(select) ( int n,
2453 fd_set *rfds,
2454 fd_set *wfds,
2455 fd_set *xfds,
2456 struct timeval *timeout )
sewardj08a4c3f2002-04-13 03:45:44 +00002457{
sewardj5f07b662002-04-23 16:52:51 +00002458 unsigned int ms_now, ms_end;
sewardj08a4c3f2002-04-13 03:45:44 +00002459 int res;
2460 fd_set rfds_copy;
2461 fd_set wfds_copy;
2462 fd_set xfds_copy;
2463 struct vki_timeval t_now;
sewardj08a4c3f2002-04-13 03:45:44 +00002464 struct vki_timeval zero_timeout;
2465 struct vki_timespec nanosleep_interval;
2466
sewardjd140e442002-05-29 01:21:19 +00002467 __my_pthread_testcancel();
2468
sewardj5f07b662002-04-23 16:52:51 +00002469 /* gcc's complains about ms_end being used uninitialised -- classic
2470 case it can't understand, where ms_end is both defined and used
2471 only if timeout != NULL. Hence ... */
2472 ms_end = 0;
sewardj08a4c3f2002-04-13 03:45:44 +00002473
2474 /* We assume that the kernel and libc data layouts are identical
2475 for the following types. These asserts provide a crude
2476 check. */
2477 if (sizeof(fd_set) != sizeof(vki_fd_set)
2478 || sizeof(struct timeval) != sizeof(struct vki_timeval))
2479 barf("valgrind's hacky non-blocking select(): data sizes error");
2480
sewardj5f07b662002-04-23 16:52:51 +00002481 /* Detect the current time and simultaneously find out if we are
2482 running on Valgrind. */
2483 VALGRIND_MAGIC_SEQUENCE(ms_now, 0xFFFFFFFF /* default */,
2484 VG_USERREQ__READ_MILLISECOND_TIMER,
2485 0, 0, 0, 0);
2486
2487 /* If a zero timeout specified, this call is harmless. Also go
2488 this route if we're not running on Valgrind, for whatever
2489 reason. */
2490 if ( (timeout && timeout->tv_sec == 0 && timeout->tv_usec == 0)
2491 || (ms_now == 0xFFFFFFFF) ) {
sewardj02535bc2002-04-21 01:08:26 +00002492 res = do_syscall_select( n, (vki_fd_set*)rfds,
sewardj08a4c3f2002-04-13 03:45:44 +00002493 (vki_fd_set*)wfds,
2494 (vki_fd_set*)xfds,
2495 (struct vki_timeval*)timeout);
sewardj02535bc2002-04-21 01:08:26 +00002496 if (is_kerror(res)) {
2497 * (__errno_location()) = -res;
2498 return -1;
2499 } else {
2500 return res;
2501 }
2502 }
sewardj08a4c3f2002-04-13 03:45:44 +00002503
sewardj5f07b662002-04-23 16:52:51 +00002504 /* If a timeout was specified, set ms_end to be the end millisecond
2505 counter [wallclock] time. */
sewardj08a4c3f2002-04-13 03:45:44 +00002506 if (timeout) {
2507 res = my_do_syscall2(__NR_gettimeofday, (int)&t_now, (int)NULL);
sewardj2d94c112002-06-03 01:25:54 +00002508 my_assert(res == 0);
sewardj5f07b662002-04-23 16:52:51 +00002509 ms_end = ms_now;
2510 ms_end += (timeout->tv_usec / 1000);
2511 ms_end += (timeout->tv_sec * 1000);
sewardj08a4c3f2002-04-13 03:45:44 +00002512 /* Stay sane ... */
sewardj2d94c112002-06-03 01:25:54 +00002513 my_assert (ms_end >= ms_now);
sewardj08a4c3f2002-04-13 03:45:44 +00002514 }
2515
2516 /* fprintf(stderr, "MY_SELECT: before loop\n"); */
2517
2518 /* Either timeout == NULL, meaning wait indefinitely, or timeout !=
sewardj5f07b662002-04-23 16:52:51 +00002519 NULL, in which case ms_end holds the end time. */
sewardj05bb2c92002-06-26 00:47:17 +00002520
sewardj08a4c3f2002-04-13 03:45:44 +00002521 while (1) {
sewardj05bb2c92002-06-26 00:47:17 +00002522
2523 /* First, do a return-immediately select(). */
sewardj08a4c3f2002-04-13 03:45:44 +00002524
2525 /* These could be trashed each time round the loop, so restore
2526 them each time. */
2527 if (rfds) rfds_copy = *rfds;
2528 if (wfds) wfds_copy = *wfds;
2529 if (xfds) xfds_copy = *xfds;
2530
2531 zero_timeout.tv_sec = zero_timeout.tv_usec = 0;
2532
2533 res = do_syscall_select( n,
2534 rfds ? (vki_fd_set*)(&rfds_copy) : NULL,
2535 wfds ? (vki_fd_set*)(&wfds_copy) : NULL,
2536 xfds ? (vki_fd_set*)(&xfds_copy) : NULL,
2537 & zero_timeout );
sewardj02535bc2002-04-21 01:08:26 +00002538 if (is_kerror(res)) {
2539 /* Some kind of error (including EINTR). Set errno and
sewardj08a4c3f2002-04-13 03:45:44 +00002540 return. The sets are unspecified in this case. */
sewardj02535bc2002-04-21 01:08:26 +00002541 * (__errno_location()) = -res;
2542 return -1;
sewardj08a4c3f2002-04-13 03:45:44 +00002543 }
2544 if (res > 0) {
2545 /* one or more fds is ready. Copy out resulting sets and
2546 return. */
2547 if (rfds) *rfds = rfds_copy;
2548 if (wfds) *wfds = wfds_copy;
2549 if (xfds) *xfds = xfds_copy;
2550 return res;
2551 }
sewardj05bb2c92002-06-26 00:47:17 +00002552
2553 /* Nothing interesting happened, so we go to sleep for a
2554 while. */
2555
sewardj08a4c3f2002-04-13 03:45:44 +00002556 /* fprintf(stderr, "MY_SELECT: nanosleep\n"); */
2557 /* nanosleep and go round again */
sewardj02535bc2002-04-21 01:08:26 +00002558 nanosleep_interval.tv_sec = 0;
njn25e49d8e72002-09-23 09:36:25 +00002559 nanosleep_interval.tv_nsec = 11 * 1000 * 1000; /* 11 milliseconds */
sewardjf854f472002-04-21 12:19:41 +00002560 /* It's critical here that valgrind's nanosleep implementation
2561 is nonblocking. */
sewardj645030e2002-06-06 01:27:39 +00002562 res = my_do_syscall2(__NR_nanosleep,
sewardjf854f472002-04-21 12:19:41 +00002563 (int)(&nanosleep_interval), (int)NULL);
sewardj645030e2002-06-06 01:27:39 +00002564 if (res == -VKI_EINTR) {
2565 /* The nanosleep was interrupted by a signal. So we do the
2566 same. */
2567 * (__errno_location()) = EINTR;
2568 return -1;
2569 }
sewardj05bb2c92002-06-26 00:47:17 +00002570
2571 /* Sleeping finished. If a finite timeout, check to see if it
2572 has expired yet. */
2573 if (timeout) {
2574 VALGRIND_MAGIC_SEQUENCE(ms_now, 0xFFFFFFFF /* default */,
2575 VG_USERREQ__READ_MILLISECOND_TIMER,
2576 0, 0, 0, 0);
2577 my_assert(ms_now != 0xFFFFFFFF);
2578 if (ms_now >= ms_end) {
2579 /* timeout; nothing interesting happened. */
2580 if (rfds) FD_ZERO(rfds);
2581 if (wfds) FD_ZERO(wfds);
2582 if (xfds) FD_ZERO(xfds);
2583 return 0;
2584 }
2585 }
2586
sewardjf854f472002-04-21 12:19:41 +00002587 }
2588}
2589
2590
2591
2592
2593#include <sys/poll.h>
2594
sewardj3e909ce2002-06-03 13:27:15 +00002595#ifndef HAVE_NFDS_T
sewardj72d58482002-04-24 02:20:20 +00002596typedef unsigned long int nfds_t;
2597#endif
2598
sewardj705d3cb2002-05-23 13:13:12 +00002599
sewardj7db011a2002-11-13 22:00:20 +00002600int VGL_(poll) (struct pollfd *__fds, nfds_t __nfds, int __timeout)
sewardjf854f472002-04-21 12:19:41 +00002601{
sewardj5f07b662002-04-23 16:52:51 +00002602 unsigned int ms_now, ms_end;
sewardjf854f472002-04-21 12:19:41 +00002603 int res, i;
sewardjf854f472002-04-21 12:19:41 +00002604 struct vki_timespec nanosleep_interval;
2605
sewardjd140e442002-05-29 01:21:19 +00002606 __my_pthread_testcancel();
sewardjf854f472002-04-21 12:19:41 +00002607 ensure_valgrind("poll");
2608
sewardj5f07b662002-04-23 16:52:51 +00002609 /* Detect the current time and simultaneously find out if we are
2610 running on Valgrind. */
2611 VALGRIND_MAGIC_SEQUENCE(ms_now, 0xFFFFFFFF /* default */,
2612 VG_USERREQ__READ_MILLISECOND_TIMER,
2613 0, 0, 0, 0);
2614
sewardjf854f472002-04-21 12:19:41 +00002615 if (/* CHECK SIZES FOR struct pollfd */
2616 sizeof(struct timeval) != sizeof(struct vki_timeval))
2617 barf("valgrind's hacky non-blocking poll(): data sizes error");
2618
sewardj5f07b662002-04-23 16:52:51 +00002619 /* dummy initialisation to keep gcc -Wall happy */
2620 ms_end = 0;
2621
2622 /* If a zero timeout specified, this call is harmless. Also do
2623 this if not running on Valgrind. */
2624 if (__timeout == 0 || ms_now == 0xFFFFFFFF) {
sewardjf854f472002-04-21 12:19:41 +00002625 res = my_do_syscall3(__NR_poll, (int)__fds, __nfds, __timeout);
2626 if (is_kerror(res)) {
2627 * (__errno_location()) = -res;
2628 return -1;
2629 } else {
2630 return res;
2631 }
2632 }
2633
sewardj5f07b662002-04-23 16:52:51 +00002634 /* If a timeout was specified, set ms_end to be the end wallclock
2635 time. Easy considering that __timeout is in milliseconds. */
sewardjf854f472002-04-21 12:19:41 +00002636 if (__timeout > 0) {
sewardj650ac002002-04-29 12:20:34 +00002637 ms_end = ms_now + (unsigned int)__timeout;
sewardjf854f472002-04-21 12:19:41 +00002638 }
2639
2640 /* fprintf(stderr, "MY_POLL: before loop\n"); */
2641
2642 /* Either timeout < 0, meaning wait indefinitely, or timeout > 0,
2643 in which case t_end holds the end time. */
sewardj05bb2c92002-06-26 00:47:17 +00002644
sewardj2d94c112002-06-03 01:25:54 +00002645 my_assert(__timeout != 0);
sewardj5f07b662002-04-23 16:52:51 +00002646
sewardjf854f472002-04-21 12:19:41 +00002647 while (1) {
sewardj05bb2c92002-06-26 00:47:17 +00002648
2649 /* Do a return-immediately poll. */
2650
2651 res = my_do_syscall3(__NR_poll, (int)__fds, __nfds, 0 );
2652 if (is_kerror(res)) {
2653 /* Some kind of error. Set errno and return. */
2654 * (__errno_location()) = -res;
2655 return -1;
2656 }
2657 if (res > 0) {
2658 /* One or more fds is ready. Return now. */
2659 return res;
2660 }
2661
2662 /* Nothing interesting happened, so we go to sleep for a
2663 while. */
2664
2665 /* fprintf(stderr, "MY_POLL: nanosleep\n"); */
2666 /* nanosleep and go round again */
2667 nanosleep_interval.tv_sec = 0;
njn25e49d8e72002-09-23 09:36:25 +00002668 nanosleep_interval.tv_nsec = 13 * 1000 * 1000; /* 13 milliseconds */
sewardj05bb2c92002-06-26 00:47:17 +00002669 /* It's critical here that valgrind's nanosleep implementation
2670 is nonblocking. */
2671 (void)my_do_syscall2(__NR_nanosleep,
2672 (int)(&nanosleep_interval), (int)NULL);
2673
2674 /* Sleeping finished. If a finite timeout, check to see if it
2675 has expired yet. */
sewardjf854f472002-04-21 12:19:41 +00002676 if (__timeout > 0) {
sewardj5f07b662002-04-23 16:52:51 +00002677 VALGRIND_MAGIC_SEQUENCE(ms_now, 0xFFFFFFFF /* default */,
2678 VG_USERREQ__READ_MILLISECOND_TIMER,
2679 0, 0, 0, 0);
sewardj2d94c112002-06-03 01:25:54 +00002680 my_assert(ms_now != 0xFFFFFFFF);
sewardj5f07b662002-04-23 16:52:51 +00002681 if (ms_now >= ms_end) {
sewardjf854f472002-04-21 12:19:41 +00002682 /* timeout; nothing interesting happened. */
2683 for (i = 0; i < __nfds; i++)
2684 __fds[i].revents = 0;
2685 return 0;
2686 }
2687 }
2688
sewardj08a4c3f2002-04-13 03:45:44 +00002689 }
2690}
sewardj3b13f0e2002-04-25 20:17:29 +00002691
2692
sewardj705d3cb2002-05-23 13:13:12 +00002693/* Helper function used to make accept() non-blocking. Idea is to use
2694 the above nonblocking poll() to make this thread ONLY wait for the
2695 specified fd to become ready, and then return. */
sewardjd1c1cf22002-06-26 00:13:36 +00002696
2697/* Sigh -- a hack. We're not supposed to include this file directly;
2698 should do it via /usr/include/fcntl.h, but that introduces a
2699 varargs prototype for fcntl itself, which we can't mimic. */
2700#define _FCNTL_H
2701#include <bits/fcntl.h>
2702
sewardj705d3cb2002-05-23 13:13:12 +00002703static void wait_for_fd_to_be_readable_or_erring ( int fd )
2704{
2705 struct pollfd pfd;
sewardjd1c1cf22002-06-26 00:13:36 +00002706 int res;
2707
sewardj6e6cbaa2002-05-24 02:12:52 +00002708 /* fprintf(stderr, "wait_for_fd_to_be_readable_or_erring %d\n", fd); */
sewardjd1c1cf22002-06-26 00:13:36 +00002709
2710 /* First check to see if the fd is nonblocking, and/or invalid. In
2711 either case return immediately. */
2712 res = __libc_fcntl(fd, F_GETFL, 0);
2713 if (res == -1) return; /* fd is invalid somehow */
2714 if (res & O_NONBLOCK) return; /* fd is nonblocking */
2715
2716 /* Ok, we'd better wait with poll. */
sewardj705d3cb2002-05-23 13:13:12 +00002717 pfd.fd = fd;
2718 pfd.events = POLLIN | POLLPRI | POLLERR | POLLHUP | POLLNVAL;
2719 /* ... but not POLLOUT, you may notice. */
2720 pfd.revents = 0;
2721 (void)poll(&pfd, 1, -1 /* forever */);
2722}
2723
sewardj2a68e7e2002-11-16 11:04:18 +00002724static void wait_for_fd_to_be_writable_or_erring ( int fd )
2725{
2726 struct pollfd pfd;
2727 int res;
2728
2729 /* fprintf(stderr, "wait_for_fd_to_be_readable_or_erring %d\n", fd); */
2730
2731 /* First check to see if the fd is nonblocking, and/or invalid. In
2732 either case return immediately. */
2733 res = __libc_fcntl(fd, F_GETFL, 0);
2734 if (res == -1) return; /* fd is invalid somehow */
2735 if (res & O_NONBLOCK) return; /* fd is nonblocking */
2736
2737 /* Ok, we'd better wait with poll. */
2738 pfd.fd = fd;
2739 pfd.events = POLLOUT | POLLERR | POLLHUP | POLLNVAL;
2740 pfd.revents = 0;
2741 (void)poll(&pfd, 1, -1 /* forever */);
2742}
sewardj705d3cb2002-05-23 13:13:12 +00002743
sewardj3b13f0e2002-04-25 20:17:29 +00002744/* ---------------------------------------------------------------------
sewardj8f253ff2002-05-19 00:13:34 +00002745 Hacky implementation of semaphores.
2746 ------------------------------------------------------------------ */
2747
2748#include <semaphore.h>
2749
2750/* This is a terrible way to do the remapping. Plan is to import an
2751 AVL tree at some point. */
sewardj8f253ff2002-05-19 00:13:34 +00002752
2753typedef
2754 struct {
2755 pthread_mutex_t se_mx;
2756 pthread_cond_t se_cv;
2757 int count;
2758 }
2759 vg_sem_t;
2760
2761static pthread_mutex_t se_remap_mx = PTHREAD_MUTEX_INITIALIZER;
2762
2763static int se_remap_used = 0;
2764static sem_t* se_remap_orig[VG_N_SEMAPHORES];
2765static vg_sem_t se_remap_new[VG_N_SEMAPHORES];
2766
2767static vg_sem_t* se_remap ( sem_t* orig )
2768{
2769 int res, i;
2770 res = __pthread_mutex_lock(&se_remap_mx);
sewardj2d94c112002-06-03 01:25:54 +00002771 my_assert(res == 0);
sewardj8f253ff2002-05-19 00:13:34 +00002772
2773 for (i = 0; i < se_remap_used; i++) {
2774 if (se_remap_orig[i] == orig)
2775 break;
2776 }
2777 if (i == se_remap_used) {
2778 if (se_remap_used == VG_N_SEMAPHORES) {
2779 res = pthread_mutex_unlock(&se_remap_mx);
sewardj2d94c112002-06-03 01:25:54 +00002780 my_assert(res == 0);
sewardja1ac5cb2002-05-27 13:00:05 +00002781 barf("VG_N_SEMAPHORES is too low. Increase and recompile.");
sewardj8f253ff2002-05-19 00:13:34 +00002782 }
2783 se_remap_used++;
2784 se_remap_orig[i] = orig;
2785 /* printf("allocated semaphore %d\n", i); */
2786 }
2787 res = __pthread_mutex_unlock(&se_remap_mx);
sewardj2d94c112002-06-03 01:25:54 +00002788 my_assert(res == 0);
sewardj8f253ff2002-05-19 00:13:34 +00002789 return &se_remap_new[i];
2790}
2791
2792
2793int sem_init(sem_t *sem, int pshared, unsigned int value)
2794{
2795 int res;
2796 vg_sem_t* vg_sem;
2797 ensure_valgrind("sem_init");
2798 if (pshared != 0) {
sewardj4dced352002-06-04 22:54:20 +00002799 pthread_error("sem_init: unsupported pshared value");
sewardj8f253ff2002-05-19 00:13:34 +00002800 errno = ENOSYS;
2801 return -1;
2802 }
2803 vg_sem = se_remap(sem);
2804 res = pthread_mutex_init(&vg_sem->se_mx, NULL);
sewardj2d94c112002-06-03 01:25:54 +00002805 my_assert(res == 0);
sewardj8f253ff2002-05-19 00:13:34 +00002806 res = pthread_cond_init(&vg_sem->se_cv, NULL);
sewardj2d94c112002-06-03 01:25:54 +00002807 my_assert(res == 0);
sewardj8f253ff2002-05-19 00:13:34 +00002808 vg_sem->count = value;
2809 return 0;
2810}
2811
2812
2813int sem_wait ( sem_t* sem )
2814{
2815 int res;
2816 vg_sem_t* vg_sem;
2817 ensure_valgrind("sem_wait");
2818 vg_sem = se_remap(sem);
2819 res = __pthread_mutex_lock(&vg_sem->se_mx);
sewardj2d94c112002-06-03 01:25:54 +00002820 my_assert(res == 0);
sewardj8f253ff2002-05-19 00:13:34 +00002821 while (vg_sem->count == 0) {
2822 res = pthread_cond_wait(&vg_sem->se_cv, &vg_sem->se_mx);
sewardj2d94c112002-06-03 01:25:54 +00002823 my_assert(res == 0);
sewardj8f253ff2002-05-19 00:13:34 +00002824 }
2825 vg_sem->count--;
2826 res = __pthread_mutex_unlock(&vg_sem->se_mx);
sewardj2d94c112002-06-03 01:25:54 +00002827 my_assert(res == 0);
sewardj8f253ff2002-05-19 00:13:34 +00002828 return 0;
2829}
2830
2831int sem_post ( sem_t* sem )
2832{
2833 int res;
2834 vg_sem_t* vg_sem;
2835 ensure_valgrind("sem_post");
2836 vg_sem = se_remap(sem);
2837 res = __pthread_mutex_lock(&vg_sem->se_mx);
sewardj2d94c112002-06-03 01:25:54 +00002838 my_assert(res == 0);
sewardj8f253ff2002-05-19 00:13:34 +00002839 if (vg_sem->count == 0) {
2840 vg_sem->count++;
2841 res = pthread_cond_broadcast(&vg_sem->se_cv);
sewardj2d94c112002-06-03 01:25:54 +00002842 my_assert(res == 0);
sewardj8f253ff2002-05-19 00:13:34 +00002843 } else {
2844 vg_sem->count++;
2845 }
2846 res = __pthread_mutex_unlock(&vg_sem->se_mx);
sewardj2d94c112002-06-03 01:25:54 +00002847 my_assert(res == 0);
sewardj8f253ff2002-05-19 00:13:34 +00002848 return 0;
2849}
2850
2851
2852int sem_trywait ( sem_t* sem )
2853{
2854 int ret, res;
2855 vg_sem_t* vg_sem;
2856 ensure_valgrind("sem_trywait");
2857 vg_sem = se_remap(sem);
2858 res = __pthread_mutex_lock(&vg_sem->se_mx);
sewardj2d94c112002-06-03 01:25:54 +00002859 my_assert(res == 0);
sewardj8f253ff2002-05-19 00:13:34 +00002860 if (vg_sem->count > 0) {
2861 vg_sem->count--;
2862 ret = 0;
2863 } else {
2864 ret = -1;
2865 errno = EAGAIN;
2866 }
2867 res = __pthread_mutex_unlock(&vg_sem->se_mx);
sewardj2d94c112002-06-03 01:25:54 +00002868 my_assert(res == 0);
sewardj8f253ff2002-05-19 00:13:34 +00002869 return ret;
2870}
2871
2872
2873int sem_getvalue(sem_t* sem, int * sval)
2874{
2875 vg_sem_t* vg_sem;
2876 ensure_valgrind("sem_trywait");
2877 vg_sem = se_remap(sem);
2878 *sval = vg_sem->count;
2879 return 0;
2880}
2881
2882
2883int sem_destroy(sem_t * sem)
2884{
2885 kludged("sem_destroy");
2886 /* if someone waiting on this semaphore, errno = EBUSY, return -1 */
2887 return 0;
2888}
2889
sewardj9ad92d92002-10-16 19:45:06 +00002890
2891int sem_timedwait(sem_t* sem, const struct timespec *abstime)
2892{
2893 int res;
2894 vg_sem_t* vg_sem;
2895 ensure_valgrind("sem_timedwait");
2896 vg_sem = se_remap(sem);
2897 res = __pthread_mutex_lock(&vg_sem->se_mx);
2898 my_assert(res == 0);
2899 while ( vg_sem->count == 0 && res != ETIMEDOUT ) {
2900 res = pthread_cond_timedwait(&vg_sem->se_cv, &vg_sem->se_mx, abstime);
2901 }
2902 if ( vg_sem->count > 0 ) {
2903 vg_sem->count--;
2904 res = __pthread_mutex_unlock(&vg_sem->se_mx);
2905 my_assert(res == 0 );
2906 return 0;
2907 } else {
2908 res = __pthread_mutex_unlock(&vg_sem->se_mx);
2909 my_assert(res == 0 );
2910 *(__errno_location()) = ETIMEDOUT;
2911 return -1;
2912 }
2913}
2914
sewardj8f253ff2002-05-19 00:13:34 +00002915
2916/* ---------------------------------------------------------------------
sewardj2d8b3f02002-06-01 14:14:19 +00002917 Reader-writer locks.
sewardja1ac5cb2002-05-27 13:00:05 +00002918 ------------------------------------------------------------------ */
2919
sewardj2d8b3f02002-06-01 14:14:19 +00002920typedef
2921 struct {
2922 int initted; /* != 0 --> in use; sanity check only */
2923 int prefer_w; /* != 0 --> prefer writer */
2924 int nwait_r; /* # of waiting readers */
2925 int nwait_w; /* # of waiting writers */
2926 pthread_cond_t cv_r; /* for signalling readers */
2927 pthread_cond_t cv_w; /* for signalling writers */
2928 pthread_mutex_t mx;
2929 int status;
2930 /* allowed range for status: >= -1. -1 means 1 writer currently
2931 active, >= 0 means N readers currently active. */
2932 }
2933 vg_rwlock_t;
sewardja1ac5cb2002-05-27 13:00:05 +00002934
2935
2936static pthread_mutex_t rw_remap_mx = PTHREAD_MUTEX_INITIALIZER;
2937
2938static int rw_remap_used = 0;
2939static pthread_rwlock_t* rw_remap_orig[VG_N_RWLOCKS];
2940static vg_rwlock_t rw_remap_new[VG_N_RWLOCKS];
2941
sewardj2d8b3f02002-06-01 14:14:19 +00002942
2943static
2944void init_vg_rwlock ( vg_rwlock_t* vg_rwl )
2945{
2946 int res = 0;
2947 vg_rwl->initted = 1;
2948 vg_rwl->prefer_w = 1;
2949 vg_rwl->nwait_r = 0;
2950 vg_rwl->nwait_w = 0;
2951 vg_rwl->status = 0;
2952 res = pthread_mutex_init(&vg_rwl->mx, NULL);
2953 res |= pthread_cond_init(&vg_rwl->cv_r, NULL);
2954 res |= pthread_cond_init(&vg_rwl->cv_w, NULL);
sewardj2d94c112002-06-03 01:25:54 +00002955 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002956}
2957
2958
sewardja1ac5cb2002-05-27 13:00:05 +00002959/* Take the address of a LinuxThreads rwlock_t and return the shadow
2960 address of our version. Further, if the LinuxThreads version
2961 appears to have been statically initialised, do the same to the one
2962 we allocate here. The pthread_rwlock_t.__rw_readers field is set
2963 to zero by PTHREAD_RWLOCK_INITIALIZER, so we take zero as meaning
2964 uninitialised and non-zero meaning initialised.
2965*/
2966static vg_rwlock_t* rw_remap ( pthread_rwlock_t* orig )
2967{
2968 int res, i;
2969 vg_rwlock_t* vg_rwl;
2970 res = __pthread_mutex_lock(&rw_remap_mx);
sewardj2d94c112002-06-03 01:25:54 +00002971 my_assert(res == 0);
sewardja1ac5cb2002-05-27 13:00:05 +00002972
2973 for (i = 0; i < rw_remap_used; i++) {
2974 if (rw_remap_orig[i] == orig)
2975 break;
2976 }
2977 if (i == rw_remap_used) {
2978 if (rw_remap_used == VG_N_RWLOCKS) {
sewardj2d8b3f02002-06-01 14:14:19 +00002979 res = __pthread_mutex_unlock(&rw_remap_mx);
sewardj2d94c112002-06-03 01:25:54 +00002980 my_assert(res == 0);
sewardja1ac5cb2002-05-27 13:00:05 +00002981 barf("VG_N_RWLOCKS is too low. Increase and recompile.");
2982 }
2983 rw_remap_used++;
2984 rw_remap_orig[i] = orig;
sewardj2d8b3f02002-06-01 14:14:19 +00002985 rw_remap_new[i].initted = 0;
sewardja1ac5cb2002-05-27 13:00:05 +00002986 if (0) printf("allocated rwlock %d\n", i);
2987 }
2988 res = __pthread_mutex_unlock(&rw_remap_mx);
sewardj2d94c112002-06-03 01:25:54 +00002989 my_assert(res == 0);
sewardja1ac5cb2002-05-27 13:00:05 +00002990 vg_rwl = &rw_remap_new[i];
2991
sewardj2d8b3f02002-06-01 14:14:19 +00002992 /* Initialise the shadow, if required. */
sewardja1ac5cb2002-05-27 13:00:05 +00002993 if (orig->__rw_readers == 0) {
sewardja1ac5cb2002-05-27 13:00:05 +00002994 orig->__rw_readers = 1;
sewardj2d8b3f02002-06-01 14:14:19 +00002995 init_vg_rwlock(vg_rwl);
sewardja1ac5cb2002-05-27 13:00:05 +00002996 if (orig->__rw_kind == PTHREAD_RWLOCK_PREFER_READER_NP)
sewardj2d8b3f02002-06-01 14:14:19 +00002997 vg_rwl->prefer_w = 0;
sewardja1ac5cb2002-05-27 13:00:05 +00002998 }
2999
3000 return vg_rwl;
3001}
3002
3003
sewardja1ac5cb2002-05-27 13:00:05 +00003004int pthread_rwlock_init ( pthread_rwlock_t* orig,
3005 const pthread_rwlockattr_t* attr )
3006{
sewardja1ac5cb2002-05-27 13:00:05 +00003007 vg_rwlock_t* rwl;
3008 if (0) printf ("pthread_rwlock_init\n");
3009 /* Force the remapper to initialise the shadow. */
3010 orig->__rw_readers = 0;
3011 /* Install the lock preference; the remapper needs to know it. */
3012 orig->__rw_kind = PTHREAD_RWLOCK_DEFAULT_NP;
3013 if (attr)
3014 orig->__rw_kind = attr->__lockkind;
3015 rwl = rw_remap ( orig );
sewardj2d8b3f02002-06-01 14:14:19 +00003016 return 0;
sewardja1ac5cb2002-05-27 13:00:05 +00003017}
3018
sewardj2d8b3f02002-06-01 14:14:19 +00003019
3020static
3021void pthread_rwlock_rdlock_CANCEL_HDLR ( void* rwl_v )
sewardja1ac5cb2002-05-27 13:00:05 +00003022{
sewardj2d8b3f02002-06-01 14:14:19 +00003023 vg_rwlock_t* rwl = (vg_rwlock_t*)rwl_v;
3024 rwl->nwait_r--;
3025 pthread_mutex_unlock (&rwl->mx);
sewardja1ac5cb2002-05-27 13:00:05 +00003026}
3027
sewardj2d8b3f02002-06-01 14:14:19 +00003028
sewardja1ac5cb2002-05-27 13:00:05 +00003029int pthread_rwlock_rdlock ( pthread_rwlock_t* orig )
3030{
3031 int res;
3032 vg_rwlock_t* rwl;
3033 if (0) printf ("pthread_rwlock_rdlock\n");
3034 rwl = rw_remap ( orig );
sewardj2d8b3f02002-06-01 14:14:19 +00003035 res = __pthread_mutex_lock(&rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00003036 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00003037 if (!rwl->initted) {
3038 res = __pthread_mutex_unlock(&rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00003039 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00003040 return EINVAL;
3041 }
3042 if (rwl->status < 0) {
sewardj2d94c112002-06-03 01:25:54 +00003043 my_assert(rwl->status == -1);
sewardj2d8b3f02002-06-01 14:14:19 +00003044 rwl->nwait_r++;
3045 pthread_cleanup_push( pthread_rwlock_rdlock_CANCEL_HDLR, rwl );
3046 while (1) {
3047 if (rwl->status == 0) break;
3048 res = pthread_cond_wait(&rwl->cv_r, &rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00003049 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00003050 }
3051 pthread_cleanup_pop(0);
3052 rwl->nwait_r--;
3053 }
sewardj2d94c112002-06-03 01:25:54 +00003054 my_assert(rwl->status >= 0);
sewardj2d8b3f02002-06-01 14:14:19 +00003055 rwl->status++;
3056 res = __pthread_mutex_unlock(&rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00003057 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00003058 return 0;
sewardja1ac5cb2002-05-27 13:00:05 +00003059}
3060
sewardj2d8b3f02002-06-01 14:14:19 +00003061
sewardja1ac5cb2002-05-27 13:00:05 +00003062int pthread_rwlock_tryrdlock ( pthread_rwlock_t* orig )
3063{
3064 int res;
3065 vg_rwlock_t* rwl;
3066 if (0) printf ("pthread_rwlock_tryrdlock\n");
3067 rwl = rw_remap ( orig );
sewardj2d8b3f02002-06-01 14:14:19 +00003068 res = __pthread_mutex_lock(&rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00003069 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00003070 if (!rwl->initted) {
3071 res = __pthread_mutex_unlock(&rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00003072 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00003073 return EINVAL;
3074 }
3075 if (rwl->status == -1) {
3076 /* Writer active; we have to give up. */
3077 res = __pthread_mutex_unlock(&rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00003078 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00003079 return EBUSY;
3080 }
3081 /* Success */
sewardj2d94c112002-06-03 01:25:54 +00003082 my_assert(rwl->status >= 0);
sewardj2d8b3f02002-06-01 14:14:19 +00003083 rwl->status++;
3084 res = __pthread_mutex_unlock(&rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00003085 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00003086 return 0;
sewardja1ac5cb2002-05-27 13:00:05 +00003087}
3088
sewardj2d8b3f02002-06-01 14:14:19 +00003089
3090static
3091void pthread_rwlock_wrlock_CANCEL_HDLR ( void* rwl_v )
3092{
3093 vg_rwlock_t* rwl = (vg_rwlock_t*)rwl_v;
3094 rwl->nwait_w--;
3095 pthread_mutex_unlock (&rwl->mx);
3096}
3097
3098
sewardja1ac5cb2002-05-27 13:00:05 +00003099int pthread_rwlock_wrlock ( pthread_rwlock_t* orig )
3100{
3101 int res;
3102 vg_rwlock_t* rwl;
3103 if (0) printf ("pthread_rwlock_wrlock\n");
3104 rwl = rw_remap ( orig );
sewardj2d8b3f02002-06-01 14:14:19 +00003105 res = __pthread_mutex_lock(&rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00003106 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00003107 if (!rwl->initted) {
3108 res = __pthread_mutex_unlock(&rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00003109 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00003110 return EINVAL;
3111 }
3112 if (rwl->status != 0) {
3113 rwl->nwait_w++;
3114 pthread_cleanup_push( pthread_rwlock_wrlock_CANCEL_HDLR, rwl );
3115 while (1) {
3116 if (rwl->status == 0) break;
3117 res = pthread_cond_wait(&rwl->cv_w, &rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00003118 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00003119 }
3120 pthread_cleanup_pop(0);
3121 rwl->nwait_w--;
3122 }
sewardj2d94c112002-06-03 01:25:54 +00003123 my_assert(rwl->status == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00003124 rwl->status = -1;
3125 res = __pthread_mutex_unlock(&rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00003126 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00003127 return 0;
sewardja1ac5cb2002-05-27 13:00:05 +00003128}
3129
sewardj2d8b3f02002-06-01 14:14:19 +00003130
sewardja1ac5cb2002-05-27 13:00:05 +00003131int pthread_rwlock_trywrlock ( pthread_rwlock_t* orig )
3132{
3133 int res;
3134 vg_rwlock_t* rwl;
sewardj2d8b3f02002-06-01 14:14:19 +00003135 if (0) printf ("pthread_wrlock_trywrlock\n");
sewardja1ac5cb2002-05-27 13:00:05 +00003136 rwl = rw_remap ( orig );
sewardj2d8b3f02002-06-01 14:14:19 +00003137 res = __pthread_mutex_lock(&rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00003138 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00003139 if (!rwl->initted) {
3140 res = __pthread_mutex_unlock(&rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00003141 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00003142 return EINVAL;
3143 }
3144 if (rwl->status != 0) {
3145 /* Reader(s) or a writer active; we have to give up. */
3146 res = __pthread_mutex_unlock(&rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00003147 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00003148 return EBUSY;
3149 }
3150 /* Success */
sewardj2d94c112002-06-03 01:25:54 +00003151 my_assert(rwl->status == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00003152 rwl->status = -1;
3153 res = __pthread_mutex_unlock(&rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00003154 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00003155 return 0;
sewardja1ac5cb2002-05-27 13:00:05 +00003156}
3157
sewardj2d8b3f02002-06-01 14:14:19 +00003158
sewardja1ac5cb2002-05-27 13:00:05 +00003159int pthread_rwlock_unlock ( pthread_rwlock_t* orig )
3160{
3161 int res;
3162 vg_rwlock_t* rwl;
3163 if (0) printf ("pthread_rwlock_unlock\n");
3164 rwl = rw_remap ( orig );
sewardj2d8b3f02002-06-01 14:14:19 +00003165 rwl = rw_remap ( orig );
3166 res = __pthread_mutex_lock(&rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00003167 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00003168 if (!rwl->initted) {
3169 res = __pthread_mutex_unlock(&rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00003170 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00003171 return EINVAL;
3172 }
3173 if (rwl->status == 0) {
3174 res = __pthread_mutex_unlock(&rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00003175 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00003176 return EPERM;
3177 }
sewardj2d94c112002-06-03 01:25:54 +00003178 my_assert(rwl->status != 0);
sewardj2d8b3f02002-06-01 14:14:19 +00003179 if (rwl->status == -1) {
3180 rwl->status = 0;
3181 } else {
sewardj2d94c112002-06-03 01:25:54 +00003182 my_assert(rwl->status > 0);
sewardj2d8b3f02002-06-01 14:14:19 +00003183 rwl->status--;
3184 }
3185
sewardj2d94c112002-06-03 01:25:54 +00003186 my_assert(rwl->status >= 0);
sewardj2d8b3f02002-06-01 14:14:19 +00003187
3188 if (rwl->prefer_w) {
3189
3190 /* Favour waiting writers, if any. */
3191 if (rwl->nwait_w > 0) {
3192 /* Writer(s) are waiting. */
3193 if (rwl->status == 0) {
3194 /* We can let a writer in. */
3195 res = pthread_cond_signal(&rwl->cv_w);
sewardj2d94c112002-06-03 01:25:54 +00003196 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00003197 } else {
3198 /* There are still readers active. Do nothing; eventually
3199 they will disappear, at which point a writer will be
3200 admitted. */
3201 }
3202 }
3203 else
3204 /* No waiting writers. */
3205 if (rwl->nwait_r > 0) {
3206 /* Let in a waiting reader. */
3207 res = pthread_cond_signal(&rwl->cv_r);
sewardj2d94c112002-06-03 01:25:54 +00003208 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00003209 }
3210
3211 } else {
3212
3213 /* Favour waiting readers, if any. */
3214 if (rwl->nwait_r > 0) {
3215 /* Reader(s) are waiting; let one in. */
3216 res = pthread_cond_signal(&rwl->cv_r);
sewardj2d94c112002-06-03 01:25:54 +00003217 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00003218 }
3219 else
3220 /* No waiting readers. */
3221 if (rwl->nwait_w > 0 && rwl->status == 0) {
3222 /* We have waiting writers and no active readers; let a
3223 writer in. */
3224 res = pthread_cond_signal(&rwl->cv_w);
sewardj2d94c112002-06-03 01:25:54 +00003225 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00003226 }
3227 }
3228
3229 res = __pthread_mutex_unlock(&rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00003230 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00003231 return 0;
3232}
3233
3234
3235int pthread_rwlock_destroy ( pthread_rwlock_t *orig )
3236{
3237 int res;
3238 vg_rwlock_t* rwl;
3239 if (0) printf ("pthread_rwlock_destroy\n");
3240 rwl = rw_remap ( orig );
3241 res = __pthread_mutex_lock(&rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00003242 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00003243 if (!rwl->initted) {
3244 res = __pthread_mutex_unlock(&rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00003245 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00003246 return EINVAL;
3247 }
3248 if (rwl->status != 0 || rwl->nwait_r > 0 || rwl->nwait_w > 0) {
3249 res = __pthread_mutex_unlock(&rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00003250 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00003251 return EBUSY;
3252 }
3253 rwl->initted = 0;
3254 res = __pthread_mutex_unlock(&rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00003255 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00003256 return 0;
sewardja1ac5cb2002-05-27 13:00:05 +00003257}
3258
3259
sewardj47e4e312002-06-18 09:24:34 +00003260/* Copied directly from LinuxThreads. */
3261int
3262pthread_rwlockattr_init (pthread_rwlockattr_t *attr)
3263{
3264 attr->__lockkind = 0;
3265 attr->__pshared = PTHREAD_PROCESS_PRIVATE;
3266
3267 return 0;
3268}
3269
sewardjfe18eb82002-07-13 12:58:44 +00003270/* Copied directly from LinuxThreads. */
3271int
sewardj5706bfa2002-12-08 23:42:17 +00003272pthread_rwlockattr_destroy (pthread_rwlockattr_t *attr)
3273{
3274 return 0;
3275}
3276
3277/* Copied directly from LinuxThreads. */
3278int
sewardjfe18eb82002-07-13 12:58:44 +00003279pthread_rwlockattr_setpshared (pthread_rwlockattr_t *attr, int pshared)
3280{
3281 if (pshared != PTHREAD_PROCESS_PRIVATE && pshared != PTHREAD_PROCESS_SHARED)
3282 return EINVAL;
3283
3284 /* For now it is not possible to shared a conditional variable. */
3285 if (pshared != PTHREAD_PROCESS_PRIVATE)
3286 return ENOSYS;
3287
3288 attr->__pshared = pshared;
3289
3290 return 0;
3291}
3292
sewardj47e4e312002-06-18 09:24:34 +00003293
sewardja1ac5cb2002-05-27 13:00:05 +00003294/* ---------------------------------------------------------------------
sewardjd5bef572002-10-23 21:49:33 +00003295 Make SYSV IPC not block everything
3296 ------------------------------------------------------------------ */
3297
3298#include <sys/ipc.h>
3299#include <sys/msg.h>
3300#include <asm/ipc.h> /* for ipc_kludge */
3301
3302static inline int sys_ipc(unsigned call, int first, int second, int third, void *ptr)
3303{
3304 return my_do_syscall5(__NR_ipc, call, first, second, third, (int)ptr);
3305}
3306
3307/* Turn a blocking msgsnd() into a polling non-blocking one, so that
3308 other threads make progress */
sewardjf220ccc2002-10-23 21:53:49 +00003309int VGL_(msgsnd)(int msgid, const void *msgp, size_t msgsz, int msgflg)
sewardjd5bef572002-10-23 21:49:33 +00003310{
3311 struct vki_timespec nanosleep_interval;
3312 int err;
3313
3314 ensure_valgrind("msgsnd");
3315
3316 nanosleep_interval.tv_sec = 0;
3317 nanosleep_interval.tv_nsec = 13 * 1000 * 1000; /* 13 milliseconds */
3318
3319 if (msgflg & IPC_NOWAIT) {
3320 /* If we aren't blocking anyway, just do it */
3321 err = sys_ipc(11, msgid, msgsz, msgflg, (void *)msgp);
3322 } else {
3323 /* Otherwise poll on the queue to let other things run */
3324 for(;;) {
3325 err = sys_ipc(11, msgid, msgsz, msgflg | IPC_NOWAIT, (void *)msgp);
3326
3327 if (err != -EAGAIN)
3328 break;
3329
3330 (void)my_do_syscall2(__NR_nanosleep,
3331 (int)(&nanosleep_interval), (int)NULL);
3332 }
3333 }
3334
3335 if (is_kerror(err)) {
3336 *(__errno_location()) = -err;
3337 return -1;
3338 }
3339 return 0;
3340}
3341
3342/* Turn a blocking msgrcv() into a polling non-blocking one, so that
3343 other threads make progress */
sewardjf220ccc2002-10-23 21:53:49 +00003344int VGL_(msgrcv)( int msqid, void *msgp, size_t msgsz, long msgtyp, int msgflg )
sewardjd5bef572002-10-23 21:49:33 +00003345{
3346 struct vki_timespec nanosleep_interval;
3347 int err;
3348 struct ipc_kludge tmp;
3349
3350 ensure_valgrind("msgrcv");
3351
3352 nanosleep_interval.tv_sec = 0;
3353 nanosleep_interval.tv_nsec = 13 * 1000 * 1000; /* 13 milliseconds */
3354
3355 tmp.msgp = msgp;
3356 tmp.msgtyp = msgtyp;
3357
3358 if (msgflg & IPC_NOWAIT) {
3359 /* If we aren't blocking anyway, just do it */
3360 err = sys_ipc(12, msqid, msgsz, msgflg, &tmp );
3361 } else {
3362 /* Otherwise poll on the queue to let other things run */
3363 for(;;) {
3364 err = sys_ipc(12, msqid, msgsz, msgflg | IPC_NOWAIT, &tmp );
3365
3366 if (err != -ENOMSG)
3367 break;
3368
3369 (void)my_do_syscall2(__NR_nanosleep,
3370 (int)(&nanosleep_interval), (int)NULL);
3371 }
3372 }
3373
3374 if (is_kerror(err)) {
3375 *(__errno_location()) = -err;
3376 return -1;
3377 }
3378
3379 return 0;
3380}
3381
3382
3383
3384/* ---------------------------------------------------------------------
sewardj3b13f0e2002-04-25 20:17:29 +00003385 B'stard.
3386 ------------------------------------------------------------------ */
3387
3388# define strong_alias(name, aliasname) \
3389 extern __typeof (name) aliasname __attribute__ ((alias (#name)));
3390
sewardj5905fae2002-04-26 13:25:00 +00003391# define weak_alias(name, aliasname) \
3392 extern __typeof (name) aliasname __attribute__ ((weak, alias (#name)));
sewardj3b13f0e2002-04-25 20:17:29 +00003393
sewardj5905fae2002-04-26 13:25:00 +00003394strong_alias(__pthread_mutex_lock, pthread_mutex_lock)
3395strong_alias(__pthread_mutex_trylock, pthread_mutex_trylock)
3396strong_alias(__pthread_mutex_unlock, pthread_mutex_unlock)
3397strong_alias(__pthread_mutexattr_init, pthread_mutexattr_init)
3398 weak_alias(__pthread_mutexattr_settype, pthread_mutexattr_settype)
3399strong_alias(__pthread_mutex_init, pthread_mutex_init)
3400strong_alias(__pthread_mutexattr_destroy, pthread_mutexattr_destroy)
3401strong_alias(__pthread_mutex_destroy, pthread_mutex_destroy)
3402strong_alias(__pthread_once, pthread_once)
3403strong_alias(__pthread_atfork, pthread_atfork)
3404strong_alias(__pthread_key_create, pthread_key_create)
3405strong_alias(__pthread_getspecific, pthread_getspecific)
3406strong_alias(__pthread_setspecific, pthread_setspecific)
3407
sewardjd529a442002-05-04 19:49:21 +00003408#ifndef GLIBC_2_1
sewardj3b13f0e2002-04-25 20:17:29 +00003409strong_alias(sigaction, __sigaction)
sewardjd529a442002-05-04 19:49:21 +00003410#endif
3411
sewardj5905fae2002-04-26 13:25:00 +00003412strong_alias(close, __close)
sewardj3b13f0e2002-04-25 20:17:29 +00003413strong_alias(fcntl, __fcntl)
sewardj5905fae2002-04-26 13:25:00 +00003414strong_alias(lseek, __lseek)
3415strong_alias(open, __open)
3416strong_alias(open64, __open64)
sewardj5905fae2002-04-26 13:25:00 +00003417strong_alias(read, __read)
3418strong_alias(wait, __wait)
3419strong_alias(write, __write)
sewardj3b13f0e2002-04-25 20:17:29 +00003420strong_alias(connect, __connect)
sewardj5905fae2002-04-26 13:25:00 +00003421strong_alias(send, __send)
3422
sewardj726c4122002-05-16 23:39:10 +00003423weak_alias (__pread64, pread64)
sewardja18e2102002-05-18 10:43:22 +00003424weak_alias (__pwrite64, pwrite64)
sewardj5905fae2002-04-26 13:25:00 +00003425weak_alias(__fork, fork)
njn25e49d8e72002-09-23 09:36:25 +00003426weak_alias(__vfork, vfork)
sewardj7f6456d2002-05-21 00:51:21 +00003427
sewardjf0b06452002-06-04 08:38:04 +00003428weak_alias (__pthread_kill_other_threads_np, pthread_kill_other_threads_np)
sewardj3b13f0e2002-04-25 20:17:29 +00003429
3430/*--------------------------------------------------*/
3431
sewardj5905fae2002-04-26 13:25:00 +00003432weak_alias(pthread_rwlock_rdlock, __pthread_rwlock_rdlock)
sewardj5905fae2002-04-26 13:25:00 +00003433weak_alias(pthread_rwlock_unlock, __pthread_rwlock_unlock)
sewardj262b0292002-05-01 00:03:16 +00003434weak_alias(pthread_rwlock_wrlock, __pthread_rwlock_wrlock)
sewardj060b04f2002-04-26 21:01:13 +00003435
sewardja1ac5cb2002-05-27 13:00:05 +00003436weak_alias(pthread_rwlock_destroy, __pthread_rwlock_destroy)
3437weak_alias(pthread_rwlock_init, __pthread_rwlock_init)
3438weak_alias(pthread_rwlock_tryrdlock, __pthread_rwlock_tryrdlock)
3439weak_alias(pthread_rwlock_trywrlock, __pthread_rwlock_trywrlock)
3440
sewardj060b04f2002-04-26 21:01:13 +00003441
sewardj3b13f0e2002-04-25 20:17:29 +00003442/* I've no idea what these are, but they get called quite a lot.
3443 Anybody know? */
3444
3445#undef _IO_flockfile
3446void _IO_flockfile ( _IO_FILE * file )
3447{
sewardj853f55d2002-04-26 00:27:53 +00003448 pthread_mutex_lock(file->_lock);
sewardj3b13f0e2002-04-25 20:17:29 +00003449}
sewardj5905fae2002-04-26 13:25:00 +00003450weak_alias(_IO_flockfile, flockfile);
3451
sewardj3b13f0e2002-04-25 20:17:29 +00003452
3453#undef _IO_funlockfile
3454void _IO_funlockfile ( _IO_FILE * file )
3455{
sewardj853f55d2002-04-26 00:27:53 +00003456 pthread_mutex_unlock(file->_lock);
sewardj3b13f0e2002-04-25 20:17:29 +00003457}
sewardj5905fae2002-04-26 13:25:00 +00003458weak_alias(_IO_funlockfile, funlockfile);
3459
sewardj3b13f0e2002-04-25 20:17:29 +00003460
sewardjd4f2c712002-04-30 10:20:10 +00003461/* This doesn't seem to be needed to simulate libpthread.so's external
3462 interface, but many people complain about its absence. */
3463
3464strong_alias(__pthread_mutexattr_settype, __pthread_mutexattr_setkind_np)
3465weak_alias(__pthread_mutexattr_setkind_np, pthread_mutexattr_setkind_np)
sewardj439d45e2002-05-03 20:43:10 +00003466
3467
3468/*--------------------------------------------------------------------*/
3469/*--- end vg_libpthread.c ---*/
3470/*--------------------------------------------------------------------*/