blob: a7dfb70259cf6e3c9e04e1d456f288bb04d3aad1 [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
sewardj68b2dd92002-05-10 21:03:56 +000098/* We need this guy -- it's in valgrind.so. */
99extern void VG_(startup) ( void );
100
101
102/* Just start up Valgrind if it's not already going. VG_(startup)()
103 detects and ignores second and subsequent calls. */
sewardj604ec3c2002-04-18 22:38:41 +0000104static __inline__
sewardje663cb92002-04-12 10:26:32 +0000105void ensure_valgrind ( char* caller )
106{
sewardj68b2dd92002-05-10 21:03:56 +0000107 VG_(startup)();
sewardje663cb92002-04-12 10:26:32 +0000108}
109
sewardjbea1caa2002-05-10 23:20:58 +0000110/* While we're at it ... hook our own startup function into this
111 game. */
112__asm__ (
113 ".section .init\n"
114 "\tcall vgPlain_startup"
115);
116
sewardje663cb92002-04-12 10:26:32 +0000117
118static
sewardj3b5d8862002-04-20 13:53:23 +0000119__attribute__((noreturn))
sewardje663cb92002-04-12 10:26:32 +0000120void barf ( char* str )
121{
122 char buf[100];
123 buf[0] = 0;
sewardj439d45e2002-05-03 20:43:10 +0000124 strcat(buf, "\nvalgrind's libpthread.so: ");
sewardje663cb92002-04-12 10:26:32 +0000125 strcat(buf, str);
126 strcat(buf, "\n\n");
127 write(2, buf, strlen(buf));
128 myexit(1);
sewardj3b5d8862002-04-20 13:53:23 +0000129 /* We have to persuade gcc into believing this doesn't return. */
130 while (1) { };
sewardje663cb92002-04-12 10:26:32 +0000131}
132
133
sewardj2a3d28c2002-04-14 13:27:00 +0000134static void ignored ( char* msg )
135{
sewardj436e0582002-04-26 14:31:40 +0000136 if (get_pt_trace_level() >= 0) {
sewardj439d45e2002-05-03 20:43:10 +0000137 char* ig = "valgrind's libpthread.so: IGNORED call to: ";
sewardj45b4b372002-04-16 22:50:32 +0000138 write(2, ig, strlen(ig));
139 write(2, msg, strlen(msg));
140 ig = "\n";
141 write(2, ig, strlen(ig));
142 }
sewardj2a3d28c2002-04-14 13:27:00 +0000143}
144
sewardj30671ff2002-04-21 00:13:57 +0000145static void kludged ( char* msg )
146{
sewardj436e0582002-04-26 14:31:40 +0000147 if (get_pt_trace_level() >= 0) {
sewardj439d45e2002-05-03 20:43:10 +0000148 char* ig = "valgrind's libpthread.so: KLUDGED call to: ";
149 write(2, ig, strlen(ig));
150 write(2, msg, strlen(msg));
151 ig = "\n";
152 write(2, ig, strlen(ig));
153 }
154}
155
156static void not_inside ( char* msg )
157{
sewardj68b2dd92002-05-10 21:03:56 +0000158 VG_(startup)();
159 return;
sewardj439d45e2002-05-03 20:43:10 +0000160 if (get_pt_trace_level() >= 0) {
161 char* ig = "valgrind's libpthread.so: NOT INSIDE VALGRIND "
162 "during call to: ";
sewardj30671ff2002-04-21 00:13:57 +0000163 write(2, ig, strlen(ig));
164 write(2, msg, strlen(msg));
165 ig = "\n";
166 write(2, ig, strlen(ig));
167 }
168}
169
sewardj3b13f0e2002-04-25 20:17:29 +0000170void vgPlain_unimp ( char* what )
171{
sewardj439d45e2002-05-03 20:43:10 +0000172 char* ig = "valgrind's libpthread.so: UNIMPLEMENTED FUNCTION: ";
sewardj3b13f0e2002-04-25 20:17:29 +0000173 write(2, ig, strlen(ig));
174 write(2, what, strlen(what));
175 ig = "\n";
176 write(2, ig, strlen(ig));
177 barf("Please report this bug to me at: jseward@acm.org");
178}
179
sewardje663cb92002-04-12 10:26:32 +0000180
181/* ---------------------------------------------------------------------
182 Pass pthread_ calls to Valgrind's request mechanism.
183 ------------------------------------------------------------------ */
184
sewardjf8f819e2002-04-17 23:21:37 +0000185#include <pthread.h>
186#include <stdio.h>
187#include <errno.h>
sewardj5f07b662002-04-23 16:52:51 +0000188#include <assert.h>
189#include <sys/time.h> /* gettimeofday */
sewardjf8f819e2002-04-17 23:21:37 +0000190
191/* ---------------------------------------------------
192 THREAD ATTRIBUTES
193 ------------------------------------------------ */
194
sewardj6af4b5d2002-04-16 04:40:49 +0000195int pthread_attr_init(pthread_attr_t *attr)
196{
sewardj436e0582002-04-26 14:31:40 +0000197 static int moans = N_MOANS;
198 if (moans-- > 0)
199 ignored("pthread_attr_init");
sewardj6af4b5d2002-04-16 04:40:49 +0000200 return 0;
201}
202
203int pthread_attr_setdetachstate(pthread_attr_t *attr, int detachstate)
204{
sewardj436e0582002-04-26 14:31:40 +0000205 static int moans = N_MOANS;
206 if (moans-- > 0)
207 ignored("pthread_attr_setdetachstate");
sewardj6af4b5d2002-04-16 04:40:49 +0000208 return 0;
209}
210
sewardj30671ff2002-04-21 00:13:57 +0000211int pthread_attr_setinheritsched(pthread_attr_t *attr, int inherit)
212{
sewardj436e0582002-04-26 14:31:40 +0000213 static int moans = N_MOANS;
214 if (moans-- > 0)
215 ignored("pthread_attr_setinheritsched");
sewardj30671ff2002-04-21 00:13:57 +0000216 return 0;
217}
sewardj6af4b5d2002-04-16 04:40:49 +0000218
sewardj30671ff2002-04-21 00:13:57 +0000219/* This is completely bogus. */
220int pthread_attr_getschedparam(const pthread_attr_t *attr,
221 struct sched_param *param)
222{
sewardj436e0582002-04-26 14:31:40 +0000223 static int moans = N_MOANS;
224 if (moans-- > 0)
225 kludged("pthread_attr_getschedparam");
sewardj72d58482002-04-24 02:20:20 +0000226# ifdef GLIBC_2_1
227 if (param) param->sched_priority = 0; /* who knows */
228# else
sewardj30671ff2002-04-21 00:13:57 +0000229 if (param) param->__sched_priority = 0; /* who knows */
sewardj72d58482002-04-24 02:20:20 +0000230# endif
sewardj30671ff2002-04-21 00:13:57 +0000231 return 0;
232}
233
234int pthread_attr_setschedparam(pthread_attr_t *attr,
235 const struct sched_param *param)
236{
sewardj436e0582002-04-26 14:31:40 +0000237 static int moans = N_MOANS;
238 if (moans-- > 0)
239 ignored("pthread_attr_setschedparam");
sewardj30671ff2002-04-21 00:13:57 +0000240 return 0;
241}
242
243int pthread_attr_destroy(pthread_attr_t *attr)
244{
sewardj436e0582002-04-26 14:31:40 +0000245 static int moans = N_MOANS;
246 if (moans-- > 0)
247 ignored("pthread_attr_destroy");
sewardj30671ff2002-04-21 00:13:57 +0000248 return 0;
249}
sewardjf8f819e2002-04-17 23:21:37 +0000250
251/* ---------------------------------------------------
252 THREADs
253 ------------------------------------------------ */
254
sewardj6072c362002-04-19 14:40:57 +0000255int pthread_equal(pthread_t thread1, pthread_t thread2)
256{
257 return thread1 == thread2 ? 1 : 0;
258}
259
260
sewardje663cb92002-04-12 10:26:32 +0000261int
262pthread_create (pthread_t *__restrict __thread,
263 __const pthread_attr_t *__restrict __attr,
264 void *(*__start_routine) (void *),
265 void *__restrict __arg)
266{
267 int res;
268 ensure_valgrind("pthread_create");
269 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
270 VG_USERREQ__PTHREAD_CREATE,
271 __thread, __attr, __start_routine, __arg);
272 return res;
273}
274
275
276
277int
278pthread_join (pthread_t __th, void **__thread_return)
279{
280 int res;
281 ensure_valgrind("pthread_join");
282 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
283 VG_USERREQ__PTHREAD_JOIN,
284 __th, __thread_return, 0, 0);
285 return res;
286}
287
288
sewardj3b5d8862002-04-20 13:53:23 +0000289void pthread_exit(void *retval)
290{
291 int res;
292 ensure_valgrind("pthread_exit");
293 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
294 VG_USERREQ__PTHREAD_EXIT,
295 retval, 0, 0, 0);
296 /* Doesn't return! */
297 /* However, we have to fool gcc into knowing that. */
298 barf("pthread_exit: still alive after request?!");
299}
300
sewardje663cb92002-04-12 10:26:32 +0000301
sewardj3b13f0e2002-04-25 20:17:29 +0000302pthread_t pthread_self(void)
sewardje663cb92002-04-12 10:26:32 +0000303{
304 int tid;
sewardj3b13f0e2002-04-25 20:17:29 +0000305 ensure_valgrind("pthread_self");
sewardj439d45e2002-05-03 20:43:10 +0000306 VALGRIND_MAGIC_SEQUENCE(tid, 1 /* default */,
sewardje663cb92002-04-12 10:26:32 +0000307 VG_USERREQ__PTHREAD_GET_THREADID,
308 0, 0, 0, 0);
sewardj439d45e2002-05-03 20:43:10 +0000309 if (tid < 1 || tid >= VG_N_THREADS)
sewardj3b13f0e2002-04-25 20:17:29 +0000310 barf("pthread_self: invalid ThreadId");
311 return tid;
sewardje663cb92002-04-12 10:26:32 +0000312}
313
314
sewardj853f55d2002-04-26 00:27:53 +0000315int pthread_detach(pthread_t th)
316{
sewardj436e0582002-04-26 14:31:40 +0000317 static int moans = N_MOANS;
318 if (moans-- > 0)
319 ignored("pthread_detach");
sewardj853f55d2002-04-26 00:27:53 +0000320 return 0;
321}
322
323
sewardjf8f819e2002-04-17 23:21:37 +0000324/* ---------------------------------------------------
325 MUTEX ATTRIBUTES
326 ------------------------------------------------ */
327
sewardj5905fae2002-04-26 13:25:00 +0000328int __pthread_mutexattr_init(pthread_mutexattr_t *attr)
sewardje663cb92002-04-12 10:26:32 +0000329{
sewardjf8f819e2002-04-17 23:21:37 +0000330 attr->__mutexkind = PTHREAD_MUTEX_ERRORCHECK_NP;
sewardj8937c812002-04-12 20:12:20 +0000331 return 0;
sewardje663cb92002-04-12 10:26:32 +0000332}
333
sewardj5905fae2002-04-26 13:25:00 +0000334int __pthread_mutexattr_settype(pthread_mutexattr_t *attr, int type)
sewardjf8f819e2002-04-17 23:21:37 +0000335{
336 switch (type) {
sewardj3b13f0e2002-04-25 20:17:29 +0000337# ifndef GLIBC_2_1
sewardjf8f819e2002-04-17 23:21:37 +0000338 case PTHREAD_MUTEX_TIMED_NP:
sewardj2a1dcce2002-04-22 12:45:25 +0000339 case PTHREAD_MUTEX_ADAPTIVE_NP:
sewardj3b13f0e2002-04-25 20:17:29 +0000340# endif
sewardja1679dd2002-05-10 22:31:40 +0000341# ifdef GLIBC_2_1
sewardj68b2dd92002-05-10 21:03:56 +0000342 case PTHREAD_MUTEX_FAST_NP:
sewardja1679dd2002-05-10 22:31:40 +0000343# endif
sewardjf8f819e2002-04-17 23:21:37 +0000344 case PTHREAD_MUTEX_RECURSIVE_NP:
345 case PTHREAD_MUTEX_ERRORCHECK_NP:
sewardjf8f819e2002-04-17 23:21:37 +0000346 attr->__mutexkind = type;
347 return 0;
348 default:
349 return EINVAL;
350 }
351}
352
sewardj5905fae2002-04-26 13:25:00 +0000353int __pthread_mutexattr_destroy(pthread_mutexattr_t *attr)
sewardjf8f819e2002-04-17 23:21:37 +0000354{
355 return 0;
356}
357
358
359/* ---------------------------------------------------
360 MUTEXes
361 ------------------------------------------------ */
362
sewardj5905fae2002-04-26 13:25:00 +0000363int __pthread_mutex_init(pthread_mutex_t *mutex,
364 const pthread_mutexattr_t *mutexattr)
sewardje663cb92002-04-12 10:26:32 +0000365{
sewardj604ec3c2002-04-18 22:38:41 +0000366 mutex->__m_count = 0;
367 mutex->__m_owner = (_pthread_descr)VG_INVALID_THREADID;
368 mutex->__m_kind = PTHREAD_MUTEX_ERRORCHECK_NP;
369 if (mutexattr)
370 mutex->__m_kind = mutexattr->__mutexkind;
371 return 0;
sewardje663cb92002-04-12 10:26:32 +0000372}
373
sewardj439d45e2002-05-03 20:43:10 +0000374
sewardj5905fae2002-04-26 13:25:00 +0000375int __pthread_mutex_lock(pthread_mutex_t *mutex)
sewardje663cb92002-04-12 10:26:32 +0000376{
377 int res;
sewardj436e0582002-04-26 14:31:40 +0000378 static int moans = N_MOANS;
sewardj439d45e2002-05-03 20:43:10 +0000379 if (RUNNING_ON_VALGRIND) {
sewardje663cb92002-04-12 10:26:32 +0000380 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
381 VG_USERREQ__PTHREAD_MUTEX_LOCK,
382 mutex, 0, 0, 0);
383 return res;
sewardj439d45e2002-05-03 20:43:10 +0000384 } else {
385 if (moans-- > 0)
386 not_inside("pthread_mutex_lock");
387 return 0; /* success */
sewardje663cb92002-04-12 10:26:32 +0000388 }
389}
390
sewardj439d45e2002-05-03 20:43:10 +0000391
sewardj5905fae2002-04-26 13:25:00 +0000392int __pthread_mutex_trylock(pthread_mutex_t *mutex)
sewardj30671ff2002-04-21 00:13:57 +0000393{
394 int res;
sewardj436e0582002-04-26 14:31:40 +0000395 static int moans = N_MOANS;
sewardj439d45e2002-05-03 20:43:10 +0000396 if (RUNNING_ON_VALGRIND) {
sewardj30671ff2002-04-21 00:13:57 +0000397 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
398 VG_USERREQ__PTHREAD_MUTEX_TRYLOCK,
399 mutex, 0, 0, 0);
400 return res;
sewardj439d45e2002-05-03 20:43:10 +0000401 } else {
402 if (moans-- > 0)
403 not_inside("pthread_mutex_trylock");
404 return 0;
sewardj30671ff2002-04-21 00:13:57 +0000405 }
406}
407
sewardj439d45e2002-05-03 20:43:10 +0000408
sewardj5905fae2002-04-26 13:25:00 +0000409int __pthread_mutex_unlock(pthread_mutex_t *mutex)
sewardje663cb92002-04-12 10:26:32 +0000410{
411 int res;
sewardj436e0582002-04-26 14:31:40 +0000412 static int moans = N_MOANS;
sewardj439d45e2002-05-03 20:43:10 +0000413 if (RUNNING_ON_VALGRIND) {
sewardje663cb92002-04-12 10:26:32 +0000414 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
415 VG_USERREQ__PTHREAD_MUTEX_UNLOCK,
416 mutex, 0, 0, 0);
417 return res;
sewardj439d45e2002-05-03 20:43:10 +0000418 } else {
419 if (moans-- > 0)
420 not_inside("pthread_mutex_unlock");
421 return 0;
sewardje663cb92002-04-12 10:26:32 +0000422 }
423}
424
sewardj439d45e2002-05-03 20:43:10 +0000425
sewardj5905fae2002-04-26 13:25:00 +0000426int __pthread_mutex_destroy(pthread_mutex_t *mutex)
sewardje663cb92002-04-12 10:26:32 +0000427{
sewardj604ec3c2002-04-18 22:38:41 +0000428 /* Valgrind doesn't hold any resources on behalf of the mutex, so no
429 need to involve it. */
430 if (mutex->__m_count > 0)
431 return EBUSY;
sewardj6072c362002-04-19 14:40:57 +0000432 mutex->__m_count = 0;
433 mutex->__m_owner = (_pthread_descr)VG_INVALID_THREADID;
434 mutex->__m_kind = PTHREAD_MUTEX_ERRORCHECK_NP;
sewardj604ec3c2002-04-18 22:38:41 +0000435 return 0;
sewardje663cb92002-04-12 10:26:32 +0000436}
437
438
sewardjf8f819e2002-04-17 23:21:37 +0000439/* ---------------------------------------------------
sewardj6072c362002-04-19 14:40:57 +0000440 CONDITION VARIABLES
441 ------------------------------------------------ */
442
443/* LinuxThreads supports no attributes for conditions. Hence ... */
444
445int pthread_condattr_init(pthread_condattr_t *attr)
446{
447 return 0;
448}
449
sewardj0738a592002-04-20 13:59:33 +0000450int pthread_condattr_destroy(pthread_condattr_t *attr)
451{
452 return 0;
453}
sewardj6072c362002-04-19 14:40:57 +0000454
455int pthread_cond_init( pthread_cond_t *cond,
456 const pthread_condattr_t *cond_attr)
457{
458 cond->__c_waiting = (_pthread_descr)VG_INVALID_THREADID;
459 return 0;
460}
461
sewardjf854f472002-04-21 12:19:41 +0000462int pthread_cond_destroy(pthread_cond_t *cond)
463{
464 /* should check that no threads are waiting on this CV */
sewardj436e0582002-04-26 14:31:40 +0000465 static int moans = N_MOANS;
466 if (moans-- > 0)
467 kludged("pthread_cond_destroy");
sewardjf854f472002-04-21 12:19:41 +0000468 return 0;
469}
sewardj6072c362002-04-19 14:40:57 +0000470
471/* ---------------------------------------------------
472 SCHEDULING
473 ------------------------------------------------ */
474
475/* This is completely bogus. */
476int pthread_getschedparam(pthread_t target_thread,
477 int *policy,
478 struct sched_param *param)
479{
sewardj436e0582002-04-26 14:31:40 +0000480 static int moans = N_MOANS;
481 if (moans-- > 0)
482 kludged("pthread_getschedparam");
sewardj6072c362002-04-19 14:40:57 +0000483 if (policy) *policy = SCHED_OTHER;
sewardj2a1dcce2002-04-22 12:45:25 +0000484# ifdef GLIBC_2_1
485 if (param) param->sched_priority = 0; /* who knows */
486# else
sewardj6072c362002-04-19 14:40:57 +0000487 if (param) param->__sched_priority = 0; /* who knows */
sewardj2a1dcce2002-04-22 12:45:25 +0000488# endif
sewardj6072c362002-04-19 14:40:57 +0000489 return 0;
490}
491
492int pthread_setschedparam(pthread_t target_thread,
493 int policy,
494 const struct sched_param *param)
495{
sewardj436e0582002-04-26 14:31:40 +0000496 static int moans = N_MOANS;
497 if (moans-- > 0)
498 ignored("pthread_setschedparam");
sewardj6072c362002-04-19 14:40:57 +0000499 return 0;
500}
501
sewardj3b5d8862002-04-20 13:53:23 +0000502int pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex)
503{
504 int res;
505 ensure_valgrind("pthread_cond_wait");
506 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
507 VG_USERREQ__PTHREAD_COND_WAIT,
508 cond, mutex, 0, 0);
509 return res;
510}
511
sewardj5f07b662002-04-23 16:52:51 +0000512int pthread_cond_timedwait ( pthread_cond_t *cond,
513 pthread_mutex_t *mutex,
514 const struct timespec *abstime )
515{
516 int res;
517 unsigned int ms_now, ms_end;
518 struct timeval timeval_now;
519 unsigned long long int ull_ms_now_after_1970;
520 unsigned long long int ull_ms_end_after_1970;
521
522 ensure_valgrind("pthread_cond_timedwait");
523 VALGRIND_MAGIC_SEQUENCE(ms_now, 0xFFFFFFFF /* default */,
524 VG_USERREQ__READ_MILLISECOND_TIMER,
525 0, 0, 0, 0);
526 assert(ms_now != 0xFFFFFFFF);
527 res = gettimeofday(&timeval_now, NULL);
528 assert(res == 0);
529
530 ull_ms_now_after_1970
531 = 1000ULL * ((unsigned long long int)(timeval_now.tv_sec))
532 + ((unsigned long long int)(timeval_now.tv_usec / 1000000));
533 ull_ms_end_after_1970
534 = 1000ULL * ((unsigned long long int)(abstime->tv_sec))
535 + ((unsigned long long int)(abstime->tv_nsec / 1000000));
536 assert(ull_ms_end_after_1970 >= ull_ms_now_after_1970);
537 ms_end
538 = ms_now + (unsigned int)(ull_ms_end_after_1970 - ull_ms_now_after_1970);
539 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
540 VG_USERREQ__PTHREAD_COND_TIMEDWAIT,
541 cond, mutex, ms_end, 0);
542 return res;
543}
544
545
sewardj3b5d8862002-04-20 13:53:23 +0000546int pthread_cond_signal(pthread_cond_t *cond)
547{
548 int res;
549 ensure_valgrind("pthread_cond_signal");
550 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
551 VG_USERREQ__PTHREAD_COND_SIGNAL,
552 cond, 0, 0, 0);
553 return res;
554}
555
556int pthread_cond_broadcast(pthread_cond_t *cond)
557{
558 int res;
559 ensure_valgrind("pthread_cond_broadcast");
560 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
561 VG_USERREQ__PTHREAD_COND_BROADCAST,
562 cond, 0, 0, 0);
563 return res;
564}
565
sewardj6072c362002-04-19 14:40:57 +0000566
567/* ---------------------------------------------------
sewardjf8f819e2002-04-17 23:21:37 +0000568 CANCELLATION
569 ------------------------------------------------ */
570
sewardj853f55d2002-04-26 00:27:53 +0000571int pthread_setcancelstate(int state, int *oldstate)
572{
sewardj436e0582002-04-26 14:31:40 +0000573 static int moans = N_MOANS;
574 if (moans-- > 0)
575 ignored("pthread_setcancelstate");
sewardj853f55d2002-04-26 00:27:53 +0000576 return 0;
577}
578
sewardje663cb92002-04-12 10:26:32 +0000579int pthread_setcanceltype(int type, int *oldtype)
580{
sewardj436e0582002-04-26 14:31:40 +0000581 static int moans = N_MOANS;
582 if (moans-- > 0)
583 ignored("pthread_setcanceltype");
sewardje663cb92002-04-12 10:26:32 +0000584 return 0;
585}
586
sewardje663cb92002-04-12 10:26:32 +0000587int pthread_cancel(pthread_t thread)
588{
589 int res;
590 ensure_valgrind("pthread_cancel");
591 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
592 VG_USERREQ__PTHREAD_CANCEL,
593 thread, 0, 0, 0);
594 return res;
595}
596
sewardj853f55d2002-04-26 00:27:53 +0000597void pthread_testcancel(void)
598{
599}
600
601/*-------------------*/
602static pthread_mutex_t massacre_mx = PTHREAD_MUTEX_INITIALIZER;
603
604void __pthread_kill_other_threads_np ( void )
605{
606 int i, res, me;
sewardj68b2dd92002-05-10 21:03:56 +0000607 __pthread_mutex_lock(&massacre_mx);
sewardj853f55d2002-04-26 00:27:53 +0000608 me = pthread_self();
609 for (i = 1; i < VG_N_THREADS; i++) {
610 if (i == me) continue;
611 res = pthread_cancel(i);
sewardj436e0582002-04-26 14:31:40 +0000612 if (0 && res == 0)
sewardj853f55d2002-04-26 00:27:53 +0000613 printf("----------- NUKED %d\n", i);
614 }
sewardj68b2dd92002-05-10 21:03:56 +0000615 __pthread_mutex_unlock(&massacre_mx);
sewardj853f55d2002-04-26 00:27:53 +0000616}
617
sewardje663cb92002-04-12 10:26:32 +0000618
sewardjf8f819e2002-04-17 23:21:37 +0000619/* ---------------------------------------------------
sewardjb48e5002002-05-13 00:16:03 +0000620 SIGNALS
621 ------------------------------------------------ */
622
623#include <signal.h>
624
625int pthread_sigmask(int how, const sigset_t *newmask,
626 sigset_t *oldmask)
627{
628 int res;
629
630 /* A bit subtle, because the scheduler expects newmask and oldmask
631 to be vki_sigset_t* rather than sigset_t*, and the two are
632 different. Fortunately the first 64 bits of a sigset_t are
633 exactly a vki_sigset_t, so we just pass the pointers through
634 unmodified. Haaaack!
635
636 Also mash the how value so that the SIG_ constants from glibc
637 do not have to be included into vg_scheduler.c. */
638
639 ensure_valgrind("pthread_sigmask");
640
641 switch (how) {
642 case SIG_SETMASK: how = 1; break;
643 case SIG_BLOCK: how = 2; break;
644 case SIG_UNBLOCK: how = 3; break;
645 default: return EINVAL;
646 }
647
648 /* Crude check */
649 if (newmask == NULL)
650 return EFAULT;
651
652 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
653 VG_USERREQ__PTHREAD_SIGMASK,
654 how, newmask, oldmask, 0);
655
656 /* The scheduler tells us of any memory violations. */
657 return res == 0 ? 0 : EFAULT;
658}
659
660
661int sigwait ( const sigset_t* set, int* sig )
662{
663 int res;
664 ensure_valgrind("sigwait");
665 /* As with pthread_sigmask we deliberately confuse sigset_t with
666 vki_ksigset_t. */
667 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
668 VG_USERREQ__SIGWAIT,
669 set, sig, 0, 0);
670 return res;
671}
672
673
674/* ---------------------------------------------------
sewardjf8f819e2002-04-17 23:21:37 +0000675 THREAD-SPECIFICs
676 ------------------------------------------------ */
sewardj5e5fa512002-04-14 13:13:05 +0000677
sewardj5905fae2002-04-26 13:25:00 +0000678int __pthread_key_create(pthread_key_t *key,
679 void (*destr_function) (void *))
sewardj5e5fa512002-04-14 13:13:05 +0000680{
sewardj5f07b662002-04-23 16:52:51 +0000681 int res;
682 ensure_valgrind("pthread_key_create");
683 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
684 VG_USERREQ__PTHREAD_KEY_CREATE,
685 key, destr_function, 0, 0);
686 return res;
sewardj5e5fa512002-04-14 13:13:05 +0000687}
688
689int pthread_key_delete(pthread_key_t key)
690{
sewardj436e0582002-04-26 14:31:40 +0000691 static int moans = N_MOANS;
692 if (moans-- > 0)
693 ignored("pthread_key_delete");
sewardj5e5fa512002-04-14 13:13:05 +0000694 return 0;
695}
696
sewardj5905fae2002-04-26 13:25:00 +0000697int __pthread_setspecific(pthread_key_t key, const void *pointer)
sewardj5e5fa512002-04-14 13:13:05 +0000698{
sewardj5f07b662002-04-23 16:52:51 +0000699 int res;
700 ensure_valgrind("pthread_setspecific");
701 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
702 VG_USERREQ__PTHREAD_SETSPECIFIC,
703 key, pointer, 0, 0);
704 return res;
sewardj5e5fa512002-04-14 13:13:05 +0000705}
706
sewardj5905fae2002-04-26 13:25:00 +0000707void * __pthread_getspecific(pthread_key_t key)
sewardj5e5fa512002-04-14 13:13:05 +0000708{
sewardj5f07b662002-04-23 16:52:51 +0000709 int res;
710 ensure_valgrind("pthread_getspecific");
711 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
712 VG_USERREQ__PTHREAD_GETSPECIFIC,
713 key, 0 , 0, 0);
714 return (void*)res;
sewardj5e5fa512002-04-14 13:13:05 +0000715}
716
sewardjf8f819e2002-04-17 23:21:37 +0000717
718/* ---------------------------------------------------
sewardj89d3d852002-04-24 19:21:39 +0000719 ONCEry
720 ------------------------------------------------ */
721
722static pthread_mutex_t once_masterlock = PTHREAD_MUTEX_INITIALIZER;
723
724
sewardj5905fae2002-04-26 13:25:00 +0000725int __pthread_once ( pthread_once_t *once_control,
726 void (*init_routine) (void) )
sewardj89d3d852002-04-24 19:21:39 +0000727{
728 int res;
729 ensure_valgrind("pthread_once");
730
sewardj68b2dd92002-05-10 21:03:56 +0000731 res = __pthread_mutex_lock(&once_masterlock);
sewardj89d3d852002-04-24 19:21:39 +0000732
sewardj68b2dd92002-05-10 21:03:56 +0000733 if (res != 0) {
734 printf("res = %d\n",res);
sewardj89d3d852002-04-24 19:21:39 +0000735 barf("pthread_once: Looks like your program's "
736 "init routine calls back to pthread_once() ?!");
sewardj68b2dd92002-05-10 21:03:56 +0000737 }
sewardj89d3d852002-04-24 19:21:39 +0000738
739 if (*once_control == 0) {
740 *once_control = 1;
741 init_routine();
742 }
743
sewardj68b2dd92002-05-10 21:03:56 +0000744 __pthread_mutex_unlock(&once_masterlock);
sewardj89d3d852002-04-24 19:21:39 +0000745
746 return 0;
747}
748
749
750/* ---------------------------------------------------
sewardj853f55d2002-04-26 00:27:53 +0000751 MISC
752 ------------------------------------------------ */
753
sewardj5905fae2002-04-26 13:25:00 +0000754int __pthread_atfork ( void (*prepare)(void),
755 void (*parent)(void),
756 void (*child)(void) )
sewardj853f55d2002-04-26 00:27:53 +0000757{
sewardj436e0582002-04-26 14:31:40 +0000758 static int moans = N_MOANS;
759 if (moans-- > 0)
760 ignored("pthread_atfork");
sewardj853f55d2002-04-26 00:27:53 +0000761 return 0;
762}
763
764
sewardjbb990782002-05-08 02:01:14 +0000765__attribute__((weak))
766void __pthread_initialize ( void )
767{
sewardjbea1caa2002-05-10 23:20:58 +0000768 ensure_valgrind("__pthread_initialize");
sewardjbb990782002-05-08 02:01:14 +0000769}
770
771
sewardj853f55d2002-04-26 00:27:53 +0000772/* ---------------------------------------------------
sewardj3b13f0e2002-04-25 20:17:29 +0000773 LIBRARY-PRIVATE THREAD SPECIFIC STATE
sewardjf8f819e2002-04-17 23:21:37 +0000774 ------------------------------------------------ */
775
sewardj3b13f0e2002-04-25 20:17:29 +0000776#include <resolv.h>
777static int thread_specific_errno[VG_N_THREADS];
778static int thread_specific_h_errno[VG_N_THREADS];
779static struct __res_state
780 thread_specific_res_state[VG_N_THREADS];
sewardjf8f819e2002-04-17 23:21:37 +0000781
sewardj3b13f0e2002-04-25 20:17:29 +0000782int* __errno_location ( void )
sewardjf8f819e2002-04-17 23:21:37 +0000783{
784 int tid;
sewardj3b13f0e2002-04-25 20:17:29 +0000785 /* ensure_valgrind("__errno_location"); */
786 VALGRIND_MAGIC_SEQUENCE(tid, 1 /* default */,
sewardjf8f819e2002-04-17 23:21:37 +0000787 VG_USERREQ__PTHREAD_GET_THREADID,
788 0, 0, 0, 0);
sewardj3b13f0e2002-04-25 20:17:29 +0000789 /* 'cos I'm paranoid ... */
sewardj439d45e2002-05-03 20:43:10 +0000790 if (tid < 1 || tid >= VG_N_THREADS)
sewardj3b13f0e2002-04-25 20:17:29 +0000791 barf("__errno_location: invalid ThreadId");
792 return & thread_specific_errno[tid];
793}
794
795int* __h_errno_location ( void )
796{
797 int tid;
798 /* ensure_valgrind("__h_errno_location"); */
799 VALGRIND_MAGIC_SEQUENCE(tid, 1 /* default */,
800 VG_USERREQ__PTHREAD_GET_THREADID,
801 0, 0, 0, 0);
802 /* 'cos I'm paranoid ... */
sewardj439d45e2002-05-03 20:43:10 +0000803 if (tid < 1 || tid >= VG_N_THREADS)
sewardj3b13f0e2002-04-25 20:17:29 +0000804 barf("__h_errno_location: invalid ThreadId");
805 return & thread_specific_h_errno[tid];
806}
807
808struct __res_state* __res_state ( void )
809{
810 int tid;
811 /* ensure_valgrind("__res_state"); */
812 VALGRIND_MAGIC_SEQUENCE(tid, 1 /* default */,
813 VG_USERREQ__PTHREAD_GET_THREADID,
814 0, 0, 0, 0);
815 /* 'cos I'm paranoid ... */
sewardj439d45e2002-05-03 20:43:10 +0000816 if (tid < 1 || tid >= VG_N_THREADS)
sewardj3b13f0e2002-04-25 20:17:29 +0000817 barf("__res_state: invalid ThreadId");
818 return & thread_specific_res_state[tid];
sewardjf8f819e2002-04-17 23:21:37 +0000819}
820
821
sewardj5716dbb2002-04-26 03:28:18 +0000822/* ---------------------------------------------------
823 LIBC-PRIVATE SPECIFIC DATA
824 ------------------------------------------------ */
825
826/* Relies on assumption that initial private data is NULL. This
827 should be fixed somehow. */
828
829/* The allowable keys (indices) (all 2 of them).
830 From sysdeps/pthread/bits/libc-tsd.h
831*/
sewardj70adeb22002-04-27 01:35:38 +0000832#define N_LIBC_TSD_EXTRA_KEYS 1
833
sewardj5716dbb2002-04-26 03:28:18 +0000834enum __libc_tsd_key_t { _LIBC_TSD_KEY_MALLOC = 0,
835 _LIBC_TSD_KEY_DL_ERROR,
836 _LIBC_TSD_KEY_N };
837
838/* Auto-initialising subsystem. libc_specifics_inited is set
839 after initialisation. libc_specifics_inited_mx guards it. */
840static int libc_specifics_inited = 0;
841static pthread_mutex_t libc_specifics_inited_mx = PTHREAD_MUTEX_INITIALIZER;
842
843/* These are the keys we must initialise the first time. */
sewardj70adeb22002-04-27 01:35:38 +0000844static pthread_key_t libc_specifics_keys[_LIBC_TSD_KEY_N
845 + N_LIBC_TSD_EXTRA_KEYS];
sewardj5716dbb2002-04-26 03:28:18 +0000846
847/* Initialise the keys, if they are not already initialise. */
848static
849void init_libc_tsd_keys ( void )
850{
851 int res, i;
852 pthread_key_t k;
853
854 res = pthread_mutex_lock(&libc_specifics_inited_mx);
855 if (res != 0) barf("init_libc_tsd_keys: lock");
856
857 if (libc_specifics_inited == 0) {
858 /* printf("INIT libc specifics\n"); */
859 libc_specifics_inited = 1;
sewardj70adeb22002-04-27 01:35:38 +0000860 for (i = 0; i < _LIBC_TSD_KEY_N + N_LIBC_TSD_EXTRA_KEYS; i++) {
sewardj5716dbb2002-04-26 03:28:18 +0000861 res = pthread_key_create(&k, NULL);
862 if (res != 0) barf("init_libc_tsd_keys: create");
863 libc_specifics_keys[i] = k;
864 }
865 }
866
867 res = pthread_mutex_unlock(&libc_specifics_inited_mx);
868 if (res != 0) barf("init_libc_tsd_keys: unlock");
869}
870
871
872static int
873libc_internal_tsd_set ( enum __libc_tsd_key_t key,
874 const void * pointer )
875{
sewardj70adeb22002-04-27 01:35:38 +0000876 int res;
877 static int moans = N_MOANS;
sewardj5716dbb2002-04-26 03:28:18 +0000878 /* printf("SET SET SET key %d ptr %p\n", key, pointer); */
sewardj70adeb22002-04-27 01:35:38 +0000879 if (key < _LIBC_TSD_KEY_MALLOC
880 || key >= _LIBC_TSD_KEY_N + N_LIBC_TSD_EXTRA_KEYS)
sewardj5716dbb2002-04-26 03:28:18 +0000881 barf("libc_internal_tsd_set: invalid key");
sewardj70adeb22002-04-27 01:35:38 +0000882 if (key >= _LIBC_TSD_KEY_N && moans-- > 0)
883 fprintf(stderr,
sewardj439d45e2002-05-03 20:43:10 +0000884 "valgrind's libpthread.so: libc_internal_tsd_set: "
885 "dubious key %d\n", key);
sewardj5716dbb2002-04-26 03:28:18 +0000886 init_libc_tsd_keys();
887 res = pthread_setspecific(libc_specifics_keys[key], pointer);
888 if (res != 0) barf("libc_internal_tsd_set: setspecific failed");
889 return 0;
890}
891
892static void *
893libc_internal_tsd_get ( enum __libc_tsd_key_t key )
894{
sewardj70adeb22002-04-27 01:35:38 +0000895 void* v;
896 static int moans = N_MOANS;
sewardj5716dbb2002-04-26 03:28:18 +0000897 /* printf("GET GET GET key %d\n", key); */
sewardj70adeb22002-04-27 01:35:38 +0000898 if (key < _LIBC_TSD_KEY_MALLOC
899 || key >= _LIBC_TSD_KEY_N + N_LIBC_TSD_EXTRA_KEYS)
sewardj5716dbb2002-04-26 03:28:18 +0000900 barf("libc_internal_tsd_get: invalid key");
sewardj70adeb22002-04-27 01:35:38 +0000901 if (key >= _LIBC_TSD_KEY_N && moans-- > 0)
902 fprintf(stderr,
sewardj439d45e2002-05-03 20:43:10 +0000903 "valgrind's libpthread.so: libc_internal_tsd_get: "
904 "dubious key %d\n", key);
sewardj5716dbb2002-04-26 03:28:18 +0000905 init_libc_tsd_keys();
906 v = pthread_getspecific(libc_specifics_keys[key]);
907 /* if (v == NULL) barf("libc_internal_tsd_set: getspecific failed"); */
908 return v;
909}
910
911
912
913
sewardj70adeb22002-04-27 01:35:38 +0000914int (*__libc_internal_tsd_set)
915 (enum __libc_tsd_key_t key, const void * pointer)
916 = libc_internal_tsd_set;
sewardj5716dbb2002-04-26 03:28:18 +0000917
sewardj70adeb22002-04-27 01:35:38 +0000918void* (*__libc_internal_tsd_get)
919 (enum __libc_tsd_key_t key)
920 = libc_internal_tsd_get;
sewardj5716dbb2002-04-26 03:28:18 +0000921
922
sewardje663cb92002-04-12 10:26:32 +0000923/* ---------------------------------------------------------------------
924 These are here (I think) because they are deemed cancellation
925 points by POSIX. For the moment we'll simply pass the call along
926 to the corresponding thread-unaware (?) libc routine.
927 ------------------------------------------------------------------ */
928
sewardje663cb92002-04-12 10:26:32 +0000929#include <stdlib.h>
sewardje663cb92002-04-12 10:26:32 +0000930#include <sys/types.h>
931#include <sys/socket.h>
932
sewardjd529a442002-05-04 19:49:21 +0000933#ifdef GLIBC_2_1
934extern
935int __sigaction
936 (int signum,
937 const struct sigaction *act,
938 struct sigaction *oldact);
939#else
sewardje663cb92002-04-12 10:26:32 +0000940extern
941int __libc_sigaction
942 (int signum,
943 const struct sigaction *act,
944 struct sigaction *oldact);
sewardjd529a442002-05-04 19:49:21 +0000945#endif
sewardje663cb92002-04-12 10:26:32 +0000946int sigaction(int signum,
947 const struct sigaction *act,
948 struct sigaction *oldact)
949{
sewardj2a1dcce2002-04-22 12:45:25 +0000950# ifdef GLIBC_2_1
951 return __sigaction(signum, act, oldact);
952# else
sewardj45b4b372002-04-16 22:50:32 +0000953 return __libc_sigaction(signum, act, oldact);
sewardj2a1dcce2002-04-22 12:45:25 +0000954# endif
sewardje663cb92002-04-12 10:26:32 +0000955}
956
957
958extern
959int __libc_connect(int sockfd,
960 const struct sockaddr *serv_addr,
961 socklen_t addrlen);
sewardj5905fae2002-04-26 13:25:00 +0000962__attribute__((weak))
sewardje663cb92002-04-12 10:26:32 +0000963int connect(int sockfd,
964 const struct sockaddr *serv_addr,
965 socklen_t addrlen)
966{
sewardj45b4b372002-04-16 22:50:32 +0000967 return __libc_connect(sockfd, serv_addr, addrlen);
sewardje663cb92002-04-12 10:26:32 +0000968}
969
970
971extern
972int __libc_fcntl(int fd, int cmd, long arg);
sewardj5905fae2002-04-26 13:25:00 +0000973__attribute__((weak))
sewardje663cb92002-04-12 10:26:32 +0000974int fcntl(int fd, int cmd, long arg)
975{
sewardj45b4b372002-04-16 22:50:32 +0000976 return __libc_fcntl(fd, cmd, arg);
sewardje663cb92002-04-12 10:26:32 +0000977}
978
979
980extern
981ssize_t __libc_write(int fd, const void *buf, size_t count);
sewardj5905fae2002-04-26 13:25:00 +0000982__attribute__((weak))
sewardje663cb92002-04-12 10:26:32 +0000983ssize_t write(int fd, const void *buf, size_t count)
984{
sewardj45b4b372002-04-16 22:50:32 +0000985 return __libc_write(fd, buf, count);
sewardje663cb92002-04-12 10:26:32 +0000986}
987
988
989extern
990ssize_t __libc_read(int fd, void *buf, size_t count);
sewardj5905fae2002-04-26 13:25:00 +0000991__attribute__((weak))
sewardje663cb92002-04-12 10:26:32 +0000992ssize_t read(int fd, void *buf, size_t count)
993{
sewardj45b4b372002-04-16 22:50:32 +0000994 return __libc_read(fd, buf, count);
sewardje663cb92002-04-12 10:26:32 +0000995}
996
sewardjbe32e452002-04-24 20:29:58 +0000997
998extern
sewardj853f55d2002-04-26 00:27:53 +0000999int __libc_open64(const char *pathname, int flags, mode_t mode);
sewardj5905fae2002-04-26 13:25:00 +00001000__attribute__((weak))
sewardj853f55d2002-04-26 00:27:53 +00001001int open64(const char *pathname, int flags, mode_t mode)
sewardjbe32e452002-04-24 20:29:58 +00001002{
sewardj853f55d2002-04-26 00:27:53 +00001003 return __libc_open64(pathname, flags, mode);
sewardjbe32e452002-04-24 20:29:58 +00001004}
1005
sewardje663cb92002-04-12 10:26:32 +00001006
1007extern
sewardj853f55d2002-04-26 00:27:53 +00001008int __libc_open(const char *pathname, int flags, mode_t mode);
sewardj5905fae2002-04-26 13:25:00 +00001009__attribute__((weak))
sewardj853f55d2002-04-26 00:27:53 +00001010int open(const char *pathname, int flags, mode_t mode)
sewardje663cb92002-04-12 10:26:32 +00001011{
sewardj853f55d2002-04-26 00:27:53 +00001012 return __libc_open(pathname, flags, mode);
sewardje663cb92002-04-12 10:26:32 +00001013}
1014
1015
1016extern
1017int __libc_close(int fd);
sewardj5905fae2002-04-26 13:25:00 +00001018__attribute__((weak))
sewardje663cb92002-04-12 10:26:32 +00001019int close(int fd)
1020{
sewardj45b4b372002-04-16 22:50:32 +00001021 return __libc_close(fd);
sewardje663cb92002-04-12 10:26:32 +00001022}
1023
1024
1025extern
1026int __libc_accept(int s, struct sockaddr *addr, socklen_t *addrlen);
sewardj5905fae2002-04-26 13:25:00 +00001027__attribute__((weak))
sewardje663cb92002-04-12 10:26:32 +00001028int accept(int s, struct sockaddr *addr, socklen_t *addrlen)
1029{
sewardj45b4b372002-04-16 22:50:32 +00001030 return __libc_accept(s, addr, addrlen);
sewardje663cb92002-04-12 10:26:32 +00001031}
1032
1033
1034extern
1035pid_t __libc_fork(void);
sewardj5905fae2002-04-26 13:25:00 +00001036pid_t __fork(void)
sewardje663cb92002-04-12 10:26:32 +00001037{
sewardj45b4b372002-04-16 22:50:32 +00001038 return __libc_fork();
sewardje663cb92002-04-12 10:26:32 +00001039}
1040
1041
1042extern
1043pid_t __libc_waitpid(pid_t pid, int *status, int options);
sewardj5905fae2002-04-26 13:25:00 +00001044__attribute__((weak))
sewardje663cb92002-04-12 10:26:32 +00001045pid_t waitpid(pid_t pid, int *status, int options)
1046{
sewardj45b4b372002-04-16 22:50:32 +00001047 return __libc_waitpid(pid, status, options);
sewardje663cb92002-04-12 10:26:32 +00001048}
1049
1050
1051extern
1052int __libc_nanosleep(const struct timespec *req, struct timespec *rem);
sewardj5905fae2002-04-26 13:25:00 +00001053__attribute__((weak))
sewardje663cb92002-04-12 10:26:32 +00001054int nanosleep(const struct timespec *req, struct timespec *rem)
1055{
1056 return __libc_nanosleep(req, rem);
1057}
1058
sewardjbe32e452002-04-24 20:29:58 +00001059
sewardje663cb92002-04-12 10:26:32 +00001060extern
1061int __libc_fsync(int fd);
sewardj5905fae2002-04-26 13:25:00 +00001062__attribute__((weak))
sewardje663cb92002-04-12 10:26:32 +00001063int fsync(int fd)
1064{
sewardj45b4b372002-04-16 22:50:32 +00001065 return __libc_fsync(fd);
sewardje663cb92002-04-12 10:26:32 +00001066}
1067
sewardjbe32e452002-04-24 20:29:58 +00001068
sewardj70c75362002-04-13 04:18:32 +00001069extern
1070off_t __libc_lseek(int fildes, off_t offset, int whence);
sewardj5905fae2002-04-26 13:25:00 +00001071__attribute__((weak))
sewardj70c75362002-04-13 04:18:32 +00001072off_t lseek(int fildes, off_t offset, int whence)
1073{
sewardj45b4b372002-04-16 22:50:32 +00001074 return __libc_lseek(fildes, offset, whence);
sewardj70c75362002-04-13 04:18:32 +00001075}
1076
sewardjbe32e452002-04-24 20:29:58 +00001077
1078extern
1079__off64_t __libc_lseek64(int fildes, __off64_t offset, int whence);
sewardj5905fae2002-04-26 13:25:00 +00001080__attribute__((weak))
sewardjbe32e452002-04-24 20:29:58 +00001081__off64_t lseek64(int fildes, __off64_t offset, int whence)
1082{
1083 return __libc_lseek64(fildes, offset, whence);
1084}
1085
1086
sewardj6af4b5d2002-04-16 04:40:49 +00001087extern
1088void __libc_longjmp(jmp_buf env, int val) __attribute((noreturn));
sewardj5905fae2002-04-26 13:25:00 +00001089/* not weak: __attribute__((weak)) */
sewardj6af4b5d2002-04-16 04:40:49 +00001090void longjmp(jmp_buf env, int val)
1091{
1092 __libc_longjmp(env, val);
1093}
1094
sewardjbe32e452002-04-24 20:29:58 +00001095
sewardj6af4b5d2002-04-16 04:40:49 +00001096extern
1097int __libc_send(int s, const void *msg, size_t len, int flags);
sewardj5905fae2002-04-26 13:25:00 +00001098__attribute__((weak))
sewardj6af4b5d2002-04-16 04:40:49 +00001099int send(int s, const void *msg, size_t len, int flags)
1100{
1101 return __libc_send(s, msg, len, flags);
1102}
1103
sewardjbe32e452002-04-24 20:29:58 +00001104
sewardj1e8cdc92002-04-18 11:37:52 +00001105extern
1106int __libc_recv(int s, void *buf, size_t len, int flags);
sewardj5905fae2002-04-26 13:25:00 +00001107__attribute__((weak))
sewardj1e8cdc92002-04-18 11:37:52 +00001108int recv(int s, void *buf, size_t len, int flags)
1109{
1110 return __libc_recv(s, buf, len, flags);
1111}
1112
sewardjbe32e452002-04-24 20:29:58 +00001113
sewardj796d6a22002-04-24 02:28:34 +00001114extern
sewardj436e0582002-04-26 14:31:40 +00001115int __libc_recvfrom(int s, void *buf, size_t len, int flags,
1116 struct sockaddr *from, socklen_t *fromlen);
1117__attribute__((weak))
1118int recvfrom(int s, void *buf, size_t len, int flags,
1119 struct sockaddr *from, socklen_t *fromlen)
1120{
1121 return __libc_recvfrom(s, buf, len, flags, from, fromlen);
1122}
1123
1124
1125extern
sewardj796d6a22002-04-24 02:28:34 +00001126int __libc_sendto(int s, const void *msg, size_t len, int flags,
1127 const struct sockaddr *to, socklen_t tolen);
sewardj5905fae2002-04-26 13:25:00 +00001128__attribute__((weak))
sewardj796d6a22002-04-24 02:28:34 +00001129int sendto(int s, const void *msg, size_t len, int flags,
1130 const struct sockaddr *to, socklen_t tolen)
1131{
1132 return __libc_sendto(s, msg, len, flags, to, tolen);
1133}
1134
sewardjbe32e452002-04-24 20:29:58 +00001135
sewardj369b1702002-04-24 13:28:15 +00001136extern
1137int __libc_system(const char* str);
sewardj5905fae2002-04-26 13:25:00 +00001138__attribute__((weak))
sewardj369b1702002-04-24 13:28:15 +00001139int system(const char* str)
1140{
1141 return __libc_system(str);
1142}
1143
sewardjbe32e452002-04-24 20:29:58 +00001144
sewardjab0b1c32002-04-24 19:26:47 +00001145extern
1146pid_t __libc_wait(int *status);
sewardj5905fae2002-04-26 13:25:00 +00001147__attribute__((weak))
sewardjab0b1c32002-04-24 19:26:47 +00001148pid_t wait(int *status)
1149{
1150 return __libc_wait(status);
1151}
1152
sewardj45b4b372002-04-16 22:50:32 +00001153
sewardj5905fae2002-04-26 13:25:00 +00001154
sewardj3b13f0e2002-04-25 20:17:29 +00001155/* ---------------------------------------------------------------------
1156 Nonblocking implementations of select() and poll(). This stuff will
1157 surely rot your mind.
1158 ------------------------------------------------------------------ */
sewardje663cb92002-04-12 10:26:32 +00001159
sewardj08a4c3f2002-04-13 03:45:44 +00001160/*--------------------------------------------------*/
1161
1162#include "vg_kerneliface.h"
1163
1164static
1165__inline__
1166int is_kerror ( int res )
1167{
1168 if (res >= -4095 && res <= -1)
1169 return 1;
1170 else
1171 return 0;
1172}
1173
1174
1175static
1176int my_do_syscall1 ( int syscallno, int arg1 )
1177{
1178 int __res;
1179 __asm__ volatile ("pushl %%ebx; movl %%edx,%%ebx ; int $0x80 ; popl %%ebx"
1180 : "=a" (__res)
1181 : "0" (syscallno),
1182 "d" (arg1) );
1183 return __res;
1184}
1185
1186static
1187int my_do_syscall2 ( int syscallno,
sewardjf854f472002-04-21 12:19:41 +00001188 int arg1, int arg2 )
sewardj08a4c3f2002-04-13 03:45:44 +00001189{
1190 int __res;
1191 __asm__ volatile ("pushl %%ebx; movl %%edx,%%ebx ; int $0x80 ; popl %%ebx"
1192 : "=a" (__res)
1193 : "0" (syscallno),
1194 "d" (arg1),
1195 "c" (arg2) );
1196 return __res;
1197}
1198
1199static
sewardjf854f472002-04-21 12:19:41 +00001200int my_do_syscall3 ( int syscallno,
1201 int arg1, int arg2, int arg3 )
1202{
1203 int __res;
1204 __asm__ volatile ("pushl %%ebx; movl %%esi,%%ebx ; int $0x80 ; popl %%ebx"
1205 : "=a" (__res)
1206 : "0" (syscallno),
1207 "S" (arg1),
1208 "c" (arg2),
1209 "d" (arg3) );
1210 return __res;
1211}
1212
1213static
sewardj08a4c3f2002-04-13 03:45:44 +00001214int do_syscall_select( int n,
1215 vki_fd_set* readfds,
1216 vki_fd_set* writefds,
1217 vki_fd_set* exceptfds,
1218 struct vki_timeval * timeout )
1219{
1220 int res;
1221 int args[5];
1222 args[0] = n;
1223 args[1] = (int)readfds;
1224 args[2] = (int)writefds;
1225 args[3] = (int)exceptfds;
1226 args[4] = (int)timeout;
1227 res = my_do_syscall1(__NR_select, (int)(&(args[0])) );
sewardj02535bc2002-04-21 01:08:26 +00001228 return res;
sewardj08a4c3f2002-04-13 03:45:44 +00001229}
1230
1231
1232/* This is a wrapper round select(), which makes it thread-safe,
1233 meaning that only this thread will block, rather than the entire
1234 process. This wrapper in turn depends on nanosleep() not to block
1235 the entire process, but I think (hope? suspect?) that POSIX
1236 pthreads guarantees that to be the case.
1237
1238 Basic idea is: modify the timeout parameter to select so that it
1239 returns immediately. Poll like this until select returns non-zero,
1240 indicating something interesting happened, or until our time is up.
1241 Space out the polls with nanosleeps of say 20 milliseconds, which
1242 is required to be nonblocking; this allows other threads to run.
sewardj02535bc2002-04-21 01:08:26 +00001243
1244 Assumes:
1245 * (checked via assert) types fd_set and vki_fd_set are identical.
1246 * (checked via assert) types timeval and vki_timeval are identical.
1247 * (unchecked) libc error numbers (EINTR etc) are the negation of the
1248 kernel's error numbers (VKI_EINTR etc).
sewardj08a4c3f2002-04-13 03:45:44 +00001249*/
sewardj08a4c3f2002-04-13 03:45:44 +00001250
sewardj5905fae2002-04-26 13:25:00 +00001251/* __attribute__((weak)) */
sewardj08a4c3f2002-04-13 03:45:44 +00001252int select ( int n,
1253 fd_set *rfds,
1254 fd_set *wfds,
1255 fd_set *xfds,
1256 struct timeval *timeout )
1257{
sewardj5f07b662002-04-23 16:52:51 +00001258 unsigned int ms_now, ms_end;
sewardj08a4c3f2002-04-13 03:45:44 +00001259 int res;
1260 fd_set rfds_copy;
1261 fd_set wfds_copy;
1262 fd_set xfds_copy;
1263 struct vki_timeval t_now;
sewardj08a4c3f2002-04-13 03:45:44 +00001264 struct vki_timeval zero_timeout;
1265 struct vki_timespec nanosleep_interval;
1266
sewardj5f07b662002-04-23 16:52:51 +00001267 /* gcc's complains about ms_end being used uninitialised -- classic
1268 case it can't understand, where ms_end is both defined and used
1269 only if timeout != NULL. Hence ... */
1270 ms_end = 0;
sewardj08a4c3f2002-04-13 03:45:44 +00001271
1272 /* We assume that the kernel and libc data layouts are identical
1273 for the following types. These asserts provide a crude
1274 check. */
1275 if (sizeof(fd_set) != sizeof(vki_fd_set)
1276 || sizeof(struct timeval) != sizeof(struct vki_timeval))
1277 barf("valgrind's hacky non-blocking select(): data sizes error");
1278
sewardj5f07b662002-04-23 16:52:51 +00001279 /* Detect the current time and simultaneously find out if we are
1280 running on Valgrind. */
1281 VALGRIND_MAGIC_SEQUENCE(ms_now, 0xFFFFFFFF /* default */,
1282 VG_USERREQ__READ_MILLISECOND_TIMER,
1283 0, 0, 0, 0);
1284
1285 /* If a zero timeout specified, this call is harmless. Also go
1286 this route if we're not running on Valgrind, for whatever
1287 reason. */
1288 if ( (timeout && timeout->tv_sec == 0 && timeout->tv_usec == 0)
1289 || (ms_now == 0xFFFFFFFF) ) {
sewardj02535bc2002-04-21 01:08:26 +00001290 res = do_syscall_select( n, (vki_fd_set*)rfds,
sewardj08a4c3f2002-04-13 03:45:44 +00001291 (vki_fd_set*)wfds,
1292 (vki_fd_set*)xfds,
1293 (struct vki_timeval*)timeout);
sewardj02535bc2002-04-21 01:08:26 +00001294 if (is_kerror(res)) {
1295 * (__errno_location()) = -res;
1296 return -1;
1297 } else {
1298 return res;
1299 }
1300 }
sewardj08a4c3f2002-04-13 03:45:44 +00001301
sewardj5f07b662002-04-23 16:52:51 +00001302 /* If a timeout was specified, set ms_end to be the end millisecond
1303 counter [wallclock] time. */
sewardj08a4c3f2002-04-13 03:45:44 +00001304 if (timeout) {
1305 res = my_do_syscall2(__NR_gettimeofday, (int)&t_now, (int)NULL);
1306 assert(res == 0);
sewardj5f07b662002-04-23 16:52:51 +00001307 ms_end = ms_now;
1308 ms_end += (timeout->tv_usec / 1000);
1309 ms_end += (timeout->tv_sec * 1000);
sewardj08a4c3f2002-04-13 03:45:44 +00001310 /* Stay sane ... */
sewardj5f07b662002-04-23 16:52:51 +00001311 assert (ms_end >= ms_now);
sewardj08a4c3f2002-04-13 03:45:44 +00001312 }
1313
1314 /* fprintf(stderr, "MY_SELECT: before loop\n"); */
1315
1316 /* Either timeout == NULL, meaning wait indefinitely, or timeout !=
sewardj5f07b662002-04-23 16:52:51 +00001317 NULL, in which case ms_end holds the end time. */
sewardj08a4c3f2002-04-13 03:45:44 +00001318 while (1) {
1319 if (timeout) {
sewardj5f07b662002-04-23 16:52:51 +00001320 VALGRIND_MAGIC_SEQUENCE(ms_now, 0xFFFFFFFF /* default */,
1321 VG_USERREQ__READ_MILLISECOND_TIMER,
1322 0, 0, 0, 0);
1323 assert(ms_now != 0xFFFFFFFF);
1324 if (ms_now >= ms_end) {
sewardj08a4c3f2002-04-13 03:45:44 +00001325 /* timeout; nothing interesting happened. */
1326 if (rfds) FD_ZERO(rfds);
1327 if (wfds) FD_ZERO(wfds);
1328 if (xfds) FD_ZERO(xfds);
1329 return 0;
1330 }
1331 }
1332
1333 /* These could be trashed each time round the loop, so restore
1334 them each time. */
1335 if (rfds) rfds_copy = *rfds;
1336 if (wfds) wfds_copy = *wfds;
1337 if (xfds) xfds_copy = *xfds;
1338
1339 zero_timeout.tv_sec = zero_timeout.tv_usec = 0;
1340
1341 res = do_syscall_select( n,
1342 rfds ? (vki_fd_set*)(&rfds_copy) : NULL,
1343 wfds ? (vki_fd_set*)(&wfds_copy) : NULL,
1344 xfds ? (vki_fd_set*)(&xfds_copy) : NULL,
1345 & zero_timeout );
sewardj02535bc2002-04-21 01:08:26 +00001346 if (is_kerror(res)) {
1347 /* Some kind of error (including EINTR). Set errno and
sewardj08a4c3f2002-04-13 03:45:44 +00001348 return. The sets are unspecified in this case. */
sewardj02535bc2002-04-21 01:08:26 +00001349 * (__errno_location()) = -res;
1350 return -1;
sewardj08a4c3f2002-04-13 03:45:44 +00001351 }
1352 if (res > 0) {
1353 /* one or more fds is ready. Copy out resulting sets and
1354 return. */
1355 if (rfds) *rfds = rfds_copy;
1356 if (wfds) *wfds = wfds_copy;
1357 if (xfds) *xfds = xfds_copy;
1358 return res;
1359 }
1360 /* fprintf(stderr, "MY_SELECT: nanosleep\n"); */
1361 /* nanosleep and go round again */
sewardj02535bc2002-04-21 01:08:26 +00001362 nanosleep_interval.tv_sec = 0;
sewardj956cc1b2002-04-25 01:33:50 +00001363 nanosleep_interval.tv_nsec = 50 * 1000 * 1000; /* 50 milliseconds */
sewardjf854f472002-04-21 12:19:41 +00001364 /* It's critical here that valgrind's nanosleep implementation
1365 is nonblocking. */
1366 (void)my_do_syscall2(__NR_nanosleep,
1367 (int)(&nanosleep_interval), (int)NULL);
1368 }
1369}
1370
1371
1372
1373
1374#include <sys/poll.h>
1375
sewardj72d58482002-04-24 02:20:20 +00001376#ifdef GLIBC_2_1
1377typedef unsigned long int nfds_t;
1378#endif
1379
sewardj5905fae2002-04-26 13:25:00 +00001380/* __attribute__((weak)) */
sewardjf854f472002-04-21 12:19:41 +00001381int poll (struct pollfd *__fds, nfds_t __nfds, int __timeout)
1382{
sewardj5f07b662002-04-23 16:52:51 +00001383 unsigned int ms_now, ms_end;
sewardjf854f472002-04-21 12:19:41 +00001384 int res, i;
sewardjf854f472002-04-21 12:19:41 +00001385 struct vki_timespec nanosleep_interval;
1386
1387 ensure_valgrind("poll");
1388
sewardj5f07b662002-04-23 16:52:51 +00001389 /* Detect the current time and simultaneously find out if we are
1390 running on Valgrind. */
1391 VALGRIND_MAGIC_SEQUENCE(ms_now, 0xFFFFFFFF /* default */,
1392 VG_USERREQ__READ_MILLISECOND_TIMER,
1393 0, 0, 0, 0);
1394
sewardjf854f472002-04-21 12:19:41 +00001395 if (/* CHECK SIZES FOR struct pollfd */
1396 sizeof(struct timeval) != sizeof(struct vki_timeval))
1397 barf("valgrind's hacky non-blocking poll(): data sizes error");
1398
sewardj5f07b662002-04-23 16:52:51 +00001399 /* dummy initialisation to keep gcc -Wall happy */
1400 ms_end = 0;
1401
1402 /* If a zero timeout specified, this call is harmless. Also do
1403 this if not running on Valgrind. */
1404 if (__timeout == 0 || ms_now == 0xFFFFFFFF) {
sewardjf854f472002-04-21 12:19:41 +00001405 res = my_do_syscall3(__NR_poll, (int)__fds, __nfds, __timeout);
1406 if (is_kerror(res)) {
1407 * (__errno_location()) = -res;
1408 return -1;
1409 } else {
1410 return res;
1411 }
1412 }
1413
sewardj5f07b662002-04-23 16:52:51 +00001414 /* If a timeout was specified, set ms_end to be the end wallclock
1415 time. Easy considering that __timeout is in milliseconds. */
sewardjf854f472002-04-21 12:19:41 +00001416 if (__timeout > 0) {
sewardj650ac002002-04-29 12:20:34 +00001417 ms_end = ms_now + (unsigned int)__timeout;
sewardjf854f472002-04-21 12:19:41 +00001418 }
1419
1420 /* fprintf(stderr, "MY_POLL: before loop\n"); */
1421
1422 /* Either timeout < 0, meaning wait indefinitely, or timeout > 0,
1423 in which case t_end holds the end time. */
sewardj5f07b662002-04-23 16:52:51 +00001424 assert(__timeout != 0);
1425
sewardjf854f472002-04-21 12:19:41 +00001426 while (1) {
sewardjf854f472002-04-21 12:19:41 +00001427 if (__timeout > 0) {
sewardj5f07b662002-04-23 16:52:51 +00001428 VALGRIND_MAGIC_SEQUENCE(ms_now, 0xFFFFFFFF /* default */,
1429 VG_USERREQ__READ_MILLISECOND_TIMER,
1430 0, 0, 0, 0);
1431 assert(ms_now != 0xFFFFFFFF);
1432 if (ms_now >= ms_end) {
sewardjf854f472002-04-21 12:19:41 +00001433 /* timeout; nothing interesting happened. */
1434 for (i = 0; i < __nfds; i++)
1435 __fds[i].revents = 0;
1436 return 0;
1437 }
1438 }
1439
sewardj5f07b662002-04-23 16:52:51 +00001440 /* Do a return-immediately poll. */
sewardjf854f472002-04-21 12:19:41 +00001441 res = my_do_syscall3(__NR_poll, (int)__fds, __nfds, 0 );
1442 if (is_kerror(res)) {
1443 /* Some kind of error. Set errno and return. */
1444 * (__errno_location()) = -res;
1445 return -1;
1446 }
1447 if (res > 0) {
1448 /* One or more fds is ready. Return now. */
1449 return res;
1450 }
1451 /* fprintf(stderr, "MY_POLL: nanosleep\n"); */
1452 /* nanosleep and go round again */
1453 nanosleep_interval.tv_sec = 0;
sewardj956cc1b2002-04-25 01:33:50 +00001454 nanosleep_interval.tv_nsec = 51 * 1000 * 1000; /* 51 milliseconds */
sewardj08a4c3f2002-04-13 03:45:44 +00001455 /* It's critical here that valgrind's nanosleep implementation
1456 is nonblocking. */
1457 (void)my_do_syscall2(__NR_nanosleep,
1458 (int)(&nanosleep_interval), (int)NULL);
1459 }
1460}
sewardj3b13f0e2002-04-25 20:17:29 +00001461
1462
1463/* ---------------------------------------------------------------------
1464 B'stard.
1465 ------------------------------------------------------------------ */
1466
1467# define strong_alias(name, aliasname) \
1468 extern __typeof (name) aliasname __attribute__ ((alias (#name)));
1469
sewardj5905fae2002-04-26 13:25:00 +00001470# define weak_alias(name, aliasname) \
1471 extern __typeof (name) aliasname __attribute__ ((weak, alias (#name)));
sewardj3b13f0e2002-04-25 20:17:29 +00001472
sewardj5905fae2002-04-26 13:25:00 +00001473strong_alias(__pthread_mutex_lock, pthread_mutex_lock)
1474strong_alias(__pthread_mutex_trylock, pthread_mutex_trylock)
1475strong_alias(__pthread_mutex_unlock, pthread_mutex_unlock)
1476strong_alias(__pthread_mutexattr_init, pthread_mutexattr_init)
1477 weak_alias(__pthread_mutexattr_settype, pthread_mutexattr_settype)
1478strong_alias(__pthread_mutex_init, pthread_mutex_init)
1479strong_alias(__pthread_mutexattr_destroy, pthread_mutexattr_destroy)
1480strong_alias(__pthread_mutex_destroy, pthread_mutex_destroy)
1481strong_alias(__pthread_once, pthread_once)
1482strong_alias(__pthread_atfork, pthread_atfork)
1483strong_alias(__pthread_key_create, pthread_key_create)
1484strong_alias(__pthread_getspecific, pthread_getspecific)
1485strong_alias(__pthread_setspecific, pthread_setspecific)
1486
sewardjd529a442002-05-04 19:49:21 +00001487#ifndef GLIBC_2_1
sewardj3b13f0e2002-04-25 20:17:29 +00001488strong_alias(sigaction, __sigaction)
sewardjd529a442002-05-04 19:49:21 +00001489#endif
1490
sewardj5905fae2002-04-26 13:25:00 +00001491strong_alias(close, __close)
sewardj3b13f0e2002-04-25 20:17:29 +00001492strong_alias(fcntl, __fcntl)
sewardj5905fae2002-04-26 13:25:00 +00001493strong_alias(lseek, __lseek)
1494strong_alias(open, __open)
1495strong_alias(open64, __open64)
1496//strong_alias(pread64, __pread64)
1497//strong_alias(pwrite64, __pwrite64)
1498strong_alias(read, __read)
1499strong_alias(wait, __wait)
1500strong_alias(write, __write)
sewardj3b13f0e2002-04-25 20:17:29 +00001501strong_alias(connect, __connect)
sewardj5905fae2002-04-26 13:25:00 +00001502strong_alias(send, __send)
1503
1504weak_alias(__fork, fork)
1505//weak_alias(__vfork, vfork)
1506
sewardj3b13f0e2002-04-25 20:17:29 +00001507
1508/*--------------------------------------------------*/
1509
sewardj5716dbb2002-04-26 03:28:18 +00001510int
1511pthread_rwlock_rdlock (void* /* pthread_rwlock_t* */ rwlock)
1512{
sewardj436e0582002-04-26 14:31:40 +00001513 static int moans = N_MOANS;
1514 if (moans-- > 0)
1515 kludged("pthread_rwlock_rdlock");
sewardj5716dbb2002-04-26 03:28:18 +00001516 return 0;
1517}
1518
sewardj5905fae2002-04-26 13:25:00 +00001519weak_alias(pthread_rwlock_rdlock, __pthread_rwlock_rdlock)
sewardj5716dbb2002-04-26 03:28:18 +00001520
1521
1522int
1523pthread_rwlock_unlock (void* /* pthread_rwlock_t* */ rwlock)
1524{
sewardj436e0582002-04-26 14:31:40 +00001525 static int moans = N_MOANS;
1526 if (moans-- > 0)
1527 kludged("pthread_rwlock_unlock");
sewardj5716dbb2002-04-26 03:28:18 +00001528 return 0;
1529}
1530
sewardj5905fae2002-04-26 13:25:00 +00001531weak_alias(pthread_rwlock_unlock, __pthread_rwlock_unlock)
sewardj5716dbb2002-04-26 03:28:18 +00001532
1533
sewardj060b04f2002-04-26 21:01:13 +00001534int
1535pthread_rwlock_wrlock (void* /* pthread_rwlock_t* */ rwlock)
1536{
1537 static int moans = N_MOANS;
1538 if (moans-- > 0)
1539 kludged("pthread_rwlock_wrlock");
1540 return 0;
1541}
1542
sewardj262b0292002-05-01 00:03:16 +00001543weak_alias(pthread_rwlock_wrlock, __pthread_rwlock_wrlock)
sewardj060b04f2002-04-26 21:01:13 +00001544
1545
sewardj3b13f0e2002-04-25 20:17:29 +00001546/* I've no idea what these are, but they get called quite a lot.
1547 Anybody know? */
1548
1549#undef _IO_flockfile
1550void _IO_flockfile ( _IO_FILE * file )
1551{
sewardj853f55d2002-04-26 00:27:53 +00001552 pthread_mutex_lock(file->_lock);
sewardj3b13f0e2002-04-25 20:17:29 +00001553}
sewardj5905fae2002-04-26 13:25:00 +00001554weak_alias(_IO_flockfile, flockfile);
1555
sewardj3b13f0e2002-04-25 20:17:29 +00001556
1557#undef _IO_funlockfile
1558void _IO_funlockfile ( _IO_FILE * file )
1559{
sewardj853f55d2002-04-26 00:27:53 +00001560 pthread_mutex_unlock(file->_lock);
sewardj3b13f0e2002-04-25 20:17:29 +00001561}
sewardj5905fae2002-04-26 13:25:00 +00001562weak_alias(_IO_funlockfile, funlockfile);
1563
sewardj3b13f0e2002-04-25 20:17:29 +00001564
1565void _pthread_cleanup_push_defer ( void )
1566{
sewardj439d45e2002-05-03 20:43:10 +00001567 static int moans = N_MOANS;
1568 if (moans-- > 0)
1569 ignored("_pthread_cleanup_push_defer");
sewardj3b13f0e2002-04-25 20:17:29 +00001570}
1571
1572void _pthread_cleanup_pop_restore ( void )
1573{
sewardj439d45e2002-05-03 20:43:10 +00001574 static int moans = N_MOANS;
1575 if (moans-- > 0)
1576 ignored("_pthread_cleanup_pop_restore");
sewardj3b13f0e2002-04-25 20:17:29 +00001577}
sewardjd4f2c712002-04-30 10:20:10 +00001578
sewardj60e38422002-05-08 14:08:22 +00001579/*--------*/
1580void _pthread_cleanup_push (struct _pthread_cleanup_buffer *__buffer,
1581 void (*__routine) (void *),
1582 void *__arg)
1583{
1584 static int moans = N_MOANS;
1585 if (moans-- > 0)
1586 ignored("_pthread_cleanup_push");
1587}
1588
1589void _pthread_cleanup_pop (struct _pthread_cleanup_buffer *__buffer,
1590 int __execute)
1591{
1592 static int moans = N_MOANS;
1593 if (moans-- > 0) {
1594 if (__execute)
1595 ignored("_pthread_cleanup_pop-EXECUTE");
1596 else
1597 ignored("_pthread_cleanup_pop-NO-EXECUTE");
1598 }
1599}
1600
sewardjd4f2c712002-04-30 10:20:10 +00001601
1602/* This doesn't seem to be needed to simulate libpthread.so's external
1603 interface, but many people complain about its absence. */
1604
1605strong_alias(__pthread_mutexattr_settype, __pthread_mutexattr_setkind_np)
1606weak_alias(__pthread_mutexattr_setkind_np, pthread_mutexattr_setkind_np)
sewardj439d45e2002-05-03 20:43:10 +00001607
1608
1609/*--------------------------------------------------------------------*/
1610/*--- end vg_libpthread.c ---*/
1611/*--------------------------------------------------------------------*/