]> rtime.felk.cvut.cz Git - l4.git/blob - l4/pkg/valgrind/src/valgrind-3.6.0-svn/coregrind/m_libcproc.c
update
[l4.git] / l4 / pkg / valgrind / src / valgrind-3.6.0-svn / coregrind / m_libcproc.c
1
2 /*--------------------------------------------------------------------*/
3 /*--- Process-related libc stuff.                     m_libcproc.c ---*/
4 /*--------------------------------------------------------------------*/
5  
6 /*
7    This file is part of Valgrind, a dynamic binary instrumentation
8    framework.
9
10    Copyright (C) 2000-2010 Julian Seward 
11       jseward@acm.org
12
13    This program is free software; you can redistribute it and/or
14    modify it under the terms of the GNU General Public License as
15    published by the Free Software Foundation; either version 2 of the
16    License, or (at your option) any later version.
17
18    This program is distributed in the hope that it will be useful, but
19    WITHOUT ANY WARRANTY; without even the implied warranty of
20    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
21    General Public License for more details.
22
23    You should have received a copy of the GNU General Public License
24    along with this program; if not, write to the Free Software
25    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
26    02111-1307, USA.
27
28    The GNU General Public License is contained in the file COPYING.
29 */
30
31 #include "pub_core_basics.h"
32 #include "pub_core_vki.h"
33 #include "pub_core_vkiscnums.h"
34 #include "pub_core_libcbase.h"
35 #include "pub_core_libcassert.h"
36 #include "pub_core_libcprint.h"
37 #include "pub_core_libcproc.h"
38 #include "pub_core_libcsignal.h"
39 #include "pub_core_seqmatch.h"
40 #include "pub_core_mallocfree.h"
41 #include "pub_core_syscall.h"
42 #include "pub_core_xarray.h"
43 #include "pub_core_clientstate.h"
44
45 #ifdef VGO_l4re
46 #include <l4/sys/utcb.h>
47 #include <l4/sys/kdebug.h>
48 #endif
49
50 #if defined(VGO_darwin)
51 /* --- !!! --- EXTERNAL HEADERS start --- !!! --- */
52 #include <mach/mach.h>   /* mach_thread_self */
53 /* --- !!! --- EXTERNAL HEADERS end --- !!! --- */
54 #endif
55
56 /* IMPORTANT: on Darwin it is essential to use the _nocancel versions
57    of syscalls rather than the vanilla version, if a _nocancel version
58    is available.  See docs/internals/Darwin-notes.txt for the reason
59    why. */
60
61 /* ---------------------------------------------------------------------
62    Command line and environment stuff
63    ------------------------------------------------------------------ */
64
65 /* As deduced from sp_at_startup, the client's argc, argv[] and
66    envp[] as extracted from the client's stack at startup-time. */
67 Char** VG_(client_envp) = NULL;
68
69 /* Path to library directory */
70 const Char *VG_(libdir) = VG_LIBDIR;
71
72 const Char *VG_(LD_PRELOAD_var_name) =
73 #if defined(VGO_linux) || defined(VGO_aix5) || defined(VGO_l4re)
74    "LD_PRELOAD";
75 #elif defined(VGO_darwin)
76    "DYLD_INSERT_LIBRARIES";
77 #else
78 #  error Unknown OS
79 #endif
80
81 /* We do getenv without libc's help by snooping around in
82    VG_(client_envp) as determined at startup time. */
83 Char *VG_(getenv)(Char *varname)
84 {
85    Int i, n;
86    vg_assert( VG_(client_envp) );
87    n = VG_(strlen)(varname);
88    for (i = 0; VG_(client_envp)[i] != NULL; i++) {
89       Char* s = VG_(client_envp)[i];
90       if (VG_(strncmp)(varname, s, n) == 0 && s[n] == '=') {
91          return & s[n+1];
92       }
93    }
94    return NULL;
95 }
96
97 void  VG_(env_unsetenv) ( Char **env, const Char *varname )
98 {
99    Char **from, **to;
100    vg_assert(env);
101    vg_assert(varname);
102    to = NULL;
103    Int len = VG_(strlen)(varname);
104
105    for (from = to = env; from && *from; from++) {
106       if (!(VG_(strncmp)(varname, *from, len) == 0 && (*from)[len] == '=')) {
107          *to = *from;
108          to++;
109       }
110    }
111    *to = *from;
112 }
113
114 /* set the environment; returns the old env if a new one was allocated */
115 Char **VG_(env_setenv) ( Char ***envp, const Char* varname, const Char *val )
116 {
117    Char **env = (*envp);
118    Char **cpp;
119    Int len = VG_(strlen)(varname);
120    Char *valstr = VG_(arena_malloc)(VG_AR_CORE, "libcproc.es.1",
121                                     len + VG_(strlen)(val) + 2);
122    Char **oldenv = NULL;
123
124    VG_(sprintf)(valstr, "%s=%s", varname, val);
125
126    for (cpp = env; cpp && *cpp; cpp++) {
127       if (VG_(strncmp)(varname, *cpp, len) == 0 && (*cpp)[len] == '=') {
128          *cpp = valstr;
129          return oldenv;
130       }
131    }
132
133    if (env == NULL) {
134       env = VG_(arena_malloc)(VG_AR_CORE, "libcproc.es.2", sizeof(Char **) * 2);
135       env[0] = valstr;
136       env[1] = NULL;
137
138       *envp = env;
139
140    }  else {
141       Int envlen = (cpp-env) + 2;
142       Char **newenv = VG_(arena_malloc)(VG_AR_CORE, "libcproc.es.3",
143                                         envlen * sizeof(Char **));
144
145       for (cpp = newenv; *env; )
146          *cpp++ = *env++;
147       *cpp++ = valstr;
148       *cpp++ = NULL;
149
150       oldenv = *envp;
151
152       *envp = newenv;
153    }
154
155    return oldenv;
156 }
157
158
159 /* Walk through a colon-separated environment variable, and remove the
160    entries which match remove_pattern.  It slides everything down over
161    the removed entries, and pads the remaining space with '\0'.  It
162    modifies the entries in place (in the client address space), but it
163    shouldn't matter too much, since we only do this just before an
164    execve().
165
166    This is also careful to mop up any excess ':'s, since empty strings
167    delimited by ':' are considered to be '.' in a path.
168 */
169 static void mash_colon_env(Char *varp, const Char *remove_pattern)
170 {
171    Char *const start = varp;
172    Char *entry_start = varp;
173    Char *output = varp;
174
175    if (varp == NULL)
176       return;
177
178    while(*varp) {
179       if (*varp == ':') {
180          Char prev;
181          Bool match;
182
183          /* This is a bit subtle: we want to match against the entry
184             we just copied, because it may have overlapped with
185             itself, junking the original. */
186
187          prev = *output;
188          *output = '\0';
189
190          match = VG_(string_match)(remove_pattern, entry_start);
191
192          *output = prev;
193          
194          if (match) {
195             output = entry_start;
196             varp++;                     /* skip ':' after removed entry */
197          } else
198             entry_start = output+1;     /* entry starts after ':' */
199       }
200
201       if (*varp)
202          *output++ = *varp++;
203    }
204
205    /* make sure last entry is nul terminated */
206    *output = '\0';
207
208    /* match against the last entry */
209    if (VG_(string_match)(remove_pattern, entry_start)) {
210       output = entry_start;
211       if (output > start) {
212          /* remove trailing ':' */
213          output--;
214          vg_assert(*output == ':');
215       }
216    }     
217
218    /* pad out the left-overs with '\0' */
219    while(output < varp)
220       *output++ = '\0';
221 }
222
223
224 // Removes all the Valgrind-added stuff from the passed environment.  Used
225 // when starting child processes, so they don't see that added stuff.
226 void VG_(env_remove_valgrind_env_stuff)(Char** envp)
227 {
228
229 #if defined(VGO_darwin)
230
231    // Environment cleanup is also handled during parent launch 
232    // in vg_preloaded.c:vg_cleanup_env().
233
234 #endif
235
236    Int i;
237    Char* ld_preload_str = NULL;
238    Char* ld_library_path_str = NULL;
239    Char* dyld_insert_libraries_str = NULL;
240    Char* buf;
241
242    // Find LD_* variables
243    // DDD: should probably conditionally compiled some of this:
244    // - LD_LIBRARY_PATH is universal?
245    // - LD_PRELOAD is on Linux, not on Darwin, not sure about AIX
246    // - DYLD_INSERT_LIBRARIES and DYLD_SHARED_REGION are Darwin-only
247    for (i = 0; envp[i] != NULL; i++) {
248       if (VG_(strncmp)(envp[i], "LD_PRELOAD=", 11) == 0)
249          ld_preload_str = &envp[i][11];
250       if (VG_(strncmp)(envp[i], "LD_LIBRARY_PATH=", 16) == 0)
251          ld_library_path_str = &envp[i][16];
252       if (VG_(strncmp)(envp[i], "DYLD_INSERT_LIBRARIES=", 22) == 0)
253          dyld_insert_libraries_str = &envp[i][22];
254    }
255
256    buf = VG_(arena_malloc)(VG_AR_CORE, "libcproc.erves.1",
257                            VG_(strlen)(VG_(libdir)) + 20);
258
259    // Remove Valgrind-specific entries from LD_*.
260    VG_(sprintf)(buf, "%s*/vgpreload_*.so", VG_(libdir));
261    mash_colon_env(ld_preload_str, buf);
262    mash_colon_env(dyld_insert_libraries_str, buf);
263    VG_(sprintf)(buf, "%s*", VG_(libdir));
264    mash_colon_env(ld_library_path_str, buf);
265
266    // Remove VALGRIND_LAUNCHER variable.
267    VG_(env_unsetenv)(envp, VALGRIND_LAUNCHER);
268
269    // Remove DYLD_SHARED_REGION variable.
270    VG_(env_unsetenv)(envp, "DYLD_SHARED_REGION");
271
272    // XXX if variable becomes empty, remove it completely?
273
274    VG_(arena_free)(VG_AR_CORE, buf);
275 }
276
277 /* ---------------------------------------------------------------------
278    Various important syscall wrappers
279    ------------------------------------------------------------------ */
280
281 Int VG_(waitpid)(Int pid, Int *status, Int options)
282 {
283 #  if defined(VGO_linux)
284    SysRes res = VG_(do_syscall4)(__NR_wait4,
285                                  pid, (UWord)status, options, 0);
286    return sr_isError(res) ? -1 : sr_Res(res);
287 #  elif defined(VGO_darwin)
288    SysRes res = VG_(do_syscall4)(__NR_wait4_nocancel,
289                                  pid, (UWord)status, options, 0);
290    return sr_isError(res) ? -1 : sr_Res(res);
291 #  elif defined(VGO_aix5)
292    /* magic number 4 obtained by truss-ing a C program doing
293       'waitpid'.  Note status and pid args opposite way round from
294       POSIX. */
295    SysRes res = VG_(do_syscall5)(__NR_AIX5_kwaitpid, 
296                                  (UWord)status, pid, 4 | options,0,0);
297    if (0) VG_(printf)("waitpid: got 0x%lx 0x%lx\n", sr_Res(res), res.err);
298    return sr_isError(res) ? -1 : sr_Res(res);
299 #  elif defined(VGO_l4re)
300    enter_kdebug("waitpid");
301    return -1;
302 #  else
303 #    error Unknown OS
304 #  endif
305 }
306
307 /* clone the environment */
308 Char **VG_(env_clone) ( Char **oldenv )
309 {
310    Char **oldenvp;
311    Char **newenvp;
312    Char **newenv;
313    Int  envlen;
314
315    vg_assert(oldenv);
316    for (oldenvp = oldenv; oldenvp && *oldenvp; oldenvp++);
317
318    envlen = oldenvp - oldenv + 1;
319    
320    newenv = VG_(arena_malloc)(VG_AR_CORE, "libcproc.ec.1",
321                               envlen * sizeof(Char **));
322
323    oldenvp = oldenv;
324    newenvp = newenv;
325    
326    while (oldenvp && *oldenvp) {
327       *newenvp++ = *oldenvp++;
328    }
329    
330    *newenvp = *oldenvp;
331
332    return newenv;
333 }
334
335 void VG_(execv) ( Char* filename, Char** argv )
336 {
337 #ifdef VGO_l4re
338         enter_kdebug("execve");
339 #else
340    Char** envp;
341    SysRes res;
342
343    /* restore the DATA rlimit for the child */
344    VG_(setrlimit)(VKI_RLIMIT_DATA, &VG_(client_rlimit_data));
345
346    envp = VG_(env_clone)(VG_(client_envp));
347    VG_(env_remove_valgrind_env_stuff)( envp );
348
349    res = VG_(do_syscall3)(__NR_execve,
350                           (UWord)filename, (UWord)argv, (UWord)envp);
351
352    VG_(printf)("EXEC failed, errno = %lld\n", (Long)sr_Err(res));
353 #endif
354 }
355
356 /* Return -1 if error, else 0.  NOTE does not indicate return code of
357    child! */
358 Int VG_(system) ( Char* cmd )
359 {
360    Int pid;
361    if (cmd == NULL)
362       return 1;
363    pid = VG_(fork)();
364    if (pid < 0)
365       return -1;
366    if (pid == 0) {
367       /* child */
368       Char* argv[4] = { "/bin/sh", "-c", cmd, 0 };
369       VG_(execv)(argv[0], argv);
370
371       /* If we're still alive here, execve failed. */
372       VG_(exit)(1);
373    } else {
374       /* parent */
375       /* We have to set SIGCHLD to its default behaviour in order that
376          VG_(waitpid) works (at least on AIX).  According to the Linux
377          man page for waitpid:
378
379          POSIX.1-2001 specifies that if the disposition of SIGCHLD is
380          set to SIG_IGN or the SA_NOCLDWAIT flag is set for SIGCHLD
381          (see sigaction(2)), then children that terminate do not
382          become zombies and a call to wait() or waitpid() will block
383          until all children have terminated, and then fail with errno
384          set to ECHILD.  (The original POSIX standard left the
385          behaviour of setting SIGCHLD to SIG_IGN unspecified.)
386       */
387       Int ir, zzz;
388       vki_sigaction_toK_t sa, sa2;
389       vki_sigaction_fromK_t saved_sa;
390       VG_(memset)( &sa, 0, sizeof(sa) );
391       VG_(sigemptyset)(&sa.sa_mask);
392       sa.ksa_handler = VKI_SIG_DFL;
393       sa.sa_flags    = 0;
394       ir = VG_(sigaction)(VKI_SIGCHLD, &sa, &saved_sa);
395       vg_assert(ir == 0);
396
397       zzz = VG_(waitpid)(pid, NULL, 0);
398
399       VG_(convert_sigaction_fromK_to_toK)( &saved_sa, &sa2 );
400       ir = VG_(sigaction)(VKI_SIGCHLD, &sa2, NULL);
401       vg_assert(ir == 0);
402       return zzz == -1 ? -1 : 0;
403    }
404 }
405
406 /* ---------------------------------------------------------------------
407    Resource limits
408    ------------------------------------------------------------------ */
409
410 /* Support for getrlimit. */
411 Int VG_(getrlimit) (Int resource, struct vki_rlimit *rlim)
412 {
413 #  if defined(VGO_l4re)
414         enter_kdebug("getrlimit");
415         return -1;
416 #  else 
417
418    SysRes res = VG_(mk_SysRes_Error)(VKI_ENOSYS);
419    /* res = getrlimit( resource, rlim ); */
420 #  ifdef __NR_ugetrlimit
421    res = VG_(do_syscall2)(__NR_ugetrlimit, resource, (UWord)rlim);
422 #  endif
423    if (sr_isError(res) && sr_Err(res) == VKI_ENOSYS)
424       res = VG_(do_syscall2)(__NR_getrlimit, resource, (UWord)rlim);
425    return sr_isError(res) ? -1 : sr_Res(res);
426 #  endif
427 }
428
429
430 /* Support for setrlimit. */
431 Int VG_(setrlimit) (Int resource, const struct vki_rlimit *rlim)
432 {
433 #  if defined(VGO_l4re)
434         enter_kdebug("getrlimit");
435         return -1;
436 #  else 
437
438    SysRes res;
439    /* res = setrlimit( resource, rlim ); */
440    res = VG_(do_syscall2)(__NR_setrlimit, resource, (UWord)rlim);
441    return sr_isError(res) ? -1 : sr_Res(res);
442 #endif
443 }
444
445 /* Support for prctl. */
446 Int VG_(prctl) (Int option, 
447                 ULong arg2, ULong arg3, ULong arg4, ULong arg5)
448 {
449    SysRes res = VG_(mk_SysRes_Error)(VKI_ENOSYS);
450 #  if defined(VGO_linux)
451    /* res = prctl( option, arg2, arg3, arg4, arg5 ); */
452    res = VG_(do_syscall5)(__NR_prctl, (UWord) option,
453                           (UWord) arg2, (UWord) arg3, (UWord) arg4,
454                           (UWord) arg5);
455 #  endif
456
457    return sr_isError(res) ? -1 : sr_Res(res);
458 }
459
460 /* ---------------------------------------------------------------------
461    pids, etc
462    ------------------------------------------------------------------ */
463
464 Int VG_(gettid)(void)
465 {
466 #  if defined(VGO_linux)
467    SysRes res = VG_(do_syscall0)(__NR_gettid);
468
469    if (sr_isError(res) && sr_Res(res) == VKI_ENOSYS) {
470       Char pid[16];      
471       /*
472        * The gettid system call does not exist. The obvious assumption
473        * to make at this point would be that we are running on an older
474        * system where the getpid system call actually returns the ID of
475        * the current thread.
476        *
477        * Unfortunately it seems that there are some systems with a kernel
478        * where getpid has been changed to return the ID of the thread group
479        * leader but where the gettid system call has not yet been added.
480        *
481        * So instead of calling getpid here we use readlink to see where
482        * the /proc/self link is pointing...
483        */
484
485       res = VG_(do_syscall3)(__NR_readlink, (UWord)"/proc/self",
486                              (UWord)pid, sizeof(pid));
487       if (!sr_isError(res) && sr_Res(res) > 0) {
488          Char* s;
489          pid[sr_Res(res)] = '\0';
490          res = VG_(mk_SysRes_Success)(  VG_(strtoll10)(pid, &s) );
491          if (*s != '\0') {
492             VG_(message)(Vg_DebugMsg, 
493                "Warning: invalid file name linked to by /proc/self: %s\n",
494                pid);
495          }
496       }
497    }
498
499    return sr_Res(res);
500
501 #  elif defined(VGO_aix5)
502    SysRes res;
503    Int    r;
504    vg_assert(__NR_AIX5__thread_self != __NR_AIX5_UNKNOWN);
505    res = VG_(do_syscall0)(__NR_AIX5__thread_self);
506    r = sr_Res(res);
507    return r;
508
509 #  elif defined(VGO_darwin)
510    // Darwin's gettid syscall is something else.
511    // Use Mach thread ports for lwpid instead.
512    return mach_thread_self();
513
514 #  elif defined(VGO_l4re)
515    return l4_utcb_tcr()->user[2];
516
517 #  else
518 #    error "Unknown OS"
519 #  endif
520 }
521
522 /* You'd be amazed how many places need to know the current pid. */
523 Int VG_(getpid) ( void )
524 {
525 #if defined(VGO_l4re)
526         return VG_(gettid);
527 #else
528    /* ASSUMES SYSCALL ALWAYS SUCCEEDS */
529    return sr_Res( VG_(do_syscall0)(__NR_getpid) );
530 #endif
531 }
532
533 Int VG_(getpgrp) ( void )
534 {
535 #  if defined(VGO_l4re)
536    enter_kdebug("getpgrp");
537    return -1;
538 #  else
539    /* ASSUMES SYSCALL ALWAYS SUCCEEDS */
540    return sr_Res( VG_(do_syscall0)(__NR_getpgrp) );
541 #  endif
542 }
543
544 Int VG_(getppid) ( void )
545 {
546 #  if defined(VGO_l4re)
547    enter_kdebug("getppid");
548    return -1;
549 #  else
550    /* ASSUMES SYSCALL ALWAYS SUCCEEDS */
551    return sr_Res( VG_(do_syscall0)(__NR_getppid) );
552 #  endif
553 }
554
555 Int VG_(geteuid) ( void )
556 {
557    /* ASSUMES SYSCALL ALWAYS SUCCEEDS */
558 #  if defined(VGP_ppc32_aix5) || defined(VGP_ppc64_aix5)
559    return sr_Res( VG_(do_syscall1)(__NR_AIX5_getuidx, 1) );
560 #  elif defined(__NR_geteuid32)
561    // We use the 32-bit version if it's supported.  Otherwise, IDs greater
562    // than 65536 cause problems, as bug #151209 showed.
563    return sr_Res( VG_(do_syscall0)(__NR_geteuid32) );
564 #  elif defined(VGO_l4re)
565    if (VG_DEBUG_L4RE_FILES) VG_(printf)("unimplemented function %s()\n", __func__);
566    return 0x0815;
567 #  else
568    return sr_Res( VG_(do_syscall0)(__NR_geteuid) );
569 #  endif
570 }
571
572 Int VG_(getegid) ( void )
573 {
574    /* ASSUMES SYSCALL ALWAYS SUCCEEDS */
575 #  if defined(VGP_ppc32_aix5) || defined(VGP_ppc64_aix5)
576    return sr_Res( VG_(do_syscall1)(__NR_AIX5_getgidx, 1) );
577 #  elif defined(__NR_getegid32)
578    // We use the 32-bit version if it's supported.  Otherwise, IDs greater
579    // than 65536 cause problems, as bug #151209 showed.
580    return sr_Res( VG_(do_syscall0)(__NR_getegid32) );
581 #  elif defined(VGO_l4re)
582    if (VG_DEBUG_L4RE_FILES) VG_(printf)("unimplemented function %s()\n", __func__);
583    return 0x0815;
584 #  else
585    return sr_Res( VG_(do_syscall0)(__NR_getegid) );
586 #  endif
587 }
588
589 /* Get supplementary groups into list[0 .. size-1].  Returns the
590    number of groups written, or -1 if error.  Note that in order to be
591    portable, the groups are 32-bit unsigned ints regardless of the
592    platform. */
593 Int VG_(getgroups)( Int size, UInt* list )
594 {
595 #  if defined(VGP_x86_linux) || defined(VGP_ppc32_linux)
596    Int    i;
597    SysRes sres;
598    UShort list16[64];
599    if (size < 0) return -1;
600    if (size > 64) size = 64;
601    sres = VG_(do_syscall2)(__NR_getgroups, size, (Addr)list16);
602    if (sr_isError(sres))
603       return -1;
604    if (sr_Res(sres) > size)
605       return -1;
606    for (i = 0; i < sr_Res(sres); i++)
607       list[i] = (UInt)list16[i];
608    return sr_Res(sres);
609
610 #  elif defined(VGP_amd64_linux) || defined(VGP_ppc64_linux)  \
611         || defined(VGP_arm_linux)                             \
612         || defined(VGP_ppc32_aix5) || defined(VGP_ppc64_aix5) \
613         || defined(VGO_darwin) || defined(VGP_s390x_linux)
614    SysRes sres;
615    sres = VG_(do_syscall2)(__NR_getgroups, size, (Addr)list);
616    if (sr_isError(sres))
617       return -1;
618    return sr_Res(sres);
619
620 #  elif defined(VGO_l4re)
621    if (VG_DEBUG_L4RE_FILES) VG_(printf)("unimplemented function %s()\n", __func__);
622    return 0x0815;
623
624 #  else
625 #     error "VG_(getgroups): needs implementation on this platform"
626 #  endif
627 }
628
629 /* ---------------------------------------------------------------------
630    Process tracing
631    ------------------------------------------------------------------ */
632
633 Int VG_(ptrace) ( Int request, Int pid, void *addr, void *data )
634 {
635 #  if defined(VGO_l4re)
636    enter_kdebug("ptrace");
637    return -1;
638 #  else
639    SysRes res;
640    res = VG_(do_syscall4)(__NR_ptrace, request, pid, (UWord)addr, (UWord)data);
641    if (sr_isError(res))
642       return -1;
643    return sr_Res(res);
644 #endif
645 }
646
647 /* ---------------------------------------------------------------------
648    Fork
649    ------------------------------------------------------------------ */
650
651 Int VG_(fork) ( void )
652 {
653 #  if defined(VGO_linux) || defined(VGO_aix5)
654    SysRes res;
655    res = VG_(do_syscall0)(__NR_fork);
656    if (sr_isError(res))
657       return -1;
658    return sr_Res(res);
659
660 #  elif defined(VGO_darwin)
661    SysRes res;
662    res = VG_(do_syscall0)(__NR_fork); /* __NR_fork is UX64 */
663    if (sr_isError(res))
664       return -1;
665    /* on success: wLO = child pid; wHI = 1 for child, 0 for parent */
666    if (sr_ResHI(res) != 0) {
667       return 0;  /* this is child: return 0 instead of child pid */
668    }
669    return sr_Res(res);
670
671 #  elif defined(VGO_l4re)
672    enter_kdebug("fork");
673    return -1;
674
675 #  else
676 #    error "Unknown OS"
677 #  endif
678 }
679
680 /* ---------------------------------------------------------------------
681    Timing stuff
682    ------------------------------------------------------------------ */
683
684 UInt VG_(read_millisecond_timer) ( void )
685 {
686    /* 'now' and 'base' are in microseconds */
687    static ULong base = 0;
688    ULong  now;
689
690 #  if defined(VGO_linux)
691    { SysRes res;
692      struct vki_timespec ts_now;
693      res = VG_(do_syscall2)(__NR_clock_gettime, VKI_CLOCK_MONOTONIC,
694                             (UWord)&ts_now);
695      if (sr_isError(res) == 0) {
696         now = ts_now.tv_sec * 1000000ULL + ts_now.tv_nsec / 1000;
697      } else {
698        struct vki_timeval tv_now;
699        res = VG_(do_syscall2)(__NR_gettimeofday, (UWord)&tv_now, (UWord)NULL);
700        vg_assert(! sr_isError(res));
701        now = tv_now.tv_sec * 1000000ULL + tv_now.tv_usec;
702      }
703    }
704
705 #  elif defined(VGO_aix5)
706    /* AIX requires a totally different implementation since
707       sys_gettimeofday doesn't exist.  We use the POWER real-time
708       register facility.  This will SIGILL on PowerPC 970 on AIX,
709       since PowerPC doesn't support these instructions. */
710    UWord nsec, sec1, sec2;
711    while (1) {
712       __asm__ __volatile__ ("\n"
713          "\tmfspr %0,4\n" /* 4==RTCU */
714          "\tmfspr %1,5\n" /* 5==RTCL */
715          "\tmfspr %2,4\n" /* 4==RTCU */
716          : "=b" (sec1), "=b" (nsec), "=b" (sec2)
717       );
718       if (sec1 == sec2) break;
719    }
720    vg_assert(nsec < 1000*1000*1000);
721    now  = ((ULong)sec1) * 1000000ULL;
722    now += (ULong)(nsec / 1000);
723
724 #  elif defined(VGO_darwin)
725    // Weird: it seems that gettimeofday() doesn't fill in the timeval, but
726    // rather returns the tv_sec as the low 32 bits of the result and the
727    // tv_usec as the high 32 bits of the result.  (But the timeval cannot be
728    // NULL!)  See bug 200990.
729    { SysRes res;
730      struct vki_timeval tv_now = { 0, 0 };
731      res = VG_(do_syscall2)(__NR_gettimeofday, (UWord)&tv_now, (UWord)NULL);
732      vg_assert(! sr_isError(res));
733      now = sr_Res(res) * 1000000ULL + sr_ResHI(res);
734    }
735
736 #  elif defined(VGO_l4re)
737    struct vki_timeval tv_now;
738    int ret;
739    ret = gettimeofday(&tv_now, NULL);
740    vg_assert( ret == 0);
741    now = tv_now.tv_sec * 1000000ULL + tv_now.tv_usec;
742
743 #  else
744 #    error "Unknown OS"
745 #  endif
746
747    /* COMMON CODE */  
748    if (base == 0)
749       base = now;
750
751    return (now - base) / 1000;
752 }
753
754
755 /* ---------------------------------------------------------------------
756    atfork()
757    ------------------------------------------------------------------ */
758
759 struct atfork {
760    vg_atfork_t  pre;
761    vg_atfork_t  parent;
762    vg_atfork_t  child;
763 };
764
765 #define VG_MAX_ATFORK 10
766
767 static struct atfork atforks[VG_MAX_ATFORK];
768 static Int n_atfork = 0;
769
770 void VG_(atfork)(vg_atfork_t pre, vg_atfork_t parent, vg_atfork_t child)
771 {
772    Int i;
773
774    for (i = 0; i < n_atfork; i++) {
775       if (atforks[i].pre == pre &&
776           atforks[i].parent == parent &&
777           atforks[i].child == child)
778          return;
779    }
780
781    if (n_atfork >= VG_MAX_ATFORK)
782       VG_(core_panic)(
783          "Too many VG_(atfork) handlers requested: raise VG_MAX_ATFORK");
784
785    atforks[n_atfork].pre    = pre;
786    atforks[n_atfork].parent = parent;
787    atforks[n_atfork].child  = child;
788
789    n_atfork++;
790 }
791
792 void VG_(do_atfork_pre)(ThreadId tid)
793 {
794    Int i;
795
796    for (i = 0; i < n_atfork; i++)
797       if (atforks[i].pre != NULL)
798          (*atforks[i].pre)(tid);
799 }
800
801 void VG_(do_atfork_parent)(ThreadId tid)
802 {
803    Int i;
804
805    for (i = 0; i < n_atfork; i++)
806       if (atforks[i].parent != NULL)
807          (*atforks[i].parent)(tid);
808 }
809
810 void VG_(do_atfork_child)(ThreadId tid)
811 {
812    Int i;
813
814    for (i = 0; i < n_atfork; i++)
815       if (atforks[i].child != NULL)
816          (*atforks[i].child)(tid);
817 }
818
819
820 /*--------------------------------------------------------------------*/
821 /*--- end                                                          ---*/
822 /*--------------------------------------------------------------------*/