blob: 4644a0e610b8e9585bfd79f2d8e0479e09d29c59 [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
sewardj5716dbb2002-04-26 03:28:18 +0000682/* ---------------------------------------------------
683 LIBC-PRIVATE SPECIFIC DATA
684 ------------------------------------------------ */
685
686/* Relies on assumption that initial private data is NULL. This
687 should be fixed somehow. */
688
689/* The allowable keys (indices) (all 2 of them).
690 From sysdeps/pthread/bits/libc-tsd.h
691*/
692enum __libc_tsd_key_t { _LIBC_TSD_KEY_MALLOC = 0,
693 _LIBC_TSD_KEY_DL_ERROR,
694 _LIBC_TSD_KEY_N };
695
696/* Auto-initialising subsystem. libc_specifics_inited is set
697 after initialisation. libc_specifics_inited_mx guards it. */
698static int libc_specifics_inited = 0;
699static pthread_mutex_t libc_specifics_inited_mx = PTHREAD_MUTEX_INITIALIZER;
700
701/* These are the keys we must initialise the first time. */
702static pthread_key_t libc_specifics_keys[_LIBC_TSD_KEY_N];
703
704/* Initialise the keys, if they are not already initialise. */
705static
706void init_libc_tsd_keys ( void )
707{
708 int res, i;
709 pthread_key_t k;
710
711 res = pthread_mutex_lock(&libc_specifics_inited_mx);
712 if (res != 0) barf("init_libc_tsd_keys: lock");
713
714 if (libc_specifics_inited == 0) {
715 /* printf("INIT libc specifics\n"); */
716 libc_specifics_inited = 1;
717 for (i = 0; i < _LIBC_TSD_KEY_N; i++) {
718 res = pthread_key_create(&k, NULL);
719 if (res != 0) barf("init_libc_tsd_keys: create");
720 libc_specifics_keys[i] = k;
721 }
722 }
723
724 res = pthread_mutex_unlock(&libc_specifics_inited_mx);
725 if (res != 0) barf("init_libc_tsd_keys: unlock");
726}
727
728
729static int
730libc_internal_tsd_set ( enum __libc_tsd_key_t key,
731 const void * pointer )
732{
733 int res;
734 /* printf("SET SET SET key %d ptr %p\n", key, pointer); */
735 if (key < _LIBC_TSD_KEY_MALLOC || key >= _LIBC_TSD_KEY_N)
736 barf("libc_internal_tsd_set: invalid key");
737 init_libc_tsd_keys();
738 res = pthread_setspecific(libc_specifics_keys[key], pointer);
739 if (res != 0) barf("libc_internal_tsd_set: setspecific failed");
740 return 0;
741}
742
743static void *
744libc_internal_tsd_get ( enum __libc_tsd_key_t key )
745{
746 void* v;
747 /* printf("GET GET GET key %d\n", key); */
748 if (key < _LIBC_TSD_KEY_MALLOC || key >= _LIBC_TSD_KEY_N)
749 barf("libc_internal_tsd_get: invalid key");
750 init_libc_tsd_keys();
751 v = pthread_getspecific(libc_specifics_keys[key]);
752 /* if (v == NULL) barf("libc_internal_tsd_set: getspecific failed"); */
753 return v;
754}
755
756
757
758
759int (*__libc_internal_tsd_set)(enum __libc_tsd_key_t key, const void * pointer)
760 = libc_internal_tsd_set;
761
762void* (*__libc_internal_tsd_get)(enum __libc_tsd_key_t key)
763 = libc_internal_tsd_get;
764
765
sewardje663cb92002-04-12 10:26:32 +0000766/* ---------------------------------------------------------------------
767 These are here (I think) because they are deemed cancellation
768 points by POSIX. For the moment we'll simply pass the call along
769 to the corresponding thread-unaware (?) libc routine.
770 ------------------------------------------------------------------ */
771
sewardje663cb92002-04-12 10:26:32 +0000772#include <stdlib.h>
773#include <signal.h>
sewardje663cb92002-04-12 10:26:32 +0000774#include <sys/types.h>
775#include <sys/socket.h>
776
777extern
778int __libc_sigaction
779 (int signum,
780 const struct sigaction *act,
781 struct sigaction *oldact);
782int sigaction(int signum,
783 const struct sigaction *act,
784 struct sigaction *oldact)
785{
sewardj2a1dcce2002-04-22 12:45:25 +0000786# ifdef GLIBC_2_1
787 return __sigaction(signum, act, oldact);
788# else
sewardj45b4b372002-04-16 22:50:32 +0000789 return __libc_sigaction(signum, act, oldact);
sewardj2a1dcce2002-04-22 12:45:25 +0000790# endif
sewardje663cb92002-04-12 10:26:32 +0000791}
792
793
794extern
795int __libc_connect(int sockfd,
796 const struct sockaddr *serv_addr,
797 socklen_t addrlen);
798int connect(int sockfd,
799 const struct sockaddr *serv_addr,
800 socklen_t addrlen)
801{
sewardj45b4b372002-04-16 22:50:32 +0000802 return __libc_connect(sockfd, serv_addr, addrlen);
sewardje663cb92002-04-12 10:26:32 +0000803}
804
805
806extern
807int __libc_fcntl(int fd, int cmd, long arg);
808int fcntl(int fd, int cmd, long arg)
809{
sewardj45b4b372002-04-16 22:50:32 +0000810 return __libc_fcntl(fd, cmd, arg);
sewardje663cb92002-04-12 10:26:32 +0000811}
812
813
814extern
815ssize_t __libc_write(int fd, const void *buf, size_t count);
816ssize_t write(int fd, const void *buf, size_t count)
817{
sewardj45b4b372002-04-16 22:50:32 +0000818 return __libc_write(fd, buf, count);
sewardje663cb92002-04-12 10:26:32 +0000819}
820
821
822extern
823ssize_t __libc_read(int fd, void *buf, size_t count);
824ssize_t read(int fd, void *buf, size_t count)
825{
sewardj45b4b372002-04-16 22:50:32 +0000826 return __libc_read(fd, buf, count);
sewardje663cb92002-04-12 10:26:32 +0000827}
828
sewardjbe32e452002-04-24 20:29:58 +0000829
830extern
sewardj853f55d2002-04-26 00:27:53 +0000831int __libc_open64(const char *pathname, int flags, mode_t mode);
832int open64(const char *pathname, int flags, mode_t mode)
sewardjbe32e452002-04-24 20:29:58 +0000833{
sewardj853f55d2002-04-26 00:27:53 +0000834 return __libc_open64(pathname, flags, mode);
sewardjbe32e452002-04-24 20:29:58 +0000835}
836
sewardje663cb92002-04-12 10:26:32 +0000837
838extern
sewardj853f55d2002-04-26 00:27:53 +0000839int __libc_open(const char *pathname, int flags, mode_t mode);
840int open(const char *pathname, int flags, mode_t mode)
sewardje663cb92002-04-12 10:26:32 +0000841{
sewardj853f55d2002-04-26 00:27:53 +0000842 return __libc_open(pathname, flags, mode);
sewardje663cb92002-04-12 10:26:32 +0000843}
844
845
846extern
847int __libc_close(int fd);
848int close(int fd)
849{
sewardj45b4b372002-04-16 22:50:32 +0000850 return __libc_close(fd);
sewardje663cb92002-04-12 10:26:32 +0000851}
852
853
854extern
855int __libc_accept(int s, struct sockaddr *addr, socklen_t *addrlen);
856int accept(int s, struct sockaddr *addr, socklen_t *addrlen)
857{
sewardj45b4b372002-04-16 22:50:32 +0000858 return __libc_accept(s, addr, addrlen);
sewardje663cb92002-04-12 10:26:32 +0000859}
860
861
862extern
863pid_t __libc_fork(void);
864pid_t fork(void)
865{
sewardj45b4b372002-04-16 22:50:32 +0000866 return __libc_fork();
sewardje663cb92002-04-12 10:26:32 +0000867}
868
869
870extern
871pid_t __libc_waitpid(pid_t pid, int *status, int options);
872pid_t waitpid(pid_t pid, int *status, int options)
873{
sewardj45b4b372002-04-16 22:50:32 +0000874 return __libc_waitpid(pid, status, options);
sewardje663cb92002-04-12 10:26:32 +0000875}
876
877
878extern
879int __libc_nanosleep(const struct timespec *req, struct timespec *rem);
880int nanosleep(const struct timespec *req, struct timespec *rem)
881{
882 return __libc_nanosleep(req, rem);
883}
884
sewardjbe32e452002-04-24 20:29:58 +0000885
sewardje663cb92002-04-12 10:26:32 +0000886extern
887int __libc_fsync(int fd);
888int fsync(int fd)
889{
sewardj45b4b372002-04-16 22:50:32 +0000890 return __libc_fsync(fd);
sewardje663cb92002-04-12 10:26:32 +0000891}
892
sewardjbe32e452002-04-24 20:29:58 +0000893
sewardj70c75362002-04-13 04:18:32 +0000894extern
895off_t __libc_lseek(int fildes, off_t offset, int whence);
896off_t lseek(int fildes, off_t offset, int whence)
897{
sewardj45b4b372002-04-16 22:50:32 +0000898 return __libc_lseek(fildes, offset, whence);
sewardj70c75362002-04-13 04:18:32 +0000899}
900
sewardjbe32e452002-04-24 20:29:58 +0000901
902extern
903__off64_t __libc_lseek64(int fildes, __off64_t offset, int whence);
904__off64_t lseek64(int fildes, __off64_t offset, int whence)
905{
906 return __libc_lseek64(fildes, offset, whence);
907}
908
909
sewardj6af4b5d2002-04-16 04:40:49 +0000910extern
911void __libc_longjmp(jmp_buf env, int val) __attribute((noreturn));
912void longjmp(jmp_buf env, int val)
913{
914 __libc_longjmp(env, val);
915}
916
sewardjbe32e452002-04-24 20:29:58 +0000917
sewardj6af4b5d2002-04-16 04:40:49 +0000918extern
919int __libc_send(int s, const void *msg, size_t len, int flags);
920int send(int s, const void *msg, size_t len, int flags)
921{
922 return __libc_send(s, msg, len, flags);
923}
924
sewardjbe32e452002-04-24 20:29:58 +0000925
sewardj1e8cdc92002-04-18 11:37:52 +0000926extern
927int __libc_recv(int s, void *buf, size_t len, int flags);
928int recv(int s, void *buf, size_t len, int flags)
929{
930 return __libc_recv(s, buf, len, flags);
931}
932
sewardjbe32e452002-04-24 20:29:58 +0000933
sewardj796d6a22002-04-24 02:28:34 +0000934extern
935int __libc_sendto(int s, const void *msg, size_t len, int flags,
936 const struct sockaddr *to, socklen_t tolen);
937int sendto(int s, const void *msg, size_t len, int flags,
938 const struct sockaddr *to, socklen_t tolen)
939{
940 return __libc_sendto(s, msg, len, flags, to, tolen);
941}
942
sewardjbe32e452002-04-24 20:29:58 +0000943
sewardj369b1702002-04-24 13:28:15 +0000944extern
945int __libc_system(const char* str);
946int system(const char* str)
947{
948 return __libc_system(str);
949}
950
sewardjbe32e452002-04-24 20:29:58 +0000951
sewardjab0b1c32002-04-24 19:26:47 +0000952extern
953pid_t __libc_wait(int *status);
954pid_t wait(int *status)
955{
956 return __libc_wait(status);
957}
958
sewardj45b4b372002-04-16 22:50:32 +0000959
sewardj3b13f0e2002-04-25 20:17:29 +0000960/* ---------------------------------------------------------------------
961 Nonblocking implementations of select() and poll(). This stuff will
962 surely rot your mind.
963 ------------------------------------------------------------------ */
sewardje663cb92002-04-12 10:26:32 +0000964
sewardj08a4c3f2002-04-13 03:45:44 +0000965/*--------------------------------------------------*/
966
967#include "vg_kerneliface.h"
968
969static
970__inline__
971int is_kerror ( int res )
972{
973 if (res >= -4095 && res <= -1)
974 return 1;
975 else
976 return 0;
977}
978
979
980static
981int my_do_syscall1 ( int syscallno, int arg1 )
982{
983 int __res;
984 __asm__ volatile ("pushl %%ebx; movl %%edx,%%ebx ; int $0x80 ; popl %%ebx"
985 : "=a" (__res)
986 : "0" (syscallno),
987 "d" (arg1) );
988 return __res;
989}
990
991static
992int my_do_syscall2 ( int syscallno,
sewardjf854f472002-04-21 12:19:41 +0000993 int arg1, int arg2 )
sewardj08a4c3f2002-04-13 03:45:44 +0000994{
995 int __res;
996 __asm__ volatile ("pushl %%ebx; movl %%edx,%%ebx ; int $0x80 ; popl %%ebx"
997 : "=a" (__res)
998 : "0" (syscallno),
999 "d" (arg1),
1000 "c" (arg2) );
1001 return __res;
1002}
1003
1004static
sewardjf854f472002-04-21 12:19:41 +00001005int my_do_syscall3 ( int syscallno,
1006 int arg1, int arg2, int arg3 )
1007{
1008 int __res;
1009 __asm__ volatile ("pushl %%ebx; movl %%esi,%%ebx ; int $0x80 ; popl %%ebx"
1010 : "=a" (__res)
1011 : "0" (syscallno),
1012 "S" (arg1),
1013 "c" (arg2),
1014 "d" (arg3) );
1015 return __res;
1016}
1017
1018static
sewardj08a4c3f2002-04-13 03:45:44 +00001019int do_syscall_select( int n,
1020 vki_fd_set* readfds,
1021 vki_fd_set* writefds,
1022 vki_fd_set* exceptfds,
1023 struct vki_timeval * timeout )
1024{
1025 int res;
1026 int args[5];
1027 args[0] = n;
1028 args[1] = (int)readfds;
1029 args[2] = (int)writefds;
1030 args[3] = (int)exceptfds;
1031 args[4] = (int)timeout;
1032 res = my_do_syscall1(__NR_select, (int)(&(args[0])) );
sewardj02535bc2002-04-21 01:08:26 +00001033 return res;
sewardj08a4c3f2002-04-13 03:45:44 +00001034}
1035
1036
1037/* This is a wrapper round select(), which makes it thread-safe,
1038 meaning that only this thread will block, rather than the entire
1039 process. This wrapper in turn depends on nanosleep() not to block
1040 the entire process, but I think (hope? suspect?) that POSIX
1041 pthreads guarantees that to be the case.
1042
1043 Basic idea is: modify the timeout parameter to select so that it
1044 returns immediately. Poll like this until select returns non-zero,
1045 indicating something interesting happened, or until our time is up.
1046 Space out the polls with nanosleeps of say 20 milliseconds, which
1047 is required to be nonblocking; this allows other threads to run.
sewardj02535bc2002-04-21 01:08:26 +00001048
1049 Assumes:
1050 * (checked via assert) types fd_set and vki_fd_set are identical.
1051 * (checked via assert) types timeval and vki_timeval are identical.
1052 * (unchecked) libc error numbers (EINTR etc) are the negation of the
1053 kernel's error numbers (VKI_EINTR etc).
sewardj08a4c3f2002-04-13 03:45:44 +00001054*/
sewardj08a4c3f2002-04-13 03:45:44 +00001055
1056
1057int select ( int n,
1058 fd_set *rfds,
1059 fd_set *wfds,
1060 fd_set *xfds,
1061 struct timeval *timeout )
1062{
sewardj5f07b662002-04-23 16:52:51 +00001063 unsigned int ms_now, ms_end;
sewardj08a4c3f2002-04-13 03:45:44 +00001064 int res;
1065 fd_set rfds_copy;
1066 fd_set wfds_copy;
1067 fd_set xfds_copy;
1068 struct vki_timeval t_now;
sewardj08a4c3f2002-04-13 03:45:44 +00001069 struct vki_timeval zero_timeout;
1070 struct vki_timespec nanosleep_interval;
1071
sewardj5f07b662002-04-23 16:52:51 +00001072 /* gcc's complains about ms_end being used uninitialised -- classic
1073 case it can't understand, where ms_end is both defined and used
1074 only if timeout != NULL. Hence ... */
1075 ms_end = 0;
sewardj08a4c3f2002-04-13 03:45:44 +00001076
1077 /* We assume that the kernel and libc data layouts are identical
1078 for the following types. These asserts provide a crude
1079 check. */
1080 if (sizeof(fd_set) != sizeof(vki_fd_set)
1081 || sizeof(struct timeval) != sizeof(struct vki_timeval))
1082 barf("valgrind's hacky non-blocking select(): data sizes error");
1083
sewardj5f07b662002-04-23 16:52:51 +00001084 /* Detect the current time and simultaneously find out if we are
1085 running on Valgrind. */
1086 VALGRIND_MAGIC_SEQUENCE(ms_now, 0xFFFFFFFF /* default */,
1087 VG_USERREQ__READ_MILLISECOND_TIMER,
1088 0, 0, 0, 0);
1089
1090 /* If a zero timeout specified, this call is harmless. Also go
1091 this route if we're not running on Valgrind, for whatever
1092 reason. */
1093 if ( (timeout && timeout->tv_sec == 0 && timeout->tv_usec == 0)
1094 || (ms_now == 0xFFFFFFFF) ) {
sewardj02535bc2002-04-21 01:08:26 +00001095 res = do_syscall_select( n, (vki_fd_set*)rfds,
sewardj08a4c3f2002-04-13 03:45:44 +00001096 (vki_fd_set*)wfds,
1097 (vki_fd_set*)xfds,
1098 (struct vki_timeval*)timeout);
sewardj02535bc2002-04-21 01:08:26 +00001099 if (is_kerror(res)) {
1100 * (__errno_location()) = -res;
1101 return -1;
1102 } else {
1103 return res;
1104 }
1105 }
sewardj08a4c3f2002-04-13 03:45:44 +00001106
sewardj5f07b662002-04-23 16:52:51 +00001107 /* If a timeout was specified, set ms_end to be the end millisecond
1108 counter [wallclock] time. */
sewardj08a4c3f2002-04-13 03:45:44 +00001109 if (timeout) {
1110 res = my_do_syscall2(__NR_gettimeofday, (int)&t_now, (int)NULL);
1111 assert(res == 0);
sewardj5f07b662002-04-23 16:52:51 +00001112 ms_end = ms_now;
1113 ms_end += (timeout->tv_usec / 1000);
1114 ms_end += (timeout->tv_sec * 1000);
sewardj08a4c3f2002-04-13 03:45:44 +00001115 /* Stay sane ... */
sewardj5f07b662002-04-23 16:52:51 +00001116 assert (ms_end >= ms_now);
sewardj08a4c3f2002-04-13 03:45:44 +00001117 }
1118
1119 /* fprintf(stderr, "MY_SELECT: before loop\n"); */
1120
1121 /* Either timeout == NULL, meaning wait indefinitely, or timeout !=
sewardj5f07b662002-04-23 16:52:51 +00001122 NULL, in which case ms_end holds the end time. */
sewardj08a4c3f2002-04-13 03:45:44 +00001123 while (1) {
1124 if (timeout) {
sewardj5f07b662002-04-23 16:52:51 +00001125 VALGRIND_MAGIC_SEQUENCE(ms_now, 0xFFFFFFFF /* default */,
1126 VG_USERREQ__READ_MILLISECOND_TIMER,
1127 0, 0, 0, 0);
1128 assert(ms_now != 0xFFFFFFFF);
1129 if (ms_now >= ms_end) {
sewardj08a4c3f2002-04-13 03:45:44 +00001130 /* timeout; nothing interesting happened. */
1131 if (rfds) FD_ZERO(rfds);
1132 if (wfds) FD_ZERO(wfds);
1133 if (xfds) FD_ZERO(xfds);
1134 return 0;
1135 }
1136 }
1137
1138 /* These could be trashed each time round the loop, so restore
1139 them each time. */
1140 if (rfds) rfds_copy = *rfds;
1141 if (wfds) wfds_copy = *wfds;
1142 if (xfds) xfds_copy = *xfds;
1143
1144 zero_timeout.tv_sec = zero_timeout.tv_usec = 0;
1145
1146 res = do_syscall_select( n,
1147 rfds ? (vki_fd_set*)(&rfds_copy) : NULL,
1148 wfds ? (vki_fd_set*)(&wfds_copy) : NULL,
1149 xfds ? (vki_fd_set*)(&xfds_copy) : NULL,
1150 & zero_timeout );
sewardj02535bc2002-04-21 01:08:26 +00001151 if (is_kerror(res)) {
1152 /* Some kind of error (including EINTR). Set errno and
sewardj08a4c3f2002-04-13 03:45:44 +00001153 return. The sets are unspecified in this case. */
sewardj02535bc2002-04-21 01:08:26 +00001154 * (__errno_location()) = -res;
1155 return -1;
sewardj08a4c3f2002-04-13 03:45:44 +00001156 }
1157 if (res > 0) {
1158 /* one or more fds is ready. Copy out resulting sets and
1159 return. */
1160 if (rfds) *rfds = rfds_copy;
1161 if (wfds) *wfds = wfds_copy;
1162 if (xfds) *xfds = xfds_copy;
1163 return res;
1164 }
1165 /* fprintf(stderr, "MY_SELECT: nanosleep\n"); */
1166 /* nanosleep and go round again */
sewardj02535bc2002-04-21 01:08:26 +00001167 nanosleep_interval.tv_sec = 0;
sewardj956cc1b2002-04-25 01:33:50 +00001168 nanosleep_interval.tv_nsec = 50 * 1000 * 1000; /* 50 milliseconds */
sewardjf854f472002-04-21 12:19:41 +00001169 /* It's critical here that valgrind's nanosleep implementation
1170 is nonblocking. */
1171 (void)my_do_syscall2(__NR_nanosleep,
1172 (int)(&nanosleep_interval), (int)NULL);
1173 }
1174}
1175
1176
1177
1178
1179#include <sys/poll.h>
1180
sewardj72d58482002-04-24 02:20:20 +00001181#ifdef GLIBC_2_1
1182typedef unsigned long int nfds_t;
1183#endif
1184
sewardjf854f472002-04-21 12:19:41 +00001185int poll (struct pollfd *__fds, nfds_t __nfds, int __timeout)
1186{
sewardj5f07b662002-04-23 16:52:51 +00001187 unsigned int ms_now, ms_end;
sewardjf854f472002-04-21 12:19:41 +00001188 int res, i;
sewardjf854f472002-04-21 12:19:41 +00001189 struct vki_timespec nanosleep_interval;
1190
1191 ensure_valgrind("poll");
1192
sewardj5f07b662002-04-23 16:52:51 +00001193 /* Detect the current time and simultaneously find out if we are
1194 running on Valgrind. */
1195 VALGRIND_MAGIC_SEQUENCE(ms_now, 0xFFFFFFFF /* default */,
1196 VG_USERREQ__READ_MILLISECOND_TIMER,
1197 0, 0, 0, 0);
1198
sewardjf854f472002-04-21 12:19:41 +00001199 if (/* CHECK SIZES FOR struct pollfd */
1200 sizeof(struct timeval) != sizeof(struct vki_timeval))
1201 barf("valgrind's hacky non-blocking poll(): data sizes error");
1202
sewardj5f07b662002-04-23 16:52:51 +00001203 /* dummy initialisation to keep gcc -Wall happy */
1204 ms_end = 0;
1205
1206 /* If a zero timeout specified, this call is harmless. Also do
1207 this if not running on Valgrind. */
1208 if (__timeout == 0 || ms_now == 0xFFFFFFFF) {
sewardjf854f472002-04-21 12:19:41 +00001209 res = my_do_syscall3(__NR_poll, (int)__fds, __nfds, __timeout);
1210 if (is_kerror(res)) {
1211 * (__errno_location()) = -res;
1212 return -1;
1213 } else {
1214 return res;
1215 }
1216 }
1217
sewardj5f07b662002-04-23 16:52:51 +00001218 /* If a timeout was specified, set ms_end to be the end wallclock
1219 time. Easy considering that __timeout is in milliseconds. */
sewardjf854f472002-04-21 12:19:41 +00001220 if (__timeout > 0) {
sewardj5f07b662002-04-23 16:52:51 +00001221 ms_end += (unsigned int)__timeout;
sewardjf854f472002-04-21 12:19:41 +00001222 }
1223
1224 /* fprintf(stderr, "MY_POLL: before loop\n"); */
1225
1226 /* Either timeout < 0, meaning wait indefinitely, or timeout > 0,
1227 in which case t_end holds the end time. */
sewardj5f07b662002-04-23 16:52:51 +00001228 assert(__timeout != 0);
1229
sewardjf854f472002-04-21 12:19:41 +00001230 while (1) {
sewardjf854f472002-04-21 12:19:41 +00001231 if (__timeout > 0) {
sewardj5f07b662002-04-23 16:52:51 +00001232 VALGRIND_MAGIC_SEQUENCE(ms_now, 0xFFFFFFFF /* default */,
1233 VG_USERREQ__READ_MILLISECOND_TIMER,
1234 0, 0, 0, 0);
1235 assert(ms_now != 0xFFFFFFFF);
1236 if (ms_now >= ms_end) {
sewardjf854f472002-04-21 12:19:41 +00001237 /* timeout; nothing interesting happened. */
1238 for (i = 0; i < __nfds; i++)
1239 __fds[i].revents = 0;
1240 return 0;
1241 }
1242 }
1243
sewardj5f07b662002-04-23 16:52:51 +00001244 /* Do a return-immediately poll. */
sewardjf854f472002-04-21 12:19:41 +00001245 res = my_do_syscall3(__NR_poll, (int)__fds, __nfds, 0 );
1246 if (is_kerror(res)) {
1247 /* Some kind of error. Set errno and return. */
1248 * (__errno_location()) = -res;
1249 return -1;
1250 }
1251 if (res > 0) {
1252 /* One or more fds is ready. Return now. */
1253 return res;
1254 }
1255 /* fprintf(stderr, "MY_POLL: nanosleep\n"); */
1256 /* nanosleep and go round again */
1257 nanosleep_interval.tv_sec = 0;
sewardj956cc1b2002-04-25 01:33:50 +00001258 nanosleep_interval.tv_nsec = 51 * 1000 * 1000; /* 51 milliseconds */
sewardj08a4c3f2002-04-13 03:45:44 +00001259 /* It's critical here that valgrind's nanosleep implementation
1260 is nonblocking. */
1261 (void)my_do_syscall2(__NR_nanosleep,
1262 (int)(&nanosleep_interval), (int)NULL);
1263 }
1264}
sewardj3b13f0e2002-04-25 20:17:29 +00001265
1266
1267/* ---------------------------------------------------------------------
1268 B'stard.
1269 ------------------------------------------------------------------ */
1270
1271# define strong_alias(name, aliasname) \
1272 extern __typeof (name) aliasname __attribute__ ((alias (#name)));
1273
1274strong_alias(pthread_mutex_lock, __pthread_mutex_lock)
sewardj853f55d2002-04-26 00:27:53 +00001275strong_alias(pthread_mutex_trylock, __pthread_mutex_trylock)
sewardj3b13f0e2002-04-25 20:17:29 +00001276strong_alias(pthread_mutex_unlock, __pthread_mutex_unlock)
1277strong_alias(pthread_mutexattr_init, __pthread_mutexattr_init)
1278strong_alias(pthread_mutexattr_settype, __pthread_mutexattr_settype)
1279strong_alias(pthread_mutex_init, __pthread_mutex_init)
1280strong_alias(pthread_mutexattr_destroy, __pthread_mutexattr_destroy)
1281strong_alias(pthread_mutex_destroy, __pthread_mutex_destroy)
1282strong_alias(pthread_once, __pthread_once)
sewardj853f55d2002-04-26 00:27:53 +00001283strong_alias(pthread_atfork, __pthread_atfork)
sewardj3b13f0e2002-04-25 20:17:29 +00001284
sewardj853f55d2002-04-26 00:27:53 +00001285strong_alias(fork, __fork)
sewardj3b13f0e2002-04-25 20:17:29 +00001286strong_alias(close, __close)
1287strong_alias(write, __write)
1288strong_alias(read, __read)
1289strong_alias(open, __open)
1290strong_alias(sigaction, __sigaction)
1291
1292strong_alias(pthread_key_create, __pthread_key_create)
1293strong_alias(pthread_getspecific, __pthread_getspecific)
1294strong_alias(pthread_setspecific, __pthread_setspecific)
1295strong_alias(open64, __open64)
1296strong_alias(fcntl, __fcntl)
1297strong_alias(connect, __connect)
1298
1299/*--------------------------------------------------*/
1300
sewardj5716dbb2002-04-26 03:28:18 +00001301int
1302pthread_rwlock_rdlock (void* /* pthread_rwlock_t* */ rwlock)
1303{
1304 kludged("pthread_rwlock_rdlock");
1305 return 0;
1306}
1307
1308strong_alias(pthread_rwlock_rdlock, __pthread_rwlock_rdlock)
1309
1310
1311int
1312pthread_rwlock_unlock (void* /* pthread_rwlock_t* */ rwlock)
1313{
1314 kludged("pthread_rwlock_unlock");
1315 return 0;
1316}
1317
1318strong_alias(pthread_rwlock_unlock, __pthread_rwlock_unlock)
1319
1320
sewardj3b13f0e2002-04-25 20:17:29 +00001321/* I've no idea what these are, but they get called quite a lot.
1322 Anybody know? */
1323
1324#undef _IO_flockfile
1325void _IO_flockfile ( _IO_FILE * file )
1326{
sewardj853f55d2002-04-26 00:27:53 +00001327 //char* str = "_IO_flockfile\n";
1328 //write(2, str, strlen(str));
1329 pthread_mutex_lock(file->_lock);
sewardj3b13f0e2002-04-25 20:17:29 +00001330 // barf("_IO_flockfile");
1331}
1332
1333#undef _IO_funlockfile
1334void _IO_funlockfile ( _IO_FILE * file )
1335{
sewardj853f55d2002-04-26 00:27:53 +00001336 //char* str = "_IO_funlockfile\n";
1337 //write(2, str, strlen(str));
1338 pthread_mutex_unlock(file->_lock);
sewardj3b13f0e2002-04-25 20:17:29 +00001339 // barf("_IO_funlockfile");
1340}
1341
1342void _pthread_cleanup_push_defer ( void )
1343{
1344 // char* str = "_pthread_cleanup_push_defer\n";
1345 // write(2, str, strlen(str));
1346}
1347
1348void _pthread_cleanup_pop_restore ( void )
1349{
1350 // char* str = "_pthread_cleanup_pop_restore\n";
1351 // write(2, str, strlen(str));
1352}