blob: 5e6e14c61ca9232265676fc86a5070e556a6d9ec [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/* ---------------------------------------------------
620 THREAD-SPECIFICs
621 ------------------------------------------------ */
sewardj5e5fa512002-04-14 13:13:05 +0000622
sewardj5905fae2002-04-26 13:25:00 +0000623int __pthread_key_create(pthread_key_t *key,
624 void (*destr_function) (void *))
sewardj5e5fa512002-04-14 13:13:05 +0000625{
sewardj5f07b662002-04-23 16:52:51 +0000626 int res;
627 ensure_valgrind("pthread_key_create");
628 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
629 VG_USERREQ__PTHREAD_KEY_CREATE,
630 key, destr_function, 0, 0);
631 return res;
sewardj5e5fa512002-04-14 13:13:05 +0000632}
633
634int pthread_key_delete(pthread_key_t key)
635{
sewardj436e0582002-04-26 14:31:40 +0000636 static int moans = N_MOANS;
637 if (moans-- > 0)
638 ignored("pthread_key_delete");
sewardj5e5fa512002-04-14 13:13:05 +0000639 return 0;
640}
641
sewardj5905fae2002-04-26 13:25:00 +0000642int __pthread_setspecific(pthread_key_t key, const void *pointer)
sewardj5e5fa512002-04-14 13:13:05 +0000643{
sewardj5f07b662002-04-23 16:52:51 +0000644 int res;
645 ensure_valgrind("pthread_setspecific");
646 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
647 VG_USERREQ__PTHREAD_SETSPECIFIC,
648 key, pointer, 0, 0);
649 return res;
sewardj5e5fa512002-04-14 13:13:05 +0000650}
651
sewardj5905fae2002-04-26 13:25:00 +0000652void * __pthread_getspecific(pthread_key_t key)
sewardj5e5fa512002-04-14 13:13:05 +0000653{
sewardj5f07b662002-04-23 16:52:51 +0000654 int res;
655 ensure_valgrind("pthread_getspecific");
656 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
657 VG_USERREQ__PTHREAD_GETSPECIFIC,
658 key, 0 , 0, 0);
659 return (void*)res;
sewardj5e5fa512002-04-14 13:13:05 +0000660}
661
sewardjf8f819e2002-04-17 23:21:37 +0000662
663/* ---------------------------------------------------
sewardj89d3d852002-04-24 19:21:39 +0000664 ONCEry
665 ------------------------------------------------ */
666
667static pthread_mutex_t once_masterlock = PTHREAD_MUTEX_INITIALIZER;
668
669
sewardj5905fae2002-04-26 13:25:00 +0000670int __pthread_once ( pthread_once_t *once_control,
671 void (*init_routine) (void) )
sewardj89d3d852002-04-24 19:21:39 +0000672{
673 int res;
674 ensure_valgrind("pthread_once");
675
sewardj68b2dd92002-05-10 21:03:56 +0000676 res = __pthread_mutex_lock(&once_masterlock);
sewardj89d3d852002-04-24 19:21:39 +0000677
sewardj68b2dd92002-05-10 21:03:56 +0000678 if (res != 0) {
679 printf("res = %d\n",res);
sewardj89d3d852002-04-24 19:21:39 +0000680 barf("pthread_once: Looks like your program's "
681 "init routine calls back to pthread_once() ?!");
sewardj68b2dd92002-05-10 21:03:56 +0000682 }
sewardj89d3d852002-04-24 19:21:39 +0000683
684 if (*once_control == 0) {
685 *once_control = 1;
686 init_routine();
687 }
688
sewardj68b2dd92002-05-10 21:03:56 +0000689 __pthread_mutex_unlock(&once_masterlock);
sewardj89d3d852002-04-24 19:21:39 +0000690
691 return 0;
692}
693
694
695/* ---------------------------------------------------
sewardj853f55d2002-04-26 00:27:53 +0000696 MISC
697 ------------------------------------------------ */
698
sewardj5905fae2002-04-26 13:25:00 +0000699int __pthread_atfork ( void (*prepare)(void),
700 void (*parent)(void),
701 void (*child)(void) )
sewardj853f55d2002-04-26 00:27:53 +0000702{
sewardj436e0582002-04-26 14:31:40 +0000703 static int moans = N_MOANS;
704 if (moans-- > 0)
705 ignored("pthread_atfork");
sewardj853f55d2002-04-26 00:27:53 +0000706 return 0;
707}
708
709
sewardjbb990782002-05-08 02:01:14 +0000710__attribute__((weak))
711void __pthread_initialize ( void )
712{
sewardjbea1caa2002-05-10 23:20:58 +0000713 ensure_valgrind("__pthread_initialize");
sewardjbb990782002-05-08 02:01:14 +0000714}
715
716
sewardj853f55d2002-04-26 00:27:53 +0000717/* ---------------------------------------------------
sewardj3b13f0e2002-04-25 20:17:29 +0000718 LIBRARY-PRIVATE THREAD SPECIFIC STATE
sewardjf8f819e2002-04-17 23:21:37 +0000719 ------------------------------------------------ */
720
sewardj3b13f0e2002-04-25 20:17:29 +0000721#include <resolv.h>
722static int thread_specific_errno[VG_N_THREADS];
723static int thread_specific_h_errno[VG_N_THREADS];
724static struct __res_state
725 thread_specific_res_state[VG_N_THREADS];
sewardjf8f819e2002-04-17 23:21:37 +0000726
sewardj3b13f0e2002-04-25 20:17:29 +0000727int* __errno_location ( void )
sewardjf8f819e2002-04-17 23:21:37 +0000728{
729 int tid;
sewardj3b13f0e2002-04-25 20:17:29 +0000730 /* ensure_valgrind("__errno_location"); */
731 VALGRIND_MAGIC_SEQUENCE(tid, 1 /* default */,
sewardjf8f819e2002-04-17 23:21:37 +0000732 VG_USERREQ__PTHREAD_GET_THREADID,
733 0, 0, 0, 0);
sewardj3b13f0e2002-04-25 20:17:29 +0000734 /* 'cos I'm paranoid ... */
sewardj439d45e2002-05-03 20:43:10 +0000735 if (tid < 1 || tid >= VG_N_THREADS)
sewardj3b13f0e2002-04-25 20:17:29 +0000736 barf("__errno_location: invalid ThreadId");
737 return & thread_specific_errno[tid];
738}
739
740int* __h_errno_location ( void )
741{
742 int tid;
743 /* ensure_valgrind("__h_errno_location"); */
744 VALGRIND_MAGIC_SEQUENCE(tid, 1 /* default */,
745 VG_USERREQ__PTHREAD_GET_THREADID,
746 0, 0, 0, 0);
747 /* 'cos I'm paranoid ... */
sewardj439d45e2002-05-03 20:43:10 +0000748 if (tid < 1 || tid >= VG_N_THREADS)
sewardj3b13f0e2002-04-25 20:17:29 +0000749 barf("__h_errno_location: invalid ThreadId");
750 return & thread_specific_h_errno[tid];
751}
752
753struct __res_state* __res_state ( void )
754{
755 int tid;
756 /* ensure_valgrind("__res_state"); */
757 VALGRIND_MAGIC_SEQUENCE(tid, 1 /* default */,
758 VG_USERREQ__PTHREAD_GET_THREADID,
759 0, 0, 0, 0);
760 /* 'cos I'm paranoid ... */
sewardj439d45e2002-05-03 20:43:10 +0000761 if (tid < 1 || tid >= VG_N_THREADS)
sewardj3b13f0e2002-04-25 20:17:29 +0000762 barf("__res_state: invalid ThreadId");
763 return & thread_specific_res_state[tid];
sewardjf8f819e2002-04-17 23:21:37 +0000764}
765
766
sewardj5716dbb2002-04-26 03:28:18 +0000767/* ---------------------------------------------------
768 LIBC-PRIVATE SPECIFIC DATA
769 ------------------------------------------------ */
770
771/* Relies on assumption that initial private data is NULL. This
772 should be fixed somehow. */
773
774/* The allowable keys (indices) (all 2 of them).
775 From sysdeps/pthread/bits/libc-tsd.h
776*/
sewardj70adeb22002-04-27 01:35:38 +0000777#define N_LIBC_TSD_EXTRA_KEYS 1
778
sewardj5716dbb2002-04-26 03:28:18 +0000779enum __libc_tsd_key_t { _LIBC_TSD_KEY_MALLOC = 0,
780 _LIBC_TSD_KEY_DL_ERROR,
781 _LIBC_TSD_KEY_N };
782
783/* Auto-initialising subsystem. libc_specifics_inited is set
784 after initialisation. libc_specifics_inited_mx guards it. */
785static int libc_specifics_inited = 0;
786static pthread_mutex_t libc_specifics_inited_mx = PTHREAD_MUTEX_INITIALIZER;
787
788/* These are the keys we must initialise the first time. */
sewardj70adeb22002-04-27 01:35:38 +0000789static pthread_key_t libc_specifics_keys[_LIBC_TSD_KEY_N
790 + N_LIBC_TSD_EXTRA_KEYS];
sewardj5716dbb2002-04-26 03:28:18 +0000791
792/* Initialise the keys, if they are not already initialise. */
793static
794void init_libc_tsd_keys ( void )
795{
796 int res, i;
797 pthread_key_t k;
798
799 res = pthread_mutex_lock(&libc_specifics_inited_mx);
800 if (res != 0) barf("init_libc_tsd_keys: lock");
801
802 if (libc_specifics_inited == 0) {
803 /* printf("INIT libc specifics\n"); */
804 libc_specifics_inited = 1;
sewardj70adeb22002-04-27 01:35:38 +0000805 for (i = 0; i < _LIBC_TSD_KEY_N + N_LIBC_TSD_EXTRA_KEYS; i++) {
sewardj5716dbb2002-04-26 03:28:18 +0000806 res = pthread_key_create(&k, NULL);
807 if (res != 0) barf("init_libc_tsd_keys: create");
808 libc_specifics_keys[i] = k;
809 }
810 }
811
812 res = pthread_mutex_unlock(&libc_specifics_inited_mx);
813 if (res != 0) barf("init_libc_tsd_keys: unlock");
814}
815
816
817static int
818libc_internal_tsd_set ( enum __libc_tsd_key_t key,
819 const void * pointer )
820{
sewardj70adeb22002-04-27 01:35:38 +0000821 int res;
822 static int moans = N_MOANS;
sewardj5716dbb2002-04-26 03:28:18 +0000823 /* printf("SET SET SET key %d ptr %p\n", key, pointer); */
sewardj70adeb22002-04-27 01:35:38 +0000824 if (key < _LIBC_TSD_KEY_MALLOC
825 || key >= _LIBC_TSD_KEY_N + N_LIBC_TSD_EXTRA_KEYS)
sewardj5716dbb2002-04-26 03:28:18 +0000826 barf("libc_internal_tsd_set: invalid key");
sewardj70adeb22002-04-27 01:35:38 +0000827 if (key >= _LIBC_TSD_KEY_N && moans-- > 0)
828 fprintf(stderr,
sewardj439d45e2002-05-03 20:43:10 +0000829 "valgrind's libpthread.so: libc_internal_tsd_set: "
830 "dubious key %d\n", key);
sewardj5716dbb2002-04-26 03:28:18 +0000831 init_libc_tsd_keys();
832 res = pthread_setspecific(libc_specifics_keys[key], pointer);
833 if (res != 0) barf("libc_internal_tsd_set: setspecific failed");
834 return 0;
835}
836
837static void *
838libc_internal_tsd_get ( enum __libc_tsd_key_t key )
839{
sewardj70adeb22002-04-27 01:35:38 +0000840 void* v;
841 static int moans = N_MOANS;
sewardj5716dbb2002-04-26 03:28:18 +0000842 /* printf("GET GET GET key %d\n", key); */
sewardj70adeb22002-04-27 01:35:38 +0000843 if (key < _LIBC_TSD_KEY_MALLOC
844 || key >= _LIBC_TSD_KEY_N + N_LIBC_TSD_EXTRA_KEYS)
sewardj5716dbb2002-04-26 03:28:18 +0000845 barf("libc_internal_tsd_get: invalid key");
sewardj70adeb22002-04-27 01:35:38 +0000846 if (key >= _LIBC_TSD_KEY_N && moans-- > 0)
847 fprintf(stderr,
sewardj439d45e2002-05-03 20:43:10 +0000848 "valgrind's libpthread.so: libc_internal_tsd_get: "
849 "dubious key %d\n", key);
sewardj5716dbb2002-04-26 03:28:18 +0000850 init_libc_tsd_keys();
851 v = pthread_getspecific(libc_specifics_keys[key]);
852 /* if (v == NULL) barf("libc_internal_tsd_set: getspecific failed"); */
853 return v;
854}
855
856
857
858
sewardj70adeb22002-04-27 01:35:38 +0000859int (*__libc_internal_tsd_set)
860 (enum __libc_tsd_key_t key, const void * pointer)
861 = libc_internal_tsd_set;
sewardj5716dbb2002-04-26 03:28:18 +0000862
sewardj70adeb22002-04-27 01:35:38 +0000863void* (*__libc_internal_tsd_get)
864 (enum __libc_tsd_key_t key)
865 = libc_internal_tsd_get;
sewardj5716dbb2002-04-26 03:28:18 +0000866
867
sewardje663cb92002-04-12 10:26:32 +0000868/* ---------------------------------------------------------------------
869 These are here (I think) because they are deemed cancellation
870 points by POSIX. For the moment we'll simply pass the call along
871 to the corresponding thread-unaware (?) libc routine.
872 ------------------------------------------------------------------ */
873
sewardje663cb92002-04-12 10:26:32 +0000874#include <stdlib.h>
875#include <signal.h>
sewardje663cb92002-04-12 10:26:32 +0000876#include <sys/types.h>
877#include <sys/socket.h>
878
sewardjd529a442002-05-04 19:49:21 +0000879#ifdef GLIBC_2_1
880extern
881int __sigaction
882 (int signum,
883 const struct sigaction *act,
884 struct sigaction *oldact);
885#else
sewardje663cb92002-04-12 10:26:32 +0000886extern
887int __libc_sigaction
888 (int signum,
889 const struct sigaction *act,
890 struct sigaction *oldact);
sewardjd529a442002-05-04 19:49:21 +0000891#endif
sewardje663cb92002-04-12 10:26:32 +0000892int sigaction(int signum,
893 const struct sigaction *act,
894 struct sigaction *oldact)
895{
sewardj2a1dcce2002-04-22 12:45:25 +0000896# ifdef GLIBC_2_1
897 return __sigaction(signum, act, oldact);
898# else
sewardj45b4b372002-04-16 22:50:32 +0000899 return __libc_sigaction(signum, act, oldact);
sewardj2a1dcce2002-04-22 12:45:25 +0000900# endif
sewardje663cb92002-04-12 10:26:32 +0000901}
902
903
904extern
905int __libc_connect(int sockfd,
906 const struct sockaddr *serv_addr,
907 socklen_t addrlen);
sewardj5905fae2002-04-26 13:25:00 +0000908__attribute__((weak))
sewardje663cb92002-04-12 10:26:32 +0000909int connect(int sockfd,
910 const struct sockaddr *serv_addr,
911 socklen_t addrlen)
912{
sewardj45b4b372002-04-16 22:50:32 +0000913 return __libc_connect(sockfd, serv_addr, addrlen);
sewardje663cb92002-04-12 10:26:32 +0000914}
915
916
917extern
918int __libc_fcntl(int fd, int cmd, long arg);
sewardj5905fae2002-04-26 13:25:00 +0000919__attribute__((weak))
sewardje663cb92002-04-12 10:26:32 +0000920int fcntl(int fd, int cmd, long arg)
921{
sewardj45b4b372002-04-16 22:50:32 +0000922 return __libc_fcntl(fd, cmd, arg);
sewardje663cb92002-04-12 10:26:32 +0000923}
924
925
926extern
927ssize_t __libc_write(int fd, const void *buf, size_t count);
sewardj5905fae2002-04-26 13:25:00 +0000928__attribute__((weak))
sewardje663cb92002-04-12 10:26:32 +0000929ssize_t write(int fd, const void *buf, size_t count)
930{
sewardj45b4b372002-04-16 22:50:32 +0000931 return __libc_write(fd, buf, count);
sewardje663cb92002-04-12 10:26:32 +0000932}
933
934
935extern
936ssize_t __libc_read(int fd, void *buf, size_t count);
sewardj5905fae2002-04-26 13:25:00 +0000937__attribute__((weak))
sewardje663cb92002-04-12 10:26:32 +0000938ssize_t read(int fd, void *buf, size_t count)
939{
sewardj45b4b372002-04-16 22:50:32 +0000940 return __libc_read(fd, buf, count);
sewardje663cb92002-04-12 10:26:32 +0000941}
942
sewardjbe32e452002-04-24 20:29:58 +0000943
944extern
sewardj853f55d2002-04-26 00:27:53 +0000945int __libc_open64(const char *pathname, int flags, mode_t mode);
sewardj5905fae2002-04-26 13:25:00 +0000946__attribute__((weak))
sewardj853f55d2002-04-26 00:27:53 +0000947int open64(const char *pathname, int flags, mode_t mode)
sewardjbe32e452002-04-24 20:29:58 +0000948{
sewardj853f55d2002-04-26 00:27:53 +0000949 return __libc_open64(pathname, flags, mode);
sewardjbe32e452002-04-24 20:29:58 +0000950}
951
sewardje663cb92002-04-12 10:26:32 +0000952
953extern
sewardj853f55d2002-04-26 00:27:53 +0000954int __libc_open(const char *pathname, int flags, mode_t mode);
sewardj5905fae2002-04-26 13:25:00 +0000955__attribute__((weak))
sewardj853f55d2002-04-26 00:27:53 +0000956int open(const char *pathname, int flags, mode_t mode)
sewardje663cb92002-04-12 10:26:32 +0000957{
sewardj853f55d2002-04-26 00:27:53 +0000958 return __libc_open(pathname, flags, mode);
sewardje663cb92002-04-12 10:26:32 +0000959}
960
961
962extern
963int __libc_close(int fd);
sewardj5905fae2002-04-26 13:25:00 +0000964__attribute__((weak))
sewardje663cb92002-04-12 10:26:32 +0000965int close(int fd)
966{
sewardj45b4b372002-04-16 22:50:32 +0000967 return __libc_close(fd);
sewardje663cb92002-04-12 10:26:32 +0000968}
969
970
971extern
972int __libc_accept(int s, struct sockaddr *addr, socklen_t *addrlen);
sewardj5905fae2002-04-26 13:25:00 +0000973__attribute__((weak))
sewardje663cb92002-04-12 10:26:32 +0000974int accept(int s, struct sockaddr *addr, socklen_t *addrlen)
975{
sewardj45b4b372002-04-16 22:50:32 +0000976 return __libc_accept(s, addr, addrlen);
sewardje663cb92002-04-12 10:26:32 +0000977}
978
979
980extern
981pid_t __libc_fork(void);
sewardj5905fae2002-04-26 13:25:00 +0000982pid_t __fork(void)
sewardje663cb92002-04-12 10:26:32 +0000983{
sewardj45b4b372002-04-16 22:50:32 +0000984 return __libc_fork();
sewardje663cb92002-04-12 10:26:32 +0000985}
986
987
988extern
989pid_t __libc_waitpid(pid_t pid, int *status, int options);
sewardj5905fae2002-04-26 13:25:00 +0000990__attribute__((weak))
sewardje663cb92002-04-12 10:26:32 +0000991pid_t waitpid(pid_t pid, int *status, int options)
992{
sewardj45b4b372002-04-16 22:50:32 +0000993 return __libc_waitpid(pid, status, options);
sewardje663cb92002-04-12 10:26:32 +0000994}
995
996
997extern
998int __libc_nanosleep(const struct timespec *req, struct timespec *rem);
sewardj5905fae2002-04-26 13:25:00 +0000999__attribute__((weak))
sewardje663cb92002-04-12 10:26:32 +00001000int nanosleep(const struct timespec *req, struct timespec *rem)
1001{
1002 return __libc_nanosleep(req, rem);
1003}
1004
sewardjbe32e452002-04-24 20:29:58 +00001005
sewardje663cb92002-04-12 10:26:32 +00001006extern
1007int __libc_fsync(int fd);
sewardj5905fae2002-04-26 13:25:00 +00001008__attribute__((weak))
sewardje663cb92002-04-12 10:26:32 +00001009int fsync(int fd)
1010{
sewardj45b4b372002-04-16 22:50:32 +00001011 return __libc_fsync(fd);
sewardje663cb92002-04-12 10:26:32 +00001012}
1013
sewardjbe32e452002-04-24 20:29:58 +00001014
sewardj70c75362002-04-13 04:18:32 +00001015extern
1016off_t __libc_lseek(int fildes, off_t offset, int whence);
sewardj5905fae2002-04-26 13:25:00 +00001017__attribute__((weak))
sewardj70c75362002-04-13 04:18:32 +00001018off_t lseek(int fildes, off_t offset, int whence)
1019{
sewardj45b4b372002-04-16 22:50:32 +00001020 return __libc_lseek(fildes, offset, whence);
sewardj70c75362002-04-13 04:18:32 +00001021}
1022
sewardjbe32e452002-04-24 20:29:58 +00001023
1024extern
1025__off64_t __libc_lseek64(int fildes, __off64_t offset, int whence);
sewardj5905fae2002-04-26 13:25:00 +00001026__attribute__((weak))
sewardjbe32e452002-04-24 20:29:58 +00001027__off64_t lseek64(int fildes, __off64_t offset, int whence)
1028{
1029 return __libc_lseek64(fildes, offset, whence);
1030}
1031
1032
sewardj6af4b5d2002-04-16 04:40:49 +00001033extern
1034void __libc_longjmp(jmp_buf env, int val) __attribute((noreturn));
sewardj5905fae2002-04-26 13:25:00 +00001035/* not weak: __attribute__((weak)) */
sewardj6af4b5d2002-04-16 04:40:49 +00001036void longjmp(jmp_buf env, int val)
1037{
1038 __libc_longjmp(env, val);
1039}
1040
sewardjbe32e452002-04-24 20:29:58 +00001041
sewardj6af4b5d2002-04-16 04:40:49 +00001042extern
1043int __libc_send(int s, const void *msg, size_t len, int flags);
sewardj5905fae2002-04-26 13:25:00 +00001044__attribute__((weak))
sewardj6af4b5d2002-04-16 04:40:49 +00001045int send(int s, const void *msg, size_t len, int flags)
1046{
1047 return __libc_send(s, msg, len, flags);
1048}
1049
sewardjbe32e452002-04-24 20:29:58 +00001050
sewardj1e8cdc92002-04-18 11:37:52 +00001051extern
1052int __libc_recv(int s, void *buf, size_t len, int flags);
sewardj5905fae2002-04-26 13:25:00 +00001053__attribute__((weak))
sewardj1e8cdc92002-04-18 11:37:52 +00001054int recv(int s, void *buf, size_t len, int flags)
1055{
1056 return __libc_recv(s, buf, len, flags);
1057}
1058
sewardjbe32e452002-04-24 20:29:58 +00001059
sewardj796d6a22002-04-24 02:28:34 +00001060extern
sewardj436e0582002-04-26 14:31:40 +00001061int __libc_recvfrom(int s, void *buf, size_t len, int flags,
1062 struct sockaddr *from, socklen_t *fromlen);
1063__attribute__((weak))
1064int recvfrom(int s, void *buf, size_t len, int flags,
1065 struct sockaddr *from, socklen_t *fromlen)
1066{
1067 return __libc_recvfrom(s, buf, len, flags, from, fromlen);
1068}
1069
1070
1071extern
sewardj796d6a22002-04-24 02:28:34 +00001072int __libc_sendto(int s, const void *msg, size_t len, int flags,
1073 const struct sockaddr *to, socklen_t tolen);
sewardj5905fae2002-04-26 13:25:00 +00001074__attribute__((weak))
sewardj796d6a22002-04-24 02:28:34 +00001075int sendto(int s, const void *msg, size_t len, int flags,
1076 const struct sockaddr *to, socklen_t tolen)
1077{
1078 return __libc_sendto(s, msg, len, flags, to, tolen);
1079}
1080
sewardjbe32e452002-04-24 20:29:58 +00001081
sewardj369b1702002-04-24 13:28:15 +00001082extern
1083int __libc_system(const char* str);
sewardj5905fae2002-04-26 13:25:00 +00001084__attribute__((weak))
sewardj369b1702002-04-24 13:28:15 +00001085int system(const char* str)
1086{
1087 return __libc_system(str);
1088}
1089
sewardjbe32e452002-04-24 20:29:58 +00001090
sewardjab0b1c32002-04-24 19:26:47 +00001091extern
1092pid_t __libc_wait(int *status);
sewardj5905fae2002-04-26 13:25:00 +00001093__attribute__((weak))
sewardjab0b1c32002-04-24 19:26:47 +00001094pid_t wait(int *status)
1095{
1096 return __libc_wait(status);
1097}
1098
sewardj45b4b372002-04-16 22:50:32 +00001099
sewardj5905fae2002-04-26 13:25:00 +00001100
sewardj3b13f0e2002-04-25 20:17:29 +00001101/* ---------------------------------------------------------------------
1102 Nonblocking implementations of select() and poll(). This stuff will
1103 surely rot your mind.
1104 ------------------------------------------------------------------ */
sewardje663cb92002-04-12 10:26:32 +00001105
sewardj08a4c3f2002-04-13 03:45:44 +00001106/*--------------------------------------------------*/
1107
1108#include "vg_kerneliface.h"
1109
1110static
1111__inline__
1112int is_kerror ( int res )
1113{
1114 if (res >= -4095 && res <= -1)
1115 return 1;
1116 else
1117 return 0;
1118}
1119
1120
1121static
1122int my_do_syscall1 ( int syscallno, int arg1 )
1123{
1124 int __res;
1125 __asm__ volatile ("pushl %%ebx; movl %%edx,%%ebx ; int $0x80 ; popl %%ebx"
1126 : "=a" (__res)
1127 : "0" (syscallno),
1128 "d" (arg1) );
1129 return __res;
1130}
1131
1132static
1133int my_do_syscall2 ( int syscallno,
sewardjf854f472002-04-21 12:19:41 +00001134 int arg1, int arg2 )
sewardj08a4c3f2002-04-13 03:45:44 +00001135{
1136 int __res;
1137 __asm__ volatile ("pushl %%ebx; movl %%edx,%%ebx ; int $0x80 ; popl %%ebx"
1138 : "=a" (__res)
1139 : "0" (syscallno),
1140 "d" (arg1),
1141 "c" (arg2) );
1142 return __res;
1143}
1144
1145static
sewardjf854f472002-04-21 12:19:41 +00001146int my_do_syscall3 ( int syscallno,
1147 int arg1, int arg2, int arg3 )
1148{
1149 int __res;
1150 __asm__ volatile ("pushl %%ebx; movl %%esi,%%ebx ; int $0x80 ; popl %%ebx"
1151 : "=a" (__res)
1152 : "0" (syscallno),
1153 "S" (arg1),
1154 "c" (arg2),
1155 "d" (arg3) );
1156 return __res;
1157}
1158
1159static
sewardj08a4c3f2002-04-13 03:45:44 +00001160int do_syscall_select( int n,
1161 vki_fd_set* readfds,
1162 vki_fd_set* writefds,
1163 vki_fd_set* exceptfds,
1164 struct vki_timeval * timeout )
1165{
1166 int res;
1167 int args[5];
1168 args[0] = n;
1169 args[1] = (int)readfds;
1170 args[2] = (int)writefds;
1171 args[3] = (int)exceptfds;
1172 args[4] = (int)timeout;
1173 res = my_do_syscall1(__NR_select, (int)(&(args[0])) );
sewardj02535bc2002-04-21 01:08:26 +00001174 return res;
sewardj08a4c3f2002-04-13 03:45:44 +00001175}
1176
1177
1178/* This is a wrapper round select(), which makes it thread-safe,
1179 meaning that only this thread will block, rather than the entire
1180 process. This wrapper in turn depends on nanosleep() not to block
1181 the entire process, but I think (hope? suspect?) that POSIX
1182 pthreads guarantees that to be the case.
1183
1184 Basic idea is: modify the timeout parameter to select so that it
1185 returns immediately. Poll like this until select returns non-zero,
1186 indicating something interesting happened, or until our time is up.
1187 Space out the polls with nanosleeps of say 20 milliseconds, which
1188 is required to be nonblocking; this allows other threads to run.
sewardj02535bc2002-04-21 01:08:26 +00001189
1190 Assumes:
1191 * (checked via assert) types fd_set and vki_fd_set are identical.
1192 * (checked via assert) types timeval and vki_timeval are identical.
1193 * (unchecked) libc error numbers (EINTR etc) are the negation of the
1194 kernel's error numbers (VKI_EINTR etc).
sewardj08a4c3f2002-04-13 03:45:44 +00001195*/
sewardj08a4c3f2002-04-13 03:45:44 +00001196
sewardj5905fae2002-04-26 13:25:00 +00001197/* __attribute__((weak)) */
sewardj08a4c3f2002-04-13 03:45:44 +00001198int select ( int n,
1199 fd_set *rfds,
1200 fd_set *wfds,
1201 fd_set *xfds,
1202 struct timeval *timeout )
1203{
sewardj5f07b662002-04-23 16:52:51 +00001204 unsigned int ms_now, ms_end;
sewardj08a4c3f2002-04-13 03:45:44 +00001205 int res;
1206 fd_set rfds_copy;
1207 fd_set wfds_copy;
1208 fd_set xfds_copy;
1209 struct vki_timeval t_now;
sewardj08a4c3f2002-04-13 03:45:44 +00001210 struct vki_timeval zero_timeout;
1211 struct vki_timespec nanosleep_interval;
1212
sewardj5f07b662002-04-23 16:52:51 +00001213 /* gcc's complains about ms_end being used uninitialised -- classic
1214 case it can't understand, where ms_end is both defined and used
1215 only if timeout != NULL. Hence ... */
1216 ms_end = 0;
sewardj08a4c3f2002-04-13 03:45:44 +00001217
1218 /* We assume that the kernel and libc data layouts are identical
1219 for the following types. These asserts provide a crude
1220 check. */
1221 if (sizeof(fd_set) != sizeof(vki_fd_set)
1222 || sizeof(struct timeval) != sizeof(struct vki_timeval))
1223 barf("valgrind's hacky non-blocking select(): data sizes error");
1224
sewardj5f07b662002-04-23 16:52:51 +00001225 /* Detect the current time and simultaneously find out if we are
1226 running on Valgrind. */
1227 VALGRIND_MAGIC_SEQUENCE(ms_now, 0xFFFFFFFF /* default */,
1228 VG_USERREQ__READ_MILLISECOND_TIMER,
1229 0, 0, 0, 0);
1230
1231 /* If a zero timeout specified, this call is harmless. Also go
1232 this route if we're not running on Valgrind, for whatever
1233 reason. */
1234 if ( (timeout && timeout->tv_sec == 0 && timeout->tv_usec == 0)
1235 || (ms_now == 0xFFFFFFFF) ) {
sewardj02535bc2002-04-21 01:08:26 +00001236 res = do_syscall_select( n, (vki_fd_set*)rfds,
sewardj08a4c3f2002-04-13 03:45:44 +00001237 (vki_fd_set*)wfds,
1238 (vki_fd_set*)xfds,
1239 (struct vki_timeval*)timeout);
sewardj02535bc2002-04-21 01:08:26 +00001240 if (is_kerror(res)) {
1241 * (__errno_location()) = -res;
1242 return -1;
1243 } else {
1244 return res;
1245 }
1246 }
sewardj08a4c3f2002-04-13 03:45:44 +00001247
sewardj5f07b662002-04-23 16:52:51 +00001248 /* If a timeout was specified, set ms_end to be the end millisecond
1249 counter [wallclock] time. */
sewardj08a4c3f2002-04-13 03:45:44 +00001250 if (timeout) {
1251 res = my_do_syscall2(__NR_gettimeofday, (int)&t_now, (int)NULL);
1252 assert(res == 0);
sewardj5f07b662002-04-23 16:52:51 +00001253 ms_end = ms_now;
1254 ms_end += (timeout->tv_usec / 1000);
1255 ms_end += (timeout->tv_sec * 1000);
sewardj08a4c3f2002-04-13 03:45:44 +00001256 /* Stay sane ... */
sewardj5f07b662002-04-23 16:52:51 +00001257 assert (ms_end >= ms_now);
sewardj08a4c3f2002-04-13 03:45:44 +00001258 }
1259
1260 /* fprintf(stderr, "MY_SELECT: before loop\n"); */
1261
1262 /* Either timeout == NULL, meaning wait indefinitely, or timeout !=
sewardj5f07b662002-04-23 16:52:51 +00001263 NULL, in which case ms_end holds the end time. */
sewardj08a4c3f2002-04-13 03:45:44 +00001264 while (1) {
1265 if (timeout) {
sewardj5f07b662002-04-23 16:52:51 +00001266 VALGRIND_MAGIC_SEQUENCE(ms_now, 0xFFFFFFFF /* default */,
1267 VG_USERREQ__READ_MILLISECOND_TIMER,
1268 0, 0, 0, 0);
1269 assert(ms_now != 0xFFFFFFFF);
1270 if (ms_now >= ms_end) {
sewardj08a4c3f2002-04-13 03:45:44 +00001271 /* timeout; nothing interesting happened. */
1272 if (rfds) FD_ZERO(rfds);
1273 if (wfds) FD_ZERO(wfds);
1274 if (xfds) FD_ZERO(xfds);
1275 return 0;
1276 }
1277 }
1278
1279 /* These could be trashed each time round the loop, so restore
1280 them each time. */
1281 if (rfds) rfds_copy = *rfds;
1282 if (wfds) wfds_copy = *wfds;
1283 if (xfds) xfds_copy = *xfds;
1284
1285 zero_timeout.tv_sec = zero_timeout.tv_usec = 0;
1286
1287 res = do_syscall_select( n,
1288 rfds ? (vki_fd_set*)(&rfds_copy) : NULL,
1289 wfds ? (vki_fd_set*)(&wfds_copy) : NULL,
1290 xfds ? (vki_fd_set*)(&xfds_copy) : NULL,
1291 & zero_timeout );
sewardj02535bc2002-04-21 01:08:26 +00001292 if (is_kerror(res)) {
1293 /* Some kind of error (including EINTR). Set errno and
sewardj08a4c3f2002-04-13 03:45:44 +00001294 return. The sets are unspecified in this case. */
sewardj02535bc2002-04-21 01:08:26 +00001295 * (__errno_location()) = -res;
1296 return -1;
sewardj08a4c3f2002-04-13 03:45:44 +00001297 }
1298 if (res > 0) {
1299 /* one or more fds is ready. Copy out resulting sets and
1300 return. */
1301 if (rfds) *rfds = rfds_copy;
1302 if (wfds) *wfds = wfds_copy;
1303 if (xfds) *xfds = xfds_copy;
1304 return res;
1305 }
1306 /* fprintf(stderr, "MY_SELECT: nanosleep\n"); */
1307 /* nanosleep and go round again */
sewardj02535bc2002-04-21 01:08:26 +00001308 nanosleep_interval.tv_sec = 0;
sewardj956cc1b2002-04-25 01:33:50 +00001309 nanosleep_interval.tv_nsec = 50 * 1000 * 1000; /* 50 milliseconds */
sewardjf854f472002-04-21 12:19:41 +00001310 /* It's critical here that valgrind's nanosleep implementation
1311 is nonblocking. */
1312 (void)my_do_syscall2(__NR_nanosleep,
1313 (int)(&nanosleep_interval), (int)NULL);
1314 }
1315}
1316
1317
1318
1319
1320#include <sys/poll.h>
1321
sewardj72d58482002-04-24 02:20:20 +00001322#ifdef GLIBC_2_1
1323typedef unsigned long int nfds_t;
1324#endif
1325
sewardj5905fae2002-04-26 13:25:00 +00001326/* __attribute__((weak)) */
sewardjf854f472002-04-21 12:19:41 +00001327int poll (struct pollfd *__fds, nfds_t __nfds, int __timeout)
1328{
sewardj5f07b662002-04-23 16:52:51 +00001329 unsigned int ms_now, ms_end;
sewardjf854f472002-04-21 12:19:41 +00001330 int res, i;
sewardjf854f472002-04-21 12:19:41 +00001331 struct vki_timespec nanosleep_interval;
1332
1333 ensure_valgrind("poll");
1334
sewardj5f07b662002-04-23 16:52:51 +00001335 /* Detect the current time and simultaneously find out if we are
1336 running on Valgrind. */
1337 VALGRIND_MAGIC_SEQUENCE(ms_now, 0xFFFFFFFF /* default */,
1338 VG_USERREQ__READ_MILLISECOND_TIMER,
1339 0, 0, 0, 0);
1340
sewardjf854f472002-04-21 12:19:41 +00001341 if (/* CHECK SIZES FOR struct pollfd */
1342 sizeof(struct timeval) != sizeof(struct vki_timeval))
1343 barf("valgrind's hacky non-blocking poll(): data sizes error");
1344
sewardj5f07b662002-04-23 16:52:51 +00001345 /* dummy initialisation to keep gcc -Wall happy */
1346 ms_end = 0;
1347
1348 /* If a zero timeout specified, this call is harmless. Also do
1349 this if not running on Valgrind. */
1350 if (__timeout == 0 || ms_now == 0xFFFFFFFF) {
sewardjf854f472002-04-21 12:19:41 +00001351 res = my_do_syscall3(__NR_poll, (int)__fds, __nfds, __timeout);
1352 if (is_kerror(res)) {
1353 * (__errno_location()) = -res;
1354 return -1;
1355 } else {
1356 return res;
1357 }
1358 }
1359
sewardj5f07b662002-04-23 16:52:51 +00001360 /* If a timeout was specified, set ms_end to be the end wallclock
1361 time. Easy considering that __timeout is in milliseconds. */
sewardjf854f472002-04-21 12:19:41 +00001362 if (__timeout > 0) {
sewardj650ac002002-04-29 12:20:34 +00001363 ms_end = ms_now + (unsigned int)__timeout;
sewardjf854f472002-04-21 12:19:41 +00001364 }
1365
1366 /* fprintf(stderr, "MY_POLL: before loop\n"); */
1367
1368 /* Either timeout < 0, meaning wait indefinitely, or timeout > 0,
1369 in which case t_end holds the end time. */
sewardj5f07b662002-04-23 16:52:51 +00001370 assert(__timeout != 0);
1371
sewardjf854f472002-04-21 12:19:41 +00001372 while (1) {
sewardjf854f472002-04-21 12:19:41 +00001373 if (__timeout > 0) {
sewardj5f07b662002-04-23 16:52:51 +00001374 VALGRIND_MAGIC_SEQUENCE(ms_now, 0xFFFFFFFF /* default */,
1375 VG_USERREQ__READ_MILLISECOND_TIMER,
1376 0, 0, 0, 0);
1377 assert(ms_now != 0xFFFFFFFF);
1378 if (ms_now >= ms_end) {
sewardjf854f472002-04-21 12:19:41 +00001379 /* timeout; nothing interesting happened. */
1380 for (i = 0; i < __nfds; i++)
1381 __fds[i].revents = 0;
1382 return 0;
1383 }
1384 }
1385
sewardj5f07b662002-04-23 16:52:51 +00001386 /* Do a return-immediately poll. */
sewardjf854f472002-04-21 12:19:41 +00001387 res = my_do_syscall3(__NR_poll, (int)__fds, __nfds, 0 );
1388 if (is_kerror(res)) {
1389 /* Some kind of error. Set errno and return. */
1390 * (__errno_location()) = -res;
1391 return -1;
1392 }
1393 if (res > 0) {
1394 /* One or more fds is ready. Return now. */
1395 return res;
1396 }
1397 /* fprintf(stderr, "MY_POLL: nanosleep\n"); */
1398 /* nanosleep and go round again */
1399 nanosleep_interval.tv_sec = 0;
sewardj956cc1b2002-04-25 01:33:50 +00001400 nanosleep_interval.tv_nsec = 51 * 1000 * 1000; /* 51 milliseconds */
sewardj08a4c3f2002-04-13 03:45:44 +00001401 /* It's critical here that valgrind's nanosleep implementation
1402 is nonblocking. */
1403 (void)my_do_syscall2(__NR_nanosleep,
1404 (int)(&nanosleep_interval), (int)NULL);
1405 }
1406}
sewardj3b13f0e2002-04-25 20:17:29 +00001407
1408
1409/* ---------------------------------------------------------------------
1410 B'stard.
1411 ------------------------------------------------------------------ */
1412
1413# define strong_alias(name, aliasname) \
1414 extern __typeof (name) aliasname __attribute__ ((alias (#name)));
1415
sewardj5905fae2002-04-26 13:25:00 +00001416# define weak_alias(name, aliasname) \
1417 extern __typeof (name) aliasname __attribute__ ((weak, alias (#name)));
sewardj3b13f0e2002-04-25 20:17:29 +00001418
sewardj5905fae2002-04-26 13:25:00 +00001419strong_alias(__pthread_mutex_lock, pthread_mutex_lock)
1420strong_alias(__pthread_mutex_trylock, pthread_mutex_trylock)
1421strong_alias(__pthread_mutex_unlock, pthread_mutex_unlock)
1422strong_alias(__pthread_mutexattr_init, pthread_mutexattr_init)
1423 weak_alias(__pthread_mutexattr_settype, pthread_mutexattr_settype)
1424strong_alias(__pthread_mutex_init, pthread_mutex_init)
1425strong_alias(__pthread_mutexattr_destroy, pthread_mutexattr_destroy)
1426strong_alias(__pthread_mutex_destroy, pthread_mutex_destroy)
1427strong_alias(__pthread_once, pthread_once)
1428strong_alias(__pthread_atfork, pthread_atfork)
1429strong_alias(__pthread_key_create, pthread_key_create)
1430strong_alias(__pthread_getspecific, pthread_getspecific)
1431strong_alias(__pthread_setspecific, pthread_setspecific)
1432
sewardjd529a442002-05-04 19:49:21 +00001433#ifndef GLIBC_2_1
sewardj3b13f0e2002-04-25 20:17:29 +00001434strong_alias(sigaction, __sigaction)
sewardjd529a442002-05-04 19:49:21 +00001435#endif
1436
sewardj5905fae2002-04-26 13:25:00 +00001437strong_alias(close, __close)
sewardj3b13f0e2002-04-25 20:17:29 +00001438strong_alias(fcntl, __fcntl)
sewardj5905fae2002-04-26 13:25:00 +00001439strong_alias(lseek, __lseek)
1440strong_alias(open, __open)
1441strong_alias(open64, __open64)
1442//strong_alias(pread64, __pread64)
1443//strong_alias(pwrite64, __pwrite64)
1444strong_alias(read, __read)
1445strong_alias(wait, __wait)
1446strong_alias(write, __write)
sewardj3b13f0e2002-04-25 20:17:29 +00001447strong_alias(connect, __connect)
sewardj5905fae2002-04-26 13:25:00 +00001448strong_alias(send, __send)
1449
1450weak_alias(__fork, fork)
1451//weak_alias(__vfork, vfork)
1452
sewardj3b13f0e2002-04-25 20:17:29 +00001453
1454/*--------------------------------------------------*/
1455
sewardj5716dbb2002-04-26 03:28:18 +00001456int
1457pthread_rwlock_rdlock (void* /* pthread_rwlock_t* */ rwlock)
1458{
sewardj436e0582002-04-26 14:31:40 +00001459 static int moans = N_MOANS;
1460 if (moans-- > 0)
1461 kludged("pthread_rwlock_rdlock");
sewardj5716dbb2002-04-26 03:28:18 +00001462 return 0;
1463}
1464
sewardj5905fae2002-04-26 13:25:00 +00001465weak_alias(pthread_rwlock_rdlock, __pthread_rwlock_rdlock)
sewardj5716dbb2002-04-26 03:28:18 +00001466
1467
1468int
1469pthread_rwlock_unlock (void* /* pthread_rwlock_t* */ rwlock)
1470{
sewardj436e0582002-04-26 14:31:40 +00001471 static int moans = N_MOANS;
1472 if (moans-- > 0)
1473 kludged("pthread_rwlock_unlock");
sewardj5716dbb2002-04-26 03:28:18 +00001474 return 0;
1475}
1476
sewardj5905fae2002-04-26 13:25:00 +00001477weak_alias(pthread_rwlock_unlock, __pthread_rwlock_unlock)
sewardj5716dbb2002-04-26 03:28:18 +00001478
1479
sewardj060b04f2002-04-26 21:01:13 +00001480int
1481pthread_rwlock_wrlock (void* /* pthread_rwlock_t* */ rwlock)
1482{
1483 static int moans = N_MOANS;
1484 if (moans-- > 0)
1485 kludged("pthread_rwlock_wrlock");
1486 return 0;
1487}
1488
sewardj262b0292002-05-01 00:03:16 +00001489weak_alias(pthread_rwlock_wrlock, __pthread_rwlock_wrlock)
sewardj060b04f2002-04-26 21:01:13 +00001490
1491
sewardj3b13f0e2002-04-25 20:17:29 +00001492/* I've no idea what these are, but they get called quite a lot.
1493 Anybody know? */
1494
1495#undef _IO_flockfile
1496void _IO_flockfile ( _IO_FILE * file )
1497{
sewardj853f55d2002-04-26 00:27:53 +00001498 pthread_mutex_lock(file->_lock);
sewardj3b13f0e2002-04-25 20:17:29 +00001499}
sewardj5905fae2002-04-26 13:25:00 +00001500weak_alias(_IO_flockfile, flockfile);
1501
sewardj3b13f0e2002-04-25 20:17:29 +00001502
1503#undef _IO_funlockfile
1504void _IO_funlockfile ( _IO_FILE * file )
1505{
sewardj853f55d2002-04-26 00:27:53 +00001506 pthread_mutex_unlock(file->_lock);
sewardj3b13f0e2002-04-25 20:17:29 +00001507}
sewardj5905fae2002-04-26 13:25:00 +00001508weak_alias(_IO_funlockfile, funlockfile);
1509
sewardj3b13f0e2002-04-25 20:17:29 +00001510
1511void _pthread_cleanup_push_defer ( void )
1512{
sewardj439d45e2002-05-03 20:43:10 +00001513 static int moans = N_MOANS;
1514 if (moans-- > 0)
1515 ignored("_pthread_cleanup_push_defer");
sewardj3b13f0e2002-04-25 20:17:29 +00001516}
1517
1518void _pthread_cleanup_pop_restore ( void )
1519{
sewardj439d45e2002-05-03 20:43:10 +00001520 static int moans = N_MOANS;
1521 if (moans-- > 0)
1522 ignored("_pthread_cleanup_pop_restore");
sewardj3b13f0e2002-04-25 20:17:29 +00001523}
sewardjd4f2c712002-04-30 10:20:10 +00001524
sewardj60e38422002-05-08 14:08:22 +00001525/*--------*/
1526void _pthread_cleanup_push (struct _pthread_cleanup_buffer *__buffer,
1527 void (*__routine) (void *),
1528 void *__arg)
1529{
1530 static int moans = N_MOANS;
1531 if (moans-- > 0)
1532 ignored("_pthread_cleanup_push");
1533}
1534
1535void _pthread_cleanup_pop (struct _pthread_cleanup_buffer *__buffer,
1536 int __execute)
1537{
1538 static int moans = N_MOANS;
1539 if (moans-- > 0) {
1540 if (__execute)
1541 ignored("_pthread_cleanup_pop-EXECUTE");
1542 else
1543 ignored("_pthread_cleanup_pop-NO-EXECUTE");
1544 }
1545}
1546
sewardjd4f2c712002-04-30 10:20:10 +00001547
1548/* This doesn't seem to be needed to simulate libpthread.so's external
1549 interface, but many people complain about its absence. */
1550
1551strong_alias(__pthread_mutexattr_settype, __pthread_mutexattr_setkind_np)
1552weak_alias(__pthread_mutexattr_setkind_np, pthread_mutexattr_setkind_np)
sewardj439d45e2002-05-03 20:43:10 +00001553
1554
1555/*--------------------------------------------------------------------*/
1556/*--- end vg_libpthread.c ---*/
1557/*--------------------------------------------------------------------*/