blob: 46d1c65a7949188e2c0faef47c58ff44d4b22212 [file] [log] [blame]
sewardje663cb92002-04-12 10:26:32 +00001
sewardj439d45e2002-05-03 20:43:10 +00002/*--------------------------------------------------------------------*/
3/*--- A replacement for the standard libpthread.so. ---*/
4/*--- vg_libpthread.c ---*/
5/*--------------------------------------------------------------------*/
6
7/*
8 This file is part of Valgrind, an x86 protected-mode emulator
9 designed for debugging and profiling binaries on x86-Unixes.
10
11 Copyright (C) 2000-2002 Julian Seward
12 jseward@acm.org
13
14 This program is free software; you can redistribute it and/or
15 modify it under the terms of the GNU General Public License as
16 published by the Free Software Foundation; either version 2 of the
17 License, or (at your option) any later version.
18
19 This program is distributed in the hope that it will be useful, but
20 WITHOUT ANY WARRANTY; without even the implied warranty of
21 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
22 General Public License for more details.
23
24 You should have received a copy of the GNU General Public License
25 along with this program; if not, write to the Free Software
26 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
27 02111-1307, USA.
28
29 The GNU General Public License is contained in the file LICENSE.
30*/
31
32/* ALL THIS CODE RUNS ON THE SIMULATED CPU.
33
34 This is a replacement for the standard libpthread.so. It is loaded
sewardje663cb92002-04-12 10:26:32 +000035 as part of the client's image (if required) and directs pthread
36 calls through to Valgrind's request mechanism.
37
38 A couple of caveats.
39
40 1. Since it's a binary-compatible replacement for an existing library,
41 we must take care to used exactly the same data layouts, etc, as
42 the standard pthread.so does.
43
44 2. Since this runs as part of the client, there are no specific
45 restrictions on what headers etc we can include, so long as
46 this libpthread.so does not end up having dependencies on .so's
47 which the real one doesn't.
48
49 Later ... it appears we cannot call file-related stuff in libc here,
50 perhaps fair enough. Be careful what you call from here. Even exit()
51 doesn't work (gives infinite recursion and then stack overflow); hence
52 myexit(). Also fprintf doesn't seem safe.
53*/
54
55#include "valgrind.h" /* For the request-passing mechanism */
56#include "vg_include.h" /* For the VG_USERREQ__* constants */
57
sewardje663cb92002-04-12 10:26:32 +000058#include <unistd.h>
59#include <string.h>
sewardj2a1dcce2002-04-22 12:45:25 +000060#ifdef GLIBC_2_1
61#include <sys/time.h>
62#endif
sewardje663cb92002-04-12 10:26:32 +000063
64/* ---------------------------------------------------------------------
65 Helpers. We have to be pretty self-sufficient.
66 ------------------------------------------------------------------ */
67
sewardj436e0582002-04-26 14:31:40 +000068/* Number of times any given error message is printed. */
69#define N_MOANS 3
70
sewardj45b4b372002-04-16 22:50:32 +000071/* Extract from Valgrind the value of VG_(clo_trace_pthread_level).
72 Returns 0 (none) if not running on Valgrind. */
73static
74int get_pt_trace_level ( void )
75{
76 int res;
77 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
78 VG_USERREQ__GET_PTHREAD_TRACE_LEVEL,
79 0, 0, 0, 0);
80 return res;
81}
82
83
sewardje663cb92002-04-12 10:26:32 +000084static
85void myexit ( int arg )
86{
sewardj45b4b372002-04-16 22:50:32 +000087 int __res;
sewardje663cb92002-04-12 10:26:32 +000088 __asm__ volatile ("movl %%ecx, %%ebx ; int $0x80"
89 : "=a" (__res)
90 : "0" (__NR_exit),
91 "c" (arg) );
sewardj45b4b372002-04-16 22:50:32 +000092 /* We don't bother to mention the fact that this asm trashes %ebx,
93 since it won't return. If you ever do let it return ... fix
94 this! */
sewardje663cb92002-04-12 10:26:32 +000095}
96
97
sewardj68b2dd92002-05-10 21:03:56 +000098/* We need this guy -- it's in valgrind.so. */
99extern void VG_(startup) ( void );
100
101
102/* Just start up Valgrind if it's not already going. VG_(startup)()
103 detects and ignores second and subsequent calls. */
sewardj604ec3c2002-04-18 22:38:41 +0000104static __inline__
sewardje663cb92002-04-12 10:26:32 +0000105void ensure_valgrind ( char* caller )
106{
sewardj68b2dd92002-05-10 21:03:56 +0000107 VG_(startup)();
sewardje663cb92002-04-12 10:26:32 +0000108}
109
sewardjbea1caa2002-05-10 23:20:58 +0000110/* While we're at it ... hook our own startup function into this
111 game. */
112__asm__ (
113 ".section .init\n"
114 "\tcall vgPlain_startup"
115);
116
sewardje663cb92002-04-12 10:26:32 +0000117
118static
sewardj3b5d8862002-04-20 13:53:23 +0000119__attribute__((noreturn))
sewardje663cb92002-04-12 10:26:32 +0000120void barf ( char* str )
121{
122 char buf[100];
123 buf[0] = 0;
sewardj439d45e2002-05-03 20:43:10 +0000124 strcat(buf, "\nvalgrind's libpthread.so: ");
sewardje663cb92002-04-12 10:26:32 +0000125 strcat(buf, str);
126 strcat(buf, "\n\n");
127 write(2, buf, strlen(buf));
128 myexit(1);
sewardj3b5d8862002-04-20 13:53:23 +0000129 /* We have to persuade gcc into believing this doesn't return. */
130 while (1) { };
sewardje663cb92002-04-12 10:26:32 +0000131}
132
133
sewardj2a3d28c2002-04-14 13:27:00 +0000134static void ignored ( char* msg )
135{
sewardj436e0582002-04-26 14:31:40 +0000136 if (get_pt_trace_level() >= 0) {
sewardj439d45e2002-05-03 20:43:10 +0000137 char* ig = "valgrind's libpthread.so: IGNORED call to: ";
sewardj45b4b372002-04-16 22:50:32 +0000138 write(2, ig, strlen(ig));
139 write(2, msg, strlen(msg));
140 ig = "\n";
141 write(2, ig, strlen(ig));
142 }
sewardj2a3d28c2002-04-14 13:27:00 +0000143}
144
sewardj30671ff2002-04-21 00:13:57 +0000145static void kludged ( char* msg )
146{
sewardj436e0582002-04-26 14:31:40 +0000147 if (get_pt_trace_level() >= 0) {
sewardj439d45e2002-05-03 20:43:10 +0000148 char* ig = "valgrind's libpthread.so: KLUDGED call to: ";
149 write(2, ig, strlen(ig));
150 write(2, msg, strlen(msg));
151 ig = "\n";
152 write(2, ig, strlen(ig));
153 }
154}
155
156static void not_inside ( char* msg )
157{
sewardj68b2dd92002-05-10 21:03:56 +0000158 VG_(startup)();
sewardj30671ff2002-04-21 00:13:57 +0000159}
160
sewardj3b13f0e2002-04-25 20:17:29 +0000161void vgPlain_unimp ( char* what )
162{
sewardj439d45e2002-05-03 20:43:10 +0000163 char* ig = "valgrind's libpthread.so: UNIMPLEMENTED FUNCTION: ";
sewardj3b13f0e2002-04-25 20:17:29 +0000164 write(2, ig, strlen(ig));
165 write(2, what, strlen(what));
166 ig = "\n";
167 write(2, ig, strlen(ig));
168 barf("Please report this bug to me at: jseward@acm.org");
169}
170
sewardje663cb92002-04-12 10:26:32 +0000171
172/* ---------------------------------------------------------------------
173 Pass pthread_ calls to Valgrind's request mechanism.
174 ------------------------------------------------------------------ */
175
sewardjf8f819e2002-04-17 23:21:37 +0000176#include <pthread.h>
177#include <stdio.h>
178#include <errno.h>
sewardj5f07b662002-04-23 16:52:51 +0000179#include <assert.h>
180#include <sys/time.h> /* gettimeofday */
sewardjf8f819e2002-04-17 23:21:37 +0000181
182/* ---------------------------------------------------
183 THREAD ATTRIBUTES
184 ------------------------------------------------ */
185
sewardj6af4b5d2002-04-16 04:40:49 +0000186int pthread_attr_init(pthread_attr_t *attr)
187{
sewardj436e0582002-04-26 14:31:40 +0000188 static int moans = N_MOANS;
189 if (moans-- > 0)
190 ignored("pthread_attr_init");
sewardj6af4b5d2002-04-16 04:40:49 +0000191 return 0;
192}
193
194int pthread_attr_setdetachstate(pthread_attr_t *attr, int detachstate)
195{
sewardj436e0582002-04-26 14:31:40 +0000196 static int moans = N_MOANS;
197 if (moans-- > 0)
198 ignored("pthread_attr_setdetachstate");
sewardj6af4b5d2002-04-16 04:40:49 +0000199 return 0;
200}
201
sewardj30671ff2002-04-21 00:13:57 +0000202int pthread_attr_setinheritsched(pthread_attr_t *attr, int inherit)
203{
sewardj436e0582002-04-26 14:31:40 +0000204 static int moans = N_MOANS;
205 if (moans-- > 0)
206 ignored("pthread_attr_setinheritsched");
sewardj30671ff2002-04-21 00:13:57 +0000207 return 0;
208}
sewardj6af4b5d2002-04-16 04:40:49 +0000209
sewardj0286dd52002-05-16 20:51:15 +0000210__attribute__((weak))
211int pthread_attr_setstacksize (pthread_attr_t *__attr,
212 size_t __stacksize)
213{
sewardja18e2102002-05-18 10:43:22 +0000214 size_t limit;
sewardj0286dd52002-05-16 20:51:15 +0000215 ensure_valgrind("pthread_attr_setstacksize");
sewardja18e2102002-05-18 10:43:22 +0000216 limit = VG_PTHREAD_STACK_SIZE - VG_AR_CLIENT_STACKBASE_REDZONE_SZB
217 - 1000; /* paranoia */
218 if (__stacksize < limit)
sewardj0286dd52002-05-16 20:51:15 +0000219 return 0;
220 barf("pthread_attr_setstacksize: "
221 "requested size >= VG_PTHREAD_STACK_SIZE\n "
222 "edit vg_include.h and rebuild.");
223}
224
225
sewardj30671ff2002-04-21 00:13:57 +0000226/* This is completely bogus. */
227int pthread_attr_getschedparam(const pthread_attr_t *attr,
228 struct sched_param *param)
229{
sewardj436e0582002-04-26 14:31:40 +0000230 static int moans = N_MOANS;
231 if (moans-- > 0)
232 kludged("pthread_attr_getschedparam");
sewardj72d58482002-04-24 02:20:20 +0000233# ifdef GLIBC_2_1
234 if (param) param->sched_priority = 0; /* who knows */
235# else
sewardj30671ff2002-04-21 00:13:57 +0000236 if (param) param->__sched_priority = 0; /* who knows */
sewardj72d58482002-04-24 02:20:20 +0000237# endif
sewardj30671ff2002-04-21 00:13:57 +0000238 return 0;
239}
240
241int pthread_attr_setschedparam(pthread_attr_t *attr,
242 const struct sched_param *param)
243{
sewardj436e0582002-04-26 14:31:40 +0000244 static int moans = N_MOANS;
245 if (moans-- > 0)
246 ignored("pthread_attr_setschedparam");
sewardj30671ff2002-04-21 00:13:57 +0000247 return 0;
248}
249
250int pthread_attr_destroy(pthread_attr_t *attr)
251{
sewardj436e0582002-04-26 14:31:40 +0000252 static int moans = N_MOANS;
253 if (moans-- > 0)
254 ignored("pthread_attr_destroy");
sewardj30671ff2002-04-21 00:13:57 +0000255 return 0;
256}
sewardjf8f819e2002-04-17 23:21:37 +0000257
258/* ---------------------------------------------------
259 THREADs
260 ------------------------------------------------ */
261
sewardjff42d1d2002-05-22 13:17:31 +0000262__attribute__((weak))
263int pthread_yield ( void )
264{
265 int res;
266 ensure_valgrind("pthread_yield");
267 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
268 VG_USERREQ__PTHREAD_YIELD, 0, 0, 0, 0);
269 return 0;
270}
271
272
sewardj6072c362002-04-19 14:40:57 +0000273int pthread_equal(pthread_t thread1, pthread_t thread2)
274{
275 return thread1 == thread2 ? 1 : 0;
276}
277
278
sewardje663cb92002-04-12 10:26:32 +0000279int
280pthread_create (pthread_t *__restrict __thread,
281 __const pthread_attr_t *__restrict __attr,
282 void *(*__start_routine) (void *),
283 void *__restrict __arg)
284{
285 int res;
286 ensure_valgrind("pthread_create");
287 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
288 VG_USERREQ__PTHREAD_CREATE,
289 __thread, __attr, __start_routine, __arg);
290 return res;
291}
292
293
294
295int
296pthread_join (pthread_t __th, void **__thread_return)
297{
298 int res;
299 ensure_valgrind("pthread_join");
300 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
301 VG_USERREQ__PTHREAD_JOIN,
302 __th, __thread_return, 0, 0);
303 return res;
304}
305
306
sewardj3b5d8862002-04-20 13:53:23 +0000307void pthread_exit(void *retval)
308{
309 int res;
310 ensure_valgrind("pthread_exit");
311 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
312 VG_USERREQ__PTHREAD_EXIT,
313 retval, 0, 0, 0);
314 /* Doesn't return! */
315 /* However, we have to fool gcc into knowing that. */
316 barf("pthread_exit: still alive after request?!");
317}
318
sewardje663cb92002-04-12 10:26:32 +0000319
sewardj3b13f0e2002-04-25 20:17:29 +0000320pthread_t pthread_self(void)
sewardje663cb92002-04-12 10:26:32 +0000321{
322 int tid;
sewardj3b13f0e2002-04-25 20:17:29 +0000323 ensure_valgrind("pthread_self");
sewardj439d45e2002-05-03 20:43:10 +0000324 VALGRIND_MAGIC_SEQUENCE(tid, 1 /* default */,
sewardje663cb92002-04-12 10:26:32 +0000325 VG_USERREQ__PTHREAD_GET_THREADID,
326 0, 0, 0, 0);
sewardj439d45e2002-05-03 20:43:10 +0000327 if (tid < 1 || tid >= VG_N_THREADS)
sewardj3b13f0e2002-04-25 20:17:29 +0000328 barf("pthread_self: invalid ThreadId");
329 return tid;
sewardje663cb92002-04-12 10:26:32 +0000330}
331
332
sewardj853f55d2002-04-26 00:27:53 +0000333int pthread_detach(pthread_t th)
334{
sewardj436e0582002-04-26 14:31:40 +0000335 static int moans = N_MOANS;
336 if (moans-- > 0)
337 ignored("pthread_detach");
sewardj853f55d2002-04-26 00:27:53 +0000338 return 0;
339}
340
341
sewardjf8f819e2002-04-17 23:21:37 +0000342/* ---------------------------------------------------
343 MUTEX ATTRIBUTES
344 ------------------------------------------------ */
345
sewardj5905fae2002-04-26 13:25:00 +0000346int __pthread_mutexattr_init(pthread_mutexattr_t *attr)
sewardje663cb92002-04-12 10:26:32 +0000347{
sewardjf8f819e2002-04-17 23:21:37 +0000348 attr->__mutexkind = PTHREAD_MUTEX_ERRORCHECK_NP;
sewardj8937c812002-04-12 20:12:20 +0000349 return 0;
sewardje663cb92002-04-12 10:26:32 +0000350}
351
sewardj5905fae2002-04-26 13:25:00 +0000352int __pthread_mutexattr_settype(pthread_mutexattr_t *attr, int type)
sewardjf8f819e2002-04-17 23:21:37 +0000353{
354 switch (type) {
sewardj3b13f0e2002-04-25 20:17:29 +0000355# ifndef GLIBC_2_1
sewardjf8f819e2002-04-17 23:21:37 +0000356 case PTHREAD_MUTEX_TIMED_NP:
sewardj2a1dcce2002-04-22 12:45:25 +0000357 case PTHREAD_MUTEX_ADAPTIVE_NP:
sewardj3b13f0e2002-04-25 20:17:29 +0000358# endif
sewardja1679dd2002-05-10 22:31:40 +0000359# ifdef GLIBC_2_1
sewardj68b2dd92002-05-10 21:03:56 +0000360 case PTHREAD_MUTEX_FAST_NP:
sewardja1679dd2002-05-10 22:31:40 +0000361# endif
sewardjf8f819e2002-04-17 23:21:37 +0000362 case PTHREAD_MUTEX_RECURSIVE_NP:
363 case PTHREAD_MUTEX_ERRORCHECK_NP:
sewardjf8f819e2002-04-17 23:21:37 +0000364 attr->__mutexkind = type;
365 return 0;
366 default:
367 return EINVAL;
368 }
369}
370
sewardj5905fae2002-04-26 13:25:00 +0000371int __pthread_mutexattr_destroy(pthread_mutexattr_t *attr)
sewardjf8f819e2002-04-17 23:21:37 +0000372{
373 return 0;
374}
375
376
377/* ---------------------------------------------------
378 MUTEXes
379 ------------------------------------------------ */
380
sewardj5905fae2002-04-26 13:25:00 +0000381int __pthread_mutex_init(pthread_mutex_t *mutex,
382 const pthread_mutexattr_t *mutexattr)
sewardje663cb92002-04-12 10:26:32 +0000383{
sewardj604ec3c2002-04-18 22:38:41 +0000384 mutex->__m_count = 0;
385 mutex->__m_owner = (_pthread_descr)VG_INVALID_THREADID;
386 mutex->__m_kind = PTHREAD_MUTEX_ERRORCHECK_NP;
387 if (mutexattr)
388 mutex->__m_kind = mutexattr->__mutexkind;
389 return 0;
sewardje663cb92002-04-12 10:26:32 +0000390}
391
sewardj439d45e2002-05-03 20:43:10 +0000392
sewardj5905fae2002-04-26 13:25:00 +0000393int __pthread_mutex_lock(pthread_mutex_t *mutex)
sewardje663cb92002-04-12 10:26:32 +0000394{
395 int res;
sewardj436e0582002-04-26 14:31:40 +0000396 static int moans = N_MOANS;
sewardj439d45e2002-05-03 20:43:10 +0000397 if (RUNNING_ON_VALGRIND) {
sewardje663cb92002-04-12 10:26:32 +0000398 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
399 VG_USERREQ__PTHREAD_MUTEX_LOCK,
400 mutex, 0, 0, 0);
401 return res;
sewardj439d45e2002-05-03 20:43:10 +0000402 } else {
403 if (moans-- > 0)
404 not_inside("pthread_mutex_lock");
405 return 0; /* success */
sewardje663cb92002-04-12 10:26:32 +0000406 }
407}
408
sewardj439d45e2002-05-03 20:43:10 +0000409
sewardj5905fae2002-04-26 13:25:00 +0000410int __pthread_mutex_trylock(pthread_mutex_t *mutex)
sewardj30671ff2002-04-21 00:13:57 +0000411{
412 int res;
sewardj436e0582002-04-26 14:31:40 +0000413 static int moans = N_MOANS;
sewardj439d45e2002-05-03 20:43:10 +0000414 if (RUNNING_ON_VALGRIND) {
sewardj30671ff2002-04-21 00:13:57 +0000415 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
416 VG_USERREQ__PTHREAD_MUTEX_TRYLOCK,
417 mutex, 0, 0, 0);
418 return res;
sewardj439d45e2002-05-03 20:43:10 +0000419 } else {
420 if (moans-- > 0)
421 not_inside("pthread_mutex_trylock");
422 return 0;
sewardj30671ff2002-04-21 00:13:57 +0000423 }
424}
425
sewardj439d45e2002-05-03 20:43:10 +0000426
sewardj5905fae2002-04-26 13:25:00 +0000427int __pthread_mutex_unlock(pthread_mutex_t *mutex)
sewardje663cb92002-04-12 10:26:32 +0000428{
429 int res;
sewardj436e0582002-04-26 14:31:40 +0000430 static int moans = N_MOANS;
sewardj439d45e2002-05-03 20:43:10 +0000431 if (RUNNING_ON_VALGRIND) {
sewardje663cb92002-04-12 10:26:32 +0000432 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
433 VG_USERREQ__PTHREAD_MUTEX_UNLOCK,
434 mutex, 0, 0, 0);
435 return res;
sewardj439d45e2002-05-03 20:43:10 +0000436 } else {
437 if (moans-- > 0)
438 not_inside("pthread_mutex_unlock");
439 return 0;
sewardje663cb92002-04-12 10:26:32 +0000440 }
441}
442
sewardj439d45e2002-05-03 20:43:10 +0000443
sewardj5905fae2002-04-26 13:25:00 +0000444int __pthread_mutex_destroy(pthread_mutex_t *mutex)
sewardje663cb92002-04-12 10:26:32 +0000445{
sewardj604ec3c2002-04-18 22:38:41 +0000446 /* Valgrind doesn't hold any resources on behalf of the mutex, so no
447 need to involve it. */
448 if (mutex->__m_count > 0)
449 return EBUSY;
sewardj6072c362002-04-19 14:40:57 +0000450 mutex->__m_count = 0;
451 mutex->__m_owner = (_pthread_descr)VG_INVALID_THREADID;
452 mutex->__m_kind = PTHREAD_MUTEX_ERRORCHECK_NP;
sewardj604ec3c2002-04-18 22:38:41 +0000453 return 0;
sewardje663cb92002-04-12 10:26:32 +0000454}
455
456
sewardjf8f819e2002-04-17 23:21:37 +0000457/* ---------------------------------------------------
sewardj6072c362002-04-19 14:40:57 +0000458 CONDITION VARIABLES
459 ------------------------------------------------ */
460
461/* LinuxThreads supports no attributes for conditions. Hence ... */
462
463int pthread_condattr_init(pthread_condattr_t *attr)
464{
465 return 0;
466}
467
sewardj0738a592002-04-20 13:59:33 +0000468int pthread_condattr_destroy(pthread_condattr_t *attr)
469{
470 return 0;
471}
sewardj6072c362002-04-19 14:40:57 +0000472
473int pthread_cond_init( pthread_cond_t *cond,
474 const pthread_condattr_t *cond_attr)
475{
476 cond->__c_waiting = (_pthread_descr)VG_INVALID_THREADID;
477 return 0;
478}
479
sewardjf854f472002-04-21 12:19:41 +0000480int pthread_cond_destroy(pthread_cond_t *cond)
481{
482 /* should check that no threads are waiting on this CV */
sewardj436e0582002-04-26 14:31:40 +0000483 static int moans = N_MOANS;
484 if (moans-- > 0)
485 kludged("pthread_cond_destroy");
sewardjf854f472002-04-21 12:19:41 +0000486 return 0;
487}
sewardj6072c362002-04-19 14:40:57 +0000488
489/* ---------------------------------------------------
490 SCHEDULING
491 ------------------------------------------------ */
492
493/* This is completely bogus. */
494int pthread_getschedparam(pthread_t target_thread,
495 int *policy,
496 struct sched_param *param)
497{
sewardj436e0582002-04-26 14:31:40 +0000498 static int moans = N_MOANS;
499 if (moans-- > 0)
500 kludged("pthread_getschedparam");
sewardj6072c362002-04-19 14:40:57 +0000501 if (policy) *policy = SCHED_OTHER;
sewardj2a1dcce2002-04-22 12:45:25 +0000502# ifdef GLIBC_2_1
503 if (param) param->sched_priority = 0; /* who knows */
504# else
sewardj6072c362002-04-19 14:40:57 +0000505 if (param) param->__sched_priority = 0; /* who knows */
sewardj2a1dcce2002-04-22 12:45:25 +0000506# endif
sewardj6072c362002-04-19 14:40:57 +0000507 return 0;
508}
509
510int pthread_setschedparam(pthread_t target_thread,
511 int policy,
512 const struct sched_param *param)
513{
sewardj436e0582002-04-26 14:31:40 +0000514 static int moans = N_MOANS;
515 if (moans-- > 0)
516 ignored("pthread_setschedparam");
sewardj6072c362002-04-19 14:40:57 +0000517 return 0;
518}
519
sewardj3b5d8862002-04-20 13:53:23 +0000520int pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex)
521{
522 int res;
523 ensure_valgrind("pthread_cond_wait");
524 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
525 VG_USERREQ__PTHREAD_COND_WAIT,
526 cond, mutex, 0, 0);
527 return res;
528}
529
sewardj5f07b662002-04-23 16:52:51 +0000530int pthread_cond_timedwait ( pthread_cond_t *cond,
531 pthread_mutex_t *mutex,
532 const struct timespec *abstime )
533{
534 int res;
535 unsigned int ms_now, ms_end;
536 struct timeval timeval_now;
537 unsigned long long int ull_ms_now_after_1970;
538 unsigned long long int ull_ms_end_after_1970;
539
540 ensure_valgrind("pthread_cond_timedwait");
541 VALGRIND_MAGIC_SEQUENCE(ms_now, 0xFFFFFFFF /* default */,
542 VG_USERREQ__READ_MILLISECOND_TIMER,
543 0, 0, 0, 0);
544 assert(ms_now != 0xFFFFFFFF);
545 res = gettimeofday(&timeval_now, NULL);
546 assert(res == 0);
547
548 ull_ms_now_after_1970
549 = 1000ULL * ((unsigned long long int)(timeval_now.tv_sec))
550 + ((unsigned long long int)(timeval_now.tv_usec / 1000000));
551 ull_ms_end_after_1970
552 = 1000ULL * ((unsigned long long int)(abstime->tv_sec))
553 + ((unsigned long long int)(abstime->tv_nsec / 1000000));
554 assert(ull_ms_end_after_1970 >= ull_ms_now_after_1970);
555 ms_end
556 = ms_now + (unsigned int)(ull_ms_end_after_1970 - ull_ms_now_after_1970);
557 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
558 VG_USERREQ__PTHREAD_COND_TIMEDWAIT,
559 cond, mutex, ms_end, 0);
560 return res;
561}
562
563
sewardj3b5d8862002-04-20 13:53:23 +0000564int pthread_cond_signal(pthread_cond_t *cond)
565{
566 int res;
567 ensure_valgrind("pthread_cond_signal");
568 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
569 VG_USERREQ__PTHREAD_COND_SIGNAL,
570 cond, 0, 0, 0);
571 return res;
572}
573
574int pthread_cond_broadcast(pthread_cond_t *cond)
575{
576 int res;
577 ensure_valgrind("pthread_cond_broadcast");
578 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
579 VG_USERREQ__PTHREAD_COND_BROADCAST,
580 cond, 0, 0, 0);
581 return res;
582}
583
sewardj6072c362002-04-19 14:40:57 +0000584
585/* ---------------------------------------------------
sewardjf8f819e2002-04-17 23:21:37 +0000586 CANCELLATION
587 ------------------------------------------------ */
588
sewardj853f55d2002-04-26 00:27:53 +0000589int pthread_setcancelstate(int state, int *oldstate)
590{
sewardj436e0582002-04-26 14:31:40 +0000591 static int moans = N_MOANS;
592 if (moans-- > 0)
593 ignored("pthread_setcancelstate");
sewardj853f55d2002-04-26 00:27:53 +0000594 return 0;
595}
596
sewardje663cb92002-04-12 10:26:32 +0000597int pthread_setcanceltype(int type, int *oldtype)
598{
sewardj436e0582002-04-26 14:31:40 +0000599 static int moans = N_MOANS;
600 if (moans-- > 0)
601 ignored("pthread_setcanceltype");
sewardje663cb92002-04-12 10:26:32 +0000602 return 0;
603}
604
sewardje663cb92002-04-12 10:26:32 +0000605int pthread_cancel(pthread_t thread)
606{
607 int res;
608 ensure_valgrind("pthread_cancel");
609 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
610 VG_USERREQ__PTHREAD_CANCEL,
611 thread, 0, 0, 0);
612 return res;
613}
614
sewardj853f55d2002-04-26 00:27:53 +0000615void pthread_testcancel(void)
616{
617}
618
619/*-------------------*/
620static pthread_mutex_t massacre_mx = PTHREAD_MUTEX_INITIALIZER;
621
622void __pthread_kill_other_threads_np ( void )
623{
624 int i, res, me;
sewardj68b2dd92002-05-10 21:03:56 +0000625 __pthread_mutex_lock(&massacre_mx);
sewardj853f55d2002-04-26 00:27:53 +0000626 me = pthread_self();
627 for (i = 1; i < VG_N_THREADS; i++) {
628 if (i == me) continue;
629 res = pthread_cancel(i);
sewardj436e0582002-04-26 14:31:40 +0000630 if (0 && res == 0)
sewardj853f55d2002-04-26 00:27:53 +0000631 printf("----------- NUKED %d\n", i);
632 }
sewardj68b2dd92002-05-10 21:03:56 +0000633 __pthread_mutex_unlock(&massacre_mx);
sewardj853f55d2002-04-26 00:27:53 +0000634}
635
sewardje663cb92002-04-12 10:26:32 +0000636
sewardjf8f819e2002-04-17 23:21:37 +0000637/* ---------------------------------------------------
sewardjb48e5002002-05-13 00:16:03 +0000638 SIGNALS
639 ------------------------------------------------ */
640
641#include <signal.h>
642
643int pthread_sigmask(int how, const sigset_t *newmask,
644 sigset_t *oldmask)
645{
646 int res;
647
648 /* A bit subtle, because the scheduler expects newmask and oldmask
649 to be vki_sigset_t* rather than sigset_t*, and the two are
650 different. Fortunately the first 64 bits of a sigset_t are
651 exactly a vki_sigset_t, so we just pass the pointers through
652 unmodified. Haaaack!
653
654 Also mash the how value so that the SIG_ constants from glibc
sewardj018f7622002-05-15 21:13:39 +0000655 constants to VKI_ constants, so that the former do not have to
656 be included into vg_scheduler.c. */
sewardjb48e5002002-05-13 00:16:03 +0000657
658 ensure_valgrind("pthread_sigmask");
659
660 switch (how) {
sewardj018f7622002-05-15 21:13:39 +0000661 case SIG_SETMASK: how = VKI_SIG_SETMASK; break;
662 case SIG_BLOCK: how = VKI_SIG_BLOCK; break;
663 case SIG_UNBLOCK: how = VKI_SIG_UNBLOCK; break;
sewardjb48e5002002-05-13 00:16:03 +0000664 default: return EINVAL;
665 }
666
667 /* Crude check */
668 if (newmask == NULL)
669 return EFAULT;
670
671 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
672 VG_USERREQ__PTHREAD_SIGMASK,
673 how, newmask, oldmask, 0);
674
675 /* The scheduler tells us of any memory violations. */
676 return res == 0 ? 0 : EFAULT;
677}
678
679
680int sigwait ( const sigset_t* set, int* sig )
681{
682 int res;
683 ensure_valgrind("sigwait");
684 /* As with pthread_sigmask we deliberately confuse sigset_t with
685 vki_ksigset_t. */
686 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
687 VG_USERREQ__SIGWAIT,
688 set, sig, 0, 0);
689 return res;
690}
691
692
sewardj018f7622002-05-15 21:13:39 +0000693int pthread_kill(pthread_t thread, int signo)
694{
695 int res;
696 ensure_valgrind("pthread_kill");
697 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
698 VG_USERREQ__PTHREAD_KILL,
699 thread, signo, 0, 0);
700 return res;
701}
702
703
sewardj3665ded2002-05-16 16:57:25 +0000704/* Copied verbatim from Linuxthreads */
705/* Redefine raise() to send signal to calling thread only,
706 as per POSIX 1003.1c */
707int raise (int sig)
708{
709 int retcode = pthread_kill(pthread_self(), sig);
710 if (retcode == 0)
711 return 0;
712 else {
713 errno = retcode;
714 return -1;
715 }
716}
717
718
sewardjb48e5002002-05-13 00:16:03 +0000719/* ---------------------------------------------------
sewardjf8f819e2002-04-17 23:21:37 +0000720 THREAD-SPECIFICs
721 ------------------------------------------------ */
sewardj5e5fa512002-04-14 13:13:05 +0000722
sewardj5905fae2002-04-26 13:25:00 +0000723int __pthread_key_create(pthread_key_t *key,
724 void (*destr_function) (void *))
sewardj5e5fa512002-04-14 13:13:05 +0000725{
sewardj5f07b662002-04-23 16:52:51 +0000726 int res;
727 ensure_valgrind("pthread_key_create");
728 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
729 VG_USERREQ__PTHREAD_KEY_CREATE,
730 key, destr_function, 0, 0);
731 return res;
sewardj5e5fa512002-04-14 13:13:05 +0000732}
733
734int pthread_key_delete(pthread_key_t key)
735{
sewardj436e0582002-04-26 14:31:40 +0000736 static int moans = N_MOANS;
737 if (moans-- > 0)
738 ignored("pthread_key_delete");
sewardj5e5fa512002-04-14 13:13:05 +0000739 return 0;
740}
741
sewardj5905fae2002-04-26 13:25:00 +0000742int __pthread_setspecific(pthread_key_t key, const void *pointer)
sewardj5e5fa512002-04-14 13:13:05 +0000743{
sewardj5f07b662002-04-23 16:52:51 +0000744 int res;
745 ensure_valgrind("pthread_setspecific");
746 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
747 VG_USERREQ__PTHREAD_SETSPECIFIC,
748 key, pointer, 0, 0);
749 return res;
sewardj5e5fa512002-04-14 13:13:05 +0000750}
751
sewardj5905fae2002-04-26 13:25:00 +0000752void * __pthread_getspecific(pthread_key_t key)
sewardj5e5fa512002-04-14 13:13:05 +0000753{
sewardj5f07b662002-04-23 16:52:51 +0000754 int res;
755 ensure_valgrind("pthread_getspecific");
756 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
757 VG_USERREQ__PTHREAD_GETSPECIFIC,
758 key, 0 , 0, 0);
759 return (void*)res;
sewardj5e5fa512002-04-14 13:13:05 +0000760}
761
sewardjf8f819e2002-04-17 23:21:37 +0000762
763/* ---------------------------------------------------
sewardj89d3d852002-04-24 19:21:39 +0000764 ONCEry
765 ------------------------------------------------ */
766
767static pthread_mutex_t once_masterlock = PTHREAD_MUTEX_INITIALIZER;
768
769
sewardj5905fae2002-04-26 13:25:00 +0000770int __pthread_once ( pthread_once_t *once_control,
771 void (*init_routine) (void) )
sewardj89d3d852002-04-24 19:21:39 +0000772{
773 int res;
774 ensure_valgrind("pthread_once");
775
sewardj68b2dd92002-05-10 21:03:56 +0000776 res = __pthread_mutex_lock(&once_masterlock);
sewardj89d3d852002-04-24 19:21:39 +0000777
sewardj68b2dd92002-05-10 21:03:56 +0000778 if (res != 0) {
779 printf("res = %d\n",res);
sewardj89d3d852002-04-24 19:21:39 +0000780 barf("pthread_once: Looks like your program's "
781 "init routine calls back to pthread_once() ?!");
sewardj68b2dd92002-05-10 21:03:56 +0000782 }
sewardj89d3d852002-04-24 19:21:39 +0000783
784 if (*once_control == 0) {
785 *once_control = 1;
786 init_routine();
787 }
788
sewardj68b2dd92002-05-10 21:03:56 +0000789 __pthread_mutex_unlock(&once_masterlock);
sewardj89d3d852002-04-24 19:21:39 +0000790
791 return 0;
792}
793
794
795/* ---------------------------------------------------
sewardj853f55d2002-04-26 00:27:53 +0000796 MISC
797 ------------------------------------------------ */
798
sewardj5905fae2002-04-26 13:25:00 +0000799int __pthread_atfork ( void (*prepare)(void),
800 void (*parent)(void),
801 void (*child)(void) )
sewardj853f55d2002-04-26 00:27:53 +0000802{
sewardj436e0582002-04-26 14:31:40 +0000803 static int moans = N_MOANS;
804 if (moans-- > 0)
805 ignored("pthread_atfork");
sewardj853f55d2002-04-26 00:27:53 +0000806 return 0;
807}
808
809
sewardjbb990782002-05-08 02:01:14 +0000810__attribute__((weak))
811void __pthread_initialize ( void )
812{
sewardjbea1caa2002-05-10 23:20:58 +0000813 ensure_valgrind("__pthread_initialize");
sewardjbb990782002-05-08 02:01:14 +0000814}
815
816
sewardj853f55d2002-04-26 00:27:53 +0000817/* ---------------------------------------------------
sewardj3b13f0e2002-04-25 20:17:29 +0000818 LIBRARY-PRIVATE THREAD SPECIFIC STATE
sewardjf8f819e2002-04-17 23:21:37 +0000819 ------------------------------------------------ */
820
sewardj3b13f0e2002-04-25 20:17:29 +0000821#include <resolv.h>
822static int thread_specific_errno[VG_N_THREADS];
823static int thread_specific_h_errno[VG_N_THREADS];
824static struct __res_state
825 thread_specific_res_state[VG_N_THREADS];
sewardjf8f819e2002-04-17 23:21:37 +0000826
sewardj3b13f0e2002-04-25 20:17:29 +0000827int* __errno_location ( void )
sewardjf8f819e2002-04-17 23:21:37 +0000828{
829 int tid;
sewardj3b13f0e2002-04-25 20:17:29 +0000830 /* ensure_valgrind("__errno_location"); */
831 VALGRIND_MAGIC_SEQUENCE(tid, 1 /* default */,
sewardjf8f819e2002-04-17 23:21:37 +0000832 VG_USERREQ__PTHREAD_GET_THREADID,
833 0, 0, 0, 0);
sewardj3b13f0e2002-04-25 20:17:29 +0000834 /* 'cos I'm paranoid ... */
sewardj439d45e2002-05-03 20:43:10 +0000835 if (tid < 1 || tid >= VG_N_THREADS)
sewardj3b13f0e2002-04-25 20:17:29 +0000836 barf("__errno_location: invalid ThreadId");
837 return & thread_specific_errno[tid];
838}
839
840int* __h_errno_location ( void )
841{
842 int tid;
843 /* ensure_valgrind("__h_errno_location"); */
844 VALGRIND_MAGIC_SEQUENCE(tid, 1 /* default */,
845 VG_USERREQ__PTHREAD_GET_THREADID,
846 0, 0, 0, 0);
847 /* 'cos I'm paranoid ... */
sewardj439d45e2002-05-03 20:43:10 +0000848 if (tid < 1 || tid >= VG_N_THREADS)
sewardj3b13f0e2002-04-25 20:17:29 +0000849 barf("__h_errno_location: invalid ThreadId");
850 return & thread_specific_h_errno[tid];
851}
852
853struct __res_state* __res_state ( void )
854{
855 int tid;
856 /* ensure_valgrind("__res_state"); */
857 VALGRIND_MAGIC_SEQUENCE(tid, 1 /* default */,
858 VG_USERREQ__PTHREAD_GET_THREADID,
859 0, 0, 0, 0);
860 /* 'cos I'm paranoid ... */
sewardj439d45e2002-05-03 20:43:10 +0000861 if (tid < 1 || tid >= VG_N_THREADS)
sewardj3b13f0e2002-04-25 20:17:29 +0000862 barf("__res_state: invalid ThreadId");
863 return & thread_specific_res_state[tid];
sewardjf8f819e2002-04-17 23:21:37 +0000864}
865
866
sewardj5716dbb2002-04-26 03:28:18 +0000867/* ---------------------------------------------------
868 LIBC-PRIVATE SPECIFIC DATA
869 ------------------------------------------------ */
870
871/* Relies on assumption that initial private data is NULL. This
872 should be fixed somehow. */
873
874/* The allowable keys (indices) (all 2 of them).
875 From sysdeps/pthread/bits/libc-tsd.h
876*/
sewardj70adeb22002-04-27 01:35:38 +0000877#define N_LIBC_TSD_EXTRA_KEYS 1
878
sewardj5716dbb2002-04-26 03:28:18 +0000879enum __libc_tsd_key_t { _LIBC_TSD_KEY_MALLOC = 0,
880 _LIBC_TSD_KEY_DL_ERROR,
881 _LIBC_TSD_KEY_N };
882
883/* Auto-initialising subsystem. libc_specifics_inited is set
884 after initialisation. libc_specifics_inited_mx guards it. */
885static int libc_specifics_inited = 0;
886static pthread_mutex_t libc_specifics_inited_mx = PTHREAD_MUTEX_INITIALIZER;
887
888/* These are the keys we must initialise the first time. */
sewardj70adeb22002-04-27 01:35:38 +0000889static pthread_key_t libc_specifics_keys[_LIBC_TSD_KEY_N
890 + N_LIBC_TSD_EXTRA_KEYS];
sewardj5716dbb2002-04-26 03:28:18 +0000891
892/* Initialise the keys, if they are not already initialise. */
893static
894void init_libc_tsd_keys ( void )
895{
896 int res, i;
897 pthread_key_t k;
898
899 res = pthread_mutex_lock(&libc_specifics_inited_mx);
900 if (res != 0) barf("init_libc_tsd_keys: lock");
901
902 if (libc_specifics_inited == 0) {
903 /* printf("INIT libc specifics\n"); */
904 libc_specifics_inited = 1;
sewardj70adeb22002-04-27 01:35:38 +0000905 for (i = 0; i < _LIBC_TSD_KEY_N + N_LIBC_TSD_EXTRA_KEYS; i++) {
sewardj5716dbb2002-04-26 03:28:18 +0000906 res = pthread_key_create(&k, NULL);
907 if (res != 0) barf("init_libc_tsd_keys: create");
908 libc_specifics_keys[i] = k;
909 }
910 }
911
912 res = pthread_mutex_unlock(&libc_specifics_inited_mx);
913 if (res != 0) barf("init_libc_tsd_keys: unlock");
914}
915
916
917static int
918libc_internal_tsd_set ( enum __libc_tsd_key_t key,
919 const void * pointer )
920{
sewardj70adeb22002-04-27 01:35:38 +0000921 int res;
922 static int moans = N_MOANS;
sewardj5716dbb2002-04-26 03:28:18 +0000923 /* printf("SET SET SET key %d ptr %p\n", key, pointer); */
sewardj70adeb22002-04-27 01:35:38 +0000924 if (key < _LIBC_TSD_KEY_MALLOC
925 || key >= _LIBC_TSD_KEY_N + N_LIBC_TSD_EXTRA_KEYS)
sewardj5716dbb2002-04-26 03:28:18 +0000926 barf("libc_internal_tsd_set: invalid key");
sewardj70adeb22002-04-27 01:35:38 +0000927 if (key >= _LIBC_TSD_KEY_N && moans-- > 0)
928 fprintf(stderr,
sewardj439d45e2002-05-03 20:43:10 +0000929 "valgrind's libpthread.so: libc_internal_tsd_set: "
930 "dubious key %d\n", key);
sewardj5716dbb2002-04-26 03:28:18 +0000931 init_libc_tsd_keys();
932 res = pthread_setspecific(libc_specifics_keys[key], pointer);
933 if (res != 0) barf("libc_internal_tsd_set: setspecific failed");
934 return 0;
935}
936
937static void *
938libc_internal_tsd_get ( enum __libc_tsd_key_t key )
939{
sewardj70adeb22002-04-27 01:35:38 +0000940 void* v;
941 static int moans = N_MOANS;
sewardj5716dbb2002-04-26 03:28:18 +0000942 /* printf("GET GET GET key %d\n", key); */
sewardj70adeb22002-04-27 01:35:38 +0000943 if (key < _LIBC_TSD_KEY_MALLOC
944 || key >= _LIBC_TSD_KEY_N + N_LIBC_TSD_EXTRA_KEYS)
sewardj5716dbb2002-04-26 03:28:18 +0000945 barf("libc_internal_tsd_get: invalid key");
sewardj70adeb22002-04-27 01:35:38 +0000946 if (key >= _LIBC_TSD_KEY_N && moans-- > 0)
947 fprintf(stderr,
sewardj439d45e2002-05-03 20:43:10 +0000948 "valgrind's libpthread.so: libc_internal_tsd_get: "
949 "dubious key %d\n", key);
sewardj5716dbb2002-04-26 03:28:18 +0000950 init_libc_tsd_keys();
951 v = pthread_getspecific(libc_specifics_keys[key]);
952 /* if (v == NULL) barf("libc_internal_tsd_set: getspecific failed"); */
953 return v;
954}
955
956
957
958
sewardj70adeb22002-04-27 01:35:38 +0000959int (*__libc_internal_tsd_set)
960 (enum __libc_tsd_key_t key, const void * pointer)
961 = libc_internal_tsd_set;
sewardj5716dbb2002-04-26 03:28:18 +0000962
sewardj70adeb22002-04-27 01:35:38 +0000963void* (*__libc_internal_tsd_get)
964 (enum __libc_tsd_key_t key)
965 = libc_internal_tsd_get;
sewardj5716dbb2002-04-26 03:28:18 +0000966
967
sewardje663cb92002-04-12 10:26:32 +0000968/* ---------------------------------------------------------------------
969 These are here (I think) because they are deemed cancellation
970 points by POSIX. For the moment we'll simply pass the call along
971 to the corresponding thread-unaware (?) libc routine.
972 ------------------------------------------------------------------ */
973
sewardje663cb92002-04-12 10:26:32 +0000974#include <stdlib.h>
sewardje663cb92002-04-12 10:26:32 +0000975#include <sys/types.h>
976#include <sys/socket.h>
977
sewardjd529a442002-05-04 19:49:21 +0000978#ifdef GLIBC_2_1
979extern
980int __sigaction
981 (int signum,
982 const struct sigaction *act,
983 struct sigaction *oldact);
984#else
sewardje663cb92002-04-12 10:26:32 +0000985extern
986int __libc_sigaction
987 (int signum,
988 const struct sigaction *act,
989 struct sigaction *oldact);
sewardjd529a442002-05-04 19:49:21 +0000990#endif
sewardje663cb92002-04-12 10:26:32 +0000991int sigaction(int signum,
992 const struct sigaction *act,
993 struct sigaction *oldact)
994{
sewardj2a1dcce2002-04-22 12:45:25 +0000995# ifdef GLIBC_2_1
996 return __sigaction(signum, act, oldact);
997# else
sewardj45b4b372002-04-16 22:50:32 +0000998 return __libc_sigaction(signum, act, oldact);
sewardj2a1dcce2002-04-22 12:45:25 +0000999# endif
sewardje663cb92002-04-12 10:26:32 +00001000}
1001
1002
1003extern
1004int __libc_connect(int sockfd,
1005 const struct sockaddr *serv_addr,
1006 socklen_t addrlen);
sewardj5905fae2002-04-26 13:25:00 +00001007__attribute__((weak))
sewardje663cb92002-04-12 10:26:32 +00001008int connect(int sockfd,
1009 const struct sockaddr *serv_addr,
1010 socklen_t addrlen)
1011{
sewardj45b4b372002-04-16 22:50:32 +00001012 return __libc_connect(sockfd, serv_addr, addrlen);
sewardje663cb92002-04-12 10:26:32 +00001013}
1014
1015
1016extern
1017int __libc_fcntl(int fd, int cmd, long arg);
sewardj5905fae2002-04-26 13:25:00 +00001018__attribute__((weak))
sewardje663cb92002-04-12 10:26:32 +00001019int fcntl(int fd, int cmd, long arg)
1020{
sewardj45b4b372002-04-16 22:50:32 +00001021 return __libc_fcntl(fd, cmd, arg);
sewardje663cb92002-04-12 10:26:32 +00001022}
1023
1024
1025extern
1026ssize_t __libc_write(int fd, const void *buf, size_t count);
sewardj5905fae2002-04-26 13:25:00 +00001027__attribute__((weak))
sewardje663cb92002-04-12 10:26:32 +00001028ssize_t write(int fd, const void *buf, size_t count)
1029{
sewardj45b4b372002-04-16 22:50:32 +00001030 return __libc_write(fd, buf, count);
sewardje663cb92002-04-12 10:26:32 +00001031}
1032
1033
1034extern
1035ssize_t __libc_read(int fd, void *buf, size_t count);
sewardj5905fae2002-04-26 13:25:00 +00001036__attribute__((weak))
sewardje663cb92002-04-12 10:26:32 +00001037ssize_t read(int fd, void *buf, size_t count)
1038{
sewardj45b4b372002-04-16 22:50:32 +00001039 return __libc_read(fd, buf, count);
sewardje663cb92002-04-12 10:26:32 +00001040}
1041
sewardjbe32e452002-04-24 20:29:58 +00001042
1043extern
sewardj853f55d2002-04-26 00:27:53 +00001044int __libc_open64(const char *pathname, int flags, mode_t mode);
sewardj5905fae2002-04-26 13:25:00 +00001045__attribute__((weak))
sewardj853f55d2002-04-26 00:27:53 +00001046int open64(const char *pathname, int flags, mode_t mode)
sewardjbe32e452002-04-24 20:29:58 +00001047{
sewardj853f55d2002-04-26 00:27:53 +00001048 return __libc_open64(pathname, flags, mode);
sewardjbe32e452002-04-24 20:29:58 +00001049}
1050
sewardje663cb92002-04-12 10:26:32 +00001051
1052extern
sewardj853f55d2002-04-26 00:27:53 +00001053int __libc_open(const char *pathname, int flags, mode_t mode);
sewardj5905fae2002-04-26 13:25:00 +00001054__attribute__((weak))
sewardj853f55d2002-04-26 00:27:53 +00001055int open(const char *pathname, int flags, mode_t mode)
sewardje663cb92002-04-12 10:26:32 +00001056{
sewardj853f55d2002-04-26 00:27:53 +00001057 return __libc_open(pathname, flags, mode);
sewardje663cb92002-04-12 10:26:32 +00001058}
1059
1060
1061extern
1062int __libc_close(int fd);
sewardj5905fae2002-04-26 13:25:00 +00001063__attribute__((weak))
sewardje663cb92002-04-12 10:26:32 +00001064int close(int fd)
1065{
sewardj45b4b372002-04-16 22:50:32 +00001066 return __libc_close(fd);
sewardje663cb92002-04-12 10:26:32 +00001067}
1068
1069
1070extern
1071int __libc_accept(int s, struct sockaddr *addr, socklen_t *addrlen);
sewardj5905fae2002-04-26 13:25:00 +00001072__attribute__((weak))
sewardje663cb92002-04-12 10:26:32 +00001073int accept(int s, struct sockaddr *addr, socklen_t *addrlen)
1074{
sewardj45b4b372002-04-16 22:50:32 +00001075 return __libc_accept(s, addr, addrlen);
sewardje663cb92002-04-12 10:26:32 +00001076}
1077
1078
1079extern
1080pid_t __libc_fork(void);
sewardj5905fae2002-04-26 13:25:00 +00001081pid_t __fork(void)
sewardje663cb92002-04-12 10:26:32 +00001082{
sewardj45b4b372002-04-16 22:50:32 +00001083 return __libc_fork();
sewardje663cb92002-04-12 10:26:32 +00001084}
1085
1086
1087extern
1088pid_t __libc_waitpid(pid_t pid, int *status, int options);
sewardj5905fae2002-04-26 13:25:00 +00001089__attribute__((weak))
sewardje663cb92002-04-12 10:26:32 +00001090pid_t waitpid(pid_t pid, int *status, int options)
1091{
sewardj45b4b372002-04-16 22:50:32 +00001092 return __libc_waitpid(pid, status, options);
sewardje663cb92002-04-12 10:26:32 +00001093}
1094
1095
1096extern
1097int __libc_nanosleep(const struct timespec *req, struct timespec *rem);
sewardj5905fae2002-04-26 13:25:00 +00001098__attribute__((weak))
sewardje663cb92002-04-12 10:26:32 +00001099int nanosleep(const struct timespec *req, struct timespec *rem)
1100{
1101 return __libc_nanosleep(req, rem);
1102}
1103
sewardjbe32e452002-04-24 20:29:58 +00001104
sewardje663cb92002-04-12 10:26:32 +00001105extern
1106int __libc_fsync(int fd);
sewardj5905fae2002-04-26 13:25:00 +00001107__attribute__((weak))
sewardje663cb92002-04-12 10:26:32 +00001108int fsync(int fd)
1109{
sewardj45b4b372002-04-16 22:50:32 +00001110 return __libc_fsync(fd);
sewardje663cb92002-04-12 10:26:32 +00001111}
1112
sewardjbe32e452002-04-24 20:29:58 +00001113
sewardj70c75362002-04-13 04:18:32 +00001114extern
1115off_t __libc_lseek(int fildes, off_t offset, int whence);
sewardj5905fae2002-04-26 13:25:00 +00001116__attribute__((weak))
sewardj70c75362002-04-13 04:18:32 +00001117off_t lseek(int fildes, off_t offset, int whence)
1118{
sewardj45b4b372002-04-16 22:50:32 +00001119 return __libc_lseek(fildes, offset, whence);
sewardj70c75362002-04-13 04:18:32 +00001120}
1121
sewardjbe32e452002-04-24 20:29:58 +00001122
1123extern
1124__off64_t __libc_lseek64(int fildes, __off64_t offset, int whence);
sewardj5905fae2002-04-26 13:25:00 +00001125__attribute__((weak))
sewardjbe32e452002-04-24 20:29:58 +00001126__off64_t lseek64(int fildes, __off64_t offset, int whence)
1127{
1128 return __libc_lseek64(fildes, offset, whence);
1129}
1130
1131
sewardj726c4122002-05-16 23:39:10 +00001132extern
1133ssize_t __libc_pread64 (int __fd, void *__buf, size_t __nbytes,
1134 __off64_t __offset);
1135ssize_t __pread64 (int __fd, void *__buf, size_t __nbytes,
1136 __off64_t __offset)
1137{
1138 return __libc_pread64(__fd, __buf, __nbytes, __offset);
1139}
1140
1141
sewardja18e2102002-05-18 10:43:22 +00001142extern
1143ssize_t __libc_pwrite64 (int __fd, const void *__buf, size_t __nbytes,
1144 __off64_t __offset);
1145ssize_t __pwrite64 (int __fd, const void *__buf, size_t __nbytes,
1146 __off64_t __offset)
1147{
1148 return __libc_pwrite64(__fd, __buf, __nbytes, __offset);
1149}
1150
sewardj726c4122002-05-16 23:39:10 +00001151
sewardj39b93b12002-05-18 10:56:27 +00001152extern
1153ssize_t __libc_pwrite(int fd, const void *buf, size_t count, off_t offset);
1154__attribute__((weak))
1155ssize_t pwrite(int fd, const void *buf, size_t count, off_t offset)
1156{
1157 return __libc_pwrite(fd, buf, count, offset);
1158}
1159
1160
1161extern
1162ssize_t __libc_pread(int fd, void *buf, size_t count, off_t offset);
1163__attribute__((weak))
1164ssize_t pread(int fd, void *buf, size_t count, off_t offset)
1165{
1166 return __libc_pread(fd, buf, count, offset);
1167}
1168
1169
sewardj6af4b5d2002-04-16 04:40:49 +00001170extern
1171void __libc_longjmp(jmp_buf env, int val) __attribute((noreturn));
sewardj5905fae2002-04-26 13:25:00 +00001172/* not weak: __attribute__((weak)) */
sewardj6af4b5d2002-04-16 04:40:49 +00001173void longjmp(jmp_buf env, int val)
1174{
1175 __libc_longjmp(env, val);
1176}
1177
sewardjbe32e452002-04-24 20:29:58 +00001178
sewardj6af4b5d2002-04-16 04:40:49 +00001179extern
1180int __libc_send(int s, const void *msg, size_t len, int flags);
sewardj5905fae2002-04-26 13:25:00 +00001181__attribute__((weak))
sewardj6af4b5d2002-04-16 04:40:49 +00001182int send(int s, const void *msg, size_t len, int flags)
1183{
1184 return __libc_send(s, msg, len, flags);
1185}
1186
sewardjbe32e452002-04-24 20:29:58 +00001187
sewardj1e8cdc92002-04-18 11:37:52 +00001188extern
1189int __libc_recv(int s, void *buf, size_t len, int flags);
sewardj5905fae2002-04-26 13:25:00 +00001190__attribute__((weak))
sewardj1e8cdc92002-04-18 11:37:52 +00001191int recv(int s, void *buf, size_t len, int flags)
1192{
1193 return __libc_recv(s, buf, len, flags);
1194}
1195
sewardjbe32e452002-04-24 20:29:58 +00001196
sewardj3665ded2002-05-16 16:57:25 +00001197extern
1198int __libc_sendmsg(int s, const struct msghdr *msg, int flags);
1199__attribute__((weak))
1200int sendmsg(int s, const struct msghdr *msg, int flags)
1201{
1202 return __libc_sendmsg(s, msg, flags);
1203}
1204
1205
sewardj796d6a22002-04-24 02:28:34 +00001206extern
sewardj436e0582002-04-26 14:31:40 +00001207int __libc_recvfrom(int s, void *buf, size_t len, int flags,
1208 struct sockaddr *from, socklen_t *fromlen);
1209__attribute__((weak))
1210int recvfrom(int s, void *buf, size_t len, int flags,
1211 struct sockaddr *from, socklen_t *fromlen)
1212{
1213 return __libc_recvfrom(s, buf, len, flags, from, fromlen);
1214}
1215
1216
1217extern
sewardj796d6a22002-04-24 02:28:34 +00001218int __libc_sendto(int s, const void *msg, size_t len, int flags,
1219 const struct sockaddr *to, socklen_t tolen);
sewardj5905fae2002-04-26 13:25:00 +00001220__attribute__((weak))
sewardj796d6a22002-04-24 02:28:34 +00001221int sendto(int s, const void *msg, size_t len, int flags,
1222 const struct sockaddr *to, socklen_t tolen)
1223{
1224 return __libc_sendto(s, msg, len, flags, to, tolen);
1225}
1226
sewardjbe32e452002-04-24 20:29:58 +00001227
sewardj369b1702002-04-24 13:28:15 +00001228extern
1229int __libc_system(const char* str);
sewardj5905fae2002-04-26 13:25:00 +00001230__attribute__((weak))
sewardj369b1702002-04-24 13:28:15 +00001231int system(const char* str)
1232{
1233 return __libc_system(str);
1234}
1235
sewardjbe32e452002-04-24 20:29:58 +00001236
sewardjab0b1c32002-04-24 19:26:47 +00001237extern
1238pid_t __libc_wait(int *status);
sewardj5905fae2002-04-26 13:25:00 +00001239__attribute__((weak))
sewardjab0b1c32002-04-24 19:26:47 +00001240pid_t wait(int *status)
1241{
1242 return __libc_wait(status);
1243}
1244
sewardj45b4b372002-04-16 22:50:32 +00001245
sewardj5905fae2002-04-26 13:25:00 +00001246
sewardj3b13f0e2002-04-25 20:17:29 +00001247/* ---------------------------------------------------------------------
1248 Nonblocking implementations of select() and poll(). This stuff will
1249 surely rot your mind.
1250 ------------------------------------------------------------------ */
sewardje663cb92002-04-12 10:26:32 +00001251
sewardj08a4c3f2002-04-13 03:45:44 +00001252/*--------------------------------------------------*/
1253
1254#include "vg_kerneliface.h"
1255
1256static
1257__inline__
1258int is_kerror ( int res )
1259{
1260 if (res >= -4095 && res <= -1)
1261 return 1;
1262 else
1263 return 0;
1264}
1265
1266
1267static
1268int my_do_syscall1 ( int syscallno, int arg1 )
1269{
1270 int __res;
1271 __asm__ volatile ("pushl %%ebx; movl %%edx,%%ebx ; int $0x80 ; popl %%ebx"
1272 : "=a" (__res)
1273 : "0" (syscallno),
1274 "d" (arg1) );
1275 return __res;
1276}
1277
1278static
1279int my_do_syscall2 ( int syscallno,
sewardjf854f472002-04-21 12:19:41 +00001280 int arg1, int arg2 )
sewardj08a4c3f2002-04-13 03:45:44 +00001281{
1282 int __res;
1283 __asm__ volatile ("pushl %%ebx; movl %%edx,%%ebx ; int $0x80 ; popl %%ebx"
1284 : "=a" (__res)
1285 : "0" (syscallno),
1286 "d" (arg1),
1287 "c" (arg2) );
1288 return __res;
1289}
1290
1291static
sewardjf854f472002-04-21 12:19:41 +00001292int my_do_syscall3 ( int syscallno,
1293 int arg1, int arg2, int arg3 )
1294{
1295 int __res;
1296 __asm__ volatile ("pushl %%ebx; movl %%esi,%%ebx ; int $0x80 ; popl %%ebx"
1297 : "=a" (__res)
1298 : "0" (syscallno),
1299 "S" (arg1),
1300 "c" (arg2),
1301 "d" (arg3) );
1302 return __res;
1303}
1304
1305static
sewardj08a4c3f2002-04-13 03:45:44 +00001306int do_syscall_select( int n,
1307 vki_fd_set* readfds,
1308 vki_fd_set* writefds,
1309 vki_fd_set* exceptfds,
1310 struct vki_timeval * timeout )
1311{
1312 int res;
1313 int args[5];
1314 args[0] = n;
1315 args[1] = (int)readfds;
1316 args[2] = (int)writefds;
1317 args[3] = (int)exceptfds;
1318 args[4] = (int)timeout;
1319 res = my_do_syscall1(__NR_select, (int)(&(args[0])) );
sewardj02535bc2002-04-21 01:08:26 +00001320 return res;
sewardj08a4c3f2002-04-13 03:45:44 +00001321}
1322
1323
1324/* This is a wrapper round select(), which makes it thread-safe,
1325 meaning that only this thread will block, rather than the entire
1326 process. This wrapper in turn depends on nanosleep() not to block
1327 the entire process, but I think (hope? suspect?) that POSIX
1328 pthreads guarantees that to be the case.
1329
1330 Basic idea is: modify the timeout parameter to select so that it
1331 returns immediately. Poll like this until select returns non-zero,
1332 indicating something interesting happened, or until our time is up.
1333 Space out the polls with nanosleeps of say 20 milliseconds, which
1334 is required to be nonblocking; this allows other threads to run.
sewardj02535bc2002-04-21 01:08:26 +00001335
1336 Assumes:
1337 * (checked via assert) types fd_set and vki_fd_set are identical.
1338 * (checked via assert) types timeval and vki_timeval are identical.
1339 * (unchecked) libc error numbers (EINTR etc) are the negation of the
1340 kernel's error numbers (VKI_EINTR etc).
sewardj08a4c3f2002-04-13 03:45:44 +00001341*/
sewardj08a4c3f2002-04-13 03:45:44 +00001342
sewardj5905fae2002-04-26 13:25:00 +00001343/* __attribute__((weak)) */
sewardj08a4c3f2002-04-13 03:45:44 +00001344int select ( int n,
1345 fd_set *rfds,
1346 fd_set *wfds,
1347 fd_set *xfds,
1348 struct timeval *timeout )
1349{
sewardj5f07b662002-04-23 16:52:51 +00001350 unsigned int ms_now, ms_end;
sewardj08a4c3f2002-04-13 03:45:44 +00001351 int res;
1352 fd_set rfds_copy;
1353 fd_set wfds_copy;
1354 fd_set xfds_copy;
1355 struct vki_timeval t_now;
sewardj08a4c3f2002-04-13 03:45:44 +00001356 struct vki_timeval zero_timeout;
1357 struct vki_timespec nanosleep_interval;
1358
sewardj5f07b662002-04-23 16:52:51 +00001359 /* gcc's complains about ms_end being used uninitialised -- classic
1360 case it can't understand, where ms_end is both defined and used
1361 only if timeout != NULL. Hence ... */
1362 ms_end = 0;
sewardj08a4c3f2002-04-13 03:45:44 +00001363
1364 /* We assume that the kernel and libc data layouts are identical
1365 for the following types. These asserts provide a crude
1366 check. */
1367 if (sizeof(fd_set) != sizeof(vki_fd_set)
1368 || sizeof(struct timeval) != sizeof(struct vki_timeval))
1369 barf("valgrind's hacky non-blocking select(): data sizes error");
1370
sewardj5f07b662002-04-23 16:52:51 +00001371 /* Detect the current time and simultaneously find out if we are
1372 running on Valgrind. */
1373 VALGRIND_MAGIC_SEQUENCE(ms_now, 0xFFFFFFFF /* default */,
1374 VG_USERREQ__READ_MILLISECOND_TIMER,
1375 0, 0, 0, 0);
1376
1377 /* If a zero timeout specified, this call is harmless. Also go
1378 this route if we're not running on Valgrind, for whatever
1379 reason. */
1380 if ( (timeout && timeout->tv_sec == 0 && timeout->tv_usec == 0)
1381 || (ms_now == 0xFFFFFFFF) ) {
sewardj02535bc2002-04-21 01:08:26 +00001382 res = do_syscall_select( n, (vki_fd_set*)rfds,
sewardj08a4c3f2002-04-13 03:45:44 +00001383 (vki_fd_set*)wfds,
1384 (vki_fd_set*)xfds,
1385 (struct vki_timeval*)timeout);
sewardj02535bc2002-04-21 01:08:26 +00001386 if (is_kerror(res)) {
1387 * (__errno_location()) = -res;
1388 return -1;
1389 } else {
1390 return res;
1391 }
1392 }
sewardj08a4c3f2002-04-13 03:45:44 +00001393
sewardj5f07b662002-04-23 16:52:51 +00001394 /* If a timeout was specified, set ms_end to be the end millisecond
1395 counter [wallclock] time. */
sewardj08a4c3f2002-04-13 03:45:44 +00001396 if (timeout) {
1397 res = my_do_syscall2(__NR_gettimeofday, (int)&t_now, (int)NULL);
1398 assert(res == 0);
sewardj5f07b662002-04-23 16:52:51 +00001399 ms_end = ms_now;
1400 ms_end += (timeout->tv_usec / 1000);
1401 ms_end += (timeout->tv_sec * 1000);
sewardj08a4c3f2002-04-13 03:45:44 +00001402 /* Stay sane ... */
sewardj5f07b662002-04-23 16:52:51 +00001403 assert (ms_end >= ms_now);
sewardj08a4c3f2002-04-13 03:45:44 +00001404 }
1405
1406 /* fprintf(stderr, "MY_SELECT: before loop\n"); */
1407
1408 /* Either timeout == NULL, meaning wait indefinitely, or timeout !=
sewardj5f07b662002-04-23 16:52:51 +00001409 NULL, in which case ms_end holds the end time. */
sewardj08a4c3f2002-04-13 03:45:44 +00001410 while (1) {
1411 if (timeout) {
sewardj5f07b662002-04-23 16:52:51 +00001412 VALGRIND_MAGIC_SEQUENCE(ms_now, 0xFFFFFFFF /* default */,
1413 VG_USERREQ__READ_MILLISECOND_TIMER,
1414 0, 0, 0, 0);
1415 assert(ms_now != 0xFFFFFFFF);
1416 if (ms_now >= ms_end) {
sewardj08a4c3f2002-04-13 03:45:44 +00001417 /* timeout; nothing interesting happened. */
1418 if (rfds) FD_ZERO(rfds);
1419 if (wfds) FD_ZERO(wfds);
1420 if (xfds) FD_ZERO(xfds);
1421 return 0;
1422 }
1423 }
1424
1425 /* These could be trashed each time round the loop, so restore
1426 them each time. */
1427 if (rfds) rfds_copy = *rfds;
1428 if (wfds) wfds_copy = *wfds;
1429 if (xfds) xfds_copy = *xfds;
1430
1431 zero_timeout.tv_sec = zero_timeout.tv_usec = 0;
1432
1433 res = do_syscall_select( n,
1434 rfds ? (vki_fd_set*)(&rfds_copy) : NULL,
1435 wfds ? (vki_fd_set*)(&wfds_copy) : NULL,
1436 xfds ? (vki_fd_set*)(&xfds_copy) : NULL,
1437 & zero_timeout );
sewardj02535bc2002-04-21 01:08:26 +00001438 if (is_kerror(res)) {
1439 /* Some kind of error (including EINTR). Set errno and
sewardj08a4c3f2002-04-13 03:45:44 +00001440 return. The sets are unspecified in this case. */
sewardj02535bc2002-04-21 01:08:26 +00001441 * (__errno_location()) = -res;
1442 return -1;
sewardj08a4c3f2002-04-13 03:45:44 +00001443 }
1444 if (res > 0) {
1445 /* one or more fds is ready. Copy out resulting sets and
1446 return. */
1447 if (rfds) *rfds = rfds_copy;
1448 if (wfds) *wfds = wfds_copy;
1449 if (xfds) *xfds = xfds_copy;
1450 return res;
1451 }
1452 /* fprintf(stderr, "MY_SELECT: nanosleep\n"); */
1453 /* nanosleep and go round again */
sewardj02535bc2002-04-21 01:08:26 +00001454 nanosleep_interval.tv_sec = 0;
sewardj956cc1b2002-04-25 01:33:50 +00001455 nanosleep_interval.tv_nsec = 50 * 1000 * 1000; /* 50 milliseconds */
sewardjf854f472002-04-21 12:19:41 +00001456 /* It's critical here that valgrind's nanosleep implementation
1457 is nonblocking. */
1458 (void)my_do_syscall2(__NR_nanosleep,
1459 (int)(&nanosleep_interval), (int)NULL);
1460 }
1461}
1462
1463
1464
1465
1466#include <sys/poll.h>
1467
sewardj72d58482002-04-24 02:20:20 +00001468#ifdef GLIBC_2_1
1469typedef unsigned long int nfds_t;
1470#endif
1471
sewardj5905fae2002-04-26 13:25:00 +00001472/* __attribute__((weak)) */
sewardjf854f472002-04-21 12:19:41 +00001473int poll (struct pollfd *__fds, nfds_t __nfds, int __timeout)
1474{
sewardj5f07b662002-04-23 16:52:51 +00001475 unsigned int ms_now, ms_end;
sewardjf854f472002-04-21 12:19:41 +00001476 int res, i;
sewardjf854f472002-04-21 12:19:41 +00001477 struct vki_timespec nanosleep_interval;
1478
1479 ensure_valgrind("poll");
1480
sewardj5f07b662002-04-23 16:52:51 +00001481 /* Detect the current time and simultaneously find out if we are
1482 running on Valgrind. */
1483 VALGRIND_MAGIC_SEQUENCE(ms_now, 0xFFFFFFFF /* default */,
1484 VG_USERREQ__READ_MILLISECOND_TIMER,
1485 0, 0, 0, 0);
1486
sewardjf854f472002-04-21 12:19:41 +00001487 if (/* CHECK SIZES FOR struct pollfd */
1488 sizeof(struct timeval) != sizeof(struct vki_timeval))
1489 barf("valgrind's hacky non-blocking poll(): data sizes error");
1490
sewardj5f07b662002-04-23 16:52:51 +00001491 /* dummy initialisation to keep gcc -Wall happy */
1492 ms_end = 0;
1493
1494 /* If a zero timeout specified, this call is harmless. Also do
1495 this if not running on Valgrind. */
1496 if (__timeout == 0 || ms_now == 0xFFFFFFFF) {
sewardjf854f472002-04-21 12:19:41 +00001497 res = my_do_syscall3(__NR_poll, (int)__fds, __nfds, __timeout);
1498 if (is_kerror(res)) {
1499 * (__errno_location()) = -res;
1500 return -1;
1501 } else {
1502 return res;
1503 }
1504 }
1505
sewardj5f07b662002-04-23 16:52:51 +00001506 /* If a timeout was specified, set ms_end to be the end wallclock
1507 time. Easy considering that __timeout is in milliseconds. */
sewardjf854f472002-04-21 12:19:41 +00001508 if (__timeout > 0) {
sewardj650ac002002-04-29 12:20:34 +00001509 ms_end = ms_now + (unsigned int)__timeout;
sewardjf854f472002-04-21 12:19:41 +00001510 }
1511
1512 /* fprintf(stderr, "MY_POLL: before loop\n"); */
1513
1514 /* Either timeout < 0, meaning wait indefinitely, or timeout > 0,
1515 in which case t_end holds the end time. */
sewardj5f07b662002-04-23 16:52:51 +00001516 assert(__timeout != 0);
1517
sewardjf854f472002-04-21 12:19:41 +00001518 while (1) {
sewardjf854f472002-04-21 12:19:41 +00001519 if (__timeout > 0) {
sewardj5f07b662002-04-23 16:52:51 +00001520 VALGRIND_MAGIC_SEQUENCE(ms_now, 0xFFFFFFFF /* default */,
1521 VG_USERREQ__READ_MILLISECOND_TIMER,
1522 0, 0, 0, 0);
1523 assert(ms_now != 0xFFFFFFFF);
1524 if (ms_now >= ms_end) {
sewardjf854f472002-04-21 12:19:41 +00001525 /* timeout; nothing interesting happened. */
1526 for (i = 0; i < __nfds; i++)
1527 __fds[i].revents = 0;
1528 return 0;
1529 }
1530 }
1531
sewardj5f07b662002-04-23 16:52:51 +00001532 /* Do a return-immediately poll. */
sewardjf854f472002-04-21 12:19:41 +00001533 res = my_do_syscall3(__NR_poll, (int)__fds, __nfds, 0 );
1534 if (is_kerror(res)) {
1535 /* Some kind of error. Set errno and return. */
1536 * (__errno_location()) = -res;
1537 return -1;
1538 }
1539 if (res > 0) {
1540 /* One or more fds is ready. Return now. */
1541 return res;
1542 }
1543 /* fprintf(stderr, "MY_POLL: nanosleep\n"); */
1544 /* nanosleep and go round again */
1545 nanosleep_interval.tv_sec = 0;
sewardj956cc1b2002-04-25 01:33:50 +00001546 nanosleep_interval.tv_nsec = 51 * 1000 * 1000; /* 51 milliseconds */
sewardj08a4c3f2002-04-13 03:45:44 +00001547 /* It's critical here that valgrind's nanosleep implementation
1548 is nonblocking. */
1549 (void)my_do_syscall2(__NR_nanosleep,
1550 (int)(&nanosleep_interval), (int)NULL);
1551 }
1552}
sewardj3b13f0e2002-04-25 20:17:29 +00001553
1554
1555/* ---------------------------------------------------------------------
sewardj8f253ff2002-05-19 00:13:34 +00001556 Hacky implementation of semaphores.
1557 ------------------------------------------------------------------ */
1558
1559#include <semaphore.h>
1560
1561/* This is a terrible way to do the remapping. Plan is to import an
1562 AVL tree at some point. */
1563#define VG_N_SEMAPHORES 50
1564
1565typedef
1566 struct {
1567 pthread_mutex_t se_mx;
1568 pthread_cond_t se_cv;
1569 int count;
1570 }
1571 vg_sem_t;
1572
1573static pthread_mutex_t se_remap_mx = PTHREAD_MUTEX_INITIALIZER;
1574
1575static int se_remap_used = 0;
1576static sem_t* se_remap_orig[VG_N_SEMAPHORES];
1577static vg_sem_t se_remap_new[VG_N_SEMAPHORES];
1578
1579static vg_sem_t* se_remap ( sem_t* orig )
1580{
1581 int res, i;
1582 res = __pthread_mutex_lock(&se_remap_mx);
1583 assert(res == 0);
1584
1585 for (i = 0; i < se_remap_used; i++) {
1586 if (se_remap_orig[i] == orig)
1587 break;
1588 }
1589 if (i == se_remap_used) {
1590 if (se_remap_used == VG_N_SEMAPHORES) {
1591 res = pthread_mutex_unlock(&se_remap_mx);
1592 assert(res == 0);
1593 barf("N_SEMAPHORES is too low. Increase and recompile.");
1594 }
1595 se_remap_used++;
1596 se_remap_orig[i] = orig;
1597 /* printf("allocated semaphore %d\n", i); */
1598 }
1599 res = __pthread_mutex_unlock(&se_remap_mx);
1600 assert(res == 0);
1601 return &se_remap_new[i];
1602}
1603
1604
1605int sem_init(sem_t *sem, int pshared, unsigned int value)
1606{
1607 int res;
1608 vg_sem_t* vg_sem;
1609 ensure_valgrind("sem_init");
1610 if (pshared != 0) {
1611 errno = ENOSYS;
1612 return -1;
1613 }
1614 vg_sem = se_remap(sem);
1615 res = pthread_mutex_init(&vg_sem->se_mx, NULL);
1616 assert(res == 0);
1617 res = pthread_cond_init(&vg_sem->se_cv, NULL);
1618 assert(res == 0);
1619 vg_sem->count = value;
1620 return 0;
1621}
1622
1623
1624int sem_wait ( sem_t* sem )
1625{
1626 int res;
1627 vg_sem_t* vg_sem;
1628 ensure_valgrind("sem_wait");
1629 vg_sem = se_remap(sem);
1630 res = __pthread_mutex_lock(&vg_sem->se_mx);
1631 assert(res == 0);
1632 while (vg_sem->count == 0) {
1633 res = pthread_cond_wait(&vg_sem->se_cv, &vg_sem->se_mx);
1634 assert(res == 0);
1635 }
1636 vg_sem->count--;
1637 res = __pthread_mutex_unlock(&vg_sem->se_mx);
1638 assert(res == 0);
1639 return 0;
1640}
1641
1642int sem_post ( sem_t* sem )
1643{
1644 int res;
1645 vg_sem_t* vg_sem;
1646 ensure_valgrind("sem_post");
1647 vg_sem = se_remap(sem);
1648 res = __pthread_mutex_lock(&vg_sem->se_mx);
1649 assert(res == 0);
1650 if (vg_sem->count == 0) {
1651 vg_sem->count++;
1652 res = pthread_cond_broadcast(&vg_sem->se_cv);
1653 assert(res == 0);
1654 } else {
1655 vg_sem->count++;
1656 }
1657 res = __pthread_mutex_unlock(&vg_sem->se_mx);
1658 assert(res == 0);
1659 return 0;
1660}
1661
1662
1663int sem_trywait ( sem_t* sem )
1664{
1665 int ret, res;
1666 vg_sem_t* vg_sem;
1667 ensure_valgrind("sem_trywait");
1668 vg_sem = se_remap(sem);
1669 res = __pthread_mutex_lock(&vg_sem->se_mx);
1670 assert(res == 0);
1671 if (vg_sem->count > 0) {
1672 vg_sem->count--;
1673 ret = 0;
1674 } else {
1675 ret = -1;
1676 errno = EAGAIN;
1677 }
1678 res = __pthread_mutex_unlock(&vg_sem->se_mx);
1679 assert(res == 0);
1680 return ret;
1681}
1682
1683
1684int sem_getvalue(sem_t* sem, int * sval)
1685{
1686 vg_sem_t* vg_sem;
1687 ensure_valgrind("sem_trywait");
1688 vg_sem = se_remap(sem);
1689 *sval = vg_sem->count;
1690 return 0;
1691}
1692
1693
1694int sem_destroy(sem_t * sem)
1695{
1696 kludged("sem_destroy");
1697 /* if someone waiting on this semaphore, errno = EBUSY, return -1 */
1698 return 0;
1699}
1700
1701
1702/* ---------------------------------------------------------------------
sewardj3b13f0e2002-04-25 20:17:29 +00001703 B'stard.
1704 ------------------------------------------------------------------ */
1705
1706# define strong_alias(name, aliasname) \
1707 extern __typeof (name) aliasname __attribute__ ((alias (#name)));
1708
sewardj5905fae2002-04-26 13:25:00 +00001709# define weak_alias(name, aliasname) \
1710 extern __typeof (name) aliasname __attribute__ ((weak, alias (#name)));
sewardj3b13f0e2002-04-25 20:17:29 +00001711
sewardj5905fae2002-04-26 13:25:00 +00001712strong_alias(__pthread_mutex_lock, pthread_mutex_lock)
1713strong_alias(__pthread_mutex_trylock, pthread_mutex_trylock)
1714strong_alias(__pthread_mutex_unlock, pthread_mutex_unlock)
1715strong_alias(__pthread_mutexattr_init, pthread_mutexattr_init)
1716 weak_alias(__pthread_mutexattr_settype, pthread_mutexattr_settype)
1717strong_alias(__pthread_mutex_init, pthread_mutex_init)
1718strong_alias(__pthread_mutexattr_destroy, pthread_mutexattr_destroy)
1719strong_alias(__pthread_mutex_destroy, pthread_mutex_destroy)
1720strong_alias(__pthread_once, pthread_once)
1721strong_alias(__pthread_atfork, pthread_atfork)
1722strong_alias(__pthread_key_create, pthread_key_create)
1723strong_alias(__pthread_getspecific, pthread_getspecific)
1724strong_alias(__pthread_setspecific, pthread_setspecific)
1725
sewardjd529a442002-05-04 19:49:21 +00001726#ifndef GLIBC_2_1
sewardj3b13f0e2002-04-25 20:17:29 +00001727strong_alias(sigaction, __sigaction)
sewardjd529a442002-05-04 19:49:21 +00001728#endif
1729
sewardj5905fae2002-04-26 13:25:00 +00001730strong_alias(close, __close)
sewardj3b13f0e2002-04-25 20:17:29 +00001731strong_alias(fcntl, __fcntl)
sewardj5905fae2002-04-26 13:25:00 +00001732strong_alias(lseek, __lseek)
1733strong_alias(open, __open)
1734strong_alias(open64, __open64)
sewardj5905fae2002-04-26 13:25:00 +00001735strong_alias(read, __read)
1736strong_alias(wait, __wait)
1737strong_alias(write, __write)
sewardj3b13f0e2002-04-25 20:17:29 +00001738strong_alias(connect, __connect)
sewardj5905fae2002-04-26 13:25:00 +00001739strong_alias(send, __send)
1740
sewardj726c4122002-05-16 23:39:10 +00001741weak_alias (__pread64, pread64)
sewardja18e2102002-05-18 10:43:22 +00001742weak_alias (__pwrite64, pwrite64)
sewardj5905fae2002-04-26 13:25:00 +00001743weak_alias(__fork, fork)
sewardj7f6456d2002-05-21 00:51:21 +00001744
sewardj5905fae2002-04-26 13:25:00 +00001745
sewardj3b13f0e2002-04-25 20:17:29 +00001746
1747/*--------------------------------------------------*/
1748
sewardj5716dbb2002-04-26 03:28:18 +00001749int
1750pthread_rwlock_rdlock (void* /* pthread_rwlock_t* */ rwlock)
1751{
sewardj436e0582002-04-26 14:31:40 +00001752 static int moans = N_MOANS;
1753 if (moans-- > 0)
1754 kludged("pthread_rwlock_rdlock");
sewardj5716dbb2002-04-26 03:28:18 +00001755 return 0;
1756}
1757
sewardj5905fae2002-04-26 13:25:00 +00001758weak_alias(pthread_rwlock_rdlock, __pthread_rwlock_rdlock)
sewardj5716dbb2002-04-26 03:28:18 +00001759
1760
1761int
1762pthread_rwlock_unlock (void* /* pthread_rwlock_t* */ rwlock)
1763{
sewardj436e0582002-04-26 14:31:40 +00001764 static int moans = N_MOANS;
1765 if (moans-- > 0)
1766 kludged("pthread_rwlock_unlock");
sewardj5716dbb2002-04-26 03:28:18 +00001767 return 0;
1768}
1769
sewardj5905fae2002-04-26 13:25:00 +00001770weak_alias(pthread_rwlock_unlock, __pthread_rwlock_unlock)
sewardj5716dbb2002-04-26 03:28:18 +00001771
1772
sewardj060b04f2002-04-26 21:01:13 +00001773int
1774pthread_rwlock_wrlock (void* /* pthread_rwlock_t* */ rwlock)
1775{
1776 static int moans = N_MOANS;
1777 if (moans-- > 0)
1778 kludged("pthread_rwlock_wrlock");
1779 return 0;
1780}
1781
sewardj262b0292002-05-01 00:03:16 +00001782weak_alias(pthread_rwlock_wrlock, __pthread_rwlock_wrlock)
sewardj060b04f2002-04-26 21:01:13 +00001783
1784
sewardj3b13f0e2002-04-25 20:17:29 +00001785/* I've no idea what these are, but they get called quite a lot.
1786 Anybody know? */
1787
1788#undef _IO_flockfile
1789void _IO_flockfile ( _IO_FILE * file )
1790{
sewardj853f55d2002-04-26 00:27:53 +00001791 pthread_mutex_lock(file->_lock);
sewardj3b13f0e2002-04-25 20:17:29 +00001792}
sewardj5905fae2002-04-26 13:25:00 +00001793weak_alias(_IO_flockfile, flockfile);
1794
sewardj3b13f0e2002-04-25 20:17:29 +00001795
1796#undef _IO_funlockfile
1797void _IO_funlockfile ( _IO_FILE * file )
1798{
sewardj853f55d2002-04-26 00:27:53 +00001799 pthread_mutex_unlock(file->_lock);
sewardj3b13f0e2002-04-25 20:17:29 +00001800}
sewardj5905fae2002-04-26 13:25:00 +00001801weak_alias(_IO_funlockfile, funlockfile);
1802
sewardj3b13f0e2002-04-25 20:17:29 +00001803
1804void _pthread_cleanup_push_defer ( void )
1805{
sewardj439d45e2002-05-03 20:43:10 +00001806 static int moans = N_MOANS;
1807 if (moans-- > 0)
1808 ignored("_pthread_cleanup_push_defer");
sewardj3b13f0e2002-04-25 20:17:29 +00001809}
1810
1811void _pthread_cleanup_pop_restore ( void )
1812{
sewardj439d45e2002-05-03 20:43:10 +00001813 static int moans = N_MOANS;
1814 if (moans-- > 0)
1815 ignored("_pthread_cleanup_pop_restore");
sewardj3b13f0e2002-04-25 20:17:29 +00001816}
sewardjd4f2c712002-04-30 10:20:10 +00001817
sewardj60e38422002-05-08 14:08:22 +00001818/*--------*/
1819void _pthread_cleanup_push (struct _pthread_cleanup_buffer *__buffer,
1820 void (*__routine) (void *),
1821 void *__arg)
1822{
1823 static int moans = N_MOANS;
1824 if (moans-- > 0)
1825 ignored("_pthread_cleanup_push");
1826}
1827
1828void _pthread_cleanup_pop (struct _pthread_cleanup_buffer *__buffer,
1829 int __execute)
1830{
1831 static int moans = N_MOANS;
1832 if (moans-- > 0) {
1833 if (__execute)
1834 ignored("_pthread_cleanup_pop-EXECUTE");
1835 else
1836 ignored("_pthread_cleanup_pop-NO-EXECUTE");
1837 }
1838}
1839
sewardjd4f2c712002-04-30 10:20:10 +00001840
1841/* This doesn't seem to be needed to simulate libpthread.so's external
1842 interface, but many people complain about its absence. */
1843
1844strong_alias(__pthread_mutexattr_settype, __pthread_mutexattr_setkind_np)
1845weak_alias(__pthread_mutexattr_setkind_np, pthread_mutexattr_setkind_np)
sewardj439d45e2002-05-03 20:43:10 +00001846
1847
1848/*--------------------------------------------------------------------*/
1849/*--- end vg_libpthread.c ---*/
1850/*--------------------------------------------------------------------*/