blob: cbc8fadb2246ba87f02060c8ac8e1ad0ada32e88 [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 );
78
sewardj9a2224b2002-06-19 10:17:40 +000079static
sewardj08c7f012002-10-07 23:56:55 +000080int my_do_syscall1 ( int syscallno, int arg1 );
81
82static
sewardj9a2224b2002-06-19 10:17:40 +000083int my_do_syscall2 ( int syscallno,
84 int arg1, int arg2 );
85
sewardj08c7f012002-10-07 23:56:55 +000086static
87int my_do_syscall3 ( int syscallno,
88 int arg1, int arg2, int arg3 );
89
90
91#ifdef GLIBC_2_3
92 /* kludge by JRS (not from glibc) ... */
93 typedef void* __locale_t;
94
95 /* Copied from locale/locale.h in glibc-2.2.93 sources */
96 /* This value can be passed to `uselocale' and may be returned by
97 it. Passing this value to any other function has undefined
98 behavior. */
99# define LC_GLOBAL_LOCALE ((__locale_t) -1L)
100 extern __locale_t __uselocale ( __locale_t );
101#endif
102
sewardj00a66b12002-10-12 16:42:35 +0000103static
104void init_libc_tsd_keys ( void );
105
sewardj705d3cb2002-05-23 13:13:12 +0000106
sewardje663cb92002-04-12 10:26:32 +0000107/* ---------------------------------------------------------------------
108 Helpers. We have to be pretty self-sufficient.
109 ------------------------------------------------------------------ */
110
sewardj436e0582002-04-26 14:31:40 +0000111/* Number of times any given error message is printed. */
112#define N_MOANS 3
113
sewardj45b4b372002-04-16 22:50:32 +0000114/* Extract from Valgrind the value of VG_(clo_trace_pthread_level).
115 Returns 0 (none) if not running on Valgrind. */
116static
117int get_pt_trace_level ( void )
118{
119 int res;
120 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
121 VG_USERREQ__GET_PTHREAD_TRACE_LEVEL,
122 0, 0, 0, 0);
123 return res;
124}
125
sewardje663cb92002-04-12 10:26:32 +0000126static
sewardj2d94c112002-06-03 01:25:54 +0000127void my_exit ( int arg )
sewardje663cb92002-04-12 10:26:32 +0000128{
sewardj08c7f012002-10-07 23:56:55 +0000129 my_do_syscall1(__NR_exit, arg);
130 /*NOTREACHED*/
sewardje663cb92002-04-12 10:26:32 +0000131}
132
sewardj08c7f012002-10-07 23:56:55 +0000133static
134void my_write ( int fd, const void *buf, int count )
135{
136 my_do_syscall3(__NR_write, fd, (int)buf, count );
137}
sewardje663cb92002-04-12 10:26:32 +0000138
sewardj68b2dd92002-05-10 21:03:56 +0000139/* We need this guy -- it's in valgrind.so. */
140extern void VG_(startup) ( void );
141
142
143/* Just start up Valgrind if it's not already going. VG_(startup)()
144 detects and ignores second and subsequent calls. */
sewardj604ec3c2002-04-18 22:38:41 +0000145static __inline__
sewardje663cb92002-04-12 10:26:32 +0000146void ensure_valgrind ( char* caller )
147{
sewardj68b2dd92002-05-10 21:03:56 +0000148 VG_(startup)();
sewardje663cb92002-04-12 10:26:32 +0000149}
150
sewardjbea1caa2002-05-10 23:20:58 +0000151/* While we're at it ... hook our own startup function into this
152 game. */
153__asm__ (
154 ".section .init\n"
155 "\tcall vgPlain_startup"
156);
157
sewardje663cb92002-04-12 10:26:32 +0000158
159static
sewardj3b5d8862002-04-20 13:53:23 +0000160__attribute__((noreturn))
sewardje663cb92002-04-12 10:26:32 +0000161void barf ( char* str )
162{
sewardj69a72a52002-11-03 13:41:41 +0000163 int res;
164 char buf[1000];
sewardje663cb92002-04-12 10:26:32 +0000165 buf[0] = 0;
sewardj439d45e2002-05-03 20:43:10 +0000166 strcat(buf, "\nvalgrind's libpthread.so: ");
sewardje663cb92002-04-12 10:26:32 +0000167 strcat(buf, str);
168 strcat(buf, "\n\n");
sewardj69a72a52002-11-03 13:41:41 +0000169 VALGRIND_MAGIC_SEQUENCE(res, 0, /* irrelevant default */
170 VG_USERREQ__LOGMESSAGE, buf, 0, 0, 0);
sewardj2d94c112002-06-03 01:25:54 +0000171 my_exit(1);
sewardj3b5d8862002-04-20 13:53:23 +0000172 /* We have to persuade gcc into believing this doesn't return. */
173 while (1) { };
sewardje663cb92002-04-12 10:26:32 +0000174}
175
176
sewardj69a72a52002-11-03 13:41:41 +0000177static void cat_n_send ( char* pre, char* msg )
sewardj2a3d28c2002-04-14 13:27:00 +0000178{
sewardj69a72a52002-11-03 13:41:41 +0000179 char buf[1000];
180 int res;
sewardj436e0582002-04-26 14:31:40 +0000181 if (get_pt_trace_level() >= 0) {
sewardj69a72a52002-11-03 13:41:41 +0000182 snprintf(buf, sizeof(buf), "%s%s", pre, msg );
183 buf[sizeof(buf)-1] = '\0';
184 VALGRIND_MAGIC_SEQUENCE(res, 0, /* irrelevant default */
185 VG_USERREQ__LOGMESSAGE, buf, 0, 0, 0);
sewardj45b4b372002-04-16 22:50:32 +0000186 }
sewardj2a3d28c2002-04-14 13:27:00 +0000187}
188
sewardj69a72a52002-11-03 13:41:41 +0000189static void ignored ( char* msg )
190{
191 cat_n_send ( "valgrind's libpthread.so: IGNORED call to: ", msg );
192}
193
194
sewardj30671ff2002-04-21 00:13:57 +0000195static void kludged ( char* msg )
196{
sewardj69a72a52002-11-03 13:41:41 +0000197 cat_n_send ( "valgrind's libpthread.so: KLUDGED call to: ", msg );
sewardj439d45e2002-05-03 20:43:10 +0000198}
199
sewardj69a72a52002-11-03 13:41:41 +0000200
sewardjccef2e62002-05-29 19:26:32 +0000201__attribute__((noreturn))
sewardj3b13f0e2002-04-25 20:17:29 +0000202void vgPlain_unimp ( char* what )
203{
sewardj69a72a52002-11-03 13:41:41 +0000204 cat_n_send (
205 "valgrind's libpthread.so: UNIMPLEMENTED FUNCTION: ", what );
sewardj3b13f0e2002-04-25 20:17:29 +0000206 barf("Please report this bug to me at: jseward@acm.org");
207}
208
sewardje663cb92002-04-12 10:26:32 +0000209
sewardj457cc472002-06-03 23:13:47 +0000210static
sewardj2d94c112002-06-03 01:25:54 +0000211void my_assert_fail ( Char* expr, Char* file, Int line, Char* fn )
212{
sewardj69a72a52002-11-03 13:41:41 +0000213 char buf[1000];
sewardj2d94c112002-06-03 01:25:54 +0000214 static Bool entered = False;
215 if (entered)
216 my_exit(2);
217 entered = True;
sewardj69a72a52002-11-03 13:41:41 +0000218 sprintf(buf, "\n%s: %s:%d (%s): Assertion `%s' failed.\n",
219 "valgrind", file, line, fn, expr );
220 cat_n_send ( "", buf );
221 sprintf(buf, "Please report this bug to me at: %s\n\n",
222 VG_EMAIL_ADDR);
223 cat_n_send ( "", buf );
sewardj2d94c112002-06-03 01:25:54 +0000224 my_exit(1);
225}
226
227#define MY__STRING(__str) #__str
228
229#define my_assert(expr) \
230 ((void) ((expr) ? 0 : \
231 (my_assert_fail (MY__STRING(expr), \
232 __FILE__, __LINE__, \
233 __PRETTY_FUNCTION__), 0)))
234
sewardj00a66b12002-10-12 16:42:35 +0000235static
236void my_free ( void* ptr )
237{
238 int res;
239 VALGRIND_MAGIC_SEQUENCE(res, (-1) /* default */,
240 VG_USERREQ__FREE, ptr, 0, 0, 0);
241 my_assert(res == 0);
242}
243
244
245static
246void* my_malloc ( int nbytes )
247{
248 void* res;
249 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
250 VG_USERREQ__MALLOC, nbytes, 0, 0, 0);
251 my_assert(res != (void*)0);
252 return res;
253}
254
255
sewardj2d94c112002-06-03 01:25:54 +0000256
sewardje663cb92002-04-12 10:26:32 +0000257/* ---------------------------------------------------------------------
258 Pass pthread_ calls to Valgrind's request mechanism.
259 ------------------------------------------------------------------ */
260
sewardjf8f819e2002-04-17 23:21:37 +0000261#include <errno.h>
sewardj5f07b662002-04-23 16:52:51 +0000262#include <sys/time.h> /* gettimeofday */
sewardjf8f819e2002-04-17 23:21:37 +0000263
sewardja1ac5cb2002-05-27 13:00:05 +0000264
sewardjf8f819e2002-04-17 23:21:37 +0000265/* ---------------------------------------------------
sewardj4dced352002-06-04 22:54:20 +0000266 Ummm ..
267 ------------------------------------------------ */
268
269static
270void pthread_error ( const char* msg )
271{
272 int res;
273 VALGRIND_MAGIC_SEQUENCE(res, 0,
274 VG_USERREQ__PTHREAD_ERROR,
275 msg, 0, 0, 0);
276}
277
278
279/* ---------------------------------------------------
sewardj00a66b12002-10-12 16:42:35 +0000280 Here so it can be inlined without complaint.
281 ------------------------------------------------ */
282
283__inline__
284pthread_t pthread_self(void)
285{
286 int tid;
287 ensure_valgrind("pthread_self");
288 VALGRIND_MAGIC_SEQUENCE(tid, 0 /* default */,
289 VG_USERREQ__PTHREAD_GET_THREADID,
290 0, 0, 0, 0);
291 if (tid < 1 || tid >= VG_N_THREADS)
292 barf("pthread_self: invalid ThreadId");
293 return tid;
294}
295
296
297/* ---------------------------------------------------
sewardjf8f819e2002-04-17 23:21:37 +0000298 THREAD ATTRIBUTES
299 ------------------------------------------------ */
300
sewardj6af4b5d2002-04-16 04:40:49 +0000301int pthread_attr_init(pthread_attr_t *attr)
302{
sewardj7989d0c2002-05-28 11:00:01 +0000303 /* Just initialise the fields which we might look at. */
304 attr->__detachstate = PTHREAD_CREATE_JOINABLE;
sewardj111b14c2002-10-20 16:22:57 +0000305 /* Linuxthreads sets this field to the value __getpagesize(), so I
306 guess the following is OK. */
307 attr->__guardsize = VKI_BYTES_PER_PAGE; return 0;
sewardj6af4b5d2002-04-16 04:40:49 +0000308}
309
310int pthread_attr_setdetachstate(pthread_attr_t *attr, int detachstate)
311{
sewardj7989d0c2002-05-28 11:00:01 +0000312 if (detachstate != PTHREAD_CREATE_JOINABLE
sewardj4dced352002-06-04 22:54:20 +0000313 && detachstate != PTHREAD_CREATE_DETACHED) {
314 pthread_error("pthread_attr_setdetachstate: "
315 "detachstate is invalid");
sewardj7989d0c2002-05-28 11:00:01 +0000316 return EINVAL;
sewardj4dced352002-06-04 22:54:20 +0000317 }
sewardj7989d0c2002-05-28 11:00:01 +0000318 attr->__detachstate = detachstate;
sewardj6af4b5d2002-04-16 04:40:49 +0000319 return 0;
320}
321
njn25e49d8e72002-09-23 09:36:25 +0000322int pthread_attr_getdetachstate(const pthread_attr_t *attr, int *detachstate)
323{
324 *detachstate = attr->__detachstate;
325 return 0;
326}
327
sewardj30671ff2002-04-21 00:13:57 +0000328int pthread_attr_setinheritsched(pthread_attr_t *attr, int inherit)
329{
sewardj436e0582002-04-26 14:31:40 +0000330 static int moans = N_MOANS;
331 if (moans-- > 0)
332 ignored("pthread_attr_setinheritsched");
sewardj30671ff2002-04-21 00:13:57 +0000333 return 0;
334}
sewardj6af4b5d2002-04-16 04:40:49 +0000335
sewardj0286dd52002-05-16 20:51:15 +0000336__attribute__((weak))
337int pthread_attr_setstacksize (pthread_attr_t *__attr,
338 size_t __stacksize)
339{
sewardja18e2102002-05-18 10:43:22 +0000340 size_t limit;
sewardj3d7c8d62002-06-04 20:59:16 +0000341 char buf[1024];
sewardj0286dd52002-05-16 20:51:15 +0000342 ensure_valgrind("pthread_attr_setstacksize");
sewardja18e2102002-05-18 10:43:22 +0000343 limit = VG_PTHREAD_STACK_SIZE - VG_AR_CLIENT_STACKBASE_REDZONE_SZB
344 - 1000; /* paranoia */
345 if (__stacksize < limit)
sewardj0286dd52002-05-16 20:51:15 +0000346 return 0;
sewardj3d7c8d62002-06-04 20:59:16 +0000347 snprintf(buf, sizeof(buf), "pthread_attr_setstacksize: "
348 "requested size %d >= VG_PTHREAD_STACK_SIZE\n "
349 "edit vg_include.h and rebuild.", __stacksize);
350 buf[sizeof(buf)-1] = '\0'; /* Make sure it is zero terminated */
351 barf(buf);
sewardj0286dd52002-05-16 20:51:15 +0000352}
353
354
sewardj30671ff2002-04-21 00:13:57 +0000355/* This is completely bogus. */
356int pthread_attr_getschedparam(const pthread_attr_t *attr,
357 struct sched_param *param)
358{
sewardj436e0582002-04-26 14:31:40 +0000359 static int moans = N_MOANS;
360 if (moans-- > 0)
361 kludged("pthread_attr_getschedparam");
sewardj3e909ce2002-06-03 13:27:15 +0000362# ifdef HAVE_SCHED_PRIORITY
sewardj72d58482002-04-24 02:20:20 +0000363 if (param) param->sched_priority = 0; /* who knows */
364# else
sewardj30671ff2002-04-21 00:13:57 +0000365 if (param) param->__sched_priority = 0; /* who knows */
sewardj72d58482002-04-24 02:20:20 +0000366# endif
sewardj30671ff2002-04-21 00:13:57 +0000367 return 0;
368}
369
370int pthread_attr_setschedparam(pthread_attr_t *attr,
371 const struct sched_param *param)
372{
sewardj436e0582002-04-26 14:31:40 +0000373 static int moans = N_MOANS;
374 if (moans-- > 0)
375 ignored("pthread_attr_setschedparam");
sewardj30671ff2002-04-21 00:13:57 +0000376 return 0;
377}
378
379int pthread_attr_destroy(pthread_attr_t *attr)
380{
sewardj436e0582002-04-26 14:31:40 +0000381 static int moans = N_MOANS;
382 if (moans-- > 0)
383 ignored("pthread_attr_destroy");
sewardj30671ff2002-04-21 00:13:57 +0000384 return 0;
385}
sewardjf8f819e2002-04-17 23:21:37 +0000386
sewardj0d844232002-06-02 09:29:31 +0000387/* These are no-ops, as with LinuxThreads. */
388int pthread_attr_setscope ( pthread_attr_t *attr, int scope )
389{
390 ensure_valgrind("pthread_attr_setscope");
391 if (scope == PTHREAD_SCOPE_SYSTEM)
392 return 0;
sewardj4dced352002-06-04 22:54:20 +0000393 pthread_error("pthread_attr_setscope: "
394 "invalid or unsupported scope");
sewardj0d844232002-06-02 09:29:31 +0000395 if (scope == PTHREAD_SCOPE_PROCESS)
396 return ENOTSUP;
397 return EINVAL;
398}
399
400int pthread_attr_getscope ( const pthread_attr_t *attr, int *scope )
401{
402 ensure_valgrind("pthread_attr_setscope");
403 if (scope)
404 *scope = PTHREAD_SCOPE_SYSTEM;
405 return 0;
406}
407
sewardj64039bb2002-06-03 00:58:18 +0000408
409/* Pretty bogus. Avoid if possible. */
410int pthread_getattr_np (pthread_t thread, pthread_attr_t *attr)
411{
412 int detached;
413 size_t limit;
414 ensure_valgrind("pthread_getattr_np");
415 kludged("pthread_getattr_np");
416 limit = VG_PTHREAD_STACK_SIZE - VG_AR_CLIENT_STACKBASE_REDZONE_SZB
417 - 1000; /* paranoia */
418 attr->__detachstate = PTHREAD_CREATE_JOINABLE;
419 attr->__schedpolicy = SCHED_OTHER;
420 attr->__schedparam.sched_priority = 0;
421 attr->__inheritsched = PTHREAD_EXPLICIT_SCHED;
422 attr->__scope = PTHREAD_SCOPE_SYSTEM;
423 attr->__guardsize = VKI_BYTES_PER_PAGE;
424 attr->__stackaddr = NULL;
425 attr->__stackaddr_set = 0;
426 attr->__stacksize = limit;
427 VALGRIND_MAGIC_SEQUENCE(detached, (-1) /* default */,
428 VG_USERREQ__SET_OR_GET_DETACH,
429 2 /* get */, thread, 0, 0);
sewardj2d94c112002-06-03 01:25:54 +0000430 my_assert(detached == 0 || detached == 1);
sewardj64039bb2002-06-03 00:58:18 +0000431 if (detached)
432 attr->__detachstate = PTHREAD_CREATE_DETACHED;
433 return 0;
434}
435
436
437/* Bogus ... */
sewardj111b14c2002-10-20 16:22:57 +0000438__attribute__((weak))
sewardj64039bb2002-06-03 00:58:18 +0000439int pthread_attr_getstackaddr ( const pthread_attr_t * attr,
440 void ** stackaddr )
441{
442 ensure_valgrind("pthread_attr_getstackaddr");
443 kludged("pthread_attr_getstackaddr");
444 if (stackaddr)
445 *stackaddr = NULL;
446 return 0;
447}
448
449/* Not bogus (!) */
sewardj111b14c2002-10-20 16:22:57 +0000450__attribute__((weak))
sewardj64039bb2002-06-03 00:58:18 +0000451int pthread_attr_getstacksize ( const pthread_attr_t * _attr,
452 size_t * __stacksize )
453{
454 size_t limit;
455 ensure_valgrind("pthread_attr_getstacksize");
456 limit = VG_PTHREAD_STACK_SIZE - VG_AR_CLIENT_STACKBASE_REDZONE_SZB
457 - 1000; /* paranoia */
458 if (__stacksize)
459 *__stacksize = limit;
460 return 0;
461}
462
sewardja3be12f2002-06-17 12:19:44 +0000463int pthread_attr_setschedpolicy(pthread_attr_t *attr, int policy)
464{
465 if (policy != SCHED_OTHER && policy != SCHED_FIFO && policy != SCHED_RR)
466 return EINVAL;
467 attr->__schedpolicy = policy;
468 return 0;
469}
470
471int pthread_attr_getschedpolicy(const pthread_attr_t *attr, int *policy)
472{
473 *policy = attr->__schedpolicy;
474 return 0;
475}
476
477
sewardj111b14c2002-10-20 16:22:57 +0000478/* This is completely bogus. We reject all attempts to change it from
479 VKI_BYTES_PER_PAGE. I don't have a clue what it's for so it seems
480 safest to be paranoid. */
481__attribute__((weak))
482int pthread_attr_setguardsize(pthread_attr_t *attr, size_t guardsize)
483{
484 static int moans = N_MOANS;
485
486 if (guardsize == VKI_BYTES_PER_PAGE)
487 return 0;
488
489 if (moans-- > 0)
490 ignored("pthread_attr_setguardsize: ignoring guardsize != 4096");
491
492 return 0;
493}
494
495/* A straight copy of the LinuxThreads code. */
496__attribute__((weak))
497int pthread_attr_getguardsize(const pthread_attr_t *attr, size_t *guardsize)
498{
499 *guardsize = attr->__guardsize;
500 return 0;
501}
502
503
sewardj20917d82002-05-28 01:36:45 +0000504/* ---------------------------------------------------
505 Helper functions for running a thread
506 and for clearing up afterwards.
507 ------------------------------------------------ */
508
509/* All exiting threads eventually pass through here, bearing the
510 return value, or PTHREAD_CANCELED, in ret_val. */
511static
512__attribute__((noreturn))
513void thread_exit_wrapper ( void* ret_val )
514{
sewardj870497a2002-05-29 01:06:47 +0000515 int detached, res;
516 CleanupEntry cu;
517 pthread_key_t key;
sewardj00a66b12002-10-12 16:42:35 +0000518 void** specifics_ptr;
sewardj870497a2002-05-29 01:06:47 +0000519
sewardj20917d82002-05-28 01:36:45 +0000520 /* Run this thread's cleanup handlers. */
sewardj8ad94e12002-05-29 00:10:20 +0000521 while (1) {
522 VALGRIND_MAGIC_SEQUENCE(res, (-1) /* default */,
523 VG_USERREQ__CLEANUP_POP,
524 &cu, 0, 0, 0);
525 if (res == -1) break; /* stack empty */
sewardj2d94c112002-06-03 01:25:54 +0000526 my_assert(res == 0);
sewardj8ad94e12002-05-29 00:10:20 +0000527 if (0) printf("running exit cleanup handler");
528 cu.fn ( cu.arg );
529 }
530
sewardj870497a2002-05-29 01:06:47 +0000531 /* Run this thread's key finalizers. Really this should be run
532 PTHREAD_DESTRUCTOR_ITERATIONS times. */
533 for (key = 0; key < VG_N_THREAD_KEYS; key++) {
534 VALGRIND_MAGIC_SEQUENCE(res, (-2) /* default */,
535 VG_USERREQ__GET_KEY_D_AND_S,
536 key, &cu, 0, 0 );
537 if (res == 0) {
538 /* valid key */
539 if (cu.fn && cu.arg)
540 cu.fn /* destructor for key */
541 ( cu.arg /* specific for key for this thread */ );
542 continue;
543 }
sewardj2d94c112002-06-03 01:25:54 +0000544 my_assert(res == -1);
sewardj870497a2002-05-29 01:06:47 +0000545 }
sewardj20917d82002-05-28 01:36:45 +0000546
sewardj00a66b12002-10-12 16:42:35 +0000547 /* Free up my specifics space, if any. */
548 VALGRIND_MAGIC_SEQUENCE(specifics_ptr, 3 /* default */,
549 VG_USERREQ__PTHREAD_GETSPECIFIC_PTR,
550 pthread_self(), 0, 0, 0);
551 my_assert(specifics_ptr != (void**)3);
552 my_assert(specifics_ptr != (void**)1); /* 1 means invalid thread */
553 if (specifics_ptr != NULL)
554 my_free(specifics_ptr);
555
sewardj20917d82002-05-28 01:36:45 +0000556 /* Decide on my final disposition. */
557 VALGRIND_MAGIC_SEQUENCE(detached, (-1) /* default */,
558 VG_USERREQ__SET_OR_GET_DETACH,
sewardj7989d0c2002-05-28 11:00:01 +0000559 2 /* get */, pthread_self(), 0, 0);
sewardj2d94c112002-06-03 01:25:54 +0000560 my_assert(detached == 0 || detached == 1);
sewardj20917d82002-05-28 01:36:45 +0000561
562 if (detached) {
563 /* Detached; I just quit right now. */
564 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
565 VG_USERREQ__QUIT, 0, 0, 0, 0);
566 } else {
567 /* Not detached; so I wait for a joiner. */
568 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
569 VG_USERREQ__WAIT_JOINER, ret_val, 0, 0, 0);
570 }
571 /* NOTREACHED */
572 barf("thread_exit_wrapper: still alive?!");
573}
574
575
576/* This function is a wrapper function for running a thread. It runs
577 the root function specified in pthread_create, and then, should the
578 root function return a value, it arranges to run the thread's
579 cleanup handlers and exit correctly. */
580
sewardj728a5272002-06-20 10:25:37 +0000581/* Struct used to convey info from pthread_create to thread_wrapper.
582 Must be careful not to pass to the child thread any pointers to
583 objects which might be on the parent's stack. */
sewardj20917d82002-05-28 01:36:45 +0000584typedef
585 struct {
sewardj728a5272002-06-20 10:25:37 +0000586 int attr__detachstate;
sewardj20917d82002-05-28 01:36:45 +0000587 void* (*root_fn) ( void* );
588 void* arg;
589 }
590 NewThreadInfo;
591
592
593/* This is passed to the VG_USERREQ__APPLY_IN_NEW_THREAD and so must
594 not return. Note that this runs in the new thread, not the
595 parent. */
596static
597__attribute__((noreturn))
598void thread_wrapper ( NewThreadInfo* info )
599{
sewardj728a5272002-06-20 10:25:37 +0000600 int attr__detachstate;
sewardj20917d82002-05-28 01:36:45 +0000601 void* (*root_fn) ( void* );
602 void* arg;
603 void* ret_val;
604
sewardj728a5272002-06-20 10:25:37 +0000605 attr__detachstate = info->attr__detachstate;
606 root_fn = info->root_fn;
607 arg = info->arg;
sewardj20917d82002-05-28 01:36:45 +0000608
sewardj20917d82002-05-28 01:36:45 +0000609 /* Free up the arg block that pthread_create malloced. */
sewardj00a66b12002-10-12 16:42:35 +0000610 my_free(info);
sewardj20917d82002-05-28 01:36:45 +0000611
sewardj7989d0c2002-05-28 11:00:01 +0000612 /* Minimally observe the attributes supplied. */
sewardj728a5272002-06-20 10:25:37 +0000613 if (attr__detachstate != PTHREAD_CREATE_DETACHED
614 && attr__detachstate != PTHREAD_CREATE_JOINABLE)
615 pthread_error("thread_wrapper: invalid attr->__detachstate");
616 if (attr__detachstate == PTHREAD_CREATE_DETACHED)
617 pthread_detach(pthread_self());
sewardj7989d0c2002-05-28 11:00:01 +0000618
sewardj00a66b12002-10-12 16:42:35 +0000619# ifdef GLIBC_2_3
620 /* Set this thread's locale to the global (default) locale. A hack
621 in support of glibc-2.3. This does the biz for the all new
622 threads; the root thread is done with a horrible hack in
623 init_libc_tsd_keys() below.
624 */
625 __uselocale(LC_GLOBAL_LOCALE);
626# endif
627
sewardj20917d82002-05-28 01:36:45 +0000628 /* The root function might not return. But if it does we simply
629 move along to thread_exit_wrapper. All other ways out for the
630 thread (cancellation, or calling pthread_exit) lead there
631 too. */
632 ret_val = root_fn(arg);
633 thread_exit_wrapper(ret_val);
634 /* NOTREACHED */
635}
636
637
sewardjf8f819e2002-04-17 23:21:37 +0000638/* ---------------------------------------------------
639 THREADs
640 ------------------------------------------------ */
641
sewardjff42d1d2002-05-22 13:17:31 +0000642__attribute__((weak))
643int pthread_yield ( void )
644{
645 int res;
646 ensure_valgrind("pthread_yield");
647 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
648 VG_USERREQ__PTHREAD_YIELD, 0, 0, 0, 0);
649 return 0;
650}
651
652
sewardj6072c362002-04-19 14:40:57 +0000653int pthread_equal(pthread_t thread1, pthread_t thread2)
654{
655 return thread1 == thread2 ? 1 : 0;
656}
657
658
sewardj20917d82002-05-28 01:36:45 +0000659/* Bundle up the args into a malloc'd block and create a new thread
660 consisting of thread_wrapper() applied to said malloc'd block. */
sewardje663cb92002-04-12 10:26:32 +0000661int
sewardj1462c8b2002-07-24 09:41:52 +0000662pthread_create (pthread_t *__restrict __thredd,
sewardje663cb92002-04-12 10:26:32 +0000663 __const pthread_attr_t *__restrict __attr,
664 void *(*__start_routine) (void *),
665 void *__restrict __arg)
666{
sewardj20917d82002-05-28 01:36:45 +0000667 int tid_child;
668 NewThreadInfo* info;
sewardje663cb92002-04-12 10:26:32 +0000669
sewardj20917d82002-05-28 01:36:45 +0000670 ensure_valgrind("pthread_create");
671
sewardj00a66b12002-10-12 16:42:35 +0000672 /* make sure the tsd keys, and hence locale info, are initialised
673 before we get into complications making new threads. */
674 init_libc_tsd_keys();
675
sewardj20917d82002-05-28 01:36:45 +0000676 /* Allocate space for the arg block. thread_wrapper will free
677 it. */
sewardj00a66b12002-10-12 16:42:35 +0000678 info = my_malloc(sizeof(NewThreadInfo));
sewardj2d94c112002-06-03 01:25:54 +0000679 my_assert(info != NULL);
sewardj20917d82002-05-28 01:36:45 +0000680
sewardj728a5272002-06-20 10:25:37 +0000681 if (__attr)
682 info->attr__detachstate = __attr->__detachstate;
683 else
684 info->attr__detachstate = PTHREAD_CREATE_JOINABLE;
685
sewardj20917d82002-05-28 01:36:45 +0000686 info->root_fn = __start_routine;
687 info->arg = __arg;
688 VALGRIND_MAGIC_SEQUENCE(tid_child, VG_INVALID_THREADID /* default */,
689 VG_USERREQ__APPLY_IN_NEW_THREAD,
690 &thread_wrapper, info, 0, 0);
sewardj2d94c112002-06-03 01:25:54 +0000691 my_assert(tid_child != VG_INVALID_THREADID);
sewardj20917d82002-05-28 01:36:45 +0000692
sewardj1462c8b2002-07-24 09:41:52 +0000693 if (__thredd)
694 *__thredd = tid_child;
sewardj20917d82002-05-28 01:36:45 +0000695 return 0; /* success */
696}
sewardje663cb92002-04-12 10:26:32 +0000697
698
699int
700pthread_join (pthread_t __th, void **__thread_return)
701{
702 int res;
703 ensure_valgrind("pthread_join");
704 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
705 VG_USERREQ__PTHREAD_JOIN,
706 __th, __thread_return, 0, 0);
707 return res;
708}
709
710
sewardj3b5d8862002-04-20 13:53:23 +0000711void pthread_exit(void *retval)
712{
sewardj3b5d8862002-04-20 13:53:23 +0000713 ensure_valgrind("pthread_exit");
sewardj20917d82002-05-28 01:36:45 +0000714 /* Simple! */
715 thread_exit_wrapper(retval);
sewardj3b5d8862002-04-20 13:53:23 +0000716}
717
sewardje663cb92002-04-12 10:26:32 +0000718
sewardj853f55d2002-04-26 00:27:53 +0000719int pthread_detach(pthread_t th)
720{
sewardj20917d82002-05-28 01:36:45 +0000721 int res;
722 ensure_valgrind("pthread_detach");
sewardj7989d0c2002-05-28 11:00:01 +0000723 /* First we enquire as to the current detach state. */
724 VALGRIND_MAGIC_SEQUENCE(res, (-2) /* default */,
sewardj20917d82002-05-28 01:36:45 +0000725 VG_USERREQ__SET_OR_GET_DETACH,
sewardj7989d0c2002-05-28 11:00:01 +0000726 2 /* get */, th, 0, 0);
sewardj4dced352002-06-04 22:54:20 +0000727 if (res == -1) {
728 /* not found */
729 pthread_error("pthread_detach: "
730 "invalid target thread");
sewardj7989d0c2002-05-28 11:00:01 +0000731 return ESRCH;
sewardj4dced352002-06-04 22:54:20 +0000732 }
733 if (res == 1) {
734 /* already detached */
735 pthread_error("pthread_detach: "
736 "target thread is already detached");
sewardj7989d0c2002-05-28 11:00:01 +0000737 return EINVAL;
sewardj4dced352002-06-04 22:54:20 +0000738 }
sewardj7989d0c2002-05-28 11:00:01 +0000739 if (res == 0) {
740 VALGRIND_MAGIC_SEQUENCE(res, (-2) /* default */,
741 VG_USERREQ__SET_OR_GET_DETACH,
742 1 /* set */, th, 0, 0);
sewardj2d94c112002-06-03 01:25:54 +0000743 my_assert(res == 0);
sewardj7989d0c2002-05-28 11:00:01 +0000744 return 0;
745 }
746 barf("pthread_detach");
sewardj853f55d2002-04-26 00:27:53 +0000747}
748
749
sewardjf8f819e2002-04-17 23:21:37 +0000750/* ---------------------------------------------------
sewardj8ad94e12002-05-29 00:10:20 +0000751 CLEANUP STACKS
752 ------------------------------------------------ */
753
754void _pthread_cleanup_push (struct _pthread_cleanup_buffer *__buffer,
755 void (*__routine) (void *),
756 void *__arg)
757{
758 int res;
759 CleanupEntry cu;
760 ensure_valgrind("_pthread_cleanup_push");
761 cu.fn = __routine;
762 cu.arg = __arg;
763 VALGRIND_MAGIC_SEQUENCE(res, (-1) /* default */,
764 VG_USERREQ__CLEANUP_PUSH,
765 &cu, 0, 0, 0);
sewardj2d94c112002-06-03 01:25:54 +0000766 my_assert(res == 0);
sewardj8ad94e12002-05-29 00:10:20 +0000767}
768
769
770void _pthread_cleanup_push_defer (struct _pthread_cleanup_buffer *__buffer,
771 void (*__routine) (void *),
772 void *__arg)
773{
774 /* As _pthread_cleanup_push, but first save the thread's original
775 cancellation type in __buffer and set it to Deferred. */
776 int orig_ctype;
777 ensure_valgrind("_pthread_cleanup_push_defer");
778 /* Set to Deferred, and put the old cancellation type in res. */
sewardj2d94c112002-06-03 01:25:54 +0000779 my_assert(-1 != PTHREAD_CANCEL_DEFERRED);
780 my_assert(-1 != PTHREAD_CANCEL_ASYNCHRONOUS);
781 my_assert(sizeof(struct _pthread_cleanup_buffer) >= sizeof(int));
sewardj8ad94e12002-05-29 00:10:20 +0000782 VALGRIND_MAGIC_SEQUENCE(orig_ctype, (-1) /* default */,
783 VG_USERREQ__SET_CANCELTYPE,
784 PTHREAD_CANCEL_DEFERRED, 0, 0, 0);
sewardj2d94c112002-06-03 01:25:54 +0000785 my_assert(orig_ctype != -1);
sewardj8ad94e12002-05-29 00:10:20 +0000786 *((int*)(__buffer)) = orig_ctype;
787 /* Now push the cleanup. */
788 _pthread_cleanup_push(NULL, __routine, __arg);
789}
790
791
792void _pthread_cleanup_pop (struct _pthread_cleanup_buffer *__buffer,
793 int __execute)
794{
795 int res;
796 CleanupEntry cu;
797 ensure_valgrind("_pthread_cleanup_push");
798 cu.fn = cu.arg = NULL; /* paranoia */
799 VALGRIND_MAGIC_SEQUENCE(res, (-1) /* default */,
800 VG_USERREQ__CLEANUP_POP,
801 &cu, 0, 0, 0);
802 if (res == 0) {
803 /* pop succeeded */
804 if (__execute) {
805 cu.fn ( cu.arg );
806 }
807 return;
808 }
809 if (res == -1) {
810 /* stack underflow */
811 return;
812 }
813 barf("_pthread_cleanup_pop");
814}
815
816
817void _pthread_cleanup_pop_restore (struct _pthread_cleanup_buffer *__buffer,
818 int __execute)
819{
820 int orig_ctype, fake_ctype;
821 /* As _pthread_cleanup_pop, but after popping/running the handler,
822 restore the thread's original cancellation type from the first
823 word of __buffer. */
824 _pthread_cleanup_pop(NULL, __execute);
825 orig_ctype = *((int*)(__buffer));
sewardj2d94c112002-06-03 01:25:54 +0000826 my_assert(orig_ctype == PTHREAD_CANCEL_DEFERRED
sewardj8ad94e12002-05-29 00:10:20 +0000827 || orig_ctype == PTHREAD_CANCEL_ASYNCHRONOUS);
sewardj2d94c112002-06-03 01:25:54 +0000828 my_assert(-1 != PTHREAD_CANCEL_DEFERRED);
829 my_assert(-1 != PTHREAD_CANCEL_ASYNCHRONOUS);
830 my_assert(sizeof(struct _pthread_cleanup_buffer) >= sizeof(int));
sewardj8ad94e12002-05-29 00:10:20 +0000831 VALGRIND_MAGIC_SEQUENCE(fake_ctype, (-1) /* default */,
832 VG_USERREQ__SET_CANCELTYPE,
833 orig_ctype, 0, 0, 0);
sewardj2d94c112002-06-03 01:25:54 +0000834 my_assert(fake_ctype == PTHREAD_CANCEL_DEFERRED);
sewardj8ad94e12002-05-29 00:10:20 +0000835}
836
837
838/* ---------------------------------------------------
sewardjf8f819e2002-04-17 23:21:37 +0000839 MUTEX ATTRIBUTES
840 ------------------------------------------------ */
841
sewardj5905fae2002-04-26 13:25:00 +0000842int __pthread_mutexattr_init(pthread_mutexattr_t *attr)
sewardje663cb92002-04-12 10:26:32 +0000843{
sewardjf8f819e2002-04-17 23:21:37 +0000844 attr->__mutexkind = PTHREAD_MUTEX_ERRORCHECK_NP;
sewardj8937c812002-04-12 20:12:20 +0000845 return 0;
sewardje663cb92002-04-12 10:26:32 +0000846}
847
sewardj5905fae2002-04-26 13:25:00 +0000848int __pthread_mutexattr_settype(pthread_mutexattr_t *attr, int type)
sewardjf8f819e2002-04-17 23:21:37 +0000849{
850 switch (type) {
sewardj3b13f0e2002-04-25 20:17:29 +0000851# ifndef GLIBC_2_1
sewardjf8f819e2002-04-17 23:21:37 +0000852 case PTHREAD_MUTEX_TIMED_NP:
sewardj2a1dcce2002-04-22 12:45:25 +0000853 case PTHREAD_MUTEX_ADAPTIVE_NP:
sewardj3b13f0e2002-04-25 20:17:29 +0000854# endif
sewardja1679dd2002-05-10 22:31:40 +0000855# ifdef GLIBC_2_1
sewardj68b2dd92002-05-10 21:03:56 +0000856 case PTHREAD_MUTEX_FAST_NP:
sewardja1679dd2002-05-10 22:31:40 +0000857# endif
sewardjf8f819e2002-04-17 23:21:37 +0000858 case PTHREAD_MUTEX_RECURSIVE_NP:
859 case PTHREAD_MUTEX_ERRORCHECK_NP:
sewardjf8f819e2002-04-17 23:21:37 +0000860 attr->__mutexkind = type;
861 return 0;
862 default:
sewardj4dced352002-06-04 22:54:20 +0000863 pthread_error("pthread_mutexattr_settype: "
864 "invalid type");
sewardjf8f819e2002-04-17 23:21:37 +0000865 return EINVAL;
866 }
867}
868
sewardj5905fae2002-04-26 13:25:00 +0000869int __pthread_mutexattr_destroy(pthread_mutexattr_t *attr)
sewardjf8f819e2002-04-17 23:21:37 +0000870{
871 return 0;
872}
873
874
875/* ---------------------------------------------------
876 MUTEXes
877 ------------------------------------------------ */
878
sewardj5905fae2002-04-26 13:25:00 +0000879int __pthread_mutex_init(pthread_mutex_t *mutex,
880 const pthread_mutexattr_t *mutexattr)
sewardje663cb92002-04-12 10:26:32 +0000881{
sewardj604ec3c2002-04-18 22:38:41 +0000882 mutex->__m_count = 0;
883 mutex->__m_owner = (_pthread_descr)VG_INVALID_THREADID;
884 mutex->__m_kind = PTHREAD_MUTEX_ERRORCHECK_NP;
885 if (mutexattr)
886 mutex->__m_kind = mutexattr->__mutexkind;
887 return 0;
sewardje663cb92002-04-12 10:26:32 +0000888}
889
sewardj439d45e2002-05-03 20:43:10 +0000890
sewardj5905fae2002-04-26 13:25:00 +0000891int __pthread_mutex_lock(pthread_mutex_t *mutex)
sewardje663cb92002-04-12 10:26:32 +0000892{
893 int res;
sewardjd8acdf22002-11-13 21:57:52 +0000894
sewardj439d45e2002-05-03 20:43:10 +0000895 if (RUNNING_ON_VALGRIND) {
sewardje663cb92002-04-12 10:26:32 +0000896 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
897 VG_USERREQ__PTHREAD_MUTEX_LOCK,
898 mutex, 0, 0, 0);
899 return res;
sewardj439d45e2002-05-03 20:43:10 +0000900 } else {
sewardjd8acdf22002-11-13 21:57:52 +0000901 /* Play at locking */
902 if (0)
903 kludged("prehistoric lock");
904 mutex->__m_owner = (_pthread_descr)1;
905 mutex->__m_count = 1;
906 mutex->__m_kind |= VG_PTHREAD_PREHISTORY;
sewardj439d45e2002-05-03 20:43:10 +0000907 return 0; /* success */
sewardje663cb92002-04-12 10:26:32 +0000908 }
909}
910
sewardj439d45e2002-05-03 20:43:10 +0000911
sewardj5905fae2002-04-26 13:25:00 +0000912int __pthread_mutex_trylock(pthread_mutex_t *mutex)
sewardj30671ff2002-04-21 00:13:57 +0000913{
914 int res;
sewardjd8acdf22002-11-13 21:57:52 +0000915
sewardj439d45e2002-05-03 20:43:10 +0000916 if (RUNNING_ON_VALGRIND) {
sewardj30671ff2002-04-21 00:13:57 +0000917 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
918 VG_USERREQ__PTHREAD_MUTEX_TRYLOCK,
919 mutex, 0, 0, 0);
920 return res;
sewardj439d45e2002-05-03 20:43:10 +0000921 } else {
sewardjd8acdf22002-11-13 21:57:52 +0000922 /* Play at locking */
923 if (0)
924 kludged("prehistoric trylock");
925 mutex->__m_owner = (_pthread_descr)1;
926 mutex->__m_count = 1;
927 mutex->__m_kind |= VG_PTHREAD_PREHISTORY;
928 return 0; /* success */
sewardj30671ff2002-04-21 00:13:57 +0000929 }
930}
931
sewardj439d45e2002-05-03 20:43:10 +0000932
sewardj5905fae2002-04-26 13:25:00 +0000933int __pthread_mutex_unlock(pthread_mutex_t *mutex)
sewardje663cb92002-04-12 10:26:32 +0000934{
935 int res;
sewardjd8acdf22002-11-13 21:57:52 +0000936
sewardj439d45e2002-05-03 20:43:10 +0000937 if (RUNNING_ON_VALGRIND) {
sewardje663cb92002-04-12 10:26:32 +0000938 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
939 VG_USERREQ__PTHREAD_MUTEX_UNLOCK,
940 mutex, 0, 0, 0);
941 return res;
sewardj439d45e2002-05-03 20:43:10 +0000942 } else {
sewardjd8acdf22002-11-13 21:57:52 +0000943 /* Play at locking */
944 if (0)
945 kludged("prehistoric unlock");
946 mutex->__m_owner = 0;
947 mutex->__m_count = 0;
948 mutex->__m_kind &= ~VG_PTHREAD_PREHISTORY;
949 return 0; /* success */
sewardje663cb92002-04-12 10:26:32 +0000950 }
951}
952
sewardj439d45e2002-05-03 20:43:10 +0000953
sewardj5905fae2002-04-26 13:25:00 +0000954int __pthread_mutex_destroy(pthread_mutex_t *mutex)
sewardje663cb92002-04-12 10:26:32 +0000955{
sewardj604ec3c2002-04-18 22:38:41 +0000956 /* Valgrind doesn't hold any resources on behalf of the mutex, so no
957 need to involve it. */
sewardj4dced352002-06-04 22:54:20 +0000958 if (mutex->__m_count > 0) {
sewardjd8acdf22002-11-13 21:57:52 +0000959 /* Oh, the horror. glibc's internal use of pthreads "knows"
960 that destroying a lock does an implicit unlock. Make it
961 explicit. */
962 __pthread_mutex_unlock(mutex);
963 pthread_error("pthread_mutex_destroy: "
964 "mutex is still in use");
965 return EBUSY;
sewardj4dced352002-06-04 22:54:20 +0000966 }
967 mutex->__m_count = 0;
968 mutex->__m_owner = (_pthread_descr)VG_INVALID_THREADID;
969 mutex->__m_kind = PTHREAD_MUTEX_ERRORCHECK_NP;
970 return 0;
sewardje663cb92002-04-12 10:26:32 +0000971}
972
973
sewardjf8f819e2002-04-17 23:21:37 +0000974/* ---------------------------------------------------
sewardj6072c362002-04-19 14:40:57 +0000975 CONDITION VARIABLES
976 ------------------------------------------------ */
977
978/* LinuxThreads supports no attributes for conditions. Hence ... */
979
980int pthread_condattr_init(pthread_condattr_t *attr)
981{
982 return 0;
983}
984
sewardj0738a592002-04-20 13:59:33 +0000985int pthread_condattr_destroy(pthread_condattr_t *attr)
986{
987 return 0;
988}
sewardj6072c362002-04-19 14:40:57 +0000989
990int pthread_cond_init( pthread_cond_t *cond,
991 const pthread_condattr_t *cond_attr)
992{
993 cond->__c_waiting = (_pthread_descr)VG_INVALID_THREADID;
994 return 0;
995}
996
sewardjf854f472002-04-21 12:19:41 +0000997int pthread_cond_destroy(pthread_cond_t *cond)
998{
999 /* should check that no threads are waiting on this CV */
sewardj436e0582002-04-26 14:31:40 +00001000 static int moans = N_MOANS;
1001 if (moans-- > 0)
1002 kludged("pthread_cond_destroy");
sewardjf854f472002-04-21 12:19:41 +00001003 return 0;
1004}
sewardj6072c362002-04-19 14:40:57 +00001005
1006/* ---------------------------------------------------
1007 SCHEDULING
1008 ------------------------------------------------ */
1009
1010/* This is completely bogus. */
1011int pthread_getschedparam(pthread_t target_thread,
1012 int *policy,
1013 struct sched_param *param)
1014{
sewardj436e0582002-04-26 14:31:40 +00001015 static int moans = N_MOANS;
1016 if (moans-- > 0)
1017 kludged("pthread_getschedparam");
sewardj6072c362002-04-19 14:40:57 +00001018 if (policy) *policy = SCHED_OTHER;
sewardj3e909ce2002-06-03 13:27:15 +00001019# ifdef HAVE_SCHED_PRIORITY
sewardj2a1dcce2002-04-22 12:45:25 +00001020 if (param) param->sched_priority = 0; /* who knows */
1021# else
sewardj6072c362002-04-19 14:40:57 +00001022 if (param) param->__sched_priority = 0; /* who knows */
sewardj2a1dcce2002-04-22 12:45:25 +00001023# endif
sewardj6072c362002-04-19 14:40:57 +00001024 return 0;
1025}
1026
1027int pthread_setschedparam(pthread_t target_thread,
1028 int policy,
1029 const struct sched_param *param)
1030{
sewardj436e0582002-04-26 14:31:40 +00001031 static int moans = N_MOANS;
1032 if (moans-- > 0)
1033 ignored("pthread_setschedparam");
sewardj6072c362002-04-19 14:40:57 +00001034 return 0;
1035}
1036
sewardj3b5d8862002-04-20 13:53:23 +00001037int pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex)
1038{
1039 int res;
1040 ensure_valgrind("pthread_cond_wait");
1041 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
1042 VG_USERREQ__PTHREAD_COND_WAIT,
1043 cond, mutex, 0, 0);
1044 return res;
1045}
1046
sewardj5f07b662002-04-23 16:52:51 +00001047int pthread_cond_timedwait ( pthread_cond_t *cond,
1048 pthread_mutex_t *mutex,
1049 const struct timespec *abstime )
1050{
1051 int res;
1052 unsigned int ms_now, ms_end;
1053 struct timeval timeval_now;
1054 unsigned long long int ull_ms_now_after_1970;
1055 unsigned long long int ull_ms_end_after_1970;
1056
1057 ensure_valgrind("pthread_cond_timedwait");
1058 VALGRIND_MAGIC_SEQUENCE(ms_now, 0xFFFFFFFF /* default */,
1059 VG_USERREQ__READ_MILLISECOND_TIMER,
1060 0, 0, 0, 0);
sewardj2d94c112002-06-03 01:25:54 +00001061 my_assert(ms_now != 0xFFFFFFFF);
sewardj5f07b662002-04-23 16:52:51 +00001062 res = gettimeofday(&timeval_now, NULL);
sewardj2d94c112002-06-03 01:25:54 +00001063 my_assert(res == 0);
sewardj5f07b662002-04-23 16:52:51 +00001064
1065 ull_ms_now_after_1970
1066 = 1000ULL * ((unsigned long long int)(timeval_now.tv_sec))
1067 + ((unsigned long long int)(timeval_now.tv_usec / 1000000));
1068 ull_ms_end_after_1970
1069 = 1000ULL * ((unsigned long long int)(abstime->tv_sec))
1070 + ((unsigned long long int)(abstime->tv_nsec / 1000000));
sewardjd8e919e2002-05-29 20:13:53 +00001071 if (ull_ms_end_after_1970 < ull_ms_now_after_1970)
1072 ull_ms_end_after_1970 = ull_ms_now_after_1970;
sewardj5f07b662002-04-23 16:52:51 +00001073 ms_end
1074 = ms_now + (unsigned int)(ull_ms_end_after_1970 - ull_ms_now_after_1970);
1075 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
1076 VG_USERREQ__PTHREAD_COND_TIMEDWAIT,
1077 cond, mutex, ms_end, 0);
1078 return res;
1079}
1080
1081
sewardj3b5d8862002-04-20 13:53:23 +00001082int pthread_cond_signal(pthread_cond_t *cond)
1083{
1084 int res;
1085 ensure_valgrind("pthread_cond_signal");
1086 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
1087 VG_USERREQ__PTHREAD_COND_SIGNAL,
1088 cond, 0, 0, 0);
1089 return res;
1090}
1091
1092int pthread_cond_broadcast(pthread_cond_t *cond)
1093{
1094 int res;
1095 ensure_valgrind("pthread_cond_broadcast");
1096 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
1097 VG_USERREQ__PTHREAD_COND_BROADCAST,
1098 cond, 0, 0, 0);
1099 return res;
1100}
1101
sewardj6072c362002-04-19 14:40:57 +00001102
1103/* ---------------------------------------------------
sewardjf8f819e2002-04-17 23:21:37 +00001104 CANCELLATION
1105 ------------------------------------------------ */
1106
sewardj853f55d2002-04-26 00:27:53 +00001107int pthread_setcancelstate(int state, int *oldstate)
1108{
sewardj20917d82002-05-28 01:36:45 +00001109 int res;
1110 ensure_valgrind("pthread_setcancelstate");
1111 if (state != PTHREAD_CANCEL_ENABLE
sewardj4dced352002-06-04 22:54:20 +00001112 && state != PTHREAD_CANCEL_DISABLE) {
1113 pthread_error("pthread_setcancelstate: "
1114 "invalid state");
sewardj20917d82002-05-28 01:36:45 +00001115 return EINVAL;
sewardj4dced352002-06-04 22:54:20 +00001116 }
sewardj2d94c112002-06-03 01:25:54 +00001117 my_assert(-1 != PTHREAD_CANCEL_ENABLE);
1118 my_assert(-1 != PTHREAD_CANCEL_DISABLE);
sewardj20917d82002-05-28 01:36:45 +00001119 VALGRIND_MAGIC_SEQUENCE(res, (-1) /* default */,
1120 VG_USERREQ__SET_CANCELSTATE,
1121 state, 0, 0, 0);
sewardj2d94c112002-06-03 01:25:54 +00001122 my_assert(res != -1);
sewardj20917d82002-05-28 01:36:45 +00001123 if (oldstate)
1124 *oldstate = res;
sewardj853f55d2002-04-26 00:27:53 +00001125 return 0;
1126}
1127
sewardje663cb92002-04-12 10:26:32 +00001128int pthread_setcanceltype(int type, int *oldtype)
1129{
sewardj20917d82002-05-28 01:36:45 +00001130 int res;
1131 ensure_valgrind("pthread_setcanceltype");
1132 if (type != PTHREAD_CANCEL_DEFERRED
sewardj4dced352002-06-04 22:54:20 +00001133 && type != PTHREAD_CANCEL_ASYNCHRONOUS) {
1134 pthread_error("pthread_setcanceltype: "
1135 "invalid type");
sewardj20917d82002-05-28 01:36:45 +00001136 return EINVAL;
sewardj4dced352002-06-04 22:54:20 +00001137 }
sewardj2d94c112002-06-03 01:25:54 +00001138 my_assert(-1 != PTHREAD_CANCEL_DEFERRED);
1139 my_assert(-1 != PTHREAD_CANCEL_ASYNCHRONOUS);
sewardj20917d82002-05-28 01:36:45 +00001140 VALGRIND_MAGIC_SEQUENCE(res, (-1) /* default */,
1141 VG_USERREQ__SET_CANCELTYPE,
1142 type, 0, 0, 0);
sewardj2d94c112002-06-03 01:25:54 +00001143 my_assert(res != -1);
sewardj20917d82002-05-28 01:36:45 +00001144 if (oldtype)
1145 *oldtype = res;
sewardje663cb92002-04-12 10:26:32 +00001146 return 0;
1147}
1148
sewardje663cb92002-04-12 10:26:32 +00001149int pthread_cancel(pthread_t thread)
1150{
1151 int res;
1152 ensure_valgrind("pthread_cancel");
sewardj20917d82002-05-28 01:36:45 +00001153 VALGRIND_MAGIC_SEQUENCE(res, (-1) /* default */,
1154 VG_USERREQ__SET_CANCELPEND,
1155 thread, &thread_exit_wrapper, 0, 0);
sewardj2d94c112002-06-03 01:25:54 +00001156 my_assert(res != -1);
sewardje663cb92002-04-12 10:26:32 +00001157 return res;
1158}
1159
sewardjd140e442002-05-29 01:21:19 +00001160static __inline__
1161void __my_pthread_testcancel(void)
sewardj853f55d2002-04-26 00:27:53 +00001162{
sewardj20917d82002-05-28 01:36:45 +00001163 int res;
njn25e49d8e72002-09-23 09:36:25 +00001164 ensure_valgrind("__my_pthread_testcancel");
sewardj20917d82002-05-28 01:36:45 +00001165 VALGRIND_MAGIC_SEQUENCE(res, (-1) /* default */,
1166 VG_USERREQ__TESTCANCEL,
1167 0, 0, 0, 0);
sewardj2d94c112002-06-03 01:25:54 +00001168 my_assert(res == 0);
sewardj853f55d2002-04-26 00:27:53 +00001169}
1170
sewardjd140e442002-05-29 01:21:19 +00001171void pthread_testcancel ( void )
1172{
1173 __my_pthread_testcancel();
1174}
1175
sewardj20917d82002-05-28 01:36:45 +00001176
sewardjef037c72002-05-30 00:40:03 +00001177/* Not really sure what this is for. I suspect for doing the POSIX
1178 requirements for fork() and exec(). We do this internally anyway
1179 whenever those syscalls are observed, so this could be superfluous,
1180 but hey ...
1181*/
sewardj853f55d2002-04-26 00:27:53 +00001182void __pthread_kill_other_threads_np ( void )
1183{
sewardjef037c72002-05-30 00:40:03 +00001184 int res;
1185 ensure_valgrind("__pthread_kill_other_threads_np");
1186 VALGRIND_MAGIC_SEQUENCE(res, (-1) /* default */,
1187 VG_USERREQ__NUKE_OTHER_THREADS,
1188 0, 0, 0, 0);
sewardj2d94c112002-06-03 01:25:54 +00001189 my_assert(res == 0);
sewardj853f55d2002-04-26 00:27:53 +00001190}
1191
sewardje663cb92002-04-12 10:26:32 +00001192
sewardjf8f819e2002-04-17 23:21:37 +00001193/* ---------------------------------------------------
sewardjb48e5002002-05-13 00:16:03 +00001194 SIGNALS
1195 ------------------------------------------------ */
1196
1197#include <signal.h>
1198
1199int pthread_sigmask(int how, const sigset_t *newmask,
1200 sigset_t *oldmask)
1201{
1202 int res;
1203
1204 /* A bit subtle, because the scheduler expects newmask and oldmask
1205 to be vki_sigset_t* rather than sigset_t*, and the two are
1206 different. Fortunately the first 64 bits of a sigset_t are
1207 exactly a vki_sigset_t, so we just pass the pointers through
1208 unmodified. Haaaack!
1209
1210 Also mash the how value so that the SIG_ constants from glibc
sewardj018f7622002-05-15 21:13:39 +00001211 constants to VKI_ constants, so that the former do not have to
1212 be included into vg_scheduler.c. */
sewardjb48e5002002-05-13 00:16:03 +00001213
1214 ensure_valgrind("pthread_sigmask");
1215
1216 switch (how) {
sewardj018f7622002-05-15 21:13:39 +00001217 case SIG_SETMASK: how = VKI_SIG_SETMASK; break;
1218 case SIG_BLOCK: how = VKI_SIG_BLOCK; break;
1219 case SIG_UNBLOCK: how = VKI_SIG_UNBLOCK; break;
sewardj4dced352002-06-04 22:54:20 +00001220 default: pthread_error("pthread_sigmask: invalid how");
1221 return EINVAL;
sewardjb48e5002002-05-13 00:16:03 +00001222 }
1223
1224 /* Crude check */
1225 if (newmask == NULL)
1226 return EFAULT;
1227
1228 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
1229 VG_USERREQ__PTHREAD_SIGMASK,
1230 how, newmask, oldmask, 0);
1231
1232 /* The scheduler tells us of any memory violations. */
1233 return res == 0 ? 0 : EFAULT;
1234}
1235
1236
1237int sigwait ( const sigset_t* set, int* sig )
1238{
1239 int res;
1240 ensure_valgrind("sigwait");
1241 /* As with pthread_sigmask we deliberately confuse sigset_t with
1242 vki_ksigset_t. */
1243 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
1244 VG_USERREQ__SIGWAIT,
1245 set, sig, 0, 0);
1246 return res;
1247}
1248
1249
sewardj018f7622002-05-15 21:13:39 +00001250int pthread_kill(pthread_t thread, int signo)
1251{
1252 int res;
1253 ensure_valgrind("pthread_kill");
1254 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
1255 VG_USERREQ__PTHREAD_KILL,
1256 thread, signo, 0, 0);
1257 return res;
1258}
1259
1260
sewardj3665ded2002-05-16 16:57:25 +00001261/* Copied verbatim from Linuxthreads */
1262/* Redefine raise() to send signal to calling thread only,
1263 as per POSIX 1003.1c */
1264int raise (int sig)
1265{
1266 int retcode = pthread_kill(pthread_self(), sig);
sewardj4dced352002-06-04 22:54:20 +00001267 if (retcode == 0) {
sewardj3665ded2002-05-16 16:57:25 +00001268 return 0;
sewardj4dced352002-06-04 22:54:20 +00001269 } else {
sewardj3665ded2002-05-16 16:57:25 +00001270 errno = retcode;
1271 return -1;
1272 }
1273}
1274
1275
sewardj9a2224b2002-06-19 10:17:40 +00001276int pause ( void )
1277{
1278 unsigned int n_orig, n_now;
1279 struct vki_timespec nanosleep_interval;
1280 ensure_valgrind("pause");
1281
1282 /* This is surely a cancellation point. */
1283 __my_pthread_testcancel();
1284
1285 VALGRIND_MAGIC_SEQUENCE(n_orig, 0xFFFFFFFF /* default */,
1286 VG_USERREQ__GET_N_SIGS_RETURNED,
1287 0, 0, 0, 0);
1288 my_assert(n_orig != 0xFFFFFFFF);
1289
1290 while (1) {
1291 VALGRIND_MAGIC_SEQUENCE(n_now, 0xFFFFFFFF /* default */,
1292 VG_USERREQ__GET_N_SIGS_RETURNED,
1293 0, 0, 0, 0);
1294 my_assert(n_now != 0xFFFFFFFF);
1295 my_assert(n_now >= n_orig);
1296 if (n_now != n_orig) break;
1297
1298 nanosleep_interval.tv_sec = 0;
njn25e49d8e72002-09-23 09:36:25 +00001299 nanosleep_interval.tv_nsec = 12 * 1000 * 1000; /* 12 milliseconds */
sewardj9a2224b2002-06-19 10:17:40 +00001300 /* It's critical here that valgrind's nanosleep implementation
1301 is nonblocking. */
1302 (void)my_do_syscall2(__NR_nanosleep,
1303 (int)(&nanosleep_interval), (int)NULL);
1304 }
1305
1306 * (__errno_location()) = EINTR;
1307 return -1;
1308}
1309
1310
sewardjb48e5002002-05-13 00:16:03 +00001311/* ---------------------------------------------------
sewardjf8f819e2002-04-17 23:21:37 +00001312 THREAD-SPECIFICs
1313 ------------------------------------------------ */
sewardj5e5fa512002-04-14 13:13:05 +00001314
sewardj00a66b12002-10-12 16:42:35 +00001315static
1316int key_is_valid (pthread_key_t key)
1317{
1318 int res;
1319 VALGRIND_MAGIC_SEQUENCE(res, 2 /* default */,
1320 VG_USERREQ__PTHREAD_KEY_VALIDATE,
1321 key, 0, 0, 0);
1322 my_assert(res != 2);
1323 return res;
1324}
1325
1326
1327/* Returns NULL if thread is invalid. Otherwise, if the thread
1328 already has a specifics area, return that. Otherwise allocate it
1329 one. */
1330static
1331void** get_or_allocate_specifics_ptr ( pthread_t thread )
1332{
1333 int res, i;
1334 void** specifics_ptr;
1335 ensure_valgrind("get_or_allocate_specifics_ptr");
1336
1337 /* Returns zero if the thread has no specific_ptr. One if thread
1338 is invalid. Otherwise, the specific_ptr value. This is
1339 allocated with my_malloc and so is aligned and cannot be
1340 confused with 1 or 3. */
1341 VALGRIND_MAGIC_SEQUENCE(specifics_ptr, 3 /* default */,
1342 VG_USERREQ__PTHREAD_GETSPECIFIC_PTR,
1343 thread, 0, 0, 0);
1344 my_assert(specifics_ptr != (void**)3);
1345
1346 if (specifics_ptr == (void**)1)
1347 return NULL; /* invalid thread */
1348
1349 if (specifics_ptr != NULL)
1350 return specifics_ptr; /* already has a specifics ptr. */
1351
1352 /* None yet ... allocate a new one. Should never fail. */
1353 specifics_ptr = my_malloc( VG_N_THREAD_KEYS * sizeof(void*) );
1354 my_assert(specifics_ptr != NULL);
1355
1356 VALGRIND_MAGIC_SEQUENCE(res, -1 /* default */,
1357 VG_USERREQ__PTHREAD_SETSPECIFIC_PTR,
1358 specifics_ptr, 0, 0, 0);
1359 my_assert(res == 0);
1360
1361 /* POSIX sez: "Upon thread creation, the value NULL shall be
1362 associated with all defined keys in the new thread." This
1363 allocation is in effect a delayed allocation of the specific
1364 data for a thread, at its first-use. Hence we initialise it
1365 here. */
1366 for (i = 0; i < VG_N_THREAD_KEYS; i++) {
1367 specifics_ptr[i] = NULL;
1368 }
1369
1370 return specifics_ptr;
1371}
1372
1373
sewardj5905fae2002-04-26 13:25:00 +00001374int __pthread_key_create(pthread_key_t *key,
1375 void (*destr_function) (void *))
sewardj5e5fa512002-04-14 13:13:05 +00001376{
sewardj00a66b12002-10-12 16:42:35 +00001377 void** specifics_ptr;
1378 int res, i;
sewardj5f07b662002-04-23 16:52:51 +00001379 ensure_valgrind("pthread_key_create");
sewardj00a66b12002-10-12 16:42:35 +00001380
1381 /* This writes *key if successful. It should never fail. */
1382 VALGRIND_MAGIC_SEQUENCE(res, 1 /* default */,
sewardj5f07b662002-04-23 16:52:51 +00001383 VG_USERREQ__PTHREAD_KEY_CREATE,
1384 key, destr_function, 0, 0);
sewardj00a66b12002-10-12 16:42:35 +00001385 my_assert(res == 0);
1386
1387 /* POSIX sez: "Upon key creation, the value NULL shall be
1388 associated with the new key in all active threads." */
1389 for (i = 0; i < VG_N_THREADS; i++) {
1390 specifics_ptr = get_or_allocate_specifics_ptr(i);
1391 /* we get NULL if i is an invalid thread. */
1392 if (specifics_ptr != NULL)
1393 specifics_ptr[*key] = NULL;
1394 }
1395
sewardj5f07b662002-04-23 16:52:51 +00001396 return res;
sewardj5e5fa512002-04-14 13:13:05 +00001397}
1398
1399int pthread_key_delete(pthread_key_t key)
1400{
sewardj00a66b12002-10-12 16:42:35 +00001401 int res;
1402 ensure_valgrind("pthread_key_create");
1403 if (!key_is_valid(key))
1404 return EINVAL;
1405 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
1406 VG_USERREQ__PTHREAD_KEY_DELETE,
1407 key, 0, 0, 0);
1408 my_assert(res == 0);
sewardj5e5fa512002-04-14 13:13:05 +00001409 return 0;
1410}
1411
sewardj5905fae2002-04-26 13:25:00 +00001412int __pthread_setspecific(pthread_key_t key, const void *pointer)
sewardj5e5fa512002-04-14 13:13:05 +00001413{
sewardj00a66b12002-10-12 16:42:35 +00001414 void** specifics_ptr;
sewardj5f07b662002-04-23 16:52:51 +00001415 ensure_valgrind("pthread_setspecific");
sewardj00a66b12002-10-12 16:42:35 +00001416
1417 if (!key_is_valid(key))
1418 return EINVAL;
1419
1420 specifics_ptr = get_or_allocate_specifics_ptr(pthread_self());
1421 specifics_ptr[key] = (void*)pointer;
1422 return 0;
sewardj5e5fa512002-04-14 13:13:05 +00001423}
1424
sewardj5905fae2002-04-26 13:25:00 +00001425void * __pthread_getspecific(pthread_key_t key)
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_getspecific");
sewardj00a66b12002-10-12 16:42:35 +00001429
1430 if (!key_is_valid(key))
1431 return NULL;
1432
1433 specifics_ptr = get_or_allocate_specifics_ptr(pthread_self());
1434 return specifics_ptr[key];
1435}
1436
1437
sewardj9aa918d2002-10-20 16:25:55 +00001438#ifdef GLIBC_2_3
sewardj00a66b12002-10-12 16:42:35 +00001439static
1440void ** __pthread_getspecific_addr(pthread_key_t key)
1441{
1442 void** specifics_ptr;
1443 ensure_valgrind("pthread_getspecific_addr");
1444
1445 if (!key_is_valid(key))
1446 return NULL;
1447
1448 specifics_ptr = get_or_allocate_specifics_ptr(pthread_self());
1449 return &(specifics_ptr[key]);
sewardj5e5fa512002-04-14 13:13:05 +00001450}
sewardj9aa918d2002-10-20 16:25:55 +00001451#endif
sewardjf8f819e2002-04-17 23:21:37 +00001452
1453/* ---------------------------------------------------
sewardj89d3d852002-04-24 19:21:39 +00001454 ONCEry
1455 ------------------------------------------------ */
1456
1457static pthread_mutex_t once_masterlock = PTHREAD_MUTEX_INITIALIZER;
1458
1459
sewardj5905fae2002-04-26 13:25:00 +00001460int __pthread_once ( pthread_once_t *once_control,
1461 void (*init_routine) (void) )
sewardj89d3d852002-04-24 19:21:39 +00001462{
1463 int res;
1464 ensure_valgrind("pthread_once");
1465
sewardj68b2dd92002-05-10 21:03:56 +00001466 res = __pthread_mutex_lock(&once_masterlock);
sewardj89d3d852002-04-24 19:21:39 +00001467
sewardj68b2dd92002-05-10 21:03:56 +00001468 if (res != 0) {
sewardj89d3d852002-04-24 19:21:39 +00001469 barf("pthread_once: Looks like your program's "
1470 "init routine calls back to pthread_once() ?!");
sewardj68b2dd92002-05-10 21:03:56 +00001471 }
sewardj89d3d852002-04-24 19:21:39 +00001472
1473 if (*once_control == 0) {
1474 *once_control = 1;
1475 init_routine();
1476 }
1477
sewardj68b2dd92002-05-10 21:03:56 +00001478 __pthread_mutex_unlock(&once_masterlock);
sewardj89d3d852002-04-24 19:21:39 +00001479
1480 return 0;
1481}
1482
1483
1484/* ---------------------------------------------------
sewardj853f55d2002-04-26 00:27:53 +00001485 MISC
1486 ------------------------------------------------ */
1487
sewardj2cb00342002-06-28 01:46:26 +00001488static pthread_mutex_t pthread_atfork_lock
1489 = PTHREAD_MUTEX_INITIALIZER;
1490
sewardj5905fae2002-04-26 13:25:00 +00001491int __pthread_atfork ( void (*prepare)(void),
1492 void (*parent)(void),
1493 void (*child)(void) )
sewardj853f55d2002-04-26 00:27:53 +00001494{
sewardj2cb00342002-06-28 01:46:26 +00001495 int n, res;
1496 ForkHandlerEntry entry;
1497
1498 ensure_valgrind("pthread_atfork");
1499 __pthread_mutex_lock(&pthread_atfork_lock);
1500
1501 /* Fetch old counter */
1502 VALGRIND_MAGIC_SEQUENCE(n, -2 /* default */,
1503 VG_USERREQ__GET_FHSTACK_USED,
1504 0, 0, 0, 0);
1505 my_assert(n >= 0 && n < VG_N_FORKHANDLERSTACK);
1506 if (n == VG_N_FORKHANDLERSTACK-1)
1507 barf("pthread_atfork: VG_N_FORKHANDLERSTACK is too low; "
1508 "increase and recompile");
1509
1510 /* Add entry */
1511 entry.prepare = *prepare;
1512 entry.parent = *parent;
1513 entry.child = *child;
1514 VALGRIND_MAGIC_SEQUENCE(res, -2 /* default */,
1515 VG_USERREQ__SET_FHSTACK_ENTRY,
1516 n, &entry, 0, 0);
1517 my_assert(res == 0);
1518
1519 /* Bump counter */
1520 VALGRIND_MAGIC_SEQUENCE(res, -2 /* default */,
1521 VG_USERREQ__SET_FHSTACK_USED,
1522 n+1, 0, 0, 0);
1523 my_assert(res == 0);
1524
1525 __pthread_mutex_unlock(&pthread_atfork_lock);
1526 return 0;
sewardj853f55d2002-04-26 00:27:53 +00001527}
1528
1529
sewardjbb990782002-05-08 02:01:14 +00001530__attribute__((weak))
1531void __pthread_initialize ( void )
1532{
sewardjbea1caa2002-05-10 23:20:58 +00001533 ensure_valgrind("__pthread_initialize");
sewardjbb990782002-05-08 02:01:14 +00001534}
1535
1536
sewardj853f55d2002-04-26 00:27:53 +00001537/* ---------------------------------------------------
sewardj3b13f0e2002-04-25 20:17:29 +00001538 LIBRARY-PRIVATE THREAD SPECIFIC STATE
sewardjf8f819e2002-04-17 23:21:37 +00001539 ------------------------------------------------ */
1540
sewardj3b13f0e2002-04-25 20:17:29 +00001541#include <resolv.h>
1542static int thread_specific_errno[VG_N_THREADS];
1543static int thread_specific_h_errno[VG_N_THREADS];
1544static struct __res_state
1545 thread_specific_res_state[VG_N_THREADS];
sewardjf8f819e2002-04-17 23:21:37 +00001546
sewardj3b13f0e2002-04-25 20:17:29 +00001547int* __errno_location ( void )
sewardjf8f819e2002-04-17 23:21:37 +00001548{
1549 int tid;
sewardj3b13f0e2002-04-25 20:17:29 +00001550 /* ensure_valgrind("__errno_location"); */
1551 VALGRIND_MAGIC_SEQUENCE(tid, 1 /* default */,
sewardjf8f819e2002-04-17 23:21:37 +00001552 VG_USERREQ__PTHREAD_GET_THREADID,
1553 0, 0, 0, 0);
sewardj3b13f0e2002-04-25 20:17:29 +00001554 /* 'cos I'm paranoid ... */
sewardj439d45e2002-05-03 20:43:10 +00001555 if (tid < 1 || tid >= VG_N_THREADS)
sewardj3b13f0e2002-04-25 20:17:29 +00001556 barf("__errno_location: invalid ThreadId");
1557 return & thread_specific_errno[tid];
1558}
1559
1560int* __h_errno_location ( void )
1561{
1562 int tid;
1563 /* ensure_valgrind("__h_errno_location"); */
1564 VALGRIND_MAGIC_SEQUENCE(tid, 1 /* default */,
1565 VG_USERREQ__PTHREAD_GET_THREADID,
1566 0, 0, 0, 0);
1567 /* '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("__h_errno_location: invalid ThreadId");
1570 return & thread_specific_h_errno[tid];
1571}
1572
sewardjb0ff1032002-08-06 09:02:53 +00001573
1574#undef _res
1575extern struct __res_state _res;
1576
sewardj3b13f0e2002-04-25 20:17:29 +00001577struct __res_state* __res_state ( void )
1578{
1579 int tid;
1580 /* ensure_valgrind("__res_state"); */
1581 VALGRIND_MAGIC_SEQUENCE(tid, 1 /* default */,
1582 VG_USERREQ__PTHREAD_GET_THREADID,
1583 0, 0, 0, 0);
1584 /* 'cos I'm paranoid ... */
sewardj439d45e2002-05-03 20:43:10 +00001585 if (tid < 1 || tid >= VG_N_THREADS)
sewardj3b13f0e2002-04-25 20:17:29 +00001586 barf("__res_state: invalid ThreadId");
sewardjb0ff1032002-08-06 09:02:53 +00001587 if (tid == 1)
1588 return & _res;
sewardj3b13f0e2002-04-25 20:17:29 +00001589 return & thread_specific_res_state[tid];
sewardjf8f819e2002-04-17 23:21:37 +00001590}
1591
1592
sewardj5716dbb2002-04-26 03:28:18 +00001593/* ---------------------------------------------------
1594 LIBC-PRIVATE SPECIFIC DATA
1595 ------------------------------------------------ */
1596
1597/* Relies on assumption that initial private data is NULL. This
1598 should be fixed somehow. */
1599
njn25e49d8e72002-09-23 09:36:25 +00001600/* The allowable keys (indices) (all 3 of them).
sewardj5716dbb2002-04-26 03:28:18 +00001601 From sysdeps/pthread/bits/libc-tsd.h
1602*/
sewardjcb7f08a2002-10-02 09:41:49 +00001603/* as per glibc anoncvs HEAD of 20021001. */
sewardj5716dbb2002-04-26 03:28:18 +00001604enum __libc_tsd_key_t { _LIBC_TSD_KEY_MALLOC = 0,
1605 _LIBC_TSD_KEY_DL_ERROR,
njn25e49d8e72002-09-23 09:36:25 +00001606 _LIBC_TSD_KEY_RPC_VARS,
sewardjcb7f08a2002-10-02 09:41:49 +00001607 _LIBC_TSD_KEY_LOCALE,
1608 _LIBC_TSD_KEY_CTYPE_B,
1609 _LIBC_TSD_KEY_CTYPE_TOLOWER,
1610 _LIBC_TSD_KEY_CTYPE_TOUPPER,
sewardj5716dbb2002-04-26 03:28:18 +00001611 _LIBC_TSD_KEY_N };
1612
1613/* Auto-initialising subsystem. libc_specifics_inited is set
1614 after initialisation. libc_specifics_inited_mx guards it. */
1615static int libc_specifics_inited = 0;
1616static pthread_mutex_t libc_specifics_inited_mx = PTHREAD_MUTEX_INITIALIZER;
1617
sewardj00a66b12002-10-12 16:42:35 +00001618
sewardj5716dbb2002-04-26 03:28:18 +00001619/* These are the keys we must initialise the first time. */
sewardjcb7f08a2002-10-02 09:41:49 +00001620static pthread_key_t libc_specifics_keys[_LIBC_TSD_KEY_N];
sewardj5716dbb2002-04-26 03:28:18 +00001621
sewardj00a66b12002-10-12 16:42:35 +00001622
sewardjcb7f08a2002-10-02 09:41:49 +00001623/* Initialise the keys, if they are not already initialised. */
sewardj5716dbb2002-04-26 03:28:18 +00001624static
1625void init_libc_tsd_keys ( void )
1626{
1627 int res, i;
1628 pthread_key_t k;
1629
sewardj08c7f012002-10-07 23:56:55 +00001630 /* Don't fall into deadlock if we get called again whilst we still
1631 hold the lock, via the __uselocale() call herein. */
1632 if (libc_specifics_inited != 0)
1633 return;
1634
1635 /* Take the lock. */
sewardj00a66b12002-10-12 16:42:35 +00001636 res = __pthread_mutex_lock(&libc_specifics_inited_mx);
sewardj5716dbb2002-04-26 03:28:18 +00001637 if (res != 0) barf("init_libc_tsd_keys: lock");
1638
sewardj08c7f012002-10-07 23:56:55 +00001639 /* Now test again, to be sure there is no mistake. */
1640 if (libc_specifics_inited != 0) {
sewardj00a66b12002-10-12 16:42:35 +00001641 res = __pthread_mutex_unlock(&libc_specifics_inited_mx);
sewardj08c7f012002-10-07 23:56:55 +00001642 if (res != 0) barf("init_libc_tsd_keys: unlock(1)");
1643 return;
sewardj5716dbb2002-04-26 03:28:18 +00001644 }
1645
sewardj08c7f012002-10-07 23:56:55 +00001646 /* Actually do the initialisation. */
1647 /* printf("INIT libc specifics\n"); */
1648 for (i = 0; i < _LIBC_TSD_KEY_N; i++) {
sewardj00a66b12002-10-12 16:42:35 +00001649 res = __pthread_key_create(&k, NULL);
sewardj08c7f012002-10-07 23:56:55 +00001650 if (res != 0) barf("init_libc_tsd_keys: create");
1651 libc_specifics_keys[i] = k;
1652 }
1653
1654 /* Signify init done. */
1655 libc_specifics_inited = 1;
1656
1657# ifdef GLIBC_2_3
1658 /* Set the initialising thread's locale to the global (default)
sewardj00a66b12002-10-12 16:42:35 +00001659 locale. A hack in support of glibc-2.3. This does the biz for
1660 the root thread. For all other threads we run this in
1661 thread_wrapper(), which does the real work of
1662 pthread_create(). */
1663 /* assert that we are the root thread. I don't know if this is
1664 really a valid assertion to make; if it breaks I'll reconsider
1665 it. */
1666 my_assert(pthread_self() == 1);
sewardj08c7f012002-10-07 23:56:55 +00001667 __uselocale(LC_GLOBAL_LOCALE);
1668# endif
1669
1670 /* Unlock and return. */
sewardj00a66b12002-10-12 16:42:35 +00001671 res = __pthread_mutex_unlock(&libc_specifics_inited_mx);
sewardj5716dbb2002-04-26 03:28:18 +00001672 if (res != 0) barf("init_libc_tsd_keys: unlock");
1673}
1674
1675
1676static int
1677libc_internal_tsd_set ( enum __libc_tsd_key_t key,
1678 const void * pointer )
1679{
sewardjcb7f08a2002-10-02 09:41:49 +00001680 int res;
sewardj5716dbb2002-04-26 03:28:18 +00001681 /* printf("SET SET SET key %d ptr %p\n", key, pointer); */
sewardjcb7f08a2002-10-02 09:41:49 +00001682 if (key < _LIBC_TSD_KEY_MALLOC || key >= _LIBC_TSD_KEY_N)
sewardj5716dbb2002-04-26 03:28:18 +00001683 barf("libc_internal_tsd_set: invalid key");
1684 init_libc_tsd_keys();
sewardj00a66b12002-10-12 16:42:35 +00001685 res = __pthread_setspecific(libc_specifics_keys[key], pointer);
sewardj5716dbb2002-04-26 03:28:18 +00001686 if (res != 0) barf("libc_internal_tsd_set: setspecific failed");
1687 return 0;
1688}
1689
1690static void *
1691libc_internal_tsd_get ( enum __libc_tsd_key_t key )
1692{
sewardjcb7f08a2002-10-02 09:41:49 +00001693 void* v;
sewardj5716dbb2002-04-26 03:28:18 +00001694 /* printf("GET GET GET key %d\n", key); */
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_get: invalid key");
1697 init_libc_tsd_keys();
sewardj00a66b12002-10-12 16:42:35 +00001698 v = __pthread_getspecific(libc_specifics_keys[key]);
sewardj5716dbb2002-04-26 03:28:18 +00001699 /* if (v == NULL) barf("libc_internal_tsd_set: getspecific failed"); */
1700 return v;
1701}
1702
1703
sewardj70adeb22002-04-27 01:35:38 +00001704int (*__libc_internal_tsd_set)
1705 (enum __libc_tsd_key_t key, const void * pointer)
1706 = libc_internal_tsd_set;
sewardj5716dbb2002-04-26 03:28:18 +00001707
sewardj70adeb22002-04-27 01:35:38 +00001708void* (*__libc_internal_tsd_get)
1709 (enum __libc_tsd_key_t key)
1710 = libc_internal_tsd_get;
sewardj5716dbb2002-04-26 03:28:18 +00001711
1712
sewardj00a66b12002-10-12 16:42:35 +00001713#ifdef GLIBC_2_3
1714/* This one was first spotted be me in the glibc-2.2.93 sources. */
1715static void**
1716libc_internal_tsd_address ( enum __libc_tsd_key_t key )
1717{
1718 void** v;
1719 /* printf("ADDR ADDR ADDR key %d\n", key); */
1720 if (key < _LIBC_TSD_KEY_MALLOC || key >= _LIBC_TSD_KEY_N)
1721 barf("libc_internal_tsd_address: invalid key");
1722 init_libc_tsd_keys();
1723 v = __pthread_getspecific_addr(libc_specifics_keys[key]);
1724 return v;
1725}
1726
1727void ** (*__libc_internal_tsd_address)
1728 (enum __libc_tsd_key_t key)
1729 = libc_internal_tsd_address;
1730#endif
1731
1732
sewardje663cb92002-04-12 10:26:32 +00001733/* ---------------------------------------------------------------------
1734 These are here (I think) because they are deemed cancellation
1735 points by POSIX. For the moment we'll simply pass the call along
1736 to the corresponding thread-unaware (?) libc routine.
1737 ------------------------------------------------------------------ */
1738
sewardje663cb92002-04-12 10:26:32 +00001739#include <stdlib.h>
sewardje663cb92002-04-12 10:26:32 +00001740#include <sys/types.h>
1741#include <sys/socket.h>
1742
sewardjd529a442002-05-04 19:49:21 +00001743#ifdef GLIBC_2_1
1744extern
1745int __sigaction
1746 (int signum,
1747 const struct sigaction *act,
1748 struct sigaction *oldact);
1749#else
sewardje663cb92002-04-12 10:26:32 +00001750extern
1751int __libc_sigaction
1752 (int signum,
1753 const struct sigaction *act,
1754 struct sigaction *oldact);
sewardjd529a442002-05-04 19:49:21 +00001755#endif
sewardje663cb92002-04-12 10:26:32 +00001756int sigaction(int signum,
1757 const struct sigaction *act,
1758 struct sigaction *oldact)
1759{
sewardjd140e442002-05-29 01:21:19 +00001760 __my_pthread_testcancel();
sewardj2a1dcce2002-04-22 12:45:25 +00001761# ifdef GLIBC_2_1
1762 return __sigaction(signum, act, oldact);
1763# else
sewardj45b4b372002-04-16 22:50:32 +00001764 return __libc_sigaction(signum, act, oldact);
sewardj2a1dcce2002-04-22 12:45:25 +00001765# endif
sewardje663cb92002-04-12 10:26:32 +00001766}
1767
1768
1769extern
1770int __libc_connect(int sockfd,
1771 const struct sockaddr *serv_addr,
1772 socklen_t addrlen);
sewardj5905fae2002-04-26 13:25:00 +00001773__attribute__((weak))
sewardje663cb92002-04-12 10:26:32 +00001774int connect(int sockfd,
1775 const struct sockaddr *serv_addr,
1776 socklen_t addrlen)
1777{
sewardjd140e442002-05-29 01:21:19 +00001778 __my_pthread_testcancel();
sewardj45b4b372002-04-16 22:50:32 +00001779 return __libc_connect(sockfd, serv_addr, addrlen);
sewardje663cb92002-04-12 10:26:32 +00001780}
1781
1782
1783extern
1784int __libc_fcntl(int fd, int cmd, long arg);
sewardj5905fae2002-04-26 13:25:00 +00001785__attribute__((weak))
sewardje663cb92002-04-12 10:26:32 +00001786int fcntl(int fd, int cmd, long arg)
1787{
sewardjd140e442002-05-29 01:21:19 +00001788 __my_pthread_testcancel();
sewardj45b4b372002-04-16 22:50:32 +00001789 return __libc_fcntl(fd, cmd, arg);
sewardje663cb92002-04-12 10:26:32 +00001790}
1791
1792
1793extern
1794ssize_t __libc_write(int fd, const void *buf, size_t count);
sewardj5905fae2002-04-26 13:25:00 +00001795__attribute__((weak))
sewardje663cb92002-04-12 10:26:32 +00001796ssize_t write(int fd, const void *buf, size_t count)
1797{
sewardjd140e442002-05-29 01:21:19 +00001798 __my_pthread_testcancel();
sewardj45b4b372002-04-16 22:50:32 +00001799 return __libc_write(fd, buf, count);
sewardje663cb92002-04-12 10:26:32 +00001800}
1801
1802
1803extern
1804ssize_t __libc_read(int fd, void *buf, size_t count);
sewardj5905fae2002-04-26 13:25:00 +00001805__attribute__((weak))
sewardje663cb92002-04-12 10:26:32 +00001806ssize_t read(int fd, void *buf, size_t count)
1807{
sewardjd140e442002-05-29 01:21:19 +00001808 __my_pthread_testcancel();
sewardj45b4b372002-04-16 22:50:32 +00001809 return __libc_read(fd, buf, count);
sewardje663cb92002-04-12 10:26:32 +00001810}
1811
sewardjf912dfc2002-11-13 21:51:10 +00001812/*
1813 * Ugh, this is horrible but here goes:
1814 *
1815 * Open of a named pipe (fifo file) can block. In a threaded program,
1816 * this means that the whole thing can block. We therefore need to
1817 * make the open appear to block to the caller, but still keep polling
1818 * for everyone else.
1819 *
1820 * There are four cases:
1821 *
1822 * - the caller asked for O_NONBLOCK. The easy one: we just do it.
1823 *
1824 * - the caller asked for a blocking O_RDONLY open. We open it with
1825 * O_NONBLOCK and then use poll to wait for it to become ready.
1826 *
1827 * - the caller asked for a blocking O_WRONLY open. Unfortunately, this
1828 * will fail with ENXIO when we make it non-blocking. Doubly
1829 * unfortunate is that we can only rely on these semantics if it is
1830 * actually a fifo file; the hack is that if we see that it is a
1831 * O_WRONLY open and we get ENXIO, then stat the path and see if it
1832 * actually is a fifo. This is racy, but it is the best we can do.
1833 * If it is a fifo, then keep trying the open until it works; if not
1834 * just return the error.
1835 *
1836 * - the caller asked for a blocking O_RDWR open. Well, under Linux,
1837 * this never blocks, so we just clear the non-blocking flag and
1838 * return.
1839 *
1840 * This code assumes that for whatever we open, O_NONBLOCK followed by
1841 * a fcntl clearing O_NONBLOCK is the same as opening without
1842 * O_NONBLOCK. Also assumes that stat and fstat have no side-effects.
1843 *
1844 * XXX Should probably put in special cases for some devices as well,
1845 * like serial ports. Unfortunately they don't work like fifos, so
1846 * this logic will become even more tortured. Wait until we really
1847 * need it.
1848 */
1849static inline int _open(const char *pathname, int flags, mode_t mode,
1850 int (*openp)(const char *, int, mode_t))
sewardjbe32e452002-04-24 20:29:58 +00001851{
sewardjf912dfc2002-11-13 21:51:10 +00001852 int fd;
1853 struct stat st;
1854 struct vki_timespec nanosleep_interval;
1855 int saved_errno;
1856
sewardjd140e442002-05-29 01:21:19 +00001857 __my_pthread_testcancel();
sewardjf912dfc2002-11-13 21:51:10 +00001858
1859 /* Assume we can only get O_RDONLY, O_WRONLY or O_RDWR */
1860 my_assert((flags & VKI_O_ACCMODE) != VKI_O_ACCMODE);
1861
1862 for(;;) {
1863 fd = (*openp)(pathname, flags | VKI_O_NONBLOCK, mode);
1864
1865 /* return immediately if caller wanted nonblocking anyway */
1866 if (flags & VKI_O_NONBLOCK)
1867 return fd;
1868
1869 saved_errno = errno;
1870
1871 if (fd != -1)
1872 break; /* open worked */
1873
1874 /* If we got ENXIO and we're opening WRONLY, and it turns out
1875 to really be a FIFO, then poll waiting for open to succeed */
1876 if (errno == ENXIO &&
1877 (flags & VKI_O_ACCMODE) == VKI_O_WRONLY &&
1878 (stat(pathname, &st) == 0 && S_ISFIFO(st.st_mode))) {
1879
1880 /* OK, we're opening a FIFO for writing; sleep and spin */
1881 nanosleep_interval.tv_sec = 0;
1882 nanosleep_interval.tv_nsec = 13 * 1000 * 1000; /* 13 milliseconds */
1883 /* It's critical here that valgrind's nanosleep implementation
1884 is nonblocking. */
1885 (void)my_do_syscall2(__NR_nanosleep,
1886 (int)(&nanosleep_interval), (int)NULL);
1887 } else {
1888 /* it was just an error */
1889 errno = saved_errno;
1890 return -1;
1891 }
1892 }
1893
1894 /* OK, we've got a nonblocking FD for a caller who wants blocking;
1895 reset the flags to what they asked for */
1896 fcntl(fd, VKI_F_SETFL, flags);
1897
1898 /* Return now if one of:
1899 - we were opening O_RDWR (never blocks)
1900 - we opened with O_WRONLY (polling already done)
1901 - the thing we opened wasn't a FIFO after all (or fstat failed)
1902 */
1903 if ((flags & VKI_O_ACCMODE) != VKI_O_RDONLY ||
1904 (fstat(fd, &st) == -1 || !S_ISFIFO(st.st_mode))) {
1905 errno = saved_errno;
1906 return fd;
1907 }
1908
1909 /* OK, drop into the poll loop looking for something to read on the fd */
1910 my_assert((flags & VKI_O_ACCMODE) == VKI_O_RDONLY);
1911 for(;;) {
1912 struct pollfd pollfd;
1913 int res;
1914
1915 pollfd.fd = fd;
1916 pollfd.events = POLLIN;
1917 pollfd.revents = 0;
1918
1919 res = my_do_syscall3(__NR_poll, (int)&pollfd, 1, 0);
1920
1921 my_assert(res == 0 || res == 1);
1922
1923 if (res == 1) {
1924 /* OK, got it.
1925
1926 XXX This is wrong: we're waiting for either something to
1927 read or a HUP on the file descriptor, but the semantics of
1928 fifo open are that we should unblock as soon as someone
1929 simply opens the other end, not that they write something.
1930 With luck this won't matter in practice.
1931 */
1932 my_assert(pollfd.revents & (POLLIN|POLLHUP));
1933 break;
1934 }
1935
1936 /* Still nobody home; sleep and spin */
1937 nanosleep_interval.tv_sec = 0;
1938 nanosleep_interval.tv_nsec = 13 * 1000 * 1000; /* 13 milliseconds */
1939 /* It's critical here that valgrind's nanosleep implementation
1940 is nonblocking. */
1941 (void)my_do_syscall2(__NR_nanosleep,
1942 (int)(&nanosleep_interval), (int)NULL);
1943 }
1944
1945 errno = saved_errno;
1946 return fd;
sewardjbe32e452002-04-24 20:29:58 +00001947}
1948
sewardjf912dfc2002-11-13 21:51:10 +00001949extern
1950int __libc_open64(const char *pathname, int flags, mode_t mode);
1951/* __attribute__((weak)) */
1952int open64(const char *pathname, int flags, mode_t mode)
1953{
1954 return _open(pathname, flags, mode, __libc_open64);
1955}
sewardje663cb92002-04-12 10:26:32 +00001956
1957extern
sewardj853f55d2002-04-26 00:27:53 +00001958int __libc_open(const char *pathname, int flags, mode_t mode);
sewardjf912dfc2002-11-13 21:51:10 +00001959/* __attribute__((weak)) */
sewardj853f55d2002-04-26 00:27:53 +00001960int open(const char *pathname, int flags, mode_t mode)
sewardje663cb92002-04-12 10:26:32 +00001961{
sewardjf912dfc2002-11-13 21:51:10 +00001962 return _open(pathname, flags, mode, __libc_open);
sewardje663cb92002-04-12 10:26:32 +00001963}
1964
sewardje663cb92002-04-12 10:26:32 +00001965extern
1966int __libc_close(int fd);
sewardj5905fae2002-04-26 13:25:00 +00001967__attribute__((weak))
sewardje663cb92002-04-12 10:26:32 +00001968int close(int fd)
1969{
sewardjd140e442002-05-29 01:21:19 +00001970 __my_pthread_testcancel();
sewardj45b4b372002-04-16 22:50:32 +00001971 return __libc_close(fd);
sewardje663cb92002-04-12 10:26:32 +00001972}
1973
1974
1975extern
1976int __libc_accept(int s, struct sockaddr *addr, socklen_t *addrlen);
sewardjf220ccc2002-10-23 21:53:49 +00001977
1978int VGL_(accept)(int s, struct sockaddr *addr, socklen_t *addrlen)
sewardje663cb92002-04-12 10:26:32 +00001979{
sewardjd140e442002-05-29 01:21:19 +00001980 __my_pthread_testcancel();
sewardj705d3cb2002-05-23 13:13:12 +00001981 wait_for_fd_to_be_readable_or_erring(s);
sewardjd140e442002-05-29 01:21:19 +00001982 __my_pthread_testcancel();
sewardj45b4b372002-04-16 22:50:32 +00001983 return __libc_accept(s, addr, addrlen);
sewardje663cb92002-04-12 10:26:32 +00001984}
1985
sewardj0c573af92002-10-23 21:55:01 +00001986extern
1987int __libc_recv(int s, void *buf, size_t len, int flags);
1988
1989int VGL_(recv)(int s, void *buf, size_t len, int flags)
1990{
1991 __my_pthread_testcancel();
1992 wait_for_fd_to_be_readable_or_erring(s);
1993 __my_pthread_testcancel();
1994 return __libc_recv(s, buf, len, flags);
1995}
1996
sewardj2a68e7e2002-11-16 11:04:18 +00001997int VGL_(readv)(int fd, const struct iovec *iov, int count)
1998{
1999 __my_pthread_testcancel();
2000 wait_for_fd_to_be_readable_or_erring(fd);
2001 __my_pthread_testcancel();
2002 return my_do_syscall3(__NR_readv, fd, (unsigned)iov, count);
2003}
2004
2005int VGL_(writev)(int fd, struct iovec *iov, int count)
2006{
2007 __my_pthread_testcancel();
2008 wait_for_fd_to_be_writable_or_erring(fd);
2009 __my_pthread_testcancel();
2010 return my_do_syscall3(__NR_writev, fd, (unsigned)iov, count);
2011}
sewardje663cb92002-04-12 10:26:32 +00002012
2013extern
sewardje663cb92002-04-12 10:26:32 +00002014pid_t __libc_waitpid(pid_t pid, int *status, int options);
sewardj5905fae2002-04-26 13:25:00 +00002015__attribute__((weak))
sewardje663cb92002-04-12 10:26:32 +00002016pid_t waitpid(pid_t pid, int *status, int options)
2017{
sewardjd140e442002-05-29 01:21:19 +00002018 __my_pthread_testcancel();
sewardj45b4b372002-04-16 22:50:32 +00002019 return __libc_waitpid(pid, status, options);
sewardje663cb92002-04-12 10:26:32 +00002020}
2021
2022
2023extern
2024int __libc_nanosleep(const struct timespec *req, struct timespec *rem);
sewardj5905fae2002-04-26 13:25:00 +00002025__attribute__((weak))
sewardje663cb92002-04-12 10:26:32 +00002026int nanosleep(const struct timespec *req, struct timespec *rem)
2027{
sewardjd140e442002-05-29 01:21:19 +00002028 __my_pthread_testcancel();
sewardje663cb92002-04-12 10:26:32 +00002029 return __libc_nanosleep(req, rem);
2030}
2031
sewardjbe32e452002-04-24 20:29:58 +00002032
sewardje663cb92002-04-12 10:26:32 +00002033extern
2034int __libc_fsync(int fd);
sewardj5905fae2002-04-26 13:25:00 +00002035__attribute__((weak))
sewardje663cb92002-04-12 10:26:32 +00002036int fsync(int fd)
2037{
sewardjd140e442002-05-29 01:21:19 +00002038 __my_pthread_testcancel();
sewardj45b4b372002-04-16 22:50:32 +00002039 return __libc_fsync(fd);
sewardje663cb92002-04-12 10:26:32 +00002040}
2041
sewardjbe32e452002-04-24 20:29:58 +00002042
sewardj70c75362002-04-13 04:18:32 +00002043extern
2044off_t __libc_lseek(int fildes, off_t offset, int whence);
sewardj5905fae2002-04-26 13:25:00 +00002045__attribute__((weak))
sewardj70c75362002-04-13 04:18:32 +00002046off_t lseek(int fildes, off_t offset, int whence)
2047{
sewardjd140e442002-05-29 01:21:19 +00002048 __my_pthread_testcancel();
sewardj45b4b372002-04-16 22:50:32 +00002049 return __libc_lseek(fildes, offset, whence);
sewardj70c75362002-04-13 04:18:32 +00002050}
2051
sewardjbe32e452002-04-24 20:29:58 +00002052
2053extern
2054__off64_t __libc_lseek64(int fildes, __off64_t offset, int whence);
sewardj5905fae2002-04-26 13:25:00 +00002055__attribute__((weak))
sewardjbe32e452002-04-24 20:29:58 +00002056__off64_t lseek64(int fildes, __off64_t offset, int whence)
2057{
sewardjd140e442002-05-29 01:21:19 +00002058 __my_pthread_testcancel();
sewardjbe32e452002-04-24 20:29:58 +00002059 return __libc_lseek64(fildes, offset, whence);
2060}
2061
2062
sewardj726c4122002-05-16 23:39:10 +00002063extern
2064ssize_t __libc_pread64 (int __fd, void *__buf, size_t __nbytes,
2065 __off64_t __offset);
2066ssize_t __pread64 (int __fd, void *__buf, size_t __nbytes,
2067 __off64_t __offset)
2068{
sewardjd140e442002-05-29 01:21:19 +00002069 __my_pthread_testcancel();
sewardj726c4122002-05-16 23:39:10 +00002070 return __libc_pread64(__fd, __buf, __nbytes, __offset);
2071}
2072
2073
sewardja18e2102002-05-18 10:43:22 +00002074extern
2075ssize_t __libc_pwrite64 (int __fd, const void *__buf, size_t __nbytes,
2076 __off64_t __offset);
2077ssize_t __pwrite64 (int __fd, const void *__buf, size_t __nbytes,
2078 __off64_t __offset)
2079{
sewardjd140e442002-05-29 01:21:19 +00002080 __my_pthread_testcancel();
sewardja18e2102002-05-18 10:43:22 +00002081 return __libc_pwrite64(__fd, __buf, __nbytes, __offset);
2082}
2083
sewardj726c4122002-05-16 23:39:10 +00002084
sewardj39b93b12002-05-18 10:56:27 +00002085extern
2086ssize_t __libc_pwrite(int fd, const void *buf, size_t count, off_t offset);
2087__attribute__((weak))
2088ssize_t pwrite(int fd, const void *buf, size_t count, off_t offset)
2089{
sewardjd140e442002-05-29 01:21:19 +00002090 __my_pthread_testcancel();
sewardj39b93b12002-05-18 10:56:27 +00002091 return __libc_pwrite(fd, buf, count, offset);
2092}
2093
2094
2095extern
2096ssize_t __libc_pread(int fd, void *buf, size_t count, off_t offset);
2097__attribute__((weak))
2098ssize_t pread(int fd, void *buf, size_t count, off_t offset)
2099{
sewardjd140e442002-05-29 01:21:19 +00002100 __my_pthread_testcancel();
sewardj39b93b12002-05-18 10:56:27 +00002101 return __libc_pread(fd, buf, count, offset);
2102}
2103
2104
sewardj6af4b5d2002-04-16 04:40:49 +00002105extern
2106void __libc_longjmp(jmp_buf env, int val) __attribute((noreturn));
sewardj5905fae2002-04-26 13:25:00 +00002107/* not weak: __attribute__((weak)) */
sewardj6af4b5d2002-04-16 04:40:49 +00002108void longjmp(jmp_buf env, int val)
2109{
2110 __libc_longjmp(env, val);
2111}
2112
sewardjbe32e452002-04-24 20:29:58 +00002113
sewardj436c2db2002-06-18 09:07:54 +00002114extern void __libc_siglongjmp (sigjmp_buf env, int val)
2115 __attribute__ ((noreturn));
2116void siglongjmp(sigjmp_buf env, int val)
2117{
2118 kludged("siglongjmp (cleanup handlers are ignored)");
2119 __libc_siglongjmp(env, val);
2120}
2121
2122
sewardj6af4b5d2002-04-16 04:40:49 +00002123extern
2124int __libc_send(int s, const void *msg, size_t len, int flags);
sewardj5905fae2002-04-26 13:25:00 +00002125__attribute__((weak))
sewardj6af4b5d2002-04-16 04:40:49 +00002126int send(int s, const void *msg, size_t len, int flags)
2127{
sewardjd140e442002-05-29 01:21:19 +00002128 __my_pthread_testcancel();
sewardj6af4b5d2002-04-16 04:40:49 +00002129 return __libc_send(s, msg, len, flags);
2130}
2131
sewardjbe32e452002-04-24 20:29:58 +00002132
sewardj1e8cdc92002-04-18 11:37:52 +00002133extern
2134int __libc_recv(int s, void *buf, size_t len, int flags);
sewardj5905fae2002-04-26 13:25:00 +00002135__attribute__((weak))
sewardj1e8cdc92002-04-18 11:37:52 +00002136int recv(int s, void *buf, size_t len, int flags)
2137{
sewardjd140e442002-05-29 01:21:19 +00002138 __my_pthread_testcancel();
sewardj1d6b3a22002-06-20 07:58:33 +00002139 wait_for_fd_to_be_readable_or_erring(s);
2140 __my_pthread_testcancel();
sewardj1e8cdc92002-04-18 11:37:52 +00002141 return __libc_recv(s, buf, len, flags);
2142}
2143
sewardjbe32e452002-04-24 20:29:58 +00002144
sewardj3665ded2002-05-16 16:57:25 +00002145extern
2146int __libc_sendmsg(int s, const struct msghdr *msg, int flags);
2147__attribute__((weak))
2148int sendmsg(int s, const struct msghdr *msg, int flags)
2149{
sewardjd140e442002-05-29 01:21:19 +00002150 __my_pthread_testcancel();
sewardj3665ded2002-05-16 16:57:25 +00002151 return __libc_sendmsg(s, msg, flags);
2152}
2153
2154
sewardj796d6a22002-04-24 02:28:34 +00002155extern
sewardj59da27a2002-06-06 08:33:54 +00002156int __libc_recvmsg(int s, struct msghdr *msg, int flags);
2157__attribute__((weak))
2158int recvmsg(int s, struct msghdr *msg, int flags)
2159{
2160 __my_pthread_testcancel();
2161 return __libc_recvmsg(s, msg, flags);
2162}
2163
2164
2165extern
sewardj436e0582002-04-26 14:31:40 +00002166int __libc_recvfrom(int s, void *buf, size_t len, int flags,
2167 struct sockaddr *from, socklen_t *fromlen);
2168__attribute__((weak))
2169int recvfrom(int s, void *buf, size_t len, int flags,
2170 struct sockaddr *from, socklen_t *fromlen)
2171{
sewardjd140e442002-05-29 01:21:19 +00002172 __my_pthread_testcancel();
sewardj2e207632002-06-13 17:29:53 +00002173 wait_for_fd_to_be_readable_or_erring(s);
2174 __my_pthread_testcancel();
sewardj436e0582002-04-26 14:31:40 +00002175 return __libc_recvfrom(s, buf, len, flags, from, fromlen);
2176}
2177
2178
2179extern
sewardj796d6a22002-04-24 02:28:34 +00002180int __libc_sendto(int s, const void *msg, size_t len, int flags,
2181 const struct sockaddr *to, socklen_t tolen);
sewardj5905fae2002-04-26 13:25:00 +00002182__attribute__((weak))
sewardj796d6a22002-04-24 02:28:34 +00002183int sendto(int s, const void *msg, size_t len, int flags,
2184 const struct sockaddr *to, socklen_t tolen)
2185{
sewardjd140e442002-05-29 01:21:19 +00002186 __my_pthread_testcancel();
sewardj796d6a22002-04-24 02:28:34 +00002187 return __libc_sendto(s, msg, len, flags, to, tolen);
2188}
2189
sewardjbe32e452002-04-24 20:29:58 +00002190
sewardj369b1702002-04-24 13:28:15 +00002191extern
2192int __libc_system(const char* str);
sewardj5905fae2002-04-26 13:25:00 +00002193__attribute__((weak))
sewardj369b1702002-04-24 13:28:15 +00002194int system(const char* str)
2195{
sewardjd140e442002-05-29 01:21:19 +00002196 __my_pthread_testcancel();
sewardj369b1702002-04-24 13:28:15 +00002197 return __libc_system(str);
2198}
2199
sewardjbe32e452002-04-24 20:29:58 +00002200
sewardjab0b1c32002-04-24 19:26:47 +00002201extern
2202pid_t __libc_wait(int *status);
sewardj5905fae2002-04-26 13:25:00 +00002203__attribute__((weak))
sewardjab0b1c32002-04-24 19:26:47 +00002204pid_t wait(int *status)
2205{
sewardjd140e442002-05-29 01:21:19 +00002206 __my_pthread_testcancel();
sewardjab0b1c32002-04-24 19:26:47 +00002207 return __libc_wait(status);
2208}
2209
sewardj45b4b372002-04-16 22:50:32 +00002210
sewardj67f1d582002-05-24 02:11:32 +00002211extern
2212int __libc_msync(const void *start, size_t length, int flags);
2213__attribute__((weak))
2214int msync(const void *start, size_t length, int flags)
2215{
sewardjd140e442002-05-29 01:21:19 +00002216 __my_pthread_testcancel();
sewardj67f1d582002-05-24 02:11:32 +00002217 return __libc_msync(start, length, flags);
2218}
2219
sewardj5905fae2002-04-26 13:25:00 +00002220
sewardj2cb00342002-06-28 01:46:26 +00002221/*--- fork and its helper ---*/
2222
2223static
2224void run_fork_handlers ( int what )
2225{
2226 ForkHandlerEntry entry;
2227 int n_h, n_handlers, i, res;
2228
2229 my_assert(what == 0 || what == 1 || what == 2);
2230
2231 /* Fetch old counter */
2232 VALGRIND_MAGIC_SEQUENCE(n_handlers, -2 /* default */,
2233 VG_USERREQ__GET_FHSTACK_USED,
2234 0, 0, 0, 0);
2235 my_assert(n_handlers >= 0 && n_handlers < VG_N_FORKHANDLERSTACK);
2236
2237 /* Prepare handlers (what == 0) are called in opposite order of
2238 calls to pthread_atfork. Parent and child handlers are called
2239 in the same order as calls to pthread_atfork. */
2240 if (what == 0)
2241 n_h = n_handlers - 1;
2242 else
2243 n_h = 0;
2244
2245 for (i = 0; i < n_handlers; i++) {
2246 VALGRIND_MAGIC_SEQUENCE(res, -2 /* default */,
2247 VG_USERREQ__GET_FHSTACK_ENTRY,
2248 n_h, &entry, 0, 0);
2249 my_assert(res == 0);
2250 switch (what) {
2251 case 0: if (entry.prepare) entry.prepare();
2252 n_h--; break;
2253 case 1: if (entry.parent) entry.parent();
2254 n_h++; break;
2255 case 2: if (entry.child) entry.child();
2256 n_h++; break;
2257 default: barf("run_fork_handlers: invalid what");
2258 }
2259 }
2260
2261 if (what != 0 /* prepare */) {
2262 /* Empty out the stack. */
2263 VALGRIND_MAGIC_SEQUENCE(res, -2 /* default */,
2264 VG_USERREQ__SET_FHSTACK_USED,
2265 0, 0, 0, 0);
2266 my_assert(res == 0);
2267 }
2268}
2269
2270extern
2271pid_t __libc_fork(void);
2272pid_t __fork(void)
2273{
2274 pid_t pid;
2275 __my_pthread_testcancel();
2276 __pthread_mutex_lock(&pthread_atfork_lock);
2277
2278 run_fork_handlers(0 /* prepare */);
2279 pid = __libc_fork();
2280 if (pid == 0) {
2281 /* I am the child */
2282 run_fork_handlers(2 /* child */);
sewardjd8acdf22002-11-13 21:57:52 +00002283 __pthread_mutex_unlock(&pthread_atfork_lock);
sewardj2cb00342002-06-28 01:46:26 +00002284 __pthread_mutex_init(&pthread_atfork_lock, NULL);
2285 } else {
2286 /* I am the parent */
2287 run_fork_handlers(1 /* parent */);
2288 __pthread_mutex_unlock(&pthread_atfork_lock);
2289 }
2290 return pid;
2291}
2292
2293
njn25e49d8e72002-09-23 09:36:25 +00002294pid_t __vfork(void)
2295{
2296 return __fork();
2297}
sewardj2cb00342002-06-28 01:46:26 +00002298
2299
sewardj3b13f0e2002-04-25 20:17:29 +00002300/* ---------------------------------------------------------------------
2301 Nonblocking implementations of select() and poll(). This stuff will
2302 surely rot your mind.
2303 ------------------------------------------------------------------ */
sewardje663cb92002-04-12 10:26:32 +00002304
sewardj08a4c3f2002-04-13 03:45:44 +00002305/*--------------------------------------------------*/
2306
2307#include "vg_kerneliface.h"
2308
2309static
2310__inline__
2311int is_kerror ( int res )
2312{
2313 if (res >= -4095 && res <= -1)
2314 return 1;
2315 else
2316 return 0;
2317}
2318
2319
2320static
2321int my_do_syscall1 ( int syscallno, int arg1 )
2322{
2323 int __res;
2324 __asm__ volatile ("pushl %%ebx; movl %%edx,%%ebx ; int $0x80 ; popl %%ebx"
2325 : "=a" (__res)
2326 : "0" (syscallno),
2327 "d" (arg1) );
2328 return __res;
2329}
2330
2331static
2332int my_do_syscall2 ( int syscallno,
sewardjf854f472002-04-21 12:19:41 +00002333 int arg1, int arg2 )
sewardj08a4c3f2002-04-13 03:45:44 +00002334{
2335 int __res;
2336 __asm__ volatile ("pushl %%ebx; movl %%edx,%%ebx ; int $0x80 ; popl %%ebx"
2337 : "=a" (__res)
2338 : "0" (syscallno),
2339 "d" (arg1),
2340 "c" (arg2) );
2341 return __res;
2342}
2343
2344static
sewardjf854f472002-04-21 12:19:41 +00002345int my_do_syscall3 ( int syscallno,
2346 int arg1, int arg2, int arg3 )
2347{
2348 int __res;
2349 __asm__ volatile ("pushl %%ebx; movl %%esi,%%ebx ; int $0x80 ; popl %%ebx"
2350 : "=a" (__res)
2351 : "0" (syscallno),
2352 "S" (arg1),
2353 "c" (arg2),
2354 "d" (arg3) );
2355 return __res;
2356}
2357
sewardjd5bef572002-10-23 21:49:33 +00002358static inline
2359int my_do_syscall5 ( int syscallno,
2360 int arg1, int arg2, int arg3, int arg4, int arg5 )
2361{
2362 int __res;
2363 __asm__ volatile ("int $0x80"
2364 : "=a" (__res)
2365 : "0" (syscallno),
2366 "b" (arg1),
2367 "c" (arg2),
2368 "d" (arg3),
2369 "S" (arg4),
2370 "D" (arg5));
2371 return __res;
2372}
2373
sewardjf854f472002-04-21 12:19:41 +00002374static
sewardj08a4c3f2002-04-13 03:45:44 +00002375int do_syscall_select( int n,
2376 vki_fd_set* readfds,
2377 vki_fd_set* writefds,
2378 vki_fd_set* exceptfds,
2379 struct vki_timeval * timeout )
2380{
2381 int res;
2382 int args[5];
2383 args[0] = n;
2384 args[1] = (int)readfds;
2385 args[2] = (int)writefds;
2386 args[3] = (int)exceptfds;
2387 args[4] = (int)timeout;
2388 res = my_do_syscall1(__NR_select, (int)(&(args[0])) );
sewardj02535bc2002-04-21 01:08:26 +00002389 return res;
sewardj08a4c3f2002-04-13 03:45:44 +00002390}
2391
2392
2393/* This is a wrapper round select(), which makes it thread-safe,
2394 meaning that only this thread will block, rather than the entire
2395 process. This wrapper in turn depends on nanosleep() not to block
2396 the entire process, but I think (hope? suspect?) that POSIX
2397 pthreads guarantees that to be the case.
2398
2399 Basic idea is: modify the timeout parameter to select so that it
2400 returns immediately. Poll like this until select returns non-zero,
2401 indicating something interesting happened, or until our time is up.
njn25e49d8e72002-09-23 09:36:25 +00002402 Space out the polls with nanosleeps of say 11 milliseconds, which
sewardj08a4c3f2002-04-13 03:45:44 +00002403 is required to be nonblocking; this allows other threads to run.
sewardj02535bc2002-04-21 01:08:26 +00002404
2405 Assumes:
sewardj2d94c112002-06-03 01:25:54 +00002406 * (checked via my_assert) types fd_set and vki_fd_set are identical.
2407 * (checked via my_assert) types timeval and vki_timeval are identical.
sewardj02535bc2002-04-21 01:08:26 +00002408 * (unchecked) libc error numbers (EINTR etc) are the negation of the
2409 kernel's error numbers (VKI_EINTR etc).
sewardj08a4c3f2002-04-13 03:45:44 +00002410*/
sewardj08a4c3f2002-04-13 03:45:44 +00002411
sewardj7db011a2002-11-13 22:00:20 +00002412int VGL_(select) ( int n,
2413 fd_set *rfds,
2414 fd_set *wfds,
2415 fd_set *xfds,
2416 struct timeval *timeout )
sewardj08a4c3f2002-04-13 03:45:44 +00002417{
sewardj5f07b662002-04-23 16:52:51 +00002418 unsigned int ms_now, ms_end;
sewardj08a4c3f2002-04-13 03:45:44 +00002419 int res;
2420 fd_set rfds_copy;
2421 fd_set wfds_copy;
2422 fd_set xfds_copy;
2423 struct vki_timeval t_now;
sewardj08a4c3f2002-04-13 03:45:44 +00002424 struct vki_timeval zero_timeout;
2425 struct vki_timespec nanosleep_interval;
2426
sewardjd140e442002-05-29 01:21:19 +00002427 __my_pthread_testcancel();
2428
sewardj5f07b662002-04-23 16:52:51 +00002429 /* gcc's complains about ms_end being used uninitialised -- classic
2430 case it can't understand, where ms_end is both defined and used
2431 only if timeout != NULL. Hence ... */
2432 ms_end = 0;
sewardj08a4c3f2002-04-13 03:45:44 +00002433
2434 /* We assume that the kernel and libc data layouts are identical
2435 for the following types. These asserts provide a crude
2436 check. */
2437 if (sizeof(fd_set) != sizeof(vki_fd_set)
2438 || sizeof(struct timeval) != sizeof(struct vki_timeval))
2439 barf("valgrind's hacky non-blocking select(): data sizes error");
2440
sewardj5f07b662002-04-23 16:52:51 +00002441 /* Detect the current time and simultaneously find out if we are
2442 running on Valgrind. */
2443 VALGRIND_MAGIC_SEQUENCE(ms_now, 0xFFFFFFFF /* default */,
2444 VG_USERREQ__READ_MILLISECOND_TIMER,
2445 0, 0, 0, 0);
2446
2447 /* If a zero timeout specified, this call is harmless. Also go
2448 this route if we're not running on Valgrind, for whatever
2449 reason. */
2450 if ( (timeout && timeout->tv_sec == 0 && timeout->tv_usec == 0)
2451 || (ms_now == 0xFFFFFFFF) ) {
sewardj02535bc2002-04-21 01:08:26 +00002452 res = do_syscall_select( n, (vki_fd_set*)rfds,
sewardj08a4c3f2002-04-13 03:45:44 +00002453 (vki_fd_set*)wfds,
2454 (vki_fd_set*)xfds,
2455 (struct vki_timeval*)timeout);
sewardj02535bc2002-04-21 01:08:26 +00002456 if (is_kerror(res)) {
2457 * (__errno_location()) = -res;
2458 return -1;
2459 } else {
2460 return res;
2461 }
2462 }
sewardj08a4c3f2002-04-13 03:45:44 +00002463
sewardj5f07b662002-04-23 16:52:51 +00002464 /* If a timeout was specified, set ms_end to be the end millisecond
2465 counter [wallclock] time. */
sewardj08a4c3f2002-04-13 03:45:44 +00002466 if (timeout) {
2467 res = my_do_syscall2(__NR_gettimeofday, (int)&t_now, (int)NULL);
sewardj2d94c112002-06-03 01:25:54 +00002468 my_assert(res == 0);
sewardj5f07b662002-04-23 16:52:51 +00002469 ms_end = ms_now;
2470 ms_end += (timeout->tv_usec / 1000);
2471 ms_end += (timeout->tv_sec * 1000);
sewardj08a4c3f2002-04-13 03:45:44 +00002472 /* Stay sane ... */
sewardj2d94c112002-06-03 01:25:54 +00002473 my_assert (ms_end >= ms_now);
sewardj08a4c3f2002-04-13 03:45:44 +00002474 }
2475
2476 /* fprintf(stderr, "MY_SELECT: before loop\n"); */
2477
2478 /* Either timeout == NULL, meaning wait indefinitely, or timeout !=
sewardj5f07b662002-04-23 16:52:51 +00002479 NULL, in which case ms_end holds the end time. */
sewardj05bb2c92002-06-26 00:47:17 +00002480
sewardj08a4c3f2002-04-13 03:45:44 +00002481 while (1) {
sewardj05bb2c92002-06-26 00:47:17 +00002482
2483 /* First, do a return-immediately select(). */
sewardj08a4c3f2002-04-13 03:45:44 +00002484
2485 /* These could be trashed each time round the loop, so restore
2486 them each time. */
2487 if (rfds) rfds_copy = *rfds;
2488 if (wfds) wfds_copy = *wfds;
2489 if (xfds) xfds_copy = *xfds;
2490
2491 zero_timeout.tv_sec = zero_timeout.tv_usec = 0;
2492
2493 res = do_syscall_select( n,
2494 rfds ? (vki_fd_set*)(&rfds_copy) : NULL,
2495 wfds ? (vki_fd_set*)(&wfds_copy) : NULL,
2496 xfds ? (vki_fd_set*)(&xfds_copy) : NULL,
2497 & zero_timeout );
sewardj02535bc2002-04-21 01:08:26 +00002498 if (is_kerror(res)) {
2499 /* Some kind of error (including EINTR). Set errno and
sewardj08a4c3f2002-04-13 03:45:44 +00002500 return. The sets are unspecified in this case. */
sewardj02535bc2002-04-21 01:08:26 +00002501 * (__errno_location()) = -res;
2502 return -1;
sewardj08a4c3f2002-04-13 03:45:44 +00002503 }
2504 if (res > 0) {
2505 /* one or more fds is ready. Copy out resulting sets and
2506 return. */
2507 if (rfds) *rfds = rfds_copy;
2508 if (wfds) *wfds = wfds_copy;
2509 if (xfds) *xfds = xfds_copy;
2510 return res;
2511 }
sewardj05bb2c92002-06-26 00:47:17 +00002512
2513 /* Nothing interesting happened, so we go to sleep for a
2514 while. */
2515
sewardj08a4c3f2002-04-13 03:45:44 +00002516 /* fprintf(stderr, "MY_SELECT: nanosleep\n"); */
2517 /* nanosleep and go round again */
sewardj02535bc2002-04-21 01:08:26 +00002518 nanosleep_interval.tv_sec = 0;
njn25e49d8e72002-09-23 09:36:25 +00002519 nanosleep_interval.tv_nsec = 11 * 1000 * 1000; /* 11 milliseconds */
sewardjf854f472002-04-21 12:19:41 +00002520 /* It's critical here that valgrind's nanosleep implementation
2521 is nonblocking. */
sewardj645030e2002-06-06 01:27:39 +00002522 res = my_do_syscall2(__NR_nanosleep,
sewardjf854f472002-04-21 12:19:41 +00002523 (int)(&nanosleep_interval), (int)NULL);
sewardj645030e2002-06-06 01:27:39 +00002524 if (res == -VKI_EINTR) {
2525 /* The nanosleep was interrupted by a signal. So we do the
2526 same. */
2527 * (__errno_location()) = EINTR;
2528 return -1;
2529 }
sewardj05bb2c92002-06-26 00:47:17 +00002530
2531 /* Sleeping finished. If a finite timeout, check to see if it
2532 has expired yet. */
2533 if (timeout) {
2534 VALGRIND_MAGIC_SEQUENCE(ms_now, 0xFFFFFFFF /* default */,
2535 VG_USERREQ__READ_MILLISECOND_TIMER,
2536 0, 0, 0, 0);
2537 my_assert(ms_now != 0xFFFFFFFF);
2538 if (ms_now >= ms_end) {
2539 /* timeout; nothing interesting happened. */
2540 if (rfds) FD_ZERO(rfds);
2541 if (wfds) FD_ZERO(wfds);
2542 if (xfds) FD_ZERO(xfds);
2543 return 0;
2544 }
2545 }
2546
sewardjf854f472002-04-21 12:19:41 +00002547 }
2548}
2549
2550
2551
2552
2553#include <sys/poll.h>
2554
sewardj3e909ce2002-06-03 13:27:15 +00002555#ifndef HAVE_NFDS_T
sewardj72d58482002-04-24 02:20:20 +00002556typedef unsigned long int nfds_t;
2557#endif
2558
sewardj705d3cb2002-05-23 13:13:12 +00002559
sewardj7db011a2002-11-13 22:00:20 +00002560int VGL_(poll) (struct pollfd *__fds, nfds_t __nfds, int __timeout)
sewardjf854f472002-04-21 12:19:41 +00002561{
sewardj5f07b662002-04-23 16:52:51 +00002562 unsigned int ms_now, ms_end;
sewardjf854f472002-04-21 12:19:41 +00002563 int res, i;
sewardjf854f472002-04-21 12:19:41 +00002564 struct vki_timespec nanosleep_interval;
2565
sewardjd140e442002-05-29 01:21:19 +00002566 __my_pthread_testcancel();
sewardjf854f472002-04-21 12:19:41 +00002567 ensure_valgrind("poll");
2568
sewardj5f07b662002-04-23 16:52:51 +00002569 /* Detect the current time and simultaneously find out if we are
2570 running on Valgrind. */
2571 VALGRIND_MAGIC_SEQUENCE(ms_now, 0xFFFFFFFF /* default */,
2572 VG_USERREQ__READ_MILLISECOND_TIMER,
2573 0, 0, 0, 0);
2574
sewardjf854f472002-04-21 12:19:41 +00002575 if (/* CHECK SIZES FOR struct pollfd */
2576 sizeof(struct timeval) != sizeof(struct vki_timeval))
2577 barf("valgrind's hacky non-blocking poll(): data sizes error");
2578
sewardj5f07b662002-04-23 16:52:51 +00002579 /* dummy initialisation to keep gcc -Wall happy */
2580 ms_end = 0;
2581
2582 /* If a zero timeout specified, this call is harmless. Also do
2583 this if not running on Valgrind. */
2584 if (__timeout == 0 || ms_now == 0xFFFFFFFF) {
sewardjf854f472002-04-21 12:19:41 +00002585 res = my_do_syscall3(__NR_poll, (int)__fds, __nfds, __timeout);
2586 if (is_kerror(res)) {
2587 * (__errno_location()) = -res;
2588 return -1;
2589 } else {
2590 return res;
2591 }
2592 }
2593
sewardj5f07b662002-04-23 16:52:51 +00002594 /* If a timeout was specified, set ms_end to be the end wallclock
2595 time. Easy considering that __timeout is in milliseconds. */
sewardjf854f472002-04-21 12:19:41 +00002596 if (__timeout > 0) {
sewardj650ac002002-04-29 12:20:34 +00002597 ms_end = ms_now + (unsigned int)__timeout;
sewardjf854f472002-04-21 12:19:41 +00002598 }
2599
2600 /* fprintf(stderr, "MY_POLL: before loop\n"); */
2601
2602 /* Either timeout < 0, meaning wait indefinitely, or timeout > 0,
2603 in which case t_end holds the end time. */
sewardj05bb2c92002-06-26 00:47:17 +00002604
sewardj2d94c112002-06-03 01:25:54 +00002605 my_assert(__timeout != 0);
sewardj5f07b662002-04-23 16:52:51 +00002606
sewardjf854f472002-04-21 12:19:41 +00002607 while (1) {
sewardj05bb2c92002-06-26 00:47:17 +00002608
2609 /* Do a return-immediately poll. */
2610
2611 res = my_do_syscall3(__NR_poll, (int)__fds, __nfds, 0 );
2612 if (is_kerror(res)) {
2613 /* Some kind of error. Set errno and return. */
2614 * (__errno_location()) = -res;
2615 return -1;
2616 }
2617 if (res > 0) {
2618 /* One or more fds is ready. Return now. */
2619 return res;
2620 }
2621
2622 /* Nothing interesting happened, so we go to sleep for a
2623 while. */
2624
2625 /* fprintf(stderr, "MY_POLL: nanosleep\n"); */
2626 /* nanosleep and go round again */
2627 nanosleep_interval.tv_sec = 0;
njn25e49d8e72002-09-23 09:36:25 +00002628 nanosleep_interval.tv_nsec = 13 * 1000 * 1000; /* 13 milliseconds */
sewardj05bb2c92002-06-26 00:47:17 +00002629 /* It's critical here that valgrind's nanosleep implementation
2630 is nonblocking. */
2631 (void)my_do_syscall2(__NR_nanosleep,
2632 (int)(&nanosleep_interval), (int)NULL);
2633
2634 /* Sleeping finished. If a finite timeout, check to see if it
2635 has expired yet. */
sewardjf854f472002-04-21 12:19:41 +00002636 if (__timeout > 0) {
sewardj5f07b662002-04-23 16:52:51 +00002637 VALGRIND_MAGIC_SEQUENCE(ms_now, 0xFFFFFFFF /* default */,
2638 VG_USERREQ__READ_MILLISECOND_TIMER,
2639 0, 0, 0, 0);
sewardj2d94c112002-06-03 01:25:54 +00002640 my_assert(ms_now != 0xFFFFFFFF);
sewardj5f07b662002-04-23 16:52:51 +00002641 if (ms_now >= ms_end) {
sewardjf854f472002-04-21 12:19:41 +00002642 /* timeout; nothing interesting happened. */
2643 for (i = 0; i < __nfds; i++)
2644 __fds[i].revents = 0;
2645 return 0;
2646 }
2647 }
2648
sewardj08a4c3f2002-04-13 03:45:44 +00002649 }
2650}
sewardj3b13f0e2002-04-25 20:17:29 +00002651
2652
sewardj705d3cb2002-05-23 13:13:12 +00002653/* Helper function used to make accept() non-blocking. Idea is to use
2654 the above nonblocking poll() to make this thread ONLY wait for the
2655 specified fd to become ready, and then return. */
sewardjd1c1cf22002-06-26 00:13:36 +00002656
2657/* Sigh -- a hack. We're not supposed to include this file directly;
2658 should do it via /usr/include/fcntl.h, but that introduces a
2659 varargs prototype for fcntl itself, which we can't mimic. */
2660#define _FCNTL_H
2661#include <bits/fcntl.h>
2662
sewardj705d3cb2002-05-23 13:13:12 +00002663static void wait_for_fd_to_be_readable_or_erring ( int fd )
2664{
2665 struct pollfd pfd;
sewardjd1c1cf22002-06-26 00:13:36 +00002666 int res;
2667
sewardj6e6cbaa2002-05-24 02:12:52 +00002668 /* fprintf(stderr, "wait_for_fd_to_be_readable_or_erring %d\n", fd); */
sewardjd1c1cf22002-06-26 00:13:36 +00002669
2670 /* First check to see if the fd is nonblocking, and/or invalid. In
2671 either case return immediately. */
2672 res = __libc_fcntl(fd, F_GETFL, 0);
2673 if (res == -1) return; /* fd is invalid somehow */
2674 if (res & O_NONBLOCK) return; /* fd is nonblocking */
2675
2676 /* Ok, we'd better wait with poll. */
sewardj705d3cb2002-05-23 13:13:12 +00002677 pfd.fd = fd;
2678 pfd.events = POLLIN | POLLPRI | POLLERR | POLLHUP | POLLNVAL;
2679 /* ... but not POLLOUT, you may notice. */
2680 pfd.revents = 0;
2681 (void)poll(&pfd, 1, -1 /* forever */);
2682}
2683
sewardj2a68e7e2002-11-16 11:04:18 +00002684static void wait_for_fd_to_be_writable_or_erring ( int fd )
2685{
2686 struct pollfd pfd;
2687 int res;
2688
2689 /* fprintf(stderr, "wait_for_fd_to_be_readable_or_erring %d\n", fd); */
2690
2691 /* First check to see if the fd is nonblocking, and/or invalid. In
2692 either case return immediately. */
2693 res = __libc_fcntl(fd, F_GETFL, 0);
2694 if (res == -1) return; /* fd is invalid somehow */
2695 if (res & O_NONBLOCK) return; /* fd is nonblocking */
2696
2697 /* Ok, we'd better wait with poll. */
2698 pfd.fd = fd;
2699 pfd.events = POLLOUT | POLLERR | POLLHUP | POLLNVAL;
2700 pfd.revents = 0;
2701 (void)poll(&pfd, 1, -1 /* forever */);
2702}
sewardj705d3cb2002-05-23 13:13:12 +00002703
sewardj3b13f0e2002-04-25 20:17:29 +00002704/* ---------------------------------------------------------------------
sewardj8f253ff2002-05-19 00:13:34 +00002705 Hacky implementation of semaphores.
2706 ------------------------------------------------------------------ */
2707
2708#include <semaphore.h>
2709
2710/* This is a terrible way to do the remapping. Plan is to import an
2711 AVL tree at some point. */
sewardj8f253ff2002-05-19 00:13:34 +00002712
2713typedef
2714 struct {
2715 pthread_mutex_t se_mx;
2716 pthread_cond_t se_cv;
2717 int count;
2718 }
2719 vg_sem_t;
2720
2721static pthread_mutex_t se_remap_mx = PTHREAD_MUTEX_INITIALIZER;
2722
2723static int se_remap_used = 0;
2724static sem_t* se_remap_orig[VG_N_SEMAPHORES];
2725static vg_sem_t se_remap_new[VG_N_SEMAPHORES];
2726
2727static vg_sem_t* se_remap ( sem_t* orig )
2728{
2729 int res, i;
2730 res = __pthread_mutex_lock(&se_remap_mx);
sewardj2d94c112002-06-03 01:25:54 +00002731 my_assert(res == 0);
sewardj8f253ff2002-05-19 00:13:34 +00002732
2733 for (i = 0; i < se_remap_used; i++) {
2734 if (se_remap_orig[i] == orig)
2735 break;
2736 }
2737 if (i == se_remap_used) {
2738 if (se_remap_used == VG_N_SEMAPHORES) {
2739 res = pthread_mutex_unlock(&se_remap_mx);
sewardj2d94c112002-06-03 01:25:54 +00002740 my_assert(res == 0);
sewardja1ac5cb2002-05-27 13:00:05 +00002741 barf("VG_N_SEMAPHORES is too low. Increase and recompile.");
sewardj8f253ff2002-05-19 00:13:34 +00002742 }
2743 se_remap_used++;
2744 se_remap_orig[i] = orig;
2745 /* printf("allocated semaphore %d\n", i); */
2746 }
2747 res = __pthread_mutex_unlock(&se_remap_mx);
sewardj2d94c112002-06-03 01:25:54 +00002748 my_assert(res == 0);
sewardj8f253ff2002-05-19 00:13:34 +00002749 return &se_remap_new[i];
2750}
2751
2752
2753int sem_init(sem_t *sem, int pshared, unsigned int value)
2754{
2755 int res;
2756 vg_sem_t* vg_sem;
2757 ensure_valgrind("sem_init");
2758 if (pshared != 0) {
sewardj4dced352002-06-04 22:54:20 +00002759 pthread_error("sem_init: unsupported pshared value");
sewardj8f253ff2002-05-19 00:13:34 +00002760 errno = ENOSYS;
2761 return -1;
2762 }
2763 vg_sem = se_remap(sem);
2764 res = pthread_mutex_init(&vg_sem->se_mx, NULL);
sewardj2d94c112002-06-03 01:25:54 +00002765 my_assert(res == 0);
sewardj8f253ff2002-05-19 00:13:34 +00002766 res = pthread_cond_init(&vg_sem->se_cv, NULL);
sewardj2d94c112002-06-03 01:25:54 +00002767 my_assert(res == 0);
sewardj8f253ff2002-05-19 00:13:34 +00002768 vg_sem->count = value;
2769 return 0;
2770}
2771
2772
2773int sem_wait ( sem_t* sem )
2774{
2775 int res;
2776 vg_sem_t* vg_sem;
2777 ensure_valgrind("sem_wait");
2778 vg_sem = se_remap(sem);
2779 res = __pthread_mutex_lock(&vg_sem->se_mx);
sewardj2d94c112002-06-03 01:25:54 +00002780 my_assert(res == 0);
sewardj8f253ff2002-05-19 00:13:34 +00002781 while (vg_sem->count == 0) {
2782 res = pthread_cond_wait(&vg_sem->se_cv, &vg_sem->se_mx);
sewardj2d94c112002-06-03 01:25:54 +00002783 my_assert(res == 0);
sewardj8f253ff2002-05-19 00:13:34 +00002784 }
2785 vg_sem->count--;
2786 res = __pthread_mutex_unlock(&vg_sem->se_mx);
sewardj2d94c112002-06-03 01:25:54 +00002787 my_assert(res == 0);
sewardj8f253ff2002-05-19 00:13:34 +00002788 return 0;
2789}
2790
2791int sem_post ( sem_t* sem )
2792{
2793 int res;
2794 vg_sem_t* vg_sem;
2795 ensure_valgrind("sem_post");
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 if (vg_sem->count == 0) {
2800 vg_sem->count++;
2801 res = pthread_cond_broadcast(&vg_sem->se_cv);
sewardj2d94c112002-06-03 01:25:54 +00002802 my_assert(res == 0);
sewardj8f253ff2002-05-19 00:13:34 +00002803 } else {
2804 vg_sem->count++;
2805 }
2806 res = __pthread_mutex_unlock(&vg_sem->se_mx);
sewardj2d94c112002-06-03 01:25:54 +00002807 my_assert(res == 0);
sewardj8f253ff2002-05-19 00:13:34 +00002808 return 0;
2809}
2810
2811
2812int sem_trywait ( sem_t* sem )
2813{
2814 int ret, res;
2815 vg_sem_t* vg_sem;
2816 ensure_valgrind("sem_trywait");
2817 vg_sem = se_remap(sem);
2818 res = __pthread_mutex_lock(&vg_sem->se_mx);
sewardj2d94c112002-06-03 01:25:54 +00002819 my_assert(res == 0);
sewardj8f253ff2002-05-19 00:13:34 +00002820 if (vg_sem->count > 0) {
2821 vg_sem->count--;
2822 ret = 0;
2823 } else {
2824 ret = -1;
2825 errno = EAGAIN;
2826 }
2827 res = __pthread_mutex_unlock(&vg_sem->se_mx);
sewardj2d94c112002-06-03 01:25:54 +00002828 my_assert(res == 0);
sewardj8f253ff2002-05-19 00:13:34 +00002829 return ret;
2830}
2831
2832
2833int sem_getvalue(sem_t* sem, int * sval)
2834{
2835 vg_sem_t* vg_sem;
2836 ensure_valgrind("sem_trywait");
2837 vg_sem = se_remap(sem);
2838 *sval = vg_sem->count;
2839 return 0;
2840}
2841
2842
2843int sem_destroy(sem_t * sem)
2844{
2845 kludged("sem_destroy");
2846 /* if someone waiting on this semaphore, errno = EBUSY, return -1 */
2847 return 0;
2848}
2849
sewardj9ad92d92002-10-16 19:45:06 +00002850
2851int sem_timedwait(sem_t* sem, const struct timespec *abstime)
2852{
2853 int res;
2854 vg_sem_t* vg_sem;
2855 ensure_valgrind("sem_timedwait");
2856 vg_sem = se_remap(sem);
2857 res = __pthread_mutex_lock(&vg_sem->se_mx);
2858 my_assert(res == 0);
2859 while ( vg_sem->count == 0 && res != ETIMEDOUT ) {
2860 res = pthread_cond_timedwait(&vg_sem->se_cv, &vg_sem->se_mx, abstime);
2861 }
2862 if ( vg_sem->count > 0 ) {
2863 vg_sem->count--;
2864 res = __pthread_mutex_unlock(&vg_sem->se_mx);
2865 my_assert(res == 0 );
2866 return 0;
2867 } else {
2868 res = __pthread_mutex_unlock(&vg_sem->se_mx);
2869 my_assert(res == 0 );
2870 *(__errno_location()) = ETIMEDOUT;
2871 return -1;
2872 }
2873}
2874
sewardj8f253ff2002-05-19 00:13:34 +00002875
2876/* ---------------------------------------------------------------------
sewardj2d8b3f02002-06-01 14:14:19 +00002877 Reader-writer locks.
sewardja1ac5cb2002-05-27 13:00:05 +00002878 ------------------------------------------------------------------ */
2879
sewardj2d8b3f02002-06-01 14:14:19 +00002880typedef
2881 struct {
2882 int initted; /* != 0 --> in use; sanity check only */
2883 int prefer_w; /* != 0 --> prefer writer */
2884 int nwait_r; /* # of waiting readers */
2885 int nwait_w; /* # of waiting writers */
2886 pthread_cond_t cv_r; /* for signalling readers */
2887 pthread_cond_t cv_w; /* for signalling writers */
2888 pthread_mutex_t mx;
2889 int status;
2890 /* allowed range for status: >= -1. -1 means 1 writer currently
2891 active, >= 0 means N readers currently active. */
2892 }
2893 vg_rwlock_t;
sewardja1ac5cb2002-05-27 13:00:05 +00002894
2895
2896static pthread_mutex_t rw_remap_mx = PTHREAD_MUTEX_INITIALIZER;
2897
2898static int rw_remap_used = 0;
2899static pthread_rwlock_t* rw_remap_orig[VG_N_RWLOCKS];
2900static vg_rwlock_t rw_remap_new[VG_N_RWLOCKS];
2901
sewardj2d8b3f02002-06-01 14:14:19 +00002902
2903static
2904void init_vg_rwlock ( vg_rwlock_t* vg_rwl )
2905{
2906 int res = 0;
2907 vg_rwl->initted = 1;
2908 vg_rwl->prefer_w = 1;
2909 vg_rwl->nwait_r = 0;
2910 vg_rwl->nwait_w = 0;
2911 vg_rwl->status = 0;
2912 res = pthread_mutex_init(&vg_rwl->mx, NULL);
2913 res |= pthread_cond_init(&vg_rwl->cv_r, NULL);
2914 res |= pthread_cond_init(&vg_rwl->cv_w, NULL);
sewardj2d94c112002-06-03 01:25:54 +00002915 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002916}
2917
2918
sewardja1ac5cb2002-05-27 13:00:05 +00002919/* Take the address of a LinuxThreads rwlock_t and return the shadow
2920 address of our version. Further, if the LinuxThreads version
2921 appears to have been statically initialised, do the same to the one
2922 we allocate here. The pthread_rwlock_t.__rw_readers field is set
2923 to zero by PTHREAD_RWLOCK_INITIALIZER, so we take zero as meaning
2924 uninitialised and non-zero meaning initialised.
2925*/
2926static vg_rwlock_t* rw_remap ( pthread_rwlock_t* orig )
2927{
2928 int res, i;
2929 vg_rwlock_t* vg_rwl;
2930 res = __pthread_mutex_lock(&rw_remap_mx);
sewardj2d94c112002-06-03 01:25:54 +00002931 my_assert(res == 0);
sewardja1ac5cb2002-05-27 13:00:05 +00002932
2933 for (i = 0; i < rw_remap_used; i++) {
2934 if (rw_remap_orig[i] == orig)
2935 break;
2936 }
2937 if (i == rw_remap_used) {
2938 if (rw_remap_used == VG_N_RWLOCKS) {
sewardj2d8b3f02002-06-01 14:14:19 +00002939 res = __pthread_mutex_unlock(&rw_remap_mx);
sewardj2d94c112002-06-03 01:25:54 +00002940 my_assert(res == 0);
sewardja1ac5cb2002-05-27 13:00:05 +00002941 barf("VG_N_RWLOCKS is too low. Increase and recompile.");
2942 }
2943 rw_remap_used++;
2944 rw_remap_orig[i] = orig;
sewardj2d8b3f02002-06-01 14:14:19 +00002945 rw_remap_new[i].initted = 0;
sewardja1ac5cb2002-05-27 13:00:05 +00002946 if (0) printf("allocated rwlock %d\n", i);
2947 }
2948 res = __pthread_mutex_unlock(&rw_remap_mx);
sewardj2d94c112002-06-03 01:25:54 +00002949 my_assert(res == 0);
sewardja1ac5cb2002-05-27 13:00:05 +00002950 vg_rwl = &rw_remap_new[i];
2951
sewardj2d8b3f02002-06-01 14:14:19 +00002952 /* Initialise the shadow, if required. */
sewardja1ac5cb2002-05-27 13:00:05 +00002953 if (orig->__rw_readers == 0) {
sewardja1ac5cb2002-05-27 13:00:05 +00002954 orig->__rw_readers = 1;
sewardj2d8b3f02002-06-01 14:14:19 +00002955 init_vg_rwlock(vg_rwl);
sewardja1ac5cb2002-05-27 13:00:05 +00002956 if (orig->__rw_kind == PTHREAD_RWLOCK_PREFER_READER_NP)
sewardj2d8b3f02002-06-01 14:14:19 +00002957 vg_rwl->prefer_w = 0;
sewardja1ac5cb2002-05-27 13:00:05 +00002958 }
2959
2960 return vg_rwl;
2961}
2962
2963
sewardja1ac5cb2002-05-27 13:00:05 +00002964int pthread_rwlock_init ( pthread_rwlock_t* orig,
2965 const pthread_rwlockattr_t* attr )
2966{
sewardja1ac5cb2002-05-27 13:00:05 +00002967 vg_rwlock_t* rwl;
2968 if (0) printf ("pthread_rwlock_init\n");
2969 /* Force the remapper to initialise the shadow. */
2970 orig->__rw_readers = 0;
2971 /* Install the lock preference; the remapper needs to know it. */
2972 orig->__rw_kind = PTHREAD_RWLOCK_DEFAULT_NP;
2973 if (attr)
2974 orig->__rw_kind = attr->__lockkind;
2975 rwl = rw_remap ( orig );
sewardj2d8b3f02002-06-01 14:14:19 +00002976 return 0;
sewardja1ac5cb2002-05-27 13:00:05 +00002977}
2978
sewardj2d8b3f02002-06-01 14:14:19 +00002979
2980static
2981void pthread_rwlock_rdlock_CANCEL_HDLR ( void* rwl_v )
sewardja1ac5cb2002-05-27 13:00:05 +00002982{
sewardj2d8b3f02002-06-01 14:14:19 +00002983 vg_rwlock_t* rwl = (vg_rwlock_t*)rwl_v;
2984 rwl->nwait_r--;
2985 pthread_mutex_unlock (&rwl->mx);
sewardja1ac5cb2002-05-27 13:00:05 +00002986}
2987
sewardj2d8b3f02002-06-01 14:14:19 +00002988
sewardja1ac5cb2002-05-27 13:00:05 +00002989int pthread_rwlock_rdlock ( pthread_rwlock_t* orig )
2990{
2991 int res;
2992 vg_rwlock_t* rwl;
2993 if (0) printf ("pthread_rwlock_rdlock\n");
2994 rwl = rw_remap ( orig );
sewardj2d8b3f02002-06-01 14:14:19 +00002995 res = __pthread_mutex_lock(&rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00002996 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002997 if (!rwl->initted) {
2998 res = __pthread_mutex_unlock(&rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00002999 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00003000 return EINVAL;
3001 }
3002 if (rwl->status < 0) {
sewardj2d94c112002-06-03 01:25:54 +00003003 my_assert(rwl->status == -1);
sewardj2d8b3f02002-06-01 14:14:19 +00003004 rwl->nwait_r++;
3005 pthread_cleanup_push( pthread_rwlock_rdlock_CANCEL_HDLR, rwl );
3006 while (1) {
3007 if (rwl->status == 0) break;
3008 res = pthread_cond_wait(&rwl->cv_r, &rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00003009 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00003010 }
3011 pthread_cleanup_pop(0);
3012 rwl->nwait_r--;
3013 }
sewardj2d94c112002-06-03 01:25:54 +00003014 my_assert(rwl->status >= 0);
sewardj2d8b3f02002-06-01 14:14:19 +00003015 rwl->status++;
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 0;
sewardja1ac5cb2002-05-27 13:00:05 +00003019}
3020
sewardj2d8b3f02002-06-01 14:14:19 +00003021
sewardja1ac5cb2002-05-27 13:00:05 +00003022int pthread_rwlock_tryrdlock ( pthread_rwlock_t* orig )
3023{
3024 int res;
3025 vg_rwlock_t* rwl;
3026 if (0) printf ("pthread_rwlock_tryrdlock\n");
3027 rwl = rw_remap ( orig );
sewardj2d8b3f02002-06-01 14:14:19 +00003028 res = __pthread_mutex_lock(&rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00003029 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00003030 if (!rwl->initted) {
3031 res = __pthread_mutex_unlock(&rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00003032 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00003033 return EINVAL;
3034 }
3035 if (rwl->status == -1) {
3036 /* Writer active; we have to give up. */
3037 res = __pthread_mutex_unlock(&rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00003038 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00003039 return EBUSY;
3040 }
3041 /* Success */
sewardj2d94c112002-06-03 01:25:54 +00003042 my_assert(rwl->status >= 0);
sewardj2d8b3f02002-06-01 14:14:19 +00003043 rwl->status++;
3044 res = __pthread_mutex_unlock(&rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00003045 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00003046 return 0;
sewardja1ac5cb2002-05-27 13:00:05 +00003047}
3048
sewardj2d8b3f02002-06-01 14:14:19 +00003049
3050static
3051void pthread_rwlock_wrlock_CANCEL_HDLR ( void* rwl_v )
3052{
3053 vg_rwlock_t* rwl = (vg_rwlock_t*)rwl_v;
3054 rwl->nwait_w--;
3055 pthread_mutex_unlock (&rwl->mx);
3056}
3057
3058
sewardja1ac5cb2002-05-27 13:00:05 +00003059int pthread_rwlock_wrlock ( pthread_rwlock_t* orig )
3060{
3061 int res;
3062 vg_rwlock_t* rwl;
3063 if (0) printf ("pthread_rwlock_wrlock\n");
3064 rwl = rw_remap ( orig );
sewardj2d8b3f02002-06-01 14:14:19 +00003065 res = __pthread_mutex_lock(&rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00003066 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00003067 if (!rwl->initted) {
3068 res = __pthread_mutex_unlock(&rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00003069 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00003070 return EINVAL;
3071 }
3072 if (rwl->status != 0) {
3073 rwl->nwait_w++;
3074 pthread_cleanup_push( pthread_rwlock_wrlock_CANCEL_HDLR, rwl );
3075 while (1) {
3076 if (rwl->status == 0) break;
3077 res = pthread_cond_wait(&rwl->cv_w, &rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00003078 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00003079 }
3080 pthread_cleanup_pop(0);
3081 rwl->nwait_w--;
3082 }
sewardj2d94c112002-06-03 01:25:54 +00003083 my_assert(rwl->status == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00003084 rwl->status = -1;
3085 res = __pthread_mutex_unlock(&rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00003086 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00003087 return 0;
sewardja1ac5cb2002-05-27 13:00:05 +00003088}
3089
sewardj2d8b3f02002-06-01 14:14:19 +00003090
sewardja1ac5cb2002-05-27 13:00:05 +00003091int pthread_rwlock_trywrlock ( pthread_rwlock_t* orig )
3092{
3093 int res;
3094 vg_rwlock_t* rwl;
sewardj2d8b3f02002-06-01 14:14:19 +00003095 if (0) printf ("pthread_wrlock_trywrlock\n");
sewardja1ac5cb2002-05-27 13:00:05 +00003096 rwl = rw_remap ( orig );
sewardj2d8b3f02002-06-01 14:14:19 +00003097 res = __pthread_mutex_lock(&rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00003098 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00003099 if (!rwl->initted) {
3100 res = __pthread_mutex_unlock(&rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00003101 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00003102 return EINVAL;
3103 }
3104 if (rwl->status != 0) {
3105 /* Reader(s) or a writer active; we have to give up. */
3106 res = __pthread_mutex_unlock(&rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00003107 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00003108 return EBUSY;
3109 }
3110 /* Success */
sewardj2d94c112002-06-03 01:25:54 +00003111 my_assert(rwl->status == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00003112 rwl->status = -1;
3113 res = __pthread_mutex_unlock(&rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00003114 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00003115 return 0;
sewardja1ac5cb2002-05-27 13:00:05 +00003116}
3117
sewardj2d8b3f02002-06-01 14:14:19 +00003118
sewardja1ac5cb2002-05-27 13:00:05 +00003119int pthread_rwlock_unlock ( pthread_rwlock_t* orig )
3120{
3121 int res;
3122 vg_rwlock_t* rwl;
3123 if (0) printf ("pthread_rwlock_unlock\n");
3124 rwl = rw_remap ( orig );
sewardj2d8b3f02002-06-01 14:14:19 +00003125 rwl = rw_remap ( orig );
3126 res = __pthread_mutex_lock(&rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00003127 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00003128 if (!rwl->initted) {
3129 res = __pthread_mutex_unlock(&rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00003130 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00003131 return EINVAL;
3132 }
3133 if (rwl->status == 0) {
3134 res = __pthread_mutex_unlock(&rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00003135 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00003136 return EPERM;
3137 }
sewardj2d94c112002-06-03 01:25:54 +00003138 my_assert(rwl->status != 0);
sewardj2d8b3f02002-06-01 14:14:19 +00003139 if (rwl->status == -1) {
3140 rwl->status = 0;
3141 } else {
sewardj2d94c112002-06-03 01:25:54 +00003142 my_assert(rwl->status > 0);
sewardj2d8b3f02002-06-01 14:14:19 +00003143 rwl->status--;
3144 }
3145
sewardj2d94c112002-06-03 01:25:54 +00003146 my_assert(rwl->status >= 0);
sewardj2d8b3f02002-06-01 14:14:19 +00003147
3148 if (rwl->prefer_w) {
3149
3150 /* Favour waiting writers, if any. */
3151 if (rwl->nwait_w > 0) {
3152 /* Writer(s) are waiting. */
3153 if (rwl->status == 0) {
3154 /* We can let a writer in. */
3155 res = pthread_cond_signal(&rwl->cv_w);
sewardj2d94c112002-06-03 01:25:54 +00003156 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00003157 } else {
3158 /* There are still readers active. Do nothing; eventually
3159 they will disappear, at which point a writer will be
3160 admitted. */
3161 }
3162 }
3163 else
3164 /* No waiting writers. */
3165 if (rwl->nwait_r > 0) {
3166 /* Let in a waiting reader. */
3167 res = pthread_cond_signal(&rwl->cv_r);
sewardj2d94c112002-06-03 01:25:54 +00003168 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00003169 }
3170
3171 } else {
3172
3173 /* Favour waiting readers, if any. */
3174 if (rwl->nwait_r > 0) {
3175 /* Reader(s) are waiting; let one in. */
3176 res = pthread_cond_signal(&rwl->cv_r);
sewardj2d94c112002-06-03 01:25:54 +00003177 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00003178 }
3179 else
3180 /* No waiting readers. */
3181 if (rwl->nwait_w > 0 && rwl->status == 0) {
3182 /* We have waiting writers and no active readers; let a
3183 writer in. */
3184 res = pthread_cond_signal(&rwl->cv_w);
sewardj2d94c112002-06-03 01:25:54 +00003185 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00003186 }
3187 }
3188
3189 res = __pthread_mutex_unlock(&rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00003190 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00003191 return 0;
3192}
3193
3194
3195int pthread_rwlock_destroy ( pthread_rwlock_t *orig )
3196{
3197 int res;
3198 vg_rwlock_t* rwl;
3199 if (0) printf ("pthread_rwlock_destroy\n");
3200 rwl = rw_remap ( orig );
3201 res = __pthread_mutex_lock(&rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00003202 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00003203 if (!rwl->initted) {
3204 res = __pthread_mutex_unlock(&rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00003205 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00003206 return EINVAL;
3207 }
3208 if (rwl->status != 0 || rwl->nwait_r > 0 || rwl->nwait_w > 0) {
3209 res = __pthread_mutex_unlock(&rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00003210 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00003211 return EBUSY;
3212 }
3213 rwl->initted = 0;
3214 res = __pthread_mutex_unlock(&rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00003215 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00003216 return 0;
sewardja1ac5cb2002-05-27 13:00:05 +00003217}
3218
3219
sewardj47e4e312002-06-18 09:24:34 +00003220/* Copied directly from LinuxThreads. */
3221int
3222pthread_rwlockattr_init (pthread_rwlockattr_t *attr)
3223{
3224 attr->__lockkind = 0;
3225 attr->__pshared = PTHREAD_PROCESS_PRIVATE;
3226
3227 return 0;
3228}
3229
sewardjfe18eb82002-07-13 12:58:44 +00003230/* Copied directly from LinuxThreads. */
3231int
3232pthread_rwlockattr_setpshared (pthread_rwlockattr_t *attr, int pshared)
3233{
3234 if (pshared != PTHREAD_PROCESS_PRIVATE && pshared != PTHREAD_PROCESS_SHARED)
3235 return EINVAL;
3236
3237 /* For now it is not possible to shared a conditional variable. */
3238 if (pshared != PTHREAD_PROCESS_PRIVATE)
3239 return ENOSYS;
3240
3241 attr->__pshared = pshared;
3242
3243 return 0;
3244}
3245
sewardj47e4e312002-06-18 09:24:34 +00003246
sewardja1ac5cb2002-05-27 13:00:05 +00003247/* ---------------------------------------------------------------------
sewardjd5bef572002-10-23 21:49:33 +00003248 Make SYSV IPC not block everything
3249 ------------------------------------------------------------------ */
3250
3251#include <sys/ipc.h>
3252#include <sys/msg.h>
3253#include <asm/ipc.h> /* for ipc_kludge */
3254
3255static inline int sys_ipc(unsigned call, int first, int second, int third, void *ptr)
3256{
3257 return my_do_syscall5(__NR_ipc, call, first, second, third, (int)ptr);
3258}
3259
3260/* Turn a blocking msgsnd() into a polling non-blocking one, so that
3261 other threads make progress */
sewardjf220ccc2002-10-23 21:53:49 +00003262int VGL_(msgsnd)(int msgid, const void *msgp, size_t msgsz, int msgflg)
sewardjd5bef572002-10-23 21:49:33 +00003263{
3264 struct vki_timespec nanosleep_interval;
3265 int err;
3266
3267 ensure_valgrind("msgsnd");
3268
3269 nanosleep_interval.tv_sec = 0;
3270 nanosleep_interval.tv_nsec = 13 * 1000 * 1000; /* 13 milliseconds */
3271
3272 if (msgflg & IPC_NOWAIT) {
3273 /* If we aren't blocking anyway, just do it */
3274 err = sys_ipc(11, msgid, msgsz, msgflg, (void *)msgp);
3275 } else {
3276 /* Otherwise poll on the queue to let other things run */
3277 for(;;) {
3278 err = sys_ipc(11, msgid, msgsz, msgflg | IPC_NOWAIT, (void *)msgp);
3279
3280 if (err != -EAGAIN)
3281 break;
3282
3283 (void)my_do_syscall2(__NR_nanosleep,
3284 (int)(&nanosleep_interval), (int)NULL);
3285 }
3286 }
3287
3288 if (is_kerror(err)) {
3289 *(__errno_location()) = -err;
3290 return -1;
3291 }
3292 return 0;
3293}
3294
3295/* Turn a blocking msgrcv() into a polling non-blocking one, so that
3296 other threads make progress */
sewardjf220ccc2002-10-23 21:53:49 +00003297int VGL_(msgrcv)( int msqid, void *msgp, size_t msgsz, long msgtyp, int msgflg )
sewardjd5bef572002-10-23 21:49:33 +00003298{
3299 struct vki_timespec nanosleep_interval;
3300 int err;
3301 struct ipc_kludge tmp;
3302
3303 ensure_valgrind("msgrcv");
3304
3305 nanosleep_interval.tv_sec = 0;
3306 nanosleep_interval.tv_nsec = 13 * 1000 * 1000; /* 13 milliseconds */
3307
3308 tmp.msgp = msgp;
3309 tmp.msgtyp = msgtyp;
3310
3311 if (msgflg & IPC_NOWAIT) {
3312 /* If we aren't blocking anyway, just do it */
3313 err = sys_ipc(12, msqid, msgsz, msgflg, &tmp );
3314 } else {
3315 /* Otherwise poll on the queue to let other things run */
3316 for(;;) {
3317 err = sys_ipc(12, msqid, msgsz, msgflg | IPC_NOWAIT, &tmp );
3318
3319 if (err != -ENOMSG)
3320 break;
3321
3322 (void)my_do_syscall2(__NR_nanosleep,
3323 (int)(&nanosleep_interval), (int)NULL);
3324 }
3325 }
3326
3327 if (is_kerror(err)) {
3328 *(__errno_location()) = -err;
3329 return -1;
3330 }
3331
3332 return 0;
3333}
3334
3335
3336
3337/* ---------------------------------------------------------------------
sewardj3b13f0e2002-04-25 20:17:29 +00003338 B'stard.
3339 ------------------------------------------------------------------ */
3340
3341# define strong_alias(name, aliasname) \
3342 extern __typeof (name) aliasname __attribute__ ((alias (#name)));
3343
sewardj5905fae2002-04-26 13:25:00 +00003344# define weak_alias(name, aliasname) \
3345 extern __typeof (name) aliasname __attribute__ ((weak, alias (#name)));
sewardj3b13f0e2002-04-25 20:17:29 +00003346
sewardj5905fae2002-04-26 13:25:00 +00003347strong_alias(__pthread_mutex_lock, pthread_mutex_lock)
3348strong_alias(__pthread_mutex_trylock, pthread_mutex_trylock)
3349strong_alias(__pthread_mutex_unlock, pthread_mutex_unlock)
3350strong_alias(__pthread_mutexattr_init, pthread_mutexattr_init)
3351 weak_alias(__pthread_mutexattr_settype, pthread_mutexattr_settype)
3352strong_alias(__pthread_mutex_init, pthread_mutex_init)
3353strong_alias(__pthread_mutexattr_destroy, pthread_mutexattr_destroy)
3354strong_alias(__pthread_mutex_destroy, pthread_mutex_destroy)
3355strong_alias(__pthread_once, pthread_once)
3356strong_alias(__pthread_atfork, pthread_atfork)
3357strong_alias(__pthread_key_create, pthread_key_create)
3358strong_alias(__pthread_getspecific, pthread_getspecific)
3359strong_alias(__pthread_setspecific, pthread_setspecific)
3360
sewardjd529a442002-05-04 19:49:21 +00003361#ifndef GLIBC_2_1
sewardj3b13f0e2002-04-25 20:17:29 +00003362strong_alias(sigaction, __sigaction)
sewardjd529a442002-05-04 19:49:21 +00003363#endif
3364
sewardj5905fae2002-04-26 13:25:00 +00003365strong_alias(close, __close)
sewardj3b13f0e2002-04-25 20:17:29 +00003366strong_alias(fcntl, __fcntl)
sewardj5905fae2002-04-26 13:25:00 +00003367strong_alias(lseek, __lseek)
3368strong_alias(open, __open)
3369strong_alias(open64, __open64)
sewardj5905fae2002-04-26 13:25:00 +00003370strong_alias(read, __read)
3371strong_alias(wait, __wait)
3372strong_alias(write, __write)
sewardj3b13f0e2002-04-25 20:17:29 +00003373strong_alias(connect, __connect)
sewardj5905fae2002-04-26 13:25:00 +00003374strong_alias(send, __send)
3375
sewardj726c4122002-05-16 23:39:10 +00003376weak_alias (__pread64, pread64)
sewardja18e2102002-05-18 10:43:22 +00003377weak_alias (__pwrite64, pwrite64)
sewardj5905fae2002-04-26 13:25:00 +00003378weak_alias(__fork, fork)
njn25e49d8e72002-09-23 09:36:25 +00003379weak_alias(__vfork, vfork)
sewardj7f6456d2002-05-21 00:51:21 +00003380
sewardjf0b06452002-06-04 08:38:04 +00003381weak_alias (__pthread_kill_other_threads_np, pthread_kill_other_threads_np)
sewardj3b13f0e2002-04-25 20:17:29 +00003382
3383/*--------------------------------------------------*/
3384
sewardj5905fae2002-04-26 13:25:00 +00003385weak_alias(pthread_rwlock_rdlock, __pthread_rwlock_rdlock)
sewardj5905fae2002-04-26 13:25:00 +00003386weak_alias(pthread_rwlock_unlock, __pthread_rwlock_unlock)
sewardj262b0292002-05-01 00:03:16 +00003387weak_alias(pthread_rwlock_wrlock, __pthread_rwlock_wrlock)
sewardj060b04f2002-04-26 21:01:13 +00003388
sewardja1ac5cb2002-05-27 13:00:05 +00003389weak_alias(pthread_rwlock_destroy, __pthread_rwlock_destroy)
3390weak_alias(pthread_rwlock_init, __pthread_rwlock_init)
3391weak_alias(pthread_rwlock_tryrdlock, __pthread_rwlock_tryrdlock)
3392weak_alias(pthread_rwlock_trywrlock, __pthread_rwlock_trywrlock)
3393
sewardj060b04f2002-04-26 21:01:13 +00003394
sewardj3b13f0e2002-04-25 20:17:29 +00003395/* I've no idea what these are, but they get called quite a lot.
3396 Anybody know? */
3397
3398#undef _IO_flockfile
3399void _IO_flockfile ( _IO_FILE * file )
3400{
sewardj853f55d2002-04-26 00:27:53 +00003401 pthread_mutex_lock(file->_lock);
sewardj3b13f0e2002-04-25 20:17:29 +00003402}
sewardj5905fae2002-04-26 13:25:00 +00003403weak_alias(_IO_flockfile, flockfile);
3404
sewardj3b13f0e2002-04-25 20:17:29 +00003405
3406#undef _IO_funlockfile
3407void _IO_funlockfile ( _IO_FILE * file )
3408{
sewardj853f55d2002-04-26 00:27:53 +00003409 pthread_mutex_unlock(file->_lock);
sewardj3b13f0e2002-04-25 20:17:29 +00003410}
sewardj5905fae2002-04-26 13:25:00 +00003411weak_alias(_IO_funlockfile, funlockfile);
3412
sewardj3b13f0e2002-04-25 20:17:29 +00003413
sewardjd4f2c712002-04-30 10:20:10 +00003414/* This doesn't seem to be needed to simulate libpthread.so's external
3415 interface, but many people complain about its absence. */
3416
3417strong_alias(__pthread_mutexattr_settype, __pthread_mutexattr_setkind_np)
3418weak_alias(__pthread_mutexattr_setkind_np, pthread_mutexattr_setkind_np)
sewardj439d45e2002-05-03 20:43:10 +00003419
3420
3421/*--------------------------------------------------------------------*/
3422/*--- end vg_libpthread.c ---*/
3423/*--------------------------------------------------------------------*/