Skip site navigation (1)Skip section navigation (2)
Date:      Fri, 7 Nov 2008 22:36:49 GMT
From:      Peter Wemm <peter@FreeBSD.org>
To:        Perforce Change Reviews <perforce@freebsd.org>
Subject:   PERFORCE change 152635 for review
Message-ID:  <200811072236.mA7Mano2058175@repoman.freebsd.org>

next in thread | raw e-mail | index | archive | help
http://perforce.freebsd.org/chv.cgi?CH=152635

Change 152635 by peter@peter_hammer on 2008/11/07 22:36:07

	Ugh.  FreeBSD-6 had sigtimedwait(), but it was missing from compat32.
	Add a detection for running under 32 bit emulation so we can emulate
	it on 6.x under compat32.  (This is also needed for other things too)

Affected files ...

.. //depot/projects/valgrind/coregrind/m_coredump/coredump-elf.c#5 edit
.. //depot/projects/valgrind/coregrind/m_libcproc.c#7 edit
.. //depot/projects/valgrind/coregrind/m_libcsignal.c#9 edit
.. //depot/projects/valgrind/coregrind/m_main.c#11 edit
.. //depot/projects/valgrind/coregrind/pub_core_libcproc.h#4 edit
.. //depot/projects/valgrind/include/vki/vki-freebsd.h#12 edit

Differences ...

==== //depot/projects/valgrind/coregrind/m_coredump/coredump-elf.c#5 (text+ko) ====

@@ -240,12 +240,6 @@
 			  const vki_siginfo_t *si)
 {
    struct vki_user_regs_struct *regs;
-   Int error, osreldate;
-   vki_size_t osreldatel;
-
-   osreldate = 0;
-   osreldatel = sizeof(osreldate);
-   error = VG_(sysctlbyname)("kern.osreldate", &osreldate, &osreldatel, 0, 0);
 
    VG_(memset)(prs, 0, sizeof(*prs));
 
@@ -253,7 +247,7 @@
    prs->pr_statussz = sizeof(struct vki_elf_prstatus);
    prs->pr_gregsetsz = sizeof(vki_elf_gregset_t);
    prs->pr_fpregsetsz = sizeof(vki_elf_fpregset_t);
-   prs->pr_osreldate = osreldate;
+   prs->pr_osreldate = VG_(getosreldate)();
 
    prs->pr_cursig = si->si_signo;
    prs->pr_pid = tst->os_state.lwpid;

==== //depot/projects/valgrind/coregrind/m_libcproc.c#7 (text+ko) ====

@@ -675,14 +675,51 @@
    return error;
 }
 
-Int VG_(modfind)(const Char *modname)
+Int VG_(getosreldate)(void)
+{
+   static Int osreldate = 0;
+   vki_size_t osreldatel;
+
+   if (osreldate == 0) {
+      osreldatel = sizeof(osreldate);
+      VG_(sysctlbyname)("kern.osreldate", &osreldate, &osreldatel, 0, 0);
+   }
+   return (osreldate);
+}
+
+Bool VG_(is32on64)(void)
 {
-   SysRes res;
+#if defined(VGP_amd64_freebsd)
+   return False;
+#elif defined(VGP_x86_freebsd)
+   Int oid[2], error;
+   vki_size_t len;
+   char machbuf[32];
+   static Int is32on64 = -1;
 
-   res = VG_(do_syscall1)(__NR_modfind, (UWord)modname);
-   if (res.isError)
-      return -1;
-   return res.res;
+   if (is32on64 == -1) {
+      oid[0] = VKI_CTL_HW;
+      oid[1] = VKI_HW_MACHINE;
+      len = sizeof(machbuf);
+      error =  VG_(sysctl)(oid, 2, machbuf, &len, NULL, 0);
+      if (error == 0) {
+	 machbuf[31] = '\0';
+	 if (VG_(strcmp)(machbuf, "amd64") == 0)
+	    is32on64 = 1;
+	 else
+	    is32on64 = 0;
+      } else {
+	 is32on64 = -2;
+      }
+   }
+   if (is32on64 == 1) {
+      return True;
+   } else {
+      return False;
+   }
+#else
+#  error Unknown platform
+#endif
 }
 #endif
 

==== //depot/projects/valgrind/coregrind/m_libcsignal.c#9 (text+ko) ====

@@ -36,6 +36,7 @@
 #include "pub_core_libcassert.h"
 #include "pub_core_syscall.h"
 #include "pub_core_libcsignal.h"    /* self */
+#include "pub_core_libcproc.h"
 
 /* sigemptyset, sigfullset, sigaddset and sigdelset return 0 on
    success and -1 on error.  */
@@ -227,21 +228,7 @@
    return res.isError ? -1 : res.res;
 }
 
-#elif defined(VGO_freebsd) && __FreeBSD__ >= 7
-Int VG_(sigtimedwait_zero)( const vki_sigset_t *set, 
-                            vki_siginfo_t *info )
-{
-   static const struct vki_timespec zero = { 0, 0 };
-   /* only on freebsd6.x and higher */
-   SysRes res = VG_(do_syscall3)(__NR_sigtimedwait, (UWord)set, (UWord)info, 
-                                 (UWord)&zero);
-   return res.isError ? -1 : res.res;
-}
-#elif defined(VGO_aix5) || (defined(VGO_freebsd) && __FreeBSD__ < 7)
-#if defined(VGO_freebsd)
-#define __NR__sigpending __NR_sigpending
-#define __NR__sigsuspend __NR_sigsuspend
-#endif
+#elif defined(VGO_aix5)
 /* The general idea is:
    - use sigpending to find out which signals are pending
    - choose one
@@ -332,10 +319,119 @@
 
   return i;
 }
-#if defined(VGO_freebsd)
-#undef __NR__sigpending
-#undef __NR__sigsuspend
+#elif defined(VGO_freebsd)
+
+/*
+ * This is a mess.  sigtimedwait() was added in FreeBSD-6.  However,
+ * there was no 32 bit syscall version until FreeBSD-7.  So on older
+ * platforms we have to check.
+ */
+#if __FreeBSD__ < 7
+static void sigtimedwait_zero_handler ( Int sig ) 
+{ 
+   vg_assert(sig != VKI_SIGILL);
+   vg_assert(sig != VKI_SIGSEGV);
+   vg_assert(sig != VKI_SIGBUS);
+   vg_assert(sig != VKI_SIGTRAP);
+   vg_assert(sig != VKI_SIGSYS);
+   /* do nothing */ 
+}
+#endif
+
+Int VG_(sigtimedwait_zero)( const vki_sigset_t *set, 
+                            vki_siginfo_t *info )
+{
+#if __FreeBSD__ < 7
+  Int    i, ir;
+  SysRes sr;
+  vki_sigset_t pending, blocked, allbutone;
+  struct vki_sigaction sa, saved_sa;
+  Int osreldate;
+#if defined(VGP_x86_freebsd)
+  Int is32on64;
+#endif
+#endif
+  Bool have_sigtimedwait_zero = True;
+  static const struct vki_timespec zero = { 0, 0 };
+
+#if __FreeBSD__ < 7
+  osreldate = VG_(getosreldate)();
+  if (osreldate < 600000)
+     have_sigtimedwait_zero = False;
+#if defined(VGP_x86_freebsd)
+  /* 32 bit emulation is busted, no sigtimedwait even though the kernel has it */
+  is32on64 = VG_(is32on64)();
+  if (is32on64 && osreldate < 700000)
+     have_sigtimedwait_zero = False;
+#endif
+#endif
+  if (have_sigtimedwait_zero) {
+     SysRes res = VG_(do_syscall3)(__NR_sigtimedwait, (UWord)set, (UWord)info, 
+                                   (UWord)&zero);
+     return res.isError ? -1 : res.res;
+  }
+
+#if __FreeBSD__ < 7
+  /* Find out what's pending: FreeBSD sigpending */
+  sr = VG_(do_syscall1)(__NR_sigpending, (UWord)&pending);
+  vg_assert(!sr.isError);
+
+  /* don't try for signals not in 'set' */
+  /* pending = pending `intersect` set */
+  for (i = 0; i < _VKI_NSIG_WORDS; i++)
+     pending.sig[i] &= set->sig[i];
+
+  /* don't try for signals not blocked at the moment */
+  ir = VG_(sigprocmask)(VKI_SIG_SETMASK, NULL, &blocked);
+  vg_assert(ir == 0);
+
+  /* pending = pending `intersect` blocked */
+  for (i = 0; i < _VKI_NSIG_WORDS; i++)
+     pending.sig[i] &= blocked.sig[i];
+
+  /* decide which signal we're going to snarf */
+  for (i = 1; i < _VKI_NSIG; i++)
+     if (VG_(sigismember)(&pending,i))
+        break;
+
+  if (i == _VKI_NSIG)
+     return 0;
+
+  /* fetch signal i.
+     pre: i is blocked and pending
+     pre: we are the only thread running 
+  */
+  /* Set up alternative signal handler */
+  VG_(sigfillset)(&allbutone);
+  VG_(sigdelset)(&allbutone, i);
+  sa.sa_mask     = allbutone;
+  sa.ksa_handler = &sigtimedwait_zero_handler;
+  sa.sa_flags    = 0;
+  ir = VG_(sigaction)(i, &sa, &saved_sa);
+  vg_assert(ir == 0);
+
+  /* Switch signal masks and wait for the signal.  This should happen
+     immediately, since we've already established it is pending and
+     blocked. */
+  sr = VG_(do_syscall1)(__NR_sigsuspend, (UWord)&allbutone);
+  vg_assert(sr.isError);
+  if (0)
+     VG_(debugLog)(0, "libcsignal",
+                      "sigtimedwait_zero: sigsuspend got res %ld err %ld\n", 
+                      sr.res, sr.err);
+  vg_assert(sr.res == (UWord)-1);
+
+  /* Restore signal's handler to whatever it was before */
+  ir = VG_(sigaction)(i, &saved_sa, NULL);
+  vg_assert(ir == 0);
+
+  /* This is bogus - we could get more info from the sighandler. */
+  VG_(memset)( info, 0, sizeof(*info) );
+  info->si_signo = i;
+
+  return i;
 #endif
+}
 
 #else
 #  error Unknown OS

==== //depot/projects/valgrind/coregrind/m_main.c#11 (text+ko) ====

@@ -324,25 +324,6 @@
    /* log to stderr by default, but usage message goes to stdout */
    tmp_log_fd = 2; 
 
-#if defined(VGO_freebsd) && 0
-   {
-      Int modid;
-
-      modid = VG_(modfind)("getpath_fromfd");
-      if (modid < 0) {
-	 struct vki_timespec ts = { 2, 0 };
-	 VG_(message)(Vg_UserMsg, "");
-	 VG_(message)(Vg_UserMsg, "*** WARNING! Functionality SEVERELY LIMITED without getpath_kern module!! ***");
-#if defined(for_yahoo)
-	 VG_(message)(Vg_UserMsg, "Please yinst install getpath_kern");
-#else
-	 VG_(message)(Vg_UserMsg, "There is a copy in valgrind/getpath/*");
-#endif
-	 VG_(message)(Vg_UserMsg, "");
-	 VG_(do_syscall2)(__NR_nanosleep, (UWord)&ts, (UWord)NULL);
-      }
-   }
-#endif
    /* Check for sane path in ./configure --prefix=... */
    if (VG_LIBDIR[0] != '/') 
       VG_(err_config_error)("Please use absolute paths in "

==== //depot/projects/valgrind/coregrind/pub_core_libcproc.h#4 (text+ko) ====

@@ -88,7 +88,8 @@
 // sysctl, modfind
 extern Int VG_(sysctl)(Int *oid, UInt oidlen, void *oldp, vki_size_t *oldlenp, void *newp, vki_size_t newlen);
 extern Int VG_(sysctlbyname)(const Char *name, void *oldp, vki_size_t *oldlenp, void *newp, vki_size_t newlen);
-extern Int VG_(modfind)(const Char *name);
+extern Int VG_(getosreldate)(void);
+extern Bool VG_(is32on64)(void);
 #endif
 
 #endif   // __PUB_CORE_LIBCPROC_H

==== //depot/projects/valgrind/include/vki/vki-freebsd.h#12 (text+ko) ====

@@ -1815,8 +1815,10 @@
 //----------------------------------------------------------------------
 
 #define VKI_CTL_KERN         1
+#define VKI_CTL_HW           6
 #define VKI_KERN_PROC        14
 #define VKI_KERN_PROC_VMMAP  13
+#define VKI_HW_MACHINE       1
 
 //----------------------------------------------------------------------
 // From sys/thr.h



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200811072236.mA7Mano2058175>