PERFORCE change 152635 for review
Peter Wemm
peter at FreeBSD.org
Fri Nov 7 14:36:50 PST 2008
http://perforce.freebsd.org/chv.cgi?CH=152635
Change 152635 by peter at 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
More information about the p4-projects
mailing list