blob: af9dc1e8948aaebb054419101b87876801e57dcf [file] [log] [blame]
sewardje663cb92002-04-12 10:26:32 +00001
sewardj439d45e2002-05-03 20:43:10 +00002/*--------------------------------------------------------------------*/
3/*--- A replacement for the standard libpthread.so. ---*/
4/*--- vg_libpthread.c ---*/
5/*--------------------------------------------------------------------*/
6
7/*
njnc9539842002-10-02 13:26:35 +00008 This file is part of Valgrind, an extensible x86 protected-mode
9 emulator for monitoring program execution on x86-Unixes.
sewardj439d45e2002-05-03 20:43:10 +000010
njn0e1b5142003-04-15 14:58:06 +000011 Copyright (C) 2000-2003 Julian Seward
sewardj439d45e2002-05-03 20:43:10 +000012 jseward@acm.org
13
14 This program is free software; you can redistribute it and/or
15 modify it under the terms of the GNU General Public License as
16 published by the Free Software Foundation; either version 2 of the
17 License, or (at your option) any later version.
18
19 This program is distributed in the hope that it will be useful, but
20 WITHOUT ANY WARRANTY; without even the implied warranty of
21 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
22 General Public License for more details.
23
24 You should have received a copy of the GNU General Public License
25 along with this program; if not, write to the Free Software
26 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
27 02111-1307, USA.
28
njn25e49d8e72002-09-23 09:36:25 +000029 The GNU General Public License is contained in the file COPYING.
sewardj439d45e2002-05-03 20:43:10 +000030*/
31
32/* ALL THIS CODE RUNS ON THE SIMULATED CPU.
33
34 This is a replacement for the standard libpthread.so. It is loaded
sewardje663cb92002-04-12 10:26:32 +000035 as part of the client's image (if required) and directs pthread
36 calls through to Valgrind's request mechanism.
37
38 A couple of caveats.
39
40 1. Since it's a binary-compatible replacement for an existing library,
41 we must take care to used exactly the same data layouts, etc, as
42 the standard pthread.so does.
43
44 2. Since this runs as part of the client, there are no specific
45 restrictions on what headers etc we can include, so long as
46 this libpthread.so does not end up having dependencies on .so's
47 which the real one doesn't.
48
49 Later ... it appears we cannot call file-related stuff in libc here,
50 perhaps fair enough. Be careful what you call from here. Even exit()
51 doesn't work (gives infinite recursion and then stack overflow); hence
52 myexit(). Also fprintf doesn't seem safe.
53*/
54
55#include "valgrind.h" /* For the request-passing mechanism */
56#include "vg_include.h" /* For the VG_USERREQ__* constants */
57
sewardja1ac5cb2002-05-27 13:00:05 +000058#define __USE_UNIX98
59#include <sys/types.h>
60#include <pthread.h>
61#undef __USE_UNIX98
62
sewardje663cb92002-04-12 10:26:32 +000063#include <unistd.h>
64#include <string.h>
sewardj2a1dcce2002-04-22 12:45:25 +000065#include <sys/time.h>
sewardjf912dfc2002-11-13 21:51:10 +000066#include <sys/stat.h>
67#include <sys/poll.h>
sewardj2d94c112002-06-03 01:25:54 +000068#include <stdio.h>
daywalker005e7c12003-10-16 16:14:13 +000069#include <errno.h>
sewardj2d94c112002-06-03 01:25:54 +000070
sewardj705d3cb2002-05-23 13:13:12 +000071
jsgf855d93d2003-10-13 22:26:55 +000072# define strong_alias(name, aliasname) \
73 extern __typeof (name) aliasname __attribute__ ((alias (#name)));
74
75# define weak_alias(name, aliasname) \
76 extern __typeof (name) aliasname __attribute__ ((weak, alias (#name)));
77
78
sewardj705d3cb2002-05-23 13:13:12 +000079/* ---------------------------------------------------------------------
80 Forwardses.
81 ------------------------------------------------------------------ */
82
sewardj11f0bb42003-04-26 20:11:15 +000083#define WEAK __attribute__((weak))
84
sewardjfd7747b2002-12-01 10:25:53 +000085static
86__inline__
87int is_kerror ( int res )
88{
89 if (res >= -4095 && res <= -1)
90 return 1;
91 else
92 return 0;
93}
94
sewardj08c7f012002-10-07 23:56:55 +000095
96#ifdef GLIBC_2_3
97 /* kludge by JRS (not from glibc) ... */
98 typedef void* __locale_t;
99
100 /* Copied from locale/locale.h in glibc-2.2.93 sources */
101 /* This value can be passed to `uselocale' and may be returned by
102 it. Passing this value to any other function has undefined
103 behavior. */
104# define LC_GLOBAL_LOCALE ((__locale_t) -1L)
105 extern __locale_t __uselocale ( __locale_t );
106#endif
107
sewardj00a66b12002-10-12 16:42:35 +0000108static
109void init_libc_tsd_keys ( void );
110
sewardj705d3cb2002-05-23 13:13:12 +0000111
sewardje663cb92002-04-12 10:26:32 +0000112/* ---------------------------------------------------------------------
113 Helpers. We have to be pretty self-sufficient.
114 ------------------------------------------------------------------ */
115
sewardj436e0582002-04-26 14:31:40 +0000116/* Number of times any given error message is printed. */
117#define N_MOANS 3
118
sewardj45b4b372002-04-16 22:50:32 +0000119/* Extract from Valgrind the value of VG_(clo_trace_pthread_level).
120 Returns 0 (none) if not running on Valgrind. */
121static
122int get_pt_trace_level ( void )
123{
124 int res;
125 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
126 VG_USERREQ__GET_PTHREAD_TRACE_LEVEL,
127 0, 0, 0, 0);
128 return res;
129}
130
sewardje663cb92002-04-12 10:26:32 +0000131static
sewardj2d94c112002-06-03 01:25:54 +0000132void my_exit ( int arg )
sewardje663cb92002-04-12 10:26:32 +0000133{
jsgf855d93d2003-10-13 22:26:55 +0000134 VG_(do_syscall)(__NR_exit, arg);
sewardj08c7f012002-10-07 23:56:55 +0000135 /*NOTREACHED*/
sewardje663cb92002-04-12 10:26:32 +0000136}
137
sewardje0cfe2a2002-11-30 14:04:45 +0000138/* Apparently unused.
sewardj08c7f012002-10-07 23:56:55 +0000139static
140void my_write ( int fd, const void *buf, int count )
141{
jsgf855d93d2003-10-13 22:26:55 +0000142 VG_(do_syscall)(__NR_write, fd, (int)buf, count );
sewardj08c7f012002-10-07 23:56:55 +0000143}
sewardje0cfe2a2002-11-30 14:04:45 +0000144*/
sewardje663cb92002-04-12 10:26:32 +0000145
sewardj68b2dd92002-05-10 21:03:56 +0000146/* We need this guy -- it's in valgrind.so. */
147extern void VG_(startup) ( void );
148
149
150/* Just start up Valgrind if it's not already going. VG_(startup)()
151 detects and ignores second and subsequent calls. */
sewardj604ec3c2002-04-18 22:38:41 +0000152static __inline__
sewardje663cb92002-04-12 10:26:32 +0000153void ensure_valgrind ( char* caller )
154{
sewardj68b2dd92002-05-10 21:03:56 +0000155 VG_(startup)();
sewardje663cb92002-04-12 10:26:32 +0000156}
157
sewardjbea1caa2002-05-10 23:20:58 +0000158/* While we're at it ... hook our own startup function into this
159 game. */
160__asm__ (
161 ".section .init\n"
162 "\tcall vgPlain_startup"
163);
164
sewardje663cb92002-04-12 10:26:32 +0000165
166static
sewardj3b5d8862002-04-20 13:53:23 +0000167__attribute__((noreturn))
daywalker3222e0a2003-09-18 01:39:50 +0000168void barf ( const char* str )
sewardje663cb92002-04-12 10:26:32 +0000169{
sewardj69a72a52002-11-03 13:41:41 +0000170 char buf[1000];
daywalker3222e0a2003-09-18 01:39:50 +0000171 strcpy(buf, "\nvalgrind's libpthread.so: ");
sewardje663cb92002-04-12 10:26:32 +0000172 strcat(buf, str);
173 strcat(buf, "\n\n");
njn4c791212003-05-02 17:53:54 +0000174 VALGRIND_NON_SIMD_CALL2(VG_(message), Vg_UserMsg, buf);
sewardj2d94c112002-06-03 01:25:54 +0000175 my_exit(1);
sewardj3b5d8862002-04-20 13:53:23 +0000176 /* We have to persuade gcc into believing this doesn't return. */
177 while (1) { };
sewardje663cb92002-04-12 10:26:32 +0000178}
179
180
nethercoteaad8c192003-11-20 14:23:09 +0000181static void cat_n_send ( char* s1, char* s2, char* s3 )
sewardj2a3d28c2002-04-14 13:27:00 +0000182{
sewardj69a72a52002-11-03 13:41:41 +0000183 char buf[1000];
sewardj436e0582002-04-26 14:31:40 +0000184 if (get_pt_trace_level() >= 0) {
nethercoteaad8c192003-11-20 14:23:09 +0000185 snprintf(buf, sizeof(buf), "%s%s%s", s1, s2, s3);
sewardj69a72a52002-11-03 13:41:41 +0000186 buf[sizeof(buf)-1] = '\0';
njn4c791212003-05-02 17:53:54 +0000187 VALGRIND_NON_SIMD_CALL2(VG_(message), Vg_UserMsg, buf);
sewardj45b4b372002-04-16 22:50:32 +0000188 }
sewardj2a3d28c2002-04-14 13:27:00 +0000189}
190
nethercoteaad8c192003-11-20 14:23:09 +0000191static void oh_dear ( char* fn, char* aux, char* s )
sewardj69a72a52002-11-03 13:41:41 +0000192{
nethercoteaad8c192003-11-20 14:23:09 +0000193 cat_n_send ( "warning: Valgrind's ", fn, s );
194 if (NULL != aux)
195 cat_n_send ( " ", aux, "" );
196 cat_n_send ( " your program may misbehave as a result", "", "" );
sewardj69a72a52002-11-03 13:41:41 +0000197}
198
nethercoteaad8c192003-11-20 14:23:09 +0000199static void ignored ( char* fn, char* aux )
sewardj30671ff2002-04-21 00:13:57 +0000200{
nethercoteaad8c192003-11-20 14:23:09 +0000201 oh_dear ( fn, aux, " does nothing" );
202}
203
204static void kludged ( char* fn, char* aux )
205{
206 oh_dear ( fn, aux, " is incomplete" );
sewardj439d45e2002-05-03 20:43:10 +0000207}
208
sewardj69a72a52002-11-03 13:41:41 +0000209
sewardjccef2e62002-05-29 19:26:32 +0000210__attribute__((noreturn))
nethercoteaad8c192003-11-20 14:23:09 +0000211void vgPlain_unimp ( char* fn )
sewardj3b13f0e2002-04-25 20:17:29 +0000212{
nethercoteaad8c192003-11-20 14:23:09 +0000213 cat_n_send ( "valgrind's libpthread.so: UNIMPLEMENTED FUNCTION: ", fn, "" );
sewardj3b13f0e2002-04-25 20:17:29 +0000214 barf("Please report this bug to me at: jseward@acm.org");
215}
216
sewardje663cb92002-04-12 10:26:32 +0000217
sewardj457cc472002-06-03 23:13:47 +0000218static
daywalker3222e0a2003-09-18 01:39:50 +0000219void my_assert_fail ( const Char* expr, const Char* file, Int line, const Char* fn )
sewardj2d94c112002-06-03 01:25:54 +0000220{
sewardj69a72a52002-11-03 13:41:41 +0000221 char buf[1000];
sewardj2d94c112002-06-03 01:25:54 +0000222 static Bool entered = False;
223 if (entered)
224 my_exit(2);
225 entered = True;
sewardj69a72a52002-11-03 13:41:41 +0000226 sprintf(buf, "\n%s: %s:%d (%s): Assertion `%s' failed.\n",
227 "valgrind", file, line, fn, expr );
nethercoteaad8c192003-11-20 14:23:09 +0000228 cat_n_send ( "", buf, "" );
229 sprintf(buf, "Please report this bug to me at: %s\n\n", VG_EMAIL_ADDR);
sewardj2d94c112002-06-03 01:25:54 +0000230 my_exit(1);
231}
232
233#define MY__STRING(__str) #__str
234
235#define my_assert(expr) \
236 ((void) ((expr) ? 0 : \
237 (my_assert_fail (MY__STRING(expr), \
238 __FILE__, __LINE__, \
239 __PRETTY_FUNCTION__), 0)))
240
sewardj00a66b12002-10-12 16:42:35 +0000241static
242void my_free ( void* ptr )
243{
244 int res;
245 VALGRIND_MAGIC_SEQUENCE(res, (-1) /* default */,
246 VG_USERREQ__FREE, ptr, 0, 0, 0);
247 my_assert(res == 0);
248}
249
250
251static
252void* my_malloc ( int nbytes )
253{
254 void* res;
255 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
256 VG_USERREQ__MALLOC, nbytes, 0, 0, 0);
257 my_assert(res != (void*)0);
258 return res;
259}
260
261
sewardj2d94c112002-06-03 01:25:54 +0000262
sewardje663cb92002-04-12 10:26:32 +0000263/* ---------------------------------------------------------------------
264 Pass pthread_ calls to Valgrind's request mechanism.
265 ------------------------------------------------------------------ */
266
sewardja1ac5cb2002-05-27 13:00:05 +0000267
sewardjf8f819e2002-04-17 23:21:37 +0000268/* ---------------------------------------------------
sewardj4dced352002-06-04 22:54:20 +0000269 Ummm ..
270 ------------------------------------------------ */
271
272static
273void pthread_error ( const char* msg )
274{
275 int res;
276 VALGRIND_MAGIC_SEQUENCE(res, 0,
277 VG_USERREQ__PTHREAD_ERROR,
278 msg, 0, 0, 0);
279}
280
281
282/* ---------------------------------------------------
sewardj00a66b12002-10-12 16:42:35 +0000283 Here so it can be inlined without complaint.
284 ------------------------------------------------ */
285
286__inline__
287pthread_t pthread_self(void)
288{
289 int tid;
290 ensure_valgrind("pthread_self");
291 VALGRIND_MAGIC_SEQUENCE(tid, 0 /* default */,
292 VG_USERREQ__PTHREAD_GET_THREADID,
293 0, 0, 0, 0);
294 if (tid < 1 || tid >= VG_N_THREADS)
295 barf("pthread_self: invalid ThreadId");
296 return tid;
297}
298
299
300/* ---------------------------------------------------
sewardjf8f819e2002-04-17 23:21:37 +0000301 THREAD ATTRIBUTES
302 ------------------------------------------------ */
303
sewardj6af4b5d2002-04-16 04:40:49 +0000304int pthread_attr_init(pthread_attr_t *attr)
305{
sewardj7989d0c2002-05-28 11:00:01 +0000306 /* Just initialise the fields which we might look at. */
307 attr->__detachstate = PTHREAD_CREATE_JOINABLE;
sewardj111b14c2002-10-20 16:22:57 +0000308 /* Linuxthreads sets this field to the value __getpagesize(), so I
309 guess the following is OK. */
310 attr->__guardsize = VKI_BYTES_PER_PAGE; return 0;
sewardj6af4b5d2002-04-16 04:40:49 +0000311}
312
313int pthread_attr_setdetachstate(pthread_attr_t *attr, int detachstate)
314{
sewardj7989d0c2002-05-28 11:00:01 +0000315 if (detachstate != PTHREAD_CREATE_JOINABLE
sewardj4dced352002-06-04 22:54:20 +0000316 && detachstate != PTHREAD_CREATE_DETACHED) {
317 pthread_error("pthread_attr_setdetachstate: "
318 "detachstate is invalid");
sewardj7989d0c2002-05-28 11:00:01 +0000319 return EINVAL;
sewardj4dced352002-06-04 22:54:20 +0000320 }
sewardj7989d0c2002-05-28 11:00:01 +0000321 attr->__detachstate = detachstate;
sewardj6af4b5d2002-04-16 04:40:49 +0000322 return 0;
323}
324
njn25e49d8e72002-09-23 09:36:25 +0000325int pthread_attr_getdetachstate(const pthread_attr_t *attr, int *detachstate)
326{
327 *detachstate = attr->__detachstate;
328 return 0;
329}
330
sewardj30671ff2002-04-21 00:13:57 +0000331int pthread_attr_setinheritsched(pthread_attr_t *attr, int inherit)
332{
sewardj436e0582002-04-26 14:31:40 +0000333 static int moans = N_MOANS;
334 if (moans-- > 0)
nethercoteaad8c192003-11-20 14:23:09 +0000335 ignored("pthread_attr_setinheritsched", NULL);
sewardj30671ff2002-04-21 00:13:57 +0000336 return 0;
337}
sewardj6af4b5d2002-04-16 04:40:49 +0000338
sewardj11f0bb42003-04-26 20:11:15 +0000339WEAK
sewardj0286dd52002-05-16 20:51:15 +0000340int pthread_attr_setstacksize (pthread_attr_t *__attr,
341 size_t __stacksize)
342{
sewardja18e2102002-05-18 10:43:22 +0000343 size_t limit;
sewardj3d7c8d62002-06-04 20:59:16 +0000344 char buf[1024];
sewardj0286dd52002-05-16 20:51:15 +0000345 ensure_valgrind("pthread_attr_setstacksize");
sewardja18e2102002-05-18 10:43:22 +0000346 limit = VG_PTHREAD_STACK_SIZE - VG_AR_CLIENT_STACKBASE_REDZONE_SZB
347 - 1000; /* paranoia */
348 if (__stacksize < limit)
sewardj0286dd52002-05-16 20:51:15 +0000349 return 0;
sewardj3d7c8d62002-06-04 20:59:16 +0000350 snprintf(buf, sizeof(buf), "pthread_attr_setstacksize: "
351 "requested size %d >= VG_PTHREAD_STACK_SIZE\n "
352 "edit vg_include.h and rebuild.", __stacksize);
353 buf[sizeof(buf)-1] = '\0'; /* Make sure it is zero terminated */
354 barf(buf);
sewardj0286dd52002-05-16 20:51:15 +0000355}
356
357
sewardj30671ff2002-04-21 00:13:57 +0000358/* This is completely bogus. */
359int pthread_attr_getschedparam(const pthread_attr_t *attr,
360 struct sched_param *param)
361{
sewardj436e0582002-04-26 14:31:40 +0000362 static int moans = N_MOANS;
363 if (moans-- > 0)
nethercoteaad8c192003-11-20 14:23:09 +0000364 kludged("pthread_attr_getschedparam", NULL);
sewardj3e909ce2002-06-03 13:27:15 +0000365# ifdef HAVE_SCHED_PRIORITY
sewardj72d58482002-04-24 02:20:20 +0000366 if (param) param->sched_priority = 0; /* who knows */
367# else
sewardj30671ff2002-04-21 00:13:57 +0000368 if (param) param->__sched_priority = 0; /* who knows */
sewardj72d58482002-04-24 02:20:20 +0000369# endif
sewardj30671ff2002-04-21 00:13:57 +0000370 return 0;
371}
372
373int pthread_attr_setschedparam(pthread_attr_t *attr,
374 const struct sched_param *param)
375{
sewardj436e0582002-04-26 14:31:40 +0000376 static int moans = N_MOANS;
377 if (moans-- > 0)
nethercoteaad8c192003-11-20 14:23:09 +0000378 ignored("pthread_attr_setschedparam", "(scheduling not changeable)");
sewardj30671ff2002-04-21 00:13:57 +0000379 return 0;
380}
381
382int pthread_attr_destroy(pthread_attr_t *attr)
383{
sewardj436e0582002-04-26 14:31:40 +0000384 static int moans = N_MOANS;
385 if (moans-- > 0)
nethercoteaad8c192003-11-20 14:23:09 +0000386 ignored("pthread_attr_destroy", NULL);
sewardj30671ff2002-04-21 00:13:57 +0000387 return 0;
388}
sewardjf8f819e2002-04-17 23:21:37 +0000389
sewardj0d844232002-06-02 09:29:31 +0000390/* These are no-ops, as with LinuxThreads. */
391int pthread_attr_setscope ( pthread_attr_t *attr, int scope )
392{
393 ensure_valgrind("pthread_attr_setscope");
394 if (scope == PTHREAD_SCOPE_SYSTEM)
395 return 0;
sewardj4dced352002-06-04 22:54:20 +0000396 pthread_error("pthread_attr_setscope: "
397 "invalid or unsupported scope");
sewardj0d844232002-06-02 09:29:31 +0000398 if (scope == PTHREAD_SCOPE_PROCESS)
399 return ENOTSUP;
400 return EINVAL;
401}
402
403int pthread_attr_getscope ( const pthread_attr_t *attr, int *scope )
404{
405 ensure_valgrind("pthread_attr_setscope");
406 if (scope)
407 *scope = PTHREAD_SCOPE_SYSTEM;
408 return 0;
409}
410
sewardj64039bb2002-06-03 00:58:18 +0000411
412/* Pretty bogus. Avoid if possible. */
413int pthread_getattr_np (pthread_t thread, pthread_attr_t *attr)
414{
415 int detached;
416 size_t limit;
417 ensure_valgrind("pthread_getattr_np");
nethercoteaad8c192003-11-20 14:23:09 +0000418 kludged("pthread_getattr_np", NULL);
sewardj64039bb2002-06-03 00:58:18 +0000419 limit = VG_PTHREAD_STACK_SIZE - VG_AR_CLIENT_STACKBASE_REDZONE_SZB
420 - 1000; /* paranoia */
421 attr->__detachstate = PTHREAD_CREATE_JOINABLE;
422 attr->__schedpolicy = SCHED_OTHER;
423 attr->__schedparam.sched_priority = 0;
424 attr->__inheritsched = PTHREAD_EXPLICIT_SCHED;
425 attr->__scope = PTHREAD_SCOPE_SYSTEM;
426 attr->__guardsize = VKI_BYTES_PER_PAGE;
427 attr->__stackaddr = NULL;
428 attr->__stackaddr_set = 0;
429 attr->__stacksize = limit;
430 VALGRIND_MAGIC_SEQUENCE(detached, (-1) /* default */,
431 VG_USERREQ__SET_OR_GET_DETACH,
432 2 /* get */, thread, 0, 0);
sewardj2d94c112002-06-03 01:25:54 +0000433 my_assert(detached == 0 || detached == 1);
sewardj64039bb2002-06-03 00:58:18 +0000434 if (detached)
435 attr->__detachstate = PTHREAD_CREATE_DETACHED;
436 return 0;
437}
438
439
440/* Bogus ... */
sewardj11f0bb42003-04-26 20:11:15 +0000441WEAK
sewardj64039bb2002-06-03 00:58:18 +0000442int pthread_attr_getstackaddr ( const pthread_attr_t * attr,
443 void ** stackaddr )
444{
445 ensure_valgrind("pthread_attr_getstackaddr");
nethercoteaad8c192003-11-20 14:23:09 +0000446 kludged("pthread_attr_getstackaddr", "(it always sets stackaddr to zero)");
sewardj64039bb2002-06-03 00:58:18 +0000447 if (stackaddr)
448 *stackaddr = NULL;
449 return 0;
450}
451
452/* Not bogus (!) */
sewardj11f0bb42003-04-26 20:11:15 +0000453WEAK
sewardj64039bb2002-06-03 00:58:18 +0000454int pthread_attr_getstacksize ( const pthread_attr_t * _attr,
455 size_t * __stacksize )
456{
457 size_t limit;
458 ensure_valgrind("pthread_attr_getstacksize");
459 limit = VG_PTHREAD_STACK_SIZE - VG_AR_CLIENT_STACKBASE_REDZONE_SZB
460 - 1000; /* paranoia */
461 if (__stacksize)
462 *__stacksize = limit;
463 return 0;
464}
465
sewardja3be12f2002-06-17 12:19:44 +0000466int pthread_attr_setschedpolicy(pthread_attr_t *attr, int policy)
467{
468 if (policy != SCHED_OTHER && policy != SCHED_FIFO && policy != SCHED_RR)
469 return EINVAL;
470 attr->__schedpolicy = policy;
471 return 0;
472}
473
474int pthread_attr_getschedpolicy(const pthread_attr_t *attr, int *policy)
475{
476 *policy = attr->__schedpolicy;
477 return 0;
478}
479
480
sewardj111b14c2002-10-20 16:22:57 +0000481/* This is completely bogus. We reject all attempts to change it from
482 VKI_BYTES_PER_PAGE. I don't have a clue what it's for so it seems
483 safest to be paranoid. */
sewardj11f0bb42003-04-26 20:11:15 +0000484WEAK
sewardj111b14c2002-10-20 16:22:57 +0000485int pthread_attr_setguardsize(pthread_attr_t *attr, size_t guardsize)
486{
487 static int moans = N_MOANS;
488
489 if (guardsize == VKI_BYTES_PER_PAGE)
490 return 0;
491
492 if (moans-- > 0)
nethercoteaad8c192003-11-20 14:23:09 +0000493 ignored("pthread_attr_setguardsize",
494 "(it ignores any guardsize != 4096)");
sewardj111b14c2002-10-20 16:22:57 +0000495
496 return 0;
497}
498
499/* A straight copy of the LinuxThreads code. */
sewardj11f0bb42003-04-26 20:11:15 +0000500WEAK
sewardj111b14c2002-10-20 16:22:57 +0000501int pthread_attr_getguardsize(const pthread_attr_t *attr, size_t *guardsize)
502{
503 *guardsize = attr->__guardsize;
504 return 0;
505}
506
sewardjab2e1232002-12-26 12:16:11 +0000507/* Again, like LinuxThreads. */
508
509static int concurrency_current_level = 0;
510
sewardj11f0bb42003-04-26 20:11:15 +0000511WEAK
sewardjb34e4db2002-12-08 23:51:32 +0000512int pthread_setconcurrency(int new_level)
513{
514 if (new_level < 0)
515 return EINVAL;
sewardjab2e1232002-12-26 12:16:11 +0000516 else {
517 concurrency_current_level = new_level;
sewardjb34e4db2002-12-08 23:51:32 +0000518 return 0;
sewardjab2e1232002-12-26 12:16:11 +0000519 }
sewardjb34e4db2002-12-08 23:51:32 +0000520}
521
sewardj11f0bb42003-04-26 20:11:15 +0000522WEAK
sewardjab2e1232002-12-26 12:16:11 +0000523int pthread_getconcurrency(void)
524{
525 return concurrency_current_level;
526}
527
528
sewardj111b14c2002-10-20 16:22:57 +0000529
sewardj20917d82002-05-28 01:36:45 +0000530/* ---------------------------------------------------
531 Helper functions for running a thread
532 and for clearing up afterwards.
533 ------------------------------------------------ */
534
535/* All exiting threads eventually pass through here, bearing the
536 return value, or PTHREAD_CANCELED, in ret_val. */
537static
538__attribute__((noreturn))
539void thread_exit_wrapper ( void* ret_val )
540{
sewardj870497a2002-05-29 01:06:47 +0000541 int detached, res;
542 CleanupEntry cu;
543 pthread_key_t key;
sewardj00a66b12002-10-12 16:42:35 +0000544 void** specifics_ptr;
sewardj870497a2002-05-29 01:06:47 +0000545
sewardj20917d82002-05-28 01:36:45 +0000546 /* Run this thread's cleanup handlers. */
sewardj8ad94e12002-05-29 00:10:20 +0000547 while (1) {
548 VALGRIND_MAGIC_SEQUENCE(res, (-1) /* default */,
549 VG_USERREQ__CLEANUP_POP,
550 &cu, 0, 0, 0);
551 if (res == -1) break; /* stack empty */
sewardj2d94c112002-06-03 01:25:54 +0000552 my_assert(res == 0);
sewardj8ad94e12002-05-29 00:10:20 +0000553 if (0) printf("running exit cleanup handler");
554 cu.fn ( cu.arg );
555 }
556
sewardj870497a2002-05-29 01:06:47 +0000557 /* Run this thread's key finalizers. Really this should be run
558 PTHREAD_DESTRUCTOR_ITERATIONS times. */
559 for (key = 0; key < VG_N_THREAD_KEYS; key++) {
560 VALGRIND_MAGIC_SEQUENCE(res, (-2) /* default */,
561 VG_USERREQ__GET_KEY_D_AND_S,
562 key, &cu, 0, 0 );
563 if (res == 0) {
564 /* valid key */
565 if (cu.fn && cu.arg)
566 cu.fn /* destructor for key */
567 ( cu.arg /* specific for key for this thread */ );
568 continue;
569 }
sewardj2d94c112002-06-03 01:25:54 +0000570 my_assert(res == -1);
sewardj870497a2002-05-29 01:06:47 +0000571 }
sewardj20917d82002-05-28 01:36:45 +0000572
sewardj00a66b12002-10-12 16:42:35 +0000573 /* Free up my specifics space, if any. */
574 VALGRIND_MAGIC_SEQUENCE(specifics_ptr, 3 /* default */,
575 VG_USERREQ__PTHREAD_GETSPECIFIC_PTR,
576 pthread_self(), 0, 0, 0);
577 my_assert(specifics_ptr != (void**)3);
578 my_assert(specifics_ptr != (void**)1); /* 1 means invalid thread */
579 if (specifics_ptr != NULL)
580 my_free(specifics_ptr);
581
sewardj20917d82002-05-28 01:36:45 +0000582 /* Decide on my final disposition. */
583 VALGRIND_MAGIC_SEQUENCE(detached, (-1) /* default */,
584 VG_USERREQ__SET_OR_GET_DETACH,
sewardj7989d0c2002-05-28 11:00:01 +0000585 2 /* get */, pthread_self(), 0, 0);
sewardj2d94c112002-06-03 01:25:54 +0000586 my_assert(detached == 0 || detached == 1);
sewardj20917d82002-05-28 01:36:45 +0000587
588 if (detached) {
589 /* Detached; I just quit right now. */
590 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
591 VG_USERREQ__QUIT, 0, 0, 0, 0);
592 } else {
593 /* Not detached; so I wait for a joiner. */
594 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
595 VG_USERREQ__WAIT_JOINER, ret_val, 0, 0, 0);
596 }
597 /* NOTREACHED */
598 barf("thread_exit_wrapper: still alive?!");
599}
600
601
602/* This function is a wrapper function for running a thread. It runs
603 the root function specified in pthread_create, and then, should the
604 root function return a value, it arranges to run the thread's
605 cleanup handlers and exit correctly. */
606
sewardj728a5272002-06-20 10:25:37 +0000607/* Struct used to convey info from pthread_create to thread_wrapper.
608 Must be careful not to pass to the child thread any pointers to
609 objects which might be on the parent's stack. */
sewardj20917d82002-05-28 01:36:45 +0000610typedef
611 struct {
sewardj728a5272002-06-20 10:25:37 +0000612 int attr__detachstate;
sewardj20917d82002-05-28 01:36:45 +0000613 void* (*root_fn) ( void* );
614 void* arg;
615 }
616 NewThreadInfo;
617
618
619/* This is passed to the VG_USERREQ__APPLY_IN_NEW_THREAD and so must
620 not return. Note that this runs in the new thread, not the
621 parent. */
622static
623__attribute__((noreturn))
624void thread_wrapper ( NewThreadInfo* info )
625{
sewardj728a5272002-06-20 10:25:37 +0000626 int attr__detachstate;
sewardj20917d82002-05-28 01:36:45 +0000627 void* (*root_fn) ( void* );
628 void* arg;
629 void* ret_val;
630
sewardj728a5272002-06-20 10:25:37 +0000631 attr__detachstate = info->attr__detachstate;
632 root_fn = info->root_fn;
633 arg = info->arg;
sewardj20917d82002-05-28 01:36:45 +0000634
sewardj20917d82002-05-28 01:36:45 +0000635 /* Free up the arg block that pthread_create malloced. */
sewardj00a66b12002-10-12 16:42:35 +0000636 my_free(info);
sewardj20917d82002-05-28 01:36:45 +0000637
sewardj7989d0c2002-05-28 11:00:01 +0000638 /* Minimally observe the attributes supplied. */
sewardj728a5272002-06-20 10:25:37 +0000639 if (attr__detachstate != PTHREAD_CREATE_DETACHED
640 && attr__detachstate != PTHREAD_CREATE_JOINABLE)
641 pthread_error("thread_wrapper: invalid attr->__detachstate");
642 if (attr__detachstate == PTHREAD_CREATE_DETACHED)
643 pthread_detach(pthread_self());
sewardj7989d0c2002-05-28 11:00:01 +0000644
sewardj00a66b12002-10-12 16:42:35 +0000645# ifdef GLIBC_2_3
646 /* Set this thread's locale to the global (default) locale. A hack
647 in support of glibc-2.3. This does the biz for the all new
648 threads; the root thread is done with a horrible hack in
649 init_libc_tsd_keys() below.
650 */
651 __uselocale(LC_GLOBAL_LOCALE);
652# endif
653
sewardj20917d82002-05-28 01:36:45 +0000654 /* The root function might not return. But if it does we simply
655 move along to thread_exit_wrapper. All other ways out for the
656 thread (cancellation, or calling pthread_exit) lead there
657 too. */
658 ret_val = root_fn(arg);
659 thread_exit_wrapper(ret_val);
660 /* NOTREACHED */
661}
662
663
sewardjf8f819e2002-04-17 23:21:37 +0000664/* ---------------------------------------------------
665 THREADs
666 ------------------------------------------------ */
667
sewardjc91a4ff2003-07-11 00:12:58 +0000668static void __valgrind_pthread_yield ( void )
sewardjff42d1d2002-05-22 13:17:31 +0000669{
670 int res;
671 ensure_valgrind("pthread_yield");
672 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
673 VG_USERREQ__PTHREAD_YIELD, 0, 0, 0, 0);
sewardjc91a4ff2003-07-11 00:12:58 +0000674}
675
676WEAK
677int pthread_yield ( void )
678{
679 __valgrind_pthread_yield();
sewardjff42d1d2002-05-22 13:17:31 +0000680 return 0;
681}
682
683
sewardj6072c362002-04-19 14:40:57 +0000684int pthread_equal(pthread_t thread1, pthread_t thread2)
685{
686 return thread1 == thread2 ? 1 : 0;
687}
688
689
sewardj20917d82002-05-28 01:36:45 +0000690/* Bundle up the args into a malloc'd block and create a new thread
691 consisting of thread_wrapper() applied to said malloc'd block. */
sewardje663cb92002-04-12 10:26:32 +0000692int
sewardj1462c8b2002-07-24 09:41:52 +0000693pthread_create (pthread_t *__restrict __thredd,
sewardje663cb92002-04-12 10:26:32 +0000694 __const pthread_attr_t *__restrict __attr,
695 void *(*__start_routine) (void *),
696 void *__restrict __arg)
697{
sewardj20917d82002-05-28 01:36:45 +0000698 int tid_child;
699 NewThreadInfo* info;
sewardje663cb92002-04-12 10:26:32 +0000700
sewardj20917d82002-05-28 01:36:45 +0000701 ensure_valgrind("pthread_create");
702
sewardj00a66b12002-10-12 16:42:35 +0000703 /* make sure the tsd keys, and hence locale info, are initialised
704 before we get into complications making new threads. */
705 init_libc_tsd_keys();
706
sewardj20917d82002-05-28 01:36:45 +0000707 /* Allocate space for the arg block. thread_wrapper will free
708 it. */
sewardj00a66b12002-10-12 16:42:35 +0000709 info = my_malloc(sizeof(NewThreadInfo));
sewardj2d94c112002-06-03 01:25:54 +0000710 my_assert(info != NULL);
sewardj20917d82002-05-28 01:36:45 +0000711
sewardj728a5272002-06-20 10:25:37 +0000712 if (__attr)
713 info->attr__detachstate = __attr->__detachstate;
714 else
715 info->attr__detachstate = PTHREAD_CREATE_JOINABLE;
716
sewardj20917d82002-05-28 01:36:45 +0000717 info->root_fn = __start_routine;
718 info->arg = __arg;
719 VALGRIND_MAGIC_SEQUENCE(tid_child, VG_INVALID_THREADID /* default */,
720 VG_USERREQ__APPLY_IN_NEW_THREAD,
721 &thread_wrapper, info, 0, 0);
sewardj2d94c112002-06-03 01:25:54 +0000722 my_assert(tid_child != VG_INVALID_THREADID);
sewardj20917d82002-05-28 01:36:45 +0000723
sewardj1462c8b2002-07-24 09:41:52 +0000724 if (__thredd)
725 *__thredd = tid_child;
sewardj20917d82002-05-28 01:36:45 +0000726 return 0; /* success */
727}
sewardje663cb92002-04-12 10:26:32 +0000728
729
730int
731pthread_join (pthread_t __th, void **__thread_return)
732{
733 int res;
734 ensure_valgrind("pthread_join");
735 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
736 VG_USERREQ__PTHREAD_JOIN,
737 __th, __thread_return, 0, 0);
738 return res;
739}
740
741
sewardj3b5d8862002-04-20 13:53:23 +0000742void pthread_exit(void *retval)
743{
sewardj3b5d8862002-04-20 13:53:23 +0000744 ensure_valgrind("pthread_exit");
sewardj20917d82002-05-28 01:36:45 +0000745 /* Simple! */
746 thread_exit_wrapper(retval);
sewardj3b5d8862002-04-20 13:53:23 +0000747}
748
sewardje663cb92002-04-12 10:26:32 +0000749
sewardj853f55d2002-04-26 00:27:53 +0000750int pthread_detach(pthread_t th)
751{
sewardj20917d82002-05-28 01:36:45 +0000752 int res;
753 ensure_valgrind("pthread_detach");
sewardj7989d0c2002-05-28 11:00:01 +0000754 /* First we enquire as to the current detach state. */
755 VALGRIND_MAGIC_SEQUENCE(res, (-2) /* default */,
sewardj20917d82002-05-28 01:36:45 +0000756 VG_USERREQ__SET_OR_GET_DETACH,
sewardj7989d0c2002-05-28 11:00:01 +0000757 2 /* get */, th, 0, 0);
sewardj4dced352002-06-04 22:54:20 +0000758 if (res == -1) {
759 /* not found */
760 pthread_error("pthread_detach: "
761 "invalid target thread");
sewardj7989d0c2002-05-28 11:00:01 +0000762 return ESRCH;
sewardj4dced352002-06-04 22:54:20 +0000763 }
764 if (res == 1) {
765 /* already detached */
766 pthread_error("pthread_detach: "
767 "target thread is already detached");
sewardj7989d0c2002-05-28 11:00:01 +0000768 return EINVAL;
sewardj4dced352002-06-04 22:54:20 +0000769 }
sewardj7989d0c2002-05-28 11:00:01 +0000770 if (res == 0) {
771 VALGRIND_MAGIC_SEQUENCE(res, (-2) /* default */,
772 VG_USERREQ__SET_OR_GET_DETACH,
773 1 /* set */, th, 0, 0);
sewardj2d94c112002-06-03 01:25:54 +0000774 my_assert(res == 0);
sewardj7989d0c2002-05-28 11:00:01 +0000775 return 0;
776 }
777 barf("pthread_detach");
sewardj853f55d2002-04-26 00:27:53 +0000778}
779
780
sewardjf8f819e2002-04-17 23:21:37 +0000781/* ---------------------------------------------------
sewardj8ad94e12002-05-29 00:10:20 +0000782 CLEANUP STACKS
783 ------------------------------------------------ */
784
785void _pthread_cleanup_push (struct _pthread_cleanup_buffer *__buffer,
786 void (*__routine) (void *),
787 void *__arg)
788{
789 int res;
790 CleanupEntry cu;
791 ensure_valgrind("_pthread_cleanup_push");
792 cu.fn = __routine;
793 cu.arg = __arg;
794 VALGRIND_MAGIC_SEQUENCE(res, (-1) /* default */,
795 VG_USERREQ__CLEANUP_PUSH,
796 &cu, 0, 0, 0);
sewardj2d94c112002-06-03 01:25:54 +0000797 my_assert(res == 0);
sewardj8ad94e12002-05-29 00:10:20 +0000798}
799
800
801void _pthread_cleanup_push_defer (struct _pthread_cleanup_buffer *__buffer,
802 void (*__routine) (void *),
803 void *__arg)
804{
805 /* As _pthread_cleanup_push, but first save the thread's original
806 cancellation type in __buffer and set it to Deferred. */
807 int orig_ctype;
808 ensure_valgrind("_pthread_cleanup_push_defer");
809 /* Set to Deferred, and put the old cancellation type in res. */
sewardj2d94c112002-06-03 01:25:54 +0000810 my_assert(-1 != PTHREAD_CANCEL_DEFERRED);
811 my_assert(-1 != PTHREAD_CANCEL_ASYNCHRONOUS);
812 my_assert(sizeof(struct _pthread_cleanup_buffer) >= sizeof(int));
sewardj8ad94e12002-05-29 00:10:20 +0000813 VALGRIND_MAGIC_SEQUENCE(orig_ctype, (-1) /* default */,
814 VG_USERREQ__SET_CANCELTYPE,
815 PTHREAD_CANCEL_DEFERRED, 0, 0, 0);
sewardj2d94c112002-06-03 01:25:54 +0000816 my_assert(orig_ctype != -1);
sewardj8ad94e12002-05-29 00:10:20 +0000817 *((int*)(__buffer)) = orig_ctype;
818 /* Now push the cleanup. */
819 _pthread_cleanup_push(NULL, __routine, __arg);
820}
821
822
823void _pthread_cleanup_pop (struct _pthread_cleanup_buffer *__buffer,
824 int __execute)
825{
826 int res;
827 CleanupEntry cu;
828 ensure_valgrind("_pthread_cleanup_push");
829 cu.fn = cu.arg = NULL; /* paranoia */
830 VALGRIND_MAGIC_SEQUENCE(res, (-1) /* default */,
831 VG_USERREQ__CLEANUP_POP,
832 &cu, 0, 0, 0);
833 if (res == 0) {
834 /* pop succeeded */
835 if (__execute) {
836 cu.fn ( cu.arg );
837 }
838 return;
839 }
840 if (res == -1) {
841 /* stack underflow */
842 return;
843 }
844 barf("_pthread_cleanup_pop");
845}
846
847
848void _pthread_cleanup_pop_restore (struct _pthread_cleanup_buffer *__buffer,
849 int __execute)
850{
851 int orig_ctype, fake_ctype;
852 /* As _pthread_cleanup_pop, but after popping/running the handler,
853 restore the thread's original cancellation type from the first
854 word of __buffer. */
855 _pthread_cleanup_pop(NULL, __execute);
856 orig_ctype = *((int*)(__buffer));
sewardj2d94c112002-06-03 01:25:54 +0000857 my_assert(orig_ctype == PTHREAD_CANCEL_DEFERRED
sewardj8ad94e12002-05-29 00:10:20 +0000858 || orig_ctype == PTHREAD_CANCEL_ASYNCHRONOUS);
sewardj2d94c112002-06-03 01:25:54 +0000859 my_assert(-1 != PTHREAD_CANCEL_DEFERRED);
860 my_assert(-1 != PTHREAD_CANCEL_ASYNCHRONOUS);
861 my_assert(sizeof(struct _pthread_cleanup_buffer) >= sizeof(int));
sewardj8ad94e12002-05-29 00:10:20 +0000862 VALGRIND_MAGIC_SEQUENCE(fake_ctype, (-1) /* default */,
863 VG_USERREQ__SET_CANCELTYPE,
864 orig_ctype, 0, 0, 0);
sewardj2d94c112002-06-03 01:25:54 +0000865 my_assert(fake_ctype == PTHREAD_CANCEL_DEFERRED);
sewardj8ad94e12002-05-29 00:10:20 +0000866}
867
868
869/* ---------------------------------------------------
sewardjf8f819e2002-04-17 23:21:37 +0000870 MUTEX ATTRIBUTES
871 ------------------------------------------------ */
872
sewardj5905fae2002-04-26 13:25:00 +0000873int __pthread_mutexattr_init(pthread_mutexattr_t *attr)
sewardje663cb92002-04-12 10:26:32 +0000874{
sewardjf8f819e2002-04-17 23:21:37 +0000875 attr->__mutexkind = PTHREAD_MUTEX_ERRORCHECK_NP;
sewardj8937c812002-04-12 20:12:20 +0000876 return 0;
sewardje663cb92002-04-12 10:26:32 +0000877}
878
sewardj5905fae2002-04-26 13:25:00 +0000879int __pthread_mutexattr_settype(pthread_mutexattr_t *attr, int type)
sewardjf8f819e2002-04-17 23:21:37 +0000880{
881 switch (type) {
sewardj3b13f0e2002-04-25 20:17:29 +0000882# ifndef GLIBC_2_1
sewardjf8f819e2002-04-17 23:21:37 +0000883 case PTHREAD_MUTEX_TIMED_NP:
sewardj2a1dcce2002-04-22 12:45:25 +0000884 case PTHREAD_MUTEX_ADAPTIVE_NP:
sewardj3b13f0e2002-04-25 20:17:29 +0000885# endif
sewardja1679dd2002-05-10 22:31:40 +0000886# ifdef GLIBC_2_1
sewardj68b2dd92002-05-10 21:03:56 +0000887 case PTHREAD_MUTEX_FAST_NP:
sewardja1679dd2002-05-10 22:31:40 +0000888# endif
sewardjf8f819e2002-04-17 23:21:37 +0000889 case PTHREAD_MUTEX_RECURSIVE_NP:
890 case PTHREAD_MUTEX_ERRORCHECK_NP:
sewardjf8f819e2002-04-17 23:21:37 +0000891 attr->__mutexkind = type;
892 return 0;
893 default:
sewardj4dced352002-06-04 22:54:20 +0000894 pthread_error("pthread_mutexattr_settype: "
895 "invalid type");
sewardjf8f819e2002-04-17 23:21:37 +0000896 return EINVAL;
897 }
898}
899
sewardj5905fae2002-04-26 13:25:00 +0000900int __pthread_mutexattr_destroy(pthread_mutexattr_t *attr)
sewardjf8f819e2002-04-17 23:21:37 +0000901{
902 return 0;
903}
904
sewardjf0995512003-07-06 01:29:49 +0000905int __pthread_mutexattr_setpshared ( pthread_mutexattr_t* attr, int pshared)
sewardj7685cae2003-07-06 01:23:11 +0000906{
907 if (pshared != PTHREAD_PROCESS_PRIVATE && pshared != PTHREAD_PROCESS_SHARED)
908 return EINVAL;
909
910 /* For now it is not possible to shared a conditional variable. */
911 if (pshared != PTHREAD_PROCESS_PRIVATE)
912 return ENOSYS;
913
914 return 0;
915}
916
sewardjf8f819e2002-04-17 23:21:37 +0000917
918/* ---------------------------------------------------
919 MUTEXes
920 ------------------------------------------------ */
921
sewardj5905fae2002-04-26 13:25:00 +0000922int __pthread_mutex_init(pthread_mutex_t *mutex,
923 const pthread_mutexattr_t *mutexattr)
sewardje663cb92002-04-12 10:26:32 +0000924{
sewardj604ec3c2002-04-18 22:38:41 +0000925 mutex->__m_count = 0;
926 mutex->__m_owner = (_pthread_descr)VG_INVALID_THREADID;
927 mutex->__m_kind = PTHREAD_MUTEX_ERRORCHECK_NP;
928 if (mutexattr)
929 mutex->__m_kind = mutexattr->__mutexkind;
930 return 0;
sewardje663cb92002-04-12 10:26:32 +0000931}
932
sewardj439d45e2002-05-03 20:43:10 +0000933
sewardj5905fae2002-04-26 13:25:00 +0000934int __pthread_mutex_lock(pthread_mutex_t *mutex)
sewardje663cb92002-04-12 10:26:32 +0000935{
936 int res;
sewardjd8acdf22002-11-13 21:57:52 +0000937
sewardj439d45e2002-05-03 20:43:10 +0000938 if (RUNNING_ON_VALGRIND) {
sewardje663cb92002-04-12 10:26:32 +0000939 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
940 VG_USERREQ__PTHREAD_MUTEX_LOCK,
941 mutex, 0, 0, 0);
942 return res;
sewardj439d45e2002-05-03 20:43:10 +0000943 } else {
sewardjd8acdf22002-11-13 21:57:52 +0000944 /* Play at locking */
945 if (0)
nethercoteaad8c192003-11-20 14:23:09 +0000946 kludged("prehistoric lock", NULL);
sewardjd8acdf22002-11-13 21:57:52 +0000947 mutex->__m_owner = (_pthread_descr)1;
948 mutex->__m_count = 1;
949 mutex->__m_kind |= VG_PTHREAD_PREHISTORY;
sewardj439d45e2002-05-03 20:43:10 +0000950 return 0; /* success */
sewardje663cb92002-04-12 10:26:32 +0000951 }
952}
953
sewardj439d45e2002-05-03 20:43:10 +0000954
sewardj5905fae2002-04-26 13:25:00 +0000955int __pthread_mutex_trylock(pthread_mutex_t *mutex)
sewardj30671ff2002-04-21 00:13:57 +0000956{
957 int res;
sewardjd8acdf22002-11-13 21:57:52 +0000958
sewardj439d45e2002-05-03 20:43:10 +0000959 if (RUNNING_ON_VALGRIND) {
sewardj30671ff2002-04-21 00:13:57 +0000960 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
961 VG_USERREQ__PTHREAD_MUTEX_TRYLOCK,
962 mutex, 0, 0, 0);
963 return res;
sewardj439d45e2002-05-03 20:43:10 +0000964 } else {
sewardjd8acdf22002-11-13 21:57:52 +0000965 /* Play at locking */
966 if (0)
nethercoteaad8c192003-11-20 14:23:09 +0000967 kludged("prehistoric trylock", NULL);
sewardjd8acdf22002-11-13 21:57:52 +0000968 mutex->__m_owner = (_pthread_descr)1;
969 mutex->__m_count = 1;
970 mutex->__m_kind |= VG_PTHREAD_PREHISTORY;
971 return 0; /* success */
sewardj30671ff2002-04-21 00:13:57 +0000972 }
973}
974
sewardj439d45e2002-05-03 20:43:10 +0000975
sewardj5905fae2002-04-26 13:25:00 +0000976int __pthread_mutex_unlock(pthread_mutex_t *mutex)
sewardje663cb92002-04-12 10:26:32 +0000977{
978 int res;
sewardjd8acdf22002-11-13 21:57:52 +0000979
sewardj439d45e2002-05-03 20:43:10 +0000980 if (RUNNING_ON_VALGRIND) {
sewardje663cb92002-04-12 10:26:32 +0000981 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
982 VG_USERREQ__PTHREAD_MUTEX_UNLOCK,
983 mutex, 0, 0, 0);
984 return res;
sewardj439d45e2002-05-03 20:43:10 +0000985 } else {
sewardjd8acdf22002-11-13 21:57:52 +0000986 /* Play at locking */
987 if (0)
nethercoteaad8c192003-11-20 14:23:09 +0000988 kludged("prehistoric unlock", NULL);
sewardjd8acdf22002-11-13 21:57:52 +0000989 mutex->__m_owner = 0;
990 mutex->__m_count = 0;
991 mutex->__m_kind &= ~VG_PTHREAD_PREHISTORY;
992 return 0; /* success */
sewardje663cb92002-04-12 10:26:32 +0000993 }
994}
995
sewardj439d45e2002-05-03 20:43:10 +0000996
sewardj5905fae2002-04-26 13:25:00 +0000997int __pthread_mutex_destroy(pthread_mutex_t *mutex)
sewardje663cb92002-04-12 10:26:32 +0000998{
sewardj604ec3c2002-04-18 22:38:41 +0000999 /* Valgrind doesn't hold any resources on behalf of the mutex, so no
1000 need to involve it. */
sewardj4dced352002-06-04 22:54:20 +00001001 if (mutex->__m_count > 0) {
sewardjd8acdf22002-11-13 21:57:52 +00001002 /* Oh, the horror. glibc's internal use of pthreads "knows"
1003 that destroying a lock does an implicit unlock. Make it
1004 explicit. */
1005 __pthread_mutex_unlock(mutex);
1006 pthread_error("pthread_mutex_destroy: "
1007 "mutex is still in use");
1008 return EBUSY;
sewardj4dced352002-06-04 22:54:20 +00001009 }
1010 mutex->__m_count = 0;
1011 mutex->__m_owner = (_pthread_descr)VG_INVALID_THREADID;
1012 mutex->__m_kind = PTHREAD_MUTEX_ERRORCHECK_NP;
1013 return 0;
sewardje663cb92002-04-12 10:26:32 +00001014}
1015
1016
sewardjf8f819e2002-04-17 23:21:37 +00001017/* ---------------------------------------------------
sewardj6072c362002-04-19 14:40:57 +00001018 CONDITION VARIABLES
1019 ------------------------------------------------ */
1020
1021/* LinuxThreads supports no attributes for conditions. Hence ... */
1022
1023int pthread_condattr_init(pthread_condattr_t *attr)
1024{
1025 return 0;
1026}
1027
sewardj0738a592002-04-20 13:59:33 +00001028int pthread_condattr_destroy(pthread_condattr_t *attr)
1029{
1030 return 0;
1031}
sewardj6072c362002-04-19 14:40:57 +00001032
1033int pthread_cond_init( pthread_cond_t *cond,
1034 const pthread_condattr_t *cond_attr)
1035{
1036 cond->__c_waiting = (_pthread_descr)VG_INVALID_THREADID;
1037 return 0;
1038}
1039
sewardjf854f472002-04-21 12:19:41 +00001040int pthread_cond_destroy(pthread_cond_t *cond)
1041{
1042 /* should check that no threads are waiting on this CV */
sewardj436e0582002-04-26 14:31:40 +00001043 static int moans = N_MOANS;
1044 if (moans-- > 0)
nethercoteaad8c192003-11-20 14:23:09 +00001045 kludged("pthread_cond_destroy",
1046 "(it doesn't check if the cond is waited on)" );
sewardjf854f472002-04-21 12:19:41 +00001047 return 0;
1048}
sewardj6072c362002-04-19 14:40:57 +00001049
1050/* ---------------------------------------------------
1051 SCHEDULING
1052 ------------------------------------------------ */
1053
1054/* This is completely bogus. */
1055int pthread_getschedparam(pthread_t target_thread,
1056 int *policy,
1057 struct sched_param *param)
1058{
sewardj436e0582002-04-26 14:31:40 +00001059 static int moans = N_MOANS;
1060 if (moans-- > 0)
nethercoteaad8c192003-11-20 14:23:09 +00001061 kludged("pthread_getschedparam", NULL);
sewardj6072c362002-04-19 14:40:57 +00001062 if (policy) *policy = SCHED_OTHER;
sewardj3e909ce2002-06-03 13:27:15 +00001063# ifdef HAVE_SCHED_PRIORITY
sewardj2a1dcce2002-04-22 12:45:25 +00001064 if (param) param->sched_priority = 0; /* who knows */
1065# else
sewardj6072c362002-04-19 14:40:57 +00001066 if (param) param->__sched_priority = 0; /* who knows */
sewardj2a1dcce2002-04-22 12:45:25 +00001067# endif
sewardj6072c362002-04-19 14:40:57 +00001068 return 0;
1069}
1070
1071int pthread_setschedparam(pthread_t target_thread,
1072 int policy,
1073 const struct sched_param *param)
1074{
sewardj436e0582002-04-26 14:31:40 +00001075 static int moans = N_MOANS;
1076 if (moans-- > 0)
nethercoteaad8c192003-11-20 14:23:09 +00001077 ignored("pthread_setschedparam", "(scheduling not changeable)");
sewardj6072c362002-04-19 14:40:57 +00001078 return 0;
1079}
1080
sewardj3b5d8862002-04-20 13:53:23 +00001081int pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex)
1082{
1083 int res;
1084 ensure_valgrind("pthread_cond_wait");
1085 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
1086 VG_USERREQ__PTHREAD_COND_WAIT,
1087 cond, mutex, 0, 0);
1088 return res;
1089}
1090
sewardj5f07b662002-04-23 16:52:51 +00001091int pthread_cond_timedwait ( pthread_cond_t *cond,
1092 pthread_mutex_t *mutex,
1093 const struct timespec *abstime )
1094{
1095 int res;
1096 unsigned int ms_now, ms_end;
1097 struct timeval timeval_now;
1098 unsigned long long int ull_ms_now_after_1970;
1099 unsigned long long int ull_ms_end_after_1970;
1100
1101 ensure_valgrind("pthread_cond_timedwait");
1102 VALGRIND_MAGIC_SEQUENCE(ms_now, 0xFFFFFFFF /* default */,
1103 VG_USERREQ__READ_MILLISECOND_TIMER,
1104 0, 0, 0, 0);
sewardj2d94c112002-06-03 01:25:54 +00001105 my_assert(ms_now != 0xFFFFFFFF);
sewardj5f07b662002-04-23 16:52:51 +00001106 res = gettimeofday(&timeval_now, NULL);
sewardj2d94c112002-06-03 01:25:54 +00001107 my_assert(res == 0);
sewardj5f07b662002-04-23 16:52:51 +00001108
1109 ull_ms_now_after_1970
1110 = 1000ULL * ((unsigned long long int)(timeval_now.tv_sec))
1111 + ((unsigned long long int)(timeval_now.tv_usec / 1000000));
1112 ull_ms_end_after_1970
1113 = 1000ULL * ((unsigned long long int)(abstime->tv_sec))
1114 + ((unsigned long long int)(abstime->tv_nsec / 1000000));
sewardjd8e919e2002-05-29 20:13:53 +00001115 if (ull_ms_end_after_1970 < ull_ms_now_after_1970)
1116 ull_ms_end_after_1970 = ull_ms_now_after_1970;
sewardj5f07b662002-04-23 16:52:51 +00001117 ms_end
1118 = ms_now + (unsigned int)(ull_ms_end_after_1970 - ull_ms_now_after_1970);
1119 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
1120 VG_USERREQ__PTHREAD_COND_TIMEDWAIT,
1121 cond, mutex, ms_end, 0);
1122 return res;
1123}
1124
1125
sewardj3b5d8862002-04-20 13:53:23 +00001126int pthread_cond_signal(pthread_cond_t *cond)
1127{
1128 int res;
1129 ensure_valgrind("pthread_cond_signal");
1130 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
1131 VG_USERREQ__PTHREAD_COND_SIGNAL,
1132 cond, 0, 0, 0);
1133 return res;
1134}
1135
1136int pthread_cond_broadcast(pthread_cond_t *cond)
1137{
1138 int res;
1139 ensure_valgrind("pthread_cond_broadcast");
1140 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
1141 VG_USERREQ__PTHREAD_COND_BROADCAST,
1142 cond, 0, 0, 0);
1143 return res;
1144}
1145
sewardj6072c362002-04-19 14:40:57 +00001146
1147/* ---------------------------------------------------
sewardjf8f819e2002-04-17 23:21:37 +00001148 CANCELLATION
1149 ------------------------------------------------ */
1150
sewardj853f55d2002-04-26 00:27:53 +00001151int pthread_setcancelstate(int state, int *oldstate)
1152{
sewardj20917d82002-05-28 01:36:45 +00001153 int res;
1154 ensure_valgrind("pthread_setcancelstate");
1155 if (state != PTHREAD_CANCEL_ENABLE
sewardj4dced352002-06-04 22:54:20 +00001156 && state != PTHREAD_CANCEL_DISABLE) {
1157 pthread_error("pthread_setcancelstate: "
1158 "invalid state");
sewardj20917d82002-05-28 01:36:45 +00001159 return EINVAL;
sewardj4dced352002-06-04 22:54:20 +00001160 }
sewardj2d94c112002-06-03 01:25:54 +00001161 my_assert(-1 != PTHREAD_CANCEL_ENABLE);
1162 my_assert(-1 != PTHREAD_CANCEL_DISABLE);
sewardj20917d82002-05-28 01:36:45 +00001163 VALGRIND_MAGIC_SEQUENCE(res, (-1) /* default */,
1164 VG_USERREQ__SET_CANCELSTATE,
1165 state, 0, 0, 0);
sewardj2d94c112002-06-03 01:25:54 +00001166 my_assert(res != -1);
sewardj20917d82002-05-28 01:36:45 +00001167 if (oldstate)
1168 *oldstate = res;
sewardj853f55d2002-04-26 00:27:53 +00001169 return 0;
1170}
1171
sewardje663cb92002-04-12 10:26:32 +00001172int pthread_setcanceltype(int type, int *oldtype)
1173{
sewardj20917d82002-05-28 01:36:45 +00001174 int res;
1175 ensure_valgrind("pthread_setcanceltype");
1176 if (type != PTHREAD_CANCEL_DEFERRED
sewardj4dced352002-06-04 22:54:20 +00001177 && type != PTHREAD_CANCEL_ASYNCHRONOUS) {
1178 pthread_error("pthread_setcanceltype: "
1179 "invalid type");
sewardj20917d82002-05-28 01:36:45 +00001180 return EINVAL;
sewardj4dced352002-06-04 22:54:20 +00001181 }
sewardj2d94c112002-06-03 01:25:54 +00001182 my_assert(-1 != PTHREAD_CANCEL_DEFERRED);
1183 my_assert(-1 != PTHREAD_CANCEL_ASYNCHRONOUS);
sewardj20917d82002-05-28 01:36:45 +00001184 VALGRIND_MAGIC_SEQUENCE(res, (-1) /* default */,
1185 VG_USERREQ__SET_CANCELTYPE,
1186 type, 0, 0, 0);
sewardj2d94c112002-06-03 01:25:54 +00001187 my_assert(res != -1);
sewardj20917d82002-05-28 01:36:45 +00001188 if (oldtype)
1189 *oldtype = res;
sewardje663cb92002-04-12 10:26:32 +00001190 return 0;
1191}
1192
sewardje663cb92002-04-12 10:26:32 +00001193int pthread_cancel(pthread_t thread)
1194{
1195 int res;
1196 ensure_valgrind("pthread_cancel");
sewardj20917d82002-05-28 01:36:45 +00001197 VALGRIND_MAGIC_SEQUENCE(res, (-1) /* default */,
1198 VG_USERREQ__SET_CANCELPEND,
1199 thread, &thread_exit_wrapper, 0, 0);
sewardj2d94c112002-06-03 01:25:54 +00001200 my_assert(res != -1);
sewardje663cb92002-04-12 10:26:32 +00001201 return res;
1202}
1203
jsgf855d93d2003-10-13 22:26:55 +00001204static
sewardjd140e442002-05-29 01:21:19 +00001205void __my_pthread_testcancel(void)
sewardj853f55d2002-04-26 00:27:53 +00001206{
sewardj20917d82002-05-28 01:36:45 +00001207 int res;
njn25e49d8e72002-09-23 09:36:25 +00001208 ensure_valgrind("__my_pthread_testcancel");
sewardj20917d82002-05-28 01:36:45 +00001209 VALGRIND_MAGIC_SEQUENCE(res, (-1) /* default */,
1210 VG_USERREQ__TESTCANCEL,
1211 0, 0, 0, 0);
sewardj2d94c112002-06-03 01:25:54 +00001212 my_assert(res == 0);
sewardj853f55d2002-04-26 00:27:53 +00001213}
1214
sewardjd140e442002-05-29 01:21:19 +00001215void pthread_testcancel ( void )
1216{
1217 __my_pthread_testcancel();
1218}
1219
sewardj20917d82002-05-28 01:36:45 +00001220
sewardjef037c72002-05-30 00:40:03 +00001221/* Not really sure what this is for. I suspect for doing the POSIX
1222 requirements for fork() and exec(). We do this internally anyway
1223 whenever those syscalls are observed, so this could be superfluous,
1224 but hey ...
1225*/
sewardj853f55d2002-04-26 00:27:53 +00001226void __pthread_kill_other_threads_np ( void )
1227{
sewardjef037c72002-05-30 00:40:03 +00001228 int res;
1229 ensure_valgrind("__pthread_kill_other_threads_np");
1230 VALGRIND_MAGIC_SEQUENCE(res, (-1) /* default */,
1231 VG_USERREQ__NUKE_OTHER_THREADS,
1232 0, 0, 0, 0);
sewardj2d94c112002-06-03 01:25:54 +00001233 my_assert(res == 0);
sewardj853f55d2002-04-26 00:27:53 +00001234}
1235
sewardje663cb92002-04-12 10:26:32 +00001236
sewardjf8f819e2002-04-17 23:21:37 +00001237/* ---------------------------------------------------
sewardjb48e5002002-05-13 00:16:03 +00001238 SIGNALS
1239 ------------------------------------------------ */
1240
1241#include <signal.h>
1242
1243int pthread_sigmask(int how, const sigset_t *newmask,
1244 sigset_t *oldmask)
1245{
1246 int res;
1247
1248 /* A bit subtle, because the scheduler expects newmask and oldmask
1249 to be vki_sigset_t* rather than sigset_t*, and the two are
1250 different. Fortunately the first 64 bits of a sigset_t are
1251 exactly a vki_sigset_t, so we just pass the pointers through
1252 unmodified. Haaaack!
1253
1254 Also mash the how value so that the SIG_ constants from glibc
sewardj018f7622002-05-15 21:13:39 +00001255 constants to VKI_ constants, so that the former do not have to
1256 be included into vg_scheduler.c. */
sewardjb48e5002002-05-13 00:16:03 +00001257
1258 ensure_valgrind("pthread_sigmask");
1259
1260 switch (how) {
sewardj018f7622002-05-15 21:13:39 +00001261 case SIG_SETMASK: how = VKI_SIG_SETMASK; break;
1262 case SIG_BLOCK: how = VKI_SIG_BLOCK; break;
1263 case SIG_UNBLOCK: how = VKI_SIG_UNBLOCK; break;
sewardj4dced352002-06-04 22:54:20 +00001264 default: pthread_error("pthread_sigmask: invalid how");
1265 return EINVAL;
sewardjb48e5002002-05-13 00:16:03 +00001266 }
1267
sewardjb48e5002002-05-13 00:16:03 +00001268 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
1269 VG_USERREQ__PTHREAD_SIGMASK,
1270 how, newmask, oldmask, 0);
1271
1272 /* The scheduler tells us of any memory violations. */
1273 return res == 0 ? 0 : EFAULT;
1274}
1275
sewardjb48e5002002-05-13 00:16:03 +00001276int sigwait ( const sigset_t* set, int* sig )
1277{
1278 int res;
jsgf855d93d2003-10-13 22:26:55 +00001279 vki_ksiginfo_t si;
1280
1281 __my_pthread_testcancel();
1282
sewardjb48e5002002-05-13 00:16:03 +00001283 /* As with pthread_sigmask we deliberately confuse sigset_t with
1284 vki_ksigset_t. */
jsgf855d93d2003-10-13 22:26:55 +00001285 si.si_signo = 0;
1286 res = VG_(ksigtimedwait)((const vki_ksigset_t *)set, &si, NULL);
1287 *sig = si.si_signo;
1288
1289 return 0; /* always returns 0 */
sewardjb48e5002002-05-13 00:16:03 +00001290}
1291
1292
sewardj018f7622002-05-15 21:13:39 +00001293int pthread_kill(pthread_t thread, int signo)
1294{
1295 int res;
1296 ensure_valgrind("pthread_kill");
1297 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
1298 VG_USERREQ__PTHREAD_KILL,
1299 thread, signo, 0, 0);
1300 return res;
1301}
1302
1303
sewardj3665ded2002-05-16 16:57:25 +00001304/* Copied verbatim from Linuxthreads */
1305/* Redefine raise() to send signal to calling thread only,
1306 as per POSIX 1003.1c */
1307int raise (int sig)
1308{
1309 int retcode = pthread_kill(pthread_self(), sig);
sewardj4dced352002-06-04 22:54:20 +00001310 if (retcode == 0) {
sewardj3665ded2002-05-16 16:57:25 +00001311 return 0;
sewardj4dced352002-06-04 22:54:20 +00001312 } else {
sewardj25418ae2003-05-09 23:40:34 +00001313 *(__errno_location()) = retcode;
sewardj3665ded2002-05-16 16:57:25 +00001314 return -1;
1315 }
1316}
1317
1318
sewardj9a2224b2002-06-19 10:17:40 +00001319
sewardjb48e5002002-05-13 00:16:03 +00001320/* ---------------------------------------------------
sewardjf8f819e2002-04-17 23:21:37 +00001321 THREAD-SPECIFICs
1322 ------------------------------------------------ */
sewardj5e5fa512002-04-14 13:13:05 +00001323
sewardj00a66b12002-10-12 16:42:35 +00001324static
1325int key_is_valid (pthread_key_t key)
1326{
1327 int res;
1328 VALGRIND_MAGIC_SEQUENCE(res, 2 /* default */,
1329 VG_USERREQ__PTHREAD_KEY_VALIDATE,
1330 key, 0, 0, 0);
1331 my_assert(res != 2);
1332 return res;
1333}
1334
1335
1336/* Returns NULL if thread is invalid. Otherwise, if the thread
1337 already has a specifics area, return that. Otherwise allocate it
1338 one. */
1339static
1340void** get_or_allocate_specifics_ptr ( pthread_t thread )
1341{
1342 int res, i;
1343 void** specifics_ptr;
1344 ensure_valgrind("get_or_allocate_specifics_ptr");
1345
1346 /* Returns zero if the thread has no specific_ptr. One if thread
1347 is invalid. Otherwise, the specific_ptr value. This is
1348 allocated with my_malloc and so is aligned and cannot be
1349 confused with 1 or 3. */
1350 VALGRIND_MAGIC_SEQUENCE(specifics_ptr, 3 /* default */,
1351 VG_USERREQ__PTHREAD_GETSPECIFIC_PTR,
1352 thread, 0, 0, 0);
1353 my_assert(specifics_ptr != (void**)3);
1354
1355 if (specifics_ptr == (void**)1)
1356 return NULL; /* invalid thread */
1357
1358 if (specifics_ptr != NULL)
1359 return specifics_ptr; /* already has a specifics ptr. */
1360
1361 /* None yet ... allocate a new one. Should never fail. */
1362 specifics_ptr = my_malloc( VG_N_THREAD_KEYS * sizeof(void*) );
1363 my_assert(specifics_ptr != NULL);
1364
1365 VALGRIND_MAGIC_SEQUENCE(res, -1 /* default */,
1366 VG_USERREQ__PTHREAD_SETSPECIFIC_PTR,
1367 specifics_ptr, 0, 0, 0);
1368 my_assert(res == 0);
1369
1370 /* POSIX sez: "Upon thread creation, the value NULL shall be
1371 associated with all defined keys in the new thread." This
1372 allocation is in effect a delayed allocation of the specific
1373 data for a thread, at its first-use. Hence we initialise it
1374 here. */
1375 for (i = 0; i < VG_N_THREAD_KEYS; i++) {
1376 specifics_ptr[i] = NULL;
1377 }
1378
1379 return specifics_ptr;
1380}
1381
1382
sewardj5905fae2002-04-26 13:25:00 +00001383int __pthread_key_create(pthread_key_t *key,
1384 void (*destr_function) (void *))
sewardj5e5fa512002-04-14 13:13:05 +00001385{
sewardj00a66b12002-10-12 16:42:35 +00001386 void** specifics_ptr;
1387 int res, i;
sewardj5f07b662002-04-23 16:52:51 +00001388 ensure_valgrind("pthread_key_create");
sewardj00a66b12002-10-12 16:42:35 +00001389
1390 /* This writes *key if successful. It should never fail. */
1391 VALGRIND_MAGIC_SEQUENCE(res, 1 /* default */,
sewardj5f07b662002-04-23 16:52:51 +00001392 VG_USERREQ__PTHREAD_KEY_CREATE,
1393 key, destr_function, 0, 0);
jsgf855d93d2003-10-13 22:26:55 +00001394
1395 if (res == 0) {
1396 /* POSIX sez: "Upon key creation, the value NULL shall be
1397 associated with the new key in all active threads." */
1398 for (i = 0; i < VG_N_THREADS; i++) {
1399 specifics_ptr = get_or_allocate_specifics_ptr(i);
1400 /* we get NULL if i is an invalid thread. */
1401 if (specifics_ptr != NULL)
1402 specifics_ptr[*key] = NULL;
1403 }
sewardj00a66b12002-10-12 16:42:35 +00001404 }
1405
sewardj5f07b662002-04-23 16:52:51 +00001406 return res;
sewardj5e5fa512002-04-14 13:13:05 +00001407}
1408
1409int pthread_key_delete(pthread_key_t key)
1410{
sewardj00a66b12002-10-12 16:42:35 +00001411 int res;
njndfc9b8c2003-09-29 12:58:37 +00001412 ensure_valgrind("pthread_key_delete");
sewardj00a66b12002-10-12 16:42:35 +00001413 if (!key_is_valid(key))
1414 return EINVAL;
1415 VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
1416 VG_USERREQ__PTHREAD_KEY_DELETE,
1417 key, 0, 0, 0);
1418 my_assert(res == 0);
sewardj5e5fa512002-04-14 13:13:05 +00001419 return 0;
1420}
1421
sewardj5905fae2002-04-26 13:25:00 +00001422int __pthread_setspecific(pthread_key_t key, const void *pointer)
sewardj5e5fa512002-04-14 13:13:05 +00001423{
sewardj00a66b12002-10-12 16:42:35 +00001424 void** specifics_ptr;
sewardj5f07b662002-04-23 16:52:51 +00001425 ensure_valgrind("pthread_setspecific");
sewardj00a66b12002-10-12 16:42:35 +00001426
1427 if (!key_is_valid(key))
1428 return EINVAL;
1429
1430 specifics_ptr = get_or_allocate_specifics_ptr(pthread_self());
1431 specifics_ptr[key] = (void*)pointer;
1432 return 0;
sewardj5e5fa512002-04-14 13:13:05 +00001433}
1434
sewardj5905fae2002-04-26 13:25:00 +00001435void * __pthread_getspecific(pthread_key_t key)
sewardj5e5fa512002-04-14 13:13:05 +00001436{
sewardj00a66b12002-10-12 16:42:35 +00001437 void** specifics_ptr;
sewardj5f07b662002-04-23 16:52:51 +00001438 ensure_valgrind("pthread_getspecific");
sewardj00a66b12002-10-12 16:42:35 +00001439
1440 if (!key_is_valid(key))
1441 return NULL;
1442
1443 specifics_ptr = get_or_allocate_specifics_ptr(pthread_self());
1444 return specifics_ptr[key];
1445}
1446
1447
sewardj9aa918d2002-10-20 16:25:55 +00001448#ifdef GLIBC_2_3
sewardj00a66b12002-10-12 16:42:35 +00001449static
1450void ** __pthread_getspecific_addr(pthread_key_t key)
1451{
1452 void** specifics_ptr;
1453 ensure_valgrind("pthread_getspecific_addr");
1454
1455 if (!key_is_valid(key))
1456 return NULL;
1457
1458 specifics_ptr = get_or_allocate_specifics_ptr(pthread_self());
1459 return &(specifics_ptr[key]);
sewardj5e5fa512002-04-14 13:13:05 +00001460}
sewardj9aa918d2002-10-20 16:25:55 +00001461#endif
sewardjf8f819e2002-04-17 23:21:37 +00001462
sewardjc91a4ff2003-07-11 00:12:58 +00001463
sewardjf8f819e2002-04-17 23:21:37 +00001464/* ---------------------------------------------------
sewardj89d3d852002-04-24 19:21:39 +00001465 ONCEry
1466 ------------------------------------------------ */
1467
sewardjc91a4ff2003-07-11 00:12:58 +00001468/* This protects reads and writes of the once_control variable
1469 supplied. It is never held whilst any particular initialiser is
1470 running. */
sewardj89d3d852002-04-24 19:21:39 +00001471static pthread_mutex_t once_masterlock = PTHREAD_MUTEX_INITIALIZER;
1472
sewardjc91a4ff2003-07-11 00:12:58 +00001473/* Initialiser needs to be run. */
1474#define P_ONCE_NOT_DONE ((PTHREAD_ONCE_INIT) + 0)
1475
1476/* Initialiser currently running. */
1477#define P_ONCE_RUNNING ((PTHREAD_ONCE_INIT) + 1)
1478
1479/* Initialiser has completed. */
1480#define P_ONCE_COMPLETED ((PTHREAD_ONCE_INIT) + 2)
sewardj89d3d852002-04-24 19:21:39 +00001481
sewardj5905fae2002-04-26 13:25:00 +00001482int __pthread_once ( pthread_once_t *once_control,
1483 void (*init_routine) (void) )
sewardj89d3d852002-04-24 19:21:39 +00001484{
1485 int res;
sewardjc91a4ff2003-07-11 00:12:58 +00001486 int done;
sewardj89d3d852002-04-24 19:21:39 +00001487
sewardjc91a4ff2003-07-11 00:12:58 +00001488# define TAKE_LOCK \
1489 res = __pthread_mutex_lock(&once_masterlock); \
1490 my_assert(res == 0);
sewardj89d3d852002-04-24 19:21:39 +00001491
sewardjc91a4ff2003-07-11 00:12:58 +00001492# define RELEASE_LOCK \
1493 res = __pthread_mutex_unlock(&once_masterlock); \
1494 my_assert(res == 0);
sewardj89d3d852002-04-24 19:21:39 +00001495
jsgf855d93d2003-10-13 22:26:55 +00001496 void cleanup(void *v) {
1497 TAKE_LOCK;
1498 *once_control = P_ONCE_NOT_DONE;
1499 RELEASE_LOCK;
1500 }
1501
1502 ensure_valgrind("pthread_once");
1503
sewardjc91a4ff2003-07-11 00:12:58 +00001504 /* Grab the lock transiently, so we can safely see what state this
1505 once_control is in. */
1506
1507 TAKE_LOCK;
1508
1509 switch (*once_control) {
1510
1511 case P_ONCE_NOT_DONE:
1512 /* Not started. Change state to indicate running, drop the
1513 lock and run. */
1514 *once_control = P_ONCE_RUNNING;
jsgf855d93d2003-10-13 22:26:55 +00001515 _pthread_cleanup_push(NULL, cleanup, NULL);
sewardjc91a4ff2003-07-11 00:12:58 +00001516 RELEASE_LOCK;
1517 init_routine();
1518 /* re-take the lock, and set state to indicate done. */
1519 TAKE_LOCK;
jsgf855d93d2003-10-13 22:26:55 +00001520 _pthread_cleanup_pop(NULL, False);
sewardjc91a4ff2003-07-11 00:12:58 +00001521 *once_control = P_ONCE_COMPLETED;
1522 RELEASE_LOCK;
1523 break;
1524
1525 case P_ONCE_RUNNING:
1526 /* This is the tricky case. The initialiser is running in
1527 some other thread, but we have to delay this thread till
1528 the other one completes. So we sort-of busy wait. In
1529 fact it makes sense to yield now, because what we want to
1530 happen is for the thread running the initialiser to
1531 complete ASAP. */
1532 RELEASE_LOCK;
1533 done = 0;
1534 while (1) {
1535 /* Let others run for a while. */
1536 __valgrind_pthread_yield();
1537 /* Grab the lock and see if we're done waiting. */
1538 TAKE_LOCK;
1539 if (*once_control == P_ONCE_COMPLETED)
1540 done = 1;
1541 RELEASE_LOCK;
1542 if (done)
1543 break;
1544 }
1545 break;
1546
1547 case P_ONCE_COMPLETED:
1548 default:
1549 /* Easy. It's already done. Just drop the lock. */
1550 RELEASE_LOCK;
1551 break;
sewardj89d3d852002-04-24 19:21:39 +00001552 }
1553
sewardj89d3d852002-04-24 19:21:39 +00001554 return 0;
sewardjc91a4ff2003-07-11 00:12:58 +00001555
1556# undef TAKE_LOCK
1557# undef RELEASE_LOCK
sewardj89d3d852002-04-24 19:21:39 +00001558}
1559
sewardjc91a4ff2003-07-11 00:12:58 +00001560#undef P_ONCE_NOT_DONE
1561#undef P_ONCE_RUNNING
1562#undef P_ONCE_COMPLETED
1563
sewardj89d3d852002-04-24 19:21:39 +00001564
1565/* ---------------------------------------------------
sewardj853f55d2002-04-26 00:27:53 +00001566 MISC
1567 ------------------------------------------------ */
1568
sewardj2cb00342002-06-28 01:46:26 +00001569static pthread_mutex_t pthread_atfork_lock
1570 = PTHREAD_MUTEX_INITIALIZER;
1571
sewardj5905fae2002-04-26 13:25:00 +00001572int __pthread_atfork ( void (*prepare)(void),
1573 void (*parent)(void),
1574 void (*child)(void) )
sewardj853f55d2002-04-26 00:27:53 +00001575{
sewardj2cb00342002-06-28 01:46:26 +00001576 int n, res;
1577 ForkHandlerEntry entry;
1578
1579 ensure_valgrind("pthread_atfork");
1580 __pthread_mutex_lock(&pthread_atfork_lock);
1581
1582 /* Fetch old counter */
1583 VALGRIND_MAGIC_SEQUENCE(n, -2 /* default */,
1584 VG_USERREQ__GET_FHSTACK_USED,
1585 0, 0, 0, 0);
1586 my_assert(n >= 0 && n < VG_N_FORKHANDLERSTACK);
1587 if (n == VG_N_FORKHANDLERSTACK-1)
1588 barf("pthread_atfork: VG_N_FORKHANDLERSTACK is too low; "
1589 "increase and recompile");
1590
1591 /* Add entry */
1592 entry.prepare = *prepare;
1593 entry.parent = *parent;
1594 entry.child = *child;
1595 VALGRIND_MAGIC_SEQUENCE(res, -2 /* default */,
1596 VG_USERREQ__SET_FHSTACK_ENTRY,
1597 n, &entry, 0, 0);
1598 my_assert(res == 0);
1599
1600 /* Bump counter */
1601 VALGRIND_MAGIC_SEQUENCE(res, -2 /* default */,
1602 VG_USERREQ__SET_FHSTACK_USED,
1603 n+1, 0, 0, 0);
1604 my_assert(res == 0);
1605
1606 __pthread_mutex_unlock(&pthread_atfork_lock);
1607 return 0;
sewardj853f55d2002-04-26 00:27:53 +00001608}
1609
1610
sewardj9df78832003-05-04 12:35:54 +00001611#ifdef GLIBC_2_3
1612/* This seems to be a hook which appeared in glibc-2.3.2. */
1613int __register_atfork ( void (*prepare)(void),
1614 void (*parent)(void),
1615 void (*child)(void) )
1616{
1617 return __pthread_atfork(prepare,parent,child);
1618}
1619#endif
1620
sewardj11f0bb42003-04-26 20:11:15 +00001621WEAK
sewardjbb990782002-05-08 02:01:14 +00001622void __pthread_initialize ( void )
1623{
sewardjbea1caa2002-05-10 23:20:58 +00001624 ensure_valgrind("__pthread_initialize");
sewardjbb990782002-05-08 02:01:14 +00001625}
1626
1627
sewardj853f55d2002-04-26 00:27:53 +00001628/* ---------------------------------------------------
sewardj3b13f0e2002-04-25 20:17:29 +00001629 LIBRARY-PRIVATE THREAD SPECIFIC STATE
sewardjf8f819e2002-04-17 23:21:37 +00001630 ------------------------------------------------ */
1631
sewardj3b13f0e2002-04-25 20:17:29 +00001632#include <resolv.h>
1633static int thread_specific_errno[VG_N_THREADS];
1634static int thread_specific_h_errno[VG_N_THREADS];
1635static struct __res_state
1636 thread_specific_res_state[VG_N_THREADS];
sewardjf8f819e2002-04-17 23:21:37 +00001637
sewardj25418ae2003-05-09 23:40:34 +00001638#undef errno
1639extern int errno;
sewardj3b13f0e2002-04-25 20:17:29 +00001640int* __errno_location ( void )
sewardjf8f819e2002-04-17 23:21:37 +00001641{
1642 int tid;
sewardj3b13f0e2002-04-25 20:17:29 +00001643 /* ensure_valgrind("__errno_location"); */
1644 VALGRIND_MAGIC_SEQUENCE(tid, 1 /* default */,
sewardjf8f819e2002-04-17 23:21:37 +00001645 VG_USERREQ__PTHREAD_GET_THREADID,
1646 0, 0, 0, 0);
sewardj3b13f0e2002-04-25 20:17:29 +00001647 /* 'cos I'm paranoid ... */
sewardj439d45e2002-05-03 20:43:10 +00001648 if (tid < 1 || tid >= VG_N_THREADS)
sewardj3b13f0e2002-04-25 20:17:29 +00001649 barf("__errno_location: invalid ThreadId");
sewardj25418ae2003-05-09 23:40:34 +00001650 if (tid == 1)
1651 return &errno;
sewardj3b13f0e2002-04-25 20:17:29 +00001652 return & thread_specific_errno[tid];
1653}
1654
sewardj25418ae2003-05-09 23:40:34 +00001655#undef h_errno
1656extern int h_errno;
sewardj3b13f0e2002-04-25 20:17:29 +00001657int* __h_errno_location ( void )
1658{
1659 int tid;
1660 /* ensure_valgrind("__h_errno_location"); */
1661 VALGRIND_MAGIC_SEQUENCE(tid, 1 /* default */,
1662 VG_USERREQ__PTHREAD_GET_THREADID,
1663 0, 0, 0, 0);
1664 /* 'cos I'm paranoid ... */
sewardj439d45e2002-05-03 20:43:10 +00001665 if (tid < 1 || tid >= VG_N_THREADS)
sewardj3b13f0e2002-04-25 20:17:29 +00001666 barf("__h_errno_location: invalid ThreadId");
sewardj25418ae2003-05-09 23:40:34 +00001667 if (tid == 1)
1668 return &h_errno;
sewardj3b13f0e2002-04-25 20:17:29 +00001669 return & thread_specific_h_errno[tid];
1670}
1671
sewardjb0ff1032002-08-06 09:02:53 +00001672
1673#undef _res
1674extern struct __res_state _res;
sewardj3b13f0e2002-04-25 20:17:29 +00001675struct __res_state* __res_state ( void )
1676{
1677 int tid;
1678 /* ensure_valgrind("__res_state"); */
1679 VALGRIND_MAGIC_SEQUENCE(tid, 1 /* default */,
1680 VG_USERREQ__PTHREAD_GET_THREADID,
1681 0, 0, 0, 0);
1682 /* 'cos I'm paranoid ... */
sewardj439d45e2002-05-03 20:43:10 +00001683 if (tid < 1 || tid >= VG_N_THREADS)
sewardj3b13f0e2002-04-25 20:17:29 +00001684 barf("__res_state: invalid ThreadId");
sewardjb0ff1032002-08-06 09:02:53 +00001685 if (tid == 1)
1686 return & _res;
sewardj3b13f0e2002-04-25 20:17:29 +00001687 return & thread_specific_res_state[tid];
sewardjf8f819e2002-04-17 23:21:37 +00001688}
1689
1690
sewardj5716dbb2002-04-26 03:28:18 +00001691/* ---------------------------------------------------
1692 LIBC-PRIVATE SPECIFIC DATA
1693 ------------------------------------------------ */
1694
1695/* Relies on assumption that initial private data is NULL. This
1696 should be fixed somehow. */
1697
njn25e49d8e72002-09-23 09:36:25 +00001698/* The allowable keys (indices) (all 3 of them).
sewardj5716dbb2002-04-26 03:28:18 +00001699 From sysdeps/pthread/bits/libc-tsd.h
1700*/
sewardjcb7f08a2002-10-02 09:41:49 +00001701/* as per glibc anoncvs HEAD of 20021001. */
sewardj5716dbb2002-04-26 03:28:18 +00001702enum __libc_tsd_key_t { _LIBC_TSD_KEY_MALLOC = 0,
1703 _LIBC_TSD_KEY_DL_ERROR,
njn25e49d8e72002-09-23 09:36:25 +00001704 _LIBC_TSD_KEY_RPC_VARS,
sewardjcb7f08a2002-10-02 09:41:49 +00001705 _LIBC_TSD_KEY_LOCALE,
1706 _LIBC_TSD_KEY_CTYPE_B,
1707 _LIBC_TSD_KEY_CTYPE_TOLOWER,
1708 _LIBC_TSD_KEY_CTYPE_TOUPPER,
sewardj5716dbb2002-04-26 03:28:18 +00001709 _LIBC_TSD_KEY_N };
1710
1711/* Auto-initialising subsystem. libc_specifics_inited is set
1712 after initialisation. libc_specifics_inited_mx guards it. */
1713static int libc_specifics_inited = 0;
1714static pthread_mutex_t libc_specifics_inited_mx = PTHREAD_MUTEX_INITIALIZER;
1715
sewardj00a66b12002-10-12 16:42:35 +00001716
sewardj5716dbb2002-04-26 03:28:18 +00001717/* These are the keys we must initialise the first time. */
sewardjcb7f08a2002-10-02 09:41:49 +00001718static pthread_key_t libc_specifics_keys[_LIBC_TSD_KEY_N];
sewardj5716dbb2002-04-26 03:28:18 +00001719
sewardj00a66b12002-10-12 16:42:35 +00001720
sewardjcb7f08a2002-10-02 09:41:49 +00001721/* Initialise the keys, if they are not already initialised. */
sewardj5716dbb2002-04-26 03:28:18 +00001722static
1723void init_libc_tsd_keys ( void )
1724{
1725 int res, i;
1726 pthread_key_t k;
1727
sewardj08c7f012002-10-07 23:56:55 +00001728 /* Don't fall into deadlock if we get called again whilst we still
1729 hold the lock, via the __uselocale() call herein. */
1730 if (libc_specifics_inited != 0)
1731 return;
1732
1733 /* Take the lock. */
sewardj00a66b12002-10-12 16:42:35 +00001734 res = __pthread_mutex_lock(&libc_specifics_inited_mx);
sewardj5716dbb2002-04-26 03:28:18 +00001735 if (res != 0) barf("init_libc_tsd_keys: lock");
1736
sewardj08c7f012002-10-07 23:56:55 +00001737 /* Now test again, to be sure there is no mistake. */
1738 if (libc_specifics_inited != 0) {
sewardj00a66b12002-10-12 16:42:35 +00001739 res = __pthread_mutex_unlock(&libc_specifics_inited_mx);
sewardj08c7f012002-10-07 23:56:55 +00001740 if (res != 0) barf("init_libc_tsd_keys: unlock(1)");
1741 return;
sewardj5716dbb2002-04-26 03:28:18 +00001742 }
1743
sewardj08c7f012002-10-07 23:56:55 +00001744 /* Actually do the initialisation. */
1745 /* printf("INIT libc specifics\n"); */
1746 for (i = 0; i < _LIBC_TSD_KEY_N; i++) {
sewardj00a66b12002-10-12 16:42:35 +00001747 res = __pthread_key_create(&k, NULL);
sewardj08c7f012002-10-07 23:56:55 +00001748 if (res != 0) barf("init_libc_tsd_keys: create");
1749 libc_specifics_keys[i] = k;
1750 }
1751
1752 /* Signify init done. */
1753 libc_specifics_inited = 1;
1754
1755# ifdef GLIBC_2_3
1756 /* Set the initialising thread's locale to the global (default)
sewardj00a66b12002-10-12 16:42:35 +00001757 locale. A hack in support of glibc-2.3. This does the biz for
1758 the root thread. For all other threads we run this in
1759 thread_wrapper(), which does the real work of
1760 pthread_create(). */
1761 /* assert that we are the root thread. I don't know if this is
1762 really a valid assertion to make; if it breaks I'll reconsider
1763 it. */
1764 my_assert(pthread_self() == 1);
sewardj08c7f012002-10-07 23:56:55 +00001765 __uselocale(LC_GLOBAL_LOCALE);
1766# endif
1767
1768 /* Unlock and return. */
sewardj00a66b12002-10-12 16:42:35 +00001769 res = __pthread_mutex_unlock(&libc_specifics_inited_mx);
sewardj5716dbb2002-04-26 03:28:18 +00001770 if (res != 0) barf("init_libc_tsd_keys: unlock");
1771}
1772
1773
1774static int
1775libc_internal_tsd_set ( enum __libc_tsd_key_t key,
1776 const void * pointer )
1777{
sewardjcb7f08a2002-10-02 09:41:49 +00001778 int res;
sewardj5716dbb2002-04-26 03:28:18 +00001779 /* printf("SET SET SET key %d ptr %p\n", key, pointer); */
sewardjcb7f08a2002-10-02 09:41:49 +00001780 if (key < _LIBC_TSD_KEY_MALLOC || key >= _LIBC_TSD_KEY_N)
sewardj5716dbb2002-04-26 03:28:18 +00001781 barf("libc_internal_tsd_set: invalid key");
1782 init_libc_tsd_keys();
sewardj00a66b12002-10-12 16:42:35 +00001783 res = __pthread_setspecific(libc_specifics_keys[key], pointer);
sewardj5716dbb2002-04-26 03:28:18 +00001784 if (res != 0) barf("libc_internal_tsd_set: setspecific failed");
1785 return 0;
1786}
1787
1788static void *
1789libc_internal_tsd_get ( enum __libc_tsd_key_t key )
1790{
sewardjcb7f08a2002-10-02 09:41:49 +00001791 void* v;
sewardj5716dbb2002-04-26 03:28:18 +00001792 /* printf("GET GET GET key %d\n", key); */
sewardjcb7f08a2002-10-02 09:41:49 +00001793 if (key < _LIBC_TSD_KEY_MALLOC || key >= _LIBC_TSD_KEY_N)
sewardj5716dbb2002-04-26 03:28:18 +00001794 barf("libc_internal_tsd_get: invalid key");
1795 init_libc_tsd_keys();
sewardj00a66b12002-10-12 16:42:35 +00001796 v = __pthread_getspecific(libc_specifics_keys[key]);
sewardj5716dbb2002-04-26 03:28:18 +00001797 /* if (v == NULL) barf("libc_internal_tsd_set: getspecific failed"); */
1798 return v;
1799}
1800
1801
sewardj70adeb22002-04-27 01:35:38 +00001802int (*__libc_internal_tsd_set)
1803 (enum __libc_tsd_key_t key, const void * pointer)
1804 = libc_internal_tsd_set;
sewardj5716dbb2002-04-26 03:28:18 +00001805
sewardj70adeb22002-04-27 01:35:38 +00001806void* (*__libc_internal_tsd_get)
1807 (enum __libc_tsd_key_t key)
1808 = libc_internal_tsd_get;
sewardj5716dbb2002-04-26 03:28:18 +00001809
1810
sewardj00a66b12002-10-12 16:42:35 +00001811#ifdef GLIBC_2_3
1812/* This one was first spotted be me in the glibc-2.2.93 sources. */
1813static void**
1814libc_internal_tsd_address ( enum __libc_tsd_key_t key )
1815{
1816 void** v;
1817 /* printf("ADDR ADDR ADDR key %d\n", key); */
1818 if (key < _LIBC_TSD_KEY_MALLOC || key >= _LIBC_TSD_KEY_N)
1819 barf("libc_internal_tsd_address: invalid key");
1820 init_libc_tsd_keys();
1821 v = __pthread_getspecific_addr(libc_specifics_keys[key]);
1822 return v;
1823}
1824
1825void ** (*__libc_internal_tsd_address)
1826 (enum __libc_tsd_key_t key)
1827 = libc_internal_tsd_address;
1828#endif
1829
1830
sewardje663cb92002-04-12 10:26:32 +00001831/* ---------------------------------------------------------------------
1832 These are here (I think) because they are deemed cancellation
1833 points by POSIX. For the moment we'll simply pass the call along
1834 to the corresponding thread-unaware (?) libc routine.
1835 ------------------------------------------------------------------ */
1836
sewardjd529a442002-05-04 19:49:21 +00001837#ifdef GLIBC_2_1
1838extern
1839int __sigaction
1840 (int signum,
1841 const struct sigaction *act,
1842 struct sigaction *oldact);
1843#else
sewardje663cb92002-04-12 10:26:32 +00001844extern
1845int __libc_sigaction
1846 (int signum,
1847 const struct sigaction *act,
1848 struct sigaction *oldact);
sewardjd529a442002-05-04 19:49:21 +00001849#endif
sewardje663cb92002-04-12 10:26:32 +00001850int sigaction(int signum,
1851 const struct sigaction *act,
1852 struct sigaction *oldact)
1853{
sewardjd140e442002-05-29 01:21:19 +00001854 __my_pthread_testcancel();
sewardj2a1dcce2002-04-22 12:45:25 +00001855# ifdef GLIBC_2_1
1856 return __sigaction(signum, act, oldact);
1857# else
sewardj45b4b372002-04-16 22:50:32 +00001858 return __libc_sigaction(signum, act, oldact);
sewardj2a1dcce2002-04-22 12:45:25 +00001859# endif
sewardje663cb92002-04-12 10:26:32 +00001860}
1861
jsgf855d93d2003-10-13 22:26:55 +00001862extern
1863int __libc_accept(int fd, struct sockaddr *addr, socklen_t *len);
1864
1865WEAK int __accept(int fd, struct sockaddr *addr, socklen_t *len)
1866{
1867 __my_pthread_testcancel();
1868 return __libc_accept(fd, addr, len);
1869}
1870strong_alias(__accept, accept);
sewardje663cb92002-04-12 10:26:32 +00001871
1872extern
1873int __libc_connect(int sockfd,
1874 const struct sockaddr *serv_addr,
1875 socklen_t addrlen);
sewardj11f0bb42003-04-26 20:11:15 +00001876WEAK
sewardje663cb92002-04-12 10:26:32 +00001877int connect(int sockfd,
1878 const struct sockaddr *serv_addr,
1879 socklen_t addrlen)
1880{
sewardjd140e442002-05-29 01:21:19 +00001881 __my_pthread_testcancel();
sewardj45b4b372002-04-16 22:50:32 +00001882 return __libc_connect(sockfd, serv_addr, addrlen);
sewardje663cb92002-04-12 10:26:32 +00001883}
1884
1885
1886extern
1887int __libc_fcntl(int fd, int cmd, long arg);
sewardj11f0bb42003-04-26 20:11:15 +00001888WEAK
sewardje663cb92002-04-12 10:26:32 +00001889int fcntl(int fd, int cmd, long arg)
1890{
sewardjd140e442002-05-29 01:21:19 +00001891 __my_pthread_testcancel();
sewardj45b4b372002-04-16 22:50:32 +00001892 return __libc_fcntl(fd, cmd, arg);
sewardje663cb92002-04-12 10:26:32 +00001893}
1894
1895
1896extern
1897ssize_t __libc_write(int fd, const void *buf, size_t count);
sewardj11f0bb42003-04-26 20:11:15 +00001898WEAK
sewardje663cb92002-04-12 10:26:32 +00001899ssize_t write(int fd, const void *buf, size_t count)
1900{
sewardjd140e442002-05-29 01:21:19 +00001901 __my_pthread_testcancel();
sewardj45b4b372002-04-16 22:50:32 +00001902 return __libc_write(fd, buf, count);
sewardje663cb92002-04-12 10:26:32 +00001903}
1904
1905
1906extern
1907ssize_t __libc_read(int fd, void *buf, size_t count);
sewardj11f0bb42003-04-26 20:11:15 +00001908WEAK
sewardje663cb92002-04-12 10:26:32 +00001909ssize_t read(int fd, void *buf, size_t count)
1910{
sewardjd140e442002-05-29 01:21:19 +00001911 __my_pthread_testcancel();
sewardj45b4b372002-04-16 22:50:32 +00001912 return __libc_read(fd, buf, count);
sewardje663cb92002-04-12 10:26:32 +00001913}
1914
sewardjf912dfc2002-11-13 21:51:10 +00001915extern
1916int __libc_open64(const char *pathname, int flags, mode_t mode);
sewardj11f0bb42003-04-26 20:11:15 +00001917/* WEAK */
sewardjf912dfc2002-11-13 21:51:10 +00001918int open64(const char *pathname, int flags, mode_t mode)
1919{
jsgf855d93d2003-10-13 22:26:55 +00001920 return __libc_open64(pathname, flags, mode);
sewardjf912dfc2002-11-13 21:51:10 +00001921}
sewardje663cb92002-04-12 10:26:32 +00001922
1923extern
sewardj853f55d2002-04-26 00:27:53 +00001924int __libc_open(const char *pathname, int flags, mode_t mode);
sewardj11f0bb42003-04-26 20:11:15 +00001925/* WEAK */
sewardj853f55d2002-04-26 00:27:53 +00001926int open(const char *pathname, int flags, mode_t mode)
sewardje663cb92002-04-12 10:26:32 +00001927{
jsgf855d93d2003-10-13 22:26:55 +00001928 return __libc_open(pathname, flags, mode);
sewardje663cb92002-04-12 10:26:32 +00001929}
1930
sewardje663cb92002-04-12 10:26:32 +00001931extern
1932int __libc_close(int fd);
sewardj11f0bb42003-04-26 20:11:15 +00001933WEAK
sewardje663cb92002-04-12 10:26:32 +00001934int close(int fd)
1935{
sewardjd140e442002-05-29 01:21:19 +00001936 __my_pthread_testcancel();
sewardj45b4b372002-04-16 22:50:32 +00001937 return __libc_close(fd);
sewardje663cb92002-04-12 10:26:32 +00001938}
1939
1940
sewardje663cb92002-04-12 10:26:32 +00001941extern
sewardje663cb92002-04-12 10:26:32 +00001942pid_t __libc_waitpid(pid_t pid, int *status, int options);
sewardj11f0bb42003-04-26 20:11:15 +00001943WEAK
sewardje663cb92002-04-12 10:26:32 +00001944pid_t waitpid(pid_t pid, int *status, int options)
1945{
sewardjd140e442002-05-29 01:21:19 +00001946 __my_pthread_testcancel();
sewardj45b4b372002-04-16 22:50:32 +00001947 return __libc_waitpid(pid, status, options);
sewardje663cb92002-04-12 10:26:32 +00001948}
1949
1950
1951extern
1952int __libc_nanosleep(const struct timespec *req, struct timespec *rem);
sewardj11f0bb42003-04-26 20:11:15 +00001953WEAK
jsgf855d93d2003-10-13 22:26:55 +00001954int __nanosleep(const struct timespec *req, struct timespec *rem)
sewardje663cb92002-04-12 10:26:32 +00001955{
sewardjd140e442002-05-29 01:21:19 +00001956 __my_pthread_testcancel();
sewardje663cb92002-04-12 10:26:32 +00001957 return __libc_nanosleep(req, rem);
1958}
1959
jsgf855d93d2003-10-13 22:26:55 +00001960extern
1961int __libc_pause(void);
1962WEAK
1963int __pause(void)
1964{
1965 __my_pthread_testcancel();
1966 return __libc_pause();
1967}
1968
sewardjbe32e452002-04-24 20:29:58 +00001969
sewardje663cb92002-04-12 10:26:32 +00001970extern
1971int __libc_fsync(int fd);
sewardj11f0bb42003-04-26 20:11:15 +00001972WEAK
sewardje663cb92002-04-12 10:26:32 +00001973int fsync(int fd)
1974{
sewardjd140e442002-05-29 01:21:19 +00001975 __my_pthread_testcancel();
sewardj45b4b372002-04-16 22:50:32 +00001976 return __libc_fsync(fd);
sewardje663cb92002-04-12 10:26:32 +00001977}
1978
sewardjbe32e452002-04-24 20:29:58 +00001979
sewardj70c75362002-04-13 04:18:32 +00001980extern
1981off_t __libc_lseek(int fildes, off_t offset, int whence);
sewardj11f0bb42003-04-26 20:11:15 +00001982WEAK
sewardj70c75362002-04-13 04:18:32 +00001983off_t lseek(int fildes, off_t offset, int whence)
1984{
sewardjd140e442002-05-29 01:21:19 +00001985 __my_pthread_testcancel();
sewardj45b4b372002-04-16 22:50:32 +00001986 return __libc_lseek(fildes, offset, whence);
sewardj70c75362002-04-13 04:18:32 +00001987}
1988
sewardjbe32e452002-04-24 20:29:58 +00001989
1990extern
1991__off64_t __libc_lseek64(int fildes, __off64_t offset, int whence);
sewardj11f0bb42003-04-26 20:11:15 +00001992WEAK
sewardjbe32e452002-04-24 20:29:58 +00001993__off64_t lseek64(int fildes, __off64_t offset, int whence)
1994{
sewardjd140e442002-05-29 01:21:19 +00001995 __my_pthread_testcancel();
sewardjbe32e452002-04-24 20:29:58 +00001996 return __libc_lseek64(fildes, offset, whence);
1997}
1998
1999
sewardj726c4122002-05-16 23:39:10 +00002000extern
2001ssize_t __libc_pread64 (int __fd, void *__buf, size_t __nbytes,
2002 __off64_t __offset);
2003ssize_t __pread64 (int __fd, void *__buf, size_t __nbytes,
2004 __off64_t __offset)
2005{
sewardjd140e442002-05-29 01:21:19 +00002006 __my_pthread_testcancel();
sewardj726c4122002-05-16 23:39:10 +00002007 return __libc_pread64(__fd, __buf, __nbytes, __offset);
2008}
2009
2010
sewardja18e2102002-05-18 10:43:22 +00002011extern
2012ssize_t __libc_pwrite64 (int __fd, const void *__buf, size_t __nbytes,
2013 __off64_t __offset);
2014ssize_t __pwrite64 (int __fd, const void *__buf, size_t __nbytes,
2015 __off64_t __offset)
2016{
sewardjd140e442002-05-29 01:21:19 +00002017 __my_pthread_testcancel();
sewardja18e2102002-05-18 10:43:22 +00002018 return __libc_pwrite64(__fd, __buf, __nbytes, __offset);
2019}
2020
sewardj726c4122002-05-16 23:39:10 +00002021
sewardj39b93b12002-05-18 10:56:27 +00002022extern
2023ssize_t __libc_pwrite(int fd, const void *buf, size_t count, off_t offset);
sewardj11f0bb42003-04-26 20:11:15 +00002024WEAK
sewardj39b93b12002-05-18 10:56:27 +00002025ssize_t pwrite(int fd, const void *buf, size_t count, off_t offset)
2026{
sewardjd140e442002-05-29 01:21:19 +00002027 __my_pthread_testcancel();
sewardj39b93b12002-05-18 10:56:27 +00002028 return __libc_pwrite(fd, buf, count, offset);
2029}
2030
2031
2032extern
2033ssize_t __libc_pread(int fd, void *buf, size_t count, off_t offset);
sewardj11f0bb42003-04-26 20:11:15 +00002034WEAK
sewardj39b93b12002-05-18 10:56:27 +00002035ssize_t pread(int fd, void *buf, size_t count, off_t offset)
2036{
sewardjd140e442002-05-29 01:21:19 +00002037 __my_pthread_testcancel();
sewardj39b93b12002-05-18 10:56:27 +00002038 return __libc_pread(fd, buf, count, offset);
2039}
2040
jsgf855d93d2003-10-13 22:26:55 +00002041extern
2042int __libc_recv(int s, void *msg, size_t len, int flags);
2043WEAK
2044int recv(int s, void *msg, size_t len, int flags)
sewardj6af4b5d2002-04-16 04:40:49 +00002045{
jsgf855d93d2003-10-13 22:26:55 +00002046 __my_pthread_testcancel();
2047 return __libc_recv(s, msg, len, flags);
sewardj6af4b5d2002-04-16 04:40:49 +00002048}
2049
2050extern
2051int __libc_send(int s, const void *msg, size_t len, int flags);
sewardj11f0bb42003-04-26 20:11:15 +00002052WEAK
sewardj6af4b5d2002-04-16 04:40:49 +00002053int send(int s, const void *msg, size_t len, int flags)
2054{
sewardjd140e442002-05-29 01:21:19 +00002055 __my_pthread_testcancel();
sewardj6af4b5d2002-04-16 04:40:49 +00002056 return __libc_send(s, msg, len, flags);
2057}
2058
sewardjbe32e452002-04-24 20:29:58 +00002059
sewardj3665ded2002-05-16 16:57:25 +00002060extern
2061int __libc_sendmsg(int s, const struct msghdr *msg, int flags);
sewardj11f0bb42003-04-26 20:11:15 +00002062WEAK
sewardj3665ded2002-05-16 16:57:25 +00002063int sendmsg(int s, const struct msghdr *msg, int flags)
2064{
sewardjd140e442002-05-29 01:21:19 +00002065 __my_pthread_testcancel();
sewardj3665ded2002-05-16 16:57:25 +00002066 return __libc_sendmsg(s, msg, flags);
2067}
2068
2069
sewardj796d6a22002-04-24 02:28:34 +00002070extern
sewardj59da27a2002-06-06 08:33:54 +00002071int __libc_recvmsg(int s, struct msghdr *msg, int flags);
sewardj11f0bb42003-04-26 20:11:15 +00002072WEAK
sewardj59da27a2002-06-06 08:33:54 +00002073int recvmsg(int s, struct msghdr *msg, int flags)
2074{
2075 __my_pthread_testcancel();
2076 return __libc_recvmsg(s, msg, flags);
2077}
2078
2079
2080extern
sewardj436e0582002-04-26 14:31:40 +00002081int __libc_recvfrom(int s, void *buf, size_t len, int flags,
2082 struct sockaddr *from, socklen_t *fromlen);
sewardj11f0bb42003-04-26 20:11:15 +00002083WEAK
sewardj436e0582002-04-26 14:31:40 +00002084int recvfrom(int s, void *buf, size_t len, int flags,
2085 struct sockaddr *from, socklen_t *fromlen)
2086{
sewardjd140e442002-05-29 01:21:19 +00002087 __my_pthread_testcancel();
sewardj436e0582002-04-26 14:31:40 +00002088 return __libc_recvfrom(s, buf, len, flags, from, fromlen);
2089}
2090
2091
2092extern
sewardj796d6a22002-04-24 02:28:34 +00002093int __libc_sendto(int s, const void *msg, size_t len, int flags,
2094 const struct sockaddr *to, socklen_t tolen);
sewardj11f0bb42003-04-26 20:11:15 +00002095WEAK
sewardj796d6a22002-04-24 02:28:34 +00002096int sendto(int s, const void *msg, size_t len, int flags,
2097 const struct sockaddr *to, socklen_t tolen)
2098{
sewardjd140e442002-05-29 01:21:19 +00002099 __my_pthread_testcancel();
sewardj796d6a22002-04-24 02:28:34 +00002100 return __libc_sendto(s, msg, len, flags, to, tolen);
2101}
2102
sewardjbe32e452002-04-24 20:29:58 +00002103
sewardj369b1702002-04-24 13:28:15 +00002104extern
2105int __libc_system(const char* str);
sewardj11f0bb42003-04-26 20:11:15 +00002106WEAK
sewardj369b1702002-04-24 13:28:15 +00002107int system(const char* str)
2108{
sewardjd140e442002-05-29 01:21:19 +00002109 __my_pthread_testcancel();
sewardj369b1702002-04-24 13:28:15 +00002110 return __libc_system(str);
2111}
2112
sewardjbe32e452002-04-24 20:29:58 +00002113
sewardjab0b1c32002-04-24 19:26:47 +00002114extern
2115pid_t __libc_wait(int *status);
sewardj11f0bb42003-04-26 20:11:15 +00002116WEAK
sewardjab0b1c32002-04-24 19:26:47 +00002117pid_t wait(int *status)
2118{
sewardjd140e442002-05-29 01:21:19 +00002119 __my_pthread_testcancel();
sewardjab0b1c32002-04-24 19:26:47 +00002120 return __libc_wait(status);
2121}
2122
sewardj45b4b372002-04-16 22:50:32 +00002123
sewardj67f1d582002-05-24 02:11:32 +00002124extern
2125int __libc_msync(const void *start, size_t length, int flags);
sewardj11f0bb42003-04-26 20:11:15 +00002126WEAK
sewardj67f1d582002-05-24 02:11:32 +00002127int msync(const void *start, size_t length, int flags)
2128{
sewardjd140e442002-05-29 01:21:19 +00002129 __my_pthread_testcancel();
sewardj67f1d582002-05-24 02:11:32 +00002130 return __libc_msync(start, length, flags);
2131}
2132
jsgf855d93d2003-10-13 22:26:55 +00002133strong_alias(close, __close)
2134strong_alias(fcntl, __fcntl)
2135strong_alias(lseek, __lseek)
2136strong_alias(open, __open)
2137strong_alias(open64, __open64)
2138strong_alias(read, __read)
2139strong_alias(wait, __wait)
2140strong_alias(write, __write)
2141strong_alias(connect, __connect)
2142strong_alias(send, __send)
2143
2144weak_alias (__pread64, pread64)
2145weak_alias (__pwrite64, pwrite64)
2146weak_alias(__nanosleep, nanosleep)
2147weak_alias(__pause, pause)
2148
2149
2150extern
2151void __libc_longjmp(jmp_buf env, int val) __attribute((noreturn));
2152/* not weak: WEAK */
2153void longjmp(jmp_buf env, int val)
2154{
2155 __libc_longjmp(env, val);
2156}
2157
2158
2159extern void __libc_siglongjmp (sigjmp_buf env, int val)
2160 __attribute__ ((noreturn));
2161void siglongjmp(sigjmp_buf env, int val)
2162{
nethercoteaad8c192003-11-20 14:23:09 +00002163 kludged("siglongjmp", "(it ignores cleanup handlers)");
jsgf855d93d2003-10-13 22:26:55 +00002164 __libc_siglongjmp(env, val);
2165}
2166
sewardj5905fae2002-04-26 13:25:00 +00002167
sewardj2cb00342002-06-28 01:46:26 +00002168/*--- fork and its helper ---*/
2169
2170static
2171void run_fork_handlers ( int what )
2172{
2173 ForkHandlerEntry entry;
2174 int n_h, n_handlers, i, res;
2175
2176 my_assert(what == 0 || what == 1 || what == 2);
2177
2178 /* Fetch old counter */
2179 VALGRIND_MAGIC_SEQUENCE(n_handlers, -2 /* default */,
2180 VG_USERREQ__GET_FHSTACK_USED,
2181 0, 0, 0, 0);
2182 my_assert(n_handlers >= 0 && n_handlers < VG_N_FORKHANDLERSTACK);
2183
2184 /* Prepare handlers (what == 0) are called in opposite order of
2185 calls to pthread_atfork. Parent and child handlers are called
2186 in the same order as calls to pthread_atfork. */
2187 if (what == 0)
2188 n_h = n_handlers - 1;
2189 else
2190 n_h = 0;
2191
2192 for (i = 0; i < n_handlers; i++) {
2193 VALGRIND_MAGIC_SEQUENCE(res, -2 /* default */,
2194 VG_USERREQ__GET_FHSTACK_ENTRY,
2195 n_h, &entry, 0, 0);
2196 my_assert(res == 0);
2197 switch (what) {
2198 case 0: if (entry.prepare) entry.prepare();
2199 n_h--; break;
2200 case 1: if (entry.parent) entry.parent();
2201 n_h++; break;
2202 case 2: if (entry.child) entry.child();
2203 n_h++; break;
2204 default: barf("run_fork_handlers: invalid what");
2205 }
2206 }
2207
2208 if (what != 0 /* prepare */) {
2209 /* Empty out the stack. */
2210 VALGRIND_MAGIC_SEQUENCE(res, -2 /* default */,
2211 VG_USERREQ__SET_FHSTACK_USED,
2212 0, 0, 0, 0);
2213 my_assert(res == 0);
2214 }
2215}
2216
2217extern
2218pid_t __libc_fork(void);
2219pid_t __fork(void)
2220{
2221 pid_t pid;
2222 __my_pthread_testcancel();
2223 __pthread_mutex_lock(&pthread_atfork_lock);
2224
2225 run_fork_handlers(0 /* prepare */);
2226 pid = __libc_fork();
2227 if (pid == 0) {
2228 /* I am the child */
2229 run_fork_handlers(2 /* child */);
sewardjd8acdf22002-11-13 21:57:52 +00002230 __pthread_mutex_unlock(&pthread_atfork_lock);
sewardj2cb00342002-06-28 01:46:26 +00002231 __pthread_mutex_init(&pthread_atfork_lock, NULL);
2232 } else {
2233 /* I am the parent */
2234 run_fork_handlers(1 /* parent */);
2235 __pthread_mutex_unlock(&pthread_atfork_lock);
2236 }
2237 return pid;
2238}
2239
2240
njn25e49d8e72002-09-23 09:36:25 +00002241pid_t __vfork(void)
2242{
2243 return __fork();
2244}
sewardj2cb00342002-06-28 01:46:26 +00002245
2246
sewardj08a4c3f2002-04-13 03:45:44 +00002247
sewardj3b13f0e2002-04-25 20:17:29 +00002248/* ---------------------------------------------------------------------
sewardj8f253ff2002-05-19 00:13:34 +00002249 Hacky implementation of semaphores.
2250 ------------------------------------------------------------------ */
2251
2252#include <semaphore.h>
2253
2254/* This is a terrible way to do the remapping. Plan is to import an
2255 AVL tree at some point. */
sewardj8f253ff2002-05-19 00:13:34 +00002256
2257typedef
2258 struct {
2259 pthread_mutex_t se_mx;
2260 pthread_cond_t se_cv;
2261 int count;
2262 }
2263 vg_sem_t;
2264
2265static pthread_mutex_t se_remap_mx = PTHREAD_MUTEX_INITIALIZER;
2266
2267static int se_remap_used = 0;
2268static sem_t* se_remap_orig[VG_N_SEMAPHORES];
2269static vg_sem_t se_remap_new[VG_N_SEMAPHORES];
2270
2271static vg_sem_t* se_remap ( sem_t* orig )
2272{
2273 int res, i;
2274 res = __pthread_mutex_lock(&se_remap_mx);
sewardj2d94c112002-06-03 01:25:54 +00002275 my_assert(res == 0);
sewardj8f253ff2002-05-19 00:13:34 +00002276
2277 for (i = 0; i < se_remap_used; i++) {
2278 if (se_remap_orig[i] == orig)
2279 break;
2280 }
2281 if (i == se_remap_used) {
2282 if (se_remap_used == VG_N_SEMAPHORES) {
2283 res = pthread_mutex_unlock(&se_remap_mx);
sewardj2d94c112002-06-03 01:25:54 +00002284 my_assert(res == 0);
sewardja1ac5cb2002-05-27 13:00:05 +00002285 barf("VG_N_SEMAPHORES is too low. Increase and recompile.");
sewardj8f253ff2002-05-19 00:13:34 +00002286 }
2287 se_remap_used++;
2288 se_remap_orig[i] = orig;
2289 /* printf("allocated semaphore %d\n", i); */
2290 }
2291 res = __pthread_mutex_unlock(&se_remap_mx);
sewardj2d94c112002-06-03 01:25:54 +00002292 my_assert(res == 0);
sewardj8f253ff2002-05-19 00:13:34 +00002293 return &se_remap_new[i];
2294}
2295
2296
2297int sem_init(sem_t *sem, int pshared, unsigned int value)
2298{
2299 int res;
2300 vg_sem_t* vg_sem;
2301 ensure_valgrind("sem_init");
2302 if (pshared != 0) {
sewardj4dced352002-06-04 22:54:20 +00002303 pthread_error("sem_init: unsupported pshared value");
sewardj25418ae2003-05-09 23:40:34 +00002304 *(__errno_location()) = ENOSYS;
sewardj8f253ff2002-05-19 00:13:34 +00002305 return -1;
2306 }
2307 vg_sem = se_remap(sem);
2308 res = pthread_mutex_init(&vg_sem->se_mx, NULL);
sewardj2d94c112002-06-03 01:25:54 +00002309 my_assert(res == 0);
sewardj8f253ff2002-05-19 00:13:34 +00002310 res = pthread_cond_init(&vg_sem->se_cv, NULL);
sewardj2d94c112002-06-03 01:25:54 +00002311 my_assert(res == 0);
sewardj8f253ff2002-05-19 00:13:34 +00002312 vg_sem->count = value;
2313 return 0;
2314}
2315
2316
2317int sem_wait ( sem_t* sem )
2318{
2319 int res;
2320 vg_sem_t* vg_sem;
2321 ensure_valgrind("sem_wait");
2322 vg_sem = se_remap(sem);
2323 res = __pthread_mutex_lock(&vg_sem->se_mx);
sewardj2d94c112002-06-03 01:25:54 +00002324 my_assert(res == 0);
sewardj8f253ff2002-05-19 00:13:34 +00002325 while (vg_sem->count == 0) {
2326 res = pthread_cond_wait(&vg_sem->se_cv, &vg_sem->se_mx);
sewardj2d94c112002-06-03 01:25:54 +00002327 my_assert(res == 0);
sewardj8f253ff2002-05-19 00:13:34 +00002328 }
2329 vg_sem->count--;
2330 res = __pthread_mutex_unlock(&vg_sem->se_mx);
sewardj2d94c112002-06-03 01:25:54 +00002331 my_assert(res == 0);
sewardj8f253ff2002-05-19 00:13:34 +00002332 return 0;
2333}
2334
2335int sem_post ( sem_t* sem )
2336{
2337 int res;
2338 vg_sem_t* vg_sem;
2339 ensure_valgrind("sem_post");
2340 vg_sem = se_remap(sem);
2341 res = __pthread_mutex_lock(&vg_sem->se_mx);
sewardj2d94c112002-06-03 01:25:54 +00002342 my_assert(res == 0);
sewardj8f253ff2002-05-19 00:13:34 +00002343 if (vg_sem->count == 0) {
2344 vg_sem->count++;
2345 res = pthread_cond_broadcast(&vg_sem->se_cv);
sewardj2d94c112002-06-03 01:25:54 +00002346 my_assert(res == 0);
sewardj8f253ff2002-05-19 00:13:34 +00002347 } else {
2348 vg_sem->count++;
2349 }
2350 res = __pthread_mutex_unlock(&vg_sem->se_mx);
sewardj2d94c112002-06-03 01:25:54 +00002351 my_assert(res == 0);
sewardj8f253ff2002-05-19 00:13:34 +00002352 return 0;
2353}
2354
2355
2356int sem_trywait ( sem_t* sem )
2357{
2358 int ret, res;
2359 vg_sem_t* vg_sem;
2360 ensure_valgrind("sem_trywait");
2361 vg_sem = se_remap(sem);
2362 res = __pthread_mutex_lock(&vg_sem->se_mx);
sewardj2d94c112002-06-03 01:25:54 +00002363 my_assert(res == 0);
sewardj8f253ff2002-05-19 00:13:34 +00002364 if (vg_sem->count > 0) {
2365 vg_sem->count--;
2366 ret = 0;
2367 } else {
2368 ret = -1;
sewardj25418ae2003-05-09 23:40:34 +00002369 *(__errno_location()) = EAGAIN;
sewardj8f253ff2002-05-19 00:13:34 +00002370 }
2371 res = __pthread_mutex_unlock(&vg_sem->se_mx);
sewardj2d94c112002-06-03 01:25:54 +00002372 my_assert(res == 0);
sewardj8f253ff2002-05-19 00:13:34 +00002373 return ret;
2374}
2375
2376
2377int sem_getvalue(sem_t* sem, int * sval)
2378{
2379 vg_sem_t* vg_sem;
2380 ensure_valgrind("sem_trywait");
2381 vg_sem = se_remap(sem);
2382 *sval = vg_sem->count;
2383 return 0;
2384}
2385
2386
2387int sem_destroy(sem_t * sem)
2388{
nethercoteaad8c192003-11-20 14:23:09 +00002389 kludged("sem_destroy", "(it always succeeds, even if semaphore waited on)");
sewardj8f253ff2002-05-19 00:13:34 +00002390 /* if someone waiting on this semaphore, errno = EBUSY, return -1 */
2391 return 0;
2392}
2393
sewardj9ad92d92002-10-16 19:45:06 +00002394
2395int sem_timedwait(sem_t* sem, const struct timespec *abstime)
2396{
2397 int res;
2398 vg_sem_t* vg_sem;
2399 ensure_valgrind("sem_timedwait");
2400 vg_sem = se_remap(sem);
2401 res = __pthread_mutex_lock(&vg_sem->se_mx);
2402 my_assert(res == 0);
2403 while ( vg_sem->count == 0 && res != ETIMEDOUT ) {
2404 res = pthread_cond_timedwait(&vg_sem->se_cv, &vg_sem->se_mx, abstime);
2405 }
2406 if ( vg_sem->count > 0 ) {
2407 vg_sem->count--;
2408 res = __pthread_mutex_unlock(&vg_sem->se_mx);
2409 my_assert(res == 0 );
2410 return 0;
2411 } else {
2412 res = __pthread_mutex_unlock(&vg_sem->se_mx);
2413 my_assert(res == 0 );
2414 *(__errno_location()) = ETIMEDOUT;
2415 return -1;
2416 }
2417}
2418
sewardj8f253ff2002-05-19 00:13:34 +00002419
2420/* ---------------------------------------------------------------------
sewardj2d8b3f02002-06-01 14:14:19 +00002421 Reader-writer locks.
sewardja1ac5cb2002-05-27 13:00:05 +00002422 ------------------------------------------------------------------ */
2423
sewardj2d8b3f02002-06-01 14:14:19 +00002424typedef
2425 struct {
2426 int initted; /* != 0 --> in use; sanity check only */
2427 int prefer_w; /* != 0 --> prefer writer */
2428 int nwait_r; /* # of waiting readers */
2429 int nwait_w; /* # of waiting writers */
2430 pthread_cond_t cv_r; /* for signalling readers */
2431 pthread_cond_t cv_w; /* for signalling writers */
2432 pthread_mutex_t mx;
2433 int status;
2434 /* allowed range for status: >= -1. -1 means 1 writer currently
2435 active, >= 0 means N readers currently active. */
2436 }
2437 vg_rwlock_t;
sewardja1ac5cb2002-05-27 13:00:05 +00002438
2439
2440static pthread_mutex_t rw_remap_mx = PTHREAD_MUTEX_INITIALIZER;
2441
2442static int rw_remap_used = 0;
2443static pthread_rwlock_t* rw_remap_orig[VG_N_RWLOCKS];
2444static vg_rwlock_t rw_remap_new[VG_N_RWLOCKS];
2445
sewardj2d8b3f02002-06-01 14:14:19 +00002446
2447static
2448void init_vg_rwlock ( vg_rwlock_t* vg_rwl )
2449{
2450 int res = 0;
2451 vg_rwl->initted = 1;
2452 vg_rwl->prefer_w = 1;
2453 vg_rwl->nwait_r = 0;
2454 vg_rwl->nwait_w = 0;
2455 vg_rwl->status = 0;
2456 res = pthread_mutex_init(&vg_rwl->mx, NULL);
2457 res |= pthread_cond_init(&vg_rwl->cv_r, NULL);
2458 res |= pthread_cond_init(&vg_rwl->cv_w, NULL);
sewardj2d94c112002-06-03 01:25:54 +00002459 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002460}
2461
2462
sewardja1ac5cb2002-05-27 13:00:05 +00002463/* Take the address of a LinuxThreads rwlock_t and return the shadow
2464 address of our version. Further, if the LinuxThreads version
2465 appears to have been statically initialised, do the same to the one
2466 we allocate here. The pthread_rwlock_t.__rw_readers field is set
2467 to zero by PTHREAD_RWLOCK_INITIALIZER, so we take zero as meaning
2468 uninitialised and non-zero meaning initialised.
2469*/
2470static vg_rwlock_t* rw_remap ( pthread_rwlock_t* orig )
2471{
2472 int res, i;
2473 vg_rwlock_t* vg_rwl;
2474 res = __pthread_mutex_lock(&rw_remap_mx);
sewardj2d94c112002-06-03 01:25:54 +00002475 my_assert(res == 0);
sewardja1ac5cb2002-05-27 13:00:05 +00002476
2477 for (i = 0; i < rw_remap_used; i++) {
2478 if (rw_remap_orig[i] == orig)
2479 break;
2480 }
2481 if (i == rw_remap_used) {
2482 if (rw_remap_used == VG_N_RWLOCKS) {
sewardj2d8b3f02002-06-01 14:14:19 +00002483 res = __pthread_mutex_unlock(&rw_remap_mx);
sewardj2d94c112002-06-03 01:25:54 +00002484 my_assert(res == 0);
sewardja1ac5cb2002-05-27 13:00:05 +00002485 barf("VG_N_RWLOCKS is too low. Increase and recompile.");
2486 }
2487 rw_remap_used++;
2488 rw_remap_orig[i] = orig;
sewardj2d8b3f02002-06-01 14:14:19 +00002489 rw_remap_new[i].initted = 0;
sewardja1ac5cb2002-05-27 13:00:05 +00002490 if (0) printf("allocated rwlock %d\n", i);
2491 }
2492 res = __pthread_mutex_unlock(&rw_remap_mx);
sewardj2d94c112002-06-03 01:25:54 +00002493 my_assert(res == 0);
sewardja1ac5cb2002-05-27 13:00:05 +00002494 vg_rwl = &rw_remap_new[i];
2495
sewardj2d8b3f02002-06-01 14:14:19 +00002496 /* Initialise the shadow, if required. */
sewardja1ac5cb2002-05-27 13:00:05 +00002497 if (orig->__rw_readers == 0) {
sewardja1ac5cb2002-05-27 13:00:05 +00002498 orig->__rw_readers = 1;
sewardj2d8b3f02002-06-01 14:14:19 +00002499 init_vg_rwlock(vg_rwl);
sewardja1ac5cb2002-05-27 13:00:05 +00002500 if (orig->__rw_kind == PTHREAD_RWLOCK_PREFER_READER_NP)
sewardj2d8b3f02002-06-01 14:14:19 +00002501 vg_rwl->prefer_w = 0;
sewardja1ac5cb2002-05-27 13:00:05 +00002502 }
2503
2504 return vg_rwl;
2505}
2506
2507
sewardja1ac5cb2002-05-27 13:00:05 +00002508int pthread_rwlock_init ( pthread_rwlock_t* orig,
2509 const pthread_rwlockattr_t* attr )
2510{
sewardja1ac5cb2002-05-27 13:00:05 +00002511 vg_rwlock_t* rwl;
2512 if (0) printf ("pthread_rwlock_init\n");
2513 /* Force the remapper to initialise the shadow. */
2514 orig->__rw_readers = 0;
2515 /* Install the lock preference; the remapper needs to know it. */
2516 orig->__rw_kind = PTHREAD_RWLOCK_DEFAULT_NP;
2517 if (attr)
2518 orig->__rw_kind = attr->__lockkind;
2519 rwl = rw_remap ( orig );
sewardj2d8b3f02002-06-01 14:14:19 +00002520 return 0;
sewardja1ac5cb2002-05-27 13:00:05 +00002521}
2522
sewardj2d8b3f02002-06-01 14:14:19 +00002523
2524static
2525void pthread_rwlock_rdlock_CANCEL_HDLR ( void* rwl_v )
sewardja1ac5cb2002-05-27 13:00:05 +00002526{
sewardj2d8b3f02002-06-01 14:14:19 +00002527 vg_rwlock_t* rwl = (vg_rwlock_t*)rwl_v;
2528 rwl->nwait_r--;
2529 pthread_mutex_unlock (&rwl->mx);
sewardja1ac5cb2002-05-27 13:00:05 +00002530}
2531
sewardj2d8b3f02002-06-01 14:14:19 +00002532
sewardja1ac5cb2002-05-27 13:00:05 +00002533int pthread_rwlock_rdlock ( pthread_rwlock_t* orig )
2534{
2535 int res;
2536 vg_rwlock_t* rwl;
2537 if (0) printf ("pthread_rwlock_rdlock\n");
2538 rwl = rw_remap ( orig );
sewardj2d8b3f02002-06-01 14:14:19 +00002539 res = __pthread_mutex_lock(&rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00002540 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002541 if (!rwl->initted) {
2542 res = __pthread_mutex_unlock(&rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00002543 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002544 return EINVAL;
2545 }
2546 if (rwl->status < 0) {
sewardj2d94c112002-06-03 01:25:54 +00002547 my_assert(rwl->status == -1);
sewardj2d8b3f02002-06-01 14:14:19 +00002548 rwl->nwait_r++;
2549 pthread_cleanup_push( pthread_rwlock_rdlock_CANCEL_HDLR, rwl );
2550 while (1) {
2551 if (rwl->status == 0) break;
2552 res = pthread_cond_wait(&rwl->cv_r, &rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00002553 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002554 }
2555 pthread_cleanup_pop(0);
2556 rwl->nwait_r--;
2557 }
sewardj2d94c112002-06-03 01:25:54 +00002558 my_assert(rwl->status >= 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002559 rwl->status++;
2560 res = __pthread_mutex_unlock(&rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00002561 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002562 return 0;
sewardja1ac5cb2002-05-27 13:00:05 +00002563}
2564
sewardj2d8b3f02002-06-01 14:14:19 +00002565
sewardja1ac5cb2002-05-27 13:00:05 +00002566int pthread_rwlock_tryrdlock ( pthread_rwlock_t* orig )
2567{
2568 int res;
2569 vg_rwlock_t* rwl;
2570 if (0) printf ("pthread_rwlock_tryrdlock\n");
2571 rwl = rw_remap ( orig );
sewardj2d8b3f02002-06-01 14:14:19 +00002572 res = __pthread_mutex_lock(&rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00002573 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002574 if (!rwl->initted) {
2575 res = __pthread_mutex_unlock(&rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00002576 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002577 return EINVAL;
2578 }
2579 if (rwl->status == -1) {
2580 /* Writer active; we have to give up. */
2581 res = __pthread_mutex_unlock(&rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00002582 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002583 return EBUSY;
2584 }
2585 /* Success */
sewardj2d94c112002-06-03 01:25:54 +00002586 my_assert(rwl->status >= 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002587 rwl->status++;
2588 res = __pthread_mutex_unlock(&rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00002589 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002590 return 0;
sewardja1ac5cb2002-05-27 13:00:05 +00002591}
2592
sewardj2d8b3f02002-06-01 14:14:19 +00002593
2594static
2595void pthread_rwlock_wrlock_CANCEL_HDLR ( void* rwl_v )
2596{
2597 vg_rwlock_t* rwl = (vg_rwlock_t*)rwl_v;
2598 rwl->nwait_w--;
2599 pthread_mutex_unlock (&rwl->mx);
2600}
2601
2602
sewardja1ac5cb2002-05-27 13:00:05 +00002603int pthread_rwlock_wrlock ( pthread_rwlock_t* orig )
2604{
2605 int res;
2606 vg_rwlock_t* rwl;
2607 if (0) printf ("pthread_rwlock_wrlock\n");
2608 rwl = rw_remap ( orig );
sewardj2d8b3f02002-06-01 14:14:19 +00002609 res = __pthread_mutex_lock(&rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00002610 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002611 if (!rwl->initted) {
2612 res = __pthread_mutex_unlock(&rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00002613 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002614 return EINVAL;
2615 }
2616 if (rwl->status != 0) {
2617 rwl->nwait_w++;
2618 pthread_cleanup_push( pthread_rwlock_wrlock_CANCEL_HDLR, rwl );
2619 while (1) {
2620 if (rwl->status == 0) break;
2621 res = pthread_cond_wait(&rwl->cv_w, &rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00002622 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002623 }
2624 pthread_cleanup_pop(0);
2625 rwl->nwait_w--;
2626 }
sewardj2d94c112002-06-03 01:25:54 +00002627 my_assert(rwl->status == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002628 rwl->status = -1;
2629 res = __pthread_mutex_unlock(&rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00002630 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002631 return 0;
sewardja1ac5cb2002-05-27 13:00:05 +00002632}
2633
sewardj2d8b3f02002-06-01 14:14:19 +00002634
sewardja1ac5cb2002-05-27 13:00:05 +00002635int pthread_rwlock_trywrlock ( pthread_rwlock_t* orig )
2636{
2637 int res;
2638 vg_rwlock_t* rwl;
sewardj2d8b3f02002-06-01 14:14:19 +00002639 if (0) printf ("pthread_wrlock_trywrlock\n");
sewardja1ac5cb2002-05-27 13:00:05 +00002640 rwl = rw_remap ( orig );
sewardj2d8b3f02002-06-01 14:14:19 +00002641 res = __pthread_mutex_lock(&rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00002642 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002643 if (!rwl->initted) {
2644 res = __pthread_mutex_unlock(&rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00002645 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002646 return EINVAL;
2647 }
2648 if (rwl->status != 0) {
2649 /* Reader(s) or a writer active; we have to give up. */
2650 res = __pthread_mutex_unlock(&rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00002651 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002652 return EBUSY;
2653 }
2654 /* Success */
sewardj2d94c112002-06-03 01:25:54 +00002655 my_assert(rwl->status == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002656 rwl->status = -1;
2657 res = __pthread_mutex_unlock(&rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00002658 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002659 return 0;
sewardja1ac5cb2002-05-27 13:00:05 +00002660}
2661
sewardj2d8b3f02002-06-01 14:14:19 +00002662
sewardja1ac5cb2002-05-27 13:00:05 +00002663int pthread_rwlock_unlock ( pthread_rwlock_t* orig )
2664{
2665 int res;
2666 vg_rwlock_t* rwl;
2667 if (0) printf ("pthread_rwlock_unlock\n");
2668 rwl = rw_remap ( orig );
sewardj2d8b3f02002-06-01 14:14:19 +00002669 rwl = rw_remap ( orig );
2670 res = __pthread_mutex_lock(&rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00002671 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002672 if (!rwl->initted) {
2673 res = __pthread_mutex_unlock(&rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00002674 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002675 return EINVAL;
2676 }
2677 if (rwl->status == 0) {
2678 res = __pthread_mutex_unlock(&rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00002679 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002680 return EPERM;
2681 }
sewardj2d94c112002-06-03 01:25:54 +00002682 my_assert(rwl->status != 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002683 if (rwl->status == -1) {
2684 rwl->status = 0;
2685 } else {
sewardj2d94c112002-06-03 01:25:54 +00002686 my_assert(rwl->status > 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002687 rwl->status--;
2688 }
2689
sewardj2d94c112002-06-03 01:25:54 +00002690 my_assert(rwl->status >= 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002691
2692 if (rwl->prefer_w) {
2693
2694 /* Favour waiting writers, if any. */
2695 if (rwl->nwait_w > 0) {
2696 /* Writer(s) are waiting. */
2697 if (rwl->status == 0) {
2698 /* We can let a writer in. */
2699 res = pthread_cond_signal(&rwl->cv_w);
sewardj2d94c112002-06-03 01:25:54 +00002700 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002701 } else {
2702 /* There are still readers active. Do nothing; eventually
2703 they will disappear, at which point a writer will be
2704 admitted. */
2705 }
2706 }
2707 else
2708 /* No waiting writers. */
2709 if (rwl->nwait_r > 0) {
2710 /* Let in a waiting reader. */
2711 res = pthread_cond_signal(&rwl->cv_r);
sewardj2d94c112002-06-03 01:25:54 +00002712 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002713 }
2714
2715 } else {
2716
2717 /* Favour waiting readers, if any. */
2718 if (rwl->nwait_r > 0) {
2719 /* Reader(s) are waiting; let one in. */
2720 res = pthread_cond_signal(&rwl->cv_r);
sewardj2d94c112002-06-03 01:25:54 +00002721 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002722 }
2723 else
2724 /* No waiting readers. */
2725 if (rwl->nwait_w > 0 && rwl->status == 0) {
2726 /* We have waiting writers and no active readers; let a
2727 writer in. */
2728 res = pthread_cond_signal(&rwl->cv_w);
sewardj2d94c112002-06-03 01:25:54 +00002729 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002730 }
2731 }
2732
2733 res = __pthread_mutex_unlock(&rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00002734 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002735 return 0;
2736}
2737
2738
2739int pthread_rwlock_destroy ( pthread_rwlock_t *orig )
2740{
2741 int res;
2742 vg_rwlock_t* rwl;
2743 if (0) printf ("pthread_rwlock_destroy\n");
2744 rwl = rw_remap ( orig );
2745 res = __pthread_mutex_lock(&rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00002746 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002747 if (!rwl->initted) {
2748 res = __pthread_mutex_unlock(&rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00002749 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002750 return EINVAL;
2751 }
2752 if (rwl->status != 0 || rwl->nwait_r > 0 || rwl->nwait_w > 0) {
2753 res = __pthread_mutex_unlock(&rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00002754 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002755 return EBUSY;
2756 }
2757 rwl->initted = 0;
2758 res = __pthread_mutex_unlock(&rwl->mx);
sewardj2d94c112002-06-03 01:25:54 +00002759 my_assert(res == 0);
sewardj2d8b3f02002-06-01 14:14:19 +00002760 return 0;
sewardja1ac5cb2002-05-27 13:00:05 +00002761}
2762
2763
sewardj47e4e312002-06-18 09:24:34 +00002764/* Copied directly from LinuxThreads. */
2765int
2766pthread_rwlockattr_init (pthread_rwlockattr_t *attr)
2767{
2768 attr->__lockkind = 0;
2769 attr->__pshared = PTHREAD_PROCESS_PRIVATE;
2770
2771 return 0;
2772}
2773
sewardjfe18eb82002-07-13 12:58:44 +00002774/* Copied directly from LinuxThreads. */
2775int
sewardj5706bfa2002-12-08 23:42:17 +00002776pthread_rwlockattr_destroy (pthread_rwlockattr_t *attr)
2777{
2778 return 0;
2779}
2780
2781/* Copied directly from LinuxThreads. */
2782int
sewardjfe18eb82002-07-13 12:58:44 +00002783pthread_rwlockattr_setpshared (pthread_rwlockattr_t *attr, int pshared)
2784{
2785 if (pshared != PTHREAD_PROCESS_PRIVATE && pshared != PTHREAD_PROCESS_SHARED)
2786 return EINVAL;
2787
2788 /* For now it is not possible to shared a conditional variable. */
2789 if (pshared != PTHREAD_PROCESS_PRIVATE)
2790 return ENOSYS;
2791
2792 attr->__pshared = pshared;
2793
2794 return 0;
2795}
2796
sewardj47e4e312002-06-18 09:24:34 +00002797
sewardj262b5be2003-04-26 21:19:53 +00002798
2799/* ---------------------------------------------------------------------
jsgf855d93d2003-10-13 22:26:55 +00002800 Manage the allocation and use of RT signals. The Valgrind core
2801 uses one. glibc needs us to implement this to make RT signals
2802 work; things just seem to crash if we don't.
sewardj262b5be2003-04-26 21:19:53 +00002803 ------------------------------------------------------------------ */
sewardj262b5be2003-04-26 21:19:53 +00002804int __libc_current_sigrtmin (void)
2805{
jsgf855d93d2003-10-13 22:26:55 +00002806 return VG_(sig_rtmin);
sewardj262b5be2003-04-26 21:19:53 +00002807}
2808
2809int __libc_current_sigrtmax (void)
2810{
jsgf855d93d2003-10-13 22:26:55 +00002811 return VG_(sig_rtmax);
sewardj262b5be2003-04-26 21:19:53 +00002812}
2813
2814int __libc_allocate_rtsig (int high)
2815{
jsgf855d93d2003-10-13 22:26:55 +00002816 return VG_(sig_alloc_rtsig)(high);
sewardj262b5be2003-04-26 21:19:53 +00002817}
2818
sewardjd5bef572002-10-23 21:49:33 +00002819/* ---------------------------------------------------------------------
sewardj3b13f0e2002-04-25 20:17:29 +00002820 B'stard.
2821 ------------------------------------------------------------------ */
sewardj5905fae2002-04-26 13:25:00 +00002822strong_alias(__pthread_mutex_lock, pthread_mutex_lock)
2823strong_alias(__pthread_mutex_trylock, pthread_mutex_trylock)
2824strong_alias(__pthread_mutex_unlock, pthread_mutex_unlock)
2825strong_alias(__pthread_mutexattr_init, pthread_mutexattr_init)
2826 weak_alias(__pthread_mutexattr_settype, pthread_mutexattr_settype)
sewardjf0995512003-07-06 01:29:49 +00002827 weak_alias(__pthread_mutexattr_setpshared, pthread_mutexattr_setpshared)
sewardj5905fae2002-04-26 13:25:00 +00002828strong_alias(__pthread_mutex_init, pthread_mutex_init)
2829strong_alias(__pthread_mutexattr_destroy, pthread_mutexattr_destroy)
2830strong_alias(__pthread_mutex_destroy, pthread_mutex_destroy)
2831strong_alias(__pthread_once, pthread_once)
2832strong_alias(__pthread_atfork, pthread_atfork)
2833strong_alias(__pthread_key_create, pthread_key_create)
2834strong_alias(__pthread_getspecific, pthread_getspecific)
2835strong_alias(__pthread_setspecific, pthread_setspecific)
2836
sewardjd529a442002-05-04 19:49:21 +00002837#ifndef GLIBC_2_1
sewardj3b13f0e2002-04-25 20:17:29 +00002838strong_alias(sigaction, __sigaction)
sewardjd529a442002-05-04 19:49:21 +00002839#endif
2840
sewardj5905fae2002-04-26 13:25:00 +00002841weak_alias(__fork, fork)
njn25e49d8e72002-09-23 09:36:25 +00002842weak_alias(__vfork, vfork)
sewardjf0b06452002-06-04 08:38:04 +00002843weak_alias (__pthread_kill_other_threads_np, pthread_kill_other_threads_np)
sewardj3b13f0e2002-04-25 20:17:29 +00002844
2845/*--------------------------------------------------*/
2846
sewardj5905fae2002-04-26 13:25:00 +00002847weak_alias(pthread_rwlock_rdlock, __pthread_rwlock_rdlock)
sewardj5905fae2002-04-26 13:25:00 +00002848weak_alias(pthread_rwlock_unlock, __pthread_rwlock_unlock)
sewardj262b0292002-05-01 00:03:16 +00002849weak_alias(pthread_rwlock_wrlock, __pthread_rwlock_wrlock)
sewardj060b04f2002-04-26 21:01:13 +00002850
sewardja1ac5cb2002-05-27 13:00:05 +00002851weak_alias(pthread_rwlock_destroy, __pthread_rwlock_destroy)
2852weak_alias(pthread_rwlock_init, __pthread_rwlock_init)
2853weak_alias(pthread_rwlock_tryrdlock, __pthread_rwlock_tryrdlock)
2854weak_alias(pthread_rwlock_trywrlock, __pthread_rwlock_trywrlock)
2855
sewardj060b04f2002-04-26 21:01:13 +00002856
sewardj3b13f0e2002-04-25 20:17:29 +00002857/* I've no idea what these are, but they get called quite a lot.
2858 Anybody know? */
2859
njnff28df92003-10-12 17:26:04 +00002860#ifndef __UCLIBC__
sewardj3b13f0e2002-04-25 20:17:29 +00002861#undef _IO_flockfile
2862void _IO_flockfile ( _IO_FILE * file )
2863{
sewardj853f55d2002-04-26 00:27:53 +00002864 pthread_mutex_lock(file->_lock);
sewardj3b13f0e2002-04-25 20:17:29 +00002865}
sewardj5905fae2002-04-26 13:25:00 +00002866weak_alias(_IO_flockfile, flockfile);
2867
sewardj3b13f0e2002-04-25 20:17:29 +00002868#undef _IO_funlockfile
2869void _IO_funlockfile ( _IO_FILE * file )
2870{
sewardj853f55d2002-04-26 00:27:53 +00002871 pthread_mutex_unlock(file->_lock);
sewardj3b13f0e2002-04-25 20:17:29 +00002872}
sewardj5905fae2002-04-26 13:25:00 +00002873weak_alias(_IO_funlockfile, funlockfile);
njnff28df92003-10-12 17:26:04 +00002874#endif
sewardj5905fae2002-04-26 13:25:00 +00002875
sewardj3b13f0e2002-04-25 20:17:29 +00002876
sewardjd4f2c712002-04-30 10:20:10 +00002877/* This doesn't seem to be needed to simulate libpthread.so's external
2878 interface, but many people complain about its absence. */
2879
2880strong_alias(__pthread_mutexattr_settype, __pthread_mutexattr_setkind_np)
2881weak_alias(__pthread_mutexattr_setkind_np, pthread_mutexattr_setkind_np)
sewardj439d45e2002-05-03 20:43:10 +00002882
sewardj5e657c32003-10-12 08:33:30 +00002883/* POSIX spinlocks, taken from glibc linuxthreads/sysdeps/i386 */
2884
2885typedef volatile int pthread_spinlock_t; /* Huh? Guarded by __USE_XOPEN2K */
2886
2887int pthread_spin_init(pthread_spinlock_t *lock, int pshared)
2888{
2889 /* We can ignore the `pshared' parameter. Since we are busy-waiting
2890 all processes which can access the memory location `lock' points
2891 to can use the spinlock. */
2892 *lock = 1;
2893 return 0;
2894}
2895
2896int pthread_spin_lock(pthread_spinlock_t *lock)
2897{
2898 asm volatile
2899 ("\n"
2900 "1:\n\t"
2901 "lock; decl %0\n\t"
2902 "js 2f\n\t"
2903 ".section .text.spinlock,\"ax\"\n"
2904 "2:\n\t"
2905 "cmpl $0,%0\n\t"
2906 "rep; nop\n\t"
2907 "jle 2b\n\t"
2908 "jmp 1b\n\t"
2909 ".previous"
2910 : "=m" (*lock));
2911 return 0;
2912}
2913
2914int pthread_spin_unlock(pthread_spinlock_t *lock)
2915{
2916 asm volatile
2917 ("movl $1,%0"
2918 : "=m" (*lock));
2919 return 0;
2920}
2921
2922int pthread_spin_destroy(pthread_spinlock_t *lock)
2923{
2924 /* Nothing to do. */
2925 return 0;
2926}
2927
2928int pthread_spin_trylock(pthread_spinlock_t *lock)
2929{
2930 int oldval;
2931
2932 asm volatile
2933 ("xchgl %0,%1"
2934 : "=r" (oldval), "=m" (*lock)
2935 : "0" (0));
2936 return oldval > 0 ? 0 : EBUSY;
2937}
sewardj439d45e2002-05-03 20:43:10 +00002938
2939/*--------------------------------------------------------------------*/
2940/*--- end vg_libpthread.c ---*/
2941/*--------------------------------------------------------------------*/