blob: d869d533fcae1f2b2805f5db5397476977953e3c [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/*
8 This file is part of Valgrind, an x86 protected-mode emulator
9 designed for debugging and profiling binaries on x86-Unixes.
10
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
29 The GNU General Public License is contained in the file LICENSE.
30*/
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
sewardje663cb92002-04-12 10:26:32 +000058#include <unistd.h>
59#include <string.h>
sewardj2a1dcce2002-04-22 12:45:25 +000060#ifdef GLIBC_2_1
61#include <sys/time.h>
62#endif
sewardje663cb92002-04-12 10:26:32 +000063
64/* ---------------------------------------------------------------------
65 Helpers. We have to be pretty self-sufficient.
66 ------------------------------------------------------------------ */
67
sewardj436e0582002-04-26 14:31:40 +000068/* Number of times any given error message is printed. */
69#define N_MOANS 3
70
sewardj45b4b372002-04-16 22:50:32 +000071/* Extract from Valgrind the value of VG_(clo_trace_pthread_level).
72 Returns 0 (none) if not running on Valgrind. */
73static
74int get_pt_trace_level ( void )
75{
76 int res;
77 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
78 VG_USERREQ__GET_PTHREAD_TRACE_LEVEL,
79 0, 0, 0, 0);
80 return res;
81}
82
83
sewardje663cb92002-04-12 10:26:32 +000084static
85void myexit ( int arg )
86{
sewardj45b4b372002-04-16 22:50:32 +000087 int __res;
sewardje663cb92002-04-12 10:26:32 +000088 __asm__ volatile ("movl %%ecx, %%ebx ; int $0x80"
89 : "=a" (__res)
90 : "0" (__NR_exit),
91 "c" (arg) );
sewardj45b4b372002-04-16 22:50:32 +000092 /* We don't bother to mention the fact that this asm trashes %ebx,
93 since it won't return. If you ever do let it return ... fix
94 this! */
sewardje663cb92002-04-12 10:26:32 +000095}
96
97
98/* Give up without using printf etc, since they seem to give
99 segfaults. */
sewardj604ec3c2002-04-18 22:38:41 +0000100static __inline__
sewardje663cb92002-04-12 10:26:32 +0000101void ensure_valgrind ( char* caller )
102{
103 char* str;
104 int is_valgrind = RUNNING_ON_VALGRIND;
105 if (!is_valgrind) {
sewardj439d45e2002-05-03 20:43:10 +0000106 str = "\nvalgrind's libpthread.so: "
sewardje663cb92002-04-12 10:26:32 +0000107 "pthread call when\n";
108 write(2, str, strlen(str));
109 str = "not running on valgrind; aborting! "
110 "This is probably a bug in\n";
111 write(2, str, strlen(str));
112 str = "valgrind. Please report it to me at: "
113 "jseward@acm.org. Thanks.\n";
114 write(2, str, strlen(str));
115 str = "unexpectedly called function is: ";
116 write(2, str, strlen(str));
117 write(2, caller, strlen(caller));
118 str = "\n\n";
119 write(2, str, strlen(str));
120 myexit(1);
121 }
122}
123
124
125static
sewardj3b5d8862002-04-20 13:53:23 +0000126__attribute__((noreturn))
sewardje663cb92002-04-12 10:26:32 +0000127void barf ( char* str )
128{
129 char buf[100];
130 buf[0] = 0;
sewardj439d45e2002-05-03 20:43:10 +0000131 strcat(buf, "\nvalgrind's libpthread.so: ");
sewardje663cb92002-04-12 10:26:32 +0000132 strcat(buf, str);
133 strcat(buf, "\n\n");
134 write(2, buf, strlen(buf));
135 myexit(1);
sewardj3b5d8862002-04-20 13:53:23 +0000136 /* We have to persuade gcc into believing this doesn't return. */
137 while (1) { };
sewardje663cb92002-04-12 10:26:32 +0000138}
139
140
sewardj2a3d28c2002-04-14 13:27:00 +0000141static void ignored ( char* msg )
142{
sewardj436e0582002-04-26 14:31:40 +0000143 if (get_pt_trace_level() >= 0) {
sewardj439d45e2002-05-03 20:43:10 +0000144 char* ig = "valgrind's libpthread.so: IGNORED call to: ";
sewardj45b4b372002-04-16 22:50:32 +0000145 write(2, ig, strlen(ig));
146 write(2, msg, strlen(msg));
147 ig = "\n";
148 write(2, ig, strlen(ig));
149 }
sewardj2a3d28c2002-04-14 13:27:00 +0000150}
151
sewardj30671ff2002-04-21 00:13:57 +0000152static void kludged ( char* msg )
153{
sewardj436e0582002-04-26 14:31:40 +0000154 if (get_pt_trace_level() >= 0) {
sewardj439d45e2002-05-03 20:43:10 +0000155 char* ig = "valgrind's libpthread.so: KLUDGED call to: ";
156 write(2, ig, strlen(ig));
157 write(2, msg, strlen(msg));
158 ig = "\n";
159 write(2, ig, strlen(ig));
160 }
161}
162
163static void not_inside ( char* msg )
164{
165 if (get_pt_trace_level() >= 0) {
166 char* ig = "valgrind's libpthread.so: NOT INSIDE VALGRIND "
167 "during call to: ";
sewardj30671ff2002-04-21 00:13:57 +0000168 write(2, ig, strlen(ig));
169 write(2, msg, strlen(msg));
170 ig = "\n";
171 write(2, ig, strlen(ig));
172 }
173}
174
sewardj3b13f0e2002-04-25 20:17:29 +0000175void vgPlain_unimp ( char* what )
176{
sewardj439d45e2002-05-03 20:43:10 +0000177 char* ig = "valgrind's libpthread.so: UNIMPLEMENTED FUNCTION: ";
sewardj3b13f0e2002-04-25 20:17:29 +0000178 write(2, ig, strlen(ig));
179 write(2, what, strlen(what));
180 ig = "\n";
181 write(2, ig, strlen(ig));
182 barf("Please report this bug to me at: jseward@acm.org");
183}
184
sewardje663cb92002-04-12 10:26:32 +0000185
186/* ---------------------------------------------------------------------
187 Pass pthread_ calls to Valgrind's request mechanism.
188 ------------------------------------------------------------------ */
189
sewardjf8f819e2002-04-17 23:21:37 +0000190#include <pthread.h>
191#include <stdio.h>
192#include <errno.h>
sewardj5f07b662002-04-23 16:52:51 +0000193#include <assert.h>
194#include <sys/time.h> /* gettimeofday */
sewardjf8f819e2002-04-17 23:21:37 +0000195
196/* ---------------------------------------------------
197 THREAD ATTRIBUTES
198 ------------------------------------------------ */
199
sewardj6af4b5d2002-04-16 04:40:49 +0000200int pthread_attr_init(pthread_attr_t *attr)
201{
sewardj436e0582002-04-26 14:31:40 +0000202 static int moans = N_MOANS;
203 if (moans-- > 0)
204 ignored("pthread_attr_init");
sewardj6af4b5d2002-04-16 04:40:49 +0000205 return 0;
206}
207
208int pthread_attr_setdetachstate(pthread_attr_t *attr, int detachstate)
209{
sewardj436e0582002-04-26 14:31:40 +0000210 static int moans = N_MOANS;
211 if (moans-- > 0)
212 ignored("pthread_attr_setdetachstate");
sewardj6af4b5d2002-04-16 04:40:49 +0000213 return 0;
214}
215
sewardj30671ff2002-04-21 00:13:57 +0000216int pthread_attr_setinheritsched(pthread_attr_t *attr, int inherit)
217{
sewardj436e0582002-04-26 14:31:40 +0000218 static int moans = N_MOANS;
219 if (moans-- > 0)
220 ignored("pthread_attr_setinheritsched");
sewardj30671ff2002-04-21 00:13:57 +0000221 return 0;
222}
sewardj6af4b5d2002-04-16 04:40:49 +0000223
sewardj30671ff2002-04-21 00:13:57 +0000224/* This is completely bogus. */
225int pthread_attr_getschedparam(const pthread_attr_t *attr,
226 struct sched_param *param)
227{
sewardj436e0582002-04-26 14:31:40 +0000228 static int moans = N_MOANS;
229 if (moans-- > 0)
230 kludged("pthread_attr_getschedparam");
sewardj72d58482002-04-24 02:20:20 +0000231# ifdef GLIBC_2_1
232 if (param) param->sched_priority = 0; /* who knows */
233# else
sewardj30671ff2002-04-21 00:13:57 +0000234 if (param) param->__sched_priority = 0; /* who knows */
sewardj72d58482002-04-24 02:20:20 +0000235# endif
sewardj30671ff2002-04-21 00:13:57 +0000236 return 0;
237}
238
239int pthread_attr_setschedparam(pthread_attr_t *attr,
240 const struct sched_param *param)
241{
sewardj436e0582002-04-26 14:31:40 +0000242 static int moans = N_MOANS;
243 if (moans-- > 0)
244 ignored("pthread_attr_setschedparam");
sewardj30671ff2002-04-21 00:13:57 +0000245 return 0;
246}
247
248int pthread_attr_destroy(pthread_attr_t *attr)
249{
sewardj436e0582002-04-26 14:31:40 +0000250 static int moans = N_MOANS;
251 if (moans-- > 0)
252 ignored("pthread_attr_destroy");
sewardj30671ff2002-04-21 00:13:57 +0000253 return 0;
254}
sewardjf8f819e2002-04-17 23:21:37 +0000255
256/* ---------------------------------------------------
257 THREADs
258 ------------------------------------------------ */
259
sewardj6072c362002-04-19 14:40:57 +0000260int pthread_equal(pthread_t thread1, pthread_t thread2)
261{
262 return thread1 == thread2 ? 1 : 0;
263}
264
265
sewardje663cb92002-04-12 10:26:32 +0000266int
267pthread_create (pthread_t *__restrict __thread,
268 __const pthread_attr_t *__restrict __attr,
269 void *(*__start_routine) (void *),
270 void *__restrict __arg)
271{
272 int res;
273 ensure_valgrind("pthread_create");
274 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
275 VG_USERREQ__PTHREAD_CREATE,
276 __thread, __attr, __start_routine, __arg);
277 return res;
278}
279
280
281
282int
283pthread_join (pthread_t __th, void **__thread_return)
284{
285 int res;
286 ensure_valgrind("pthread_join");
287 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
288 VG_USERREQ__PTHREAD_JOIN,
289 __th, __thread_return, 0, 0);
290 return res;
291}
292
293
sewardj3b5d8862002-04-20 13:53:23 +0000294void pthread_exit(void *retval)
295{
296 int res;
297 ensure_valgrind("pthread_exit");
298 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
299 VG_USERREQ__PTHREAD_EXIT,
300 retval, 0, 0, 0);
301 /* Doesn't return! */
302 /* However, we have to fool gcc into knowing that. */
303 barf("pthread_exit: still alive after request?!");
304}
305
sewardje663cb92002-04-12 10:26:32 +0000306
sewardj3b13f0e2002-04-25 20:17:29 +0000307pthread_t pthread_self(void)
sewardje663cb92002-04-12 10:26:32 +0000308{
309 int tid;
sewardj3b13f0e2002-04-25 20:17:29 +0000310 ensure_valgrind("pthread_self");
sewardj439d45e2002-05-03 20:43:10 +0000311 VALGRIND_MAGIC_SEQUENCE(tid, 1 /* default */,
sewardje663cb92002-04-12 10:26:32 +0000312 VG_USERREQ__PTHREAD_GET_THREADID,
313 0, 0, 0, 0);
sewardj439d45e2002-05-03 20:43:10 +0000314 if (tid < 1 || tid >= VG_N_THREADS)
sewardj3b13f0e2002-04-25 20:17:29 +0000315 barf("pthread_self: invalid ThreadId");
316 return tid;
sewardje663cb92002-04-12 10:26:32 +0000317}
318
319
sewardj853f55d2002-04-26 00:27:53 +0000320int pthread_detach(pthread_t th)
321{
sewardj436e0582002-04-26 14:31:40 +0000322 static int moans = N_MOANS;
323 if (moans-- > 0)
324 ignored("pthread_detach");
sewardj853f55d2002-04-26 00:27:53 +0000325 return 0;
326}
327
328
sewardjf8f819e2002-04-17 23:21:37 +0000329/* ---------------------------------------------------
330 MUTEX ATTRIBUTES
331 ------------------------------------------------ */
332
sewardj5905fae2002-04-26 13:25:00 +0000333int __pthread_mutexattr_init(pthread_mutexattr_t *attr)
sewardje663cb92002-04-12 10:26:32 +0000334{
sewardjf8f819e2002-04-17 23:21:37 +0000335 attr->__mutexkind = PTHREAD_MUTEX_ERRORCHECK_NP;
sewardj8937c812002-04-12 20:12:20 +0000336 return 0;
sewardje663cb92002-04-12 10:26:32 +0000337}
338
sewardj5905fae2002-04-26 13:25:00 +0000339int __pthread_mutexattr_settype(pthread_mutexattr_t *attr, int type)
sewardjf8f819e2002-04-17 23:21:37 +0000340{
341 switch (type) {
sewardj3b13f0e2002-04-25 20:17:29 +0000342# ifndef GLIBC_2_1
sewardjf8f819e2002-04-17 23:21:37 +0000343 case PTHREAD_MUTEX_TIMED_NP:
sewardj2a1dcce2002-04-22 12:45:25 +0000344 case PTHREAD_MUTEX_ADAPTIVE_NP:
sewardj3b13f0e2002-04-25 20:17:29 +0000345# endif
sewardjf8f819e2002-04-17 23:21:37 +0000346 case PTHREAD_MUTEX_RECURSIVE_NP:
347 case PTHREAD_MUTEX_ERRORCHECK_NP:
sewardjf8f819e2002-04-17 23:21:37 +0000348 attr->__mutexkind = type;
349 return 0;
350 default:
351 return EINVAL;
352 }
353}
354
sewardj5905fae2002-04-26 13:25:00 +0000355int __pthread_mutexattr_destroy(pthread_mutexattr_t *attr)
sewardjf8f819e2002-04-17 23:21:37 +0000356{
357 return 0;
358}
359
360
361/* ---------------------------------------------------
362 MUTEXes
363 ------------------------------------------------ */
364
sewardj5905fae2002-04-26 13:25:00 +0000365int __pthread_mutex_init(pthread_mutex_t *mutex,
366 const pthread_mutexattr_t *mutexattr)
sewardje663cb92002-04-12 10:26:32 +0000367{
sewardj604ec3c2002-04-18 22:38:41 +0000368 mutex->__m_count = 0;
369 mutex->__m_owner = (_pthread_descr)VG_INVALID_THREADID;
370 mutex->__m_kind = PTHREAD_MUTEX_ERRORCHECK_NP;
371 if (mutexattr)
372 mutex->__m_kind = mutexattr->__mutexkind;
373 return 0;
sewardje663cb92002-04-12 10:26:32 +0000374}
375
sewardj439d45e2002-05-03 20:43:10 +0000376
sewardj5905fae2002-04-26 13:25:00 +0000377int __pthread_mutex_lock(pthread_mutex_t *mutex)
sewardje663cb92002-04-12 10:26:32 +0000378{
379 int res;
sewardj436e0582002-04-26 14:31:40 +0000380 static int moans = N_MOANS;
sewardj439d45e2002-05-03 20:43:10 +0000381 if (RUNNING_ON_VALGRIND) {
sewardje663cb92002-04-12 10:26:32 +0000382 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
383 VG_USERREQ__PTHREAD_MUTEX_LOCK,
384 mutex, 0, 0, 0);
385 return res;
sewardj439d45e2002-05-03 20:43:10 +0000386 } else {
387 if (moans-- > 0)
388 not_inside("pthread_mutex_lock");
389 return 0; /* success */
sewardje663cb92002-04-12 10:26:32 +0000390 }
391}
392
sewardj439d45e2002-05-03 20:43:10 +0000393
sewardj5905fae2002-04-26 13:25:00 +0000394int __pthread_mutex_trylock(pthread_mutex_t *mutex)
sewardj30671ff2002-04-21 00:13:57 +0000395{
396 int res;
sewardj436e0582002-04-26 14:31:40 +0000397 static int moans = N_MOANS;
sewardj439d45e2002-05-03 20:43:10 +0000398 if (RUNNING_ON_VALGRIND) {
sewardj30671ff2002-04-21 00:13:57 +0000399 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
400 VG_USERREQ__PTHREAD_MUTEX_TRYLOCK,
401 mutex, 0, 0, 0);
402 return res;
sewardj439d45e2002-05-03 20:43:10 +0000403 } else {
404 if (moans-- > 0)
405 not_inside("pthread_mutex_trylock");
406 return 0;
sewardj30671ff2002-04-21 00:13:57 +0000407 }
408}
409
sewardj439d45e2002-05-03 20:43:10 +0000410
sewardj5905fae2002-04-26 13:25:00 +0000411int __pthread_mutex_unlock(pthread_mutex_t *mutex)
sewardje663cb92002-04-12 10:26:32 +0000412{
413 int res;
sewardj436e0582002-04-26 14:31:40 +0000414 static int moans = N_MOANS;
sewardj439d45e2002-05-03 20:43:10 +0000415 if (RUNNING_ON_VALGRIND) {
sewardje663cb92002-04-12 10:26:32 +0000416 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
417 VG_USERREQ__PTHREAD_MUTEX_UNLOCK,
418 mutex, 0, 0, 0);
419 return res;
sewardj439d45e2002-05-03 20:43:10 +0000420 } else {
421 if (moans-- > 0)
422 not_inside("pthread_mutex_unlock");
423 return 0;
sewardje663cb92002-04-12 10:26:32 +0000424 }
425}
426
sewardj439d45e2002-05-03 20:43:10 +0000427
sewardj5905fae2002-04-26 13:25:00 +0000428int __pthread_mutex_destroy(pthread_mutex_t *mutex)
sewardje663cb92002-04-12 10:26:32 +0000429{
sewardj604ec3c2002-04-18 22:38:41 +0000430 /* Valgrind doesn't hold any resources on behalf of the mutex, so no
431 need to involve it. */
432 if (mutex->__m_count > 0)
433 return EBUSY;
sewardj6072c362002-04-19 14:40:57 +0000434 mutex->__m_count = 0;
435 mutex->__m_owner = (_pthread_descr)VG_INVALID_THREADID;
436 mutex->__m_kind = PTHREAD_MUTEX_ERRORCHECK_NP;
sewardj604ec3c2002-04-18 22:38:41 +0000437 return 0;
sewardje663cb92002-04-12 10:26:32 +0000438}
439
440
sewardjf8f819e2002-04-17 23:21:37 +0000441/* ---------------------------------------------------
sewardj6072c362002-04-19 14:40:57 +0000442 CONDITION VARIABLES
443 ------------------------------------------------ */
444
445/* LinuxThreads supports no attributes for conditions. Hence ... */
446
447int pthread_condattr_init(pthread_condattr_t *attr)
448{
449 return 0;
450}
451
sewardj0738a592002-04-20 13:59:33 +0000452int pthread_condattr_destroy(pthread_condattr_t *attr)
453{
454 return 0;
455}
sewardj6072c362002-04-19 14:40:57 +0000456
457int pthread_cond_init( pthread_cond_t *cond,
458 const pthread_condattr_t *cond_attr)
459{
460 cond->__c_waiting = (_pthread_descr)VG_INVALID_THREADID;
461 return 0;
462}
463
sewardjf854f472002-04-21 12:19:41 +0000464int pthread_cond_destroy(pthread_cond_t *cond)
465{
466 /* should check that no threads are waiting on this CV */
sewardj436e0582002-04-26 14:31:40 +0000467 static int moans = N_MOANS;
468 if (moans-- > 0)
469 kludged("pthread_cond_destroy");
sewardjf854f472002-04-21 12:19:41 +0000470 return 0;
471}
sewardj6072c362002-04-19 14:40:57 +0000472
473/* ---------------------------------------------------
474 SCHEDULING
475 ------------------------------------------------ */
476
477/* This is completely bogus. */
478int pthread_getschedparam(pthread_t target_thread,
479 int *policy,
480 struct sched_param *param)
481{
sewardj436e0582002-04-26 14:31:40 +0000482 static int moans = N_MOANS;
483 if (moans-- > 0)
484 kludged("pthread_getschedparam");
sewardj6072c362002-04-19 14:40:57 +0000485 if (policy) *policy = SCHED_OTHER;
sewardj2a1dcce2002-04-22 12:45:25 +0000486# ifdef GLIBC_2_1
487 if (param) param->sched_priority = 0; /* who knows */
488# else
sewardj6072c362002-04-19 14:40:57 +0000489 if (param) param->__sched_priority = 0; /* who knows */
sewardj2a1dcce2002-04-22 12:45:25 +0000490# endif
sewardj6072c362002-04-19 14:40:57 +0000491 return 0;
492}
493
494int pthread_setschedparam(pthread_t target_thread,
495 int policy,
496 const struct sched_param *param)
497{
sewardj436e0582002-04-26 14:31:40 +0000498 static int moans = N_MOANS;
499 if (moans-- > 0)
500 ignored("pthread_setschedparam");
sewardj6072c362002-04-19 14:40:57 +0000501 return 0;
502}
503
sewardj3b5d8862002-04-20 13:53:23 +0000504int pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex)
505{
506 int res;
507 ensure_valgrind("pthread_cond_wait");
508 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
509 VG_USERREQ__PTHREAD_COND_WAIT,
510 cond, mutex, 0, 0);
511 return res;
512}
513
sewardj5f07b662002-04-23 16:52:51 +0000514int pthread_cond_timedwait ( pthread_cond_t *cond,
515 pthread_mutex_t *mutex,
516 const struct timespec *abstime )
517{
518 int res;
519 unsigned int ms_now, ms_end;
520 struct timeval timeval_now;
521 unsigned long long int ull_ms_now_after_1970;
522 unsigned long long int ull_ms_end_after_1970;
523
524 ensure_valgrind("pthread_cond_timedwait");
525 VALGRIND_MAGIC_SEQUENCE(ms_now, 0xFFFFFFFF /* default */,
526 VG_USERREQ__READ_MILLISECOND_TIMER,
527 0, 0, 0, 0);
528 assert(ms_now != 0xFFFFFFFF);
529 res = gettimeofday(&timeval_now, NULL);
530 assert(res == 0);
531
532 ull_ms_now_after_1970
533 = 1000ULL * ((unsigned long long int)(timeval_now.tv_sec))
534 + ((unsigned long long int)(timeval_now.tv_usec / 1000000));
535 ull_ms_end_after_1970
536 = 1000ULL * ((unsigned long long int)(abstime->tv_sec))
537 + ((unsigned long long int)(abstime->tv_nsec / 1000000));
538 assert(ull_ms_end_after_1970 >= ull_ms_now_after_1970);
539 ms_end
540 = ms_now + (unsigned int)(ull_ms_end_after_1970 - ull_ms_now_after_1970);
541 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
542 VG_USERREQ__PTHREAD_COND_TIMEDWAIT,
543 cond, mutex, ms_end, 0);
544 return res;
545}
546
547
sewardj3b5d8862002-04-20 13:53:23 +0000548int pthread_cond_signal(pthread_cond_t *cond)
549{
550 int res;
551 ensure_valgrind("pthread_cond_signal");
552 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
553 VG_USERREQ__PTHREAD_COND_SIGNAL,
554 cond, 0, 0, 0);
555 return res;
556}
557
558int pthread_cond_broadcast(pthread_cond_t *cond)
559{
560 int res;
561 ensure_valgrind("pthread_cond_broadcast");
562 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
563 VG_USERREQ__PTHREAD_COND_BROADCAST,
564 cond, 0, 0, 0);
565 return res;
566}
567
sewardj6072c362002-04-19 14:40:57 +0000568
569/* ---------------------------------------------------
sewardjf8f819e2002-04-17 23:21:37 +0000570 CANCELLATION
571 ------------------------------------------------ */
572
sewardj853f55d2002-04-26 00:27:53 +0000573int pthread_setcancelstate(int state, int *oldstate)
574{
sewardj436e0582002-04-26 14:31:40 +0000575 static int moans = N_MOANS;
576 if (moans-- > 0)
577 ignored("pthread_setcancelstate");
sewardj853f55d2002-04-26 00:27:53 +0000578 return 0;
579}
580
sewardje663cb92002-04-12 10:26:32 +0000581int pthread_setcanceltype(int type, int *oldtype)
582{
sewardj436e0582002-04-26 14:31:40 +0000583 static int moans = N_MOANS;
584 if (moans-- > 0)
585 ignored("pthread_setcanceltype");
sewardje663cb92002-04-12 10:26:32 +0000586 return 0;
587}
588
sewardje663cb92002-04-12 10:26:32 +0000589int pthread_cancel(pthread_t thread)
590{
591 int res;
592 ensure_valgrind("pthread_cancel");
593 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
594 VG_USERREQ__PTHREAD_CANCEL,
595 thread, 0, 0, 0);
596 return res;
597}
598
sewardj853f55d2002-04-26 00:27:53 +0000599void pthread_testcancel(void)
600{
601}
602
603/*-------------------*/
604static pthread_mutex_t massacre_mx = PTHREAD_MUTEX_INITIALIZER;
605
606void __pthread_kill_other_threads_np ( void )
607{
608 int i, res, me;
609 pthread_mutex_lock(&massacre_mx);
610 me = pthread_self();
611 for (i = 1; i < VG_N_THREADS; i++) {
612 if (i == me) continue;
613 res = pthread_cancel(i);
sewardj436e0582002-04-26 14:31:40 +0000614 if (0 && res == 0)
sewardj853f55d2002-04-26 00:27:53 +0000615 printf("----------- NUKED %d\n", i);
616 }
617 pthread_mutex_unlock(&massacre_mx);
618}
619
sewardje663cb92002-04-12 10:26:32 +0000620
sewardjf8f819e2002-04-17 23:21:37 +0000621/* ---------------------------------------------------
622 THREAD-SPECIFICs
623 ------------------------------------------------ */
sewardj5e5fa512002-04-14 13:13:05 +0000624
sewardj5905fae2002-04-26 13:25:00 +0000625int __pthread_key_create(pthread_key_t *key,
626 void (*destr_function) (void *))
sewardj5e5fa512002-04-14 13:13:05 +0000627{
sewardj5f07b662002-04-23 16:52:51 +0000628 int res;
629 ensure_valgrind("pthread_key_create");
630 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
631 VG_USERREQ__PTHREAD_KEY_CREATE,
632 key, destr_function, 0, 0);
633 return res;
sewardj5e5fa512002-04-14 13:13:05 +0000634}
635
636int pthread_key_delete(pthread_key_t key)
637{
sewardj436e0582002-04-26 14:31:40 +0000638 static int moans = N_MOANS;
639 if (moans-- > 0)
640 ignored("pthread_key_delete");
sewardj5e5fa512002-04-14 13:13:05 +0000641 return 0;
642}
643
sewardj5905fae2002-04-26 13:25:00 +0000644int __pthread_setspecific(pthread_key_t key, const void *pointer)
sewardj5e5fa512002-04-14 13:13:05 +0000645{
sewardj5f07b662002-04-23 16:52:51 +0000646 int res;
647 ensure_valgrind("pthread_setspecific");
648 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
649 VG_USERREQ__PTHREAD_SETSPECIFIC,
650 key, pointer, 0, 0);
651 return res;
sewardj5e5fa512002-04-14 13:13:05 +0000652}
653
sewardj5905fae2002-04-26 13:25:00 +0000654void * __pthread_getspecific(pthread_key_t key)
sewardj5e5fa512002-04-14 13:13:05 +0000655{
sewardj5f07b662002-04-23 16:52:51 +0000656 int res;
657 ensure_valgrind("pthread_getspecific");
658 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
659 VG_USERREQ__PTHREAD_GETSPECIFIC,
660 key, 0 , 0, 0);
661 return (void*)res;
sewardj5e5fa512002-04-14 13:13:05 +0000662}
663
sewardjf8f819e2002-04-17 23:21:37 +0000664
665/* ---------------------------------------------------
sewardj89d3d852002-04-24 19:21:39 +0000666 ONCEry
667 ------------------------------------------------ */
668
669static pthread_mutex_t once_masterlock = PTHREAD_MUTEX_INITIALIZER;
670
671
sewardj5905fae2002-04-26 13:25:00 +0000672int __pthread_once ( pthread_once_t *once_control,
673 void (*init_routine) (void) )
sewardj89d3d852002-04-24 19:21:39 +0000674{
675 int res;
676 ensure_valgrind("pthread_once");
677
678 res = pthread_mutex_lock(&once_masterlock);
679
680 if (res != 0)
681 barf("pthread_once: Looks like your program's "
682 "init routine calls back to pthread_once() ?!");
683
684 if (*once_control == 0) {
685 *once_control = 1;
686 init_routine();
687 }
688
689 pthread_mutex_unlock(&once_masterlock);
690
691 return 0;
692}
693
694
695/* ---------------------------------------------------
sewardj853f55d2002-04-26 00:27:53 +0000696 MISC
697 ------------------------------------------------ */
698
sewardj5905fae2002-04-26 13:25:00 +0000699int __pthread_atfork ( void (*prepare)(void),
700 void (*parent)(void),
701 void (*child)(void) )
sewardj853f55d2002-04-26 00:27:53 +0000702{
sewardj436e0582002-04-26 14:31:40 +0000703 static int moans = N_MOANS;
704 if (moans-- > 0)
705 ignored("pthread_atfork");
sewardj853f55d2002-04-26 00:27:53 +0000706 return 0;
707}
708
709
sewardjbb990782002-05-08 02:01:14 +0000710__attribute__((weak))
711void __pthread_initialize ( void )
712{
713 static int moans = N_MOANS;
714 if (moans-- > 0)
715 ignored("__pthread_initialize");
716}
717
718
sewardj853f55d2002-04-26 00:27:53 +0000719/* ---------------------------------------------------
sewardj3b13f0e2002-04-25 20:17:29 +0000720 LIBRARY-PRIVATE THREAD SPECIFIC STATE
sewardjf8f819e2002-04-17 23:21:37 +0000721 ------------------------------------------------ */
722
sewardj3b13f0e2002-04-25 20:17:29 +0000723#include <resolv.h>
724static int thread_specific_errno[VG_N_THREADS];
725static int thread_specific_h_errno[VG_N_THREADS];
726static struct __res_state
727 thread_specific_res_state[VG_N_THREADS];
sewardjf8f819e2002-04-17 23:21:37 +0000728
sewardj3b13f0e2002-04-25 20:17:29 +0000729int* __errno_location ( void )
sewardjf8f819e2002-04-17 23:21:37 +0000730{
731 int tid;
sewardj3b13f0e2002-04-25 20:17:29 +0000732 /* ensure_valgrind("__errno_location"); */
733 VALGRIND_MAGIC_SEQUENCE(tid, 1 /* default */,
sewardjf8f819e2002-04-17 23:21:37 +0000734 VG_USERREQ__PTHREAD_GET_THREADID,
735 0, 0, 0, 0);
sewardj3b13f0e2002-04-25 20:17:29 +0000736 /* 'cos I'm paranoid ... */
sewardj439d45e2002-05-03 20:43:10 +0000737 if (tid < 1 || tid >= VG_N_THREADS)
sewardj3b13f0e2002-04-25 20:17:29 +0000738 barf("__errno_location: invalid ThreadId");
739 return & thread_specific_errno[tid];
740}
741
742int* __h_errno_location ( void )
743{
744 int tid;
745 /* ensure_valgrind("__h_errno_location"); */
746 VALGRIND_MAGIC_SEQUENCE(tid, 1 /* default */,
747 VG_USERREQ__PTHREAD_GET_THREADID,
748 0, 0, 0, 0);
749 /* 'cos I'm paranoid ... */
sewardj439d45e2002-05-03 20:43:10 +0000750 if (tid < 1 || tid >= VG_N_THREADS)
sewardj3b13f0e2002-04-25 20:17:29 +0000751 barf("__h_errno_location: invalid ThreadId");
752 return & thread_specific_h_errno[tid];
753}
754
755struct __res_state* __res_state ( void )
756{
757 int tid;
758 /* ensure_valgrind("__res_state"); */
759 VALGRIND_MAGIC_SEQUENCE(tid, 1 /* default */,
760 VG_USERREQ__PTHREAD_GET_THREADID,
761 0, 0, 0, 0);
762 /* 'cos I'm paranoid ... */
sewardj439d45e2002-05-03 20:43:10 +0000763 if (tid < 1 || tid >= VG_N_THREADS)
sewardj3b13f0e2002-04-25 20:17:29 +0000764 barf("__res_state: invalid ThreadId");
765 return & thread_specific_res_state[tid];
sewardjf8f819e2002-04-17 23:21:37 +0000766}
767
768
sewardj5716dbb2002-04-26 03:28:18 +0000769/* ---------------------------------------------------
770 LIBC-PRIVATE SPECIFIC DATA
771 ------------------------------------------------ */
772
773/* Relies on assumption that initial private data is NULL. This
774 should be fixed somehow. */
775
776/* The allowable keys (indices) (all 2 of them).
777 From sysdeps/pthread/bits/libc-tsd.h
778*/
sewardj70adeb22002-04-27 01:35:38 +0000779#define N_LIBC_TSD_EXTRA_KEYS 1
780
sewardj5716dbb2002-04-26 03:28:18 +0000781enum __libc_tsd_key_t { _LIBC_TSD_KEY_MALLOC = 0,
782 _LIBC_TSD_KEY_DL_ERROR,
783 _LIBC_TSD_KEY_N };
784
785/* Auto-initialising subsystem. libc_specifics_inited is set
786 after initialisation. libc_specifics_inited_mx guards it. */
787static int libc_specifics_inited = 0;
788static pthread_mutex_t libc_specifics_inited_mx = PTHREAD_MUTEX_INITIALIZER;
789
790/* These are the keys we must initialise the first time. */
sewardj70adeb22002-04-27 01:35:38 +0000791static pthread_key_t libc_specifics_keys[_LIBC_TSD_KEY_N
792 + N_LIBC_TSD_EXTRA_KEYS];
sewardj5716dbb2002-04-26 03:28:18 +0000793
794/* Initialise the keys, if they are not already initialise. */
795static
796void init_libc_tsd_keys ( void )
797{
798 int res, i;
799 pthread_key_t k;
800
801 res = pthread_mutex_lock(&libc_specifics_inited_mx);
802 if (res != 0) barf("init_libc_tsd_keys: lock");
803
804 if (libc_specifics_inited == 0) {
805 /* printf("INIT libc specifics\n"); */
806 libc_specifics_inited = 1;
sewardj70adeb22002-04-27 01:35:38 +0000807 for (i = 0; i < _LIBC_TSD_KEY_N + N_LIBC_TSD_EXTRA_KEYS; i++) {
sewardj5716dbb2002-04-26 03:28:18 +0000808 res = pthread_key_create(&k, NULL);
809 if (res != 0) barf("init_libc_tsd_keys: create");
810 libc_specifics_keys[i] = k;
811 }
812 }
813
814 res = pthread_mutex_unlock(&libc_specifics_inited_mx);
815 if (res != 0) barf("init_libc_tsd_keys: unlock");
816}
817
818
819static int
820libc_internal_tsd_set ( enum __libc_tsd_key_t key,
821 const void * pointer )
822{
sewardj70adeb22002-04-27 01:35:38 +0000823 int res;
824 static int moans = N_MOANS;
sewardj5716dbb2002-04-26 03:28:18 +0000825 /* printf("SET SET SET key %d ptr %p\n", key, pointer); */
sewardj70adeb22002-04-27 01:35:38 +0000826 if (key < _LIBC_TSD_KEY_MALLOC
827 || key >= _LIBC_TSD_KEY_N + N_LIBC_TSD_EXTRA_KEYS)
sewardj5716dbb2002-04-26 03:28:18 +0000828 barf("libc_internal_tsd_set: invalid key");
sewardj70adeb22002-04-27 01:35:38 +0000829 if (key >= _LIBC_TSD_KEY_N && moans-- > 0)
830 fprintf(stderr,
sewardj439d45e2002-05-03 20:43:10 +0000831 "valgrind's libpthread.so: libc_internal_tsd_set: "
832 "dubious key %d\n", key);
sewardj5716dbb2002-04-26 03:28:18 +0000833 init_libc_tsd_keys();
834 res = pthread_setspecific(libc_specifics_keys[key], pointer);
835 if (res != 0) barf("libc_internal_tsd_set: setspecific failed");
836 return 0;
837}
838
839static void *
840libc_internal_tsd_get ( enum __libc_tsd_key_t key )
841{
sewardj70adeb22002-04-27 01:35:38 +0000842 void* v;
843 static int moans = N_MOANS;
sewardj5716dbb2002-04-26 03:28:18 +0000844 /* printf("GET GET GET key %d\n", key); */
sewardj70adeb22002-04-27 01:35:38 +0000845 if (key < _LIBC_TSD_KEY_MALLOC
846 || key >= _LIBC_TSD_KEY_N + N_LIBC_TSD_EXTRA_KEYS)
sewardj5716dbb2002-04-26 03:28:18 +0000847 barf("libc_internal_tsd_get: invalid key");
sewardj70adeb22002-04-27 01:35:38 +0000848 if (key >= _LIBC_TSD_KEY_N && moans-- > 0)
849 fprintf(stderr,
sewardj439d45e2002-05-03 20:43:10 +0000850 "valgrind's libpthread.so: libc_internal_tsd_get: "
851 "dubious key %d\n", key);
sewardj5716dbb2002-04-26 03:28:18 +0000852 init_libc_tsd_keys();
853 v = pthread_getspecific(libc_specifics_keys[key]);
854 /* if (v == NULL) barf("libc_internal_tsd_set: getspecific failed"); */
855 return v;
856}
857
858
859
860
sewardj70adeb22002-04-27 01:35:38 +0000861int (*__libc_internal_tsd_set)
862 (enum __libc_tsd_key_t key, const void * pointer)
863 = libc_internal_tsd_set;
sewardj5716dbb2002-04-26 03:28:18 +0000864
sewardj70adeb22002-04-27 01:35:38 +0000865void* (*__libc_internal_tsd_get)
866 (enum __libc_tsd_key_t key)
867 = libc_internal_tsd_get;
sewardj5716dbb2002-04-26 03:28:18 +0000868
869
sewardje663cb92002-04-12 10:26:32 +0000870/* ---------------------------------------------------------------------
871 These are here (I think) because they are deemed cancellation
872 points by POSIX. For the moment we'll simply pass the call along
873 to the corresponding thread-unaware (?) libc routine.
874 ------------------------------------------------------------------ */
875
sewardje663cb92002-04-12 10:26:32 +0000876#include <stdlib.h>
877#include <signal.h>
sewardje663cb92002-04-12 10:26:32 +0000878#include <sys/types.h>
879#include <sys/socket.h>
880
sewardjd529a442002-05-04 19:49:21 +0000881#ifdef GLIBC_2_1
882extern
883int __sigaction
884 (int signum,
885 const struct sigaction *act,
886 struct sigaction *oldact);
887#else
sewardje663cb92002-04-12 10:26:32 +0000888extern
889int __libc_sigaction
890 (int signum,
891 const struct sigaction *act,
892 struct sigaction *oldact);
sewardjd529a442002-05-04 19:49:21 +0000893#endif
sewardje663cb92002-04-12 10:26:32 +0000894int sigaction(int signum,
895 const struct sigaction *act,
896 struct sigaction *oldact)
897{
sewardj2a1dcce2002-04-22 12:45:25 +0000898# ifdef GLIBC_2_1
899 return __sigaction(signum, act, oldact);
900# else
sewardj45b4b372002-04-16 22:50:32 +0000901 return __libc_sigaction(signum, act, oldact);
sewardj2a1dcce2002-04-22 12:45:25 +0000902# endif
sewardje663cb92002-04-12 10:26:32 +0000903}
904
905
906extern
907int __libc_connect(int sockfd,
908 const struct sockaddr *serv_addr,
909 socklen_t addrlen);
sewardj5905fae2002-04-26 13:25:00 +0000910__attribute__((weak))
sewardje663cb92002-04-12 10:26:32 +0000911int connect(int sockfd,
912 const struct sockaddr *serv_addr,
913 socklen_t addrlen)
914{
sewardj45b4b372002-04-16 22:50:32 +0000915 return __libc_connect(sockfd, serv_addr, addrlen);
sewardje663cb92002-04-12 10:26:32 +0000916}
917
918
919extern
920int __libc_fcntl(int fd, int cmd, long arg);
sewardj5905fae2002-04-26 13:25:00 +0000921__attribute__((weak))
sewardje663cb92002-04-12 10:26:32 +0000922int fcntl(int fd, int cmd, long arg)
923{
sewardj45b4b372002-04-16 22:50:32 +0000924 return __libc_fcntl(fd, cmd, arg);
sewardje663cb92002-04-12 10:26:32 +0000925}
926
927
928extern
929ssize_t __libc_write(int fd, const void *buf, size_t count);
sewardj5905fae2002-04-26 13:25:00 +0000930__attribute__((weak))
sewardje663cb92002-04-12 10:26:32 +0000931ssize_t write(int fd, const void *buf, size_t count)
932{
sewardj45b4b372002-04-16 22:50:32 +0000933 return __libc_write(fd, buf, count);
sewardje663cb92002-04-12 10:26:32 +0000934}
935
936
937extern
938ssize_t __libc_read(int fd, void *buf, size_t count);
sewardj5905fae2002-04-26 13:25:00 +0000939__attribute__((weak))
sewardje663cb92002-04-12 10:26:32 +0000940ssize_t read(int fd, void *buf, size_t count)
941{
sewardj45b4b372002-04-16 22:50:32 +0000942 return __libc_read(fd, buf, count);
sewardje663cb92002-04-12 10:26:32 +0000943}
944
sewardjbe32e452002-04-24 20:29:58 +0000945
946extern
sewardj853f55d2002-04-26 00:27:53 +0000947int __libc_open64(const char *pathname, int flags, mode_t mode);
sewardj5905fae2002-04-26 13:25:00 +0000948__attribute__((weak))
sewardj853f55d2002-04-26 00:27:53 +0000949int open64(const char *pathname, int flags, mode_t mode)
sewardjbe32e452002-04-24 20:29:58 +0000950{
sewardj853f55d2002-04-26 00:27:53 +0000951 return __libc_open64(pathname, flags, mode);
sewardjbe32e452002-04-24 20:29:58 +0000952}
953
sewardje663cb92002-04-12 10:26:32 +0000954
955extern
sewardj853f55d2002-04-26 00:27:53 +0000956int __libc_open(const char *pathname, int flags, mode_t mode);
sewardj5905fae2002-04-26 13:25:00 +0000957__attribute__((weak))
sewardj853f55d2002-04-26 00:27:53 +0000958int open(const char *pathname, int flags, mode_t mode)
sewardje663cb92002-04-12 10:26:32 +0000959{
sewardj853f55d2002-04-26 00:27:53 +0000960 return __libc_open(pathname, flags, mode);
sewardje663cb92002-04-12 10:26:32 +0000961}
962
963
964extern
965int __libc_close(int fd);
sewardj5905fae2002-04-26 13:25:00 +0000966__attribute__((weak))
sewardje663cb92002-04-12 10:26:32 +0000967int close(int fd)
968{
sewardj45b4b372002-04-16 22:50:32 +0000969 return __libc_close(fd);
sewardje663cb92002-04-12 10:26:32 +0000970}
971
972
973extern
974int __libc_accept(int s, struct sockaddr *addr, socklen_t *addrlen);
sewardj5905fae2002-04-26 13:25:00 +0000975__attribute__((weak))
sewardje663cb92002-04-12 10:26:32 +0000976int accept(int s, struct sockaddr *addr, socklen_t *addrlen)
977{
sewardj45b4b372002-04-16 22:50:32 +0000978 return __libc_accept(s, addr, addrlen);
sewardje663cb92002-04-12 10:26:32 +0000979}
980
981
982extern
983pid_t __libc_fork(void);
sewardj5905fae2002-04-26 13:25:00 +0000984pid_t __fork(void)
sewardje663cb92002-04-12 10:26:32 +0000985{
sewardj45b4b372002-04-16 22:50:32 +0000986 return __libc_fork();
sewardje663cb92002-04-12 10:26:32 +0000987}
988
989
990extern
991pid_t __libc_waitpid(pid_t pid, int *status, int options);
sewardj5905fae2002-04-26 13:25:00 +0000992__attribute__((weak))
sewardje663cb92002-04-12 10:26:32 +0000993pid_t waitpid(pid_t pid, int *status, int options)
994{
sewardj45b4b372002-04-16 22:50:32 +0000995 return __libc_waitpid(pid, status, options);
sewardje663cb92002-04-12 10:26:32 +0000996}
997
998
999extern
1000int __libc_nanosleep(const struct timespec *req, struct timespec *rem);
sewardj5905fae2002-04-26 13:25:00 +00001001__attribute__((weak))
sewardje663cb92002-04-12 10:26:32 +00001002int nanosleep(const struct timespec *req, struct timespec *rem)
1003{
1004 return __libc_nanosleep(req, rem);
1005}
1006
sewardjbe32e452002-04-24 20:29:58 +00001007
sewardje663cb92002-04-12 10:26:32 +00001008extern
1009int __libc_fsync(int fd);
sewardj5905fae2002-04-26 13:25:00 +00001010__attribute__((weak))
sewardje663cb92002-04-12 10:26:32 +00001011int fsync(int fd)
1012{
sewardj45b4b372002-04-16 22:50:32 +00001013 return __libc_fsync(fd);
sewardje663cb92002-04-12 10:26:32 +00001014}
1015
sewardjbe32e452002-04-24 20:29:58 +00001016
sewardj70c75362002-04-13 04:18:32 +00001017extern
1018off_t __libc_lseek(int fildes, off_t offset, int whence);
sewardj5905fae2002-04-26 13:25:00 +00001019__attribute__((weak))
sewardj70c75362002-04-13 04:18:32 +00001020off_t lseek(int fildes, off_t offset, int whence)
1021{
sewardj45b4b372002-04-16 22:50:32 +00001022 return __libc_lseek(fildes, offset, whence);
sewardj70c75362002-04-13 04:18:32 +00001023}
1024
sewardjbe32e452002-04-24 20:29:58 +00001025
1026extern
1027__off64_t __libc_lseek64(int fildes, __off64_t offset, int whence);
sewardj5905fae2002-04-26 13:25:00 +00001028__attribute__((weak))
sewardjbe32e452002-04-24 20:29:58 +00001029__off64_t lseek64(int fildes, __off64_t offset, int whence)
1030{
1031 return __libc_lseek64(fildes, offset, whence);
1032}
1033
1034
sewardj6af4b5d2002-04-16 04:40:49 +00001035extern
1036void __libc_longjmp(jmp_buf env, int val) __attribute((noreturn));
sewardj5905fae2002-04-26 13:25:00 +00001037/* not weak: __attribute__((weak)) */
sewardj6af4b5d2002-04-16 04:40:49 +00001038void longjmp(jmp_buf env, int val)
1039{
1040 __libc_longjmp(env, val);
1041}
1042
sewardjbe32e452002-04-24 20:29:58 +00001043
sewardj6af4b5d2002-04-16 04:40:49 +00001044extern
1045int __libc_send(int s, const void *msg, size_t len, int flags);
sewardj5905fae2002-04-26 13:25:00 +00001046__attribute__((weak))
sewardj6af4b5d2002-04-16 04:40:49 +00001047int send(int s, const void *msg, size_t len, int flags)
1048{
1049 return __libc_send(s, msg, len, flags);
1050}
1051
sewardjbe32e452002-04-24 20:29:58 +00001052
sewardj1e8cdc92002-04-18 11:37:52 +00001053extern
1054int __libc_recv(int s, void *buf, size_t len, int flags);
sewardj5905fae2002-04-26 13:25:00 +00001055__attribute__((weak))
sewardj1e8cdc92002-04-18 11:37:52 +00001056int recv(int s, void *buf, size_t len, int flags)
1057{
1058 return __libc_recv(s, buf, len, flags);
1059}
1060
sewardjbe32e452002-04-24 20:29:58 +00001061
sewardj796d6a22002-04-24 02:28:34 +00001062extern
sewardj436e0582002-04-26 14:31:40 +00001063int __libc_recvfrom(int s, void *buf, size_t len, int flags,
1064 struct sockaddr *from, socklen_t *fromlen);
1065__attribute__((weak))
1066int recvfrom(int s, void *buf, size_t len, int flags,
1067 struct sockaddr *from, socklen_t *fromlen)
1068{
1069 return __libc_recvfrom(s, buf, len, flags, from, fromlen);
1070}
1071
1072
1073extern
sewardj796d6a22002-04-24 02:28:34 +00001074int __libc_sendto(int s, const void *msg, size_t len, int flags,
1075 const struct sockaddr *to, socklen_t tolen);
sewardj5905fae2002-04-26 13:25:00 +00001076__attribute__((weak))
sewardj796d6a22002-04-24 02:28:34 +00001077int sendto(int s, const void *msg, size_t len, int flags,
1078 const struct sockaddr *to, socklen_t tolen)
1079{
1080 return __libc_sendto(s, msg, len, flags, to, tolen);
1081}
1082
sewardjbe32e452002-04-24 20:29:58 +00001083
sewardj369b1702002-04-24 13:28:15 +00001084extern
1085int __libc_system(const char* str);
sewardj5905fae2002-04-26 13:25:00 +00001086__attribute__((weak))
sewardj369b1702002-04-24 13:28:15 +00001087int system(const char* str)
1088{
1089 return __libc_system(str);
1090}
1091
sewardjbe32e452002-04-24 20:29:58 +00001092
sewardjab0b1c32002-04-24 19:26:47 +00001093extern
1094pid_t __libc_wait(int *status);
sewardj5905fae2002-04-26 13:25:00 +00001095__attribute__((weak))
sewardjab0b1c32002-04-24 19:26:47 +00001096pid_t wait(int *status)
1097{
1098 return __libc_wait(status);
1099}
1100
sewardj45b4b372002-04-16 22:50:32 +00001101
sewardj5905fae2002-04-26 13:25:00 +00001102
sewardj3b13f0e2002-04-25 20:17:29 +00001103/* ---------------------------------------------------------------------
1104 Nonblocking implementations of select() and poll(). This stuff will
1105 surely rot your mind.
1106 ------------------------------------------------------------------ */
sewardje663cb92002-04-12 10:26:32 +00001107
sewardj08a4c3f2002-04-13 03:45:44 +00001108/*--------------------------------------------------*/
1109
1110#include "vg_kerneliface.h"
1111
1112static
1113__inline__
1114int is_kerror ( int res )
1115{
1116 if (res >= -4095 && res <= -1)
1117 return 1;
1118 else
1119 return 0;
1120}
1121
1122
1123static
1124int my_do_syscall1 ( int syscallno, int arg1 )
1125{
1126 int __res;
1127 __asm__ volatile ("pushl %%ebx; movl %%edx,%%ebx ; int $0x80 ; popl %%ebx"
1128 : "=a" (__res)
1129 : "0" (syscallno),
1130 "d" (arg1) );
1131 return __res;
1132}
1133
1134static
1135int my_do_syscall2 ( int syscallno,
sewardjf854f472002-04-21 12:19:41 +00001136 int arg1, int arg2 )
sewardj08a4c3f2002-04-13 03:45:44 +00001137{
1138 int __res;
1139 __asm__ volatile ("pushl %%ebx; movl %%edx,%%ebx ; int $0x80 ; popl %%ebx"
1140 : "=a" (__res)
1141 : "0" (syscallno),
1142 "d" (arg1),
1143 "c" (arg2) );
1144 return __res;
1145}
1146
1147static
sewardjf854f472002-04-21 12:19:41 +00001148int my_do_syscall3 ( int syscallno,
1149 int arg1, int arg2, int arg3 )
1150{
1151 int __res;
1152 __asm__ volatile ("pushl %%ebx; movl %%esi,%%ebx ; int $0x80 ; popl %%ebx"
1153 : "=a" (__res)
1154 : "0" (syscallno),
1155 "S" (arg1),
1156 "c" (arg2),
1157 "d" (arg3) );
1158 return __res;
1159}
1160
1161static
sewardj08a4c3f2002-04-13 03:45:44 +00001162int do_syscall_select( int n,
1163 vki_fd_set* readfds,
1164 vki_fd_set* writefds,
1165 vki_fd_set* exceptfds,
1166 struct vki_timeval * timeout )
1167{
1168 int res;
1169 int args[5];
1170 args[0] = n;
1171 args[1] = (int)readfds;
1172 args[2] = (int)writefds;
1173 args[3] = (int)exceptfds;
1174 args[4] = (int)timeout;
1175 res = my_do_syscall1(__NR_select, (int)(&(args[0])) );
sewardj02535bc2002-04-21 01:08:26 +00001176 return res;
sewardj08a4c3f2002-04-13 03:45:44 +00001177}
1178
1179
1180/* This is a wrapper round select(), which makes it thread-safe,
1181 meaning that only this thread will block, rather than the entire
1182 process. This wrapper in turn depends on nanosleep() not to block
1183 the entire process, but I think (hope? suspect?) that POSIX
1184 pthreads guarantees that to be the case.
1185
1186 Basic idea is: modify the timeout parameter to select so that it
1187 returns immediately. Poll like this until select returns non-zero,
1188 indicating something interesting happened, or until our time is up.
1189 Space out the polls with nanosleeps of say 20 milliseconds, which
1190 is required to be nonblocking; this allows other threads to run.
sewardj02535bc2002-04-21 01:08:26 +00001191
1192 Assumes:
1193 * (checked via assert) types fd_set and vki_fd_set are identical.
1194 * (checked via assert) types timeval and vki_timeval are identical.
1195 * (unchecked) libc error numbers (EINTR etc) are the negation of the
1196 kernel's error numbers (VKI_EINTR etc).
sewardj08a4c3f2002-04-13 03:45:44 +00001197*/
sewardj08a4c3f2002-04-13 03:45:44 +00001198
sewardj5905fae2002-04-26 13:25:00 +00001199/* __attribute__((weak)) */
sewardj08a4c3f2002-04-13 03:45:44 +00001200int select ( int n,
1201 fd_set *rfds,
1202 fd_set *wfds,
1203 fd_set *xfds,
1204 struct timeval *timeout )
1205{
sewardj5f07b662002-04-23 16:52:51 +00001206 unsigned int ms_now, ms_end;
sewardj08a4c3f2002-04-13 03:45:44 +00001207 int res;
1208 fd_set rfds_copy;
1209 fd_set wfds_copy;
1210 fd_set xfds_copy;
1211 struct vki_timeval t_now;
sewardj08a4c3f2002-04-13 03:45:44 +00001212 struct vki_timeval zero_timeout;
1213 struct vki_timespec nanosleep_interval;
1214
sewardj5f07b662002-04-23 16:52:51 +00001215 /* gcc's complains about ms_end being used uninitialised -- classic
1216 case it can't understand, where ms_end is both defined and used
1217 only if timeout != NULL. Hence ... */
1218 ms_end = 0;
sewardj08a4c3f2002-04-13 03:45:44 +00001219
1220 /* We assume that the kernel and libc data layouts are identical
1221 for the following types. These asserts provide a crude
1222 check. */
1223 if (sizeof(fd_set) != sizeof(vki_fd_set)
1224 || sizeof(struct timeval) != sizeof(struct vki_timeval))
1225 barf("valgrind's hacky non-blocking select(): data sizes error");
1226
sewardj5f07b662002-04-23 16:52:51 +00001227 /* Detect the current time and simultaneously find out if we are
1228 running on Valgrind. */
1229 VALGRIND_MAGIC_SEQUENCE(ms_now, 0xFFFFFFFF /* default */,
1230 VG_USERREQ__READ_MILLISECOND_TIMER,
1231 0, 0, 0, 0);
1232
1233 /* If a zero timeout specified, this call is harmless. Also go
1234 this route if we're not running on Valgrind, for whatever
1235 reason. */
1236 if ( (timeout && timeout->tv_sec == 0 && timeout->tv_usec == 0)
1237 || (ms_now == 0xFFFFFFFF) ) {
sewardj02535bc2002-04-21 01:08:26 +00001238 res = do_syscall_select( n, (vki_fd_set*)rfds,
sewardj08a4c3f2002-04-13 03:45:44 +00001239 (vki_fd_set*)wfds,
1240 (vki_fd_set*)xfds,
1241 (struct vki_timeval*)timeout);
sewardj02535bc2002-04-21 01:08:26 +00001242 if (is_kerror(res)) {
1243 * (__errno_location()) = -res;
1244 return -1;
1245 } else {
1246 return res;
1247 }
1248 }
sewardj08a4c3f2002-04-13 03:45:44 +00001249
sewardj5f07b662002-04-23 16:52:51 +00001250 /* If a timeout was specified, set ms_end to be the end millisecond
1251 counter [wallclock] time. */
sewardj08a4c3f2002-04-13 03:45:44 +00001252 if (timeout) {
1253 res = my_do_syscall2(__NR_gettimeofday, (int)&t_now, (int)NULL);
1254 assert(res == 0);
sewardj5f07b662002-04-23 16:52:51 +00001255 ms_end = ms_now;
1256 ms_end += (timeout->tv_usec / 1000);
1257 ms_end += (timeout->tv_sec * 1000);
sewardj08a4c3f2002-04-13 03:45:44 +00001258 /* Stay sane ... */
sewardj5f07b662002-04-23 16:52:51 +00001259 assert (ms_end >= ms_now);
sewardj08a4c3f2002-04-13 03:45:44 +00001260 }
1261
1262 /* fprintf(stderr, "MY_SELECT: before loop\n"); */
1263
1264 /* Either timeout == NULL, meaning wait indefinitely, or timeout !=
sewardj5f07b662002-04-23 16:52:51 +00001265 NULL, in which case ms_end holds the end time. */
sewardj08a4c3f2002-04-13 03:45:44 +00001266 while (1) {
1267 if (timeout) {
sewardj5f07b662002-04-23 16:52:51 +00001268 VALGRIND_MAGIC_SEQUENCE(ms_now, 0xFFFFFFFF /* default */,
1269 VG_USERREQ__READ_MILLISECOND_TIMER,
1270 0, 0, 0, 0);
1271 assert(ms_now != 0xFFFFFFFF);
1272 if (ms_now >= ms_end) {
sewardj08a4c3f2002-04-13 03:45:44 +00001273 /* timeout; nothing interesting happened. */
1274 if (rfds) FD_ZERO(rfds);
1275 if (wfds) FD_ZERO(wfds);
1276 if (xfds) FD_ZERO(xfds);
1277 return 0;
1278 }
1279 }
1280
1281 /* These could be trashed each time round the loop, so restore
1282 them each time. */
1283 if (rfds) rfds_copy = *rfds;
1284 if (wfds) wfds_copy = *wfds;
1285 if (xfds) xfds_copy = *xfds;
1286
1287 zero_timeout.tv_sec = zero_timeout.tv_usec = 0;
1288
1289 res = do_syscall_select( n,
1290 rfds ? (vki_fd_set*)(&rfds_copy) : NULL,
1291 wfds ? (vki_fd_set*)(&wfds_copy) : NULL,
1292 xfds ? (vki_fd_set*)(&xfds_copy) : NULL,
1293 & zero_timeout );
sewardj02535bc2002-04-21 01:08:26 +00001294 if (is_kerror(res)) {
1295 /* Some kind of error (including EINTR). Set errno and
sewardj08a4c3f2002-04-13 03:45:44 +00001296 return. The sets are unspecified in this case. */
sewardj02535bc2002-04-21 01:08:26 +00001297 * (__errno_location()) = -res;
1298 return -1;
sewardj08a4c3f2002-04-13 03:45:44 +00001299 }
1300 if (res > 0) {
1301 /* one or more fds is ready. Copy out resulting sets and
1302 return. */
1303 if (rfds) *rfds = rfds_copy;
1304 if (wfds) *wfds = wfds_copy;
1305 if (xfds) *xfds = xfds_copy;
1306 return res;
1307 }
1308 /* fprintf(stderr, "MY_SELECT: nanosleep\n"); */
1309 /* nanosleep and go round again */
sewardj02535bc2002-04-21 01:08:26 +00001310 nanosleep_interval.tv_sec = 0;
sewardj956cc1b2002-04-25 01:33:50 +00001311 nanosleep_interval.tv_nsec = 50 * 1000 * 1000; /* 50 milliseconds */
sewardjf854f472002-04-21 12:19:41 +00001312 /* It's critical here that valgrind's nanosleep implementation
1313 is nonblocking. */
1314 (void)my_do_syscall2(__NR_nanosleep,
1315 (int)(&nanosleep_interval), (int)NULL);
1316 }
1317}
1318
1319
1320
1321
1322#include <sys/poll.h>
1323
sewardj72d58482002-04-24 02:20:20 +00001324#ifdef GLIBC_2_1
1325typedef unsigned long int nfds_t;
1326#endif
1327
sewardj5905fae2002-04-26 13:25:00 +00001328/* __attribute__((weak)) */
sewardjf854f472002-04-21 12:19:41 +00001329int poll (struct pollfd *__fds, nfds_t __nfds, int __timeout)
1330{
sewardj5f07b662002-04-23 16:52:51 +00001331 unsigned int ms_now, ms_end;
sewardjf854f472002-04-21 12:19:41 +00001332 int res, i;
sewardjf854f472002-04-21 12:19:41 +00001333 struct vki_timespec nanosleep_interval;
1334
1335 ensure_valgrind("poll");
1336
sewardj5f07b662002-04-23 16:52:51 +00001337 /* Detect the current time and simultaneously find out if we are
1338 running on Valgrind. */
1339 VALGRIND_MAGIC_SEQUENCE(ms_now, 0xFFFFFFFF /* default */,
1340 VG_USERREQ__READ_MILLISECOND_TIMER,
1341 0, 0, 0, 0);
1342
sewardjf854f472002-04-21 12:19:41 +00001343 if (/* CHECK SIZES FOR struct pollfd */
1344 sizeof(struct timeval) != sizeof(struct vki_timeval))
1345 barf("valgrind's hacky non-blocking poll(): data sizes error");
1346
sewardj5f07b662002-04-23 16:52:51 +00001347 /* dummy initialisation to keep gcc -Wall happy */
1348 ms_end = 0;
1349
1350 /* If a zero timeout specified, this call is harmless. Also do
1351 this if not running on Valgrind. */
1352 if (__timeout == 0 || ms_now == 0xFFFFFFFF) {
sewardjf854f472002-04-21 12:19:41 +00001353 res = my_do_syscall3(__NR_poll, (int)__fds, __nfds, __timeout);
1354 if (is_kerror(res)) {
1355 * (__errno_location()) = -res;
1356 return -1;
1357 } else {
1358 return res;
1359 }
1360 }
1361
sewardj5f07b662002-04-23 16:52:51 +00001362 /* If a timeout was specified, set ms_end to be the end wallclock
1363 time. Easy considering that __timeout is in milliseconds. */
sewardjf854f472002-04-21 12:19:41 +00001364 if (__timeout > 0) {
sewardj650ac002002-04-29 12:20:34 +00001365 ms_end = ms_now + (unsigned int)__timeout;
sewardjf854f472002-04-21 12:19:41 +00001366 }
1367
1368 /* fprintf(stderr, "MY_POLL: before loop\n"); */
1369
1370 /* Either timeout < 0, meaning wait indefinitely, or timeout > 0,
1371 in which case t_end holds the end time. */
sewardj5f07b662002-04-23 16:52:51 +00001372 assert(__timeout != 0);
1373
sewardjf854f472002-04-21 12:19:41 +00001374 while (1) {
sewardjf854f472002-04-21 12:19:41 +00001375 if (__timeout > 0) {
sewardj5f07b662002-04-23 16:52:51 +00001376 VALGRIND_MAGIC_SEQUENCE(ms_now, 0xFFFFFFFF /* default */,
1377 VG_USERREQ__READ_MILLISECOND_TIMER,
1378 0, 0, 0, 0);
1379 assert(ms_now != 0xFFFFFFFF);
1380 if (ms_now >= ms_end) {
sewardjf854f472002-04-21 12:19:41 +00001381 /* timeout; nothing interesting happened. */
1382 for (i = 0; i < __nfds; i++)
1383 __fds[i].revents = 0;
1384 return 0;
1385 }
1386 }
1387
sewardj5f07b662002-04-23 16:52:51 +00001388 /* Do a return-immediately poll. */
sewardjf854f472002-04-21 12:19:41 +00001389 res = my_do_syscall3(__NR_poll, (int)__fds, __nfds, 0 );
1390 if (is_kerror(res)) {
1391 /* Some kind of error. Set errno and return. */
1392 * (__errno_location()) = -res;
1393 return -1;
1394 }
1395 if (res > 0) {
1396 /* One or more fds is ready. Return now. */
1397 return res;
1398 }
1399 /* fprintf(stderr, "MY_POLL: nanosleep\n"); */
1400 /* nanosleep and go round again */
1401 nanosleep_interval.tv_sec = 0;
sewardj956cc1b2002-04-25 01:33:50 +00001402 nanosleep_interval.tv_nsec = 51 * 1000 * 1000; /* 51 milliseconds */
sewardj08a4c3f2002-04-13 03:45:44 +00001403 /* It's critical here that valgrind's nanosleep implementation
1404 is nonblocking. */
1405 (void)my_do_syscall2(__NR_nanosleep,
1406 (int)(&nanosleep_interval), (int)NULL);
1407 }
1408}
sewardj3b13f0e2002-04-25 20:17:29 +00001409
1410
1411/* ---------------------------------------------------------------------
1412 B'stard.
1413 ------------------------------------------------------------------ */
1414
1415# define strong_alias(name, aliasname) \
1416 extern __typeof (name) aliasname __attribute__ ((alias (#name)));
1417
sewardj5905fae2002-04-26 13:25:00 +00001418# define weak_alias(name, aliasname) \
1419 extern __typeof (name) aliasname __attribute__ ((weak, alias (#name)));
sewardj3b13f0e2002-04-25 20:17:29 +00001420
sewardj5905fae2002-04-26 13:25:00 +00001421strong_alias(__pthread_mutex_lock, pthread_mutex_lock)
1422strong_alias(__pthread_mutex_trylock, pthread_mutex_trylock)
1423strong_alias(__pthread_mutex_unlock, pthread_mutex_unlock)
1424strong_alias(__pthread_mutexattr_init, pthread_mutexattr_init)
1425 weak_alias(__pthread_mutexattr_settype, pthread_mutexattr_settype)
1426strong_alias(__pthread_mutex_init, pthread_mutex_init)
1427strong_alias(__pthread_mutexattr_destroy, pthread_mutexattr_destroy)
1428strong_alias(__pthread_mutex_destroy, pthread_mutex_destroy)
1429strong_alias(__pthread_once, pthread_once)
1430strong_alias(__pthread_atfork, pthread_atfork)
1431strong_alias(__pthread_key_create, pthread_key_create)
1432strong_alias(__pthread_getspecific, pthread_getspecific)
1433strong_alias(__pthread_setspecific, pthread_setspecific)
1434
sewardjd529a442002-05-04 19:49:21 +00001435#ifndef GLIBC_2_1
sewardj3b13f0e2002-04-25 20:17:29 +00001436strong_alias(sigaction, __sigaction)
sewardjd529a442002-05-04 19:49:21 +00001437#endif
1438
sewardj5905fae2002-04-26 13:25:00 +00001439strong_alias(close, __close)
sewardj3b13f0e2002-04-25 20:17:29 +00001440strong_alias(fcntl, __fcntl)
sewardj5905fae2002-04-26 13:25:00 +00001441strong_alias(lseek, __lseek)
1442strong_alias(open, __open)
1443strong_alias(open64, __open64)
1444//strong_alias(pread64, __pread64)
1445//strong_alias(pwrite64, __pwrite64)
1446strong_alias(read, __read)
1447strong_alias(wait, __wait)
1448strong_alias(write, __write)
sewardj3b13f0e2002-04-25 20:17:29 +00001449strong_alias(connect, __connect)
sewardj5905fae2002-04-26 13:25:00 +00001450strong_alias(send, __send)
1451
1452weak_alias(__fork, fork)
1453//weak_alias(__vfork, vfork)
1454
sewardj3b13f0e2002-04-25 20:17:29 +00001455
1456/*--------------------------------------------------*/
1457
sewardj5716dbb2002-04-26 03:28:18 +00001458int
1459pthread_rwlock_rdlock (void* /* pthread_rwlock_t* */ rwlock)
1460{
sewardj436e0582002-04-26 14:31:40 +00001461 static int moans = N_MOANS;
1462 if (moans-- > 0)
1463 kludged("pthread_rwlock_rdlock");
sewardj5716dbb2002-04-26 03:28:18 +00001464 return 0;
1465}
1466
sewardj5905fae2002-04-26 13:25:00 +00001467weak_alias(pthread_rwlock_rdlock, __pthread_rwlock_rdlock)
sewardj5716dbb2002-04-26 03:28:18 +00001468
1469
1470int
1471pthread_rwlock_unlock (void* /* pthread_rwlock_t* */ rwlock)
1472{
sewardj436e0582002-04-26 14:31:40 +00001473 static int moans = N_MOANS;
1474 if (moans-- > 0)
1475 kludged("pthread_rwlock_unlock");
sewardj5716dbb2002-04-26 03:28:18 +00001476 return 0;
1477}
1478
sewardj5905fae2002-04-26 13:25:00 +00001479weak_alias(pthread_rwlock_unlock, __pthread_rwlock_unlock)
sewardj5716dbb2002-04-26 03:28:18 +00001480
1481
sewardj060b04f2002-04-26 21:01:13 +00001482int
1483pthread_rwlock_wrlock (void* /* pthread_rwlock_t* */ rwlock)
1484{
1485 static int moans = N_MOANS;
1486 if (moans-- > 0)
1487 kludged("pthread_rwlock_wrlock");
1488 return 0;
1489}
1490
sewardj262b0292002-05-01 00:03:16 +00001491weak_alias(pthread_rwlock_wrlock, __pthread_rwlock_wrlock)
sewardj060b04f2002-04-26 21:01:13 +00001492
1493
sewardj3b13f0e2002-04-25 20:17:29 +00001494/* I've no idea what these are, but they get called quite a lot.
1495 Anybody know? */
1496
1497#undef _IO_flockfile
1498void _IO_flockfile ( _IO_FILE * file )
1499{
sewardj853f55d2002-04-26 00:27:53 +00001500 pthread_mutex_lock(file->_lock);
sewardj3b13f0e2002-04-25 20:17:29 +00001501}
sewardj5905fae2002-04-26 13:25:00 +00001502weak_alias(_IO_flockfile, flockfile);
1503
sewardj3b13f0e2002-04-25 20:17:29 +00001504
1505#undef _IO_funlockfile
1506void _IO_funlockfile ( _IO_FILE * file )
1507{
sewardj853f55d2002-04-26 00:27:53 +00001508 pthread_mutex_unlock(file->_lock);
sewardj3b13f0e2002-04-25 20:17:29 +00001509}
sewardj5905fae2002-04-26 13:25:00 +00001510weak_alias(_IO_funlockfile, funlockfile);
1511
sewardj3b13f0e2002-04-25 20:17:29 +00001512
1513void _pthread_cleanup_push_defer ( void )
1514{
sewardj439d45e2002-05-03 20:43:10 +00001515 static int moans = N_MOANS;
1516 if (moans-- > 0)
1517 ignored("_pthread_cleanup_push_defer");
sewardj3b13f0e2002-04-25 20:17:29 +00001518}
1519
1520void _pthread_cleanup_pop_restore ( void )
1521{
sewardj439d45e2002-05-03 20:43:10 +00001522 static int moans = N_MOANS;
1523 if (moans-- > 0)
1524 ignored("_pthread_cleanup_pop_restore");
sewardj3b13f0e2002-04-25 20:17:29 +00001525}
sewardjd4f2c712002-04-30 10:20:10 +00001526
1527
1528/* This doesn't seem to be needed to simulate libpthread.so's external
1529 interface, but many people complain about its absence. */
1530
1531strong_alias(__pthread_mutexattr_settype, __pthread_mutexattr_setkind_np)
1532weak_alias(__pthread_mutexattr_setkind_np, pthread_mutexattr_setkind_np)
sewardj439d45e2002-05-03 20:43:10 +00001533
1534
1535/*--------------------------------------------------------------------*/
1536/*--- end vg_libpthread.c ---*/
1537/*--------------------------------------------------------------------*/