blob: 55846f06a85e8a1f9905eb6e4094599141f4a1fc [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
872extern
873int __libc_sigaction
874 (int signum,
875 const struct sigaction *act,
876 struct sigaction *oldact);
877int sigaction(int signum,
878 const struct sigaction *act,
879 struct sigaction *oldact)
880{
sewardj2a1dcce2002-04-22 12:45:25 +0000881# ifdef GLIBC_2_1
882 return __sigaction(signum, act, oldact);
883# else
sewardj45b4b372002-04-16 22:50:32 +0000884 return __libc_sigaction(signum, act, oldact);
sewardj2a1dcce2002-04-22 12:45:25 +0000885# endif
sewardje663cb92002-04-12 10:26:32 +0000886}
887
888
889extern
890int __libc_connect(int sockfd,
891 const struct sockaddr *serv_addr,
892 socklen_t addrlen);
sewardj5905fae2002-04-26 13:25:00 +0000893__attribute__((weak))
sewardje663cb92002-04-12 10:26:32 +0000894int connect(int sockfd,
895 const struct sockaddr *serv_addr,
896 socklen_t addrlen)
897{
sewardj45b4b372002-04-16 22:50:32 +0000898 return __libc_connect(sockfd, serv_addr, addrlen);
sewardje663cb92002-04-12 10:26:32 +0000899}
900
901
902extern
903int __libc_fcntl(int fd, int cmd, long arg);
sewardj5905fae2002-04-26 13:25:00 +0000904__attribute__((weak))
sewardje663cb92002-04-12 10:26:32 +0000905int fcntl(int fd, int cmd, long arg)
906{
sewardj45b4b372002-04-16 22:50:32 +0000907 return __libc_fcntl(fd, cmd, arg);
sewardje663cb92002-04-12 10:26:32 +0000908}
909
910
911extern
912ssize_t __libc_write(int fd, const void *buf, size_t count);
sewardj5905fae2002-04-26 13:25:00 +0000913__attribute__((weak))
sewardje663cb92002-04-12 10:26:32 +0000914ssize_t write(int fd, const void *buf, size_t count)
915{
sewardj45b4b372002-04-16 22:50:32 +0000916 return __libc_write(fd, buf, count);
sewardje663cb92002-04-12 10:26:32 +0000917}
918
919
920extern
921ssize_t __libc_read(int fd, void *buf, size_t count);
sewardj5905fae2002-04-26 13:25:00 +0000922__attribute__((weak))
sewardje663cb92002-04-12 10:26:32 +0000923ssize_t read(int fd, void *buf, size_t count)
924{
sewardj45b4b372002-04-16 22:50:32 +0000925 return __libc_read(fd, buf, count);
sewardje663cb92002-04-12 10:26:32 +0000926}
927
sewardjbe32e452002-04-24 20:29:58 +0000928
929extern
sewardj853f55d2002-04-26 00:27:53 +0000930int __libc_open64(const char *pathname, int flags, mode_t mode);
sewardj5905fae2002-04-26 13:25:00 +0000931__attribute__((weak))
sewardj853f55d2002-04-26 00:27:53 +0000932int open64(const char *pathname, int flags, mode_t mode)
sewardjbe32e452002-04-24 20:29:58 +0000933{
sewardj853f55d2002-04-26 00:27:53 +0000934 return __libc_open64(pathname, flags, mode);
sewardjbe32e452002-04-24 20:29:58 +0000935}
936
sewardje663cb92002-04-12 10:26:32 +0000937
938extern
sewardj853f55d2002-04-26 00:27:53 +0000939int __libc_open(const char *pathname, int flags, mode_t mode);
sewardj5905fae2002-04-26 13:25:00 +0000940__attribute__((weak))
sewardj853f55d2002-04-26 00:27:53 +0000941int open(const char *pathname, int flags, mode_t mode)
sewardje663cb92002-04-12 10:26:32 +0000942{
sewardj853f55d2002-04-26 00:27:53 +0000943 return __libc_open(pathname, flags, mode);
sewardje663cb92002-04-12 10:26:32 +0000944}
945
946
947extern
948int __libc_close(int fd);
sewardj5905fae2002-04-26 13:25:00 +0000949__attribute__((weak))
sewardje663cb92002-04-12 10:26:32 +0000950int close(int fd)
951{
sewardj45b4b372002-04-16 22:50:32 +0000952 return __libc_close(fd);
sewardje663cb92002-04-12 10:26:32 +0000953}
954
955
956extern
957int __libc_accept(int s, struct sockaddr *addr, socklen_t *addrlen);
sewardj5905fae2002-04-26 13:25:00 +0000958__attribute__((weak))
sewardje663cb92002-04-12 10:26:32 +0000959int accept(int s, struct sockaddr *addr, socklen_t *addrlen)
960{
sewardj45b4b372002-04-16 22:50:32 +0000961 return __libc_accept(s, addr, addrlen);
sewardje663cb92002-04-12 10:26:32 +0000962}
963
964
965extern
966pid_t __libc_fork(void);
sewardj5905fae2002-04-26 13:25:00 +0000967pid_t __fork(void)
sewardje663cb92002-04-12 10:26:32 +0000968{
sewardj45b4b372002-04-16 22:50:32 +0000969 return __libc_fork();
sewardje663cb92002-04-12 10:26:32 +0000970}
971
972
973extern
974pid_t __libc_waitpid(pid_t pid, int *status, int options);
sewardj5905fae2002-04-26 13:25:00 +0000975__attribute__((weak))
sewardje663cb92002-04-12 10:26:32 +0000976pid_t waitpid(pid_t pid, int *status, int options)
977{
sewardj45b4b372002-04-16 22:50:32 +0000978 return __libc_waitpid(pid, status, options);
sewardje663cb92002-04-12 10:26:32 +0000979}
980
981
982extern
983int __libc_nanosleep(const struct timespec *req, struct timespec *rem);
sewardj5905fae2002-04-26 13:25:00 +0000984__attribute__((weak))
sewardje663cb92002-04-12 10:26:32 +0000985int nanosleep(const struct timespec *req, struct timespec *rem)
986{
987 return __libc_nanosleep(req, rem);
988}
989
sewardjbe32e452002-04-24 20:29:58 +0000990
sewardje663cb92002-04-12 10:26:32 +0000991extern
992int __libc_fsync(int fd);
sewardj5905fae2002-04-26 13:25:00 +0000993__attribute__((weak))
sewardje663cb92002-04-12 10:26:32 +0000994int fsync(int fd)
995{
sewardj45b4b372002-04-16 22:50:32 +0000996 return __libc_fsync(fd);
sewardje663cb92002-04-12 10:26:32 +0000997}
998
sewardjbe32e452002-04-24 20:29:58 +0000999
sewardj70c75362002-04-13 04:18:32 +00001000extern
1001off_t __libc_lseek(int fildes, off_t offset, int whence);
sewardj5905fae2002-04-26 13:25:00 +00001002__attribute__((weak))
sewardj70c75362002-04-13 04:18:32 +00001003off_t lseek(int fildes, off_t offset, int whence)
1004{
sewardj45b4b372002-04-16 22:50:32 +00001005 return __libc_lseek(fildes, offset, whence);
sewardj70c75362002-04-13 04:18:32 +00001006}
1007
sewardjbe32e452002-04-24 20:29:58 +00001008
1009extern
1010__off64_t __libc_lseek64(int fildes, __off64_t offset, int whence);
sewardj5905fae2002-04-26 13:25:00 +00001011__attribute__((weak))
sewardjbe32e452002-04-24 20:29:58 +00001012__off64_t lseek64(int fildes, __off64_t offset, int whence)
1013{
1014 return __libc_lseek64(fildes, offset, whence);
1015}
1016
1017
sewardj6af4b5d2002-04-16 04:40:49 +00001018extern
1019void __libc_longjmp(jmp_buf env, int val) __attribute((noreturn));
sewardj5905fae2002-04-26 13:25:00 +00001020/* not weak: __attribute__((weak)) */
sewardj6af4b5d2002-04-16 04:40:49 +00001021void longjmp(jmp_buf env, int val)
1022{
1023 __libc_longjmp(env, val);
1024}
1025
sewardjbe32e452002-04-24 20:29:58 +00001026
sewardj6af4b5d2002-04-16 04:40:49 +00001027extern
1028int __libc_send(int s, const void *msg, size_t len, int flags);
sewardj5905fae2002-04-26 13:25:00 +00001029__attribute__((weak))
sewardj6af4b5d2002-04-16 04:40:49 +00001030int send(int s, const void *msg, size_t len, int flags)
1031{
1032 return __libc_send(s, msg, len, flags);
1033}
1034
sewardjbe32e452002-04-24 20:29:58 +00001035
sewardj1e8cdc92002-04-18 11:37:52 +00001036extern
1037int __libc_recv(int s, void *buf, size_t len, int flags);
sewardj5905fae2002-04-26 13:25:00 +00001038__attribute__((weak))
sewardj1e8cdc92002-04-18 11:37:52 +00001039int recv(int s, void *buf, size_t len, int flags)
1040{
1041 return __libc_recv(s, buf, len, flags);
1042}
1043
sewardjbe32e452002-04-24 20:29:58 +00001044
sewardj796d6a22002-04-24 02:28:34 +00001045extern
sewardj436e0582002-04-26 14:31:40 +00001046int __libc_recvfrom(int s, void *buf, size_t len, int flags,
1047 struct sockaddr *from, socklen_t *fromlen);
1048__attribute__((weak))
1049int recvfrom(int s, void *buf, size_t len, int flags,
1050 struct sockaddr *from, socklen_t *fromlen)
1051{
1052 return __libc_recvfrom(s, buf, len, flags, from, fromlen);
1053}
1054
1055
1056extern
sewardj796d6a22002-04-24 02:28:34 +00001057int __libc_sendto(int s, const void *msg, size_t len, int flags,
1058 const struct sockaddr *to, socklen_t tolen);
sewardj5905fae2002-04-26 13:25:00 +00001059__attribute__((weak))
sewardj796d6a22002-04-24 02:28:34 +00001060int sendto(int s, const void *msg, size_t len, int flags,
1061 const struct sockaddr *to, socklen_t tolen)
1062{
1063 return __libc_sendto(s, msg, len, flags, to, tolen);
1064}
1065
sewardjbe32e452002-04-24 20:29:58 +00001066
sewardj369b1702002-04-24 13:28:15 +00001067extern
1068int __libc_system(const char* str);
sewardj5905fae2002-04-26 13:25:00 +00001069__attribute__((weak))
sewardj369b1702002-04-24 13:28:15 +00001070int system(const char* str)
1071{
1072 return __libc_system(str);
1073}
1074
sewardjbe32e452002-04-24 20:29:58 +00001075
sewardjab0b1c32002-04-24 19:26:47 +00001076extern
1077pid_t __libc_wait(int *status);
sewardj5905fae2002-04-26 13:25:00 +00001078__attribute__((weak))
sewardjab0b1c32002-04-24 19:26:47 +00001079pid_t wait(int *status)
1080{
1081 return __libc_wait(status);
1082}
1083
sewardj45b4b372002-04-16 22:50:32 +00001084
sewardj5905fae2002-04-26 13:25:00 +00001085
sewardj3b13f0e2002-04-25 20:17:29 +00001086/* ---------------------------------------------------------------------
1087 Nonblocking implementations of select() and poll(). This stuff will
1088 surely rot your mind.
1089 ------------------------------------------------------------------ */
sewardje663cb92002-04-12 10:26:32 +00001090
sewardj08a4c3f2002-04-13 03:45:44 +00001091/*--------------------------------------------------*/
1092
1093#include "vg_kerneliface.h"
1094
1095static
1096__inline__
1097int is_kerror ( int res )
1098{
1099 if (res >= -4095 && res <= -1)
1100 return 1;
1101 else
1102 return 0;
1103}
1104
1105
1106static
1107int my_do_syscall1 ( int syscallno, int arg1 )
1108{
1109 int __res;
1110 __asm__ volatile ("pushl %%ebx; movl %%edx,%%ebx ; int $0x80 ; popl %%ebx"
1111 : "=a" (__res)
1112 : "0" (syscallno),
1113 "d" (arg1) );
1114 return __res;
1115}
1116
1117static
1118int my_do_syscall2 ( int syscallno,
sewardjf854f472002-04-21 12:19:41 +00001119 int arg1, int arg2 )
sewardj08a4c3f2002-04-13 03:45:44 +00001120{
1121 int __res;
1122 __asm__ volatile ("pushl %%ebx; movl %%edx,%%ebx ; int $0x80 ; popl %%ebx"
1123 : "=a" (__res)
1124 : "0" (syscallno),
1125 "d" (arg1),
1126 "c" (arg2) );
1127 return __res;
1128}
1129
1130static
sewardjf854f472002-04-21 12:19:41 +00001131int my_do_syscall3 ( int syscallno,
1132 int arg1, int arg2, int arg3 )
1133{
1134 int __res;
1135 __asm__ volatile ("pushl %%ebx; movl %%esi,%%ebx ; int $0x80 ; popl %%ebx"
1136 : "=a" (__res)
1137 : "0" (syscallno),
1138 "S" (arg1),
1139 "c" (arg2),
1140 "d" (arg3) );
1141 return __res;
1142}
1143
1144static
sewardj08a4c3f2002-04-13 03:45:44 +00001145int do_syscall_select( int n,
1146 vki_fd_set* readfds,
1147 vki_fd_set* writefds,
1148 vki_fd_set* exceptfds,
1149 struct vki_timeval * timeout )
1150{
1151 int res;
1152 int args[5];
1153 args[0] = n;
1154 args[1] = (int)readfds;
1155 args[2] = (int)writefds;
1156 args[3] = (int)exceptfds;
1157 args[4] = (int)timeout;
1158 res = my_do_syscall1(__NR_select, (int)(&(args[0])) );
sewardj02535bc2002-04-21 01:08:26 +00001159 return res;
sewardj08a4c3f2002-04-13 03:45:44 +00001160}
1161
1162
1163/* This is a wrapper round select(), which makes it thread-safe,
1164 meaning that only this thread will block, rather than the entire
1165 process. This wrapper in turn depends on nanosleep() not to block
1166 the entire process, but I think (hope? suspect?) that POSIX
1167 pthreads guarantees that to be the case.
1168
1169 Basic idea is: modify the timeout parameter to select so that it
1170 returns immediately. Poll like this until select returns non-zero,
1171 indicating something interesting happened, or until our time is up.
1172 Space out the polls with nanosleeps of say 20 milliseconds, which
1173 is required to be nonblocking; this allows other threads to run.
sewardj02535bc2002-04-21 01:08:26 +00001174
1175 Assumes:
1176 * (checked via assert) types fd_set and vki_fd_set are identical.
1177 * (checked via assert) types timeval and vki_timeval are identical.
1178 * (unchecked) libc error numbers (EINTR etc) are the negation of the
1179 kernel's error numbers (VKI_EINTR etc).
sewardj08a4c3f2002-04-13 03:45:44 +00001180*/
sewardj08a4c3f2002-04-13 03:45:44 +00001181
sewardj5905fae2002-04-26 13:25:00 +00001182/* __attribute__((weak)) */
sewardj08a4c3f2002-04-13 03:45:44 +00001183int select ( int n,
1184 fd_set *rfds,
1185 fd_set *wfds,
1186 fd_set *xfds,
1187 struct timeval *timeout )
1188{
sewardj5f07b662002-04-23 16:52:51 +00001189 unsigned int ms_now, ms_end;
sewardj08a4c3f2002-04-13 03:45:44 +00001190 int res;
1191 fd_set rfds_copy;
1192 fd_set wfds_copy;
1193 fd_set xfds_copy;
1194 struct vki_timeval t_now;
sewardj08a4c3f2002-04-13 03:45:44 +00001195 struct vki_timeval zero_timeout;
1196 struct vki_timespec nanosleep_interval;
1197
sewardj5f07b662002-04-23 16:52:51 +00001198 /* gcc's complains about ms_end being used uninitialised -- classic
1199 case it can't understand, where ms_end is both defined and used
1200 only if timeout != NULL. Hence ... */
1201 ms_end = 0;
sewardj08a4c3f2002-04-13 03:45:44 +00001202
1203 /* We assume that the kernel and libc data layouts are identical
1204 for the following types. These asserts provide a crude
1205 check. */
1206 if (sizeof(fd_set) != sizeof(vki_fd_set)
1207 || sizeof(struct timeval) != sizeof(struct vki_timeval))
1208 barf("valgrind's hacky non-blocking select(): data sizes error");
1209
sewardj5f07b662002-04-23 16:52:51 +00001210 /* Detect the current time and simultaneously find out if we are
1211 running on Valgrind. */
1212 VALGRIND_MAGIC_SEQUENCE(ms_now, 0xFFFFFFFF /* default */,
1213 VG_USERREQ__READ_MILLISECOND_TIMER,
1214 0, 0, 0, 0);
1215
1216 /* If a zero timeout specified, this call is harmless. Also go
1217 this route if we're not running on Valgrind, for whatever
1218 reason. */
1219 if ( (timeout && timeout->tv_sec == 0 && timeout->tv_usec == 0)
1220 || (ms_now == 0xFFFFFFFF) ) {
sewardj02535bc2002-04-21 01:08:26 +00001221 res = do_syscall_select( n, (vki_fd_set*)rfds,
sewardj08a4c3f2002-04-13 03:45:44 +00001222 (vki_fd_set*)wfds,
1223 (vki_fd_set*)xfds,
1224 (struct vki_timeval*)timeout);
sewardj02535bc2002-04-21 01:08:26 +00001225 if (is_kerror(res)) {
1226 * (__errno_location()) = -res;
1227 return -1;
1228 } else {
1229 return res;
1230 }
1231 }
sewardj08a4c3f2002-04-13 03:45:44 +00001232
sewardj5f07b662002-04-23 16:52:51 +00001233 /* If a timeout was specified, set ms_end to be the end millisecond
1234 counter [wallclock] time. */
sewardj08a4c3f2002-04-13 03:45:44 +00001235 if (timeout) {
1236 res = my_do_syscall2(__NR_gettimeofday, (int)&t_now, (int)NULL);
1237 assert(res == 0);
sewardj5f07b662002-04-23 16:52:51 +00001238 ms_end = ms_now;
1239 ms_end += (timeout->tv_usec / 1000);
1240 ms_end += (timeout->tv_sec * 1000);
sewardj08a4c3f2002-04-13 03:45:44 +00001241 /* Stay sane ... */
sewardj5f07b662002-04-23 16:52:51 +00001242 assert (ms_end >= ms_now);
sewardj08a4c3f2002-04-13 03:45:44 +00001243 }
1244
1245 /* fprintf(stderr, "MY_SELECT: before loop\n"); */
1246
1247 /* Either timeout == NULL, meaning wait indefinitely, or timeout !=
sewardj5f07b662002-04-23 16:52:51 +00001248 NULL, in which case ms_end holds the end time. */
sewardj08a4c3f2002-04-13 03:45:44 +00001249 while (1) {
1250 if (timeout) {
sewardj5f07b662002-04-23 16:52:51 +00001251 VALGRIND_MAGIC_SEQUENCE(ms_now, 0xFFFFFFFF /* default */,
1252 VG_USERREQ__READ_MILLISECOND_TIMER,
1253 0, 0, 0, 0);
1254 assert(ms_now != 0xFFFFFFFF);
1255 if (ms_now >= ms_end) {
sewardj08a4c3f2002-04-13 03:45:44 +00001256 /* timeout; nothing interesting happened. */
1257 if (rfds) FD_ZERO(rfds);
1258 if (wfds) FD_ZERO(wfds);
1259 if (xfds) FD_ZERO(xfds);
1260 return 0;
1261 }
1262 }
1263
1264 /* These could be trashed each time round the loop, so restore
1265 them each time. */
1266 if (rfds) rfds_copy = *rfds;
1267 if (wfds) wfds_copy = *wfds;
1268 if (xfds) xfds_copy = *xfds;
1269
1270 zero_timeout.tv_sec = zero_timeout.tv_usec = 0;
1271
1272 res = do_syscall_select( n,
1273 rfds ? (vki_fd_set*)(&rfds_copy) : NULL,
1274 wfds ? (vki_fd_set*)(&wfds_copy) : NULL,
1275 xfds ? (vki_fd_set*)(&xfds_copy) : NULL,
1276 & zero_timeout );
sewardj02535bc2002-04-21 01:08:26 +00001277 if (is_kerror(res)) {
1278 /* Some kind of error (including EINTR). Set errno and
sewardj08a4c3f2002-04-13 03:45:44 +00001279 return. The sets are unspecified in this case. */
sewardj02535bc2002-04-21 01:08:26 +00001280 * (__errno_location()) = -res;
1281 return -1;
sewardj08a4c3f2002-04-13 03:45:44 +00001282 }
1283 if (res > 0) {
1284 /* one or more fds is ready. Copy out resulting sets and
1285 return. */
1286 if (rfds) *rfds = rfds_copy;
1287 if (wfds) *wfds = wfds_copy;
1288 if (xfds) *xfds = xfds_copy;
1289 return res;
1290 }
1291 /* fprintf(stderr, "MY_SELECT: nanosleep\n"); */
1292 /* nanosleep and go round again */
sewardj02535bc2002-04-21 01:08:26 +00001293 nanosleep_interval.tv_sec = 0;
sewardj956cc1b2002-04-25 01:33:50 +00001294 nanosleep_interval.tv_nsec = 50 * 1000 * 1000; /* 50 milliseconds */
sewardjf854f472002-04-21 12:19:41 +00001295 /* It's critical here that valgrind's nanosleep implementation
1296 is nonblocking. */
1297 (void)my_do_syscall2(__NR_nanosleep,
1298 (int)(&nanosleep_interval), (int)NULL);
1299 }
1300}
1301
1302
1303
1304
1305#include <sys/poll.h>
1306
sewardj72d58482002-04-24 02:20:20 +00001307#ifdef GLIBC_2_1
1308typedef unsigned long int nfds_t;
1309#endif
1310
sewardj5905fae2002-04-26 13:25:00 +00001311/* __attribute__((weak)) */
sewardjf854f472002-04-21 12:19:41 +00001312int poll (struct pollfd *__fds, nfds_t __nfds, int __timeout)
1313{
sewardj5f07b662002-04-23 16:52:51 +00001314 unsigned int ms_now, ms_end;
sewardjf854f472002-04-21 12:19:41 +00001315 int res, i;
sewardjf854f472002-04-21 12:19:41 +00001316 struct vki_timespec nanosleep_interval;
1317
1318 ensure_valgrind("poll");
1319
sewardj5f07b662002-04-23 16:52:51 +00001320 /* Detect the current time and simultaneously find out if we are
1321 running on Valgrind. */
1322 VALGRIND_MAGIC_SEQUENCE(ms_now, 0xFFFFFFFF /* default */,
1323 VG_USERREQ__READ_MILLISECOND_TIMER,
1324 0, 0, 0, 0);
1325
sewardjf854f472002-04-21 12:19:41 +00001326 if (/* CHECK SIZES FOR struct pollfd */
1327 sizeof(struct timeval) != sizeof(struct vki_timeval))
1328 barf("valgrind's hacky non-blocking poll(): data sizes error");
1329
sewardj5f07b662002-04-23 16:52:51 +00001330 /* dummy initialisation to keep gcc -Wall happy */
1331 ms_end = 0;
1332
1333 /* If a zero timeout specified, this call is harmless. Also do
1334 this if not running on Valgrind. */
1335 if (__timeout == 0 || ms_now == 0xFFFFFFFF) {
sewardjf854f472002-04-21 12:19:41 +00001336 res = my_do_syscall3(__NR_poll, (int)__fds, __nfds, __timeout);
1337 if (is_kerror(res)) {
1338 * (__errno_location()) = -res;
1339 return -1;
1340 } else {
1341 return res;
1342 }
1343 }
1344
sewardj5f07b662002-04-23 16:52:51 +00001345 /* If a timeout was specified, set ms_end to be the end wallclock
1346 time. Easy considering that __timeout is in milliseconds. */
sewardjf854f472002-04-21 12:19:41 +00001347 if (__timeout > 0) {
sewardj650ac002002-04-29 12:20:34 +00001348 ms_end = ms_now + (unsigned int)__timeout;
sewardjf854f472002-04-21 12:19:41 +00001349 }
1350
1351 /* fprintf(stderr, "MY_POLL: before loop\n"); */
1352
1353 /* Either timeout < 0, meaning wait indefinitely, or timeout > 0,
1354 in which case t_end holds the end time. */
sewardj5f07b662002-04-23 16:52:51 +00001355 assert(__timeout != 0);
1356
sewardjf854f472002-04-21 12:19:41 +00001357 while (1) {
sewardjf854f472002-04-21 12:19:41 +00001358 if (__timeout > 0) {
sewardj5f07b662002-04-23 16:52:51 +00001359 VALGRIND_MAGIC_SEQUENCE(ms_now, 0xFFFFFFFF /* default */,
1360 VG_USERREQ__READ_MILLISECOND_TIMER,
1361 0, 0, 0, 0);
1362 assert(ms_now != 0xFFFFFFFF);
1363 if (ms_now >= ms_end) {
sewardjf854f472002-04-21 12:19:41 +00001364 /* timeout; nothing interesting happened. */
1365 for (i = 0; i < __nfds; i++)
1366 __fds[i].revents = 0;
1367 return 0;
1368 }
1369 }
1370
sewardj5f07b662002-04-23 16:52:51 +00001371 /* Do a return-immediately poll. */
sewardjf854f472002-04-21 12:19:41 +00001372 res = my_do_syscall3(__NR_poll, (int)__fds, __nfds, 0 );
1373 if (is_kerror(res)) {
1374 /* Some kind of error. Set errno and return. */
1375 * (__errno_location()) = -res;
1376 return -1;
1377 }
1378 if (res > 0) {
1379 /* One or more fds is ready. Return now. */
1380 return res;
1381 }
1382 /* fprintf(stderr, "MY_POLL: nanosleep\n"); */
1383 /* nanosleep and go round again */
1384 nanosleep_interval.tv_sec = 0;
sewardj956cc1b2002-04-25 01:33:50 +00001385 nanosleep_interval.tv_nsec = 51 * 1000 * 1000; /* 51 milliseconds */
sewardj08a4c3f2002-04-13 03:45:44 +00001386 /* It's critical here that valgrind's nanosleep implementation
1387 is nonblocking. */
1388 (void)my_do_syscall2(__NR_nanosleep,
1389 (int)(&nanosleep_interval), (int)NULL);
1390 }
1391}
sewardj3b13f0e2002-04-25 20:17:29 +00001392
1393
1394/* ---------------------------------------------------------------------
1395 B'stard.
1396 ------------------------------------------------------------------ */
1397
1398# define strong_alias(name, aliasname) \
1399 extern __typeof (name) aliasname __attribute__ ((alias (#name)));
1400
sewardj5905fae2002-04-26 13:25:00 +00001401# define weak_alias(name, aliasname) \
1402 extern __typeof (name) aliasname __attribute__ ((weak, alias (#name)));
sewardj3b13f0e2002-04-25 20:17:29 +00001403
sewardj5905fae2002-04-26 13:25:00 +00001404strong_alias(__pthread_mutex_lock, pthread_mutex_lock)
1405strong_alias(__pthread_mutex_trylock, pthread_mutex_trylock)
1406strong_alias(__pthread_mutex_unlock, pthread_mutex_unlock)
1407strong_alias(__pthread_mutexattr_init, pthread_mutexattr_init)
1408 weak_alias(__pthread_mutexattr_settype, pthread_mutexattr_settype)
1409strong_alias(__pthread_mutex_init, pthread_mutex_init)
1410strong_alias(__pthread_mutexattr_destroy, pthread_mutexattr_destroy)
1411strong_alias(__pthread_mutex_destroy, pthread_mutex_destroy)
1412strong_alias(__pthread_once, pthread_once)
1413strong_alias(__pthread_atfork, pthread_atfork)
1414strong_alias(__pthread_key_create, pthread_key_create)
1415strong_alias(__pthread_getspecific, pthread_getspecific)
1416strong_alias(__pthread_setspecific, pthread_setspecific)
1417
1418//strong_alias(__sigaction, sigaction)
sewardj3b13f0e2002-04-25 20:17:29 +00001419strong_alias(sigaction, __sigaction)
1420
sewardj5905fae2002-04-26 13:25:00 +00001421strong_alias(close, __close)
sewardj3b13f0e2002-04-25 20:17:29 +00001422strong_alias(fcntl, __fcntl)
sewardj5905fae2002-04-26 13:25:00 +00001423strong_alias(lseek, __lseek)
1424strong_alias(open, __open)
1425strong_alias(open64, __open64)
1426//strong_alias(pread64, __pread64)
1427//strong_alias(pwrite64, __pwrite64)
1428strong_alias(read, __read)
1429strong_alias(wait, __wait)
1430strong_alias(write, __write)
sewardj3b13f0e2002-04-25 20:17:29 +00001431strong_alias(connect, __connect)
sewardj5905fae2002-04-26 13:25:00 +00001432strong_alias(send, __send)
1433
1434weak_alias(__fork, fork)
1435//weak_alias(__vfork, vfork)
1436
sewardj3b13f0e2002-04-25 20:17:29 +00001437
1438/*--------------------------------------------------*/
1439
sewardj5716dbb2002-04-26 03:28:18 +00001440int
1441pthread_rwlock_rdlock (void* /* pthread_rwlock_t* */ rwlock)
1442{
sewardj436e0582002-04-26 14:31:40 +00001443 static int moans = N_MOANS;
1444 if (moans-- > 0)
1445 kludged("pthread_rwlock_rdlock");
sewardj5716dbb2002-04-26 03:28:18 +00001446 return 0;
1447}
1448
sewardj5905fae2002-04-26 13:25:00 +00001449weak_alias(pthread_rwlock_rdlock, __pthread_rwlock_rdlock)
sewardj5716dbb2002-04-26 03:28:18 +00001450
1451
1452int
1453pthread_rwlock_unlock (void* /* pthread_rwlock_t* */ rwlock)
1454{
sewardj436e0582002-04-26 14:31:40 +00001455 static int moans = N_MOANS;
1456 if (moans-- > 0)
1457 kludged("pthread_rwlock_unlock");
sewardj5716dbb2002-04-26 03:28:18 +00001458 return 0;
1459}
1460
sewardj5905fae2002-04-26 13:25:00 +00001461weak_alias(pthread_rwlock_unlock, __pthread_rwlock_unlock)
sewardj5716dbb2002-04-26 03:28:18 +00001462
1463
sewardj060b04f2002-04-26 21:01:13 +00001464int
1465pthread_rwlock_wrlock (void* /* pthread_rwlock_t* */ rwlock)
1466{
1467 static int moans = N_MOANS;
1468 if (moans-- > 0)
1469 kludged("pthread_rwlock_wrlock");
1470 return 0;
1471}
1472
sewardj262b0292002-05-01 00:03:16 +00001473weak_alias(pthread_rwlock_wrlock, __pthread_rwlock_wrlock)
sewardj060b04f2002-04-26 21:01:13 +00001474
1475
sewardj3b13f0e2002-04-25 20:17:29 +00001476/* I've no idea what these are, but they get called quite a lot.
1477 Anybody know? */
1478
1479#undef _IO_flockfile
1480void _IO_flockfile ( _IO_FILE * file )
1481{
sewardj853f55d2002-04-26 00:27:53 +00001482 pthread_mutex_lock(file->_lock);
sewardj3b13f0e2002-04-25 20:17:29 +00001483}
sewardj5905fae2002-04-26 13:25:00 +00001484weak_alias(_IO_flockfile, flockfile);
1485
sewardj3b13f0e2002-04-25 20:17:29 +00001486
1487#undef _IO_funlockfile
1488void _IO_funlockfile ( _IO_FILE * file )
1489{
sewardj853f55d2002-04-26 00:27:53 +00001490 pthread_mutex_unlock(file->_lock);
sewardj3b13f0e2002-04-25 20:17:29 +00001491}
sewardj5905fae2002-04-26 13:25:00 +00001492weak_alias(_IO_funlockfile, funlockfile);
1493
sewardj3b13f0e2002-04-25 20:17:29 +00001494
1495void _pthread_cleanup_push_defer ( void )
1496{
sewardj439d45e2002-05-03 20:43:10 +00001497 static int moans = N_MOANS;
1498 if (moans-- > 0)
1499 ignored("_pthread_cleanup_push_defer");
sewardj3b13f0e2002-04-25 20:17:29 +00001500}
1501
1502void _pthread_cleanup_pop_restore ( void )
1503{
sewardj439d45e2002-05-03 20:43:10 +00001504 static int moans = N_MOANS;
1505 if (moans-- > 0)
1506 ignored("_pthread_cleanup_pop_restore");
sewardj3b13f0e2002-04-25 20:17:29 +00001507}
sewardjd4f2c712002-04-30 10:20:10 +00001508
1509
1510/* This doesn't seem to be needed to simulate libpthread.so's external
1511 interface, but many people complain about its absence. */
1512
1513strong_alias(__pthread_mutexattr_settype, __pthread_mutexattr_setkind_np)
1514weak_alias(__pthread_mutexattr_setkind_np, pthread_mutexattr_setkind_np)
sewardj439d45e2002-05-03 20:43:10 +00001515
1516
1517/*--------------------------------------------------------------------*/
1518/*--- end vg_libpthread.c ---*/
1519/*--------------------------------------------------------------------*/