blob: 3ed46c033e5c64cf96043b131044f93f2de2f688 [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
sewardj457cc472002-06-03 23:13:47 +0000188static
sewardj2d94c112002-06-03 01:25:54 +0000189void my_assert_fail ( Char* expr, Char* file, Int line, Char* fn )
190{
191 static Bool entered = False;
192 if (entered)
193 my_exit(2);
194 entered = True;
195 fprintf(stderr, "\n%s: %s:%d (%s): Assertion `%s' failed.\n",
196 "valgrind", file, line, fn, expr );
197 fprintf(stderr, "Please report this bug to me at: %s\n\n",
198 VG_EMAIL_ADDR);
199 my_exit(1);
200}
201
202#define MY__STRING(__str) #__str
203
204#define my_assert(expr) \
205 ((void) ((expr) ? 0 : \
206 (my_assert_fail (MY__STRING(expr), \
207 __FILE__, __LINE__, \
208 __PRETTY_FUNCTION__), 0)))
209
210
sewardje663cb92002-04-12 10:26:32 +0000211/* ---------------------------------------------------------------------
212 Pass pthread_ calls to Valgrind's request mechanism.
213 ------------------------------------------------------------------ */
214
sewardjf8f819e2002-04-17 23:21:37 +0000215#include <errno.h>
sewardj5f07b662002-04-23 16:52:51 +0000216#include <sys/time.h> /* gettimeofday */
sewardjf8f819e2002-04-17 23:21:37 +0000217
sewardja1ac5cb2002-05-27 13:00:05 +0000218
sewardjf8f819e2002-04-17 23:21:37 +0000219/* ---------------------------------------------------
220 THREAD ATTRIBUTES
221 ------------------------------------------------ */
222
sewardj6af4b5d2002-04-16 04:40:49 +0000223int pthread_attr_init(pthread_attr_t *attr)
224{
sewardj7989d0c2002-05-28 11:00:01 +0000225 /* Just initialise the fields which we might look at. */
226 attr->__detachstate = PTHREAD_CREATE_JOINABLE;
sewardj6af4b5d2002-04-16 04:40:49 +0000227 return 0;
228}
229
230int pthread_attr_setdetachstate(pthread_attr_t *attr, int detachstate)
231{
sewardj7989d0c2002-05-28 11:00:01 +0000232 if (detachstate != PTHREAD_CREATE_JOINABLE
233 && detachstate != PTHREAD_CREATE_DETACHED)
234 return EINVAL;
235 attr->__detachstate = detachstate;
sewardj6af4b5d2002-04-16 04:40:49 +0000236 return 0;
237}
238
sewardj30671ff2002-04-21 00:13:57 +0000239int pthread_attr_setinheritsched(pthread_attr_t *attr, int inherit)
240{
sewardj436e0582002-04-26 14:31:40 +0000241 static int moans = N_MOANS;
242 if (moans-- > 0)
243 ignored("pthread_attr_setinheritsched");
sewardj30671ff2002-04-21 00:13:57 +0000244 return 0;
245}
sewardj6af4b5d2002-04-16 04:40:49 +0000246
sewardj0286dd52002-05-16 20:51:15 +0000247__attribute__((weak))
248int pthread_attr_setstacksize (pthread_attr_t *__attr,
249 size_t __stacksize)
250{
sewardja18e2102002-05-18 10:43:22 +0000251 size_t limit;
sewardj0286dd52002-05-16 20:51:15 +0000252 ensure_valgrind("pthread_attr_setstacksize");
sewardja18e2102002-05-18 10:43:22 +0000253 limit = VG_PTHREAD_STACK_SIZE - VG_AR_CLIENT_STACKBASE_REDZONE_SZB
254 - 1000; /* paranoia */
255 if (__stacksize < limit)
sewardj0286dd52002-05-16 20:51:15 +0000256 return 0;
257 barf("pthread_attr_setstacksize: "
258 "requested size >= VG_PTHREAD_STACK_SIZE\n "
259 "edit vg_include.h and rebuild.");
260}
261
262
sewardj30671ff2002-04-21 00:13:57 +0000263/* This is completely bogus. */
264int pthread_attr_getschedparam(const pthread_attr_t *attr,
265 struct sched_param *param)
266{
sewardj436e0582002-04-26 14:31:40 +0000267 static int moans = N_MOANS;
268 if (moans-- > 0)
269 kludged("pthread_attr_getschedparam");
sewardj3e909ce2002-06-03 13:27:15 +0000270# ifdef HAVE_SCHED_PRIORITY
sewardj72d58482002-04-24 02:20:20 +0000271 if (param) param->sched_priority = 0; /* who knows */
272# else
sewardj30671ff2002-04-21 00:13:57 +0000273 if (param) param->__sched_priority = 0; /* who knows */
sewardj72d58482002-04-24 02:20:20 +0000274# endif
sewardj30671ff2002-04-21 00:13:57 +0000275 return 0;
276}
277
278int pthread_attr_setschedparam(pthread_attr_t *attr,
279 const struct sched_param *param)
280{
sewardj436e0582002-04-26 14:31:40 +0000281 static int moans = N_MOANS;
282 if (moans-- > 0)
283 ignored("pthread_attr_setschedparam");
sewardj30671ff2002-04-21 00:13:57 +0000284 return 0;
285}
286
287int pthread_attr_destroy(pthread_attr_t *attr)
288{
sewardj436e0582002-04-26 14:31:40 +0000289 static int moans = N_MOANS;
290 if (moans-- > 0)
291 ignored("pthread_attr_destroy");
sewardj30671ff2002-04-21 00:13:57 +0000292 return 0;
293}
sewardjf8f819e2002-04-17 23:21:37 +0000294
sewardj0d844232002-06-02 09:29:31 +0000295/* These are no-ops, as with LinuxThreads. */
296int pthread_attr_setscope ( pthread_attr_t *attr, int scope )
297{
298 ensure_valgrind("pthread_attr_setscope");
299 if (scope == PTHREAD_SCOPE_SYSTEM)
300 return 0;
301 if (scope == PTHREAD_SCOPE_PROCESS)
302 return ENOTSUP;
303 return EINVAL;
304}
305
306int pthread_attr_getscope ( const pthread_attr_t *attr, int *scope )
307{
308 ensure_valgrind("pthread_attr_setscope");
309 if (scope)
310 *scope = PTHREAD_SCOPE_SYSTEM;
311 return 0;
312}
313
sewardj64039bb2002-06-03 00:58:18 +0000314
315/* Pretty bogus. Avoid if possible. */
316int pthread_getattr_np (pthread_t thread, pthread_attr_t *attr)
317{
318 int detached;
319 size_t limit;
320 ensure_valgrind("pthread_getattr_np");
321 kludged("pthread_getattr_np");
322 limit = VG_PTHREAD_STACK_SIZE - VG_AR_CLIENT_STACKBASE_REDZONE_SZB
323 - 1000; /* paranoia */
324 attr->__detachstate = PTHREAD_CREATE_JOINABLE;
325 attr->__schedpolicy = SCHED_OTHER;
326 attr->__schedparam.sched_priority = 0;
327 attr->__inheritsched = PTHREAD_EXPLICIT_SCHED;
328 attr->__scope = PTHREAD_SCOPE_SYSTEM;
329 attr->__guardsize = VKI_BYTES_PER_PAGE;
330 attr->__stackaddr = NULL;
331 attr->__stackaddr_set = 0;
332 attr->__stacksize = limit;
333 VALGRIND_MAGIC_SEQUENCE(detached, (-1) /* default */,
334 VG_USERREQ__SET_OR_GET_DETACH,
335 2 /* get */, thread, 0, 0);
sewardj2d94c112002-06-03 01:25:54 +0000336 my_assert(detached == 0 || detached == 1);
sewardj64039bb2002-06-03 00:58:18 +0000337 if (detached)
338 attr->__detachstate = PTHREAD_CREATE_DETACHED;
339 return 0;
340}
341
342
343/* Bogus ... */
344int pthread_attr_getstackaddr ( const pthread_attr_t * attr,
345 void ** stackaddr )
346{
347 ensure_valgrind("pthread_attr_getstackaddr");
348 kludged("pthread_attr_getstackaddr");
349 if (stackaddr)
350 *stackaddr = NULL;
351 return 0;
352}
353
354/* Not bogus (!) */
355int pthread_attr_getstacksize ( const pthread_attr_t * _attr,
356 size_t * __stacksize )
357{
358 size_t limit;
359 ensure_valgrind("pthread_attr_getstacksize");
360 limit = VG_PTHREAD_STACK_SIZE - VG_AR_CLIENT_STACKBASE_REDZONE_SZB
361 - 1000; /* paranoia */
362 if (__stacksize)
363 *__stacksize = limit;
364 return 0;
365}
366
sewardj20917d82002-05-28 01:36:45 +0000367/* ---------------------------------------------------
368 Helper functions for running a thread
369 and for clearing up afterwards.
370 ------------------------------------------------ */
371
372/* All exiting threads eventually pass through here, bearing the
373 return value, or PTHREAD_CANCELED, in ret_val. */
374static
375__attribute__((noreturn))
376void thread_exit_wrapper ( void* ret_val )
377{
sewardj870497a2002-05-29 01:06:47 +0000378 int detached, res;
379 CleanupEntry cu;
380 pthread_key_t key;
381
sewardj20917d82002-05-28 01:36:45 +0000382 /* Run this thread's cleanup handlers. */
sewardj8ad94e12002-05-29 00:10:20 +0000383 while (1) {
384 VALGRIND_MAGIC_SEQUENCE(res, (-1) /* default */,
385 VG_USERREQ__CLEANUP_POP,
386 &cu, 0, 0, 0);
387 if (res == -1) break; /* stack empty */
sewardj2d94c112002-06-03 01:25:54 +0000388 my_assert(res == 0);
sewardj8ad94e12002-05-29 00:10:20 +0000389 if (0) printf("running exit cleanup handler");
390 cu.fn ( cu.arg );
391 }
392
sewardj870497a2002-05-29 01:06:47 +0000393 /* Run this thread's key finalizers. Really this should be run
394 PTHREAD_DESTRUCTOR_ITERATIONS times. */
395 for (key = 0; key < VG_N_THREAD_KEYS; key++) {
396 VALGRIND_MAGIC_SEQUENCE(res, (-2) /* default */,
397 VG_USERREQ__GET_KEY_D_AND_S,
398 key, &cu, 0, 0 );
399 if (res == 0) {
400 /* valid key */
401 if (cu.fn && cu.arg)
402 cu.fn /* destructor for key */
403 ( cu.arg /* specific for key for this thread */ );
404 continue;
405 }
sewardj2d94c112002-06-03 01:25:54 +0000406 my_assert(res == -1);
sewardj870497a2002-05-29 01:06:47 +0000407 }
sewardj20917d82002-05-28 01:36:45 +0000408
409 /* Decide on my final disposition. */
410 VALGRIND_MAGIC_SEQUENCE(detached, (-1) /* default */,
411 VG_USERREQ__SET_OR_GET_DETACH,
sewardj7989d0c2002-05-28 11:00:01 +0000412 2 /* get */, pthread_self(), 0, 0);
sewardj2d94c112002-06-03 01:25:54 +0000413 my_assert(detached == 0 || detached == 1);
sewardj20917d82002-05-28 01:36:45 +0000414
415 if (detached) {
416 /* Detached; I just quit right now. */
417 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
418 VG_USERREQ__QUIT, 0, 0, 0, 0);
419 } else {
420 /* Not detached; so I wait for a joiner. */
421 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
422 VG_USERREQ__WAIT_JOINER, ret_val, 0, 0, 0);
423 }
424 /* NOTREACHED */
425 barf("thread_exit_wrapper: still alive?!");
426}
427
428
429/* This function is a wrapper function for running a thread. It runs
430 the root function specified in pthread_create, and then, should the
431 root function return a value, it arranges to run the thread's
432 cleanup handlers and exit correctly. */
433
434/* Struct used to convey info from pthread_create to
435 thread_wrapper. */
436typedef
437 struct {
438 pthread_attr_t* attr;
439 void* (*root_fn) ( void* );
440 void* arg;
441 }
442 NewThreadInfo;
443
444
445/* This is passed to the VG_USERREQ__APPLY_IN_NEW_THREAD and so must
446 not return. Note that this runs in the new thread, not the
447 parent. */
448static
449__attribute__((noreturn))
450void thread_wrapper ( NewThreadInfo* info )
451{
452 int res;
453 pthread_attr_t* attr;
454 void* (*root_fn) ( void* );
455 void* arg;
456 void* ret_val;
457
458 attr = info->attr;
459 root_fn = info->root_fn;
460 arg = info->arg;
461
sewardj20917d82002-05-28 01:36:45 +0000462 /* Free up the arg block that pthread_create malloced. */
463 VALGRIND_MAGIC_SEQUENCE(res, (-1) /* default */,
464 VG_USERREQ__FREE, info, 0, 0, 0);
sewardj2d94c112002-06-03 01:25:54 +0000465 my_assert(res == 0);
sewardj20917d82002-05-28 01:36:45 +0000466
sewardj7989d0c2002-05-28 11:00:01 +0000467 /* Minimally observe the attributes supplied. */
468 if (attr) {
sewardj2d94c112002-06-03 01:25:54 +0000469 my_assert(attr->__detachstate == PTHREAD_CREATE_DETACHED
sewardj7989d0c2002-05-28 11:00:01 +0000470 || attr->__detachstate == PTHREAD_CREATE_JOINABLE);
471 if (attr->__detachstate == PTHREAD_CREATE_DETACHED)
472 pthread_detach(pthread_self());
473 }
474
sewardj20917d82002-05-28 01:36:45 +0000475 /* The root function might not return. But if it does we simply
476 move along to thread_exit_wrapper. All other ways out for the
477 thread (cancellation, or calling pthread_exit) lead there
478 too. */
479 ret_val = root_fn(arg);
480 thread_exit_wrapper(ret_val);
481 /* NOTREACHED */
482}
483
484
sewardjf8f819e2002-04-17 23:21:37 +0000485/* ---------------------------------------------------
486 THREADs
487 ------------------------------------------------ */
488
sewardjff42d1d2002-05-22 13:17:31 +0000489__attribute__((weak))
490int pthread_yield ( void )
491{
492 int res;
493 ensure_valgrind("pthread_yield");
494 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
495 VG_USERREQ__PTHREAD_YIELD, 0, 0, 0, 0);
496 return 0;
497}
498
499
sewardj6072c362002-04-19 14:40:57 +0000500int pthread_equal(pthread_t thread1, pthread_t thread2)
501{
502 return thread1 == thread2 ? 1 : 0;
503}
504
505
sewardj20917d82002-05-28 01:36:45 +0000506/* Bundle up the args into a malloc'd block and create a new thread
507 consisting of thread_wrapper() applied to said malloc'd block. */
sewardje663cb92002-04-12 10:26:32 +0000508int
509pthread_create (pthread_t *__restrict __thread,
510 __const pthread_attr_t *__restrict __attr,
511 void *(*__start_routine) (void *),
512 void *__restrict __arg)
513{
sewardj20917d82002-05-28 01:36:45 +0000514 int tid_child;
515 NewThreadInfo* info;
sewardje663cb92002-04-12 10:26:32 +0000516
sewardj20917d82002-05-28 01:36:45 +0000517 ensure_valgrind("pthread_create");
518
519 /* Allocate space for the arg block. thread_wrapper will free
520 it. */
521 VALGRIND_MAGIC_SEQUENCE(info, NULL /* default */,
522 VG_USERREQ__MALLOC,
523 sizeof(NewThreadInfo), 0, 0, 0);
sewardj2d94c112002-06-03 01:25:54 +0000524 my_assert(info != NULL);
sewardj20917d82002-05-28 01:36:45 +0000525
526 info->attr = (pthread_attr_t*)__attr;
527 info->root_fn = __start_routine;
528 info->arg = __arg;
529 VALGRIND_MAGIC_SEQUENCE(tid_child, VG_INVALID_THREADID /* default */,
530 VG_USERREQ__APPLY_IN_NEW_THREAD,
531 &thread_wrapper, info, 0, 0);
sewardj2d94c112002-06-03 01:25:54 +0000532 my_assert(tid_child != VG_INVALID_THREADID);
sewardj20917d82002-05-28 01:36:45 +0000533
534 if (__thread)
535 *__thread = tid_child;
536 return 0; /* success */
537}
sewardje663cb92002-04-12 10:26:32 +0000538
539
540int
541pthread_join (pthread_t __th, void **__thread_return)
542{
543 int res;
544 ensure_valgrind("pthread_join");
545 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
546 VG_USERREQ__PTHREAD_JOIN,
547 __th, __thread_return, 0, 0);
548 return res;
549}
550
551
sewardj3b5d8862002-04-20 13:53:23 +0000552void pthread_exit(void *retval)
553{
sewardj3b5d8862002-04-20 13:53:23 +0000554 ensure_valgrind("pthread_exit");
sewardj20917d82002-05-28 01:36:45 +0000555 /* Simple! */
556 thread_exit_wrapper(retval);
sewardj3b5d8862002-04-20 13:53:23 +0000557}
558
sewardje663cb92002-04-12 10:26:32 +0000559
sewardj3b13f0e2002-04-25 20:17:29 +0000560pthread_t pthread_self(void)
sewardje663cb92002-04-12 10:26:32 +0000561{
562 int tid;
sewardj3b13f0e2002-04-25 20:17:29 +0000563 ensure_valgrind("pthread_self");
sewardj439d45e2002-05-03 20:43:10 +0000564 VALGRIND_MAGIC_SEQUENCE(tid, 1 /* default */,
sewardje663cb92002-04-12 10:26:32 +0000565 VG_USERREQ__PTHREAD_GET_THREADID,
566 0, 0, 0, 0);
sewardj439d45e2002-05-03 20:43:10 +0000567 if (tid < 1 || tid >= VG_N_THREADS)
sewardj3b13f0e2002-04-25 20:17:29 +0000568 barf("pthread_self: invalid ThreadId");
569 return tid;
sewardje663cb92002-04-12 10:26:32 +0000570}
571
572
sewardj853f55d2002-04-26 00:27:53 +0000573int pthread_detach(pthread_t th)
574{
sewardj20917d82002-05-28 01:36:45 +0000575 int res;
576 ensure_valgrind("pthread_detach");
sewardj7989d0c2002-05-28 11:00:01 +0000577 /* First we enquire as to the current detach state. */
578 VALGRIND_MAGIC_SEQUENCE(res, (-2) /* default */,
sewardj20917d82002-05-28 01:36:45 +0000579 VG_USERREQ__SET_OR_GET_DETACH,
sewardj7989d0c2002-05-28 11:00:01 +0000580 2 /* get */, th, 0, 0);
581 if (res == -1) /* not found */
582 return ESRCH;
583 if (res == 1) /* already detached */
584 return EINVAL;
585 if (res == 0) {
586 VALGRIND_MAGIC_SEQUENCE(res, (-2) /* default */,
587 VG_USERREQ__SET_OR_GET_DETACH,
588 1 /* set */, th, 0, 0);
sewardj2d94c112002-06-03 01:25:54 +0000589 my_assert(res == 0);
sewardj7989d0c2002-05-28 11:00:01 +0000590 return 0;
591 }
592 barf("pthread_detach");
sewardj853f55d2002-04-26 00:27:53 +0000593}
594
595
sewardjf8f819e2002-04-17 23:21:37 +0000596/* ---------------------------------------------------
sewardj8ad94e12002-05-29 00:10:20 +0000597 CLEANUP STACKS
598 ------------------------------------------------ */
599
600void _pthread_cleanup_push (struct _pthread_cleanup_buffer *__buffer,
601 void (*__routine) (void *),
602 void *__arg)
603{
604 int res;
605 CleanupEntry cu;
606 ensure_valgrind("_pthread_cleanup_push");
607 cu.fn = __routine;
608 cu.arg = __arg;
609 VALGRIND_MAGIC_SEQUENCE(res, (-1) /* default */,
610 VG_USERREQ__CLEANUP_PUSH,
611 &cu, 0, 0, 0);
sewardj2d94c112002-06-03 01:25:54 +0000612 my_assert(res == 0);
sewardj8ad94e12002-05-29 00:10:20 +0000613}
614
615
616void _pthread_cleanup_push_defer (struct _pthread_cleanup_buffer *__buffer,
617 void (*__routine) (void *),
618 void *__arg)
619{
620 /* As _pthread_cleanup_push, but first save the thread's original
621 cancellation type in __buffer and set it to Deferred. */
622 int orig_ctype;
623 ensure_valgrind("_pthread_cleanup_push_defer");
624 /* Set to Deferred, and put the old cancellation type in res. */
sewardj2d94c112002-06-03 01:25:54 +0000625 my_assert(-1 != PTHREAD_CANCEL_DEFERRED);
626 my_assert(-1 != PTHREAD_CANCEL_ASYNCHRONOUS);
627 my_assert(sizeof(struct _pthread_cleanup_buffer) >= sizeof(int));
sewardj8ad94e12002-05-29 00:10:20 +0000628 VALGRIND_MAGIC_SEQUENCE(orig_ctype, (-1) /* default */,
629 VG_USERREQ__SET_CANCELTYPE,
630 PTHREAD_CANCEL_DEFERRED, 0, 0, 0);
sewardj2d94c112002-06-03 01:25:54 +0000631 my_assert(orig_ctype != -1);
sewardj8ad94e12002-05-29 00:10:20 +0000632 *((int*)(__buffer)) = orig_ctype;
633 /* Now push the cleanup. */
634 _pthread_cleanup_push(NULL, __routine, __arg);
635}
636
637
638void _pthread_cleanup_pop (struct _pthread_cleanup_buffer *__buffer,
639 int __execute)
640{
641 int res;
642 CleanupEntry cu;
643 ensure_valgrind("_pthread_cleanup_push");
644 cu.fn = cu.arg = NULL; /* paranoia */
645 VALGRIND_MAGIC_SEQUENCE(res, (-1) /* default */,
646 VG_USERREQ__CLEANUP_POP,
647 &cu, 0, 0, 0);
648 if (res == 0) {
649 /* pop succeeded */
650 if (__execute) {
651 cu.fn ( cu.arg );
652 }
653 return;
654 }
655 if (res == -1) {
656 /* stack underflow */
657 return;
658 }
659 barf("_pthread_cleanup_pop");
660}
661
662
663void _pthread_cleanup_pop_restore (struct _pthread_cleanup_buffer *__buffer,
664 int __execute)
665{
666 int orig_ctype, fake_ctype;
667 /* As _pthread_cleanup_pop, but after popping/running the handler,
668 restore the thread's original cancellation type from the first
669 word of __buffer. */
670 _pthread_cleanup_pop(NULL, __execute);
671 orig_ctype = *((int*)(__buffer));
sewardj2d94c112002-06-03 01:25:54 +0000672 my_assert(orig_ctype == PTHREAD_CANCEL_DEFERRED
sewardj8ad94e12002-05-29 00:10:20 +0000673 || orig_ctype == PTHREAD_CANCEL_ASYNCHRONOUS);
sewardj2d94c112002-06-03 01:25:54 +0000674 my_assert(-1 != PTHREAD_CANCEL_DEFERRED);
675 my_assert(-1 != PTHREAD_CANCEL_ASYNCHRONOUS);
676 my_assert(sizeof(struct _pthread_cleanup_buffer) >= sizeof(int));
sewardj8ad94e12002-05-29 00:10:20 +0000677 VALGRIND_MAGIC_SEQUENCE(fake_ctype, (-1) /* default */,
678 VG_USERREQ__SET_CANCELTYPE,
679 orig_ctype, 0, 0, 0);
sewardj2d94c112002-06-03 01:25:54 +0000680 my_assert(fake_ctype == PTHREAD_CANCEL_DEFERRED);
sewardj8ad94e12002-05-29 00:10:20 +0000681}
682
683
684/* ---------------------------------------------------
sewardjf8f819e2002-04-17 23:21:37 +0000685 MUTEX ATTRIBUTES
686 ------------------------------------------------ */
687
sewardj5905fae2002-04-26 13:25:00 +0000688int __pthread_mutexattr_init(pthread_mutexattr_t *attr)
sewardje663cb92002-04-12 10:26:32 +0000689{
sewardjf8f819e2002-04-17 23:21:37 +0000690 attr->__mutexkind = PTHREAD_MUTEX_ERRORCHECK_NP;
sewardj8937c812002-04-12 20:12:20 +0000691 return 0;
sewardje663cb92002-04-12 10:26:32 +0000692}
693
sewardj5905fae2002-04-26 13:25:00 +0000694int __pthread_mutexattr_settype(pthread_mutexattr_t *attr, int type)
sewardjf8f819e2002-04-17 23:21:37 +0000695{
696 switch (type) {
sewardj3b13f0e2002-04-25 20:17:29 +0000697# ifndef GLIBC_2_1
sewardjf8f819e2002-04-17 23:21:37 +0000698 case PTHREAD_MUTEX_TIMED_NP:
sewardj2a1dcce2002-04-22 12:45:25 +0000699 case PTHREAD_MUTEX_ADAPTIVE_NP:
sewardj3b13f0e2002-04-25 20:17:29 +0000700# endif
sewardja1679dd2002-05-10 22:31:40 +0000701# ifdef GLIBC_2_1
sewardj68b2dd92002-05-10 21:03:56 +0000702 case PTHREAD_MUTEX_FAST_NP:
sewardja1679dd2002-05-10 22:31:40 +0000703# endif
sewardjf8f819e2002-04-17 23:21:37 +0000704 case PTHREAD_MUTEX_RECURSIVE_NP:
705 case PTHREAD_MUTEX_ERRORCHECK_NP:
sewardjf8f819e2002-04-17 23:21:37 +0000706 attr->__mutexkind = type;
707 return 0;
708 default:
709 return EINVAL;
710 }
711}
712
sewardj5905fae2002-04-26 13:25:00 +0000713int __pthread_mutexattr_destroy(pthread_mutexattr_t *attr)
sewardjf8f819e2002-04-17 23:21:37 +0000714{
715 return 0;
716}
717
718
719/* ---------------------------------------------------
720 MUTEXes
721 ------------------------------------------------ */
722
sewardj5905fae2002-04-26 13:25:00 +0000723int __pthread_mutex_init(pthread_mutex_t *mutex,
724 const pthread_mutexattr_t *mutexattr)
sewardje663cb92002-04-12 10:26:32 +0000725{
sewardj604ec3c2002-04-18 22:38:41 +0000726 mutex->__m_count = 0;
727 mutex->__m_owner = (_pthread_descr)VG_INVALID_THREADID;
728 mutex->__m_kind = PTHREAD_MUTEX_ERRORCHECK_NP;
729 if (mutexattr)
730 mutex->__m_kind = mutexattr->__mutexkind;
731 return 0;
sewardje663cb92002-04-12 10:26:32 +0000732}
733
sewardj439d45e2002-05-03 20:43:10 +0000734
sewardj5905fae2002-04-26 13:25:00 +0000735int __pthread_mutex_lock(pthread_mutex_t *mutex)
sewardje663cb92002-04-12 10:26:32 +0000736{
737 int res;
sewardj436e0582002-04-26 14:31:40 +0000738 static int moans = N_MOANS;
sewardj439d45e2002-05-03 20:43:10 +0000739 if (RUNNING_ON_VALGRIND) {
sewardje663cb92002-04-12 10:26:32 +0000740 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
741 VG_USERREQ__PTHREAD_MUTEX_LOCK,
742 mutex, 0, 0, 0);
743 return res;
sewardj439d45e2002-05-03 20:43:10 +0000744 } else {
745 if (moans-- > 0)
746 not_inside("pthread_mutex_lock");
747 return 0; /* success */
sewardje663cb92002-04-12 10:26:32 +0000748 }
749}
750
sewardj439d45e2002-05-03 20:43:10 +0000751
sewardj5905fae2002-04-26 13:25:00 +0000752int __pthread_mutex_trylock(pthread_mutex_t *mutex)
sewardj30671ff2002-04-21 00:13:57 +0000753{
754 int res;
sewardj436e0582002-04-26 14:31:40 +0000755 static int moans = N_MOANS;
sewardj439d45e2002-05-03 20:43:10 +0000756 if (RUNNING_ON_VALGRIND) {
sewardj30671ff2002-04-21 00:13:57 +0000757 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
758 VG_USERREQ__PTHREAD_MUTEX_TRYLOCK,
759 mutex, 0, 0, 0);
760 return res;
sewardj439d45e2002-05-03 20:43:10 +0000761 } else {
762 if (moans-- > 0)
763 not_inside("pthread_mutex_trylock");
764 return 0;
sewardj30671ff2002-04-21 00:13:57 +0000765 }
766}
767
sewardj439d45e2002-05-03 20:43:10 +0000768
sewardj5905fae2002-04-26 13:25:00 +0000769int __pthread_mutex_unlock(pthread_mutex_t *mutex)
sewardje663cb92002-04-12 10:26:32 +0000770{
771 int res;
sewardj436e0582002-04-26 14:31:40 +0000772 static int moans = N_MOANS;
sewardj439d45e2002-05-03 20:43:10 +0000773 if (RUNNING_ON_VALGRIND) {
sewardje663cb92002-04-12 10:26:32 +0000774 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
775 VG_USERREQ__PTHREAD_MUTEX_UNLOCK,
776 mutex, 0, 0, 0);
777 return res;
sewardj439d45e2002-05-03 20:43:10 +0000778 } else {
779 if (moans-- > 0)
780 not_inside("pthread_mutex_unlock");
781 return 0;
sewardje663cb92002-04-12 10:26:32 +0000782 }
783}
784
sewardj439d45e2002-05-03 20:43:10 +0000785
sewardj5905fae2002-04-26 13:25:00 +0000786int __pthread_mutex_destroy(pthread_mutex_t *mutex)
sewardje663cb92002-04-12 10:26:32 +0000787{
sewardj604ec3c2002-04-18 22:38:41 +0000788 /* Valgrind doesn't hold any resources on behalf of the mutex, so no
789 need to involve it. */
790 if (mutex->__m_count > 0)
791 return EBUSY;
sewardj6072c362002-04-19 14:40:57 +0000792 mutex->__m_count = 0;
793 mutex->__m_owner = (_pthread_descr)VG_INVALID_THREADID;
794 mutex->__m_kind = PTHREAD_MUTEX_ERRORCHECK_NP;
sewardj604ec3c2002-04-18 22:38:41 +0000795 return 0;
sewardje663cb92002-04-12 10:26:32 +0000796}
797
798
sewardjf8f819e2002-04-17 23:21:37 +0000799/* ---------------------------------------------------
sewardj6072c362002-04-19 14:40:57 +0000800 CONDITION VARIABLES
801 ------------------------------------------------ */
802
803/* LinuxThreads supports no attributes for conditions. Hence ... */
804
805int pthread_condattr_init(pthread_condattr_t *attr)
806{
807 return 0;
808}
809
sewardj0738a592002-04-20 13:59:33 +0000810int pthread_condattr_destroy(pthread_condattr_t *attr)
811{
812 return 0;
813}
sewardj6072c362002-04-19 14:40:57 +0000814
815int pthread_cond_init( pthread_cond_t *cond,
816 const pthread_condattr_t *cond_attr)
817{
818 cond->__c_waiting = (_pthread_descr)VG_INVALID_THREADID;
819 return 0;
820}
821
sewardjf854f472002-04-21 12:19:41 +0000822int pthread_cond_destroy(pthread_cond_t *cond)
823{
824 /* should check that no threads are waiting on this CV */
sewardj436e0582002-04-26 14:31:40 +0000825 static int moans = N_MOANS;
826 if (moans-- > 0)
827 kludged("pthread_cond_destroy");
sewardjf854f472002-04-21 12:19:41 +0000828 return 0;
829}
sewardj6072c362002-04-19 14:40:57 +0000830
831/* ---------------------------------------------------
832 SCHEDULING
833 ------------------------------------------------ */
834
835/* This is completely bogus. */
836int pthread_getschedparam(pthread_t target_thread,
837 int *policy,
838 struct sched_param *param)
839{
sewardj436e0582002-04-26 14:31:40 +0000840 static int moans = N_MOANS;
841 if (moans-- > 0)
842 kludged("pthread_getschedparam");
sewardj6072c362002-04-19 14:40:57 +0000843 if (policy) *policy = SCHED_OTHER;
sewardj3e909ce2002-06-03 13:27:15 +0000844# ifdef HAVE_SCHED_PRIORITY
sewardj2a1dcce2002-04-22 12:45:25 +0000845 if (param) param->sched_priority = 0; /* who knows */
846# else
sewardj6072c362002-04-19 14:40:57 +0000847 if (param) param->__sched_priority = 0; /* who knows */
sewardj2a1dcce2002-04-22 12:45:25 +0000848# endif
sewardj6072c362002-04-19 14:40:57 +0000849 return 0;
850}
851
852int pthread_setschedparam(pthread_t target_thread,
853 int policy,
854 const struct sched_param *param)
855{
sewardj436e0582002-04-26 14:31:40 +0000856 static int moans = N_MOANS;
857 if (moans-- > 0)
858 ignored("pthread_setschedparam");
sewardj6072c362002-04-19 14:40:57 +0000859 return 0;
860}
861
sewardj3b5d8862002-04-20 13:53:23 +0000862int pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex)
863{
864 int res;
865 ensure_valgrind("pthread_cond_wait");
866 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
867 VG_USERREQ__PTHREAD_COND_WAIT,
868 cond, mutex, 0, 0);
869 return res;
870}
871
sewardj5f07b662002-04-23 16:52:51 +0000872int pthread_cond_timedwait ( pthread_cond_t *cond,
873 pthread_mutex_t *mutex,
874 const struct timespec *abstime )
875{
876 int res;
877 unsigned int ms_now, ms_end;
878 struct timeval timeval_now;
879 unsigned long long int ull_ms_now_after_1970;
880 unsigned long long int ull_ms_end_after_1970;
881
882 ensure_valgrind("pthread_cond_timedwait");
883 VALGRIND_MAGIC_SEQUENCE(ms_now, 0xFFFFFFFF /* default */,
884 VG_USERREQ__READ_MILLISECOND_TIMER,
885 0, 0, 0, 0);
sewardj2d94c112002-06-03 01:25:54 +0000886 my_assert(ms_now != 0xFFFFFFFF);
sewardj5f07b662002-04-23 16:52:51 +0000887 res = gettimeofday(&timeval_now, NULL);
sewardj2d94c112002-06-03 01:25:54 +0000888 my_assert(res == 0);
sewardj5f07b662002-04-23 16:52:51 +0000889
890 ull_ms_now_after_1970
891 = 1000ULL * ((unsigned long long int)(timeval_now.tv_sec))
892 + ((unsigned long long int)(timeval_now.tv_usec / 1000000));
893 ull_ms_end_after_1970
894 = 1000ULL * ((unsigned long long int)(abstime->tv_sec))
895 + ((unsigned long long int)(abstime->tv_nsec / 1000000));
sewardjd8e919e2002-05-29 20:13:53 +0000896 if (ull_ms_end_after_1970 < ull_ms_now_after_1970)
897 ull_ms_end_after_1970 = ull_ms_now_after_1970;
sewardj5f07b662002-04-23 16:52:51 +0000898 ms_end
899 = ms_now + (unsigned int)(ull_ms_end_after_1970 - ull_ms_now_after_1970);
900 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
901 VG_USERREQ__PTHREAD_COND_TIMEDWAIT,
902 cond, mutex, ms_end, 0);
903 return res;
904}
905
906
sewardj3b5d8862002-04-20 13:53:23 +0000907int pthread_cond_signal(pthread_cond_t *cond)
908{
909 int res;
910 ensure_valgrind("pthread_cond_signal");
911 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
912 VG_USERREQ__PTHREAD_COND_SIGNAL,
913 cond, 0, 0, 0);
914 return res;
915}
916
917int pthread_cond_broadcast(pthread_cond_t *cond)
918{
919 int res;
920 ensure_valgrind("pthread_cond_broadcast");
921 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
922 VG_USERREQ__PTHREAD_COND_BROADCAST,
923 cond, 0, 0, 0);
924 return res;
925}
926
sewardj6072c362002-04-19 14:40:57 +0000927
928/* ---------------------------------------------------
sewardjf8f819e2002-04-17 23:21:37 +0000929 CANCELLATION
930 ------------------------------------------------ */
931
sewardj853f55d2002-04-26 00:27:53 +0000932int pthread_setcancelstate(int state, int *oldstate)
933{
sewardj20917d82002-05-28 01:36:45 +0000934 int res;
935 ensure_valgrind("pthread_setcancelstate");
936 if (state != PTHREAD_CANCEL_ENABLE
937 && state != PTHREAD_CANCEL_DISABLE)
938 return EINVAL;
sewardj2d94c112002-06-03 01:25:54 +0000939 my_assert(-1 != PTHREAD_CANCEL_ENABLE);
940 my_assert(-1 != PTHREAD_CANCEL_DISABLE);
sewardj20917d82002-05-28 01:36:45 +0000941 VALGRIND_MAGIC_SEQUENCE(res, (-1) /* default */,
942 VG_USERREQ__SET_CANCELSTATE,
943 state, 0, 0, 0);
sewardj2d94c112002-06-03 01:25:54 +0000944 my_assert(res != -1);
sewardj20917d82002-05-28 01:36:45 +0000945 if (oldstate)
946 *oldstate = res;
sewardj853f55d2002-04-26 00:27:53 +0000947 return 0;
948}
949
sewardje663cb92002-04-12 10:26:32 +0000950int pthread_setcanceltype(int type, int *oldtype)
951{
sewardj20917d82002-05-28 01:36:45 +0000952 int res;
953 ensure_valgrind("pthread_setcanceltype");
954 if (type != PTHREAD_CANCEL_DEFERRED
955 && type != PTHREAD_CANCEL_ASYNCHRONOUS)
956 return EINVAL;
sewardj2d94c112002-06-03 01:25:54 +0000957 my_assert(-1 != PTHREAD_CANCEL_DEFERRED);
958 my_assert(-1 != PTHREAD_CANCEL_ASYNCHRONOUS);
sewardj20917d82002-05-28 01:36:45 +0000959 VALGRIND_MAGIC_SEQUENCE(res, (-1) /* default */,
960 VG_USERREQ__SET_CANCELTYPE,
961 type, 0, 0, 0);
sewardj2d94c112002-06-03 01:25:54 +0000962 my_assert(res != -1);
sewardj20917d82002-05-28 01:36:45 +0000963 if (oldtype)
964 *oldtype = res;
sewardje663cb92002-04-12 10:26:32 +0000965 return 0;
966}
967
sewardje663cb92002-04-12 10:26:32 +0000968int pthread_cancel(pthread_t thread)
969{
970 int res;
971 ensure_valgrind("pthread_cancel");
sewardj20917d82002-05-28 01:36:45 +0000972 VALGRIND_MAGIC_SEQUENCE(res, (-1) /* default */,
973 VG_USERREQ__SET_CANCELPEND,
974 thread, &thread_exit_wrapper, 0, 0);
sewardj2d94c112002-06-03 01:25:54 +0000975 my_assert(res != -1);
sewardje663cb92002-04-12 10:26:32 +0000976 return res;
977}
978
sewardjd140e442002-05-29 01:21:19 +0000979static __inline__
980void __my_pthread_testcancel(void)
sewardj853f55d2002-04-26 00:27:53 +0000981{
sewardj20917d82002-05-28 01:36:45 +0000982 int res;
983 VALGRIND_MAGIC_SEQUENCE(res, (-1) /* default */,
984 VG_USERREQ__TESTCANCEL,
985 0, 0, 0, 0);
sewardj2d94c112002-06-03 01:25:54 +0000986 my_assert(res == 0);
sewardj853f55d2002-04-26 00:27:53 +0000987}
988
sewardjd140e442002-05-29 01:21:19 +0000989void pthread_testcancel ( void )
990{
991 __my_pthread_testcancel();
992}
993
sewardj20917d82002-05-28 01:36:45 +0000994
sewardjef037c72002-05-30 00:40:03 +0000995/* Not really sure what this is for. I suspect for doing the POSIX
996 requirements for fork() and exec(). We do this internally anyway
997 whenever those syscalls are observed, so this could be superfluous,
998 but hey ...
999*/
sewardj853f55d2002-04-26 00:27:53 +00001000void __pthread_kill_other_threads_np ( void )
1001{
sewardjef037c72002-05-30 00:40:03 +00001002 int res;
1003 ensure_valgrind("__pthread_kill_other_threads_np");
1004 VALGRIND_MAGIC_SEQUENCE(res, (-1) /* default */,
1005 VG_USERREQ__NUKE_OTHER_THREADS,
1006 0, 0, 0, 0);
sewardj2d94c112002-06-03 01:25:54 +00001007 my_assert(res == 0);
sewardj853f55d2002-04-26 00:27:53 +00001008}
1009
sewardje663cb92002-04-12 10:26:32 +00001010
sewardjf8f819e2002-04-17 23:21:37 +00001011/* ---------------------------------------------------
sewardjb48e5002002-05-13 00:16:03 +00001012 SIGNALS
1013 ------------------------------------------------ */
1014
1015#include <signal.h>
1016
1017int pthread_sigmask(int how, const sigset_t *newmask,
1018 sigset_t *oldmask)
1019{
1020 int res;
1021
1022 /* A bit subtle, because the scheduler expects newmask and oldmask
1023 to be vki_sigset_t* rather than sigset_t*, and the two are
1024 different. Fortunately the first 64 bits of a sigset_t are
1025 exactly a vki_sigset_t, so we just pass the pointers through
1026 unmodified. Haaaack!
1027
1028 Also mash the how value so that the SIG_ constants from glibc
sewardj018f7622002-05-15 21:13:39 +00001029 constants to VKI_ constants, so that the former do not have to
1030 be included into vg_scheduler.c. */
sewardjb48e5002002-05-13 00:16:03 +00001031
1032 ensure_valgrind("pthread_sigmask");
1033
1034 switch (how) {
sewardj018f7622002-05-15 21:13:39 +00001035 case SIG_SETMASK: how = VKI_SIG_SETMASK; break;
1036 case SIG_BLOCK: how = VKI_SIG_BLOCK; break;
1037 case SIG_UNBLOCK: how = VKI_SIG_UNBLOCK; break;
sewardjb48e5002002-05-13 00:16:03 +00001038 default: return EINVAL;
1039 }
1040
1041 /* Crude check */
1042 if (newmask == NULL)
1043 return EFAULT;
1044
1045 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
1046 VG_USERREQ__PTHREAD_SIGMASK,
1047 how, newmask, oldmask, 0);
1048
1049 /* The scheduler tells us of any memory violations. */
1050 return res == 0 ? 0 : EFAULT;
1051}
1052
1053
1054int sigwait ( const sigset_t* set, int* sig )
1055{
1056 int res;
1057 ensure_valgrind("sigwait");
1058 /* As with pthread_sigmask we deliberately confuse sigset_t with
1059 vki_ksigset_t. */
1060 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
1061 VG_USERREQ__SIGWAIT,
1062 set, sig, 0, 0);
1063 return res;
1064}
1065
1066
sewardj018f7622002-05-15 21:13:39 +00001067int pthread_kill(pthread_t thread, int signo)
1068{
1069 int res;
1070 ensure_valgrind("pthread_kill");
1071 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
1072 VG_USERREQ__PTHREAD_KILL,
1073 thread, signo, 0, 0);
1074 return res;
1075}
1076
1077
sewardj3665ded2002-05-16 16:57:25 +00001078/* Copied verbatim from Linuxthreads */
1079/* Redefine raise() to send signal to calling thread only,
1080 as per POSIX 1003.1c */
1081int raise (int sig)
1082{
1083 int retcode = pthread_kill(pthread_self(), sig);
1084 if (retcode == 0)
1085 return 0;
1086 else {
1087 errno = retcode;
1088 return -1;
1089 }
1090}
1091
1092
sewardjb48e5002002-05-13 00:16:03 +00001093/* ---------------------------------------------------
sewardjf8f819e2002-04-17 23:21:37 +00001094 THREAD-SPECIFICs
1095 ------------------------------------------------ */
sewardj5e5fa512002-04-14 13:13:05 +00001096
sewardj5905fae2002-04-26 13:25:00 +00001097int __pthread_key_create(pthread_key_t *key,
1098 void (*destr_function) (void *))
sewardj5e5fa512002-04-14 13:13:05 +00001099{
sewardj5f07b662002-04-23 16:52:51 +00001100 int res;
1101 ensure_valgrind("pthread_key_create");
1102 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
1103 VG_USERREQ__PTHREAD_KEY_CREATE,
1104 key, destr_function, 0, 0);
1105 return res;
sewardj5e5fa512002-04-14 13:13:05 +00001106}
1107
1108int pthread_key_delete(pthread_key_t key)
1109{
sewardj436e0582002-04-26 14:31:40 +00001110 static int moans = N_MOANS;
1111 if (moans-- > 0)
1112 ignored("pthread_key_delete");
sewardj5e5fa512002-04-14 13:13:05 +00001113 return 0;
1114}
1115
sewardj5905fae2002-04-26 13:25:00 +00001116int __pthread_setspecific(pthread_key_t key, const void *pointer)
sewardj5e5fa512002-04-14 13:13:05 +00001117{
sewardj5f07b662002-04-23 16:52:51 +00001118 int res;
1119 ensure_valgrind("pthread_setspecific");
1120 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
1121 VG_USERREQ__PTHREAD_SETSPECIFIC,
1122 key, pointer, 0, 0);
1123 return res;
sewardj5e5fa512002-04-14 13:13:05 +00001124}
1125
sewardj5905fae2002-04-26 13:25:00 +00001126void * __pthread_getspecific(pthread_key_t key)
sewardj5e5fa512002-04-14 13:13:05 +00001127{
sewardj5f07b662002-04-23 16:52:51 +00001128 int res;
1129 ensure_valgrind("pthread_getspecific");
1130 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
1131 VG_USERREQ__PTHREAD_GETSPECIFIC,
1132 key, 0 , 0, 0);
1133 return (void*)res;
sewardj5e5fa512002-04-14 13:13:05 +00001134}
1135
sewardjf8f819e2002-04-17 23:21:37 +00001136
1137/* ---------------------------------------------------
sewardj89d3d852002-04-24 19:21:39 +00001138 ONCEry
1139 ------------------------------------------------ */
1140
1141static pthread_mutex_t once_masterlock = PTHREAD_MUTEX_INITIALIZER;
1142
1143
sewardj5905fae2002-04-26 13:25:00 +00001144int __pthread_once ( pthread_once_t *once_control,
1145 void (*init_routine) (void) )
sewardj89d3d852002-04-24 19:21:39 +00001146{
1147 int res;
1148 ensure_valgrind("pthread_once");
1149
sewardj68b2dd92002-05-10 21:03:56 +00001150 res = __pthread_mutex_lock(&once_masterlock);
sewardj89d3d852002-04-24 19:21:39 +00001151
sewardj68b2dd92002-05-10 21:03:56 +00001152 if (res != 0) {
1153 printf("res = %d\n",res);
sewardj89d3d852002-04-24 19:21:39 +00001154 barf("pthread_once: Looks like your program's "
1155 "init routine calls back to pthread_once() ?!");
sewardj68b2dd92002-05-10 21:03:56 +00001156 }
sewardj89d3d852002-04-24 19:21:39 +00001157
1158 if (*once_control == 0) {
1159 *once_control = 1;
1160 init_routine();
1161 }
1162
sewardj68b2dd92002-05-10 21:03:56 +00001163 __pthread_mutex_unlock(&once_masterlock);
sewardj89d3d852002-04-24 19:21:39 +00001164
1165 return 0;
1166}
1167
1168
1169/* ---------------------------------------------------
sewardj853f55d2002-04-26 00:27:53 +00001170 MISC
1171 ------------------------------------------------ */
1172
sewardj5905fae2002-04-26 13:25:00 +00001173int __pthread_atfork ( void (*prepare)(void),
1174 void (*parent)(void),
1175 void (*child)(void) )
sewardj853f55d2002-04-26 00:27:53 +00001176{
sewardjccef2e62002-05-29 19:26:32 +00001177 /* We have to do this properly or not at all; faking it isn't an
1178 option. */
1179 vgPlain_unimp("__pthread_atfork");
sewardj853f55d2002-04-26 00:27:53 +00001180}
1181
1182
sewardjbb990782002-05-08 02:01:14 +00001183__attribute__((weak))
1184void __pthread_initialize ( void )
1185{
sewardjbea1caa2002-05-10 23:20:58 +00001186 ensure_valgrind("__pthread_initialize");
sewardjbb990782002-05-08 02:01:14 +00001187}
1188
1189
sewardj853f55d2002-04-26 00:27:53 +00001190/* ---------------------------------------------------
sewardj3b13f0e2002-04-25 20:17:29 +00001191 LIBRARY-PRIVATE THREAD SPECIFIC STATE
sewardjf8f819e2002-04-17 23:21:37 +00001192 ------------------------------------------------ */
1193
sewardj3b13f0e2002-04-25 20:17:29 +00001194#include <resolv.h>
1195static int thread_specific_errno[VG_N_THREADS];
1196static int thread_specific_h_errno[VG_N_THREADS];
1197static struct __res_state
1198 thread_specific_res_state[VG_N_THREADS];
sewardjf8f819e2002-04-17 23:21:37 +00001199
sewardj3b13f0e2002-04-25 20:17:29 +00001200int* __errno_location ( void )
sewardjf8f819e2002-04-17 23:21:37 +00001201{
1202 int tid;
sewardj3b13f0e2002-04-25 20:17:29 +00001203 /* ensure_valgrind("__errno_location"); */
1204 VALGRIND_MAGIC_SEQUENCE(tid, 1 /* default */,
sewardjf8f819e2002-04-17 23:21:37 +00001205 VG_USERREQ__PTHREAD_GET_THREADID,
1206 0, 0, 0, 0);
sewardj3b13f0e2002-04-25 20:17:29 +00001207 /* 'cos I'm paranoid ... */
sewardj439d45e2002-05-03 20:43:10 +00001208 if (tid < 1 || tid >= VG_N_THREADS)
sewardj3b13f0e2002-04-25 20:17:29 +00001209 barf("__errno_location: invalid ThreadId");
1210 return & thread_specific_errno[tid];
1211}
1212
1213int* __h_errno_location ( void )
1214{
1215 int tid;
1216 /* ensure_valgrind("__h_errno_location"); */
1217 VALGRIND_MAGIC_SEQUENCE(tid, 1 /* default */,
1218 VG_USERREQ__PTHREAD_GET_THREADID,
1219 0, 0, 0, 0);
1220 /* 'cos I'm paranoid ... */
sewardj439d45e2002-05-03 20:43:10 +00001221 if (tid < 1 || tid >= VG_N_THREADS)
sewardj3b13f0e2002-04-25 20:17:29 +00001222 barf("__h_errno_location: invalid ThreadId");
1223 return & thread_specific_h_errno[tid];
1224}
1225
1226struct __res_state* __res_state ( void )
1227{
1228 int tid;
1229 /* ensure_valgrind("__res_state"); */
1230 VALGRIND_MAGIC_SEQUENCE(tid, 1 /* default */,
1231 VG_USERREQ__PTHREAD_GET_THREADID,
1232 0, 0, 0, 0);
1233 /* 'cos I'm paranoid ... */
sewardj439d45e2002-05-03 20:43:10 +00001234 if (tid < 1 || tid >= VG_N_THREADS)
sewardj3b13f0e2002-04-25 20:17:29 +00001235 barf("__res_state: invalid ThreadId");
1236 return & thread_specific_res_state[tid];
sewardjf8f819e2002-04-17 23:21:37 +00001237}
1238
1239
sewardj5716dbb2002-04-26 03:28:18 +00001240/* ---------------------------------------------------
1241 LIBC-PRIVATE SPECIFIC DATA
1242 ------------------------------------------------ */
1243
1244/* Relies on assumption that initial private data is NULL. This
1245 should be fixed somehow. */
1246
1247/* The allowable keys (indices) (all 2 of them).
1248 From sysdeps/pthread/bits/libc-tsd.h
1249*/
sewardj70adeb22002-04-27 01:35:38 +00001250#define N_LIBC_TSD_EXTRA_KEYS 1
1251
sewardj5716dbb2002-04-26 03:28:18 +00001252enum __libc_tsd_key_t { _LIBC_TSD_KEY_MALLOC = 0,
1253 _LIBC_TSD_KEY_DL_ERROR,
1254 _LIBC_TSD_KEY_N };
1255
1256/* Auto-initialising subsystem. libc_specifics_inited is set
1257 after initialisation. libc_specifics_inited_mx guards it. */
1258static int libc_specifics_inited = 0;
1259static pthread_mutex_t libc_specifics_inited_mx = PTHREAD_MUTEX_INITIALIZER;
1260
1261/* These are the keys we must initialise the first time. */
sewardj70adeb22002-04-27 01:35:38 +00001262static pthread_key_t libc_specifics_keys[_LIBC_TSD_KEY_N
1263 + N_LIBC_TSD_EXTRA_KEYS];
sewardj5716dbb2002-04-26 03:28:18 +00001264
1265/* Initialise the keys, if they are not already initialise. */
1266static
1267void init_libc_tsd_keys ( void )
1268{
1269 int res, i;
1270 pthread_key_t k;
1271
1272 res = pthread_mutex_lock(&libc_specifics_inited_mx);
1273 if (res != 0) barf("init_libc_tsd_keys: lock");
1274
1275 if (libc_specifics_inited == 0) {
1276 /* printf("INIT libc specifics\n"); */
1277 libc_specifics_inited = 1;
sewardj70adeb22002-04-27 01:35:38 +00001278 for (i = 0; i < _LIBC_TSD_KEY_N + N_LIBC_TSD_EXTRA_KEYS; i++) {
sewardj5716dbb2002-04-26 03:28:18 +00001279 res = pthread_key_create(&k, NULL);
1280 if (res != 0) barf("init_libc_tsd_keys: create");
1281 libc_specifics_keys[i] = k;
1282 }
1283 }
1284
1285 res = pthread_mutex_unlock(&libc_specifics_inited_mx);
1286 if (res != 0) barf("init_libc_tsd_keys: unlock");
1287}
1288
1289
1290static int
1291libc_internal_tsd_set ( enum __libc_tsd_key_t key,
1292 const void * pointer )
1293{
sewardj70adeb22002-04-27 01:35:38 +00001294 int res;
1295 static int moans = N_MOANS;
sewardj5716dbb2002-04-26 03:28:18 +00001296 /* printf("SET SET SET key %d ptr %p\n", key, pointer); */
sewardj70adeb22002-04-27 01:35:38 +00001297 if (key < _LIBC_TSD_KEY_MALLOC
1298 || key >= _LIBC_TSD_KEY_N + N_LIBC_TSD_EXTRA_KEYS)
sewardj5716dbb2002-04-26 03:28:18 +00001299 barf("libc_internal_tsd_set: invalid key");
sewardj70adeb22002-04-27 01:35:38 +00001300 if (key >= _LIBC_TSD_KEY_N && moans-- > 0)
1301 fprintf(stderr,
sewardj439d45e2002-05-03 20:43:10 +00001302 "valgrind's libpthread.so: libc_internal_tsd_set: "
1303 "dubious key %d\n", key);
sewardj5716dbb2002-04-26 03:28:18 +00001304 init_libc_tsd_keys();
1305 res = pthread_setspecific(libc_specifics_keys[key], pointer);
1306 if (res != 0) barf("libc_internal_tsd_set: setspecific failed");
1307 return 0;
1308}
1309
1310static void *
1311libc_internal_tsd_get ( enum __libc_tsd_key_t key )
1312{
sewardj70adeb22002-04-27 01:35:38 +00001313 void* v;
1314 static int moans = N_MOANS;
sewardj5716dbb2002-04-26 03:28:18 +00001315 /* printf("GET GET GET key %d\n", key); */
sewardj70adeb22002-04-27 01:35:38 +00001316 if (key < _LIBC_TSD_KEY_MALLOC
1317 || key >= _LIBC_TSD_KEY_N + N_LIBC_TSD_EXTRA_KEYS)
sewardj5716dbb2002-04-26 03:28:18 +00001318 barf("libc_internal_tsd_get: invalid key");
sewardj70adeb22002-04-27 01:35:38 +00001319 if (key >= _LIBC_TSD_KEY_N && moans-- > 0)
1320 fprintf(stderr,
sewardj439d45e2002-05-03 20:43:10 +00001321 "valgrind's libpthread.so: libc_internal_tsd_get: "
1322 "dubious key %d\n", key);
sewardj5716dbb2002-04-26 03:28:18 +00001323 init_libc_tsd_keys();
1324 v = pthread_getspecific(libc_specifics_keys[key]);
1325 /* if (v == NULL) barf("libc_internal_tsd_set: getspecific failed"); */
1326 return v;
1327}
1328
1329
1330
1331
sewardj70adeb22002-04-27 01:35:38 +00001332int (*__libc_internal_tsd_set)
1333 (enum __libc_tsd_key_t key, const void * pointer)
1334 = libc_internal_tsd_set;
sewardj5716dbb2002-04-26 03:28:18 +00001335
sewardj70adeb22002-04-27 01:35:38 +00001336void* (*__libc_internal_tsd_get)
1337 (enum __libc_tsd_key_t key)
1338 = libc_internal_tsd_get;
sewardj5716dbb2002-04-26 03:28:18 +00001339
1340
sewardje663cb92002-04-12 10:26:32 +00001341/* ---------------------------------------------------------------------
1342 These are here (I think) because they are deemed cancellation
1343 points by POSIX. For the moment we'll simply pass the call along
1344 to the corresponding thread-unaware (?) libc routine.
1345 ------------------------------------------------------------------ */
1346
sewardje663cb92002-04-12 10:26:32 +00001347#include <stdlib.h>
sewardje663cb92002-04-12 10:26:32 +00001348#include <sys/types.h>
1349#include <sys/socket.h>
1350
sewardjd529a442002-05-04 19:49:21 +00001351#ifdef GLIBC_2_1
1352extern
1353int __sigaction
1354 (int signum,
1355 const struct sigaction *act,
1356 struct sigaction *oldact);
1357#else
sewardje663cb92002-04-12 10:26:32 +00001358extern
1359int __libc_sigaction
1360 (int signum,
1361 const struct sigaction *act,
1362 struct sigaction *oldact);
sewardjd529a442002-05-04 19:49:21 +00001363#endif
sewardje663cb92002-04-12 10:26:32 +00001364int sigaction(int signum,
1365 const struct sigaction *act,
1366 struct sigaction *oldact)
1367{
sewardjd140e442002-05-29 01:21:19 +00001368 __my_pthread_testcancel();
sewardj2a1dcce2002-04-22 12:45:25 +00001369# ifdef GLIBC_2_1
1370 return __sigaction(signum, act, oldact);
1371# else
sewardj45b4b372002-04-16 22:50:32 +00001372 return __libc_sigaction(signum, act, oldact);
sewardj2a1dcce2002-04-22 12:45:25 +00001373# endif
sewardje663cb92002-04-12 10:26:32 +00001374}
1375
1376
1377extern
1378int __libc_connect(int sockfd,
1379 const struct sockaddr *serv_addr,
1380 socklen_t addrlen);
sewardj5905fae2002-04-26 13:25:00 +00001381__attribute__((weak))
sewardje663cb92002-04-12 10:26:32 +00001382int connect(int sockfd,
1383 const struct sockaddr *serv_addr,
1384 socklen_t addrlen)
1385{
sewardjd140e442002-05-29 01:21:19 +00001386 __my_pthread_testcancel();
sewardj45b4b372002-04-16 22:50:32 +00001387 return __libc_connect(sockfd, serv_addr, addrlen);
sewardje663cb92002-04-12 10:26:32 +00001388}
1389
1390
1391extern
1392int __libc_fcntl(int fd, int cmd, long arg);
sewardj5905fae2002-04-26 13:25:00 +00001393__attribute__((weak))
sewardje663cb92002-04-12 10:26:32 +00001394int fcntl(int fd, int cmd, long arg)
1395{
sewardjd140e442002-05-29 01:21:19 +00001396 __my_pthread_testcancel();
sewardj45b4b372002-04-16 22:50:32 +00001397 return __libc_fcntl(fd, cmd, arg);
sewardje663cb92002-04-12 10:26:32 +00001398}
1399
1400
1401extern
1402ssize_t __libc_write(int fd, const void *buf, size_t count);
sewardj5905fae2002-04-26 13:25:00 +00001403__attribute__((weak))
sewardje663cb92002-04-12 10:26:32 +00001404ssize_t write(int fd, const void *buf, size_t count)
1405{
sewardjd140e442002-05-29 01:21:19 +00001406 __my_pthread_testcancel();
sewardj45b4b372002-04-16 22:50:32 +00001407 return __libc_write(fd, buf, count);
sewardje663cb92002-04-12 10:26:32 +00001408}
1409
1410
1411extern
1412ssize_t __libc_read(int fd, void *buf, size_t count);
sewardj5905fae2002-04-26 13:25:00 +00001413__attribute__((weak))
sewardje663cb92002-04-12 10:26:32 +00001414ssize_t read(int fd, void *buf, size_t count)
1415{
sewardjd140e442002-05-29 01:21:19 +00001416 __my_pthread_testcancel();
sewardj45b4b372002-04-16 22:50:32 +00001417 return __libc_read(fd, buf, count);
sewardje663cb92002-04-12 10:26:32 +00001418}
1419
sewardjbe32e452002-04-24 20:29:58 +00001420
1421extern
sewardj853f55d2002-04-26 00:27:53 +00001422int __libc_open64(const char *pathname, int flags, mode_t mode);
sewardj5905fae2002-04-26 13:25:00 +00001423__attribute__((weak))
sewardj853f55d2002-04-26 00:27:53 +00001424int open64(const char *pathname, int flags, mode_t mode)
sewardjbe32e452002-04-24 20:29:58 +00001425{
sewardjd140e442002-05-29 01:21:19 +00001426 __my_pthread_testcancel();
sewardj853f55d2002-04-26 00:27:53 +00001427 return __libc_open64(pathname, flags, mode);
sewardjbe32e452002-04-24 20:29:58 +00001428}
1429
sewardje663cb92002-04-12 10:26:32 +00001430
1431extern
sewardj853f55d2002-04-26 00:27:53 +00001432int __libc_open(const char *pathname, int flags, mode_t mode);
sewardj5905fae2002-04-26 13:25:00 +00001433__attribute__((weak))
sewardj853f55d2002-04-26 00:27:53 +00001434int open(const char *pathname, int flags, mode_t mode)
sewardje663cb92002-04-12 10:26:32 +00001435{
sewardjd140e442002-05-29 01:21:19 +00001436 __my_pthread_testcancel();
sewardj853f55d2002-04-26 00:27:53 +00001437 return __libc_open(pathname, flags, mode);
sewardje663cb92002-04-12 10:26:32 +00001438}
1439
1440
1441extern
1442int __libc_close(int fd);
sewardj5905fae2002-04-26 13:25:00 +00001443__attribute__((weak))
sewardje663cb92002-04-12 10:26:32 +00001444int close(int fd)
1445{
sewardjd140e442002-05-29 01:21:19 +00001446 __my_pthread_testcancel();
sewardj45b4b372002-04-16 22:50:32 +00001447 return __libc_close(fd);
sewardje663cb92002-04-12 10:26:32 +00001448}
1449
1450
1451extern
1452int __libc_accept(int s, struct sockaddr *addr, socklen_t *addrlen);
sewardj5905fae2002-04-26 13:25:00 +00001453__attribute__((weak))
sewardje663cb92002-04-12 10:26:32 +00001454int accept(int s, struct sockaddr *addr, socklen_t *addrlen)
1455{
sewardjd140e442002-05-29 01:21:19 +00001456 __my_pthread_testcancel();
sewardj705d3cb2002-05-23 13:13:12 +00001457 wait_for_fd_to_be_readable_or_erring(s);
sewardjd140e442002-05-29 01:21:19 +00001458 __my_pthread_testcancel();
sewardj45b4b372002-04-16 22:50:32 +00001459 return __libc_accept(s, addr, addrlen);
sewardje663cb92002-04-12 10:26:32 +00001460}
1461
1462
1463extern
1464pid_t __libc_fork(void);
sewardj5905fae2002-04-26 13:25:00 +00001465pid_t __fork(void)
sewardje663cb92002-04-12 10:26:32 +00001466{
sewardjd140e442002-05-29 01:21:19 +00001467 __my_pthread_testcancel();
sewardj45b4b372002-04-16 22:50:32 +00001468 return __libc_fork();
sewardje663cb92002-04-12 10:26:32 +00001469}
1470
1471
1472extern
1473pid_t __libc_waitpid(pid_t pid, int *status, int options);
sewardj5905fae2002-04-26 13:25:00 +00001474__attribute__((weak))
sewardje663cb92002-04-12 10:26:32 +00001475pid_t waitpid(pid_t pid, int *status, int options)
1476{
sewardjd140e442002-05-29 01:21:19 +00001477 __my_pthread_testcancel();
sewardj45b4b372002-04-16 22:50:32 +00001478 return __libc_waitpid(pid, status, options);
sewardje663cb92002-04-12 10:26:32 +00001479}
1480
1481
1482extern
1483int __libc_nanosleep(const struct timespec *req, struct timespec *rem);
sewardj5905fae2002-04-26 13:25:00 +00001484__attribute__((weak))
sewardje663cb92002-04-12 10:26:32 +00001485int nanosleep(const struct timespec *req, struct timespec *rem)
1486{
sewardjd140e442002-05-29 01:21:19 +00001487 __my_pthread_testcancel();
sewardje663cb92002-04-12 10:26:32 +00001488 return __libc_nanosleep(req, rem);
1489}
1490
sewardjbe32e452002-04-24 20:29:58 +00001491
sewardje663cb92002-04-12 10:26:32 +00001492extern
1493int __libc_fsync(int fd);
sewardj5905fae2002-04-26 13:25:00 +00001494__attribute__((weak))
sewardje663cb92002-04-12 10:26:32 +00001495int fsync(int fd)
1496{
sewardjd140e442002-05-29 01:21:19 +00001497 __my_pthread_testcancel();
sewardj45b4b372002-04-16 22:50:32 +00001498 return __libc_fsync(fd);
sewardje663cb92002-04-12 10:26:32 +00001499}
1500
sewardjbe32e452002-04-24 20:29:58 +00001501
sewardj70c75362002-04-13 04:18:32 +00001502extern
1503off_t __libc_lseek(int fildes, off_t offset, int whence);
sewardj5905fae2002-04-26 13:25:00 +00001504__attribute__((weak))
sewardj70c75362002-04-13 04:18:32 +00001505off_t lseek(int fildes, off_t offset, int whence)
1506{
sewardjd140e442002-05-29 01:21:19 +00001507 __my_pthread_testcancel();
sewardj45b4b372002-04-16 22:50:32 +00001508 return __libc_lseek(fildes, offset, whence);
sewardj70c75362002-04-13 04:18:32 +00001509}
1510
sewardjbe32e452002-04-24 20:29:58 +00001511
1512extern
1513__off64_t __libc_lseek64(int fildes, __off64_t offset, int whence);
sewardj5905fae2002-04-26 13:25:00 +00001514__attribute__((weak))
sewardjbe32e452002-04-24 20:29:58 +00001515__off64_t lseek64(int fildes, __off64_t offset, int whence)
1516{
sewardjd140e442002-05-29 01:21:19 +00001517 __my_pthread_testcancel();
sewardjbe32e452002-04-24 20:29:58 +00001518 return __libc_lseek64(fildes, offset, whence);
1519}
1520
1521
sewardj726c4122002-05-16 23:39:10 +00001522extern
1523ssize_t __libc_pread64 (int __fd, void *__buf, size_t __nbytes,
1524 __off64_t __offset);
1525ssize_t __pread64 (int __fd, void *__buf, size_t __nbytes,
1526 __off64_t __offset)
1527{
sewardjd140e442002-05-29 01:21:19 +00001528 __my_pthread_testcancel();
sewardj726c4122002-05-16 23:39:10 +00001529 return __libc_pread64(__fd, __buf, __nbytes, __offset);
1530}
1531
1532
sewardja18e2102002-05-18 10:43:22 +00001533extern
1534ssize_t __libc_pwrite64 (int __fd, const void *__buf, size_t __nbytes,
1535 __off64_t __offset);
1536ssize_t __pwrite64 (int __fd, const void *__buf, size_t __nbytes,
1537 __off64_t __offset)
1538{
sewardjd140e442002-05-29 01:21:19 +00001539 __my_pthread_testcancel();
sewardja18e2102002-05-18 10:43:22 +00001540 return __libc_pwrite64(__fd, __buf, __nbytes, __offset);
1541}
1542
sewardj726c4122002-05-16 23:39:10 +00001543
sewardj39b93b12002-05-18 10:56:27 +00001544extern
1545ssize_t __libc_pwrite(int fd, const void *buf, size_t count, off_t offset);
1546__attribute__((weak))
1547ssize_t pwrite(int fd, const void *buf, size_t count, off_t offset)
1548{
sewardjd140e442002-05-29 01:21:19 +00001549 __my_pthread_testcancel();
sewardj39b93b12002-05-18 10:56:27 +00001550 return __libc_pwrite(fd, buf, count, offset);
1551}
1552
1553
1554extern
1555ssize_t __libc_pread(int fd, void *buf, size_t count, off_t offset);
1556__attribute__((weak))
1557ssize_t pread(int fd, void *buf, size_t count, off_t offset)
1558{
sewardjd140e442002-05-29 01:21:19 +00001559 __my_pthread_testcancel();
sewardj39b93b12002-05-18 10:56:27 +00001560 return __libc_pread(fd, buf, count, offset);
1561}
1562
1563
sewardj6af4b5d2002-04-16 04:40:49 +00001564extern
1565void __libc_longjmp(jmp_buf env, int val) __attribute((noreturn));
sewardj5905fae2002-04-26 13:25:00 +00001566/* not weak: __attribute__((weak)) */
sewardj6af4b5d2002-04-16 04:40:49 +00001567void longjmp(jmp_buf env, int val)
1568{
sewardjd140e442002-05-29 01:21:19 +00001569 __my_pthread_testcancel();
sewardj6af4b5d2002-04-16 04:40:49 +00001570 __libc_longjmp(env, val);
1571}
1572
sewardjbe32e452002-04-24 20:29:58 +00001573
sewardj6af4b5d2002-04-16 04:40:49 +00001574extern
1575int __libc_send(int s, const void *msg, size_t len, int flags);
sewardj5905fae2002-04-26 13:25:00 +00001576__attribute__((weak))
sewardj6af4b5d2002-04-16 04:40:49 +00001577int send(int s, const void *msg, size_t len, int flags)
1578{
sewardjd140e442002-05-29 01:21:19 +00001579 __my_pthread_testcancel();
sewardj6af4b5d2002-04-16 04:40:49 +00001580 return __libc_send(s, msg, len, flags);
1581}
1582
sewardjbe32e452002-04-24 20:29:58 +00001583
sewardj1e8cdc92002-04-18 11:37:52 +00001584extern
1585int __libc_recv(int s, void *buf, size_t len, int flags);
sewardj5905fae2002-04-26 13:25:00 +00001586__attribute__((weak))
sewardj1e8cdc92002-04-18 11:37:52 +00001587int recv(int s, void *buf, size_t len, int flags)
1588{
sewardjd140e442002-05-29 01:21:19 +00001589 __my_pthread_testcancel();
sewardj1e8cdc92002-04-18 11:37:52 +00001590 return __libc_recv(s, buf, len, flags);
1591}
1592
sewardjbe32e452002-04-24 20:29:58 +00001593
sewardj3665ded2002-05-16 16:57:25 +00001594extern
1595int __libc_sendmsg(int s, const struct msghdr *msg, int flags);
1596__attribute__((weak))
1597int sendmsg(int s, const struct msghdr *msg, int flags)
1598{
sewardjd140e442002-05-29 01:21:19 +00001599 __my_pthread_testcancel();
sewardj3665ded2002-05-16 16:57:25 +00001600 return __libc_sendmsg(s, msg, flags);
1601}
1602
1603
sewardj796d6a22002-04-24 02:28:34 +00001604extern
sewardj436e0582002-04-26 14:31:40 +00001605int __libc_recvfrom(int s, void *buf, size_t len, int flags,
1606 struct sockaddr *from, socklen_t *fromlen);
1607__attribute__((weak))
1608int recvfrom(int s, void *buf, size_t len, int flags,
1609 struct sockaddr *from, socklen_t *fromlen)
1610{
sewardjd140e442002-05-29 01:21:19 +00001611 __my_pthread_testcancel();
sewardj436e0582002-04-26 14:31:40 +00001612 return __libc_recvfrom(s, buf, len, flags, from, fromlen);
1613}
1614
1615
1616extern
sewardj796d6a22002-04-24 02:28:34 +00001617int __libc_sendto(int s, const void *msg, size_t len, int flags,
1618 const struct sockaddr *to, socklen_t tolen);
sewardj5905fae2002-04-26 13:25:00 +00001619__attribute__((weak))
sewardj796d6a22002-04-24 02:28:34 +00001620int sendto(int s, const void *msg, size_t len, int flags,
1621 const struct sockaddr *to, socklen_t tolen)
1622{
sewardjd140e442002-05-29 01:21:19 +00001623 __my_pthread_testcancel();
sewardj796d6a22002-04-24 02:28:34 +00001624 return __libc_sendto(s, msg, len, flags, to, tolen);
1625}
1626
sewardjbe32e452002-04-24 20:29:58 +00001627
sewardj369b1702002-04-24 13:28:15 +00001628extern
1629int __libc_system(const char* str);
sewardj5905fae2002-04-26 13:25:00 +00001630__attribute__((weak))
sewardj369b1702002-04-24 13:28:15 +00001631int system(const char* str)
1632{
sewardjd140e442002-05-29 01:21:19 +00001633 __my_pthread_testcancel();
sewardj369b1702002-04-24 13:28:15 +00001634 return __libc_system(str);
1635}
1636
sewardjbe32e452002-04-24 20:29:58 +00001637
sewardjab0b1c32002-04-24 19:26:47 +00001638extern
1639pid_t __libc_wait(int *status);
sewardj5905fae2002-04-26 13:25:00 +00001640__attribute__((weak))
sewardjab0b1c32002-04-24 19:26:47 +00001641pid_t wait(int *status)
1642{
sewardjd140e442002-05-29 01:21:19 +00001643 __my_pthread_testcancel();
sewardjab0b1c32002-04-24 19:26:47 +00001644 return __libc_wait(status);
1645}
1646
sewardj45b4b372002-04-16 22:50:32 +00001647
sewardj67f1d582002-05-24 02:11:32 +00001648extern
1649int __libc_msync(const void *start, size_t length, int flags);
1650__attribute__((weak))
1651int msync(const void *start, size_t length, int flags)
1652{
sewardjd140e442002-05-29 01:21:19 +00001653 __my_pthread_testcancel();
sewardj67f1d582002-05-24 02:11:32 +00001654 return __libc_msync(start, length, flags);
1655}
1656
sewardj5905fae2002-04-26 13:25:00 +00001657
sewardj3b13f0e2002-04-25 20:17:29 +00001658/* ---------------------------------------------------------------------
1659 Nonblocking implementations of select() and poll(). This stuff will
1660 surely rot your mind.
1661 ------------------------------------------------------------------ */
sewardje663cb92002-04-12 10:26:32 +00001662
sewardj08a4c3f2002-04-13 03:45:44 +00001663/*--------------------------------------------------*/
1664
1665#include "vg_kerneliface.h"
1666
1667static
1668__inline__
1669int is_kerror ( int res )
1670{
1671 if (res >= -4095 && res <= -1)
1672 return 1;
1673 else
1674 return 0;
1675}
1676
1677
1678static
1679int my_do_syscall1 ( int syscallno, int arg1 )
1680{
1681 int __res;
1682 __asm__ volatile ("pushl %%ebx; movl %%edx,%%ebx ; int $0x80 ; popl %%ebx"
1683 : "=a" (__res)
1684 : "0" (syscallno),
1685 "d" (arg1) );
1686 return __res;
1687}
1688
1689static
1690int my_do_syscall2 ( int syscallno,
sewardjf854f472002-04-21 12:19:41 +00001691 int arg1, int arg2 )
sewardj08a4c3f2002-04-13 03:45:44 +00001692{
1693 int __res;
1694 __asm__ volatile ("pushl %%ebx; movl %%edx,%%ebx ; int $0x80 ; popl %%ebx"
1695 : "=a" (__res)
1696 : "0" (syscallno),
1697 "d" (arg1),
1698 "c" (arg2) );
1699 return __res;
1700}
1701
1702static
sewardjf854f472002-04-21 12:19:41 +00001703int my_do_syscall3 ( int syscallno,
1704 int arg1, int arg2, int arg3 )
1705{
1706 int __res;
1707 __asm__ volatile ("pushl %%ebx; movl %%esi,%%ebx ; int $0x80 ; popl %%ebx"
1708 : "=a" (__res)
1709 : "0" (syscallno),
1710 "S" (arg1),
1711 "c" (arg2),
1712 "d" (arg3) );
1713 return __res;
1714}
1715
1716static
sewardj08a4c3f2002-04-13 03:45:44 +00001717int do_syscall_select( int n,
1718 vki_fd_set* readfds,
1719 vki_fd_set* writefds,
1720 vki_fd_set* exceptfds,
1721 struct vki_timeval * timeout )
1722{
1723 int res;
1724 int args[5];
1725 args[0] = n;
1726 args[1] = (int)readfds;
1727 args[2] = (int)writefds;
1728 args[3] = (int)exceptfds;
1729 args[4] = (int)timeout;
1730 res = my_do_syscall1(__NR_select, (int)(&(args[0])) );
sewardj02535bc2002-04-21 01:08:26 +00001731 return res;
sewardj08a4c3f2002-04-13 03:45:44 +00001732}
1733
1734
1735/* This is a wrapper round select(), which makes it thread-safe,
1736 meaning that only this thread will block, rather than the entire
1737 process. This wrapper in turn depends on nanosleep() not to block
1738 the entire process, but I think (hope? suspect?) that POSIX
1739 pthreads guarantees that to be the case.
1740
1741 Basic idea is: modify the timeout parameter to select so that it
1742 returns immediately. Poll like this until select returns non-zero,
1743 indicating something interesting happened, or until our time is up.
1744 Space out the polls with nanosleeps of say 20 milliseconds, which
1745 is required to be nonblocking; this allows other threads to run.
sewardj02535bc2002-04-21 01:08:26 +00001746
1747 Assumes:
sewardj2d94c112002-06-03 01:25:54 +00001748 * (checked via my_assert) types fd_set and vki_fd_set are identical.
1749 * (checked via my_assert) types timeval and vki_timeval are identical.
sewardj02535bc2002-04-21 01:08:26 +00001750 * (unchecked) libc error numbers (EINTR etc) are the negation of the
1751 kernel's error numbers (VKI_EINTR etc).
sewardj08a4c3f2002-04-13 03:45:44 +00001752*/
sewardj08a4c3f2002-04-13 03:45:44 +00001753
sewardj5905fae2002-04-26 13:25:00 +00001754/* __attribute__((weak)) */
sewardj08a4c3f2002-04-13 03:45:44 +00001755int select ( int n,
1756 fd_set *rfds,
1757 fd_set *wfds,
1758 fd_set *xfds,
1759 struct timeval *timeout )
1760{
sewardj5f07b662002-04-23 16:52:51 +00001761 unsigned int ms_now, ms_end;
sewardj08a4c3f2002-04-13 03:45:44 +00001762 int res;
1763 fd_set rfds_copy;
1764 fd_set wfds_copy;
1765 fd_set xfds_copy;
1766 struct vki_timeval t_now;
sewardj08a4c3f2002-04-13 03:45:44 +00001767 struct vki_timeval zero_timeout;
1768 struct vki_timespec nanosleep_interval;
1769
sewardjd140e442002-05-29 01:21:19 +00001770 __my_pthread_testcancel();
1771
sewardj5f07b662002-04-23 16:52:51 +00001772 /* gcc's complains about ms_end being used uninitialised -- classic
1773 case it can't understand, where ms_end is both defined and used
1774 only if timeout != NULL. Hence ... */
1775 ms_end = 0;
sewardj08a4c3f2002-04-13 03:45:44 +00001776
1777 /* We assume that the kernel and libc data layouts are identical
1778 for the following types. These asserts provide a crude
1779 check. */
1780 if (sizeof(fd_set) != sizeof(vki_fd_set)
1781 || sizeof(struct timeval) != sizeof(struct vki_timeval))
1782 barf("valgrind's hacky non-blocking select(): data sizes error");
1783
sewardj5f07b662002-04-23 16:52:51 +00001784 /* Detect the current time and simultaneously find out if we are
1785 running on Valgrind. */
1786 VALGRIND_MAGIC_SEQUENCE(ms_now, 0xFFFFFFFF /* default */,
1787 VG_USERREQ__READ_MILLISECOND_TIMER,
1788 0, 0, 0, 0);
1789
1790 /* If a zero timeout specified, this call is harmless. Also go
1791 this route if we're not running on Valgrind, for whatever
1792 reason. */
1793 if ( (timeout && timeout->tv_sec == 0 && timeout->tv_usec == 0)
1794 || (ms_now == 0xFFFFFFFF) ) {
sewardj02535bc2002-04-21 01:08:26 +00001795 res = do_syscall_select( n, (vki_fd_set*)rfds,
sewardj08a4c3f2002-04-13 03:45:44 +00001796 (vki_fd_set*)wfds,
1797 (vki_fd_set*)xfds,
1798 (struct vki_timeval*)timeout);
sewardj02535bc2002-04-21 01:08:26 +00001799 if (is_kerror(res)) {
1800 * (__errno_location()) = -res;
1801 return -1;
1802 } else {
1803 return res;
1804 }
1805 }
sewardj08a4c3f2002-04-13 03:45:44 +00001806
sewardj5f07b662002-04-23 16:52:51 +00001807 /* If a timeout was specified, set ms_end to be the end millisecond
1808 counter [wallclock] time. */
sewardj08a4c3f2002-04-13 03:45:44 +00001809 if (timeout) {
1810 res = my_do_syscall2(__NR_gettimeofday, (int)&t_now, (int)NULL);
sewardj2d94c112002-06-03 01:25:54 +00001811 my_assert(res == 0);
sewardj5f07b662002-04-23 16:52:51 +00001812 ms_end = ms_now;
1813 ms_end += (timeout->tv_usec / 1000);
1814 ms_end += (timeout->tv_sec * 1000);
sewardj08a4c3f2002-04-13 03:45:44 +00001815 /* Stay sane ... */
sewardj2d94c112002-06-03 01:25:54 +00001816 my_assert (ms_end >= ms_now);
sewardj08a4c3f2002-04-13 03:45:44 +00001817 }
1818
1819 /* fprintf(stderr, "MY_SELECT: before loop\n"); */
1820
1821 /* Either timeout == NULL, meaning wait indefinitely, or timeout !=
sewardj5f07b662002-04-23 16:52:51 +00001822 NULL, in which case ms_end holds the end time. */
sewardj08a4c3f2002-04-13 03:45:44 +00001823 while (1) {
1824 if (timeout) {
sewardj5f07b662002-04-23 16:52:51 +00001825 VALGRIND_MAGIC_SEQUENCE(ms_now, 0xFFFFFFFF /* default */,
1826 VG_USERREQ__READ_MILLISECOND_TIMER,
1827 0, 0, 0, 0);
sewardj2d94c112002-06-03 01:25:54 +00001828 my_assert(ms_now != 0xFFFFFFFF);
sewardj5f07b662002-04-23 16:52:51 +00001829 if (ms_now >= ms_end) {
sewardj08a4c3f2002-04-13 03:45:44 +00001830 /* timeout; nothing interesting happened. */
1831 if (rfds) FD_ZERO(rfds);
1832 if (wfds) FD_ZERO(wfds);
1833 if (xfds) FD_ZERO(xfds);
1834 return 0;
1835 }
1836 }
1837
1838 /* These could be trashed each time round the loop, so restore
1839 them each time. */
1840 if (rfds) rfds_copy = *rfds;
1841 if (wfds) wfds_copy = *wfds;
1842 if (xfds) xfds_copy = *xfds;
1843
1844 zero_timeout.tv_sec = zero_timeout.tv_usec = 0;
1845
1846 res = do_syscall_select( n,
1847 rfds ? (vki_fd_set*)(&rfds_copy) : NULL,
1848 wfds ? (vki_fd_set*)(&wfds_copy) : NULL,
1849 xfds ? (vki_fd_set*)(&xfds_copy) : NULL,
1850 & zero_timeout );
sewardj02535bc2002-04-21 01:08:26 +00001851 if (is_kerror(res)) {
1852 /* Some kind of error (including EINTR). Set errno and
sewardj08a4c3f2002-04-13 03:45:44 +00001853 return. The sets are unspecified in this case. */
sewardj02535bc2002-04-21 01:08:26 +00001854 * (__errno_location()) = -res;
1855 return -1;
sewardj08a4c3f2002-04-13 03:45:44 +00001856 }
1857 if (res > 0) {
1858 /* one or more fds is ready. Copy out resulting sets and
1859 return. */
1860 if (rfds) *rfds = rfds_copy;
1861 if (wfds) *wfds = wfds_copy;
1862 if (xfds) *xfds = xfds_copy;
1863 return res;
1864 }
1865 /* fprintf(stderr, "MY_SELECT: nanosleep\n"); */
1866 /* nanosleep and go round again */
sewardj02535bc2002-04-21 01:08:26 +00001867 nanosleep_interval.tv_sec = 0;
sewardj956cc1b2002-04-25 01:33:50 +00001868 nanosleep_interval.tv_nsec = 50 * 1000 * 1000; /* 50 milliseconds */
sewardjf854f472002-04-21 12:19:41 +00001869 /* It's critical here that valgrind's nanosleep implementation
1870 is nonblocking. */
1871 (void)my_do_syscall2(__NR_nanosleep,
1872 (int)(&nanosleep_interval), (int)NULL);
1873 }
1874}
1875
1876
1877
1878
1879#include <sys/poll.h>
1880
sewardj3e909ce2002-06-03 13:27:15 +00001881#ifndef HAVE_NFDS_T
sewardj72d58482002-04-24 02:20:20 +00001882typedef unsigned long int nfds_t;
1883#endif
1884
sewardj705d3cb2002-05-23 13:13:12 +00001885
sewardj5905fae2002-04-26 13:25:00 +00001886/* __attribute__((weak)) */
sewardjf854f472002-04-21 12:19:41 +00001887int poll (struct pollfd *__fds, nfds_t __nfds, int __timeout)
1888{
sewardj5f07b662002-04-23 16:52:51 +00001889 unsigned int ms_now, ms_end;
sewardjf854f472002-04-21 12:19:41 +00001890 int res, i;
sewardjf854f472002-04-21 12:19:41 +00001891 struct vki_timespec nanosleep_interval;
1892
sewardjd140e442002-05-29 01:21:19 +00001893 __my_pthread_testcancel();
sewardjf854f472002-04-21 12:19:41 +00001894 ensure_valgrind("poll");
1895
sewardj5f07b662002-04-23 16:52:51 +00001896 /* Detect the current time and simultaneously find out if we are
1897 running on Valgrind. */
1898 VALGRIND_MAGIC_SEQUENCE(ms_now, 0xFFFFFFFF /* default */,
1899 VG_USERREQ__READ_MILLISECOND_TIMER,
1900 0, 0, 0, 0);
1901
sewardjf854f472002-04-21 12:19:41 +00001902 if (/* CHECK SIZES FOR struct pollfd */
1903 sizeof(struct timeval) != sizeof(struct vki_timeval))
1904 barf("valgrind's hacky non-blocking poll(): data sizes error");
1905
sewardj5f07b662002-04-23 16:52:51 +00001906 /* dummy initialisation to keep gcc -Wall happy */
1907 ms_end = 0;
1908
1909 /* If a zero timeout specified, this call is harmless. Also do
1910 this if not running on Valgrind. */
1911 if (__timeout == 0 || ms_now == 0xFFFFFFFF) {
sewardjf854f472002-04-21 12:19:41 +00001912 res = my_do_syscall3(__NR_poll, (int)__fds, __nfds, __timeout);
1913 if (is_kerror(res)) {
1914 * (__errno_location()) = -res;
1915 return -1;
1916 } else {
1917 return res;
1918 }
1919 }
1920
sewardj5f07b662002-04-23 16:52:51 +00001921 /* If a timeout was specified, set ms_end to be the end wallclock
1922 time. Easy considering that __timeout is in milliseconds. */
sewardjf854f472002-04-21 12:19:41 +00001923 if (__timeout > 0) {
sewardj650ac002002-04-29 12:20:34 +00001924 ms_end = ms_now + (unsigned int)__timeout;
sewardjf854f472002-04-21 12:19:41 +00001925 }
1926
1927 /* fprintf(stderr, "MY_POLL: before loop\n"); */
1928
1929 /* Either timeout < 0, meaning wait indefinitely, or timeout > 0,
1930 in which case t_end holds the end time. */
sewardj2d94c112002-06-03 01:25:54 +00001931 my_assert(__timeout != 0);
sewardj5f07b662002-04-23 16:52:51 +00001932
sewardjf854f472002-04-21 12:19:41 +00001933 while (1) {
sewardjf854f472002-04-21 12:19:41 +00001934 if (__timeout > 0) {
sewardj5f07b662002-04-23 16:52:51 +00001935 VALGRIND_MAGIC_SEQUENCE(ms_now, 0xFFFFFFFF /* default */,
1936 VG_USERREQ__READ_MILLISECOND_TIMER,
1937 0, 0, 0, 0);
sewardj2d94c112002-06-03 01:25:54 +00001938 my_assert(ms_now != 0xFFFFFFFF);
sewardj5f07b662002-04-23 16:52:51 +00001939 if (ms_now >= ms_end) {
sewardjf854f472002-04-21 12:19:41 +00001940 /* timeout; nothing interesting happened. */
1941 for (i = 0; i < __nfds; i++)
1942 __fds[i].revents = 0;
1943 return 0;
1944 }
1945 }
1946
sewardj5f07b662002-04-23 16:52:51 +00001947 /* Do a return-immediately poll. */
sewardjf854f472002-04-21 12:19:41 +00001948 res = my_do_syscall3(__NR_poll, (int)__fds, __nfds, 0 );
1949 if (is_kerror(res)) {
1950 /* Some kind of error. Set errno and return. */
1951 * (__errno_location()) = -res;
1952 return -1;
1953 }
1954 if (res > 0) {
1955 /* One or more fds is ready. Return now. */
1956 return res;
1957 }
1958 /* fprintf(stderr, "MY_POLL: nanosleep\n"); */
1959 /* nanosleep and go round again */
1960 nanosleep_interval.tv_sec = 0;
sewardj956cc1b2002-04-25 01:33:50 +00001961 nanosleep_interval.tv_nsec = 51 * 1000 * 1000; /* 51 milliseconds */
sewardj08a4c3f2002-04-13 03:45:44 +00001962 /* It's critical here that valgrind's nanosleep implementation
1963 is nonblocking. */
1964 (void)my_do_syscall2(__NR_nanosleep,
1965 (int)(&nanosleep_interval), (int)NULL);
1966 }
1967}
sewardj3b13f0e2002-04-25 20:17:29 +00001968
1969
sewardj705d3cb2002-05-23 13:13:12 +00001970/* Helper function used to make accept() non-blocking. Idea is to use
1971 the above nonblocking poll() to make this thread ONLY wait for the
1972 specified fd to become ready, and then return. */
1973static void wait_for_fd_to_be_readable_or_erring ( int fd )
1974{
1975 struct pollfd pfd;
sewardj6e6cbaa2002-05-24 02:12:52 +00001976 /* fprintf(stderr, "wait_for_fd_to_be_readable_or_erring %d\n", fd); */
sewardj705d3cb2002-05-23 13:13:12 +00001977 pfd.fd = fd;
1978 pfd.events = POLLIN | POLLPRI | POLLERR | POLLHUP | POLLNVAL;
1979 /* ... but not POLLOUT, you may notice. */
1980 pfd.revents = 0;
1981 (void)poll(&pfd, 1, -1 /* forever */);
1982}
1983
1984
sewardj3b13f0e2002-04-25 20:17:29 +00001985/* ---------------------------------------------------------------------
sewardj8f253ff2002-05-19 00:13:34 +00001986 Hacky implementation of semaphores.
1987 ------------------------------------------------------------------ */
1988
1989#include <semaphore.h>
1990
1991/* This is a terrible way to do the remapping. Plan is to import an
1992 AVL tree at some point. */
sewardj8f253ff2002-05-19 00:13:34 +00001993
1994typedef
1995 struct {
1996 pthread_mutex_t se_mx;
1997 pthread_cond_t se_cv;
1998 int count;
1999 }
2000 vg_sem_t;
2001
2002static pthread_mutex_t se_remap_mx = PTHREAD_MUTEX_INITIALIZER;
2003
2004static int se_remap_used = 0;
2005static sem_t* se_remap_orig[VG_N_SEMAPHORES];
2006static vg_sem_t se_remap_new[VG_N_SEMAPHORES];
2007
2008static vg_sem_t* se_remap ( sem_t* orig )
2009{
2010 int res, i;
2011 res = __pthread_mutex_lock(&se_remap_mx);
sewardj2d94c112002-06-03 01:25:54 +00002012 my_assert(res == 0);
sewardj8f253ff2002-05-19 00:13:34 +00002013
2014 for (i = 0; i < se_remap_used; i++) {
2015 if (se_remap_orig[i] == orig)
2016 break;
2017 }
2018 if (i == se_remap_used) {
2019 if (se_remap_used == VG_N_SEMAPHORES) {
2020 res = pthread_mutex_unlock(&se_remap_mx);
sewardj2d94c112002-06-03 01:25:54 +00002021 my_assert(res == 0);
sewardja1ac5cb2002-05-27 13:00:05 +00002022 barf("VG_N_SEMAPHORES is too low. Increase and recompile.");
sewardj8f253ff2002-05-19 00:13:34 +00002023 }
2024 se_remap_used++;
2025 se_remap_orig[i] = orig;
2026 /* printf("allocated semaphore %d\n", i); */
2027 }
2028 res = __pthread_mutex_unlock(&se_remap_mx);
sewardj2d94c112002-06-03 01:25:54 +00002029 my_assert(res == 0);
sewardj8f253ff2002-05-19 00:13:34 +00002030 return &se_remap_new[i];
2031}
2032
2033
2034int sem_init(sem_t *sem, int pshared, unsigned int value)
2035{
2036 int res;
2037 vg_sem_t* vg_sem;
2038 ensure_valgrind("sem_init");
2039 if (pshared != 0) {
2040 errno = ENOSYS;
2041 return -1;
2042 }
2043 vg_sem = se_remap(sem);
2044 res = pthread_mutex_init(&vg_sem->se_mx, NULL);
sewardj2d94c112002-06-03 01:25:54 +00002045 my_assert(res == 0);
sewardj8f253ff2002-05-19 00:13:34 +00002046 res = pthread_cond_init(&vg_sem->se_cv, NULL);
sewardj2d94c112002-06-03 01:25:54 +00002047 my_assert(res == 0);
sewardj8f253ff2002-05-19 00:13:34 +00002048 vg_sem->count = value;
2049 return 0;
2050}
2051
2052
2053int sem_wait ( sem_t* sem )
2054{
2055 int res;
2056 vg_sem_t* vg_sem;
2057 ensure_valgrind("sem_wait");
2058 vg_sem = se_remap(sem);
2059 res = __pthread_mutex_lock(&vg_sem->se_mx);
sewardj2d94c112002-06-03 01:25:54 +00002060 my_assert(res == 0);
sewardj8f253ff2002-05-19 00:13:34 +00002061 while (vg_sem->count == 0) {
2062 res = pthread_cond_wait(&vg_sem->se_cv, &vg_sem->se_mx);
sewardj2d94c112002-06-03 01:25:54 +00002063 my_assert(res == 0);
sewardj8f253ff2002-05-19 00:13:34 +00002064 }
2065 vg_sem->count--;
2066 res = __pthread_mutex_unlock(&vg_sem->se_mx);
sewardj2d94c112002-06-03 01:25:54 +00002067 my_assert(res == 0);
sewardj8f253ff2002-05-19 00:13:34 +00002068 return 0;
2069}
2070
2071int sem_post ( sem_t* sem )
2072{
2073 int res;
2074 vg_sem_t* vg_sem;
2075 ensure_valgrind("sem_post");
2076 vg_sem = se_remap(sem);
2077 res = __pthread_mutex_lock(&vg_sem->se_mx);
sewardj2d94c112002-06-03 01:25:54 +00002078 my_assert(res == 0);
sewardj8f253ff2002-05-19 00:13:34 +00002079 if (vg_sem->count == 0) {
2080 vg_sem->count++;
2081 res = pthread_cond_broadcast(&vg_sem->se_cv);
sewardj2d94c112002-06-03 01:25:54 +00002082 my_assert(res == 0);
sewardj8f253ff2002-05-19 00:13:34 +00002083 } else {
2084 vg_sem->count++;
2085 }
2086 res = __pthread_mutex_unlock(&vg_sem->se_mx);
sewardj2d94c112002-06-03 01:25:54 +00002087 my_assert(res == 0);
sewardj8f253ff2002-05-19 00:13:34 +00002088 return 0;
2089}
2090
2091
2092int sem_trywait ( sem_t* sem )
2093{
2094 int ret, res;
2095 vg_sem_t* vg_sem;
2096 ensure_valgrind("sem_trywait");
2097 vg_sem = se_remap(sem);
2098 res = __pthread_mutex_lock(&vg_sem->se_mx);
sewardj2d94c112002-06-03 01:25:54 +00002099 my_assert(res == 0);
sewardj8f253ff2002-05-19 00:13:34 +00002100 if (vg_sem->count > 0) {
2101 vg_sem->count--;
2102 ret = 0;
2103 } else {
2104 ret = -1;
2105 errno = EAGAIN;
2106 }
2107 res = __pthread_mutex_unlock(&vg_sem->se_mx);
sewardj2d94c112002-06-03 01:25:54 +00002108 my_assert(res == 0);
sewardj8f253ff2002-05-19 00:13:34 +00002109 return ret;
2110}
2111
2112
2113int sem_getvalue(sem_t* sem, int * sval)
2114{
2115 vg_sem_t* vg_sem;
2116 ensure_valgrind("sem_trywait");
2117 vg_sem = se_remap(sem);
2118 *sval = vg_sem->count;
2119 return 0;
2120}
2121
2122
2123int sem_destroy(sem_t * sem)
2124{
2125 kludged("sem_destroy");
2126 /* if someone waiting on this semaphore, errno = EBUSY, return -1 */
2127 return 0;
2128}
2129
2130
2131/* ---------------------------------------------------------------------
sewardj2d8b3f02002-06-01 14:14:19 +00002132 Reader-writer locks.
sewardja1ac5cb2002-05-27 13:00:05 +00002133 ------------------------------------------------------------------ */
2134
sewardj2d8b3f02002-06-01 14:14:19 +00002135typedef
2136 struct {
2137 int initted; /* != 0 --> in use; sanity check only */
2138 int prefer_w; /* != 0 --> prefer writer */
2139 int nwait_r; /* # of waiting readers */
2140 int nwait_w; /* # of waiting writers */
2141 pthread_cond_t cv_r; /* for signalling readers */
2142 pthread_cond_t cv_w; /* for signalling writers */
2143 pthread_mutex_t mx;
2144 int status;
2145 /* allowed range for status: >= -1. -1 means 1 writer currently
2146 active, >= 0 means N readers currently active. */
2147 }
2148 vg_rwlock_t;
sewardja1ac5cb2002-05-27 13:00:05 +00002149
2150
2151static pthread_mutex_t rw_remap_mx = PTHREAD_MUTEX_INITIALIZER;
2152
2153static int rw_remap_used = 0;
2154static pthread_rwlock_t* rw_remap_orig[VG_N_RWLOCKS];
2155static vg_rwlock_t rw_remap_new[VG_N_RWLOCKS];
2156
sewardj2d8b3f02002-06-01 14:14:19 +00002157
2158static
2159void init_vg_rwlock ( vg_rwlock_t* vg_rwl )
2160{
2161 int res = 0;
2162 vg_rwl->initted = 1;
2163 vg_rwl->prefer_w = 1;
2164 vg_rwl->nwait_r = 0;
2165 vg_rwl->nwait_w = 0;
2166 vg_rwl->status = 0;
2167 res = pthread_mutex_init(&vg_rwl->mx, NULL);
2168 res |= pthread_cond_init(&vg_rwl->cv_r, NULL);
2169 res |= pthread_cond_init(&vg_rwl->cv_w, NULL);
sewardj2d94c112002-06-03 01:25:54 +00002170 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002171}
2172
2173
sewardja1ac5cb2002-05-27 13:00:05 +00002174/* Take the address of a LinuxThreads rwlock_t and return the shadow
2175 address of our version. Further, if the LinuxThreads version
2176 appears to have been statically initialised, do the same to the one
2177 we allocate here. The pthread_rwlock_t.__rw_readers field is set
2178 to zero by PTHREAD_RWLOCK_INITIALIZER, so we take zero as meaning
2179 uninitialised and non-zero meaning initialised.
2180*/
2181static vg_rwlock_t* rw_remap ( pthread_rwlock_t* orig )
2182{
2183 int res, i;
2184 vg_rwlock_t* vg_rwl;
2185 res = __pthread_mutex_lock(&rw_remap_mx);
sewardj2d94c112002-06-03 01:25:54 +00002186 my_assert(res == 0);
sewardja1ac5cb2002-05-27 13:00:05 +00002187
2188 for (i = 0; i < rw_remap_used; i++) {
2189 if (rw_remap_orig[i] == orig)
2190 break;
2191 }
2192 if (i == rw_remap_used) {
2193 if (rw_remap_used == VG_N_RWLOCKS) {
sewardj2d8b3f02002-06-01 14:14:19 +00002194 res = __pthread_mutex_unlock(&rw_remap_mx);
sewardj2d94c112002-06-03 01:25:54 +00002195 my_assert(res == 0);
sewardja1ac5cb2002-05-27 13:00:05 +00002196 barf("VG_N_RWLOCKS is too low. Increase and recompile.");
2197 }
2198 rw_remap_used++;
2199 rw_remap_orig[i] = orig;
sewardj2d8b3f02002-06-01 14:14:19 +00002200 rw_remap_new[i].initted = 0;
sewardja1ac5cb2002-05-27 13:00:05 +00002201 if (0) printf("allocated rwlock %d\n", i);
2202 }
2203 res = __pthread_mutex_unlock(&rw_remap_mx);
sewardj2d94c112002-06-03 01:25:54 +00002204 my_assert(res == 0);
sewardja1ac5cb2002-05-27 13:00:05 +00002205 vg_rwl = &rw_remap_new[i];
2206
sewardj2d8b3f02002-06-01 14:14:19 +00002207 /* Initialise the shadow, if required. */
sewardja1ac5cb2002-05-27 13:00:05 +00002208 if (orig->__rw_readers == 0) {
sewardja1ac5cb2002-05-27 13:00:05 +00002209 orig->__rw_readers = 1;
sewardj2d8b3f02002-06-01 14:14:19 +00002210 init_vg_rwlock(vg_rwl);
sewardja1ac5cb2002-05-27 13:00:05 +00002211 if (orig->__rw_kind == PTHREAD_RWLOCK_PREFER_READER_NP)
sewardj2d8b3f02002-06-01 14:14:19 +00002212 vg_rwl->prefer_w = 0;
sewardja1ac5cb2002-05-27 13:00:05 +00002213 }
2214
2215 return vg_rwl;
2216}
2217
2218
sewardja1ac5cb2002-05-27 13:00:05 +00002219int pthread_rwlock_init ( pthread_rwlock_t* orig,
2220 const pthread_rwlockattr_t* attr )
2221{
sewardja1ac5cb2002-05-27 13:00:05 +00002222 vg_rwlock_t* rwl;
2223 if (0) printf ("pthread_rwlock_init\n");
2224 /* Force the remapper to initialise the shadow. */
2225 orig->__rw_readers = 0;
2226 /* Install the lock preference; the remapper needs to know it. */
2227 orig->__rw_kind = PTHREAD_RWLOCK_DEFAULT_NP;
2228 if (attr)
2229 orig->__rw_kind = attr->__lockkind;
2230 rwl = rw_remap ( orig );
sewardj2d8b3f02002-06-01 14:14:19 +00002231 return 0;
sewardja1ac5cb2002-05-27 13:00:05 +00002232}
2233
sewardj2d8b3f02002-06-01 14:14:19 +00002234
2235static
2236void pthread_rwlock_rdlock_CANCEL_HDLR ( void* rwl_v )
sewardja1ac5cb2002-05-27 13:00:05 +00002237{
sewardj2d8b3f02002-06-01 14:14:19 +00002238 vg_rwlock_t* rwl = (vg_rwlock_t*)rwl_v;
2239 rwl->nwait_r--;
2240 pthread_mutex_unlock (&rwl->mx);
sewardja1ac5cb2002-05-27 13:00:05 +00002241}
2242
sewardj2d8b3f02002-06-01 14:14:19 +00002243
sewardja1ac5cb2002-05-27 13:00:05 +00002244int pthread_rwlock_rdlock ( pthread_rwlock_t* orig )
2245{
2246 int res;
2247 vg_rwlock_t* rwl;
2248 if (0) printf ("pthread_rwlock_rdlock\n");
2249 rwl = rw_remap ( orig );
sewardj2d8b3f02002-06-01 14:14:19 +00002250 res = __pthread_mutex_lock(&rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00002251 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002252 if (!rwl->initted) {
2253 res = __pthread_mutex_unlock(&rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00002254 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002255 return EINVAL;
2256 }
2257 if (rwl->status < 0) {
sewardj2d94c112002-06-03 01:25:54 +00002258 my_assert(rwl->status == -1);
sewardj2d8b3f02002-06-01 14:14:19 +00002259 rwl->nwait_r++;
2260 pthread_cleanup_push( pthread_rwlock_rdlock_CANCEL_HDLR, rwl );
2261 while (1) {
2262 if (rwl->status == 0) break;
2263 res = pthread_cond_wait(&rwl->cv_r, &rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00002264 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002265 }
2266 pthread_cleanup_pop(0);
2267 rwl->nwait_r--;
2268 }
sewardj2d94c112002-06-03 01:25:54 +00002269 my_assert(rwl->status >= 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002270 rwl->status++;
2271 res = __pthread_mutex_unlock(&rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00002272 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002273 return 0;
sewardja1ac5cb2002-05-27 13:00:05 +00002274}
2275
sewardj2d8b3f02002-06-01 14:14:19 +00002276
sewardja1ac5cb2002-05-27 13:00:05 +00002277int pthread_rwlock_tryrdlock ( pthread_rwlock_t* orig )
2278{
2279 int res;
2280 vg_rwlock_t* rwl;
2281 if (0) printf ("pthread_rwlock_tryrdlock\n");
2282 rwl = rw_remap ( orig );
sewardj2d8b3f02002-06-01 14:14:19 +00002283 res = __pthread_mutex_lock(&rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00002284 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002285 if (!rwl->initted) {
2286 res = __pthread_mutex_unlock(&rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00002287 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002288 return EINVAL;
2289 }
2290 if (rwl->status == -1) {
2291 /* Writer active; we have to give up. */
2292 res = __pthread_mutex_unlock(&rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00002293 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002294 return EBUSY;
2295 }
2296 /* Success */
sewardj2d94c112002-06-03 01:25:54 +00002297 my_assert(rwl->status >= 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002298 rwl->status++;
2299 res = __pthread_mutex_unlock(&rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00002300 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002301 return 0;
sewardja1ac5cb2002-05-27 13:00:05 +00002302}
2303
sewardj2d8b3f02002-06-01 14:14:19 +00002304
2305static
2306void pthread_rwlock_wrlock_CANCEL_HDLR ( void* rwl_v )
2307{
2308 vg_rwlock_t* rwl = (vg_rwlock_t*)rwl_v;
2309 rwl->nwait_w--;
2310 pthread_mutex_unlock (&rwl->mx);
2311}
2312
2313
sewardja1ac5cb2002-05-27 13:00:05 +00002314int pthread_rwlock_wrlock ( pthread_rwlock_t* orig )
2315{
2316 int res;
2317 vg_rwlock_t* rwl;
2318 if (0) printf ("pthread_rwlock_wrlock\n");
2319 rwl = rw_remap ( orig );
sewardj2d8b3f02002-06-01 14:14:19 +00002320 res = __pthread_mutex_lock(&rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00002321 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002322 if (!rwl->initted) {
2323 res = __pthread_mutex_unlock(&rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00002324 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002325 return EINVAL;
2326 }
2327 if (rwl->status != 0) {
2328 rwl->nwait_w++;
2329 pthread_cleanup_push( pthread_rwlock_wrlock_CANCEL_HDLR, rwl );
2330 while (1) {
2331 if (rwl->status == 0) break;
2332 res = pthread_cond_wait(&rwl->cv_w, &rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00002333 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002334 }
2335 pthread_cleanup_pop(0);
2336 rwl->nwait_w--;
2337 }
sewardj2d94c112002-06-03 01:25:54 +00002338 my_assert(rwl->status == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002339 rwl->status = -1;
2340 res = __pthread_mutex_unlock(&rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00002341 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002342 return 0;
sewardja1ac5cb2002-05-27 13:00:05 +00002343}
2344
sewardj2d8b3f02002-06-01 14:14:19 +00002345
sewardja1ac5cb2002-05-27 13:00:05 +00002346int pthread_rwlock_trywrlock ( pthread_rwlock_t* orig )
2347{
2348 int res;
2349 vg_rwlock_t* rwl;
sewardj2d8b3f02002-06-01 14:14:19 +00002350 if (0) printf ("pthread_wrlock_trywrlock\n");
sewardja1ac5cb2002-05-27 13:00:05 +00002351 rwl = rw_remap ( orig );
sewardj2d8b3f02002-06-01 14:14:19 +00002352 res = __pthread_mutex_lock(&rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00002353 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002354 if (!rwl->initted) {
2355 res = __pthread_mutex_unlock(&rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00002356 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002357 return EINVAL;
2358 }
2359 if (rwl->status != 0) {
2360 /* Reader(s) or a writer active; we have to give up. */
2361 res = __pthread_mutex_unlock(&rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00002362 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002363 return EBUSY;
2364 }
2365 /* Success */
sewardj2d94c112002-06-03 01:25:54 +00002366 my_assert(rwl->status == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002367 rwl->status = -1;
2368 res = __pthread_mutex_unlock(&rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00002369 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002370 return 0;
sewardja1ac5cb2002-05-27 13:00:05 +00002371}
2372
sewardj2d8b3f02002-06-01 14:14:19 +00002373
sewardja1ac5cb2002-05-27 13:00:05 +00002374int pthread_rwlock_unlock ( pthread_rwlock_t* orig )
2375{
2376 int res;
2377 vg_rwlock_t* rwl;
2378 if (0) printf ("pthread_rwlock_unlock\n");
2379 rwl = rw_remap ( orig );
sewardj2d8b3f02002-06-01 14:14:19 +00002380 rwl = rw_remap ( orig );
2381 res = __pthread_mutex_lock(&rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00002382 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002383 if (!rwl->initted) {
2384 res = __pthread_mutex_unlock(&rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00002385 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002386 return EINVAL;
2387 }
2388 if (rwl->status == 0) {
2389 res = __pthread_mutex_unlock(&rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00002390 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002391 return EPERM;
2392 }
sewardj2d94c112002-06-03 01:25:54 +00002393 my_assert(rwl->status != 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002394 if (rwl->status == -1) {
2395 rwl->status = 0;
2396 } else {
sewardj2d94c112002-06-03 01:25:54 +00002397 my_assert(rwl->status > 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002398 rwl->status--;
2399 }
2400
sewardj2d94c112002-06-03 01:25:54 +00002401 my_assert(rwl->status >= 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002402
2403 if (rwl->prefer_w) {
2404
2405 /* Favour waiting writers, if any. */
2406 if (rwl->nwait_w > 0) {
2407 /* Writer(s) are waiting. */
2408 if (rwl->status == 0) {
2409 /* We can let a writer in. */
2410 res = pthread_cond_signal(&rwl->cv_w);
sewardj2d94c112002-06-03 01:25:54 +00002411 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002412 } else {
2413 /* There are still readers active. Do nothing; eventually
2414 they will disappear, at which point a writer will be
2415 admitted. */
2416 }
2417 }
2418 else
2419 /* No waiting writers. */
2420 if (rwl->nwait_r > 0) {
2421 /* Let in a waiting reader. */
2422 res = pthread_cond_signal(&rwl->cv_r);
sewardj2d94c112002-06-03 01:25:54 +00002423 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002424 }
2425
2426 } else {
2427
2428 /* Favour waiting readers, if any. */
2429 if (rwl->nwait_r > 0) {
2430 /* Reader(s) are waiting; let one in. */
2431 res = pthread_cond_signal(&rwl->cv_r);
sewardj2d94c112002-06-03 01:25:54 +00002432 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002433 }
2434 else
2435 /* No waiting readers. */
2436 if (rwl->nwait_w > 0 && rwl->status == 0) {
2437 /* We have waiting writers and no active readers; let a
2438 writer in. */
2439 res = pthread_cond_signal(&rwl->cv_w);
sewardj2d94c112002-06-03 01:25:54 +00002440 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002441 }
2442 }
2443
2444 res = __pthread_mutex_unlock(&rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00002445 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002446 return 0;
2447}
2448
2449
2450int pthread_rwlock_destroy ( pthread_rwlock_t *orig )
2451{
2452 int res;
2453 vg_rwlock_t* rwl;
2454 if (0) printf ("pthread_rwlock_destroy\n");
2455 rwl = rw_remap ( orig );
2456 res = __pthread_mutex_lock(&rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00002457 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002458 if (!rwl->initted) {
2459 res = __pthread_mutex_unlock(&rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00002460 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002461 return EINVAL;
2462 }
2463 if (rwl->status != 0 || rwl->nwait_r > 0 || rwl->nwait_w > 0) {
2464 res = __pthread_mutex_unlock(&rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00002465 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002466 return EBUSY;
2467 }
2468 rwl->initted = 0;
2469 res = __pthread_mutex_unlock(&rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00002470 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002471 return 0;
sewardja1ac5cb2002-05-27 13:00:05 +00002472}
2473
2474
2475/* ---------------------------------------------------------------------
sewardj3b13f0e2002-04-25 20:17:29 +00002476 B'stard.
2477 ------------------------------------------------------------------ */
2478
2479# define strong_alias(name, aliasname) \
2480 extern __typeof (name) aliasname __attribute__ ((alias (#name)));
2481
sewardj5905fae2002-04-26 13:25:00 +00002482# define weak_alias(name, aliasname) \
2483 extern __typeof (name) aliasname __attribute__ ((weak, alias (#name)));
sewardj3b13f0e2002-04-25 20:17:29 +00002484
sewardj5905fae2002-04-26 13:25:00 +00002485strong_alias(__pthread_mutex_lock, pthread_mutex_lock)
2486strong_alias(__pthread_mutex_trylock, pthread_mutex_trylock)
2487strong_alias(__pthread_mutex_unlock, pthread_mutex_unlock)
2488strong_alias(__pthread_mutexattr_init, pthread_mutexattr_init)
2489 weak_alias(__pthread_mutexattr_settype, pthread_mutexattr_settype)
2490strong_alias(__pthread_mutex_init, pthread_mutex_init)
2491strong_alias(__pthread_mutexattr_destroy, pthread_mutexattr_destroy)
2492strong_alias(__pthread_mutex_destroy, pthread_mutex_destroy)
2493strong_alias(__pthread_once, pthread_once)
2494strong_alias(__pthread_atfork, pthread_atfork)
2495strong_alias(__pthread_key_create, pthread_key_create)
2496strong_alias(__pthread_getspecific, pthread_getspecific)
2497strong_alias(__pthread_setspecific, pthread_setspecific)
2498
sewardjd529a442002-05-04 19:49:21 +00002499#ifndef GLIBC_2_1
sewardj3b13f0e2002-04-25 20:17:29 +00002500strong_alias(sigaction, __sigaction)
sewardjd529a442002-05-04 19:49:21 +00002501#endif
2502
sewardj5905fae2002-04-26 13:25:00 +00002503strong_alias(close, __close)
sewardj3b13f0e2002-04-25 20:17:29 +00002504strong_alias(fcntl, __fcntl)
sewardj5905fae2002-04-26 13:25:00 +00002505strong_alias(lseek, __lseek)
2506strong_alias(open, __open)
2507strong_alias(open64, __open64)
sewardj5905fae2002-04-26 13:25:00 +00002508strong_alias(read, __read)
2509strong_alias(wait, __wait)
2510strong_alias(write, __write)
sewardj3b13f0e2002-04-25 20:17:29 +00002511strong_alias(connect, __connect)
sewardj5905fae2002-04-26 13:25:00 +00002512strong_alias(send, __send)
2513
sewardj726c4122002-05-16 23:39:10 +00002514weak_alias (__pread64, pread64)
sewardja18e2102002-05-18 10:43:22 +00002515weak_alias (__pwrite64, pwrite64)
sewardj5905fae2002-04-26 13:25:00 +00002516weak_alias(__fork, fork)
sewardj7f6456d2002-05-21 00:51:21 +00002517
sewardjf0b06452002-06-04 08:38:04 +00002518weak_alias (__pthread_kill_other_threads_np, pthread_kill_other_threads_np)
sewardj3b13f0e2002-04-25 20:17:29 +00002519
2520/*--------------------------------------------------*/
2521
sewardj5905fae2002-04-26 13:25:00 +00002522weak_alias(pthread_rwlock_rdlock, __pthread_rwlock_rdlock)
sewardj5905fae2002-04-26 13:25:00 +00002523weak_alias(pthread_rwlock_unlock, __pthread_rwlock_unlock)
sewardj262b0292002-05-01 00:03:16 +00002524weak_alias(pthread_rwlock_wrlock, __pthread_rwlock_wrlock)
sewardj060b04f2002-04-26 21:01:13 +00002525
sewardja1ac5cb2002-05-27 13:00:05 +00002526weak_alias(pthread_rwlock_destroy, __pthread_rwlock_destroy)
2527weak_alias(pthread_rwlock_init, __pthread_rwlock_init)
2528weak_alias(pthread_rwlock_tryrdlock, __pthread_rwlock_tryrdlock)
2529weak_alias(pthread_rwlock_trywrlock, __pthread_rwlock_trywrlock)
2530
sewardj060b04f2002-04-26 21:01:13 +00002531
sewardj3b13f0e2002-04-25 20:17:29 +00002532/* I've no idea what these are, but they get called quite a lot.
2533 Anybody know? */
2534
2535#undef _IO_flockfile
2536void _IO_flockfile ( _IO_FILE * file )
2537{
sewardj853f55d2002-04-26 00:27:53 +00002538 pthread_mutex_lock(file->_lock);
sewardj3b13f0e2002-04-25 20:17:29 +00002539}
sewardj5905fae2002-04-26 13:25:00 +00002540weak_alias(_IO_flockfile, flockfile);
2541
sewardj3b13f0e2002-04-25 20:17:29 +00002542
2543#undef _IO_funlockfile
2544void _IO_funlockfile ( _IO_FILE * file )
2545{
sewardj853f55d2002-04-26 00:27:53 +00002546 pthread_mutex_unlock(file->_lock);
sewardj3b13f0e2002-04-25 20:17:29 +00002547}
sewardj5905fae2002-04-26 13:25:00 +00002548weak_alias(_IO_funlockfile, funlockfile);
2549
sewardj3b13f0e2002-04-25 20:17:29 +00002550
sewardjd4f2c712002-04-30 10:20:10 +00002551/* This doesn't seem to be needed to simulate libpthread.so's external
2552 interface, but many people complain about its absence. */
2553
2554strong_alias(__pthread_mutexattr_settype, __pthread_mutexattr_setkind_np)
2555weak_alias(__pthread_mutexattr_setkind_np, pthread_mutexattr_setkind_np)
sewardj439d45e2002-05-03 20:43:10 +00002556
2557
2558/*--------------------------------------------------------------------*/
2559/*--- end vg_libpthread.c ---*/
2560/*--------------------------------------------------------------------*/