blob: f125ea799123807f4ca358e3ad77cafef7c619f2 [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
710/* ---------------------------------------------------
sewardj3b13f0e2002-04-25 20:17:29 +0000711 LIBRARY-PRIVATE THREAD SPECIFIC STATE
sewardjf8f819e2002-04-17 23:21:37 +0000712 ------------------------------------------------ */
713
sewardj3b13f0e2002-04-25 20:17:29 +0000714#include <resolv.h>
715static int thread_specific_errno[VG_N_THREADS];
716static int thread_specific_h_errno[VG_N_THREADS];
717static struct __res_state
718 thread_specific_res_state[VG_N_THREADS];
sewardjf8f819e2002-04-17 23:21:37 +0000719
sewardj3b13f0e2002-04-25 20:17:29 +0000720int* __errno_location ( void )
sewardjf8f819e2002-04-17 23:21:37 +0000721{
722 int tid;
sewardj3b13f0e2002-04-25 20:17:29 +0000723 /* ensure_valgrind("__errno_location"); */
724 VALGRIND_MAGIC_SEQUENCE(tid, 1 /* default */,
sewardjf8f819e2002-04-17 23:21:37 +0000725 VG_USERREQ__PTHREAD_GET_THREADID,
726 0, 0, 0, 0);
sewardj3b13f0e2002-04-25 20:17:29 +0000727 /* 'cos I'm paranoid ... */
sewardj439d45e2002-05-03 20:43:10 +0000728 if (tid < 1 || tid >= VG_N_THREADS)
sewardj3b13f0e2002-04-25 20:17:29 +0000729 barf("__errno_location: invalid ThreadId");
730 return & thread_specific_errno[tid];
731}
732
733int* __h_errno_location ( void )
734{
735 int tid;
736 /* ensure_valgrind("__h_errno_location"); */
737 VALGRIND_MAGIC_SEQUENCE(tid, 1 /* default */,
738 VG_USERREQ__PTHREAD_GET_THREADID,
739 0, 0, 0, 0);
740 /* 'cos I'm paranoid ... */
sewardj439d45e2002-05-03 20:43:10 +0000741 if (tid < 1 || tid >= VG_N_THREADS)
sewardj3b13f0e2002-04-25 20:17:29 +0000742 barf("__h_errno_location: invalid ThreadId");
743 return & thread_specific_h_errno[tid];
744}
745
746struct __res_state* __res_state ( void )
747{
748 int tid;
749 /* ensure_valgrind("__res_state"); */
750 VALGRIND_MAGIC_SEQUENCE(tid, 1 /* default */,
751 VG_USERREQ__PTHREAD_GET_THREADID,
752 0, 0, 0, 0);
753 /* 'cos I'm paranoid ... */
sewardj439d45e2002-05-03 20:43:10 +0000754 if (tid < 1 || tid >= VG_N_THREADS)
sewardj3b13f0e2002-04-25 20:17:29 +0000755 barf("__res_state: invalid ThreadId");
756 return & thread_specific_res_state[tid];
sewardjf8f819e2002-04-17 23:21:37 +0000757}
758
759
sewardj5716dbb2002-04-26 03:28:18 +0000760/* ---------------------------------------------------
761 LIBC-PRIVATE SPECIFIC DATA
762 ------------------------------------------------ */
763
764/* Relies on assumption that initial private data is NULL. This
765 should be fixed somehow. */
766
767/* The allowable keys (indices) (all 2 of them).
768 From sysdeps/pthread/bits/libc-tsd.h
769*/
sewardj70adeb22002-04-27 01:35:38 +0000770#define N_LIBC_TSD_EXTRA_KEYS 1
771
sewardj5716dbb2002-04-26 03:28:18 +0000772enum __libc_tsd_key_t { _LIBC_TSD_KEY_MALLOC = 0,
773 _LIBC_TSD_KEY_DL_ERROR,
774 _LIBC_TSD_KEY_N };
775
776/* Auto-initialising subsystem. libc_specifics_inited is set
777 after initialisation. libc_specifics_inited_mx guards it. */
778static int libc_specifics_inited = 0;
779static pthread_mutex_t libc_specifics_inited_mx = PTHREAD_MUTEX_INITIALIZER;
780
781/* These are the keys we must initialise the first time. */
sewardj70adeb22002-04-27 01:35:38 +0000782static pthread_key_t libc_specifics_keys[_LIBC_TSD_KEY_N
783 + N_LIBC_TSD_EXTRA_KEYS];
sewardj5716dbb2002-04-26 03:28:18 +0000784
785/* Initialise the keys, if they are not already initialise. */
786static
787void init_libc_tsd_keys ( void )
788{
789 int res, i;
790 pthread_key_t k;
791
792 res = pthread_mutex_lock(&libc_specifics_inited_mx);
793 if (res != 0) barf("init_libc_tsd_keys: lock");
794
795 if (libc_specifics_inited == 0) {
796 /* printf("INIT libc specifics\n"); */
797 libc_specifics_inited = 1;
sewardj70adeb22002-04-27 01:35:38 +0000798 for (i = 0; i < _LIBC_TSD_KEY_N + N_LIBC_TSD_EXTRA_KEYS; i++) {
sewardj5716dbb2002-04-26 03:28:18 +0000799 res = pthread_key_create(&k, NULL);
800 if (res != 0) barf("init_libc_tsd_keys: create");
801 libc_specifics_keys[i] = k;
802 }
803 }
804
805 res = pthread_mutex_unlock(&libc_specifics_inited_mx);
806 if (res != 0) barf("init_libc_tsd_keys: unlock");
807}
808
809
810static int
811libc_internal_tsd_set ( enum __libc_tsd_key_t key,
812 const void * pointer )
813{
sewardj70adeb22002-04-27 01:35:38 +0000814 int res;
815 static int moans = N_MOANS;
sewardj5716dbb2002-04-26 03:28:18 +0000816 /* printf("SET SET SET key %d ptr %p\n", key, pointer); */
sewardj70adeb22002-04-27 01:35:38 +0000817 if (key < _LIBC_TSD_KEY_MALLOC
818 || key >= _LIBC_TSD_KEY_N + N_LIBC_TSD_EXTRA_KEYS)
sewardj5716dbb2002-04-26 03:28:18 +0000819 barf("libc_internal_tsd_set: invalid key");
sewardj70adeb22002-04-27 01:35:38 +0000820 if (key >= _LIBC_TSD_KEY_N && moans-- > 0)
821 fprintf(stderr,
sewardj439d45e2002-05-03 20:43:10 +0000822 "valgrind's libpthread.so: libc_internal_tsd_set: "
823 "dubious key %d\n", key);
sewardj5716dbb2002-04-26 03:28:18 +0000824 init_libc_tsd_keys();
825 res = pthread_setspecific(libc_specifics_keys[key], pointer);
826 if (res != 0) barf("libc_internal_tsd_set: setspecific failed");
827 return 0;
828}
829
830static void *
831libc_internal_tsd_get ( enum __libc_tsd_key_t key )
832{
sewardj70adeb22002-04-27 01:35:38 +0000833 void* v;
834 static int moans = N_MOANS;
sewardj5716dbb2002-04-26 03:28:18 +0000835 /* printf("GET GET GET key %d\n", key); */
sewardj70adeb22002-04-27 01:35:38 +0000836 if (key < _LIBC_TSD_KEY_MALLOC
837 || key >= _LIBC_TSD_KEY_N + N_LIBC_TSD_EXTRA_KEYS)
sewardj5716dbb2002-04-26 03:28:18 +0000838 barf("libc_internal_tsd_get: invalid key");
sewardj70adeb22002-04-27 01:35:38 +0000839 if (key >= _LIBC_TSD_KEY_N && moans-- > 0)
840 fprintf(stderr,
sewardj439d45e2002-05-03 20:43:10 +0000841 "valgrind's libpthread.so: libc_internal_tsd_get: "
842 "dubious key %d\n", key);
sewardj5716dbb2002-04-26 03:28:18 +0000843 init_libc_tsd_keys();
844 v = pthread_getspecific(libc_specifics_keys[key]);
845 /* if (v == NULL) barf("libc_internal_tsd_set: getspecific failed"); */
846 return v;
847}
848
849
850
851
sewardj70adeb22002-04-27 01:35:38 +0000852int (*__libc_internal_tsd_set)
853 (enum __libc_tsd_key_t key, const void * pointer)
854 = libc_internal_tsd_set;
sewardj5716dbb2002-04-26 03:28:18 +0000855
sewardj70adeb22002-04-27 01:35:38 +0000856void* (*__libc_internal_tsd_get)
857 (enum __libc_tsd_key_t key)
858 = libc_internal_tsd_get;
sewardj5716dbb2002-04-26 03:28:18 +0000859
860
sewardje663cb92002-04-12 10:26:32 +0000861/* ---------------------------------------------------------------------
862 These are here (I think) because they are deemed cancellation
863 points by POSIX. For the moment we'll simply pass the call along
864 to the corresponding thread-unaware (?) libc routine.
865 ------------------------------------------------------------------ */
866
sewardje663cb92002-04-12 10:26:32 +0000867#include <stdlib.h>
868#include <signal.h>
sewardje663cb92002-04-12 10:26:32 +0000869#include <sys/types.h>
870#include <sys/socket.h>
871
sewardjd529a442002-05-04 19:49:21 +0000872#ifdef GLIBC_2_1
873extern
874int __sigaction
875 (int signum,
876 const struct sigaction *act,
877 struct sigaction *oldact);
878#else
sewardje663cb92002-04-12 10:26:32 +0000879extern
880int __libc_sigaction
881 (int signum,
882 const struct sigaction *act,
883 struct sigaction *oldact);
sewardjd529a442002-05-04 19:49:21 +0000884#endif
sewardje663cb92002-04-12 10:26:32 +0000885int sigaction(int signum,
886 const struct sigaction *act,
887 struct sigaction *oldact)
888{
sewardj2a1dcce2002-04-22 12:45:25 +0000889# ifdef GLIBC_2_1
890 return __sigaction(signum, act, oldact);
891# else
sewardj45b4b372002-04-16 22:50:32 +0000892 return __libc_sigaction(signum, act, oldact);
sewardj2a1dcce2002-04-22 12:45:25 +0000893# endif
sewardje663cb92002-04-12 10:26:32 +0000894}
895
896
897extern
898int __libc_connect(int sockfd,
899 const struct sockaddr *serv_addr,
900 socklen_t addrlen);
sewardj5905fae2002-04-26 13:25:00 +0000901__attribute__((weak))
sewardje663cb92002-04-12 10:26:32 +0000902int connect(int sockfd,
903 const struct sockaddr *serv_addr,
904 socklen_t addrlen)
905{
sewardj45b4b372002-04-16 22:50:32 +0000906 return __libc_connect(sockfd, serv_addr, addrlen);
sewardje663cb92002-04-12 10:26:32 +0000907}
908
909
910extern
911int __libc_fcntl(int fd, int cmd, long arg);
sewardj5905fae2002-04-26 13:25:00 +0000912__attribute__((weak))
sewardje663cb92002-04-12 10:26:32 +0000913int fcntl(int fd, int cmd, long arg)
914{
sewardj45b4b372002-04-16 22:50:32 +0000915 return __libc_fcntl(fd, cmd, arg);
sewardje663cb92002-04-12 10:26:32 +0000916}
917
918
919extern
920ssize_t __libc_write(int fd, const void *buf, size_t count);
sewardj5905fae2002-04-26 13:25:00 +0000921__attribute__((weak))
sewardje663cb92002-04-12 10:26:32 +0000922ssize_t write(int fd, const void *buf, size_t count)
923{
sewardj45b4b372002-04-16 22:50:32 +0000924 return __libc_write(fd, buf, count);
sewardje663cb92002-04-12 10:26:32 +0000925}
926
927
928extern
929ssize_t __libc_read(int fd, void *buf, size_t count);
sewardj5905fae2002-04-26 13:25:00 +0000930__attribute__((weak))
sewardje663cb92002-04-12 10:26:32 +0000931ssize_t read(int fd, void *buf, size_t count)
932{
sewardj45b4b372002-04-16 22:50:32 +0000933 return __libc_read(fd, buf, count);
sewardje663cb92002-04-12 10:26:32 +0000934}
935
sewardjbe32e452002-04-24 20:29:58 +0000936
937extern
sewardj853f55d2002-04-26 00:27:53 +0000938int __libc_open64(const char *pathname, int flags, mode_t mode);
sewardj5905fae2002-04-26 13:25:00 +0000939__attribute__((weak))
sewardj853f55d2002-04-26 00:27:53 +0000940int open64(const char *pathname, int flags, mode_t mode)
sewardjbe32e452002-04-24 20:29:58 +0000941{
sewardj853f55d2002-04-26 00:27:53 +0000942 return __libc_open64(pathname, flags, mode);
sewardjbe32e452002-04-24 20:29:58 +0000943}
944
sewardje663cb92002-04-12 10:26:32 +0000945
946extern
sewardj853f55d2002-04-26 00:27:53 +0000947int __libc_open(const char *pathname, int flags, mode_t mode);
sewardj5905fae2002-04-26 13:25:00 +0000948__attribute__((weak))
sewardj853f55d2002-04-26 00:27:53 +0000949int open(const char *pathname, int flags, mode_t mode)
sewardje663cb92002-04-12 10:26:32 +0000950{
sewardj853f55d2002-04-26 00:27:53 +0000951 return __libc_open(pathname, flags, mode);
sewardje663cb92002-04-12 10:26:32 +0000952}
953
954
955extern
956int __libc_close(int fd);
sewardj5905fae2002-04-26 13:25:00 +0000957__attribute__((weak))
sewardje663cb92002-04-12 10:26:32 +0000958int close(int fd)
959{
sewardj45b4b372002-04-16 22:50:32 +0000960 return __libc_close(fd);
sewardje663cb92002-04-12 10:26:32 +0000961}
962
963
964extern
965int __libc_accept(int s, struct sockaddr *addr, socklen_t *addrlen);
sewardj5905fae2002-04-26 13:25:00 +0000966__attribute__((weak))
sewardje663cb92002-04-12 10:26:32 +0000967int accept(int s, struct sockaddr *addr, socklen_t *addrlen)
968{
sewardj45b4b372002-04-16 22:50:32 +0000969 return __libc_accept(s, addr, addrlen);
sewardje663cb92002-04-12 10:26:32 +0000970}
971
972
973extern
974pid_t __libc_fork(void);
sewardj5905fae2002-04-26 13:25:00 +0000975pid_t __fork(void)
sewardje663cb92002-04-12 10:26:32 +0000976{
sewardj45b4b372002-04-16 22:50:32 +0000977 return __libc_fork();
sewardje663cb92002-04-12 10:26:32 +0000978}
979
980
981extern
982pid_t __libc_waitpid(pid_t pid, int *status, int options);
sewardj5905fae2002-04-26 13:25:00 +0000983__attribute__((weak))
sewardje663cb92002-04-12 10:26:32 +0000984pid_t waitpid(pid_t pid, int *status, int options)
985{
sewardj45b4b372002-04-16 22:50:32 +0000986 return __libc_waitpid(pid, status, options);
sewardje663cb92002-04-12 10:26:32 +0000987}
988
989
990extern
991int __libc_nanosleep(const struct timespec *req, struct timespec *rem);
sewardj5905fae2002-04-26 13:25:00 +0000992__attribute__((weak))
sewardje663cb92002-04-12 10:26:32 +0000993int nanosleep(const struct timespec *req, struct timespec *rem)
994{
995 return __libc_nanosleep(req, rem);
996}
997
sewardjbe32e452002-04-24 20:29:58 +0000998
sewardje663cb92002-04-12 10:26:32 +0000999extern
1000int __libc_fsync(int fd);
sewardj5905fae2002-04-26 13:25:00 +00001001__attribute__((weak))
sewardje663cb92002-04-12 10:26:32 +00001002int fsync(int fd)
1003{
sewardj45b4b372002-04-16 22:50:32 +00001004 return __libc_fsync(fd);
sewardje663cb92002-04-12 10:26:32 +00001005}
1006
sewardjbe32e452002-04-24 20:29:58 +00001007
sewardj70c75362002-04-13 04:18:32 +00001008extern
1009off_t __libc_lseek(int fildes, off_t offset, int whence);
sewardj5905fae2002-04-26 13:25:00 +00001010__attribute__((weak))
sewardj70c75362002-04-13 04:18:32 +00001011off_t lseek(int fildes, off_t offset, int whence)
1012{
sewardj45b4b372002-04-16 22:50:32 +00001013 return __libc_lseek(fildes, offset, whence);
sewardj70c75362002-04-13 04:18:32 +00001014}
1015
sewardjbe32e452002-04-24 20:29:58 +00001016
1017extern
1018__off64_t __libc_lseek64(int fildes, __off64_t offset, int whence);
sewardj5905fae2002-04-26 13:25:00 +00001019__attribute__((weak))
sewardjbe32e452002-04-24 20:29:58 +00001020__off64_t lseek64(int fildes, __off64_t offset, int whence)
1021{
1022 return __libc_lseek64(fildes, offset, whence);
1023}
1024
1025
sewardj6af4b5d2002-04-16 04:40:49 +00001026extern
1027void __libc_longjmp(jmp_buf env, int val) __attribute((noreturn));
sewardj5905fae2002-04-26 13:25:00 +00001028/* not weak: __attribute__((weak)) */
sewardj6af4b5d2002-04-16 04:40:49 +00001029void longjmp(jmp_buf env, int val)
1030{
1031 __libc_longjmp(env, val);
1032}
1033
sewardjbe32e452002-04-24 20:29:58 +00001034
sewardj6af4b5d2002-04-16 04:40:49 +00001035extern
1036int __libc_send(int s, const void *msg, size_t len, int flags);
sewardj5905fae2002-04-26 13:25:00 +00001037__attribute__((weak))
sewardj6af4b5d2002-04-16 04:40:49 +00001038int send(int s, const void *msg, size_t len, int flags)
1039{
1040 return __libc_send(s, msg, len, flags);
1041}
1042
sewardjbe32e452002-04-24 20:29:58 +00001043
sewardj1e8cdc92002-04-18 11:37:52 +00001044extern
1045int __libc_recv(int s, void *buf, size_t len, int flags);
sewardj5905fae2002-04-26 13:25:00 +00001046__attribute__((weak))
sewardj1e8cdc92002-04-18 11:37:52 +00001047int recv(int s, void *buf, size_t len, int flags)
1048{
1049 return __libc_recv(s, buf, len, flags);
1050}
1051
sewardjbe32e452002-04-24 20:29:58 +00001052
sewardj796d6a22002-04-24 02:28:34 +00001053extern
sewardj436e0582002-04-26 14:31:40 +00001054int __libc_recvfrom(int s, void *buf, size_t len, int flags,
1055 struct sockaddr *from, socklen_t *fromlen);
1056__attribute__((weak))
1057int recvfrom(int s, void *buf, size_t len, int flags,
1058 struct sockaddr *from, socklen_t *fromlen)
1059{
1060 return __libc_recvfrom(s, buf, len, flags, from, fromlen);
1061}
1062
1063
1064extern
sewardj796d6a22002-04-24 02:28:34 +00001065int __libc_sendto(int s, const void *msg, size_t len, int flags,
1066 const struct sockaddr *to, socklen_t tolen);
sewardj5905fae2002-04-26 13:25:00 +00001067__attribute__((weak))
sewardj796d6a22002-04-24 02:28:34 +00001068int sendto(int s, const void *msg, size_t len, int flags,
1069 const struct sockaddr *to, socklen_t tolen)
1070{
1071 return __libc_sendto(s, msg, len, flags, to, tolen);
1072}
1073
sewardjbe32e452002-04-24 20:29:58 +00001074
sewardj369b1702002-04-24 13:28:15 +00001075extern
1076int __libc_system(const char* str);
sewardj5905fae2002-04-26 13:25:00 +00001077__attribute__((weak))
sewardj369b1702002-04-24 13:28:15 +00001078int system(const char* str)
1079{
1080 return __libc_system(str);
1081}
1082
sewardjbe32e452002-04-24 20:29:58 +00001083
sewardjab0b1c32002-04-24 19:26:47 +00001084extern
1085pid_t __libc_wait(int *status);
sewardj5905fae2002-04-26 13:25:00 +00001086__attribute__((weak))
sewardjab0b1c32002-04-24 19:26:47 +00001087pid_t wait(int *status)
1088{
1089 return __libc_wait(status);
1090}
1091
sewardj45b4b372002-04-16 22:50:32 +00001092
sewardj5905fae2002-04-26 13:25:00 +00001093
sewardj3b13f0e2002-04-25 20:17:29 +00001094/* ---------------------------------------------------------------------
1095 Nonblocking implementations of select() and poll(). This stuff will
1096 surely rot your mind.
1097 ------------------------------------------------------------------ */
sewardje663cb92002-04-12 10:26:32 +00001098
sewardj08a4c3f2002-04-13 03:45:44 +00001099/*--------------------------------------------------*/
1100
1101#include "vg_kerneliface.h"
1102
1103static
1104__inline__
1105int is_kerror ( int res )
1106{
1107 if (res >= -4095 && res <= -1)
1108 return 1;
1109 else
1110 return 0;
1111}
1112
1113
1114static
1115int my_do_syscall1 ( int syscallno, int arg1 )
1116{
1117 int __res;
1118 __asm__ volatile ("pushl %%ebx; movl %%edx,%%ebx ; int $0x80 ; popl %%ebx"
1119 : "=a" (__res)
1120 : "0" (syscallno),
1121 "d" (arg1) );
1122 return __res;
1123}
1124
1125static
1126int my_do_syscall2 ( int syscallno,
sewardjf854f472002-04-21 12:19:41 +00001127 int arg1, int arg2 )
sewardj08a4c3f2002-04-13 03:45:44 +00001128{
1129 int __res;
1130 __asm__ volatile ("pushl %%ebx; movl %%edx,%%ebx ; int $0x80 ; popl %%ebx"
1131 : "=a" (__res)
1132 : "0" (syscallno),
1133 "d" (arg1),
1134 "c" (arg2) );
1135 return __res;
1136}
1137
1138static
sewardjf854f472002-04-21 12:19:41 +00001139int my_do_syscall3 ( int syscallno,
1140 int arg1, int arg2, int arg3 )
1141{
1142 int __res;
1143 __asm__ volatile ("pushl %%ebx; movl %%esi,%%ebx ; int $0x80 ; popl %%ebx"
1144 : "=a" (__res)
1145 : "0" (syscallno),
1146 "S" (arg1),
1147 "c" (arg2),
1148 "d" (arg3) );
1149 return __res;
1150}
1151
1152static
sewardj08a4c3f2002-04-13 03:45:44 +00001153int do_syscall_select( int n,
1154 vki_fd_set* readfds,
1155 vki_fd_set* writefds,
1156 vki_fd_set* exceptfds,
1157 struct vki_timeval * timeout )
1158{
1159 int res;
1160 int args[5];
1161 args[0] = n;
1162 args[1] = (int)readfds;
1163 args[2] = (int)writefds;
1164 args[3] = (int)exceptfds;
1165 args[4] = (int)timeout;
1166 res = my_do_syscall1(__NR_select, (int)(&(args[0])) );
sewardj02535bc2002-04-21 01:08:26 +00001167 return res;
sewardj08a4c3f2002-04-13 03:45:44 +00001168}
1169
1170
1171/* This is a wrapper round select(), which makes it thread-safe,
1172 meaning that only this thread will block, rather than the entire
1173 process. This wrapper in turn depends on nanosleep() not to block
1174 the entire process, but I think (hope? suspect?) that POSIX
1175 pthreads guarantees that to be the case.
1176
1177 Basic idea is: modify the timeout parameter to select so that it
1178 returns immediately. Poll like this until select returns non-zero,
1179 indicating something interesting happened, or until our time is up.
1180 Space out the polls with nanosleeps of say 20 milliseconds, which
1181 is required to be nonblocking; this allows other threads to run.
sewardj02535bc2002-04-21 01:08:26 +00001182
1183 Assumes:
1184 * (checked via assert) types fd_set and vki_fd_set are identical.
1185 * (checked via assert) types timeval and vki_timeval are identical.
1186 * (unchecked) libc error numbers (EINTR etc) are the negation of the
1187 kernel's error numbers (VKI_EINTR etc).
sewardj08a4c3f2002-04-13 03:45:44 +00001188*/
sewardj08a4c3f2002-04-13 03:45:44 +00001189
sewardj5905fae2002-04-26 13:25:00 +00001190/* __attribute__((weak)) */
sewardj08a4c3f2002-04-13 03:45:44 +00001191int select ( int n,
1192 fd_set *rfds,
1193 fd_set *wfds,
1194 fd_set *xfds,
1195 struct timeval *timeout )
1196{
sewardj5f07b662002-04-23 16:52:51 +00001197 unsigned int ms_now, ms_end;
sewardj08a4c3f2002-04-13 03:45:44 +00001198 int res;
1199 fd_set rfds_copy;
1200 fd_set wfds_copy;
1201 fd_set xfds_copy;
1202 struct vki_timeval t_now;
sewardj08a4c3f2002-04-13 03:45:44 +00001203 struct vki_timeval zero_timeout;
1204 struct vki_timespec nanosleep_interval;
1205
sewardj5f07b662002-04-23 16:52:51 +00001206 /* gcc's complains about ms_end being used uninitialised -- classic
1207 case it can't understand, where ms_end is both defined and used
1208 only if timeout != NULL. Hence ... */
1209 ms_end = 0;
sewardj08a4c3f2002-04-13 03:45:44 +00001210
1211 /* We assume that the kernel and libc data layouts are identical
1212 for the following types. These asserts provide a crude
1213 check. */
1214 if (sizeof(fd_set) != sizeof(vki_fd_set)
1215 || sizeof(struct timeval) != sizeof(struct vki_timeval))
1216 barf("valgrind's hacky non-blocking select(): data sizes error");
1217
sewardj5f07b662002-04-23 16:52:51 +00001218 /* Detect the current time and simultaneously find out if we are
1219 running on Valgrind. */
1220 VALGRIND_MAGIC_SEQUENCE(ms_now, 0xFFFFFFFF /* default */,
1221 VG_USERREQ__READ_MILLISECOND_TIMER,
1222 0, 0, 0, 0);
1223
1224 /* If a zero timeout specified, this call is harmless. Also go
1225 this route if we're not running on Valgrind, for whatever
1226 reason. */
1227 if ( (timeout && timeout->tv_sec == 0 && timeout->tv_usec == 0)
1228 || (ms_now == 0xFFFFFFFF) ) {
sewardj02535bc2002-04-21 01:08:26 +00001229 res = do_syscall_select( n, (vki_fd_set*)rfds,
sewardj08a4c3f2002-04-13 03:45:44 +00001230 (vki_fd_set*)wfds,
1231 (vki_fd_set*)xfds,
1232 (struct vki_timeval*)timeout);
sewardj02535bc2002-04-21 01:08:26 +00001233 if (is_kerror(res)) {
1234 * (__errno_location()) = -res;
1235 return -1;
1236 } else {
1237 return res;
1238 }
1239 }
sewardj08a4c3f2002-04-13 03:45:44 +00001240
sewardj5f07b662002-04-23 16:52:51 +00001241 /* If a timeout was specified, set ms_end to be the end millisecond
1242 counter [wallclock] time. */
sewardj08a4c3f2002-04-13 03:45:44 +00001243 if (timeout) {
1244 res = my_do_syscall2(__NR_gettimeofday, (int)&t_now, (int)NULL);
1245 assert(res == 0);
sewardj5f07b662002-04-23 16:52:51 +00001246 ms_end = ms_now;
1247 ms_end += (timeout->tv_usec / 1000);
1248 ms_end += (timeout->tv_sec * 1000);
sewardj08a4c3f2002-04-13 03:45:44 +00001249 /* Stay sane ... */
sewardj5f07b662002-04-23 16:52:51 +00001250 assert (ms_end >= ms_now);
sewardj08a4c3f2002-04-13 03:45:44 +00001251 }
1252
1253 /* fprintf(stderr, "MY_SELECT: before loop\n"); */
1254
1255 /* Either timeout == NULL, meaning wait indefinitely, or timeout !=
sewardj5f07b662002-04-23 16:52:51 +00001256 NULL, in which case ms_end holds the end time. */
sewardj08a4c3f2002-04-13 03:45:44 +00001257 while (1) {
1258 if (timeout) {
sewardj5f07b662002-04-23 16:52:51 +00001259 VALGRIND_MAGIC_SEQUENCE(ms_now, 0xFFFFFFFF /* default */,
1260 VG_USERREQ__READ_MILLISECOND_TIMER,
1261 0, 0, 0, 0);
1262 assert(ms_now != 0xFFFFFFFF);
1263 if (ms_now >= ms_end) {
sewardj08a4c3f2002-04-13 03:45:44 +00001264 /* timeout; nothing interesting happened. */
1265 if (rfds) FD_ZERO(rfds);
1266 if (wfds) FD_ZERO(wfds);
1267 if (xfds) FD_ZERO(xfds);
1268 return 0;
1269 }
1270 }
1271
1272 /* These could be trashed each time round the loop, so restore
1273 them each time. */
1274 if (rfds) rfds_copy = *rfds;
1275 if (wfds) wfds_copy = *wfds;
1276 if (xfds) xfds_copy = *xfds;
1277
1278 zero_timeout.tv_sec = zero_timeout.tv_usec = 0;
1279
1280 res = do_syscall_select( n,
1281 rfds ? (vki_fd_set*)(&rfds_copy) : NULL,
1282 wfds ? (vki_fd_set*)(&wfds_copy) : NULL,
1283 xfds ? (vki_fd_set*)(&xfds_copy) : NULL,
1284 & zero_timeout );
sewardj02535bc2002-04-21 01:08:26 +00001285 if (is_kerror(res)) {
1286 /* Some kind of error (including EINTR). Set errno and
sewardj08a4c3f2002-04-13 03:45:44 +00001287 return. The sets are unspecified in this case. */
sewardj02535bc2002-04-21 01:08:26 +00001288 * (__errno_location()) = -res;
1289 return -1;
sewardj08a4c3f2002-04-13 03:45:44 +00001290 }
1291 if (res > 0) {
1292 /* one or more fds is ready. Copy out resulting sets and
1293 return. */
1294 if (rfds) *rfds = rfds_copy;
1295 if (wfds) *wfds = wfds_copy;
1296 if (xfds) *xfds = xfds_copy;
1297 return res;
1298 }
1299 /* fprintf(stderr, "MY_SELECT: nanosleep\n"); */
1300 /* nanosleep and go round again */
sewardj02535bc2002-04-21 01:08:26 +00001301 nanosleep_interval.tv_sec = 0;
sewardj956cc1b2002-04-25 01:33:50 +00001302 nanosleep_interval.tv_nsec = 50 * 1000 * 1000; /* 50 milliseconds */
sewardjf854f472002-04-21 12:19:41 +00001303 /* It's critical here that valgrind's nanosleep implementation
1304 is nonblocking. */
1305 (void)my_do_syscall2(__NR_nanosleep,
1306 (int)(&nanosleep_interval), (int)NULL);
1307 }
1308}
1309
1310
1311
1312
1313#include <sys/poll.h>
1314
sewardj72d58482002-04-24 02:20:20 +00001315#ifdef GLIBC_2_1
1316typedef unsigned long int nfds_t;
1317#endif
1318
sewardj5905fae2002-04-26 13:25:00 +00001319/* __attribute__((weak)) */
sewardjf854f472002-04-21 12:19:41 +00001320int poll (struct pollfd *__fds, nfds_t __nfds, int __timeout)
1321{
sewardj5f07b662002-04-23 16:52:51 +00001322 unsigned int ms_now, ms_end;
sewardjf854f472002-04-21 12:19:41 +00001323 int res, i;
sewardjf854f472002-04-21 12:19:41 +00001324 struct vki_timespec nanosleep_interval;
1325
1326 ensure_valgrind("poll");
1327
sewardj5f07b662002-04-23 16:52:51 +00001328 /* Detect the current time and simultaneously find out if we are
1329 running on Valgrind. */
1330 VALGRIND_MAGIC_SEQUENCE(ms_now, 0xFFFFFFFF /* default */,
1331 VG_USERREQ__READ_MILLISECOND_TIMER,
1332 0, 0, 0, 0);
1333
sewardjf854f472002-04-21 12:19:41 +00001334 if (/* CHECK SIZES FOR struct pollfd */
1335 sizeof(struct timeval) != sizeof(struct vki_timeval))
1336 barf("valgrind's hacky non-blocking poll(): data sizes error");
1337
sewardj5f07b662002-04-23 16:52:51 +00001338 /* dummy initialisation to keep gcc -Wall happy */
1339 ms_end = 0;
1340
1341 /* If a zero timeout specified, this call is harmless. Also do
1342 this if not running on Valgrind. */
1343 if (__timeout == 0 || ms_now == 0xFFFFFFFF) {
sewardjf854f472002-04-21 12:19:41 +00001344 res = my_do_syscall3(__NR_poll, (int)__fds, __nfds, __timeout);
1345 if (is_kerror(res)) {
1346 * (__errno_location()) = -res;
1347 return -1;
1348 } else {
1349 return res;
1350 }
1351 }
1352
sewardj5f07b662002-04-23 16:52:51 +00001353 /* If a timeout was specified, set ms_end to be the end wallclock
1354 time. Easy considering that __timeout is in milliseconds. */
sewardjf854f472002-04-21 12:19:41 +00001355 if (__timeout > 0) {
sewardj650ac002002-04-29 12:20:34 +00001356 ms_end = ms_now + (unsigned int)__timeout;
sewardjf854f472002-04-21 12:19:41 +00001357 }
1358
1359 /* fprintf(stderr, "MY_POLL: before loop\n"); */
1360
1361 /* Either timeout < 0, meaning wait indefinitely, or timeout > 0,
1362 in which case t_end holds the end time. */
sewardj5f07b662002-04-23 16:52:51 +00001363 assert(__timeout != 0);
1364
sewardjf854f472002-04-21 12:19:41 +00001365 while (1) {
sewardjf854f472002-04-21 12:19:41 +00001366 if (__timeout > 0) {
sewardj5f07b662002-04-23 16:52:51 +00001367 VALGRIND_MAGIC_SEQUENCE(ms_now, 0xFFFFFFFF /* default */,
1368 VG_USERREQ__READ_MILLISECOND_TIMER,
1369 0, 0, 0, 0);
1370 assert(ms_now != 0xFFFFFFFF);
1371 if (ms_now >= ms_end) {
sewardjf854f472002-04-21 12:19:41 +00001372 /* timeout; nothing interesting happened. */
1373 for (i = 0; i < __nfds; i++)
1374 __fds[i].revents = 0;
1375 return 0;
1376 }
1377 }
1378
sewardj5f07b662002-04-23 16:52:51 +00001379 /* Do a return-immediately poll. */
sewardjf854f472002-04-21 12:19:41 +00001380 res = my_do_syscall3(__NR_poll, (int)__fds, __nfds, 0 );
1381 if (is_kerror(res)) {
1382 /* Some kind of error. Set errno and return. */
1383 * (__errno_location()) = -res;
1384 return -1;
1385 }
1386 if (res > 0) {
1387 /* One or more fds is ready. Return now. */
1388 return res;
1389 }
1390 /* fprintf(stderr, "MY_POLL: nanosleep\n"); */
1391 /* nanosleep and go round again */
1392 nanosleep_interval.tv_sec = 0;
sewardj956cc1b2002-04-25 01:33:50 +00001393 nanosleep_interval.tv_nsec = 51 * 1000 * 1000; /* 51 milliseconds */
sewardj08a4c3f2002-04-13 03:45:44 +00001394 /* It's critical here that valgrind's nanosleep implementation
1395 is nonblocking. */
1396 (void)my_do_syscall2(__NR_nanosleep,
1397 (int)(&nanosleep_interval), (int)NULL);
1398 }
1399}
sewardj3b13f0e2002-04-25 20:17:29 +00001400
1401
1402/* ---------------------------------------------------------------------
1403 B'stard.
1404 ------------------------------------------------------------------ */
1405
1406# define strong_alias(name, aliasname) \
1407 extern __typeof (name) aliasname __attribute__ ((alias (#name)));
1408
sewardj5905fae2002-04-26 13:25:00 +00001409# define weak_alias(name, aliasname) \
1410 extern __typeof (name) aliasname __attribute__ ((weak, alias (#name)));
sewardj3b13f0e2002-04-25 20:17:29 +00001411
sewardj5905fae2002-04-26 13:25:00 +00001412strong_alias(__pthread_mutex_lock, pthread_mutex_lock)
1413strong_alias(__pthread_mutex_trylock, pthread_mutex_trylock)
1414strong_alias(__pthread_mutex_unlock, pthread_mutex_unlock)
1415strong_alias(__pthread_mutexattr_init, pthread_mutexattr_init)
1416 weak_alias(__pthread_mutexattr_settype, pthread_mutexattr_settype)
1417strong_alias(__pthread_mutex_init, pthread_mutex_init)
1418strong_alias(__pthread_mutexattr_destroy, pthread_mutexattr_destroy)
1419strong_alias(__pthread_mutex_destroy, pthread_mutex_destroy)
1420strong_alias(__pthread_once, pthread_once)
1421strong_alias(__pthread_atfork, pthread_atfork)
1422strong_alias(__pthread_key_create, pthread_key_create)
1423strong_alias(__pthread_getspecific, pthread_getspecific)
1424strong_alias(__pthread_setspecific, pthread_setspecific)
1425
sewardjd529a442002-05-04 19:49:21 +00001426#ifndef GLIBC_2_1
sewardj3b13f0e2002-04-25 20:17:29 +00001427strong_alias(sigaction, __sigaction)
sewardjd529a442002-05-04 19:49:21 +00001428#endif
1429
sewardj5905fae2002-04-26 13:25:00 +00001430strong_alias(close, __close)
sewardj3b13f0e2002-04-25 20:17:29 +00001431strong_alias(fcntl, __fcntl)
sewardj5905fae2002-04-26 13:25:00 +00001432strong_alias(lseek, __lseek)
1433strong_alias(open, __open)
1434strong_alias(open64, __open64)
1435//strong_alias(pread64, __pread64)
1436//strong_alias(pwrite64, __pwrite64)
1437strong_alias(read, __read)
1438strong_alias(wait, __wait)
1439strong_alias(write, __write)
sewardj3b13f0e2002-04-25 20:17:29 +00001440strong_alias(connect, __connect)
sewardj5905fae2002-04-26 13:25:00 +00001441strong_alias(send, __send)
1442
1443weak_alias(__fork, fork)
1444//weak_alias(__vfork, vfork)
1445
sewardj3b13f0e2002-04-25 20:17:29 +00001446
1447/*--------------------------------------------------*/
1448
sewardj5716dbb2002-04-26 03:28:18 +00001449int
1450pthread_rwlock_rdlock (void* /* pthread_rwlock_t* */ rwlock)
1451{
sewardj436e0582002-04-26 14:31:40 +00001452 static int moans = N_MOANS;
1453 if (moans-- > 0)
1454 kludged("pthread_rwlock_rdlock");
sewardj5716dbb2002-04-26 03:28:18 +00001455 return 0;
1456}
1457
sewardj5905fae2002-04-26 13:25:00 +00001458weak_alias(pthread_rwlock_rdlock, __pthread_rwlock_rdlock)
sewardj5716dbb2002-04-26 03:28:18 +00001459
1460
1461int
1462pthread_rwlock_unlock (void* /* pthread_rwlock_t* */ rwlock)
1463{
sewardj436e0582002-04-26 14:31:40 +00001464 static int moans = N_MOANS;
1465 if (moans-- > 0)
1466 kludged("pthread_rwlock_unlock");
sewardj5716dbb2002-04-26 03:28:18 +00001467 return 0;
1468}
1469
sewardj5905fae2002-04-26 13:25:00 +00001470weak_alias(pthread_rwlock_unlock, __pthread_rwlock_unlock)
sewardj5716dbb2002-04-26 03:28:18 +00001471
1472
sewardj060b04f2002-04-26 21:01:13 +00001473int
1474pthread_rwlock_wrlock (void* /* pthread_rwlock_t* */ rwlock)
1475{
1476 static int moans = N_MOANS;
1477 if (moans-- > 0)
1478 kludged("pthread_rwlock_wrlock");
1479 return 0;
1480}
1481
sewardj262b0292002-05-01 00:03:16 +00001482weak_alias(pthread_rwlock_wrlock, __pthread_rwlock_wrlock)
sewardj060b04f2002-04-26 21:01:13 +00001483
1484
sewardj3b13f0e2002-04-25 20:17:29 +00001485/* I've no idea what these are, but they get called quite a lot.
1486 Anybody know? */
1487
1488#undef _IO_flockfile
1489void _IO_flockfile ( _IO_FILE * file )
1490{
sewardj853f55d2002-04-26 00:27:53 +00001491 pthread_mutex_lock(file->_lock);
sewardj3b13f0e2002-04-25 20:17:29 +00001492}
sewardj5905fae2002-04-26 13:25:00 +00001493weak_alias(_IO_flockfile, flockfile);
1494
sewardj3b13f0e2002-04-25 20:17:29 +00001495
1496#undef _IO_funlockfile
1497void _IO_funlockfile ( _IO_FILE * file )
1498{
sewardj853f55d2002-04-26 00:27:53 +00001499 pthread_mutex_unlock(file->_lock);
sewardj3b13f0e2002-04-25 20:17:29 +00001500}
sewardj5905fae2002-04-26 13:25:00 +00001501weak_alias(_IO_funlockfile, funlockfile);
1502
sewardj3b13f0e2002-04-25 20:17:29 +00001503
1504void _pthread_cleanup_push_defer ( void )
1505{
sewardj439d45e2002-05-03 20:43:10 +00001506 static int moans = N_MOANS;
1507 if (moans-- > 0)
1508 ignored("_pthread_cleanup_push_defer");
sewardj3b13f0e2002-04-25 20:17:29 +00001509}
1510
1511void _pthread_cleanup_pop_restore ( void )
1512{
sewardj439d45e2002-05-03 20:43:10 +00001513 static int moans = N_MOANS;
1514 if (moans-- > 0)
1515 ignored("_pthread_cleanup_pop_restore");
sewardj3b13f0e2002-04-25 20:17:29 +00001516}
sewardjd4f2c712002-04-30 10:20:10 +00001517
1518
1519/* This doesn't seem to be needed to simulate libpthread.so's external
1520 interface, but many people complain about its absence. */
1521
1522strong_alias(__pthread_mutexattr_settype, __pthread_mutexattr_setkind_np)
1523weak_alias(__pthread_mutexattr_setkind_np, pthread_mutexattr_setkind_np)
sewardj439d45e2002-05-03 20:43:10 +00001524
1525
1526/*--------------------------------------------------------------------*/
1527/*--- end vg_libpthread.c ---*/
1528/*--------------------------------------------------------------------*/