blob: 2a9350be3ecbdeea601e374a7651b4e46998b543 [file] [log] [blame]
sewardje663cb92002-04-12 10:26:32 +00001
sewardj439d45e2002-05-03 20:43:10 +00002/*--------------------------------------------------------------------*/
3/*--- A replacement for the standard libpthread.so. ---*/
4/*--- vg_libpthread.c ---*/
5/*--------------------------------------------------------------------*/
6
7/*
njnc9539842002-10-02 13:26:35 +00008 This file is part of Valgrind, an extensible x86 protected-mode
9 emulator for monitoring program execution on x86-Unixes.
sewardj439d45e2002-05-03 20:43:10 +000010
11 Copyright (C) 2000-2002 Julian Seward
12 jseward@acm.org
13
14 This program is free software; you can redistribute it and/or
15 modify it under the terms of the GNU General Public License as
16 published by the Free Software Foundation; either version 2 of the
17 License, or (at your option) any later version.
18
19 This program is distributed in the hope that it will be useful, but
20 WITHOUT ANY WARRANTY; without even the implied warranty of
21 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
22 General Public License for more details.
23
24 You should have received a copy of the GNU General Public License
25 along with this program; if not, write to the Free Software
26 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
27 02111-1307, USA.
28
njn25e49d8e72002-09-23 09:36:25 +000029 The GNU General Public License is contained in the file COPYING.
sewardj439d45e2002-05-03 20:43:10 +000030*/
31
32/* ALL THIS CODE RUNS ON THE SIMULATED CPU.
33
34 This is a replacement for the standard libpthread.so. It is loaded
sewardje663cb92002-04-12 10:26:32 +000035 as part of the client's image (if required) and directs pthread
36 calls through to Valgrind's request mechanism.
37
38 A couple of caveats.
39
40 1. Since it's a binary-compatible replacement for an existing library,
41 we must take care to used exactly the same data layouts, etc, as
42 the standard pthread.so does.
43
44 2. Since this runs as part of the client, there are no specific
45 restrictions on what headers etc we can include, so long as
46 this libpthread.so does not end up having dependencies on .so's
47 which the real one doesn't.
48
49 Later ... it appears we cannot call file-related stuff in libc here,
50 perhaps fair enough. Be careful what you call from here. Even exit()
51 doesn't work (gives infinite recursion and then stack overflow); hence
52 myexit(). Also fprintf doesn't seem safe.
53*/
54
55#include "valgrind.h" /* For the request-passing mechanism */
56#include "vg_include.h" /* For the VG_USERREQ__* constants */
57
sewardja1ac5cb2002-05-27 13:00:05 +000058#define __USE_UNIX98
59#include <sys/types.h>
60#include <pthread.h>
61#undef __USE_UNIX98
62
sewardje663cb92002-04-12 10:26:32 +000063#include <unistd.h>
64#include <string.h>
sewardj2a1dcce2002-04-22 12:45:25 +000065#ifdef GLIBC_2_1
66#include <sys/time.h>
67#endif
sewardjf912dfc2002-11-13 21:51:10 +000068#include <sys/stat.h>
69#include <sys/poll.h>
sewardj2d94c112002-06-03 01:25:54 +000070#include <stdio.h>
71
sewardj705d3cb2002-05-23 13:13:12 +000072
73/* ---------------------------------------------------------------------
74 Forwardses.
75 ------------------------------------------------------------------ */
76
77static void wait_for_fd_to_be_readable_or_erring ( int fd );
sewardj12a0e042002-11-30 14:02:53 +000078static void wait_for_fd_to_be_writable_or_erring ( int fd );
sewardj705d3cb2002-05-23 13:13:12 +000079
sewardj9a2224b2002-06-19 10:17:40 +000080static
sewardj08c7f012002-10-07 23:56:55 +000081int my_do_syscall1 ( int syscallno, int arg1 );
82
83static
sewardj9a2224b2002-06-19 10:17:40 +000084int my_do_syscall2 ( int syscallno,
85 int arg1, int arg2 );
86
sewardj08c7f012002-10-07 23:56:55 +000087static
88int my_do_syscall3 ( int syscallno,
89 int arg1, int arg2, int arg3 );
90
91
92#ifdef GLIBC_2_3
93 /* kludge by JRS (not from glibc) ... */
94 typedef void* __locale_t;
95
96 /* Copied from locale/locale.h in glibc-2.2.93 sources */
97 /* This value can be passed to `uselocale' and may be returned by
98 it. Passing this value to any other function has undefined
99 behavior. */
100# define LC_GLOBAL_LOCALE ((__locale_t) -1L)
101 extern __locale_t __uselocale ( __locale_t );
102#endif
103
sewardj00a66b12002-10-12 16:42:35 +0000104static
105void init_libc_tsd_keys ( void );
106
sewardj705d3cb2002-05-23 13:13:12 +0000107
sewardje663cb92002-04-12 10:26:32 +0000108/* ---------------------------------------------------------------------
109 Helpers. We have to be pretty self-sufficient.
110 ------------------------------------------------------------------ */
111
sewardj436e0582002-04-26 14:31:40 +0000112/* Number of times any given error message is printed. */
113#define N_MOANS 3
114
sewardj45b4b372002-04-16 22:50:32 +0000115/* Extract from Valgrind the value of VG_(clo_trace_pthread_level).
116 Returns 0 (none) if not running on Valgrind. */
117static
118int get_pt_trace_level ( void )
119{
120 int res;
121 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
122 VG_USERREQ__GET_PTHREAD_TRACE_LEVEL,
123 0, 0, 0, 0);
124 return res;
125}
126
sewardje663cb92002-04-12 10:26:32 +0000127static
sewardj2d94c112002-06-03 01:25:54 +0000128void my_exit ( int arg )
sewardje663cb92002-04-12 10:26:32 +0000129{
sewardj08c7f012002-10-07 23:56:55 +0000130 my_do_syscall1(__NR_exit, arg);
131 /*NOTREACHED*/
sewardje663cb92002-04-12 10:26:32 +0000132}
133
sewardj08c7f012002-10-07 23:56:55 +0000134static
135void my_write ( int fd, const void *buf, int count )
136{
137 my_do_syscall3(__NR_write, fd, (int)buf, count );
138}
sewardje663cb92002-04-12 10:26:32 +0000139
sewardj68b2dd92002-05-10 21:03:56 +0000140/* We need this guy -- it's in valgrind.so. */
141extern void VG_(startup) ( void );
142
143
144/* Just start up Valgrind if it's not already going. VG_(startup)()
145 detects and ignores second and subsequent calls. */
sewardj604ec3c2002-04-18 22:38:41 +0000146static __inline__
sewardje663cb92002-04-12 10:26:32 +0000147void ensure_valgrind ( char* caller )
148{
sewardj68b2dd92002-05-10 21:03:56 +0000149 VG_(startup)();
sewardje663cb92002-04-12 10:26:32 +0000150}
151
sewardjbea1caa2002-05-10 23:20:58 +0000152/* While we're at it ... hook our own startup function into this
153 game. */
154__asm__ (
155 ".section .init\n"
156 "\tcall vgPlain_startup"
157);
158
sewardje663cb92002-04-12 10:26:32 +0000159
160static
sewardj3b5d8862002-04-20 13:53:23 +0000161__attribute__((noreturn))
sewardje663cb92002-04-12 10:26:32 +0000162void barf ( char* str )
163{
sewardj69a72a52002-11-03 13:41:41 +0000164 int res;
165 char buf[1000];
sewardje663cb92002-04-12 10:26:32 +0000166 buf[0] = 0;
sewardj439d45e2002-05-03 20:43:10 +0000167 strcat(buf, "\nvalgrind's libpthread.so: ");
sewardje663cb92002-04-12 10:26:32 +0000168 strcat(buf, str);
169 strcat(buf, "\n\n");
sewardj69a72a52002-11-03 13:41:41 +0000170 VALGRIND_MAGIC_SEQUENCE(res, 0, /* irrelevant default */
171 VG_USERREQ__LOGMESSAGE, buf, 0, 0, 0);
sewardj2d94c112002-06-03 01:25:54 +0000172 my_exit(1);
sewardj3b5d8862002-04-20 13:53:23 +0000173 /* We have to persuade gcc into believing this doesn't return. */
174 while (1) { };
sewardje663cb92002-04-12 10:26:32 +0000175}
176
177
sewardj69a72a52002-11-03 13:41:41 +0000178static void cat_n_send ( char* pre, char* msg )
sewardj2a3d28c2002-04-14 13:27:00 +0000179{
sewardj69a72a52002-11-03 13:41:41 +0000180 char buf[1000];
181 int res;
sewardj436e0582002-04-26 14:31:40 +0000182 if (get_pt_trace_level() >= 0) {
sewardj69a72a52002-11-03 13:41:41 +0000183 snprintf(buf, sizeof(buf), "%s%s", pre, msg );
184 buf[sizeof(buf)-1] = '\0';
185 VALGRIND_MAGIC_SEQUENCE(res, 0, /* irrelevant default */
186 VG_USERREQ__LOGMESSAGE, buf, 0, 0, 0);
sewardj45b4b372002-04-16 22:50:32 +0000187 }
sewardj2a3d28c2002-04-14 13:27:00 +0000188}
189
sewardj69a72a52002-11-03 13:41:41 +0000190static void ignored ( char* msg )
191{
192 cat_n_send ( "valgrind's libpthread.so: IGNORED call to: ", msg );
193}
194
195
sewardj30671ff2002-04-21 00:13:57 +0000196static void kludged ( char* msg )
197{
sewardj69a72a52002-11-03 13:41:41 +0000198 cat_n_send ( "valgrind's libpthread.so: KLUDGED call to: ", msg );
sewardj439d45e2002-05-03 20:43:10 +0000199}
200
sewardj69a72a52002-11-03 13:41:41 +0000201
sewardjccef2e62002-05-29 19:26:32 +0000202__attribute__((noreturn))
sewardj3b13f0e2002-04-25 20:17:29 +0000203void vgPlain_unimp ( char* what )
204{
sewardj69a72a52002-11-03 13:41:41 +0000205 cat_n_send (
206 "valgrind's libpthread.so: UNIMPLEMENTED FUNCTION: ", what );
sewardj3b13f0e2002-04-25 20:17:29 +0000207 barf("Please report this bug to me at: jseward@acm.org");
208}
209
sewardje663cb92002-04-12 10:26:32 +0000210
sewardj457cc472002-06-03 23:13:47 +0000211static
sewardj2d94c112002-06-03 01:25:54 +0000212void my_assert_fail ( Char* expr, Char* file, Int line, Char* fn )
213{
sewardj69a72a52002-11-03 13:41:41 +0000214 char buf[1000];
sewardj2d94c112002-06-03 01:25:54 +0000215 static Bool entered = False;
216 if (entered)
217 my_exit(2);
218 entered = True;
sewardj69a72a52002-11-03 13:41:41 +0000219 sprintf(buf, "\n%s: %s:%d (%s): Assertion `%s' failed.\n",
220 "valgrind", file, line, fn, expr );
221 cat_n_send ( "", buf );
222 sprintf(buf, "Please report this bug to me at: %s\n\n",
223 VG_EMAIL_ADDR);
224 cat_n_send ( "", buf );
sewardj2d94c112002-06-03 01:25:54 +0000225 my_exit(1);
226}
227
228#define MY__STRING(__str) #__str
229
230#define my_assert(expr) \
231 ((void) ((expr) ? 0 : \
232 (my_assert_fail (MY__STRING(expr), \
233 __FILE__, __LINE__, \
234 __PRETTY_FUNCTION__), 0)))
235
sewardj00a66b12002-10-12 16:42:35 +0000236static
237void my_free ( void* ptr )
238{
239 int res;
240 VALGRIND_MAGIC_SEQUENCE(res, (-1) /* default */,
241 VG_USERREQ__FREE, ptr, 0, 0, 0);
242 my_assert(res == 0);
243}
244
245
246static
247void* my_malloc ( int nbytes )
248{
249 void* res;
250 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
251 VG_USERREQ__MALLOC, nbytes, 0, 0, 0);
252 my_assert(res != (void*)0);
253 return res;
254}
255
256
sewardj2d94c112002-06-03 01:25:54 +0000257
sewardje663cb92002-04-12 10:26:32 +0000258/* ---------------------------------------------------------------------
259 Pass pthread_ calls to Valgrind's request mechanism.
260 ------------------------------------------------------------------ */
261
sewardjf8f819e2002-04-17 23:21:37 +0000262#include <errno.h>
sewardj5f07b662002-04-23 16:52:51 +0000263#include <sys/time.h> /* gettimeofday */
sewardjf8f819e2002-04-17 23:21:37 +0000264
sewardja1ac5cb2002-05-27 13:00:05 +0000265
sewardjf8f819e2002-04-17 23:21:37 +0000266/* ---------------------------------------------------
sewardj4dced352002-06-04 22:54:20 +0000267 Ummm ..
268 ------------------------------------------------ */
269
270static
271void pthread_error ( const char* msg )
272{
273 int res;
274 VALGRIND_MAGIC_SEQUENCE(res, 0,
275 VG_USERREQ__PTHREAD_ERROR,
276 msg, 0, 0, 0);
277}
278
279
280/* ---------------------------------------------------
sewardj00a66b12002-10-12 16:42:35 +0000281 Here so it can be inlined without complaint.
282 ------------------------------------------------ */
283
284__inline__
285pthread_t pthread_self(void)
286{
287 int tid;
288 ensure_valgrind("pthread_self");
289 VALGRIND_MAGIC_SEQUENCE(tid, 0 /* default */,
290 VG_USERREQ__PTHREAD_GET_THREADID,
291 0, 0, 0, 0);
292 if (tid < 1 || tid >= VG_N_THREADS)
293 barf("pthread_self: invalid ThreadId");
294 return tid;
295}
296
297
298/* ---------------------------------------------------
sewardjf8f819e2002-04-17 23:21:37 +0000299 THREAD ATTRIBUTES
300 ------------------------------------------------ */
301
sewardj6af4b5d2002-04-16 04:40:49 +0000302int pthread_attr_init(pthread_attr_t *attr)
303{
sewardj7989d0c2002-05-28 11:00:01 +0000304 /* Just initialise the fields which we might look at. */
305 attr->__detachstate = PTHREAD_CREATE_JOINABLE;
sewardj111b14c2002-10-20 16:22:57 +0000306 /* Linuxthreads sets this field to the value __getpagesize(), so I
307 guess the following is OK. */
308 attr->__guardsize = VKI_BYTES_PER_PAGE; return 0;
sewardj6af4b5d2002-04-16 04:40:49 +0000309}
310
311int pthread_attr_setdetachstate(pthread_attr_t *attr, int detachstate)
312{
sewardj7989d0c2002-05-28 11:00:01 +0000313 if (detachstate != PTHREAD_CREATE_JOINABLE
sewardj4dced352002-06-04 22:54:20 +0000314 && detachstate != PTHREAD_CREATE_DETACHED) {
315 pthread_error("pthread_attr_setdetachstate: "
316 "detachstate is invalid");
sewardj7989d0c2002-05-28 11:00:01 +0000317 return EINVAL;
sewardj4dced352002-06-04 22:54:20 +0000318 }
sewardj7989d0c2002-05-28 11:00:01 +0000319 attr->__detachstate = detachstate;
sewardj6af4b5d2002-04-16 04:40:49 +0000320 return 0;
321}
322
njn25e49d8e72002-09-23 09:36:25 +0000323int pthread_attr_getdetachstate(const pthread_attr_t *attr, int *detachstate)
324{
325 *detachstate = attr->__detachstate;
326 return 0;
327}
328
sewardj30671ff2002-04-21 00:13:57 +0000329int pthread_attr_setinheritsched(pthread_attr_t *attr, int inherit)
330{
sewardj436e0582002-04-26 14:31:40 +0000331 static int moans = N_MOANS;
332 if (moans-- > 0)
333 ignored("pthread_attr_setinheritsched");
sewardj30671ff2002-04-21 00:13:57 +0000334 return 0;
335}
sewardj6af4b5d2002-04-16 04:40:49 +0000336
sewardj0286dd52002-05-16 20:51:15 +0000337__attribute__((weak))
338int pthread_attr_setstacksize (pthread_attr_t *__attr,
339 size_t __stacksize)
340{
sewardja18e2102002-05-18 10:43:22 +0000341 size_t limit;
sewardj3d7c8d62002-06-04 20:59:16 +0000342 char buf[1024];
sewardj0286dd52002-05-16 20:51:15 +0000343 ensure_valgrind("pthread_attr_setstacksize");
sewardja18e2102002-05-18 10:43:22 +0000344 limit = VG_PTHREAD_STACK_SIZE - VG_AR_CLIENT_STACKBASE_REDZONE_SZB
345 - 1000; /* paranoia */
346 if (__stacksize < limit)
sewardj0286dd52002-05-16 20:51:15 +0000347 return 0;
sewardj3d7c8d62002-06-04 20:59:16 +0000348 snprintf(buf, sizeof(buf), "pthread_attr_setstacksize: "
349 "requested size %d >= VG_PTHREAD_STACK_SIZE\n "
350 "edit vg_include.h and rebuild.", __stacksize);
351 buf[sizeof(buf)-1] = '\0'; /* Make sure it is zero terminated */
352 barf(buf);
sewardj0286dd52002-05-16 20:51:15 +0000353}
354
355
sewardj30671ff2002-04-21 00:13:57 +0000356/* This is completely bogus. */
357int pthread_attr_getschedparam(const pthread_attr_t *attr,
358 struct sched_param *param)
359{
sewardj436e0582002-04-26 14:31:40 +0000360 static int moans = N_MOANS;
361 if (moans-- > 0)
362 kludged("pthread_attr_getschedparam");
sewardj3e909ce2002-06-03 13:27:15 +0000363# ifdef HAVE_SCHED_PRIORITY
sewardj72d58482002-04-24 02:20:20 +0000364 if (param) param->sched_priority = 0; /* who knows */
365# else
sewardj30671ff2002-04-21 00:13:57 +0000366 if (param) param->__sched_priority = 0; /* who knows */
sewardj72d58482002-04-24 02:20:20 +0000367# endif
sewardj30671ff2002-04-21 00:13:57 +0000368 return 0;
369}
370
371int pthread_attr_setschedparam(pthread_attr_t *attr,
372 const struct sched_param *param)
373{
sewardj436e0582002-04-26 14:31:40 +0000374 static int moans = N_MOANS;
375 if (moans-- > 0)
376 ignored("pthread_attr_setschedparam");
sewardj30671ff2002-04-21 00:13:57 +0000377 return 0;
378}
379
380int pthread_attr_destroy(pthread_attr_t *attr)
381{
sewardj436e0582002-04-26 14:31:40 +0000382 static int moans = N_MOANS;
383 if (moans-- > 0)
384 ignored("pthread_attr_destroy");
sewardj30671ff2002-04-21 00:13:57 +0000385 return 0;
386}
sewardjf8f819e2002-04-17 23:21:37 +0000387
sewardj0d844232002-06-02 09:29:31 +0000388/* These are no-ops, as with LinuxThreads. */
389int pthread_attr_setscope ( pthread_attr_t *attr, int scope )
390{
391 ensure_valgrind("pthread_attr_setscope");
392 if (scope == PTHREAD_SCOPE_SYSTEM)
393 return 0;
sewardj4dced352002-06-04 22:54:20 +0000394 pthread_error("pthread_attr_setscope: "
395 "invalid or unsupported scope");
sewardj0d844232002-06-02 09:29:31 +0000396 if (scope == PTHREAD_SCOPE_PROCESS)
397 return ENOTSUP;
398 return EINVAL;
399}
400
401int pthread_attr_getscope ( const pthread_attr_t *attr, int *scope )
402{
403 ensure_valgrind("pthread_attr_setscope");
404 if (scope)
405 *scope = PTHREAD_SCOPE_SYSTEM;
406 return 0;
407}
408
sewardj64039bb2002-06-03 00:58:18 +0000409
410/* Pretty bogus. Avoid if possible. */
411int pthread_getattr_np (pthread_t thread, pthread_attr_t *attr)
412{
413 int detached;
414 size_t limit;
415 ensure_valgrind("pthread_getattr_np");
416 kludged("pthread_getattr_np");
417 limit = VG_PTHREAD_STACK_SIZE - VG_AR_CLIENT_STACKBASE_REDZONE_SZB
418 - 1000; /* paranoia */
419 attr->__detachstate = PTHREAD_CREATE_JOINABLE;
420 attr->__schedpolicy = SCHED_OTHER;
421 attr->__schedparam.sched_priority = 0;
422 attr->__inheritsched = PTHREAD_EXPLICIT_SCHED;
423 attr->__scope = PTHREAD_SCOPE_SYSTEM;
424 attr->__guardsize = VKI_BYTES_PER_PAGE;
425 attr->__stackaddr = NULL;
426 attr->__stackaddr_set = 0;
427 attr->__stacksize = limit;
428 VALGRIND_MAGIC_SEQUENCE(detached, (-1) /* default */,
429 VG_USERREQ__SET_OR_GET_DETACH,
430 2 /* get */, thread, 0, 0);
sewardj2d94c112002-06-03 01:25:54 +0000431 my_assert(detached == 0 || detached == 1);
sewardj64039bb2002-06-03 00:58:18 +0000432 if (detached)
433 attr->__detachstate = PTHREAD_CREATE_DETACHED;
434 return 0;
435}
436
437
438/* Bogus ... */
sewardj111b14c2002-10-20 16:22:57 +0000439__attribute__((weak))
sewardj64039bb2002-06-03 00:58:18 +0000440int pthread_attr_getstackaddr ( const pthread_attr_t * attr,
441 void ** stackaddr )
442{
443 ensure_valgrind("pthread_attr_getstackaddr");
444 kludged("pthread_attr_getstackaddr");
445 if (stackaddr)
446 *stackaddr = NULL;
447 return 0;
448}
449
450/* Not bogus (!) */
sewardj111b14c2002-10-20 16:22:57 +0000451__attribute__((weak))
sewardj64039bb2002-06-03 00:58:18 +0000452int pthread_attr_getstacksize ( const pthread_attr_t * _attr,
453 size_t * __stacksize )
454{
455 size_t limit;
456 ensure_valgrind("pthread_attr_getstacksize");
457 limit = VG_PTHREAD_STACK_SIZE - VG_AR_CLIENT_STACKBASE_REDZONE_SZB
458 - 1000; /* paranoia */
459 if (__stacksize)
460 *__stacksize = limit;
461 return 0;
462}
463
sewardja3be12f2002-06-17 12:19:44 +0000464int pthread_attr_setschedpolicy(pthread_attr_t *attr, int policy)
465{
466 if (policy != SCHED_OTHER && policy != SCHED_FIFO && policy != SCHED_RR)
467 return EINVAL;
468 attr->__schedpolicy = policy;
469 return 0;
470}
471
472int pthread_attr_getschedpolicy(const pthread_attr_t *attr, int *policy)
473{
474 *policy = attr->__schedpolicy;
475 return 0;
476}
477
478
sewardj111b14c2002-10-20 16:22:57 +0000479/* This is completely bogus. We reject all attempts to change it from
480 VKI_BYTES_PER_PAGE. I don't have a clue what it's for so it seems
481 safest to be paranoid. */
482__attribute__((weak))
483int pthread_attr_setguardsize(pthread_attr_t *attr, size_t guardsize)
484{
485 static int moans = N_MOANS;
486
487 if (guardsize == VKI_BYTES_PER_PAGE)
488 return 0;
489
490 if (moans-- > 0)
491 ignored("pthread_attr_setguardsize: ignoring guardsize != 4096");
492
493 return 0;
494}
495
496/* A straight copy of the LinuxThreads code. */
497__attribute__((weak))
498int pthread_attr_getguardsize(const pthread_attr_t *attr, size_t *guardsize)
499{
500 *guardsize = attr->__guardsize;
501 return 0;
502}
503
504
sewardj20917d82002-05-28 01:36:45 +0000505/* ---------------------------------------------------
506 Helper functions for running a thread
507 and for clearing up afterwards.
508 ------------------------------------------------ */
509
510/* All exiting threads eventually pass through here, bearing the
511 return value, or PTHREAD_CANCELED, in ret_val. */
512static
513__attribute__((noreturn))
514void thread_exit_wrapper ( void* ret_val )
515{
sewardj870497a2002-05-29 01:06:47 +0000516 int detached, res;
517 CleanupEntry cu;
518 pthread_key_t key;
sewardj00a66b12002-10-12 16:42:35 +0000519 void** specifics_ptr;
sewardj870497a2002-05-29 01:06:47 +0000520
sewardj20917d82002-05-28 01:36:45 +0000521 /* Run this thread's cleanup handlers. */
sewardj8ad94e12002-05-29 00:10:20 +0000522 while (1) {
523 VALGRIND_MAGIC_SEQUENCE(res, (-1) /* default */,
524 VG_USERREQ__CLEANUP_POP,
525 &cu, 0, 0, 0);
526 if (res == -1) break; /* stack empty */
sewardj2d94c112002-06-03 01:25:54 +0000527 my_assert(res == 0);
sewardj8ad94e12002-05-29 00:10:20 +0000528 if (0) printf("running exit cleanup handler");
529 cu.fn ( cu.arg );
530 }
531
sewardj870497a2002-05-29 01:06:47 +0000532 /* Run this thread's key finalizers. Really this should be run
533 PTHREAD_DESTRUCTOR_ITERATIONS times. */
534 for (key = 0; key < VG_N_THREAD_KEYS; key++) {
535 VALGRIND_MAGIC_SEQUENCE(res, (-2) /* default */,
536 VG_USERREQ__GET_KEY_D_AND_S,
537 key, &cu, 0, 0 );
538 if (res == 0) {
539 /* valid key */
540 if (cu.fn && cu.arg)
541 cu.fn /* destructor for key */
542 ( cu.arg /* specific for key for this thread */ );
543 continue;
544 }
sewardj2d94c112002-06-03 01:25:54 +0000545 my_assert(res == -1);
sewardj870497a2002-05-29 01:06:47 +0000546 }
sewardj20917d82002-05-28 01:36:45 +0000547
sewardj00a66b12002-10-12 16:42:35 +0000548 /* Free up my specifics space, if any. */
549 VALGRIND_MAGIC_SEQUENCE(specifics_ptr, 3 /* default */,
550 VG_USERREQ__PTHREAD_GETSPECIFIC_PTR,
551 pthread_self(), 0, 0, 0);
552 my_assert(specifics_ptr != (void**)3);
553 my_assert(specifics_ptr != (void**)1); /* 1 means invalid thread */
554 if (specifics_ptr != NULL)
555 my_free(specifics_ptr);
556
sewardj20917d82002-05-28 01:36:45 +0000557 /* Decide on my final disposition. */
558 VALGRIND_MAGIC_SEQUENCE(detached, (-1) /* default */,
559 VG_USERREQ__SET_OR_GET_DETACH,
sewardj7989d0c2002-05-28 11:00:01 +0000560 2 /* get */, pthread_self(), 0, 0);
sewardj2d94c112002-06-03 01:25:54 +0000561 my_assert(detached == 0 || detached == 1);
sewardj20917d82002-05-28 01:36:45 +0000562
563 if (detached) {
564 /* Detached; I just quit right now. */
565 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
566 VG_USERREQ__QUIT, 0, 0, 0, 0);
567 } else {
568 /* Not detached; so I wait for a joiner. */
569 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
570 VG_USERREQ__WAIT_JOINER, ret_val, 0, 0, 0);
571 }
572 /* NOTREACHED */
573 barf("thread_exit_wrapper: still alive?!");
574}
575
576
577/* This function is a wrapper function for running a thread. It runs
578 the root function specified in pthread_create, and then, should the
579 root function return a value, it arranges to run the thread's
580 cleanup handlers and exit correctly. */
581
sewardj728a5272002-06-20 10:25:37 +0000582/* Struct used to convey info from pthread_create to thread_wrapper.
583 Must be careful not to pass to the child thread any pointers to
584 objects which might be on the parent's stack. */
sewardj20917d82002-05-28 01:36:45 +0000585typedef
586 struct {
sewardj728a5272002-06-20 10:25:37 +0000587 int attr__detachstate;
sewardj20917d82002-05-28 01:36:45 +0000588 void* (*root_fn) ( void* );
589 void* arg;
590 }
591 NewThreadInfo;
592
593
594/* This is passed to the VG_USERREQ__APPLY_IN_NEW_THREAD and so must
595 not return. Note that this runs in the new thread, not the
596 parent. */
597static
598__attribute__((noreturn))
599void thread_wrapper ( NewThreadInfo* info )
600{
sewardj728a5272002-06-20 10:25:37 +0000601 int attr__detachstate;
sewardj20917d82002-05-28 01:36:45 +0000602 void* (*root_fn) ( void* );
603 void* arg;
604 void* ret_val;
605
sewardj728a5272002-06-20 10:25:37 +0000606 attr__detachstate = info->attr__detachstate;
607 root_fn = info->root_fn;
608 arg = info->arg;
sewardj20917d82002-05-28 01:36:45 +0000609
sewardj20917d82002-05-28 01:36:45 +0000610 /* Free up the arg block that pthread_create malloced. */
sewardj00a66b12002-10-12 16:42:35 +0000611 my_free(info);
sewardj20917d82002-05-28 01:36:45 +0000612
sewardj7989d0c2002-05-28 11:00:01 +0000613 /* Minimally observe the attributes supplied. */
sewardj728a5272002-06-20 10:25:37 +0000614 if (attr__detachstate != PTHREAD_CREATE_DETACHED
615 && attr__detachstate != PTHREAD_CREATE_JOINABLE)
616 pthread_error("thread_wrapper: invalid attr->__detachstate");
617 if (attr__detachstate == PTHREAD_CREATE_DETACHED)
618 pthread_detach(pthread_self());
sewardj7989d0c2002-05-28 11:00:01 +0000619
sewardj00a66b12002-10-12 16:42:35 +0000620# ifdef GLIBC_2_3
621 /* Set this thread's locale to the global (default) locale. A hack
622 in support of glibc-2.3. This does the biz for the all new
623 threads; the root thread is done with a horrible hack in
624 init_libc_tsd_keys() below.
625 */
626 __uselocale(LC_GLOBAL_LOCALE);
627# endif
628
sewardj20917d82002-05-28 01:36:45 +0000629 /* The root function might not return. But if it does we simply
630 move along to thread_exit_wrapper. All other ways out for the
631 thread (cancellation, or calling pthread_exit) lead there
632 too. */
633 ret_val = root_fn(arg);
634 thread_exit_wrapper(ret_val);
635 /* NOTREACHED */
636}
637
638
sewardjf8f819e2002-04-17 23:21:37 +0000639/* ---------------------------------------------------
640 THREADs
641 ------------------------------------------------ */
642
sewardjff42d1d2002-05-22 13:17:31 +0000643__attribute__((weak))
644int pthread_yield ( void )
645{
646 int res;
647 ensure_valgrind("pthread_yield");
648 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
649 VG_USERREQ__PTHREAD_YIELD, 0, 0, 0, 0);
650 return 0;
651}
652
653
sewardj6072c362002-04-19 14:40:57 +0000654int pthread_equal(pthread_t thread1, pthread_t thread2)
655{
656 return thread1 == thread2 ? 1 : 0;
657}
658
659
sewardj20917d82002-05-28 01:36:45 +0000660/* Bundle up the args into a malloc'd block and create a new thread
661 consisting of thread_wrapper() applied to said malloc'd block. */
sewardje663cb92002-04-12 10:26:32 +0000662int
sewardj1462c8b2002-07-24 09:41:52 +0000663pthread_create (pthread_t *__restrict __thredd,
sewardje663cb92002-04-12 10:26:32 +0000664 __const pthread_attr_t *__restrict __attr,
665 void *(*__start_routine) (void *),
666 void *__restrict __arg)
667{
sewardj20917d82002-05-28 01:36:45 +0000668 int tid_child;
669 NewThreadInfo* info;
sewardje663cb92002-04-12 10:26:32 +0000670
sewardj20917d82002-05-28 01:36:45 +0000671 ensure_valgrind("pthread_create");
672
sewardj00a66b12002-10-12 16:42:35 +0000673 /* make sure the tsd keys, and hence locale info, are initialised
674 before we get into complications making new threads. */
675 init_libc_tsd_keys();
676
sewardj20917d82002-05-28 01:36:45 +0000677 /* Allocate space for the arg block. thread_wrapper will free
678 it. */
sewardj00a66b12002-10-12 16:42:35 +0000679 info = my_malloc(sizeof(NewThreadInfo));
sewardj2d94c112002-06-03 01:25:54 +0000680 my_assert(info != NULL);
sewardj20917d82002-05-28 01:36:45 +0000681
sewardj728a5272002-06-20 10:25:37 +0000682 if (__attr)
683 info->attr__detachstate = __attr->__detachstate;
684 else
685 info->attr__detachstate = PTHREAD_CREATE_JOINABLE;
686
sewardj20917d82002-05-28 01:36:45 +0000687 info->root_fn = __start_routine;
688 info->arg = __arg;
689 VALGRIND_MAGIC_SEQUENCE(tid_child, VG_INVALID_THREADID /* default */,
690 VG_USERREQ__APPLY_IN_NEW_THREAD,
691 &thread_wrapper, info, 0, 0);
sewardj2d94c112002-06-03 01:25:54 +0000692 my_assert(tid_child != VG_INVALID_THREADID);
sewardj20917d82002-05-28 01:36:45 +0000693
sewardj1462c8b2002-07-24 09:41:52 +0000694 if (__thredd)
695 *__thredd = tid_child;
sewardj20917d82002-05-28 01:36:45 +0000696 return 0; /* success */
697}
sewardje663cb92002-04-12 10:26:32 +0000698
699
700int
701pthread_join (pthread_t __th, void **__thread_return)
702{
703 int res;
704 ensure_valgrind("pthread_join");
705 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
706 VG_USERREQ__PTHREAD_JOIN,
707 __th, __thread_return, 0, 0);
708 return res;
709}
710
711
sewardj3b5d8862002-04-20 13:53:23 +0000712void pthread_exit(void *retval)
713{
sewardj3b5d8862002-04-20 13:53:23 +0000714 ensure_valgrind("pthread_exit");
sewardj20917d82002-05-28 01:36:45 +0000715 /* Simple! */
716 thread_exit_wrapper(retval);
sewardj3b5d8862002-04-20 13:53:23 +0000717}
718
sewardje663cb92002-04-12 10:26:32 +0000719
sewardj853f55d2002-04-26 00:27:53 +0000720int pthread_detach(pthread_t th)
721{
sewardj20917d82002-05-28 01:36:45 +0000722 int res;
723 ensure_valgrind("pthread_detach");
sewardj7989d0c2002-05-28 11:00:01 +0000724 /* First we enquire as to the current detach state. */
725 VALGRIND_MAGIC_SEQUENCE(res, (-2) /* default */,
sewardj20917d82002-05-28 01:36:45 +0000726 VG_USERREQ__SET_OR_GET_DETACH,
sewardj7989d0c2002-05-28 11:00:01 +0000727 2 /* get */, th, 0, 0);
sewardj4dced352002-06-04 22:54:20 +0000728 if (res == -1) {
729 /* not found */
730 pthread_error("pthread_detach: "
731 "invalid target thread");
sewardj7989d0c2002-05-28 11:00:01 +0000732 return ESRCH;
sewardj4dced352002-06-04 22:54:20 +0000733 }
734 if (res == 1) {
735 /* already detached */
736 pthread_error("pthread_detach: "
737 "target thread is already detached");
sewardj7989d0c2002-05-28 11:00:01 +0000738 return EINVAL;
sewardj4dced352002-06-04 22:54:20 +0000739 }
sewardj7989d0c2002-05-28 11:00:01 +0000740 if (res == 0) {
741 VALGRIND_MAGIC_SEQUENCE(res, (-2) /* default */,
742 VG_USERREQ__SET_OR_GET_DETACH,
743 1 /* set */, th, 0, 0);
sewardj2d94c112002-06-03 01:25:54 +0000744 my_assert(res == 0);
sewardj7989d0c2002-05-28 11:00:01 +0000745 return 0;
746 }
747 barf("pthread_detach");
sewardj853f55d2002-04-26 00:27:53 +0000748}
749
750
sewardjf8f819e2002-04-17 23:21:37 +0000751/* ---------------------------------------------------
sewardj8ad94e12002-05-29 00:10:20 +0000752 CLEANUP STACKS
753 ------------------------------------------------ */
754
755void _pthread_cleanup_push (struct _pthread_cleanup_buffer *__buffer,
756 void (*__routine) (void *),
757 void *__arg)
758{
759 int res;
760 CleanupEntry cu;
761 ensure_valgrind("_pthread_cleanup_push");
762 cu.fn = __routine;
763 cu.arg = __arg;
764 VALGRIND_MAGIC_SEQUENCE(res, (-1) /* default */,
765 VG_USERREQ__CLEANUP_PUSH,
766 &cu, 0, 0, 0);
sewardj2d94c112002-06-03 01:25:54 +0000767 my_assert(res == 0);
sewardj8ad94e12002-05-29 00:10:20 +0000768}
769
770
771void _pthread_cleanup_push_defer (struct _pthread_cleanup_buffer *__buffer,
772 void (*__routine) (void *),
773 void *__arg)
774{
775 /* As _pthread_cleanup_push, but first save the thread's original
776 cancellation type in __buffer and set it to Deferred. */
777 int orig_ctype;
778 ensure_valgrind("_pthread_cleanup_push_defer");
779 /* Set to Deferred, and put the old cancellation type in res. */
sewardj2d94c112002-06-03 01:25:54 +0000780 my_assert(-1 != PTHREAD_CANCEL_DEFERRED);
781 my_assert(-1 != PTHREAD_CANCEL_ASYNCHRONOUS);
782 my_assert(sizeof(struct _pthread_cleanup_buffer) >= sizeof(int));
sewardj8ad94e12002-05-29 00:10:20 +0000783 VALGRIND_MAGIC_SEQUENCE(orig_ctype, (-1) /* default */,
784 VG_USERREQ__SET_CANCELTYPE,
785 PTHREAD_CANCEL_DEFERRED, 0, 0, 0);
sewardj2d94c112002-06-03 01:25:54 +0000786 my_assert(orig_ctype != -1);
sewardj8ad94e12002-05-29 00:10:20 +0000787 *((int*)(__buffer)) = orig_ctype;
788 /* Now push the cleanup. */
789 _pthread_cleanup_push(NULL, __routine, __arg);
790}
791
792
793void _pthread_cleanup_pop (struct _pthread_cleanup_buffer *__buffer,
794 int __execute)
795{
796 int res;
797 CleanupEntry cu;
798 ensure_valgrind("_pthread_cleanup_push");
799 cu.fn = cu.arg = NULL; /* paranoia */
800 VALGRIND_MAGIC_SEQUENCE(res, (-1) /* default */,
801 VG_USERREQ__CLEANUP_POP,
802 &cu, 0, 0, 0);
803 if (res == 0) {
804 /* pop succeeded */
805 if (__execute) {
806 cu.fn ( cu.arg );
807 }
808 return;
809 }
810 if (res == -1) {
811 /* stack underflow */
812 return;
813 }
814 barf("_pthread_cleanup_pop");
815}
816
817
818void _pthread_cleanup_pop_restore (struct _pthread_cleanup_buffer *__buffer,
819 int __execute)
820{
821 int orig_ctype, fake_ctype;
822 /* As _pthread_cleanup_pop, but after popping/running the handler,
823 restore the thread's original cancellation type from the first
824 word of __buffer. */
825 _pthread_cleanup_pop(NULL, __execute);
826 orig_ctype = *((int*)(__buffer));
sewardj2d94c112002-06-03 01:25:54 +0000827 my_assert(orig_ctype == PTHREAD_CANCEL_DEFERRED
sewardj8ad94e12002-05-29 00:10:20 +0000828 || orig_ctype == PTHREAD_CANCEL_ASYNCHRONOUS);
sewardj2d94c112002-06-03 01:25:54 +0000829 my_assert(-1 != PTHREAD_CANCEL_DEFERRED);
830 my_assert(-1 != PTHREAD_CANCEL_ASYNCHRONOUS);
831 my_assert(sizeof(struct _pthread_cleanup_buffer) >= sizeof(int));
sewardj8ad94e12002-05-29 00:10:20 +0000832 VALGRIND_MAGIC_SEQUENCE(fake_ctype, (-1) /* default */,
833 VG_USERREQ__SET_CANCELTYPE,
834 orig_ctype, 0, 0, 0);
sewardj2d94c112002-06-03 01:25:54 +0000835 my_assert(fake_ctype == PTHREAD_CANCEL_DEFERRED);
sewardj8ad94e12002-05-29 00:10:20 +0000836}
837
838
839/* ---------------------------------------------------
sewardjf8f819e2002-04-17 23:21:37 +0000840 MUTEX ATTRIBUTES
841 ------------------------------------------------ */
842
sewardj5905fae2002-04-26 13:25:00 +0000843int __pthread_mutexattr_init(pthread_mutexattr_t *attr)
sewardje663cb92002-04-12 10:26:32 +0000844{
sewardjf8f819e2002-04-17 23:21:37 +0000845 attr->__mutexkind = PTHREAD_MUTEX_ERRORCHECK_NP;
sewardj8937c812002-04-12 20:12:20 +0000846 return 0;
sewardje663cb92002-04-12 10:26:32 +0000847}
848
sewardj5905fae2002-04-26 13:25:00 +0000849int __pthread_mutexattr_settype(pthread_mutexattr_t *attr, int type)
sewardjf8f819e2002-04-17 23:21:37 +0000850{
851 switch (type) {
sewardj3b13f0e2002-04-25 20:17:29 +0000852# ifndef GLIBC_2_1
sewardjf8f819e2002-04-17 23:21:37 +0000853 case PTHREAD_MUTEX_TIMED_NP:
sewardj2a1dcce2002-04-22 12:45:25 +0000854 case PTHREAD_MUTEX_ADAPTIVE_NP:
sewardj3b13f0e2002-04-25 20:17:29 +0000855# endif
sewardja1679dd2002-05-10 22:31:40 +0000856# ifdef GLIBC_2_1
sewardj68b2dd92002-05-10 21:03:56 +0000857 case PTHREAD_MUTEX_FAST_NP:
sewardja1679dd2002-05-10 22:31:40 +0000858# endif
sewardjf8f819e2002-04-17 23:21:37 +0000859 case PTHREAD_MUTEX_RECURSIVE_NP:
860 case PTHREAD_MUTEX_ERRORCHECK_NP:
sewardjf8f819e2002-04-17 23:21:37 +0000861 attr->__mutexkind = type;
862 return 0;
863 default:
sewardj4dced352002-06-04 22:54:20 +0000864 pthread_error("pthread_mutexattr_settype: "
865 "invalid type");
sewardjf8f819e2002-04-17 23:21:37 +0000866 return EINVAL;
867 }
868}
869
sewardj5905fae2002-04-26 13:25:00 +0000870int __pthread_mutexattr_destroy(pthread_mutexattr_t *attr)
sewardjf8f819e2002-04-17 23:21:37 +0000871{
872 return 0;
873}
874
875
876/* ---------------------------------------------------
877 MUTEXes
878 ------------------------------------------------ */
879
sewardj5905fae2002-04-26 13:25:00 +0000880int __pthread_mutex_init(pthread_mutex_t *mutex,
881 const pthread_mutexattr_t *mutexattr)
sewardje663cb92002-04-12 10:26:32 +0000882{
sewardj604ec3c2002-04-18 22:38:41 +0000883 mutex->__m_count = 0;
884 mutex->__m_owner = (_pthread_descr)VG_INVALID_THREADID;
885 mutex->__m_kind = PTHREAD_MUTEX_ERRORCHECK_NP;
886 if (mutexattr)
887 mutex->__m_kind = mutexattr->__mutexkind;
888 return 0;
sewardje663cb92002-04-12 10:26:32 +0000889}
890
sewardj439d45e2002-05-03 20:43:10 +0000891
sewardj5905fae2002-04-26 13:25:00 +0000892int __pthread_mutex_lock(pthread_mutex_t *mutex)
sewardje663cb92002-04-12 10:26:32 +0000893{
894 int res;
sewardjd8acdf22002-11-13 21:57:52 +0000895
sewardj439d45e2002-05-03 20:43:10 +0000896 if (RUNNING_ON_VALGRIND) {
sewardje663cb92002-04-12 10:26:32 +0000897 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
898 VG_USERREQ__PTHREAD_MUTEX_LOCK,
899 mutex, 0, 0, 0);
900 return res;
sewardj439d45e2002-05-03 20:43:10 +0000901 } else {
sewardjd8acdf22002-11-13 21:57:52 +0000902 /* Play at locking */
903 if (0)
904 kludged("prehistoric lock");
905 mutex->__m_owner = (_pthread_descr)1;
906 mutex->__m_count = 1;
907 mutex->__m_kind |= VG_PTHREAD_PREHISTORY;
sewardj439d45e2002-05-03 20:43:10 +0000908 return 0; /* success */
sewardje663cb92002-04-12 10:26:32 +0000909 }
910}
911
sewardj439d45e2002-05-03 20:43:10 +0000912
sewardj5905fae2002-04-26 13:25:00 +0000913int __pthread_mutex_trylock(pthread_mutex_t *mutex)
sewardj30671ff2002-04-21 00:13:57 +0000914{
915 int res;
sewardjd8acdf22002-11-13 21:57:52 +0000916
sewardj439d45e2002-05-03 20:43:10 +0000917 if (RUNNING_ON_VALGRIND) {
sewardj30671ff2002-04-21 00:13:57 +0000918 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
919 VG_USERREQ__PTHREAD_MUTEX_TRYLOCK,
920 mutex, 0, 0, 0);
921 return res;
sewardj439d45e2002-05-03 20:43:10 +0000922 } else {
sewardjd8acdf22002-11-13 21:57:52 +0000923 /* Play at locking */
924 if (0)
925 kludged("prehistoric trylock");
926 mutex->__m_owner = (_pthread_descr)1;
927 mutex->__m_count = 1;
928 mutex->__m_kind |= VG_PTHREAD_PREHISTORY;
929 return 0; /* success */
sewardj30671ff2002-04-21 00:13:57 +0000930 }
931}
932
sewardj439d45e2002-05-03 20:43:10 +0000933
sewardj5905fae2002-04-26 13:25:00 +0000934int __pthread_mutex_unlock(pthread_mutex_t *mutex)
sewardje663cb92002-04-12 10:26:32 +0000935{
936 int res;
sewardjd8acdf22002-11-13 21:57:52 +0000937
sewardj439d45e2002-05-03 20:43:10 +0000938 if (RUNNING_ON_VALGRIND) {
sewardje663cb92002-04-12 10:26:32 +0000939 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
940 VG_USERREQ__PTHREAD_MUTEX_UNLOCK,
941 mutex, 0, 0, 0);
942 return res;
sewardj439d45e2002-05-03 20:43:10 +0000943 } else {
sewardjd8acdf22002-11-13 21:57:52 +0000944 /* Play at locking */
945 if (0)
946 kludged("prehistoric unlock");
947 mutex->__m_owner = 0;
948 mutex->__m_count = 0;
949 mutex->__m_kind &= ~VG_PTHREAD_PREHISTORY;
950 return 0; /* success */
sewardje663cb92002-04-12 10:26:32 +0000951 }
952}
953
sewardj439d45e2002-05-03 20:43:10 +0000954
sewardj5905fae2002-04-26 13:25:00 +0000955int __pthread_mutex_destroy(pthread_mutex_t *mutex)
sewardje663cb92002-04-12 10:26:32 +0000956{
sewardj604ec3c2002-04-18 22:38:41 +0000957 /* Valgrind doesn't hold any resources on behalf of the mutex, so no
958 need to involve it. */
sewardj4dced352002-06-04 22:54:20 +0000959 if (mutex->__m_count > 0) {
sewardjd8acdf22002-11-13 21:57:52 +0000960 /* Oh, the horror. glibc's internal use of pthreads "knows"
961 that destroying a lock does an implicit unlock. Make it
962 explicit. */
963 __pthread_mutex_unlock(mutex);
964 pthread_error("pthread_mutex_destroy: "
965 "mutex is still in use");
966 return EBUSY;
sewardj4dced352002-06-04 22:54:20 +0000967 }
968 mutex->__m_count = 0;
969 mutex->__m_owner = (_pthread_descr)VG_INVALID_THREADID;
970 mutex->__m_kind = PTHREAD_MUTEX_ERRORCHECK_NP;
971 return 0;
sewardje663cb92002-04-12 10:26:32 +0000972}
973
974
sewardjf8f819e2002-04-17 23:21:37 +0000975/* ---------------------------------------------------
sewardj6072c362002-04-19 14:40:57 +0000976 CONDITION VARIABLES
977 ------------------------------------------------ */
978
979/* LinuxThreads supports no attributes for conditions. Hence ... */
980
981int pthread_condattr_init(pthread_condattr_t *attr)
982{
983 return 0;
984}
985
sewardj0738a592002-04-20 13:59:33 +0000986int pthread_condattr_destroy(pthread_condattr_t *attr)
987{
988 return 0;
989}
sewardj6072c362002-04-19 14:40:57 +0000990
991int pthread_cond_init( pthread_cond_t *cond,
992 const pthread_condattr_t *cond_attr)
993{
994 cond->__c_waiting = (_pthread_descr)VG_INVALID_THREADID;
995 return 0;
996}
997
sewardjf854f472002-04-21 12:19:41 +0000998int pthread_cond_destroy(pthread_cond_t *cond)
999{
1000 /* should check that no threads are waiting on this CV */
sewardj436e0582002-04-26 14:31:40 +00001001 static int moans = N_MOANS;
1002 if (moans-- > 0)
1003 kludged("pthread_cond_destroy");
sewardjf854f472002-04-21 12:19:41 +00001004 return 0;
1005}
sewardj6072c362002-04-19 14:40:57 +00001006
1007/* ---------------------------------------------------
1008 SCHEDULING
1009 ------------------------------------------------ */
1010
1011/* This is completely bogus. */
1012int pthread_getschedparam(pthread_t target_thread,
1013 int *policy,
1014 struct sched_param *param)
1015{
sewardj436e0582002-04-26 14:31:40 +00001016 static int moans = N_MOANS;
1017 if (moans-- > 0)
1018 kludged("pthread_getschedparam");
sewardj6072c362002-04-19 14:40:57 +00001019 if (policy) *policy = SCHED_OTHER;
sewardj3e909ce2002-06-03 13:27:15 +00001020# ifdef HAVE_SCHED_PRIORITY
sewardj2a1dcce2002-04-22 12:45:25 +00001021 if (param) param->sched_priority = 0; /* who knows */
1022# else
sewardj6072c362002-04-19 14:40:57 +00001023 if (param) param->__sched_priority = 0; /* who knows */
sewardj2a1dcce2002-04-22 12:45:25 +00001024# endif
sewardj6072c362002-04-19 14:40:57 +00001025 return 0;
1026}
1027
1028int pthread_setschedparam(pthread_t target_thread,
1029 int policy,
1030 const struct sched_param *param)
1031{
sewardj436e0582002-04-26 14:31:40 +00001032 static int moans = N_MOANS;
1033 if (moans-- > 0)
1034 ignored("pthread_setschedparam");
sewardj6072c362002-04-19 14:40:57 +00001035 return 0;
1036}
1037
sewardj3b5d8862002-04-20 13:53:23 +00001038int pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex)
1039{
1040 int res;
1041 ensure_valgrind("pthread_cond_wait");
1042 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
1043 VG_USERREQ__PTHREAD_COND_WAIT,
1044 cond, mutex, 0, 0);
1045 return res;
1046}
1047
sewardj5f07b662002-04-23 16:52:51 +00001048int pthread_cond_timedwait ( pthread_cond_t *cond,
1049 pthread_mutex_t *mutex,
1050 const struct timespec *abstime )
1051{
1052 int res;
1053 unsigned int ms_now, ms_end;
1054 struct timeval timeval_now;
1055 unsigned long long int ull_ms_now_after_1970;
1056 unsigned long long int ull_ms_end_after_1970;
1057
1058 ensure_valgrind("pthread_cond_timedwait");
1059 VALGRIND_MAGIC_SEQUENCE(ms_now, 0xFFFFFFFF /* default */,
1060 VG_USERREQ__READ_MILLISECOND_TIMER,
1061 0, 0, 0, 0);
sewardj2d94c112002-06-03 01:25:54 +00001062 my_assert(ms_now != 0xFFFFFFFF);
sewardj5f07b662002-04-23 16:52:51 +00001063 res = gettimeofday(&timeval_now, NULL);
sewardj2d94c112002-06-03 01:25:54 +00001064 my_assert(res == 0);
sewardj5f07b662002-04-23 16:52:51 +00001065
1066 ull_ms_now_after_1970
1067 = 1000ULL * ((unsigned long long int)(timeval_now.tv_sec))
1068 + ((unsigned long long int)(timeval_now.tv_usec / 1000000));
1069 ull_ms_end_after_1970
1070 = 1000ULL * ((unsigned long long int)(abstime->tv_sec))
1071 + ((unsigned long long int)(abstime->tv_nsec / 1000000));
sewardjd8e919e2002-05-29 20:13:53 +00001072 if (ull_ms_end_after_1970 < ull_ms_now_after_1970)
1073 ull_ms_end_after_1970 = ull_ms_now_after_1970;
sewardj5f07b662002-04-23 16:52:51 +00001074 ms_end
1075 = ms_now + (unsigned int)(ull_ms_end_after_1970 - ull_ms_now_after_1970);
1076 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
1077 VG_USERREQ__PTHREAD_COND_TIMEDWAIT,
1078 cond, mutex, ms_end, 0);
1079 return res;
1080}
1081
1082
sewardj3b5d8862002-04-20 13:53:23 +00001083int pthread_cond_signal(pthread_cond_t *cond)
1084{
1085 int res;
1086 ensure_valgrind("pthread_cond_signal");
1087 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
1088 VG_USERREQ__PTHREAD_COND_SIGNAL,
1089 cond, 0, 0, 0);
1090 return res;
1091}
1092
1093int pthread_cond_broadcast(pthread_cond_t *cond)
1094{
1095 int res;
1096 ensure_valgrind("pthread_cond_broadcast");
1097 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
1098 VG_USERREQ__PTHREAD_COND_BROADCAST,
1099 cond, 0, 0, 0);
1100 return res;
1101}
1102
sewardj6072c362002-04-19 14:40:57 +00001103
1104/* ---------------------------------------------------
sewardjf8f819e2002-04-17 23:21:37 +00001105 CANCELLATION
1106 ------------------------------------------------ */
1107
sewardj853f55d2002-04-26 00:27:53 +00001108int pthread_setcancelstate(int state, int *oldstate)
1109{
sewardj20917d82002-05-28 01:36:45 +00001110 int res;
1111 ensure_valgrind("pthread_setcancelstate");
1112 if (state != PTHREAD_CANCEL_ENABLE
sewardj4dced352002-06-04 22:54:20 +00001113 && state != PTHREAD_CANCEL_DISABLE) {
1114 pthread_error("pthread_setcancelstate: "
1115 "invalid state");
sewardj20917d82002-05-28 01:36:45 +00001116 return EINVAL;
sewardj4dced352002-06-04 22:54:20 +00001117 }
sewardj2d94c112002-06-03 01:25:54 +00001118 my_assert(-1 != PTHREAD_CANCEL_ENABLE);
1119 my_assert(-1 != PTHREAD_CANCEL_DISABLE);
sewardj20917d82002-05-28 01:36:45 +00001120 VALGRIND_MAGIC_SEQUENCE(res, (-1) /* default */,
1121 VG_USERREQ__SET_CANCELSTATE,
1122 state, 0, 0, 0);
sewardj2d94c112002-06-03 01:25:54 +00001123 my_assert(res != -1);
sewardj20917d82002-05-28 01:36:45 +00001124 if (oldstate)
1125 *oldstate = res;
sewardj853f55d2002-04-26 00:27:53 +00001126 return 0;
1127}
1128
sewardje663cb92002-04-12 10:26:32 +00001129int pthread_setcanceltype(int type, int *oldtype)
1130{
sewardj20917d82002-05-28 01:36:45 +00001131 int res;
1132 ensure_valgrind("pthread_setcanceltype");
1133 if (type != PTHREAD_CANCEL_DEFERRED
sewardj4dced352002-06-04 22:54:20 +00001134 && type != PTHREAD_CANCEL_ASYNCHRONOUS) {
1135 pthread_error("pthread_setcanceltype: "
1136 "invalid type");
sewardj20917d82002-05-28 01:36:45 +00001137 return EINVAL;
sewardj4dced352002-06-04 22:54:20 +00001138 }
sewardj2d94c112002-06-03 01:25:54 +00001139 my_assert(-1 != PTHREAD_CANCEL_DEFERRED);
1140 my_assert(-1 != PTHREAD_CANCEL_ASYNCHRONOUS);
sewardj20917d82002-05-28 01:36:45 +00001141 VALGRIND_MAGIC_SEQUENCE(res, (-1) /* default */,
1142 VG_USERREQ__SET_CANCELTYPE,
1143 type, 0, 0, 0);
sewardj2d94c112002-06-03 01:25:54 +00001144 my_assert(res != -1);
sewardj20917d82002-05-28 01:36:45 +00001145 if (oldtype)
1146 *oldtype = res;
sewardje663cb92002-04-12 10:26:32 +00001147 return 0;
1148}
1149
sewardje663cb92002-04-12 10:26:32 +00001150int pthread_cancel(pthread_t thread)
1151{
1152 int res;
1153 ensure_valgrind("pthread_cancel");
sewardj20917d82002-05-28 01:36:45 +00001154 VALGRIND_MAGIC_SEQUENCE(res, (-1) /* default */,
1155 VG_USERREQ__SET_CANCELPEND,
1156 thread, &thread_exit_wrapper, 0, 0);
sewardj2d94c112002-06-03 01:25:54 +00001157 my_assert(res != -1);
sewardje663cb92002-04-12 10:26:32 +00001158 return res;
1159}
1160
sewardjd140e442002-05-29 01:21:19 +00001161static __inline__
1162void __my_pthread_testcancel(void)
sewardj853f55d2002-04-26 00:27:53 +00001163{
sewardj20917d82002-05-28 01:36:45 +00001164 int res;
njn25e49d8e72002-09-23 09:36:25 +00001165 ensure_valgrind("__my_pthread_testcancel");
sewardj20917d82002-05-28 01:36:45 +00001166 VALGRIND_MAGIC_SEQUENCE(res, (-1) /* default */,
1167 VG_USERREQ__TESTCANCEL,
1168 0, 0, 0, 0);
sewardj2d94c112002-06-03 01:25:54 +00001169 my_assert(res == 0);
sewardj853f55d2002-04-26 00:27:53 +00001170}
1171
sewardjd140e442002-05-29 01:21:19 +00001172void pthread_testcancel ( void )
1173{
1174 __my_pthread_testcancel();
1175}
1176
sewardj20917d82002-05-28 01:36:45 +00001177
sewardjef037c72002-05-30 00:40:03 +00001178/* Not really sure what this is for. I suspect for doing the POSIX
1179 requirements for fork() and exec(). We do this internally anyway
1180 whenever those syscalls are observed, so this could be superfluous,
1181 but hey ...
1182*/
sewardj853f55d2002-04-26 00:27:53 +00001183void __pthread_kill_other_threads_np ( void )
1184{
sewardjef037c72002-05-30 00:40:03 +00001185 int res;
1186 ensure_valgrind("__pthread_kill_other_threads_np");
1187 VALGRIND_MAGIC_SEQUENCE(res, (-1) /* default */,
1188 VG_USERREQ__NUKE_OTHER_THREADS,
1189 0, 0, 0, 0);
sewardj2d94c112002-06-03 01:25:54 +00001190 my_assert(res == 0);
sewardj853f55d2002-04-26 00:27:53 +00001191}
1192
sewardje663cb92002-04-12 10:26:32 +00001193
sewardjf8f819e2002-04-17 23:21:37 +00001194/* ---------------------------------------------------
sewardjb48e5002002-05-13 00:16:03 +00001195 SIGNALS
1196 ------------------------------------------------ */
1197
1198#include <signal.h>
1199
1200int pthread_sigmask(int how, const sigset_t *newmask,
1201 sigset_t *oldmask)
1202{
1203 int res;
1204
1205 /* A bit subtle, because the scheduler expects newmask and oldmask
1206 to be vki_sigset_t* rather than sigset_t*, and the two are
1207 different. Fortunately the first 64 bits of a sigset_t are
1208 exactly a vki_sigset_t, so we just pass the pointers through
1209 unmodified. Haaaack!
1210
1211 Also mash the how value so that the SIG_ constants from glibc
sewardj018f7622002-05-15 21:13:39 +00001212 constants to VKI_ constants, so that the former do not have to
1213 be included into vg_scheduler.c. */
sewardjb48e5002002-05-13 00:16:03 +00001214
1215 ensure_valgrind("pthread_sigmask");
1216
1217 switch (how) {
sewardj018f7622002-05-15 21:13:39 +00001218 case SIG_SETMASK: how = VKI_SIG_SETMASK; break;
1219 case SIG_BLOCK: how = VKI_SIG_BLOCK; break;
1220 case SIG_UNBLOCK: how = VKI_SIG_UNBLOCK; break;
sewardj4dced352002-06-04 22:54:20 +00001221 default: pthread_error("pthread_sigmask: invalid how");
1222 return EINVAL;
sewardjb48e5002002-05-13 00:16:03 +00001223 }
1224
1225 /* Crude check */
1226 if (newmask == NULL)
1227 return EFAULT;
1228
1229 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
1230 VG_USERREQ__PTHREAD_SIGMASK,
1231 how, newmask, oldmask, 0);
1232
1233 /* The scheduler tells us of any memory violations. */
1234 return res == 0 ? 0 : EFAULT;
1235}
1236
1237
1238int sigwait ( const sigset_t* set, int* sig )
1239{
1240 int res;
1241 ensure_valgrind("sigwait");
1242 /* As with pthread_sigmask we deliberately confuse sigset_t with
1243 vki_ksigset_t. */
1244 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
1245 VG_USERREQ__SIGWAIT,
1246 set, sig, 0, 0);
1247 return res;
1248}
1249
1250
sewardj018f7622002-05-15 21:13:39 +00001251int pthread_kill(pthread_t thread, int signo)
1252{
1253 int res;
1254 ensure_valgrind("pthread_kill");
1255 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
1256 VG_USERREQ__PTHREAD_KILL,
1257 thread, signo, 0, 0);
1258 return res;
1259}
1260
1261
sewardj3665ded2002-05-16 16:57:25 +00001262/* Copied verbatim from Linuxthreads */
1263/* Redefine raise() to send signal to calling thread only,
1264 as per POSIX 1003.1c */
1265int raise (int sig)
1266{
1267 int retcode = pthread_kill(pthread_self(), sig);
sewardj4dced352002-06-04 22:54:20 +00001268 if (retcode == 0) {
sewardj3665ded2002-05-16 16:57:25 +00001269 return 0;
sewardj4dced352002-06-04 22:54:20 +00001270 } else {
sewardj3665ded2002-05-16 16:57:25 +00001271 errno = retcode;
1272 return -1;
1273 }
1274}
1275
1276
sewardj9a2224b2002-06-19 10:17:40 +00001277int pause ( void )
1278{
1279 unsigned int n_orig, n_now;
1280 struct vki_timespec nanosleep_interval;
1281 ensure_valgrind("pause");
1282
1283 /* This is surely a cancellation point. */
1284 __my_pthread_testcancel();
1285
1286 VALGRIND_MAGIC_SEQUENCE(n_orig, 0xFFFFFFFF /* default */,
1287 VG_USERREQ__GET_N_SIGS_RETURNED,
1288 0, 0, 0, 0);
1289 my_assert(n_orig != 0xFFFFFFFF);
1290
1291 while (1) {
1292 VALGRIND_MAGIC_SEQUENCE(n_now, 0xFFFFFFFF /* default */,
1293 VG_USERREQ__GET_N_SIGS_RETURNED,
1294 0, 0, 0, 0);
1295 my_assert(n_now != 0xFFFFFFFF);
1296 my_assert(n_now >= n_orig);
1297 if (n_now != n_orig) break;
1298
1299 nanosleep_interval.tv_sec = 0;
njn25e49d8e72002-09-23 09:36:25 +00001300 nanosleep_interval.tv_nsec = 12 * 1000 * 1000; /* 12 milliseconds */
sewardj9a2224b2002-06-19 10:17:40 +00001301 /* It's critical here that valgrind's nanosleep implementation
1302 is nonblocking. */
1303 (void)my_do_syscall2(__NR_nanosleep,
1304 (int)(&nanosleep_interval), (int)NULL);
1305 }
1306
1307 * (__errno_location()) = EINTR;
1308 return -1;
1309}
1310
1311
sewardjb48e5002002-05-13 00:16:03 +00001312/* ---------------------------------------------------
sewardjf8f819e2002-04-17 23:21:37 +00001313 THREAD-SPECIFICs
1314 ------------------------------------------------ */
sewardj5e5fa512002-04-14 13:13:05 +00001315
sewardj00a66b12002-10-12 16:42:35 +00001316static
1317int key_is_valid (pthread_key_t key)
1318{
1319 int res;
1320 VALGRIND_MAGIC_SEQUENCE(res, 2 /* default */,
1321 VG_USERREQ__PTHREAD_KEY_VALIDATE,
1322 key, 0, 0, 0);
1323 my_assert(res != 2);
1324 return res;
1325}
1326
1327
1328/* Returns NULL if thread is invalid. Otherwise, if the thread
1329 already has a specifics area, return that. Otherwise allocate it
1330 one. */
1331static
1332void** get_or_allocate_specifics_ptr ( pthread_t thread )
1333{
1334 int res, i;
1335 void** specifics_ptr;
1336 ensure_valgrind("get_or_allocate_specifics_ptr");
1337
1338 /* Returns zero if the thread has no specific_ptr. One if thread
1339 is invalid. Otherwise, the specific_ptr value. This is
1340 allocated with my_malloc and so is aligned and cannot be
1341 confused with 1 or 3. */
1342 VALGRIND_MAGIC_SEQUENCE(specifics_ptr, 3 /* default */,
1343 VG_USERREQ__PTHREAD_GETSPECIFIC_PTR,
1344 thread, 0, 0, 0);
1345 my_assert(specifics_ptr != (void**)3);
1346
1347 if (specifics_ptr == (void**)1)
1348 return NULL; /* invalid thread */
1349
1350 if (specifics_ptr != NULL)
1351 return specifics_ptr; /* already has a specifics ptr. */
1352
1353 /* None yet ... allocate a new one. Should never fail. */
1354 specifics_ptr = my_malloc( VG_N_THREAD_KEYS * sizeof(void*) );
1355 my_assert(specifics_ptr != NULL);
1356
1357 VALGRIND_MAGIC_SEQUENCE(res, -1 /* default */,
1358 VG_USERREQ__PTHREAD_SETSPECIFIC_PTR,
1359 specifics_ptr, 0, 0, 0);
1360 my_assert(res == 0);
1361
1362 /* POSIX sez: "Upon thread creation, the value NULL shall be
1363 associated with all defined keys in the new thread." This
1364 allocation is in effect a delayed allocation of the specific
1365 data for a thread, at its first-use. Hence we initialise it
1366 here. */
1367 for (i = 0; i < VG_N_THREAD_KEYS; i++) {
1368 specifics_ptr[i] = NULL;
1369 }
1370
1371 return specifics_ptr;
1372}
1373
1374
sewardj5905fae2002-04-26 13:25:00 +00001375int __pthread_key_create(pthread_key_t *key,
1376 void (*destr_function) (void *))
sewardj5e5fa512002-04-14 13:13:05 +00001377{
sewardj00a66b12002-10-12 16:42:35 +00001378 void** specifics_ptr;
1379 int res, i;
sewardj5f07b662002-04-23 16:52:51 +00001380 ensure_valgrind("pthread_key_create");
sewardj00a66b12002-10-12 16:42:35 +00001381
1382 /* This writes *key if successful. It should never fail. */
1383 VALGRIND_MAGIC_SEQUENCE(res, 1 /* default */,
sewardj5f07b662002-04-23 16:52:51 +00001384 VG_USERREQ__PTHREAD_KEY_CREATE,
1385 key, destr_function, 0, 0);
sewardj00a66b12002-10-12 16:42:35 +00001386 my_assert(res == 0);
1387
1388 /* POSIX sez: "Upon key creation, the value NULL shall be
1389 associated with the new key in all active threads." */
1390 for (i = 0; i < VG_N_THREADS; i++) {
1391 specifics_ptr = get_or_allocate_specifics_ptr(i);
1392 /* we get NULL if i is an invalid thread. */
1393 if (specifics_ptr != NULL)
1394 specifics_ptr[*key] = NULL;
1395 }
1396
sewardj5f07b662002-04-23 16:52:51 +00001397 return res;
sewardj5e5fa512002-04-14 13:13:05 +00001398}
1399
1400int pthread_key_delete(pthread_key_t key)
1401{
sewardj00a66b12002-10-12 16:42:35 +00001402 int res;
1403 ensure_valgrind("pthread_key_create");
1404 if (!key_is_valid(key))
1405 return EINVAL;
1406 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
1407 VG_USERREQ__PTHREAD_KEY_DELETE,
1408 key, 0, 0, 0);
1409 my_assert(res == 0);
sewardj5e5fa512002-04-14 13:13:05 +00001410 return 0;
1411}
1412
sewardj5905fae2002-04-26 13:25:00 +00001413int __pthread_setspecific(pthread_key_t key, const void *pointer)
sewardj5e5fa512002-04-14 13:13:05 +00001414{
sewardj00a66b12002-10-12 16:42:35 +00001415 void** specifics_ptr;
sewardj5f07b662002-04-23 16:52:51 +00001416 ensure_valgrind("pthread_setspecific");
sewardj00a66b12002-10-12 16:42:35 +00001417
1418 if (!key_is_valid(key))
1419 return EINVAL;
1420
1421 specifics_ptr = get_or_allocate_specifics_ptr(pthread_self());
1422 specifics_ptr[key] = (void*)pointer;
1423 return 0;
sewardj5e5fa512002-04-14 13:13:05 +00001424}
1425
sewardj5905fae2002-04-26 13:25:00 +00001426void * __pthread_getspecific(pthread_key_t key)
sewardj5e5fa512002-04-14 13:13:05 +00001427{
sewardj00a66b12002-10-12 16:42:35 +00001428 void** specifics_ptr;
sewardj5f07b662002-04-23 16:52:51 +00001429 ensure_valgrind("pthread_getspecific");
sewardj00a66b12002-10-12 16:42:35 +00001430
1431 if (!key_is_valid(key))
1432 return NULL;
1433
1434 specifics_ptr = get_or_allocate_specifics_ptr(pthread_self());
1435 return specifics_ptr[key];
1436}
1437
1438
sewardj9aa918d2002-10-20 16:25:55 +00001439#ifdef GLIBC_2_3
sewardj00a66b12002-10-12 16:42:35 +00001440static
1441void ** __pthread_getspecific_addr(pthread_key_t key)
1442{
1443 void** specifics_ptr;
1444 ensure_valgrind("pthread_getspecific_addr");
1445
1446 if (!key_is_valid(key))
1447 return NULL;
1448
1449 specifics_ptr = get_or_allocate_specifics_ptr(pthread_self());
1450 return &(specifics_ptr[key]);
sewardj5e5fa512002-04-14 13:13:05 +00001451}
sewardj9aa918d2002-10-20 16:25:55 +00001452#endif
sewardjf8f819e2002-04-17 23:21:37 +00001453
1454/* ---------------------------------------------------
sewardj89d3d852002-04-24 19:21:39 +00001455 ONCEry
1456 ------------------------------------------------ */
1457
1458static pthread_mutex_t once_masterlock = PTHREAD_MUTEX_INITIALIZER;
1459
1460
sewardj5905fae2002-04-26 13:25:00 +00001461int __pthread_once ( pthread_once_t *once_control,
1462 void (*init_routine) (void) )
sewardj89d3d852002-04-24 19:21:39 +00001463{
1464 int res;
1465 ensure_valgrind("pthread_once");
1466
sewardj68b2dd92002-05-10 21:03:56 +00001467 res = __pthread_mutex_lock(&once_masterlock);
sewardj89d3d852002-04-24 19:21:39 +00001468
sewardj68b2dd92002-05-10 21:03:56 +00001469 if (res != 0) {
sewardj89d3d852002-04-24 19:21:39 +00001470 barf("pthread_once: Looks like your program's "
1471 "init routine calls back to pthread_once() ?!");
sewardj68b2dd92002-05-10 21:03:56 +00001472 }
sewardj89d3d852002-04-24 19:21:39 +00001473
1474 if (*once_control == 0) {
1475 *once_control = 1;
1476 init_routine();
1477 }
1478
sewardj68b2dd92002-05-10 21:03:56 +00001479 __pthread_mutex_unlock(&once_masterlock);
sewardj89d3d852002-04-24 19:21:39 +00001480
1481 return 0;
1482}
1483
1484
1485/* ---------------------------------------------------
sewardj853f55d2002-04-26 00:27:53 +00001486 MISC
1487 ------------------------------------------------ */
1488
sewardj2cb00342002-06-28 01:46:26 +00001489static pthread_mutex_t pthread_atfork_lock
1490 = PTHREAD_MUTEX_INITIALIZER;
1491
sewardj5905fae2002-04-26 13:25:00 +00001492int __pthread_atfork ( void (*prepare)(void),
1493 void (*parent)(void),
1494 void (*child)(void) )
sewardj853f55d2002-04-26 00:27:53 +00001495{
sewardj2cb00342002-06-28 01:46:26 +00001496 int n, res;
1497 ForkHandlerEntry entry;
1498
1499 ensure_valgrind("pthread_atfork");
1500 __pthread_mutex_lock(&pthread_atfork_lock);
1501
1502 /* Fetch old counter */
1503 VALGRIND_MAGIC_SEQUENCE(n, -2 /* default */,
1504 VG_USERREQ__GET_FHSTACK_USED,
1505 0, 0, 0, 0);
1506 my_assert(n >= 0 && n < VG_N_FORKHANDLERSTACK);
1507 if (n == VG_N_FORKHANDLERSTACK-1)
1508 barf("pthread_atfork: VG_N_FORKHANDLERSTACK is too low; "
1509 "increase and recompile");
1510
1511 /* Add entry */
1512 entry.prepare = *prepare;
1513 entry.parent = *parent;
1514 entry.child = *child;
1515 VALGRIND_MAGIC_SEQUENCE(res, -2 /* default */,
1516 VG_USERREQ__SET_FHSTACK_ENTRY,
1517 n, &entry, 0, 0);
1518 my_assert(res == 0);
1519
1520 /* Bump counter */
1521 VALGRIND_MAGIC_SEQUENCE(res, -2 /* default */,
1522 VG_USERREQ__SET_FHSTACK_USED,
1523 n+1, 0, 0, 0);
1524 my_assert(res == 0);
1525
1526 __pthread_mutex_unlock(&pthread_atfork_lock);
1527 return 0;
sewardj853f55d2002-04-26 00:27:53 +00001528}
1529
1530
sewardjbb990782002-05-08 02:01:14 +00001531__attribute__((weak))
1532void __pthread_initialize ( void )
1533{
sewardjbea1caa2002-05-10 23:20:58 +00001534 ensure_valgrind("__pthread_initialize");
sewardjbb990782002-05-08 02:01:14 +00001535}
1536
1537
sewardj853f55d2002-04-26 00:27:53 +00001538/* ---------------------------------------------------
sewardj3b13f0e2002-04-25 20:17:29 +00001539 LIBRARY-PRIVATE THREAD SPECIFIC STATE
sewardjf8f819e2002-04-17 23:21:37 +00001540 ------------------------------------------------ */
1541
sewardj3b13f0e2002-04-25 20:17:29 +00001542#include <resolv.h>
1543static int thread_specific_errno[VG_N_THREADS];
1544static int thread_specific_h_errno[VG_N_THREADS];
1545static struct __res_state
1546 thread_specific_res_state[VG_N_THREADS];
sewardjf8f819e2002-04-17 23:21:37 +00001547
sewardj3b13f0e2002-04-25 20:17:29 +00001548int* __errno_location ( void )
sewardjf8f819e2002-04-17 23:21:37 +00001549{
1550 int tid;
sewardj3b13f0e2002-04-25 20:17:29 +00001551 /* ensure_valgrind("__errno_location"); */
1552 VALGRIND_MAGIC_SEQUENCE(tid, 1 /* default */,
sewardjf8f819e2002-04-17 23:21:37 +00001553 VG_USERREQ__PTHREAD_GET_THREADID,
1554 0, 0, 0, 0);
sewardj3b13f0e2002-04-25 20:17:29 +00001555 /* 'cos I'm paranoid ... */
sewardj439d45e2002-05-03 20:43:10 +00001556 if (tid < 1 || tid >= VG_N_THREADS)
sewardj3b13f0e2002-04-25 20:17:29 +00001557 barf("__errno_location: invalid ThreadId");
1558 return & thread_specific_errno[tid];
1559}
1560
1561int* __h_errno_location ( void )
1562{
1563 int tid;
1564 /* ensure_valgrind("__h_errno_location"); */
1565 VALGRIND_MAGIC_SEQUENCE(tid, 1 /* default */,
1566 VG_USERREQ__PTHREAD_GET_THREADID,
1567 0, 0, 0, 0);
1568 /* 'cos I'm paranoid ... */
sewardj439d45e2002-05-03 20:43:10 +00001569 if (tid < 1 || tid >= VG_N_THREADS)
sewardj3b13f0e2002-04-25 20:17:29 +00001570 barf("__h_errno_location: invalid ThreadId");
1571 return & thread_specific_h_errno[tid];
1572}
1573
sewardjb0ff1032002-08-06 09:02:53 +00001574
1575#undef _res
1576extern struct __res_state _res;
1577
sewardj3b13f0e2002-04-25 20:17:29 +00001578struct __res_state* __res_state ( void )
1579{
1580 int tid;
1581 /* ensure_valgrind("__res_state"); */
1582 VALGRIND_MAGIC_SEQUENCE(tid, 1 /* default */,
1583 VG_USERREQ__PTHREAD_GET_THREADID,
1584 0, 0, 0, 0);
1585 /* 'cos I'm paranoid ... */
sewardj439d45e2002-05-03 20:43:10 +00001586 if (tid < 1 || tid >= VG_N_THREADS)
sewardj3b13f0e2002-04-25 20:17:29 +00001587 barf("__res_state: invalid ThreadId");
sewardjb0ff1032002-08-06 09:02:53 +00001588 if (tid == 1)
1589 return & _res;
sewardj3b13f0e2002-04-25 20:17:29 +00001590 return & thread_specific_res_state[tid];
sewardjf8f819e2002-04-17 23:21:37 +00001591}
1592
1593
sewardj5716dbb2002-04-26 03:28:18 +00001594/* ---------------------------------------------------
1595 LIBC-PRIVATE SPECIFIC DATA
1596 ------------------------------------------------ */
1597
1598/* Relies on assumption that initial private data is NULL. This
1599 should be fixed somehow. */
1600
njn25e49d8e72002-09-23 09:36:25 +00001601/* The allowable keys (indices) (all 3 of them).
sewardj5716dbb2002-04-26 03:28:18 +00001602 From sysdeps/pthread/bits/libc-tsd.h
1603*/
sewardjcb7f08a2002-10-02 09:41:49 +00001604/* as per glibc anoncvs HEAD of 20021001. */
sewardj5716dbb2002-04-26 03:28:18 +00001605enum __libc_tsd_key_t { _LIBC_TSD_KEY_MALLOC = 0,
1606 _LIBC_TSD_KEY_DL_ERROR,
njn25e49d8e72002-09-23 09:36:25 +00001607 _LIBC_TSD_KEY_RPC_VARS,
sewardjcb7f08a2002-10-02 09:41:49 +00001608 _LIBC_TSD_KEY_LOCALE,
1609 _LIBC_TSD_KEY_CTYPE_B,
1610 _LIBC_TSD_KEY_CTYPE_TOLOWER,
1611 _LIBC_TSD_KEY_CTYPE_TOUPPER,
sewardj5716dbb2002-04-26 03:28:18 +00001612 _LIBC_TSD_KEY_N };
1613
1614/* Auto-initialising subsystem. libc_specifics_inited is set
1615 after initialisation. libc_specifics_inited_mx guards it. */
1616static int libc_specifics_inited = 0;
1617static pthread_mutex_t libc_specifics_inited_mx = PTHREAD_MUTEX_INITIALIZER;
1618
sewardj00a66b12002-10-12 16:42:35 +00001619
sewardj5716dbb2002-04-26 03:28:18 +00001620/* These are the keys we must initialise the first time. */
sewardjcb7f08a2002-10-02 09:41:49 +00001621static pthread_key_t libc_specifics_keys[_LIBC_TSD_KEY_N];
sewardj5716dbb2002-04-26 03:28:18 +00001622
sewardj00a66b12002-10-12 16:42:35 +00001623
sewardjcb7f08a2002-10-02 09:41:49 +00001624/* Initialise the keys, if they are not already initialised. */
sewardj5716dbb2002-04-26 03:28:18 +00001625static
1626void init_libc_tsd_keys ( void )
1627{
1628 int res, i;
1629 pthread_key_t k;
1630
sewardj08c7f012002-10-07 23:56:55 +00001631 /* Don't fall into deadlock if we get called again whilst we still
1632 hold the lock, via the __uselocale() call herein. */
1633 if (libc_specifics_inited != 0)
1634 return;
1635
1636 /* Take the lock. */
sewardj00a66b12002-10-12 16:42:35 +00001637 res = __pthread_mutex_lock(&libc_specifics_inited_mx);
sewardj5716dbb2002-04-26 03:28:18 +00001638 if (res != 0) barf("init_libc_tsd_keys: lock");
1639
sewardj08c7f012002-10-07 23:56:55 +00001640 /* Now test again, to be sure there is no mistake. */
1641 if (libc_specifics_inited != 0) {
sewardj00a66b12002-10-12 16:42:35 +00001642 res = __pthread_mutex_unlock(&libc_specifics_inited_mx);
sewardj08c7f012002-10-07 23:56:55 +00001643 if (res != 0) barf("init_libc_tsd_keys: unlock(1)");
1644 return;
sewardj5716dbb2002-04-26 03:28:18 +00001645 }
1646
sewardj08c7f012002-10-07 23:56:55 +00001647 /* Actually do the initialisation. */
1648 /* printf("INIT libc specifics\n"); */
1649 for (i = 0; i < _LIBC_TSD_KEY_N; i++) {
sewardj00a66b12002-10-12 16:42:35 +00001650 res = __pthread_key_create(&k, NULL);
sewardj08c7f012002-10-07 23:56:55 +00001651 if (res != 0) barf("init_libc_tsd_keys: create");
1652 libc_specifics_keys[i] = k;
1653 }
1654
1655 /* Signify init done. */
1656 libc_specifics_inited = 1;
1657
1658# ifdef GLIBC_2_3
1659 /* Set the initialising thread's locale to the global (default)
sewardj00a66b12002-10-12 16:42:35 +00001660 locale. A hack in support of glibc-2.3. This does the biz for
1661 the root thread. For all other threads we run this in
1662 thread_wrapper(), which does the real work of
1663 pthread_create(). */
1664 /* assert that we are the root thread. I don't know if this is
1665 really a valid assertion to make; if it breaks I'll reconsider
1666 it. */
1667 my_assert(pthread_self() == 1);
sewardj08c7f012002-10-07 23:56:55 +00001668 __uselocale(LC_GLOBAL_LOCALE);
1669# endif
1670
1671 /* Unlock and return. */
sewardj00a66b12002-10-12 16:42:35 +00001672 res = __pthread_mutex_unlock(&libc_specifics_inited_mx);
sewardj5716dbb2002-04-26 03:28:18 +00001673 if (res != 0) barf("init_libc_tsd_keys: unlock");
1674}
1675
1676
1677static int
1678libc_internal_tsd_set ( enum __libc_tsd_key_t key,
1679 const void * pointer )
1680{
sewardjcb7f08a2002-10-02 09:41:49 +00001681 int res;
sewardj5716dbb2002-04-26 03:28:18 +00001682 /* printf("SET SET SET key %d ptr %p\n", key, pointer); */
sewardjcb7f08a2002-10-02 09:41:49 +00001683 if (key < _LIBC_TSD_KEY_MALLOC || key >= _LIBC_TSD_KEY_N)
sewardj5716dbb2002-04-26 03:28:18 +00001684 barf("libc_internal_tsd_set: invalid key");
1685 init_libc_tsd_keys();
sewardj00a66b12002-10-12 16:42:35 +00001686 res = __pthread_setspecific(libc_specifics_keys[key], pointer);
sewardj5716dbb2002-04-26 03:28:18 +00001687 if (res != 0) barf("libc_internal_tsd_set: setspecific failed");
1688 return 0;
1689}
1690
1691static void *
1692libc_internal_tsd_get ( enum __libc_tsd_key_t key )
1693{
sewardjcb7f08a2002-10-02 09:41:49 +00001694 void* v;
sewardj5716dbb2002-04-26 03:28:18 +00001695 /* printf("GET GET GET key %d\n", key); */
sewardjcb7f08a2002-10-02 09:41:49 +00001696 if (key < _LIBC_TSD_KEY_MALLOC || key >= _LIBC_TSD_KEY_N)
sewardj5716dbb2002-04-26 03:28:18 +00001697 barf("libc_internal_tsd_get: invalid key");
1698 init_libc_tsd_keys();
sewardj00a66b12002-10-12 16:42:35 +00001699 v = __pthread_getspecific(libc_specifics_keys[key]);
sewardj5716dbb2002-04-26 03:28:18 +00001700 /* if (v == NULL) barf("libc_internal_tsd_set: getspecific failed"); */
1701 return v;
1702}
1703
1704
sewardj70adeb22002-04-27 01:35:38 +00001705int (*__libc_internal_tsd_set)
1706 (enum __libc_tsd_key_t key, const void * pointer)
1707 = libc_internal_tsd_set;
sewardj5716dbb2002-04-26 03:28:18 +00001708
sewardj70adeb22002-04-27 01:35:38 +00001709void* (*__libc_internal_tsd_get)
1710 (enum __libc_tsd_key_t key)
1711 = libc_internal_tsd_get;
sewardj5716dbb2002-04-26 03:28:18 +00001712
1713
sewardj00a66b12002-10-12 16:42:35 +00001714#ifdef GLIBC_2_3
1715/* This one was first spotted be me in the glibc-2.2.93 sources. */
1716static void**
1717libc_internal_tsd_address ( enum __libc_tsd_key_t key )
1718{
1719 void** v;
1720 /* printf("ADDR ADDR ADDR key %d\n", key); */
1721 if (key < _LIBC_TSD_KEY_MALLOC || key >= _LIBC_TSD_KEY_N)
1722 barf("libc_internal_tsd_address: invalid key");
1723 init_libc_tsd_keys();
1724 v = __pthread_getspecific_addr(libc_specifics_keys[key]);
1725 return v;
1726}
1727
1728void ** (*__libc_internal_tsd_address)
1729 (enum __libc_tsd_key_t key)
1730 = libc_internal_tsd_address;
1731#endif
1732
1733
sewardje663cb92002-04-12 10:26:32 +00001734/* ---------------------------------------------------------------------
1735 These are here (I think) because they are deemed cancellation
1736 points by POSIX. For the moment we'll simply pass the call along
1737 to the corresponding thread-unaware (?) libc routine.
1738 ------------------------------------------------------------------ */
1739
sewardje663cb92002-04-12 10:26:32 +00001740#include <stdlib.h>
sewardje663cb92002-04-12 10:26:32 +00001741#include <sys/types.h>
1742#include <sys/socket.h>
1743
sewardjd529a442002-05-04 19:49:21 +00001744#ifdef GLIBC_2_1
1745extern
1746int __sigaction
1747 (int signum,
1748 const struct sigaction *act,
1749 struct sigaction *oldact);
1750#else
sewardje663cb92002-04-12 10:26:32 +00001751extern
1752int __libc_sigaction
1753 (int signum,
1754 const struct sigaction *act,
1755 struct sigaction *oldact);
sewardjd529a442002-05-04 19:49:21 +00001756#endif
sewardje663cb92002-04-12 10:26:32 +00001757int sigaction(int signum,
1758 const struct sigaction *act,
1759 struct sigaction *oldact)
1760{
sewardjd140e442002-05-29 01:21:19 +00001761 __my_pthread_testcancel();
sewardj2a1dcce2002-04-22 12:45:25 +00001762# ifdef GLIBC_2_1
1763 return __sigaction(signum, act, oldact);
1764# else
sewardj45b4b372002-04-16 22:50:32 +00001765 return __libc_sigaction(signum, act, oldact);
sewardj2a1dcce2002-04-22 12:45:25 +00001766# endif
sewardje663cb92002-04-12 10:26:32 +00001767}
1768
1769
1770extern
1771int __libc_connect(int sockfd,
1772 const struct sockaddr *serv_addr,
1773 socklen_t addrlen);
sewardj5905fae2002-04-26 13:25:00 +00001774__attribute__((weak))
sewardje663cb92002-04-12 10:26:32 +00001775int connect(int sockfd,
1776 const struct sockaddr *serv_addr,
1777 socklen_t addrlen)
1778{
sewardjd140e442002-05-29 01:21:19 +00001779 __my_pthread_testcancel();
sewardj45b4b372002-04-16 22:50:32 +00001780 return __libc_connect(sockfd, serv_addr, addrlen);
sewardje663cb92002-04-12 10:26:32 +00001781}
1782
1783
1784extern
1785int __libc_fcntl(int fd, int cmd, long arg);
sewardj5905fae2002-04-26 13:25:00 +00001786__attribute__((weak))
sewardje663cb92002-04-12 10:26:32 +00001787int fcntl(int fd, int cmd, long arg)
1788{
sewardjd140e442002-05-29 01:21:19 +00001789 __my_pthread_testcancel();
sewardj45b4b372002-04-16 22:50:32 +00001790 return __libc_fcntl(fd, cmd, arg);
sewardje663cb92002-04-12 10:26:32 +00001791}
1792
1793
1794extern
1795ssize_t __libc_write(int fd, const void *buf, size_t count);
sewardj5905fae2002-04-26 13:25:00 +00001796__attribute__((weak))
sewardje663cb92002-04-12 10:26:32 +00001797ssize_t write(int fd, const void *buf, size_t count)
1798{
sewardjd140e442002-05-29 01:21:19 +00001799 __my_pthread_testcancel();
sewardj45b4b372002-04-16 22:50:32 +00001800 return __libc_write(fd, buf, count);
sewardje663cb92002-04-12 10:26:32 +00001801}
1802
1803
1804extern
1805ssize_t __libc_read(int fd, void *buf, size_t count);
sewardj5905fae2002-04-26 13:25:00 +00001806__attribute__((weak))
sewardje663cb92002-04-12 10:26:32 +00001807ssize_t read(int fd, void *buf, size_t count)
1808{
sewardjd140e442002-05-29 01:21:19 +00001809 __my_pthread_testcancel();
sewardj45b4b372002-04-16 22:50:32 +00001810 return __libc_read(fd, buf, count);
sewardje663cb92002-04-12 10:26:32 +00001811}
1812
sewardjf912dfc2002-11-13 21:51:10 +00001813/*
1814 * Ugh, this is horrible but here goes:
1815 *
1816 * Open of a named pipe (fifo file) can block. In a threaded program,
1817 * this means that the whole thing can block. We therefore need to
1818 * make the open appear to block to the caller, but still keep polling
1819 * for everyone else.
1820 *
1821 * There are four cases:
1822 *
1823 * - the caller asked for O_NONBLOCK. The easy one: we just do it.
1824 *
1825 * - the caller asked for a blocking O_RDONLY open. We open it with
1826 * O_NONBLOCK and then use poll to wait for it to become ready.
1827 *
1828 * - the caller asked for a blocking O_WRONLY open. Unfortunately, this
1829 * will fail with ENXIO when we make it non-blocking. Doubly
1830 * unfortunate is that we can only rely on these semantics if it is
1831 * actually a fifo file; the hack is that if we see that it is a
1832 * O_WRONLY open and we get ENXIO, then stat the path and see if it
1833 * actually is a fifo. This is racy, but it is the best we can do.
1834 * If it is a fifo, then keep trying the open until it works; if not
1835 * just return the error.
1836 *
1837 * - the caller asked for a blocking O_RDWR open. Well, under Linux,
1838 * this never blocks, so we just clear the non-blocking flag and
1839 * return.
1840 *
1841 * This code assumes that for whatever we open, O_NONBLOCK followed by
1842 * a fcntl clearing O_NONBLOCK is the same as opening without
1843 * O_NONBLOCK. Also assumes that stat and fstat have no side-effects.
1844 *
1845 * XXX Should probably put in special cases for some devices as well,
1846 * like serial ports. Unfortunately they don't work like fifos, so
1847 * this logic will become even more tortured. Wait until we really
1848 * need it.
1849 */
1850static inline int _open(const char *pathname, int flags, mode_t mode,
1851 int (*openp)(const char *, int, mode_t))
sewardjbe32e452002-04-24 20:29:58 +00001852{
sewardjf912dfc2002-11-13 21:51:10 +00001853 int fd;
1854 struct stat st;
1855 struct vki_timespec nanosleep_interval;
1856 int saved_errno;
1857
sewardjd140e442002-05-29 01:21:19 +00001858 __my_pthread_testcancel();
sewardjf912dfc2002-11-13 21:51:10 +00001859
1860 /* Assume we can only get O_RDONLY, O_WRONLY or O_RDWR */
1861 my_assert((flags & VKI_O_ACCMODE) != VKI_O_ACCMODE);
1862
1863 for(;;) {
1864 fd = (*openp)(pathname, flags | VKI_O_NONBLOCK, mode);
1865
1866 /* return immediately if caller wanted nonblocking anyway */
1867 if (flags & VKI_O_NONBLOCK)
1868 return fd;
1869
1870 saved_errno = errno;
1871
1872 if (fd != -1)
1873 break; /* open worked */
1874
1875 /* If we got ENXIO and we're opening WRONLY, and it turns out
1876 to really be a FIFO, then poll waiting for open to succeed */
1877 if (errno == ENXIO &&
1878 (flags & VKI_O_ACCMODE) == VKI_O_WRONLY &&
1879 (stat(pathname, &st) == 0 && S_ISFIFO(st.st_mode))) {
1880
1881 /* OK, we're opening a FIFO for writing; sleep and spin */
1882 nanosleep_interval.tv_sec = 0;
1883 nanosleep_interval.tv_nsec = 13 * 1000 * 1000; /* 13 milliseconds */
1884 /* It's critical here that valgrind's nanosleep implementation
1885 is nonblocking. */
1886 (void)my_do_syscall2(__NR_nanosleep,
1887 (int)(&nanosleep_interval), (int)NULL);
1888 } else {
1889 /* it was just an error */
1890 errno = saved_errno;
1891 return -1;
1892 }
1893 }
1894
1895 /* OK, we've got a nonblocking FD for a caller who wants blocking;
1896 reset the flags to what they asked for */
1897 fcntl(fd, VKI_F_SETFL, flags);
1898
1899 /* Return now if one of:
1900 - we were opening O_RDWR (never blocks)
1901 - we opened with O_WRONLY (polling already done)
1902 - the thing we opened wasn't a FIFO after all (or fstat failed)
1903 */
1904 if ((flags & VKI_O_ACCMODE) != VKI_O_RDONLY ||
1905 (fstat(fd, &st) == -1 || !S_ISFIFO(st.st_mode))) {
1906 errno = saved_errno;
1907 return fd;
1908 }
1909
1910 /* OK, drop into the poll loop looking for something to read on the fd */
1911 my_assert((flags & VKI_O_ACCMODE) == VKI_O_RDONLY);
1912 for(;;) {
1913 struct pollfd pollfd;
1914 int res;
1915
1916 pollfd.fd = fd;
1917 pollfd.events = POLLIN;
1918 pollfd.revents = 0;
1919
1920 res = my_do_syscall3(__NR_poll, (int)&pollfd, 1, 0);
1921
1922 my_assert(res == 0 || res == 1);
1923
1924 if (res == 1) {
1925 /* OK, got it.
1926
1927 XXX This is wrong: we're waiting for either something to
1928 read or a HUP on the file descriptor, but the semantics of
1929 fifo open are that we should unblock as soon as someone
1930 simply opens the other end, not that they write something.
1931 With luck this won't matter in practice.
1932 */
1933 my_assert(pollfd.revents & (POLLIN|POLLHUP));
1934 break;
1935 }
1936
1937 /* Still nobody home; sleep and spin */
1938 nanosleep_interval.tv_sec = 0;
1939 nanosleep_interval.tv_nsec = 13 * 1000 * 1000; /* 13 milliseconds */
1940 /* It's critical here that valgrind's nanosleep implementation
1941 is nonblocking. */
1942 (void)my_do_syscall2(__NR_nanosleep,
1943 (int)(&nanosleep_interval), (int)NULL);
1944 }
1945
1946 errno = saved_errno;
1947 return fd;
sewardjbe32e452002-04-24 20:29:58 +00001948}
1949
sewardjf912dfc2002-11-13 21:51:10 +00001950extern
1951int __libc_open64(const char *pathname, int flags, mode_t mode);
1952/* __attribute__((weak)) */
1953int open64(const char *pathname, int flags, mode_t mode)
1954{
1955 return _open(pathname, flags, mode, __libc_open64);
1956}
sewardje663cb92002-04-12 10:26:32 +00001957
1958extern
sewardj853f55d2002-04-26 00:27:53 +00001959int __libc_open(const char *pathname, int flags, mode_t mode);
sewardjf912dfc2002-11-13 21:51:10 +00001960/* __attribute__((weak)) */
sewardj853f55d2002-04-26 00:27:53 +00001961int open(const char *pathname, int flags, mode_t mode)
sewardje663cb92002-04-12 10:26:32 +00001962{
sewardjf912dfc2002-11-13 21:51:10 +00001963 return _open(pathname, flags, mode, __libc_open);
sewardje663cb92002-04-12 10:26:32 +00001964}
1965
sewardje663cb92002-04-12 10:26:32 +00001966extern
1967int __libc_close(int fd);
sewardj5905fae2002-04-26 13:25:00 +00001968__attribute__((weak))
sewardje663cb92002-04-12 10:26:32 +00001969int close(int fd)
1970{
sewardjd140e442002-05-29 01:21:19 +00001971 __my_pthread_testcancel();
sewardj45b4b372002-04-16 22:50:32 +00001972 return __libc_close(fd);
sewardje663cb92002-04-12 10:26:32 +00001973}
1974
1975
1976extern
1977int __libc_accept(int s, struct sockaddr *addr, socklen_t *addrlen);
sewardjf220ccc2002-10-23 21:53:49 +00001978
1979int VGL_(accept)(int s, struct sockaddr *addr, socklen_t *addrlen)
sewardje663cb92002-04-12 10:26:32 +00001980{
sewardjd140e442002-05-29 01:21:19 +00001981 __my_pthread_testcancel();
sewardj705d3cb2002-05-23 13:13:12 +00001982 wait_for_fd_to_be_readable_or_erring(s);
sewardjd140e442002-05-29 01:21:19 +00001983 __my_pthread_testcancel();
sewardj45b4b372002-04-16 22:50:32 +00001984 return __libc_accept(s, addr, addrlen);
sewardje663cb92002-04-12 10:26:32 +00001985}
1986
sewardj0c573af92002-10-23 21:55:01 +00001987extern
1988int __libc_recv(int s, void *buf, size_t len, int flags);
1989
1990int VGL_(recv)(int s, void *buf, size_t len, int flags)
1991{
1992 __my_pthread_testcancel();
1993 wait_for_fd_to_be_readable_or_erring(s);
1994 __my_pthread_testcancel();
1995 return __libc_recv(s, buf, len, flags);
1996}
1997
sewardj2a68e7e2002-11-16 11:04:18 +00001998int VGL_(readv)(int fd, const struct iovec *iov, int count)
1999{
2000 __my_pthread_testcancel();
2001 wait_for_fd_to_be_readable_or_erring(fd);
2002 __my_pthread_testcancel();
2003 return my_do_syscall3(__NR_readv, fd, (unsigned)iov, count);
2004}
2005
2006int VGL_(writev)(int fd, struct iovec *iov, int count)
2007{
2008 __my_pthread_testcancel();
2009 wait_for_fd_to_be_writable_or_erring(fd);
2010 __my_pthread_testcancel();
2011 return my_do_syscall3(__NR_writev, fd, (unsigned)iov, count);
2012}
sewardje663cb92002-04-12 10:26:32 +00002013
2014extern
sewardje663cb92002-04-12 10:26:32 +00002015pid_t __libc_waitpid(pid_t pid, int *status, int options);
sewardj5905fae2002-04-26 13:25:00 +00002016__attribute__((weak))
sewardje663cb92002-04-12 10:26:32 +00002017pid_t waitpid(pid_t pid, int *status, int options)
2018{
sewardjd140e442002-05-29 01:21:19 +00002019 __my_pthread_testcancel();
sewardj45b4b372002-04-16 22:50:32 +00002020 return __libc_waitpid(pid, status, options);
sewardje663cb92002-04-12 10:26:32 +00002021}
2022
2023
2024extern
2025int __libc_nanosleep(const struct timespec *req, struct timespec *rem);
sewardj5905fae2002-04-26 13:25:00 +00002026__attribute__((weak))
sewardje663cb92002-04-12 10:26:32 +00002027int nanosleep(const struct timespec *req, struct timespec *rem)
2028{
sewardjd140e442002-05-29 01:21:19 +00002029 __my_pthread_testcancel();
sewardje663cb92002-04-12 10:26:32 +00002030 return __libc_nanosleep(req, rem);
2031}
2032
sewardjbe32e452002-04-24 20:29:58 +00002033
sewardje663cb92002-04-12 10:26:32 +00002034extern
2035int __libc_fsync(int fd);
sewardj5905fae2002-04-26 13:25:00 +00002036__attribute__((weak))
sewardje663cb92002-04-12 10:26:32 +00002037int fsync(int fd)
2038{
sewardjd140e442002-05-29 01:21:19 +00002039 __my_pthread_testcancel();
sewardj45b4b372002-04-16 22:50:32 +00002040 return __libc_fsync(fd);
sewardje663cb92002-04-12 10:26:32 +00002041}
2042
sewardjbe32e452002-04-24 20:29:58 +00002043
sewardj70c75362002-04-13 04:18:32 +00002044extern
2045off_t __libc_lseek(int fildes, off_t offset, int whence);
sewardj5905fae2002-04-26 13:25:00 +00002046__attribute__((weak))
sewardj70c75362002-04-13 04:18:32 +00002047off_t lseek(int fildes, off_t offset, int whence)
2048{
sewardjd140e442002-05-29 01:21:19 +00002049 __my_pthread_testcancel();
sewardj45b4b372002-04-16 22:50:32 +00002050 return __libc_lseek(fildes, offset, whence);
sewardj70c75362002-04-13 04:18:32 +00002051}
2052
sewardjbe32e452002-04-24 20:29:58 +00002053
2054extern
2055__off64_t __libc_lseek64(int fildes, __off64_t offset, int whence);
sewardj5905fae2002-04-26 13:25:00 +00002056__attribute__((weak))
sewardjbe32e452002-04-24 20:29:58 +00002057__off64_t lseek64(int fildes, __off64_t offset, int whence)
2058{
sewardjd140e442002-05-29 01:21:19 +00002059 __my_pthread_testcancel();
sewardjbe32e452002-04-24 20:29:58 +00002060 return __libc_lseek64(fildes, offset, whence);
2061}
2062
2063
sewardj726c4122002-05-16 23:39:10 +00002064extern
2065ssize_t __libc_pread64 (int __fd, void *__buf, size_t __nbytes,
2066 __off64_t __offset);
2067ssize_t __pread64 (int __fd, void *__buf, size_t __nbytes,
2068 __off64_t __offset)
2069{
sewardjd140e442002-05-29 01:21:19 +00002070 __my_pthread_testcancel();
sewardj726c4122002-05-16 23:39:10 +00002071 return __libc_pread64(__fd, __buf, __nbytes, __offset);
2072}
2073
2074
sewardja18e2102002-05-18 10:43:22 +00002075extern
2076ssize_t __libc_pwrite64 (int __fd, const void *__buf, size_t __nbytes,
2077 __off64_t __offset);
2078ssize_t __pwrite64 (int __fd, const void *__buf, size_t __nbytes,
2079 __off64_t __offset)
2080{
sewardjd140e442002-05-29 01:21:19 +00002081 __my_pthread_testcancel();
sewardja18e2102002-05-18 10:43:22 +00002082 return __libc_pwrite64(__fd, __buf, __nbytes, __offset);
2083}
2084
sewardj726c4122002-05-16 23:39:10 +00002085
sewardj39b93b12002-05-18 10:56:27 +00002086extern
2087ssize_t __libc_pwrite(int fd, const void *buf, size_t count, off_t offset);
2088__attribute__((weak))
2089ssize_t pwrite(int fd, const void *buf, size_t count, off_t offset)
2090{
sewardjd140e442002-05-29 01:21:19 +00002091 __my_pthread_testcancel();
sewardj39b93b12002-05-18 10:56:27 +00002092 return __libc_pwrite(fd, buf, count, offset);
2093}
2094
2095
2096extern
2097ssize_t __libc_pread(int fd, void *buf, size_t count, off_t offset);
2098__attribute__((weak))
2099ssize_t pread(int fd, void *buf, size_t count, off_t offset)
2100{
sewardjd140e442002-05-29 01:21:19 +00002101 __my_pthread_testcancel();
sewardj39b93b12002-05-18 10:56:27 +00002102 return __libc_pread(fd, buf, count, offset);
2103}
2104
2105
sewardj6af4b5d2002-04-16 04:40:49 +00002106extern
2107void __libc_longjmp(jmp_buf env, int val) __attribute((noreturn));
sewardj5905fae2002-04-26 13:25:00 +00002108/* not weak: __attribute__((weak)) */
sewardj6af4b5d2002-04-16 04:40:49 +00002109void longjmp(jmp_buf env, int val)
2110{
2111 __libc_longjmp(env, val);
2112}
2113
sewardjbe32e452002-04-24 20:29:58 +00002114
sewardj436c2db2002-06-18 09:07:54 +00002115extern void __libc_siglongjmp (sigjmp_buf env, int val)
2116 __attribute__ ((noreturn));
2117void siglongjmp(sigjmp_buf env, int val)
2118{
2119 kludged("siglongjmp (cleanup handlers are ignored)");
2120 __libc_siglongjmp(env, val);
2121}
2122
2123
sewardj6af4b5d2002-04-16 04:40:49 +00002124extern
2125int __libc_send(int s, const void *msg, size_t len, int flags);
sewardj5905fae2002-04-26 13:25:00 +00002126__attribute__((weak))
sewardj6af4b5d2002-04-16 04:40:49 +00002127int send(int s, const void *msg, size_t len, int flags)
2128{
sewardjd140e442002-05-29 01:21:19 +00002129 __my_pthread_testcancel();
sewardj6af4b5d2002-04-16 04:40:49 +00002130 return __libc_send(s, msg, len, flags);
2131}
2132
sewardjbe32e452002-04-24 20:29:58 +00002133
sewardj1e8cdc92002-04-18 11:37:52 +00002134extern
2135int __libc_recv(int s, void *buf, size_t len, int flags);
sewardj5905fae2002-04-26 13:25:00 +00002136__attribute__((weak))
sewardj1e8cdc92002-04-18 11:37:52 +00002137int recv(int s, void *buf, size_t len, int flags)
2138{
sewardjd140e442002-05-29 01:21:19 +00002139 __my_pthread_testcancel();
sewardj1d6b3a22002-06-20 07:58:33 +00002140 wait_for_fd_to_be_readable_or_erring(s);
2141 __my_pthread_testcancel();
sewardj1e8cdc92002-04-18 11:37:52 +00002142 return __libc_recv(s, buf, len, flags);
2143}
2144
sewardjbe32e452002-04-24 20:29:58 +00002145
sewardj3665ded2002-05-16 16:57:25 +00002146extern
2147int __libc_sendmsg(int s, const struct msghdr *msg, int flags);
2148__attribute__((weak))
2149int sendmsg(int s, const struct msghdr *msg, int flags)
2150{
sewardjd140e442002-05-29 01:21:19 +00002151 __my_pthread_testcancel();
sewardj3665ded2002-05-16 16:57:25 +00002152 return __libc_sendmsg(s, msg, flags);
2153}
2154
2155
sewardj796d6a22002-04-24 02:28:34 +00002156extern
sewardj59da27a2002-06-06 08:33:54 +00002157int __libc_recvmsg(int s, struct msghdr *msg, int flags);
2158__attribute__((weak))
2159int recvmsg(int s, struct msghdr *msg, int flags)
2160{
2161 __my_pthread_testcancel();
2162 return __libc_recvmsg(s, msg, flags);
2163}
2164
2165
2166extern
sewardj436e0582002-04-26 14:31:40 +00002167int __libc_recvfrom(int s, void *buf, size_t len, int flags,
2168 struct sockaddr *from, socklen_t *fromlen);
2169__attribute__((weak))
2170int recvfrom(int s, void *buf, size_t len, int flags,
2171 struct sockaddr *from, socklen_t *fromlen)
2172{
sewardjd140e442002-05-29 01:21:19 +00002173 __my_pthread_testcancel();
sewardj2e207632002-06-13 17:29:53 +00002174 wait_for_fd_to_be_readable_or_erring(s);
2175 __my_pthread_testcancel();
sewardj436e0582002-04-26 14:31:40 +00002176 return __libc_recvfrom(s, buf, len, flags, from, fromlen);
2177}
2178
2179
2180extern
sewardj796d6a22002-04-24 02:28:34 +00002181int __libc_sendto(int s, const void *msg, size_t len, int flags,
2182 const struct sockaddr *to, socklen_t tolen);
sewardj5905fae2002-04-26 13:25:00 +00002183__attribute__((weak))
sewardj796d6a22002-04-24 02:28:34 +00002184int sendto(int s, const void *msg, size_t len, int flags,
2185 const struct sockaddr *to, socklen_t tolen)
2186{
sewardjd140e442002-05-29 01:21:19 +00002187 __my_pthread_testcancel();
sewardj796d6a22002-04-24 02:28:34 +00002188 return __libc_sendto(s, msg, len, flags, to, tolen);
2189}
2190
sewardjbe32e452002-04-24 20:29:58 +00002191
sewardj369b1702002-04-24 13:28:15 +00002192extern
2193int __libc_system(const char* str);
sewardj5905fae2002-04-26 13:25:00 +00002194__attribute__((weak))
sewardj369b1702002-04-24 13:28:15 +00002195int system(const char* str)
2196{
sewardjd140e442002-05-29 01:21:19 +00002197 __my_pthread_testcancel();
sewardj369b1702002-04-24 13:28:15 +00002198 return __libc_system(str);
2199}
2200
sewardjbe32e452002-04-24 20:29:58 +00002201
sewardjab0b1c32002-04-24 19:26:47 +00002202extern
2203pid_t __libc_wait(int *status);
sewardj5905fae2002-04-26 13:25:00 +00002204__attribute__((weak))
sewardjab0b1c32002-04-24 19:26:47 +00002205pid_t wait(int *status)
2206{
sewardjd140e442002-05-29 01:21:19 +00002207 __my_pthread_testcancel();
sewardjab0b1c32002-04-24 19:26:47 +00002208 return __libc_wait(status);
2209}
2210
sewardj45b4b372002-04-16 22:50:32 +00002211
sewardj67f1d582002-05-24 02:11:32 +00002212extern
2213int __libc_msync(const void *start, size_t length, int flags);
2214__attribute__((weak))
2215int msync(const void *start, size_t length, int flags)
2216{
sewardjd140e442002-05-29 01:21:19 +00002217 __my_pthread_testcancel();
sewardj67f1d582002-05-24 02:11:32 +00002218 return __libc_msync(start, length, flags);
2219}
2220
sewardj5905fae2002-04-26 13:25:00 +00002221
sewardj2cb00342002-06-28 01:46:26 +00002222/*--- fork and its helper ---*/
2223
2224static
2225void run_fork_handlers ( int what )
2226{
2227 ForkHandlerEntry entry;
2228 int n_h, n_handlers, i, res;
2229
2230 my_assert(what == 0 || what == 1 || what == 2);
2231
2232 /* Fetch old counter */
2233 VALGRIND_MAGIC_SEQUENCE(n_handlers, -2 /* default */,
2234 VG_USERREQ__GET_FHSTACK_USED,
2235 0, 0, 0, 0);
2236 my_assert(n_handlers >= 0 && n_handlers < VG_N_FORKHANDLERSTACK);
2237
2238 /* Prepare handlers (what == 0) are called in opposite order of
2239 calls to pthread_atfork. Parent and child handlers are called
2240 in the same order as calls to pthread_atfork. */
2241 if (what == 0)
2242 n_h = n_handlers - 1;
2243 else
2244 n_h = 0;
2245
2246 for (i = 0; i < n_handlers; i++) {
2247 VALGRIND_MAGIC_SEQUENCE(res, -2 /* default */,
2248 VG_USERREQ__GET_FHSTACK_ENTRY,
2249 n_h, &entry, 0, 0);
2250 my_assert(res == 0);
2251 switch (what) {
2252 case 0: if (entry.prepare) entry.prepare();
2253 n_h--; break;
2254 case 1: if (entry.parent) entry.parent();
2255 n_h++; break;
2256 case 2: if (entry.child) entry.child();
2257 n_h++; break;
2258 default: barf("run_fork_handlers: invalid what");
2259 }
2260 }
2261
2262 if (what != 0 /* prepare */) {
2263 /* Empty out the stack. */
2264 VALGRIND_MAGIC_SEQUENCE(res, -2 /* default */,
2265 VG_USERREQ__SET_FHSTACK_USED,
2266 0, 0, 0, 0);
2267 my_assert(res == 0);
2268 }
2269}
2270
2271extern
2272pid_t __libc_fork(void);
2273pid_t __fork(void)
2274{
2275 pid_t pid;
2276 __my_pthread_testcancel();
2277 __pthread_mutex_lock(&pthread_atfork_lock);
2278
2279 run_fork_handlers(0 /* prepare */);
2280 pid = __libc_fork();
2281 if (pid == 0) {
2282 /* I am the child */
2283 run_fork_handlers(2 /* child */);
sewardjd8acdf22002-11-13 21:57:52 +00002284 __pthread_mutex_unlock(&pthread_atfork_lock);
sewardj2cb00342002-06-28 01:46:26 +00002285 __pthread_mutex_init(&pthread_atfork_lock, NULL);
2286 } else {
2287 /* I am the parent */
2288 run_fork_handlers(1 /* parent */);
2289 __pthread_mutex_unlock(&pthread_atfork_lock);
2290 }
2291 return pid;
2292}
2293
2294
njn25e49d8e72002-09-23 09:36:25 +00002295pid_t __vfork(void)
2296{
2297 return __fork();
2298}
sewardj2cb00342002-06-28 01:46:26 +00002299
2300
sewardj3b13f0e2002-04-25 20:17:29 +00002301/* ---------------------------------------------------------------------
2302 Nonblocking implementations of select() and poll(). This stuff will
2303 surely rot your mind.
2304 ------------------------------------------------------------------ */
sewardje663cb92002-04-12 10:26:32 +00002305
sewardj08a4c3f2002-04-13 03:45:44 +00002306/*--------------------------------------------------*/
2307
2308#include "vg_kerneliface.h"
2309
2310static
2311__inline__
2312int is_kerror ( int res )
2313{
2314 if (res >= -4095 && res <= -1)
2315 return 1;
2316 else
2317 return 0;
2318}
2319
2320
2321static
2322int my_do_syscall1 ( int syscallno, int arg1 )
2323{
2324 int __res;
2325 __asm__ volatile ("pushl %%ebx; movl %%edx,%%ebx ; int $0x80 ; popl %%ebx"
2326 : "=a" (__res)
2327 : "0" (syscallno),
2328 "d" (arg1) );
2329 return __res;
2330}
2331
2332static
2333int my_do_syscall2 ( int syscallno,
sewardjf854f472002-04-21 12:19:41 +00002334 int arg1, int arg2 )
sewardj08a4c3f2002-04-13 03:45:44 +00002335{
2336 int __res;
2337 __asm__ volatile ("pushl %%ebx; movl %%edx,%%ebx ; int $0x80 ; popl %%ebx"
2338 : "=a" (__res)
2339 : "0" (syscallno),
2340 "d" (arg1),
2341 "c" (arg2) );
2342 return __res;
2343}
2344
2345static
sewardjf854f472002-04-21 12:19:41 +00002346int my_do_syscall3 ( int syscallno,
2347 int arg1, int arg2, int arg3 )
2348{
2349 int __res;
2350 __asm__ volatile ("pushl %%ebx; movl %%esi,%%ebx ; int $0x80 ; popl %%ebx"
2351 : "=a" (__res)
2352 : "0" (syscallno),
2353 "S" (arg1),
2354 "c" (arg2),
2355 "d" (arg3) );
2356 return __res;
2357}
2358
sewardjd5bef572002-10-23 21:49:33 +00002359static inline
2360int my_do_syscall5 ( int syscallno,
2361 int arg1, int arg2, int arg3, int arg4, int arg5 )
2362{
2363 int __res;
2364 __asm__ volatile ("int $0x80"
2365 : "=a" (__res)
2366 : "0" (syscallno),
2367 "b" (arg1),
2368 "c" (arg2),
2369 "d" (arg3),
2370 "S" (arg4),
2371 "D" (arg5));
2372 return __res;
2373}
2374
sewardjf854f472002-04-21 12:19:41 +00002375static
sewardj08a4c3f2002-04-13 03:45:44 +00002376int do_syscall_select( int n,
2377 vki_fd_set* readfds,
2378 vki_fd_set* writefds,
2379 vki_fd_set* exceptfds,
2380 struct vki_timeval * timeout )
2381{
2382 int res;
2383 int args[5];
2384 args[0] = n;
2385 args[1] = (int)readfds;
2386 args[2] = (int)writefds;
2387 args[3] = (int)exceptfds;
2388 args[4] = (int)timeout;
2389 res = my_do_syscall1(__NR_select, (int)(&(args[0])) );
sewardj02535bc2002-04-21 01:08:26 +00002390 return res;
sewardj08a4c3f2002-04-13 03:45:44 +00002391}
2392
2393
2394/* This is a wrapper round select(), which makes it thread-safe,
2395 meaning that only this thread will block, rather than the entire
2396 process. This wrapper in turn depends on nanosleep() not to block
2397 the entire process, but I think (hope? suspect?) that POSIX
2398 pthreads guarantees that to be the case.
2399
2400 Basic idea is: modify the timeout parameter to select so that it
2401 returns immediately. Poll like this until select returns non-zero,
2402 indicating something interesting happened, or until our time is up.
njn25e49d8e72002-09-23 09:36:25 +00002403 Space out the polls with nanosleeps of say 11 milliseconds, which
sewardj08a4c3f2002-04-13 03:45:44 +00002404 is required to be nonblocking; this allows other threads to run.
sewardj02535bc2002-04-21 01:08:26 +00002405
2406 Assumes:
sewardj2d94c112002-06-03 01:25:54 +00002407 * (checked via my_assert) types fd_set and vki_fd_set are identical.
2408 * (checked via my_assert) types timeval and vki_timeval are identical.
sewardj02535bc2002-04-21 01:08:26 +00002409 * (unchecked) libc error numbers (EINTR etc) are the negation of the
2410 kernel's error numbers (VKI_EINTR etc).
sewardj08a4c3f2002-04-13 03:45:44 +00002411*/
sewardj08a4c3f2002-04-13 03:45:44 +00002412
sewardj7db011a2002-11-13 22:00:20 +00002413int VGL_(select) ( int n,
2414 fd_set *rfds,
2415 fd_set *wfds,
2416 fd_set *xfds,
2417 struct timeval *timeout )
sewardj08a4c3f2002-04-13 03:45:44 +00002418{
sewardj5f07b662002-04-23 16:52:51 +00002419 unsigned int ms_now, ms_end;
sewardj08a4c3f2002-04-13 03:45:44 +00002420 int res;
2421 fd_set rfds_copy;
2422 fd_set wfds_copy;
2423 fd_set xfds_copy;
2424 struct vki_timeval t_now;
sewardj08a4c3f2002-04-13 03:45:44 +00002425 struct vki_timeval zero_timeout;
2426 struct vki_timespec nanosleep_interval;
2427
sewardjd140e442002-05-29 01:21:19 +00002428 __my_pthread_testcancel();
2429
sewardj5f07b662002-04-23 16:52:51 +00002430 /* gcc's complains about ms_end being used uninitialised -- classic
2431 case it can't understand, where ms_end is both defined and used
2432 only if timeout != NULL. Hence ... */
2433 ms_end = 0;
sewardj08a4c3f2002-04-13 03:45:44 +00002434
2435 /* We assume that the kernel and libc data layouts are identical
2436 for the following types. These asserts provide a crude
2437 check. */
2438 if (sizeof(fd_set) != sizeof(vki_fd_set)
2439 || sizeof(struct timeval) != sizeof(struct vki_timeval))
2440 barf("valgrind's hacky non-blocking select(): data sizes error");
2441
sewardj5f07b662002-04-23 16:52:51 +00002442 /* Detect the current time and simultaneously find out if we are
2443 running on Valgrind. */
2444 VALGRIND_MAGIC_SEQUENCE(ms_now, 0xFFFFFFFF /* default */,
2445 VG_USERREQ__READ_MILLISECOND_TIMER,
2446 0, 0, 0, 0);
2447
2448 /* If a zero timeout specified, this call is harmless. Also go
2449 this route if we're not running on Valgrind, for whatever
2450 reason. */
2451 if ( (timeout && timeout->tv_sec == 0 && timeout->tv_usec == 0)
2452 || (ms_now == 0xFFFFFFFF) ) {
sewardj02535bc2002-04-21 01:08:26 +00002453 res = do_syscall_select( n, (vki_fd_set*)rfds,
sewardj08a4c3f2002-04-13 03:45:44 +00002454 (vki_fd_set*)wfds,
2455 (vki_fd_set*)xfds,
2456 (struct vki_timeval*)timeout);
sewardj02535bc2002-04-21 01:08:26 +00002457 if (is_kerror(res)) {
2458 * (__errno_location()) = -res;
2459 return -1;
2460 } else {
2461 return res;
2462 }
2463 }
sewardj08a4c3f2002-04-13 03:45:44 +00002464
sewardj5f07b662002-04-23 16:52:51 +00002465 /* If a timeout was specified, set ms_end to be the end millisecond
2466 counter [wallclock] time. */
sewardj08a4c3f2002-04-13 03:45:44 +00002467 if (timeout) {
2468 res = my_do_syscall2(__NR_gettimeofday, (int)&t_now, (int)NULL);
sewardj2d94c112002-06-03 01:25:54 +00002469 my_assert(res == 0);
sewardj5f07b662002-04-23 16:52:51 +00002470 ms_end = ms_now;
2471 ms_end += (timeout->tv_usec / 1000);
2472 ms_end += (timeout->tv_sec * 1000);
sewardj08a4c3f2002-04-13 03:45:44 +00002473 /* Stay sane ... */
sewardj2d94c112002-06-03 01:25:54 +00002474 my_assert (ms_end >= ms_now);
sewardj08a4c3f2002-04-13 03:45:44 +00002475 }
2476
2477 /* fprintf(stderr, "MY_SELECT: before loop\n"); */
2478
2479 /* Either timeout == NULL, meaning wait indefinitely, or timeout !=
sewardj5f07b662002-04-23 16:52:51 +00002480 NULL, in which case ms_end holds the end time. */
sewardj05bb2c92002-06-26 00:47:17 +00002481
sewardj08a4c3f2002-04-13 03:45:44 +00002482 while (1) {
sewardj05bb2c92002-06-26 00:47:17 +00002483
2484 /* First, do a return-immediately select(). */
sewardj08a4c3f2002-04-13 03:45:44 +00002485
2486 /* These could be trashed each time round the loop, so restore
2487 them each time. */
2488 if (rfds) rfds_copy = *rfds;
2489 if (wfds) wfds_copy = *wfds;
2490 if (xfds) xfds_copy = *xfds;
2491
2492 zero_timeout.tv_sec = zero_timeout.tv_usec = 0;
2493
2494 res = do_syscall_select( n,
2495 rfds ? (vki_fd_set*)(&rfds_copy) : NULL,
2496 wfds ? (vki_fd_set*)(&wfds_copy) : NULL,
2497 xfds ? (vki_fd_set*)(&xfds_copy) : NULL,
2498 & zero_timeout );
sewardj02535bc2002-04-21 01:08:26 +00002499 if (is_kerror(res)) {
2500 /* Some kind of error (including EINTR). Set errno and
sewardj08a4c3f2002-04-13 03:45:44 +00002501 return. The sets are unspecified in this case. */
sewardj02535bc2002-04-21 01:08:26 +00002502 * (__errno_location()) = -res;
2503 return -1;
sewardj08a4c3f2002-04-13 03:45:44 +00002504 }
2505 if (res > 0) {
2506 /* one or more fds is ready. Copy out resulting sets and
2507 return. */
2508 if (rfds) *rfds = rfds_copy;
2509 if (wfds) *wfds = wfds_copy;
2510 if (xfds) *xfds = xfds_copy;
2511 return res;
2512 }
sewardj05bb2c92002-06-26 00:47:17 +00002513
2514 /* Nothing interesting happened, so we go to sleep for a
2515 while. */
2516
sewardj08a4c3f2002-04-13 03:45:44 +00002517 /* fprintf(stderr, "MY_SELECT: nanosleep\n"); */
2518 /* nanosleep and go round again */
sewardj02535bc2002-04-21 01:08:26 +00002519 nanosleep_interval.tv_sec = 0;
njn25e49d8e72002-09-23 09:36:25 +00002520 nanosleep_interval.tv_nsec = 11 * 1000 * 1000; /* 11 milliseconds */
sewardjf854f472002-04-21 12:19:41 +00002521 /* It's critical here that valgrind's nanosleep implementation
2522 is nonblocking. */
sewardj645030e2002-06-06 01:27:39 +00002523 res = my_do_syscall2(__NR_nanosleep,
sewardjf854f472002-04-21 12:19:41 +00002524 (int)(&nanosleep_interval), (int)NULL);
sewardj645030e2002-06-06 01:27:39 +00002525 if (res == -VKI_EINTR) {
2526 /* The nanosleep was interrupted by a signal. So we do the
2527 same. */
2528 * (__errno_location()) = EINTR;
2529 return -1;
2530 }
sewardj05bb2c92002-06-26 00:47:17 +00002531
2532 /* Sleeping finished. If a finite timeout, check to see if it
2533 has expired yet. */
2534 if (timeout) {
2535 VALGRIND_MAGIC_SEQUENCE(ms_now, 0xFFFFFFFF /* default */,
2536 VG_USERREQ__READ_MILLISECOND_TIMER,
2537 0, 0, 0, 0);
2538 my_assert(ms_now != 0xFFFFFFFF);
2539 if (ms_now >= ms_end) {
2540 /* timeout; nothing interesting happened. */
2541 if (rfds) FD_ZERO(rfds);
2542 if (wfds) FD_ZERO(wfds);
2543 if (xfds) FD_ZERO(xfds);
2544 return 0;
2545 }
2546 }
2547
sewardjf854f472002-04-21 12:19:41 +00002548 }
2549}
2550
2551
2552
2553
2554#include <sys/poll.h>
2555
sewardj3e909ce2002-06-03 13:27:15 +00002556#ifndef HAVE_NFDS_T
sewardj72d58482002-04-24 02:20:20 +00002557typedef unsigned long int nfds_t;
2558#endif
2559
sewardj705d3cb2002-05-23 13:13:12 +00002560
sewardj7db011a2002-11-13 22:00:20 +00002561int VGL_(poll) (struct pollfd *__fds, nfds_t __nfds, int __timeout)
sewardjf854f472002-04-21 12:19:41 +00002562{
sewardj5f07b662002-04-23 16:52:51 +00002563 unsigned int ms_now, ms_end;
sewardjf854f472002-04-21 12:19:41 +00002564 int res, i;
sewardjf854f472002-04-21 12:19:41 +00002565 struct vki_timespec nanosleep_interval;
2566
sewardjd140e442002-05-29 01:21:19 +00002567 __my_pthread_testcancel();
sewardjf854f472002-04-21 12:19:41 +00002568 ensure_valgrind("poll");
2569
sewardj5f07b662002-04-23 16:52:51 +00002570 /* Detect the current time and simultaneously find out if we are
2571 running on Valgrind. */
2572 VALGRIND_MAGIC_SEQUENCE(ms_now, 0xFFFFFFFF /* default */,
2573 VG_USERREQ__READ_MILLISECOND_TIMER,
2574 0, 0, 0, 0);
2575
sewardjf854f472002-04-21 12:19:41 +00002576 if (/* CHECK SIZES FOR struct pollfd */
2577 sizeof(struct timeval) != sizeof(struct vki_timeval))
2578 barf("valgrind's hacky non-blocking poll(): data sizes error");
2579
sewardj5f07b662002-04-23 16:52:51 +00002580 /* dummy initialisation to keep gcc -Wall happy */
2581 ms_end = 0;
2582
2583 /* If a zero timeout specified, this call is harmless. Also do
2584 this if not running on Valgrind. */
2585 if (__timeout == 0 || ms_now == 0xFFFFFFFF) {
sewardjf854f472002-04-21 12:19:41 +00002586 res = my_do_syscall3(__NR_poll, (int)__fds, __nfds, __timeout);
2587 if (is_kerror(res)) {
2588 * (__errno_location()) = -res;
2589 return -1;
2590 } else {
2591 return res;
2592 }
2593 }
2594
sewardj5f07b662002-04-23 16:52:51 +00002595 /* If a timeout was specified, set ms_end to be the end wallclock
2596 time. Easy considering that __timeout is in milliseconds. */
sewardjf854f472002-04-21 12:19:41 +00002597 if (__timeout > 0) {
sewardj650ac002002-04-29 12:20:34 +00002598 ms_end = ms_now + (unsigned int)__timeout;
sewardjf854f472002-04-21 12:19:41 +00002599 }
2600
2601 /* fprintf(stderr, "MY_POLL: before loop\n"); */
2602
2603 /* Either timeout < 0, meaning wait indefinitely, or timeout > 0,
2604 in which case t_end holds the end time. */
sewardj05bb2c92002-06-26 00:47:17 +00002605
sewardj2d94c112002-06-03 01:25:54 +00002606 my_assert(__timeout != 0);
sewardj5f07b662002-04-23 16:52:51 +00002607
sewardjf854f472002-04-21 12:19:41 +00002608 while (1) {
sewardj05bb2c92002-06-26 00:47:17 +00002609
2610 /* Do a return-immediately poll. */
2611
2612 res = my_do_syscall3(__NR_poll, (int)__fds, __nfds, 0 );
2613 if (is_kerror(res)) {
2614 /* Some kind of error. Set errno and return. */
2615 * (__errno_location()) = -res;
2616 return -1;
2617 }
2618 if (res > 0) {
2619 /* One or more fds is ready. Return now. */
2620 return res;
2621 }
2622
2623 /* Nothing interesting happened, so we go to sleep for a
2624 while. */
2625
2626 /* fprintf(stderr, "MY_POLL: nanosleep\n"); */
2627 /* nanosleep and go round again */
2628 nanosleep_interval.tv_sec = 0;
njn25e49d8e72002-09-23 09:36:25 +00002629 nanosleep_interval.tv_nsec = 13 * 1000 * 1000; /* 13 milliseconds */
sewardj05bb2c92002-06-26 00:47:17 +00002630 /* It's critical here that valgrind's nanosleep implementation
2631 is nonblocking. */
2632 (void)my_do_syscall2(__NR_nanosleep,
2633 (int)(&nanosleep_interval), (int)NULL);
2634
2635 /* Sleeping finished. If a finite timeout, check to see if it
2636 has expired yet. */
sewardjf854f472002-04-21 12:19:41 +00002637 if (__timeout > 0) {
sewardj5f07b662002-04-23 16:52:51 +00002638 VALGRIND_MAGIC_SEQUENCE(ms_now, 0xFFFFFFFF /* default */,
2639 VG_USERREQ__READ_MILLISECOND_TIMER,
2640 0, 0, 0, 0);
sewardj2d94c112002-06-03 01:25:54 +00002641 my_assert(ms_now != 0xFFFFFFFF);
sewardj5f07b662002-04-23 16:52:51 +00002642 if (ms_now >= ms_end) {
sewardjf854f472002-04-21 12:19:41 +00002643 /* timeout; nothing interesting happened. */
2644 for (i = 0; i < __nfds; i++)
2645 __fds[i].revents = 0;
2646 return 0;
2647 }
2648 }
2649
sewardj08a4c3f2002-04-13 03:45:44 +00002650 }
2651}
sewardj3b13f0e2002-04-25 20:17:29 +00002652
2653
sewardj705d3cb2002-05-23 13:13:12 +00002654/* Helper function used to make accept() non-blocking. Idea is to use
2655 the above nonblocking poll() to make this thread ONLY wait for the
2656 specified fd to become ready, and then return. */
sewardjd1c1cf22002-06-26 00:13:36 +00002657
2658/* Sigh -- a hack. We're not supposed to include this file directly;
2659 should do it via /usr/include/fcntl.h, but that introduces a
2660 varargs prototype for fcntl itself, which we can't mimic. */
2661#define _FCNTL_H
2662#include <bits/fcntl.h>
2663
sewardj705d3cb2002-05-23 13:13:12 +00002664static void wait_for_fd_to_be_readable_or_erring ( int fd )
2665{
2666 struct pollfd pfd;
sewardjd1c1cf22002-06-26 00:13:36 +00002667 int res;
2668
sewardj6e6cbaa2002-05-24 02:12:52 +00002669 /* fprintf(stderr, "wait_for_fd_to_be_readable_or_erring %d\n", fd); */
sewardjd1c1cf22002-06-26 00:13:36 +00002670
2671 /* First check to see if the fd is nonblocking, and/or invalid. In
2672 either case return immediately. */
2673 res = __libc_fcntl(fd, F_GETFL, 0);
2674 if (res == -1) return; /* fd is invalid somehow */
2675 if (res & O_NONBLOCK) return; /* fd is nonblocking */
2676
2677 /* Ok, we'd better wait with poll. */
sewardj705d3cb2002-05-23 13:13:12 +00002678 pfd.fd = fd;
2679 pfd.events = POLLIN | POLLPRI | POLLERR | POLLHUP | POLLNVAL;
2680 /* ... but not POLLOUT, you may notice. */
2681 pfd.revents = 0;
2682 (void)poll(&pfd, 1, -1 /* forever */);
2683}
2684
sewardj2a68e7e2002-11-16 11:04:18 +00002685static void wait_for_fd_to_be_writable_or_erring ( int fd )
2686{
2687 struct pollfd pfd;
2688 int res;
2689
2690 /* fprintf(stderr, "wait_for_fd_to_be_readable_or_erring %d\n", fd); */
2691
2692 /* First check to see if the fd is nonblocking, and/or invalid. In
2693 either case return immediately. */
2694 res = __libc_fcntl(fd, F_GETFL, 0);
2695 if (res == -1) return; /* fd is invalid somehow */
2696 if (res & O_NONBLOCK) return; /* fd is nonblocking */
2697
2698 /* Ok, we'd better wait with poll. */
2699 pfd.fd = fd;
2700 pfd.events = POLLOUT | POLLERR | POLLHUP | POLLNVAL;
2701 pfd.revents = 0;
2702 (void)poll(&pfd, 1, -1 /* forever */);
2703}
sewardj705d3cb2002-05-23 13:13:12 +00002704
sewardj3b13f0e2002-04-25 20:17:29 +00002705/* ---------------------------------------------------------------------
sewardj8f253ff2002-05-19 00:13:34 +00002706 Hacky implementation of semaphores.
2707 ------------------------------------------------------------------ */
2708
2709#include <semaphore.h>
2710
2711/* This is a terrible way to do the remapping. Plan is to import an
2712 AVL tree at some point. */
sewardj8f253ff2002-05-19 00:13:34 +00002713
2714typedef
2715 struct {
2716 pthread_mutex_t se_mx;
2717 pthread_cond_t se_cv;
2718 int count;
2719 }
2720 vg_sem_t;
2721
2722static pthread_mutex_t se_remap_mx = PTHREAD_MUTEX_INITIALIZER;
2723
2724static int se_remap_used = 0;
2725static sem_t* se_remap_orig[VG_N_SEMAPHORES];
2726static vg_sem_t se_remap_new[VG_N_SEMAPHORES];
2727
2728static vg_sem_t* se_remap ( sem_t* orig )
2729{
2730 int res, i;
2731 res = __pthread_mutex_lock(&se_remap_mx);
sewardj2d94c112002-06-03 01:25:54 +00002732 my_assert(res == 0);
sewardj8f253ff2002-05-19 00:13:34 +00002733
2734 for (i = 0; i < se_remap_used; i++) {
2735 if (se_remap_orig[i] == orig)
2736 break;
2737 }
2738 if (i == se_remap_used) {
2739 if (se_remap_used == VG_N_SEMAPHORES) {
2740 res = pthread_mutex_unlock(&se_remap_mx);
sewardj2d94c112002-06-03 01:25:54 +00002741 my_assert(res == 0);
sewardja1ac5cb2002-05-27 13:00:05 +00002742 barf("VG_N_SEMAPHORES is too low. Increase and recompile.");
sewardj8f253ff2002-05-19 00:13:34 +00002743 }
2744 se_remap_used++;
2745 se_remap_orig[i] = orig;
2746 /* printf("allocated semaphore %d\n", i); */
2747 }
2748 res = __pthread_mutex_unlock(&se_remap_mx);
sewardj2d94c112002-06-03 01:25:54 +00002749 my_assert(res == 0);
sewardj8f253ff2002-05-19 00:13:34 +00002750 return &se_remap_new[i];
2751}
2752
2753
2754int sem_init(sem_t *sem, int pshared, unsigned int value)
2755{
2756 int res;
2757 vg_sem_t* vg_sem;
2758 ensure_valgrind("sem_init");
2759 if (pshared != 0) {
sewardj4dced352002-06-04 22:54:20 +00002760 pthread_error("sem_init: unsupported pshared value");
sewardj8f253ff2002-05-19 00:13:34 +00002761 errno = ENOSYS;
2762 return -1;
2763 }
2764 vg_sem = se_remap(sem);
2765 res = pthread_mutex_init(&vg_sem->se_mx, NULL);
sewardj2d94c112002-06-03 01:25:54 +00002766 my_assert(res == 0);
sewardj8f253ff2002-05-19 00:13:34 +00002767 res = pthread_cond_init(&vg_sem->se_cv, NULL);
sewardj2d94c112002-06-03 01:25:54 +00002768 my_assert(res == 0);
sewardj8f253ff2002-05-19 00:13:34 +00002769 vg_sem->count = value;
2770 return 0;
2771}
2772
2773
2774int sem_wait ( sem_t* sem )
2775{
2776 int res;
2777 vg_sem_t* vg_sem;
2778 ensure_valgrind("sem_wait");
2779 vg_sem = se_remap(sem);
2780 res = __pthread_mutex_lock(&vg_sem->se_mx);
sewardj2d94c112002-06-03 01:25:54 +00002781 my_assert(res == 0);
sewardj8f253ff2002-05-19 00:13:34 +00002782 while (vg_sem->count == 0) {
2783 res = pthread_cond_wait(&vg_sem->se_cv, &vg_sem->se_mx);
sewardj2d94c112002-06-03 01:25:54 +00002784 my_assert(res == 0);
sewardj8f253ff2002-05-19 00:13:34 +00002785 }
2786 vg_sem->count--;
2787 res = __pthread_mutex_unlock(&vg_sem->se_mx);
sewardj2d94c112002-06-03 01:25:54 +00002788 my_assert(res == 0);
sewardj8f253ff2002-05-19 00:13:34 +00002789 return 0;
2790}
2791
2792int sem_post ( sem_t* sem )
2793{
2794 int res;
2795 vg_sem_t* vg_sem;
2796 ensure_valgrind("sem_post");
2797 vg_sem = se_remap(sem);
2798 res = __pthread_mutex_lock(&vg_sem->se_mx);
sewardj2d94c112002-06-03 01:25:54 +00002799 my_assert(res == 0);
sewardj8f253ff2002-05-19 00:13:34 +00002800 if (vg_sem->count == 0) {
2801 vg_sem->count++;
2802 res = pthread_cond_broadcast(&vg_sem->se_cv);
sewardj2d94c112002-06-03 01:25:54 +00002803 my_assert(res == 0);
sewardj8f253ff2002-05-19 00:13:34 +00002804 } else {
2805 vg_sem->count++;
2806 }
2807 res = __pthread_mutex_unlock(&vg_sem->se_mx);
sewardj2d94c112002-06-03 01:25:54 +00002808 my_assert(res == 0);
sewardj8f253ff2002-05-19 00:13:34 +00002809 return 0;
2810}
2811
2812
2813int sem_trywait ( sem_t* sem )
2814{
2815 int ret, res;
2816 vg_sem_t* vg_sem;
2817 ensure_valgrind("sem_trywait");
2818 vg_sem = se_remap(sem);
2819 res = __pthread_mutex_lock(&vg_sem->se_mx);
sewardj2d94c112002-06-03 01:25:54 +00002820 my_assert(res == 0);
sewardj8f253ff2002-05-19 00:13:34 +00002821 if (vg_sem->count > 0) {
2822 vg_sem->count--;
2823 ret = 0;
2824 } else {
2825 ret = -1;
2826 errno = EAGAIN;
2827 }
2828 res = __pthread_mutex_unlock(&vg_sem->se_mx);
sewardj2d94c112002-06-03 01:25:54 +00002829 my_assert(res == 0);
sewardj8f253ff2002-05-19 00:13:34 +00002830 return ret;
2831}
2832
2833
2834int sem_getvalue(sem_t* sem, int * sval)
2835{
2836 vg_sem_t* vg_sem;
2837 ensure_valgrind("sem_trywait");
2838 vg_sem = se_remap(sem);
2839 *sval = vg_sem->count;
2840 return 0;
2841}
2842
2843
2844int sem_destroy(sem_t * sem)
2845{
2846 kludged("sem_destroy");
2847 /* if someone waiting on this semaphore, errno = EBUSY, return -1 */
2848 return 0;
2849}
2850
sewardj9ad92d92002-10-16 19:45:06 +00002851
2852int sem_timedwait(sem_t* sem, const struct timespec *abstime)
2853{
2854 int res;
2855 vg_sem_t* vg_sem;
2856 ensure_valgrind("sem_timedwait");
2857 vg_sem = se_remap(sem);
2858 res = __pthread_mutex_lock(&vg_sem->se_mx);
2859 my_assert(res == 0);
2860 while ( vg_sem->count == 0 && res != ETIMEDOUT ) {
2861 res = pthread_cond_timedwait(&vg_sem->se_cv, &vg_sem->se_mx, abstime);
2862 }
2863 if ( vg_sem->count > 0 ) {
2864 vg_sem->count--;
2865 res = __pthread_mutex_unlock(&vg_sem->se_mx);
2866 my_assert(res == 0 );
2867 return 0;
2868 } else {
2869 res = __pthread_mutex_unlock(&vg_sem->se_mx);
2870 my_assert(res == 0 );
2871 *(__errno_location()) = ETIMEDOUT;
2872 return -1;
2873 }
2874}
2875
sewardj8f253ff2002-05-19 00:13:34 +00002876
2877/* ---------------------------------------------------------------------
sewardj2d8b3f02002-06-01 14:14:19 +00002878 Reader-writer locks.
sewardja1ac5cb2002-05-27 13:00:05 +00002879 ------------------------------------------------------------------ */
2880
sewardj2d8b3f02002-06-01 14:14:19 +00002881typedef
2882 struct {
2883 int initted; /* != 0 --> in use; sanity check only */
2884 int prefer_w; /* != 0 --> prefer writer */
2885 int nwait_r; /* # of waiting readers */
2886 int nwait_w; /* # of waiting writers */
2887 pthread_cond_t cv_r; /* for signalling readers */
2888 pthread_cond_t cv_w; /* for signalling writers */
2889 pthread_mutex_t mx;
2890 int status;
2891 /* allowed range for status: >= -1. -1 means 1 writer currently
2892 active, >= 0 means N readers currently active. */
2893 }
2894 vg_rwlock_t;
sewardja1ac5cb2002-05-27 13:00:05 +00002895
2896
2897static pthread_mutex_t rw_remap_mx = PTHREAD_MUTEX_INITIALIZER;
2898
2899static int rw_remap_used = 0;
2900static pthread_rwlock_t* rw_remap_orig[VG_N_RWLOCKS];
2901static vg_rwlock_t rw_remap_new[VG_N_RWLOCKS];
2902
sewardj2d8b3f02002-06-01 14:14:19 +00002903
2904static
2905void init_vg_rwlock ( vg_rwlock_t* vg_rwl )
2906{
2907 int res = 0;
2908 vg_rwl->initted = 1;
2909 vg_rwl->prefer_w = 1;
2910 vg_rwl->nwait_r = 0;
2911 vg_rwl->nwait_w = 0;
2912 vg_rwl->status = 0;
2913 res = pthread_mutex_init(&vg_rwl->mx, NULL);
2914 res |= pthread_cond_init(&vg_rwl->cv_r, NULL);
2915 res |= pthread_cond_init(&vg_rwl->cv_w, NULL);
sewardj2d94c112002-06-03 01:25:54 +00002916 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002917}
2918
2919
sewardja1ac5cb2002-05-27 13:00:05 +00002920/* Take the address of a LinuxThreads rwlock_t and return the shadow
2921 address of our version. Further, if the LinuxThreads version
2922 appears to have been statically initialised, do the same to the one
2923 we allocate here. The pthread_rwlock_t.__rw_readers field is set
2924 to zero by PTHREAD_RWLOCK_INITIALIZER, so we take zero as meaning
2925 uninitialised and non-zero meaning initialised.
2926*/
2927static vg_rwlock_t* rw_remap ( pthread_rwlock_t* orig )
2928{
2929 int res, i;
2930 vg_rwlock_t* vg_rwl;
2931 res = __pthread_mutex_lock(&rw_remap_mx);
sewardj2d94c112002-06-03 01:25:54 +00002932 my_assert(res == 0);
sewardja1ac5cb2002-05-27 13:00:05 +00002933
2934 for (i = 0; i < rw_remap_used; i++) {
2935 if (rw_remap_orig[i] == orig)
2936 break;
2937 }
2938 if (i == rw_remap_used) {
2939 if (rw_remap_used == VG_N_RWLOCKS) {
sewardj2d8b3f02002-06-01 14:14:19 +00002940 res = __pthread_mutex_unlock(&rw_remap_mx);
sewardj2d94c112002-06-03 01:25:54 +00002941 my_assert(res == 0);
sewardja1ac5cb2002-05-27 13:00:05 +00002942 barf("VG_N_RWLOCKS is too low. Increase and recompile.");
2943 }
2944 rw_remap_used++;
2945 rw_remap_orig[i] = orig;
sewardj2d8b3f02002-06-01 14:14:19 +00002946 rw_remap_new[i].initted = 0;
sewardja1ac5cb2002-05-27 13:00:05 +00002947 if (0) printf("allocated rwlock %d\n", i);
2948 }
2949 res = __pthread_mutex_unlock(&rw_remap_mx);
sewardj2d94c112002-06-03 01:25:54 +00002950 my_assert(res == 0);
sewardja1ac5cb2002-05-27 13:00:05 +00002951 vg_rwl = &rw_remap_new[i];
2952
sewardj2d8b3f02002-06-01 14:14:19 +00002953 /* Initialise the shadow, if required. */
sewardja1ac5cb2002-05-27 13:00:05 +00002954 if (orig->__rw_readers == 0) {
sewardja1ac5cb2002-05-27 13:00:05 +00002955 orig->__rw_readers = 1;
sewardj2d8b3f02002-06-01 14:14:19 +00002956 init_vg_rwlock(vg_rwl);
sewardja1ac5cb2002-05-27 13:00:05 +00002957 if (orig->__rw_kind == PTHREAD_RWLOCK_PREFER_READER_NP)
sewardj2d8b3f02002-06-01 14:14:19 +00002958 vg_rwl->prefer_w = 0;
sewardja1ac5cb2002-05-27 13:00:05 +00002959 }
2960
2961 return vg_rwl;
2962}
2963
2964
sewardja1ac5cb2002-05-27 13:00:05 +00002965int pthread_rwlock_init ( pthread_rwlock_t* orig,
2966 const pthread_rwlockattr_t* attr )
2967{
sewardja1ac5cb2002-05-27 13:00:05 +00002968 vg_rwlock_t* rwl;
2969 if (0) printf ("pthread_rwlock_init\n");
2970 /* Force the remapper to initialise the shadow. */
2971 orig->__rw_readers = 0;
2972 /* Install the lock preference; the remapper needs to know it. */
2973 orig->__rw_kind = PTHREAD_RWLOCK_DEFAULT_NP;
2974 if (attr)
2975 orig->__rw_kind = attr->__lockkind;
2976 rwl = rw_remap ( orig );
sewardj2d8b3f02002-06-01 14:14:19 +00002977 return 0;
sewardja1ac5cb2002-05-27 13:00:05 +00002978}
2979
sewardj2d8b3f02002-06-01 14:14:19 +00002980
2981static
2982void pthread_rwlock_rdlock_CANCEL_HDLR ( void* rwl_v )
sewardja1ac5cb2002-05-27 13:00:05 +00002983{
sewardj2d8b3f02002-06-01 14:14:19 +00002984 vg_rwlock_t* rwl = (vg_rwlock_t*)rwl_v;
2985 rwl->nwait_r--;
2986 pthread_mutex_unlock (&rwl->mx);
sewardja1ac5cb2002-05-27 13:00:05 +00002987}
2988
sewardj2d8b3f02002-06-01 14:14:19 +00002989
sewardja1ac5cb2002-05-27 13:00:05 +00002990int pthread_rwlock_rdlock ( pthread_rwlock_t* orig )
2991{
2992 int res;
2993 vg_rwlock_t* rwl;
2994 if (0) printf ("pthread_rwlock_rdlock\n");
2995 rwl = rw_remap ( orig );
sewardj2d8b3f02002-06-01 14:14:19 +00002996 res = __pthread_mutex_lock(&rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00002997 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002998 if (!rwl->initted) {
2999 res = __pthread_mutex_unlock(&rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00003000 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00003001 return EINVAL;
3002 }
3003 if (rwl->status < 0) {
sewardj2d94c112002-06-03 01:25:54 +00003004 my_assert(rwl->status == -1);
sewardj2d8b3f02002-06-01 14:14:19 +00003005 rwl->nwait_r++;
3006 pthread_cleanup_push( pthread_rwlock_rdlock_CANCEL_HDLR, rwl );
3007 while (1) {
3008 if (rwl->status == 0) break;
3009 res = pthread_cond_wait(&rwl->cv_r, &rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00003010 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00003011 }
3012 pthread_cleanup_pop(0);
3013 rwl->nwait_r--;
3014 }
sewardj2d94c112002-06-03 01:25:54 +00003015 my_assert(rwl->status >= 0);
sewardj2d8b3f02002-06-01 14:14:19 +00003016 rwl->status++;
3017 res = __pthread_mutex_unlock(&rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00003018 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00003019 return 0;
sewardja1ac5cb2002-05-27 13:00:05 +00003020}
3021
sewardj2d8b3f02002-06-01 14:14:19 +00003022
sewardja1ac5cb2002-05-27 13:00:05 +00003023int pthread_rwlock_tryrdlock ( pthread_rwlock_t* orig )
3024{
3025 int res;
3026 vg_rwlock_t* rwl;
3027 if (0) printf ("pthread_rwlock_tryrdlock\n");
3028 rwl = rw_remap ( orig );
sewardj2d8b3f02002-06-01 14:14:19 +00003029 res = __pthread_mutex_lock(&rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00003030 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00003031 if (!rwl->initted) {
3032 res = __pthread_mutex_unlock(&rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00003033 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00003034 return EINVAL;
3035 }
3036 if (rwl->status == -1) {
3037 /* Writer active; we have to give up. */
3038 res = __pthread_mutex_unlock(&rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00003039 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00003040 return EBUSY;
3041 }
3042 /* Success */
sewardj2d94c112002-06-03 01:25:54 +00003043 my_assert(rwl->status >= 0);
sewardj2d8b3f02002-06-01 14:14:19 +00003044 rwl->status++;
3045 res = __pthread_mutex_unlock(&rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00003046 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00003047 return 0;
sewardja1ac5cb2002-05-27 13:00:05 +00003048}
3049
sewardj2d8b3f02002-06-01 14:14:19 +00003050
3051static
3052void pthread_rwlock_wrlock_CANCEL_HDLR ( void* rwl_v )
3053{
3054 vg_rwlock_t* rwl = (vg_rwlock_t*)rwl_v;
3055 rwl->nwait_w--;
3056 pthread_mutex_unlock (&rwl->mx);
3057}
3058
3059
sewardja1ac5cb2002-05-27 13:00:05 +00003060int pthread_rwlock_wrlock ( pthread_rwlock_t* orig )
3061{
3062 int res;
3063 vg_rwlock_t* rwl;
3064 if (0) printf ("pthread_rwlock_wrlock\n");
3065 rwl = rw_remap ( orig );
sewardj2d8b3f02002-06-01 14:14:19 +00003066 res = __pthread_mutex_lock(&rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00003067 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00003068 if (!rwl->initted) {
3069 res = __pthread_mutex_unlock(&rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00003070 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00003071 return EINVAL;
3072 }
3073 if (rwl->status != 0) {
3074 rwl->nwait_w++;
3075 pthread_cleanup_push( pthread_rwlock_wrlock_CANCEL_HDLR, rwl );
3076 while (1) {
3077 if (rwl->status == 0) break;
3078 res = pthread_cond_wait(&rwl->cv_w, &rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00003079 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00003080 }
3081 pthread_cleanup_pop(0);
3082 rwl->nwait_w--;
3083 }
sewardj2d94c112002-06-03 01:25:54 +00003084 my_assert(rwl->status == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00003085 rwl->status = -1;
3086 res = __pthread_mutex_unlock(&rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00003087 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00003088 return 0;
sewardja1ac5cb2002-05-27 13:00:05 +00003089}
3090
sewardj2d8b3f02002-06-01 14:14:19 +00003091
sewardja1ac5cb2002-05-27 13:00:05 +00003092int pthread_rwlock_trywrlock ( pthread_rwlock_t* orig )
3093{
3094 int res;
3095 vg_rwlock_t* rwl;
sewardj2d8b3f02002-06-01 14:14:19 +00003096 if (0) printf ("pthread_wrlock_trywrlock\n");
sewardja1ac5cb2002-05-27 13:00:05 +00003097 rwl = rw_remap ( orig );
sewardj2d8b3f02002-06-01 14:14:19 +00003098 res = __pthread_mutex_lock(&rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00003099 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00003100 if (!rwl->initted) {
3101 res = __pthread_mutex_unlock(&rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00003102 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00003103 return EINVAL;
3104 }
3105 if (rwl->status != 0) {
3106 /* Reader(s) or a writer active; we have to give up. */
3107 res = __pthread_mutex_unlock(&rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00003108 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00003109 return EBUSY;
3110 }
3111 /* Success */
sewardj2d94c112002-06-03 01:25:54 +00003112 my_assert(rwl->status == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00003113 rwl->status = -1;
3114 res = __pthread_mutex_unlock(&rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00003115 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00003116 return 0;
sewardja1ac5cb2002-05-27 13:00:05 +00003117}
3118
sewardj2d8b3f02002-06-01 14:14:19 +00003119
sewardja1ac5cb2002-05-27 13:00:05 +00003120int pthread_rwlock_unlock ( pthread_rwlock_t* orig )
3121{
3122 int res;
3123 vg_rwlock_t* rwl;
3124 if (0) printf ("pthread_rwlock_unlock\n");
3125 rwl = rw_remap ( orig );
sewardj2d8b3f02002-06-01 14:14:19 +00003126 rwl = rw_remap ( orig );
3127 res = __pthread_mutex_lock(&rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00003128 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00003129 if (!rwl->initted) {
3130 res = __pthread_mutex_unlock(&rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00003131 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00003132 return EINVAL;
3133 }
3134 if (rwl->status == 0) {
3135 res = __pthread_mutex_unlock(&rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00003136 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00003137 return EPERM;
3138 }
sewardj2d94c112002-06-03 01:25:54 +00003139 my_assert(rwl->status != 0);
sewardj2d8b3f02002-06-01 14:14:19 +00003140 if (rwl->status == -1) {
3141 rwl->status = 0;
3142 } else {
sewardj2d94c112002-06-03 01:25:54 +00003143 my_assert(rwl->status > 0);
sewardj2d8b3f02002-06-01 14:14:19 +00003144 rwl->status--;
3145 }
3146
sewardj2d94c112002-06-03 01:25:54 +00003147 my_assert(rwl->status >= 0);
sewardj2d8b3f02002-06-01 14:14:19 +00003148
3149 if (rwl->prefer_w) {
3150
3151 /* Favour waiting writers, if any. */
3152 if (rwl->nwait_w > 0) {
3153 /* Writer(s) are waiting. */
3154 if (rwl->status == 0) {
3155 /* We can let a writer in. */
3156 res = pthread_cond_signal(&rwl->cv_w);
sewardj2d94c112002-06-03 01:25:54 +00003157 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00003158 } else {
3159 /* There are still readers active. Do nothing; eventually
3160 they will disappear, at which point a writer will be
3161 admitted. */
3162 }
3163 }
3164 else
3165 /* No waiting writers. */
3166 if (rwl->nwait_r > 0) {
3167 /* Let in a waiting reader. */
3168 res = pthread_cond_signal(&rwl->cv_r);
sewardj2d94c112002-06-03 01:25:54 +00003169 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00003170 }
3171
3172 } else {
3173
3174 /* Favour waiting readers, if any. */
3175 if (rwl->nwait_r > 0) {
3176 /* Reader(s) are waiting; let one in. */
3177 res = pthread_cond_signal(&rwl->cv_r);
sewardj2d94c112002-06-03 01:25:54 +00003178 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00003179 }
3180 else
3181 /* No waiting readers. */
3182 if (rwl->nwait_w > 0 && rwl->status == 0) {
3183 /* We have waiting writers and no active readers; let a
3184 writer in. */
3185 res = pthread_cond_signal(&rwl->cv_w);
sewardj2d94c112002-06-03 01:25:54 +00003186 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00003187 }
3188 }
3189
3190 res = __pthread_mutex_unlock(&rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00003191 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00003192 return 0;
3193}
3194
3195
3196int pthread_rwlock_destroy ( pthread_rwlock_t *orig )
3197{
3198 int res;
3199 vg_rwlock_t* rwl;
3200 if (0) printf ("pthread_rwlock_destroy\n");
3201 rwl = rw_remap ( orig );
3202 res = __pthread_mutex_lock(&rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00003203 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00003204 if (!rwl->initted) {
3205 res = __pthread_mutex_unlock(&rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00003206 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00003207 return EINVAL;
3208 }
3209 if (rwl->status != 0 || rwl->nwait_r > 0 || rwl->nwait_w > 0) {
3210 res = __pthread_mutex_unlock(&rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00003211 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00003212 return EBUSY;
3213 }
3214 rwl->initted = 0;
3215 res = __pthread_mutex_unlock(&rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00003216 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00003217 return 0;
sewardja1ac5cb2002-05-27 13:00:05 +00003218}
3219
3220
sewardj47e4e312002-06-18 09:24:34 +00003221/* Copied directly from LinuxThreads. */
3222int
3223pthread_rwlockattr_init (pthread_rwlockattr_t *attr)
3224{
3225 attr->__lockkind = 0;
3226 attr->__pshared = PTHREAD_PROCESS_PRIVATE;
3227
3228 return 0;
3229}
3230
sewardjfe18eb82002-07-13 12:58:44 +00003231/* Copied directly from LinuxThreads. */
3232int
3233pthread_rwlockattr_setpshared (pthread_rwlockattr_t *attr, int pshared)
3234{
3235 if (pshared != PTHREAD_PROCESS_PRIVATE && pshared != PTHREAD_PROCESS_SHARED)
3236 return EINVAL;
3237
3238 /* For now it is not possible to shared a conditional variable. */
3239 if (pshared != PTHREAD_PROCESS_PRIVATE)
3240 return ENOSYS;
3241
3242 attr->__pshared = pshared;
3243
3244 return 0;
3245}
3246
sewardj47e4e312002-06-18 09:24:34 +00003247
sewardja1ac5cb2002-05-27 13:00:05 +00003248/* ---------------------------------------------------------------------
sewardjd5bef572002-10-23 21:49:33 +00003249 Make SYSV IPC not block everything
3250 ------------------------------------------------------------------ */
3251
3252#include <sys/ipc.h>
3253#include <sys/msg.h>
3254#include <asm/ipc.h> /* for ipc_kludge */
3255
3256static inline int sys_ipc(unsigned call, int first, int second, int third, void *ptr)
3257{
3258 return my_do_syscall5(__NR_ipc, call, first, second, third, (int)ptr);
3259}
3260
3261/* Turn a blocking msgsnd() into a polling non-blocking one, so that
3262 other threads make progress */
sewardjf220ccc2002-10-23 21:53:49 +00003263int VGL_(msgsnd)(int msgid, const void *msgp, size_t msgsz, int msgflg)
sewardjd5bef572002-10-23 21:49:33 +00003264{
3265 struct vki_timespec nanosleep_interval;
3266 int err;
3267
3268 ensure_valgrind("msgsnd");
3269
3270 nanosleep_interval.tv_sec = 0;
3271 nanosleep_interval.tv_nsec = 13 * 1000 * 1000; /* 13 milliseconds */
3272
3273 if (msgflg & IPC_NOWAIT) {
3274 /* If we aren't blocking anyway, just do it */
3275 err = sys_ipc(11, msgid, msgsz, msgflg, (void *)msgp);
3276 } else {
3277 /* Otherwise poll on the queue to let other things run */
3278 for(;;) {
3279 err = sys_ipc(11, msgid, msgsz, msgflg | IPC_NOWAIT, (void *)msgp);
3280
3281 if (err != -EAGAIN)
3282 break;
3283
3284 (void)my_do_syscall2(__NR_nanosleep,
3285 (int)(&nanosleep_interval), (int)NULL);
3286 }
3287 }
3288
3289 if (is_kerror(err)) {
3290 *(__errno_location()) = -err;
3291 return -1;
3292 }
3293 return 0;
3294}
3295
3296/* Turn a blocking msgrcv() into a polling non-blocking one, so that
3297 other threads make progress */
sewardjf220ccc2002-10-23 21:53:49 +00003298int VGL_(msgrcv)( int msqid, void *msgp, size_t msgsz, long msgtyp, int msgflg )
sewardjd5bef572002-10-23 21:49:33 +00003299{
3300 struct vki_timespec nanosleep_interval;
3301 int err;
3302 struct ipc_kludge tmp;
3303
3304 ensure_valgrind("msgrcv");
3305
3306 nanosleep_interval.tv_sec = 0;
3307 nanosleep_interval.tv_nsec = 13 * 1000 * 1000; /* 13 milliseconds */
3308
3309 tmp.msgp = msgp;
3310 tmp.msgtyp = msgtyp;
3311
3312 if (msgflg & IPC_NOWAIT) {
3313 /* If we aren't blocking anyway, just do it */
3314 err = sys_ipc(12, msqid, msgsz, msgflg, &tmp );
3315 } else {
3316 /* Otherwise poll on the queue to let other things run */
3317 for(;;) {
3318 err = sys_ipc(12, msqid, msgsz, msgflg | IPC_NOWAIT, &tmp );
3319
3320 if (err != -ENOMSG)
3321 break;
3322
3323 (void)my_do_syscall2(__NR_nanosleep,
3324 (int)(&nanosleep_interval), (int)NULL);
3325 }
3326 }
3327
3328 if (is_kerror(err)) {
3329 *(__errno_location()) = -err;
3330 return -1;
3331 }
3332
3333 return 0;
3334}
3335
3336
3337
3338/* ---------------------------------------------------------------------
sewardj3b13f0e2002-04-25 20:17:29 +00003339 B'stard.
3340 ------------------------------------------------------------------ */
3341
3342# define strong_alias(name, aliasname) \
3343 extern __typeof (name) aliasname __attribute__ ((alias (#name)));
3344
sewardj5905fae2002-04-26 13:25:00 +00003345# define weak_alias(name, aliasname) \
3346 extern __typeof (name) aliasname __attribute__ ((weak, alias (#name)));
sewardj3b13f0e2002-04-25 20:17:29 +00003347
sewardj5905fae2002-04-26 13:25:00 +00003348strong_alias(__pthread_mutex_lock, pthread_mutex_lock)
3349strong_alias(__pthread_mutex_trylock, pthread_mutex_trylock)
3350strong_alias(__pthread_mutex_unlock, pthread_mutex_unlock)
3351strong_alias(__pthread_mutexattr_init, pthread_mutexattr_init)
3352 weak_alias(__pthread_mutexattr_settype, pthread_mutexattr_settype)
3353strong_alias(__pthread_mutex_init, pthread_mutex_init)
3354strong_alias(__pthread_mutexattr_destroy, pthread_mutexattr_destroy)
3355strong_alias(__pthread_mutex_destroy, pthread_mutex_destroy)
3356strong_alias(__pthread_once, pthread_once)
3357strong_alias(__pthread_atfork, pthread_atfork)
3358strong_alias(__pthread_key_create, pthread_key_create)
3359strong_alias(__pthread_getspecific, pthread_getspecific)
3360strong_alias(__pthread_setspecific, pthread_setspecific)
3361
sewardjd529a442002-05-04 19:49:21 +00003362#ifndef GLIBC_2_1
sewardj3b13f0e2002-04-25 20:17:29 +00003363strong_alias(sigaction, __sigaction)
sewardjd529a442002-05-04 19:49:21 +00003364#endif
3365
sewardj5905fae2002-04-26 13:25:00 +00003366strong_alias(close, __close)
sewardj3b13f0e2002-04-25 20:17:29 +00003367strong_alias(fcntl, __fcntl)
sewardj5905fae2002-04-26 13:25:00 +00003368strong_alias(lseek, __lseek)
3369strong_alias(open, __open)
3370strong_alias(open64, __open64)
sewardj5905fae2002-04-26 13:25:00 +00003371strong_alias(read, __read)
3372strong_alias(wait, __wait)
3373strong_alias(write, __write)
sewardj3b13f0e2002-04-25 20:17:29 +00003374strong_alias(connect, __connect)
sewardj5905fae2002-04-26 13:25:00 +00003375strong_alias(send, __send)
3376
sewardj726c4122002-05-16 23:39:10 +00003377weak_alias (__pread64, pread64)
sewardja18e2102002-05-18 10:43:22 +00003378weak_alias (__pwrite64, pwrite64)
sewardj5905fae2002-04-26 13:25:00 +00003379weak_alias(__fork, fork)
njn25e49d8e72002-09-23 09:36:25 +00003380weak_alias(__vfork, vfork)
sewardj7f6456d2002-05-21 00:51:21 +00003381
sewardjf0b06452002-06-04 08:38:04 +00003382weak_alias (__pthread_kill_other_threads_np, pthread_kill_other_threads_np)
sewardj3b13f0e2002-04-25 20:17:29 +00003383
3384/*--------------------------------------------------*/
3385
sewardj5905fae2002-04-26 13:25:00 +00003386weak_alias(pthread_rwlock_rdlock, __pthread_rwlock_rdlock)
sewardj5905fae2002-04-26 13:25:00 +00003387weak_alias(pthread_rwlock_unlock, __pthread_rwlock_unlock)
sewardj262b0292002-05-01 00:03:16 +00003388weak_alias(pthread_rwlock_wrlock, __pthread_rwlock_wrlock)
sewardj060b04f2002-04-26 21:01:13 +00003389
sewardja1ac5cb2002-05-27 13:00:05 +00003390weak_alias(pthread_rwlock_destroy, __pthread_rwlock_destroy)
3391weak_alias(pthread_rwlock_init, __pthread_rwlock_init)
3392weak_alias(pthread_rwlock_tryrdlock, __pthread_rwlock_tryrdlock)
3393weak_alias(pthread_rwlock_trywrlock, __pthread_rwlock_trywrlock)
3394
sewardj060b04f2002-04-26 21:01:13 +00003395
sewardj3b13f0e2002-04-25 20:17:29 +00003396/* I've no idea what these are, but they get called quite a lot.
3397 Anybody know? */
3398
3399#undef _IO_flockfile
3400void _IO_flockfile ( _IO_FILE * file )
3401{
sewardj853f55d2002-04-26 00:27:53 +00003402 pthread_mutex_lock(file->_lock);
sewardj3b13f0e2002-04-25 20:17:29 +00003403}
sewardj5905fae2002-04-26 13:25:00 +00003404weak_alias(_IO_flockfile, flockfile);
3405
sewardj3b13f0e2002-04-25 20:17:29 +00003406
3407#undef _IO_funlockfile
3408void _IO_funlockfile ( _IO_FILE * file )
3409{
sewardj853f55d2002-04-26 00:27:53 +00003410 pthread_mutex_unlock(file->_lock);
sewardj3b13f0e2002-04-25 20:17:29 +00003411}
sewardj5905fae2002-04-26 13:25:00 +00003412weak_alias(_IO_funlockfile, funlockfile);
3413
sewardj3b13f0e2002-04-25 20:17:29 +00003414
sewardjd4f2c712002-04-30 10:20:10 +00003415/* This doesn't seem to be needed to simulate libpthread.so's external
3416 interface, but many people complain about its absence. */
3417
3418strong_alias(__pthread_mutexattr_settype, __pthread_mutexattr_setkind_np)
3419weak_alias(__pthread_mutexattr_setkind_np, pthread_mutexattr_setkind_np)
sewardj439d45e2002-05-03 20:43:10 +00003420
3421
3422/*--------------------------------------------------------------------*/
3423/*--- end vg_libpthread.c ---*/
3424/*--------------------------------------------------------------------*/