blob: 93cb7373ddaa2811c70cd3b77542b713f58c23ab [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)();
sewardj30671ff2002-04-21 00:13:57 +0000159}
160
sewardj3b13f0e2002-04-25 20:17:29 +0000161void vgPlain_unimp ( char* what )
162{
sewardj439d45e2002-05-03 20:43:10 +0000163 char* ig = "valgrind's libpthread.so: UNIMPLEMENTED FUNCTION: ";
sewardj3b13f0e2002-04-25 20:17:29 +0000164 write(2, ig, strlen(ig));
165 write(2, what, strlen(what));
166 ig = "\n";
167 write(2, ig, strlen(ig));
168 barf("Please report this bug to me at: jseward@acm.org");
169}
170
sewardje663cb92002-04-12 10:26:32 +0000171
172/* ---------------------------------------------------------------------
173 Pass pthread_ calls to Valgrind's request mechanism.
174 ------------------------------------------------------------------ */
175
sewardjf8f819e2002-04-17 23:21:37 +0000176#include <pthread.h>
177#include <stdio.h>
178#include <errno.h>
sewardj5f07b662002-04-23 16:52:51 +0000179#include <assert.h>
180#include <sys/time.h> /* gettimeofday */
sewardjf8f819e2002-04-17 23:21:37 +0000181
182/* ---------------------------------------------------
183 THREAD ATTRIBUTES
184 ------------------------------------------------ */
185
sewardj6af4b5d2002-04-16 04:40:49 +0000186int pthread_attr_init(pthread_attr_t *attr)
187{
sewardj436e0582002-04-26 14:31:40 +0000188 static int moans = N_MOANS;
189 if (moans-- > 0)
190 ignored("pthread_attr_init");
sewardj6af4b5d2002-04-16 04:40:49 +0000191 return 0;
192}
193
194int pthread_attr_setdetachstate(pthread_attr_t *attr, int detachstate)
195{
sewardj436e0582002-04-26 14:31:40 +0000196 static int moans = N_MOANS;
197 if (moans-- > 0)
198 ignored("pthread_attr_setdetachstate");
sewardj6af4b5d2002-04-16 04:40:49 +0000199 return 0;
200}
201
sewardj30671ff2002-04-21 00:13:57 +0000202int pthread_attr_setinheritsched(pthread_attr_t *attr, int inherit)
203{
sewardj436e0582002-04-26 14:31:40 +0000204 static int moans = N_MOANS;
205 if (moans-- > 0)
206 ignored("pthread_attr_setinheritsched");
sewardj30671ff2002-04-21 00:13:57 +0000207 return 0;
208}
sewardj6af4b5d2002-04-16 04:40:49 +0000209
sewardj0286dd52002-05-16 20:51:15 +0000210__attribute__((weak))
211int pthread_attr_setstacksize (pthread_attr_t *__attr,
212 size_t __stacksize)
213{
sewardja18e2102002-05-18 10:43:22 +0000214 size_t limit;
sewardj0286dd52002-05-16 20:51:15 +0000215 ensure_valgrind("pthread_attr_setstacksize");
sewardja18e2102002-05-18 10:43:22 +0000216 limit = VG_PTHREAD_STACK_SIZE - VG_AR_CLIENT_STACKBASE_REDZONE_SZB
217 - 1000; /* paranoia */
218 if (__stacksize < limit)
sewardj0286dd52002-05-16 20:51:15 +0000219 return 0;
220 barf("pthread_attr_setstacksize: "
221 "requested size >= VG_PTHREAD_STACK_SIZE\n "
222 "edit vg_include.h and rebuild.");
223}
224
225
sewardj30671ff2002-04-21 00:13:57 +0000226/* This is completely bogus. */
227int pthread_attr_getschedparam(const pthread_attr_t *attr,
228 struct sched_param *param)
229{
sewardj436e0582002-04-26 14:31:40 +0000230 static int moans = N_MOANS;
231 if (moans-- > 0)
232 kludged("pthread_attr_getschedparam");
sewardj72d58482002-04-24 02:20:20 +0000233# ifdef GLIBC_2_1
234 if (param) param->sched_priority = 0; /* who knows */
235# else
sewardj30671ff2002-04-21 00:13:57 +0000236 if (param) param->__sched_priority = 0; /* who knows */
sewardj72d58482002-04-24 02:20:20 +0000237# endif
sewardj30671ff2002-04-21 00:13:57 +0000238 return 0;
239}
240
241int pthread_attr_setschedparam(pthread_attr_t *attr,
242 const struct sched_param *param)
243{
sewardj436e0582002-04-26 14:31:40 +0000244 static int moans = N_MOANS;
245 if (moans-- > 0)
246 ignored("pthread_attr_setschedparam");
sewardj30671ff2002-04-21 00:13:57 +0000247 return 0;
248}
249
250int pthread_attr_destroy(pthread_attr_t *attr)
251{
sewardj436e0582002-04-26 14:31:40 +0000252 static int moans = N_MOANS;
253 if (moans-- > 0)
254 ignored("pthread_attr_destroy");
sewardj30671ff2002-04-21 00:13:57 +0000255 return 0;
256}
sewardjf8f819e2002-04-17 23:21:37 +0000257
258/* ---------------------------------------------------
259 THREADs
260 ------------------------------------------------ */
261
sewardj6072c362002-04-19 14:40:57 +0000262int pthread_equal(pthread_t thread1, pthread_t thread2)
263{
264 return thread1 == thread2 ? 1 : 0;
265}
266
267
sewardje663cb92002-04-12 10:26:32 +0000268int
269pthread_create (pthread_t *__restrict __thread,
270 __const pthread_attr_t *__restrict __attr,
271 void *(*__start_routine) (void *),
272 void *__restrict __arg)
273{
274 int res;
275 ensure_valgrind("pthread_create");
276 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
277 VG_USERREQ__PTHREAD_CREATE,
278 __thread, __attr, __start_routine, __arg);
279 return res;
280}
281
282
283
284int
285pthread_join (pthread_t __th, void **__thread_return)
286{
287 int res;
288 ensure_valgrind("pthread_join");
289 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
290 VG_USERREQ__PTHREAD_JOIN,
291 __th, __thread_return, 0, 0);
292 return res;
293}
294
295
sewardj3b5d8862002-04-20 13:53:23 +0000296void pthread_exit(void *retval)
297{
298 int res;
299 ensure_valgrind("pthread_exit");
300 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
301 VG_USERREQ__PTHREAD_EXIT,
302 retval, 0, 0, 0);
303 /* Doesn't return! */
304 /* However, we have to fool gcc into knowing that. */
305 barf("pthread_exit: still alive after request?!");
306}
307
sewardje663cb92002-04-12 10:26:32 +0000308
sewardj3b13f0e2002-04-25 20:17:29 +0000309pthread_t pthread_self(void)
sewardje663cb92002-04-12 10:26:32 +0000310{
311 int tid;
sewardj3b13f0e2002-04-25 20:17:29 +0000312 ensure_valgrind("pthread_self");
sewardj439d45e2002-05-03 20:43:10 +0000313 VALGRIND_MAGIC_SEQUENCE(tid, 1 /* default */,
sewardje663cb92002-04-12 10:26:32 +0000314 VG_USERREQ__PTHREAD_GET_THREADID,
315 0, 0, 0, 0);
sewardj439d45e2002-05-03 20:43:10 +0000316 if (tid < 1 || tid >= VG_N_THREADS)
sewardj3b13f0e2002-04-25 20:17:29 +0000317 barf("pthread_self: invalid ThreadId");
318 return tid;
sewardje663cb92002-04-12 10:26:32 +0000319}
320
321
sewardj853f55d2002-04-26 00:27:53 +0000322int pthread_detach(pthread_t th)
323{
sewardj436e0582002-04-26 14:31:40 +0000324 static int moans = N_MOANS;
325 if (moans-- > 0)
326 ignored("pthread_detach");
sewardj853f55d2002-04-26 00:27:53 +0000327 return 0;
328}
329
330
sewardjf8f819e2002-04-17 23:21:37 +0000331/* ---------------------------------------------------
332 MUTEX ATTRIBUTES
333 ------------------------------------------------ */
334
sewardj5905fae2002-04-26 13:25:00 +0000335int __pthread_mutexattr_init(pthread_mutexattr_t *attr)
sewardje663cb92002-04-12 10:26:32 +0000336{
sewardjf8f819e2002-04-17 23:21:37 +0000337 attr->__mutexkind = PTHREAD_MUTEX_ERRORCHECK_NP;
sewardj8937c812002-04-12 20:12:20 +0000338 return 0;
sewardje663cb92002-04-12 10:26:32 +0000339}
340
sewardj5905fae2002-04-26 13:25:00 +0000341int __pthread_mutexattr_settype(pthread_mutexattr_t *attr, int type)
sewardjf8f819e2002-04-17 23:21:37 +0000342{
343 switch (type) {
sewardj3b13f0e2002-04-25 20:17:29 +0000344# ifndef GLIBC_2_1
sewardjf8f819e2002-04-17 23:21:37 +0000345 case PTHREAD_MUTEX_TIMED_NP:
sewardj2a1dcce2002-04-22 12:45:25 +0000346 case PTHREAD_MUTEX_ADAPTIVE_NP:
sewardj3b13f0e2002-04-25 20:17:29 +0000347# endif
sewardja1679dd2002-05-10 22:31:40 +0000348# ifdef GLIBC_2_1
sewardj68b2dd92002-05-10 21:03:56 +0000349 case PTHREAD_MUTEX_FAST_NP:
sewardja1679dd2002-05-10 22:31:40 +0000350# endif
sewardjf8f819e2002-04-17 23:21:37 +0000351 case PTHREAD_MUTEX_RECURSIVE_NP:
352 case PTHREAD_MUTEX_ERRORCHECK_NP:
sewardjf8f819e2002-04-17 23:21:37 +0000353 attr->__mutexkind = type;
354 return 0;
355 default:
356 return EINVAL;
357 }
358}
359
sewardj5905fae2002-04-26 13:25:00 +0000360int __pthread_mutexattr_destroy(pthread_mutexattr_t *attr)
sewardjf8f819e2002-04-17 23:21:37 +0000361{
362 return 0;
363}
364
365
366/* ---------------------------------------------------
367 MUTEXes
368 ------------------------------------------------ */
369
sewardj5905fae2002-04-26 13:25:00 +0000370int __pthread_mutex_init(pthread_mutex_t *mutex,
371 const pthread_mutexattr_t *mutexattr)
sewardje663cb92002-04-12 10:26:32 +0000372{
sewardj604ec3c2002-04-18 22:38:41 +0000373 mutex->__m_count = 0;
374 mutex->__m_owner = (_pthread_descr)VG_INVALID_THREADID;
375 mutex->__m_kind = PTHREAD_MUTEX_ERRORCHECK_NP;
376 if (mutexattr)
377 mutex->__m_kind = mutexattr->__mutexkind;
378 return 0;
sewardje663cb92002-04-12 10:26:32 +0000379}
380
sewardj439d45e2002-05-03 20:43:10 +0000381
sewardj5905fae2002-04-26 13:25:00 +0000382int __pthread_mutex_lock(pthread_mutex_t *mutex)
sewardje663cb92002-04-12 10:26:32 +0000383{
384 int res;
sewardj436e0582002-04-26 14:31:40 +0000385 static int moans = N_MOANS;
sewardj439d45e2002-05-03 20:43:10 +0000386 if (RUNNING_ON_VALGRIND) {
sewardje663cb92002-04-12 10:26:32 +0000387 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
388 VG_USERREQ__PTHREAD_MUTEX_LOCK,
389 mutex, 0, 0, 0);
390 return res;
sewardj439d45e2002-05-03 20:43:10 +0000391 } else {
392 if (moans-- > 0)
393 not_inside("pthread_mutex_lock");
394 return 0; /* success */
sewardje663cb92002-04-12 10:26:32 +0000395 }
396}
397
sewardj439d45e2002-05-03 20:43:10 +0000398
sewardj5905fae2002-04-26 13:25:00 +0000399int __pthread_mutex_trylock(pthread_mutex_t *mutex)
sewardj30671ff2002-04-21 00:13:57 +0000400{
401 int res;
sewardj436e0582002-04-26 14:31:40 +0000402 static int moans = N_MOANS;
sewardj439d45e2002-05-03 20:43:10 +0000403 if (RUNNING_ON_VALGRIND) {
sewardj30671ff2002-04-21 00:13:57 +0000404 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
405 VG_USERREQ__PTHREAD_MUTEX_TRYLOCK,
406 mutex, 0, 0, 0);
407 return res;
sewardj439d45e2002-05-03 20:43:10 +0000408 } else {
409 if (moans-- > 0)
410 not_inside("pthread_mutex_trylock");
411 return 0;
sewardj30671ff2002-04-21 00:13:57 +0000412 }
413}
414
sewardj439d45e2002-05-03 20:43:10 +0000415
sewardj5905fae2002-04-26 13:25:00 +0000416int __pthread_mutex_unlock(pthread_mutex_t *mutex)
sewardje663cb92002-04-12 10:26:32 +0000417{
418 int res;
sewardj436e0582002-04-26 14:31:40 +0000419 static int moans = N_MOANS;
sewardj439d45e2002-05-03 20:43:10 +0000420 if (RUNNING_ON_VALGRIND) {
sewardje663cb92002-04-12 10:26:32 +0000421 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
422 VG_USERREQ__PTHREAD_MUTEX_UNLOCK,
423 mutex, 0, 0, 0);
424 return res;
sewardj439d45e2002-05-03 20:43:10 +0000425 } else {
426 if (moans-- > 0)
427 not_inside("pthread_mutex_unlock");
428 return 0;
sewardje663cb92002-04-12 10:26:32 +0000429 }
430}
431
sewardj439d45e2002-05-03 20:43:10 +0000432
sewardj5905fae2002-04-26 13:25:00 +0000433int __pthread_mutex_destroy(pthread_mutex_t *mutex)
sewardje663cb92002-04-12 10:26:32 +0000434{
sewardj604ec3c2002-04-18 22:38:41 +0000435 /* Valgrind doesn't hold any resources on behalf of the mutex, so no
436 need to involve it. */
437 if (mutex->__m_count > 0)
438 return EBUSY;
sewardj6072c362002-04-19 14:40:57 +0000439 mutex->__m_count = 0;
440 mutex->__m_owner = (_pthread_descr)VG_INVALID_THREADID;
441 mutex->__m_kind = PTHREAD_MUTEX_ERRORCHECK_NP;
sewardj604ec3c2002-04-18 22:38:41 +0000442 return 0;
sewardje663cb92002-04-12 10:26:32 +0000443}
444
445
sewardjf8f819e2002-04-17 23:21:37 +0000446/* ---------------------------------------------------
sewardj6072c362002-04-19 14:40:57 +0000447 CONDITION VARIABLES
448 ------------------------------------------------ */
449
450/* LinuxThreads supports no attributes for conditions. Hence ... */
451
452int pthread_condattr_init(pthread_condattr_t *attr)
453{
454 return 0;
455}
456
sewardj0738a592002-04-20 13:59:33 +0000457int pthread_condattr_destroy(pthread_condattr_t *attr)
458{
459 return 0;
460}
sewardj6072c362002-04-19 14:40:57 +0000461
462int pthread_cond_init( pthread_cond_t *cond,
463 const pthread_condattr_t *cond_attr)
464{
465 cond->__c_waiting = (_pthread_descr)VG_INVALID_THREADID;
466 return 0;
467}
468
sewardjf854f472002-04-21 12:19:41 +0000469int pthread_cond_destroy(pthread_cond_t *cond)
470{
471 /* should check that no threads are waiting on this CV */
sewardj436e0582002-04-26 14:31:40 +0000472 static int moans = N_MOANS;
473 if (moans-- > 0)
474 kludged("pthread_cond_destroy");
sewardjf854f472002-04-21 12:19:41 +0000475 return 0;
476}
sewardj6072c362002-04-19 14:40:57 +0000477
478/* ---------------------------------------------------
479 SCHEDULING
480 ------------------------------------------------ */
481
482/* This is completely bogus. */
483int pthread_getschedparam(pthread_t target_thread,
484 int *policy,
485 struct sched_param *param)
486{
sewardj436e0582002-04-26 14:31:40 +0000487 static int moans = N_MOANS;
488 if (moans-- > 0)
489 kludged("pthread_getschedparam");
sewardj6072c362002-04-19 14:40:57 +0000490 if (policy) *policy = SCHED_OTHER;
sewardj2a1dcce2002-04-22 12:45:25 +0000491# ifdef GLIBC_2_1
492 if (param) param->sched_priority = 0; /* who knows */
493# else
sewardj6072c362002-04-19 14:40:57 +0000494 if (param) param->__sched_priority = 0; /* who knows */
sewardj2a1dcce2002-04-22 12:45:25 +0000495# endif
sewardj6072c362002-04-19 14:40:57 +0000496 return 0;
497}
498
499int pthread_setschedparam(pthread_t target_thread,
500 int policy,
501 const struct sched_param *param)
502{
sewardj436e0582002-04-26 14:31:40 +0000503 static int moans = N_MOANS;
504 if (moans-- > 0)
505 ignored("pthread_setschedparam");
sewardj6072c362002-04-19 14:40:57 +0000506 return 0;
507}
508
sewardj3b5d8862002-04-20 13:53:23 +0000509int pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex)
510{
511 int res;
512 ensure_valgrind("pthread_cond_wait");
513 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
514 VG_USERREQ__PTHREAD_COND_WAIT,
515 cond, mutex, 0, 0);
516 return res;
517}
518
sewardj5f07b662002-04-23 16:52:51 +0000519int pthread_cond_timedwait ( pthread_cond_t *cond,
520 pthread_mutex_t *mutex,
521 const struct timespec *abstime )
522{
523 int res;
524 unsigned int ms_now, ms_end;
525 struct timeval timeval_now;
526 unsigned long long int ull_ms_now_after_1970;
527 unsigned long long int ull_ms_end_after_1970;
528
529 ensure_valgrind("pthread_cond_timedwait");
530 VALGRIND_MAGIC_SEQUENCE(ms_now, 0xFFFFFFFF /* default */,
531 VG_USERREQ__READ_MILLISECOND_TIMER,
532 0, 0, 0, 0);
533 assert(ms_now != 0xFFFFFFFF);
534 res = gettimeofday(&timeval_now, NULL);
535 assert(res == 0);
536
537 ull_ms_now_after_1970
538 = 1000ULL * ((unsigned long long int)(timeval_now.tv_sec))
539 + ((unsigned long long int)(timeval_now.tv_usec / 1000000));
540 ull_ms_end_after_1970
541 = 1000ULL * ((unsigned long long int)(abstime->tv_sec))
542 + ((unsigned long long int)(abstime->tv_nsec / 1000000));
543 assert(ull_ms_end_after_1970 >= ull_ms_now_after_1970);
544 ms_end
545 = ms_now + (unsigned int)(ull_ms_end_after_1970 - ull_ms_now_after_1970);
546 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
547 VG_USERREQ__PTHREAD_COND_TIMEDWAIT,
548 cond, mutex, ms_end, 0);
549 return res;
550}
551
552
sewardj3b5d8862002-04-20 13:53:23 +0000553int pthread_cond_signal(pthread_cond_t *cond)
554{
555 int res;
556 ensure_valgrind("pthread_cond_signal");
557 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
558 VG_USERREQ__PTHREAD_COND_SIGNAL,
559 cond, 0, 0, 0);
560 return res;
561}
562
563int pthread_cond_broadcast(pthread_cond_t *cond)
564{
565 int res;
566 ensure_valgrind("pthread_cond_broadcast");
567 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
568 VG_USERREQ__PTHREAD_COND_BROADCAST,
569 cond, 0, 0, 0);
570 return res;
571}
572
sewardj6072c362002-04-19 14:40:57 +0000573
574/* ---------------------------------------------------
sewardjf8f819e2002-04-17 23:21:37 +0000575 CANCELLATION
576 ------------------------------------------------ */
577
sewardj853f55d2002-04-26 00:27:53 +0000578int pthread_setcancelstate(int state, int *oldstate)
579{
sewardj436e0582002-04-26 14:31:40 +0000580 static int moans = N_MOANS;
581 if (moans-- > 0)
582 ignored("pthread_setcancelstate");
sewardj853f55d2002-04-26 00:27:53 +0000583 return 0;
584}
585
sewardje663cb92002-04-12 10:26:32 +0000586int pthread_setcanceltype(int type, int *oldtype)
587{
sewardj436e0582002-04-26 14:31:40 +0000588 static int moans = N_MOANS;
589 if (moans-- > 0)
590 ignored("pthread_setcanceltype");
sewardje663cb92002-04-12 10:26:32 +0000591 return 0;
592}
593
sewardje663cb92002-04-12 10:26:32 +0000594int pthread_cancel(pthread_t thread)
595{
596 int res;
597 ensure_valgrind("pthread_cancel");
598 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
599 VG_USERREQ__PTHREAD_CANCEL,
600 thread, 0, 0, 0);
601 return res;
602}
603
sewardj853f55d2002-04-26 00:27:53 +0000604void pthread_testcancel(void)
605{
606}
607
608/*-------------------*/
609static pthread_mutex_t massacre_mx = PTHREAD_MUTEX_INITIALIZER;
610
611void __pthread_kill_other_threads_np ( void )
612{
613 int i, res, me;
sewardj68b2dd92002-05-10 21:03:56 +0000614 __pthread_mutex_lock(&massacre_mx);
sewardj853f55d2002-04-26 00:27:53 +0000615 me = pthread_self();
616 for (i = 1; i < VG_N_THREADS; i++) {
617 if (i == me) continue;
618 res = pthread_cancel(i);
sewardj436e0582002-04-26 14:31:40 +0000619 if (0 && res == 0)
sewardj853f55d2002-04-26 00:27:53 +0000620 printf("----------- NUKED %d\n", i);
621 }
sewardj68b2dd92002-05-10 21:03:56 +0000622 __pthread_mutex_unlock(&massacre_mx);
sewardj853f55d2002-04-26 00:27:53 +0000623}
624
sewardje663cb92002-04-12 10:26:32 +0000625
sewardjf8f819e2002-04-17 23:21:37 +0000626/* ---------------------------------------------------
sewardjb48e5002002-05-13 00:16:03 +0000627 SIGNALS
628 ------------------------------------------------ */
629
630#include <signal.h>
631
632int pthread_sigmask(int how, const sigset_t *newmask,
633 sigset_t *oldmask)
634{
635 int res;
636
637 /* A bit subtle, because the scheduler expects newmask and oldmask
638 to be vki_sigset_t* rather than sigset_t*, and the two are
639 different. Fortunately the first 64 bits of a sigset_t are
640 exactly a vki_sigset_t, so we just pass the pointers through
641 unmodified. Haaaack!
642
643 Also mash the how value so that the SIG_ constants from glibc
sewardj018f7622002-05-15 21:13:39 +0000644 constants to VKI_ constants, so that the former do not have to
645 be included into vg_scheduler.c. */
sewardjb48e5002002-05-13 00:16:03 +0000646
647 ensure_valgrind("pthread_sigmask");
648
649 switch (how) {
sewardj018f7622002-05-15 21:13:39 +0000650 case SIG_SETMASK: how = VKI_SIG_SETMASK; break;
651 case SIG_BLOCK: how = VKI_SIG_BLOCK; break;
652 case SIG_UNBLOCK: how = VKI_SIG_UNBLOCK; break;
sewardjb48e5002002-05-13 00:16:03 +0000653 default: return EINVAL;
654 }
655
656 /* Crude check */
657 if (newmask == NULL)
658 return EFAULT;
659
660 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
661 VG_USERREQ__PTHREAD_SIGMASK,
662 how, newmask, oldmask, 0);
663
664 /* The scheduler tells us of any memory violations. */
665 return res == 0 ? 0 : EFAULT;
666}
667
668
669int sigwait ( const sigset_t* set, int* sig )
670{
671 int res;
672 ensure_valgrind("sigwait");
673 /* As with pthread_sigmask we deliberately confuse sigset_t with
674 vki_ksigset_t. */
675 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
676 VG_USERREQ__SIGWAIT,
677 set, sig, 0, 0);
678 return res;
679}
680
681
sewardj018f7622002-05-15 21:13:39 +0000682int pthread_kill(pthread_t thread, int signo)
683{
684 int res;
685 ensure_valgrind("pthread_kill");
686 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
687 VG_USERREQ__PTHREAD_KILL,
688 thread, signo, 0, 0);
689 return res;
690}
691
692
sewardj3665ded2002-05-16 16:57:25 +0000693/* Copied verbatim from Linuxthreads */
694/* Redefine raise() to send signal to calling thread only,
695 as per POSIX 1003.1c */
696int raise (int sig)
697{
698 int retcode = pthread_kill(pthread_self(), sig);
699 if (retcode == 0)
700 return 0;
701 else {
702 errno = retcode;
703 return -1;
704 }
705}
706
707
sewardjb48e5002002-05-13 00:16:03 +0000708/* ---------------------------------------------------
sewardjf8f819e2002-04-17 23:21:37 +0000709 THREAD-SPECIFICs
710 ------------------------------------------------ */
sewardj5e5fa512002-04-14 13:13:05 +0000711
sewardj5905fae2002-04-26 13:25:00 +0000712int __pthread_key_create(pthread_key_t *key,
713 void (*destr_function) (void *))
sewardj5e5fa512002-04-14 13:13:05 +0000714{
sewardj5f07b662002-04-23 16:52:51 +0000715 int res;
716 ensure_valgrind("pthread_key_create");
717 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
718 VG_USERREQ__PTHREAD_KEY_CREATE,
719 key, destr_function, 0, 0);
720 return res;
sewardj5e5fa512002-04-14 13:13:05 +0000721}
722
723int pthread_key_delete(pthread_key_t key)
724{
sewardj436e0582002-04-26 14:31:40 +0000725 static int moans = N_MOANS;
726 if (moans-- > 0)
727 ignored("pthread_key_delete");
sewardj5e5fa512002-04-14 13:13:05 +0000728 return 0;
729}
730
sewardj5905fae2002-04-26 13:25:00 +0000731int __pthread_setspecific(pthread_key_t key, const void *pointer)
sewardj5e5fa512002-04-14 13:13:05 +0000732{
sewardj5f07b662002-04-23 16:52:51 +0000733 int res;
734 ensure_valgrind("pthread_setspecific");
735 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
736 VG_USERREQ__PTHREAD_SETSPECIFIC,
737 key, pointer, 0, 0);
738 return res;
sewardj5e5fa512002-04-14 13:13:05 +0000739}
740
sewardj5905fae2002-04-26 13:25:00 +0000741void * __pthread_getspecific(pthread_key_t key)
sewardj5e5fa512002-04-14 13:13:05 +0000742{
sewardj5f07b662002-04-23 16:52:51 +0000743 int res;
744 ensure_valgrind("pthread_getspecific");
745 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
746 VG_USERREQ__PTHREAD_GETSPECIFIC,
747 key, 0 , 0, 0);
748 return (void*)res;
sewardj5e5fa512002-04-14 13:13:05 +0000749}
750
sewardjf8f819e2002-04-17 23:21:37 +0000751
752/* ---------------------------------------------------
sewardj89d3d852002-04-24 19:21:39 +0000753 ONCEry
754 ------------------------------------------------ */
755
756static pthread_mutex_t once_masterlock = PTHREAD_MUTEX_INITIALIZER;
757
758
sewardj5905fae2002-04-26 13:25:00 +0000759int __pthread_once ( pthread_once_t *once_control,
760 void (*init_routine) (void) )
sewardj89d3d852002-04-24 19:21:39 +0000761{
762 int res;
763 ensure_valgrind("pthread_once");
764
sewardj68b2dd92002-05-10 21:03:56 +0000765 res = __pthread_mutex_lock(&once_masterlock);
sewardj89d3d852002-04-24 19:21:39 +0000766
sewardj68b2dd92002-05-10 21:03:56 +0000767 if (res != 0) {
768 printf("res = %d\n",res);
sewardj89d3d852002-04-24 19:21:39 +0000769 barf("pthread_once: Looks like your program's "
770 "init routine calls back to pthread_once() ?!");
sewardj68b2dd92002-05-10 21:03:56 +0000771 }
sewardj89d3d852002-04-24 19:21:39 +0000772
773 if (*once_control == 0) {
774 *once_control = 1;
775 init_routine();
776 }
777
sewardj68b2dd92002-05-10 21:03:56 +0000778 __pthread_mutex_unlock(&once_masterlock);
sewardj89d3d852002-04-24 19:21:39 +0000779
780 return 0;
781}
782
783
784/* ---------------------------------------------------
sewardj853f55d2002-04-26 00:27:53 +0000785 MISC
786 ------------------------------------------------ */
787
sewardj5905fae2002-04-26 13:25:00 +0000788int __pthread_atfork ( void (*prepare)(void),
789 void (*parent)(void),
790 void (*child)(void) )
sewardj853f55d2002-04-26 00:27:53 +0000791{
sewardj436e0582002-04-26 14:31:40 +0000792 static int moans = N_MOANS;
793 if (moans-- > 0)
794 ignored("pthread_atfork");
sewardj853f55d2002-04-26 00:27:53 +0000795 return 0;
796}
797
798
sewardjbb990782002-05-08 02:01:14 +0000799__attribute__((weak))
800void __pthread_initialize ( void )
801{
sewardjbea1caa2002-05-10 23:20:58 +0000802 ensure_valgrind("__pthread_initialize");
sewardjbb990782002-05-08 02:01:14 +0000803}
804
805
sewardj853f55d2002-04-26 00:27:53 +0000806/* ---------------------------------------------------
sewardj3b13f0e2002-04-25 20:17:29 +0000807 LIBRARY-PRIVATE THREAD SPECIFIC STATE
sewardjf8f819e2002-04-17 23:21:37 +0000808 ------------------------------------------------ */
809
sewardj3b13f0e2002-04-25 20:17:29 +0000810#include <resolv.h>
811static int thread_specific_errno[VG_N_THREADS];
812static int thread_specific_h_errno[VG_N_THREADS];
813static struct __res_state
814 thread_specific_res_state[VG_N_THREADS];
sewardjf8f819e2002-04-17 23:21:37 +0000815
sewardj3b13f0e2002-04-25 20:17:29 +0000816int* __errno_location ( void )
sewardjf8f819e2002-04-17 23:21:37 +0000817{
818 int tid;
sewardj3b13f0e2002-04-25 20:17:29 +0000819 /* ensure_valgrind("__errno_location"); */
820 VALGRIND_MAGIC_SEQUENCE(tid, 1 /* default */,
sewardjf8f819e2002-04-17 23:21:37 +0000821 VG_USERREQ__PTHREAD_GET_THREADID,
822 0, 0, 0, 0);
sewardj3b13f0e2002-04-25 20:17:29 +0000823 /* 'cos I'm paranoid ... */
sewardj439d45e2002-05-03 20:43:10 +0000824 if (tid < 1 || tid >= VG_N_THREADS)
sewardj3b13f0e2002-04-25 20:17:29 +0000825 barf("__errno_location: invalid ThreadId");
826 return & thread_specific_errno[tid];
827}
828
829int* __h_errno_location ( void )
830{
831 int tid;
832 /* ensure_valgrind("__h_errno_location"); */
833 VALGRIND_MAGIC_SEQUENCE(tid, 1 /* default */,
834 VG_USERREQ__PTHREAD_GET_THREADID,
835 0, 0, 0, 0);
836 /* 'cos I'm paranoid ... */
sewardj439d45e2002-05-03 20:43:10 +0000837 if (tid < 1 || tid >= VG_N_THREADS)
sewardj3b13f0e2002-04-25 20:17:29 +0000838 barf("__h_errno_location: invalid ThreadId");
839 return & thread_specific_h_errno[tid];
840}
841
842struct __res_state* __res_state ( void )
843{
844 int tid;
845 /* ensure_valgrind("__res_state"); */
846 VALGRIND_MAGIC_SEQUENCE(tid, 1 /* default */,
847 VG_USERREQ__PTHREAD_GET_THREADID,
848 0, 0, 0, 0);
849 /* 'cos I'm paranoid ... */
sewardj439d45e2002-05-03 20:43:10 +0000850 if (tid < 1 || tid >= VG_N_THREADS)
sewardj3b13f0e2002-04-25 20:17:29 +0000851 barf("__res_state: invalid ThreadId");
852 return & thread_specific_res_state[tid];
sewardjf8f819e2002-04-17 23:21:37 +0000853}
854
855
sewardj5716dbb2002-04-26 03:28:18 +0000856/* ---------------------------------------------------
857 LIBC-PRIVATE SPECIFIC DATA
858 ------------------------------------------------ */
859
860/* Relies on assumption that initial private data is NULL. This
861 should be fixed somehow. */
862
863/* The allowable keys (indices) (all 2 of them).
864 From sysdeps/pthread/bits/libc-tsd.h
865*/
sewardj70adeb22002-04-27 01:35:38 +0000866#define N_LIBC_TSD_EXTRA_KEYS 1
867
sewardj5716dbb2002-04-26 03:28:18 +0000868enum __libc_tsd_key_t { _LIBC_TSD_KEY_MALLOC = 0,
869 _LIBC_TSD_KEY_DL_ERROR,
870 _LIBC_TSD_KEY_N };
871
872/* Auto-initialising subsystem. libc_specifics_inited is set
873 after initialisation. libc_specifics_inited_mx guards it. */
874static int libc_specifics_inited = 0;
875static pthread_mutex_t libc_specifics_inited_mx = PTHREAD_MUTEX_INITIALIZER;
876
877/* These are the keys we must initialise the first time. */
sewardj70adeb22002-04-27 01:35:38 +0000878static pthread_key_t libc_specifics_keys[_LIBC_TSD_KEY_N
879 + N_LIBC_TSD_EXTRA_KEYS];
sewardj5716dbb2002-04-26 03:28:18 +0000880
881/* Initialise the keys, if they are not already initialise. */
882static
883void init_libc_tsd_keys ( void )
884{
885 int res, i;
886 pthread_key_t k;
887
888 res = pthread_mutex_lock(&libc_specifics_inited_mx);
889 if (res != 0) barf("init_libc_tsd_keys: lock");
890
891 if (libc_specifics_inited == 0) {
892 /* printf("INIT libc specifics\n"); */
893 libc_specifics_inited = 1;
sewardj70adeb22002-04-27 01:35:38 +0000894 for (i = 0; i < _LIBC_TSD_KEY_N + N_LIBC_TSD_EXTRA_KEYS; i++) {
sewardj5716dbb2002-04-26 03:28:18 +0000895 res = pthread_key_create(&k, NULL);
896 if (res != 0) barf("init_libc_tsd_keys: create");
897 libc_specifics_keys[i] = k;
898 }
899 }
900
901 res = pthread_mutex_unlock(&libc_specifics_inited_mx);
902 if (res != 0) barf("init_libc_tsd_keys: unlock");
903}
904
905
906static int
907libc_internal_tsd_set ( enum __libc_tsd_key_t key,
908 const void * pointer )
909{
sewardj70adeb22002-04-27 01:35:38 +0000910 int res;
911 static int moans = N_MOANS;
sewardj5716dbb2002-04-26 03:28:18 +0000912 /* printf("SET SET SET key %d ptr %p\n", key, pointer); */
sewardj70adeb22002-04-27 01:35:38 +0000913 if (key < _LIBC_TSD_KEY_MALLOC
914 || key >= _LIBC_TSD_KEY_N + N_LIBC_TSD_EXTRA_KEYS)
sewardj5716dbb2002-04-26 03:28:18 +0000915 barf("libc_internal_tsd_set: invalid key");
sewardj70adeb22002-04-27 01:35:38 +0000916 if (key >= _LIBC_TSD_KEY_N && moans-- > 0)
917 fprintf(stderr,
sewardj439d45e2002-05-03 20:43:10 +0000918 "valgrind's libpthread.so: libc_internal_tsd_set: "
919 "dubious key %d\n", key);
sewardj5716dbb2002-04-26 03:28:18 +0000920 init_libc_tsd_keys();
921 res = pthread_setspecific(libc_specifics_keys[key], pointer);
922 if (res != 0) barf("libc_internal_tsd_set: setspecific failed");
923 return 0;
924}
925
926static void *
927libc_internal_tsd_get ( enum __libc_tsd_key_t key )
928{
sewardj70adeb22002-04-27 01:35:38 +0000929 void* v;
930 static int moans = N_MOANS;
sewardj5716dbb2002-04-26 03:28:18 +0000931 /* printf("GET GET GET key %d\n", key); */
sewardj70adeb22002-04-27 01:35:38 +0000932 if (key < _LIBC_TSD_KEY_MALLOC
933 || key >= _LIBC_TSD_KEY_N + N_LIBC_TSD_EXTRA_KEYS)
sewardj5716dbb2002-04-26 03:28:18 +0000934 barf("libc_internal_tsd_get: invalid key");
sewardj70adeb22002-04-27 01:35:38 +0000935 if (key >= _LIBC_TSD_KEY_N && moans-- > 0)
936 fprintf(stderr,
sewardj439d45e2002-05-03 20:43:10 +0000937 "valgrind's libpthread.so: libc_internal_tsd_get: "
938 "dubious key %d\n", key);
sewardj5716dbb2002-04-26 03:28:18 +0000939 init_libc_tsd_keys();
940 v = pthread_getspecific(libc_specifics_keys[key]);
941 /* if (v == NULL) barf("libc_internal_tsd_set: getspecific failed"); */
942 return v;
943}
944
945
946
947
sewardj70adeb22002-04-27 01:35:38 +0000948int (*__libc_internal_tsd_set)
949 (enum __libc_tsd_key_t key, const void * pointer)
950 = libc_internal_tsd_set;
sewardj5716dbb2002-04-26 03:28:18 +0000951
sewardj70adeb22002-04-27 01:35:38 +0000952void* (*__libc_internal_tsd_get)
953 (enum __libc_tsd_key_t key)
954 = libc_internal_tsd_get;
sewardj5716dbb2002-04-26 03:28:18 +0000955
956
sewardje663cb92002-04-12 10:26:32 +0000957/* ---------------------------------------------------------------------
958 These are here (I think) because they are deemed cancellation
959 points by POSIX. For the moment we'll simply pass the call along
960 to the corresponding thread-unaware (?) libc routine.
961 ------------------------------------------------------------------ */
962
sewardje663cb92002-04-12 10:26:32 +0000963#include <stdlib.h>
sewardje663cb92002-04-12 10:26:32 +0000964#include <sys/types.h>
965#include <sys/socket.h>
966
sewardjd529a442002-05-04 19:49:21 +0000967#ifdef GLIBC_2_1
968extern
969int __sigaction
970 (int signum,
971 const struct sigaction *act,
972 struct sigaction *oldact);
973#else
sewardje663cb92002-04-12 10:26:32 +0000974extern
975int __libc_sigaction
976 (int signum,
977 const struct sigaction *act,
978 struct sigaction *oldact);
sewardjd529a442002-05-04 19:49:21 +0000979#endif
sewardje663cb92002-04-12 10:26:32 +0000980int sigaction(int signum,
981 const struct sigaction *act,
982 struct sigaction *oldact)
983{
sewardj2a1dcce2002-04-22 12:45:25 +0000984# ifdef GLIBC_2_1
985 return __sigaction(signum, act, oldact);
986# else
sewardj45b4b372002-04-16 22:50:32 +0000987 return __libc_sigaction(signum, act, oldact);
sewardj2a1dcce2002-04-22 12:45:25 +0000988# endif
sewardje663cb92002-04-12 10:26:32 +0000989}
990
991
992extern
993int __libc_connect(int sockfd,
994 const struct sockaddr *serv_addr,
995 socklen_t addrlen);
sewardj5905fae2002-04-26 13:25:00 +0000996__attribute__((weak))
sewardje663cb92002-04-12 10:26:32 +0000997int connect(int sockfd,
998 const struct sockaddr *serv_addr,
999 socklen_t addrlen)
1000{
sewardj45b4b372002-04-16 22:50:32 +00001001 return __libc_connect(sockfd, serv_addr, addrlen);
sewardje663cb92002-04-12 10:26:32 +00001002}
1003
1004
1005extern
1006int __libc_fcntl(int fd, int cmd, long arg);
sewardj5905fae2002-04-26 13:25:00 +00001007__attribute__((weak))
sewardje663cb92002-04-12 10:26:32 +00001008int fcntl(int fd, int cmd, long arg)
1009{
sewardj45b4b372002-04-16 22:50:32 +00001010 return __libc_fcntl(fd, cmd, arg);
sewardje663cb92002-04-12 10:26:32 +00001011}
1012
1013
1014extern
1015ssize_t __libc_write(int fd, const void *buf, size_t count);
sewardj5905fae2002-04-26 13:25:00 +00001016__attribute__((weak))
sewardje663cb92002-04-12 10:26:32 +00001017ssize_t write(int fd, const void *buf, size_t count)
1018{
sewardj45b4b372002-04-16 22:50:32 +00001019 return __libc_write(fd, buf, count);
sewardje663cb92002-04-12 10:26:32 +00001020}
1021
1022
1023extern
1024ssize_t __libc_read(int fd, void *buf, size_t count);
sewardj5905fae2002-04-26 13:25:00 +00001025__attribute__((weak))
sewardje663cb92002-04-12 10:26:32 +00001026ssize_t read(int fd, void *buf, size_t count)
1027{
sewardj45b4b372002-04-16 22:50:32 +00001028 return __libc_read(fd, buf, count);
sewardje663cb92002-04-12 10:26:32 +00001029}
1030
sewardjbe32e452002-04-24 20:29:58 +00001031
1032extern
sewardj853f55d2002-04-26 00:27:53 +00001033int __libc_open64(const char *pathname, int flags, mode_t mode);
sewardj5905fae2002-04-26 13:25:00 +00001034__attribute__((weak))
sewardj853f55d2002-04-26 00:27:53 +00001035int open64(const char *pathname, int flags, mode_t mode)
sewardjbe32e452002-04-24 20:29:58 +00001036{
sewardj853f55d2002-04-26 00:27:53 +00001037 return __libc_open64(pathname, flags, mode);
sewardjbe32e452002-04-24 20:29:58 +00001038}
1039
sewardje663cb92002-04-12 10:26:32 +00001040
1041extern
sewardj853f55d2002-04-26 00:27:53 +00001042int __libc_open(const char *pathname, int flags, mode_t mode);
sewardj5905fae2002-04-26 13:25:00 +00001043__attribute__((weak))
sewardj853f55d2002-04-26 00:27:53 +00001044int open(const char *pathname, int flags, mode_t mode)
sewardje663cb92002-04-12 10:26:32 +00001045{
sewardj853f55d2002-04-26 00:27:53 +00001046 return __libc_open(pathname, flags, mode);
sewardje663cb92002-04-12 10:26:32 +00001047}
1048
1049
1050extern
1051int __libc_close(int fd);
sewardj5905fae2002-04-26 13:25:00 +00001052__attribute__((weak))
sewardje663cb92002-04-12 10:26:32 +00001053int close(int fd)
1054{
sewardj45b4b372002-04-16 22:50:32 +00001055 return __libc_close(fd);
sewardje663cb92002-04-12 10:26:32 +00001056}
1057
1058
1059extern
1060int __libc_accept(int s, struct sockaddr *addr, socklen_t *addrlen);
sewardj5905fae2002-04-26 13:25:00 +00001061__attribute__((weak))
sewardje663cb92002-04-12 10:26:32 +00001062int accept(int s, struct sockaddr *addr, socklen_t *addrlen)
1063{
sewardj45b4b372002-04-16 22:50:32 +00001064 return __libc_accept(s, addr, addrlen);
sewardje663cb92002-04-12 10:26:32 +00001065}
1066
1067
1068extern
1069pid_t __libc_fork(void);
sewardj5905fae2002-04-26 13:25:00 +00001070pid_t __fork(void)
sewardje663cb92002-04-12 10:26:32 +00001071{
sewardj45b4b372002-04-16 22:50:32 +00001072 return __libc_fork();
sewardje663cb92002-04-12 10:26:32 +00001073}
1074
1075
1076extern
1077pid_t __libc_waitpid(pid_t pid, int *status, int options);
sewardj5905fae2002-04-26 13:25:00 +00001078__attribute__((weak))
sewardje663cb92002-04-12 10:26:32 +00001079pid_t waitpid(pid_t pid, int *status, int options)
1080{
sewardj45b4b372002-04-16 22:50:32 +00001081 return __libc_waitpid(pid, status, options);
sewardje663cb92002-04-12 10:26:32 +00001082}
1083
1084
1085extern
1086int __libc_nanosleep(const struct timespec *req, struct timespec *rem);
sewardj5905fae2002-04-26 13:25:00 +00001087__attribute__((weak))
sewardje663cb92002-04-12 10:26:32 +00001088int nanosleep(const struct timespec *req, struct timespec *rem)
1089{
1090 return __libc_nanosleep(req, rem);
1091}
1092
sewardjbe32e452002-04-24 20:29:58 +00001093
sewardje663cb92002-04-12 10:26:32 +00001094extern
1095int __libc_fsync(int fd);
sewardj5905fae2002-04-26 13:25:00 +00001096__attribute__((weak))
sewardje663cb92002-04-12 10:26:32 +00001097int fsync(int fd)
1098{
sewardj45b4b372002-04-16 22:50:32 +00001099 return __libc_fsync(fd);
sewardje663cb92002-04-12 10:26:32 +00001100}
1101
sewardjbe32e452002-04-24 20:29:58 +00001102
sewardj70c75362002-04-13 04:18:32 +00001103extern
1104off_t __libc_lseek(int fildes, off_t offset, int whence);
sewardj5905fae2002-04-26 13:25:00 +00001105__attribute__((weak))
sewardj70c75362002-04-13 04:18:32 +00001106off_t lseek(int fildes, off_t offset, int whence)
1107{
sewardj45b4b372002-04-16 22:50:32 +00001108 return __libc_lseek(fildes, offset, whence);
sewardj70c75362002-04-13 04:18:32 +00001109}
1110
sewardjbe32e452002-04-24 20:29:58 +00001111
1112extern
1113__off64_t __libc_lseek64(int fildes, __off64_t offset, int whence);
sewardj5905fae2002-04-26 13:25:00 +00001114__attribute__((weak))
sewardjbe32e452002-04-24 20:29:58 +00001115__off64_t lseek64(int fildes, __off64_t offset, int whence)
1116{
1117 return __libc_lseek64(fildes, offset, whence);
1118}
1119
1120
sewardj726c4122002-05-16 23:39:10 +00001121extern
1122ssize_t __libc_pread64 (int __fd, void *__buf, size_t __nbytes,
1123 __off64_t __offset);
1124ssize_t __pread64 (int __fd, void *__buf, size_t __nbytes,
1125 __off64_t __offset)
1126{
1127 return __libc_pread64(__fd, __buf, __nbytes, __offset);
1128}
1129
1130
sewardja18e2102002-05-18 10:43:22 +00001131extern
1132ssize_t __libc_pwrite64 (int __fd, const void *__buf, size_t __nbytes,
1133 __off64_t __offset);
1134ssize_t __pwrite64 (int __fd, const void *__buf, size_t __nbytes,
1135 __off64_t __offset)
1136{
1137 return __libc_pwrite64(__fd, __buf, __nbytes, __offset);
1138}
1139
sewardj726c4122002-05-16 23:39:10 +00001140
sewardj6af4b5d2002-04-16 04:40:49 +00001141extern
1142void __libc_longjmp(jmp_buf env, int val) __attribute((noreturn));
sewardj5905fae2002-04-26 13:25:00 +00001143/* not weak: __attribute__((weak)) */
sewardj6af4b5d2002-04-16 04:40:49 +00001144void longjmp(jmp_buf env, int val)
1145{
1146 __libc_longjmp(env, val);
1147}
1148
sewardjbe32e452002-04-24 20:29:58 +00001149
sewardj6af4b5d2002-04-16 04:40:49 +00001150extern
1151int __libc_send(int s, const void *msg, size_t len, int flags);
sewardj5905fae2002-04-26 13:25:00 +00001152__attribute__((weak))
sewardj6af4b5d2002-04-16 04:40:49 +00001153int send(int s, const void *msg, size_t len, int flags)
1154{
1155 return __libc_send(s, msg, len, flags);
1156}
1157
sewardjbe32e452002-04-24 20:29:58 +00001158
sewardj1e8cdc92002-04-18 11:37:52 +00001159extern
1160int __libc_recv(int s, void *buf, size_t len, int flags);
sewardj5905fae2002-04-26 13:25:00 +00001161__attribute__((weak))
sewardj1e8cdc92002-04-18 11:37:52 +00001162int recv(int s, void *buf, size_t len, int flags)
1163{
1164 return __libc_recv(s, buf, len, flags);
1165}
1166
sewardjbe32e452002-04-24 20:29:58 +00001167
sewardj3665ded2002-05-16 16:57:25 +00001168extern
1169int __libc_sendmsg(int s, const struct msghdr *msg, int flags);
1170__attribute__((weak))
1171int sendmsg(int s, const struct msghdr *msg, int flags)
1172{
1173 return __libc_sendmsg(s, msg, flags);
1174}
1175
1176
sewardj796d6a22002-04-24 02:28:34 +00001177extern
sewardj436e0582002-04-26 14:31:40 +00001178int __libc_recvfrom(int s, void *buf, size_t len, int flags,
1179 struct sockaddr *from, socklen_t *fromlen);
1180__attribute__((weak))
1181int recvfrom(int s, void *buf, size_t len, int flags,
1182 struct sockaddr *from, socklen_t *fromlen)
1183{
1184 return __libc_recvfrom(s, buf, len, flags, from, fromlen);
1185}
1186
1187
1188extern
sewardj796d6a22002-04-24 02:28:34 +00001189int __libc_sendto(int s, const void *msg, size_t len, int flags,
1190 const struct sockaddr *to, socklen_t tolen);
sewardj5905fae2002-04-26 13:25:00 +00001191__attribute__((weak))
sewardj796d6a22002-04-24 02:28:34 +00001192int sendto(int s, const void *msg, size_t len, int flags,
1193 const struct sockaddr *to, socklen_t tolen)
1194{
1195 return __libc_sendto(s, msg, len, flags, to, tolen);
1196}
1197
sewardjbe32e452002-04-24 20:29:58 +00001198
sewardj369b1702002-04-24 13:28:15 +00001199extern
1200int __libc_system(const char* str);
sewardj5905fae2002-04-26 13:25:00 +00001201__attribute__((weak))
sewardj369b1702002-04-24 13:28:15 +00001202int system(const char* str)
1203{
1204 return __libc_system(str);
1205}
1206
sewardjbe32e452002-04-24 20:29:58 +00001207
sewardjab0b1c32002-04-24 19:26:47 +00001208extern
1209pid_t __libc_wait(int *status);
sewardj5905fae2002-04-26 13:25:00 +00001210__attribute__((weak))
sewardjab0b1c32002-04-24 19:26:47 +00001211pid_t wait(int *status)
1212{
1213 return __libc_wait(status);
1214}
1215
sewardj45b4b372002-04-16 22:50:32 +00001216
sewardj5905fae2002-04-26 13:25:00 +00001217
sewardj3b13f0e2002-04-25 20:17:29 +00001218/* ---------------------------------------------------------------------
1219 Nonblocking implementations of select() and poll(). This stuff will
1220 surely rot your mind.
1221 ------------------------------------------------------------------ */
sewardje663cb92002-04-12 10:26:32 +00001222
sewardj08a4c3f2002-04-13 03:45:44 +00001223/*--------------------------------------------------*/
1224
1225#include "vg_kerneliface.h"
1226
1227static
1228__inline__
1229int is_kerror ( int res )
1230{
1231 if (res >= -4095 && res <= -1)
1232 return 1;
1233 else
1234 return 0;
1235}
1236
1237
1238static
1239int my_do_syscall1 ( int syscallno, int arg1 )
1240{
1241 int __res;
1242 __asm__ volatile ("pushl %%ebx; movl %%edx,%%ebx ; int $0x80 ; popl %%ebx"
1243 : "=a" (__res)
1244 : "0" (syscallno),
1245 "d" (arg1) );
1246 return __res;
1247}
1248
1249static
1250int my_do_syscall2 ( int syscallno,
sewardjf854f472002-04-21 12:19:41 +00001251 int arg1, int arg2 )
sewardj08a4c3f2002-04-13 03:45:44 +00001252{
1253 int __res;
1254 __asm__ volatile ("pushl %%ebx; movl %%edx,%%ebx ; int $0x80 ; popl %%ebx"
1255 : "=a" (__res)
1256 : "0" (syscallno),
1257 "d" (arg1),
1258 "c" (arg2) );
1259 return __res;
1260}
1261
1262static
sewardjf854f472002-04-21 12:19:41 +00001263int my_do_syscall3 ( int syscallno,
1264 int arg1, int arg2, int arg3 )
1265{
1266 int __res;
1267 __asm__ volatile ("pushl %%ebx; movl %%esi,%%ebx ; int $0x80 ; popl %%ebx"
1268 : "=a" (__res)
1269 : "0" (syscallno),
1270 "S" (arg1),
1271 "c" (arg2),
1272 "d" (arg3) );
1273 return __res;
1274}
1275
1276static
sewardj08a4c3f2002-04-13 03:45:44 +00001277int do_syscall_select( int n,
1278 vki_fd_set* readfds,
1279 vki_fd_set* writefds,
1280 vki_fd_set* exceptfds,
1281 struct vki_timeval * timeout )
1282{
1283 int res;
1284 int args[5];
1285 args[0] = n;
1286 args[1] = (int)readfds;
1287 args[2] = (int)writefds;
1288 args[3] = (int)exceptfds;
1289 args[4] = (int)timeout;
1290 res = my_do_syscall1(__NR_select, (int)(&(args[0])) );
sewardj02535bc2002-04-21 01:08:26 +00001291 return res;
sewardj08a4c3f2002-04-13 03:45:44 +00001292}
1293
1294
1295/* This is a wrapper round select(), which makes it thread-safe,
1296 meaning that only this thread will block, rather than the entire
1297 process. This wrapper in turn depends on nanosleep() not to block
1298 the entire process, but I think (hope? suspect?) that POSIX
1299 pthreads guarantees that to be the case.
1300
1301 Basic idea is: modify the timeout parameter to select so that it
1302 returns immediately. Poll like this until select returns non-zero,
1303 indicating something interesting happened, or until our time is up.
1304 Space out the polls with nanosleeps of say 20 milliseconds, which
1305 is required to be nonblocking; this allows other threads to run.
sewardj02535bc2002-04-21 01:08:26 +00001306
1307 Assumes:
1308 * (checked via assert) types fd_set and vki_fd_set are identical.
1309 * (checked via assert) types timeval and vki_timeval are identical.
1310 * (unchecked) libc error numbers (EINTR etc) are the negation of the
1311 kernel's error numbers (VKI_EINTR etc).
sewardj08a4c3f2002-04-13 03:45:44 +00001312*/
sewardj08a4c3f2002-04-13 03:45:44 +00001313
sewardj5905fae2002-04-26 13:25:00 +00001314/* __attribute__((weak)) */
sewardj08a4c3f2002-04-13 03:45:44 +00001315int select ( int n,
1316 fd_set *rfds,
1317 fd_set *wfds,
1318 fd_set *xfds,
1319 struct timeval *timeout )
1320{
sewardj5f07b662002-04-23 16:52:51 +00001321 unsigned int ms_now, ms_end;
sewardj08a4c3f2002-04-13 03:45:44 +00001322 int res;
1323 fd_set rfds_copy;
1324 fd_set wfds_copy;
1325 fd_set xfds_copy;
1326 struct vki_timeval t_now;
sewardj08a4c3f2002-04-13 03:45:44 +00001327 struct vki_timeval zero_timeout;
1328 struct vki_timespec nanosleep_interval;
1329
sewardj5f07b662002-04-23 16:52:51 +00001330 /* gcc's complains about ms_end being used uninitialised -- classic
1331 case it can't understand, where ms_end is both defined and used
1332 only if timeout != NULL. Hence ... */
1333 ms_end = 0;
sewardj08a4c3f2002-04-13 03:45:44 +00001334
1335 /* We assume that the kernel and libc data layouts are identical
1336 for the following types. These asserts provide a crude
1337 check. */
1338 if (sizeof(fd_set) != sizeof(vki_fd_set)
1339 || sizeof(struct timeval) != sizeof(struct vki_timeval))
1340 barf("valgrind's hacky non-blocking select(): data sizes error");
1341
sewardj5f07b662002-04-23 16:52:51 +00001342 /* Detect the current time and simultaneously find out if we are
1343 running on Valgrind. */
1344 VALGRIND_MAGIC_SEQUENCE(ms_now, 0xFFFFFFFF /* default */,
1345 VG_USERREQ__READ_MILLISECOND_TIMER,
1346 0, 0, 0, 0);
1347
1348 /* If a zero timeout specified, this call is harmless. Also go
1349 this route if we're not running on Valgrind, for whatever
1350 reason. */
1351 if ( (timeout && timeout->tv_sec == 0 && timeout->tv_usec == 0)
1352 || (ms_now == 0xFFFFFFFF) ) {
sewardj02535bc2002-04-21 01:08:26 +00001353 res = do_syscall_select( n, (vki_fd_set*)rfds,
sewardj08a4c3f2002-04-13 03:45:44 +00001354 (vki_fd_set*)wfds,
1355 (vki_fd_set*)xfds,
1356 (struct vki_timeval*)timeout);
sewardj02535bc2002-04-21 01:08:26 +00001357 if (is_kerror(res)) {
1358 * (__errno_location()) = -res;
1359 return -1;
1360 } else {
1361 return res;
1362 }
1363 }
sewardj08a4c3f2002-04-13 03:45:44 +00001364
sewardj5f07b662002-04-23 16:52:51 +00001365 /* If a timeout was specified, set ms_end to be the end millisecond
1366 counter [wallclock] time. */
sewardj08a4c3f2002-04-13 03:45:44 +00001367 if (timeout) {
1368 res = my_do_syscall2(__NR_gettimeofday, (int)&t_now, (int)NULL);
1369 assert(res == 0);
sewardj5f07b662002-04-23 16:52:51 +00001370 ms_end = ms_now;
1371 ms_end += (timeout->tv_usec / 1000);
1372 ms_end += (timeout->tv_sec * 1000);
sewardj08a4c3f2002-04-13 03:45:44 +00001373 /* Stay sane ... */
sewardj5f07b662002-04-23 16:52:51 +00001374 assert (ms_end >= ms_now);
sewardj08a4c3f2002-04-13 03:45:44 +00001375 }
1376
1377 /* fprintf(stderr, "MY_SELECT: before loop\n"); */
1378
1379 /* Either timeout == NULL, meaning wait indefinitely, or timeout !=
sewardj5f07b662002-04-23 16:52:51 +00001380 NULL, in which case ms_end holds the end time. */
sewardj08a4c3f2002-04-13 03:45:44 +00001381 while (1) {
1382 if (timeout) {
sewardj5f07b662002-04-23 16:52:51 +00001383 VALGRIND_MAGIC_SEQUENCE(ms_now, 0xFFFFFFFF /* default */,
1384 VG_USERREQ__READ_MILLISECOND_TIMER,
1385 0, 0, 0, 0);
1386 assert(ms_now != 0xFFFFFFFF);
1387 if (ms_now >= ms_end) {
sewardj08a4c3f2002-04-13 03:45:44 +00001388 /* timeout; nothing interesting happened. */
1389 if (rfds) FD_ZERO(rfds);
1390 if (wfds) FD_ZERO(wfds);
1391 if (xfds) FD_ZERO(xfds);
1392 return 0;
1393 }
1394 }
1395
1396 /* These could be trashed each time round the loop, so restore
1397 them each time. */
1398 if (rfds) rfds_copy = *rfds;
1399 if (wfds) wfds_copy = *wfds;
1400 if (xfds) xfds_copy = *xfds;
1401
1402 zero_timeout.tv_sec = zero_timeout.tv_usec = 0;
1403
1404 res = do_syscall_select( n,
1405 rfds ? (vki_fd_set*)(&rfds_copy) : NULL,
1406 wfds ? (vki_fd_set*)(&wfds_copy) : NULL,
1407 xfds ? (vki_fd_set*)(&xfds_copy) : NULL,
1408 & zero_timeout );
sewardj02535bc2002-04-21 01:08:26 +00001409 if (is_kerror(res)) {
1410 /* Some kind of error (including EINTR). Set errno and
sewardj08a4c3f2002-04-13 03:45:44 +00001411 return. The sets are unspecified in this case. */
sewardj02535bc2002-04-21 01:08:26 +00001412 * (__errno_location()) = -res;
1413 return -1;
sewardj08a4c3f2002-04-13 03:45:44 +00001414 }
1415 if (res > 0) {
1416 /* one or more fds is ready. Copy out resulting sets and
1417 return. */
1418 if (rfds) *rfds = rfds_copy;
1419 if (wfds) *wfds = wfds_copy;
1420 if (xfds) *xfds = xfds_copy;
1421 return res;
1422 }
1423 /* fprintf(stderr, "MY_SELECT: nanosleep\n"); */
1424 /* nanosleep and go round again */
sewardj02535bc2002-04-21 01:08:26 +00001425 nanosleep_interval.tv_sec = 0;
sewardj956cc1b2002-04-25 01:33:50 +00001426 nanosleep_interval.tv_nsec = 50 * 1000 * 1000; /* 50 milliseconds */
sewardjf854f472002-04-21 12:19:41 +00001427 /* It's critical here that valgrind's nanosleep implementation
1428 is nonblocking. */
1429 (void)my_do_syscall2(__NR_nanosleep,
1430 (int)(&nanosleep_interval), (int)NULL);
1431 }
1432}
1433
1434
1435
1436
1437#include <sys/poll.h>
1438
sewardj72d58482002-04-24 02:20:20 +00001439#ifdef GLIBC_2_1
1440typedef unsigned long int nfds_t;
1441#endif
1442
sewardj5905fae2002-04-26 13:25:00 +00001443/* __attribute__((weak)) */
sewardjf854f472002-04-21 12:19:41 +00001444int poll (struct pollfd *__fds, nfds_t __nfds, int __timeout)
1445{
sewardj5f07b662002-04-23 16:52:51 +00001446 unsigned int ms_now, ms_end;
sewardjf854f472002-04-21 12:19:41 +00001447 int res, i;
sewardjf854f472002-04-21 12:19:41 +00001448 struct vki_timespec nanosleep_interval;
1449
1450 ensure_valgrind("poll");
1451
sewardj5f07b662002-04-23 16:52:51 +00001452 /* Detect the current time and simultaneously find out if we are
1453 running on Valgrind. */
1454 VALGRIND_MAGIC_SEQUENCE(ms_now, 0xFFFFFFFF /* default */,
1455 VG_USERREQ__READ_MILLISECOND_TIMER,
1456 0, 0, 0, 0);
1457
sewardjf854f472002-04-21 12:19:41 +00001458 if (/* CHECK SIZES FOR struct pollfd */
1459 sizeof(struct timeval) != sizeof(struct vki_timeval))
1460 barf("valgrind's hacky non-blocking poll(): data sizes error");
1461
sewardj5f07b662002-04-23 16:52:51 +00001462 /* dummy initialisation to keep gcc -Wall happy */
1463 ms_end = 0;
1464
1465 /* If a zero timeout specified, this call is harmless. Also do
1466 this if not running on Valgrind. */
1467 if (__timeout == 0 || ms_now == 0xFFFFFFFF) {
sewardjf854f472002-04-21 12:19:41 +00001468 res = my_do_syscall3(__NR_poll, (int)__fds, __nfds, __timeout);
1469 if (is_kerror(res)) {
1470 * (__errno_location()) = -res;
1471 return -1;
1472 } else {
1473 return res;
1474 }
1475 }
1476
sewardj5f07b662002-04-23 16:52:51 +00001477 /* If a timeout was specified, set ms_end to be the end wallclock
1478 time. Easy considering that __timeout is in milliseconds. */
sewardjf854f472002-04-21 12:19:41 +00001479 if (__timeout > 0) {
sewardj650ac002002-04-29 12:20:34 +00001480 ms_end = ms_now + (unsigned int)__timeout;
sewardjf854f472002-04-21 12:19:41 +00001481 }
1482
1483 /* fprintf(stderr, "MY_POLL: before loop\n"); */
1484
1485 /* Either timeout < 0, meaning wait indefinitely, or timeout > 0,
1486 in which case t_end holds the end time. */
sewardj5f07b662002-04-23 16:52:51 +00001487 assert(__timeout != 0);
1488
sewardjf854f472002-04-21 12:19:41 +00001489 while (1) {
sewardjf854f472002-04-21 12:19:41 +00001490 if (__timeout > 0) {
sewardj5f07b662002-04-23 16:52:51 +00001491 VALGRIND_MAGIC_SEQUENCE(ms_now, 0xFFFFFFFF /* default */,
1492 VG_USERREQ__READ_MILLISECOND_TIMER,
1493 0, 0, 0, 0);
1494 assert(ms_now != 0xFFFFFFFF);
1495 if (ms_now >= ms_end) {
sewardjf854f472002-04-21 12:19:41 +00001496 /* timeout; nothing interesting happened. */
1497 for (i = 0; i < __nfds; i++)
1498 __fds[i].revents = 0;
1499 return 0;
1500 }
1501 }
1502
sewardj5f07b662002-04-23 16:52:51 +00001503 /* Do a return-immediately poll. */
sewardjf854f472002-04-21 12:19:41 +00001504 res = my_do_syscall3(__NR_poll, (int)__fds, __nfds, 0 );
1505 if (is_kerror(res)) {
1506 /* Some kind of error. Set errno and return. */
1507 * (__errno_location()) = -res;
1508 return -1;
1509 }
1510 if (res > 0) {
1511 /* One or more fds is ready. Return now. */
1512 return res;
1513 }
1514 /* fprintf(stderr, "MY_POLL: nanosleep\n"); */
1515 /* nanosleep and go round again */
1516 nanosleep_interval.tv_sec = 0;
sewardj956cc1b2002-04-25 01:33:50 +00001517 nanosleep_interval.tv_nsec = 51 * 1000 * 1000; /* 51 milliseconds */
sewardj08a4c3f2002-04-13 03:45:44 +00001518 /* It's critical here that valgrind's nanosleep implementation
1519 is nonblocking. */
1520 (void)my_do_syscall2(__NR_nanosleep,
1521 (int)(&nanosleep_interval), (int)NULL);
1522 }
1523}
sewardj3b13f0e2002-04-25 20:17:29 +00001524
1525
1526/* ---------------------------------------------------------------------
1527 B'stard.
1528 ------------------------------------------------------------------ */
1529
1530# define strong_alias(name, aliasname) \
1531 extern __typeof (name) aliasname __attribute__ ((alias (#name)));
1532
sewardj5905fae2002-04-26 13:25:00 +00001533# define weak_alias(name, aliasname) \
1534 extern __typeof (name) aliasname __attribute__ ((weak, alias (#name)));
sewardj3b13f0e2002-04-25 20:17:29 +00001535
sewardj5905fae2002-04-26 13:25:00 +00001536strong_alias(__pthread_mutex_lock, pthread_mutex_lock)
1537strong_alias(__pthread_mutex_trylock, pthread_mutex_trylock)
1538strong_alias(__pthread_mutex_unlock, pthread_mutex_unlock)
1539strong_alias(__pthread_mutexattr_init, pthread_mutexattr_init)
1540 weak_alias(__pthread_mutexattr_settype, pthread_mutexattr_settype)
1541strong_alias(__pthread_mutex_init, pthread_mutex_init)
1542strong_alias(__pthread_mutexattr_destroy, pthread_mutexattr_destroy)
1543strong_alias(__pthread_mutex_destroy, pthread_mutex_destroy)
1544strong_alias(__pthread_once, pthread_once)
1545strong_alias(__pthread_atfork, pthread_atfork)
1546strong_alias(__pthread_key_create, pthread_key_create)
1547strong_alias(__pthread_getspecific, pthread_getspecific)
1548strong_alias(__pthread_setspecific, pthread_setspecific)
1549
sewardjd529a442002-05-04 19:49:21 +00001550#ifndef GLIBC_2_1
sewardj3b13f0e2002-04-25 20:17:29 +00001551strong_alias(sigaction, __sigaction)
sewardjd529a442002-05-04 19:49:21 +00001552#endif
1553
sewardj5905fae2002-04-26 13:25:00 +00001554strong_alias(close, __close)
sewardj3b13f0e2002-04-25 20:17:29 +00001555strong_alias(fcntl, __fcntl)
sewardj5905fae2002-04-26 13:25:00 +00001556strong_alias(lseek, __lseek)
1557strong_alias(open, __open)
1558strong_alias(open64, __open64)
1559//strong_alias(pread64, __pread64)
1560//strong_alias(pwrite64, __pwrite64)
1561strong_alias(read, __read)
1562strong_alias(wait, __wait)
1563strong_alias(write, __write)
sewardj3b13f0e2002-04-25 20:17:29 +00001564strong_alias(connect, __connect)
sewardj5905fae2002-04-26 13:25:00 +00001565strong_alias(send, __send)
1566
sewardj726c4122002-05-16 23:39:10 +00001567weak_alias (__pread64, pread64)
sewardja18e2102002-05-18 10:43:22 +00001568weak_alias (__pwrite64, pwrite64)
sewardj5905fae2002-04-26 13:25:00 +00001569weak_alias(__fork, fork)
1570//weak_alias(__vfork, vfork)
1571
sewardj3b13f0e2002-04-25 20:17:29 +00001572
1573/*--------------------------------------------------*/
1574
sewardj5716dbb2002-04-26 03:28:18 +00001575int
1576pthread_rwlock_rdlock (void* /* pthread_rwlock_t* */ rwlock)
1577{
sewardj436e0582002-04-26 14:31:40 +00001578 static int moans = N_MOANS;
1579 if (moans-- > 0)
1580 kludged("pthread_rwlock_rdlock");
sewardj5716dbb2002-04-26 03:28:18 +00001581 return 0;
1582}
1583
sewardj5905fae2002-04-26 13:25:00 +00001584weak_alias(pthread_rwlock_rdlock, __pthread_rwlock_rdlock)
sewardj5716dbb2002-04-26 03:28:18 +00001585
1586
1587int
1588pthread_rwlock_unlock (void* /* pthread_rwlock_t* */ rwlock)
1589{
sewardj436e0582002-04-26 14:31:40 +00001590 static int moans = N_MOANS;
1591 if (moans-- > 0)
1592 kludged("pthread_rwlock_unlock");
sewardj5716dbb2002-04-26 03:28:18 +00001593 return 0;
1594}
1595
sewardj5905fae2002-04-26 13:25:00 +00001596weak_alias(pthread_rwlock_unlock, __pthread_rwlock_unlock)
sewardj5716dbb2002-04-26 03:28:18 +00001597
1598
sewardj060b04f2002-04-26 21:01:13 +00001599int
1600pthread_rwlock_wrlock (void* /* pthread_rwlock_t* */ rwlock)
1601{
1602 static int moans = N_MOANS;
1603 if (moans-- > 0)
1604 kludged("pthread_rwlock_wrlock");
1605 return 0;
1606}
1607
sewardj262b0292002-05-01 00:03:16 +00001608weak_alias(pthread_rwlock_wrlock, __pthread_rwlock_wrlock)
sewardj060b04f2002-04-26 21:01:13 +00001609
1610
sewardj3b13f0e2002-04-25 20:17:29 +00001611/* I've no idea what these are, but they get called quite a lot.
1612 Anybody know? */
1613
1614#undef _IO_flockfile
1615void _IO_flockfile ( _IO_FILE * file )
1616{
sewardj853f55d2002-04-26 00:27:53 +00001617 pthread_mutex_lock(file->_lock);
sewardj3b13f0e2002-04-25 20:17:29 +00001618}
sewardj5905fae2002-04-26 13:25:00 +00001619weak_alias(_IO_flockfile, flockfile);
1620
sewardj3b13f0e2002-04-25 20:17:29 +00001621
1622#undef _IO_funlockfile
1623void _IO_funlockfile ( _IO_FILE * file )
1624{
sewardj853f55d2002-04-26 00:27:53 +00001625 pthread_mutex_unlock(file->_lock);
sewardj3b13f0e2002-04-25 20:17:29 +00001626}
sewardj5905fae2002-04-26 13:25:00 +00001627weak_alias(_IO_funlockfile, funlockfile);
1628
sewardj3b13f0e2002-04-25 20:17:29 +00001629
1630void _pthread_cleanup_push_defer ( void )
1631{
sewardj439d45e2002-05-03 20:43:10 +00001632 static int moans = N_MOANS;
1633 if (moans-- > 0)
1634 ignored("_pthread_cleanup_push_defer");
sewardj3b13f0e2002-04-25 20:17:29 +00001635}
1636
1637void _pthread_cleanup_pop_restore ( void )
1638{
sewardj439d45e2002-05-03 20:43:10 +00001639 static int moans = N_MOANS;
1640 if (moans-- > 0)
1641 ignored("_pthread_cleanup_pop_restore");
sewardj3b13f0e2002-04-25 20:17:29 +00001642}
sewardjd4f2c712002-04-30 10:20:10 +00001643
sewardj60e38422002-05-08 14:08:22 +00001644/*--------*/
1645void _pthread_cleanup_push (struct _pthread_cleanup_buffer *__buffer,
1646 void (*__routine) (void *),
1647 void *__arg)
1648{
1649 static int moans = N_MOANS;
1650 if (moans-- > 0)
1651 ignored("_pthread_cleanup_push");
1652}
1653
1654void _pthread_cleanup_pop (struct _pthread_cleanup_buffer *__buffer,
1655 int __execute)
1656{
1657 static int moans = N_MOANS;
1658 if (moans-- > 0) {
1659 if (__execute)
1660 ignored("_pthread_cleanup_pop-EXECUTE");
1661 else
1662 ignored("_pthread_cleanup_pop-NO-EXECUTE");
1663 }
1664}
1665
sewardjd4f2c712002-04-30 10:20:10 +00001666
1667/* This doesn't seem to be needed to simulate libpthread.so's external
1668 interface, but many people complain about its absence. */
1669
1670strong_alias(__pthread_mutexattr_settype, __pthread_mutexattr_setkind_np)
1671weak_alias(__pthread_mutexattr_setkind_np, pthread_mutexattr_setkind_np)
sewardj439d45e2002-05-03 20:43:10 +00001672
1673
1674/*--------------------------------------------------------------------*/
1675/*--- end vg_libpthread.c ---*/
1676/*--------------------------------------------------------------------*/