blob: e0f480669aebb96bd577ab72a422efca6ca863dd [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
sewardj3665ded2002-05-16 16:57:25 +0000686/* Copied verbatim from Linuxthreads */
687/* Redefine raise() to send signal to calling thread only,
688 as per POSIX 1003.1c */
689int raise (int sig)
690{
691 int retcode = pthread_kill(pthread_self(), sig);
692 if (retcode == 0)
693 return 0;
694 else {
695 errno = retcode;
696 return -1;
697 }
698}
699
700
sewardjb48e5002002-05-13 00:16:03 +0000701/* ---------------------------------------------------
sewardjf8f819e2002-04-17 23:21:37 +0000702 THREAD-SPECIFICs
703 ------------------------------------------------ */
sewardj5e5fa512002-04-14 13:13:05 +0000704
sewardj5905fae2002-04-26 13:25:00 +0000705int __pthread_key_create(pthread_key_t *key,
706 void (*destr_function) (void *))
sewardj5e5fa512002-04-14 13:13:05 +0000707{
sewardj5f07b662002-04-23 16:52:51 +0000708 int res;
709 ensure_valgrind("pthread_key_create");
710 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
711 VG_USERREQ__PTHREAD_KEY_CREATE,
712 key, destr_function, 0, 0);
713 return res;
sewardj5e5fa512002-04-14 13:13:05 +0000714}
715
716int pthread_key_delete(pthread_key_t key)
717{
sewardj436e0582002-04-26 14:31:40 +0000718 static int moans = N_MOANS;
719 if (moans-- > 0)
720 ignored("pthread_key_delete");
sewardj5e5fa512002-04-14 13:13:05 +0000721 return 0;
722}
723
sewardj5905fae2002-04-26 13:25:00 +0000724int __pthread_setspecific(pthread_key_t key, const void *pointer)
sewardj5e5fa512002-04-14 13:13:05 +0000725{
sewardj5f07b662002-04-23 16:52:51 +0000726 int res;
727 ensure_valgrind("pthread_setspecific");
728 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
729 VG_USERREQ__PTHREAD_SETSPECIFIC,
730 key, pointer, 0, 0);
731 return res;
sewardj5e5fa512002-04-14 13:13:05 +0000732}
733
sewardj5905fae2002-04-26 13:25:00 +0000734void * __pthread_getspecific(pthread_key_t key)
sewardj5e5fa512002-04-14 13:13:05 +0000735{
sewardj5f07b662002-04-23 16:52:51 +0000736 int res;
737 ensure_valgrind("pthread_getspecific");
738 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
739 VG_USERREQ__PTHREAD_GETSPECIFIC,
740 key, 0 , 0, 0);
741 return (void*)res;
sewardj5e5fa512002-04-14 13:13:05 +0000742}
743
sewardjf8f819e2002-04-17 23:21:37 +0000744
745/* ---------------------------------------------------
sewardj89d3d852002-04-24 19:21:39 +0000746 ONCEry
747 ------------------------------------------------ */
748
749static pthread_mutex_t once_masterlock = PTHREAD_MUTEX_INITIALIZER;
750
751
sewardj5905fae2002-04-26 13:25:00 +0000752int __pthread_once ( pthread_once_t *once_control,
753 void (*init_routine) (void) )
sewardj89d3d852002-04-24 19:21:39 +0000754{
755 int res;
756 ensure_valgrind("pthread_once");
757
sewardj68b2dd92002-05-10 21:03:56 +0000758 res = __pthread_mutex_lock(&once_masterlock);
sewardj89d3d852002-04-24 19:21:39 +0000759
sewardj68b2dd92002-05-10 21:03:56 +0000760 if (res != 0) {
761 printf("res = %d\n",res);
sewardj89d3d852002-04-24 19:21:39 +0000762 barf("pthread_once: Looks like your program's "
763 "init routine calls back to pthread_once() ?!");
sewardj68b2dd92002-05-10 21:03:56 +0000764 }
sewardj89d3d852002-04-24 19:21:39 +0000765
766 if (*once_control == 0) {
767 *once_control = 1;
768 init_routine();
769 }
770
sewardj68b2dd92002-05-10 21:03:56 +0000771 __pthread_mutex_unlock(&once_masterlock);
sewardj89d3d852002-04-24 19:21:39 +0000772
773 return 0;
774}
775
776
777/* ---------------------------------------------------
sewardj853f55d2002-04-26 00:27:53 +0000778 MISC
779 ------------------------------------------------ */
780
sewardj5905fae2002-04-26 13:25:00 +0000781int __pthread_atfork ( void (*prepare)(void),
782 void (*parent)(void),
783 void (*child)(void) )
sewardj853f55d2002-04-26 00:27:53 +0000784{
sewardj436e0582002-04-26 14:31:40 +0000785 static int moans = N_MOANS;
786 if (moans-- > 0)
787 ignored("pthread_atfork");
sewardj853f55d2002-04-26 00:27:53 +0000788 return 0;
789}
790
791
sewardjbb990782002-05-08 02:01:14 +0000792__attribute__((weak))
793void __pthread_initialize ( void )
794{
sewardjbea1caa2002-05-10 23:20:58 +0000795 ensure_valgrind("__pthread_initialize");
sewardjbb990782002-05-08 02:01:14 +0000796}
797
798
sewardj853f55d2002-04-26 00:27:53 +0000799/* ---------------------------------------------------
sewardj3b13f0e2002-04-25 20:17:29 +0000800 LIBRARY-PRIVATE THREAD SPECIFIC STATE
sewardjf8f819e2002-04-17 23:21:37 +0000801 ------------------------------------------------ */
802
sewardj3b13f0e2002-04-25 20:17:29 +0000803#include <resolv.h>
804static int thread_specific_errno[VG_N_THREADS];
805static int thread_specific_h_errno[VG_N_THREADS];
806static struct __res_state
807 thread_specific_res_state[VG_N_THREADS];
sewardjf8f819e2002-04-17 23:21:37 +0000808
sewardj3b13f0e2002-04-25 20:17:29 +0000809int* __errno_location ( void )
sewardjf8f819e2002-04-17 23:21:37 +0000810{
811 int tid;
sewardj3b13f0e2002-04-25 20:17:29 +0000812 /* ensure_valgrind("__errno_location"); */
813 VALGRIND_MAGIC_SEQUENCE(tid, 1 /* default */,
sewardjf8f819e2002-04-17 23:21:37 +0000814 VG_USERREQ__PTHREAD_GET_THREADID,
815 0, 0, 0, 0);
sewardj3b13f0e2002-04-25 20:17:29 +0000816 /* 'cos I'm paranoid ... */
sewardj439d45e2002-05-03 20:43:10 +0000817 if (tid < 1 || tid >= VG_N_THREADS)
sewardj3b13f0e2002-04-25 20:17:29 +0000818 barf("__errno_location: invalid ThreadId");
819 return & thread_specific_errno[tid];
820}
821
822int* __h_errno_location ( void )
823{
824 int tid;
825 /* ensure_valgrind("__h_errno_location"); */
826 VALGRIND_MAGIC_SEQUENCE(tid, 1 /* default */,
827 VG_USERREQ__PTHREAD_GET_THREADID,
828 0, 0, 0, 0);
829 /* 'cos I'm paranoid ... */
sewardj439d45e2002-05-03 20:43:10 +0000830 if (tid < 1 || tid >= VG_N_THREADS)
sewardj3b13f0e2002-04-25 20:17:29 +0000831 barf("__h_errno_location: invalid ThreadId");
832 return & thread_specific_h_errno[tid];
833}
834
835struct __res_state* __res_state ( void )
836{
837 int tid;
838 /* ensure_valgrind("__res_state"); */
839 VALGRIND_MAGIC_SEQUENCE(tid, 1 /* default */,
840 VG_USERREQ__PTHREAD_GET_THREADID,
841 0, 0, 0, 0);
842 /* 'cos I'm paranoid ... */
sewardj439d45e2002-05-03 20:43:10 +0000843 if (tid < 1 || tid >= VG_N_THREADS)
sewardj3b13f0e2002-04-25 20:17:29 +0000844 barf("__res_state: invalid ThreadId");
845 return & thread_specific_res_state[tid];
sewardjf8f819e2002-04-17 23:21:37 +0000846}
847
848
sewardj5716dbb2002-04-26 03:28:18 +0000849/* ---------------------------------------------------
850 LIBC-PRIVATE SPECIFIC DATA
851 ------------------------------------------------ */
852
853/* Relies on assumption that initial private data is NULL. This
854 should be fixed somehow. */
855
856/* The allowable keys (indices) (all 2 of them).
857 From sysdeps/pthread/bits/libc-tsd.h
858*/
sewardj70adeb22002-04-27 01:35:38 +0000859#define N_LIBC_TSD_EXTRA_KEYS 1
860
sewardj5716dbb2002-04-26 03:28:18 +0000861enum __libc_tsd_key_t { _LIBC_TSD_KEY_MALLOC = 0,
862 _LIBC_TSD_KEY_DL_ERROR,
863 _LIBC_TSD_KEY_N };
864
865/* Auto-initialising subsystem. libc_specifics_inited is set
866 after initialisation. libc_specifics_inited_mx guards it. */
867static int libc_specifics_inited = 0;
868static pthread_mutex_t libc_specifics_inited_mx = PTHREAD_MUTEX_INITIALIZER;
869
870/* These are the keys we must initialise the first time. */
sewardj70adeb22002-04-27 01:35:38 +0000871static pthread_key_t libc_specifics_keys[_LIBC_TSD_KEY_N
872 + N_LIBC_TSD_EXTRA_KEYS];
sewardj5716dbb2002-04-26 03:28:18 +0000873
874/* Initialise the keys, if they are not already initialise. */
875static
876void init_libc_tsd_keys ( void )
877{
878 int res, i;
879 pthread_key_t k;
880
881 res = pthread_mutex_lock(&libc_specifics_inited_mx);
882 if (res != 0) barf("init_libc_tsd_keys: lock");
883
884 if (libc_specifics_inited == 0) {
885 /* printf("INIT libc specifics\n"); */
886 libc_specifics_inited = 1;
sewardj70adeb22002-04-27 01:35:38 +0000887 for (i = 0; i < _LIBC_TSD_KEY_N + N_LIBC_TSD_EXTRA_KEYS; i++) {
sewardj5716dbb2002-04-26 03:28:18 +0000888 res = pthread_key_create(&k, NULL);
889 if (res != 0) barf("init_libc_tsd_keys: create");
890 libc_specifics_keys[i] = k;
891 }
892 }
893
894 res = pthread_mutex_unlock(&libc_specifics_inited_mx);
895 if (res != 0) barf("init_libc_tsd_keys: unlock");
896}
897
898
899static int
900libc_internal_tsd_set ( enum __libc_tsd_key_t key,
901 const void * pointer )
902{
sewardj70adeb22002-04-27 01:35:38 +0000903 int res;
904 static int moans = N_MOANS;
sewardj5716dbb2002-04-26 03:28:18 +0000905 /* printf("SET SET SET key %d ptr %p\n", key, pointer); */
sewardj70adeb22002-04-27 01:35:38 +0000906 if (key < _LIBC_TSD_KEY_MALLOC
907 || key >= _LIBC_TSD_KEY_N + N_LIBC_TSD_EXTRA_KEYS)
sewardj5716dbb2002-04-26 03:28:18 +0000908 barf("libc_internal_tsd_set: invalid key");
sewardj70adeb22002-04-27 01:35:38 +0000909 if (key >= _LIBC_TSD_KEY_N && moans-- > 0)
910 fprintf(stderr,
sewardj439d45e2002-05-03 20:43:10 +0000911 "valgrind's libpthread.so: libc_internal_tsd_set: "
912 "dubious key %d\n", key);
sewardj5716dbb2002-04-26 03:28:18 +0000913 init_libc_tsd_keys();
914 res = pthread_setspecific(libc_specifics_keys[key], pointer);
915 if (res != 0) barf("libc_internal_tsd_set: setspecific failed");
916 return 0;
917}
918
919static void *
920libc_internal_tsd_get ( enum __libc_tsd_key_t key )
921{
sewardj70adeb22002-04-27 01:35:38 +0000922 void* v;
923 static int moans = N_MOANS;
sewardj5716dbb2002-04-26 03:28:18 +0000924 /* printf("GET GET GET key %d\n", key); */
sewardj70adeb22002-04-27 01:35:38 +0000925 if (key < _LIBC_TSD_KEY_MALLOC
926 || key >= _LIBC_TSD_KEY_N + N_LIBC_TSD_EXTRA_KEYS)
sewardj5716dbb2002-04-26 03:28:18 +0000927 barf("libc_internal_tsd_get: invalid key");
sewardj70adeb22002-04-27 01:35:38 +0000928 if (key >= _LIBC_TSD_KEY_N && moans-- > 0)
929 fprintf(stderr,
sewardj439d45e2002-05-03 20:43:10 +0000930 "valgrind's libpthread.so: libc_internal_tsd_get: "
931 "dubious key %d\n", key);
sewardj5716dbb2002-04-26 03:28:18 +0000932 init_libc_tsd_keys();
933 v = pthread_getspecific(libc_specifics_keys[key]);
934 /* if (v == NULL) barf("libc_internal_tsd_set: getspecific failed"); */
935 return v;
936}
937
938
939
940
sewardj70adeb22002-04-27 01:35:38 +0000941int (*__libc_internal_tsd_set)
942 (enum __libc_tsd_key_t key, const void * pointer)
943 = libc_internal_tsd_set;
sewardj5716dbb2002-04-26 03:28:18 +0000944
sewardj70adeb22002-04-27 01:35:38 +0000945void* (*__libc_internal_tsd_get)
946 (enum __libc_tsd_key_t key)
947 = libc_internal_tsd_get;
sewardj5716dbb2002-04-26 03:28:18 +0000948
949
sewardje663cb92002-04-12 10:26:32 +0000950/* ---------------------------------------------------------------------
951 These are here (I think) because they are deemed cancellation
952 points by POSIX. For the moment we'll simply pass the call along
953 to the corresponding thread-unaware (?) libc routine.
954 ------------------------------------------------------------------ */
955
sewardje663cb92002-04-12 10:26:32 +0000956#include <stdlib.h>
sewardje663cb92002-04-12 10:26:32 +0000957#include <sys/types.h>
958#include <sys/socket.h>
959
sewardjd529a442002-05-04 19:49:21 +0000960#ifdef GLIBC_2_1
961extern
962int __sigaction
963 (int signum,
964 const struct sigaction *act,
965 struct sigaction *oldact);
966#else
sewardje663cb92002-04-12 10:26:32 +0000967extern
968int __libc_sigaction
969 (int signum,
970 const struct sigaction *act,
971 struct sigaction *oldact);
sewardjd529a442002-05-04 19:49:21 +0000972#endif
sewardje663cb92002-04-12 10:26:32 +0000973int sigaction(int signum,
974 const struct sigaction *act,
975 struct sigaction *oldact)
976{
sewardj2a1dcce2002-04-22 12:45:25 +0000977# ifdef GLIBC_2_1
978 return __sigaction(signum, act, oldact);
979# else
sewardj45b4b372002-04-16 22:50:32 +0000980 return __libc_sigaction(signum, act, oldact);
sewardj2a1dcce2002-04-22 12:45:25 +0000981# endif
sewardje663cb92002-04-12 10:26:32 +0000982}
983
984
985extern
986int __libc_connect(int sockfd,
987 const struct sockaddr *serv_addr,
988 socklen_t addrlen);
sewardj5905fae2002-04-26 13:25:00 +0000989__attribute__((weak))
sewardje663cb92002-04-12 10:26:32 +0000990int connect(int sockfd,
991 const struct sockaddr *serv_addr,
992 socklen_t addrlen)
993{
sewardj45b4b372002-04-16 22:50:32 +0000994 return __libc_connect(sockfd, serv_addr, addrlen);
sewardje663cb92002-04-12 10:26:32 +0000995}
996
997
998extern
999int __libc_fcntl(int fd, int cmd, long arg);
sewardj5905fae2002-04-26 13:25:00 +00001000__attribute__((weak))
sewardje663cb92002-04-12 10:26:32 +00001001int fcntl(int fd, int cmd, long arg)
1002{
sewardj45b4b372002-04-16 22:50:32 +00001003 return __libc_fcntl(fd, cmd, arg);
sewardje663cb92002-04-12 10:26:32 +00001004}
1005
1006
1007extern
1008ssize_t __libc_write(int fd, const void *buf, size_t count);
sewardj5905fae2002-04-26 13:25:00 +00001009__attribute__((weak))
sewardje663cb92002-04-12 10:26:32 +00001010ssize_t write(int fd, const void *buf, size_t count)
1011{
sewardj45b4b372002-04-16 22:50:32 +00001012 return __libc_write(fd, buf, count);
sewardje663cb92002-04-12 10:26:32 +00001013}
1014
1015
1016extern
1017ssize_t __libc_read(int fd, void *buf, size_t count);
sewardj5905fae2002-04-26 13:25:00 +00001018__attribute__((weak))
sewardje663cb92002-04-12 10:26:32 +00001019ssize_t read(int fd, void *buf, size_t count)
1020{
sewardj45b4b372002-04-16 22:50:32 +00001021 return __libc_read(fd, buf, count);
sewardje663cb92002-04-12 10:26:32 +00001022}
1023
sewardjbe32e452002-04-24 20:29:58 +00001024
1025extern
sewardj853f55d2002-04-26 00:27:53 +00001026int __libc_open64(const char *pathname, int flags, mode_t mode);
sewardj5905fae2002-04-26 13:25:00 +00001027__attribute__((weak))
sewardj853f55d2002-04-26 00:27:53 +00001028int open64(const char *pathname, int flags, mode_t mode)
sewardjbe32e452002-04-24 20:29:58 +00001029{
sewardj853f55d2002-04-26 00:27:53 +00001030 return __libc_open64(pathname, flags, mode);
sewardjbe32e452002-04-24 20:29:58 +00001031}
1032
sewardje663cb92002-04-12 10:26:32 +00001033
1034extern
sewardj853f55d2002-04-26 00:27:53 +00001035int __libc_open(const char *pathname, int flags, mode_t mode);
sewardj5905fae2002-04-26 13:25:00 +00001036__attribute__((weak))
sewardj853f55d2002-04-26 00:27:53 +00001037int open(const char *pathname, int flags, mode_t mode)
sewardje663cb92002-04-12 10:26:32 +00001038{
sewardj853f55d2002-04-26 00:27:53 +00001039 return __libc_open(pathname, flags, mode);
sewardje663cb92002-04-12 10:26:32 +00001040}
1041
1042
1043extern
1044int __libc_close(int fd);
sewardj5905fae2002-04-26 13:25:00 +00001045__attribute__((weak))
sewardje663cb92002-04-12 10:26:32 +00001046int close(int fd)
1047{
sewardj45b4b372002-04-16 22:50:32 +00001048 return __libc_close(fd);
sewardje663cb92002-04-12 10:26:32 +00001049}
1050
1051
1052extern
1053int __libc_accept(int s, struct sockaddr *addr, socklen_t *addrlen);
sewardj5905fae2002-04-26 13:25:00 +00001054__attribute__((weak))
sewardje663cb92002-04-12 10:26:32 +00001055int accept(int s, struct sockaddr *addr, socklen_t *addrlen)
1056{
sewardj45b4b372002-04-16 22:50:32 +00001057 return __libc_accept(s, addr, addrlen);
sewardje663cb92002-04-12 10:26:32 +00001058}
1059
1060
1061extern
1062pid_t __libc_fork(void);
sewardj5905fae2002-04-26 13:25:00 +00001063pid_t __fork(void)
sewardje663cb92002-04-12 10:26:32 +00001064{
sewardj45b4b372002-04-16 22:50:32 +00001065 return __libc_fork();
sewardje663cb92002-04-12 10:26:32 +00001066}
1067
1068
1069extern
1070pid_t __libc_waitpid(pid_t pid, int *status, int options);
sewardj5905fae2002-04-26 13:25:00 +00001071__attribute__((weak))
sewardje663cb92002-04-12 10:26:32 +00001072pid_t waitpid(pid_t pid, int *status, int options)
1073{
sewardj45b4b372002-04-16 22:50:32 +00001074 return __libc_waitpid(pid, status, options);
sewardje663cb92002-04-12 10:26:32 +00001075}
1076
1077
1078extern
1079int __libc_nanosleep(const struct timespec *req, struct timespec *rem);
sewardj5905fae2002-04-26 13:25:00 +00001080__attribute__((weak))
sewardje663cb92002-04-12 10:26:32 +00001081int nanosleep(const struct timespec *req, struct timespec *rem)
1082{
1083 return __libc_nanosleep(req, rem);
1084}
1085
sewardjbe32e452002-04-24 20:29:58 +00001086
sewardje663cb92002-04-12 10:26:32 +00001087extern
1088int __libc_fsync(int fd);
sewardj5905fae2002-04-26 13:25:00 +00001089__attribute__((weak))
sewardje663cb92002-04-12 10:26:32 +00001090int fsync(int fd)
1091{
sewardj45b4b372002-04-16 22:50:32 +00001092 return __libc_fsync(fd);
sewardje663cb92002-04-12 10:26:32 +00001093}
1094
sewardjbe32e452002-04-24 20:29:58 +00001095
sewardj70c75362002-04-13 04:18:32 +00001096extern
1097off_t __libc_lseek(int fildes, off_t offset, int whence);
sewardj5905fae2002-04-26 13:25:00 +00001098__attribute__((weak))
sewardj70c75362002-04-13 04:18:32 +00001099off_t lseek(int fildes, off_t offset, int whence)
1100{
sewardj45b4b372002-04-16 22:50:32 +00001101 return __libc_lseek(fildes, offset, whence);
sewardj70c75362002-04-13 04:18:32 +00001102}
1103
sewardjbe32e452002-04-24 20:29:58 +00001104
1105extern
1106__off64_t __libc_lseek64(int fildes, __off64_t offset, int whence);
sewardj5905fae2002-04-26 13:25:00 +00001107__attribute__((weak))
sewardjbe32e452002-04-24 20:29:58 +00001108__off64_t lseek64(int fildes, __off64_t offset, int whence)
1109{
1110 return __libc_lseek64(fildes, offset, whence);
1111}
1112
1113
sewardj6af4b5d2002-04-16 04:40:49 +00001114extern
1115void __libc_longjmp(jmp_buf env, int val) __attribute((noreturn));
sewardj5905fae2002-04-26 13:25:00 +00001116/* not weak: __attribute__((weak)) */
sewardj6af4b5d2002-04-16 04:40:49 +00001117void longjmp(jmp_buf env, int val)
1118{
1119 __libc_longjmp(env, val);
1120}
1121
sewardjbe32e452002-04-24 20:29:58 +00001122
sewardj6af4b5d2002-04-16 04:40:49 +00001123extern
1124int __libc_send(int s, const void *msg, size_t len, int flags);
sewardj5905fae2002-04-26 13:25:00 +00001125__attribute__((weak))
sewardj6af4b5d2002-04-16 04:40:49 +00001126int send(int s, const void *msg, size_t len, int flags)
1127{
1128 return __libc_send(s, msg, len, flags);
1129}
1130
sewardjbe32e452002-04-24 20:29:58 +00001131
sewardj1e8cdc92002-04-18 11:37:52 +00001132extern
1133int __libc_recv(int s, void *buf, size_t len, int flags);
sewardj5905fae2002-04-26 13:25:00 +00001134__attribute__((weak))
sewardj1e8cdc92002-04-18 11:37:52 +00001135int recv(int s, void *buf, size_t len, int flags)
1136{
1137 return __libc_recv(s, buf, len, flags);
1138}
1139
sewardjbe32e452002-04-24 20:29:58 +00001140
sewardj3665ded2002-05-16 16:57:25 +00001141extern
1142int __libc_sendmsg(int s, const struct msghdr *msg, int flags);
1143__attribute__((weak))
1144int sendmsg(int s, const struct msghdr *msg, int flags)
1145{
1146 return __libc_sendmsg(s, msg, flags);
1147}
1148
1149
sewardj796d6a22002-04-24 02:28:34 +00001150extern
sewardj436e0582002-04-26 14:31:40 +00001151int __libc_recvfrom(int s, void *buf, size_t len, int flags,
1152 struct sockaddr *from, socklen_t *fromlen);
1153__attribute__((weak))
1154int recvfrom(int s, void *buf, size_t len, int flags,
1155 struct sockaddr *from, socklen_t *fromlen)
1156{
1157 return __libc_recvfrom(s, buf, len, flags, from, fromlen);
1158}
1159
1160
1161extern
sewardj796d6a22002-04-24 02:28:34 +00001162int __libc_sendto(int s, const void *msg, size_t len, int flags,
1163 const struct sockaddr *to, socklen_t tolen);
sewardj5905fae2002-04-26 13:25:00 +00001164__attribute__((weak))
sewardj796d6a22002-04-24 02:28:34 +00001165int sendto(int s, const void *msg, size_t len, int flags,
1166 const struct sockaddr *to, socklen_t tolen)
1167{
1168 return __libc_sendto(s, msg, len, flags, to, tolen);
1169}
1170
sewardjbe32e452002-04-24 20:29:58 +00001171
sewardj369b1702002-04-24 13:28:15 +00001172extern
1173int __libc_system(const char* str);
sewardj5905fae2002-04-26 13:25:00 +00001174__attribute__((weak))
sewardj369b1702002-04-24 13:28:15 +00001175int system(const char* str)
1176{
1177 return __libc_system(str);
1178}
1179
sewardjbe32e452002-04-24 20:29:58 +00001180
sewardjab0b1c32002-04-24 19:26:47 +00001181extern
1182pid_t __libc_wait(int *status);
sewardj5905fae2002-04-26 13:25:00 +00001183__attribute__((weak))
sewardjab0b1c32002-04-24 19:26:47 +00001184pid_t wait(int *status)
1185{
1186 return __libc_wait(status);
1187}
1188
sewardj45b4b372002-04-16 22:50:32 +00001189
sewardj5905fae2002-04-26 13:25:00 +00001190
sewardj3b13f0e2002-04-25 20:17:29 +00001191/* ---------------------------------------------------------------------
1192 Nonblocking implementations of select() and poll(). This stuff will
1193 surely rot your mind.
1194 ------------------------------------------------------------------ */
sewardje663cb92002-04-12 10:26:32 +00001195
sewardj08a4c3f2002-04-13 03:45:44 +00001196/*--------------------------------------------------*/
1197
1198#include "vg_kerneliface.h"
1199
1200static
1201__inline__
1202int is_kerror ( int res )
1203{
1204 if (res >= -4095 && res <= -1)
1205 return 1;
1206 else
1207 return 0;
1208}
1209
1210
1211static
1212int my_do_syscall1 ( int syscallno, int arg1 )
1213{
1214 int __res;
1215 __asm__ volatile ("pushl %%ebx; movl %%edx,%%ebx ; int $0x80 ; popl %%ebx"
1216 : "=a" (__res)
1217 : "0" (syscallno),
1218 "d" (arg1) );
1219 return __res;
1220}
1221
1222static
1223int my_do_syscall2 ( int syscallno,
sewardjf854f472002-04-21 12:19:41 +00001224 int arg1, int arg2 )
sewardj08a4c3f2002-04-13 03:45:44 +00001225{
1226 int __res;
1227 __asm__ volatile ("pushl %%ebx; movl %%edx,%%ebx ; int $0x80 ; popl %%ebx"
1228 : "=a" (__res)
1229 : "0" (syscallno),
1230 "d" (arg1),
1231 "c" (arg2) );
1232 return __res;
1233}
1234
1235static
sewardjf854f472002-04-21 12:19:41 +00001236int my_do_syscall3 ( int syscallno,
1237 int arg1, int arg2, int arg3 )
1238{
1239 int __res;
1240 __asm__ volatile ("pushl %%ebx; movl %%esi,%%ebx ; int $0x80 ; popl %%ebx"
1241 : "=a" (__res)
1242 : "0" (syscallno),
1243 "S" (arg1),
1244 "c" (arg2),
1245 "d" (arg3) );
1246 return __res;
1247}
1248
1249static
sewardj08a4c3f2002-04-13 03:45:44 +00001250int do_syscall_select( int n,
1251 vki_fd_set* readfds,
1252 vki_fd_set* writefds,
1253 vki_fd_set* exceptfds,
1254 struct vki_timeval * timeout )
1255{
1256 int res;
1257 int args[5];
1258 args[0] = n;
1259 args[1] = (int)readfds;
1260 args[2] = (int)writefds;
1261 args[3] = (int)exceptfds;
1262 args[4] = (int)timeout;
1263 res = my_do_syscall1(__NR_select, (int)(&(args[0])) );
sewardj02535bc2002-04-21 01:08:26 +00001264 return res;
sewardj08a4c3f2002-04-13 03:45:44 +00001265}
1266
1267
1268/* This is a wrapper round select(), which makes it thread-safe,
1269 meaning that only this thread will block, rather than the entire
1270 process. This wrapper in turn depends on nanosleep() not to block
1271 the entire process, but I think (hope? suspect?) that POSIX
1272 pthreads guarantees that to be the case.
1273
1274 Basic idea is: modify the timeout parameter to select so that it
1275 returns immediately. Poll like this until select returns non-zero,
1276 indicating something interesting happened, or until our time is up.
1277 Space out the polls with nanosleeps of say 20 milliseconds, which
1278 is required to be nonblocking; this allows other threads to run.
sewardj02535bc2002-04-21 01:08:26 +00001279
1280 Assumes:
1281 * (checked via assert) types fd_set and vki_fd_set are identical.
1282 * (checked via assert) types timeval and vki_timeval are identical.
1283 * (unchecked) libc error numbers (EINTR etc) are the negation of the
1284 kernel's error numbers (VKI_EINTR etc).
sewardj08a4c3f2002-04-13 03:45:44 +00001285*/
sewardj08a4c3f2002-04-13 03:45:44 +00001286
sewardj5905fae2002-04-26 13:25:00 +00001287/* __attribute__((weak)) */
sewardj08a4c3f2002-04-13 03:45:44 +00001288int select ( int n,
1289 fd_set *rfds,
1290 fd_set *wfds,
1291 fd_set *xfds,
1292 struct timeval *timeout )
1293{
sewardj5f07b662002-04-23 16:52:51 +00001294 unsigned int ms_now, ms_end;
sewardj08a4c3f2002-04-13 03:45:44 +00001295 int res;
1296 fd_set rfds_copy;
1297 fd_set wfds_copy;
1298 fd_set xfds_copy;
1299 struct vki_timeval t_now;
sewardj08a4c3f2002-04-13 03:45:44 +00001300 struct vki_timeval zero_timeout;
1301 struct vki_timespec nanosleep_interval;
1302
sewardj5f07b662002-04-23 16:52:51 +00001303 /* gcc's complains about ms_end being used uninitialised -- classic
1304 case it can't understand, where ms_end is both defined and used
1305 only if timeout != NULL. Hence ... */
1306 ms_end = 0;
sewardj08a4c3f2002-04-13 03:45:44 +00001307
1308 /* We assume that the kernel and libc data layouts are identical
1309 for the following types. These asserts provide a crude
1310 check. */
1311 if (sizeof(fd_set) != sizeof(vki_fd_set)
1312 || sizeof(struct timeval) != sizeof(struct vki_timeval))
1313 barf("valgrind's hacky non-blocking select(): data sizes error");
1314
sewardj5f07b662002-04-23 16:52:51 +00001315 /* Detect the current time and simultaneously find out if we are
1316 running on Valgrind. */
1317 VALGRIND_MAGIC_SEQUENCE(ms_now, 0xFFFFFFFF /* default */,
1318 VG_USERREQ__READ_MILLISECOND_TIMER,
1319 0, 0, 0, 0);
1320
1321 /* If a zero timeout specified, this call is harmless. Also go
1322 this route if we're not running on Valgrind, for whatever
1323 reason. */
1324 if ( (timeout && timeout->tv_sec == 0 && timeout->tv_usec == 0)
1325 || (ms_now == 0xFFFFFFFF) ) {
sewardj02535bc2002-04-21 01:08:26 +00001326 res = do_syscall_select( n, (vki_fd_set*)rfds,
sewardj08a4c3f2002-04-13 03:45:44 +00001327 (vki_fd_set*)wfds,
1328 (vki_fd_set*)xfds,
1329 (struct vki_timeval*)timeout);
sewardj02535bc2002-04-21 01:08:26 +00001330 if (is_kerror(res)) {
1331 * (__errno_location()) = -res;
1332 return -1;
1333 } else {
1334 return res;
1335 }
1336 }
sewardj08a4c3f2002-04-13 03:45:44 +00001337
sewardj5f07b662002-04-23 16:52:51 +00001338 /* If a timeout was specified, set ms_end to be the end millisecond
1339 counter [wallclock] time. */
sewardj08a4c3f2002-04-13 03:45:44 +00001340 if (timeout) {
1341 res = my_do_syscall2(__NR_gettimeofday, (int)&t_now, (int)NULL);
1342 assert(res == 0);
sewardj5f07b662002-04-23 16:52:51 +00001343 ms_end = ms_now;
1344 ms_end += (timeout->tv_usec / 1000);
1345 ms_end += (timeout->tv_sec * 1000);
sewardj08a4c3f2002-04-13 03:45:44 +00001346 /* Stay sane ... */
sewardj5f07b662002-04-23 16:52:51 +00001347 assert (ms_end >= ms_now);
sewardj08a4c3f2002-04-13 03:45:44 +00001348 }
1349
1350 /* fprintf(stderr, "MY_SELECT: before loop\n"); */
1351
1352 /* Either timeout == NULL, meaning wait indefinitely, or timeout !=
sewardj5f07b662002-04-23 16:52:51 +00001353 NULL, in which case ms_end holds the end time. */
sewardj08a4c3f2002-04-13 03:45:44 +00001354 while (1) {
1355 if (timeout) {
sewardj5f07b662002-04-23 16:52:51 +00001356 VALGRIND_MAGIC_SEQUENCE(ms_now, 0xFFFFFFFF /* default */,
1357 VG_USERREQ__READ_MILLISECOND_TIMER,
1358 0, 0, 0, 0);
1359 assert(ms_now != 0xFFFFFFFF);
1360 if (ms_now >= ms_end) {
sewardj08a4c3f2002-04-13 03:45:44 +00001361 /* timeout; nothing interesting happened. */
1362 if (rfds) FD_ZERO(rfds);
1363 if (wfds) FD_ZERO(wfds);
1364 if (xfds) FD_ZERO(xfds);
1365 return 0;
1366 }
1367 }
1368
1369 /* These could be trashed each time round the loop, so restore
1370 them each time. */
1371 if (rfds) rfds_copy = *rfds;
1372 if (wfds) wfds_copy = *wfds;
1373 if (xfds) xfds_copy = *xfds;
1374
1375 zero_timeout.tv_sec = zero_timeout.tv_usec = 0;
1376
1377 res = do_syscall_select( n,
1378 rfds ? (vki_fd_set*)(&rfds_copy) : NULL,
1379 wfds ? (vki_fd_set*)(&wfds_copy) : NULL,
1380 xfds ? (vki_fd_set*)(&xfds_copy) : NULL,
1381 & zero_timeout );
sewardj02535bc2002-04-21 01:08:26 +00001382 if (is_kerror(res)) {
1383 /* Some kind of error (including EINTR). Set errno and
sewardj08a4c3f2002-04-13 03:45:44 +00001384 return. The sets are unspecified in this case. */
sewardj02535bc2002-04-21 01:08:26 +00001385 * (__errno_location()) = -res;
1386 return -1;
sewardj08a4c3f2002-04-13 03:45:44 +00001387 }
1388 if (res > 0) {
1389 /* one or more fds is ready. Copy out resulting sets and
1390 return. */
1391 if (rfds) *rfds = rfds_copy;
1392 if (wfds) *wfds = wfds_copy;
1393 if (xfds) *xfds = xfds_copy;
1394 return res;
1395 }
1396 /* fprintf(stderr, "MY_SELECT: nanosleep\n"); */
1397 /* nanosleep and go round again */
sewardj02535bc2002-04-21 01:08:26 +00001398 nanosleep_interval.tv_sec = 0;
sewardj956cc1b2002-04-25 01:33:50 +00001399 nanosleep_interval.tv_nsec = 50 * 1000 * 1000; /* 50 milliseconds */
sewardjf854f472002-04-21 12:19:41 +00001400 /* It's critical here that valgrind's nanosleep implementation
1401 is nonblocking. */
1402 (void)my_do_syscall2(__NR_nanosleep,
1403 (int)(&nanosleep_interval), (int)NULL);
1404 }
1405}
1406
1407
1408
1409
1410#include <sys/poll.h>
1411
sewardj72d58482002-04-24 02:20:20 +00001412#ifdef GLIBC_2_1
1413typedef unsigned long int nfds_t;
1414#endif
1415
sewardj5905fae2002-04-26 13:25:00 +00001416/* __attribute__((weak)) */
sewardjf854f472002-04-21 12:19:41 +00001417int poll (struct pollfd *__fds, nfds_t __nfds, int __timeout)
1418{
sewardj5f07b662002-04-23 16:52:51 +00001419 unsigned int ms_now, ms_end;
sewardjf854f472002-04-21 12:19:41 +00001420 int res, i;
sewardjf854f472002-04-21 12:19:41 +00001421 struct vki_timespec nanosleep_interval;
1422
1423 ensure_valgrind("poll");
1424
sewardj5f07b662002-04-23 16:52:51 +00001425 /* Detect the current time and simultaneously find out if we are
1426 running on Valgrind. */
1427 VALGRIND_MAGIC_SEQUENCE(ms_now, 0xFFFFFFFF /* default */,
1428 VG_USERREQ__READ_MILLISECOND_TIMER,
1429 0, 0, 0, 0);
1430
sewardjf854f472002-04-21 12:19:41 +00001431 if (/* CHECK SIZES FOR struct pollfd */
1432 sizeof(struct timeval) != sizeof(struct vki_timeval))
1433 barf("valgrind's hacky non-blocking poll(): data sizes error");
1434
sewardj5f07b662002-04-23 16:52:51 +00001435 /* dummy initialisation to keep gcc -Wall happy */
1436 ms_end = 0;
1437
1438 /* If a zero timeout specified, this call is harmless. Also do
1439 this if not running on Valgrind. */
1440 if (__timeout == 0 || ms_now == 0xFFFFFFFF) {
sewardjf854f472002-04-21 12:19:41 +00001441 res = my_do_syscall3(__NR_poll, (int)__fds, __nfds, __timeout);
1442 if (is_kerror(res)) {
1443 * (__errno_location()) = -res;
1444 return -1;
1445 } else {
1446 return res;
1447 }
1448 }
1449
sewardj5f07b662002-04-23 16:52:51 +00001450 /* If a timeout was specified, set ms_end to be the end wallclock
1451 time. Easy considering that __timeout is in milliseconds. */
sewardjf854f472002-04-21 12:19:41 +00001452 if (__timeout > 0) {
sewardj650ac002002-04-29 12:20:34 +00001453 ms_end = ms_now + (unsigned int)__timeout;
sewardjf854f472002-04-21 12:19:41 +00001454 }
1455
1456 /* fprintf(stderr, "MY_POLL: before loop\n"); */
1457
1458 /* Either timeout < 0, meaning wait indefinitely, or timeout > 0,
1459 in which case t_end holds the end time. */
sewardj5f07b662002-04-23 16:52:51 +00001460 assert(__timeout != 0);
1461
sewardjf854f472002-04-21 12:19:41 +00001462 while (1) {
sewardjf854f472002-04-21 12:19:41 +00001463 if (__timeout > 0) {
sewardj5f07b662002-04-23 16:52:51 +00001464 VALGRIND_MAGIC_SEQUENCE(ms_now, 0xFFFFFFFF /* default */,
1465 VG_USERREQ__READ_MILLISECOND_TIMER,
1466 0, 0, 0, 0);
1467 assert(ms_now != 0xFFFFFFFF);
1468 if (ms_now >= ms_end) {
sewardjf854f472002-04-21 12:19:41 +00001469 /* timeout; nothing interesting happened. */
1470 for (i = 0; i < __nfds; i++)
1471 __fds[i].revents = 0;
1472 return 0;
1473 }
1474 }
1475
sewardj5f07b662002-04-23 16:52:51 +00001476 /* Do a return-immediately poll. */
sewardjf854f472002-04-21 12:19:41 +00001477 res = my_do_syscall3(__NR_poll, (int)__fds, __nfds, 0 );
1478 if (is_kerror(res)) {
1479 /* Some kind of error. Set errno and return. */
1480 * (__errno_location()) = -res;
1481 return -1;
1482 }
1483 if (res > 0) {
1484 /* One or more fds is ready. Return now. */
1485 return res;
1486 }
1487 /* fprintf(stderr, "MY_POLL: nanosleep\n"); */
1488 /* nanosleep and go round again */
1489 nanosleep_interval.tv_sec = 0;
sewardj956cc1b2002-04-25 01:33:50 +00001490 nanosleep_interval.tv_nsec = 51 * 1000 * 1000; /* 51 milliseconds */
sewardj08a4c3f2002-04-13 03:45:44 +00001491 /* It's critical here that valgrind's nanosleep implementation
1492 is nonblocking. */
1493 (void)my_do_syscall2(__NR_nanosleep,
1494 (int)(&nanosleep_interval), (int)NULL);
1495 }
1496}
sewardj3b13f0e2002-04-25 20:17:29 +00001497
1498
1499/* ---------------------------------------------------------------------
1500 B'stard.
1501 ------------------------------------------------------------------ */
1502
1503# define strong_alias(name, aliasname) \
1504 extern __typeof (name) aliasname __attribute__ ((alias (#name)));
1505
sewardj5905fae2002-04-26 13:25:00 +00001506# define weak_alias(name, aliasname) \
1507 extern __typeof (name) aliasname __attribute__ ((weak, alias (#name)));
sewardj3b13f0e2002-04-25 20:17:29 +00001508
sewardj5905fae2002-04-26 13:25:00 +00001509strong_alias(__pthread_mutex_lock, pthread_mutex_lock)
1510strong_alias(__pthread_mutex_trylock, pthread_mutex_trylock)
1511strong_alias(__pthread_mutex_unlock, pthread_mutex_unlock)
1512strong_alias(__pthread_mutexattr_init, pthread_mutexattr_init)
1513 weak_alias(__pthread_mutexattr_settype, pthread_mutexattr_settype)
1514strong_alias(__pthread_mutex_init, pthread_mutex_init)
1515strong_alias(__pthread_mutexattr_destroy, pthread_mutexattr_destroy)
1516strong_alias(__pthread_mutex_destroy, pthread_mutex_destroy)
1517strong_alias(__pthread_once, pthread_once)
1518strong_alias(__pthread_atfork, pthread_atfork)
1519strong_alias(__pthread_key_create, pthread_key_create)
1520strong_alias(__pthread_getspecific, pthread_getspecific)
1521strong_alias(__pthread_setspecific, pthread_setspecific)
1522
sewardjd529a442002-05-04 19:49:21 +00001523#ifndef GLIBC_2_1
sewardj3b13f0e2002-04-25 20:17:29 +00001524strong_alias(sigaction, __sigaction)
sewardjd529a442002-05-04 19:49:21 +00001525#endif
1526
sewardj5905fae2002-04-26 13:25:00 +00001527strong_alias(close, __close)
sewardj3b13f0e2002-04-25 20:17:29 +00001528strong_alias(fcntl, __fcntl)
sewardj5905fae2002-04-26 13:25:00 +00001529strong_alias(lseek, __lseek)
1530strong_alias(open, __open)
1531strong_alias(open64, __open64)
1532//strong_alias(pread64, __pread64)
1533//strong_alias(pwrite64, __pwrite64)
1534strong_alias(read, __read)
1535strong_alias(wait, __wait)
1536strong_alias(write, __write)
sewardj3b13f0e2002-04-25 20:17:29 +00001537strong_alias(connect, __connect)
sewardj5905fae2002-04-26 13:25:00 +00001538strong_alias(send, __send)
1539
1540weak_alias(__fork, fork)
1541//weak_alias(__vfork, vfork)
1542
sewardj3b13f0e2002-04-25 20:17:29 +00001543
1544/*--------------------------------------------------*/
1545
sewardj5716dbb2002-04-26 03:28:18 +00001546int
1547pthread_rwlock_rdlock (void* /* pthread_rwlock_t* */ rwlock)
1548{
sewardj436e0582002-04-26 14:31:40 +00001549 static int moans = N_MOANS;
1550 if (moans-- > 0)
1551 kludged("pthread_rwlock_rdlock");
sewardj5716dbb2002-04-26 03:28:18 +00001552 return 0;
1553}
1554
sewardj5905fae2002-04-26 13:25:00 +00001555weak_alias(pthread_rwlock_rdlock, __pthread_rwlock_rdlock)
sewardj5716dbb2002-04-26 03:28:18 +00001556
1557
1558int
1559pthread_rwlock_unlock (void* /* pthread_rwlock_t* */ rwlock)
1560{
sewardj436e0582002-04-26 14:31:40 +00001561 static int moans = N_MOANS;
1562 if (moans-- > 0)
1563 kludged("pthread_rwlock_unlock");
sewardj5716dbb2002-04-26 03:28:18 +00001564 return 0;
1565}
1566
sewardj5905fae2002-04-26 13:25:00 +00001567weak_alias(pthread_rwlock_unlock, __pthread_rwlock_unlock)
sewardj5716dbb2002-04-26 03:28:18 +00001568
1569
sewardj060b04f2002-04-26 21:01:13 +00001570int
1571pthread_rwlock_wrlock (void* /* pthread_rwlock_t* */ rwlock)
1572{
1573 static int moans = N_MOANS;
1574 if (moans-- > 0)
1575 kludged("pthread_rwlock_wrlock");
1576 return 0;
1577}
1578
sewardj262b0292002-05-01 00:03:16 +00001579weak_alias(pthread_rwlock_wrlock, __pthread_rwlock_wrlock)
sewardj060b04f2002-04-26 21:01:13 +00001580
1581
sewardj3b13f0e2002-04-25 20:17:29 +00001582/* I've no idea what these are, but they get called quite a lot.
1583 Anybody know? */
1584
1585#undef _IO_flockfile
1586void _IO_flockfile ( _IO_FILE * file )
1587{
sewardj853f55d2002-04-26 00:27:53 +00001588 pthread_mutex_lock(file->_lock);
sewardj3b13f0e2002-04-25 20:17:29 +00001589}
sewardj5905fae2002-04-26 13:25:00 +00001590weak_alias(_IO_flockfile, flockfile);
1591
sewardj3b13f0e2002-04-25 20:17:29 +00001592
1593#undef _IO_funlockfile
1594void _IO_funlockfile ( _IO_FILE * file )
1595{
sewardj853f55d2002-04-26 00:27:53 +00001596 pthread_mutex_unlock(file->_lock);
sewardj3b13f0e2002-04-25 20:17:29 +00001597}
sewardj5905fae2002-04-26 13:25:00 +00001598weak_alias(_IO_funlockfile, funlockfile);
1599
sewardj3b13f0e2002-04-25 20:17:29 +00001600
1601void _pthread_cleanup_push_defer ( void )
1602{
sewardj439d45e2002-05-03 20:43:10 +00001603 static int moans = N_MOANS;
1604 if (moans-- > 0)
1605 ignored("_pthread_cleanup_push_defer");
sewardj3b13f0e2002-04-25 20:17:29 +00001606}
1607
1608void _pthread_cleanup_pop_restore ( void )
1609{
sewardj439d45e2002-05-03 20:43:10 +00001610 static int moans = N_MOANS;
1611 if (moans-- > 0)
1612 ignored("_pthread_cleanup_pop_restore");
sewardj3b13f0e2002-04-25 20:17:29 +00001613}
sewardjd4f2c712002-04-30 10:20:10 +00001614
sewardj60e38422002-05-08 14:08:22 +00001615/*--------*/
1616void _pthread_cleanup_push (struct _pthread_cleanup_buffer *__buffer,
1617 void (*__routine) (void *),
1618 void *__arg)
1619{
1620 static int moans = N_MOANS;
1621 if (moans-- > 0)
1622 ignored("_pthread_cleanup_push");
1623}
1624
1625void _pthread_cleanup_pop (struct _pthread_cleanup_buffer *__buffer,
1626 int __execute)
1627{
1628 static int moans = N_MOANS;
1629 if (moans-- > 0) {
1630 if (__execute)
1631 ignored("_pthread_cleanup_pop-EXECUTE");
1632 else
1633 ignored("_pthread_cleanup_pop-NO-EXECUTE");
1634 }
1635}
1636
sewardjd4f2c712002-04-30 10:20:10 +00001637
1638/* This doesn't seem to be needed to simulate libpthread.so's external
1639 interface, but many people complain about its absence. */
1640
1641strong_alias(__pthread_mutexattr_settype, __pthread_mutexattr_setkind_np)
1642weak_alias(__pthread_mutexattr_setkind_np, pthread_mutexattr_setkind_np)
sewardj439d45e2002-05-03 20:43:10 +00001643
1644
1645/*--------------------------------------------------------------------*/
1646/*--- end vg_libpthread.c ---*/
1647/*--------------------------------------------------------------------*/