blob: c2b0f68e619ec9fdf8888422e0dcfdb74cada214 [file] [log] [blame]
sewardje663cb92002-04-12 10:26:32 +00001
sewardj439d45e2002-05-03 20:43:10 +00002/*--------------------------------------------------------------------*/
3/*--- A replacement for the standard libpthread.so. ---*/
4/*--- vg_libpthread.c ---*/
5/*--------------------------------------------------------------------*/
6
7/*
8 This file is part of Valgrind, an x86 protected-mode emulator
9 designed for debugging and profiling binaries on x86-Unixes.
10
11 Copyright (C) 2000-2002 Julian Seward
12 jseward@acm.org
13
14 This program is free software; you can redistribute it and/or
15 modify it under the terms of the GNU General Public License as
16 published by the Free Software Foundation; either version 2 of the
17 License, or (at your option) any later version.
18
19 This program is distributed in the hope that it will be useful, but
20 WITHOUT ANY WARRANTY; without even the implied warranty of
21 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
22 General Public License for more details.
23
24 You should have received a copy of the GNU General Public License
25 along with this program; if not, write to the Free Software
26 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
27 02111-1307, USA.
28
29 The GNU General Public License is contained in the file LICENSE.
30*/
31
32/* ALL THIS CODE RUNS ON THE SIMULATED CPU.
33
34 This is a replacement for the standard libpthread.so. It is loaded
sewardje663cb92002-04-12 10:26:32 +000035 as part of the client's image (if required) and directs pthread
36 calls through to Valgrind's request mechanism.
37
38 A couple of caveats.
39
40 1. Since it's a binary-compatible replacement for an existing library,
41 we must take care to used exactly the same data layouts, etc, as
42 the standard pthread.so does.
43
44 2. Since this runs as part of the client, there are no specific
45 restrictions on what headers etc we can include, so long as
46 this libpthread.so does not end up having dependencies on .so's
47 which the real one doesn't.
48
49 Later ... it appears we cannot call file-related stuff in libc here,
50 perhaps fair enough. Be careful what you call from here. Even exit()
51 doesn't work (gives infinite recursion and then stack overflow); hence
52 myexit(). Also fprintf doesn't seem safe.
53*/
54
55#include "valgrind.h" /* For the request-passing mechanism */
56#include "vg_include.h" /* For the VG_USERREQ__* constants */
57
sewardja1ac5cb2002-05-27 13:00:05 +000058#define __USE_UNIX98
59#include <sys/types.h>
60#include <pthread.h>
61#undef __USE_UNIX98
62
sewardje663cb92002-04-12 10:26:32 +000063#include <unistd.h>
64#include <string.h>
sewardj2a1dcce2002-04-22 12:45:25 +000065#ifdef GLIBC_2_1
66#include <sys/time.h>
67#endif
sewardje663cb92002-04-12 10:26:32 +000068
sewardj2d94c112002-06-03 01:25:54 +000069#include <stdio.h>
70
sewardj705d3cb2002-05-23 13:13:12 +000071
72/* ---------------------------------------------------------------------
73 Forwardses.
74 ------------------------------------------------------------------ */
75
76static void wait_for_fd_to_be_readable_or_erring ( int fd );
77
78
sewardje663cb92002-04-12 10:26:32 +000079/* ---------------------------------------------------------------------
80 Helpers. We have to be pretty self-sufficient.
81 ------------------------------------------------------------------ */
82
sewardj436e0582002-04-26 14:31:40 +000083/* Number of times any given error message is printed. */
84#define N_MOANS 3
85
sewardj45b4b372002-04-16 22:50:32 +000086/* Extract from Valgrind the value of VG_(clo_trace_pthread_level).
87 Returns 0 (none) if not running on Valgrind. */
88static
89int get_pt_trace_level ( void )
90{
91 int res;
92 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
93 VG_USERREQ__GET_PTHREAD_TRACE_LEVEL,
94 0, 0, 0, 0);
95 return res;
96}
97
98
sewardje663cb92002-04-12 10:26:32 +000099static
sewardj2d94c112002-06-03 01:25:54 +0000100void my_exit ( int arg )
sewardje663cb92002-04-12 10:26:32 +0000101{
sewardj45b4b372002-04-16 22:50:32 +0000102 int __res;
sewardje663cb92002-04-12 10:26:32 +0000103 __asm__ volatile ("movl %%ecx, %%ebx ; int $0x80"
104 : "=a" (__res)
105 : "0" (__NR_exit),
106 "c" (arg) );
sewardj45b4b372002-04-16 22:50:32 +0000107 /* We don't bother to mention the fact that this asm trashes %ebx,
108 since it won't return. If you ever do let it return ... fix
109 this! */
sewardje663cb92002-04-12 10:26:32 +0000110}
111
112
sewardj68b2dd92002-05-10 21:03:56 +0000113/* We need this guy -- it's in valgrind.so. */
114extern void VG_(startup) ( void );
115
116
117/* Just start up Valgrind if it's not already going. VG_(startup)()
118 detects and ignores second and subsequent calls. */
sewardj604ec3c2002-04-18 22:38:41 +0000119static __inline__
sewardje663cb92002-04-12 10:26:32 +0000120void ensure_valgrind ( char* caller )
121{
sewardj68b2dd92002-05-10 21:03:56 +0000122 VG_(startup)();
sewardje663cb92002-04-12 10:26:32 +0000123}
124
sewardjbea1caa2002-05-10 23:20:58 +0000125/* While we're at it ... hook our own startup function into this
126 game. */
127__asm__ (
128 ".section .init\n"
129 "\tcall vgPlain_startup"
130);
131
sewardje663cb92002-04-12 10:26:32 +0000132
133static
sewardj3b5d8862002-04-20 13:53:23 +0000134__attribute__((noreturn))
sewardje663cb92002-04-12 10:26:32 +0000135void barf ( char* str )
136{
137 char buf[100];
138 buf[0] = 0;
sewardj439d45e2002-05-03 20:43:10 +0000139 strcat(buf, "\nvalgrind's libpthread.so: ");
sewardje663cb92002-04-12 10:26:32 +0000140 strcat(buf, str);
141 strcat(buf, "\n\n");
142 write(2, buf, strlen(buf));
sewardj2d94c112002-06-03 01:25:54 +0000143 my_exit(1);
sewardj3b5d8862002-04-20 13:53:23 +0000144 /* We have to persuade gcc into believing this doesn't return. */
145 while (1) { };
sewardje663cb92002-04-12 10:26:32 +0000146}
147
148
sewardj2a3d28c2002-04-14 13:27:00 +0000149static void ignored ( char* msg )
150{
sewardj436e0582002-04-26 14:31:40 +0000151 if (get_pt_trace_level() >= 0) {
sewardj439d45e2002-05-03 20:43:10 +0000152 char* ig = "valgrind's libpthread.so: IGNORED call to: ";
sewardj45b4b372002-04-16 22:50:32 +0000153 write(2, ig, strlen(ig));
154 write(2, msg, strlen(msg));
155 ig = "\n";
156 write(2, ig, strlen(ig));
157 }
sewardj2a3d28c2002-04-14 13:27:00 +0000158}
159
sewardj30671ff2002-04-21 00:13:57 +0000160static void kludged ( char* msg )
161{
sewardj436e0582002-04-26 14:31:40 +0000162 if (get_pt_trace_level() >= 0) {
sewardj439d45e2002-05-03 20:43:10 +0000163 char* ig = "valgrind's libpthread.so: KLUDGED call to: ";
164 write(2, ig, strlen(ig));
165 write(2, msg, strlen(msg));
166 ig = "\n";
167 write(2, ig, strlen(ig));
168 }
169}
170
171static void not_inside ( char* msg )
172{
sewardj68b2dd92002-05-10 21:03:56 +0000173 VG_(startup)();
sewardj30671ff2002-04-21 00:13:57 +0000174}
175
sewardjccef2e62002-05-29 19:26:32 +0000176__attribute__((noreturn))
sewardj3b13f0e2002-04-25 20:17:29 +0000177void vgPlain_unimp ( char* what )
178{
sewardj439d45e2002-05-03 20:43:10 +0000179 char* ig = "valgrind's libpthread.so: UNIMPLEMENTED FUNCTION: ";
sewardj3b13f0e2002-04-25 20:17:29 +0000180 write(2, ig, strlen(ig));
181 write(2, what, strlen(what));
182 ig = "\n";
183 write(2, ig, strlen(ig));
184 barf("Please report this bug to me at: jseward@acm.org");
185}
186
sewardje663cb92002-04-12 10:26:32 +0000187
sewardj457cc472002-06-03 23:13:47 +0000188static
sewardj2d94c112002-06-03 01:25:54 +0000189void my_assert_fail ( Char* expr, Char* file, Int line, Char* fn )
190{
191 static Bool entered = False;
192 if (entered)
193 my_exit(2);
194 entered = True;
195 fprintf(stderr, "\n%s: %s:%d (%s): Assertion `%s' failed.\n",
196 "valgrind", file, line, fn, expr );
197 fprintf(stderr, "Please report this bug to me at: %s\n\n",
198 VG_EMAIL_ADDR);
199 my_exit(1);
200}
201
202#define MY__STRING(__str) #__str
203
204#define my_assert(expr) \
205 ((void) ((expr) ? 0 : \
206 (my_assert_fail (MY__STRING(expr), \
207 __FILE__, __LINE__, \
208 __PRETTY_FUNCTION__), 0)))
209
210
sewardje663cb92002-04-12 10:26:32 +0000211/* ---------------------------------------------------------------------
212 Pass pthread_ calls to Valgrind's request mechanism.
213 ------------------------------------------------------------------ */
214
sewardjf8f819e2002-04-17 23:21:37 +0000215#include <errno.h>
sewardj5f07b662002-04-23 16:52:51 +0000216#include <sys/time.h> /* gettimeofday */
sewardjf8f819e2002-04-17 23:21:37 +0000217
sewardja1ac5cb2002-05-27 13:00:05 +0000218
sewardjf8f819e2002-04-17 23:21:37 +0000219/* ---------------------------------------------------
220 THREAD ATTRIBUTES
221 ------------------------------------------------ */
222
sewardj6af4b5d2002-04-16 04:40:49 +0000223int pthread_attr_init(pthread_attr_t *attr)
224{
sewardj7989d0c2002-05-28 11:00:01 +0000225 /* Just initialise the fields which we might look at. */
226 attr->__detachstate = PTHREAD_CREATE_JOINABLE;
sewardj6af4b5d2002-04-16 04:40:49 +0000227 return 0;
228}
229
230int pthread_attr_setdetachstate(pthread_attr_t *attr, int detachstate)
231{
sewardj7989d0c2002-05-28 11:00:01 +0000232 if (detachstate != PTHREAD_CREATE_JOINABLE
233 && detachstate != PTHREAD_CREATE_DETACHED)
234 return EINVAL;
235 attr->__detachstate = detachstate;
sewardj6af4b5d2002-04-16 04:40:49 +0000236 return 0;
237}
238
sewardj30671ff2002-04-21 00:13:57 +0000239int pthread_attr_setinheritsched(pthread_attr_t *attr, int inherit)
240{
sewardj436e0582002-04-26 14:31:40 +0000241 static int moans = N_MOANS;
242 if (moans-- > 0)
243 ignored("pthread_attr_setinheritsched");
sewardj30671ff2002-04-21 00:13:57 +0000244 return 0;
245}
sewardj6af4b5d2002-04-16 04:40:49 +0000246
sewardj0286dd52002-05-16 20:51:15 +0000247__attribute__((weak))
248int pthread_attr_setstacksize (pthread_attr_t *__attr,
249 size_t __stacksize)
250{
sewardja18e2102002-05-18 10:43:22 +0000251 size_t limit;
sewardj3d7c8d62002-06-04 20:59:16 +0000252 char buf[1024];
sewardj0286dd52002-05-16 20:51:15 +0000253 ensure_valgrind("pthread_attr_setstacksize");
sewardja18e2102002-05-18 10:43:22 +0000254 limit = VG_PTHREAD_STACK_SIZE - VG_AR_CLIENT_STACKBASE_REDZONE_SZB
255 - 1000; /* paranoia */
256 if (__stacksize < limit)
sewardj0286dd52002-05-16 20:51:15 +0000257 return 0;
sewardj3d7c8d62002-06-04 20:59:16 +0000258 snprintf(buf, sizeof(buf), "pthread_attr_setstacksize: "
259 "requested size %d >= VG_PTHREAD_STACK_SIZE\n "
260 "edit vg_include.h and rebuild.", __stacksize);
261 buf[sizeof(buf)-1] = '\0'; /* Make sure it is zero terminated */
262 barf(buf);
sewardj0286dd52002-05-16 20:51:15 +0000263}
264
265
sewardj30671ff2002-04-21 00:13:57 +0000266/* This is completely bogus. */
267int pthread_attr_getschedparam(const pthread_attr_t *attr,
268 struct sched_param *param)
269{
sewardj436e0582002-04-26 14:31:40 +0000270 static int moans = N_MOANS;
271 if (moans-- > 0)
272 kludged("pthread_attr_getschedparam");
sewardj3e909ce2002-06-03 13:27:15 +0000273# ifdef HAVE_SCHED_PRIORITY
sewardj72d58482002-04-24 02:20:20 +0000274 if (param) param->sched_priority = 0; /* who knows */
275# else
sewardj30671ff2002-04-21 00:13:57 +0000276 if (param) param->__sched_priority = 0; /* who knows */
sewardj72d58482002-04-24 02:20:20 +0000277# endif
sewardj30671ff2002-04-21 00:13:57 +0000278 return 0;
279}
280
281int pthread_attr_setschedparam(pthread_attr_t *attr,
282 const struct sched_param *param)
283{
sewardj436e0582002-04-26 14:31:40 +0000284 static int moans = N_MOANS;
285 if (moans-- > 0)
286 ignored("pthread_attr_setschedparam");
sewardj30671ff2002-04-21 00:13:57 +0000287 return 0;
288}
289
290int pthread_attr_destroy(pthread_attr_t *attr)
291{
sewardj436e0582002-04-26 14:31:40 +0000292 static int moans = N_MOANS;
293 if (moans-- > 0)
294 ignored("pthread_attr_destroy");
sewardj30671ff2002-04-21 00:13:57 +0000295 return 0;
296}
sewardjf8f819e2002-04-17 23:21:37 +0000297
sewardj0d844232002-06-02 09:29:31 +0000298/* These are no-ops, as with LinuxThreads. */
299int pthread_attr_setscope ( pthread_attr_t *attr, int scope )
300{
301 ensure_valgrind("pthread_attr_setscope");
302 if (scope == PTHREAD_SCOPE_SYSTEM)
303 return 0;
304 if (scope == PTHREAD_SCOPE_PROCESS)
305 return ENOTSUP;
306 return EINVAL;
307}
308
309int pthread_attr_getscope ( const pthread_attr_t *attr, int *scope )
310{
311 ensure_valgrind("pthread_attr_setscope");
312 if (scope)
313 *scope = PTHREAD_SCOPE_SYSTEM;
314 return 0;
315}
316
sewardj64039bb2002-06-03 00:58:18 +0000317
318/* Pretty bogus. Avoid if possible. */
319int pthread_getattr_np (pthread_t thread, pthread_attr_t *attr)
320{
321 int detached;
322 size_t limit;
323 ensure_valgrind("pthread_getattr_np");
324 kludged("pthread_getattr_np");
325 limit = VG_PTHREAD_STACK_SIZE - VG_AR_CLIENT_STACKBASE_REDZONE_SZB
326 - 1000; /* paranoia */
327 attr->__detachstate = PTHREAD_CREATE_JOINABLE;
328 attr->__schedpolicy = SCHED_OTHER;
329 attr->__schedparam.sched_priority = 0;
330 attr->__inheritsched = PTHREAD_EXPLICIT_SCHED;
331 attr->__scope = PTHREAD_SCOPE_SYSTEM;
332 attr->__guardsize = VKI_BYTES_PER_PAGE;
333 attr->__stackaddr = NULL;
334 attr->__stackaddr_set = 0;
335 attr->__stacksize = limit;
336 VALGRIND_MAGIC_SEQUENCE(detached, (-1) /* default */,
337 VG_USERREQ__SET_OR_GET_DETACH,
338 2 /* get */, thread, 0, 0);
sewardj2d94c112002-06-03 01:25:54 +0000339 my_assert(detached == 0 || detached == 1);
sewardj64039bb2002-06-03 00:58:18 +0000340 if (detached)
341 attr->__detachstate = PTHREAD_CREATE_DETACHED;
342 return 0;
343}
344
345
346/* Bogus ... */
347int pthread_attr_getstackaddr ( const pthread_attr_t * attr,
348 void ** stackaddr )
349{
350 ensure_valgrind("pthread_attr_getstackaddr");
351 kludged("pthread_attr_getstackaddr");
352 if (stackaddr)
353 *stackaddr = NULL;
354 return 0;
355}
356
357/* Not bogus (!) */
358int pthread_attr_getstacksize ( const pthread_attr_t * _attr,
359 size_t * __stacksize )
360{
361 size_t limit;
362 ensure_valgrind("pthread_attr_getstacksize");
363 limit = VG_PTHREAD_STACK_SIZE - VG_AR_CLIENT_STACKBASE_REDZONE_SZB
364 - 1000; /* paranoia */
365 if (__stacksize)
366 *__stacksize = limit;
367 return 0;
368}
369
sewardj20917d82002-05-28 01:36:45 +0000370/* ---------------------------------------------------
371 Helper functions for running a thread
372 and for clearing up afterwards.
373 ------------------------------------------------ */
374
375/* All exiting threads eventually pass through here, bearing the
376 return value, or PTHREAD_CANCELED, in ret_val. */
377static
378__attribute__((noreturn))
379void thread_exit_wrapper ( void* ret_val )
380{
sewardj870497a2002-05-29 01:06:47 +0000381 int detached, res;
382 CleanupEntry cu;
383 pthread_key_t key;
384
sewardj20917d82002-05-28 01:36:45 +0000385 /* Run this thread's cleanup handlers. */
sewardj8ad94e12002-05-29 00:10:20 +0000386 while (1) {
387 VALGRIND_MAGIC_SEQUENCE(res, (-1) /* default */,
388 VG_USERREQ__CLEANUP_POP,
389 &cu, 0, 0, 0);
390 if (res == -1) break; /* stack empty */
sewardj2d94c112002-06-03 01:25:54 +0000391 my_assert(res == 0);
sewardj8ad94e12002-05-29 00:10:20 +0000392 if (0) printf("running exit cleanup handler");
393 cu.fn ( cu.arg );
394 }
395
sewardj870497a2002-05-29 01:06:47 +0000396 /* Run this thread's key finalizers. Really this should be run
397 PTHREAD_DESTRUCTOR_ITERATIONS times. */
398 for (key = 0; key < VG_N_THREAD_KEYS; key++) {
399 VALGRIND_MAGIC_SEQUENCE(res, (-2) /* default */,
400 VG_USERREQ__GET_KEY_D_AND_S,
401 key, &cu, 0, 0 );
402 if (res == 0) {
403 /* valid key */
404 if (cu.fn && cu.arg)
405 cu.fn /* destructor for key */
406 ( cu.arg /* specific for key for this thread */ );
407 continue;
408 }
sewardj2d94c112002-06-03 01:25:54 +0000409 my_assert(res == -1);
sewardj870497a2002-05-29 01:06:47 +0000410 }
sewardj20917d82002-05-28 01:36:45 +0000411
412 /* Decide on my final disposition. */
413 VALGRIND_MAGIC_SEQUENCE(detached, (-1) /* default */,
414 VG_USERREQ__SET_OR_GET_DETACH,
sewardj7989d0c2002-05-28 11:00:01 +0000415 2 /* get */, pthread_self(), 0, 0);
sewardj2d94c112002-06-03 01:25:54 +0000416 my_assert(detached == 0 || detached == 1);
sewardj20917d82002-05-28 01:36:45 +0000417
418 if (detached) {
419 /* Detached; I just quit right now. */
420 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
421 VG_USERREQ__QUIT, 0, 0, 0, 0);
422 } else {
423 /* Not detached; so I wait for a joiner. */
424 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
425 VG_USERREQ__WAIT_JOINER, ret_val, 0, 0, 0);
426 }
427 /* NOTREACHED */
428 barf("thread_exit_wrapper: still alive?!");
429}
430
431
432/* This function is a wrapper function for running a thread. It runs
433 the root function specified in pthread_create, and then, should the
434 root function return a value, it arranges to run the thread's
435 cleanup handlers and exit correctly. */
436
437/* Struct used to convey info from pthread_create to
438 thread_wrapper. */
439typedef
440 struct {
441 pthread_attr_t* attr;
442 void* (*root_fn) ( void* );
443 void* arg;
444 }
445 NewThreadInfo;
446
447
448/* This is passed to the VG_USERREQ__APPLY_IN_NEW_THREAD and so must
449 not return. Note that this runs in the new thread, not the
450 parent. */
451static
452__attribute__((noreturn))
453void thread_wrapper ( NewThreadInfo* info )
454{
455 int res;
456 pthread_attr_t* attr;
457 void* (*root_fn) ( void* );
458 void* arg;
459 void* ret_val;
460
461 attr = info->attr;
462 root_fn = info->root_fn;
463 arg = info->arg;
464
sewardj20917d82002-05-28 01:36:45 +0000465 /* Free up the arg block that pthread_create malloced. */
466 VALGRIND_MAGIC_SEQUENCE(res, (-1) /* default */,
467 VG_USERREQ__FREE, info, 0, 0, 0);
sewardj2d94c112002-06-03 01:25:54 +0000468 my_assert(res == 0);
sewardj20917d82002-05-28 01:36:45 +0000469
sewardj7989d0c2002-05-28 11:00:01 +0000470 /* Minimally observe the attributes supplied. */
471 if (attr) {
sewardj2d94c112002-06-03 01:25:54 +0000472 my_assert(attr->__detachstate == PTHREAD_CREATE_DETACHED
sewardj7989d0c2002-05-28 11:00:01 +0000473 || attr->__detachstate == PTHREAD_CREATE_JOINABLE);
474 if (attr->__detachstate == PTHREAD_CREATE_DETACHED)
475 pthread_detach(pthread_self());
476 }
477
sewardj20917d82002-05-28 01:36:45 +0000478 /* The root function might not return. But if it does we simply
479 move along to thread_exit_wrapper. All other ways out for the
480 thread (cancellation, or calling pthread_exit) lead there
481 too. */
482 ret_val = root_fn(arg);
483 thread_exit_wrapper(ret_val);
484 /* NOTREACHED */
485}
486
487
sewardjf8f819e2002-04-17 23:21:37 +0000488/* ---------------------------------------------------
489 THREADs
490 ------------------------------------------------ */
491
sewardjff42d1d2002-05-22 13:17:31 +0000492__attribute__((weak))
493int pthread_yield ( void )
494{
495 int res;
496 ensure_valgrind("pthread_yield");
497 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
498 VG_USERREQ__PTHREAD_YIELD, 0, 0, 0, 0);
499 return 0;
500}
501
502
sewardj6072c362002-04-19 14:40:57 +0000503int pthread_equal(pthread_t thread1, pthread_t thread2)
504{
505 return thread1 == thread2 ? 1 : 0;
506}
507
508
sewardj20917d82002-05-28 01:36:45 +0000509/* Bundle up the args into a malloc'd block and create a new thread
510 consisting of thread_wrapper() applied to said malloc'd block. */
sewardje663cb92002-04-12 10:26:32 +0000511int
512pthread_create (pthread_t *__restrict __thread,
513 __const pthread_attr_t *__restrict __attr,
514 void *(*__start_routine) (void *),
515 void *__restrict __arg)
516{
sewardj20917d82002-05-28 01:36:45 +0000517 int tid_child;
518 NewThreadInfo* info;
sewardje663cb92002-04-12 10:26:32 +0000519
sewardj20917d82002-05-28 01:36:45 +0000520 ensure_valgrind("pthread_create");
521
522 /* Allocate space for the arg block. thread_wrapper will free
523 it. */
524 VALGRIND_MAGIC_SEQUENCE(info, NULL /* default */,
525 VG_USERREQ__MALLOC,
526 sizeof(NewThreadInfo), 0, 0, 0);
sewardj2d94c112002-06-03 01:25:54 +0000527 my_assert(info != NULL);
sewardj20917d82002-05-28 01:36:45 +0000528
529 info->attr = (pthread_attr_t*)__attr;
530 info->root_fn = __start_routine;
531 info->arg = __arg;
532 VALGRIND_MAGIC_SEQUENCE(tid_child, VG_INVALID_THREADID /* default */,
533 VG_USERREQ__APPLY_IN_NEW_THREAD,
534 &thread_wrapper, info, 0, 0);
sewardj2d94c112002-06-03 01:25:54 +0000535 my_assert(tid_child != VG_INVALID_THREADID);
sewardj20917d82002-05-28 01:36:45 +0000536
537 if (__thread)
538 *__thread = tid_child;
539 return 0; /* success */
540}
sewardje663cb92002-04-12 10:26:32 +0000541
542
543int
544pthread_join (pthread_t __th, void **__thread_return)
545{
546 int res;
547 ensure_valgrind("pthread_join");
548 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
549 VG_USERREQ__PTHREAD_JOIN,
550 __th, __thread_return, 0, 0);
551 return res;
552}
553
554
sewardj3b5d8862002-04-20 13:53:23 +0000555void pthread_exit(void *retval)
556{
sewardj3b5d8862002-04-20 13:53:23 +0000557 ensure_valgrind("pthread_exit");
sewardj20917d82002-05-28 01:36:45 +0000558 /* Simple! */
559 thread_exit_wrapper(retval);
sewardj3b5d8862002-04-20 13:53:23 +0000560}
561
sewardje663cb92002-04-12 10:26:32 +0000562
sewardj3b13f0e2002-04-25 20:17:29 +0000563pthread_t pthread_self(void)
sewardje663cb92002-04-12 10:26:32 +0000564{
565 int tid;
sewardj3b13f0e2002-04-25 20:17:29 +0000566 ensure_valgrind("pthread_self");
sewardj439d45e2002-05-03 20:43:10 +0000567 VALGRIND_MAGIC_SEQUENCE(tid, 1 /* default */,
sewardje663cb92002-04-12 10:26:32 +0000568 VG_USERREQ__PTHREAD_GET_THREADID,
569 0, 0, 0, 0);
sewardj439d45e2002-05-03 20:43:10 +0000570 if (tid < 1 || tid >= VG_N_THREADS)
sewardj3b13f0e2002-04-25 20:17:29 +0000571 barf("pthread_self: invalid ThreadId");
572 return tid;
sewardje663cb92002-04-12 10:26:32 +0000573}
574
575
sewardj853f55d2002-04-26 00:27:53 +0000576int pthread_detach(pthread_t th)
577{
sewardj20917d82002-05-28 01:36:45 +0000578 int res;
579 ensure_valgrind("pthread_detach");
sewardj7989d0c2002-05-28 11:00:01 +0000580 /* First we enquire as to the current detach state. */
581 VALGRIND_MAGIC_SEQUENCE(res, (-2) /* default */,
sewardj20917d82002-05-28 01:36:45 +0000582 VG_USERREQ__SET_OR_GET_DETACH,
sewardj7989d0c2002-05-28 11:00:01 +0000583 2 /* get */, th, 0, 0);
584 if (res == -1) /* not found */
585 return ESRCH;
586 if (res == 1) /* already detached */
587 return EINVAL;
588 if (res == 0) {
589 VALGRIND_MAGIC_SEQUENCE(res, (-2) /* default */,
590 VG_USERREQ__SET_OR_GET_DETACH,
591 1 /* set */, th, 0, 0);
sewardj2d94c112002-06-03 01:25:54 +0000592 my_assert(res == 0);
sewardj7989d0c2002-05-28 11:00:01 +0000593 return 0;
594 }
595 barf("pthread_detach");
sewardj853f55d2002-04-26 00:27:53 +0000596}
597
598
sewardjf8f819e2002-04-17 23:21:37 +0000599/* ---------------------------------------------------
sewardj8ad94e12002-05-29 00:10:20 +0000600 CLEANUP STACKS
601 ------------------------------------------------ */
602
603void _pthread_cleanup_push (struct _pthread_cleanup_buffer *__buffer,
604 void (*__routine) (void *),
605 void *__arg)
606{
607 int res;
608 CleanupEntry cu;
609 ensure_valgrind("_pthread_cleanup_push");
610 cu.fn = __routine;
611 cu.arg = __arg;
612 VALGRIND_MAGIC_SEQUENCE(res, (-1) /* default */,
613 VG_USERREQ__CLEANUP_PUSH,
614 &cu, 0, 0, 0);
sewardj2d94c112002-06-03 01:25:54 +0000615 my_assert(res == 0);
sewardj8ad94e12002-05-29 00:10:20 +0000616}
617
618
619void _pthread_cleanup_push_defer (struct _pthread_cleanup_buffer *__buffer,
620 void (*__routine) (void *),
621 void *__arg)
622{
623 /* As _pthread_cleanup_push, but first save the thread's original
624 cancellation type in __buffer and set it to Deferred. */
625 int orig_ctype;
626 ensure_valgrind("_pthread_cleanup_push_defer");
627 /* Set to Deferred, and put the old cancellation type in res. */
sewardj2d94c112002-06-03 01:25:54 +0000628 my_assert(-1 != PTHREAD_CANCEL_DEFERRED);
629 my_assert(-1 != PTHREAD_CANCEL_ASYNCHRONOUS);
630 my_assert(sizeof(struct _pthread_cleanup_buffer) >= sizeof(int));
sewardj8ad94e12002-05-29 00:10:20 +0000631 VALGRIND_MAGIC_SEQUENCE(orig_ctype, (-1) /* default */,
632 VG_USERREQ__SET_CANCELTYPE,
633 PTHREAD_CANCEL_DEFERRED, 0, 0, 0);
sewardj2d94c112002-06-03 01:25:54 +0000634 my_assert(orig_ctype != -1);
sewardj8ad94e12002-05-29 00:10:20 +0000635 *((int*)(__buffer)) = orig_ctype;
636 /* Now push the cleanup. */
637 _pthread_cleanup_push(NULL, __routine, __arg);
638}
639
640
641void _pthread_cleanup_pop (struct _pthread_cleanup_buffer *__buffer,
642 int __execute)
643{
644 int res;
645 CleanupEntry cu;
646 ensure_valgrind("_pthread_cleanup_push");
647 cu.fn = cu.arg = NULL; /* paranoia */
648 VALGRIND_MAGIC_SEQUENCE(res, (-1) /* default */,
649 VG_USERREQ__CLEANUP_POP,
650 &cu, 0, 0, 0);
651 if (res == 0) {
652 /* pop succeeded */
653 if (__execute) {
654 cu.fn ( cu.arg );
655 }
656 return;
657 }
658 if (res == -1) {
659 /* stack underflow */
660 return;
661 }
662 barf("_pthread_cleanup_pop");
663}
664
665
666void _pthread_cleanup_pop_restore (struct _pthread_cleanup_buffer *__buffer,
667 int __execute)
668{
669 int orig_ctype, fake_ctype;
670 /* As _pthread_cleanup_pop, but after popping/running the handler,
671 restore the thread's original cancellation type from the first
672 word of __buffer. */
673 _pthread_cleanup_pop(NULL, __execute);
674 orig_ctype = *((int*)(__buffer));
sewardj2d94c112002-06-03 01:25:54 +0000675 my_assert(orig_ctype == PTHREAD_CANCEL_DEFERRED
sewardj8ad94e12002-05-29 00:10:20 +0000676 || orig_ctype == PTHREAD_CANCEL_ASYNCHRONOUS);
sewardj2d94c112002-06-03 01:25:54 +0000677 my_assert(-1 != PTHREAD_CANCEL_DEFERRED);
678 my_assert(-1 != PTHREAD_CANCEL_ASYNCHRONOUS);
679 my_assert(sizeof(struct _pthread_cleanup_buffer) >= sizeof(int));
sewardj8ad94e12002-05-29 00:10:20 +0000680 VALGRIND_MAGIC_SEQUENCE(fake_ctype, (-1) /* default */,
681 VG_USERREQ__SET_CANCELTYPE,
682 orig_ctype, 0, 0, 0);
sewardj2d94c112002-06-03 01:25:54 +0000683 my_assert(fake_ctype == PTHREAD_CANCEL_DEFERRED);
sewardj8ad94e12002-05-29 00:10:20 +0000684}
685
686
687/* ---------------------------------------------------
sewardjf8f819e2002-04-17 23:21:37 +0000688 MUTEX ATTRIBUTES
689 ------------------------------------------------ */
690
sewardj5905fae2002-04-26 13:25:00 +0000691int __pthread_mutexattr_init(pthread_mutexattr_t *attr)
sewardje663cb92002-04-12 10:26:32 +0000692{
sewardjf8f819e2002-04-17 23:21:37 +0000693 attr->__mutexkind = PTHREAD_MUTEX_ERRORCHECK_NP;
sewardj8937c812002-04-12 20:12:20 +0000694 return 0;
sewardje663cb92002-04-12 10:26:32 +0000695}
696
sewardj5905fae2002-04-26 13:25:00 +0000697int __pthread_mutexattr_settype(pthread_mutexattr_t *attr, int type)
sewardjf8f819e2002-04-17 23:21:37 +0000698{
699 switch (type) {
sewardj3b13f0e2002-04-25 20:17:29 +0000700# ifndef GLIBC_2_1
sewardjf8f819e2002-04-17 23:21:37 +0000701 case PTHREAD_MUTEX_TIMED_NP:
sewardj2a1dcce2002-04-22 12:45:25 +0000702 case PTHREAD_MUTEX_ADAPTIVE_NP:
sewardj3b13f0e2002-04-25 20:17:29 +0000703# endif
sewardja1679dd2002-05-10 22:31:40 +0000704# ifdef GLIBC_2_1
sewardj68b2dd92002-05-10 21:03:56 +0000705 case PTHREAD_MUTEX_FAST_NP:
sewardja1679dd2002-05-10 22:31:40 +0000706# endif
sewardjf8f819e2002-04-17 23:21:37 +0000707 case PTHREAD_MUTEX_RECURSIVE_NP:
708 case PTHREAD_MUTEX_ERRORCHECK_NP:
sewardjf8f819e2002-04-17 23:21:37 +0000709 attr->__mutexkind = type;
710 return 0;
711 default:
712 return EINVAL;
713 }
714}
715
sewardj5905fae2002-04-26 13:25:00 +0000716int __pthread_mutexattr_destroy(pthread_mutexattr_t *attr)
sewardjf8f819e2002-04-17 23:21:37 +0000717{
718 return 0;
719}
720
721
722/* ---------------------------------------------------
723 MUTEXes
724 ------------------------------------------------ */
725
sewardj5905fae2002-04-26 13:25:00 +0000726int __pthread_mutex_init(pthread_mutex_t *mutex,
727 const pthread_mutexattr_t *mutexattr)
sewardje663cb92002-04-12 10:26:32 +0000728{
sewardj604ec3c2002-04-18 22:38:41 +0000729 mutex->__m_count = 0;
730 mutex->__m_owner = (_pthread_descr)VG_INVALID_THREADID;
731 mutex->__m_kind = PTHREAD_MUTEX_ERRORCHECK_NP;
732 if (mutexattr)
733 mutex->__m_kind = mutexattr->__mutexkind;
734 return 0;
sewardje663cb92002-04-12 10:26:32 +0000735}
736
sewardj439d45e2002-05-03 20:43:10 +0000737
sewardj5905fae2002-04-26 13:25:00 +0000738int __pthread_mutex_lock(pthread_mutex_t *mutex)
sewardje663cb92002-04-12 10:26:32 +0000739{
740 int res;
sewardj436e0582002-04-26 14:31:40 +0000741 static int moans = N_MOANS;
sewardj439d45e2002-05-03 20:43:10 +0000742 if (RUNNING_ON_VALGRIND) {
sewardje663cb92002-04-12 10:26:32 +0000743 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
744 VG_USERREQ__PTHREAD_MUTEX_LOCK,
745 mutex, 0, 0, 0);
746 return res;
sewardj439d45e2002-05-03 20:43:10 +0000747 } else {
748 if (moans-- > 0)
749 not_inside("pthread_mutex_lock");
750 return 0; /* success */
sewardje663cb92002-04-12 10:26:32 +0000751 }
752}
753
sewardj439d45e2002-05-03 20:43:10 +0000754
sewardj5905fae2002-04-26 13:25:00 +0000755int __pthread_mutex_trylock(pthread_mutex_t *mutex)
sewardj30671ff2002-04-21 00:13:57 +0000756{
757 int res;
sewardj436e0582002-04-26 14:31:40 +0000758 static int moans = N_MOANS;
sewardj439d45e2002-05-03 20:43:10 +0000759 if (RUNNING_ON_VALGRIND) {
sewardj30671ff2002-04-21 00:13:57 +0000760 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
761 VG_USERREQ__PTHREAD_MUTEX_TRYLOCK,
762 mutex, 0, 0, 0);
763 return res;
sewardj439d45e2002-05-03 20:43:10 +0000764 } else {
765 if (moans-- > 0)
766 not_inside("pthread_mutex_trylock");
767 return 0;
sewardj30671ff2002-04-21 00:13:57 +0000768 }
769}
770
sewardj439d45e2002-05-03 20:43:10 +0000771
sewardj5905fae2002-04-26 13:25:00 +0000772int __pthread_mutex_unlock(pthread_mutex_t *mutex)
sewardje663cb92002-04-12 10:26:32 +0000773{
774 int res;
sewardj436e0582002-04-26 14:31:40 +0000775 static int moans = N_MOANS;
sewardj439d45e2002-05-03 20:43:10 +0000776 if (RUNNING_ON_VALGRIND) {
sewardje663cb92002-04-12 10:26:32 +0000777 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
778 VG_USERREQ__PTHREAD_MUTEX_UNLOCK,
779 mutex, 0, 0, 0);
780 return res;
sewardj439d45e2002-05-03 20:43:10 +0000781 } else {
782 if (moans-- > 0)
783 not_inside("pthread_mutex_unlock");
784 return 0;
sewardje663cb92002-04-12 10:26:32 +0000785 }
786}
787
sewardj439d45e2002-05-03 20:43:10 +0000788
sewardj5905fae2002-04-26 13:25:00 +0000789int __pthread_mutex_destroy(pthread_mutex_t *mutex)
sewardje663cb92002-04-12 10:26:32 +0000790{
sewardj604ec3c2002-04-18 22:38:41 +0000791 /* Valgrind doesn't hold any resources on behalf of the mutex, so no
792 need to involve it. */
793 if (mutex->__m_count > 0)
794 return EBUSY;
sewardj6072c362002-04-19 14:40:57 +0000795 mutex->__m_count = 0;
796 mutex->__m_owner = (_pthread_descr)VG_INVALID_THREADID;
797 mutex->__m_kind = PTHREAD_MUTEX_ERRORCHECK_NP;
sewardj604ec3c2002-04-18 22:38:41 +0000798 return 0;
sewardje663cb92002-04-12 10:26:32 +0000799}
800
801
sewardjf8f819e2002-04-17 23:21:37 +0000802/* ---------------------------------------------------
sewardj6072c362002-04-19 14:40:57 +0000803 CONDITION VARIABLES
804 ------------------------------------------------ */
805
806/* LinuxThreads supports no attributes for conditions. Hence ... */
807
808int pthread_condattr_init(pthread_condattr_t *attr)
809{
810 return 0;
811}
812
sewardj0738a592002-04-20 13:59:33 +0000813int pthread_condattr_destroy(pthread_condattr_t *attr)
814{
815 return 0;
816}
sewardj6072c362002-04-19 14:40:57 +0000817
818int pthread_cond_init( pthread_cond_t *cond,
819 const pthread_condattr_t *cond_attr)
820{
821 cond->__c_waiting = (_pthread_descr)VG_INVALID_THREADID;
822 return 0;
823}
824
sewardjf854f472002-04-21 12:19:41 +0000825int pthread_cond_destroy(pthread_cond_t *cond)
826{
827 /* should check that no threads are waiting on this CV */
sewardj436e0582002-04-26 14:31:40 +0000828 static int moans = N_MOANS;
829 if (moans-- > 0)
830 kludged("pthread_cond_destroy");
sewardjf854f472002-04-21 12:19:41 +0000831 return 0;
832}
sewardj6072c362002-04-19 14:40:57 +0000833
834/* ---------------------------------------------------
835 SCHEDULING
836 ------------------------------------------------ */
837
838/* This is completely bogus. */
839int pthread_getschedparam(pthread_t target_thread,
840 int *policy,
841 struct sched_param *param)
842{
sewardj436e0582002-04-26 14:31:40 +0000843 static int moans = N_MOANS;
844 if (moans-- > 0)
845 kludged("pthread_getschedparam");
sewardj6072c362002-04-19 14:40:57 +0000846 if (policy) *policy = SCHED_OTHER;
sewardj3e909ce2002-06-03 13:27:15 +0000847# ifdef HAVE_SCHED_PRIORITY
sewardj2a1dcce2002-04-22 12:45:25 +0000848 if (param) param->sched_priority = 0; /* who knows */
849# else
sewardj6072c362002-04-19 14:40:57 +0000850 if (param) param->__sched_priority = 0; /* who knows */
sewardj2a1dcce2002-04-22 12:45:25 +0000851# endif
sewardj6072c362002-04-19 14:40:57 +0000852 return 0;
853}
854
855int pthread_setschedparam(pthread_t target_thread,
856 int policy,
857 const struct sched_param *param)
858{
sewardj436e0582002-04-26 14:31:40 +0000859 static int moans = N_MOANS;
860 if (moans-- > 0)
861 ignored("pthread_setschedparam");
sewardj6072c362002-04-19 14:40:57 +0000862 return 0;
863}
864
sewardj3b5d8862002-04-20 13:53:23 +0000865int pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex)
866{
867 int res;
868 ensure_valgrind("pthread_cond_wait");
869 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
870 VG_USERREQ__PTHREAD_COND_WAIT,
871 cond, mutex, 0, 0);
872 return res;
873}
874
sewardj5f07b662002-04-23 16:52:51 +0000875int pthread_cond_timedwait ( pthread_cond_t *cond,
876 pthread_mutex_t *mutex,
877 const struct timespec *abstime )
878{
879 int res;
880 unsigned int ms_now, ms_end;
881 struct timeval timeval_now;
882 unsigned long long int ull_ms_now_after_1970;
883 unsigned long long int ull_ms_end_after_1970;
884
885 ensure_valgrind("pthread_cond_timedwait");
886 VALGRIND_MAGIC_SEQUENCE(ms_now, 0xFFFFFFFF /* default */,
887 VG_USERREQ__READ_MILLISECOND_TIMER,
888 0, 0, 0, 0);
sewardj2d94c112002-06-03 01:25:54 +0000889 my_assert(ms_now != 0xFFFFFFFF);
sewardj5f07b662002-04-23 16:52:51 +0000890 res = gettimeofday(&timeval_now, NULL);
sewardj2d94c112002-06-03 01:25:54 +0000891 my_assert(res == 0);
sewardj5f07b662002-04-23 16:52:51 +0000892
893 ull_ms_now_after_1970
894 = 1000ULL * ((unsigned long long int)(timeval_now.tv_sec))
895 + ((unsigned long long int)(timeval_now.tv_usec / 1000000));
896 ull_ms_end_after_1970
897 = 1000ULL * ((unsigned long long int)(abstime->tv_sec))
898 + ((unsigned long long int)(abstime->tv_nsec / 1000000));
sewardjd8e919e2002-05-29 20:13:53 +0000899 if (ull_ms_end_after_1970 < ull_ms_now_after_1970)
900 ull_ms_end_after_1970 = ull_ms_now_after_1970;
sewardj5f07b662002-04-23 16:52:51 +0000901 ms_end
902 = ms_now + (unsigned int)(ull_ms_end_after_1970 - ull_ms_now_after_1970);
903 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
904 VG_USERREQ__PTHREAD_COND_TIMEDWAIT,
905 cond, mutex, ms_end, 0);
906 return res;
907}
908
909
sewardj3b5d8862002-04-20 13:53:23 +0000910int pthread_cond_signal(pthread_cond_t *cond)
911{
912 int res;
913 ensure_valgrind("pthread_cond_signal");
914 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
915 VG_USERREQ__PTHREAD_COND_SIGNAL,
916 cond, 0, 0, 0);
917 return res;
918}
919
920int pthread_cond_broadcast(pthread_cond_t *cond)
921{
922 int res;
923 ensure_valgrind("pthread_cond_broadcast");
924 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
925 VG_USERREQ__PTHREAD_COND_BROADCAST,
926 cond, 0, 0, 0);
927 return res;
928}
929
sewardj6072c362002-04-19 14:40:57 +0000930
931/* ---------------------------------------------------
sewardjf8f819e2002-04-17 23:21:37 +0000932 CANCELLATION
933 ------------------------------------------------ */
934
sewardj853f55d2002-04-26 00:27:53 +0000935int pthread_setcancelstate(int state, int *oldstate)
936{
sewardj20917d82002-05-28 01:36:45 +0000937 int res;
938 ensure_valgrind("pthread_setcancelstate");
939 if (state != PTHREAD_CANCEL_ENABLE
940 && state != PTHREAD_CANCEL_DISABLE)
941 return EINVAL;
sewardj2d94c112002-06-03 01:25:54 +0000942 my_assert(-1 != PTHREAD_CANCEL_ENABLE);
943 my_assert(-1 != PTHREAD_CANCEL_DISABLE);
sewardj20917d82002-05-28 01:36:45 +0000944 VALGRIND_MAGIC_SEQUENCE(res, (-1) /* default */,
945 VG_USERREQ__SET_CANCELSTATE,
946 state, 0, 0, 0);
sewardj2d94c112002-06-03 01:25:54 +0000947 my_assert(res != -1);
sewardj20917d82002-05-28 01:36:45 +0000948 if (oldstate)
949 *oldstate = res;
sewardj853f55d2002-04-26 00:27:53 +0000950 return 0;
951}
952
sewardje663cb92002-04-12 10:26:32 +0000953int pthread_setcanceltype(int type, int *oldtype)
954{
sewardj20917d82002-05-28 01:36:45 +0000955 int res;
956 ensure_valgrind("pthread_setcanceltype");
957 if (type != PTHREAD_CANCEL_DEFERRED
958 && type != PTHREAD_CANCEL_ASYNCHRONOUS)
959 return EINVAL;
sewardj2d94c112002-06-03 01:25:54 +0000960 my_assert(-1 != PTHREAD_CANCEL_DEFERRED);
961 my_assert(-1 != PTHREAD_CANCEL_ASYNCHRONOUS);
sewardj20917d82002-05-28 01:36:45 +0000962 VALGRIND_MAGIC_SEQUENCE(res, (-1) /* default */,
963 VG_USERREQ__SET_CANCELTYPE,
964 type, 0, 0, 0);
sewardj2d94c112002-06-03 01:25:54 +0000965 my_assert(res != -1);
sewardj20917d82002-05-28 01:36:45 +0000966 if (oldtype)
967 *oldtype = res;
sewardje663cb92002-04-12 10:26:32 +0000968 return 0;
969}
970
sewardje663cb92002-04-12 10:26:32 +0000971int pthread_cancel(pthread_t thread)
972{
973 int res;
974 ensure_valgrind("pthread_cancel");
sewardj20917d82002-05-28 01:36:45 +0000975 VALGRIND_MAGIC_SEQUENCE(res, (-1) /* default */,
976 VG_USERREQ__SET_CANCELPEND,
977 thread, &thread_exit_wrapper, 0, 0);
sewardj2d94c112002-06-03 01:25:54 +0000978 my_assert(res != -1);
sewardje663cb92002-04-12 10:26:32 +0000979 return res;
980}
981
sewardjd140e442002-05-29 01:21:19 +0000982static __inline__
983void __my_pthread_testcancel(void)
sewardj853f55d2002-04-26 00:27:53 +0000984{
sewardj20917d82002-05-28 01:36:45 +0000985 int res;
986 VALGRIND_MAGIC_SEQUENCE(res, (-1) /* default */,
987 VG_USERREQ__TESTCANCEL,
988 0, 0, 0, 0);
sewardj2d94c112002-06-03 01:25:54 +0000989 my_assert(res == 0);
sewardj853f55d2002-04-26 00:27:53 +0000990}
991
sewardjd140e442002-05-29 01:21:19 +0000992void pthread_testcancel ( void )
993{
994 __my_pthread_testcancel();
995}
996
sewardj20917d82002-05-28 01:36:45 +0000997
sewardjef037c72002-05-30 00:40:03 +0000998/* Not really sure what this is for. I suspect for doing the POSIX
999 requirements for fork() and exec(). We do this internally anyway
1000 whenever those syscalls are observed, so this could be superfluous,
1001 but hey ...
1002*/
sewardj853f55d2002-04-26 00:27:53 +00001003void __pthread_kill_other_threads_np ( void )
1004{
sewardjef037c72002-05-30 00:40:03 +00001005 int res;
1006 ensure_valgrind("__pthread_kill_other_threads_np");
1007 VALGRIND_MAGIC_SEQUENCE(res, (-1) /* default */,
1008 VG_USERREQ__NUKE_OTHER_THREADS,
1009 0, 0, 0, 0);
sewardj2d94c112002-06-03 01:25:54 +00001010 my_assert(res == 0);
sewardj853f55d2002-04-26 00:27:53 +00001011}
1012
sewardje663cb92002-04-12 10:26:32 +00001013
sewardjf8f819e2002-04-17 23:21:37 +00001014/* ---------------------------------------------------
sewardjb48e5002002-05-13 00:16:03 +00001015 SIGNALS
1016 ------------------------------------------------ */
1017
1018#include <signal.h>
1019
1020int pthread_sigmask(int how, const sigset_t *newmask,
1021 sigset_t *oldmask)
1022{
1023 int res;
1024
1025 /* A bit subtle, because the scheduler expects newmask and oldmask
1026 to be vki_sigset_t* rather than sigset_t*, and the two are
1027 different. Fortunately the first 64 bits of a sigset_t are
1028 exactly a vki_sigset_t, so we just pass the pointers through
1029 unmodified. Haaaack!
1030
1031 Also mash the how value so that the SIG_ constants from glibc
sewardj018f7622002-05-15 21:13:39 +00001032 constants to VKI_ constants, so that the former do not have to
1033 be included into vg_scheduler.c. */
sewardjb48e5002002-05-13 00:16:03 +00001034
1035 ensure_valgrind("pthread_sigmask");
1036
1037 switch (how) {
sewardj018f7622002-05-15 21:13:39 +00001038 case SIG_SETMASK: how = VKI_SIG_SETMASK; break;
1039 case SIG_BLOCK: how = VKI_SIG_BLOCK; break;
1040 case SIG_UNBLOCK: how = VKI_SIG_UNBLOCK; break;
sewardjb48e5002002-05-13 00:16:03 +00001041 default: return EINVAL;
1042 }
1043
1044 /* Crude check */
1045 if (newmask == NULL)
1046 return EFAULT;
1047
1048 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
1049 VG_USERREQ__PTHREAD_SIGMASK,
1050 how, newmask, oldmask, 0);
1051
1052 /* The scheduler tells us of any memory violations. */
1053 return res == 0 ? 0 : EFAULT;
1054}
1055
1056
1057int sigwait ( const sigset_t* set, int* sig )
1058{
1059 int res;
1060 ensure_valgrind("sigwait");
1061 /* As with pthread_sigmask we deliberately confuse sigset_t with
1062 vki_ksigset_t. */
1063 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
1064 VG_USERREQ__SIGWAIT,
1065 set, sig, 0, 0);
1066 return res;
1067}
1068
1069
sewardj018f7622002-05-15 21:13:39 +00001070int pthread_kill(pthread_t thread, int signo)
1071{
1072 int res;
1073 ensure_valgrind("pthread_kill");
1074 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
1075 VG_USERREQ__PTHREAD_KILL,
1076 thread, signo, 0, 0);
1077 return res;
1078}
1079
1080
sewardj3665ded2002-05-16 16:57:25 +00001081/* Copied verbatim from Linuxthreads */
1082/* Redefine raise() to send signal to calling thread only,
1083 as per POSIX 1003.1c */
1084int raise (int sig)
1085{
1086 int retcode = pthread_kill(pthread_self(), sig);
1087 if (retcode == 0)
1088 return 0;
1089 else {
1090 errno = retcode;
1091 return -1;
1092 }
1093}
1094
1095
sewardjb48e5002002-05-13 00:16:03 +00001096/* ---------------------------------------------------
sewardjf8f819e2002-04-17 23:21:37 +00001097 THREAD-SPECIFICs
1098 ------------------------------------------------ */
sewardj5e5fa512002-04-14 13:13:05 +00001099
sewardj5905fae2002-04-26 13:25:00 +00001100int __pthread_key_create(pthread_key_t *key,
1101 void (*destr_function) (void *))
sewardj5e5fa512002-04-14 13:13:05 +00001102{
sewardj5f07b662002-04-23 16:52:51 +00001103 int res;
1104 ensure_valgrind("pthread_key_create");
1105 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
1106 VG_USERREQ__PTHREAD_KEY_CREATE,
1107 key, destr_function, 0, 0);
1108 return res;
sewardj5e5fa512002-04-14 13:13:05 +00001109}
1110
1111int pthread_key_delete(pthread_key_t key)
1112{
sewardj436e0582002-04-26 14:31:40 +00001113 static int moans = N_MOANS;
1114 if (moans-- > 0)
1115 ignored("pthread_key_delete");
sewardj5e5fa512002-04-14 13:13:05 +00001116 return 0;
1117}
1118
sewardj5905fae2002-04-26 13:25:00 +00001119int __pthread_setspecific(pthread_key_t key, const void *pointer)
sewardj5e5fa512002-04-14 13:13:05 +00001120{
sewardj5f07b662002-04-23 16:52:51 +00001121 int res;
1122 ensure_valgrind("pthread_setspecific");
1123 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
1124 VG_USERREQ__PTHREAD_SETSPECIFIC,
1125 key, pointer, 0, 0);
1126 return res;
sewardj5e5fa512002-04-14 13:13:05 +00001127}
1128
sewardj5905fae2002-04-26 13:25:00 +00001129void * __pthread_getspecific(pthread_key_t key)
sewardj5e5fa512002-04-14 13:13:05 +00001130{
sewardj5f07b662002-04-23 16:52:51 +00001131 int res;
1132 ensure_valgrind("pthread_getspecific");
1133 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
1134 VG_USERREQ__PTHREAD_GETSPECIFIC,
1135 key, 0 , 0, 0);
1136 return (void*)res;
sewardj5e5fa512002-04-14 13:13:05 +00001137}
1138
sewardjf8f819e2002-04-17 23:21:37 +00001139
1140/* ---------------------------------------------------
sewardj89d3d852002-04-24 19:21:39 +00001141 ONCEry
1142 ------------------------------------------------ */
1143
1144static pthread_mutex_t once_masterlock = PTHREAD_MUTEX_INITIALIZER;
1145
1146
sewardj5905fae2002-04-26 13:25:00 +00001147int __pthread_once ( pthread_once_t *once_control,
1148 void (*init_routine) (void) )
sewardj89d3d852002-04-24 19:21:39 +00001149{
1150 int res;
1151 ensure_valgrind("pthread_once");
1152
sewardj68b2dd92002-05-10 21:03:56 +00001153 res = __pthread_mutex_lock(&once_masterlock);
sewardj89d3d852002-04-24 19:21:39 +00001154
sewardj68b2dd92002-05-10 21:03:56 +00001155 if (res != 0) {
1156 printf("res = %d\n",res);
sewardj89d3d852002-04-24 19:21:39 +00001157 barf("pthread_once: Looks like your program's "
1158 "init routine calls back to pthread_once() ?!");
sewardj68b2dd92002-05-10 21:03:56 +00001159 }
sewardj89d3d852002-04-24 19:21:39 +00001160
1161 if (*once_control == 0) {
1162 *once_control = 1;
1163 init_routine();
1164 }
1165
sewardj68b2dd92002-05-10 21:03:56 +00001166 __pthread_mutex_unlock(&once_masterlock);
sewardj89d3d852002-04-24 19:21:39 +00001167
1168 return 0;
1169}
1170
1171
1172/* ---------------------------------------------------
sewardj853f55d2002-04-26 00:27:53 +00001173 MISC
1174 ------------------------------------------------ */
1175
sewardj5905fae2002-04-26 13:25:00 +00001176int __pthread_atfork ( void (*prepare)(void),
1177 void (*parent)(void),
1178 void (*child)(void) )
sewardj853f55d2002-04-26 00:27:53 +00001179{
sewardjccef2e62002-05-29 19:26:32 +00001180 /* We have to do this properly or not at all; faking it isn't an
1181 option. */
1182 vgPlain_unimp("__pthread_atfork");
sewardj853f55d2002-04-26 00:27:53 +00001183}
1184
1185
sewardjbb990782002-05-08 02:01:14 +00001186__attribute__((weak))
1187void __pthread_initialize ( void )
1188{
sewardjbea1caa2002-05-10 23:20:58 +00001189 ensure_valgrind("__pthread_initialize");
sewardjbb990782002-05-08 02:01:14 +00001190}
1191
1192
sewardj853f55d2002-04-26 00:27:53 +00001193/* ---------------------------------------------------
sewardj3b13f0e2002-04-25 20:17:29 +00001194 LIBRARY-PRIVATE THREAD SPECIFIC STATE
sewardjf8f819e2002-04-17 23:21:37 +00001195 ------------------------------------------------ */
1196
sewardj3b13f0e2002-04-25 20:17:29 +00001197#include <resolv.h>
1198static int thread_specific_errno[VG_N_THREADS];
1199static int thread_specific_h_errno[VG_N_THREADS];
1200static struct __res_state
1201 thread_specific_res_state[VG_N_THREADS];
sewardjf8f819e2002-04-17 23:21:37 +00001202
sewardj3b13f0e2002-04-25 20:17:29 +00001203int* __errno_location ( void )
sewardjf8f819e2002-04-17 23:21:37 +00001204{
1205 int tid;
sewardj3b13f0e2002-04-25 20:17:29 +00001206 /* ensure_valgrind("__errno_location"); */
1207 VALGRIND_MAGIC_SEQUENCE(tid, 1 /* default */,
sewardjf8f819e2002-04-17 23:21:37 +00001208 VG_USERREQ__PTHREAD_GET_THREADID,
1209 0, 0, 0, 0);
sewardj3b13f0e2002-04-25 20:17:29 +00001210 /* 'cos I'm paranoid ... */
sewardj439d45e2002-05-03 20:43:10 +00001211 if (tid < 1 || tid >= VG_N_THREADS)
sewardj3b13f0e2002-04-25 20:17:29 +00001212 barf("__errno_location: invalid ThreadId");
1213 return & thread_specific_errno[tid];
1214}
1215
1216int* __h_errno_location ( void )
1217{
1218 int tid;
1219 /* ensure_valgrind("__h_errno_location"); */
1220 VALGRIND_MAGIC_SEQUENCE(tid, 1 /* default */,
1221 VG_USERREQ__PTHREAD_GET_THREADID,
1222 0, 0, 0, 0);
1223 /* 'cos I'm paranoid ... */
sewardj439d45e2002-05-03 20:43:10 +00001224 if (tid < 1 || tid >= VG_N_THREADS)
sewardj3b13f0e2002-04-25 20:17:29 +00001225 barf("__h_errno_location: invalid ThreadId");
1226 return & thread_specific_h_errno[tid];
1227}
1228
1229struct __res_state* __res_state ( void )
1230{
1231 int tid;
1232 /* ensure_valgrind("__res_state"); */
1233 VALGRIND_MAGIC_SEQUENCE(tid, 1 /* default */,
1234 VG_USERREQ__PTHREAD_GET_THREADID,
1235 0, 0, 0, 0);
1236 /* 'cos I'm paranoid ... */
sewardj439d45e2002-05-03 20:43:10 +00001237 if (tid < 1 || tid >= VG_N_THREADS)
sewardj3b13f0e2002-04-25 20:17:29 +00001238 barf("__res_state: invalid ThreadId");
1239 return & thread_specific_res_state[tid];
sewardjf8f819e2002-04-17 23:21:37 +00001240}
1241
1242
sewardj5716dbb2002-04-26 03:28:18 +00001243/* ---------------------------------------------------
1244 LIBC-PRIVATE SPECIFIC DATA
1245 ------------------------------------------------ */
1246
1247/* Relies on assumption that initial private data is NULL. This
1248 should be fixed somehow. */
1249
1250/* The allowable keys (indices) (all 2 of them).
1251 From sysdeps/pthread/bits/libc-tsd.h
1252*/
sewardj70adeb22002-04-27 01:35:38 +00001253#define N_LIBC_TSD_EXTRA_KEYS 1
1254
sewardj5716dbb2002-04-26 03:28:18 +00001255enum __libc_tsd_key_t { _LIBC_TSD_KEY_MALLOC = 0,
1256 _LIBC_TSD_KEY_DL_ERROR,
1257 _LIBC_TSD_KEY_N };
1258
1259/* Auto-initialising subsystem. libc_specifics_inited is set
1260 after initialisation. libc_specifics_inited_mx guards it. */
1261static int libc_specifics_inited = 0;
1262static pthread_mutex_t libc_specifics_inited_mx = PTHREAD_MUTEX_INITIALIZER;
1263
1264/* These are the keys we must initialise the first time. */
sewardj70adeb22002-04-27 01:35:38 +00001265static pthread_key_t libc_specifics_keys[_LIBC_TSD_KEY_N
1266 + N_LIBC_TSD_EXTRA_KEYS];
sewardj5716dbb2002-04-26 03:28:18 +00001267
1268/* Initialise the keys, if they are not already initialise. */
1269static
1270void init_libc_tsd_keys ( void )
1271{
1272 int res, i;
1273 pthread_key_t k;
1274
1275 res = pthread_mutex_lock(&libc_specifics_inited_mx);
1276 if (res != 0) barf("init_libc_tsd_keys: lock");
1277
1278 if (libc_specifics_inited == 0) {
1279 /* printf("INIT libc specifics\n"); */
1280 libc_specifics_inited = 1;
sewardj70adeb22002-04-27 01:35:38 +00001281 for (i = 0; i < _LIBC_TSD_KEY_N + N_LIBC_TSD_EXTRA_KEYS; i++) {
sewardj5716dbb2002-04-26 03:28:18 +00001282 res = pthread_key_create(&k, NULL);
1283 if (res != 0) barf("init_libc_tsd_keys: create");
1284 libc_specifics_keys[i] = k;
1285 }
1286 }
1287
1288 res = pthread_mutex_unlock(&libc_specifics_inited_mx);
1289 if (res != 0) barf("init_libc_tsd_keys: unlock");
1290}
1291
1292
1293static int
1294libc_internal_tsd_set ( enum __libc_tsd_key_t key,
1295 const void * pointer )
1296{
sewardj70adeb22002-04-27 01:35:38 +00001297 int res;
1298 static int moans = N_MOANS;
sewardj5716dbb2002-04-26 03:28:18 +00001299 /* printf("SET SET SET key %d ptr %p\n", key, pointer); */
sewardj70adeb22002-04-27 01:35:38 +00001300 if (key < _LIBC_TSD_KEY_MALLOC
1301 || key >= _LIBC_TSD_KEY_N + N_LIBC_TSD_EXTRA_KEYS)
sewardj5716dbb2002-04-26 03:28:18 +00001302 barf("libc_internal_tsd_set: invalid key");
sewardj70adeb22002-04-27 01:35:38 +00001303 if (key >= _LIBC_TSD_KEY_N && moans-- > 0)
1304 fprintf(stderr,
sewardj439d45e2002-05-03 20:43:10 +00001305 "valgrind's libpthread.so: libc_internal_tsd_set: "
1306 "dubious key %d\n", key);
sewardj5716dbb2002-04-26 03:28:18 +00001307 init_libc_tsd_keys();
1308 res = pthread_setspecific(libc_specifics_keys[key], pointer);
1309 if (res != 0) barf("libc_internal_tsd_set: setspecific failed");
1310 return 0;
1311}
1312
1313static void *
1314libc_internal_tsd_get ( enum __libc_tsd_key_t key )
1315{
sewardj70adeb22002-04-27 01:35:38 +00001316 void* v;
1317 static int moans = N_MOANS;
sewardj5716dbb2002-04-26 03:28:18 +00001318 /* printf("GET GET GET key %d\n", key); */
sewardj70adeb22002-04-27 01:35:38 +00001319 if (key < _LIBC_TSD_KEY_MALLOC
1320 || key >= _LIBC_TSD_KEY_N + N_LIBC_TSD_EXTRA_KEYS)
sewardj5716dbb2002-04-26 03:28:18 +00001321 barf("libc_internal_tsd_get: invalid key");
sewardj70adeb22002-04-27 01:35:38 +00001322 if (key >= _LIBC_TSD_KEY_N && moans-- > 0)
1323 fprintf(stderr,
sewardj439d45e2002-05-03 20:43:10 +00001324 "valgrind's libpthread.so: libc_internal_tsd_get: "
1325 "dubious key %d\n", key);
sewardj5716dbb2002-04-26 03:28:18 +00001326 init_libc_tsd_keys();
1327 v = pthread_getspecific(libc_specifics_keys[key]);
1328 /* if (v == NULL) barf("libc_internal_tsd_set: getspecific failed"); */
1329 return v;
1330}
1331
1332
1333
1334
sewardj70adeb22002-04-27 01:35:38 +00001335int (*__libc_internal_tsd_set)
1336 (enum __libc_tsd_key_t key, const void * pointer)
1337 = libc_internal_tsd_set;
sewardj5716dbb2002-04-26 03:28:18 +00001338
sewardj70adeb22002-04-27 01:35:38 +00001339void* (*__libc_internal_tsd_get)
1340 (enum __libc_tsd_key_t key)
1341 = libc_internal_tsd_get;
sewardj5716dbb2002-04-26 03:28:18 +00001342
1343
sewardje663cb92002-04-12 10:26:32 +00001344/* ---------------------------------------------------------------------
1345 These are here (I think) because they are deemed cancellation
1346 points by POSIX. For the moment we'll simply pass the call along
1347 to the corresponding thread-unaware (?) libc routine.
1348 ------------------------------------------------------------------ */
1349
sewardje663cb92002-04-12 10:26:32 +00001350#include <stdlib.h>
sewardje663cb92002-04-12 10:26:32 +00001351#include <sys/types.h>
1352#include <sys/socket.h>
1353
sewardjd529a442002-05-04 19:49:21 +00001354#ifdef GLIBC_2_1
1355extern
1356int __sigaction
1357 (int signum,
1358 const struct sigaction *act,
1359 struct sigaction *oldact);
1360#else
sewardje663cb92002-04-12 10:26:32 +00001361extern
1362int __libc_sigaction
1363 (int signum,
1364 const struct sigaction *act,
1365 struct sigaction *oldact);
sewardjd529a442002-05-04 19:49:21 +00001366#endif
sewardje663cb92002-04-12 10:26:32 +00001367int sigaction(int signum,
1368 const struct sigaction *act,
1369 struct sigaction *oldact)
1370{
sewardjd140e442002-05-29 01:21:19 +00001371 __my_pthread_testcancel();
sewardj2a1dcce2002-04-22 12:45:25 +00001372# ifdef GLIBC_2_1
1373 return __sigaction(signum, act, oldact);
1374# else
sewardj45b4b372002-04-16 22:50:32 +00001375 return __libc_sigaction(signum, act, oldact);
sewardj2a1dcce2002-04-22 12:45:25 +00001376# endif
sewardje663cb92002-04-12 10:26:32 +00001377}
1378
1379
1380extern
1381int __libc_connect(int sockfd,
1382 const struct sockaddr *serv_addr,
1383 socklen_t addrlen);
sewardj5905fae2002-04-26 13:25:00 +00001384__attribute__((weak))
sewardje663cb92002-04-12 10:26:32 +00001385int connect(int sockfd,
1386 const struct sockaddr *serv_addr,
1387 socklen_t addrlen)
1388{
sewardjd140e442002-05-29 01:21:19 +00001389 __my_pthread_testcancel();
sewardj45b4b372002-04-16 22:50:32 +00001390 return __libc_connect(sockfd, serv_addr, addrlen);
sewardje663cb92002-04-12 10:26:32 +00001391}
1392
1393
1394extern
1395int __libc_fcntl(int fd, int cmd, long arg);
sewardj5905fae2002-04-26 13:25:00 +00001396__attribute__((weak))
sewardje663cb92002-04-12 10:26:32 +00001397int fcntl(int fd, int cmd, long arg)
1398{
sewardjd140e442002-05-29 01:21:19 +00001399 __my_pthread_testcancel();
sewardj45b4b372002-04-16 22:50:32 +00001400 return __libc_fcntl(fd, cmd, arg);
sewardje663cb92002-04-12 10:26:32 +00001401}
1402
1403
1404extern
1405ssize_t __libc_write(int fd, const void *buf, size_t count);
sewardj5905fae2002-04-26 13:25:00 +00001406__attribute__((weak))
sewardje663cb92002-04-12 10:26:32 +00001407ssize_t write(int fd, const void *buf, size_t count)
1408{
sewardjd140e442002-05-29 01:21:19 +00001409 __my_pthread_testcancel();
sewardj45b4b372002-04-16 22:50:32 +00001410 return __libc_write(fd, buf, count);
sewardje663cb92002-04-12 10:26:32 +00001411}
1412
1413
1414extern
1415ssize_t __libc_read(int fd, void *buf, size_t count);
sewardj5905fae2002-04-26 13:25:00 +00001416__attribute__((weak))
sewardje663cb92002-04-12 10:26:32 +00001417ssize_t read(int fd, void *buf, size_t count)
1418{
sewardjd140e442002-05-29 01:21:19 +00001419 __my_pthread_testcancel();
sewardj45b4b372002-04-16 22:50:32 +00001420 return __libc_read(fd, buf, count);
sewardje663cb92002-04-12 10:26:32 +00001421}
1422
sewardjbe32e452002-04-24 20:29:58 +00001423
1424extern
sewardj853f55d2002-04-26 00:27:53 +00001425int __libc_open64(const char *pathname, int flags, mode_t mode);
sewardj5905fae2002-04-26 13:25:00 +00001426__attribute__((weak))
sewardj853f55d2002-04-26 00:27:53 +00001427int open64(const char *pathname, int flags, mode_t mode)
sewardjbe32e452002-04-24 20:29:58 +00001428{
sewardjd140e442002-05-29 01:21:19 +00001429 __my_pthread_testcancel();
sewardj853f55d2002-04-26 00:27:53 +00001430 return __libc_open64(pathname, flags, mode);
sewardjbe32e452002-04-24 20:29:58 +00001431}
1432
sewardje663cb92002-04-12 10:26:32 +00001433
1434extern
sewardj853f55d2002-04-26 00:27:53 +00001435int __libc_open(const char *pathname, int flags, mode_t mode);
sewardj5905fae2002-04-26 13:25:00 +00001436__attribute__((weak))
sewardj853f55d2002-04-26 00:27:53 +00001437int open(const char *pathname, int flags, mode_t mode)
sewardje663cb92002-04-12 10:26:32 +00001438{
sewardjd140e442002-05-29 01:21:19 +00001439 __my_pthread_testcancel();
sewardj853f55d2002-04-26 00:27:53 +00001440 return __libc_open(pathname, flags, mode);
sewardje663cb92002-04-12 10:26:32 +00001441}
1442
1443
1444extern
1445int __libc_close(int fd);
sewardj5905fae2002-04-26 13:25:00 +00001446__attribute__((weak))
sewardje663cb92002-04-12 10:26:32 +00001447int close(int fd)
1448{
sewardjd140e442002-05-29 01:21:19 +00001449 __my_pthread_testcancel();
sewardj45b4b372002-04-16 22:50:32 +00001450 return __libc_close(fd);
sewardje663cb92002-04-12 10:26:32 +00001451}
1452
1453
1454extern
1455int __libc_accept(int s, struct sockaddr *addr, socklen_t *addrlen);
sewardj5905fae2002-04-26 13:25:00 +00001456__attribute__((weak))
sewardje663cb92002-04-12 10:26:32 +00001457int accept(int s, struct sockaddr *addr, socklen_t *addrlen)
1458{
sewardjd140e442002-05-29 01:21:19 +00001459 __my_pthread_testcancel();
sewardj705d3cb2002-05-23 13:13:12 +00001460 wait_for_fd_to_be_readable_or_erring(s);
sewardjd140e442002-05-29 01:21:19 +00001461 __my_pthread_testcancel();
sewardj45b4b372002-04-16 22:50:32 +00001462 return __libc_accept(s, addr, addrlen);
sewardje663cb92002-04-12 10:26:32 +00001463}
1464
1465
1466extern
1467pid_t __libc_fork(void);
sewardj5905fae2002-04-26 13:25:00 +00001468pid_t __fork(void)
sewardje663cb92002-04-12 10:26:32 +00001469{
sewardjd140e442002-05-29 01:21:19 +00001470 __my_pthread_testcancel();
sewardj45b4b372002-04-16 22:50:32 +00001471 return __libc_fork();
sewardje663cb92002-04-12 10:26:32 +00001472}
1473
1474
1475extern
1476pid_t __libc_waitpid(pid_t pid, int *status, int options);
sewardj5905fae2002-04-26 13:25:00 +00001477__attribute__((weak))
sewardje663cb92002-04-12 10:26:32 +00001478pid_t waitpid(pid_t pid, int *status, int options)
1479{
sewardjd140e442002-05-29 01:21:19 +00001480 __my_pthread_testcancel();
sewardj45b4b372002-04-16 22:50:32 +00001481 return __libc_waitpid(pid, status, options);
sewardje663cb92002-04-12 10:26:32 +00001482}
1483
1484
1485extern
1486int __libc_nanosleep(const struct timespec *req, struct timespec *rem);
sewardj5905fae2002-04-26 13:25:00 +00001487__attribute__((weak))
sewardje663cb92002-04-12 10:26:32 +00001488int nanosleep(const struct timespec *req, struct timespec *rem)
1489{
sewardjd140e442002-05-29 01:21:19 +00001490 __my_pthread_testcancel();
sewardje663cb92002-04-12 10:26:32 +00001491 return __libc_nanosleep(req, rem);
1492}
1493
sewardjbe32e452002-04-24 20:29:58 +00001494
sewardje663cb92002-04-12 10:26:32 +00001495extern
1496int __libc_fsync(int fd);
sewardj5905fae2002-04-26 13:25:00 +00001497__attribute__((weak))
sewardje663cb92002-04-12 10:26:32 +00001498int fsync(int fd)
1499{
sewardjd140e442002-05-29 01:21:19 +00001500 __my_pthread_testcancel();
sewardj45b4b372002-04-16 22:50:32 +00001501 return __libc_fsync(fd);
sewardje663cb92002-04-12 10:26:32 +00001502}
1503
sewardjbe32e452002-04-24 20:29:58 +00001504
sewardj70c75362002-04-13 04:18:32 +00001505extern
1506off_t __libc_lseek(int fildes, off_t offset, int whence);
sewardj5905fae2002-04-26 13:25:00 +00001507__attribute__((weak))
sewardj70c75362002-04-13 04:18:32 +00001508off_t lseek(int fildes, off_t offset, int whence)
1509{
sewardjd140e442002-05-29 01:21:19 +00001510 __my_pthread_testcancel();
sewardj45b4b372002-04-16 22:50:32 +00001511 return __libc_lseek(fildes, offset, whence);
sewardj70c75362002-04-13 04:18:32 +00001512}
1513
sewardjbe32e452002-04-24 20:29:58 +00001514
1515extern
1516__off64_t __libc_lseek64(int fildes, __off64_t offset, int whence);
sewardj5905fae2002-04-26 13:25:00 +00001517__attribute__((weak))
sewardjbe32e452002-04-24 20:29:58 +00001518__off64_t lseek64(int fildes, __off64_t offset, int whence)
1519{
sewardjd140e442002-05-29 01:21:19 +00001520 __my_pthread_testcancel();
sewardjbe32e452002-04-24 20:29:58 +00001521 return __libc_lseek64(fildes, offset, whence);
1522}
1523
1524
sewardj726c4122002-05-16 23:39:10 +00001525extern
1526ssize_t __libc_pread64 (int __fd, void *__buf, size_t __nbytes,
1527 __off64_t __offset);
1528ssize_t __pread64 (int __fd, void *__buf, size_t __nbytes,
1529 __off64_t __offset)
1530{
sewardjd140e442002-05-29 01:21:19 +00001531 __my_pthread_testcancel();
sewardj726c4122002-05-16 23:39:10 +00001532 return __libc_pread64(__fd, __buf, __nbytes, __offset);
1533}
1534
1535
sewardja18e2102002-05-18 10:43:22 +00001536extern
1537ssize_t __libc_pwrite64 (int __fd, const void *__buf, size_t __nbytes,
1538 __off64_t __offset);
1539ssize_t __pwrite64 (int __fd, const void *__buf, size_t __nbytes,
1540 __off64_t __offset)
1541{
sewardjd140e442002-05-29 01:21:19 +00001542 __my_pthread_testcancel();
sewardja18e2102002-05-18 10:43:22 +00001543 return __libc_pwrite64(__fd, __buf, __nbytes, __offset);
1544}
1545
sewardj726c4122002-05-16 23:39:10 +00001546
sewardj39b93b12002-05-18 10:56:27 +00001547extern
1548ssize_t __libc_pwrite(int fd, const void *buf, size_t count, off_t offset);
1549__attribute__((weak))
1550ssize_t pwrite(int fd, const void *buf, size_t count, off_t offset)
1551{
sewardjd140e442002-05-29 01:21:19 +00001552 __my_pthread_testcancel();
sewardj39b93b12002-05-18 10:56:27 +00001553 return __libc_pwrite(fd, buf, count, offset);
1554}
1555
1556
1557extern
1558ssize_t __libc_pread(int fd, void *buf, size_t count, off_t offset);
1559__attribute__((weak))
1560ssize_t pread(int fd, void *buf, size_t count, off_t offset)
1561{
sewardjd140e442002-05-29 01:21:19 +00001562 __my_pthread_testcancel();
sewardj39b93b12002-05-18 10:56:27 +00001563 return __libc_pread(fd, buf, count, offset);
1564}
1565
1566
sewardj6af4b5d2002-04-16 04:40:49 +00001567extern
1568void __libc_longjmp(jmp_buf env, int val) __attribute((noreturn));
sewardj5905fae2002-04-26 13:25:00 +00001569/* not weak: __attribute__((weak)) */
sewardj6af4b5d2002-04-16 04:40:49 +00001570void longjmp(jmp_buf env, int val)
1571{
sewardjd140e442002-05-29 01:21:19 +00001572 __my_pthread_testcancel();
sewardj6af4b5d2002-04-16 04:40:49 +00001573 __libc_longjmp(env, val);
1574}
1575
sewardjbe32e452002-04-24 20:29:58 +00001576
sewardj6af4b5d2002-04-16 04:40:49 +00001577extern
1578int __libc_send(int s, const void *msg, size_t len, int flags);
sewardj5905fae2002-04-26 13:25:00 +00001579__attribute__((weak))
sewardj6af4b5d2002-04-16 04:40:49 +00001580int send(int s, const void *msg, size_t len, int flags)
1581{
sewardjd140e442002-05-29 01:21:19 +00001582 __my_pthread_testcancel();
sewardj6af4b5d2002-04-16 04:40:49 +00001583 return __libc_send(s, msg, len, flags);
1584}
1585
sewardjbe32e452002-04-24 20:29:58 +00001586
sewardj1e8cdc92002-04-18 11:37:52 +00001587extern
1588int __libc_recv(int s, void *buf, size_t len, int flags);
sewardj5905fae2002-04-26 13:25:00 +00001589__attribute__((weak))
sewardj1e8cdc92002-04-18 11:37:52 +00001590int recv(int s, void *buf, size_t len, int flags)
1591{
sewardjd140e442002-05-29 01:21:19 +00001592 __my_pthread_testcancel();
sewardj1e8cdc92002-04-18 11:37:52 +00001593 return __libc_recv(s, buf, len, flags);
1594}
1595
sewardjbe32e452002-04-24 20:29:58 +00001596
sewardj3665ded2002-05-16 16:57:25 +00001597extern
1598int __libc_sendmsg(int s, const struct msghdr *msg, int flags);
1599__attribute__((weak))
1600int sendmsg(int s, const struct msghdr *msg, int flags)
1601{
sewardjd140e442002-05-29 01:21:19 +00001602 __my_pthread_testcancel();
sewardj3665ded2002-05-16 16:57:25 +00001603 return __libc_sendmsg(s, msg, flags);
1604}
1605
1606
sewardj796d6a22002-04-24 02:28:34 +00001607extern
sewardj436e0582002-04-26 14:31:40 +00001608int __libc_recvfrom(int s, void *buf, size_t len, int flags,
1609 struct sockaddr *from, socklen_t *fromlen);
1610__attribute__((weak))
1611int recvfrom(int s, void *buf, size_t len, int flags,
1612 struct sockaddr *from, socklen_t *fromlen)
1613{
sewardjd140e442002-05-29 01:21:19 +00001614 __my_pthread_testcancel();
sewardj436e0582002-04-26 14:31:40 +00001615 return __libc_recvfrom(s, buf, len, flags, from, fromlen);
1616}
1617
1618
1619extern
sewardj796d6a22002-04-24 02:28:34 +00001620int __libc_sendto(int s, const void *msg, size_t len, int flags,
1621 const struct sockaddr *to, socklen_t tolen);
sewardj5905fae2002-04-26 13:25:00 +00001622__attribute__((weak))
sewardj796d6a22002-04-24 02:28:34 +00001623int sendto(int s, const void *msg, size_t len, int flags,
1624 const struct sockaddr *to, socklen_t tolen)
1625{
sewardjd140e442002-05-29 01:21:19 +00001626 __my_pthread_testcancel();
sewardj796d6a22002-04-24 02:28:34 +00001627 return __libc_sendto(s, msg, len, flags, to, tolen);
1628}
1629
sewardjbe32e452002-04-24 20:29:58 +00001630
sewardj369b1702002-04-24 13:28:15 +00001631extern
1632int __libc_system(const char* str);
sewardj5905fae2002-04-26 13:25:00 +00001633__attribute__((weak))
sewardj369b1702002-04-24 13:28:15 +00001634int system(const char* str)
1635{
sewardjd140e442002-05-29 01:21:19 +00001636 __my_pthread_testcancel();
sewardj369b1702002-04-24 13:28:15 +00001637 return __libc_system(str);
1638}
1639
sewardjbe32e452002-04-24 20:29:58 +00001640
sewardjab0b1c32002-04-24 19:26:47 +00001641extern
1642pid_t __libc_wait(int *status);
sewardj5905fae2002-04-26 13:25:00 +00001643__attribute__((weak))
sewardjab0b1c32002-04-24 19:26:47 +00001644pid_t wait(int *status)
1645{
sewardjd140e442002-05-29 01:21:19 +00001646 __my_pthread_testcancel();
sewardjab0b1c32002-04-24 19:26:47 +00001647 return __libc_wait(status);
1648}
1649
sewardj45b4b372002-04-16 22:50:32 +00001650
sewardj67f1d582002-05-24 02:11:32 +00001651extern
1652int __libc_msync(const void *start, size_t length, int flags);
1653__attribute__((weak))
1654int msync(const void *start, size_t length, int flags)
1655{
sewardjd140e442002-05-29 01:21:19 +00001656 __my_pthread_testcancel();
sewardj67f1d582002-05-24 02:11:32 +00001657 return __libc_msync(start, length, flags);
1658}
1659
sewardj5905fae2002-04-26 13:25:00 +00001660
sewardj3b13f0e2002-04-25 20:17:29 +00001661/* ---------------------------------------------------------------------
1662 Nonblocking implementations of select() and poll(). This stuff will
1663 surely rot your mind.
1664 ------------------------------------------------------------------ */
sewardje663cb92002-04-12 10:26:32 +00001665
sewardj08a4c3f2002-04-13 03:45:44 +00001666/*--------------------------------------------------*/
1667
1668#include "vg_kerneliface.h"
1669
1670static
1671__inline__
1672int is_kerror ( int res )
1673{
1674 if (res >= -4095 && res <= -1)
1675 return 1;
1676 else
1677 return 0;
1678}
1679
1680
1681static
1682int my_do_syscall1 ( int syscallno, int arg1 )
1683{
1684 int __res;
1685 __asm__ volatile ("pushl %%ebx; movl %%edx,%%ebx ; int $0x80 ; popl %%ebx"
1686 : "=a" (__res)
1687 : "0" (syscallno),
1688 "d" (arg1) );
1689 return __res;
1690}
1691
1692static
1693int my_do_syscall2 ( int syscallno,
sewardjf854f472002-04-21 12:19:41 +00001694 int arg1, int arg2 )
sewardj08a4c3f2002-04-13 03:45:44 +00001695{
1696 int __res;
1697 __asm__ volatile ("pushl %%ebx; movl %%edx,%%ebx ; int $0x80 ; popl %%ebx"
1698 : "=a" (__res)
1699 : "0" (syscallno),
1700 "d" (arg1),
1701 "c" (arg2) );
1702 return __res;
1703}
1704
1705static
sewardjf854f472002-04-21 12:19:41 +00001706int my_do_syscall3 ( int syscallno,
1707 int arg1, int arg2, int arg3 )
1708{
1709 int __res;
1710 __asm__ volatile ("pushl %%ebx; movl %%esi,%%ebx ; int $0x80 ; popl %%ebx"
1711 : "=a" (__res)
1712 : "0" (syscallno),
1713 "S" (arg1),
1714 "c" (arg2),
1715 "d" (arg3) );
1716 return __res;
1717}
1718
1719static
sewardj08a4c3f2002-04-13 03:45:44 +00001720int do_syscall_select( int n,
1721 vki_fd_set* readfds,
1722 vki_fd_set* writefds,
1723 vki_fd_set* exceptfds,
1724 struct vki_timeval * timeout )
1725{
1726 int res;
1727 int args[5];
1728 args[0] = n;
1729 args[1] = (int)readfds;
1730 args[2] = (int)writefds;
1731 args[3] = (int)exceptfds;
1732 args[4] = (int)timeout;
1733 res = my_do_syscall1(__NR_select, (int)(&(args[0])) );
sewardj02535bc2002-04-21 01:08:26 +00001734 return res;
sewardj08a4c3f2002-04-13 03:45:44 +00001735}
1736
1737
1738/* This is a wrapper round select(), which makes it thread-safe,
1739 meaning that only this thread will block, rather than the entire
1740 process. This wrapper in turn depends on nanosleep() not to block
1741 the entire process, but I think (hope? suspect?) that POSIX
1742 pthreads guarantees that to be the case.
1743
1744 Basic idea is: modify the timeout parameter to select so that it
1745 returns immediately. Poll like this until select returns non-zero,
1746 indicating something interesting happened, or until our time is up.
1747 Space out the polls with nanosleeps of say 20 milliseconds, which
1748 is required to be nonblocking; this allows other threads to run.
sewardj02535bc2002-04-21 01:08:26 +00001749
1750 Assumes:
sewardj2d94c112002-06-03 01:25:54 +00001751 * (checked via my_assert) types fd_set and vki_fd_set are identical.
1752 * (checked via my_assert) types timeval and vki_timeval are identical.
sewardj02535bc2002-04-21 01:08:26 +00001753 * (unchecked) libc error numbers (EINTR etc) are the negation of the
1754 kernel's error numbers (VKI_EINTR etc).
sewardj08a4c3f2002-04-13 03:45:44 +00001755*/
sewardj08a4c3f2002-04-13 03:45:44 +00001756
sewardj5905fae2002-04-26 13:25:00 +00001757/* __attribute__((weak)) */
sewardj08a4c3f2002-04-13 03:45:44 +00001758int select ( int n,
1759 fd_set *rfds,
1760 fd_set *wfds,
1761 fd_set *xfds,
1762 struct timeval *timeout )
1763{
sewardj5f07b662002-04-23 16:52:51 +00001764 unsigned int ms_now, ms_end;
sewardj08a4c3f2002-04-13 03:45:44 +00001765 int res;
1766 fd_set rfds_copy;
1767 fd_set wfds_copy;
1768 fd_set xfds_copy;
1769 struct vki_timeval t_now;
sewardj08a4c3f2002-04-13 03:45:44 +00001770 struct vki_timeval zero_timeout;
1771 struct vki_timespec nanosleep_interval;
1772
sewardjd140e442002-05-29 01:21:19 +00001773 __my_pthread_testcancel();
1774
sewardj5f07b662002-04-23 16:52:51 +00001775 /* gcc's complains about ms_end being used uninitialised -- classic
1776 case it can't understand, where ms_end is both defined and used
1777 only if timeout != NULL. Hence ... */
1778 ms_end = 0;
sewardj08a4c3f2002-04-13 03:45:44 +00001779
1780 /* We assume that the kernel and libc data layouts are identical
1781 for the following types. These asserts provide a crude
1782 check. */
1783 if (sizeof(fd_set) != sizeof(vki_fd_set)
1784 || sizeof(struct timeval) != sizeof(struct vki_timeval))
1785 barf("valgrind's hacky non-blocking select(): data sizes error");
1786
sewardj5f07b662002-04-23 16:52:51 +00001787 /* Detect the current time and simultaneously find out if we are
1788 running on Valgrind. */
1789 VALGRIND_MAGIC_SEQUENCE(ms_now, 0xFFFFFFFF /* default */,
1790 VG_USERREQ__READ_MILLISECOND_TIMER,
1791 0, 0, 0, 0);
1792
1793 /* If a zero timeout specified, this call is harmless. Also go
1794 this route if we're not running on Valgrind, for whatever
1795 reason. */
1796 if ( (timeout && timeout->tv_sec == 0 && timeout->tv_usec == 0)
1797 || (ms_now == 0xFFFFFFFF) ) {
sewardj02535bc2002-04-21 01:08:26 +00001798 res = do_syscall_select( n, (vki_fd_set*)rfds,
sewardj08a4c3f2002-04-13 03:45:44 +00001799 (vki_fd_set*)wfds,
1800 (vki_fd_set*)xfds,
1801 (struct vki_timeval*)timeout);
sewardj02535bc2002-04-21 01:08:26 +00001802 if (is_kerror(res)) {
1803 * (__errno_location()) = -res;
1804 return -1;
1805 } else {
1806 return res;
1807 }
1808 }
sewardj08a4c3f2002-04-13 03:45:44 +00001809
sewardj5f07b662002-04-23 16:52:51 +00001810 /* If a timeout was specified, set ms_end to be the end millisecond
1811 counter [wallclock] time. */
sewardj08a4c3f2002-04-13 03:45:44 +00001812 if (timeout) {
1813 res = my_do_syscall2(__NR_gettimeofday, (int)&t_now, (int)NULL);
sewardj2d94c112002-06-03 01:25:54 +00001814 my_assert(res == 0);
sewardj5f07b662002-04-23 16:52:51 +00001815 ms_end = ms_now;
1816 ms_end += (timeout->tv_usec / 1000);
1817 ms_end += (timeout->tv_sec * 1000);
sewardj08a4c3f2002-04-13 03:45:44 +00001818 /* Stay sane ... */
sewardj2d94c112002-06-03 01:25:54 +00001819 my_assert (ms_end >= ms_now);
sewardj08a4c3f2002-04-13 03:45:44 +00001820 }
1821
1822 /* fprintf(stderr, "MY_SELECT: before loop\n"); */
1823
1824 /* Either timeout == NULL, meaning wait indefinitely, or timeout !=
sewardj5f07b662002-04-23 16:52:51 +00001825 NULL, in which case ms_end holds the end time. */
sewardj08a4c3f2002-04-13 03:45:44 +00001826 while (1) {
1827 if (timeout) {
sewardj5f07b662002-04-23 16:52:51 +00001828 VALGRIND_MAGIC_SEQUENCE(ms_now, 0xFFFFFFFF /* default */,
1829 VG_USERREQ__READ_MILLISECOND_TIMER,
1830 0, 0, 0, 0);
sewardj2d94c112002-06-03 01:25:54 +00001831 my_assert(ms_now != 0xFFFFFFFF);
sewardj5f07b662002-04-23 16:52:51 +00001832 if (ms_now >= ms_end) {
sewardj08a4c3f2002-04-13 03:45:44 +00001833 /* timeout; nothing interesting happened. */
1834 if (rfds) FD_ZERO(rfds);
1835 if (wfds) FD_ZERO(wfds);
1836 if (xfds) FD_ZERO(xfds);
1837 return 0;
1838 }
1839 }
1840
1841 /* These could be trashed each time round the loop, so restore
1842 them each time. */
1843 if (rfds) rfds_copy = *rfds;
1844 if (wfds) wfds_copy = *wfds;
1845 if (xfds) xfds_copy = *xfds;
1846
1847 zero_timeout.tv_sec = zero_timeout.tv_usec = 0;
1848
1849 res = do_syscall_select( n,
1850 rfds ? (vki_fd_set*)(&rfds_copy) : NULL,
1851 wfds ? (vki_fd_set*)(&wfds_copy) : NULL,
1852 xfds ? (vki_fd_set*)(&xfds_copy) : NULL,
1853 & zero_timeout );
sewardj02535bc2002-04-21 01:08:26 +00001854 if (is_kerror(res)) {
1855 /* Some kind of error (including EINTR). Set errno and
sewardj08a4c3f2002-04-13 03:45:44 +00001856 return. The sets are unspecified in this case. */
sewardj02535bc2002-04-21 01:08:26 +00001857 * (__errno_location()) = -res;
1858 return -1;
sewardj08a4c3f2002-04-13 03:45:44 +00001859 }
1860 if (res > 0) {
1861 /* one or more fds is ready. Copy out resulting sets and
1862 return. */
1863 if (rfds) *rfds = rfds_copy;
1864 if (wfds) *wfds = wfds_copy;
1865 if (xfds) *xfds = xfds_copy;
1866 return res;
1867 }
1868 /* fprintf(stderr, "MY_SELECT: nanosleep\n"); */
1869 /* nanosleep and go round again */
sewardj02535bc2002-04-21 01:08:26 +00001870 nanosleep_interval.tv_sec = 0;
sewardj956cc1b2002-04-25 01:33:50 +00001871 nanosleep_interval.tv_nsec = 50 * 1000 * 1000; /* 50 milliseconds */
sewardjf854f472002-04-21 12:19:41 +00001872 /* It's critical here that valgrind's nanosleep implementation
1873 is nonblocking. */
1874 (void)my_do_syscall2(__NR_nanosleep,
1875 (int)(&nanosleep_interval), (int)NULL);
1876 }
1877}
1878
1879
1880
1881
1882#include <sys/poll.h>
1883
sewardj3e909ce2002-06-03 13:27:15 +00001884#ifndef HAVE_NFDS_T
sewardj72d58482002-04-24 02:20:20 +00001885typedef unsigned long int nfds_t;
1886#endif
1887
sewardj705d3cb2002-05-23 13:13:12 +00001888
sewardj5905fae2002-04-26 13:25:00 +00001889/* __attribute__((weak)) */
sewardjf854f472002-04-21 12:19:41 +00001890int poll (struct pollfd *__fds, nfds_t __nfds, int __timeout)
1891{
sewardj5f07b662002-04-23 16:52:51 +00001892 unsigned int ms_now, ms_end;
sewardjf854f472002-04-21 12:19:41 +00001893 int res, i;
sewardjf854f472002-04-21 12:19:41 +00001894 struct vki_timespec nanosleep_interval;
1895
sewardjd140e442002-05-29 01:21:19 +00001896 __my_pthread_testcancel();
sewardjf854f472002-04-21 12:19:41 +00001897 ensure_valgrind("poll");
1898
sewardj5f07b662002-04-23 16:52:51 +00001899 /* Detect the current time and simultaneously find out if we are
1900 running on Valgrind. */
1901 VALGRIND_MAGIC_SEQUENCE(ms_now, 0xFFFFFFFF /* default */,
1902 VG_USERREQ__READ_MILLISECOND_TIMER,
1903 0, 0, 0, 0);
1904
sewardjf854f472002-04-21 12:19:41 +00001905 if (/* CHECK SIZES FOR struct pollfd */
1906 sizeof(struct timeval) != sizeof(struct vki_timeval))
1907 barf("valgrind's hacky non-blocking poll(): data sizes error");
1908
sewardj5f07b662002-04-23 16:52:51 +00001909 /* dummy initialisation to keep gcc -Wall happy */
1910 ms_end = 0;
1911
1912 /* If a zero timeout specified, this call is harmless. Also do
1913 this if not running on Valgrind. */
1914 if (__timeout == 0 || ms_now == 0xFFFFFFFF) {
sewardjf854f472002-04-21 12:19:41 +00001915 res = my_do_syscall3(__NR_poll, (int)__fds, __nfds, __timeout);
1916 if (is_kerror(res)) {
1917 * (__errno_location()) = -res;
1918 return -1;
1919 } else {
1920 return res;
1921 }
1922 }
1923
sewardj5f07b662002-04-23 16:52:51 +00001924 /* If a timeout was specified, set ms_end to be the end wallclock
1925 time. Easy considering that __timeout is in milliseconds. */
sewardjf854f472002-04-21 12:19:41 +00001926 if (__timeout > 0) {
sewardj650ac002002-04-29 12:20:34 +00001927 ms_end = ms_now + (unsigned int)__timeout;
sewardjf854f472002-04-21 12:19:41 +00001928 }
1929
1930 /* fprintf(stderr, "MY_POLL: before loop\n"); */
1931
1932 /* Either timeout < 0, meaning wait indefinitely, or timeout > 0,
1933 in which case t_end holds the end time. */
sewardj2d94c112002-06-03 01:25:54 +00001934 my_assert(__timeout != 0);
sewardj5f07b662002-04-23 16:52:51 +00001935
sewardjf854f472002-04-21 12:19:41 +00001936 while (1) {
sewardjf854f472002-04-21 12:19:41 +00001937 if (__timeout > 0) {
sewardj5f07b662002-04-23 16:52:51 +00001938 VALGRIND_MAGIC_SEQUENCE(ms_now, 0xFFFFFFFF /* default */,
1939 VG_USERREQ__READ_MILLISECOND_TIMER,
1940 0, 0, 0, 0);
sewardj2d94c112002-06-03 01:25:54 +00001941 my_assert(ms_now != 0xFFFFFFFF);
sewardj5f07b662002-04-23 16:52:51 +00001942 if (ms_now >= ms_end) {
sewardjf854f472002-04-21 12:19:41 +00001943 /* timeout; nothing interesting happened. */
1944 for (i = 0; i < __nfds; i++)
1945 __fds[i].revents = 0;
1946 return 0;
1947 }
1948 }
1949
sewardj5f07b662002-04-23 16:52:51 +00001950 /* Do a return-immediately poll. */
sewardjf854f472002-04-21 12:19:41 +00001951 res = my_do_syscall3(__NR_poll, (int)__fds, __nfds, 0 );
1952 if (is_kerror(res)) {
1953 /* Some kind of error. Set errno and return. */
1954 * (__errno_location()) = -res;
1955 return -1;
1956 }
1957 if (res > 0) {
1958 /* One or more fds is ready. Return now. */
1959 return res;
1960 }
1961 /* fprintf(stderr, "MY_POLL: nanosleep\n"); */
1962 /* nanosleep and go round again */
1963 nanosleep_interval.tv_sec = 0;
sewardj956cc1b2002-04-25 01:33:50 +00001964 nanosleep_interval.tv_nsec = 51 * 1000 * 1000; /* 51 milliseconds */
sewardj08a4c3f2002-04-13 03:45:44 +00001965 /* It's critical here that valgrind's nanosleep implementation
1966 is nonblocking. */
1967 (void)my_do_syscall2(__NR_nanosleep,
1968 (int)(&nanosleep_interval), (int)NULL);
1969 }
1970}
sewardj3b13f0e2002-04-25 20:17:29 +00001971
1972
sewardj705d3cb2002-05-23 13:13:12 +00001973/* Helper function used to make accept() non-blocking. Idea is to use
1974 the above nonblocking poll() to make this thread ONLY wait for the
1975 specified fd to become ready, and then return. */
1976static void wait_for_fd_to_be_readable_or_erring ( int fd )
1977{
1978 struct pollfd pfd;
sewardj6e6cbaa2002-05-24 02:12:52 +00001979 /* fprintf(stderr, "wait_for_fd_to_be_readable_or_erring %d\n", fd); */
sewardj705d3cb2002-05-23 13:13:12 +00001980 pfd.fd = fd;
1981 pfd.events = POLLIN | POLLPRI | POLLERR | POLLHUP | POLLNVAL;
1982 /* ... but not POLLOUT, you may notice. */
1983 pfd.revents = 0;
1984 (void)poll(&pfd, 1, -1 /* forever */);
1985}
1986
1987
sewardj3b13f0e2002-04-25 20:17:29 +00001988/* ---------------------------------------------------------------------
sewardj8f253ff2002-05-19 00:13:34 +00001989 Hacky implementation of semaphores.
1990 ------------------------------------------------------------------ */
1991
1992#include <semaphore.h>
1993
1994/* This is a terrible way to do the remapping. Plan is to import an
1995 AVL tree at some point. */
sewardj8f253ff2002-05-19 00:13:34 +00001996
1997typedef
1998 struct {
1999 pthread_mutex_t se_mx;
2000 pthread_cond_t se_cv;
2001 int count;
2002 }
2003 vg_sem_t;
2004
2005static pthread_mutex_t se_remap_mx = PTHREAD_MUTEX_INITIALIZER;
2006
2007static int se_remap_used = 0;
2008static sem_t* se_remap_orig[VG_N_SEMAPHORES];
2009static vg_sem_t se_remap_new[VG_N_SEMAPHORES];
2010
2011static vg_sem_t* se_remap ( sem_t* orig )
2012{
2013 int res, i;
2014 res = __pthread_mutex_lock(&se_remap_mx);
sewardj2d94c112002-06-03 01:25:54 +00002015 my_assert(res == 0);
sewardj8f253ff2002-05-19 00:13:34 +00002016
2017 for (i = 0; i < se_remap_used; i++) {
2018 if (se_remap_orig[i] == orig)
2019 break;
2020 }
2021 if (i == se_remap_used) {
2022 if (se_remap_used == VG_N_SEMAPHORES) {
2023 res = pthread_mutex_unlock(&se_remap_mx);
sewardj2d94c112002-06-03 01:25:54 +00002024 my_assert(res == 0);
sewardja1ac5cb2002-05-27 13:00:05 +00002025 barf("VG_N_SEMAPHORES is too low. Increase and recompile.");
sewardj8f253ff2002-05-19 00:13:34 +00002026 }
2027 se_remap_used++;
2028 se_remap_orig[i] = orig;
2029 /* printf("allocated semaphore %d\n", i); */
2030 }
2031 res = __pthread_mutex_unlock(&se_remap_mx);
sewardj2d94c112002-06-03 01:25:54 +00002032 my_assert(res == 0);
sewardj8f253ff2002-05-19 00:13:34 +00002033 return &se_remap_new[i];
2034}
2035
2036
2037int sem_init(sem_t *sem, int pshared, unsigned int value)
2038{
2039 int res;
2040 vg_sem_t* vg_sem;
2041 ensure_valgrind("sem_init");
2042 if (pshared != 0) {
2043 errno = ENOSYS;
2044 return -1;
2045 }
2046 vg_sem = se_remap(sem);
2047 res = pthread_mutex_init(&vg_sem->se_mx, NULL);
sewardj2d94c112002-06-03 01:25:54 +00002048 my_assert(res == 0);
sewardj8f253ff2002-05-19 00:13:34 +00002049 res = pthread_cond_init(&vg_sem->se_cv, NULL);
sewardj2d94c112002-06-03 01:25:54 +00002050 my_assert(res == 0);
sewardj8f253ff2002-05-19 00:13:34 +00002051 vg_sem->count = value;
2052 return 0;
2053}
2054
2055
2056int sem_wait ( sem_t* sem )
2057{
2058 int res;
2059 vg_sem_t* vg_sem;
2060 ensure_valgrind("sem_wait");
2061 vg_sem = se_remap(sem);
2062 res = __pthread_mutex_lock(&vg_sem->se_mx);
sewardj2d94c112002-06-03 01:25:54 +00002063 my_assert(res == 0);
sewardj8f253ff2002-05-19 00:13:34 +00002064 while (vg_sem->count == 0) {
2065 res = pthread_cond_wait(&vg_sem->se_cv, &vg_sem->se_mx);
sewardj2d94c112002-06-03 01:25:54 +00002066 my_assert(res == 0);
sewardj8f253ff2002-05-19 00:13:34 +00002067 }
2068 vg_sem->count--;
2069 res = __pthread_mutex_unlock(&vg_sem->se_mx);
sewardj2d94c112002-06-03 01:25:54 +00002070 my_assert(res == 0);
sewardj8f253ff2002-05-19 00:13:34 +00002071 return 0;
2072}
2073
2074int sem_post ( sem_t* sem )
2075{
2076 int res;
2077 vg_sem_t* vg_sem;
2078 ensure_valgrind("sem_post");
2079 vg_sem = se_remap(sem);
2080 res = __pthread_mutex_lock(&vg_sem->se_mx);
sewardj2d94c112002-06-03 01:25:54 +00002081 my_assert(res == 0);
sewardj8f253ff2002-05-19 00:13:34 +00002082 if (vg_sem->count == 0) {
2083 vg_sem->count++;
2084 res = pthread_cond_broadcast(&vg_sem->se_cv);
sewardj2d94c112002-06-03 01:25:54 +00002085 my_assert(res == 0);
sewardj8f253ff2002-05-19 00:13:34 +00002086 } else {
2087 vg_sem->count++;
2088 }
2089 res = __pthread_mutex_unlock(&vg_sem->se_mx);
sewardj2d94c112002-06-03 01:25:54 +00002090 my_assert(res == 0);
sewardj8f253ff2002-05-19 00:13:34 +00002091 return 0;
2092}
2093
2094
2095int sem_trywait ( sem_t* sem )
2096{
2097 int ret, res;
2098 vg_sem_t* vg_sem;
2099 ensure_valgrind("sem_trywait");
2100 vg_sem = se_remap(sem);
2101 res = __pthread_mutex_lock(&vg_sem->se_mx);
sewardj2d94c112002-06-03 01:25:54 +00002102 my_assert(res == 0);
sewardj8f253ff2002-05-19 00:13:34 +00002103 if (vg_sem->count > 0) {
2104 vg_sem->count--;
2105 ret = 0;
2106 } else {
2107 ret = -1;
2108 errno = EAGAIN;
2109 }
2110 res = __pthread_mutex_unlock(&vg_sem->se_mx);
sewardj2d94c112002-06-03 01:25:54 +00002111 my_assert(res == 0);
sewardj8f253ff2002-05-19 00:13:34 +00002112 return ret;
2113}
2114
2115
2116int sem_getvalue(sem_t* sem, int * sval)
2117{
2118 vg_sem_t* vg_sem;
2119 ensure_valgrind("sem_trywait");
2120 vg_sem = se_remap(sem);
2121 *sval = vg_sem->count;
2122 return 0;
2123}
2124
2125
2126int sem_destroy(sem_t * sem)
2127{
2128 kludged("sem_destroy");
2129 /* if someone waiting on this semaphore, errno = EBUSY, return -1 */
2130 return 0;
2131}
2132
2133
2134/* ---------------------------------------------------------------------
sewardj2d8b3f02002-06-01 14:14:19 +00002135 Reader-writer locks.
sewardja1ac5cb2002-05-27 13:00:05 +00002136 ------------------------------------------------------------------ */
2137
sewardj2d8b3f02002-06-01 14:14:19 +00002138typedef
2139 struct {
2140 int initted; /* != 0 --> in use; sanity check only */
2141 int prefer_w; /* != 0 --> prefer writer */
2142 int nwait_r; /* # of waiting readers */
2143 int nwait_w; /* # of waiting writers */
2144 pthread_cond_t cv_r; /* for signalling readers */
2145 pthread_cond_t cv_w; /* for signalling writers */
2146 pthread_mutex_t mx;
2147 int status;
2148 /* allowed range for status: >= -1. -1 means 1 writer currently
2149 active, >= 0 means N readers currently active. */
2150 }
2151 vg_rwlock_t;
sewardja1ac5cb2002-05-27 13:00:05 +00002152
2153
2154static pthread_mutex_t rw_remap_mx = PTHREAD_MUTEX_INITIALIZER;
2155
2156static int rw_remap_used = 0;
2157static pthread_rwlock_t* rw_remap_orig[VG_N_RWLOCKS];
2158static vg_rwlock_t rw_remap_new[VG_N_RWLOCKS];
2159
sewardj2d8b3f02002-06-01 14:14:19 +00002160
2161static
2162void init_vg_rwlock ( vg_rwlock_t* vg_rwl )
2163{
2164 int res = 0;
2165 vg_rwl->initted = 1;
2166 vg_rwl->prefer_w = 1;
2167 vg_rwl->nwait_r = 0;
2168 vg_rwl->nwait_w = 0;
2169 vg_rwl->status = 0;
2170 res = pthread_mutex_init(&vg_rwl->mx, NULL);
2171 res |= pthread_cond_init(&vg_rwl->cv_r, NULL);
2172 res |= pthread_cond_init(&vg_rwl->cv_w, NULL);
sewardj2d94c112002-06-03 01:25:54 +00002173 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002174}
2175
2176
sewardja1ac5cb2002-05-27 13:00:05 +00002177/* Take the address of a LinuxThreads rwlock_t and return the shadow
2178 address of our version. Further, if the LinuxThreads version
2179 appears to have been statically initialised, do the same to the one
2180 we allocate here. The pthread_rwlock_t.__rw_readers field is set
2181 to zero by PTHREAD_RWLOCK_INITIALIZER, so we take zero as meaning
2182 uninitialised and non-zero meaning initialised.
2183*/
2184static vg_rwlock_t* rw_remap ( pthread_rwlock_t* orig )
2185{
2186 int res, i;
2187 vg_rwlock_t* vg_rwl;
2188 res = __pthread_mutex_lock(&rw_remap_mx);
sewardj2d94c112002-06-03 01:25:54 +00002189 my_assert(res == 0);
sewardja1ac5cb2002-05-27 13:00:05 +00002190
2191 for (i = 0; i < rw_remap_used; i++) {
2192 if (rw_remap_orig[i] == orig)
2193 break;
2194 }
2195 if (i == rw_remap_used) {
2196 if (rw_remap_used == VG_N_RWLOCKS) {
sewardj2d8b3f02002-06-01 14:14:19 +00002197 res = __pthread_mutex_unlock(&rw_remap_mx);
sewardj2d94c112002-06-03 01:25:54 +00002198 my_assert(res == 0);
sewardja1ac5cb2002-05-27 13:00:05 +00002199 barf("VG_N_RWLOCKS is too low. Increase and recompile.");
2200 }
2201 rw_remap_used++;
2202 rw_remap_orig[i] = orig;
sewardj2d8b3f02002-06-01 14:14:19 +00002203 rw_remap_new[i].initted = 0;
sewardja1ac5cb2002-05-27 13:00:05 +00002204 if (0) printf("allocated rwlock %d\n", i);
2205 }
2206 res = __pthread_mutex_unlock(&rw_remap_mx);
sewardj2d94c112002-06-03 01:25:54 +00002207 my_assert(res == 0);
sewardja1ac5cb2002-05-27 13:00:05 +00002208 vg_rwl = &rw_remap_new[i];
2209
sewardj2d8b3f02002-06-01 14:14:19 +00002210 /* Initialise the shadow, if required. */
sewardja1ac5cb2002-05-27 13:00:05 +00002211 if (orig->__rw_readers == 0) {
sewardja1ac5cb2002-05-27 13:00:05 +00002212 orig->__rw_readers = 1;
sewardj2d8b3f02002-06-01 14:14:19 +00002213 init_vg_rwlock(vg_rwl);
sewardja1ac5cb2002-05-27 13:00:05 +00002214 if (orig->__rw_kind == PTHREAD_RWLOCK_PREFER_READER_NP)
sewardj2d8b3f02002-06-01 14:14:19 +00002215 vg_rwl->prefer_w = 0;
sewardja1ac5cb2002-05-27 13:00:05 +00002216 }
2217
2218 return vg_rwl;
2219}
2220
2221
sewardja1ac5cb2002-05-27 13:00:05 +00002222int pthread_rwlock_init ( pthread_rwlock_t* orig,
2223 const pthread_rwlockattr_t* attr )
2224{
sewardja1ac5cb2002-05-27 13:00:05 +00002225 vg_rwlock_t* rwl;
2226 if (0) printf ("pthread_rwlock_init\n");
2227 /* Force the remapper to initialise the shadow. */
2228 orig->__rw_readers = 0;
2229 /* Install the lock preference; the remapper needs to know it. */
2230 orig->__rw_kind = PTHREAD_RWLOCK_DEFAULT_NP;
2231 if (attr)
2232 orig->__rw_kind = attr->__lockkind;
2233 rwl = rw_remap ( orig );
sewardj2d8b3f02002-06-01 14:14:19 +00002234 return 0;
sewardja1ac5cb2002-05-27 13:00:05 +00002235}
2236
sewardj2d8b3f02002-06-01 14:14:19 +00002237
2238static
2239void pthread_rwlock_rdlock_CANCEL_HDLR ( void* rwl_v )
sewardja1ac5cb2002-05-27 13:00:05 +00002240{
sewardj2d8b3f02002-06-01 14:14:19 +00002241 vg_rwlock_t* rwl = (vg_rwlock_t*)rwl_v;
2242 rwl->nwait_r--;
2243 pthread_mutex_unlock (&rwl->mx);
sewardja1ac5cb2002-05-27 13:00:05 +00002244}
2245
sewardj2d8b3f02002-06-01 14:14:19 +00002246
sewardja1ac5cb2002-05-27 13:00:05 +00002247int pthread_rwlock_rdlock ( pthread_rwlock_t* orig )
2248{
2249 int res;
2250 vg_rwlock_t* rwl;
2251 if (0) printf ("pthread_rwlock_rdlock\n");
2252 rwl = rw_remap ( orig );
sewardj2d8b3f02002-06-01 14:14:19 +00002253 res = __pthread_mutex_lock(&rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00002254 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002255 if (!rwl->initted) {
2256 res = __pthread_mutex_unlock(&rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00002257 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002258 return EINVAL;
2259 }
2260 if (rwl->status < 0) {
sewardj2d94c112002-06-03 01:25:54 +00002261 my_assert(rwl->status == -1);
sewardj2d8b3f02002-06-01 14:14:19 +00002262 rwl->nwait_r++;
2263 pthread_cleanup_push( pthread_rwlock_rdlock_CANCEL_HDLR, rwl );
2264 while (1) {
2265 if (rwl->status == 0) break;
2266 res = pthread_cond_wait(&rwl->cv_r, &rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00002267 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002268 }
2269 pthread_cleanup_pop(0);
2270 rwl->nwait_r--;
2271 }
sewardj2d94c112002-06-03 01:25:54 +00002272 my_assert(rwl->status >= 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002273 rwl->status++;
2274 res = __pthread_mutex_unlock(&rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00002275 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002276 return 0;
sewardja1ac5cb2002-05-27 13:00:05 +00002277}
2278
sewardj2d8b3f02002-06-01 14:14:19 +00002279
sewardja1ac5cb2002-05-27 13:00:05 +00002280int pthread_rwlock_tryrdlock ( pthread_rwlock_t* orig )
2281{
2282 int res;
2283 vg_rwlock_t* rwl;
2284 if (0) printf ("pthread_rwlock_tryrdlock\n");
2285 rwl = rw_remap ( orig );
sewardj2d8b3f02002-06-01 14:14:19 +00002286 res = __pthread_mutex_lock(&rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00002287 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002288 if (!rwl->initted) {
2289 res = __pthread_mutex_unlock(&rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00002290 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002291 return EINVAL;
2292 }
2293 if (rwl->status == -1) {
2294 /* Writer active; we have to give up. */
2295 res = __pthread_mutex_unlock(&rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00002296 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002297 return EBUSY;
2298 }
2299 /* Success */
sewardj2d94c112002-06-03 01:25:54 +00002300 my_assert(rwl->status >= 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002301 rwl->status++;
2302 res = __pthread_mutex_unlock(&rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00002303 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002304 return 0;
sewardja1ac5cb2002-05-27 13:00:05 +00002305}
2306
sewardj2d8b3f02002-06-01 14:14:19 +00002307
2308static
2309void pthread_rwlock_wrlock_CANCEL_HDLR ( void* rwl_v )
2310{
2311 vg_rwlock_t* rwl = (vg_rwlock_t*)rwl_v;
2312 rwl->nwait_w--;
2313 pthread_mutex_unlock (&rwl->mx);
2314}
2315
2316
sewardja1ac5cb2002-05-27 13:00:05 +00002317int pthread_rwlock_wrlock ( pthread_rwlock_t* orig )
2318{
2319 int res;
2320 vg_rwlock_t* rwl;
2321 if (0) printf ("pthread_rwlock_wrlock\n");
2322 rwl = rw_remap ( orig );
sewardj2d8b3f02002-06-01 14:14:19 +00002323 res = __pthread_mutex_lock(&rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00002324 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002325 if (!rwl->initted) {
2326 res = __pthread_mutex_unlock(&rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00002327 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002328 return EINVAL;
2329 }
2330 if (rwl->status != 0) {
2331 rwl->nwait_w++;
2332 pthread_cleanup_push( pthread_rwlock_wrlock_CANCEL_HDLR, rwl );
2333 while (1) {
2334 if (rwl->status == 0) break;
2335 res = pthread_cond_wait(&rwl->cv_w, &rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00002336 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002337 }
2338 pthread_cleanup_pop(0);
2339 rwl->nwait_w--;
2340 }
sewardj2d94c112002-06-03 01:25:54 +00002341 my_assert(rwl->status == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002342 rwl->status = -1;
2343 res = __pthread_mutex_unlock(&rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00002344 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002345 return 0;
sewardja1ac5cb2002-05-27 13:00:05 +00002346}
2347
sewardj2d8b3f02002-06-01 14:14:19 +00002348
sewardja1ac5cb2002-05-27 13:00:05 +00002349int pthread_rwlock_trywrlock ( pthread_rwlock_t* orig )
2350{
2351 int res;
2352 vg_rwlock_t* rwl;
sewardj2d8b3f02002-06-01 14:14:19 +00002353 if (0) printf ("pthread_wrlock_trywrlock\n");
sewardja1ac5cb2002-05-27 13:00:05 +00002354 rwl = rw_remap ( orig );
sewardj2d8b3f02002-06-01 14:14:19 +00002355 res = __pthread_mutex_lock(&rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00002356 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002357 if (!rwl->initted) {
2358 res = __pthread_mutex_unlock(&rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00002359 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002360 return EINVAL;
2361 }
2362 if (rwl->status != 0) {
2363 /* Reader(s) or a writer active; we have to give up. */
2364 res = __pthread_mutex_unlock(&rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00002365 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002366 return EBUSY;
2367 }
2368 /* Success */
sewardj2d94c112002-06-03 01:25:54 +00002369 my_assert(rwl->status == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002370 rwl->status = -1;
2371 res = __pthread_mutex_unlock(&rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00002372 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002373 return 0;
sewardja1ac5cb2002-05-27 13:00:05 +00002374}
2375
sewardj2d8b3f02002-06-01 14:14:19 +00002376
sewardja1ac5cb2002-05-27 13:00:05 +00002377int pthread_rwlock_unlock ( pthread_rwlock_t* orig )
2378{
2379 int res;
2380 vg_rwlock_t* rwl;
2381 if (0) printf ("pthread_rwlock_unlock\n");
2382 rwl = rw_remap ( orig );
sewardj2d8b3f02002-06-01 14:14:19 +00002383 rwl = rw_remap ( orig );
2384 res = __pthread_mutex_lock(&rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00002385 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002386 if (!rwl->initted) {
2387 res = __pthread_mutex_unlock(&rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00002388 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002389 return EINVAL;
2390 }
2391 if (rwl->status == 0) {
2392 res = __pthread_mutex_unlock(&rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00002393 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002394 return EPERM;
2395 }
sewardj2d94c112002-06-03 01:25:54 +00002396 my_assert(rwl->status != 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002397 if (rwl->status == -1) {
2398 rwl->status = 0;
2399 } else {
sewardj2d94c112002-06-03 01:25:54 +00002400 my_assert(rwl->status > 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002401 rwl->status--;
2402 }
2403
sewardj2d94c112002-06-03 01:25:54 +00002404 my_assert(rwl->status >= 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002405
2406 if (rwl->prefer_w) {
2407
2408 /* Favour waiting writers, if any. */
2409 if (rwl->nwait_w > 0) {
2410 /* Writer(s) are waiting. */
2411 if (rwl->status == 0) {
2412 /* We can let a writer in. */
2413 res = pthread_cond_signal(&rwl->cv_w);
sewardj2d94c112002-06-03 01:25:54 +00002414 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002415 } else {
2416 /* There are still readers active. Do nothing; eventually
2417 they will disappear, at which point a writer will be
2418 admitted. */
2419 }
2420 }
2421 else
2422 /* No waiting writers. */
2423 if (rwl->nwait_r > 0) {
2424 /* Let in a waiting reader. */
2425 res = pthread_cond_signal(&rwl->cv_r);
sewardj2d94c112002-06-03 01:25:54 +00002426 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002427 }
2428
2429 } else {
2430
2431 /* Favour waiting readers, if any. */
2432 if (rwl->nwait_r > 0) {
2433 /* Reader(s) are waiting; let one in. */
2434 res = pthread_cond_signal(&rwl->cv_r);
sewardj2d94c112002-06-03 01:25:54 +00002435 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002436 }
2437 else
2438 /* No waiting readers. */
2439 if (rwl->nwait_w > 0 && rwl->status == 0) {
2440 /* We have waiting writers and no active readers; let a
2441 writer in. */
2442 res = pthread_cond_signal(&rwl->cv_w);
sewardj2d94c112002-06-03 01:25:54 +00002443 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002444 }
2445 }
2446
2447 res = __pthread_mutex_unlock(&rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00002448 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002449 return 0;
2450}
2451
2452
2453int pthread_rwlock_destroy ( pthread_rwlock_t *orig )
2454{
2455 int res;
2456 vg_rwlock_t* rwl;
2457 if (0) printf ("pthread_rwlock_destroy\n");
2458 rwl = rw_remap ( orig );
2459 res = __pthread_mutex_lock(&rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00002460 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002461 if (!rwl->initted) {
2462 res = __pthread_mutex_unlock(&rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00002463 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002464 return EINVAL;
2465 }
2466 if (rwl->status != 0 || rwl->nwait_r > 0 || rwl->nwait_w > 0) {
2467 res = __pthread_mutex_unlock(&rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00002468 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002469 return EBUSY;
2470 }
2471 rwl->initted = 0;
2472 res = __pthread_mutex_unlock(&rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00002473 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002474 return 0;
sewardja1ac5cb2002-05-27 13:00:05 +00002475}
2476
2477
2478/* ---------------------------------------------------------------------
sewardj3b13f0e2002-04-25 20:17:29 +00002479 B'stard.
2480 ------------------------------------------------------------------ */
2481
2482# define strong_alias(name, aliasname) \
2483 extern __typeof (name) aliasname __attribute__ ((alias (#name)));
2484
sewardj5905fae2002-04-26 13:25:00 +00002485# define weak_alias(name, aliasname) \
2486 extern __typeof (name) aliasname __attribute__ ((weak, alias (#name)));
sewardj3b13f0e2002-04-25 20:17:29 +00002487
sewardj5905fae2002-04-26 13:25:00 +00002488strong_alias(__pthread_mutex_lock, pthread_mutex_lock)
2489strong_alias(__pthread_mutex_trylock, pthread_mutex_trylock)
2490strong_alias(__pthread_mutex_unlock, pthread_mutex_unlock)
2491strong_alias(__pthread_mutexattr_init, pthread_mutexattr_init)
2492 weak_alias(__pthread_mutexattr_settype, pthread_mutexattr_settype)
2493strong_alias(__pthread_mutex_init, pthread_mutex_init)
2494strong_alias(__pthread_mutexattr_destroy, pthread_mutexattr_destroy)
2495strong_alias(__pthread_mutex_destroy, pthread_mutex_destroy)
2496strong_alias(__pthread_once, pthread_once)
2497strong_alias(__pthread_atfork, pthread_atfork)
2498strong_alias(__pthread_key_create, pthread_key_create)
2499strong_alias(__pthread_getspecific, pthread_getspecific)
2500strong_alias(__pthread_setspecific, pthread_setspecific)
2501
sewardjd529a442002-05-04 19:49:21 +00002502#ifndef GLIBC_2_1
sewardj3b13f0e2002-04-25 20:17:29 +00002503strong_alias(sigaction, __sigaction)
sewardjd529a442002-05-04 19:49:21 +00002504#endif
2505
sewardj5905fae2002-04-26 13:25:00 +00002506strong_alias(close, __close)
sewardj3b13f0e2002-04-25 20:17:29 +00002507strong_alias(fcntl, __fcntl)
sewardj5905fae2002-04-26 13:25:00 +00002508strong_alias(lseek, __lseek)
2509strong_alias(open, __open)
2510strong_alias(open64, __open64)
sewardj5905fae2002-04-26 13:25:00 +00002511strong_alias(read, __read)
2512strong_alias(wait, __wait)
2513strong_alias(write, __write)
sewardj3b13f0e2002-04-25 20:17:29 +00002514strong_alias(connect, __connect)
sewardj5905fae2002-04-26 13:25:00 +00002515strong_alias(send, __send)
2516
sewardj726c4122002-05-16 23:39:10 +00002517weak_alias (__pread64, pread64)
sewardja18e2102002-05-18 10:43:22 +00002518weak_alias (__pwrite64, pwrite64)
sewardj5905fae2002-04-26 13:25:00 +00002519weak_alias(__fork, fork)
sewardj7f6456d2002-05-21 00:51:21 +00002520
sewardjf0b06452002-06-04 08:38:04 +00002521weak_alias (__pthread_kill_other_threads_np, pthread_kill_other_threads_np)
sewardj3b13f0e2002-04-25 20:17:29 +00002522
2523/*--------------------------------------------------*/
2524
sewardj5905fae2002-04-26 13:25:00 +00002525weak_alias(pthread_rwlock_rdlock, __pthread_rwlock_rdlock)
sewardj5905fae2002-04-26 13:25:00 +00002526weak_alias(pthread_rwlock_unlock, __pthread_rwlock_unlock)
sewardj262b0292002-05-01 00:03:16 +00002527weak_alias(pthread_rwlock_wrlock, __pthread_rwlock_wrlock)
sewardj060b04f2002-04-26 21:01:13 +00002528
sewardja1ac5cb2002-05-27 13:00:05 +00002529weak_alias(pthread_rwlock_destroy, __pthread_rwlock_destroy)
2530weak_alias(pthread_rwlock_init, __pthread_rwlock_init)
2531weak_alias(pthread_rwlock_tryrdlock, __pthread_rwlock_tryrdlock)
2532weak_alias(pthread_rwlock_trywrlock, __pthread_rwlock_trywrlock)
2533
sewardj060b04f2002-04-26 21:01:13 +00002534
sewardj3b13f0e2002-04-25 20:17:29 +00002535/* I've no idea what these are, but they get called quite a lot.
2536 Anybody know? */
2537
2538#undef _IO_flockfile
2539void _IO_flockfile ( _IO_FILE * file )
2540{
sewardj853f55d2002-04-26 00:27:53 +00002541 pthread_mutex_lock(file->_lock);
sewardj3b13f0e2002-04-25 20:17:29 +00002542}
sewardj5905fae2002-04-26 13:25:00 +00002543weak_alias(_IO_flockfile, flockfile);
2544
sewardj3b13f0e2002-04-25 20:17:29 +00002545
2546#undef _IO_funlockfile
2547void _IO_funlockfile ( _IO_FILE * file )
2548{
sewardj853f55d2002-04-26 00:27:53 +00002549 pthread_mutex_unlock(file->_lock);
sewardj3b13f0e2002-04-25 20:17:29 +00002550}
sewardj5905fae2002-04-26 13:25:00 +00002551weak_alias(_IO_funlockfile, funlockfile);
2552
sewardj3b13f0e2002-04-25 20:17:29 +00002553
sewardjd4f2c712002-04-30 10:20:10 +00002554/* This doesn't seem to be needed to simulate libpthread.so's external
2555 interface, but many people complain about its absence. */
2556
2557strong_alias(__pthread_mutexattr_settype, __pthread_mutexattr_setkind_np)
2558weak_alias(__pthread_mutexattr_setkind_np, pthread_mutexattr_setkind_np)
sewardj439d45e2002-05-03 20:43:10 +00002559
2560
2561/*--------------------------------------------------------------------*/
2562/*--- end vg_libpthread.c ---*/
2563/*--------------------------------------------------------------------*/