blob: 2715953a05cc222704738782da5c492cabad6947 [file] [log] [blame]
sewardje663cb92002-04-12 10:26:32 +00001
2/* This is a replacement for the standard libpthread.so. It is loaded
3 as part of the client's image (if required) and directs pthread
4 calls through to Valgrind's request mechanism.
5
6 A couple of caveats.
7
8 1. Since it's a binary-compatible replacement for an existing library,
9 we must take care to used exactly the same data layouts, etc, as
10 the standard pthread.so does.
11
12 2. Since this runs as part of the client, there are no specific
13 restrictions on what headers etc we can include, so long as
14 this libpthread.so does not end up having dependencies on .so's
15 which the real one doesn't.
16
17 Later ... it appears we cannot call file-related stuff in libc here,
18 perhaps fair enough. Be careful what you call from here. Even exit()
19 doesn't work (gives infinite recursion and then stack overflow); hence
20 myexit(). Also fprintf doesn't seem safe.
21*/
22
23#include "valgrind.h" /* For the request-passing mechanism */
24#include "vg_include.h" /* For the VG_USERREQ__* constants */
25
sewardje663cb92002-04-12 10:26:32 +000026#include <unistd.h>
27#include <string.h>
sewardj2a1dcce2002-04-22 12:45:25 +000028#ifdef GLIBC_2_1
29#include <sys/time.h>
30#endif
sewardje663cb92002-04-12 10:26:32 +000031
32/* ---------------------------------------------------------------------
33 Helpers. We have to be pretty self-sufficient.
34 ------------------------------------------------------------------ */
35
sewardj45b4b372002-04-16 22:50:32 +000036/* Extract from Valgrind the value of VG_(clo_trace_pthread_level).
37 Returns 0 (none) if not running on Valgrind. */
38static
39int get_pt_trace_level ( void )
40{
41 int res;
42 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
43 VG_USERREQ__GET_PTHREAD_TRACE_LEVEL,
44 0, 0, 0, 0);
45 return res;
46}
47
48
49
sewardje663cb92002-04-12 10:26:32 +000050static
51void myexit ( int arg )
52{
sewardj45b4b372002-04-16 22:50:32 +000053 int __res;
sewardje663cb92002-04-12 10:26:32 +000054 __asm__ volatile ("movl %%ecx, %%ebx ; int $0x80"
55 : "=a" (__res)
56 : "0" (__NR_exit),
57 "c" (arg) );
sewardj45b4b372002-04-16 22:50:32 +000058 /* We don't bother to mention the fact that this asm trashes %ebx,
59 since it won't return. If you ever do let it return ... fix
60 this! */
sewardje663cb92002-04-12 10:26:32 +000061}
62
63
64/* Give up without using printf etc, since they seem to give
65 segfaults. */
sewardj604ec3c2002-04-18 22:38:41 +000066static __inline__
sewardje663cb92002-04-12 10:26:32 +000067void ensure_valgrind ( char* caller )
68{
69 char* str;
70 int is_valgrind = RUNNING_ON_VALGRIND;
71 if (!is_valgrind) {
72 str = "\nvalgrind-ed process: vg_libpthread.so: "
73 "pthread call when\n";
74 write(2, str, strlen(str));
75 str = "not running on valgrind; aborting! "
76 "This is probably a bug in\n";
77 write(2, str, strlen(str));
78 str = "valgrind. Please report it to me at: "
79 "jseward@acm.org. Thanks.\n";
80 write(2, str, strlen(str));
81 str = "unexpectedly called function is: ";
82 write(2, str, strlen(str));
83 write(2, caller, strlen(caller));
84 str = "\n\n";
85 write(2, str, strlen(str));
86 myexit(1);
87 }
88}
89
90
91static
sewardj3b5d8862002-04-20 13:53:23 +000092__attribute__((noreturn))
sewardje663cb92002-04-12 10:26:32 +000093void barf ( char* str )
94{
95 char buf[100];
96 buf[0] = 0;
97 strcat(buf, "\nvg_libpthread.so: ");
98 strcat(buf, str);
99 strcat(buf, "\n\n");
100 write(2, buf, strlen(buf));
101 myexit(1);
sewardj3b5d8862002-04-20 13:53:23 +0000102 /* We have to persuade gcc into believing this doesn't return. */
103 while (1) { };
sewardje663cb92002-04-12 10:26:32 +0000104}
105
106
sewardj2a3d28c2002-04-14 13:27:00 +0000107static void ignored ( char* msg )
108{
sewardj45b4b372002-04-16 22:50:32 +0000109 if (get_pt_trace_level() >= 1) {
110 char* ig = "vg_libpthread.so: IGNORED call to: ";
111 write(2, ig, strlen(ig));
112 write(2, msg, strlen(msg));
113 ig = "\n";
114 write(2, ig, strlen(ig));
115 }
sewardj2a3d28c2002-04-14 13:27:00 +0000116}
117
sewardj30671ff2002-04-21 00:13:57 +0000118static void kludged ( char* msg )
119{
120 if (get_pt_trace_level() >= 1) {
121 char* ig = "vg_libpthread.so: KLUDGED call to: ";
122 write(2, ig, strlen(ig));
123 write(2, msg, strlen(msg));
124 ig = "\n";
125 write(2, ig, strlen(ig));
126 }
127}
128
sewardj3b13f0e2002-04-25 20:17:29 +0000129void vgPlain_unimp ( char* what )
130{
131 char* ig = "vg_libpthread.so: UNIMPLEMENTED FUNCTION: ";
132 write(2, ig, strlen(ig));
133 write(2, what, strlen(what));
134 ig = "\n";
135 write(2, ig, strlen(ig));
136 barf("Please report this bug to me at: jseward@acm.org");
137}
138
sewardje663cb92002-04-12 10:26:32 +0000139
140/* ---------------------------------------------------------------------
141 Pass pthread_ calls to Valgrind's request mechanism.
142 ------------------------------------------------------------------ */
143
sewardjf8f819e2002-04-17 23:21:37 +0000144#include <pthread.h>
145#include <stdio.h>
146#include <errno.h>
sewardj5f07b662002-04-23 16:52:51 +0000147#include <assert.h>
148#include <sys/time.h> /* gettimeofday */
sewardjf8f819e2002-04-17 23:21:37 +0000149
150/* ---------------------------------------------------
151 THREAD ATTRIBUTES
152 ------------------------------------------------ */
153
sewardj6af4b5d2002-04-16 04:40:49 +0000154int pthread_attr_init(pthread_attr_t *attr)
155{
156 ignored("pthread_attr_init");
157 return 0;
158}
159
160int pthread_attr_setdetachstate(pthread_attr_t *attr, int detachstate)
161{
162 ignored("pthread_attr_setdetachstate");
163 return 0;
164}
165
sewardj30671ff2002-04-21 00:13:57 +0000166int pthread_attr_setinheritsched(pthread_attr_t *attr, int inherit)
167{
168 ignored("pthread_attr_setinheritsched");
169 return 0;
170}
sewardj6af4b5d2002-04-16 04:40:49 +0000171
sewardj30671ff2002-04-21 00:13:57 +0000172/* This is completely bogus. */
173int pthread_attr_getschedparam(const pthread_attr_t *attr,
174 struct sched_param *param)
175{
176 kludged("pthread_attr_getschedparam");
sewardj72d58482002-04-24 02:20:20 +0000177# ifdef GLIBC_2_1
178 if (param) param->sched_priority = 0; /* who knows */
179# else
sewardj30671ff2002-04-21 00:13:57 +0000180 if (param) param->__sched_priority = 0; /* who knows */
sewardj72d58482002-04-24 02:20:20 +0000181# endif
sewardj30671ff2002-04-21 00:13:57 +0000182 return 0;
183}
184
185int pthread_attr_setschedparam(pthread_attr_t *attr,
186 const struct sched_param *param)
187{
188 ignored("pthread_attr_setschedparam");
189 return 0;
190}
191
192int pthread_attr_destroy(pthread_attr_t *attr)
193{
194 ignored("pthread_attr_destroy");
195 return 0;
196}
sewardjf8f819e2002-04-17 23:21:37 +0000197
198/* ---------------------------------------------------
199 THREADs
200 ------------------------------------------------ */
201
sewardj6072c362002-04-19 14:40:57 +0000202int pthread_equal(pthread_t thread1, pthread_t thread2)
203{
204 return thread1 == thread2 ? 1 : 0;
205}
206
207
sewardje663cb92002-04-12 10:26:32 +0000208int
209pthread_create (pthread_t *__restrict __thread,
210 __const pthread_attr_t *__restrict __attr,
211 void *(*__start_routine) (void *),
212 void *__restrict __arg)
213{
214 int res;
215 ensure_valgrind("pthread_create");
216 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
217 VG_USERREQ__PTHREAD_CREATE,
218 __thread, __attr, __start_routine, __arg);
219 return res;
220}
221
222
223
224int
225pthread_join (pthread_t __th, void **__thread_return)
226{
227 int res;
228 ensure_valgrind("pthread_join");
229 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
230 VG_USERREQ__PTHREAD_JOIN,
231 __th, __thread_return, 0, 0);
232 return res;
233}
234
235
sewardj3b5d8862002-04-20 13:53:23 +0000236void pthread_exit(void *retval)
237{
238 int res;
239 ensure_valgrind("pthread_exit");
240 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
241 VG_USERREQ__PTHREAD_EXIT,
242 retval, 0, 0, 0);
243 /* Doesn't return! */
244 /* However, we have to fool gcc into knowing that. */
245 barf("pthread_exit: still alive after request?!");
246}
247
sewardje663cb92002-04-12 10:26:32 +0000248
sewardj3b13f0e2002-04-25 20:17:29 +0000249pthread_t pthread_self(void)
sewardje663cb92002-04-12 10:26:32 +0000250{
251 int tid;
sewardj3b13f0e2002-04-25 20:17:29 +0000252 ensure_valgrind("pthread_self");
sewardje663cb92002-04-12 10:26:32 +0000253 VALGRIND_MAGIC_SEQUENCE(tid, 0 /* default */,
254 VG_USERREQ__PTHREAD_GET_THREADID,
255 0, 0, 0, 0);
sewardje663cb92002-04-12 10:26:32 +0000256 if (tid < 0 || tid >= VG_N_THREADS)
sewardj3b13f0e2002-04-25 20:17:29 +0000257 barf("pthread_self: invalid ThreadId");
258 return tid;
sewardje663cb92002-04-12 10:26:32 +0000259}
260
261
sewardj853f55d2002-04-26 00:27:53 +0000262int pthread_detach(pthread_t th)
263{
264 ignored("pthread_detach");
265 return 0;
266}
267
268
sewardjf8f819e2002-04-17 23:21:37 +0000269/* ---------------------------------------------------
270 MUTEX ATTRIBUTES
271 ------------------------------------------------ */
272
sewardje663cb92002-04-12 10:26:32 +0000273int pthread_mutexattr_init(pthread_mutexattr_t *attr)
274{
sewardjf8f819e2002-04-17 23:21:37 +0000275 attr->__mutexkind = PTHREAD_MUTEX_ERRORCHECK_NP;
sewardj8937c812002-04-12 20:12:20 +0000276 return 0;
sewardje663cb92002-04-12 10:26:32 +0000277}
278
sewardjf8f819e2002-04-17 23:21:37 +0000279int pthread_mutexattr_settype(pthread_mutexattr_t *attr, int type)
280{
281 switch (type) {
sewardj3b13f0e2002-04-25 20:17:29 +0000282# ifndef GLIBC_2_1
sewardjf8f819e2002-04-17 23:21:37 +0000283 case PTHREAD_MUTEX_TIMED_NP:
sewardj2a1dcce2002-04-22 12:45:25 +0000284 case PTHREAD_MUTEX_ADAPTIVE_NP:
sewardj3b13f0e2002-04-25 20:17:29 +0000285# endif
sewardjf8f819e2002-04-17 23:21:37 +0000286 case PTHREAD_MUTEX_RECURSIVE_NP:
287 case PTHREAD_MUTEX_ERRORCHECK_NP:
sewardjf8f819e2002-04-17 23:21:37 +0000288 attr->__mutexkind = type;
289 return 0;
290 default:
291 return EINVAL;
292 }
293}
294
295int pthread_mutexattr_destroy(pthread_mutexattr_t *attr)
296{
297 return 0;
298}
299
300
301/* ---------------------------------------------------
302 MUTEXes
303 ------------------------------------------------ */
304
sewardje663cb92002-04-12 10:26:32 +0000305int pthread_mutex_init(pthread_mutex_t *mutex,
306 const pthread_mutexattr_t *mutexattr)
307{
sewardj604ec3c2002-04-18 22:38:41 +0000308 mutex->__m_count = 0;
309 mutex->__m_owner = (_pthread_descr)VG_INVALID_THREADID;
310 mutex->__m_kind = PTHREAD_MUTEX_ERRORCHECK_NP;
311 if (mutexattr)
312 mutex->__m_kind = mutexattr->__mutexkind;
313 return 0;
sewardje663cb92002-04-12 10:26:32 +0000314}
315
sewardje663cb92002-04-12 10:26:32 +0000316int pthread_mutex_lock(pthread_mutex_t *mutex)
317{
318 int res;
sewardj604ec3c2002-04-18 22:38:41 +0000319 static int moans = 3;
sewardj45b4b372002-04-16 22:50:32 +0000320 if (!(RUNNING_ON_VALGRIND) && moans-- > 0) {
sewardje663cb92002-04-12 10:26:32 +0000321 char* str = "pthread_mutex_lock-NOT-INSIDE-VALGRIND\n";
322 write(2, str, strlen(str));
323 return 0;
324 } else {
325 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
326 VG_USERREQ__PTHREAD_MUTEX_LOCK,
327 mutex, 0, 0, 0);
328 return res;
329 }
330}
331
sewardj30671ff2002-04-21 00:13:57 +0000332int pthread_mutex_trylock(pthread_mutex_t *mutex)
333{
334 int res;
335 static int moans = 3;
336 if (!(RUNNING_ON_VALGRIND) && moans-- > 0) {
337 char* str = "pthread_mutex_trylock-NOT-INSIDE-VALGRIND\n";
338 write(2, str, strlen(str));
339 return 0;
340 } else {
341 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
342 VG_USERREQ__PTHREAD_MUTEX_TRYLOCK,
343 mutex, 0, 0, 0);
344 return res;
345 }
346}
347
sewardje663cb92002-04-12 10:26:32 +0000348int pthread_mutex_unlock(pthread_mutex_t *mutex)
349{
350 int res;
sewardj604ec3c2002-04-18 22:38:41 +0000351 static int moans = 3;
sewardj45b4b372002-04-16 22:50:32 +0000352 if (!(RUNNING_ON_VALGRIND) && moans-- > 0) {
sewardje663cb92002-04-12 10:26:32 +0000353 char* str = "pthread_mutex_unlock-NOT-INSIDE-VALGRIND\n";
354 write(2, str, strlen(str));
355 return 0;
356 } else {
357 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
358 VG_USERREQ__PTHREAD_MUTEX_UNLOCK,
359 mutex, 0, 0, 0);
360 return res;
361 }
362}
363
sewardje663cb92002-04-12 10:26:32 +0000364int pthread_mutex_destroy(pthread_mutex_t *mutex)
365{
sewardj604ec3c2002-04-18 22:38:41 +0000366 /* Valgrind doesn't hold any resources on behalf of the mutex, so no
367 need to involve it. */
368 if (mutex->__m_count > 0)
369 return EBUSY;
sewardj6072c362002-04-19 14:40:57 +0000370 mutex->__m_count = 0;
371 mutex->__m_owner = (_pthread_descr)VG_INVALID_THREADID;
372 mutex->__m_kind = PTHREAD_MUTEX_ERRORCHECK_NP;
sewardj604ec3c2002-04-18 22:38:41 +0000373 return 0;
sewardje663cb92002-04-12 10:26:32 +0000374}
375
376
sewardjf8f819e2002-04-17 23:21:37 +0000377/* ---------------------------------------------------
sewardj6072c362002-04-19 14:40:57 +0000378 CONDITION VARIABLES
379 ------------------------------------------------ */
380
381/* LinuxThreads supports no attributes for conditions. Hence ... */
382
383int pthread_condattr_init(pthread_condattr_t *attr)
384{
385 return 0;
386}
387
sewardj0738a592002-04-20 13:59:33 +0000388int pthread_condattr_destroy(pthread_condattr_t *attr)
389{
390 return 0;
391}
sewardj6072c362002-04-19 14:40:57 +0000392
393int pthread_cond_init( pthread_cond_t *cond,
394 const pthread_condattr_t *cond_attr)
395{
396 cond->__c_waiting = (_pthread_descr)VG_INVALID_THREADID;
397 return 0;
398}
399
sewardjf854f472002-04-21 12:19:41 +0000400int pthread_cond_destroy(pthread_cond_t *cond)
401{
402 /* should check that no threads are waiting on this CV */
403 kludged("pthread_cond_destroy");
404 return 0;
405}
sewardj6072c362002-04-19 14:40:57 +0000406
407/* ---------------------------------------------------
408 SCHEDULING
409 ------------------------------------------------ */
410
411/* This is completely bogus. */
412int pthread_getschedparam(pthread_t target_thread,
413 int *policy,
414 struct sched_param *param)
415{
sewardj30671ff2002-04-21 00:13:57 +0000416 kludged("pthread_getschedparam");
sewardj6072c362002-04-19 14:40:57 +0000417 if (policy) *policy = SCHED_OTHER;
sewardj2a1dcce2002-04-22 12:45:25 +0000418# ifdef GLIBC_2_1
419 if (param) param->sched_priority = 0; /* who knows */
420# else
sewardj6072c362002-04-19 14:40:57 +0000421 if (param) param->__sched_priority = 0; /* who knows */
sewardj2a1dcce2002-04-22 12:45:25 +0000422# endif
sewardj6072c362002-04-19 14:40:57 +0000423 return 0;
424}
425
426int pthread_setschedparam(pthread_t target_thread,
427 int policy,
428 const struct sched_param *param)
429{
430 ignored("pthread_setschedparam");
431 return 0;
432}
433
sewardj3b5d8862002-04-20 13:53:23 +0000434int pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex)
435{
436 int res;
437 ensure_valgrind("pthread_cond_wait");
438 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
439 VG_USERREQ__PTHREAD_COND_WAIT,
440 cond, mutex, 0, 0);
441 return res;
442}
443
sewardj5f07b662002-04-23 16:52:51 +0000444int pthread_cond_timedwait ( pthread_cond_t *cond,
445 pthread_mutex_t *mutex,
446 const struct timespec *abstime )
447{
448 int res;
449 unsigned int ms_now, ms_end;
450 struct timeval timeval_now;
451 unsigned long long int ull_ms_now_after_1970;
452 unsigned long long int ull_ms_end_after_1970;
453
454 ensure_valgrind("pthread_cond_timedwait");
455 VALGRIND_MAGIC_SEQUENCE(ms_now, 0xFFFFFFFF /* default */,
456 VG_USERREQ__READ_MILLISECOND_TIMER,
457 0, 0, 0, 0);
458 assert(ms_now != 0xFFFFFFFF);
459 res = gettimeofday(&timeval_now, NULL);
460 assert(res == 0);
461
462 ull_ms_now_after_1970
463 = 1000ULL * ((unsigned long long int)(timeval_now.tv_sec))
464 + ((unsigned long long int)(timeval_now.tv_usec / 1000000));
465 ull_ms_end_after_1970
466 = 1000ULL * ((unsigned long long int)(abstime->tv_sec))
467 + ((unsigned long long int)(abstime->tv_nsec / 1000000));
468 assert(ull_ms_end_after_1970 >= ull_ms_now_after_1970);
469 ms_end
470 = ms_now + (unsigned int)(ull_ms_end_after_1970 - ull_ms_now_after_1970);
471 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
472 VG_USERREQ__PTHREAD_COND_TIMEDWAIT,
473 cond, mutex, ms_end, 0);
474 return res;
475}
476
477
sewardj3b5d8862002-04-20 13:53:23 +0000478int pthread_cond_signal(pthread_cond_t *cond)
479{
480 int res;
481 ensure_valgrind("pthread_cond_signal");
482 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
483 VG_USERREQ__PTHREAD_COND_SIGNAL,
484 cond, 0, 0, 0);
485 return res;
486}
487
488int pthread_cond_broadcast(pthread_cond_t *cond)
489{
490 int res;
491 ensure_valgrind("pthread_cond_broadcast");
492 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
493 VG_USERREQ__PTHREAD_COND_BROADCAST,
494 cond, 0, 0, 0);
495 return res;
496}
497
sewardj6072c362002-04-19 14:40:57 +0000498
499/* ---------------------------------------------------
sewardjf8f819e2002-04-17 23:21:37 +0000500 CANCELLATION
501 ------------------------------------------------ */
502
sewardj853f55d2002-04-26 00:27:53 +0000503int pthread_setcancelstate(int state, int *oldstate)
504{
505 ignored("pthread_setcancelstate");
506 return 0;
507}
508
sewardje663cb92002-04-12 10:26:32 +0000509int pthread_setcanceltype(int type, int *oldtype)
510{
sewardj2a3d28c2002-04-14 13:27:00 +0000511 ignored("pthread_setcanceltype");
sewardje663cb92002-04-12 10:26:32 +0000512 return 0;
513}
514
sewardje663cb92002-04-12 10:26:32 +0000515int pthread_cancel(pthread_t thread)
516{
517 int res;
518 ensure_valgrind("pthread_cancel");
519 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
520 VG_USERREQ__PTHREAD_CANCEL,
521 thread, 0, 0, 0);
522 return res;
523}
524
sewardj853f55d2002-04-26 00:27:53 +0000525void pthread_testcancel(void)
526{
527}
528
529/*-------------------*/
530static pthread_mutex_t massacre_mx = PTHREAD_MUTEX_INITIALIZER;
531
532void __pthread_kill_other_threads_np ( void )
533{
534 int i, res, me;
535 pthread_mutex_lock(&massacre_mx);
536 me = pthread_self();
537 for (i = 1; i < VG_N_THREADS; i++) {
538 if (i == me) continue;
539 res = pthread_cancel(i);
540 if (res == 0)
541 printf("----------- NUKED %d\n", i);
542 }
543 pthread_mutex_unlock(&massacre_mx);
544}
545
sewardje663cb92002-04-12 10:26:32 +0000546
sewardjf8f819e2002-04-17 23:21:37 +0000547/* ---------------------------------------------------
548 THREAD-SPECIFICs
549 ------------------------------------------------ */
sewardj5e5fa512002-04-14 13:13:05 +0000550
551int pthread_key_create(pthread_key_t *key,
552 void (*destr_function) (void *))
553{
sewardj5f07b662002-04-23 16:52:51 +0000554 int res;
555 ensure_valgrind("pthread_key_create");
556 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
557 VG_USERREQ__PTHREAD_KEY_CREATE,
558 key, destr_function, 0, 0);
559 return res;
sewardj5e5fa512002-04-14 13:13:05 +0000560}
561
562int pthread_key_delete(pthread_key_t key)
563{
sewardj2a3d28c2002-04-14 13:27:00 +0000564 ignored("pthread_key_delete");
sewardj5e5fa512002-04-14 13:13:05 +0000565 return 0;
566}
567
568int pthread_setspecific(pthread_key_t key, const void *pointer)
569{
sewardj5f07b662002-04-23 16:52:51 +0000570 int res;
571 ensure_valgrind("pthread_setspecific");
572 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
573 VG_USERREQ__PTHREAD_SETSPECIFIC,
574 key, pointer, 0, 0);
575 return res;
sewardj5e5fa512002-04-14 13:13:05 +0000576}
577
578void * pthread_getspecific(pthread_key_t key)
579{
sewardj5f07b662002-04-23 16:52:51 +0000580 int res;
581 ensure_valgrind("pthread_getspecific");
582 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
583 VG_USERREQ__PTHREAD_GETSPECIFIC,
584 key, 0 , 0, 0);
585 return (void*)res;
sewardj5e5fa512002-04-14 13:13:05 +0000586}
587
sewardjf8f819e2002-04-17 23:21:37 +0000588
589/* ---------------------------------------------------
sewardj89d3d852002-04-24 19:21:39 +0000590 ONCEry
591 ------------------------------------------------ */
592
593static pthread_mutex_t once_masterlock = PTHREAD_MUTEX_INITIALIZER;
594
595
596int pthread_once ( pthread_once_t *once_control,
597 void (*init_routine) (void) )
598{
599 int res;
600 ensure_valgrind("pthread_once");
601
602 res = pthread_mutex_lock(&once_masterlock);
603
604 if (res != 0)
605 barf("pthread_once: Looks like your program's "
606 "init routine calls back to pthread_once() ?!");
607
608 if (*once_control == 0) {
609 *once_control = 1;
610 init_routine();
611 }
612
613 pthread_mutex_unlock(&once_masterlock);
614
615 return 0;
616}
617
618
619/* ---------------------------------------------------
sewardj853f55d2002-04-26 00:27:53 +0000620 MISC
621 ------------------------------------------------ */
622
623int pthread_atfork ( void (*prepare)(void),
624 void (*parent)(void),
625 void (*child)(void) )
626{
627 ignored("pthread_atfork");
628 return 0;
629}
630
631
632/* ---------------------------------------------------
sewardj3b13f0e2002-04-25 20:17:29 +0000633 LIBRARY-PRIVATE THREAD SPECIFIC STATE
sewardjf8f819e2002-04-17 23:21:37 +0000634 ------------------------------------------------ */
635
sewardj3b13f0e2002-04-25 20:17:29 +0000636#include <resolv.h>
637static int thread_specific_errno[VG_N_THREADS];
638static int thread_specific_h_errno[VG_N_THREADS];
639static struct __res_state
640 thread_specific_res_state[VG_N_THREADS];
sewardjf8f819e2002-04-17 23:21:37 +0000641
sewardj3b13f0e2002-04-25 20:17:29 +0000642int* __errno_location ( void )
sewardjf8f819e2002-04-17 23:21:37 +0000643{
644 int tid;
sewardj3b13f0e2002-04-25 20:17:29 +0000645 /* ensure_valgrind("__errno_location"); */
646 VALGRIND_MAGIC_SEQUENCE(tid, 1 /* default */,
sewardjf8f819e2002-04-17 23:21:37 +0000647 VG_USERREQ__PTHREAD_GET_THREADID,
648 0, 0, 0, 0);
sewardj3b13f0e2002-04-25 20:17:29 +0000649 /* 'cos I'm paranoid ... */
sewardjf8f819e2002-04-17 23:21:37 +0000650 if (tid < 0 || tid >= VG_N_THREADS)
sewardj3b13f0e2002-04-25 20:17:29 +0000651 barf("__errno_location: invalid ThreadId");
652 return & thread_specific_errno[tid];
653}
654
655int* __h_errno_location ( void )
656{
657 int tid;
658 /* ensure_valgrind("__h_errno_location"); */
659 VALGRIND_MAGIC_SEQUENCE(tid, 1 /* default */,
660 VG_USERREQ__PTHREAD_GET_THREADID,
661 0, 0, 0, 0);
662 /* 'cos I'm paranoid ... */
663 if (tid < 0 || tid >= VG_N_THREADS)
664 barf("__h_errno_location: invalid ThreadId");
665 return & thread_specific_h_errno[tid];
666}
667
668struct __res_state* __res_state ( void )
669{
670 int tid;
671 /* ensure_valgrind("__res_state"); */
672 VALGRIND_MAGIC_SEQUENCE(tid, 1 /* default */,
673 VG_USERREQ__PTHREAD_GET_THREADID,
674 0, 0, 0, 0);
675 /* 'cos I'm paranoid ... */
676 if (tid < 0 || tid >= VG_N_THREADS)
677 barf("__res_state: invalid ThreadId");
678 return & thread_specific_res_state[tid];
sewardjf8f819e2002-04-17 23:21:37 +0000679}
680
681
sewardje663cb92002-04-12 10:26:32 +0000682/* ---------------------------------------------------------------------
683 These are here (I think) because they are deemed cancellation
684 points by POSIX. For the moment we'll simply pass the call along
685 to the corresponding thread-unaware (?) libc routine.
686 ------------------------------------------------------------------ */
687
sewardje663cb92002-04-12 10:26:32 +0000688#include <stdlib.h>
689#include <signal.h>
sewardje663cb92002-04-12 10:26:32 +0000690#include <sys/types.h>
691#include <sys/socket.h>
692
693extern
694int __libc_sigaction
695 (int signum,
696 const struct sigaction *act,
697 struct sigaction *oldact);
698int sigaction(int signum,
699 const struct sigaction *act,
700 struct sigaction *oldact)
701{
sewardj2a1dcce2002-04-22 12:45:25 +0000702# ifdef GLIBC_2_1
703 return __sigaction(signum, act, oldact);
704# else
sewardj45b4b372002-04-16 22:50:32 +0000705 return __libc_sigaction(signum, act, oldact);
sewardj2a1dcce2002-04-22 12:45:25 +0000706# endif
sewardje663cb92002-04-12 10:26:32 +0000707}
708
709
710extern
711int __libc_connect(int sockfd,
712 const struct sockaddr *serv_addr,
713 socklen_t addrlen);
714int connect(int sockfd,
715 const struct sockaddr *serv_addr,
716 socklen_t addrlen)
717{
sewardj45b4b372002-04-16 22:50:32 +0000718 return __libc_connect(sockfd, serv_addr, addrlen);
sewardje663cb92002-04-12 10:26:32 +0000719}
720
721
722extern
723int __libc_fcntl(int fd, int cmd, long arg);
724int fcntl(int fd, int cmd, long arg)
725{
sewardj45b4b372002-04-16 22:50:32 +0000726 return __libc_fcntl(fd, cmd, arg);
sewardje663cb92002-04-12 10:26:32 +0000727}
728
729
730extern
731ssize_t __libc_write(int fd, const void *buf, size_t count);
732ssize_t write(int fd, const void *buf, size_t count)
733{
sewardj45b4b372002-04-16 22:50:32 +0000734 return __libc_write(fd, buf, count);
sewardje663cb92002-04-12 10:26:32 +0000735}
736
737
738extern
739ssize_t __libc_read(int fd, void *buf, size_t count);
740ssize_t read(int fd, void *buf, size_t count)
741{
sewardj45b4b372002-04-16 22:50:32 +0000742 return __libc_read(fd, buf, count);
sewardje663cb92002-04-12 10:26:32 +0000743}
744
sewardjbe32e452002-04-24 20:29:58 +0000745
746extern
sewardj853f55d2002-04-26 00:27:53 +0000747int __libc_open64(const char *pathname, int flags, mode_t mode);
748int open64(const char *pathname, int flags, mode_t mode)
sewardjbe32e452002-04-24 20:29:58 +0000749{
sewardj853f55d2002-04-26 00:27:53 +0000750 return __libc_open64(pathname, flags, mode);
sewardjbe32e452002-04-24 20:29:58 +0000751}
752
sewardje663cb92002-04-12 10:26:32 +0000753
754extern
sewardj853f55d2002-04-26 00:27:53 +0000755int __libc_open(const char *pathname, int flags, mode_t mode);
756int open(const char *pathname, int flags, mode_t mode)
sewardje663cb92002-04-12 10:26:32 +0000757{
sewardj853f55d2002-04-26 00:27:53 +0000758 return __libc_open(pathname, flags, mode);
sewardje663cb92002-04-12 10:26:32 +0000759}
760
761
762extern
763int __libc_close(int fd);
764int close(int fd)
765{
sewardj45b4b372002-04-16 22:50:32 +0000766 return __libc_close(fd);
sewardje663cb92002-04-12 10:26:32 +0000767}
768
769
770extern
771int __libc_accept(int s, struct sockaddr *addr, socklen_t *addrlen);
772int accept(int s, struct sockaddr *addr, socklen_t *addrlen)
773{
sewardj45b4b372002-04-16 22:50:32 +0000774 return __libc_accept(s, addr, addrlen);
sewardje663cb92002-04-12 10:26:32 +0000775}
776
777
778extern
779pid_t __libc_fork(void);
780pid_t fork(void)
781{
sewardj45b4b372002-04-16 22:50:32 +0000782 return __libc_fork();
sewardje663cb92002-04-12 10:26:32 +0000783}
784
785
786extern
787pid_t __libc_waitpid(pid_t pid, int *status, int options);
788pid_t waitpid(pid_t pid, int *status, int options)
789{
sewardj45b4b372002-04-16 22:50:32 +0000790 return __libc_waitpid(pid, status, options);
sewardje663cb92002-04-12 10:26:32 +0000791}
792
793
794extern
795int __libc_nanosleep(const struct timespec *req, struct timespec *rem);
796int nanosleep(const struct timespec *req, struct timespec *rem)
797{
798 return __libc_nanosleep(req, rem);
799}
800
sewardjbe32e452002-04-24 20:29:58 +0000801
sewardje663cb92002-04-12 10:26:32 +0000802extern
803int __libc_fsync(int fd);
804int fsync(int fd)
805{
sewardj45b4b372002-04-16 22:50:32 +0000806 return __libc_fsync(fd);
sewardje663cb92002-04-12 10:26:32 +0000807}
808
sewardjbe32e452002-04-24 20:29:58 +0000809
sewardj70c75362002-04-13 04:18:32 +0000810extern
811off_t __libc_lseek(int fildes, off_t offset, int whence);
812off_t lseek(int fildes, off_t offset, int whence)
813{
sewardj45b4b372002-04-16 22:50:32 +0000814 return __libc_lseek(fildes, offset, whence);
sewardj70c75362002-04-13 04:18:32 +0000815}
816
sewardjbe32e452002-04-24 20:29:58 +0000817
818extern
819__off64_t __libc_lseek64(int fildes, __off64_t offset, int whence);
820__off64_t lseek64(int fildes, __off64_t offset, int whence)
821{
822 return __libc_lseek64(fildes, offset, whence);
823}
824
825
sewardj6af4b5d2002-04-16 04:40:49 +0000826extern
827void __libc_longjmp(jmp_buf env, int val) __attribute((noreturn));
828void longjmp(jmp_buf env, int val)
829{
830 __libc_longjmp(env, val);
831}
832
sewardjbe32e452002-04-24 20:29:58 +0000833
sewardj6af4b5d2002-04-16 04:40:49 +0000834extern
835int __libc_send(int s, const void *msg, size_t len, int flags);
836int send(int s, const void *msg, size_t len, int flags)
837{
838 return __libc_send(s, msg, len, flags);
839}
840
sewardjbe32e452002-04-24 20:29:58 +0000841
sewardj1e8cdc92002-04-18 11:37:52 +0000842extern
843int __libc_recv(int s, void *buf, size_t len, int flags);
844int recv(int s, void *buf, size_t len, int flags)
845{
846 return __libc_recv(s, buf, len, flags);
847}
848
sewardjbe32e452002-04-24 20:29:58 +0000849
sewardj796d6a22002-04-24 02:28:34 +0000850extern
851int __libc_sendto(int s, const void *msg, size_t len, int flags,
852 const struct sockaddr *to, socklen_t tolen);
853int sendto(int s, const void *msg, size_t len, int flags,
854 const struct sockaddr *to, socklen_t tolen)
855{
856 return __libc_sendto(s, msg, len, flags, to, tolen);
857}
858
sewardjbe32e452002-04-24 20:29:58 +0000859
sewardj369b1702002-04-24 13:28:15 +0000860extern
861int __libc_system(const char* str);
862int system(const char* str)
863{
864 return __libc_system(str);
865}
866
sewardjbe32e452002-04-24 20:29:58 +0000867
sewardjab0b1c32002-04-24 19:26:47 +0000868extern
869pid_t __libc_wait(int *status);
870pid_t wait(int *status)
871{
872 return __libc_wait(status);
873}
874
sewardj45b4b372002-04-16 22:50:32 +0000875
sewardj3b13f0e2002-04-25 20:17:29 +0000876/* ---------------------------------------------------------------------
877 Nonblocking implementations of select() and poll(). This stuff will
878 surely rot your mind.
879 ------------------------------------------------------------------ */
sewardje663cb92002-04-12 10:26:32 +0000880
sewardj08a4c3f2002-04-13 03:45:44 +0000881/*--------------------------------------------------*/
882
883#include "vg_kerneliface.h"
884
885static
886__inline__
887int is_kerror ( int res )
888{
889 if (res >= -4095 && res <= -1)
890 return 1;
891 else
892 return 0;
893}
894
895
896static
897int my_do_syscall1 ( int syscallno, int arg1 )
898{
899 int __res;
900 __asm__ volatile ("pushl %%ebx; movl %%edx,%%ebx ; int $0x80 ; popl %%ebx"
901 : "=a" (__res)
902 : "0" (syscallno),
903 "d" (arg1) );
904 return __res;
905}
906
907static
908int my_do_syscall2 ( int syscallno,
sewardjf854f472002-04-21 12:19:41 +0000909 int arg1, int arg2 )
sewardj08a4c3f2002-04-13 03:45:44 +0000910{
911 int __res;
912 __asm__ volatile ("pushl %%ebx; movl %%edx,%%ebx ; int $0x80 ; popl %%ebx"
913 : "=a" (__res)
914 : "0" (syscallno),
915 "d" (arg1),
916 "c" (arg2) );
917 return __res;
918}
919
920static
sewardjf854f472002-04-21 12:19:41 +0000921int my_do_syscall3 ( int syscallno,
922 int arg1, int arg2, int arg3 )
923{
924 int __res;
925 __asm__ volatile ("pushl %%ebx; movl %%esi,%%ebx ; int $0x80 ; popl %%ebx"
926 : "=a" (__res)
927 : "0" (syscallno),
928 "S" (arg1),
929 "c" (arg2),
930 "d" (arg3) );
931 return __res;
932}
933
934static
sewardj08a4c3f2002-04-13 03:45:44 +0000935int do_syscall_select( int n,
936 vki_fd_set* readfds,
937 vki_fd_set* writefds,
938 vki_fd_set* exceptfds,
939 struct vki_timeval * timeout )
940{
941 int res;
942 int args[5];
943 args[0] = n;
944 args[1] = (int)readfds;
945 args[2] = (int)writefds;
946 args[3] = (int)exceptfds;
947 args[4] = (int)timeout;
948 res = my_do_syscall1(__NR_select, (int)(&(args[0])) );
sewardj02535bc2002-04-21 01:08:26 +0000949 return res;
sewardj08a4c3f2002-04-13 03:45:44 +0000950}
951
952
953/* This is a wrapper round select(), which makes it thread-safe,
954 meaning that only this thread will block, rather than the entire
955 process. This wrapper in turn depends on nanosleep() not to block
956 the entire process, but I think (hope? suspect?) that POSIX
957 pthreads guarantees that to be the case.
958
959 Basic idea is: modify the timeout parameter to select so that it
960 returns immediately. Poll like this until select returns non-zero,
961 indicating something interesting happened, or until our time is up.
962 Space out the polls with nanosleeps of say 20 milliseconds, which
963 is required to be nonblocking; this allows other threads to run.
sewardj02535bc2002-04-21 01:08:26 +0000964
965 Assumes:
966 * (checked via assert) types fd_set and vki_fd_set are identical.
967 * (checked via assert) types timeval and vki_timeval are identical.
968 * (unchecked) libc error numbers (EINTR etc) are the negation of the
969 kernel's error numbers (VKI_EINTR etc).
sewardj08a4c3f2002-04-13 03:45:44 +0000970*/
sewardj08a4c3f2002-04-13 03:45:44 +0000971
972
973int select ( int n,
974 fd_set *rfds,
975 fd_set *wfds,
976 fd_set *xfds,
977 struct timeval *timeout )
978{
sewardj5f07b662002-04-23 16:52:51 +0000979 unsigned int ms_now, ms_end;
sewardj08a4c3f2002-04-13 03:45:44 +0000980 int res;
981 fd_set rfds_copy;
982 fd_set wfds_copy;
983 fd_set xfds_copy;
984 struct vki_timeval t_now;
sewardj08a4c3f2002-04-13 03:45:44 +0000985 struct vki_timeval zero_timeout;
986 struct vki_timespec nanosleep_interval;
987
sewardj5f07b662002-04-23 16:52:51 +0000988 /* gcc's complains about ms_end being used uninitialised -- classic
989 case it can't understand, where ms_end is both defined and used
990 only if timeout != NULL. Hence ... */
991 ms_end = 0;
sewardj08a4c3f2002-04-13 03:45:44 +0000992
993 /* We assume that the kernel and libc data layouts are identical
994 for the following types. These asserts provide a crude
995 check. */
996 if (sizeof(fd_set) != sizeof(vki_fd_set)
997 || sizeof(struct timeval) != sizeof(struct vki_timeval))
998 barf("valgrind's hacky non-blocking select(): data sizes error");
999
sewardj5f07b662002-04-23 16:52:51 +00001000 /* Detect the current time and simultaneously find out if we are
1001 running on Valgrind. */
1002 VALGRIND_MAGIC_SEQUENCE(ms_now, 0xFFFFFFFF /* default */,
1003 VG_USERREQ__READ_MILLISECOND_TIMER,
1004 0, 0, 0, 0);
1005
1006 /* If a zero timeout specified, this call is harmless. Also go
1007 this route if we're not running on Valgrind, for whatever
1008 reason. */
1009 if ( (timeout && timeout->tv_sec == 0 && timeout->tv_usec == 0)
1010 || (ms_now == 0xFFFFFFFF) ) {
sewardj02535bc2002-04-21 01:08:26 +00001011 res = do_syscall_select( n, (vki_fd_set*)rfds,
sewardj08a4c3f2002-04-13 03:45:44 +00001012 (vki_fd_set*)wfds,
1013 (vki_fd_set*)xfds,
1014 (struct vki_timeval*)timeout);
sewardj02535bc2002-04-21 01:08:26 +00001015 if (is_kerror(res)) {
1016 * (__errno_location()) = -res;
1017 return -1;
1018 } else {
1019 return res;
1020 }
1021 }
sewardj08a4c3f2002-04-13 03:45:44 +00001022
sewardj5f07b662002-04-23 16:52:51 +00001023 /* If a timeout was specified, set ms_end to be the end millisecond
1024 counter [wallclock] time. */
sewardj08a4c3f2002-04-13 03:45:44 +00001025 if (timeout) {
1026 res = my_do_syscall2(__NR_gettimeofday, (int)&t_now, (int)NULL);
1027 assert(res == 0);
sewardj5f07b662002-04-23 16:52:51 +00001028 ms_end = ms_now;
1029 ms_end += (timeout->tv_usec / 1000);
1030 ms_end += (timeout->tv_sec * 1000);
sewardj08a4c3f2002-04-13 03:45:44 +00001031 /* Stay sane ... */
sewardj5f07b662002-04-23 16:52:51 +00001032 assert (ms_end >= ms_now);
sewardj08a4c3f2002-04-13 03:45:44 +00001033 }
1034
1035 /* fprintf(stderr, "MY_SELECT: before loop\n"); */
1036
1037 /* Either timeout == NULL, meaning wait indefinitely, or timeout !=
sewardj5f07b662002-04-23 16:52:51 +00001038 NULL, in which case ms_end holds the end time. */
sewardj08a4c3f2002-04-13 03:45:44 +00001039 while (1) {
1040 if (timeout) {
sewardj5f07b662002-04-23 16:52:51 +00001041 VALGRIND_MAGIC_SEQUENCE(ms_now, 0xFFFFFFFF /* default */,
1042 VG_USERREQ__READ_MILLISECOND_TIMER,
1043 0, 0, 0, 0);
1044 assert(ms_now != 0xFFFFFFFF);
1045 if (ms_now >= ms_end) {
sewardj08a4c3f2002-04-13 03:45:44 +00001046 /* timeout; nothing interesting happened. */
1047 if (rfds) FD_ZERO(rfds);
1048 if (wfds) FD_ZERO(wfds);
1049 if (xfds) FD_ZERO(xfds);
1050 return 0;
1051 }
1052 }
1053
1054 /* These could be trashed each time round the loop, so restore
1055 them each time. */
1056 if (rfds) rfds_copy = *rfds;
1057 if (wfds) wfds_copy = *wfds;
1058 if (xfds) xfds_copy = *xfds;
1059
1060 zero_timeout.tv_sec = zero_timeout.tv_usec = 0;
1061
1062 res = do_syscall_select( n,
1063 rfds ? (vki_fd_set*)(&rfds_copy) : NULL,
1064 wfds ? (vki_fd_set*)(&wfds_copy) : NULL,
1065 xfds ? (vki_fd_set*)(&xfds_copy) : NULL,
1066 & zero_timeout );
sewardj02535bc2002-04-21 01:08:26 +00001067 if (is_kerror(res)) {
1068 /* Some kind of error (including EINTR). Set errno and
sewardj08a4c3f2002-04-13 03:45:44 +00001069 return. The sets are unspecified in this case. */
sewardj02535bc2002-04-21 01:08:26 +00001070 * (__errno_location()) = -res;
1071 return -1;
sewardj08a4c3f2002-04-13 03:45:44 +00001072 }
1073 if (res > 0) {
1074 /* one or more fds is ready. Copy out resulting sets and
1075 return. */
1076 if (rfds) *rfds = rfds_copy;
1077 if (wfds) *wfds = wfds_copy;
1078 if (xfds) *xfds = xfds_copy;
1079 return res;
1080 }
1081 /* fprintf(stderr, "MY_SELECT: nanosleep\n"); */
1082 /* nanosleep and go round again */
sewardj02535bc2002-04-21 01:08:26 +00001083 nanosleep_interval.tv_sec = 0;
sewardj956cc1b2002-04-25 01:33:50 +00001084 nanosleep_interval.tv_nsec = 50 * 1000 * 1000; /* 50 milliseconds */
sewardjf854f472002-04-21 12:19:41 +00001085 /* It's critical here that valgrind's nanosleep implementation
1086 is nonblocking. */
1087 (void)my_do_syscall2(__NR_nanosleep,
1088 (int)(&nanosleep_interval), (int)NULL);
1089 }
1090}
1091
1092
1093
1094
1095#include <sys/poll.h>
1096
sewardj72d58482002-04-24 02:20:20 +00001097#ifdef GLIBC_2_1
1098typedef unsigned long int nfds_t;
1099#endif
1100
sewardjf854f472002-04-21 12:19:41 +00001101int poll (struct pollfd *__fds, nfds_t __nfds, int __timeout)
1102{
sewardj5f07b662002-04-23 16:52:51 +00001103 unsigned int ms_now, ms_end;
sewardjf854f472002-04-21 12:19:41 +00001104 int res, i;
sewardjf854f472002-04-21 12:19:41 +00001105 struct vki_timespec nanosleep_interval;
1106
1107 ensure_valgrind("poll");
1108
sewardj5f07b662002-04-23 16:52:51 +00001109 /* Detect the current time and simultaneously find out if we are
1110 running on Valgrind. */
1111 VALGRIND_MAGIC_SEQUENCE(ms_now, 0xFFFFFFFF /* default */,
1112 VG_USERREQ__READ_MILLISECOND_TIMER,
1113 0, 0, 0, 0);
1114
sewardjf854f472002-04-21 12:19:41 +00001115 if (/* CHECK SIZES FOR struct pollfd */
1116 sizeof(struct timeval) != sizeof(struct vki_timeval))
1117 barf("valgrind's hacky non-blocking poll(): data sizes error");
1118
sewardj5f07b662002-04-23 16:52:51 +00001119 /* dummy initialisation to keep gcc -Wall happy */
1120 ms_end = 0;
1121
1122 /* If a zero timeout specified, this call is harmless. Also do
1123 this if not running on Valgrind. */
1124 if (__timeout == 0 || ms_now == 0xFFFFFFFF) {
sewardjf854f472002-04-21 12:19:41 +00001125 res = my_do_syscall3(__NR_poll, (int)__fds, __nfds, __timeout);
1126 if (is_kerror(res)) {
1127 * (__errno_location()) = -res;
1128 return -1;
1129 } else {
1130 return res;
1131 }
1132 }
1133
sewardj5f07b662002-04-23 16:52:51 +00001134 /* If a timeout was specified, set ms_end to be the end wallclock
1135 time. Easy considering that __timeout is in milliseconds. */
sewardjf854f472002-04-21 12:19:41 +00001136 if (__timeout > 0) {
sewardj5f07b662002-04-23 16:52:51 +00001137 ms_end += (unsigned int)__timeout;
sewardjf854f472002-04-21 12:19:41 +00001138 }
1139
1140 /* fprintf(stderr, "MY_POLL: before loop\n"); */
1141
1142 /* Either timeout < 0, meaning wait indefinitely, or timeout > 0,
1143 in which case t_end holds the end time. */
sewardj5f07b662002-04-23 16:52:51 +00001144 assert(__timeout != 0);
1145
sewardjf854f472002-04-21 12:19:41 +00001146 while (1) {
sewardjf854f472002-04-21 12:19:41 +00001147 if (__timeout > 0) {
sewardj5f07b662002-04-23 16:52:51 +00001148 VALGRIND_MAGIC_SEQUENCE(ms_now, 0xFFFFFFFF /* default */,
1149 VG_USERREQ__READ_MILLISECOND_TIMER,
1150 0, 0, 0, 0);
1151 assert(ms_now != 0xFFFFFFFF);
1152 if (ms_now >= ms_end) {
sewardjf854f472002-04-21 12:19:41 +00001153 /* timeout; nothing interesting happened. */
1154 for (i = 0; i < __nfds; i++)
1155 __fds[i].revents = 0;
1156 return 0;
1157 }
1158 }
1159
sewardj5f07b662002-04-23 16:52:51 +00001160 /* Do a return-immediately poll. */
sewardjf854f472002-04-21 12:19:41 +00001161 res = my_do_syscall3(__NR_poll, (int)__fds, __nfds, 0 );
1162 if (is_kerror(res)) {
1163 /* Some kind of error. Set errno and return. */
1164 * (__errno_location()) = -res;
1165 return -1;
1166 }
1167 if (res > 0) {
1168 /* One or more fds is ready. Return now. */
1169 return res;
1170 }
1171 /* fprintf(stderr, "MY_POLL: nanosleep\n"); */
1172 /* nanosleep and go round again */
1173 nanosleep_interval.tv_sec = 0;
sewardj956cc1b2002-04-25 01:33:50 +00001174 nanosleep_interval.tv_nsec = 51 * 1000 * 1000; /* 51 milliseconds */
sewardj08a4c3f2002-04-13 03:45:44 +00001175 /* It's critical here that valgrind's nanosleep implementation
1176 is nonblocking. */
1177 (void)my_do_syscall2(__NR_nanosleep,
1178 (int)(&nanosleep_interval), (int)NULL);
1179 }
1180}
sewardj3b13f0e2002-04-25 20:17:29 +00001181
1182
1183/* ---------------------------------------------------------------------
1184 B'stard.
1185 ------------------------------------------------------------------ */
1186
1187# define strong_alias(name, aliasname) \
1188 extern __typeof (name) aliasname __attribute__ ((alias (#name)));
1189
1190strong_alias(pthread_mutex_lock, __pthread_mutex_lock)
sewardj853f55d2002-04-26 00:27:53 +00001191strong_alias(pthread_mutex_trylock, __pthread_mutex_trylock)
sewardj3b13f0e2002-04-25 20:17:29 +00001192strong_alias(pthread_mutex_unlock, __pthread_mutex_unlock)
1193strong_alias(pthread_mutexattr_init, __pthread_mutexattr_init)
1194strong_alias(pthread_mutexattr_settype, __pthread_mutexattr_settype)
1195strong_alias(pthread_mutex_init, __pthread_mutex_init)
1196strong_alias(pthread_mutexattr_destroy, __pthread_mutexattr_destroy)
1197strong_alias(pthread_mutex_destroy, __pthread_mutex_destroy)
1198strong_alias(pthread_once, __pthread_once)
sewardj853f55d2002-04-26 00:27:53 +00001199strong_alias(pthread_atfork, __pthread_atfork)
sewardj3b13f0e2002-04-25 20:17:29 +00001200
sewardj853f55d2002-04-26 00:27:53 +00001201strong_alias(fork, __fork)
sewardj3b13f0e2002-04-25 20:17:29 +00001202strong_alias(close, __close)
1203strong_alias(write, __write)
1204strong_alias(read, __read)
1205strong_alias(open, __open)
1206strong_alias(sigaction, __sigaction)
1207
1208strong_alias(pthread_key_create, __pthread_key_create)
1209strong_alias(pthread_getspecific, __pthread_getspecific)
1210strong_alias(pthread_setspecific, __pthread_setspecific)
1211strong_alias(open64, __open64)
1212strong_alias(fcntl, __fcntl)
1213strong_alias(connect, __connect)
1214
1215/*--------------------------------------------------*/
1216
1217/* I've no idea what these are, but they get called quite a lot.
1218 Anybody know? */
1219
1220#undef _IO_flockfile
1221void _IO_flockfile ( _IO_FILE * file )
1222{
sewardj853f55d2002-04-26 00:27:53 +00001223 //char* str = "_IO_flockfile\n";
1224 //write(2, str, strlen(str));
1225 pthread_mutex_lock(file->_lock);
sewardj3b13f0e2002-04-25 20:17:29 +00001226 // barf("_IO_flockfile");
1227}
1228
1229#undef _IO_funlockfile
1230void _IO_funlockfile ( _IO_FILE * file )
1231{
sewardj853f55d2002-04-26 00:27:53 +00001232 //char* str = "_IO_funlockfile\n";
1233 //write(2, str, strlen(str));
1234 pthread_mutex_unlock(file->_lock);
sewardj3b13f0e2002-04-25 20:17:29 +00001235 // barf("_IO_funlockfile");
1236}
1237
1238void _pthread_cleanup_push_defer ( void )
1239{
1240 // char* str = "_pthread_cleanup_push_defer\n";
1241 // write(2, str, strlen(str));
1242}
1243
1244void _pthread_cleanup_pop_restore ( void )
1245{
1246 // char* str = "_pthread_cleanup_pop_restore\n";
1247 // write(2, str, strlen(str));
1248}