blob: 400af5d001beaa834334843eb6f91d14ab192da4 [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
njn0e1b5142003-04-15 14:58:06 +000011 Copyright (C) 2000-2003 Julian Seward
sewardj439d45e2002-05-03 20:43:10 +000012 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
sewardje12a45f2003-03-15 20:03:33 +000055/* Sidestep the normal check which disallows using valgrind.h
56 directly. */
57#define __VALGRIND_SOMESKIN_H
sewardje663cb92002-04-12 10:26:32 +000058#include "valgrind.h" /* For the request-passing mechanism */
sewardje12a45f2003-03-15 20:03:33 +000059
sewardje663cb92002-04-12 10:26:32 +000060#include "vg_include.h" /* For the VG_USERREQ__* constants */
61
sewardja1ac5cb2002-05-27 13:00:05 +000062#define __USE_UNIX98
63#include <sys/types.h>
64#include <pthread.h>
65#undef __USE_UNIX98
66
sewardje663cb92002-04-12 10:26:32 +000067#include <unistd.h>
68#include <string.h>
sewardj2a1dcce2002-04-22 12:45:25 +000069#ifdef GLIBC_2_1
70#include <sys/time.h>
71#endif
sewardjf912dfc2002-11-13 21:51:10 +000072#include <sys/stat.h>
73#include <sys/poll.h>
sewardj2d94c112002-06-03 01:25:54 +000074#include <stdio.h>
75
sewardj705d3cb2002-05-23 13:13:12 +000076
77/* ---------------------------------------------------------------------
78 Forwardses.
79 ------------------------------------------------------------------ */
80
81static void wait_for_fd_to_be_readable_or_erring ( int fd );
sewardj12a0e042002-11-30 14:02:53 +000082static void wait_for_fd_to_be_writable_or_erring ( int fd );
sewardj705d3cb2002-05-23 13:13:12 +000083
sewardj9a2224b2002-06-19 10:17:40 +000084static
sewardj08c7f012002-10-07 23:56:55 +000085int my_do_syscall1 ( int syscallno, int arg1 );
86
87static
sewardj9a2224b2002-06-19 10:17:40 +000088int my_do_syscall2 ( int syscallno,
89 int arg1, int arg2 );
90
sewardj08c7f012002-10-07 23:56:55 +000091static
92int my_do_syscall3 ( int syscallno,
93 int arg1, int arg2, int arg3 );
94
sewardjfd7747b2002-12-01 10:25:53 +000095static
96__inline__
97int is_kerror ( int res )
98{
99 if (res >= -4095 && res <= -1)
100 return 1;
101 else
102 return 0;
103}
104
sewardj08c7f012002-10-07 23:56:55 +0000105
106#ifdef GLIBC_2_3
107 /* kludge by JRS (not from glibc) ... */
108 typedef void* __locale_t;
109
110 /* Copied from locale/locale.h in glibc-2.2.93 sources */
111 /* This value can be passed to `uselocale' and may be returned by
112 it. Passing this value to any other function has undefined
113 behavior. */
114# define LC_GLOBAL_LOCALE ((__locale_t) -1L)
115 extern __locale_t __uselocale ( __locale_t );
116#endif
117
sewardj00a66b12002-10-12 16:42:35 +0000118static
119void init_libc_tsd_keys ( void );
120
sewardj705d3cb2002-05-23 13:13:12 +0000121
sewardje663cb92002-04-12 10:26:32 +0000122/* ---------------------------------------------------------------------
123 Helpers. We have to be pretty self-sufficient.
124 ------------------------------------------------------------------ */
125
sewardj436e0582002-04-26 14:31:40 +0000126/* Number of times any given error message is printed. */
127#define N_MOANS 3
128
sewardj45b4b372002-04-16 22:50:32 +0000129/* Extract from Valgrind the value of VG_(clo_trace_pthread_level).
130 Returns 0 (none) if not running on Valgrind. */
131static
132int get_pt_trace_level ( void )
133{
134 int res;
135 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
136 VG_USERREQ__GET_PTHREAD_TRACE_LEVEL,
137 0, 0, 0, 0);
138 return res;
139}
140
sewardje663cb92002-04-12 10:26:32 +0000141static
sewardj2d94c112002-06-03 01:25:54 +0000142void my_exit ( int arg )
sewardje663cb92002-04-12 10:26:32 +0000143{
sewardj08c7f012002-10-07 23:56:55 +0000144 my_do_syscall1(__NR_exit, arg);
145 /*NOTREACHED*/
sewardje663cb92002-04-12 10:26:32 +0000146}
147
sewardje0cfe2a2002-11-30 14:04:45 +0000148/* Apparently unused.
sewardj08c7f012002-10-07 23:56:55 +0000149static
150void my_write ( int fd, const void *buf, int count )
151{
152 my_do_syscall3(__NR_write, fd, (int)buf, count );
153}
sewardje0cfe2a2002-11-30 14:04:45 +0000154*/
sewardje663cb92002-04-12 10:26:32 +0000155
sewardj68b2dd92002-05-10 21:03:56 +0000156/* We need this guy -- it's in valgrind.so. */
157extern void VG_(startup) ( void );
158
159
160/* Just start up Valgrind if it's not already going. VG_(startup)()
161 detects and ignores second and subsequent calls. */
sewardj604ec3c2002-04-18 22:38:41 +0000162static __inline__
sewardje663cb92002-04-12 10:26:32 +0000163void ensure_valgrind ( char* caller )
164{
sewardj68b2dd92002-05-10 21:03:56 +0000165 VG_(startup)();
sewardje663cb92002-04-12 10:26:32 +0000166}
167
sewardjbea1caa2002-05-10 23:20:58 +0000168/* While we're at it ... hook our own startup function into this
169 game. */
170__asm__ (
171 ".section .init\n"
172 "\tcall vgPlain_startup"
173);
174
sewardje663cb92002-04-12 10:26:32 +0000175
176static
sewardj3b5d8862002-04-20 13:53:23 +0000177__attribute__((noreturn))
sewardje663cb92002-04-12 10:26:32 +0000178void barf ( char* str )
179{
sewardj69a72a52002-11-03 13:41:41 +0000180 int res;
181 char buf[1000];
sewardje663cb92002-04-12 10:26:32 +0000182 buf[0] = 0;
sewardj439d45e2002-05-03 20:43:10 +0000183 strcat(buf, "\nvalgrind's libpthread.so: ");
sewardje663cb92002-04-12 10:26:32 +0000184 strcat(buf, str);
185 strcat(buf, "\n\n");
sewardj69a72a52002-11-03 13:41:41 +0000186 VALGRIND_MAGIC_SEQUENCE(res, 0, /* irrelevant default */
187 VG_USERREQ__LOGMESSAGE, buf, 0, 0, 0);
sewardj2d94c112002-06-03 01:25:54 +0000188 my_exit(1);
sewardj3b5d8862002-04-20 13:53:23 +0000189 /* We have to persuade gcc into believing this doesn't return. */
190 while (1) { };
sewardje663cb92002-04-12 10:26:32 +0000191}
192
193
sewardj69a72a52002-11-03 13:41:41 +0000194static void cat_n_send ( char* pre, char* msg )
sewardj2a3d28c2002-04-14 13:27:00 +0000195{
sewardj69a72a52002-11-03 13:41:41 +0000196 char buf[1000];
197 int res;
sewardj436e0582002-04-26 14:31:40 +0000198 if (get_pt_trace_level() >= 0) {
sewardj69a72a52002-11-03 13:41:41 +0000199 snprintf(buf, sizeof(buf), "%s%s", pre, msg );
200 buf[sizeof(buf)-1] = '\0';
201 VALGRIND_MAGIC_SEQUENCE(res, 0, /* irrelevant default */
202 VG_USERREQ__LOGMESSAGE, buf, 0, 0, 0);
sewardj45b4b372002-04-16 22:50:32 +0000203 }
sewardj2a3d28c2002-04-14 13:27:00 +0000204}
205
sewardj69a72a52002-11-03 13:41:41 +0000206static void ignored ( char* msg )
207{
208 cat_n_send ( "valgrind's libpthread.so: IGNORED call to: ", msg );
209}
210
211
sewardj30671ff2002-04-21 00:13:57 +0000212static void kludged ( char* msg )
213{
sewardj69a72a52002-11-03 13:41:41 +0000214 cat_n_send ( "valgrind's libpthread.so: KLUDGED call to: ", msg );
sewardj439d45e2002-05-03 20:43:10 +0000215}
216
sewardj69a72a52002-11-03 13:41:41 +0000217
sewardjccef2e62002-05-29 19:26:32 +0000218__attribute__((noreturn))
sewardj3b13f0e2002-04-25 20:17:29 +0000219void vgPlain_unimp ( char* what )
220{
sewardj69a72a52002-11-03 13:41:41 +0000221 cat_n_send (
222 "valgrind's libpthread.so: UNIMPLEMENTED FUNCTION: ", what );
sewardj3b13f0e2002-04-25 20:17:29 +0000223 barf("Please report this bug to me at: jseward@acm.org");
224}
225
sewardje663cb92002-04-12 10:26:32 +0000226
sewardj457cc472002-06-03 23:13:47 +0000227static
sewardj2d94c112002-06-03 01:25:54 +0000228void my_assert_fail ( Char* expr, Char* file, Int line, Char* fn )
229{
sewardj69a72a52002-11-03 13:41:41 +0000230 char buf[1000];
sewardj2d94c112002-06-03 01:25:54 +0000231 static Bool entered = False;
232 if (entered)
233 my_exit(2);
234 entered = True;
sewardj69a72a52002-11-03 13:41:41 +0000235 sprintf(buf, "\n%s: %s:%d (%s): Assertion `%s' failed.\n",
236 "valgrind", file, line, fn, expr );
237 cat_n_send ( "", buf );
238 sprintf(buf, "Please report this bug to me at: %s\n\n",
239 VG_EMAIL_ADDR);
240 cat_n_send ( "", buf );
sewardj2d94c112002-06-03 01:25:54 +0000241 my_exit(1);
242}
243
244#define MY__STRING(__str) #__str
245
246#define my_assert(expr) \
247 ((void) ((expr) ? 0 : \
248 (my_assert_fail (MY__STRING(expr), \
249 __FILE__, __LINE__, \
250 __PRETTY_FUNCTION__), 0)))
251
sewardj00a66b12002-10-12 16:42:35 +0000252static
253void my_free ( void* ptr )
254{
255 int res;
256 VALGRIND_MAGIC_SEQUENCE(res, (-1) /* default */,
257 VG_USERREQ__FREE, ptr, 0, 0, 0);
258 my_assert(res == 0);
259}
260
261
262static
263void* my_malloc ( int nbytes )
264{
265 void* res;
266 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
267 VG_USERREQ__MALLOC, nbytes, 0, 0, 0);
268 my_assert(res != (void*)0);
269 return res;
270}
271
272
sewardj2d94c112002-06-03 01:25:54 +0000273
sewardje663cb92002-04-12 10:26:32 +0000274/* ---------------------------------------------------------------------
275 Pass pthread_ calls to Valgrind's request mechanism.
276 ------------------------------------------------------------------ */
277
sewardjf8f819e2002-04-17 23:21:37 +0000278#include <errno.h>
sewardj5f07b662002-04-23 16:52:51 +0000279#include <sys/time.h> /* gettimeofday */
sewardjf8f819e2002-04-17 23:21:37 +0000280
sewardja1ac5cb2002-05-27 13:00:05 +0000281
sewardjf8f819e2002-04-17 23:21:37 +0000282/* ---------------------------------------------------
sewardj4dced352002-06-04 22:54:20 +0000283 Ummm ..
284 ------------------------------------------------ */
285
286static
287void pthread_error ( const char* msg )
288{
289 int res;
290 VALGRIND_MAGIC_SEQUENCE(res, 0,
291 VG_USERREQ__PTHREAD_ERROR,
292 msg, 0, 0, 0);
293}
294
295
296/* ---------------------------------------------------
sewardj00a66b12002-10-12 16:42:35 +0000297 Here so it can be inlined without complaint.
298 ------------------------------------------------ */
299
300__inline__
301pthread_t pthread_self(void)
302{
303 int tid;
304 ensure_valgrind("pthread_self");
305 VALGRIND_MAGIC_SEQUENCE(tid, 0 /* default */,
306 VG_USERREQ__PTHREAD_GET_THREADID,
307 0, 0, 0, 0);
308 if (tid < 1 || tid >= VG_N_THREADS)
309 barf("pthread_self: invalid ThreadId");
310 return tid;
311}
312
313
314/* ---------------------------------------------------
sewardjf8f819e2002-04-17 23:21:37 +0000315 THREAD ATTRIBUTES
316 ------------------------------------------------ */
317
sewardj6af4b5d2002-04-16 04:40:49 +0000318int pthread_attr_init(pthread_attr_t *attr)
319{
sewardj7989d0c2002-05-28 11:00:01 +0000320 /* Just initialise the fields which we might look at. */
321 attr->__detachstate = PTHREAD_CREATE_JOINABLE;
sewardj111b14c2002-10-20 16:22:57 +0000322 /* Linuxthreads sets this field to the value __getpagesize(), so I
323 guess the following is OK. */
324 attr->__guardsize = VKI_BYTES_PER_PAGE; return 0;
sewardj6af4b5d2002-04-16 04:40:49 +0000325}
326
327int pthread_attr_setdetachstate(pthread_attr_t *attr, int detachstate)
328{
sewardj7989d0c2002-05-28 11:00:01 +0000329 if (detachstate != PTHREAD_CREATE_JOINABLE
sewardj4dced352002-06-04 22:54:20 +0000330 && detachstate != PTHREAD_CREATE_DETACHED) {
331 pthread_error("pthread_attr_setdetachstate: "
332 "detachstate is invalid");
sewardj7989d0c2002-05-28 11:00:01 +0000333 return EINVAL;
sewardj4dced352002-06-04 22:54:20 +0000334 }
sewardj7989d0c2002-05-28 11:00:01 +0000335 attr->__detachstate = detachstate;
sewardj6af4b5d2002-04-16 04:40:49 +0000336 return 0;
337}
338
njn25e49d8e72002-09-23 09:36:25 +0000339int pthread_attr_getdetachstate(const pthread_attr_t *attr, int *detachstate)
340{
341 *detachstate = attr->__detachstate;
342 return 0;
343}
344
sewardj30671ff2002-04-21 00:13:57 +0000345int pthread_attr_setinheritsched(pthread_attr_t *attr, int inherit)
346{
sewardj436e0582002-04-26 14:31:40 +0000347 static int moans = N_MOANS;
348 if (moans-- > 0)
349 ignored("pthread_attr_setinheritsched");
sewardj30671ff2002-04-21 00:13:57 +0000350 return 0;
351}
sewardj6af4b5d2002-04-16 04:40:49 +0000352
sewardj0286dd52002-05-16 20:51:15 +0000353__attribute__((weak))
354int pthread_attr_setstacksize (pthread_attr_t *__attr,
355 size_t __stacksize)
356{
sewardja18e2102002-05-18 10:43:22 +0000357 size_t limit;
sewardj3d7c8d62002-06-04 20:59:16 +0000358 char buf[1024];
sewardj0286dd52002-05-16 20:51:15 +0000359 ensure_valgrind("pthread_attr_setstacksize");
sewardja18e2102002-05-18 10:43:22 +0000360 limit = VG_PTHREAD_STACK_SIZE - VG_AR_CLIENT_STACKBASE_REDZONE_SZB
361 - 1000; /* paranoia */
362 if (__stacksize < limit)
sewardj0286dd52002-05-16 20:51:15 +0000363 return 0;
sewardj3d7c8d62002-06-04 20:59:16 +0000364 snprintf(buf, sizeof(buf), "pthread_attr_setstacksize: "
365 "requested size %d >= VG_PTHREAD_STACK_SIZE\n "
366 "edit vg_include.h and rebuild.", __stacksize);
367 buf[sizeof(buf)-1] = '\0'; /* Make sure it is zero terminated */
368 barf(buf);
sewardj0286dd52002-05-16 20:51:15 +0000369}
370
371
sewardj30671ff2002-04-21 00:13:57 +0000372/* This is completely bogus. */
373int pthread_attr_getschedparam(const pthread_attr_t *attr,
374 struct sched_param *param)
375{
sewardj436e0582002-04-26 14:31:40 +0000376 static int moans = N_MOANS;
377 if (moans-- > 0)
378 kludged("pthread_attr_getschedparam");
sewardj3e909ce2002-06-03 13:27:15 +0000379# ifdef HAVE_SCHED_PRIORITY
sewardj72d58482002-04-24 02:20:20 +0000380 if (param) param->sched_priority = 0; /* who knows */
381# else
sewardj30671ff2002-04-21 00:13:57 +0000382 if (param) param->__sched_priority = 0; /* who knows */
sewardj72d58482002-04-24 02:20:20 +0000383# endif
sewardj30671ff2002-04-21 00:13:57 +0000384 return 0;
385}
386
387int pthread_attr_setschedparam(pthread_attr_t *attr,
388 const struct sched_param *param)
389{
sewardj436e0582002-04-26 14:31:40 +0000390 static int moans = N_MOANS;
391 if (moans-- > 0)
392 ignored("pthread_attr_setschedparam");
sewardj30671ff2002-04-21 00:13:57 +0000393 return 0;
394}
395
396int pthread_attr_destroy(pthread_attr_t *attr)
397{
sewardj436e0582002-04-26 14:31:40 +0000398 static int moans = N_MOANS;
399 if (moans-- > 0)
400 ignored("pthread_attr_destroy");
sewardj30671ff2002-04-21 00:13:57 +0000401 return 0;
402}
sewardjf8f819e2002-04-17 23:21:37 +0000403
sewardj0d844232002-06-02 09:29:31 +0000404/* These are no-ops, as with LinuxThreads. */
405int pthread_attr_setscope ( pthread_attr_t *attr, int scope )
406{
407 ensure_valgrind("pthread_attr_setscope");
408 if (scope == PTHREAD_SCOPE_SYSTEM)
409 return 0;
sewardj4dced352002-06-04 22:54:20 +0000410 pthread_error("pthread_attr_setscope: "
411 "invalid or unsupported scope");
sewardj0d844232002-06-02 09:29:31 +0000412 if (scope == PTHREAD_SCOPE_PROCESS)
413 return ENOTSUP;
414 return EINVAL;
415}
416
417int pthread_attr_getscope ( const pthread_attr_t *attr, int *scope )
418{
419 ensure_valgrind("pthread_attr_setscope");
420 if (scope)
421 *scope = PTHREAD_SCOPE_SYSTEM;
422 return 0;
423}
424
sewardj64039bb2002-06-03 00:58:18 +0000425
426/* Pretty bogus. Avoid if possible. */
427int pthread_getattr_np (pthread_t thread, pthread_attr_t *attr)
428{
429 int detached;
430 size_t limit;
431 ensure_valgrind("pthread_getattr_np");
432 kludged("pthread_getattr_np");
433 limit = VG_PTHREAD_STACK_SIZE - VG_AR_CLIENT_STACKBASE_REDZONE_SZB
434 - 1000; /* paranoia */
435 attr->__detachstate = PTHREAD_CREATE_JOINABLE;
436 attr->__schedpolicy = SCHED_OTHER;
437 attr->__schedparam.sched_priority = 0;
438 attr->__inheritsched = PTHREAD_EXPLICIT_SCHED;
439 attr->__scope = PTHREAD_SCOPE_SYSTEM;
440 attr->__guardsize = VKI_BYTES_PER_PAGE;
441 attr->__stackaddr = NULL;
442 attr->__stackaddr_set = 0;
443 attr->__stacksize = limit;
444 VALGRIND_MAGIC_SEQUENCE(detached, (-1) /* default */,
445 VG_USERREQ__SET_OR_GET_DETACH,
446 2 /* get */, thread, 0, 0);
sewardj2d94c112002-06-03 01:25:54 +0000447 my_assert(detached == 0 || detached == 1);
sewardj64039bb2002-06-03 00:58:18 +0000448 if (detached)
449 attr->__detachstate = PTHREAD_CREATE_DETACHED;
450 return 0;
451}
452
453
454/* Bogus ... */
sewardj111b14c2002-10-20 16:22:57 +0000455__attribute__((weak))
sewardj64039bb2002-06-03 00:58:18 +0000456int pthread_attr_getstackaddr ( const pthread_attr_t * attr,
457 void ** stackaddr )
458{
459 ensure_valgrind("pthread_attr_getstackaddr");
460 kludged("pthread_attr_getstackaddr");
461 if (stackaddr)
462 *stackaddr = NULL;
463 return 0;
464}
465
466/* Not bogus (!) */
sewardj111b14c2002-10-20 16:22:57 +0000467__attribute__((weak))
sewardj64039bb2002-06-03 00:58:18 +0000468int pthread_attr_getstacksize ( const pthread_attr_t * _attr,
469 size_t * __stacksize )
470{
471 size_t limit;
472 ensure_valgrind("pthread_attr_getstacksize");
473 limit = VG_PTHREAD_STACK_SIZE - VG_AR_CLIENT_STACKBASE_REDZONE_SZB
474 - 1000; /* paranoia */
475 if (__stacksize)
476 *__stacksize = limit;
477 return 0;
478}
479
sewardja3be12f2002-06-17 12:19:44 +0000480int pthread_attr_setschedpolicy(pthread_attr_t *attr, int policy)
481{
482 if (policy != SCHED_OTHER && policy != SCHED_FIFO && policy != SCHED_RR)
483 return EINVAL;
484 attr->__schedpolicy = policy;
485 return 0;
486}
487
488int pthread_attr_getschedpolicy(const pthread_attr_t *attr, int *policy)
489{
490 *policy = attr->__schedpolicy;
491 return 0;
492}
493
494
sewardj111b14c2002-10-20 16:22:57 +0000495/* This is completely bogus. We reject all attempts to change it from
496 VKI_BYTES_PER_PAGE. I don't have a clue what it's for so it seems
497 safest to be paranoid. */
498__attribute__((weak))
499int pthread_attr_setguardsize(pthread_attr_t *attr, size_t guardsize)
500{
501 static int moans = N_MOANS;
502
503 if (guardsize == VKI_BYTES_PER_PAGE)
504 return 0;
505
506 if (moans-- > 0)
507 ignored("pthread_attr_setguardsize: ignoring guardsize != 4096");
508
509 return 0;
510}
511
512/* A straight copy of the LinuxThreads code. */
513__attribute__((weak))
514int pthread_attr_getguardsize(const pthread_attr_t *attr, size_t *guardsize)
515{
516 *guardsize = attr->__guardsize;
517 return 0;
518}
519
sewardjab2e1232002-12-26 12:16:11 +0000520/* Again, like LinuxThreads. */
521
522static int concurrency_current_level = 0;
523
sewardjb34e4db2002-12-08 23:51:32 +0000524__attribute__((weak))
525int pthread_setconcurrency(int new_level)
526{
527 if (new_level < 0)
528 return EINVAL;
sewardjab2e1232002-12-26 12:16:11 +0000529 else {
530 concurrency_current_level = new_level;
sewardjb34e4db2002-12-08 23:51:32 +0000531 return 0;
sewardjab2e1232002-12-26 12:16:11 +0000532 }
sewardjb34e4db2002-12-08 23:51:32 +0000533}
534
sewardjab2e1232002-12-26 12:16:11 +0000535__attribute__((weak))
536int pthread_getconcurrency(void)
537{
538 return concurrency_current_level;
539}
540
541
sewardj111b14c2002-10-20 16:22:57 +0000542
sewardj20917d82002-05-28 01:36:45 +0000543/* ---------------------------------------------------
544 Helper functions for running a thread
545 and for clearing up afterwards.
546 ------------------------------------------------ */
547
548/* All exiting threads eventually pass through here, bearing the
549 return value, or PTHREAD_CANCELED, in ret_val. */
550static
551__attribute__((noreturn))
552void thread_exit_wrapper ( void* ret_val )
553{
sewardj870497a2002-05-29 01:06:47 +0000554 int detached, res;
555 CleanupEntry cu;
556 pthread_key_t key;
sewardj00a66b12002-10-12 16:42:35 +0000557 void** specifics_ptr;
sewardj870497a2002-05-29 01:06:47 +0000558
sewardj20917d82002-05-28 01:36:45 +0000559 /* Run this thread's cleanup handlers. */
sewardj8ad94e12002-05-29 00:10:20 +0000560 while (1) {
561 VALGRIND_MAGIC_SEQUENCE(res, (-1) /* default */,
562 VG_USERREQ__CLEANUP_POP,
563 &cu, 0, 0, 0);
564 if (res == -1) break; /* stack empty */
sewardj2d94c112002-06-03 01:25:54 +0000565 my_assert(res == 0);
sewardj8ad94e12002-05-29 00:10:20 +0000566 if (0) printf("running exit cleanup handler");
567 cu.fn ( cu.arg );
568 }
569
sewardj870497a2002-05-29 01:06:47 +0000570 /* Run this thread's key finalizers. Really this should be run
571 PTHREAD_DESTRUCTOR_ITERATIONS times. */
572 for (key = 0; key < VG_N_THREAD_KEYS; key++) {
573 VALGRIND_MAGIC_SEQUENCE(res, (-2) /* default */,
574 VG_USERREQ__GET_KEY_D_AND_S,
575 key, &cu, 0, 0 );
576 if (res == 0) {
577 /* valid key */
578 if (cu.fn && cu.arg)
579 cu.fn /* destructor for key */
580 ( cu.arg /* specific for key for this thread */ );
581 continue;
582 }
sewardj2d94c112002-06-03 01:25:54 +0000583 my_assert(res == -1);
sewardj870497a2002-05-29 01:06:47 +0000584 }
sewardj20917d82002-05-28 01:36:45 +0000585
sewardj00a66b12002-10-12 16:42:35 +0000586 /* Free up my specifics space, if any. */
587 VALGRIND_MAGIC_SEQUENCE(specifics_ptr, 3 /* default */,
588 VG_USERREQ__PTHREAD_GETSPECIFIC_PTR,
589 pthread_self(), 0, 0, 0);
590 my_assert(specifics_ptr != (void**)3);
591 my_assert(specifics_ptr != (void**)1); /* 1 means invalid thread */
592 if (specifics_ptr != NULL)
593 my_free(specifics_ptr);
594
sewardj20917d82002-05-28 01:36:45 +0000595 /* Decide on my final disposition. */
596 VALGRIND_MAGIC_SEQUENCE(detached, (-1) /* default */,
597 VG_USERREQ__SET_OR_GET_DETACH,
sewardj7989d0c2002-05-28 11:00:01 +0000598 2 /* get */, pthread_self(), 0, 0);
sewardj2d94c112002-06-03 01:25:54 +0000599 my_assert(detached == 0 || detached == 1);
sewardj20917d82002-05-28 01:36:45 +0000600
601 if (detached) {
602 /* Detached; I just quit right now. */
603 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
604 VG_USERREQ__QUIT, 0, 0, 0, 0);
605 } else {
606 /* Not detached; so I wait for a joiner. */
607 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
608 VG_USERREQ__WAIT_JOINER, ret_val, 0, 0, 0);
609 }
610 /* NOTREACHED */
611 barf("thread_exit_wrapper: still alive?!");
612}
613
614
615/* This function is a wrapper function for running a thread. It runs
616 the root function specified in pthread_create, and then, should the
617 root function return a value, it arranges to run the thread's
618 cleanup handlers and exit correctly. */
619
sewardj728a5272002-06-20 10:25:37 +0000620/* Struct used to convey info from pthread_create to thread_wrapper.
621 Must be careful not to pass to the child thread any pointers to
622 objects which might be on the parent's stack. */
sewardj20917d82002-05-28 01:36:45 +0000623typedef
624 struct {
sewardj728a5272002-06-20 10:25:37 +0000625 int attr__detachstate;
sewardj20917d82002-05-28 01:36:45 +0000626 void* (*root_fn) ( void* );
627 void* arg;
628 }
629 NewThreadInfo;
630
631
632/* This is passed to the VG_USERREQ__APPLY_IN_NEW_THREAD and so must
633 not return. Note that this runs in the new thread, not the
634 parent. */
635static
636__attribute__((noreturn))
637void thread_wrapper ( NewThreadInfo* info )
638{
sewardj728a5272002-06-20 10:25:37 +0000639 int attr__detachstate;
sewardj20917d82002-05-28 01:36:45 +0000640 void* (*root_fn) ( void* );
641 void* arg;
642 void* ret_val;
643
sewardj728a5272002-06-20 10:25:37 +0000644 attr__detachstate = info->attr__detachstate;
645 root_fn = info->root_fn;
646 arg = info->arg;
sewardj20917d82002-05-28 01:36:45 +0000647
sewardj20917d82002-05-28 01:36:45 +0000648 /* Free up the arg block that pthread_create malloced. */
sewardj00a66b12002-10-12 16:42:35 +0000649 my_free(info);
sewardj20917d82002-05-28 01:36:45 +0000650
sewardj7989d0c2002-05-28 11:00:01 +0000651 /* Minimally observe the attributes supplied. */
sewardj728a5272002-06-20 10:25:37 +0000652 if (attr__detachstate != PTHREAD_CREATE_DETACHED
653 && attr__detachstate != PTHREAD_CREATE_JOINABLE)
654 pthread_error("thread_wrapper: invalid attr->__detachstate");
655 if (attr__detachstate == PTHREAD_CREATE_DETACHED)
656 pthread_detach(pthread_self());
sewardj7989d0c2002-05-28 11:00:01 +0000657
sewardj00a66b12002-10-12 16:42:35 +0000658# ifdef GLIBC_2_3
659 /* Set this thread's locale to the global (default) locale. A hack
660 in support of glibc-2.3. This does the biz for the all new
661 threads; the root thread is done with a horrible hack in
662 init_libc_tsd_keys() below.
663 */
664 __uselocale(LC_GLOBAL_LOCALE);
665# endif
666
sewardj20917d82002-05-28 01:36:45 +0000667 /* The root function might not return. But if it does we simply
668 move along to thread_exit_wrapper. All other ways out for the
669 thread (cancellation, or calling pthread_exit) lead there
670 too. */
671 ret_val = root_fn(arg);
672 thread_exit_wrapper(ret_val);
673 /* NOTREACHED */
674}
675
676
sewardjf8f819e2002-04-17 23:21:37 +0000677/* ---------------------------------------------------
678 THREADs
679 ------------------------------------------------ */
680
sewardjff42d1d2002-05-22 13:17:31 +0000681__attribute__((weak))
682int pthread_yield ( void )
683{
684 int res;
685 ensure_valgrind("pthread_yield");
686 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
687 VG_USERREQ__PTHREAD_YIELD, 0, 0, 0, 0);
688 return 0;
689}
690
691
sewardj6072c362002-04-19 14:40:57 +0000692int pthread_equal(pthread_t thread1, pthread_t thread2)
693{
694 return thread1 == thread2 ? 1 : 0;
695}
696
697
sewardj20917d82002-05-28 01:36:45 +0000698/* Bundle up the args into a malloc'd block and create a new thread
699 consisting of thread_wrapper() applied to said malloc'd block. */
sewardje663cb92002-04-12 10:26:32 +0000700int
sewardj1462c8b2002-07-24 09:41:52 +0000701pthread_create (pthread_t *__restrict __thredd,
sewardje663cb92002-04-12 10:26:32 +0000702 __const pthread_attr_t *__restrict __attr,
703 void *(*__start_routine) (void *),
704 void *__restrict __arg)
705{
sewardj20917d82002-05-28 01:36:45 +0000706 int tid_child;
707 NewThreadInfo* info;
sewardje663cb92002-04-12 10:26:32 +0000708
sewardj20917d82002-05-28 01:36:45 +0000709 ensure_valgrind("pthread_create");
710
sewardj00a66b12002-10-12 16:42:35 +0000711 /* make sure the tsd keys, and hence locale info, are initialised
712 before we get into complications making new threads. */
713 init_libc_tsd_keys();
714
sewardj20917d82002-05-28 01:36:45 +0000715 /* Allocate space for the arg block. thread_wrapper will free
716 it. */
sewardj00a66b12002-10-12 16:42:35 +0000717 info = my_malloc(sizeof(NewThreadInfo));
sewardj2d94c112002-06-03 01:25:54 +0000718 my_assert(info != NULL);
sewardj20917d82002-05-28 01:36:45 +0000719
sewardj728a5272002-06-20 10:25:37 +0000720 if (__attr)
721 info->attr__detachstate = __attr->__detachstate;
722 else
723 info->attr__detachstate = PTHREAD_CREATE_JOINABLE;
724
sewardj20917d82002-05-28 01:36:45 +0000725 info->root_fn = __start_routine;
726 info->arg = __arg;
727 VALGRIND_MAGIC_SEQUENCE(tid_child, VG_INVALID_THREADID /* default */,
728 VG_USERREQ__APPLY_IN_NEW_THREAD,
729 &thread_wrapper, info, 0, 0);
sewardj2d94c112002-06-03 01:25:54 +0000730 my_assert(tid_child != VG_INVALID_THREADID);
sewardj20917d82002-05-28 01:36:45 +0000731
sewardj1462c8b2002-07-24 09:41:52 +0000732 if (__thredd)
733 *__thredd = tid_child;
sewardj20917d82002-05-28 01:36:45 +0000734 return 0; /* success */
735}
sewardje663cb92002-04-12 10:26:32 +0000736
737
738int
739pthread_join (pthread_t __th, void **__thread_return)
740{
741 int res;
742 ensure_valgrind("pthread_join");
743 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
744 VG_USERREQ__PTHREAD_JOIN,
745 __th, __thread_return, 0, 0);
746 return res;
747}
748
749
sewardj3b5d8862002-04-20 13:53:23 +0000750void pthread_exit(void *retval)
751{
sewardj3b5d8862002-04-20 13:53:23 +0000752 ensure_valgrind("pthread_exit");
sewardj20917d82002-05-28 01:36:45 +0000753 /* Simple! */
754 thread_exit_wrapper(retval);
sewardj3b5d8862002-04-20 13:53:23 +0000755}
756
sewardje663cb92002-04-12 10:26:32 +0000757
sewardj853f55d2002-04-26 00:27:53 +0000758int pthread_detach(pthread_t th)
759{
sewardj20917d82002-05-28 01:36:45 +0000760 int res;
761 ensure_valgrind("pthread_detach");
sewardj7989d0c2002-05-28 11:00:01 +0000762 /* First we enquire as to the current detach state. */
763 VALGRIND_MAGIC_SEQUENCE(res, (-2) /* default */,
sewardj20917d82002-05-28 01:36:45 +0000764 VG_USERREQ__SET_OR_GET_DETACH,
sewardj7989d0c2002-05-28 11:00:01 +0000765 2 /* get */, th, 0, 0);
sewardj4dced352002-06-04 22:54:20 +0000766 if (res == -1) {
767 /* not found */
768 pthread_error("pthread_detach: "
769 "invalid target thread");
sewardj7989d0c2002-05-28 11:00:01 +0000770 return ESRCH;
sewardj4dced352002-06-04 22:54:20 +0000771 }
772 if (res == 1) {
773 /* already detached */
774 pthread_error("pthread_detach: "
775 "target thread is already detached");
sewardj7989d0c2002-05-28 11:00:01 +0000776 return EINVAL;
sewardj4dced352002-06-04 22:54:20 +0000777 }
sewardj7989d0c2002-05-28 11:00:01 +0000778 if (res == 0) {
779 VALGRIND_MAGIC_SEQUENCE(res, (-2) /* default */,
780 VG_USERREQ__SET_OR_GET_DETACH,
781 1 /* set */, th, 0, 0);
sewardj2d94c112002-06-03 01:25:54 +0000782 my_assert(res == 0);
sewardj7989d0c2002-05-28 11:00:01 +0000783 return 0;
784 }
785 barf("pthread_detach");
sewardj853f55d2002-04-26 00:27:53 +0000786}
787
788
sewardjf8f819e2002-04-17 23:21:37 +0000789/* ---------------------------------------------------
sewardj8ad94e12002-05-29 00:10:20 +0000790 CLEANUP STACKS
791 ------------------------------------------------ */
792
793void _pthread_cleanup_push (struct _pthread_cleanup_buffer *__buffer,
794 void (*__routine) (void *),
795 void *__arg)
796{
797 int res;
798 CleanupEntry cu;
799 ensure_valgrind("_pthread_cleanup_push");
800 cu.fn = __routine;
801 cu.arg = __arg;
802 VALGRIND_MAGIC_SEQUENCE(res, (-1) /* default */,
803 VG_USERREQ__CLEANUP_PUSH,
804 &cu, 0, 0, 0);
sewardj2d94c112002-06-03 01:25:54 +0000805 my_assert(res == 0);
sewardj8ad94e12002-05-29 00:10:20 +0000806}
807
808
809void _pthread_cleanup_push_defer (struct _pthread_cleanup_buffer *__buffer,
810 void (*__routine) (void *),
811 void *__arg)
812{
813 /* As _pthread_cleanup_push, but first save the thread's original
814 cancellation type in __buffer and set it to Deferred. */
815 int orig_ctype;
816 ensure_valgrind("_pthread_cleanup_push_defer");
817 /* Set to Deferred, and put the old cancellation type in res. */
sewardj2d94c112002-06-03 01:25:54 +0000818 my_assert(-1 != PTHREAD_CANCEL_DEFERRED);
819 my_assert(-1 != PTHREAD_CANCEL_ASYNCHRONOUS);
820 my_assert(sizeof(struct _pthread_cleanup_buffer) >= sizeof(int));
sewardj8ad94e12002-05-29 00:10:20 +0000821 VALGRIND_MAGIC_SEQUENCE(orig_ctype, (-1) /* default */,
822 VG_USERREQ__SET_CANCELTYPE,
823 PTHREAD_CANCEL_DEFERRED, 0, 0, 0);
sewardj2d94c112002-06-03 01:25:54 +0000824 my_assert(orig_ctype != -1);
sewardj8ad94e12002-05-29 00:10:20 +0000825 *((int*)(__buffer)) = orig_ctype;
826 /* Now push the cleanup. */
827 _pthread_cleanup_push(NULL, __routine, __arg);
828}
829
830
831void _pthread_cleanup_pop (struct _pthread_cleanup_buffer *__buffer,
832 int __execute)
833{
834 int res;
835 CleanupEntry cu;
836 ensure_valgrind("_pthread_cleanup_push");
837 cu.fn = cu.arg = NULL; /* paranoia */
838 VALGRIND_MAGIC_SEQUENCE(res, (-1) /* default */,
839 VG_USERREQ__CLEANUP_POP,
840 &cu, 0, 0, 0);
841 if (res == 0) {
842 /* pop succeeded */
843 if (__execute) {
844 cu.fn ( cu.arg );
845 }
846 return;
847 }
848 if (res == -1) {
849 /* stack underflow */
850 return;
851 }
852 barf("_pthread_cleanup_pop");
853}
854
855
856void _pthread_cleanup_pop_restore (struct _pthread_cleanup_buffer *__buffer,
857 int __execute)
858{
859 int orig_ctype, fake_ctype;
860 /* As _pthread_cleanup_pop, but after popping/running the handler,
861 restore the thread's original cancellation type from the first
862 word of __buffer. */
863 _pthread_cleanup_pop(NULL, __execute);
864 orig_ctype = *((int*)(__buffer));
sewardj2d94c112002-06-03 01:25:54 +0000865 my_assert(orig_ctype == PTHREAD_CANCEL_DEFERRED
sewardj8ad94e12002-05-29 00:10:20 +0000866 || orig_ctype == PTHREAD_CANCEL_ASYNCHRONOUS);
sewardj2d94c112002-06-03 01:25:54 +0000867 my_assert(-1 != PTHREAD_CANCEL_DEFERRED);
868 my_assert(-1 != PTHREAD_CANCEL_ASYNCHRONOUS);
869 my_assert(sizeof(struct _pthread_cleanup_buffer) >= sizeof(int));
sewardj8ad94e12002-05-29 00:10:20 +0000870 VALGRIND_MAGIC_SEQUENCE(fake_ctype, (-1) /* default */,
871 VG_USERREQ__SET_CANCELTYPE,
872 orig_ctype, 0, 0, 0);
sewardj2d94c112002-06-03 01:25:54 +0000873 my_assert(fake_ctype == PTHREAD_CANCEL_DEFERRED);
sewardj8ad94e12002-05-29 00:10:20 +0000874}
875
876
877/* ---------------------------------------------------
sewardjf8f819e2002-04-17 23:21:37 +0000878 MUTEX ATTRIBUTES
879 ------------------------------------------------ */
880
sewardj5905fae2002-04-26 13:25:00 +0000881int __pthread_mutexattr_init(pthread_mutexattr_t *attr)
sewardje663cb92002-04-12 10:26:32 +0000882{
sewardjf8f819e2002-04-17 23:21:37 +0000883 attr->__mutexkind = PTHREAD_MUTEX_ERRORCHECK_NP;
sewardj8937c812002-04-12 20:12:20 +0000884 return 0;
sewardje663cb92002-04-12 10:26:32 +0000885}
886
sewardj5905fae2002-04-26 13:25:00 +0000887int __pthread_mutexattr_settype(pthread_mutexattr_t *attr, int type)
sewardjf8f819e2002-04-17 23:21:37 +0000888{
889 switch (type) {
sewardj3b13f0e2002-04-25 20:17:29 +0000890# ifndef GLIBC_2_1
sewardjf8f819e2002-04-17 23:21:37 +0000891 case PTHREAD_MUTEX_TIMED_NP:
sewardj2a1dcce2002-04-22 12:45:25 +0000892 case PTHREAD_MUTEX_ADAPTIVE_NP:
sewardj3b13f0e2002-04-25 20:17:29 +0000893# endif
sewardja1679dd2002-05-10 22:31:40 +0000894# ifdef GLIBC_2_1
sewardj68b2dd92002-05-10 21:03:56 +0000895 case PTHREAD_MUTEX_FAST_NP:
sewardja1679dd2002-05-10 22:31:40 +0000896# endif
sewardjf8f819e2002-04-17 23:21:37 +0000897 case PTHREAD_MUTEX_RECURSIVE_NP:
898 case PTHREAD_MUTEX_ERRORCHECK_NP:
sewardjf8f819e2002-04-17 23:21:37 +0000899 attr->__mutexkind = type;
900 return 0;
901 default:
sewardj4dced352002-06-04 22:54:20 +0000902 pthread_error("pthread_mutexattr_settype: "
903 "invalid type");
sewardjf8f819e2002-04-17 23:21:37 +0000904 return EINVAL;
905 }
906}
907
sewardj5905fae2002-04-26 13:25:00 +0000908int __pthread_mutexattr_destroy(pthread_mutexattr_t *attr)
sewardjf8f819e2002-04-17 23:21:37 +0000909{
910 return 0;
911}
912
913
914/* ---------------------------------------------------
915 MUTEXes
916 ------------------------------------------------ */
917
sewardj5905fae2002-04-26 13:25:00 +0000918int __pthread_mutex_init(pthread_mutex_t *mutex,
919 const pthread_mutexattr_t *mutexattr)
sewardje663cb92002-04-12 10:26:32 +0000920{
sewardj604ec3c2002-04-18 22:38:41 +0000921 mutex->__m_count = 0;
922 mutex->__m_owner = (_pthread_descr)VG_INVALID_THREADID;
923 mutex->__m_kind = PTHREAD_MUTEX_ERRORCHECK_NP;
924 if (mutexattr)
925 mutex->__m_kind = mutexattr->__mutexkind;
926 return 0;
sewardje663cb92002-04-12 10:26:32 +0000927}
928
sewardj439d45e2002-05-03 20:43:10 +0000929
sewardj5905fae2002-04-26 13:25:00 +0000930int __pthread_mutex_lock(pthread_mutex_t *mutex)
sewardje663cb92002-04-12 10:26:32 +0000931{
932 int res;
sewardjd8acdf22002-11-13 21:57:52 +0000933
sewardj439d45e2002-05-03 20:43:10 +0000934 if (RUNNING_ON_VALGRIND) {
sewardje663cb92002-04-12 10:26:32 +0000935 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
936 VG_USERREQ__PTHREAD_MUTEX_LOCK,
937 mutex, 0, 0, 0);
938 return res;
sewardj439d45e2002-05-03 20:43:10 +0000939 } else {
sewardjd8acdf22002-11-13 21:57:52 +0000940 /* Play at locking */
941 if (0)
942 kludged("prehistoric lock");
943 mutex->__m_owner = (_pthread_descr)1;
944 mutex->__m_count = 1;
945 mutex->__m_kind |= VG_PTHREAD_PREHISTORY;
sewardj439d45e2002-05-03 20:43:10 +0000946 return 0; /* success */
sewardje663cb92002-04-12 10:26:32 +0000947 }
948}
949
sewardj439d45e2002-05-03 20:43:10 +0000950
sewardj5905fae2002-04-26 13:25:00 +0000951int __pthread_mutex_trylock(pthread_mutex_t *mutex)
sewardj30671ff2002-04-21 00:13:57 +0000952{
953 int res;
sewardjd8acdf22002-11-13 21:57:52 +0000954
sewardj439d45e2002-05-03 20:43:10 +0000955 if (RUNNING_ON_VALGRIND) {
sewardj30671ff2002-04-21 00:13:57 +0000956 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
957 VG_USERREQ__PTHREAD_MUTEX_TRYLOCK,
958 mutex, 0, 0, 0);
959 return res;
sewardj439d45e2002-05-03 20:43:10 +0000960 } else {
sewardjd8acdf22002-11-13 21:57:52 +0000961 /* Play at locking */
962 if (0)
963 kludged("prehistoric trylock");
964 mutex->__m_owner = (_pthread_descr)1;
965 mutex->__m_count = 1;
966 mutex->__m_kind |= VG_PTHREAD_PREHISTORY;
967 return 0; /* success */
sewardj30671ff2002-04-21 00:13:57 +0000968 }
969}
970
sewardj439d45e2002-05-03 20:43:10 +0000971
sewardj5905fae2002-04-26 13:25:00 +0000972int __pthread_mutex_unlock(pthread_mutex_t *mutex)
sewardje663cb92002-04-12 10:26:32 +0000973{
974 int res;
sewardjd8acdf22002-11-13 21:57:52 +0000975
sewardj439d45e2002-05-03 20:43:10 +0000976 if (RUNNING_ON_VALGRIND) {
sewardje663cb92002-04-12 10:26:32 +0000977 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
978 VG_USERREQ__PTHREAD_MUTEX_UNLOCK,
979 mutex, 0, 0, 0);
980 return res;
sewardj439d45e2002-05-03 20:43:10 +0000981 } else {
sewardjd8acdf22002-11-13 21:57:52 +0000982 /* Play at locking */
983 if (0)
984 kludged("prehistoric unlock");
985 mutex->__m_owner = 0;
986 mutex->__m_count = 0;
987 mutex->__m_kind &= ~VG_PTHREAD_PREHISTORY;
988 return 0; /* success */
sewardje663cb92002-04-12 10:26:32 +0000989 }
990}
991
sewardj439d45e2002-05-03 20:43:10 +0000992
sewardj5905fae2002-04-26 13:25:00 +0000993int __pthread_mutex_destroy(pthread_mutex_t *mutex)
sewardje663cb92002-04-12 10:26:32 +0000994{
sewardj604ec3c2002-04-18 22:38:41 +0000995 /* Valgrind doesn't hold any resources on behalf of the mutex, so no
996 need to involve it. */
sewardj4dced352002-06-04 22:54:20 +0000997 if (mutex->__m_count > 0) {
sewardjd8acdf22002-11-13 21:57:52 +0000998 /* Oh, the horror. glibc's internal use of pthreads "knows"
999 that destroying a lock does an implicit unlock. Make it
1000 explicit. */
1001 __pthread_mutex_unlock(mutex);
1002 pthread_error("pthread_mutex_destroy: "
1003 "mutex is still in use");
1004 return EBUSY;
sewardj4dced352002-06-04 22:54:20 +00001005 }
1006 mutex->__m_count = 0;
1007 mutex->__m_owner = (_pthread_descr)VG_INVALID_THREADID;
1008 mutex->__m_kind = PTHREAD_MUTEX_ERRORCHECK_NP;
1009 return 0;
sewardje663cb92002-04-12 10:26:32 +00001010}
1011
1012
sewardjf8f819e2002-04-17 23:21:37 +00001013/* ---------------------------------------------------
sewardj6072c362002-04-19 14:40:57 +00001014 CONDITION VARIABLES
1015 ------------------------------------------------ */
1016
1017/* LinuxThreads supports no attributes for conditions. Hence ... */
1018
1019int pthread_condattr_init(pthread_condattr_t *attr)
1020{
1021 return 0;
1022}
1023
sewardj0738a592002-04-20 13:59:33 +00001024int pthread_condattr_destroy(pthread_condattr_t *attr)
1025{
1026 return 0;
1027}
sewardj6072c362002-04-19 14:40:57 +00001028
1029int pthread_cond_init( pthread_cond_t *cond,
1030 const pthread_condattr_t *cond_attr)
1031{
1032 cond->__c_waiting = (_pthread_descr)VG_INVALID_THREADID;
1033 return 0;
1034}
1035
sewardjf854f472002-04-21 12:19:41 +00001036int pthread_cond_destroy(pthread_cond_t *cond)
1037{
1038 /* should check that no threads are waiting on this CV */
sewardj436e0582002-04-26 14:31:40 +00001039 static int moans = N_MOANS;
1040 if (moans-- > 0)
1041 kludged("pthread_cond_destroy");
sewardjf854f472002-04-21 12:19:41 +00001042 return 0;
1043}
sewardj6072c362002-04-19 14:40:57 +00001044
1045/* ---------------------------------------------------
1046 SCHEDULING
1047 ------------------------------------------------ */
1048
1049/* This is completely bogus. */
1050int pthread_getschedparam(pthread_t target_thread,
1051 int *policy,
1052 struct sched_param *param)
1053{
sewardj436e0582002-04-26 14:31:40 +00001054 static int moans = N_MOANS;
1055 if (moans-- > 0)
1056 kludged("pthread_getschedparam");
sewardj6072c362002-04-19 14:40:57 +00001057 if (policy) *policy = SCHED_OTHER;
sewardj3e909ce2002-06-03 13:27:15 +00001058# ifdef HAVE_SCHED_PRIORITY
sewardj2a1dcce2002-04-22 12:45:25 +00001059 if (param) param->sched_priority = 0; /* who knows */
1060# else
sewardj6072c362002-04-19 14:40:57 +00001061 if (param) param->__sched_priority = 0; /* who knows */
sewardj2a1dcce2002-04-22 12:45:25 +00001062# endif
sewardj6072c362002-04-19 14:40:57 +00001063 return 0;
1064}
1065
1066int pthread_setschedparam(pthread_t target_thread,
1067 int policy,
1068 const struct sched_param *param)
1069{
sewardj436e0582002-04-26 14:31:40 +00001070 static int moans = N_MOANS;
1071 if (moans-- > 0)
1072 ignored("pthread_setschedparam");
sewardj6072c362002-04-19 14:40:57 +00001073 return 0;
1074}
1075
sewardj3b5d8862002-04-20 13:53:23 +00001076int pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex)
1077{
1078 int res;
1079 ensure_valgrind("pthread_cond_wait");
1080 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
1081 VG_USERREQ__PTHREAD_COND_WAIT,
1082 cond, mutex, 0, 0);
1083 return res;
1084}
1085
sewardj5f07b662002-04-23 16:52:51 +00001086int pthread_cond_timedwait ( pthread_cond_t *cond,
1087 pthread_mutex_t *mutex,
1088 const struct timespec *abstime )
1089{
1090 int res;
1091 unsigned int ms_now, ms_end;
1092 struct timeval timeval_now;
1093 unsigned long long int ull_ms_now_after_1970;
1094 unsigned long long int ull_ms_end_after_1970;
1095
1096 ensure_valgrind("pthread_cond_timedwait");
1097 VALGRIND_MAGIC_SEQUENCE(ms_now, 0xFFFFFFFF /* default */,
1098 VG_USERREQ__READ_MILLISECOND_TIMER,
1099 0, 0, 0, 0);
sewardj2d94c112002-06-03 01:25:54 +00001100 my_assert(ms_now != 0xFFFFFFFF);
sewardj5f07b662002-04-23 16:52:51 +00001101 res = gettimeofday(&timeval_now, NULL);
sewardj2d94c112002-06-03 01:25:54 +00001102 my_assert(res == 0);
sewardj5f07b662002-04-23 16:52:51 +00001103
1104 ull_ms_now_after_1970
1105 = 1000ULL * ((unsigned long long int)(timeval_now.tv_sec))
1106 + ((unsigned long long int)(timeval_now.tv_usec / 1000000));
1107 ull_ms_end_after_1970
1108 = 1000ULL * ((unsigned long long int)(abstime->tv_sec))
1109 + ((unsigned long long int)(abstime->tv_nsec / 1000000));
sewardjd8e919e2002-05-29 20:13:53 +00001110 if (ull_ms_end_after_1970 < ull_ms_now_after_1970)
1111 ull_ms_end_after_1970 = ull_ms_now_after_1970;
sewardj5f07b662002-04-23 16:52:51 +00001112 ms_end
1113 = ms_now + (unsigned int)(ull_ms_end_after_1970 - ull_ms_now_after_1970);
1114 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
1115 VG_USERREQ__PTHREAD_COND_TIMEDWAIT,
1116 cond, mutex, ms_end, 0);
1117 return res;
1118}
1119
1120
sewardj3b5d8862002-04-20 13:53:23 +00001121int pthread_cond_signal(pthread_cond_t *cond)
1122{
1123 int res;
1124 ensure_valgrind("pthread_cond_signal");
1125 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
1126 VG_USERREQ__PTHREAD_COND_SIGNAL,
1127 cond, 0, 0, 0);
1128 return res;
1129}
1130
1131int pthread_cond_broadcast(pthread_cond_t *cond)
1132{
1133 int res;
1134 ensure_valgrind("pthread_cond_broadcast");
1135 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
1136 VG_USERREQ__PTHREAD_COND_BROADCAST,
1137 cond, 0, 0, 0);
1138 return res;
1139}
1140
sewardj6072c362002-04-19 14:40:57 +00001141
1142/* ---------------------------------------------------
sewardjf8f819e2002-04-17 23:21:37 +00001143 CANCELLATION
1144 ------------------------------------------------ */
1145
sewardj853f55d2002-04-26 00:27:53 +00001146int pthread_setcancelstate(int state, int *oldstate)
1147{
sewardj20917d82002-05-28 01:36:45 +00001148 int res;
1149 ensure_valgrind("pthread_setcancelstate");
1150 if (state != PTHREAD_CANCEL_ENABLE
sewardj4dced352002-06-04 22:54:20 +00001151 && state != PTHREAD_CANCEL_DISABLE) {
1152 pthread_error("pthread_setcancelstate: "
1153 "invalid state");
sewardj20917d82002-05-28 01:36:45 +00001154 return EINVAL;
sewardj4dced352002-06-04 22:54:20 +00001155 }
sewardj2d94c112002-06-03 01:25:54 +00001156 my_assert(-1 != PTHREAD_CANCEL_ENABLE);
1157 my_assert(-1 != PTHREAD_CANCEL_DISABLE);
sewardj20917d82002-05-28 01:36:45 +00001158 VALGRIND_MAGIC_SEQUENCE(res, (-1) /* default */,
1159 VG_USERREQ__SET_CANCELSTATE,
1160 state, 0, 0, 0);
sewardj2d94c112002-06-03 01:25:54 +00001161 my_assert(res != -1);
sewardj20917d82002-05-28 01:36:45 +00001162 if (oldstate)
1163 *oldstate = res;
sewardj853f55d2002-04-26 00:27:53 +00001164 return 0;
1165}
1166
sewardje663cb92002-04-12 10:26:32 +00001167int pthread_setcanceltype(int type, int *oldtype)
1168{
sewardj20917d82002-05-28 01:36:45 +00001169 int res;
1170 ensure_valgrind("pthread_setcanceltype");
1171 if (type != PTHREAD_CANCEL_DEFERRED
sewardj4dced352002-06-04 22:54:20 +00001172 && type != PTHREAD_CANCEL_ASYNCHRONOUS) {
1173 pthread_error("pthread_setcanceltype: "
1174 "invalid type");
sewardj20917d82002-05-28 01:36:45 +00001175 return EINVAL;
sewardj4dced352002-06-04 22:54:20 +00001176 }
sewardj2d94c112002-06-03 01:25:54 +00001177 my_assert(-1 != PTHREAD_CANCEL_DEFERRED);
1178 my_assert(-1 != PTHREAD_CANCEL_ASYNCHRONOUS);
sewardj20917d82002-05-28 01:36:45 +00001179 VALGRIND_MAGIC_SEQUENCE(res, (-1) /* default */,
1180 VG_USERREQ__SET_CANCELTYPE,
1181 type, 0, 0, 0);
sewardj2d94c112002-06-03 01:25:54 +00001182 my_assert(res != -1);
sewardj20917d82002-05-28 01:36:45 +00001183 if (oldtype)
1184 *oldtype = res;
sewardje663cb92002-04-12 10:26:32 +00001185 return 0;
1186}
1187
sewardje663cb92002-04-12 10:26:32 +00001188int pthread_cancel(pthread_t thread)
1189{
1190 int res;
1191 ensure_valgrind("pthread_cancel");
sewardj20917d82002-05-28 01:36:45 +00001192 VALGRIND_MAGIC_SEQUENCE(res, (-1) /* default */,
1193 VG_USERREQ__SET_CANCELPEND,
1194 thread, &thread_exit_wrapper, 0, 0);
sewardj2d94c112002-06-03 01:25:54 +00001195 my_assert(res != -1);
sewardje663cb92002-04-12 10:26:32 +00001196 return res;
1197}
1198
sewardjd140e442002-05-29 01:21:19 +00001199static __inline__
1200void __my_pthread_testcancel(void)
sewardj853f55d2002-04-26 00:27:53 +00001201{
sewardj20917d82002-05-28 01:36:45 +00001202 int res;
njn25e49d8e72002-09-23 09:36:25 +00001203 ensure_valgrind("__my_pthread_testcancel");
sewardj20917d82002-05-28 01:36:45 +00001204 VALGRIND_MAGIC_SEQUENCE(res, (-1) /* default */,
1205 VG_USERREQ__TESTCANCEL,
1206 0, 0, 0, 0);
sewardj2d94c112002-06-03 01:25:54 +00001207 my_assert(res == 0);
sewardj853f55d2002-04-26 00:27:53 +00001208}
1209
sewardjd140e442002-05-29 01:21:19 +00001210void pthread_testcancel ( void )
1211{
1212 __my_pthread_testcancel();
1213}
1214
sewardj20917d82002-05-28 01:36:45 +00001215
sewardjef037c72002-05-30 00:40:03 +00001216/* Not really sure what this is for. I suspect for doing the POSIX
1217 requirements for fork() and exec(). We do this internally anyway
1218 whenever those syscalls are observed, so this could be superfluous,
1219 but hey ...
1220*/
sewardj853f55d2002-04-26 00:27:53 +00001221void __pthread_kill_other_threads_np ( void )
1222{
sewardjef037c72002-05-30 00:40:03 +00001223 int res;
1224 ensure_valgrind("__pthread_kill_other_threads_np");
1225 VALGRIND_MAGIC_SEQUENCE(res, (-1) /* default */,
1226 VG_USERREQ__NUKE_OTHER_THREADS,
1227 0, 0, 0, 0);
sewardj2d94c112002-06-03 01:25:54 +00001228 my_assert(res == 0);
sewardj853f55d2002-04-26 00:27:53 +00001229}
1230
sewardje663cb92002-04-12 10:26:32 +00001231
sewardjf8f819e2002-04-17 23:21:37 +00001232/* ---------------------------------------------------
sewardjb48e5002002-05-13 00:16:03 +00001233 SIGNALS
1234 ------------------------------------------------ */
1235
1236#include <signal.h>
1237
1238int pthread_sigmask(int how, const sigset_t *newmask,
1239 sigset_t *oldmask)
1240{
1241 int res;
1242
1243 /* A bit subtle, because the scheduler expects newmask and oldmask
1244 to be vki_sigset_t* rather than sigset_t*, and the two are
1245 different. Fortunately the first 64 bits of a sigset_t are
1246 exactly a vki_sigset_t, so we just pass the pointers through
1247 unmodified. Haaaack!
1248
1249 Also mash the how value so that the SIG_ constants from glibc
sewardj018f7622002-05-15 21:13:39 +00001250 constants to VKI_ constants, so that the former do not have to
1251 be included into vg_scheduler.c. */
sewardjb48e5002002-05-13 00:16:03 +00001252
1253 ensure_valgrind("pthread_sigmask");
1254
1255 switch (how) {
sewardj018f7622002-05-15 21:13:39 +00001256 case SIG_SETMASK: how = VKI_SIG_SETMASK; break;
1257 case SIG_BLOCK: how = VKI_SIG_BLOCK; break;
1258 case SIG_UNBLOCK: how = VKI_SIG_UNBLOCK; break;
sewardj4dced352002-06-04 22:54:20 +00001259 default: pthread_error("pthread_sigmask: invalid how");
1260 return EINVAL;
sewardjb48e5002002-05-13 00:16:03 +00001261 }
1262
1263 /* Crude check */
1264 if (newmask == NULL)
1265 return EFAULT;
1266
1267 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
1268 VG_USERREQ__PTHREAD_SIGMASK,
1269 how, newmask, oldmask, 0);
1270
1271 /* The scheduler tells us of any memory violations. */
1272 return res == 0 ? 0 : EFAULT;
1273}
1274
1275
1276int sigwait ( const sigset_t* set, int* sig )
1277{
1278 int res;
1279 ensure_valgrind("sigwait");
1280 /* As with pthread_sigmask we deliberately confuse sigset_t with
1281 vki_ksigset_t. */
1282 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
1283 VG_USERREQ__SIGWAIT,
1284 set, sig, 0, 0);
1285 return res;
1286}
1287
1288
sewardj018f7622002-05-15 21:13:39 +00001289int pthread_kill(pthread_t thread, int signo)
1290{
1291 int res;
1292 ensure_valgrind("pthread_kill");
1293 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
1294 VG_USERREQ__PTHREAD_KILL,
1295 thread, signo, 0, 0);
1296 return res;
1297}
1298
1299
sewardj3665ded2002-05-16 16:57:25 +00001300/* Copied verbatim from Linuxthreads */
1301/* Redefine raise() to send signal to calling thread only,
1302 as per POSIX 1003.1c */
1303int raise (int sig)
1304{
1305 int retcode = pthread_kill(pthread_self(), sig);
sewardj4dced352002-06-04 22:54:20 +00001306 if (retcode == 0) {
sewardj3665ded2002-05-16 16:57:25 +00001307 return 0;
sewardj4dced352002-06-04 22:54:20 +00001308 } else {
sewardj3665ded2002-05-16 16:57:25 +00001309 errno = retcode;
1310 return -1;
1311 }
1312}
1313
1314
sewardj9a2224b2002-06-19 10:17:40 +00001315int pause ( void )
1316{
1317 unsigned int n_orig, n_now;
1318 struct vki_timespec nanosleep_interval;
1319 ensure_valgrind("pause");
1320
1321 /* This is surely a cancellation point. */
1322 __my_pthread_testcancel();
1323
1324 VALGRIND_MAGIC_SEQUENCE(n_orig, 0xFFFFFFFF /* default */,
1325 VG_USERREQ__GET_N_SIGS_RETURNED,
1326 0, 0, 0, 0);
1327 my_assert(n_orig != 0xFFFFFFFF);
1328
1329 while (1) {
1330 VALGRIND_MAGIC_SEQUENCE(n_now, 0xFFFFFFFF /* default */,
1331 VG_USERREQ__GET_N_SIGS_RETURNED,
1332 0, 0, 0, 0);
1333 my_assert(n_now != 0xFFFFFFFF);
1334 my_assert(n_now >= n_orig);
1335 if (n_now != n_orig) break;
1336
1337 nanosleep_interval.tv_sec = 0;
njn25e49d8e72002-09-23 09:36:25 +00001338 nanosleep_interval.tv_nsec = 12 * 1000 * 1000; /* 12 milliseconds */
sewardj9a2224b2002-06-19 10:17:40 +00001339 /* It's critical here that valgrind's nanosleep implementation
1340 is nonblocking. */
1341 (void)my_do_syscall2(__NR_nanosleep,
1342 (int)(&nanosleep_interval), (int)NULL);
1343 }
1344
1345 * (__errno_location()) = EINTR;
1346 return -1;
1347}
1348
1349
sewardjb48e5002002-05-13 00:16:03 +00001350/* ---------------------------------------------------
sewardjf8f819e2002-04-17 23:21:37 +00001351 THREAD-SPECIFICs
1352 ------------------------------------------------ */
sewardj5e5fa512002-04-14 13:13:05 +00001353
sewardj00a66b12002-10-12 16:42:35 +00001354static
1355int key_is_valid (pthread_key_t key)
1356{
1357 int res;
1358 VALGRIND_MAGIC_SEQUENCE(res, 2 /* default */,
1359 VG_USERREQ__PTHREAD_KEY_VALIDATE,
1360 key, 0, 0, 0);
1361 my_assert(res != 2);
1362 return res;
1363}
1364
1365
1366/* Returns NULL if thread is invalid. Otherwise, if the thread
1367 already has a specifics area, return that. Otherwise allocate it
1368 one. */
1369static
1370void** get_or_allocate_specifics_ptr ( pthread_t thread )
1371{
1372 int res, i;
1373 void** specifics_ptr;
1374 ensure_valgrind("get_or_allocate_specifics_ptr");
1375
1376 /* Returns zero if the thread has no specific_ptr. One if thread
1377 is invalid. Otherwise, the specific_ptr value. This is
1378 allocated with my_malloc and so is aligned and cannot be
1379 confused with 1 or 3. */
1380 VALGRIND_MAGIC_SEQUENCE(specifics_ptr, 3 /* default */,
1381 VG_USERREQ__PTHREAD_GETSPECIFIC_PTR,
1382 thread, 0, 0, 0);
1383 my_assert(specifics_ptr != (void**)3);
1384
1385 if (specifics_ptr == (void**)1)
1386 return NULL; /* invalid thread */
1387
1388 if (specifics_ptr != NULL)
1389 return specifics_ptr; /* already has a specifics ptr. */
1390
1391 /* None yet ... allocate a new one. Should never fail. */
1392 specifics_ptr = my_malloc( VG_N_THREAD_KEYS * sizeof(void*) );
1393 my_assert(specifics_ptr != NULL);
1394
1395 VALGRIND_MAGIC_SEQUENCE(res, -1 /* default */,
1396 VG_USERREQ__PTHREAD_SETSPECIFIC_PTR,
1397 specifics_ptr, 0, 0, 0);
1398 my_assert(res == 0);
1399
1400 /* POSIX sez: "Upon thread creation, the value NULL shall be
1401 associated with all defined keys in the new thread." This
1402 allocation is in effect a delayed allocation of the specific
1403 data for a thread, at its first-use. Hence we initialise it
1404 here. */
1405 for (i = 0; i < VG_N_THREAD_KEYS; i++) {
1406 specifics_ptr[i] = NULL;
1407 }
1408
1409 return specifics_ptr;
1410}
1411
1412
sewardj5905fae2002-04-26 13:25:00 +00001413int __pthread_key_create(pthread_key_t *key,
1414 void (*destr_function) (void *))
sewardj5e5fa512002-04-14 13:13:05 +00001415{
sewardj00a66b12002-10-12 16:42:35 +00001416 void** specifics_ptr;
1417 int res, i;
sewardj5f07b662002-04-23 16:52:51 +00001418 ensure_valgrind("pthread_key_create");
sewardj00a66b12002-10-12 16:42:35 +00001419
1420 /* This writes *key if successful. It should never fail. */
1421 VALGRIND_MAGIC_SEQUENCE(res, 1 /* default */,
sewardj5f07b662002-04-23 16:52:51 +00001422 VG_USERREQ__PTHREAD_KEY_CREATE,
1423 key, destr_function, 0, 0);
sewardj00a66b12002-10-12 16:42:35 +00001424 my_assert(res == 0);
1425
1426 /* POSIX sez: "Upon key creation, the value NULL shall be
1427 associated with the new key in all active threads." */
1428 for (i = 0; i < VG_N_THREADS; i++) {
1429 specifics_ptr = get_or_allocate_specifics_ptr(i);
1430 /* we get NULL if i is an invalid thread. */
1431 if (specifics_ptr != NULL)
1432 specifics_ptr[*key] = NULL;
1433 }
1434
sewardj5f07b662002-04-23 16:52:51 +00001435 return res;
sewardj5e5fa512002-04-14 13:13:05 +00001436}
1437
1438int pthread_key_delete(pthread_key_t key)
1439{
sewardj00a66b12002-10-12 16:42:35 +00001440 int res;
1441 ensure_valgrind("pthread_key_create");
1442 if (!key_is_valid(key))
1443 return EINVAL;
1444 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
1445 VG_USERREQ__PTHREAD_KEY_DELETE,
1446 key, 0, 0, 0);
1447 my_assert(res == 0);
sewardj5e5fa512002-04-14 13:13:05 +00001448 return 0;
1449}
1450
sewardj5905fae2002-04-26 13:25:00 +00001451int __pthread_setspecific(pthread_key_t key, const void *pointer)
sewardj5e5fa512002-04-14 13:13:05 +00001452{
sewardj00a66b12002-10-12 16:42:35 +00001453 void** specifics_ptr;
sewardj5f07b662002-04-23 16:52:51 +00001454 ensure_valgrind("pthread_setspecific");
sewardj00a66b12002-10-12 16:42:35 +00001455
1456 if (!key_is_valid(key))
1457 return EINVAL;
1458
1459 specifics_ptr = get_or_allocate_specifics_ptr(pthread_self());
1460 specifics_ptr[key] = (void*)pointer;
1461 return 0;
sewardj5e5fa512002-04-14 13:13:05 +00001462}
1463
sewardj5905fae2002-04-26 13:25:00 +00001464void * __pthread_getspecific(pthread_key_t key)
sewardj5e5fa512002-04-14 13:13:05 +00001465{
sewardj00a66b12002-10-12 16:42:35 +00001466 void** specifics_ptr;
sewardj5f07b662002-04-23 16:52:51 +00001467 ensure_valgrind("pthread_getspecific");
sewardj00a66b12002-10-12 16:42:35 +00001468
1469 if (!key_is_valid(key))
1470 return NULL;
1471
1472 specifics_ptr = get_or_allocate_specifics_ptr(pthread_self());
1473 return specifics_ptr[key];
1474}
1475
1476
sewardj9aa918d2002-10-20 16:25:55 +00001477#ifdef GLIBC_2_3
sewardj00a66b12002-10-12 16:42:35 +00001478static
1479void ** __pthread_getspecific_addr(pthread_key_t key)
1480{
1481 void** specifics_ptr;
1482 ensure_valgrind("pthread_getspecific_addr");
1483
1484 if (!key_is_valid(key))
1485 return NULL;
1486
1487 specifics_ptr = get_or_allocate_specifics_ptr(pthread_self());
1488 return &(specifics_ptr[key]);
sewardj5e5fa512002-04-14 13:13:05 +00001489}
sewardj9aa918d2002-10-20 16:25:55 +00001490#endif
sewardjf8f819e2002-04-17 23:21:37 +00001491
1492/* ---------------------------------------------------
sewardj89d3d852002-04-24 19:21:39 +00001493 ONCEry
1494 ------------------------------------------------ */
1495
1496static pthread_mutex_t once_masterlock = PTHREAD_MUTEX_INITIALIZER;
1497
1498
sewardj5905fae2002-04-26 13:25:00 +00001499int __pthread_once ( pthread_once_t *once_control,
1500 void (*init_routine) (void) )
sewardj89d3d852002-04-24 19:21:39 +00001501{
1502 int res;
1503 ensure_valgrind("pthread_once");
1504
sewardj68b2dd92002-05-10 21:03:56 +00001505 res = __pthread_mutex_lock(&once_masterlock);
sewardj89d3d852002-04-24 19:21:39 +00001506
sewardj68b2dd92002-05-10 21:03:56 +00001507 if (res != 0) {
sewardj89d3d852002-04-24 19:21:39 +00001508 barf("pthread_once: Looks like your program's "
1509 "init routine calls back to pthread_once() ?!");
sewardj68b2dd92002-05-10 21:03:56 +00001510 }
sewardj89d3d852002-04-24 19:21:39 +00001511
1512 if (*once_control == 0) {
1513 *once_control = 1;
1514 init_routine();
1515 }
1516
sewardj68b2dd92002-05-10 21:03:56 +00001517 __pthread_mutex_unlock(&once_masterlock);
sewardj89d3d852002-04-24 19:21:39 +00001518
1519 return 0;
1520}
1521
1522
1523/* ---------------------------------------------------
sewardj853f55d2002-04-26 00:27:53 +00001524 MISC
1525 ------------------------------------------------ */
1526
sewardj2cb00342002-06-28 01:46:26 +00001527static pthread_mutex_t pthread_atfork_lock
1528 = PTHREAD_MUTEX_INITIALIZER;
1529
sewardj5905fae2002-04-26 13:25:00 +00001530int __pthread_atfork ( void (*prepare)(void),
1531 void (*parent)(void),
1532 void (*child)(void) )
sewardj853f55d2002-04-26 00:27:53 +00001533{
sewardj2cb00342002-06-28 01:46:26 +00001534 int n, res;
1535 ForkHandlerEntry entry;
1536
1537 ensure_valgrind("pthread_atfork");
1538 __pthread_mutex_lock(&pthread_atfork_lock);
1539
1540 /* Fetch old counter */
1541 VALGRIND_MAGIC_SEQUENCE(n, -2 /* default */,
1542 VG_USERREQ__GET_FHSTACK_USED,
1543 0, 0, 0, 0);
1544 my_assert(n >= 0 && n < VG_N_FORKHANDLERSTACK);
1545 if (n == VG_N_FORKHANDLERSTACK-1)
1546 barf("pthread_atfork: VG_N_FORKHANDLERSTACK is too low; "
1547 "increase and recompile");
1548
1549 /* Add entry */
1550 entry.prepare = *prepare;
1551 entry.parent = *parent;
1552 entry.child = *child;
1553 VALGRIND_MAGIC_SEQUENCE(res, -2 /* default */,
1554 VG_USERREQ__SET_FHSTACK_ENTRY,
1555 n, &entry, 0, 0);
1556 my_assert(res == 0);
1557
1558 /* Bump counter */
1559 VALGRIND_MAGIC_SEQUENCE(res, -2 /* default */,
1560 VG_USERREQ__SET_FHSTACK_USED,
1561 n+1, 0, 0, 0);
1562 my_assert(res == 0);
1563
1564 __pthread_mutex_unlock(&pthread_atfork_lock);
1565 return 0;
sewardj853f55d2002-04-26 00:27:53 +00001566}
1567
1568
sewardjbb990782002-05-08 02:01:14 +00001569__attribute__((weak))
1570void __pthread_initialize ( void )
1571{
sewardjbea1caa2002-05-10 23:20:58 +00001572 ensure_valgrind("__pthread_initialize");
sewardjbb990782002-05-08 02:01:14 +00001573}
1574
1575
sewardj853f55d2002-04-26 00:27:53 +00001576/* ---------------------------------------------------
sewardj3b13f0e2002-04-25 20:17:29 +00001577 LIBRARY-PRIVATE THREAD SPECIFIC STATE
sewardjf8f819e2002-04-17 23:21:37 +00001578 ------------------------------------------------ */
1579
sewardj3b13f0e2002-04-25 20:17:29 +00001580#include <resolv.h>
1581static int thread_specific_errno[VG_N_THREADS];
1582static int thread_specific_h_errno[VG_N_THREADS];
1583static struct __res_state
1584 thread_specific_res_state[VG_N_THREADS];
sewardjf8f819e2002-04-17 23:21:37 +00001585
sewardj3b13f0e2002-04-25 20:17:29 +00001586int* __errno_location ( void )
sewardjf8f819e2002-04-17 23:21:37 +00001587{
1588 int tid;
sewardj3b13f0e2002-04-25 20:17:29 +00001589 /* ensure_valgrind("__errno_location"); */
1590 VALGRIND_MAGIC_SEQUENCE(tid, 1 /* default */,
sewardjf8f819e2002-04-17 23:21:37 +00001591 VG_USERREQ__PTHREAD_GET_THREADID,
1592 0, 0, 0, 0);
sewardj3b13f0e2002-04-25 20:17:29 +00001593 /* 'cos I'm paranoid ... */
sewardj439d45e2002-05-03 20:43:10 +00001594 if (tid < 1 || tid >= VG_N_THREADS)
sewardj3b13f0e2002-04-25 20:17:29 +00001595 barf("__errno_location: invalid ThreadId");
1596 return & thread_specific_errno[tid];
1597}
1598
1599int* __h_errno_location ( void )
1600{
1601 int tid;
1602 /* ensure_valgrind("__h_errno_location"); */
1603 VALGRIND_MAGIC_SEQUENCE(tid, 1 /* default */,
1604 VG_USERREQ__PTHREAD_GET_THREADID,
1605 0, 0, 0, 0);
1606 /* 'cos I'm paranoid ... */
sewardj439d45e2002-05-03 20:43:10 +00001607 if (tid < 1 || tid >= VG_N_THREADS)
sewardj3b13f0e2002-04-25 20:17:29 +00001608 barf("__h_errno_location: invalid ThreadId");
1609 return & thread_specific_h_errno[tid];
1610}
1611
sewardjb0ff1032002-08-06 09:02:53 +00001612
1613#undef _res
1614extern struct __res_state _res;
1615
sewardj3b13f0e2002-04-25 20:17:29 +00001616struct __res_state* __res_state ( void )
1617{
1618 int tid;
1619 /* ensure_valgrind("__res_state"); */
1620 VALGRIND_MAGIC_SEQUENCE(tid, 1 /* default */,
1621 VG_USERREQ__PTHREAD_GET_THREADID,
1622 0, 0, 0, 0);
1623 /* 'cos I'm paranoid ... */
sewardj439d45e2002-05-03 20:43:10 +00001624 if (tid < 1 || tid >= VG_N_THREADS)
sewardj3b13f0e2002-04-25 20:17:29 +00001625 barf("__res_state: invalid ThreadId");
sewardjb0ff1032002-08-06 09:02:53 +00001626 if (tid == 1)
1627 return & _res;
sewardj3b13f0e2002-04-25 20:17:29 +00001628 return & thread_specific_res_state[tid];
sewardjf8f819e2002-04-17 23:21:37 +00001629}
1630
1631
sewardj5716dbb2002-04-26 03:28:18 +00001632/* ---------------------------------------------------
1633 LIBC-PRIVATE SPECIFIC DATA
1634 ------------------------------------------------ */
1635
1636/* Relies on assumption that initial private data is NULL. This
1637 should be fixed somehow. */
1638
njn25e49d8e72002-09-23 09:36:25 +00001639/* The allowable keys (indices) (all 3 of them).
sewardj5716dbb2002-04-26 03:28:18 +00001640 From sysdeps/pthread/bits/libc-tsd.h
1641*/
sewardjcb7f08a2002-10-02 09:41:49 +00001642/* as per glibc anoncvs HEAD of 20021001. */
sewardj5716dbb2002-04-26 03:28:18 +00001643enum __libc_tsd_key_t { _LIBC_TSD_KEY_MALLOC = 0,
1644 _LIBC_TSD_KEY_DL_ERROR,
njn25e49d8e72002-09-23 09:36:25 +00001645 _LIBC_TSD_KEY_RPC_VARS,
sewardjcb7f08a2002-10-02 09:41:49 +00001646 _LIBC_TSD_KEY_LOCALE,
1647 _LIBC_TSD_KEY_CTYPE_B,
1648 _LIBC_TSD_KEY_CTYPE_TOLOWER,
1649 _LIBC_TSD_KEY_CTYPE_TOUPPER,
sewardj5716dbb2002-04-26 03:28:18 +00001650 _LIBC_TSD_KEY_N };
1651
1652/* Auto-initialising subsystem. libc_specifics_inited is set
1653 after initialisation. libc_specifics_inited_mx guards it. */
1654static int libc_specifics_inited = 0;
1655static pthread_mutex_t libc_specifics_inited_mx = PTHREAD_MUTEX_INITIALIZER;
1656
sewardj00a66b12002-10-12 16:42:35 +00001657
sewardj5716dbb2002-04-26 03:28:18 +00001658/* These are the keys we must initialise the first time. */
sewardjcb7f08a2002-10-02 09:41:49 +00001659static pthread_key_t libc_specifics_keys[_LIBC_TSD_KEY_N];
sewardj5716dbb2002-04-26 03:28:18 +00001660
sewardj00a66b12002-10-12 16:42:35 +00001661
sewardjcb7f08a2002-10-02 09:41:49 +00001662/* Initialise the keys, if they are not already initialised. */
sewardj5716dbb2002-04-26 03:28:18 +00001663static
1664void init_libc_tsd_keys ( void )
1665{
1666 int res, i;
1667 pthread_key_t k;
1668
sewardj08c7f012002-10-07 23:56:55 +00001669 /* Don't fall into deadlock if we get called again whilst we still
1670 hold the lock, via the __uselocale() call herein. */
1671 if (libc_specifics_inited != 0)
1672 return;
1673
1674 /* Take the lock. */
sewardj00a66b12002-10-12 16:42:35 +00001675 res = __pthread_mutex_lock(&libc_specifics_inited_mx);
sewardj5716dbb2002-04-26 03:28:18 +00001676 if (res != 0) barf("init_libc_tsd_keys: lock");
1677
sewardj08c7f012002-10-07 23:56:55 +00001678 /* Now test again, to be sure there is no mistake. */
1679 if (libc_specifics_inited != 0) {
sewardj00a66b12002-10-12 16:42:35 +00001680 res = __pthread_mutex_unlock(&libc_specifics_inited_mx);
sewardj08c7f012002-10-07 23:56:55 +00001681 if (res != 0) barf("init_libc_tsd_keys: unlock(1)");
1682 return;
sewardj5716dbb2002-04-26 03:28:18 +00001683 }
1684
sewardj08c7f012002-10-07 23:56:55 +00001685 /* Actually do the initialisation. */
1686 /* printf("INIT libc specifics\n"); */
1687 for (i = 0; i < _LIBC_TSD_KEY_N; i++) {
sewardj00a66b12002-10-12 16:42:35 +00001688 res = __pthread_key_create(&k, NULL);
sewardj08c7f012002-10-07 23:56:55 +00001689 if (res != 0) barf("init_libc_tsd_keys: create");
1690 libc_specifics_keys[i] = k;
1691 }
1692
1693 /* Signify init done. */
1694 libc_specifics_inited = 1;
1695
1696# ifdef GLIBC_2_3
1697 /* Set the initialising thread's locale to the global (default)
sewardj00a66b12002-10-12 16:42:35 +00001698 locale. A hack in support of glibc-2.3. This does the biz for
1699 the root thread. For all other threads we run this in
1700 thread_wrapper(), which does the real work of
1701 pthread_create(). */
1702 /* assert that we are the root thread. I don't know if this is
1703 really a valid assertion to make; if it breaks I'll reconsider
1704 it. */
1705 my_assert(pthread_self() == 1);
sewardj08c7f012002-10-07 23:56:55 +00001706 __uselocale(LC_GLOBAL_LOCALE);
1707# endif
1708
1709 /* Unlock and return. */
sewardj00a66b12002-10-12 16:42:35 +00001710 res = __pthread_mutex_unlock(&libc_specifics_inited_mx);
sewardj5716dbb2002-04-26 03:28:18 +00001711 if (res != 0) barf("init_libc_tsd_keys: unlock");
1712}
1713
1714
1715static int
1716libc_internal_tsd_set ( enum __libc_tsd_key_t key,
1717 const void * pointer )
1718{
sewardjcb7f08a2002-10-02 09:41:49 +00001719 int res;
sewardj5716dbb2002-04-26 03:28:18 +00001720 /* printf("SET SET SET key %d ptr %p\n", key, pointer); */
sewardjcb7f08a2002-10-02 09:41:49 +00001721 if (key < _LIBC_TSD_KEY_MALLOC || key >= _LIBC_TSD_KEY_N)
sewardj5716dbb2002-04-26 03:28:18 +00001722 barf("libc_internal_tsd_set: invalid key");
1723 init_libc_tsd_keys();
sewardj00a66b12002-10-12 16:42:35 +00001724 res = __pthread_setspecific(libc_specifics_keys[key], pointer);
sewardj5716dbb2002-04-26 03:28:18 +00001725 if (res != 0) barf("libc_internal_tsd_set: setspecific failed");
1726 return 0;
1727}
1728
1729static void *
1730libc_internal_tsd_get ( enum __libc_tsd_key_t key )
1731{
sewardjcb7f08a2002-10-02 09:41:49 +00001732 void* v;
sewardj5716dbb2002-04-26 03:28:18 +00001733 /* printf("GET GET GET key %d\n", key); */
sewardjcb7f08a2002-10-02 09:41:49 +00001734 if (key < _LIBC_TSD_KEY_MALLOC || key >= _LIBC_TSD_KEY_N)
sewardj5716dbb2002-04-26 03:28:18 +00001735 barf("libc_internal_tsd_get: invalid key");
1736 init_libc_tsd_keys();
sewardj00a66b12002-10-12 16:42:35 +00001737 v = __pthread_getspecific(libc_specifics_keys[key]);
sewardj5716dbb2002-04-26 03:28:18 +00001738 /* if (v == NULL) barf("libc_internal_tsd_set: getspecific failed"); */
1739 return v;
1740}
1741
1742
sewardj70adeb22002-04-27 01:35:38 +00001743int (*__libc_internal_tsd_set)
1744 (enum __libc_tsd_key_t key, const void * pointer)
1745 = libc_internal_tsd_set;
sewardj5716dbb2002-04-26 03:28:18 +00001746
sewardj70adeb22002-04-27 01:35:38 +00001747void* (*__libc_internal_tsd_get)
1748 (enum __libc_tsd_key_t key)
1749 = libc_internal_tsd_get;
sewardj5716dbb2002-04-26 03:28:18 +00001750
1751
sewardj00a66b12002-10-12 16:42:35 +00001752#ifdef GLIBC_2_3
1753/* This one was first spotted be me in the glibc-2.2.93 sources. */
1754static void**
1755libc_internal_tsd_address ( enum __libc_tsd_key_t key )
1756{
1757 void** v;
1758 /* printf("ADDR ADDR ADDR key %d\n", key); */
1759 if (key < _LIBC_TSD_KEY_MALLOC || key >= _LIBC_TSD_KEY_N)
1760 barf("libc_internal_tsd_address: invalid key");
1761 init_libc_tsd_keys();
1762 v = __pthread_getspecific_addr(libc_specifics_keys[key]);
1763 return v;
1764}
1765
1766void ** (*__libc_internal_tsd_address)
1767 (enum __libc_tsd_key_t key)
1768 = libc_internal_tsd_address;
1769#endif
1770
1771
sewardje663cb92002-04-12 10:26:32 +00001772/* ---------------------------------------------------------------------
1773 These are here (I think) because they are deemed cancellation
1774 points by POSIX. For the moment we'll simply pass the call along
1775 to the corresponding thread-unaware (?) libc routine.
1776 ------------------------------------------------------------------ */
1777
sewardje663cb92002-04-12 10:26:32 +00001778#include <stdlib.h>
sewardje663cb92002-04-12 10:26:32 +00001779#include <sys/types.h>
1780#include <sys/socket.h>
1781
sewardjd529a442002-05-04 19:49:21 +00001782#ifdef GLIBC_2_1
1783extern
1784int __sigaction
1785 (int signum,
1786 const struct sigaction *act,
1787 struct sigaction *oldact);
1788#else
sewardje663cb92002-04-12 10:26:32 +00001789extern
1790int __libc_sigaction
1791 (int signum,
1792 const struct sigaction *act,
1793 struct sigaction *oldact);
sewardjd529a442002-05-04 19:49:21 +00001794#endif
sewardje663cb92002-04-12 10:26:32 +00001795int sigaction(int signum,
1796 const struct sigaction *act,
1797 struct sigaction *oldact)
1798{
sewardjd140e442002-05-29 01:21:19 +00001799 __my_pthread_testcancel();
sewardj2a1dcce2002-04-22 12:45:25 +00001800# ifdef GLIBC_2_1
1801 return __sigaction(signum, act, oldact);
1802# else
sewardj45b4b372002-04-16 22:50:32 +00001803 return __libc_sigaction(signum, act, oldact);
sewardj2a1dcce2002-04-22 12:45:25 +00001804# endif
sewardje663cb92002-04-12 10:26:32 +00001805}
1806
1807
1808extern
1809int __libc_connect(int sockfd,
1810 const struct sockaddr *serv_addr,
1811 socklen_t addrlen);
sewardj5905fae2002-04-26 13:25:00 +00001812__attribute__((weak))
sewardje663cb92002-04-12 10:26:32 +00001813int connect(int sockfd,
1814 const struct sockaddr *serv_addr,
1815 socklen_t addrlen)
1816{
sewardjd140e442002-05-29 01:21:19 +00001817 __my_pthread_testcancel();
sewardj45b4b372002-04-16 22:50:32 +00001818 return __libc_connect(sockfd, serv_addr, addrlen);
sewardje663cb92002-04-12 10:26:32 +00001819}
1820
1821
1822extern
1823int __libc_fcntl(int fd, int cmd, long arg);
sewardj5905fae2002-04-26 13:25:00 +00001824__attribute__((weak))
sewardje663cb92002-04-12 10:26:32 +00001825int fcntl(int fd, int cmd, long arg)
1826{
sewardjd140e442002-05-29 01:21:19 +00001827 __my_pthread_testcancel();
sewardj45b4b372002-04-16 22:50:32 +00001828 return __libc_fcntl(fd, cmd, arg);
sewardje663cb92002-04-12 10:26:32 +00001829}
1830
1831
1832extern
1833ssize_t __libc_write(int fd, const void *buf, size_t count);
sewardj5905fae2002-04-26 13:25:00 +00001834__attribute__((weak))
sewardje663cb92002-04-12 10:26:32 +00001835ssize_t write(int fd, const void *buf, size_t count)
1836{
sewardjd140e442002-05-29 01:21:19 +00001837 __my_pthread_testcancel();
sewardj45b4b372002-04-16 22:50:32 +00001838 return __libc_write(fd, buf, count);
sewardje663cb92002-04-12 10:26:32 +00001839}
1840
1841
1842extern
1843ssize_t __libc_read(int fd, void *buf, size_t count);
sewardj5905fae2002-04-26 13:25:00 +00001844__attribute__((weak))
sewardje663cb92002-04-12 10:26:32 +00001845ssize_t read(int fd, void *buf, size_t count)
1846{
sewardjd140e442002-05-29 01:21:19 +00001847 __my_pthread_testcancel();
sewardj45b4b372002-04-16 22:50:32 +00001848 return __libc_read(fd, buf, count);
sewardje663cb92002-04-12 10:26:32 +00001849}
1850
sewardjf912dfc2002-11-13 21:51:10 +00001851/*
1852 * Ugh, this is horrible but here goes:
1853 *
1854 * Open of a named pipe (fifo file) can block. In a threaded program,
1855 * this means that the whole thing can block. We therefore need to
1856 * make the open appear to block to the caller, but still keep polling
1857 * for everyone else.
1858 *
1859 * There are four cases:
1860 *
1861 * - the caller asked for O_NONBLOCK. The easy one: we just do it.
1862 *
1863 * - the caller asked for a blocking O_RDONLY open. We open it with
1864 * O_NONBLOCK and then use poll to wait for it to become ready.
1865 *
1866 * - the caller asked for a blocking O_WRONLY open. Unfortunately, this
1867 * will fail with ENXIO when we make it non-blocking. Doubly
1868 * unfortunate is that we can only rely on these semantics if it is
1869 * actually a fifo file; the hack is that if we see that it is a
1870 * O_WRONLY open and we get ENXIO, then stat the path and see if it
1871 * actually is a fifo. This is racy, but it is the best we can do.
1872 * If it is a fifo, then keep trying the open until it works; if not
1873 * just return the error.
1874 *
1875 * - the caller asked for a blocking O_RDWR open. Well, under Linux,
1876 * this never blocks, so we just clear the non-blocking flag and
1877 * return.
1878 *
1879 * This code assumes that for whatever we open, O_NONBLOCK followed by
1880 * a fcntl clearing O_NONBLOCK is the same as opening without
1881 * O_NONBLOCK. Also assumes that stat and fstat have no side-effects.
1882 *
1883 * XXX Should probably put in special cases for some devices as well,
1884 * like serial ports. Unfortunately they don't work like fifos, so
1885 * this logic will become even more tortured. Wait until we really
1886 * need it.
1887 */
1888static inline int _open(const char *pathname, int flags, mode_t mode,
1889 int (*openp)(const char *, int, mode_t))
sewardjbe32e452002-04-24 20:29:58 +00001890{
sewardjf912dfc2002-11-13 21:51:10 +00001891 int fd;
1892 struct stat st;
1893 struct vki_timespec nanosleep_interval;
1894 int saved_errno;
1895
sewardjd140e442002-05-29 01:21:19 +00001896 __my_pthread_testcancel();
sewardjf912dfc2002-11-13 21:51:10 +00001897
1898 /* Assume we can only get O_RDONLY, O_WRONLY or O_RDWR */
1899 my_assert((flags & VKI_O_ACCMODE) != VKI_O_ACCMODE);
1900
1901 for(;;) {
1902 fd = (*openp)(pathname, flags | VKI_O_NONBLOCK, mode);
1903
1904 /* return immediately if caller wanted nonblocking anyway */
1905 if (flags & VKI_O_NONBLOCK)
1906 return fd;
1907
1908 saved_errno = errno;
1909
1910 if (fd != -1)
1911 break; /* open worked */
1912
1913 /* If we got ENXIO and we're opening WRONLY, and it turns out
1914 to really be a FIFO, then poll waiting for open to succeed */
1915 if (errno == ENXIO &&
1916 (flags & VKI_O_ACCMODE) == VKI_O_WRONLY &&
1917 (stat(pathname, &st) == 0 && S_ISFIFO(st.st_mode))) {
1918
1919 /* OK, we're opening a FIFO for writing; sleep and spin */
1920 nanosleep_interval.tv_sec = 0;
1921 nanosleep_interval.tv_nsec = 13 * 1000 * 1000; /* 13 milliseconds */
1922 /* It's critical here that valgrind's nanosleep implementation
1923 is nonblocking. */
1924 (void)my_do_syscall2(__NR_nanosleep,
1925 (int)(&nanosleep_interval), (int)NULL);
1926 } else {
1927 /* it was just an error */
1928 errno = saved_errno;
1929 return -1;
1930 }
1931 }
1932
1933 /* OK, we've got a nonblocking FD for a caller who wants blocking;
1934 reset the flags to what they asked for */
1935 fcntl(fd, VKI_F_SETFL, flags);
1936
1937 /* Return now if one of:
1938 - we were opening O_RDWR (never blocks)
1939 - we opened with O_WRONLY (polling already done)
1940 - the thing we opened wasn't a FIFO after all (or fstat failed)
1941 */
1942 if ((flags & VKI_O_ACCMODE) != VKI_O_RDONLY ||
1943 (fstat(fd, &st) == -1 || !S_ISFIFO(st.st_mode))) {
1944 errno = saved_errno;
1945 return fd;
1946 }
1947
1948 /* OK, drop into the poll loop looking for something to read on the fd */
1949 my_assert((flags & VKI_O_ACCMODE) == VKI_O_RDONLY);
1950 for(;;) {
1951 struct pollfd pollfd;
1952 int res;
1953
1954 pollfd.fd = fd;
1955 pollfd.events = POLLIN;
1956 pollfd.revents = 0;
1957
1958 res = my_do_syscall3(__NR_poll, (int)&pollfd, 1, 0);
1959
1960 my_assert(res == 0 || res == 1);
1961
1962 if (res == 1) {
1963 /* OK, got it.
1964
1965 XXX This is wrong: we're waiting for either something to
1966 read or a HUP on the file descriptor, but the semantics of
1967 fifo open are that we should unblock as soon as someone
1968 simply opens the other end, not that they write something.
1969 With luck this won't matter in practice.
1970 */
1971 my_assert(pollfd.revents & (POLLIN|POLLHUP));
1972 break;
1973 }
1974
1975 /* Still nobody home; sleep and spin */
1976 nanosleep_interval.tv_sec = 0;
1977 nanosleep_interval.tv_nsec = 13 * 1000 * 1000; /* 13 milliseconds */
1978 /* It's critical here that valgrind's nanosleep implementation
1979 is nonblocking. */
1980 (void)my_do_syscall2(__NR_nanosleep,
1981 (int)(&nanosleep_interval), (int)NULL);
1982 }
1983
1984 errno = saved_errno;
1985 return fd;
sewardjbe32e452002-04-24 20:29:58 +00001986}
1987
sewardjf912dfc2002-11-13 21:51:10 +00001988extern
1989int __libc_open64(const char *pathname, int flags, mode_t mode);
1990/* __attribute__((weak)) */
1991int open64(const char *pathname, int flags, mode_t mode)
1992{
1993 return _open(pathname, flags, mode, __libc_open64);
1994}
sewardje663cb92002-04-12 10:26:32 +00001995
1996extern
sewardj853f55d2002-04-26 00:27:53 +00001997int __libc_open(const char *pathname, int flags, mode_t mode);
sewardjf912dfc2002-11-13 21:51:10 +00001998/* __attribute__((weak)) */
sewardj853f55d2002-04-26 00:27:53 +00001999int open(const char *pathname, int flags, mode_t mode)
sewardje663cb92002-04-12 10:26:32 +00002000{
sewardjf912dfc2002-11-13 21:51:10 +00002001 return _open(pathname, flags, mode, __libc_open);
sewardje663cb92002-04-12 10:26:32 +00002002}
2003
sewardje663cb92002-04-12 10:26:32 +00002004extern
2005int __libc_close(int fd);
sewardj5905fae2002-04-26 13:25:00 +00002006__attribute__((weak))
sewardje663cb92002-04-12 10:26:32 +00002007int close(int fd)
2008{
sewardjd140e442002-05-29 01:21:19 +00002009 __my_pthread_testcancel();
sewardj45b4b372002-04-16 22:50:32 +00002010 return __libc_close(fd);
sewardje663cb92002-04-12 10:26:32 +00002011}
2012
2013
2014extern
2015int __libc_accept(int s, struct sockaddr *addr, socklen_t *addrlen);
sewardjf220ccc2002-10-23 21:53:49 +00002016
2017int VGL_(accept)(int s, struct sockaddr *addr, socklen_t *addrlen)
sewardje663cb92002-04-12 10:26:32 +00002018{
sewardjd140e442002-05-29 01:21:19 +00002019 __my_pthread_testcancel();
sewardj705d3cb2002-05-23 13:13:12 +00002020 wait_for_fd_to_be_readable_or_erring(s);
sewardjd140e442002-05-29 01:21:19 +00002021 __my_pthread_testcancel();
sewardj45b4b372002-04-16 22:50:32 +00002022 return __libc_accept(s, addr, addrlen);
sewardje663cb92002-04-12 10:26:32 +00002023}
2024
sewardj0c573af92002-10-23 21:55:01 +00002025extern
2026int __libc_recv(int s, void *buf, size_t len, int flags);
2027
2028int VGL_(recv)(int s, void *buf, size_t len, int flags)
2029{
2030 __my_pthread_testcancel();
2031 wait_for_fd_to_be_readable_or_erring(s);
2032 __my_pthread_testcancel();
2033 return __libc_recv(s, buf, len, flags);
2034}
2035
sewardj2a68e7e2002-11-16 11:04:18 +00002036int VGL_(readv)(int fd, const struct iovec *iov, int count)
2037{
sewardjfd7747b2002-12-01 10:25:53 +00002038 int res;
2039
sewardj2a68e7e2002-11-16 11:04:18 +00002040 __my_pthread_testcancel();
2041 wait_for_fd_to_be_readable_or_erring(fd);
2042 __my_pthread_testcancel();
sewardjfd7747b2002-12-01 10:25:53 +00002043 res = my_do_syscall3(__NR_readv, fd, (unsigned)iov, count);
2044
2045 if (is_kerror(res)) {
2046 *(__errno_location()) = -res;
2047 return -1;
2048 }
2049 return res;
sewardj2a68e7e2002-11-16 11:04:18 +00002050}
2051
2052int VGL_(writev)(int fd, struct iovec *iov, int count)
2053{
sewardjfd7747b2002-12-01 10:25:53 +00002054 int res;
2055
sewardj2a68e7e2002-11-16 11:04:18 +00002056 __my_pthread_testcancel();
2057 wait_for_fd_to_be_writable_or_erring(fd);
2058 __my_pthread_testcancel();
sewardjfd7747b2002-12-01 10:25:53 +00002059 res = my_do_syscall3(__NR_writev, fd, (unsigned)iov, count);
2060
2061 if (is_kerror(res)) {
2062 *(__errno_location()) = -res;
2063 return -1;
2064 }
2065 return res;
sewardj2a68e7e2002-11-16 11:04:18 +00002066}
sewardje663cb92002-04-12 10:26:32 +00002067
2068extern
sewardje663cb92002-04-12 10:26:32 +00002069pid_t __libc_waitpid(pid_t pid, int *status, int options);
sewardj5905fae2002-04-26 13:25:00 +00002070__attribute__((weak))
sewardje663cb92002-04-12 10:26:32 +00002071pid_t waitpid(pid_t pid, int *status, int options)
2072{
sewardjd140e442002-05-29 01:21:19 +00002073 __my_pthread_testcancel();
sewardj45b4b372002-04-16 22:50:32 +00002074 return __libc_waitpid(pid, status, options);
sewardje663cb92002-04-12 10:26:32 +00002075}
2076
2077
2078extern
2079int __libc_nanosleep(const struct timespec *req, struct timespec *rem);
sewardj5905fae2002-04-26 13:25:00 +00002080__attribute__((weak))
sewardje663cb92002-04-12 10:26:32 +00002081int nanosleep(const struct timespec *req, struct timespec *rem)
2082{
sewardjd140e442002-05-29 01:21:19 +00002083 __my_pthread_testcancel();
sewardje663cb92002-04-12 10:26:32 +00002084 return __libc_nanosleep(req, rem);
2085}
2086
sewardjbe32e452002-04-24 20:29:58 +00002087
sewardje663cb92002-04-12 10:26:32 +00002088extern
2089int __libc_fsync(int fd);
sewardj5905fae2002-04-26 13:25:00 +00002090__attribute__((weak))
sewardje663cb92002-04-12 10:26:32 +00002091int fsync(int fd)
2092{
sewardjd140e442002-05-29 01:21:19 +00002093 __my_pthread_testcancel();
sewardj45b4b372002-04-16 22:50:32 +00002094 return __libc_fsync(fd);
sewardje663cb92002-04-12 10:26:32 +00002095}
2096
sewardjbe32e452002-04-24 20:29:58 +00002097
sewardj70c75362002-04-13 04:18:32 +00002098extern
2099off_t __libc_lseek(int fildes, off_t offset, int whence);
sewardj5905fae2002-04-26 13:25:00 +00002100__attribute__((weak))
sewardj70c75362002-04-13 04:18:32 +00002101off_t lseek(int fildes, off_t offset, int whence)
2102{
sewardjd140e442002-05-29 01:21:19 +00002103 __my_pthread_testcancel();
sewardj45b4b372002-04-16 22:50:32 +00002104 return __libc_lseek(fildes, offset, whence);
sewardj70c75362002-04-13 04:18:32 +00002105}
2106
sewardjbe32e452002-04-24 20:29:58 +00002107
2108extern
2109__off64_t __libc_lseek64(int fildes, __off64_t offset, int whence);
sewardj5905fae2002-04-26 13:25:00 +00002110__attribute__((weak))
sewardjbe32e452002-04-24 20:29:58 +00002111__off64_t lseek64(int fildes, __off64_t offset, int whence)
2112{
sewardjd140e442002-05-29 01:21:19 +00002113 __my_pthread_testcancel();
sewardjbe32e452002-04-24 20:29:58 +00002114 return __libc_lseek64(fildes, offset, whence);
2115}
2116
2117
sewardj726c4122002-05-16 23:39:10 +00002118extern
2119ssize_t __libc_pread64 (int __fd, void *__buf, size_t __nbytes,
2120 __off64_t __offset);
2121ssize_t __pread64 (int __fd, void *__buf, size_t __nbytes,
2122 __off64_t __offset)
2123{
sewardjd140e442002-05-29 01:21:19 +00002124 __my_pthread_testcancel();
sewardj726c4122002-05-16 23:39:10 +00002125 return __libc_pread64(__fd, __buf, __nbytes, __offset);
2126}
2127
2128
sewardja18e2102002-05-18 10:43:22 +00002129extern
2130ssize_t __libc_pwrite64 (int __fd, const void *__buf, size_t __nbytes,
2131 __off64_t __offset);
2132ssize_t __pwrite64 (int __fd, const void *__buf, size_t __nbytes,
2133 __off64_t __offset)
2134{
sewardjd140e442002-05-29 01:21:19 +00002135 __my_pthread_testcancel();
sewardja18e2102002-05-18 10:43:22 +00002136 return __libc_pwrite64(__fd, __buf, __nbytes, __offset);
2137}
2138
sewardj726c4122002-05-16 23:39:10 +00002139
sewardj39b93b12002-05-18 10:56:27 +00002140extern
2141ssize_t __libc_pwrite(int fd, const void *buf, size_t count, off_t offset);
2142__attribute__((weak))
2143ssize_t pwrite(int fd, const void *buf, size_t count, off_t offset)
2144{
sewardjd140e442002-05-29 01:21:19 +00002145 __my_pthread_testcancel();
sewardj39b93b12002-05-18 10:56:27 +00002146 return __libc_pwrite(fd, buf, count, offset);
2147}
2148
2149
2150extern
2151ssize_t __libc_pread(int fd, void *buf, size_t count, off_t offset);
2152__attribute__((weak))
2153ssize_t pread(int fd, void *buf, size_t count, off_t offset)
2154{
sewardjd140e442002-05-29 01:21:19 +00002155 __my_pthread_testcancel();
sewardj39b93b12002-05-18 10:56:27 +00002156 return __libc_pread(fd, buf, count, offset);
2157}
2158
2159
sewardj6af4b5d2002-04-16 04:40:49 +00002160extern
2161void __libc_longjmp(jmp_buf env, int val) __attribute((noreturn));
sewardj5905fae2002-04-26 13:25:00 +00002162/* not weak: __attribute__((weak)) */
sewardj6af4b5d2002-04-16 04:40:49 +00002163void longjmp(jmp_buf env, int val)
2164{
2165 __libc_longjmp(env, val);
2166}
2167
sewardjbe32e452002-04-24 20:29:58 +00002168
sewardj436c2db2002-06-18 09:07:54 +00002169extern void __libc_siglongjmp (sigjmp_buf env, int val)
2170 __attribute__ ((noreturn));
2171void siglongjmp(sigjmp_buf env, int val)
2172{
2173 kludged("siglongjmp (cleanup handlers are ignored)");
2174 __libc_siglongjmp(env, val);
2175}
2176
2177
sewardj6af4b5d2002-04-16 04:40:49 +00002178extern
2179int __libc_send(int s, const void *msg, size_t len, int flags);
sewardj5905fae2002-04-26 13:25:00 +00002180__attribute__((weak))
sewardj6af4b5d2002-04-16 04:40:49 +00002181int send(int s, const void *msg, size_t len, int flags)
2182{
sewardjd140e442002-05-29 01:21:19 +00002183 __my_pthread_testcancel();
sewardj6af4b5d2002-04-16 04:40:49 +00002184 return __libc_send(s, msg, len, flags);
2185}
2186
sewardjbe32e452002-04-24 20:29:58 +00002187
sewardj1e8cdc92002-04-18 11:37:52 +00002188extern
2189int __libc_recv(int s, void *buf, size_t len, int flags);
sewardj5905fae2002-04-26 13:25:00 +00002190__attribute__((weak))
sewardj1e8cdc92002-04-18 11:37:52 +00002191int recv(int s, void *buf, size_t len, int flags)
2192{
sewardjd140e442002-05-29 01:21:19 +00002193 __my_pthread_testcancel();
sewardj1d6b3a22002-06-20 07:58:33 +00002194 wait_for_fd_to_be_readable_or_erring(s);
2195 __my_pthread_testcancel();
sewardj1e8cdc92002-04-18 11:37:52 +00002196 return __libc_recv(s, buf, len, flags);
2197}
2198
sewardjbe32e452002-04-24 20:29:58 +00002199
sewardj3665ded2002-05-16 16:57:25 +00002200extern
2201int __libc_sendmsg(int s, const struct msghdr *msg, int flags);
2202__attribute__((weak))
2203int sendmsg(int s, const struct msghdr *msg, int flags)
2204{
sewardjd140e442002-05-29 01:21:19 +00002205 __my_pthread_testcancel();
sewardj3665ded2002-05-16 16:57:25 +00002206 return __libc_sendmsg(s, msg, flags);
2207}
2208
2209
sewardj796d6a22002-04-24 02:28:34 +00002210extern
sewardj59da27a2002-06-06 08:33:54 +00002211int __libc_recvmsg(int s, struct msghdr *msg, int flags);
2212__attribute__((weak))
2213int recvmsg(int s, struct msghdr *msg, int flags)
2214{
2215 __my_pthread_testcancel();
2216 return __libc_recvmsg(s, msg, flags);
2217}
2218
2219
2220extern
sewardj436e0582002-04-26 14:31:40 +00002221int __libc_recvfrom(int s, void *buf, size_t len, int flags,
2222 struct sockaddr *from, socklen_t *fromlen);
2223__attribute__((weak))
2224int recvfrom(int s, void *buf, size_t len, int flags,
2225 struct sockaddr *from, socklen_t *fromlen)
2226{
sewardjd140e442002-05-29 01:21:19 +00002227 __my_pthread_testcancel();
sewardj2e207632002-06-13 17:29:53 +00002228 wait_for_fd_to_be_readable_or_erring(s);
2229 __my_pthread_testcancel();
sewardj436e0582002-04-26 14:31:40 +00002230 return __libc_recvfrom(s, buf, len, flags, from, fromlen);
2231}
2232
2233
2234extern
sewardj796d6a22002-04-24 02:28:34 +00002235int __libc_sendto(int s, const void *msg, size_t len, int flags,
2236 const struct sockaddr *to, socklen_t tolen);
sewardj5905fae2002-04-26 13:25:00 +00002237__attribute__((weak))
sewardj796d6a22002-04-24 02:28:34 +00002238int sendto(int s, const void *msg, size_t len, int flags,
2239 const struct sockaddr *to, socklen_t tolen)
2240{
sewardjd140e442002-05-29 01:21:19 +00002241 __my_pthread_testcancel();
sewardj796d6a22002-04-24 02:28:34 +00002242 return __libc_sendto(s, msg, len, flags, to, tolen);
2243}
2244
sewardjbe32e452002-04-24 20:29:58 +00002245
sewardj369b1702002-04-24 13:28:15 +00002246extern
2247int __libc_system(const char* str);
sewardj5905fae2002-04-26 13:25:00 +00002248__attribute__((weak))
sewardj369b1702002-04-24 13:28:15 +00002249int system(const char* str)
2250{
sewardjd140e442002-05-29 01:21:19 +00002251 __my_pthread_testcancel();
sewardj369b1702002-04-24 13:28:15 +00002252 return __libc_system(str);
2253}
2254
sewardjbe32e452002-04-24 20:29:58 +00002255
sewardjab0b1c32002-04-24 19:26:47 +00002256extern
2257pid_t __libc_wait(int *status);
sewardj5905fae2002-04-26 13:25:00 +00002258__attribute__((weak))
sewardjab0b1c32002-04-24 19:26:47 +00002259pid_t wait(int *status)
2260{
sewardjd140e442002-05-29 01:21:19 +00002261 __my_pthread_testcancel();
sewardjab0b1c32002-04-24 19:26:47 +00002262 return __libc_wait(status);
2263}
2264
sewardj45b4b372002-04-16 22:50:32 +00002265
sewardj67f1d582002-05-24 02:11:32 +00002266extern
2267int __libc_msync(const void *start, size_t length, int flags);
2268__attribute__((weak))
2269int msync(const void *start, size_t length, int flags)
2270{
sewardjd140e442002-05-29 01:21:19 +00002271 __my_pthread_testcancel();
sewardj67f1d582002-05-24 02:11:32 +00002272 return __libc_msync(start, length, flags);
2273}
2274
sewardj5905fae2002-04-26 13:25:00 +00002275
sewardj2cb00342002-06-28 01:46:26 +00002276/*--- fork and its helper ---*/
2277
2278static
2279void run_fork_handlers ( int what )
2280{
2281 ForkHandlerEntry entry;
2282 int n_h, n_handlers, i, res;
2283
2284 my_assert(what == 0 || what == 1 || what == 2);
2285
2286 /* Fetch old counter */
2287 VALGRIND_MAGIC_SEQUENCE(n_handlers, -2 /* default */,
2288 VG_USERREQ__GET_FHSTACK_USED,
2289 0, 0, 0, 0);
2290 my_assert(n_handlers >= 0 && n_handlers < VG_N_FORKHANDLERSTACK);
2291
2292 /* Prepare handlers (what == 0) are called in opposite order of
2293 calls to pthread_atfork. Parent and child handlers are called
2294 in the same order as calls to pthread_atfork. */
2295 if (what == 0)
2296 n_h = n_handlers - 1;
2297 else
2298 n_h = 0;
2299
2300 for (i = 0; i < n_handlers; i++) {
2301 VALGRIND_MAGIC_SEQUENCE(res, -2 /* default */,
2302 VG_USERREQ__GET_FHSTACK_ENTRY,
2303 n_h, &entry, 0, 0);
2304 my_assert(res == 0);
2305 switch (what) {
2306 case 0: if (entry.prepare) entry.prepare();
2307 n_h--; break;
2308 case 1: if (entry.parent) entry.parent();
2309 n_h++; break;
2310 case 2: if (entry.child) entry.child();
2311 n_h++; break;
2312 default: barf("run_fork_handlers: invalid what");
2313 }
2314 }
2315
2316 if (what != 0 /* prepare */) {
2317 /* Empty out the stack. */
2318 VALGRIND_MAGIC_SEQUENCE(res, -2 /* default */,
2319 VG_USERREQ__SET_FHSTACK_USED,
2320 0, 0, 0, 0);
2321 my_assert(res == 0);
2322 }
2323}
2324
2325extern
2326pid_t __libc_fork(void);
2327pid_t __fork(void)
2328{
2329 pid_t pid;
2330 __my_pthread_testcancel();
2331 __pthread_mutex_lock(&pthread_atfork_lock);
2332
2333 run_fork_handlers(0 /* prepare */);
2334 pid = __libc_fork();
2335 if (pid == 0) {
2336 /* I am the child */
2337 run_fork_handlers(2 /* child */);
sewardjd8acdf22002-11-13 21:57:52 +00002338 __pthread_mutex_unlock(&pthread_atfork_lock);
sewardj2cb00342002-06-28 01:46:26 +00002339 __pthread_mutex_init(&pthread_atfork_lock, NULL);
2340 } else {
2341 /* I am the parent */
2342 run_fork_handlers(1 /* parent */);
2343 __pthread_mutex_unlock(&pthread_atfork_lock);
2344 }
2345 return pid;
2346}
2347
2348
njn25e49d8e72002-09-23 09:36:25 +00002349pid_t __vfork(void)
2350{
2351 return __fork();
2352}
sewardj2cb00342002-06-28 01:46:26 +00002353
2354
sewardj3b13f0e2002-04-25 20:17:29 +00002355/* ---------------------------------------------------------------------
2356 Nonblocking implementations of select() and poll(). This stuff will
2357 surely rot your mind.
2358 ------------------------------------------------------------------ */
sewardje663cb92002-04-12 10:26:32 +00002359
sewardj08a4c3f2002-04-13 03:45:44 +00002360/*--------------------------------------------------*/
2361
2362#include "vg_kerneliface.h"
2363
2364static
sewardj08a4c3f2002-04-13 03:45:44 +00002365int my_do_syscall1 ( int syscallno, int arg1 )
2366{
2367 int __res;
2368 __asm__ volatile ("pushl %%ebx; movl %%edx,%%ebx ; int $0x80 ; popl %%ebx"
2369 : "=a" (__res)
2370 : "0" (syscallno),
2371 "d" (arg1) );
2372 return __res;
2373}
2374
2375static
2376int my_do_syscall2 ( int syscallno,
sewardjf854f472002-04-21 12:19:41 +00002377 int arg1, int arg2 )
sewardj08a4c3f2002-04-13 03:45:44 +00002378{
2379 int __res;
2380 __asm__ volatile ("pushl %%ebx; movl %%edx,%%ebx ; int $0x80 ; popl %%ebx"
2381 : "=a" (__res)
2382 : "0" (syscallno),
2383 "d" (arg1),
2384 "c" (arg2) );
2385 return __res;
2386}
2387
2388static
sewardjf854f472002-04-21 12:19:41 +00002389int my_do_syscall3 ( int syscallno,
2390 int arg1, int arg2, int arg3 )
2391{
2392 int __res;
2393 __asm__ volatile ("pushl %%ebx; movl %%esi,%%ebx ; int $0x80 ; popl %%ebx"
2394 : "=a" (__res)
2395 : "0" (syscallno),
2396 "S" (arg1),
2397 "c" (arg2),
2398 "d" (arg3) );
2399 return __res;
2400}
2401
sewardjd5bef572002-10-23 21:49:33 +00002402static inline
2403int my_do_syscall5 ( int syscallno,
2404 int arg1, int arg2, int arg3, int arg4, int arg5 )
2405{
2406 int __res;
2407 __asm__ volatile ("int $0x80"
2408 : "=a" (__res)
2409 : "0" (syscallno),
2410 "b" (arg1),
2411 "c" (arg2),
2412 "d" (arg3),
2413 "S" (arg4),
2414 "D" (arg5));
2415 return __res;
2416}
2417
sewardjf854f472002-04-21 12:19:41 +00002418static
sewardj08a4c3f2002-04-13 03:45:44 +00002419int do_syscall_select( int n,
2420 vki_fd_set* readfds,
2421 vki_fd_set* writefds,
2422 vki_fd_set* exceptfds,
2423 struct vki_timeval * timeout )
2424{
2425 int res;
2426 int args[5];
2427 args[0] = n;
2428 args[1] = (int)readfds;
2429 args[2] = (int)writefds;
2430 args[3] = (int)exceptfds;
2431 args[4] = (int)timeout;
2432 res = my_do_syscall1(__NR_select, (int)(&(args[0])) );
sewardj02535bc2002-04-21 01:08:26 +00002433 return res;
sewardj08a4c3f2002-04-13 03:45:44 +00002434}
2435
2436
2437/* This is a wrapper round select(), which makes it thread-safe,
2438 meaning that only this thread will block, rather than the entire
2439 process. This wrapper in turn depends on nanosleep() not to block
2440 the entire process, but I think (hope? suspect?) that POSIX
2441 pthreads guarantees that to be the case.
2442
2443 Basic idea is: modify the timeout parameter to select so that it
2444 returns immediately. Poll like this until select returns non-zero,
2445 indicating something interesting happened, or until our time is up.
njn25e49d8e72002-09-23 09:36:25 +00002446 Space out the polls with nanosleeps of say 11 milliseconds, which
sewardj08a4c3f2002-04-13 03:45:44 +00002447 is required to be nonblocking; this allows other threads to run.
sewardj02535bc2002-04-21 01:08:26 +00002448
2449 Assumes:
sewardj2d94c112002-06-03 01:25:54 +00002450 * (checked via my_assert) types fd_set and vki_fd_set are identical.
2451 * (checked via my_assert) types timeval and vki_timeval are identical.
sewardj02535bc2002-04-21 01:08:26 +00002452 * (unchecked) libc error numbers (EINTR etc) are the negation of the
2453 kernel's error numbers (VKI_EINTR etc).
sewardj08a4c3f2002-04-13 03:45:44 +00002454*/
sewardj08a4c3f2002-04-13 03:45:44 +00002455
sewardj7db011a2002-11-13 22:00:20 +00002456int VGL_(select) ( int n,
2457 fd_set *rfds,
2458 fd_set *wfds,
2459 fd_set *xfds,
2460 struct timeval *timeout )
sewardj08a4c3f2002-04-13 03:45:44 +00002461{
sewardj5f07b662002-04-23 16:52:51 +00002462 unsigned int ms_now, ms_end;
sewardj08a4c3f2002-04-13 03:45:44 +00002463 int res;
2464 fd_set rfds_copy;
2465 fd_set wfds_copy;
2466 fd_set xfds_copy;
2467 struct vki_timeval t_now;
sewardj08a4c3f2002-04-13 03:45:44 +00002468 struct vki_timeval zero_timeout;
2469 struct vki_timespec nanosleep_interval;
2470
sewardjd140e442002-05-29 01:21:19 +00002471 __my_pthread_testcancel();
2472
sewardj5f07b662002-04-23 16:52:51 +00002473 /* gcc's complains about ms_end being used uninitialised -- classic
2474 case it can't understand, where ms_end is both defined and used
2475 only if timeout != NULL. Hence ... */
2476 ms_end = 0;
sewardj08a4c3f2002-04-13 03:45:44 +00002477
2478 /* We assume that the kernel and libc data layouts are identical
2479 for the following types. These asserts provide a crude
2480 check. */
2481 if (sizeof(fd_set) != sizeof(vki_fd_set)
2482 || sizeof(struct timeval) != sizeof(struct vki_timeval))
2483 barf("valgrind's hacky non-blocking select(): data sizes error");
2484
sewardj5f07b662002-04-23 16:52:51 +00002485 /* Detect the current time and simultaneously find out if we are
2486 running on Valgrind. */
2487 VALGRIND_MAGIC_SEQUENCE(ms_now, 0xFFFFFFFF /* default */,
2488 VG_USERREQ__READ_MILLISECOND_TIMER,
2489 0, 0, 0, 0);
2490
2491 /* If a zero timeout specified, this call is harmless. Also go
2492 this route if we're not running on Valgrind, for whatever
2493 reason. */
2494 if ( (timeout && timeout->tv_sec == 0 && timeout->tv_usec == 0)
2495 || (ms_now == 0xFFFFFFFF) ) {
sewardj02535bc2002-04-21 01:08:26 +00002496 res = do_syscall_select( n, (vki_fd_set*)rfds,
sewardj08a4c3f2002-04-13 03:45:44 +00002497 (vki_fd_set*)wfds,
2498 (vki_fd_set*)xfds,
2499 (struct vki_timeval*)timeout);
sewardj02535bc2002-04-21 01:08:26 +00002500 if (is_kerror(res)) {
2501 * (__errno_location()) = -res;
2502 return -1;
2503 } else {
2504 return res;
2505 }
2506 }
sewardj08a4c3f2002-04-13 03:45:44 +00002507
sewardj5f07b662002-04-23 16:52:51 +00002508 /* If a timeout was specified, set ms_end to be the end millisecond
2509 counter [wallclock] time. */
sewardj08a4c3f2002-04-13 03:45:44 +00002510 if (timeout) {
2511 res = my_do_syscall2(__NR_gettimeofday, (int)&t_now, (int)NULL);
sewardj2d94c112002-06-03 01:25:54 +00002512 my_assert(res == 0);
sewardj5f07b662002-04-23 16:52:51 +00002513 ms_end = ms_now;
2514 ms_end += (timeout->tv_usec / 1000);
2515 ms_end += (timeout->tv_sec * 1000);
sewardj08a4c3f2002-04-13 03:45:44 +00002516 /* Stay sane ... */
sewardj2d94c112002-06-03 01:25:54 +00002517 my_assert (ms_end >= ms_now);
sewardj08a4c3f2002-04-13 03:45:44 +00002518 }
2519
2520 /* fprintf(stderr, "MY_SELECT: before loop\n"); */
2521
2522 /* Either timeout == NULL, meaning wait indefinitely, or timeout !=
sewardj5f07b662002-04-23 16:52:51 +00002523 NULL, in which case ms_end holds the end time. */
sewardj05bb2c92002-06-26 00:47:17 +00002524
sewardj08a4c3f2002-04-13 03:45:44 +00002525 while (1) {
sewardj05bb2c92002-06-26 00:47:17 +00002526
2527 /* First, do a return-immediately select(). */
sewardj08a4c3f2002-04-13 03:45:44 +00002528
2529 /* These could be trashed each time round the loop, so restore
2530 them each time. */
2531 if (rfds) rfds_copy = *rfds;
2532 if (wfds) wfds_copy = *wfds;
2533 if (xfds) xfds_copy = *xfds;
2534
2535 zero_timeout.tv_sec = zero_timeout.tv_usec = 0;
2536
2537 res = do_syscall_select( n,
2538 rfds ? (vki_fd_set*)(&rfds_copy) : NULL,
2539 wfds ? (vki_fd_set*)(&wfds_copy) : NULL,
2540 xfds ? (vki_fd_set*)(&xfds_copy) : NULL,
2541 & zero_timeout );
sewardj02535bc2002-04-21 01:08:26 +00002542 if (is_kerror(res)) {
2543 /* Some kind of error (including EINTR). Set errno and
sewardj08a4c3f2002-04-13 03:45:44 +00002544 return. The sets are unspecified in this case. */
sewardj02535bc2002-04-21 01:08:26 +00002545 * (__errno_location()) = -res;
2546 return -1;
sewardj08a4c3f2002-04-13 03:45:44 +00002547 }
2548 if (res > 0) {
2549 /* one or more fds is ready. Copy out resulting sets and
2550 return. */
2551 if (rfds) *rfds = rfds_copy;
2552 if (wfds) *wfds = wfds_copy;
2553 if (xfds) *xfds = xfds_copy;
2554 return res;
2555 }
sewardj05bb2c92002-06-26 00:47:17 +00002556
2557 /* Nothing interesting happened, so we go to sleep for a
2558 while. */
2559
sewardj08a4c3f2002-04-13 03:45:44 +00002560 /* fprintf(stderr, "MY_SELECT: nanosleep\n"); */
2561 /* nanosleep and go round again */
sewardj02535bc2002-04-21 01:08:26 +00002562 nanosleep_interval.tv_sec = 0;
njn25e49d8e72002-09-23 09:36:25 +00002563 nanosleep_interval.tv_nsec = 11 * 1000 * 1000; /* 11 milliseconds */
sewardjf854f472002-04-21 12:19:41 +00002564 /* It's critical here that valgrind's nanosleep implementation
2565 is nonblocking. */
sewardj645030e2002-06-06 01:27:39 +00002566 res = my_do_syscall2(__NR_nanosleep,
sewardjf854f472002-04-21 12:19:41 +00002567 (int)(&nanosleep_interval), (int)NULL);
sewardj645030e2002-06-06 01:27:39 +00002568 if (res == -VKI_EINTR) {
2569 /* The nanosleep was interrupted by a signal. So we do the
2570 same. */
2571 * (__errno_location()) = EINTR;
2572 return -1;
2573 }
sewardj05bb2c92002-06-26 00:47:17 +00002574
2575 /* Sleeping finished. If a finite timeout, check to see if it
2576 has expired yet. */
2577 if (timeout) {
2578 VALGRIND_MAGIC_SEQUENCE(ms_now, 0xFFFFFFFF /* default */,
2579 VG_USERREQ__READ_MILLISECOND_TIMER,
2580 0, 0, 0, 0);
2581 my_assert(ms_now != 0xFFFFFFFF);
2582 if (ms_now >= ms_end) {
2583 /* timeout; nothing interesting happened. */
2584 if (rfds) FD_ZERO(rfds);
2585 if (wfds) FD_ZERO(wfds);
2586 if (xfds) FD_ZERO(xfds);
2587 return 0;
2588 }
2589 }
2590
sewardjf854f472002-04-21 12:19:41 +00002591 }
2592}
2593
2594
2595
2596
2597#include <sys/poll.h>
2598
sewardj3e909ce2002-06-03 13:27:15 +00002599#ifndef HAVE_NFDS_T
sewardj72d58482002-04-24 02:20:20 +00002600typedef unsigned long int nfds_t;
2601#endif
2602
sewardj705d3cb2002-05-23 13:13:12 +00002603
sewardj7db011a2002-11-13 22:00:20 +00002604int VGL_(poll) (struct pollfd *__fds, nfds_t __nfds, int __timeout)
sewardjf854f472002-04-21 12:19:41 +00002605{
sewardj5f07b662002-04-23 16:52:51 +00002606 unsigned int ms_now, ms_end;
sewardjf854f472002-04-21 12:19:41 +00002607 int res, i;
sewardjf854f472002-04-21 12:19:41 +00002608 struct vki_timespec nanosleep_interval;
2609
sewardjd140e442002-05-29 01:21:19 +00002610 __my_pthread_testcancel();
sewardjf854f472002-04-21 12:19:41 +00002611 ensure_valgrind("poll");
2612
sewardj5f07b662002-04-23 16:52:51 +00002613 /* Detect the current time and simultaneously find out if we are
2614 running on Valgrind. */
2615 VALGRIND_MAGIC_SEQUENCE(ms_now, 0xFFFFFFFF /* default */,
2616 VG_USERREQ__READ_MILLISECOND_TIMER,
2617 0, 0, 0, 0);
2618
sewardjf854f472002-04-21 12:19:41 +00002619 if (/* CHECK SIZES FOR struct pollfd */
2620 sizeof(struct timeval) != sizeof(struct vki_timeval))
2621 barf("valgrind's hacky non-blocking poll(): data sizes error");
2622
sewardj5f07b662002-04-23 16:52:51 +00002623 /* dummy initialisation to keep gcc -Wall happy */
2624 ms_end = 0;
2625
2626 /* If a zero timeout specified, this call is harmless. Also do
2627 this if not running on Valgrind. */
2628 if (__timeout == 0 || ms_now == 0xFFFFFFFF) {
sewardjf854f472002-04-21 12:19:41 +00002629 res = my_do_syscall3(__NR_poll, (int)__fds, __nfds, __timeout);
2630 if (is_kerror(res)) {
2631 * (__errno_location()) = -res;
2632 return -1;
2633 } else {
2634 return res;
2635 }
2636 }
2637
sewardj5f07b662002-04-23 16:52:51 +00002638 /* If a timeout was specified, set ms_end to be the end wallclock
2639 time. Easy considering that __timeout is in milliseconds. */
sewardjf854f472002-04-21 12:19:41 +00002640 if (__timeout > 0) {
sewardj650ac002002-04-29 12:20:34 +00002641 ms_end = ms_now + (unsigned int)__timeout;
sewardjf854f472002-04-21 12:19:41 +00002642 }
2643
2644 /* fprintf(stderr, "MY_POLL: before loop\n"); */
2645
2646 /* Either timeout < 0, meaning wait indefinitely, or timeout > 0,
2647 in which case t_end holds the end time. */
sewardj05bb2c92002-06-26 00:47:17 +00002648
sewardj2d94c112002-06-03 01:25:54 +00002649 my_assert(__timeout != 0);
sewardj5f07b662002-04-23 16:52:51 +00002650
sewardjf854f472002-04-21 12:19:41 +00002651 while (1) {
sewardj05bb2c92002-06-26 00:47:17 +00002652
2653 /* Do a return-immediately poll. */
2654
2655 res = my_do_syscall3(__NR_poll, (int)__fds, __nfds, 0 );
2656 if (is_kerror(res)) {
2657 /* Some kind of error. Set errno and return. */
2658 * (__errno_location()) = -res;
2659 return -1;
2660 }
2661 if (res > 0) {
2662 /* One or more fds is ready. Return now. */
2663 return res;
2664 }
2665
2666 /* Nothing interesting happened, so we go to sleep for a
2667 while. */
2668
2669 /* fprintf(stderr, "MY_POLL: nanosleep\n"); */
2670 /* nanosleep and go round again */
2671 nanosleep_interval.tv_sec = 0;
njn25e49d8e72002-09-23 09:36:25 +00002672 nanosleep_interval.tv_nsec = 13 * 1000 * 1000; /* 13 milliseconds */
sewardj05bb2c92002-06-26 00:47:17 +00002673 /* It's critical here that valgrind's nanosleep implementation
2674 is nonblocking. */
sewardj49b5d172003-02-23 03:37:58 +00002675 res = my_do_syscall2(__NR_nanosleep,
sewardj05bb2c92002-06-26 00:47:17 +00002676 (int)(&nanosleep_interval), (int)NULL);
sewardj49b5d172003-02-23 03:37:58 +00002677 if (res == -VKI_EINTR) {
sewardj669610b2003-02-23 03:40:03 +00002678 /* The nanosleep was interrupted by a signal. So we do the
sewardj49b5d172003-02-23 03:37:58 +00002679 same. */
2680 * (__errno_location()) = EINTR;
2681 return -1;
2682 }
sewardj05bb2c92002-06-26 00:47:17 +00002683
2684 /* Sleeping finished. If a finite timeout, check to see if it
2685 has expired yet. */
sewardjf854f472002-04-21 12:19:41 +00002686 if (__timeout > 0) {
sewardj5f07b662002-04-23 16:52:51 +00002687 VALGRIND_MAGIC_SEQUENCE(ms_now, 0xFFFFFFFF /* default */,
2688 VG_USERREQ__READ_MILLISECOND_TIMER,
2689 0, 0, 0, 0);
sewardj2d94c112002-06-03 01:25:54 +00002690 my_assert(ms_now != 0xFFFFFFFF);
sewardj5f07b662002-04-23 16:52:51 +00002691 if (ms_now >= ms_end) {
sewardjf854f472002-04-21 12:19:41 +00002692 /* timeout; nothing interesting happened. */
2693 for (i = 0; i < __nfds; i++)
2694 __fds[i].revents = 0;
2695 return 0;
2696 }
2697 }
2698
sewardj08a4c3f2002-04-13 03:45:44 +00002699 }
2700}
sewardj3b13f0e2002-04-25 20:17:29 +00002701
2702
sewardj705d3cb2002-05-23 13:13:12 +00002703/* Helper function used to make accept() non-blocking. Idea is to use
2704 the above nonblocking poll() to make this thread ONLY wait for the
2705 specified fd to become ready, and then return. */
sewardjd1c1cf22002-06-26 00:13:36 +00002706
2707/* Sigh -- a hack. We're not supposed to include this file directly;
2708 should do it via /usr/include/fcntl.h, but that introduces a
2709 varargs prototype for fcntl itself, which we can't mimic. */
2710#define _FCNTL_H
2711#include <bits/fcntl.h>
2712
sewardj705d3cb2002-05-23 13:13:12 +00002713static void wait_for_fd_to_be_readable_or_erring ( int fd )
2714{
2715 struct pollfd pfd;
sewardjd1c1cf22002-06-26 00:13:36 +00002716 int res;
2717
sewardj6e6cbaa2002-05-24 02:12:52 +00002718 /* fprintf(stderr, "wait_for_fd_to_be_readable_or_erring %d\n", fd); */
sewardjd1c1cf22002-06-26 00:13:36 +00002719
2720 /* First check to see if the fd is nonblocking, and/or invalid. In
2721 either case return immediately. */
2722 res = __libc_fcntl(fd, F_GETFL, 0);
2723 if (res == -1) return; /* fd is invalid somehow */
2724 if (res & O_NONBLOCK) return; /* fd is nonblocking */
2725
2726 /* Ok, we'd better wait with poll. */
sewardj705d3cb2002-05-23 13:13:12 +00002727 pfd.fd = fd;
2728 pfd.events = POLLIN | POLLPRI | POLLERR | POLLHUP | POLLNVAL;
2729 /* ... but not POLLOUT, you may notice. */
2730 pfd.revents = 0;
2731 (void)poll(&pfd, 1, -1 /* forever */);
2732}
2733
sewardj2a68e7e2002-11-16 11:04:18 +00002734static void wait_for_fd_to_be_writable_or_erring ( int fd )
2735{
2736 struct pollfd pfd;
2737 int res;
2738
2739 /* fprintf(stderr, "wait_for_fd_to_be_readable_or_erring %d\n", fd); */
2740
2741 /* First check to see if the fd is nonblocking, and/or invalid. In
2742 either case return immediately. */
2743 res = __libc_fcntl(fd, F_GETFL, 0);
2744 if (res == -1) return; /* fd is invalid somehow */
2745 if (res & O_NONBLOCK) return; /* fd is nonblocking */
2746
2747 /* Ok, we'd better wait with poll. */
2748 pfd.fd = fd;
2749 pfd.events = POLLOUT | POLLERR | POLLHUP | POLLNVAL;
2750 pfd.revents = 0;
2751 (void)poll(&pfd, 1, -1 /* forever */);
2752}
sewardj705d3cb2002-05-23 13:13:12 +00002753
sewardj3b13f0e2002-04-25 20:17:29 +00002754/* ---------------------------------------------------------------------
sewardj8f253ff2002-05-19 00:13:34 +00002755 Hacky implementation of semaphores.
2756 ------------------------------------------------------------------ */
2757
2758#include <semaphore.h>
2759
2760/* This is a terrible way to do the remapping. Plan is to import an
2761 AVL tree at some point. */
sewardj8f253ff2002-05-19 00:13:34 +00002762
2763typedef
2764 struct {
2765 pthread_mutex_t se_mx;
2766 pthread_cond_t se_cv;
2767 int count;
2768 }
2769 vg_sem_t;
2770
2771static pthread_mutex_t se_remap_mx = PTHREAD_MUTEX_INITIALIZER;
2772
2773static int se_remap_used = 0;
2774static sem_t* se_remap_orig[VG_N_SEMAPHORES];
2775static vg_sem_t se_remap_new[VG_N_SEMAPHORES];
2776
2777static vg_sem_t* se_remap ( sem_t* orig )
2778{
2779 int res, i;
2780 res = __pthread_mutex_lock(&se_remap_mx);
sewardj2d94c112002-06-03 01:25:54 +00002781 my_assert(res == 0);
sewardj8f253ff2002-05-19 00:13:34 +00002782
2783 for (i = 0; i < se_remap_used; i++) {
2784 if (se_remap_orig[i] == orig)
2785 break;
2786 }
2787 if (i == se_remap_used) {
2788 if (se_remap_used == VG_N_SEMAPHORES) {
2789 res = pthread_mutex_unlock(&se_remap_mx);
sewardj2d94c112002-06-03 01:25:54 +00002790 my_assert(res == 0);
sewardja1ac5cb2002-05-27 13:00:05 +00002791 barf("VG_N_SEMAPHORES is too low. Increase and recompile.");
sewardj8f253ff2002-05-19 00:13:34 +00002792 }
2793 se_remap_used++;
2794 se_remap_orig[i] = orig;
2795 /* printf("allocated semaphore %d\n", i); */
2796 }
2797 res = __pthread_mutex_unlock(&se_remap_mx);
sewardj2d94c112002-06-03 01:25:54 +00002798 my_assert(res == 0);
sewardj8f253ff2002-05-19 00:13:34 +00002799 return &se_remap_new[i];
2800}
2801
2802
2803int sem_init(sem_t *sem, int pshared, unsigned int value)
2804{
2805 int res;
2806 vg_sem_t* vg_sem;
2807 ensure_valgrind("sem_init");
2808 if (pshared != 0) {
sewardj4dced352002-06-04 22:54:20 +00002809 pthread_error("sem_init: unsupported pshared value");
sewardj8f253ff2002-05-19 00:13:34 +00002810 errno = ENOSYS;
2811 return -1;
2812 }
2813 vg_sem = se_remap(sem);
2814 res = pthread_mutex_init(&vg_sem->se_mx, NULL);
sewardj2d94c112002-06-03 01:25:54 +00002815 my_assert(res == 0);
sewardj8f253ff2002-05-19 00:13:34 +00002816 res = pthread_cond_init(&vg_sem->se_cv, NULL);
sewardj2d94c112002-06-03 01:25:54 +00002817 my_assert(res == 0);
sewardj8f253ff2002-05-19 00:13:34 +00002818 vg_sem->count = value;
2819 return 0;
2820}
2821
2822
2823int sem_wait ( sem_t* sem )
2824{
2825 int res;
2826 vg_sem_t* vg_sem;
2827 ensure_valgrind("sem_wait");
2828 vg_sem = se_remap(sem);
2829 res = __pthread_mutex_lock(&vg_sem->se_mx);
sewardj2d94c112002-06-03 01:25:54 +00002830 my_assert(res == 0);
sewardj8f253ff2002-05-19 00:13:34 +00002831 while (vg_sem->count == 0) {
2832 res = pthread_cond_wait(&vg_sem->se_cv, &vg_sem->se_mx);
sewardj2d94c112002-06-03 01:25:54 +00002833 my_assert(res == 0);
sewardj8f253ff2002-05-19 00:13:34 +00002834 }
2835 vg_sem->count--;
2836 res = __pthread_mutex_unlock(&vg_sem->se_mx);
sewardj2d94c112002-06-03 01:25:54 +00002837 my_assert(res == 0);
sewardj8f253ff2002-05-19 00:13:34 +00002838 return 0;
2839}
2840
2841int sem_post ( sem_t* sem )
2842{
2843 int res;
2844 vg_sem_t* vg_sem;
2845 ensure_valgrind("sem_post");
2846 vg_sem = se_remap(sem);
2847 res = __pthread_mutex_lock(&vg_sem->se_mx);
sewardj2d94c112002-06-03 01:25:54 +00002848 my_assert(res == 0);
sewardj8f253ff2002-05-19 00:13:34 +00002849 if (vg_sem->count == 0) {
2850 vg_sem->count++;
2851 res = pthread_cond_broadcast(&vg_sem->se_cv);
sewardj2d94c112002-06-03 01:25:54 +00002852 my_assert(res == 0);
sewardj8f253ff2002-05-19 00:13:34 +00002853 } else {
2854 vg_sem->count++;
2855 }
2856 res = __pthread_mutex_unlock(&vg_sem->se_mx);
sewardj2d94c112002-06-03 01:25:54 +00002857 my_assert(res == 0);
sewardj8f253ff2002-05-19 00:13:34 +00002858 return 0;
2859}
2860
2861
2862int sem_trywait ( sem_t* sem )
2863{
2864 int ret, res;
2865 vg_sem_t* vg_sem;
2866 ensure_valgrind("sem_trywait");
2867 vg_sem = se_remap(sem);
2868 res = __pthread_mutex_lock(&vg_sem->se_mx);
sewardj2d94c112002-06-03 01:25:54 +00002869 my_assert(res == 0);
sewardj8f253ff2002-05-19 00:13:34 +00002870 if (vg_sem->count > 0) {
2871 vg_sem->count--;
2872 ret = 0;
2873 } else {
2874 ret = -1;
2875 errno = EAGAIN;
2876 }
2877 res = __pthread_mutex_unlock(&vg_sem->se_mx);
sewardj2d94c112002-06-03 01:25:54 +00002878 my_assert(res == 0);
sewardj8f253ff2002-05-19 00:13:34 +00002879 return ret;
2880}
2881
2882
2883int sem_getvalue(sem_t* sem, int * sval)
2884{
2885 vg_sem_t* vg_sem;
2886 ensure_valgrind("sem_trywait");
2887 vg_sem = se_remap(sem);
2888 *sval = vg_sem->count;
2889 return 0;
2890}
2891
2892
2893int sem_destroy(sem_t * sem)
2894{
2895 kludged("sem_destroy");
2896 /* if someone waiting on this semaphore, errno = EBUSY, return -1 */
2897 return 0;
2898}
2899
sewardj9ad92d92002-10-16 19:45:06 +00002900
2901int sem_timedwait(sem_t* sem, const struct timespec *abstime)
2902{
2903 int res;
2904 vg_sem_t* vg_sem;
2905 ensure_valgrind("sem_timedwait");
2906 vg_sem = se_remap(sem);
2907 res = __pthread_mutex_lock(&vg_sem->se_mx);
2908 my_assert(res == 0);
2909 while ( vg_sem->count == 0 && res != ETIMEDOUT ) {
2910 res = pthread_cond_timedwait(&vg_sem->se_cv, &vg_sem->se_mx, abstime);
2911 }
2912 if ( vg_sem->count > 0 ) {
2913 vg_sem->count--;
2914 res = __pthread_mutex_unlock(&vg_sem->se_mx);
2915 my_assert(res == 0 );
2916 return 0;
2917 } else {
2918 res = __pthread_mutex_unlock(&vg_sem->se_mx);
2919 my_assert(res == 0 );
2920 *(__errno_location()) = ETIMEDOUT;
2921 return -1;
2922 }
2923}
2924
sewardj8f253ff2002-05-19 00:13:34 +00002925
2926/* ---------------------------------------------------------------------
sewardj2d8b3f02002-06-01 14:14:19 +00002927 Reader-writer locks.
sewardja1ac5cb2002-05-27 13:00:05 +00002928 ------------------------------------------------------------------ */
2929
sewardj2d8b3f02002-06-01 14:14:19 +00002930typedef
2931 struct {
2932 int initted; /* != 0 --> in use; sanity check only */
2933 int prefer_w; /* != 0 --> prefer writer */
2934 int nwait_r; /* # of waiting readers */
2935 int nwait_w; /* # of waiting writers */
2936 pthread_cond_t cv_r; /* for signalling readers */
2937 pthread_cond_t cv_w; /* for signalling writers */
2938 pthread_mutex_t mx;
2939 int status;
2940 /* allowed range for status: >= -1. -1 means 1 writer currently
2941 active, >= 0 means N readers currently active. */
2942 }
2943 vg_rwlock_t;
sewardja1ac5cb2002-05-27 13:00:05 +00002944
2945
2946static pthread_mutex_t rw_remap_mx = PTHREAD_MUTEX_INITIALIZER;
2947
2948static int rw_remap_used = 0;
2949static pthread_rwlock_t* rw_remap_orig[VG_N_RWLOCKS];
2950static vg_rwlock_t rw_remap_new[VG_N_RWLOCKS];
2951
sewardj2d8b3f02002-06-01 14:14:19 +00002952
2953static
2954void init_vg_rwlock ( vg_rwlock_t* vg_rwl )
2955{
2956 int res = 0;
2957 vg_rwl->initted = 1;
2958 vg_rwl->prefer_w = 1;
2959 vg_rwl->nwait_r = 0;
2960 vg_rwl->nwait_w = 0;
2961 vg_rwl->status = 0;
2962 res = pthread_mutex_init(&vg_rwl->mx, NULL);
2963 res |= pthread_cond_init(&vg_rwl->cv_r, NULL);
2964 res |= pthread_cond_init(&vg_rwl->cv_w, NULL);
sewardj2d94c112002-06-03 01:25:54 +00002965 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002966}
2967
2968
sewardja1ac5cb2002-05-27 13:00:05 +00002969/* Take the address of a LinuxThreads rwlock_t and return the shadow
2970 address of our version. Further, if the LinuxThreads version
2971 appears to have been statically initialised, do the same to the one
2972 we allocate here. The pthread_rwlock_t.__rw_readers field is set
2973 to zero by PTHREAD_RWLOCK_INITIALIZER, so we take zero as meaning
2974 uninitialised and non-zero meaning initialised.
2975*/
2976static vg_rwlock_t* rw_remap ( pthread_rwlock_t* orig )
2977{
2978 int res, i;
2979 vg_rwlock_t* vg_rwl;
2980 res = __pthread_mutex_lock(&rw_remap_mx);
sewardj2d94c112002-06-03 01:25:54 +00002981 my_assert(res == 0);
sewardja1ac5cb2002-05-27 13:00:05 +00002982
2983 for (i = 0; i < rw_remap_used; i++) {
2984 if (rw_remap_orig[i] == orig)
2985 break;
2986 }
2987 if (i == rw_remap_used) {
2988 if (rw_remap_used == VG_N_RWLOCKS) {
sewardj2d8b3f02002-06-01 14:14:19 +00002989 res = __pthread_mutex_unlock(&rw_remap_mx);
sewardj2d94c112002-06-03 01:25:54 +00002990 my_assert(res == 0);
sewardja1ac5cb2002-05-27 13:00:05 +00002991 barf("VG_N_RWLOCKS is too low. Increase and recompile.");
2992 }
2993 rw_remap_used++;
2994 rw_remap_orig[i] = orig;
sewardj2d8b3f02002-06-01 14:14:19 +00002995 rw_remap_new[i].initted = 0;
sewardja1ac5cb2002-05-27 13:00:05 +00002996 if (0) printf("allocated rwlock %d\n", i);
2997 }
2998 res = __pthread_mutex_unlock(&rw_remap_mx);
sewardj2d94c112002-06-03 01:25:54 +00002999 my_assert(res == 0);
sewardja1ac5cb2002-05-27 13:00:05 +00003000 vg_rwl = &rw_remap_new[i];
3001
sewardj2d8b3f02002-06-01 14:14:19 +00003002 /* Initialise the shadow, if required. */
sewardja1ac5cb2002-05-27 13:00:05 +00003003 if (orig->__rw_readers == 0) {
sewardja1ac5cb2002-05-27 13:00:05 +00003004 orig->__rw_readers = 1;
sewardj2d8b3f02002-06-01 14:14:19 +00003005 init_vg_rwlock(vg_rwl);
sewardja1ac5cb2002-05-27 13:00:05 +00003006 if (orig->__rw_kind == PTHREAD_RWLOCK_PREFER_READER_NP)
sewardj2d8b3f02002-06-01 14:14:19 +00003007 vg_rwl->prefer_w = 0;
sewardja1ac5cb2002-05-27 13:00:05 +00003008 }
3009
3010 return vg_rwl;
3011}
3012
3013
sewardja1ac5cb2002-05-27 13:00:05 +00003014int pthread_rwlock_init ( pthread_rwlock_t* orig,
3015 const pthread_rwlockattr_t* attr )
3016{
sewardja1ac5cb2002-05-27 13:00:05 +00003017 vg_rwlock_t* rwl;
3018 if (0) printf ("pthread_rwlock_init\n");
3019 /* Force the remapper to initialise the shadow. */
3020 orig->__rw_readers = 0;
3021 /* Install the lock preference; the remapper needs to know it. */
3022 orig->__rw_kind = PTHREAD_RWLOCK_DEFAULT_NP;
3023 if (attr)
3024 orig->__rw_kind = attr->__lockkind;
3025 rwl = rw_remap ( orig );
sewardj2d8b3f02002-06-01 14:14:19 +00003026 return 0;
sewardja1ac5cb2002-05-27 13:00:05 +00003027}
3028
sewardj2d8b3f02002-06-01 14:14:19 +00003029
3030static
3031void pthread_rwlock_rdlock_CANCEL_HDLR ( void* rwl_v )
sewardja1ac5cb2002-05-27 13:00:05 +00003032{
sewardj2d8b3f02002-06-01 14:14:19 +00003033 vg_rwlock_t* rwl = (vg_rwlock_t*)rwl_v;
3034 rwl->nwait_r--;
3035 pthread_mutex_unlock (&rwl->mx);
sewardja1ac5cb2002-05-27 13:00:05 +00003036}
3037
sewardj2d8b3f02002-06-01 14:14:19 +00003038
sewardja1ac5cb2002-05-27 13:00:05 +00003039int pthread_rwlock_rdlock ( pthread_rwlock_t* orig )
3040{
3041 int res;
3042 vg_rwlock_t* rwl;
3043 if (0) printf ("pthread_rwlock_rdlock\n");
3044 rwl = rw_remap ( orig );
sewardj2d8b3f02002-06-01 14:14:19 +00003045 res = __pthread_mutex_lock(&rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00003046 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00003047 if (!rwl->initted) {
3048 res = __pthread_mutex_unlock(&rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00003049 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00003050 return EINVAL;
3051 }
3052 if (rwl->status < 0) {
sewardj2d94c112002-06-03 01:25:54 +00003053 my_assert(rwl->status == -1);
sewardj2d8b3f02002-06-01 14:14:19 +00003054 rwl->nwait_r++;
3055 pthread_cleanup_push( pthread_rwlock_rdlock_CANCEL_HDLR, rwl );
3056 while (1) {
3057 if (rwl->status == 0) break;
3058 res = pthread_cond_wait(&rwl->cv_r, &rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00003059 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00003060 }
3061 pthread_cleanup_pop(0);
3062 rwl->nwait_r--;
3063 }
sewardj2d94c112002-06-03 01:25:54 +00003064 my_assert(rwl->status >= 0);
sewardj2d8b3f02002-06-01 14:14:19 +00003065 rwl->status++;
3066 res = __pthread_mutex_unlock(&rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00003067 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00003068 return 0;
sewardja1ac5cb2002-05-27 13:00:05 +00003069}
3070
sewardj2d8b3f02002-06-01 14:14:19 +00003071
sewardja1ac5cb2002-05-27 13:00:05 +00003072int pthread_rwlock_tryrdlock ( pthread_rwlock_t* orig )
3073{
3074 int res;
3075 vg_rwlock_t* rwl;
3076 if (0) printf ("pthread_rwlock_tryrdlock\n");
3077 rwl = rw_remap ( orig );
sewardj2d8b3f02002-06-01 14:14:19 +00003078 res = __pthread_mutex_lock(&rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00003079 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00003080 if (!rwl->initted) {
3081 res = __pthread_mutex_unlock(&rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00003082 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00003083 return EINVAL;
3084 }
3085 if (rwl->status == -1) {
3086 /* Writer active; we have to give up. */
3087 res = __pthread_mutex_unlock(&rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00003088 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00003089 return EBUSY;
3090 }
3091 /* Success */
sewardj2d94c112002-06-03 01:25:54 +00003092 my_assert(rwl->status >= 0);
sewardj2d8b3f02002-06-01 14:14:19 +00003093 rwl->status++;
3094 res = __pthread_mutex_unlock(&rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00003095 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00003096 return 0;
sewardja1ac5cb2002-05-27 13:00:05 +00003097}
3098
sewardj2d8b3f02002-06-01 14:14:19 +00003099
3100static
3101void pthread_rwlock_wrlock_CANCEL_HDLR ( void* rwl_v )
3102{
3103 vg_rwlock_t* rwl = (vg_rwlock_t*)rwl_v;
3104 rwl->nwait_w--;
3105 pthread_mutex_unlock (&rwl->mx);
3106}
3107
3108
sewardja1ac5cb2002-05-27 13:00:05 +00003109int pthread_rwlock_wrlock ( pthread_rwlock_t* orig )
3110{
3111 int res;
3112 vg_rwlock_t* rwl;
3113 if (0) printf ("pthread_rwlock_wrlock\n");
3114 rwl = rw_remap ( orig );
sewardj2d8b3f02002-06-01 14:14:19 +00003115 res = __pthread_mutex_lock(&rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00003116 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00003117 if (!rwl->initted) {
3118 res = __pthread_mutex_unlock(&rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00003119 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00003120 return EINVAL;
3121 }
3122 if (rwl->status != 0) {
3123 rwl->nwait_w++;
3124 pthread_cleanup_push( pthread_rwlock_wrlock_CANCEL_HDLR, rwl );
3125 while (1) {
3126 if (rwl->status == 0) break;
3127 res = pthread_cond_wait(&rwl->cv_w, &rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00003128 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00003129 }
3130 pthread_cleanup_pop(0);
3131 rwl->nwait_w--;
3132 }
sewardj2d94c112002-06-03 01:25:54 +00003133 my_assert(rwl->status == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00003134 rwl->status = -1;
3135 res = __pthread_mutex_unlock(&rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00003136 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00003137 return 0;
sewardja1ac5cb2002-05-27 13:00:05 +00003138}
3139
sewardj2d8b3f02002-06-01 14:14:19 +00003140
sewardja1ac5cb2002-05-27 13:00:05 +00003141int pthread_rwlock_trywrlock ( pthread_rwlock_t* orig )
3142{
3143 int res;
3144 vg_rwlock_t* rwl;
sewardj2d8b3f02002-06-01 14:14:19 +00003145 if (0) printf ("pthread_wrlock_trywrlock\n");
sewardja1ac5cb2002-05-27 13:00:05 +00003146 rwl = rw_remap ( orig );
sewardj2d8b3f02002-06-01 14:14:19 +00003147 res = __pthread_mutex_lock(&rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00003148 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00003149 if (!rwl->initted) {
3150 res = __pthread_mutex_unlock(&rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00003151 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00003152 return EINVAL;
3153 }
3154 if (rwl->status != 0) {
3155 /* Reader(s) or a writer active; we have to give up. */
3156 res = __pthread_mutex_unlock(&rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00003157 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00003158 return EBUSY;
3159 }
3160 /* Success */
sewardj2d94c112002-06-03 01:25:54 +00003161 my_assert(rwl->status == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00003162 rwl->status = -1;
3163 res = __pthread_mutex_unlock(&rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00003164 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00003165 return 0;
sewardja1ac5cb2002-05-27 13:00:05 +00003166}
3167
sewardj2d8b3f02002-06-01 14:14:19 +00003168
sewardja1ac5cb2002-05-27 13:00:05 +00003169int pthread_rwlock_unlock ( pthread_rwlock_t* orig )
3170{
3171 int res;
3172 vg_rwlock_t* rwl;
3173 if (0) printf ("pthread_rwlock_unlock\n");
3174 rwl = rw_remap ( orig );
sewardj2d8b3f02002-06-01 14:14:19 +00003175 rwl = rw_remap ( orig );
3176 res = __pthread_mutex_lock(&rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00003177 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00003178 if (!rwl->initted) {
3179 res = __pthread_mutex_unlock(&rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00003180 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00003181 return EINVAL;
3182 }
3183 if (rwl->status == 0) {
3184 res = __pthread_mutex_unlock(&rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00003185 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00003186 return EPERM;
3187 }
sewardj2d94c112002-06-03 01:25:54 +00003188 my_assert(rwl->status != 0);
sewardj2d8b3f02002-06-01 14:14:19 +00003189 if (rwl->status == -1) {
3190 rwl->status = 0;
3191 } else {
sewardj2d94c112002-06-03 01:25:54 +00003192 my_assert(rwl->status > 0);
sewardj2d8b3f02002-06-01 14:14:19 +00003193 rwl->status--;
3194 }
3195
sewardj2d94c112002-06-03 01:25:54 +00003196 my_assert(rwl->status >= 0);
sewardj2d8b3f02002-06-01 14:14:19 +00003197
3198 if (rwl->prefer_w) {
3199
3200 /* Favour waiting writers, if any. */
3201 if (rwl->nwait_w > 0) {
3202 /* Writer(s) are waiting. */
3203 if (rwl->status == 0) {
3204 /* We can let a writer in. */
3205 res = pthread_cond_signal(&rwl->cv_w);
sewardj2d94c112002-06-03 01:25:54 +00003206 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00003207 } else {
3208 /* There are still readers active. Do nothing; eventually
3209 they will disappear, at which point a writer will be
3210 admitted. */
3211 }
3212 }
3213 else
3214 /* No waiting writers. */
3215 if (rwl->nwait_r > 0) {
3216 /* Let in a waiting reader. */
3217 res = pthread_cond_signal(&rwl->cv_r);
sewardj2d94c112002-06-03 01:25:54 +00003218 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00003219 }
3220
3221 } else {
3222
3223 /* Favour waiting readers, if any. */
3224 if (rwl->nwait_r > 0) {
3225 /* Reader(s) are waiting; let one in. */
3226 res = pthread_cond_signal(&rwl->cv_r);
sewardj2d94c112002-06-03 01:25:54 +00003227 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00003228 }
3229 else
3230 /* No waiting readers. */
3231 if (rwl->nwait_w > 0 && rwl->status == 0) {
3232 /* We have waiting writers and no active readers; let a
3233 writer in. */
3234 res = pthread_cond_signal(&rwl->cv_w);
sewardj2d94c112002-06-03 01:25:54 +00003235 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00003236 }
3237 }
3238
3239 res = __pthread_mutex_unlock(&rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00003240 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00003241 return 0;
3242}
3243
3244
3245int pthread_rwlock_destroy ( pthread_rwlock_t *orig )
3246{
3247 int res;
3248 vg_rwlock_t* rwl;
3249 if (0) printf ("pthread_rwlock_destroy\n");
3250 rwl = rw_remap ( orig );
3251 res = __pthread_mutex_lock(&rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00003252 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00003253 if (!rwl->initted) {
3254 res = __pthread_mutex_unlock(&rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00003255 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00003256 return EINVAL;
3257 }
3258 if (rwl->status != 0 || rwl->nwait_r > 0 || rwl->nwait_w > 0) {
3259 res = __pthread_mutex_unlock(&rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00003260 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00003261 return EBUSY;
3262 }
3263 rwl->initted = 0;
3264 res = __pthread_mutex_unlock(&rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00003265 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00003266 return 0;
sewardja1ac5cb2002-05-27 13:00:05 +00003267}
3268
3269
sewardj47e4e312002-06-18 09:24:34 +00003270/* Copied directly from LinuxThreads. */
3271int
3272pthread_rwlockattr_init (pthread_rwlockattr_t *attr)
3273{
3274 attr->__lockkind = 0;
3275 attr->__pshared = PTHREAD_PROCESS_PRIVATE;
3276
3277 return 0;
3278}
3279
sewardjfe18eb82002-07-13 12:58:44 +00003280/* Copied directly from LinuxThreads. */
3281int
sewardj5706bfa2002-12-08 23:42:17 +00003282pthread_rwlockattr_destroy (pthread_rwlockattr_t *attr)
3283{
3284 return 0;
3285}
3286
3287/* Copied directly from LinuxThreads. */
3288int
sewardjfe18eb82002-07-13 12:58:44 +00003289pthread_rwlockattr_setpshared (pthread_rwlockattr_t *attr, int pshared)
3290{
3291 if (pshared != PTHREAD_PROCESS_PRIVATE && pshared != PTHREAD_PROCESS_SHARED)
3292 return EINVAL;
3293
3294 /* For now it is not possible to shared a conditional variable. */
3295 if (pshared != PTHREAD_PROCESS_PRIVATE)
3296 return ENOSYS;
3297
3298 attr->__pshared = pshared;
3299
3300 return 0;
3301}
3302
sewardj47e4e312002-06-18 09:24:34 +00003303
sewardja1ac5cb2002-05-27 13:00:05 +00003304/* ---------------------------------------------------------------------
sewardjd5bef572002-10-23 21:49:33 +00003305 Make SYSV IPC not block everything
3306 ------------------------------------------------------------------ */
3307
3308#include <sys/ipc.h>
3309#include <sys/msg.h>
3310#include <asm/ipc.h> /* for ipc_kludge */
3311
3312static inline int sys_ipc(unsigned call, int first, int second, int third, void *ptr)
3313{
3314 return my_do_syscall5(__NR_ipc, call, first, second, third, (int)ptr);
3315}
3316
3317/* Turn a blocking msgsnd() into a polling non-blocking one, so that
3318 other threads make progress */
sewardjf220ccc2002-10-23 21:53:49 +00003319int VGL_(msgsnd)(int msgid, const void *msgp, size_t msgsz, int msgflg)
sewardjd5bef572002-10-23 21:49:33 +00003320{
3321 struct vki_timespec nanosleep_interval;
3322 int err;
3323
3324 ensure_valgrind("msgsnd");
3325
3326 nanosleep_interval.tv_sec = 0;
3327 nanosleep_interval.tv_nsec = 13 * 1000 * 1000; /* 13 milliseconds */
3328
3329 if (msgflg & IPC_NOWAIT) {
3330 /* If we aren't blocking anyway, just do it */
3331 err = sys_ipc(11, msgid, msgsz, msgflg, (void *)msgp);
3332 } else {
3333 /* Otherwise poll on the queue to let other things run */
3334 for(;;) {
3335 err = sys_ipc(11, msgid, msgsz, msgflg | IPC_NOWAIT, (void *)msgp);
3336
3337 if (err != -EAGAIN)
3338 break;
3339
3340 (void)my_do_syscall2(__NR_nanosleep,
3341 (int)(&nanosleep_interval), (int)NULL);
3342 }
3343 }
3344
3345 if (is_kerror(err)) {
3346 *(__errno_location()) = -err;
3347 return -1;
3348 }
3349 return 0;
3350}
3351
3352/* Turn a blocking msgrcv() into a polling non-blocking one, so that
3353 other threads make progress */
sewardjf220ccc2002-10-23 21:53:49 +00003354int VGL_(msgrcv)( int msqid, void *msgp, size_t msgsz, long msgtyp, int msgflg )
sewardjd5bef572002-10-23 21:49:33 +00003355{
3356 struct vki_timespec nanosleep_interval;
3357 int err;
3358 struct ipc_kludge tmp;
3359
3360 ensure_valgrind("msgrcv");
3361
3362 nanosleep_interval.tv_sec = 0;
3363 nanosleep_interval.tv_nsec = 13 * 1000 * 1000; /* 13 milliseconds */
3364
3365 tmp.msgp = msgp;
3366 tmp.msgtyp = msgtyp;
3367
3368 if (msgflg & IPC_NOWAIT) {
3369 /* If we aren't blocking anyway, just do it */
3370 err = sys_ipc(12, msqid, msgsz, msgflg, &tmp );
3371 } else {
3372 /* Otherwise poll on the queue to let other things run */
3373 for(;;) {
3374 err = sys_ipc(12, msqid, msgsz, msgflg | IPC_NOWAIT, &tmp );
3375
3376 if (err != -ENOMSG)
3377 break;
3378
3379 (void)my_do_syscall2(__NR_nanosleep,
3380 (int)(&nanosleep_interval), (int)NULL);
3381 }
3382 }
3383
3384 if (is_kerror(err)) {
3385 *(__errno_location()) = -err;
3386 return -1;
3387 }
3388
sewardj17c79772003-02-23 03:00:29 +00003389 return err;
sewardjd5bef572002-10-23 21:49:33 +00003390}
3391
3392
3393
3394/* ---------------------------------------------------------------------
sewardj3b13f0e2002-04-25 20:17:29 +00003395 B'stard.
3396 ------------------------------------------------------------------ */
3397
3398# define strong_alias(name, aliasname) \
3399 extern __typeof (name) aliasname __attribute__ ((alias (#name)));
3400
sewardj5905fae2002-04-26 13:25:00 +00003401# define weak_alias(name, aliasname) \
3402 extern __typeof (name) aliasname __attribute__ ((weak, alias (#name)));
sewardj3b13f0e2002-04-25 20:17:29 +00003403
sewardj5905fae2002-04-26 13:25:00 +00003404strong_alias(__pthread_mutex_lock, pthread_mutex_lock)
3405strong_alias(__pthread_mutex_trylock, pthread_mutex_trylock)
3406strong_alias(__pthread_mutex_unlock, pthread_mutex_unlock)
3407strong_alias(__pthread_mutexattr_init, pthread_mutexattr_init)
3408 weak_alias(__pthread_mutexattr_settype, pthread_mutexattr_settype)
3409strong_alias(__pthread_mutex_init, pthread_mutex_init)
3410strong_alias(__pthread_mutexattr_destroy, pthread_mutexattr_destroy)
3411strong_alias(__pthread_mutex_destroy, pthread_mutex_destroy)
3412strong_alias(__pthread_once, pthread_once)
3413strong_alias(__pthread_atfork, pthread_atfork)
3414strong_alias(__pthread_key_create, pthread_key_create)
3415strong_alias(__pthread_getspecific, pthread_getspecific)
3416strong_alias(__pthread_setspecific, pthread_setspecific)
3417
sewardjd529a442002-05-04 19:49:21 +00003418#ifndef GLIBC_2_1
sewardj3b13f0e2002-04-25 20:17:29 +00003419strong_alias(sigaction, __sigaction)
sewardjd529a442002-05-04 19:49:21 +00003420#endif
3421
sewardj5905fae2002-04-26 13:25:00 +00003422strong_alias(close, __close)
sewardj3b13f0e2002-04-25 20:17:29 +00003423strong_alias(fcntl, __fcntl)
sewardj5905fae2002-04-26 13:25:00 +00003424strong_alias(lseek, __lseek)
3425strong_alias(open, __open)
3426strong_alias(open64, __open64)
sewardj5905fae2002-04-26 13:25:00 +00003427strong_alias(read, __read)
3428strong_alias(wait, __wait)
3429strong_alias(write, __write)
sewardj3b13f0e2002-04-25 20:17:29 +00003430strong_alias(connect, __connect)
sewardj5905fae2002-04-26 13:25:00 +00003431strong_alias(send, __send)
3432
sewardj726c4122002-05-16 23:39:10 +00003433weak_alias (__pread64, pread64)
sewardja18e2102002-05-18 10:43:22 +00003434weak_alias (__pwrite64, pwrite64)
sewardj5905fae2002-04-26 13:25:00 +00003435weak_alias(__fork, fork)
njn25e49d8e72002-09-23 09:36:25 +00003436weak_alias(__vfork, vfork)
sewardj7f6456d2002-05-21 00:51:21 +00003437
sewardjf0b06452002-06-04 08:38:04 +00003438weak_alias (__pthread_kill_other_threads_np, pthread_kill_other_threads_np)
sewardj3b13f0e2002-04-25 20:17:29 +00003439
3440/*--------------------------------------------------*/
3441
sewardj5905fae2002-04-26 13:25:00 +00003442weak_alias(pthread_rwlock_rdlock, __pthread_rwlock_rdlock)
sewardj5905fae2002-04-26 13:25:00 +00003443weak_alias(pthread_rwlock_unlock, __pthread_rwlock_unlock)
sewardj262b0292002-05-01 00:03:16 +00003444weak_alias(pthread_rwlock_wrlock, __pthread_rwlock_wrlock)
sewardj060b04f2002-04-26 21:01:13 +00003445
sewardja1ac5cb2002-05-27 13:00:05 +00003446weak_alias(pthread_rwlock_destroy, __pthread_rwlock_destroy)
3447weak_alias(pthread_rwlock_init, __pthread_rwlock_init)
3448weak_alias(pthread_rwlock_tryrdlock, __pthread_rwlock_tryrdlock)
3449weak_alias(pthread_rwlock_trywrlock, __pthread_rwlock_trywrlock)
3450
sewardj060b04f2002-04-26 21:01:13 +00003451
sewardj3b13f0e2002-04-25 20:17:29 +00003452/* I've no idea what these are, but they get called quite a lot.
3453 Anybody know? */
3454
3455#undef _IO_flockfile
3456void _IO_flockfile ( _IO_FILE * file )
3457{
sewardj853f55d2002-04-26 00:27:53 +00003458 pthread_mutex_lock(file->_lock);
sewardj3b13f0e2002-04-25 20:17:29 +00003459}
sewardj5905fae2002-04-26 13:25:00 +00003460weak_alias(_IO_flockfile, flockfile);
3461
sewardj3b13f0e2002-04-25 20:17:29 +00003462
3463#undef _IO_funlockfile
3464void _IO_funlockfile ( _IO_FILE * file )
3465{
sewardj853f55d2002-04-26 00:27:53 +00003466 pthread_mutex_unlock(file->_lock);
sewardj3b13f0e2002-04-25 20:17:29 +00003467}
sewardj5905fae2002-04-26 13:25:00 +00003468weak_alias(_IO_funlockfile, funlockfile);
3469
sewardj3b13f0e2002-04-25 20:17:29 +00003470
sewardjd4f2c712002-04-30 10:20:10 +00003471/* This doesn't seem to be needed to simulate libpthread.so's external
3472 interface, but many people complain about its absence. */
3473
3474strong_alias(__pthread_mutexattr_settype, __pthread_mutexattr_setkind_np)
3475weak_alias(__pthread_mutexattr_setkind_np, pthread_mutexattr_setkind_np)
sewardj439d45e2002-05-03 20:43:10 +00003476
3477
3478/*--------------------------------------------------------------------*/
3479/*--- end vg_libpthread.c ---*/
3480/*--------------------------------------------------------------------*/