blob: 692e5d89ab48f6ae5fbebc41017c6941601d3624 [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/*
njnc9539842002-10-02 13:26:35 +00008 This file is part of Valgrind, an extensible x86 protected-mode
9 emulator for monitoring program execution on x86-Unixes.
sewardj439d45e2002-05-03 20:43:10 +000010
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
sewardj6e1543f2002-10-01 00:25:04 +000082__attribute__((weak))
83ssize_t write(int fd, const void *buf, size_t count);
sewardj705d3cb2002-05-23 13:13:12 +000084
sewardje663cb92002-04-12 10:26:32 +000085/* ---------------------------------------------------------------------
86 Helpers. We have to be pretty self-sufficient.
87 ------------------------------------------------------------------ */
88
sewardj436e0582002-04-26 14:31:40 +000089/* Number of times any given error message is printed. */
90#define N_MOANS 3
91
sewardj45b4b372002-04-16 22:50:32 +000092/* Extract from Valgrind the value of VG_(clo_trace_pthread_level).
93 Returns 0 (none) if not running on Valgrind. */
94static
95int get_pt_trace_level ( void )
96{
97 int res;
98 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
99 VG_USERREQ__GET_PTHREAD_TRACE_LEVEL,
100 0, 0, 0, 0);
101 return res;
102}
103
104
sewardje663cb92002-04-12 10:26:32 +0000105static
sewardj2d94c112002-06-03 01:25:54 +0000106void my_exit ( int arg )
sewardje663cb92002-04-12 10:26:32 +0000107{
sewardj45b4b372002-04-16 22:50:32 +0000108 int __res;
sewardje663cb92002-04-12 10:26:32 +0000109 __asm__ volatile ("movl %%ecx, %%ebx ; int $0x80"
110 : "=a" (__res)
111 : "0" (__NR_exit),
112 "c" (arg) );
sewardj45b4b372002-04-16 22:50:32 +0000113 /* We don't bother to mention the fact that this asm trashes %ebx,
114 since it won't return. If you ever do let it return ... fix
115 this! */
sewardje663cb92002-04-12 10:26:32 +0000116}
117
118
sewardj68b2dd92002-05-10 21:03:56 +0000119/* We need this guy -- it's in valgrind.so. */
120extern void VG_(startup) ( void );
121
122
123/* Just start up Valgrind if it's not already going. VG_(startup)()
124 detects and ignores second and subsequent calls. */
sewardj604ec3c2002-04-18 22:38:41 +0000125static __inline__
sewardje663cb92002-04-12 10:26:32 +0000126void ensure_valgrind ( char* caller )
127{
sewardj68b2dd92002-05-10 21:03:56 +0000128 VG_(startup)();
sewardje663cb92002-04-12 10:26:32 +0000129}
130
sewardjbea1caa2002-05-10 23:20:58 +0000131/* While we're at it ... hook our own startup function into this
132 game. */
133__asm__ (
134 ".section .init\n"
135 "\tcall vgPlain_startup"
136);
137
sewardje663cb92002-04-12 10:26:32 +0000138
139static
sewardj3b5d8862002-04-20 13:53:23 +0000140__attribute__((noreturn))
sewardje663cb92002-04-12 10:26:32 +0000141void barf ( char* str )
142{
143 char buf[100];
144 buf[0] = 0;
sewardj439d45e2002-05-03 20:43:10 +0000145 strcat(buf, "\nvalgrind's libpthread.so: ");
sewardje663cb92002-04-12 10:26:32 +0000146 strcat(buf, str);
147 strcat(buf, "\n\n");
148 write(2, buf, strlen(buf));
sewardj2d94c112002-06-03 01:25:54 +0000149 my_exit(1);
sewardj3b5d8862002-04-20 13:53:23 +0000150 /* We have to persuade gcc into believing this doesn't return. */
151 while (1) { };
sewardje663cb92002-04-12 10:26:32 +0000152}
153
154
sewardj2a3d28c2002-04-14 13:27:00 +0000155static void ignored ( char* msg )
156{
sewardj436e0582002-04-26 14:31:40 +0000157 if (get_pt_trace_level() >= 0) {
sewardj439d45e2002-05-03 20:43:10 +0000158 char* ig = "valgrind's libpthread.so: IGNORED call to: ";
sewardj45b4b372002-04-16 22:50:32 +0000159 write(2, ig, strlen(ig));
160 write(2, msg, strlen(msg));
161 ig = "\n";
162 write(2, ig, strlen(ig));
163 }
sewardj2a3d28c2002-04-14 13:27:00 +0000164}
165
sewardj30671ff2002-04-21 00:13:57 +0000166static void kludged ( char* msg )
167{
sewardj436e0582002-04-26 14:31:40 +0000168 if (get_pt_trace_level() >= 0) {
sewardj439d45e2002-05-03 20:43:10 +0000169 char* ig = "valgrind's libpthread.so: KLUDGED call to: ";
170 write(2, ig, strlen(ig));
171 write(2, msg, strlen(msg));
172 ig = "\n";
173 write(2, ig, strlen(ig));
174 }
175}
176
177static void not_inside ( char* msg )
178{
sewardj68b2dd92002-05-10 21:03:56 +0000179 VG_(startup)();
sewardj30671ff2002-04-21 00:13:57 +0000180}
181
sewardjccef2e62002-05-29 19:26:32 +0000182__attribute__((noreturn))
sewardj3b13f0e2002-04-25 20:17:29 +0000183void vgPlain_unimp ( char* what )
184{
sewardj439d45e2002-05-03 20:43:10 +0000185 char* ig = "valgrind's libpthread.so: UNIMPLEMENTED FUNCTION: ";
sewardj3b13f0e2002-04-25 20:17:29 +0000186 write(2, ig, strlen(ig));
187 write(2, what, strlen(what));
188 ig = "\n";
189 write(2, ig, strlen(ig));
190 barf("Please report this bug to me at: jseward@acm.org");
191}
192
sewardje663cb92002-04-12 10:26:32 +0000193
sewardj457cc472002-06-03 23:13:47 +0000194static
sewardj2d94c112002-06-03 01:25:54 +0000195void my_assert_fail ( Char* expr, Char* file, Int line, Char* fn )
196{
197 static Bool entered = False;
198 if (entered)
199 my_exit(2);
200 entered = True;
201 fprintf(stderr, "\n%s: %s:%d (%s): Assertion `%s' failed.\n",
202 "valgrind", file, line, fn, expr );
203 fprintf(stderr, "Please report this bug to me at: %s\n\n",
204 VG_EMAIL_ADDR);
205 my_exit(1);
206}
207
208#define MY__STRING(__str) #__str
209
210#define my_assert(expr) \
211 ((void) ((expr) ? 0 : \
212 (my_assert_fail (MY__STRING(expr), \
213 __FILE__, __LINE__, \
214 __PRETTY_FUNCTION__), 0)))
215
216
sewardje663cb92002-04-12 10:26:32 +0000217/* ---------------------------------------------------------------------
218 Pass pthread_ calls to Valgrind's request mechanism.
219 ------------------------------------------------------------------ */
220
sewardjf8f819e2002-04-17 23:21:37 +0000221#include <errno.h>
sewardj5f07b662002-04-23 16:52:51 +0000222#include <sys/time.h> /* gettimeofday */
sewardjf8f819e2002-04-17 23:21:37 +0000223
sewardja1ac5cb2002-05-27 13:00:05 +0000224
sewardjf8f819e2002-04-17 23:21:37 +0000225/* ---------------------------------------------------
sewardj4dced352002-06-04 22:54:20 +0000226 Ummm ..
227 ------------------------------------------------ */
228
229static
230void pthread_error ( const char* msg )
231{
232 int res;
233 VALGRIND_MAGIC_SEQUENCE(res, 0,
234 VG_USERREQ__PTHREAD_ERROR,
235 msg, 0, 0, 0);
236}
237
238
239/* ---------------------------------------------------
sewardjf8f819e2002-04-17 23:21:37 +0000240 THREAD ATTRIBUTES
241 ------------------------------------------------ */
242
sewardj6af4b5d2002-04-16 04:40:49 +0000243int pthread_attr_init(pthread_attr_t *attr)
244{
sewardj7989d0c2002-05-28 11:00:01 +0000245 /* Just initialise the fields which we might look at. */
246 attr->__detachstate = PTHREAD_CREATE_JOINABLE;
sewardj6af4b5d2002-04-16 04:40:49 +0000247 return 0;
248}
249
250int pthread_attr_setdetachstate(pthread_attr_t *attr, int detachstate)
251{
sewardj7989d0c2002-05-28 11:00:01 +0000252 if (detachstate != PTHREAD_CREATE_JOINABLE
sewardj4dced352002-06-04 22:54:20 +0000253 && detachstate != PTHREAD_CREATE_DETACHED) {
254 pthread_error("pthread_attr_setdetachstate: "
255 "detachstate is invalid");
sewardj7989d0c2002-05-28 11:00:01 +0000256 return EINVAL;
sewardj4dced352002-06-04 22:54:20 +0000257 }
sewardj7989d0c2002-05-28 11:00:01 +0000258 attr->__detachstate = detachstate;
sewardj6af4b5d2002-04-16 04:40:49 +0000259 return 0;
260}
261
njn25e49d8e72002-09-23 09:36:25 +0000262int pthread_attr_getdetachstate(const pthread_attr_t *attr, int *detachstate)
263{
264 *detachstate = attr->__detachstate;
265 return 0;
266}
267
sewardj30671ff2002-04-21 00:13:57 +0000268int pthread_attr_setinheritsched(pthread_attr_t *attr, int inherit)
269{
sewardj436e0582002-04-26 14:31:40 +0000270 static int moans = N_MOANS;
271 if (moans-- > 0)
272 ignored("pthread_attr_setinheritsched");
sewardj30671ff2002-04-21 00:13:57 +0000273 return 0;
274}
sewardj6af4b5d2002-04-16 04:40:49 +0000275
sewardj0286dd52002-05-16 20:51:15 +0000276__attribute__((weak))
277int pthread_attr_setstacksize (pthread_attr_t *__attr,
278 size_t __stacksize)
279{
sewardja18e2102002-05-18 10:43:22 +0000280 size_t limit;
sewardj3d7c8d62002-06-04 20:59:16 +0000281 char buf[1024];
sewardj0286dd52002-05-16 20:51:15 +0000282 ensure_valgrind("pthread_attr_setstacksize");
sewardja18e2102002-05-18 10:43:22 +0000283 limit = VG_PTHREAD_STACK_SIZE - VG_AR_CLIENT_STACKBASE_REDZONE_SZB
284 - 1000; /* paranoia */
285 if (__stacksize < limit)
sewardj0286dd52002-05-16 20:51:15 +0000286 return 0;
sewardj3d7c8d62002-06-04 20:59:16 +0000287 snprintf(buf, sizeof(buf), "pthread_attr_setstacksize: "
288 "requested size %d >= VG_PTHREAD_STACK_SIZE\n "
289 "edit vg_include.h and rebuild.", __stacksize);
290 buf[sizeof(buf)-1] = '\0'; /* Make sure it is zero terminated */
291 barf(buf);
sewardj0286dd52002-05-16 20:51:15 +0000292}
293
294
sewardj30671ff2002-04-21 00:13:57 +0000295/* This is completely bogus. */
296int pthread_attr_getschedparam(const pthread_attr_t *attr,
297 struct sched_param *param)
298{
sewardj436e0582002-04-26 14:31:40 +0000299 static int moans = N_MOANS;
300 if (moans-- > 0)
301 kludged("pthread_attr_getschedparam");
sewardj3e909ce2002-06-03 13:27:15 +0000302# ifdef HAVE_SCHED_PRIORITY
sewardj72d58482002-04-24 02:20:20 +0000303 if (param) param->sched_priority = 0; /* who knows */
304# else
sewardj30671ff2002-04-21 00:13:57 +0000305 if (param) param->__sched_priority = 0; /* who knows */
sewardj72d58482002-04-24 02:20:20 +0000306# endif
sewardj30671ff2002-04-21 00:13:57 +0000307 return 0;
308}
309
310int pthread_attr_setschedparam(pthread_attr_t *attr,
311 const struct sched_param *param)
312{
sewardj436e0582002-04-26 14:31:40 +0000313 static int moans = N_MOANS;
314 if (moans-- > 0)
315 ignored("pthread_attr_setschedparam");
sewardj30671ff2002-04-21 00:13:57 +0000316 return 0;
317}
318
319int pthread_attr_destroy(pthread_attr_t *attr)
320{
sewardj436e0582002-04-26 14:31:40 +0000321 static int moans = N_MOANS;
322 if (moans-- > 0)
323 ignored("pthread_attr_destroy");
sewardj30671ff2002-04-21 00:13:57 +0000324 return 0;
325}
sewardjf8f819e2002-04-17 23:21:37 +0000326
sewardj0d844232002-06-02 09:29:31 +0000327/* These are no-ops, as with LinuxThreads. */
328int pthread_attr_setscope ( pthread_attr_t *attr, int scope )
329{
330 ensure_valgrind("pthread_attr_setscope");
331 if (scope == PTHREAD_SCOPE_SYSTEM)
332 return 0;
sewardj4dced352002-06-04 22:54:20 +0000333 pthread_error("pthread_attr_setscope: "
334 "invalid or unsupported scope");
sewardj0d844232002-06-02 09:29:31 +0000335 if (scope == PTHREAD_SCOPE_PROCESS)
336 return ENOTSUP;
337 return EINVAL;
338}
339
340int pthread_attr_getscope ( const pthread_attr_t *attr, int *scope )
341{
342 ensure_valgrind("pthread_attr_setscope");
343 if (scope)
344 *scope = PTHREAD_SCOPE_SYSTEM;
345 return 0;
346}
347
sewardj64039bb2002-06-03 00:58:18 +0000348
349/* Pretty bogus. Avoid if possible. */
350int pthread_getattr_np (pthread_t thread, pthread_attr_t *attr)
351{
352 int detached;
353 size_t limit;
354 ensure_valgrind("pthread_getattr_np");
355 kludged("pthread_getattr_np");
356 limit = VG_PTHREAD_STACK_SIZE - VG_AR_CLIENT_STACKBASE_REDZONE_SZB
357 - 1000; /* paranoia */
358 attr->__detachstate = PTHREAD_CREATE_JOINABLE;
359 attr->__schedpolicy = SCHED_OTHER;
360 attr->__schedparam.sched_priority = 0;
361 attr->__inheritsched = PTHREAD_EXPLICIT_SCHED;
362 attr->__scope = PTHREAD_SCOPE_SYSTEM;
363 attr->__guardsize = VKI_BYTES_PER_PAGE;
364 attr->__stackaddr = NULL;
365 attr->__stackaddr_set = 0;
366 attr->__stacksize = limit;
367 VALGRIND_MAGIC_SEQUENCE(detached, (-1) /* default */,
368 VG_USERREQ__SET_OR_GET_DETACH,
369 2 /* get */, thread, 0, 0);
sewardj2d94c112002-06-03 01:25:54 +0000370 my_assert(detached == 0 || detached == 1);
sewardj64039bb2002-06-03 00:58:18 +0000371 if (detached)
372 attr->__detachstate = PTHREAD_CREATE_DETACHED;
373 return 0;
374}
375
376
377/* Bogus ... */
378int pthread_attr_getstackaddr ( const pthread_attr_t * attr,
379 void ** stackaddr )
380{
381 ensure_valgrind("pthread_attr_getstackaddr");
382 kludged("pthread_attr_getstackaddr");
383 if (stackaddr)
384 *stackaddr = NULL;
385 return 0;
386}
387
388/* Not bogus (!) */
389int pthread_attr_getstacksize ( const pthread_attr_t * _attr,
390 size_t * __stacksize )
391{
392 size_t limit;
393 ensure_valgrind("pthread_attr_getstacksize");
394 limit = VG_PTHREAD_STACK_SIZE - VG_AR_CLIENT_STACKBASE_REDZONE_SZB
395 - 1000; /* paranoia */
396 if (__stacksize)
397 *__stacksize = limit;
398 return 0;
399}
400
sewardja3be12f2002-06-17 12:19:44 +0000401int pthread_attr_setschedpolicy(pthread_attr_t *attr, int policy)
402{
403 if (policy != SCHED_OTHER && policy != SCHED_FIFO && policy != SCHED_RR)
404 return EINVAL;
405 attr->__schedpolicy = policy;
406 return 0;
407}
408
409int pthread_attr_getschedpolicy(const pthread_attr_t *attr, int *policy)
410{
411 *policy = attr->__schedpolicy;
412 return 0;
413}
414
415
sewardj20917d82002-05-28 01:36:45 +0000416/* ---------------------------------------------------
417 Helper functions for running a thread
418 and for clearing up afterwards.
419 ------------------------------------------------ */
420
421/* All exiting threads eventually pass through here, bearing the
422 return value, or PTHREAD_CANCELED, in ret_val. */
423static
424__attribute__((noreturn))
425void thread_exit_wrapper ( void* ret_val )
426{
sewardj870497a2002-05-29 01:06:47 +0000427 int detached, res;
428 CleanupEntry cu;
429 pthread_key_t key;
430
sewardj20917d82002-05-28 01:36:45 +0000431 /* Run this thread's cleanup handlers. */
sewardj8ad94e12002-05-29 00:10:20 +0000432 while (1) {
433 VALGRIND_MAGIC_SEQUENCE(res, (-1) /* default */,
434 VG_USERREQ__CLEANUP_POP,
435 &cu, 0, 0, 0);
436 if (res == -1) break; /* stack empty */
sewardj2d94c112002-06-03 01:25:54 +0000437 my_assert(res == 0);
sewardj8ad94e12002-05-29 00:10:20 +0000438 if (0) printf("running exit cleanup handler");
439 cu.fn ( cu.arg );
440 }
441
sewardj870497a2002-05-29 01:06:47 +0000442 /* Run this thread's key finalizers. Really this should be run
443 PTHREAD_DESTRUCTOR_ITERATIONS times. */
444 for (key = 0; key < VG_N_THREAD_KEYS; key++) {
445 VALGRIND_MAGIC_SEQUENCE(res, (-2) /* default */,
446 VG_USERREQ__GET_KEY_D_AND_S,
447 key, &cu, 0, 0 );
448 if (res == 0) {
449 /* valid key */
450 if (cu.fn && cu.arg)
451 cu.fn /* destructor for key */
452 ( cu.arg /* specific for key for this thread */ );
453 continue;
454 }
sewardj2d94c112002-06-03 01:25:54 +0000455 my_assert(res == -1);
sewardj870497a2002-05-29 01:06:47 +0000456 }
sewardj20917d82002-05-28 01:36:45 +0000457
458 /* Decide on my final disposition. */
459 VALGRIND_MAGIC_SEQUENCE(detached, (-1) /* default */,
460 VG_USERREQ__SET_OR_GET_DETACH,
sewardj7989d0c2002-05-28 11:00:01 +0000461 2 /* get */, pthread_self(), 0, 0);
sewardj2d94c112002-06-03 01:25:54 +0000462 my_assert(detached == 0 || detached == 1);
sewardj20917d82002-05-28 01:36:45 +0000463
464 if (detached) {
465 /* Detached; I just quit right now. */
466 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
467 VG_USERREQ__QUIT, 0, 0, 0, 0);
468 } else {
469 /* Not detached; so I wait for a joiner. */
470 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
471 VG_USERREQ__WAIT_JOINER, ret_val, 0, 0, 0);
472 }
473 /* NOTREACHED */
474 barf("thread_exit_wrapper: still alive?!");
475}
476
477
478/* This function is a wrapper function for running a thread. It runs
479 the root function specified in pthread_create, and then, should the
480 root function return a value, it arranges to run the thread's
481 cleanup handlers and exit correctly. */
482
sewardj728a5272002-06-20 10:25:37 +0000483/* Struct used to convey info from pthread_create to thread_wrapper.
484 Must be careful not to pass to the child thread any pointers to
485 objects which might be on the parent's stack. */
sewardj20917d82002-05-28 01:36:45 +0000486typedef
487 struct {
sewardj728a5272002-06-20 10:25:37 +0000488 int attr__detachstate;
sewardj20917d82002-05-28 01:36:45 +0000489 void* (*root_fn) ( void* );
490 void* arg;
491 }
492 NewThreadInfo;
493
494
495/* This is passed to the VG_USERREQ__APPLY_IN_NEW_THREAD and so must
496 not return. Note that this runs in the new thread, not the
497 parent. */
498static
499__attribute__((noreturn))
500void thread_wrapper ( NewThreadInfo* info )
501{
sewardj728a5272002-06-20 10:25:37 +0000502 int res;
503 int attr__detachstate;
sewardj20917d82002-05-28 01:36:45 +0000504 void* (*root_fn) ( void* );
505 void* arg;
506 void* ret_val;
507
sewardj728a5272002-06-20 10:25:37 +0000508 attr__detachstate = info->attr__detachstate;
509 root_fn = info->root_fn;
510 arg = info->arg;
sewardj20917d82002-05-28 01:36:45 +0000511
sewardj20917d82002-05-28 01:36:45 +0000512 /* Free up the arg block that pthread_create malloced. */
513 VALGRIND_MAGIC_SEQUENCE(res, (-1) /* default */,
514 VG_USERREQ__FREE, info, 0, 0, 0);
sewardj2d94c112002-06-03 01:25:54 +0000515 my_assert(res == 0);
sewardj20917d82002-05-28 01:36:45 +0000516
sewardj7989d0c2002-05-28 11:00:01 +0000517 /* Minimally observe the attributes supplied. */
sewardj728a5272002-06-20 10:25:37 +0000518 if (attr__detachstate != PTHREAD_CREATE_DETACHED
519 && attr__detachstate != PTHREAD_CREATE_JOINABLE)
520 pthread_error("thread_wrapper: invalid attr->__detachstate");
521 if (attr__detachstate == PTHREAD_CREATE_DETACHED)
522 pthread_detach(pthread_self());
sewardj7989d0c2002-05-28 11:00:01 +0000523
sewardj20917d82002-05-28 01:36:45 +0000524 /* The root function might not return. But if it does we simply
525 move along to thread_exit_wrapper. All other ways out for the
526 thread (cancellation, or calling pthread_exit) lead there
527 too. */
528 ret_val = root_fn(arg);
529 thread_exit_wrapper(ret_val);
530 /* NOTREACHED */
531}
532
533
sewardjf8f819e2002-04-17 23:21:37 +0000534/* ---------------------------------------------------
535 THREADs
536 ------------------------------------------------ */
537
sewardjff42d1d2002-05-22 13:17:31 +0000538__attribute__((weak))
539int pthread_yield ( void )
540{
541 int res;
542 ensure_valgrind("pthread_yield");
543 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
544 VG_USERREQ__PTHREAD_YIELD, 0, 0, 0, 0);
545 return 0;
546}
547
548
sewardj6072c362002-04-19 14:40:57 +0000549int pthread_equal(pthread_t thread1, pthread_t thread2)
550{
551 return thread1 == thread2 ? 1 : 0;
552}
553
554
sewardj20917d82002-05-28 01:36:45 +0000555/* Bundle up the args into a malloc'd block and create a new thread
556 consisting of thread_wrapper() applied to said malloc'd block. */
sewardje663cb92002-04-12 10:26:32 +0000557int
sewardj1462c8b2002-07-24 09:41:52 +0000558pthread_create (pthread_t *__restrict __thredd,
sewardje663cb92002-04-12 10:26:32 +0000559 __const pthread_attr_t *__restrict __attr,
560 void *(*__start_routine) (void *),
561 void *__restrict __arg)
562{
sewardj20917d82002-05-28 01:36:45 +0000563 int tid_child;
564 NewThreadInfo* info;
sewardje663cb92002-04-12 10:26:32 +0000565
sewardj20917d82002-05-28 01:36:45 +0000566 ensure_valgrind("pthread_create");
567
568 /* Allocate space for the arg block. thread_wrapper will free
569 it. */
570 VALGRIND_MAGIC_SEQUENCE(info, NULL /* default */,
571 VG_USERREQ__MALLOC,
572 sizeof(NewThreadInfo), 0, 0, 0);
sewardj2d94c112002-06-03 01:25:54 +0000573 my_assert(info != NULL);
sewardj20917d82002-05-28 01:36:45 +0000574
sewardj728a5272002-06-20 10:25:37 +0000575 if (__attr)
576 info->attr__detachstate = __attr->__detachstate;
577 else
578 info->attr__detachstate = PTHREAD_CREATE_JOINABLE;
579
sewardj20917d82002-05-28 01:36:45 +0000580 info->root_fn = __start_routine;
581 info->arg = __arg;
582 VALGRIND_MAGIC_SEQUENCE(tid_child, VG_INVALID_THREADID /* default */,
583 VG_USERREQ__APPLY_IN_NEW_THREAD,
584 &thread_wrapper, info, 0, 0);
sewardj2d94c112002-06-03 01:25:54 +0000585 my_assert(tid_child != VG_INVALID_THREADID);
sewardj20917d82002-05-28 01:36:45 +0000586
sewardj1462c8b2002-07-24 09:41:52 +0000587 if (__thredd)
588 *__thredd = tid_child;
sewardj20917d82002-05-28 01:36:45 +0000589 return 0; /* success */
590}
sewardje663cb92002-04-12 10:26:32 +0000591
592
593int
594pthread_join (pthread_t __th, void **__thread_return)
595{
596 int res;
597 ensure_valgrind("pthread_join");
598 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
599 VG_USERREQ__PTHREAD_JOIN,
600 __th, __thread_return, 0, 0);
601 return res;
602}
603
604
sewardj3b5d8862002-04-20 13:53:23 +0000605void pthread_exit(void *retval)
606{
sewardj3b5d8862002-04-20 13:53:23 +0000607 ensure_valgrind("pthread_exit");
sewardj20917d82002-05-28 01:36:45 +0000608 /* Simple! */
609 thread_exit_wrapper(retval);
sewardj3b5d8862002-04-20 13:53:23 +0000610}
611
sewardje663cb92002-04-12 10:26:32 +0000612
sewardj3b13f0e2002-04-25 20:17:29 +0000613pthread_t pthread_self(void)
sewardje663cb92002-04-12 10:26:32 +0000614{
615 int tid;
sewardj3b13f0e2002-04-25 20:17:29 +0000616 ensure_valgrind("pthread_self");
sewardj439d45e2002-05-03 20:43:10 +0000617 VALGRIND_MAGIC_SEQUENCE(tid, 1 /* default */,
sewardje663cb92002-04-12 10:26:32 +0000618 VG_USERREQ__PTHREAD_GET_THREADID,
619 0, 0, 0, 0);
sewardj439d45e2002-05-03 20:43:10 +0000620 if (tid < 1 || tid >= VG_N_THREADS)
sewardj3b13f0e2002-04-25 20:17:29 +0000621 barf("pthread_self: invalid ThreadId");
622 return tid;
sewardje663cb92002-04-12 10:26:32 +0000623}
624
625
sewardj853f55d2002-04-26 00:27:53 +0000626int pthread_detach(pthread_t th)
627{
sewardj20917d82002-05-28 01:36:45 +0000628 int res;
629 ensure_valgrind("pthread_detach");
sewardj7989d0c2002-05-28 11:00:01 +0000630 /* First we enquire as to the current detach state. */
631 VALGRIND_MAGIC_SEQUENCE(res, (-2) /* default */,
sewardj20917d82002-05-28 01:36:45 +0000632 VG_USERREQ__SET_OR_GET_DETACH,
sewardj7989d0c2002-05-28 11:00:01 +0000633 2 /* get */, th, 0, 0);
sewardj4dced352002-06-04 22:54:20 +0000634 if (res == -1) {
635 /* not found */
636 pthread_error("pthread_detach: "
637 "invalid target thread");
sewardj7989d0c2002-05-28 11:00:01 +0000638 return ESRCH;
sewardj4dced352002-06-04 22:54:20 +0000639 }
640 if (res == 1) {
641 /* already detached */
642 pthread_error("pthread_detach: "
643 "target thread is already detached");
sewardj7989d0c2002-05-28 11:00:01 +0000644 return EINVAL;
sewardj4dced352002-06-04 22:54:20 +0000645 }
sewardj7989d0c2002-05-28 11:00:01 +0000646 if (res == 0) {
647 VALGRIND_MAGIC_SEQUENCE(res, (-2) /* default */,
648 VG_USERREQ__SET_OR_GET_DETACH,
649 1 /* set */, th, 0, 0);
sewardj2d94c112002-06-03 01:25:54 +0000650 my_assert(res == 0);
sewardj7989d0c2002-05-28 11:00:01 +0000651 return 0;
652 }
653 barf("pthread_detach");
sewardj853f55d2002-04-26 00:27:53 +0000654}
655
656
sewardjf8f819e2002-04-17 23:21:37 +0000657/* ---------------------------------------------------
sewardj8ad94e12002-05-29 00:10:20 +0000658 CLEANUP STACKS
659 ------------------------------------------------ */
660
661void _pthread_cleanup_push (struct _pthread_cleanup_buffer *__buffer,
662 void (*__routine) (void *),
663 void *__arg)
664{
665 int res;
666 CleanupEntry cu;
667 ensure_valgrind("_pthread_cleanup_push");
668 cu.fn = __routine;
669 cu.arg = __arg;
670 VALGRIND_MAGIC_SEQUENCE(res, (-1) /* default */,
671 VG_USERREQ__CLEANUP_PUSH,
672 &cu, 0, 0, 0);
sewardj2d94c112002-06-03 01:25:54 +0000673 my_assert(res == 0);
sewardj8ad94e12002-05-29 00:10:20 +0000674}
675
676
677void _pthread_cleanup_push_defer (struct _pthread_cleanup_buffer *__buffer,
678 void (*__routine) (void *),
679 void *__arg)
680{
681 /* As _pthread_cleanup_push, but first save the thread's original
682 cancellation type in __buffer and set it to Deferred. */
683 int orig_ctype;
684 ensure_valgrind("_pthread_cleanup_push_defer");
685 /* Set to Deferred, and put the old cancellation type in res. */
sewardj2d94c112002-06-03 01:25:54 +0000686 my_assert(-1 != PTHREAD_CANCEL_DEFERRED);
687 my_assert(-1 != PTHREAD_CANCEL_ASYNCHRONOUS);
688 my_assert(sizeof(struct _pthread_cleanup_buffer) >= sizeof(int));
sewardj8ad94e12002-05-29 00:10:20 +0000689 VALGRIND_MAGIC_SEQUENCE(orig_ctype, (-1) /* default */,
690 VG_USERREQ__SET_CANCELTYPE,
691 PTHREAD_CANCEL_DEFERRED, 0, 0, 0);
sewardj2d94c112002-06-03 01:25:54 +0000692 my_assert(orig_ctype != -1);
sewardj8ad94e12002-05-29 00:10:20 +0000693 *((int*)(__buffer)) = orig_ctype;
694 /* Now push the cleanup. */
695 _pthread_cleanup_push(NULL, __routine, __arg);
696}
697
698
699void _pthread_cleanup_pop (struct _pthread_cleanup_buffer *__buffer,
700 int __execute)
701{
702 int res;
703 CleanupEntry cu;
704 ensure_valgrind("_pthread_cleanup_push");
705 cu.fn = cu.arg = NULL; /* paranoia */
706 VALGRIND_MAGIC_SEQUENCE(res, (-1) /* default */,
707 VG_USERREQ__CLEANUP_POP,
708 &cu, 0, 0, 0);
709 if (res == 0) {
710 /* pop succeeded */
711 if (__execute) {
712 cu.fn ( cu.arg );
713 }
714 return;
715 }
716 if (res == -1) {
717 /* stack underflow */
718 return;
719 }
720 barf("_pthread_cleanup_pop");
721}
722
723
724void _pthread_cleanup_pop_restore (struct _pthread_cleanup_buffer *__buffer,
725 int __execute)
726{
727 int orig_ctype, fake_ctype;
728 /* As _pthread_cleanup_pop, but after popping/running the handler,
729 restore the thread's original cancellation type from the first
730 word of __buffer. */
731 _pthread_cleanup_pop(NULL, __execute);
732 orig_ctype = *((int*)(__buffer));
sewardj2d94c112002-06-03 01:25:54 +0000733 my_assert(orig_ctype == PTHREAD_CANCEL_DEFERRED
sewardj8ad94e12002-05-29 00:10:20 +0000734 || orig_ctype == PTHREAD_CANCEL_ASYNCHRONOUS);
sewardj2d94c112002-06-03 01:25:54 +0000735 my_assert(-1 != PTHREAD_CANCEL_DEFERRED);
736 my_assert(-1 != PTHREAD_CANCEL_ASYNCHRONOUS);
737 my_assert(sizeof(struct _pthread_cleanup_buffer) >= sizeof(int));
sewardj8ad94e12002-05-29 00:10:20 +0000738 VALGRIND_MAGIC_SEQUENCE(fake_ctype, (-1) /* default */,
739 VG_USERREQ__SET_CANCELTYPE,
740 orig_ctype, 0, 0, 0);
sewardj2d94c112002-06-03 01:25:54 +0000741 my_assert(fake_ctype == PTHREAD_CANCEL_DEFERRED);
sewardj8ad94e12002-05-29 00:10:20 +0000742}
743
744
745/* ---------------------------------------------------
sewardjf8f819e2002-04-17 23:21:37 +0000746 MUTEX ATTRIBUTES
747 ------------------------------------------------ */
748
sewardj5905fae2002-04-26 13:25:00 +0000749int __pthread_mutexattr_init(pthread_mutexattr_t *attr)
sewardje663cb92002-04-12 10:26:32 +0000750{
sewardjf8f819e2002-04-17 23:21:37 +0000751 attr->__mutexkind = PTHREAD_MUTEX_ERRORCHECK_NP;
sewardj8937c812002-04-12 20:12:20 +0000752 return 0;
sewardje663cb92002-04-12 10:26:32 +0000753}
754
sewardj5905fae2002-04-26 13:25:00 +0000755int __pthread_mutexattr_settype(pthread_mutexattr_t *attr, int type)
sewardjf8f819e2002-04-17 23:21:37 +0000756{
757 switch (type) {
sewardj3b13f0e2002-04-25 20:17:29 +0000758# ifndef GLIBC_2_1
sewardjf8f819e2002-04-17 23:21:37 +0000759 case PTHREAD_MUTEX_TIMED_NP:
sewardj2a1dcce2002-04-22 12:45:25 +0000760 case PTHREAD_MUTEX_ADAPTIVE_NP:
sewardj3b13f0e2002-04-25 20:17:29 +0000761# endif
sewardja1679dd2002-05-10 22:31:40 +0000762# ifdef GLIBC_2_1
sewardj68b2dd92002-05-10 21:03:56 +0000763 case PTHREAD_MUTEX_FAST_NP:
sewardja1679dd2002-05-10 22:31:40 +0000764# endif
sewardjf8f819e2002-04-17 23:21:37 +0000765 case PTHREAD_MUTEX_RECURSIVE_NP:
766 case PTHREAD_MUTEX_ERRORCHECK_NP:
sewardjf8f819e2002-04-17 23:21:37 +0000767 attr->__mutexkind = type;
768 return 0;
769 default:
sewardj4dced352002-06-04 22:54:20 +0000770 pthread_error("pthread_mutexattr_settype: "
771 "invalid type");
sewardjf8f819e2002-04-17 23:21:37 +0000772 return EINVAL;
773 }
774}
775
sewardj5905fae2002-04-26 13:25:00 +0000776int __pthread_mutexattr_destroy(pthread_mutexattr_t *attr)
sewardjf8f819e2002-04-17 23:21:37 +0000777{
778 return 0;
779}
780
781
782/* ---------------------------------------------------
783 MUTEXes
784 ------------------------------------------------ */
785
sewardj5905fae2002-04-26 13:25:00 +0000786int __pthread_mutex_init(pthread_mutex_t *mutex,
787 const pthread_mutexattr_t *mutexattr)
sewardje663cb92002-04-12 10:26:32 +0000788{
sewardj604ec3c2002-04-18 22:38:41 +0000789 mutex->__m_count = 0;
790 mutex->__m_owner = (_pthread_descr)VG_INVALID_THREADID;
791 mutex->__m_kind = PTHREAD_MUTEX_ERRORCHECK_NP;
792 if (mutexattr)
793 mutex->__m_kind = mutexattr->__mutexkind;
794 return 0;
sewardje663cb92002-04-12 10:26:32 +0000795}
796
sewardj439d45e2002-05-03 20:43:10 +0000797
sewardj5905fae2002-04-26 13:25:00 +0000798int __pthread_mutex_lock(pthread_mutex_t *mutex)
sewardje663cb92002-04-12 10:26:32 +0000799{
800 int res;
sewardj436e0582002-04-26 14:31:40 +0000801 static int moans = N_MOANS;
sewardj439d45e2002-05-03 20:43:10 +0000802 if (RUNNING_ON_VALGRIND) {
sewardje663cb92002-04-12 10:26:32 +0000803 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
804 VG_USERREQ__PTHREAD_MUTEX_LOCK,
805 mutex, 0, 0, 0);
806 return res;
sewardj439d45e2002-05-03 20:43:10 +0000807 } else {
808 if (moans-- > 0)
809 not_inside("pthread_mutex_lock");
810 return 0; /* success */
sewardje663cb92002-04-12 10:26:32 +0000811 }
812}
813
sewardj439d45e2002-05-03 20:43:10 +0000814
sewardj5905fae2002-04-26 13:25:00 +0000815int __pthread_mutex_trylock(pthread_mutex_t *mutex)
sewardj30671ff2002-04-21 00:13:57 +0000816{
817 int res;
sewardj436e0582002-04-26 14:31:40 +0000818 static int moans = N_MOANS;
sewardj439d45e2002-05-03 20:43:10 +0000819 if (RUNNING_ON_VALGRIND) {
sewardj30671ff2002-04-21 00:13:57 +0000820 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
821 VG_USERREQ__PTHREAD_MUTEX_TRYLOCK,
822 mutex, 0, 0, 0);
823 return res;
sewardj439d45e2002-05-03 20:43:10 +0000824 } else {
825 if (moans-- > 0)
826 not_inside("pthread_mutex_trylock");
827 return 0;
sewardj30671ff2002-04-21 00:13:57 +0000828 }
829}
830
sewardj439d45e2002-05-03 20:43:10 +0000831
sewardj5905fae2002-04-26 13:25:00 +0000832int __pthread_mutex_unlock(pthread_mutex_t *mutex)
sewardje663cb92002-04-12 10:26:32 +0000833{
834 int res;
sewardj436e0582002-04-26 14:31:40 +0000835 static int moans = N_MOANS;
sewardj439d45e2002-05-03 20:43:10 +0000836 if (RUNNING_ON_VALGRIND) {
sewardje663cb92002-04-12 10:26:32 +0000837 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
838 VG_USERREQ__PTHREAD_MUTEX_UNLOCK,
839 mutex, 0, 0, 0);
840 return res;
sewardj439d45e2002-05-03 20:43:10 +0000841 } else {
842 if (moans-- > 0)
843 not_inside("pthread_mutex_unlock");
844 return 0;
sewardje663cb92002-04-12 10:26:32 +0000845 }
846}
847
sewardj439d45e2002-05-03 20:43:10 +0000848
sewardj5905fae2002-04-26 13:25:00 +0000849int __pthread_mutex_destroy(pthread_mutex_t *mutex)
sewardje663cb92002-04-12 10:26:32 +0000850{
sewardj604ec3c2002-04-18 22:38:41 +0000851 /* Valgrind doesn't hold any resources on behalf of the mutex, so no
852 need to involve it. */
sewardj4dced352002-06-04 22:54:20 +0000853 if (mutex->__m_count > 0) {
854 pthread_error("pthread_mutex_destroy: "
855 "mutex is still in use");
sewardj604ec3c2002-04-18 22:38:41 +0000856 return EBUSY;
sewardj4dced352002-06-04 22:54:20 +0000857 }
858 mutex->__m_count = 0;
859 mutex->__m_owner = (_pthread_descr)VG_INVALID_THREADID;
860 mutex->__m_kind = PTHREAD_MUTEX_ERRORCHECK_NP;
861 return 0;
sewardje663cb92002-04-12 10:26:32 +0000862}
863
864
sewardjf8f819e2002-04-17 23:21:37 +0000865/* ---------------------------------------------------
sewardj6072c362002-04-19 14:40:57 +0000866 CONDITION VARIABLES
867 ------------------------------------------------ */
868
869/* LinuxThreads supports no attributes for conditions. Hence ... */
870
871int pthread_condattr_init(pthread_condattr_t *attr)
872{
873 return 0;
874}
875
sewardj0738a592002-04-20 13:59:33 +0000876int pthread_condattr_destroy(pthread_condattr_t *attr)
877{
878 return 0;
879}
sewardj6072c362002-04-19 14:40:57 +0000880
881int pthread_cond_init( pthread_cond_t *cond,
882 const pthread_condattr_t *cond_attr)
883{
884 cond->__c_waiting = (_pthread_descr)VG_INVALID_THREADID;
885 return 0;
886}
887
sewardjf854f472002-04-21 12:19:41 +0000888int pthread_cond_destroy(pthread_cond_t *cond)
889{
890 /* should check that no threads are waiting on this CV */
sewardj436e0582002-04-26 14:31:40 +0000891 static int moans = N_MOANS;
892 if (moans-- > 0)
893 kludged("pthread_cond_destroy");
sewardjf854f472002-04-21 12:19:41 +0000894 return 0;
895}
sewardj6072c362002-04-19 14:40:57 +0000896
897/* ---------------------------------------------------
898 SCHEDULING
899 ------------------------------------------------ */
900
901/* This is completely bogus. */
902int pthread_getschedparam(pthread_t target_thread,
903 int *policy,
904 struct sched_param *param)
905{
sewardj436e0582002-04-26 14:31:40 +0000906 static int moans = N_MOANS;
907 if (moans-- > 0)
908 kludged("pthread_getschedparam");
sewardj6072c362002-04-19 14:40:57 +0000909 if (policy) *policy = SCHED_OTHER;
sewardj3e909ce2002-06-03 13:27:15 +0000910# ifdef HAVE_SCHED_PRIORITY
sewardj2a1dcce2002-04-22 12:45:25 +0000911 if (param) param->sched_priority = 0; /* who knows */
912# else
sewardj6072c362002-04-19 14:40:57 +0000913 if (param) param->__sched_priority = 0; /* who knows */
sewardj2a1dcce2002-04-22 12:45:25 +0000914# endif
sewardj6072c362002-04-19 14:40:57 +0000915 return 0;
916}
917
918int pthread_setschedparam(pthread_t target_thread,
919 int policy,
920 const struct sched_param *param)
921{
sewardj436e0582002-04-26 14:31:40 +0000922 static int moans = N_MOANS;
923 if (moans-- > 0)
924 ignored("pthread_setschedparam");
sewardj6072c362002-04-19 14:40:57 +0000925 return 0;
926}
927
sewardj3b5d8862002-04-20 13:53:23 +0000928int pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex)
929{
930 int res;
931 ensure_valgrind("pthread_cond_wait");
932 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
933 VG_USERREQ__PTHREAD_COND_WAIT,
934 cond, mutex, 0, 0);
935 return res;
936}
937
sewardj5f07b662002-04-23 16:52:51 +0000938int pthread_cond_timedwait ( pthread_cond_t *cond,
939 pthread_mutex_t *mutex,
940 const struct timespec *abstime )
941{
942 int res;
943 unsigned int ms_now, ms_end;
944 struct timeval timeval_now;
945 unsigned long long int ull_ms_now_after_1970;
946 unsigned long long int ull_ms_end_after_1970;
947
948 ensure_valgrind("pthread_cond_timedwait");
949 VALGRIND_MAGIC_SEQUENCE(ms_now, 0xFFFFFFFF /* default */,
950 VG_USERREQ__READ_MILLISECOND_TIMER,
951 0, 0, 0, 0);
sewardj2d94c112002-06-03 01:25:54 +0000952 my_assert(ms_now != 0xFFFFFFFF);
sewardj5f07b662002-04-23 16:52:51 +0000953 res = gettimeofday(&timeval_now, NULL);
sewardj2d94c112002-06-03 01:25:54 +0000954 my_assert(res == 0);
sewardj5f07b662002-04-23 16:52:51 +0000955
956 ull_ms_now_after_1970
957 = 1000ULL * ((unsigned long long int)(timeval_now.tv_sec))
958 + ((unsigned long long int)(timeval_now.tv_usec / 1000000));
959 ull_ms_end_after_1970
960 = 1000ULL * ((unsigned long long int)(abstime->tv_sec))
961 + ((unsigned long long int)(abstime->tv_nsec / 1000000));
sewardjd8e919e2002-05-29 20:13:53 +0000962 if (ull_ms_end_after_1970 < ull_ms_now_after_1970)
963 ull_ms_end_after_1970 = ull_ms_now_after_1970;
sewardj5f07b662002-04-23 16:52:51 +0000964 ms_end
965 = ms_now + (unsigned int)(ull_ms_end_after_1970 - ull_ms_now_after_1970);
966 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
967 VG_USERREQ__PTHREAD_COND_TIMEDWAIT,
968 cond, mutex, ms_end, 0);
969 return res;
970}
971
972
sewardj3b5d8862002-04-20 13:53:23 +0000973int pthread_cond_signal(pthread_cond_t *cond)
974{
975 int res;
976 ensure_valgrind("pthread_cond_signal");
977 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
978 VG_USERREQ__PTHREAD_COND_SIGNAL,
979 cond, 0, 0, 0);
980 return res;
981}
982
983int pthread_cond_broadcast(pthread_cond_t *cond)
984{
985 int res;
986 ensure_valgrind("pthread_cond_broadcast");
987 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
988 VG_USERREQ__PTHREAD_COND_BROADCAST,
989 cond, 0, 0, 0);
990 return res;
991}
992
sewardj6072c362002-04-19 14:40:57 +0000993
994/* ---------------------------------------------------
sewardjf8f819e2002-04-17 23:21:37 +0000995 CANCELLATION
996 ------------------------------------------------ */
997
sewardj853f55d2002-04-26 00:27:53 +0000998int pthread_setcancelstate(int state, int *oldstate)
999{
sewardj20917d82002-05-28 01:36:45 +00001000 int res;
1001 ensure_valgrind("pthread_setcancelstate");
1002 if (state != PTHREAD_CANCEL_ENABLE
sewardj4dced352002-06-04 22:54:20 +00001003 && state != PTHREAD_CANCEL_DISABLE) {
1004 pthread_error("pthread_setcancelstate: "
1005 "invalid state");
sewardj20917d82002-05-28 01:36:45 +00001006 return EINVAL;
sewardj4dced352002-06-04 22:54:20 +00001007 }
sewardj2d94c112002-06-03 01:25:54 +00001008 my_assert(-1 != PTHREAD_CANCEL_ENABLE);
1009 my_assert(-1 != PTHREAD_CANCEL_DISABLE);
sewardj20917d82002-05-28 01:36:45 +00001010 VALGRIND_MAGIC_SEQUENCE(res, (-1) /* default */,
1011 VG_USERREQ__SET_CANCELSTATE,
1012 state, 0, 0, 0);
sewardj2d94c112002-06-03 01:25:54 +00001013 my_assert(res != -1);
sewardj20917d82002-05-28 01:36:45 +00001014 if (oldstate)
1015 *oldstate = res;
sewardj853f55d2002-04-26 00:27:53 +00001016 return 0;
1017}
1018
sewardje663cb92002-04-12 10:26:32 +00001019int pthread_setcanceltype(int type, int *oldtype)
1020{
sewardj20917d82002-05-28 01:36:45 +00001021 int res;
1022 ensure_valgrind("pthread_setcanceltype");
1023 if (type != PTHREAD_CANCEL_DEFERRED
sewardj4dced352002-06-04 22:54:20 +00001024 && type != PTHREAD_CANCEL_ASYNCHRONOUS) {
1025 pthread_error("pthread_setcanceltype: "
1026 "invalid type");
sewardj20917d82002-05-28 01:36:45 +00001027 return EINVAL;
sewardj4dced352002-06-04 22:54:20 +00001028 }
sewardj2d94c112002-06-03 01:25:54 +00001029 my_assert(-1 != PTHREAD_CANCEL_DEFERRED);
1030 my_assert(-1 != PTHREAD_CANCEL_ASYNCHRONOUS);
sewardj20917d82002-05-28 01:36:45 +00001031 VALGRIND_MAGIC_SEQUENCE(res, (-1) /* default */,
1032 VG_USERREQ__SET_CANCELTYPE,
1033 type, 0, 0, 0);
sewardj2d94c112002-06-03 01:25:54 +00001034 my_assert(res != -1);
sewardj20917d82002-05-28 01:36:45 +00001035 if (oldtype)
1036 *oldtype = res;
sewardje663cb92002-04-12 10:26:32 +00001037 return 0;
1038}
1039
sewardje663cb92002-04-12 10:26:32 +00001040int pthread_cancel(pthread_t thread)
1041{
1042 int res;
1043 ensure_valgrind("pthread_cancel");
sewardj20917d82002-05-28 01:36:45 +00001044 VALGRIND_MAGIC_SEQUENCE(res, (-1) /* default */,
1045 VG_USERREQ__SET_CANCELPEND,
1046 thread, &thread_exit_wrapper, 0, 0);
sewardj2d94c112002-06-03 01:25:54 +00001047 my_assert(res != -1);
sewardje663cb92002-04-12 10:26:32 +00001048 return res;
1049}
1050
sewardjd140e442002-05-29 01:21:19 +00001051static __inline__
1052void __my_pthread_testcancel(void)
sewardj853f55d2002-04-26 00:27:53 +00001053{
sewardj20917d82002-05-28 01:36:45 +00001054 int res;
njn25e49d8e72002-09-23 09:36:25 +00001055 ensure_valgrind("__my_pthread_testcancel");
sewardj20917d82002-05-28 01:36:45 +00001056 VALGRIND_MAGIC_SEQUENCE(res, (-1) /* default */,
1057 VG_USERREQ__TESTCANCEL,
1058 0, 0, 0, 0);
sewardj2d94c112002-06-03 01:25:54 +00001059 my_assert(res == 0);
sewardj853f55d2002-04-26 00:27:53 +00001060}
1061
sewardjd140e442002-05-29 01:21:19 +00001062void pthread_testcancel ( void )
1063{
1064 __my_pthread_testcancel();
1065}
1066
sewardj20917d82002-05-28 01:36:45 +00001067
sewardjef037c72002-05-30 00:40:03 +00001068/* Not really sure what this is for. I suspect for doing the POSIX
1069 requirements for fork() and exec(). We do this internally anyway
1070 whenever those syscalls are observed, so this could be superfluous,
1071 but hey ...
1072*/
sewardj853f55d2002-04-26 00:27:53 +00001073void __pthread_kill_other_threads_np ( void )
1074{
sewardjef037c72002-05-30 00:40:03 +00001075 int res;
1076 ensure_valgrind("__pthread_kill_other_threads_np");
1077 VALGRIND_MAGIC_SEQUENCE(res, (-1) /* default */,
1078 VG_USERREQ__NUKE_OTHER_THREADS,
1079 0, 0, 0, 0);
sewardj2d94c112002-06-03 01:25:54 +00001080 my_assert(res == 0);
sewardj853f55d2002-04-26 00:27:53 +00001081}
1082
sewardje663cb92002-04-12 10:26:32 +00001083
sewardjf8f819e2002-04-17 23:21:37 +00001084/* ---------------------------------------------------
sewardjb48e5002002-05-13 00:16:03 +00001085 SIGNALS
1086 ------------------------------------------------ */
1087
1088#include <signal.h>
1089
1090int pthread_sigmask(int how, const sigset_t *newmask,
1091 sigset_t *oldmask)
1092{
1093 int res;
1094
1095 /* A bit subtle, because the scheduler expects newmask and oldmask
1096 to be vki_sigset_t* rather than sigset_t*, and the two are
1097 different. Fortunately the first 64 bits of a sigset_t are
1098 exactly a vki_sigset_t, so we just pass the pointers through
1099 unmodified. Haaaack!
1100
1101 Also mash the how value so that the SIG_ constants from glibc
sewardj018f7622002-05-15 21:13:39 +00001102 constants to VKI_ constants, so that the former do not have to
1103 be included into vg_scheduler.c. */
sewardjb48e5002002-05-13 00:16:03 +00001104
1105 ensure_valgrind("pthread_sigmask");
1106
1107 switch (how) {
sewardj018f7622002-05-15 21:13:39 +00001108 case SIG_SETMASK: how = VKI_SIG_SETMASK; break;
1109 case SIG_BLOCK: how = VKI_SIG_BLOCK; break;
1110 case SIG_UNBLOCK: how = VKI_SIG_UNBLOCK; break;
sewardj4dced352002-06-04 22:54:20 +00001111 default: pthread_error("pthread_sigmask: invalid how");
1112 return EINVAL;
sewardjb48e5002002-05-13 00:16:03 +00001113 }
1114
1115 /* Crude check */
1116 if (newmask == NULL)
1117 return EFAULT;
1118
1119 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
1120 VG_USERREQ__PTHREAD_SIGMASK,
1121 how, newmask, oldmask, 0);
1122
1123 /* The scheduler tells us of any memory violations. */
1124 return res == 0 ? 0 : EFAULT;
1125}
1126
1127
1128int sigwait ( const sigset_t* set, int* sig )
1129{
1130 int res;
1131 ensure_valgrind("sigwait");
1132 /* As with pthread_sigmask we deliberately confuse sigset_t with
1133 vki_ksigset_t. */
1134 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
1135 VG_USERREQ__SIGWAIT,
1136 set, sig, 0, 0);
1137 return res;
1138}
1139
1140
sewardj018f7622002-05-15 21:13:39 +00001141int pthread_kill(pthread_t thread, int signo)
1142{
1143 int res;
1144 ensure_valgrind("pthread_kill");
1145 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
1146 VG_USERREQ__PTHREAD_KILL,
1147 thread, signo, 0, 0);
1148 return res;
1149}
1150
1151
sewardj3665ded2002-05-16 16:57:25 +00001152/* Copied verbatim from Linuxthreads */
1153/* Redefine raise() to send signal to calling thread only,
1154 as per POSIX 1003.1c */
1155int raise (int sig)
1156{
1157 int retcode = pthread_kill(pthread_self(), sig);
sewardj4dced352002-06-04 22:54:20 +00001158 if (retcode == 0) {
sewardj3665ded2002-05-16 16:57:25 +00001159 return 0;
sewardj4dced352002-06-04 22:54:20 +00001160 } else {
sewardj3665ded2002-05-16 16:57:25 +00001161 errno = retcode;
1162 return -1;
1163 }
1164}
1165
1166
sewardj9a2224b2002-06-19 10:17:40 +00001167int pause ( void )
1168{
1169 unsigned int n_orig, n_now;
1170 struct vki_timespec nanosleep_interval;
1171 ensure_valgrind("pause");
1172
1173 /* This is surely a cancellation point. */
1174 __my_pthread_testcancel();
1175
1176 VALGRIND_MAGIC_SEQUENCE(n_orig, 0xFFFFFFFF /* default */,
1177 VG_USERREQ__GET_N_SIGS_RETURNED,
1178 0, 0, 0, 0);
1179 my_assert(n_orig != 0xFFFFFFFF);
1180
1181 while (1) {
1182 VALGRIND_MAGIC_SEQUENCE(n_now, 0xFFFFFFFF /* default */,
1183 VG_USERREQ__GET_N_SIGS_RETURNED,
1184 0, 0, 0, 0);
1185 my_assert(n_now != 0xFFFFFFFF);
1186 my_assert(n_now >= n_orig);
1187 if (n_now != n_orig) break;
1188
1189 nanosleep_interval.tv_sec = 0;
njn25e49d8e72002-09-23 09:36:25 +00001190 nanosleep_interval.tv_nsec = 12 * 1000 * 1000; /* 12 milliseconds */
sewardj9a2224b2002-06-19 10:17:40 +00001191 /* It's critical here that valgrind's nanosleep implementation
1192 is nonblocking. */
1193 (void)my_do_syscall2(__NR_nanosleep,
1194 (int)(&nanosleep_interval), (int)NULL);
1195 }
1196
1197 * (__errno_location()) = EINTR;
1198 return -1;
1199}
1200
1201
sewardjb48e5002002-05-13 00:16:03 +00001202/* ---------------------------------------------------
sewardjf8f819e2002-04-17 23:21:37 +00001203 THREAD-SPECIFICs
1204 ------------------------------------------------ */
sewardj5e5fa512002-04-14 13:13:05 +00001205
sewardj5905fae2002-04-26 13:25:00 +00001206int __pthread_key_create(pthread_key_t *key,
1207 void (*destr_function) (void *))
sewardj5e5fa512002-04-14 13:13:05 +00001208{
sewardj5f07b662002-04-23 16:52:51 +00001209 int res;
1210 ensure_valgrind("pthread_key_create");
1211 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
1212 VG_USERREQ__PTHREAD_KEY_CREATE,
1213 key, destr_function, 0, 0);
1214 return res;
sewardj5e5fa512002-04-14 13:13:05 +00001215}
1216
1217int pthread_key_delete(pthread_key_t key)
1218{
sewardj436e0582002-04-26 14:31:40 +00001219 static int moans = N_MOANS;
1220 if (moans-- > 0)
1221 ignored("pthread_key_delete");
sewardj5e5fa512002-04-14 13:13:05 +00001222 return 0;
1223}
1224
sewardj5905fae2002-04-26 13:25:00 +00001225int __pthread_setspecific(pthread_key_t key, const void *pointer)
sewardj5e5fa512002-04-14 13:13:05 +00001226{
sewardj5f07b662002-04-23 16:52:51 +00001227 int res;
1228 ensure_valgrind("pthread_setspecific");
1229 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
1230 VG_USERREQ__PTHREAD_SETSPECIFIC,
1231 key, pointer, 0, 0);
1232 return res;
sewardj5e5fa512002-04-14 13:13:05 +00001233}
1234
sewardj5905fae2002-04-26 13:25:00 +00001235void * __pthread_getspecific(pthread_key_t key)
sewardj5e5fa512002-04-14 13:13:05 +00001236{
sewardj5f07b662002-04-23 16:52:51 +00001237 int res;
1238 ensure_valgrind("pthread_getspecific");
1239 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
1240 VG_USERREQ__PTHREAD_GETSPECIFIC,
1241 key, 0 , 0, 0);
1242 return (void*)res;
sewardj5e5fa512002-04-14 13:13:05 +00001243}
1244
sewardjf8f819e2002-04-17 23:21:37 +00001245
1246/* ---------------------------------------------------
sewardj89d3d852002-04-24 19:21:39 +00001247 ONCEry
1248 ------------------------------------------------ */
1249
1250static pthread_mutex_t once_masterlock = PTHREAD_MUTEX_INITIALIZER;
1251
1252
sewardj5905fae2002-04-26 13:25:00 +00001253int __pthread_once ( pthread_once_t *once_control,
1254 void (*init_routine) (void) )
sewardj89d3d852002-04-24 19:21:39 +00001255{
1256 int res;
1257 ensure_valgrind("pthread_once");
1258
sewardj68b2dd92002-05-10 21:03:56 +00001259 res = __pthread_mutex_lock(&once_masterlock);
sewardj89d3d852002-04-24 19:21:39 +00001260
sewardj68b2dd92002-05-10 21:03:56 +00001261 if (res != 0) {
sewardj89d3d852002-04-24 19:21:39 +00001262 barf("pthread_once: Looks like your program's "
1263 "init routine calls back to pthread_once() ?!");
sewardj68b2dd92002-05-10 21:03:56 +00001264 }
sewardj89d3d852002-04-24 19:21:39 +00001265
1266 if (*once_control == 0) {
1267 *once_control = 1;
1268 init_routine();
1269 }
1270
sewardj68b2dd92002-05-10 21:03:56 +00001271 __pthread_mutex_unlock(&once_masterlock);
sewardj89d3d852002-04-24 19:21:39 +00001272
1273 return 0;
1274}
1275
1276
1277/* ---------------------------------------------------
sewardj853f55d2002-04-26 00:27:53 +00001278 MISC
1279 ------------------------------------------------ */
1280
sewardj2cb00342002-06-28 01:46:26 +00001281static pthread_mutex_t pthread_atfork_lock
1282 = PTHREAD_MUTEX_INITIALIZER;
1283
sewardj5905fae2002-04-26 13:25:00 +00001284int __pthread_atfork ( void (*prepare)(void),
1285 void (*parent)(void),
1286 void (*child)(void) )
sewardj853f55d2002-04-26 00:27:53 +00001287{
sewardj2cb00342002-06-28 01:46:26 +00001288 int n, res;
1289 ForkHandlerEntry entry;
1290
1291 ensure_valgrind("pthread_atfork");
1292 __pthread_mutex_lock(&pthread_atfork_lock);
1293
1294 /* Fetch old counter */
1295 VALGRIND_MAGIC_SEQUENCE(n, -2 /* default */,
1296 VG_USERREQ__GET_FHSTACK_USED,
1297 0, 0, 0, 0);
1298 my_assert(n >= 0 && n < VG_N_FORKHANDLERSTACK);
1299 if (n == VG_N_FORKHANDLERSTACK-1)
1300 barf("pthread_atfork: VG_N_FORKHANDLERSTACK is too low; "
1301 "increase and recompile");
1302
1303 /* Add entry */
1304 entry.prepare = *prepare;
1305 entry.parent = *parent;
1306 entry.child = *child;
1307 VALGRIND_MAGIC_SEQUENCE(res, -2 /* default */,
1308 VG_USERREQ__SET_FHSTACK_ENTRY,
1309 n, &entry, 0, 0);
1310 my_assert(res == 0);
1311
1312 /* Bump counter */
1313 VALGRIND_MAGIC_SEQUENCE(res, -2 /* default */,
1314 VG_USERREQ__SET_FHSTACK_USED,
1315 n+1, 0, 0, 0);
1316 my_assert(res == 0);
1317
1318 __pthread_mutex_unlock(&pthread_atfork_lock);
1319 return 0;
sewardj853f55d2002-04-26 00:27:53 +00001320}
1321
1322
sewardjbb990782002-05-08 02:01:14 +00001323__attribute__((weak))
1324void __pthread_initialize ( void )
1325{
sewardjbea1caa2002-05-10 23:20:58 +00001326 ensure_valgrind("__pthread_initialize");
sewardjbb990782002-05-08 02:01:14 +00001327}
1328
1329
sewardj853f55d2002-04-26 00:27:53 +00001330/* ---------------------------------------------------
sewardj3b13f0e2002-04-25 20:17:29 +00001331 LIBRARY-PRIVATE THREAD SPECIFIC STATE
sewardjf8f819e2002-04-17 23:21:37 +00001332 ------------------------------------------------ */
1333
sewardj3b13f0e2002-04-25 20:17:29 +00001334#include <resolv.h>
1335static int thread_specific_errno[VG_N_THREADS];
1336static int thread_specific_h_errno[VG_N_THREADS];
1337static struct __res_state
1338 thread_specific_res_state[VG_N_THREADS];
sewardjf8f819e2002-04-17 23:21:37 +00001339
sewardj3b13f0e2002-04-25 20:17:29 +00001340int* __errno_location ( void )
sewardjf8f819e2002-04-17 23:21:37 +00001341{
1342 int tid;
sewardj3b13f0e2002-04-25 20:17:29 +00001343 /* ensure_valgrind("__errno_location"); */
1344 VALGRIND_MAGIC_SEQUENCE(tid, 1 /* default */,
sewardjf8f819e2002-04-17 23:21:37 +00001345 VG_USERREQ__PTHREAD_GET_THREADID,
1346 0, 0, 0, 0);
sewardj3b13f0e2002-04-25 20:17:29 +00001347 /* 'cos I'm paranoid ... */
sewardj439d45e2002-05-03 20:43:10 +00001348 if (tid < 1 || tid >= VG_N_THREADS)
sewardj3b13f0e2002-04-25 20:17:29 +00001349 barf("__errno_location: invalid ThreadId");
1350 return & thread_specific_errno[tid];
1351}
1352
1353int* __h_errno_location ( void )
1354{
1355 int tid;
1356 /* ensure_valgrind("__h_errno_location"); */
1357 VALGRIND_MAGIC_SEQUENCE(tid, 1 /* default */,
1358 VG_USERREQ__PTHREAD_GET_THREADID,
1359 0, 0, 0, 0);
1360 /* 'cos I'm paranoid ... */
sewardj439d45e2002-05-03 20:43:10 +00001361 if (tid < 1 || tid >= VG_N_THREADS)
sewardj3b13f0e2002-04-25 20:17:29 +00001362 barf("__h_errno_location: invalid ThreadId");
1363 return & thread_specific_h_errno[tid];
1364}
1365
sewardjb0ff1032002-08-06 09:02:53 +00001366
1367#undef _res
1368extern struct __res_state _res;
1369
sewardj3b13f0e2002-04-25 20:17:29 +00001370struct __res_state* __res_state ( void )
1371{
1372 int tid;
1373 /* ensure_valgrind("__res_state"); */
1374 VALGRIND_MAGIC_SEQUENCE(tid, 1 /* default */,
1375 VG_USERREQ__PTHREAD_GET_THREADID,
1376 0, 0, 0, 0);
1377 /* 'cos I'm paranoid ... */
sewardj439d45e2002-05-03 20:43:10 +00001378 if (tid < 1 || tid >= VG_N_THREADS)
sewardj3b13f0e2002-04-25 20:17:29 +00001379 barf("__res_state: invalid ThreadId");
sewardjb0ff1032002-08-06 09:02:53 +00001380 if (tid == 1)
1381 return & _res;
sewardj3b13f0e2002-04-25 20:17:29 +00001382 return & thread_specific_res_state[tid];
sewardjf8f819e2002-04-17 23:21:37 +00001383}
1384
1385
sewardj5716dbb2002-04-26 03:28:18 +00001386/* ---------------------------------------------------
1387 LIBC-PRIVATE SPECIFIC DATA
1388 ------------------------------------------------ */
1389
1390/* Relies on assumption that initial private data is NULL. This
1391 should be fixed somehow. */
1392
njn25e49d8e72002-09-23 09:36:25 +00001393/* The allowable keys (indices) (all 3 of them).
sewardj5716dbb2002-04-26 03:28:18 +00001394 From sysdeps/pthread/bits/libc-tsd.h
1395*/
sewardjcb7f08a2002-10-02 09:41:49 +00001396/* as per glibc anoncvs HEAD of 20021001. */
sewardj5716dbb2002-04-26 03:28:18 +00001397enum __libc_tsd_key_t { _LIBC_TSD_KEY_MALLOC = 0,
1398 _LIBC_TSD_KEY_DL_ERROR,
njn25e49d8e72002-09-23 09:36:25 +00001399 _LIBC_TSD_KEY_RPC_VARS,
sewardjcb7f08a2002-10-02 09:41:49 +00001400 _LIBC_TSD_KEY_LOCALE,
1401 _LIBC_TSD_KEY_CTYPE_B,
1402 _LIBC_TSD_KEY_CTYPE_TOLOWER,
1403 _LIBC_TSD_KEY_CTYPE_TOUPPER,
sewardj5716dbb2002-04-26 03:28:18 +00001404 _LIBC_TSD_KEY_N };
1405
1406/* Auto-initialising subsystem. libc_specifics_inited is set
1407 after initialisation. libc_specifics_inited_mx guards it. */
1408static int libc_specifics_inited = 0;
1409static pthread_mutex_t libc_specifics_inited_mx = PTHREAD_MUTEX_INITIALIZER;
1410
1411/* These are the keys we must initialise the first time. */
sewardjcb7f08a2002-10-02 09:41:49 +00001412static pthread_key_t libc_specifics_keys[_LIBC_TSD_KEY_N];
sewardj5716dbb2002-04-26 03:28:18 +00001413
sewardjcb7f08a2002-10-02 09:41:49 +00001414/* Initialise the keys, if they are not already initialised. */
sewardj5716dbb2002-04-26 03:28:18 +00001415static
1416void init_libc_tsd_keys ( void )
1417{
1418 int res, i;
1419 pthread_key_t k;
1420
1421 res = pthread_mutex_lock(&libc_specifics_inited_mx);
1422 if (res != 0) barf("init_libc_tsd_keys: lock");
1423
1424 if (libc_specifics_inited == 0) {
1425 /* printf("INIT libc specifics\n"); */
1426 libc_specifics_inited = 1;
sewardjcb7f08a2002-10-02 09:41:49 +00001427 for (i = 0; i < _LIBC_TSD_KEY_N; i++) {
sewardj5716dbb2002-04-26 03:28:18 +00001428 res = pthread_key_create(&k, NULL);
1429 if (res != 0) barf("init_libc_tsd_keys: create");
1430 libc_specifics_keys[i] = k;
1431 }
1432 }
1433
1434 res = pthread_mutex_unlock(&libc_specifics_inited_mx);
1435 if (res != 0) barf("init_libc_tsd_keys: unlock");
1436}
1437
1438
1439static int
1440libc_internal_tsd_set ( enum __libc_tsd_key_t key,
1441 const void * pointer )
1442{
sewardjcb7f08a2002-10-02 09:41:49 +00001443 int res;
sewardj5716dbb2002-04-26 03:28:18 +00001444 /* printf("SET SET SET key %d ptr %p\n", key, pointer); */
sewardjcb7f08a2002-10-02 09:41:49 +00001445 if (key < _LIBC_TSD_KEY_MALLOC || key >= _LIBC_TSD_KEY_N)
sewardj5716dbb2002-04-26 03:28:18 +00001446 barf("libc_internal_tsd_set: invalid key");
1447 init_libc_tsd_keys();
1448 res = pthread_setspecific(libc_specifics_keys[key], pointer);
1449 if (res != 0) barf("libc_internal_tsd_set: setspecific failed");
1450 return 0;
1451}
1452
1453static void *
1454libc_internal_tsd_get ( enum __libc_tsd_key_t key )
1455{
sewardjcb7f08a2002-10-02 09:41:49 +00001456 void* v;
sewardj5716dbb2002-04-26 03:28:18 +00001457 /* printf("GET GET GET key %d\n", key); */
sewardjcb7f08a2002-10-02 09:41:49 +00001458 if (key < _LIBC_TSD_KEY_MALLOC || key >= _LIBC_TSD_KEY_N)
sewardj5716dbb2002-04-26 03:28:18 +00001459 barf("libc_internal_tsd_get: invalid key");
1460 init_libc_tsd_keys();
1461 v = pthread_getspecific(libc_specifics_keys[key]);
1462 /* if (v == NULL) barf("libc_internal_tsd_set: getspecific failed"); */
1463 return v;
1464}
1465
1466
1467
sewardj70adeb22002-04-27 01:35:38 +00001468int (*__libc_internal_tsd_set)
1469 (enum __libc_tsd_key_t key, const void * pointer)
1470 = libc_internal_tsd_set;
sewardj5716dbb2002-04-26 03:28:18 +00001471
sewardj70adeb22002-04-27 01:35:38 +00001472void* (*__libc_internal_tsd_get)
1473 (enum __libc_tsd_key_t key)
1474 = libc_internal_tsd_get;
sewardj5716dbb2002-04-26 03:28:18 +00001475
1476
sewardje663cb92002-04-12 10:26:32 +00001477/* ---------------------------------------------------------------------
1478 These are here (I think) because they are deemed cancellation
1479 points by POSIX. For the moment we'll simply pass the call along
1480 to the corresponding thread-unaware (?) libc routine.
1481 ------------------------------------------------------------------ */
1482
sewardje663cb92002-04-12 10:26:32 +00001483#include <stdlib.h>
sewardje663cb92002-04-12 10:26:32 +00001484#include <sys/types.h>
1485#include <sys/socket.h>
1486
sewardjd529a442002-05-04 19:49:21 +00001487#ifdef GLIBC_2_1
1488extern
1489int __sigaction
1490 (int signum,
1491 const struct sigaction *act,
1492 struct sigaction *oldact);
1493#else
sewardje663cb92002-04-12 10:26:32 +00001494extern
1495int __libc_sigaction
1496 (int signum,
1497 const struct sigaction *act,
1498 struct sigaction *oldact);
sewardjd529a442002-05-04 19:49:21 +00001499#endif
sewardje663cb92002-04-12 10:26:32 +00001500int sigaction(int signum,
1501 const struct sigaction *act,
1502 struct sigaction *oldact)
1503{
sewardjd140e442002-05-29 01:21:19 +00001504 __my_pthread_testcancel();
sewardj2a1dcce2002-04-22 12:45:25 +00001505# ifdef GLIBC_2_1
1506 return __sigaction(signum, act, oldact);
1507# else
sewardj45b4b372002-04-16 22:50:32 +00001508 return __libc_sigaction(signum, act, oldact);
sewardj2a1dcce2002-04-22 12:45:25 +00001509# endif
sewardje663cb92002-04-12 10:26:32 +00001510}
1511
1512
1513extern
1514int __libc_connect(int sockfd,
1515 const struct sockaddr *serv_addr,
1516 socklen_t addrlen);
sewardj5905fae2002-04-26 13:25:00 +00001517__attribute__((weak))
sewardje663cb92002-04-12 10:26:32 +00001518int connect(int sockfd,
1519 const struct sockaddr *serv_addr,
1520 socklen_t addrlen)
1521{
sewardjd140e442002-05-29 01:21:19 +00001522 __my_pthread_testcancel();
sewardj45b4b372002-04-16 22:50:32 +00001523 return __libc_connect(sockfd, serv_addr, addrlen);
sewardje663cb92002-04-12 10:26:32 +00001524}
1525
1526
1527extern
1528int __libc_fcntl(int fd, int cmd, long arg);
sewardj5905fae2002-04-26 13:25:00 +00001529__attribute__((weak))
sewardje663cb92002-04-12 10:26:32 +00001530int fcntl(int fd, int cmd, long arg)
1531{
sewardjd140e442002-05-29 01:21:19 +00001532 __my_pthread_testcancel();
sewardj45b4b372002-04-16 22:50:32 +00001533 return __libc_fcntl(fd, cmd, arg);
sewardje663cb92002-04-12 10:26:32 +00001534}
1535
1536
1537extern
1538ssize_t __libc_write(int fd, const void *buf, size_t count);
sewardj5905fae2002-04-26 13:25:00 +00001539__attribute__((weak))
sewardje663cb92002-04-12 10:26:32 +00001540ssize_t write(int fd, const void *buf, size_t count)
1541{
sewardjd140e442002-05-29 01:21:19 +00001542 __my_pthread_testcancel();
sewardj45b4b372002-04-16 22:50:32 +00001543 return __libc_write(fd, buf, count);
sewardje663cb92002-04-12 10:26:32 +00001544}
1545
1546
1547extern
1548ssize_t __libc_read(int fd, void *buf, size_t count);
sewardj5905fae2002-04-26 13:25:00 +00001549__attribute__((weak))
sewardje663cb92002-04-12 10:26:32 +00001550ssize_t read(int fd, void *buf, size_t count)
1551{
sewardjd140e442002-05-29 01:21:19 +00001552 __my_pthread_testcancel();
sewardj45b4b372002-04-16 22:50:32 +00001553 return __libc_read(fd, buf, count);
sewardje663cb92002-04-12 10:26:32 +00001554}
1555
sewardjbe32e452002-04-24 20:29:58 +00001556
1557extern
sewardj853f55d2002-04-26 00:27:53 +00001558int __libc_open64(const char *pathname, int flags, mode_t mode);
sewardj5905fae2002-04-26 13:25:00 +00001559__attribute__((weak))
sewardj853f55d2002-04-26 00:27:53 +00001560int open64(const char *pathname, int flags, mode_t mode)
sewardjbe32e452002-04-24 20:29:58 +00001561{
sewardjd140e442002-05-29 01:21:19 +00001562 __my_pthread_testcancel();
sewardj853f55d2002-04-26 00:27:53 +00001563 return __libc_open64(pathname, flags, mode);
sewardjbe32e452002-04-24 20:29:58 +00001564}
1565
sewardje663cb92002-04-12 10:26:32 +00001566
1567extern
sewardj853f55d2002-04-26 00:27:53 +00001568int __libc_open(const char *pathname, int flags, mode_t mode);
sewardj5905fae2002-04-26 13:25:00 +00001569__attribute__((weak))
sewardj853f55d2002-04-26 00:27:53 +00001570int open(const char *pathname, int flags, mode_t mode)
sewardje663cb92002-04-12 10:26:32 +00001571{
sewardjd140e442002-05-29 01:21:19 +00001572 __my_pthread_testcancel();
sewardj853f55d2002-04-26 00:27:53 +00001573 return __libc_open(pathname, flags, mode);
sewardje663cb92002-04-12 10:26:32 +00001574}
1575
1576
1577extern
1578int __libc_close(int fd);
sewardj5905fae2002-04-26 13:25:00 +00001579__attribute__((weak))
sewardje663cb92002-04-12 10:26:32 +00001580int close(int fd)
1581{
sewardjd140e442002-05-29 01:21:19 +00001582 __my_pthread_testcancel();
sewardj45b4b372002-04-16 22:50:32 +00001583 return __libc_close(fd);
sewardje663cb92002-04-12 10:26:32 +00001584}
1585
1586
1587extern
1588int __libc_accept(int s, struct sockaddr *addr, socklen_t *addrlen);
sewardj5905fae2002-04-26 13:25:00 +00001589__attribute__((weak))
sewardje663cb92002-04-12 10:26:32 +00001590int accept(int s, struct sockaddr *addr, socklen_t *addrlen)
1591{
sewardjd140e442002-05-29 01:21:19 +00001592 __my_pthread_testcancel();
sewardj705d3cb2002-05-23 13:13:12 +00001593 wait_for_fd_to_be_readable_or_erring(s);
sewardjd140e442002-05-29 01:21:19 +00001594 __my_pthread_testcancel();
sewardj45b4b372002-04-16 22:50:32 +00001595 return __libc_accept(s, addr, addrlen);
sewardje663cb92002-04-12 10:26:32 +00001596}
1597
1598
1599extern
sewardje663cb92002-04-12 10:26:32 +00001600pid_t __libc_waitpid(pid_t pid, int *status, int options);
sewardj5905fae2002-04-26 13:25:00 +00001601__attribute__((weak))
sewardje663cb92002-04-12 10:26:32 +00001602pid_t waitpid(pid_t pid, int *status, int options)
1603{
sewardjd140e442002-05-29 01:21:19 +00001604 __my_pthread_testcancel();
sewardj45b4b372002-04-16 22:50:32 +00001605 return __libc_waitpid(pid, status, options);
sewardje663cb92002-04-12 10:26:32 +00001606}
1607
1608
1609extern
1610int __libc_nanosleep(const struct timespec *req, struct timespec *rem);
sewardj5905fae2002-04-26 13:25:00 +00001611__attribute__((weak))
sewardje663cb92002-04-12 10:26:32 +00001612int nanosleep(const struct timespec *req, struct timespec *rem)
1613{
sewardjd140e442002-05-29 01:21:19 +00001614 __my_pthread_testcancel();
sewardje663cb92002-04-12 10:26:32 +00001615 return __libc_nanosleep(req, rem);
1616}
1617
sewardjbe32e452002-04-24 20:29:58 +00001618
sewardje663cb92002-04-12 10:26:32 +00001619extern
1620int __libc_fsync(int fd);
sewardj5905fae2002-04-26 13:25:00 +00001621__attribute__((weak))
sewardje663cb92002-04-12 10:26:32 +00001622int fsync(int fd)
1623{
sewardjd140e442002-05-29 01:21:19 +00001624 __my_pthread_testcancel();
sewardj45b4b372002-04-16 22:50:32 +00001625 return __libc_fsync(fd);
sewardje663cb92002-04-12 10:26:32 +00001626}
1627
sewardjbe32e452002-04-24 20:29:58 +00001628
sewardj70c75362002-04-13 04:18:32 +00001629extern
1630off_t __libc_lseek(int fildes, off_t offset, int whence);
sewardj5905fae2002-04-26 13:25:00 +00001631__attribute__((weak))
sewardj70c75362002-04-13 04:18:32 +00001632off_t lseek(int fildes, off_t offset, int whence)
1633{
sewardjd140e442002-05-29 01:21:19 +00001634 __my_pthread_testcancel();
sewardj45b4b372002-04-16 22:50:32 +00001635 return __libc_lseek(fildes, offset, whence);
sewardj70c75362002-04-13 04:18:32 +00001636}
1637
sewardjbe32e452002-04-24 20:29:58 +00001638
1639extern
1640__off64_t __libc_lseek64(int fildes, __off64_t offset, int whence);
sewardj5905fae2002-04-26 13:25:00 +00001641__attribute__((weak))
sewardjbe32e452002-04-24 20:29:58 +00001642__off64_t lseek64(int fildes, __off64_t offset, int whence)
1643{
sewardjd140e442002-05-29 01:21:19 +00001644 __my_pthread_testcancel();
sewardjbe32e452002-04-24 20:29:58 +00001645 return __libc_lseek64(fildes, offset, whence);
1646}
1647
1648
sewardj726c4122002-05-16 23:39:10 +00001649extern
1650ssize_t __libc_pread64 (int __fd, void *__buf, size_t __nbytes,
1651 __off64_t __offset);
1652ssize_t __pread64 (int __fd, void *__buf, size_t __nbytes,
1653 __off64_t __offset)
1654{
sewardjd140e442002-05-29 01:21:19 +00001655 __my_pthread_testcancel();
sewardj726c4122002-05-16 23:39:10 +00001656 return __libc_pread64(__fd, __buf, __nbytes, __offset);
1657}
1658
1659
sewardja18e2102002-05-18 10:43:22 +00001660extern
1661ssize_t __libc_pwrite64 (int __fd, const void *__buf, size_t __nbytes,
1662 __off64_t __offset);
1663ssize_t __pwrite64 (int __fd, const void *__buf, size_t __nbytes,
1664 __off64_t __offset)
1665{
sewardjd140e442002-05-29 01:21:19 +00001666 __my_pthread_testcancel();
sewardja18e2102002-05-18 10:43:22 +00001667 return __libc_pwrite64(__fd, __buf, __nbytes, __offset);
1668}
1669
sewardj726c4122002-05-16 23:39:10 +00001670
sewardj39b93b12002-05-18 10:56:27 +00001671extern
1672ssize_t __libc_pwrite(int fd, const void *buf, size_t count, off_t offset);
1673__attribute__((weak))
1674ssize_t pwrite(int fd, const void *buf, size_t count, off_t offset)
1675{
sewardjd140e442002-05-29 01:21:19 +00001676 __my_pthread_testcancel();
sewardj39b93b12002-05-18 10:56:27 +00001677 return __libc_pwrite(fd, buf, count, offset);
1678}
1679
1680
1681extern
1682ssize_t __libc_pread(int fd, void *buf, size_t count, off_t offset);
1683__attribute__((weak))
1684ssize_t pread(int fd, void *buf, size_t count, off_t offset)
1685{
sewardjd140e442002-05-29 01:21:19 +00001686 __my_pthread_testcancel();
sewardj39b93b12002-05-18 10:56:27 +00001687 return __libc_pread(fd, buf, count, offset);
1688}
1689
1690
sewardj6af4b5d2002-04-16 04:40:49 +00001691extern
1692void __libc_longjmp(jmp_buf env, int val) __attribute((noreturn));
sewardj5905fae2002-04-26 13:25:00 +00001693/* not weak: __attribute__((weak)) */
sewardj6af4b5d2002-04-16 04:40:49 +00001694void longjmp(jmp_buf env, int val)
1695{
1696 __libc_longjmp(env, val);
1697}
1698
sewardjbe32e452002-04-24 20:29:58 +00001699
sewardj436c2db2002-06-18 09:07:54 +00001700extern void __libc_siglongjmp (sigjmp_buf env, int val)
1701 __attribute__ ((noreturn));
1702void siglongjmp(sigjmp_buf env, int val)
1703{
1704 kludged("siglongjmp (cleanup handlers are ignored)");
1705 __libc_siglongjmp(env, val);
1706}
1707
1708
sewardj6af4b5d2002-04-16 04:40:49 +00001709extern
1710int __libc_send(int s, const void *msg, size_t len, int flags);
sewardj5905fae2002-04-26 13:25:00 +00001711__attribute__((weak))
sewardj6af4b5d2002-04-16 04:40:49 +00001712int send(int s, const void *msg, size_t len, int flags)
1713{
sewardjd140e442002-05-29 01:21:19 +00001714 __my_pthread_testcancel();
sewardj6af4b5d2002-04-16 04:40:49 +00001715 return __libc_send(s, msg, len, flags);
1716}
1717
sewardjbe32e452002-04-24 20:29:58 +00001718
sewardj1e8cdc92002-04-18 11:37:52 +00001719extern
1720int __libc_recv(int s, void *buf, size_t len, int flags);
sewardj5905fae2002-04-26 13:25:00 +00001721__attribute__((weak))
sewardj1e8cdc92002-04-18 11:37:52 +00001722int recv(int s, void *buf, size_t len, int flags)
1723{
sewardjd140e442002-05-29 01:21:19 +00001724 __my_pthread_testcancel();
sewardj1d6b3a22002-06-20 07:58:33 +00001725 wait_for_fd_to_be_readable_or_erring(s);
1726 __my_pthread_testcancel();
sewardj1e8cdc92002-04-18 11:37:52 +00001727 return __libc_recv(s, buf, len, flags);
1728}
1729
sewardjbe32e452002-04-24 20:29:58 +00001730
sewardj3665ded2002-05-16 16:57:25 +00001731extern
1732int __libc_sendmsg(int s, const struct msghdr *msg, int flags);
1733__attribute__((weak))
1734int sendmsg(int s, const struct msghdr *msg, int flags)
1735{
sewardjd140e442002-05-29 01:21:19 +00001736 __my_pthread_testcancel();
sewardj3665ded2002-05-16 16:57:25 +00001737 return __libc_sendmsg(s, msg, flags);
1738}
1739
1740
sewardj796d6a22002-04-24 02:28:34 +00001741extern
sewardj59da27a2002-06-06 08:33:54 +00001742int __libc_recvmsg(int s, struct msghdr *msg, int flags);
1743__attribute__((weak))
1744int recvmsg(int s, struct msghdr *msg, int flags)
1745{
1746 __my_pthread_testcancel();
1747 return __libc_recvmsg(s, msg, flags);
1748}
1749
1750
1751extern
sewardj436e0582002-04-26 14:31:40 +00001752int __libc_recvfrom(int s, void *buf, size_t len, int flags,
1753 struct sockaddr *from, socklen_t *fromlen);
1754__attribute__((weak))
1755int recvfrom(int s, void *buf, size_t len, int flags,
1756 struct sockaddr *from, socklen_t *fromlen)
1757{
sewardjd140e442002-05-29 01:21:19 +00001758 __my_pthread_testcancel();
sewardj2e207632002-06-13 17:29:53 +00001759 wait_for_fd_to_be_readable_or_erring(s);
1760 __my_pthread_testcancel();
sewardj436e0582002-04-26 14:31:40 +00001761 return __libc_recvfrom(s, buf, len, flags, from, fromlen);
1762}
1763
1764
1765extern
sewardj796d6a22002-04-24 02:28:34 +00001766int __libc_sendto(int s, const void *msg, size_t len, int flags,
1767 const struct sockaddr *to, socklen_t tolen);
sewardj5905fae2002-04-26 13:25:00 +00001768__attribute__((weak))
sewardj796d6a22002-04-24 02:28:34 +00001769int sendto(int s, const void *msg, size_t len, int flags,
1770 const struct sockaddr *to, socklen_t tolen)
1771{
sewardjd140e442002-05-29 01:21:19 +00001772 __my_pthread_testcancel();
sewardj796d6a22002-04-24 02:28:34 +00001773 return __libc_sendto(s, msg, len, flags, to, tolen);
1774}
1775
sewardjbe32e452002-04-24 20:29:58 +00001776
sewardj369b1702002-04-24 13:28:15 +00001777extern
1778int __libc_system(const char* str);
sewardj5905fae2002-04-26 13:25:00 +00001779__attribute__((weak))
sewardj369b1702002-04-24 13:28:15 +00001780int system(const char* str)
1781{
sewardjd140e442002-05-29 01:21:19 +00001782 __my_pthread_testcancel();
sewardj369b1702002-04-24 13:28:15 +00001783 return __libc_system(str);
1784}
1785
sewardjbe32e452002-04-24 20:29:58 +00001786
sewardjab0b1c32002-04-24 19:26:47 +00001787extern
1788pid_t __libc_wait(int *status);
sewardj5905fae2002-04-26 13:25:00 +00001789__attribute__((weak))
sewardjab0b1c32002-04-24 19:26:47 +00001790pid_t wait(int *status)
1791{
sewardjd140e442002-05-29 01:21:19 +00001792 __my_pthread_testcancel();
sewardjab0b1c32002-04-24 19:26:47 +00001793 return __libc_wait(status);
1794}
1795
sewardj45b4b372002-04-16 22:50:32 +00001796
sewardj67f1d582002-05-24 02:11:32 +00001797extern
1798int __libc_msync(const void *start, size_t length, int flags);
1799__attribute__((weak))
1800int msync(const void *start, size_t length, int flags)
1801{
sewardjd140e442002-05-29 01:21:19 +00001802 __my_pthread_testcancel();
sewardj67f1d582002-05-24 02:11:32 +00001803 return __libc_msync(start, length, flags);
1804}
1805
sewardj5905fae2002-04-26 13:25:00 +00001806
sewardj2cb00342002-06-28 01:46:26 +00001807/*--- fork and its helper ---*/
1808
1809static
1810void run_fork_handlers ( int what )
1811{
1812 ForkHandlerEntry entry;
1813 int n_h, n_handlers, i, res;
1814
1815 my_assert(what == 0 || what == 1 || what == 2);
1816
1817 /* Fetch old counter */
1818 VALGRIND_MAGIC_SEQUENCE(n_handlers, -2 /* default */,
1819 VG_USERREQ__GET_FHSTACK_USED,
1820 0, 0, 0, 0);
1821 my_assert(n_handlers >= 0 && n_handlers < VG_N_FORKHANDLERSTACK);
1822
1823 /* Prepare handlers (what == 0) are called in opposite order of
1824 calls to pthread_atfork. Parent and child handlers are called
1825 in the same order as calls to pthread_atfork. */
1826 if (what == 0)
1827 n_h = n_handlers - 1;
1828 else
1829 n_h = 0;
1830
1831 for (i = 0; i < n_handlers; i++) {
1832 VALGRIND_MAGIC_SEQUENCE(res, -2 /* default */,
1833 VG_USERREQ__GET_FHSTACK_ENTRY,
1834 n_h, &entry, 0, 0);
1835 my_assert(res == 0);
1836 switch (what) {
1837 case 0: if (entry.prepare) entry.prepare();
1838 n_h--; break;
1839 case 1: if (entry.parent) entry.parent();
1840 n_h++; break;
1841 case 2: if (entry.child) entry.child();
1842 n_h++; break;
1843 default: barf("run_fork_handlers: invalid what");
1844 }
1845 }
1846
1847 if (what != 0 /* prepare */) {
1848 /* Empty out the stack. */
1849 VALGRIND_MAGIC_SEQUENCE(res, -2 /* default */,
1850 VG_USERREQ__SET_FHSTACK_USED,
1851 0, 0, 0, 0);
1852 my_assert(res == 0);
1853 }
1854}
1855
1856extern
1857pid_t __libc_fork(void);
1858pid_t __fork(void)
1859{
1860 pid_t pid;
1861 __my_pthread_testcancel();
1862 __pthread_mutex_lock(&pthread_atfork_lock);
1863
1864 run_fork_handlers(0 /* prepare */);
1865 pid = __libc_fork();
1866 if (pid == 0) {
1867 /* I am the child */
1868 run_fork_handlers(2 /* child */);
1869 __pthread_mutex_init(&pthread_atfork_lock, NULL);
1870 } else {
1871 /* I am the parent */
1872 run_fork_handlers(1 /* parent */);
1873 __pthread_mutex_unlock(&pthread_atfork_lock);
1874 }
1875 return pid;
1876}
1877
1878
njn25e49d8e72002-09-23 09:36:25 +00001879pid_t __vfork(void)
1880{
1881 return __fork();
1882}
sewardj2cb00342002-06-28 01:46:26 +00001883
1884
sewardj3b13f0e2002-04-25 20:17:29 +00001885/* ---------------------------------------------------------------------
1886 Nonblocking implementations of select() and poll(). This stuff will
1887 surely rot your mind.
1888 ------------------------------------------------------------------ */
sewardje663cb92002-04-12 10:26:32 +00001889
sewardj08a4c3f2002-04-13 03:45:44 +00001890/*--------------------------------------------------*/
1891
1892#include "vg_kerneliface.h"
1893
1894static
1895__inline__
1896int is_kerror ( int res )
1897{
1898 if (res >= -4095 && res <= -1)
1899 return 1;
1900 else
1901 return 0;
1902}
1903
1904
1905static
1906int my_do_syscall1 ( int syscallno, int arg1 )
1907{
1908 int __res;
1909 __asm__ volatile ("pushl %%ebx; movl %%edx,%%ebx ; int $0x80 ; popl %%ebx"
1910 : "=a" (__res)
1911 : "0" (syscallno),
1912 "d" (arg1) );
1913 return __res;
1914}
1915
1916static
1917int my_do_syscall2 ( int syscallno,
sewardjf854f472002-04-21 12:19:41 +00001918 int arg1, int arg2 )
sewardj08a4c3f2002-04-13 03:45:44 +00001919{
1920 int __res;
1921 __asm__ volatile ("pushl %%ebx; movl %%edx,%%ebx ; int $0x80 ; popl %%ebx"
1922 : "=a" (__res)
1923 : "0" (syscallno),
1924 "d" (arg1),
1925 "c" (arg2) );
1926 return __res;
1927}
1928
1929static
sewardjf854f472002-04-21 12:19:41 +00001930int my_do_syscall3 ( int syscallno,
1931 int arg1, int arg2, int arg3 )
1932{
1933 int __res;
1934 __asm__ volatile ("pushl %%ebx; movl %%esi,%%ebx ; int $0x80 ; popl %%ebx"
1935 : "=a" (__res)
1936 : "0" (syscallno),
1937 "S" (arg1),
1938 "c" (arg2),
1939 "d" (arg3) );
1940 return __res;
1941}
1942
1943static
sewardj08a4c3f2002-04-13 03:45:44 +00001944int do_syscall_select( int n,
1945 vki_fd_set* readfds,
1946 vki_fd_set* writefds,
1947 vki_fd_set* exceptfds,
1948 struct vki_timeval * timeout )
1949{
1950 int res;
1951 int args[5];
1952 args[0] = n;
1953 args[1] = (int)readfds;
1954 args[2] = (int)writefds;
1955 args[3] = (int)exceptfds;
1956 args[4] = (int)timeout;
1957 res = my_do_syscall1(__NR_select, (int)(&(args[0])) );
sewardj02535bc2002-04-21 01:08:26 +00001958 return res;
sewardj08a4c3f2002-04-13 03:45:44 +00001959}
1960
1961
1962/* This is a wrapper round select(), which makes it thread-safe,
1963 meaning that only this thread will block, rather than the entire
1964 process. This wrapper in turn depends on nanosleep() not to block
1965 the entire process, but I think (hope? suspect?) that POSIX
1966 pthreads guarantees that to be the case.
1967
1968 Basic idea is: modify the timeout parameter to select so that it
1969 returns immediately. Poll like this until select returns non-zero,
1970 indicating something interesting happened, or until our time is up.
njn25e49d8e72002-09-23 09:36:25 +00001971 Space out the polls with nanosleeps of say 11 milliseconds, which
sewardj08a4c3f2002-04-13 03:45:44 +00001972 is required to be nonblocking; this allows other threads to run.
sewardj02535bc2002-04-21 01:08:26 +00001973
1974 Assumes:
sewardj2d94c112002-06-03 01:25:54 +00001975 * (checked via my_assert) types fd_set and vki_fd_set are identical.
1976 * (checked via my_assert) types timeval and vki_timeval are identical.
sewardj02535bc2002-04-21 01:08:26 +00001977 * (unchecked) libc error numbers (EINTR etc) are the negation of the
1978 kernel's error numbers (VKI_EINTR etc).
sewardj08a4c3f2002-04-13 03:45:44 +00001979*/
sewardj08a4c3f2002-04-13 03:45:44 +00001980
sewardj5905fae2002-04-26 13:25:00 +00001981/* __attribute__((weak)) */
sewardj08a4c3f2002-04-13 03:45:44 +00001982int select ( int n,
1983 fd_set *rfds,
1984 fd_set *wfds,
1985 fd_set *xfds,
1986 struct timeval *timeout )
1987{
sewardj5f07b662002-04-23 16:52:51 +00001988 unsigned int ms_now, ms_end;
sewardj08a4c3f2002-04-13 03:45:44 +00001989 int res;
1990 fd_set rfds_copy;
1991 fd_set wfds_copy;
1992 fd_set xfds_copy;
1993 struct vki_timeval t_now;
sewardj08a4c3f2002-04-13 03:45:44 +00001994 struct vki_timeval zero_timeout;
1995 struct vki_timespec nanosleep_interval;
1996
sewardjd140e442002-05-29 01:21:19 +00001997 __my_pthread_testcancel();
1998
sewardj5f07b662002-04-23 16:52:51 +00001999 /* gcc's complains about ms_end being used uninitialised -- classic
2000 case it can't understand, where ms_end is both defined and used
2001 only if timeout != NULL. Hence ... */
2002 ms_end = 0;
sewardj08a4c3f2002-04-13 03:45:44 +00002003
2004 /* We assume that the kernel and libc data layouts are identical
2005 for the following types. These asserts provide a crude
2006 check. */
2007 if (sizeof(fd_set) != sizeof(vki_fd_set)
2008 || sizeof(struct timeval) != sizeof(struct vki_timeval))
2009 barf("valgrind's hacky non-blocking select(): data sizes error");
2010
sewardj5f07b662002-04-23 16:52:51 +00002011 /* Detect the current time and simultaneously find out if we are
2012 running on Valgrind. */
2013 VALGRIND_MAGIC_SEQUENCE(ms_now, 0xFFFFFFFF /* default */,
2014 VG_USERREQ__READ_MILLISECOND_TIMER,
2015 0, 0, 0, 0);
2016
2017 /* If a zero timeout specified, this call is harmless. Also go
2018 this route if we're not running on Valgrind, for whatever
2019 reason. */
2020 if ( (timeout && timeout->tv_sec == 0 && timeout->tv_usec == 0)
2021 || (ms_now == 0xFFFFFFFF) ) {
sewardj02535bc2002-04-21 01:08:26 +00002022 res = do_syscall_select( n, (vki_fd_set*)rfds,
sewardj08a4c3f2002-04-13 03:45:44 +00002023 (vki_fd_set*)wfds,
2024 (vki_fd_set*)xfds,
2025 (struct vki_timeval*)timeout);
sewardj02535bc2002-04-21 01:08:26 +00002026 if (is_kerror(res)) {
2027 * (__errno_location()) = -res;
2028 return -1;
2029 } else {
2030 return res;
2031 }
2032 }
sewardj08a4c3f2002-04-13 03:45:44 +00002033
sewardj5f07b662002-04-23 16:52:51 +00002034 /* If a timeout was specified, set ms_end to be the end millisecond
2035 counter [wallclock] time. */
sewardj08a4c3f2002-04-13 03:45:44 +00002036 if (timeout) {
2037 res = my_do_syscall2(__NR_gettimeofday, (int)&t_now, (int)NULL);
sewardj2d94c112002-06-03 01:25:54 +00002038 my_assert(res == 0);
sewardj5f07b662002-04-23 16:52:51 +00002039 ms_end = ms_now;
2040 ms_end += (timeout->tv_usec / 1000);
2041 ms_end += (timeout->tv_sec * 1000);
sewardj08a4c3f2002-04-13 03:45:44 +00002042 /* Stay sane ... */
sewardj2d94c112002-06-03 01:25:54 +00002043 my_assert (ms_end >= ms_now);
sewardj08a4c3f2002-04-13 03:45:44 +00002044 }
2045
2046 /* fprintf(stderr, "MY_SELECT: before loop\n"); */
2047
2048 /* Either timeout == NULL, meaning wait indefinitely, or timeout !=
sewardj5f07b662002-04-23 16:52:51 +00002049 NULL, in which case ms_end holds the end time. */
sewardj05bb2c92002-06-26 00:47:17 +00002050
sewardj08a4c3f2002-04-13 03:45:44 +00002051 while (1) {
sewardj05bb2c92002-06-26 00:47:17 +00002052
2053 /* First, do a return-immediately select(). */
sewardj08a4c3f2002-04-13 03:45:44 +00002054
2055 /* These could be trashed each time round the loop, so restore
2056 them each time. */
2057 if (rfds) rfds_copy = *rfds;
2058 if (wfds) wfds_copy = *wfds;
2059 if (xfds) xfds_copy = *xfds;
2060
2061 zero_timeout.tv_sec = zero_timeout.tv_usec = 0;
2062
2063 res = do_syscall_select( n,
2064 rfds ? (vki_fd_set*)(&rfds_copy) : NULL,
2065 wfds ? (vki_fd_set*)(&wfds_copy) : NULL,
2066 xfds ? (vki_fd_set*)(&xfds_copy) : NULL,
2067 & zero_timeout );
sewardj02535bc2002-04-21 01:08:26 +00002068 if (is_kerror(res)) {
2069 /* Some kind of error (including EINTR). Set errno and
sewardj08a4c3f2002-04-13 03:45:44 +00002070 return. The sets are unspecified in this case. */
sewardj02535bc2002-04-21 01:08:26 +00002071 * (__errno_location()) = -res;
2072 return -1;
sewardj08a4c3f2002-04-13 03:45:44 +00002073 }
2074 if (res > 0) {
2075 /* one or more fds is ready. Copy out resulting sets and
2076 return. */
2077 if (rfds) *rfds = rfds_copy;
2078 if (wfds) *wfds = wfds_copy;
2079 if (xfds) *xfds = xfds_copy;
2080 return res;
2081 }
sewardj05bb2c92002-06-26 00:47:17 +00002082
2083 /* Nothing interesting happened, so we go to sleep for a
2084 while. */
2085
sewardj08a4c3f2002-04-13 03:45:44 +00002086 /* fprintf(stderr, "MY_SELECT: nanosleep\n"); */
2087 /* nanosleep and go round again */
sewardj02535bc2002-04-21 01:08:26 +00002088 nanosleep_interval.tv_sec = 0;
njn25e49d8e72002-09-23 09:36:25 +00002089 nanosleep_interval.tv_nsec = 11 * 1000 * 1000; /* 11 milliseconds */
sewardjf854f472002-04-21 12:19:41 +00002090 /* It's critical here that valgrind's nanosleep implementation
2091 is nonblocking. */
sewardj645030e2002-06-06 01:27:39 +00002092 res = my_do_syscall2(__NR_nanosleep,
sewardjf854f472002-04-21 12:19:41 +00002093 (int)(&nanosleep_interval), (int)NULL);
sewardj645030e2002-06-06 01:27:39 +00002094 if (res == -VKI_EINTR) {
2095 /* The nanosleep was interrupted by a signal. So we do the
2096 same. */
2097 * (__errno_location()) = EINTR;
2098 return -1;
2099 }
sewardj05bb2c92002-06-26 00:47:17 +00002100
2101 /* Sleeping finished. If a finite timeout, check to see if it
2102 has expired yet. */
2103 if (timeout) {
2104 VALGRIND_MAGIC_SEQUENCE(ms_now, 0xFFFFFFFF /* default */,
2105 VG_USERREQ__READ_MILLISECOND_TIMER,
2106 0, 0, 0, 0);
2107 my_assert(ms_now != 0xFFFFFFFF);
2108 if (ms_now >= ms_end) {
2109 /* timeout; nothing interesting happened. */
2110 if (rfds) FD_ZERO(rfds);
2111 if (wfds) FD_ZERO(wfds);
2112 if (xfds) FD_ZERO(xfds);
2113 return 0;
2114 }
2115 }
2116
sewardjf854f472002-04-21 12:19:41 +00002117 }
2118}
2119
2120
2121
2122
2123#include <sys/poll.h>
2124
sewardj3e909ce2002-06-03 13:27:15 +00002125#ifndef HAVE_NFDS_T
sewardj72d58482002-04-24 02:20:20 +00002126typedef unsigned long int nfds_t;
2127#endif
2128
sewardj705d3cb2002-05-23 13:13:12 +00002129
sewardj5905fae2002-04-26 13:25:00 +00002130/* __attribute__((weak)) */
sewardjf854f472002-04-21 12:19:41 +00002131int poll (struct pollfd *__fds, nfds_t __nfds, int __timeout)
2132{
sewardj5f07b662002-04-23 16:52:51 +00002133 unsigned int ms_now, ms_end;
sewardjf854f472002-04-21 12:19:41 +00002134 int res, i;
sewardjf854f472002-04-21 12:19:41 +00002135 struct vki_timespec nanosleep_interval;
2136
sewardjd140e442002-05-29 01:21:19 +00002137 __my_pthread_testcancel();
sewardjf854f472002-04-21 12:19:41 +00002138 ensure_valgrind("poll");
2139
sewardj5f07b662002-04-23 16:52:51 +00002140 /* Detect the current time and simultaneously find out if we are
2141 running on Valgrind. */
2142 VALGRIND_MAGIC_SEQUENCE(ms_now, 0xFFFFFFFF /* default */,
2143 VG_USERREQ__READ_MILLISECOND_TIMER,
2144 0, 0, 0, 0);
2145
sewardjf854f472002-04-21 12:19:41 +00002146 if (/* CHECK SIZES FOR struct pollfd */
2147 sizeof(struct timeval) != sizeof(struct vki_timeval))
2148 barf("valgrind's hacky non-blocking poll(): data sizes error");
2149
sewardj5f07b662002-04-23 16:52:51 +00002150 /* dummy initialisation to keep gcc -Wall happy */
2151 ms_end = 0;
2152
2153 /* If a zero timeout specified, this call is harmless. Also do
2154 this if not running on Valgrind. */
2155 if (__timeout == 0 || ms_now == 0xFFFFFFFF) {
sewardjf854f472002-04-21 12:19:41 +00002156 res = my_do_syscall3(__NR_poll, (int)__fds, __nfds, __timeout);
2157 if (is_kerror(res)) {
2158 * (__errno_location()) = -res;
2159 return -1;
2160 } else {
2161 return res;
2162 }
2163 }
2164
sewardj5f07b662002-04-23 16:52:51 +00002165 /* If a timeout was specified, set ms_end to be the end wallclock
2166 time. Easy considering that __timeout is in milliseconds. */
sewardjf854f472002-04-21 12:19:41 +00002167 if (__timeout > 0) {
sewardj650ac002002-04-29 12:20:34 +00002168 ms_end = ms_now + (unsigned int)__timeout;
sewardjf854f472002-04-21 12:19:41 +00002169 }
2170
2171 /* fprintf(stderr, "MY_POLL: before loop\n"); */
2172
2173 /* Either timeout < 0, meaning wait indefinitely, or timeout > 0,
2174 in which case t_end holds the end time. */
sewardj05bb2c92002-06-26 00:47:17 +00002175
sewardj2d94c112002-06-03 01:25:54 +00002176 my_assert(__timeout != 0);
sewardj5f07b662002-04-23 16:52:51 +00002177
sewardjf854f472002-04-21 12:19:41 +00002178 while (1) {
sewardj05bb2c92002-06-26 00:47:17 +00002179
2180 /* Do a return-immediately poll. */
2181
2182 res = my_do_syscall3(__NR_poll, (int)__fds, __nfds, 0 );
2183 if (is_kerror(res)) {
2184 /* Some kind of error. Set errno and return. */
2185 * (__errno_location()) = -res;
2186 return -1;
2187 }
2188 if (res > 0) {
2189 /* One or more fds is ready. Return now. */
2190 return res;
2191 }
2192
2193 /* Nothing interesting happened, so we go to sleep for a
2194 while. */
2195
2196 /* fprintf(stderr, "MY_POLL: nanosleep\n"); */
2197 /* nanosleep and go round again */
2198 nanosleep_interval.tv_sec = 0;
njn25e49d8e72002-09-23 09:36:25 +00002199 nanosleep_interval.tv_nsec = 13 * 1000 * 1000; /* 13 milliseconds */
sewardj05bb2c92002-06-26 00:47:17 +00002200 /* It's critical here that valgrind's nanosleep implementation
2201 is nonblocking. */
2202 (void)my_do_syscall2(__NR_nanosleep,
2203 (int)(&nanosleep_interval), (int)NULL);
2204
2205 /* Sleeping finished. If a finite timeout, check to see if it
2206 has expired yet. */
sewardjf854f472002-04-21 12:19:41 +00002207 if (__timeout > 0) {
sewardj5f07b662002-04-23 16:52:51 +00002208 VALGRIND_MAGIC_SEQUENCE(ms_now, 0xFFFFFFFF /* default */,
2209 VG_USERREQ__READ_MILLISECOND_TIMER,
2210 0, 0, 0, 0);
sewardj2d94c112002-06-03 01:25:54 +00002211 my_assert(ms_now != 0xFFFFFFFF);
sewardj5f07b662002-04-23 16:52:51 +00002212 if (ms_now >= ms_end) {
sewardjf854f472002-04-21 12:19:41 +00002213 /* timeout; nothing interesting happened. */
2214 for (i = 0; i < __nfds; i++)
2215 __fds[i].revents = 0;
2216 return 0;
2217 }
2218 }
2219
sewardj08a4c3f2002-04-13 03:45:44 +00002220 }
2221}
sewardj3b13f0e2002-04-25 20:17:29 +00002222
2223
sewardj705d3cb2002-05-23 13:13:12 +00002224/* Helper function used to make accept() non-blocking. Idea is to use
2225 the above nonblocking poll() to make this thread ONLY wait for the
2226 specified fd to become ready, and then return. */
sewardjd1c1cf22002-06-26 00:13:36 +00002227
2228/* Sigh -- a hack. We're not supposed to include this file directly;
2229 should do it via /usr/include/fcntl.h, but that introduces a
2230 varargs prototype for fcntl itself, which we can't mimic. */
2231#define _FCNTL_H
2232#include <bits/fcntl.h>
2233
sewardj705d3cb2002-05-23 13:13:12 +00002234static void wait_for_fd_to_be_readable_or_erring ( int fd )
2235{
2236 struct pollfd pfd;
sewardjd1c1cf22002-06-26 00:13:36 +00002237 int res;
2238
sewardj6e6cbaa2002-05-24 02:12:52 +00002239 /* fprintf(stderr, "wait_for_fd_to_be_readable_or_erring %d\n", fd); */
sewardjd1c1cf22002-06-26 00:13:36 +00002240
2241 /* First check to see if the fd is nonblocking, and/or invalid. In
2242 either case return immediately. */
2243 res = __libc_fcntl(fd, F_GETFL, 0);
2244 if (res == -1) return; /* fd is invalid somehow */
2245 if (res & O_NONBLOCK) return; /* fd is nonblocking */
2246
2247 /* Ok, we'd better wait with poll. */
sewardj705d3cb2002-05-23 13:13:12 +00002248 pfd.fd = fd;
2249 pfd.events = POLLIN | POLLPRI | POLLERR | POLLHUP | POLLNVAL;
2250 /* ... but not POLLOUT, you may notice. */
2251 pfd.revents = 0;
2252 (void)poll(&pfd, 1, -1 /* forever */);
2253}
2254
2255
sewardj3b13f0e2002-04-25 20:17:29 +00002256/* ---------------------------------------------------------------------
sewardj8f253ff2002-05-19 00:13:34 +00002257 Hacky implementation of semaphores.
2258 ------------------------------------------------------------------ */
2259
2260#include <semaphore.h>
2261
2262/* This is a terrible way to do the remapping. Plan is to import an
2263 AVL tree at some point. */
sewardj8f253ff2002-05-19 00:13:34 +00002264
2265typedef
2266 struct {
2267 pthread_mutex_t se_mx;
2268 pthread_cond_t se_cv;
2269 int count;
2270 }
2271 vg_sem_t;
2272
2273static pthread_mutex_t se_remap_mx = PTHREAD_MUTEX_INITIALIZER;
2274
2275static int se_remap_used = 0;
2276static sem_t* se_remap_orig[VG_N_SEMAPHORES];
2277static vg_sem_t se_remap_new[VG_N_SEMAPHORES];
2278
2279static vg_sem_t* se_remap ( sem_t* orig )
2280{
2281 int res, i;
2282 res = __pthread_mutex_lock(&se_remap_mx);
sewardj2d94c112002-06-03 01:25:54 +00002283 my_assert(res == 0);
sewardj8f253ff2002-05-19 00:13:34 +00002284
2285 for (i = 0; i < se_remap_used; i++) {
2286 if (se_remap_orig[i] == orig)
2287 break;
2288 }
2289 if (i == se_remap_used) {
2290 if (se_remap_used == VG_N_SEMAPHORES) {
2291 res = pthread_mutex_unlock(&se_remap_mx);
sewardj2d94c112002-06-03 01:25:54 +00002292 my_assert(res == 0);
sewardja1ac5cb2002-05-27 13:00:05 +00002293 barf("VG_N_SEMAPHORES is too low. Increase and recompile.");
sewardj8f253ff2002-05-19 00:13:34 +00002294 }
2295 se_remap_used++;
2296 se_remap_orig[i] = orig;
2297 /* printf("allocated semaphore %d\n", i); */
2298 }
2299 res = __pthread_mutex_unlock(&se_remap_mx);
sewardj2d94c112002-06-03 01:25:54 +00002300 my_assert(res == 0);
sewardj8f253ff2002-05-19 00:13:34 +00002301 return &se_remap_new[i];
2302}
2303
2304
2305int sem_init(sem_t *sem, int pshared, unsigned int value)
2306{
2307 int res;
2308 vg_sem_t* vg_sem;
2309 ensure_valgrind("sem_init");
2310 if (pshared != 0) {
sewardj4dced352002-06-04 22:54:20 +00002311 pthread_error("sem_init: unsupported pshared value");
sewardj8f253ff2002-05-19 00:13:34 +00002312 errno = ENOSYS;
2313 return -1;
2314 }
2315 vg_sem = se_remap(sem);
2316 res = pthread_mutex_init(&vg_sem->se_mx, NULL);
sewardj2d94c112002-06-03 01:25:54 +00002317 my_assert(res == 0);
sewardj8f253ff2002-05-19 00:13:34 +00002318 res = pthread_cond_init(&vg_sem->se_cv, NULL);
sewardj2d94c112002-06-03 01:25:54 +00002319 my_assert(res == 0);
sewardj8f253ff2002-05-19 00:13:34 +00002320 vg_sem->count = value;
2321 return 0;
2322}
2323
2324
2325int sem_wait ( sem_t* sem )
2326{
2327 int res;
2328 vg_sem_t* vg_sem;
2329 ensure_valgrind("sem_wait");
2330 vg_sem = se_remap(sem);
2331 res = __pthread_mutex_lock(&vg_sem->se_mx);
sewardj2d94c112002-06-03 01:25:54 +00002332 my_assert(res == 0);
sewardj8f253ff2002-05-19 00:13:34 +00002333 while (vg_sem->count == 0) {
2334 res = pthread_cond_wait(&vg_sem->se_cv, &vg_sem->se_mx);
sewardj2d94c112002-06-03 01:25:54 +00002335 my_assert(res == 0);
sewardj8f253ff2002-05-19 00:13:34 +00002336 }
2337 vg_sem->count--;
2338 res = __pthread_mutex_unlock(&vg_sem->se_mx);
sewardj2d94c112002-06-03 01:25:54 +00002339 my_assert(res == 0);
sewardj8f253ff2002-05-19 00:13:34 +00002340 return 0;
2341}
2342
2343int sem_post ( sem_t* sem )
2344{
2345 int res;
2346 vg_sem_t* vg_sem;
2347 ensure_valgrind("sem_post");
2348 vg_sem = se_remap(sem);
2349 res = __pthread_mutex_lock(&vg_sem->se_mx);
sewardj2d94c112002-06-03 01:25:54 +00002350 my_assert(res == 0);
sewardj8f253ff2002-05-19 00:13:34 +00002351 if (vg_sem->count == 0) {
2352 vg_sem->count++;
2353 res = pthread_cond_broadcast(&vg_sem->se_cv);
sewardj2d94c112002-06-03 01:25:54 +00002354 my_assert(res == 0);
sewardj8f253ff2002-05-19 00:13:34 +00002355 } else {
2356 vg_sem->count++;
2357 }
2358 res = __pthread_mutex_unlock(&vg_sem->se_mx);
sewardj2d94c112002-06-03 01:25:54 +00002359 my_assert(res == 0);
sewardj8f253ff2002-05-19 00:13:34 +00002360 return 0;
2361}
2362
2363
2364int sem_trywait ( sem_t* sem )
2365{
2366 int ret, res;
2367 vg_sem_t* vg_sem;
2368 ensure_valgrind("sem_trywait");
2369 vg_sem = se_remap(sem);
2370 res = __pthread_mutex_lock(&vg_sem->se_mx);
sewardj2d94c112002-06-03 01:25:54 +00002371 my_assert(res == 0);
sewardj8f253ff2002-05-19 00:13:34 +00002372 if (vg_sem->count > 0) {
2373 vg_sem->count--;
2374 ret = 0;
2375 } else {
2376 ret = -1;
2377 errno = EAGAIN;
2378 }
2379 res = __pthread_mutex_unlock(&vg_sem->se_mx);
sewardj2d94c112002-06-03 01:25:54 +00002380 my_assert(res == 0);
sewardj8f253ff2002-05-19 00:13:34 +00002381 return ret;
2382}
2383
2384
2385int sem_getvalue(sem_t* sem, int * sval)
2386{
2387 vg_sem_t* vg_sem;
2388 ensure_valgrind("sem_trywait");
2389 vg_sem = se_remap(sem);
2390 *sval = vg_sem->count;
2391 return 0;
2392}
2393
2394
2395int sem_destroy(sem_t * sem)
2396{
2397 kludged("sem_destroy");
2398 /* if someone waiting on this semaphore, errno = EBUSY, return -1 */
2399 return 0;
2400}
2401
2402
2403/* ---------------------------------------------------------------------
sewardj2d8b3f02002-06-01 14:14:19 +00002404 Reader-writer locks.
sewardja1ac5cb2002-05-27 13:00:05 +00002405 ------------------------------------------------------------------ */
2406
sewardj2d8b3f02002-06-01 14:14:19 +00002407typedef
2408 struct {
2409 int initted; /* != 0 --> in use; sanity check only */
2410 int prefer_w; /* != 0 --> prefer writer */
2411 int nwait_r; /* # of waiting readers */
2412 int nwait_w; /* # of waiting writers */
2413 pthread_cond_t cv_r; /* for signalling readers */
2414 pthread_cond_t cv_w; /* for signalling writers */
2415 pthread_mutex_t mx;
2416 int status;
2417 /* allowed range for status: >= -1. -1 means 1 writer currently
2418 active, >= 0 means N readers currently active. */
2419 }
2420 vg_rwlock_t;
sewardja1ac5cb2002-05-27 13:00:05 +00002421
2422
2423static pthread_mutex_t rw_remap_mx = PTHREAD_MUTEX_INITIALIZER;
2424
2425static int rw_remap_used = 0;
2426static pthread_rwlock_t* rw_remap_orig[VG_N_RWLOCKS];
2427static vg_rwlock_t rw_remap_new[VG_N_RWLOCKS];
2428
sewardj2d8b3f02002-06-01 14:14:19 +00002429
2430static
2431void init_vg_rwlock ( vg_rwlock_t* vg_rwl )
2432{
2433 int res = 0;
2434 vg_rwl->initted = 1;
2435 vg_rwl->prefer_w = 1;
2436 vg_rwl->nwait_r = 0;
2437 vg_rwl->nwait_w = 0;
2438 vg_rwl->status = 0;
2439 res = pthread_mutex_init(&vg_rwl->mx, NULL);
2440 res |= pthread_cond_init(&vg_rwl->cv_r, NULL);
2441 res |= pthread_cond_init(&vg_rwl->cv_w, NULL);
sewardj2d94c112002-06-03 01:25:54 +00002442 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002443}
2444
2445
sewardja1ac5cb2002-05-27 13:00:05 +00002446/* Take the address of a LinuxThreads rwlock_t and return the shadow
2447 address of our version. Further, if the LinuxThreads version
2448 appears to have been statically initialised, do the same to the one
2449 we allocate here. The pthread_rwlock_t.__rw_readers field is set
2450 to zero by PTHREAD_RWLOCK_INITIALIZER, so we take zero as meaning
2451 uninitialised and non-zero meaning initialised.
2452*/
2453static vg_rwlock_t* rw_remap ( pthread_rwlock_t* orig )
2454{
2455 int res, i;
2456 vg_rwlock_t* vg_rwl;
2457 res = __pthread_mutex_lock(&rw_remap_mx);
sewardj2d94c112002-06-03 01:25:54 +00002458 my_assert(res == 0);
sewardja1ac5cb2002-05-27 13:00:05 +00002459
2460 for (i = 0; i < rw_remap_used; i++) {
2461 if (rw_remap_orig[i] == orig)
2462 break;
2463 }
2464 if (i == rw_remap_used) {
2465 if (rw_remap_used == VG_N_RWLOCKS) {
sewardj2d8b3f02002-06-01 14:14:19 +00002466 res = __pthread_mutex_unlock(&rw_remap_mx);
sewardj2d94c112002-06-03 01:25:54 +00002467 my_assert(res == 0);
sewardja1ac5cb2002-05-27 13:00:05 +00002468 barf("VG_N_RWLOCKS is too low. Increase and recompile.");
2469 }
2470 rw_remap_used++;
2471 rw_remap_orig[i] = orig;
sewardj2d8b3f02002-06-01 14:14:19 +00002472 rw_remap_new[i].initted = 0;
sewardja1ac5cb2002-05-27 13:00:05 +00002473 if (0) printf("allocated rwlock %d\n", i);
2474 }
2475 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 vg_rwl = &rw_remap_new[i];
2478
sewardj2d8b3f02002-06-01 14:14:19 +00002479 /* Initialise the shadow, if required. */
sewardja1ac5cb2002-05-27 13:00:05 +00002480 if (orig->__rw_readers == 0) {
sewardja1ac5cb2002-05-27 13:00:05 +00002481 orig->__rw_readers = 1;
sewardj2d8b3f02002-06-01 14:14:19 +00002482 init_vg_rwlock(vg_rwl);
sewardja1ac5cb2002-05-27 13:00:05 +00002483 if (orig->__rw_kind == PTHREAD_RWLOCK_PREFER_READER_NP)
sewardj2d8b3f02002-06-01 14:14:19 +00002484 vg_rwl->prefer_w = 0;
sewardja1ac5cb2002-05-27 13:00:05 +00002485 }
2486
2487 return vg_rwl;
2488}
2489
2490
sewardja1ac5cb2002-05-27 13:00:05 +00002491int pthread_rwlock_init ( pthread_rwlock_t* orig,
2492 const pthread_rwlockattr_t* attr )
2493{
sewardja1ac5cb2002-05-27 13:00:05 +00002494 vg_rwlock_t* rwl;
2495 if (0) printf ("pthread_rwlock_init\n");
2496 /* Force the remapper to initialise the shadow. */
2497 orig->__rw_readers = 0;
2498 /* Install the lock preference; the remapper needs to know it. */
2499 orig->__rw_kind = PTHREAD_RWLOCK_DEFAULT_NP;
2500 if (attr)
2501 orig->__rw_kind = attr->__lockkind;
2502 rwl = rw_remap ( orig );
sewardj2d8b3f02002-06-01 14:14:19 +00002503 return 0;
sewardja1ac5cb2002-05-27 13:00:05 +00002504}
2505
sewardj2d8b3f02002-06-01 14:14:19 +00002506
2507static
2508void pthread_rwlock_rdlock_CANCEL_HDLR ( void* rwl_v )
sewardja1ac5cb2002-05-27 13:00:05 +00002509{
sewardj2d8b3f02002-06-01 14:14:19 +00002510 vg_rwlock_t* rwl = (vg_rwlock_t*)rwl_v;
2511 rwl->nwait_r--;
2512 pthread_mutex_unlock (&rwl->mx);
sewardja1ac5cb2002-05-27 13:00:05 +00002513}
2514
sewardj2d8b3f02002-06-01 14:14:19 +00002515
sewardja1ac5cb2002-05-27 13:00:05 +00002516int pthread_rwlock_rdlock ( pthread_rwlock_t* orig )
2517{
2518 int res;
2519 vg_rwlock_t* rwl;
2520 if (0) printf ("pthread_rwlock_rdlock\n");
2521 rwl = rw_remap ( orig );
sewardj2d8b3f02002-06-01 14:14:19 +00002522 res = __pthread_mutex_lock(&rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00002523 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002524 if (!rwl->initted) {
2525 res = __pthread_mutex_unlock(&rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00002526 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002527 return EINVAL;
2528 }
2529 if (rwl->status < 0) {
sewardj2d94c112002-06-03 01:25:54 +00002530 my_assert(rwl->status == -1);
sewardj2d8b3f02002-06-01 14:14:19 +00002531 rwl->nwait_r++;
2532 pthread_cleanup_push( pthread_rwlock_rdlock_CANCEL_HDLR, rwl );
2533 while (1) {
2534 if (rwl->status == 0) break;
2535 res = pthread_cond_wait(&rwl->cv_r, &rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00002536 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002537 }
2538 pthread_cleanup_pop(0);
2539 rwl->nwait_r--;
2540 }
sewardj2d94c112002-06-03 01:25:54 +00002541 my_assert(rwl->status >= 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002542 rwl->status++;
2543 res = __pthread_mutex_unlock(&rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00002544 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002545 return 0;
sewardja1ac5cb2002-05-27 13:00:05 +00002546}
2547
sewardj2d8b3f02002-06-01 14:14:19 +00002548
sewardja1ac5cb2002-05-27 13:00:05 +00002549int pthread_rwlock_tryrdlock ( pthread_rwlock_t* orig )
2550{
2551 int res;
2552 vg_rwlock_t* rwl;
2553 if (0) printf ("pthread_rwlock_tryrdlock\n");
2554 rwl = rw_remap ( orig );
sewardj2d8b3f02002-06-01 14:14:19 +00002555 res = __pthread_mutex_lock(&rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00002556 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002557 if (!rwl->initted) {
2558 res = __pthread_mutex_unlock(&rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00002559 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002560 return EINVAL;
2561 }
2562 if (rwl->status == -1) {
2563 /* Writer active; we have to give up. */
2564 res = __pthread_mutex_unlock(&rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00002565 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002566 return EBUSY;
2567 }
2568 /* Success */
sewardj2d94c112002-06-03 01:25:54 +00002569 my_assert(rwl->status >= 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002570 rwl->status++;
2571 res = __pthread_mutex_unlock(&rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00002572 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002573 return 0;
sewardja1ac5cb2002-05-27 13:00:05 +00002574}
2575
sewardj2d8b3f02002-06-01 14:14:19 +00002576
2577static
2578void pthread_rwlock_wrlock_CANCEL_HDLR ( void* rwl_v )
2579{
2580 vg_rwlock_t* rwl = (vg_rwlock_t*)rwl_v;
2581 rwl->nwait_w--;
2582 pthread_mutex_unlock (&rwl->mx);
2583}
2584
2585
sewardja1ac5cb2002-05-27 13:00:05 +00002586int pthread_rwlock_wrlock ( pthread_rwlock_t* orig )
2587{
2588 int res;
2589 vg_rwlock_t* rwl;
2590 if (0) printf ("pthread_rwlock_wrlock\n");
2591 rwl = rw_remap ( orig );
sewardj2d8b3f02002-06-01 14:14:19 +00002592 res = __pthread_mutex_lock(&rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00002593 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002594 if (!rwl->initted) {
2595 res = __pthread_mutex_unlock(&rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00002596 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002597 return EINVAL;
2598 }
2599 if (rwl->status != 0) {
2600 rwl->nwait_w++;
2601 pthread_cleanup_push( pthread_rwlock_wrlock_CANCEL_HDLR, rwl );
2602 while (1) {
2603 if (rwl->status == 0) break;
2604 res = pthread_cond_wait(&rwl->cv_w, &rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00002605 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002606 }
2607 pthread_cleanup_pop(0);
2608 rwl->nwait_w--;
2609 }
sewardj2d94c112002-06-03 01:25:54 +00002610 my_assert(rwl->status == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002611 rwl->status = -1;
2612 res = __pthread_mutex_unlock(&rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00002613 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002614 return 0;
sewardja1ac5cb2002-05-27 13:00:05 +00002615}
2616
sewardj2d8b3f02002-06-01 14:14:19 +00002617
sewardja1ac5cb2002-05-27 13:00:05 +00002618int pthread_rwlock_trywrlock ( pthread_rwlock_t* orig )
2619{
2620 int res;
2621 vg_rwlock_t* rwl;
sewardj2d8b3f02002-06-01 14:14:19 +00002622 if (0) printf ("pthread_wrlock_trywrlock\n");
sewardja1ac5cb2002-05-27 13:00:05 +00002623 rwl = rw_remap ( orig );
sewardj2d8b3f02002-06-01 14:14:19 +00002624 res = __pthread_mutex_lock(&rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00002625 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002626 if (!rwl->initted) {
2627 res = __pthread_mutex_unlock(&rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00002628 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002629 return EINVAL;
2630 }
2631 if (rwl->status != 0) {
2632 /* Reader(s) or a writer active; we have to give up. */
2633 res = __pthread_mutex_unlock(&rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00002634 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002635 return EBUSY;
2636 }
2637 /* Success */
sewardj2d94c112002-06-03 01:25:54 +00002638 my_assert(rwl->status == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002639 rwl->status = -1;
2640 res = __pthread_mutex_unlock(&rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00002641 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002642 return 0;
sewardja1ac5cb2002-05-27 13:00:05 +00002643}
2644
sewardj2d8b3f02002-06-01 14:14:19 +00002645
sewardja1ac5cb2002-05-27 13:00:05 +00002646int pthread_rwlock_unlock ( pthread_rwlock_t* orig )
2647{
2648 int res;
2649 vg_rwlock_t* rwl;
2650 if (0) printf ("pthread_rwlock_unlock\n");
2651 rwl = rw_remap ( orig );
sewardj2d8b3f02002-06-01 14:14:19 +00002652 rwl = rw_remap ( orig );
2653 res = __pthread_mutex_lock(&rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00002654 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002655 if (!rwl->initted) {
2656 res = __pthread_mutex_unlock(&rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00002657 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002658 return EINVAL;
2659 }
2660 if (rwl->status == 0) {
2661 res = __pthread_mutex_unlock(&rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00002662 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002663 return EPERM;
2664 }
sewardj2d94c112002-06-03 01:25:54 +00002665 my_assert(rwl->status != 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002666 if (rwl->status == -1) {
2667 rwl->status = 0;
2668 } else {
sewardj2d94c112002-06-03 01:25:54 +00002669 my_assert(rwl->status > 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002670 rwl->status--;
2671 }
2672
sewardj2d94c112002-06-03 01:25:54 +00002673 my_assert(rwl->status >= 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002674
2675 if (rwl->prefer_w) {
2676
2677 /* Favour waiting writers, if any. */
2678 if (rwl->nwait_w > 0) {
2679 /* Writer(s) are waiting. */
2680 if (rwl->status == 0) {
2681 /* We can let a writer in. */
2682 res = pthread_cond_signal(&rwl->cv_w);
sewardj2d94c112002-06-03 01:25:54 +00002683 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002684 } else {
2685 /* There are still readers active. Do nothing; eventually
2686 they will disappear, at which point a writer will be
2687 admitted. */
2688 }
2689 }
2690 else
2691 /* No waiting writers. */
2692 if (rwl->nwait_r > 0) {
2693 /* Let in a waiting reader. */
2694 res = pthread_cond_signal(&rwl->cv_r);
sewardj2d94c112002-06-03 01:25:54 +00002695 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002696 }
2697
2698 } else {
2699
2700 /* Favour waiting readers, if any. */
2701 if (rwl->nwait_r > 0) {
2702 /* Reader(s) are waiting; let one in. */
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 else
2707 /* No waiting readers. */
2708 if (rwl->nwait_w > 0 && rwl->status == 0) {
2709 /* We have waiting writers and no active readers; let a
2710 writer in. */
2711 res = pthread_cond_signal(&rwl->cv_w);
sewardj2d94c112002-06-03 01:25:54 +00002712 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002713 }
2714 }
2715
2716 res = __pthread_mutex_unlock(&rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00002717 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002718 return 0;
2719}
2720
2721
2722int pthread_rwlock_destroy ( pthread_rwlock_t *orig )
2723{
2724 int res;
2725 vg_rwlock_t* rwl;
2726 if (0) printf ("pthread_rwlock_destroy\n");
2727 rwl = rw_remap ( orig );
2728 res = __pthread_mutex_lock(&rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00002729 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002730 if (!rwl->initted) {
2731 res = __pthread_mutex_unlock(&rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00002732 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002733 return EINVAL;
2734 }
2735 if (rwl->status != 0 || rwl->nwait_r > 0 || rwl->nwait_w > 0) {
2736 res = __pthread_mutex_unlock(&rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00002737 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002738 return EBUSY;
2739 }
2740 rwl->initted = 0;
2741 res = __pthread_mutex_unlock(&rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00002742 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002743 return 0;
sewardja1ac5cb2002-05-27 13:00:05 +00002744}
2745
2746
sewardj47e4e312002-06-18 09:24:34 +00002747/* Copied directly from LinuxThreads. */
2748int
2749pthread_rwlockattr_init (pthread_rwlockattr_t *attr)
2750{
2751 attr->__lockkind = 0;
2752 attr->__pshared = PTHREAD_PROCESS_PRIVATE;
2753
2754 return 0;
2755}
2756
sewardjfe18eb82002-07-13 12:58:44 +00002757/* Copied directly from LinuxThreads. */
2758int
2759pthread_rwlockattr_setpshared (pthread_rwlockattr_t *attr, int pshared)
2760{
2761 if (pshared != PTHREAD_PROCESS_PRIVATE && pshared != PTHREAD_PROCESS_SHARED)
2762 return EINVAL;
2763
2764 /* For now it is not possible to shared a conditional variable. */
2765 if (pshared != PTHREAD_PROCESS_PRIVATE)
2766 return ENOSYS;
2767
2768 attr->__pshared = pshared;
2769
2770 return 0;
2771}
2772
sewardj47e4e312002-06-18 09:24:34 +00002773
sewardja1ac5cb2002-05-27 13:00:05 +00002774/* ---------------------------------------------------------------------
sewardj3b13f0e2002-04-25 20:17:29 +00002775 B'stard.
2776 ------------------------------------------------------------------ */
2777
2778# define strong_alias(name, aliasname) \
2779 extern __typeof (name) aliasname __attribute__ ((alias (#name)));
2780
sewardj5905fae2002-04-26 13:25:00 +00002781# define weak_alias(name, aliasname) \
2782 extern __typeof (name) aliasname __attribute__ ((weak, alias (#name)));
sewardj3b13f0e2002-04-25 20:17:29 +00002783
sewardj5905fae2002-04-26 13:25:00 +00002784strong_alias(__pthread_mutex_lock, pthread_mutex_lock)
2785strong_alias(__pthread_mutex_trylock, pthread_mutex_trylock)
2786strong_alias(__pthread_mutex_unlock, pthread_mutex_unlock)
2787strong_alias(__pthread_mutexattr_init, pthread_mutexattr_init)
2788 weak_alias(__pthread_mutexattr_settype, pthread_mutexattr_settype)
2789strong_alias(__pthread_mutex_init, pthread_mutex_init)
2790strong_alias(__pthread_mutexattr_destroy, pthread_mutexattr_destroy)
2791strong_alias(__pthread_mutex_destroy, pthread_mutex_destroy)
2792strong_alias(__pthread_once, pthread_once)
2793strong_alias(__pthread_atfork, pthread_atfork)
2794strong_alias(__pthread_key_create, pthread_key_create)
2795strong_alias(__pthread_getspecific, pthread_getspecific)
2796strong_alias(__pthread_setspecific, pthread_setspecific)
2797
sewardjd529a442002-05-04 19:49:21 +00002798#ifndef GLIBC_2_1
sewardj3b13f0e2002-04-25 20:17:29 +00002799strong_alias(sigaction, __sigaction)
sewardjd529a442002-05-04 19:49:21 +00002800#endif
2801
sewardj5905fae2002-04-26 13:25:00 +00002802strong_alias(close, __close)
sewardj3b13f0e2002-04-25 20:17:29 +00002803strong_alias(fcntl, __fcntl)
sewardj5905fae2002-04-26 13:25:00 +00002804strong_alias(lseek, __lseek)
2805strong_alias(open, __open)
2806strong_alias(open64, __open64)
sewardj5905fae2002-04-26 13:25:00 +00002807strong_alias(read, __read)
2808strong_alias(wait, __wait)
2809strong_alias(write, __write)
sewardj3b13f0e2002-04-25 20:17:29 +00002810strong_alias(connect, __connect)
sewardj5905fae2002-04-26 13:25:00 +00002811strong_alias(send, __send)
2812
sewardj726c4122002-05-16 23:39:10 +00002813weak_alias (__pread64, pread64)
sewardja18e2102002-05-18 10:43:22 +00002814weak_alias (__pwrite64, pwrite64)
sewardj5905fae2002-04-26 13:25:00 +00002815weak_alias(__fork, fork)
njn25e49d8e72002-09-23 09:36:25 +00002816weak_alias(__vfork, vfork)
sewardj7f6456d2002-05-21 00:51:21 +00002817
sewardjf0b06452002-06-04 08:38:04 +00002818weak_alias (__pthread_kill_other_threads_np, pthread_kill_other_threads_np)
sewardj3b13f0e2002-04-25 20:17:29 +00002819
2820/*--------------------------------------------------*/
2821
sewardj5905fae2002-04-26 13:25:00 +00002822weak_alias(pthread_rwlock_rdlock, __pthread_rwlock_rdlock)
sewardj5905fae2002-04-26 13:25:00 +00002823weak_alias(pthread_rwlock_unlock, __pthread_rwlock_unlock)
sewardj262b0292002-05-01 00:03:16 +00002824weak_alias(pthread_rwlock_wrlock, __pthread_rwlock_wrlock)
sewardj060b04f2002-04-26 21:01:13 +00002825
sewardja1ac5cb2002-05-27 13:00:05 +00002826weak_alias(pthread_rwlock_destroy, __pthread_rwlock_destroy)
2827weak_alias(pthread_rwlock_init, __pthread_rwlock_init)
2828weak_alias(pthread_rwlock_tryrdlock, __pthread_rwlock_tryrdlock)
2829weak_alias(pthread_rwlock_trywrlock, __pthread_rwlock_trywrlock)
2830
sewardj060b04f2002-04-26 21:01:13 +00002831
sewardj3b13f0e2002-04-25 20:17:29 +00002832/* I've no idea what these are, but they get called quite a lot.
2833 Anybody know? */
2834
2835#undef _IO_flockfile
2836void _IO_flockfile ( _IO_FILE * file )
2837{
sewardj853f55d2002-04-26 00:27:53 +00002838 pthread_mutex_lock(file->_lock);
sewardj3b13f0e2002-04-25 20:17:29 +00002839}
sewardj5905fae2002-04-26 13:25:00 +00002840weak_alias(_IO_flockfile, flockfile);
2841
sewardj3b13f0e2002-04-25 20:17:29 +00002842
2843#undef _IO_funlockfile
2844void _IO_funlockfile ( _IO_FILE * file )
2845{
sewardj853f55d2002-04-26 00:27:53 +00002846 pthread_mutex_unlock(file->_lock);
sewardj3b13f0e2002-04-25 20:17:29 +00002847}
sewardj5905fae2002-04-26 13:25:00 +00002848weak_alias(_IO_funlockfile, funlockfile);
2849
sewardj3b13f0e2002-04-25 20:17:29 +00002850
sewardjd4f2c712002-04-30 10:20:10 +00002851/* This doesn't seem to be needed to simulate libpthread.so's external
2852 interface, but many people complain about its absence. */
2853
2854strong_alias(__pthread_mutexattr_settype, __pthread_mutexattr_setkind_np)
2855weak_alias(__pthread_mutexattr_setkind_np, pthread_mutexattr_setkind_np)
sewardj439d45e2002-05-03 20:43:10 +00002856
2857
2858/*--------------------------------------------------------------------*/
2859/*--- end vg_libpthread.c ---*/
2860/*--------------------------------------------------------------------*/