blob: f71eff41852d7d0d1740f41be64c1640560bbd3e [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
sewardja1ac5cb2002-05-27 13:00:05 +000058#define __USE_UNIX98
59#include <sys/types.h>
60#include <pthread.h>
61#undef __USE_UNIX98
62
sewardje663cb92002-04-12 10:26:32 +000063#include <unistd.h>
64#include <string.h>
sewardj2a1dcce2002-04-22 12:45:25 +000065#ifdef GLIBC_2_1
66#include <sys/time.h>
67#endif
sewardje663cb92002-04-12 10:26:32 +000068
sewardj2d94c112002-06-03 01:25:54 +000069#include <stdio.h>
70
sewardj705d3cb2002-05-23 13:13:12 +000071
72/* ---------------------------------------------------------------------
73 Forwardses.
74 ------------------------------------------------------------------ */
75
76static void wait_for_fd_to_be_readable_or_erring ( int fd );
77
78
sewardje663cb92002-04-12 10:26:32 +000079/* ---------------------------------------------------------------------
80 Helpers. We have to be pretty self-sufficient.
81 ------------------------------------------------------------------ */
82
sewardj436e0582002-04-26 14:31:40 +000083/* Number of times any given error message is printed. */
84#define N_MOANS 3
85
sewardj45b4b372002-04-16 22:50:32 +000086/* Extract from Valgrind the value of VG_(clo_trace_pthread_level).
87 Returns 0 (none) if not running on Valgrind. */
88static
89int get_pt_trace_level ( void )
90{
91 int res;
92 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
93 VG_USERREQ__GET_PTHREAD_TRACE_LEVEL,
94 0, 0, 0, 0);
95 return res;
96}
97
98
sewardje663cb92002-04-12 10:26:32 +000099static
sewardj2d94c112002-06-03 01:25:54 +0000100void my_exit ( int arg )
sewardje663cb92002-04-12 10:26:32 +0000101{
sewardj45b4b372002-04-16 22:50:32 +0000102 int __res;
sewardje663cb92002-04-12 10:26:32 +0000103 __asm__ volatile ("movl %%ecx, %%ebx ; int $0x80"
104 : "=a" (__res)
105 : "0" (__NR_exit),
106 "c" (arg) );
sewardj45b4b372002-04-16 22:50:32 +0000107 /* We don't bother to mention the fact that this asm trashes %ebx,
108 since it won't return. If you ever do let it return ... fix
109 this! */
sewardje663cb92002-04-12 10:26:32 +0000110}
111
112
sewardj68b2dd92002-05-10 21:03:56 +0000113/* We need this guy -- it's in valgrind.so. */
114extern void VG_(startup) ( void );
115
116
117/* Just start up Valgrind if it's not already going. VG_(startup)()
118 detects and ignores second and subsequent calls. */
sewardj604ec3c2002-04-18 22:38:41 +0000119static __inline__
sewardje663cb92002-04-12 10:26:32 +0000120void ensure_valgrind ( char* caller )
121{
sewardj68b2dd92002-05-10 21:03:56 +0000122 VG_(startup)();
sewardje663cb92002-04-12 10:26:32 +0000123}
124
sewardjbea1caa2002-05-10 23:20:58 +0000125/* While we're at it ... hook our own startup function into this
126 game. */
127__asm__ (
128 ".section .init\n"
129 "\tcall vgPlain_startup"
130);
131
sewardje663cb92002-04-12 10:26:32 +0000132
133static
sewardj3b5d8862002-04-20 13:53:23 +0000134__attribute__((noreturn))
sewardje663cb92002-04-12 10:26:32 +0000135void barf ( char* str )
136{
137 char buf[100];
138 buf[0] = 0;
sewardj439d45e2002-05-03 20:43:10 +0000139 strcat(buf, "\nvalgrind's libpthread.so: ");
sewardje663cb92002-04-12 10:26:32 +0000140 strcat(buf, str);
141 strcat(buf, "\n\n");
142 write(2, buf, strlen(buf));
sewardj2d94c112002-06-03 01:25:54 +0000143 my_exit(1);
sewardj3b5d8862002-04-20 13:53:23 +0000144 /* We have to persuade gcc into believing this doesn't return. */
145 while (1) { };
sewardje663cb92002-04-12 10:26:32 +0000146}
147
148
sewardj2a3d28c2002-04-14 13:27:00 +0000149static void ignored ( char* msg )
150{
sewardj436e0582002-04-26 14:31:40 +0000151 if (get_pt_trace_level() >= 0) {
sewardj439d45e2002-05-03 20:43:10 +0000152 char* ig = "valgrind's libpthread.so: IGNORED call to: ";
sewardj45b4b372002-04-16 22:50:32 +0000153 write(2, ig, strlen(ig));
154 write(2, msg, strlen(msg));
155 ig = "\n";
156 write(2, ig, strlen(ig));
157 }
sewardj2a3d28c2002-04-14 13:27:00 +0000158}
159
sewardj30671ff2002-04-21 00:13:57 +0000160static void kludged ( char* msg )
161{
sewardj436e0582002-04-26 14:31:40 +0000162 if (get_pt_trace_level() >= 0) {
sewardj439d45e2002-05-03 20:43:10 +0000163 char* ig = "valgrind's libpthread.so: KLUDGED call to: ";
164 write(2, ig, strlen(ig));
165 write(2, msg, strlen(msg));
166 ig = "\n";
167 write(2, ig, strlen(ig));
168 }
169}
170
171static void not_inside ( char* msg )
172{
sewardj68b2dd92002-05-10 21:03:56 +0000173 VG_(startup)();
sewardj30671ff2002-04-21 00:13:57 +0000174}
175
sewardjccef2e62002-05-29 19:26:32 +0000176__attribute__((noreturn))
sewardj3b13f0e2002-04-25 20:17:29 +0000177void vgPlain_unimp ( char* what )
178{
sewardj439d45e2002-05-03 20:43:10 +0000179 char* ig = "valgrind's libpthread.so: UNIMPLEMENTED FUNCTION: ";
sewardj3b13f0e2002-04-25 20:17:29 +0000180 write(2, ig, strlen(ig));
181 write(2, what, strlen(what));
182 ig = "\n";
183 write(2, ig, strlen(ig));
184 barf("Please report this bug to me at: jseward@acm.org");
185}
186
sewardje663cb92002-04-12 10:26:32 +0000187
sewardj2d94c112002-06-03 01:25:54 +0000188void my_assert_fail ( Char* expr, Char* file, Int line, Char* fn )
189{
190 static Bool entered = False;
191 if (entered)
192 my_exit(2);
193 entered = True;
194 fprintf(stderr, "\n%s: %s:%d (%s): Assertion `%s' failed.\n",
195 "valgrind", file, line, fn, expr );
196 fprintf(stderr, "Please report this bug to me at: %s\n\n",
197 VG_EMAIL_ADDR);
198 my_exit(1);
199}
200
201#define MY__STRING(__str) #__str
202
203#define my_assert(expr) \
204 ((void) ((expr) ? 0 : \
205 (my_assert_fail (MY__STRING(expr), \
206 __FILE__, __LINE__, \
207 __PRETTY_FUNCTION__), 0)))
208
209
sewardje663cb92002-04-12 10:26:32 +0000210/* ---------------------------------------------------------------------
211 Pass pthread_ calls to Valgrind's request mechanism.
212 ------------------------------------------------------------------ */
213
sewardjf8f819e2002-04-17 23:21:37 +0000214#include <errno.h>
sewardj5f07b662002-04-23 16:52:51 +0000215#include <sys/time.h> /* gettimeofday */
sewardjf8f819e2002-04-17 23:21:37 +0000216
sewardja1ac5cb2002-05-27 13:00:05 +0000217
sewardjf8f819e2002-04-17 23:21:37 +0000218/* ---------------------------------------------------
219 THREAD ATTRIBUTES
220 ------------------------------------------------ */
221
sewardj6af4b5d2002-04-16 04:40:49 +0000222int pthread_attr_init(pthread_attr_t *attr)
223{
sewardj7989d0c2002-05-28 11:00:01 +0000224 /* Just initialise the fields which we might look at. */
225 attr->__detachstate = PTHREAD_CREATE_JOINABLE;
sewardj6af4b5d2002-04-16 04:40:49 +0000226 return 0;
227}
228
229int pthread_attr_setdetachstate(pthread_attr_t *attr, int detachstate)
230{
sewardj7989d0c2002-05-28 11:00:01 +0000231 if (detachstate != PTHREAD_CREATE_JOINABLE
232 && detachstate != PTHREAD_CREATE_DETACHED)
233 return EINVAL;
234 attr->__detachstate = detachstate;
sewardj6af4b5d2002-04-16 04:40:49 +0000235 return 0;
236}
237
sewardj30671ff2002-04-21 00:13:57 +0000238int pthread_attr_setinheritsched(pthread_attr_t *attr, int inherit)
239{
sewardj436e0582002-04-26 14:31:40 +0000240 static int moans = N_MOANS;
241 if (moans-- > 0)
242 ignored("pthread_attr_setinheritsched");
sewardj30671ff2002-04-21 00:13:57 +0000243 return 0;
244}
sewardj6af4b5d2002-04-16 04:40:49 +0000245
sewardj0286dd52002-05-16 20:51:15 +0000246__attribute__((weak))
247int pthread_attr_setstacksize (pthread_attr_t *__attr,
248 size_t __stacksize)
249{
sewardja18e2102002-05-18 10:43:22 +0000250 size_t limit;
sewardj0286dd52002-05-16 20:51:15 +0000251 ensure_valgrind("pthread_attr_setstacksize");
sewardja18e2102002-05-18 10:43:22 +0000252 limit = VG_PTHREAD_STACK_SIZE - VG_AR_CLIENT_STACKBASE_REDZONE_SZB
253 - 1000; /* paranoia */
254 if (__stacksize < limit)
sewardj0286dd52002-05-16 20:51:15 +0000255 return 0;
256 barf("pthread_attr_setstacksize: "
257 "requested size >= VG_PTHREAD_STACK_SIZE\n "
258 "edit vg_include.h and rebuild.");
259}
260
261
sewardj30671ff2002-04-21 00:13:57 +0000262/* This is completely bogus. */
263int pthread_attr_getschedparam(const pthread_attr_t *attr,
264 struct sched_param *param)
265{
sewardj436e0582002-04-26 14:31:40 +0000266 static int moans = N_MOANS;
267 if (moans-- > 0)
268 kludged("pthread_attr_getschedparam");
sewardj3e909ce2002-06-03 13:27:15 +0000269# ifdef HAVE_SCHED_PRIORITY
sewardj72d58482002-04-24 02:20:20 +0000270 if (param) param->sched_priority = 0; /* who knows */
271# else
sewardj30671ff2002-04-21 00:13:57 +0000272 if (param) param->__sched_priority = 0; /* who knows */
sewardj72d58482002-04-24 02:20:20 +0000273# endif
sewardj30671ff2002-04-21 00:13:57 +0000274 return 0;
275}
276
277int pthread_attr_setschedparam(pthread_attr_t *attr,
278 const struct sched_param *param)
279{
sewardj436e0582002-04-26 14:31:40 +0000280 static int moans = N_MOANS;
281 if (moans-- > 0)
282 ignored("pthread_attr_setschedparam");
sewardj30671ff2002-04-21 00:13:57 +0000283 return 0;
284}
285
286int pthread_attr_destroy(pthread_attr_t *attr)
287{
sewardj436e0582002-04-26 14:31:40 +0000288 static int moans = N_MOANS;
289 if (moans-- > 0)
290 ignored("pthread_attr_destroy");
sewardj30671ff2002-04-21 00:13:57 +0000291 return 0;
292}
sewardjf8f819e2002-04-17 23:21:37 +0000293
sewardj0d844232002-06-02 09:29:31 +0000294/* These are no-ops, as with LinuxThreads. */
295int pthread_attr_setscope ( pthread_attr_t *attr, int scope )
296{
297 ensure_valgrind("pthread_attr_setscope");
298 if (scope == PTHREAD_SCOPE_SYSTEM)
299 return 0;
300 if (scope == PTHREAD_SCOPE_PROCESS)
301 return ENOTSUP;
302 return EINVAL;
303}
304
305int pthread_attr_getscope ( const pthread_attr_t *attr, int *scope )
306{
307 ensure_valgrind("pthread_attr_setscope");
308 if (scope)
309 *scope = PTHREAD_SCOPE_SYSTEM;
310 return 0;
311}
312
sewardj64039bb2002-06-03 00:58:18 +0000313
314/* Pretty bogus. Avoid if possible. */
315int pthread_getattr_np (pthread_t thread, pthread_attr_t *attr)
316{
317 int detached;
318 size_t limit;
319 ensure_valgrind("pthread_getattr_np");
320 kludged("pthread_getattr_np");
321 limit = VG_PTHREAD_STACK_SIZE - VG_AR_CLIENT_STACKBASE_REDZONE_SZB
322 - 1000; /* paranoia */
323 attr->__detachstate = PTHREAD_CREATE_JOINABLE;
324 attr->__schedpolicy = SCHED_OTHER;
325 attr->__schedparam.sched_priority = 0;
326 attr->__inheritsched = PTHREAD_EXPLICIT_SCHED;
327 attr->__scope = PTHREAD_SCOPE_SYSTEM;
328 attr->__guardsize = VKI_BYTES_PER_PAGE;
329 attr->__stackaddr = NULL;
330 attr->__stackaddr_set = 0;
331 attr->__stacksize = limit;
332 VALGRIND_MAGIC_SEQUENCE(detached, (-1) /* default */,
333 VG_USERREQ__SET_OR_GET_DETACH,
334 2 /* get */, thread, 0, 0);
sewardj2d94c112002-06-03 01:25:54 +0000335 my_assert(detached == 0 || detached == 1);
sewardj64039bb2002-06-03 00:58:18 +0000336 if (detached)
337 attr->__detachstate = PTHREAD_CREATE_DETACHED;
338 return 0;
339}
340
341
342/* Bogus ... */
343int pthread_attr_getstackaddr ( const pthread_attr_t * attr,
344 void ** stackaddr )
345{
346 ensure_valgrind("pthread_attr_getstackaddr");
347 kludged("pthread_attr_getstackaddr");
348 if (stackaddr)
349 *stackaddr = NULL;
350 return 0;
351}
352
353/* Not bogus (!) */
354int pthread_attr_getstacksize ( const pthread_attr_t * _attr,
355 size_t * __stacksize )
356{
357 size_t limit;
358 ensure_valgrind("pthread_attr_getstacksize");
359 limit = VG_PTHREAD_STACK_SIZE - VG_AR_CLIENT_STACKBASE_REDZONE_SZB
360 - 1000; /* paranoia */
361 if (__stacksize)
362 *__stacksize = limit;
363 return 0;
364}
365
sewardj20917d82002-05-28 01:36:45 +0000366/* ---------------------------------------------------
367 Helper functions for running a thread
368 and for clearing up afterwards.
369 ------------------------------------------------ */
370
371/* All exiting threads eventually pass through here, bearing the
372 return value, or PTHREAD_CANCELED, in ret_val. */
373static
374__attribute__((noreturn))
375void thread_exit_wrapper ( void* ret_val )
376{
sewardj870497a2002-05-29 01:06:47 +0000377 int detached, res;
378 CleanupEntry cu;
379 pthread_key_t key;
380
sewardj20917d82002-05-28 01:36:45 +0000381 /* Run this thread's cleanup handlers. */
sewardj8ad94e12002-05-29 00:10:20 +0000382 while (1) {
383 VALGRIND_MAGIC_SEQUENCE(res, (-1) /* default */,
384 VG_USERREQ__CLEANUP_POP,
385 &cu, 0, 0, 0);
386 if (res == -1) break; /* stack empty */
sewardj2d94c112002-06-03 01:25:54 +0000387 my_assert(res == 0);
sewardj8ad94e12002-05-29 00:10:20 +0000388 if (0) printf("running exit cleanup handler");
389 cu.fn ( cu.arg );
390 }
391
sewardj870497a2002-05-29 01:06:47 +0000392 /* Run this thread's key finalizers. Really this should be run
393 PTHREAD_DESTRUCTOR_ITERATIONS times. */
394 for (key = 0; key < VG_N_THREAD_KEYS; key++) {
395 VALGRIND_MAGIC_SEQUENCE(res, (-2) /* default */,
396 VG_USERREQ__GET_KEY_D_AND_S,
397 key, &cu, 0, 0 );
398 if (res == 0) {
399 /* valid key */
400 if (cu.fn && cu.arg)
401 cu.fn /* destructor for key */
402 ( cu.arg /* specific for key for this thread */ );
403 continue;
404 }
sewardj2d94c112002-06-03 01:25:54 +0000405 my_assert(res == -1);
sewardj870497a2002-05-29 01:06:47 +0000406 }
sewardj20917d82002-05-28 01:36:45 +0000407
408 /* Decide on my final disposition. */
409 VALGRIND_MAGIC_SEQUENCE(detached, (-1) /* default */,
410 VG_USERREQ__SET_OR_GET_DETACH,
sewardj7989d0c2002-05-28 11:00:01 +0000411 2 /* get */, pthread_self(), 0, 0);
sewardj2d94c112002-06-03 01:25:54 +0000412 my_assert(detached == 0 || detached == 1);
sewardj20917d82002-05-28 01:36:45 +0000413
414 if (detached) {
415 /* Detached; I just quit right now. */
416 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
417 VG_USERREQ__QUIT, 0, 0, 0, 0);
418 } else {
419 /* Not detached; so I wait for a joiner. */
420 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
421 VG_USERREQ__WAIT_JOINER, ret_val, 0, 0, 0);
422 }
423 /* NOTREACHED */
424 barf("thread_exit_wrapper: still alive?!");
425}
426
427
428/* This function is a wrapper function for running a thread. It runs
429 the root function specified in pthread_create, and then, should the
430 root function return a value, it arranges to run the thread's
431 cleanup handlers and exit correctly. */
432
433/* Struct used to convey info from pthread_create to
434 thread_wrapper. */
435typedef
436 struct {
437 pthread_attr_t* attr;
438 void* (*root_fn) ( void* );
439 void* arg;
440 }
441 NewThreadInfo;
442
443
444/* This is passed to the VG_USERREQ__APPLY_IN_NEW_THREAD and so must
445 not return. Note that this runs in the new thread, not the
446 parent. */
447static
448__attribute__((noreturn))
449void thread_wrapper ( NewThreadInfo* info )
450{
451 int res;
452 pthread_attr_t* attr;
453 void* (*root_fn) ( void* );
454 void* arg;
455 void* ret_val;
456
457 attr = info->attr;
458 root_fn = info->root_fn;
459 arg = info->arg;
460
sewardj20917d82002-05-28 01:36:45 +0000461 /* Free up the arg block that pthread_create malloced. */
462 VALGRIND_MAGIC_SEQUENCE(res, (-1) /* default */,
463 VG_USERREQ__FREE, info, 0, 0, 0);
sewardj2d94c112002-06-03 01:25:54 +0000464 my_assert(res == 0);
sewardj20917d82002-05-28 01:36:45 +0000465
sewardj7989d0c2002-05-28 11:00:01 +0000466 /* Minimally observe the attributes supplied. */
467 if (attr) {
sewardj2d94c112002-06-03 01:25:54 +0000468 my_assert(attr->__detachstate == PTHREAD_CREATE_DETACHED
sewardj7989d0c2002-05-28 11:00:01 +0000469 || attr->__detachstate == PTHREAD_CREATE_JOINABLE);
470 if (attr->__detachstate == PTHREAD_CREATE_DETACHED)
471 pthread_detach(pthread_self());
472 }
473
sewardj20917d82002-05-28 01:36:45 +0000474 /* The root function might not return. But if it does we simply
475 move along to thread_exit_wrapper. All other ways out for the
476 thread (cancellation, or calling pthread_exit) lead there
477 too. */
478 ret_val = root_fn(arg);
479 thread_exit_wrapper(ret_val);
480 /* NOTREACHED */
481}
482
483
sewardjf8f819e2002-04-17 23:21:37 +0000484/* ---------------------------------------------------
485 THREADs
486 ------------------------------------------------ */
487
sewardjff42d1d2002-05-22 13:17:31 +0000488__attribute__((weak))
489int pthread_yield ( void )
490{
491 int res;
492 ensure_valgrind("pthread_yield");
493 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
494 VG_USERREQ__PTHREAD_YIELD, 0, 0, 0, 0);
495 return 0;
496}
497
498
sewardj6072c362002-04-19 14:40:57 +0000499int pthread_equal(pthread_t thread1, pthread_t thread2)
500{
501 return thread1 == thread2 ? 1 : 0;
502}
503
504
sewardj20917d82002-05-28 01:36:45 +0000505/* Bundle up the args into a malloc'd block and create a new thread
506 consisting of thread_wrapper() applied to said malloc'd block. */
sewardje663cb92002-04-12 10:26:32 +0000507int
508pthread_create (pthread_t *__restrict __thread,
509 __const pthread_attr_t *__restrict __attr,
510 void *(*__start_routine) (void *),
511 void *__restrict __arg)
512{
sewardj20917d82002-05-28 01:36:45 +0000513 int tid_child;
514 NewThreadInfo* info;
sewardje663cb92002-04-12 10:26:32 +0000515
sewardj20917d82002-05-28 01:36:45 +0000516 ensure_valgrind("pthread_create");
517
518 /* Allocate space for the arg block. thread_wrapper will free
519 it. */
520 VALGRIND_MAGIC_SEQUENCE(info, NULL /* default */,
521 VG_USERREQ__MALLOC,
522 sizeof(NewThreadInfo), 0, 0, 0);
sewardj2d94c112002-06-03 01:25:54 +0000523 my_assert(info != NULL);
sewardj20917d82002-05-28 01:36:45 +0000524
525 info->attr = (pthread_attr_t*)__attr;
526 info->root_fn = __start_routine;
527 info->arg = __arg;
528 VALGRIND_MAGIC_SEQUENCE(tid_child, VG_INVALID_THREADID /* default */,
529 VG_USERREQ__APPLY_IN_NEW_THREAD,
530 &thread_wrapper, info, 0, 0);
sewardj2d94c112002-06-03 01:25:54 +0000531 my_assert(tid_child != VG_INVALID_THREADID);
sewardj20917d82002-05-28 01:36:45 +0000532
533 if (__thread)
534 *__thread = tid_child;
535 return 0; /* success */
536}
sewardje663cb92002-04-12 10:26:32 +0000537
538
539int
540pthread_join (pthread_t __th, void **__thread_return)
541{
542 int res;
543 ensure_valgrind("pthread_join");
544 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
545 VG_USERREQ__PTHREAD_JOIN,
546 __th, __thread_return, 0, 0);
547 return res;
548}
549
550
sewardj3b5d8862002-04-20 13:53:23 +0000551void pthread_exit(void *retval)
552{
sewardj3b5d8862002-04-20 13:53:23 +0000553 ensure_valgrind("pthread_exit");
sewardj20917d82002-05-28 01:36:45 +0000554 /* Simple! */
555 thread_exit_wrapper(retval);
sewardj3b5d8862002-04-20 13:53:23 +0000556}
557
sewardje663cb92002-04-12 10:26:32 +0000558
sewardj3b13f0e2002-04-25 20:17:29 +0000559pthread_t pthread_self(void)
sewardje663cb92002-04-12 10:26:32 +0000560{
561 int tid;
sewardj3b13f0e2002-04-25 20:17:29 +0000562 ensure_valgrind("pthread_self");
sewardj439d45e2002-05-03 20:43:10 +0000563 VALGRIND_MAGIC_SEQUENCE(tid, 1 /* default */,
sewardje663cb92002-04-12 10:26:32 +0000564 VG_USERREQ__PTHREAD_GET_THREADID,
565 0, 0, 0, 0);
sewardj439d45e2002-05-03 20:43:10 +0000566 if (tid < 1 || tid >= VG_N_THREADS)
sewardj3b13f0e2002-04-25 20:17:29 +0000567 barf("pthread_self: invalid ThreadId");
568 return tid;
sewardje663cb92002-04-12 10:26:32 +0000569}
570
571
sewardj853f55d2002-04-26 00:27:53 +0000572int pthread_detach(pthread_t th)
573{
sewardj20917d82002-05-28 01:36:45 +0000574 int res;
575 ensure_valgrind("pthread_detach");
sewardj7989d0c2002-05-28 11:00:01 +0000576 /* First we enquire as to the current detach state. */
577 VALGRIND_MAGIC_SEQUENCE(res, (-2) /* default */,
sewardj20917d82002-05-28 01:36:45 +0000578 VG_USERREQ__SET_OR_GET_DETACH,
sewardj7989d0c2002-05-28 11:00:01 +0000579 2 /* get */, th, 0, 0);
580 if (res == -1) /* not found */
581 return ESRCH;
582 if (res == 1) /* already detached */
583 return EINVAL;
584 if (res == 0) {
585 VALGRIND_MAGIC_SEQUENCE(res, (-2) /* default */,
586 VG_USERREQ__SET_OR_GET_DETACH,
587 1 /* set */, th, 0, 0);
sewardj2d94c112002-06-03 01:25:54 +0000588 my_assert(res == 0);
sewardj7989d0c2002-05-28 11:00:01 +0000589 return 0;
590 }
591 barf("pthread_detach");
sewardj853f55d2002-04-26 00:27:53 +0000592}
593
594
sewardjf8f819e2002-04-17 23:21:37 +0000595/* ---------------------------------------------------
sewardj8ad94e12002-05-29 00:10:20 +0000596 CLEANUP STACKS
597 ------------------------------------------------ */
598
599void _pthread_cleanup_push (struct _pthread_cleanup_buffer *__buffer,
600 void (*__routine) (void *),
601 void *__arg)
602{
603 int res;
604 CleanupEntry cu;
605 ensure_valgrind("_pthread_cleanup_push");
606 cu.fn = __routine;
607 cu.arg = __arg;
608 VALGRIND_MAGIC_SEQUENCE(res, (-1) /* default */,
609 VG_USERREQ__CLEANUP_PUSH,
610 &cu, 0, 0, 0);
sewardj2d94c112002-06-03 01:25:54 +0000611 my_assert(res == 0);
sewardj8ad94e12002-05-29 00:10:20 +0000612}
613
614
615void _pthread_cleanup_push_defer (struct _pthread_cleanup_buffer *__buffer,
616 void (*__routine) (void *),
617 void *__arg)
618{
619 /* As _pthread_cleanup_push, but first save the thread's original
620 cancellation type in __buffer and set it to Deferred. */
621 int orig_ctype;
622 ensure_valgrind("_pthread_cleanup_push_defer");
623 /* Set to Deferred, and put the old cancellation type in res. */
sewardj2d94c112002-06-03 01:25:54 +0000624 my_assert(-1 != PTHREAD_CANCEL_DEFERRED);
625 my_assert(-1 != PTHREAD_CANCEL_ASYNCHRONOUS);
626 my_assert(sizeof(struct _pthread_cleanup_buffer) >= sizeof(int));
sewardj8ad94e12002-05-29 00:10:20 +0000627 VALGRIND_MAGIC_SEQUENCE(orig_ctype, (-1) /* default */,
628 VG_USERREQ__SET_CANCELTYPE,
629 PTHREAD_CANCEL_DEFERRED, 0, 0, 0);
sewardj2d94c112002-06-03 01:25:54 +0000630 my_assert(orig_ctype != -1);
sewardj8ad94e12002-05-29 00:10:20 +0000631 *((int*)(__buffer)) = orig_ctype;
632 /* Now push the cleanup. */
633 _pthread_cleanup_push(NULL, __routine, __arg);
634}
635
636
637void _pthread_cleanup_pop (struct _pthread_cleanup_buffer *__buffer,
638 int __execute)
639{
640 int res;
641 CleanupEntry cu;
642 ensure_valgrind("_pthread_cleanup_push");
643 cu.fn = cu.arg = NULL; /* paranoia */
644 VALGRIND_MAGIC_SEQUENCE(res, (-1) /* default */,
645 VG_USERREQ__CLEANUP_POP,
646 &cu, 0, 0, 0);
647 if (res == 0) {
648 /* pop succeeded */
649 if (__execute) {
650 cu.fn ( cu.arg );
651 }
652 return;
653 }
654 if (res == -1) {
655 /* stack underflow */
656 return;
657 }
658 barf("_pthread_cleanup_pop");
659}
660
661
662void _pthread_cleanup_pop_restore (struct _pthread_cleanup_buffer *__buffer,
663 int __execute)
664{
665 int orig_ctype, fake_ctype;
666 /* As _pthread_cleanup_pop, but after popping/running the handler,
667 restore the thread's original cancellation type from the first
668 word of __buffer. */
669 _pthread_cleanup_pop(NULL, __execute);
670 orig_ctype = *((int*)(__buffer));
sewardj2d94c112002-06-03 01:25:54 +0000671 my_assert(orig_ctype == PTHREAD_CANCEL_DEFERRED
sewardj8ad94e12002-05-29 00:10:20 +0000672 || orig_ctype == PTHREAD_CANCEL_ASYNCHRONOUS);
sewardj2d94c112002-06-03 01:25:54 +0000673 my_assert(-1 != PTHREAD_CANCEL_DEFERRED);
674 my_assert(-1 != PTHREAD_CANCEL_ASYNCHRONOUS);
675 my_assert(sizeof(struct _pthread_cleanup_buffer) >= sizeof(int));
sewardj8ad94e12002-05-29 00:10:20 +0000676 VALGRIND_MAGIC_SEQUENCE(fake_ctype, (-1) /* default */,
677 VG_USERREQ__SET_CANCELTYPE,
678 orig_ctype, 0, 0, 0);
sewardj2d94c112002-06-03 01:25:54 +0000679 my_assert(fake_ctype == PTHREAD_CANCEL_DEFERRED);
sewardj8ad94e12002-05-29 00:10:20 +0000680}
681
682
683/* ---------------------------------------------------
sewardjf8f819e2002-04-17 23:21:37 +0000684 MUTEX ATTRIBUTES
685 ------------------------------------------------ */
686
sewardj5905fae2002-04-26 13:25:00 +0000687int __pthread_mutexattr_init(pthread_mutexattr_t *attr)
sewardje663cb92002-04-12 10:26:32 +0000688{
sewardjf8f819e2002-04-17 23:21:37 +0000689 attr->__mutexkind = PTHREAD_MUTEX_ERRORCHECK_NP;
sewardj8937c812002-04-12 20:12:20 +0000690 return 0;
sewardje663cb92002-04-12 10:26:32 +0000691}
692
sewardj5905fae2002-04-26 13:25:00 +0000693int __pthread_mutexattr_settype(pthread_mutexattr_t *attr, int type)
sewardjf8f819e2002-04-17 23:21:37 +0000694{
695 switch (type) {
sewardj3b13f0e2002-04-25 20:17:29 +0000696# ifndef GLIBC_2_1
sewardjf8f819e2002-04-17 23:21:37 +0000697 case PTHREAD_MUTEX_TIMED_NP:
sewardj2a1dcce2002-04-22 12:45:25 +0000698 case PTHREAD_MUTEX_ADAPTIVE_NP:
sewardj3b13f0e2002-04-25 20:17:29 +0000699# endif
sewardja1679dd2002-05-10 22:31:40 +0000700# ifdef GLIBC_2_1
sewardj68b2dd92002-05-10 21:03:56 +0000701 case PTHREAD_MUTEX_FAST_NP:
sewardja1679dd2002-05-10 22:31:40 +0000702# endif
sewardjf8f819e2002-04-17 23:21:37 +0000703 case PTHREAD_MUTEX_RECURSIVE_NP:
704 case PTHREAD_MUTEX_ERRORCHECK_NP:
sewardjf8f819e2002-04-17 23:21:37 +0000705 attr->__mutexkind = type;
706 return 0;
707 default:
708 return EINVAL;
709 }
710}
711
sewardj5905fae2002-04-26 13:25:00 +0000712int __pthread_mutexattr_destroy(pthread_mutexattr_t *attr)
sewardjf8f819e2002-04-17 23:21:37 +0000713{
714 return 0;
715}
716
717
718/* ---------------------------------------------------
719 MUTEXes
720 ------------------------------------------------ */
721
sewardj5905fae2002-04-26 13:25:00 +0000722int __pthread_mutex_init(pthread_mutex_t *mutex,
723 const pthread_mutexattr_t *mutexattr)
sewardje663cb92002-04-12 10:26:32 +0000724{
sewardj604ec3c2002-04-18 22:38:41 +0000725 mutex->__m_count = 0;
726 mutex->__m_owner = (_pthread_descr)VG_INVALID_THREADID;
727 mutex->__m_kind = PTHREAD_MUTEX_ERRORCHECK_NP;
728 if (mutexattr)
729 mutex->__m_kind = mutexattr->__mutexkind;
730 return 0;
sewardje663cb92002-04-12 10:26:32 +0000731}
732
sewardj439d45e2002-05-03 20:43:10 +0000733
sewardj5905fae2002-04-26 13:25:00 +0000734int __pthread_mutex_lock(pthread_mutex_t *mutex)
sewardje663cb92002-04-12 10:26:32 +0000735{
736 int res;
sewardj436e0582002-04-26 14:31:40 +0000737 static int moans = N_MOANS;
sewardj439d45e2002-05-03 20:43:10 +0000738 if (RUNNING_ON_VALGRIND) {
sewardje663cb92002-04-12 10:26:32 +0000739 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
740 VG_USERREQ__PTHREAD_MUTEX_LOCK,
741 mutex, 0, 0, 0);
742 return res;
sewardj439d45e2002-05-03 20:43:10 +0000743 } else {
744 if (moans-- > 0)
745 not_inside("pthread_mutex_lock");
746 return 0; /* success */
sewardje663cb92002-04-12 10:26:32 +0000747 }
748}
749
sewardj439d45e2002-05-03 20:43:10 +0000750
sewardj5905fae2002-04-26 13:25:00 +0000751int __pthread_mutex_trylock(pthread_mutex_t *mutex)
sewardj30671ff2002-04-21 00:13:57 +0000752{
753 int res;
sewardj436e0582002-04-26 14:31:40 +0000754 static int moans = N_MOANS;
sewardj439d45e2002-05-03 20:43:10 +0000755 if (RUNNING_ON_VALGRIND) {
sewardj30671ff2002-04-21 00:13:57 +0000756 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
757 VG_USERREQ__PTHREAD_MUTEX_TRYLOCK,
758 mutex, 0, 0, 0);
759 return res;
sewardj439d45e2002-05-03 20:43:10 +0000760 } else {
761 if (moans-- > 0)
762 not_inside("pthread_mutex_trylock");
763 return 0;
sewardj30671ff2002-04-21 00:13:57 +0000764 }
765}
766
sewardj439d45e2002-05-03 20:43:10 +0000767
sewardj5905fae2002-04-26 13:25:00 +0000768int __pthread_mutex_unlock(pthread_mutex_t *mutex)
sewardje663cb92002-04-12 10:26:32 +0000769{
770 int res;
sewardj436e0582002-04-26 14:31:40 +0000771 static int moans = N_MOANS;
sewardj439d45e2002-05-03 20:43:10 +0000772 if (RUNNING_ON_VALGRIND) {
sewardje663cb92002-04-12 10:26:32 +0000773 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
774 VG_USERREQ__PTHREAD_MUTEX_UNLOCK,
775 mutex, 0, 0, 0);
776 return res;
sewardj439d45e2002-05-03 20:43:10 +0000777 } else {
778 if (moans-- > 0)
779 not_inside("pthread_mutex_unlock");
780 return 0;
sewardje663cb92002-04-12 10:26:32 +0000781 }
782}
783
sewardj439d45e2002-05-03 20:43:10 +0000784
sewardj5905fae2002-04-26 13:25:00 +0000785int __pthread_mutex_destroy(pthread_mutex_t *mutex)
sewardje663cb92002-04-12 10:26:32 +0000786{
sewardj604ec3c2002-04-18 22:38:41 +0000787 /* Valgrind doesn't hold any resources on behalf of the mutex, so no
788 need to involve it. */
789 if (mutex->__m_count > 0)
790 return EBUSY;
sewardj6072c362002-04-19 14:40:57 +0000791 mutex->__m_count = 0;
792 mutex->__m_owner = (_pthread_descr)VG_INVALID_THREADID;
793 mutex->__m_kind = PTHREAD_MUTEX_ERRORCHECK_NP;
sewardj604ec3c2002-04-18 22:38:41 +0000794 return 0;
sewardje663cb92002-04-12 10:26:32 +0000795}
796
797
sewardjf8f819e2002-04-17 23:21:37 +0000798/* ---------------------------------------------------
sewardj6072c362002-04-19 14:40:57 +0000799 CONDITION VARIABLES
800 ------------------------------------------------ */
801
802/* LinuxThreads supports no attributes for conditions. Hence ... */
803
804int pthread_condattr_init(pthread_condattr_t *attr)
805{
806 return 0;
807}
808
sewardj0738a592002-04-20 13:59:33 +0000809int pthread_condattr_destroy(pthread_condattr_t *attr)
810{
811 return 0;
812}
sewardj6072c362002-04-19 14:40:57 +0000813
814int pthread_cond_init( pthread_cond_t *cond,
815 const pthread_condattr_t *cond_attr)
816{
817 cond->__c_waiting = (_pthread_descr)VG_INVALID_THREADID;
818 return 0;
819}
820
sewardjf854f472002-04-21 12:19:41 +0000821int pthread_cond_destroy(pthread_cond_t *cond)
822{
823 /* should check that no threads are waiting on this CV */
sewardj436e0582002-04-26 14:31:40 +0000824 static int moans = N_MOANS;
825 if (moans-- > 0)
826 kludged("pthread_cond_destroy");
sewardjf854f472002-04-21 12:19:41 +0000827 return 0;
828}
sewardj6072c362002-04-19 14:40:57 +0000829
830/* ---------------------------------------------------
831 SCHEDULING
832 ------------------------------------------------ */
833
834/* This is completely bogus. */
835int pthread_getschedparam(pthread_t target_thread,
836 int *policy,
837 struct sched_param *param)
838{
sewardj436e0582002-04-26 14:31:40 +0000839 static int moans = N_MOANS;
840 if (moans-- > 0)
841 kludged("pthread_getschedparam");
sewardj6072c362002-04-19 14:40:57 +0000842 if (policy) *policy = SCHED_OTHER;
sewardj3e909ce2002-06-03 13:27:15 +0000843# ifdef HAVE_SCHED_PRIORITY
sewardj2a1dcce2002-04-22 12:45:25 +0000844 if (param) param->sched_priority = 0; /* who knows */
845# else
sewardj6072c362002-04-19 14:40:57 +0000846 if (param) param->__sched_priority = 0; /* who knows */
sewardj2a1dcce2002-04-22 12:45:25 +0000847# endif
sewardj6072c362002-04-19 14:40:57 +0000848 return 0;
849}
850
851int pthread_setschedparam(pthread_t target_thread,
852 int policy,
853 const struct sched_param *param)
854{
sewardj436e0582002-04-26 14:31:40 +0000855 static int moans = N_MOANS;
856 if (moans-- > 0)
857 ignored("pthread_setschedparam");
sewardj6072c362002-04-19 14:40:57 +0000858 return 0;
859}
860
sewardj3b5d8862002-04-20 13:53:23 +0000861int pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex)
862{
863 int res;
864 ensure_valgrind("pthread_cond_wait");
865 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
866 VG_USERREQ__PTHREAD_COND_WAIT,
867 cond, mutex, 0, 0);
868 return res;
869}
870
sewardj5f07b662002-04-23 16:52:51 +0000871int pthread_cond_timedwait ( pthread_cond_t *cond,
872 pthread_mutex_t *mutex,
873 const struct timespec *abstime )
874{
875 int res;
876 unsigned int ms_now, ms_end;
877 struct timeval timeval_now;
878 unsigned long long int ull_ms_now_after_1970;
879 unsigned long long int ull_ms_end_after_1970;
880
881 ensure_valgrind("pthread_cond_timedwait");
882 VALGRIND_MAGIC_SEQUENCE(ms_now, 0xFFFFFFFF /* default */,
883 VG_USERREQ__READ_MILLISECOND_TIMER,
884 0, 0, 0, 0);
sewardj2d94c112002-06-03 01:25:54 +0000885 my_assert(ms_now != 0xFFFFFFFF);
sewardj5f07b662002-04-23 16:52:51 +0000886 res = gettimeofday(&timeval_now, NULL);
sewardj2d94c112002-06-03 01:25:54 +0000887 my_assert(res == 0);
sewardj5f07b662002-04-23 16:52:51 +0000888
889 ull_ms_now_after_1970
890 = 1000ULL * ((unsigned long long int)(timeval_now.tv_sec))
891 + ((unsigned long long int)(timeval_now.tv_usec / 1000000));
892 ull_ms_end_after_1970
893 = 1000ULL * ((unsigned long long int)(abstime->tv_sec))
894 + ((unsigned long long int)(abstime->tv_nsec / 1000000));
sewardjd8e919e2002-05-29 20:13:53 +0000895 if (ull_ms_end_after_1970 < ull_ms_now_after_1970)
896 ull_ms_end_after_1970 = ull_ms_now_after_1970;
sewardj5f07b662002-04-23 16:52:51 +0000897 ms_end
898 = ms_now + (unsigned int)(ull_ms_end_after_1970 - ull_ms_now_after_1970);
899 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
900 VG_USERREQ__PTHREAD_COND_TIMEDWAIT,
901 cond, mutex, ms_end, 0);
902 return res;
903}
904
905
sewardj3b5d8862002-04-20 13:53:23 +0000906int pthread_cond_signal(pthread_cond_t *cond)
907{
908 int res;
909 ensure_valgrind("pthread_cond_signal");
910 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
911 VG_USERREQ__PTHREAD_COND_SIGNAL,
912 cond, 0, 0, 0);
913 return res;
914}
915
916int pthread_cond_broadcast(pthread_cond_t *cond)
917{
918 int res;
919 ensure_valgrind("pthread_cond_broadcast");
920 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
921 VG_USERREQ__PTHREAD_COND_BROADCAST,
922 cond, 0, 0, 0);
923 return res;
924}
925
sewardj6072c362002-04-19 14:40:57 +0000926
927/* ---------------------------------------------------
sewardjf8f819e2002-04-17 23:21:37 +0000928 CANCELLATION
929 ------------------------------------------------ */
930
sewardj853f55d2002-04-26 00:27:53 +0000931int pthread_setcancelstate(int state, int *oldstate)
932{
sewardj20917d82002-05-28 01:36:45 +0000933 int res;
934 ensure_valgrind("pthread_setcancelstate");
935 if (state != PTHREAD_CANCEL_ENABLE
936 && state != PTHREAD_CANCEL_DISABLE)
937 return EINVAL;
sewardj2d94c112002-06-03 01:25:54 +0000938 my_assert(-1 != PTHREAD_CANCEL_ENABLE);
939 my_assert(-1 != PTHREAD_CANCEL_DISABLE);
sewardj20917d82002-05-28 01:36:45 +0000940 VALGRIND_MAGIC_SEQUENCE(res, (-1) /* default */,
941 VG_USERREQ__SET_CANCELSTATE,
942 state, 0, 0, 0);
sewardj2d94c112002-06-03 01:25:54 +0000943 my_assert(res != -1);
sewardj20917d82002-05-28 01:36:45 +0000944 if (oldstate)
945 *oldstate = res;
sewardj853f55d2002-04-26 00:27:53 +0000946 return 0;
947}
948
sewardje663cb92002-04-12 10:26:32 +0000949int pthread_setcanceltype(int type, int *oldtype)
950{
sewardj20917d82002-05-28 01:36:45 +0000951 int res;
952 ensure_valgrind("pthread_setcanceltype");
953 if (type != PTHREAD_CANCEL_DEFERRED
954 && type != PTHREAD_CANCEL_ASYNCHRONOUS)
955 return EINVAL;
sewardj2d94c112002-06-03 01:25:54 +0000956 my_assert(-1 != PTHREAD_CANCEL_DEFERRED);
957 my_assert(-1 != PTHREAD_CANCEL_ASYNCHRONOUS);
sewardj20917d82002-05-28 01:36:45 +0000958 VALGRIND_MAGIC_SEQUENCE(res, (-1) /* default */,
959 VG_USERREQ__SET_CANCELTYPE,
960 type, 0, 0, 0);
sewardj2d94c112002-06-03 01:25:54 +0000961 my_assert(res != -1);
sewardj20917d82002-05-28 01:36:45 +0000962 if (oldtype)
963 *oldtype = res;
sewardje663cb92002-04-12 10:26:32 +0000964 return 0;
965}
966
sewardje663cb92002-04-12 10:26:32 +0000967int pthread_cancel(pthread_t thread)
968{
969 int res;
970 ensure_valgrind("pthread_cancel");
sewardj20917d82002-05-28 01:36:45 +0000971 VALGRIND_MAGIC_SEQUENCE(res, (-1) /* default */,
972 VG_USERREQ__SET_CANCELPEND,
973 thread, &thread_exit_wrapper, 0, 0);
sewardj2d94c112002-06-03 01:25:54 +0000974 my_assert(res != -1);
sewardje663cb92002-04-12 10:26:32 +0000975 return res;
976}
977
sewardjd140e442002-05-29 01:21:19 +0000978static __inline__
979void __my_pthread_testcancel(void)
sewardj853f55d2002-04-26 00:27:53 +0000980{
sewardj20917d82002-05-28 01:36:45 +0000981 int res;
982 VALGRIND_MAGIC_SEQUENCE(res, (-1) /* default */,
983 VG_USERREQ__TESTCANCEL,
984 0, 0, 0, 0);
sewardj2d94c112002-06-03 01:25:54 +0000985 my_assert(res == 0);
sewardj853f55d2002-04-26 00:27:53 +0000986}
987
sewardjd140e442002-05-29 01:21:19 +0000988void pthread_testcancel ( void )
989{
990 __my_pthread_testcancel();
991}
992
sewardj20917d82002-05-28 01:36:45 +0000993
sewardjef037c72002-05-30 00:40:03 +0000994/* Not really sure what this is for. I suspect for doing the POSIX
995 requirements for fork() and exec(). We do this internally anyway
996 whenever those syscalls are observed, so this could be superfluous,
997 but hey ...
998*/
sewardj853f55d2002-04-26 00:27:53 +0000999void __pthread_kill_other_threads_np ( void )
1000{
sewardjef037c72002-05-30 00:40:03 +00001001 int res;
1002 ensure_valgrind("__pthread_kill_other_threads_np");
1003 VALGRIND_MAGIC_SEQUENCE(res, (-1) /* default */,
1004 VG_USERREQ__NUKE_OTHER_THREADS,
1005 0, 0, 0, 0);
sewardj2d94c112002-06-03 01:25:54 +00001006 my_assert(res == 0);
sewardj853f55d2002-04-26 00:27:53 +00001007}
1008
sewardje663cb92002-04-12 10:26:32 +00001009
sewardjf8f819e2002-04-17 23:21:37 +00001010/* ---------------------------------------------------
sewardjb48e5002002-05-13 00:16:03 +00001011 SIGNALS
1012 ------------------------------------------------ */
1013
1014#include <signal.h>
1015
1016int pthread_sigmask(int how, const sigset_t *newmask,
1017 sigset_t *oldmask)
1018{
1019 int res;
1020
1021 /* A bit subtle, because the scheduler expects newmask and oldmask
1022 to be vki_sigset_t* rather than sigset_t*, and the two are
1023 different. Fortunately the first 64 bits of a sigset_t are
1024 exactly a vki_sigset_t, so we just pass the pointers through
1025 unmodified. Haaaack!
1026
1027 Also mash the how value so that the SIG_ constants from glibc
sewardj018f7622002-05-15 21:13:39 +00001028 constants to VKI_ constants, so that the former do not have to
1029 be included into vg_scheduler.c. */
sewardjb48e5002002-05-13 00:16:03 +00001030
1031 ensure_valgrind("pthread_sigmask");
1032
1033 switch (how) {
sewardj018f7622002-05-15 21:13:39 +00001034 case SIG_SETMASK: how = VKI_SIG_SETMASK; break;
1035 case SIG_BLOCK: how = VKI_SIG_BLOCK; break;
1036 case SIG_UNBLOCK: how = VKI_SIG_UNBLOCK; break;
sewardjb48e5002002-05-13 00:16:03 +00001037 default: return EINVAL;
1038 }
1039
1040 /* Crude check */
1041 if (newmask == NULL)
1042 return EFAULT;
1043
1044 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
1045 VG_USERREQ__PTHREAD_SIGMASK,
1046 how, newmask, oldmask, 0);
1047
1048 /* The scheduler tells us of any memory violations. */
1049 return res == 0 ? 0 : EFAULT;
1050}
1051
1052
1053int sigwait ( const sigset_t* set, int* sig )
1054{
1055 int res;
1056 ensure_valgrind("sigwait");
1057 /* As with pthread_sigmask we deliberately confuse sigset_t with
1058 vki_ksigset_t. */
1059 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
1060 VG_USERREQ__SIGWAIT,
1061 set, sig, 0, 0);
1062 return res;
1063}
1064
1065
sewardj018f7622002-05-15 21:13:39 +00001066int pthread_kill(pthread_t thread, int signo)
1067{
1068 int res;
1069 ensure_valgrind("pthread_kill");
1070 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
1071 VG_USERREQ__PTHREAD_KILL,
1072 thread, signo, 0, 0);
1073 return res;
1074}
1075
1076
sewardj3665ded2002-05-16 16:57:25 +00001077/* Copied verbatim from Linuxthreads */
1078/* Redefine raise() to send signal to calling thread only,
1079 as per POSIX 1003.1c */
1080int raise (int sig)
1081{
1082 int retcode = pthread_kill(pthread_self(), sig);
1083 if (retcode == 0)
1084 return 0;
1085 else {
1086 errno = retcode;
1087 return -1;
1088 }
1089}
1090
1091
sewardjb48e5002002-05-13 00:16:03 +00001092/* ---------------------------------------------------
sewardjf8f819e2002-04-17 23:21:37 +00001093 THREAD-SPECIFICs
1094 ------------------------------------------------ */
sewardj5e5fa512002-04-14 13:13:05 +00001095
sewardj5905fae2002-04-26 13:25:00 +00001096int __pthread_key_create(pthread_key_t *key,
1097 void (*destr_function) (void *))
sewardj5e5fa512002-04-14 13:13:05 +00001098{
sewardj5f07b662002-04-23 16:52:51 +00001099 int res;
1100 ensure_valgrind("pthread_key_create");
1101 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
1102 VG_USERREQ__PTHREAD_KEY_CREATE,
1103 key, destr_function, 0, 0);
1104 return res;
sewardj5e5fa512002-04-14 13:13:05 +00001105}
1106
1107int pthread_key_delete(pthread_key_t key)
1108{
sewardj436e0582002-04-26 14:31:40 +00001109 static int moans = N_MOANS;
1110 if (moans-- > 0)
1111 ignored("pthread_key_delete");
sewardj5e5fa512002-04-14 13:13:05 +00001112 return 0;
1113}
1114
sewardj5905fae2002-04-26 13:25:00 +00001115int __pthread_setspecific(pthread_key_t key, const void *pointer)
sewardj5e5fa512002-04-14 13:13:05 +00001116{
sewardj5f07b662002-04-23 16:52:51 +00001117 int res;
1118 ensure_valgrind("pthread_setspecific");
1119 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
1120 VG_USERREQ__PTHREAD_SETSPECIFIC,
1121 key, pointer, 0, 0);
1122 return res;
sewardj5e5fa512002-04-14 13:13:05 +00001123}
1124
sewardj5905fae2002-04-26 13:25:00 +00001125void * __pthread_getspecific(pthread_key_t key)
sewardj5e5fa512002-04-14 13:13:05 +00001126{
sewardj5f07b662002-04-23 16:52:51 +00001127 int res;
1128 ensure_valgrind("pthread_getspecific");
1129 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
1130 VG_USERREQ__PTHREAD_GETSPECIFIC,
1131 key, 0 , 0, 0);
1132 return (void*)res;
sewardj5e5fa512002-04-14 13:13:05 +00001133}
1134
sewardjf8f819e2002-04-17 23:21:37 +00001135
1136/* ---------------------------------------------------
sewardj89d3d852002-04-24 19:21:39 +00001137 ONCEry
1138 ------------------------------------------------ */
1139
1140static pthread_mutex_t once_masterlock = PTHREAD_MUTEX_INITIALIZER;
1141
1142
sewardj5905fae2002-04-26 13:25:00 +00001143int __pthread_once ( pthread_once_t *once_control,
1144 void (*init_routine) (void) )
sewardj89d3d852002-04-24 19:21:39 +00001145{
1146 int res;
1147 ensure_valgrind("pthread_once");
1148
sewardj68b2dd92002-05-10 21:03:56 +00001149 res = __pthread_mutex_lock(&once_masterlock);
sewardj89d3d852002-04-24 19:21:39 +00001150
sewardj68b2dd92002-05-10 21:03:56 +00001151 if (res != 0) {
1152 printf("res = %d\n",res);
sewardj89d3d852002-04-24 19:21:39 +00001153 barf("pthread_once: Looks like your program's "
1154 "init routine calls back to pthread_once() ?!");
sewardj68b2dd92002-05-10 21:03:56 +00001155 }
sewardj89d3d852002-04-24 19:21:39 +00001156
1157 if (*once_control == 0) {
1158 *once_control = 1;
1159 init_routine();
1160 }
1161
sewardj68b2dd92002-05-10 21:03:56 +00001162 __pthread_mutex_unlock(&once_masterlock);
sewardj89d3d852002-04-24 19:21:39 +00001163
1164 return 0;
1165}
1166
1167
1168/* ---------------------------------------------------
sewardj853f55d2002-04-26 00:27:53 +00001169 MISC
1170 ------------------------------------------------ */
1171
sewardj5905fae2002-04-26 13:25:00 +00001172int __pthread_atfork ( void (*prepare)(void),
1173 void (*parent)(void),
1174 void (*child)(void) )
sewardj853f55d2002-04-26 00:27:53 +00001175{
sewardjccef2e62002-05-29 19:26:32 +00001176 /* We have to do this properly or not at all; faking it isn't an
1177 option. */
1178 vgPlain_unimp("__pthread_atfork");
sewardj853f55d2002-04-26 00:27:53 +00001179}
1180
1181
sewardjbb990782002-05-08 02:01:14 +00001182__attribute__((weak))
1183void __pthread_initialize ( void )
1184{
sewardjbea1caa2002-05-10 23:20:58 +00001185 ensure_valgrind("__pthread_initialize");
sewardjbb990782002-05-08 02:01:14 +00001186}
1187
1188
sewardj853f55d2002-04-26 00:27:53 +00001189/* ---------------------------------------------------
sewardj3b13f0e2002-04-25 20:17:29 +00001190 LIBRARY-PRIVATE THREAD SPECIFIC STATE
sewardjf8f819e2002-04-17 23:21:37 +00001191 ------------------------------------------------ */
1192
sewardj3b13f0e2002-04-25 20:17:29 +00001193#include <resolv.h>
1194static int thread_specific_errno[VG_N_THREADS];
1195static int thread_specific_h_errno[VG_N_THREADS];
1196static struct __res_state
1197 thread_specific_res_state[VG_N_THREADS];
sewardjf8f819e2002-04-17 23:21:37 +00001198
sewardj3b13f0e2002-04-25 20:17:29 +00001199int* __errno_location ( void )
sewardjf8f819e2002-04-17 23:21:37 +00001200{
1201 int tid;
sewardj3b13f0e2002-04-25 20:17:29 +00001202 /* ensure_valgrind("__errno_location"); */
1203 VALGRIND_MAGIC_SEQUENCE(tid, 1 /* default */,
sewardjf8f819e2002-04-17 23:21:37 +00001204 VG_USERREQ__PTHREAD_GET_THREADID,
1205 0, 0, 0, 0);
sewardj3b13f0e2002-04-25 20:17:29 +00001206 /* 'cos I'm paranoid ... */
sewardj439d45e2002-05-03 20:43:10 +00001207 if (tid < 1 || tid >= VG_N_THREADS)
sewardj3b13f0e2002-04-25 20:17:29 +00001208 barf("__errno_location: invalid ThreadId");
1209 return & thread_specific_errno[tid];
1210}
1211
1212int* __h_errno_location ( void )
1213{
1214 int tid;
1215 /* ensure_valgrind("__h_errno_location"); */
1216 VALGRIND_MAGIC_SEQUENCE(tid, 1 /* default */,
1217 VG_USERREQ__PTHREAD_GET_THREADID,
1218 0, 0, 0, 0);
1219 /* 'cos I'm paranoid ... */
sewardj439d45e2002-05-03 20:43:10 +00001220 if (tid < 1 || tid >= VG_N_THREADS)
sewardj3b13f0e2002-04-25 20:17:29 +00001221 barf("__h_errno_location: invalid ThreadId");
1222 return & thread_specific_h_errno[tid];
1223}
1224
1225struct __res_state* __res_state ( void )
1226{
1227 int tid;
1228 /* ensure_valgrind("__res_state"); */
1229 VALGRIND_MAGIC_SEQUENCE(tid, 1 /* default */,
1230 VG_USERREQ__PTHREAD_GET_THREADID,
1231 0, 0, 0, 0);
1232 /* 'cos I'm paranoid ... */
sewardj439d45e2002-05-03 20:43:10 +00001233 if (tid < 1 || tid >= VG_N_THREADS)
sewardj3b13f0e2002-04-25 20:17:29 +00001234 barf("__res_state: invalid ThreadId");
1235 return & thread_specific_res_state[tid];
sewardjf8f819e2002-04-17 23:21:37 +00001236}
1237
1238
sewardj5716dbb2002-04-26 03:28:18 +00001239/* ---------------------------------------------------
1240 LIBC-PRIVATE SPECIFIC DATA
1241 ------------------------------------------------ */
1242
1243/* Relies on assumption that initial private data is NULL. This
1244 should be fixed somehow. */
1245
1246/* The allowable keys (indices) (all 2 of them).
1247 From sysdeps/pthread/bits/libc-tsd.h
1248*/
sewardj70adeb22002-04-27 01:35:38 +00001249#define N_LIBC_TSD_EXTRA_KEYS 1
1250
sewardj5716dbb2002-04-26 03:28:18 +00001251enum __libc_tsd_key_t { _LIBC_TSD_KEY_MALLOC = 0,
1252 _LIBC_TSD_KEY_DL_ERROR,
1253 _LIBC_TSD_KEY_N };
1254
1255/* Auto-initialising subsystem. libc_specifics_inited is set
1256 after initialisation. libc_specifics_inited_mx guards it. */
1257static int libc_specifics_inited = 0;
1258static pthread_mutex_t libc_specifics_inited_mx = PTHREAD_MUTEX_INITIALIZER;
1259
1260/* These are the keys we must initialise the first time. */
sewardj70adeb22002-04-27 01:35:38 +00001261static pthread_key_t libc_specifics_keys[_LIBC_TSD_KEY_N
1262 + N_LIBC_TSD_EXTRA_KEYS];
sewardj5716dbb2002-04-26 03:28:18 +00001263
1264/* Initialise the keys, if they are not already initialise. */
1265static
1266void init_libc_tsd_keys ( void )
1267{
1268 int res, i;
1269 pthread_key_t k;
1270
1271 res = pthread_mutex_lock(&libc_specifics_inited_mx);
1272 if (res != 0) barf("init_libc_tsd_keys: lock");
1273
1274 if (libc_specifics_inited == 0) {
1275 /* printf("INIT libc specifics\n"); */
1276 libc_specifics_inited = 1;
sewardj70adeb22002-04-27 01:35:38 +00001277 for (i = 0; i < _LIBC_TSD_KEY_N + N_LIBC_TSD_EXTRA_KEYS; i++) {
sewardj5716dbb2002-04-26 03:28:18 +00001278 res = pthread_key_create(&k, NULL);
1279 if (res != 0) barf("init_libc_tsd_keys: create");
1280 libc_specifics_keys[i] = k;
1281 }
1282 }
1283
1284 res = pthread_mutex_unlock(&libc_specifics_inited_mx);
1285 if (res != 0) barf("init_libc_tsd_keys: unlock");
1286}
1287
1288
1289static int
1290libc_internal_tsd_set ( enum __libc_tsd_key_t key,
1291 const void * pointer )
1292{
sewardj70adeb22002-04-27 01:35:38 +00001293 int res;
1294 static int moans = N_MOANS;
sewardj5716dbb2002-04-26 03:28:18 +00001295 /* printf("SET SET SET key %d ptr %p\n", key, pointer); */
sewardj70adeb22002-04-27 01:35:38 +00001296 if (key < _LIBC_TSD_KEY_MALLOC
1297 || key >= _LIBC_TSD_KEY_N + N_LIBC_TSD_EXTRA_KEYS)
sewardj5716dbb2002-04-26 03:28:18 +00001298 barf("libc_internal_tsd_set: invalid key");
sewardj70adeb22002-04-27 01:35:38 +00001299 if (key >= _LIBC_TSD_KEY_N && moans-- > 0)
1300 fprintf(stderr,
sewardj439d45e2002-05-03 20:43:10 +00001301 "valgrind's libpthread.so: libc_internal_tsd_set: "
1302 "dubious key %d\n", key);
sewardj5716dbb2002-04-26 03:28:18 +00001303 init_libc_tsd_keys();
1304 res = pthread_setspecific(libc_specifics_keys[key], pointer);
1305 if (res != 0) barf("libc_internal_tsd_set: setspecific failed");
1306 return 0;
1307}
1308
1309static void *
1310libc_internal_tsd_get ( enum __libc_tsd_key_t key )
1311{
sewardj70adeb22002-04-27 01:35:38 +00001312 void* v;
1313 static int moans = N_MOANS;
sewardj5716dbb2002-04-26 03:28:18 +00001314 /* printf("GET GET GET key %d\n", key); */
sewardj70adeb22002-04-27 01:35:38 +00001315 if (key < _LIBC_TSD_KEY_MALLOC
1316 || key >= _LIBC_TSD_KEY_N + N_LIBC_TSD_EXTRA_KEYS)
sewardj5716dbb2002-04-26 03:28:18 +00001317 barf("libc_internal_tsd_get: invalid key");
sewardj70adeb22002-04-27 01:35:38 +00001318 if (key >= _LIBC_TSD_KEY_N && moans-- > 0)
1319 fprintf(stderr,
sewardj439d45e2002-05-03 20:43:10 +00001320 "valgrind's libpthread.so: libc_internal_tsd_get: "
1321 "dubious key %d\n", key);
sewardj5716dbb2002-04-26 03:28:18 +00001322 init_libc_tsd_keys();
1323 v = pthread_getspecific(libc_specifics_keys[key]);
1324 /* if (v == NULL) barf("libc_internal_tsd_set: getspecific failed"); */
1325 return v;
1326}
1327
1328
1329
1330
sewardj70adeb22002-04-27 01:35:38 +00001331int (*__libc_internal_tsd_set)
1332 (enum __libc_tsd_key_t key, const void * pointer)
1333 = libc_internal_tsd_set;
sewardj5716dbb2002-04-26 03:28:18 +00001334
sewardj70adeb22002-04-27 01:35:38 +00001335void* (*__libc_internal_tsd_get)
1336 (enum __libc_tsd_key_t key)
1337 = libc_internal_tsd_get;
sewardj5716dbb2002-04-26 03:28:18 +00001338
1339
sewardje663cb92002-04-12 10:26:32 +00001340/* ---------------------------------------------------------------------
1341 These are here (I think) because they are deemed cancellation
1342 points by POSIX. For the moment we'll simply pass the call along
1343 to the corresponding thread-unaware (?) libc routine.
1344 ------------------------------------------------------------------ */
1345
sewardje663cb92002-04-12 10:26:32 +00001346#include <stdlib.h>
sewardje663cb92002-04-12 10:26:32 +00001347#include <sys/types.h>
1348#include <sys/socket.h>
1349
sewardjd529a442002-05-04 19:49:21 +00001350#ifdef GLIBC_2_1
1351extern
1352int __sigaction
1353 (int signum,
1354 const struct sigaction *act,
1355 struct sigaction *oldact);
1356#else
sewardje663cb92002-04-12 10:26:32 +00001357extern
1358int __libc_sigaction
1359 (int signum,
1360 const struct sigaction *act,
1361 struct sigaction *oldact);
sewardjd529a442002-05-04 19:49:21 +00001362#endif
sewardje663cb92002-04-12 10:26:32 +00001363int sigaction(int signum,
1364 const struct sigaction *act,
1365 struct sigaction *oldact)
1366{
sewardjd140e442002-05-29 01:21:19 +00001367 __my_pthread_testcancel();
sewardj2a1dcce2002-04-22 12:45:25 +00001368# ifdef GLIBC_2_1
1369 return __sigaction(signum, act, oldact);
1370# else
sewardj45b4b372002-04-16 22:50:32 +00001371 return __libc_sigaction(signum, act, oldact);
sewardj2a1dcce2002-04-22 12:45:25 +00001372# endif
sewardje663cb92002-04-12 10:26:32 +00001373}
1374
1375
1376extern
1377int __libc_connect(int sockfd,
1378 const struct sockaddr *serv_addr,
1379 socklen_t addrlen);
sewardj5905fae2002-04-26 13:25:00 +00001380__attribute__((weak))
sewardje663cb92002-04-12 10:26:32 +00001381int connect(int sockfd,
1382 const struct sockaddr *serv_addr,
1383 socklen_t addrlen)
1384{
sewardjd140e442002-05-29 01:21:19 +00001385 __my_pthread_testcancel();
sewardj45b4b372002-04-16 22:50:32 +00001386 return __libc_connect(sockfd, serv_addr, addrlen);
sewardje663cb92002-04-12 10:26:32 +00001387}
1388
1389
1390extern
1391int __libc_fcntl(int fd, int cmd, long arg);
sewardj5905fae2002-04-26 13:25:00 +00001392__attribute__((weak))
sewardje663cb92002-04-12 10:26:32 +00001393int fcntl(int fd, int cmd, long arg)
1394{
sewardjd140e442002-05-29 01:21:19 +00001395 __my_pthread_testcancel();
sewardj45b4b372002-04-16 22:50:32 +00001396 return __libc_fcntl(fd, cmd, arg);
sewardje663cb92002-04-12 10:26:32 +00001397}
1398
1399
1400extern
1401ssize_t __libc_write(int fd, const void *buf, size_t count);
sewardj5905fae2002-04-26 13:25:00 +00001402__attribute__((weak))
sewardje663cb92002-04-12 10:26:32 +00001403ssize_t write(int fd, const void *buf, size_t count)
1404{
sewardjd140e442002-05-29 01:21:19 +00001405 __my_pthread_testcancel();
sewardj45b4b372002-04-16 22:50:32 +00001406 return __libc_write(fd, buf, count);
sewardje663cb92002-04-12 10:26:32 +00001407}
1408
1409
1410extern
1411ssize_t __libc_read(int fd, void *buf, size_t count);
sewardj5905fae2002-04-26 13:25:00 +00001412__attribute__((weak))
sewardje663cb92002-04-12 10:26:32 +00001413ssize_t read(int fd, void *buf, size_t count)
1414{
sewardjd140e442002-05-29 01:21:19 +00001415 __my_pthread_testcancel();
sewardj45b4b372002-04-16 22:50:32 +00001416 return __libc_read(fd, buf, count);
sewardje663cb92002-04-12 10:26:32 +00001417}
1418
sewardjbe32e452002-04-24 20:29:58 +00001419
1420extern
sewardj853f55d2002-04-26 00:27:53 +00001421int __libc_open64(const char *pathname, int flags, mode_t mode);
sewardj5905fae2002-04-26 13:25:00 +00001422__attribute__((weak))
sewardj853f55d2002-04-26 00:27:53 +00001423int open64(const char *pathname, int flags, mode_t mode)
sewardjbe32e452002-04-24 20:29:58 +00001424{
sewardjd140e442002-05-29 01:21:19 +00001425 __my_pthread_testcancel();
sewardj853f55d2002-04-26 00:27:53 +00001426 return __libc_open64(pathname, flags, mode);
sewardjbe32e452002-04-24 20:29:58 +00001427}
1428
sewardje663cb92002-04-12 10:26:32 +00001429
1430extern
sewardj853f55d2002-04-26 00:27:53 +00001431int __libc_open(const char *pathname, int flags, mode_t mode);
sewardj5905fae2002-04-26 13:25:00 +00001432__attribute__((weak))
sewardj853f55d2002-04-26 00:27:53 +00001433int open(const char *pathname, int flags, mode_t mode)
sewardje663cb92002-04-12 10:26:32 +00001434{
sewardjd140e442002-05-29 01:21:19 +00001435 __my_pthread_testcancel();
sewardj853f55d2002-04-26 00:27:53 +00001436 return __libc_open(pathname, flags, mode);
sewardje663cb92002-04-12 10:26:32 +00001437}
1438
1439
1440extern
1441int __libc_close(int fd);
sewardj5905fae2002-04-26 13:25:00 +00001442__attribute__((weak))
sewardje663cb92002-04-12 10:26:32 +00001443int close(int fd)
1444{
sewardjd140e442002-05-29 01:21:19 +00001445 __my_pthread_testcancel();
sewardj45b4b372002-04-16 22:50:32 +00001446 return __libc_close(fd);
sewardje663cb92002-04-12 10:26:32 +00001447}
1448
1449
1450extern
1451int __libc_accept(int s, struct sockaddr *addr, socklen_t *addrlen);
sewardj5905fae2002-04-26 13:25:00 +00001452__attribute__((weak))
sewardje663cb92002-04-12 10:26:32 +00001453int accept(int s, struct sockaddr *addr, socklen_t *addrlen)
1454{
sewardjd140e442002-05-29 01:21:19 +00001455 __my_pthread_testcancel();
sewardj705d3cb2002-05-23 13:13:12 +00001456 wait_for_fd_to_be_readable_or_erring(s);
sewardjd140e442002-05-29 01:21:19 +00001457 __my_pthread_testcancel();
sewardj45b4b372002-04-16 22:50:32 +00001458 return __libc_accept(s, addr, addrlen);
sewardje663cb92002-04-12 10:26:32 +00001459}
1460
1461
1462extern
1463pid_t __libc_fork(void);
sewardj5905fae2002-04-26 13:25:00 +00001464pid_t __fork(void)
sewardje663cb92002-04-12 10:26:32 +00001465{
sewardjd140e442002-05-29 01:21:19 +00001466 __my_pthread_testcancel();
sewardj45b4b372002-04-16 22:50:32 +00001467 return __libc_fork();
sewardje663cb92002-04-12 10:26:32 +00001468}
1469
1470
1471extern
1472pid_t __libc_waitpid(pid_t pid, int *status, int options);
sewardj5905fae2002-04-26 13:25:00 +00001473__attribute__((weak))
sewardje663cb92002-04-12 10:26:32 +00001474pid_t waitpid(pid_t pid, int *status, int options)
1475{
sewardjd140e442002-05-29 01:21:19 +00001476 __my_pthread_testcancel();
sewardj45b4b372002-04-16 22:50:32 +00001477 return __libc_waitpid(pid, status, options);
sewardje663cb92002-04-12 10:26:32 +00001478}
1479
1480
1481extern
1482int __libc_nanosleep(const struct timespec *req, struct timespec *rem);
sewardj5905fae2002-04-26 13:25:00 +00001483__attribute__((weak))
sewardje663cb92002-04-12 10:26:32 +00001484int nanosleep(const struct timespec *req, struct timespec *rem)
1485{
sewardjd140e442002-05-29 01:21:19 +00001486 __my_pthread_testcancel();
sewardje663cb92002-04-12 10:26:32 +00001487 return __libc_nanosleep(req, rem);
1488}
1489
sewardjbe32e452002-04-24 20:29:58 +00001490
sewardje663cb92002-04-12 10:26:32 +00001491extern
1492int __libc_fsync(int fd);
sewardj5905fae2002-04-26 13:25:00 +00001493__attribute__((weak))
sewardje663cb92002-04-12 10:26:32 +00001494int fsync(int fd)
1495{
sewardjd140e442002-05-29 01:21:19 +00001496 __my_pthread_testcancel();
sewardj45b4b372002-04-16 22:50:32 +00001497 return __libc_fsync(fd);
sewardje663cb92002-04-12 10:26:32 +00001498}
1499
sewardjbe32e452002-04-24 20:29:58 +00001500
sewardj70c75362002-04-13 04:18:32 +00001501extern
1502off_t __libc_lseek(int fildes, off_t offset, int whence);
sewardj5905fae2002-04-26 13:25:00 +00001503__attribute__((weak))
sewardj70c75362002-04-13 04:18:32 +00001504off_t lseek(int fildes, off_t offset, int whence)
1505{
sewardjd140e442002-05-29 01:21:19 +00001506 __my_pthread_testcancel();
sewardj45b4b372002-04-16 22:50:32 +00001507 return __libc_lseek(fildes, offset, whence);
sewardj70c75362002-04-13 04:18:32 +00001508}
1509
sewardjbe32e452002-04-24 20:29:58 +00001510
1511extern
1512__off64_t __libc_lseek64(int fildes, __off64_t offset, int whence);
sewardj5905fae2002-04-26 13:25:00 +00001513__attribute__((weak))
sewardjbe32e452002-04-24 20:29:58 +00001514__off64_t lseek64(int fildes, __off64_t offset, int whence)
1515{
sewardjd140e442002-05-29 01:21:19 +00001516 __my_pthread_testcancel();
sewardjbe32e452002-04-24 20:29:58 +00001517 return __libc_lseek64(fildes, offset, whence);
1518}
1519
1520
sewardj726c4122002-05-16 23:39:10 +00001521extern
1522ssize_t __libc_pread64 (int __fd, void *__buf, size_t __nbytes,
1523 __off64_t __offset);
1524ssize_t __pread64 (int __fd, void *__buf, size_t __nbytes,
1525 __off64_t __offset)
1526{
sewardjd140e442002-05-29 01:21:19 +00001527 __my_pthread_testcancel();
sewardj726c4122002-05-16 23:39:10 +00001528 return __libc_pread64(__fd, __buf, __nbytes, __offset);
1529}
1530
1531
sewardja18e2102002-05-18 10:43:22 +00001532extern
1533ssize_t __libc_pwrite64 (int __fd, const void *__buf, size_t __nbytes,
1534 __off64_t __offset);
1535ssize_t __pwrite64 (int __fd, const void *__buf, size_t __nbytes,
1536 __off64_t __offset)
1537{
sewardjd140e442002-05-29 01:21:19 +00001538 __my_pthread_testcancel();
sewardja18e2102002-05-18 10:43:22 +00001539 return __libc_pwrite64(__fd, __buf, __nbytes, __offset);
1540}
1541
sewardj726c4122002-05-16 23:39:10 +00001542
sewardj39b93b12002-05-18 10:56:27 +00001543extern
1544ssize_t __libc_pwrite(int fd, const void *buf, size_t count, off_t offset);
1545__attribute__((weak))
1546ssize_t pwrite(int fd, const void *buf, size_t count, off_t offset)
1547{
sewardjd140e442002-05-29 01:21:19 +00001548 __my_pthread_testcancel();
sewardj39b93b12002-05-18 10:56:27 +00001549 return __libc_pwrite(fd, buf, count, offset);
1550}
1551
1552
1553extern
1554ssize_t __libc_pread(int fd, void *buf, size_t count, off_t offset);
1555__attribute__((weak))
1556ssize_t pread(int fd, void *buf, size_t count, off_t offset)
1557{
sewardjd140e442002-05-29 01:21:19 +00001558 __my_pthread_testcancel();
sewardj39b93b12002-05-18 10:56:27 +00001559 return __libc_pread(fd, buf, count, offset);
1560}
1561
1562
sewardj6af4b5d2002-04-16 04:40:49 +00001563extern
1564void __libc_longjmp(jmp_buf env, int val) __attribute((noreturn));
sewardj5905fae2002-04-26 13:25:00 +00001565/* not weak: __attribute__((weak)) */
sewardj6af4b5d2002-04-16 04:40:49 +00001566void longjmp(jmp_buf env, int val)
1567{
sewardjd140e442002-05-29 01:21:19 +00001568 __my_pthread_testcancel();
sewardj6af4b5d2002-04-16 04:40:49 +00001569 __libc_longjmp(env, val);
1570}
1571
sewardjbe32e452002-04-24 20:29:58 +00001572
sewardj6af4b5d2002-04-16 04:40:49 +00001573extern
1574int __libc_send(int s, const void *msg, size_t len, int flags);
sewardj5905fae2002-04-26 13:25:00 +00001575__attribute__((weak))
sewardj6af4b5d2002-04-16 04:40:49 +00001576int send(int s, const void *msg, size_t len, int flags)
1577{
sewardjd140e442002-05-29 01:21:19 +00001578 __my_pthread_testcancel();
sewardj6af4b5d2002-04-16 04:40:49 +00001579 return __libc_send(s, msg, len, flags);
1580}
1581
sewardjbe32e452002-04-24 20:29:58 +00001582
sewardj1e8cdc92002-04-18 11:37:52 +00001583extern
1584int __libc_recv(int s, void *buf, size_t len, int flags);
sewardj5905fae2002-04-26 13:25:00 +00001585__attribute__((weak))
sewardj1e8cdc92002-04-18 11:37:52 +00001586int recv(int s, void *buf, size_t len, int flags)
1587{
sewardjd140e442002-05-29 01:21:19 +00001588 __my_pthread_testcancel();
sewardj1e8cdc92002-04-18 11:37:52 +00001589 return __libc_recv(s, buf, len, flags);
1590}
1591
sewardjbe32e452002-04-24 20:29:58 +00001592
sewardj3665ded2002-05-16 16:57:25 +00001593extern
1594int __libc_sendmsg(int s, const struct msghdr *msg, int flags);
1595__attribute__((weak))
1596int sendmsg(int s, const struct msghdr *msg, int flags)
1597{
sewardjd140e442002-05-29 01:21:19 +00001598 __my_pthread_testcancel();
sewardj3665ded2002-05-16 16:57:25 +00001599 return __libc_sendmsg(s, msg, flags);
1600}
1601
1602
sewardj796d6a22002-04-24 02:28:34 +00001603extern
sewardj436e0582002-04-26 14:31:40 +00001604int __libc_recvfrom(int s, void *buf, size_t len, int flags,
1605 struct sockaddr *from, socklen_t *fromlen);
1606__attribute__((weak))
1607int recvfrom(int s, void *buf, size_t len, int flags,
1608 struct sockaddr *from, socklen_t *fromlen)
1609{
sewardjd140e442002-05-29 01:21:19 +00001610 __my_pthread_testcancel();
sewardj436e0582002-04-26 14:31:40 +00001611 return __libc_recvfrom(s, buf, len, flags, from, fromlen);
1612}
1613
1614
1615extern
sewardj796d6a22002-04-24 02:28:34 +00001616int __libc_sendto(int s, const void *msg, size_t len, int flags,
1617 const struct sockaddr *to, socklen_t tolen);
sewardj5905fae2002-04-26 13:25:00 +00001618__attribute__((weak))
sewardj796d6a22002-04-24 02:28:34 +00001619int sendto(int s, const void *msg, size_t len, int flags,
1620 const struct sockaddr *to, socklen_t tolen)
1621{
sewardjd140e442002-05-29 01:21:19 +00001622 __my_pthread_testcancel();
sewardj796d6a22002-04-24 02:28:34 +00001623 return __libc_sendto(s, msg, len, flags, to, tolen);
1624}
1625
sewardjbe32e452002-04-24 20:29:58 +00001626
sewardj369b1702002-04-24 13:28:15 +00001627extern
1628int __libc_system(const char* str);
sewardj5905fae2002-04-26 13:25:00 +00001629__attribute__((weak))
sewardj369b1702002-04-24 13:28:15 +00001630int system(const char* str)
1631{
sewardjd140e442002-05-29 01:21:19 +00001632 __my_pthread_testcancel();
sewardj369b1702002-04-24 13:28:15 +00001633 return __libc_system(str);
1634}
1635
sewardjbe32e452002-04-24 20:29:58 +00001636
sewardjab0b1c32002-04-24 19:26:47 +00001637extern
1638pid_t __libc_wait(int *status);
sewardj5905fae2002-04-26 13:25:00 +00001639__attribute__((weak))
sewardjab0b1c32002-04-24 19:26:47 +00001640pid_t wait(int *status)
1641{
sewardjd140e442002-05-29 01:21:19 +00001642 __my_pthread_testcancel();
sewardjab0b1c32002-04-24 19:26:47 +00001643 return __libc_wait(status);
1644}
1645
sewardj45b4b372002-04-16 22:50:32 +00001646
sewardj67f1d582002-05-24 02:11:32 +00001647extern
1648int __libc_msync(const void *start, size_t length, int flags);
1649__attribute__((weak))
1650int msync(const void *start, size_t length, int flags)
1651{
sewardjd140e442002-05-29 01:21:19 +00001652 __my_pthread_testcancel();
sewardj67f1d582002-05-24 02:11:32 +00001653 return __libc_msync(start, length, flags);
1654}
1655
sewardj5905fae2002-04-26 13:25:00 +00001656
sewardj3b13f0e2002-04-25 20:17:29 +00001657/* ---------------------------------------------------------------------
1658 Nonblocking implementations of select() and poll(). This stuff will
1659 surely rot your mind.
1660 ------------------------------------------------------------------ */
sewardje663cb92002-04-12 10:26:32 +00001661
sewardj08a4c3f2002-04-13 03:45:44 +00001662/*--------------------------------------------------*/
1663
1664#include "vg_kerneliface.h"
1665
1666static
1667__inline__
1668int is_kerror ( int res )
1669{
1670 if (res >= -4095 && res <= -1)
1671 return 1;
1672 else
1673 return 0;
1674}
1675
1676
1677static
1678int my_do_syscall1 ( int syscallno, int arg1 )
1679{
1680 int __res;
1681 __asm__ volatile ("pushl %%ebx; movl %%edx,%%ebx ; int $0x80 ; popl %%ebx"
1682 : "=a" (__res)
1683 : "0" (syscallno),
1684 "d" (arg1) );
1685 return __res;
1686}
1687
1688static
1689int my_do_syscall2 ( int syscallno,
sewardjf854f472002-04-21 12:19:41 +00001690 int arg1, int arg2 )
sewardj08a4c3f2002-04-13 03:45:44 +00001691{
1692 int __res;
1693 __asm__ volatile ("pushl %%ebx; movl %%edx,%%ebx ; int $0x80 ; popl %%ebx"
1694 : "=a" (__res)
1695 : "0" (syscallno),
1696 "d" (arg1),
1697 "c" (arg2) );
1698 return __res;
1699}
1700
1701static
sewardjf854f472002-04-21 12:19:41 +00001702int my_do_syscall3 ( int syscallno,
1703 int arg1, int arg2, int arg3 )
1704{
1705 int __res;
1706 __asm__ volatile ("pushl %%ebx; movl %%esi,%%ebx ; int $0x80 ; popl %%ebx"
1707 : "=a" (__res)
1708 : "0" (syscallno),
1709 "S" (arg1),
1710 "c" (arg2),
1711 "d" (arg3) );
1712 return __res;
1713}
1714
1715static
sewardj08a4c3f2002-04-13 03:45:44 +00001716int do_syscall_select( int n,
1717 vki_fd_set* readfds,
1718 vki_fd_set* writefds,
1719 vki_fd_set* exceptfds,
1720 struct vki_timeval * timeout )
1721{
1722 int res;
1723 int args[5];
1724 args[0] = n;
1725 args[1] = (int)readfds;
1726 args[2] = (int)writefds;
1727 args[3] = (int)exceptfds;
1728 args[4] = (int)timeout;
1729 res = my_do_syscall1(__NR_select, (int)(&(args[0])) );
sewardj02535bc2002-04-21 01:08:26 +00001730 return res;
sewardj08a4c3f2002-04-13 03:45:44 +00001731}
1732
1733
1734/* This is a wrapper round select(), which makes it thread-safe,
1735 meaning that only this thread will block, rather than the entire
1736 process. This wrapper in turn depends on nanosleep() not to block
1737 the entire process, but I think (hope? suspect?) that POSIX
1738 pthreads guarantees that to be the case.
1739
1740 Basic idea is: modify the timeout parameter to select so that it
1741 returns immediately. Poll like this until select returns non-zero,
1742 indicating something interesting happened, or until our time is up.
1743 Space out the polls with nanosleeps of say 20 milliseconds, which
1744 is required to be nonblocking; this allows other threads to run.
sewardj02535bc2002-04-21 01:08:26 +00001745
1746 Assumes:
sewardj2d94c112002-06-03 01:25:54 +00001747 * (checked via my_assert) types fd_set and vki_fd_set are identical.
1748 * (checked via my_assert) types timeval and vki_timeval are identical.
sewardj02535bc2002-04-21 01:08:26 +00001749 * (unchecked) libc error numbers (EINTR etc) are the negation of the
1750 kernel's error numbers (VKI_EINTR etc).
sewardj08a4c3f2002-04-13 03:45:44 +00001751*/
sewardj08a4c3f2002-04-13 03:45:44 +00001752
sewardj5905fae2002-04-26 13:25:00 +00001753/* __attribute__((weak)) */
sewardj08a4c3f2002-04-13 03:45:44 +00001754int select ( int n,
1755 fd_set *rfds,
1756 fd_set *wfds,
1757 fd_set *xfds,
1758 struct timeval *timeout )
1759{
sewardj5f07b662002-04-23 16:52:51 +00001760 unsigned int ms_now, ms_end;
sewardj08a4c3f2002-04-13 03:45:44 +00001761 int res;
1762 fd_set rfds_copy;
1763 fd_set wfds_copy;
1764 fd_set xfds_copy;
1765 struct vki_timeval t_now;
sewardj08a4c3f2002-04-13 03:45:44 +00001766 struct vki_timeval zero_timeout;
1767 struct vki_timespec nanosleep_interval;
1768
sewardjd140e442002-05-29 01:21:19 +00001769 __my_pthread_testcancel();
1770
sewardj5f07b662002-04-23 16:52:51 +00001771 /* gcc's complains about ms_end being used uninitialised -- classic
1772 case it can't understand, where ms_end is both defined and used
1773 only if timeout != NULL. Hence ... */
1774 ms_end = 0;
sewardj08a4c3f2002-04-13 03:45:44 +00001775
1776 /* We assume that the kernel and libc data layouts are identical
1777 for the following types. These asserts provide a crude
1778 check. */
1779 if (sizeof(fd_set) != sizeof(vki_fd_set)
1780 || sizeof(struct timeval) != sizeof(struct vki_timeval))
1781 barf("valgrind's hacky non-blocking select(): data sizes error");
1782
sewardj5f07b662002-04-23 16:52:51 +00001783 /* Detect the current time and simultaneously find out if we are
1784 running on Valgrind. */
1785 VALGRIND_MAGIC_SEQUENCE(ms_now, 0xFFFFFFFF /* default */,
1786 VG_USERREQ__READ_MILLISECOND_TIMER,
1787 0, 0, 0, 0);
1788
1789 /* If a zero timeout specified, this call is harmless. Also go
1790 this route if we're not running on Valgrind, for whatever
1791 reason. */
1792 if ( (timeout && timeout->tv_sec == 0 && timeout->tv_usec == 0)
1793 || (ms_now == 0xFFFFFFFF) ) {
sewardj02535bc2002-04-21 01:08:26 +00001794 res = do_syscall_select( n, (vki_fd_set*)rfds,
sewardj08a4c3f2002-04-13 03:45:44 +00001795 (vki_fd_set*)wfds,
1796 (vki_fd_set*)xfds,
1797 (struct vki_timeval*)timeout);
sewardj02535bc2002-04-21 01:08:26 +00001798 if (is_kerror(res)) {
1799 * (__errno_location()) = -res;
1800 return -1;
1801 } else {
1802 return res;
1803 }
1804 }
sewardj08a4c3f2002-04-13 03:45:44 +00001805
sewardj5f07b662002-04-23 16:52:51 +00001806 /* If a timeout was specified, set ms_end to be the end millisecond
1807 counter [wallclock] time. */
sewardj08a4c3f2002-04-13 03:45:44 +00001808 if (timeout) {
1809 res = my_do_syscall2(__NR_gettimeofday, (int)&t_now, (int)NULL);
sewardj2d94c112002-06-03 01:25:54 +00001810 my_assert(res == 0);
sewardj5f07b662002-04-23 16:52:51 +00001811 ms_end = ms_now;
1812 ms_end += (timeout->tv_usec / 1000);
1813 ms_end += (timeout->tv_sec * 1000);
sewardj08a4c3f2002-04-13 03:45:44 +00001814 /* Stay sane ... */
sewardj2d94c112002-06-03 01:25:54 +00001815 my_assert (ms_end >= ms_now);
sewardj08a4c3f2002-04-13 03:45:44 +00001816 }
1817
1818 /* fprintf(stderr, "MY_SELECT: before loop\n"); */
1819
1820 /* Either timeout == NULL, meaning wait indefinitely, or timeout !=
sewardj5f07b662002-04-23 16:52:51 +00001821 NULL, in which case ms_end holds the end time. */
sewardj08a4c3f2002-04-13 03:45:44 +00001822 while (1) {
1823 if (timeout) {
sewardj5f07b662002-04-23 16:52:51 +00001824 VALGRIND_MAGIC_SEQUENCE(ms_now, 0xFFFFFFFF /* default */,
1825 VG_USERREQ__READ_MILLISECOND_TIMER,
1826 0, 0, 0, 0);
sewardj2d94c112002-06-03 01:25:54 +00001827 my_assert(ms_now != 0xFFFFFFFF);
sewardj5f07b662002-04-23 16:52:51 +00001828 if (ms_now >= ms_end) {
sewardj08a4c3f2002-04-13 03:45:44 +00001829 /* timeout; nothing interesting happened. */
1830 if (rfds) FD_ZERO(rfds);
1831 if (wfds) FD_ZERO(wfds);
1832 if (xfds) FD_ZERO(xfds);
1833 return 0;
1834 }
1835 }
1836
1837 /* These could be trashed each time round the loop, so restore
1838 them each time. */
1839 if (rfds) rfds_copy = *rfds;
1840 if (wfds) wfds_copy = *wfds;
1841 if (xfds) xfds_copy = *xfds;
1842
1843 zero_timeout.tv_sec = zero_timeout.tv_usec = 0;
1844
1845 res = do_syscall_select( n,
1846 rfds ? (vki_fd_set*)(&rfds_copy) : NULL,
1847 wfds ? (vki_fd_set*)(&wfds_copy) : NULL,
1848 xfds ? (vki_fd_set*)(&xfds_copy) : NULL,
1849 & zero_timeout );
sewardj02535bc2002-04-21 01:08:26 +00001850 if (is_kerror(res)) {
1851 /* Some kind of error (including EINTR). Set errno and
sewardj08a4c3f2002-04-13 03:45:44 +00001852 return. The sets are unspecified in this case. */
sewardj02535bc2002-04-21 01:08:26 +00001853 * (__errno_location()) = -res;
1854 return -1;
sewardj08a4c3f2002-04-13 03:45:44 +00001855 }
1856 if (res > 0) {
1857 /* one or more fds is ready. Copy out resulting sets and
1858 return. */
1859 if (rfds) *rfds = rfds_copy;
1860 if (wfds) *wfds = wfds_copy;
1861 if (xfds) *xfds = xfds_copy;
1862 return res;
1863 }
1864 /* fprintf(stderr, "MY_SELECT: nanosleep\n"); */
1865 /* nanosleep and go round again */
sewardj02535bc2002-04-21 01:08:26 +00001866 nanosleep_interval.tv_sec = 0;
sewardj956cc1b2002-04-25 01:33:50 +00001867 nanosleep_interval.tv_nsec = 50 * 1000 * 1000; /* 50 milliseconds */
sewardjf854f472002-04-21 12:19:41 +00001868 /* It's critical here that valgrind's nanosleep implementation
1869 is nonblocking. */
1870 (void)my_do_syscall2(__NR_nanosleep,
1871 (int)(&nanosleep_interval), (int)NULL);
1872 }
1873}
1874
1875
1876
1877
1878#include <sys/poll.h>
1879
sewardj3e909ce2002-06-03 13:27:15 +00001880#ifndef HAVE_NFDS_T
sewardj72d58482002-04-24 02:20:20 +00001881typedef unsigned long int nfds_t;
1882#endif
1883
sewardj705d3cb2002-05-23 13:13:12 +00001884
sewardj5905fae2002-04-26 13:25:00 +00001885/* __attribute__((weak)) */
sewardjf854f472002-04-21 12:19:41 +00001886int poll (struct pollfd *__fds, nfds_t __nfds, int __timeout)
1887{
sewardj5f07b662002-04-23 16:52:51 +00001888 unsigned int ms_now, ms_end;
sewardjf854f472002-04-21 12:19:41 +00001889 int res, i;
sewardjf854f472002-04-21 12:19:41 +00001890 struct vki_timespec nanosleep_interval;
1891
sewardjd140e442002-05-29 01:21:19 +00001892 __my_pthread_testcancel();
sewardjf854f472002-04-21 12:19:41 +00001893 ensure_valgrind("poll");
1894
sewardj5f07b662002-04-23 16:52:51 +00001895 /* Detect the current time and simultaneously find out if we are
1896 running on Valgrind. */
1897 VALGRIND_MAGIC_SEQUENCE(ms_now, 0xFFFFFFFF /* default */,
1898 VG_USERREQ__READ_MILLISECOND_TIMER,
1899 0, 0, 0, 0);
1900
sewardjf854f472002-04-21 12:19:41 +00001901 if (/* CHECK SIZES FOR struct pollfd */
1902 sizeof(struct timeval) != sizeof(struct vki_timeval))
1903 barf("valgrind's hacky non-blocking poll(): data sizes error");
1904
sewardj5f07b662002-04-23 16:52:51 +00001905 /* dummy initialisation to keep gcc -Wall happy */
1906 ms_end = 0;
1907
1908 /* If a zero timeout specified, this call is harmless. Also do
1909 this if not running on Valgrind. */
1910 if (__timeout == 0 || ms_now == 0xFFFFFFFF) {
sewardjf854f472002-04-21 12:19:41 +00001911 res = my_do_syscall3(__NR_poll, (int)__fds, __nfds, __timeout);
1912 if (is_kerror(res)) {
1913 * (__errno_location()) = -res;
1914 return -1;
1915 } else {
1916 return res;
1917 }
1918 }
1919
sewardj5f07b662002-04-23 16:52:51 +00001920 /* If a timeout was specified, set ms_end to be the end wallclock
1921 time. Easy considering that __timeout is in milliseconds. */
sewardjf854f472002-04-21 12:19:41 +00001922 if (__timeout > 0) {
sewardj650ac002002-04-29 12:20:34 +00001923 ms_end = ms_now + (unsigned int)__timeout;
sewardjf854f472002-04-21 12:19:41 +00001924 }
1925
1926 /* fprintf(stderr, "MY_POLL: before loop\n"); */
1927
1928 /* Either timeout < 0, meaning wait indefinitely, or timeout > 0,
1929 in which case t_end holds the end time. */
sewardj2d94c112002-06-03 01:25:54 +00001930 my_assert(__timeout != 0);
sewardj5f07b662002-04-23 16:52:51 +00001931
sewardjf854f472002-04-21 12:19:41 +00001932 while (1) {
sewardjf854f472002-04-21 12:19:41 +00001933 if (__timeout > 0) {
sewardj5f07b662002-04-23 16:52:51 +00001934 VALGRIND_MAGIC_SEQUENCE(ms_now, 0xFFFFFFFF /* default */,
1935 VG_USERREQ__READ_MILLISECOND_TIMER,
1936 0, 0, 0, 0);
sewardj2d94c112002-06-03 01:25:54 +00001937 my_assert(ms_now != 0xFFFFFFFF);
sewardj5f07b662002-04-23 16:52:51 +00001938 if (ms_now >= ms_end) {
sewardjf854f472002-04-21 12:19:41 +00001939 /* timeout; nothing interesting happened. */
1940 for (i = 0; i < __nfds; i++)
1941 __fds[i].revents = 0;
1942 return 0;
1943 }
1944 }
1945
sewardj5f07b662002-04-23 16:52:51 +00001946 /* Do a return-immediately poll. */
sewardjf854f472002-04-21 12:19:41 +00001947 res = my_do_syscall3(__NR_poll, (int)__fds, __nfds, 0 );
1948 if (is_kerror(res)) {
1949 /* Some kind of error. Set errno and return. */
1950 * (__errno_location()) = -res;
1951 return -1;
1952 }
1953 if (res > 0) {
1954 /* One or more fds is ready. Return now. */
1955 return res;
1956 }
1957 /* fprintf(stderr, "MY_POLL: nanosleep\n"); */
1958 /* nanosleep and go round again */
1959 nanosleep_interval.tv_sec = 0;
sewardj956cc1b2002-04-25 01:33:50 +00001960 nanosleep_interval.tv_nsec = 51 * 1000 * 1000; /* 51 milliseconds */
sewardj08a4c3f2002-04-13 03:45:44 +00001961 /* It's critical here that valgrind's nanosleep implementation
1962 is nonblocking. */
1963 (void)my_do_syscall2(__NR_nanosleep,
1964 (int)(&nanosleep_interval), (int)NULL);
1965 }
1966}
sewardj3b13f0e2002-04-25 20:17:29 +00001967
1968
sewardj705d3cb2002-05-23 13:13:12 +00001969/* Helper function used to make accept() non-blocking. Idea is to use
1970 the above nonblocking poll() to make this thread ONLY wait for the
1971 specified fd to become ready, and then return. */
1972static void wait_for_fd_to_be_readable_or_erring ( int fd )
1973{
1974 struct pollfd pfd;
sewardj6e6cbaa2002-05-24 02:12:52 +00001975 /* fprintf(stderr, "wait_for_fd_to_be_readable_or_erring %d\n", fd); */
sewardj705d3cb2002-05-23 13:13:12 +00001976 pfd.fd = fd;
1977 pfd.events = POLLIN | POLLPRI | POLLERR | POLLHUP | POLLNVAL;
1978 /* ... but not POLLOUT, you may notice. */
1979 pfd.revents = 0;
1980 (void)poll(&pfd, 1, -1 /* forever */);
1981}
1982
1983
sewardj3b13f0e2002-04-25 20:17:29 +00001984/* ---------------------------------------------------------------------
sewardj8f253ff2002-05-19 00:13:34 +00001985 Hacky implementation of semaphores.
1986 ------------------------------------------------------------------ */
1987
1988#include <semaphore.h>
1989
1990/* This is a terrible way to do the remapping. Plan is to import an
1991 AVL tree at some point. */
sewardj8f253ff2002-05-19 00:13:34 +00001992
1993typedef
1994 struct {
1995 pthread_mutex_t se_mx;
1996 pthread_cond_t se_cv;
1997 int count;
1998 }
1999 vg_sem_t;
2000
2001static pthread_mutex_t se_remap_mx = PTHREAD_MUTEX_INITIALIZER;
2002
2003static int se_remap_used = 0;
2004static sem_t* se_remap_orig[VG_N_SEMAPHORES];
2005static vg_sem_t se_remap_new[VG_N_SEMAPHORES];
2006
2007static vg_sem_t* se_remap ( sem_t* orig )
2008{
2009 int res, i;
2010 res = __pthread_mutex_lock(&se_remap_mx);
sewardj2d94c112002-06-03 01:25:54 +00002011 my_assert(res == 0);
sewardj8f253ff2002-05-19 00:13:34 +00002012
2013 for (i = 0; i < se_remap_used; i++) {
2014 if (se_remap_orig[i] == orig)
2015 break;
2016 }
2017 if (i == se_remap_used) {
2018 if (se_remap_used == VG_N_SEMAPHORES) {
2019 res = pthread_mutex_unlock(&se_remap_mx);
sewardj2d94c112002-06-03 01:25:54 +00002020 my_assert(res == 0);
sewardja1ac5cb2002-05-27 13:00:05 +00002021 barf("VG_N_SEMAPHORES is too low. Increase and recompile.");
sewardj8f253ff2002-05-19 00:13:34 +00002022 }
2023 se_remap_used++;
2024 se_remap_orig[i] = orig;
2025 /* printf("allocated semaphore %d\n", i); */
2026 }
2027 res = __pthread_mutex_unlock(&se_remap_mx);
sewardj2d94c112002-06-03 01:25:54 +00002028 my_assert(res == 0);
sewardj8f253ff2002-05-19 00:13:34 +00002029 return &se_remap_new[i];
2030}
2031
2032
2033int sem_init(sem_t *sem, int pshared, unsigned int value)
2034{
2035 int res;
2036 vg_sem_t* vg_sem;
2037 ensure_valgrind("sem_init");
2038 if (pshared != 0) {
2039 errno = ENOSYS;
2040 return -1;
2041 }
2042 vg_sem = se_remap(sem);
2043 res = pthread_mutex_init(&vg_sem->se_mx, NULL);
sewardj2d94c112002-06-03 01:25:54 +00002044 my_assert(res == 0);
sewardj8f253ff2002-05-19 00:13:34 +00002045 res = pthread_cond_init(&vg_sem->se_cv, NULL);
sewardj2d94c112002-06-03 01:25:54 +00002046 my_assert(res == 0);
sewardj8f253ff2002-05-19 00:13:34 +00002047 vg_sem->count = value;
2048 return 0;
2049}
2050
2051
2052int sem_wait ( sem_t* sem )
2053{
2054 int res;
2055 vg_sem_t* vg_sem;
2056 ensure_valgrind("sem_wait");
2057 vg_sem = se_remap(sem);
2058 res = __pthread_mutex_lock(&vg_sem->se_mx);
sewardj2d94c112002-06-03 01:25:54 +00002059 my_assert(res == 0);
sewardj8f253ff2002-05-19 00:13:34 +00002060 while (vg_sem->count == 0) {
2061 res = pthread_cond_wait(&vg_sem->se_cv, &vg_sem->se_mx);
sewardj2d94c112002-06-03 01:25:54 +00002062 my_assert(res == 0);
sewardj8f253ff2002-05-19 00:13:34 +00002063 }
2064 vg_sem->count--;
2065 res = __pthread_mutex_unlock(&vg_sem->se_mx);
sewardj2d94c112002-06-03 01:25:54 +00002066 my_assert(res == 0);
sewardj8f253ff2002-05-19 00:13:34 +00002067 return 0;
2068}
2069
2070int sem_post ( sem_t* sem )
2071{
2072 int res;
2073 vg_sem_t* vg_sem;
2074 ensure_valgrind("sem_post");
2075 vg_sem = se_remap(sem);
2076 res = __pthread_mutex_lock(&vg_sem->se_mx);
sewardj2d94c112002-06-03 01:25:54 +00002077 my_assert(res == 0);
sewardj8f253ff2002-05-19 00:13:34 +00002078 if (vg_sem->count == 0) {
2079 vg_sem->count++;
2080 res = pthread_cond_broadcast(&vg_sem->se_cv);
sewardj2d94c112002-06-03 01:25:54 +00002081 my_assert(res == 0);
sewardj8f253ff2002-05-19 00:13:34 +00002082 } else {
2083 vg_sem->count++;
2084 }
2085 res = __pthread_mutex_unlock(&vg_sem->se_mx);
sewardj2d94c112002-06-03 01:25:54 +00002086 my_assert(res == 0);
sewardj8f253ff2002-05-19 00:13:34 +00002087 return 0;
2088}
2089
2090
2091int sem_trywait ( sem_t* sem )
2092{
2093 int ret, res;
2094 vg_sem_t* vg_sem;
2095 ensure_valgrind("sem_trywait");
2096 vg_sem = se_remap(sem);
2097 res = __pthread_mutex_lock(&vg_sem->se_mx);
sewardj2d94c112002-06-03 01:25:54 +00002098 my_assert(res == 0);
sewardj8f253ff2002-05-19 00:13:34 +00002099 if (vg_sem->count > 0) {
2100 vg_sem->count--;
2101 ret = 0;
2102 } else {
2103 ret = -1;
2104 errno = EAGAIN;
2105 }
2106 res = __pthread_mutex_unlock(&vg_sem->se_mx);
sewardj2d94c112002-06-03 01:25:54 +00002107 my_assert(res == 0);
sewardj8f253ff2002-05-19 00:13:34 +00002108 return ret;
2109}
2110
2111
2112int sem_getvalue(sem_t* sem, int * sval)
2113{
2114 vg_sem_t* vg_sem;
2115 ensure_valgrind("sem_trywait");
2116 vg_sem = se_remap(sem);
2117 *sval = vg_sem->count;
2118 return 0;
2119}
2120
2121
2122int sem_destroy(sem_t * sem)
2123{
2124 kludged("sem_destroy");
2125 /* if someone waiting on this semaphore, errno = EBUSY, return -1 */
2126 return 0;
2127}
2128
2129
2130/* ---------------------------------------------------------------------
sewardj2d8b3f02002-06-01 14:14:19 +00002131 Reader-writer locks.
sewardja1ac5cb2002-05-27 13:00:05 +00002132 ------------------------------------------------------------------ */
2133
sewardj2d8b3f02002-06-01 14:14:19 +00002134typedef
2135 struct {
2136 int initted; /* != 0 --> in use; sanity check only */
2137 int prefer_w; /* != 0 --> prefer writer */
2138 int nwait_r; /* # of waiting readers */
2139 int nwait_w; /* # of waiting writers */
2140 pthread_cond_t cv_r; /* for signalling readers */
2141 pthread_cond_t cv_w; /* for signalling writers */
2142 pthread_mutex_t mx;
2143 int status;
2144 /* allowed range for status: >= -1. -1 means 1 writer currently
2145 active, >= 0 means N readers currently active. */
2146 }
2147 vg_rwlock_t;
sewardja1ac5cb2002-05-27 13:00:05 +00002148
2149
2150static pthread_mutex_t rw_remap_mx = PTHREAD_MUTEX_INITIALIZER;
2151
2152static int rw_remap_used = 0;
2153static pthread_rwlock_t* rw_remap_orig[VG_N_RWLOCKS];
2154static vg_rwlock_t rw_remap_new[VG_N_RWLOCKS];
2155
sewardj2d8b3f02002-06-01 14:14:19 +00002156
2157static
2158void init_vg_rwlock ( vg_rwlock_t* vg_rwl )
2159{
2160 int res = 0;
2161 vg_rwl->initted = 1;
2162 vg_rwl->prefer_w = 1;
2163 vg_rwl->nwait_r = 0;
2164 vg_rwl->nwait_w = 0;
2165 vg_rwl->status = 0;
2166 res = pthread_mutex_init(&vg_rwl->mx, NULL);
2167 res |= pthread_cond_init(&vg_rwl->cv_r, NULL);
2168 res |= pthread_cond_init(&vg_rwl->cv_w, NULL);
sewardj2d94c112002-06-03 01:25:54 +00002169 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002170}
2171
2172
sewardja1ac5cb2002-05-27 13:00:05 +00002173/* Take the address of a LinuxThreads rwlock_t and return the shadow
2174 address of our version. Further, if the LinuxThreads version
2175 appears to have been statically initialised, do the same to the one
2176 we allocate here. The pthread_rwlock_t.__rw_readers field is set
2177 to zero by PTHREAD_RWLOCK_INITIALIZER, so we take zero as meaning
2178 uninitialised and non-zero meaning initialised.
2179*/
2180static vg_rwlock_t* rw_remap ( pthread_rwlock_t* orig )
2181{
2182 int res, i;
2183 vg_rwlock_t* vg_rwl;
2184 res = __pthread_mutex_lock(&rw_remap_mx);
sewardj2d94c112002-06-03 01:25:54 +00002185 my_assert(res == 0);
sewardja1ac5cb2002-05-27 13:00:05 +00002186
2187 for (i = 0; i < rw_remap_used; i++) {
2188 if (rw_remap_orig[i] == orig)
2189 break;
2190 }
2191 if (i == rw_remap_used) {
2192 if (rw_remap_used == VG_N_RWLOCKS) {
sewardj2d8b3f02002-06-01 14:14:19 +00002193 res = __pthread_mutex_unlock(&rw_remap_mx);
sewardj2d94c112002-06-03 01:25:54 +00002194 my_assert(res == 0);
sewardja1ac5cb2002-05-27 13:00:05 +00002195 barf("VG_N_RWLOCKS is too low. Increase and recompile.");
2196 }
2197 rw_remap_used++;
2198 rw_remap_orig[i] = orig;
sewardj2d8b3f02002-06-01 14:14:19 +00002199 rw_remap_new[i].initted = 0;
sewardja1ac5cb2002-05-27 13:00:05 +00002200 if (0) printf("allocated rwlock %d\n", i);
2201 }
2202 res = __pthread_mutex_unlock(&rw_remap_mx);
sewardj2d94c112002-06-03 01:25:54 +00002203 my_assert(res == 0);
sewardja1ac5cb2002-05-27 13:00:05 +00002204 vg_rwl = &rw_remap_new[i];
2205
sewardj2d8b3f02002-06-01 14:14:19 +00002206 /* Initialise the shadow, if required. */
sewardja1ac5cb2002-05-27 13:00:05 +00002207 if (orig->__rw_readers == 0) {
sewardja1ac5cb2002-05-27 13:00:05 +00002208 orig->__rw_readers = 1;
sewardj2d8b3f02002-06-01 14:14:19 +00002209 init_vg_rwlock(vg_rwl);
sewardja1ac5cb2002-05-27 13:00:05 +00002210 if (orig->__rw_kind == PTHREAD_RWLOCK_PREFER_READER_NP)
sewardj2d8b3f02002-06-01 14:14:19 +00002211 vg_rwl->prefer_w = 0;
sewardja1ac5cb2002-05-27 13:00:05 +00002212 }
2213
2214 return vg_rwl;
2215}
2216
2217
sewardja1ac5cb2002-05-27 13:00:05 +00002218int pthread_rwlock_init ( pthread_rwlock_t* orig,
2219 const pthread_rwlockattr_t* attr )
2220{
sewardja1ac5cb2002-05-27 13:00:05 +00002221 vg_rwlock_t* rwl;
2222 if (0) printf ("pthread_rwlock_init\n");
2223 /* Force the remapper to initialise the shadow. */
2224 orig->__rw_readers = 0;
2225 /* Install the lock preference; the remapper needs to know it. */
2226 orig->__rw_kind = PTHREAD_RWLOCK_DEFAULT_NP;
2227 if (attr)
2228 orig->__rw_kind = attr->__lockkind;
2229 rwl = rw_remap ( orig );
sewardj2d8b3f02002-06-01 14:14:19 +00002230 return 0;
sewardja1ac5cb2002-05-27 13:00:05 +00002231}
2232
sewardj2d8b3f02002-06-01 14:14:19 +00002233
2234static
2235void pthread_rwlock_rdlock_CANCEL_HDLR ( void* rwl_v )
sewardja1ac5cb2002-05-27 13:00:05 +00002236{
sewardj2d8b3f02002-06-01 14:14:19 +00002237 vg_rwlock_t* rwl = (vg_rwlock_t*)rwl_v;
2238 rwl->nwait_r--;
2239 pthread_mutex_unlock (&rwl->mx);
sewardja1ac5cb2002-05-27 13:00:05 +00002240}
2241
sewardj2d8b3f02002-06-01 14:14:19 +00002242
sewardja1ac5cb2002-05-27 13:00:05 +00002243int pthread_rwlock_rdlock ( pthread_rwlock_t* orig )
2244{
2245 int res;
2246 vg_rwlock_t* rwl;
2247 if (0) printf ("pthread_rwlock_rdlock\n");
2248 rwl = rw_remap ( orig );
sewardj2d8b3f02002-06-01 14:14:19 +00002249 res = __pthread_mutex_lock(&rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00002250 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002251 if (!rwl->initted) {
2252 res = __pthread_mutex_unlock(&rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00002253 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002254 return EINVAL;
2255 }
2256 if (rwl->status < 0) {
sewardj2d94c112002-06-03 01:25:54 +00002257 my_assert(rwl->status == -1);
sewardj2d8b3f02002-06-01 14:14:19 +00002258 rwl->nwait_r++;
2259 pthread_cleanup_push( pthread_rwlock_rdlock_CANCEL_HDLR, rwl );
2260 while (1) {
2261 if (rwl->status == 0) break;
2262 res = pthread_cond_wait(&rwl->cv_r, &rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00002263 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002264 }
2265 pthread_cleanup_pop(0);
2266 rwl->nwait_r--;
2267 }
sewardj2d94c112002-06-03 01:25:54 +00002268 my_assert(rwl->status >= 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002269 rwl->status++;
2270 res = __pthread_mutex_unlock(&rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00002271 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002272 return 0;
sewardja1ac5cb2002-05-27 13:00:05 +00002273}
2274
sewardj2d8b3f02002-06-01 14:14:19 +00002275
sewardja1ac5cb2002-05-27 13:00:05 +00002276int pthread_rwlock_tryrdlock ( pthread_rwlock_t* orig )
2277{
2278 int res;
2279 vg_rwlock_t* rwl;
2280 if (0) printf ("pthread_rwlock_tryrdlock\n");
2281 rwl = rw_remap ( orig );
sewardj2d8b3f02002-06-01 14:14:19 +00002282 res = __pthread_mutex_lock(&rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00002283 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002284 if (!rwl->initted) {
2285 res = __pthread_mutex_unlock(&rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00002286 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002287 return EINVAL;
2288 }
2289 if (rwl->status == -1) {
2290 /* Writer active; we have to give up. */
2291 res = __pthread_mutex_unlock(&rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00002292 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002293 return EBUSY;
2294 }
2295 /* Success */
sewardj2d94c112002-06-03 01:25:54 +00002296 my_assert(rwl->status >= 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002297 rwl->status++;
2298 res = __pthread_mutex_unlock(&rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00002299 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002300 return 0;
sewardja1ac5cb2002-05-27 13:00:05 +00002301}
2302
sewardj2d8b3f02002-06-01 14:14:19 +00002303
2304static
2305void pthread_rwlock_wrlock_CANCEL_HDLR ( void* rwl_v )
2306{
2307 vg_rwlock_t* rwl = (vg_rwlock_t*)rwl_v;
2308 rwl->nwait_w--;
2309 pthread_mutex_unlock (&rwl->mx);
2310}
2311
2312
sewardja1ac5cb2002-05-27 13:00:05 +00002313int pthread_rwlock_wrlock ( pthread_rwlock_t* orig )
2314{
2315 int res;
2316 vg_rwlock_t* rwl;
2317 if (0) printf ("pthread_rwlock_wrlock\n");
2318 rwl = rw_remap ( orig );
sewardj2d8b3f02002-06-01 14:14:19 +00002319 res = __pthread_mutex_lock(&rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00002320 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002321 if (!rwl->initted) {
2322 res = __pthread_mutex_unlock(&rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00002323 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002324 return EINVAL;
2325 }
2326 if (rwl->status != 0) {
2327 rwl->nwait_w++;
2328 pthread_cleanup_push( pthread_rwlock_wrlock_CANCEL_HDLR, rwl );
2329 while (1) {
2330 if (rwl->status == 0) break;
2331 res = pthread_cond_wait(&rwl->cv_w, &rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00002332 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002333 }
2334 pthread_cleanup_pop(0);
2335 rwl->nwait_w--;
2336 }
sewardj2d94c112002-06-03 01:25:54 +00002337 my_assert(rwl->status == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002338 rwl->status = -1;
2339 res = __pthread_mutex_unlock(&rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00002340 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002341 return 0;
sewardja1ac5cb2002-05-27 13:00:05 +00002342}
2343
sewardj2d8b3f02002-06-01 14:14:19 +00002344
sewardja1ac5cb2002-05-27 13:00:05 +00002345int pthread_rwlock_trywrlock ( pthread_rwlock_t* orig )
2346{
2347 int res;
2348 vg_rwlock_t* rwl;
sewardj2d8b3f02002-06-01 14:14:19 +00002349 if (0) printf ("pthread_wrlock_trywrlock\n");
sewardja1ac5cb2002-05-27 13:00:05 +00002350 rwl = rw_remap ( orig );
sewardj2d8b3f02002-06-01 14:14:19 +00002351 res = __pthread_mutex_lock(&rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00002352 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002353 if (!rwl->initted) {
2354 res = __pthread_mutex_unlock(&rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00002355 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002356 return EINVAL;
2357 }
2358 if (rwl->status != 0) {
2359 /* Reader(s) or a writer active; we have to give up. */
2360 res = __pthread_mutex_unlock(&rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00002361 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002362 return EBUSY;
2363 }
2364 /* Success */
sewardj2d94c112002-06-03 01:25:54 +00002365 my_assert(rwl->status == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002366 rwl->status = -1;
2367 res = __pthread_mutex_unlock(&rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00002368 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002369 return 0;
sewardja1ac5cb2002-05-27 13:00:05 +00002370}
2371
sewardj2d8b3f02002-06-01 14:14:19 +00002372
sewardja1ac5cb2002-05-27 13:00:05 +00002373int pthread_rwlock_unlock ( pthread_rwlock_t* orig )
2374{
2375 int res;
2376 vg_rwlock_t* rwl;
2377 if (0) printf ("pthread_rwlock_unlock\n");
2378 rwl = rw_remap ( orig );
sewardj2d8b3f02002-06-01 14:14:19 +00002379 rwl = rw_remap ( orig );
2380 res = __pthread_mutex_lock(&rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00002381 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002382 if (!rwl->initted) {
2383 res = __pthread_mutex_unlock(&rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00002384 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002385 return EINVAL;
2386 }
2387 if (rwl->status == 0) {
2388 res = __pthread_mutex_unlock(&rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00002389 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002390 return EPERM;
2391 }
sewardj2d94c112002-06-03 01:25:54 +00002392 my_assert(rwl->status != 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002393 if (rwl->status == -1) {
2394 rwl->status = 0;
2395 } else {
sewardj2d94c112002-06-03 01:25:54 +00002396 my_assert(rwl->status > 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002397 rwl->status--;
2398 }
2399
sewardj2d94c112002-06-03 01:25:54 +00002400 my_assert(rwl->status >= 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002401
2402 if (rwl->prefer_w) {
2403
2404 /* Favour waiting writers, if any. */
2405 if (rwl->nwait_w > 0) {
2406 /* Writer(s) are waiting. */
2407 if (rwl->status == 0) {
2408 /* We can let a writer in. */
2409 res = pthread_cond_signal(&rwl->cv_w);
sewardj2d94c112002-06-03 01:25:54 +00002410 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002411 } else {
2412 /* There are still readers active. Do nothing; eventually
2413 they will disappear, at which point a writer will be
2414 admitted. */
2415 }
2416 }
2417 else
2418 /* No waiting writers. */
2419 if (rwl->nwait_r > 0) {
2420 /* Let in a waiting reader. */
2421 res = pthread_cond_signal(&rwl->cv_r);
sewardj2d94c112002-06-03 01:25:54 +00002422 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002423 }
2424
2425 } else {
2426
2427 /* Favour waiting readers, if any. */
2428 if (rwl->nwait_r > 0) {
2429 /* Reader(s) are waiting; let one in. */
2430 res = pthread_cond_signal(&rwl->cv_r);
sewardj2d94c112002-06-03 01:25:54 +00002431 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002432 }
2433 else
2434 /* No waiting readers. */
2435 if (rwl->nwait_w > 0 && rwl->status == 0) {
2436 /* We have waiting writers and no active readers; let a
2437 writer in. */
2438 res = pthread_cond_signal(&rwl->cv_w);
sewardj2d94c112002-06-03 01:25:54 +00002439 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002440 }
2441 }
2442
2443 res = __pthread_mutex_unlock(&rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00002444 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002445 return 0;
2446}
2447
2448
2449int pthread_rwlock_destroy ( pthread_rwlock_t *orig )
2450{
2451 int res;
2452 vg_rwlock_t* rwl;
2453 if (0) printf ("pthread_rwlock_destroy\n");
2454 rwl = rw_remap ( orig );
2455 res = __pthread_mutex_lock(&rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00002456 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002457 if (!rwl->initted) {
2458 res = __pthread_mutex_unlock(&rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00002459 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002460 return EINVAL;
2461 }
2462 if (rwl->status != 0 || rwl->nwait_r > 0 || rwl->nwait_w > 0) {
2463 res = __pthread_mutex_unlock(&rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00002464 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002465 return EBUSY;
2466 }
2467 rwl->initted = 0;
2468 res = __pthread_mutex_unlock(&rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00002469 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002470 return 0;
sewardja1ac5cb2002-05-27 13:00:05 +00002471}
2472
2473
2474/* ---------------------------------------------------------------------
sewardj3b13f0e2002-04-25 20:17:29 +00002475 B'stard.
2476 ------------------------------------------------------------------ */
2477
2478# define strong_alias(name, aliasname) \
2479 extern __typeof (name) aliasname __attribute__ ((alias (#name)));
2480
sewardj5905fae2002-04-26 13:25:00 +00002481# define weak_alias(name, aliasname) \
2482 extern __typeof (name) aliasname __attribute__ ((weak, alias (#name)));
sewardj3b13f0e2002-04-25 20:17:29 +00002483
sewardj5905fae2002-04-26 13:25:00 +00002484strong_alias(__pthread_mutex_lock, pthread_mutex_lock)
2485strong_alias(__pthread_mutex_trylock, pthread_mutex_trylock)
2486strong_alias(__pthread_mutex_unlock, pthread_mutex_unlock)
2487strong_alias(__pthread_mutexattr_init, pthread_mutexattr_init)
2488 weak_alias(__pthread_mutexattr_settype, pthread_mutexattr_settype)
2489strong_alias(__pthread_mutex_init, pthread_mutex_init)
2490strong_alias(__pthread_mutexattr_destroy, pthread_mutexattr_destroy)
2491strong_alias(__pthread_mutex_destroy, pthread_mutex_destroy)
2492strong_alias(__pthread_once, pthread_once)
2493strong_alias(__pthread_atfork, pthread_atfork)
2494strong_alias(__pthread_key_create, pthread_key_create)
2495strong_alias(__pthread_getspecific, pthread_getspecific)
2496strong_alias(__pthread_setspecific, pthread_setspecific)
2497
sewardjd529a442002-05-04 19:49:21 +00002498#ifndef GLIBC_2_1
sewardj3b13f0e2002-04-25 20:17:29 +00002499strong_alias(sigaction, __sigaction)
sewardjd529a442002-05-04 19:49:21 +00002500#endif
2501
sewardj5905fae2002-04-26 13:25:00 +00002502strong_alias(close, __close)
sewardj3b13f0e2002-04-25 20:17:29 +00002503strong_alias(fcntl, __fcntl)
sewardj5905fae2002-04-26 13:25:00 +00002504strong_alias(lseek, __lseek)
2505strong_alias(open, __open)
2506strong_alias(open64, __open64)
sewardj5905fae2002-04-26 13:25:00 +00002507strong_alias(read, __read)
2508strong_alias(wait, __wait)
2509strong_alias(write, __write)
sewardj3b13f0e2002-04-25 20:17:29 +00002510strong_alias(connect, __connect)
sewardj5905fae2002-04-26 13:25:00 +00002511strong_alias(send, __send)
2512
sewardj726c4122002-05-16 23:39:10 +00002513weak_alias (__pread64, pread64)
sewardja18e2102002-05-18 10:43:22 +00002514weak_alias (__pwrite64, pwrite64)
sewardj5905fae2002-04-26 13:25:00 +00002515weak_alias(__fork, fork)
sewardj7f6456d2002-05-21 00:51:21 +00002516
sewardj5905fae2002-04-26 13:25:00 +00002517
sewardj3b13f0e2002-04-25 20:17:29 +00002518
2519/*--------------------------------------------------*/
2520
sewardj5905fae2002-04-26 13:25:00 +00002521weak_alias(pthread_rwlock_rdlock, __pthread_rwlock_rdlock)
sewardj5905fae2002-04-26 13:25:00 +00002522weak_alias(pthread_rwlock_unlock, __pthread_rwlock_unlock)
sewardj262b0292002-05-01 00:03:16 +00002523weak_alias(pthread_rwlock_wrlock, __pthread_rwlock_wrlock)
sewardj060b04f2002-04-26 21:01:13 +00002524
sewardja1ac5cb2002-05-27 13:00:05 +00002525weak_alias(pthread_rwlock_destroy, __pthread_rwlock_destroy)
2526weak_alias(pthread_rwlock_init, __pthread_rwlock_init)
2527weak_alias(pthread_rwlock_tryrdlock, __pthread_rwlock_tryrdlock)
2528weak_alias(pthread_rwlock_trywrlock, __pthread_rwlock_trywrlock)
2529
sewardj060b04f2002-04-26 21:01:13 +00002530
sewardj3b13f0e2002-04-25 20:17:29 +00002531/* I've no idea what these are, but they get called quite a lot.
2532 Anybody know? */
2533
2534#undef _IO_flockfile
2535void _IO_flockfile ( _IO_FILE * file )
2536{
sewardj853f55d2002-04-26 00:27:53 +00002537 pthread_mutex_lock(file->_lock);
sewardj3b13f0e2002-04-25 20:17:29 +00002538}
sewardj5905fae2002-04-26 13:25:00 +00002539weak_alias(_IO_flockfile, flockfile);
2540
sewardj3b13f0e2002-04-25 20:17:29 +00002541
2542#undef _IO_funlockfile
2543void _IO_funlockfile ( _IO_FILE * file )
2544{
sewardj853f55d2002-04-26 00:27:53 +00002545 pthread_mutex_unlock(file->_lock);
sewardj3b13f0e2002-04-25 20:17:29 +00002546}
sewardj5905fae2002-04-26 13:25:00 +00002547weak_alias(_IO_funlockfile, funlockfile);
2548
sewardj3b13f0e2002-04-25 20:17:29 +00002549
sewardjd4f2c712002-04-30 10:20:10 +00002550/* This doesn't seem to be needed to simulate libpthread.so's external
2551 interface, but many people complain about its absence. */
2552
2553strong_alias(__pthread_mutexattr_settype, __pthread_mutexattr_setkind_np)
2554weak_alias(__pthread_mutexattr_setkind_np, pthread_mutexattr_setkind_np)
sewardj439d45e2002-05-03 20:43:10 +00002555
2556
2557/*--------------------------------------------------------------------*/
2558/*--- end vg_libpthread.c ---*/
2559/*--------------------------------------------------------------------*/