|
From: <sv...@va...> - 2006-10-01 17:24:00
|
Author: sewardj
Date: 2006-10-01 18:23:57 +0100 (Sun, 01 Oct 2006)
New Revision: 6120
Log:
Get rid of VG_(sigtimedwait) and replace it a simpler version,
VG_(sigtimedwait_zero), which polls for signals and returns
immediately. AIX doesn't have a sigtimedwait syscall, so in that case
try and implement VG_(sigtimedwait_zero) using various other signal
syscalls.
Modified:
branches/AIX5/coregrind/m_libcsignal.c
branches/AIX5/include/pub_tool_libcsignal.h
Modified: branches/AIX5/coregrind/m_libcsignal.c
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
--- branches/AIX5/coregrind/m_libcsignal.c 2006-10-01 17:19:52 UTC (rev 6=
119)
+++ branches/AIX5/coregrind/m_libcsignal.c 2006-10-01 17:23:57 UTC (rev 6=
120)
@@ -29,14 +29,18 @@
*/
=20
#include "pub_core_basics.h"
+#include "pub_core_debuglog.h"
+#include "pub_core_vki.h"
+#include "pub_core_vkiscnums.h"
#include "pub_core_libcbase.h"
#include "pub_core_libcassert.h"
#include "pub_core_libcsignal.h"
#include "pub_core_syscall.h"
-#include "vki_unistd.h"
=20
/* sigemptyset, sigfullset, sigaddset and sigdelset return 0 on
success and -1 on error. */
+/* I believe the indexing scheme in ->sig[] is also correct for
+ 32- and 64-bit AIX (verified 27 July 06). */
=20
Int VG_(sigfillset)( vki_sigset_t* set )
{
@@ -121,7 +125,6 @@
return 0;
}
=20
-
/* Add all signals in src to dst. */
void VG_(sigaddset_from_set)( vki_sigset_t* dst, vki_sigset_t* src )
{
@@ -163,14 +166,6 @@
}
=20
=20
-Int VG_(sigtimedwait)( const vki_sigset_t *set, vki_siginfo_t *info,=20
- const struct vki_timespec *timeout )
-{
- SysRes res =3D VG_(do_syscall4)(__NR_rt_sigtimedwait, (UWord)set, (UW=
ord)info,=20
- (UWord)timeout, sizeof(*set));
- return res.isError ? -1 : res.val;
-}
-=20
Int VG_(signal)(Int signum, void (*sighandler)(Int))
{
SysRes res;
@@ -178,7 +173,9 @@
struct vki_sigaction sa;
sa.ksa_handler =3D sighandler;
sa.sa_flags =3D VKI_SA_ONSTACK | VKI_SA_RESTART;
+# if !defined(VGO_aix5)
sa.sa_restorer =3D NULL;
+# endif
n =3D VG_(sigemptyset)( &sa.sa_mask );
vg_assert(n =3D=3D 0);
res =3D VG_(do_syscall4)(__NR_rt_sigaction, signum, (UWord)&sa, (UWor=
d)NULL,
@@ -197,21 +194,134 @@
Int VG_(tkill)( ThreadId tid, Int signo )
{
SysRes res =3D VG_(mk_SysRes_Error)(VKI_ENOSYS);
+ res =3D VG_(do_syscall2)(__NR_tkill, tid, signo);
+ if (res.isError && res.err =3D=3D VKI_ENOSYS)
+ res =3D VG_(do_syscall2)(__NR_kill, tid, signo);
+ return res.isError ? -1 : 0;
+}
=20
-#if 0
- /* This isn't right because the client may create a process
- structure with multiple thread groups */
- res =3D VG_(do_syscall3)(__NR_tgkill, VG_(getpid)(), tid, signo);
-#endif
=20
- res =3D VG_(do_syscall2)(__NR_tkill, tid, signo);
+/* A cut-down version of POSIX sigtimedwait: poll for pending signals
+ mentioned in the sigset_t, and if any are present, select one
+ arbitrarily, return its number (which must be > 0), and put
+ auxiliary info about it in the siginfo_t, and make it
+ not-pending-any-more. If none are pending, return zero. The _zero
+ refers to the fact that there is zero timeout, so if no signals are
+ pending it returns immediately. Perhaps a better name would be
+ 'sigpoll'. Returns -1 on error, 0 if no signals pending, and n > 0
+ if signal n was selected.=20
=20
- if (res.isError && res.val =3D=3D VKI_ENOSYS)
- res =3D VG_(do_syscall2)(__NR_kill, tid, signo);
+ The Linux implementation is trivial: do the corresponding syscall.
=20
- return res.isError ? -1 : 0;
+ The AIX implementation is horrible and probably broken in a dozen
+ obscure ways. I suspect it's only thread-safe because V forces
+ single-threadedness. */
+
+#if defined(VGO_linux)
+Int VG_(sigtimedwait_zero)( const vki_sigset_t *set,=20
+ vki_siginfo_t *info )
+{
+ static const struct vki_timespec zero =3D { 0, 0 };
+ SysRes res =3D VG_(do_syscall4)(__NR_rt_sigtimedwait, (UWord)set, (UW=
ord)info,=20
+ (UWord)&zero, sizeof(*set));
+ return res.isError ? -1 : res.res;
}
=20
+#elif defined(VGO_aix5)
+/* The general idea is:
+ - use sigpending to find out which signals are pending
+ - choose one
+ - temporarily set its handler to sigtimedwait_zero_handler
+ - use sigsuspend atomically unblock it and wait for the signal.
+ Upon return, sigsuspend restores the signal mask to what it
+ was to start with.
+ - Restore the handler for the signal to whatever it was before.
+*/
+
+/* A signal handler which does nothing (it doesn't need to). It does
+ however check that it's not handing a sync signal for which
+ returning is meaningless. */
+static void sigtimedwait_zero_handler ( Int sig )=20
+{=20
+ vg_assert(sig !=3D VKI_SIGILL);
+ vg_assert(sig !=3D VKI_SIGSEGV);
+ vg_assert(sig !=3D VKI_SIGBUS);
+ vg_assert(sig !=3D VKI_SIGTRAP);
+ /* do nothing */=20
+}
+
+Int VG_(sigtimedwait_zero)( const vki_sigset_t *set,=20
+ vki_siginfo_t *info )
+{
+ Int i, ir;
+ SysRes sr;
+ vki_sigset_t pending, blocked, allbutone;
+ struct vki_sigaction sa, saved_sa;
+
+ /* Find out what's pending: AIX _sigpending */
+ sr =3D VG_(do_syscall1)(__NR__sigpending, (UWord)&pending);
+ vg_assert(!sr.isError);
+
+ /* don't try for signals not in 'set' */
+ /* pending =3D pending `intersect` set */
+ for (i =3D 0; i < _VKI_NSIG_WORDS; i++)
+ pending.sig[i] &=3D set->sig[i];
+
+ /* don't try for signals not blocked at the moment */
+ ir =3D VG_(sigprocmask)(VKI_SIG_SETMASK, NULL, &blocked);
+ vg_assert(ir =3D=3D 0);
+
+ /* pending =3D pending `intersect` blocked */
+ for (i =3D 0; i < _VKI_NSIG_WORDS; i++)
+ pending.sig[i] &=3D blocked.sig[i];
+
+ /* decide which signal we're going to snarf */
+ for (i =3D 1; i < _VKI_NSIG; i++)
+ if (VG_(sigismember)(&pending,i))
+ break;
+
+ if (i =3D=3D _VKI_NSIG)
+ return 0;
+
+ /* fetch signal i.
+ pre: i is blocked and pending
+ pre: we are the only thread running=20
+ */
+ /* Set up alternative signal handler */
+ VG_(sigfillset)(&allbutone);
+ VG_(sigdelset)(&allbutone, i);
+ sa.sa_mask =3D allbutone;
+ sa.ksa_handler =3D &sigtimedwait_zero_handler;
+ sa.sa_flags =3D 0;
+ ir =3D VG_(sigaction)(i, &sa, &saved_sa);
+ vg_assert(ir =3D=3D 0);
+
+ /* Switch signal masks and wait for the signal. This should happen
+ immediately, since we've already established it is pending and
+ blocked. */
+ sr =3D 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",=20
+ sr.res, sr.err);
+ vg_assert(sr.res =3D=3D (UWord)-1);
+
+ /* Restore signal's handler to whatever it was before */
+ ir =3D VG_(sigaction)(i, &saved_sa, NULL);
+ vg_assert(ir =3D=3D 0);
+
+ /* This is bogus - we could get more info from the sighandler. */
+ VG_(memset)( info, 0, sizeof(*info) );
+ info->si_signo =3D i;
+
+ return i;
+}
+
+#else
+# error Unknown OS
+#endif
+
/*--------------------------------------------------------------------*/
/*--- end ---*/
/*--------------------------------------------------------------------*/
Modified: branches/AIX5/include/pub_tool_libcsignal.h
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
--- branches/AIX5/include/pub_tool_libcsignal.h 2006-10-01 17:19:52 UTC (=
rev 6119)
+++ branches/AIX5/include/pub_tool_libcsignal.h 2006-10-01 17:23:57 UTC (=
rev 6120)
@@ -40,6 +40,17 @@
extern Int VG_(sigprocmask) ( Int how, const vki_sigset_t* set,
vki_sigset_t* oldset );
=20
+/* A cut-down version of POSIX sigtimedwait: poll for pending signals
+ mentioned in the sigset_t, and if any are present, select one
+ arbitrarily, return its number (which must be > 0), and put
+ auxiliary info about it in the siginfo_t, and make it
+ not-pending-any-more. If none are pending, return zero. The _zero
+ refers to the fact that there is zero timeout, so if no signals are
+ pending it returns immediately. Perhaps a better name would be
+ 'sigpoll'. Returns -1 on error, 0 if no signals pending, and n > 0
+ if signal n was selected. */
+extern Int VG_(sigtimedwait_zero)( const vki_sigset_t *, vki_siginfo_t *=
);
+
#endif // __PUB_TOOL_LIBCBSIGNAL_H
=20
/*--------------------------------------------------------------------*/
|