blob: 8904c62f151c84badc6e1632e0480bee32e68fca [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
516
sewardj20917d82002-05-28 01:36:45 +0000517/* ---------------------------------------------------
518 Helper functions for running a thread
519 and for clearing up afterwards.
520 ------------------------------------------------ */
521
522/* All exiting threads eventually pass through here, bearing the
523 return value, or PTHREAD_CANCELED, in ret_val. */
524static
525__attribute__((noreturn))
526void thread_exit_wrapper ( void* ret_val )
527{
sewardj870497a2002-05-29 01:06:47 +0000528 int detached, res;
529 CleanupEntry cu;
530 pthread_key_t key;
sewardj00a66b12002-10-12 16:42:35 +0000531 void** specifics_ptr;
sewardj870497a2002-05-29 01:06:47 +0000532
sewardj20917d82002-05-28 01:36:45 +0000533 /* Run this thread's cleanup handlers. */
sewardj8ad94e12002-05-29 00:10:20 +0000534 while (1) {
535 VALGRIND_MAGIC_SEQUENCE(res, (-1) /* default */,
536 VG_USERREQ__CLEANUP_POP,
537 &cu, 0, 0, 0);
538 if (res == -1) break; /* stack empty */
sewardj2d94c112002-06-03 01:25:54 +0000539 my_assert(res == 0);
sewardj8ad94e12002-05-29 00:10:20 +0000540 if (0) printf("running exit cleanup handler");
541 cu.fn ( cu.arg );
542 }
543
sewardj870497a2002-05-29 01:06:47 +0000544 /* Run this thread's key finalizers. Really this should be run
545 PTHREAD_DESTRUCTOR_ITERATIONS times. */
546 for (key = 0; key < VG_N_THREAD_KEYS; key++) {
547 VALGRIND_MAGIC_SEQUENCE(res, (-2) /* default */,
548 VG_USERREQ__GET_KEY_D_AND_S,
549 key, &cu, 0, 0 );
550 if (res == 0) {
551 /* valid key */
552 if (cu.fn && cu.arg)
553 cu.fn /* destructor for key */
554 ( cu.arg /* specific for key for this thread */ );
555 continue;
556 }
sewardj2d94c112002-06-03 01:25:54 +0000557 my_assert(res == -1);
sewardj870497a2002-05-29 01:06:47 +0000558 }
sewardj20917d82002-05-28 01:36:45 +0000559
sewardj00a66b12002-10-12 16:42:35 +0000560 /* Free up my specifics space, if any. */
561 VALGRIND_MAGIC_SEQUENCE(specifics_ptr, 3 /* default */,
562 VG_USERREQ__PTHREAD_GETSPECIFIC_PTR,
563 pthread_self(), 0, 0, 0);
564 my_assert(specifics_ptr != (void**)3);
565 my_assert(specifics_ptr != (void**)1); /* 1 means invalid thread */
566 if (specifics_ptr != NULL)
567 my_free(specifics_ptr);
568
sewardj20917d82002-05-28 01:36:45 +0000569 /* Decide on my final disposition. */
570 VALGRIND_MAGIC_SEQUENCE(detached, (-1) /* default */,
571 VG_USERREQ__SET_OR_GET_DETACH,
sewardj7989d0c2002-05-28 11:00:01 +0000572 2 /* get */, pthread_self(), 0, 0);
sewardj2d94c112002-06-03 01:25:54 +0000573 my_assert(detached == 0 || detached == 1);
sewardj20917d82002-05-28 01:36:45 +0000574
575 if (detached) {
576 /* Detached; I just quit right now. */
577 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
578 VG_USERREQ__QUIT, 0, 0, 0, 0);
579 } else {
580 /* Not detached; so I wait for a joiner. */
581 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
582 VG_USERREQ__WAIT_JOINER, ret_val, 0, 0, 0);
583 }
584 /* NOTREACHED */
585 barf("thread_exit_wrapper: still alive?!");
586}
587
588
589/* This function is a wrapper function for running a thread. It runs
590 the root function specified in pthread_create, and then, should the
591 root function return a value, it arranges to run the thread's
592 cleanup handlers and exit correctly. */
593
sewardj728a5272002-06-20 10:25:37 +0000594/* Struct used to convey info from pthread_create to thread_wrapper.
595 Must be careful not to pass to the child thread any pointers to
596 objects which might be on the parent's stack. */
sewardj20917d82002-05-28 01:36:45 +0000597typedef
598 struct {
sewardj728a5272002-06-20 10:25:37 +0000599 int attr__detachstate;
sewardj20917d82002-05-28 01:36:45 +0000600 void* (*root_fn) ( void* );
601 void* arg;
602 }
603 NewThreadInfo;
604
605
606/* This is passed to the VG_USERREQ__APPLY_IN_NEW_THREAD and so must
607 not return. Note that this runs in the new thread, not the
608 parent. */
609static
610__attribute__((noreturn))
611void thread_wrapper ( NewThreadInfo* info )
612{
sewardj728a5272002-06-20 10:25:37 +0000613 int attr__detachstate;
sewardj20917d82002-05-28 01:36:45 +0000614 void* (*root_fn) ( void* );
615 void* arg;
616 void* ret_val;
617
sewardj728a5272002-06-20 10:25:37 +0000618 attr__detachstate = info->attr__detachstate;
619 root_fn = info->root_fn;
620 arg = info->arg;
sewardj20917d82002-05-28 01:36:45 +0000621
sewardj20917d82002-05-28 01:36:45 +0000622 /* Free up the arg block that pthread_create malloced. */
sewardj00a66b12002-10-12 16:42:35 +0000623 my_free(info);
sewardj20917d82002-05-28 01:36:45 +0000624
sewardj7989d0c2002-05-28 11:00:01 +0000625 /* Minimally observe the attributes supplied. */
sewardj728a5272002-06-20 10:25:37 +0000626 if (attr__detachstate != PTHREAD_CREATE_DETACHED
627 && attr__detachstate != PTHREAD_CREATE_JOINABLE)
628 pthread_error("thread_wrapper: invalid attr->__detachstate");
629 if (attr__detachstate == PTHREAD_CREATE_DETACHED)
630 pthread_detach(pthread_self());
sewardj7989d0c2002-05-28 11:00:01 +0000631
sewardj00a66b12002-10-12 16:42:35 +0000632# ifdef GLIBC_2_3
633 /* Set this thread's locale to the global (default) locale. A hack
634 in support of glibc-2.3. This does the biz for the all new
635 threads; the root thread is done with a horrible hack in
636 init_libc_tsd_keys() below.
637 */
638 __uselocale(LC_GLOBAL_LOCALE);
639# endif
640
sewardj20917d82002-05-28 01:36:45 +0000641 /* The root function might not return. But if it does we simply
642 move along to thread_exit_wrapper. All other ways out for the
643 thread (cancellation, or calling pthread_exit) lead there
644 too. */
645 ret_val = root_fn(arg);
646 thread_exit_wrapper(ret_val);
647 /* NOTREACHED */
648}
649
650
sewardjf8f819e2002-04-17 23:21:37 +0000651/* ---------------------------------------------------
652 THREADs
653 ------------------------------------------------ */
654
sewardjff42d1d2002-05-22 13:17:31 +0000655__attribute__((weak))
656int pthread_yield ( void )
657{
658 int res;
659 ensure_valgrind("pthread_yield");
660 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
661 VG_USERREQ__PTHREAD_YIELD, 0, 0, 0, 0);
662 return 0;
663}
664
665
sewardj6072c362002-04-19 14:40:57 +0000666int pthread_equal(pthread_t thread1, pthread_t thread2)
667{
668 return thread1 == thread2 ? 1 : 0;
669}
670
671
sewardj20917d82002-05-28 01:36:45 +0000672/* Bundle up the args into a malloc'd block and create a new thread
673 consisting of thread_wrapper() applied to said malloc'd block. */
sewardje663cb92002-04-12 10:26:32 +0000674int
sewardj1462c8b2002-07-24 09:41:52 +0000675pthread_create (pthread_t *__restrict __thredd,
sewardje663cb92002-04-12 10:26:32 +0000676 __const pthread_attr_t *__restrict __attr,
677 void *(*__start_routine) (void *),
678 void *__restrict __arg)
679{
sewardj20917d82002-05-28 01:36:45 +0000680 int tid_child;
681 NewThreadInfo* info;
sewardje663cb92002-04-12 10:26:32 +0000682
sewardj20917d82002-05-28 01:36:45 +0000683 ensure_valgrind("pthread_create");
684
sewardj00a66b12002-10-12 16:42:35 +0000685 /* make sure the tsd keys, and hence locale info, are initialised
686 before we get into complications making new threads. */
687 init_libc_tsd_keys();
688
sewardj20917d82002-05-28 01:36:45 +0000689 /* Allocate space for the arg block. thread_wrapper will free
690 it. */
sewardj00a66b12002-10-12 16:42:35 +0000691 info = my_malloc(sizeof(NewThreadInfo));
sewardj2d94c112002-06-03 01:25:54 +0000692 my_assert(info != NULL);
sewardj20917d82002-05-28 01:36:45 +0000693
sewardj728a5272002-06-20 10:25:37 +0000694 if (__attr)
695 info->attr__detachstate = __attr->__detachstate;
696 else
697 info->attr__detachstate = PTHREAD_CREATE_JOINABLE;
698
sewardj20917d82002-05-28 01:36:45 +0000699 info->root_fn = __start_routine;
700 info->arg = __arg;
701 VALGRIND_MAGIC_SEQUENCE(tid_child, VG_INVALID_THREADID /* default */,
702 VG_USERREQ__APPLY_IN_NEW_THREAD,
703 &thread_wrapper, info, 0, 0);
sewardj2d94c112002-06-03 01:25:54 +0000704 my_assert(tid_child != VG_INVALID_THREADID);
sewardj20917d82002-05-28 01:36:45 +0000705
sewardj1462c8b2002-07-24 09:41:52 +0000706 if (__thredd)
707 *__thredd = tid_child;
sewardj20917d82002-05-28 01:36:45 +0000708 return 0; /* success */
709}
sewardje663cb92002-04-12 10:26:32 +0000710
711
712int
713pthread_join (pthread_t __th, void **__thread_return)
714{
715 int res;
716 ensure_valgrind("pthread_join");
717 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
718 VG_USERREQ__PTHREAD_JOIN,
719 __th, __thread_return, 0, 0);
720 return res;
721}
722
723
sewardj3b5d8862002-04-20 13:53:23 +0000724void pthread_exit(void *retval)
725{
sewardj3b5d8862002-04-20 13:53:23 +0000726 ensure_valgrind("pthread_exit");
sewardj20917d82002-05-28 01:36:45 +0000727 /* Simple! */
728 thread_exit_wrapper(retval);
sewardj3b5d8862002-04-20 13:53:23 +0000729}
730
sewardje663cb92002-04-12 10:26:32 +0000731
sewardj853f55d2002-04-26 00:27:53 +0000732int pthread_detach(pthread_t th)
733{
sewardj20917d82002-05-28 01:36:45 +0000734 int res;
735 ensure_valgrind("pthread_detach");
sewardj7989d0c2002-05-28 11:00:01 +0000736 /* First we enquire as to the current detach state. */
737 VALGRIND_MAGIC_SEQUENCE(res, (-2) /* default */,
sewardj20917d82002-05-28 01:36:45 +0000738 VG_USERREQ__SET_OR_GET_DETACH,
sewardj7989d0c2002-05-28 11:00:01 +0000739 2 /* get */, th, 0, 0);
sewardj4dced352002-06-04 22:54:20 +0000740 if (res == -1) {
741 /* not found */
742 pthread_error("pthread_detach: "
743 "invalid target thread");
sewardj7989d0c2002-05-28 11:00:01 +0000744 return ESRCH;
sewardj4dced352002-06-04 22:54:20 +0000745 }
746 if (res == 1) {
747 /* already detached */
748 pthread_error("pthread_detach: "
749 "target thread is already detached");
sewardj7989d0c2002-05-28 11:00:01 +0000750 return EINVAL;
sewardj4dced352002-06-04 22:54:20 +0000751 }
sewardj7989d0c2002-05-28 11:00:01 +0000752 if (res == 0) {
753 VALGRIND_MAGIC_SEQUENCE(res, (-2) /* default */,
754 VG_USERREQ__SET_OR_GET_DETACH,
755 1 /* set */, th, 0, 0);
sewardj2d94c112002-06-03 01:25:54 +0000756 my_assert(res == 0);
sewardj7989d0c2002-05-28 11:00:01 +0000757 return 0;
758 }
759 barf("pthread_detach");
sewardj853f55d2002-04-26 00:27:53 +0000760}
761
762
sewardjf8f819e2002-04-17 23:21:37 +0000763/* ---------------------------------------------------
sewardj8ad94e12002-05-29 00:10:20 +0000764 CLEANUP STACKS
765 ------------------------------------------------ */
766
767void _pthread_cleanup_push (struct _pthread_cleanup_buffer *__buffer,
768 void (*__routine) (void *),
769 void *__arg)
770{
771 int res;
772 CleanupEntry cu;
773 ensure_valgrind("_pthread_cleanup_push");
774 cu.fn = __routine;
775 cu.arg = __arg;
776 VALGRIND_MAGIC_SEQUENCE(res, (-1) /* default */,
777 VG_USERREQ__CLEANUP_PUSH,
778 &cu, 0, 0, 0);
sewardj2d94c112002-06-03 01:25:54 +0000779 my_assert(res == 0);
sewardj8ad94e12002-05-29 00:10:20 +0000780}
781
782
783void _pthread_cleanup_push_defer (struct _pthread_cleanup_buffer *__buffer,
784 void (*__routine) (void *),
785 void *__arg)
786{
787 /* As _pthread_cleanup_push, but first save the thread's original
788 cancellation type in __buffer and set it to Deferred. */
789 int orig_ctype;
790 ensure_valgrind("_pthread_cleanup_push_defer");
791 /* Set to Deferred, and put the old cancellation type in res. */
sewardj2d94c112002-06-03 01:25:54 +0000792 my_assert(-1 != PTHREAD_CANCEL_DEFERRED);
793 my_assert(-1 != PTHREAD_CANCEL_ASYNCHRONOUS);
794 my_assert(sizeof(struct _pthread_cleanup_buffer) >= sizeof(int));
sewardj8ad94e12002-05-29 00:10:20 +0000795 VALGRIND_MAGIC_SEQUENCE(orig_ctype, (-1) /* default */,
796 VG_USERREQ__SET_CANCELTYPE,
797 PTHREAD_CANCEL_DEFERRED, 0, 0, 0);
sewardj2d94c112002-06-03 01:25:54 +0000798 my_assert(orig_ctype != -1);
sewardj8ad94e12002-05-29 00:10:20 +0000799 *((int*)(__buffer)) = orig_ctype;
800 /* Now push the cleanup. */
801 _pthread_cleanup_push(NULL, __routine, __arg);
802}
803
804
805void _pthread_cleanup_pop (struct _pthread_cleanup_buffer *__buffer,
806 int __execute)
807{
808 int res;
809 CleanupEntry cu;
810 ensure_valgrind("_pthread_cleanup_push");
811 cu.fn = cu.arg = NULL; /* paranoia */
812 VALGRIND_MAGIC_SEQUENCE(res, (-1) /* default */,
813 VG_USERREQ__CLEANUP_POP,
814 &cu, 0, 0, 0);
815 if (res == 0) {
816 /* pop succeeded */
817 if (__execute) {
818 cu.fn ( cu.arg );
819 }
820 return;
821 }
822 if (res == -1) {
823 /* stack underflow */
824 return;
825 }
826 barf("_pthread_cleanup_pop");
827}
828
829
830void _pthread_cleanup_pop_restore (struct _pthread_cleanup_buffer *__buffer,
831 int __execute)
832{
833 int orig_ctype, fake_ctype;
834 /* As _pthread_cleanup_pop, but after popping/running the handler,
835 restore the thread's original cancellation type from the first
836 word of __buffer. */
837 _pthread_cleanup_pop(NULL, __execute);
838 orig_ctype = *((int*)(__buffer));
sewardj2d94c112002-06-03 01:25:54 +0000839 my_assert(orig_ctype == PTHREAD_CANCEL_DEFERRED
sewardj8ad94e12002-05-29 00:10:20 +0000840 || orig_ctype == PTHREAD_CANCEL_ASYNCHRONOUS);
sewardj2d94c112002-06-03 01:25:54 +0000841 my_assert(-1 != PTHREAD_CANCEL_DEFERRED);
842 my_assert(-1 != PTHREAD_CANCEL_ASYNCHRONOUS);
843 my_assert(sizeof(struct _pthread_cleanup_buffer) >= sizeof(int));
sewardj8ad94e12002-05-29 00:10:20 +0000844 VALGRIND_MAGIC_SEQUENCE(fake_ctype, (-1) /* default */,
845 VG_USERREQ__SET_CANCELTYPE,
846 orig_ctype, 0, 0, 0);
sewardj2d94c112002-06-03 01:25:54 +0000847 my_assert(fake_ctype == PTHREAD_CANCEL_DEFERRED);
sewardj8ad94e12002-05-29 00:10:20 +0000848}
849
850
851/* ---------------------------------------------------
sewardjf8f819e2002-04-17 23:21:37 +0000852 MUTEX ATTRIBUTES
853 ------------------------------------------------ */
854
sewardj5905fae2002-04-26 13:25:00 +0000855int __pthread_mutexattr_init(pthread_mutexattr_t *attr)
sewardje663cb92002-04-12 10:26:32 +0000856{
sewardjf8f819e2002-04-17 23:21:37 +0000857 attr->__mutexkind = PTHREAD_MUTEX_ERRORCHECK_NP;
sewardj8937c812002-04-12 20:12:20 +0000858 return 0;
sewardje663cb92002-04-12 10:26:32 +0000859}
860
sewardj5905fae2002-04-26 13:25:00 +0000861int __pthread_mutexattr_settype(pthread_mutexattr_t *attr, int type)
sewardjf8f819e2002-04-17 23:21:37 +0000862{
863 switch (type) {
sewardj3b13f0e2002-04-25 20:17:29 +0000864# ifndef GLIBC_2_1
sewardjf8f819e2002-04-17 23:21:37 +0000865 case PTHREAD_MUTEX_TIMED_NP:
sewardj2a1dcce2002-04-22 12:45:25 +0000866 case PTHREAD_MUTEX_ADAPTIVE_NP:
sewardj3b13f0e2002-04-25 20:17:29 +0000867# endif
sewardja1679dd2002-05-10 22:31:40 +0000868# ifdef GLIBC_2_1
sewardj68b2dd92002-05-10 21:03:56 +0000869 case PTHREAD_MUTEX_FAST_NP:
sewardja1679dd2002-05-10 22:31:40 +0000870# endif
sewardjf8f819e2002-04-17 23:21:37 +0000871 case PTHREAD_MUTEX_RECURSIVE_NP:
872 case PTHREAD_MUTEX_ERRORCHECK_NP:
sewardjf8f819e2002-04-17 23:21:37 +0000873 attr->__mutexkind = type;
874 return 0;
875 default:
sewardj4dced352002-06-04 22:54:20 +0000876 pthread_error("pthread_mutexattr_settype: "
877 "invalid type");
sewardjf8f819e2002-04-17 23:21:37 +0000878 return EINVAL;
879 }
880}
881
sewardj5905fae2002-04-26 13:25:00 +0000882int __pthread_mutexattr_destroy(pthread_mutexattr_t *attr)
sewardjf8f819e2002-04-17 23:21:37 +0000883{
884 return 0;
885}
886
887
888/* ---------------------------------------------------
889 MUTEXes
890 ------------------------------------------------ */
891
sewardj5905fae2002-04-26 13:25:00 +0000892int __pthread_mutex_init(pthread_mutex_t *mutex,
893 const pthread_mutexattr_t *mutexattr)
sewardje663cb92002-04-12 10:26:32 +0000894{
sewardj604ec3c2002-04-18 22:38:41 +0000895 mutex->__m_count = 0;
896 mutex->__m_owner = (_pthread_descr)VG_INVALID_THREADID;
897 mutex->__m_kind = PTHREAD_MUTEX_ERRORCHECK_NP;
898 if (mutexattr)
899 mutex->__m_kind = mutexattr->__mutexkind;
900 return 0;
sewardje663cb92002-04-12 10:26:32 +0000901}
902
sewardj439d45e2002-05-03 20:43:10 +0000903
sewardj5905fae2002-04-26 13:25:00 +0000904int __pthread_mutex_lock(pthread_mutex_t *mutex)
sewardje663cb92002-04-12 10:26:32 +0000905{
906 int res;
sewardjd8acdf22002-11-13 21:57:52 +0000907
sewardj439d45e2002-05-03 20:43:10 +0000908 if (RUNNING_ON_VALGRIND) {
sewardje663cb92002-04-12 10:26:32 +0000909 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
910 VG_USERREQ__PTHREAD_MUTEX_LOCK,
911 mutex, 0, 0, 0);
912 return res;
sewardj439d45e2002-05-03 20:43:10 +0000913 } else {
sewardjd8acdf22002-11-13 21:57:52 +0000914 /* Play at locking */
915 if (0)
916 kludged("prehistoric lock");
917 mutex->__m_owner = (_pthread_descr)1;
918 mutex->__m_count = 1;
919 mutex->__m_kind |= VG_PTHREAD_PREHISTORY;
sewardj439d45e2002-05-03 20:43:10 +0000920 return 0; /* success */
sewardje663cb92002-04-12 10:26:32 +0000921 }
922}
923
sewardj439d45e2002-05-03 20:43:10 +0000924
sewardj5905fae2002-04-26 13:25:00 +0000925int __pthread_mutex_trylock(pthread_mutex_t *mutex)
sewardj30671ff2002-04-21 00:13:57 +0000926{
927 int res;
sewardjd8acdf22002-11-13 21:57:52 +0000928
sewardj439d45e2002-05-03 20:43:10 +0000929 if (RUNNING_ON_VALGRIND) {
sewardj30671ff2002-04-21 00:13:57 +0000930 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
931 VG_USERREQ__PTHREAD_MUTEX_TRYLOCK,
932 mutex, 0, 0, 0);
933 return res;
sewardj439d45e2002-05-03 20:43:10 +0000934 } else {
sewardjd8acdf22002-11-13 21:57:52 +0000935 /* Play at locking */
936 if (0)
937 kludged("prehistoric trylock");
938 mutex->__m_owner = (_pthread_descr)1;
939 mutex->__m_count = 1;
940 mutex->__m_kind |= VG_PTHREAD_PREHISTORY;
941 return 0; /* success */
sewardj30671ff2002-04-21 00:13:57 +0000942 }
943}
944
sewardj439d45e2002-05-03 20:43:10 +0000945
sewardj5905fae2002-04-26 13:25:00 +0000946int __pthread_mutex_unlock(pthread_mutex_t *mutex)
sewardje663cb92002-04-12 10:26:32 +0000947{
948 int res;
sewardjd8acdf22002-11-13 21:57:52 +0000949
sewardj439d45e2002-05-03 20:43:10 +0000950 if (RUNNING_ON_VALGRIND) {
sewardje663cb92002-04-12 10:26:32 +0000951 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
952 VG_USERREQ__PTHREAD_MUTEX_UNLOCK,
953 mutex, 0, 0, 0);
954 return res;
sewardj439d45e2002-05-03 20:43:10 +0000955 } else {
sewardjd8acdf22002-11-13 21:57:52 +0000956 /* Play at locking */
957 if (0)
958 kludged("prehistoric unlock");
959 mutex->__m_owner = 0;
960 mutex->__m_count = 0;
961 mutex->__m_kind &= ~VG_PTHREAD_PREHISTORY;
962 return 0; /* success */
sewardje663cb92002-04-12 10:26:32 +0000963 }
964}
965
sewardj439d45e2002-05-03 20:43:10 +0000966
sewardj5905fae2002-04-26 13:25:00 +0000967int __pthread_mutex_destroy(pthread_mutex_t *mutex)
sewardje663cb92002-04-12 10:26:32 +0000968{
sewardj604ec3c2002-04-18 22:38:41 +0000969 /* Valgrind doesn't hold any resources on behalf of the mutex, so no
970 need to involve it. */
sewardj4dced352002-06-04 22:54:20 +0000971 if (mutex->__m_count > 0) {
sewardjd8acdf22002-11-13 21:57:52 +0000972 /* Oh, the horror. glibc's internal use of pthreads "knows"
973 that destroying a lock does an implicit unlock. Make it
974 explicit. */
975 __pthread_mutex_unlock(mutex);
976 pthread_error("pthread_mutex_destroy: "
977 "mutex is still in use");
978 return EBUSY;
sewardj4dced352002-06-04 22:54:20 +0000979 }
980 mutex->__m_count = 0;
981 mutex->__m_owner = (_pthread_descr)VG_INVALID_THREADID;
982 mutex->__m_kind = PTHREAD_MUTEX_ERRORCHECK_NP;
983 return 0;
sewardje663cb92002-04-12 10:26:32 +0000984}
985
986
sewardjf8f819e2002-04-17 23:21:37 +0000987/* ---------------------------------------------------
sewardj6072c362002-04-19 14:40:57 +0000988 CONDITION VARIABLES
989 ------------------------------------------------ */
990
991/* LinuxThreads supports no attributes for conditions. Hence ... */
992
993int pthread_condattr_init(pthread_condattr_t *attr)
994{
995 return 0;
996}
997
sewardj0738a592002-04-20 13:59:33 +0000998int pthread_condattr_destroy(pthread_condattr_t *attr)
999{
1000 return 0;
1001}
sewardj6072c362002-04-19 14:40:57 +00001002
1003int pthread_cond_init( pthread_cond_t *cond,
1004 const pthread_condattr_t *cond_attr)
1005{
1006 cond->__c_waiting = (_pthread_descr)VG_INVALID_THREADID;
1007 return 0;
1008}
1009
sewardjf854f472002-04-21 12:19:41 +00001010int pthread_cond_destroy(pthread_cond_t *cond)
1011{
1012 /* should check that no threads are waiting on this CV */
sewardj436e0582002-04-26 14:31:40 +00001013 static int moans = N_MOANS;
1014 if (moans-- > 0)
1015 kludged("pthread_cond_destroy");
sewardjf854f472002-04-21 12:19:41 +00001016 return 0;
1017}
sewardj6072c362002-04-19 14:40:57 +00001018
1019/* ---------------------------------------------------
1020 SCHEDULING
1021 ------------------------------------------------ */
1022
1023/* This is completely bogus. */
1024int pthread_getschedparam(pthread_t target_thread,
1025 int *policy,
1026 struct sched_param *param)
1027{
sewardj436e0582002-04-26 14:31:40 +00001028 static int moans = N_MOANS;
1029 if (moans-- > 0)
1030 kludged("pthread_getschedparam");
sewardj6072c362002-04-19 14:40:57 +00001031 if (policy) *policy = SCHED_OTHER;
sewardj3e909ce2002-06-03 13:27:15 +00001032# ifdef HAVE_SCHED_PRIORITY
sewardj2a1dcce2002-04-22 12:45:25 +00001033 if (param) param->sched_priority = 0; /* who knows */
1034# else
sewardj6072c362002-04-19 14:40:57 +00001035 if (param) param->__sched_priority = 0; /* who knows */
sewardj2a1dcce2002-04-22 12:45:25 +00001036# endif
sewardj6072c362002-04-19 14:40:57 +00001037 return 0;
1038}
1039
1040int pthread_setschedparam(pthread_t target_thread,
1041 int policy,
1042 const struct sched_param *param)
1043{
sewardj436e0582002-04-26 14:31:40 +00001044 static int moans = N_MOANS;
1045 if (moans-- > 0)
1046 ignored("pthread_setschedparam");
sewardj6072c362002-04-19 14:40:57 +00001047 return 0;
1048}
1049
sewardj3b5d8862002-04-20 13:53:23 +00001050int pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex)
1051{
1052 int res;
1053 ensure_valgrind("pthread_cond_wait");
1054 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
1055 VG_USERREQ__PTHREAD_COND_WAIT,
1056 cond, mutex, 0, 0);
1057 return res;
1058}
1059
sewardj5f07b662002-04-23 16:52:51 +00001060int pthread_cond_timedwait ( pthread_cond_t *cond,
1061 pthread_mutex_t *mutex,
1062 const struct timespec *abstime )
1063{
1064 int res;
1065 unsigned int ms_now, ms_end;
1066 struct timeval timeval_now;
1067 unsigned long long int ull_ms_now_after_1970;
1068 unsigned long long int ull_ms_end_after_1970;
1069
1070 ensure_valgrind("pthread_cond_timedwait");
1071 VALGRIND_MAGIC_SEQUENCE(ms_now, 0xFFFFFFFF /* default */,
1072 VG_USERREQ__READ_MILLISECOND_TIMER,
1073 0, 0, 0, 0);
sewardj2d94c112002-06-03 01:25:54 +00001074 my_assert(ms_now != 0xFFFFFFFF);
sewardj5f07b662002-04-23 16:52:51 +00001075 res = gettimeofday(&timeval_now, NULL);
sewardj2d94c112002-06-03 01:25:54 +00001076 my_assert(res == 0);
sewardj5f07b662002-04-23 16:52:51 +00001077
1078 ull_ms_now_after_1970
1079 = 1000ULL * ((unsigned long long int)(timeval_now.tv_sec))
1080 + ((unsigned long long int)(timeval_now.tv_usec / 1000000));
1081 ull_ms_end_after_1970
1082 = 1000ULL * ((unsigned long long int)(abstime->tv_sec))
1083 + ((unsigned long long int)(abstime->tv_nsec / 1000000));
sewardjd8e919e2002-05-29 20:13:53 +00001084 if (ull_ms_end_after_1970 < ull_ms_now_after_1970)
1085 ull_ms_end_after_1970 = ull_ms_now_after_1970;
sewardj5f07b662002-04-23 16:52:51 +00001086 ms_end
1087 = ms_now + (unsigned int)(ull_ms_end_after_1970 - ull_ms_now_after_1970);
1088 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
1089 VG_USERREQ__PTHREAD_COND_TIMEDWAIT,
1090 cond, mutex, ms_end, 0);
1091 return res;
1092}
1093
1094
sewardj3b5d8862002-04-20 13:53:23 +00001095int pthread_cond_signal(pthread_cond_t *cond)
1096{
1097 int res;
1098 ensure_valgrind("pthread_cond_signal");
1099 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
1100 VG_USERREQ__PTHREAD_COND_SIGNAL,
1101 cond, 0, 0, 0);
1102 return res;
1103}
1104
1105int pthread_cond_broadcast(pthread_cond_t *cond)
1106{
1107 int res;
1108 ensure_valgrind("pthread_cond_broadcast");
1109 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
1110 VG_USERREQ__PTHREAD_COND_BROADCAST,
1111 cond, 0, 0, 0);
1112 return res;
1113}
1114
sewardj6072c362002-04-19 14:40:57 +00001115
1116/* ---------------------------------------------------
sewardjf8f819e2002-04-17 23:21:37 +00001117 CANCELLATION
1118 ------------------------------------------------ */
1119
sewardj853f55d2002-04-26 00:27:53 +00001120int pthread_setcancelstate(int state, int *oldstate)
1121{
sewardj20917d82002-05-28 01:36:45 +00001122 int res;
1123 ensure_valgrind("pthread_setcancelstate");
1124 if (state != PTHREAD_CANCEL_ENABLE
sewardj4dced352002-06-04 22:54:20 +00001125 && state != PTHREAD_CANCEL_DISABLE) {
1126 pthread_error("pthread_setcancelstate: "
1127 "invalid state");
sewardj20917d82002-05-28 01:36:45 +00001128 return EINVAL;
sewardj4dced352002-06-04 22:54:20 +00001129 }
sewardj2d94c112002-06-03 01:25:54 +00001130 my_assert(-1 != PTHREAD_CANCEL_ENABLE);
1131 my_assert(-1 != PTHREAD_CANCEL_DISABLE);
sewardj20917d82002-05-28 01:36:45 +00001132 VALGRIND_MAGIC_SEQUENCE(res, (-1) /* default */,
1133 VG_USERREQ__SET_CANCELSTATE,
1134 state, 0, 0, 0);
sewardj2d94c112002-06-03 01:25:54 +00001135 my_assert(res != -1);
sewardj20917d82002-05-28 01:36:45 +00001136 if (oldstate)
1137 *oldstate = res;
sewardj853f55d2002-04-26 00:27:53 +00001138 return 0;
1139}
1140
sewardje663cb92002-04-12 10:26:32 +00001141int pthread_setcanceltype(int type, int *oldtype)
1142{
sewardj20917d82002-05-28 01:36:45 +00001143 int res;
1144 ensure_valgrind("pthread_setcanceltype");
1145 if (type != PTHREAD_CANCEL_DEFERRED
sewardj4dced352002-06-04 22:54:20 +00001146 && type != PTHREAD_CANCEL_ASYNCHRONOUS) {
1147 pthread_error("pthread_setcanceltype: "
1148 "invalid type");
sewardj20917d82002-05-28 01:36:45 +00001149 return EINVAL;
sewardj4dced352002-06-04 22:54:20 +00001150 }
sewardj2d94c112002-06-03 01:25:54 +00001151 my_assert(-1 != PTHREAD_CANCEL_DEFERRED);
1152 my_assert(-1 != PTHREAD_CANCEL_ASYNCHRONOUS);
sewardj20917d82002-05-28 01:36:45 +00001153 VALGRIND_MAGIC_SEQUENCE(res, (-1) /* default */,
1154 VG_USERREQ__SET_CANCELTYPE,
1155 type, 0, 0, 0);
sewardj2d94c112002-06-03 01:25:54 +00001156 my_assert(res != -1);
sewardj20917d82002-05-28 01:36:45 +00001157 if (oldtype)
1158 *oldtype = res;
sewardje663cb92002-04-12 10:26:32 +00001159 return 0;
1160}
1161
sewardje663cb92002-04-12 10:26:32 +00001162int pthread_cancel(pthread_t thread)
1163{
1164 int res;
1165 ensure_valgrind("pthread_cancel");
sewardj20917d82002-05-28 01:36:45 +00001166 VALGRIND_MAGIC_SEQUENCE(res, (-1) /* default */,
1167 VG_USERREQ__SET_CANCELPEND,
1168 thread, &thread_exit_wrapper, 0, 0);
sewardj2d94c112002-06-03 01:25:54 +00001169 my_assert(res != -1);
sewardje663cb92002-04-12 10:26:32 +00001170 return res;
1171}
1172
sewardjd140e442002-05-29 01:21:19 +00001173static __inline__
1174void __my_pthread_testcancel(void)
sewardj853f55d2002-04-26 00:27:53 +00001175{
sewardj20917d82002-05-28 01:36:45 +00001176 int res;
njn25e49d8e72002-09-23 09:36:25 +00001177 ensure_valgrind("__my_pthread_testcancel");
sewardj20917d82002-05-28 01:36:45 +00001178 VALGRIND_MAGIC_SEQUENCE(res, (-1) /* default */,
1179 VG_USERREQ__TESTCANCEL,
1180 0, 0, 0, 0);
sewardj2d94c112002-06-03 01:25:54 +00001181 my_assert(res == 0);
sewardj853f55d2002-04-26 00:27:53 +00001182}
1183
sewardjd140e442002-05-29 01:21:19 +00001184void pthread_testcancel ( void )
1185{
1186 __my_pthread_testcancel();
1187}
1188
sewardj20917d82002-05-28 01:36:45 +00001189
sewardjef037c72002-05-30 00:40:03 +00001190/* Not really sure what this is for. I suspect for doing the POSIX
1191 requirements for fork() and exec(). We do this internally anyway
1192 whenever those syscalls are observed, so this could be superfluous,
1193 but hey ...
1194*/
sewardj853f55d2002-04-26 00:27:53 +00001195void __pthread_kill_other_threads_np ( void )
1196{
sewardjef037c72002-05-30 00:40:03 +00001197 int res;
1198 ensure_valgrind("__pthread_kill_other_threads_np");
1199 VALGRIND_MAGIC_SEQUENCE(res, (-1) /* default */,
1200 VG_USERREQ__NUKE_OTHER_THREADS,
1201 0, 0, 0, 0);
sewardj2d94c112002-06-03 01:25:54 +00001202 my_assert(res == 0);
sewardj853f55d2002-04-26 00:27:53 +00001203}
1204
sewardje663cb92002-04-12 10:26:32 +00001205
sewardjf8f819e2002-04-17 23:21:37 +00001206/* ---------------------------------------------------
sewardjb48e5002002-05-13 00:16:03 +00001207 SIGNALS
1208 ------------------------------------------------ */
1209
1210#include <signal.h>
1211
1212int pthread_sigmask(int how, const sigset_t *newmask,
1213 sigset_t *oldmask)
1214{
1215 int res;
1216
1217 /* A bit subtle, because the scheduler expects newmask and oldmask
1218 to be vki_sigset_t* rather than sigset_t*, and the two are
1219 different. Fortunately the first 64 bits of a sigset_t are
1220 exactly a vki_sigset_t, so we just pass the pointers through
1221 unmodified. Haaaack!
1222
1223 Also mash the how value so that the SIG_ constants from glibc
sewardj018f7622002-05-15 21:13:39 +00001224 constants to VKI_ constants, so that the former do not have to
1225 be included into vg_scheduler.c. */
sewardjb48e5002002-05-13 00:16:03 +00001226
1227 ensure_valgrind("pthread_sigmask");
1228
1229 switch (how) {
sewardj018f7622002-05-15 21:13:39 +00001230 case SIG_SETMASK: how = VKI_SIG_SETMASK; break;
1231 case SIG_BLOCK: how = VKI_SIG_BLOCK; break;
1232 case SIG_UNBLOCK: how = VKI_SIG_UNBLOCK; break;
sewardj4dced352002-06-04 22:54:20 +00001233 default: pthread_error("pthread_sigmask: invalid how");
1234 return EINVAL;
sewardjb48e5002002-05-13 00:16:03 +00001235 }
1236
1237 /* Crude check */
1238 if (newmask == NULL)
1239 return EFAULT;
1240
1241 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
1242 VG_USERREQ__PTHREAD_SIGMASK,
1243 how, newmask, oldmask, 0);
1244
1245 /* The scheduler tells us of any memory violations. */
1246 return res == 0 ? 0 : EFAULT;
1247}
1248
1249
1250int sigwait ( const sigset_t* set, int* sig )
1251{
1252 int res;
1253 ensure_valgrind("sigwait");
1254 /* As with pthread_sigmask we deliberately confuse sigset_t with
1255 vki_ksigset_t. */
1256 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
1257 VG_USERREQ__SIGWAIT,
1258 set, sig, 0, 0);
1259 return res;
1260}
1261
1262
sewardj018f7622002-05-15 21:13:39 +00001263int pthread_kill(pthread_t thread, int signo)
1264{
1265 int res;
1266 ensure_valgrind("pthread_kill");
1267 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
1268 VG_USERREQ__PTHREAD_KILL,
1269 thread, signo, 0, 0);
1270 return res;
1271}
1272
1273
sewardj3665ded2002-05-16 16:57:25 +00001274/* Copied verbatim from Linuxthreads */
1275/* Redefine raise() to send signal to calling thread only,
1276 as per POSIX 1003.1c */
1277int raise (int sig)
1278{
1279 int retcode = pthread_kill(pthread_self(), sig);
sewardj4dced352002-06-04 22:54:20 +00001280 if (retcode == 0) {
sewardj3665ded2002-05-16 16:57:25 +00001281 return 0;
sewardj4dced352002-06-04 22:54:20 +00001282 } else {
sewardj3665ded2002-05-16 16:57:25 +00001283 errno = retcode;
1284 return -1;
1285 }
1286}
1287
1288
sewardj9a2224b2002-06-19 10:17:40 +00001289int pause ( void )
1290{
1291 unsigned int n_orig, n_now;
1292 struct vki_timespec nanosleep_interval;
1293 ensure_valgrind("pause");
1294
1295 /* This is surely a cancellation point. */
1296 __my_pthread_testcancel();
1297
1298 VALGRIND_MAGIC_SEQUENCE(n_orig, 0xFFFFFFFF /* default */,
1299 VG_USERREQ__GET_N_SIGS_RETURNED,
1300 0, 0, 0, 0);
1301 my_assert(n_orig != 0xFFFFFFFF);
1302
1303 while (1) {
1304 VALGRIND_MAGIC_SEQUENCE(n_now, 0xFFFFFFFF /* default */,
1305 VG_USERREQ__GET_N_SIGS_RETURNED,
1306 0, 0, 0, 0);
1307 my_assert(n_now != 0xFFFFFFFF);
1308 my_assert(n_now >= n_orig);
1309 if (n_now != n_orig) break;
1310
1311 nanosleep_interval.tv_sec = 0;
njn25e49d8e72002-09-23 09:36:25 +00001312 nanosleep_interval.tv_nsec = 12 * 1000 * 1000; /* 12 milliseconds */
sewardj9a2224b2002-06-19 10:17:40 +00001313 /* It's critical here that valgrind's nanosleep implementation
1314 is nonblocking. */
1315 (void)my_do_syscall2(__NR_nanosleep,
1316 (int)(&nanosleep_interval), (int)NULL);
1317 }
1318
1319 * (__errno_location()) = EINTR;
1320 return -1;
1321}
1322
1323
sewardjb48e5002002-05-13 00:16:03 +00001324/* ---------------------------------------------------
sewardjf8f819e2002-04-17 23:21:37 +00001325 THREAD-SPECIFICs
1326 ------------------------------------------------ */
sewardj5e5fa512002-04-14 13:13:05 +00001327
sewardj00a66b12002-10-12 16:42:35 +00001328static
1329int key_is_valid (pthread_key_t key)
1330{
1331 int res;
1332 VALGRIND_MAGIC_SEQUENCE(res, 2 /* default */,
1333 VG_USERREQ__PTHREAD_KEY_VALIDATE,
1334 key, 0, 0, 0);
1335 my_assert(res != 2);
1336 return res;
1337}
1338
1339
1340/* Returns NULL if thread is invalid. Otherwise, if the thread
1341 already has a specifics area, return that. Otherwise allocate it
1342 one. */
1343static
1344void** get_or_allocate_specifics_ptr ( pthread_t thread )
1345{
1346 int res, i;
1347 void** specifics_ptr;
1348 ensure_valgrind("get_or_allocate_specifics_ptr");
1349
1350 /* Returns zero if the thread has no specific_ptr. One if thread
1351 is invalid. Otherwise, the specific_ptr value. This is
1352 allocated with my_malloc and so is aligned and cannot be
1353 confused with 1 or 3. */
1354 VALGRIND_MAGIC_SEQUENCE(specifics_ptr, 3 /* default */,
1355 VG_USERREQ__PTHREAD_GETSPECIFIC_PTR,
1356 thread, 0, 0, 0);
1357 my_assert(specifics_ptr != (void**)3);
1358
1359 if (specifics_ptr == (void**)1)
1360 return NULL; /* invalid thread */
1361
1362 if (specifics_ptr != NULL)
1363 return specifics_ptr; /* already has a specifics ptr. */
1364
1365 /* None yet ... allocate a new one. Should never fail. */
1366 specifics_ptr = my_malloc( VG_N_THREAD_KEYS * sizeof(void*) );
1367 my_assert(specifics_ptr != NULL);
1368
1369 VALGRIND_MAGIC_SEQUENCE(res, -1 /* default */,
1370 VG_USERREQ__PTHREAD_SETSPECIFIC_PTR,
1371 specifics_ptr, 0, 0, 0);
1372 my_assert(res == 0);
1373
1374 /* POSIX sez: "Upon thread creation, the value NULL shall be
1375 associated with all defined keys in the new thread." This
1376 allocation is in effect a delayed allocation of the specific
1377 data for a thread, at its first-use. Hence we initialise it
1378 here. */
1379 for (i = 0; i < VG_N_THREAD_KEYS; i++) {
1380 specifics_ptr[i] = NULL;
1381 }
1382
1383 return specifics_ptr;
1384}
1385
1386
sewardj5905fae2002-04-26 13:25:00 +00001387int __pthread_key_create(pthread_key_t *key,
1388 void (*destr_function) (void *))
sewardj5e5fa512002-04-14 13:13:05 +00001389{
sewardj00a66b12002-10-12 16:42:35 +00001390 void** specifics_ptr;
1391 int res, i;
sewardj5f07b662002-04-23 16:52:51 +00001392 ensure_valgrind("pthread_key_create");
sewardj00a66b12002-10-12 16:42:35 +00001393
1394 /* This writes *key if successful. It should never fail. */
1395 VALGRIND_MAGIC_SEQUENCE(res, 1 /* default */,
sewardj5f07b662002-04-23 16:52:51 +00001396 VG_USERREQ__PTHREAD_KEY_CREATE,
1397 key, destr_function, 0, 0);
sewardj00a66b12002-10-12 16:42:35 +00001398 my_assert(res == 0);
1399
1400 /* POSIX sez: "Upon key creation, the value NULL shall be
1401 associated with the new key in all active threads." */
1402 for (i = 0; i < VG_N_THREADS; i++) {
1403 specifics_ptr = get_or_allocate_specifics_ptr(i);
1404 /* we get NULL if i is an invalid thread. */
1405 if (specifics_ptr != NULL)
1406 specifics_ptr[*key] = NULL;
1407 }
1408
sewardj5f07b662002-04-23 16:52:51 +00001409 return res;
sewardj5e5fa512002-04-14 13:13:05 +00001410}
1411
1412int pthread_key_delete(pthread_key_t key)
1413{
sewardj00a66b12002-10-12 16:42:35 +00001414 int res;
1415 ensure_valgrind("pthread_key_create");
1416 if (!key_is_valid(key))
1417 return EINVAL;
1418 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
1419 VG_USERREQ__PTHREAD_KEY_DELETE,
1420 key, 0, 0, 0);
1421 my_assert(res == 0);
sewardj5e5fa512002-04-14 13:13:05 +00001422 return 0;
1423}
1424
sewardj5905fae2002-04-26 13:25:00 +00001425int __pthread_setspecific(pthread_key_t key, const void *pointer)
sewardj5e5fa512002-04-14 13:13:05 +00001426{
sewardj00a66b12002-10-12 16:42:35 +00001427 void** specifics_ptr;
sewardj5f07b662002-04-23 16:52:51 +00001428 ensure_valgrind("pthread_setspecific");
sewardj00a66b12002-10-12 16:42:35 +00001429
1430 if (!key_is_valid(key))
1431 return EINVAL;
1432
1433 specifics_ptr = get_or_allocate_specifics_ptr(pthread_self());
1434 specifics_ptr[key] = (void*)pointer;
1435 return 0;
sewardj5e5fa512002-04-14 13:13:05 +00001436}
1437
sewardj5905fae2002-04-26 13:25:00 +00001438void * __pthread_getspecific(pthread_key_t key)
sewardj5e5fa512002-04-14 13:13:05 +00001439{
sewardj00a66b12002-10-12 16:42:35 +00001440 void** specifics_ptr;
sewardj5f07b662002-04-23 16:52:51 +00001441 ensure_valgrind("pthread_getspecific");
sewardj00a66b12002-10-12 16:42:35 +00001442
1443 if (!key_is_valid(key))
1444 return NULL;
1445
1446 specifics_ptr = get_or_allocate_specifics_ptr(pthread_self());
1447 return specifics_ptr[key];
1448}
1449
1450
sewardj9aa918d2002-10-20 16:25:55 +00001451#ifdef GLIBC_2_3
sewardj00a66b12002-10-12 16:42:35 +00001452static
1453void ** __pthread_getspecific_addr(pthread_key_t key)
1454{
1455 void** specifics_ptr;
1456 ensure_valgrind("pthread_getspecific_addr");
1457
1458 if (!key_is_valid(key))
1459 return NULL;
1460
1461 specifics_ptr = get_or_allocate_specifics_ptr(pthread_self());
1462 return &(specifics_ptr[key]);
sewardj5e5fa512002-04-14 13:13:05 +00001463}
sewardj9aa918d2002-10-20 16:25:55 +00001464#endif
sewardjf8f819e2002-04-17 23:21:37 +00001465
1466/* ---------------------------------------------------
sewardj89d3d852002-04-24 19:21:39 +00001467 ONCEry
1468 ------------------------------------------------ */
1469
1470static pthread_mutex_t once_masterlock = PTHREAD_MUTEX_INITIALIZER;
1471
1472
sewardj5905fae2002-04-26 13:25:00 +00001473int __pthread_once ( pthread_once_t *once_control,
1474 void (*init_routine) (void) )
sewardj89d3d852002-04-24 19:21:39 +00001475{
1476 int res;
1477 ensure_valgrind("pthread_once");
1478
sewardj68b2dd92002-05-10 21:03:56 +00001479 res = __pthread_mutex_lock(&once_masterlock);
sewardj89d3d852002-04-24 19:21:39 +00001480
sewardj68b2dd92002-05-10 21:03:56 +00001481 if (res != 0) {
sewardj89d3d852002-04-24 19:21:39 +00001482 barf("pthread_once: Looks like your program's "
1483 "init routine calls back to pthread_once() ?!");
sewardj68b2dd92002-05-10 21:03:56 +00001484 }
sewardj89d3d852002-04-24 19:21:39 +00001485
1486 if (*once_control == 0) {
1487 *once_control = 1;
1488 init_routine();
1489 }
1490
sewardj68b2dd92002-05-10 21:03:56 +00001491 __pthread_mutex_unlock(&once_masterlock);
sewardj89d3d852002-04-24 19:21:39 +00001492
1493 return 0;
1494}
1495
1496
1497/* ---------------------------------------------------
sewardj853f55d2002-04-26 00:27:53 +00001498 MISC
1499 ------------------------------------------------ */
1500
sewardj2cb00342002-06-28 01:46:26 +00001501static pthread_mutex_t pthread_atfork_lock
1502 = PTHREAD_MUTEX_INITIALIZER;
1503
sewardj5905fae2002-04-26 13:25:00 +00001504int __pthread_atfork ( void (*prepare)(void),
1505 void (*parent)(void),
1506 void (*child)(void) )
sewardj853f55d2002-04-26 00:27:53 +00001507{
sewardj2cb00342002-06-28 01:46:26 +00001508 int n, res;
1509 ForkHandlerEntry entry;
1510
1511 ensure_valgrind("pthread_atfork");
1512 __pthread_mutex_lock(&pthread_atfork_lock);
1513
1514 /* Fetch old counter */
1515 VALGRIND_MAGIC_SEQUENCE(n, -2 /* default */,
1516 VG_USERREQ__GET_FHSTACK_USED,
1517 0, 0, 0, 0);
1518 my_assert(n >= 0 && n < VG_N_FORKHANDLERSTACK);
1519 if (n == VG_N_FORKHANDLERSTACK-1)
1520 barf("pthread_atfork: VG_N_FORKHANDLERSTACK is too low; "
1521 "increase and recompile");
1522
1523 /* Add entry */
1524 entry.prepare = *prepare;
1525 entry.parent = *parent;
1526 entry.child = *child;
1527 VALGRIND_MAGIC_SEQUENCE(res, -2 /* default */,
1528 VG_USERREQ__SET_FHSTACK_ENTRY,
1529 n, &entry, 0, 0);
1530 my_assert(res == 0);
1531
1532 /* Bump counter */
1533 VALGRIND_MAGIC_SEQUENCE(res, -2 /* default */,
1534 VG_USERREQ__SET_FHSTACK_USED,
1535 n+1, 0, 0, 0);
1536 my_assert(res == 0);
1537
1538 __pthread_mutex_unlock(&pthread_atfork_lock);
1539 return 0;
sewardj853f55d2002-04-26 00:27:53 +00001540}
1541
1542
sewardjbb990782002-05-08 02:01:14 +00001543__attribute__((weak))
1544void __pthread_initialize ( void )
1545{
sewardjbea1caa2002-05-10 23:20:58 +00001546 ensure_valgrind("__pthread_initialize");
sewardjbb990782002-05-08 02:01:14 +00001547}
1548
1549
sewardj853f55d2002-04-26 00:27:53 +00001550/* ---------------------------------------------------
sewardj3b13f0e2002-04-25 20:17:29 +00001551 LIBRARY-PRIVATE THREAD SPECIFIC STATE
sewardjf8f819e2002-04-17 23:21:37 +00001552 ------------------------------------------------ */
1553
sewardj3b13f0e2002-04-25 20:17:29 +00001554#include <resolv.h>
1555static int thread_specific_errno[VG_N_THREADS];
1556static int thread_specific_h_errno[VG_N_THREADS];
1557static struct __res_state
1558 thread_specific_res_state[VG_N_THREADS];
sewardjf8f819e2002-04-17 23:21:37 +00001559
sewardj3b13f0e2002-04-25 20:17:29 +00001560int* __errno_location ( void )
sewardjf8f819e2002-04-17 23:21:37 +00001561{
1562 int tid;
sewardj3b13f0e2002-04-25 20:17:29 +00001563 /* ensure_valgrind("__errno_location"); */
1564 VALGRIND_MAGIC_SEQUENCE(tid, 1 /* default */,
sewardjf8f819e2002-04-17 23:21:37 +00001565 VG_USERREQ__PTHREAD_GET_THREADID,
1566 0, 0, 0, 0);
sewardj3b13f0e2002-04-25 20:17:29 +00001567 /* 'cos I'm paranoid ... */
sewardj439d45e2002-05-03 20:43:10 +00001568 if (tid < 1 || tid >= VG_N_THREADS)
sewardj3b13f0e2002-04-25 20:17:29 +00001569 barf("__errno_location: invalid ThreadId");
1570 return & thread_specific_errno[tid];
1571}
1572
1573int* __h_errno_location ( void )
1574{
1575 int tid;
1576 /* ensure_valgrind("__h_errno_location"); */
1577 VALGRIND_MAGIC_SEQUENCE(tid, 1 /* default */,
1578 VG_USERREQ__PTHREAD_GET_THREADID,
1579 0, 0, 0, 0);
1580 /* 'cos I'm paranoid ... */
sewardj439d45e2002-05-03 20:43:10 +00001581 if (tid < 1 || tid >= VG_N_THREADS)
sewardj3b13f0e2002-04-25 20:17:29 +00001582 barf("__h_errno_location: invalid ThreadId");
1583 return & thread_specific_h_errno[tid];
1584}
1585
sewardjb0ff1032002-08-06 09:02:53 +00001586
1587#undef _res
1588extern struct __res_state _res;
1589
sewardj3b13f0e2002-04-25 20:17:29 +00001590struct __res_state* __res_state ( void )
1591{
1592 int tid;
1593 /* ensure_valgrind("__res_state"); */
1594 VALGRIND_MAGIC_SEQUENCE(tid, 1 /* default */,
1595 VG_USERREQ__PTHREAD_GET_THREADID,
1596 0, 0, 0, 0);
1597 /* 'cos I'm paranoid ... */
sewardj439d45e2002-05-03 20:43:10 +00001598 if (tid < 1 || tid >= VG_N_THREADS)
sewardj3b13f0e2002-04-25 20:17:29 +00001599 barf("__res_state: invalid ThreadId");
sewardjb0ff1032002-08-06 09:02:53 +00001600 if (tid == 1)
1601 return & _res;
sewardj3b13f0e2002-04-25 20:17:29 +00001602 return & thread_specific_res_state[tid];
sewardjf8f819e2002-04-17 23:21:37 +00001603}
1604
1605
sewardj5716dbb2002-04-26 03:28:18 +00001606/* ---------------------------------------------------
1607 LIBC-PRIVATE SPECIFIC DATA
1608 ------------------------------------------------ */
1609
1610/* Relies on assumption that initial private data is NULL. This
1611 should be fixed somehow. */
1612
njn25e49d8e72002-09-23 09:36:25 +00001613/* The allowable keys (indices) (all 3 of them).
sewardj5716dbb2002-04-26 03:28:18 +00001614 From sysdeps/pthread/bits/libc-tsd.h
1615*/
sewardjcb7f08a2002-10-02 09:41:49 +00001616/* as per glibc anoncvs HEAD of 20021001. */
sewardj5716dbb2002-04-26 03:28:18 +00001617enum __libc_tsd_key_t { _LIBC_TSD_KEY_MALLOC = 0,
1618 _LIBC_TSD_KEY_DL_ERROR,
njn25e49d8e72002-09-23 09:36:25 +00001619 _LIBC_TSD_KEY_RPC_VARS,
sewardjcb7f08a2002-10-02 09:41:49 +00001620 _LIBC_TSD_KEY_LOCALE,
1621 _LIBC_TSD_KEY_CTYPE_B,
1622 _LIBC_TSD_KEY_CTYPE_TOLOWER,
1623 _LIBC_TSD_KEY_CTYPE_TOUPPER,
sewardj5716dbb2002-04-26 03:28:18 +00001624 _LIBC_TSD_KEY_N };
1625
1626/* Auto-initialising subsystem. libc_specifics_inited is set
1627 after initialisation. libc_specifics_inited_mx guards it. */
1628static int libc_specifics_inited = 0;
1629static pthread_mutex_t libc_specifics_inited_mx = PTHREAD_MUTEX_INITIALIZER;
1630
sewardj00a66b12002-10-12 16:42:35 +00001631
sewardj5716dbb2002-04-26 03:28:18 +00001632/* These are the keys we must initialise the first time. */
sewardjcb7f08a2002-10-02 09:41:49 +00001633static pthread_key_t libc_specifics_keys[_LIBC_TSD_KEY_N];
sewardj5716dbb2002-04-26 03:28:18 +00001634
sewardj00a66b12002-10-12 16:42:35 +00001635
sewardjcb7f08a2002-10-02 09:41:49 +00001636/* Initialise the keys, if they are not already initialised. */
sewardj5716dbb2002-04-26 03:28:18 +00001637static
1638void init_libc_tsd_keys ( void )
1639{
1640 int res, i;
1641 pthread_key_t k;
1642
sewardj08c7f012002-10-07 23:56:55 +00001643 /* Don't fall into deadlock if we get called again whilst we still
1644 hold the lock, via the __uselocale() call herein. */
1645 if (libc_specifics_inited != 0)
1646 return;
1647
1648 /* Take the lock. */
sewardj00a66b12002-10-12 16:42:35 +00001649 res = __pthread_mutex_lock(&libc_specifics_inited_mx);
sewardj5716dbb2002-04-26 03:28:18 +00001650 if (res != 0) barf("init_libc_tsd_keys: lock");
1651
sewardj08c7f012002-10-07 23:56:55 +00001652 /* Now test again, to be sure there is no mistake. */
1653 if (libc_specifics_inited != 0) {
sewardj00a66b12002-10-12 16:42:35 +00001654 res = __pthread_mutex_unlock(&libc_specifics_inited_mx);
sewardj08c7f012002-10-07 23:56:55 +00001655 if (res != 0) barf("init_libc_tsd_keys: unlock(1)");
1656 return;
sewardj5716dbb2002-04-26 03:28:18 +00001657 }
1658
sewardj08c7f012002-10-07 23:56:55 +00001659 /* Actually do the initialisation. */
1660 /* printf("INIT libc specifics\n"); */
1661 for (i = 0; i < _LIBC_TSD_KEY_N; i++) {
sewardj00a66b12002-10-12 16:42:35 +00001662 res = __pthread_key_create(&k, NULL);
sewardj08c7f012002-10-07 23:56:55 +00001663 if (res != 0) barf("init_libc_tsd_keys: create");
1664 libc_specifics_keys[i] = k;
1665 }
1666
1667 /* Signify init done. */
1668 libc_specifics_inited = 1;
1669
1670# ifdef GLIBC_2_3
1671 /* Set the initialising thread's locale to the global (default)
sewardj00a66b12002-10-12 16:42:35 +00001672 locale. A hack in support of glibc-2.3. This does the biz for
1673 the root thread. For all other threads we run this in
1674 thread_wrapper(), which does the real work of
1675 pthread_create(). */
1676 /* assert that we are the root thread. I don't know if this is
1677 really a valid assertion to make; if it breaks I'll reconsider
1678 it. */
1679 my_assert(pthread_self() == 1);
sewardj08c7f012002-10-07 23:56:55 +00001680 __uselocale(LC_GLOBAL_LOCALE);
1681# endif
1682
1683 /* Unlock and return. */
sewardj00a66b12002-10-12 16:42:35 +00001684 res = __pthread_mutex_unlock(&libc_specifics_inited_mx);
sewardj5716dbb2002-04-26 03:28:18 +00001685 if (res != 0) barf("init_libc_tsd_keys: unlock");
1686}
1687
1688
1689static int
1690libc_internal_tsd_set ( enum __libc_tsd_key_t key,
1691 const void * pointer )
1692{
sewardjcb7f08a2002-10-02 09:41:49 +00001693 int res;
sewardj5716dbb2002-04-26 03:28:18 +00001694 /* printf("SET SET SET key %d ptr %p\n", key, pointer); */
sewardjcb7f08a2002-10-02 09:41:49 +00001695 if (key < _LIBC_TSD_KEY_MALLOC || key >= _LIBC_TSD_KEY_N)
sewardj5716dbb2002-04-26 03:28:18 +00001696 barf("libc_internal_tsd_set: invalid key");
1697 init_libc_tsd_keys();
sewardj00a66b12002-10-12 16:42:35 +00001698 res = __pthread_setspecific(libc_specifics_keys[key], pointer);
sewardj5716dbb2002-04-26 03:28:18 +00001699 if (res != 0) barf("libc_internal_tsd_set: setspecific failed");
1700 return 0;
1701}
1702
1703static void *
1704libc_internal_tsd_get ( enum __libc_tsd_key_t key )
1705{
sewardjcb7f08a2002-10-02 09:41:49 +00001706 void* v;
sewardj5716dbb2002-04-26 03:28:18 +00001707 /* printf("GET GET GET key %d\n", key); */
sewardjcb7f08a2002-10-02 09:41:49 +00001708 if (key < _LIBC_TSD_KEY_MALLOC || key >= _LIBC_TSD_KEY_N)
sewardj5716dbb2002-04-26 03:28:18 +00001709 barf("libc_internal_tsd_get: invalid key");
1710 init_libc_tsd_keys();
sewardj00a66b12002-10-12 16:42:35 +00001711 v = __pthread_getspecific(libc_specifics_keys[key]);
sewardj5716dbb2002-04-26 03:28:18 +00001712 /* if (v == NULL) barf("libc_internal_tsd_set: getspecific failed"); */
1713 return v;
1714}
1715
1716
sewardj70adeb22002-04-27 01:35:38 +00001717int (*__libc_internal_tsd_set)
1718 (enum __libc_tsd_key_t key, const void * pointer)
1719 = libc_internal_tsd_set;
sewardj5716dbb2002-04-26 03:28:18 +00001720
sewardj70adeb22002-04-27 01:35:38 +00001721void* (*__libc_internal_tsd_get)
1722 (enum __libc_tsd_key_t key)
1723 = libc_internal_tsd_get;
sewardj5716dbb2002-04-26 03:28:18 +00001724
1725
sewardj00a66b12002-10-12 16:42:35 +00001726#ifdef GLIBC_2_3
1727/* This one was first spotted be me in the glibc-2.2.93 sources. */
1728static void**
1729libc_internal_tsd_address ( enum __libc_tsd_key_t key )
1730{
1731 void** v;
1732 /* printf("ADDR ADDR ADDR key %d\n", key); */
1733 if (key < _LIBC_TSD_KEY_MALLOC || key >= _LIBC_TSD_KEY_N)
1734 barf("libc_internal_tsd_address: invalid key");
1735 init_libc_tsd_keys();
1736 v = __pthread_getspecific_addr(libc_specifics_keys[key]);
1737 return v;
1738}
1739
1740void ** (*__libc_internal_tsd_address)
1741 (enum __libc_tsd_key_t key)
1742 = libc_internal_tsd_address;
1743#endif
1744
1745
sewardje663cb92002-04-12 10:26:32 +00001746/* ---------------------------------------------------------------------
1747 These are here (I think) because they are deemed cancellation
1748 points by POSIX. For the moment we'll simply pass the call along
1749 to the corresponding thread-unaware (?) libc routine.
1750 ------------------------------------------------------------------ */
1751
sewardje663cb92002-04-12 10:26:32 +00001752#include <stdlib.h>
sewardje663cb92002-04-12 10:26:32 +00001753#include <sys/types.h>
1754#include <sys/socket.h>
1755
sewardjd529a442002-05-04 19:49:21 +00001756#ifdef GLIBC_2_1
1757extern
1758int __sigaction
1759 (int signum,
1760 const struct sigaction *act,
1761 struct sigaction *oldact);
1762#else
sewardje663cb92002-04-12 10:26:32 +00001763extern
1764int __libc_sigaction
1765 (int signum,
1766 const struct sigaction *act,
1767 struct sigaction *oldact);
sewardjd529a442002-05-04 19:49:21 +00001768#endif
sewardje663cb92002-04-12 10:26:32 +00001769int sigaction(int signum,
1770 const struct sigaction *act,
1771 struct sigaction *oldact)
1772{
sewardjd140e442002-05-29 01:21:19 +00001773 __my_pthread_testcancel();
sewardj2a1dcce2002-04-22 12:45:25 +00001774# ifdef GLIBC_2_1
1775 return __sigaction(signum, act, oldact);
1776# else
sewardj45b4b372002-04-16 22:50:32 +00001777 return __libc_sigaction(signum, act, oldact);
sewardj2a1dcce2002-04-22 12:45:25 +00001778# endif
sewardje663cb92002-04-12 10:26:32 +00001779}
1780
1781
1782extern
1783int __libc_connect(int sockfd,
1784 const struct sockaddr *serv_addr,
1785 socklen_t addrlen);
sewardj5905fae2002-04-26 13:25:00 +00001786__attribute__((weak))
sewardje663cb92002-04-12 10:26:32 +00001787int connect(int sockfd,
1788 const struct sockaddr *serv_addr,
1789 socklen_t addrlen)
1790{
sewardjd140e442002-05-29 01:21:19 +00001791 __my_pthread_testcancel();
sewardj45b4b372002-04-16 22:50:32 +00001792 return __libc_connect(sockfd, serv_addr, addrlen);
sewardje663cb92002-04-12 10:26:32 +00001793}
1794
1795
1796extern
1797int __libc_fcntl(int fd, int cmd, long arg);
sewardj5905fae2002-04-26 13:25:00 +00001798__attribute__((weak))
sewardje663cb92002-04-12 10:26:32 +00001799int fcntl(int fd, int cmd, long arg)
1800{
sewardjd140e442002-05-29 01:21:19 +00001801 __my_pthread_testcancel();
sewardj45b4b372002-04-16 22:50:32 +00001802 return __libc_fcntl(fd, cmd, arg);
sewardje663cb92002-04-12 10:26:32 +00001803}
1804
1805
1806extern
1807ssize_t __libc_write(int fd, const void *buf, size_t count);
sewardj5905fae2002-04-26 13:25:00 +00001808__attribute__((weak))
sewardje663cb92002-04-12 10:26:32 +00001809ssize_t write(int fd, const void *buf, size_t count)
1810{
sewardjd140e442002-05-29 01:21:19 +00001811 __my_pthread_testcancel();
sewardj45b4b372002-04-16 22:50:32 +00001812 return __libc_write(fd, buf, count);
sewardje663cb92002-04-12 10:26:32 +00001813}
1814
1815
1816extern
1817ssize_t __libc_read(int fd, void *buf, size_t count);
sewardj5905fae2002-04-26 13:25:00 +00001818__attribute__((weak))
sewardje663cb92002-04-12 10:26:32 +00001819ssize_t read(int fd, void *buf, size_t count)
1820{
sewardjd140e442002-05-29 01:21:19 +00001821 __my_pthread_testcancel();
sewardj45b4b372002-04-16 22:50:32 +00001822 return __libc_read(fd, buf, count);
sewardje663cb92002-04-12 10:26:32 +00001823}
1824
sewardjf912dfc2002-11-13 21:51:10 +00001825/*
1826 * Ugh, this is horrible but here goes:
1827 *
1828 * Open of a named pipe (fifo file) can block. In a threaded program,
1829 * this means that the whole thing can block. We therefore need to
1830 * make the open appear to block to the caller, but still keep polling
1831 * for everyone else.
1832 *
1833 * There are four cases:
1834 *
1835 * - the caller asked for O_NONBLOCK. The easy one: we just do it.
1836 *
1837 * - the caller asked for a blocking O_RDONLY open. We open it with
1838 * O_NONBLOCK and then use poll to wait for it to become ready.
1839 *
1840 * - the caller asked for a blocking O_WRONLY open. Unfortunately, this
1841 * will fail with ENXIO when we make it non-blocking. Doubly
1842 * unfortunate is that we can only rely on these semantics if it is
1843 * actually a fifo file; the hack is that if we see that it is a
1844 * O_WRONLY open and we get ENXIO, then stat the path and see if it
1845 * actually is a fifo. This is racy, but it is the best we can do.
1846 * If it is a fifo, then keep trying the open until it works; if not
1847 * just return the error.
1848 *
1849 * - the caller asked for a blocking O_RDWR open. Well, under Linux,
1850 * this never blocks, so we just clear the non-blocking flag and
1851 * return.
1852 *
1853 * This code assumes that for whatever we open, O_NONBLOCK followed by
1854 * a fcntl clearing O_NONBLOCK is the same as opening without
1855 * O_NONBLOCK. Also assumes that stat and fstat have no side-effects.
1856 *
1857 * XXX Should probably put in special cases for some devices as well,
1858 * like serial ports. Unfortunately they don't work like fifos, so
1859 * this logic will become even more tortured. Wait until we really
1860 * need it.
1861 */
1862static inline int _open(const char *pathname, int flags, mode_t mode,
1863 int (*openp)(const char *, int, mode_t))
sewardjbe32e452002-04-24 20:29:58 +00001864{
sewardjf912dfc2002-11-13 21:51:10 +00001865 int fd;
1866 struct stat st;
1867 struct vki_timespec nanosleep_interval;
1868 int saved_errno;
1869
sewardjd140e442002-05-29 01:21:19 +00001870 __my_pthread_testcancel();
sewardjf912dfc2002-11-13 21:51:10 +00001871
1872 /* Assume we can only get O_RDONLY, O_WRONLY or O_RDWR */
1873 my_assert((flags & VKI_O_ACCMODE) != VKI_O_ACCMODE);
1874
1875 for(;;) {
1876 fd = (*openp)(pathname, flags | VKI_O_NONBLOCK, mode);
1877
1878 /* return immediately if caller wanted nonblocking anyway */
1879 if (flags & VKI_O_NONBLOCK)
1880 return fd;
1881
1882 saved_errno = errno;
1883
1884 if (fd != -1)
1885 break; /* open worked */
1886
1887 /* If we got ENXIO and we're opening WRONLY, and it turns out
1888 to really be a FIFO, then poll waiting for open to succeed */
1889 if (errno == ENXIO &&
1890 (flags & VKI_O_ACCMODE) == VKI_O_WRONLY &&
1891 (stat(pathname, &st) == 0 && S_ISFIFO(st.st_mode))) {
1892
1893 /* OK, we're opening a FIFO for writing; sleep and spin */
1894 nanosleep_interval.tv_sec = 0;
1895 nanosleep_interval.tv_nsec = 13 * 1000 * 1000; /* 13 milliseconds */
1896 /* It's critical here that valgrind's nanosleep implementation
1897 is nonblocking. */
1898 (void)my_do_syscall2(__NR_nanosleep,
1899 (int)(&nanosleep_interval), (int)NULL);
1900 } else {
1901 /* it was just an error */
1902 errno = saved_errno;
1903 return -1;
1904 }
1905 }
1906
1907 /* OK, we've got a nonblocking FD for a caller who wants blocking;
1908 reset the flags to what they asked for */
1909 fcntl(fd, VKI_F_SETFL, flags);
1910
1911 /* Return now if one of:
1912 - we were opening O_RDWR (never blocks)
1913 - we opened with O_WRONLY (polling already done)
1914 - the thing we opened wasn't a FIFO after all (or fstat failed)
1915 */
1916 if ((flags & VKI_O_ACCMODE) != VKI_O_RDONLY ||
1917 (fstat(fd, &st) == -1 || !S_ISFIFO(st.st_mode))) {
1918 errno = saved_errno;
1919 return fd;
1920 }
1921
1922 /* OK, drop into the poll loop looking for something to read on the fd */
1923 my_assert((flags & VKI_O_ACCMODE) == VKI_O_RDONLY);
1924 for(;;) {
1925 struct pollfd pollfd;
1926 int res;
1927
1928 pollfd.fd = fd;
1929 pollfd.events = POLLIN;
1930 pollfd.revents = 0;
1931
1932 res = my_do_syscall3(__NR_poll, (int)&pollfd, 1, 0);
1933
1934 my_assert(res == 0 || res == 1);
1935
1936 if (res == 1) {
1937 /* OK, got it.
1938
1939 XXX This is wrong: we're waiting for either something to
1940 read or a HUP on the file descriptor, but the semantics of
1941 fifo open are that we should unblock as soon as someone
1942 simply opens the other end, not that they write something.
1943 With luck this won't matter in practice.
1944 */
1945 my_assert(pollfd.revents & (POLLIN|POLLHUP));
1946 break;
1947 }
1948
1949 /* Still nobody home; sleep and spin */
1950 nanosleep_interval.tv_sec = 0;
1951 nanosleep_interval.tv_nsec = 13 * 1000 * 1000; /* 13 milliseconds */
1952 /* It's critical here that valgrind's nanosleep implementation
1953 is nonblocking. */
1954 (void)my_do_syscall2(__NR_nanosleep,
1955 (int)(&nanosleep_interval), (int)NULL);
1956 }
1957
1958 errno = saved_errno;
1959 return fd;
sewardjbe32e452002-04-24 20:29:58 +00001960}
1961
sewardjf912dfc2002-11-13 21:51:10 +00001962extern
1963int __libc_open64(const char *pathname, int flags, mode_t mode);
1964/* __attribute__((weak)) */
1965int open64(const char *pathname, int flags, mode_t mode)
1966{
1967 return _open(pathname, flags, mode, __libc_open64);
1968}
sewardje663cb92002-04-12 10:26:32 +00001969
1970extern
sewardj853f55d2002-04-26 00:27:53 +00001971int __libc_open(const char *pathname, int flags, mode_t mode);
sewardjf912dfc2002-11-13 21:51:10 +00001972/* __attribute__((weak)) */
sewardj853f55d2002-04-26 00:27:53 +00001973int open(const char *pathname, int flags, mode_t mode)
sewardje663cb92002-04-12 10:26:32 +00001974{
sewardjf912dfc2002-11-13 21:51:10 +00001975 return _open(pathname, flags, mode, __libc_open);
sewardje663cb92002-04-12 10:26:32 +00001976}
1977
sewardje663cb92002-04-12 10:26:32 +00001978extern
1979int __libc_close(int fd);
sewardj5905fae2002-04-26 13:25:00 +00001980__attribute__((weak))
sewardje663cb92002-04-12 10:26:32 +00001981int close(int fd)
1982{
sewardjd140e442002-05-29 01:21:19 +00001983 __my_pthread_testcancel();
sewardj45b4b372002-04-16 22:50:32 +00001984 return __libc_close(fd);
sewardje663cb92002-04-12 10:26:32 +00001985}
1986
1987
1988extern
1989int __libc_accept(int s, struct sockaddr *addr, socklen_t *addrlen);
sewardjf220ccc2002-10-23 21:53:49 +00001990
1991int VGL_(accept)(int s, struct sockaddr *addr, socklen_t *addrlen)
sewardje663cb92002-04-12 10:26:32 +00001992{
sewardjd140e442002-05-29 01:21:19 +00001993 __my_pthread_testcancel();
sewardj705d3cb2002-05-23 13:13:12 +00001994 wait_for_fd_to_be_readable_or_erring(s);
sewardjd140e442002-05-29 01:21:19 +00001995 __my_pthread_testcancel();
sewardj45b4b372002-04-16 22:50:32 +00001996 return __libc_accept(s, addr, addrlen);
sewardje663cb92002-04-12 10:26:32 +00001997}
1998
sewardj0c573af92002-10-23 21:55:01 +00001999extern
2000int __libc_recv(int s, void *buf, size_t len, int flags);
2001
2002int VGL_(recv)(int s, void *buf, size_t len, int flags)
2003{
2004 __my_pthread_testcancel();
2005 wait_for_fd_to_be_readable_or_erring(s);
2006 __my_pthread_testcancel();
2007 return __libc_recv(s, buf, len, flags);
2008}
2009
sewardj2a68e7e2002-11-16 11:04:18 +00002010int VGL_(readv)(int fd, const struct iovec *iov, int count)
2011{
sewardjfd7747b2002-12-01 10:25:53 +00002012 int res;
2013
sewardj2a68e7e2002-11-16 11:04:18 +00002014 __my_pthread_testcancel();
2015 wait_for_fd_to_be_readable_or_erring(fd);
2016 __my_pthread_testcancel();
sewardjfd7747b2002-12-01 10:25:53 +00002017 res = my_do_syscall3(__NR_readv, fd, (unsigned)iov, count);
2018
2019 if (is_kerror(res)) {
2020 *(__errno_location()) = -res;
2021 return -1;
2022 }
2023 return res;
sewardj2a68e7e2002-11-16 11:04:18 +00002024}
2025
2026int VGL_(writev)(int fd, struct iovec *iov, int count)
2027{
sewardjfd7747b2002-12-01 10:25:53 +00002028 int res;
2029
sewardj2a68e7e2002-11-16 11:04:18 +00002030 __my_pthread_testcancel();
2031 wait_for_fd_to_be_writable_or_erring(fd);
2032 __my_pthread_testcancel();
sewardjfd7747b2002-12-01 10:25:53 +00002033 res = my_do_syscall3(__NR_writev, fd, (unsigned)iov, count);
2034
2035 if (is_kerror(res)) {
2036 *(__errno_location()) = -res;
2037 return -1;
2038 }
2039 return res;
sewardj2a68e7e2002-11-16 11:04:18 +00002040}
sewardje663cb92002-04-12 10:26:32 +00002041
2042extern
sewardje663cb92002-04-12 10:26:32 +00002043pid_t __libc_waitpid(pid_t pid, int *status, int options);
sewardj5905fae2002-04-26 13:25:00 +00002044__attribute__((weak))
sewardje663cb92002-04-12 10:26:32 +00002045pid_t waitpid(pid_t pid, int *status, int options)
2046{
sewardjd140e442002-05-29 01:21:19 +00002047 __my_pthread_testcancel();
sewardj45b4b372002-04-16 22:50:32 +00002048 return __libc_waitpid(pid, status, options);
sewardje663cb92002-04-12 10:26:32 +00002049}
2050
2051
2052extern
2053int __libc_nanosleep(const struct timespec *req, struct timespec *rem);
sewardj5905fae2002-04-26 13:25:00 +00002054__attribute__((weak))
sewardje663cb92002-04-12 10:26:32 +00002055int nanosleep(const struct timespec *req, struct timespec *rem)
2056{
sewardjd140e442002-05-29 01:21:19 +00002057 __my_pthread_testcancel();
sewardje663cb92002-04-12 10:26:32 +00002058 return __libc_nanosleep(req, rem);
2059}
2060
sewardjbe32e452002-04-24 20:29:58 +00002061
sewardje663cb92002-04-12 10:26:32 +00002062extern
2063int __libc_fsync(int fd);
sewardj5905fae2002-04-26 13:25:00 +00002064__attribute__((weak))
sewardje663cb92002-04-12 10:26:32 +00002065int fsync(int fd)
2066{
sewardjd140e442002-05-29 01:21:19 +00002067 __my_pthread_testcancel();
sewardj45b4b372002-04-16 22:50:32 +00002068 return __libc_fsync(fd);
sewardje663cb92002-04-12 10:26:32 +00002069}
2070
sewardjbe32e452002-04-24 20:29:58 +00002071
sewardj70c75362002-04-13 04:18:32 +00002072extern
2073off_t __libc_lseek(int fildes, off_t offset, int whence);
sewardj5905fae2002-04-26 13:25:00 +00002074__attribute__((weak))
sewardj70c75362002-04-13 04:18:32 +00002075off_t lseek(int fildes, off_t offset, int whence)
2076{
sewardjd140e442002-05-29 01:21:19 +00002077 __my_pthread_testcancel();
sewardj45b4b372002-04-16 22:50:32 +00002078 return __libc_lseek(fildes, offset, whence);
sewardj70c75362002-04-13 04:18:32 +00002079}
2080
sewardjbe32e452002-04-24 20:29:58 +00002081
2082extern
2083__off64_t __libc_lseek64(int fildes, __off64_t offset, int whence);
sewardj5905fae2002-04-26 13:25:00 +00002084__attribute__((weak))
sewardjbe32e452002-04-24 20:29:58 +00002085__off64_t lseek64(int fildes, __off64_t offset, int whence)
2086{
sewardjd140e442002-05-29 01:21:19 +00002087 __my_pthread_testcancel();
sewardjbe32e452002-04-24 20:29:58 +00002088 return __libc_lseek64(fildes, offset, whence);
2089}
2090
2091
sewardj726c4122002-05-16 23:39:10 +00002092extern
2093ssize_t __libc_pread64 (int __fd, void *__buf, size_t __nbytes,
2094 __off64_t __offset);
2095ssize_t __pread64 (int __fd, void *__buf, size_t __nbytes,
2096 __off64_t __offset)
2097{
sewardjd140e442002-05-29 01:21:19 +00002098 __my_pthread_testcancel();
sewardj726c4122002-05-16 23:39:10 +00002099 return __libc_pread64(__fd, __buf, __nbytes, __offset);
2100}
2101
2102
sewardja18e2102002-05-18 10:43:22 +00002103extern
2104ssize_t __libc_pwrite64 (int __fd, const void *__buf, size_t __nbytes,
2105 __off64_t __offset);
2106ssize_t __pwrite64 (int __fd, const void *__buf, size_t __nbytes,
2107 __off64_t __offset)
2108{
sewardjd140e442002-05-29 01:21:19 +00002109 __my_pthread_testcancel();
sewardja18e2102002-05-18 10:43:22 +00002110 return __libc_pwrite64(__fd, __buf, __nbytes, __offset);
2111}
2112
sewardj726c4122002-05-16 23:39:10 +00002113
sewardj39b93b12002-05-18 10:56:27 +00002114extern
2115ssize_t __libc_pwrite(int fd, const void *buf, size_t count, off_t offset);
2116__attribute__((weak))
2117ssize_t pwrite(int fd, const void *buf, size_t count, off_t offset)
2118{
sewardjd140e442002-05-29 01:21:19 +00002119 __my_pthread_testcancel();
sewardj39b93b12002-05-18 10:56:27 +00002120 return __libc_pwrite(fd, buf, count, offset);
2121}
2122
2123
2124extern
2125ssize_t __libc_pread(int fd, void *buf, size_t count, off_t offset);
2126__attribute__((weak))
2127ssize_t pread(int fd, void *buf, size_t count, off_t offset)
2128{
sewardjd140e442002-05-29 01:21:19 +00002129 __my_pthread_testcancel();
sewardj39b93b12002-05-18 10:56:27 +00002130 return __libc_pread(fd, buf, count, offset);
2131}
2132
2133
sewardj6af4b5d2002-04-16 04:40:49 +00002134extern
2135void __libc_longjmp(jmp_buf env, int val) __attribute((noreturn));
sewardj5905fae2002-04-26 13:25:00 +00002136/* not weak: __attribute__((weak)) */
sewardj6af4b5d2002-04-16 04:40:49 +00002137void longjmp(jmp_buf env, int val)
2138{
2139 __libc_longjmp(env, val);
2140}
2141
sewardjbe32e452002-04-24 20:29:58 +00002142
sewardj436c2db2002-06-18 09:07:54 +00002143extern void __libc_siglongjmp (sigjmp_buf env, int val)
2144 __attribute__ ((noreturn));
2145void siglongjmp(sigjmp_buf env, int val)
2146{
2147 kludged("siglongjmp (cleanup handlers are ignored)");
2148 __libc_siglongjmp(env, val);
2149}
2150
2151
sewardj6af4b5d2002-04-16 04:40:49 +00002152extern
2153int __libc_send(int s, const void *msg, size_t len, int flags);
sewardj5905fae2002-04-26 13:25:00 +00002154__attribute__((weak))
sewardj6af4b5d2002-04-16 04:40:49 +00002155int send(int s, const void *msg, size_t len, int flags)
2156{
sewardjd140e442002-05-29 01:21:19 +00002157 __my_pthread_testcancel();
sewardj6af4b5d2002-04-16 04:40:49 +00002158 return __libc_send(s, msg, len, flags);
2159}
2160
sewardjbe32e452002-04-24 20:29:58 +00002161
sewardj1e8cdc92002-04-18 11:37:52 +00002162extern
2163int __libc_recv(int s, void *buf, size_t len, int flags);
sewardj5905fae2002-04-26 13:25:00 +00002164__attribute__((weak))
sewardj1e8cdc92002-04-18 11:37:52 +00002165int recv(int s, void *buf, size_t len, int flags)
2166{
sewardjd140e442002-05-29 01:21:19 +00002167 __my_pthread_testcancel();
sewardj1d6b3a22002-06-20 07:58:33 +00002168 wait_for_fd_to_be_readable_or_erring(s);
2169 __my_pthread_testcancel();
sewardj1e8cdc92002-04-18 11:37:52 +00002170 return __libc_recv(s, buf, len, flags);
2171}
2172
sewardjbe32e452002-04-24 20:29:58 +00002173
sewardj3665ded2002-05-16 16:57:25 +00002174extern
2175int __libc_sendmsg(int s, const struct msghdr *msg, int flags);
2176__attribute__((weak))
2177int sendmsg(int s, const struct msghdr *msg, int flags)
2178{
sewardjd140e442002-05-29 01:21:19 +00002179 __my_pthread_testcancel();
sewardj3665ded2002-05-16 16:57:25 +00002180 return __libc_sendmsg(s, msg, flags);
2181}
2182
2183
sewardj796d6a22002-04-24 02:28:34 +00002184extern
sewardj59da27a2002-06-06 08:33:54 +00002185int __libc_recvmsg(int s, struct msghdr *msg, int flags);
2186__attribute__((weak))
2187int recvmsg(int s, struct msghdr *msg, int flags)
2188{
2189 __my_pthread_testcancel();
2190 return __libc_recvmsg(s, msg, flags);
2191}
2192
2193
2194extern
sewardj436e0582002-04-26 14:31:40 +00002195int __libc_recvfrom(int s, void *buf, size_t len, int flags,
2196 struct sockaddr *from, socklen_t *fromlen);
2197__attribute__((weak))
2198int recvfrom(int s, void *buf, size_t len, int flags,
2199 struct sockaddr *from, socklen_t *fromlen)
2200{
sewardjd140e442002-05-29 01:21:19 +00002201 __my_pthread_testcancel();
sewardj2e207632002-06-13 17:29:53 +00002202 wait_for_fd_to_be_readable_or_erring(s);
2203 __my_pthread_testcancel();
sewardj436e0582002-04-26 14:31:40 +00002204 return __libc_recvfrom(s, buf, len, flags, from, fromlen);
2205}
2206
2207
2208extern
sewardj796d6a22002-04-24 02:28:34 +00002209int __libc_sendto(int s, const void *msg, size_t len, int flags,
2210 const struct sockaddr *to, socklen_t tolen);
sewardj5905fae2002-04-26 13:25:00 +00002211__attribute__((weak))
sewardj796d6a22002-04-24 02:28:34 +00002212int sendto(int s, const void *msg, size_t len, int flags,
2213 const struct sockaddr *to, socklen_t tolen)
2214{
sewardjd140e442002-05-29 01:21:19 +00002215 __my_pthread_testcancel();
sewardj796d6a22002-04-24 02:28:34 +00002216 return __libc_sendto(s, msg, len, flags, to, tolen);
2217}
2218
sewardjbe32e452002-04-24 20:29:58 +00002219
sewardj369b1702002-04-24 13:28:15 +00002220extern
2221int __libc_system(const char* str);
sewardj5905fae2002-04-26 13:25:00 +00002222__attribute__((weak))
sewardj369b1702002-04-24 13:28:15 +00002223int system(const char* str)
2224{
sewardjd140e442002-05-29 01:21:19 +00002225 __my_pthread_testcancel();
sewardj369b1702002-04-24 13:28:15 +00002226 return __libc_system(str);
2227}
2228
sewardjbe32e452002-04-24 20:29:58 +00002229
sewardjab0b1c32002-04-24 19:26:47 +00002230extern
2231pid_t __libc_wait(int *status);
sewardj5905fae2002-04-26 13:25:00 +00002232__attribute__((weak))
sewardjab0b1c32002-04-24 19:26:47 +00002233pid_t wait(int *status)
2234{
sewardjd140e442002-05-29 01:21:19 +00002235 __my_pthread_testcancel();
sewardjab0b1c32002-04-24 19:26:47 +00002236 return __libc_wait(status);
2237}
2238
sewardj45b4b372002-04-16 22:50:32 +00002239
sewardj67f1d582002-05-24 02:11:32 +00002240extern
2241int __libc_msync(const void *start, size_t length, int flags);
2242__attribute__((weak))
2243int msync(const void *start, size_t length, int flags)
2244{
sewardjd140e442002-05-29 01:21:19 +00002245 __my_pthread_testcancel();
sewardj67f1d582002-05-24 02:11:32 +00002246 return __libc_msync(start, length, flags);
2247}
2248
sewardj5905fae2002-04-26 13:25:00 +00002249
sewardj2cb00342002-06-28 01:46:26 +00002250/*--- fork and its helper ---*/
2251
2252static
2253void run_fork_handlers ( int what )
2254{
2255 ForkHandlerEntry entry;
2256 int n_h, n_handlers, i, res;
2257
2258 my_assert(what == 0 || what == 1 || what == 2);
2259
2260 /* Fetch old counter */
2261 VALGRIND_MAGIC_SEQUENCE(n_handlers, -2 /* default */,
2262 VG_USERREQ__GET_FHSTACK_USED,
2263 0, 0, 0, 0);
2264 my_assert(n_handlers >= 0 && n_handlers < VG_N_FORKHANDLERSTACK);
2265
2266 /* Prepare handlers (what == 0) are called in opposite order of
2267 calls to pthread_atfork. Parent and child handlers are called
2268 in the same order as calls to pthread_atfork. */
2269 if (what == 0)
2270 n_h = n_handlers - 1;
2271 else
2272 n_h = 0;
2273
2274 for (i = 0; i < n_handlers; i++) {
2275 VALGRIND_MAGIC_SEQUENCE(res, -2 /* default */,
2276 VG_USERREQ__GET_FHSTACK_ENTRY,
2277 n_h, &entry, 0, 0);
2278 my_assert(res == 0);
2279 switch (what) {
2280 case 0: if (entry.prepare) entry.prepare();
2281 n_h--; break;
2282 case 1: if (entry.parent) entry.parent();
2283 n_h++; break;
2284 case 2: if (entry.child) entry.child();
2285 n_h++; break;
2286 default: barf("run_fork_handlers: invalid what");
2287 }
2288 }
2289
2290 if (what != 0 /* prepare */) {
2291 /* Empty out the stack. */
2292 VALGRIND_MAGIC_SEQUENCE(res, -2 /* default */,
2293 VG_USERREQ__SET_FHSTACK_USED,
2294 0, 0, 0, 0);
2295 my_assert(res == 0);
2296 }
2297}
2298
2299extern
2300pid_t __libc_fork(void);
2301pid_t __fork(void)
2302{
2303 pid_t pid;
2304 __my_pthread_testcancel();
2305 __pthread_mutex_lock(&pthread_atfork_lock);
2306
2307 run_fork_handlers(0 /* prepare */);
2308 pid = __libc_fork();
2309 if (pid == 0) {
2310 /* I am the child */
2311 run_fork_handlers(2 /* child */);
sewardjd8acdf22002-11-13 21:57:52 +00002312 __pthread_mutex_unlock(&pthread_atfork_lock);
sewardj2cb00342002-06-28 01:46:26 +00002313 __pthread_mutex_init(&pthread_atfork_lock, NULL);
2314 } else {
2315 /* I am the parent */
2316 run_fork_handlers(1 /* parent */);
2317 __pthread_mutex_unlock(&pthread_atfork_lock);
2318 }
2319 return pid;
2320}
2321
2322
njn25e49d8e72002-09-23 09:36:25 +00002323pid_t __vfork(void)
2324{
2325 return __fork();
2326}
sewardj2cb00342002-06-28 01:46:26 +00002327
2328
sewardj3b13f0e2002-04-25 20:17:29 +00002329/* ---------------------------------------------------------------------
2330 Nonblocking implementations of select() and poll(). This stuff will
2331 surely rot your mind.
2332 ------------------------------------------------------------------ */
sewardje663cb92002-04-12 10:26:32 +00002333
sewardj08a4c3f2002-04-13 03:45:44 +00002334/*--------------------------------------------------*/
2335
2336#include "vg_kerneliface.h"
2337
2338static
sewardj08a4c3f2002-04-13 03:45:44 +00002339int my_do_syscall1 ( int syscallno, int arg1 )
2340{
2341 int __res;
2342 __asm__ volatile ("pushl %%ebx; movl %%edx,%%ebx ; int $0x80 ; popl %%ebx"
2343 : "=a" (__res)
2344 : "0" (syscallno),
2345 "d" (arg1) );
2346 return __res;
2347}
2348
2349static
2350int my_do_syscall2 ( int syscallno,
sewardjf854f472002-04-21 12:19:41 +00002351 int arg1, int arg2 )
sewardj08a4c3f2002-04-13 03:45:44 +00002352{
2353 int __res;
2354 __asm__ volatile ("pushl %%ebx; movl %%edx,%%ebx ; int $0x80 ; popl %%ebx"
2355 : "=a" (__res)
2356 : "0" (syscallno),
2357 "d" (arg1),
2358 "c" (arg2) );
2359 return __res;
2360}
2361
2362static
sewardjf854f472002-04-21 12:19:41 +00002363int my_do_syscall3 ( int syscallno,
2364 int arg1, int arg2, int arg3 )
2365{
2366 int __res;
2367 __asm__ volatile ("pushl %%ebx; movl %%esi,%%ebx ; int $0x80 ; popl %%ebx"
2368 : "=a" (__res)
2369 : "0" (syscallno),
2370 "S" (arg1),
2371 "c" (arg2),
2372 "d" (arg3) );
2373 return __res;
2374}
2375
sewardjd5bef572002-10-23 21:49:33 +00002376static inline
2377int my_do_syscall5 ( int syscallno,
2378 int arg1, int arg2, int arg3, int arg4, int arg5 )
2379{
2380 int __res;
2381 __asm__ volatile ("int $0x80"
2382 : "=a" (__res)
2383 : "0" (syscallno),
2384 "b" (arg1),
2385 "c" (arg2),
2386 "d" (arg3),
2387 "S" (arg4),
2388 "D" (arg5));
2389 return __res;
2390}
2391
sewardjf854f472002-04-21 12:19:41 +00002392static
sewardj08a4c3f2002-04-13 03:45:44 +00002393int do_syscall_select( int n,
2394 vki_fd_set* readfds,
2395 vki_fd_set* writefds,
2396 vki_fd_set* exceptfds,
2397 struct vki_timeval * timeout )
2398{
2399 int res;
2400 int args[5];
2401 args[0] = n;
2402 args[1] = (int)readfds;
2403 args[2] = (int)writefds;
2404 args[3] = (int)exceptfds;
2405 args[4] = (int)timeout;
2406 res = my_do_syscall1(__NR_select, (int)(&(args[0])) );
sewardj02535bc2002-04-21 01:08:26 +00002407 return res;
sewardj08a4c3f2002-04-13 03:45:44 +00002408}
2409
2410
2411/* This is a wrapper round select(), which makes it thread-safe,
2412 meaning that only this thread will block, rather than the entire
2413 process. This wrapper in turn depends on nanosleep() not to block
2414 the entire process, but I think (hope? suspect?) that POSIX
2415 pthreads guarantees that to be the case.
2416
2417 Basic idea is: modify the timeout parameter to select so that it
2418 returns immediately. Poll like this until select returns non-zero,
2419 indicating something interesting happened, or until our time is up.
njn25e49d8e72002-09-23 09:36:25 +00002420 Space out the polls with nanosleeps of say 11 milliseconds, which
sewardj08a4c3f2002-04-13 03:45:44 +00002421 is required to be nonblocking; this allows other threads to run.
sewardj02535bc2002-04-21 01:08:26 +00002422
2423 Assumes:
sewardj2d94c112002-06-03 01:25:54 +00002424 * (checked via my_assert) types fd_set and vki_fd_set are identical.
2425 * (checked via my_assert) types timeval and vki_timeval are identical.
sewardj02535bc2002-04-21 01:08:26 +00002426 * (unchecked) libc error numbers (EINTR etc) are the negation of the
2427 kernel's error numbers (VKI_EINTR etc).
sewardj08a4c3f2002-04-13 03:45:44 +00002428*/
sewardj08a4c3f2002-04-13 03:45:44 +00002429
sewardj7db011a2002-11-13 22:00:20 +00002430int VGL_(select) ( int n,
2431 fd_set *rfds,
2432 fd_set *wfds,
2433 fd_set *xfds,
2434 struct timeval *timeout )
sewardj08a4c3f2002-04-13 03:45:44 +00002435{
sewardj5f07b662002-04-23 16:52:51 +00002436 unsigned int ms_now, ms_end;
sewardj08a4c3f2002-04-13 03:45:44 +00002437 int res;
2438 fd_set rfds_copy;
2439 fd_set wfds_copy;
2440 fd_set xfds_copy;
2441 struct vki_timeval t_now;
sewardj08a4c3f2002-04-13 03:45:44 +00002442 struct vki_timeval zero_timeout;
2443 struct vki_timespec nanosleep_interval;
2444
sewardjd140e442002-05-29 01:21:19 +00002445 __my_pthread_testcancel();
2446
sewardj5f07b662002-04-23 16:52:51 +00002447 /* gcc's complains about ms_end being used uninitialised -- classic
2448 case it can't understand, where ms_end is both defined and used
2449 only if timeout != NULL. Hence ... */
2450 ms_end = 0;
sewardj08a4c3f2002-04-13 03:45:44 +00002451
2452 /* We assume that the kernel and libc data layouts are identical
2453 for the following types. These asserts provide a crude
2454 check. */
2455 if (sizeof(fd_set) != sizeof(vki_fd_set)
2456 || sizeof(struct timeval) != sizeof(struct vki_timeval))
2457 barf("valgrind's hacky non-blocking select(): data sizes error");
2458
sewardj5f07b662002-04-23 16:52:51 +00002459 /* Detect the current time and simultaneously find out if we are
2460 running on Valgrind. */
2461 VALGRIND_MAGIC_SEQUENCE(ms_now, 0xFFFFFFFF /* default */,
2462 VG_USERREQ__READ_MILLISECOND_TIMER,
2463 0, 0, 0, 0);
2464
2465 /* If a zero timeout specified, this call is harmless. Also go
2466 this route if we're not running on Valgrind, for whatever
2467 reason. */
2468 if ( (timeout && timeout->tv_sec == 0 && timeout->tv_usec == 0)
2469 || (ms_now == 0xFFFFFFFF) ) {
sewardj02535bc2002-04-21 01:08:26 +00002470 res = do_syscall_select( n, (vki_fd_set*)rfds,
sewardj08a4c3f2002-04-13 03:45:44 +00002471 (vki_fd_set*)wfds,
2472 (vki_fd_set*)xfds,
2473 (struct vki_timeval*)timeout);
sewardj02535bc2002-04-21 01:08:26 +00002474 if (is_kerror(res)) {
2475 * (__errno_location()) = -res;
2476 return -1;
2477 } else {
2478 return res;
2479 }
2480 }
sewardj08a4c3f2002-04-13 03:45:44 +00002481
sewardj5f07b662002-04-23 16:52:51 +00002482 /* If a timeout was specified, set ms_end to be the end millisecond
2483 counter [wallclock] time. */
sewardj08a4c3f2002-04-13 03:45:44 +00002484 if (timeout) {
2485 res = my_do_syscall2(__NR_gettimeofday, (int)&t_now, (int)NULL);
sewardj2d94c112002-06-03 01:25:54 +00002486 my_assert(res == 0);
sewardj5f07b662002-04-23 16:52:51 +00002487 ms_end = ms_now;
2488 ms_end += (timeout->tv_usec / 1000);
2489 ms_end += (timeout->tv_sec * 1000);
sewardj08a4c3f2002-04-13 03:45:44 +00002490 /* Stay sane ... */
sewardj2d94c112002-06-03 01:25:54 +00002491 my_assert (ms_end >= ms_now);
sewardj08a4c3f2002-04-13 03:45:44 +00002492 }
2493
2494 /* fprintf(stderr, "MY_SELECT: before loop\n"); */
2495
2496 /* Either timeout == NULL, meaning wait indefinitely, or timeout !=
sewardj5f07b662002-04-23 16:52:51 +00002497 NULL, in which case ms_end holds the end time. */
sewardj05bb2c92002-06-26 00:47:17 +00002498
sewardj08a4c3f2002-04-13 03:45:44 +00002499 while (1) {
sewardj05bb2c92002-06-26 00:47:17 +00002500
2501 /* First, do a return-immediately select(). */
sewardj08a4c3f2002-04-13 03:45:44 +00002502
2503 /* These could be trashed each time round the loop, so restore
2504 them each time. */
2505 if (rfds) rfds_copy = *rfds;
2506 if (wfds) wfds_copy = *wfds;
2507 if (xfds) xfds_copy = *xfds;
2508
2509 zero_timeout.tv_sec = zero_timeout.tv_usec = 0;
2510
2511 res = do_syscall_select( n,
2512 rfds ? (vki_fd_set*)(&rfds_copy) : NULL,
2513 wfds ? (vki_fd_set*)(&wfds_copy) : NULL,
2514 xfds ? (vki_fd_set*)(&xfds_copy) : NULL,
2515 & zero_timeout );
sewardj02535bc2002-04-21 01:08:26 +00002516 if (is_kerror(res)) {
2517 /* Some kind of error (including EINTR). Set errno and
sewardj08a4c3f2002-04-13 03:45:44 +00002518 return. The sets are unspecified in this case. */
sewardj02535bc2002-04-21 01:08:26 +00002519 * (__errno_location()) = -res;
2520 return -1;
sewardj08a4c3f2002-04-13 03:45:44 +00002521 }
2522 if (res > 0) {
2523 /* one or more fds is ready. Copy out resulting sets and
2524 return. */
2525 if (rfds) *rfds = rfds_copy;
2526 if (wfds) *wfds = wfds_copy;
2527 if (xfds) *xfds = xfds_copy;
2528 return res;
2529 }
sewardj05bb2c92002-06-26 00:47:17 +00002530
2531 /* Nothing interesting happened, so we go to sleep for a
2532 while. */
2533
sewardj08a4c3f2002-04-13 03:45:44 +00002534 /* fprintf(stderr, "MY_SELECT: nanosleep\n"); */
2535 /* nanosleep and go round again */
sewardj02535bc2002-04-21 01:08:26 +00002536 nanosleep_interval.tv_sec = 0;
njn25e49d8e72002-09-23 09:36:25 +00002537 nanosleep_interval.tv_nsec = 11 * 1000 * 1000; /* 11 milliseconds */
sewardjf854f472002-04-21 12:19:41 +00002538 /* It's critical here that valgrind's nanosleep implementation
2539 is nonblocking. */
sewardj645030e2002-06-06 01:27:39 +00002540 res = my_do_syscall2(__NR_nanosleep,
sewardjf854f472002-04-21 12:19:41 +00002541 (int)(&nanosleep_interval), (int)NULL);
sewardj645030e2002-06-06 01:27:39 +00002542 if (res == -VKI_EINTR) {
2543 /* The nanosleep was interrupted by a signal. So we do the
2544 same. */
2545 * (__errno_location()) = EINTR;
2546 return -1;
2547 }
sewardj05bb2c92002-06-26 00:47:17 +00002548
2549 /* Sleeping finished. If a finite timeout, check to see if it
2550 has expired yet. */
2551 if (timeout) {
2552 VALGRIND_MAGIC_SEQUENCE(ms_now, 0xFFFFFFFF /* default */,
2553 VG_USERREQ__READ_MILLISECOND_TIMER,
2554 0, 0, 0, 0);
2555 my_assert(ms_now != 0xFFFFFFFF);
2556 if (ms_now >= ms_end) {
2557 /* timeout; nothing interesting happened. */
2558 if (rfds) FD_ZERO(rfds);
2559 if (wfds) FD_ZERO(wfds);
2560 if (xfds) FD_ZERO(xfds);
2561 return 0;
2562 }
2563 }
2564
sewardjf854f472002-04-21 12:19:41 +00002565 }
2566}
2567
2568
2569
2570
2571#include <sys/poll.h>
2572
sewardj3e909ce2002-06-03 13:27:15 +00002573#ifndef HAVE_NFDS_T
sewardj72d58482002-04-24 02:20:20 +00002574typedef unsigned long int nfds_t;
2575#endif
2576
sewardj705d3cb2002-05-23 13:13:12 +00002577
sewardj7db011a2002-11-13 22:00:20 +00002578int VGL_(poll) (struct pollfd *__fds, nfds_t __nfds, int __timeout)
sewardjf854f472002-04-21 12:19:41 +00002579{
sewardj5f07b662002-04-23 16:52:51 +00002580 unsigned int ms_now, ms_end;
sewardjf854f472002-04-21 12:19:41 +00002581 int res, i;
sewardjf854f472002-04-21 12:19:41 +00002582 struct vki_timespec nanosleep_interval;
2583
sewardjd140e442002-05-29 01:21:19 +00002584 __my_pthread_testcancel();
sewardjf854f472002-04-21 12:19:41 +00002585 ensure_valgrind("poll");
2586
sewardj5f07b662002-04-23 16:52:51 +00002587 /* Detect the current time and simultaneously find out if we are
2588 running on Valgrind. */
2589 VALGRIND_MAGIC_SEQUENCE(ms_now, 0xFFFFFFFF /* default */,
2590 VG_USERREQ__READ_MILLISECOND_TIMER,
2591 0, 0, 0, 0);
2592
sewardjf854f472002-04-21 12:19:41 +00002593 if (/* CHECK SIZES FOR struct pollfd */
2594 sizeof(struct timeval) != sizeof(struct vki_timeval))
2595 barf("valgrind's hacky non-blocking poll(): data sizes error");
2596
sewardj5f07b662002-04-23 16:52:51 +00002597 /* dummy initialisation to keep gcc -Wall happy */
2598 ms_end = 0;
2599
2600 /* If a zero timeout specified, this call is harmless. Also do
2601 this if not running on Valgrind. */
2602 if (__timeout == 0 || ms_now == 0xFFFFFFFF) {
sewardjf854f472002-04-21 12:19:41 +00002603 res = my_do_syscall3(__NR_poll, (int)__fds, __nfds, __timeout);
2604 if (is_kerror(res)) {
2605 * (__errno_location()) = -res;
2606 return -1;
2607 } else {
2608 return res;
2609 }
2610 }
2611
sewardj5f07b662002-04-23 16:52:51 +00002612 /* If a timeout was specified, set ms_end to be the end wallclock
2613 time. Easy considering that __timeout is in milliseconds. */
sewardjf854f472002-04-21 12:19:41 +00002614 if (__timeout > 0) {
sewardj650ac002002-04-29 12:20:34 +00002615 ms_end = ms_now + (unsigned int)__timeout;
sewardjf854f472002-04-21 12:19:41 +00002616 }
2617
2618 /* fprintf(stderr, "MY_POLL: before loop\n"); */
2619
2620 /* Either timeout < 0, meaning wait indefinitely, or timeout > 0,
2621 in which case t_end holds the end time. */
sewardj05bb2c92002-06-26 00:47:17 +00002622
sewardj2d94c112002-06-03 01:25:54 +00002623 my_assert(__timeout != 0);
sewardj5f07b662002-04-23 16:52:51 +00002624
sewardjf854f472002-04-21 12:19:41 +00002625 while (1) {
sewardj05bb2c92002-06-26 00:47:17 +00002626
2627 /* Do a return-immediately poll. */
2628
2629 res = my_do_syscall3(__NR_poll, (int)__fds, __nfds, 0 );
2630 if (is_kerror(res)) {
2631 /* Some kind of error. Set errno and return. */
2632 * (__errno_location()) = -res;
2633 return -1;
2634 }
2635 if (res > 0) {
2636 /* One or more fds is ready. Return now. */
2637 return res;
2638 }
2639
2640 /* Nothing interesting happened, so we go to sleep for a
2641 while. */
2642
2643 /* fprintf(stderr, "MY_POLL: nanosleep\n"); */
2644 /* nanosleep and go round again */
2645 nanosleep_interval.tv_sec = 0;
njn25e49d8e72002-09-23 09:36:25 +00002646 nanosleep_interval.tv_nsec = 13 * 1000 * 1000; /* 13 milliseconds */
sewardj05bb2c92002-06-26 00:47:17 +00002647 /* It's critical here that valgrind's nanosleep implementation
2648 is nonblocking. */
2649 (void)my_do_syscall2(__NR_nanosleep,
2650 (int)(&nanosleep_interval), (int)NULL);
2651
2652 /* Sleeping finished. If a finite timeout, check to see if it
2653 has expired yet. */
sewardjf854f472002-04-21 12:19:41 +00002654 if (__timeout > 0) {
sewardj5f07b662002-04-23 16:52:51 +00002655 VALGRIND_MAGIC_SEQUENCE(ms_now, 0xFFFFFFFF /* default */,
2656 VG_USERREQ__READ_MILLISECOND_TIMER,
2657 0, 0, 0, 0);
sewardj2d94c112002-06-03 01:25:54 +00002658 my_assert(ms_now != 0xFFFFFFFF);
sewardj5f07b662002-04-23 16:52:51 +00002659 if (ms_now >= ms_end) {
sewardjf854f472002-04-21 12:19:41 +00002660 /* timeout; nothing interesting happened. */
2661 for (i = 0; i < __nfds; i++)
2662 __fds[i].revents = 0;
2663 return 0;
2664 }
2665 }
2666
sewardj08a4c3f2002-04-13 03:45:44 +00002667 }
2668}
sewardj3b13f0e2002-04-25 20:17:29 +00002669
2670
sewardj705d3cb2002-05-23 13:13:12 +00002671/* Helper function used to make accept() non-blocking. Idea is to use
2672 the above nonblocking poll() to make this thread ONLY wait for the
2673 specified fd to become ready, and then return. */
sewardjd1c1cf22002-06-26 00:13:36 +00002674
2675/* Sigh -- a hack. We're not supposed to include this file directly;
2676 should do it via /usr/include/fcntl.h, but that introduces a
2677 varargs prototype for fcntl itself, which we can't mimic. */
2678#define _FCNTL_H
2679#include <bits/fcntl.h>
2680
sewardj705d3cb2002-05-23 13:13:12 +00002681static void wait_for_fd_to_be_readable_or_erring ( int fd )
2682{
2683 struct pollfd pfd;
sewardjd1c1cf22002-06-26 00:13:36 +00002684 int res;
2685
sewardj6e6cbaa2002-05-24 02:12:52 +00002686 /* fprintf(stderr, "wait_for_fd_to_be_readable_or_erring %d\n", fd); */
sewardjd1c1cf22002-06-26 00:13:36 +00002687
2688 /* First check to see if the fd is nonblocking, and/or invalid. In
2689 either case return immediately. */
2690 res = __libc_fcntl(fd, F_GETFL, 0);
2691 if (res == -1) return; /* fd is invalid somehow */
2692 if (res & O_NONBLOCK) return; /* fd is nonblocking */
2693
2694 /* Ok, we'd better wait with poll. */
sewardj705d3cb2002-05-23 13:13:12 +00002695 pfd.fd = fd;
2696 pfd.events = POLLIN | POLLPRI | POLLERR | POLLHUP | POLLNVAL;
2697 /* ... but not POLLOUT, you may notice. */
2698 pfd.revents = 0;
2699 (void)poll(&pfd, 1, -1 /* forever */);
2700}
2701
sewardj2a68e7e2002-11-16 11:04:18 +00002702static void wait_for_fd_to_be_writable_or_erring ( int fd )
2703{
2704 struct pollfd pfd;
2705 int res;
2706
2707 /* fprintf(stderr, "wait_for_fd_to_be_readable_or_erring %d\n", fd); */
2708
2709 /* First check to see if the fd is nonblocking, and/or invalid. In
2710 either case return immediately. */
2711 res = __libc_fcntl(fd, F_GETFL, 0);
2712 if (res == -1) return; /* fd is invalid somehow */
2713 if (res & O_NONBLOCK) return; /* fd is nonblocking */
2714
2715 /* Ok, we'd better wait with poll. */
2716 pfd.fd = fd;
2717 pfd.events = POLLOUT | POLLERR | POLLHUP | POLLNVAL;
2718 pfd.revents = 0;
2719 (void)poll(&pfd, 1, -1 /* forever */);
2720}
sewardj705d3cb2002-05-23 13:13:12 +00002721
sewardj3b13f0e2002-04-25 20:17:29 +00002722/* ---------------------------------------------------------------------
sewardj8f253ff2002-05-19 00:13:34 +00002723 Hacky implementation of semaphores.
2724 ------------------------------------------------------------------ */
2725
2726#include <semaphore.h>
2727
2728/* This is a terrible way to do the remapping. Plan is to import an
2729 AVL tree at some point. */
sewardj8f253ff2002-05-19 00:13:34 +00002730
2731typedef
2732 struct {
2733 pthread_mutex_t se_mx;
2734 pthread_cond_t se_cv;
2735 int count;
2736 }
2737 vg_sem_t;
2738
2739static pthread_mutex_t se_remap_mx = PTHREAD_MUTEX_INITIALIZER;
2740
2741static int se_remap_used = 0;
2742static sem_t* se_remap_orig[VG_N_SEMAPHORES];
2743static vg_sem_t se_remap_new[VG_N_SEMAPHORES];
2744
2745static vg_sem_t* se_remap ( sem_t* orig )
2746{
2747 int res, i;
2748 res = __pthread_mutex_lock(&se_remap_mx);
sewardj2d94c112002-06-03 01:25:54 +00002749 my_assert(res == 0);
sewardj8f253ff2002-05-19 00:13:34 +00002750
2751 for (i = 0; i < se_remap_used; i++) {
2752 if (se_remap_orig[i] == orig)
2753 break;
2754 }
2755 if (i == se_remap_used) {
2756 if (se_remap_used == VG_N_SEMAPHORES) {
2757 res = pthread_mutex_unlock(&se_remap_mx);
sewardj2d94c112002-06-03 01:25:54 +00002758 my_assert(res == 0);
sewardja1ac5cb2002-05-27 13:00:05 +00002759 barf("VG_N_SEMAPHORES is too low. Increase and recompile.");
sewardj8f253ff2002-05-19 00:13:34 +00002760 }
2761 se_remap_used++;
2762 se_remap_orig[i] = orig;
2763 /* printf("allocated semaphore %d\n", i); */
2764 }
2765 res = __pthread_mutex_unlock(&se_remap_mx);
sewardj2d94c112002-06-03 01:25:54 +00002766 my_assert(res == 0);
sewardj8f253ff2002-05-19 00:13:34 +00002767 return &se_remap_new[i];
2768}
2769
2770
2771int sem_init(sem_t *sem, int pshared, unsigned int value)
2772{
2773 int res;
2774 vg_sem_t* vg_sem;
2775 ensure_valgrind("sem_init");
2776 if (pshared != 0) {
sewardj4dced352002-06-04 22:54:20 +00002777 pthread_error("sem_init: unsupported pshared value");
sewardj8f253ff2002-05-19 00:13:34 +00002778 errno = ENOSYS;
2779 return -1;
2780 }
2781 vg_sem = se_remap(sem);
2782 res = pthread_mutex_init(&vg_sem->se_mx, NULL);
sewardj2d94c112002-06-03 01:25:54 +00002783 my_assert(res == 0);
sewardj8f253ff2002-05-19 00:13:34 +00002784 res = pthread_cond_init(&vg_sem->se_cv, NULL);
sewardj2d94c112002-06-03 01:25:54 +00002785 my_assert(res == 0);
sewardj8f253ff2002-05-19 00:13:34 +00002786 vg_sem->count = value;
2787 return 0;
2788}
2789
2790
2791int sem_wait ( sem_t* sem )
2792{
2793 int res;
2794 vg_sem_t* vg_sem;
2795 ensure_valgrind("sem_wait");
2796 vg_sem = se_remap(sem);
2797 res = __pthread_mutex_lock(&vg_sem->se_mx);
sewardj2d94c112002-06-03 01:25:54 +00002798 my_assert(res == 0);
sewardj8f253ff2002-05-19 00:13:34 +00002799 while (vg_sem->count == 0) {
2800 res = pthread_cond_wait(&vg_sem->se_cv, &vg_sem->se_mx);
sewardj2d94c112002-06-03 01:25:54 +00002801 my_assert(res == 0);
sewardj8f253ff2002-05-19 00:13:34 +00002802 }
2803 vg_sem->count--;
2804 res = __pthread_mutex_unlock(&vg_sem->se_mx);
sewardj2d94c112002-06-03 01:25:54 +00002805 my_assert(res == 0);
sewardj8f253ff2002-05-19 00:13:34 +00002806 return 0;
2807}
2808
2809int sem_post ( sem_t* sem )
2810{
2811 int res;
2812 vg_sem_t* vg_sem;
2813 ensure_valgrind("sem_post");
2814 vg_sem = se_remap(sem);
2815 res = __pthread_mutex_lock(&vg_sem->se_mx);
sewardj2d94c112002-06-03 01:25:54 +00002816 my_assert(res == 0);
sewardj8f253ff2002-05-19 00:13:34 +00002817 if (vg_sem->count == 0) {
2818 vg_sem->count++;
2819 res = pthread_cond_broadcast(&vg_sem->se_cv);
sewardj2d94c112002-06-03 01:25:54 +00002820 my_assert(res == 0);
sewardj8f253ff2002-05-19 00:13:34 +00002821 } else {
2822 vg_sem->count++;
2823 }
2824 res = __pthread_mutex_unlock(&vg_sem->se_mx);
sewardj2d94c112002-06-03 01:25:54 +00002825 my_assert(res == 0);
sewardj8f253ff2002-05-19 00:13:34 +00002826 return 0;
2827}
2828
2829
2830int sem_trywait ( sem_t* sem )
2831{
2832 int ret, res;
2833 vg_sem_t* vg_sem;
2834 ensure_valgrind("sem_trywait");
2835 vg_sem = se_remap(sem);
2836 res = __pthread_mutex_lock(&vg_sem->se_mx);
sewardj2d94c112002-06-03 01:25:54 +00002837 my_assert(res == 0);
sewardj8f253ff2002-05-19 00:13:34 +00002838 if (vg_sem->count > 0) {
2839 vg_sem->count--;
2840 ret = 0;
2841 } else {
2842 ret = -1;
2843 errno = EAGAIN;
2844 }
2845 res = __pthread_mutex_unlock(&vg_sem->se_mx);
sewardj2d94c112002-06-03 01:25:54 +00002846 my_assert(res == 0);
sewardj8f253ff2002-05-19 00:13:34 +00002847 return ret;
2848}
2849
2850
2851int sem_getvalue(sem_t* sem, int * sval)
2852{
2853 vg_sem_t* vg_sem;
2854 ensure_valgrind("sem_trywait");
2855 vg_sem = se_remap(sem);
2856 *sval = vg_sem->count;
2857 return 0;
2858}
2859
2860
2861int sem_destroy(sem_t * sem)
2862{
2863 kludged("sem_destroy");
2864 /* if someone waiting on this semaphore, errno = EBUSY, return -1 */
2865 return 0;
2866}
2867
sewardj9ad92d92002-10-16 19:45:06 +00002868
2869int sem_timedwait(sem_t* sem, const struct timespec *abstime)
2870{
2871 int res;
2872 vg_sem_t* vg_sem;
2873 ensure_valgrind("sem_timedwait");
2874 vg_sem = se_remap(sem);
2875 res = __pthread_mutex_lock(&vg_sem->se_mx);
2876 my_assert(res == 0);
2877 while ( vg_sem->count == 0 && res != ETIMEDOUT ) {
2878 res = pthread_cond_timedwait(&vg_sem->se_cv, &vg_sem->se_mx, abstime);
2879 }
2880 if ( vg_sem->count > 0 ) {
2881 vg_sem->count--;
2882 res = __pthread_mutex_unlock(&vg_sem->se_mx);
2883 my_assert(res == 0 );
2884 return 0;
2885 } else {
2886 res = __pthread_mutex_unlock(&vg_sem->se_mx);
2887 my_assert(res == 0 );
2888 *(__errno_location()) = ETIMEDOUT;
2889 return -1;
2890 }
2891}
2892
sewardj8f253ff2002-05-19 00:13:34 +00002893
2894/* ---------------------------------------------------------------------
sewardj2d8b3f02002-06-01 14:14:19 +00002895 Reader-writer locks.
sewardja1ac5cb2002-05-27 13:00:05 +00002896 ------------------------------------------------------------------ */
2897
sewardj2d8b3f02002-06-01 14:14:19 +00002898typedef
2899 struct {
2900 int initted; /* != 0 --> in use; sanity check only */
2901 int prefer_w; /* != 0 --> prefer writer */
2902 int nwait_r; /* # of waiting readers */
2903 int nwait_w; /* # of waiting writers */
2904 pthread_cond_t cv_r; /* for signalling readers */
2905 pthread_cond_t cv_w; /* for signalling writers */
2906 pthread_mutex_t mx;
2907 int status;
2908 /* allowed range for status: >= -1. -1 means 1 writer currently
2909 active, >= 0 means N readers currently active. */
2910 }
2911 vg_rwlock_t;
sewardja1ac5cb2002-05-27 13:00:05 +00002912
2913
2914static pthread_mutex_t rw_remap_mx = PTHREAD_MUTEX_INITIALIZER;
2915
2916static int rw_remap_used = 0;
2917static pthread_rwlock_t* rw_remap_orig[VG_N_RWLOCKS];
2918static vg_rwlock_t rw_remap_new[VG_N_RWLOCKS];
2919
sewardj2d8b3f02002-06-01 14:14:19 +00002920
2921static
2922void init_vg_rwlock ( vg_rwlock_t* vg_rwl )
2923{
2924 int res = 0;
2925 vg_rwl->initted = 1;
2926 vg_rwl->prefer_w = 1;
2927 vg_rwl->nwait_r = 0;
2928 vg_rwl->nwait_w = 0;
2929 vg_rwl->status = 0;
2930 res = pthread_mutex_init(&vg_rwl->mx, NULL);
2931 res |= pthread_cond_init(&vg_rwl->cv_r, NULL);
2932 res |= pthread_cond_init(&vg_rwl->cv_w, NULL);
sewardj2d94c112002-06-03 01:25:54 +00002933 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002934}
2935
2936
sewardja1ac5cb2002-05-27 13:00:05 +00002937/* Take the address of a LinuxThreads rwlock_t and return the shadow
2938 address of our version. Further, if the LinuxThreads version
2939 appears to have been statically initialised, do the same to the one
2940 we allocate here. The pthread_rwlock_t.__rw_readers field is set
2941 to zero by PTHREAD_RWLOCK_INITIALIZER, so we take zero as meaning
2942 uninitialised and non-zero meaning initialised.
2943*/
2944static vg_rwlock_t* rw_remap ( pthread_rwlock_t* orig )
2945{
2946 int res, i;
2947 vg_rwlock_t* vg_rwl;
2948 res = __pthread_mutex_lock(&rw_remap_mx);
sewardj2d94c112002-06-03 01:25:54 +00002949 my_assert(res == 0);
sewardja1ac5cb2002-05-27 13:00:05 +00002950
2951 for (i = 0; i < rw_remap_used; i++) {
2952 if (rw_remap_orig[i] == orig)
2953 break;
2954 }
2955 if (i == rw_remap_used) {
2956 if (rw_remap_used == VG_N_RWLOCKS) {
sewardj2d8b3f02002-06-01 14:14:19 +00002957 res = __pthread_mutex_unlock(&rw_remap_mx);
sewardj2d94c112002-06-03 01:25:54 +00002958 my_assert(res == 0);
sewardja1ac5cb2002-05-27 13:00:05 +00002959 barf("VG_N_RWLOCKS is too low. Increase and recompile.");
2960 }
2961 rw_remap_used++;
2962 rw_remap_orig[i] = orig;
sewardj2d8b3f02002-06-01 14:14:19 +00002963 rw_remap_new[i].initted = 0;
sewardja1ac5cb2002-05-27 13:00:05 +00002964 if (0) printf("allocated rwlock %d\n", i);
2965 }
2966 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 vg_rwl = &rw_remap_new[i];
2969
sewardj2d8b3f02002-06-01 14:14:19 +00002970 /* Initialise the shadow, if required. */
sewardja1ac5cb2002-05-27 13:00:05 +00002971 if (orig->__rw_readers == 0) {
sewardja1ac5cb2002-05-27 13:00:05 +00002972 orig->__rw_readers = 1;
sewardj2d8b3f02002-06-01 14:14:19 +00002973 init_vg_rwlock(vg_rwl);
sewardja1ac5cb2002-05-27 13:00:05 +00002974 if (orig->__rw_kind == PTHREAD_RWLOCK_PREFER_READER_NP)
sewardj2d8b3f02002-06-01 14:14:19 +00002975 vg_rwl->prefer_w = 0;
sewardja1ac5cb2002-05-27 13:00:05 +00002976 }
2977
2978 return vg_rwl;
2979}
2980
2981
sewardja1ac5cb2002-05-27 13:00:05 +00002982int pthread_rwlock_init ( pthread_rwlock_t* orig,
2983 const pthread_rwlockattr_t* attr )
2984{
sewardja1ac5cb2002-05-27 13:00:05 +00002985 vg_rwlock_t* rwl;
2986 if (0) printf ("pthread_rwlock_init\n");
2987 /* Force the remapper to initialise the shadow. */
2988 orig->__rw_readers = 0;
2989 /* Install the lock preference; the remapper needs to know it. */
2990 orig->__rw_kind = PTHREAD_RWLOCK_DEFAULT_NP;
2991 if (attr)
2992 orig->__rw_kind = attr->__lockkind;
2993 rwl = rw_remap ( orig );
sewardj2d8b3f02002-06-01 14:14:19 +00002994 return 0;
sewardja1ac5cb2002-05-27 13:00:05 +00002995}
2996
sewardj2d8b3f02002-06-01 14:14:19 +00002997
2998static
2999void pthread_rwlock_rdlock_CANCEL_HDLR ( void* rwl_v )
sewardja1ac5cb2002-05-27 13:00:05 +00003000{
sewardj2d8b3f02002-06-01 14:14:19 +00003001 vg_rwlock_t* rwl = (vg_rwlock_t*)rwl_v;
3002 rwl->nwait_r--;
3003 pthread_mutex_unlock (&rwl->mx);
sewardja1ac5cb2002-05-27 13:00:05 +00003004}
3005
sewardj2d8b3f02002-06-01 14:14:19 +00003006
sewardja1ac5cb2002-05-27 13:00:05 +00003007int pthread_rwlock_rdlock ( pthread_rwlock_t* orig )
3008{
3009 int res;
3010 vg_rwlock_t* rwl;
3011 if (0) printf ("pthread_rwlock_rdlock\n");
3012 rwl = rw_remap ( orig );
sewardj2d8b3f02002-06-01 14:14:19 +00003013 res = __pthread_mutex_lock(&rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00003014 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00003015 if (!rwl->initted) {
3016 res = __pthread_mutex_unlock(&rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00003017 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00003018 return EINVAL;
3019 }
3020 if (rwl->status < 0) {
sewardj2d94c112002-06-03 01:25:54 +00003021 my_assert(rwl->status == -1);
sewardj2d8b3f02002-06-01 14:14:19 +00003022 rwl->nwait_r++;
3023 pthread_cleanup_push( pthread_rwlock_rdlock_CANCEL_HDLR, rwl );
3024 while (1) {
3025 if (rwl->status == 0) break;
3026 res = pthread_cond_wait(&rwl->cv_r, &rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00003027 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00003028 }
3029 pthread_cleanup_pop(0);
3030 rwl->nwait_r--;
3031 }
sewardj2d94c112002-06-03 01:25:54 +00003032 my_assert(rwl->status >= 0);
sewardj2d8b3f02002-06-01 14:14:19 +00003033 rwl->status++;
3034 res = __pthread_mutex_unlock(&rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00003035 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00003036 return 0;
sewardja1ac5cb2002-05-27 13:00:05 +00003037}
3038
sewardj2d8b3f02002-06-01 14:14:19 +00003039
sewardja1ac5cb2002-05-27 13:00:05 +00003040int pthread_rwlock_tryrdlock ( pthread_rwlock_t* orig )
3041{
3042 int res;
3043 vg_rwlock_t* rwl;
3044 if (0) printf ("pthread_rwlock_tryrdlock\n");
3045 rwl = rw_remap ( orig );
sewardj2d8b3f02002-06-01 14:14:19 +00003046 res = __pthread_mutex_lock(&rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00003047 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00003048 if (!rwl->initted) {
3049 res = __pthread_mutex_unlock(&rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00003050 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00003051 return EINVAL;
3052 }
3053 if (rwl->status == -1) {
3054 /* Writer active; we have to give up. */
3055 res = __pthread_mutex_unlock(&rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00003056 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00003057 return EBUSY;
3058 }
3059 /* Success */
sewardj2d94c112002-06-03 01:25:54 +00003060 my_assert(rwl->status >= 0);
sewardj2d8b3f02002-06-01 14:14:19 +00003061 rwl->status++;
3062 res = __pthread_mutex_unlock(&rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00003063 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00003064 return 0;
sewardja1ac5cb2002-05-27 13:00:05 +00003065}
3066
sewardj2d8b3f02002-06-01 14:14:19 +00003067
3068static
3069void pthread_rwlock_wrlock_CANCEL_HDLR ( void* rwl_v )
3070{
3071 vg_rwlock_t* rwl = (vg_rwlock_t*)rwl_v;
3072 rwl->nwait_w--;
3073 pthread_mutex_unlock (&rwl->mx);
3074}
3075
3076
sewardja1ac5cb2002-05-27 13:00:05 +00003077int pthread_rwlock_wrlock ( pthread_rwlock_t* orig )
3078{
3079 int res;
3080 vg_rwlock_t* rwl;
3081 if (0) printf ("pthread_rwlock_wrlock\n");
3082 rwl = rw_remap ( orig );
sewardj2d8b3f02002-06-01 14:14:19 +00003083 res = __pthread_mutex_lock(&rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00003084 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00003085 if (!rwl->initted) {
3086 res = __pthread_mutex_unlock(&rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00003087 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00003088 return EINVAL;
3089 }
3090 if (rwl->status != 0) {
3091 rwl->nwait_w++;
3092 pthread_cleanup_push( pthread_rwlock_wrlock_CANCEL_HDLR, rwl );
3093 while (1) {
3094 if (rwl->status == 0) break;
3095 res = pthread_cond_wait(&rwl->cv_w, &rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00003096 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00003097 }
3098 pthread_cleanup_pop(0);
3099 rwl->nwait_w--;
3100 }
sewardj2d94c112002-06-03 01:25:54 +00003101 my_assert(rwl->status == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00003102 rwl->status = -1;
3103 res = __pthread_mutex_unlock(&rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00003104 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00003105 return 0;
sewardja1ac5cb2002-05-27 13:00:05 +00003106}
3107
sewardj2d8b3f02002-06-01 14:14:19 +00003108
sewardja1ac5cb2002-05-27 13:00:05 +00003109int pthread_rwlock_trywrlock ( pthread_rwlock_t* orig )
3110{
3111 int res;
3112 vg_rwlock_t* rwl;
sewardj2d8b3f02002-06-01 14:14:19 +00003113 if (0) printf ("pthread_wrlock_trywrlock\n");
sewardja1ac5cb2002-05-27 13:00:05 +00003114 rwl = rw_remap ( orig );
sewardj2d8b3f02002-06-01 14:14:19 +00003115 res = __pthread_mutex_lock(&rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00003116 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00003117 if (!rwl->initted) {
3118 res = __pthread_mutex_unlock(&rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00003119 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00003120 return EINVAL;
3121 }
3122 if (rwl->status != 0) {
3123 /* Reader(s) or a writer active; we have to give up. */
3124 res = __pthread_mutex_unlock(&rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00003125 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00003126 return EBUSY;
3127 }
3128 /* Success */
sewardj2d94c112002-06-03 01:25:54 +00003129 my_assert(rwl->status == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00003130 rwl->status = -1;
3131 res = __pthread_mutex_unlock(&rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00003132 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00003133 return 0;
sewardja1ac5cb2002-05-27 13:00:05 +00003134}
3135
sewardj2d8b3f02002-06-01 14:14:19 +00003136
sewardja1ac5cb2002-05-27 13:00:05 +00003137int pthread_rwlock_unlock ( pthread_rwlock_t* orig )
3138{
3139 int res;
3140 vg_rwlock_t* rwl;
3141 if (0) printf ("pthread_rwlock_unlock\n");
3142 rwl = rw_remap ( orig );
sewardj2d8b3f02002-06-01 14:14:19 +00003143 rwl = rw_remap ( orig );
3144 res = __pthread_mutex_lock(&rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00003145 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00003146 if (!rwl->initted) {
3147 res = __pthread_mutex_unlock(&rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00003148 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00003149 return EINVAL;
3150 }
3151 if (rwl->status == 0) {
3152 res = __pthread_mutex_unlock(&rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00003153 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00003154 return EPERM;
3155 }
sewardj2d94c112002-06-03 01:25:54 +00003156 my_assert(rwl->status != 0);
sewardj2d8b3f02002-06-01 14:14:19 +00003157 if (rwl->status == -1) {
3158 rwl->status = 0;
3159 } else {
sewardj2d94c112002-06-03 01:25:54 +00003160 my_assert(rwl->status > 0);
sewardj2d8b3f02002-06-01 14:14:19 +00003161 rwl->status--;
3162 }
3163
sewardj2d94c112002-06-03 01:25:54 +00003164 my_assert(rwl->status >= 0);
sewardj2d8b3f02002-06-01 14:14:19 +00003165
3166 if (rwl->prefer_w) {
3167
3168 /* Favour waiting writers, if any. */
3169 if (rwl->nwait_w > 0) {
3170 /* Writer(s) are waiting. */
3171 if (rwl->status == 0) {
3172 /* We can let a writer in. */
3173 res = pthread_cond_signal(&rwl->cv_w);
sewardj2d94c112002-06-03 01:25:54 +00003174 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00003175 } else {
3176 /* There are still readers active. Do nothing; eventually
3177 they will disappear, at which point a writer will be
3178 admitted. */
3179 }
3180 }
3181 else
3182 /* No waiting writers. */
3183 if (rwl->nwait_r > 0) {
3184 /* Let in a waiting reader. */
3185 res = pthread_cond_signal(&rwl->cv_r);
sewardj2d94c112002-06-03 01:25:54 +00003186 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00003187 }
3188
3189 } else {
3190
3191 /* Favour waiting readers, if any. */
3192 if (rwl->nwait_r > 0) {
3193 /* Reader(s) are waiting; let one in. */
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 else
3198 /* No waiting readers. */
3199 if (rwl->nwait_w > 0 && rwl->status == 0) {
3200 /* We have waiting writers and no active readers; let a
3201 writer in. */
3202 res = pthread_cond_signal(&rwl->cv_w);
sewardj2d94c112002-06-03 01:25:54 +00003203 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00003204 }
3205 }
3206
3207 res = __pthread_mutex_unlock(&rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00003208 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00003209 return 0;
3210}
3211
3212
3213int pthread_rwlock_destroy ( pthread_rwlock_t *orig )
3214{
3215 int res;
3216 vg_rwlock_t* rwl;
3217 if (0) printf ("pthread_rwlock_destroy\n");
3218 rwl = rw_remap ( orig );
3219 res = __pthread_mutex_lock(&rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00003220 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00003221 if (!rwl->initted) {
3222 res = __pthread_mutex_unlock(&rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00003223 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00003224 return EINVAL;
3225 }
3226 if (rwl->status != 0 || rwl->nwait_r > 0 || rwl->nwait_w > 0) {
3227 res = __pthread_mutex_unlock(&rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00003228 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00003229 return EBUSY;
3230 }
3231 rwl->initted = 0;
3232 res = __pthread_mutex_unlock(&rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00003233 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00003234 return 0;
sewardja1ac5cb2002-05-27 13:00:05 +00003235}
3236
3237
sewardj47e4e312002-06-18 09:24:34 +00003238/* Copied directly from LinuxThreads. */
3239int
3240pthread_rwlockattr_init (pthread_rwlockattr_t *attr)
3241{
3242 attr->__lockkind = 0;
3243 attr->__pshared = PTHREAD_PROCESS_PRIVATE;
3244
3245 return 0;
3246}
3247
sewardjfe18eb82002-07-13 12:58:44 +00003248/* Copied directly from LinuxThreads. */
3249int
3250pthread_rwlockattr_setpshared (pthread_rwlockattr_t *attr, int pshared)
3251{
3252 if (pshared != PTHREAD_PROCESS_PRIVATE && pshared != PTHREAD_PROCESS_SHARED)
3253 return EINVAL;
3254
3255 /* For now it is not possible to shared a conditional variable. */
3256 if (pshared != PTHREAD_PROCESS_PRIVATE)
3257 return ENOSYS;
3258
3259 attr->__pshared = pshared;
3260
3261 return 0;
3262}
3263
sewardj47e4e312002-06-18 09:24:34 +00003264
sewardja1ac5cb2002-05-27 13:00:05 +00003265/* ---------------------------------------------------------------------
sewardjd5bef572002-10-23 21:49:33 +00003266 Make SYSV IPC not block everything
3267 ------------------------------------------------------------------ */
3268
3269#include <sys/ipc.h>
3270#include <sys/msg.h>
3271#include <asm/ipc.h> /* for ipc_kludge */
3272
3273static inline int sys_ipc(unsigned call, int first, int second, int third, void *ptr)
3274{
3275 return my_do_syscall5(__NR_ipc, call, first, second, third, (int)ptr);
3276}
3277
3278/* Turn a blocking msgsnd() into a polling non-blocking one, so that
3279 other threads make progress */
sewardjf220ccc2002-10-23 21:53:49 +00003280int VGL_(msgsnd)(int msgid, const void *msgp, size_t msgsz, int msgflg)
sewardjd5bef572002-10-23 21:49:33 +00003281{
3282 struct vki_timespec nanosleep_interval;
3283 int err;
3284
3285 ensure_valgrind("msgsnd");
3286
3287 nanosleep_interval.tv_sec = 0;
3288 nanosleep_interval.tv_nsec = 13 * 1000 * 1000; /* 13 milliseconds */
3289
3290 if (msgflg & IPC_NOWAIT) {
3291 /* If we aren't blocking anyway, just do it */
3292 err = sys_ipc(11, msgid, msgsz, msgflg, (void *)msgp);
3293 } else {
3294 /* Otherwise poll on the queue to let other things run */
3295 for(;;) {
3296 err = sys_ipc(11, msgid, msgsz, msgflg | IPC_NOWAIT, (void *)msgp);
3297
3298 if (err != -EAGAIN)
3299 break;
3300
3301 (void)my_do_syscall2(__NR_nanosleep,
3302 (int)(&nanosleep_interval), (int)NULL);
3303 }
3304 }
3305
3306 if (is_kerror(err)) {
3307 *(__errno_location()) = -err;
3308 return -1;
3309 }
3310 return 0;
3311}
3312
3313/* Turn a blocking msgrcv() into a polling non-blocking one, so that
3314 other threads make progress */
sewardjf220ccc2002-10-23 21:53:49 +00003315int VGL_(msgrcv)( int msqid, void *msgp, size_t msgsz, long msgtyp, int msgflg )
sewardjd5bef572002-10-23 21:49:33 +00003316{
3317 struct vki_timespec nanosleep_interval;
3318 int err;
3319 struct ipc_kludge tmp;
3320
3321 ensure_valgrind("msgrcv");
3322
3323 nanosleep_interval.tv_sec = 0;
3324 nanosleep_interval.tv_nsec = 13 * 1000 * 1000; /* 13 milliseconds */
3325
3326 tmp.msgp = msgp;
3327 tmp.msgtyp = msgtyp;
3328
3329 if (msgflg & IPC_NOWAIT) {
3330 /* If we aren't blocking anyway, just do it */
3331 err = sys_ipc(12, msqid, msgsz, msgflg, &tmp );
3332 } else {
3333 /* Otherwise poll on the queue to let other things run */
3334 for(;;) {
3335 err = sys_ipc(12, msqid, msgsz, msgflg | IPC_NOWAIT, &tmp );
3336
3337 if (err != -ENOMSG)
3338 break;
3339
3340 (void)my_do_syscall2(__NR_nanosleep,
3341 (int)(&nanosleep_interval), (int)NULL);
3342 }
3343 }
3344
3345 if (is_kerror(err)) {
3346 *(__errno_location()) = -err;
3347 return -1;
3348 }
3349
3350 return 0;
3351}
3352
3353
3354
3355/* ---------------------------------------------------------------------
sewardj3b13f0e2002-04-25 20:17:29 +00003356 B'stard.
3357 ------------------------------------------------------------------ */
3358
3359# define strong_alias(name, aliasname) \
3360 extern __typeof (name) aliasname __attribute__ ((alias (#name)));
3361
sewardj5905fae2002-04-26 13:25:00 +00003362# define weak_alias(name, aliasname) \
3363 extern __typeof (name) aliasname __attribute__ ((weak, alias (#name)));
sewardj3b13f0e2002-04-25 20:17:29 +00003364
sewardj5905fae2002-04-26 13:25:00 +00003365strong_alias(__pthread_mutex_lock, pthread_mutex_lock)
3366strong_alias(__pthread_mutex_trylock, pthread_mutex_trylock)
3367strong_alias(__pthread_mutex_unlock, pthread_mutex_unlock)
3368strong_alias(__pthread_mutexattr_init, pthread_mutexattr_init)
3369 weak_alias(__pthread_mutexattr_settype, pthread_mutexattr_settype)
3370strong_alias(__pthread_mutex_init, pthread_mutex_init)
3371strong_alias(__pthread_mutexattr_destroy, pthread_mutexattr_destroy)
3372strong_alias(__pthread_mutex_destroy, pthread_mutex_destroy)
3373strong_alias(__pthread_once, pthread_once)
3374strong_alias(__pthread_atfork, pthread_atfork)
3375strong_alias(__pthread_key_create, pthread_key_create)
3376strong_alias(__pthread_getspecific, pthread_getspecific)
3377strong_alias(__pthread_setspecific, pthread_setspecific)
3378
sewardjd529a442002-05-04 19:49:21 +00003379#ifndef GLIBC_2_1
sewardj3b13f0e2002-04-25 20:17:29 +00003380strong_alias(sigaction, __sigaction)
sewardjd529a442002-05-04 19:49:21 +00003381#endif
3382
sewardj5905fae2002-04-26 13:25:00 +00003383strong_alias(close, __close)
sewardj3b13f0e2002-04-25 20:17:29 +00003384strong_alias(fcntl, __fcntl)
sewardj5905fae2002-04-26 13:25:00 +00003385strong_alias(lseek, __lseek)
3386strong_alias(open, __open)
3387strong_alias(open64, __open64)
sewardj5905fae2002-04-26 13:25:00 +00003388strong_alias(read, __read)
3389strong_alias(wait, __wait)
3390strong_alias(write, __write)
sewardj3b13f0e2002-04-25 20:17:29 +00003391strong_alias(connect, __connect)
sewardj5905fae2002-04-26 13:25:00 +00003392strong_alias(send, __send)
3393
sewardj726c4122002-05-16 23:39:10 +00003394weak_alias (__pread64, pread64)
sewardja18e2102002-05-18 10:43:22 +00003395weak_alias (__pwrite64, pwrite64)
sewardj5905fae2002-04-26 13:25:00 +00003396weak_alias(__fork, fork)
njn25e49d8e72002-09-23 09:36:25 +00003397weak_alias(__vfork, vfork)
sewardj7f6456d2002-05-21 00:51:21 +00003398
sewardjf0b06452002-06-04 08:38:04 +00003399weak_alias (__pthread_kill_other_threads_np, pthread_kill_other_threads_np)
sewardj3b13f0e2002-04-25 20:17:29 +00003400
3401/*--------------------------------------------------*/
3402
sewardj5905fae2002-04-26 13:25:00 +00003403weak_alias(pthread_rwlock_rdlock, __pthread_rwlock_rdlock)
sewardj5905fae2002-04-26 13:25:00 +00003404weak_alias(pthread_rwlock_unlock, __pthread_rwlock_unlock)
sewardj262b0292002-05-01 00:03:16 +00003405weak_alias(pthread_rwlock_wrlock, __pthread_rwlock_wrlock)
sewardj060b04f2002-04-26 21:01:13 +00003406
sewardja1ac5cb2002-05-27 13:00:05 +00003407weak_alias(pthread_rwlock_destroy, __pthread_rwlock_destroy)
3408weak_alias(pthread_rwlock_init, __pthread_rwlock_init)
3409weak_alias(pthread_rwlock_tryrdlock, __pthread_rwlock_tryrdlock)
3410weak_alias(pthread_rwlock_trywrlock, __pthread_rwlock_trywrlock)
3411
sewardj060b04f2002-04-26 21:01:13 +00003412
sewardj3b13f0e2002-04-25 20:17:29 +00003413/* I've no idea what these are, but they get called quite a lot.
3414 Anybody know? */
3415
3416#undef _IO_flockfile
3417void _IO_flockfile ( _IO_FILE * file )
3418{
sewardj853f55d2002-04-26 00:27:53 +00003419 pthread_mutex_lock(file->_lock);
sewardj3b13f0e2002-04-25 20:17:29 +00003420}
sewardj5905fae2002-04-26 13:25:00 +00003421weak_alias(_IO_flockfile, flockfile);
3422
sewardj3b13f0e2002-04-25 20:17:29 +00003423
3424#undef _IO_funlockfile
3425void _IO_funlockfile ( _IO_FILE * file )
3426{
sewardj853f55d2002-04-26 00:27:53 +00003427 pthread_mutex_unlock(file->_lock);
sewardj3b13f0e2002-04-25 20:17:29 +00003428}
sewardj5905fae2002-04-26 13:25:00 +00003429weak_alias(_IO_funlockfile, funlockfile);
3430
sewardj3b13f0e2002-04-25 20:17:29 +00003431
sewardjd4f2c712002-04-30 10:20:10 +00003432/* This doesn't seem to be needed to simulate libpthread.so's external
3433 interface, but many people complain about its absence. */
3434
3435strong_alias(__pthread_mutexattr_settype, __pthread_mutexattr_setkind_np)
3436weak_alias(__pthread_mutexattr_setkind_np, pthread_mutexattr_setkind_np)
sewardj439d45e2002-05-03 20:43:10 +00003437
3438
3439/*--------------------------------------------------------------------*/
3440/*--- end vg_libpthread.c ---*/
3441/*--------------------------------------------------------------------*/