blob: 6cd7e40d0cf91166c417c386cdbe5068b7953b04 [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
sewardj5905fae2002-04-26 13:25:00 +00001255
sewardj3b13f0e2002-04-25 20:17:29 +00001256/* ---------------------------------------------------------------------
1257 Nonblocking implementations of select() and poll(). This stuff will
1258 surely rot your mind.
1259 ------------------------------------------------------------------ */
sewardje663cb92002-04-12 10:26:32 +00001260
sewardj08a4c3f2002-04-13 03:45:44 +00001261/*--------------------------------------------------*/
1262
1263#include "vg_kerneliface.h"
1264
1265static
1266__inline__
1267int is_kerror ( int res )
1268{
1269 if (res >= -4095 && res <= -1)
1270 return 1;
1271 else
1272 return 0;
1273}
1274
1275
1276static
1277int my_do_syscall1 ( int syscallno, int arg1 )
1278{
1279 int __res;
1280 __asm__ volatile ("pushl %%ebx; movl %%edx,%%ebx ; int $0x80 ; popl %%ebx"
1281 : "=a" (__res)
1282 : "0" (syscallno),
1283 "d" (arg1) );
1284 return __res;
1285}
1286
1287static
1288int my_do_syscall2 ( int syscallno,
sewardjf854f472002-04-21 12:19:41 +00001289 int arg1, int arg2 )
sewardj08a4c3f2002-04-13 03:45:44 +00001290{
1291 int __res;
1292 __asm__ volatile ("pushl %%ebx; movl %%edx,%%ebx ; int $0x80 ; popl %%ebx"
1293 : "=a" (__res)
1294 : "0" (syscallno),
1295 "d" (arg1),
1296 "c" (arg2) );
1297 return __res;
1298}
1299
1300static
sewardjf854f472002-04-21 12:19:41 +00001301int my_do_syscall3 ( int syscallno,
1302 int arg1, int arg2, int arg3 )
1303{
1304 int __res;
1305 __asm__ volatile ("pushl %%ebx; movl %%esi,%%ebx ; int $0x80 ; popl %%ebx"
1306 : "=a" (__res)
1307 : "0" (syscallno),
1308 "S" (arg1),
1309 "c" (arg2),
1310 "d" (arg3) );
1311 return __res;
1312}
1313
1314static
sewardj08a4c3f2002-04-13 03:45:44 +00001315int do_syscall_select( int n,
1316 vki_fd_set* readfds,
1317 vki_fd_set* writefds,
1318 vki_fd_set* exceptfds,
1319 struct vki_timeval * timeout )
1320{
1321 int res;
1322 int args[5];
1323 args[0] = n;
1324 args[1] = (int)readfds;
1325 args[2] = (int)writefds;
1326 args[3] = (int)exceptfds;
1327 args[4] = (int)timeout;
1328 res = my_do_syscall1(__NR_select, (int)(&(args[0])) );
sewardj02535bc2002-04-21 01:08:26 +00001329 return res;
sewardj08a4c3f2002-04-13 03:45:44 +00001330}
1331
1332
1333/* This is a wrapper round select(), which makes it thread-safe,
1334 meaning that only this thread will block, rather than the entire
1335 process. This wrapper in turn depends on nanosleep() not to block
1336 the entire process, but I think (hope? suspect?) that POSIX
1337 pthreads guarantees that to be the case.
1338
1339 Basic idea is: modify the timeout parameter to select so that it
1340 returns immediately. Poll like this until select returns non-zero,
1341 indicating something interesting happened, or until our time is up.
1342 Space out the polls with nanosleeps of say 20 milliseconds, which
1343 is required to be nonblocking; this allows other threads to run.
sewardj02535bc2002-04-21 01:08:26 +00001344
1345 Assumes:
1346 * (checked via assert) types fd_set and vki_fd_set are identical.
1347 * (checked via assert) types timeval and vki_timeval are identical.
1348 * (unchecked) libc error numbers (EINTR etc) are the negation of the
1349 kernel's error numbers (VKI_EINTR etc).
sewardj08a4c3f2002-04-13 03:45:44 +00001350*/
sewardj08a4c3f2002-04-13 03:45:44 +00001351
sewardj5905fae2002-04-26 13:25:00 +00001352/* __attribute__((weak)) */
sewardj08a4c3f2002-04-13 03:45:44 +00001353int select ( int n,
1354 fd_set *rfds,
1355 fd_set *wfds,
1356 fd_set *xfds,
1357 struct timeval *timeout )
1358{
sewardj5f07b662002-04-23 16:52:51 +00001359 unsigned int ms_now, ms_end;
sewardj08a4c3f2002-04-13 03:45:44 +00001360 int res;
1361 fd_set rfds_copy;
1362 fd_set wfds_copy;
1363 fd_set xfds_copy;
1364 struct vki_timeval t_now;
sewardj08a4c3f2002-04-13 03:45:44 +00001365 struct vki_timeval zero_timeout;
1366 struct vki_timespec nanosleep_interval;
1367
sewardj5f07b662002-04-23 16:52:51 +00001368 /* gcc's complains about ms_end being used uninitialised -- classic
1369 case it can't understand, where ms_end is both defined and used
1370 only if timeout != NULL. Hence ... */
1371 ms_end = 0;
sewardj08a4c3f2002-04-13 03:45:44 +00001372
1373 /* We assume that the kernel and libc data layouts are identical
1374 for the following types. These asserts provide a crude
1375 check. */
1376 if (sizeof(fd_set) != sizeof(vki_fd_set)
1377 || sizeof(struct timeval) != sizeof(struct vki_timeval))
1378 barf("valgrind's hacky non-blocking select(): data sizes error");
1379
sewardj5f07b662002-04-23 16:52:51 +00001380 /* Detect the current time and simultaneously find out if we are
1381 running on Valgrind. */
1382 VALGRIND_MAGIC_SEQUENCE(ms_now, 0xFFFFFFFF /* default */,
1383 VG_USERREQ__READ_MILLISECOND_TIMER,
1384 0, 0, 0, 0);
1385
1386 /* If a zero timeout specified, this call is harmless. Also go
1387 this route if we're not running on Valgrind, for whatever
1388 reason. */
1389 if ( (timeout && timeout->tv_sec == 0 && timeout->tv_usec == 0)
1390 || (ms_now == 0xFFFFFFFF) ) {
sewardj02535bc2002-04-21 01:08:26 +00001391 res = do_syscall_select( n, (vki_fd_set*)rfds,
sewardj08a4c3f2002-04-13 03:45:44 +00001392 (vki_fd_set*)wfds,
1393 (vki_fd_set*)xfds,
1394 (struct vki_timeval*)timeout);
sewardj02535bc2002-04-21 01:08:26 +00001395 if (is_kerror(res)) {
1396 * (__errno_location()) = -res;
1397 return -1;
1398 } else {
1399 return res;
1400 }
1401 }
sewardj08a4c3f2002-04-13 03:45:44 +00001402
sewardj5f07b662002-04-23 16:52:51 +00001403 /* If a timeout was specified, set ms_end to be the end millisecond
1404 counter [wallclock] time. */
sewardj08a4c3f2002-04-13 03:45:44 +00001405 if (timeout) {
1406 res = my_do_syscall2(__NR_gettimeofday, (int)&t_now, (int)NULL);
1407 assert(res == 0);
sewardj5f07b662002-04-23 16:52:51 +00001408 ms_end = ms_now;
1409 ms_end += (timeout->tv_usec / 1000);
1410 ms_end += (timeout->tv_sec * 1000);
sewardj08a4c3f2002-04-13 03:45:44 +00001411 /* Stay sane ... */
sewardj5f07b662002-04-23 16:52:51 +00001412 assert (ms_end >= ms_now);
sewardj08a4c3f2002-04-13 03:45:44 +00001413 }
1414
1415 /* fprintf(stderr, "MY_SELECT: before loop\n"); */
1416
1417 /* Either timeout == NULL, meaning wait indefinitely, or timeout !=
sewardj5f07b662002-04-23 16:52:51 +00001418 NULL, in which case ms_end holds the end time. */
sewardj08a4c3f2002-04-13 03:45:44 +00001419 while (1) {
1420 if (timeout) {
sewardj5f07b662002-04-23 16:52:51 +00001421 VALGRIND_MAGIC_SEQUENCE(ms_now, 0xFFFFFFFF /* default */,
1422 VG_USERREQ__READ_MILLISECOND_TIMER,
1423 0, 0, 0, 0);
1424 assert(ms_now != 0xFFFFFFFF);
1425 if (ms_now >= ms_end) {
sewardj08a4c3f2002-04-13 03:45:44 +00001426 /* timeout; nothing interesting happened. */
1427 if (rfds) FD_ZERO(rfds);
1428 if (wfds) FD_ZERO(wfds);
1429 if (xfds) FD_ZERO(xfds);
1430 return 0;
1431 }
1432 }
1433
1434 /* These could be trashed each time round the loop, so restore
1435 them each time. */
1436 if (rfds) rfds_copy = *rfds;
1437 if (wfds) wfds_copy = *wfds;
1438 if (xfds) xfds_copy = *xfds;
1439
1440 zero_timeout.tv_sec = zero_timeout.tv_usec = 0;
1441
1442 res = do_syscall_select( n,
1443 rfds ? (vki_fd_set*)(&rfds_copy) : NULL,
1444 wfds ? (vki_fd_set*)(&wfds_copy) : NULL,
1445 xfds ? (vki_fd_set*)(&xfds_copy) : NULL,
1446 & zero_timeout );
sewardj02535bc2002-04-21 01:08:26 +00001447 if (is_kerror(res)) {
1448 /* Some kind of error (including EINTR). Set errno and
sewardj08a4c3f2002-04-13 03:45:44 +00001449 return. The sets are unspecified in this case. */
sewardj02535bc2002-04-21 01:08:26 +00001450 * (__errno_location()) = -res;
1451 return -1;
sewardj08a4c3f2002-04-13 03:45:44 +00001452 }
1453 if (res > 0) {
1454 /* one or more fds is ready. Copy out resulting sets and
1455 return. */
1456 if (rfds) *rfds = rfds_copy;
1457 if (wfds) *wfds = wfds_copy;
1458 if (xfds) *xfds = xfds_copy;
1459 return res;
1460 }
1461 /* fprintf(stderr, "MY_SELECT: nanosleep\n"); */
1462 /* nanosleep and go round again */
sewardj02535bc2002-04-21 01:08:26 +00001463 nanosleep_interval.tv_sec = 0;
sewardj956cc1b2002-04-25 01:33:50 +00001464 nanosleep_interval.tv_nsec = 50 * 1000 * 1000; /* 50 milliseconds */
sewardjf854f472002-04-21 12:19:41 +00001465 /* It's critical here that valgrind's nanosleep implementation
1466 is nonblocking. */
1467 (void)my_do_syscall2(__NR_nanosleep,
1468 (int)(&nanosleep_interval), (int)NULL);
1469 }
1470}
1471
1472
1473
1474
1475#include <sys/poll.h>
1476
sewardj72d58482002-04-24 02:20:20 +00001477#ifdef GLIBC_2_1
1478typedef unsigned long int nfds_t;
1479#endif
1480
sewardj705d3cb2002-05-23 13:13:12 +00001481
sewardj5905fae2002-04-26 13:25:00 +00001482/* __attribute__((weak)) */
sewardjf854f472002-04-21 12:19:41 +00001483int poll (struct pollfd *__fds, nfds_t __nfds, int __timeout)
1484{
sewardj5f07b662002-04-23 16:52:51 +00001485 unsigned int ms_now, ms_end;
sewardjf854f472002-04-21 12:19:41 +00001486 int res, i;
sewardjf854f472002-04-21 12:19:41 +00001487 struct vki_timespec nanosleep_interval;
1488
1489 ensure_valgrind("poll");
1490
sewardj5f07b662002-04-23 16:52:51 +00001491 /* Detect the current time and simultaneously find out if we are
1492 running on Valgrind. */
1493 VALGRIND_MAGIC_SEQUENCE(ms_now, 0xFFFFFFFF /* default */,
1494 VG_USERREQ__READ_MILLISECOND_TIMER,
1495 0, 0, 0, 0);
1496
sewardjf854f472002-04-21 12:19:41 +00001497 if (/* CHECK SIZES FOR struct pollfd */
1498 sizeof(struct timeval) != sizeof(struct vki_timeval))
1499 barf("valgrind's hacky non-blocking poll(): data sizes error");
1500
sewardj5f07b662002-04-23 16:52:51 +00001501 /* dummy initialisation to keep gcc -Wall happy */
1502 ms_end = 0;
1503
1504 /* If a zero timeout specified, this call is harmless. Also do
1505 this if not running on Valgrind. */
1506 if (__timeout == 0 || ms_now == 0xFFFFFFFF) {
sewardjf854f472002-04-21 12:19:41 +00001507 res = my_do_syscall3(__NR_poll, (int)__fds, __nfds, __timeout);
1508 if (is_kerror(res)) {
1509 * (__errno_location()) = -res;
1510 return -1;
1511 } else {
1512 return res;
1513 }
1514 }
1515
sewardj5f07b662002-04-23 16:52:51 +00001516 /* If a timeout was specified, set ms_end to be the end wallclock
1517 time. Easy considering that __timeout is in milliseconds. */
sewardjf854f472002-04-21 12:19:41 +00001518 if (__timeout > 0) {
sewardj650ac002002-04-29 12:20:34 +00001519 ms_end = ms_now + (unsigned int)__timeout;
sewardjf854f472002-04-21 12:19:41 +00001520 }
1521
1522 /* fprintf(stderr, "MY_POLL: before loop\n"); */
1523
1524 /* Either timeout < 0, meaning wait indefinitely, or timeout > 0,
1525 in which case t_end holds the end time. */
sewardj5f07b662002-04-23 16:52:51 +00001526 assert(__timeout != 0);
1527
sewardjf854f472002-04-21 12:19:41 +00001528 while (1) {
sewardjf854f472002-04-21 12:19:41 +00001529 if (__timeout > 0) {
sewardj5f07b662002-04-23 16:52:51 +00001530 VALGRIND_MAGIC_SEQUENCE(ms_now, 0xFFFFFFFF /* default */,
1531 VG_USERREQ__READ_MILLISECOND_TIMER,
1532 0, 0, 0, 0);
1533 assert(ms_now != 0xFFFFFFFF);
1534 if (ms_now >= ms_end) {
sewardjf854f472002-04-21 12:19:41 +00001535 /* timeout; nothing interesting happened. */
1536 for (i = 0; i < __nfds; i++)
1537 __fds[i].revents = 0;
1538 return 0;
1539 }
1540 }
1541
sewardj5f07b662002-04-23 16:52:51 +00001542 /* Do a return-immediately poll. */
sewardjf854f472002-04-21 12:19:41 +00001543 res = my_do_syscall3(__NR_poll, (int)__fds, __nfds, 0 );
1544 if (is_kerror(res)) {
1545 /* Some kind of error. Set errno and return. */
1546 * (__errno_location()) = -res;
1547 return -1;
1548 }
1549 if (res > 0) {
1550 /* One or more fds is ready. Return now. */
1551 return res;
1552 }
1553 /* fprintf(stderr, "MY_POLL: nanosleep\n"); */
1554 /* nanosleep and go round again */
1555 nanosleep_interval.tv_sec = 0;
sewardj956cc1b2002-04-25 01:33:50 +00001556 nanosleep_interval.tv_nsec = 51 * 1000 * 1000; /* 51 milliseconds */
sewardj08a4c3f2002-04-13 03:45:44 +00001557 /* It's critical here that valgrind's nanosleep implementation
1558 is nonblocking. */
1559 (void)my_do_syscall2(__NR_nanosleep,
1560 (int)(&nanosleep_interval), (int)NULL);
1561 }
1562}
sewardj3b13f0e2002-04-25 20:17:29 +00001563
1564
sewardj705d3cb2002-05-23 13:13:12 +00001565/* Helper function used to make accept() non-blocking. Idea is to use
1566 the above nonblocking poll() to make this thread ONLY wait for the
1567 specified fd to become ready, and then return. */
1568static void wait_for_fd_to_be_readable_or_erring ( int fd )
1569{
1570 struct pollfd pfd;
1571 fprintf(stderr, "wait_for_fd_to_be_readable_or_erring %d\n", fd);
1572 pfd.fd = fd;
1573 pfd.events = POLLIN | POLLPRI | POLLERR | POLLHUP | POLLNVAL;
1574 /* ... but not POLLOUT, you may notice. */
1575 pfd.revents = 0;
1576 (void)poll(&pfd, 1, -1 /* forever */);
1577}
1578
1579
sewardj3b13f0e2002-04-25 20:17:29 +00001580/* ---------------------------------------------------------------------
sewardj8f253ff2002-05-19 00:13:34 +00001581 Hacky implementation of semaphores.
1582 ------------------------------------------------------------------ */
1583
1584#include <semaphore.h>
1585
1586/* This is a terrible way to do the remapping. Plan is to import an
1587 AVL tree at some point. */
1588#define VG_N_SEMAPHORES 50
1589
1590typedef
1591 struct {
1592 pthread_mutex_t se_mx;
1593 pthread_cond_t se_cv;
1594 int count;
1595 }
1596 vg_sem_t;
1597
1598static pthread_mutex_t se_remap_mx = PTHREAD_MUTEX_INITIALIZER;
1599
1600static int se_remap_used = 0;
1601static sem_t* se_remap_orig[VG_N_SEMAPHORES];
1602static vg_sem_t se_remap_new[VG_N_SEMAPHORES];
1603
1604static vg_sem_t* se_remap ( sem_t* orig )
1605{
1606 int res, i;
1607 res = __pthread_mutex_lock(&se_remap_mx);
1608 assert(res == 0);
1609
1610 for (i = 0; i < se_remap_used; i++) {
1611 if (se_remap_orig[i] == orig)
1612 break;
1613 }
1614 if (i == se_remap_used) {
1615 if (se_remap_used == VG_N_SEMAPHORES) {
1616 res = pthread_mutex_unlock(&se_remap_mx);
1617 assert(res == 0);
1618 barf("N_SEMAPHORES is too low. Increase and recompile.");
1619 }
1620 se_remap_used++;
1621 se_remap_orig[i] = orig;
1622 /* printf("allocated semaphore %d\n", i); */
1623 }
1624 res = __pthread_mutex_unlock(&se_remap_mx);
1625 assert(res == 0);
1626 return &se_remap_new[i];
1627}
1628
1629
1630int sem_init(sem_t *sem, int pshared, unsigned int value)
1631{
1632 int res;
1633 vg_sem_t* vg_sem;
1634 ensure_valgrind("sem_init");
1635 if (pshared != 0) {
1636 errno = ENOSYS;
1637 return -1;
1638 }
1639 vg_sem = se_remap(sem);
1640 res = pthread_mutex_init(&vg_sem->se_mx, NULL);
1641 assert(res == 0);
1642 res = pthread_cond_init(&vg_sem->se_cv, NULL);
1643 assert(res == 0);
1644 vg_sem->count = value;
1645 return 0;
1646}
1647
1648
1649int sem_wait ( sem_t* sem )
1650{
1651 int res;
1652 vg_sem_t* vg_sem;
1653 ensure_valgrind("sem_wait");
1654 vg_sem = se_remap(sem);
1655 res = __pthread_mutex_lock(&vg_sem->se_mx);
1656 assert(res == 0);
1657 while (vg_sem->count == 0) {
1658 res = pthread_cond_wait(&vg_sem->se_cv, &vg_sem->se_mx);
1659 assert(res == 0);
1660 }
1661 vg_sem->count--;
1662 res = __pthread_mutex_unlock(&vg_sem->se_mx);
1663 assert(res == 0);
1664 return 0;
1665}
1666
1667int sem_post ( sem_t* sem )
1668{
1669 int res;
1670 vg_sem_t* vg_sem;
1671 ensure_valgrind("sem_post");
1672 vg_sem = se_remap(sem);
1673 res = __pthread_mutex_lock(&vg_sem->se_mx);
1674 assert(res == 0);
1675 if (vg_sem->count == 0) {
1676 vg_sem->count++;
1677 res = pthread_cond_broadcast(&vg_sem->se_cv);
1678 assert(res == 0);
1679 } else {
1680 vg_sem->count++;
1681 }
1682 res = __pthread_mutex_unlock(&vg_sem->se_mx);
1683 assert(res == 0);
1684 return 0;
1685}
1686
1687
1688int sem_trywait ( sem_t* sem )
1689{
1690 int ret, res;
1691 vg_sem_t* vg_sem;
1692 ensure_valgrind("sem_trywait");
1693 vg_sem = se_remap(sem);
1694 res = __pthread_mutex_lock(&vg_sem->se_mx);
1695 assert(res == 0);
1696 if (vg_sem->count > 0) {
1697 vg_sem->count--;
1698 ret = 0;
1699 } else {
1700 ret = -1;
1701 errno = EAGAIN;
1702 }
1703 res = __pthread_mutex_unlock(&vg_sem->se_mx);
1704 assert(res == 0);
1705 return ret;
1706}
1707
1708
1709int sem_getvalue(sem_t* sem, int * sval)
1710{
1711 vg_sem_t* vg_sem;
1712 ensure_valgrind("sem_trywait");
1713 vg_sem = se_remap(sem);
1714 *sval = vg_sem->count;
1715 return 0;
1716}
1717
1718
1719int sem_destroy(sem_t * sem)
1720{
1721 kludged("sem_destroy");
1722 /* if someone waiting on this semaphore, errno = EBUSY, return -1 */
1723 return 0;
1724}
1725
1726
1727/* ---------------------------------------------------------------------
sewardj3b13f0e2002-04-25 20:17:29 +00001728 B'stard.
1729 ------------------------------------------------------------------ */
1730
1731# define strong_alias(name, aliasname) \
1732 extern __typeof (name) aliasname __attribute__ ((alias (#name)));
1733
sewardj5905fae2002-04-26 13:25:00 +00001734# define weak_alias(name, aliasname) \
1735 extern __typeof (name) aliasname __attribute__ ((weak, alias (#name)));
sewardj3b13f0e2002-04-25 20:17:29 +00001736
sewardj5905fae2002-04-26 13:25:00 +00001737strong_alias(__pthread_mutex_lock, pthread_mutex_lock)
1738strong_alias(__pthread_mutex_trylock, pthread_mutex_trylock)
1739strong_alias(__pthread_mutex_unlock, pthread_mutex_unlock)
1740strong_alias(__pthread_mutexattr_init, pthread_mutexattr_init)
1741 weak_alias(__pthread_mutexattr_settype, pthread_mutexattr_settype)
1742strong_alias(__pthread_mutex_init, pthread_mutex_init)
1743strong_alias(__pthread_mutexattr_destroy, pthread_mutexattr_destroy)
1744strong_alias(__pthread_mutex_destroy, pthread_mutex_destroy)
1745strong_alias(__pthread_once, pthread_once)
1746strong_alias(__pthread_atfork, pthread_atfork)
1747strong_alias(__pthread_key_create, pthread_key_create)
1748strong_alias(__pthread_getspecific, pthread_getspecific)
1749strong_alias(__pthread_setspecific, pthread_setspecific)
1750
sewardjd529a442002-05-04 19:49:21 +00001751#ifndef GLIBC_2_1
sewardj3b13f0e2002-04-25 20:17:29 +00001752strong_alias(sigaction, __sigaction)
sewardjd529a442002-05-04 19:49:21 +00001753#endif
1754
sewardj5905fae2002-04-26 13:25:00 +00001755strong_alias(close, __close)
sewardj3b13f0e2002-04-25 20:17:29 +00001756strong_alias(fcntl, __fcntl)
sewardj5905fae2002-04-26 13:25:00 +00001757strong_alias(lseek, __lseek)
1758strong_alias(open, __open)
1759strong_alias(open64, __open64)
sewardj5905fae2002-04-26 13:25:00 +00001760strong_alias(read, __read)
1761strong_alias(wait, __wait)
1762strong_alias(write, __write)
sewardj3b13f0e2002-04-25 20:17:29 +00001763strong_alias(connect, __connect)
sewardj5905fae2002-04-26 13:25:00 +00001764strong_alias(send, __send)
1765
sewardj726c4122002-05-16 23:39:10 +00001766weak_alias (__pread64, pread64)
sewardja18e2102002-05-18 10:43:22 +00001767weak_alias (__pwrite64, pwrite64)
sewardj5905fae2002-04-26 13:25:00 +00001768weak_alias(__fork, fork)
sewardj7f6456d2002-05-21 00:51:21 +00001769
sewardj5905fae2002-04-26 13:25:00 +00001770
sewardj3b13f0e2002-04-25 20:17:29 +00001771
1772/*--------------------------------------------------*/
1773
sewardj5716dbb2002-04-26 03:28:18 +00001774int
1775pthread_rwlock_rdlock (void* /* pthread_rwlock_t* */ rwlock)
1776{
sewardj436e0582002-04-26 14:31:40 +00001777 static int moans = N_MOANS;
1778 if (moans-- > 0)
1779 kludged("pthread_rwlock_rdlock");
sewardj5716dbb2002-04-26 03:28:18 +00001780 return 0;
1781}
1782
sewardj5905fae2002-04-26 13:25:00 +00001783weak_alias(pthread_rwlock_rdlock, __pthread_rwlock_rdlock)
sewardj5716dbb2002-04-26 03:28:18 +00001784
1785
1786int
1787pthread_rwlock_unlock (void* /* pthread_rwlock_t* */ rwlock)
1788{
sewardj436e0582002-04-26 14:31:40 +00001789 static int moans = N_MOANS;
1790 if (moans-- > 0)
1791 kludged("pthread_rwlock_unlock");
sewardj5716dbb2002-04-26 03:28:18 +00001792 return 0;
1793}
1794
sewardj5905fae2002-04-26 13:25:00 +00001795weak_alias(pthread_rwlock_unlock, __pthread_rwlock_unlock)
sewardj5716dbb2002-04-26 03:28:18 +00001796
1797
sewardj060b04f2002-04-26 21:01:13 +00001798int
1799pthread_rwlock_wrlock (void* /* pthread_rwlock_t* */ rwlock)
1800{
1801 static int moans = N_MOANS;
1802 if (moans-- > 0)
1803 kludged("pthread_rwlock_wrlock");
1804 return 0;
1805}
1806
sewardj262b0292002-05-01 00:03:16 +00001807weak_alias(pthread_rwlock_wrlock, __pthread_rwlock_wrlock)
sewardj060b04f2002-04-26 21:01:13 +00001808
1809
sewardj3b13f0e2002-04-25 20:17:29 +00001810/* I've no idea what these are, but they get called quite a lot.
1811 Anybody know? */
1812
1813#undef _IO_flockfile
1814void _IO_flockfile ( _IO_FILE * file )
1815{
sewardj853f55d2002-04-26 00:27:53 +00001816 pthread_mutex_lock(file->_lock);
sewardj3b13f0e2002-04-25 20:17:29 +00001817}
sewardj5905fae2002-04-26 13:25:00 +00001818weak_alias(_IO_flockfile, flockfile);
1819
sewardj3b13f0e2002-04-25 20:17:29 +00001820
1821#undef _IO_funlockfile
1822void _IO_funlockfile ( _IO_FILE * file )
1823{
sewardj853f55d2002-04-26 00:27:53 +00001824 pthread_mutex_unlock(file->_lock);
sewardj3b13f0e2002-04-25 20:17:29 +00001825}
sewardj5905fae2002-04-26 13:25:00 +00001826weak_alias(_IO_funlockfile, funlockfile);
1827
sewardj3b13f0e2002-04-25 20:17:29 +00001828
1829void _pthread_cleanup_push_defer ( void )
1830{
sewardj439d45e2002-05-03 20:43:10 +00001831 static int moans = N_MOANS;
1832 if (moans-- > 0)
1833 ignored("_pthread_cleanup_push_defer");
sewardj3b13f0e2002-04-25 20:17:29 +00001834}
1835
1836void _pthread_cleanup_pop_restore ( void )
1837{
sewardj439d45e2002-05-03 20:43:10 +00001838 static int moans = N_MOANS;
1839 if (moans-- > 0)
1840 ignored("_pthread_cleanup_pop_restore");
sewardj3b13f0e2002-04-25 20:17:29 +00001841}
sewardjd4f2c712002-04-30 10:20:10 +00001842
sewardj60e38422002-05-08 14:08:22 +00001843/*--------*/
1844void _pthread_cleanup_push (struct _pthread_cleanup_buffer *__buffer,
1845 void (*__routine) (void *),
1846 void *__arg)
1847{
1848 static int moans = N_MOANS;
1849 if (moans-- > 0)
1850 ignored("_pthread_cleanup_push");
1851}
1852
1853void _pthread_cleanup_pop (struct _pthread_cleanup_buffer *__buffer,
1854 int __execute)
1855{
1856 static int moans = N_MOANS;
1857 if (moans-- > 0) {
1858 if (__execute)
1859 ignored("_pthread_cleanup_pop-EXECUTE");
1860 else
1861 ignored("_pthread_cleanup_pop-NO-EXECUTE");
1862 }
1863}
1864
sewardjd4f2c712002-04-30 10:20:10 +00001865
1866/* This doesn't seem to be needed to simulate libpthread.so's external
1867 interface, but many people complain about its absence. */
1868
1869strong_alias(__pthread_mutexattr_settype, __pthread_mutexattr_setkind_np)
1870weak_alias(__pthread_mutexattr_setkind_np, pthread_mutexattr_setkind_np)
sewardj439d45e2002-05-03 20:43:10 +00001871
1872
1873/*--------------------------------------------------------------------*/
1874/*--- end vg_libpthread.c ---*/
1875/*--------------------------------------------------------------------*/