Made sure that DRD processes client programs that use SA_ONSTACK
correctly (e.g. Wine).


git-svn-id: svn://svn.valgrind.org/valgrind/trunk@11329 a5019735-40e9-0310-863c-91ae7b9d1cf9
diff --git a/drd/drd_main.c b/drd/drd_main.c
index 63e1bb0..cc019af 100644
--- a/drd/drd_main.c
+++ b/drd/drd_main.c
@@ -326,9 +326,6 @@
 {
    const Addr a2 = a1 + len;
 
-   if (len == 0)
-      return;
-
    tl_assert(a1 < a2);
 
    if (UNLIKELY(DRD_(any_address_is_traced)()))
@@ -451,6 +448,74 @@
                       True);
 }
 
+static
+Bool on_alt_stack(const Addr a)
+{
+   ThreadId vg_tid;
+   Addr alt_min;
+   SizeT alt_size;
+
+   vg_tid = VG_(get_running_tid)();
+   alt_min = VG_(thread_get_altstack_min)(vg_tid);
+   alt_size = VG_(thread_get_altstack_size)(vg_tid);
+   return (SizeT)(a - alt_min) < alt_size;
+}
+
+static
+void drd_start_using_mem_alt_stack(const Addr a, const SizeT len)
+{
+   if (!on_alt_stack(a))
+      drd_start_using_mem_stack(a, len);
+}
+
+static
+void drd_stop_using_mem_alt_stack(const Addr a, const SizeT len)
+{
+   if (!on_alt_stack(a))
+      drd_stop_using_mem_stack(a, len);
+}
+
+/**
+ * Callback function invoked by the Valgrind core before a signal is delivered.
+ */
+static
+void drd_pre_deliver_signal(const ThreadId vg_tid, const Int sigNo,
+                            const Bool alt_stack)
+{
+   DrdThreadId drd_tid;
+
+   drd_tid = DRD_(VgThreadIdToDrdThreadId)(vg_tid);
+   DRD_(thread_set_on_alt_stack)(drd_tid, alt_stack);
+   if (alt_stack)
+   {
+      /*
+       * As soon a signal handler has been invoked on the alternate stack,
+       * switch to stack memory handling functions that can handle the
+       * alternate stack.
+       */
+      VG_(track_new_mem_stack)(drd_start_using_mem_alt_stack);
+      VG_(track_die_mem_stack)(drd_stop_using_mem_alt_stack);
+   }
+}
+
+/**
+ * Callback function invoked by the Valgrind core after a signal is delivered,
+ * at least if the signal handler did not longjmp().
+ */
+static
+void drd_post_deliver_signal(const ThreadId vg_tid, const Int sigNo)
+{
+   DrdThreadId drd_tid;
+
+   drd_tid = DRD_(VgThreadIdToDrdThreadId)(vg_tid);
+   DRD_(thread_set_on_alt_stack)(drd_tid, False);
+   if (DRD_(thread_get_threads_on_alt_stack)() == 0)
+   {
+      VG_(track_new_mem_stack)(drd_start_using_mem_stack);
+      VG_(track_die_mem_stack)(drd_stop_using_mem_stack);
+   }
+}
+
 /**
  * Callback function called by the Valgrind core before a stack area is
  * being used by a signal handler.
@@ -683,6 +748,8 @@
    VG_(track_die_mem_munmap)       (drd_stop_using_nonstack_mem);
    VG_(track_die_mem_stack)        (drd_stop_using_mem_stack);
    VG_(track_die_mem_stack_signal) (drd_stop_using_mem_stack_signal);
+   VG_(track_pre_deliver_signal)   (drd_pre_deliver_signal);
+   VG_(track_post_deliver_signal)  (drd_post_deliver_signal);
    VG_(track_start_client_code)    (drd_start_client_code);
    VG_(track_pre_thread_ll_create) (drd_pre_thread_create);
    VG_(track_pre_thread_first_insn)(drd_post_thread_create);