blob: d5641fd6e2ce652787809640f80804d5f8084253 [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
sewardje0cfe2a2002-11-30 14:04:45 +0000134/* Apparently unused.
sewardj08c7f012002-10-07 23:56:55 +0000135static
136void my_write ( int fd, const void *buf, int count )
137{
138 my_do_syscall3(__NR_write, fd, (int)buf, count );
139}
sewardje0cfe2a2002-11-30 14:04:45 +0000140*/
sewardje663cb92002-04-12 10:26:32 +0000141
sewardj68b2dd92002-05-10 21:03:56 +0000142/* We need this guy -- it's in valgrind.so. */
143extern void VG_(startup) ( void );
144
145
146/* Just start up Valgrind if it's not already going. VG_(startup)()
147 detects and ignores second and subsequent calls. */
sewardj604ec3c2002-04-18 22:38:41 +0000148static __inline__
sewardje663cb92002-04-12 10:26:32 +0000149void ensure_valgrind ( char* caller )
150{
sewardj68b2dd92002-05-10 21:03:56 +0000151 VG_(startup)();
sewardje663cb92002-04-12 10:26:32 +0000152}
153
sewardjbea1caa2002-05-10 23:20:58 +0000154/* While we're at it ... hook our own startup function into this
155 game. */
156__asm__ (
157 ".section .init\n"
158 "\tcall vgPlain_startup"
159);
160
sewardje663cb92002-04-12 10:26:32 +0000161
162static
sewardj3b5d8862002-04-20 13:53:23 +0000163__attribute__((noreturn))
sewardje663cb92002-04-12 10:26:32 +0000164void barf ( char* str )
165{
sewardj69a72a52002-11-03 13:41:41 +0000166 int res;
167 char buf[1000];
sewardje663cb92002-04-12 10:26:32 +0000168 buf[0] = 0;
sewardj439d45e2002-05-03 20:43:10 +0000169 strcat(buf, "\nvalgrind's libpthread.so: ");
sewardje663cb92002-04-12 10:26:32 +0000170 strcat(buf, str);
171 strcat(buf, "\n\n");
sewardj69a72a52002-11-03 13:41:41 +0000172 VALGRIND_MAGIC_SEQUENCE(res, 0, /* irrelevant default */
173 VG_USERREQ__LOGMESSAGE, buf, 0, 0, 0);
sewardj2d94c112002-06-03 01:25:54 +0000174 my_exit(1);
sewardj3b5d8862002-04-20 13:53:23 +0000175 /* We have to persuade gcc into believing this doesn't return. */
176 while (1) { };
sewardje663cb92002-04-12 10:26:32 +0000177}
178
179
sewardj69a72a52002-11-03 13:41:41 +0000180static void cat_n_send ( char* pre, char* msg )
sewardj2a3d28c2002-04-14 13:27:00 +0000181{
sewardj69a72a52002-11-03 13:41:41 +0000182 char buf[1000];
183 int res;
sewardj436e0582002-04-26 14:31:40 +0000184 if (get_pt_trace_level() >= 0) {
sewardj69a72a52002-11-03 13:41:41 +0000185 snprintf(buf, sizeof(buf), "%s%s", pre, msg );
186 buf[sizeof(buf)-1] = '\0';
187 VALGRIND_MAGIC_SEQUENCE(res, 0, /* irrelevant default */
188 VG_USERREQ__LOGMESSAGE, buf, 0, 0, 0);
sewardj45b4b372002-04-16 22:50:32 +0000189 }
sewardj2a3d28c2002-04-14 13:27:00 +0000190}
191
sewardj69a72a52002-11-03 13:41:41 +0000192static void ignored ( char* msg )
193{
194 cat_n_send ( "valgrind's libpthread.so: IGNORED call to: ", msg );
195}
196
197
sewardj30671ff2002-04-21 00:13:57 +0000198static void kludged ( char* msg )
199{
sewardj69a72a52002-11-03 13:41:41 +0000200 cat_n_send ( "valgrind's libpthread.so: KLUDGED call to: ", msg );
sewardj439d45e2002-05-03 20:43:10 +0000201}
202
sewardj69a72a52002-11-03 13:41:41 +0000203
sewardjccef2e62002-05-29 19:26:32 +0000204__attribute__((noreturn))
sewardj3b13f0e2002-04-25 20:17:29 +0000205void vgPlain_unimp ( char* what )
206{
sewardj69a72a52002-11-03 13:41:41 +0000207 cat_n_send (
208 "valgrind's libpthread.so: UNIMPLEMENTED FUNCTION: ", what );
sewardj3b13f0e2002-04-25 20:17:29 +0000209 barf("Please report this bug to me at: jseward@acm.org");
210}
211
sewardje663cb92002-04-12 10:26:32 +0000212
sewardj457cc472002-06-03 23:13:47 +0000213static
sewardj2d94c112002-06-03 01:25:54 +0000214void my_assert_fail ( Char* expr, Char* file, Int line, Char* fn )
215{
sewardj69a72a52002-11-03 13:41:41 +0000216 char buf[1000];
sewardj2d94c112002-06-03 01:25:54 +0000217 static Bool entered = False;
218 if (entered)
219 my_exit(2);
220 entered = True;
sewardj69a72a52002-11-03 13:41:41 +0000221 sprintf(buf, "\n%s: %s:%d (%s): Assertion `%s' failed.\n",
222 "valgrind", file, line, fn, expr );
223 cat_n_send ( "", buf );
224 sprintf(buf, "Please report this bug to me at: %s\n\n",
225 VG_EMAIL_ADDR);
226 cat_n_send ( "", buf );
sewardj2d94c112002-06-03 01:25:54 +0000227 my_exit(1);
228}
229
230#define MY__STRING(__str) #__str
231
232#define my_assert(expr) \
233 ((void) ((expr) ? 0 : \
234 (my_assert_fail (MY__STRING(expr), \
235 __FILE__, __LINE__, \
236 __PRETTY_FUNCTION__), 0)))
237
sewardj00a66b12002-10-12 16:42:35 +0000238static
239void my_free ( void* ptr )
240{
241 int res;
242 VALGRIND_MAGIC_SEQUENCE(res, (-1) /* default */,
243 VG_USERREQ__FREE, ptr, 0, 0, 0);
244 my_assert(res == 0);
245}
246
247
248static
249void* my_malloc ( int nbytes )
250{
251 void* res;
252 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
253 VG_USERREQ__MALLOC, nbytes, 0, 0, 0);
254 my_assert(res != (void*)0);
255 return res;
256}
257
258
sewardj2d94c112002-06-03 01:25:54 +0000259
sewardje663cb92002-04-12 10:26:32 +0000260/* ---------------------------------------------------------------------
261 Pass pthread_ calls to Valgrind's request mechanism.
262 ------------------------------------------------------------------ */
263
sewardjf8f819e2002-04-17 23:21:37 +0000264#include <errno.h>
sewardj5f07b662002-04-23 16:52:51 +0000265#include <sys/time.h> /* gettimeofday */
sewardjf8f819e2002-04-17 23:21:37 +0000266
sewardja1ac5cb2002-05-27 13:00:05 +0000267
sewardjf8f819e2002-04-17 23:21:37 +0000268/* ---------------------------------------------------
sewardj4dced352002-06-04 22:54:20 +0000269 Ummm ..
270 ------------------------------------------------ */
271
272static
273void pthread_error ( const char* msg )
274{
275 int res;
276 VALGRIND_MAGIC_SEQUENCE(res, 0,
277 VG_USERREQ__PTHREAD_ERROR,
278 msg, 0, 0, 0);
279}
280
281
282/* ---------------------------------------------------
sewardj00a66b12002-10-12 16:42:35 +0000283 Here so it can be inlined without complaint.
284 ------------------------------------------------ */
285
286__inline__
287pthread_t pthread_self(void)
288{
289 int tid;
290 ensure_valgrind("pthread_self");
291 VALGRIND_MAGIC_SEQUENCE(tid, 0 /* default */,
292 VG_USERREQ__PTHREAD_GET_THREADID,
293 0, 0, 0, 0);
294 if (tid < 1 || tid >= VG_N_THREADS)
295 barf("pthread_self: invalid ThreadId");
296 return tid;
297}
298
299
300/* ---------------------------------------------------
sewardjf8f819e2002-04-17 23:21:37 +0000301 THREAD ATTRIBUTES
302 ------------------------------------------------ */
303
sewardj6af4b5d2002-04-16 04:40:49 +0000304int pthread_attr_init(pthread_attr_t *attr)
305{
sewardj7989d0c2002-05-28 11:00:01 +0000306 /* Just initialise the fields which we might look at. */
307 attr->__detachstate = PTHREAD_CREATE_JOINABLE;
sewardj111b14c2002-10-20 16:22:57 +0000308 /* Linuxthreads sets this field to the value __getpagesize(), so I
309 guess the following is OK. */
310 attr->__guardsize = VKI_BYTES_PER_PAGE; return 0;
sewardj6af4b5d2002-04-16 04:40:49 +0000311}
312
313int pthread_attr_setdetachstate(pthread_attr_t *attr, int detachstate)
314{
sewardj7989d0c2002-05-28 11:00:01 +0000315 if (detachstate != PTHREAD_CREATE_JOINABLE
sewardj4dced352002-06-04 22:54:20 +0000316 && detachstate != PTHREAD_CREATE_DETACHED) {
317 pthread_error("pthread_attr_setdetachstate: "
318 "detachstate is invalid");
sewardj7989d0c2002-05-28 11:00:01 +0000319 return EINVAL;
sewardj4dced352002-06-04 22:54:20 +0000320 }
sewardj7989d0c2002-05-28 11:00:01 +0000321 attr->__detachstate = detachstate;
sewardj6af4b5d2002-04-16 04:40:49 +0000322 return 0;
323}
324
njn25e49d8e72002-09-23 09:36:25 +0000325int pthread_attr_getdetachstate(const pthread_attr_t *attr, int *detachstate)
326{
327 *detachstate = attr->__detachstate;
328 return 0;
329}
330
sewardj30671ff2002-04-21 00:13:57 +0000331int pthread_attr_setinheritsched(pthread_attr_t *attr, int inherit)
332{
sewardj436e0582002-04-26 14:31:40 +0000333 static int moans = N_MOANS;
334 if (moans-- > 0)
335 ignored("pthread_attr_setinheritsched");
sewardj30671ff2002-04-21 00:13:57 +0000336 return 0;
337}
sewardj6af4b5d2002-04-16 04:40:49 +0000338
sewardj0286dd52002-05-16 20:51:15 +0000339__attribute__((weak))
340int pthread_attr_setstacksize (pthread_attr_t *__attr,
341 size_t __stacksize)
342{
sewardja18e2102002-05-18 10:43:22 +0000343 size_t limit;
sewardj3d7c8d62002-06-04 20:59:16 +0000344 char buf[1024];
sewardj0286dd52002-05-16 20:51:15 +0000345 ensure_valgrind("pthread_attr_setstacksize");
sewardja18e2102002-05-18 10:43:22 +0000346 limit = VG_PTHREAD_STACK_SIZE - VG_AR_CLIENT_STACKBASE_REDZONE_SZB
347 - 1000; /* paranoia */
348 if (__stacksize < limit)
sewardj0286dd52002-05-16 20:51:15 +0000349 return 0;
sewardj3d7c8d62002-06-04 20:59:16 +0000350 snprintf(buf, sizeof(buf), "pthread_attr_setstacksize: "
351 "requested size %d >= VG_PTHREAD_STACK_SIZE\n "
352 "edit vg_include.h and rebuild.", __stacksize);
353 buf[sizeof(buf)-1] = '\0'; /* Make sure it is zero terminated */
354 barf(buf);
sewardj0286dd52002-05-16 20:51:15 +0000355}
356
357
sewardj30671ff2002-04-21 00:13:57 +0000358/* This is completely bogus. */
359int pthread_attr_getschedparam(const pthread_attr_t *attr,
360 struct sched_param *param)
361{
sewardj436e0582002-04-26 14:31:40 +0000362 static int moans = N_MOANS;
363 if (moans-- > 0)
364 kludged("pthread_attr_getschedparam");
sewardj3e909ce2002-06-03 13:27:15 +0000365# ifdef HAVE_SCHED_PRIORITY
sewardj72d58482002-04-24 02:20:20 +0000366 if (param) param->sched_priority = 0; /* who knows */
367# else
sewardj30671ff2002-04-21 00:13:57 +0000368 if (param) param->__sched_priority = 0; /* who knows */
sewardj72d58482002-04-24 02:20:20 +0000369# endif
sewardj30671ff2002-04-21 00:13:57 +0000370 return 0;
371}
372
373int pthread_attr_setschedparam(pthread_attr_t *attr,
374 const struct sched_param *param)
375{
sewardj436e0582002-04-26 14:31:40 +0000376 static int moans = N_MOANS;
377 if (moans-- > 0)
378 ignored("pthread_attr_setschedparam");
sewardj30671ff2002-04-21 00:13:57 +0000379 return 0;
380}
381
382int pthread_attr_destroy(pthread_attr_t *attr)
383{
sewardj436e0582002-04-26 14:31:40 +0000384 static int moans = N_MOANS;
385 if (moans-- > 0)
386 ignored("pthread_attr_destroy");
sewardj30671ff2002-04-21 00:13:57 +0000387 return 0;
388}
sewardjf8f819e2002-04-17 23:21:37 +0000389
sewardj0d844232002-06-02 09:29:31 +0000390/* These are no-ops, as with LinuxThreads. */
391int pthread_attr_setscope ( pthread_attr_t *attr, int scope )
392{
393 ensure_valgrind("pthread_attr_setscope");
394 if (scope == PTHREAD_SCOPE_SYSTEM)
395 return 0;
sewardj4dced352002-06-04 22:54:20 +0000396 pthread_error("pthread_attr_setscope: "
397 "invalid or unsupported scope");
sewardj0d844232002-06-02 09:29:31 +0000398 if (scope == PTHREAD_SCOPE_PROCESS)
399 return ENOTSUP;
400 return EINVAL;
401}
402
403int pthread_attr_getscope ( const pthread_attr_t *attr, int *scope )
404{
405 ensure_valgrind("pthread_attr_setscope");
406 if (scope)
407 *scope = PTHREAD_SCOPE_SYSTEM;
408 return 0;
409}
410
sewardj64039bb2002-06-03 00:58:18 +0000411
412/* Pretty bogus. Avoid if possible. */
413int pthread_getattr_np (pthread_t thread, pthread_attr_t *attr)
414{
415 int detached;
416 size_t limit;
417 ensure_valgrind("pthread_getattr_np");
418 kludged("pthread_getattr_np");
419 limit = VG_PTHREAD_STACK_SIZE - VG_AR_CLIENT_STACKBASE_REDZONE_SZB
420 - 1000; /* paranoia */
421 attr->__detachstate = PTHREAD_CREATE_JOINABLE;
422 attr->__schedpolicy = SCHED_OTHER;
423 attr->__schedparam.sched_priority = 0;
424 attr->__inheritsched = PTHREAD_EXPLICIT_SCHED;
425 attr->__scope = PTHREAD_SCOPE_SYSTEM;
426 attr->__guardsize = VKI_BYTES_PER_PAGE;
427 attr->__stackaddr = NULL;
428 attr->__stackaddr_set = 0;
429 attr->__stacksize = limit;
430 VALGRIND_MAGIC_SEQUENCE(detached, (-1) /* default */,
431 VG_USERREQ__SET_OR_GET_DETACH,
432 2 /* get */, thread, 0, 0);
sewardj2d94c112002-06-03 01:25:54 +0000433 my_assert(detached == 0 || detached == 1);
sewardj64039bb2002-06-03 00:58:18 +0000434 if (detached)
435 attr->__detachstate = PTHREAD_CREATE_DETACHED;
436 return 0;
437}
438
439
440/* Bogus ... */
sewardj111b14c2002-10-20 16:22:57 +0000441__attribute__((weak))
sewardj64039bb2002-06-03 00:58:18 +0000442int pthread_attr_getstackaddr ( const pthread_attr_t * attr,
443 void ** stackaddr )
444{
445 ensure_valgrind("pthread_attr_getstackaddr");
446 kludged("pthread_attr_getstackaddr");
447 if (stackaddr)
448 *stackaddr = NULL;
449 return 0;
450}
451
452/* Not bogus (!) */
sewardj111b14c2002-10-20 16:22:57 +0000453__attribute__((weak))
sewardj64039bb2002-06-03 00:58:18 +0000454int pthread_attr_getstacksize ( const pthread_attr_t * _attr,
455 size_t * __stacksize )
456{
457 size_t limit;
458 ensure_valgrind("pthread_attr_getstacksize");
459 limit = VG_PTHREAD_STACK_SIZE - VG_AR_CLIENT_STACKBASE_REDZONE_SZB
460 - 1000; /* paranoia */
461 if (__stacksize)
462 *__stacksize = limit;
463 return 0;
464}
465
sewardja3be12f2002-06-17 12:19:44 +0000466int pthread_attr_setschedpolicy(pthread_attr_t *attr, int policy)
467{
468 if (policy != SCHED_OTHER && policy != SCHED_FIFO && policy != SCHED_RR)
469 return EINVAL;
470 attr->__schedpolicy = policy;
471 return 0;
472}
473
474int pthread_attr_getschedpolicy(const pthread_attr_t *attr, int *policy)
475{
476 *policy = attr->__schedpolicy;
477 return 0;
478}
479
480
sewardj111b14c2002-10-20 16:22:57 +0000481/* This is completely bogus. We reject all attempts to change it from
482 VKI_BYTES_PER_PAGE. I don't have a clue what it's for so it seems
483 safest to be paranoid. */
484__attribute__((weak))
485int pthread_attr_setguardsize(pthread_attr_t *attr, size_t guardsize)
486{
487 static int moans = N_MOANS;
488
489 if (guardsize == VKI_BYTES_PER_PAGE)
490 return 0;
491
492 if (moans-- > 0)
493 ignored("pthread_attr_setguardsize: ignoring guardsize != 4096");
494
495 return 0;
496}
497
498/* A straight copy of the LinuxThreads code. */
499__attribute__((weak))
500int pthread_attr_getguardsize(const pthread_attr_t *attr, size_t *guardsize)
501{
502 *guardsize = attr->__guardsize;
503 return 0;
504}
505
506
sewardj20917d82002-05-28 01:36:45 +0000507/* ---------------------------------------------------
508 Helper functions for running a thread
509 and for clearing up afterwards.
510 ------------------------------------------------ */
511
512/* All exiting threads eventually pass through here, bearing the
513 return value, or PTHREAD_CANCELED, in ret_val. */
514static
515__attribute__((noreturn))
516void thread_exit_wrapper ( void* ret_val )
517{
sewardj870497a2002-05-29 01:06:47 +0000518 int detached, res;
519 CleanupEntry cu;
520 pthread_key_t key;
sewardj00a66b12002-10-12 16:42:35 +0000521 void** specifics_ptr;
sewardj870497a2002-05-29 01:06:47 +0000522
sewardj20917d82002-05-28 01:36:45 +0000523 /* Run this thread's cleanup handlers. */
sewardj8ad94e12002-05-29 00:10:20 +0000524 while (1) {
525 VALGRIND_MAGIC_SEQUENCE(res, (-1) /* default */,
526 VG_USERREQ__CLEANUP_POP,
527 &cu, 0, 0, 0);
528 if (res == -1) break; /* stack empty */
sewardj2d94c112002-06-03 01:25:54 +0000529 my_assert(res == 0);
sewardj8ad94e12002-05-29 00:10:20 +0000530 if (0) printf("running exit cleanup handler");
531 cu.fn ( cu.arg );
532 }
533
sewardj870497a2002-05-29 01:06:47 +0000534 /* Run this thread's key finalizers. Really this should be run
535 PTHREAD_DESTRUCTOR_ITERATIONS times. */
536 for (key = 0; key < VG_N_THREAD_KEYS; key++) {
537 VALGRIND_MAGIC_SEQUENCE(res, (-2) /* default */,
538 VG_USERREQ__GET_KEY_D_AND_S,
539 key, &cu, 0, 0 );
540 if (res == 0) {
541 /* valid key */
542 if (cu.fn && cu.arg)
543 cu.fn /* destructor for key */
544 ( cu.arg /* specific for key for this thread */ );
545 continue;
546 }
sewardj2d94c112002-06-03 01:25:54 +0000547 my_assert(res == -1);
sewardj870497a2002-05-29 01:06:47 +0000548 }
sewardj20917d82002-05-28 01:36:45 +0000549
sewardj00a66b12002-10-12 16:42:35 +0000550 /* Free up my specifics space, if any. */
551 VALGRIND_MAGIC_SEQUENCE(specifics_ptr, 3 /* default */,
552 VG_USERREQ__PTHREAD_GETSPECIFIC_PTR,
553 pthread_self(), 0, 0, 0);
554 my_assert(specifics_ptr != (void**)3);
555 my_assert(specifics_ptr != (void**)1); /* 1 means invalid thread */
556 if (specifics_ptr != NULL)
557 my_free(specifics_ptr);
558
sewardj20917d82002-05-28 01:36:45 +0000559 /* Decide on my final disposition. */
560 VALGRIND_MAGIC_SEQUENCE(detached, (-1) /* default */,
561 VG_USERREQ__SET_OR_GET_DETACH,
sewardj7989d0c2002-05-28 11:00:01 +0000562 2 /* get */, pthread_self(), 0, 0);
sewardj2d94c112002-06-03 01:25:54 +0000563 my_assert(detached == 0 || detached == 1);
sewardj20917d82002-05-28 01:36:45 +0000564
565 if (detached) {
566 /* Detached; I just quit right now. */
567 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
568 VG_USERREQ__QUIT, 0, 0, 0, 0);
569 } else {
570 /* Not detached; so I wait for a joiner. */
571 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
572 VG_USERREQ__WAIT_JOINER, ret_val, 0, 0, 0);
573 }
574 /* NOTREACHED */
575 barf("thread_exit_wrapper: still alive?!");
576}
577
578
579/* This function is a wrapper function for running a thread. It runs
580 the root function specified in pthread_create, and then, should the
581 root function return a value, it arranges to run the thread's
582 cleanup handlers and exit correctly. */
583
sewardj728a5272002-06-20 10:25:37 +0000584/* Struct used to convey info from pthread_create to thread_wrapper.
585 Must be careful not to pass to the child thread any pointers to
586 objects which might be on the parent's stack. */
sewardj20917d82002-05-28 01:36:45 +0000587typedef
588 struct {
sewardj728a5272002-06-20 10:25:37 +0000589 int attr__detachstate;
sewardj20917d82002-05-28 01:36:45 +0000590 void* (*root_fn) ( void* );
591 void* arg;
592 }
593 NewThreadInfo;
594
595
596/* This is passed to the VG_USERREQ__APPLY_IN_NEW_THREAD and so must
597 not return. Note that this runs in the new thread, not the
598 parent. */
599static
600__attribute__((noreturn))
601void thread_wrapper ( NewThreadInfo* info )
602{
sewardj728a5272002-06-20 10:25:37 +0000603 int attr__detachstate;
sewardj20917d82002-05-28 01:36:45 +0000604 void* (*root_fn) ( void* );
605 void* arg;
606 void* ret_val;
607
sewardj728a5272002-06-20 10:25:37 +0000608 attr__detachstate = info->attr__detachstate;
609 root_fn = info->root_fn;
610 arg = info->arg;
sewardj20917d82002-05-28 01:36:45 +0000611
sewardj20917d82002-05-28 01:36:45 +0000612 /* Free up the arg block that pthread_create malloced. */
sewardj00a66b12002-10-12 16:42:35 +0000613 my_free(info);
sewardj20917d82002-05-28 01:36:45 +0000614
sewardj7989d0c2002-05-28 11:00:01 +0000615 /* Minimally observe the attributes supplied. */
sewardj728a5272002-06-20 10:25:37 +0000616 if (attr__detachstate != PTHREAD_CREATE_DETACHED
617 && attr__detachstate != PTHREAD_CREATE_JOINABLE)
618 pthread_error("thread_wrapper: invalid attr->__detachstate");
619 if (attr__detachstate == PTHREAD_CREATE_DETACHED)
620 pthread_detach(pthread_self());
sewardj7989d0c2002-05-28 11:00:01 +0000621
sewardj00a66b12002-10-12 16:42:35 +0000622# ifdef GLIBC_2_3
623 /* Set this thread's locale to the global (default) locale. A hack
624 in support of glibc-2.3. This does the biz for the all new
625 threads; the root thread is done with a horrible hack in
626 init_libc_tsd_keys() below.
627 */
628 __uselocale(LC_GLOBAL_LOCALE);
629# endif
630
sewardj20917d82002-05-28 01:36:45 +0000631 /* The root function might not return. But if it does we simply
632 move along to thread_exit_wrapper. All other ways out for the
633 thread (cancellation, or calling pthread_exit) lead there
634 too. */
635 ret_val = root_fn(arg);
636 thread_exit_wrapper(ret_val);
637 /* NOTREACHED */
638}
639
640
sewardjf8f819e2002-04-17 23:21:37 +0000641/* ---------------------------------------------------
642 THREADs
643 ------------------------------------------------ */
644
sewardjff42d1d2002-05-22 13:17:31 +0000645__attribute__((weak))
646int pthread_yield ( void )
647{
648 int res;
649 ensure_valgrind("pthread_yield");
650 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
651 VG_USERREQ__PTHREAD_YIELD, 0, 0, 0, 0);
652 return 0;
653}
654
655
sewardj6072c362002-04-19 14:40:57 +0000656int pthread_equal(pthread_t thread1, pthread_t thread2)
657{
658 return thread1 == thread2 ? 1 : 0;
659}
660
661
sewardj20917d82002-05-28 01:36:45 +0000662/* Bundle up the args into a malloc'd block and create a new thread
663 consisting of thread_wrapper() applied to said malloc'd block. */
sewardje663cb92002-04-12 10:26:32 +0000664int
sewardj1462c8b2002-07-24 09:41:52 +0000665pthread_create (pthread_t *__restrict __thredd,
sewardje663cb92002-04-12 10:26:32 +0000666 __const pthread_attr_t *__restrict __attr,
667 void *(*__start_routine) (void *),
668 void *__restrict __arg)
669{
sewardj20917d82002-05-28 01:36:45 +0000670 int tid_child;
671 NewThreadInfo* info;
sewardje663cb92002-04-12 10:26:32 +0000672
sewardj20917d82002-05-28 01:36:45 +0000673 ensure_valgrind("pthread_create");
674
sewardj00a66b12002-10-12 16:42:35 +0000675 /* make sure the tsd keys, and hence locale info, are initialised
676 before we get into complications making new threads. */
677 init_libc_tsd_keys();
678
sewardj20917d82002-05-28 01:36:45 +0000679 /* Allocate space for the arg block. thread_wrapper will free
680 it. */
sewardj00a66b12002-10-12 16:42:35 +0000681 info = my_malloc(sizeof(NewThreadInfo));
sewardj2d94c112002-06-03 01:25:54 +0000682 my_assert(info != NULL);
sewardj20917d82002-05-28 01:36:45 +0000683
sewardj728a5272002-06-20 10:25:37 +0000684 if (__attr)
685 info->attr__detachstate = __attr->__detachstate;
686 else
687 info->attr__detachstate = PTHREAD_CREATE_JOINABLE;
688
sewardj20917d82002-05-28 01:36:45 +0000689 info->root_fn = __start_routine;
690 info->arg = __arg;
691 VALGRIND_MAGIC_SEQUENCE(tid_child, VG_INVALID_THREADID /* default */,
692 VG_USERREQ__APPLY_IN_NEW_THREAD,
693 &thread_wrapper, info, 0, 0);
sewardj2d94c112002-06-03 01:25:54 +0000694 my_assert(tid_child != VG_INVALID_THREADID);
sewardj20917d82002-05-28 01:36:45 +0000695
sewardj1462c8b2002-07-24 09:41:52 +0000696 if (__thredd)
697 *__thredd = tid_child;
sewardj20917d82002-05-28 01:36:45 +0000698 return 0; /* success */
699}
sewardje663cb92002-04-12 10:26:32 +0000700
701
702int
703pthread_join (pthread_t __th, void **__thread_return)
704{
705 int res;
706 ensure_valgrind("pthread_join");
707 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
708 VG_USERREQ__PTHREAD_JOIN,
709 __th, __thread_return, 0, 0);
710 return res;
711}
712
713
sewardj3b5d8862002-04-20 13:53:23 +0000714void pthread_exit(void *retval)
715{
sewardj3b5d8862002-04-20 13:53:23 +0000716 ensure_valgrind("pthread_exit");
sewardj20917d82002-05-28 01:36:45 +0000717 /* Simple! */
718 thread_exit_wrapper(retval);
sewardj3b5d8862002-04-20 13:53:23 +0000719}
720
sewardje663cb92002-04-12 10:26:32 +0000721
sewardj853f55d2002-04-26 00:27:53 +0000722int pthread_detach(pthread_t th)
723{
sewardj20917d82002-05-28 01:36:45 +0000724 int res;
725 ensure_valgrind("pthread_detach");
sewardj7989d0c2002-05-28 11:00:01 +0000726 /* First we enquire as to the current detach state. */
727 VALGRIND_MAGIC_SEQUENCE(res, (-2) /* default */,
sewardj20917d82002-05-28 01:36:45 +0000728 VG_USERREQ__SET_OR_GET_DETACH,
sewardj7989d0c2002-05-28 11:00:01 +0000729 2 /* get */, th, 0, 0);
sewardj4dced352002-06-04 22:54:20 +0000730 if (res == -1) {
731 /* not found */
732 pthread_error("pthread_detach: "
733 "invalid target thread");
sewardj7989d0c2002-05-28 11:00:01 +0000734 return ESRCH;
sewardj4dced352002-06-04 22:54:20 +0000735 }
736 if (res == 1) {
737 /* already detached */
738 pthread_error("pthread_detach: "
739 "target thread is already detached");
sewardj7989d0c2002-05-28 11:00:01 +0000740 return EINVAL;
sewardj4dced352002-06-04 22:54:20 +0000741 }
sewardj7989d0c2002-05-28 11:00:01 +0000742 if (res == 0) {
743 VALGRIND_MAGIC_SEQUENCE(res, (-2) /* default */,
744 VG_USERREQ__SET_OR_GET_DETACH,
745 1 /* set */, th, 0, 0);
sewardj2d94c112002-06-03 01:25:54 +0000746 my_assert(res == 0);
sewardj7989d0c2002-05-28 11:00:01 +0000747 return 0;
748 }
749 barf("pthread_detach");
sewardj853f55d2002-04-26 00:27:53 +0000750}
751
752
sewardjf8f819e2002-04-17 23:21:37 +0000753/* ---------------------------------------------------
sewardj8ad94e12002-05-29 00:10:20 +0000754 CLEANUP STACKS
755 ------------------------------------------------ */
756
757void _pthread_cleanup_push (struct _pthread_cleanup_buffer *__buffer,
758 void (*__routine) (void *),
759 void *__arg)
760{
761 int res;
762 CleanupEntry cu;
763 ensure_valgrind("_pthread_cleanup_push");
764 cu.fn = __routine;
765 cu.arg = __arg;
766 VALGRIND_MAGIC_SEQUENCE(res, (-1) /* default */,
767 VG_USERREQ__CLEANUP_PUSH,
768 &cu, 0, 0, 0);
sewardj2d94c112002-06-03 01:25:54 +0000769 my_assert(res == 0);
sewardj8ad94e12002-05-29 00:10:20 +0000770}
771
772
773void _pthread_cleanup_push_defer (struct _pthread_cleanup_buffer *__buffer,
774 void (*__routine) (void *),
775 void *__arg)
776{
777 /* As _pthread_cleanup_push, but first save the thread's original
778 cancellation type in __buffer and set it to Deferred. */
779 int orig_ctype;
780 ensure_valgrind("_pthread_cleanup_push_defer");
781 /* Set to Deferred, and put the old cancellation type in res. */
sewardj2d94c112002-06-03 01:25:54 +0000782 my_assert(-1 != PTHREAD_CANCEL_DEFERRED);
783 my_assert(-1 != PTHREAD_CANCEL_ASYNCHRONOUS);
784 my_assert(sizeof(struct _pthread_cleanup_buffer) >= sizeof(int));
sewardj8ad94e12002-05-29 00:10:20 +0000785 VALGRIND_MAGIC_SEQUENCE(orig_ctype, (-1) /* default */,
786 VG_USERREQ__SET_CANCELTYPE,
787 PTHREAD_CANCEL_DEFERRED, 0, 0, 0);
sewardj2d94c112002-06-03 01:25:54 +0000788 my_assert(orig_ctype != -1);
sewardj8ad94e12002-05-29 00:10:20 +0000789 *((int*)(__buffer)) = orig_ctype;
790 /* Now push the cleanup. */
791 _pthread_cleanup_push(NULL, __routine, __arg);
792}
793
794
795void _pthread_cleanup_pop (struct _pthread_cleanup_buffer *__buffer,
796 int __execute)
797{
798 int res;
799 CleanupEntry cu;
800 ensure_valgrind("_pthread_cleanup_push");
801 cu.fn = cu.arg = NULL; /* paranoia */
802 VALGRIND_MAGIC_SEQUENCE(res, (-1) /* default */,
803 VG_USERREQ__CLEANUP_POP,
804 &cu, 0, 0, 0);
805 if (res == 0) {
806 /* pop succeeded */
807 if (__execute) {
808 cu.fn ( cu.arg );
809 }
810 return;
811 }
812 if (res == -1) {
813 /* stack underflow */
814 return;
815 }
816 barf("_pthread_cleanup_pop");
817}
818
819
820void _pthread_cleanup_pop_restore (struct _pthread_cleanup_buffer *__buffer,
821 int __execute)
822{
823 int orig_ctype, fake_ctype;
824 /* As _pthread_cleanup_pop, but after popping/running the handler,
825 restore the thread's original cancellation type from the first
826 word of __buffer. */
827 _pthread_cleanup_pop(NULL, __execute);
828 orig_ctype = *((int*)(__buffer));
sewardj2d94c112002-06-03 01:25:54 +0000829 my_assert(orig_ctype == PTHREAD_CANCEL_DEFERRED
sewardj8ad94e12002-05-29 00:10:20 +0000830 || orig_ctype == PTHREAD_CANCEL_ASYNCHRONOUS);
sewardj2d94c112002-06-03 01:25:54 +0000831 my_assert(-1 != PTHREAD_CANCEL_DEFERRED);
832 my_assert(-1 != PTHREAD_CANCEL_ASYNCHRONOUS);
833 my_assert(sizeof(struct _pthread_cleanup_buffer) >= sizeof(int));
sewardj8ad94e12002-05-29 00:10:20 +0000834 VALGRIND_MAGIC_SEQUENCE(fake_ctype, (-1) /* default */,
835 VG_USERREQ__SET_CANCELTYPE,
836 orig_ctype, 0, 0, 0);
sewardj2d94c112002-06-03 01:25:54 +0000837 my_assert(fake_ctype == PTHREAD_CANCEL_DEFERRED);
sewardj8ad94e12002-05-29 00:10:20 +0000838}
839
840
841/* ---------------------------------------------------
sewardjf8f819e2002-04-17 23:21:37 +0000842 MUTEX ATTRIBUTES
843 ------------------------------------------------ */
844
sewardj5905fae2002-04-26 13:25:00 +0000845int __pthread_mutexattr_init(pthread_mutexattr_t *attr)
sewardje663cb92002-04-12 10:26:32 +0000846{
sewardjf8f819e2002-04-17 23:21:37 +0000847 attr->__mutexkind = PTHREAD_MUTEX_ERRORCHECK_NP;
sewardj8937c812002-04-12 20:12:20 +0000848 return 0;
sewardje663cb92002-04-12 10:26:32 +0000849}
850
sewardj5905fae2002-04-26 13:25:00 +0000851int __pthread_mutexattr_settype(pthread_mutexattr_t *attr, int type)
sewardjf8f819e2002-04-17 23:21:37 +0000852{
853 switch (type) {
sewardj3b13f0e2002-04-25 20:17:29 +0000854# ifndef GLIBC_2_1
sewardjf8f819e2002-04-17 23:21:37 +0000855 case PTHREAD_MUTEX_TIMED_NP:
sewardj2a1dcce2002-04-22 12:45:25 +0000856 case PTHREAD_MUTEX_ADAPTIVE_NP:
sewardj3b13f0e2002-04-25 20:17:29 +0000857# endif
sewardja1679dd2002-05-10 22:31:40 +0000858# ifdef GLIBC_2_1
sewardj68b2dd92002-05-10 21:03:56 +0000859 case PTHREAD_MUTEX_FAST_NP:
sewardja1679dd2002-05-10 22:31:40 +0000860# endif
sewardjf8f819e2002-04-17 23:21:37 +0000861 case PTHREAD_MUTEX_RECURSIVE_NP:
862 case PTHREAD_MUTEX_ERRORCHECK_NP:
sewardjf8f819e2002-04-17 23:21:37 +0000863 attr->__mutexkind = type;
864 return 0;
865 default:
sewardj4dced352002-06-04 22:54:20 +0000866 pthread_error("pthread_mutexattr_settype: "
867 "invalid type");
sewardjf8f819e2002-04-17 23:21:37 +0000868 return EINVAL;
869 }
870}
871
sewardj5905fae2002-04-26 13:25:00 +0000872int __pthread_mutexattr_destroy(pthread_mutexattr_t *attr)
sewardjf8f819e2002-04-17 23:21:37 +0000873{
874 return 0;
875}
876
877
878/* ---------------------------------------------------
879 MUTEXes
880 ------------------------------------------------ */
881
sewardj5905fae2002-04-26 13:25:00 +0000882int __pthread_mutex_init(pthread_mutex_t *mutex,
883 const pthread_mutexattr_t *mutexattr)
sewardje663cb92002-04-12 10:26:32 +0000884{
sewardj604ec3c2002-04-18 22:38:41 +0000885 mutex->__m_count = 0;
886 mutex->__m_owner = (_pthread_descr)VG_INVALID_THREADID;
887 mutex->__m_kind = PTHREAD_MUTEX_ERRORCHECK_NP;
888 if (mutexattr)
889 mutex->__m_kind = mutexattr->__mutexkind;
890 return 0;
sewardje663cb92002-04-12 10:26:32 +0000891}
892
sewardj439d45e2002-05-03 20:43:10 +0000893
sewardj5905fae2002-04-26 13:25:00 +0000894int __pthread_mutex_lock(pthread_mutex_t *mutex)
sewardje663cb92002-04-12 10:26:32 +0000895{
896 int res;
sewardjd8acdf22002-11-13 21:57:52 +0000897
sewardj439d45e2002-05-03 20:43:10 +0000898 if (RUNNING_ON_VALGRIND) {
sewardje663cb92002-04-12 10:26:32 +0000899 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
900 VG_USERREQ__PTHREAD_MUTEX_LOCK,
901 mutex, 0, 0, 0);
902 return res;
sewardj439d45e2002-05-03 20:43:10 +0000903 } else {
sewardjd8acdf22002-11-13 21:57:52 +0000904 /* Play at locking */
905 if (0)
906 kludged("prehistoric lock");
907 mutex->__m_owner = (_pthread_descr)1;
908 mutex->__m_count = 1;
909 mutex->__m_kind |= VG_PTHREAD_PREHISTORY;
sewardj439d45e2002-05-03 20:43:10 +0000910 return 0; /* success */
sewardje663cb92002-04-12 10:26:32 +0000911 }
912}
913
sewardj439d45e2002-05-03 20:43:10 +0000914
sewardj5905fae2002-04-26 13:25:00 +0000915int __pthread_mutex_trylock(pthread_mutex_t *mutex)
sewardj30671ff2002-04-21 00:13:57 +0000916{
917 int res;
sewardjd8acdf22002-11-13 21:57:52 +0000918
sewardj439d45e2002-05-03 20:43:10 +0000919 if (RUNNING_ON_VALGRIND) {
sewardj30671ff2002-04-21 00:13:57 +0000920 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
921 VG_USERREQ__PTHREAD_MUTEX_TRYLOCK,
922 mutex, 0, 0, 0);
923 return res;
sewardj439d45e2002-05-03 20:43:10 +0000924 } else {
sewardjd8acdf22002-11-13 21:57:52 +0000925 /* Play at locking */
926 if (0)
927 kludged("prehistoric trylock");
928 mutex->__m_owner = (_pthread_descr)1;
929 mutex->__m_count = 1;
930 mutex->__m_kind |= VG_PTHREAD_PREHISTORY;
931 return 0; /* success */
sewardj30671ff2002-04-21 00:13:57 +0000932 }
933}
934
sewardj439d45e2002-05-03 20:43:10 +0000935
sewardj5905fae2002-04-26 13:25:00 +0000936int __pthread_mutex_unlock(pthread_mutex_t *mutex)
sewardje663cb92002-04-12 10:26:32 +0000937{
938 int res;
sewardjd8acdf22002-11-13 21:57:52 +0000939
sewardj439d45e2002-05-03 20:43:10 +0000940 if (RUNNING_ON_VALGRIND) {
sewardje663cb92002-04-12 10:26:32 +0000941 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
942 VG_USERREQ__PTHREAD_MUTEX_UNLOCK,
943 mutex, 0, 0, 0);
944 return res;
sewardj439d45e2002-05-03 20:43:10 +0000945 } else {
sewardjd8acdf22002-11-13 21:57:52 +0000946 /* Play at locking */
947 if (0)
948 kludged("prehistoric unlock");
949 mutex->__m_owner = 0;
950 mutex->__m_count = 0;
951 mutex->__m_kind &= ~VG_PTHREAD_PREHISTORY;
952 return 0; /* success */
sewardje663cb92002-04-12 10:26:32 +0000953 }
954}
955
sewardj439d45e2002-05-03 20:43:10 +0000956
sewardj5905fae2002-04-26 13:25:00 +0000957int __pthread_mutex_destroy(pthread_mutex_t *mutex)
sewardje663cb92002-04-12 10:26:32 +0000958{
sewardj604ec3c2002-04-18 22:38:41 +0000959 /* Valgrind doesn't hold any resources on behalf of the mutex, so no
960 need to involve it. */
sewardj4dced352002-06-04 22:54:20 +0000961 if (mutex->__m_count > 0) {
sewardjd8acdf22002-11-13 21:57:52 +0000962 /* Oh, the horror. glibc's internal use of pthreads "knows"
963 that destroying a lock does an implicit unlock. Make it
964 explicit. */
965 __pthread_mutex_unlock(mutex);
966 pthread_error("pthread_mutex_destroy: "
967 "mutex is still in use");
968 return EBUSY;
sewardj4dced352002-06-04 22:54:20 +0000969 }
970 mutex->__m_count = 0;
971 mutex->__m_owner = (_pthread_descr)VG_INVALID_THREADID;
972 mutex->__m_kind = PTHREAD_MUTEX_ERRORCHECK_NP;
973 return 0;
sewardje663cb92002-04-12 10:26:32 +0000974}
975
976
sewardjf8f819e2002-04-17 23:21:37 +0000977/* ---------------------------------------------------
sewardj6072c362002-04-19 14:40:57 +0000978 CONDITION VARIABLES
979 ------------------------------------------------ */
980
981/* LinuxThreads supports no attributes for conditions. Hence ... */
982
983int pthread_condattr_init(pthread_condattr_t *attr)
984{
985 return 0;
986}
987
sewardj0738a592002-04-20 13:59:33 +0000988int pthread_condattr_destroy(pthread_condattr_t *attr)
989{
990 return 0;
991}
sewardj6072c362002-04-19 14:40:57 +0000992
993int pthread_cond_init( pthread_cond_t *cond,
994 const pthread_condattr_t *cond_attr)
995{
996 cond->__c_waiting = (_pthread_descr)VG_INVALID_THREADID;
997 return 0;
998}
999
sewardjf854f472002-04-21 12:19:41 +00001000int pthread_cond_destroy(pthread_cond_t *cond)
1001{
1002 /* should check that no threads are waiting on this CV */
sewardj436e0582002-04-26 14:31:40 +00001003 static int moans = N_MOANS;
1004 if (moans-- > 0)
1005 kludged("pthread_cond_destroy");
sewardjf854f472002-04-21 12:19:41 +00001006 return 0;
1007}
sewardj6072c362002-04-19 14:40:57 +00001008
1009/* ---------------------------------------------------
1010 SCHEDULING
1011 ------------------------------------------------ */
1012
1013/* This is completely bogus. */
1014int pthread_getschedparam(pthread_t target_thread,
1015 int *policy,
1016 struct sched_param *param)
1017{
sewardj436e0582002-04-26 14:31:40 +00001018 static int moans = N_MOANS;
1019 if (moans-- > 0)
1020 kludged("pthread_getschedparam");
sewardj6072c362002-04-19 14:40:57 +00001021 if (policy) *policy = SCHED_OTHER;
sewardj3e909ce2002-06-03 13:27:15 +00001022# ifdef HAVE_SCHED_PRIORITY
sewardj2a1dcce2002-04-22 12:45:25 +00001023 if (param) param->sched_priority = 0; /* who knows */
1024# else
sewardj6072c362002-04-19 14:40:57 +00001025 if (param) param->__sched_priority = 0; /* who knows */
sewardj2a1dcce2002-04-22 12:45:25 +00001026# endif
sewardj6072c362002-04-19 14:40:57 +00001027 return 0;
1028}
1029
1030int pthread_setschedparam(pthread_t target_thread,
1031 int policy,
1032 const struct sched_param *param)
1033{
sewardj436e0582002-04-26 14:31:40 +00001034 static int moans = N_MOANS;
1035 if (moans-- > 0)
1036 ignored("pthread_setschedparam");
sewardj6072c362002-04-19 14:40:57 +00001037 return 0;
1038}
1039
sewardj3b5d8862002-04-20 13:53:23 +00001040int pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex)
1041{
1042 int res;
1043 ensure_valgrind("pthread_cond_wait");
1044 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
1045 VG_USERREQ__PTHREAD_COND_WAIT,
1046 cond, mutex, 0, 0);
1047 return res;
1048}
1049
sewardj5f07b662002-04-23 16:52:51 +00001050int pthread_cond_timedwait ( pthread_cond_t *cond,
1051 pthread_mutex_t *mutex,
1052 const struct timespec *abstime )
1053{
1054 int res;
1055 unsigned int ms_now, ms_end;
1056 struct timeval timeval_now;
1057 unsigned long long int ull_ms_now_after_1970;
1058 unsigned long long int ull_ms_end_after_1970;
1059
1060 ensure_valgrind("pthread_cond_timedwait");
1061 VALGRIND_MAGIC_SEQUENCE(ms_now, 0xFFFFFFFF /* default */,
1062 VG_USERREQ__READ_MILLISECOND_TIMER,
1063 0, 0, 0, 0);
sewardj2d94c112002-06-03 01:25:54 +00001064 my_assert(ms_now != 0xFFFFFFFF);
sewardj5f07b662002-04-23 16:52:51 +00001065 res = gettimeofday(&timeval_now, NULL);
sewardj2d94c112002-06-03 01:25:54 +00001066 my_assert(res == 0);
sewardj5f07b662002-04-23 16:52:51 +00001067
1068 ull_ms_now_after_1970
1069 = 1000ULL * ((unsigned long long int)(timeval_now.tv_sec))
1070 + ((unsigned long long int)(timeval_now.tv_usec / 1000000));
1071 ull_ms_end_after_1970
1072 = 1000ULL * ((unsigned long long int)(abstime->tv_sec))
1073 + ((unsigned long long int)(abstime->tv_nsec / 1000000));
sewardjd8e919e2002-05-29 20:13:53 +00001074 if (ull_ms_end_after_1970 < ull_ms_now_after_1970)
1075 ull_ms_end_after_1970 = ull_ms_now_after_1970;
sewardj5f07b662002-04-23 16:52:51 +00001076 ms_end
1077 = ms_now + (unsigned int)(ull_ms_end_after_1970 - ull_ms_now_after_1970);
1078 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
1079 VG_USERREQ__PTHREAD_COND_TIMEDWAIT,
1080 cond, mutex, ms_end, 0);
1081 return res;
1082}
1083
1084
sewardj3b5d8862002-04-20 13:53:23 +00001085int pthread_cond_signal(pthread_cond_t *cond)
1086{
1087 int res;
1088 ensure_valgrind("pthread_cond_signal");
1089 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
1090 VG_USERREQ__PTHREAD_COND_SIGNAL,
1091 cond, 0, 0, 0);
1092 return res;
1093}
1094
1095int pthread_cond_broadcast(pthread_cond_t *cond)
1096{
1097 int res;
1098 ensure_valgrind("pthread_cond_broadcast");
1099 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
1100 VG_USERREQ__PTHREAD_COND_BROADCAST,
1101 cond, 0, 0, 0);
1102 return res;
1103}
1104
sewardj6072c362002-04-19 14:40:57 +00001105
1106/* ---------------------------------------------------
sewardjf8f819e2002-04-17 23:21:37 +00001107 CANCELLATION
1108 ------------------------------------------------ */
1109
sewardj853f55d2002-04-26 00:27:53 +00001110int pthread_setcancelstate(int state, int *oldstate)
1111{
sewardj20917d82002-05-28 01:36:45 +00001112 int res;
1113 ensure_valgrind("pthread_setcancelstate");
1114 if (state != PTHREAD_CANCEL_ENABLE
sewardj4dced352002-06-04 22:54:20 +00001115 && state != PTHREAD_CANCEL_DISABLE) {
1116 pthread_error("pthread_setcancelstate: "
1117 "invalid state");
sewardj20917d82002-05-28 01:36:45 +00001118 return EINVAL;
sewardj4dced352002-06-04 22:54:20 +00001119 }
sewardj2d94c112002-06-03 01:25:54 +00001120 my_assert(-1 != PTHREAD_CANCEL_ENABLE);
1121 my_assert(-1 != PTHREAD_CANCEL_DISABLE);
sewardj20917d82002-05-28 01:36:45 +00001122 VALGRIND_MAGIC_SEQUENCE(res, (-1) /* default */,
1123 VG_USERREQ__SET_CANCELSTATE,
1124 state, 0, 0, 0);
sewardj2d94c112002-06-03 01:25:54 +00001125 my_assert(res != -1);
sewardj20917d82002-05-28 01:36:45 +00001126 if (oldstate)
1127 *oldstate = res;
sewardj853f55d2002-04-26 00:27:53 +00001128 return 0;
1129}
1130
sewardje663cb92002-04-12 10:26:32 +00001131int pthread_setcanceltype(int type, int *oldtype)
1132{
sewardj20917d82002-05-28 01:36:45 +00001133 int res;
1134 ensure_valgrind("pthread_setcanceltype");
1135 if (type != PTHREAD_CANCEL_DEFERRED
sewardj4dced352002-06-04 22:54:20 +00001136 && type != PTHREAD_CANCEL_ASYNCHRONOUS) {
1137 pthread_error("pthread_setcanceltype: "
1138 "invalid type");
sewardj20917d82002-05-28 01:36:45 +00001139 return EINVAL;
sewardj4dced352002-06-04 22:54:20 +00001140 }
sewardj2d94c112002-06-03 01:25:54 +00001141 my_assert(-1 != PTHREAD_CANCEL_DEFERRED);
1142 my_assert(-1 != PTHREAD_CANCEL_ASYNCHRONOUS);
sewardj20917d82002-05-28 01:36:45 +00001143 VALGRIND_MAGIC_SEQUENCE(res, (-1) /* default */,
1144 VG_USERREQ__SET_CANCELTYPE,
1145 type, 0, 0, 0);
sewardj2d94c112002-06-03 01:25:54 +00001146 my_assert(res != -1);
sewardj20917d82002-05-28 01:36:45 +00001147 if (oldtype)
1148 *oldtype = res;
sewardje663cb92002-04-12 10:26:32 +00001149 return 0;
1150}
1151
sewardje663cb92002-04-12 10:26:32 +00001152int pthread_cancel(pthread_t thread)
1153{
1154 int res;
1155 ensure_valgrind("pthread_cancel");
sewardj20917d82002-05-28 01:36:45 +00001156 VALGRIND_MAGIC_SEQUENCE(res, (-1) /* default */,
1157 VG_USERREQ__SET_CANCELPEND,
1158 thread, &thread_exit_wrapper, 0, 0);
sewardj2d94c112002-06-03 01:25:54 +00001159 my_assert(res != -1);
sewardje663cb92002-04-12 10:26:32 +00001160 return res;
1161}
1162
sewardjd140e442002-05-29 01:21:19 +00001163static __inline__
1164void __my_pthread_testcancel(void)
sewardj853f55d2002-04-26 00:27:53 +00001165{
sewardj20917d82002-05-28 01:36:45 +00001166 int res;
njn25e49d8e72002-09-23 09:36:25 +00001167 ensure_valgrind("__my_pthread_testcancel");
sewardj20917d82002-05-28 01:36:45 +00001168 VALGRIND_MAGIC_SEQUENCE(res, (-1) /* default */,
1169 VG_USERREQ__TESTCANCEL,
1170 0, 0, 0, 0);
sewardj2d94c112002-06-03 01:25:54 +00001171 my_assert(res == 0);
sewardj853f55d2002-04-26 00:27:53 +00001172}
1173
sewardjd140e442002-05-29 01:21:19 +00001174void pthread_testcancel ( void )
1175{
1176 __my_pthread_testcancel();
1177}
1178
sewardj20917d82002-05-28 01:36:45 +00001179
sewardjef037c72002-05-30 00:40:03 +00001180/* Not really sure what this is for. I suspect for doing the POSIX
1181 requirements for fork() and exec(). We do this internally anyway
1182 whenever those syscalls are observed, so this could be superfluous,
1183 but hey ...
1184*/
sewardj853f55d2002-04-26 00:27:53 +00001185void __pthread_kill_other_threads_np ( void )
1186{
sewardjef037c72002-05-30 00:40:03 +00001187 int res;
1188 ensure_valgrind("__pthread_kill_other_threads_np");
1189 VALGRIND_MAGIC_SEQUENCE(res, (-1) /* default */,
1190 VG_USERREQ__NUKE_OTHER_THREADS,
1191 0, 0, 0, 0);
sewardj2d94c112002-06-03 01:25:54 +00001192 my_assert(res == 0);
sewardj853f55d2002-04-26 00:27:53 +00001193}
1194
sewardje663cb92002-04-12 10:26:32 +00001195
sewardjf8f819e2002-04-17 23:21:37 +00001196/* ---------------------------------------------------
sewardjb48e5002002-05-13 00:16:03 +00001197 SIGNALS
1198 ------------------------------------------------ */
1199
1200#include <signal.h>
1201
1202int pthread_sigmask(int how, const sigset_t *newmask,
1203 sigset_t *oldmask)
1204{
1205 int res;
1206
1207 /* A bit subtle, because the scheduler expects newmask and oldmask
1208 to be vki_sigset_t* rather than sigset_t*, and the two are
1209 different. Fortunately the first 64 bits of a sigset_t are
1210 exactly a vki_sigset_t, so we just pass the pointers through
1211 unmodified. Haaaack!
1212
1213 Also mash the how value so that the SIG_ constants from glibc
sewardj018f7622002-05-15 21:13:39 +00001214 constants to VKI_ constants, so that the former do not have to
1215 be included into vg_scheduler.c. */
sewardjb48e5002002-05-13 00:16:03 +00001216
1217 ensure_valgrind("pthread_sigmask");
1218
1219 switch (how) {
sewardj018f7622002-05-15 21:13:39 +00001220 case SIG_SETMASK: how = VKI_SIG_SETMASK; break;
1221 case SIG_BLOCK: how = VKI_SIG_BLOCK; break;
1222 case SIG_UNBLOCK: how = VKI_SIG_UNBLOCK; break;
sewardj4dced352002-06-04 22:54:20 +00001223 default: pthread_error("pthread_sigmask: invalid how");
1224 return EINVAL;
sewardjb48e5002002-05-13 00:16:03 +00001225 }
1226
1227 /* Crude check */
1228 if (newmask == NULL)
1229 return EFAULT;
1230
1231 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
1232 VG_USERREQ__PTHREAD_SIGMASK,
1233 how, newmask, oldmask, 0);
1234
1235 /* The scheduler tells us of any memory violations. */
1236 return res == 0 ? 0 : EFAULT;
1237}
1238
1239
1240int sigwait ( const sigset_t* set, int* sig )
1241{
1242 int res;
1243 ensure_valgrind("sigwait");
1244 /* As with pthread_sigmask we deliberately confuse sigset_t with
1245 vki_ksigset_t. */
1246 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
1247 VG_USERREQ__SIGWAIT,
1248 set, sig, 0, 0);
1249 return res;
1250}
1251
1252
sewardj018f7622002-05-15 21:13:39 +00001253int pthread_kill(pthread_t thread, int signo)
1254{
1255 int res;
1256 ensure_valgrind("pthread_kill");
1257 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
1258 VG_USERREQ__PTHREAD_KILL,
1259 thread, signo, 0, 0);
1260 return res;
1261}
1262
1263
sewardj3665ded2002-05-16 16:57:25 +00001264/* Copied verbatim from Linuxthreads */
1265/* Redefine raise() to send signal to calling thread only,
1266 as per POSIX 1003.1c */
1267int raise (int sig)
1268{
1269 int retcode = pthread_kill(pthread_self(), sig);
sewardj4dced352002-06-04 22:54:20 +00001270 if (retcode == 0) {
sewardj3665ded2002-05-16 16:57:25 +00001271 return 0;
sewardj4dced352002-06-04 22:54:20 +00001272 } else {
sewardj3665ded2002-05-16 16:57:25 +00001273 errno = retcode;
1274 return -1;
1275 }
1276}
1277
1278
sewardj9a2224b2002-06-19 10:17:40 +00001279int pause ( void )
1280{
1281 unsigned int n_orig, n_now;
1282 struct vki_timespec nanosleep_interval;
1283 ensure_valgrind("pause");
1284
1285 /* This is surely a cancellation point. */
1286 __my_pthread_testcancel();
1287
1288 VALGRIND_MAGIC_SEQUENCE(n_orig, 0xFFFFFFFF /* default */,
1289 VG_USERREQ__GET_N_SIGS_RETURNED,
1290 0, 0, 0, 0);
1291 my_assert(n_orig != 0xFFFFFFFF);
1292
1293 while (1) {
1294 VALGRIND_MAGIC_SEQUENCE(n_now, 0xFFFFFFFF /* default */,
1295 VG_USERREQ__GET_N_SIGS_RETURNED,
1296 0, 0, 0, 0);
1297 my_assert(n_now != 0xFFFFFFFF);
1298 my_assert(n_now >= n_orig);
1299 if (n_now != n_orig) break;
1300
1301 nanosleep_interval.tv_sec = 0;
njn25e49d8e72002-09-23 09:36:25 +00001302 nanosleep_interval.tv_nsec = 12 * 1000 * 1000; /* 12 milliseconds */
sewardj9a2224b2002-06-19 10:17:40 +00001303 /* It's critical here that valgrind's nanosleep implementation
1304 is nonblocking. */
1305 (void)my_do_syscall2(__NR_nanosleep,
1306 (int)(&nanosleep_interval), (int)NULL);
1307 }
1308
1309 * (__errno_location()) = EINTR;
1310 return -1;
1311}
1312
1313
sewardjb48e5002002-05-13 00:16:03 +00001314/* ---------------------------------------------------
sewardjf8f819e2002-04-17 23:21:37 +00001315 THREAD-SPECIFICs
1316 ------------------------------------------------ */
sewardj5e5fa512002-04-14 13:13:05 +00001317
sewardj00a66b12002-10-12 16:42:35 +00001318static
1319int key_is_valid (pthread_key_t key)
1320{
1321 int res;
1322 VALGRIND_MAGIC_SEQUENCE(res, 2 /* default */,
1323 VG_USERREQ__PTHREAD_KEY_VALIDATE,
1324 key, 0, 0, 0);
1325 my_assert(res != 2);
1326 return res;
1327}
1328
1329
1330/* Returns NULL if thread is invalid. Otherwise, if the thread
1331 already has a specifics area, return that. Otherwise allocate it
1332 one. */
1333static
1334void** get_or_allocate_specifics_ptr ( pthread_t thread )
1335{
1336 int res, i;
1337 void** specifics_ptr;
1338 ensure_valgrind("get_or_allocate_specifics_ptr");
1339
1340 /* Returns zero if the thread has no specific_ptr. One if thread
1341 is invalid. Otherwise, the specific_ptr value. This is
1342 allocated with my_malloc and so is aligned and cannot be
1343 confused with 1 or 3. */
1344 VALGRIND_MAGIC_SEQUENCE(specifics_ptr, 3 /* default */,
1345 VG_USERREQ__PTHREAD_GETSPECIFIC_PTR,
1346 thread, 0, 0, 0);
1347 my_assert(specifics_ptr != (void**)3);
1348
1349 if (specifics_ptr == (void**)1)
1350 return NULL; /* invalid thread */
1351
1352 if (specifics_ptr != NULL)
1353 return specifics_ptr; /* already has a specifics ptr. */
1354
1355 /* None yet ... allocate a new one. Should never fail. */
1356 specifics_ptr = my_malloc( VG_N_THREAD_KEYS * sizeof(void*) );
1357 my_assert(specifics_ptr != NULL);
1358
1359 VALGRIND_MAGIC_SEQUENCE(res, -1 /* default */,
1360 VG_USERREQ__PTHREAD_SETSPECIFIC_PTR,
1361 specifics_ptr, 0, 0, 0);
1362 my_assert(res == 0);
1363
1364 /* POSIX sez: "Upon thread creation, the value NULL shall be
1365 associated with all defined keys in the new thread." This
1366 allocation is in effect a delayed allocation of the specific
1367 data for a thread, at its first-use. Hence we initialise it
1368 here. */
1369 for (i = 0; i < VG_N_THREAD_KEYS; i++) {
1370 specifics_ptr[i] = NULL;
1371 }
1372
1373 return specifics_ptr;
1374}
1375
1376
sewardj5905fae2002-04-26 13:25:00 +00001377int __pthread_key_create(pthread_key_t *key,
1378 void (*destr_function) (void *))
sewardj5e5fa512002-04-14 13:13:05 +00001379{
sewardj00a66b12002-10-12 16:42:35 +00001380 void** specifics_ptr;
1381 int res, i;
sewardj5f07b662002-04-23 16:52:51 +00001382 ensure_valgrind("pthread_key_create");
sewardj00a66b12002-10-12 16:42:35 +00001383
1384 /* This writes *key if successful. It should never fail. */
1385 VALGRIND_MAGIC_SEQUENCE(res, 1 /* default */,
sewardj5f07b662002-04-23 16:52:51 +00001386 VG_USERREQ__PTHREAD_KEY_CREATE,
1387 key, destr_function, 0, 0);
sewardj00a66b12002-10-12 16:42:35 +00001388 my_assert(res == 0);
1389
1390 /* POSIX sez: "Upon key creation, the value NULL shall be
1391 associated with the new key in all active threads." */
1392 for (i = 0; i < VG_N_THREADS; i++) {
1393 specifics_ptr = get_or_allocate_specifics_ptr(i);
1394 /* we get NULL if i is an invalid thread. */
1395 if (specifics_ptr != NULL)
1396 specifics_ptr[*key] = NULL;
1397 }
1398
sewardj5f07b662002-04-23 16:52:51 +00001399 return res;
sewardj5e5fa512002-04-14 13:13:05 +00001400}
1401
1402int pthread_key_delete(pthread_key_t key)
1403{
sewardj00a66b12002-10-12 16:42:35 +00001404 int res;
1405 ensure_valgrind("pthread_key_create");
1406 if (!key_is_valid(key))
1407 return EINVAL;
1408 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
1409 VG_USERREQ__PTHREAD_KEY_DELETE,
1410 key, 0, 0, 0);
1411 my_assert(res == 0);
sewardj5e5fa512002-04-14 13:13:05 +00001412 return 0;
1413}
1414
sewardj5905fae2002-04-26 13:25:00 +00001415int __pthread_setspecific(pthread_key_t key, const void *pointer)
sewardj5e5fa512002-04-14 13:13:05 +00001416{
sewardj00a66b12002-10-12 16:42:35 +00001417 void** specifics_ptr;
sewardj5f07b662002-04-23 16:52:51 +00001418 ensure_valgrind("pthread_setspecific");
sewardj00a66b12002-10-12 16:42:35 +00001419
1420 if (!key_is_valid(key))
1421 return EINVAL;
1422
1423 specifics_ptr = get_or_allocate_specifics_ptr(pthread_self());
1424 specifics_ptr[key] = (void*)pointer;
1425 return 0;
sewardj5e5fa512002-04-14 13:13:05 +00001426}
1427
sewardj5905fae2002-04-26 13:25:00 +00001428void * __pthread_getspecific(pthread_key_t key)
sewardj5e5fa512002-04-14 13:13:05 +00001429{
sewardj00a66b12002-10-12 16:42:35 +00001430 void** specifics_ptr;
sewardj5f07b662002-04-23 16:52:51 +00001431 ensure_valgrind("pthread_getspecific");
sewardj00a66b12002-10-12 16:42:35 +00001432
1433 if (!key_is_valid(key))
1434 return NULL;
1435
1436 specifics_ptr = get_or_allocate_specifics_ptr(pthread_self());
1437 return specifics_ptr[key];
1438}
1439
1440
sewardj9aa918d2002-10-20 16:25:55 +00001441#ifdef GLIBC_2_3
sewardj00a66b12002-10-12 16:42:35 +00001442static
1443void ** __pthread_getspecific_addr(pthread_key_t key)
1444{
1445 void** specifics_ptr;
1446 ensure_valgrind("pthread_getspecific_addr");
1447
1448 if (!key_is_valid(key))
1449 return NULL;
1450
1451 specifics_ptr = get_or_allocate_specifics_ptr(pthread_self());
1452 return &(specifics_ptr[key]);
sewardj5e5fa512002-04-14 13:13:05 +00001453}
sewardj9aa918d2002-10-20 16:25:55 +00001454#endif
sewardjf8f819e2002-04-17 23:21:37 +00001455
1456/* ---------------------------------------------------
sewardj89d3d852002-04-24 19:21:39 +00001457 ONCEry
1458 ------------------------------------------------ */
1459
1460static pthread_mutex_t once_masterlock = PTHREAD_MUTEX_INITIALIZER;
1461
1462
sewardj5905fae2002-04-26 13:25:00 +00001463int __pthread_once ( pthread_once_t *once_control,
1464 void (*init_routine) (void) )
sewardj89d3d852002-04-24 19:21:39 +00001465{
1466 int res;
1467 ensure_valgrind("pthread_once");
1468
sewardj68b2dd92002-05-10 21:03:56 +00001469 res = __pthread_mutex_lock(&once_masterlock);
sewardj89d3d852002-04-24 19:21:39 +00001470
sewardj68b2dd92002-05-10 21:03:56 +00001471 if (res != 0) {
sewardj89d3d852002-04-24 19:21:39 +00001472 barf("pthread_once: Looks like your program's "
1473 "init routine calls back to pthread_once() ?!");
sewardj68b2dd92002-05-10 21:03:56 +00001474 }
sewardj89d3d852002-04-24 19:21:39 +00001475
1476 if (*once_control == 0) {
1477 *once_control = 1;
1478 init_routine();
1479 }
1480
sewardj68b2dd92002-05-10 21:03:56 +00001481 __pthread_mutex_unlock(&once_masterlock);
sewardj89d3d852002-04-24 19:21:39 +00001482
1483 return 0;
1484}
1485
1486
1487/* ---------------------------------------------------
sewardj853f55d2002-04-26 00:27:53 +00001488 MISC
1489 ------------------------------------------------ */
1490
sewardj2cb00342002-06-28 01:46:26 +00001491static pthread_mutex_t pthread_atfork_lock
1492 = PTHREAD_MUTEX_INITIALIZER;
1493
sewardj5905fae2002-04-26 13:25:00 +00001494int __pthread_atfork ( void (*prepare)(void),
1495 void (*parent)(void),
1496 void (*child)(void) )
sewardj853f55d2002-04-26 00:27:53 +00001497{
sewardj2cb00342002-06-28 01:46:26 +00001498 int n, res;
1499 ForkHandlerEntry entry;
1500
1501 ensure_valgrind("pthread_atfork");
1502 __pthread_mutex_lock(&pthread_atfork_lock);
1503
1504 /* Fetch old counter */
1505 VALGRIND_MAGIC_SEQUENCE(n, -2 /* default */,
1506 VG_USERREQ__GET_FHSTACK_USED,
1507 0, 0, 0, 0);
1508 my_assert(n >= 0 && n < VG_N_FORKHANDLERSTACK);
1509 if (n == VG_N_FORKHANDLERSTACK-1)
1510 barf("pthread_atfork: VG_N_FORKHANDLERSTACK is too low; "
1511 "increase and recompile");
1512
1513 /* Add entry */
1514 entry.prepare = *prepare;
1515 entry.parent = *parent;
1516 entry.child = *child;
1517 VALGRIND_MAGIC_SEQUENCE(res, -2 /* default */,
1518 VG_USERREQ__SET_FHSTACK_ENTRY,
1519 n, &entry, 0, 0);
1520 my_assert(res == 0);
1521
1522 /* Bump counter */
1523 VALGRIND_MAGIC_SEQUENCE(res, -2 /* default */,
1524 VG_USERREQ__SET_FHSTACK_USED,
1525 n+1, 0, 0, 0);
1526 my_assert(res == 0);
1527
1528 __pthread_mutex_unlock(&pthread_atfork_lock);
1529 return 0;
sewardj853f55d2002-04-26 00:27:53 +00001530}
1531
1532
sewardjbb990782002-05-08 02:01:14 +00001533__attribute__((weak))
1534void __pthread_initialize ( void )
1535{
sewardjbea1caa2002-05-10 23:20:58 +00001536 ensure_valgrind("__pthread_initialize");
sewardjbb990782002-05-08 02:01:14 +00001537}
1538
1539
sewardj853f55d2002-04-26 00:27:53 +00001540/* ---------------------------------------------------
sewardj3b13f0e2002-04-25 20:17:29 +00001541 LIBRARY-PRIVATE THREAD SPECIFIC STATE
sewardjf8f819e2002-04-17 23:21:37 +00001542 ------------------------------------------------ */
1543
sewardj3b13f0e2002-04-25 20:17:29 +00001544#include <resolv.h>
1545static int thread_specific_errno[VG_N_THREADS];
1546static int thread_specific_h_errno[VG_N_THREADS];
1547static struct __res_state
1548 thread_specific_res_state[VG_N_THREADS];
sewardjf8f819e2002-04-17 23:21:37 +00001549
sewardj3b13f0e2002-04-25 20:17:29 +00001550int* __errno_location ( void )
sewardjf8f819e2002-04-17 23:21:37 +00001551{
1552 int tid;
sewardj3b13f0e2002-04-25 20:17:29 +00001553 /* ensure_valgrind("__errno_location"); */
1554 VALGRIND_MAGIC_SEQUENCE(tid, 1 /* default */,
sewardjf8f819e2002-04-17 23:21:37 +00001555 VG_USERREQ__PTHREAD_GET_THREADID,
1556 0, 0, 0, 0);
sewardj3b13f0e2002-04-25 20:17:29 +00001557 /* 'cos I'm paranoid ... */
sewardj439d45e2002-05-03 20:43:10 +00001558 if (tid < 1 || tid >= VG_N_THREADS)
sewardj3b13f0e2002-04-25 20:17:29 +00001559 barf("__errno_location: invalid ThreadId");
1560 return & thread_specific_errno[tid];
1561}
1562
1563int* __h_errno_location ( void )
1564{
1565 int tid;
1566 /* ensure_valgrind("__h_errno_location"); */
1567 VALGRIND_MAGIC_SEQUENCE(tid, 1 /* default */,
1568 VG_USERREQ__PTHREAD_GET_THREADID,
1569 0, 0, 0, 0);
1570 /* 'cos I'm paranoid ... */
sewardj439d45e2002-05-03 20:43:10 +00001571 if (tid < 1 || tid >= VG_N_THREADS)
sewardj3b13f0e2002-04-25 20:17:29 +00001572 barf("__h_errno_location: invalid ThreadId");
1573 return & thread_specific_h_errno[tid];
1574}
1575
sewardjb0ff1032002-08-06 09:02:53 +00001576
1577#undef _res
1578extern struct __res_state _res;
1579
sewardj3b13f0e2002-04-25 20:17:29 +00001580struct __res_state* __res_state ( void )
1581{
1582 int tid;
1583 /* ensure_valgrind("__res_state"); */
1584 VALGRIND_MAGIC_SEQUENCE(tid, 1 /* default */,
1585 VG_USERREQ__PTHREAD_GET_THREADID,
1586 0, 0, 0, 0);
1587 /* 'cos I'm paranoid ... */
sewardj439d45e2002-05-03 20:43:10 +00001588 if (tid < 1 || tid >= VG_N_THREADS)
sewardj3b13f0e2002-04-25 20:17:29 +00001589 barf("__res_state: invalid ThreadId");
sewardjb0ff1032002-08-06 09:02:53 +00001590 if (tid == 1)
1591 return & _res;
sewardj3b13f0e2002-04-25 20:17:29 +00001592 return & thread_specific_res_state[tid];
sewardjf8f819e2002-04-17 23:21:37 +00001593}
1594
1595
sewardj5716dbb2002-04-26 03:28:18 +00001596/* ---------------------------------------------------
1597 LIBC-PRIVATE SPECIFIC DATA
1598 ------------------------------------------------ */
1599
1600/* Relies on assumption that initial private data is NULL. This
1601 should be fixed somehow. */
1602
njn25e49d8e72002-09-23 09:36:25 +00001603/* The allowable keys (indices) (all 3 of them).
sewardj5716dbb2002-04-26 03:28:18 +00001604 From sysdeps/pthread/bits/libc-tsd.h
1605*/
sewardjcb7f08a2002-10-02 09:41:49 +00001606/* as per glibc anoncvs HEAD of 20021001. */
sewardj5716dbb2002-04-26 03:28:18 +00001607enum __libc_tsd_key_t { _LIBC_TSD_KEY_MALLOC = 0,
1608 _LIBC_TSD_KEY_DL_ERROR,
njn25e49d8e72002-09-23 09:36:25 +00001609 _LIBC_TSD_KEY_RPC_VARS,
sewardjcb7f08a2002-10-02 09:41:49 +00001610 _LIBC_TSD_KEY_LOCALE,
1611 _LIBC_TSD_KEY_CTYPE_B,
1612 _LIBC_TSD_KEY_CTYPE_TOLOWER,
1613 _LIBC_TSD_KEY_CTYPE_TOUPPER,
sewardj5716dbb2002-04-26 03:28:18 +00001614 _LIBC_TSD_KEY_N };
1615
1616/* Auto-initialising subsystem. libc_specifics_inited is set
1617 after initialisation. libc_specifics_inited_mx guards it. */
1618static int libc_specifics_inited = 0;
1619static pthread_mutex_t libc_specifics_inited_mx = PTHREAD_MUTEX_INITIALIZER;
1620
sewardj00a66b12002-10-12 16:42:35 +00001621
sewardj5716dbb2002-04-26 03:28:18 +00001622/* These are the keys we must initialise the first time. */
sewardjcb7f08a2002-10-02 09:41:49 +00001623static pthread_key_t libc_specifics_keys[_LIBC_TSD_KEY_N];
sewardj5716dbb2002-04-26 03:28:18 +00001624
sewardj00a66b12002-10-12 16:42:35 +00001625
sewardjcb7f08a2002-10-02 09:41:49 +00001626/* Initialise the keys, if they are not already initialised. */
sewardj5716dbb2002-04-26 03:28:18 +00001627static
1628void init_libc_tsd_keys ( void )
1629{
1630 int res, i;
1631 pthread_key_t k;
1632
sewardj08c7f012002-10-07 23:56:55 +00001633 /* Don't fall into deadlock if we get called again whilst we still
1634 hold the lock, via the __uselocale() call herein. */
1635 if (libc_specifics_inited != 0)
1636 return;
1637
1638 /* Take the lock. */
sewardj00a66b12002-10-12 16:42:35 +00001639 res = __pthread_mutex_lock(&libc_specifics_inited_mx);
sewardj5716dbb2002-04-26 03:28:18 +00001640 if (res != 0) barf("init_libc_tsd_keys: lock");
1641
sewardj08c7f012002-10-07 23:56:55 +00001642 /* Now test again, to be sure there is no mistake. */
1643 if (libc_specifics_inited != 0) {
sewardj00a66b12002-10-12 16:42:35 +00001644 res = __pthread_mutex_unlock(&libc_specifics_inited_mx);
sewardj08c7f012002-10-07 23:56:55 +00001645 if (res != 0) barf("init_libc_tsd_keys: unlock(1)");
1646 return;
sewardj5716dbb2002-04-26 03:28:18 +00001647 }
1648
sewardj08c7f012002-10-07 23:56:55 +00001649 /* Actually do the initialisation. */
1650 /* printf("INIT libc specifics\n"); */
1651 for (i = 0; i < _LIBC_TSD_KEY_N; i++) {
sewardj00a66b12002-10-12 16:42:35 +00001652 res = __pthread_key_create(&k, NULL);
sewardj08c7f012002-10-07 23:56:55 +00001653 if (res != 0) barf("init_libc_tsd_keys: create");
1654 libc_specifics_keys[i] = k;
1655 }
1656
1657 /* Signify init done. */
1658 libc_specifics_inited = 1;
1659
1660# ifdef GLIBC_2_3
1661 /* Set the initialising thread's locale to the global (default)
sewardj00a66b12002-10-12 16:42:35 +00001662 locale. A hack in support of glibc-2.3. This does the biz for
1663 the root thread. For all other threads we run this in
1664 thread_wrapper(), which does the real work of
1665 pthread_create(). */
1666 /* assert that we are the root thread. I don't know if this is
1667 really a valid assertion to make; if it breaks I'll reconsider
1668 it. */
1669 my_assert(pthread_self() == 1);
sewardj08c7f012002-10-07 23:56:55 +00001670 __uselocale(LC_GLOBAL_LOCALE);
1671# endif
1672
1673 /* Unlock and return. */
sewardj00a66b12002-10-12 16:42:35 +00001674 res = __pthread_mutex_unlock(&libc_specifics_inited_mx);
sewardj5716dbb2002-04-26 03:28:18 +00001675 if (res != 0) barf("init_libc_tsd_keys: unlock");
1676}
1677
1678
1679static int
1680libc_internal_tsd_set ( enum __libc_tsd_key_t key,
1681 const void * pointer )
1682{
sewardjcb7f08a2002-10-02 09:41:49 +00001683 int res;
sewardj5716dbb2002-04-26 03:28:18 +00001684 /* printf("SET SET SET key %d ptr %p\n", key, pointer); */
sewardjcb7f08a2002-10-02 09:41:49 +00001685 if (key < _LIBC_TSD_KEY_MALLOC || key >= _LIBC_TSD_KEY_N)
sewardj5716dbb2002-04-26 03:28:18 +00001686 barf("libc_internal_tsd_set: invalid key");
1687 init_libc_tsd_keys();
sewardj00a66b12002-10-12 16:42:35 +00001688 res = __pthread_setspecific(libc_specifics_keys[key], pointer);
sewardj5716dbb2002-04-26 03:28:18 +00001689 if (res != 0) barf("libc_internal_tsd_set: setspecific failed");
1690 return 0;
1691}
1692
1693static void *
1694libc_internal_tsd_get ( enum __libc_tsd_key_t key )
1695{
sewardjcb7f08a2002-10-02 09:41:49 +00001696 void* v;
sewardj5716dbb2002-04-26 03:28:18 +00001697 /* printf("GET GET GET key %d\n", key); */
sewardjcb7f08a2002-10-02 09:41:49 +00001698 if (key < _LIBC_TSD_KEY_MALLOC || key >= _LIBC_TSD_KEY_N)
sewardj5716dbb2002-04-26 03:28:18 +00001699 barf("libc_internal_tsd_get: invalid key");
1700 init_libc_tsd_keys();
sewardj00a66b12002-10-12 16:42:35 +00001701 v = __pthread_getspecific(libc_specifics_keys[key]);
sewardj5716dbb2002-04-26 03:28:18 +00001702 /* if (v == NULL) barf("libc_internal_tsd_set: getspecific failed"); */
1703 return v;
1704}
1705
1706
sewardj70adeb22002-04-27 01:35:38 +00001707int (*__libc_internal_tsd_set)
1708 (enum __libc_tsd_key_t key, const void * pointer)
1709 = libc_internal_tsd_set;
sewardj5716dbb2002-04-26 03:28:18 +00001710
sewardj70adeb22002-04-27 01:35:38 +00001711void* (*__libc_internal_tsd_get)
1712 (enum __libc_tsd_key_t key)
1713 = libc_internal_tsd_get;
sewardj5716dbb2002-04-26 03:28:18 +00001714
1715
sewardj00a66b12002-10-12 16:42:35 +00001716#ifdef GLIBC_2_3
1717/* This one was first spotted be me in the glibc-2.2.93 sources. */
1718static void**
1719libc_internal_tsd_address ( enum __libc_tsd_key_t key )
1720{
1721 void** v;
1722 /* printf("ADDR ADDR ADDR key %d\n", key); */
1723 if (key < _LIBC_TSD_KEY_MALLOC || key >= _LIBC_TSD_KEY_N)
1724 barf("libc_internal_tsd_address: invalid key");
1725 init_libc_tsd_keys();
1726 v = __pthread_getspecific_addr(libc_specifics_keys[key]);
1727 return v;
1728}
1729
1730void ** (*__libc_internal_tsd_address)
1731 (enum __libc_tsd_key_t key)
1732 = libc_internal_tsd_address;
1733#endif
1734
1735
sewardje663cb92002-04-12 10:26:32 +00001736/* ---------------------------------------------------------------------
1737 These are here (I think) because they are deemed cancellation
1738 points by POSIX. For the moment we'll simply pass the call along
1739 to the corresponding thread-unaware (?) libc routine.
1740 ------------------------------------------------------------------ */
1741
sewardje663cb92002-04-12 10:26:32 +00001742#include <stdlib.h>
sewardje663cb92002-04-12 10:26:32 +00001743#include <sys/types.h>
1744#include <sys/socket.h>
1745
sewardjd529a442002-05-04 19:49:21 +00001746#ifdef GLIBC_2_1
1747extern
1748int __sigaction
1749 (int signum,
1750 const struct sigaction *act,
1751 struct sigaction *oldact);
1752#else
sewardje663cb92002-04-12 10:26:32 +00001753extern
1754int __libc_sigaction
1755 (int signum,
1756 const struct sigaction *act,
1757 struct sigaction *oldact);
sewardjd529a442002-05-04 19:49:21 +00001758#endif
sewardje663cb92002-04-12 10:26:32 +00001759int sigaction(int signum,
1760 const struct sigaction *act,
1761 struct sigaction *oldact)
1762{
sewardjd140e442002-05-29 01:21:19 +00001763 __my_pthread_testcancel();
sewardj2a1dcce2002-04-22 12:45:25 +00001764# ifdef GLIBC_2_1
1765 return __sigaction(signum, act, oldact);
1766# else
sewardj45b4b372002-04-16 22:50:32 +00001767 return __libc_sigaction(signum, act, oldact);
sewardj2a1dcce2002-04-22 12:45:25 +00001768# endif
sewardje663cb92002-04-12 10:26:32 +00001769}
1770
1771
1772extern
1773int __libc_connect(int sockfd,
1774 const struct sockaddr *serv_addr,
1775 socklen_t addrlen);
sewardj5905fae2002-04-26 13:25:00 +00001776__attribute__((weak))
sewardje663cb92002-04-12 10:26:32 +00001777int connect(int sockfd,
1778 const struct sockaddr *serv_addr,
1779 socklen_t addrlen)
1780{
sewardjd140e442002-05-29 01:21:19 +00001781 __my_pthread_testcancel();
sewardj45b4b372002-04-16 22:50:32 +00001782 return __libc_connect(sockfd, serv_addr, addrlen);
sewardje663cb92002-04-12 10:26:32 +00001783}
1784
1785
1786extern
1787int __libc_fcntl(int fd, int cmd, long arg);
sewardj5905fae2002-04-26 13:25:00 +00001788__attribute__((weak))
sewardje663cb92002-04-12 10:26:32 +00001789int fcntl(int fd, int cmd, long arg)
1790{
sewardjd140e442002-05-29 01:21:19 +00001791 __my_pthread_testcancel();
sewardj45b4b372002-04-16 22:50:32 +00001792 return __libc_fcntl(fd, cmd, arg);
sewardje663cb92002-04-12 10:26:32 +00001793}
1794
1795
1796extern
1797ssize_t __libc_write(int fd, const void *buf, size_t count);
sewardj5905fae2002-04-26 13:25:00 +00001798__attribute__((weak))
sewardje663cb92002-04-12 10:26:32 +00001799ssize_t write(int fd, const void *buf, size_t count)
1800{
sewardjd140e442002-05-29 01:21:19 +00001801 __my_pthread_testcancel();
sewardj45b4b372002-04-16 22:50:32 +00001802 return __libc_write(fd, buf, count);
sewardje663cb92002-04-12 10:26:32 +00001803}
1804
1805
1806extern
1807ssize_t __libc_read(int fd, void *buf, size_t count);
sewardj5905fae2002-04-26 13:25:00 +00001808__attribute__((weak))
sewardje663cb92002-04-12 10:26:32 +00001809ssize_t read(int fd, void *buf, size_t count)
1810{
sewardjd140e442002-05-29 01:21:19 +00001811 __my_pthread_testcancel();
sewardj45b4b372002-04-16 22:50:32 +00001812 return __libc_read(fd, buf, count);
sewardje663cb92002-04-12 10:26:32 +00001813}
1814
sewardjf912dfc2002-11-13 21:51:10 +00001815/*
1816 * Ugh, this is horrible but here goes:
1817 *
1818 * Open of a named pipe (fifo file) can block. In a threaded program,
1819 * this means that the whole thing can block. We therefore need to
1820 * make the open appear to block to the caller, but still keep polling
1821 * for everyone else.
1822 *
1823 * There are four cases:
1824 *
1825 * - the caller asked for O_NONBLOCK. The easy one: we just do it.
1826 *
1827 * - the caller asked for a blocking O_RDONLY open. We open it with
1828 * O_NONBLOCK and then use poll to wait for it to become ready.
1829 *
1830 * - the caller asked for a blocking O_WRONLY open. Unfortunately, this
1831 * will fail with ENXIO when we make it non-blocking. Doubly
1832 * unfortunate is that we can only rely on these semantics if it is
1833 * actually a fifo file; the hack is that if we see that it is a
1834 * O_WRONLY open and we get ENXIO, then stat the path and see if it
1835 * actually is a fifo. This is racy, but it is the best we can do.
1836 * If it is a fifo, then keep trying the open until it works; if not
1837 * just return the error.
1838 *
1839 * - the caller asked for a blocking O_RDWR open. Well, under Linux,
1840 * this never blocks, so we just clear the non-blocking flag and
1841 * return.
1842 *
1843 * This code assumes that for whatever we open, O_NONBLOCK followed by
1844 * a fcntl clearing O_NONBLOCK is the same as opening without
1845 * O_NONBLOCK. Also assumes that stat and fstat have no side-effects.
1846 *
1847 * XXX Should probably put in special cases for some devices as well,
1848 * like serial ports. Unfortunately they don't work like fifos, so
1849 * this logic will become even more tortured. Wait until we really
1850 * need it.
1851 */
1852static inline int _open(const char *pathname, int flags, mode_t mode,
1853 int (*openp)(const char *, int, mode_t))
sewardjbe32e452002-04-24 20:29:58 +00001854{
sewardjf912dfc2002-11-13 21:51:10 +00001855 int fd;
1856 struct stat st;
1857 struct vki_timespec nanosleep_interval;
1858 int saved_errno;
1859
sewardjd140e442002-05-29 01:21:19 +00001860 __my_pthread_testcancel();
sewardjf912dfc2002-11-13 21:51:10 +00001861
1862 /* Assume we can only get O_RDONLY, O_WRONLY or O_RDWR */
1863 my_assert((flags & VKI_O_ACCMODE) != VKI_O_ACCMODE);
1864
1865 for(;;) {
1866 fd = (*openp)(pathname, flags | VKI_O_NONBLOCK, mode);
1867
1868 /* return immediately if caller wanted nonblocking anyway */
1869 if (flags & VKI_O_NONBLOCK)
1870 return fd;
1871
1872 saved_errno = errno;
1873
1874 if (fd != -1)
1875 break; /* open worked */
1876
1877 /* If we got ENXIO and we're opening WRONLY, and it turns out
1878 to really be a FIFO, then poll waiting for open to succeed */
1879 if (errno == ENXIO &&
1880 (flags & VKI_O_ACCMODE) == VKI_O_WRONLY &&
1881 (stat(pathname, &st) == 0 && S_ISFIFO(st.st_mode))) {
1882
1883 /* OK, we're opening a FIFO for writing; sleep and spin */
1884 nanosleep_interval.tv_sec = 0;
1885 nanosleep_interval.tv_nsec = 13 * 1000 * 1000; /* 13 milliseconds */
1886 /* It's critical here that valgrind's nanosleep implementation
1887 is nonblocking. */
1888 (void)my_do_syscall2(__NR_nanosleep,
1889 (int)(&nanosleep_interval), (int)NULL);
1890 } else {
1891 /* it was just an error */
1892 errno = saved_errno;
1893 return -1;
1894 }
1895 }
1896
1897 /* OK, we've got a nonblocking FD for a caller who wants blocking;
1898 reset the flags to what they asked for */
1899 fcntl(fd, VKI_F_SETFL, flags);
1900
1901 /* Return now if one of:
1902 - we were opening O_RDWR (never blocks)
1903 - we opened with O_WRONLY (polling already done)
1904 - the thing we opened wasn't a FIFO after all (or fstat failed)
1905 */
1906 if ((flags & VKI_O_ACCMODE) != VKI_O_RDONLY ||
1907 (fstat(fd, &st) == -1 || !S_ISFIFO(st.st_mode))) {
1908 errno = saved_errno;
1909 return fd;
1910 }
1911
1912 /* OK, drop into the poll loop looking for something to read on the fd */
1913 my_assert((flags & VKI_O_ACCMODE) == VKI_O_RDONLY);
1914 for(;;) {
1915 struct pollfd pollfd;
1916 int res;
1917
1918 pollfd.fd = fd;
1919 pollfd.events = POLLIN;
1920 pollfd.revents = 0;
1921
1922 res = my_do_syscall3(__NR_poll, (int)&pollfd, 1, 0);
1923
1924 my_assert(res == 0 || res == 1);
1925
1926 if (res == 1) {
1927 /* OK, got it.
1928
1929 XXX This is wrong: we're waiting for either something to
1930 read or a HUP on the file descriptor, but the semantics of
1931 fifo open are that we should unblock as soon as someone
1932 simply opens the other end, not that they write something.
1933 With luck this won't matter in practice.
1934 */
1935 my_assert(pollfd.revents & (POLLIN|POLLHUP));
1936 break;
1937 }
1938
1939 /* Still nobody home; sleep and spin */
1940 nanosleep_interval.tv_sec = 0;
1941 nanosleep_interval.tv_nsec = 13 * 1000 * 1000; /* 13 milliseconds */
1942 /* It's critical here that valgrind's nanosleep implementation
1943 is nonblocking. */
1944 (void)my_do_syscall2(__NR_nanosleep,
1945 (int)(&nanosleep_interval), (int)NULL);
1946 }
1947
1948 errno = saved_errno;
1949 return fd;
sewardjbe32e452002-04-24 20:29:58 +00001950}
1951
sewardjf912dfc2002-11-13 21:51:10 +00001952extern
1953int __libc_open64(const char *pathname, int flags, mode_t mode);
1954/* __attribute__((weak)) */
1955int open64(const char *pathname, int flags, mode_t mode)
1956{
1957 return _open(pathname, flags, mode, __libc_open64);
1958}
sewardje663cb92002-04-12 10:26:32 +00001959
1960extern
sewardj853f55d2002-04-26 00:27:53 +00001961int __libc_open(const char *pathname, int flags, mode_t mode);
sewardjf912dfc2002-11-13 21:51:10 +00001962/* __attribute__((weak)) */
sewardj853f55d2002-04-26 00:27:53 +00001963int open(const char *pathname, int flags, mode_t mode)
sewardje663cb92002-04-12 10:26:32 +00001964{
sewardjf912dfc2002-11-13 21:51:10 +00001965 return _open(pathname, flags, mode, __libc_open);
sewardje663cb92002-04-12 10:26:32 +00001966}
1967
sewardje663cb92002-04-12 10:26:32 +00001968extern
1969int __libc_close(int fd);
sewardj5905fae2002-04-26 13:25:00 +00001970__attribute__((weak))
sewardje663cb92002-04-12 10:26:32 +00001971int close(int fd)
1972{
sewardjd140e442002-05-29 01:21:19 +00001973 __my_pthread_testcancel();
sewardj45b4b372002-04-16 22:50:32 +00001974 return __libc_close(fd);
sewardje663cb92002-04-12 10:26:32 +00001975}
1976
1977
1978extern
1979int __libc_accept(int s, struct sockaddr *addr, socklen_t *addrlen);
sewardjf220ccc2002-10-23 21:53:49 +00001980
1981int VGL_(accept)(int s, struct sockaddr *addr, socklen_t *addrlen)
sewardje663cb92002-04-12 10:26:32 +00001982{
sewardjd140e442002-05-29 01:21:19 +00001983 __my_pthread_testcancel();
sewardj705d3cb2002-05-23 13:13:12 +00001984 wait_for_fd_to_be_readable_or_erring(s);
sewardjd140e442002-05-29 01:21:19 +00001985 __my_pthread_testcancel();
sewardj45b4b372002-04-16 22:50:32 +00001986 return __libc_accept(s, addr, addrlen);
sewardje663cb92002-04-12 10:26:32 +00001987}
1988
sewardj0c573af92002-10-23 21:55:01 +00001989extern
1990int __libc_recv(int s, void *buf, size_t len, int flags);
1991
1992int VGL_(recv)(int s, void *buf, size_t len, int flags)
1993{
1994 __my_pthread_testcancel();
1995 wait_for_fd_to_be_readable_or_erring(s);
1996 __my_pthread_testcancel();
1997 return __libc_recv(s, buf, len, flags);
1998}
1999
sewardj2a68e7e2002-11-16 11:04:18 +00002000int VGL_(readv)(int fd, const struct iovec *iov, int count)
2001{
2002 __my_pthread_testcancel();
2003 wait_for_fd_to_be_readable_or_erring(fd);
2004 __my_pthread_testcancel();
2005 return my_do_syscall3(__NR_readv, fd, (unsigned)iov, count);
2006}
2007
2008int VGL_(writev)(int fd, struct iovec *iov, int count)
2009{
2010 __my_pthread_testcancel();
2011 wait_for_fd_to_be_writable_or_erring(fd);
2012 __my_pthread_testcancel();
2013 return my_do_syscall3(__NR_writev, fd, (unsigned)iov, count);
2014}
sewardje663cb92002-04-12 10:26:32 +00002015
2016extern
sewardje663cb92002-04-12 10:26:32 +00002017pid_t __libc_waitpid(pid_t pid, int *status, int options);
sewardj5905fae2002-04-26 13:25:00 +00002018__attribute__((weak))
sewardje663cb92002-04-12 10:26:32 +00002019pid_t waitpid(pid_t pid, int *status, int options)
2020{
sewardjd140e442002-05-29 01:21:19 +00002021 __my_pthread_testcancel();
sewardj45b4b372002-04-16 22:50:32 +00002022 return __libc_waitpid(pid, status, options);
sewardje663cb92002-04-12 10:26:32 +00002023}
2024
2025
2026extern
2027int __libc_nanosleep(const struct timespec *req, struct timespec *rem);
sewardj5905fae2002-04-26 13:25:00 +00002028__attribute__((weak))
sewardje663cb92002-04-12 10:26:32 +00002029int nanosleep(const struct timespec *req, struct timespec *rem)
2030{
sewardjd140e442002-05-29 01:21:19 +00002031 __my_pthread_testcancel();
sewardje663cb92002-04-12 10:26:32 +00002032 return __libc_nanosleep(req, rem);
2033}
2034
sewardjbe32e452002-04-24 20:29:58 +00002035
sewardje663cb92002-04-12 10:26:32 +00002036extern
2037int __libc_fsync(int fd);
sewardj5905fae2002-04-26 13:25:00 +00002038__attribute__((weak))
sewardje663cb92002-04-12 10:26:32 +00002039int fsync(int fd)
2040{
sewardjd140e442002-05-29 01:21:19 +00002041 __my_pthread_testcancel();
sewardj45b4b372002-04-16 22:50:32 +00002042 return __libc_fsync(fd);
sewardje663cb92002-04-12 10:26:32 +00002043}
2044
sewardjbe32e452002-04-24 20:29:58 +00002045
sewardj70c75362002-04-13 04:18:32 +00002046extern
2047off_t __libc_lseek(int fildes, off_t offset, int whence);
sewardj5905fae2002-04-26 13:25:00 +00002048__attribute__((weak))
sewardj70c75362002-04-13 04:18:32 +00002049off_t lseek(int fildes, off_t offset, int whence)
2050{
sewardjd140e442002-05-29 01:21:19 +00002051 __my_pthread_testcancel();
sewardj45b4b372002-04-16 22:50:32 +00002052 return __libc_lseek(fildes, offset, whence);
sewardj70c75362002-04-13 04:18:32 +00002053}
2054
sewardjbe32e452002-04-24 20:29:58 +00002055
2056extern
2057__off64_t __libc_lseek64(int fildes, __off64_t offset, int whence);
sewardj5905fae2002-04-26 13:25:00 +00002058__attribute__((weak))
sewardjbe32e452002-04-24 20:29:58 +00002059__off64_t lseek64(int fildes, __off64_t offset, int whence)
2060{
sewardjd140e442002-05-29 01:21:19 +00002061 __my_pthread_testcancel();
sewardjbe32e452002-04-24 20:29:58 +00002062 return __libc_lseek64(fildes, offset, whence);
2063}
2064
2065
sewardj726c4122002-05-16 23:39:10 +00002066extern
2067ssize_t __libc_pread64 (int __fd, void *__buf, size_t __nbytes,
2068 __off64_t __offset);
2069ssize_t __pread64 (int __fd, void *__buf, size_t __nbytes,
2070 __off64_t __offset)
2071{
sewardjd140e442002-05-29 01:21:19 +00002072 __my_pthread_testcancel();
sewardj726c4122002-05-16 23:39:10 +00002073 return __libc_pread64(__fd, __buf, __nbytes, __offset);
2074}
2075
2076
sewardja18e2102002-05-18 10:43:22 +00002077extern
2078ssize_t __libc_pwrite64 (int __fd, const void *__buf, size_t __nbytes,
2079 __off64_t __offset);
2080ssize_t __pwrite64 (int __fd, const void *__buf, size_t __nbytes,
2081 __off64_t __offset)
2082{
sewardjd140e442002-05-29 01:21:19 +00002083 __my_pthread_testcancel();
sewardja18e2102002-05-18 10:43:22 +00002084 return __libc_pwrite64(__fd, __buf, __nbytes, __offset);
2085}
2086
sewardj726c4122002-05-16 23:39:10 +00002087
sewardj39b93b12002-05-18 10:56:27 +00002088extern
2089ssize_t __libc_pwrite(int fd, const void *buf, size_t count, off_t offset);
2090__attribute__((weak))
2091ssize_t pwrite(int fd, const void *buf, size_t count, off_t offset)
2092{
sewardjd140e442002-05-29 01:21:19 +00002093 __my_pthread_testcancel();
sewardj39b93b12002-05-18 10:56:27 +00002094 return __libc_pwrite(fd, buf, count, offset);
2095}
2096
2097
2098extern
2099ssize_t __libc_pread(int fd, void *buf, size_t count, off_t offset);
2100__attribute__((weak))
2101ssize_t pread(int fd, void *buf, size_t count, off_t offset)
2102{
sewardjd140e442002-05-29 01:21:19 +00002103 __my_pthread_testcancel();
sewardj39b93b12002-05-18 10:56:27 +00002104 return __libc_pread(fd, buf, count, offset);
2105}
2106
2107
sewardj6af4b5d2002-04-16 04:40:49 +00002108extern
2109void __libc_longjmp(jmp_buf env, int val) __attribute((noreturn));
sewardj5905fae2002-04-26 13:25:00 +00002110/* not weak: __attribute__((weak)) */
sewardj6af4b5d2002-04-16 04:40:49 +00002111void longjmp(jmp_buf env, int val)
2112{
2113 __libc_longjmp(env, val);
2114}
2115
sewardjbe32e452002-04-24 20:29:58 +00002116
sewardj436c2db2002-06-18 09:07:54 +00002117extern void __libc_siglongjmp (sigjmp_buf env, int val)
2118 __attribute__ ((noreturn));
2119void siglongjmp(sigjmp_buf env, int val)
2120{
2121 kludged("siglongjmp (cleanup handlers are ignored)");
2122 __libc_siglongjmp(env, val);
2123}
2124
2125
sewardj6af4b5d2002-04-16 04:40:49 +00002126extern
2127int __libc_send(int s, const void *msg, size_t len, int flags);
sewardj5905fae2002-04-26 13:25:00 +00002128__attribute__((weak))
sewardj6af4b5d2002-04-16 04:40:49 +00002129int send(int s, const void *msg, size_t len, int flags)
2130{
sewardjd140e442002-05-29 01:21:19 +00002131 __my_pthread_testcancel();
sewardj6af4b5d2002-04-16 04:40:49 +00002132 return __libc_send(s, msg, len, flags);
2133}
2134
sewardjbe32e452002-04-24 20:29:58 +00002135
sewardj1e8cdc92002-04-18 11:37:52 +00002136extern
2137int __libc_recv(int s, void *buf, size_t len, int flags);
sewardj5905fae2002-04-26 13:25:00 +00002138__attribute__((weak))
sewardj1e8cdc92002-04-18 11:37:52 +00002139int recv(int s, void *buf, size_t len, int flags)
2140{
sewardjd140e442002-05-29 01:21:19 +00002141 __my_pthread_testcancel();
sewardj1d6b3a22002-06-20 07:58:33 +00002142 wait_for_fd_to_be_readable_or_erring(s);
2143 __my_pthread_testcancel();
sewardj1e8cdc92002-04-18 11:37:52 +00002144 return __libc_recv(s, buf, len, flags);
2145}
2146
sewardjbe32e452002-04-24 20:29:58 +00002147
sewardj3665ded2002-05-16 16:57:25 +00002148extern
2149int __libc_sendmsg(int s, const struct msghdr *msg, int flags);
2150__attribute__((weak))
2151int sendmsg(int s, const struct msghdr *msg, int flags)
2152{
sewardjd140e442002-05-29 01:21:19 +00002153 __my_pthread_testcancel();
sewardj3665ded2002-05-16 16:57:25 +00002154 return __libc_sendmsg(s, msg, flags);
2155}
2156
2157
sewardj796d6a22002-04-24 02:28:34 +00002158extern
sewardj59da27a2002-06-06 08:33:54 +00002159int __libc_recvmsg(int s, struct msghdr *msg, int flags);
2160__attribute__((weak))
2161int recvmsg(int s, struct msghdr *msg, int flags)
2162{
2163 __my_pthread_testcancel();
2164 return __libc_recvmsg(s, msg, flags);
2165}
2166
2167
2168extern
sewardj436e0582002-04-26 14:31:40 +00002169int __libc_recvfrom(int s, void *buf, size_t len, int flags,
2170 struct sockaddr *from, socklen_t *fromlen);
2171__attribute__((weak))
2172int recvfrom(int s, void *buf, size_t len, int flags,
2173 struct sockaddr *from, socklen_t *fromlen)
2174{
sewardjd140e442002-05-29 01:21:19 +00002175 __my_pthread_testcancel();
sewardj2e207632002-06-13 17:29:53 +00002176 wait_for_fd_to_be_readable_or_erring(s);
2177 __my_pthread_testcancel();
sewardj436e0582002-04-26 14:31:40 +00002178 return __libc_recvfrom(s, buf, len, flags, from, fromlen);
2179}
2180
2181
2182extern
sewardj796d6a22002-04-24 02:28:34 +00002183int __libc_sendto(int s, const void *msg, size_t len, int flags,
2184 const struct sockaddr *to, socklen_t tolen);
sewardj5905fae2002-04-26 13:25:00 +00002185__attribute__((weak))
sewardj796d6a22002-04-24 02:28:34 +00002186int sendto(int s, const void *msg, size_t len, int flags,
2187 const struct sockaddr *to, socklen_t tolen)
2188{
sewardjd140e442002-05-29 01:21:19 +00002189 __my_pthread_testcancel();
sewardj796d6a22002-04-24 02:28:34 +00002190 return __libc_sendto(s, msg, len, flags, to, tolen);
2191}
2192
sewardjbe32e452002-04-24 20:29:58 +00002193
sewardj369b1702002-04-24 13:28:15 +00002194extern
2195int __libc_system(const char* str);
sewardj5905fae2002-04-26 13:25:00 +00002196__attribute__((weak))
sewardj369b1702002-04-24 13:28:15 +00002197int system(const char* str)
2198{
sewardjd140e442002-05-29 01:21:19 +00002199 __my_pthread_testcancel();
sewardj369b1702002-04-24 13:28:15 +00002200 return __libc_system(str);
2201}
2202
sewardjbe32e452002-04-24 20:29:58 +00002203
sewardjab0b1c32002-04-24 19:26:47 +00002204extern
2205pid_t __libc_wait(int *status);
sewardj5905fae2002-04-26 13:25:00 +00002206__attribute__((weak))
sewardjab0b1c32002-04-24 19:26:47 +00002207pid_t wait(int *status)
2208{
sewardjd140e442002-05-29 01:21:19 +00002209 __my_pthread_testcancel();
sewardjab0b1c32002-04-24 19:26:47 +00002210 return __libc_wait(status);
2211}
2212
sewardj45b4b372002-04-16 22:50:32 +00002213
sewardj67f1d582002-05-24 02:11:32 +00002214extern
2215int __libc_msync(const void *start, size_t length, int flags);
2216__attribute__((weak))
2217int msync(const void *start, size_t length, int flags)
2218{
sewardjd140e442002-05-29 01:21:19 +00002219 __my_pthread_testcancel();
sewardj67f1d582002-05-24 02:11:32 +00002220 return __libc_msync(start, length, flags);
2221}
2222
sewardj5905fae2002-04-26 13:25:00 +00002223
sewardj2cb00342002-06-28 01:46:26 +00002224/*--- fork and its helper ---*/
2225
2226static
2227void run_fork_handlers ( int what )
2228{
2229 ForkHandlerEntry entry;
2230 int n_h, n_handlers, i, res;
2231
2232 my_assert(what == 0 || what == 1 || what == 2);
2233
2234 /* Fetch old counter */
2235 VALGRIND_MAGIC_SEQUENCE(n_handlers, -2 /* default */,
2236 VG_USERREQ__GET_FHSTACK_USED,
2237 0, 0, 0, 0);
2238 my_assert(n_handlers >= 0 && n_handlers < VG_N_FORKHANDLERSTACK);
2239
2240 /* Prepare handlers (what == 0) are called in opposite order of
2241 calls to pthread_atfork. Parent and child handlers are called
2242 in the same order as calls to pthread_atfork. */
2243 if (what == 0)
2244 n_h = n_handlers - 1;
2245 else
2246 n_h = 0;
2247
2248 for (i = 0; i < n_handlers; i++) {
2249 VALGRIND_MAGIC_SEQUENCE(res, -2 /* default */,
2250 VG_USERREQ__GET_FHSTACK_ENTRY,
2251 n_h, &entry, 0, 0);
2252 my_assert(res == 0);
2253 switch (what) {
2254 case 0: if (entry.prepare) entry.prepare();
2255 n_h--; break;
2256 case 1: if (entry.parent) entry.parent();
2257 n_h++; break;
2258 case 2: if (entry.child) entry.child();
2259 n_h++; break;
2260 default: barf("run_fork_handlers: invalid what");
2261 }
2262 }
2263
2264 if (what != 0 /* prepare */) {
2265 /* Empty out the stack. */
2266 VALGRIND_MAGIC_SEQUENCE(res, -2 /* default */,
2267 VG_USERREQ__SET_FHSTACK_USED,
2268 0, 0, 0, 0);
2269 my_assert(res == 0);
2270 }
2271}
2272
2273extern
2274pid_t __libc_fork(void);
2275pid_t __fork(void)
2276{
2277 pid_t pid;
2278 __my_pthread_testcancel();
2279 __pthread_mutex_lock(&pthread_atfork_lock);
2280
2281 run_fork_handlers(0 /* prepare */);
2282 pid = __libc_fork();
2283 if (pid == 0) {
2284 /* I am the child */
2285 run_fork_handlers(2 /* child */);
sewardjd8acdf22002-11-13 21:57:52 +00002286 __pthread_mutex_unlock(&pthread_atfork_lock);
sewardj2cb00342002-06-28 01:46:26 +00002287 __pthread_mutex_init(&pthread_atfork_lock, NULL);
2288 } else {
2289 /* I am the parent */
2290 run_fork_handlers(1 /* parent */);
2291 __pthread_mutex_unlock(&pthread_atfork_lock);
2292 }
2293 return pid;
2294}
2295
2296
njn25e49d8e72002-09-23 09:36:25 +00002297pid_t __vfork(void)
2298{
2299 return __fork();
2300}
sewardj2cb00342002-06-28 01:46:26 +00002301
2302
sewardj3b13f0e2002-04-25 20:17:29 +00002303/* ---------------------------------------------------------------------
2304 Nonblocking implementations of select() and poll(). This stuff will
2305 surely rot your mind.
2306 ------------------------------------------------------------------ */
sewardje663cb92002-04-12 10:26:32 +00002307
sewardj08a4c3f2002-04-13 03:45:44 +00002308/*--------------------------------------------------*/
2309
2310#include "vg_kerneliface.h"
2311
2312static
2313__inline__
2314int is_kerror ( int res )
2315{
2316 if (res >= -4095 && res <= -1)
2317 return 1;
2318 else
2319 return 0;
2320}
2321
2322
2323static
2324int my_do_syscall1 ( int syscallno, int arg1 )
2325{
2326 int __res;
2327 __asm__ volatile ("pushl %%ebx; movl %%edx,%%ebx ; int $0x80 ; popl %%ebx"
2328 : "=a" (__res)
2329 : "0" (syscallno),
2330 "d" (arg1) );
2331 return __res;
2332}
2333
2334static
2335int my_do_syscall2 ( int syscallno,
sewardjf854f472002-04-21 12:19:41 +00002336 int arg1, int arg2 )
sewardj08a4c3f2002-04-13 03:45:44 +00002337{
2338 int __res;
2339 __asm__ volatile ("pushl %%ebx; movl %%edx,%%ebx ; int $0x80 ; popl %%ebx"
2340 : "=a" (__res)
2341 : "0" (syscallno),
2342 "d" (arg1),
2343 "c" (arg2) );
2344 return __res;
2345}
2346
2347static
sewardjf854f472002-04-21 12:19:41 +00002348int my_do_syscall3 ( int syscallno,
2349 int arg1, int arg2, int arg3 )
2350{
2351 int __res;
2352 __asm__ volatile ("pushl %%ebx; movl %%esi,%%ebx ; int $0x80 ; popl %%ebx"
2353 : "=a" (__res)
2354 : "0" (syscallno),
2355 "S" (arg1),
2356 "c" (arg2),
2357 "d" (arg3) );
2358 return __res;
2359}
2360
sewardjd5bef572002-10-23 21:49:33 +00002361static inline
2362int my_do_syscall5 ( int syscallno,
2363 int arg1, int arg2, int arg3, int arg4, int arg5 )
2364{
2365 int __res;
2366 __asm__ volatile ("int $0x80"
2367 : "=a" (__res)
2368 : "0" (syscallno),
2369 "b" (arg1),
2370 "c" (arg2),
2371 "d" (arg3),
2372 "S" (arg4),
2373 "D" (arg5));
2374 return __res;
2375}
2376
sewardjf854f472002-04-21 12:19:41 +00002377static
sewardj08a4c3f2002-04-13 03:45:44 +00002378int do_syscall_select( int n,
2379 vki_fd_set* readfds,
2380 vki_fd_set* writefds,
2381 vki_fd_set* exceptfds,
2382 struct vki_timeval * timeout )
2383{
2384 int res;
2385 int args[5];
2386 args[0] = n;
2387 args[1] = (int)readfds;
2388 args[2] = (int)writefds;
2389 args[3] = (int)exceptfds;
2390 args[4] = (int)timeout;
2391 res = my_do_syscall1(__NR_select, (int)(&(args[0])) );
sewardj02535bc2002-04-21 01:08:26 +00002392 return res;
sewardj08a4c3f2002-04-13 03:45:44 +00002393}
2394
2395
2396/* This is a wrapper round select(), which makes it thread-safe,
2397 meaning that only this thread will block, rather than the entire
2398 process. This wrapper in turn depends on nanosleep() not to block
2399 the entire process, but I think (hope? suspect?) that POSIX
2400 pthreads guarantees that to be the case.
2401
2402 Basic idea is: modify the timeout parameter to select so that it
2403 returns immediately. Poll like this until select returns non-zero,
2404 indicating something interesting happened, or until our time is up.
njn25e49d8e72002-09-23 09:36:25 +00002405 Space out the polls with nanosleeps of say 11 milliseconds, which
sewardj08a4c3f2002-04-13 03:45:44 +00002406 is required to be nonblocking; this allows other threads to run.
sewardj02535bc2002-04-21 01:08:26 +00002407
2408 Assumes:
sewardj2d94c112002-06-03 01:25:54 +00002409 * (checked via my_assert) types fd_set and vki_fd_set are identical.
2410 * (checked via my_assert) types timeval and vki_timeval are identical.
sewardj02535bc2002-04-21 01:08:26 +00002411 * (unchecked) libc error numbers (EINTR etc) are the negation of the
2412 kernel's error numbers (VKI_EINTR etc).
sewardj08a4c3f2002-04-13 03:45:44 +00002413*/
sewardj08a4c3f2002-04-13 03:45:44 +00002414
sewardj7db011a2002-11-13 22:00:20 +00002415int VGL_(select) ( int n,
2416 fd_set *rfds,
2417 fd_set *wfds,
2418 fd_set *xfds,
2419 struct timeval *timeout )
sewardj08a4c3f2002-04-13 03:45:44 +00002420{
sewardj5f07b662002-04-23 16:52:51 +00002421 unsigned int ms_now, ms_end;
sewardj08a4c3f2002-04-13 03:45:44 +00002422 int res;
2423 fd_set rfds_copy;
2424 fd_set wfds_copy;
2425 fd_set xfds_copy;
2426 struct vki_timeval t_now;
sewardj08a4c3f2002-04-13 03:45:44 +00002427 struct vki_timeval zero_timeout;
2428 struct vki_timespec nanosleep_interval;
2429
sewardjd140e442002-05-29 01:21:19 +00002430 __my_pthread_testcancel();
2431
sewardj5f07b662002-04-23 16:52:51 +00002432 /* gcc's complains about ms_end being used uninitialised -- classic
2433 case it can't understand, where ms_end is both defined and used
2434 only if timeout != NULL. Hence ... */
2435 ms_end = 0;
sewardj08a4c3f2002-04-13 03:45:44 +00002436
2437 /* We assume that the kernel and libc data layouts are identical
2438 for the following types. These asserts provide a crude
2439 check. */
2440 if (sizeof(fd_set) != sizeof(vki_fd_set)
2441 || sizeof(struct timeval) != sizeof(struct vki_timeval))
2442 barf("valgrind's hacky non-blocking select(): data sizes error");
2443
sewardj5f07b662002-04-23 16:52:51 +00002444 /* Detect the current time and simultaneously find out if we are
2445 running on Valgrind. */
2446 VALGRIND_MAGIC_SEQUENCE(ms_now, 0xFFFFFFFF /* default */,
2447 VG_USERREQ__READ_MILLISECOND_TIMER,
2448 0, 0, 0, 0);
2449
2450 /* If a zero timeout specified, this call is harmless. Also go
2451 this route if we're not running on Valgrind, for whatever
2452 reason. */
2453 if ( (timeout && timeout->tv_sec == 0 && timeout->tv_usec == 0)
2454 || (ms_now == 0xFFFFFFFF) ) {
sewardj02535bc2002-04-21 01:08:26 +00002455 res = do_syscall_select( n, (vki_fd_set*)rfds,
sewardj08a4c3f2002-04-13 03:45:44 +00002456 (vki_fd_set*)wfds,
2457 (vki_fd_set*)xfds,
2458 (struct vki_timeval*)timeout);
sewardj02535bc2002-04-21 01:08:26 +00002459 if (is_kerror(res)) {
2460 * (__errno_location()) = -res;
2461 return -1;
2462 } else {
2463 return res;
2464 }
2465 }
sewardj08a4c3f2002-04-13 03:45:44 +00002466
sewardj5f07b662002-04-23 16:52:51 +00002467 /* If a timeout was specified, set ms_end to be the end millisecond
2468 counter [wallclock] time. */
sewardj08a4c3f2002-04-13 03:45:44 +00002469 if (timeout) {
2470 res = my_do_syscall2(__NR_gettimeofday, (int)&t_now, (int)NULL);
sewardj2d94c112002-06-03 01:25:54 +00002471 my_assert(res == 0);
sewardj5f07b662002-04-23 16:52:51 +00002472 ms_end = ms_now;
2473 ms_end += (timeout->tv_usec / 1000);
2474 ms_end += (timeout->tv_sec * 1000);
sewardj08a4c3f2002-04-13 03:45:44 +00002475 /* Stay sane ... */
sewardj2d94c112002-06-03 01:25:54 +00002476 my_assert (ms_end >= ms_now);
sewardj08a4c3f2002-04-13 03:45:44 +00002477 }
2478
2479 /* fprintf(stderr, "MY_SELECT: before loop\n"); */
2480
2481 /* Either timeout == NULL, meaning wait indefinitely, or timeout !=
sewardj5f07b662002-04-23 16:52:51 +00002482 NULL, in which case ms_end holds the end time. */
sewardj05bb2c92002-06-26 00:47:17 +00002483
sewardj08a4c3f2002-04-13 03:45:44 +00002484 while (1) {
sewardj05bb2c92002-06-26 00:47:17 +00002485
2486 /* First, do a return-immediately select(). */
sewardj08a4c3f2002-04-13 03:45:44 +00002487
2488 /* These could be trashed each time round the loop, so restore
2489 them each time. */
2490 if (rfds) rfds_copy = *rfds;
2491 if (wfds) wfds_copy = *wfds;
2492 if (xfds) xfds_copy = *xfds;
2493
2494 zero_timeout.tv_sec = zero_timeout.tv_usec = 0;
2495
2496 res = do_syscall_select( n,
2497 rfds ? (vki_fd_set*)(&rfds_copy) : NULL,
2498 wfds ? (vki_fd_set*)(&wfds_copy) : NULL,
2499 xfds ? (vki_fd_set*)(&xfds_copy) : NULL,
2500 & zero_timeout );
sewardj02535bc2002-04-21 01:08:26 +00002501 if (is_kerror(res)) {
2502 /* Some kind of error (including EINTR). Set errno and
sewardj08a4c3f2002-04-13 03:45:44 +00002503 return. The sets are unspecified in this case. */
sewardj02535bc2002-04-21 01:08:26 +00002504 * (__errno_location()) = -res;
2505 return -1;
sewardj08a4c3f2002-04-13 03:45:44 +00002506 }
2507 if (res > 0) {
2508 /* one or more fds is ready. Copy out resulting sets and
2509 return. */
2510 if (rfds) *rfds = rfds_copy;
2511 if (wfds) *wfds = wfds_copy;
2512 if (xfds) *xfds = xfds_copy;
2513 return res;
2514 }
sewardj05bb2c92002-06-26 00:47:17 +00002515
2516 /* Nothing interesting happened, so we go to sleep for a
2517 while. */
2518
sewardj08a4c3f2002-04-13 03:45:44 +00002519 /* fprintf(stderr, "MY_SELECT: nanosleep\n"); */
2520 /* nanosleep and go round again */
sewardj02535bc2002-04-21 01:08:26 +00002521 nanosleep_interval.tv_sec = 0;
njn25e49d8e72002-09-23 09:36:25 +00002522 nanosleep_interval.tv_nsec = 11 * 1000 * 1000; /* 11 milliseconds */
sewardjf854f472002-04-21 12:19:41 +00002523 /* It's critical here that valgrind's nanosleep implementation
2524 is nonblocking. */
sewardj645030e2002-06-06 01:27:39 +00002525 res = my_do_syscall2(__NR_nanosleep,
sewardjf854f472002-04-21 12:19:41 +00002526 (int)(&nanosleep_interval), (int)NULL);
sewardj645030e2002-06-06 01:27:39 +00002527 if (res == -VKI_EINTR) {
2528 /* The nanosleep was interrupted by a signal. So we do the
2529 same. */
2530 * (__errno_location()) = EINTR;
2531 return -1;
2532 }
sewardj05bb2c92002-06-26 00:47:17 +00002533
2534 /* Sleeping finished. If a finite timeout, check to see if it
2535 has expired yet. */
2536 if (timeout) {
2537 VALGRIND_MAGIC_SEQUENCE(ms_now, 0xFFFFFFFF /* default */,
2538 VG_USERREQ__READ_MILLISECOND_TIMER,
2539 0, 0, 0, 0);
2540 my_assert(ms_now != 0xFFFFFFFF);
2541 if (ms_now >= ms_end) {
2542 /* timeout; nothing interesting happened. */
2543 if (rfds) FD_ZERO(rfds);
2544 if (wfds) FD_ZERO(wfds);
2545 if (xfds) FD_ZERO(xfds);
2546 return 0;
2547 }
2548 }
2549
sewardjf854f472002-04-21 12:19:41 +00002550 }
2551}
2552
2553
2554
2555
2556#include <sys/poll.h>
2557
sewardj3e909ce2002-06-03 13:27:15 +00002558#ifndef HAVE_NFDS_T
sewardj72d58482002-04-24 02:20:20 +00002559typedef unsigned long int nfds_t;
2560#endif
2561
sewardj705d3cb2002-05-23 13:13:12 +00002562
sewardj7db011a2002-11-13 22:00:20 +00002563int VGL_(poll) (struct pollfd *__fds, nfds_t __nfds, int __timeout)
sewardjf854f472002-04-21 12:19:41 +00002564{
sewardj5f07b662002-04-23 16:52:51 +00002565 unsigned int ms_now, ms_end;
sewardjf854f472002-04-21 12:19:41 +00002566 int res, i;
sewardjf854f472002-04-21 12:19:41 +00002567 struct vki_timespec nanosleep_interval;
2568
sewardjd140e442002-05-29 01:21:19 +00002569 __my_pthread_testcancel();
sewardjf854f472002-04-21 12:19:41 +00002570 ensure_valgrind("poll");
2571
sewardj5f07b662002-04-23 16:52:51 +00002572 /* Detect the current time and simultaneously find out if we are
2573 running on Valgrind. */
2574 VALGRIND_MAGIC_SEQUENCE(ms_now, 0xFFFFFFFF /* default */,
2575 VG_USERREQ__READ_MILLISECOND_TIMER,
2576 0, 0, 0, 0);
2577
sewardjf854f472002-04-21 12:19:41 +00002578 if (/* CHECK SIZES FOR struct pollfd */
2579 sizeof(struct timeval) != sizeof(struct vki_timeval))
2580 barf("valgrind's hacky non-blocking poll(): data sizes error");
2581
sewardj5f07b662002-04-23 16:52:51 +00002582 /* dummy initialisation to keep gcc -Wall happy */
2583 ms_end = 0;
2584
2585 /* If a zero timeout specified, this call is harmless. Also do
2586 this if not running on Valgrind. */
2587 if (__timeout == 0 || ms_now == 0xFFFFFFFF) {
sewardjf854f472002-04-21 12:19:41 +00002588 res = my_do_syscall3(__NR_poll, (int)__fds, __nfds, __timeout);
2589 if (is_kerror(res)) {
2590 * (__errno_location()) = -res;
2591 return -1;
2592 } else {
2593 return res;
2594 }
2595 }
2596
sewardj5f07b662002-04-23 16:52:51 +00002597 /* If a timeout was specified, set ms_end to be the end wallclock
2598 time. Easy considering that __timeout is in milliseconds. */
sewardjf854f472002-04-21 12:19:41 +00002599 if (__timeout > 0) {
sewardj650ac002002-04-29 12:20:34 +00002600 ms_end = ms_now + (unsigned int)__timeout;
sewardjf854f472002-04-21 12:19:41 +00002601 }
2602
2603 /* fprintf(stderr, "MY_POLL: before loop\n"); */
2604
2605 /* Either timeout < 0, meaning wait indefinitely, or timeout > 0,
2606 in which case t_end holds the end time. */
sewardj05bb2c92002-06-26 00:47:17 +00002607
sewardj2d94c112002-06-03 01:25:54 +00002608 my_assert(__timeout != 0);
sewardj5f07b662002-04-23 16:52:51 +00002609
sewardjf854f472002-04-21 12:19:41 +00002610 while (1) {
sewardj05bb2c92002-06-26 00:47:17 +00002611
2612 /* Do a return-immediately poll. */
2613
2614 res = my_do_syscall3(__NR_poll, (int)__fds, __nfds, 0 );
2615 if (is_kerror(res)) {
2616 /* Some kind of error. Set errno and return. */
2617 * (__errno_location()) = -res;
2618 return -1;
2619 }
2620 if (res > 0) {
2621 /* One or more fds is ready. Return now. */
2622 return res;
2623 }
2624
2625 /* Nothing interesting happened, so we go to sleep for a
2626 while. */
2627
2628 /* fprintf(stderr, "MY_POLL: nanosleep\n"); */
2629 /* nanosleep and go round again */
2630 nanosleep_interval.tv_sec = 0;
njn25e49d8e72002-09-23 09:36:25 +00002631 nanosleep_interval.tv_nsec = 13 * 1000 * 1000; /* 13 milliseconds */
sewardj05bb2c92002-06-26 00:47:17 +00002632 /* It's critical here that valgrind's nanosleep implementation
2633 is nonblocking. */
2634 (void)my_do_syscall2(__NR_nanosleep,
2635 (int)(&nanosleep_interval), (int)NULL);
2636
2637 /* Sleeping finished. If a finite timeout, check to see if it
2638 has expired yet. */
sewardjf854f472002-04-21 12:19:41 +00002639 if (__timeout > 0) {
sewardj5f07b662002-04-23 16:52:51 +00002640 VALGRIND_MAGIC_SEQUENCE(ms_now, 0xFFFFFFFF /* default */,
2641 VG_USERREQ__READ_MILLISECOND_TIMER,
2642 0, 0, 0, 0);
sewardj2d94c112002-06-03 01:25:54 +00002643 my_assert(ms_now != 0xFFFFFFFF);
sewardj5f07b662002-04-23 16:52:51 +00002644 if (ms_now >= ms_end) {
sewardjf854f472002-04-21 12:19:41 +00002645 /* timeout; nothing interesting happened. */
2646 for (i = 0; i < __nfds; i++)
2647 __fds[i].revents = 0;
2648 return 0;
2649 }
2650 }
2651
sewardj08a4c3f2002-04-13 03:45:44 +00002652 }
2653}
sewardj3b13f0e2002-04-25 20:17:29 +00002654
2655
sewardj705d3cb2002-05-23 13:13:12 +00002656/* Helper function used to make accept() non-blocking. Idea is to use
2657 the above nonblocking poll() to make this thread ONLY wait for the
2658 specified fd to become ready, and then return. */
sewardjd1c1cf22002-06-26 00:13:36 +00002659
2660/* Sigh -- a hack. We're not supposed to include this file directly;
2661 should do it via /usr/include/fcntl.h, but that introduces a
2662 varargs prototype for fcntl itself, which we can't mimic. */
2663#define _FCNTL_H
2664#include <bits/fcntl.h>
2665
sewardj705d3cb2002-05-23 13:13:12 +00002666static void wait_for_fd_to_be_readable_or_erring ( int fd )
2667{
2668 struct pollfd pfd;
sewardjd1c1cf22002-06-26 00:13:36 +00002669 int res;
2670
sewardj6e6cbaa2002-05-24 02:12:52 +00002671 /* fprintf(stderr, "wait_for_fd_to_be_readable_or_erring %d\n", fd); */
sewardjd1c1cf22002-06-26 00:13:36 +00002672
2673 /* First check to see if the fd is nonblocking, and/or invalid. In
2674 either case return immediately. */
2675 res = __libc_fcntl(fd, F_GETFL, 0);
2676 if (res == -1) return; /* fd is invalid somehow */
2677 if (res & O_NONBLOCK) return; /* fd is nonblocking */
2678
2679 /* Ok, we'd better wait with poll. */
sewardj705d3cb2002-05-23 13:13:12 +00002680 pfd.fd = fd;
2681 pfd.events = POLLIN | POLLPRI | POLLERR | POLLHUP | POLLNVAL;
2682 /* ... but not POLLOUT, you may notice. */
2683 pfd.revents = 0;
2684 (void)poll(&pfd, 1, -1 /* forever */);
2685}
2686
sewardj2a68e7e2002-11-16 11:04:18 +00002687static void wait_for_fd_to_be_writable_or_erring ( int fd )
2688{
2689 struct pollfd pfd;
2690 int res;
2691
2692 /* fprintf(stderr, "wait_for_fd_to_be_readable_or_erring %d\n", fd); */
2693
2694 /* First check to see if the fd is nonblocking, and/or invalid. In
2695 either case return immediately. */
2696 res = __libc_fcntl(fd, F_GETFL, 0);
2697 if (res == -1) return; /* fd is invalid somehow */
2698 if (res & O_NONBLOCK) return; /* fd is nonblocking */
2699
2700 /* Ok, we'd better wait with poll. */
2701 pfd.fd = fd;
2702 pfd.events = POLLOUT | POLLERR | POLLHUP | POLLNVAL;
2703 pfd.revents = 0;
2704 (void)poll(&pfd, 1, -1 /* forever */);
2705}
sewardj705d3cb2002-05-23 13:13:12 +00002706
sewardj3b13f0e2002-04-25 20:17:29 +00002707/* ---------------------------------------------------------------------
sewardj8f253ff2002-05-19 00:13:34 +00002708 Hacky implementation of semaphores.
2709 ------------------------------------------------------------------ */
2710
2711#include <semaphore.h>
2712
2713/* This is a terrible way to do the remapping. Plan is to import an
2714 AVL tree at some point. */
sewardj8f253ff2002-05-19 00:13:34 +00002715
2716typedef
2717 struct {
2718 pthread_mutex_t se_mx;
2719 pthread_cond_t se_cv;
2720 int count;
2721 }
2722 vg_sem_t;
2723
2724static pthread_mutex_t se_remap_mx = PTHREAD_MUTEX_INITIALIZER;
2725
2726static int se_remap_used = 0;
2727static sem_t* se_remap_orig[VG_N_SEMAPHORES];
2728static vg_sem_t se_remap_new[VG_N_SEMAPHORES];
2729
2730static vg_sem_t* se_remap ( sem_t* orig )
2731{
2732 int res, i;
2733 res = __pthread_mutex_lock(&se_remap_mx);
sewardj2d94c112002-06-03 01:25:54 +00002734 my_assert(res == 0);
sewardj8f253ff2002-05-19 00:13:34 +00002735
2736 for (i = 0; i < se_remap_used; i++) {
2737 if (se_remap_orig[i] == orig)
2738 break;
2739 }
2740 if (i == se_remap_used) {
2741 if (se_remap_used == VG_N_SEMAPHORES) {
2742 res = pthread_mutex_unlock(&se_remap_mx);
sewardj2d94c112002-06-03 01:25:54 +00002743 my_assert(res == 0);
sewardja1ac5cb2002-05-27 13:00:05 +00002744 barf("VG_N_SEMAPHORES is too low. Increase and recompile.");
sewardj8f253ff2002-05-19 00:13:34 +00002745 }
2746 se_remap_used++;
2747 se_remap_orig[i] = orig;
2748 /* printf("allocated semaphore %d\n", i); */
2749 }
2750 res = __pthread_mutex_unlock(&se_remap_mx);
sewardj2d94c112002-06-03 01:25:54 +00002751 my_assert(res == 0);
sewardj8f253ff2002-05-19 00:13:34 +00002752 return &se_remap_new[i];
2753}
2754
2755
2756int sem_init(sem_t *sem, int pshared, unsigned int value)
2757{
2758 int res;
2759 vg_sem_t* vg_sem;
2760 ensure_valgrind("sem_init");
2761 if (pshared != 0) {
sewardj4dced352002-06-04 22:54:20 +00002762 pthread_error("sem_init: unsupported pshared value");
sewardj8f253ff2002-05-19 00:13:34 +00002763 errno = ENOSYS;
2764 return -1;
2765 }
2766 vg_sem = se_remap(sem);
2767 res = pthread_mutex_init(&vg_sem->se_mx, NULL);
sewardj2d94c112002-06-03 01:25:54 +00002768 my_assert(res == 0);
sewardj8f253ff2002-05-19 00:13:34 +00002769 res = pthread_cond_init(&vg_sem->se_cv, NULL);
sewardj2d94c112002-06-03 01:25:54 +00002770 my_assert(res == 0);
sewardj8f253ff2002-05-19 00:13:34 +00002771 vg_sem->count = value;
2772 return 0;
2773}
2774
2775
2776int sem_wait ( sem_t* sem )
2777{
2778 int res;
2779 vg_sem_t* vg_sem;
2780 ensure_valgrind("sem_wait");
2781 vg_sem = se_remap(sem);
2782 res = __pthread_mutex_lock(&vg_sem->se_mx);
sewardj2d94c112002-06-03 01:25:54 +00002783 my_assert(res == 0);
sewardj8f253ff2002-05-19 00:13:34 +00002784 while (vg_sem->count == 0) {
2785 res = pthread_cond_wait(&vg_sem->se_cv, &vg_sem->se_mx);
sewardj2d94c112002-06-03 01:25:54 +00002786 my_assert(res == 0);
sewardj8f253ff2002-05-19 00:13:34 +00002787 }
2788 vg_sem->count--;
2789 res = __pthread_mutex_unlock(&vg_sem->se_mx);
sewardj2d94c112002-06-03 01:25:54 +00002790 my_assert(res == 0);
sewardj8f253ff2002-05-19 00:13:34 +00002791 return 0;
2792}
2793
2794int sem_post ( sem_t* sem )
2795{
2796 int res;
2797 vg_sem_t* vg_sem;
2798 ensure_valgrind("sem_post");
2799 vg_sem = se_remap(sem);
2800 res = __pthread_mutex_lock(&vg_sem->se_mx);
sewardj2d94c112002-06-03 01:25:54 +00002801 my_assert(res == 0);
sewardj8f253ff2002-05-19 00:13:34 +00002802 if (vg_sem->count == 0) {
2803 vg_sem->count++;
2804 res = pthread_cond_broadcast(&vg_sem->se_cv);
sewardj2d94c112002-06-03 01:25:54 +00002805 my_assert(res == 0);
sewardj8f253ff2002-05-19 00:13:34 +00002806 } else {
2807 vg_sem->count++;
2808 }
2809 res = __pthread_mutex_unlock(&vg_sem->se_mx);
sewardj2d94c112002-06-03 01:25:54 +00002810 my_assert(res == 0);
sewardj8f253ff2002-05-19 00:13:34 +00002811 return 0;
2812}
2813
2814
2815int sem_trywait ( sem_t* sem )
2816{
2817 int ret, res;
2818 vg_sem_t* vg_sem;
2819 ensure_valgrind("sem_trywait");
2820 vg_sem = se_remap(sem);
2821 res = __pthread_mutex_lock(&vg_sem->se_mx);
sewardj2d94c112002-06-03 01:25:54 +00002822 my_assert(res == 0);
sewardj8f253ff2002-05-19 00:13:34 +00002823 if (vg_sem->count > 0) {
2824 vg_sem->count--;
2825 ret = 0;
2826 } else {
2827 ret = -1;
2828 errno = EAGAIN;
2829 }
2830 res = __pthread_mutex_unlock(&vg_sem->se_mx);
sewardj2d94c112002-06-03 01:25:54 +00002831 my_assert(res == 0);
sewardj8f253ff2002-05-19 00:13:34 +00002832 return ret;
2833}
2834
2835
2836int sem_getvalue(sem_t* sem, int * sval)
2837{
2838 vg_sem_t* vg_sem;
2839 ensure_valgrind("sem_trywait");
2840 vg_sem = se_remap(sem);
2841 *sval = vg_sem->count;
2842 return 0;
2843}
2844
2845
2846int sem_destroy(sem_t * sem)
2847{
2848 kludged("sem_destroy");
2849 /* if someone waiting on this semaphore, errno = EBUSY, return -1 */
2850 return 0;
2851}
2852
sewardj9ad92d92002-10-16 19:45:06 +00002853
2854int sem_timedwait(sem_t* sem, const struct timespec *abstime)
2855{
2856 int res;
2857 vg_sem_t* vg_sem;
2858 ensure_valgrind("sem_timedwait");
2859 vg_sem = se_remap(sem);
2860 res = __pthread_mutex_lock(&vg_sem->se_mx);
2861 my_assert(res == 0);
2862 while ( vg_sem->count == 0 && res != ETIMEDOUT ) {
2863 res = pthread_cond_timedwait(&vg_sem->se_cv, &vg_sem->se_mx, abstime);
2864 }
2865 if ( vg_sem->count > 0 ) {
2866 vg_sem->count--;
2867 res = __pthread_mutex_unlock(&vg_sem->se_mx);
2868 my_assert(res == 0 );
2869 return 0;
2870 } else {
2871 res = __pthread_mutex_unlock(&vg_sem->se_mx);
2872 my_assert(res == 0 );
2873 *(__errno_location()) = ETIMEDOUT;
2874 return -1;
2875 }
2876}
2877
sewardj8f253ff2002-05-19 00:13:34 +00002878
2879/* ---------------------------------------------------------------------
sewardj2d8b3f02002-06-01 14:14:19 +00002880 Reader-writer locks.
sewardja1ac5cb2002-05-27 13:00:05 +00002881 ------------------------------------------------------------------ */
2882
sewardj2d8b3f02002-06-01 14:14:19 +00002883typedef
2884 struct {
2885 int initted; /* != 0 --> in use; sanity check only */
2886 int prefer_w; /* != 0 --> prefer writer */
2887 int nwait_r; /* # of waiting readers */
2888 int nwait_w; /* # of waiting writers */
2889 pthread_cond_t cv_r; /* for signalling readers */
2890 pthread_cond_t cv_w; /* for signalling writers */
2891 pthread_mutex_t mx;
2892 int status;
2893 /* allowed range for status: >= -1. -1 means 1 writer currently
2894 active, >= 0 means N readers currently active. */
2895 }
2896 vg_rwlock_t;
sewardja1ac5cb2002-05-27 13:00:05 +00002897
2898
2899static pthread_mutex_t rw_remap_mx = PTHREAD_MUTEX_INITIALIZER;
2900
2901static int rw_remap_used = 0;
2902static pthread_rwlock_t* rw_remap_orig[VG_N_RWLOCKS];
2903static vg_rwlock_t rw_remap_new[VG_N_RWLOCKS];
2904
sewardj2d8b3f02002-06-01 14:14:19 +00002905
2906static
2907void init_vg_rwlock ( vg_rwlock_t* vg_rwl )
2908{
2909 int res = 0;
2910 vg_rwl->initted = 1;
2911 vg_rwl->prefer_w = 1;
2912 vg_rwl->nwait_r = 0;
2913 vg_rwl->nwait_w = 0;
2914 vg_rwl->status = 0;
2915 res = pthread_mutex_init(&vg_rwl->mx, NULL);
2916 res |= pthread_cond_init(&vg_rwl->cv_r, NULL);
2917 res |= pthread_cond_init(&vg_rwl->cv_w, NULL);
sewardj2d94c112002-06-03 01:25:54 +00002918 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002919}
2920
2921
sewardja1ac5cb2002-05-27 13:00:05 +00002922/* Take the address of a LinuxThreads rwlock_t and return the shadow
2923 address of our version. Further, if the LinuxThreads version
2924 appears to have been statically initialised, do the same to the one
2925 we allocate here. The pthread_rwlock_t.__rw_readers field is set
2926 to zero by PTHREAD_RWLOCK_INITIALIZER, so we take zero as meaning
2927 uninitialised and non-zero meaning initialised.
2928*/
2929static vg_rwlock_t* rw_remap ( pthread_rwlock_t* orig )
2930{
2931 int res, i;
2932 vg_rwlock_t* vg_rwl;
2933 res = __pthread_mutex_lock(&rw_remap_mx);
sewardj2d94c112002-06-03 01:25:54 +00002934 my_assert(res == 0);
sewardja1ac5cb2002-05-27 13:00:05 +00002935
2936 for (i = 0; i < rw_remap_used; i++) {
2937 if (rw_remap_orig[i] == orig)
2938 break;
2939 }
2940 if (i == rw_remap_used) {
2941 if (rw_remap_used == VG_N_RWLOCKS) {
sewardj2d8b3f02002-06-01 14:14:19 +00002942 res = __pthread_mutex_unlock(&rw_remap_mx);
sewardj2d94c112002-06-03 01:25:54 +00002943 my_assert(res == 0);
sewardja1ac5cb2002-05-27 13:00:05 +00002944 barf("VG_N_RWLOCKS is too low. Increase and recompile.");
2945 }
2946 rw_remap_used++;
2947 rw_remap_orig[i] = orig;
sewardj2d8b3f02002-06-01 14:14:19 +00002948 rw_remap_new[i].initted = 0;
sewardja1ac5cb2002-05-27 13:00:05 +00002949 if (0) printf("allocated rwlock %d\n", i);
2950 }
2951 res = __pthread_mutex_unlock(&rw_remap_mx);
sewardj2d94c112002-06-03 01:25:54 +00002952 my_assert(res == 0);
sewardja1ac5cb2002-05-27 13:00:05 +00002953 vg_rwl = &rw_remap_new[i];
2954
sewardj2d8b3f02002-06-01 14:14:19 +00002955 /* Initialise the shadow, if required. */
sewardja1ac5cb2002-05-27 13:00:05 +00002956 if (orig->__rw_readers == 0) {
sewardja1ac5cb2002-05-27 13:00:05 +00002957 orig->__rw_readers = 1;
sewardj2d8b3f02002-06-01 14:14:19 +00002958 init_vg_rwlock(vg_rwl);
sewardja1ac5cb2002-05-27 13:00:05 +00002959 if (orig->__rw_kind == PTHREAD_RWLOCK_PREFER_READER_NP)
sewardj2d8b3f02002-06-01 14:14:19 +00002960 vg_rwl->prefer_w = 0;
sewardja1ac5cb2002-05-27 13:00:05 +00002961 }
2962
2963 return vg_rwl;
2964}
2965
2966
sewardja1ac5cb2002-05-27 13:00:05 +00002967int pthread_rwlock_init ( pthread_rwlock_t* orig,
2968 const pthread_rwlockattr_t* attr )
2969{
sewardja1ac5cb2002-05-27 13:00:05 +00002970 vg_rwlock_t* rwl;
2971 if (0) printf ("pthread_rwlock_init\n");
2972 /* Force the remapper to initialise the shadow. */
2973 orig->__rw_readers = 0;
2974 /* Install the lock preference; the remapper needs to know it. */
2975 orig->__rw_kind = PTHREAD_RWLOCK_DEFAULT_NP;
2976 if (attr)
2977 orig->__rw_kind = attr->__lockkind;
2978 rwl = rw_remap ( orig );
sewardj2d8b3f02002-06-01 14:14:19 +00002979 return 0;
sewardja1ac5cb2002-05-27 13:00:05 +00002980}
2981
sewardj2d8b3f02002-06-01 14:14:19 +00002982
2983static
2984void pthread_rwlock_rdlock_CANCEL_HDLR ( void* rwl_v )
sewardja1ac5cb2002-05-27 13:00:05 +00002985{
sewardj2d8b3f02002-06-01 14:14:19 +00002986 vg_rwlock_t* rwl = (vg_rwlock_t*)rwl_v;
2987 rwl->nwait_r--;
2988 pthread_mutex_unlock (&rwl->mx);
sewardja1ac5cb2002-05-27 13:00:05 +00002989}
2990
sewardj2d8b3f02002-06-01 14:14:19 +00002991
sewardja1ac5cb2002-05-27 13:00:05 +00002992int pthread_rwlock_rdlock ( pthread_rwlock_t* orig )
2993{
2994 int res;
2995 vg_rwlock_t* rwl;
2996 if (0) printf ("pthread_rwlock_rdlock\n");
2997 rwl = rw_remap ( orig );
sewardj2d8b3f02002-06-01 14:14:19 +00002998 res = __pthread_mutex_lock(&rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00002999 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00003000 if (!rwl->initted) {
3001 res = __pthread_mutex_unlock(&rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00003002 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00003003 return EINVAL;
3004 }
3005 if (rwl->status < 0) {
sewardj2d94c112002-06-03 01:25:54 +00003006 my_assert(rwl->status == -1);
sewardj2d8b3f02002-06-01 14:14:19 +00003007 rwl->nwait_r++;
3008 pthread_cleanup_push( pthread_rwlock_rdlock_CANCEL_HDLR, rwl );
3009 while (1) {
3010 if (rwl->status == 0) break;
3011 res = pthread_cond_wait(&rwl->cv_r, &rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00003012 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00003013 }
3014 pthread_cleanup_pop(0);
3015 rwl->nwait_r--;
3016 }
sewardj2d94c112002-06-03 01:25:54 +00003017 my_assert(rwl->status >= 0);
sewardj2d8b3f02002-06-01 14:14:19 +00003018 rwl->status++;
3019 res = __pthread_mutex_unlock(&rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00003020 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00003021 return 0;
sewardja1ac5cb2002-05-27 13:00:05 +00003022}
3023
sewardj2d8b3f02002-06-01 14:14:19 +00003024
sewardja1ac5cb2002-05-27 13:00:05 +00003025int pthread_rwlock_tryrdlock ( pthread_rwlock_t* orig )
3026{
3027 int res;
3028 vg_rwlock_t* rwl;
3029 if (0) printf ("pthread_rwlock_tryrdlock\n");
3030 rwl = rw_remap ( orig );
sewardj2d8b3f02002-06-01 14:14:19 +00003031 res = __pthread_mutex_lock(&rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00003032 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00003033 if (!rwl->initted) {
3034 res = __pthread_mutex_unlock(&rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00003035 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00003036 return EINVAL;
3037 }
3038 if (rwl->status == -1) {
3039 /* Writer active; we have to give up. */
3040 res = __pthread_mutex_unlock(&rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00003041 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00003042 return EBUSY;
3043 }
3044 /* Success */
sewardj2d94c112002-06-03 01:25:54 +00003045 my_assert(rwl->status >= 0);
sewardj2d8b3f02002-06-01 14:14:19 +00003046 rwl->status++;
3047 res = __pthread_mutex_unlock(&rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00003048 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00003049 return 0;
sewardja1ac5cb2002-05-27 13:00:05 +00003050}
3051
sewardj2d8b3f02002-06-01 14:14:19 +00003052
3053static
3054void pthread_rwlock_wrlock_CANCEL_HDLR ( void* rwl_v )
3055{
3056 vg_rwlock_t* rwl = (vg_rwlock_t*)rwl_v;
3057 rwl->nwait_w--;
3058 pthread_mutex_unlock (&rwl->mx);
3059}
3060
3061
sewardja1ac5cb2002-05-27 13:00:05 +00003062int pthread_rwlock_wrlock ( pthread_rwlock_t* orig )
3063{
3064 int res;
3065 vg_rwlock_t* rwl;
3066 if (0) printf ("pthread_rwlock_wrlock\n");
3067 rwl = rw_remap ( orig );
sewardj2d8b3f02002-06-01 14:14:19 +00003068 res = __pthread_mutex_lock(&rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00003069 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00003070 if (!rwl->initted) {
3071 res = __pthread_mutex_unlock(&rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00003072 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00003073 return EINVAL;
3074 }
3075 if (rwl->status != 0) {
3076 rwl->nwait_w++;
3077 pthread_cleanup_push( pthread_rwlock_wrlock_CANCEL_HDLR, rwl );
3078 while (1) {
3079 if (rwl->status == 0) break;
3080 res = pthread_cond_wait(&rwl->cv_w, &rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00003081 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00003082 }
3083 pthread_cleanup_pop(0);
3084 rwl->nwait_w--;
3085 }
sewardj2d94c112002-06-03 01:25:54 +00003086 my_assert(rwl->status == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00003087 rwl->status = -1;
3088 res = __pthread_mutex_unlock(&rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00003089 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00003090 return 0;
sewardja1ac5cb2002-05-27 13:00:05 +00003091}
3092
sewardj2d8b3f02002-06-01 14:14:19 +00003093
sewardja1ac5cb2002-05-27 13:00:05 +00003094int pthread_rwlock_trywrlock ( pthread_rwlock_t* orig )
3095{
3096 int res;
3097 vg_rwlock_t* rwl;
sewardj2d8b3f02002-06-01 14:14:19 +00003098 if (0) printf ("pthread_wrlock_trywrlock\n");
sewardja1ac5cb2002-05-27 13:00:05 +00003099 rwl = rw_remap ( orig );
sewardj2d8b3f02002-06-01 14:14:19 +00003100 res = __pthread_mutex_lock(&rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00003101 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00003102 if (!rwl->initted) {
3103 res = __pthread_mutex_unlock(&rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00003104 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00003105 return EINVAL;
3106 }
3107 if (rwl->status != 0) {
3108 /* Reader(s) or a writer active; we have to give up. */
3109 res = __pthread_mutex_unlock(&rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00003110 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00003111 return EBUSY;
3112 }
3113 /* Success */
sewardj2d94c112002-06-03 01:25:54 +00003114 my_assert(rwl->status == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00003115 rwl->status = -1;
3116 res = __pthread_mutex_unlock(&rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00003117 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00003118 return 0;
sewardja1ac5cb2002-05-27 13:00:05 +00003119}
3120
sewardj2d8b3f02002-06-01 14:14:19 +00003121
sewardja1ac5cb2002-05-27 13:00:05 +00003122int pthread_rwlock_unlock ( pthread_rwlock_t* orig )
3123{
3124 int res;
3125 vg_rwlock_t* rwl;
3126 if (0) printf ("pthread_rwlock_unlock\n");
3127 rwl = rw_remap ( orig );
sewardj2d8b3f02002-06-01 14:14:19 +00003128 rwl = rw_remap ( orig );
3129 res = __pthread_mutex_lock(&rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00003130 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00003131 if (!rwl->initted) {
3132 res = __pthread_mutex_unlock(&rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00003133 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00003134 return EINVAL;
3135 }
3136 if (rwl->status == 0) {
3137 res = __pthread_mutex_unlock(&rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00003138 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00003139 return EPERM;
3140 }
sewardj2d94c112002-06-03 01:25:54 +00003141 my_assert(rwl->status != 0);
sewardj2d8b3f02002-06-01 14:14:19 +00003142 if (rwl->status == -1) {
3143 rwl->status = 0;
3144 } else {
sewardj2d94c112002-06-03 01:25:54 +00003145 my_assert(rwl->status > 0);
sewardj2d8b3f02002-06-01 14:14:19 +00003146 rwl->status--;
3147 }
3148
sewardj2d94c112002-06-03 01:25:54 +00003149 my_assert(rwl->status >= 0);
sewardj2d8b3f02002-06-01 14:14:19 +00003150
3151 if (rwl->prefer_w) {
3152
3153 /* Favour waiting writers, if any. */
3154 if (rwl->nwait_w > 0) {
3155 /* Writer(s) are waiting. */
3156 if (rwl->status == 0) {
3157 /* We can let a writer in. */
3158 res = pthread_cond_signal(&rwl->cv_w);
sewardj2d94c112002-06-03 01:25:54 +00003159 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00003160 } else {
3161 /* There are still readers active. Do nothing; eventually
3162 they will disappear, at which point a writer will be
3163 admitted. */
3164 }
3165 }
3166 else
3167 /* No waiting writers. */
3168 if (rwl->nwait_r > 0) {
3169 /* Let in a waiting reader. */
3170 res = pthread_cond_signal(&rwl->cv_r);
sewardj2d94c112002-06-03 01:25:54 +00003171 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00003172 }
3173
3174 } else {
3175
3176 /* Favour waiting readers, if any. */
3177 if (rwl->nwait_r > 0) {
3178 /* Reader(s) are waiting; let one in. */
3179 res = pthread_cond_signal(&rwl->cv_r);
sewardj2d94c112002-06-03 01:25:54 +00003180 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00003181 }
3182 else
3183 /* No waiting readers. */
3184 if (rwl->nwait_w > 0 && rwl->status == 0) {
3185 /* We have waiting writers and no active readers; let a
3186 writer in. */
3187 res = pthread_cond_signal(&rwl->cv_w);
sewardj2d94c112002-06-03 01:25:54 +00003188 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00003189 }
3190 }
3191
3192 res = __pthread_mutex_unlock(&rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00003193 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00003194 return 0;
3195}
3196
3197
3198int pthread_rwlock_destroy ( pthread_rwlock_t *orig )
3199{
3200 int res;
3201 vg_rwlock_t* rwl;
3202 if (0) printf ("pthread_rwlock_destroy\n");
3203 rwl = rw_remap ( orig );
3204 res = __pthread_mutex_lock(&rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00003205 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00003206 if (!rwl->initted) {
3207 res = __pthread_mutex_unlock(&rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00003208 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00003209 return EINVAL;
3210 }
3211 if (rwl->status != 0 || rwl->nwait_r > 0 || rwl->nwait_w > 0) {
3212 res = __pthread_mutex_unlock(&rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00003213 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00003214 return EBUSY;
3215 }
3216 rwl->initted = 0;
3217 res = __pthread_mutex_unlock(&rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00003218 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00003219 return 0;
sewardja1ac5cb2002-05-27 13:00:05 +00003220}
3221
3222
sewardj47e4e312002-06-18 09:24:34 +00003223/* Copied directly from LinuxThreads. */
3224int
3225pthread_rwlockattr_init (pthread_rwlockattr_t *attr)
3226{
3227 attr->__lockkind = 0;
3228 attr->__pshared = PTHREAD_PROCESS_PRIVATE;
3229
3230 return 0;
3231}
3232
sewardjfe18eb82002-07-13 12:58:44 +00003233/* Copied directly from LinuxThreads. */
3234int
3235pthread_rwlockattr_setpshared (pthread_rwlockattr_t *attr, int pshared)
3236{
3237 if (pshared != PTHREAD_PROCESS_PRIVATE && pshared != PTHREAD_PROCESS_SHARED)
3238 return EINVAL;
3239
3240 /* For now it is not possible to shared a conditional variable. */
3241 if (pshared != PTHREAD_PROCESS_PRIVATE)
3242 return ENOSYS;
3243
3244 attr->__pshared = pshared;
3245
3246 return 0;
3247}
3248
sewardj47e4e312002-06-18 09:24:34 +00003249
sewardja1ac5cb2002-05-27 13:00:05 +00003250/* ---------------------------------------------------------------------
sewardjd5bef572002-10-23 21:49:33 +00003251 Make SYSV IPC not block everything
3252 ------------------------------------------------------------------ */
3253
3254#include <sys/ipc.h>
3255#include <sys/msg.h>
3256#include <asm/ipc.h> /* for ipc_kludge */
3257
3258static inline int sys_ipc(unsigned call, int first, int second, int third, void *ptr)
3259{
3260 return my_do_syscall5(__NR_ipc, call, first, second, third, (int)ptr);
3261}
3262
3263/* Turn a blocking msgsnd() into a polling non-blocking one, so that
3264 other threads make progress */
sewardjf220ccc2002-10-23 21:53:49 +00003265int VGL_(msgsnd)(int msgid, const void *msgp, size_t msgsz, int msgflg)
sewardjd5bef572002-10-23 21:49:33 +00003266{
3267 struct vki_timespec nanosleep_interval;
3268 int err;
3269
3270 ensure_valgrind("msgsnd");
3271
3272 nanosleep_interval.tv_sec = 0;
3273 nanosleep_interval.tv_nsec = 13 * 1000 * 1000; /* 13 milliseconds */
3274
3275 if (msgflg & IPC_NOWAIT) {
3276 /* If we aren't blocking anyway, just do it */
3277 err = sys_ipc(11, msgid, msgsz, msgflg, (void *)msgp);
3278 } else {
3279 /* Otherwise poll on the queue to let other things run */
3280 for(;;) {
3281 err = sys_ipc(11, msgid, msgsz, msgflg | IPC_NOWAIT, (void *)msgp);
3282
3283 if (err != -EAGAIN)
3284 break;
3285
3286 (void)my_do_syscall2(__NR_nanosleep,
3287 (int)(&nanosleep_interval), (int)NULL);
3288 }
3289 }
3290
3291 if (is_kerror(err)) {
3292 *(__errno_location()) = -err;
3293 return -1;
3294 }
3295 return 0;
3296}
3297
3298/* Turn a blocking msgrcv() into a polling non-blocking one, so that
3299 other threads make progress */
sewardjf220ccc2002-10-23 21:53:49 +00003300int VGL_(msgrcv)( int msqid, void *msgp, size_t msgsz, long msgtyp, int msgflg )
sewardjd5bef572002-10-23 21:49:33 +00003301{
3302 struct vki_timespec nanosleep_interval;
3303 int err;
3304 struct ipc_kludge tmp;
3305
3306 ensure_valgrind("msgrcv");
3307
3308 nanosleep_interval.tv_sec = 0;
3309 nanosleep_interval.tv_nsec = 13 * 1000 * 1000; /* 13 milliseconds */
3310
3311 tmp.msgp = msgp;
3312 tmp.msgtyp = msgtyp;
3313
3314 if (msgflg & IPC_NOWAIT) {
3315 /* If we aren't blocking anyway, just do it */
3316 err = sys_ipc(12, msqid, msgsz, msgflg, &tmp );
3317 } else {
3318 /* Otherwise poll on the queue to let other things run */
3319 for(;;) {
3320 err = sys_ipc(12, msqid, msgsz, msgflg | IPC_NOWAIT, &tmp );
3321
3322 if (err != -ENOMSG)
3323 break;
3324
3325 (void)my_do_syscall2(__NR_nanosleep,
3326 (int)(&nanosleep_interval), (int)NULL);
3327 }
3328 }
3329
3330 if (is_kerror(err)) {
3331 *(__errno_location()) = -err;
3332 return -1;
3333 }
3334
3335 return 0;
3336}
3337
3338
3339
3340/* ---------------------------------------------------------------------
sewardj3b13f0e2002-04-25 20:17:29 +00003341 B'stard.
3342 ------------------------------------------------------------------ */
3343
3344# define strong_alias(name, aliasname) \
3345 extern __typeof (name) aliasname __attribute__ ((alias (#name)));
3346
sewardj5905fae2002-04-26 13:25:00 +00003347# define weak_alias(name, aliasname) \
3348 extern __typeof (name) aliasname __attribute__ ((weak, alias (#name)));
sewardj3b13f0e2002-04-25 20:17:29 +00003349
sewardj5905fae2002-04-26 13:25:00 +00003350strong_alias(__pthread_mutex_lock, pthread_mutex_lock)
3351strong_alias(__pthread_mutex_trylock, pthread_mutex_trylock)
3352strong_alias(__pthread_mutex_unlock, pthread_mutex_unlock)
3353strong_alias(__pthread_mutexattr_init, pthread_mutexattr_init)
3354 weak_alias(__pthread_mutexattr_settype, pthread_mutexattr_settype)
3355strong_alias(__pthread_mutex_init, pthread_mutex_init)
3356strong_alias(__pthread_mutexattr_destroy, pthread_mutexattr_destroy)
3357strong_alias(__pthread_mutex_destroy, pthread_mutex_destroy)
3358strong_alias(__pthread_once, pthread_once)
3359strong_alias(__pthread_atfork, pthread_atfork)
3360strong_alias(__pthread_key_create, pthread_key_create)
3361strong_alias(__pthread_getspecific, pthread_getspecific)
3362strong_alias(__pthread_setspecific, pthread_setspecific)
3363
sewardjd529a442002-05-04 19:49:21 +00003364#ifndef GLIBC_2_1
sewardj3b13f0e2002-04-25 20:17:29 +00003365strong_alias(sigaction, __sigaction)
sewardjd529a442002-05-04 19:49:21 +00003366#endif
3367
sewardj5905fae2002-04-26 13:25:00 +00003368strong_alias(close, __close)
sewardj3b13f0e2002-04-25 20:17:29 +00003369strong_alias(fcntl, __fcntl)
sewardj5905fae2002-04-26 13:25:00 +00003370strong_alias(lseek, __lseek)
3371strong_alias(open, __open)
3372strong_alias(open64, __open64)
sewardj5905fae2002-04-26 13:25:00 +00003373strong_alias(read, __read)
3374strong_alias(wait, __wait)
3375strong_alias(write, __write)
sewardj3b13f0e2002-04-25 20:17:29 +00003376strong_alias(connect, __connect)
sewardj5905fae2002-04-26 13:25:00 +00003377strong_alias(send, __send)
3378
sewardj726c4122002-05-16 23:39:10 +00003379weak_alias (__pread64, pread64)
sewardja18e2102002-05-18 10:43:22 +00003380weak_alias (__pwrite64, pwrite64)
sewardj5905fae2002-04-26 13:25:00 +00003381weak_alias(__fork, fork)
njn25e49d8e72002-09-23 09:36:25 +00003382weak_alias(__vfork, vfork)
sewardj7f6456d2002-05-21 00:51:21 +00003383
sewardjf0b06452002-06-04 08:38:04 +00003384weak_alias (__pthread_kill_other_threads_np, pthread_kill_other_threads_np)
sewardj3b13f0e2002-04-25 20:17:29 +00003385
3386/*--------------------------------------------------*/
3387
sewardj5905fae2002-04-26 13:25:00 +00003388weak_alias(pthread_rwlock_rdlock, __pthread_rwlock_rdlock)
sewardj5905fae2002-04-26 13:25:00 +00003389weak_alias(pthread_rwlock_unlock, __pthread_rwlock_unlock)
sewardj262b0292002-05-01 00:03:16 +00003390weak_alias(pthread_rwlock_wrlock, __pthread_rwlock_wrlock)
sewardj060b04f2002-04-26 21:01:13 +00003391
sewardja1ac5cb2002-05-27 13:00:05 +00003392weak_alias(pthread_rwlock_destroy, __pthread_rwlock_destroy)
3393weak_alias(pthread_rwlock_init, __pthread_rwlock_init)
3394weak_alias(pthread_rwlock_tryrdlock, __pthread_rwlock_tryrdlock)
3395weak_alias(pthread_rwlock_trywrlock, __pthread_rwlock_trywrlock)
3396
sewardj060b04f2002-04-26 21:01:13 +00003397
sewardj3b13f0e2002-04-25 20:17:29 +00003398/* I've no idea what these are, but they get called quite a lot.
3399 Anybody know? */
3400
3401#undef _IO_flockfile
3402void _IO_flockfile ( _IO_FILE * file )
3403{
sewardj853f55d2002-04-26 00:27:53 +00003404 pthread_mutex_lock(file->_lock);
sewardj3b13f0e2002-04-25 20:17:29 +00003405}
sewardj5905fae2002-04-26 13:25:00 +00003406weak_alias(_IO_flockfile, flockfile);
3407
sewardj3b13f0e2002-04-25 20:17:29 +00003408
3409#undef _IO_funlockfile
3410void _IO_funlockfile ( _IO_FILE * file )
3411{
sewardj853f55d2002-04-26 00:27:53 +00003412 pthread_mutex_unlock(file->_lock);
sewardj3b13f0e2002-04-25 20:17:29 +00003413}
sewardj5905fae2002-04-26 13:25:00 +00003414weak_alias(_IO_funlockfile, funlockfile);
3415
sewardj3b13f0e2002-04-25 20:17:29 +00003416
sewardjd4f2c712002-04-30 10:20:10 +00003417/* This doesn't seem to be needed to simulate libpthread.so's external
3418 interface, but many people complain about its absence. */
3419
3420strong_alias(__pthread_mutexattr_settype, __pthread_mutexattr_setkind_np)
3421weak_alias(__pthread_mutexattr_setkind_np, pthread_mutexattr_setkind_np)
sewardj439d45e2002-05-03 20:43:10 +00003422
3423
3424/*--------------------------------------------------------------------*/
3425/*--- end vg_libpthread.c ---*/
3426/*--------------------------------------------------------------------*/