blob: 5972dfa640c23d24a84cf7ca46bc7fb76ac20818 [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
njn25e49d8e72002-09-23 09:36:25 +000029 The GNU General Public License is contained in the file COPYING.
sewardj439d45e2002-05-03 20:43:10 +000030*/
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
sewardj9a2224b2002-06-19 10:17:40 +000078static
79int my_do_syscall2 ( int syscallno,
80 int arg1, int arg2 );
81
sewardj705d3cb2002-05-23 13:13:12 +000082
sewardje663cb92002-04-12 10:26:32 +000083/* ---------------------------------------------------------------------
84 Helpers. We have to be pretty self-sufficient.
85 ------------------------------------------------------------------ */
86
sewardj436e0582002-04-26 14:31:40 +000087/* Number of times any given error message is printed. */
88#define N_MOANS 3
89
sewardj45b4b372002-04-16 22:50:32 +000090/* Extract from Valgrind the value of VG_(clo_trace_pthread_level).
91 Returns 0 (none) if not running on Valgrind. */
92static
93int get_pt_trace_level ( void )
94{
95 int res;
96 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
97 VG_USERREQ__GET_PTHREAD_TRACE_LEVEL,
98 0, 0, 0, 0);
99 return res;
100}
101
102
sewardje663cb92002-04-12 10:26:32 +0000103static
sewardj2d94c112002-06-03 01:25:54 +0000104void my_exit ( int arg )
sewardje663cb92002-04-12 10:26:32 +0000105{
sewardj45b4b372002-04-16 22:50:32 +0000106 int __res;
sewardje663cb92002-04-12 10:26:32 +0000107 __asm__ volatile ("movl %%ecx, %%ebx ; int $0x80"
108 : "=a" (__res)
109 : "0" (__NR_exit),
110 "c" (arg) );
sewardj45b4b372002-04-16 22:50:32 +0000111 /* We don't bother to mention the fact that this asm trashes %ebx,
112 since it won't return. If you ever do let it return ... fix
113 this! */
sewardje663cb92002-04-12 10:26:32 +0000114}
115
116
sewardj68b2dd92002-05-10 21:03:56 +0000117/* We need this guy -- it's in valgrind.so. */
118extern void VG_(startup) ( void );
119
120
121/* Just start up Valgrind if it's not already going. VG_(startup)()
122 detects and ignores second and subsequent calls. */
sewardj604ec3c2002-04-18 22:38:41 +0000123static __inline__
sewardje663cb92002-04-12 10:26:32 +0000124void ensure_valgrind ( char* caller )
125{
sewardj68b2dd92002-05-10 21:03:56 +0000126 VG_(startup)();
sewardje663cb92002-04-12 10:26:32 +0000127}
128
sewardjbea1caa2002-05-10 23:20:58 +0000129/* While we're at it ... hook our own startup function into this
130 game. */
131__asm__ (
132 ".section .init\n"
133 "\tcall vgPlain_startup"
134);
135
sewardje663cb92002-04-12 10:26:32 +0000136
137static
sewardj3b5d8862002-04-20 13:53:23 +0000138__attribute__((noreturn))
sewardje663cb92002-04-12 10:26:32 +0000139void barf ( char* str )
140{
141 char buf[100];
142 buf[0] = 0;
sewardj439d45e2002-05-03 20:43:10 +0000143 strcat(buf, "\nvalgrind's libpthread.so: ");
sewardje663cb92002-04-12 10:26:32 +0000144 strcat(buf, str);
145 strcat(buf, "\n\n");
146 write(2, buf, strlen(buf));
sewardj2d94c112002-06-03 01:25:54 +0000147 my_exit(1);
sewardj3b5d8862002-04-20 13:53:23 +0000148 /* We have to persuade gcc into believing this doesn't return. */
149 while (1) { };
sewardje663cb92002-04-12 10:26:32 +0000150}
151
152
sewardj2a3d28c2002-04-14 13:27:00 +0000153static void ignored ( char* msg )
154{
sewardj436e0582002-04-26 14:31:40 +0000155 if (get_pt_trace_level() >= 0) {
sewardj439d45e2002-05-03 20:43:10 +0000156 char* ig = "valgrind's libpthread.so: IGNORED call to: ";
sewardj45b4b372002-04-16 22:50:32 +0000157 write(2, ig, strlen(ig));
158 write(2, msg, strlen(msg));
159 ig = "\n";
160 write(2, ig, strlen(ig));
161 }
sewardj2a3d28c2002-04-14 13:27:00 +0000162}
163
sewardj30671ff2002-04-21 00:13:57 +0000164static void kludged ( char* msg )
165{
sewardj436e0582002-04-26 14:31:40 +0000166 if (get_pt_trace_level() >= 0) {
sewardj439d45e2002-05-03 20:43:10 +0000167 char* ig = "valgrind's libpthread.so: KLUDGED call to: ";
168 write(2, ig, strlen(ig));
169 write(2, msg, strlen(msg));
170 ig = "\n";
171 write(2, ig, strlen(ig));
172 }
173}
174
175static void not_inside ( char* msg )
176{
sewardj68b2dd92002-05-10 21:03:56 +0000177 VG_(startup)();
sewardj30671ff2002-04-21 00:13:57 +0000178}
179
sewardjccef2e62002-05-29 19:26:32 +0000180__attribute__((noreturn))
sewardj3b13f0e2002-04-25 20:17:29 +0000181void vgPlain_unimp ( char* what )
182{
sewardj439d45e2002-05-03 20:43:10 +0000183 char* ig = "valgrind's libpthread.so: UNIMPLEMENTED FUNCTION: ";
sewardj3b13f0e2002-04-25 20:17:29 +0000184 write(2, ig, strlen(ig));
185 write(2, what, strlen(what));
186 ig = "\n";
187 write(2, ig, strlen(ig));
188 barf("Please report this bug to me at: jseward@acm.org");
189}
190
sewardje663cb92002-04-12 10:26:32 +0000191
sewardj457cc472002-06-03 23:13:47 +0000192static
sewardj2d94c112002-06-03 01:25:54 +0000193void my_assert_fail ( Char* expr, Char* file, Int line, Char* fn )
194{
195 static Bool entered = False;
196 if (entered)
197 my_exit(2);
198 entered = True;
199 fprintf(stderr, "\n%s: %s:%d (%s): Assertion `%s' failed.\n",
200 "valgrind", file, line, fn, expr );
201 fprintf(stderr, "Please report this bug to me at: %s\n\n",
202 VG_EMAIL_ADDR);
203 my_exit(1);
204}
205
206#define MY__STRING(__str) #__str
207
208#define my_assert(expr) \
209 ((void) ((expr) ? 0 : \
210 (my_assert_fail (MY__STRING(expr), \
211 __FILE__, __LINE__, \
212 __PRETTY_FUNCTION__), 0)))
213
214
sewardje663cb92002-04-12 10:26:32 +0000215/* ---------------------------------------------------------------------
216 Pass pthread_ calls to Valgrind's request mechanism.
217 ------------------------------------------------------------------ */
218
sewardjf8f819e2002-04-17 23:21:37 +0000219#include <errno.h>
sewardj5f07b662002-04-23 16:52:51 +0000220#include <sys/time.h> /* gettimeofday */
sewardjf8f819e2002-04-17 23:21:37 +0000221
sewardja1ac5cb2002-05-27 13:00:05 +0000222
sewardjf8f819e2002-04-17 23:21:37 +0000223/* ---------------------------------------------------
sewardj4dced352002-06-04 22:54:20 +0000224 Ummm ..
225 ------------------------------------------------ */
226
227static
228void pthread_error ( const char* msg )
229{
230 int res;
231 VALGRIND_MAGIC_SEQUENCE(res, 0,
232 VG_USERREQ__PTHREAD_ERROR,
233 msg, 0, 0, 0);
234}
235
236
237/* ---------------------------------------------------
sewardjf8f819e2002-04-17 23:21:37 +0000238 THREAD ATTRIBUTES
239 ------------------------------------------------ */
240
sewardj6af4b5d2002-04-16 04:40:49 +0000241int pthread_attr_init(pthread_attr_t *attr)
242{
sewardj7989d0c2002-05-28 11:00:01 +0000243 /* Just initialise the fields which we might look at. */
244 attr->__detachstate = PTHREAD_CREATE_JOINABLE;
sewardj6af4b5d2002-04-16 04:40:49 +0000245 return 0;
246}
247
248int pthread_attr_setdetachstate(pthread_attr_t *attr, int detachstate)
249{
sewardj7989d0c2002-05-28 11:00:01 +0000250 if (detachstate != PTHREAD_CREATE_JOINABLE
sewardj4dced352002-06-04 22:54:20 +0000251 && detachstate != PTHREAD_CREATE_DETACHED) {
252 pthread_error("pthread_attr_setdetachstate: "
253 "detachstate is invalid");
sewardj7989d0c2002-05-28 11:00:01 +0000254 return EINVAL;
sewardj4dced352002-06-04 22:54:20 +0000255 }
sewardj7989d0c2002-05-28 11:00:01 +0000256 attr->__detachstate = detachstate;
sewardj6af4b5d2002-04-16 04:40:49 +0000257 return 0;
258}
259
njn25e49d8e72002-09-23 09:36:25 +0000260int pthread_attr_getdetachstate(const pthread_attr_t *attr, int *detachstate)
261{
262 *detachstate = attr->__detachstate;
263 return 0;
264}
265
sewardj30671ff2002-04-21 00:13:57 +0000266int pthread_attr_setinheritsched(pthread_attr_t *attr, int inherit)
267{
sewardj436e0582002-04-26 14:31:40 +0000268 static int moans = N_MOANS;
269 if (moans-- > 0)
270 ignored("pthread_attr_setinheritsched");
sewardj30671ff2002-04-21 00:13:57 +0000271 return 0;
272}
sewardj6af4b5d2002-04-16 04:40:49 +0000273
sewardj0286dd52002-05-16 20:51:15 +0000274__attribute__((weak))
275int pthread_attr_setstacksize (pthread_attr_t *__attr,
276 size_t __stacksize)
277{
sewardja18e2102002-05-18 10:43:22 +0000278 size_t limit;
sewardj3d7c8d62002-06-04 20:59:16 +0000279 char buf[1024];
sewardj0286dd52002-05-16 20:51:15 +0000280 ensure_valgrind("pthread_attr_setstacksize");
sewardja18e2102002-05-18 10:43:22 +0000281 limit = VG_PTHREAD_STACK_SIZE - VG_AR_CLIENT_STACKBASE_REDZONE_SZB
282 - 1000; /* paranoia */
283 if (__stacksize < limit)
sewardj0286dd52002-05-16 20:51:15 +0000284 return 0;
sewardj3d7c8d62002-06-04 20:59:16 +0000285 snprintf(buf, sizeof(buf), "pthread_attr_setstacksize: "
286 "requested size %d >= VG_PTHREAD_STACK_SIZE\n "
287 "edit vg_include.h and rebuild.", __stacksize);
288 buf[sizeof(buf)-1] = '\0'; /* Make sure it is zero terminated */
289 barf(buf);
sewardj0286dd52002-05-16 20:51:15 +0000290}
291
292
sewardj30671ff2002-04-21 00:13:57 +0000293/* This is completely bogus. */
294int pthread_attr_getschedparam(const pthread_attr_t *attr,
295 struct sched_param *param)
296{
sewardj436e0582002-04-26 14:31:40 +0000297 static int moans = N_MOANS;
298 if (moans-- > 0)
299 kludged("pthread_attr_getschedparam");
sewardj3e909ce2002-06-03 13:27:15 +0000300# ifdef HAVE_SCHED_PRIORITY
sewardj72d58482002-04-24 02:20:20 +0000301 if (param) param->sched_priority = 0; /* who knows */
302# else
sewardj30671ff2002-04-21 00:13:57 +0000303 if (param) param->__sched_priority = 0; /* who knows */
sewardj72d58482002-04-24 02:20:20 +0000304# endif
sewardj30671ff2002-04-21 00:13:57 +0000305 return 0;
306}
307
308int pthread_attr_setschedparam(pthread_attr_t *attr,
309 const struct sched_param *param)
310{
sewardj436e0582002-04-26 14:31:40 +0000311 static int moans = N_MOANS;
312 if (moans-- > 0)
313 ignored("pthread_attr_setschedparam");
sewardj30671ff2002-04-21 00:13:57 +0000314 return 0;
315}
316
317int pthread_attr_destroy(pthread_attr_t *attr)
318{
sewardj436e0582002-04-26 14:31:40 +0000319 static int moans = N_MOANS;
320 if (moans-- > 0)
321 ignored("pthread_attr_destroy");
sewardj30671ff2002-04-21 00:13:57 +0000322 return 0;
323}
sewardjf8f819e2002-04-17 23:21:37 +0000324
sewardj0d844232002-06-02 09:29:31 +0000325/* These are no-ops, as with LinuxThreads. */
326int pthread_attr_setscope ( pthread_attr_t *attr, int scope )
327{
328 ensure_valgrind("pthread_attr_setscope");
329 if (scope == PTHREAD_SCOPE_SYSTEM)
330 return 0;
sewardj4dced352002-06-04 22:54:20 +0000331 pthread_error("pthread_attr_setscope: "
332 "invalid or unsupported scope");
sewardj0d844232002-06-02 09:29:31 +0000333 if (scope == PTHREAD_SCOPE_PROCESS)
334 return ENOTSUP;
335 return EINVAL;
336}
337
338int pthread_attr_getscope ( const pthread_attr_t *attr, int *scope )
339{
340 ensure_valgrind("pthread_attr_setscope");
341 if (scope)
342 *scope = PTHREAD_SCOPE_SYSTEM;
343 return 0;
344}
345
sewardj64039bb2002-06-03 00:58:18 +0000346
347/* Pretty bogus. Avoid if possible. */
348int pthread_getattr_np (pthread_t thread, pthread_attr_t *attr)
349{
350 int detached;
351 size_t limit;
352 ensure_valgrind("pthread_getattr_np");
353 kludged("pthread_getattr_np");
354 limit = VG_PTHREAD_STACK_SIZE - VG_AR_CLIENT_STACKBASE_REDZONE_SZB
355 - 1000; /* paranoia */
356 attr->__detachstate = PTHREAD_CREATE_JOINABLE;
357 attr->__schedpolicy = SCHED_OTHER;
358 attr->__schedparam.sched_priority = 0;
359 attr->__inheritsched = PTHREAD_EXPLICIT_SCHED;
360 attr->__scope = PTHREAD_SCOPE_SYSTEM;
361 attr->__guardsize = VKI_BYTES_PER_PAGE;
362 attr->__stackaddr = NULL;
363 attr->__stackaddr_set = 0;
364 attr->__stacksize = limit;
365 VALGRIND_MAGIC_SEQUENCE(detached, (-1) /* default */,
366 VG_USERREQ__SET_OR_GET_DETACH,
367 2 /* get */, thread, 0, 0);
sewardj2d94c112002-06-03 01:25:54 +0000368 my_assert(detached == 0 || detached == 1);
sewardj64039bb2002-06-03 00:58:18 +0000369 if (detached)
370 attr->__detachstate = PTHREAD_CREATE_DETACHED;
371 return 0;
372}
373
374
375/* Bogus ... */
376int pthread_attr_getstackaddr ( const pthread_attr_t * attr,
377 void ** stackaddr )
378{
379 ensure_valgrind("pthread_attr_getstackaddr");
380 kludged("pthread_attr_getstackaddr");
381 if (stackaddr)
382 *stackaddr = NULL;
383 return 0;
384}
385
386/* Not bogus (!) */
387int pthread_attr_getstacksize ( const pthread_attr_t * _attr,
388 size_t * __stacksize )
389{
390 size_t limit;
391 ensure_valgrind("pthread_attr_getstacksize");
392 limit = VG_PTHREAD_STACK_SIZE - VG_AR_CLIENT_STACKBASE_REDZONE_SZB
393 - 1000; /* paranoia */
394 if (__stacksize)
395 *__stacksize = limit;
396 return 0;
397}
398
sewardja3be12f2002-06-17 12:19:44 +0000399int pthread_attr_setschedpolicy(pthread_attr_t *attr, int policy)
400{
401 if (policy != SCHED_OTHER && policy != SCHED_FIFO && policy != SCHED_RR)
402 return EINVAL;
403 attr->__schedpolicy = policy;
404 return 0;
405}
406
407int pthread_attr_getschedpolicy(const pthread_attr_t *attr, int *policy)
408{
409 *policy = attr->__schedpolicy;
410 return 0;
411}
412
413
sewardj20917d82002-05-28 01:36:45 +0000414/* ---------------------------------------------------
415 Helper functions for running a thread
416 and for clearing up afterwards.
417 ------------------------------------------------ */
418
419/* All exiting threads eventually pass through here, bearing the
420 return value, or PTHREAD_CANCELED, in ret_val. */
421static
422__attribute__((noreturn))
423void thread_exit_wrapper ( void* ret_val )
424{
sewardj870497a2002-05-29 01:06:47 +0000425 int detached, res;
426 CleanupEntry cu;
427 pthread_key_t key;
428
sewardj20917d82002-05-28 01:36:45 +0000429 /* Run this thread's cleanup handlers. */
sewardj8ad94e12002-05-29 00:10:20 +0000430 while (1) {
431 VALGRIND_MAGIC_SEQUENCE(res, (-1) /* default */,
432 VG_USERREQ__CLEANUP_POP,
433 &cu, 0, 0, 0);
434 if (res == -1) break; /* stack empty */
sewardj2d94c112002-06-03 01:25:54 +0000435 my_assert(res == 0);
sewardj8ad94e12002-05-29 00:10:20 +0000436 if (0) printf("running exit cleanup handler");
437 cu.fn ( cu.arg );
438 }
439
sewardj870497a2002-05-29 01:06:47 +0000440 /* Run this thread's key finalizers. Really this should be run
441 PTHREAD_DESTRUCTOR_ITERATIONS times. */
442 for (key = 0; key < VG_N_THREAD_KEYS; key++) {
443 VALGRIND_MAGIC_SEQUENCE(res, (-2) /* default */,
444 VG_USERREQ__GET_KEY_D_AND_S,
445 key, &cu, 0, 0 );
446 if (res == 0) {
447 /* valid key */
448 if (cu.fn && cu.arg)
449 cu.fn /* destructor for key */
450 ( cu.arg /* specific for key for this thread */ );
451 continue;
452 }
sewardj2d94c112002-06-03 01:25:54 +0000453 my_assert(res == -1);
sewardj870497a2002-05-29 01:06:47 +0000454 }
sewardj20917d82002-05-28 01:36:45 +0000455
456 /* Decide on my final disposition. */
457 VALGRIND_MAGIC_SEQUENCE(detached, (-1) /* default */,
458 VG_USERREQ__SET_OR_GET_DETACH,
sewardj7989d0c2002-05-28 11:00:01 +0000459 2 /* get */, pthread_self(), 0, 0);
sewardj2d94c112002-06-03 01:25:54 +0000460 my_assert(detached == 0 || detached == 1);
sewardj20917d82002-05-28 01:36:45 +0000461
462 if (detached) {
463 /* Detached; I just quit right now. */
464 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
465 VG_USERREQ__QUIT, 0, 0, 0, 0);
466 } else {
467 /* Not detached; so I wait for a joiner. */
468 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
469 VG_USERREQ__WAIT_JOINER, ret_val, 0, 0, 0);
470 }
471 /* NOTREACHED */
472 barf("thread_exit_wrapper: still alive?!");
473}
474
475
476/* This function is a wrapper function for running a thread. It runs
477 the root function specified in pthread_create, and then, should the
478 root function return a value, it arranges to run the thread's
479 cleanup handlers and exit correctly. */
480
sewardj728a5272002-06-20 10:25:37 +0000481/* Struct used to convey info from pthread_create to thread_wrapper.
482 Must be careful not to pass to the child thread any pointers to
483 objects which might be on the parent's stack. */
sewardj20917d82002-05-28 01:36:45 +0000484typedef
485 struct {
sewardj728a5272002-06-20 10:25:37 +0000486 int attr__detachstate;
sewardj20917d82002-05-28 01:36:45 +0000487 void* (*root_fn) ( void* );
488 void* arg;
489 }
490 NewThreadInfo;
491
492
493/* This is passed to the VG_USERREQ__APPLY_IN_NEW_THREAD and so must
494 not return. Note that this runs in the new thread, not the
495 parent. */
496static
497__attribute__((noreturn))
498void thread_wrapper ( NewThreadInfo* info )
499{
sewardj728a5272002-06-20 10:25:37 +0000500 int res;
501 int attr__detachstate;
sewardj20917d82002-05-28 01:36:45 +0000502 void* (*root_fn) ( void* );
503 void* arg;
504 void* ret_val;
505
sewardj728a5272002-06-20 10:25:37 +0000506 attr__detachstate = info->attr__detachstate;
507 root_fn = info->root_fn;
508 arg = info->arg;
sewardj20917d82002-05-28 01:36:45 +0000509
sewardj20917d82002-05-28 01:36:45 +0000510 /* Free up the arg block that pthread_create malloced. */
511 VALGRIND_MAGIC_SEQUENCE(res, (-1) /* default */,
512 VG_USERREQ__FREE, info, 0, 0, 0);
sewardj2d94c112002-06-03 01:25:54 +0000513 my_assert(res == 0);
sewardj20917d82002-05-28 01:36:45 +0000514
sewardj7989d0c2002-05-28 11:00:01 +0000515 /* Minimally observe the attributes supplied. */
sewardj728a5272002-06-20 10:25:37 +0000516 if (attr__detachstate != PTHREAD_CREATE_DETACHED
517 && attr__detachstate != PTHREAD_CREATE_JOINABLE)
518 pthread_error("thread_wrapper: invalid attr->__detachstate");
519 if (attr__detachstate == PTHREAD_CREATE_DETACHED)
520 pthread_detach(pthread_self());
sewardj7989d0c2002-05-28 11:00:01 +0000521
sewardj20917d82002-05-28 01:36:45 +0000522 /* The root function might not return. But if it does we simply
523 move along to thread_exit_wrapper. All other ways out for the
524 thread (cancellation, or calling pthread_exit) lead there
525 too. */
526 ret_val = root_fn(arg);
527 thread_exit_wrapper(ret_val);
528 /* NOTREACHED */
529}
530
531
sewardjf8f819e2002-04-17 23:21:37 +0000532/* ---------------------------------------------------
533 THREADs
534 ------------------------------------------------ */
535
sewardjff42d1d2002-05-22 13:17:31 +0000536__attribute__((weak))
537int pthread_yield ( void )
538{
539 int res;
540 ensure_valgrind("pthread_yield");
541 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
542 VG_USERREQ__PTHREAD_YIELD, 0, 0, 0, 0);
543 return 0;
544}
545
546
sewardj6072c362002-04-19 14:40:57 +0000547int pthread_equal(pthread_t thread1, pthread_t thread2)
548{
549 return thread1 == thread2 ? 1 : 0;
550}
551
552
sewardj20917d82002-05-28 01:36:45 +0000553/* Bundle up the args into a malloc'd block and create a new thread
554 consisting of thread_wrapper() applied to said malloc'd block. */
sewardje663cb92002-04-12 10:26:32 +0000555int
sewardj1462c8b2002-07-24 09:41:52 +0000556pthread_create (pthread_t *__restrict __thredd,
sewardje663cb92002-04-12 10:26:32 +0000557 __const pthread_attr_t *__restrict __attr,
558 void *(*__start_routine) (void *),
559 void *__restrict __arg)
560{
sewardj20917d82002-05-28 01:36:45 +0000561 int tid_child;
562 NewThreadInfo* info;
sewardje663cb92002-04-12 10:26:32 +0000563
sewardj20917d82002-05-28 01:36:45 +0000564 ensure_valgrind("pthread_create");
565
566 /* Allocate space for the arg block. thread_wrapper will free
567 it. */
568 VALGRIND_MAGIC_SEQUENCE(info, NULL /* default */,
569 VG_USERREQ__MALLOC,
570 sizeof(NewThreadInfo), 0, 0, 0);
sewardj2d94c112002-06-03 01:25:54 +0000571 my_assert(info != NULL);
sewardj20917d82002-05-28 01:36:45 +0000572
sewardj728a5272002-06-20 10:25:37 +0000573 if (__attr)
574 info->attr__detachstate = __attr->__detachstate;
575 else
576 info->attr__detachstate = PTHREAD_CREATE_JOINABLE;
577
sewardj20917d82002-05-28 01:36:45 +0000578 info->root_fn = __start_routine;
579 info->arg = __arg;
580 VALGRIND_MAGIC_SEQUENCE(tid_child, VG_INVALID_THREADID /* default */,
581 VG_USERREQ__APPLY_IN_NEW_THREAD,
582 &thread_wrapper, info, 0, 0);
sewardj2d94c112002-06-03 01:25:54 +0000583 my_assert(tid_child != VG_INVALID_THREADID);
sewardj20917d82002-05-28 01:36:45 +0000584
sewardj1462c8b2002-07-24 09:41:52 +0000585 if (__thredd)
586 *__thredd = tid_child;
sewardj20917d82002-05-28 01:36:45 +0000587 return 0; /* success */
588}
sewardje663cb92002-04-12 10:26:32 +0000589
590
591int
592pthread_join (pthread_t __th, void **__thread_return)
593{
594 int res;
595 ensure_valgrind("pthread_join");
596 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
597 VG_USERREQ__PTHREAD_JOIN,
598 __th, __thread_return, 0, 0);
599 return res;
600}
601
602
sewardj3b5d8862002-04-20 13:53:23 +0000603void pthread_exit(void *retval)
604{
sewardj3b5d8862002-04-20 13:53:23 +0000605 ensure_valgrind("pthread_exit");
sewardj20917d82002-05-28 01:36:45 +0000606 /* Simple! */
607 thread_exit_wrapper(retval);
sewardj3b5d8862002-04-20 13:53:23 +0000608}
609
sewardje663cb92002-04-12 10:26:32 +0000610
sewardj3b13f0e2002-04-25 20:17:29 +0000611pthread_t pthread_self(void)
sewardje663cb92002-04-12 10:26:32 +0000612{
613 int tid;
sewardj3b13f0e2002-04-25 20:17:29 +0000614 ensure_valgrind("pthread_self");
sewardj439d45e2002-05-03 20:43:10 +0000615 VALGRIND_MAGIC_SEQUENCE(tid, 1 /* default */,
sewardje663cb92002-04-12 10:26:32 +0000616 VG_USERREQ__PTHREAD_GET_THREADID,
617 0, 0, 0, 0);
sewardj439d45e2002-05-03 20:43:10 +0000618 if (tid < 1 || tid >= VG_N_THREADS)
sewardj3b13f0e2002-04-25 20:17:29 +0000619 barf("pthread_self: invalid ThreadId");
620 return tid;
sewardje663cb92002-04-12 10:26:32 +0000621}
622
623
sewardj853f55d2002-04-26 00:27:53 +0000624int pthread_detach(pthread_t th)
625{
sewardj20917d82002-05-28 01:36:45 +0000626 int res;
627 ensure_valgrind("pthread_detach");
sewardj7989d0c2002-05-28 11:00:01 +0000628 /* First we enquire as to the current detach state. */
629 VALGRIND_MAGIC_SEQUENCE(res, (-2) /* default */,
sewardj20917d82002-05-28 01:36:45 +0000630 VG_USERREQ__SET_OR_GET_DETACH,
sewardj7989d0c2002-05-28 11:00:01 +0000631 2 /* get */, th, 0, 0);
sewardj4dced352002-06-04 22:54:20 +0000632 if (res == -1) {
633 /* not found */
634 pthread_error("pthread_detach: "
635 "invalid target thread");
sewardj7989d0c2002-05-28 11:00:01 +0000636 return ESRCH;
sewardj4dced352002-06-04 22:54:20 +0000637 }
638 if (res == 1) {
639 /* already detached */
640 pthread_error("pthread_detach: "
641 "target thread is already detached");
sewardj7989d0c2002-05-28 11:00:01 +0000642 return EINVAL;
sewardj4dced352002-06-04 22:54:20 +0000643 }
sewardj7989d0c2002-05-28 11:00:01 +0000644 if (res == 0) {
645 VALGRIND_MAGIC_SEQUENCE(res, (-2) /* default */,
646 VG_USERREQ__SET_OR_GET_DETACH,
647 1 /* set */, th, 0, 0);
sewardj2d94c112002-06-03 01:25:54 +0000648 my_assert(res == 0);
sewardj7989d0c2002-05-28 11:00:01 +0000649 return 0;
650 }
651 barf("pthread_detach");
sewardj853f55d2002-04-26 00:27:53 +0000652}
653
654
sewardjf8f819e2002-04-17 23:21:37 +0000655/* ---------------------------------------------------
sewardj8ad94e12002-05-29 00:10:20 +0000656 CLEANUP STACKS
657 ------------------------------------------------ */
658
659void _pthread_cleanup_push (struct _pthread_cleanup_buffer *__buffer,
660 void (*__routine) (void *),
661 void *__arg)
662{
663 int res;
664 CleanupEntry cu;
665 ensure_valgrind("_pthread_cleanup_push");
666 cu.fn = __routine;
667 cu.arg = __arg;
668 VALGRIND_MAGIC_SEQUENCE(res, (-1) /* default */,
669 VG_USERREQ__CLEANUP_PUSH,
670 &cu, 0, 0, 0);
sewardj2d94c112002-06-03 01:25:54 +0000671 my_assert(res == 0);
sewardj8ad94e12002-05-29 00:10:20 +0000672}
673
674
675void _pthread_cleanup_push_defer (struct _pthread_cleanup_buffer *__buffer,
676 void (*__routine) (void *),
677 void *__arg)
678{
679 /* As _pthread_cleanup_push, but first save the thread's original
680 cancellation type in __buffer and set it to Deferred. */
681 int orig_ctype;
682 ensure_valgrind("_pthread_cleanup_push_defer");
683 /* Set to Deferred, and put the old cancellation type in res. */
sewardj2d94c112002-06-03 01:25:54 +0000684 my_assert(-1 != PTHREAD_CANCEL_DEFERRED);
685 my_assert(-1 != PTHREAD_CANCEL_ASYNCHRONOUS);
686 my_assert(sizeof(struct _pthread_cleanup_buffer) >= sizeof(int));
sewardj8ad94e12002-05-29 00:10:20 +0000687 VALGRIND_MAGIC_SEQUENCE(orig_ctype, (-1) /* default */,
688 VG_USERREQ__SET_CANCELTYPE,
689 PTHREAD_CANCEL_DEFERRED, 0, 0, 0);
sewardj2d94c112002-06-03 01:25:54 +0000690 my_assert(orig_ctype != -1);
sewardj8ad94e12002-05-29 00:10:20 +0000691 *((int*)(__buffer)) = orig_ctype;
692 /* Now push the cleanup. */
693 _pthread_cleanup_push(NULL, __routine, __arg);
694}
695
696
697void _pthread_cleanup_pop (struct _pthread_cleanup_buffer *__buffer,
698 int __execute)
699{
700 int res;
701 CleanupEntry cu;
702 ensure_valgrind("_pthread_cleanup_push");
703 cu.fn = cu.arg = NULL; /* paranoia */
704 VALGRIND_MAGIC_SEQUENCE(res, (-1) /* default */,
705 VG_USERREQ__CLEANUP_POP,
706 &cu, 0, 0, 0);
707 if (res == 0) {
708 /* pop succeeded */
709 if (__execute) {
710 cu.fn ( cu.arg );
711 }
712 return;
713 }
714 if (res == -1) {
715 /* stack underflow */
716 return;
717 }
718 barf("_pthread_cleanup_pop");
719}
720
721
722void _pthread_cleanup_pop_restore (struct _pthread_cleanup_buffer *__buffer,
723 int __execute)
724{
725 int orig_ctype, fake_ctype;
726 /* As _pthread_cleanup_pop, but after popping/running the handler,
727 restore the thread's original cancellation type from the first
728 word of __buffer. */
729 _pthread_cleanup_pop(NULL, __execute);
730 orig_ctype = *((int*)(__buffer));
sewardj2d94c112002-06-03 01:25:54 +0000731 my_assert(orig_ctype == PTHREAD_CANCEL_DEFERRED
sewardj8ad94e12002-05-29 00:10:20 +0000732 || orig_ctype == PTHREAD_CANCEL_ASYNCHRONOUS);
sewardj2d94c112002-06-03 01:25:54 +0000733 my_assert(-1 != PTHREAD_CANCEL_DEFERRED);
734 my_assert(-1 != PTHREAD_CANCEL_ASYNCHRONOUS);
735 my_assert(sizeof(struct _pthread_cleanup_buffer) >= sizeof(int));
sewardj8ad94e12002-05-29 00:10:20 +0000736 VALGRIND_MAGIC_SEQUENCE(fake_ctype, (-1) /* default */,
737 VG_USERREQ__SET_CANCELTYPE,
738 orig_ctype, 0, 0, 0);
sewardj2d94c112002-06-03 01:25:54 +0000739 my_assert(fake_ctype == PTHREAD_CANCEL_DEFERRED);
sewardj8ad94e12002-05-29 00:10:20 +0000740}
741
742
743/* ---------------------------------------------------
sewardjf8f819e2002-04-17 23:21:37 +0000744 MUTEX ATTRIBUTES
745 ------------------------------------------------ */
746
sewardj5905fae2002-04-26 13:25:00 +0000747int __pthread_mutexattr_init(pthread_mutexattr_t *attr)
sewardje663cb92002-04-12 10:26:32 +0000748{
sewardjf8f819e2002-04-17 23:21:37 +0000749 attr->__mutexkind = PTHREAD_MUTEX_ERRORCHECK_NP;
sewardj8937c812002-04-12 20:12:20 +0000750 return 0;
sewardje663cb92002-04-12 10:26:32 +0000751}
752
sewardj5905fae2002-04-26 13:25:00 +0000753int __pthread_mutexattr_settype(pthread_mutexattr_t *attr, int type)
sewardjf8f819e2002-04-17 23:21:37 +0000754{
755 switch (type) {
sewardj3b13f0e2002-04-25 20:17:29 +0000756# ifndef GLIBC_2_1
sewardjf8f819e2002-04-17 23:21:37 +0000757 case PTHREAD_MUTEX_TIMED_NP:
sewardj2a1dcce2002-04-22 12:45:25 +0000758 case PTHREAD_MUTEX_ADAPTIVE_NP:
sewardj3b13f0e2002-04-25 20:17:29 +0000759# endif
sewardja1679dd2002-05-10 22:31:40 +0000760# ifdef GLIBC_2_1
sewardj68b2dd92002-05-10 21:03:56 +0000761 case PTHREAD_MUTEX_FAST_NP:
sewardja1679dd2002-05-10 22:31:40 +0000762# endif
sewardjf8f819e2002-04-17 23:21:37 +0000763 case PTHREAD_MUTEX_RECURSIVE_NP:
764 case PTHREAD_MUTEX_ERRORCHECK_NP:
sewardjf8f819e2002-04-17 23:21:37 +0000765 attr->__mutexkind = type;
766 return 0;
767 default:
sewardj4dced352002-06-04 22:54:20 +0000768 pthread_error("pthread_mutexattr_settype: "
769 "invalid type");
sewardjf8f819e2002-04-17 23:21:37 +0000770 return EINVAL;
771 }
772}
773
sewardj5905fae2002-04-26 13:25:00 +0000774int __pthread_mutexattr_destroy(pthread_mutexattr_t *attr)
sewardjf8f819e2002-04-17 23:21:37 +0000775{
776 return 0;
777}
778
779
780/* ---------------------------------------------------
781 MUTEXes
782 ------------------------------------------------ */
783
sewardj5905fae2002-04-26 13:25:00 +0000784int __pthread_mutex_init(pthread_mutex_t *mutex,
785 const pthread_mutexattr_t *mutexattr)
sewardje663cb92002-04-12 10:26:32 +0000786{
sewardj604ec3c2002-04-18 22:38:41 +0000787 mutex->__m_count = 0;
788 mutex->__m_owner = (_pthread_descr)VG_INVALID_THREADID;
789 mutex->__m_kind = PTHREAD_MUTEX_ERRORCHECK_NP;
790 if (mutexattr)
791 mutex->__m_kind = mutexattr->__mutexkind;
792 return 0;
sewardje663cb92002-04-12 10:26:32 +0000793}
794
sewardj439d45e2002-05-03 20:43:10 +0000795
sewardj5905fae2002-04-26 13:25:00 +0000796int __pthread_mutex_lock(pthread_mutex_t *mutex)
sewardje663cb92002-04-12 10:26:32 +0000797{
798 int res;
sewardj436e0582002-04-26 14:31:40 +0000799 static int moans = N_MOANS;
sewardj439d45e2002-05-03 20:43:10 +0000800 if (RUNNING_ON_VALGRIND) {
sewardje663cb92002-04-12 10:26:32 +0000801 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
802 VG_USERREQ__PTHREAD_MUTEX_LOCK,
803 mutex, 0, 0, 0);
804 return res;
sewardj439d45e2002-05-03 20:43:10 +0000805 } else {
806 if (moans-- > 0)
807 not_inside("pthread_mutex_lock");
808 return 0; /* success */
sewardje663cb92002-04-12 10:26:32 +0000809 }
810}
811
sewardj439d45e2002-05-03 20:43:10 +0000812
sewardj5905fae2002-04-26 13:25:00 +0000813int __pthread_mutex_trylock(pthread_mutex_t *mutex)
sewardj30671ff2002-04-21 00:13:57 +0000814{
815 int res;
sewardj436e0582002-04-26 14:31:40 +0000816 static int moans = N_MOANS;
sewardj439d45e2002-05-03 20:43:10 +0000817 if (RUNNING_ON_VALGRIND) {
sewardj30671ff2002-04-21 00:13:57 +0000818 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
819 VG_USERREQ__PTHREAD_MUTEX_TRYLOCK,
820 mutex, 0, 0, 0);
821 return res;
sewardj439d45e2002-05-03 20:43:10 +0000822 } else {
823 if (moans-- > 0)
824 not_inside("pthread_mutex_trylock");
825 return 0;
sewardj30671ff2002-04-21 00:13:57 +0000826 }
827}
828
sewardj439d45e2002-05-03 20:43:10 +0000829
sewardj5905fae2002-04-26 13:25:00 +0000830int __pthread_mutex_unlock(pthread_mutex_t *mutex)
sewardje663cb92002-04-12 10:26:32 +0000831{
832 int res;
sewardj436e0582002-04-26 14:31:40 +0000833 static int moans = N_MOANS;
sewardj439d45e2002-05-03 20:43:10 +0000834 if (RUNNING_ON_VALGRIND) {
sewardje663cb92002-04-12 10:26:32 +0000835 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
836 VG_USERREQ__PTHREAD_MUTEX_UNLOCK,
837 mutex, 0, 0, 0);
838 return res;
sewardj439d45e2002-05-03 20:43:10 +0000839 } else {
840 if (moans-- > 0)
841 not_inside("pthread_mutex_unlock");
842 return 0;
sewardje663cb92002-04-12 10:26:32 +0000843 }
844}
845
sewardj439d45e2002-05-03 20:43:10 +0000846
sewardj5905fae2002-04-26 13:25:00 +0000847int __pthread_mutex_destroy(pthread_mutex_t *mutex)
sewardje663cb92002-04-12 10:26:32 +0000848{
sewardj604ec3c2002-04-18 22:38:41 +0000849 /* Valgrind doesn't hold any resources on behalf of the mutex, so no
850 need to involve it. */
sewardj4dced352002-06-04 22:54:20 +0000851 if (mutex->__m_count > 0) {
852 pthread_error("pthread_mutex_destroy: "
853 "mutex is still in use");
sewardj604ec3c2002-04-18 22:38:41 +0000854 return EBUSY;
sewardj4dced352002-06-04 22:54:20 +0000855 }
856 mutex->__m_count = 0;
857 mutex->__m_owner = (_pthread_descr)VG_INVALID_THREADID;
858 mutex->__m_kind = PTHREAD_MUTEX_ERRORCHECK_NP;
859 return 0;
sewardje663cb92002-04-12 10:26:32 +0000860}
861
862
sewardjf8f819e2002-04-17 23:21:37 +0000863/* ---------------------------------------------------
sewardj6072c362002-04-19 14:40:57 +0000864 CONDITION VARIABLES
865 ------------------------------------------------ */
866
867/* LinuxThreads supports no attributes for conditions. Hence ... */
868
869int pthread_condattr_init(pthread_condattr_t *attr)
870{
871 return 0;
872}
873
sewardj0738a592002-04-20 13:59:33 +0000874int pthread_condattr_destroy(pthread_condattr_t *attr)
875{
876 return 0;
877}
sewardj6072c362002-04-19 14:40:57 +0000878
879int pthread_cond_init( pthread_cond_t *cond,
880 const pthread_condattr_t *cond_attr)
881{
882 cond->__c_waiting = (_pthread_descr)VG_INVALID_THREADID;
883 return 0;
884}
885
sewardjf854f472002-04-21 12:19:41 +0000886int pthread_cond_destroy(pthread_cond_t *cond)
887{
888 /* should check that no threads are waiting on this CV */
sewardj436e0582002-04-26 14:31:40 +0000889 static int moans = N_MOANS;
890 if (moans-- > 0)
891 kludged("pthread_cond_destroy");
sewardjf854f472002-04-21 12:19:41 +0000892 return 0;
893}
sewardj6072c362002-04-19 14:40:57 +0000894
895/* ---------------------------------------------------
896 SCHEDULING
897 ------------------------------------------------ */
898
899/* This is completely bogus. */
900int pthread_getschedparam(pthread_t target_thread,
901 int *policy,
902 struct sched_param *param)
903{
sewardj436e0582002-04-26 14:31:40 +0000904 static int moans = N_MOANS;
905 if (moans-- > 0)
906 kludged("pthread_getschedparam");
sewardj6072c362002-04-19 14:40:57 +0000907 if (policy) *policy = SCHED_OTHER;
sewardj3e909ce2002-06-03 13:27:15 +0000908# ifdef HAVE_SCHED_PRIORITY
sewardj2a1dcce2002-04-22 12:45:25 +0000909 if (param) param->sched_priority = 0; /* who knows */
910# else
sewardj6072c362002-04-19 14:40:57 +0000911 if (param) param->__sched_priority = 0; /* who knows */
sewardj2a1dcce2002-04-22 12:45:25 +0000912# endif
sewardj6072c362002-04-19 14:40:57 +0000913 return 0;
914}
915
916int pthread_setschedparam(pthread_t target_thread,
917 int policy,
918 const struct sched_param *param)
919{
sewardj436e0582002-04-26 14:31:40 +0000920 static int moans = N_MOANS;
921 if (moans-- > 0)
922 ignored("pthread_setschedparam");
sewardj6072c362002-04-19 14:40:57 +0000923 return 0;
924}
925
sewardj3b5d8862002-04-20 13:53:23 +0000926int pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex)
927{
928 int res;
929 ensure_valgrind("pthread_cond_wait");
930 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
931 VG_USERREQ__PTHREAD_COND_WAIT,
932 cond, mutex, 0, 0);
933 return res;
934}
935
sewardj5f07b662002-04-23 16:52:51 +0000936int pthread_cond_timedwait ( pthread_cond_t *cond,
937 pthread_mutex_t *mutex,
938 const struct timespec *abstime )
939{
940 int res;
941 unsigned int ms_now, ms_end;
942 struct timeval timeval_now;
943 unsigned long long int ull_ms_now_after_1970;
944 unsigned long long int ull_ms_end_after_1970;
945
946 ensure_valgrind("pthread_cond_timedwait");
947 VALGRIND_MAGIC_SEQUENCE(ms_now, 0xFFFFFFFF /* default */,
948 VG_USERREQ__READ_MILLISECOND_TIMER,
949 0, 0, 0, 0);
sewardj2d94c112002-06-03 01:25:54 +0000950 my_assert(ms_now != 0xFFFFFFFF);
sewardj5f07b662002-04-23 16:52:51 +0000951 res = gettimeofday(&timeval_now, NULL);
sewardj2d94c112002-06-03 01:25:54 +0000952 my_assert(res == 0);
sewardj5f07b662002-04-23 16:52:51 +0000953
954 ull_ms_now_after_1970
955 = 1000ULL * ((unsigned long long int)(timeval_now.tv_sec))
956 + ((unsigned long long int)(timeval_now.tv_usec / 1000000));
957 ull_ms_end_after_1970
958 = 1000ULL * ((unsigned long long int)(abstime->tv_sec))
959 + ((unsigned long long int)(abstime->tv_nsec / 1000000));
sewardjd8e919e2002-05-29 20:13:53 +0000960 if (ull_ms_end_after_1970 < ull_ms_now_after_1970)
961 ull_ms_end_after_1970 = ull_ms_now_after_1970;
sewardj5f07b662002-04-23 16:52:51 +0000962 ms_end
963 = ms_now + (unsigned int)(ull_ms_end_after_1970 - ull_ms_now_after_1970);
964 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
965 VG_USERREQ__PTHREAD_COND_TIMEDWAIT,
966 cond, mutex, ms_end, 0);
967 return res;
968}
969
970
sewardj3b5d8862002-04-20 13:53:23 +0000971int pthread_cond_signal(pthread_cond_t *cond)
972{
973 int res;
974 ensure_valgrind("pthread_cond_signal");
975 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
976 VG_USERREQ__PTHREAD_COND_SIGNAL,
977 cond, 0, 0, 0);
978 return res;
979}
980
981int pthread_cond_broadcast(pthread_cond_t *cond)
982{
983 int res;
984 ensure_valgrind("pthread_cond_broadcast");
985 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
986 VG_USERREQ__PTHREAD_COND_BROADCAST,
987 cond, 0, 0, 0);
988 return res;
989}
990
sewardj6072c362002-04-19 14:40:57 +0000991
992/* ---------------------------------------------------
sewardjf8f819e2002-04-17 23:21:37 +0000993 CANCELLATION
994 ------------------------------------------------ */
995
sewardj853f55d2002-04-26 00:27:53 +0000996int pthread_setcancelstate(int state, int *oldstate)
997{
sewardj20917d82002-05-28 01:36:45 +0000998 int res;
999 ensure_valgrind("pthread_setcancelstate");
1000 if (state != PTHREAD_CANCEL_ENABLE
sewardj4dced352002-06-04 22:54:20 +00001001 && state != PTHREAD_CANCEL_DISABLE) {
1002 pthread_error("pthread_setcancelstate: "
1003 "invalid state");
sewardj20917d82002-05-28 01:36:45 +00001004 return EINVAL;
sewardj4dced352002-06-04 22:54:20 +00001005 }
sewardj2d94c112002-06-03 01:25:54 +00001006 my_assert(-1 != PTHREAD_CANCEL_ENABLE);
1007 my_assert(-1 != PTHREAD_CANCEL_DISABLE);
sewardj20917d82002-05-28 01:36:45 +00001008 VALGRIND_MAGIC_SEQUENCE(res, (-1) /* default */,
1009 VG_USERREQ__SET_CANCELSTATE,
1010 state, 0, 0, 0);
sewardj2d94c112002-06-03 01:25:54 +00001011 my_assert(res != -1);
sewardj20917d82002-05-28 01:36:45 +00001012 if (oldstate)
1013 *oldstate = res;
sewardj853f55d2002-04-26 00:27:53 +00001014 return 0;
1015}
1016
sewardje663cb92002-04-12 10:26:32 +00001017int pthread_setcanceltype(int type, int *oldtype)
1018{
sewardj20917d82002-05-28 01:36:45 +00001019 int res;
1020 ensure_valgrind("pthread_setcanceltype");
1021 if (type != PTHREAD_CANCEL_DEFERRED
sewardj4dced352002-06-04 22:54:20 +00001022 && type != PTHREAD_CANCEL_ASYNCHRONOUS) {
1023 pthread_error("pthread_setcanceltype: "
1024 "invalid type");
sewardj20917d82002-05-28 01:36:45 +00001025 return EINVAL;
sewardj4dced352002-06-04 22:54:20 +00001026 }
sewardj2d94c112002-06-03 01:25:54 +00001027 my_assert(-1 != PTHREAD_CANCEL_DEFERRED);
1028 my_assert(-1 != PTHREAD_CANCEL_ASYNCHRONOUS);
sewardj20917d82002-05-28 01:36:45 +00001029 VALGRIND_MAGIC_SEQUENCE(res, (-1) /* default */,
1030 VG_USERREQ__SET_CANCELTYPE,
1031 type, 0, 0, 0);
sewardj2d94c112002-06-03 01:25:54 +00001032 my_assert(res != -1);
sewardj20917d82002-05-28 01:36:45 +00001033 if (oldtype)
1034 *oldtype = res;
sewardje663cb92002-04-12 10:26:32 +00001035 return 0;
1036}
1037
sewardje663cb92002-04-12 10:26:32 +00001038int pthread_cancel(pthread_t thread)
1039{
1040 int res;
1041 ensure_valgrind("pthread_cancel");
sewardj20917d82002-05-28 01:36:45 +00001042 VALGRIND_MAGIC_SEQUENCE(res, (-1) /* default */,
1043 VG_USERREQ__SET_CANCELPEND,
1044 thread, &thread_exit_wrapper, 0, 0);
sewardj2d94c112002-06-03 01:25:54 +00001045 my_assert(res != -1);
sewardje663cb92002-04-12 10:26:32 +00001046 return res;
1047}
1048
sewardjd140e442002-05-29 01:21:19 +00001049static __inline__
1050void __my_pthread_testcancel(void)
sewardj853f55d2002-04-26 00:27:53 +00001051{
sewardj20917d82002-05-28 01:36:45 +00001052 int res;
njn25e49d8e72002-09-23 09:36:25 +00001053 ensure_valgrind("__my_pthread_testcancel");
sewardj20917d82002-05-28 01:36:45 +00001054 VALGRIND_MAGIC_SEQUENCE(res, (-1) /* default */,
1055 VG_USERREQ__TESTCANCEL,
1056 0, 0, 0, 0);
sewardj2d94c112002-06-03 01:25:54 +00001057 my_assert(res == 0);
sewardj853f55d2002-04-26 00:27:53 +00001058}
1059
sewardjd140e442002-05-29 01:21:19 +00001060void pthread_testcancel ( void )
1061{
1062 __my_pthread_testcancel();
1063}
1064
sewardj20917d82002-05-28 01:36:45 +00001065
sewardjef037c72002-05-30 00:40:03 +00001066/* Not really sure what this is for. I suspect for doing the POSIX
1067 requirements for fork() and exec(). We do this internally anyway
1068 whenever those syscalls are observed, so this could be superfluous,
1069 but hey ...
1070*/
sewardj853f55d2002-04-26 00:27:53 +00001071void __pthread_kill_other_threads_np ( void )
1072{
sewardjef037c72002-05-30 00:40:03 +00001073 int res;
1074 ensure_valgrind("__pthread_kill_other_threads_np");
1075 VALGRIND_MAGIC_SEQUENCE(res, (-1) /* default */,
1076 VG_USERREQ__NUKE_OTHER_THREADS,
1077 0, 0, 0, 0);
sewardj2d94c112002-06-03 01:25:54 +00001078 my_assert(res == 0);
sewardj853f55d2002-04-26 00:27:53 +00001079}
1080
sewardje663cb92002-04-12 10:26:32 +00001081
sewardjf8f819e2002-04-17 23:21:37 +00001082/* ---------------------------------------------------
sewardjb48e5002002-05-13 00:16:03 +00001083 SIGNALS
1084 ------------------------------------------------ */
1085
1086#include <signal.h>
1087
1088int pthread_sigmask(int how, const sigset_t *newmask,
1089 sigset_t *oldmask)
1090{
1091 int res;
1092
1093 /* A bit subtle, because the scheduler expects newmask and oldmask
1094 to be vki_sigset_t* rather than sigset_t*, and the two are
1095 different. Fortunately the first 64 bits of a sigset_t are
1096 exactly a vki_sigset_t, so we just pass the pointers through
1097 unmodified. Haaaack!
1098
1099 Also mash the how value so that the SIG_ constants from glibc
sewardj018f7622002-05-15 21:13:39 +00001100 constants to VKI_ constants, so that the former do not have to
1101 be included into vg_scheduler.c. */
sewardjb48e5002002-05-13 00:16:03 +00001102
1103 ensure_valgrind("pthread_sigmask");
1104
1105 switch (how) {
sewardj018f7622002-05-15 21:13:39 +00001106 case SIG_SETMASK: how = VKI_SIG_SETMASK; break;
1107 case SIG_BLOCK: how = VKI_SIG_BLOCK; break;
1108 case SIG_UNBLOCK: how = VKI_SIG_UNBLOCK; break;
sewardj4dced352002-06-04 22:54:20 +00001109 default: pthread_error("pthread_sigmask: invalid how");
1110 return EINVAL;
sewardjb48e5002002-05-13 00:16:03 +00001111 }
1112
1113 /* Crude check */
1114 if (newmask == NULL)
1115 return EFAULT;
1116
1117 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
1118 VG_USERREQ__PTHREAD_SIGMASK,
1119 how, newmask, oldmask, 0);
1120
1121 /* The scheduler tells us of any memory violations. */
1122 return res == 0 ? 0 : EFAULT;
1123}
1124
1125
1126int sigwait ( const sigset_t* set, int* sig )
1127{
1128 int res;
1129 ensure_valgrind("sigwait");
1130 /* As with pthread_sigmask we deliberately confuse sigset_t with
1131 vki_ksigset_t. */
1132 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
1133 VG_USERREQ__SIGWAIT,
1134 set, sig, 0, 0);
1135 return res;
1136}
1137
1138
sewardj018f7622002-05-15 21:13:39 +00001139int pthread_kill(pthread_t thread, int signo)
1140{
1141 int res;
1142 ensure_valgrind("pthread_kill");
1143 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
1144 VG_USERREQ__PTHREAD_KILL,
1145 thread, signo, 0, 0);
1146 return res;
1147}
1148
1149
sewardj3665ded2002-05-16 16:57:25 +00001150/* Copied verbatim from Linuxthreads */
1151/* Redefine raise() to send signal to calling thread only,
1152 as per POSIX 1003.1c */
1153int raise (int sig)
1154{
1155 int retcode = pthread_kill(pthread_self(), sig);
sewardj4dced352002-06-04 22:54:20 +00001156 if (retcode == 0) {
sewardj3665ded2002-05-16 16:57:25 +00001157 return 0;
sewardj4dced352002-06-04 22:54:20 +00001158 } else {
sewardj3665ded2002-05-16 16:57:25 +00001159 errno = retcode;
1160 return -1;
1161 }
1162}
1163
1164
sewardj9a2224b2002-06-19 10:17:40 +00001165int pause ( void )
1166{
1167 unsigned int n_orig, n_now;
1168 struct vki_timespec nanosleep_interval;
1169 ensure_valgrind("pause");
1170
1171 /* This is surely a cancellation point. */
1172 __my_pthread_testcancel();
1173
1174 VALGRIND_MAGIC_SEQUENCE(n_orig, 0xFFFFFFFF /* default */,
1175 VG_USERREQ__GET_N_SIGS_RETURNED,
1176 0, 0, 0, 0);
1177 my_assert(n_orig != 0xFFFFFFFF);
1178
1179 while (1) {
1180 VALGRIND_MAGIC_SEQUENCE(n_now, 0xFFFFFFFF /* default */,
1181 VG_USERREQ__GET_N_SIGS_RETURNED,
1182 0, 0, 0, 0);
1183 my_assert(n_now != 0xFFFFFFFF);
1184 my_assert(n_now >= n_orig);
1185 if (n_now != n_orig) break;
1186
1187 nanosleep_interval.tv_sec = 0;
njn25e49d8e72002-09-23 09:36:25 +00001188 nanosleep_interval.tv_nsec = 12 * 1000 * 1000; /* 12 milliseconds */
sewardj9a2224b2002-06-19 10:17:40 +00001189 /* It's critical here that valgrind's nanosleep implementation
1190 is nonblocking. */
1191 (void)my_do_syscall2(__NR_nanosleep,
1192 (int)(&nanosleep_interval), (int)NULL);
1193 }
1194
1195 * (__errno_location()) = EINTR;
1196 return -1;
1197}
1198
1199
sewardjb48e5002002-05-13 00:16:03 +00001200/* ---------------------------------------------------
sewardjf8f819e2002-04-17 23:21:37 +00001201 THREAD-SPECIFICs
1202 ------------------------------------------------ */
sewardj5e5fa512002-04-14 13:13:05 +00001203
sewardj5905fae2002-04-26 13:25:00 +00001204int __pthread_key_create(pthread_key_t *key,
1205 void (*destr_function) (void *))
sewardj5e5fa512002-04-14 13:13:05 +00001206{
sewardj5f07b662002-04-23 16:52:51 +00001207 int res;
1208 ensure_valgrind("pthread_key_create");
1209 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
1210 VG_USERREQ__PTHREAD_KEY_CREATE,
1211 key, destr_function, 0, 0);
1212 return res;
sewardj5e5fa512002-04-14 13:13:05 +00001213}
1214
1215int pthread_key_delete(pthread_key_t key)
1216{
sewardj436e0582002-04-26 14:31:40 +00001217 static int moans = N_MOANS;
1218 if (moans-- > 0)
1219 ignored("pthread_key_delete");
sewardj5e5fa512002-04-14 13:13:05 +00001220 return 0;
1221}
1222
sewardj5905fae2002-04-26 13:25:00 +00001223int __pthread_setspecific(pthread_key_t key, const void *pointer)
sewardj5e5fa512002-04-14 13:13:05 +00001224{
sewardj5f07b662002-04-23 16:52:51 +00001225 int res;
1226 ensure_valgrind("pthread_setspecific");
1227 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
1228 VG_USERREQ__PTHREAD_SETSPECIFIC,
1229 key, pointer, 0, 0);
1230 return res;
sewardj5e5fa512002-04-14 13:13:05 +00001231}
1232
sewardj5905fae2002-04-26 13:25:00 +00001233void * __pthread_getspecific(pthread_key_t key)
sewardj5e5fa512002-04-14 13:13:05 +00001234{
sewardj5f07b662002-04-23 16:52:51 +00001235 int res;
1236 ensure_valgrind("pthread_getspecific");
1237 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
1238 VG_USERREQ__PTHREAD_GETSPECIFIC,
1239 key, 0 , 0, 0);
1240 return (void*)res;
sewardj5e5fa512002-04-14 13:13:05 +00001241}
1242
sewardjf8f819e2002-04-17 23:21:37 +00001243
1244/* ---------------------------------------------------
sewardj89d3d852002-04-24 19:21:39 +00001245 ONCEry
1246 ------------------------------------------------ */
1247
1248static pthread_mutex_t once_masterlock = PTHREAD_MUTEX_INITIALIZER;
1249
1250
sewardj5905fae2002-04-26 13:25:00 +00001251int __pthread_once ( pthread_once_t *once_control,
1252 void (*init_routine) (void) )
sewardj89d3d852002-04-24 19:21:39 +00001253{
1254 int res;
1255 ensure_valgrind("pthread_once");
1256
sewardj68b2dd92002-05-10 21:03:56 +00001257 res = __pthread_mutex_lock(&once_masterlock);
sewardj89d3d852002-04-24 19:21:39 +00001258
sewardj68b2dd92002-05-10 21:03:56 +00001259 if (res != 0) {
sewardj89d3d852002-04-24 19:21:39 +00001260 barf("pthread_once: Looks like your program's "
1261 "init routine calls back to pthread_once() ?!");
sewardj68b2dd92002-05-10 21:03:56 +00001262 }
sewardj89d3d852002-04-24 19:21:39 +00001263
1264 if (*once_control == 0) {
1265 *once_control = 1;
1266 init_routine();
1267 }
1268
sewardj68b2dd92002-05-10 21:03:56 +00001269 __pthread_mutex_unlock(&once_masterlock);
sewardj89d3d852002-04-24 19:21:39 +00001270
1271 return 0;
1272}
1273
1274
1275/* ---------------------------------------------------
sewardj853f55d2002-04-26 00:27:53 +00001276 MISC
1277 ------------------------------------------------ */
1278
sewardj2cb00342002-06-28 01:46:26 +00001279static pthread_mutex_t pthread_atfork_lock
1280 = PTHREAD_MUTEX_INITIALIZER;
1281
sewardj5905fae2002-04-26 13:25:00 +00001282int __pthread_atfork ( void (*prepare)(void),
1283 void (*parent)(void),
1284 void (*child)(void) )
sewardj853f55d2002-04-26 00:27:53 +00001285{
sewardj2cb00342002-06-28 01:46:26 +00001286 int n, res;
1287 ForkHandlerEntry entry;
1288
1289 ensure_valgrind("pthread_atfork");
1290 __pthread_mutex_lock(&pthread_atfork_lock);
1291
1292 /* Fetch old counter */
1293 VALGRIND_MAGIC_SEQUENCE(n, -2 /* default */,
1294 VG_USERREQ__GET_FHSTACK_USED,
1295 0, 0, 0, 0);
1296 my_assert(n >= 0 && n < VG_N_FORKHANDLERSTACK);
1297 if (n == VG_N_FORKHANDLERSTACK-1)
1298 barf("pthread_atfork: VG_N_FORKHANDLERSTACK is too low; "
1299 "increase and recompile");
1300
1301 /* Add entry */
1302 entry.prepare = *prepare;
1303 entry.parent = *parent;
1304 entry.child = *child;
1305 VALGRIND_MAGIC_SEQUENCE(res, -2 /* default */,
1306 VG_USERREQ__SET_FHSTACK_ENTRY,
1307 n, &entry, 0, 0);
1308 my_assert(res == 0);
1309
1310 /* Bump counter */
1311 VALGRIND_MAGIC_SEQUENCE(res, -2 /* default */,
1312 VG_USERREQ__SET_FHSTACK_USED,
1313 n+1, 0, 0, 0);
1314 my_assert(res == 0);
1315
1316 __pthread_mutex_unlock(&pthread_atfork_lock);
1317 return 0;
sewardj853f55d2002-04-26 00:27:53 +00001318}
1319
1320
sewardjbb990782002-05-08 02:01:14 +00001321__attribute__((weak))
1322void __pthread_initialize ( void )
1323{
sewardjbea1caa2002-05-10 23:20:58 +00001324 ensure_valgrind("__pthread_initialize");
sewardjbb990782002-05-08 02:01:14 +00001325}
1326
1327
sewardj853f55d2002-04-26 00:27:53 +00001328/* ---------------------------------------------------
sewardj3b13f0e2002-04-25 20:17:29 +00001329 LIBRARY-PRIVATE THREAD SPECIFIC STATE
sewardjf8f819e2002-04-17 23:21:37 +00001330 ------------------------------------------------ */
1331
sewardj3b13f0e2002-04-25 20:17:29 +00001332#include <resolv.h>
1333static int thread_specific_errno[VG_N_THREADS];
1334static int thread_specific_h_errno[VG_N_THREADS];
1335static struct __res_state
1336 thread_specific_res_state[VG_N_THREADS];
sewardjf8f819e2002-04-17 23:21:37 +00001337
sewardj3b13f0e2002-04-25 20:17:29 +00001338int* __errno_location ( void )
sewardjf8f819e2002-04-17 23:21:37 +00001339{
1340 int tid;
sewardj3b13f0e2002-04-25 20:17:29 +00001341 /* ensure_valgrind("__errno_location"); */
1342 VALGRIND_MAGIC_SEQUENCE(tid, 1 /* default */,
sewardjf8f819e2002-04-17 23:21:37 +00001343 VG_USERREQ__PTHREAD_GET_THREADID,
1344 0, 0, 0, 0);
sewardj3b13f0e2002-04-25 20:17:29 +00001345 /* 'cos I'm paranoid ... */
sewardj439d45e2002-05-03 20:43:10 +00001346 if (tid < 1 || tid >= VG_N_THREADS)
sewardj3b13f0e2002-04-25 20:17:29 +00001347 barf("__errno_location: invalid ThreadId");
1348 return & thread_specific_errno[tid];
1349}
1350
1351int* __h_errno_location ( void )
1352{
1353 int tid;
1354 /* ensure_valgrind("__h_errno_location"); */
1355 VALGRIND_MAGIC_SEQUENCE(tid, 1 /* default */,
1356 VG_USERREQ__PTHREAD_GET_THREADID,
1357 0, 0, 0, 0);
1358 /* 'cos I'm paranoid ... */
sewardj439d45e2002-05-03 20:43:10 +00001359 if (tid < 1 || tid >= VG_N_THREADS)
sewardj3b13f0e2002-04-25 20:17:29 +00001360 barf("__h_errno_location: invalid ThreadId");
1361 return & thread_specific_h_errno[tid];
1362}
1363
sewardjb0ff1032002-08-06 09:02:53 +00001364
1365#undef _res
1366extern struct __res_state _res;
1367
sewardj3b13f0e2002-04-25 20:17:29 +00001368struct __res_state* __res_state ( void )
1369{
1370 int tid;
1371 /* ensure_valgrind("__res_state"); */
1372 VALGRIND_MAGIC_SEQUENCE(tid, 1 /* default */,
1373 VG_USERREQ__PTHREAD_GET_THREADID,
1374 0, 0, 0, 0);
1375 /* 'cos I'm paranoid ... */
sewardj439d45e2002-05-03 20:43:10 +00001376 if (tid < 1 || tid >= VG_N_THREADS)
sewardj3b13f0e2002-04-25 20:17:29 +00001377 barf("__res_state: invalid ThreadId");
sewardjb0ff1032002-08-06 09:02:53 +00001378 if (tid == 1)
1379 return & _res;
sewardj3b13f0e2002-04-25 20:17:29 +00001380 return & thread_specific_res_state[tid];
sewardjf8f819e2002-04-17 23:21:37 +00001381}
1382
1383
sewardj5716dbb2002-04-26 03:28:18 +00001384/* ---------------------------------------------------
1385 LIBC-PRIVATE SPECIFIC DATA
1386 ------------------------------------------------ */
1387
1388/* Relies on assumption that initial private data is NULL. This
1389 should be fixed somehow. */
1390
njn25e49d8e72002-09-23 09:36:25 +00001391/* The allowable keys (indices) (all 3 of them).
sewardj5716dbb2002-04-26 03:28:18 +00001392 From sysdeps/pthread/bits/libc-tsd.h
1393*/
njn25e49d8e72002-09-23 09:36:25 +00001394#define N_LIBC_TSD_EXTRA_KEYS 0
sewardj70adeb22002-04-27 01:35:38 +00001395
sewardj5716dbb2002-04-26 03:28:18 +00001396enum __libc_tsd_key_t { _LIBC_TSD_KEY_MALLOC = 0,
1397 _LIBC_TSD_KEY_DL_ERROR,
njn25e49d8e72002-09-23 09:36:25 +00001398 _LIBC_TSD_KEY_RPC_VARS,
sewardj5716dbb2002-04-26 03:28:18 +00001399 _LIBC_TSD_KEY_N };
1400
1401/* Auto-initialising subsystem. libc_specifics_inited is set
1402 after initialisation. libc_specifics_inited_mx guards it. */
1403static int libc_specifics_inited = 0;
1404static pthread_mutex_t libc_specifics_inited_mx = PTHREAD_MUTEX_INITIALIZER;
1405
1406/* These are the keys we must initialise the first time. */
sewardj70adeb22002-04-27 01:35:38 +00001407static pthread_key_t libc_specifics_keys[_LIBC_TSD_KEY_N
1408 + N_LIBC_TSD_EXTRA_KEYS];
sewardj5716dbb2002-04-26 03:28:18 +00001409
1410/* Initialise the keys, if they are not already initialise. */
1411static
1412void init_libc_tsd_keys ( void )
1413{
1414 int res, i;
1415 pthread_key_t k;
1416
1417 res = pthread_mutex_lock(&libc_specifics_inited_mx);
1418 if (res != 0) barf("init_libc_tsd_keys: lock");
1419
1420 if (libc_specifics_inited == 0) {
1421 /* printf("INIT libc specifics\n"); */
1422 libc_specifics_inited = 1;
sewardj70adeb22002-04-27 01:35:38 +00001423 for (i = 0; i < _LIBC_TSD_KEY_N + N_LIBC_TSD_EXTRA_KEYS; i++) {
sewardj5716dbb2002-04-26 03:28:18 +00001424 res = pthread_key_create(&k, NULL);
1425 if (res != 0) barf("init_libc_tsd_keys: create");
1426 libc_specifics_keys[i] = k;
1427 }
1428 }
1429
1430 res = pthread_mutex_unlock(&libc_specifics_inited_mx);
1431 if (res != 0) barf("init_libc_tsd_keys: unlock");
1432}
1433
1434
1435static int
1436libc_internal_tsd_set ( enum __libc_tsd_key_t key,
1437 const void * pointer )
1438{
sewardj70adeb22002-04-27 01:35:38 +00001439 int res;
1440 static int moans = N_MOANS;
sewardj5716dbb2002-04-26 03:28:18 +00001441 /* printf("SET SET SET key %d ptr %p\n", key, pointer); */
sewardj70adeb22002-04-27 01:35:38 +00001442 if (key < _LIBC_TSD_KEY_MALLOC
1443 || key >= _LIBC_TSD_KEY_N + N_LIBC_TSD_EXTRA_KEYS)
sewardj5716dbb2002-04-26 03:28:18 +00001444 barf("libc_internal_tsd_set: invalid key");
sewardj70adeb22002-04-27 01:35:38 +00001445 if (key >= _LIBC_TSD_KEY_N && moans-- > 0)
1446 fprintf(stderr,
sewardj439d45e2002-05-03 20:43:10 +00001447 "valgrind's libpthread.so: libc_internal_tsd_set: "
1448 "dubious key %d\n", key);
sewardj5716dbb2002-04-26 03:28:18 +00001449 init_libc_tsd_keys();
1450 res = pthread_setspecific(libc_specifics_keys[key], pointer);
1451 if (res != 0) barf("libc_internal_tsd_set: setspecific failed");
1452 return 0;
1453}
1454
1455static void *
1456libc_internal_tsd_get ( enum __libc_tsd_key_t key )
1457{
sewardj70adeb22002-04-27 01:35:38 +00001458 void* v;
1459 static int moans = N_MOANS;
sewardj5716dbb2002-04-26 03:28:18 +00001460 /* printf("GET GET GET key %d\n", key); */
sewardj70adeb22002-04-27 01:35:38 +00001461 if (key < _LIBC_TSD_KEY_MALLOC
1462 || key >= _LIBC_TSD_KEY_N + N_LIBC_TSD_EXTRA_KEYS)
sewardj5716dbb2002-04-26 03:28:18 +00001463 barf("libc_internal_tsd_get: invalid key");
sewardj70adeb22002-04-27 01:35:38 +00001464 if (key >= _LIBC_TSD_KEY_N && moans-- > 0)
1465 fprintf(stderr,
sewardj439d45e2002-05-03 20:43:10 +00001466 "valgrind's libpthread.so: libc_internal_tsd_get: "
1467 "dubious key %d\n", key);
sewardj5716dbb2002-04-26 03:28:18 +00001468 init_libc_tsd_keys();
1469 v = pthread_getspecific(libc_specifics_keys[key]);
1470 /* if (v == NULL) barf("libc_internal_tsd_set: getspecific failed"); */
1471 return v;
1472}
1473
1474
1475
1476
sewardj70adeb22002-04-27 01:35:38 +00001477int (*__libc_internal_tsd_set)
1478 (enum __libc_tsd_key_t key, const void * pointer)
1479 = libc_internal_tsd_set;
sewardj5716dbb2002-04-26 03:28:18 +00001480
sewardj70adeb22002-04-27 01:35:38 +00001481void* (*__libc_internal_tsd_get)
1482 (enum __libc_tsd_key_t key)
1483 = libc_internal_tsd_get;
sewardj5716dbb2002-04-26 03:28:18 +00001484
1485
sewardje663cb92002-04-12 10:26:32 +00001486/* ---------------------------------------------------------------------
1487 These are here (I think) because they are deemed cancellation
1488 points by POSIX. For the moment we'll simply pass the call along
1489 to the corresponding thread-unaware (?) libc routine.
1490 ------------------------------------------------------------------ */
1491
sewardje663cb92002-04-12 10:26:32 +00001492#include <stdlib.h>
sewardje663cb92002-04-12 10:26:32 +00001493#include <sys/types.h>
1494#include <sys/socket.h>
1495
sewardjd529a442002-05-04 19:49:21 +00001496#ifdef GLIBC_2_1
1497extern
1498int __sigaction
1499 (int signum,
1500 const struct sigaction *act,
1501 struct sigaction *oldact);
1502#else
sewardje663cb92002-04-12 10:26:32 +00001503extern
1504int __libc_sigaction
1505 (int signum,
1506 const struct sigaction *act,
1507 struct sigaction *oldact);
sewardjd529a442002-05-04 19:49:21 +00001508#endif
sewardje663cb92002-04-12 10:26:32 +00001509int sigaction(int signum,
1510 const struct sigaction *act,
1511 struct sigaction *oldact)
1512{
sewardjd140e442002-05-29 01:21:19 +00001513 __my_pthread_testcancel();
sewardj2a1dcce2002-04-22 12:45:25 +00001514# ifdef GLIBC_2_1
1515 return __sigaction(signum, act, oldact);
1516# else
sewardj45b4b372002-04-16 22:50:32 +00001517 return __libc_sigaction(signum, act, oldact);
sewardj2a1dcce2002-04-22 12:45:25 +00001518# endif
sewardje663cb92002-04-12 10:26:32 +00001519}
1520
1521
1522extern
1523int __libc_connect(int sockfd,
1524 const struct sockaddr *serv_addr,
1525 socklen_t addrlen);
sewardj5905fae2002-04-26 13:25:00 +00001526__attribute__((weak))
sewardje663cb92002-04-12 10:26:32 +00001527int connect(int sockfd,
1528 const struct sockaddr *serv_addr,
1529 socklen_t addrlen)
1530{
sewardjd140e442002-05-29 01:21:19 +00001531 __my_pthread_testcancel();
sewardj45b4b372002-04-16 22:50:32 +00001532 return __libc_connect(sockfd, serv_addr, addrlen);
sewardje663cb92002-04-12 10:26:32 +00001533}
1534
1535
1536extern
1537int __libc_fcntl(int fd, int cmd, long arg);
sewardj5905fae2002-04-26 13:25:00 +00001538__attribute__((weak))
sewardje663cb92002-04-12 10:26:32 +00001539int fcntl(int fd, int cmd, long arg)
1540{
sewardjd140e442002-05-29 01:21:19 +00001541 __my_pthread_testcancel();
sewardj45b4b372002-04-16 22:50:32 +00001542 return __libc_fcntl(fd, cmd, arg);
sewardje663cb92002-04-12 10:26:32 +00001543}
1544
1545
1546extern
1547ssize_t __libc_write(int fd, const void *buf, size_t count);
sewardj5905fae2002-04-26 13:25:00 +00001548__attribute__((weak))
sewardje663cb92002-04-12 10:26:32 +00001549ssize_t write(int fd, const void *buf, size_t count)
1550{
sewardjd140e442002-05-29 01:21:19 +00001551 __my_pthread_testcancel();
sewardj45b4b372002-04-16 22:50:32 +00001552 return __libc_write(fd, buf, count);
sewardje663cb92002-04-12 10:26:32 +00001553}
1554
1555
1556extern
1557ssize_t __libc_read(int fd, void *buf, size_t count);
sewardj5905fae2002-04-26 13:25:00 +00001558__attribute__((weak))
sewardje663cb92002-04-12 10:26:32 +00001559ssize_t read(int fd, void *buf, size_t count)
1560{
sewardjd140e442002-05-29 01:21:19 +00001561 __my_pthread_testcancel();
sewardj45b4b372002-04-16 22:50:32 +00001562 return __libc_read(fd, buf, count);
sewardje663cb92002-04-12 10:26:32 +00001563}
1564
sewardjbe32e452002-04-24 20:29:58 +00001565
1566extern
sewardj853f55d2002-04-26 00:27:53 +00001567int __libc_open64(const char *pathname, int flags, mode_t mode);
sewardj5905fae2002-04-26 13:25:00 +00001568__attribute__((weak))
sewardj853f55d2002-04-26 00:27:53 +00001569int open64(const char *pathname, int flags, mode_t mode)
sewardjbe32e452002-04-24 20:29:58 +00001570{
sewardjd140e442002-05-29 01:21:19 +00001571 __my_pthread_testcancel();
sewardj853f55d2002-04-26 00:27:53 +00001572 return __libc_open64(pathname, flags, mode);
sewardjbe32e452002-04-24 20:29:58 +00001573}
1574
sewardje663cb92002-04-12 10:26:32 +00001575
1576extern
sewardj853f55d2002-04-26 00:27:53 +00001577int __libc_open(const char *pathname, int flags, mode_t mode);
sewardj5905fae2002-04-26 13:25:00 +00001578__attribute__((weak))
sewardj853f55d2002-04-26 00:27:53 +00001579int open(const char *pathname, int flags, mode_t mode)
sewardje663cb92002-04-12 10:26:32 +00001580{
sewardjd140e442002-05-29 01:21:19 +00001581 __my_pthread_testcancel();
sewardj853f55d2002-04-26 00:27:53 +00001582 return __libc_open(pathname, flags, mode);
sewardje663cb92002-04-12 10:26:32 +00001583}
1584
1585
1586extern
1587int __libc_close(int fd);
sewardj5905fae2002-04-26 13:25:00 +00001588__attribute__((weak))
sewardje663cb92002-04-12 10:26:32 +00001589int close(int fd)
1590{
sewardjd140e442002-05-29 01:21:19 +00001591 __my_pthread_testcancel();
sewardj45b4b372002-04-16 22:50:32 +00001592 return __libc_close(fd);
sewardje663cb92002-04-12 10:26:32 +00001593}
1594
1595
1596extern
1597int __libc_accept(int s, struct sockaddr *addr, socklen_t *addrlen);
sewardj5905fae2002-04-26 13:25:00 +00001598__attribute__((weak))
sewardje663cb92002-04-12 10:26:32 +00001599int accept(int s, struct sockaddr *addr, socklen_t *addrlen)
1600{
sewardjd140e442002-05-29 01:21:19 +00001601 __my_pthread_testcancel();
sewardj705d3cb2002-05-23 13:13:12 +00001602 wait_for_fd_to_be_readable_or_erring(s);
sewardjd140e442002-05-29 01:21:19 +00001603 __my_pthread_testcancel();
sewardj45b4b372002-04-16 22:50:32 +00001604 return __libc_accept(s, addr, addrlen);
sewardje663cb92002-04-12 10:26:32 +00001605}
1606
1607
1608extern
sewardje663cb92002-04-12 10:26:32 +00001609pid_t __libc_waitpid(pid_t pid, int *status, int options);
sewardj5905fae2002-04-26 13:25:00 +00001610__attribute__((weak))
sewardje663cb92002-04-12 10:26:32 +00001611pid_t waitpid(pid_t pid, int *status, int options)
1612{
sewardjd140e442002-05-29 01:21:19 +00001613 __my_pthread_testcancel();
sewardj45b4b372002-04-16 22:50:32 +00001614 return __libc_waitpid(pid, status, options);
sewardje663cb92002-04-12 10:26:32 +00001615}
1616
1617
1618extern
1619int __libc_nanosleep(const struct timespec *req, struct timespec *rem);
sewardj5905fae2002-04-26 13:25:00 +00001620__attribute__((weak))
sewardje663cb92002-04-12 10:26:32 +00001621int nanosleep(const struct timespec *req, struct timespec *rem)
1622{
sewardjd140e442002-05-29 01:21:19 +00001623 __my_pthread_testcancel();
sewardje663cb92002-04-12 10:26:32 +00001624 return __libc_nanosleep(req, rem);
1625}
1626
sewardjbe32e452002-04-24 20:29:58 +00001627
sewardje663cb92002-04-12 10:26:32 +00001628extern
1629int __libc_fsync(int fd);
sewardj5905fae2002-04-26 13:25:00 +00001630__attribute__((weak))
sewardje663cb92002-04-12 10:26:32 +00001631int fsync(int fd)
1632{
sewardjd140e442002-05-29 01:21:19 +00001633 __my_pthread_testcancel();
sewardj45b4b372002-04-16 22:50:32 +00001634 return __libc_fsync(fd);
sewardje663cb92002-04-12 10:26:32 +00001635}
1636
sewardjbe32e452002-04-24 20:29:58 +00001637
sewardj70c75362002-04-13 04:18:32 +00001638extern
1639off_t __libc_lseek(int fildes, off_t offset, int whence);
sewardj5905fae2002-04-26 13:25:00 +00001640__attribute__((weak))
sewardj70c75362002-04-13 04:18:32 +00001641off_t lseek(int fildes, off_t offset, int whence)
1642{
sewardjd140e442002-05-29 01:21:19 +00001643 __my_pthread_testcancel();
sewardj45b4b372002-04-16 22:50:32 +00001644 return __libc_lseek(fildes, offset, whence);
sewardj70c75362002-04-13 04:18:32 +00001645}
1646
sewardjbe32e452002-04-24 20:29:58 +00001647
1648extern
1649__off64_t __libc_lseek64(int fildes, __off64_t offset, int whence);
sewardj5905fae2002-04-26 13:25:00 +00001650__attribute__((weak))
sewardjbe32e452002-04-24 20:29:58 +00001651__off64_t lseek64(int fildes, __off64_t offset, int whence)
1652{
sewardjd140e442002-05-29 01:21:19 +00001653 __my_pthread_testcancel();
sewardjbe32e452002-04-24 20:29:58 +00001654 return __libc_lseek64(fildes, offset, whence);
1655}
1656
1657
sewardj726c4122002-05-16 23:39:10 +00001658extern
1659ssize_t __libc_pread64 (int __fd, void *__buf, size_t __nbytes,
1660 __off64_t __offset);
1661ssize_t __pread64 (int __fd, void *__buf, size_t __nbytes,
1662 __off64_t __offset)
1663{
sewardjd140e442002-05-29 01:21:19 +00001664 __my_pthread_testcancel();
sewardj726c4122002-05-16 23:39:10 +00001665 return __libc_pread64(__fd, __buf, __nbytes, __offset);
1666}
1667
1668
sewardja18e2102002-05-18 10:43:22 +00001669extern
1670ssize_t __libc_pwrite64 (int __fd, const void *__buf, size_t __nbytes,
1671 __off64_t __offset);
1672ssize_t __pwrite64 (int __fd, const void *__buf, size_t __nbytes,
1673 __off64_t __offset)
1674{
sewardjd140e442002-05-29 01:21:19 +00001675 __my_pthread_testcancel();
sewardja18e2102002-05-18 10:43:22 +00001676 return __libc_pwrite64(__fd, __buf, __nbytes, __offset);
1677}
1678
sewardj726c4122002-05-16 23:39:10 +00001679
sewardj39b93b12002-05-18 10:56:27 +00001680extern
1681ssize_t __libc_pwrite(int fd, const void *buf, size_t count, off_t offset);
1682__attribute__((weak))
1683ssize_t pwrite(int fd, const void *buf, size_t count, off_t offset)
1684{
sewardjd140e442002-05-29 01:21:19 +00001685 __my_pthread_testcancel();
sewardj39b93b12002-05-18 10:56:27 +00001686 return __libc_pwrite(fd, buf, count, offset);
1687}
1688
1689
1690extern
1691ssize_t __libc_pread(int fd, void *buf, size_t count, off_t offset);
1692__attribute__((weak))
1693ssize_t pread(int fd, void *buf, size_t count, off_t offset)
1694{
sewardjd140e442002-05-29 01:21:19 +00001695 __my_pthread_testcancel();
sewardj39b93b12002-05-18 10:56:27 +00001696 return __libc_pread(fd, buf, count, offset);
1697}
1698
1699
sewardj6af4b5d2002-04-16 04:40:49 +00001700extern
1701void __libc_longjmp(jmp_buf env, int val) __attribute((noreturn));
sewardj5905fae2002-04-26 13:25:00 +00001702/* not weak: __attribute__((weak)) */
sewardj6af4b5d2002-04-16 04:40:49 +00001703void longjmp(jmp_buf env, int val)
1704{
1705 __libc_longjmp(env, val);
1706}
1707
sewardjbe32e452002-04-24 20:29:58 +00001708
sewardj436c2db2002-06-18 09:07:54 +00001709extern void __libc_siglongjmp (sigjmp_buf env, int val)
1710 __attribute__ ((noreturn));
1711void siglongjmp(sigjmp_buf env, int val)
1712{
1713 kludged("siglongjmp (cleanup handlers are ignored)");
1714 __libc_siglongjmp(env, val);
1715}
1716
1717
sewardj6af4b5d2002-04-16 04:40:49 +00001718extern
1719int __libc_send(int s, const void *msg, size_t len, int flags);
sewardj5905fae2002-04-26 13:25:00 +00001720__attribute__((weak))
sewardj6af4b5d2002-04-16 04:40:49 +00001721int send(int s, const void *msg, size_t len, int flags)
1722{
sewardjd140e442002-05-29 01:21:19 +00001723 __my_pthread_testcancel();
sewardj6af4b5d2002-04-16 04:40:49 +00001724 return __libc_send(s, msg, len, flags);
1725}
1726
sewardjbe32e452002-04-24 20:29:58 +00001727
sewardj1e8cdc92002-04-18 11:37:52 +00001728extern
1729int __libc_recv(int s, void *buf, size_t len, int flags);
sewardj5905fae2002-04-26 13:25:00 +00001730__attribute__((weak))
sewardj1e8cdc92002-04-18 11:37:52 +00001731int recv(int s, void *buf, size_t len, int flags)
1732{
sewardjd140e442002-05-29 01:21:19 +00001733 __my_pthread_testcancel();
sewardj1d6b3a22002-06-20 07:58:33 +00001734 wait_for_fd_to_be_readable_or_erring(s);
1735 __my_pthread_testcancel();
sewardj1e8cdc92002-04-18 11:37:52 +00001736 return __libc_recv(s, buf, len, flags);
1737}
1738
sewardjbe32e452002-04-24 20:29:58 +00001739
sewardj3665ded2002-05-16 16:57:25 +00001740extern
1741int __libc_sendmsg(int s, const struct msghdr *msg, int flags);
1742__attribute__((weak))
1743int sendmsg(int s, const struct msghdr *msg, int flags)
1744{
sewardjd140e442002-05-29 01:21:19 +00001745 __my_pthread_testcancel();
sewardj3665ded2002-05-16 16:57:25 +00001746 return __libc_sendmsg(s, msg, flags);
1747}
1748
1749
sewardj796d6a22002-04-24 02:28:34 +00001750extern
sewardj59da27a2002-06-06 08:33:54 +00001751int __libc_recvmsg(int s, struct msghdr *msg, int flags);
1752__attribute__((weak))
1753int recvmsg(int s, struct msghdr *msg, int flags)
1754{
1755 __my_pthread_testcancel();
1756 return __libc_recvmsg(s, msg, flags);
1757}
1758
1759
1760extern
sewardj436e0582002-04-26 14:31:40 +00001761int __libc_recvfrom(int s, void *buf, size_t len, int flags,
1762 struct sockaddr *from, socklen_t *fromlen);
1763__attribute__((weak))
1764int recvfrom(int s, void *buf, size_t len, int flags,
1765 struct sockaddr *from, socklen_t *fromlen)
1766{
sewardjd140e442002-05-29 01:21:19 +00001767 __my_pthread_testcancel();
sewardj2e207632002-06-13 17:29:53 +00001768 wait_for_fd_to_be_readable_or_erring(s);
1769 __my_pthread_testcancel();
sewardj436e0582002-04-26 14:31:40 +00001770 return __libc_recvfrom(s, buf, len, flags, from, fromlen);
1771}
1772
1773
1774extern
sewardj796d6a22002-04-24 02:28:34 +00001775int __libc_sendto(int s, const void *msg, size_t len, int flags,
1776 const struct sockaddr *to, socklen_t tolen);
sewardj5905fae2002-04-26 13:25:00 +00001777__attribute__((weak))
sewardj796d6a22002-04-24 02:28:34 +00001778int sendto(int s, const void *msg, size_t len, int flags,
1779 const struct sockaddr *to, socklen_t tolen)
1780{
sewardjd140e442002-05-29 01:21:19 +00001781 __my_pthread_testcancel();
sewardj796d6a22002-04-24 02:28:34 +00001782 return __libc_sendto(s, msg, len, flags, to, tolen);
1783}
1784
sewardjbe32e452002-04-24 20:29:58 +00001785
sewardj369b1702002-04-24 13:28:15 +00001786extern
1787int __libc_system(const char* str);
sewardj5905fae2002-04-26 13:25:00 +00001788__attribute__((weak))
sewardj369b1702002-04-24 13:28:15 +00001789int system(const char* str)
1790{
sewardjd140e442002-05-29 01:21:19 +00001791 __my_pthread_testcancel();
sewardj369b1702002-04-24 13:28:15 +00001792 return __libc_system(str);
1793}
1794
sewardjbe32e452002-04-24 20:29:58 +00001795
sewardjab0b1c32002-04-24 19:26:47 +00001796extern
1797pid_t __libc_wait(int *status);
sewardj5905fae2002-04-26 13:25:00 +00001798__attribute__((weak))
sewardjab0b1c32002-04-24 19:26:47 +00001799pid_t wait(int *status)
1800{
sewardjd140e442002-05-29 01:21:19 +00001801 __my_pthread_testcancel();
sewardjab0b1c32002-04-24 19:26:47 +00001802 return __libc_wait(status);
1803}
1804
sewardj45b4b372002-04-16 22:50:32 +00001805
sewardj67f1d582002-05-24 02:11:32 +00001806extern
1807int __libc_msync(const void *start, size_t length, int flags);
1808__attribute__((weak))
1809int msync(const void *start, size_t length, int flags)
1810{
sewardjd140e442002-05-29 01:21:19 +00001811 __my_pthread_testcancel();
sewardj67f1d582002-05-24 02:11:32 +00001812 return __libc_msync(start, length, flags);
1813}
1814
sewardj5905fae2002-04-26 13:25:00 +00001815
sewardj2cb00342002-06-28 01:46:26 +00001816/*--- fork and its helper ---*/
1817
1818static
1819void run_fork_handlers ( int what )
1820{
1821 ForkHandlerEntry entry;
1822 int n_h, n_handlers, i, res;
1823
1824 my_assert(what == 0 || what == 1 || what == 2);
1825
1826 /* Fetch old counter */
1827 VALGRIND_MAGIC_SEQUENCE(n_handlers, -2 /* default */,
1828 VG_USERREQ__GET_FHSTACK_USED,
1829 0, 0, 0, 0);
1830 my_assert(n_handlers >= 0 && n_handlers < VG_N_FORKHANDLERSTACK);
1831
1832 /* Prepare handlers (what == 0) are called in opposite order of
1833 calls to pthread_atfork. Parent and child handlers are called
1834 in the same order as calls to pthread_atfork. */
1835 if (what == 0)
1836 n_h = n_handlers - 1;
1837 else
1838 n_h = 0;
1839
1840 for (i = 0; i < n_handlers; i++) {
1841 VALGRIND_MAGIC_SEQUENCE(res, -2 /* default */,
1842 VG_USERREQ__GET_FHSTACK_ENTRY,
1843 n_h, &entry, 0, 0);
1844 my_assert(res == 0);
1845 switch (what) {
1846 case 0: if (entry.prepare) entry.prepare();
1847 n_h--; break;
1848 case 1: if (entry.parent) entry.parent();
1849 n_h++; break;
1850 case 2: if (entry.child) entry.child();
1851 n_h++; break;
1852 default: barf("run_fork_handlers: invalid what");
1853 }
1854 }
1855
1856 if (what != 0 /* prepare */) {
1857 /* Empty out the stack. */
1858 VALGRIND_MAGIC_SEQUENCE(res, -2 /* default */,
1859 VG_USERREQ__SET_FHSTACK_USED,
1860 0, 0, 0, 0);
1861 my_assert(res == 0);
1862 }
1863}
1864
1865extern
1866pid_t __libc_fork(void);
1867pid_t __fork(void)
1868{
1869 pid_t pid;
1870 __my_pthread_testcancel();
1871 __pthread_mutex_lock(&pthread_atfork_lock);
1872
1873 run_fork_handlers(0 /* prepare */);
1874 pid = __libc_fork();
1875 if (pid == 0) {
1876 /* I am the child */
1877 run_fork_handlers(2 /* child */);
1878 __pthread_mutex_init(&pthread_atfork_lock, NULL);
1879 } else {
1880 /* I am the parent */
1881 run_fork_handlers(1 /* parent */);
1882 __pthread_mutex_unlock(&pthread_atfork_lock);
1883 }
1884 return pid;
1885}
1886
1887
njn25e49d8e72002-09-23 09:36:25 +00001888pid_t __vfork(void)
1889{
1890 return __fork();
1891}
sewardj2cb00342002-06-28 01:46:26 +00001892
1893
sewardj3b13f0e2002-04-25 20:17:29 +00001894/* ---------------------------------------------------------------------
1895 Nonblocking implementations of select() and poll(). This stuff will
1896 surely rot your mind.
1897 ------------------------------------------------------------------ */
sewardje663cb92002-04-12 10:26:32 +00001898
sewardj08a4c3f2002-04-13 03:45:44 +00001899/*--------------------------------------------------*/
1900
1901#include "vg_kerneliface.h"
1902
1903static
1904__inline__
1905int is_kerror ( int res )
1906{
1907 if (res >= -4095 && res <= -1)
1908 return 1;
1909 else
1910 return 0;
1911}
1912
1913
1914static
1915int my_do_syscall1 ( int syscallno, int arg1 )
1916{
1917 int __res;
1918 __asm__ volatile ("pushl %%ebx; movl %%edx,%%ebx ; int $0x80 ; popl %%ebx"
1919 : "=a" (__res)
1920 : "0" (syscallno),
1921 "d" (arg1) );
1922 return __res;
1923}
1924
1925static
1926int my_do_syscall2 ( int syscallno,
sewardjf854f472002-04-21 12:19:41 +00001927 int arg1, int arg2 )
sewardj08a4c3f2002-04-13 03:45:44 +00001928{
1929 int __res;
1930 __asm__ volatile ("pushl %%ebx; movl %%edx,%%ebx ; int $0x80 ; popl %%ebx"
1931 : "=a" (__res)
1932 : "0" (syscallno),
1933 "d" (arg1),
1934 "c" (arg2) );
1935 return __res;
1936}
1937
1938static
sewardjf854f472002-04-21 12:19:41 +00001939int my_do_syscall3 ( int syscallno,
1940 int arg1, int arg2, int arg3 )
1941{
1942 int __res;
1943 __asm__ volatile ("pushl %%ebx; movl %%esi,%%ebx ; int $0x80 ; popl %%ebx"
1944 : "=a" (__res)
1945 : "0" (syscallno),
1946 "S" (arg1),
1947 "c" (arg2),
1948 "d" (arg3) );
1949 return __res;
1950}
1951
1952static
sewardj08a4c3f2002-04-13 03:45:44 +00001953int do_syscall_select( int n,
1954 vki_fd_set* readfds,
1955 vki_fd_set* writefds,
1956 vki_fd_set* exceptfds,
1957 struct vki_timeval * timeout )
1958{
1959 int res;
1960 int args[5];
1961 args[0] = n;
1962 args[1] = (int)readfds;
1963 args[2] = (int)writefds;
1964 args[3] = (int)exceptfds;
1965 args[4] = (int)timeout;
1966 res = my_do_syscall1(__NR_select, (int)(&(args[0])) );
sewardj02535bc2002-04-21 01:08:26 +00001967 return res;
sewardj08a4c3f2002-04-13 03:45:44 +00001968}
1969
1970
1971/* This is a wrapper round select(), which makes it thread-safe,
1972 meaning that only this thread will block, rather than the entire
1973 process. This wrapper in turn depends on nanosleep() not to block
1974 the entire process, but I think (hope? suspect?) that POSIX
1975 pthreads guarantees that to be the case.
1976
1977 Basic idea is: modify the timeout parameter to select so that it
1978 returns immediately. Poll like this until select returns non-zero,
1979 indicating something interesting happened, or until our time is up.
njn25e49d8e72002-09-23 09:36:25 +00001980 Space out the polls with nanosleeps of say 11 milliseconds, which
sewardj08a4c3f2002-04-13 03:45:44 +00001981 is required to be nonblocking; this allows other threads to run.
sewardj02535bc2002-04-21 01:08:26 +00001982
1983 Assumes:
sewardj2d94c112002-06-03 01:25:54 +00001984 * (checked via my_assert) types fd_set and vki_fd_set are identical.
1985 * (checked via my_assert) types timeval and vki_timeval are identical.
sewardj02535bc2002-04-21 01:08:26 +00001986 * (unchecked) libc error numbers (EINTR etc) are the negation of the
1987 kernel's error numbers (VKI_EINTR etc).
sewardj08a4c3f2002-04-13 03:45:44 +00001988*/
sewardj08a4c3f2002-04-13 03:45:44 +00001989
sewardj5905fae2002-04-26 13:25:00 +00001990/* __attribute__((weak)) */
sewardj08a4c3f2002-04-13 03:45:44 +00001991int select ( int n,
1992 fd_set *rfds,
1993 fd_set *wfds,
1994 fd_set *xfds,
1995 struct timeval *timeout )
1996{
sewardj5f07b662002-04-23 16:52:51 +00001997 unsigned int ms_now, ms_end;
sewardj08a4c3f2002-04-13 03:45:44 +00001998 int res;
1999 fd_set rfds_copy;
2000 fd_set wfds_copy;
2001 fd_set xfds_copy;
2002 struct vki_timeval t_now;
sewardj08a4c3f2002-04-13 03:45:44 +00002003 struct vki_timeval zero_timeout;
2004 struct vki_timespec nanosleep_interval;
2005
sewardjd140e442002-05-29 01:21:19 +00002006 __my_pthread_testcancel();
2007
sewardj5f07b662002-04-23 16:52:51 +00002008 /* gcc's complains about ms_end being used uninitialised -- classic
2009 case it can't understand, where ms_end is both defined and used
2010 only if timeout != NULL. Hence ... */
2011 ms_end = 0;
sewardj08a4c3f2002-04-13 03:45:44 +00002012
2013 /* We assume that the kernel and libc data layouts are identical
2014 for the following types. These asserts provide a crude
2015 check. */
2016 if (sizeof(fd_set) != sizeof(vki_fd_set)
2017 || sizeof(struct timeval) != sizeof(struct vki_timeval))
2018 barf("valgrind's hacky non-blocking select(): data sizes error");
2019
sewardj5f07b662002-04-23 16:52:51 +00002020 /* Detect the current time and simultaneously find out if we are
2021 running on Valgrind. */
2022 VALGRIND_MAGIC_SEQUENCE(ms_now, 0xFFFFFFFF /* default */,
2023 VG_USERREQ__READ_MILLISECOND_TIMER,
2024 0, 0, 0, 0);
2025
2026 /* If a zero timeout specified, this call is harmless. Also go
2027 this route if we're not running on Valgrind, for whatever
2028 reason. */
2029 if ( (timeout && timeout->tv_sec == 0 && timeout->tv_usec == 0)
2030 || (ms_now == 0xFFFFFFFF) ) {
sewardj02535bc2002-04-21 01:08:26 +00002031 res = do_syscall_select( n, (vki_fd_set*)rfds,
sewardj08a4c3f2002-04-13 03:45:44 +00002032 (vki_fd_set*)wfds,
2033 (vki_fd_set*)xfds,
2034 (struct vki_timeval*)timeout);
sewardj02535bc2002-04-21 01:08:26 +00002035 if (is_kerror(res)) {
2036 * (__errno_location()) = -res;
2037 return -1;
2038 } else {
2039 return res;
2040 }
2041 }
sewardj08a4c3f2002-04-13 03:45:44 +00002042
sewardj5f07b662002-04-23 16:52:51 +00002043 /* If a timeout was specified, set ms_end to be the end millisecond
2044 counter [wallclock] time. */
sewardj08a4c3f2002-04-13 03:45:44 +00002045 if (timeout) {
2046 res = my_do_syscall2(__NR_gettimeofday, (int)&t_now, (int)NULL);
sewardj2d94c112002-06-03 01:25:54 +00002047 my_assert(res == 0);
sewardj5f07b662002-04-23 16:52:51 +00002048 ms_end = ms_now;
2049 ms_end += (timeout->tv_usec / 1000);
2050 ms_end += (timeout->tv_sec * 1000);
sewardj08a4c3f2002-04-13 03:45:44 +00002051 /* Stay sane ... */
sewardj2d94c112002-06-03 01:25:54 +00002052 my_assert (ms_end >= ms_now);
sewardj08a4c3f2002-04-13 03:45:44 +00002053 }
2054
2055 /* fprintf(stderr, "MY_SELECT: before loop\n"); */
2056
2057 /* Either timeout == NULL, meaning wait indefinitely, or timeout !=
sewardj5f07b662002-04-23 16:52:51 +00002058 NULL, in which case ms_end holds the end time. */
sewardj05bb2c92002-06-26 00:47:17 +00002059
sewardj08a4c3f2002-04-13 03:45:44 +00002060 while (1) {
sewardj05bb2c92002-06-26 00:47:17 +00002061
2062 /* First, do a return-immediately select(). */
sewardj08a4c3f2002-04-13 03:45:44 +00002063
2064 /* These could be trashed each time round the loop, so restore
2065 them each time. */
2066 if (rfds) rfds_copy = *rfds;
2067 if (wfds) wfds_copy = *wfds;
2068 if (xfds) xfds_copy = *xfds;
2069
2070 zero_timeout.tv_sec = zero_timeout.tv_usec = 0;
2071
2072 res = do_syscall_select( n,
2073 rfds ? (vki_fd_set*)(&rfds_copy) : NULL,
2074 wfds ? (vki_fd_set*)(&wfds_copy) : NULL,
2075 xfds ? (vki_fd_set*)(&xfds_copy) : NULL,
2076 & zero_timeout );
sewardj02535bc2002-04-21 01:08:26 +00002077 if (is_kerror(res)) {
2078 /* Some kind of error (including EINTR). Set errno and
sewardj08a4c3f2002-04-13 03:45:44 +00002079 return. The sets are unspecified in this case. */
sewardj02535bc2002-04-21 01:08:26 +00002080 * (__errno_location()) = -res;
2081 return -1;
sewardj08a4c3f2002-04-13 03:45:44 +00002082 }
2083 if (res > 0) {
2084 /* one or more fds is ready. Copy out resulting sets and
2085 return. */
2086 if (rfds) *rfds = rfds_copy;
2087 if (wfds) *wfds = wfds_copy;
2088 if (xfds) *xfds = xfds_copy;
2089 return res;
2090 }
sewardj05bb2c92002-06-26 00:47:17 +00002091
2092 /* Nothing interesting happened, so we go to sleep for a
2093 while. */
2094
sewardj08a4c3f2002-04-13 03:45:44 +00002095 /* fprintf(stderr, "MY_SELECT: nanosleep\n"); */
2096 /* nanosleep and go round again */
sewardj02535bc2002-04-21 01:08:26 +00002097 nanosleep_interval.tv_sec = 0;
njn25e49d8e72002-09-23 09:36:25 +00002098 nanosleep_interval.tv_nsec = 11 * 1000 * 1000; /* 11 milliseconds */
sewardjf854f472002-04-21 12:19:41 +00002099 /* It's critical here that valgrind's nanosleep implementation
2100 is nonblocking. */
sewardj645030e2002-06-06 01:27:39 +00002101 res = my_do_syscall2(__NR_nanosleep,
sewardjf854f472002-04-21 12:19:41 +00002102 (int)(&nanosleep_interval), (int)NULL);
sewardj645030e2002-06-06 01:27:39 +00002103 if (res == -VKI_EINTR) {
2104 /* The nanosleep was interrupted by a signal. So we do the
2105 same. */
2106 * (__errno_location()) = EINTR;
2107 return -1;
2108 }
sewardj05bb2c92002-06-26 00:47:17 +00002109
2110 /* Sleeping finished. If a finite timeout, check to see if it
2111 has expired yet. */
2112 if (timeout) {
2113 VALGRIND_MAGIC_SEQUENCE(ms_now, 0xFFFFFFFF /* default */,
2114 VG_USERREQ__READ_MILLISECOND_TIMER,
2115 0, 0, 0, 0);
2116 my_assert(ms_now != 0xFFFFFFFF);
2117 if (ms_now >= ms_end) {
2118 /* timeout; nothing interesting happened. */
2119 if (rfds) FD_ZERO(rfds);
2120 if (wfds) FD_ZERO(wfds);
2121 if (xfds) FD_ZERO(xfds);
2122 return 0;
2123 }
2124 }
2125
sewardjf854f472002-04-21 12:19:41 +00002126 }
2127}
2128
2129
2130
2131
2132#include <sys/poll.h>
2133
sewardj3e909ce2002-06-03 13:27:15 +00002134#ifndef HAVE_NFDS_T
sewardj72d58482002-04-24 02:20:20 +00002135typedef unsigned long int nfds_t;
2136#endif
2137
sewardj705d3cb2002-05-23 13:13:12 +00002138
sewardj5905fae2002-04-26 13:25:00 +00002139/* __attribute__((weak)) */
sewardjf854f472002-04-21 12:19:41 +00002140int poll (struct pollfd *__fds, nfds_t __nfds, int __timeout)
2141{
sewardj5f07b662002-04-23 16:52:51 +00002142 unsigned int ms_now, ms_end;
sewardjf854f472002-04-21 12:19:41 +00002143 int res, i;
sewardjf854f472002-04-21 12:19:41 +00002144 struct vki_timespec nanosleep_interval;
2145
sewardjd140e442002-05-29 01:21:19 +00002146 __my_pthread_testcancel();
sewardjf854f472002-04-21 12:19:41 +00002147 ensure_valgrind("poll");
2148
sewardj5f07b662002-04-23 16:52:51 +00002149 /* Detect the current time and simultaneously find out if we are
2150 running on Valgrind. */
2151 VALGRIND_MAGIC_SEQUENCE(ms_now, 0xFFFFFFFF /* default */,
2152 VG_USERREQ__READ_MILLISECOND_TIMER,
2153 0, 0, 0, 0);
2154
sewardjf854f472002-04-21 12:19:41 +00002155 if (/* CHECK SIZES FOR struct pollfd */
2156 sizeof(struct timeval) != sizeof(struct vki_timeval))
2157 barf("valgrind's hacky non-blocking poll(): data sizes error");
2158
sewardj5f07b662002-04-23 16:52:51 +00002159 /* dummy initialisation to keep gcc -Wall happy */
2160 ms_end = 0;
2161
2162 /* If a zero timeout specified, this call is harmless. Also do
2163 this if not running on Valgrind. */
2164 if (__timeout == 0 || ms_now == 0xFFFFFFFF) {
sewardjf854f472002-04-21 12:19:41 +00002165 res = my_do_syscall3(__NR_poll, (int)__fds, __nfds, __timeout);
2166 if (is_kerror(res)) {
2167 * (__errno_location()) = -res;
2168 return -1;
2169 } else {
2170 return res;
2171 }
2172 }
2173
sewardj5f07b662002-04-23 16:52:51 +00002174 /* If a timeout was specified, set ms_end to be the end wallclock
2175 time. Easy considering that __timeout is in milliseconds. */
sewardjf854f472002-04-21 12:19:41 +00002176 if (__timeout > 0) {
sewardj650ac002002-04-29 12:20:34 +00002177 ms_end = ms_now + (unsigned int)__timeout;
sewardjf854f472002-04-21 12:19:41 +00002178 }
2179
2180 /* fprintf(stderr, "MY_POLL: before loop\n"); */
2181
2182 /* Either timeout < 0, meaning wait indefinitely, or timeout > 0,
2183 in which case t_end holds the end time. */
sewardj05bb2c92002-06-26 00:47:17 +00002184
sewardj2d94c112002-06-03 01:25:54 +00002185 my_assert(__timeout != 0);
sewardj5f07b662002-04-23 16:52:51 +00002186
sewardjf854f472002-04-21 12:19:41 +00002187 while (1) {
sewardj05bb2c92002-06-26 00:47:17 +00002188
2189 /* Do a return-immediately poll. */
2190
2191 res = my_do_syscall3(__NR_poll, (int)__fds, __nfds, 0 );
2192 if (is_kerror(res)) {
2193 /* Some kind of error. Set errno and return. */
2194 * (__errno_location()) = -res;
2195 return -1;
2196 }
2197 if (res > 0) {
2198 /* One or more fds is ready. Return now. */
2199 return res;
2200 }
2201
2202 /* Nothing interesting happened, so we go to sleep for a
2203 while. */
2204
2205 /* fprintf(stderr, "MY_POLL: nanosleep\n"); */
2206 /* nanosleep and go round again */
2207 nanosleep_interval.tv_sec = 0;
njn25e49d8e72002-09-23 09:36:25 +00002208 nanosleep_interval.tv_nsec = 13 * 1000 * 1000; /* 13 milliseconds */
sewardj05bb2c92002-06-26 00:47:17 +00002209 /* It's critical here that valgrind's nanosleep implementation
2210 is nonblocking. */
2211 (void)my_do_syscall2(__NR_nanosleep,
2212 (int)(&nanosleep_interval), (int)NULL);
2213
2214 /* Sleeping finished. If a finite timeout, check to see if it
2215 has expired yet. */
sewardjf854f472002-04-21 12:19:41 +00002216 if (__timeout > 0) {
sewardj5f07b662002-04-23 16:52:51 +00002217 VALGRIND_MAGIC_SEQUENCE(ms_now, 0xFFFFFFFF /* default */,
2218 VG_USERREQ__READ_MILLISECOND_TIMER,
2219 0, 0, 0, 0);
sewardj2d94c112002-06-03 01:25:54 +00002220 my_assert(ms_now != 0xFFFFFFFF);
sewardj5f07b662002-04-23 16:52:51 +00002221 if (ms_now >= ms_end) {
sewardjf854f472002-04-21 12:19:41 +00002222 /* timeout; nothing interesting happened. */
2223 for (i = 0; i < __nfds; i++)
2224 __fds[i].revents = 0;
2225 return 0;
2226 }
2227 }
2228
sewardj08a4c3f2002-04-13 03:45:44 +00002229 }
2230}
sewardj3b13f0e2002-04-25 20:17:29 +00002231
2232
sewardj705d3cb2002-05-23 13:13:12 +00002233/* Helper function used to make accept() non-blocking. Idea is to use
2234 the above nonblocking poll() to make this thread ONLY wait for the
2235 specified fd to become ready, and then return. */
sewardjd1c1cf22002-06-26 00:13:36 +00002236
2237/* Sigh -- a hack. We're not supposed to include this file directly;
2238 should do it via /usr/include/fcntl.h, but that introduces a
2239 varargs prototype for fcntl itself, which we can't mimic. */
2240#define _FCNTL_H
2241#include <bits/fcntl.h>
2242
sewardj705d3cb2002-05-23 13:13:12 +00002243static void wait_for_fd_to_be_readable_or_erring ( int fd )
2244{
2245 struct pollfd pfd;
sewardjd1c1cf22002-06-26 00:13:36 +00002246 int res;
2247
sewardj6e6cbaa2002-05-24 02:12:52 +00002248 /* fprintf(stderr, "wait_for_fd_to_be_readable_or_erring %d\n", fd); */
sewardjd1c1cf22002-06-26 00:13:36 +00002249
2250 /* First check to see if the fd is nonblocking, and/or invalid. In
2251 either case return immediately. */
2252 res = __libc_fcntl(fd, F_GETFL, 0);
2253 if (res == -1) return; /* fd is invalid somehow */
2254 if (res & O_NONBLOCK) return; /* fd is nonblocking */
2255
2256 /* Ok, we'd better wait with poll. */
sewardj705d3cb2002-05-23 13:13:12 +00002257 pfd.fd = fd;
2258 pfd.events = POLLIN | POLLPRI | POLLERR | POLLHUP | POLLNVAL;
2259 /* ... but not POLLOUT, you may notice. */
2260 pfd.revents = 0;
2261 (void)poll(&pfd, 1, -1 /* forever */);
2262}
2263
2264
sewardj3b13f0e2002-04-25 20:17:29 +00002265/* ---------------------------------------------------------------------
sewardj8f253ff2002-05-19 00:13:34 +00002266 Hacky implementation of semaphores.
2267 ------------------------------------------------------------------ */
2268
2269#include <semaphore.h>
2270
2271/* This is a terrible way to do the remapping. Plan is to import an
2272 AVL tree at some point. */
sewardj8f253ff2002-05-19 00:13:34 +00002273
2274typedef
2275 struct {
2276 pthread_mutex_t se_mx;
2277 pthread_cond_t se_cv;
2278 int count;
2279 }
2280 vg_sem_t;
2281
2282static pthread_mutex_t se_remap_mx = PTHREAD_MUTEX_INITIALIZER;
2283
2284static int se_remap_used = 0;
2285static sem_t* se_remap_orig[VG_N_SEMAPHORES];
2286static vg_sem_t se_remap_new[VG_N_SEMAPHORES];
2287
2288static vg_sem_t* se_remap ( sem_t* orig )
2289{
2290 int res, i;
2291 res = __pthread_mutex_lock(&se_remap_mx);
sewardj2d94c112002-06-03 01:25:54 +00002292 my_assert(res == 0);
sewardj8f253ff2002-05-19 00:13:34 +00002293
2294 for (i = 0; i < se_remap_used; i++) {
2295 if (se_remap_orig[i] == orig)
2296 break;
2297 }
2298 if (i == se_remap_used) {
2299 if (se_remap_used == VG_N_SEMAPHORES) {
2300 res = pthread_mutex_unlock(&se_remap_mx);
sewardj2d94c112002-06-03 01:25:54 +00002301 my_assert(res == 0);
sewardja1ac5cb2002-05-27 13:00:05 +00002302 barf("VG_N_SEMAPHORES is too low. Increase and recompile.");
sewardj8f253ff2002-05-19 00:13:34 +00002303 }
2304 se_remap_used++;
2305 se_remap_orig[i] = orig;
2306 /* printf("allocated semaphore %d\n", i); */
2307 }
2308 res = __pthread_mutex_unlock(&se_remap_mx);
sewardj2d94c112002-06-03 01:25:54 +00002309 my_assert(res == 0);
sewardj8f253ff2002-05-19 00:13:34 +00002310 return &se_remap_new[i];
2311}
2312
2313
2314int sem_init(sem_t *sem, int pshared, unsigned int value)
2315{
2316 int res;
2317 vg_sem_t* vg_sem;
2318 ensure_valgrind("sem_init");
2319 if (pshared != 0) {
sewardj4dced352002-06-04 22:54:20 +00002320 pthread_error("sem_init: unsupported pshared value");
sewardj8f253ff2002-05-19 00:13:34 +00002321 errno = ENOSYS;
2322 return -1;
2323 }
2324 vg_sem = se_remap(sem);
2325 res = pthread_mutex_init(&vg_sem->se_mx, NULL);
sewardj2d94c112002-06-03 01:25:54 +00002326 my_assert(res == 0);
sewardj8f253ff2002-05-19 00:13:34 +00002327 res = pthread_cond_init(&vg_sem->se_cv, NULL);
sewardj2d94c112002-06-03 01:25:54 +00002328 my_assert(res == 0);
sewardj8f253ff2002-05-19 00:13:34 +00002329 vg_sem->count = value;
2330 return 0;
2331}
2332
2333
2334int sem_wait ( sem_t* sem )
2335{
2336 int res;
2337 vg_sem_t* vg_sem;
2338 ensure_valgrind("sem_wait");
2339 vg_sem = se_remap(sem);
2340 res = __pthread_mutex_lock(&vg_sem->se_mx);
sewardj2d94c112002-06-03 01:25:54 +00002341 my_assert(res == 0);
sewardj8f253ff2002-05-19 00:13:34 +00002342 while (vg_sem->count == 0) {
2343 res = pthread_cond_wait(&vg_sem->se_cv, &vg_sem->se_mx);
sewardj2d94c112002-06-03 01:25:54 +00002344 my_assert(res == 0);
sewardj8f253ff2002-05-19 00:13:34 +00002345 }
2346 vg_sem->count--;
2347 res = __pthread_mutex_unlock(&vg_sem->se_mx);
sewardj2d94c112002-06-03 01:25:54 +00002348 my_assert(res == 0);
sewardj8f253ff2002-05-19 00:13:34 +00002349 return 0;
2350}
2351
2352int sem_post ( sem_t* sem )
2353{
2354 int res;
2355 vg_sem_t* vg_sem;
2356 ensure_valgrind("sem_post");
2357 vg_sem = se_remap(sem);
2358 res = __pthread_mutex_lock(&vg_sem->se_mx);
sewardj2d94c112002-06-03 01:25:54 +00002359 my_assert(res == 0);
sewardj8f253ff2002-05-19 00:13:34 +00002360 if (vg_sem->count == 0) {
2361 vg_sem->count++;
2362 res = pthread_cond_broadcast(&vg_sem->se_cv);
sewardj2d94c112002-06-03 01:25:54 +00002363 my_assert(res == 0);
sewardj8f253ff2002-05-19 00:13:34 +00002364 } else {
2365 vg_sem->count++;
2366 }
2367 res = __pthread_mutex_unlock(&vg_sem->se_mx);
sewardj2d94c112002-06-03 01:25:54 +00002368 my_assert(res == 0);
sewardj8f253ff2002-05-19 00:13:34 +00002369 return 0;
2370}
2371
2372
2373int sem_trywait ( sem_t* sem )
2374{
2375 int ret, res;
2376 vg_sem_t* vg_sem;
2377 ensure_valgrind("sem_trywait");
2378 vg_sem = se_remap(sem);
2379 res = __pthread_mutex_lock(&vg_sem->se_mx);
sewardj2d94c112002-06-03 01:25:54 +00002380 my_assert(res == 0);
sewardj8f253ff2002-05-19 00:13:34 +00002381 if (vg_sem->count > 0) {
2382 vg_sem->count--;
2383 ret = 0;
2384 } else {
2385 ret = -1;
2386 errno = EAGAIN;
2387 }
2388 res = __pthread_mutex_unlock(&vg_sem->se_mx);
sewardj2d94c112002-06-03 01:25:54 +00002389 my_assert(res == 0);
sewardj8f253ff2002-05-19 00:13:34 +00002390 return ret;
2391}
2392
2393
2394int sem_getvalue(sem_t* sem, int * sval)
2395{
2396 vg_sem_t* vg_sem;
2397 ensure_valgrind("sem_trywait");
2398 vg_sem = se_remap(sem);
2399 *sval = vg_sem->count;
2400 return 0;
2401}
2402
2403
2404int sem_destroy(sem_t * sem)
2405{
2406 kludged("sem_destroy");
2407 /* if someone waiting on this semaphore, errno = EBUSY, return -1 */
2408 return 0;
2409}
2410
2411
2412/* ---------------------------------------------------------------------
sewardj2d8b3f02002-06-01 14:14:19 +00002413 Reader-writer locks.
sewardja1ac5cb2002-05-27 13:00:05 +00002414 ------------------------------------------------------------------ */
2415
sewardj2d8b3f02002-06-01 14:14:19 +00002416typedef
2417 struct {
2418 int initted; /* != 0 --> in use; sanity check only */
2419 int prefer_w; /* != 0 --> prefer writer */
2420 int nwait_r; /* # of waiting readers */
2421 int nwait_w; /* # of waiting writers */
2422 pthread_cond_t cv_r; /* for signalling readers */
2423 pthread_cond_t cv_w; /* for signalling writers */
2424 pthread_mutex_t mx;
2425 int status;
2426 /* allowed range for status: >= -1. -1 means 1 writer currently
2427 active, >= 0 means N readers currently active. */
2428 }
2429 vg_rwlock_t;
sewardja1ac5cb2002-05-27 13:00:05 +00002430
2431
2432static pthread_mutex_t rw_remap_mx = PTHREAD_MUTEX_INITIALIZER;
2433
2434static int rw_remap_used = 0;
2435static pthread_rwlock_t* rw_remap_orig[VG_N_RWLOCKS];
2436static vg_rwlock_t rw_remap_new[VG_N_RWLOCKS];
2437
sewardj2d8b3f02002-06-01 14:14:19 +00002438
2439static
2440void init_vg_rwlock ( vg_rwlock_t* vg_rwl )
2441{
2442 int res = 0;
2443 vg_rwl->initted = 1;
2444 vg_rwl->prefer_w = 1;
2445 vg_rwl->nwait_r = 0;
2446 vg_rwl->nwait_w = 0;
2447 vg_rwl->status = 0;
2448 res = pthread_mutex_init(&vg_rwl->mx, NULL);
2449 res |= pthread_cond_init(&vg_rwl->cv_r, NULL);
2450 res |= pthread_cond_init(&vg_rwl->cv_w, NULL);
sewardj2d94c112002-06-03 01:25:54 +00002451 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002452}
2453
2454
sewardja1ac5cb2002-05-27 13:00:05 +00002455/* Take the address of a LinuxThreads rwlock_t and return the shadow
2456 address of our version. Further, if the LinuxThreads version
2457 appears to have been statically initialised, do the same to the one
2458 we allocate here. The pthread_rwlock_t.__rw_readers field is set
2459 to zero by PTHREAD_RWLOCK_INITIALIZER, so we take zero as meaning
2460 uninitialised and non-zero meaning initialised.
2461*/
2462static vg_rwlock_t* rw_remap ( pthread_rwlock_t* orig )
2463{
2464 int res, i;
2465 vg_rwlock_t* vg_rwl;
2466 res = __pthread_mutex_lock(&rw_remap_mx);
sewardj2d94c112002-06-03 01:25:54 +00002467 my_assert(res == 0);
sewardja1ac5cb2002-05-27 13:00:05 +00002468
2469 for (i = 0; i < rw_remap_used; i++) {
2470 if (rw_remap_orig[i] == orig)
2471 break;
2472 }
2473 if (i == rw_remap_used) {
2474 if (rw_remap_used == VG_N_RWLOCKS) {
sewardj2d8b3f02002-06-01 14:14:19 +00002475 res = __pthread_mutex_unlock(&rw_remap_mx);
sewardj2d94c112002-06-03 01:25:54 +00002476 my_assert(res == 0);
sewardja1ac5cb2002-05-27 13:00:05 +00002477 barf("VG_N_RWLOCKS is too low. Increase and recompile.");
2478 }
2479 rw_remap_used++;
2480 rw_remap_orig[i] = orig;
sewardj2d8b3f02002-06-01 14:14:19 +00002481 rw_remap_new[i].initted = 0;
sewardja1ac5cb2002-05-27 13:00:05 +00002482 if (0) printf("allocated rwlock %d\n", i);
2483 }
2484 res = __pthread_mutex_unlock(&rw_remap_mx);
sewardj2d94c112002-06-03 01:25:54 +00002485 my_assert(res == 0);
sewardja1ac5cb2002-05-27 13:00:05 +00002486 vg_rwl = &rw_remap_new[i];
2487
sewardj2d8b3f02002-06-01 14:14:19 +00002488 /* Initialise the shadow, if required. */
sewardja1ac5cb2002-05-27 13:00:05 +00002489 if (orig->__rw_readers == 0) {
sewardja1ac5cb2002-05-27 13:00:05 +00002490 orig->__rw_readers = 1;
sewardj2d8b3f02002-06-01 14:14:19 +00002491 init_vg_rwlock(vg_rwl);
sewardja1ac5cb2002-05-27 13:00:05 +00002492 if (orig->__rw_kind == PTHREAD_RWLOCK_PREFER_READER_NP)
sewardj2d8b3f02002-06-01 14:14:19 +00002493 vg_rwl->prefer_w = 0;
sewardja1ac5cb2002-05-27 13:00:05 +00002494 }
2495
2496 return vg_rwl;
2497}
2498
2499
sewardja1ac5cb2002-05-27 13:00:05 +00002500int pthread_rwlock_init ( pthread_rwlock_t* orig,
2501 const pthread_rwlockattr_t* attr )
2502{
sewardja1ac5cb2002-05-27 13:00:05 +00002503 vg_rwlock_t* rwl;
2504 if (0) printf ("pthread_rwlock_init\n");
2505 /* Force the remapper to initialise the shadow. */
2506 orig->__rw_readers = 0;
2507 /* Install the lock preference; the remapper needs to know it. */
2508 orig->__rw_kind = PTHREAD_RWLOCK_DEFAULT_NP;
2509 if (attr)
2510 orig->__rw_kind = attr->__lockkind;
2511 rwl = rw_remap ( orig );
sewardj2d8b3f02002-06-01 14:14:19 +00002512 return 0;
sewardja1ac5cb2002-05-27 13:00:05 +00002513}
2514
sewardj2d8b3f02002-06-01 14:14:19 +00002515
2516static
2517void pthread_rwlock_rdlock_CANCEL_HDLR ( void* rwl_v )
sewardja1ac5cb2002-05-27 13:00:05 +00002518{
sewardj2d8b3f02002-06-01 14:14:19 +00002519 vg_rwlock_t* rwl = (vg_rwlock_t*)rwl_v;
2520 rwl->nwait_r--;
2521 pthread_mutex_unlock (&rwl->mx);
sewardja1ac5cb2002-05-27 13:00:05 +00002522}
2523
sewardj2d8b3f02002-06-01 14:14:19 +00002524
sewardja1ac5cb2002-05-27 13:00:05 +00002525int pthread_rwlock_rdlock ( pthread_rwlock_t* orig )
2526{
2527 int res;
2528 vg_rwlock_t* rwl;
2529 if (0) printf ("pthread_rwlock_rdlock\n");
2530 rwl = rw_remap ( orig );
sewardj2d8b3f02002-06-01 14:14:19 +00002531 res = __pthread_mutex_lock(&rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00002532 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002533 if (!rwl->initted) {
2534 res = __pthread_mutex_unlock(&rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00002535 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002536 return EINVAL;
2537 }
2538 if (rwl->status < 0) {
sewardj2d94c112002-06-03 01:25:54 +00002539 my_assert(rwl->status == -1);
sewardj2d8b3f02002-06-01 14:14:19 +00002540 rwl->nwait_r++;
2541 pthread_cleanup_push( pthread_rwlock_rdlock_CANCEL_HDLR, rwl );
2542 while (1) {
2543 if (rwl->status == 0) break;
2544 res = pthread_cond_wait(&rwl->cv_r, &rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00002545 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002546 }
2547 pthread_cleanup_pop(0);
2548 rwl->nwait_r--;
2549 }
sewardj2d94c112002-06-03 01:25:54 +00002550 my_assert(rwl->status >= 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002551 rwl->status++;
2552 res = __pthread_mutex_unlock(&rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00002553 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002554 return 0;
sewardja1ac5cb2002-05-27 13:00:05 +00002555}
2556
sewardj2d8b3f02002-06-01 14:14:19 +00002557
sewardja1ac5cb2002-05-27 13:00:05 +00002558int pthread_rwlock_tryrdlock ( pthread_rwlock_t* orig )
2559{
2560 int res;
2561 vg_rwlock_t* rwl;
2562 if (0) printf ("pthread_rwlock_tryrdlock\n");
2563 rwl = rw_remap ( orig );
sewardj2d8b3f02002-06-01 14:14:19 +00002564 res = __pthread_mutex_lock(&rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00002565 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002566 if (!rwl->initted) {
2567 res = __pthread_mutex_unlock(&rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00002568 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002569 return EINVAL;
2570 }
2571 if (rwl->status == -1) {
2572 /* Writer active; we have to give up. */
2573 res = __pthread_mutex_unlock(&rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00002574 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002575 return EBUSY;
2576 }
2577 /* Success */
sewardj2d94c112002-06-03 01:25:54 +00002578 my_assert(rwl->status >= 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002579 rwl->status++;
2580 res = __pthread_mutex_unlock(&rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00002581 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002582 return 0;
sewardja1ac5cb2002-05-27 13:00:05 +00002583}
2584
sewardj2d8b3f02002-06-01 14:14:19 +00002585
2586static
2587void pthread_rwlock_wrlock_CANCEL_HDLR ( void* rwl_v )
2588{
2589 vg_rwlock_t* rwl = (vg_rwlock_t*)rwl_v;
2590 rwl->nwait_w--;
2591 pthread_mutex_unlock (&rwl->mx);
2592}
2593
2594
sewardja1ac5cb2002-05-27 13:00:05 +00002595int pthread_rwlock_wrlock ( pthread_rwlock_t* orig )
2596{
2597 int res;
2598 vg_rwlock_t* rwl;
2599 if (0) printf ("pthread_rwlock_wrlock\n");
2600 rwl = rw_remap ( orig );
sewardj2d8b3f02002-06-01 14:14:19 +00002601 res = __pthread_mutex_lock(&rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00002602 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002603 if (!rwl->initted) {
2604 res = __pthread_mutex_unlock(&rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00002605 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002606 return EINVAL;
2607 }
2608 if (rwl->status != 0) {
2609 rwl->nwait_w++;
2610 pthread_cleanup_push( pthread_rwlock_wrlock_CANCEL_HDLR, rwl );
2611 while (1) {
2612 if (rwl->status == 0) break;
2613 res = pthread_cond_wait(&rwl->cv_w, &rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00002614 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002615 }
2616 pthread_cleanup_pop(0);
2617 rwl->nwait_w--;
2618 }
sewardj2d94c112002-06-03 01:25:54 +00002619 my_assert(rwl->status == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002620 rwl->status = -1;
2621 res = __pthread_mutex_unlock(&rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00002622 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002623 return 0;
sewardja1ac5cb2002-05-27 13:00:05 +00002624}
2625
sewardj2d8b3f02002-06-01 14:14:19 +00002626
sewardja1ac5cb2002-05-27 13:00:05 +00002627int pthread_rwlock_trywrlock ( pthread_rwlock_t* orig )
2628{
2629 int res;
2630 vg_rwlock_t* rwl;
sewardj2d8b3f02002-06-01 14:14:19 +00002631 if (0) printf ("pthread_wrlock_trywrlock\n");
sewardja1ac5cb2002-05-27 13:00:05 +00002632 rwl = rw_remap ( orig );
sewardj2d8b3f02002-06-01 14:14:19 +00002633 res = __pthread_mutex_lock(&rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00002634 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002635 if (!rwl->initted) {
2636 res = __pthread_mutex_unlock(&rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00002637 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002638 return EINVAL;
2639 }
2640 if (rwl->status != 0) {
2641 /* Reader(s) or a writer active; we have to give up. */
2642 res = __pthread_mutex_unlock(&rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00002643 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002644 return EBUSY;
2645 }
2646 /* Success */
sewardj2d94c112002-06-03 01:25:54 +00002647 my_assert(rwl->status == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002648 rwl->status = -1;
2649 res = __pthread_mutex_unlock(&rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00002650 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002651 return 0;
sewardja1ac5cb2002-05-27 13:00:05 +00002652}
2653
sewardj2d8b3f02002-06-01 14:14:19 +00002654
sewardja1ac5cb2002-05-27 13:00:05 +00002655int pthread_rwlock_unlock ( pthread_rwlock_t* orig )
2656{
2657 int res;
2658 vg_rwlock_t* rwl;
2659 if (0) printf ("pthread_rwlock_unlock\n");
2660 rwl = rw_remap ( orig );
sewardj2d8b3f02002-06-01 14:14:19 +00002661 rwl = rw_remap ( orig );
2662 res = __pthread_mutex_lock(&rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00002663 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002664 if (!rwl->initted) {
2665 res = __pthread_mutex_unlock(&rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00002666 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002667 return EINVAL;
2668 }
2669 if (rwl->status == 0) {
2670 res = __pthread_mutex_unlock(&rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00002671 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002672 return EPERM;
2673 }
sewardj2d94c112002-06-03 01:25:54 +00002674 my_assert(rwl->status != 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002675 if (rwl->status == -1) {
2676 rwl->status = 0;
2677 } else {
sewardj2d94c112002-06-03 01:25:54 +00002678 my_assert(rwl->status > 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002679 rwl->status--;
2680 }
2681
sewardj2d94c112002-06-03 01:25:54 +00002682 my_assert(rwl->status >= 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002683
2684 if (rwl->prefer_w) {
2685
2686 /* Favour waiting writers, if any. */
2687 if (rwl->nwait_w > 0) {
2688 /* Writer(s) are waiting. */
2689 if (rwl->status == 0) {
2690 /* We can let a writer in. */
2691 res = pthread_cond_signal(&rwl->cv_w);
sewardj2d94c112002-06-03 01:25:54 +00002692 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002693 } else {
2694 /* There are still readers active. Do nothing; eventually
2695 they will disappear, at which point a writer will be
2696 admitted. */
2697 }
2698 }
2699 else
2700 /* No waiting writers. */
2701 if (rwl->nwait_r > 0) {
2702 /* Let in a waiting reader. */
2703 res = pthread_cond_signal(&rwl->cv_r);
sewardj2d94c112002-06-03 01:25:54 +00002704 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002705 }
2706
2707 } else {
2708
2709 /* Favour waiting readers, if any. */
2710 if (rwl->nwait_r > 0) {
2711 /* Reader(s) are waiting; let one in. */
2712 res = pthread_cond_signal(&rwl->cv_r);
sewardj2d94c112002-06-03 01:25:54 +00002713 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002714 }
2715 else
2716 /* No waiting readers. */
2717 if (rwl->nwait_w > 0 && rwl->status == 0) {
2718 /* We have waiting writers and no active readers; let a
2719 writer in. */
2720 res = pthread_cond_signal(&rwl->cv_w);
sewardj2d94c112002-06-03 01:25:54 +00002721 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002722 }
2723 }
2724
2725 res = __pthread_mutex_unlock(&rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00002726 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002727 return 0;
2728}
2729
2730
2731int pthread_rwlock_destroy ( pthread_rwlock_t *orig )
2732{
2733 int res;
2734 vg_rwlock_t* rwl;
2735 if (0) printf ("pthread_rwlock_destroy\n");
2736 rwl = rw_remap ( orig );
2737 res = __pthread_mutex_lock(&rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00002738 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002739 if (!rwl->initted) {
2740 res = __pthread_mutex_unlock(&rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00002741 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002742 return EINVAL;
2743 }
2744 if (rwl->status != 0 || rwl->nwait_r > 0 || rwl->nwait_w > 0) {
2745 res = __pthread_mutex_unlock(&rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00002746 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002747 return EBUSY;
2748 }
2749 rwl->initted = 0;
2750 res = __pthread_mutex_unlock(&rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00002751 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002752 return 0;
sewardja1ac5cb2002-05-27 13:00:05 +00002753}
2754
2755
sewardj47e4e312002-06-18 09:24:34 +00002756/* Copied directly from LinuxThreads. */
2757int
2758pthread_rwlockattr_init (pthread_rwlockattr_t *attr)
2759{
2760 attr->__lockkind = 0;
2761 attr->__pshared = PTHREAD_PROCESS_PRIVATE;
2762
2763 return 0;
2764}
2765
sewardjfe18eb82002-07-13 12:58:44 +00002766/* Copied directly from LinuxThreads. */
2767int
2768pthread_rwlockattr_setpshared (pthread_rwlockattr_t *attr, int pshared)
2769{
2770 if (pshared != PTHREAD_PROCESS_PRIVATE && pshared != PTHREAD_PROCESS_SHARED)
2771 return EINVAL;
2772
2773 /* For now it is not possible to shared a conditional variable. */
2774 if (pshared != PTHREAD_PROCESS_PRIVATE)
2775 return ENOSYS;
2776
2777 attr->__pshared = pshared;
2778
2779 return 0;
2780}
2781
sewardj47e4e312002-06-18 09:24:34 +00002782
sewardja1ac5cb2002-05-27 13:00:05 +00002783/* ---------------------------------------------------------------------
sewardj3b13f0e2002-04-25 20:17:29 +00002784 B'stard.
2785 ------------------------------------------------------------------ */
2786
2787# define strong_alias(name, aliasname) \
2788 extern __typeof (name) aliasname __attribute__ ((alias (#name)));
2789
sewardj5905fae2002-04-26 13:25:00 +00002790# define weak_alias(name, aliasname) \
2791 extern __typeof (name) aliasname __attribute__ ((weak, alias (#name)));
sewardj3b13f0e2002-04-25 20:17:29 +00002792
sewardj5905fae2002-04-26 13:25:00 +00002793strong_alias(__pthread_mutex_lock, pthread_mutex_lock)
2794strong_alias(__pthread_mutex_trylock, pthread_mutex_trylock)
2795strong_alias(__pthread_mutex_unlock, pthread_mutex_unlock)
2796strong_alias(__pthread_mutexattr_init, pthread_mutexattr_init)
2797 weak_alias(__pthread_mutexattr_settype, pthread_mutexattr_settype)
2798strong_alias(__pthread_mutex_init, pthread_mutex_init)
2799strong_alias(__pthread_mutexattr_destroy, pthread_mutexattr_destroy)
2800strong_alias(__pthread_mutex_destroy, pthread_mutex_destroy)
2801strong_alias(__pthread_once, pthread_once)
2802strong_alias(__pthread_atfork, pthread_atfork)
2803strong_alias(__pthread_key_create, pthread_key_create)
2804strong_alias(__pthread_getspecific, pthread_getspecific)
2805strong_alias(__pthread_setspecific, pthread_setspecific)
2806
sewardjd529a442002-05-04 19:49:21 +00002807#ifndef GLIBC_2_1
sewardj3b13f0e2002-04-25 20:17:29 +00002808strong_alias(sigaction, __sigaction)
sewardjd529a442002-05-04 19:49:21 +00002809#endif
2810
sewardj5905fae2002-04-26 13:25:00 +00002811strong_alias(close, __close)
sewardj3b13f0e2002-04-25 20:17:29 +00002812strong_alias(fcntl, __fcntl)
sewardj5905fae2002-04-26 13:25:00 +00002813strong_alias(lseek, __lseek)
2814strong_alias(open, __open)
2815strong_alias(open64, __open64)
sewardj5905fae2002-04-26 13:25:00 +00002816strong_alias(read, __read)
2817strong_alias(wait, __wait)
2818strong_alias(write, __write)
sewardj3b13f0e2002-04-25 20:17:29 +00002819strong_alias(connect, __connect)
sewardj5905fae2002-04-26 13:25:00 +00002820strong_alias(send, __send)
2821
sewardj726c4122002-05-16 23:39:10 +00002822weak_alias (__pread64, pread64)
sewardja18e2102002-05-18 10:43:22 +00002823weak_alias (__pwrite64, pwrite64)
sewardj5905fae2002-04-26 13:25:00 +00002824weak_alias(__fork, fork)
njn25e49d8e72002-09-23 09:36:25 +00002825weak_alias(__vfork, vfork)
sewardj7f6456d2002-05-21 00:51:21 +00002826
sewardjf0b06452002-06-04 08:38:04 +00002827weak_alias (__pthread_kill_other_threads_np, pthread_kill_other_threads_np)
sewardj3b13f0e2002-04-25 20:17:29 +00002828
2829/*--------------------------------------------------*/
2830
sewardj5905fae2002-04-26 13:25:00 +00002831weak_alias(pthread_rwlock_rdlock, __pthread_rwlock_rdlock)
sewardj5905fae2002-04-26 13:25:00 +00002832weak_alias(pthread_rwlock_unlock, __pthread_rwlock_unlock)
sewardj262b0292002-05-01 00:03:16 +00002833weak_alias(pthread_rwlock_wrlock, __pthread_rwlock_wrlock)
sewardj060b04f2002-04-26 21:01:13 +00002834
sewardja1ac5cb2002-05-27 13:00:05 +00002835weak_alias(pthread_rwlock_destroy, __pthread_rwlock_destroy)
2836weak_alias(pthread_rwlock_init, __pthread_rwlock_init)
2837weak_alias(pthread_rwlock_tryrdlock, __pthread_rwlock_tryrdlock)
2838weak_alias(pthread_rwlock_trywrlock, __pthread_rwlock_trywrlock)
2839
sewardj060b04f2002-04-26 21:01:13 +00002840
sewardj3b13f0e2002-04-25 20:17:29 +00002841/* I've no idea what these are, but they get called quite a lot.
2842 Anybody know? */
2843
2844#undef _IO_flockfile
2845void _IO_flockfile ( _IO_FILE * file )
2846{
sewardj853f55d2002-04-26 00:27:53 +00002847 pthread_mutex_lock(file->_lock);
sewardj3b13f0e2002-04-25 20:17:29 +00002848}
sewardj5905fae2002-04-26 13:25:00 +00002849weak_alias(_IO_flockfile, flockfile);
2850
sewardj3b13f0e2002-04-25 20:17:29 +00002851
2852#undef _IO_funlockfile
2853void _IO_funlockfile ( _IO_FILE * file )
2854{
sewardj853f55d2002-04-26 00:27:53 +00002855 pthread_mutex_unlock(file->_lock);
sewardj3b13f0e2002-04-25 20:17:29 +00002856}
sewardj5905fae2002-04-26 13:25:00 +00002857weak_alias(_IO_funlockfile, funlockfile);
2858
sewardj3b13f0e2002-04-25 20:17:29 +00002859
sewardjd4f2c712002-04-30 10:20:10 +00002860/* This doesn't seem to be needed to simulate libpthread.so's external
2861 interface, but many people complain about its absence. */
2862
2863strong_alias(__pthread_mutexattr_settype, __pthread_mutexattr_setkind_np)
2864weak_alias(__pthread_mutexattr_setkind_np, pthread_mutexattr_setkind_np)
sewardj439d45e2002-05-03 20:43:10 +00002865
2866
2867/*--------------------------------------------------------------------*/
2868/*--- end vg_libpthread.c ---*/
2869/*--------------------------------------------------------------------*/