blob: 45d99a9b2d6833c1d6e9b3615212e8cabfdc4a6b [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
sewardj705d3cb2002-05-23 13:13:12 +000064
65/* ---------------------------------------------------------------------
66 Forwardses.
67 ------------------------------------------------------------------ */
68
69static void wait_for_fd_to_be_readable_or_erring ( int fd );
70
71
sewardje663cb92002-04-12 10:26:32 +000072/* ---------------------------------------------------------------------
73 Helpers. We have to be pretty self-sufficient.
74 ------------------------------------------------------------------ */
75
sewardj436e0582002-04-26 14:31:40 +000076/* Number of times any given error message is printed. */
77#define N_MOANS 3
78
sewardj45b4b372002-04-16 22:50:32 +000079/* Extract from Valgrind the value of VG_(clo_trace_pthread_level).
80 Returns 0 (none) if not running on Valgrind. */
81static
82int get_pt_trace_level ( void )
83{
84 int res;
85 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
86 VG_USERREQ__GET_PTHREAD_TRACE_LEVEL,
87 0, 0, 0, 0);
88 return res;
89}
90
91
sewardje663cb92002-04-12 10:26:32 +000092static
93void myexit ( int arg )
94{
sewardj45b4b372002-04-16 22:50:32 +000095 int __res;
sewardje663cb92002-04-12 10:26:32 +000096 __asm__ volatile ("movl %%ecx, %%ebx ; int $0x80"
97 : "=a" (__res)
98 : "0" (__NR_exit),
99 "c" (arg) );
sewardj45b4b372002-04-16 22:50:32 +0000100 /* We don't bother to mention the fact that this asm trashes %ebx,
101 since it won't return. If you ever do let it return ... fix
102 this! */
sewardje663cb92002-04-12 10:26:32 +0000103}
104
105
sewardj68b2dd92002-05-10 21:03:56 +0000106/* We need this guy -- it's in valgrind.so. */
107extern void VG_(startup) ( void );
108
109
110/* Just start up Valgrind if it's not already going. VG_(startup)()
111 detects and ignores second and subsequent calls. */
sewardj604ec3c2002-04-18 22:38:41 +0000112static __inline__
sewardje663cb92002-04-12 10:26:32 +0000113void ensure_valgrind ( char* caller )
114{
sewardj68b2dd92002-05-10 21:03:56 +0000115 VG_(startup)();
sewardje663cb92002-04-12 10:26:32 +0000116}
117
sewardjbea1caa2002-05-10 23:20:58 +0000118/* While we're at it ... hook our own startup function into this
119 game. */
120__asm__ (
121 ".section .init\n"
122 "\tcall vgPlain_startup"
123);
124
sewardje663cb92002-04-12 10:26:32 +0000125
126static
sewardj3b5d8862002-04-20 13:53:23 +0000127__attribute__((noreturn))
sewardje663cb92002-04-12 10:26:32 +0000128void barf ( char* str )
129{
130 char buf[100];
131 buf[0] = 0;
sewardj439d45e2002-05-03 20:43:10 +0000132 strcat(buf, "\nvalgrind's libpthread.so: ");
sewardje663cb92002-04-12 10:26:32 +0000133 strcat(buf, str);
134 strcat(buf, "\n\n");
135 write(2, buf, strlen(buf));
136 myexit(1);
sewardj3b5d8862002-04-20 13:53:23 +0000137 /* We have to persuade gcc into believing this doesn't return. */
138 while (1) { };
sewardje663cb92002-04-12 10:26:32 +0000139}
140
141
sewardj2a3d28c2002-04-14 13:27:00 +0000142static void ignored ( char* msg )
143{
sewardj436e0582002-04-26 14:31:40 +0000144 if (get_pt_trace_level() >= 0) {
sewardj439d45e2002-05-03 20:43:10 +0000145 char* ig = "valgrind's libpthread.so: IGNORED call to: ";
sewardj45b4b372002-04-16 22:50:32 +0000146 write(2, ig, strlen(ig));
147 write(2, msg, strlen(msg));
148 ig = "\n";
149 write(2, ig, strlen(ig));
150 }
sewardj2a3d28c2002-04-14 13:27:00 +0000151}
152
sewardj30671ff2002-04-21 00:13:57 +0000153static void kludged ( char* msg )
154{
sewardj436e0582002-04-26 14:31:40 +0000155 if (get_pt_trace_level() >= 0) {
sewardj439d45e2002-05-03 20:43:10 +0000156 char* ig = "valgrind's libpthread.so: KLUDGED call to: ";
157 write(2, ig, strlen(ig));
158 write(2, msg, strlen(msg));
159 ig = "\n";
160 write(2, ig, strlen(ig));
161 }
162}
163
164static void not_inside ( char* msg )
165{
sewardj68b2dd92002-05-10 21:03:56 +0000166 VG_(startup)();
sewardj30671ff2002-04-21 00:13:57 +0000167}
168
sewardj3b13f0e2002-04-25 20:17:29 +0000169void vgPlain_unimp ( char* what )
170{
sewardj439d45e2002-05-03 20:43:10 +0000171 char* ig = "valgrind's libpthread.so: UNIMPLEMENTED FUNCTION: ";
sewardj3b13f0e2002-04-25 20:17:29 +0000172 write(2, ig, strlen(ig));
173 write(2, what, strlen(what));
174 ig = "\n";
175 write(2, ig, strlen(ig));
176 barf("Please report this bug to me at: jseward@acm.org");
177}
178
sewardje663cb92002-04-12 10:26:32 +0000179
180/* ---------------------------------------------------------------------
181 Pass pthread_ calls to Valgrind's request mechanism.
182 ------------------------------------------------------------------ */
183
sewardjf8f819e2002-04-17 23:21:37 +0000184#include <pthread.h>
185#include <stdio.h>
186#include <errno.h>
sewardj5f07b662002-04-23 16:52:51 +0000187#include <assert.h>
188#include <sys/time.h> /* gettimeofday */
sewardjf8f819e2002-04-17 23:21:37 +0000189
190/* ---------------------------------------------------
191 THREAD ATTRIBUTES
192 ------------------------------------------------ */
193
sewardj6af4b5d2002-04-16 04:40:49 +0000194int pthread_attr_init(pthread_attr_t *attr)
195{
sewardj436e0582002-04-26 14:31:40 +0000196 static int moans = N_MOANS;
197 if (moans-- > 0)
198 ignored("pthread_attr_init");
sewardj6af4b5d2002-04-16 04:40:49 +0000199 return 0;
200}
201
202int pthread_attr_setdetachstate(pthread_attr_t *attr, int detachstate)
203{
sewardj436e0582002-04-26 14:31:40 +0000204 static int moans = N_MOANS;
205 if (moans-- > 0)
206 ignored("pthread_attr_setdetachstate");
sewardj6af4b5d2002-04-16 04:40:49 +0000207 return 0;
208}
209
sewardj30671ff2002-04-21 00:13:57 +0000210int pthread_attr_setinheritsched(pthread_attr_t *attr, int inherit)
211{
sewardj436e0582002-04-26 14:31:40 +0000212 static int moans = N_MOANS;
213 if (moans-- > 0)
214 ignored("pthread_attr_setinheritsched");
sewardj30671ff2002-04-21 00:13:57 +0000215 return 0;
216}
sewardj6af4b5d2002-04-16 04:40:49 +0000217
sewardj0286dd52002-05-16 20:51:15 +0000218__attribute__((weak))
219int pthread_attr_setstacksize (pthread_attr_t *__attr,
220 size_t __stacksize)
221{
sewardja18e2102002-05-18 10:43:22 +0000222 size_t limit;
sewardj0286dd52002-05-16 20:51:15 +0000223 ensure_valgrind("pthread_attr_setstacksize");
sewardja18e2102002-05-18 10:43:22 +0000224 limit = VG_PTHREAD_STACK_SIZE - VG_AR_CLIENT_STACKBASE_REDZONE_SZB
225 - 1000; /* paranoia */
226 if (__stacksize < limit)
sewardj0286dd52002-05-16 20:51:15 +0000227 return 0;
228 barf("pthread_attr_setstacksize: "
229 "requested size >= VG_PTHREAD_STACK_SIZE\n "
230 "edit vg_include.h and rebuild.");
231}
232
233
sewardj30671ff2002-04-21 00:13:57 +0000234/* This is completely bogus. */
235int pthread_attr_getschedparam(const pthread_attr_t *attr,
236 struct sched_param *param)
237{
sewardj436e0582002-04-26 14:31:40 +0000238 static int moans = N_MOANS;
239 if (moans-- > 0)
240 kludged("pthread_attr_getschedparam");
sewardj72d58482002-04-24 02:20:20 +0000241# ifdef GLIBC_2_1
242 if (param) param->sched_priority = 0; /* who knows */
243# else
sewardj30671ff2002-04-21 00:13:57 +0000244 if (param) param->__sched_priority = 0; /* who knows */
sewardj72d58482002-04-24 02:20:20 +0000245# endif
sewardj30671ff2002-04-21 00:13:57 +0000246 return 0;
247}
248
249int pthread_attr_setschedparam(pthread_attr_t *attr,
250 const struct sched_param *param)
251{
sewardj436e0582002-04-26 14:31:40 +0000252 static int moans = N_MOANS;
253 if (moans-- > 0)
254 ignored("pthread_attr_setschedparam");
sewardj30671ff2002-04-21 00:13:57 +0000255 return 0;
256}
257
258int pthread_attr_destroy(pthread_attr_t *attr)
259{
sewardj436e0582002-04-26 14:31:40 +0000260 static int moans = N_MOANS;
261 if (moans-- > 0)
262 ignored("pthread_attr_destroy");
sewardj30671ff2002-04-21 00:13:57 +0000263 return 0;
264}
sewardjf8f819e2002-04-17 23:21:37 +0000265
266/* ---------------------------------------------------
267 THREADs
268 ------------------------------------------------ */
269
sewardjff42d1d2002-05-22 13:17:31 +0000270__attribute__((weak))
271int pthread_yield ( void )
272{
273 int res;
274 ensure_valgrind("pthread_yield");
275 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
276 VG_USERREQ__PTHREAD_YIELD, 0, 0, 0, 0);
277 return 0;
278}
279
280
sewardj6072c362002-04-19 14:40:57 +0000281int pthread_equal(pthread_t thread1, pthread_t thread2)
282{
283 return thread1 == thread2 ? 1 : 0;
284}
285
286
sewardje663cb92002-04-12 10:26:32 +0000287int
288pthread_create (pthread_t *__restrict __thread,
289 __const pthread_attr_t *__restrict __attr,
290 void *(*__start_routine) (void *),
291 void *__restrict __arg)
292{
293 int res;
294 ensure_valgrind("pthread_create");
295 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
296 VG_USERREQ__PTHREAD_CREATE,
297 __thread, __attr, __start_routine, __arg);
298 return res;
299}
300
301
302
303int
304pthread_join (pthread_t __th, void **__thread_return)
305{
306 int res;
307 ensure_valgrind("pthread_join");
308 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
309 VG_USERREQ__PTHREAD_JOIN,
310 __th, __thread_return, 0, 0);
311 return res;
312}
313
314
sewardj3b5d8862002-04-20 13:53:23 +0000315void pthread_exit(void *retval)
316{
317 int res;
318 ensure_valgrind("pthread_exit");
319 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
320 VG_USERREQ__PTHREAD_EXIT,
321 retval, 0, 0, 0);
322 /* Doesn't return! */
323 /* However, we have to fool gcc into knowing that. */
324 barf("pthread_exit: still alive after request?!");
325}
326
sewardje663cb92002-04-12 10:26:32 +0000327
sewardj3b13f0e2002-04-25 20:17:29 +0000328pthread_t pthread_self(void)
sewardje663cb92002-04-12 10:26:32 +0000329{
330 int tid;
sewardj3b13f0e2002-04-25 20:17:29 +0000331 ensure_valgrind("pthread_self");
sewardj439d45e2002-05-03 20:43:10 +0000332 VALGRIND_MAGIC_SEQUENCE(tid, 1 /* default */,
sewardje663cb92002-04-12 10:26:32 +0000333 VG_USERREQ__PTHREAD_GET_THREADID,
334 0, 0, 0, 0);
sewardj439d45e2002-05-03 20:43:10 +0000335 if (tid < 1 || tid >= VG_N_THREADS)
sewardj3b13f0e2002-04-25 20:17:29 +0000336 barf("pthread_self: invalid ThreadId");
337 return tid;
sewardje663cb92002-04-12 10:26:32 +0000338}
339
340
sewardj853f55d2002-04-26 00:27:53 +0000341int pthread_detach(pthread_t th)
342{
sewardj436e0582002-04-26 14:31:40 +0000343 static int moans = N_MOANS;
344 if (moans-- > 0)
345 ignored("pthread_detach");
sewardj853f55d2002-04-26 00:27:53 +0000346 return 0;
347}
348
349
sewardjf8f819e2002-04-17 23:21:37 +0000350/* ---------------------------------------------------
351 MUTEX ATTRIBUTES
352 ------------------------------------------------ */
353
sewardj5905fae2002-04-26 13:25:00 +0000354int __pthread_mutexattr_init(pthread_mutexattr_t *attr)
sewardje663cb92002-04-12 10:26:32 +0000355{
sewardjf8f819e2002-04-17 23:21:37 +0000356 attr->__mutexkind = PTHREAD_MUTEX_ERRORCHECK_NP;
sewardj8937c812002-04-12 20:12:20 +0000357 return 0;
sewardje663cb92002-04-12 10:26:32 +0000358}
359
sewardj5905fae2002-04-26 13:25:00 +0000360int __pthread_mutexattr_settype(pthread_mutexattr_t *attr, int type)
sewardjf8f819e2002-04-17 23:21:37 +0000361{
362 switch (type) {
sewardj3b13f0e2002-04-25 20:17:29 +0000363# ifndef GLIBC_2_1
sewardjf8f819e2002-04-17 23:21:37 +0000364 case PTHREAD_MUTEX_TIMED_NP:
sewardj2a1dcce2002-04-22 12:45:25 +0000365 case PTHREAD_MUTEX_ADAPTIVE_NP:
sewardj3b13f0e2002-04-25 20:17:29 +0000366# endif
sewardja1679dd2002-05-10 22:31:40 +0000367# ifdef GLIBC_2_1
sewardj68b2dd92002-05-10 21:03:56 +0000368 case PTHREAD_MUTEX_FAST_NP:
sewardja1679dd2002-05-10 22:31:40 +0000369# endif
sewardjf8f819e2002-04-17 23:21:37 +0000370 case PTHREAD_MUTEX_RECURSIVE_NP:
371 case PTHREAD_MUTEX_ERRORCHECK_NP:
sewardjf8f819e2002-04-17 23:21:37 +0000372 attr->__mutexkind = type;
373 return 0;
374 default:
375 return EINVAL;
376 }
377}
378
sewardj5905fae2002-04-26 13:25:00 +0000379int __pthread_mutexattr_destroy(pthread_mutexattr_t *attr)
sewardjf8f819e2002-04-17 23:21:37 +0000380{
381 return 0;
382}
383
384
385/* ---------------------------------------------------
386 MUTEXes
387 ------------------------------------------------ */
388
sewardj5905fae2002-04-26 13:25:00 +0000389int __pthread_mutex_init(pthread_mutex_t *mutex,
390 const pthread_mutexattr_t *mutexattr)
sewardje663cb92002-04-12 10:26:32 +0000391{
sewardj604ec3c2002-04-18 22:38:41 +0000392 mutex->__m_count = 0;
393 mutex->__m_owner = (_pthread_descr)VG_INVALID_THREADID;
394 mutex->__m_kind = PTHREAD_MUTEX_ERRORCHECK_NP;
395 if (mutexattr)
396 mutex->__m_kind = mutexattr->__mutexkind;
397 return 0;
sewardje663cb92002-04-12 10:26:32 +0000398}
399
sewardj439d45e2002-05-03 20:43:10 +0000400
sewardj5905fae2002-04-26 13:25:00 +0000401int __pthread_mutex_lock(pthread_mutex_t *mutex)
sewardje663cb92002-04-12 10:26:32 +0000402{
403 int res;
sewardj436e0582002-04-26 14:31:40 +0000404 static int moans = N_MOANS;
sewardj439d45e2002-05-03 20:43:10 +0000405 if (RUNNING_ON_VALGRIND) {
sewardje663cb92002-04-12 10:26:32 +0000406 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
407 VG_USERREQ__PTHREAD_MUTEX_LOCK,
408 mutex, 0, 0, 0);
409 return res;
sewardj439d45e2002-05-03 20:43:10 +0000410 } else {
411 if (moans-- > 0)
412 not_inside("pthread_mutex_lock");
413 return 0; /* success */
sewardje663cb92002-04-12 10:26:32 +0000414 }
415}
416
sewardj439d45e2002-05-03 20:43:10 +0000417
sewardj5905fae2002-04-26 13:25:00 +0000418int __pthread_mutex_trylock(pthread_mutex_t *mutex)
sewardj30671ff2002-04-21 00:13:57 +0000419{
420 int res;
sewardj436e0582002-04-26 14:31:40 +0000421 static int moans = N_MOANS;
sewardj439d45e2002-05-03 20:43:10 +0000422 if (RUNNING_ON_VALGRIND) {
sewardj30671ff2002-04-21 00:13:57 +0000423 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
424 VG_USERREQ__PTHREAD_MUTEX_TRYLOCK,
425 mutex, 0, 0, 0);
426 return res;
sewardj439d45e2002-05-03 20:43:10 +0000427 } else {
428 if (moans-- > 0)
429 not_inside("pthread_mutex_trylock");
430 return 0;
sewardj30671ff2002-04-21 00:13:57 +0000431 }
432}
433
sewardj439d45e2002-05-03 20:43:10 +0000434
sewardj5905fae2002-04-26 13:25:00 +0000435int __pthread_mutex_unlock(pthread_mutex_t *mutex)
sewardje663cb92002-04-12 10:26:32 +0000436{
437 int res;
sewardj436e0582002-04-26 14:31:40 +0000438 static int moans = N_MOANS;
sewardj439d45e2002-05-03 20:43:10 +0000439 if (RUNNING_ON_VALGRIND) {
sewardje663cb92002-04-12 10:26:32 +0000440 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
441 VG_USERREQ__PTHREAD_MUTEX_UNLOCK,
442 mutex, 0, 0, 0);
443 return res;
sewardj439d45e2002-05-03 20:43:10 +0000444 } else {
445 if (moans-- > 0)
446 not_inside("pthread_mutex_unlock");
447 return 0;
sewardje663cb92002-04-12 10:26:32 +0000448 }
449}
450
sewardj439d45e2002-05-03 20:43:10 +0000451
sewardj5905fae2002-04-26 13:25:00 +0000452int __pthread_mutex_destroy(pthread_mutex_t *mutex)
sewardje663cb92002-04-12 10:26:32 +0000453{
sewardj604ec3c2002-04-18 22:38:41 +0000454 /* Valgrind doesn't hold any resources on behalf of the mutex, so no
455 need to involve it. */
456 if (mutex->__m_count > 0)
457 return EBUSY;
sewardj6072c362002-04-19 14:40:57 +0000458 mutex->__m_count = 0;
459 mutex->__m_owner = (_pthread_descr)VG_INVALID_THREADID;
460 mutex->__m_kind = PTHREAD_MUTEX_ERRORCHECK_NP;
sewardj604ec3c2002-04-18 22:38:41 +0000461 return 0;
sewardje663cb92002-04-12 10:26:32 +0000462}
463
464
sewardjf8f819e2002-04-17 23:21:37 +0000465/* ---------------------------------------------------
sewardj6072c362002-04-19 14:40:57 +0000466 CONDITION VARIABLES
467 ------------------------------------------------ */
468
469/* LinuxThreads supports no attributes for conditions. Hence ... */
470
471int pthread_condattr_init(pthread_condattr_t *attr)
472{
473 return 0;
474}
475
sewardj0738a592002-04-20 13:59:33 +0000476int pthread_condattr_destroy(pthread_condattr_t *attr)
477{
478 return 0;
479}
sewardj6072c362002-04-19 14:40:57 +0000480
481int pthread_cond_init( pthread_cond_t *cond,
482 const pthread_condattr_t *cond_attr)
483{
484 cond->__c_waiting = (_pthread_descr)VG_INVALID_THREADID;
485 return 0;
486}
487
sewardjf854f472002-04-21 12:19:41 +0000488int pthread_cond_destroy(pthread_cond_t *cond)
489{
490 /* should check that no threads are waiting on this CV */
sewardj436e0582002-04-26 14:31:40 +0000491 static int moans = N_MOANS;
492 if (moans-- > 0)
493 kludged("pthread_cond_destroy");
sewardjf854f472002-04-21 12:19:41 +0000494 return 0;
495}
sewardj6072c362002-04-19 14:40:57 +0000496
497/* ---------------------------------------------------
498 SCHEDULING
499 ------------------------------------------------ */
500
501/* This is completely bogus. */
502int pthread_getschedparam(pthread_t target_thread,
503 int *policy,
504 struct sched_param *param)
505{
sewardj436e0582002-04-26 14:31:40 +0000506 static int moans = N_MOANS;
507 if (moans-- > 0)
508 kludged("pthread_getschedparam");
sewardj6072c362002-04-19 14:40:57 +0000509 if (policy) *policy = SCHED_OTHER;
sewardj2a1dcce2002-04-22 12:45:25 +0000510# ifdef GLIBC_2_1
511 if (param) param->sched_priority = 0; /* who knows */
512# else
sewardj6072c362002-04-19 14:40:57 +0000513 if (param) param->__sched_priority = 0; /* who knows */
sewardj2a1dcce2002-04-22 12:45:25 +0000514# endif
sewardj6072c362002-04-19 14:40:57 +0000515 return 0;
516}
517
518int pthread_setschedparam(pthread_t target_thread,
519 int policy,
520 const struct sched_param *param)
521{
sewardj436e0582002-04-26 14:31:40 +0000522 static int moans = N_MOANS;
523 if (moans-- > 0)
524 ignored("pthread_setschedparam");
sewardj6072c362002-04-19 14:40:57 +0000525 return 0;
526}
527
sewardj3b5d8862002-04-20 13:53:23 +0000528int pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex)
529{
530 int res;
531 ensure_valgrind("pthread_cond_wait");
532 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
533 VG_USERREQ__PTHREAD_COND_WAIT,
534 cond, mutex, 0, 0);
535 return res;
536}
537
sewardj5f07b662002-04-23 16:52:51 +0000538int pthread_cond_timedwait ( pthread_cond_t *cond,
539 pthread_mutex_t *mutex,
540 const struct timespec *abstime )
541{
542 int res;
543 unsigned int ms_now, ms_end;
544 struct timeval timeval_now;
545 unsigned long long int ull_ms_now_after_1970;
546 unsigned long long int ull_ms_end_after_1970;
547
548 ensure_valgrind("pthread_cond_timedwait");
549 VALGRIND_MAGIC_SEQUENCE(ms_now, 0xFFFFFFFF /* default */,
550 VG_USERREQ__READ_MILLISECOND_TIMER,
551 0, 0, 0, 0);
552 assert(ms_now != 0xFFFFFFFF);
553 res = gettimeofday(&timeval_now, NULL);
554 assert(res == 0);
555
556 ull_ms_now_after_1970
557 = 1000ULL * ((unsigned long long int)(timeval_now.tv_sec))
558 + ((unsigned long long int)(timeval_now.tv_usec / 1000000));
559 ull_ms_end_after_1970
560 = 1000ULL * ((unsigned long long int)(abstime->tv_sec))
561 + ((unsigned long long int)(abstime->tv_nsec / 1000000));
562 assert(ull_ms_end_after_1970 >= ull_ms_now_after_1970);
563 ms_end
564 = ms_now + (unsigned int)(ull_ms_end_after_1970 - ull_ms_now_after_1970);
565 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
566 VG_USERREQ__PTHREAD_COND_TIMEDWAIT,
567 cond, mutex, ms_end, 0);
568 return res;
569}
570
571
sewardj3b5d8862002-04-20 13:53:23 +0000572int pthread_cond_signal(pthread_cond_t *cond)
573{
574 int res;
575 ensure_valgrind("pthread_cond_signal");
576 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
577 VG_USERREQ__PTHREAD_COND_SIGNAL,
578 cond, 0, 0, 0);
579 return res;
580}
581
582int pthread_cond_broadcast(pthread_cond_t *cond)
583{
584 int res;
585 ensure_valgrind("pthread_cond_broadcast");
586 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
587 VG_USERREQ__PTHREAD_COND_BROADCAST,
588 cond, 0, 0, 0);
589 return res;
590}
591
sewardj6072c362002-04-19 14:40:57 +0000592
593/* ---------------------------------------------------
sewardjf8f819e2002-04-17 23:21:37 +0000594 CANCELLATION
595 ------------------------------------------------ */
596
sewardj853f55d2002-04-26 00:27:53 +0000597int pthread_setcancelstate(int state, int *oldstate)
598{
sewardj436e0582002-04-26 14:31:40 +0000599 static int moans = N_MOANS;
600 if (moans-- > 0)
601 ignored("pthread_setcancelstate");
sewardj853f55d2002-04-26 00:27:53 +0000602 return 0;
603}
604
sewardje663cb92002-04-12 10:26:32 +0000605int pthread_setcanceltype(int type, int *oldtype)
606{
sewardj436e0582002-04-26 14:31:40 +0000607 static int moans = N_MOANS;
608 if (moans-- > 0)
609 ignored("pthread_setcanceltype");
sewardje663cb92002-04-12 10:26:32 +0000610 return 0;
611}
612
sewardje663cb92002-04-12 10:26:32 +0000613int pthread_cancel(pthread_t thread)
614{
615 int res;
616 ensure_valgrind("pthread_cancel");
617 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
618 VG_USERREQ__PTHREAD_CANCEL,
619 thread, 0, 0, 0);
620 return res;
621}
622
sewardj853f55d2002-04-26 00:27:53 +0000623void pthread_testcancel(void)
624{
625}
626
627/*-------------------*/
628static pthread_mutex_t massacre_mx = PTHREAD_MUTEX_INITIALIZER;
629
630void __pthread_kill_other_threads_np ( void )
631{
632 int i, res, me;
sewardj68b2dd92002-05-10 21:03:56 +0000633 __pthread_mutex_lock(&massacre_mx);
sewardj853f55d2002-04-26 00:27:53 +0000634 me = pthread_self();
635 for (i = 1; i < VG_N_THREADS; i++) {
636 if (i == me) continue;
637 res = pthread_cancel(i);
sewardj436e0582002-04-26 14:31:40 +0000638 if (0 && res == 0)
sewardj853f55d2002-04-26 00:27:53 +0000639 printf("----------- NUKED %d\n", i);
640 }
sewardj68b2dd92002-05-10 21:03:56 +0000641 __pthread_mutex_unlock(&massacre_mx);
sewardj853f55d2002-04-26 00:27:53 +0000642}
643
sewardje663cb92002-04-12 10:26:32 +0000644
sewardjf8f819e2002-04-17 23:21:37 +0000645/* ---------------------------------------------------
sewardjb48e5002002-05-13 00:16:03 +0000646 SIGNALS
647 ------------------------------------------------ */
648
649#include <signal.h>
650
651int pthread_sigmask(int how, const sigset_t *newmask,
652 sigset_t *oldmask)
653{
654 int res;
655
656 /* A bit subtle, because the scheduler expects newmask and oldmask
657 to be vki_sigset_t* rather than sigset_t*, and the two are
658 different. Fortunately the first 64 bits of a sigset_t are
659 exactly a vki_sigset_t, so we just pass the pointers through
660 unmodified. Haaaack!
661
662 Also mash the how value so that the SIG_ constants from glibc
sewardj018f7622002-05-15 21:13:39 +0000663 constants to VKI_ constants, so that the former do not have to
664 be included into vg_scheduler.c. */
sewardjb48e5002002-05-13 00:16:03 +0000665
666 ensure_valgrind("pthread_sigmask");
667
668 switch (how) {
sewardj018f7622002-05-15 21:13:39 +0000669 case SIG_SETMASK: how = VKI_SIG_SETMASK; break;
670 case SIG_BLOCK: how = VKI_SIG_BLOCK; break;
671 case SIG_UNBLOCK: how = VKI_SIG_UNBLOCK; break;
sewardjb48e5002002-05-13 00:16:03 +0000672 default: return EINVAL;
673 }
674
675 /* Crude check */
676 if (newmask == NULL)
677 return EFAULT;
678
679 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
680 VG_USERREQ__PTHREAD_SIGMASK,
681 how, newmask, oldmask, 0);
682
683 /* The scheduler tells us of any memory violations. */
684 return res == 0 ? 0 : EFAULT;
685}
686
687
688int sigwait ( const sigset_t* set, int* sig )
689{
690 int res;
691 ensure_valgrind("sigwait");
692 /* As with pthread_sigmask we deliberately confuse sigset_t with
693 vki_ksigset_t. */
694 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
695 VG_USERREQ__SIGWAIT,
696 set, sig, 0, 0);
697 return res;
698}
699
700
sewardj018f7622002-05-15 21:13:39 +0000701int pthread_kill(pthread_t thread, int signo)
702{
703 int res;
704 ensure_valgrind("pthread_kill");
705 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
706 VG_USERREQ__PTHREAD_KILL,
707 thread, signo, 0, 0);
708 return res;
709}
710
711
sewardj3665ded2002-05-16 16:57:25 +0000712/* Copied verbatim from Linuxthreads */
713/* Redefine raise() to send signal to calling thread only,
714 as per POSIX 1003.1c */
715int raise (int sig)
716{
717 int retcode = pthread_kill(pthread_self(), sig);
718 if (retcode == 0)
719 return 0;
720 else {
721 errno = retcode;
722 return -1;
723 }
724}
725
726
sewardjb48e5002002-05-13 00:16:03 +0000727/* ---------------------------------------------------
sewardjf8f819e2002-04-17 23:21:37 +0000728 THREAD-SPECIFICs
729 ------------------------------------------------ */
sewardj5e5fa512002-04-14 13:13:05 +0000730
sewardj5905fae2002-04-26 13:25:00 +0000731int __pthread_key_create(pthread_key_t *key,
732 void (*destr_function) (void *))
sewardj5e5fa512002-04-14 13:13:05 +0000733{
sewardj5f07b662002-04-23 16:52:51 +0000734 int res;
735 ensure_valgrind("pthread_key_create");
736 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
737 VG_USERREQ__PTHREAD_KEY_CREATE,
738 key, destr_function, 0, 0);
739 return res;
sewardj5e5fa512002-04-14 13:13:05 +0000740}
741
742int pthread_key_delete(pthread_key_t key)
743{
sewardj436e0582002-04-26 14:31:40 +0000744 static int moans = N_MOANS;
745 if (moans-- > 0)
746 ignored("pthread_key_delete");
sewardj5e5fa512002-04-14 13:13:05 +0000747 return 0;
748}
749
sewardj5905fae2002-04-26 13:25:00 +0000750int __pthread_setspecific(pthread_key_t key, const void *pointer)
sewardj5e5fa512002-04-14 13:13:05 +0000751{
sewardj5f07b662002-04-23 16:52:51 +0000752 int res;
753 ensure_valgrind("pthread_setspecific");
754 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
755 VG_USERREQ__PTHREAD_SETSPECIFIC,
756 key, pointer, 0, 0);
757 return res;
sewardj5e5fa512002-04-14 13:13:05 +0000758}
759
sewardj5905fae2002-04-26 13:25:00 +0000760void * __pthread_getspecific(pthread_key_t key)
sewardj5e5fa512002-04-14 13:13:05 +0000761{
sewardj5f07b662002-04-23 16:52:51 +0000762 int res;
763 ensure_valgrind("pthread_getspecific");
764 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
765 VG_USERREQ__PTHREAD_GETSPECIFIC,
766 key, 0 , 0, 0);
767 return (void*)res;
sewardj5e5fa512002-04-14 13:13:05 +0000768}
769
sewardjf8f819e2002-04-17 23:21:37 +0000770
771/* ---------------------------------------------------
sewardj89d3d852002-04-24 19:21:39 +0000772 ONCEry
773 ------------------------------------------------ */
774
775static pthread_mutex_t once_masterlock = PTHREAD_MUTEX_INITIALIZER;
776
777
sewardj5905fae2002-04-26 13:25:00 +0000778int __pthread_once ( pthread_once_t *once_control,
779 void (*init_routine) (void) )
sewardj89d3d852002-04-24 19:21:39 +0000780{
781 int res;
782 ensure_valgrind("pthread_once");
783
sewardj68b2dd92002-05-10 21:03:56 +0000784 res = __pthread_mutex_lock(&once_masterlock);
sewardj89d3d852002-04-24 19:21:39 +0000785
sewardj68b2dd92002-05-10 21:03:56 +0000786 if (res != 0) {
787 printf("res = %d\n",res);
sewardj89d3d852002-04-24 19:21:39 +0000788 barf("pthread_once: Looks like your program's "
789 "init routine calls back to pthread_once() ?!");
sewardj68b2dd92002-05-10 21:03:56 +0000790 }
sewardj89d3d852002-04-24 19:21:39 +0000791
792 if (*once_control == 0) {
793 *once_control = 1;
794 init_routine();
795 }
796
sewardj68b2dd92002-05-10 21:03:56 +0000797 __pthread_mutex_unlock(&once_masterlock);
sewardj89d3d852002-04-24 19:21:39 +0000798
799 return 0;
800}
801
802
803/* ---------------------------------------------------
sewardj853f55d2002-04-26 00:27:53 +0000804 MISC
805 ------------------------------------------------ */
806
sewardj5905fae2002-04-26 13:25:00 +0000807int __pthread_atfork ( void (*prepare)(void),
808 void (*parent)(void),
809 void (*child)(void) )
sewardj853f55d2002-04-26 00:27:53 +0000810{
sewardj436e0582002-04-26 14:31:40 +0000811 static int moans = N_MOANS;
812 if (moans-- > 0)
813 ignored("pthread_atfork");
sewardj853f55d2002-04-26 00:27:53 +0000814 return 0;
815}
816
817
sewardjbb990782002-05-08 02:01:14 +0000818__attribute__((weak))
819void __pthread_initialize ( void )
820{
sewardjbea1caa2002-05-10 23:20:58 +0000821 ensure_valgrind("__pthread_initialize");
sewardjbb990782002-05-08 02:01:14 +0000822}
823
824
sewardj853f55d2002-04-26 00:27:53 +0000825/* ---------------------------------------------------
sewardj3b13f0e2002-04-25 20:17:29 +0000826 LIBRARY-PRIVATE THREAD SPECIFIC STATE
sewardjf8f819e2002-04-17 23:21:37 +0000827 ------------------------------------------------ */
828
sewardj3b13f0e2002-04-25 20:17:29 +0000829#include <resolv.h>
830static int thread_specific_errno[VG_N_THREADS];
831static int thread_specific_h_errno[VG_N_THREADS];
832static struct __res_state
833 thread_specific_res_state[VG_N_THREADS];
sewardjf8f819e2002-04-17 23:21:37 +0000834
sewardj3b13f0e2002-04-25 20:17:29 +0000835int* __errno_location ( void )
sewardjf8f819e2002-04-17 23:21:37 +0000836{
837 int tid;
sewardj3b13f0e2002-04-25 20:17:29 +0000838 /* ensure_valgrind("__errno_location"); */
839 VALGRIND_MAGIC_SEQUENCE(tid, 1 /* default */,
sewardjf8f819e2002-04-17 23:21:37 +0000840 VG_USERREQ__PTHREAD_GET_THREADID,
841 0, 0, 0, 0);
sewardj3b13f0e2002-04-25 20:17:29 +0000842 /* '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("__errno_location: invalid ThreadId");
845 return & thread_specific_errno[tid];
846}
847
848int* __h_errno_location ( void )
849{
850 int tid;
851 /* ensure_valgrind("__h_errno_location"); */
852 VALGRIND_MAGIC_SEQUENCE(tid, 1 /* default */,
853 VG_USERREQ__PTHREAD_GET_THREADID,
854 0, 0, 0, 0);
855 /* 'cos I'm paranoid ... */
sewardj439d45e2002-05-03 20:43:10 +0000856 if (tid < 1 || tid >= VG_N_THREADS)
sewardj3b13f0e2002-04-25 20:17:29 +0000857 barf("__h_errno_location: invalid ThreadId");
858 return & thread_specific_h_errno[tid];
859}
860
861struct __res_state* __res_state ( void )
862{
863 int tid;
864 /* ensure_valgrind("__res_state"); */
865 VALGRIND_MAGIC_SEQUENCE(tid, 1 /* default */,
866 VG_USERREQ__PTHREAD_GET_THREADID,
867 0, 0, 0, 0);
868 /* 'cos I'm paranoid ... */
sewardj439d45e2002-05-03 20:43:10 +0000869 if (tid < 1 || tid >= VG_N_THREADS)
sewardj3b13f0e2002-04-25 20:17:29 +0000870 barf("__res_state: invalid ThreadId");
871 return & thread_specific_res_state[tid];
sewardjf8f819e2002-04-17 23:21:37 +0000872}
873
874
sewardj5716dbb2002-04-26 03:28:18 +0000875/* ---------------------------------------------------
876 LIBC-PRIVATE SPECIFIC DATA
877 ------------------------------------------------ */
878
879/* Relies on assumption that initial private data is NULL. This
880 should be fixed somehow. */
881
882/* The allowable keys (indices) (all 2 of them).
883 From sysdeps/pthread/bits/libc-tsd.h
884*/
sewardj70adeb22002-04-27 01:35:38 +0000885#define N_LIBC_TSD_EXTRA_KEYS 1
886
sewardj5716dbb2002-04-26 03:28:18 +0000887enum __libc_tsd_key_t { _LIBC_TSD_KEY_MALLOC = 0,
888 _LIBC_TSD_KEY_DL_ERROR,
889 _LIBC_TSD_KEY_N };
890
891/* Auto-initialising subsystem. libc_specifics_inited is set
892 after initialisation. libc_specifics_inited_mx guards it. */
893static int libc_specifics_inited = 0;
894static pthread_mutex_t libc_specifics_inited_mx = PTHREAD_MUTEX_INITIALIZER;
895
896/* These are the keys we must initialise the first time. */
sewardj70adeb22002-04-27 01:35:38 +0000897static pthread_key_t libc_specifics_keys[_LIBC_TSD_KEY_N
898 + N_LIBC_TSD_EXTRA_KEYS];
sewardj5716dbb2002-04-26 03:28:18 +0000899
900/* Initialise the keys, if they are not already initialise. */
901static
902void init_libc_tsd_keys ( void )
903{
904 int res, i;
905 pthread_key_t k;
906
907 res = pthread_mutex_lock(&libc_specifics_inited_mx);
908 if (res != 0) barf("init_libc_tsd_keys: lock");
909
910 if (libc_specifics_inited == 0) {
911 /* printf("INIT libc specifics\n"); */
912 libc_specifics_inited = 1;
sewardj70adeb22002-04-27 01:35:38 +0000913 for (i = 0; i < _LIBC_TSD_KEY_N + N_LIBC_TSD_EXTRA_KEYS; i++) {
sewardj5716dbb2002-04-26 03:28:18 +0000914 res = pthread_key_create(&k, NULL);
915 if (res != 0) barf("init_libc_tsd_keys: create");
916 libc_specifics_keys[i] = k;
917 }
918 }
919
920 res = pthread_mutex_unlock(&libc_specifics_inited_mx);
921 if (res != 0) barf("init_libc_tsd_keys: unlock");
922}
923
924
925static int
926libc_internal_tsd_set ( enum __libc_tsd_key_t key,
927 const void * pointer )
928{
sewardj70adeb22002-04-27 01:35:38 +0000929 int res;
930 static int moans = N_MOANS;
sewardj5716dbb2002-04-26 03:28:18 +0000931 /* printf("SET SET SET key %d ptr %p\n", key, pointer); */
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_set: 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_set: "
938 "dubious key %d\n", key);
sewardj5716dbb2002-04-26 03:28:18 +0000939 init_libc_tsd_keys();
940 res = pthread_setspecific(libc_specifics_keys[key], pointer);
941 if (res != 0) barf("libc_internal_tsd_set: setspecific failed");
942 return 0;
943}
944
945static void *
946libc_internal_tsd_get ( enum __libc_tsd_key_t key )
947{
sewardj70adeb22002-04-27 01:35:38 +0000948 void* v;
949 static int moans = N_MOANS;
sewardj5716dbb2002-04-26 03:28:18 +0000950 /* printf("GET GET GET key %d\n", key); */
sewardj70adeb22002-04-27 01:35:38 +0000951 if (key < _LIBC_TSD_KEY_MALLOC
952 || key >= _LIBC_TSD_KEY_N + N_LIBC_TSD_EXTRA_KEYS)
sewardj5716dbb2002-04-26 03:28:18 +0000953 barf("libc_internal_tsd_get: invalid key");
sewardj70adeb22002-04-27 01:35:38 +0000954 if (key >= _LIBC_TSD_KEY_N && moans-- > 0)
955 fprintf(stderr,
sewardj439d45e2002-05-03 20:43:10 +0000956 "valgrind's libpthread.so: libc_internal_tsd_get: "
957 "dubious key %d\n", key);
sewardj5716dbb2002-04-26 03:28:18 +0000958 init_libc_tsd_keys();
959 v = pthread_getspecific(libc_specifics_keys[key]);
960 /* if (v == NULL) barf("libc_internal_tsd_set: getspecific failed"); */
961 return v;
962}
963
964
965
966
sewardj70adeb22002-04-27 01:35:38 +0000967int (*__libc_internal_tsd_set)
968 (enum __libc_tsd_key_t key, const void * pointer)
969 = libc_internal_tsd_set;
sewardj5716dbb2002-04-26 03:28:18 +0000970
sewardj70adeb22002-04-27 01:35:38 +0000971void* (*__libc_internal_tsd_get)
972 (enum __libc_tsd_key_t key)
973 = libc_internal_tsd_get;
sewardj5716dbb2002-04-26 03:28:18 +0000974
975
sewardje663cb92002-04-12 10:26:32 +0000976/* ---------------------------------------------------------------------
977 These are here (I think) because they are deemed cancellation
978 points by POSIX. For the moment we'll simply pass the call along
979 to the corresponding thread-unaware (?) libc routine.
980 ------------------------------------------------------------------ */
981
sewardje663cb92002-04-12 10:26:32 +0000982#include <stdlib.h>
sewardje663cb92002-04-12 10:26:32 +0000983#include <sys/types.h>
984#include <sys/socket.h>
985
sewardjd529a442002-05-04 19:49:21 +0000986#ifdef GLIBC_2_1
987extern
988int __sigaction
989 (int signum,
990 const struct sigaction *act,
991 struct sigaction *oldact);
992#else
sewardje663cb92002-04-12 10:26:32 +0000993extern
994int __libc_sigaction
995 (int signum,
996 const struct sigaction *act,
997 struct sigaction *oldact);
sewardjd529a442002-05-04 19:49:21 +0000998#endif
sewardje663cb92002-04-12 10:26:32 +0000999int sigaction(int signum,
1000 const struct sigaction *act,
1001 struct sigaction *oldact)
1002{
sewardj2a1dcce2002-04-22 12:45:25 +00001003# ifdef GLIBC_2_1
1004 return __sigaction(signum, act, oldact);
1005# else
sewardj45b4b372002-04-16 22:50:32 +00001006 return __libc_sigaction(signum, act, oldact);
sewardj2a1dcce2002-04-22 12:45:25 +00001007# endif
sewardje663cb92002-04-12 10:26:32 +00001008}
1009
1010
1011extern
1012int __libc_connect(int sockfd,
1013 const struct sockaddr *serv_addr,
1014 socklen_t addrlen);
sewardj5905fae2002-04-26 13:25:00 +00001015__attribute__((weak))
sewardje663cb92002-04-12 10:26:32 +00001016int connect(int sockfd,
1017 const struct sockaddr *serv_addr,
1018 socklen_t addrlen)
1019{
sewardj45b4b372002-04-16 22:50:32 +00001020 return __libc_connect(sockfd, serv_addr, addrlen);
sewardje663cb92002-04-12 10:26:32 +00001021}
1022
1023
1024extern
1025int __libc_fcntl(int fd, int cmd, long arg);
sewardj5905fae2002-04-26 13:25:00 +00001026__attribute__((weak))
sewardje663cb92002-04-12 10:26:32 +00001027int fcntl(int fd, int cmd, long arg)
1028{
sewardj45b4b372002-04-16 22:50:32 +00001029 return __libc_fcntl(fd, cmd, arg);
sewardje663cb92002-04-12 10:26:32 +00001030}
1031
1032
1033extern
1034ssize_t __libc_write(int fd, const void *buf, size_t count);
sewardj5905fae2002-04-26 13:25:00 +00001035__attribute__((weak))
sewardje663cb92002-04-12 10:26:32 +00001036ssize_t write(int fd, const void *buf, size_t count)
1037{
sewardj45b4b372002-04-16 22:50:32 +00001038 return __libc_write(fd, buf, count);
sewardje663cb92002-04-12 10:26:32 +00001039}
1040
1041
1042extern
1043ssize_t __libc_read(int fd, void *buf, size_t count);
sewardj5905fae2002-04-26 13:25:00 +00001044__attribute__((weak))
sewardje663cb92002-04-12 10:26:32 +00001045ssize_t read(int fd, void *buf, size_t count)
1046{
sewardj45b4b372002-04-16 22:50:32 +00001047 return __libc_read(fd, buf, count);
sewardje663cb92002-04-12 10:26:32 +00001048}
1049
sewardjbe32e452002-04-24 20:29:58 +00001050
1051extern
sewardj853f55d2002-04-26 00:27:53 +00001052int __libc_open64(const char *pathname, int flags, mode_t mode);
sewardj5905fae2002-04-26 13:25:00 +00001053__attribute__((weak))
sewardj853f55d2002-04-26 00:27:53 +00001054int open64(const char *pathname, int flags, mode_t mode)
sewardjbe32e452002-04-24 20:29:58 +00001055{
sewardj853f55d2002-04-26 00:27:53 +00001056 return __libc_open64(pathname, flags, mode);
sewardjbe32e452002-04-24 20:29:58 +00001057}
1058
sewardje663cb92002-04-12 10:26:32 +00001059
1060extern
sewardj853f55d2002-04-26 00:27:53 +00001061int __libc_open(const char *pathname, int flags, mode_t mode);
sewardj5905fae2002-04-26 13:25:00 +00001062__attribute__((weak))
sewardj853f55d2002-04-26 00:27:53 +00001063int open(const char *pathname, int flags, mode_t mode)
sewardje663cb92002-04-12 10:26:32 +00001064{
sewardj853f55d2002-04-26 00:27:53 +00001065 return __libc_open(pathname, flags, mode);
sewardje663cb92002-04-12 10:26:32 +00001066}
1067
1068
1069extern
1070int __libc_close(int fd);
sewardj5905fae2002-04-26 13:25:00 +00001071__attribute__((weak))
sewardje663cb92002-04-12 10:26:32 +00001072int close(int fd)
1073{
sewardj45b4b372002-04-16 22:50:32 +00001074 return __libc_close(fd);
sewardje663cb92002-04-12 10:26:32 +00001075}
1076
1077
1078extern
1079int __libc_accept(int s, struct sockaddr *addr, socklen_t *addrlen);
sewardj5905fae2002-04-26 13:25:00 +00001080__attribute__((weak))
sewardje663cb92002-04-12 10:26:32 +00001081int accept(int s, struct sockaddr *addr, socklen_t *addrlen)
1082{
sewardj705d3cb2002-05-23 13:13:12 +00001083 wait_for_fd_to_be_readable_or_erring(s);
sewardj45b4b372002-04-16 22:50:32 +00001084 return __libc_accept(s, addr, addrlen);
sewardje663cb92002-04-12 10:26:32 +00001085}
1086
1087
1088extern
1089pid_t __libc_fork(void);
sewardj5905fae2002-04-26 13:25:00 +00001090pid_t __fork(void)
sewardje663cb92002-04-12 10:26:32 +00001091{
sewardj45b4b372002-04-16 22:50:32 +00001092 return __libc_fork();
sewardje663cb92002-04-12 10:26:32 +00001093}
1094
1095
1096extern
1097pid_t __libc_waitpid(pid_t pid, int *status, int options);
sewardj5905fae2002-04-26 13:25:00 +00001098__attribute__((weak))
sewardje663cb92002-04-12 10:26:32 +00001099pid_t waitpid(pid_t pid, int *status, int options)
1100{
sewardj45b4b372002-04-16 22:50:32 +00001101 return __libc_waitpid(pid, status, options);
sewardje663cb92002-04-12 10:26:32 +00001102}
1103
1104
1105extern
1106int __libc_nanosleep(const struct timespec *req, struct timespec *rem);
sewardj5905fae2002-04-26 13:25:00 +00001107__attribute__((weak))
sewardje663cb92002-04-12 10:26:32 +00001108int nanosleep(const struct timespec *req, struct timespec *rem)
1109{
1110 return __libc_nanosleep(req, rem);
1111}
1112
sewardjbe32e452002-04-24 20:29:58 +00001113
sewardje663cb92002-04-12 10:26:32 +00001114extern
1115int __libc_fsync(int fd);
sewardj5905fae2002-04-26 13:25:00 +00001116__attribute__((weak))
sewardje663cb92002-04-12 10:26:32 +00001117int fsync(int fd)
1118{
sewardj45b4b372002-04-16 22:50:32 +00001119 return __libc_fsync(fd);
sewardje663cb92002-04-12 10:26:32 +00001120}
1121
sewardjbe32e452002-04-24 20:29:58 +00001122
sewardj70c75362002-04-13 04:18:32 +00001123extern
1124off_t __libc_lseek(int fildes, off_t offset, int whence);
sewardj5905fae2002-04-26 13:25:00 +00001125__attribute__((weak))
sewardj70c75362002-04-13 04:18:32 +00001126off_t lseek(int fildes, off_t offset, int whence)
1127{
sewardj45b4b372002-04-16 22:50:32 +00001128 return __libc_lseek(fildes, offset, whence);
sewardj70c75362002-04-13 04:18:32 +00001129}
1130
sewardjbe32e452002-04-24 20:29:58 +00001131
1132extern
1133__off64_t __libc_lseek64(int fildes, __off64_t offset, int whence);
sewardj5905fae2002-04-26 13:25:00 +00001134__attribute__((weak))
sewardjbe32e452002-04-24 20:29:58 +00001135__off64_t lseek64(int fildes, __off64_t offset, int whence)
1136{
1137 return __libc_lseek64(fildes, offset, whence);
1138}
1139
1140
sewardj726c4122002-05-16 23:39:10 +00001141extern
1142ssize_t __libc_pread64 (int __fd, void *__buf, size_t __nbytes,
1143 __off64_t __offset);
1144ssize_t __pread64 (int __fd, void *__buf, size_t __nbytes,
1145 __off64_t __offset)
1146{
1147 return __libc_pread64(__fd, __buf, __nbytes, __offset);
1148}
1149
1150
sewardja18e2102002-05-18 10:43:22 +00001151extern
1152ssize_t __libc_pwrite64 (int __fd, const void *__buf, size_t __nbytes,
1153 __off64_t __offset);
1154ssize_t __pwrite64 (int __fd, const void *__buf, size_t __nbytes,
1155 __off64_t __offset)
1156{
1157 return __libc_pwrite64(__fd, __buf, __nbytes, __offset);
1158}
1159
sewardj726c4122002-05-16 23:39:10 +00001160
sewardj39b93b12002-05-18 10:56:27 +00001161extern
1162ssize_t __libc_pwrite(int fd, const void *buf, size_t count, off_t offset);
1163__attribute__((weak))
1164ssize_t pwrite(int fd, const void *buf, size_t count, off_t offset)
1165{
1166 return __libc_pwrite(fd, buf, count, offset);
1167}
1168
1169
1170extern
1171ssize_t __libc_pread(int fd, void *buf, size_t count, off_t offset);
1172__attribute__((weak))
1173ssize_t pread(int fd, void *buf, size_t count, off_t offset)
1174{
1175 return __libc_pread(fd, buf, count, offset);
1176}
1177
1178
sewardj6af4b5d2002-04-16 04:40:49 +00001179extern
1180void __libc_longjmp(jmp_buf env, int val) __attribute((noreturn));
sewardj5905fae2002-04-26 13:25:00 +00001181/* not weak: __attribute__((weak)) */
sewardj6af4b5d2002-04-16 04:40:49 +00001182void longjmp(jmp_buf env, int val)
1183{
1184 __libc_longjmp(env, val);
1185}
1186
sewardjbe32e452002-04-24 20:29:58 +00001187
sewardj6af4b5d2002-04-16 04:40:49 +00001188extern
1189int __libc_send(int s, const void *msg, size_t len, int flags);
sewardj5905fae2002-04-26 13:25:00 +00001190__attribute__((weak))
sewardj6af4b5d2002-04-16 04:40:49 +00001191int send(int s, const void *msg, size_t len, int flags)
1192{
1193 return __libc_send(s, msg, len, flags);
1194}
1195
sewardjbe32e452002-04-24 20:29:58 +00001196
sewardj1e8cdc92002-04-18 11:37:52 +00001197extern
1198int __libc_recv(int s, void *buf, size_t len, int flags);
sewardj5905fae2002-04-26 13:25:00 +00001199__attribute__((weak))
sewardj1e8cdc92002-04-18 11:37:52 +00001200int recv(int s, void *buf, size_t len, int flags)
1201{
1202 return __libc_recv(s, buf, len, flags);
1203}
1204
sewardjbe32e452002-04-24 20:29:58 +00001205
sewardj3665ded2002-05-16 16:57:25 +00001206extern
1207int __libc_sendmsg(int s, const struct msghdr *msg, int flags);
1208__attribute__((weak))
1209int sendmsg(int s, const struct msghdr *msg, int flags)
1210{
1211 return __libc_sendmsg(s, msg, flags);
1212}
1213
1214
sewardj796d6a22002-04-24 02:28:34 +00001215extern
sewardj436e0582002-04-26 14:31:40 +00001216int __libc_recvfrom(int s, void *buf, size_t len, int flags,
1217 struct sockaddr *from, socklen_t *fromlen);
1218__attribute__((weak))
1219int recvfrom(int s, void *buf, size_t len, int flags,
1220 struct sockaddr *from, socklen_t *fromlen)
1221{
1222 return __libc_recvfrom(s, buf, len, flags, from, fromlen);
1223}
1224
1225
1226extern
sewardj796d6a22002-04-24 02:28:34 +00001227int __libc_sendto(int s, const void *msg, size_t len, int flags,
1228 const struct sockaddr *to, socklen_t tolen);
sewardj5905fae2002-04-26 13:25:00 +00001229__attribute__((weak))
sewardj796d6a22002-04-24 02:28:34 +00001230int sendto(int s, const void *msg, size_t len, int flags,
1231 const struct sockaddr *to, socklen_t tolen)
1232{
1233 return __libc_sendto(s, msg, len, flags, to, tolen);
1234}
1235
sewardjbe32e452002-04-24 20:29:58 +00001236
sewardj369b1702002-04-24 13:28:15 +00001237extern
1238int __libc_system(const char* str);
sewardj5905fae2002-04-26 13:25:00 +00001239__attribute__((weak))
sewardj369b1702002-04-24 13:28:15 +00001240int system(const char* str)
1241{
1242 return __libc_system(str);
1243}
1244
sewardjbe32e452002-04-24 20:29:58 +00001245
sewardjab0b1c32002-04-24 19:26:47 +00001246extern
1247pid_t __libc_wait(int *status);
sewardj5905fae2002-04-26 13:25:00 +00001248__attribute__((weak))
sewardjab0b1c32002-04-24 19:26:47 +00001249pid_t wait(int *status)
1250{
1251 return __libc_wait(status);
1252}
1253
sewardj45b4b372002-04-16 22:50:32 +00001254
sewardj67f1d582002-05-24 02:11:32 +00001255extern
1256int __libc_msync(const void *start, size_t length, int flags);
1257__attribute__((weak))
1258int msync(const void *start, size_t length, int flags)
1259{
1260 return __libc_msync(start, length, flags);
1261}
1262
sewardj5905fae2002-04-26 13:25:00 +00001263
sewardj3b13f0e2002-04-25 20:17:29 +00001264/* ---------------------------------------------------------------------
1265 Nonblocking implementations of select() and poll(). This stuff will
1266 surely rot your mind.
1267 ------------------------------------------------------------------ */
sewardje663cb92002-04-12 10:26:32 +00001268
sewardj08a4c3f2002-04-13 03:45:44 +00001269/*--------------------------------------------------*/
1270
1271#include "vg_kerneliface.h"
1272
1273static
1274__inline__
1275int is_kerror ( int res )
1276{
1277 if (res >= -4095 && res <= -1)
1278 return 1;
1279 else
1280 return 0;
1281}
1282
1283
1284static
1285int my_do_syscall1 ( int syscallno, int arg1 )
1286{
1287 int __res;
1288 __asm__ volatile ("pushl %%ebx; movl %%edx,%%ebx ; int $0x80 ; popl %%ebx"
1289 : "=a" (__res)
1290 : "0" (syscallno),
1291 "d" (arg1) );
1292 return __res;
1293}
1294
1295static
1296int my_do_syscall2 ( int syscallno,
sewardjf854f472002-04-21 12:19:41 +00001297 int arg1, int arg2 )
sewardj08a4c3f2002-04-13 03:45:44 +00001298{
1299 int __res;
1300 __asm__ volatile ("pushl %%ebx; movl %%edx,%%ebx ; int $0x80 ; popl %%ebx"
1301 : "=a" (__res)
1302 : "0" (syscallno),
1303 "d" (arg1),
1304 "c" (arg2) );
1305 return __res;
1306}
1307
1308static
sewardjf854f472002-04-21 12:19:41 +00001309int my_do_syscall3 ( int syscallno,
1310 int arg1, int arg2, int arg3 )
1311{
1312 int __res;
1313 __asm__ volatile ("pushl %%ebx; movl %%esi,%%ebx ; int $0x80 ; popl %%ebx"
1314 : "=a" (__res)
1315 : "0" (syscallno),
1316 "S" (arg1),
1317 "c" (arg2),
1318 "d" (arg3) );
1319 return __res;
1320}
1321
1322static
sewardj08a4c3f2002-04-13 03:45:44 +00001323int do_syscall_select( int n,
1324 vki_fd_set* readfds,
1325 vki_fd_set* writefds,
1326 vki_fd_set* exceptfds,
1327 struct vki_timeval * timeout )
1328{
1329 int res;
1330 int args[5];
1331 args[0] = n;
1332 args[1] = (int)readfds;
1333 args[2] = (int)writefds;
1334 args[3] = (int)exceptfds;
1335 args[4] = (int)timeout;
1336 res = my_do_syscall1(__NR_select, (int)(&(args[0])) );
sewardj02535bc2002-04-21 01:08:26 +00001337 return res;
sewardj08a4c3f2002-04-13 03:45:44 +00001338}
1339
1340
1341/* This is a wrapper round select(), which makes it thread-safe,
1342 meaning that only this thread will block, rather than the entire
1343 process. This wrapper in turn depends on nanosleep() not to block
1344 the entire process, but I think (hope? suspect?) that POSIX
1345 pthreads guarantees that to be the case.
1346
1347 Basic idea is: modify the timeout parameter to select so that it
1348 returns immediately. Poll like this until select returns non-zero,
1349 indicating something interesting happened, or until our time is up.
1350 Space out the polls with nanosleeps of say 20 milliseconds, which
1351 is required to be nonblocking; this allows other threads to run.
sewardj02535bc2002-04-21 01:08:26 +00001352
1353 Assumes:
1354 * (checked via assert) types fd_set and vki_fd_set are identical.
1355 * (checked via assert) types timeval and vki_timeval are identical.
1356 * (unchecked) libc error numbers (EINTR etc) are the negation of the
1357 kernel's error numbers (VKI_EINTR etc).
sewardj08a4c3f2002-04-13 03:45:44 +00001358*/
sewardj08a4c3f2002-04-13 03:45:44 +00001359
sewardj5905fae2002-04-26 13:25:00 +00001360/* __attribute__((weak)) */
sewardj08a4c3f2002-04-13 03:45:44 +00001361int select ( int n,
1362 fd_set *rfds,
1363 fd_set *wfds,
1364 fd_set *xfds,
1365 struct timeval *timeout )
1366{
sewardj5f07b662002-04-23 16:52:51 +00001367 unsigned int ms_now, ms_end;
sewardj08a4c3f2002-04-13 03:45:44 +00001368 int res;
1369 fd_set rfds_copy;
1370 fd_set wfds_copy;
1371 fd_set xfds_copy;
1372 struct vki_timeval t_now;
sewardj08a4c3f2002-04-13 03:45:44 +00001373 struct vki_timeval zero_timeout;
1374 struct vki_timespec nanosleep_interval;
1375
sewardj5f07b662002-04-23 16:52:51 +00001376 /* gcc's complains about ms_end being used uninitialised -- classic
1377 case it can't understand, where ms_end is both defined and used
1378 only if timeout != NULL. Hence ... */
1379 ms_end = 0;
sewardj08a4c3f2002-04-13 03:45:44 +00001380
1381 /* We assume that the kernel and libc data layouts are identical
1382 for the following types. These asserts provide a crude
1383 check. */
1384 if (sizeof(fd_set) != sizeof(vki_fd_set)
1385 || sizeof(struct timeval) != sizeof(struct vki_timeval))
1386 barf("valgrind's hacky non-blocking select(): data sizes error");
1387
sewardj5f07b662002-04-23 16:52:51 +00001388 /* Detect the current time and simultaneously find out if we are
1389 running on Valgrind. */
1390 VALGRIND_MAGIC_SEQUENCE(ms_now, 0xFFFFFFFF /* default */,
1391 VG_USERREQ__READ_MILLISECOND_TIMER,
1392 0, 0, 0, 0);
1393
1394 /* If a zero timeout specified, this call is harmless. Also go
1395 this route if we're not running on Valgrind, for whatever
1396 reason. */
1397 if ( (timeout && timeout->tv_sec == 0 && timeout->tv_usec == 0)
1398 || (ms_now == 0xFFFFFFFF) ) {
sewardj02535bc2002-04-21 01:08:26 +00001399 res = do_syscall_select( n, (vki_fd_set*)rfds,
sewardj08a4c3f2002-04-13 03:45:44 +00001400 (vki_fd_set*)wfds,
1401 (vki_fd_set*)xfds,
1402 (struct vki_timeval*)timeout);
sewardj02535bc2002-04-21 01:08:26 +00001403 if (is_kerror(res)) {
1404 * (__errno_location()) = -res;
1405 return -1;
1406 } else {
1407 return res;
1408 }
1409 }
sewardj08a4c3f2002-04-13 03:45:44 +00001410
sewardj5f07b662002-04-23 16:52:51 +00001411 /* If a timeout was specified, set ms_end to be the end millisecond
1412 counter [wallclock] time. */
sewardj08a4c3f2002-04-13 03:45:44 +00001413 if (timeout) {
1414 res = my_do_syscall2(__NR_gettimeofday, (int)&t_now, (int)NULL);
1415 assert(res == 0);
sewardj5f07b662002-04-23 16:52:51 +00001416 ms_end = ms_now;
1417 ms_end += (timeout->tv_usec / 1000);
1418 ms_end += (timeout->tv_sec * 1000);
sewardj08a4c3f2002-04-13 03:45:44 +00001419 /* Stay sane ... */
sewardj5f07b662002-04-23 16:52:51 +00001420 assert (ms_end >= ms_now);
sewardj08a4c3f2002-04-13 03:45:44 +00001421 }
1422
1423 /* fprintf(stderr, "MY_SELECT: before loop\n"); */
1424
1425 /* Either timeout == NULL, meaning wait indefinitely, or timeout !=
sewardj5f07b662002-04-23 16:52:51 +00001426 NULL, in which case ms_end holds the end time. */
sewardj08a4c3f2002-04-13 03:45:44 +00001427 while (1) {
1428 if (timeout) {
sewardj5f07b662002-04-23 16:52:51 +00001429 VALGRIND_MAGIC_SEQUENCE(ms_now, 0xFFFFFFFF /* default */,
1430 VG_USERREQ__READ_MILLISECOND_TIMER,
1431 0, 0, 0, 0);
1432 assert(ms_now != 0xFFFFFFFF);
1433 if (ms_now >= ms_end) {
sewardj08a4c3f2002-04-13 03:45:44 +00001434 /* timeout; nothing interesting happened. */
1435 if (rfds) FD_ZERO(rfds);
1436 if (wfds) FD_ZERO(wfds);
1437 if (xfds) FD_ZERO(xfds);
1438 return 0;
1439 }
1440 }
1441
1442 /* These could be trashed each time round the loop, so restore
1443 them each time. */
1444 if (rfds) rfds_copy = *rfds;
1445 if (wfds) wfds_copy = *wfds;
1446 if (xfds) xfds_copy = *xfds;
1447
1448 zero_timeout.tv_sec = zero_timeout.tv_usec = 0;
1449
1450 res = do_syscall_select( n,
1451 rfds ? (vki_fd_set*)(&rfds_copy) : NULL,
1452 wfds ? (vki_fd_set*)(&wfds_copy) : NULL,
1453 xfds ? (vki_fd_set*)(&xfds_copy) : NULL,
1454 & zero_timeout );
sewardj02535bc2002-04-21 01:08:26 +00001455 if (is_kerror(res)) {
1456 /* Some kind of error (including EINTR). Set errno and
sewardj08a4c3f2002-04-13 03:45:44 +00001457 return. The sets are unspecified in this case. */
sewardj02535bc2002-04-21 01:08:26 +00001458 * (__errno_location()) = -res;
1459 return -1;
sewardj08a4c3f2002-04-13 03:45:44 +00001460 }
1461 if (res > 0) {
1462 /* one or more fds is ready. Copy out resulting sets and
1463 return. */
1464 if (rfds) *rfds = rfds_copy;
1465 if (wfds) *wfds = wfds_copy;
1466 if (xfds) *xfds = xfds_copy;
1467 return res;
1468 }
1469 /* fprintf(stderr, "MY_SELECT: nanosleep\n"); */
1470 /* nanosleep and go round again */
sewardj02535bc2002-04-21 01:08:26 +00001471 nanosleep_interval.tv_sec = 0;
sewardj956cc1b2002-04-25 01:33:50 +00001472 nanosleep_interval.tv_nsec = 50 * 1000 * 1000; /* 50 milliseconds */
sewardjf854f472002-04-21 12:19:41 +00001473 /* It's critical here that valgrind's nanosleep implementation
1474 is nonblocking. */
1475 (void)my_do_syscall2(__NR_nanosleep,
1476 (int)(&nanosleep_interval), (int)NULL);
1477 }
1478}
1479
1480
1481
1482
1483#include <sys/poll.h>
1484
sewardj72d58482002-04-24 02:20:20 +00001485#ifdef GLIBC_2_1
1486typedef unsigned long int nfds_t;
1487#endif
1488
sewardj705d3cb2002-05-23 13:13:12 +00001489
sewardj5905fae2002-04-26 13:25:00 +00001490/* __attribute__((weak)) */
sewardjf854f472002-04-21 12:19:41 +00001491int poll (struct pollfd *__fds, nfds_t __nfds, int __timeout)
1492{
sewardj5f07b662002-04-23 16:52:51 +00001493 unsigned int ms_now, ms_end;
sewardjf854f472002-04-21 12:19:41 +00001494 int res, i;
sewardjf854f472002-04-21 12:19:41 +00001495 struct vki_timespec nanosleep_interval;
1496
1497 ensure_valgrind("poll");
1498
sewardj5f07b662002-04-23 16:52:51 +00001499 /* Detect the current time and simultaneously find out if we are
1500 running on Valgrind. */
1501 VALGRIND_MAGIC_SEQUENCE(ms_now, 0xFFFFFFFF /* default */,
1502 VG_USERREQ__READ_MILLISECOND_TIMER,
1503 0, 0, 0, 0);
1504
sewardjf854f472002-04-21 12:19:41 +00001505 if (/* CHECK SIZES FOR struct pollfd */
1506 sizeof(struct timeval) != sizeof(struct vki_timeval))
1507 barf("valgrind's hacky non-blocking poll(): data sizes error");
1508
sewardj5f07b662002-04-23 16:52:51 +00001509 /* dummy initialisation to keep gcc -Wall happy */
1510 ms_end = 0;
1511
1512 /* If a zero timeout specified, this call is harmless. Also do
1513 this if not running on Valgrind. */
1514 if (__timeout == 0 || ms_now == 0xFFFFFFFF) {
sewardjf854f472002-04-21 12:19:41 +00001515 res = my_do_syscall3(__NR_poll, (int)__fds, __nfds, __timeout);
1516 if (is_kerror(res)) {
1517 * (__errno_location()) = -res;
1518 return -1;
1519 } else {
1520 return res;
1521 }
1522 }
1523
sewardj5f07b662002-04-23 16:52:51 +00001524 /* If a timeout was specified, set ms_end to be the end wallclock
1525 time. Easy considering that __timeout is in milliseconds. */
sewardjf854f472002-04-21 12:19:41 +00001526 if (__timeout > 0) {
sewardj650ac002002-04-29 12:20:34 +00001527 ms_end = ms_now + (unsigned int)__timeout;
sewardjf854f472002-04-21 12:19:41 +00001528 }
1529
1530 /* fprintf(stderr, "MY_POLL: before loop\n"); */
1531
1532 /* Either timeout < 0, meaning wait indefinitely, or timeout > 0,
1533 in which case t_end holds the end time. */
sewardj5f07b662002-04-23 16:52:51 +00001534 assert(__timeout != 0);
1535
sewardjf854f472002-04-21 12:19:41 +00001536 while (1) {
sewardjf854f472002-04-21 12:19:41 +00001537 if (__timeout > 0) {
sewardj5f07b662002-04-23 16:52:51 +00001538 VALGRIND_MAGIC_SEQUENCE(ms_now, 0xFFFFFFFF /* default */,
1539 VG_USERREQ__READ_MILLISECOND_TIMER,
1540 0, 0, 0, 0);
1541 assert(ms_now != 0xFFFFFFFF);
1542 if (ms_now >= ms_end) {
sewardjf854f472002-04-21 12:19:41 +00001543 /* timeout; nothing interesting happened. */
1544 for (i = 0; i < __nfds; i++)
1545 __fds[i].revents = 0;
1546 return 0;
1547 }
1548 }
1549
sewardj5f07b662002-04-23 16:52:51 +00001550 /* Do a return-immediately poll. */
sewardjf854f472002-04-21 12:19:41 +00001551 res = my_do_syscall3(__NR_poll, (int)__fds, __nfds, 0 );
1552 if (is_kerror(res)) {
1553 /* Some kind of error. Set errno and return. */
1554 * (__errno_location()) = -res;
1555 return -1;
1556 }
1557 if (res > 0) {
1558 /* One or more fds is ready. Return now. */
1559 return res;
1560 }
1561 /* fprintf(stderr, "MY_POLL: nanosleep\n"); */
1562 /* nanosleep and go round again */
1563 nanosleep_interval.tv_sec = 0;
sewardj956cc1b2002-04-25 01:33:50 +00001564 nanosleep_interval.tv_nsec = 51 * 1000 * 1000; /* 51 milliseconds */
sewardj08a4c3f2002-04-13 03:45:44 +00001565 /* It's critical here that valgrind's nanosleep implementation
1566 is nonblocking. */
1567 (void)my_do_syscall2(__NR_nanosleep,
1568 (int)(&nanosleep_interval), (int)NULL);
1569 }
1570}
sewardj3b13f0e2002-04-25 20:17:29 +00001571
1572
sewardj705d3cb2002-05-23 13:13:12 +00001573/* Helper function used to make accept() non-blocking. Idea is to use
1574 the above nonblocking poll() to make this thread ONLY wait for the
1575 specified fd to become ready, and then return. */
1576static void wait_for_fd_to_be_readable_or_erring ( int fd )
1577{
1578 struct pollfd pfd;
1579 fprintf(stderr, "wait_for_fd_to_be_readable_or_erring %d\n", fd);
1580 pfd.fd = fd;
1581 pfd.events = POLLIN | POLLPRI | POLLERR | POLLHUP | POLLNVAL;
1582 /* ... but not POLLOUT, you may notice. */
1583 pfd.revents = 0;
1584 (void)poll(&pfd, 1, -1 /* forever */);
1585}
1586
1587
sewardj3b13f0e2002-04-25 20:17:29 +00001588/* ---------------------------------------------------------------------
sewardj8f253ff2002-05-19 00:13:34 +00001589 Hacky implementation of semaphores.
1590 ------------------------------------------------------------------ */
1591
1592#include <semaphore.h>
1593
1594/* This is a terrible way to do the remapping. Plan is to import an
1595 AVL tree at some point. */
1596#define VG_N_SEMAPHORES 50
1597
1598typedef
1599 struct {
1600 pthread_mutex_t se_mx;
1601 pthread_cond_t se_cv;
1602 int count;
1603 }
1604 vg_sem_t;
1605
1606static pthread_mutex_t se_remap_mx = PTHREAD_MUTEX_INITIALIZER;
1607
1608static int se_remap_used = 0;
1609static sem_t* se_remap_orig[VG_N_SEMAPHORES];
1610static vg_sem_t se_remap_new[VG_N_SEMAPHORES];
1611
1612static vg_sem_t* se_remap ( sem_t* orig )
1613{
1614 int res, i;
1615 res = __pthread_mutex_lock(&se_remap_mx);
1616 assert(res == 0);
1617
1618 for (i = 0; i < se_remap_used; i++) {
1619 if (se_remap_orig[i] == orig)
1620 break;
1621 }
1622 if (i == se_remap_used) {
1623 if (se_remap_used == VG_N_SEMAPHORES) {
1624 res = pthread_mutex_unlock(&se_remap_mx);
1625 assert(res == 0);
1626 barf("N_SEMAPHORES is too low. Increase and recompile.");
1627 }
1628 se_remap_used++;
1629 se_remap_orig[i] = orig;
1630 /* printf("allocated semaphore %d\n", i); */
1631 }
1632 res = __pthread_mutex_unlock(&se_remap_mx);
1633 assert(res == 0);
1634 return &se_remap_new[i];
1635}
1636
1637
1638int sem_init(sem_t *sem, int pshared, unsigned int value)
1639{
1640 int res;
1641 vg_sem_t* vg_sem;
1642 ensure_valgrind("sem_init");
1643 if (pshared != 0) {
1644 errno = ENOSYS;
1645 return -1;
1646 }
1647 vg_sem = se_remap(sem);
1648 res = pthread_mutex_init(&vg_sem->se_mx, NULL);
1649 assert(res == 0);
1650 res = pthread_cond_init(&vg_sem->se_cv, NULL);
1651 assert(res == 0);
1652 vg_sem->count = value;
1653 return 0;
1654}
1655
1656
1657int sem_wait ( sem_t* sem )
1658{
1659 int res;
1660 vg_sem_t* vg_sem;
1661 ensure_valgrind("sem_wait");
1662 vg_sem = se_remap(sem);
1663 res = __pthread_mutex_lock(&vg_sem->se_mx);
1664 assert(res == 0);
1665 while (vg_sem->count == 0) {
1666 res = pthread_cond_wait(&vg_sem->se_cv, &vg_sem->se_mx);
1667 assert(res == 0);
1668 }
1669 vg_sem->count--;
1670 res = __pthread_mutex_unlock(&vg_sem->se_mx);
1671 assert(res == 0);
1672 return 0;
1673}
1674
1675int sem_post ( sem_t* sem )
1676{
1677 int res;
1678 vg_sem_t* vg_sem;
1679 ensure_valgrind("sem_post");
1680 vg_sem = se_remap(sem);
1681 res = __pthread_mutex_lock(&vg_sem->se_mx);
1682 assert(res == 0);
1683 if (vg_sem->count == 0) {
1684 vg_sem->count++;
1685 res = pthread_cond_broadcast(&vg_sem->se_cv);
1686 assert(res == 0);
1687 } else {
1688 vg_sem->count++;
1689 }
1690 res = __pthread_mutex_unlock(&vg_sem->se_mx);
1691 assert(res == 0);
1692 return 0;
1693}
1694
1695
1696int sem_trywait ( sem_t* sem )
1697{
1698 int ret, res;
1699 vg_sem_t* vg_sem;
1700 ensure_valgrind("sem_trywait");
1701 vg_sem = se_remap(sem);
1702 res = __pthread_mutex_lock(&vg_sem->se_mx);
1703 assert(res == 0);
1704 if (vg_sem->count > 0) {
1705 vg_sem->count--;
1706 ret = 0;
1707 } else {
1708 ret = -1;
1709 errno = EAGAIN;
1710 }
1711 res = __pthread_mutex_unlock(&vg_sem->se_mx);
1712 assert(res == 0);
1713 return ret;
1714}
1715
1716
1717int sem_getvalue(sem_t* sem, int * sval)
1718{
1719 vg_sem_t* vg_sem;
1720 ensure_valgrind("sem_trywait");
1721 vg_sem = se_remap(sem);
1722 *sval = vg_sem->count;
1723 return 0;
1724}
1725
1726
1727int sem_destroy(sem_t * sem)
1728{
1729 kludged("sem_destroy");
1730 /* if someone waiting on this semaphore, errno = EBUSY, return -1 */
1731 return 0;
1732}
1733
1734
1735/* ---------------------------------------------------------------------
sewardj3b13f0e2002-04-25 20:17:29 +00001736 B'stard.
1737 ------------------------------------------------------------------ */
1738
1739# define strong_alias(name, aliasname) \
1740 extern __typeof (name) aliasname __attribute__ ((alias (#name)));
1741
sewardj5905fae2002-04-26 13:25:00 +00001742# define weak_alias(name, aliasname) \
1743 extern __typeof (name) aliasname __attribute__ ((weak, alias (#name)));
sewardj3b13f0e2002-04-25 20:17:29 +00001744
sewardj5905fae2002-04-26 13:25:00 +00001745strong_alias(__pthread_mutex_lock, pthread_mutex_lock)
1746strong_alias(__pthread_mutex_trylock, pthread_mutex_trylock)
1747strong_alias(__pthread_mutex_unlock, pthread_mutex_unlock)
1748strong_alias(__pthread_mutexattr_init, pthread_mutexattr_init)
1749 weak_alias(__pthread_mutexattr_settype, pthread_mutexattr_settype)
1750strong_alias(__pthread_mutex_init, pthread_mutex_init)
1751strong_alias(__pthread_mutexattr_destroy, pthread_mutexattr_destroy)
1752strong_alias(__pthread_mutex_destroy, pthread_mutex_destroy)
1753strong_alias(__pthread_once, pthread_once)
1754strong_alias(__pthread_atfork, pthread_atfork)
1755strong_alias(__pthread_key_create, pthread_key_create)
1756strong_alias(__pthread_getspecific, pthread_getspecific)
1757strong_alias(__pthread_setspecific, pthread_setspecific)
1758
sewardjd529a442002-05-04 19:49:21 +00001759#ifndef GLIBC_2_1
sewardj3b13f0e2002-04-25 20:17:29 +00001760strong_alias(sigaction, __sigaction)
sewardjd529a442002-05-04 19:49:21 +00001761#endif
1762
sewardj5905fae2002-04-26 13:25:00 +00001763strong_alias(close, __close)
sewardj3b13f0e2002-04-25 20:17:29 +00001764strong_alias(fcntl, __fcntl)
sewardj5905fae2002-04-26 13:25:00 +00001765strong_alias(lseek, __lseek)
1766strong_alias(open, __open)
1767strong_alias(open64, __open64)
sewardj5905fae2002-04-26 13:25:00 +00001768strong_alias(read, __read)
1769strong_alias(wait, __wait)
1770strong_alias(write, __write)
sewardj3b13f0e2002-04-25 20:17:29 +00001771strong_alias(connect, __connect)
sewardj5905fae2002-04-26 13:25:00 +00001772strong_alias(send, __send)
1773
sewardj726c4122002-05-16 23:39:10 +00001774weak_alias (__pread64, pread64)
sewardja18e2102002-05-18 10:43:22 +00001775weak_alias (__pwrite64, pwrite64)
sewardj5905fae2002-04-26 13:25:00 +00001776weak_alias(__fork, fork)
sewardj7f6456d2002-05-21 00:51:21 +00001777
sewardj5905fae2002-04-26 13:25:00 +00001778
sewardj3b13f0e2002-04-25 20:17:29 +00001779
1780/*--------------------------------------------------*/
1781
sewardj5716dbb2002-04-26 03:28:18 +00001782int
1783pthread_rwlock_rdlock (void* /* pthread_rwlock_t* */ rwlock)
1784{
sewardj436e0582002-04-26 14:31:40 +00001785 static int moans = N_MOANS;
1786 if (moans-- > 0)
1787 kludged("pthread_rwlock_rdlock");
sewardj5716dbb2002-04-26 03:28:18 +00001788 return 0;
1789}
1790
sewardj5905fae2002-04-26 13:25:00 +00001791weak_alias(pthread_rwlock_rdlock, __pthread_rwlock_rdlock)
sewardj5716dbb2002-04-26 03:28:18 +00001792
1793
1794int
1795pthread_rwlock_unlock (void* /* pthread_rwlock_t* */ rwlock)
1796{
sewardj436e0582002-04-26 14:31:40 +00001797 static int moans = N_MOANS;
1798 if (moans-- > 0)
1799 kludged("pthread_rwlock_unlock");
sewardj5716dbb2002-04-26 03:28:18 +00001800 return 0;
1801}
1802
sewardj5905fae2002-04-26 13:25:00 +00001803weak_alias(pthread_rwlock_unlock, __pthread_rwlock_unlock)
sewardj5716dbb2002-04-26 03:28:18 +00001804
1805
sewardj060b04f2002-04-26 21:01:13 +00001806int
1807pthread_rwlock_wrlock (void* /* pthread_rwlock_t* */ rwlock)
1808{
1809 static int moans = N_MOANS;
1810 if (moans-- > 0)
1811 kludged("pthread_rwlock_wrlock");
1812 return 0;
1813}
1814
sewardj262b0292002-05-01 00:03:16 +00001815weak_alias(pthread_rwlock_wrlock, __pthread_rwlock_wrlock)
sewardj060b04f2002-04-26 21:01:13 +00001816
1817
sewardj3b13f0e2002-04-25 20:17:29 +00001818/* I've no idea what these are, but they get called quite a lot.
1819 Anybody know? */
1820
1821#undef _IO_flockfile
1822void _IO_flockfile ( _IO_FILE * file )
1823{
sewardj853f55d2002-04-26 00:27:53 +00001824 pthread_mutex_lock(file->_lock);
sewardj3b13f0e2002-04-25 20:17:29 +00001825}
sewardj5905fae2002-04-26 13:25:00 +00001826weak_alias(_IO_flockfile, flockfile);
1827
sewardj3b13f0e2002-04-25 20:17:29 +00001828
1829#undef _IO_funlockfile
1830void _IO_funlockfile ( _IO_FILE * file )
1831{
sewardj853f55d2002-04-26 00:27:53 +00001832 pthread_mutex_unlock(file->_lock);
sewardj3b13f0e2002-04-25 20:17:29 +00001833}
sewardj5905fae2002-04-26 13:25:00 +00001834weak_alias(_IO_funlockfile, funlockfile);
1835
sewardj3b13f0e2002-04-25 20:17:29 +00001836
1837void _pthread_cleanup_push_defer ( void )
1838{
sewardj439d45e2002-05-03 20:43:10 +00001839 static int moans = N_MOANS;
1840 if (moans-- > 0)
1841 ignored("_pthread_cleanup_push_defer");
sewardj3b13f0e2002-04-25 20:17:29 +00001842}
1843
1844void _pthread_cleanup_pop_restore ( void )
1845{
sewardj439d45e2002-05-03 20:43:10 +00001846 static int moans = N_MOANS;
1847 if (moans-- > 0)
1848 ignored("_pthread_cleanup_pop_restore");
sewardj3b13f0e2002-04-25 20:17:29 +00001849}
sewardjd4f2c712002-04-30 10:20:10 +00001850
sewardj60e38422002-05-08 14:08:22 +00001851/*--------*/
1852void _pthread_cleanup_push (struct _pthread_cleanup_buffer *__buffer,
1853 void (*__routine) (void *),
1854 void *__arg)
1855{
1856 static int moans = N_MOANS;
1857 if (moans-- > 0)
1858 ignored("_pthread_cleanup_push");
1859}
1860
1861void _pthread_cleanup_pop (struct _pthread_cleanup_buffer *__buffer,
1862 int __execute)
1863{
1864 static int moans = N_MOANS;
1865 if (moans-- > 0) {
1866 if (__execute)
1867 ignored("_pthread_cleanup_pop-EXECUTE");
1868 else
1869 ignored("_pthread_cleanup_pop-NO-EXECUTE");
1870 }
1871}
1872
sewardjd4f2c712002-04-30 10:20:10 +00001873
1874/* This doesn't seem to be needed to simulate libpthread.so's external
1875 interface, but many people complain about its absence. */
1876
1877strong_alias(__pthread_mutexattr_settype, __pthread_mutexattr_setkind_np)
1878weak_alias(__pthread_mutexattr_setkind_np, pthread_mutexattr_setkind_np)
sewardj439d45e2002-05-03 20:43:10 +00001879
1880
1881/*--------------------------------------------------------------------*/
1882/*--- end vg_libpthread.c ---*/
1883/*--------------------------------------------------------------------*/