blob: deaeab7f9de8ca6cb75e06688c63cb2dd4cfec3a [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
sewardjb34e4db2002-12-08 23:51:32 +0000516__attribute__((weak))
517int pthread_setconcurrency(int new_level)
518{
519 if (new_level < 0)
520 return EINVAL;
521 else
522 return 0;
523}
524
sewardj111b14c2002-10-20 16:22:57 +0000525
sewardj20917d82002-05-28 01:36:45 +0000526/* ---------------------------------------------------
527 Helper functions for running a thread
528 and for clearing up afterwards.
529 ------------------------------------------------ */
530
531/* All exiting threads eventually pass through here, bearing the
532 return value, or PTHREAD_CANCELED, in ret_val. */
533static
534__attribute__((noreturn))
535void thread_exit_wrapper ( void* ret_val )
536{
sewardj870497a2002-05-29 01:06:47 +0000537 int detached, res;
538 CleanupEntry cu;
539 pthread_key_t key;
sewardj00a66b12002-10-12 16:42:35 +0000540 void** specifics_ptr;
sewardj870497a2002-05-29 01:06:47 +0000541
sewardj20917d82002-05-28 01:36:45 +0000542 /* Run this thread's cleanup handlers. */
sewardj8ad94e12002-05-29 00:10:20 +0000543 while (1) {
544 VALGRIND_MAGIC_SEQUENCE(res, (-1) /* default */,
545 VG_USERREQ__CLEANUP_POP,
546 &cu, 0, 0, 0);
547 if (res == -1) break; /* stack empty */
sewardj2d94c112002-06-03 01:25:54 +0000548 my_assert(res == 0);
sewardj8ad94e12002-05-29 00:10:20 +0000549 if (0) printf("running exit cleanup handler");
550 cu.fn ( cu.arg );
551 }
552
sewardj870497a2002-05-29 01:06:47 +0000553 /* Run this thread's key finalizers. Really this should be run
554 PTHREAD_DESTRUCTOR_ITERATIONS times. */
555 for (key = 0; key < VG_N_THREAD_KEYS; key++) {
556 VALGRIND_MAGIC_SEQUENCE(res, (-2) /* default */,
557 VG_USERREQ__GET_KEY_D_AND_S,
558 key, &cu, 0, 0 );
559 if (res == 0) {
560 /* valid key */
561 if (cu.fn && cu.arg)
562 cu.fn /* destructor for key */
563 ( cu.arg /* specific for key for this thread */ );
564 continue;
565 }
sewardj2d94c112002-06-03 01:25:54 +0000566 my_assert(res == -1);
sewardj870497a2002-05-29 01:06:47 +0000567 }
sewardj20917d82002-05-28 01:36:45 +0000568
sewardj00a66b12002-10-12 16:42:35 +0000569 /* Free up my specifics space, if any. */
570 VALGRIND_MAGIC_SEQUENCE(specifics_ptr, 3 /* default */,
571 VG_USERREQ__PTHREAD_GETSPECIFIC_PTR,
572 pthread_self(), 0, 0, 0);
573 my_assert(specifics_ptr != (void**)3);
574 my_assert(specifics_ptr != (void**)1); /* 1 means invalid thread */
575 if (specifics_ptr != NULL)
576 my_free(specifics_ptr);
577
sewardj20917d82002-05-28 01:36:45 +0000578 /* Decide on my final disposition. */
579 VALGRIND_MAGIC_SEQUENCE(detached, (-1) /* default */,
580 VG_USERREQ__SET_OR_GET_DETACH,
sewardj7989d0c2002-05-28 11:00:01 +0000581 2 /* get */, pthread_self(), 0, 0);
sewardj2d94c112002-06-03 01:25:54 +0000582 my_assert(detached == 0 || detached == 1);
sewardj20917d82002-05-28 01:36:45 +0000583
584 if (detached) {
585 /* Detached; I just quit right now. */
586 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
587 VG_USERREQ__QUIT, 0, 0, 0, 0);
588 } else {
589 /* Not detached; so I wait for a joiner. */
590 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
591 VG_USERREQ__WAIT_JOINER, ret_val, 0, 0, 0);
592 }
593 /* NOTREACHED */
594 barf("thread_exit_wrapper: still alive?!");
595}
596
597
598/* This function is a wrapper function for running a thread. It runs
599 the root function specified in pthread_create, and then, should the
600 root function return a value, it arranges to run the thread's
601 cleanup handlers and exit correctly. */
602
sewardj728a5272002-06-20 10:25:37 +0000603/* Struct used to convey info from pthread_create to thread_wrapper.
604 Must be careful not to pass to the child thread any pointers to
605 objects which might be on the parent's stack. */
sewardj20917d82002-05-28 01:36:45 +0000606typedef
607 struct {
sewardj728a5272002-06-20 10:25:37 +0000608 int attr__detachstate;
sewardj20917d82002-05-28 01:36:45 +0000609 void* (*root_fn) ( void* );
610 void* arg;
611 }
612 NewThreadInfo;
613
614
615/* This is passed to the VG_USERREQ__APPLY_IN_NEW_THREAD and so must
616 not return. Note that this runs in the new thread, not the
617 parent. */
618static
619__attribute__((noreturn))
620void thread_wrapper ( NewThreadInfo* info )
621{
sewardj728a5272002-06-20 10:25:37 +0000622 int attr__detachstate;
sewardj20917d82002-05-28 01:36:45 +0000623 void* (*root_fn) ( void* );
624 void* arg;
625 void* ret_val;
626
sewardj728a5272002-06-20 10:25:37 +0000627 attr__detachstate = info->attr__detachstate;
628 root_fn = info->root_fn;
629 arg = info->arg;
sewardj20917d82002-05-28 01:36:45 +0000630
sewardj20917d82002-05-28 01:36:45 +0000631 /* Free up the arg block that pthread_create malloced. */
sewardj00a66b12002-10-12 16:42:35 +0000632 my_free(info);
sewardj20917d82002-05-28 01:36:45 +0000633
sewardj7989d0c2002-05-28 11:00:01 +0000634 /* Minimally observe the attributes supplied. */
sewardj728a5272002-06-20 10:25:37 +0000635 if (attr__detachstate != PTHREAD_CREATE_DETACHED
636 && attr__detachstate != PTHREAD_CREATE_JOINABLE)
637 pthread_error("thread_wrapper: invalid attr->__detachstate");
638 if (attr__detachstate == PTHREAD_CREATE_DETACHED)
639 pthread_detach(pthread_self());
sewardj7989d0c2002-05-28 11:00:01 +0000640
sewardj00a66b12002-10-12 16:42:35 +0000641# ifdef GLIBC_2_3
642 /* Set this thread's locale to the global (default) locale. A hack
643 in support of glibc-2.3. This does the biz for the all new
644 threads; the root thread is done with a horrible hack in
645 init_libc_tsd_keys() below.
646 */
647 __uselocale(LC_GLOBAL_LOCALE);
648# endif
649
sewardj20917d82002-05-28 01:36:45 +0000650 /* The root function might not return. But if it does we simply
651 move along to thread_exit_wrapper. All other ways out for the
652 thread (cancellation, or calling pthread_exit) lead there
653 too. */
654 ret_val = root_fn(arg);
655 thread_exit_wrapper(ret_val);
656 /* NOTREACHED */
657}
658
659
sewardjf8f819e2002-04-17 23:21:37 +0000660/* ---------------------------------------------------
661 THREADs
662 ------------------------------------------------ */
663
sewardjff42d1d2002-05-22 13:17:31 +0000664__attribute__((weak))
665int pthread_yield ( void )
666{
667 int res;
668 ensure_valgrind("pthread_yield");
669 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
670 VG_USERREQ__PTHREAD_YIELD, 0, 0, 0, 0);
671 return 0;
672}
673
674
sewardj6072c362002-04-19 14:40:57 +0000675int pthread_equal(pthread_t thread1, pthread_t thread2)
676{
677 return thread1 == thread2 ? 1 : 0;
678}
679
680
sewardj20917d82002-05-28 01:36:45 +0000681/* Bundle up the args into a malloc'd block and create a new thread
682 consisting of thread_wrapper() applied to said malloc'd block. */
sewardje663cb92002-04-12 10:26:32 +0000683int
sewardj1462c8b2002-07-24 09:41:52 +0000684pthread_create (pthread_t *__restrict __thredd,
sewardje663cb92002-04-12 10:26:32 +0000685 __const pthread_attr_t *__restrict __attr,
686 void *(*__start_routine) (void *),
687 void *__restrict __arg)
688{
sewardj20917d82002-05-28 01:36:45 +0000689 int tid_child;
690 NewThreadInfo* info;
sewardje663cb92002-04-12 10:26:32 +0000691
sewardj20917d82002-05-28 01:36:45 +0000692 ensure_valgrind("pthread_create");
693
sewardj00a66b12002-10-12 16:42:35 +0000694 /* make sure the tsd keys, and hence locale info, are initialised
695 before we get into complications making new threads. */
696 init_libc_tsd_keys();
697
sewardj20917d82002-05-28 01:36:45 +0000698 /* Allocate space for the arg block. thread_wrapper will free
699 it. */
sewardj00a66b12002-10-12 16:42:35 +0000700 info = my_malloc(sizeof(NewThreadInfo));
sewardj2d94c112002-06-03 01:25:54 +0000701 my_assert(info != NULL);
sewardj20917d82002-05-28 01:36:45 +0000702
sewardj728a5272002-06-20 10:25:37 +0000703 if (__attr)
704 info->attr__detachstate = __attr->__detachstate;
705 else
706 info->attr__detachstate = PTHREAD_CREATE_JOINABLE;
707
sewardj20917d82002-05-28 01:36:45 +0000708 info->root_fn = __start_routine;
709 info->arg = __arg;
710 VALGRIND_MAGIC_SEQUENCE(tid_child, VG_INVALID_THREADID /* default */,
711 VG_USERREQ__APPLY_IN_NEW_THREAD,
712 &thread_wrapper, info, 0, 0);
sewardj2d94c112002-06-03 01:25:54 +0000713 my_assert(tid_child != VG_INVALID_THREADID);
sewardj20917d82002-05-28 01:36:45 +0000714
sewardj1462c8b2002-07-24 09:41:52 +0000715 if (__thredd)
716 *__thredd = tid_child;
sewardj20917d82002-05-28 01:36:45 +0000717 return 0; /* success */
718}
sewardje663cb92002-04-12 10:26:32 +0000719
720
721int
722pthread_join (pthread_t __th, void **__thread_return)
723{
724 int res;
725 ensure_valgrind("pthread_join");
726 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
727 VG_USERREQ__PTHREAD_JOIN,
728 __th, __thread_return, 0, 0);
729 return res;
730}
731
732
sewardj3b5d8862002-04-20 13:53:23 +0000733void pthread_exit(void *retval)
734{
sewardj3b5d8862002-04-20 13:53:23 +0000735 ensure_valgrind("pthread_exit");
sewardj20917d82002-05-28 01:36:45 +0000736 /* Simple! */
737 thread_exit_wrapper(retval);
sewardj3b5d8862002-04-20 13:53:23 +0000738}
739
sewardje663cb92002-04-12 10:26:32 +0000740
sewardj853f55d2002-04-26 00:27:53 +0000741int pthread_detach(pthread_t th)
742{
sewardj20917d82002-05-28 01:36:45 +0000743 int res;
744 ensure_valgrind("pthread_detach");
sewardj7989d0c2002-05-28 11:00:01 +0000745 /* First we enquire as to the current detach state. */
746 VALGRIND_MAGIC_SEQUENCE(res, (-2) /* default */,
sewardj20917d82002-05-28 01:36:45 +0000747 VG_USERREQ__SET_OR_GET_DETACH,
sewardj7989d0c2002-05-28 11:00:01 +0000748 2 /* get */, th, 0, 0);
sewardj4dced352002-06-04 22:54:20 +0000749 if (res == -1) {
750 /* not found */
751 pthread_error("pthread_detach: "
752 "invalid target thread");
sewardj7989d0c2002-05-28 11:00:01 +0000753 return ESRCH;
sewardj4dced352002-06-04 22:54:20 +0000754 }
755 if (res == 1) {
756 /* already detached */
757 pthread_error("pthread_detach: "
758 "target thread is already detached");
sewardj7989d0c2002-05-28 11:00:01 +0000759 return EINVAL;
sewardj4dced352002-06-04 22:54:20 +0000760 }
sewardj7989d0c2002-05-28 11:00:01 +0000761 if (res == 0) {
762 VALGRIND_MAGIC_SEQUENCE(res, (-2) /* default */,
763 VG_USERREQ__SET_OR_GET_DETACH,
764 1 /* set */, th, 0, 0);
sewardj2d94c112002-06-03 01:25:54 +0000765 my_assert(res == 0);
sewardj7989d0c2002-05-28 11:00:01 +0000766 return 0;
767 }
768 barf("pthread_detach");
sewardj853f55d2002-04-26 00:27:53 +0000769}
770
771
sewardjf8f819e2002-04-17 23:21:37 +0000772/* ---------------------------------------------------
sewardj8ad94e12002-05-29 00:10:20 +0000773 CLEANUP STACKS
774 ------------------------------------------------ */
775
776void _pthread_cleanup_push (struct _pthread_cleanup_buffer *__buffer,
777 void (*__routine) (void *),
778 void *__arg)
779{
780 int res;
781 CleanupEntry cu;
782 ensure_valgrind("_pthread_cleanup_push");
783 cu.fn = __routine;
784 cu.arg = __arg;
785 VALGRIND_MAGIC_SEQUENCE(res, (-1) /* default */,
786 VG_USERREQ__CLEANUP_PUSH,
787 &cu, 0, 0, 0);
sewardj2d94c112002-06-03 01:25:54 +0000788 my_assert(res == 0);
sewardj8ad94e12002-05-29 00:10:20 +0000789}
790
791
792void _pthread_cleanup_push_defer (struct _pthread_cleanup_buffer *__buffer,
793 void (*__routine) (void *),
794 void *__arg)
795{
796 /* As _pthread_cleanup_push, but first save the thread's original
797 cancellation type in __buffer and set it to Deferred. */
798 int orig_ctype;
799 ensure_valgrind("_pthread_cleanup_push_defer");
800 /* Set to Deferred, and put the old cancellation type in res. */
sewardj2d94c112002-06-03 01:25:54 +0000801 my_assert(-1 != PTHREAD_CANCEL_DEFERRED);
802 my_assert(-1 != PTHREAD_CANCEL_ASYNCHRONOUS);
803 my_assert(sizeof(struct _pthread_cleanup_buffer) >= sizeof(int));
sewardj8ad94e12002-05-29 00:10:20 +0000804 VALGRIND_MAGIC_SEQUENCE(orig_ctype, (-1) /* default */,
805 VG_USERREQ__SET_CANCELTYPE,
806 PTHREAD_CANCEL_DEFERRED, 0, 0, 0);
sewardj2d94c112002-06-03 01:25:54 +0000807 my_assert(orig_ctype != -1);
sewardj8ad94e12002-05-29 00:10:20 +0000808 *((int*)(__buffer)) = orig_ctype;
809 /* Now push the cleanup. */
810 _pthread_cleanup_push(NULL, __routine, __arg);
811}
812
813
814void _pthread_cleanup_pop (struct _pthread_cleanup_buffer *__buffer,
815 int __execute)
816{
817 int res;
818 CleanupEntry cu;
819 ensure_valgrind("_pthread_cleanup_push");
820 cu.fn = cu.arg = NULL; /* paranoia */
821 VALGRIND_MAGIC_SEQUENCE(res, (-1) /* default */,
822 VG_USERREQ__CLEANUP_POP,
823 &cu, 0, 0, 0);
824 if (res == 0) {
825 /* pop succeeded */
826 if (__execute) {
827 cu.fn ( cu.arg );
828 }
829 return;
830 }
831 if (res == -1) {
832 /* stack underflow */
833 return;
834 }
835 barf("_pthread_cleanup_pop");
836}
837
838
839void _pthread_cleanup_pop_restore (struct _pthread_cleanup_buffer *__buffer,
840 int __execute)
841{
842 int orig_ctype, fake_ctype;
843 /* As _pthread_cleanup_pop, but after popping/running the handler,
844 restore the thread's original cancellation type from the first
845 word of __buffer. */
846 _pthread_cleanup_pop(NULL, __execute);
847 orig_ctype = *((int*)(__buffer));
sewardj2d94c112002-06-03 01:25:54 +0000848 my_assert(orig_ctype == PTHREAD_CANCEL_DEFERRED
sewardj8ad94e12002-05-29 00:10:20 +0000849 || orig_ctype == PTHREAD_CANCEL_ASYNCHRONOUS);
sewardj2d94c112002-06-03 01:25:54 +0000850 my_assert(-1 != PTHREAD_CANCEL_DEFERRED);
851 my_assert(-1 != PTHREAD_CANCEL_ASYNCHRONOUS);
852 my_assert(sizeof(struct _pthread_cleanup_buffer) >= sizeof(int));
sewardj8ad94e12002-05-29 00:10:20 +0000853 VALGRIND_MAGIC_SEQUENCE(fake_ctype, (-1) /* default */,
854 VG_USERREQ__SET_CANCELTYPE,
855 orig_ctype, 0, 0, 0);
sewardj2d94c112002-06-03 01:25:54 +0000856 my_assert(fake_ctype == PTHREAD_CANCEL_DEFERRED);
sewardj8ad94e12002-05-29 00:10:20 +0000857}
858
859
860/* ---------------------------------------------------
sewardjf8f819e2002-04-17 23:21:37 +0000861 MUTEX ATTRIBUTES
862 ------------------------------------------------ */
863
sewardj5905fae2002-04-26 13:25:00 +0000864int __pthread_mutexattr_init(pthread_mutexattr_t *attr)
sewardje663cb92002-04-12 10:26:32 +0000865{
sewardjf8f819e2002-04-17 23:21:37 +0000866 attr->__mutexkind = PTHREAD_MUTEX_ERRORCHECK_NP;
sewardj8937c812002-04-12 20:12:20 +0000867 return 0;
sewardje663cb92002-04-12 10:26:32 +0000868}
869
sewardj5905fae2002-04-26 13:25:00 +0000870int __pthread_mutexattr_settype(pthread_mutexattr_t *attr, int type)
sewardjf8f819e2002-04-17 23:21:37 +0000871{
872 switch (type) {
sewardj3b13f0e2002-04-25 20:17:29 +0000873# ifndef GLIBC_2_1
sewardjf8f819e2002-04-17 23:21:37 +0000874 case PTHREAD_MUTEX_TIMED_NP:
sewardj2a1dcce2002-04-22 12:45:25 +0000875 case PTHREAD_MUTEX_ADAPTIVE_NP:
sewardj3b13f0e2002-04-25 20:17:29 +0000876# endif
sewardja1679dd2002-05-10 22:31:40 +0000877# ifdef GLIBC_2_1
sewardj68b2dd92002-05-10 21:03:56 +0000878 case PTHREAD_MUTEX_FAST_NP:
sewardja1679dd2002-05-10 22:31:40 +0000879# endif
sewardjf8f819e2002-04-17 23:21:37 +0000880 case PTHREAD_MUTEX_RECURSIVE_NP:
881 case PTHREAD_MUTEX_ERRORCHECK_NP:
sewardjf8f819e2002-04-17 23:21:37 +0000882 attr->__mutexkind = type;
883 return 0;
884 default:
sewardj4dced352002-06-04 22:54:20 +0000885 pthread_error("pthread_mutexattr_settype: "
886 "invalid type");
sewardjf8f819e2002-04-17 23:21:37 +0000887 return EINVAL;
888 }
889}
890
sewardj5905fae2002-04-26 13:25:00 +0000891int __pthread_mutexattr_destroy(pthread_mutexattr_t *attr)
sewardjf8f819e2002-04-17 23:21:37 +0000892{
893 return 0;
894}
895
896
897/* ---------------------------------------------------
898 MUTEXes
899 ------------------------------------------------ */
900
sewardj5905fae2002-04-26 13:25:00 +0000901int __pthread_mutex_init(pthread_mutex_t *mutex,
902 const pthread_mutexattr_t *mutexattr)
sewardje663cb92002-04-12 10:26:32 +0000903{
sewardj604ec3c2002-04-18 22:38:41 +0000904 mutex->__m_count = 0;
905 mutex->__m_owner = (_pthread_descr)VG_INVALID_THREADID;
906 mutex->__m_kind = PTHREAD_MUTEX_ERRORCHECK_NP;
907 if (mutexattr)
908 mutex->__m_kind = mutexattr->__mutexkind;
909 return 0;
sewardje663cb92002-04-12 10:26:32 +0000910}
911
sewardj439d45e2002-05-03 20:43:10 +0000912
sewardj5905fae2002-04-26 13:25:00 +0000913int __pthread_mutex_lock(pthread_mutex_t *mutex)
sewardje663cb92002-04-12 10:26:32 +0000914{
915 int res;
sewardjd8acdf22002-11-13 21:57:52 +0000916
sewardj439d45e2002-05-03 20:43:10 +0000917 if (RUNNING_ON_VALGRIND) {
sewardje663cb92002-04-12 10:26:32 +0000918 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
919 VG_USERREQ__PTHREAD_MUTEX_LOCK,
920 mutex, 0, 0, 0);
921 return res;
sewardj439d45e2002-05-03 20:43:10 +0000922 } else {
sewardjd8acdf22002-11-13 21:57:52 +0000923 /* Play at locking */
924 if (0)
925 kludged("prehistoric lock");
926 mutex->__m_owner = (_pthread_descr)1;
927 mutex->__m_count = 1;
928 mutex->__m_kind |= VG_PTHREAD_PREHISTORY;
sewardj439d45e2002-05-03 20:43:10 +0000929 return 0; /* success */
sewardje663cb92002-04-12 10:26:32 +0000930 }
931}
932
sewardj439d45e2002-05-03 20:43:10 +0000933
sewardj5905fae2002-04-26 13:25:00 +0000934int __pthread_mutex_trylock(pthread_mutex_t *mutex)
sewardj30671ff2002-04-21 00:13:57 +0000935{
936 int res;
sewardjd8acdf22002-11-13 21:57:52 +0000937
sewardj439d45e2002-05-03 20:43:10 +0000938 if (RUNNING_ON_VALGRIND) {
sewardj30671ff2002-04-21 00:13:57 +0000939 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
940 VG_USERREQ__PTHREAD_MUTEX_TRYLOCK,
941 mutex, 0, 0, 0);
942 return res;
sewardj439d45e2002-05-03 20:43:10 +0000943 } else {
sewardjd8acdf22002-11-13 21:57:52 +0000944 /* Play at locking */
945 if (0)
946 kludged("prehistoric trylock");
947 mutex->__m_owner = (_pthread_descr)1;
948 mutex->__m_count = 1;
949 mutex->__m_kind |= VG_PTHREAD_PREHISTORY;
950 return 0; /* success */
sewardj30671ff2002-04-21 00:13:57 +0000951 }
952}
953
sewardj439d45e2002-05-03 20:43:10 +0000954
sewardj5905fae2002-04-26 13:25:00 +0000955int __pthread_mutex_unlock(pthread_mutex_t *mutex)
sewardje663cb92002-04-12 10:26:32 +0000956{
957 int res;
sewardjd8acdf22002-11-13 21:57:52 +0000958
sewardj439d45e2002-05-03 20:43:10 +0000959 if (RUNNING_ON_VALGRIND) {
sewardje663cb92002-04-12 10:26:32 +0000960 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
961 VG_USERREQ__PTHREAD_MUTEX_UNLOCK,
962 mutex, 0, 0, 0);
963 return res;
sewardj439d45e2002-05-03 20:43:10 +0000964 } else {
sewardjd8acdf22002-11-13 21:57:52 +0000965 /* Play at locking */
966 if (0)
967 kludged("prehistoric unlock");
968 mutex->__m_owner = 0;
969 mutex->__m_count = 0;
970 mutex->__m_kind &= ~VG_PTHREAD_PREHISTORY;
971 return 0; /* success */
sewardje663cb92002-04-12 10:26:32 +0000972 }
973}
974
sewardj439d45e2002-05-03 20:43:10 +0000975
sewardj5905fae2002-04-26 13:25:00 +0000976int __pthread_mutex_destroy(pthread_mutex_t *mutex)
sewardje663cb92002-04-12 10:26:32 +0000977{
sewardj604ec3c2002-04-18 22:38:41 +0000978 /* Valgrind doesn't hold any resources on behalf of the mutex, so no
979 need to involve it. */
sewardj4dced352002-06-04 22:54:20 +0000980 if (mutex->__m_count > 0) {
sewardjd8acdf22002-11-13 21:57:52 +0000981 /* Oh, the horror. glibc's internal use of pthreads "knows"
982 that destroying a lock does an implicit unlock. Make it
983 explicit. */
984 __pthread_mutex_unlock(mutex);
985 pthread_error("pthread_mutex_destroy: "
986 "mutex is still in use");
987 return EBUSY;
sewardj4dced352002-06-04 22:54:20 +0000988 }
989 mutex->__m_count = 0;
990 mutex->__m_owner = (_pthread_descr)VG_INVALID_THREADID;
991 mutex->__m_kind = PTHREAD_MUTEX_ERRORCHECK_NP;
992 return 0;
sewardje663cb92002-04-12 10:26:32 +0000993}
994
995
sewardjf8f819e2002-04-17 23:21:37 +0000996/* ---------------------------------------------------
sewardj6072c362002-04-19 14:40:57 +0000997 CONDITION VARIABLES
998 ------------------------------------------------ */
999
1000/* LinuxThreads supports no attributes for conditions. Hence ... */
1001
1002int pthread_condattr_init(pthread_condattr_t *attr)
1003{
1004 return 0;
1005}
1006
sewardj0738a592002-04-20 13:59:33 +00001007int pthread_condattr_destroy(pthread_condattr_t *attr)
1008{
1009 return 0;
1010}
sewardj6072c362002-04-19 14:40:57 +00001011
1012int pthread_cond_init( pthread_cond_t *cond,
1013 const pthread_condattr_t *cond_attr)
1014{
1015 cond->__c_waiting = (_pthread_descr)VG_INVALID_THREADID;
1016 return 0;
1017}
1018
sewardjf854f472002-04-21 12:19:41 +00001019int pthread_cond_destroy(pthread_cond_t *cond)
1020{
1021 /* should check that no threads are waiting on this CV */
sewardj436e0582002-04-26 14:31:40 +00001022 static int moans = N_MOANS;
1023 if (moans-- > 0)
1024 kludged("pthread_cond_destroy");
sewardjf854f472002-04-21 12:19:41 +00001025 return 0;
1026}
sewardj6072c362002-04-19 14:40:57 +00001027
1028/* ---------------------------------------------------
1029 SCHEDULING
1030 ------------------------------------------------ */
1031
1032/* This is completely bogus. */
1033int pthread_getschedparam(pthread_t target_thread,
1034 int *policy,
1035 struct sched_param *param)
1036{
sewardj436e0582002-04-26 14:31:40 +00001037 static int moans = N_MOANS;
1038 if (moans-- > 0)
1039 kludged("pthread_getschedparam");
sewardj6072c362002-04-19 14:40:57 +00001040 if (policy) *policy = SCHED_OTHER;
sewardj3e909ce2002-06-03 13:27:15 +00001041# ifdef HAVE_SCHED_PRIORITY
sewardj2a1dcce2002-04-22 12:45:25 +00001042 if (param) param->sched_priority = 0; /* who knows */
1043# else
sewardj6072c362002-04-19 14:40:57 +00001044 if (param) param->__sched_priority = 0; /* who knows */
sewardj2a1dcce2002-04-22 12:45:25 +00001045# endif
sewardj6072c362002-04-19 14:40:57 +00001046 return 0;
1047}
1048
1049int pthread_setschedparam(pthread_t target_thread,
1050 int policy,
1051 const struct sched_param *param)
1052{
sewardj436e0582002-04-26 14:31:40 +00001053 static int moans = N_MOANS;
1054 if (moans-- > 0)
1055 ignored("pthread_setschedparam");
sewardj6072c362002-04-19 14:40:57 +00001056 return 0;
1057}
1058
sewardj3b5d8862002-04-20 13:53:23 +00001059int pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex)
1060{
1061 int res;
1062 ensure_valgrind("pthread_cond_wait");
1063 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
1064 VG_USERREQ__PTHREAD_COND_WAIT,
1065 cond, mutex, 0, 0);
1066 return res;
1067}
1068
sewardj5f07b662002-04-23 16:52:51 +00001069int pthread_cond_timedwait ( pthread_cond_t *cond,
1070 pthread_mutex_t *mutex,
1071 const struct timespec *abstime )
1072{
1073 int res;
1074 unsigned int ms_now, ms_end;
1075 struct timeval timeval_now;
1076 unsigned long long int ull_ms_now_after_1970;
1077 unsigned long long int ull_ms_end_after_1970;
1078
1079 ensure_valgrind("pthread_cond_timedwait");
1080 VALGRIND_MAGIC_SEQUENCE(ms_now, 0xFFFFFFFF /* default */,
1081 VG_USERREQ__READ_MILLISECOND_TIMER,
1082 0, 0, 0, 0);
sewardj2d94c112002-06-03 01:25:54 +00001083 my_assert(ms_now != 0xFFFFFFFF);
sewardj5f07b662002-04-23 16:52:51 +00001084 res = gettimeofday(&timeval_now, NULL);
sewardj2d94c112002-06-03 01:25:54 +00001085 my_assert(res == 0);
sewardj5f07b662002-04-23 16:52:51 +00001086
1087 ull_ms_now_after_1970
1088 = 1000ULL * ((unsigned long long int)(timeval_now.tv_sec))
1089 + ((unsigned long long int)(timeval_now.tv_usec / 1000000));
1090 ull_ms_end_after_1970
1091 = 1000ULL * ((unsigned long long int)(abstime->tv_sec))
1092 + ((unsigned long long int)(abstime->tv_nsec / 1000000));
sewardjd8e919e2002-05-29 20:13:53 +00001093 if (ull_ms_end_after_1970 < ull_ms_now_after_1970)
1094 ull_ms_end_after_1970 = ull_ms_now_after_1970;
sewardj5f07b662002-04-23 16:52:51 +00001095 ms_end
1096 = ms_now + (unsigned int)(ull_ms_end_after_1970 - ull_ms_now_after_1970);
1097 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
1098 VG_USERREQ__PTHREAD_COND_TIMEDWAIT,
1099 cond, mutex, ms_end, 0);
1100 return res;
1101}
1102
1103
sewardj3b5d8862002-04-20 13:53:23 +00001104int pthread_cond_signal(pthread_cond_t *cond)
1105{
1106 int res;
1107 ensure_valgrind("pthread_cond_signal");
1108 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
1109 VG_USERREQ__PTHREAD_COND_SIGNAL,
1110 cond, 0, 0, 0);
1111 return res;
1112}
1113
1114int pthread_cond_broadcast(pthread_cond_t *cond)
1115{
1116 int res;
1117 ensure_valgrind("pthread_cond_broadcast");
1118 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
1119 VG_USERREQ__PTHREAD_COND_BROADCAST,
1120 cond, 0, 0, 0);
1121 return res;
1122}
1123
sewardj6072c362002-04-19 14:40:57 +00001124
1125/* ---------------------------------------------------
sewardjf8f819e2002-04-17 23:21:37 +00001126 CANCELLATION
1127 ------------------------------------------------ */
1128
sewardj853f55d2002-04-26 00:27:53 +00001129int pthread_setcancelstate(int state, int *oldstate)
1130{
sewardj20917d82002-05-28 01:36:45 +00001131 int res;
1132 ensure_valgrind("pthread_setcancelstate");
1133 if (state != PTHREAD_CANCEL_ENABLE
sewardj4dced352002-06-04 22:54:20 +00001134 && state != PTHREAD_CANCEL_DISABLE) {
1135 pthread_error("pthread_setcancelstate: "
1136 "invalid state");
sewardj20917d82002-05-28 01:36:45 +00001137 return EINVAL;
sewardj4dced352002-06-04 22:54:20 +00001138 }
sewardj2d94c112002-06-03 01:25:54 +00001139 my_assert(-1 != PTHREAD_CANCEL_ENABLE);
1140 my_assert(-1 != PTHREAD_CANCEL_DISABLE);
sewardj20917d82002-05-28 01:36:45 +00001141 VALGRIND_MAGIC_SEQUENCE(res, (-1) /* default */,
1142 VG_USERREQ__SET_CANCELSTATE,
1143 state, 0, 0, 0);
sewardj2d94c112002-06-03 01:25:54 +00001144 my_assert(res != -1);
sewardj20917d82002-05-28 01:36:45 +00001145 if (oldstate)
1146 *oldstate = res;
sewardj853f55d2002-04-26 00:27:53 +00001147 return 0;
1148}
1149
sewardje663cb92002-04-12 10:26:32 +00001150int pthread_setcanceltype(int type, int *oldtype)
1151{
sewardj20917d82002-05-28 01:36:45 +00001152 int res;
1153 ensure_valgrind("pthread_setcanceltype");
1154 if (type != PTHREAD_CANCEL_DEFERRED
sewardj4dced352002-06-04 22:54:20 +00001155 && type != PTHREAD_CANCEL_ASYNCHRONOUS) {
1156 pthread_error("pthread_setcanceltype: "
1157 "invalid type");
sewardj20917d82002-05-28 01:36:45 +00001158 return EINVAL;
sewardj4dced352002-06-04 22:54:20 +00001159 }
sewardj2d94c112002-06-03 01:25:54 +00001160 my_assert(-1 != PTHREAD_CANCEL_DEFERRED);
1161 my_assert(-1 != PTHREAD_CANCEL_ASYNCHRONOUS);
sewardj20917d82002-05-28 01:36:45 +00001162 VALGRIND_MAGIC_SEQUENCE(res, (-1) /* default */,
1163 VG_USERREQ__SET_CANCELTYPE,
1164 type, 0, 0, 0);
sewardj2d94c112002-06-03 01:25:54 +00001165 my_assert(res != -1);
sewardj20917d82002-05-28 01:36:45 +00001166 if (oldtype)
1167 *oldtype = res;
sewardje663cb92002-04-12 10:26:32 +00001168 return 0;
1169}
1170
sewardje663cb92002-04-12 10:26:32 +00001171int pthread_cancel(pthread_t thread)
1172{
1173 int res;
1174 ensure_valgrind("pthread_cancel");
sewardj20917d82002-05-28 01:36:45 +00001175 VALGRIND_MAGIC_SEQUENCE(res, (-1) /* default */,
1176 VG_USERREQ__SET_CANCELPEND,
1177 thread, &thread_exit_wrapper, 0, 0);
sewardj2d94c112002-06-03 01:25:54 +00001178 my_assert(res != -1);
sewardje663cb92002-04-12 10:26:32 +00001179 return res;
1180}
1181
sewardjd140e442002-05-29 01:21:19 +00001182static __inline__
1183void __my_pthread_testcancel(void)
sewardj853f55d2002-04-26 00:27:53 +00001184{
sewardj20917d82002-05-28 01:36:45 +00001185 int res;
njn25e49d8e72002-09-23 09:36:25 +00001186 ensure_valgrind("__my_pthread_testcancel");
sewardj20917d82002-05-28 01:36:45 +00001187 VALGRIND_MAGIC_SEQUENCE(res, (-1) /* default */,
1188 VG_USERREQ__TESTCANCEL,
1189 0, 0, 0, 0);
sewardj2d94c112002-06-03 01:25:54 +00001190 my_assert(res == 0);
sewardj853f55d2002-04-26 00:27:53 +00001191}
1192
sewardjd140e442002-05-29 01:21:19 +00001193void pthread_testcancel ( void )
1194{
1195 __my_pthread_testcancel();
1196}
1197
sewardj20917d82002-05-28 01:36:45 +00001198
sewardjef037c72002-05-30 00:40:03 +00001199/* Not really sure what this is for. I suspect for doing the POSIX
1200 requirements for fork() and exec(). We do this internally anyway
1201 whenever those syscalls are observed, so this could be superfluous,
1202 but hey ...
1203*/
sewardj853f55d2002-04-26 00:27:53 +00001204void __pthread_kill_other_threads_np ( void )
1205{
sewardjef037c72002-05-30 00:40:03 +00001206 int res;
1207 ensure_valgrind("__pthread_kill_other_threads_np");
1208 VALGRIND_MAGIC_SEQUENCE(res, (-1) /* default */,
1209 VG_USERREQ__NUKE_OTHER_THREADS,
1210 0, 0, 0, 0);
sewardj2d94c112002-06-03 01:25:54 +00001211 my_assert(res == 0);
sewardj853f55d2002-04-26 00:27:53 +00001212}
1213
sewardje663cb92002-04-12 10:26:32 +00001214
sewardjf8f819e2002-04-17 23:21:37 +00001215/* ---------------------------------------------------
sewardjb48e5002002-05-13 00:16:03 +00001216 SIGNALS
1217 ------------------------------------------------ */
1218
1219#include <signal.h>
1220
1221int pthread_sigmask(int how, const sigset_t *newmask,
1222 sigset_t *oldmask)
1223{
1224 int res;
1225
1226 /* A bit subtle, because the scheduler expects newmask and oldmask
1227 to be vki_sigset_t* rather than sigset_t*, and the two are
1228 different. Fortunately the first 64 bits of a sigset_t are
1229 exactly a vki_sigset_t, so we just pass the pointers through
1230 unmodified. Haaaack!
1231
1232 Also mash the how value so that the SIG_ constants from glibc
sewardj018f7622002-05-15 21:13:39 +00001233 constants to VKI_ constants, so that the former do not have to
1234 be included into vg_scheduler.c. */
sewardjb48e5002002-05-13 00:16:03 +00001235
1236 ensure_valgrind("pthread_sigmask");
1237
1238 switch (how) {
sewardj018f7622002-05-15 21:13:39 +00001239 case SIG_SETMASK: how = VKI_SIG_SETMASK; break;
1240 case SIG_BLOCK: how = VKI_SIG_BLOCK; break;
1241 case SIG_UNBLOCK: how = VKI_SIG_UNBLOCK; break;
sewardj4dced352002-06-04 22:54:20 +00001242 default: pthread_error("pthread_sigmask: invalid how");
1243 return EINVAL;
sewardjb48e5002002-05-13 00:16:03 +00001244 }
1245
1246 /* Crude check */
1247 if (newmask == NULL)
1248 return EFAULT;
1249
1250 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
1251 VG_USERREQ__PTHREAD_SIGMASK,
1252 how, newmask, oldmask, 0);
1253
1254 /* The scheduler tells us of any memory violations. */
1255 return res == 0 ? 0 : EFAULT;
1256}
1257
1258
1259int sigwait ( const sigset_t* set, int* sig )
1260{
1261 int res;
1262 ensure_valgrind("sigwait");
1263 /* As with pthread_sigmask we deliberately confuse sigset_t with
1264 vki_ksigset_t. */
1265 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
1266 VG_USERREQ__SIGWAIT,
1267 set, sig, 0, 0);
1268 return res;
1269}
1270
1271
sewardj018f7622002-05-15 21:13:39 +00001272int pthread_kill(pthread_t thread, int signo)
1273{
1274 int res;
1275 ensure_valgrind("pthread_kill");
1276 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
1277 VG_USERREQ__PTHREAD_KILL,
1278 thread, signo, 0, 0);
1279 return res;
1280}
1281
1282
sewardj3665ded2002-05-16 16:57:25 +00001283/* Copied verbatim from Linuxthreads */
1284/* Redefine raise() to send signal to calling thread only,
1285 as per POSIX 1003.1c */
1286int raise (int sig)
1287{
1288 int retcode = pthread_kill(pthread_self(), sig);
sewardj4dced352002-06-04 22:54:20 +00001289 if (retcode == 0) {
sewardj3665ded2002-05-16 16:57:25 +00001290 return 0;
sewardj4dced352002-06-04 22:54:20 +00001291 } else {
sewardj3665ded2002-05-16 16:57:25 +00001292 errno = retcode;
1293 return -1;
1294 }
1295}
1296
1297
sewardj9a2224b2002-06-19 10:17:40 +00001298int pause ( void )
1299{
1300 unsigned int n_orig, n_now;
1301 struct vki_timespec nanosleep_interval;
1302 ensure_valgrind("pause");
1303
1304 /* This is surely a cancellation point. */
1305 __my_pthread_testcancel();
1306
1307 VALGRIND_MAGIC_SEQUENCE(n_orig, 0xFFFFFFFF /* default */,
1308 VG_USERREQ__GET_N_SIGS_RETURNED,
1309 0, 0, 0, 0);
1310 my_assert(n_orig != 0xFFFFFFFF);
1311
1312 while (1) {
1313 VALGRIND_MAGIC_SEQUENCE(n_now, 0xFFFFFFFF /* default */,
1314 VG_USERREQ__GET_N_SIGS_RETURNED,
1315 0, 0, 0, 0);
1316 my_assert(n_now != 0xFFFFFFFF);
1317 my_assert(n_now >= n_orig);
1318 if (n_now != n_orig) break;
1319
1320 nanosleep_interval.tv_sec = 0;
njn25e49d8e72002-09-23 09:36:25 +00001321 nanosleep_interval.tv_nsec = 12 * 1000 * 1000; /* 12 milliseconds */
sewardj9a2224b2002-06-19 10:17:40 +00001322 /* It's critical here that valgrind's nanosleep implementation
1323 is nonblocking. */
1324 (void)my_do_syscall2(__NR_nanosleep,
1325 (int)(&nanosleep_interval), (int)NULL);
1326 }
1327
1328 * (__errno_location()) = EINTR;
1329 return -1;
1330}
1331
1332
sewardjb48e5002002-05-13 00:16:03 +00001333/* ---------------------------------------------------
sewardjf8f819e2002-04-17 23:21:37 +00001334 THREAD-SPECIFICs
1335 ------------------------------------------------ */
sewardj5e5fa512002-04-14 13:13:05 +00001336
sewardj00a66b12002-10-12 16:42:35 +00001337static
1338int key_is_valid (pthread_key_t key)
1339{
1340 int res;
1341 VALGRIND_MAGIC_SEQUENCE(res, 2 /* default */,
1342 VG_USERREQ__PTHREAD_KEY_VALIDATE,
1343 key, 0, 0, 0);
1344 my_assert(res != 2);
1345 return res;
1346}
1347
1348
1349/* Returns NULL if thread is invalid. Otherwise, if the thread
1350 already has a specifics area, return that. Otherwise allocate it
1351 one. */
1352static
1353void** get_or_allocate_specifics_ptr ( pthread_t thread )
1354{
1355 int res, i;
1356 void** specifics_ptr;
1357 ensure_valgrind("get_or_allocate_specifics_ptr");
1358
1359 /* Returns zero if the thread has no specific_ptr. One if thread
1360 is invalid. Otherwise, the specific_ptr value. This is
1361 allocated with my_malloc and so is aligned and cannot be
1362 confused with 1 or 3. */
1363 VALGRIND_MAGIC_SEQUENCE(specifics_ptr, 3 /* default */,
1364 VG_USERREQ__PTHREAD_GETSPECIFIC_PTR,
1365 thread, 0, 0, 0);
1366 my_assert(specifics_ptr != (void**)3);
1367
1368 if (specifics_ptr == (void**)1)
1369 return NULL; /* invalid thread */
1370
1371 if (specifics_ptr != NULL)
1372 return specifics_ptr; /* already has a specifics ptr. */
1373
1374 /* None yet ... allocate a new one. Should never fail. */
1375 specifics_ptr = my_malloc( VG_N_THREAD_KEYS * sizeof(void*) );
1376 my_assert(specifics_ptr != NULL);
1377
1378 VALGRIND_MAGIC_SEQUENCE(res, -1 /* default */,
1379 VG_USERREQ__PTHREAD_SETSPECIFIC_PTR,
1380 specifics_ptr, 0, 0, 0);
1381 my_assert(res == 0);
1382
1383 /* POSIX sez: "Upon thread creation, the value NULL shall be
1384 associated with all defined keys in the new thread." This
1385 allocation is in effect a delayed allocation of the specific
1386 data for a thread, at its first-use. Hence we initialise it
1387 here. */
1388 for (i = 0; i < VG_N_THREAD_KEYS; i++) {
1389 specifics_ptr[i] = NULL;
1390 }
1391
1392 return specifics_ptr;
1393}
1394
1395
sewardj5905fae2002-04-26 13:25:00 +00001396int __pthread_key_create(pthread_key_t *key,
1397 void (*destr_function) (void *))
sewardj5e5fa512002-04-14 13:13:05 +00001398{
sewardj00a66b12002-10-12 16:42:35 +00001399 void** specifics_ptr;
1400 int res, i;
sewardj5f07b662002-04-23 16:52:51 +00001401 ensure_valgrind("pthread_key_create");
sewardj00a66b12002-10-12 16:42:35 +00001402
1403 /* This writes *key if successful. It should never fail. */
1404 VALGRIND_MAGIC_SEQUENCE(res, 1 /* default */,
sewardj5f07b662002-04-23 16:52:51 +00001405 VG_USERREQ__PTHREAD_KEY_CREATE,
1406 key, destr_function, 0, 0);
sewardj00a66b12002-10-12 16:42:35 +00001407 my_assert(res == 0);
1408
1409 /* POSIX sez: "Upon key creation, the value NULL shall be
1410 associated with the new key in all active threads." */
1411 for (i = 0; i < VG_N_THREADS; i++) {
1412 specifics_ptr = get_or_allocate_specifics_ptr(i);
1413 /* we get NULL if i is an invalid thread. */
1414 if (specifics_ptr != NULL)
1415 specifics_ptr[*key] = NULL;
1416 }
1417
sewardj5f07b662002-04-23 16:52:51 +00001418 return res;
sewardj5e5fa512002-04-14 13:13:05 +00001419}
1420
1421int pthread_key_delete(pthread_key_t key)
1422{
sewardj00a66b12002-10-12 16:42:35 +00001423 int res;
1424 ensure_valgrind("pthread_key_create");
1425 if (!key_is_valid(key))
1426 return EINVAL;
1427 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
1428 VG_USERREQ__PTHREAD_KEY_DELETE,
1429 key, 0, 0, 0);
1430 my_assert(res == 0);
sewardj5e5fa512002-04-14 13:13:05 +00001431 return 0;
1432}
1433
sewardj5905fae2002-04-26 13:25:00 +00001434int __pthread_setspecific(pthread_key_t key, const void *pointer)
sewardj5e5fa512002-04-14 13:13:05 +00001435{
sewardj00a66b12002-10-12 16:42:35 +00001436 void** specifics_ptr;
sewardj5f07b662002-04-23 16:52:51 +00001437 ensure_valgrind("pthread_setspecific");
sewardj00a66b12002-10-12 16:42:35 +00001438
1439 if (!key_is_valid(key))
1440 return EINVAL;
1441
1442 specifics_ptr = get_or_allocate_specifics_ptr(pthread_self());
1443 specifics_ptr[key] = (void*)pointer;
1444 return 0;
sewardj5e5fa512002-04-14 13:13:05 +00001445}
1446
sewardj5905fae2002-04-26 13:25:00 +00001447void * __pthread_getspecific(pthread_key_t key)
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_getspecific");
sewardj00a66b12002-10-12 16:42:35 +00001451
1452 if (!key_is_valid(key))
1453 return NULL;
1454
1455 specifics_ptr = get_or_allocate_specifics_ptr(pthread_self());
1456 return specifics_ptr[key];
1457}
1458
1459
sewardj9aa918d2002-10-20 16:25:55 +00001460#ifdef GLIBC_2_3
sewardj00a66b12002-10-12 16:42:35 +00001461static
1462void ** __pthread_getspecific_addr(pthread_key_t key)
1463{
1464 void** specifics_ptr;
1465 ensure_valgrind("pthread_getspecific_addr");
1466
1467 if (!key_is_valid(key))
1468 return NULL;
1469
1470 specifics_ptr = get_or_allocate_specifics_ptr(pthread_self());
1471 return &(specifics_ptr[key]);
sewardj5e5fa512002-04-14 13:13:05 +00001472}
sewardj9aa918d2002-10-20 16:25:55 +00001473#endif
sewardjf8f819e2002-04-17 23:21:37 +00001474
1475/* ---------------------------------------------------
sewardj89d3d852002-04-24 19:21:39 +00001476 ONCEry
1477 ------------------------------------------------ */
1478
1479static pthread_mutex_t once_masterlock = PTHREAD_MUTEX_INITIALIZER;
1480
1481
sewardj5905fae2002-04-26 13:25:00 +00001482int __pthread_once ( pthread_once_t *once_control,
1483 void (*init_routine) (void) )
sewardj89d3d852002-04-24 19:21:39 +00001484{
1485 int res;
1486 ensure_valgrind("pthread_once");
1487
sewardj68b2dd92002-05-10 21:03:56 +00001488 res = __pthread_mutex_lock(&once_masterlock);
sewardj89d3d852002-04-24 19:21:39 +00001489
sewardj68b2dd92002-05-10 21:03:56 +00001490 if (res != 0) {
sewardj89d3d852002-04-24 19:21:39 +00001491 barf("pthread_once: Looks like your program's "
1492 "init routine calls back to pthread_once() ?!");
sewardj68b2dd92002-05-10 21:03:56 +00001493 }
sewardj89d3d852002-04-24 19:21:39 +00001494
1495 if (*once_control == 0) {
1496 *once_control = 1;
1497 init_routine();
1498 }
1499
sewardj68b2dd92002-05-10 21:03:56 +00001500 __pthread_mutex_unlock(&once_masterlock);
sewardj89d3d852002-04-24 19:21:39 +00001501
1502 return 0;
1503}
1504
1505
1506/* ---------------------------------------------------
sewardj853f55d2002-04-26 00:27:53 +00001507 MISC
1508 ------------------------------------------------ */
1509
sewardj2cb00342002-06-28 01:46:26 +00001510static pthread_mutex_t pthread_atfork_lock
1511 = PTHREAD_MUTEX_INITIALIZER;
1512
sewardj5905fae2002-04-26 13:25:00 +00001513int __pthread_atfork ( void (*prepare)(void),
1514 void (*parent)(void),
1515 void (*child)(void) )
sewardj853f55d2002-04-26 00:27:53 +00001516{
sewardj2cb00342002-06-28 01:46:26 +00001517 int n, res;
1518 ForkHandlerEntry entry;
1519
1520 ensure_valgrind("pthread_atfork");
1521 __pthread_mutex_lock(&pthread_atfork_lock);
1522
1523 /* Fetch old counter */
1524 VALGRIND_MAGIC_SEQUENCE(n, -2 /* default */,
1525 VG_USERREQ__GET_FHSTACK_USED,
1526 0, 0, 0, 0);
1527 my_assert(n >= 0 && n < VG_N_FORKHANDLERSTACK);
1528 if (n == VG_N_FORKHANDLERSTACK-1)
1529 barf("pthread_atfork: VG_N_FORKHANDLERSTACK is too low; "
1530 "increase and recompile");
1531
1532 /* Add entry */
1533 entry.prepare = *prepare;
1534 entry.parent = *parent;
1535 entry.child = *child;
1536 VALGRIND_MAGIC_SEQUENCE(res, -2 /* default */,
1537 VG_USERREQ__SET_FHSTACK_ENTRY,
1538 n, &entry, 0, 0);
1539 my_assert(res == 0);
1540
1541 /* Bump counter */
1542 VALGRIND_MAGIC_SEQUENCE(res, -2 /* default */,
1543 VG_USERREQ__SET_FHSTACK_USED,
1544 n+1, 0, 0, 0);
1545 my_assert(res == 0);
1546
1547 __pthread_mutex_unlock(&pthread_atfork_lock);
1548 return 0;
sewardj853f55d2002-04-26 00:27:53 +00001549}
1550
1551
sewardjbb990782002-05-08 02:01:14 +00001552__attribute__((weak))
1553void __pthread_initialize ( void )
1554{
sewardjbea1caa2002-05-10 23:20:58 +00001555 ensure_valgrind("__pthread_initialize");
sewardjbb990782002-05-08 02:01:14 +00001556}
1557
1558
sewardj853f55d2002-04-26 00:27:53 +00001559/* ---------------------------------------------------
sewardj3b13f0e2002-04-25 20:17:29 +00001560 LIBRARY-PRIVATE THREAD SPECIFIC STATE
sewardjf8f819e2002-04-17 23:21:37 +00001561 ------------------------------------------------ */
1562
sewardj3b13f0e2002-04-25 20:17:29 +00001563#include <resolv.h>
1564static int thread_specific_errno[VG_N_THREADS];
1565static int thread_specific_h_errno[VG_N_THREADS];
1566static struct __res_state
1567 thread_specific_res_state[VG_N_THREADS];
sewardjf8f819e2002-04-17 23:21:37 +00001568
sewardj3b13f0e2002-04-25 20:17:29 +00001569int* __errno_location ( void )
sewardjf8f819e2002-04-17 23:21:37 +00001570{
1571 int tid;
sewardj3b13f0e2002-04-25 20:17:29 +00001572 /* ensure_valgrind("__errno_location"); */
1573 VALGRIND_MAGIC_SEQUENCE(tid, 1 /* default */,
sewardjf8f819e2002-04-17 23:21:37 +00001574 VG_USERREQ__PTHREAD_GET_THREADID,
1575 0, 0, 0, 0);
sewardj3b13f0e2002-04-25 20:17:29 +00001576 /* 'cos I'm paranoid ... */
sewardj439d45e2002-05-03 20:43:10 +00001577 if (tid < 1 || tid >= VG_N_THREADS)
sewardj3b13f0e2002-04-25 20:17:29 +00001578 barf("__errno_location: invalid ThreadId");
1579 return & thread_specific_errno[tid];
1580}
1581
1582int* __h_errno_location ( void )
1583{
1584 int tid;
1585 /* ensure_valgrind("__h_errno_location"); */
1586 VALGRIND_MAGIC_SEQUENCE(tid, 1 /* default */,
1587 VG_USERREQ__PTHREAD_GET_THREADID,
1588 0, 0, 0, 0);
1589 /* '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("__h_errno_location: invalid ThreadId");
1592 return & thread_specific_h_errno[tid];
1593}
1594
sewardjb0ff1032002-08-06 09:02:53 +00001595
1596#undef _res
1597extern struct __res_state _res;
1598
sewardj3b13f0e2002-04-25 20:17:29 +00001599struct __res_state* __res_state ( void )
1600{
1601 int tid;
1602 /* ensure_valgrind("__res_state"); */
1603 VALGRIND_MAGIC_SEQUENCE(tid, 1 /* default */,
1604 VG_USERREQ__PTHREAD_GET_THREADID,
1605 0, 0, 0, 0);
1606 /* 'cos I'm paranoid ... */
sewardj439d45e2002-05-03 20:43:10 +00001607 if (tid < 1 || tid >= VG_N_THREADS)
sewardj3b13f0e2002-04-25 20:17:29 +00001608 barf("__res_state: invalid ThreadId");
sewardjb0ff1032002-08-06 09:02:53 +00001609 if (tid == 1)
1610 return & _res;
sewardj3b13f0e2002-04-25 20:17:29 +00001611 return & thread_specific_res_state[tid];
sewardjf8f819e2002-04-17 23:21:37 +00001612}
1613
1614
sewardj5716dbb2002-04-26 03:28:18 +00001615/* ---------------------------------------------------
1616 LIBC-PRIVATE SPECIFIC DATA
1617 ------------------------------------------------ */
1618
1619/* Relies on assumption that initial private data is NULL. This
1620 should be fixed somehow. */
1621
njn25e49d8e72002-09-23 09:36:25 +00001622/* The allowable keys (indices) (all 3 of them).
sewardj5716dbb2002-04-26 03:28:18 +00001623 From sysdeps/pthread/bits/libc-tsd.h
1624*/
sewardjcb7f08a2002-10-02 09:41:49 +00001625/* as per glibc anoncvs HEAD of 20021001. */
sewardj5716dbb2002-04-26 03:28:18 +00001626enum __libc_tsd_key_t { _LIBC_TSD_KEY_MALLOC = 0,
1627 _LIBC_TSD_KEY_DL_ERROR,
njn25e49d8e72002-09-23 09:36:25 +00001628 _LIBC_TSD_KEY_RPC_VARS,
sewardjcb7f08a2002-10-02 09:41:49 +00001629 _LIBC_TSD_KEY_LOCALE,
1630 _LIBC_TSD_KEY_CTYPE_B,
1631 _LIBC_TSD_KEY_CTYPE_TOLOWER,
1632 _LIBC_TSD_KEY_CTYPE_TOUPPER,
sewardj5716dbb2002-04-26 03:28:18 +00001633 _LIBC_TSD_KEY_N };
1634
1635/* Auto-initialising subsystem. libc_specifics_inited is set
1636 after initialisation. libc_specifics_inited_mx guards it. */
1637static int libc_specifics_inited = 0;
1638static pthread_mutex_t libc_specifics_inited_mx = PTHREAD_MUTEX_INITIALIZER;
1639
sewardj00a66b12002-10-12 16:42:35 +00001640
sewardj5716dbb2002-04-26 03:28:18 +00001641/* These are the keys we must initialise the first time. */
sewardjcb7f08a2002-10-02 09:41:49 +00001642static pthread_key_t libc_specifics_keys[_LIBC_TSD_KEY_N];
sewardj5716dbb2002-04-26 03:28:18 +00001643
sewardj00a66b12002-10-12 16:42:35 +00001644
sewardjcb7f08a2002-10-02 09:41:49 +00001645/* Initialise the keys, if they are not already initialised. */
sewardj5716dbb2002-04-26 03:28:18 +00001646static
1647void init_libc_tsd_keys ( void )
1648{
1649 int res, i;
1650 pthread_key_t k;
1651
sewardj08c7f012002-10-07 23:56:55 +00001652 /* Don't fall into deadlock if we get called again whilst we still
1653 hold the lock, via the __uselocale() call herein. */
1654 if (libc_specifics_inited != 0)
1655 return;
1656
1657 /* Take the lock. */
sewardj00a66b12002-10-12 16:42:35 +00001658 res = __pthread_mutex_lock(&libc_specifics_inited_mx);
sewardj5716dbb2002-04-26 03:28:18 +00001659 if (res != 0) barf("init_libc_tsd_keys: lock");
1660
sewardj08c7f012002-10-07 23:56:55 +00001661 /* Now test again, to be sure there is no mistake. */
1662 if (libc_specifics_inited != 0) {
sewardj00a66b12002-10-12 16:42:35 +00001663 res = __pthread_mutex_unlock(&libc_specifics_inited_mx);
sewardj08c7f012002-10-07 23:56:55 +00001664 if (res != 0) barf("init_libc_tsd_keys: unlock(1)");
1665 return;
sewardj5716dbb2002-04-26 03:28:18 +00001666 }
1667
sewardj08c7f012002-10-07 23:56:55 +00001668 /* Actually do the initialisation. */
1669 /* printf("INIT libc specifics\n"); */
1670 for (i = 0; i < _LIBC_TSD_KEY_N; i++) {
sewardj00a66b12002-10-12 16:42:35 +00001671 res = __pthread_key_create(&k, NULL);
sewardj08c7f012002-10-07 23:56:55 +00001672 if (res != 0) barf("init_libc_tsd_keys: create");
1673 libc_specifics_keys[i] = k;
1674 }
1675
1676 /* Signify init done. */
1677 libc_specifics_inited = 1;
1678
1679# ifdef GLIBC_2_3
1680 /* Set the initialising thread's locale to the global (default)
sewardj00a66b12002-10-12 16:42:35 +00001681 locale. A hack in support of glibc-2.3. This does the biz for
1682 the root thread. For all other threads we run this in
1683 thread_wrapper(), which does the real work of
1684 pthread_create(). */
1685 /* assert that we are the root thread. I don't know if this is
1686 really a valid assertion to make; if it breaks I'll reconsider
1687 it. */
1688 my_assert(pthread_self() == 1);
sewardj08c7f012002-10-07 23:56:55 +00001689 __uselocale(LC_GLOBAL_LOCALE);
1690# endif
1691
1692 /* Unlock and return. */
sewardj00a66b12002-10-12 16:42:35 +00001693 res = __pthread_mutex_unlock(&libc_specifics_inited_mx);
sewardj5716dbb2002-04-26 03:28:18 +00001694 if (res != 0) barf("init_libc_tsd_keys: unlock");
1695}
1696
1697
1698static int
1699libc_internal_tsd_set ( enum __libc_tsd_key_t key,
1700 const void * pointer )
1701{
sewardjcb7f08a2002-10-02 09:41:49 +00001702 int res;
sewardj5716dbb2002-04-26 03:28:18 +00001703 /* printf("SET SET SET key %d ptr %p\n", key, pointer); */
sewardjcb7f08a2002-10-02 09:41:49 +00001704 if (key < _LIBC_TSD_KEY_MALLOC || key >= _LIBC_TSD_KEY_N)
sewardj5716dbb2002-04-26 03:28:18 +00001705 barf("libc_internal_tsd_set: invalid key");
1706 init_libc_tsd_keys();
sewardj00a66b12002-10-12 16:42:35 +00001707 res = __pthread_setspecific(libc_specifics_keys[key], pointer);
sewardj5716dbb2002-04-26 03:28:18 +00001708 if (res != 0) barf("libc_internal_tsd_set: setspecific failed");
1709 return 0;
1710}
1711
1712static void *
1713libc_internal_tsd_get ( enum __libc_tsd_key_t key )
1714{
sewardjcb7f08a2002-10-02 09:41:49 +00001715 void* v;
sewardj5716dbb2002-04-26 03:28:18 +00001716 /* printf("GET GET GET key %d\n", key); */
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_get: invalid key");
1719 init_libc_tsd_keys();
sewardj00a66b12002-10-12 16:42:35 +00001720 v = __pthread_getspecific(libc_specifics_keys[key]);
sewardj5716dbb2002-04-26 03:28:18 +00001721 /* if (v == NULL) barf("libc_internal_tsd_set: getspecific failed"); */
1722 return v;
1723}
1724
1725
sewardj70adeb22002-04-27 01:35:38 +00001726int (*__libc_internal_tsd_set)
1727 (enum __libc_tsd_key_t key, const void * pointer)
1728 = libc_internal_tsd_set;
sewardj5716dbb2002-04-26 03:28:18 +00001729
sewardj70adeb22002-04-27 01:35:38 +00001730void* (*__libc_internal_tsd_get)
1731 (enum __libc_tsd_key_t key)
1732 = libc_internal_tsd_get;
sewardj5716dbb2002-04-26 03:28:18 +00001733
1734
sewardj00a66b12002-10-12 16:42:35 +00001735#ifdef GLIBC_2_3
1736/* This one was first spotted be me in the glibc-2.2.93 sources. */
1737static void**
1738libc_internal_tsd_address ( enum __libc_tsd_key_t key )
1739{
1740 void** v;
1741 /* printf("ADDR ADDR ADDR key %d\n", key); */
1742 if (key < _LIBC_TSD_KEY_MALLOC || key >= _LIBC_TSD_KEY_N)
1743 barf("libc_internal_tsd_address: invalid key");
1744 init_libc_tsd_keys();
1745 v = __pthread_getspecific_addr(libc_specifics_keys[key]);
1746 return v;
1747}
1748
1749void ** (*__libc_internal_tsd_address)
1750 (enum __libc_tsd_key_t key)
1751 = libc_internal_tsd_address;
1752#endif
1753
1754
sewardje663cb92002-04-12 10:26:32 +00001755/* ---------------------------------------------------------------------
1756 These are here (I think) because they are deemed cancellation
1757 points by POSIX. For the moment we'll simply pass the call along
1758 to the corresponding thread-unaware (?) libc routine.
1759 ------------------------------------------------------------------ */
1760
sewardje663cb92002-04-12 10:26:32 +00001761#include <stdlib.h>
sewardje663cb92002-04-12 10:26:32 +00001762#include <sys/types.h>
1763#include <sys/socket.h>
1764
sewardjd529a442002-05-04 19:49:21 +00001765#ifdef GLIBC_2_1
1766extern
1767int __sigaction
1768 (int signum,
1769 const struct sigaction *act,
1770 struct sigaction *oldact);
1771#else
sewardje663cb92002-04-12 10:26:32 +00001772extern
1773int __libc_sigaction
1774 (int signum,
1775 const struct sigaction *act,
1776 struct sigaction *oldact);
sewardjd529a442002-05-04 19:49:21 +00001777#endif
sewardje663cb92002-04-12 10:26:32 +00001778int sigaction(int signum,
1779 const struct sigaction *act,
1780 struct sigaction *oldact)
1781{
sewardjd140e442002-05-29 01:21:19 +00001782 __my_pthread_testcancel();
sewardj2a1dcce2002-04-22 12:45:25 +00001783# ifdef GLIBC_2_1
1784 return __sigaction(signum, act, oldact);
1785# else
sewardj45b4b372002-04-16 22:50:32 +00001786 return __libc_sigaction(signum, act, oldact);
sewardj2a1dcce2002-04-22 12:45:25 +00001787# endif
sewardje663cb92002-04-12 10:26:32 +00001788}
1789
1790
1791extern
1792int __libc_connect(int sockfd,
1793 const struct sockaddr *serv_addr,
1794 socklen_t addrlen);
sewardj5905fae2002-04-26 13:25:00 +00001795__attribute__((weak))
sewardje663cb92002-04-12 10:26:32 +00001796int connect(int sockfd,
1797 const struct sockaddr *serv_addr,
1798 socklen_t addrlen)
1799{
sewardjd140e442002-05-29 01:21:19 +00001800 __my_pthread_testcancel();
sewardj45b4b372002-04-16 22:50:32 +00001801 return __libc_connect(sockfd, serv_addr, addrlen);
sewardje663cb92002-04-12 10:26:32 +00001802}
1803
1804
1805extern
1806int __libc_fcntl(int fd, int cmd, long arg);
sewardj5905fae2002-04-26 13:25:00 +00001807__attribute__((weak))
sewardje663cb92002-04-12 10:26:32 +00001808int fcntl(int fd, int cmd, long arg)
1809{
sewardjd140e442002-05-29 01:21:19 +00001810 __my_pthread_testcancel();
sewardj45b4b372002-04-16 22:50:32 +00001811 return __libc_fcntl(fd, cmd, arg);
sewardje663cb92002-04-12 10:26:32 +00001812}
1813
1814
1815extern
1816ssize_t __libc_write(int fd, const void *buf, size_t count);
sewardj5905fae2002-04-26 13:25:00 +00001817__attribute__((weak))
sewardje663cb92002-04-12 10:26:32 +00001818ssize_t write(int fd, const void *buf, size_t count)
1819{
sewardjd140e442002-05-29 01:21:19 +00001820 __my_pthread_testcancel();
sewardj45b4b372002-04-16 22:50:32 +00001821 return __libc_write(fd, buf, count);
sewardje663cb92002-04-12 10:26:32 +00001822}
1823
1824
1825extern
1826ssize_t __libc_read(int fd, void *buf, size_t count);
sewardj5905fae2002-04-26 13:25:00 +00001827__attribute__((weak))
sewardje663cb92002-04-12 10:26:32 +00001828ssize_t read(int fd, void *buf, size_t count)
1829{
sewardjd140e442002-05-29 01:21:19 +00001830 __my_pthread_testcancel();
sewardj45b4b372002-04-16 22:50:32 +00001831 return __libc_read(fd, buf, count);
sewardje663cb92002-04-12 10:26:32 +00001832}
1833
sewardjf912dfc2002-11-13 21:51:10 +00001834/*
1835 * Ugh, this is horrible but here goes:
1836 *
1837 * Open of a named pipe (fifo file) can block. In a threaded program,
1838 * this means that the whole thing can block. We therefore need to
1839 * make the open appear to block to the caller, but still keep polling
1840 * for everyone else.
1841 *
1842 * There are four cases:
1843 *
1844 * - the caller asked for O_NONBLOCK. The easy one: we just do it.
1845 *
1846 * - the caller asked for a blocking O_RDONLY open. We open it with
1847 * O_NONBLOCK and then use poll to wait for it to become ready.
1848 *
1849 * - the caller asked for a blocking O_WRONLY open. Unfortunately, this
1850 * will fail with ENXIO when we make it non-blocking. Doubly
1851 * unfortunate is that we can only rely on these semantics if it is
1852 * actually a fifo file; the hack is that if we see that it is a
1853 * O_WRONLY open and we get ENXIO, then stat the path and see if it
1854 * actually is a fifo. This is racy, but it is the best we can do.
1855 * If it is a fifo, then keep trying the open until it works; if not
1856 * just return the error.
1857 *
1858 * - the caller asked for a blocking O_RDWR open. Well, under Linux,
1859 * this never blocks, so we just clear the non-blocking flag and
1860 * return.
1861 *
1862 * This code assumes that for whatever we open, O_NONBLOCK followed by
1863 * a fcntl clearing O_NONBLOCK is the same as opening without
1864 * O_NONBLOCK. Also assumes that stat and fstat have no side-effects.
1865 *
1866 * XXX Should probably put in special cases for some devices as well,
1867 * like serial ports. Unfortunately they don't work like fifos, so
1868 * this logic will become even more tortured. Wait until we really
1869 * need it.
1870 */
1871static inline int _open(const char *pathname, int flags, mode_t mode,
1872 int (*openp)(const char *, int, mode_t))
sewardjbe32e452002-04-24 20:29:58 +00001873{
sewardjf912dfc2002-11-13 21:51:10 +00001874 int fd;
1875 struct stat st;
1876 struct vki_timespec nanosleep_interval;
1877 int saved_errno;
1878
sewardjd140e442002-05-29 01:21:19 +00001879 __my_pthread_testcancel();
sewardjf912dfc2002-11-13 21:51:10 +00001880
1881 /* Assume we can only get O_RDONLY, O_WRONLY or O_RDWR */
1882 my_assert((flags & VKI_O_ACCMODE) != VKI_O_ACCMODE);
1883
1884 for(;;) {
1885 fd = (*openp)(pathname, flags | VKI_O_NONBLOCK, mode);
1886
1887 /* return immediately if caller wanted nonblocking anyway */
1888 if (flags & VKI_O_NONBLOCK)
1889 return fd;
1890
1891 saved_errno = errno;
1892
1893 if (fd != -1)
1894 break; /* open worked */
1895
1896 /* If we got ENXIO and we're opening WRONLY, and it turns out
1897 to really be a FIFO, then poll waiting for open to succeed */
1898 if (errno == ENXIO &&
1899 (flags & VKI_O_ACCMODE) == VKI_O_WRONLY &&
1900 (stat(pathname, &st) == 0 && S_ISFIFO(st.st_mode))) {
1901
1902 /* OK, we're opening a FIFO for writing; sleep and spin */
1903 nanosleep_interval.tv_sec = 0;
1904 nanosleep_interval.tv_nsec = 13 * 1000 * 1000; /* 13 milliseconds */
1905 /* It's critical here that valgrind's nanosleep implementation
1906 is nonblocking. */
1907 (void)my_do_syscall2(__NR_nanosleep,
1908 (int)(&nanosleep_interval), (int)NULL);
1909 } else {
1910 /* it was just an error */
1911 errno = saved_errno;
1912 return -1;
1913 }
1914 }
1915
1916 /* OK, we've got a nonblocking FD for a caller who wants blocking;
1917 reset the flags to what they asked for */
1918 fcntl(fd, VKI_F_SETFL, flags);
1919
1920 /* Return now if one of:
1921 - we were opening O_RDWR (never blocks)
1922 - we opened with O_WRONLY (polling already done)
1923 - the thing we opened wasn't a FIFO after all (or fstat failed)
1924 */
1925 if ((flags & VKI_O_ACCMODE) != VKI_O_RDONLY ||
1926 (fstat(fd, &st) == -1 || !S_ISFIFO(st.st_mode))) {
1927 errno = saved_errno;
1928 return fd;
1929 }
1930
1931 /* OK, drop into the poll loop looking for something to read on the fd */
1932 my_assert((flags & VKI_O_ACCMODE) == VKI_O_RDONLY);
1933 for(;;) {
1934 struct pollfd pollfd;
1935 int res;
1936
1937 pollfd.fd = fd;
1938 pollfd.events = POLLIN;
1939 pollfd.revents = 0;
1940
1941 res = my_do_syscall3(__NR_poll, (int)&pollfd, 1, 0);
1942
1943 my_assert(res == 0 || res == 1);
1944
1945 if (res == 1) {
1946 /* OK, got it.
1947
1948 XXX This is wrong: we're waiting for either something to
1949 read or a HUP on the file descriptor, but the semantics of
1950 fifo open are that we should unblock as soon as someone
1951 simply opens the other end, not that they write something.
1952 With luck this won't matter in practice.
1953 */
1954 my_assert(pollfd.revents & (POLLIN|POLLHUP));
1955 break;
1956 }
1957
1958 /* Still nobody home; sleep and spin */
1959 nanosleep_interval.tv_sec = 0;
1960 nanosleep_interval.tv_nsec = 13 * 1000 * 1000; /* 13 milliseconds */
1961 /* It's critical here that valgrind's nanosleep implementation
1962 is nonblocking. */
1963 (void)my_do_syscall2(__NR_nanosleep,
1964 (int)(&nanosleep_interval), (int)NULL);
1965 }
1966
1967 errno = saved_errno;
1968 return fd;
sewardjbe32e452002-04-24 20:29:58 +00001969}
1970
sewardjf912dfc2002-11-13 21:51:10 +00001971extern
1972int __libc_open64(const char *pathname, int flags, mode_t mode);
1973/* __attribute__((weak)) */
1974int open64(const char *pathname, int flags, mode_t mode)
1975{
1976 return _open(pathname, flags, mode, __libc_open64);
1977}
sewardje663cb92002-04-12 10:26:32 +00001978
1979extern
sewardj853f55d2002-04-26 00:27:53 +00001980int __libc_open(const char *pathname, int flags, mode_t mode);
sewardjf912dfc2002-11-13 21:51:10 +00001981/* __attribute__((weak)) */
sewardj853f55d2002-04-26 00:27:53 +00001982int open(const char *pathname, int flags, mode_t mode)
sewardje663cb92002-04-12 10:26:32 +00001983{
sewardjf912dfc2002-11-13 21:51:10 +00001984 return _open(pathname, flags, mode, __libc_open);
sewardje663cb92002-04-12 10:26:32 +00001985}
1986
sewardje663cb92002-04-12 10:26:32 +00001987extern
1988int __libc_close(int fd);
sewardj5905fae2002-04-26 13:25:00 +00001989__attribute__((weak))
sewardje663cb92002-04-12 10:26:32 +00001990int close(int fd)
1991{
sewardjd140e442002-05-29 01:21:19 +00001992 __my_pthread_testcancel();
sewardj45b4b372002-04-16 22:50:32 +00001993 return __libc_close(fd);
sewardje663cb92002-04-12 10:26:32 +00001994}
1995
1996
1997extern
1998int __libc_accept(int s, struct sockaddr *addr, socklen_t *addrlen);
sewardjf220ccc2002-10-23 21:53:49 +00001999
2000int VGL_(accept)(int s, struct sockaddr *addr, socklen_t *addrlen)
sewardje663cb92002-04-12 10:26:32 +00002001{
sewardjd140e442002-05-29 01:21:19 +00002002 __my_pthread_testcancel();
sewardj705d3cb2002-05-23 13:13:12 +00002003 wait_for_fd_to_be_readable_or_erring(s);
sewardjd140e442002-05-29 01:21:19 +00002004 __my_pthread_testcancel();
sewardj45b4b372002-04-16 22:50:32 +00002005 return __libc_accept(s, addr, addrlen);
sewardje663cb92002-04-12 10:26:32 +00002006}
2007
sewardj0c573af92002-10-23 21:55:01 +00002008extern
2009int __libc_recv(int s, void *buf, size_t len, int flags);
2010
2011int VGL_(recv)(int s, void *buf, size_t len, int flags)
2012{
2013 __my_pthread_testcancel();
2014 wait_for_fd_to_be_readable_or_erring(s);
2015 __my_pthread_testcancel();
2016 return __libc_recv(s, buf, len, flags);
2017}
2018
sewardj2a68e7e2002-11-16 11:04:18 +00002019int VGL_(readv)(int fd, const struct iovec *iov, int count)
2020{
sewardjfd7747b2002-12-01 10:25:53 +00002021 int res;
2022
sewardj2a68e7e2002-11-16 11:04:18 +00002023 __my_pthread_testcancel();
2024 wait_for_fd_to_be_readable_or_erring(fd);
2025 __my_pthread_testcancel();
sewardjfd7747b2002-12-01 10:25:53 +00002026 res = my_do_syscall3(__NR_readv, fd, (unsigned)iov, count);
2027
2028 if (is_kerror(res)) {
2029 *(__errno_location()) = -res;
2030 return -1;
2031 }
2032 return res;
sewardj2a68e7e2002-11-16 11:04:18 +00002033}
2034
2035int VGL_(writev)(int fd, struct iovec *iov, int count)
2036{
sewardjfd7747b2002-12-01 10:25:53 +00002037 int res;
2038
sewardj2a68e7e2002-11-16 11:04:18 +00002039 __my_pthread_testcancel();
2040 wait_for_fd_to_be_writable_or_erring(fd);
2041 __my_pthread_testcancel();
sewardjfd7747b2002-12-01 10:25:53 +00002042 res = my_do_syscall3(__NR_writev, fd, (unsigned)iov, count);
2043
2044 if (is_kerror(res)) {
2045 *(__errno_location()) = -res;
2046 return -1;
2047 }
2048 return res;
sewardj2a68e7e2002-11-16 11:04:18 +00002049}
sewardje663cb92002-04-12 10:26:32 +00002050
2051extern
sewardje663cb92002-04-12 10:26:32 +00002052pid_t __libc_waitpid(pid_t pid, int *status, int options);
sewardj5905fae2002-04-26 13:25:00 +00002053__attribute__((weak))
sewardje663cb92002-04-12 10:26:32 +00002054pid_t waitpid(pid_t pid, int *status, int options)
2055{
sewardjd140e442002-05-29 01:21:19 +00002056 __my_pthread_testcancel();
sewardj45b4b372002-04-16 22:50:32 +00002057 return __libc_waitpid(pid, status, options);
sewardje663cb92002-04-12 10:26:32 +00002058}
2059
2060
2061extern
2062int __libc_nanosleep(const struct timespec *req, struct timespec *rem);
sewardj5905fae2002-04-26 13:25:00 +00002063__attribute__((weak))
sewardje663cb92002-04-12 10:26:32 +00002064int nanosleep(const struct timespec *req, struct timespec *rem)
2065{
sewardjd140e442002-05-29 01:21:19 +00002066 __my_pthread_testcancel();
sewardje663cb92002-04-12 10:26:32 +00002067 return __libc_nanosleep(req, rem);
2068}
2069
sewardjbe32e452002-04-24 20:29:58 +00002070
sewardje663cb92002-04-12 10:26:32 +00002071extern
2072int __libc_fsync(int fd);
sewardj5905fae2002-04-26 13:25:00 +00002073__attribute__((weak))
sewardje663cb92002-04-12 10:26:32 +00002074int fsync(int fd)
2075{
sewardjd140e442002-05-29 01:21:19 +00002076 __my_pthread_testcancel();
sewardj45b4b372002-04-16 22:50:32 +00002077 return __libc_fsync(fd);
sewardje663cb92002-04-12 10:26:32 +00002078}
2079
sewardjbe32e452002-04-24 20:29:58 +00002080
sewardj70c75362002-04-13 04:18:32 +00002081extern
2082off_t __libc_lseek(int fildes, off_t offset, int whence);
sewardj5905fae2002-04-26 13:25:00 +00002083__attribute__((weak))
sewardj70c75362002-04-13 04:18:32 +00002084off_t lseek(int fildes, off_t offset, int whence)
2085{
sewardjd140e442002-05-29 01:21:19 +00002086 __my_pthread_testcancel();
sewardj45b4b372002-04-16 22:50:32 +00002087 return __libc_lseek(fildes, offset, whence);
sewardj70c75362002-04-13 04:18:32 +00002088}
2089
sewardjbe32e452002-04-24 20:29:58 +00002090
2091extern
2092__off64_t __libc_lseek64(int fildes, __off64_t offset, int whence);
sewardj5905fae2002-04-26 13:25:00 +00002093__attribute__((weak))
sewardjbe32e452002-04-24 20:29:58 +00002094__off64_t lseek64(int fildes, __off64_t offset, int whence)
2095{
sewardjd140e442002-05-29 01:21:19 +00002096 __my_pthread_testcancel();
sewardjbe32e452002-04-24 20:29:58 +00002097 return __libc_lseek64(fildes, offset, whence);
2098}
2099
2100
sewardj726c4122002-05-16 23:39:10 +00002101extern
2102ssize_t __libc_pread64 (int __fd, void *__buf, size_t __nbytes,
2103 __off64_t __offset);
2104ssize_t __pread64 (int __fd, void *__buf, size_t __nbytes,
2105 __off64_t __offset)
2106{
sewardjd140e442002-05-29 01:21:19 +00002107 __my_pthread_testcancel();
sewardj726c4122002-05-16 23:39:10 +00002108 return __libc_pread64(__fd, __buf, __nbytes, __offset);
2109}
2110
2111
sewardja18e2102002-05-18 10:43:22 +00002112extern
2113ssize_t __libc_pwrite64 (int __fd, const void *__buf, size_t __nbytes,
2114 __off64_t __offset);
2115ssize_t __pwrite64 (int __fd, const void *__buf, size_t __nbytes,
2116 __off64_t __offset)
2117{
sewardjd140e442002-05-29 01:21:19 +00002118 __my_pthread_testcancel();
sewardja18e2102002-05-18 10:43:22 +00002119 return __libc_pwrite64(__fd, __buf, __nbytes, __offset);
2120}
2121
sewardj726c4122002-05-16 23:39:10 +00002122
sewardj39b93b12002-05-18 10:56:27 +00002123extern
2124ssize_t __libc_pwrite(int fd, const void *buf, size_t count, off_t offset);
2125__attribute__((weak))
2126ssize_t pwrite(int fd, const void *buf, size_t count, off_t offset)
2127{
sewardjd140e442002-05-29 01:21:19 +00002128 __my_pthread_testcancel();
sewardj39b93b12002-05-18 10:56:27 +00002129 return __libc_pwrite(fd, buf, count, offset);
2130}
2131
2132
2133extern
2134ssize_t __libc_pread(int fd, void *buf, size_t count, off_t offset);
2135__attribute__((weak))
2136ssize_t pread(int fd, void *buf, size_t count, off_t offset)
2137{
sewardjd140e442002-05-29 01:21:19 +00002138 __my_pthread_testcancel();
sewardj39b93b12002-05-18 10:56:27 +00002139 return __libc_pread(fd, buf, count, offset);
2140}
2141
2142
sewardj6af4b5d2002-04-16 04:40:49 +00002143extern
2144void __libc_longjmp(jmp_buf env, int val) __attribute((noreturn));
sewardj5905fae2002-04-26 13:25:00 +00002145/* not weak: __attribute__((weak)) */
sewardj6af4b5d2002-04-16 04:40:49 +00002146void longjmp(jmp_buf env, int val)
2147{
2148 __libc_longjmp(env, val);
2149}
2150
sewardjbe32e452002-04-24 20:29:58 +00002151
sewardj436c2db2002-06-18 09:07:54 +00002152extern void __libc_siglongjmp (sigjmp_buf env, int val)
2153 __attribute__ ((noreturn));
2154void siglongjmp(sigjmp_buf env, int val)
2155{
2156 kludged("siglongjmp (cleanup handlers are ignored)");
2157 __libc_siglongjmp(env, val);
2158}
2159
2160
sewardj6af4b5d2002-04-16 04:40:49 +00002161extern
2162int __libc_send(int s, const void *msg, size_t len, int flags);
sewardj5905fae2002-04-26 13:25:00 +00002163__attribute__((weak))
sewardj6af4b5d2002-04-16 04:40:49 +00002164int send(int s, const void *msg, size_t len, int flags)
2165{
sewardjd140e442002-05-29 01:21:19 +00002166 __my_pthread_testcancel();
sewardj6af4b5d2002-04-16 04:40:49 +00002167 return __libc_send(s, msg, len, flags);
2168}
2169
sewardjbe32e452002-04-24 20:29:58 +00002170
sewardj1e8cdc92002-04-18 11:37:52 +00002171extern
2172int __libc_recv(int s, void *buf, size_t len, int flags);
sewardj5905fae2002-04-26 13:25:00 +00002173__attribute__((weak))
sewardj1e8cdc92002-04-18 11:37:52 +00002174int recv(int s, void *buf, size_t len, int flags)
2175{
sewardjd140e442002-05-29 01:21:19 +00002176 __my_pthread_testcancel();
sewardj1d6b3a22002-06-20 07:58:33 +00002177 wait_for_fd_to_be_readable_or_erring(s);
2178 __my_pthread_testcancel();
sewardj1e8cdc92002-04-18 11:37:52 +00002179 return __libc_recv(s, buf, len, flags);
2180}
2181
sewardjbe32e452002-04-24 20:29:58 +00002182
sewardj3665ded2002-05-16 16:57:25 +00002183extern
2184int __libc_sendmsg(int s, const struct msghdr *msg, int flags);
2185__attribute__((weak))
2186int sendmsg(int s, const struct msghdr *msg, int flags)
2187{
sewardjd140e442002-05-29 01:21:19 +00002188 __my_pthread_testcancel();
sewardj3665ded2002-05-16 16:57:25 +00002189 return __libc_sendmsg(s, msg, flags);
2190}
2191
2192
sewardj796d6a22002-04-24 02:28:34 +00002193extern
sewardj59da27a2002-06-06 08:33:54 +00002194int __libc_recvmsg(int s, struct msghdr *msg, int flags);
2195__attribute__((weak))
2196int recvmsg(int s, struct msghdr *msg, int flags)
2197{
2198 __my_pthread_testcancel();
2199 return __libc_recvmsg(s, msg, flags);
2200}
2201
2202
2203extern
sewardj436e0582002-04-26 14:31:40 +00002204int __libc_recvfrom(int s, void *buf, size_t len, int flags,
2205 struct sockaddr *from, socklen_t *fromlen);
2206__attribute__((weak))
2207int recvfrom(int s, void *buf, size_t len, int flags,
2208 struct sockaddr *from, socklen_t *fromlen)
2209{
sewardjd140e442002-05-29 01:21:19 +00002210 __my_pthread_testcancel();
sewardj2e207632002-06-13 17:29:53 +00002211 wait_for_fd_to_be_readable_or_erring(s);
2212 __my_pthread_testcancel();
sewardj436e0582002-04-26 14:31:40 +00002213 return __libc_recvfrom(s, buf, len, flags, from, fromlen);
2214}
2215
2216
2217extern
sewardj796d6a22002-04-24 02:28:34 +00002218int __libc_sendto(int s, const void *msg, size_t len, int flags,
2219 const struct sockaddr *to, socklen_t tolen);
sewardj5905fae2002-04-26 13:25:00 +00002220__attribute__((weak))
sewardj796d6a22002-04-24 02:28:34 +00002221int sendto(int s, const void *msg, size_t len, int flags,
2222 const struct sockaddr *to, socklen_t tolen)
2223{
sewardjd140e442002-05-29 01:21:19 +00002224 __my_pthread_testcancel();
sewardj796d6a22002-04-24 02:28:34 +00002225 return __libc_sendto(s, msg, len, flags, to, tolen);
2226}
2227
sewardjbe32e452002-04-24 20:29:58 +00002228
sewardj369b1702002-04-24 13:28:15 +00002229extern
2230int __libc_system(const char* str);
sewardj5905fae2002-04-26 13:25:00 +00002231__attribute__((weak))
sewardj369b1702002-04-24 13:28:15 +00002232int system(const char* str)
2233{
sewardjd140e442002-05-29 01:21:19 +00002234 __my_pthread_testcancel();
sewardj369b1702002-04-24 13:28:15 +00002235 return __libc_system(str);
2236}
2237
sewardjbe32e452002-04-24 20:29:58 +00002238
sewardjab0b1c32002-04-24 19:26:47 +00002239extern
2240pid_t __libc_wait(int *status);
sewardj5905fae2002-04-26 13:25:00 +00002241__attribute__((weak))
sewardjab0b1c32002-04-24 19:26:47 +00002242pid_t wait(int *status)
2243{
sewardjd140e442002-05-29 01:21:19 +00002244 __my_pthread_testcancel();
sewardjab0b1c32002-04-24 19:26:47 +00002245 return __libc_wait(status);
2246}
2247
sewardj45b4b372002-04-16 22:50:32 +00002248
sewardj67f1d582002-05-24 02:11:32 +00002249extern
2250int __libc_msync(const void *start, size_t length, int flags);
2251__attribute__((weak))
2252int msync(const void *start, size_t length, int flags)
2253{
sewardjd140e442002-05-29 01:21:19 +00002254 __my_pthread_testcancel();
sewardj67f1d582002-05-24 02:11:32 +00002255 return __libc_msync(start, length, flags);
2256}
2257
sewardj5905fae2002-04-26 13:25:00 +00002258
sewardj2cb00342002-06-28 01:46:26 +00002259/*--- fork and its helper ---*/
2260
2261static
2262void run_fork_handlers ( int what )
2263{
2264 ForkHandlerEntry entry;
2265 int n_h, n_handlers, i, res;
2266
2267 my_assert(what == 0 || what == 1 || what == 2);
2268
2269 /* Fetch old counter */
2270 VALGRIND_MAGIC_SEQUENCE(n_handlers, -2 /* default */,
2271 VG_USERREQ__GET_FHSTACK_USED,
2272 0, 0, 0, 0);
2273 my_assert(n_handlers >= 0 && n_handlers < VG_N_FORKHANDLERSTACK);
2274
2275 /* Prepare handlers (what == 0) are called in opposite order of
2276 calls to pthread_atfork. Parent and child handlers are called
2277 in the same order as calls to pthread_atfork. */
2278 if (what == 0)
2279 n_h = n_handlers - 1;
2280 else
2281 n_h = 0;
2282
2283 for (i = 0; i < n_handlers; i++) {
2284 VALGRIND_MAGIC_SEQUENCE(res, -2 /* default */,
2285 VG_USERREQ__GET_FHSTACK_ENTRY,
2286 n_h, &entry, 0, 0);
2287 my_assert(res == 0);
2288 switch (what) {
2289 case 0: if (entry.prepare) entry.prepare();
2290 n_h--; break;
2291 case 1: if (entry.parent) entry.parent();
2292 n_h++; break;
2293 case 2: if (entry.child) entry.child();
2294 n_h++; break;
2295 default: barf("run_fork_handlers: invalid what");
2296 }
2297 }
2298
2299 if (what != 0 /* prepare */) {
2300 /* Empty out the stack. */
2301 VALGRIND_MAGIC_SEQUENCE(res, -2 /* default */,
2302 VG_USERREQ__SET_FHSTACK_USED,
2303 0, 0, 0, 0);
2304 my_assert(res == 0);
2305 }
2306}
2307
2308extern
2309pid_t __libc_fork(void);
2310pid_t __fork(void)
2311{
2312 pid_t pid;
2313 __my_pthread_testcancel();
2314 __pthread_mutex_lock(&pthread_atfork_lock);
2315
2316 run_fork_handlers(0 /* prepare */);
2317 pid = __libc_fork();
2318 if (pid == 0) {
2319 /* I am the child */
2320 run_fork_handlers(2 /* child */);
sewardjd8acdf22002-11-13 21:57:52 +00002321 __pthread_mutex_unlock(&pthread_atfork_lock);
sewardj2cb00342002-06-28 01:46:26 +00002322 __pthread_mutex_init(&pthread_atfork_lock, NULL);
2323 } else {
2324 /* I am the parent */
2325 run_fork_handlers(1 /* parent */);
2326 __pthread_mutex_unlock(&pthread_atfork_lock);
2327 }
2328 return pid;
2329}
2330
2331
njn25e49d8e72002-09-23 09:36:25 +00002332pid_t __vfork(void)
2333{
2334 return __fork();
2335}
sewardj2cb00342002-06-28 01:46:26 +00002336
2337
sewardj3b13f0e2002-04-25 20:17:29 +00002338/* ---------------------------------------------------------------------
2339 Nonblocking implementations of select() and poll(). This stuff will
2340 surely rot your mind.
2341 ------------------------------------------------------------------ */
sewardje663cb92002-04-12 10:26:32 +00002342
sewardj08a4c3f2002-04-13 03:45:44 +00002343/*--------------------------------------------------*/
2344
2345#include "vg_kerneliface.h"
2346
2347static
sewardj08a4c3f2002-04-13 03:45:44 +00002348int my_do_syscall1 ( int syscallno, int arg1 )
2349{
2350 int __res;
2351 __asm__ volatile ("pushl %%ebx; movl %%edx,%%ebx ; int $0x80 ; popl %%ebx"
2352 : "=a" (__res)
2353 : "0" (syscallno),
2354 "d" (arg1) );
2355 return __res;
2356}
2357
2358static
2359int my_do_syscall2 ( int syscallno,
sewardjf854f472002-04-21 12:19:41 +00002360 int arg1, int arg2 )
sewardj08a4c3f2002-04-13 03:45:44 +00002361{
2362 int __res;
2363 __asm__ volatile ("pushl %%ebx; movl %%edx,%%ebx ; int $0x80 ; popl %%ebx"
2364 : "=a" (__res)
2365 : "0" (syscallno),
2366 "d" (arg1),
2367 "c" (arg2) );
2368 return __res;
2369}
2370
2371static
sewardjf854f472002-04-21 12:19:41 +00002372int my_do_syscall3 ( int syscallno,
2373 int arg1, int arg2, int arg3 )
2374{
2375 int __res;
2376 __asm__ volatile ("pushl %%ebx; movl %%esi,%%ebx ; int $0x80 ; popl %%ebx"
2377 : "=a" (__res)
2378 : "0" (syscallno),
2379 "S" (arg1),
2380 "c" (arg2),
2381 "d" (arg3) );
2382 return __res;
2383}
2384
sewardjd5bef572002-10-23 21:49:33 +00002385static inline
2386int my_do_syscall5 ( int syscallno,
2387 int arg1, int arg2, int arg3, int arg4, int arg5 )
2388{
2389 int __res;
2390 __asm__ volatile ("int $0x80"
2391 : "=a" (__res)
2392 : "0" (syscallno),
2393 "b" (arg1),
2394 "c" (arg2),
2395 "d" (arg3),
2396 "S" (arg4),
2397 "D" (arg5));
2398 return __res;
2399}
2400
sewardjf854f472002-04-21 12:19:41 +00002401static
sewardj08a4c3f2002-04-13 03:45:44 +00002402int do_syscall_select( int n,
2403 vki_fd_set* readfds,
2404 vki_fd_set* writefds,
2405 vki_fd_set* exceptfds,
2406 struct vki_timeval * timeout )
2407{
2408 int res;
2409 int args[5];
2410 args[0] = n;
2411 args[1] = (int)readfds;
2412 args[2] = (int)writefds;
2413 args[3] = (int)exceptfds;
2414 args[4] = (int)timeout;
2415 res = my_do_syscall1(__NR_select, (int)(&(args[0])) );
sewardj02535bc2002-04-21 01:08:26 +00002416 return res;
sewardj08a4c3f2002-04-13 03:45:44 +00002417}
2418
2419
2420/* This is a wrapper round select(), which makes it thread-safe,
2421 meaning that only this thread will block, rather than the entire
2422 process. This wrapper in turn depends on nanosleep() not to block
2423 the entire process, but I think (hope? suspect?) that POSIX
2424 pthreads guarantees that to be the case.
2425
2426 Basic idea is: modify the timeout parameter to select so that it
2427 returns immediately. Poll like this until select returns non-zero,
2428 indicating something interesting happened, or until our time is up.
njn25e49d8e72002-09-23 09:36:25 +00002429 Space out the polls with nanosleeps of say 11 milliseconds, which
sewardj08a4c3f2002-04-13 03:45:44 +00002430 is required to be nonblocking; this allows other threads to run.
sewardj02535bc2002-04-21 01:08:26 +00002431
2432 Assumes:
sewardj2d94c112002-06-03 01:25:54 +00002433 * (checked via my_assert) types fd_set and vki_fd_set are identical.
2434 * (checked via my_assert) types timeval and vki_timeval are identical.
sewardj02535bc2002-04-21 01:08:26 +00002435 * (unchecked) libc error numbers (EINTR etc) are the negation of the
2436 kernel's error numbers (VKI_EINTR etc).
sewardj08a4c3f2002-04-13 03:45:44 +00002437*/
sewardj08a4c3f2002-04-13 03:45:44 +00002438
sewardj7db011a2002-11-13 22:00:20 +00002439int VGL_(select) ( int n,
2440 fd_set *rfds,
2441 fd_set *wfds,
2442 fd_set *xfds,
2443 struct timeval *timeout )
sewardj08a4c3f2002-04-13 03:45:44 +00002444{
sewardj5f07b662002-04-23 16:52:51 +00002445 unsigned int ms_now, ms_end;
sewardj08a4c3f2002-04-13 03:45:44 +00002446 int res;
2447 fd_set rfds_copy;
2448 fd_set wfds_copy;
2449 fd_set xfds_copy;
2450 struct vki_timeval t_now;
sewardj08a4c3f2002-04-13 03:45:44 +00002451 struct vki_timeval zero_timeout;
2452 struct vki_timespec nanosleep_interval;
2453
sewardjd140e442002-05-29 01:21:19 +00002454 __my_pthread_testcancel();
2455
sewardj5f07b662002-04-23 16:52:51 +00002456 /* gcc's complains about ms_end being used uninitialised -- classic
2457 case it can't understand, where ms_end is both defined and used
2458 only if timeout != NULL. Hence ... */
2459 ms_end = 0;
sewardj08a4c3f2002-04-13 03:45:44 +00002460
2461 /* We assume that the kernel and libc data layouts are identical
2462 for the following types. These asserts provide a crude
2463 check. */
2464 if (sizeof(fd_set) != sizeof(vki_fd_set)
2465 || sizeof(struct timeval) != sizeof(struct vki_timeval))
2466 barf("valgrind's hacky non-blocking select(): data sizes error");
2467
sewardj5f07b662002-04-23 16:52:51 +00002468 /* Detect the current time and simultaneously find out if we are
2469 running on Valgrind. */
2470 VALGRIND_MAGIC_SEQUENCE(ms_now, 0xFFFFFFFF /* default */,
2471 VG_USERREQ__READ_MILLISECOND_TIMER,
2472 0, 0, 0, 0);
2473
2474 /* If a zero timeout specified, this call is harmless. Also go
2475 this route if we're not running on Valgrind, for whatever
2476 reason. */
2477 if ( (timeout && timeout->tv_sec == 0 && timeout->tv_usec == 0)
2478 || (ms_now == 0xFFFFFFFF) ) {
sewardj02535bc2002-04-21 01:08:26 +00002479 res = do_syscall_select( n, (vki_fd_set*)rfds,
sewardj08a4c3f2002-04-13 03:45:44 +00002480 (vki_fd_set*)wfds,
2481 (vki_fd_set*)xfds,
2482 (struct vki_timeval*)timeout);
sewardj02535bc2002-04-21 01:08:26 +00002483 if (is_kerror(res)) {
2484 * (__errno_location()) = -res;
2485 return -1;
2486 } else {
2487 return res;
2488 }
2489 }
sewardj08a4c3f2002-04-13 03:45:44 +00002490
sewardj5f07b662002-04-23 16:52:51 +00002491 /* If a timeout was specified, set ms_end to be the end millisecond
2492 counter [wallclock] time. */
sewardj08a4c3f2002-04-13 03:45:44 +00002493 if (timeout) {
2494 res = my_do_syscall2(__NR_gettimeofday, (int)&t_now, (int)NULL);
sewardj2d94c112002-06-03 01:25:54 +00002495 my_assert(res == 0);
sewardj5f07b662002-04-23 16:52:51 +00002496 ms_end = ms_now;
2497 ms_end += (timeout->tv_usec / 1000);
2498 ms_end += (timeout->tv_sec * 1000);
sewardj08a4c3f2002-04-13 03:45:44 +00002499 /* Stay sane ... */
sewardj2d94c112002-06-03 01:25:54 +00002500 my_assert (ms_end >= ms_now);
sewardj08a4c3f2002-04-13 03:45:44 +00002501 }
2502
2503 /* fprintf(stderr, "MY_SELECT: before loop\n"); */
2504
2505 /* Either timeout == NULL, meaning wait indefinitely, or timeout !=
sewardj5f07b662002-04-23 16:52:51 +00002506 NULL, in which case ms_end holds the end time. */
sewardj05bb2c92002-06-26 00:47:17 +00002507
sewardj08a4c3f2002-04-13 03:45:44 +00002508 while (1) {
sewardj05bb2c92002-06-26 00:47:17 +00002509
2510 /* First, do a return-immediately select(). */
sewardj08a4c3f2002-04-13 03:45:44 +00002511
2512 /* These could be trashed each time round the loop, so restore
2513 them each time. */
2514 if (rfds) rfds_copy = *rfds;
2515 if (wfds) wfds_copy = *wfds;
2516 if (xfds) xfds_copy = *xfds;
2517
2518 zero_timeout.tv_sec = zero_timeout.tv_usec = 0;
2519
2520 res = do_syscall_select( n,
2521 rfds ? (vki_fd_set*)(&rfds_copy) : NULL,
2522 wfds ? (vki_fd_set*)(&wfds_copy) : NULL,
2523 xfds ? (vki_fd_set*)(&xfds_copy) : NULL,
2524 & zero_timeout );
sewardj02535bc2002-04-21 01:08:26 +00002525 if (is_kerror(res)) {
2526 /* Some kind of error (including EINTR). Set errno and
sewardj08a4c3f2002-04-13 03:45:44 +00002527 return. The sets are unspecified in this case. */
sewardj02535bc2002-04-21 01:08:26 +00002528 * (__errno_location()) = -res;
2529 return -1;
sewardj08a4c3f2002-04-13 03:45:44 +00002530 }
2531 if (res > 0) {
2532 /* one or more fds is ready. Copy out resulting sets and
2533 return. */
2534 if (rfds) *rfds = rfds_copy;
2535 if (wfds) *wfds = wfds_copy;
2536 if (xfds) *xfds = xfds_copy;
2537 return res;
2538 }
sewardj05bb2c92002-06-26 00:47:17 +00002539
2540 /* Nothing interesting happened, so we go to sleep for a
2541 while. */
2542
sewardj08a4c3f2002-04-13 03:45:44 +00002543 /* fprintf(stderr, "MY_SELECT: nanosleep\n"); */
2544 /* nanosleep and go round again */
sewardj02535bc2002-04-21 01:08:26 +00002545 nanosleep_interval.tv_sec = 0;
njn25e49d8e72002-09-23 09:36:25 +00002546 nanosleep_interval.tv_nsec = 11 * 1000 * 1000; /* 11 milliseconds */
sewardjf854f472002-04-21 12:19:41 +00002547 /* It's critical here that valgrind's nanosleep implementation
2548 is nonblocking. */
sewardj645030e2002-06-06 01:27:39 +00002549 res = my_do_syscall2(__NR_nanosleep,
sewardjf854f472002-04-21 12:19:41 +00002550 (int)(&nanosleep_interval), (int)NULL);
sewardj645030e2002-06-06 01:27:39 +00002551 if (res == -VKI_EINTR) {
2552 /* The nanosleep was interrupted by a signal. So we do the
2553 same. */
2554 * (__errno_location()) = EINTR;
2555 return -1;
2556 }
sewardj05bb2c92002-06-26 00:47:17 +00002557
2558 /* Sleeping finished. If a finite timeout, check to see if it
2559 has expired yet. */
2560 if (timeout) {
2561 VALGRIND_MAGIC_SEQUENCE(ms_now, 0xFFFFFFFF /* default */,
2562 VG_USERREQ__READ_MILLISECOND_TIMER,
2563 0, 0, 0, 0);
2564 my_assert(ms_now != 0xFFFFFFFF);
2565 if (ms_now >= ms_end) {
2566 /* timeout; nothing interesting happened. */
2567 if (rfds) FD_ZERO(rfds);
2568 if (wfds) FD_ZERO(wfds);
2569 if (xfds) FD_ZERO(xfds);
2570 return 0;
2571 }
2572 }
2573
sewardjf854f472002-04-21 12:19:41 +00002574 }
2575}
2576
2577
2578
2579
2580#include <sys/poll.h>
2581
sewardj3e909ce2002-06-03 13:27:15 +00002582#ifndef HAVE_NFDS_T
sewardj72d58482002-04-24 02:20:20 +00002583typedef unsigned long int nfds_t;
2584#endif
2585
sewardj705d3cb2002-05-23 13:13:12 +00002586
sewardj7db011a2002-11-13 22:00:20 +00002587int VGL_(poll) (struct pollfd *__fds, nfds_t __nfds, int __timeout)
sewardjf854f472002-04-21 12:19:41 +00002588{
sewardj5f07b662002-04-23 16:52:51 +00002589 unsigned int ms_now, ms_end;
sewardjf854f472002-04-21 12:19:41 +00002590 int res, i;
sewardjf854f472002-04-21 12:19:41 +00002591 struct vki_timespec nanosleep_interval;
2592
sewardjd140e442002-05-29 01:21:19 +00002593 __my_pthread_testcancel();
sewardjf854f472002-04-21 12:19:41 +00002594 ensure_valgrind("poll");
2595
sewardj5f07b662002-04-23 16:52:51 +00002596 /* Detect the current time and simultaneously find out if we are
2597 running on Valgrind. */
2598 VALGRIND_MAGIC_SEQUENCE(ms_now, 0xFFFFFFFF /* default */,
2599 VG_USERREQ__READ_MILLISECOND_TIMER,
2600 0, 0, 0, 0);
2601
sewardjf854f472002-04-21 12:19:41 +00002602 if (/* CHECK SIZES FOR struct pollfd */
2603 sizeof(struct timeval) != sizeof(struct vki_timeval))
2604 barf("valgrind's hacky non-blocking poll(): data sizes error");
2605
sewardj5f07b662002-04-23 16:52:51 +00002606 /* dummy initialisation to keep gcc -Wall happy */
2607 ms_end = 0;
2608
2609 /* If a zero timeout specified, this call is harmless. Also do
2610 this if not running on Valgrind. */
2611 if (__timeout == 0 || ms_now == 0xFFFFFFFF) {
sewardjf854f472002-04-21 12:19:41 +00002612 res = my_do_syscall3(__NR_poll, (int)__fds, __nfds, __timeout);
2613 if (is_kerror(res)) {
2614 * (__errno_location()) = -res;
2615 return -1;
2616 } else {
2617 return res;
2618 }
2619 }
2620
sewardj5f07b662002-04-23 16:52:51 +00002621 /* If a timeout was specified, set ms_end to be the end wallclock
2622 time. Easy considering that __timeout is in milliseconds. */
sewardjf854f472002-04-21 12:19:41 +00002623 if (__timeout > 0) {
sewardj650ac002002-04-29 12:20:34 +00002624 ms_end = ms_now + (unsigned int)__timeout;
sewardjf854f472002-04-21 12:19:41 +00002625 }
2626
2627 /* fprintf(stderr, "MY_POLL: before loop\n"); */
2628
2629 /* Either timeout < 0, meaning wait indefinitely, or timeout > 0,
2630 in which case t_end holds the end time. */
sewardj05bb2c92002-06-26 00:47:17 +00002631
sewardj2d94c112002-06-03 01:25:54 +00002632 my_assert(__timeout != 0);
sewardj5f07b662002-04-23 16:52:51 +00002633
sewardjf854f472002-04-21 12:19:41 +00002634 while (1) {
sewardj05bb2c92002-06-26 00:47:17 +00002635
2636 /* Do a return-immediately poll. */
2637
2638 res = my_do_syscall3(__NR_poll, (int)__fds, __nfds, 0 );
2639 if (is_kerror(res)) {
2640 /* Some kind of error. Set errno and return. */
2641 * (__errno_location()) = -res;
2642 return -1;
2643 }
2644 if (res > 0) {
2645 /* One or more fds is ready. Return now. */
2646 return res;
2647 }
2648
2649 /* Nothing interesting happened, so we go to sleep for a
2650 while. */
2651
2652 /* fprintf(stderr, "MY_POLL: nanosleep\n"); */
2653 /* nanosleep and go round again */
2654 nanosleep_interval.tv_sec = 0;
njn25e49d8e72002-09-23 09:36:25 +00002655 nanosleep_interval.tv_nsec = 13 * 1000 * 1000; /* 13 milliseconds */
sewardj05bb2c92002-06-26 00:47:17 +00002656 /* It's critical here that valgrind's nanosleep implementation
2657 is nonblocking. */
2658 (void)my_do_syscall2(__NR_nanosleep,
2659 (int)(&nanosleep_interval), (int)NULL);
2660
2661 /* Sleeping finished. If a finite timeout, check to see if it
2662 has expired yet. */
sewardjf854f472002-04-21 12:19:41 +00002663 if (__timeout > 0) {
sewardj5f07b662002-04-23 16:52:51 +00002664 VALGRIND_MAGIC_SEQUENCE(ms_now, 0xFFFFFFFF /* default */,
2665 VG_USERREQ__READ_MILLISECOND_TIMER,
2666 0, 0, 0, 0);
sewardj2d94c112002-06-03 01:25:54 +00002667 my_assert(ms_now != 0xFFFFFFFF);
sewardj5f07b662002-04-23 16:52:51 +00002668 if (ms_now >= ms_end) {
sewardjf854f472002-04-21 12:19:41 +00002669 /* timeout; nothing interesting happened. */
2670 for (i = 0; i < __nfds; i++)
2671 __fds[i].revents = 0;
2672 return 0;
2673 }
2674 }
2675
sewardj08a4c3f2002-04-13 03:45:44 +00002676 }
2677}
sewardj3b13f0e2002-04-25 20:17:29 +00002678
2679
sewardj705d3cb2002-05-23 13:13:12 +00002680/* Helper function used to make accept() non-blocking. Idea is to use
2681 the above nonblocking poll() to make this thread ONLY wait for the
2682 specified fd to become ready, and then return. */
sewardjd1c1cf22002-06-26 00:13:36 +00002683
2684/* Sigh -- a hack. We're not supposed to include this file directly;
2685 should do it via /usr/include/fcntl.h, but that introduces a
2686 varargs prototype for fcntl itself, which we can't mimic. */
2687#define _FCNTL_H
2688#include <bits/fcntl.h>
2689
sewardj705d3cb2002-05-23 13:13:12 +00002690static void wait_for_fd_to_be_readable_or_erring ( int fd )
2691{
2692 struct pollfd pfd;
sewardjd1c1cf22002-06-26 00:13:36 +00002693 int res;
2694
sewardj6e6cbaa2002-05-24 02:12:52 +00002695 /* fprintf(stderr, "wait_for_fd_to_be_readable_or_erring %d\n", fd); */
sewardjd1c1cf22002-06-26 00:13:36 +00002696
2697 /* First check to see if the fd is nonblocking, and/or invalid. In
2698 either case return immediately. */
2699 res = __libc_fcntl(fd, F_GETFL, 0);
2700 if (res == -1) return; /* fd is invalid somehow */
2701 if (res & O_NONBLOCK) return; /* fd is nonblocking */
2702
2703 /* Ok, we'd better wait with poll. */
sewardj705d3cb2002-05-23 13:13:12 +00002704 pfd.fd = fd;
2705 pfd.events = POLLIN | POLLPRI | POLLERR | POLLHUP | POLLNVAL;
2706 /* ... but not POLLOUT, you may notice. */
2707 pfd.revents = 0;
2708 (void)poll(&pfd, 1, -1 /* forever */);
2709}
2710
sewardj2a68e7e2002-11-16 11:04:18 +00002711static void wait_for_fd_to_be_writable_or_erring ( int fd )
2712{
2713 struct pollfd pfd;
2714 int res;
2715
2716 /* fprintf(stderr, "wait_for_fd_to_be_readable_or_erring %d\n", fd); */
2717
2718 /* First check to see if the fd is nonblocking, and/or invalid. In
2719 either case return immediately. */
2720 res = __libc_fcntl(fd, F_GETFL, 0);
2721 if (res == -1) return; /* fd is invalid somehow */
2722 if (res & O_NONBLOCK) return; /* fd is nonblocking */
2723
2724 /* Ok, we'd better wait with poll. */
2725 pfd.fd = fd;
2726 pfd.events = POLLOUT | POLLERR | POLLHUP | POLLNVAL;
2727 pfd.revents = 0;
2728 (void)poll(&pfd, 1, -1 /* forever */);
2729}
sewardj705d3cb2002-05-23 13:13:12 +00002730
sewardj3b13f0e2002-04-25 20:17:29 +00002731/* ---------------------------------------------------------------------
sewardj8f253ff2002-05-19 00:13:34 +00002732 Hacky implementation of semaphores.
2733 ------------------------------------------------------------------ */
2734
2735#include <semaphore.h>
2736
2737/* This is a terrible way to do the remapping. Plan is to import an
2738 AVL tree at some point. */
sewardj8f253ff2002-05-19 00:13:34 +00002739
2740typedef
2741 struct {
2742 pthread_mutex_t se_mx;
2743 pthread_cond_t se_cv;
2744 int count;
2745 }
2746 vg_sem_t;
2747
2748static pthread_mutex_t se_remap_mx = PTHREAD_MUTEX_INITIALIZER;
2749
2750static int se_remap_used = 0;
2751static sem_t* se_remap_orig[VG_N_SEMAPHORES];
2752static vg_sem_t se_remap_new[VG_N_SEMAPHORES];
2753
2754static vg_sem_t* se_remap ( sem_t* orig )
2755{
2756 int res, i;
2757 res = __pthread_mutex_lock(&se_remap_mx);
sewardj2d94c112002-06-03 01:25:54 +00002758 my_assert(res == 0);
sewardj8f253ff2002-05-19 00:13:34 +00002759
2760 for (i = 0; i < se_remap_used; i++) {
2761 if (se_remap_orig[i] == orig)
2762 break;
2763 }
2764 if (i == se_remap_used) {
2765 if (se_remap_used == VG_N_SEMAPHORES) {
2766 res = pthread_mutex_unlock(&se_remap_mx);
sewardj2d94c112002-06-03 01:25:54 +00002767 my_assert(res == 0);
sewardja1ac5cb2002-05-27 13:00:05 +00002768 barf("VG_N_SEMAPHORES is too low. Increase and recompile.");
sewardj8f253ff2002-05-19 00:13:34 +00002769 }
2770 se_remap_used++;
2771 se_remap_orig[i] = orig;
2772 /* printf("allocated semaphore %d\n", i); */
2773 }
2774 res = __pthread_mutex_unlock(&se_remap_mx);
sewardj2d94c112002-06-03 01:25:54 +00002775 my_assert(res == 0);
sewardj8f253ff2002-05-19 00:13:34 +00002776 return &se_remap_new[i];
2777}
2778
2779
2780int sem_init(sem_t *sem, int pshared, unsigned int value)
2781{
2782 int res;
2783 vg_sem_t* vg_sem;
2784 ensure_valgrind("sem_init");
2785 if (pshared != 0) {
sewardj4dced352002-06-04 22:54:20 +00002786 pthread_error("sem_init: unsupported pshared value");
sewardj8f253ff2002-05-19 00:13:34 +00002787 errno = ENOSYS;
2788 return -1;
2789 }
2790 vg_sem = se_remap(sem);
2791 res = pthread_mutex_init(&vg_sem->se_mx, NULL);
sewardj2d94c112002-06-03 01:25:54 +00002792 my_assert(res == 0);
sewardj8f253ff2002-05-19 00:13:34 +00002793 res = pthread_cond_init(&vg_sem->se_cv, NULL);
sewardj2d94c112002-06-03 01:25:54 +00002794 my_assert(res == 0);
sewardj8f253ff2002-05-19 00:13:34 +00002795 vg_sem->count = value;
2796 return 0;
2797}
2798
2799
2800int sem_wait ( sem_t* sem )
2801{
2802 int res;
2803 vg_sem_t* vg_sem;
2804 ensure_valgrind("sem_wait");
2805 vg_sem = se_remap(sem);
2806 res = __pthread_mutex_lock(&vg_sem->se_mx);
sewardj2d94c112002-06-03 01:25:54 +00002807 my_assert(res == 0);
sewardj8f253ff2002-05-19 00:13:34 +00002808 while (vg_sem->count == 0) {
2809 res = pthread_cond_wait(&vg_sem->se_cv, &vg_sem->se_mx);
sewardj2d94c112002-06-03 01:25:54 +00002810 my_assert(res == 0);
sewardj8f253ff2002-05-19 00:13:34 +00002811 }
2812 vg_sem->count--;
2813 res = __pthread_mutex_unlock(&vg_sem->se_mx);
sewardj2d94c112002-06-03 01:25:54 +00002814 my_assert(res == 0);
sewardj8f253ff2002-05-19 00:13:34 +00002815 return 0;
2816}
2817
2818int sem_post ( sem_t* sem )
2819{
2820 int res;
2821 vg_sem_t* vg_sem;
2822 ensure_valgrind("sem_post");
2823 vg_sem = se_remap(sem);
2824 res = __pthread_mutex_lock(&vg_sem->se_mx);
sewardj2d94c112002-06-03 01:25:54 +00002825 my_assert(res == 0);
sewardj8f253ff2002-05-19 00:13:34 +00002826 if (vg_sem->count == 0) {
2827 vg_sem->count++;
2828 res = pthread_cond_broadcast(&vg_sem->se_cv);
sewardj2d94c112002-06-03 01:25:54 +00002829 my_assert(res == 0);
sewardj8f253ff2002-05-19 00:13:34 +00002830 } else {
2831 vg_sem->count++;
2832 }
2833 res = __pthread_mutex_unlock(&vg_sem->se_mx);
sewardj2d94c112002-06-03 01:25:54 +00002834 my_assert(res == 0);
sewardj8f253ff2002-05-19 00:13:34 +00002835 return 0;
2836}
2837
2838
2839int sem_trywait ( sem_t* sem )
2840{
2841 int ret, res;
2842 vg_sem_t* vg_sem;
2843 ensure_valgrind("sem_trywait");
2844 vg_sem = se_remap(sem);
2845 res = __pthread_mutex_lock(&vg_sem->se_mx);
sewardj2d94c112002-06-03 01:25:54 +00002846 my_assert(res == 0);
sewardj8f253ff2002-05-19 00:13:34 +00002847 if (vg_sem->count > 0) {
2848 vg_sem->count--;
2849 ret = 0;
2850 } else {
2851 ret = -1;
2852 errno = EAGAIN;
2853 }
2854 res = __pthread_mutex_unlock(&vg_sem->se_mx);
sewardj2d94c112002-06-03 01:25:54 +00002855 my_assert(res == 0);
sewardj8f253ff2002-05-19 00:13:34 +00002856 return ret;
2857}
2858
2859
2860int sem_getvalue(sem_t* sem, int * sval)
2861{
2862 vg_sem_t* vg_sem;
2863 ensure_valgrind("sem_trywait");
2864 vg_sem = se_remap(sem);
2865 *sval = vg_sem->count;
2866 return 0;
2867}
2868
2869
2870int sem_destroy(sem_t * sem)
2871{
2872 kludged("sem_destroy");
2873 /* if someone waiting on this semaphore, errno = EBUSY, return -1 */
2874 return 0;
2875}
2876
sewardj9ad92d92002-10-16 19:45:06 +00002877
2878int sem_timedwait(sem_t* sem, const struct timespec *abstime)
2879{
2880 int res;
2881 vg_sem_t* vg_sem;
2882 ensure_valgrind("sem_timedwait");
2883 vg_sem = se_remap(sem);
2884 res = __pthread_mutex_lock(&vg_sem->se_mx);
2885 my_assert(res == 0);
2886 while ( vg_sem->count == 0 && res != ETIMEDOUT ) {
2887 res = pthread_cond_timedwait(&vg_sem->se_cv, &vg_sem->se_mx, abstime);
2888 }
2889 if ( vg_sem->count > 0 ) {
2890 vg_sem->count--;
2891 res = __pthread_mutex_unlock(&vg_sem->se_mx);
2892 my_assert(res == 0 );
2893 return 0;
2894 } else {
2895 res = __pthread_mutex_unlock(&vg_sem->se_mx);
2896 my_assert(res == 0 );
2897 *(__errno_location()) = ETIMEDOUT;
2898 return -1;
2899 }
2900}
2901
sewardj8f253ff2002-05-19 00:13:34 +00002902
2903/* ---------------------------------------------------------------------
sewardj2d8b3f02002-06-01 14:14:19 +00002904 Reader-writer locks.
sewardja1ac5cb2002-05-27 13:00:05 +00002905 ------------------------------------------------------------------ */
2906
sewardj2d8b3f02002-06-01 14:14:19 +00002907typedef
2908 struct {
2909 int initted; /* != 0 --> in use; sanity check only */
2910 int prefer_w; /* != 0 --> prefer writer */
2911 int nwait_r; /* # of waiting readers */
2912 int nwait_w; /* # of waiting writers */
2913 pthread_cond_t cv_r; /* for signalling readers */
2914 pthread_cond_t cv_w; /* for signalling writers */
2915 pthread_mutex_t mx;
2916 int status;
2917 /* allowed range for status: >= -1. -1 means 1 writer currently
2918 active, >= 0 means N readers currently active. */
2919 }
2920 vg_rwlock_t;
sewardja1ac5cb2002-05-27 13:00:05 +00002921
2922
2923static pthread_mutex_t rw_remap_mx = PTHREAD_MUTEX_INITIALIZER;
2924
2925static int rw_remap_used = 0;
2926static pthread_rwlock_t* rw_remap_orig[VG_N_RWLOCKS];
2927static vg_rwlock_t rw_remap_new[VG_N_RWLOCKS];
2928
sewardj2d8b3f02002-06-01 14:14:19 +00002929
2930static
2931void init_vg_rwlock ( vg_rwlock_t* vg_rwl )
2932{
2933 int res = 0;
2934 vg_rwl->initted = 1;
2935 vg_rwl->prefer_w = 1;
2936 vg_rwl->nwait_r = 0;
2937 vg_rwl->nwait_w = 0;
2938 vg_rwl->status = 0;
2939 res = pthread_mutex_init(&vg_rwl->mx, NULL);
2940 res |= pthread_cond_init(&vg_rwl->cv_r, NULL);
2941 res |= pthread_cond_init(&vg_rwl->cv_w, NULL);
sewardj2d94c112002-06-03 01:25:54 +00002942 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002943}
2944
2945
sewardja1ac5cb2002-05-27 13:00:05 +00002946/* Take the address of a LinuxThreads rwlock_t and return the shadow
2947 address of our version. Further, if the LinuxThreads version
2948 appears to have been statically initialised, do the same to the one
2949 we allocate here. The pthread_rwlock_t.__rw_readers field is set
2950 to zero by PTHREAD_RWLOCK_INITIALIZER, so we take zero as meaning
2951 uninitialised and non-zero meaning initialised.
2952*/
2953static vg_rwlock_t* rw_remap ( pthread_rwlock_t* orig )
2954{
2955 int res, i;
2956 vg_rwlock_t* vg_rwl;
2957 res = __pthread_mutex_lock(&rw_remap_mx);
sewardj2d94c112002-06-03 01:25:54 +00002958 my_assert(res == 0);
sewardja1ac5cb2002-05-27 13:00:05 +00002959
2960 for (i = 0; i < rw_remap_used; i++) {
2961 if (rw_remap_orig[i] == orig)
2962 break;
2963 }
2964 if (i == rw_remap_used) {
2965 if (rw_remap_used == VG_N_RWLOCKS) {
sewardj2d8b3f02002-06-01 14:14:19 +00002966 res = __pthread_mutex_unlock(&rw_remap_mx);
sewardj2d94c112002-06-03 01:25:54 +00002967 my_assert(res == 0);
sewardja1ac5cb2002-05-27 13:00:05 +00002968 barf("VG_N_RWLOCKS is too low. Increase and recompile.");
2969 }
2970 rw_remap_used++;
2971 rw_remap_orig[i] = orig;
sewardj2d8b3f02002-06-01 14:14:19 +00002972 rw_remap_new[i].initted = 0;
sewardja1ac5cb2002-05-27 13:00:05 +00002973 if (0) printf("allocated rwlock %d\n", i);
2974 }
2975 res = __pthread_mutex_unlock(&rw_remap_mx);
sewardj2d94c112002-06-03 01:25:54 +00002976 my_assert(res == 0);
sewardja1ac5cb2002-05-27 13:00:05 +00002977 vg_rwl = &rw_remap_new[i];
2978
sewardj2d8b3f02002-06-01 14:14:19 +00002979 /* Initialise the shadow, if required. */
sewardja1ac5cb2002-05-27 13:00:05 +00002980 if (orig->__rw_readers == 0) {
sewardja1ac5cb2002-05-27 13:00:05 +00002981 orig->__rw_readers = 1;
sewardj2d8b3f02002-06-01 14:14:19 +00002982 init_vg_rwlock(vg_rwl);
sewardja1ac5cb2002-05-27 13:00:05 +00002983 if (orig->__rw_kind == PTHREAD_RWLOCK_PREFER_READER_NP)
sewardj2d8b3f02002-06-01 14:14:19 +00002984 vg_rwl->prefer_w = 0;
sewardja1ac5cb2002-05-27 13:00:05 +00002985 }
2986
2987 return vg_rwl;
2988}
2989
2990
sewardja1ac5cb2002-05-27 13:00:05 +00002991int pthread_rwlock_init ( pthread_rwlock_t* orig,
2992 const pthread_rwlockattr_t* attr )
2993{
sewardja1ac5cb2002-05-27 13:00:05 +00002994 vg_rwlock_t* rwl;
2995 if (0) printf ("pthread_rwlock_init\n");
2996 /* Force the remapper to initialise the shadow. */
2997 orig->__rw_readers = 0;
2998 /* Install the lock preference; the remapper needs to know it. */
2999 orig->__rw_kind = PTHREAD_RWLOCK_DEFAULT_NP;
3000 if (attr)
3001 orig->__rw_kind = attr->__lockkind;
3002 rwl = rw_remap ( orig );
sewardj2d8b3f02002-06-01 14:14:19 +00003003 return 0;
sewardja1ac5cb2002-05-27 13:00:05 +00003004}
3005
sewardj2d8b3f02002-06-01 14:14:19 +00003006
3007static
3008void pthread_rwlock_rdlock_CANCEL_HDLR ( void* rwl_v )
sewardja1ac5cb2002-05-27 13:00:05 +00003009{
sewardj2d8b3f02002-06-01 14:14:19 +00003010 vg_rwlock_t* rwl = (vg_rwlock_t*)rwl_v;
3011 rwl->nwait_r--;
3012 pthread_mutex_unlock (&rwl->mx);
sewardja1ac5cb2002-05-27 13:00:05 +00003013}
3014
sewardj2d8b3f02002-06-01 14:14:19 +00003015
sewardja1ac5cb2002-05-27 13:00:05 +00003016int pthread_rwlock_rdlock ( pthread_rwlock_t* orig )
3017{
3018 int res;
3019 vg_rwlock_t* rwl;
3020 if (0) printf ("pthread_rwlock_rdlock\n");
3021 rwl = rw_remap ( orig );
sewardj2d8b3f02002-06-01 14:14:19 +00003022 res = __pthread_mutex_lock(&rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00003023 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00003024 if (!rwl->initted) {
3025 res = __pthread_mutex_unlock(&rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00003026 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00003027 return EINVAL;
3028 }
3029 if (rwl->status < 0) {
sewardj2d94c112002-06-03 01:25:54 +00003030 my_assert(rwl->status == -1);
sewardj2d8b3f02002-06-01 14:14:19 +00003031 rwl->nwait_r++;
3032 pthread_cleanup_push( pthread_rwlock_rdlock_CANCEL_HDLR, rwl );
3033 while (1) {
3034 if (rwl->status == 0) break;
3035 res = pthread_cond_wait(&rwl->cv_r, &rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00003036 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00003037 }
3038 pthread_cleanup_pop(0);
3039 rwl->nwait_r--;
3040 }
sewardj2d94c112002-06-03 01:25:54 +00003041 my_assert(rwl->status >= 0);
sewardj2d8b3f02002-06-01 14:14:19 +00003042 rwl->status++;
3043 res = __pthread_mutex_unlock(&rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00003044 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00003045 return 0;
sewardja1ac5cb2002-05-27 13:00:05 +00003046}
3047
sewardj2d8b3f02002-06-01 14:14:19 +00003048
sewardja1ac5cb2002-05-27 13:00:05 +00003049int pthread_rwlock_tryrdlock ( pthread_rwlock_t* orig )
3050{
3051 int res;
3052 vg_rwlock_t* rwl;
3053 if (0) printf ("pthread_rwlock_tryrdlock\n");
3054 rwl = rw_remap ( orig );
sewardj2d8b3f02002-06-01 14:14:19 +00003055 res = __pthread_mutex_lock(&rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00003056 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00003057 if (!rwl->initted) {
3058 res = __pthread_mutex_unlock(&rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00003059 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00003060 return EINVAL;
3061 }
3062 if (rwl->status == -1) {
3063 /* Writer active; we have to give up. */
3064 res = __pthread_mutex_unlock(&rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00003065 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00003066 return EBUSY;
3067 }
3068 /* Success */
sewardj2d94c112002-06-03 01:25:54 +00003069 my_assert(rwl->status >= 0);
sewardj2d8b3f02002-06-01 14:14:19 +00003070 rwl->status++;
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 0;
sewardja1ac5cb2002-05-27 13:00:05 +00003074}
3075
sewardj2d8b3f02002-06-01 14:14:19 +00003076
3077static
3078void pthread_rwlock_wrlock_CANCEL_HDLR ( void* rwl_v )
3079{
3080 vg_rwlock_t* rwl = (vg_rwlock_t*)rwl_v;
3081 rwl->nwait_w--;
3082 pthread_mutex_unlock (&rwl->mx);
3083}
3084
3085
sewardja1ac5cb2002-05-27 13:00:05 +00003086int pthread_rwlock_wrlock ( pthread_rwlock_t* orig )
3087{
3088 int res;
3089 vg_rwlock_t* rwl;
3090 if (0) printf ("pthread_rwlock_wrlock\n");
3091 rwl = rw_remap ( orig );
sewardj2d8b3f02002-06-01 14:14:19 +00003092 res = __pthread_mutex_lock(&rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00003093 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00003094 if (!rwl->initted) {
3095 res = __pthread_mutex_unlock(&rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00003096 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00003097 return EINVAL;
3098 }
3099 if (rwl->status != 0) {
3100 rwl->nwait_w++;
3101 pthread_cleanup_push( pthread_rwlock_wrlock_CANCEL_HDLR, rwl );
3102 while (1) {
3103 if (rwl->status == 0) break;
3104 res = pthread_cond_wait(&rwl->cv_w, &rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00003105 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00003106 }
3107 pthread_cleanup_pop(0);
3108 rwl->nwait_w--;
3109 }
sewardj2d94c112002-06-03 01:25:54 +00003110 my_assert(rwl->status == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00003111 rwl->status = -1;
3112 res = __pthread_mutex_unlock(&rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00003113 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00003114 return 0;
sewardja1ac5cb2002-05-27 13:00:05 +00003115}
3116
sewardj2d8b3f02002-06-01 14:14:19 +00003117
sewardja1ac5cb2002-05-27 13:00:05 +00003118int pthread_rwlock_trywrlock ( pthread_rwlock_t* orig )
3119{
3120 int res;
3121 vg_rwlock_t* rwl;
sewardj2d8b3f02002-06-01 14:14:19 +00003122 if (0) printf ("pthread_wrlock_trywrlock\n");
sewardja1ac5cb2002-05-27 13:00:05 +00003123 rwl = rw_remap ( orig );
sewardj2d8b3f02002-06-01 14:14:19 +00003124 res = __pthread_mutex_lock(&rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00003125 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00003126 if (!rwl->initted) {
3127 res = __pthread_mutex_unlock(&rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00003128 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00003129 return EINVAL;
3130 }
3131 if (rwl->status != 0) {
3132 /* Reader(s) or a writer active; we have to give up. */
3133 res = __pthread_mutex_unlock(&rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00003134 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00003135 return EBUSY;
3136 }
3137 /* Success */
sewardj2d94c112002-06-03 01:25:54 +00003138 my_assert(rwl->status == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00003139 rwl->status = -1;
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 0;
sewardja1ac5cb2002-05-27 13:00:05 +00003143}
3144
sewardj2d8b3f02002-06-01 14:14:19 +00003145
sewardja1ac5cb2002-05-27 13:00:05 +00003146int pthread_rwlock_unlock ( pthread_rwlock_t* orig )
3147{
3148 int res;
3149 vg_rwlock_t* rwl;
3150 if (0) printf ("pthread_rwlock_unlock\n");
3151 rwl = rw_remap ( orig );
sewardj2d8b3f02002-06-01 14:14:19 +00003152 rwl = rw_remap ( orig );
3153 res = __pthread_mutex_lock(&rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00003154 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00003155 if (!rwl->initted) {
3156 res = __pthread_mutex_unlock(&rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00003157 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00003158 return EINVAL;
3159 }
3160 if (rwl->status == 0) {
3161 res = __pthread_mutex_unlock(&rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00003162 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00003163 return EPERM;
3164 }
sewardj2d94c112002-06-03 01:25:54 +00003165 my_assert(rwl->status != 0);
sewardj2d8b3f02002-06-01 14:14:19 +00003166 if (rwl->status == -1) {
3167 rwl->status = 0;
3168 } else {
sewardj2d94c112002-06-03 01:25:54 +00003169 my_assert(rwl->status > 0);
sewardj2d8b3f02002-06-01 14:14:19 +00003170 rwl->status--;
3171 }
3172
sewardj2d94c112002-06-03 01:25:54 +00003173 my_assert(rwl->status >= 0);
sewardj2d8b3f02002-06-01 14:14:19 +00003174
3175 if (rwl->prefer_w) {
3176
3177 /* Favour waiting writers, if any. */
3178 if (rwl->nwait_w > 0) {
3179 /* Writer(s) are waiting. */
3180 if (rwl->status == 0) {
3181 /* We can let a writer in. */
3182 res = pthread_cond_signal(&rwl->cv_w);
sewardj2d94c112002-06-03 01:25:54 +00003183 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00003184 } else {
3185 /* There are still readers active. Do nothing; eventually
3186 they will disappear, at which point a writer will be
3187 admitted. */
3188 }
3189 }
3190 else
3191 /* No waiting writers. */
3192 if (rwl->nwait_r > 0) {
3193 /* Let in a waiting reader. */
3194 res = pthread_cond_signal(&rwl->cv_r);
sewardj2d94c112002-06-03 01:25:54 +00003195 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00003196 }
3197
3198 } else {
3199
3200 /* Favour waiting readers, if any. */
3201 if (rwl->nwait_r > 0) {
3202 /* Reader(s) are waiting; let one in. */
3203 res = pthread_cond_signal(&rwl->cv_r);
sewardj2d94c112002-06-03 01:25:54 +00003204 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00003205 }
3206 else
3207 /* No waiting readers. */
3208 if (rwl->nwait_w > 0 && rwl->status == 0) {
3209 /* We have waiting writers and no active readers; let a
3210 writer in. */
3211 res = pthread_cond_signal(&rwl->cv_w);
sewardj2d94c112002-06-03 01:25:54 +00003212 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00003213 }
3214 }
3215
3216 res = __pthread_mutex_unlock(&rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00003217 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00003218 return 0;
3219}
3220
3221
3222int pthread_rwlock_destroy ( pthread_rwlock_t *orig )
3223{
3224 int res;
3225 vg_rwlock_t* rwl;
3226 if (0) printf ("pthread_rwlock_destroy\n");
3227 rwl = rw_remap ( orig );
3228 res = __pthread_mutex_lock(&rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00003229 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00003230 if (!rwl->initted) {
3231 res = __pthread_mutex_unlock(&rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00003232 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00003233 return EINVAL;
3234 }
3235 if (rwl->status != 0 || rwl->nwait_r > 0 || rwl->nwait_w > 0) {
3236 res = __pthread_mutex_unlock(&rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00003237 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00003238 return EBUSY;
3239 }
3240 rwl->initted = 0;
3241 res = __pthread_mutex_unlock(&rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00003242 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00003243 return 0;
sewardja1ac5cb2002-05-27 13:00:05 +00003244}
3245
3246
sewardj47e4e312002-06-18 09:24:34 +00003247/* Copied directly from LinuxThreads. */
3248int
3249pthread_rwlockattr_init (pthread_rwlockattr_t *attr)
3250{
3251 attr->__lockkind = 0;
3252 attr->__pshared = PTHREAD_PROCESS_PRIVATE;
3253
3254 return 0;
3255}
3256
sewardjfe18eb82002-07-13 12:58:44 +00003257/* Copied directly from LinuxThreads. */
3258int
sewardj5706bfa2002-12-08 23:42:17 +00003259pthread_rwlockattr_destroy (pthread_rwlockattr_t *attr)
3260{
3261 return 0;
3262}
3263
3264/* Copied directly from LinuxThreads. */
3265int
sewardjfe18eb82002-07-13 12:58:44 +00003266pthread_rwlockattr_setpshared (pthread_rwlockattr_t *attr, int pshared)
3267{
3268 if (pshared != PTHREAD_PROCESS_PRIVATE && pshared != PTHREAD_PROCESS_SHARED)
3269 return EINVAL;
3270
3271 /* For now it is not possible to shared a conditional variable. */
3272 if (pshared != PTHREAD_PROCESS_PRIVATE)
3273 return ENOSYS;
3274
3275 attr->__pshared = pshared;
3276
3277 return 0;
3278}
3279
sewardj47e4e312002-06-18 09:24:34 +00003280
sewardja1ac5cb2002-05-27 13:00:05 +00003281/* ---------------------------------------------------------------------
sewardjd5bef572002-10-23 21:49:33 +00003282 Make SYSV IPC not block everything
3283 ------------------------------------------------------------------ */
3284
3285#include <sys/ipc.h>
3286#include <sys/msg.h>
3287#include <asm/ipc.h> /* for ipc_kludge */
3288
3289static inline int sys_ipc(unsigned call, int first, int second, int third, void *ptr)
3290{
3291 return my_do_syscall5(__NR_ipc, call, first, second, third, (int)ptr);
3292}
3293
3294/* Turn a blocking msgsnd() into a polling non-blocking one, so that
3295 other threads make progress */
sewardjf220ccc2002-10-23 21:53:49 +00003296int VGL_(msgsnd)(int msgid, const void *msgp, size_t msgsz, int msgflg)
sewardjd5bef572002-10-23 21:49:33 +00003297{
3298 struct vki_timespec nanosleep_interval;
3299 int err;
3300
3301 ensure_valgrind("msgsnd");
3302
3303 nanosleep_interval.tv_sec = 0;
3304 nanosleep_interval.tv_nsec = 13 * 1000 * 1000; /* 13 milliseconds */
3305
3306 if (msgflg & IPC_NOWAIT) {
3307 /* If we aren't blocking anyway, just do it */
3308 err = sys_ipc(11, msgid, msgsz, msgflg, (void *)msgp);
3309 } else {
3310 /* Otherwise poll on the queue to let other things run */
3311 for(;;) {
3312 err = sys_ipc(11, msgid, msgsz, msgflg | IPC_NOWAIT, (void *)msgp);
3313
3314 if (err != -EAGAIN)
3315 break;
3316
3317 (void)my_do_syscall2(__NR_nanosleep,
3318 (int)(&nanosleep_interval), (int)NULL);
3319 }
3320 }
3321
3322 if (is_kerror(err)) {
3323 *(__errno_location()) = -err;
3324 return -1;
3325 }
3326 return 0;
3327}
3328
3329/* Turn a blocking msgrcv() into a polling non-blocking one, so that
3330 other threads make progress */
sewardjf220ccc2002-10-23 21:53:49 +00003331int VGL_(msgrcv)( int msqid, void *msgp, size_t msgsz, long msgtyp, int msgflg )
sewardjd5bef572002-10-23 21:49:33 +00003332{
3333 struct vki_timespec nanosleep_interval;
3334 int err;
3335 struct ipc_kludge tmp;
3336
3337 ensure_valgrind("msgrcv");
3338
3339 nanosleep_interval.tv_sec = 0;
3340 nanosleep_interval.tv_nsec = 13 * 1000 * 1000; /* 13 milliseconds */
3341
3342 tmp.msgp = msgp;
3343 tmp.msgtyp = msgtyp;
3344
3345 if (msgflg & IPC_NOWAIT) {
3346 /* If we aren't blocking anyway, just do it */
3347 err = sys_ipc(12, msqid, msgsz, msgflg, &tmp );
3348 } else {
3349 /* Otherwise poll on the queue to let other things run */
3350 for(;;) {
3351 err = sys_ipc(12, msqid, msgsz, msgflg | IPC_NOWAIT, &tmp );
3352
3353 if (err != -ENOMSG)
3354 break;
3355
3356 (void)my_do_syscall2(__NR_nanosleep,
3357 (int)(&nanosleep_interval), (int)NULL);
3358 }
3359 }
3360
3361 if (is_kerror(err)) {
3362 *(__errno_location()) = -err;
3363 return -1;
3364 }
3365
3366 return 0;
3367}
3368
3369
3370
3371/* ---------------------------------------------------------------------
sewardj3b13f0e2002-04-25 20:17:29 +00003372 B'stard.
3373 ------------------------------------------------------------------ */
3374
3375# define strong_alias(name, aliasname) \
3376 extern __typeof (name) aliasname __attribute__ ((alias (#name)));
3377
sewardj5905fae2002-04-26 13:25:00 +00003378# define weak_alias(name, aliasname) \
3379 extern __typeof (name) aliasname __attribute__ ((weak, alias (#name)));
sewardj3b13f0e2002-04-25 20:17:29 +00003380
sewardj5905fae2002-04-26 13:25:00 +00003381strong_alias(__pthread_mutex_lock, pthread_mutex_lock)
3382strong_alias(__pthread_mutex_trylock, pthread_mutex_trylock)
3383strong_alias(__pthread_mutex_unlock, pthread_mutex_unlock)
3384strong_alias(__pthread_mutexattr_init, pthread_mutexattr_init)
3385 weak_alias(__pthread_mutexattr_settype, pthread_mutexattr_settype)
3386strong_alias(__pthread_mutex_init, pthread_mutex_init)
3387strong_alias(__pthread_mutexattr_destroy, pthread_mutexattr_destroy)
3388strong_alias(__pthread_mutex_destroy, pthread_mutex_destroy)
3389strong_alias(__pthread_once, pthread_once)
3390strong_alias(__pthread_atfork, pthread_atfork)
3391strong_alias(__pthread_key_create, pthread_key_create)
3392strong_alias(__pthread_getspecific, pthread_getspecific)
3393strong_alias(__pthread_setspecific, pthread_setspecific)
3394
sewardjd529a442002-05-04 19:49:21 +00003395#ifndef GLIBC_2_1
sewardj3b13f0e2002-04-25 20:17:29 +00003396strong_alias(sigaction, __sigaction)
sewardjd529a442002-05-04 19:49:21 +00003397#endif
3398
sewardj5905fae2002-04-26 13:25:00 +00003399strong_alias(close, __close)
sewardj3b13f0e2002-04-25 20:17:29 +00003400strong_alias(fcntl, __fcntl)
sewardj5905fae2002-04-26 13:25:00 +00003401strong_alias(lseek, __lseek)
3402strong_alias(open, __open)
3403strong_alias(open64, __open64)
sewardj5905fae2002-04-26 13:25:00 +00003404strong_alias(read, __read)
3405strong_alias(wait, __wait)
3406strong_alias(write, __write)
sewardj3b13f0e2002-04-25 20:17:29 +00003407strong_alias(connect, __connect)
sewardj5905fae2002-04-26 13:25:00 +00003408strong_alias(send, __send)
3409
sewardj726c4122002-05-16 23:39:10 +00003410weak_alias (__pread64, pread64)
sewardja18e2102002-05-18 10:43:22 +00003411weak_alias (__pwrite64, pwrite64)
sewardj5905fae2002-04-26 13:25:00 +00003412weak_alias(__fork, fork)
njn25e49d8e72002-09-23 09:36:25 +00003413weak_alias(__vfork, vfork)
sewardj7f6456d2002-05-21 00:51:21 +00003414
sewardjf0b06452002-06-04 08:38:04 +00003415weak_alias (__pthread_kill_other_threads_np, pthread_kill_other_threads_np)
sewardj3b13f0e2002-04-25 20:17:29 +00003416
3417/*--------------------------------------------------*/
3418
sewardj5905fae2002-04-26 13:25:00 +00003419weak_alias(pthread_rwlock_rdlock, __pthread_rwlock_rdlock)
sewardj5905fae2002-04-26 13:25:00 +00003420weak_alias(pthread_rwlock_unlock, __pthread_rwlock_unlock)
sewardj262b0292002-05-01 00:03:16 +00003421weak_alias(pthread_rwlock_wrlock, __pthread_rwlock_wrlock)
sewardj060b04f2002-04-26 21:01:13 +00003422
sewardja1ac5cb2002-05-27 13:00:05 +00003423weak_alias(pthread_rwlock_destroy, __pthread_rwlock_destroy)
3424weak_alias(pthread_rwlock_init, __pthread_rwlock_init)
3425weak_alias(pthread_rwlock_tryrdlock, __pthread_rwlock_tryrdlock)
3426weak_alias(pthread_rwlock_trywrlock, __pthread_rwlock_trywrlock)
3427
sewardj060b04f2002-04-26 21:01:13 +00003428
sewardj3b13f0e2002-04-25 20:17:29 +00003429/* I've no idea what these are, but they get called quite a lot.
3430 Anybody know? */
3431
3432#undef _IO_flockfile
3433void _IO_flockfile ( _IO_FILE * file )
3434{
sewardj853f55d2002-04-26 00:27:53 +00003435 pthread_mutex_lock(file->_lock);
sewardj3b13f0e2002-04-25 20:17:29 +00003436}
sewardj5905fae2002-04-26 13:25:00 +00003437weak_alias(_IO_flockfile, flockfile);
3438
sewardj3b13f0e2002-04-25 20:17:29 +00003439
3440#undef _IO_funlockfile
3441void _IO_funlockfile ( _IO_FILE * file )
3442{
sewardj853f55d2002-04-26 00:27:53 +00003443 pthread_mutex_unlock(file->_lock);
sewardj3b13f0e2002-04-25 20:17:29 +00003444}
sewardj5905fae2002-04-26 13:25:00 +00003445weak_alias(_IO_funlockfile, funlockfile);
3446
sewardj3b13f0e2002-04-25 20:17:29 +00003447
sewardjd4f2c712002-04-30 10:20:10 +00003448/* This doesn't seem to be needed to simulate libpthread.so's external
3449 interface, but many people complain about its absence. */
3450
3451strong_alias(__pthread_mutexattr_settype, __pthread_mutexattr_setkind_np)
3452weak_alias(__pthread_mutexattr_setkind_np, pthread_mutexattr_setkind_np)
sewardj439d45e2002-05-03 20:43:10 +00003453
3454
3455/*--------------------------------------------------------------------*/
3456/*--- end vg_libpthread.c ---*/
3457/*--------------------------------------------------------------------*/