blob: beaeea5b957cef0cdf7997486741c33635305ea3 [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*/
sewardj70adeb22002-04-27 01:35:38 +0000722#define N_LIBC_TSD_EXTRA_KEYS 1
723
sewardj5716dbb2002-04-26 03:28:18 +0000724enum __libc_tsd_key_t { _LIBC_TSD_KEY_MALLOC = 0,
725 _LIBC_TSD_KEY_DL_ERROR,
726 _LIBC_TSD_KEY_N };
727
728/* Auto-initialising subsystem. libc_specifics_inited is set
729 after initialisation. libc_specifics_inited_mx guards it. */
730static int libc_specifics_inited = 0;
731static pthread_mutex_t libc_specifics_inited_mx = PTHREAD_MUTEX_INITIALIZER;
732
733/* These are the keys we must initialise the first time. */
sewardj70adeb22002-04-27 01:35:38 +0000734static pthread_key_t libc_specifics_keys[_LIBC_TSD_KEY_N
735 + N_LIBC_TSD_EXTRA_KEYS];
sewardj5716dbb2002-04-26 03:28:18 +0000736
737/* Initialise the keys, if they are not already initialise. */
738static
739void init_libc_tsd_keys ( void )
740{
741 int res, i;
742 pthread_key_t k;
743
744 res = pthread_mutex_lock(&libc_specifics_inited_mx);
745 if (res != 0) barf("init_libc_tsd_keys: lock");
746
747 if (libc_specifics_inited == 0) {
748 /* printf("INIT libc specifics\n"); */
749 libc_specifics_inited = 1;
sewardj70adeb22002-04-27 01:35:38 +0000750 for (i = 0; i < _LIBC_TSD_KEY_N + N_LIBC_TSD_EXTRA_KEYS; i++) {
sewardj5716dbb2002-04-26 03:28:18 +0000751 res = pthread_key_create(&k, NULL);
752 if (res != 0) barf("init_libc_tsd_keys: create");
753 libc_specifics_keys[i] = k;
754 }
755 }
756
757 res = pthread_mutex_unlock(&libc_specifics_inited_mx);
758 if (res != 0) barf("init_libc_tsd_keys: unlock");
759}
760
761
762static int
763libc_internal_tsd_set ( enum __libc_tsd_key_t key,
764 const void * pointer )
765{
sewardj70adeb22002-04-27 01:35:38 +0000766 int res;
767 static int moans = N_MOANS;
sewardj5716dbb2002-04-26 03:28:18 +0000768 /* printf("SET SET SET key %d ptr %p\n", key, pointer); */
sewardj70adeb22002-04-27 01:35:38 +0000769 if (key < _LIBC_TSD_KEY_MALLOC
770 || key >= _LIBC_TSD_KEY_N + N_LIBC_TSD_EXTRA_KEYS)
sewardj5716dbb2002-04-26 03:28:18 +0000771 barf("libc_internal_tsd_set: invalid key");
sewardj70adeb22002-04-27 01:35:38 +0000772 if (key >= _LIBC_TSD_KEY_N && moans-- > 0)
773 fprintf(stderr,
774 "vg_libpthread.so: libc_internal_tsd_set: dubious key %d\n", key);
sewardj5716dbb2002-04-26 03:28:18 +0000775 init_libc_tsd_keys();
776 res = pthread_setspecific(libc_specifics_keys[key], pointer);
777 if (res != 0) barf("libc_internal_tsd_set: setspecific failed");
778 return 0;
779}
780
781static void *
782libc_internal_tsd_get ( enum __libc_tsd_key_t key )
783{
sewardj70adeb22002-04-27 01:35:38 +0000784 void* v;
785 static int moans = N_MOANS;
sewardj5716dbb2002-04-26 03:28:18 +0000786 /* printf("GET GET GET key %d\n", key); */
sewardj70adeb22002-04-27 01:35:38 +0000787 if (key < _LIBC_TSD_KEY_MALLOC
788 || key >= _LIBC_TSD_KEY_N + N_LIBC_TSD_EXTRA_KEYS)
sewardj5716dbb2002-04-26 03:28:18 +0000789 barf("libc_internal_tsd_get: invalid key");
sewardj70adeb22002-04-27 01:35:38 +0000790 if (key >= _LIBC_TSD_KEY_N && moans-- > 0)
791 fprintf(stderr,
792 "vg_libpthread.so: libc_internal_tsd_get: dubious key %d\n", key);
sewardj5716dbb2002-04-26 03:28:18 +0000793 init_libc_tsd_keys();
794 v = pthread_getspecific(libc_specifics_keys[key]);
795 /* if (v == NULL) barf("libc_internal_tsd_set: getspecific failed"); */
796 return v;
797}
798
799
800
801
sewardj70adeb22002-04-27 01:35:38 +0000802int (*__libc_internal_tsd_set)
803 (enum __libc_tsd_key_t key, const void * pointer)
804 = libc_internal_tsd_set;
sewardj5716dbb2002-04-26 03:28:18 +0000805
sewardj70adeb22002-04-27 01:35:38 +0000806void* (*__libc_internal_tsd_get)
807 (enum __libc_tsd_key_t key)
808 = libc_internal_tsd_get;
sewardj5716dbb2002-04-26 03:28:18 +0000809
810
sewardje663cb92002-04-12 10:26:32 +0000811/* ---------------------------------------------------------------------
812 These are here (I think) because they are deemed cancellation
813 points by POSIX. For the moment we'll simply pass the call along
814 to the corresponding thread-unaware (?) libc routine.
815 ------------------------------------------------------------------ */
816
sewardje663cb92002-04-12 10:26:32 +0000817#include <stdlib.h>
818#include <signal.h>
sewardje663cb92002-04-12 10:26:32 +0000819#include <sys/types.h>
820#include <sys/socket.h>
821
822extern
823int __libc_sigaction
824 (int signum,
825 const struct sigaction *act,
826 struct sigaction *oldact);
827int sigaction(int signum,
828 const struct sigaction *act,
829 struct sigaction *oldact)
830{
sewardj2a1dcce2002-04-22 12:45:25 +0000831# ifdef GLIBC_2_1
832 return __sigaction(signum, act, oldact);
833# else
sewardj45b4b372002-04-16 22:50:32 +0000834 return __libc_sigaction(signum, act, oldact);
sewardj2a1dcce2002-04-22 12:45:25 +0000835# endif
sewardje663cb92002-04-12 10:26:32 +0000836}
837
838
839extern
840int __libc_connect(int sockfd,
841 const struct sockaddr *serv_addr,
842 socklen_t addrlen);
sewardj5905fae2002-04-26 13:25:00 +0000843__attribute__((weak))
sewardje663cb92002-04-12 10:26:32 +0000844int connect(int sockfd,
845 const struct sockaddr *serv_addr,
846 socklen_t addrlen)
847{
sewardj45b4b372002-04-16 22:50:32 +0000848 return __libc_connect(sockfd, serv_addr, addrlen);
sewardje663cb92002-04-12 10:26:32 +0000849}
850
851
852extern
853int __libc_fcntl(int fd, int cmd, long arg);
sewardj5905fae2002-04-26 13:25:00 +0000854__attribute__((weak))
sewardje663cb92002-04-12 10:26:32 +0000855int fcntl(int fd, int cmd, long arg)
856{
sewardj45b4b372002-04-16 22:50:32 +0000857 return __libc_fcntl(fd, cmd, arg);
sewardje663cb92002-04-12 10:26:32 +0000858}
859
860
861extern
862ssize_t __libc_write(int fd, const void *buf, size_t count);
sewardj5905fae2002-04-26 13:25:00 +0000863__attribute__((weak))
sewardje663cb92002-04-12 10:26:32 +0000864ssize_t write(int fd, const void *buf, size_t count)
865{
sewardj45b4b372002-04-16 22:50:32 +0000866 return __libc_write(fd, buf, count);
sewardje663cb92002-04-12 10:26:32 +0000867}
868
869
870extern
871ssize_t __libc_read(int fd, void *buf, size_t count);
sewardj5905fae2002-04-26 13:25:00 +0000872__attribute__((weak))
sewardje663cb92002-04-12 10:26:32 +0000873ssize_t read(int fd, void *buf, size_t count)
874{
sewardj45b4b372002-04-16 22:50:32 +0000875 return __libc_read(fd, buf, count);
sewardje663cb92002-04-12 10:26:32 +0000876}
877
sewardjbe32e452002-04-24 20:29:58 +0000878
879extern
sewardj853f55d2002-04-26 00:27:53 +0000880int __libc_open64(const char *pathname, int flags, mode_t mode);
sewardj5905fae2002-04-26 13:25:00 +0000881__attribute__((weak))
sewardj853f55d2002-04-26 00:27:53 +0000882int open64(const char *pathname, int flags, mode_t mode)
sewardjbe32e452002-04-24 20:29:58 +0000883{
sewardj853f55d2002-04-26 00:27:53 +0000884 return __libc_open64(pathname, flags, mode);
sewardjbe32e452002-04-24 20:29:58 +0000885}
886
sewardje663cb92002-04-12 10:26:32 +0000887
888extern
sewardj853f55d2002-04-26 00:27:53 +0000889int __libc_open(const char *pathname, int flags, mode_t mode);
sewardj5905fae2002-04-26 13:25:00 +0000890__attribute__((weak))
sewardj853f55d2002-04-26 00:27:53 +0000891int open(const char *pathname, int flags, mode_t mode)
sewardje663cb92002-04-12 10:26:32 +0000892{
sewardj853f55d2002-04-26 00:27:53 +0000893 return __libc_open(pathname, flags, mode);
sewardje663cb92002-04-12 10:26:32 +0000894}
895
896
897extern
898int __libc_close(int fd);
sewardj5905fae2002-04-26 13:25:00 +0000899__attribute__((weak))
sewardje663cb92002-04-12 10:26:32 +0000900int close(int fd)
901{
sewardj45b4b372002-04-16 22:50:32 +0000902 return __libc_close(fd);
sewardje663cb92002-04-12 10:26:32 +0000903}
904
905
906extern
907int __libc_accept(int s, struct sockaddr *addr, socklen_t *addrlen);
sewardj5905fae2002-04-26 13:25:00 +0000908__attribute__((weak))
sewardje663cb92002-04-12 10:26:32 +0000909int accept(int s, struct sockaddr *addr, socklen_t *addrlen)
910{
sewardj45b4b372002-04-16 22:50:32 +0000911 return __libc_accept(s, addr, addrlen);
sewardje663cb92002-04-12 10:26:32 +0000912}
913
914
915extern
916pid_t __libc_fork(void);
sewardj5905fae2002-04-26 13:25:00 +0000917pid_t __fork(void)
sewardje663cb92002-04-12 10:26:32 +0000918{
sewardj45b4b372002-04-16 22:50:32 +0000919 return __libc_fork();
sewardje663cb92002-04-12 10:26:32 +0000920}
921
922
923extern
924pid_t __libc_waitpid(pid_t pid, int *status, int options);
sewardj5905fae2002-04-26 13:25:00 +0000925__attribute__((weak))
sewardje663cb92002-04-12 10:26:32 +0000926pid_t waitpid(pid_t pid, int *status, int options)
927{
sewardj45b4b372002-04-16 22:50:32 +0000928 return __libc_waitpid(pid, status, options);
sewardje663cb92002-04-12 10:26:32 +0000929}
930
931
932extern
933int __libc_nanosleep(const struct timespec *req, struct timespec *rem);
sewardj5905fae2002-04-26 13:25:00 +0000934__attribute__((weak))
sewardje663cb92002-04-12 10:26:32 +0000935int nanosleep(const struct timespec *req, struct timespec *rem)
936{
937 return __libc_nanosleep(req, rem);
938}
939
sewardjbe32e452002-04-24 20:29:58 +0000940
sewardje663cb92002-04-12 10:26:32 +0000941extern
942int __libc_fsync(int fd);
sewardj5905fae2002-04-26 13:25:00 +0000943__attribute__((weak))
sewardje663cb92002-04-12 10:26:32 +0000944int fsync(int fd)
945{
sewardj45b4b372002-04-16 22:50:32 +0000946 return __libc_fsync(fd);
sewardje663cb92002-04-12 10:26:32 +0000947}
948
sewardjbe32e452002-04-24 20:29:58 +0000949
sewardj70c75362002-04-13 04:18:32 +0000950extern
951off_t __libc_lseek(int fildes, off_t offset, int whence);
sewardj5905fae2002-04-26 13:25:00 +0000952__attribute__((weak))
sewardj70c75362002-04-13 04:18:32 +0000953off_t lseek(int fildes, off_t offset, int whence)
954{
sewardj45b4b372002-04-16 22:50:32 +0000955 return __libc_lseek(fildes, offset, whence);
sewardj70c75362002-04-13 04:18:32 +0000956}
957
sewardjbe32e452002-04-24 20:29:58 +0000958
959extern
960__off64_t __libc_lseek64(int fildes, __off64_t offset, int whence);
sewardj5905fae2002-04-26 13:25:00 +0000961__attribute__((weak))
sewardjbe32e452002-04-24 20:29:58 +0000962__off64_t lseek64(int fildes, __off64_t offset, int whence)
963{
964 return __libc_lseek64(fildes, offset, whence);
965}
966
967
sewardj6af4b5d2002-04-16 04:40:49 +0000968extern
969void __libc_longjmp(jmp_buf env, int val) __attribute((noreturn));
sewardj5905fae2002-04-26 13:25:00 +0000970/* not weak: __attribute__((weak)) */
sewardj6af4b5d2002-04-16 04:40:49 +0000971void longjmp(jmp_buf env, int val)
972{
973 __libc_longjmp(env, val);
974}
975
sewardjbe32e452002-04-24 20:29:58 +0000976
sewardj6af4b5d2002-04-16 04:40:49 +0000977extern
978int __libc_send(int s, const void *msg, size_t len, int flags);
sewardj5905fae2002-04-26 13:25:00 +0000979__attribute__((weak))
sewardj6af4b5d2002-04-16 04:40:49 +0000980int send(int s, const void *msg, size_t len, int flags)
981{
982 return __libc_send(s, msg, len, flags);
983}
984
sewardjbe32e452002-04-24 20:29:58 +0000985
sewardj1e8cdc92002-04-18 11:37:52 +0000986extern
987int __libc_recv(int s, void *buf, size_t len, int flags);
sewardj5905fae2002-04-26 13:25:00 +0000988__attribute__((weak))
sewardj1e8cdc92002-04-18 11:37:52 +0000989int recv(int s, void *buf, size_t len, int flags)
990{
991 return __libc_recv(s, buf, len, flags);
992}
993
sewardjbe32e452002-04-24 20:29:58 +0000994
sewardj796d6a22002-04-24 02:28:34 +0000995extern
sewardj436e0582002-04-26 14:31:40 +0000996int __libc_recvfrom(int s, void *buf, size_t len, int flags,
997 struct sockaddr *from, socklen_t *fromlen);
998__attribute__((weak))
999int recvfrom(int s, void *buf, size_t len, int flags,
1000 struct sockaddr *from, socklen_t *fromlen)
1001{
1002 return __libc_recvfrom(s, buf, len, flags, from, fromlen);
1003}
1004
1005
1006extern
sewardj796d6a22002-04-24 02:28:34 +00001007int __libc_sendto(int s, const void *msg, size_t len, int flags,
1008 const struct sockaddr *to, socklen_t tolen);
sewardj5905fae2002-04-26 13:25:00 +00001009__attribute__((weak))
sewardj796d6a22002-04-24 02:28:34 +00001010int sendto(int s, const void *msg, size_t len, int flags,
1011 const struct sockaddr *to, socklen_t tolen)
1012{
1013 return __libc_sendto(s, msg, len, flags, to, tolen);
1014}
1015
sewardjbe32e452002-04-24 20:29:58 +00001016
sewardj369b1702002-04-24 13:28:15 +00001017extern
1018int __libc_system(const char* str);
sewardj5905fae2002-04-26 13:25:00 +00001019__attribute__((weak))
sewardj369b1702002-04-24 13:28:15 +00001020int system(const char* str)
1021{
1022 return __libc_system(str);
1023}
1024
sewardjbe32e452002-04-24 20:29:58 +00001025
sewardjab0b1c32002-04-24 19:26:47 +00001026extern
1027pid_t __libc_wait(int *status);
sewardj5905fae2002-04-26 13:25:00 +00001028__attribute__((weak))
sewardjab0b1c32002-04-24 19:26:47 +00001029pid_t wait(int *status)
1030{
1031 return __libc_wait(status);
1032}
1033
sewardj45b4b372002-04-16 22:50:32 +00001034
sewardj5905fae2002-04-26 13:25:00 +00001035
sewardj3b13f0e2002-04-25 20:17:29 +00001036/* ---------------------------------------------------------------------
1037 Nonblocking implementations of select() and poll(). This stuff will
1038 surely rot your mind.
1039 ------------------------------------------------------------------ */
sewardje663cb92002-04-12 10:26:32 +00001040
sewardj08a4c3f2002-04-13 03:45:44 +00001041/*--------------------------------------------------*/
1042
1043#include "vg_kerneliface.h"
1044
1045static
1046__inline__
1047int is_kerror ( int res )
1048{
1049 if (res >= -4095 && res <= -1)
1050 return 1;
1051 else
1052 return 0;
1053}
1054
1055
1056static
1057int my_do_syscall1 ( int syscallno, int arg1 )
1058{
1059 int __res;
1060 __asm__ volatile ("pushl %%ebx; movl %%edx,%%ebx ; int $0x80 ; popl %%ebx"
1061 : "=a" (__res)
1062 : "0" (syscallno),
1063 "d" (arg1) );
1064 return __res;
1065}
1066
1067static
1068int my_do_syscall2 ( int syscallno,
sewardjf854f472002-04-21 12:19:41 +00001069 int arg1, int arg2 )
sewardj08a4c3f2002-04-13 03:45:44 +00001070{
1071 int __res;
1072 __asm__ volatile ("pushl %%ebx; movl %%edx,%%ebx ; int $0x80 ; popl %%ebx"
1073 : "=a" (__res)
1074 : "0" (syscallno),
1075 "d" (arg1),
1076 "c" (arg2) );
1077 return __res;
1078}
1079
1080static
sewardjf854f472002-04-21 12:19:41 +00001081int my_do_syscall3 ( int syscallno,
1082 int arg1, int arg2, int arg3 )
1083{
1084 int __res;
1085 __asm__ volatile ("pushl %%ebx; movl %%esi,%%ebx ; int $0x80 ; popl %%ebx"
1086 : "=a" (__res)
1087 : "0" (syscallno),
1088 "S" (arg1),
1089 "c" (arg2),
1090 "d" (arg3) );
1091 return __res;
1092}
1093
1094static
sewardj08a4c3f2002-04-13 03:45:44 +00001095int do_syscall_select( int n,
1096 vki_fd_set* readfds,
1097 vki_fd_set* writefds,
1098 vki_fd_set* exceptfds,
1099 struct vki_timeval * timeout )
1100{
1101 int res;
1102 int args[5];
1103 args[0] = n;
1104 args[1] = (int)readfds;
1105 args[2] = (int)writefds;
1106 args[3] = (int)exceptfds;
1107 args[4] = (int)timeout;
1108 res = my_do_syscall1(__NR_select, (int)(&(args[0])) );
sewardj02535bc2002-04-21 01:08:26 +00001109 return res;
sewardj08a4c3f2002-04-13 03:45:44 +00001110}
1111
1112
1113/* This is a wrapper round select(), which makes it thread-safe,
1114 meaning that only this thread will block, rather than the entire
1115 process. This wrapper in turn depends on nanosleep() not to block
1116 the entire process, but I think (hope? suspect?) that POSIX
1117 pthreads guarantees that to be the case.
1118
1119 Basic idea is: modify the timeout parameter to select so that it
1120 returns immediately. Poll like this until select returns non-zero,
1121 indicating something interesting happened, or until our time is up.
1122 Space out the polls with nanosleeps of say 20 milliseconds, which
1123 is required to be nonblocking; this allows other threads to run.
sewardj02535bc2002-04-21 01:08:26 +00001124
1125 Assumes:
1126 * (checked via assert) types fd_set and vki_fd_set are identical.
1127 * (checked via assert) types timeval and vki_timeval are identical.
1128 * (unchecked) libc error numbers (EINTR etc) are the negation of the
1129 kernel's error numbers (VKI_EINTR etc).
sewardj08a4c3f2002-04-13 03:45:44 +00001130*/
sewardj08a4c3f2002-04-13 03:45:44 +00001131
sewardj5905fae2002-04-26 13:25:00 +00001132/* __attribute__((weak)) */
sewardj08a4c3f2002-04-13 03:45:44 +00001133int select ( int n,
1134 fd_set *rfds,
1135 fd_set *wfds,
1136 fd_set *xfds,
1137 struct timeval *timeout )
1138{
sewardj5f07b662002-04-23 16:52:51 +00001139 unsigned int ms_now, ms_end;
sewardj08a4c3f2002-04-13 03:45:44 +00001140 int res;
1141 fd_set rfds_copy;
1142 fd_set wfds_copy;
1143 fd_set xfds_copy;
1144 struct vki_timeval t_now;
sewardj08a4c3f2002-04-13 03:45:44 +00001145 struct vki_timeval zero_timeout;
1146 struct vki_timespec nanosleep_interval;
1147
sewardj5f07b662002-04-23 16:52:51 +00001148 /* gcc's complains about ms_end being used uninitialised -- classic
1149 case it can't understand, where ms_end is both defined and used
1150 only if timeout != NULL. Hence ... */
1151 ms_end = 0;
sewardj08a4c3f2002-04-13 03:45:44 +00001152
1153 /* We assume that the kernel and libc data layouts are identical
1154 for the following types. These asserts provide a crude
1155 check. */
1156 if (sizeof(fd_set) != sizeof(vki_fd_set)
1157 || sizeof(struct timeval) != sizeof(struct vki_timeval))
1158 barf("valgrind's hacky non-blocking select(): data sizes error");
1159
sewardj5f07b662002-04-23 16:52:51 +00001160 /* Detect the current time and simultaneously find out if we are
1161 running on Valgrind. */
1162 VALGRIND_MAGIC_SEQUENCE(ms_now, 0xFFFFFFFF /* default */,
1163 VG_USERREQ__READ_MILLISECOND_TIMER,
1164 0, 0, 0, 0);
1165
1166 /* If a zero timeout specified, this call is harmless. Also go
1167 this route if we're not running on Valgrind, for whatever
1168 reason. */
1169 if ( (timeout && timeout->tv_sec == 0 && timeout->tv_usec == 0)
1170 || (ms_now == 0xFFFFFFFF) ) {
sewardj02535bc2002-04-21 01:08:26 +00001171 res = do_syscall_select( n, (vki_fd_set*)rfds,
sewardj08a4c3f2002-04-13 03:45:44 +00001172 (vki_fd_set*)wfds,
1173 (vki_fd_set*)xfds,
1174 (struct vki_timeval*)timeout);
sewardj02535bc2002-04-21 01:08:26 +00001175 if (is_kerror(res)) {
1176 * (__errno_location()) = -res;
1177 return -1;
1178 } else {
1179 return res;
1180 }
1181 }
sewardj08a4c3f2002-04-13 03:45:44 +00001182
sewardj5f07b662002-04-23 16:52:51 +00001183 /* If a timeout was specified, set ms_end to be the end millisecond
1184 counter [wallclock] time. */
sewardj08a4c3f2002-04-13 03:45:44 +00001185 if (timeout) {
1186 res = my_do_syscall2(__NR_gettimeofday, (int)&t_now, (int)NULL);
1187 assert(res == 0);
sewardj5f07b662002-04-23 16:52:51 +00001188 ms_end = ms_now;
1189 ms_end += (timeout->tv_usec / 1000);
1190 ms_end += (timeout->tv_sec * 1000);
sewardj08a4c3f2002-04-13 03:45:44 +00001191 /* Stay sane ... */
sewardj5f07b662002-04-23 16:52:51 +00001192 assert (ms_end >= ms_now);
sewardj08a4c3f2002-04-13 03:45:44 +00001193 }
1194
1195 /* fprintf(stderr, "MY_SELECT: before loop\n"); */
1196
1197 /* Either timeout == NULL, meaning wait indefinitely, or timeout !=
sewardj5f07b662002-04-23 16:52:51 +00001198 NULL, in which case ms_end holds the end time. */
sewardj08a4c3f2002-04-13 03:45:44 +00001199 while (1) {
1200 if (timeout) {
sewardj5f07b662002-04-23 16:52:51 +00001201 VALGRIND_MAGIC_SEQUENCE(ms_now, 0xFFFFFFFF /* default */,
1202 VG_USERREQ__READ_MILLISECOND_TIMER,
1203 0, 0, 0, 0);
1204 assert(ms_now != 0xFFFFFFFF);
1205 if (ms_now >= ms_end) {
sewardj08a4c3f2002-04-13 03:45:44 +00001206 /* timeout; nothing interesting happened. */
1207 if (rfds) FD_ZERO(rfds);
1208 if (wfds) FD_ZERO(wfds);
1209 if (xfds) FD_ZERO(xfds);
1210 return 0;
1211 }
1212 }
1213
1214 /* These could be trashed each time round the loop, so restore
1215 them each time. */
1216 if (rfds) rfds_copy = *rfds;
1217 if (wfds) wfds_copy = *wfds;
1218 if (xfds) xfds_copy = *xfds;
1219
1220 zero_timeout.tv_sec = zero_timeout.tv_usec = 0;
1221
1222 res = do_syscall_select( n,
1223 rfds ? (vki_fd_set*)(&rfds_copy) : NULL,
1224 wfds ? (vki_fd_set*)(&wfds_copy) : NULL,
1225 xfds ? (vki_fd_set*)(&xfds_copy) : NULL,
1226 & zero_timeout );
sewardj02535bc2002-04-21 01:08:26 +00001227 if (is_kerror(res)) {
1228 /* Some kind of error (including EINTR). Set errno and
sewardj08a4c3f2002-04-13 03:45:44 +00001229 return. The sets are unspecified in this case. */
sewardj02535bc2002-04-21 01:08:26 +00001230 * (__errno_location()) = -res;
1231 return -1;
sewardj08a4c3f2002-04-13 03:45:44 +00001232 }
1233 if (res > 0) {
1234 /* one or more fds is ready. Copy out resulting sets and
1235 return. */
1236 if (rfds) *rfds = rfds_copy;
1237 if (wfds) *wfds = wfds_copy;
1238 if (xfds) *xfds = xfds_copy;
1239 return res;
1240 }
1241 /* fprintf(stderr, "MY_SELECT: nanosleep\n"); */
1242 /* nanosleep and go round again */
sewardj02535bc2002-04-21 01:08:26 +00001243 nanosleep_interval.tv_sec = 0;
sewardj956cc1b2002-04-25 01:33:50 +00001244 nanosleep_interval.tv_nsec = 50 * 1000 * 1000; /* 50 milliseconds */
sewardjf854f472002-04-21 12:19:41 +00001245 /* It's critical here that valgrind's nanosleep implementation
1246 is nonblocking. */
1247 (void)my_do_syscall2(__NR_nanosleep,
1248 (int)(&nanosleep_interval), (int)NULL);
1249 }
1250}
1251
1252
1253
1254
1255#include <sys/poll.h>
1256
sewardj72d58482002-04-24 02:20:20 +00001257#ifdef GLIBC_2_1
1258typedef unsigned long int nfds_t;
1259#endif
1260
sewardj5905fae2002-04-26 13:25:00 +00001261/* __attribute__((weak)) */
sewardjf854f472002-04-21 12:19:41 +00001262int poll (struct pollfd *__fds, nfds_t __nfds, int __timeout)
1263{
sewardj5f07b662002-04-23 16:52:51 +00001264 unsigned int ms_now, ms_end;
sewardjf854f472002-04-21 12:19:41 +00001265 int res, i;
sewardjf854f472002-04-21 12:19:41 +00001266 struct vki_timespec nanosleep_interval;
1267
1268 ensure_valgrind("poll");
1269
sewardj5f07b662002-04-23 16:52:51 +00001270 /* Detect the current time and simultaneously find out if we are
1271 running on Valgrind. */
1272 VALGRIND_MAGIC_SEQUENCE(ms_now, 0xFFFFFFFF /* default */,
1273 VG_USERREQ__READ_MILLISECOND_TIMER,
1274 0, 0, 0, 0);
1275
sewardjf854f472002-04-21 12:19:41 +00001276 if (/* CHECK SIZES FOR struct pollfd */
1277 sizeof(struct timeval) != sizeof(struct vki_timeval))
1278 barf("valgrind's hacky non-blocking poll(): data sizes error");
1279
sewardj5f07b662002-04-23 16:52:51 +00001280 /* dummy initialisation to keep gcc -Wall happy */
1281 ms_end = 0;
1282
1283 /* If a zero timeout specified, this call is harmless. Also do
1284 this if not running on Valgrind. */
1285 if (__timeout == 0 || ms_now == 0xFFFFFFFF) {
sewardjf854f472002-04-21 12:19:41 +00001286 res = my_do_syscall3(__NR_poll, (int)__fds, __nfds, __timeout);
1287 if (is_kerror(res)) {
1288 * (__errno_location()) = -res;
1289 return -1;
1290 } else {
1291 return res;
1292 }
1293 }
1294
sewardj5f07b662002-04-23 16:52:51 +00001295 /* If a timeout was specified, set ms_end to be the end wallclock
1296 time. Easy considering that __timeout is in milliseconds. */
sewardjf854f472002-04-21 12:19:41 +00001297 if (__timeout > 0) {
sewardj650ac002002-04-29 12:20:34 +00001298 ms_end = ms_now + (unsigned int)__timeout;
sewardjf854f472002-04-21 12:19:41 +00001299 }
1300
1301 /* fprintf(stderr, "MY_POLL: before loop\n"); */
1302
1303 /* Either timeout < 0, meaning wait indefinitely, or timeout > 0,
1304 in which case t_end holds the end time. */
sewardj5f07b662002-04-23 16:52:51 +00001305 assert(__timeout != 0);
1306
sewardjf854f472002-04-21 12:19:41 +00001307 while (1) {
sewardjf854f472002-04-21 12:19:41 +00001308 if (__timeout > 0) {
sewardj5f07b662002-04-23 16:52:51 +00001309 VALGRIND_MAGIC_SEQUENCE(ms_now, 0xFFFFFFFF /* default */,
1310 VG_USERREQ__READ_MILLISECOND_TIMER,
1311 0, 0, 0, 0);
1312 assert(ms_now != 0xFFFFFFFF);
1313 if (ms_now >= ms_end) {
sewardjf854f472002-04-21 12:19:41 +00001314 /* timeout; nothing interesting happened. */
1315 for (i = 0; i < __nfds; i++)
1316 __fds[i].revents = 0;
1317 return 0;
1318 }
1319 }
1320
sewardj5f07b662002-04-23 16:52:51 +00001321 /* Do a return-immediately poll. */
sewardjf854f472002-04-21 12:19:41 +00001322 res = my_do_syscall3(__NR_poll, (int)__fds, __nfds, 0 );
1323 if (is_kerror(res)) {
1324 /* Some kind of error. Set errno and return. */
1325 * (__errno_location()) = -res;
1326 return -1;
1327 }
1328 if (res > 0) {
1329 /* One or more fds is ready. Return now. */
1330 return res;
1331 }
1332 /* fprintf(stderr, "MY_POLL: nanosleep\n"); */
1333 /* nanosleep and go round again */
1334 nanosleep_interval.tv_sec = 0;
sewardj956cc1b2002-04-25 01:33:50 +00001335 nanosleep_interval.tv_nsec = 51 * 1000 * 1000; /* 51 milliseconds */
sewardj08a4c3f2002-04-13 03:45:44 +00001336 /* It's critical here that valgrind's nanosleep implementation
1337 is nonblocking. */
1338 (void)my_do_syscall2(__NR_nanosleep,
1339 (int)(&nanosleep_interval), (int)NULL);
1340 }
1341}
sewardj3b13f0e2002-04-25 20:17:29 +00001342
1343
1344/* ---------------------------------------------------------------------
1345 B'stard.
1346 ------------------------------------------------------------------ */
1347
1348# define strong_alias(name, aliasname) \
1349 extern __typeof (name) aliasname __attribute__ ((alias (#name)));
1350
sewardj5905fae2002-04-26 13:25:00 +00001351# define weak_alias(name, aliasname) \
1352 extern __typeof (name) aliasname __attribute__ ((weak, alias (#name)));
sewardj3b13f0e2002-04-25 20:17:29 +00001353
sewardj5905fae2002-04-26 13:25:00 +00001354#if 1
1355strong_alias(__pthread_mutex_lock, pthread_mutex_lock)
1356strong_alias(__pthread_mutex_trylock, pthread_mutex_trylock)
1357strong_alias(__pthread_mutex_unlock, pthread_mutex_unlock)
1358strong_alias(__pthread_mutexattr_init, pthread_mutexattr_init)
1359 weak_alias(__pthread_mutexattr_settype, pthread_mutexattr_settype)
1360strong_alias(__pthread_mutex_init, pthread_mutex_init)
1361strong_alias(__pthread_mutexattr_destroy, pthread_mutexattr_destroy)
1362strong_alias(__pthread_mutex_destroy, pthread_mutex_destroy)
1363strong_alias(__pthread_once, pthread_once)
1364strong_alias(__pthread_atfork, pthread_atfork)
1365strong_alias(__pthread_key_create, pthread_key_create)
1366strong_alias(__pthread_getspecific, pthread_getspecific)
1367strong_alias(__pthread_setspecific, pthread_setspecific)
1368
1369//strong_alias(__sigaction, sigaction)
sewardj3b13f0e2002-04-25 20:17:29 +00001370strong_alias(sigaction, __sigaction)
1371
sewardj5905fae2002-04-26 13:25:00 +00001372strong_alias(close, __close)
sewardj3b13f0e2002-04-25 20:17:29 +00001373strong_alias(fcntl, __fcntl)
sewardj5905fae2002-04-26 13:25:00 +00001374strong_alias(lseek, __lseek)
1375strong_alias(open, __open)
1376strong_alias(open64, __open64)
1377//strong_alias(pread64, __pread64)
1378//strong_alias(pwrite64, __pwrite64)
1379strong_alias(read, __read)
1380strong_alias(wait, __wait)
1381strong_alias(write, __write)
sewardj3b13f0e2002-04-25 20:17:29 +00001382strong_alias(connect, __connect)
sewardj5905fae2002-04-26 13:25:00 +00001383strong_alias(send, __send)
1384
1385weak_alias(__fork, fork)
1386//weak_alias(__vfork, vfork)
1387
1388#endif
sewardj3b13f0e2002-04-25 20:17:29 +00001389
1390/*--------------------------------------------------*/
1391
sewardj5716dbb2002-04-26 03:28:18 +00001392int
1393pthread_rwlock_rdlock (void* /* pthread_rwlock_t* */ rwlock)
1394{
sewardj436e0582002-04-26 14:31:40 +00001395 static int moans = N_MOANS;
1396 if (moans-- > 0)
1397 kludged("pthread_rwlock_rdlock");
sewardj5716dbb2002-04-26 03:28:18 +00001398 return 0;
1399}
1400
sewardj5905fae2002-04-26 13:25:00 +00001401weak_alias(pthread_rwlock_rdlock, __pthread_rwlock_rdlock)
sewardj5716dbb2002-04-26 03:28:18 +00001402
1403
1404int
1405pthread_rwlock_unlock (void* /* pthread_rwlock_t* */ rwlock)
1406{
sewardj436e0582002-04-26 14:31:40 +00001407 static int moans = N_MOANS;
1408 if (moans-- > 0)
1409 kludged("pthread_rwlock_unlock");
sewardj5716dbb2002-04-26 03:28:18 +00001410 return 0;
1411}
1412
sewardj5905fae2002-04-26 13:25:00 +00001413weak_alias(pthread_rwlock_unlock, __pthread_rwlock_unlock)
sewardj5716dbb2002-04-26 03:28:18 +00001414
1415
sewardj060b04f2002-04-26 21:01:13 +00001416int
1417pthread_rwlock_wrlock (void* /* pthread_rwlock_t* */ rwlock)
1418{
1419 static int moans = N_MOANS;
1420 if (moans-- > 0)
1421 kludged("pthread_rwlock_wrlock");
1422 return 0;
1423}
1424
sewardj262b0292002-05-01 00:03:16 +00001425weak_alias(pthread_rwlock_wrlock, __pthread_rwlock_wrlock)
sewardj060b04f2002-04-26 21:01:13 +00001426
1427
sewardj3b13f0e2002-04-25 20:17:29 +00001428/* I've no idea what these are, but they get called quite a lot.
1429 Anybody know? */
1430
1431#undef _IO_flockfile
1432void _IO_flockfile ( _IO_FILE * file )
1433{
sewardj853f55d2002-04-26 00:27:53 +00001434 //char* str = "_IO_flockfile\n";
1435 //write(2, str, strlen(str));
1436 pthread_mutex_lock(file->_lock);
sewardj3b13f0e2002-04-25 20:17:29 +00001437 // barf("_IO_flockfile");
1438}
sewardj5905fae2002-04-26 13:25:00 +00001439weak_alias(_IO_flockfile, flockfile);
1440
sewardj3b13f0e2002-04-25 20:17:29 +00001441
1442#undef _IO_funlockfile
1443void _IO_funlockfile ( _IO_FILE * file )
1444{
sewardj853f55d2002-04-26 00:27:53 +00001445 //char* str = "_IO_funlockfile\n";
1446 //write(2, str, strlen(str));
1447 pthread_mutex_unlock(file->_lock);
sewardj3b13f0e2002-04-25 20:17:29 +00001448 // barf("_IO_funlockfile");
1449}
sewardj5905fae2002-04-26 13:25:00 +00001450weak_alias(_IO_funlockfile, funlockfile);
1451
sewardj3b13f0e2002-04-25 20:17:29 +00001452
1453void _pthread_cleanup_push_defer ( void )
1454{
1455 // char* str = "_pthread_cleanup_push_defer\n";
1456 // write(2, str, strlen(str));
1457}
1458
1459void _pthread_cleanup_pop_restore ( void )
1460{
1461 // char* str = "_pthread_cleanup_pop_restore\n";
1462 // write(2, str, strlen(str));
1463}
sewardjd4f2c712002-04-30 10:20:10 +00001464
1465
1466/* This doesn't seem to be needed to simulate libpthread.so's external
1467 interface, but many people complain about its absence. */
1468
1469strong_alias(__pthread_mutexattr_settype, __pthread_mutexattr_setkind_np)
1470weak_alias(__pthread_mutexattr_setkind_np, pthread_mutexattr_setkind_np)