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