blob: 960d98633d298d9c52a401885339422539270046 [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
sewardj436e0582002-04-26 14:31:40 +000036/* Number of times any given error message is printed. */
37#define N_MOANS 3
38
sewardj45b4b372002-04-16 22:50:32 +000039/* Extract from Valgrind the value of VG_(clo_trace_pthread_level).
40 Returns 0 (none) if not running on Valgrind. */
41static
42int get_pt_trace_level ( void )
43{
44 int res;
45 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
46 VG_USERREQ__GET_PTHREAD_TRACE_LEVEL,
47 0, 0, 0, 0);
48 return res;
49}
50
51
sewardje663cb92002-04-12 10:26:32 +000052static
53void myexit ( int arg )
54{
sewardj45b4b372002-04-16 22:50:32 +000055 int __res;
sewardje663cb92002-04-12 10:26:32 +000056 __asm__ volatile ("movl %%ecx, %%ebx ; int $0x80"
57 : "=a" (__res)
58 : "0" (__NR_exit),
59 "c" (arg) );
sewardj45b4b372002-04-16 22:50:32 +000060 /* We don't bother to mention the fact that this asm trashes %ebx,
61 since it won't return. If you ever do let it return ... fix
62 this! */
sewardje663cb92002-04-12 10:26:32 +000063}
64
65
66/* Give up without using printf etc, since they seem to give
67 segfaults. */
sewardj604ec3c2002-04-18 22:38:41 +000068static __inline__
sewardje663cb92002-04-12 10:26:32 +000069void ensure_valgrind ( char* caller )
70{
71 char* str;
72 int is_valgrind = RUNNING_ON_VALGRIND;
73 if (!is_valgrind) {
74 str = "\nvalgrind-ed process: vg_libpthread.so: "
75 "pthread call when\n";
76 write(2, str, strlen(str));
77 str = "not running on valgrind; aborting! "
78 "This is probably a bug in\n";
79 write(2, str, strlen(str));
80 str = "valgrind. Please report it to me at: "
81 "jseward@acm.org. Thanks.\n";
82 write(2, str, strlen(str));
83 str = "unexpectedly called function is: ";
84 write(2, str, strlen(str));
85 write(2, caller, strlen(caller));
86 str = "\n\n";
87 write(2, str, strlen(str));
88 myexit(1);
89 }
90}
91
92
93static
sewardj3b5d8862002-04-20 13:53:23 +000094__attribute__((noreturn))
sewardje663cb92002-04-12 10:26:32 +000095void barf ( char* str )
96{
97 char buf[100];
98 buf[0] = 0;
99 strcat(buf, "\nvg_libpthread.so: ");
100 strcat(buf, str);
101 strcat(buf, "\n\n");
102 write(2, buf, strlen(buf));
103 myexit(1);
sewardj3b5d8862002-04-20 13:53:23 +0000104 /* We have to persuade gcc into believing this doesn't return. */
105 while (1) { };
sewardje663cb92002-04-12 10:26:32 +0000106}
107
108
sewardj2a3d28c2002-04-14 13:27:00 +0000109static void ignored ( char* msg )
110{
sewardj436e0582002-04-26 14:31:40 +0000111 if (get_pt_trace_level() >= 0) {
sewardj45b4b372002-04-16 22:50:32 +0000112 char* ig = "vg_libpthread.so: IGNORED call to: ";
113 write(2, ig, strlen(ig));
114 write(2, msg, strlen(msg));
115 ig = "\n";
116 write(2, ig, strlen(ig));
117 }
sewardj2a3d28c2002-04-14 13:27:00 +0000118}
119
sewardj30671ff2002-04-21 00:13:57 +0000120static void kludged ( char* msg )
121{
sewardj436e0582002-04-26 14:31:40 +0000122 if (get_pt_trace_level() >= 0) {
sewardj30671ff2002-04-21 00:13:57 +0000123 char* ig = "vg_libpthread.so: KLUDGED call to: ";
124 write(2, ig, strlen(ig));
125 write(2, msg, strlen(msg));
126 ig = "\n";
127 write(2, ig, strlen(ig));
128 }
129}
130
sewardj3b13f0e2002-04-25 20:17:29 +0000131void vgPlain_unimp ( char* what )
132{
133 char* ig = "vg_libpthread.so: UNIMPLEMENTED FUNCTION: ";
134 write(2, ig, strlen(ig));
135 write(2, what, strlen(what));
136 ig = "\n";
137 write(2, ig, strlen(ig));
138 barf("Please report this bug to me at: jseward@acm.org");
139}
140
sewardje663cb92002-04-12 10:26:32 +0000141
142/* ---------------------------------------------------------------------
143 Pass pthread_ calls to Valgrind's request mechanism.
144 ------------------------------------------------------------------ */
145
sewardjf8f819e2002-04-17 23:21:37 +0000146#include <pthread.h>
147#include <stdio.h>
148#include <errno.h>
sewardj5f07b662002-04-23 16:52:51 +0000149#include <assert.h>
150#include <sys/time.h> /* gettimeofday */
sewardjf8f819e2002-04-17 23:21:37 +0000151
152/* ---------------------------------------------------
153 THREAD ATTRIBUTES
154 ------------------------------------------------ */
155
sewardj6af4b5d2002-04-16 04:40:49 +0000156int pthread_attr_init(pthread_attr_t *attr)
157{
sewardj436e0582002-04-26 14:31:40 +0000158 static int moans = N_MOANS;
159 if (moans-- > 0)
160 ignored("pthread_attr_init");
sewardj6af4b5d2002-04-16 04:40:49 +0000161 return 0;
162}
163
164int pthread_attr_setdetachstate(pthread_attr_t *attr, int detachstate)
165{
sewardj436e0582002-04-26 14:31:40 +0000166 static int moans = N_MOANS;
167 if (moans-- > 0)
168 ignored("pthread_attr_setdetachstate");
sewardj6af4b5d2002-04-16 04:40:49 +0000169 return 0;
170}
171
sewardj30671ff2002-04-21 00:13:57 +0000172int pthread_attr_setinheritsched(pthread_attr_t *attr, int inherit)
173{
sewardj436e0582002-04-26 14:31:40 +0000174 static int moans = N_MOANS;
175 if (moans-- > 0)
176 ignored("pthread_attr_setinheritsched");
sewardj30671ff2002-04-21 00:13:57 +0000177 return 0;
178}
sewardj6af4b5d2002-04-16 04:40:49 +0000179
sewardj30671ff2002-04-21 00:13:57 +0000180/* This is completely bogus. */
181int pthread_attr_getschedparam(const pthread_attr_t *attr,
182 struct sched_param *param)
183{
sewardj436e0582002-04-26 14:31:40 +0000184 static int moans = N_MOANS;
185 if (moans-- > 0)
186 kludged("pthread_attr_getschedparam");
sewardj72d58482002-04-24 02:20:20 +0000187# ifdef GLIBC_2_1
188 if (param) param->sched_priority = 0; /* who knows */
189# else
sewardj30671ff2002-04-21 00:13:57 +0000190 if (param) param->__sched_priority = 0; /* who knows */
sewardj72d58482002-04-24 02:20:20 +0000191# endif
sewardj30671ff2002-04-21 00:13:57 +0000192 return 0;
193}
194
195int pthread_attr_setschedparam(pthread_attr_t *attr,
196 const struct sched_param *param)
197{
sewardj436e0582002-04-26 14:31:40 +0000198 static int moans = N_MOANS;
199 if (moans-- > 0)
200 ignored("pthread_attr_setschedparam");
sewardj30671ff2002-04-21 00:13:57 +0000201 return 0;
202}
203
204int pthread_attr_destroy(pthread_attr_t *attr)
205{
sewardj436e0582002-04-26 14:31:40 +0000206 static int moans = N_MOANS;
207 if (moans-- > 0)
208 ignored("pthread_attr_destroy");
sewardj30671ff2002-04-21 00:13:57 +0000209 return 0;
210}
sewardjf8f819e2002-04-17 23:21:37 +0000211
212/* ---------------------------------------------------
213 THREADs
214 ------------------------------------------------ */
215
sewardj6072c362002-04-19 14:40:57 +0000216int pthread_equal(pthread_t thread1, pthread_t thread2)
217{
218 return thread1 == thread2 ? 1 : 0;
219}
220
221
sewardje663cb92002-04-12 10:26:32 +0000222int
223pthread_create (pthread_t *__restrict __thread,
224 __const pthread_attr_t *__restrict __attr,
225 void *(*__start_routine) (void *),
226 void *__restrict __arg)
227{
228 int res;
229 ensure_valgrind("pthread_create");
230 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
231 VG_USERREQ__PTHREAD_CREATE,
232 __thread, __attr, __start_routine, __arg);
233 return res;
234}
235
236
237
238int
239pthread_join (pthread_t __th, void **__thread_return)
240{
241 int res;
242 ensure_valgrind("pthread_join");
243 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
244 VG_USERREQ__PTHREAD_JOIN,
245 __th, __thread_return, 0, 0);
246 return res;
247}
248
249
sewardj3b5d8862002-04-20 13:53:23 +0000250void pthread_exit(void *retval)
251{
252 int res;
253 ensure_valgrind("pthread_exit");
254 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
255 VG_USERREQ__PTHREAD_EXIT,
256 retval, 0, 0, 0);
257 /* Doesn't return! */
258 /* However, we have to fool gcc into knowing that. */
259 barf("pthread_exit: still alive after request?!");
260}
261
sewardje663cb92002-04-12 10:26:32 +0000262
sewardj3b13f0e2002-04-25 20:17:29 +0000263pthread_t pthread_self(void)
sewardje663cb92002-04-12 10:26:32 +0000264{
265 int tid;
sewardj3b13f0e2002-04-25 20:17:29 +0000266 ensure_valgrind("pthread_self");
sewardje663cb92002-04-12 10:26:32 +0000267 VALGRIND_MAGIC_SEQUENCE(tid, 0 /* default */,
268 VG_USERREQ__PTHREAD_GET_THREADID,
269 0, 0, 0, 0);
sewardje663cb92002-04-12 10:26:32 +0000270 if (tid < 0 || tid >= VG_N_THREADS)
sewardj3b13f0e2002-04-25 20:17:29 +0000271 barf("pthread_self: invalid ThreadId");
272 return tid;
sewardje663cb92002-04-12 10:26:32 +0000273}
274
275
sewardj853f55d2002-04-26 00:27:53 +0000276int pthread_detach(pthread_t th)
277{
sewardj436e0582002-04-26 14:31:40 +0000278 static int moans = N_MOANS;
279 if (moans-- > 0)
280 ignored("pthread_detach");
sewardj853f55d2002-04-26 00:27:53 +0000281 return 0;
282}
283
284
sewardjf8f819e2002-04-17 23:21:37 +0000285/* ---------------------------------------------------
286 MUTEX ATTRIBUTES
287 ------------------------------------------------ */
288
sewardj5905fae2002-04-26 13:25:00 +0000289int __pthread_mutexattr_init(pthread_mutexattr_t *attr)
sewardje663cb92002-04-12 10:26:32 +0000290{
sewardjf8f819e2002-04-17 23:21:37 +0000291 attr->__mutexkind = PTHREAD_MUTEX_ERRORCHECK_NP;
sewardj8937c812002-04-12 20:12:20 +0000292 return 0;
sewardje663cb92002-04-12 10:26:32 +0000293}
294
sewardj5905fae2002-04-26 13:25:00 +0000295int __pthread_mutexattr_settype(pthread_mutexattr_t *attr, int type)
sewardjf8f819e2002-04-17 23:21:37 +0000296{
297 switch (type) {
sewardj3b13f0e2002-04-25 20:17:29 +0000298# ifndef GLIBC_2_1
sewardjf8f819e2002-04-17 23:21:37 +0000299 case PTHREAD_MUTEX_TIMED_NP:
sewardj2a1dcce2002-04-22 12:45:25 +0000300 case PTHREAD_MUTEX_ADAPTIVE_NP:
sewardj3b13f0e2002-04-25 20:17:29 +0000301# endif
sewardjf8f819e2002-04-17 23:21:37 +0000302 case PTHREAD_MUTEX_RECURSIVE_NP:
303 case PTHREAD_MUTEX_ERRORCHECK_NP:
sewardjf8f819e2002-04-17 23:21:37 +0000304 attr->__mutexkind = type;
305 return 0;
306 default:
307 return EINVAL;
308 }
309}
310
sewardj5905fae2002-04-26 13:25:00 +0000311int __pthread_mutexattr_destroy(pthread_mutexattr_t *attr)
sewardjf8f819e2002-04-17 23:21:37 +0000312{
313 return 0;
314}
315
316
317/* ---------------------------------------------------
318 MUTEXes
319 ------------------------------------------------ */
320
sewardj5905fae2002-04-26 13:25:00 +0000321int __pthread_mutex_init(pthread_mutex_t *mutex,
322 const pthread_mutexattr_t *mutexattr)
sewardje663cb92002-04-12 10:26:32 +0000323{
sewardj604ec3c2002-04-18 22:38:41 +0000324 mutex->__m_count = 0;
325 mutex->__m_owner = (_pthread_descr)VG_INVALID_THREADID;
326 mutex->__m_kind = PTHREAD_MUTEX_ERRORCHECK_NP;
327 if (mutexattr)
328 mutex->__m_kind = mutexattr->__mutexkind;
329 return 0;
sewardje663cb92002-04-12 10:26:32 +0000330}
331
sewardj5905fae2002-04-26 13:25:00 +0000332int __pthread_mutex_lock(pthread_mutex_t *mutex)
sewardje663cb92002-04-12 10:26:32 +0000333{
334 int res;
sewardj436e0582002-04-26 14:31:40 +0000335 static int moans = N_MOANS;
sewardj45b4b372002-04-16 22:50:32 +0000336 if (!(RUNNING_ON_VALGRIND) && moans-- > 0) {
sewardje663cb92002-04-12 10:26:32 +0000337 char* str = "pthread_mutex_lock-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_LOCK,
343 mutex, 0, 0, 0);
344 return res;
345 }
346}
347
sewardj5905fae2002-04-26 13:25:00 +0000348int __pthread_mutex_trylock(pthread_mutex_t *mutex)
sewardj30671ff2002-04-21 00:13:57 +0000349{
350 int res;
sewardj436e0582002-04-26 14:31:40 +0000351 static int moans = N_MOANS;
sewardj30671ff2002-04-21 00:13:57 +0000352 if (!(RUNNING_ON_VALGRIND) && moans-- > 0) {
353 char* str = "pthread_mutex_trylock-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_TRYLOCK,
359 mutex, 0, 0, 0);
360 return res;
361 }
362}
363
sewardj5905fae2002-04-26 13:25:00 +0000364int __pthread_mutex_unlock(pthread_mutex_t *mutex)
sewardje663cb92002-04-12 10:26:32 +0000365{
366 int res;
sewardj436e0582002-04-26 14:31:40 +0000367 static int moans = N_MOANS;
sewardj45b4b372002-04-16 22:50:32 +0000368 if (!(RUNNING_ON_VALGRIND) && moans-- > 0) {
sewardje663cb92002-04-12 10:26:32 +0000369 char* str = "pthread_mutex_unlock-NOT-INSIDE-VALGRIND\n";
370 write(2, str, strlen(str));
371 return 0;
372 } else {
373 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
374 VG_USERREQ__PTHREAD_MUTEX_UNLOCK,
375 mutex, 0, 0, 0);
376 return res;
377 }
378}
379
sewardj5905fae2002-04-26 13:25:00 +0000380int __pthread_mutex_destroy(pthread_mutex_t *mutex)
sewardje663cb92002-04-12 10:26:32 +0000381{
sewardj604ec3c2002-04-18 22:38:41 +0000382 /* Valgrind doesn't hold any resources on behalf of the mutex, so no
383 need to involve it. */
384 if (mutex->__m_count > 0)
385 return EBUSY;
sewardj6072c362002-04-19 14:40:57 +0000386 mutex->__m_count = 0;
387 mutex->__m_owner = (_pthread_descr)VG_INVALID_THREADID;
388 mutex->__m_kind = PTHREAD_MUTEX_ERRORCHECK_NP;
sewardj604ec3c2002-04-18 22:38:41 +0000389 return 0;
sewardje663cb92002-04-12 10:26:32 +0000390}
391
392
sewardjf8f819e2002-04-17 23:21:37 +0000393/* ---------------------------------------------------
sewardj6072c362002-04-19 14:40:57 +0000394 CONDITION VARIABLES
395 ------------------------------------------------ */
396
397/* LinuxThreads supports no attributes for conditions. Hence ... */
398
399int pthread_condattr_init(pthread_condattr_t *attr)
400{
401 return 0;
402}
403
sewardj0738a592002-04-20 13:59:33 +0000404int pthread_condattr_destroy(pthread_condattr_t *attr)
405{
406 return 0;
407}
sewardj6072c362002-04-19 14:40:57 +0000408
409int pthread_cond_init( pthread_cond_t *cond,
410 const pthread_condattr_t *cond_attr)
411{
412 cond->__c_waiting = (_pthread_descr)VG_INVALID_THREADID;
413 return 0;
414}
415
sewardjf854f472002-04-21 12:19:41 +0000416int pthread_cond_destroy(pthread_cond_t *cond)
417{
418 /* should check that no threads are waiting on this CV */
sewardj436e0582002-04-26 14:31:40 +0000419 static int moans = N_MOANS;
420 if (moans-- > 0)
421 kludged("pthread_cond_destroy");
sewardjf854f472002-04-21 12:19:41 +0000422 return 0;
423}
sewardj6072c362002-04-19 14:40:57 +0000424
425/* ---------------------------------------------------
426 SCHEDULING
427 ------------------------------------------------ */
428
429/* This is completely bogus. */
430int pthread_getschedparam(pthread_t target_thread,
431 int *policy,
432 struct sched_param *param)
433{
sewardj436e0582002-04-26 14:31:40 +0000434 static int moans = N_MOANS;
435 if (moans-- > 0)
436 kludged("pthread_getschedparam");
sewardj6072c362002-04-19 14:40:57 +0000437 if (policy) *policy = SCHED_OTHER;
sewardj2a1dcce2002-04-22 12:45:25 +0000438# ifdef GLIBC_2_1
439 if (param) param->sched_priority = 0; /* who knows */
440# else
sewardj6072c362002-04-19 14:40:57 +0000441 if (param) param->__sched_priority = 0; /* who knows */
sewardj2a1dcce2002-04-22 12:45:25 +0000442# endif
sewardj6072c362002-04-19 14:40:57 +0000443 return 0;
444}
445
446int pthread_setschedparam(pthread_t target_thread,
447 int policy,
448 const struct sched_param *param)
449{
sewardj436e0582002-04-26 14:31:40 +0000450 static int moans = N_MOANS;
451 if (moans-- > 0)
452 ignored("pthread_setschedparam");
sewardj6072c362002-04-19 14:40:57 +0000453 return 0;
454}
455
sewardj3b5d8862002-04-20 13:53:23 +0000456int pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex)
457{
458 int res;
459 ensure_valgrind("pthread_cond_wait");
460 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
461 VG_USERREQ__PTHREAD_COND_WAIT,
462 cond, mutex, 0, 0);
463 return res;
464}
465
sewardj5f07b662002-04-23 16:52:51 +0000466int pthread_cond_timedwait ( pthread_cond_t *cond,
467 pthread_mutex_t *mutex,
468 const struct timespec *abstime )
469{
470 int res;
471 unsigned int ms_now, ms_end;
472 struct timeval timeval_now;
473 unsigned long long int ull_ms_now_after_1970;
474 unsigned long long int ull_ms_end_after_1970;
475
476 ensure_valgrind("pthread_cond_timedwait");
477 VALGRIND_MAGIC_SEQUENCE(ms_now, 0xFFFFFFFF /* default */,
478 VG_USERREQ__READ_MILLISECOND_TIMER,
479 0, 0, 0, 0);
480 assert(ms_now != 0xFFFFFFFF);
481 res = gettimeofday(&timeval_now, NULL);
482 assert(res == 0);
483
484 ull_ms_now_after_1970
485 = 1000ULL * ((unsigned long long int)(timeval_now.tv_sec))
486 + ((unsigned long long int)(timeval_now.tv_usec / 1000000));
487 ull_ms_end_after_1970
488 = 1000ULL * ((unsigned long long int)(abstime->tv_sec))
489 + ((unsigned long long int)(abstime->tv_nsec / 1000000));
490 assert(ull_ms_end_after_1970 >= ull_ms_now_after_1970);
491 ms_end
492 = ms_now + (unsigned int)(ull_ms_end_after_1970 - ull_ms_now_after_1970);
493 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
494 VG_USERREQ__PTHREAD_COND_TIMEDWAIT,
495 cond, mutex, ms_end, 0);
496 return res;
497}
498
499
sewardj3b5d8862002-04-20 13:53:23 +0000500int pthread_cond_signal(pthread_cond_t *cond)
501{
502 int res;
503 ensure_valgrind("pthread_cond_signal");
504 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
505 VG_USERREQ__PTHREAD_COND_SIGNAL,
506 cond, 0, 0, 0);
507 return res;
508}
509
510int pthread_cond_broadcast(pthread_cond_t *cond)
511{
512 int res;
513 ensure_valgrind("pthread_cond_broadcast");
514 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
515 VG_USERREQ__PTHREAD_COND_BROADCAST,
516 cond, 0, 0, 0);
517 return res;
518}
519
sewardj6072c362002-04-19 14:40:57 +0000520
521/* ---------------------------------------------------
sewardjf8f819e2002-04-17 23:21:37 +0000522 CANCELLATION
523 ------------------------------------------------ */
524
sewardj853f55d2002-04-26 00:27:53 +0000525int pthread_setcancelstate(int state, int *oldstate)
526{
sewardj436e0582002-04-26 14:31:40 +0000527 static int moans = N_MOANS;
528 if (moans-- > 0)
529 ignored("pthread_setcancelstate");
sewardj853f55d2002-04-26 00:27:53 +0000530 return 0;
531}
532
sewardje663cb92002-04-12 10:26:32 +0000533int pthread_setcanceltype(int type, int *oldtype)
534{
sewardj436e0582002-04-26 14:31:40 +0000535 static int moans = N_MOANS;
536 if (moans-- > 0)
537 ignored("pthread_setcanceltype");
sewardje663cb92002-04-12 10:26:32 +0000538 return 0;
539}
540
sewardje663cb92002-04-12 10:26:32 +0000541int pthread_cancel(pthread_t thread)
542{
543 int res;
544 ensure_valgrind("pthread_cancel");
545 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
546 VG_USERREQ__PTHREAD_CANCEL,
547 thread, 0, 0, 0);
548 return res;
549}
550
sewardj853f55d2002-04-26 00:27:53 +0000551void pthread_testcancel(void)
552{
553}
554
555/*-------------------*/
556static pthread_mutex_t massacre_mx = PTHREAD_MUTEX_INITIALIZER;
557
558void __pthread_kill_other_threads_np ( void )
559{
560 int i, res, me;
561 pthread_mutex_lock(&massacre_mx);
562 me = pthread_self();
563 for (i = 1; i < VG_N_THREADS; i++) {
564 if (i == me) continue;
565 res = pthread_cancel(i);
sewardj436e0582002-04-26 14:31:40 +0000566 if (0 && res == 0)
sewardj853f55d2002-04-26 00:27:53 +0000567 printf("----------- NUKED %d\n", i);
568 }
569 pthread_mutex_unlock(&massacre_mx);
570}
571
sewardje663cb92002-04-12 10:26:32 +0000572
sewardjf8f819e2002-04-17 23:21:37 +0000573/* ---------------------------------------------------
574 THREAD-SPECIFICs
575 ------------------------------------------------ */
sewardj5e5fa512002-04-14 13:13:05 +0000576
sewardj5905fae2002-04-26 13:25:00 +0000577int __pthread_key_create(pthread_key_t *key,
578 void (*destr_function) (void *))
sewardj5e5fa512002-04-14 13:13:05 +0000579{
sewardj5f07b662002-04-23 16:52:51 +0000580 int res;
581 ensure_valgrind("pthread_key_create");
582 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
583 VG_USERREQ__PTHREAD_KEY_CREATE,
584 key, destr_function, 0, 0);
585 return res;
sewardj5e5fa512002-04-14 13:13:05 +0000586}
587
588int pthread_key_delete(pthread_key_t key)
589{
sewardj436e0582002-04-26 14:31:40 +0000590 static int moans = N_MOANS;
591 if (moans-- > 0)
592 ignored("pthread_key_delete");
sewardj5e5fa512002-04-14 13:13:05 +0000593 return 0;
594}
595
sewardj5905fae2002-04-26 13:25:00 +0000596int __pthread_setspecific(pthread_key_t key, const void *pointer)
sewardj5e5fa512002-04-14 13:13:05 +0000597{
sewardj5f07b662002-04-23 16:52:51 +0000598 int res;
599 ensure_valgrind("pthread_setspecific");
600 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
601 VG_USERREQ__PTHREAD_SETSPECIFIC,
602 key, pointer, 0, 0);
603 return res;
sewardj5e5fa512002-04-14 13:13:05 +0000604}
605
sewardj5905fae2002-04-26 13:25:00 +0000606void * __pthread_getspecific(pthread_key_t key)
sewardj5e5fa512002-04-14 13:13:05 +0000607{
sewardj5f07b662002-04-23 16:52:51 +0000608 int res;
609 ensure_valgrind("pthread_getspecific");
610 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
611 VG_USERREQ__PTHREAD_GETSPECIFIC,
612 key, 0 , 0, 0);
613 return (void*)res;
sewardj5e5fa512002-04-14 13:13:05 +0000614}
615
sewardjf8f819e2002-04-17 23:21:37 +0000616
617/* ---------------------------------------------------
sewardj89d3d852002-04-24 19:21:39 +0000618 ONCEry
619 ------------------------------------------------ */
620
621static pthread_mutex_t once_masterlock = PTHREAD_MUTEX_INITIALIZER;
622
623
sewardj5905fae2002-04-26 13:25:00 +0000624int __pthread_once ( pthread_once_t *once_control,
625 void (*init_routine) (void) )
sewardj89d3d852002-04-24 19:21:39 +0000626{
627 int res;
628 ensure_valgrind("pthread_once");
629
630 res = pthread_mutex_lock(&once_masterlock);
631
632 if (res != 0)
633 barf("pthread_once: Looks like your program's "
634 "init routine calls back to pthread_once() ?!");
635
636 if (*once_control == 0) {
637 *once_control = 1;
638 init_routine();
639 }
640
641 pthread_mutex_unlock(&once_masterlock);
642
643 return 0;
644}
645
646
647/* ---------------------------------------------------
sewardj853f55d2002-04-26 00:27:53 +0000648 MISC
649 ------------------------------------------------ */
650
sewardj5905fae2002-04-26 13:25:00 +0000651int __pthread_atfork ( void (*prepare)(void),
652 void (*parent)(void),
653 void (*child)(void) )
sewardj853f55d2002-04-26 00:27:53 +0000654{
sewardj436e0582002-04-26 14:31:40 +0000655 static int moans = N_MOANS;
656 if (moans-- > 0)
657 ignored("pthread_atfork");
sewardj853f55d2002-04-26 00:27:53 +0000658 return 0;
659}
660
661
662/* ---------------------------------------------------
sewardj3b13f0e2002-04-25 20:17:29 +0000663 LIBRARY-PRIVATE THREAD SPECIFIC STATE
sewardjf8f819e2002-04-17 23:21:37 +0000664 ------------------------------------------------ */
665
sewardj3b13f0e2002-04-25 20:17:29 +0000666#include <resolv.h>
667static int thread_specific_errno[VG_N_THREADS];
668static int thread_specific_h_errno[VG_N_THREADS];
669static struct __res_state
670 thread_specific_res_state[VG_N_THREADS];
sewardjf8f819e2002-04-17 23:21:37 +0000671
sewardj3b13f0e2002-04-25 20:17:29 +0000672int* __errno_location ( void )
sewardjf8f819e2002-04-17 23:21:37 +0000673{
674 int tid;
sewardj3b13f0e2002-04-25 20:17:29 +0000675 /* ensure_valgrind("__errno_location"); */
676 VALGRIND_MAGIC_SEQUENCE(tid, 1 /* default */,
sewardjf8f819e2002-04-17 23:21:37 +0000677 VG_USERREQ__PTHREAD_GET_THREADID,
678 0, 0, 0, 0);
sewardj3b13f0e2002-04-25 20:17:29 +0000679 /* 'cos I'm paranoid ... */
sewardjf8f819e2002-04-17 23:21:37 +0000680 if (tid < 0 || tid >= VG_N_THREADS)
sewardj3b13f0e2002-04-25 20:17:29 +0000681 barf("__errno_location: invalid ThreadId");
682 return & thread_specific_errno[tid];
683}
684
685int* __h_errno_location ( void )
686{
687 int tid;
688 /* ensure_valgrind("__h_errno_location"); */
689 VALGRIND_MAGIC_SEQUENCE(tid, 1 /* default */,
690 VG_USERREQ__PTHREAD_GET_THREADID,
691 0, 0, 0, 0);
692 /* 'cos I'm paranoid ... */
693 if (tid < 0 || tid >= VG_N_THREADS)
694 barf("__h_errno_location: invalid ThreadId");
695 return & thread_specific_h_errno[tid];
696}
697
698struct __res_state* __res_state ( void )
699{
700 int tid;
701 /* ensure_valgrind("__res_state"); */
702 VALGRIND_MAGIC_SEQUENCE(tid, 1 /* default */,
703 VG_USERREQ__PTHREAD_GET_THREADID,
704 0, 0, 0, 0);
705 /* 'cos I'm paranoid ... */
706 if (tid < 0 || tid >= VG_N_THREADS)
707 barf("__res_state: invalid ThreadId");
708 return & thread_specific_res_state[tid];
sewardjf8f819e2002-04-17 23:21:37 +0000709}
710
711
sewardj5716dbb2002-04-26 03:28:18 +0000712/* ---------------------------------------------------
713 LIBC-PRIVATE SPECIFIC DATA
714 ------------------------------------------------ */
715
716/* Relies on assumption that initial private data is NULL. This
717 should be fixed somehow. */
718
719/* The allowable keys (indices) (all 2 of them).
720 From sysdeps/pthread/bits/libc-tsd.h
721*/
722enum __libc_tsd_key_t { _LIBC_TSD_KEY_MALLOC = 0,
723 _LIBC_TSD_KEY_DL_ERROR,
724 _LIBC_TSD_KEY_N };
725
726/* Auto-initialising subsystem. libc_specifics_inited is set
727 after initialisation. libc_specifics_inited_mx guards it. */
728static int libc_specifics_inited = 0;
729static pthread_mutex_t libc_specifics_inited_mx = PTHREAD_MUTEX_INITIALIZER;
730
731/* These are the keys we must initialise the first time. */
732static pthread_key_t libc_specifics_keys[_LIBC_TSD_KEY_N];
733
734/* Initialise the keys, if they are not already initialise. */
735static
736void init_libc_tsd_keys ( void )
737{
738 int res, i;
739 pthread_key_t k;
740
741 res = pthread_mutex_lock(&libc_specifics_inited_mx);
742 if (res != 0) barf("init_libc_tsd_keys: lock");
743
744 if (libc_specifics_inited == 0) {
745 /* printf("INIT libc specifics\n"); */
746 libc_specifics_inited = 1;
747 for (i = 0; i < _LIBC_TSD_KEY_N; i++) {
748 res = pthread_key_create(&k, NULL);
749 if (res != 0) barf("init_libc_tsd_keys: create");
750 libc_specifics_keys[i] = k;
751 }
752 }
753
754 res = pthread_mutex_unlock(&libc_specifics_inited_mx);
755 if (res != 0) barf("init_libc_tsd_keys: unlock");
756}
757
758
759static int
760libc_internal_tsd_set ( enum __libc_tsd_key_t key,
761 const void * pointer )
762{
763 int res;
764 /* printf("SET SET SET key %d ptr %p\n", key, pointer); */
765 if (key < _LIBC_TSD_KEY_MALLOC || key >= _LIBC_TSD_KEY_N)
766 barf("libc_internal_tsd_set: invalid key");
767 init_libc_tsd_keys();
768 res = pthread_setspecific(libc_specifics_keys[key], pointer);
769 if (res != 0) barf("libc_internal_tsd_set: setspecific failed");
770 return 0;
771}
772
773static void *
774libc_internal_tsd_get ( enum __libc_tsd_key_t key )
775{
776 void* v;
777 /* printf("GET GET GET key %d\n", key); */
778 if (key < _LIBC_TSD_KEY_MALLOC || key >= _LIBC_TSD_KEY_N)
779 barf("libc_internal_tsd_get: invalid key");
780 init_libc_tsd_keys();
781 v = pthread_getspecific(libc_specifics_keys[key]);
782 /* if (v == NULL) barf("libc_internal_tsd_set: getspecific failed"); */
783 return v;
784}
785
786
787
788
789int (*__libc_internal_tsd_set)(enum __libc_tsd_key_t key, const void * pointer)
790 = libc_internal_tsd_set;
791
792void* (*__libc_internal_tsd_get)(enum __libc_tsd_key_t key)
793 = libc_internal_tsd_get;
794
795
sewardje663cb92002-04-12 10:26:32 +0000796/* ---------------------------------------------------------------------
797 These are here (I think) because they are deemed cancellation
798 points by POSIX. For the moment we'll simply pass the call along
799 to the corresponding thread-unaware (?) libc routine.
800 ------------------------------------------------------------------ */
801
sewardje663cb92002-04-12 10:26:32 +0000802#include <stdlib.h>
803#include <signal.h>
sewardje663cb92002-04-12 10:26:32 +0000804#include <sys/types.h>
805#include <sys/socket.h>
806
807extern
808int __libc_sigaction
809 (int signum,
810 const struct sigaction *act,
811 struct sigaction *oldact);
812int sigaction(int signum,
813 const struct sigaction *act,
814 struct sigaction *oldact)
815{
sewardj2a1dcce2002-04-22 12:45:25 +0000816# ifdef GLIBC_2_1
817 return __sigaction(signum, act, oldact);
818# else
sewardj45b4b372002-04-16 22:50:32 +0000819 return __libc_sigaction(signum, act, oldact);
sewardj2a1dcce2002-04-22 12:45:25 +0000820# endif
sewardje663cb92002-04-12 10:26:32 +0000821}
822
823
824extern
825int __libc_connect(int sockfd,
826 const struct sockaddr *serv_addr,
827 socklen_t addrlen);
sewardj5905fae2002-04-26 13:25:00 +0000828__attribute__((weak))
sewardje663cb92002-04-12 10:26:32 +0000829int connect(int sockfd,
830 const struct sockaddr *serv_addr,
831 socklen_t addrlen)
832{
sewardj45b4b372002-04-16 22:50:32 +0000833 return __libc_connect(sockfd, serv_addr, addrlen);
sewardje663cb92002-04-12 10:26:32 +0000834}
835
836
837extern
838int __libc_fcntl(int fd, int cmd, long arg);
sewardj5905fae2002-04-26 13:25:00 +0000839__attribute__((weak))
sewardje663cb92002-04-12 10:26:32 +0000840int fcntl(int fd, int cmd, long arg)
841{
sewardj45b4b372002-04-16 22:50:32 +0000842 return __libc_fcntl(fd, cmd, arg);
sewardje663cb92002-04-12 10:26:32 +0000843}
844
845
846extern
847ssize_t __libc_write(int fd, const void *buf, size_t count);
sewardj5905fae2002-04-26 13:25:00 +0000848__attribute__((weak))
sewardje663cb92002-04-12 10:26:32 +0000849ssize_t write(int fd, const void *buf, size_t count)
850{
sewardj45b4b372002-04-16 22:50:32 +0000851 return __libc_write(fd, buf, count);
sewardje663cb92002-04-12 10:26:32 +0000852}
853
854
855extern
856ssize_t __libc_read(int fd, void *buf, size_t count);
sewardj5905fae2002-04-26 13:25:00 +0000857__attribute__((weak))
sewardje663cb92002-04-12 10:26:32 +0000858ssize_t read(int fd, void *buf, size_t count)
859{
sewardj45b4b372002-04-16 22:50:32 +0000860 return __libc_read(fd, buf, count);
sewardje663cb92002-04-12 10:26:32 +0000861}
862
sewardjbe32e452002-04-24 20:29:58 +0000863
864extern
sewardj853f55d2002-04-26 00:27:53 +0000865int __libc_open64(const char *pathname, int flags, mode_t mode);
sewardj5905fae2002-04-26 13:25:00 +0000866__attribute__((weak))
sewardj853f55d2002-04-26 00:27:53 +0000867int open64(const char *pathname, int flags, mode_t mode)
sewardjbe32e452002-04-24 20:29:58 +0000868{
sewardj853f55d2002-04-26 00:27:53 +0000869 return __libc_open64(pathname, flags, mode);
sewardjbe32e452002-04-24 20:29:58 +0000870}
871
sewardje663cb92002-04-12 10:26:32 +0000872
873extern
sewardj853f55d2002-04-26 00:27:53 +0000874int __libc_open(const char *pathname, int flags, mode_t mode);
sewardj5905fae2002-04-26 13:25:00 +0000875__attribute__((weak))
sewardj853f55d2002-04-26 00:27:53 +0000876int open(const char *pathname, int flags, mode_t mode)
sewardje663cb92002-04-12 10:26:32 +0000877{
sewardj853f55d2002-04-26 00:27:53 +0000878 return __libc_open(pathname, flags, mode);
sewardje663cb92002-04-12 10:26:32 +0000879}
880
881
882extern
883int __libc_close(int fd);
sewardj5905fae2002-04-26 13:25:00 +0000884__attribute__((weak))
sewardje663cb92002-04-12 10:26:32 +0000885int close(int fd)
886{
sewardj45b4b372002-04-16 22:50:32 +0000887 return __libc_close(fd);
sewardje663cb92002-04-12 10:26:32 +0000888}
889
890
891extern
892int __libc_accept(int s, struct sockaddr *addr, socklen_t *addrlen);
sewardj5905fae2002-04-26 13:25:00 +0000893__attribute__((weak))
sewardje663cb92002-04-12 10:26:32 +0000894int accept(int s, struct sockaddr *addr, socklen_t *addrlen)
895{
sewardj45b4b372002-04-16 22:50:32 +0000896 return __libc_accept(s, addr, addrlen);
sewardje663cb92002-04-12 10:26:32 +0000897}
898
899
900extern
901pid_t __libc_fork(void);
sewardj5905fae2002-04-26 13:25:00 +0000902pid_t __fork(void)
sewardje663cb92002-04-12 10:26:32 +0000903{
sewardj45b4b372002-04-16 22:50:32 +0000904 return __libc_fork();
sewardje663cb92002-04-12 10:26:32 +0000905}
906
907
908extern
909pid_t __libc_waitpid(pid_t pid, int *status, int options);
sewardj5905fae2002-04-26 13:25:00 +0000910__attribute__((weak))
sewardje663cb92002-04-12 10:26:32 +0000911pid_t waitpid(pid_t pid, int *status, int options)
912{
sewardj45b4b372002-04-16 22:50:32 +0000913 return __libc_waitpid(pid, status, options);
sewardje663cb92002-04-12 10:26:32 +0000914}
915
916
917extern
918int __libc_nanosleep(const struct timespec *req, struct timespec *rem);
sewardj5905fae2002-04-26 13:25:00 +0000919__attribute__((weak))
sewardje663cb92002-04-12 10:26:32 +0000920int nanosleep(const struct timespec *req, struct timespec *rem)
921{
922 return __libc_nanosleep(req, rem);
923}
924
sewardjbe32e452002-04-24 20:29:58 +0000925
sewardje663cb92002-04-12 10:26:32 +0000926extern
927int __libc_fsync(int fd);
sewardj5905fae2002-04-26 13:25:00 +0000928__attribute__((weak))
sewardje663cb92002-04-12 10:26:32 +0000929int fsync(int fd)
930{
sewardj45b4b372002-04-16 22:50:32 +0000931 return __libc_fsync(fd);
sewardje663cb92002-04-12 10:26:32 +0000932}
933
sewardjbe32e452002-04-24 20:29:58 +0000934
sewardj70c75362002-04-13 04:18:32 +0000935extern
936off_t __libc_lseek(int fildes, off_t offset, int whence);
sewardj5905fae2002-04-26 13:25:00 +0000937__attribute__((weak))
sewardj70c75362002-04-13 04:18:32 +0000938off_t lseek(int fildes, off_t offset, int whence)
939{
sewardj45b4b372002-04-16 22:50:32 +0000940 return __libc_lseek(fildes, offset, whence);
sewardj70c75362002-04-13 04:18:32 +0000941}
942
sewardjbe32e452002-04-24 20:29:58 +0000943
944extern
945__off64_t __libc_lseek64(int fildes, __off64_t offset, int whence);
sewardj5905fae2002-04-26 13:25:00 +0000946__attribute__((weak))
sewardjbe32e452002-04-24 20:29:58 +0000947__off64_t lseek64(int fildes, __off64_t offset, int whence)
948{
949 return __libc_lseek64(fildes, offset, whence);
950}
951
952
sewardj6af4b5d2002-04-16 04:40:49 +0000953extern
954void __libc_longjmp(jmp_buf env, int val) __attribute((noreturn));
sewardj5905fae2002-04-26 13:25:00 +0000955/* not weak: __attribute__((weak)) */
sewardj6af4b5d2002-04-16 04:40:49 +0000956void longjmp(jmp_buf env, int val)
957{
958 __libc_longjmp(env, val);
959}
960
sewardjbe32e452002-04-24 20:29:58 +0000961
sewardj6af4b5d2002-04-16 04:40:49 +0000962extern
963int __libc_send(int s, const void *msg, size_t len, int flags);
sewardj5905fae2002-04-26 13:25:00 +0000964__attribute__((weak))
sewardj6af4b5d2002-04-16 04:40:49 +0000965int send(int s, const void *msg, size_t len, int flags)
966{
967 return __libc_send(s, msg, len, flags);
968}
969
sewardjbe32e452002-04-24 20:29:58 +0000970
sewardj1e8cdc92002-04-18 11:37:52 +0000971extern
972int __libc_recv(int s, void *buf, size_t len, int flags);
sewardj5905fae2002-04-26 13:25:00 +0000973__attribute__((weak))
sewardj1e8cdc92002-04-18 11:37:52 +0000974int recv(int s, void *buf, size_t len, int flags)
975{
976 return __libc_recv(s, buf, len, flags);
977}
978
sewardjbe32e452002-04-24 20:29:58 +0000979
sewardj796d6a22002-04-24 02:28:34 +0000980extern
sewardj436e0582002-04-26 14:31:40 +0000981int __libc_recvfrom(int s, void *buf, size_t len, int flags,
982 struct sockaddr *from, socklen_t *fromlen);
983__attribute__((weak))
984int recvfrom(int s, void *buf, size_t len, int flags,
985 struct sockaddr *from, socklen_t *fromlen)
986{
987 return __libc_recvfrom(s, buf, len, flags, from, fromlen);
988}
989
990
991extern
sewardj796d6a22002-04-24 02:28:34 +0000992int __libc_sendto(int s, const void *msg, size_t len, int flags,
993 const struct sockaddr *to, socklen_t tolen);
sewardj5905fae2002-04-26 13:25:00 +0000994__attribute__((weak))
sewardj796d6a22002-04-24 02:28:34 +0000995int sendto(int s, const void *msg, size_t len, int flags,
996 const struct sockaddr *to, socklen_t tolen)
997{
998 return __libc_sendto(s, msg, len, flags, to, tolen);
999}
1000
sewardjbe32e452002-04-24 20:29:58 +00001001
sewardj369b1702002-04-24 13:28:15 +00001002extern
1003int __libc_system(const char* str);
sewardj5905fae2002-04-26 13:25:00 +00001004__attribute__((weak))
sewardj369b1702002-04-24 13:28:15 +00001005int system(const char* str)
1006{
1007 return __libc_system(str);
1008}
1009
sewardjbe32e452002-04-24 20:29:58 +00001010
sewardjab0b1c32002-04-24 19:26:47 +00001011extern
1012pid_t __libc_wait(int *status);
sewardj5905fae2002-04-26 13:25:00 +00001013__attribute__((weak))
sewardjab0b1c32002-04-24 19:26:47 +00001014pid_t wait(int *status)
1015{
1016 return __libc_wait(status);
1017}
1018
sewardj45b4b372002-04-16 22:50:32 +00001019
sewardj5905fae2002-04-26 13:25:00 +00001020
sewardj3b13f0e2002-04-25 20:17:29 +00001021/* ---------------------------------------------------------------------
1022 Nonblocking implementations of select() and poll(). This stuff will
1023 surely rot your mind.
1024 ------------------------------------------------------------------ */
sewardje663cb92002-04-12 10:26:32 +00001025
sewardj08a4c3f2002-04-13 03:45:44 +00001026/*--------------------------------------------------*/
1027
1028#include "vg_kerneliface.h"
1029
1030static
1031__inline__
1032int is_kerror ( int res )
1033{
1034 if (res >= -4095 && res <= -1)
1035 return 1;
1036 else
1037 return 0;
1038}
1039
1040
1041static
1042int my_do_syscall1 ( int syscallno, int arg1 )
1043{
1044 int __res;
1045 __asm__ volatile ("pushl %%ebx; movl %%edx,%%ebx ; int $0x80 ; popl %%ebx"
1046 : "=a" (__res)
1047 : "0" (syscallno),
1048 "d" (arg1) );
1049 return __res;
1050}
1051
1052static
1053int my_do_syscall2 ( int syscallno,
sewardjf854f472002-04-21 12:19:41 +00001054 int arg1, int arg2 )
sewardj08a4c3f2002-04-13 03:45:44 +00001055{
1056 int __res;
1057 __asm__ volatile ("pushl %%ebx; movl %%edx,%%ebx ; int $0x80 ; popl %%ebx"
1058 : "=a" (__res)
1059 : "0" (syscallno),
1060 "d" (arg1),
1061 "c" (arg2) );
1062 return __res;
1063}
1064
1065static
sewardjf854f472002-04-21 12:19:41 +00001066int my_do_syscall3 ( int syscallno,
1067 int arg1, int arg2, int arg3 )
1068{
1069 int __res;
1070 __asm__ volatile ("pushl %%ebx; movl %%esi,%%ebx ; int $0x80 ; popl %%ebx"
1071 : "=a" (__res)
1072 : "0" (syscallno),
1073 "S" (arg1),
1074 "c" (arg2),
1075 "d" (arg3) );
1076 return __res;
1077}
1078
1079static
sewardj08a4c3f2002-04-13 03:45:44 +00001080int do_syscall_select( int n,
1081 vki_fd_set* readfds,
1082 vki_fd_set* writefds,
1083 vki_fd_set* exceptfds,
1084 struct vki_timeval * timeout )
1085{
1086 int res;
1087 int args[5];
1088 args[0] = n;
1089 args[1] = (int)readfds;
1090 args[2] = (int)writefds;
1091 args[3] = (int)exceptfds;
1092 args[4] = (int)timeout;
1093 res = my_do_syscall1(__NR_select, (int)(&(args[0])) );
sewardj02535bc2002-04-21 01:08:26 +00001094 return res;
sewardj08a4c3f2002-04-13 03:45:44 +00001095}
1096
1097
1098/* This is a wrapper round select(), which makes it thread-safe,
1099 meaning that only this thread will block, rather than the entire
1100 process. This wrapper in turn depends on nanosleep() not to block
1101 the entire process, but I think (hope? suspect?) that POSIX
1102 pthreads guarantees that to be the case.
1103
1104 Basic idea is: modify the timeout parameter to select so that it
1105 returns immediately. Poll like this until select returns non-zero,
1106 indicating something interesting happened, or until our time is up.
1107 Space out the polls with nanosleeps of say 20 milliseconds, which
1108 is required to be nonblocking; this allows other threads to run.
sewardj02535bc2002-04-21 01:08:26 +00001109
1110 Assumes:
1111 * (checked via assert) types fd_set and vki_fd_set are identical.
1112 * (checked via assert) types timeval and vki_timeval are identical.
1113 * (unchecked) libc error numbers (EINTR etc) are the negation of the
1114 kernel's error numbers (VKI_EINTR etc).
sewardj08a4c3f2002-04-13 03:45:44 +00001115*/
sewardj08a4c3f2002-04-13 03:45:44 +00001116
sewardj5905fae2002-04-26 13:25:00 +00001117/* __attribute__((weak)) */
sewardj08a4c3f2002-04-13 03:45:44 +00001118int select ( int n,
1119 fd_set *rfds,
1120 fd_set *wfds,
1121 fd_set *xfds,
1122 struct timeval *timeout )
1123{
sewardj5f07b662002-04-23 16:52:51 +00001124 unsigned int ms_now, ms_end;
sewardj08a4c3f2002-04-13 03:45:44 +00001125 int res;
1126 fd_set rfds_copy;
1127 fd_set wfds_copy;
1128 fd_set xfds_copy;
1129 struct vki_timeval t_now;
sewardj08a4c3f2002-04-13 03:45:44 +00001130 struct vki_timeval zero_timeout;
1131 struct vki_timespec nanosleep_interval;
1132
sewardj5f07b662002-04-23 16:52:51 +00001133 /* gcc's complains about ms_end being used uninitialised -- classic
1134 case it can't understand, where ms_end is both defined and used
1135 only if timeout != NULL. Hence ... */
1136 ms_end = 0;
sewardj08a4c3f2002-04-13 03:45:44 +00001137
1138 /* We assume that the kernel and libc data layouts are identical
1139 for the following types. These asserts provide a crude
1140 check. */
1141 if (sizeof(fd_set) != sizeof(vki_fd_set)
1142 || sizeof(struct timeval) != sizeof(struct vki_timeval))
1143 barf("valgrind's hacky non-blocking select(): data sizes error");
1144
sewardj5f07b662002-04-23 16:52:51 +00001145 /* Detect the current time and simultaneously find out if we are
1146 running on Valgrind. */
1147 VALGRIND_MAGIC_SEQUENCE(ms_now, 0xFFFFFFFF /* default */,
1148 VG_USERREQ__READ_MILLISECOND_TIMER,
1149 0, 0, 0, 0);
1150
1151 /* If a zero timeout specified, this call is harmless. Also go
1152 this route if we're not running on Valgrind, for whatever
1153 reason. */
1154 if ( (timeout && timeout->tv_sec == 0 && timeout->tv_usec == 0)
1155 || (ms_now == 0xFFFFFFFF) ) {
sewardj02535bc2002-04-21 01:08:26 +00001156 res = do_syscall_select( n, (vki_fd_set*)rfds,
sewardj08a4c3f2002-04-13 03:45:44 +00001157 (vki_fd_set*)wfds,
1158 (vki_fd_set*)xfds,
1159 (struct vki_timeval*)timeout);
sewardj02535bc2002-04-21 01:08:26 +00001160 if (is_kerror(res)) {
1161 * (__errno_location()) = -res;
1162 return -1;
1163 } else {
1164 return res;
1165 }
1166 }
sewardj08a4c3f2002-04-13 03:45:44 +00001167
sewardj5f07b662002-04-23 16:52:51 +00001168 /* If a timeout was specified, set ms_end to be the end millisecond
1169 counter [wallclock] time. */
sewardj08a4c3f2002-04-13 03:45:44 +00001170 if (timeout) {
1171 res = my_do_syscall2(__NR_gettimeofday, (int)&t_now, (int)NULL);
1172 assert(res == 0);
sewardj5f07b662002-04-23 16:52:51 +00001173 ms_end = ms_now;
1174 ms_end += (timeout->tv_usec / 1000);
1175 ms_end += (timeout->tv_sec * 1000);
sewardj08a4c3f2002-04-13 03:45:44 +00001176 /* Stay sane ... */
sewardj5f07b662002-04-23 16:52:51 +00001177 assert (ms_end >= ms_now);
sewardj08a4c3f2002-04-13 03:45:44 +00001178 }
1179
1180 /* fprintf(stderr, "MY_SELECT: before loop\n"); */
1181
1182 /* Either timeout == NULL, meaning wait indefinitely, or timeout !=
sewardj5f07b662002-04-23 16:52:51 +00001183 NULL, in which case ms_end holds the end time. */
sewardj08a4c3f2002-04-13 03:45:44 +00001184 while (1) {
1185 if (timeout) {
sewardj5f07b662002-04-23 16:52:51 +00001186 VALGRIND_MAGIC_SEQUENCE(ms_now, 0xFFFFFFFF /* default */,
1187 VG_USERREQ__READ_MILLISECOND_TIMER,
1188 0, 0, 0, 0);
1189 assert(ms_now != 0xFFFFFFFF);
1190 if (ms_now >= ms_end) {
sewardj08a4c3f2002-04-13 03:45:44 +00001191 /* timeout; nothing interesting happened. */
1192 if (rfds) FD_ZERO(rfds);
1193 if (wfds) FD_ZERO(wfds);
1194 if (xfds) FD_ZERO(xfds);
1195 return 0;
1196 }
1197 }
1198
1199 /* These could be trashed each time round the loop, so restore
1200 them each time. */
1201 if (rfds) rfds_copy = *rfds;
1202 if (wfds) wfds_copy = *wfds;
1203 if (xfds) xfds_copy = *xfds;
1204
1205 zero_timeout.tv_sec = zero_timeout.tv_usec = 0;
1206
1207 res = do_syscall_select( n,
1208 rfds ? (vki_fd_set*)(&rfds_copy) : NULL,
1209 wfds ? (vki_fd_set*)(&wfds_copy) : NULL,
1210 xfds ? (vki_fd_set*)(&xfds_copy) : NULL,
1211 & zero_timeout );
sewardj02535bc2002-04-21 01:08:26 +00001212 if (is_kerror(res)) {
1213 /* Some kind of error (including EINTR). Set errno and
sewardj08a4c3f2002-04-13 03:45:44 +00001214 return. The sets are unspecified in this case. */
sewardj02535bc2002-04-21 01:08:26 +00001215 * (__errno_location()) = -res;
1216 return -1;
sewardj08a4c3f2002-04-13 03:45:44 +00001217 }
1218 if (res > 0) {
1219 /* one or more fds is ready. Copy out resulting sets and
1220 return. */
1221 if (rfds) *rfds = rfds_copy;
1222 if (wfds) *wfds = wfds_copy;
1223 if (xfds) *xfds = xfds_copy;
1224 return res;
1225 }
1226 /* fprintf(stderr, "MY_SELECT: nanosleep\n"); */
1227 /* nanosleep and go round again */
sewardj02535bc2002-04-21 01:08:26 +00001228 nanosleep_interval.tv_sec = 0;
sewardj956cc1b2002-04-25 01:33:50 +00001229 nanosleep_interval.tv_nsec = 50 * 1000 * 1000; /* 50 milliseconds */
sewardjf854f472002-04-21 12:19:41 +00001230 /* It's critical here that valgrind's nanosleep implementation
1231 is nonblocking. */
1232 (void)my_do_syscall2(__NR_nanosleep,
1233 (int)(&nanosleep_interval), (int)NULL);
1234 }
1235}
1236
1237
1238
1239
1240#include <sys/poll.h>
1241
sewardj72d58482002-04-24 02:20:20 +00001242#ifdef GLIBC_2_1
1243typedef unsigned long int nfds_t;
1244#endif
1245
sewardj5905fae2002-04-26 13:25:00 +00001246/* __attribute__((weak)) */
sewardjf854f472002-04-21 12:19:41 +00001247int poll (struct pollfd *__fds, nfds_t __nfds, int __timeout)
1248{
sewardj5f07b662002-04-23 16:52:51 +00001249 unsigned int ms_now, ms_end;
sewardjf854f472002-04-21 12:19:41 +00001250 int res, i;
sewardjf854f472002-04-21 12:19:41 +00001251 struct vki_timespec nanosleep_interval;
1252
1253 ensure_valgrind("poll");
1254
sewardj5f07b662002-04-23 16:52:51 +00001255 /* Detect the current time and simultaneously find out if we are
1256 running on Valgrind. */
1257 VALGRIND_MAGIC_SEQUENCE(ms_now, 0xFFFFFFFF /* default */,
1258 VG_USERREQ__READ_MILLISECOND_TIMER,
1259 0, 0, 0, 0);
1260
sewardjf854f472002-04-21 12:19:41 +00001261 if (/* CHECK SIZES FOR struct pollfd */
1262 sizeof(struct timeval) != sizeof(struct vki_timeval))
1263 barf("valgrind's hacky non-blocking poll(): data sizes error");
1264
sewardj5f07b662002-04-23 16:52:51 +00001265 /* dummy initialisation to keep gcc -Wall happy */
1266 ms_end = 0;
1267
1268 /* If a zero timeout specified, this call is harmless. Also do
1269 this if not running on Valgrind. */
1270 if (__timeout == 0 || ms_now == 0xFFFFFFFF) {
sewardjf854f472002-04-21 12:19:41 +00001271 res = my_do_syscall3(__NR_poll, (int)__fds, __nfds, __timeout);
1272 if (is_kerror(res)) {
1273 * (__errno_location()) = -res;
1274 return -1;
1275 } else {
1276 return res;
1277 }
1278 }
1279
sewardj5f07b662002-04-23 16:52:51 +00001280 /* If a timeout was specified, set ms_end to be the end wallclock
1281 time. Easy considering that __timeout is in milliseconds. */
sewardjf854f472002-04-21 12:19:41 +00001282 if (__timeout > 0) {
sewardj5f07b662002-04-23 16:52:51 +00001283 ms_end += (unsigned int)__timeout;
sewardjf854f472002-04-21 12:19:41 +00001284 }
1285
1286 /* fprintf(stderr, "MY_POLL: before loop\n"); */
1287
1288 /* Either timeout < 0, meaning wait indefinitely, or timeout > 0,
1289 in which case t_end holds the end time. */
sewardj5f07b662002-04-23 16:52:51 +00001290 assert(__timeout != 0);
1291
sewardjf854f472002-04-21 12:19:41 +00001292 while (1) {
sewardjf854f472002-04-21 12:19:41 +00001293 if (__timeout > 0) {
sewardj5f07b662002-04-23 16:52:51 +00001294 VALGRIND_MAGIC_SEQUENCE(ms_now, 0xFFFFFFFF /* default */,
1295 VG_USERREQ__READ_MILLISECOND_TIMER,
1296 0, 0, 0, 0);
1297 assert(ms_now != 0xFFFFFFFF);
1298 if (ms_now >= ms_end) {
sewardjf854f472002-04-21 12:19:41 +00001299 /* timeout; nothing interesting happened. */
1300 for (i = 0; i < __nfds; i++)
1301 __fds[i].revents = 0;
1302 return 0;
1303 }
1304 }
1305
sewardj5f07b662002-04-23 16:52:51 +00001306 /* Do a return-immediately poll. */
sewardjf854f472002-04-21 12:19:41 +00001307 res = my_do_syscall3(__NR_poll, (int)__fds, __nfds, 0 );
1308 if (is_kerror(res)) {
1309 /* Some kind of error. Set errno and return. */
1310 * (__errno_location()) = -res;
1311 return -1;
1312 }
1313 if (res > 0) {
1314 /* One or more fds is ready. Return now. */
1315 return res;
1316 }
1317 /* fprintf(stderr, "MY_POLL: nanosleep\n"); */
1318 /* nanosleep and go round again */
1319 nanosleep_interval.tv_sec = 0;
sewardj956cc1b2002-04-25 01:33:50 +00001320 nanosleep_interval.tv_nsec = 51 * 1000 * 1000; /* 51 milliseconds */
sewardj08a4c3f2002-04-13 03:45:44 +00001321 /* It's critical here that valgrind's nanosleep implementation
1322 is nonblocking. */
1323 (void)my_do_syscall2(__NR_nanosleep,
1324 (int)(&nanosleep_interval), (int)NULL);
1325 }
1326}
sewardj3b13f0e2002-04-25 20:17:29 +00001327
1328
1329/* ---------------------------------------------------------------------
1330 B'stard.
1331 ------------------------------------------------------------------ */
1332
1333# define strong_alias(name, aliasname) \
1334 extern __typeof (name) aliasname __attribute__ ((alias (#name)));
1335
sewardj5905fae2002-04-26 13:25:00 +00001336# define weak_alias(name, aliasname) \
1337 extern __typeof (name) aliasname __attribute__ ((weak, alias (#name)));
sewardj3b13f0e2002-04-25 20:17:29 +00001338
sewardj5905fae2002-04-26 13:25:00 +00001339#if 1
1340strong_alias(__pthread_mutex_lock, pthread_mutex_lock)
1341strong_alias(__pthread_mutex_trylock, pthread_mutex_trylock)
1342strong_alias(__pthread_mutex_unlock, pthread_mutex_unlock)
1343strong_alias(__pthread_mutexattr_init, pthread_mutexattr_init)
1344 weak_alias(__pthread_mutexattr_settype, pthread_mutexattr_settype)
1345strong_alias(__pthread_mutex_init, pthread_mutex_init)
1346strong_alias(__pthread_mutexattr_destroy, pthread_mutexattr_destroy)
1347strong_alias(__pthread_mutex_destroy, pthread_mutex_destroy)
1348strong_alias(__pthread_once, pthread_once)
1349strong_alias(__pthread_atfork, pthread_atfork)
1350strong_alias(__pthread_key_create, pthread_key_create)
1351strong_alias(__pthread_getspecific, pthread_getspecific)
1352strong_alias(__pthread_setspecific, pthread_setspecific)
1353
1354//strong_alias(__sigaction, sigaction)
sewardj3b13f0e2002-04-25 20:17:29 +00001355strong_alias(sigaction, __sigaction)
1356
sewardj5905fae2002-04-26 13:25:00 +00001357strong_alias(close, __close)
sewardj3b13f0e2002-04-25 20:17:29 +00001358strong_alias(fcntl, __fcntl)
sewardj5905fae2002-04-26 13:25:00 +00001359strong_alias(lseek, __lseek)
1360strong_alias(open, __open)
1361strong_alias(open64, __open64)
1362//strong_alias(pread64, __pread64)
1363//strong_alias(pwrite64, __pwrite64)
1364strong_alias(read, __read)
1365strong_alias(wait, __wait)
1366strong_alias(write, __write)
sewardj3b13f0e2002-04-25 20:17:29 +00001367strong_alias(connect, __connect)
sewardj5905fae2002-04-26 13:25:00 +00001368strong_alias(send, __send)
1369
1370weak_alias(__fork, fork)
1371//weak_alias(__vfork, vfork)
1372
1373#endif
sewardj3b13f0e2002-04-25 20:17:29 +00001374
1375/*--------------------------------------------------*/
1376
sewardj5716dbb2002-04-26 03:28:18 +00001377int
1378pthread_rwlock_rdlock (void* /* pthread_rwlock_t* */ rwlock)
1379{
sewardj436e0582002-04-26 14:31:40 +00001380 static int moans = N_MOANS;
1381 if (moans-- > 0)
1382 kludged("pthread_rwlock_rdlock");
sewardj5716dbb2002-04-26 03:28:18 +00001383 return 0;
1384}
1385
sewardj5905fae2002-04-26 13:25:00 +00001386weak_alias(pthread_rwlock_rdlock, __pthread_rwlock_rdlock)
sewardj5716dbb2002-04-26 03:28:18 +00001387
1388
1389int
1390pthread_rwlock_unlock (void* /* pthread_rwlock_t* */ rwlock)
1391{
sewardj436e0582002-04-26 14:31:40 +00001392 static int moans = N_MOANS;
1393 if (moans-- > 0)
1394 kludged("pthread_rwlock_unlock");
sewardj5716dbb2002-04-26 03:28:18 +00001395 return 0;
1396}
1397
sewardj5905fae2002-04-26 13:25:00 +00001398weak_alias(pthread_rwlock_unlock, __pthread_rwlock_unlock)
sewardj5716dbb2002-04-26 03:28:18 +00001399
1400
sewardj060b04f2002-04-26 21:01:13 +00001401int
1402pthread_rwlock_wrlock (void* /* pthread_rwlock_t* */ rwlock)
1403{
1404 static int moans = N_MOANS;
1405 if (moans-- > 0)
1406 kludged("pthread_rwlock_wrlock");
1407 return 0;
1408}
1409
1410weak_alias(pthread_rwlock_wrlock, __pthread_wrlock_unlock)
1411
1412
sewardj3b13f0e2002-04-25 20:17:29 +00001413/* I've no idea what these are, but they get called quite a lot.
1414 Anybody know? */
1415
1416#undef _IO_flockfile
1417void _IO_flockfile ( _IO_FILE * file )
1418{
sewardj853f55d2002-04-26 00:27:53 +00001419 //char* str = "_IO_flockfile\n";
1420 //write(2, str, strlen(str));
1421 pthread_mutex_lock(file->_lock);
sewardj3b13f0e2002-04-25 20:17:29 +00001422 // barf("_IO_flockfile");
1423}
sewardj5905fae2002-04-26 13:25:00 +00001424weak_alias(_IO_flockfile, flockfile);
1425
sewardj3b13f0e2002-04-25 20:17:29 +00001426
1427#undef _IO_funlockfile
1428void _IO_funlockfile ( _IO_FILE * file )
1429{
sewardj853f55d2002-04-26 00:27:53 +00001430 //char* str = "_IO_funlockfile\n";
1431 //write(2, str, strlen(str));
1432 pthread_mutex_unlock(file->_lock);
sewardj3b13f0e2002-04-25 20:17:29 +00001433 // barf("_IO_funlockfile");
1434}
sewardj5905fae2002-04-26 13:25:00 +00001435weak_alias(_IO_funlockfile, funlockfile);
1436
sewardj3b13f0e2002-04-25 20:17:29 +00001437
1438void _pthread_cleanup_push_defer ( void )
1439{
1440 // char* str = "_pthread_cleanup_push_defer\n";
1441 // write(2, str, strlen(str));
1442}
1443
1444void _pthread_cleanup_pop_restore ( void )
1445{
1446 // char* str = "_pthread_cleanup_pop_restore\n";
1447 // write(2, str, strlen(str));
1448}