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