blob: 370acec334262fcdf7ad78a5e0fa9b46ace0ab15 [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
sewardjf8f819e2002-04-17 23:21:37 +0000262/* ---------------------------------------------------
263 MUTEX ATTRIBUTES
264 ------------------------------------------------ */
265
sewardje663cb92002-04-12 10:26:32 +0000266int pthread_mutexattr_init(pthread_mutexattr_t *attr)
267{
sewardjf8f819e2002-04-17 23:21:37 +0000268 attr->__mutexkind = PTHREAD_MUTEX_ERRORCHECK_NP;
sewardj8937c812002-04-12 20:12:20 +0000269 return 0;
sewardje663cb92002-04-12 10:26:32 +0000270}
271
sewardjf8f819e2002-04-17 23:21:37 +0000272int pthread_mutexattr_settype(pthread_mutexattr_t *attr, int type)
273{
274 switch (type) {
sewardj3b13f0e2002-04-25 20:17:29 +0000275# ifndef GLIBC_2_1
sewardjf8f819e2002-04-17 23:21:37 +0000276 case PTHREAD_MUTEX_TIMED_NP:
sewardj2a1dcce2002-04-22 12:45:25 +0000277 case PTHREAD_MUTEX_ADAPTIVE_NP:
sewardj3b13f0e2002-04-25 20:17:29 +0000278# endif
sewardjf8f819e2002-04-17 23:21:37 +0000279 case PTHREAD_MUTEX_RECURSIVE_NP:
280 case PTHREAD_MUTEX_ERRORCHECK_NP:
sewardjf8f819e2002-04-17 23:21:37 +0000281 attr->__mutexkind = type;
282 return 0;
283 default:
284 return EINVAL;
285 }
286}
287
288int pthread_mutexattr_destroy(pthread_mutexattr_t *attr)
289{
290 return 0;
291}
292
293
294/* ---------------------------------------------------
295 MUTEXes
296 ------------------------------------------------ */
297
sewardje663cb92002-04-12 10:26:32 +0000298int pthread_mutex_init(pthread_mutex_t *mutex,
299 const pthread_mutexattr_t *mutexattr)
300{
sewardj604ec3c2002-04-18 22:38:41 +0000301 mutex->__m_count = 0;
302 mutex->__m_owner = (_pthread_descr)VG_INVALID_THREADID;
303 mutex->__m_kind = PTHREAD_MUTEX_ERRORCHECK_NP;
304 if (mutexattr)
305 mutex->__m_kind = mutexattr->__mutexkind;
306 return 0;
sewardje663cb92002-04-12 10:26:32 +0000307}
308
sewardje663cb92002-04-12 10:26:32 +0000309int pthread_mutex_lock(pthread_mutex_t *mutex)
310{
311 int res;
sewardj604ec3c2002-04-18 22:38:41 +0000312 static int moans = 3;
sewardj45b4b372002-04-16 22:50:32 +0000313 if (!(RUNNING_ON_VALGRIND) && moans-- > 0) {
sewardje663cb92002-04-12 10:26:32 +0000314 char* str = "pthread_mutex_lock-NOT-INSIDE-VALGRIND\n";
315 write(2, str, strlen(str));
316 return 0;
317 } else {
318 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
319 VG_USERREQ__PTHREAD_MUTEX_LOCK,
320 mutex, 0, 0, 0);
321 return res;
322 }
323}
324
sewardj30671ff2002-04-21 00:13:57 +0000325int pthread_mutex_trylock(pthread_mutex_t *mutex)
326{
327 int res;
328 static int moans = 3;
329 if (!(RUNNING_ON_VALGRIND) && moans-- > 0) {
330 char* str = "pthread_mutex_trylock-NOT-INSIDE-VALGRIND\n";
331 write(2, str, strlen(str));
332 return 0;
333 } else {
334 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
335 VG_USERREQ__PTHREAD_MUTEX_TRYLOCK,
336 mutex, 0, 0, 0);
337 return res;
338 }
339}
340
sewardje663cb92002-04-12 10:26:32 +0000341int pthread_mutex_unlock(pthread_mutex_t *mutex)
342{
343 int res;
sewardj604ec3c2002-04-18 22:38:41 +0000344 static int moans = 3;
sewardj45b4b372002-04-16 22:50:32 +0000345 if (!(RUNNING_ON_VALGRIND) && moans-- > 0) {
sewardje663cb92002-04-12 10:26:32 +0000346 char* str = "pthread_mutex_unlock-NOT-INSIDE-VALGRIND\n";
347 write(2, str, strlen(str));
348 return 0;
349 } else {
350 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
351 VG_USERREQ__PTHREAD_MUTEX_UNLOCK,
352 mutex, 0, 0, 0);
353 return res;
354 }
355}
356
sewardje663cb92002-04-12 10:26:32 +0000357int pthread_mutex_destroy(pthread_mutex_t *mutex)
358{
sewardj604ec3c2002-04-18 22:38:41 +0000359 /* Valgrind doesn't hold any resources on behalf of the mutex, so no
360 need to involve it. */
361 if (mutex->__m_count > 0)
362 return EBUSY;
sewardj6072c362002-04-19 14:40:57 +0000363 mutex->__m_count = 0;
364 mutex->__m_owner = (_pthread_descr)VG_INVALID_THREADID;
365 mutex->__m_kind = PTHREAD_MUTEX_ERRORCHECK_NP;
sewardj604ec3c2002-04-18 22:38:41 +0000366 return 0;
sewardje663cb92002-04-12 10:26:32 +0000367}
368
369
sewardjf8f819e2002-04-17 23:21:37 +0000370/* ---------------------------------------------------
sewardj6072c362002-04-19 14:40:57 +0000371 CONDITION VARIABLES
372 ------------------------------------------------ */
373
374/* LinuxThreads supports no attributes for conditions. Hence ... */
375
376int pthread_condattr_init(pthread_condattr_t *attr)
377{
378 return 0;
379}
380
sewardj0738a592002-04-20 13:59:33 +0000381int pthread_condattr_destroy(pthread_condattr_t *attr)
382{
383 return 0;
384}
sewardj6072c362002-04-19 14:40:57 +0000385
386int pthread_cond_init( pthread_cond_t *cond,
387 const pthread_condattr_t *cond_attr)
388{
389 cond->__c_waiting = (_pthread_descr)VG_INVALID_THREADID;
390 return 0;
391}
392
sewardjf854f472002-04-21 12:19:41 +0000393int pthread_cond_destroy(pthread_cond_t *cond)
394{
395 /* should check that no threads are waiting on this CV */
396 kludged("pthread_cond_destroy");
397 return 0;
398}
sewardj6072c362002-04-19 14:40:57 +0000399
400/* ---------------------------------------------------
401 SCHEDULING
402 ------------------------------------------------ */
403
404/* This is completely bogus. */
405int pthread_getschedparam(pthread_t target_thread,
406 int *policy,
407 struct sched_param *param)
408{
sewardj30671ff2002-04-21 00:13:57 +0000409 kludged("pthread_getschedparam");
sewardj6072c362002-04-19 14:40:57 +0000410 if (policy) *policy = SCHED_OTHER;
sewardj2a1dcce2002-04-22 12:45:25 +0000411# ifdef GLIBC_2_1
412 if (param) param->sched_priority = 0; /* who knows */
413# else
sewardj6072c362002-04-19 14:40:57 +0000414 if (param) param->__sched_priority = 0; /* who knows */
sewardj2a1dcce2002-04-22 12:45:25 +0000415# endif
sewardj6072c362002-04-19 14:40:57 +0000416 return 0;
417}
418
419int pthread_setschedparam(pthread_t target_thread,
420 int policy,
421 const struct sched_param *param)
422{
423 ignored("pthread_setschedparam");
424 return 0;
425}
426
sewardj3b5d8862002-04-20 13:53:23 +0000427int pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex)
428{
429 int res;
430 ensure_valgrind("pthread_cond_wait");
431 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
432 VG_USERREQ__PTHREAD_COND_WAIT,
433 cond, mutex, 0, 0);
434 return res;
435}
436
sewardj5f07b662002-04-23 16:52:51 +0000437int pthread_cond_timedwait ( pthread_cond_t *cond,
438 pthread_mutex_t *mutex,
439 const struct timespec *abstime )
440{
441 int res;
442 unsigned int ms_now, ms_end;
443 struct timeval timeval_now;
444 unsigned long long int ull_ms_now_after_1970;
445 unsigned long long int ull_ms_end_after_1970;
446
447 ensure_valgrind("pthread_cond_timedwait");
448 VALGRIND_MAGIC_SEQUENCE(ms_now, 0xFFFFFFFF /* default */,
449 VG_USERREQ__READ_MILLISECOND_TIMER,
450 0, 0, 0, 0);
451 assert(ms_now != 0xFFFFFFFF);
452 res = gettimeofday(&timeval_now, NULL);
453 assert(res == 0);
454
455 ull_ms_now_after_1970
456 = 1000ULL * ((unsigned long long int)(timeval_now.tv_sec))
457 + ((unsigned long long int)(timeval_now.tv_usec / 1000000));
458 ull_ms_end_after_1970
459 = 1000ULL * ((unsigned long long int)(abstime->tv_sec))
460 + ((unsigned long long int)(abstime->tv_nsec / 1000000));
461 assert(ull_ms_end_after_1970 >= ull_ms_now_after_1970);
462 ms_end
463 = ms_now + (unsigned int)(ull_ms_end_after_1970 - ull_ms_now_after_1970);
464 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
465 VG_USERREQ__PTHREAD_COND_TIMEDWAIT,
466 cond, mutex, ms_end, 0);
467 return res;
468}
469
470
sewardj3b5d8862002-04-20 13:53:23 +0000471int pthread_cond_signal(pthread_cond_t *cond)
472{
473 int res;
474 ensure_valgrind("pthread_cond_signal");
475 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
476 VG_USERREQ__PTHREAD_COND_SIGNAL,
477 cond, 0, 0, 0);
478 return res;
479}
480
481int pthread_cond_broadcast(pthread_cond_t *cond)
482{
483 int res;
484 ensure_valgrind("pthread_cond_broadcast");
485 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
486 VG_USERREQ__PTHREAD_COND_BROADCAST,
487 cond, 0, 0, 0);
488 return res;
489}
490
sewardj6072c362002-04-19 14:40:57 +0000491
492/* ---------------------------------------------------
sewardjf8f819e2002-04-17 23:21:37 +0000493 CANCELLATION
494 ------------------------------------------------ */
495
sewardje663cb92002-04-12 10:26:32 +0000496int pthread_setcanceltype(int type, int *oldtype)
497{
sewardj2a3d28c2002-04-14 13:27:00 +0000498 ignored("pthread_setcanceltype");
sewardje663cb92002-04-12 10:26:32 +0000499 return 0;
500}
501
502
503int pthread_cancel(pthread_t thread)
504{
505 int res;
506 ensure_valgrind("pthread_cancel");
507 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
508 VG_USERREQ__PTHREAD_CANCEL,
509 thread, 0, 0, 0);
510 return res;
511}
512
513
sewardjf8f819e2002-04-17 23:21:37 +0000514/* ---------------------------------------------------
515 THREAD-SPECIFICs
516 ------------------------------------------------ */
sewardj5e5fa512002-04-14 13:13:05 +0000517
518int pthread_key_create(pthread_key_t *key,
519 void (*destr_function) (void *))
520{
sewardj5f07b662002-04-23 16:52:51 +0000521 int res;
522 ensure_valgrind("pthread_key_create");
523 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
524 VG_USERREQ__PTHREAD_KEY_CREATE,
525 key, destr_function, 0, 0);
526 return res;
sewardj5e5fa512002-04-14 13:13:05 +0000527}
528
529int pthread_key_delete(pthread_key_t key)
530{
sewardj2a3d28c2002-04-14 13:27:00 +0000531 ignored("pthread_key_delete");
sewardj5e5fa512002-04-14 13:13:05 +0000532 return 0;
533}
534
535int pthread_setspecific(pthread_key_t key, const void *pointer)
536{
sewardj5f07b662002-04-23 16:52:51 +0000537 int res;
538 ensure_valgrind("pthread_setspecific");
539 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
540 VG_USERREQ__PTHREAD_SETSPECIFIC,
541 key, pointer, 0, 0);
542 return res;
sewardj5e5fa512002-04-14 13:13:05 +0000543}
544
545void * pthread_getspecific(pthread_key_t key)
546{
sewardj5f07b662002-04-23 16:52:51 +0000547 int res;
548 ensure_valgrind("pthread_getspecific");
549 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
550 VG_USERREQ__PTHREAD_GETSPECIFIC,
551 key, 0 , 0, 0);
552 return (void*)res;
sewardj5e5fa512002-04-14 13:13:05 +0000553}
554
sewardjf8f819e2002-04-17 23:21:37 +0000555
556/* ---------------------------------------------------
sewardj89d3d852002-04-24 19:21:39 +0000557 ONCEry
558 ------------------------------------------------ */
559
560static pthread_mutex_t once_masterlock = PTHREAD_MUTEX_INITIALIZER;
561
562
563int pthread_once ( pthread_once_t *once_control,
564 void (*init_routine) (void) )
565{
566 int res;
567 ensure_valgrind("pthread_once");
568
569 res = pthread_mutex_lock(&once_masterlock);
570
571 if (res != 0)
572 barf("pthread_once: Looks like your program's "
573 "init routine calls back to pthread_once() ?!");
574
575 if (*once_control == 0) {
576 *once_control = 1;
577 init_routine();
578 }
579
580 pthread_mutex_unlock(&once_masterlock);
581
582 return 0;
583}
584
585
586/* ---------------------------------------------------
sewardj3b13f0e2002-04-25 20:17:29 +0000587 LIBRARY-PRIVATE THREAD SPECIFIC STATE
sewardjf8f819e2002-04-17 23:21:37 +0000588 ------------------------------------------------ */
589
sewardj3b13f0e2002-04-25 20:17:29 +0000590#include <resolv.h>
591static int thread_specific_errno[VG_N_THREADS];
592static int thread_specific_h_errno[VG_N_THREADS];
593static struct __res_state
594 thread_specific_res_state[VG_N_THREADS];
sewardjf8f819e2002-04-17 23:21:37 +0000595
sewardj3b13f0e2002-04-25 20:17:29 +0000596int* __errno_location ( void )
sewardjf8f819e2002-04-17 23:21:37 +0000597{
598 int tid;
sewardj3b13f0e2002-04-25 20:17:29 +0000599 /* ensure_valgrind("__errno_location"); */
600 VALGRIND_MAGIC_SEQUENCE(tid, 1 /* default */,
sewardjf8f819e2002-04-17 23:21:37 +0000601 VG_USERREQ__PTHREAD_GET_THREADID,
602 0, 0, 0, 0);
sewardj3b13f0e2002-04-25 20:17:29 +0000603 /* 'cos I'm paranoid ... */
sewardjf8f819e2002-04-17 23:21:37 +0000604 if (tid < 0 || tid >= VG_N_THREADS)
sewardj3b13f0e2002-04-25 20:17:29 +0000605 barf("__errno_location: invalid ThreadId");
606 return & thread_specific_errno[tid];
607}
608
609int* __h_errno_location ( void )
610{
611 int tid;
612 /* ensure_valgrind("__h_errno_location"); */
613 VALGRIND_MAGIC_SEQUENCE(tid, 1 /* default */,
614 VG_USERREQ__PTHREAD_GET_THREADID,
615 0, 0, 0, 0);
616 /* 'cos I'm paranoid ... */
617 if (tid < 0 || tid >= VG_N_THREADS)
618 barf("__h_errno_location: invalid ThreadId");
619 return & thread_specific_h_errno[tid];
620}
621
622struct __res_state* __res_state ( void )
623{
624 int tid;
625 /* ensure_valgrind("__res_state"); */
626 VALGRIND_MAGIC_SEQUENCE(tid, 1 /* default */,
627 VG_USERREQ__PTHREAD_GET_THREADID,
628 0, 0, 0, 0);
629 /* 'cos I'm paranoid ... */
630 if (tid < 0 || tid >= VG_N_THREADS)
631 barf("__res_state: invalid ThreadId");
632 return & thread_specific_res_state[tid];
sewardjf8f819e2002-04-17 23:21:37 +0000633}
634
635
sewardje663cb92002-04-12 10:26:32 +0000636/* ---------------------------------------------------------------------
637 These are here (I think) because they are deemed cancellation
638 points by POSIX. For the moment we'll simply pass the call along
639 to the corresponding thread-unaware (?) libc routine.
640 ------------------------------------------------------------------ */
641
sewardje663cb92002-04-12 10:26:32 +0000642#include <stdlib.h>
643#include <signal.h>
sewardje663cb92002-04-12 10:26:32 +0000644#include <sys/types.h>
645#include <sys/socket.h>
646
647extern
648int __libc_sigaction
649 (int signum,
650 const struct sigaction *act,
651 struct sigaction *oldact);
652int sigaction(int signum,
653 const struct sigaction *act,
654 struct sigaction *oldact)
655{
sewardj2a1dcce2002-04-22 12:45:25 +0000656# ifdef GLIBC_2_1
657 return __sigaction(signum, act, oldact);
658# else
sewardj45b4b372002-04-16 22:50:32 +0000659 return __libc_sigaction(signum, act, oldact);
sewardj2a1dcce2002-04-22 12:45:25 +0000660# endif
sewardje663cb92002-04-12 10:26:32 +0000661}
662
663
664extern
665int __libc_connect(int sockfd,
666 const struct sockaddr *serv_addr,
667 socklen_t addrlen);
668int connect(int sockfd,
669 const struct sockaddr *serv_addr,
670 socklen_t addrlen)
671{
sewardj45b4b372002-04-16 22:50:32 +0000672 return __libc_connect(sockfd, serv_addr, addrlen);
sewardje663cb92002-04-12 10:26:32 +0000673}
674
675
676extern
677int __libc_fcntl(int fd, int cmd, long arg);
678int fcntl(int fd, int cmd, long arg)
679{
sewardj45b4b372002-04-16 22:50:32 +0000680 return __libc_fcntl(fd, cmd, arg);
sewardje663cb92002-04-12 10:26:32 +0000681}
682
683
684extern
685ssize_t __libc_write(int fd, const void *buf, size_t count);
686ssize_t write(int fd, const void *buf, size_t count)
687{
sewardj45b4b372002-04-16 22:50:32 +0000688 return __libc_write(fd, buf, count);
sewardje663cb92002-04-12 10:26:32 +0000689}
690
691
692extern
693ssize_t __libc_read(int fd, void *buf, size_t count);
694ssize_t read(int fd, void *buf, size_t count)
695{
sewardj45b4b372002-04-16 22:50:32 +0000696 return __libc_read(fd, buf, count);
sewardje663cb92002-04-12 10:26:32 +0000697}
698
sewardjbe32e452002-04-24 20:29:58 +0000699
700extern
701int __libc_open64(const char *pathname, int flags, ...);
702int open64(const char *pathname, int flags, ...)
703{
704 return __libc_open64(pathname, flags);
705}
706
sewardje663cb92002-04-12 10:26:32 +0000707
708extern
709int __libc_open(const char *pathname, int flags);
710int open(const char *pathname, int flags)
711{
sewardj45b4b372002-04-16 22:50:32 +0000712 return __libc_open(pathname, flags);
sewardje663cb92002-04-12 10:26:32 +0000713}
714
715
716extern
717int __libc_close(int fd);
718int close(int fd)
719{
sewardj45b4b372002-04-16 22:50:32 +0000720 return __libc_close(fd);
sewardje663cb92002-04-12 10:26:32 +0000721}
722
723
724extern
725int __libc_accept(int s, struct sockaddr *addr, socklen_t *addrlen);
726int accept(int s, struct sockaddr *addr, socklen_t *addrlen)
727{
sewardj45b4b372002-04-16 22:50:32 +0000728 return __libc_accept(s, addr, addrlen);
sewardje663cb92002-04-12 10:26:32 +0000729}
730
731
732extern
733pid_t __libc_fork(void);
734pid_t fork(void)
735{
sewardj45b4b372002-04-16 22:50:32 +0000736 return __libc_fork();
sewardje663cb92002-04-12 10:26:32 +0000737}
738
739
740extern
741pid_t __libc_waitpid(pid_t pid, int *status, int options);
742pid_t waitpid(pid_t pid, int *status, int options)
743{
sewardj45b4b372002-04-16 22:50:32 +0000744 return __libc_waitpid(pid, status, options);
sewardje663cb92002-04-12 10:26:32 +0000745}
746
747
748extern
749int __libc_nanosleep(const struct timespec *req, struct timespec *rem);
750int nanosleep(const struct timespec *req, struct timespec *rem)
751{
752 return __libc_nanosleep(req, rem);
753}
754
sewardjbe32e452002-04-24 20:29:58 +0000755
sewardje663cb92002-04-12 10:26:32 +0000756extern
757int __libc_fsync(int fd);
758int fsync(int fd)
759{
sewardj45b4b372002-04-16 22:50:32 +0000760 return __libc_fsync(fd);
sewardje663cb92002-04-12 10:26:32 +0000761}
762
sewardjbe32e452002-04-24 20:29:58 +0000763
sewardj70c75362002-04-13 04:18:32 +0000764extern
765off_t __libc_lseek(int fildes, off_t offset, int whence);
766off_t lseek(int fildes, off_t offset, int whence)
767{
sewardj45b4b372002-04-16 22:50:32 +0000768 return __libc_lseek(fildes, offset, whence);
sewardj70c75362002-04-13 04:18:32 +0000769}
770
sewardjbe32e452002-04-24 20:29:58 +0000771
772extern
773__off64_t __libc_lseek64(int fildes, __off64_t offset, int whence);
774__off64_t lseek64(int fildes, __off64_t offset, int whence)
775{
776 return __libc_lseek64(fildes, offset, whence);
777}
778
779
sewardj6af4b5d2002-04-16 04:40:49 +0000780extern
781void __libc_longjmp(jmp_buf env, int val) __attribute((noreturn));
782void longjmp(jmp_buf env, int val)
783{
784 __libc_longjmp(env, val);
785}
786
sewardjbe32e452002-04-24 20:29:58 +0000787
sewardj6af4b5d2002-04-16 04:40:49 +0000788extern
789int __libc_send(int s, const void *msg, size_t len, int flags);
790int send(int s, const void *msg, size_t len, int flags)
791{
792 return __libc_send(s, msg, len, flags);
793}
794
sewardjbe32e452002-04-24 20:29:58 +0000795
sewardj1e8cdc92002-04-18 11:37:52 +0000796extern
797int __libc_recv(int s, void *buf, size_t len, int flags);
798int recv(int s, void *buf, size_t len, int flags)
799{
800 return __libc_recv(s, buf, len, flags);
801}
802
sewardjbe32e452002-04-24 20:29:58 +0000803
sewardj796d6a22002-04-24 02:28:34 +0000804extern
805int __libc_sendto(int s, const void *msg, size_t len, int flags,
806 const struct sockaddr *to, socklen_t tolen);
807int sendto(int s, const void *msg, size_t len, int flags,
808 const struct sockaddr *to, socklen_t tolen)
809{
810 return __libc_sendto(s, msg, len, flags, to, tolen);
811}
812
sewardjbe32e452002-04-24 20:29:58 +0000813
sewardj369b1702002-04-24 13:28:15 +0000814extern
815int __libc_system(const char* str);
816int system(const char* str)
817{
818 return __libc_system(str);
819}
820
sewardjbe32e452002-04-24 20:29:58 +0000821
sewardjab0b1c32002-04-24 19:26:47 +0000822extern
823pid_t __libc_wait(int *status);
824pid_t wait(int *status)
825{
826 return __libc_wait(status);
827}
828
sewardj45b4b372002-04-16 22:50:32 +0000829
sewardj3b13f0e2002-04-25 20:17:29 +0000830/* ---------------------------------------------------------------------
831 Nonblocking implementations of select() and poll(). This stuff will
832 surely rot your mind.
833 ------------------------------------------------------------------ */
sewardje663cb92002-04-12 10:26:32 +0000834
sewardj08a4c3f2002-04-13 03:45:44 +0000835/*--------------------------------------------------*/
836
837#include "vg_kerneliface.h"
838
839static
840__inline__
841int is_kerror ( int res )
842{
843 if (res >= -4095 && res <= -1)
844 return 1;
845 else
846 return 0;
847}
848
849
850static
851int my_do_syscall1 ( int syscallno, int arg1 )
852{
853 int __res;
854 __asm__ volatile ("pushl %%ebx; movl %%edx,%%ebx ; int $0x80 ; popl %%ebx"
855 : "=a" (__res)
856 : "0" (syscallno),
857 "d" (arg1) );
858 return __res;
859}
860
861static
862int my_do_syscall2 ( int syscallno,
sewardjf854f472002-04-21 12:19:41 +0000863 int arg1, int arg2 )
sewardj08a4c3f2002-04-13 03:45:44 +0000864{
865 int __res;
866 __asm__ volatile ("pushl %%ebx; movl %%edx,%%ebx ; int $0x80 ; popl %%ebx"
867 : "=a" (__res)
868 : "0" (syscallno),
869 "d" (arg1),
870 "c" (arg2) );
871 return __res;
872}
873
874static
sewardjf854f472002-04-21 12:19:41 +0000875int my_do_syscall3 ( int syscallno,
876 int arg1, int arg2, int arg3 )
877{
878 int __res;
879 __asm__ volatile ("pushl %%ebx; movl %%esi,%%ebx ; int $0x80 ; popl %%ebx"
880 : "=a" (__res)
881 : "0" (syscallno),
882 "S" (arg1),
883 "c" (arg2),
884 "d" (arg3) );
885 return __res;
886}
887
888static
sewardj08a4c3f2002-04-13 03:45:44 +0000889int do_syscall_select( int n,
890 vki_fd_set* readfds,
891 vki_fd_set* writefds,
892 vki_fd_set* exceptfds,
893 struct vki_timeval * timeout )
894{
895 int res;
896 int args[5];
897 args[0] = n;
898 args[1] = (int)readfds;
899 args[2] = (int)writefds;
900 args[3] = (int)exceptfds;
901 args[4] = (int)timeout;
902 res = my_do_syscall1(__NR_select, (int)(&(args[0])) );
sewardj02535bc2002-04-21 01:08:26 +0000903 return res;
sewardj08a4c3f2002-04-13 03:45:44 +0000904}
905
906
907/* This is a wrapper round select(), which makes it thread-safe,
908 meaning that only this thread will block, rather than the entire
909 process. This wrapper in turn depends on nanosleep() not to block
910 the entire process, but I think (hope? suspect?) that POSIX
911 pthreads guarantees that to be the case.
912
913 Basic idea is: modify the timeout parameter to select so that it
914 returns immediately. Poll like this until select returns non-zero,
915 indicating something interesting happened, or until our time is up.
916 Space out the polls with nanosleeps of say 20 milliseconds, which
917 is required to be nonblocking; this allows other threads to run.
sewardj02535bc2002-04-21 01:08:26 +0000918
919 Assumes:
920 * (checked via assert) types fd_set and vki_fd_set are identical.
921 * (checked via assert) types timeval and vki_timeval are identical.
922 * (unchecked) libc error numbers (EINTR etc) are the negation of the
923 kernel's error numbers (VKI_EINTR etc).
sewardj08a4c3f2002-04-13 03:45:44 +0000924*/
sewardj08a4c3f2002-04-13 03:45:44 +0000925
926
927int select ( int n,
928 fd_set *rfds,
929 fd_set *wfds,
930 fd_set *xfds,
931 struct timeval *timeout )
932{
sewardj5f07b662002-04-23 16:52:51 +0000933 unsigned int ms_now, ms_end;
sewardj08a4c3f2002-04-13 03:45:44 +0000934 int res;
935 fd_set rfds_copy;
936 fd_set wfds_copy;
937 fd_set xfds_copy;
938 struct vki_timeval t_now;
sewardj08a4c3f2002-04-13 03:45:44 +0000939 struct vki_timeval zero_timeout;
940 struct vki_timespec nanosleep_interval;
941
sewardj5f07b662002-04-23 16:52:51 +0000942 /* gcc's complains about ms_end being used uninitialised -- classic
943 case it can't understand, where ms_end is both defined and used
944 only if timeout != NULL. Hence ... */
945 ms_end = 0;
sewardj08a4c3f2002-04-13 03:45:44 +0000946
947 /* We assume that the kernel and libc data layouts are identical
948 for the following types. These asserts provide a crude
949 check. */
950 if (sizeof(fd_set) != sizeof(vki_fd_set)
951 || sizeof(struct timeval) != sizeof(struct vki_timeval))
952 barf("valgrind's hacky non-blocking select(): data sizes error");
953
sewardj5f07b662002-04-23 16:52:51 +0000954 /* Detect the current time and simultaneously find out if we are
955 running on Valgrind. */
956 VALGRIND_MAGIC_SEQUENCE(ms_now, 0xFFFFFFFF /* default */,
957 VG_USERREQ__READ_MILLISECOND_TIMER,
958 0, 0, 0, 0);
959
960 /* If a zero timeout specified, this call is harmless. Also go
961 this route if we're not running on Valgrind, for whatever
962 reason. */
963 if ( (timeout && timeout->tv_sec == 0 && timeout->tv_usec == 0)
964 || (ms_now == 0xFFFFFFFF) ) {
sewardj02535bc2002-04-21 01:08:26 +0000965 res = do_syscall_select( n, (vki_fd_set*)rfds,
sewardj08a4c3f2002-04-13 03:45:44 +0000966 (vki_fd_set*)wfds,
967 (vki_fd_set*)xfds,
968 (struct vki_timeval*)timeout);
sewardj02535bc2002-04-21 01:08:26 +0000969 if (is_kerror(res)) {
970 * (__errno_location()) = -res;
971 return -1;
972 } else {
973 return res;
974 }
975 }
sewardj08a4c3f2002-04-13 03:45:44 +0000976
sewardj5f07b662002-04-23 16:52:51 +0000977 /* If a timeout was specified, set ms_end to be the end millisecond
978 counter [wallclock] time. */
sewardj08a4c3f2002-04-13 03:45:44 +0000979 if (timeout) {
980 res = my_do_syscall2(__NR_gettimeofday, (int)&t_now, (int)NULL);
981 assert(res == 0);
sewardj5f07b662002-04-23 16:52:51 +0000982 ms_end = ms_now;
983 ms_end += (timeout->tv_usec / 1000);
984 ms_end += (timeout->tv_sec * 1000);
sewardj08a4c3f2002-04-13 03:45:44 +0000985 /* Stay sane ... */
sewardj5f07b662002-04-23 16:52:51 +0000986 assert (ms_end >= ms_now);
sewardj08a4c3f2002-04-13 03:45:44 +0000987 }
988
989 /* fprintf(stderr, "MY_SELECT: before loop\n"); */
990
991 /* Either timeout == NULL, meaning wait indefinitely, or timeout !=
sewardj5f07b662002-04-23 16:52:51 +0000992 NULL, in which case ms_end holds the end time. */
sewardj08a4c3f2002-04-13 03:45:44 +0000993 while (1) {
994 if (timeout) {
sewardj5f07b662002-04-23 16:52:51 +0000995 VALGRIND_MAGIC_SEQUENCE(ms_now, 0xFFFFFFFF /* default */,
996 VG_USERREQ__READ_MILLISECOND_TIMER,
997 0, 0, 0, 0);
998 assert(ms_now != 0xFFFFFFFF);
999 if (ms_now >= ms_end) {
sewardj08a4c3f2002-04-13 03:45:44 +00001000 /* timeout; nothing interesting happened. */
1001 if (rfds) FD_ZERO(rfds);
1002 if (wfds) FD_ZERO(wfds);
1003 if (xfds) FD_ZERO(xfds);
1004 return 0;
1005 }
1006 }
1007
1008 /* These could be trashed each time round the loop, so restore
1009 them each time. */
1010 if (rfds) rfds_copy = *rfds;
1011 if (wfds) wfds_copy = *wfds;
1012 if (xfds) xfds_copy = *xfds;
1013
1014 zero_timeout.tv_sec = zero_timeout.tv_usec = 0;
1015
1016 res = do_syscall_select( n,
1017 rfds ? (vki_fd_set*)(&rfds_copy) : NULL,
1018 wfds ? (vki_fd_set*)(&wfds_copy) : NULL,
1019 xfds ? (vki_fd_set*)(&xfds_copy) : NULL,
1020 & zero_timeout );
sewardj02535bc2002-04-21 01:08:26 +00001021 if (is_kerror(res)) {
1022 /* Some kind of error (including EINTR). Set errno and
sewardj08a4c3f2002-04-13 03:45:44 +00001023 return. The sets are unspecified in this case. */
sewardj02535bc2002-04-21 01:08:26 +00001024 * (__errno_location()) = -res;
1025 return -1;
sewardj08a4c3f2002-04-13 03:45:44 +00001026 }
1027 if (res > 0) {
1028 /* one or more fds is ready. Copy out resulting sets and
1029 return. */
1030 if (rfds) *rfds = rfds_copy;
1031 if (wfds) *wfds = wfds_copy;
1032 if (xfds) *xfds = xfds_copy;
1033 return res;
1034 }
1035 /* fprintf(stderr, "MY_SELECT: nanosleep\n"); */
1036 /* nanosleep and go round again */
sewardj02535bc2002-04-21 01:08:26 +00001037 nanosleep_interval.tv_sec = 0;
sewardj956cc1b2002-04-25 01:33:50 +00001038 nanosleep_interval.tv_nsec = 50 * 1000 * 1000; /* 50 milliseconds */
sewardjf854f472002-04-21 12:19:41 +00001039 /* It's critical here that valgrind's nanosleep implementation
1040 is nonblocking. */
1041 (void)my_do_syscall2(__NR_nanosleep,
1042 (int)(&nanosleep_interval), (int)NULL);
1043 }
1044}
1045
1046
1047
1048
1049#include <sys/poll.h>
1050
sewardj72d58482002-04-24 02:20:20 +00001051#ifdef GLIBC_2_1
1052typedef unsigned long int nfds_t;
1053#endif
1054
sewardjf854f472002-04-21 12:19:41 +00001055int poll (struct pollfd *__fds, nfds_t __nfds, int __timeout)
1056{
sewardj5f07b662002-04-23 16:52:51 +00001057 unsigned int ms_now, ms_end;
sewardjf854f472002-04-21 12:19:41 +00001058 int res, i;
sewardjf854f472002-04-21 12:19:41 +00001059 struct vki_timespec nanosleep_interval;
1060
1061 ensure_valgrind("poll");
1062
sewardj5f07b662002-04-23 16:52:51 +00001063 /* Detect the current time and simultaneously find out if we are
1064 running on Valgrind. */
1065 VALGRIND_MAGIC_SEQUENCE(ms_now, 0xFFFFFFFF /* default */,
1066 VG_USERREQ__READ_MILLISECOND_TIMER,
1067 0, 0, 0, 0);
1068
sewardjf854f472002-04-21 12:19:41 +00001069 if (/* CHECK SIZES FOR struct pollfd */
1070 sizeof(struct timeval) != sizeof(struct vki_timeval))
1071 barf("valgrind's hacky non-blocking poll(): data sizes error");
1072
sewardj5f07b662002-04-23 16:52:51 +00001073 /* dummy initialisation to keep gcc -Wall happy */
1074 ms_end = 0;
1075
1076 /* If a zero timeout specified, this call is harmless. Also do
1077 this if not running on Valgrind. */
1078 if (__timeout == 0 || ms_now == 0xFFFFFFFF) {
sewardjf854f472002-04-21 12:19:41 +00001079 res = my_do_syscall3(__NR_poll, (int)__fds, __nfds, __timeout);
1080 if (is_kerror(res)) {
1081 * (__errno_location()) = -res;
1082 return -1;
1083 } else {
1084 return res;
1085 }
1086 }
1087
sewardj5f07b662002-04-23 16:52:51 +00001088 /* If a timeout was specified, set ms_end to be the end wallclock
1089 time. Easy considering that __timeout is in milliseconds. */
sewardjf854f472002-04-21 12:19:41 +00001090 if (__timeout > 0) {
sewardj5f07b662002-04-23 16:52:51 +00001091 ms_end += (unsigned int)__timeout;
sewardjf854f472002-04-21 12:19:41 +00001092 }
1093
1094 /* fprintf(stderr, "MY_POLL: before loop\n"); */
1095
1096 /* Either timeout < 0, meaning wait indefinitely, or timeout > 0,
1097 in which case t_end holds the end time. */
sewardj5f07b662002-04-23 16:52:51 +00001098 assert(__timeout != 0);
1099
sewardjf854f472002-04-21 12:19:41 +00001100 while (1) {
sewardjf854f472002-04-21 12:19:41 +00001101 if (__timeout > 0) {
sewardj5f07b662002-04-23 16:52:51 +00001102 VALGRIND_MAGIC_SEQUENCE(ms_now, 0xFFFFFFFF /* default */,
1103 VG_USERREQ__READ_MILLISECOND_TIMER,
1104 0, 0, 0, 0);
1105 assert(ms_now != 0xFFFFFFFF);
1106 if (ms_now >= ms_end) {
sewardjf854f472002-04-21 12:19:41 +00001107 /* timeout; nothing interesting happened. */
1108 for (i = 0; i < __nfds; i++)
1109 __fds[i].revents = 0;
1110 return 0;
1111 }
1112 }
1113
sewardj5f07b662002-04-23 16:52:51 +00001114 /* Do a return-immediately poll. */
sewardjf854f472002-04-21 12:19:41 +00001115 res = my_do_syscall3(__NR_poll, (int)__fds, __nfds, 0 );
1116 if (is_kerror(res)) {
1117 /* Some kind of error. Set errno and return. */
1118 * (__errno_location()) = -res;
1119 return -1;
1120 }
1121 if (res > 0) {
1122 /* One or more fds is ready. Return now. */
1123 return res;
1124 }
1125 /* fprintf(stderr, "MY_POLL: nanosleep\n"); */
1126 /* nanosleep and go round again */
1127 nanosleep_interval.tv_sec = 0;
sewardj956cc1b2002-04-25 01:33:50 +00001128 nanosleep_interval.tv_nsec = 51 * 1000 * 1000; /* 51 milliseconds */
sewardj08a4c3f2002-04-13 03:45:44 +00001129 /* It's critical here that valgrind's nanosleep implementation
1130 is nonblocking. */
1131 (void)my_do_syscall2(__NR_nanosleep,
1132 (int)(&nanosleep_interval), (int)NULL);
1133 }
1134}
sewardj3b13f0e2002-04-25 20:17:29 +00001135
1136
1137/* ---------------------------------------------------------------------
1138 B'stard.
1139 ------------------------------------------------------------------ */
1140
1141# define strong_alias(name, aliasname) \
1142 extern __typeof (name) aliasname __attribute__ ((alias (#name)));
1143
1144strong_alias(pthread_mutex_lock, __pthread_mutex_lock)
1145strong_alias(pthread_mutex_unlock, __pthread_mutex_unlock)
1146strong_alias(pthread_mutexattr_init, __pthread_mutexattr_init)
1147strong_alias(pthread_mutexattr_settype, __pthread_mutexattr_settype)
1148strong_alias(pthread_mutex_init, __pthread_mutex_init)
1149strong_alias(pthread_mutexattr_destroy, __pthread_mutexattr_destroy)
1150strong_alias(pthread_mutex_destroy, __pthread_mutex_destroy)
1151strong_alias(pthread_once, __pthread_once)
1152
1153strong_alias(close, __close)
1154strong_alias(write, __write)
1155strong_alias(read, __read)
1156strong_alias(open, __open)
1157strong_alias(sigaction, __sigaction)
1158
1159strong_alias(pthread_key_create, __pthread_key_create)
1160strong_alias(pthread_getspecific, __pthread_getspecific)
1161strong_alias(pthread_setspecific, __pthread_setspecific)
1162strong_alias(open64, __open64)
1163strong_alias(fcntl, __fcntl)
1164strong_alias(connect, __connect)
1165
1166/*--------------------------------------------------*/
1167
1168/* I've no idea what these are, but they get called quite a lot.
1169 Anybody know? */
1170
1171#undef _IO_flockfile
1172void _IO_flockfile ( _IO_FILE * file )
1173{
1174 // char* str = "_IO_flockfile\n";
1175 // write(2, str, strlen(str));
1176 // barf("_IO_flockfile");
1177}
1178
1179#undef _IO_funlockfile
1180void _IO_funlockfile ( _IO_FILE * file )
1181{
1182 // char* str = "_IO_funlockfile\n";
1183 // write(2, str, strlen(str));
1184 // barf("_IO_funlockfile");
1185}
1186
1187void _pthread_cleanup_push_defer ( void )
1188{
1189 // char* str = "_pthread_cleanup_push_defer\n";
1190 // write(2, str, strlen(str));
1191}
1192
1193void _pthread_cleanup_pop_restore ( void )
1194{
1195 // char* str = "_pthread_cleanup_pop_restore\n";
1196 // write(2, str, strlen(str));
1197}