Commit the patch from bug 69508 that seeks to make more of the pthread
stack attribute related functions work properly as it seems to be a
sensible thing to improve even if it isn't enough to get the JVM running
under valgrind now.


git-svn-id: svn://svn.valgrind.org/valgrind/trunk@2444 a5019735-40e9-0310-863c-91ae7b9d1cf9
diff --git a/coregrind/vg_scheduler.c b/coregrind/vg_scheduler.c
index 5ef5834..3d33bad 100644
--- a/coregrind/vg_scheduler.c
+++ b/coregrind/vg_scheduler.c
@@ -596,6 +596,7 @@
       mostly_clear_thread_record(i);
       VG_(threads)[i].stack_size           = 0;
       VG_(threads)[i].stack_base           = (Addr)NULL;
+      VG_(threads)[i].stack_guard_size     = 0;
       VG_(threads)[i].stack_highest_word   = (Addr)NULL;
    }
 
@@ -1291,9 +1292,6 @@
 #include <pthread.h>
 #include <errno.h>
 
-#define VG_PTHREAD_STACK_MIN \
-   (VG_PTHREAD_STACK_SIZE - VG_AR_CLIENT_STACKBASE_REDZONE_SZB)
-
 /*  /usr/include/bits/pthreadtypes.h:
     typedef unsigned long int pthread_t;
 */
@@ -1876,7 +1874,8 @@
 static
 void do__apply_in_new_thread ( ThreadId parent_tid,
                                void* (*fn)(void *), 
-                               void* arg )
+                               void* arg,
+                               StackInfo *si )
 {
    Addr     new_stack;
    UInt     new_stk_szb;
@@ -1927,16 +1926,17 @@
 
    /* Consider allocating the child a stack, if the one it already has
       is inadequate. */
-   new_stk_szb = VG_PTHREAD_STACK_MIN;
+   new_stk_szb = si->size + VG_AR_CLIENT_STACKBASE_REDZONE_SZB + si->guardsize;
+   new_stk_szb = (new_stk_szb + VKI_BYTES_PER_PAGE - 1) & ~VKI_BYTES_PER_PAGE;
+    
+   VG_(threads)[tid].stack_guard_size = si->guardsize;
 
    if (new_stk_szb > VG_(threads)[tid].stack_size) {
       /* Again, for good measure :) We definitely don't want to be
          allocating a stack for the main thread. */
       vg_assert(tid != 1);
-      /* for now, we don't handle the case of anything other than
-         assigning it for the first time. */
-      vg_assert(VG_(threads)[tid].stack_size == 0);
-      vg_assert(VG_(threads)[tid].stack_base == (Addr)NULL);
+      if (VG_(threads)[tid].stack_size > 0)
+         VG_(client_free)(VG_(threads)[tid].stack_base);
       new_stack = VG_(client_alloc)(0, new_stk_szb, 
 				    VKI_PROT_READ | VKI_PROT_WRITE | VKI_PROT_EXEC, 
 				    SF_STACK);
@@ -1957,7 +1957,8 @@
                        - VG_AR_CLIENT_STACKBASE_REDZONE_SZB);
 
    VG_TRACK ( die_mem_stack, VG_(threads)[tid].stack_base, 
-                           + new_stk_szb - VG_AR_CLIENT_STACKBASE_REDZONE_SZB);
+                             VG_(threads)[tid].stack_size
+                             - VG_AR_CLIENT_STACKBASE_REDZONE_SZB);
    VG_TRACK ( ban_mem_stack, VG_(threads)[tid].m_esp, 
                              VG_AR_CLIENT_STACKBASE_REDZONE_SZB );
    
@@ -2918,6 +2919,34 @@
    VG_TRACK( post_mem_write, (Addr)fh, sizeof(ForkHandlerEntry) );
 }
 
+
+static
+void do__get_stack_info ( ThreadId tid, ThreadId which, StackInfo* si )
+{
+   Char msg_buf[100];
+   
+   vg_assert(VG_(is_valid_tid)(tid) 
+             && VG_(threads)[tid].status == VgTs_Runnable);
+   
+   if (VG_(clo_trace_sched)) {
+      VG_(sprintf)(msg_buf, "get_stack_info for tid %d", which );
+      print_pthread_event(tid, msg_buf);
+   }
+
+   if (!VG_(is_valid_tid)(which)) {
+      SET_PTHREQ_RETVAL(tid, -1);
+      return;
+   }
+
+   si->base = VG_(threads)[which].stack_base;
+   si->size = VG_(threads)[which].stack_size
+              - VG_AR_CLIENT_STACKBASE_REDZONE_SZB
+              - VG_(threads)[which].stack_guard_size;
+   si->guardsize = VG_(threads)[which].stack_guard_size;
+
+   SET_PTHREQ_RETVAL(tid, 0);
+}
+
 /* ---------------------------------------------------------------------
    Specifying shadow register values
    ------------------------------------------------------------------ */
@@ -3153,7 +3182,7 @@
 
       case VG_USERREQ__APPLY_IN_NEW_THREAD:
          do__apply_in_new_thread ( tid, (void*(*)(void*))arg[1], 
-                                        (void*)arg[2] );
+                                        (void*)arg[2], (StackInfo*)(arg[3]) );
          break;
 
       case VG_USERREQ__GET_KEY_D_AND_S:
@@ -3194,6 +3223,10 @@
          handle_signal_return(tid);
 	 break;
 
+      case VG_USERREQ__GET_STACK_INFO:
+         do__get_stack_info( tid, (Int)(arg[1]), (StackInfo*)(arg[2]) );
+         break;
+
 
       case VG_USERREQ__GET_SIGRT_MIN:
 	 SET_PTHREQ_RETVAL(tid, VG_(sig_rtmin));
@@ -3374,18 +3407,20 @@
          Int
          stack_used = (Addr)VG_(threads)[i].stack_highest_word 
                       - (Addr)VG_(threads)[i].m_esp;
-
+         Int
+         stack_avail = VG_(threads)[i].stack_size
+                       - VG_AR_CLIENT_STACKBASE_REDZONE_SZB
+                       - VG_(threads)[i].stack_guard_size;
 	 /* This test is a bit bogus - it doesn't take into account
 	    alternate signal stacks, for a start.  Also, if a thread
 	    has it's stack pointer somewhere strange, killing Valgrind
 	    isn't the right answer. */
          if (0 && i > 1 /* not the root thread */ 
-             && stack_used 
-                >= (VG_PTHREAD_STACK_MIN - 1000 /* paranoia */)) {
+             && stack_used >= stack_avail) {
             VG_(message)(Vg_UserMsg,
                "Error: STACK OVERFLOW: "
                "thread %d: stack used %d, available %d", 
-               i, stack_used, VG_PTHREAD_STACK_MIN );
+               i, stack_used, stack_avail );
             VG_(message)(Vg_UserMsg,
                "Terminating Valgrind.  If thread(s) "
                "really need more stack, increase");