blob: 70abb179dffda6f75e949043f9e679b4c2e1adcf [file] [log] [blame]
sewardje663cb92002-04-12 10:26:32 +00001
sewardj439d45e2002-05-03 20:43:10 +00002/*--------------------------------------------------------------------*/
3/*--- A replacement for the standard libpthread.so. ---*/
4/*--- vg_libpthread.c ---*/
5/*--------------------------------------------------------------------*/
6
7/*
njnc9539842002-10-02 13:26:35 +00008 This file is part of Valgrind, an extensible x86 protected-mode
9 emulator for monitoring program execution on x86-Unixes.
sewardj439d45e2002-05-03 20:43:10 +000010
11 Copyright (C) 2000-2002 Julian Seward
12 jseward@acm.org
13
14 This program is free software; you can redistribute it and/or
15 modify it under the terms of the GNU General Public License as
16 published by the Free Software Foundation; either version 2 of the
17 License, or (at your option) any later version.
18
19 This program is distributed in the hope that it will be useful, but
20 WITHOUT ANY WARRANTY; without even the implied warranty of
21 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
22 General Public License for more details.
23
24 You should have received a copy of the GNU General Public License
25 along with this program; if not, write to the Free Software
26 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
27 02111-1307, USA.
28
njn25e49d8e72002-09-23 09:36:25 +000029 The GNU General Public License is contained in the file COPYING.
sewardj439d45e2002-05-03 20:43:10 +000030*/
31
32/* ALL THIS CODE RUNS ON THE SIMULATED CPU.
33
34 This is a replacement for the standard libpthread.so. It is loaded
sewardje663cb92002-04-12 10:26:32 +000035 as part of the client's image (if required) and directs pthread
36 calls through to Valgrind's request mechanism.
37
38 A couple of caveats.
39
40 1. Since it's a binary-compatible replacement for an existing library,
41 we must take care to used exactly the same data layouts, etc, as
42 the standard pthread.so does.
43
44 2. Since this runs as part of the client, there are no specific
45 restrictions on what headers etc we can include, so long as
46 this libpthread.so does not end up having dependencies on .so's
47 which the real one doesn't.
48
49 Later ... it appears we cannot call file-related stuff in libc here,
50 perhaps fair enough. Be careful what you call from here. Even exit()
51 doesn't work (gives infinite recursion and then stack overflow); hence
52 myexit(). Also fprintf doesn't seem safe.
53*/
54
55#include "valgrind.h" /* For the request-passing mechanism */
56#include "vg_include.h" /* For the VG_USERREQ__* constants */
57
sewardja1ac5cb2002-05-27 13:00:05 +000058#define __USE_UNIX98
59#include <sys/types.h>
60#include <pthread.h>
61#undef __USE_UNIX98
62
sewardje663cb92002-04-12 10:26:32 +000063#include <unistd.h>
64#include <string.h>
sewardj2a1dcce2002-04-22 12:45:25 +000065#ifdef GLIBC_2_1
66#include <sys/time.h>
67#endif
sewardje663cb92002-04-12 10:26:32 +000068
sewardj2d94c112002-06-03 01:25:54 +000069#include <stdio.h>
70
sewardj705d3cb2002-05-23 13:13:12 +000071
72/* ---------------------------------------------------------------------
73 Forwardses.
74 ------------------------------------------------------------------ */
75
76static void wait_for_fd_to_be_readable_or_erring ( int fd );
77
sewardj9a2224b2002-06-19 10:17:40 +000078static
sewardj08c7f012002-10-07 23:56:55 +000079int my_do_syscall1 ( int syscallno, int arg1 );
80
81static
sewardj9a2224b2002-06-19 10:17:40 +000082int my_do_syscall2 ( int syscallno,
83 int arg1, int arg2 );
84
sewardj08c7f012002-10-07 23:56:55 +000085static
86int my_do_syscall3 ( int syscallno,
87 int arg1, int arg2, int arg3 );
88
89
90#ifdef GLIBC_2_3
91 /* kludge by JRS (not from glibc) ... */
92 typedef void* __locale_t;
93
94 /* Copied from locale/locale.h in glibc-2.2.93 sources */
95 /* This value can be passed to `uselocale' and may be returned by
96 it. Passing this value to any other function has undefined
97 behavior. */
98# define LC_GLOBAL_LOCALE ((__locale_t) -1L)
99 extern __locale_t __uselocale ( __locale_t );
100#endif
101
sewardj705d3cb2002-05-23 13:13:12 +0000102
sewardje663cb92002-04-12 10:26:32 +0000103/* ---------------------------------------------------------------------
104 Helpers. We have to be pretty self-sufficient.
105 ------------------------------------------------------------------ */
106
sewardj436e0582002-04-26 14:31:40 +0000107/* Number of times any given error message is printed. */
108#define N_MOANS 3
109
sewardj45b4b372002-04-16 22:50:32 +0000110/* Extract from Valgrind the value of VG_(clo_trace_pthread_level).
111 Returns 0 (none) if not running on Valgrind. */
112static
113int get_pt_trace_level ( void )
114{
115 int res;
116 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
117 VG_USERREQ__GET_PTHREAD_TRACE_LEVEL,
118 0, 0, 0, 0);
119 return res;
120}
121
sewardje663cb92002-04-12 10:26:32 +0000122static
sewardj2d94c112002-06-03 01:25:54 +0000123void my_exit ( int arg )
sewardje663cb92002-04-12 10:26:32 +0000124{
sewardj08c7f012002-10-07 23:56:55 +0000125 my_do_syscall1(__NR_exit, arg);
126 /*NOTREACHED*/
sewardje663cb92002-04-12 10:26:32 +0000127}
128
sewardj08c7f012002-10-07 23:56:55 +0000129static
130void my_write ( int fd, const void *buf, int count )
131{
132 my_do_syscall3(__NR_write, fd, (int)buf, count );
133}
sewardje663cb92002-04-12 10:26:32 +0000134
sewardj68b2dd92002-05-10 21:03:56 +0000135/* We need this guy -- it's in valgrind.so. */
136extern void VG_(startup) ( void );
137
138
139/* Just start up Valgrind if it's not already going. VG_(startup)()
140 detects and ignores second and subsequent calls. */
sewardj604ec3c2002-04-18 22:38:41 +0000141static __inline__
sewardje663cb92002-04-12 10:26:32 +0000142void ensure_valgrind ( char* caller )
143{
sewardj68b2dd92002-05-10 21:03:56 +0000144 VG_(startup)();
sewardje663cb92002-04-12 10:26:32 +0000145}
146
sewardjbea1caa2002-05-10 23:20:58 +0000147/* While we're at it ... hook our own startup function into this
148 game. */
149__asm__ (
150 ".section .init\n"
151 "\tcall vgPlain_startup"
152);
153
sewardje663cb92002-04-12 10:26:32 +0000154
155static
sewardj3b5d8862002-04-20 13:53:23 +0000156__attribute__((noreturn))
sewardje663cb92002-04-12 10:26:32 +0000157void barf ( char* str )
158{
159 char buf[100];
160 buf[0] = 0;
sewardj439d45e2002-05-03 20:43:10 +0000161 strcat(buf, "\nvalgrind's libpthread.so: ");
sewardje663cb92002-04-12 10:26:32 +0000162 strcat(buf, str);
163 strcat(buf, "\n\n");
sewardj08c7f012002-10-07 23:56:55 +0000164 my_write(2, buf, strlen(buf));
sewardj2d94c112002-06-03 01:25:54 +0000165 my_exit(1);
sewardj3b5d8862002-04-20 13:53:23 +0000166 /* We have to persuade gcc into believing this doesn't return. */
167 while (1) { };
sewardje663cb92002-04-12 10:26:32 +0000168}
169
170
sewardj2a3d28c2002-04-14 13:27:00 +0000171static void ignored ( char* msg )
172{
sewardj436e0582002-04-26 14:31:40 +0000173 if (get_pt_trace_level() >= 0) {
sewardj439d45e2002-05-03 20:43:10 +0000174 char* ig = "valgrind's libpthread.so: IGNORED call to: ";
sewardj08c7f012002-10-07 23:56:55 +0000175 my_write(2, ig, strlen(ig));
176 my_write(2, msg, strlen(msg));
sewardj45b4b372002-04-16 22:50:32 +0000177 ig = "\n";
sewardj08c7f012002-10-07 23:56:55 +0000178 my_write(2, ig, strlen(ig));
sewardj45b4b372002-04-16 22:50:32 +0000179 }
sewardj2a3d28c2002-04-14 13:27:00 +0000180}
181
sewardj30671ff2002-04-21 00:13:57 +0000182static void kludged ( char* msg )
183{
sewardj436e0582002-04-26 14:31:40 +0000184 if (get_pt_trace_level() >= 0) {
sewardj439d45e2002-05-03 20:43:10 +0000185 char* ig = "valgrind's libpthread.so: KLUDGED call to: ";
sewardj08c7f012002-10-07 23:56:55 +0000186 my_write(2, ig, strlen(ig));
187 my_write(2, msg, strlen(msg));
sewardj439d45e2002-05-03 20:43:10 +0000188 ig = "\n";
sewardj08c7f012002-10-07 23:56:55 +0000189 my_write(2, ig, strlen(ig));
sewardj439d45e2002-05-03 20:43:10 +0000190 }
191}
192
193static void not_inside ( char* msg )
194{
sewardj68b2dd92002-05-10 21:03:56 +0000195 VG_(startup)();
sewardj30671ff2002-04-21 00:13:57 +0000196}
197
sewardjccef2e62002-05-29 19:26:32 +0000198__attribute__((noreturn))
sewardj3b13f0e2002-04-25 20:17:29 +0000199void vgPlain_unimp ( char* what )
200{
sewardj439d45e2002-05-03 20:43:10 +0000201 char* ig = "valgrind's libpthread.so: UNIMPLEMENTED FUNCTION: ";
sewardj08c7f012002-10-07 23:56:55 +0000202 my_write(2, ig, strlen(ig));
203 my_write(2, what, strlen(what));
sewardj3b13f0e2002-04-25 20:17:29 +0000204 ig = "\n";
sewardj08c7f012002-10-07 23:56:55 +0000205 my_write(2, ig, strlen(ig));
sewardj3b13f0e2002-04-25 20:17:29 +0000206 barf("Please report this bug to me at: jseward@acm.org");
207}
208
sewardje663cb92002-04-12 10:26:32 +0000209
sewardj457cc472002-06-03 23:13:47 +0000210static
sewardj2d94c112002-06-03 01:25:54 +0000211void my_assert_fail ( Char* expr, Char* file, Int line, Char* fn )
212{
213 static Bool entered = False;
214 if (entered)
215 my_exit(2);
216 entered = True;
217 fprintf(stderr, "\n%s: %s:%d (%s): Assertion `%s' failed.\n",
218 "valgrind", file, line, fn, expr );
219 fprintf(stderr, "Please report this bug to me at: %s\n\n",
220 VG_EMAIL_ADDR);
221 my_exit(1);
222}
223
224#define MY__STRING(__str) #__str
225
226#define my_assert(expr) \
227 ((void) ((expr) ? 0 : \
228 (my_assert_fail (MY__STRING(expr), \
229 __FILE__, __LINE__, \
230 __PRETTY_FUNCTION__), 0)))
231
232
sewardje663cb92002-04-12 10:26:32 +0000233/* ---------------------------------------------------------------------
234 Pass pthread_ calls to Valgrind's request mechanism.
235 ------------------------------------------------------------------ */
236
sewardjf8f819e2002-04-17 23:21:37 +0000237#include <errno.h>
sewardj5f07b662002-04-23 16:52:51 +0000238#include <sys/time.h> /* gettimeofday */
sewardjf8f819e2002-04-17 23:21:37 +0000239
sewardja1ac5cb2002-05-27 13:00:05 +0000240
sewardjf8f819e2002-04-17 23:21:37 +0000241/* ---------------------------------------------------
sewardj4dced352002-06-04 22:54:20 +0000242 Ummm ..
243 ------------------------------------------------ */
244
245static
246void pthread_error ( const char* msg )
247{
248 int res;
249 VALGRIND_MAGIC_SEQUENCE(res, 0,
250 VG_USERREQ__PTHREAD_ERROR,
251 msg, 0, 0, 0);
252}
253
254
255/* ---------------------------------------------------
sewardjf8f819e2002-04-17 23:21:37 +0000256 THREAD ATTRIBUTES
257 ------------------------------------------------ */
258
sewardj6af4b5d2002-04-16 04:40:49 +0000259int pthread_attr_init(pthread_attr_t *attr)
260{
sewardj7989d0c2002-05-28 11:00:01 +0000261 /* Just initialise the fields which we might look at. */
262 attr->__detachstate = PTHREAD_CREATE_JOINABLE;
sewardj6af4b5d2002-04-16 04:40:49 +0000263 return 0;
264}
265
266int pthread_attr_setdetachstate(pthread_attr_t *attr, int detachstate)
267{
sewardj7989d0c2002-05-28 11:00:01 +0000268 if (detachstate != PTHREAD_CREATE_JOINABLE
sewardj4dced352002-06-04 22:54:20 +0000269 && detachstate != PTHREAD_CREATE_DETACHED) {
270 pthread_error("pthread_attr_setdetachstate: "
271 "detachstate is invalid");
sewardj7989d0c2002-05-28 11:00:01 +0000272 return EINVAL;
sewardj4dced352002-06-04 22:54:20 +0000273 }
sewardj7989d0c2002-05-28 11:00:01 +0000274 attr->__detachstate = detachstate;
sewardj6af4b5d2002-04-16 04:40:49 +0000275 return 0;
276}
277
njn25e49d8e72002-09-23 09:36:25 +0000278int pthread_attr_getdetachstate(const pthread_attr_t *attr, int *detachstate)
279{
280 *detachstate = attr->__detachstate;
281 return 0;
282}
283
sewardj30671ff2002-04-21 00:13:57 +0000284int pthread_attr_setinheritsched(pthread_attr_t *attr, int inherit)
285{
sewardj436e0582002-04-26 14:31:40 +0000286 static int moans = N_MOANS;
287 if (moans-- > 0)
288 ignored("pthread_attr_setinheritsched");
sewardj30671ff2002-04-21 00:13:57 +0000289 return 0;
290}
sewardj6af4b5d2002-04-16 04:40:49 +0000291
sewardj0286dd52002-05-16 20:51:15 +0000292__attribute__((weak))
293int pthread_attr_setstacksize (pthread_attr_t *__attr,
294 size_t __stacksize)
295{
sewardja18e2102002-05-18 10:43:22 +0000296 size_t limit;
sewardj3d7c8d62002-06-04 20:59:16 +0000297 char buf[1024];
sewardj0286dd52002-05-16 20:51:15 +0000298 ensure_valgrind("pthread_attr_setstacksize");
sewardja18e2102002-05-18 10:43:22 +0000299 limit = VG_PTHREAD_STACK_SIZE - VG_AR_CLIENT_STACKBASE_REDZONE_SZB
300 - 1000; /* paranoia */
301 if (__stacksize < limit)
sewardj0286dd52002-05-16 20:51:15 +0000302 return 0;
sewardj3d7c8d62002-06-04 20:59:16 +0000303 snprintf(buf, sizeof(buf), "pthread_attr_setstacksize: "
304 "requested size %d >= VG_PTHREAD_STACK_SIZE\n "
305 "edit vg_include.h and rebuild.", __stacksize);
306 buf[sizeof(buf)-1] = '\0'; /* Make sure it is zero terminated */
307 barf(buf);
sewardj0286dd52002-05-16 20:51:15 +0000308}
309
310
sewardj30671ff2002-04-21 00:13:57 +0000311/* This is completely bogus. */
312int pthread_attr_getschedparam(const pthread_attr_t *attr,
313 struct sched_param *param)
314{
sewardj436e0582002-04-26 14:31:40 +0000315 static int moans = N_MOANS;
316 if (moans-- > 0)
317 kludged("pthread_attr_getschedparam");
sewardj3e909ce2002-06-03 13:27:15 +0000318# ifdef HAVE_SCHED_PRIORITY
sewardj72d58482002-04-24 02:20:20 +0000319 if (param) param->sched_priority = 0; /* who knows */
320# else
sewardj30671ff2002-04-21 00:13:57 +0000321 if (param) param->__sched_priority = 0; /* who knows */
sewardj72d58482002-04-24 02:20:20 +0000322# endif
sewardj30671ff2002-04-21 00:13:57 +0000323 return 0;
324}
325
326int pthread_attr_setschedparam(pthread_attr_t *attr,
327 const struct sched_param *param)
328{
sewardj436e0582002-04-26 14:31:40 +0000329 static int moans = N_MOANS;
330 if (moans-- > 0)
331 ignored("pthread_attr_setschedparam");
sewardj30671ff2002-04-21 00:13:57 +0000332 return 0;
333}
334
335int pthread_attr_destroy(pthread_attr_t *attr)
336{
sewardj436e0582002-04-26 14:31:40 +0000337 static int moans = N_MOANS;
338 if (moans-- > 0)
339 ignored("pthread_attr_destroy");
sewardj30671ff2002-04-21 00:13:57 +0000340 return 0;
341}
sewardjf8f819e2002-04-17 23:21:37 +0000342
sewardj0d844232002-06-02 09:29:31 +0000343/* These are no-ops, as with LinuxThreads. */
344int pthread_attr_setscope ( pthread_attr_t *attr, int scope )
345{
346 ensure_valgrind("pthread_attr_setscope");
347 if (scope == PTHREAD_SCOPE_SYSTEM)
348 return 0;
sewardj4dced352002-06-04 22:54:20 +0000349 pthread_error("pthread_attr_setscope: "
350 "invalid or unsupported scope");
sewardj0d844232002-06-02 09:29:31 +0000351 if (scope == PTHREAD_SCOPE_PROCESS)
352 return ENOTSUP;
353 return EINVAL;
354}
355
356int pthread_attr_getscope ( const pthread_attr_t *attr, int *scope )
357{
358 ensure_valgrind("pthread_attr_setscope");
359 if (scope)
360 *scope = PTHREAD_SCOPE_SYSTEM;
361 return 0;
362}
363
sewardj64039bb2002-06-03 00:58:18 +0000364
365/* Pretty bogus. Avoid if possible. */
366int pthread_getattr_np (pthread_t thread, pthread_attr_t *attr)
367{
368 int detached;
369 size_t limit;
370 ensure_valgrind("pthread_getattr_np");
371 kludged("pthread_getattr_np");
372 limit = VG_PTHREAD_STACK_SIZE - VG_AR_CLIENT_STACKBASE_REDZONE_SZB
373 - 1000; /* paranoia */
374 attr->__detachstate = PTHREAD_CREATE_JOINABLE;
375 attr->__schedpolicy = SCHED_OTHER;
376 attr->__schedparam.sched_priority = 0;
377 attr->__inheritsched = PTHREAD_EXPLICIT_SCHED;
378 attr->__scope = PTHREAD_SCOPE_SYSTEM;
379 attr->__guardsize = VKI_BYTES_PER_PAGE;
380 attr->__stackaddr = NULL;
381 attr->__stackaddr_set = 0;
382 attr->__stacksize = limit;
383 VALGRIND_MAGIC_SEQUENCE(detached, (-1) /* default */,
384 VG_USERREQ__SET_OR_GET_DETACH,
385 2 /* get */, thread, 0, 0);
sewardj2d94c112002-06-03 01:25:54 +0000386 my_assert(detached == 0 || detached == 1);
sewardj64039bb2002-06-03 00:58:18 +0000387 if (detached)
388 attr->__detachstate = PTHREAD_CREATE_DETACHED;
389 return 0;
390}
391
392
393/* Bogus ... */
394int pthread_attr_getstackaddr ( const pthread_attr_t * attr,
395 void ** stackaddr )
396{
397 ensure_valgrind("pthread_attr_getstackaddr");
398 kludged("pthread_attr_getstackaddr");
399 if (stackaddr)
400 *stackaddr = NULL;
401 return 0;
402}
403
404/* Not bogus (!) */
405int pthread_attr_getstacksize ( const pthread_attr_t * _attr,
406 size_t * __stacksize )
407{
408 size_t limit;
409 ensure_valgrind("pthread_attr_getstacksize");
410 limit = VG_PTHREAD_STACK_SIZE - VG_AR_CLIENT_STACKBASE_REDZONE_SZB
411 - 1000; /* paranoia */
412 if (__stacksize)
413 *__stacksize = limit;
414 return 0;
415}
416
sewardja3be12f2002-06-17 12:19:44 +0000417int pthread_attr_setschedpolicy(pthread_attr_t *attr, int policy)
418{
419 if (policy != SCHED_OTHER && policy != SCHED_FIFO && policy != SCHED_RR)
420 return EINVAL;
421 attr->__schedpolicy = policy;
422 return 0;
423}
424
425int pthread_attr_getschedpolicy(const pthread_attr_t *attr, int *policy)
426{
427 *policy = attr->__schedpolicy;
428 return 0;
429}
430
431
sewardj20917d82002-05-28 01:36:45 +0000432/* ---------------------------------------------------
433 Helper functions for running a thread
434 and for clearing up afterwards.
435 ------------------------------------------------ */
436
437/* All exiting threads eventually pass through here, bearing the
438 return value, or PTHREAD_CANCELED, in ret_val. */
439static
440__attribute__((noreturn))
441void thread_exit_wrapper ( void* ret_val )
442{
sewardj870497a2002-05-29 01:06:47 +0000443 int detached, res;
444 CleanupEntry cu;
445 pthread_key_t key;
446
sewardj20917d82002-05-28 01:36:45 +0000447 /* Run this thread's cleanup handlers. */
sewardj8ad94e12002-05-29 00:10:20 +0000448 while (1) {
449 VALGRIND_MAGIC_SEQUENCE(res, (-1) /* default */,
450 VG_USERREQ__CLEANUP_POP,
451 &cu, 0, 0, 0);
452 if (res == -1) break; /* stack empty */
sewardj2d94c112002-06-03 01:25:54 +0000453 my_assert(res == 0);
sewardj8ad94e12002-05-29 00:10:20 +0000454 if (0) printf("running exit cleanup handler");
455 cu.fn ( cu.arg );
456 }
457
sewardj870497a2002-05-29 01:06:47 +0000458 /* Run this thread's key finalizers. Really this should be run
459 PTHREAD_DESTRUCTOR_ITERATIONS times. */
460 for (key = 0; key < VG_N_THREAD_KEYS; key++) {
461 VALGRIND_MAGIC_SEQUENCE(res, (-2) /* default */,
462 VG_USERREQ__GET_KEY_D_AND_S,
463 key, &cu, 0, 0 );
464 if (res == 0) {
465 /* valid key */
466 if (cu.fn && cu.arg)
467 cu.fn /* destructor for key */
468 ( cu.arg /* specific for key for this thread */ );
469 continue;
470 }
sewardj2d94c112002-06-03 01:25:54 +0000471 my_assert(res == -1);
sewardj870497a2002-05-29 01:06:47 +0000472 }
sewardj20917d82002-05-28 01:36:45 +0000473
474 /* Decide on my final disposition. */
475 VALGRIND_MAGIC_SEQUENCE(detached, (-1) /* default */,
476 VG_USERREQ__SET_OR_GET_DETACH,
sewardj7989d0c2002-05-28 11:00:01 +0000477 2 /* get */, pthread_self(), 0, 0);
sewardj2d94c112002-06-03 01:25:54 +0000478 my_assert(detached == 0 || detached == 1);
sewardj20917d82002-05-28 01:36:45 +0000479
480 if (detached) {
481 /* Detached; I just quit right now. */
482 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
483 VG_USERREQ__QUIT, 0, 0, 0, 0);
484 } else {
485 /* Not detached; so I wait for a joiner. */
486 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
487 VG_USERREQ__WAIT_JOINER, ret_val, 0, 0, 0);
488 }
489 /* NOTREACHED */
490 barf("thread_exit_wrapper: still alive?!");
491}
492
493
494/* This function is a wrapper function for running a thread. It runs
495 the root function specified in pthread_create, and then, should the
496 root function return a value, it arranges to run the thread's
497 cleanup handlers and exit correctly. */
498
sewardj728a5272002-06-20 10:25:37 +0000499/* Struct used to convey info from pthread_create to thread_wrapper.
500 Must be careful not to pass to the child thread any pointers to
501 objects which might be on the parent's stack. */
sewardj20917d82002-05-28 01:36:45 +0000502typedef
503 struct {
sewardj728a5272002-06-20 10:25:37 +0000504 int attr__detachstate;
sewardj20917d82002-05-28 01:36:45 +0000505 void* (*root_fn) ( void* );
506 void* arg;
507 }
508 NewThreadInfo;
509
510
511/* This is passed to the VG_USERREQ__APPLY_IN_NEW_THREAD and so must
512 not return. Note that this runs in the new thread, not the
513 parent. */
514static
515__attribute__((noreturn))
516void thread_wrapper ( NewThreadInfo* info )
517{
sewardj728a5272002-06-20 10:25:37 +0000518 int res;
519 int attr__detachstate;
sewardj20917d82002-05-28 01:36:45 +0000520 void* (*root_fn) ( void* );
521 void* arg;
522 void* ret_val;
523
sewardj728a5272002-06-20 10:25:37 +0000524 attr__detachstate = info->attr__detachstate;
525 root_fn = info->root_fn;
526 arg = info->arg;
sewardj20917d82002-05-28 01:36:45 +0000527
sewardj20917d82002-05-28 01:36:45 +0000528 /* Free up the arg block that pthread_create malloced. */
529 VALGRIND_MAGIC_SEQUENCE(res, (-1) /* default */,
530 VG_USERREQ__FREE, info, 0, 0, 0);
sewardj2d94c112002-06-03 01:25:54 +0000531 my_assert(res == 0);
sewardj20917d82002-05-28 01:36:45 +0000532
sewardj7989d0c2002-05-28 11:00:01 +0000533 /* Minimally observe the attributes supplied. */
sewardj728a5272002-06-20 10:25:37 +0000534 if (attr__detachstate != PTHREAD_CREATE_DETACHED
535 && attr__detachstate != PTHREAD_CREATE_JOINABLE)
536 pthread_error("thread_wrapper: invalid attr->__detachstate");
537 if (attr__detachstate == PTHREAD_CREATE_DETACHED)
538 pthread_detach(pthread_self());
sewardj7989d0c2002-05-28 11:00:01 +0000539
sewardj20917d82002-05-28 01:36:45 +0000540 /* The root function might not return. But if it does we simply
541 move along to thread_exit_wrapper. All other ways out for the
542 thread (cancellation, or calling pthread_exit) lead there
543 too. */
544 ret_val = root_fn(arg);
545 thread_exit_wrapper(ret_val);
546 /* NOTREACHED */
547}
548
549
sewardjf8f819e2002-04-17 23:21:37 +0000550/* ---------------------------------------------------
551 THREADs
552 ------------------------------------------------ */
553
sewardjff42d1d2002-05-22 13:17:31 +0000554__attribute__((weak))
555int pthread_yield ( void )
556{
557 int res;
558 ensure_valgrind("pthread_yield");
559 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
560 VG_USERREQ__PTHREAD_YIELD, 0, 0, 0, 0);
561 return 0;
562}
563
564
sewardj6072c362002-04-19 14:40:57 +0000565int pthread_equal(pthread_t thread1, pthread_t thread2)
566{
567 return thread1 == thread2 ? 1 : 0;
568}
569
570
sewardj20917d82002-05-28 01:36:45 +0000571/* Bundle up the args into a malloc'd block and create a new thread
572 consisting of thread_wrapper() applied to said malloc'd block. */
sewardje663cb92002-04-12 10:26:32 +0000573int
sewardj1462c8b2002-07-24 09:41:52 +0000574pthread_create (pthread_t *__restrict __thredd,
sewardje663cb92002-04-12 10:26:32 +0000575 __const pthread_attr_t *__restrict __attr,
576 void *(*__start_routine) (void *),
577 void *__restrict __arg)
578{
sewardj20917d82002-05-28 01:36:45 +0000579 int tid_child;
580 NewThreadInfo* info;
sewardje663cb92002-04-12 10:26:32 +0000581
sewardj20917d82002-05-28 01:36:45 +0000582 ensure_valgrind("pthread_create");
583
584 /* Allocate space for the arg block. thread_wrapper will free
585 it. */
586 VALGRIND_MAGIC_SEQUENCE(info, NULL /* default */,
587 VG_USERREQ__MALLOC,
588 sizeof(NewThreadInfo), 0, 0, 0);
sewardj2d94c112002-06-03 01:25:54 +0000589 my_assert(info != NULL);
sewardj20917d82002-05-28 01:36:45 +0000590
sewardj728a5272002-06-20 10:25:37 +0000591 if (__attr)
592 info->attr__detachstate = __attr->__detachstate;
593 else
594 info->attr__detachstate = PTHREAD_CREATE_JOINABLE;
595
sewardj20917d82002-05-28 01:36:45 +0000596 info->root_fn = __start_routine;
597 info->arg = __arg;
598 VALGRIND_MAGIC_SEQUENCE(tid_child, VG_INVALID_THREADID /* default */,
599 VG_USERREQ__APPLY_IN_NEW_THREAD,
600 &thread_wrapper, info, 0, 0);
sewardj2d94c112002-06-03 01:25:54 +0000601 my_assert(tid_child != VG_INVALID_THREADID);
sewardj20917d82002-05-28 01:36:45 +0000602
sewardj1462c8b2002-07-24 09:41:52 +0000603 if (__thredd)
604 *__thredd = tid_child;
sewardj20917d82002-05-28 01:36:45 +0000605 return 0; /* success */
606}
sewardje663cb92002-04-12 10:26:32 +0000607
608
609int
610pthread_join (pthread_t __th, void **__thread_return)
611{
612 int res;
613 ensure_valgrind("pthread_join");
614 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
615 VG_USERREQ__PTHREAD_JOIN,
616 __th, __thread_return, 0, 0);
617 return res;
618}
619
620
sewardj3b5d8862002-04-20 13:53:23 +0000621void pthread_exit(void *retval)
622{
sewardj3b5d8862002-04-20 13:53:23 +0000623 ensure_valgrind("pthread_exit");
sewardj20917d82002-05-28 01:36:45 +0000624 /* Simple! */
625 thread_exit_wrapper(retval);
sewardj3b5d8862002-04-20 13:53:23 +0000626}
627
sewardje663cb92002-04-12 10:26:32 +0000628
sewardj3b13f0e2002-04-25 20:17:29 +0000629pthread_t pthread_self(void)
sewardje663cb92002-04-12 10:26:32 +0000630{
631 int tid;
sewardj3b13f0e2002-04-25 20:17:29 +0000632 ensure_valgrind("pthread_self");
sewardj439d45e2002-05-03 20:43:10 +0000633 VALGRIND_MAGIC_SEQUENCE(tid, 1 /* default */,
sewardje663cb92002-04-12 10:26:32 +0000634 VG_USERREQ__PTHREAD_GET_THREADID,
635 0, 0, 0, 0);
sewardj439d45e2002-05-03 20:43:10 +0000636 if (tid < 1 || tid >= VG_N_THREADS)
sewardj3b13f0e2002-04-25 20:17:29 +0000637 barf("pthread_self: invalid ThreadId");
638 return tid;
sewardje663cb92002-04-12 10:26:32 +0000639}
640
641
sewardj853f55d2002-04-26 00:27:53 +0000642int pthread_detach(pthread_t th)
643{
sewardj20917d82002-05-28 01:36:45 +0000644 int res;
645 ensure_valgrind("pthread_detach");
sewardj7989d0c2002-05-28 11:00:01 +0000646 /* First we enquire as to the current detach state. */
647 VALGRIND_MAGIC_SEQUENCE(res, (-2) /* default */,
sewardj20917d82002-05-28 01:36:45 +0000648 VG_USERREQ__SET_OR_GET_DETACH,
sewardj7989d0c2002-05-28 11:00:01 +0000649 2 /* get */, th, 0, 0);
sewardj4dced352002-06-04 22:54:20 +0000650 if (res == -1) {
651 /* not found */
652 pthread_error("pthread_detach: "
653 "invalid target thread");
sewardj7989d0c2002-05-28 11:00:01 +0000654 return ESRCH;
sewardj4dced352002-06-04 22:54:20 +0000655 }
656 if (res == 1) {
657 /* already detached */
658 pthread_error("pthread_detach: "
659 "target thread is already detached");
sewardj7989d0c2002-05-28 11:00:01 +0000660 return EINVAL;
sewardj4dced352002-06-04 22:54:20 +0000661 }
sewardj7989d0c2002-05-28 11:00:01 +0000662 if (res == 0) {
663 VALGRIND_MAGIC_SEQUENCE(res, (-2) /* default */,
664 VG_USERREQ__SET_OR_GET_DETACH,
665 1 /* set */, th, 0, 0);
sewardj2d94c112002-06-03 01:25:54 +0000666 my_assert(res == 0);
sewardj7989d0c2002-05-28 11:00:01 +0000667 return 0;
668 }
669 barf("pthread_detach");
sewardj853f55d2002-04-26 00:27:53 +0000670}
671
672
sewardjf8f819e2002-04-17 23:21:37 +0000673/* ---------------------------------------------------
sewardj8ad94e12002-05-29 00:10:20 +0000674 CLEANUP STACKS
675 ------------------------------------------------ */
676
677void _pthread_cleanup_push (struct _pthread_cleanup_buffer *__buffer,
678 void (*__routine) (void *),
679 void *__arg)
680{
681 int res;
682 CleanupEntry cu;
683 ensure_valgrind("_pthread_cleanup_push");
684 cu.fn = __routine;
685 cu.arg = __arg;
686 VALGRIND_MAGIC_SEQUENCE(res, (-1) /* default */,
687 VG_USERREQ__CLEANUP_PUSH,
688 &cu, 0, 0, 0);
sewardj2d94c112002-06-03 01:25:54 +0000689 my_assert(res == 0);
sewardj8ad94e12002-05-29 00:10:20 +0000690}
691
692
693void _pthread_cleanup_push_defer (struct _pthread_cleanup_buffer *__buffer,
694 void (*__routine) (void *),
695 void *__arg)
696{
697 /* As _pthread_cleanup_push, but first save the thread's original
698 cancellation type in __buffer and set it to Deferred. */
699 int orig_ctype;
700 ensure_valgrind("_pthread_cleanup_push_defer");
701 /* Set to Deferred, and put the old cancellation type in res. */
sewardj2d94c112002-06-03 01:25:54 +0000702 my_assert(-1 != PTHREAD_CANCEL_DEFERRED);
703 my_assert(-1 != PTHREAD_CANCEL_ASYNCHRONOUS);
704 my_assert(sizeof(struct _pthread_cleanup_buffer) >= sizeof(int));
sewardj8ad94e12002-05-29 00:10:20 +0000705 VALGRIND_MAGIC_SEQUENCE(orig_ctype, (-1) /* default */,
706 VG_USERREQ__SET_CANCELTYPE,
707 PTHREAD_CANCEL_DEFERRED, 0, 0, 0);
sewardj2d94c112002-06-03 01:25:54 +0000708 my_assert(orig_ctype != -1);
sewardj8ad94e12002-05-29 00:10:20 +0000709 *((int*)(__buffer)) = orig_ctype;
710 /* Now push the cleanup. */
711 _pthread_cleanup_push(NULL, __routine, __arg);
712}
713
714
715void _pthread_cleanup_pop (struct _pthread_cleanup_buffer *__buffer,
716 int __execute)
717{
718 int res;
719 CleanupEntry cu;
720 ensure_valgrind("_pthread_cleanup_push");
721 cu.fn = cu.arg = NULL; /* paranoia */
722 VALGRIND_MAGIC_SEQUENCE(res, (-1) /* default */,
723 VG_USERREQ__CLEANUP_POP,
724 &cu, 0, 0, 0);
725 if (res == 0) {
726 /* pop succeeded */
727 if (__execute) {
728 cu.fn ( cu.arg );
729 }
730 return;
731 }
732 if (res == -1) {
733 /* stack underflow */
734 return;
735 }
736 barf("_pthread_cleanup_pop");
737}
738
739
740void _pthread_cleanup_pop_restore (struct _pthread_cleanup_buffer *__buffer,
741 int __execute)
742{
743 int orig_ctype, fake_ctype;
744 /* As _pthread_cleanup_pop, but after popping/running the handler,
745 restore the thread's original cancellation type from the first
746 word of __buffer. */
747 _pthread_cleanup_pop(NULL, __execute);
748 orig_ctype = *((int*)(__buffer));
sewardj2d94c112002-06-03 01:25:54 +0000749 my_assert(orig_ctype == PTHREAD_CANCEL_DEFERRED
sewardj8ad94e12002-05-29 00:10:20 +0000750 || orig_ctype == PTHREAD_CANCEL_ASYNCHRONOUS);
sewardj2d94c112002-06-03 01:25:54 +0000751 my_assert(-1 != PTHREAD_CANCEL_DEFERRED);
752 my_assert(-1 != PTHREAD_CANCEL_ASYNCHRONOUS);
753 my_assert(sizeof(struct _pthread_cleanup_buffer) >= sizeof(int));
sewardj8ad94e12002-05-29 00:10:20 +0000754 VALGRIND_MAGIC_SEQUENCE(fake_ctype, (-1) /* default */,
755 VG_USERREQ__SET_CANCELTYPE,
756 orig_ctype, 0, 0, 0);
sewardj2d94c112002-06-03 01:25:54 +0000757 my_assert(fake_ctype == PTHREAD_CANCEL_DEFERRED);
sewardj8ad94e12002-05-29 00:10:20 +0000758}
759
760
761/* ---------------------------------------------------
sewardjf8f819e2002-04-17 23:21:37 +0000762 MUTEX ATTRIBUTES
763 ------------------------------------------------ */
764
sewardj5905fae2002-04-26 13:25:00 +0000765int __pthread_mutexattr_init(pthread_mutexattr_t *attr)
sewardje663cb92002-04-12 10:26:32 +0000766{
sewardjf8f819e2002-04-17 23:21:37 +0000767 attr->__mutexkind = PTHREAD_MUTEX_ERRORCHECK_NP;
sewardj8937c812002-04-12 20:12:20 +0000768 return 0;
sewardje663cb92002-04-12 10:26:32 +0000769}
770
sewardj5905fae2002-04-26 13:25:00 +0000771int __pthread_mutexattr_settype(pthread_mutexattr_t *attr, int type)
sewardjf8f819e2002-04-17 23:21:37 +0000772{
773 switch (type) {
sewardj3b13f0e2002-04-25 20:17:29 +0000774# ifndef GLIBC_2_1
sewardjf8f819e2002-04-17 23:21:37 +0000775 case PTHREAD_MUTEX_TIMED_NP:
sewardj2a1dcce2002-04-22 12:45:25 +0000776 case PTHREAD_MUTEX_ADAPTIVE_NP:
sewardj3b13f0e2002-04-25 20:17:29 +0000777# endif
sewardja1679dd2002-05-10 22:31:40 +0000778# ifdef GLIBC_2_1
sewardj68b2dd92002-05-10 21:03:56 +0000779 case PTHREAD_MUTEX_FAST_NP:
sewardja1679dd2002-05-10 22:31:40 +0000780# endif
sewardjf8f819e2002-04-17 23:21:37 +0000781 case PTHREAD_MUTEX_RECURSIVE_NP:
782 case PTHREAD_MUTEX_ERRORCHECK_NP:
sewardjf8f819e2002-04-17 23:21:37 +0000783 attr->__mutexkind = type;
784 return 0;
785 default:
sewardj4dced352002-06-04 22:54:20 +0000786 pthread_error("pthread_mutexattr_settype: "
787 "invalid type");
sewardjf8f819e2002-04-17 23:21:37 +0000788 return EINVAL;
789 }
790}
791
sewardj5905fae2002-04-26 13:25:00 +0000792int __pthread_mutexattr_destroy(pthread_mutexattr_t *attr)
sewardjf8f819e2002-04-17 23:21:37 +0000793{
794 return 0;
795}
796
797
798/* ---------------------------------------------------
799 MUTEXes
800 ------------------------------------------------ */
801
sewardj5905fae2002-04-26 13:25:00 +0000802int __pthread_mutex_init(pthread_mutex_t *mutex,
803 const pthread_mutexattr_t *mutexattr)
sewardje663cb92002-04-12 10:26:32 +0000804{
sewardj604ec3c2002-04-18 22:38:41 +0000805 mutex->__m_count = 0;
806 mutex->__m_owner = (_pthread_descr)VG_INVALID_THREADID;
807 mutex->__m_kind = PTHREAD_MUTEX_ERRORCHECK_NP;
808 if (mutexattr)
809 mutex->__m_kind = mutexattr->__mutexkind;
810 return 0;
sewardje663cb92002-04-12 10:26:32 +0000811}
812
sewardj439d45e2002-05-03 20:43:10 +0000813
sewardj5905fae2002-04-26 13:25:00 +0000814int __pthread_mutex_lock(pthread_mutex_t *mutex)
sewardje663cb92002-04-12 10:26:32 +0000815{
816 int res;
sewardj436e0582002-04-26 14:31:40 +0000817 static int moans = N_MOANS;
sewardj439d45e2002-05-03 20:43:10 +0000818 if (RUNNING_ON_VALGRIND) {
sewardje663cb92002-04-12 10:26:32 +0000819 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
820 VG_USERREQ__PTHREAD_MUTEX_LOCK,
821 mutex, 0, 0, 0);
822 return res;
sewardj439d45e2002-05-03 20:43:10 +0000823 } else {
824 if (moans-- > 0)
825 not_inside("pthread_mutex_lock");
826 return 0; /* success */
sewardje663cb92002-04-12 10:26:32 +0000827 }
828}
829
sewardj439d45e2002-05-03 20:43:10 +0000830
sewardj5905fae2002-04-26 13:25:00 +0000831int __pthread_mutex_trylock(pthread_mutex_t *mutex)
sewardj30671ff2002-04-21 00:13:57 +0000832{
833 int res;
sewardj436e0582002-04-26 14:31:40 +0000834 static int moans = N_MOANS;
sewardj439d45e2002-05-03 20:43:10 +0000835 if (RUNNING_ON_VALGRIND) {
sewardj30671ff2002-04-21 00:13:57 +0000836 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
837 VG_USERREQ__PTHREAD_MUTEX_TRYLOCK,
838 mutex, 0, 0, 0);
839 return res;
sewardj439d45e2002-05-03 20:43:10 +0000840 } else {
841 if (moans-- > 0)
842 not_inside("pthread_mutex_trylock");
843 return 0;
sewardj30671ff2002-04-21 00:13:57 +0000844 }
845}
846
sewardj439d45e2002-05-03 20:43:10 +0000847
sewardj5905fae2002-04-26 13:25:00 +0000848int __pthread_mutex_unlock(pthread_mutex_t *mutex)
sewardje663cb92002-04-12 10:26:32 +0000849{
850 int res;
sewardj436e0582002-04-26 14:31:40 +0000851 static int moans = N_MOANS;
sewardj439d45e2002-05-03 20:43:10 +0000852 if (RUNNING_ON_VALGRIND) {
sewardje663cb92002-04-12 10:26:32 +0000853 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
854 VG_USERREQ__PTHREAD_MUTEX_UNLOCK,
855 mutex, 0, 0, 0);
856 return res;
sewardj439d45e2002-05-03 20:43:10 +0000857 } else {
858 if (moans-- > 0)
859 not_inside("pthread_mutex_unlock");
860 return 0;
sewardje663cb92002-04-12 10:26:32 +0000861 }
862}
863
sewardj439d45e2002-05-03 20:43:10 +0000864
sewardj5905fae2002-04-26 13:25:00 +0000865int __pthread_mutex_destroy(pthread_mutex_t *mutex)
sewardje663cb92002-04-12 10:26:32 +0000866{
sewardj604ec3c2002-04-18 22:38:41 +0000867 /* Valgrind doesn't hold any resources on behalf of the mutex, so no
868 need to involve it. */
sewardj4dced352002-06-04 22:54:20 +0000869 if (mutex->__m_count > 0) {
870 pthread_error("pthread_mutex_destroy: "
871 "mutex is still in use");
sewardj604ec3c2002-04-18 22:38:41 +0000872 return EBUSY;
sewardj4dced352002-06-04 22:54:20 +0000873 }
874 mutex->__m_count = 0;
875 mutex->__m_owner = (_pthread_descr)VG_INVALID_THREADID;
876 mutex->__m_kind = PTHREAD_MUTEX_ERRORCHECK_NP;
877 return 0;
sewardje663cb92002-04-12 10:26:32 +0000878}
879
880
sewardjf8f819e2002-04-17 23:21:37 +0000881/* ---------------------------------------------------
sewardj6072c362002-04-19 14:40:57 +0000882 CONDITION VARIABLES
883 ------------------------------------------------ */
884
885/* LinuxThreads supports no attributes for conditions. Hence ... */
886
887int pthread_condattr_init(pthread_condattr_t *attr)
888{
889 return 0;
890}
891
sewardj0738a592002-04-20 13:59:33 +0000892int pthread_condattr_destroy(pthread_condattr_t *attr)
893{
894 return 0;
895}
sewardj6072c362002-04-19 14:40:57 +0000896
897int pthread_cond_init( pthread_cond_t *cond,
898 const pthread_condattr_t *cond_attr)
899{
900 cond->__c_waiting = (_pthread_descr)VG_INVALID_THREADID;
901 return 0;
902}
903
sewardjf854f472002-04-21 12:19:41 +0000904int pthread_cond_destroy(pthread_cond_t *cond)
905{
906 /* should check that no threads are waiting on this CV */
sewardj436e0582002-04-26 14:31:40 +0000907 static int moans = N_MOANS;
908 if (moans-- > 0)
909 kludged("pthread_cond_destroy");
sewardjf854f472002-04-21 12:19:41 +0000910 return 0;
911}
sewardj6072c362002-04-19 14:40:57 +0000912
913/* ---------------------------------------------------
914 SCHEDULING
915 ------------------------------------------------ */
916
917/* This is completely bogus. */
918int pthread_getschedparam(pthread_t target_thread,
919 int *policy,
920 struct sched_param *param)
921{
sewardj436e0582002-04-26 14:31:40 +0000922 static int moans = N_MOANS;
923 if (moans-- > 0)
924 kludged("pthread_getschedparam");
sewardj6072c362002-04-19 14:40:57 +0000925 if (policy) *policy = SCHED_OTHER;
sewardj3e909ce2002-06-03 13:27:15 +0000926# ifdef HAVE_SCHED_PRIORITY
sewardj2a1dcce2002-04-22 12:45:25 +0000927 if (param) param->sched_priority = 0; /* who knows */
928# else
sewardj6072c362002-04-19 14:40:57 +0000929 if (param) param->__sched_priority = 0; /* who knows */
sewardj2a1dcce2002-04-22 12:45:25 +0000930# endif
sewardj6072c362002-04-19 14:40:57 +0000931 return 0;
932}
933
934int pthread_setschedparam(pthread_t target_thread,
935 int policy,
936 const struct sched_param *param)
937{
sewardj436e0582002-04-26 14:31:40 +0000938 static int moans = N_MOANS;
939 if (moans-- > 0)
940 ignored("pthread_setschedparam");
sewardj6072c362002-04-19 14:40:57 +0000941 return 0;
942}
943
sewardj3b5d8862002-04-20 13:53:23 +0000944int pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex)
945{
946 int res;
947 ensure_valgrind("pthread_cond_wait");
948 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
949 VG_USERREQ__PTHREAD_COND_WAIT,
950 cond, mutex, 0, 0);
951 return res;
952}
953
sewardj5f07b662002-04-23 16:52:51 +0000954int pthread_cond_timedwait ( pthread_cond_t *cond,
955 pthread_mutex_t *mutex,
956 const struct timespec *abstime )
957{
958 int res;
959 unsigned int ms_now, ms_end;
960 struct timeval timeval_now;
961 unsigned long long int ull_ms_now_after_1970;
962 unsigned long long int ull_ms_end_after_1970;
963
964 ensure_valgrind("pthread_cond_timedwait");
965 VALGRIND_MAGIC_SEQUENCE(ms_now, 0xFFFFFFFF /* default */,
966 VG_USERREQ__READ_MILLISECOND_TIMER,
967 0, 0, 0, 0);
sewardj2d94c112002-06-03 01:25:54 +0000968 my_assert(ms_now != 0xFFFFFFFF);
sewardj5f07b662002-04-23 16:52:51 +0000969 res = gettimeofday(&timeval_now, NULL);
sewardj2d94c112002-06-03 01:25:54 +0000970 my_assert(res == 0);
sewardj5f07b662002-04-23 16:52:51 +0000971
972 ull_ms_now_after_1970
973 = 1000ULL * ((unsigned long long int)(timeval_now.tv_sec))
974 + ((unsigned long long int)(timeval_now.tv_usec / 1000000));
975 ull_ms_end_after_1970
976 = 1000ULL * ((unsigned long long int)(abstime->tv_sec))
977 + ((unsigned long long int)(abstime->tv_nsec / 1000000));
sewardjd8e919e2002-05-29 20:13:53 +0000978 if (ull_ms_end_after_1970 < ull_ms_now_after_1970)
979 ull_ms_end_after_1970 = ull_ms_now_after_1970;
sewardj5f07b662002-04-23 16:52:51 +0000980 ms_end
981 = ms_now + (unsigned int)(ull_ms_end_after_1970 - ull_ms_now_after_1970);
982 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
983 VG_USERREQ__PTHREAD_COND_TIMEDWAIT,
984 cond, mutex, ms_end, 0);
985 return res;
986}
987
988
sewardj3b5d8862002-04-20 13:53:23 +0000989int pthread_cond_signal(pthread_cond_t *cond)
990{
991 int res;
992 ensure_valgrind("pthread_cond_signal");
993 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
994 VG_USERREQ__PTHREAD_COND_SIGNAL,
995 cond, 0, 0, 0);
996 return res;
997}
998
999int pthread_cond_broadcast(pthread_cond_t *cond)
1000{
1001 int res;
1002 ensure_valgrind("pthread_cond_broadcast");
1003 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
1004 VG_USERREQ__PTHREAD_COND_BROADCAST,
1005 cond, 0, 0, 0);
1006 return res;
1007}
1008
sewardj6072c362002-04-19 14:40:57 +00001009
1010/* ---------------------------------------------------
sewardjf8f819e2002-04-17 23:21:37 +00001011 CANCELLATION
1012 ------------------------------------------------ */
1013
sewardj853f55d2002-04-26 00:27:53 +00001014int pthread_setcancelstate(int state, int *oldstate)
1015{
sewardj20917d82002-05-28 01:36:45 +00001016 int res;
1017 ensure_valgrind("pthread_setcancelstate");
1018 if (state != PTHREAD_CANCEL_ENABLE
sewardj4dced352002-06-04 22:54:20 +00001019 && state != PTHREAD_CANCEL_DISABLE) {
1020 pthread_error("pthread_setcancelstate: "
1021 "invalid state");
sewardj20917d82002-05-28 01:36:45 +00001022 return EINVAL;
sewardj4dced352002-06-04 22:54:20 +00001023 }
sewardj2d94c112002-06-03 01:25:54 +00001024 my_assert(-1 != PTHREAD_CANCEL_ENABLE);
1025 my_assert(-1 != PTHREAD_CANCEL_DISABLE);
sewardj20917d82002-05-28 01:36:45 +00001026 VALGRIND_MAGIC_SEQUENCE(res, (-1) /* default */,
1027 VG_USERREQ__SET_CANCELSTATE,
1028 state, 0, 0, 0);
sewardj2d94c112002-06-03 01:25:54 +00001029 my_assert(res != -1);
sewardj20917d82002-05-28 01:36:45 +00001030 if (oldstate)
1031 *oldstate = res;
sewardj853f55d2002-04-26 00:27:53 +00001032 return 0;
1033}
1034
sewardje663cb92002-04-12 10:26:32 +00001035int pthread_setcanceltype(int type, int *oldtype)
1036{
sewardj20917d82002-05-28 01:36:45 +00001037 int res;
1038 ensure_valgrind("pthread_setcanceltype");
1039 if (type != PTHREAD_CANCEL_DEFERRED
sewardj4dced352002-06-04 22:54:20 +00001040 && type != PTHREAD_CANCEL_ASYNCHRONOUS) {
1041 pthread_error("pthread_setcanceltype: "
1042 "invalid type");
sewardj20917d82002-05-28 01:36:45 +00001043 return EINVAL;
sewardj4dced352002-06-04 22:54:20 +00001044 }
sewardj2d94c112002-06-03 01:25:54 +00001045 my_assert(-1 != PTHREAD_CANCEL_DEFERRED);
1046 my_assert(-1 != PTHREAD_CANCEL_ASYNCHRONOUS);
sewardj20917d82002-05-28 01:36:45 +00001047 VALGRIND_MAGIC_SEQUENCE(res, (-1) /* default */,
1048 VG_USERREQ__SET_CANCELTYPE,
1049 type, 0, 0, 0);
sewardj2d94c112002-06-03 01:25:54 +00001050 my_assert(res != -1);
sewardj20917d82002-05-28 01:36:45 +00001051 if (oldtype)
1052 *oldtype = res;
sewardje663cb92002-04-12 10:26:32 +00001053 return 0;
1054}
1055
sewardje663cb92002-04-12 10:26:32 +00001056int pthread_cancel(pthread_t thread)
1057{
1058 int res;
1059 ensure_valgrind("pthread_cancel");
sewardj20917d82002-05-28 01:36:45 +00001060 VALGRIND_MAGIC_SEQUENCE(res, (-1) /* default */,
1061 VG_USERREQ__SET_CANCELPEND,
1062 thread, &thread_exit_wrapper, 0, 0);
sewardj2d94c112002-06-03 01:25:54 +00001063 my_assert(res != -1);
sewardje663cb92002-04-12 10:26:32 +00001064 return res;
1065}
1066
sewardjd140e442002-05-29 01:21:19 +00001067static __inline__
1068void __my_pthread_testcancel(void)
sewardj853f55d2002-04-26 00:27:53 +00001069{
sewardj20917d82002-05-28 01:36:45 +00001070 int res;
njn25e49d8e72002-09-23 09:36:25 +00001071 ensure_valgrind("__my_pthread_testcancel");
sewardj20917d82002-05-28 01:36:45 +00001072 VALGRIND_MAGIC_SEQUENCE(res, (-1) /* default */,
1073 VG_USERREQ__TESTCANCEL,
1074 0, 0, 0, 0);
sewardj2d94c112002-06-03 01:25:54 +00001075 my_assert(res == 0);
sewardj853f55d2002-04-26 00:27:53 +00001076}
1077
sewardjd140e442002-05-29 01:21:19 +00001078void pthread_testcancel ( void )
1079{
1080 __my_pthread_testcancel();
1081}
1082
sewardj20917d82002-05-28 01:36:45 +00001083
sewardjef037c72002-05-30 00:40:03 +00001084/* Not really sure what this is for. I suspect for doing the POSIX
1085 requirements for fork() and exec(). We do this internally anyway
1086 whenever those syscalls are observed, so this could be superfluous,
1087 but hey ...
1088*/
sewardj853f55d2002-04-26 00:27:53 +00001089void __pthread_kill_other_threads_np ( void )
1090{
sewardjef037c72002-05-30 00:40:03 +00001091 int res;
1092 ensure_valgrind("__pthread_kill_other_threads_np");
1093 VALGRIND_MAGIC_SEQUENCE(res, (-1) /* default */,
1094 VG_USERREQ__NUKE_OTHER_THREADS,
1095 0, 0, 0, 0);
sewardj2d94c112002-06-03 01:25:54 +00001096 my_assert(res == 0);
sewardj853f55d2002-04-26 00:27:53 +00001097}
1098
sewardje663cb92002-04-12 10:26:32 +00001099
sewardjf8f819e2002-04-17 23:21:37 +00001100/* ---------------------------------------------------
sewardjb48e5002002-05-13 00:16:03 +00001101 SIGNALS
1102 ------------------------------------------------ */
1103
1104#include <signal.h>
1105
1106int pthread_sigmask(int how, const sigset_t *newmask,
1107 sigset_t *oldmask)
1108{
1109 int res;
1110
1111 /* A bit subtle, because the scheduler expects newmask and oldmask
1112 to be vki_sigset_t* rather than sigset_t*, and the two are
1113 different. Fortunately the first 64 bits of a sigset_t are
1114 exactly a vki_sigset_t, so we just pass the pointers through
1115 unmodified. Haaaack!
1116
1117 Also mash the how value so that the SIG_ constants from glibc
sewardj018f7622002-05-15 21:13:39 +00001118 constants to VKI_ constants, so that the former do not have to
1119 be included into vg_scheduler.c. */
sewardjb48e5002002-05-13 00:16:03 +00001120
1121 ensure_valgrind("pthread_sigmask");
1122
1123 switch (how) {
sewardj018f7622002-05-15 21:13:39 +00001124 case SIG_SETMASK: how = VKI_SIG_SETMASK; break;
1125 case SIG_BLOCK: how = VKI_SIG_BLOCK; break;
1126 case SIG_UNBLOCK: how = VKI_SIG_UNBLOCK; break;
sewardj4dced352002-06-04 22:54:20 +00001127 default: pthread_error("pthread_sigmask: invalid how");
1128 return EINVAL;
sewardjb48e5002002-05-13 00:16:03 +00001129 }
1130
1131 /* Crude check */
1132 if (newmask == NULL)
1133 return EFAULT;
1134
1135 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
1136 VG_USERREQ__PTHREAD_SIGMASK,
1137 how, newmask, oldmask, 0);
1138
1139 /* The scheduler tells us of any memory violations. */
1140 return res == 0 ? 0 : EFAULT;
1141}
1142
1143
1144int sigwait ( const sigset_t* set, int* sig )
1145{
1146 int res;
1147 ensure_valgrind("sigwait");
1148 /* As with pthread_sigmask we deliberately confuse sigset_t with
1149 vki_ksigset_t. */
1150 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
1151 VG_USERREQ__SIGWAIT,
1152 set, sig, 0, 0);
1153 return res;
1154}
1155
1156
sewardj018f7622002-05-15 21:13:39 +00001157int pthread_kill(pthread_t thread, int signo)
1158{
1159 int res;
1160 ensure_valgrind("pthread_kill");
1161 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
1162 VG_USERREQ__PTHREAD_KILL,
1163 thread, signo, 0, 0);
1164 return res;
1165}
1166
1167
sewardj3665ded2002-05-16 16:57:25 +00001168/* Copied verbatim from Linuxthreads */
1169/* Redefine raise() to send signal to calling thread only,
1170 as per POSIX 1003.1c */
1171int raise (int sig)
1172{
1173 int retcode = pthread_kill(pthread_self(), sig);
sewardj4dced352002-06-04 22:54:20 +00001174 if (retcode == 0) {
sewardj3665ded2002-05-16 16:57:25 +00001175 return 0;
sewardj4dced352002-06-04 22:54:20 +00001176 } else {
sewardj3665ded2002-05-16 16:57:25 +00001177 errno = retcode;
1178 return -1;
1179 }
1180}
1181
1182
sewardj9a2224b2002-06-19 10:17:40 +00001183int pause ( void )
1184{
1185 unsigned int n_orig, n_now;
1186 struct vki_timespec nanosleep_interval;
1187 ensure_valgrind("pause");
1188
1189 /* This is surely a cancellation point. */
1190 __my_pthread_testcancel();
1191
1192 VALGRIND_MAGIC_SEQUENCE(n_orig, 0xFFFFFFFF /* default */,
1193 VG_USERREQ__GET_N_SIGS_RETURNED,
1194 0, 0, 0, 0);
1195 my_assert(n_orig != 0xFFFFFFFF);
1196
1197 while (1) {
1198 VALGRIND_MAGIC_SEQUENCE(n_now, 0xFFFFFFFF /* default */,
1199 VG_USERREQ__GET_N_SIGS_RETURNED,
1200 0, 0, 0, 0);
1201 my_assert(n_now != 0xFFFFFFFF);
1202 my_assert(n_now >= n_orig);
1203 if (n_now != n_orig) break;
1204
1205 nanosleep_interval.tv_sec = 0;
njn25e49d8e72002-09-23 09:36:25 +00001206 nanosleep_interval.tv_nsec = 12 * 1000 * 1000; /* 12 milliseconds */
sewardj9a2224b2002-06-19 10:17:40 +00001207 /* It's critical here that valgrind's nanosleep implementation
1208 is nonblocking. */
1209 (void)my_do_syscall2(__NR_nanosleep,
1210 (int)(&nanosleep_interval), (int)NULL);
1211 }
1212
1213 * (__errno_location()) = EINTR;
1214 return -1;
1215}
1216
1217
sewardjb48e5002002-05-13 00:16:03 +00001218/* ---------------------------------------------------
sewardjf8f819e2002-04-17 23:21:37 +00001219 THREAD-SPECIFICs
1220 ------------------------------------------------ */
sewardj5e5fa512002-04-14 13:13:05 +00001221
sewardj5905fae2002-04-26 13:25:00 +00001222int __pthread_key_create(pthread_key_t *key,
1223 void (*destr_function) (void *))
sewardj5e5fa512002-04-14 13:13:05 +00001224{
sewardj5f07b662002-04-23 16:52:51 +00001225 int res;
1226 ensure_valgrind("pthread_key_create");
1227 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
1228 VG_USERREQ__PTHREAD_KEY_CREATE,
1229 key, destr_function, 0, 0);
1230 return res;
sewardj5e5fa512002-04-14 13:13:05 +00001231}
1232
1233int pthread_key_delete(pthread_key_t key)
1234{
sewardj436e0582002-04-26 14:31:40 +00001235 static int moans = N_MOANS;
1236 if (moans-- > 0)
1237 ignored("pthread_key_delete");
sewardj5e5fa512002-04-14 13:13:05 +00001238 return 0;
1239}
1240
sewardj5905fae2002-04-26 13:25:00 +00001241int __pthread_setspecific(pthread_key_t key, const void *pointer)
sewardj5e5fa512002-04-14 13:13:05 +00001242{
sewardj5f07b662002-04-23 16:52:51 +00001243 int res;
1244 ensure_valgrind("pthread_setspecific");
1245 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
1246 VG_USERREQ__PTHREAD_SETSPECIFIC,
1247 key, pointer, 0, 0);
1248 return res;
sewardj5e5fa512002-04-14 13:13:05 +00001249}
1250
sewardj5905fae2002-04-26 13:25:00 +00001251void * __pthread_getspecific(pthread_key_t key)
sewardj5e5fa512002-04-14 13:13:05 +00001252{
sewardj5f07b662002-04-23 16:52:51 +00001253 int res;
1254 ensure_valgrind("pthread_getspecific");
1255 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
1256 VG_USERREQ__PTHREAD_GETSPECIFIC,
1257 key, 0 , 0, 0);
1258 return (void*)res;
sewardj5e5fa512002-04-14 13:13:05 +00001259}
1260
sewardjf8f819e2002-04-17 23:21:37 +00001261
1262/* ---------------------------------------------------
sewardj89d3d852002-04-24 19:21:39 +00001263 ONCEry
1264 ------------------------------------------------ */
1265
1266static pthread_mutex_t once_masterlock = PTHREAD_MUTEX_INITIALIZER;
1267
1268
sewardj5905fae2002-04-26 13:25:00 +00001269int __pthread_once ( pthread_once_t *once_control,
1270 void (*init_routine) (void) )
sewardj89d3d852002-04-24 19:21:39 +00001271{
1272 int res;
1273 ensure_valgrind("pthread_once");
1274
sewardj68b2dd92002-05-10 21:03:56 +00001275 res = __pthread_mutex_lock(&once_masterlock);
sewardj89d3d852002-04-24 19:21:39 +00001276
sewardj68b2dd92002-05-10 21:03:56 +00001277 if (res != 0) {
sewardj89d3d852002-04-24 19:21:39 +00001278 barf("pthread_once: Looks like your program's "
1279 "init routine calls back to pthread_once() ?!");
sewardj68b2dd92002-05-10 21:03:56 +00001280 }
sewardj89d3d852002-04-24 19:21:39 +00001281
1282 if (*once_control == 0) {
1283 *once_control = 1;
1284 init_routine();
1285 }
1286
sewardj68b2dd92002-05-10 21:03:56 +00001287 __pthread_mutex_unlock(&once_masterlock);
sewardj89d3d852002-04-24 19:21:39 +00001288
1289 return 0;
1290}
1291
1292
1293/* ---------------------------------------------------
sewardj853f55d2002-04-26 00:27:53 +00001294 MISC
1295 ------------------------------------------------ */
1296
sewardj2cb00342002-06-28 01:46:26 +00001297static pthread_mutex_t pthread_atfork_lock
1298 = PTHREAD_MUTEX_INITIALIZER;
1299
sewardj5905fae2002-04-26 13:25:00 +00001300int __pthread_atfork ( void (*prepare)(void),
1301 void (*parent)(void),
1302 void (*child)(void) )
sewardj853f55d2002-04-26 00:27:53 +00001303{
sewardj2cb00342002-06-28 01:46:26 +00001304 int n, res;
1305 ForkHandlerEntry entry;
1306
1307 ensure_valgrind("pthread_atfork");
1308 __pthread_mutex_lock(&pthread_atfork_lock);
1309
1310 /* Fetch old counter */
1311 VALGRIND_MAGIC_SEQUENCE(n, -2 /* default */,
1312 VG_USERREQ__GET_FHSTACK_USED,
1313 0, 0, 0, 0);
1314 my_assert(n >= 0 && n < VG_N_FORKHANDLERSTACK);
1315 if (n == VG_N_FORKHANDLERSTACK-1)
1316 barf("pthread_atfork: VG_N_FORKHANDLERSTACK is too low; "
1317 "increase and recompile");
1318
1319 /* Add entry */
1320 entry.prepare = *prepare;
1321 entry.parent = *parent;
1322 entry.child = *child;
1323 VALGRIND_MAGIC_SEQUENCE(res, -2 /* default */,
1324 VG_USERREQ__SET_FHSTACK_ENTRY,
1325 n, &entry, 0, 0);
1326 my_assert(res == 0);
1327
1328 /* Bump counter */
1329 VALGRIND_MAGIC_SEQUENCE(res, -2 /* default */,
1330 VG_USERREQ__SET_FHSTACK_USED,
1331 n+1, 0, 0, 0);
1332 my_assert(res == 0);
1333
1334 __pthread_mutex_unlock(&pthread_atfork_lock);
1335 return 0;
sewardj853f55d2002-04-26 00:27:53 +00001336}
1337
1338
sewardjbb990782002-05-08 02:01:14 +00001339__attribute__((weak))
1340void __pthread_initialize ( void )
1341{
sewardjbea1caa2002-05-10 23:20:58 +00001342 ensure_valgrind("__pthread_initialize");
sewardjbb990782002-05-08 02:01:14 +00001343}
1344
1345
sewardj853f55d2002-04-26 00:27:53 +00001346/* ---------------------------------------------------
sewardj3b13f0e2002-04-25 20:17:29 +00001347 LIBRARY-PRIVATE THREAD SPECIFIC STATE
sewardjf8f819e2002-04-17 23:21:37 +00001348 ------------------------------------------------ */
1349
sewardj3b13f0e2002-04-25 20:17:29 +00001350#include <resolv.h>
1351static int thread_specific_errno[VG_N_THREADS];
1352static int thread_specific_h_errno[VG_N_THREADS];
1353static struct __res_state
1354 thread_specific_res_state[VG_N_THREADS];
sewardjf8f819e2002-04-17 23:21:37 +00001355
sewardj3b13f0e2002-04-25 20:17:29 +00001356int* __errno_location ( void )
sewardjf8f819e2002-04-17 23:21:37 +00001357{
1358 int tid;
sewardj3b13f0e2002-04-25 20:17:29 +00001359 /* ensure_valgrind("__errno_location"); */
1360 VALGRIND_MAGIC_SEQUENCE(tid, 1 /* default */,
sewardjf8f819e2002-04-17 23:21:37 +00001361 VG_USERREQ__PTHREAD_GET_THREADID,
1362 0, 0, 0, 0);
sewardj3b13f0e2002-04-25 20:17:29 +00001363 /* 'cos I'm paranoid ... */
sewardj439d45e2002-05-03 20:43:10 +00001364 if (tid < 1 || tid >= VG_N_THREADS)
sewardj3b13f0e2002-04-25 20:17:29 +00001365 barf("__errno_location: invalid ThreadId");
1366 return & thread_specific_errno[tid];
1367}
1368
1369int* __h_errno_location ( void )
1370{
1371 int tid;
1372 /* ensure_valgrind("__h_errno_location"); */
1373 VALGRIND_MAGIC_SEQUENCE(tid, 1 /* default */,
1374 VG_USERREQ__PTHREAD_GET_THREADID,
1375 0, 0, 0, 0);
1376 /* 'cos I'm paranoid ... */
sewardj439d45e2002-05-03 20:43:10 +00001377 if (tid < 1 || tid >= VG_N_THREADS)
sewardj3b13f0e2002-04-25 20:17:29 +00001378 barf("__h_errno_location: invalid ThreadId");
1379 return & thread_specific_h_errno[tid];
1380}
1381
sewardjb0ff1032002-08-06 09:02:53 +00001382
1383#undef _res
1384extern struct __res_state _res;
1385
sewardj3b13f0e2002-04-25 20:17:29 +00001386struct __res_state* __res_state ( void )
1387{
1388 int tid;
1389 /* ensure_valgrind("__res_state"); */
1390 VALGRIND_MAGIC_SEQUENCE(tid, 1 /* default */,
1391 VG_USERREQ__PTHREAD_GET_THREADID,
1392 0, 0, 0, 0);
1393 /* 'cos I'm paranoid ... */
sewardj439d45e2002-05-03 20:43:10 +00001394 if (tid < 1 || tid >= VG_N_THREADS)
sewardj3b13f0e2002-04-25 20:17:29 +00001395 barf("__res_state: invalid ThreadId");
sewardjb0ff1032002-08-06 09:02:53 +00001396 if (tid == 1)
1397 return & _res;
sewardj3b13f0e2002-04-25 20:17:29 +00001398 return & thread_specific_res_state[tid];
sewardjf8f819e2002-04-17 23:21:37 +00001399}
1400
1401
sewardj5716dbb2002-04-26 03:28:18 +00001402/* ---------------------------------------------------
1403 LIBC-PRIVATE SPECIFIC DATA
1404 ------------------------------------------------ */
1405
1406/* Relies on assumption that initial private data is NULL. This
1407 should be fixed somehow. */
1408
njn25e49d8e72002-09-23 09:36:25 +00001409/* The allowable keys (indices) (all 3 of them).
sewardj5716dbb2002-04-26 03:28:18 +00001410 From sysdeps/pthread/bits/libc-tsd.h
1411*/
sewardjcb7f08a2002-10-02 09:41:49 +00001412/* as per glibc anoncvs HEAD of 20021001. */
sewardj5716dbb2002-04-26 03:28:18 +00001413enum __libc_tsd_key_t { _LIBC_TSD_KEY_MALLOC = 0,
1414 _LIBC_TSD_KEY_DL_ERROR,
njn25e49d8e72002-09-23 09:36:25 +00001415 _LIBC_TSD_KEY_RPC_VARS,
sewardjcb7f08a2002-10-02 09:41:49 +00001416 _LIBC_TSD_KEY_LOCALE,
1417 _LIBC_TSD_KEY_CTYPE_B,
1418 _LIBC_TSD_KEY_CTYPE_TOLOWER,
1419 _LIBC_TSD_KEY_CTYPE_TOUPPER,
sewardj5716dbb2002-04-26 03:28:18 +00001420 _LIBC_TSD_KEY_N };
1421
1422/* Auto-initialising subsystem. libc_specifics_inited is set
1423 after initialisation. libc_specifics_inited_mx guards it. */
1424static int libc_specifics_inited = 0;
1425static pthread_mutex_t libc_specifics_inited_mx = PTHREAD_MUTEX_INITIALIZER;
1426
1427/* These are the keys we must initialise the first time. */
sewardjcb7f08a2002-10-02 09:41:49 +00001428static pthread_key_t libc_specifics_keys[_LIBC_TSD_KEY_N];
sewardj5716dbb2002-04-26 03:28:18 +00001429
sewardjcb7f08a2002-10-02 09:41:49 +00001430/* Initialise the keys, if they are not already initialised. */
sewardj5716dbb2002-04-26 03:28:18 +00001431static
1432void init_libc_tsd_keys ( void )
1433{
1434 int res, i;
1435 pthread_key_t k;
1436
sewardj08c7f012002-10-07 23:56:55 +00001437 /* Don't fall into deadlock if we get called again whilst we still
1438 hold the lock, via the __uselocale() call herein. */
1439 if (libc_specifics_inited != 0)
1440 return;
1441
1442 /* Take the lock. */
sewardj5716dbb2002-04-26 03:28:18 +00001443 res = pthread_mutex_lock(&libc_specifics_inited_mx);
1444 if (res != 0) barf("init_libc_tsd_keys: lock");
1445
sewardj08c7f012002-10-07 23:56:55 +00001446 /* Now test again, to be sure there is no mistake. */
1447 if (libc_specifics_inited != 0) {
1448 res = pthread_mutex_unlock(&libc_specifics_inited_mx);
1449 if (res != 0) barf("init_libc_tsd_keys: unlock(1)");
1450 return;
sewardj5716dbb2002-04-26 03:28:18 +00001451 }
1452
sewardj08c7f012002-10-07 23:56:55 +00001453 /* Actually do the initialisation. */
1454 /* printf("INIT libc specifics\n"); */
1455 for (i = 0; i < _LIBC_TSD_KEY_N; i++) {
1456 res = pthread_key_create(&k, NULL);
1457 if (res != 0) barf("init_libc_tsd_keys: create");
1458 libc_specifics_keys[i] = k;
1459 }
1460
1461 /* Signify init done. */
1462 libc_specifics_inited = 1;
1463
1464# ifdef GLIBC_2_3
1465 /* Set the initialising thread's locale to the global (default)
1466 locale. A hack in support of glibc-2.3. */
1467 __uselocale(LC_GLOBAL_LOCALE);
1468# endif
1469
1470 /* Unlock and return. */
sewardj5716dbb2002-04-26 03:28:18 +00001471 res = pthread_mutex_unlock(&libc_specifics_inited_mx);
1472 if (res != 0) barf("init_libc_tsd_keys: unlock");
1473}
1474
1475
1476static int
1477libc_internal_tsd_set ( enum __libc_tsd_key_t key,
1478 const void * pointer )
1479{
sewardjcb7f08a2002-10-02 09:41:49 +00001480 int res;
sewardj5716dbb2002-04-26 03:28:18 +00001481 /* printf("SET SET SET key %d ptr %p\n", key, pointer); */
sewardjcb7f08a2002-10-02 09:41:49 +00001482 if (key < _LIBC_TSD_KEY_MALLOC || key >= _LIBC_TSD_KEY_N)
sewardj5716dbb2002-04-26 03:28:18 +00001483 barf("libc_internal_tsd_set: invalid key");
1484 init_libc_tsd_keys();
1485 res = pthread_setspecific(libc_specifics_keys[key], pointer);
1486 if (res != 0) barf("libc_internal_tsd_set: setspecific failed");
1487 return 0;
1488}
1489
1490static void *
1491libc_internal_tsd_get ( enum __libc_tsd_key_t key )
1492{
sewardjcb7f08a2002-10-02 09:41:49 +00001493 void* v;
sewardj5716dbb2002-04-26 03:28:18 +00001494 /* printf("GET GET GET key %d\n", key); */
sewardjcb7f08a2002-10-02 09:41:49 +00001495 if (key < _LIBC_TSD_KEY_MALLOC || key >= _LIBC_TSD_KEY_N)
sewardj5716dbb2002-04-26 03:28:18 +00001496 barf("libc_internal_tsd_get: invalid key");
1497 init_libc_tsd_keys();
1498 v = pthread_getspecific(libc_specifics_keys[key]);
1499 /* if (v == NULL) barf("libc_internal_tsd_set: getspecific failed"); */
1500 return v;
1501}
1502
1503
1504
sewardj70adeb22002-04-27 01:35:38 +00001505int (*__libc_internal_tsd_set)
1506 (enum __libc_tsd_key_t key, const void * pointer)
1507 = libc_internal_tsd_set;
sewardj5716dbb2002-04-26 03:28:18 +00001508
sewardj70adeb22002-04-27 01:35:38 +00001509void* (*__libc_internal_tsd_get)
1510 (enum __libc_tsd_key_t key)
1511 = libc_internal_tsd_get;
sewardj5716dbb2002-04-26 03:28:18 +00001512
1513
sewardje663cb92002-04-12 10:26:32 +00001514/* ---------------------------------------------------------------------
1515 These are here (I think) because they are deemed cancellation
1516 points by POSIX. For the moment we'll simply pass the call along
1517 to the corresponding thread-unaware (?) libc routine.
1518 ------------------------------------------------------------------ */
1519
sewardje663cb92002-04-12 10:26:32 +00001520#include <stdlib.h>
sewardje663cb92002-04-12 10:26:32 +00001521#include <sys/types.h>
1522#include <sys/socket.h>
1523
sewardjd529a442002-05-04 19:49:21 +00001524#ifdef GLIBC_2_1
1525extern
1526int __sigaction
1527 (int signum,
1528 const struct sigaction *act,
1529 struct sigaction *oldact);
1530#else
sewardje663cb92002-04-12 10:26:32 +00001531extern
1532int __libc_sigaction
1533 (int signum,
1534 const struct sigaction *act,
1535 struct sigaction *oldact);
sewardjd529a442002-05-04 19:49:21 +00001536#endif
sewardje663cb92002-04-12 10:26:32 +00001537int sigaction(int signum,
1538 const struct sigaction *act,
1539 struct sigaction *oldact)
1540{
sewardjd140e442002-05-29 01:21:19 +00001541 __my_pthread_testcancel();
sewardj2a1dcce2002-04-22 12:45:25 +00001542# ifdef GLIBC_2_1
1543 return __sigaction(signum, act, oldact);
1544# else
sewardj45b4b372002-04-16 22:50:32 +00001545 return __libc_sigaction(signum, act, oldact);
sewardj2a1dcce2002-04-22 12:45:25 +00001546# endif
sewardje663cb92002-04-12 10:26:32 +00001547}
1548
1549
1550extern
1551int __libc_connect(int sockfd,
1552 const struct sockaddr *serv_addr,
1553 socklen_t addrlen);
sewardj5905fae2002-04-26 13:25:00 +00001554__attribute__((weak))
sewardje663cb92002-04-12 10:26:32 +00001555int connect(int sockfd,
1556 const struct sockaddr *serv_addr,
1557 socklen_t addrlen)
1558{
sewardjd140e442002-05-29 01:21:19 +00001559 __my_pthread_testcancel();
sewardj45b4b372002-04-16 22:50:32 +00001560 return __libc_connect(sockfd, serv_addr, addrlen);
sewardje663cb92002-04-12 10:26:32 +00001561}
1562
1563
1564extern
1565int __libc_fcntl(int fd, int cmd, long arg);
sewardj5905fae2002-04-26 13:25:00 +00001566__attribute__((weak))
sewardje663cb92002-04-12 10:26:32 +00001567int fcntl(int fd, int cmd, long arg)
1568{
sewardjd140e442002-05-29 01:21:19 +00001569 __my_pthread_testcancel();
sewardj45b4b372002-04-16 22:50:32 +00001570 return __libc_fcntl(fd, cmd, arg);
sewardje663cb92002-04-12 10:26:32 +00001571}
1572
1573
1574extern
1575ssize_t __libc_write(int fd, const void *buf, size_t count);
sewardj5905fae2002-04-26 13:25:00 +00001576__attribute__((weak))
sewardje663cb92002-04-12 10:26:32 +00001577ssize_t write(int fd, const void *buf, size_t count)
1578{
sewardjd140e442002-05-29 01:21:19 +00001579 __my_pthread_testcancel();
sewardj45b4b372002-04-16 22:50:32 +00001580 return __libc_write(fd, buf, count);
sewardje663cb92002-04-12 10:26:32 +00001581}
1582
1583
1584extern
1585ssize_t __libc_read(int fd, void *buf, size_t count);
sewardj5905fae2002-04-26 13:25:00 +00001586__attribute__((weak))
sewardje663cb92002-04-12 10:26:32 +00001587ssize_t read(int fd, void *buf, size_t count)
1588{
sewardjd140e442002-05-29 01:21:19 +00001589 __my_pthread_testcancel();
sewardj45b4b372002-04-16 22:50:32 +00001590 return __libc_read(fd, buf, count);
sewardje663cb92002-04-12 10:26:32 +00001591}
1592
sewardjbe32e452002-04-24 20:29:58 +00001593
1594extern
sewardj853f55d2002-04-26 00:27:53 +00001595int __libc_open64(const char *pathname, int flags, mode_t mode);
sewardj5905fae2002-04-26 13:25:00 +00001596__attribute__((weak))
sewardj853f55d2002-04-26 00:27:53 +00001597int open64(const char *pathname, int flags, mode_t mode)
sewardjbe32e452002-04-24 20:29:58 +00001598{
sewardjd140e442002-05-29 01:21:19 +00001599 __my_pthread_testcancel();
sewardj853f55d2002-04-26 00:27:53 +00001600 return __libc_open64(pathname, flags, mode);
sewardjbe32e452002-04-24 20:29:58 +00001601}
1602
sewardje663cb92002-04-12 10:26:32 +00001603
1604extern
sewardj853f55d2002-04-26 00:27:53 +00001605int __libc_open(const char *pathname, int flags, mode_t mode);
sewardj5905fae2002-04-26 13:25:00 +00001606__attribute__((weak))
sewardj853f55d2002-04-26 00:27:53 +00001607int open(const char *pathname, int flags, mode_t mode)
sewardje663cb92002-04-12 10:26:32 +00001608{
sewardjd140e442002-05-29 01:21:19 +00001609 __my_pthread_testcancel();
sewardj853f55d2002-04-26 00:27:53 +00001610 return __libc_open(pathname, flags, mode);
sewardje663cb92002-04-12 10:26:32 +00001611}
1612
1613
1614extern
1615int __libc_close(int fd);
sewardj5905fae2002-04-26 13:25:00 +00001616__attribute__((weak))
sewardje663cb92002-04-12 10:26:32 +00001617int close(int fd)
1618{
sewardjd140e442002-05-29 01:21:19 +00001619 __my_pthread_testcancel();
sewardj45b4b372002-04-16 22:50:32 +00001620 return __libc_close(fd);
sewardje663cb92002-04-12 10:26:32 +00001621}
1622
1623
1624extern
1625int __libc_accept(int s, struct sockaddr *addr, socklen_t *addrlen);
sewardj5905fae2002-04-26 13:25:00 +00001626__attribute__((weak))
sewardje663cb92002-04-12 10:26:32 +00001627int accept(int s, struct sockaddr *addr, socklen_t *addrlen)
1628{
sewardjd140e442002-05-29 01:21:19 +00001629 __my_pthread_testcancel();
sewardj705d3cb2002-05-23 13:13:12 +00001630 wait_for_fd_to_be_readable_or_erring(s);
sewardjd140e442002-05-29 01:21:19 +00001631 __my_pthread_testcancel();
sewardj45b4b372002-04-16 22:50:32 +00001632 return __libc_accept(s, addr, addrlen);
sewardje663cb92002-04-12 10:26:32 +00001633}
1634
1635
1636extern
sewardje663cb92002-04-12 10:26:32 +00001637pid_t __libc_waitpid(pid_t pid, int *status, int options);
sewardj5905fae2002-04-26 13:25:00 +00001638__attribute__((weak))
sewardje663cb92002-04-12 10:26:32 +00001639pid_t waitpid(pid_t pid, int *status, int options)
1640{
sewardjd140e442002-05-29 01:21:19 +00001641 __my_pthread_testcancel();
sewardj45b4b372002-04-16 22:50:32 +00001642 return __libc_waitpid(pid, status, options);
sewardje663cb92002-04-12 10:26:32 +00001643}
1644
1645
1646extern
1647int __libc_nanosleep(const struct timespec *req, struct timespec *rem);
sewardj5905fae2002-04-26 13:25:00 +00001648__attribute__((weak))
sewardje663cb92002-04-12 10:26:32 +00001649int nanosleep(const struct timespec *req, struct timespec *rem)
1650{
sewardjd140e442002-05-29 01:21:19 +00001651 __my_pthread_testcancel();
sewardje663cb92002-04-12 10:26:32 +00001652 return __libc_nanosleep(req, rem);
1653}
1654
sewardjbe32e452002-04-24 20:29:58 +00001655
sewardje663cb92002-04-12 10:26:32 +00001656extern
1657int __libc_fsync(int fd);
sewardj5905fae2002-04-26 13:25:00 +00001658__attribute__((weak))
sewardje663cb92002-04-12 10:26:32 +00001659int fsync(int fd)
1660{
sewardjd140e442002-05-29 01:21:19 +00001661 __my_pthread_testcancel();
sewardj45b4b372002-04-16 22:50:32 +00001662 return __libc_fsync(fd);
sewardje663cb92002-04-12 10:26:32 +00001663}
1664
sewardjbe32e452002-04-24 20:29:58 +00001665
sewardj70c75362002-04-13 04:18:32 +00001666extern
1667off_t __libc_lseek(int fildes, off_t offset, int whence);
sewardj5905fae2002-04-26 13:25:00 +00001668__attribute__((weak))
sewardj70c75362002-04-13 04:18:32 +00001669off_t lseek(int fildes, off_t offset, int whence)
1670{
sewardjd140e442002-05-29 01:21:19 +00001671 __my_pthread_testcancel();
sewardj45b4b372002-04-16 22:50:32 +00001672 return __libc_lseek(fildes, offset, whence);
sewardj70c75362002-04-13 04:18:32 +00001673}
1674
sewardjbe32e452002-04-24 20:29:58 +00001675
1676extern
1677__off64_t __libc_lseek64(int fildes, __off64_t offset, int whence);
sewardj5905fae2002-04-26 13:25:00 +00001678__attribute__((weak))
sewardjbe32e452002-04-24 20:29:58 +00001679__off64_t lseek64(int fildes, __off64_t offset, int whence)
1680{
sewardjd140e442002-05-29 01:21:19 +00001681 __my_pthread_testcancel();
sewardjbe32e452002-04-24 20:29:58 +00001682 return __libc_lseek64(fildes, offset, whence);
1683}
1684
1685
sewardj726c4122002-05-16 23:39:10 +00001686extern
1687ssize_t __libc_pread64 (int __fd, void *__buf, size_t __nbytes,
1688 __off64_t __offset);
1689ssize_t __pread64 (int __fd, void *__buf, size_t __nbytes,
1690 __off64_t __offset)
1691{
sewardjd140e442002-05-29 01:21:19 +00001692 __my_pthread_testcancel();
sewardj726c4122002-05-16 23:39:10 +00001693 return __libc_pread64(__fd, __buf, __nbytes, __offset);
1694}
1695
1696
sewardja18e2102002-05-18 10:43:22 +00001697extern
1698ssize_t __libc_pwrite64 (int __fd, const void *__buf, size_t __nbytes,
1699 __off64_t __offset);
1700ssize_t __pwrite64 (int __fd, const void *__buf, size_t __nbytes,
1701 __off64_t __offset)
1702{
sewardjd140e442002-05-29 01:21:19 +00001703 __my_pthread_testcancel();
sewardja18e2102002-05-18 10:43:22 +00001704 return __libc_pwrite64(__fd, __buf, __nbytes, __offset);
1705}
1706
sewardj726c4122002-05-16 23:39:10 +00001707
sewardj39b93b12002-05-18 10:56:27 +00001708extern
1709ssize_t __libc_pwrite(int fd, const void *buf, size_t count, off_t offset);
1710__attribute__((weak))
1711ssize_t pwrite(int fd, const void *buf, size_t count, off_t offset)
1712{
sewardjd140e442002-05-29 01:21:19 +00001713 __my_pthread_testcancel();
sewardj39b93b12002-05-18 10:56:27 +00001714 return __libc_pwrite(fd, buf, count, offset);
1715}
1716
1717
1718extern
1719ssize_t __libc_pread(int fd, void *buf, size_t count, off_t offset);
1720__attribute__((weak))
1721ssize_t pread(int fd, void *buf, size_t count, off_t offset)
1722{
sewardjd140e442002-05-29 01:21:19 +00001723 __my_pthread_testcancel();
sewardj39b93b12002-05-18 10:56:27 +00001724 return __libc_pread(fd, buf, count, offset);
1725}
1726
1727
sewardj6af4b5d2002-04-16 04:40:49 +00001728extern
1729void __libc_longjmp(jmp_buf env, int val) __attribute((noreturn));
sewardj5905fae2002-04-26 13:25:00 +00001730/* not weak: __attribute__((weak)) */
sewardj6af4b5d2002-04-16 04:40:49 +00001731void longjmp(jmp_buf env, int val)
1732{
1733 __libc_longjmp(env, val);
1734}
1735
sewardjbe32e452002-04-24 20:29:58 +00001736
sewardj436c2db2002-06-18 09:07:54 +00001737extern void __libc_siglongjmp (sigjmp_buf env, int val)
1738 __attribute__ ((noreturn));
1739void siglongjmp(sigjmp_buf env, int val)
1740{
1741 kludged("siglongjmp (cleanup handlers are ignored)");
1742 __libc_siglongjmp(env, val);
1743}
1744
1745
sewardj6af4b5d2002-04-16 04:40:49 +00001746extern
1747int __libc_send(int s, const void *msg, size_t len, int flags);
sewardj5905fae2002-04-26 13:25:00 +00001748__attribute__((weak))
sewardj6af4b5d2002-04-16 04:40:49 +00001749int send(int s, const void *msg, size_t len, int flags)
1750{
sewardjd140e442002-05-29 01:21:19 +00001751 __my_pthread_testcancel();
sewardj6af4b5d2002-04-16 04:40:49 +00001752 return __libc_send(s, msg, len, flags);
1753}
1754
sewardjbe32e452002-04-24 20:29:58 +00001755
sewardj1e8cdc92002-04-18 11:37:52 +00001756extern
1757int __libc_recv(int s, void *buf, size_t len, int flags);
sewardj5905fae2002-04-26 13:25:00 +00001758__attribute__((weak))
sewardj1e8cdc92002-04-18 11:37:52 +00001759int recv(int s, void *buf, size_t len, int flags)
1760{
sewardjd140e442002-05-29 01:21:19 +00001761 __my_pthread_testcancel();
sewardj1d6b3a22002-06-20 07:58:33 +00001762 wait_for_fd_to_be_readable_or_erring(s);
1763 __my_pthread_testcancel();
sewardj1e8cdc92002-04-18 11:37:52 +00001764 return __libc_recv(s, buf, len, flags);
1765}
1766
sewardjbe32e452002-04-24 20:29:58 +00001767
sewardj3665ded2002-05-16 16:57:25 +00001768extern
1769int __libc_sendmsg(int s, const struct msghdr *msg, int flags);
1770__attribute__((weak))
1771int sendmsg(int s, const struct msghdr *msg, int flags)
1772{
sewardjd140e442002-05-29 01:21:19 +00001773 __my_pthread_testcancel();
sewardj3665ded2002-05-16 16:57:25 +00001774 return __libc_sendmsg(s, msg, flags);
1775}
1776
1777
sewardj796d6a22002-04-24 02:28:34 +00001778extern
sewardj59da27a2002-06-06 08:33:54 +00001779int __libc_recvmsg(int s, struct msghdr *msg, int flags);
1780__attribute__((weak))
1781int recvmsg(int s, struct msghdr *msg, int flags)
1782{
1783 __my_pthread_testcancel();
1784 return __libc_recvmsg(s, msg, flags);
1785}
1786
1787
1788extern
sewardj436e0582002-04-26 14:31:40 +00001789int __libc_recvfrom(int s, void *buf, size_t len, int flags,
1790 struct sockaddr *from, socklen_t *fromlen);
1791__attribute__((weak))
1792int recvfrom(int s, void *buf, size_t len, int flags,
1793 struct sockaddr *from, socklen_t *fromlen)
1794{
sewardjd140e442002-05-29 01:21:19 +00001795 __my_pthread_testcancel();
sewardj2e207632002-06-13 17:29:53 +00001796 wait_for_fd_to_be_readable_or_erring(s);
1797 __my_pthread_testcancel();
sewardj436e0582002-04-26 14:31:40 +00001798 return __libc_recvfrom(s, buf, len, flags, from, fromlen);
1799}
1800
1801
1802extern
sewardj796d6a22002-04-24 02:28:34 +00001803int __libc_sendto(int s, const void *msg, size_t len, int flags,
1804 const struct sockaddr *to, socklen_t tolen);
sewardj5905fae2002-04-26 13:25:00 +00001805__attribute__((weak))
sewardj796d6a22002-04-24 02:28:34 +00001806int sendto(int s, const void *msg, size_t len, int flags,
1807 const struct sockaddr *to, socklen_t tolen)
1808{
sewardjd140e442002-05-29 01:21:19 +00001809 __my_pthread_testcancel();
sewardj796d6a22002-04-24 02:28:34 +00001810 return __libc_sendto(s, msg, len, flags, to, tolen);
1811}
1812
sewardjbe32e452002-04-24 20:29:58 +00001813
sewardj369b1702002-04-24 13:28:15 +00001814extern
1815int __libc_system(const char* str);
sewardj5905fae2002-04-26 13:25:00 +00001816__attribute__((weak))
sewardj369b1702002-04-24 13:28:15 +00001817int system(const char* str)
1818{
sewardjd140e442002-05-29 01:21:19 +00001819 __my_pthread_testcancel();
sewardj369b1702002-04-24 13:28:15 +00001820 return __libc_system(str);
1821}
1822
sewardjbe32e452002-04-24 20:29:58 +00001823
sewardjab0b1c32002-04-24 19:26:47 +00001824extern
1825pid_t __libc_wait(int *status);
sewardj5905fae2002-04-26 13:25:00 +00001826__attribute__((weak))
sewardjab0b1c32002-04-24 19:26:47 +00001827pid_t wait(int *status)
1828{
sewardjd140e442002-05-29 01:21:19 +00001829 __my_pthread_testcancel();
sewardjab0b1c32002-04-24 19:26:47 +00001830 return __libc_wait(status);
1831}
1832
sewardj45b4b372002-04-16 22:50:32 +00001833
sewardj67f1d582002-05-24 02:11:32 +00001834extern
1835int __libc_msync(const void *start, size_t length, int flags);
1836__attribute__((weak))
1837int msync(const void *start, size_t length, int flags)
1838{
sewardjd140e442002-05-29 01:21:19 +00001839 __my_pthread_testcancel();
sewardj67f1d582002-05-24 02:11:32 +00001840 return __libc_msync(start, length, flags);
1841}
1842
sewardj5905fae2002-04-26 13:25:00 +00001843
sewardj2cb00342002-06-28 01:46:26 +00001844/*--- fork and its helper ---*/
1845
1846static
1847void run_fork_handlers ( int what )
1848{
1849 ForkHandlerEntry entry;
1850 int n_h, n_handlers, i, res;
1851
1852 my_assert(what == 0 || what == 1 || what == 2);
1853
1854 /* Fetch old counter */
1855 VALGRIND_MAGIC_SEQUENCE(n_handlers, -2 /* default */,
1856 VG_USERREQ__GET_FHSTACK_USED,
1857 0, 0, 0, 0);
1858 my_assert(n_handlers >= 0 && n_handlers < VG_N_FORKHANDLERSTACK);
1859
1860 /* Prepare handlers (what == 0) are called in opposite order of
1861 calls to pthread_atfork. Parent and child handlers are called
1862 in the same order as calls to pthread_atfork. */
1863 if (what == 0)
1864 n_h = n_handlers - 1;
1865 else
1866 n_h = 0;
1867
1868 for (i = 0; i < n_handlers; i++) {
1869 VALGRIND_MAGIC_SEQUENCE(res, -2 /* default */,
1870 VG_USERREQ__GET_FHSTACK_ENTRY,
1871 n_h, &entry, 0, 0);
1872 my_assert(res == 0);
1873 switch (what) {
1874 case 0: if (entry.prepare) entry.prepare();
1875 n_h--; break;
1876 case 1: if (entry.parent) entry.parent();
1877 n_h++; break;
1878 case 2: if (entry.child) entry.child();
1879 n_h++; break;
1880 default: barf("run_fork_handlers: invalid what");
1881 }
1882 }
1883
1884 if (what != 0 /* prepare */) {
1885 /* Empty out the stack. */
1886 VALGRIND_MAGIC_SEQUENCE(res, -2 /* default */,
1887 VG_USERREQ__SET_FHSTACK_USED,
1888 0, 0, 0, 0);
1889 my_assert(res == 0);
1890 }
1891}
1892
1893extern
1894pid_t __libc_fork(void);
1895pid_t __fork(void)
1896{
1897 pid_t pid;
1898 __my_pthread_testcancel();
1899 __pthread_mutex_lock(&pthread_atfork_lock);
1900
1901 run_fork_handlers(0 /* prepare */);
1902 pid = __libc_fork();
1903 if (pid == 0) {
1904 /* I am the child */
1905 run_fork_handlers(2 /* child */);
1906 __pthread_mutex_init(&pthread_atfork_lock, NULL);
1907 } else {
1908 /* I am the parent */
1909 run_fork_handlers(1 /* parent */);
1910 __pthread_mutex_unlock(&pthread_atfork_lock);
1911 }
1912 return pid;
1913}
1914
1915
njn25e49d8e72002-09-23 09:36:25 +00001916pid_t __vfork(void)
1917{
1918 return __fork();
1919}
sewardj2cb00342002-06-28 01:46:26 +00001920
1921
sewardj3b13f0e2002-04-25 20:17:29 +00001922/* ---------------------------------------------------------------------
1923 Nonblocking implementations of select() and poll(). This stuff will
1924 surely rot your mind.
1925 ------------------------------------------------------------------ */
sewardje663cb92002-04-12 10:26:32 +00001926
sewardj08a4c3f2002-04-13 03:45:44 +00001927/*--------------------------------------------------*/
1928
1929#include "vg_kerneliface.h"
1930
1931static
1932__inline__
1933int is_kerror ( int res )
1934{
1935 if (res >= -4095 && res <= -1)
1936 return 1;
1937 else
1938 return 0;
1939}
1940
1941
1942static
1943int my_do_syscall1 ( int syscallno, int arg1 )
1944{
1945 int __res;
1946 __asm__ volatile ("pushl %%ebx; movl %%edx,%%ebx ; int $0x80 ; popl %%ebx"
1947 : "=a" (__res)
1948 : "0" (syscallno),
1949 "d" (arg1) );
1950 return __res;
1951}
1952
1953static
1954int my_do_syscall2 ( int syscallno,
sewardjf854f472002-04-21 12:19:41 +00001955 int arg1, int arg2 )
sewardj08a4c3f2002-04-13 03:45:44 +00001956{
1957 int __res;
1958 __asm__ volatile ("pushl %%ebx; movl %%edx,%%ebx ; int $0x80 ; popl %%ebx"
1959 : "=a" (__res)
1960 : "0" (syscallno),
1961 "d" (arg1),
1962 "c" (arg2) );
1963 return __res;
1964}
1965
1966static
sewardjf854f472002-04-21 12:19:41 +00001967int my_do_syscall3 ( int syscallno,
1968 int arg1, int arg2, int arg3 )
1969{
1970 int __res;
1971 __asm__ volatile ("pushl %%ebx; movl %%esi,%%ebx ; int $0x80 ; popl %%ebx"
1972 : "=a" (__res)
1973 : "0" (syscallno),
1974 "S" (arg1),
1975 "c" (arg2),
1976 "d" (arg3) );
1977 return __res;
1978}
1979
1980static
sewardj08a4c3f2002-04-13 03:45:44 +00001981int do_syscall_select( int n,
1982 vki_fd_set* readfds,
1983 vki_fd_set* writefds,
1984 vki_fd_set* exceptfds,
1985 struct vki_timeval * timeout )
1986{
1987 int res;
1988 int args[5];
1989 args[0] = n;
1990 args[1] = (int)readfds;
1991 args[2] = (int)writefds;
1992 args[3] = (int)exceptfds;
1993 args[4] = (int)timeout;
1994 res = my_do_syscall1(__NR_select, (int)(&(args[0])) );
sewardj02535bc2002-04-21 01:08:26 +00001995 return res;
sewardj08a4c3f2002-04-13 03:45:44 +00001996}
1997
1998
1999/* This is a wrapper round select(), which makes it thread-safe,
2000 meaning that only this thread will block, rather than the entire
2001 process. This wrapper in turn depends on nanosleep() not to block
2002 the entire process, but I think (hope? suspect?) that POSIX
2003 pthreads guarantees that to be the case.
2004
2005 Basic idea is: modify the timeout parameter to select so that it
2006 returns immediately. Poll like this until select returns non-zero,
2007 indicating something interesting happened, or until our time is up.
njn25e49d8e72002-09-23 09:36:25 +00002008 Space out the polls with nanosleeps of say 11 milliseconds, which
sewardj08a4c3f2002-04-13 03:45:44 +00002009 is required to be nonblocking; this allows other threads to run.
sewardj02535bc2002-04-21 01:08:26 +00002010
2011 Assumes:
sewardj2d94c112002-06-03 01:25:54 +00002012 * (checked via my_assert) types fd_set and vki_fd_set are identical.
2013 * (checked via my_assert) types timeval and vki_timeval are identical.
sewardj02535bc2002-04-21 01:08:26 +00002014 * (unchecked) libc error numbers (EINTR etc) are the negation of the
2015 kernel's error numbers (VKI_EINTR etc).
sewardj08a4c3f2002-04-13 03:45:44 +00002016*/
sewardj08a4c3f2002-04-13 03:45:44 +00002017
sewardj5905fae2002-04-26 13:25:00 +00002018/* __attribute__((weak)) */
sewardj08a4c3f2002-04-13 03:45:44 +00002019int select ( int n,
2020 fd_set *rfds,
2021 fd_set *wfds,
2022 fd_set *xfds,
2023 struct timeval *timeout )
2024{
sewardj5f07b662002-04-23 16:52:51 +00002025 unsigned int ms_now, ms_end;
sewardj08a4c3f2002-04-13 03:45:44 +00002026 int res;
2027 fd_set rfds_copy;
2028 fd_set wfds_copy;
2029 fd_set xfds_copy;
2030 struct vki_timeval t_now;
sewardj08a4c3f2002-04-13 03:45:44 +00002031 struct vki_timeval zero_timeout;
2032 struct vki_timespec nanosleep_interval;
2033
sewardjd140e442002-05-29 01:21:19 +00002034 __my_pthread_testcancel();
2035
sewardj5f07b662002-04-23 16:52:51 +00002036 /* gcc's complains about ms_end being used uninitialised -- classic
2037 case it can't understand, where ms_end is both defined and used
2038 only if timeout != NULL. Hence ... */
2039 ms_end = 0;
sewardj08a4c3f2002-04-13 03:45:44 +00002040
2041 /* We assume that the kernel and libc data layouts are identical
2042 for the following types. These asserts provide a crude
2043 check. */
2044 if (sizeof(fd_set) != sizeof(vki_fd_set)
2045 || sizeof(struct timeval) != sizeof(struct vki_timeval))
2046 barf("valgrind's hacky non-blocking select(): data sizes error");
2047
sewardj5f07b662002-04-23 16:52:51 +00002048 /* Detect the current time and simultaneously find out if we are
2049 running on Valgrind. */
2050 VALGRIND_MAGIC_SEQUENCE(ms_now, 0xFFFFFFFF /* default */,
2051 VG_USERREQ__READ_MILLISECOND_TIMER,
2052 0, 0, 0, 0);
2053
2054 /* If a zero timeout specified, this call is harmless. Also go
2055 this route if we're not running on Valgrind, for whatever
2056 reason. */
2057 if ( (timeout && timeout->tv_sec == 0 && timeout->tv_usec == 0)
2058 || (ms_now == 0xFFFFFFFF) ) {
sewardj02535bc2002-04-21 01:08:26 +00002059 res = do_syscall_select( n, (vki_fd_set*)rfds,
sewardj08a4c3f2002-04-13 03:45:44 +00002060 (vki_fd_set*)wfds,
2061 (vki_fd_set*)xfds,
2062 (struct vki_timeval*)timeout);
sewardj02535bc2002-04-21 01:08:26 +00002063 if (is_kerror(res)) {
2064 * (__errno_location()) = -res;
2065 return -1;
2066 } else {
2067 return res;
2068 }
2069 }
sewardj08a4c3f2002-04-13 03:45:44 +00002070
sewardj5f07b662002-04-23 16:52:51 +00002071 /* If a timeout was specified, set ms_end to be the end millisecond
2072 counter [wallclock] time. */
sewardj08a4c3f2002-04-13 03:45:44 +00002073 if (timeout) {
2074 res = my_do_syscall2(__NR_gettimeofday, (int)&t_now, (int)NULL);
sewardj2d94c112002-06-03 01:25:54 +00002075 my_assert(res == 0);
sewardj5f07b662002-04-23 16:52:51 +00002076 ms_end = ms_now;
2077 ms_end += (timeout->tv_usec / 1000);
2078 ms_end += (timeout->tv_sec * 1000);
sewardj08a4c3f2002-04-13 03:45:44 +00002079 /* Stay sane ... */
sewardj2d94c112002-06-03 01:25:54 +00002080 my_assert (ms_end >= ms_now);
sewardj08a4c3f2002-04-13 03:45:44 +00002081 }
2082
2083 /* fprintf(stderr, "MY_SELECT: before loop\n"); */
2084
2085 /* Either timeout == NULL, meaning wait indefinitely, or timeout !=
sewardj5f07b662002-04-23 16:52:51 +00002086 NULL, in which case ms_end holds the end time. */
sewardj05bb2c92002-06-26 00:47:17 +00002087
sewardj08a4c3f2002-04-13 03:45:44 +00002088 while (1) {
sewardj05bb2c92002-06-26 00:47:17 +00002089
2090 /* First, do a return-immediately select(). */
sewardj08a4c3f2002-04-13 03:45:44 +00002091
2092 /* These could be trashed each time round the loop, so restore
2093 them each time. */
2094 if (rfds) rfds_copy = *rfds;
2095 if (wfds) wfds_copy = *wfds;
2096 if (xfds) xfds_copy = *xfds;
2097
2098 zero_timeout.tv_sec = zero_timeout.tv_usec = 0;
2099
2100 res = do_syscall_select( n,
2101 rfds ? (vki_fd_set*)(&rfds_copy) : NULL,
2102 wfds ? (vki_fd_set*)(&wfds_copy) : NULL,
2103 xfds ? (vki_fd_set*)(&xfds_copy) : NULL,
2104 & zero_timeout );
sewardj02535bc2002-04-21 01:08:26 +00002105 if (is_kerror(res)) {
2106 /* Some kind of error (including EINTR). Set errno and
sewardj08a4c3f2002-04-13 03:45:44 +00002107 return. The sets are unspecified in this case. */
sewardj02535bc2002-04-21 01:08:26 +00002108 * (__errno_location()) = -res;
2109 return -1;
sewardj08a4c3f2002-04-13 03:45:44 +00002110 }
2111 if (res > 0) {
2112 /* one or more fds is ready. Copy out resulting sets and
2113 return. */
2114 if (rfds) *rfds = rfds_copy;
2115 if (wfds) *wfds = wfds_copy;
2116 if (xfds) *xfds = xfds_copy;
2117 return res;
2118 }
sewardj05bb2c92002-06-26 00:47:17 +00002119
2120 /* Nothing interesting happened, so we go to sleep for a
2121 while. */
2122
sewardj08a4c3f2002-04-13 03:45:44 +00002123 /* fprintf(stderr, "MY_SELECT: nanosleep\n"); */
2124 /* nanosleep and go round again */
sewardj02535bc2002-04-21 01:08:26 +00002125 nanosleep_interval.tv_sec = 0;
njn25e49d8e72002-09-23 09:36:25 +00002126 nanosleep_interval.tv_nsec = 11 * 1000 * 1000; /* 11 milliseconds */
sewardjf854f472002-04-21 12:19:41 +00002127 /* It's critical here that valgrind's nanosleep implementation
2128 is nonblocking. */
sewardj645030e2002-06-06 01:27:39 +00002129 res = my_do_syscall2(__NR_nanosleep,
sewardjf854f472002-04-21 12:19:41 +00002130 (int)(&nanosleep_interval), (int)NULL);
sewardj645030e2002-06-06 01:27:39 +00002131 if (res == -VKI_EINTR) {
2132 /* The nanosleep was interrupted by a signal. So we do the
2133 same. */
2134 * (__errno_location()) = EINTR;
2135 return -1;
2136 }
sewardj05bb2c92002-06-26 00:47:17 +00002137
2138 /* Sleeping finished. If a finite timeout, check to see if it
2139 has expired yet. */
2140 if (timeout) {
2141 VALGRIND_MAGIC_SEQUENCE(ms_now, 0xFFFFFFFF /* default */,
2142 VG_USERREQ__READ_MILLISECOND_TIMER,
2143 0, 0, 0, 0);
2144 my_assert(ms_now != 0xFFFFFFFF);
2145 if (ms_now >= ms_end) {
2146 /* timeout; nothing interesting happened. */
2147 if (rfds) FD_ZERO(rfds);
2148 if (wfds) FD_ZERO(wfds);
2149 if (xfds) FD_ZERO(xfds);
2150 return 0;
2151 }
2152 }
2153
sewardjf854f472002-04-21 12:19:41 +00002154 }
2155}
2156
2157
2158
2159
2160#include <sys/poll.h>
2161
sewardj3e909ce2002-06-03 13:27:15 +00002162#ifndef HAVE_NFDS_T
sewardj72d58482002-04-24 02:20:20 +00002163typedef unsigned long int nfds_t;
2164#endif
2165
sewardj705d3cb2002-05-23 13:13:12 +00002166
sewardj5905fae2002-04-26 13:25:00 +00002167/* __attribute__((weak)) */
sewardjf854f472002-04-21 12:19:41 +00002168int poll (struct pollfd *__fds, nfds_t __nfds, int __timeout)
2169{
sewardj5f07b662002-04-23 16:52:51 +00002170 unsigned int ms_now, ms_end;
sewardjf854f472002-04-21 12:19:41 +00002171 int res, i;
sewardjf854f472002-04-21 12:19:41 +00002172 struct vki_timespec nanosleep_interval;
2173
sewardjd140e442002-05-29 01:21:19 +00002174 __my_pthread_testcancel();
sewardjf854f472002-04-21 12:19:41 +00002175 ensure_valgrind("poll");
2176
sewardj5f07b662002-04-23 16:52:51 +00002177 /* Detect the current time and simultaneously find out if we are
2178 running on Valgrind. */
2179 VALGRIND_MAGIC_SEQUENCE(ms_now, 0xFFFFFFFF /* default */,
2180 VG_USERREQ__READ_MILLISECOND_TIMER,
2181 0, 0, 0, 0);
2182
sewardjf854f472002-04-21 12:19:41 +00002183 if (/* CHECK SIZES FOR struct pollfd */
2184 sizeof(struct timeval) != sizeof(struct vki_timeval))
2185 barf("valgrind's hacky non-blocking poll(): data sizes error");
2186
sewardj5f07b662002-04-23 16:52:51 +00002187 /* dummy initialisation to keep gcc -Wall happy */
2188 ms_end = 0;
2189
2190 /* If a zero timeout specified, this call is harmless. Also do
2191 this if not running on Valgrind. */
2192 if (__timeout == 0 || ms_now == 0xFFFFFFFF) {
sewardjf854f472002-04-21 12:19:41 +00002193 res = my_do_syscall3(__NR_poll, (int)__fds, __nfds, __timeout);
2194 if (is_kerror(res)) {
2195 * (__errno_location()) = -res;
2196 return -1;
2197 } else {
2198 return res;
2199 }
2200 }
2201
sewardj5f07b662002-04-23 16:52:51 +00002202 /* If a timeout was specified, set ms_end to be the end wallclock
2203 time. Easy considering that __timeout is in milliseconds. */
sewardjf854f472002-04-21 12:19:41 +00002204 if (__timeout > 0) {
sewardj650ac002002-04-29 12:20:34 +00002205 ms_end = ms_now + (unsigned int)__timeout;
sewardjf854f472002-04-21 12:19:41 +00002206 }
2207
2208 /* fprintf(stderr, "MY_POLL: before loop\n"); */
2209
2210 /* Either timeout < 0, meaning wait indefinitely, or timeout > 0,
2211 in which case t_end holds the end time. */
sewardj05bb2c92002-06-26 00:47:17 +00002212
sewardj2d94c112002-06-03 01:25:54 +00002213 my_assert(__timeout != 0);
sewardj5f07b662002-04-23 16:52:51 +00002214
sewardjf854f472002-04-21 12:19:41 +00002215 while (1) {
sewardj05bb2c92002-06-26 00:47:17 +00002216
2217 /* Do a return-immediately poll. */
2218
2219 res = my_do_syscall3(__NR_poll, (int)__fds, __nfds, 0 );
2220 if (is_kerror(res)) {
2221 /* Some kind of error. Set errno and return. */
2222 * (__errno_location()) = -res;
2223 return -1;
2224 }
2225 if (res > 0) {
2226 /* One or more fds is ready. Return now. */
2227 return res;
2228 }
2229
2230 /* Nothing interesting happened, so we go to sleep for a
2231 while. */
2232
2233 /* fprintf(stderr, "MY_POLL: nanosleep\n"); */
2234 /* nanosleep and go round again */
2235 nanosleep_interval.tv_sec = 0;
njn25e49d8e72002-09-23 09:36:25 +00002236 nanosleep_interval.tv_nsec = 13 * 1000 * 1000; /* 13 milliseconds */
sewardj05bb2c92002-06-26 00:47:17 +00002237 /* It's critical here that valgrind's nanosleep implementation
2238 is nonblocking. */
2239 (void)my_do_syscall2(__NR_nanosleep,
2240 (int)(&nanosleep_interval), (int)NULL);
2241
2242 /* Sleeping finished. If a finite timeout, check to see if it
2243 has expired yet. */
sewardjf854f472002-04-21 12:19:41 +00002244 if (__timeout > 0) {
sewardj5f07b662002-04-23 16:52:51 +00002245 VALGRIND_MAGIC_SEQUENCE(ms_now, 0xFFFFFFFF /* default */,
2246 VG_USERREQ__READ_MILLISECOND_TIMER,
2247 0, 0, 0, 0);
sewardj2d94c112002-06-03 01:25:54 +00002248 my_assert(ms_now != 0xFFFFFFFF);
sewardj5f07b662002-04-23 16:52:51 +00002249 if (ms_now >= ms_end) {
sewardjf854f472002-04-21 12:19:41 +00002250 /* timeout; nothing interesting happened. */
2251 for (i = 0; i < __nfds; i++)
2252 __fds[i].revents = 0;
2253 return 0;
2254 }
2255 }
2256
sewardj08a4c3f2002-04-13 03:45:44 +00002257 }
2258}
sewardj3b13f0e2002-04-25 20:17:29 +00002259
2260
sewardj705d3cb2002-05-23 13:13:12 +00002261/* Helper function used to make accept() non-blocking. Idea is to use
2262 the above nonblocking poll() to make this thread ONLY wait for the
2263 specified fd to become ready, and then return. */
sewardjd1c1cf22002-06-26 00:13:36 +00002264
2265/* Sigh -- a hack. We're not supposed to include this file directly;
2266 should do it via /usr/include/fcntl.h, but that introduces a
2267 varargs prototype for fcntl itself, which we can't mimic. */
2268#define _FCNTL_H
2269#include <bits/fcntl.h>
2270
sewardj705d3cb2002-05-23 13:13:12 +00002271static void wait_for_fd_to_be_readable_or_erring ( int fd )
2272{
2273 struct pollfd pfd;
sewardjd1c1cf22002-06-26 00:13:36 +00002274 int res;
2275
sewardj6e6cbaa2002-05-24 02:12:52 +00002276 /* fprintf(stderr, "wait_for_fd_to_be_readable_or_erring %d\n", fd); */
sewardjd1c1cf22002-06-26 00:13:36 +00002277
2278 /* First check to see if the fd is nonblocking, and/or invalid. In
2279 either case return immediately. */
2280 res = __libc_fcntl(fd, F_GETFL, 0);
2281 if (res == -1) return; /* fd is invalid somehow */
2282 if (res & O_NONBLOCK) return; /* fd is nonblocking */
2283
2284 /* Ok, we'd better wait with poll. */
sewardj705d3cb2002-05-23 13:13:12 +00002285 pfd.fd = fd;
2286 pfd.events = POLLIN | POLLPRI | POLLERR | POLLHUP | POLLNVAL;
2287 /* ... but not POLLOUT, you may notice. */
2288 pfd.revents = 0;
2289 (void)poll(&pfd, 1, -1 /* forever */);
2290}
2291
2292
sewardj3b13f0e2002-04-25 20:17:29 +00002293/* ---------------------------------------------------------------------
sewardj8f253ff2002-05-19 00:13:34 +00002294 Hacky implementation of semaphores.
2295 ------------------------------------------------------------------ */
2296
2297#include <semaphore.h>
2298
2299/* This is a terrible way to do the remapping. Plan is to import an
2300 AVL tree at some point. */
sewardj8f253ff2002-05-19 00:13:34 +00002301
2302typedef
2303 struct {
2304 pthread_mutex_t se_mx;
2305 pthread_cond_t se_cv;
2306 int count;
2307 }
2308 vg_sem_t;
2309
2310static pthread_mutex_t se_remap_mx = PTHREAD_MUTEX_INITIALIZER;
2311
2312static int se_remap_used = 0;
2313static sem_t* se_remap_orig[VG_N_SEMAPHORES];
2314static vg_sem_t se_remap_new[VG_N_SEMAPHORES];
2315
2316static vg_sem_t* se_remap ( sem_t* orig )
2317{
2318 int res, i;
2319 res = __pthread_mutex_lock(&se_remap_mx);
sewardj2d94c112002-06-03 01:25:54 +00002320 my_assert(res == 0);
sewardj8f253ff2002-05-19 00:13:34 +00002321
2322 for (i = 0; i < se_remap_used; i++) {
2323 if (se_remap_orig[i] == orig)
2324 break;
2325 }
2326 if (i == se_remap_used) {
2327 if (se_remap_used == VG_N_SEMAPHORES) {
2328 res = pthread_mutex_unlock(&se_remap_mx);
sewardj2d94c112002-06-03 01:25:54 +00002329 my_assert(res == 0);
sewardja1ac5cb2002-05-27 13:00:05 +00002330 barf("VG_N_SEMAPHORES is too low. Increase and recompile.");
sewardj8f253ff2002-05-19 00:13:34 +00002331 }
2332 se_remap_used++;
2333 se_remap_orig[i] = orig;
2334 /* printf("allocated semaphore %d\n", i); */
2335 }
2336 res = __pthread_mutex_unlock(&se_remap_mx);
sewardj2d94c112002-06-03 01:25:54 +00002337 my_assert(res == 0);
sewardj8f253ff2002-05-19 00:13:34 +00002338 return &se_remap_new[i];
2339}
2340
2341
2342int sem_init(sem_t *sem, int pshared, unsigned int value)
2343{
2344 int res;
2345 vg_sem_t* vg_sem;
2346 ensure_valgrind("sem_init");
2347 if (pshared != 0) {
sewardj4dced352002-06-04 22:54:20 +00002348 pthread_error("sem_init: unsupported pshared value");
sewardj8f253ff2002-05-19 00:13:34 +00002349 errno = ENOSYS;
2350 return -1;
2351 }
2352 vg_sem = se_remap(sem);
2353 res = pthread_mutex_init(&vg_sem->se_mx, NULL);
sewardj2d94c112002-06-03 01:25:54 +00002354 my_assert(res == 0);
sewardj8f253ff2002-05-19 00:13:34 +00002355 res = pthread_cond_init(&vg_sem->se_cv, NULL);
sewardj2d94c112002-06-03 01:25:54 +00002356 my_assert(res == 0);
sewardj8f253ff2002-05-19 00:13:34 +00002357 vg_sem->count = value;
2358 return 0;
2359}
2360
2361
2362int sem_wait ( sem_t* sem )
2363{
2364 int res;
2365 vg_sem_t* vg_sem;
2366 ensure_valgrind("sem_wait");
2367 vg_sem = se_remap(sem);
2368 res = __pthread_mutex_lock(&vg_sem->se_mx);
sewardj2d94c112002-06-03 01:25:54 +00002369 my_assert(res == 0);
sewardj8f253ff2002-05-19 00:13:34 +00002370 while (vg_sem->count == 0) {
2371 res = pthread_cond_wait(&vg_sem->se_cv, &vg_sem->se_mx);
sewardj2d94c112002-06-03 01:25:54 +00002372 my_assert(res == 0);
sewardj8f253ff2002-05-19 00:13:34 +00002373 }
2374 vg_sem->count--;
2375 res = __pthread_mutex_unlock(&vg_sem->se_mx);
sewardj2d94c112002-06-03 01:25:54 +00002376 my_assert(res == 0);
sewardj8f253ff2002-05-19 00:13:34 +00002377 return 0;
2378}
2379
2380int sem_post ( sem_t* sem )
2381{
2382 int res;
2383 vg_sem_t* vg_sem;
2384 ensure_valgrind("sem_post");
2385 vg_sem = se_remap(sem);
2386 res = __pthread_mutex_lock(&vg_sem->se_mx);
sewardj2d94c112002-06-03 01:25:54 +00002387 my_assert(res == 0);
sewardj8f253ff2002-05-19 00:13:34 +00002388 if (vg_sem->count == 0) {
2389 vg_sem->count++;
2390 res = pthread_cond_broadcast(&vg_sem->se_cv);
sewardj2d94c112002-06-03 01:25:54 +00002391 my_assert(res == 0);
sewardj8f253ff2002-05-19 00:13:34 +00002392 } else {
2393 vg_sem->count++;
2394 }
2395 res = __pthread_mutex_unlock(&vg_sem->se_mx);
sewardj2d94c112002-06-03 01:25:54 +00002396 my_assert(res == 0);
sewardj8f253ff2002-05-19 00:13:34 +00002397 return 0;
2398}
2399
2400
2401int sem_trywait ( sem_t* sem )
2402{
2403 int ret, res;
2404 vg_sem_t* vg_sem;
2405 ensure_valgrind("sem_trywait");
2406 vg_sem = se_remap(sem);
2407 res = __pthread_mutex_lock(&vg_sem->se_mx);
sewardj2d94c112002-06-03 01:25:54 +00002408 my_assert(res == 0);
sewardj8f253ff2002-05-19 00:13:34 +00002409 if (vg_sem->count > 0) {
2410 vg_sem->count--;
2411 ret = 0;
2412 } else {
2413 ret = -1;
2414 errno = EAGAIN;
2415 }
2416 res = __pthread_mutex_unlock(&vg_sem->se_mx);
sewardj2d94c112002-06-03 01:25:54 +00002417 my_assert(res == 0);
sewardj8f253ff2002-05-19 00:13:34 +00002418 return ret;
2419}
2420
2421
2422int sem_getvalue(sem_t* sem, int * sval)
2423{
2424 vg_sem_t* vg_sem;
2425 ensure_valgrind("sem_trywait");
2426 vg_sem = se_remap(sem);
2427 *sval = vg_sem->count;
2428 return 0;
2429}
2430
2431
2432int sem_destroy(sem_t * sem)
2433{
2434 kludged("sem_destroy");
2435 /* if someone waiting on this semaphore, errno = EBUSY, return -1 */
2436 return 0;
2437}
2438
2439
2440/* ---------------------------------------------------------------------
sewardj2d8b3f02002-06-01 14:14:19 +00002441 Reader-writer locks.
sewardja1ac5cb2002-05-27 13:00:05 +00002442 ------------------------------------------------------------------ */
2443
sewardj2d8b3f02002-06-01 14:14:19 +00002444typedef
2445 struct {
2446 int initted; /* != 0 --> in use; sanity check only */
2447 int prefer_w; /* != 0 --> prefer writer */
2448 int nwait_r; /* # of waiting readers */
2449 int nwait_w; /* # of waiting writers */
2450 pthread_cond_t cv_r; /* for signalling readers */
2451 pthread_cond_t cv_w; /* for signalling writers */
2452 pthread_mutex_t mx;
2453 int status;
2454 /* allowed range for status: >= -1. -1 means 1 writer currently
2455 active, >= 0 means N readers currently active. */
2456 }
2457 vg_rwlock_t;
sewardja1ac5cb2002-05-27 13:00:05 +00002458
2459
2460static pthread_mutex_t rw_remap_mx = PTHREAD_MUTEX_INITIALIZER;
2461
2462static int rw_remap_used = 0;
2463static pthread_rwlock_t* rw_remap_orig[VG_N_RWLOCKS];
2464static vg_rwlock_t rw_remap_new[VG_N_RWLOCKS];
2465
sewardj2d8b3f02002-06-01 14:14:19 +00002466
2467static
2468void init_vg_rwlock ( vg_rwlock_t* vg_rwl )
2469{
2470 int res = 0;
2471 vg_rwl->initted = 1;
2472 vg_rwl->prefer_w = 1;
2473 vg_rwl->nwait_r = 0;
2474 vg_rwl->nwait_w = 0;
2475 vg_rwl->status = 0;
2476 res = pthread_mutex_init(&vg_rwl->mx, NULL);
2477 res |= pthread_cond_init(&vg_rwl->cv_r, NULL);
2478 res |= pthread_cond_init(&vg_rwl->cv_w, NULL);
sewardj2d94c112002-06-03 01:25:54 +00002479 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002480}
2481
2482
sewardja1ac5cb2002-05-27 13:00:05 +00002483/* Take the address of a LinuxThreads rwlock_t and return the shadow
2484 address of our version. Further, if the LinuxThreads version
2485 appears to have been statically initialised, do the same to the one
2486 we allocate here. The pthread_rwlock_t.__rw_readers field is set
2487 to zero by PTHREAD_RWLOCK_INITIALIZER, so we take zero as meaning
2488 uninitialised and non-zero meaning initialised.
2489*/
2490static vg_rwlock_t* rw_remap ( pthread_rwlock_t* orig )
2491{
2492 int res, i;
2493 vg_rwlock_t* vg_rwl;
2494 res = __pthread_mutex_lock(&rw_remap_mx);
sewardj2d94c112002-06-03 01:25:54 +00002495 my_assert(res == 0);
sewardja1ac5cb2002-05-27 13:00:05 +00002496
2497 for (i = 0; i < rw_remap_used; i++) {
2498 if (rw_remap_orig[i] == orig)
2499 break;
2500 }
2501 if (i == rw_remap_used) {
2502 if (rw_remap_used == VG_N_RWLOCKS) {
sewardj2d8b3f02002-06-01 14:14:19 +00002503 res = __pthread_mutex_unlock(&rw_remap_mx);
sewardj2d94c112002-06-03 01:25:54 +00002504 my_assert(res == 0);
sewardja1ac5cb2002-05-27 13:00:05 +00002505 barf("VG_N_RWLOCKS is too low. Increase and recompile.");
2506 }
2507 rw_remap_used++;
2508 rw_remap_orig[i] = orig;
sewardj2d8b3f02002-06-01 14:14:19 +00002509 rw_remap_new[i].initted = 0;
sewardja1ac5cb2002-05-27 13:00:05 +00002510 if (0) printf("allocated rwlock %d\n", i);
2511 }
2512 res = __pthread_mutex_unlock(&rw_remap_mx);
sewardj2d94c112002-06-03 01:25:54 +00002513 my_assert(res == 0);
sewardja1ac5cb2002-05-27 13:00:05 +00002514 vg_rwl = &rw_remap_new[i];
2515
sewardj2d8b3f02002-06-01 14:14:19 +00002516 /* Initialise the shadow, if required. */
sewardja1ac5cb2002-05-27 13:00:05 +00002517 if (orig->__rw_readers == 0) {
sewardja1ac5cb2002-05-27 13:00:05 +00002518 orig->__rw_readers = 1;
sewardj2d8b3f02002-06-01 14:14:19 +00002519 init_vg_rwlock(vg_rwl);
sewardja1ac5cb2002-05-27 13:00:05 +00002520 if (orig->__rw_kind == PTHREAD_RWLOCK_PREFER_READER_NP)
sewardj2d8b3f02002-06-01 14:14:19 +00002521 vg_rwl->prefer_w = 0;
sewardja1ac5cb2002-05-27 13:00:05 +00002522 }
2523
2524 return vg_rwl;
2525}
2526
2527
sewardja1ac5cb2002-05-27 13:00:05 +00002528int pthread_rwlock_init ( pthread_rwlock_t* orig,
2529 const pthread_rwlockattr_t* attr )
2530{
sewardja1ac5cb2002-05-27 13:00:05 +00002531 vg_rwlock_t* rwl;
2532 if (0) printf ("pthread_rwlock_init\n");
2533 /* Force the remapper to initialise the shadow. */
2534 orig->__rw_readers = 0;
2535 /* Install the lock preference; the remapper needs to know it. */
2536 orig->__rw_kind = PTHREAD_RWLOCK_DEFAULT_NP;
2537 if (attr)
2538 orig->__rw_kind = attr->__lockkind;
2539 rwl = rw_remap ( orig );
sewardj2d8b3f02002-06-01 14:14:19 +00002540 return 0;
sewardja1ac5cb2002-05-27 13:00:05 +00002541}
2542
sewardj2d8b3f02002-06-01 14:14:19 +00002543
2544static
2545void pthread_rwlock_rdlock_CANCEL_HDLR ( void* rwl_v )
sewardja1ac5cb2002-05-27 13:00:05 +00002546{
sewardj2d8b3f02002-06-01 14:14:19 +00002547 vg_rwlock_t* rwl = (vg_rwlock_t*)rwl_v;
2548 rwl->nwait_r--;
2549 pthread_mutex_unlock (&rwl->mx);
sewardja1ac5cb2002-05-27 13:00:05 +00002550}
2551
sewardj2d8b3f02002-06-01 14:14:19 +00002552
sewardja1ac5cb2002-05-27 13:00:05 +00002553int pthread_rwlock_rdlock ( pthread_rwlock_t* orig )
2554{
2555 int res;
2556 vg_rwlock_t* rwl;
2557 if (0) printf ("pthread_rwlock_rdlock\n");
2558 rwl = rw_remap ( orig );
sewardj2d8b3f02002-06-01 14:14:19 +00002559 res = __pthread_mutex_lock(&rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00002560 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002561 if (!rwl->initted) {
2562 res = __pthread_mutex_unlock(&rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00002563 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002564 return EINVAL;
2565 }
2566 if (rwl->status < 0) {
sewardj2d94c112002-06-03 01:25:54 +00002567 my_assert(rwl->status == -1);
sewardj2d8b3f02002-06-01 14:14:19 +00002568 rwl->nwait_r++;
2569 pthread_cleanup_push( pthread_rwlock_rdlock_CANCEL_HDLR, rwl );
2570 while (1) {
2571 if (rwl->status == 0) break;
2572 res = pthread_cond_wait(&rwl->cv_r, &rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00002573 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002574 }
2575 pthread_cleanup_pop(0);
2576 rwl->nwait_r--;
2577 }
sewardj2d94c112002-06-03 01:25:54 +00002578 my_assert(rwl->status >= 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002579 rwl->status++;
2580 res = __pthread_mutex_unlock(&rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00002581 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002582 return 0;
sewardja1ac5cb2002-05-27 13:00:05 +00002583}
2584
sewardj2d8b3f02002-06-01 14:14:19 +00002585
sewardja1ac5cb2002-05-27 13:00:05 +00002586int pthread_rwlock_tryrdlock ( pthread_rwlock_t* orig )
2587{
2588 int res;
2589 vg_rwlock_t* rwl;
2590 if (0) printf ("pthread_rwlock_tryrdlock\n");
2591 rwl = rw_remap ( orig );
sewardj2d8b3f02002-06-01 14:14:19 +00002592 res = __pthread_mutex_lock(&rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00002593 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002594 if (!rwl->initted) {
2595 res = __pthread_mutex_unlock(&rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00002596 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002597 return EINVAL;
2598 }
2599 if (rwl->status == -1) {
2600 /* Writer active; we have to give up. */
2601 res = __pthread_mutex_unlock(&rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00002602 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002603 return EBUSY;
2604 }
2605 /* Success */
sewardj2d94c112002-06-03 01:25:54 +00002606 my_assert(rwl->status >= 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002607 rwl->status++;
2608 res = __pthread_mutex_unlock(&rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00002609 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002610 return 0;
sewardja1ac5cb2002-05-27 13:00:05 +00002611}
2612
sewardj2d8b3f02002-06-01 14:14:19 +00002613
2614static
2615void pthread_rwlock_wrlock_CANCEL_HDLR ( void* rwl_v )
2616{
2617 vg_rwlock_t* rwl = (vg_rwlock_t*)rwl_v;
2618 rwl->nwait_w--;
2619 pthread_mutex_unlock (&rwl->mx);
2620}
2621
2622
sewardja1ac5cb2002-05-27 13:00:05 +00002623int pthread_rwlock_wrlock ( pthread_rwlock_t* orig )
2624{
2625 int res;
2626 vg_rwlock_t* rwl;
2627 if (0) printf ("pthread_rwlock_wrlock\n");
2628 rwl = rw_remap ( orig );
sewardj2d8b3f02002-06-01 14:14:19 +00002629 res = __pthread_mutex_lock(&rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00002630 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002631 if (!rwl->initted) {
2632 res = __pthread_mutex_unlock(&rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00002633 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002634 return EINVAL;
2635 }
2636 if (rwl->status != 0) {
2637 rwl->nwait_w++;
2638 pthread_cleanup_push( pthread_rwlock_wrlock_CANCEL_HDLR, rwl );
2639 while (1) {
2640 if (rwl->status == 0) break;
2641 res = pthread_cond_wait(&rwl->cv_w, &rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00002642 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002643 }
2644 pthread_cleanup_pop(0);
2645 rwl->nwait_w--;
2646 }
sewardj2d94c112002-06-03 01:25:54 +00002647 my_assert(rwl->status == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002648 rwl->status = -1;
2649 res = __pthread_mutex_unlock(&rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00002650 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002651 return 0;
sewardja1ac5cb2002-05-27 13:00:05 +00002652}
2653
sewardj2d8b3f02002-06-01 14:14:19 +00002654
sewardja1ac5cb2002-05-27 13:00:05 +00002655int pthread_rwlock_trywrlock ( pthread_rwlock_t* orig )
2656{
2657 int res;
2658 vg_rwlock_t* rwl;
sewardj2d8b3f02002-06-01 14:14:19 +00002659 if (0) printf ("pthread_wrlock_trywrlock\n");
sewardja1ac5cb2002-05-27 13:00:05 +00002660 rwl = rw_remap ( orig );
sewardj2d8b3f02002-06-01 14:14:19 +00002661 res = __pthread_mutex_lock(&rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00002662 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002663 if (!rwl->initted) {
2664 res = __pthread_mutex_unlock(&rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00002665 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002666 return EINVAL;
2667 }
2668 if (rwl->status != 0) {
2669 /* Reader(s) or a writer active; we have to give up. */
2670 res = __pthread_mutex_unlock(&rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00002671 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002672 return EBUSY;
2673 }
2674 /* Success */
sewardj2d94c112002-06-03 01:25:54 +00002675 my_assert(rwl->status == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002676 rwl->status = -1;
2677 res = __pthread_mutex_unlock(&rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00002678 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002679 return 0;
sewardja1ac5cb2002-05-27 13:00:05 +00002680}
2681
sewardj2d8b3f02002-06-01 14:14:19 +00002682
sewardja1ac5cb2002-05-27 13:00:05 +00002683int pthread_rwlock_unlock ( pthread_rwlock_t* orig )
2684{
2685 int res;
2686 vg_rwlock_t* rwl;
2687 if (0) printf ("pthread_rwlock_unlock\n");
2688 rwl = rw_remap ( orig );
sewardj2d8b3f02002-06-01 14:14:19 +00002689 rwl = rw_remap ( orig );
2690 res = __pthread_mutex_lock(&rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00002691 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002692 if (!rwl->initted) {
2693 res = __pthread_mutex_unlock(&rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00002694 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002695 return EINVAL;
2696 }
2697 if (rwl->status == 0) {
2698 res = __pthread_mutex_unlock(&rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00002699 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002700 return EPERM;
2701 }
sewardj2d94c112002-06-03 01:25:54 +00002702 my_assert(rwl->status != 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002703 if (rwl->status == -1) {
2704 rwl->status = 0;
2705 } else {
sewardj2d94c112002-06-03 01:25:54 +00002706 my_assert(rwl->status > 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002707 rwl->status--;
2708 }
2709
sewardj2d94c112002-06-03 01:25:54 +00002710 my_assert(rwl->status >= 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002711
2712 if (rwl->prefer_w) {
2713
2714 /* Favour waiting writers, if any. */
2715 if (rwl->nwait_w > 0) {
2716 /* Writer(s) are waiting. */
2717 if (rwl->status == 0) {
2718 /* We can let a writer in. */
2719 res = pthread_cond_signal(&rwl->cv_w);
sewardj2d94c112002-06-03 01:25:54 +00002720 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002721 } else {
2722 /* There are still readers active. Do nothing; eventually
2723 they will disappear, at which point a writer will be
2724 admitted. */
2725 }
2726 }
2727 else
2728 /* No waiting writers. */
2729 if (rwl->nwait_r > 0) {
2730 /* Let in a waiting reader. */
2731 res = pthread_cond_signal(&rwl->cv_r);
sewardj2d94c112002-06-03 01:25:54 +00002732 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002733 }
2734
2735 } else {
2736
2737 /* Favour waiting readers, if any. */
2738 if (rwl->nwait_r > 0) {
2739 /* Reader(s) are waiting; let one in. */
2740 res = pthread_cond_signal(&rwl->cv_r);
sewardj2d94c112002-06-03 01:25:54 +00002741 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002742 }
2743 else
2744 /* No waiting readers. */
2745 if (rwl->nwait_w > 0 && rwl->status == 0) {
2746 /* We have waiting writers and no active readers; let a
2747 writer in. */
2748 res = pthread_cond_signal(&rwl->cv_w);
sewardj2d94c112002-06-03 01:25:54 +00002749 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002750 }
2751 }
2752
2753 res = __pthread_mutex_unlock(&rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00002754 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002755 return 0;
2756}
2757
2758
2759int pthread_rwlock_destroy ( pthread_rwlock_t *orig )
2760{
2761 int res;
2762 vg_rwlock_t* rwl;
2763 if (0) printf ("pthread_rwlock_destroy\n");
2764 rwl = rw_remap ( orig );
2765 res = __pthread_mutex_lock(&rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00002766 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002767 if (!rwl->initted) {
2768 res = __pthread_mutex_unlock(&rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00002769 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002770 return EINVAL;
2771 }
2772 if (rwl->status != 0 || rwl->nwait_r > 0 || rwl->nwait_w > 0) {
2773 res = __pthread_mutex_unlock(&rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00002774 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002775 return EBUSY;
2776 }
2777 rwl->initted = 0;
2778 res = __pthread_mutex_unlock(&rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00002779 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002780 return 0;
sewardja1ac5cb2002-05-27 13:00:05 +00002781}
2782
2783
sewardj47e4e312002-06-18 09:24:34 +00002784/* Copied directly from LinuxThreads. */
2785int
2786pthread_rwlockattr_init (pthread_rwlockattr_t *attr)
2787{
2788 attr->__lockkind = 0;
2789 attr->__pshared = PTHREAD_PROCESS_PRIVATE;
2790
2791 return 0;
2792}
2793
sewardjfe18eb82002-07-13 12:58:44 +00002794/* Copied directly from LinuxThreads. */
2795int
2796pthread_rwlockattr_setpshared (pthread_rwlockattr_t *attr, int pshared)
2797{
2798 if (pshared != PTHREAD_PROCESS_PRIVATE && pshared != PTHREAD_PROCESS_SHARED)
2799 return EINVAL;
2800
2801 /* For now it is not possible to shared a conditional variable. */
2802 if (pshared != PTHREAD_PROCESS_PRIVATE)
2803 return ENOSYS;
2804
2805 attr->__pshared = pshared;
2806
2807 return 0;
2808}
2809
sewardj47e4e312002-06-18 09:24:34 +00002810
sewardja1ac5cb2002-05-27 13:00:05 +00002811/* ---------------------------------------------------------------------
sewardj3b13f0e2002-04-25 20:17:29 +00002812 B'stard.
2813 ------------------------------------------------------------------ */
2814
2815# define strong_alias(name, aliasname) \
2816 extern __typeof (name) aliasname __attribute__ ((alias (#name)));
2817
sewardj5905fae2002-04-26 13:25:00 +00002818# define weak_alias(name, aliasname) \
2819 extern __typeof (name) aliasname __attribute__ ((weak, alias (#name)));
sewardj3b13f0e2002-04-25 20:17:29 +00002820
sewardj5905fae2002-04-26 13:25:00 +00002821strong_alias(__pthread_mutex_lock, pthread_mutex_lock)
2822strong_alias(__pthread_mutex_trylock, pthread_mutex_trylock)
2823strong_alias(__pthread_mutex_unlock, pthread_mutex_unlock)
2824strong_alias(__pthread_mutexattr_init, pthread_mutexattr_init)
2825 weak_alias(__pthread_mutexattr_settype, pthread_mutexattr_settype)
2826strong_alias(__pthread_mutex_init, pthread_mutex_init)
2827strong_alias(__pthread_mutexattr_destroy, pthread_mutexattr_destroy)
2828strong_alias(__pthread_mutex_destroy, pthread_mutex_destroy)
2829strong_alias(__pthread_once, pthread_once)
2830strong_alias(__pthread_atfork, pthread_atfork)
2831strong_alias(__pthread_key_create, pthread_key_create)
2832strong_alias(__pthread_getspecific, pthread_getspecific)
2833strong_alias(__pthread_setspecific, pthread_setspecific)
2834
sewardjd529a442002-05-04 19:49:21 +00002835#ifndef GLIBC_2_1
sewardj3b13f0e2002-04-25 20:17:29 +00002836strong_alias(sigaction, __sigaction)
sewardjd529a442002-05-04 19:49:21 +00002837#endif
2838
sewardj5905fae2002-04-26 13:25:00 +00002839strong_alias(close, __close)
sewardj3b13f0e2002-04-25 20:17:29 +00002840strong_alias(fcntl, __fcntl)
sewardj5905fae2002-04-26 13:25:00 +00002841strong_alias(lseek, __lseek)
2842strong_alias(open, __open)
2843strong_alias(open64, __open64)
sewardj5905fae2002-04-26 13:25:00 +00002844strong_alias(read, __read)
2845strong_alias(wait, __wait)
2846strong_alias(write, __write)
sewardj3b13f0e2002-04-25 20:17:29 +00002847strong_alias(connect, __connect)
sewardj5905fae2002-04-26 13:25:00 +00002848strong_alias(send, __send)
2849
sewardj726c4122002-05-16 23:39:10 +00002850weak_alias (__pread64, pread64)
sewardja18e2102002-05-18 10:43:22 +00002851weak_alias (__pwrite64, pwrite64)
sewardj5905fae2002-04-26 13:25:00 +00002852weak_alias(__fork, fork)
njn25e49d8e72002-09-23 09:36:25 +00002853weak_alias(__vfork, vfork)
sewardj7f6456d2002-05-21 00:51:21 +00002854
sewardjf0b06452002-06-04 08:38:04 +00002855weak_alias (__pthread_kill_other_threads_np, pthread_kill_other_threads_np)
sewardj3b13f0e2002-04-25 20:17:29 +00002856
2857/*--------------------------------------------------*/
2858
sewardj5905fae2002-04-26 13:25:00 +00002859weak_alias(pthread_rwlock_rdlock, __pthread_rwlock_rdlock)
sewardj5905fae2002-04-26 13:25:00 +00002860weak_alias(pthread_rwlock_unlock, __pthread_rwlock_unlock)
sewardj262b0292002-05-01 00:03:16 +00002861weak_alias(pthread_rwlock_wrlock, __pthread_rwlock_wrlock)
sewardj060b04f2002-04-26 21:01:13 +00002862
sewardja1ac5cb2002-05-27 13:00:05 +00002863weak_alias(pthread_rwlock_destroy, __pthread_rwlock_destroy)
2864weak_alias(pthread_rwlock_init, __pthread_rwlock_init)
2865weak_alias(pthread_rwlock_tryrdlock, __pthread_rwlock_tryrdlock)
2866weak_alias(pthread_rwlock_trywrlock, __pthread_rwlock_trywrlock)
2867
sewardj060b04f2002-04-26 21:01:13 +00002868
sewardj3b13f0e2002-04-25 20:17:29 +00002869/* I've no idea what these are, but they get called quite a lot.
2870 Anybody know? */
2871
2872#undef _IO_flockfile
2873void _IO_flockfile ( _IO_FILE * file )
2874{
sewardj853f55d2002-04-26 00:27:53 +00002875 pthread_mutex_lock(file->_lock);
sewardj3b13f0e2002-04-25 20:17:29 +00002876}
sewardj5905fae2002-04-26 13:25:00 +00002877weak_alias(_IO_flockfile, flockfile);
2878
sewardj3b13f0e2002-04-25 20:17:29 +00002879
2880#undef _IO_funlockfile
2881void _IO_funlockfile ( _IO_FILE * file )
2882{
sewardj853f55d2002-04-26 00:27:53 +00002883 pthread_mutex_unlock(file->_lock);
sewardj3b13f0e2002-04-25 20:17:29 +00002884}
sewardj5905fae2002-04-26 13:25:00 +00002885weak_alias(_IO_funlockfile, funlockfile);
2886
sewardj3b13f0e2002-04-25 20:17:29 +00002887
sewardjd4f2c712002-04-30 10:20:10 +00002888/* This doesn't seem to be needed to simulate libpthread.so's external
2889 interface, but many people complain about its absence. */
2890
2891strong_alias(__pthread_mutexattr_settype, __pthread_mutexattr_setkind_np)
2892weak_alias(__pthread_mutexattr_setkind_np, pthread_mutexattr_setkind_np)
sewardj439d45e2002-05-03 20:43:10 +00002893
2894
2895/*--------------------------------------------------------------------*/
2896/*--- end vg_libpthread.c ---*/
2897/*--------------------------------------------------------------------*/