blob: dfb02af08c5fb25eb2cb83a9f50c2f551fed93d4 [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
sewardj5905fae2002-04-26 13:25:00 +0000273int __pthread_mutexattr_init(pthread_mutexattr_t *attr)
sewardje663cb92002-04-12 10:26:32 +0000274{
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
sewardj5905fae2002-04-26 13:25:00 +0000279int __pthread_mutexattr_settype(pthread_mutexattr_t *attr, int type)
sewardjf8f819e2002-04-17 23:21:37 +0000280{
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
sewardj5905fae2002-04-26 13:25:00 +0000295int __pthread_mutexattr_destroy(pthread_mutexattr_t *attr)
sewardjf8f819e2002-04-17 23:21:37 +0000296{
297 return 0;
298}
299
300
301/* ---------------------------------------------------
302 MUTEXes
303 ------------------------------------------------ */
304
sewardj5905fae2002-04-26 13:25:00 +0000305int __pthread_mutex_init(pthread_mutex_t *mutex,
306 const pthread_mutexattr_t *mutexattr)
sewardje663cb92002-04-12 10:26:32 +0000307{
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
sewardj5905fae2002-04-26 13:25:00 +0000316int __pthread_mutex_lock(pthread_mutex_t *mutex)
sewardje663cb92002-04-12 10:26:32 +0000317{
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
sewardj5905fae2002-04-26 13:25:00 +0000332int __pthread_mutex_trylock(pthread_mutex_t *mutex)
sewardj30671ff2002-04-21 00:13:57 +0000333{
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
sewardj5905fae2002-04-26 13:25:00 +0000348int __pthread_mutex_unlock(pthread_mutex_t *mutex)
sewardje663cb92002-04-12 10:26:32 +0000349{
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
sewardj5905fae2002-04-26 13:25:00 +0000364int __pthread_mutex_destroy(pthread_mutex_t *mutex)
sewardje663cb92002-04-12 10:26:32 +0000365{
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
sewardj5905fae2002-04-26 13:25:00 +0000551int __pthread_key_create(pthread_key_t *key,
552 void (*destr_function) (void *))
sewardj5e5fa512002-04-14 13:13:05 +0000553{
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
sewardj5905fae2002-04-26 13:25:00 +0000568int __pthread_setspecific(pthread_key_t key, const void *pointer)
sewardj5e5fa512002-04-14 13:13:05 +0000569{
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
sewardj5905fae2002-04-26 13:25:00 +0000578void * __pthread_getspecific(pthread_key_t key)
sewardj5e5fa512002-04-14 13:13:05 +0000579{
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
sewardj5905fae2002-04-26 13:25:00 +0000596int __pthread_once ( pthread_once_t *once_control,
597 void (*init_routine) (void) )
sewardj89d3d852002-04-24 19:21:39 +0000598{
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
sewardj5905fae2002-04-26 13:25:00 +0000623int __pthread_atfork ( void (*prepare)(void),
624 void (*parent)(void),
625 void (*child)(void) )
sewardj853f55d2002-04-26 00:27:53 +0000626{
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);
sewardj5905fae2002-04-26 13:25:00 +0000798__attribute__((weak))
sewardje663cb92002-04-12 10:26:32 +0000799int connect(int sockfd,
800 const struct sockaddr *serv_addr,
801 socklen_t addrlen)
802{
sewardj45b4b372002-04-16 22:50:32 +0000803 return __libc_connect(sockfd, serv_addr, addrlen);
sewardje663cb92002-04-12 10:26:32 +0000804}
805
806
807extern
808int __libc_fcntl(int fd, int cmd, long arg);
sewardj5905fae2002-04-26 13:25:00 +0000809__attribute__((weak))
sewardje663cb92002-04-12 10:26:32 +0000810int fcntl(int fd, int cmd, long arg)
811{
sewardj45b4b372002-04-16 22:50:32 +0000812 return __libc_fcntl(fd, cmd, arg);
sewardje663cb92002-04-12 10:26:32 +0000813}
814
815
816extern
817ssize_t __libc_write(int fd, const void *buf, size_t count);
sewardj5905fae2002-04-26 13:25:00 +0000818__attribute__((weak))
sewardje663cb92002-04-12 10:26:32 +0000819ssize_t write(int fd, const void *buf, size_t count)
820{
sewardj45b4b372002-04-16 22:50:32 +0000821 return __libc_write(fd, buf, count);
sewardje663cb92002-04-12 10:26:32 +0000822}
823
824
825extern
826ssize_t __libc_read(int fd, void *buf, size_t count);
sewardj5905fae2002-04-26 13:25:00 +0000827__attribute__((weak))
sewardje663cb92002-04-12 10:26:32 +0000828ssize_t read(int fd, void *buf, size_t count)
829{
sewardj45b4b372002-04-16 22:50:32 +0000830 return __libc_read(fd, buf, count);
sewardje663cb92002-04-12 10:26:32 +0000831}
832
sewardjbe32e452002-04-24 20:29:58 +0000833
834extern
sewardj853f55d2002-04-26 00:27:53 +0000835int __libc_open64(const char *pathname, int flags, mode_t mode);
sewardj5905fae2002-04-26 13:25:00 +0000836__attribute__((weak))
sewardj853f55d2002-04-26 00:27:53 +0000837int open64(const char *pathname, int flags, mode_t mode)
sewardjbe32e452002-04-24 20:29:58 +0000838{
sewardj853f55d2002-04-26 00:27:53 +0000839 return __libc_open64(pathname, flags, mode);
sewardjbe32e452002-04-24 20:29:58 +0000840}
841
sewardje663cb92002-04-12 10:26:32 +0000842
843extern
sewardj853f55d2002-04-26 00:27:53 +0000844int __libc_open(const char *pathname, int flags, mode_t mode);
sewardj5905fae2002-04-26 13:25:00 +0000845__attribute__((weak))
sewardj853f55d2002-04-26 00:27:53 +0000846int open(const char *pathname, int flags, mode_t mode)
sewardje663cb92002-04-12 10:26:32 +0000847{
sewardj853f55d2002-04-26 00:27:53 +0000848 return __libc_open(pathname, flags, mode);
sewardje663cb92002-04-12 10:26:32 +0000849}
850
851
852extern
853int __libc_close(int fd);
sewardj5905fae2002-04-26 13:25:00 +0000854__attribute__((weak))
sewardje663cb92002-04-12 10:26:32 +0000855int close(int fd)
856{
sewardj45b4b372002-04-16 22:50:32 +0000857 return __libc_close(fd);
sewardje663cb92002-04-12 10:26:32 +0000858}
859
860
861extern
862int __libc_accept(int s, struct sockaddr *addr, socklen_t *addrlen);
sewardj5905fae2002-04-26 13:25:00 +0000863__attribute__((weak))
sewardje663cb92002-04-12 10:26:32 +0000864int accept(int s, struct sockaddr *addr, socklen_t *addrlen)
865{
sewardj45b4b372002-04-16 22:50:32 +0000866 return __libc_accept(s, addr, addrlen);
sewardje663cb92002-04-12 10:26:32 +0000867}
868
869
870extern
871pid_t __libc_fork(void);
sewardj5905fae2002-04-26 13:25:00 +0000872pid_t __fork(void)
sewardje663cb92002-04-12 10:26:32 +0000873{
sewardj45b4b372002-04-16 22:50:32 +0000874 return __libc_fork();
sewardje663cb92002-04-12 10:26:32 +0000875}
876
877
878extern
879pid_t __libc_waitpid(pid_t pid, int *status, int options);
sewardj5905fae2002-04-26 13:25:00 +0000880__attribute__((weak))
sewardje663cb92002-04-12 10:26:32 +0000881pid_t waitpid(pid_t pid, int *status, int options)
882{
sewardj45b4b372002-04-16 22:50:32 +0000883 return __libc_waitpid(pid, status, options);
sewardje663cb92002-04-12 10:26:32 +0000884}
885
886
887extern
888int __libc_nanosleep(const struct timespec *req, struct timespec *rem);
sewardj5905fae2002-04-26 13:25:00 +0000889__attribute__((weak))
sewardje663cb92002-04-12 10:26:32 +0000890int nanosleep(const struct timespec *req, struct timespec *rem)
891{
892 return __libc_nanosleep(req, rem);
893}
894
sewardjbe32e452002-04-24 20:29:58 +0000895
sewardje663cb92002-04-12 10:26:32 +0000896extern
897int __libc_fsync(int fd);
sewardj5905fae2002-04-26 13:25:00 +0000898__attribute__((weak))
sewardje663cb92002-04-12 10:26:32 +0000899int fsync(int fd)
900{
sewardj45b4b372002-04-16 22:50:32 +0000901 return __libc_fsync(fd);
sewardje663cb92002-04-12 10:26:32 +0000902}
903
sewardjbe32e452002-04-24 20:29:58 +0000904
sewardj70c75362002-04-13 04:18:32 +0000905extern
906off_t __libc_lseek(int fildes, off_t offset, int whence);
sewardj5905fae2002-04-26 13:25:00 +0000907__attribute__((weak))
sewardj70c75362002-04-13 04:18:32 +0000908off_t lseek(int fildes, off_t offset, int whence)
909{
sewardj45b4b372002-04-16 22:50:32 +0000910 return __libc_lseek(fildes, offset, whence);
sewardj70c75362002-04-13 04:18:32 +0000911}
912
sewardjbe32e452002-04-24 20:29:58 +0000913
914extern
915__off64_t __libc_lseek64(int fildes, __off64_t offset, int whence);
sewardj5905fae2002-04-26 13:25:00 +0000916__attribute__((weak))
sewardjbe32e452002-04-24 20:29:58 +0000917__off64_t lseek64(int fildes, __off64_t offset, int whence)
918{
919 return __libc_lseek64(fildes, offset, whence);
920}
921
922
sewardj6af4b5d2002-04-16 04:40:49 +0000923extern
924void __libc_longjmp(jmp_buf env, int val) __attribute((noreturn));
sewardj5905fae2002-04-26 13:25:00 +0000925/* not weak: __attribute__((weak)) */
sewardj6af4b5d2002-04-16 04:40:49 +0000926void longjmp(jmp_buf env, int val)
927{
928 __libc_longjmp(env, val);
929}
930
sewardjbe32e452002-04-24 20:29:58 +0000931
sewardj6af4b5d2002-04-16 04:40:49 +0000932extern
933int __libc_send(int s, const void *msg, size_t len, int flags);
sewardj5905fae2002-04-26 13:25:00 +0000934__attribute__((weak))
sewardj6af4b5d2002-04-16 04:40:49 +0000935int send(int s, const void *msg, size_t len, int flags)
936{
937 return __libc_send(s, msg, len, flags);
938}
939
sewardjbe32e452002-04-24 20:29:58 +0000940
sewardj1e8cdc92002-04-18 11:37:52 +0000941extern
942int __libc_recv(int s, void *buf, size_t len, int flags);
sewardj5905fae2002-04-26 13:25:00 +0000943__attribute__((weak))
sewardj1e8cdc92002-04-18 11:37:52 +0000944int recv(int s, void *buf, size_t len, int flags)
945{
946 return __libc_recv(s, buf, len, flags);
947}
948
sewardjbe32e452002-04-24 20:29:58 +0000949
sewardj796d6a22002-04-24 02:28:34 +0000950extern
951int __libc_sendto(int s, const void *msg, size_t len, int flags,
952 const struct sockaddr *to, socklen_t tolen);
sewardj5905fae2002-04-26 13:25:00 +0000953__attribute__((weak))
sewardj796d6a22002-04-24 02:28:34 +0000954int sendto(int s, const void *msg, size_t len, int flags,
955 const struct sockaddr *to, socklen_t tolen)
956{
957 return __libc_sendto(s, msg, len, flags, to, tolen);
958}
959
sewardjbe32e452002-04-24 20:29:58 +0000960
sewardj369b1702002-04-24 13:28:15 +0000961extern
962int __libc_system(const char* str);
sewardj5905fae2002-04-26 13:25:00 +0000963__attribute__((weak))
sewardj369b1702002-04-24 13:28:15 +0000964int system(const char* str)
965{
966 return __libc_system(str);
967}
968
sewardjbe32e452002-04-24 20:29:58 +0000969
sewardjab0b1c32002-04-24 19:26:47 +0000970extern
971pid_t __libc_wait(int *status);
sewardj5905fae2002-04-26 13:25:00 +0000972__attribute__((weak))
sewardjab0b1c32002-04-24 19:26:47 +0000973pid_t wait(int *status)
974{
975 return __libc_wait(status);
976}
977
sewardj45b4b372002-04-16 22:50:32 +0000978
sewardj5905fae2002-04-26 13:25:00 +0000979
sewardj3b13f0e2002-04-25 20:17:29 +0000980/* ---------------------------------------------------------------------
981 Nonblocking implementations of select() and poll(). This stuff will
982 surely rot your mind.
983 ------------------------------------------------------------------ */
sewardje663cb92002-04-12 10:26:32 +0000984
sewardj08a4c3f2002-04-13 03:45:44 +0000985/*--------------------------------------------------*/
986
987#include "vg_kerneliface.h"
988
989static
990__inline__
991int is_kerror ( int res )
992{
993 if (res >= -4095 && res <= -1)
994 return 1;
995 else
996 return 0;
997}
998
999
1000static
1001int my_do_syscall1 ( int syscallno, int arg1 )
1002{
1003 int __res;
1004 __asm__ volatile ("pushl %%ebx; movl %%edx,%%ebx ; int $0x80 ; popl %%ebx"
1005 : "=a" (__res)
1006 : "0" (syscallno),
1007 "d" (arg1) );
1008 return __res;
1009}
1010
1011static
1012int my_do_syscall2 ( int syscallno,
sewardjf854f472002-04-21 12:19:41 +00001013 int arg1, int arg2 )
sewardj08a4c3f2002-04-13 03:45:44 +00001014{
1015 int __res;
1016 __asm__ volatile ("pushl %%ebx; movl %%edx,%%ebx ; int $0x80 ; popl %%ebx"
1017 : "=a" (__res)
1018 : "0" (syscallno),
1019 "d" (arg1),
1020 "c" (arg2) );
1021 return __res;
1022}
1023
1024static
sewardjf854f472002-04-21 12:19:41 +00001025int my_do_syscall3 ( int syscallno,
1026 int arg1, int arg2, int arg3 )
1027{
1028 int __res;
1029 __asm__ volatile ("pushl %%ebx; movl %%esi,%%ebx ; int $0x80 ; popl %%ebx"
1030 : "=a" (__res)
1031 : "0" (syscallno),
1032 "S" (arg1),
1033 "c" (arg2),
1034 "d" (arg3) );
1035 return __res;
1036}
1037
1038static
sewardj08a4c3f2002-04-13 03:45:44 +00001039int do_syscall_select( int n,
1040 vki_fd_set* readfds,
1041 vki_fd_set* writefds,
1042 vki_fd_set* exceptfds,
1043 struct vki_timeval * timeout )
1044{
1045 int res;
1046 int args[5];
1047 args[0] = n;
1048 args[1] = (int)readfds;
1049 args[2] = (int)writefds;
1050 args[3] = (int)exceptfds;
1051 args[4] = (int)timeout;
1052 res = my_do_syscall1(__NR_select, (int)(&(args[0])) );
sewardj02535bc2002-04-21 01:08:26 +00001053 return res;
sewardj08a4c3f2002-04-13 03:45:44 +00001054}
1055
1056
1057/* This is a wrapper round select(), which makes it thread-safe,
1058 meaning that only this thread will block, rather than the entire
1059 process. This wrapper in turn depends on nanosleep() not to block
1060 the entire process, but I think (hope? suspect?) that POSIX
1061 pthreads guarantees that to be the case.
1062
1063 Basic idea is: modify the timeout parameter to select so that it
1064 returns immediately. Poll like this until select returns non-zero,
1065 indicating something interesting happened, or until our time is up.
1066 Space out the polls with nanosleeps of say 20 milliseconds, which
1067 is required to be nonblocking; this allows other threads to run.
sewardj02535bc2002-04-21 01:08:26 +00001068
1069 Assumes:
1070 * (checked via assert) types fd_set and vki_fd_set are identical.
1071 * (checked via assert) types timeval and vki_timeval are identical.
1072 * (unchecked) libc error numbers (EINTR etc) are the negation of the
1073 kernel's error numbers (VKI_EINTR etc).
sewardj08a4c3f2002-04-13 03:45:44 +00001074*/
sewardj08a4c3f2002-04-13 03:45:44 +00001075
sewardj5905fae2002-04-26 13:25:00 +00001076/* __attribute__((weak)) */
sewardj08a4c3f2002-04-13 03:45:44 +00001077int select ( int n,
1078 fd_set *rfds,
1079 fd_set *wfds,
1080 fd_set *xfds,
1081 struct timeval *timeout )
1082{
sewardj5f07b662002-04-23 16:52:51 +00001083 unsigned int ms_now, ms_end;
sewardj08a4c3f2002-04-13 03:45:44 +00001084 int res;
1085 fd_set rfds_copy;
1086 fd_set wfds_copy;
1087 fd_set xfds_copy;
1088 struct vki_timeval t_now;
sewardj08a4c3f2002-04-13 03:45:44 +00001089 struct vki_timeval zero_timeout;
1090 struct vki_timespec nanosleep_interval;
1091
sewardj5f07b662002-04-23 16:52:51 +00001092 /* gcc's complains about ms_end being used uninitialised -- classic
1093 case it can't understand, where ms_end is both defined and used
1094 only if timeout != NULL. Hence ... */
1095 ms_end = 0;
sewardj08a4c3f2002-04-13 03:45:44 +00001096
1097 /* We assume that the kernel and libc data layouts are identical
1098 for the following types. These asserts provide a crude
1099 check. */
1100 if (sizeof(fd_set) != sizeof(vki_fd_set)
1101 || sizeof(struct timeval) != sizeof(struct vki_timeval))
1102 barf("valgrind's hacky non-blocking select(): data sizes error");
1103
sewardj5f07b662002-04-23 16:52:51 +00001104 /* Detect the current time and simultaneously find out if we are
1105 running on Valgrind. */
1106 VALGRIND_MAGIC_SEQUENCE(ms_now, 0xFFFFFFFF /* default */,
1107 VG_USERREQ__READ_MILLISECOND_TIMER,
1108 0, 0, 0, 0);
1109
1110 /* If a zero timeout specified, this call is harmless. Also go
1111 this route if we're not running on Valgrind, for whatever
1112 reason. */
1113 if ( (timeout && timeout->tv_sec == 0 && timeout->tv_usec == 0)
1114 || (ms_now == 0xFFFFFFFF) ) {
sewardj02535bc2002-04-21 01:08:26 +00001115 res = do_syscall_select( n, (vki_fd_set*)rfds,
sewardj08a4c3f2002-04-13 03:45:44 +00001116 (vki_fd_set*)wfds,
1117 (vki_fd_set*)xfds,
1118 (struct vki_timeval*)timeout);
sewardj02535bc2002-04-21 01:08:26 +00001119 if (is_kerror(res)) {
1120 * (__errno_location()) = -res;
1121 return -1;
1122 } else {
1123 return res;
1124 }
1125 }
sewardj08a4c3f2002-04-13 03:45:44 +00001126
sewardj5f07b662002-04-23 16:52:51 +00001127 /* If a timeout was specified, set ms_end to be the end millisecond
1128 counter [wallclock] time. */
sewardj08a4c3f2002-04-13 03:45:44 +00001129 if (timeout) {
1130 res = my_do_syscall2(__NR_gettimeofday, (int)&t_now, (int)NULL);
1131 assert(res == 0);
sewardj5f07b662002-04-23 16:52:51 +00001132 ms_end = ms_now;
1133 ms_end += (timeout->tv_usec / 1000);
1134 ms_end += (timeout->tv_sec * 1000);
sewardj08a4c3f2002-04-13 03:45:44 +00001135 /* Stay sane ... */
sewardj5f07b662002-04-23 16:52:51 +00001136 assert (ms_end >= ms_now);
sewardj08a4c3f2002-04-13 03:45:44 +00001137 }
1138
1139 /* fprintf(stderr, "MY_SELECT: before loop\n"); */
1140
1141 /* Either timeout == NULL, meaning wait indefinitely, or timeout !=
sewardj5f07b662002-04-23 16:52:51 +00001142 NULL, in which case ms_end holds the end time. */
sewardj08a4c3f2002-04-13 03:45:44 +00001143 while (1) {
1144 if (timeout) {
sewardj5f07b662002-04-23 16:52:51 +00001145 VALGRIND_MAGIC_SEQUENCE(ms_now, 0xFFFFFFFF /* default */,
1146 VG_USERREQ__READ_MILLISECOND_TIMER,
1147 0, 0, 0, 0);
1148 assert(ms_now != 0xFFFFFFFF);
1149 if (ms_now >= ms_end) {
sewardj08a4c3f2002-04-13 03:45:44 +00001150 /* timeout; nothing interesting happened. */
1151 if (rfds) FD_ZERO(rfds);
1152 if (wfds) FD_ZERO(wfds);
1153 if (xfds) FD_ZERO(xfds);
1154 return 0;
1155 }
1156 }
1157
1158 /* These could be trashed each time round the loop, so restore
1159 them each time. */
1160 if (rfds) rfds_copy = *rfds;
1161 if (wfds) wfds_copy = *wfds;
1162 if (xfds) xfds_copy = *xfds;
1163
1164 zero_timeout.tv_sec = zero_timeout.tv_usec = 0;
1165
1166 res = do_syscall_select( n,
1167 rfds ? (vki_fd_set*)(&rfds_copy) : NULL,
1168 wfds ? (vki_fd_set*)(&wfds_copy) : NULL,
1169 xfds ? (vki_fd_set*)(&xfds_copy) : NULL,
1170 & zero_timeout );
sewardj02535bc2002-04-21 01:08:26 +00001171 if (is_kerror(res)) {
1172 /* Some kind of error (including EINTR). Set errno and
sewardj08a4c3f2002-04-13 03:45:44 +00001173 return. The sets are unspecified in this case. */
sewardj02535bc2002-04-21 01:08:26 +00001174 * (__errno_location()) = -res;
1175 return -1;
sewardj08a4c3f2002-04-13 03:45:44 +00001176 }
1177 if (res > 0) {
1178 /* one or more fds is ready. Copy out resulting sets and
1179 return. */
1180 if (rfds) *rfds = rfds_copy;
1181 if (wfds) *wfds = wfds_copy;
1182 if (xfds) *xfds = xfds_copy;
1183 return res;
1184 }
1185 /* fprintf(stderr, "MY_SELECT: nanosleep\n"); */
1186 /* nanosleep and go round again */
sewardj02535bc2002-04-21 01:08:26 +00001187 nanosleep_interval.tv_sec = 0;
sewardj956cc1b2002-04-25 01:33:50 +00001188 nanosleep_interval.tv_nsec = 50 * 1000 * 1000; /* 50 milliseconds */
sewardjf854f472002-04-21 12:19:41 +00001189 /* It's critical here that valgrind's nanosleep implementation
1190 is nonblocking. */
1191 (void)my_do_syscall2(__NR_nanosleep,
1192 (int)(&nanosleep_interval), (int)NULL);
1193 }
1194}
1195
1196
1197
1198
1199#include <sys/poll.h>
1200
sewardj72d58482002-04-24 02:20:20 +00001201#ifdef GLIBC_2_1
1202typedef unsigned long int nfds_t;
1203#endif
1204
sewardj5905fae2002-04-26 13:25:00 +00001205/* __attribute__((weak)) */
sewardjf854f472002-04-21 12:19:41 +00001206int poll (struct pollfd *__fds, nfds_t __nfds, int __timeout)
1207{
sewardj5f07b662002-04-23 16:52:51 +00001208 unsigned int ms_now, ms_end;
sewardjf854f472002-04-21 12:19:41 +00001209 int res, i;
sewardjf854f472002-04-21 12:19:41 +00001210 struct vki_timespec nanosleep_interval;
1211
1212 ensure_valgrind("poll");
1213
sewardj5f07b662002-04-23 16:52:51 +00001214 /* Detect the current time and simultaneously find out if we are
1215 running on Valgrind. */
1216 VALGRIND_MAGIC_SEQUENCE(ms_now, 0xFFFFFFFF /* default */,
1217 VG_USERREQ__READ_MILLISECOND_TIMER,
1218 0, 0, 0, 0);
1219
sewardjf854f472002-04-21 12:19:41 +00001220 if (/* CHECK SIZES FOR struct pollfd */
1221 sizeof(struct timeval) != sizeof(struct vki_timeval))
1222 barf("valgrind's hacky non-blocking poll(): data sizes error");
1223
sewardj5f07b662002-04-23 16:52:51 +00001224 /* dummy initialisation to keep gcc -Wall happy */
1225 ms_end = 0;
1226
1227 /* If a zero timeout specified, this call is harmless. Also do
1228 this if not running on Valgrind. */
1229 if (__timeout == 0 || ms_now == 0xFFFFFFFF) {
sewardjf854f472002-04-21 12:19:41 +00001230 res = my_do_syscall3(__NR_poll, (int)__fds, __nfds, __timeout);
1231 if (is_kerror(res)) {
1232 * (__errno_location()) = -res;
1233 return -1;
1234 } else {
1235 return res;
1236 }
1237 }
1238
sewardj5f07b662002-04-23 16:52:51 +00001239 /* If a timeout was specified, set ms_end to be the end wallclock
1240 time. Easy considering that __timeout is in milliseconds. */
sewardjf854f472002-04-21 12:19:41 +00001241 if (__timeout > 0) {
sewardj5f07b662002-04-23 16:52:51 +00001242 ms_end += (unsigned int)__timeout;
sewardjf854f472002-04-21 12:19:41 +00001243 }
1244
1245 /* fprintf(stderr, "MY_POLL: before loop\n"); */
1246
1247 /* Either timeout < 0, meaning wait indefinitely, or timeout > 0,
1248 in which case t_end holds the end time. */
sewardj5f07b662002-04-23 16:52:51 +00001249 assert(__timeout != 0);
1250
sewardjf854f472002-04-21 12:19:41 +00001251 while (1) {
sewardjf854f472002-04-21 12:19:41 +00001252 if (__timeout > 0) {
sewardj5f07b662002-04-23 16:52:51 +00001253 VALGRIND_MAGIC_SEQUENCE(ms_now, 0xFFFFFFFF /* default */,
1254 VG_USERREQ__READ_MILLISECOND_TIMER,
1255 0, 0, 0, 0);
1256 assert(ms_now != 0xFFFFFFFF);
1257 if (ms_now >= ms_end) {
sewardjf854f472002-04-21 12:19:41 +00001258 /* timeout; nothing interesting happened. */
1259 for (i = 0; i < __nfds; i++)
1260 __fds[i].revents = 0;
1261 return 0;
1262 }
1263 }
1264
sewardj5f07b662002-04-23 16:52:51 +00001265 /* Do a return-immediately poll. */
sewardjf854f472002-04-21 12:19:41 +00001266 res = my_do_syscall3(__NR_poll, (int)__fds, __nfds, 0 );
1267 if (is_kerror(res)) {
1268 /* Some kind of error. Set errno and return. */
1269 * (__errno_location()) = -res;
1270 return -1;
1271 }
1272 if (res > 0) {
1273 /* One or more fds is ready. Return now. */
1274 return res;
1275 }
1276 /* fprintf(stderr, "MY_POLL: nanosleep\n"); */
1277 /* nanosleep and go round again */
1278 nanosleep_interval.tv_sec = 0;
sewardj956cc1b2002-04-25 01:33:50 +00001279 nanosleep_interval.tv_nsec = 51 * 1000 * 1000; /* 51 milliseconds */
sewardj08a4c3f2002-04-13 03:45:44 +00001280 /* It's critical here that valgrind's nanosleep implementation
1281 is nonblocking. */
1282 (void)my_do_syscall2(__NR_nanosleep,
1283 (int)(&nanosleep_interval), (int)NULL);
1284 }
1285}
sewardj3b13f0e2002-04-25 20:17:29 +00001286
1287
1288/* ---------------------------------------------------------------------
1289 B'stard.
1290 ------------------------------------------------------------------ */
1291
1292# define strong_alias(name, aliasname) \
1293 extern __typeof (name) aliasname __attribute__ ((alias (#name)));
1294
sewardj5905fae2002-04-26 13:25:00 +00001295# define weak_alias(name, aliasname) \
1296 extern __typeof (name) aliasname __attribute__ ((weak, alias (#name)));
sewardj3b13f0e2002-04-25 20:17:29 +00001297
sewardj5905fae2002-04-26 13:25:00 +00001298#if 1
1299strong_alias(__pthread_mutex_lock, pthread_mutex_lock)
1300strong_alias(__pthread_mutex_trylock, pthread_mutex_trylock)
1301strong_alias(__pthread_mutex_unlock, pthread_mutex_unlock)
1302strong_alias(__pthread_mutexattr_init, pthread_mutexattr_init)
1303 weak_alias(__pthread_mutexattr_settype, pthread_mutexattr_settype)
1304strong_alias(__pthread_mutex_init, pthread_mutex_init)
1305strong_alias(__pthread_mutexattr_destroy, pthread_mutexattr_destroy)
1306strong_alias(__pthread_mutex_destroy, pthread_mutex_destroy)
1307strong_alias(__pthread_once, pthread_once)
1308strong_alias(__pthread_atfork, pthread_atfork)
1309strong_alias(__pthread_key_create, pthread_key_create)
1310strong_alias(__pthread_getspecific, pthread_getspecific)
1311strong_alias(__pthread_setspecific, pthread_setspecific)
1312
1313//strong_alias(__sigaction, sigaction)
sewardj3b13f0e2002-04-25 20:17:29 +00001314strong_alias(sigaction, __sigaction)
1315
sewardj5905fae2002-04-26 13:25:00 +00001316strong_alias(close, __close)
sewardj3b13f0e2002-04-25 20:17:29 +00001317strong_alias(fcntl, __fcntl)
sewardj5905fae2002-04-26 13:25:00 +00001318strong_alias(lseek, __lseek)
1319strong_alias(open, __open)
1320strong_alias(open64, __open64)
1321//strong_alias(pread64, __pread64)
1322//strong_alias(pwrite64, __pwrite64)
1323strong_alias(read, __read)
1324strong_alias(wait, __wait)
1325strong_alias(write, __write)
sewardj3b13f0e2002-04-25 20:17:29 +00001326strong_alias(connect, __connect)
sewardj5905fae2002-04-26 13:25:00 +00001327strong_alias(send, __send)
1328
1329weak_alias(__fork, fork)
1330//weak_alias(__vfork, vfork)
1331
1332#endif
sewardj3b13f0e2002-04-25 20:17:29 +00001333
1334/*--------------------------------------------------*/
1335
sewardj5716dbb2002-04-26 03:28:18 +00001336int
1337pthread_rwlock_rdlock (void* /* pthread_rwlock_t* */ rwlock)
1338{
1339 kludged("pthread_rwlock_rdlock");
1340 return 0;
1341}
1342
sewardj5905fae2002-04-26 13:25:00 +00001343weak_alias(pthread_rwlock_rdlock, __pthread_rwlock_rdlock)
sewardj5716dbb2002-04-26 03:28:18 +00001344
1345
1346int
1347pthread_rwlock_unlock (void* /* pthread_rwlock_t* */ rwlock)
1348{
1349 kludged("pthread_rwlock_unlock");
1350 return 0;
1351}
1352
sewardj5905fae2002-04-26 13:25:00 +00001353weak_alias(pthread_rwlock_unlock, __pthread_rwlock_unlock)
sewardj5716dbb2002-04-26 03:28:18 +00001354
1355
sewardj3b13f0e2002-04-25 20:17:29 +00001356/* I've no idea what these are, but they get called quite a lot.
1357 Anybody know? */
1358
1359#undef _IO_flockfile
1360void _IO_flockfile ( _IO_FILE * file )
1361{
sewardj853f55d2002-04-26 00:27:53 +00001362 //char* str = "_IO_flockfile\n";
1363 //write(2, str, strlen(str));
1364 pthread_mutex_lock(file->_lock);
sewardj3b13f0e2002-04-25 20:17:29 +00001365 // barf("_IO_flockfile");
1366}
sewardj5905fae2002-04-26 13:25:00 +00001367weak_alias(_IO_flockfile, flockfile);
1368
sewardj3b13f0e2002-04-25 20:17:29 +00001369
1370#undef _IO_funlockfile
1371void _IO_funlockfile ( _IO_FILE * file )
1372{
sewardj853f55d2002-04-26 00:27:53 +00001373 //char* str = "_IO_funlockfile\n";
1374 //write(2, str, strlen(str));
1375 pthread_mutex_unlock(file->_lock);
sewardj3b13f0e2002-04-25 20:17:29 +00001376 // barf("_IO_funlockfile");
1377}
sewardj5905fae2002-04-26 13:25:00 +00001378weak_alias(_IO_funlockfile, funlockfile);
1379
sewardj3b13f0e2002-04-25 20:17:29 +00001380
1381void _pthread_cleanup_push_defer ( void )
1382{
1383 // char* str = "_pthread_cleanup_push_defer\n";
1384 // write(2, str, strlen(str));
1385}
1386
1387void _pthread_cleanup_pop_restore ( void )
1388{
1389 // char* str = "_pthread_cleanup_pop_restore\n";
1390 // write(2, str, strlen(str));
1391}