blob: ba6b527ccc8f9f08bb0c910343cfb30249ea4320 [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
sewardj018f7622002-05-15 21:13:39 +0000637 constants to VKI_ constants, so that the former do not have to
638 be included into vg_scheduler.c. */
sewardjb48e5002002-05-13 00:16:03 +0000639
640 ensure_valgrind("pthread_sigmask");
641
642 switch (how) {
sewardj018f7622002-05-15 21:13:39 +0000643 case SIG_SETMASK: how = VKI_SIG_SETMASK; break;
644 case SIG_BLOCK: how = VKI_SIG_BLOCK; break;
645 case SIG_UNBLOCK: how = VKI_SIG_UNBLOCK; break;
sewardjb48e5002002-05-13 00:16:03 +0000646 default: return EINVAL;
647 }
648
649 /* Crude check */
650 if (newmask == NULL)
651 return EFAULT;
652
653 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
654 VG_USERREQ__PTHREAD_SIGMASK,
655 how, newmask, oldmask, 0);
656
657 /* The scheduler tells us of any memory violations. */
658 return res == 0 ? 0 : EFAULT;
659}
660
661
662int sigwait ( const sigset_t* set, int* sig )
663{
664 int res;
665 ensure_valgrind("sigwait");
666 /* As with pthread_sigmask we deliberately confuse sigset_t with
667 vki_ksigset_t. */
668 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
669 VG_USERREQ__SIGWAIT,
670 set, sig, 0, 0);
671 return res;
672}
673
674
sewardj018f7622002-05-15 21:13:39 +0000675int pthread_kill(pthread_t thread, int signo)
676{
677 int res;
678 ensure_valgrind("pthread_kill");
679 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
680 VG_USERREQ__PTHREAD_KILL,
681 thread, signo, 0, 0);
682 return res;
683}
684
685
sewardjb48e5002002-05-13 00:16:03 +0000686/* ---------------------------------------------------
sewardjf8f819e2002-04-17 23:21:37 +0000687 THREAD-SPECIFICs
688 ------------------------------------------------ */
sewardj5e5fa512002-04-14 13:13:05 +0000689
sewardj5905fae2002-04-26 13:25:00 +0000690int __pthread_key_create(pthread_key_t *key,
691 void (*destr_function) (void *))
sewardj5e5fa512002-04-14 13:13:05 +0000692{
sewardj5f07b662002-04-23 16:52:51 +0000693 int res;
694 ensure_valgrind("pthread_key_create");
695 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
696 VG_USERREQ__PTHREAD_KEY_CREATE,
697 key, destr_function, 0, 0);
698 return res;
sewardj5e5fa512002-04-14 13:13:05 +0000699}
700
701int pthread_key_delete(pthread_key_t key)
702{
sewardj436e0582002-04-26 14:31:40 +0000703 static int moans = N_MOANS;
704 if (moans-- > 0)
705 ignored("pthread_key_delete");
sewardj5e5fa512002-04-14 13:13:05 +0000706 return 0;
707}
708
sewardj5905fae2002-04-26 13:25:00 +0000709int __pthread_setspecific(pthread_key_t key, const void *pointer)
sewardj5e5fa512002-04-14 13:13:05 +0000710{
sewardj5f07b662002-04-23 16:52:51 +0000711 int res;
712 ensure_valgrind("pthread_setspecific");
713 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
714 VG_USERREQ__PTHREAD_SETSPECIFIC,
715 key, pointer, 0, 0);
716 return res;
sewardj5e5fa512002-04-14 13:13:05 +0000717}
718
sewardj5905fae2002-04-26 13:25:00 +0000719void * __pthread_getspecific(pthread_key_t key)
sewardj5e5fa512002-04-14 13:13:05 +0000720{
sewardj5f07b662002-04-23 16:52:51 +0000721 int res;
722 ensure_valgrind("pthread_getspecific");
723 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
724 VG_USERREQ__PTHREAD_GETSPECIFIC,
725 key, 0 , 0, 0);
726 return (void*)res;
sewardj5e5fa512002-04-14 13:13:05 +0000727}
728
sewardjf8f819e2002-04-17 23:21:37 +0000729
730/* ---------------------------------------------------
sewardj89d3d852002-04-24 19:21:39 +0000731 ONCEry
732 ------------------------------------------------ */
733
734static pthread_mutex_t once_masterlock = PTHREAD_MUTEX_INITIALIZER;
735
736
sewardj5905fae2002-04-26 13:25:00 +0000737int __pthread_once ( pthread_once_t *once_control,
738 void (*init_routine) (void) )
sewardj89d3d852002-04-24 19:21:39 +0000739{
740 int res;
741 ensure_valgrind("pthread_once");
742
sewardj68b2dd92002-05-10 21:03:56 +0000743 res = __pthread_mutex_lock(&once_masterlock);
sewardj89d3d852002-04-24 19:21:39 +0000744
sewardj68b2dd92002-05-10 21:03:56 +0000745 if (res != 0) {
746 printf("res = %d\n",res);
sewardj89d3d852002-04-24 19:21:39 +0000747 barf("pthread_once: Looks like your program's "
748 "init routine calls back to pthread_once() ?!");
sewardj68b2dd92002-05-10 21:03:56 +0000749 }
sewardj89d3d852002-04-24 19:21:39 +0000750
751 if (*once_control == 0) {
752 *once_control = 1;
753 init_routine();
754 }
755
sewardj68b2dd92002-05-10 21:03:56 +0000756 __pthread_mutex_unlock(&once_masterlock);
sewardj89d3d852002-04-24 19:21:39 +0000757
758 return 0;
759}
760
761
762/* ---------------------------------------------------
sewardj853f55d2002-04-26 00:27:53 +0000763 MISC
764 ------------------------------------------------ */
765
sewardj5905fae2002-04-26 13:25:00 +0000766int __pthread_atfork ( void (*prepare)(void),
767 void (*parent)(void),
768 void (*child)(void) )
sewardj853f55d2002-04-26 00:27:53 +0000769{
sewardj436e0582002-04-26 14:31:40 +0000770 static int moans = N_MOANS;
771 if (moans-- > 0)
772 ignored("pthread_atfork");
sewardj853f55d2002-04-26 00:27:53 +0000773 return 0;
774}
775
776
sewardjbb990782002-05-08 02:01:14 +0000777__attribute__((weak))
778void __pthread_initialize ( void )
779{
sewardjbea1caa2002-05-10 23:20:58 +0000780 ensure_valgrind("__pthread_initialize");
sewardjbb990782002-05-08 02:01:14 +0000781}
782
783
sewardj853f55d2002-04-26 00:27:53 +0000784/* ---------------------------------------------------
sewardj3b13f0e2002-04-25 20:17:29 +0000785 LIBRARY-PRIVATE THREAD SPECIFIC STATE
sewardjf8f819e2002-04-17 23:21:37 +0000786 ------------------------------------------------ */
787
sewardj3b13f0e2002-04-25 20:17:29 +0000788#include <resolv.h>
789static int thread_specific_errno[VG_N_THREADS];
790static int thread_specific_h_errno[VG_N_THREADS];
791static struct __res_state
792 thread_specific_res_state[VG_N_THREADS];
sewardjf8f819e2002-04-17 23:21:37 +0000793
sewardj3b13f0e2002-04-25 20:17:29 +0000794int* __errno_location ( void )
sewardjf8f819e2002-04-17 23:21:37 +0000795{
796 int tid;
sewardj3b13f0e2002-04-25 20:17:29 +0000797 /* ensure_valgrind("__errno_location"); */
798 VALGRIND_MAGIC_SEQUENCE(tid, 1 /* default */,
sewardjf8f819e2002-04-17 23:21:37 +0000799 VG_USERREQ__PTHREAD_GET_THREADID,
800 0, 0, 0, 0);
sewardj3b13f0e2002-04-25 20:17:29 +0000801 /* 'cos I'm paranoid ... */
sewardj439d45e2002-05-03 20:43:10 +0000802 if (tid < 1 || tid >= VG_N_THREADS)
sewardj3b13f0e2002-04-25 20:17:29 +0000803 barf("__errno_location: invalid ThreadId");
804 return & thread_specific_errno[tid];
805}
806
807int* __h_errno_location ( void )
808{
809 int tid;
810 /* ensure_valgrind("__h_errno_location"); */
811 VALGRIND_MAGIC_SEQUENCE(tid, 1 /* default */,
812 VG_USERREQ__PTHREAD_GET_THREADID,
813 0, 0, 0, 0);
814 /* 'cos I'm paranoid ... */
sewardj439d45e2002-05-03 20:43:10 +0000815 if (tid < 1 || tid >= VG_N_THREADS)
sewardj3b13f0e2002-04-25 20:17:29 +0000816 barf("__h_errno_location: invalid ThreadId");
817 return & thread_specific_h_errno[tid];
818}
819
820struct __res_state* __res_state ( void )
821{
822 int tid;
823 /* ensure_valgrind("__res_state"); */
824 VALGRIND_MAGIC_SEQUENCE(tid, 1 /* default */,
825 VG_USERREQ__PTHREAD_GET_THREADID,
826 0, 0, 0, 0);
827 /* 'cos I'm paranoid ... */
sewardj439d45e2002-05-03 20:43:10 +0000828 if (tid < 1 || tid >= VG_N_THREADS)
sewardj3b13f0e2002-04-25 20:17:29 +0000829 barf("__res_state: invalid ThreadId");
830 return & thread_specific_res_state[tid];
sewardjf8f819e2002-04-17 23:21:37 +0000831}
832
833
sewardj5716dbb2002-04-26 03:28:18 +0000834/* ---------------------------------------------------
835 LIBC-PRIVATE SPECIFIC DATA
836 ------------------------------------------------ */
837
838/* Relies on assumption that initial private data is NULL. This
839 should be fixed somehow. */
840
841/* The allowable keys (indices) (all 2 of them).
842 From sysdeps/pthread/bits/libc-tsd.h
843*/
sewardj70adeb22002-04-27 01:35:38 +0000844#define N_LIBC_TSD_EXTRA_KEYS 1
845
sewardj5716dbb2002-04-26 03:28:18 +0000846enum __libc_tsd_key_t { _LIBC_TSD_KEY_MALLOC = 0,
847 _LIBC_TSD_KEY_DL_ERROR,
848 _LIBC_TSD_KEY_N };
849
850/* Auto-initialising subsystem. libc_specifics_inited is set
851 after initialisation. libc_specifics_inited_mx guards it. */
852static int libc_specifics_inited = 0;
853static pthread_mutex_t libc_specifics_inited_mx = PTHREAD_MUTEX_INITIALIZER;
854
855/* These are the keys we must initialise the first time. */
sewardj70adeb22002-04-27 01:35:38 +0000856static pthread_key_t libc_specifics_keys[_LIBC_TSD_KEY_N
857 + N_LIBC_TSD_EXTRA_KEYS];
sewardj5716dbb2002-04-26 03:28:18 +0000858
859/* Initialise the keys, if they are not already initialise. */
860static
861void init_libc_tsd_keys ( void )
862{
863 int res, i;
864 pthread_key_t k;
865
866 res = pthread_mutex_lock(&libc_specifics_inited_mx);
867 if (res != 0) barf("init_libc_tsd_keys: lock");
868
869 if (libc_specifics_inited == 0) {
870 /* printf("INIT libc specifics\n"); */
871 libc_specifics_inited = 1;
sewardj70adeb22002-04-27 01:35:38 +0000872 for (i = 0; i < _LIBC_TSD_KEY_N + N_LIBC_TSD_EXTRA_KEYS; i++) {
sewardj5716dbb2002-04-26 03:28:18 +0000873 res = pthread_key_create(&k, NULL);
874 if (res != 0) barf("init_libc_tsd_keys: create");
875 libc_specifics_keys[i] = k;
876 }
877 }
878
879 res = pthread_mutex_unlock(&libc_specifics_inited_mx);
880 if (res != 0) barf("init_libc_tsd_keys: unlock");
881}
882
883
884static int
885libc_internal_tsd_set ( enum __libc_tsd_key_t key,
886 const void * pointer )
887{
sewardj70adeb22002-04-27 01:35:38 +0000888 int res;
889 static int moans = N_MOANS;
sewardj5716dbb2002-04-26 03:28:18 +0000890 /* printf("SET SET SET key %d ptr %p\n", key, pointer); */
sewardj70adeb22002-04-27 01:35:38 +0000891 if (key < _LIBC_TSD_KEY_MALLOC
892 || key >= _LIBC_TSD_KEY_N + N_LIBC_TSD_EXTRA_KEYS)
sewardj5716dbb2002-04-26 03:28:18 +0000893 barf("libc_internal_tsd_set: invalid key");
sewardj70adeb22002-04-27 01:35:38 +0000894 if (key >= _LIBC_TSD_KEY_N && moans-- > 0)
895 fprintf(stderr,
sewardj439d45e2002-05-03 20:43:10 +0000896 "valgrind's libpthread.so: libc_internal_tsd_set: "
897 "dubious key %d\n", key);
sewardj5716dbb2002-04-26 03:28:18 +0000898 init_libc_tsd_keys();
899 res = pthread_setspecific(libc_specifics_keys[key], pointer);
900 if (res != 0) barf("libc_internal_tsd_set: setspecific failed");
901 return 0;
902}
903
904static void *
905libc_internal_tsd_get ( enum __libc_tsd_key_t key )
906{
sewardj70adeb22002-04-27 01:35:38 +0000907 void* v;
908 static int moans = N_MOANS;
sewardj5716dbb2002-04-26 03:28:18 +0000909 /* printf("GET GET GET key %d\n", key); */
sewardj70adeb22002-04-27 01:35:38 +0000910 if (key < _LIBC_TSD_KEY_MALLOC
911 || key >= _LIBC_TSD_KEY_N + N_LIBC_TSD_EXTRA_KEYS)
sewardj5716dbb2002-04-26 03:28:18 +0000912 barf("libc_internal_tsd_get: invalid key");
sewardj70adeb22002-04-27 01:35:38 +0000913 if (key >= _LIBC_TSD_KEY_N && moans-- > 0)
914 fprintf(stderr,
sewardj439d45e2002-05-03 20:43:10 +0000915 "valgrind's libpthread.so: libc_internal_tsd_get: "
916 "dubious key %d\n", key);
sewardj5716dbb2002-04-26 03:28:18 +0000917 init_libc_tsd_keys();
918 v = pthread_getspecific(libc_specifics_keys[key]);
919 /* if (v == NULL) barf("libc_internal_tsd_set: getspecific failed"); */
920 return v;
921}
922
923
924
925
sewardj70adeb22002-04-27 01:35:38 +0000926int (*__libc_internal_tsd_set)
927 (enum __libc_tsd_key_t key, const void * pointer)
928 = libc_internal_tsd_set;
sewardj5716dbb2002-04-26 03:28:18 +0000929
sewardj70adeb22002-04-27 01:35:38 +0000930void* (*__libc_internal_tsd_get)
931 (enum __libc_tsd_key_t key)
932 = libc_internal_tsd_get;
sewardj5716dbb2002-04-26 03:28:18 +0000933
934
sewardje663cb92002-04-12 10:26:32 +0000935/* ---------------------------------------------------------------------
936 These are here (I think) because they are deemed cancellation
937 points by POSIX. For the moment we'll simply pass the call along
938 to the corresponding thread-unaware (?) libc routine.
939 ------------------------------------------------------------------ */
940
sewardje663cb92002-04-12 10:26:32 +0000941#include <stdlib.h>
sewardje663cb92002-04-12 10:26:32 +0000942#include <sys/types.h>
943#include <sys/socket.h>
944
sewardjd529a442002-05-04 19:49:21 +0000945#ifdef GLIBC_2_1
946extern
947int __sigaction
948 (int signum,
949 const struct sigaction *act,
950 struct sigaction *oldact);
951#else
sewardje663cb92002-04-12 10:26:32 +0000952extern
953int __libc_sigaction
954 (int signum,
955 const struct sigaction *act,
956 struct sigaction *oldact);
sewardjd529a442002-05-04 19:49:21 +0000957#endif
sewardje663cb92002-04-12 10:26:32 +0000958int sigaction(int signum,
959 const struct sigaction *act,
960 struct sigaction *oldact)
961{
sewardj2a1dcce2002-04-22 12:45:25 +0000962# ifdef GLIBC_2_1
963 return __sigaction(signum, act, oldact);
964# else
sewardj45b4b372002-04-16 22:50:32 +0000965 return __libc_sigaction(signum, act, oldact);
sewardj2a1dcce2002-04-22 12:45:25 +0000966# endif
sewardje663cb92002-04-12 10:26:32 +0000967}
968
969
970extern
971int __libc_connect(int sockfd,
972 const struct sockaddr *serv_addr,
973 socklen_t addrlen);
sewardj5905fae2002-04-26 13:25:00 +0000974__attribute__((weak))
sewardje663cb92002-04-12 10:26:32 +0000975int connect(int sockfd,
976 const struct sockaddr *serv_addr,
977 socklen_t addrlen)
978{
sewardj45b4b372002-04-16 22:50:32 +0000979 return __libc_connect(sockfd, serv_addr, addrlen);
sewardje663cb92002-04-12 10:26:32 +0000980}
981
982
983extern
984int __libc_fcntl(int fd, int cmd, long arg);
sewardj5905fae2002-04-26 13:25:00 +0000985__attribute__((weak))
sewardje663cb92002-04-12 10:26:32 +0000986int fcntl(int fd, int cmd, long arg)
987{
sewardj45b4b372002-04-16 22:50:32 +0000988 return __libc_fcntl(fd, cmd, arg);
sewardje663cb92002-04-12 10:26:32 +0000989}
990
991
992extern
993ssize_t __libc_write(int fd, const void *buf, size_t count);
sewardj5905fae2002-04-26 13:25:00 +0000994__attribute__((weak))
sewardje663cb92002-04-12 10:26:32 +0000995ssize_t write(int fd, const void *buf, size_t count)
996{
sewardj45b4b372002-04-16 22:50:32 +0000997 return __libc_write(fd, buf, count);
sewardje663cb92002-04-12 10:26:32 +0000998}
999
1000
1001extern
1002ssize_t __libc_read(int fd, void *buf, size_t count);
sewardj5905fae2002-04-26 13:25:00 +00001003__attribute__((weak))
sewardje663cb92002-04-12 10:26:32 +00001004ssize_t read(int fd, void *buf, size_t count)
1005{
sewardj45b4b372002-04-16 22:50:32 +00001006 return __libc_read(fd, buf, count);
sewardje663cb92002-04-12 10:26:32 +00001007}
1008
sewardjbe32e452002-04-24 20:29:58 +00001009
1010extern
sewardj853f55d2002-04-26 00:27:53 +00001011int __libc_open64(const char *pathname, int flags, mode_t mode);
sewardj5905fae2002-04-26 13:25:00 +00001012__attribute__((weak))
sewardj853f55d2002-04-26 00:27:53 +00001013int open64(const char *pathname, int flags, mode_t mode)
sewardjbe32e452002-04-24 20:29:58 +00001014{
sewardj853f55d2002-04-26 00:27:53 +00001015 return __libc_open64(pathname, flags, mode);
sewardjbe32e452002-04-24 20:29:58 +00001016}
1017
sewardje663cb92002-04-12 10:26:32 +00001018
1019extern
sewardj853f55d2002-04-26 00:27:53 +00001020int __libc_open(const char *pathname, int flags, mode_t mode);
sewardj5905fae2002-04-26 13:25:00 +00001021__attribute__((weak))
sewardj853f55d2002-04-26 00:27:53 +00001022int open(const char *pathname, int flags, mode_t mode)
sewardje663cb92002-04-12 10:26:32 +00001023{
sewardj853f55d2002-04-26 00:27:53 +00001024 return __libc_open(pathname, flags, mode);
sewardje663cb92002-04-12 10:26:32 +00001025}
1026
1027
1028extern
1029int __libc_close(int fd);
sewardj5905fae2002-04-26 13:25:00 +00001030__attribute__((weak))
sewardje663cb92002-04-12 10:26:32 +00001031int close(int fd)
1032{
sewardj45b4b372002-04-16 22:50:32 +00001033 return __libc_close(fd);
sewardje663cb92002-04-12 10:26:32 +00001034}
1035
1036
1037extern
1038int __libc_accept(int s, struct sockaddr *addr, socklen_t *addrlen);
sewardj5905fae2002-04-26 13:25:00 +00001039__attribute__((weak))
sewardje663cb92002-04-12 10:26:32 +00001040int accept(int s, struct sockaddr *addr, socklen_t *addrlen)
1041{
sewardj45b4b372002-04-16 22:50:32 +00001042 return __libc_accept(s, addr, addrlen);
sewardje663cb92002-04-12 10:26:32 +00001043}
1044
1045
1046extern
1047pid_t __libc_fork(void);
sewardj5905fae2002-04-26 13:25:00 +00001048pid_t __fork(void)
sewardje663cb92002-04-12 10:26:32 +00001049{
sewardj45b4b372002-04-16 22:50:32 +00001050 return __libc_fork();
sewardje663cb92002-04-12 10:26:32 +00001051}
1052
1053
1054extern
1055pid_t __libc_waitpid(pid_t pid, int *status, int options);
sewardj5905fae2002-04-26 13:25:00 +00001056__attribute__((weak))
sewardje663cb92002-04-12 10:26:32 +00001057pid_t waitpid(pid_t pid, int *status, int options)
1058{
sewardj45b4b372002-04-16 22:50:32 +00001059 return __libc_waitpid(pid, status, options);
sewardje663cb92002-04-12 10:26:32 +00001060}
1061
1062
1063extern
1064int __libc_nanosleep(const struct timespec *req, struct timespec *rem);
sewardj5905fae2002-04-26 13:25:00 +00001065__attribute__((weak))
sewardje663cb92002-04-12 10:26:32 +00001066int nanosleep(const struct timespec *req, struct timespec *rem)
1067{
1068 return __libc_nanosleep(req, rem);
1069}
1070
sewardjbe32e452002-04-24 20:29:58 +00001071
sewardje663cb92002-04-12 10:26:32 +00001072extern
1073int __libc_fsync(int fd);
sewardj5905fae2002-04-26 13:25:00 +00001074__attribute__((weak))
sewardje663cb92002-04-12 10:26:32 +00001075int fsync(int fd)
1076{
sewardj45b4b372002-04-16 22:50:32 +00001077 return __libc_fsync(fd);
sewardje663cb92002-04-12 10:26:32 +00001078}
1079
sewardjbe32e452002-04-24 20:29:58 +00001080
sewardj70c75362002-04-13 04:18:32 +00001081extern
1082off_t __libc_lseek(int fildes, off_t offset, int whence);
sewardj5905fae2002-04-26 13:25:00 +00001083__attribute__((weak))
sewardj70c75362002-04-13 04:18:32 +00001084off_t lseek(int fildes, off_t offset, int whence)
1085{
sewardj45b4b372002-04-16 22:50:32 +00001086 return __libc_lseek(fildes, offset, whence);
sewardj70c75362002-04-13 04:18:32 +00001087}
1088
sewardjbe32e452002-04-24 20:29:58 +00001089
1090extern
1091__off64_t __libc_lseek64(int fildes, __off64_t offset, int whence);
sewardj5905fae2002-04-26 13:25:00 +00001092__attribute__((weak))
sewardjbe32e452002-04-24 20:29:58 +00001093__off64_t lseek64(int fildes, __off64_t offset, int whence)
1094{
1095 return __libc_lseek64(fildes, offset, whence);
1096}
1097
1098
sewardj6af4b5d2002-04-16 04:40:49 +00001099extern
1100void __libc_longjmp(jmp_buf env, int val) __attribute((noreturn));
sewardj5905fae2002-04-26 13:25:00 +00001101/* not weak: __attribute__((weak)) */
sewardj6af4b5d2002-04-16 04:40:49 +00001102void longjmp(jmp_buf env, int val)
1103{
1104 __libc_longjmp(env, val);
1105}
1106
sewardjbe32e452002-04-24 20:29:58 +00001107
sewardj6af4b5d2002-04-16 04:40:49 +00001108extern
1109int __libc_send(int s, const void *msg, size_t len, int flags);
sewardj5905fae2002-04-26 13:25:00 +00001110__attribute__((weak))
sewardj6af4b5d2002-04-16 04:40:49 +00001111int send(int s, const void *msg, size_t len, int flags)
1112{
1113 return __libc_send(s, msg, len, flags);
1114}
1115
sewardjbe32e452002-04-24 20:29:58 +00001116
sewardj1e8cdc92002-04-18 11:37:52 +00001117extern
1118int __libc_recv(int s, void *buf, size_t len, int flags);
sewardj5905fae2002-04-26 13:25:00 +00001119__attribute__((weak))
sewardj1e8cdc92002-04-18 11:37:52 +00001120int recv(int s, void *buf, size_t len, int flags)
1121{
1122 return __libc_recv(s, buf, len, flags);
1123}
1124
sewardjbe32e452002-04-24 20:29:58 +00001125
sewardj796d6a22002-04-24 02:28:34 +00001126extern
sewardj436e0582002-04-26 14:31:40 +00001127int __libc_recvfrom(int s, void *buf, size_t len, int flags,
1128 struct sockaddr *from, socklen_t *fromlen);
1129__attribute__((weak))
1130int recvfrom(int s, void *buf, size_t len, int flags,
1131 struct sockaddr *from, socklen_t *fromlen)
1132{
1133 return __libc_recvfrom(s, buf, len, flags, from, fromlen);
1134}
1135
1136
1137extern
sewardj796d6a22002-04-24 02:28:34 +00001138int __libc_sendto(int s, const void *msg, size_t len, int flags,
1139 const struct sockaddr *to, socklen_t tolen);
sewardj5905fae2002-04-26 13:25:00 +00001140__attribute__((weak))
sewardj796d6a22002-04-24 02:28:34 +00001141int sendto(int s, const void *msg, size_t len, int flags,
1142 const struct sockaddr *to, socklen_t tolen)
1143{
1144 return __libc_sendto(s, msg, len, flags, to, tolen);
1145}
1146
sewardjbe32e452002-04-24 20:29:58 +00001147
sewardj369b1702002-04-24 13:28:15 +00001148extern
1149int __libc_system(const char* str);
sewardj5905fae2002-04-26 13:25:00 +00001150__attribute__((weak))
sewardj369b1702002-04-24 13:28:15 +00001151int system(const char* str)
1152{
1153 return __libc_system(str);
1154}
1155
sewardjbe32e452002-04-24 20:29:58 +00001156
sewardjab0b1c32002-04-24 19:26:47 +00001157extern
1158pid_t __libc_wait(int *status);
sewardj5905fae2002-04-26 13:25:00 +00001159__attribute__((weak))
sewardjab0b1c32002-04-24 19:26:47 +00001160pid_t wait(int *status)
1161{
1162 return __libc_wait(status);
1163}
1164
sewardj45b4b372002-04-16 22:50:32 +00001165
sewardj5905fae2002-04-26 13:25:00 +00001166
sewardj3b13f0e2002-04-25 20:17:29 +00001167/* ---------------------------------------------------------------------
1168 Nonblocking implementations of select() and poll(). This stuff will
1169 surely rot your mind.
1170 ------------------------------------------------------------------ */
sewardje663cb92002-04-12 10:26:32 +00001171
sewardj08a4c3f2002-04-13 03:45:44 +00001172/*--------------------------------------------------*/
1173
1174#include "vg_kerneliface.h"
1175
1176static
1177__inline__
1178int is_kerror ( int res )
1179{
1180 if (res >= -4095 && res <= -1)
1181 return 1;
1182 else
1183 return 0;
1184}
1185
1186
1187static
1188int my_do_syscall1 ( int syscallno, int arg1 )
1189{
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 return __res;
1196}
1197
1198static
1199int my_do_syscall2 ( int syscallno,
sewardjf854f472002-04-21 12:19:41 +00001200 int arg1, int arg2 )
sewardj08a4c3f2002-04-13 03:45:44 +00001201{
1202 int __res;
1203 __asm__ volatile ("pushl %%ebx; movl %%edx,%%ebx ; int $0x80 ; popl %%ebx"
1204 : "=a" (__res)
1205 : "0" (syscallno),
1206 "d" (arg1),
1207 "c" (arg2) );
1208 return __res;
1209}
1210
1211static
sewardjf854f472002-04-21 12:19:41 +00001212int my_do_syscall3 ( int syscallno,
1213 int arg1, int arg2, int arg3 )
1214{
1215 int __res;
1216 __asm__ volatile ("pushl %%ebx; movl %%esi,%%ebx ; int $0x80 ; popl %%ebx"
1217 : "=a" (__res)
1218 : "0" (syscallno),
1219 "S" (arg1),
1220 "c" (arg2),
1221 "d" (arg3) );
1222 return __res;
1223}
1224
1225static
sewardj08a4c3f2002-04-13 03:45:44 +00001226int do_syscall_select( int n,
1227 vki_fd_set* readfds,
1228 vki_fd_set* writefds,
1229 vki_fd_set* exceptfds,
1230 struct vki_timeval * timeout )
1231{
1232 int res;
1233 int args[5];
1234 args[0] = n;
1235 args[1] = (int)readfds;
1236 args[2] = (int)writefds;
1237 args[3] = (int)exceptfds;
1238 args[4] = (int)timeout;
1239 res = my_do_syscall1(__NR_select, (int)(&(args[0])) );
sewardj02535bc2002-04-21 01:08:26 +00001240 return res;
sewardj08a4c3f2002-04-13 03:45:44 +00001241}
1242
1243
1244/* This is a wrapper round select(), which makes it thread-safe,
1245 meaning that only this thread will block, rather than the entire
1246 process. This wrapper in turn depends on nanosleep() not to block
1247 the entire process, but I think (hope? suspect?) that POSIX
1248 pthreads guarantees that to be the case.
1249
1250 Basic idea is: modify the timeout parameter to select so that it
1251 returns immediately. Poll like this until select returns non-zero,
1252 indicating something interesting happened, or until our time is up.
1253 Space out the polls with nanosleeps of say 20 milliseconds, which
1254 is required to be nonblocking; this allows other threads to run.
sewardj02535bc2002-04-21 01:08:26 +00001255
1256 Assumes:
1257 * (checked via assert) types fd_set and vki_fd_set are identical.
1258 * (checked via assert) types timeval and vki_timeval are identical.
1259 * (unchecked) libc error numbers (EINTR etc) are the negation of the
1260 kernel's error numbers (VKI_EINTR etc).
sewardj08a4c3f2002-04-13 03:45:44 +00001261*/
sewardj08a4c3f2002-04-13 03:45:44 +00001262
sewardj5905fae2002-04-26 13:25:00 +00001263/* __attribute__((weak)) */
sewardj08a4c3f2002-04-13 03:45:44 +00001264int select ( int n,
1265 fd_set *rfds,
1266 fd_set *wfds,
1267 fd_set *xfds,
1268 struct timeval *timeout )
1269{
sewardj5f07b662002-04-23 16:52:51 +00001270 unsigned int ms_now, ms_end;
sewardj08a4c3f2002-04-13 03:45:44 +00001271 int res;
1272 fd_set rfds_copy;
1273 fd_set wfds_copy;
1274 fd_set xfds_copy;
1275 struct vki_timeval t_now;
sewardj08a4c3f2002-04-13 03:45:44 +00001276 struct vki_timeval zero_timeout;
1277 struct vki_timespec nanosleep_interval;
1278
sewardj5f07b662002-04-23 16:52:51 +00001279 /* gcc's complains about ms_end being used uninitialised -- classic
1280 case it can't understand, where ms_end is both defined and used
1281 only if timeout != NULL. Hence ... */
1282 ms_end = 0;
sewardj08a4c3f2002-04-13 03:45:44 +00001283
1284 /* We assume that the kernel and libc data layouts are identical
1285 for the following types. These asserts provide a crude
1286 check. */
1287 if (sizeof(fd_set) != sizeof(vki_fd_set)
1288 || sizeof(struct timeval) != sizeof(struct vki_timeval))
1289 barf("valgrind's hacky non-blocking select(): data sizes error");
1290
sewardj5f07b662002-04-23 16:52:51 +00001291 /* Detect the current time and simultaneously find out if we are
1292 running on Valgrind. */
1293 VALGRIND_MAGIC_SEQUENCE(ms_now, 0xFFFFFFFF /* default */,
1294 VG_USERREQ__READ_MILLISECOND_TIMER,
1295 0, 0, 0, 0);
1296
1297 /* If a zero timeout specified, this call is harmless. Also go
1298 this route if we're not running on Valgrind, for whatever
1299 reason. */
1300 if ( (timeout && timeout->tv_sec == 0 && timeout->tv_usec == 0)
1301 || (ms_now == 0xFFFFFFFF) ) {
sewardj02535bc2002-04-21 01:08:26 +00001302 res = do_syscall_select( n, (vki_fd_set*)rfds,
sewardj08a4c3f2002-04-13 03:45:44 +00001303 (vki_fd_set*)wfds,
1304 (vki_fd_set*)xfds,
1305 (struct vki_timeval*)timeout);
sewardj02535bc2002-04-21 01:08:26 +00001306 if (is_kerror(res)) {
1307 * (__errno_location()) = -res;
1308 return -1;
1309 } else {
1310 return res;
1311 }
1312 }
sewardj08a4c3f2002-04-13 03:45:44 +00001313
sewardj5f07b662002-04-23 16:52:51 +00001314 /* If a timeout was specified, set ms_end to be the end millisecond
1315 counter [wallclock] time. */
sewardj08a4c3f2002-04-13 03:45:44 +00001316 if (timeout) {
1317 res = my_do_syscall2(__NR_gettimeofday, (int)&t_now, (int)NULL);
1318 assert(res == 0);
sewardj5f07b662002-04-23 16:52:51 +00001319 ms_end = ms_now;
1320 ms_end += (timeout->tv_usec / 1000);
1321 ms_end += (timeout->tv_sec * 1000);
sewardj08a4c3f2002-04-13 03:45:44 +00001322 /* Stay sane ... */
sewardj5f07b662002-04-23 16:52:51 +00001323 assert (ms_end >= ms_now);
sewardj08a4c3f2002-04-13 03:45:44 +00001324 }
1325
1326 /* fprintf(stderr, "MY_SELECT: before loop\n"); */
1327
1328 /* Either timeout == NULL, meaning wait indefinitely, or timeout !=
sewardj5f07b662002-04-23 16:52:51 +00001329 NULL, in which case ms_end holds the end time. */
sewardj08a4c3f2002-04-13 03:45:44 +00001330 while (1) {
1331 if (timeout) {
sewardj5f07b662002-04-23 16:52:51 +00001332 VALGRIND_MAGIC_SEQUENCE(ms_now, 0xFFFFFFFF /* default */,
1333 VG_USERREQ__READ_MILLISECOND_TIMER,
1334 0, 0, 0, 0);
1335 assert(ms_now != 0xFFFFFFFF);
1336 if (ms_now >= ms_end) {
sewardj08a4c3f2002-04-13 03:45:44 +00001337 /* timeout; nothing interesting happened. */
1338 if (rfds) FD_ZERO(rfds);
1339 if (wfds) FD_ZERO(wfds);
1340 if (xfds) FD_ZERO(xfds);
1341 return 0;
1342 }
1343 }
1344
1345 /* These could be trashed each time round the loop, so restore
1346 them each time. */
1347 if (rfds) rfds_copy = *rfds;
1348 if (wfds) wfds_copy = *wfds;
1349 if (xfds) xfds_copy = *xfds;
1350
1351 zero_timeout.tv_sec = zero_timeout.tv_usec = 0;
1352
1353 res = do_syscall_select( n,
1354 rfds ? (vki_fd_set*)(&rfds_copy) : NULL,
1355 wfds ? (vki_fd_set*)(&wfds_copy) : NULL,
1356 xfds ? (vki_fd_set*)(&xfds_copy) : NULL,
1357 & zero_timeout );
sewardj02535bc2002-04-21 01:08:26 +00001358 if (is_kerror(res)) {
1359 /* Some kind of error (including EINTR). Set errno and
sewardj08a4c3f2002-04-13 03:45:44 +00001360 return. The sets are unspecified in this case. */
sewardj02535bc2002-04-21 01:08:26 +00001361 * (__errno_location()) = -res;
1362 return -1;
sewardj08a4c3f2002-04-13 03:45:44 +00001363 }
1364 if (res > 0) {
1365 /* one or more fds is ready. Copy out resulting sets and
1366 return. */
1367 if (rfds) *rfds = rfds_copy;
1368 if (wfds) *wfds = wfds_copy;
1369 if (xfds) *xfds = xfds_copy;
1370 return res;
1371 }
1372 /* fprintf(stderr, "MY_SELECT: nanosleep\n"); */
1373 /* nanosleep and go round again */
sewardj02535bc2002-04-21 01:08:26 +00001374 nanosleep_interval.tv_sec = 0;
sewardj956cc1b2002-04-25 01:33:50 +00001375 nanosleep_interval.tv_nsec = 50 * 1000 * 1000; /* 50 milliseconds */
sewardjf854f472002-04-21 12:19:41 +00001376 /* It's critical here that valgrind's nanosleep implementation
1377 is nonblocking. */
1378 (void)my_do_syscall2(__NR_nanosleep,
1379 (int)(&nanosleep_interval), (int)NULL);
1380 }
1381}
1382
1383
1384
1385
1386#include <sys/poll.h>
1387
sewardj72d58482002-04-24 02:20:20 +00001388#ifdef GLIBC_2_1
1389typedef unsigned long int nfds_t;
1390#endif
1391
sewardj5905fae2002-04-26 13:25:00 +00001392/* __attribute__((weak)) */
sewardjf854f472002-04-21 12:19:41 +00001393int poll (struct pollfd *__fds, nfds_t __nfds, int __timeout)
1394{
sewardj5f07b662002-04-23 16:52:51 +00001395 unsigned int ms_now, ms_end;
sewardjf854f472002-04-21 12:19:41 +00001396 int res, i;
sewardjf854f472002-04-21 12:19:41 +00001397 struct vki_timespec nanosleep_interval;
1398
1399 ensure_valgrind("poll");
1400
sewardj5f07b662002-04-23 16:52:51 +00001401 /* Detect the current time and simultaneously find out if we are
1402 running on Valgrind. */
1403 VALGRIND_MAGIC_SEQUENCE(ms_now, 0xFFFFFFFF /* default */,
1404 VG_USERREQ__READ_MILLISECOND_TIMER,
1405 0, 0, 0, 0);
1406
sewardjf854f472002-04-21 12:19:41 +00001407 if (/* CHECK SIZES FOR struct pollfd */
1408 sizeof(struct timeval) != sizeof(struct vki_timeval))
1409 barf("valgrind's hacky non-blocking poll(): data sizes error");
1410
sewardj5f07b662002-04-23 16:52:51 +00001411 /* dummy initialisation to keep gcc -Wall happy */
1412 ms_end = 0;
1413
1414 /* If a zero timeout specified, this call is harmless. Also do
1415 this if not running on Valgrind. */
1416 if (__timeout == 0 || ms_now == 0xFFFFFFFF) {
sewardjf854f472002-04-21 12:19:41 +00001417 res = my_do_syscall3(__NR_poll, (int)__fds, __nfds, __timeout);
1418 if (is_kerror(res)) {
1419 * (__errno_location()) = -res;
1420 return -1;
1421 } else {
1422 return res;
1423 }
1424 }
1425
sewardj5f07b662002-04-23 16:52:51 +00001426 /* If a timeout was specified, set ms_end to be the end wallclock
1427 time. Easy considering that __timeout is in milliseconds. */
sewardjf854f472002-04-21 12:19:41 +00001428 if (__timeout > 0) {
sewardj650ac002002-04-29 12:20:34 +00001429 ms_end = ms_now + (unsigned int)__timeout;
sewardjf854f472002-04-21 12:19:41 +00001430 }
1431
1432 /* fprintf(stderr, "MY_POLL: before loop\n"); */
1433
1434 /* Either timeout < 0, meaning wait indefinitely, or timeout > 0,
1435 in which case t_end holds the end time. */
sewardj5f07b662002-04-23 16:52:51 +00001436 assert(__timeout != 0);
1437
sewardjf854f472002-04-21 12:19:41 +00001438 while (1) {
sewardjf854f472002-04-21 12:19:41 +00001439 if (__timeout > 0) {
sewardj5f07b662002-04-23 16:52:51 +00001440 VALGRIND_MAGIC_SEQUENCE(ms_now, 0xFFFFFFFF /* default */,
1441 VG_USERREQ__READ_MILLISECOND_TIMER,
1442 0, 0, 0, 0);
1443 assert(ms_now != 0xFFFFFFFF);
1444 if (ms_now >= ms_end) {
sewardjf854f472002-04-21 12:19:41 +00001445 /* timeout; nothing interesting happened. */
1446 for (i = 0; i < __nfds; i++)
1447 __fds[i].revents = 0;
1448 return 0;
1449 }
1450 }
1451
sewardj5f07b662002-04-23 16:52:51 +00001452 /* Do a return-immediately poll. */
sewardjf854f472002-04-21 12:19:41 +00001453 res = my_do_syscall3(__NR_poll, (int)__fds, __nfds, 0 );
1454 if (is_kerror(res)) {
1455 /* Some kind of error. Set errno and return. */
1456 * (__errno_location()) = -res;
1457 return -1;
1458 }
1459 if (res > 0) {
1460 /* One or more fds is ready. Return now. */
1461 return res;
1462 }
1463 /* fprintf(stderr, "MY_POLL: nanosleep\n"); */
1464 /* nanosleep and go round again */
1465 nanosleep_interval.tv_sec = 0;
sewardj956cc1b2002-04-25 01:33:50 +00001466 nanosleep_interval.tv_nsec = 51 * 1000 * 1000; /* 51 milliseconds */
sewardj08a4c3f2002-04-13 03:45:44 +00001467 /* It's critical here that valgrind's nanosleep implementation
1468 is nonblocking. */
1469 (void)my_do_syscall2(__NR_nanosleep,
1470 (int)(&nanosleep_interval), (int)NULL);
1471 }
1472}
sewardj3b13f0e2002-04-25 20:17:29 +00001473
1474
1475/* ---------------------------------------------------------------------
1476 B'stard.
1477 ------------------------------------------------------------------ */
1478
1479# define strong_alias(name, aliasname) \
1480 extern __typeof (name) aliasname __attribute__ ((alias (#name)));
1481
sewardj5905fae2002-04-26 13:25:00 +00001482# define weak_alias(name, aliasname) \
1483 extern __typeof (name) aliasname __attribute__ ((weak, alias (#name)));
sewardj3b13f0e2002-04-25 20:17:29 +00001484
sewardj5905fae2002-04-26 13:25:00 +00001485strong_alias(__pthread_mutex_lock, pthread_mutex_lock)
1486strong_alias(__pthread_mutex_trylock, pthread_mutex_trylock)
1487strong_alias(__pthread_mutex_unlock, pthread_mutex_unlock)
1488strong_alias(__pthread_mutexattr_init, pthread_mutexattr_init)
1489 weak_alias(__pthread_mutexattr_settype, pthread_mutexattr_settype)
1490strong_alias(__pthread_mutex_init, pthread_mutex_init)
1491strong_alias(__pthread_mutexattr_destroy, pthread_mutexattr_destroy)
1492strong_alias(__pthread_mutex_destroy, pthread_mutex_destroy)
1493strong_alias(__pthread_once, pthread_once)
1494strong_alias(__pthread_atfork, pthread_atfork)
1495strong_alias(__pthread_key_create, pthread_key_create)
1496strong_alias(__pthread_getspecific, pthread_getspecific)
1497strong_alias(__pthread_setspecific, pthread_setspecific)
1498
sewardjd529a442002-05-04 19:49:21 +00001499#ifndef GLIBC_2_1
sewardj3b13f0e2002-04-25 20:17:29 +00001500strong_alias(sigaction, __sigaction)
sewardjd529a442002-05-04 19:49:21 +00001501#endif
1502
sewardj5905fae2002-04-26 13:25:00 +00001503strong_alias(close, __close)
sewardj3b13f0e2002-04-25 20:17:29 +00001504strong_alias(fcntl, __fcntl)
sewardj5905fae2002-04-26 13:25:00 +00001505strong_alias(lseek, __lseek)
1506strong_alias(open, __open)
1507strong_alias(open64, __open64)
1508//strong_alias(pread64, __pread64)
1509//strong_alias(pwrite64, __pwrite64)
1510strong_alias(read, __read)
1511strong_alias(wait, __wait)
1512strong_alias(write, __write)
sewardj3b13f0e2002-04-25 20:17:29 +00001513strong_alias(connect, __connect)
sewardj5905fae2002-04-26 13:25:00 +00001514strong_alias(send, __send)
1515
1516weak_alias(__fork, fork)
1517//weak_alias(__vfork, vfork)
1518
sewardj3b13f0e2002-04-25 20:17:29 +00001519
1520/*--------------------------------------------------*/
1521
sewardj5716dbb2002-04-26 03:28:18 +00001522int
1523pthread_rwlock_rdlock (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_rdlock");
sewardj5716dbb2002-04-26 03:28:18 +00001528 return 0;
1529}
1530
sewardj5905fae2002-04-26 13:25:00 +00001531weak_alias(pthread_rwlock_rdlock, __pthread_rwlock_rdlock)
sewardj5716dbb2002-04-26 03:28:18 +00001532
1533
1534int
1535pthread_rwlock_unlock (void* /* pthread_rwlock_t* */ rwlock)
1536{
sewardj436e0582002-04-26 14:31:40 +00001537 static int moans = N_MOANS;
1538 if (moans-- > 0)
1539 kludged("pthread_rwlock_unlock");
sewardj5716dbb2002-04-26 03:28:18 +00001540 return 0;
1541}
1542
sewardj5905fae2002-04-26 13:25:00 +00001543weak_alias(pthread_rwlock_unlock, __pthread_rwlock_unlock)
sewardj5716dbb2002-04-26 03:28:18 +00001544
1545
sewardj060b04f2002-04-26 21:01:13 +00001546int
1547pthread_rwlock_wrlock (void* /* pthread_rwlock_t* */ rwlock)
1548{
1549 static int moans = N_MOANS;
1550 if (moans-- > 0)
1551 kludged("pthread_rwlock_wrlock");
1552 return 0;
1553}
1554
sewardj262b0292002-05-01 00:03:16 +00001555weak_alias(pthread_rwlock_wrlock, __pthread_rwlock_wrlock)
sewardj060b04f2002-04-26 21:01:13 +00001556
1557
sewardj3b13f0e2002-04-25 20:17:29 +00001558/* I've no idea what these are, but they get called quite a lot.
1559 Anybody know? */
1560
1561#undef _IO_flockfile
1562void _IO_flockfile ( _IO_FILE * file )
1563{
sewardj853f55d2002-04-26 00:27:53 +00001564 pthread_mutex_lock(file->_lock);
sewardj3b13f0e2002-04-25 20:17:29 +00001565}
sewardj5905fae2002-04-26 13:25:00 +00001566weak_alias(_IO_flockfile, flockfile);
1567
sewardj3b13f0e2002-04-25 20:17:29 +00001568
1569#undef _IO_funlockfile
1570void _IO_funlockfile ( _IO_FILE * file )
1571{
sewardj853f55d2002-04-26 00:27:53 +00001572 pthread_mutex_unlock(file->_lock);
sewardj3b13f0e2002-04-25 20:17:29 +00001573}
sewardj5905fae2002-04-26 13:25:00 +00001574weak_alias(_IO_funlockfile, funlockfile);
1575
sewardj3b13f0e2002-04-25 20:17:29 +00001576
1577void _pthread_cleanup_push_defer ( void )
1578{
sewardj439d45e2002-05-03 20:43:10 +00001579 static int moans = N_MOANS;
1580 if (moans-- > 0)
1581 ignored("_pthread_cleanup_push_defer");
sewardj3b13f0e2002-04-25 20:17:29 +00001582}
1583
1584void _pthread_cleanup_pop_restore ( void )
1585{
sewardj439d45e2002-05-03 20:43:10 +00001586 static int moans = N_MOANS;
1587 if (moans-- > 0)
1588 ignored("_pthread_cleanup_pop_restore");
sewardj3b13f0e2002-04-25 20:17:29 +00001589}
sewardjd4f2c712002-04-30 10:20:10 +00001590
sewardj60e38422002-05-08 14:08:22 +00001591/*--------*/
1592void _pthread_cleanup_push (struct _pthread_cleanup_buffer *__buffer,
1593 void (*__routine) (void *),
1594 void *__arg)
1595{
1596 static int moans = N_MOANS;
1597 if (moans-- > 0)
1598 ignored("_pthread_cleanup_push");
1599}
1600
1601void _pthread_cleanup_pop (struct _pthread_cleanup_buffer *__buffer,
1602 int __execute)
1603{
1604 static int moans = N_MOANS;
1605 if (moans-- > 0) {
1606 if (__execute)
1607 ignored("_pthread_cleanup_pop-EXECUTE");
1608 else
1609 ignored("_pthread_cleanup_pop-NO-EXECUTE");
1610 }
1611}
1612
sewardjd4f2c712002-04-30 10:20:10 +00001613
1614/* This doesn't seem to be needed to simulate libpthread.so's external
1615 interface, but many people complain about its absence. */
1616
1617strong_alias(__pthread_mutexattr_settype, __pthread_mutexattr_setkind_np)
1618weak_alias(__pthread_mutexattr_setkind_np, pthread_mutexattr_setkind_np)
sewardj439d45e2002-05-03 20:43:10 +00001619
1620
1621/*--------------------------------------------------------------------*/
1622/*--- end vg_libpthread.c ---*/
1623/*--------------------------------------------------------------------*/