blob: 015b9f73b3c420ecb7303fbe60395e0e3fdd29ed [file] [log] [blame]
sewardje663cb92002-04-12 10:26:32 +00001
sewardj439d45e2002-05-03 20:43:10 +00002/*--------------------------------------------------------------------*/
3/*--- A replacement for the standard libpthread.so. ---*/
4/*--- vg_libpthread.c ---*/
5/*--------------------------------------------------------------------*/
6
7/*
8 This file is part of Valgrind, an x86 protected-mode emulator
9 designed for debugging and profiling binaries on x86-Unixes.
10
11 Copyright (C) 2000-2002 Julian Seward
12 jseward@acm.org
13
14 This program is free software; you can redistribute it and/or
15 modify it under the terms of the GNU General Public License as
16 published by the Free Software Foundation; either version 2 of the
17 License, or (at your option) any later version.
18
19 This program is distributed in the hope that it will be useful, but
20 WITHOUT ANY WARRANTY; without even the implied warranty of
21 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
22 General Public License for more details.
23
24 You should have received a copy of the GNU General Public License
25 along with this program; if not, write to the Free Software
26 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
27 02111-1307, USA.
28
29 The GNU General Public License is contained in the file LICENSE.
30*/
31
32/* ALL THIS CODE RUNS ON THE SIMULATED CPU.
33
34 This is a replacement for the standard libpthread.so. It is loaded
sewardje663cb92002-04-12 10:26:32 +000035 as part of the client's image (if required) and directs pthread
36 calls through to Valgrind's request mechanism.
37
38 A couple of caveats.
39
40 1. Since it's a binary-compatible replacement for an existing library,
41 we must take care to used exactly the same data layouts, etc, as
42 the standard pthread.so does.
43
44 2. Since this runs as part of the client, there are no specific
45 restrictions on what headers etc we can include, so long as
46 this libpthread.so does not end up having dependencies on .so's
47 which the real one doesn't.
48
49 Later ... it appears we cannot call file-related stuff in libc here,
50 perhaps fair enough. Be careful what you call from here. Even exit()
51 doesn't work (gives infinite recursion and then stack overflow); hence
52 myexit(). Also fprintf doesn't seem safe.
53*/
54
55#include "valgrind.h" /* For the request-passing mechanism */
56#include "vg_include.h" /* For the VG_USERREQ__* constants */
57
sewardje663cb92002-04-12 10:26:32 +000058#include <unistd.h>
59#include <string.h>
sewardj2a1dcce2002-04-22 12:45:25 +000060#ifdef GLIBC_2_1
61#include <sys/time.h>
62#endif
sewardje663cb92002-04-12 10:26:32 +000063
64/* ---------------------------------------------------------------------
65 Helpers. We have to be pretty self-sufficient.
66 ------------------------------------------------------------------ */
67
sewardj436e0582002-04-26 14:31:40 +000068/* Number of times any given error message is printed. */
69#define N_MOANS 3
70
sewardj45b4b372002-04-16 22:50:32 +000071/* Extract from Valgrind the value of VG_(clo_trace_pthread_level).
72 Returns 0 (none) if not running on Valgrind. */
73static
74int get_pt_trace_level ( void )
75{
76 int res;
77 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
78 VG_USERREQ__GET_PTHREAD_TRACE_LEVEL,
79 0, 0, 0, 0);
80 return res;
81}
82
83
sewardje663cb92002-04-12 10:26:32 +000084static
85void myexit ( int arg )
86{
sewardj45b4b372002-04-16 22:50:32 +000087 int __res;
sewardje663cb92002-04-12 10:26:32 +000088 __asm__ volatile ("movl %%ecx, %%ebx ; int $0x80"
89 : "=a" (__res)
90 : "0" (__NR_exit),
91 "c" (arg) );
sewardj45b4b372002-04-16 22:50:32 +000092 /* We don't bother to mention the fact that this asm trashes %ebx,
93 since it won't return. If you ever do let it return ... fix
94 this! */
sewardje663cb92002-04-12 10:26:32 +000095}
96
97
sewardj68b2dd92002-05-10 21:03:56 +000098/* We need this guy -- it's in valgrind.so. */
99extern void VG_(startup) ( void );
100
101
102/* Just start up Valgrind if it's not already going. VG_(startup)()
103 detects and ignores second and subsequent calls. */
sewardj604ec3c2002-04-18 22:38:41 +0000104static __inline__
sewardje663cb92002-04-12 10:26:32 +0000105void ensure_valgrind ( char* caller )
106{
107 char* str;
sewardj68b2dd92002-05-10 21:03:56 +0000108 int is_valgrind;
109 VG_(startup)();
sewardje663cb92002-04-12 10:26:32 +0000110}
111
112
113static
sewardj3b5d8862002-04-20 13:53:23 +0000114__attribute__((noreturn))
sewardje663cb92002-04-12 10:26:32 +0000115void barf ( char* str )
116{
117 char buf[100];
118 buf[0] = 0;
sewardj439d45e2002-05-03 20:43:10 +0000119 strcat(buf, "\nvalgrind's libpthread.so: ");
sewardje663cb92002-04-12 10:26:32 +0000120 strcat(buf, str);
121 strcat(buf, "\n\n");
122 write(2, buf, strlen(buf));
123 myexit(1);
sewardj3b5d8862002-04-20 13:53:23 +0000124 /* We have to persuade gcc into believing this doesn't return. */
125 while (1) { };
sewardje663cb92002-04-12 10:26:32 +0000126}
127
128
sewardj2a3d28c2002-04-14 13:27:00 +0000129static void ignored ( char* msg )
130{
sewardj436e0582002-04-26 14:31:40 +0000131 if (get_pt_trace_level() >= 0) {
sewardj439d45e2002-05-03 20:43:10 +0000132 char* ig = "valgrind's libpthread.so: IGNORED call to: ";
sewardj45b4b372002-04-16 22:50:32 +0000133 write(2, ig, strlen(ig));
134 write(2, msg, strlen(msg));
135 ig = "\n";
136 write(2, ig, strlen(ig));
137 }
sewardj2a3d28c2002-04-14 13:27:00 +0000138}
139
sewardj30671ff2002-04-21 00:13:57 +0000140static void kludged ( char* msg )
141{
sewardj436e0582002-04-26 14:31:40 +0000142 if (get_pt_trace_level() >= 0) {
sewardj439d45e2002-05-03 20:43:10 +0000143 char* ig = "valgrind's libpthread.so: KLUDGED call to: ";
144 write(2, ig, strlen(ig));
145 write(2, msg, strlen(msg));
146 ig = "\n";
147 write(2, ig, strlen(ig));
148 }
149}
150
151static void not_inside ( char* msg )
152{
sewardj68b2dd92002-05-10 21:03:56 +0000153 VG_(startup)();
154 return;
sewardj439d45e2002-05-03 20:43:10 +0000155 if (get_pt_trace_level() >= 0) {
156 char* ig = "valgrind's libpthread.so: NOT INSIDE VALGRIND "
157 "during call to: ";
sewardj30671ff2002-04-21 00:13:57 +0000158 write(2, ig, strlen(ig));
159 write(2, msg, strlen(msg));
160 ig = "\n";
161 write(2, ig, strlen(ig));
162 }
163}
164
sewardj3b13f0e2002-04-25 20:17:29 +0000165void vgPlain_unimp ( char* what )
166{
sewardj439d45e2002-05-03 20:43:10 +0000167 char* ig = "valgrind's libpthread.so: UNIMPLEMENTED FUNCTION: ";
sewardj3b13f0e2002-04-25 20:17:29 +0000168 write(2, ig, strlen(ig));
169 write(2, what, strlen(what));
170 ig = "\n";
171 write(2, ig, strlen(ig));
172 barf("Please report this bug to me at: jseward@acm.org");
173}
174
sewardje663cb92002-04-12 10:26:32 +0000175
176/* ---------------------------------------------------------------------
177 Pass pthread_ calls to Valgrind's request mechanism.
178 ------------------------------------------------------------------ */
179
sewardjf8f819e2002-04-17 23:21:37 +0000180#include <pthread.h>
181#include <stdio.h>
182#include <errno.h>
sewardj5f07b662002-04-23 16:52:51 +0000183#include <assert.h>
184#include <sys/time.h> /* gettimeofday */
sewardjf8f819e2002-04-17 23:21:37 +0000185
186/* ---------------------------------------------------
187 THREAD ATTRIBUTES
188 ------------------------------------------------ */
189
sewardj6af4b5d2002-04-16 04:40:49 +0000190int pthread_attr_init(pthread_attr_t *attr)
191{
sewardj436e0582002-04-26 14:31:40 +0000192 static int moans = N_MOANS;
193 if (moans-- > 0)
194 ignored("pthread_attr_init");
sewardj6af4b5d2002-04-16 04:40:49 +0000195 return 0;
196}
197
198int pthread_attr_setdetachstate(pthread_attr_t *attr, int detachstate)
199{
sewardj436e0582002-04-26 14:31:40 +0000200 static int moans = N_MOANS;
201 if (moans-- > 0)
202 ignored("pthread_attr_setdetachstate");
sewardj6af4b5d2002-04-16 04:40:49 +0000203 return 0;
204}
205
sewardj30671ff2002-04-21 00:13:57 +0000206int pthread_attr_setinheritsched(pthread_attr_t *attr, int inherit)
207{
sewardj436e0582002-04-26 14:31:40 +0000208 static int moans = N_MOANS;
209 if (moans-- > 0)
210 ignored("pthread_attr_setinheritsched");
sewardj30671ff2002-04-21 00:13:57 +0000211 return 0;
212}
sewardj6af4b5d2002-04-16 04:40:49 +0000213
sewardj30671ff2002-04-21 00:13:57 +0000214/* This is completely bogus. */
215int pthread_attr_getschedparam(const pthread_attr_t *attr,
216 struct sched_param *param)
217{
sewardj436e0582002-04-26 14:31:40 +0000218 static int moans = N_MOANS;
219 if (moans-- > 0)
220 kludged("pthread_attr_getschedparam");
sewardj72d58482002-04-24 02:20:20 +0000221# ifdef GLIBC_2_1
222 if (param) param->sched_priority = 0; /* who knows */
223# else
sewardj30671ff2002-04-21 00:13:57 +0000224 if (param) param->__sched_priority = 0; /* who knows */
sewardj72d58482002-04-24 02:20:20 +0000225# endif
sewardj30671ff2002-04-21 00:13:57 +0000226 return 0;
227}
228
229int pthread_attr_setschedparam(pthread_attr_t *attr,
230 const struct sched_param *param)
231{
sewardj436e0582002-04-26 14:31:40 +0000232 static int moans = N_MOANS;
233 if (moans-- > 0)
234 ignored("pthread_attr_setschedparam");
sewardj30671ff2002-04-21 00:13:57 +0000235 return 0;
236}
237
238int pthread_attr_destroy(pthread_attr_t *attr)
239{
sewardj436e0582002-04-26 14:31:40 +0000240 static int moans = N_MOANS;
241 if (moans-- > 0)
242 ignored("pthread_attr_destroy");
sewardj30671ff2002-04-21 00:13:57 +0000243 return 0;
244}
sewardjf8f819e2002-04-17 23:21:37 +0000245
246/* ---------------------------------------------------
247 THREADs
248 ------------------------------------------------ */
249
sewardj6072c362002-04-19 14:40:57 +0000250int pthread_equal(pthread_t thread1, pthread_t thread2)
251{
252 return thread1 == thread2 ? 1 : 0;
253}
254
255
sewardje663cb92002-04-12 10:26:32 +0000256int
257pthread_create (pthread_t *__restrict __thread,
258 __const pthread_attr_t *__restrict __attr,
259 void *(*__start_routine) (void *),
260 void *__restrict __arg)
261{
262 int res;
263 ensure_valgrind("pthread_create");
264 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
265 VG_USERREQ__PTHREAD_CREATE,
266 __thread, __attr, __start_routine, __arg);
267 return res;
268}
269
270
271
272int
273pthread_join (pthread_t __th, void **__thread_return)
274{
275 int res;
276 ensure_valgrind("pthread_join");
277 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
278 VG_USERREQ__PTHREAD_JOIN,
279 __th, __thread_return, 0, 0);
280 return res;
281}
282
283
sewardj3b5d8862002-04-20 13:53:23 +0000284void pthread_exit(void *retval)
285{
286 int res;
287 ensure_valgrind("pthread_exit");
288 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
289 VG_USERREQ__PTHREAD_EXIT,
290 retval, 0, 0, 0);
291 /* Doesn't return! */
292 /* However, we have to fool gcc into knowing that. */
293 barf("pthread_exit: still alive after request?!");
294}
295
sewardje663cb92002-04-12 10:26:32 +0000296
sewardj3b13f0e2002-04-25 20:17:29 +0000297pthread_t pthread_self(void)
sewardje663cb92002-04-12 10:26:32 +0000298{
299 int tid;
sewardj3b13f0e2002-04-25 20:17:29 +0000300 ensure_valgrind("pthread_self");
sewardj439d45e2002-05-03 20:43:10 +0000301 VALGRIND_MAGIC_SEQUENCE(tid, 1 /* default */,
sewardje663cb92002-04-12 10:26:32 +0000302 VG_USERREQ__PTHREAD_GET_THREADID,
303 0, 0, 0, 0);
sewardj439d45e2002-05-03 20:43:10 +0000304 if (tid < 1 || tid >= VG_N_THREADS)
sewardj3b13f0e2002-04-25 20:17:29 +0000305 barf("pthread_self: invalid ThreadId");
306 return tid;
sewardje663cb92002-04-12 10:26:32 +0000307}
308
309
sewardj853f55d2002-04-26 00:27:53 +0000310int pthread_detach(pthread_t th)
311{
sewardj436e0582002-04-26 14:31:40 +0000312 static int moans = N_MOANS;
313 if (moans-- > 0)
314 ignored("pthread_detach");
sewardj853f55d2002-04-26 00:27:53 +0000315 return 0;
316}
317
318
sewardjf8f819e2002-04-17 23:21:37 +0000319/* ---------------------------------------------------
320 MUTEX ATTRIBUTES
321 ------------------------------------------------ */
322
sewardj5905fae2002-04-26 13:25:00 +0000323int __pthread_mutexattr_init(pthread_mutexattr_t *attr)
sewardje663cb92002-04-12 10:26:32 +0000324{
sewardjf8f819e2002-04-17 23:21:37 +0000325 attr->__mutexkind = PTHREAD_MUTEX_ERRORCHECK_NP;
sewardj8937c812002-04-12 20:12:20 +0000326 return 0;
sewardje663cb92002-04-12 10:26:32 +0000327}
328
sewardj5905fae2002-04-26 13:25:00 +0000329int __pthread_mutexattr_settype(pthread_mutexattr_t *attr, int type)
sewardjf8f819e2002-04-17 23:21:37 +0000330{
331 switch (type) {
sewardj3b13f0e2002-04-25 20:17:29 +0000332# ifndef GLIBC_2_1
sewardjf8f819e2002-04-17 23:21:37 +0000333 case PTHREAD_MUTEX_TIMED_NP:
sewardj2a1dcce2002-04-22 12:45:25 +0000334 case PTHREAD_MUTEX_ADAPTIVE_NP:
sewardj3b13f0e2002-04-25 20:17:29 +0000335# endif
sewardj68b2dd92002-05-10 21:03:56 +0000336 case PTHREAD_MUTEX_FAST_NP:
sewardjf8f819e2002-04-17 23:21:37 +0000337 case PTHREAD_MUTEX_RECURSIVE_NP:
338 case PTHREAD_MUTEX_ERRORCHECK_NP:
sewardjf8f819e2002-04-17 23:21:37 +0000339 attr->__mutexkind = type;
340 return 0;
341 default:
342 return EINVAL;
343 }
344}
345
sewardj5905fae2002-04-26 13:25:00 +0000346int __pthread_mutexattr_destroy(pthread_mutexattr_t *attr)
sewardjf8f819e2002-04-17 23:21:37 +0000347{
348 return 0;
349}
350
351
352/* ---------------------------------------------------
353 MUTEXes
354 ------------------------------------------------ */
355
sewardj5905fae2002-04-26 13:25:00 +0000356int __pthread_mutex_init(pthread_mutex_t *mutex,
357 const pthread_mutexattr_t *mutexattr)
sewardje663cb92002-04-12 10:26:32 +0000358{
sewardj604ec3c2002-04-18 22:38:41 +0000359 mutex->__m_count = 0;
360 mutex->__m_owner = (_pthread_descr)VG_INVALID_THREADID;
361 mutex->__m_kind = PTHREAD_MUTEX_ERRORCHECK_NP;
362 if (mutexattr)
363 mutex->__m_kind = mutexattr->__mutexkind;
364 return 0;
sewardje663cb92002-04-12 10:26:32 +0000365}
366
sewardj439d45e2002-05-03 20:43:10 +0000367
sewardj5905fae2002-04-26 13:25:00 +0000368int __pthread_mutex_lock(pthread_mutex_t *mutex)
sewardje663cb92002-04-12 10:26:32 +0000369{
370 int res;
sewardj436e0582002-04-26 14:31:40 +0000371 static int moans = N_MOANS;
sewardj439d45e2002-05-03 20:43:10 +0000372 if (RUNNING_ON_VALGRIND) {
sewardje663cb92002-04-12 10:26:32 +0000373 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
374 VG_USERREQ__PTHREAD_MUTEX_LOCK,
375 mutex, 0, 0, 0);
376 return res;
sewardj439d45e2002-05-03 20:43:10 +0000377 } else {
378 if (moans-- > 0)
379 not_inside("pthread_mutex_lock");
380 return 0; /* success */
sewardje663cb92002-04-12 10:26:32 +0000381 }
382}
383
sewardj439d45e2002-05-03 20:43:10 +0000384
sewardj5905fae2002-04-26 13:25:00 +0000385int __pthread_mutex_trylock(pthread_mutex_t *mutex)
sewardj30671ff2002-04-21 00:13:57 +0000386{
387 int res;
sewardj436e0582002-04-26 14:31:40 +0000388 static int moans = N_MOANS;
sewardj439d45e2002-05-03 20:43:10 +0000389 if (RUNNING_ON_VALGRIND) {
sewardj30671ff2002-04-21 00:13:57 +0000390 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
391 VG_USERREQ__PTHREAD_MUTEX_TRYLOCK,
392 mutex, 0, 0, 0);
393 return res;
sewardj439d45e2002-05-03 20:43:10 +0000394 } else {
395 if (moans-- > 0)
396 not_inside("pthread_mutex_trylock");
397 return 0;
sewardj30671ff2002-04-21 00:13:57 +0000398 }
399}
400
sewardj439d45e2002-05-03 20:43:10 +0000401
sewardj5905fae2002-04-26 13:25:00 +0000402int __pthread_mutex_unlock(pthread_mutex_t *mutex)
sewardje663cb92002-04-12 10:26:32 +0000403{
404 int res;
sewardj436e0582002-04-26 14:31:40 +0000405 static int moans = N_MOANS;
sewardj439d45e2002-05-03 20:43:10 +0000406 if (RUNNING_ON_VALGRIND) {
sewardje663cb92002-04-12 10:26:32 +0000407 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
408 VG_USERREQ__PTHREAD_MUTEX_UNLOCK,
409 mutex, 0, 0, 0);
410 return res;
sewardj439d45e2002-05-03 20:43:10 +0000411 } else {
412 if (moans-- > 0)
413 not_inside("pthread_mutex_unlock");
414 return 0;
sewardje663cb92002-04-12 10:26:32 +0000415 }
416}
417
sewardj439d45e2002-05-03 20:43:10 +0000418
sewardj5905fae2002-04-26 13:25:00 +0000419int __pthread_mutex_destroy(pthread_mutex_t *mutex)
sewardje663cb92002-04-12 10:26:32 +0000420{
sewardj604ec3c2002-04-18 22:38:41 +0000421 /* Valgrind doesn't hold any resources on behalf of the mutex, so no
422 need to involve it. */
423 if (mutex->__m_count > 0)
424 return EBUSY;
sewardj6072c362002-04-19 14:40:57 +0000425 mutex->__m_count = 0;
426 mutex->__m_owner = (_pthread_descr)VG_INVALID_THREADID;
427 mutex->__m_kind = PTHREAD_MUTEX_ERRORCHECK_NP;
sewardj604ec3c2002-04-18 22:38:41 +0000428 return 0;
sewardje663cb92002-04-12 10:26:32 +0000429}
430
431
sewardjf8f819e2002-04-17 23:21:37 +0000432/* ---------------------------------------------------
sewardj6072c362002-04-19 14:40:57 +0000433 CONDITION VARIABLES
434 ------------------------------------------------ */
435
436/* LinuxThreads supports no attributes for conditions. Hence ... */
437
438int pthread_condattr_init(pthread_condattr_t *attr)
439{
440 return 0;
441}
442
sewardj0738a592002-04-20 13:59:33 +0000443int pthread_condattr_destroy(pthread_condattr_t *attr)
444{
445 return 0;
446}
sewardj6072c362002-04-19 14:40:57 +0000447
448int pthread_cond_init( pthread_cond_t *cond,
449 const pthread_condattr_t *cond_attr)
450{
451 cond->__c_waiting = (_pthread_descr)VG_INVALID_THREADID;
452 return 0;
453}
454
sewardjf854f472002-04-21 12:19:41 +0000455int pthread_cond_destroy(pthread_cond_t *cond)
456{
457 /* should check that no threads are waiting on this CV */
sewardj436e0582002-04-26 14:31:40 +0000458 static int moans = N_MOANS;
459 if (moans-- > 0)
460 kludged("pthread_cond_destroy");
sewardjf854f472002-04-21 12:19:41 +0000461 return 0;
462}
sewardj6072c362002-04-19 14:40:57 +0000463
464/* ---------------------------------------------------
465 SCHEDULING
466 ------------------------------------------------ */
467
468/* This is completely bogus. */
469int pthread_getschedparam(pthread_t target_thread,
470 int *policy,
471 struct sched_param *param)
472{
sewardj436e0582002-04-26 14:31:40 +0000473 static int moans = N_MOANS;
474 if (moans-- > 0)
475 kludged("pthread_getschedparam");
sewardj6072c362002-04-19 14:40:57 +0000476 if (policy) *policy = SCHED_OTHER;
sewardj2a1dcce2002-04-22 12:45:25 +0000477# ifdef GLIBC_2_1
478 if (param) param->sched_priority = 0; /* who knows */
479# else
sewardj6072c362002-04-19 14:40:57 +0000480 if (param) param->__sched_priority = 0; /* who knows */
sewardj2a1dcce2002-04-22 12:45:25 +0000481# endif
sewardj6072c362002-04-19 14:40:57 +0000482 return 0;
483}
484
485int pthread_setschedparam(pthread_t target_thread,
486 int policy,
487 const struct sched_param *param)
488{
sewardj436e0582002-04-26 14:31:40 +0000489 static int moans = N_MOANS;
490 if (moans-- > 0)
491 ignored("pthread_setschedparam");
sewardj6072c362002-04-19 14:40:57 +0000492 return 0;
493}
494
sewardj3b5d8862002-04-20 13:53:23 +0000495int pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex)
496{
497 int res;
498 ensure_valgrind("pthread_cond_wait");
499 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
500 VG_USERREQ__PTHREAD_COND_WAIT,
501 cond, mutex, 0, 0);
502 return res;
503}
504
sewardj5f07b662002-04-23 16:52:51 +0000505int pthread_cond_timedwait ( pthread_cond_t *cond,
506 pthread_mutex_t *mutex,
507 const struct timespec *abstime )
508{
509 int res;
510 unsigned int ms_now, ms_end;
511 struct timeval timeval_now;
512 unsigned long long int ull_ms_now_after_1970;
513 unsigned long long int ull_ms_end_after_1970;
514
515 ensure_valgrind("pthread_cond_timedwait");
516 VALGRIND_MAGIC_SEQUENCE(ms_now, 0xFFFFFFFF /* default */,
517 VG_USERREQ__READ_MILLISECOND_TIMER,
518 0, 0, 0, 0);
519 assert(ms_now != 0xFFFFFFFF);
520 res = gettimeofday(&timeval_now, NULL);
521 assert(res == 0);
522
523 ull_ms_now_after_1970
524 = 1000ULL * ((unsigned long long int)(timeval_now.tv_sec))
525 + ((unsigned long long int)(timeval_now.tv_usec / 1000000));
526 ull_ms_end_after_1970
527 = 1000ULL * ((unsigned long long int)(abstime->tv_sec))
528 + ((unsigned long long int)(abstime->tv_nsec / 1000000));
529 assert(ull_ms_end_after_1970 >= ull_ms_now_after_1970);
530 ms_end
531 = ms_now + (unsigned int)(ull_ms_end_after_1970 - ull_ms_now_after_1970);
532 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
533 VG_USERREQ__PTHREAD_COND_TIMEDWAIT,
534 cond, mutex, ms_end, 0);
535 return res;
536}
537
538
sewardj3b5d8862002-04-20 13:53:23 +0000539int pthread_cond_signal(pthread_cond_t *cond)
540{
541 int res;
542 ensure_valgrind("pthread_cond_signal");
543 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
544 VG_USERREQ__PTHREAD_COND_SIGNAL,
545 cond, 0, 0, 0);
546 return res;
547}
548
549int pthread_cond_broadcast(pthread_cond_t *cond)
550{
551 int res;
552 ensure_valgrind("pthread_cond_broadcast");
553 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
554 VG_USERREQ__PTHREAD_COND_BROADCAST,
555 cond, 0, 0, 0);
556 return res;
557}
558
sewardj6072c362002-04-19 14:40:57 +0000559
560/* ---------------------------------------------------
sewardjf8f819e2002-04-17 23:21:37 +0000561 CANCELLATION
562 ------------------------------------------------ */
563
sewardj853f55d2002-04-26 00:27:53 +0000564int pthread_setcancelstate(int state, int *oldstate)
565{
sewardj436e0582002-04-26 14:31:40 +0000566 static int moans = N_MOANS;
567 if (moans-- > 0)
568 ignored("pthread_setcancelstate");
sewardj853f55d2002-04-26 00:27:53 +0000569 return 0;
570}
571
sewardje663cb92002-04-12 10:26:32 +0000572int pthread_setcanceltype(int type, int *oldtype)
573{
sewardj436e0582002-04-26 14:31:40 +0000574 static int moans = N_MOANS;
575 if (moans-- > 0)
576 ignored("pthread_setcanceltype");
sewardje663cb92002-04-12 10:26:32 +0000577 return 0;
578}
579
sewardje663cb92002-04-12 10:26:32 +0000580int pthread_cancel(pthread_t thread)
581{
582 int res;
583 ensure_valgrind("pthread_cancel");
584 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
585 VG_USERREQ__PTHREAD_CANCEL,
586 thread, 0, 0, 0);
587 return res;
588}
589
sewardj853f55d2002-04-26 00:27:53 +0000590void pthread_testcancel(void)
591{
592}
593
594/*-------------------*/
595static pthread_mutex_t massacre_mx = PTHREAD_MUTEX_INITIALIZER;
596
597void __pthread_kill_other_threads_np ( void )
598{
599 int i, res, me;
sewardj68b2dd92002-05-10 21:03:56 +0000600 __pthread_mutex_lock(&massacre_mx);
sewardj853f55d2002-04-26 00:27:53 +0000601 me = pthread_self();
602 for (i = 1; i < VG_N_THREADS; i++) {
603 if (i == me) continue;
604 res = pthread_cancel(i);
sewardj436e0582002-04-26 14:31:40 +0000605 if (0 && res == 0)
sewardj853f55d2002-04-26 00:27:53 +0000606 printf("----------- NUKED %d\n", i);
607 }
sewardj68b2dd92002-05-10 21:03:56 +0000608 __pthread_mutex_unlock(&massacre_mx);
sewardj853f55d2002-04-26 00:27:53 +0000609}
610
sewardje663cb92002-04-12 10:26:32 +0000611
sewardjf8f819e2002-04-17 23:21:37 +0000612/* ---------------------------------------------------
613 THREAD-SPECIFICs
614 ------------------------------------------------ */
sewardj5e5fa512002-04-14 13:13:05 +0000615
sewardj5905fae2002-04-26 13:25:00 +0000616int __pthread_key_create(pthread_key_t *key,
617 void (*destr_function) (void *))
sewardj5e5fa512002-04-14 13:13:05 +0000618{
sewardj5f07b662002-04-23 16:52:51 +0000619 int res;
620 ensure_valgrind("pthread_key_create");
621 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
622 VG_USERREQ__PTHREAD_KEY_CREATE,
623 key, destr_function, 0, 0);
624 return res;
sewardj5e5fa512002-04-14 13:13:05 +0000625}
626
627int pthread_key_delete(pthread_key_t key)
628{
sewardj436e0582002-04-26 14:31:40 +0000629 static int moans = N_MOANS;
630 if (moans-- > 0)
631 ignored("pthread_key_delete");
sewardj5e5fa512002-04-14 13:13:05 +0000632 return 0;
633}
634
sewardj5905fae2002-04-26 13:25:00 +0000635int __pthread_setspecific(pthread_key_t key, const void *pointer)
sewardj5e5fa512002-04-14 13:13:05 +0000636{
sewardj5f07b662002-04-23 16:52:51 +0000637 int res;
638 ensure_valgrind("pthread_setspecific");
639 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
640 VG_USERREQ__PTHREAD_SETSPECIFIC,
641 key, pointer, 0, 0);
642 return res;
sewardj5e5fa512002-04-14 13:13:05 +0000643}
644
sewardj5905fae2002-04-26 13:25:00 +0000645void * __pthread_getspecific(pthread_key_t key)
sewardj5e5fa512002-04-14 13:13:05 +0000646{
sewardj5f07b662002-04-23 16:52:51 +0000647 int res;
648 ensure_valgrind("pthread_getspecific");
649 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
650 VG_USERREQ__PTHREAD_GETSPECIFIC,
651 key, 0 , 0, 0);
652 return (void*)res;
sewardj5e5fa512002-04-14 13:13:05 +0000653}
654
sewardjf8f819e2002-04-17 23:21:37 +0000655
656/* ---------------------------------------------------
sewardj89d3d852002-04-24 19:21:39 +0000657 ONCEry
658 ------------------------------------------------ */
659
660static pthread_mutex_t once_masterlock = PTHREAD_MUTEX_INITIALIZER;
661
662
sewardj5905fae2002-04-26 13:25:00 +0000663int __pthread_once ( pthread_once_t *once_control,
664 void (*init_routine) (void) )
sewardj89d3d852002-04-24 19:21:39 +0000665{
666 int res;
667 ensure_valgrind("pthread_once");
668
sewardj68b2dd92002-05-10 21:03:56 +0000669 res = __pthread_mutex_lock(&once_masterlock);
sewardj89d3d852002-04-24 19:21:39 +0000670
sewardj68b2dd92002-05-10 21:03:56 +0000671 if (res != 0) {
672 printf("res = %d\n",res);
sewardj89d3d852002-04-24 19:21:39 +0000673 barf("pthread_once: Looks like your program's "
674 "init routine calls back to pthread_once() ?!");
sewardj68b2dd92002-05-10 21:03:56 +0000675 }
sewardj89d3d852002-04-24 19:21:39 +0000676
677 if (*once_control == 0) {
678 *once_control = 1;
679 init_routine();
680 }
681
sewardj68b2dd92002-05-10 21:03:56 +0000682 __pthread_mutex_unlock(&once_masterlock);
sewardj89d3d852002-04-24 19:21:39 +0000683
684 return 0;
685}
686
687
688/* ---------------------------------------------------
sewardj853f55d2002-04-26 00:27:53 +0000689 MISC
690 ------------------------------------------------ */
691
sewardj5905fae2002-04-26 13:25:00 +0000692int __pthread_atfork ( void (*prepare)(void),
693 void (*parent)(void),
694 void (*child)(void) )
sewardj853f55d2002-04-26 00:27:53 +0000695{
sewardj436e0582002-04-26 14:31:40 +0000696 static int moans = N_MOANS;
697 if (moans-- > 0)
698 ignored("pthread_atfork");
sewardj853f55d2002-04-26 00:27:53 +0000699 return 0;
700}
701
702
sewardjbb990782002-05-08 02:01:14 +0000703__attribute__((weak))
704void __pthread_initialize ( void )
705{
706 static int moans = N_MOANS;
707 if (moans-- > 0)
708 ignored("__pthread_initialize");
709}
710
711
sewardj853f55d2002-04-26 00:27:53 +0000712/* ---------------------------------------------------
sewardj3b13f0e2002-04-25 20:17:29 +0000713 LIBRARY-PRIVATE THREAD SPECIFIC STATE
sewardjf8f819e2002-04-17 23:21:37 +0000714 ------------------------------------------------ */
715
sewardj3b13f0e2002-04-25 20:17:29 +0000716#include <resolv.h>
717static int thread_specific_errno[VG_N_THREADS];
718static int thread_specific_h_errno[VG_N_THREADS];
719static struct __res_state
720 thread_specific_res_state[VG_N_THREADS];
sewardjf8f819e2002-04-17 23:21:37 +0000721
sewardj3b13f0e2002-04-25 20:17:29 +0000722int* __errno_location ( void )
sewardjf8f819e2002-04-17 23:21:37 +0000723{
724 int tid;
sewardj3b13f0e2002-04-25 20:17:29 +0000725 /* ensure_valgrind("__errno_location"); */
726 VALGRIND_MAGIC_SEQUENCE(tid, 1 /* default */,
sewardjf8f819e2002-04-17 23:21:37 +0000727 VG_USERREQ__PTHREAD_GET_THREADID,
728 0, 0, 0, 0);
sewardj3b13f0e2002-04-25 20:17:29 +0000729 /* 'cos I'm paranoid ... */
sewardj439d45e2002-05-03 20:43:10 +0000730 if (tid < 1 || tid >= VG_N_THREADS)
sewardj3b13f0e2002-04-25 20:17:29 +0000731 barf("__errno_location: invalid ThreadId");
732 return & thread_specific_errno[tid];
733}
734
735int* __h_errno_location ( void )
736{
737 int tid;
738 /* ensure_valgrind("__h_errno_location"); */
739 VALGRIND_MAGIC_SEQUENCE(tid, 1 /* default */,
740 VG_USERREQ__PTHREAD_GET_THREADID,
741 0, 0, 0, 0);
742 /* 'cos I'm paranoid ... */
sewardj439d45e2002-05-03 20:43:10 +0000743 if (tid < 1 || tid >= VG_N_THREADS)
sewardj3b13f0e2002-04-25 20:17:29 +0000744 barf("__h_errno_location: invalid ThreadId");
745 return & thread_specific_h_errno[tid];
746}
747
748struct __res_state* __res_state ( void )
749{
750 int tid;
751 /* ensure_valgrind("__res_state"); */
752 VALGRIND_MAGIC_SEQUENCE(tid, 1 /* default */,
753 VG_USERREQ__PTHREAD_GET_THREADID,
754 0, 0, 0, 0);
755 /* 'cos I'm paranoid ... */
sewardj439d45e2002-05-03 20:43:10 +0000756 if (tid < 1 || tid >= VG_N_THREADS)
sewardj3b13f0e2002-04-25 20:17:29 +0000757 barf("__res_state: invalid ThreadId");
758 return & thread_specific_res_state[tid];
sewardjf8f819e2002-04-17 23:21:37 +0000759}
760
761
sewardj5716dbb2002-04-26 03:28:18 +0000762/* ---------------------------------------------------
763 LIBC-PRIVATE SPECIFIC DATA
764 ------------------------------------------------ */
765
766/* Relies on assumption that initial private data is NULL. This
767 should be fixed somehow. */
768
769/* The allowable keys (indices) (all 2 of them).
770 From sysdeps/pthread/bits/libc-tsd.h
771*/
sewardj70adeb22002-04-27 01:35:38 +0000772#define N_LIBC_TSD_EXTRA_KEYS 1
773
sewardj5716dbb2002-04-26 03:28:18 +0000774enum __libc_tsd_key_t { _LIBC_TSD_KEY_MALLOC = 0,
775 _LIBC_TSD_KEY_DL_ERROR,
776 _LIBC_TSD_KEY_N };
777
778/* Auto-initialising subsystem. libc_specifics_inited is set
779 after initialisation. libc_specifics_inited_mx guards it. */
780static int libc_specifics_inited = 0;
781static pthread_mutex_t libc_specifics_inited_mx = PTHREAD_MUTEX_INITIALIZER;
782
783/* These are the keys we must initialise the first time. */
sewardj70adeb22002-04-27 01:35:38 +0000784static pthread_key_t libc_specifics_keys[_LIBC_TSD_KEY_N
785 + N_LIBC_TSD_EXTRA_KEYS];
sewardj5716dbb2002-04-26 03:28:18 +0000786
787/* Initialise the keys, if they are not already initialise. */
788static
789void init_libc_tsd_keys ( void )
790{
791 int res, i;
792 pthread_key_t k;
793
794 res = pthread_mutex_lock(&libc_specifics_inited_mx);
795 if (res != 0) barf("init_libc_tsd_keys: lock");
796
797 if (libc_specifics_inited == 0) {
798 /* printf("INIT libc specifics\n"); */
799 libc_specifics_inited = 1;
sewardj70adeb22002-04-27 01:35:38 +0000800 for (i = 0; i < _LIBC_TSD_KEY_N + N_LIBC_TSD_EXTRA_KEYS; i++) {
sewardj5716dbb2002-04-26 03:28:18 +0000801 res = pthread_key_create(&k, NULL);
802 if (res != 0) barf("init_libc_tsd_keys: create");
803 libc_specifics_keys[i] = k;
804 }
805 }
806
807 res = pthread_mutex_unlock(&libc_specifics_inited_mx);
808 if (res != 0) barf("init_libc_tsd_keys: unlock");
809}
810
811
812static int
813libc_internal_tsd_set ( enum __libc_tsd_key_t key,
814 const void * pointer )
815{
sewardj70adeb22002-04-27 01:35:38 +0000816 int res;
817 static int moans = N_MOANS;
sewardj5716dbb2002-04-26 03:28:18 +0000818 /* printf("SET SET SET key %d ptr %p\n", key, pointer); */
sewardj70adeb22002-04-27 01:35:38 +0000819 if (key < _LIBC_TSD_KEY_MALLOC
820 || key >= _LIBC_TSD_KEY_N + N_LIBC_TSD_EXTRA_KEYS)
sewardj5716dbb2002-04-26 03:28:18 +0000821 barf("libc_internal_tsd_set: invalid key");
sewardj70adeb22002-04-27 01:35:38 +0000822 if (key >= _LIBC_TSD_KEY_N && moans-- > 0)
823 fprintf(stderr,
sewardj439d45e2002-05-03 20:43:10 +0000824 "valgrind's libpthread.so: libc_internal_tsd_set: "
825 "dubious key %d\n", key);
sewardj5716dbb2002-04-26 03:28:18 +0000826 init_libc_tsd_keys();
827 res = pthread_setspecific(libc_specifics_keys[key], pointer);
828 if (res != 0) barf("libc_internal_tsd_set: setspecific failed");
829 return 0;
830}
831
832static void *
833libc_internal_tsd_get ( enum __libc_tsd_key_t key )
834{
sewardj70adeb22002-04-27 01:35:38 +0000835 void* v;
836 static int moans = N_MOANS;
sewardj5716dbb2002-04-26 03:28:18 +0000837 /* printf("GET GET GET key %d\n", key); */
sewardj70adeb22002-04-27 01:35:38 +0000838 if (key < _LIBC_TSD_KEY_MALLOC
839 || key >= _LIBC_TSD_KEY_N + N_LIBC_TSD_EXTRA_KEYS)
sewardj5716dbb2002-04-26 03:28:18 +0000840 barf("libc_internal_tsd_get: invalid key");
sewardj70adeb22002-04-27 01:35:38 +0000841 if (key >= _LIBC_TSD_KEY_N && moans-- > 0)
842 fprintf(stderr,
sewardj439d45e2002-05-03 20:43:10 +0000843 "valgrind's libpthread.so: libc_internal_tsd_get: "
844 "dubious key %d\n", key);
sewardj5716dbb2002-04-26 03:28:18 +0000845 init_libc_tsd_keys();
846 v = pthread_getspecific(libc_specifics_keys[key]);
847 /* if (v == NULL) barf("libc_internal_tsd_set: getspecific failed"); */
848 return v;
849}
850
851
852
853
sewardj70adeb22002-04-27 01:35:38 +0000854int (*__libc_internal_tsd_set)
855 (enum __libc_tsd_key_t key, const void * pointer)
856 = libc_internal_tsd_set;
sewardj5716dbb2002-04-26 03:28:18 +0000857
sewardj70adeb22002-04-27 01:35:38 +0000858void* (*__libc_internal_tsd_get)
859 (enum __libc_tsd_key_t key)
860 = libc_internal_tsd_get;
sewardj5716dbb2002-04-26 03:28:18 +0000861
862
sewardje663cb92002-04-12 10:26:32 +0000863/* ---------------------------------------------------------------------
864 These are here (I think) because they are deemed cancellation
865 points by POSIX. For the moment we'll simply pass the call along
866 to the corresponding thread-unaware (?) libc routine.
867 ------------------------------------------------------------------ */
868
sewardje663cb92002-04-12 10:26:32 +0000869#include <stdlib.h>
870#include <signal.h>
sewardje663cb92002-04-12 10:26:32 +0000871#include <sys/types.h>
872#include <sys/socket.h>
873
sewardjd529a442002-05-04 19:49:21 +0000874#ifdef GLIBC_2_1
875extern
876int __sigaction
877 (int signum,
878 const struct sigaction *act,
879 struct sigaction *oldact);
880#else
sewardje663cb92002-04-12 10:26:32 +0000881extern
882int __libc_sigaction
883 (int signum,
884 const struct sigaction *act,
885 struct sigaction *oldact);
sewardjd529a442002-05-04 19:49:21 +0000886#endif
sewardje663cb92002-04-12 10:26:32 +0000887int sigaction(int signum,
888 const struct sigaction *act,
889 struct sigaction *oldact)
890{
sewardj2a1dcce2002-04-22 12:45:25 +0000891# ifdef GLIBC_2_1
892 return __sigaction(signum, act, oldact);
893# else
sewardj45b4b372002-04-16 22:50:32 +0000894 return __libc_sigaction(signum, act, oldact);
sewardj2a1dcce2002-04-22 12:45:25 +0000895# endif
sewardje663cb92002-04-12 10:26:32 +0000896}
897
898
899extern
900int __libc_connect(int sockfd,
901 const struct sockaddr *serv_addr,
902 socklen_t addrlen);
sewardj5905fae2002-04-26 13:25:00 +0000903__attribute__((weak))
sewardje663cb92002-04-12 10:26:32 +0000904int connect(int sockfd,
905 const struct sockaddr *serv_addr,
906 socklen_t addrlen)
907{
sewardj45b4b372002-04-16 22:50:32 +0000908 return __libc_connect(sockfd, serv_addr, addrlen);
sewardje663cb92002-04-12 10:26:32 +0000909}
910
911
912extern
913int __libc_fcntl(int fd, int cmd, long arg);
sewardj5905fae2002-04-26 13:25:00 +0000914__attribute__((weak))
sewardje663cb92002-04-12 10:26:32 +0000915int fcntl(int fd, int cmd, long arg)
916{
sewardj45b4b372002-04-16 22:50:32 +0000917 return __libc_fcntl(fd, cmd, arg);
sewardje663cb92002-04-12 10:26:32 +0000918}
919
920
921extern
922ssize_t __libc_write(int fd, const void *buf, size_t count);
sewardj5905fae2002-04-26 13:25:00 +0000923__attribute__((weak))
sewardje663cb92002-04-12 10:26:32 +0000924ssize_t write(int fd, const void *buf, size_t count)
925{
sewardj45b4b372002-04-16 22:50:32 +0000926 return __libc_write(fd, buf, count);
sewardje663cb92002-04-12 10:26:32 +0000927}
928
929
930extern
931ssize_t __libc_read(int fd, void *buf, size_t count);
sewardj5905fae2002-04-26 13:25:00 +0000932__attribute__((weak))
sewardje663cb92002-04-12 10:26:32 +0000933ssize_t read(int fd, void *buf, size_t count)
934{
sewardj45b4b372002-04-16 22:50:32 +0000935 return __libc_read(fd, buf, count);
sewardje663cb92002-04-12 10:26:32 +0000936}
937
sewardjbe32e452002-04-24 20:29:58 +0000938
939extern
sewardj853f55d2002-04-26 00:27:53 +0000940int __libc_open64(const char *pathname, int flags, mode_t mode);
sewardj5905fae2002-04-26 13:25:00 +0000941__attribute__((weak))
sewardj853f55d2002-04-26 00:27:53 +0000942int open64(const char *pathname, int flags, mode_t mode)
sewardjbe32e452002-04-24 20:29:58 +0000943{
sewardj853f55d2002-04-26 00:27:53 +0000944 return __libc_open64(pathname, flags, mode);
sewardjbe32e452002-04-24 20:29:58 +0000945}
946
sewardje663cb92002-04-12 10:26:32 +0000947
948extern
sewardj853f55d2002-04-26 00:27:53 +0000949int __libc_open(const char *pathname, int flags, mode_t mode);
sewardj5905fae2002-04-26 13:25:00 +0000950__attribute__((weak))
sewardj853f55d2002-04-26 00:27:53 +0000951int open(const char *pathname, int flags, mode_t mode)
sewardje663cb92002-04-12 10:26:32 +0000952{
sewardj853f55d2002-04-26 00:27:53 +0000953 return __libc_open(pathname, flags, mode);
sewardje663cb92002-04-12 10:26:32 +0000954}
955
956
957extern
958int __libc_close(int fd);
sewardj5905fae2002-04-26 13:25:00 +0000959__attribute__((weak))
sewardje663cb92002-04-12 10:26:32 +0000960int close(int fd)
961{
sewardj45b4b372002-04-16 22:50:32 +0000962 return __libc_close(fd);
sewardje663cb92002-04-12 10:26:32 +0000963}
964
965
966extern
967int __libc_accept(int s, struct sockaddr *addr, socklen_t *addrlen);
sewardj5905fae2002-04-26 13:25:00 +0000968__attribute__((weak))
sewardje663cb92002-04-12 10:26:32 +0000969int accept(int s, struct sockaddr *addr, socklen_t *addrlen)
970{
sewardj45b4b372002-04-16 22:50:32 +0000971 return __libc_accept(s, addr, addrlen);
sewardje663cb92002-04-12 10:26:32 +0000972}
973
974
975extern
976pid_t __libc_fork(void);
sewardj5905fae2002-04-26 13:25:00 +0000977pid_t __fork(void)
sewardje663cb92002-04-12 10:26:32 +0000978{
sewardj45b4b372002-04-16 22:50:32 +0000979 return __libc_fork();
sewardje663cb92002-04-12 10:26:32 +0000980}
981
982
983extern
984pid_t __libc_waitpid(pid_t pid, int *status, int options);
sewardj5905fae2002-04-26 13:25:00 +0000985__attribute__((weak))
sewardje663cb92002-04-12 10:26:32 +0000986pid_t waitpid(pid_t pid, int *status, int options)
987{
sewardj45b4b372002-04-16 22:50:32 +0000988 return __libc_waitpid(pid, status, options);
sewardje663cb92002-04-12 10:26:32 +0000989}
990
991
992extern
993int __libc_nanosleep(const struct timespec *req, struct timespec *rem);
sewardj5905fae2002-04-26 13:25:00 +0000994__attribute__((weak))
sewardje663cb92002-04-12 10:26:32 +0000995int nanosleep(const struct timespec *req, struct timespec *rem)
996{
997 return __libc_nanosleep(req, rem);
998}
999
sewardjbe32e452002-04-24 20:29:58 +00001000
sewardje663cb92002-04-12 10:26:32 +00001001extern
1002int __libc_fsync(int fd);
sewardj5905fae2002-04-26 13:25:00 +00001003__attribute__((weak))
sewardje663cb92002-04-12 10:26:32 +00001004int fsync(int fd)
1005{
sewardj45b4b372002-04-16 22:50:32 +00001006 return __libc_fsync(fd);
sewardje663cb92002-04-12 10:26:32 +00001007}
1008
sewardjbe32e452002-04-24 20:29:58 +00001009
sewardj70c75362002-04-13 04:18:32 +00001010extern
1011off_t __libc_lseek(int fildes, off_t offset, int whence);
sewardj5905fae2002-04-26 13:25:00 +00001012__attribute__((weak))
sewardj70c75362002-04-13 04:18:32 +00001013off_t lseek(int fildes, off_t offset, int whence)
1014{
sewardj45b4b372002-04-16 22:50:32 +00001015 return __libc_lseek(fildes, offset, whence);
sewardj70c75362002-04-13 04:18:32 +00001016}
1017
sewardjbe32e452002-04-24 20:29:58 +00001018
1019extern
1020__off64_t __libc_lseek64(int fildes, __off64_t offset, int whence);
sewardj5905fae2002-04-26 13:25:00 +00001021__attribute__((weak))
sewardjbe32e452002-04-24 20:29:58 +00001022__off64_t lseek64(int fildes, __off64_t offset, int whence)
1023{
1024 return __libc_lseek64(fildes, offset, whence);
1025}
1026
1027
sewardj6af4b5d2002-04-16 04:40:49 +00001028extern
1029void __libc_longjmp(jmp_buf env, int val) __attribute((noreturn));
sewardj5905fae2002-04-26 13:25:00 +00001030/* not weak: __attribute__((weak)) */
sewardj6af4b5d2002-04-16 04:40:49 +00001031void longjmp(jmp_buf env, int val)
1032{
1033 __libc_longjmp(env, val);
1034}
1035
sewardjbe32e452002-04-24 20:29:58 +00001036
sewardj6af4b5d2002-04-16 04:40:49 +00001037extern
1038int __libc_send(int s, const void *msg, size_t len, int flags);
sewardj5905fae2002-04-26 13:25:00 +00001039__attribute__((weak))
sewardj6af4b5d2002-04-16 04:40:49 +00001040int send(int s, const void *msg, size_t len, int flags)
1041{
1042 return __libc_send(s, msg, len, flags);
1043}
1044
sewardjbe32e452002-04-24 20:29:58 +00001045
sewardj1e8cdc92002-04-18 11:37:52 +00001046extern
1047int __libc_recv(int s, void *buf, size_t len, int flags);
sewardj5905fae2002-04-26 13:25:00 +00001048__attribute__((weak))
sewardj1e8cdc92002-04-18 11:37:52 +00001049int recv(int s, void *buf, size_t len, int flags)
1050{
1051 return __libc_recv(s, buf, len, flags);
1052}
1053
sewardjbe32e452002-04-24 20:29:58 +00001054
sewardj796d6a22002-04-24 02:28:34 +00001055extern
sewardj436e0582002-04-26 14:31:40 +00001056int __libc_recvfrom(int s, void *buf, size_t len, int flags,
1057 struct sockaddr *from, socklen_t *fromlen);
1058__attribute__((weak))
1059int recvfrom(int s, void *buf, size_t len, int flags,
1060 struct sockaddr *from, socklen_t *fromlen)
1061{
1062 return __libc_recvfrom(s, buf, len, flags, from, fromlen);
1063}
1064
1065
1066extern
sewardj796d6a22002-04-24 02:28:34 +00001067int __libc_sendto(int s, const void *msg, size_t len, int flags,
1068 const struct sockaddr *to, socklen_t tolen);
sewardj5905fae2002-04-26 13:25:00 +00001069__attribute__((weak))
sewardj796d6a22002-04-24 02:28:34 +00001070int sendto(int s, const void *msg, size_t len, int flags,
1071 const struct sockaddr *to, socklen_t tolen)
1072{
1073 return __libc_sendto(s, msg, len, flags, to, tolen);
1074}
1075
sewardjbe32e452002-04-24 20:29:58 +00001076
sewardj369b1702002-04-24 13:28:15 +00001077extern
1078int __libc_system(const char* str);
sewardj5905fae2002-04-26 13:25:00 +00001079__attribute__((weak))
sewardj369b1702002-04-24 13:28:15 +00001080int system(const char* str)
1081{
1082 return __libc_system(str);
1083}
1084
sewardjbe32e452002-04-24 20:29:58 +00001085
sewardjab0b1c32002-04-24 19:26:47 +00001086extern
1087pid_t __libc_wait(int *status);
sewardj5905fae2002-04-26 13:25:00 +00001088__attribute__((weak))
sewardjab0b1c32002-04-24 19:26:47 +00001089pid_t wait(int *status)
1090{
1091 return __libc_wait(status);
1092}
1093
sewardj45b4b372002-04-16 22:50:32 +00001094
sewardj5905fae2002-04-26 13:25:00 +00001095
sewardj3b13f0e2002-04-25 20:17:29 +00001096/* ---------------------------------------------------------------------
1097 Nonblocking implementations of select() and poll(). This stuff will
1098 surely rot your mind.
1099 ------------------------------------------------------------------ */
sewardje663cb92002-04-12 10:26:32 +00001100
sewardj08a4c3f2002-04-13 03:45:44 +00001101/*--------------------------------------------------*/
1102
1103#include "vg_kerneliface.h"
1104
1105static
1106__inline__
1107int is_kerror ( int res )
1108{
1109 if (res >= -4095 && res <= -1)
1110 return 1;
1111 else
1112 return 0;
1113}
1114
1115
1116static
1117int my_do_syscall1 ( int syscallno, int arg1 )
1118{
1119 int __res;
1120 __asm__ volatile ("pushl %%ebx; movl %%edx,%%ebx ; int $0x80 ; popl %%ebx"
1121 : "=a" (__res)
1122 : "0" (syscallno),
1123 "d" (arg1) );
1124 return __res;
1125}
1126
1127static
1128int my_do_syscall2 ( int syscallno,
sewardjf854f472002-04-21 12:19:41 +00001129 int arg1, int arg2 )
sewardj08a4c3f2002-04-13 03:45:44 +00001130{
1131 int __res;
1132 __asm__ volatile ("pushl %%ebx; movl %%edx,%%ebx ; int $0x80 ; popl %%ebx"
1133 : "=a" (__res)
1134 : "0" (syscallno),
1135 "d" (arg1),
1136 "c" (arg2) );
1137 return __res;
1138}
1139
1140static
sewardjf854f472002-04-21 12:19:41 +00001141int my_do_syscall3 ( int syscallno,
1142 int arg1, int arg2, int arg3 )
1143{
1144 int __res;
1145 __asm__ volatile ("pushl %%ebx; movl %%esi,%%ebx ; int $0x80 ; popl %%ebx"
1146 : "=a" (__res)
1147 : "0" (syscallno),
1148 "S" (arg1),
1149 "c" (arg2),
1150 "d" (arg3) );
1151 return __res;
1152}
1153
1154static
sewardj08a4c3f2002-04-13 03:45:44 +00001155int do_syscall_select( int n,
1156 vki_fd_set* readfds,
1157 vki_fd_set* writefds,
1158 vki_fd_set* exceptfds,
1159 struct vki_timeval * timeout )
1160{
1161 int res;
1162 int args[5];
1163 args[0] = n;
1164 args[1] = (int)readfds;
1165 args[2] = (int)writefds;
1166 args[3] = (int)exceptfds;
1167 args[4] = (int)timeout;
1168 res = my_do_syscall1(__NR_select, (int)(&(args[0])) );
sewardj02535bc2002-04-21 01:08:26 +00001169 return res;
sewardj08a4c3f2002-04-13 03:45:44 +00001170}
1171
1172
1173/* This is a wrapper round select(), which makes it thread-safe,
1174 meaning that only this thread will block, rather than the entire
1175 process. This wrapper in turn depends on nanosleep() not to block
1176 the entire process, but I think (hope? suspect?) that POSIX
1177 pthreads guarantees that to be the case.
1178
1179 Basic idea is: modify the timeout parameter to select so that it
1180 returns immediately. Poll like this until select returns non-zero,
1181 indicating something interesting happened, or until our time is up.
1182 Space out the polls with nanosleeps of say 20 milliseconds, which
1183 is required to be nonblocking; this allows other threads to run.
sewardj02535bc2002-04-21 01:08:26 +00001184
1185 Assumes:
1186 * (checked via assert) types fd_set and vki_fd_set are identical.
1187 * (checked via assert) types timeval and vki_timeval are identical.
1188 * (unchecked) libc error numbers (EINTR etc) are the negation of the
1189 kernel's error numbers (VKI_EINTR etc).
sewardj08a4c3f2002-04-13 03:45:44 +00001190*/
sewardj08a4c3f2002-04-13 03:45:44 +00001191
sewardj5905fae2002-04-26 13:25:00 +00001192/* __attribute__((weak)) */
sewardj08a4c3f2002-04-13 03:45:44 +00001193int select ( int n,
1194 fd_set *rfds,
1195 fd_set *wfds,
1196 fd_set *xfds,
1197 struct timeval *timeout )
1198{
sewardj5f07b662002-04-23 16:52:51 +00001199 unsigned int ms_now, ms_end;
sewardj08a4c3f2002-04-13 03:45:44 +00001200 int res;
1201 fd_set rfds_copy;
1202 fd_set wfds_copy;
1203 fd_set xfds_copy;
1204 struct vki_timeval t_now;
sewardj08a4c3f2002-04-13 03:45:44 +00001205 struct vki_timeval zero_timeout;
1206 struct vki_timespec nanosleep_interval;
1207
sewardj5f07b662002-04-23 16:52:51 +00001208 /* gcc's complains about ms_end being used uninitialised -- classic
1209 case it can't understand, where ms_end is both defined and used
1210 only if timeout != NULL. Hence ... */
1211 ms_end = 0;
sewardj08a4c3f2002-04-13 03:45:44 +00001212
1213 /* We assume that the kernel and libc data layouts are identical
1214 for the following types. These asserts provide a crude
1215 check. */
1216 if (sizeof(fd_set) != sizeof(vki_fd_set)
1217 || sizeof(struct timeval) != sizeof(struct vki_timeval))
1218 barf("valgrind's hacky non-blocking select(): data sizes error");
1219
sewardj5f07b662002-04-23 16:52:51 +00001220 /* Detect the current time and simultaneously find out if we are
1221 running on Valgrind. */
1222 VALGRIND_MAGIC_SEQUENCE(ms_now, 0xFFFFFFFF /* default */,
1223 VG_USERREQ__READ_MILLISECOND_TIMER,
1224 0, 0, 0, 0);
1225
1226 /* If a zero timeout specified, this call is harmless. Also go
1227 this route if we're not running on Valgrind, for whatever
1228 reason. */
1229 if ( (timeout && timeout->tv_sec == 0 && timeout->tv_usec == 0)
1230 || (ms_now == 0xFFFFFFFF) ) {
sewardj02535bc2002-04-21 01:08:26 +00001231 res = do_syscall_select( n, (vki_fd_set*)rfds,
sewardj08a4c3f2002-04-13 03:45:44 +00001232 (vki_fd_set*)wfds,
1233 (vki_fd_set*)xfds,
1234 (struct vki_timeval*)timeout);
sewardj02535bc2002-04-21 01:08:26 +00001235 if (is_kerror(res)) {
1236 * (__errno_location()) = -res;
1237 return -1;
1238 } else {
1239 return res;
1240 }
1241 }
sewardj08a4c3f2002-04-13 03:45:44 +00001242
sewardj5f07b662002-04-23 16:52:51 +00001243 /* If a timeout was specified, set ms_end to be the end millisecond
1244 counter [wallclock] time. */
sewardj08a4c3f2002-04-13 03:45:44 +00001245 if (timeout) {
1246 res = my_do_syscall2(__NR_gettimeofday, (int)&t_now, (int)NULL);
1247 assert(res == 0);
sewardj5f07b662002-04-23 16:52:51 +00001248 ms_end = ms_now;
1249 ms_end += (timeout->tv_usec / 1000);
1250 ms_end += (timeout->tv_sec * 1000);
sewardj08a4c3f2002-04-13 03:45:44 +00001251 /* Stay sane ... */
sewardj5f07b662002-04-23 16:52:51 +00001252 assert (ms_end >= ms_now);
sewardj08a4c3f2002-04-13 03:45:44 +00001253 }
1254
1255 /* fprintf(stderr, "MY_SELECT: before loop\n"); */
1256
1257 /* Either timeout == NULL, meaning wait indefinitely, or timeout !=
sewardj5f07b662002-04-23 16:52:51 +00001258 NULL, in which case ms_end holds the end time. */
sewardj08a4c3f2002-04-13 03:45:44 +00001259 while (1) {
1260 if (timeout) {
sewardj5f07b662002-04-23 16:52:51 +00001261 VALGRIND_MAGIC_SEQUENCE(ms_now, 0xFFFFFFFF /* default */,
1262 VG_USERREQ__READ_MILLISECOND_TIMER,
1263 0, 0, 0, 0);
1264 assert(ms_now != 0xFFFFFFFF);
1265 if (ms_now >= ms_end) {
sewardj08a4c3f2002-04-13 03:45:44 +00001266 /* timeout; nothing interesting happened. */
1267 if (rfds) FD_ZERO(rfds);
1268 if (wfds) FD_ZERO(wfds);
1269 if (xfds) FD_ZERO(xfds);
1270 return 0;
1271 }
1272 }
1273
1274 /* These could be trashed each time round the loop, so restore
1275 them each time. */
1276 if (rfds) rfds_copy = *rfds;
1277 if (wfds) wfds_copy = *wfds;
1278 if (xfds) xfds_copy = *xfds;
1279
1280 zero_timeout.tv_sec = zero_timeout.tv_usec = 0;
1281
1282 res = do_syscall_select( n,
1283 rfds ? (vki_fd_set*)(&rfds_copy) : NULL,
1284 wfds ? (vki_fd_set*)(&wfds_copy) : NULL,
1285 xfds ? (vki_fd_set*)(&xfds_copy) : NULL,
1286 & zero_timeout );
sewardj02535bc2002-04-21 01:08:26 +00001287 if (is_kerror(res)) {
1288 /* Some kind of error (including EINTR). Set errno and
sewardj08a4c3f2002-04-13 03:45:44 +00001289 return. The sets are unspecified in this case. */
sewardj02535bc2002-04-21 01:08:26 +00001290 * (__errno_location()) = -res;
1291 return -1;
sewardj08a4c3f2002-04-13 03:45:44 +00001292 }
1293 if (res > 0) {
1294 /* one or more fds is ready. Copy out resulting sets and
1295 return. */
1296 if (rfds) *rfds = rfds_copy;
1297 if (wfds) *wfds = wfds_copy;
1298 if (xfds) *xfds = xfds_copy;
1299 return res;
1300 }
1301 /* fprintf(stderr, "MY_SELECT: nanosleep\n"); */
1302 /* nanosleep and go round again */
sewardj02535bc2002-04-21 01:08:26 +00001303 nanosleep_interval.tv_sec = 0;
sewardj956cc1b2002-04-25 01:33:50 +00001304 nanosleep_interval.tv_nsec = 50 * 1000 * 1000; /* 50 milliseconds */
sewardjf854f472002-04-21 12:19:41 +00001305 /* It's critical here that valgrind's nanosleep implementation
1306 is nonblocking. */
1307 (void)my_do_syscall2(__NR_nanosleep,
1308 (int)(&nanosleep_interval), (int)NULL);
1309 }
1310}
1311
1312
1313
1314
1315#include <sys/poll.h>
1316
sewardj72d58482002-04-24 02:20:20 +00001317#ifdef GLIBC_2_1
1318typedef unsigned long int nfds_t;
1319#endif
1320
sewardj5905fae2002-04-26 13:25:00 +00001321/* __attribute__((weak)) */
sewardjf854f472002-04-21 12:19:41 +00001322int poll (struct pollfd *__fds, nfds_t __nfds, int __timeout)
1323{
sewardj5f07b662002-04-23 16:52:51 +00001324 unsigned int ms_now, ms_end;
sewardjf854f472002-04-21 12:19:41 +00001325 int res, i;
sewardjf854f472002-04-21 12:19:41 +00001326 struct vki_timespec nanosleep_interval;
1327
1328 ensure_valgrind("poll");
1329
sewardj5f07b662002-04-23 16:52:51 +00001330 /* Detect the current time and simultaneously find out if we are
1331 running on Valgrind. */
1332 VALGRIND_MAGIC_SEQUENCE(ms_now, 0xFFFFFFFF /* default */,
1333 VG_USERREQ__READ_MILLISECOND_TIMER,
1334 0, 0, 0, 0);
1335
sewardjf854f472002-04-21 12:19:41 +00001336 if (/* CHECK SIZES FOR struct pollfd */
1337 sizeof(struct timeval) != sizeof(struct vki_timeval))
1338 barf("valgrind's hacky non-blocking poll(): data sizes error");
1339
sewardj5f07b662002-04-23 16:52:51 +00001340 /* dummy initialisation to keep gcc -Wall happy */
1341 ms_end = 0;
1342
1343 /* If a zero timeout specified, this call is harmless. Also do
1344 this if not running on Valgrind. */
1345 if (__timeout == 0 || ms_now == 0xFFFFFFFF) {
sewardjf854f472002-04-21 12:19:41 +00001346 res = my_do_syscall3(__NR_poll, (int)__fds, __nfds, __timeout);
1347 if (is_kerror(res)) {
1348 * (__errno_location()) = -res;
1349 return -1;
1350 } else {
1351 return res;
1352 }
1353 }
1354
sewardj5f07b662002-04-23 16:52:51 +00001355 /* If a timeout was specified, set ms_end to be the end wallclock
1356 time. Easy considering that __timeout is in milliseconds. */
sewardjf854f472002-04-21 12:19:41 +00001357 if (__timeout > 0) {
sewardj650ac002002-04-29 12:20:34 +00001358 ms_end = ms_now + (unsigned int)__timeout;
sewardjf854f472002-04-21 12:19:41 +00001359 }
1360
1361 /* fprintf(stderr, "MY_POLL: before loop\n"); */
1362
1363 /* Either timeout < 0, meaning wait indefinitely, or timeout > 0,
1364 in which case t_end holds the end time. */
sewardj5f07b662002-04-23 16:52:51 +00001365 assert(__timeout != 0);
1366
sewardjf854f472002-04-21 12:19:41 +00001367 while (1) {
sewardjf854f472002-04-21 12:19:41 +00001368 if (__timeout > 0) {
sewardj5f07b662002-04-23 16:52:51 +00001369 VALGRIND_MAGIC_SEQUENCE(ms_now, 0xFFFFFFFF /* default */,
1370 VG_USERREQ__READ_MILLISECOND_TIMER,
1371 0, 0, 0, 0);
1372 assert(ms_now != 0xFFFFFFFF);
1373 if (ms_now >= ms_end) {
sewardjf854f472002-04-21 12:19:41 +00001374 /* timeout; nothing interesting happened. */
1375 for (i = 0; i < __nfds; i++)
1376 __fds[i].revents = 0;
1377 return 0;
1378 }
1379 }
1380
sewardj5f07b662002-04-23 16:52:51 +00001381 /* Do a return-immediately poll. */
sewardjf854f472002-04-21 12:19:41 +00001382 res = my_do_syscall3(__NR_poll, (int)__fds, __nfds, 0 );
1383 if (is_kerror(res)) {
1384 /* Some kind of error. Set errno and return. */
1385 * (__errno_location()) = -res;
1386 return -1;
1387 }
1388 if (res > 0) {
1389 /* One or more fds is ready. Return now. */
1390 return res;
1391 }
1392 /* fprintf(stderr, "MY_POLL: nanosleep\n"); */
1393 /* nanosleep and go round again */
1394 nanosleep_interval.tv_sec = 0;
sewardj956cc1b2002-04-25 01:33:50 +00001395 nanosleep_interval.tv_nsec = 51 * 1000 * 1000; /* 51 milliseconds */
sewardj08a4c3f2002-04-13 03:45:44 +00001396 /* It's critical here that valgrind's nanosleep implementation
1397 is nonblocking. */
1398 (void)my_do_syscall2(__NR_nanosleep,
1399 (int)(&nanosleep_interval), (int)NULL);
1400 }
1401}
sewardj3b13f0e2002-04-25 20:17:29 +00001402
1403
1404/* ---------------------------------------------------------------------
1405 B'stard.
1406 ------------------------------------------------------------------ */
1407
1408# define strong_alias(name, aliasname) \
1409 extern __typeof (name) aliasname __attribute__ ((alias (#name)));
1410
sewardj5905fae2002-04-26 13:25:00 +00001411# define weak_alias(name, aliasname) \
1412 extern __typeof (name) aliasname __attribute__ ((weak, alias (#name)));
sewardj3b13f0e2002-04-25 20:17:29 +00001413
sewardj5905fae2002-04-26 13:25:00 +00001414strong_alias(__pthread_mutex_lock, pthread_mutex_lock)
1415strong_alias(__pthread_mutex_trylock, pthread_mutex_trylock)
1416strong_alias(__pthread_mutex_unlock, pthread_mutex_unlock)
1417strong_alias(__pthread_mutexattr_init, pthread_mutexattr_init)
1418 weak_alias(__pthread_mutexattr_settype, pthread_mutexattr_settype)
1419strong_alias(__pthread_mutex_init, pthread_mutex_init)
1420strong_alias(__pthread_mutexattr_destroy, pthread_mutexattr_destroy)
1421strong_alias(__pthread_mutex_destroy, pthread_mutex_destroy)
1422strong_alias(__pthread_once, pthread_once)
1423strong_alias(__pthread_atfork, pthread_atfork)
1424strong_alias(__pthread_key_create, pthread_key_create)
1425strong_alias(__pthread_getspecific, pthread_getspecific)
1426strong_alias(__pthread_setspecific, pthread_setspecific)
1427
sewardjd529a442002-05-04 19:49:21 +00001428#ifndef GLIBC_2_1
sewardj3b13f0e2002-04-25 20:17:29 +00001429strong_alias(sigaction, __sigaction)
sewardjd529a442002-05-04 19:49:21 +00001430#endif
1431
sewardj5905fae2002-04-26 13:25:00 +00001432strong_alias(close, __close)
sewardj3b13f0e2002-04-25 20:17:29 +00001433strong_alias(fcntl, __fcntl)
sewardj5905fae2002-04-26 13:25:00 +00001434strong_alias(lseek, __lseek)
1435strong_alias(open, __open)
1436strong_alias(open64, __open64)
1437//strong_alias(pread64, __pread64)
1438//strong_alias(pwrite64, __pwrite64)
1439strong_alias(read, __read)
1440strong_alias(wait, __wait)
1441strong_alias(write, __write)
sewardj3b13f0e2002-04-25 20:17:29 +00001442strong_alias(connect, __connect)
sewardj5905fae2002-04-26 13:25:00 +00001443strong_alias(send, __send)
1444
1445weak_alias(__fork, fork)
1446//weak_alias(__vfork, vfork)
1447
sewardj3b13f0e2002-04-25 20:17:29 +00001448
1449/*--------------------------------------------------*/
1450
sewardj5716dbb2002-04-26 03:28:18 +00001451int
1452pthread_rwlock_rdlock (void* /* pthread_rwlock_t* */ rwlock)
1453{
sewardj436e0582002-04-26 14:31:40 +00001454 static int moans = N_MOANS;
1455 if (moans-- > 0)
1456 kludged("pthread_rwlock_rdlock");
sewardj5716dbb2002-04-26 03:28:18 +00001457 return 0;
1458}
1459
sewardj5905fae2002-04-26 13:25:00 +00001460weak_alias(pthread_rwlock_rdlock, __pthread_rwlock_rdlock)
sewardj5716dbb2002-04-26 03:28:18 +00001461
1462
1463int
1464pthread_rwlock_unlock (void* /* pthread_rwlock_t* */ rwlock)
1465{
sewardj436e0582002-04-26 14:31:40 +00001466 static int moans = N_MOANS;
1467 if (moans-- > 0)
1468 kludged("pthread_rwlock_unlock");
sewardj5716dbb2002-04-26 03:28:18 +00001469 return 0;
1470}
1471
sewardj5905fae2002-04-26 13:25:00 +00001472weak_alias(pthread_rwlock_unlock, __pthread_rwlock_unlock)
sewardj5716dbb2002-04-26 03:28:18 +00001473
1474
sewardj060b04f2002-04-26 21:01:13 +00001475int
1476pthread_rwlock_wrlock (void* /* pthread_rwlock_t* */ rwlock)
1477{
1478 static int moans = N_MOANS;
1479 if (moans-- > 0)
1480 kludged("pthread_rwlock_wrlock");
1481 return 0;
1482}
1483
sewardj262b0292002-05-01 00:03:16 +00001484weak_alias(pthread_rwlock_wrlock, __pthread_rwlock_wrlock)
sewardj060b04f2002-04-26 21:01:13 +00001485
1486
sewardj3b13f0e2002-04-25 20:17:29 +00001487/* I've no idea what these are, but they get called quite a lot.
1488 Anybody know? */
1489
1490#undef _IO_flockfile
1491void _IO_flockfile ( _IO_FILE * file )
1492{
sewardj853f55d2002-04-26 00:27:53 +00001493 pthread_mutex_lock(file->_lock);
sewardj3b13f0e2002-04-25 20:17:29 +00001494}
sewardj5905fae2002-04-26 13:25:00 +00001495weak_alias(_IO_flockfile, flockfile);
1496
sewardj3b13f0e2002-04-25 20:17:29 +00001497
1498#undef _IO_funlockfile
1499void _IO_funlockfile ( _IO_FILE * file )
1500{
sewardj853f55d2002-04-26 00:27:53 +00001501 pthread_mutex_unlock(file->_lock);
sewardj3b13f0e2002-04-25 20:17:29 +00001502}
sewardj5905fae2002-04-26 13:25:00 +00001503weak_alias(_IO_funlockfile, funlockfile);
1504
sewardj3b13f0e2002-04-25 20:17:29 +00001505
1506void _pthread_cleanup_push_defer ( void )
1507{
sewardj439d45e2002-05-03 20:43:10 +00001508 static int moans = N_MOANS;
1509 if (moans-- > 0)
1510 ignored("_pthread_cleanup_push_defer");
sewardj3b13f0e2002-04-25 20:17:29 +00001511}
1512
1513void _pthread_cleanup_pop_restore ( void )
1514{
sewardj439d45e2002-05-03 20:43:10 +00001515 static int moans = N_MOANS;
1516 if (moans-- > 0)
1517 ignored("_pthread_cleanup_pop_restore");
sewardj3b13f0e2002-04-25 20:17:29 +00001518}
sewardjd4f2c712002-04-30 10:20:10 +00001519
sewardj60e38422002-05-08 14:08:22 +00001520/*--------*/
1521void _pthread_cleanup_push (struct _pthread_cleanup_buffer *__buffer,
1522 void (*__routine) (void *),
1523 void *__arg)
1524{
1525 static int moans = N_MOANS;
1526 if (moans-- > 0)
1527 ignored("_pthread_cleanup_push");
1528}
1529
1530void _pthread_cleanup_pop (struct _pthread_cleanup_buffer *__buffer,
1531 int __execute)
1532{
1533 static int moans = N_MOANS;
1534 if (moans-- > 0) {
1535 if (__execute)
1536 ignored("_pthread_cleanup_pop-EXECUTE");
1537 else
1538 ignored("_pthread_cleanup_pop-NO-EXECUTE");
1539 }
1540}
1541
sewardjd4f2c712002-04-30 10:20:10 +00001542
1543/* This doesn't seem to be needed to simulate libpthread.so's external
1544 interface, but many people complain about its absence. */
1545
1546strong_alias(__pthread_mutexattr_settype, __pthread_mutexattr_setkind_np)
1547weak_alias(__pthread_mutexattr_setkind_np, pthread_mutexattr_setkind_np)
sewardj439d45e2002-05-03 20:43:10 +00001548
1549
1550/*--------------------------------------------------------------------*/
1551/*--- end vg_libpthread.c ---*/
1552/*--------------------------------------------------------------------*/