OSDN Git Service

* mf-runtime.c (__mfu_unregister): Warning fix for char unsigned.
[pf3gnuchains/gcc-fork.git] / libmudflap / mf-hooks3.c
index 838f381..f980c9b 100644 (file)
@@ -1,5 +1,5 @@
 /* Mudflap: narrow-pointer bounds-checking by tree rewriting.
 /* Mudflap: narrow-pointer bounds-checking by tree rewriting.
-   Copyright (C) 2002, 2003 Free Software Foundation, Inc.
+   Copyright (C) 2002, 2003, 2004 Free Software Foundation, Inc.
    Contributed by Frank Ch. Eigler <fche@redhat.com>
    and Graydon Hoare <graydon@redhat.com>
 
    Contributed by Frank Ch. Eigler <fche@redhat.com>
    and Graydon Hoare <graydon@redhat.com>
 
@@ -41,7 +41,7 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
 #if !defined(__FreeBSD__) && !defined(__APPLE__)
 #define _POSIX_SOURCE
 #endif /* Some BSDs break <sys/socket.h> if this is defined. */
 #if !defined(__FreeBSD__) && !defined(__APPLE__)
 #define _POSIX_SOURCE
 #endif /* Some BSDs break <sys/socket.h> if this is defined. */
-#define _GNU_SOURCE 
+#define _GNU_SOURCE
 #define _XOPEN_SOURCE
 #define _BSD_TYPES
 #define __EXTENSIONS__
 #define _XOPEN_SOURCE
 #define _BSD_TYPES
 #define __EXTENSIONS__
@@ -59,6 +59,7 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
 #include <errno.h>
 #include <limits.h>
 #include <sched.h>
 #include <errno.h>
 #include <limits.h>
 #include <sched.h>
+#include <fcntl.h>
 
 #include "mf-runtime.h"
 #include "mf-impl.h"
 
 #include "mf-runtime.h"
 #include "mf-impl.h"
@@ -71,8 +72,6 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
 /* Multithreading support hooks.  */
 
 
 /* Multithreading support hooks.  */
 
 
-#ifdef WRAP_pthreadstuff
-
 
 #ifndef LIBMUDFLAPTH
 #error "pthreadstuff is to be included only in libmudflapth"
 
 #ifndef LIBMUDFLAPTH
 #error "pthreadstuff is to be included only in libmudflapth"
@@ -87,9 +86,12 @@ struct pthread_info
   short dead_p;  /* Is this thread dead?  */
   pthread_t self; /* The thread id.  */
 
   short dead_p;  /* Is this thread dead?  */
   pthread_t self; /* The thread id.  */
 
-  /* If libmudflapth allocated the stack, store its base/size.  */
+  /* If libmudflapth allocated the stack, store its adjusted base/size.  */
   void *stack;
   size_t stack_size;
   void *stack;
   size_t stack_size;
+  /* The _alloc fields store unadjusted values from the moment of allocation.  */
+  void *stack_alloc;
+  size_t stack_size_alloc;
 
   int *thread_errno;
   enum __mf_state_enum state;
 
   int *thread_errno;
   enum __mf_state_enum state;
@@ -123,7 +125,7 @@ static unsigned __mf_pthread_info_idx[LIBMUDFLAPTH_THREADS_MAX];
 
 /* Find any old empty entry in __mf_pthread_info; mark it used and
    return it.  Return NULL if there are no more available slots.  */
 
 /* Find any old empty entry in __mf_pthread_info; mark it used and
    return it.  Return NULL if there are no more available slots.  */
-struct pthread_info* 
+struct pthread_info*
 __mf_allocate_blank_threadinfo (unsigned* idx)
 {
   static unsigned probe = LIBMUDFLAPTH_THREADS_MAX-1;
 __mf_allocate_blank_threadinfo (unsigned* idx)
 {
   static unsigned probe = LIBMUDFLAPTH_THREADS_MAX-1;
@@ -156,7 +158,7 @@ __mf_allocate_blank_threadinfo (unsigned* idx)
        }
     }
   while (probe != probe_at_start);
        }
     }
   while (probe != probe_at_start);
-  
+
   rc = pthread_mutex_unlock (& mutex);
   assert (rc == 0);
   return NULL;
   rc = pthread_mutex_unlock (& mutex);
   assert (rc == 0);
   return NULL;
@@ -170,8 +172,12 @@ __mf_allocate_blank_threadinfo (unsigned* idx)
    making an early call into libmudflap.  In these cases, create a new
    entry.  If not it's not the main thread, put it into reentrant
    initial state.
    making an early call into libmudflap.  In these cases, create a new
    entry.  If not it's not the main thread, put it into reentrant
    initial state.
+
+   NB: VERBOSE_TRACE type functions are not generally safe to call
+   from this context, since a new thread might just be "booting up",
+   making printf unsafe to call.
 */
 */
-static struct pthread_info* 
+static struct pthread_info*
 __mf_find_threadinfo ()
 {
   pthread_t it = pthread_self ();
 __mf_find_threadinfo ()
 {
   pthread_t it = pthread_self ();
@@ -191,14 +197,14 @@ __mf_find_threadinfo ()
     else for (i = 0; i < LIBMUDFLAPTH_THREADS_MAX; i++)
       {
        struct pthread_info* pi2 = & __mf_pthread_info [i];
     else for (i = 0; i < LIBMUDFLAPTH_THREADS_MAX; i++)
       {
        struct pthread_info* pi2 = & __mf_pthread_info [i];
-       if (pi2->used_p && pi2->self == it) 
+       if (pi2->used_p && pi2->self == it)
          {
            *hash = i;
            result = pi2;
            break;
          }
       }
          {
            *hash = i;
            result = pi2;
            break;
          }
       }
-  }    
+  }
 
   if (result == NULL)
     {
 
   if (result == NULL)
     {
@@ -223,7 +229,7 @@ __mf_find_threadinfo ()
          /* NB: leave stack-related fields unset, to avoid
             deallocation.  */
          main_thread_seen_p = 1;
          /* NB: leave stack-related fields unset, to avoid
             deallocation.  */
          main_thread_seen_p = 1;
-         VERBOSE_TRACE ("identified self as main thread\n");
+         /* VERBOSE_TRACE ("identified self as main thread\n"); */
        }
       else
        {
        }
       else
        {
@@ -234,15 +240,17 @@ __mf_find_threadinfo ()
          /* NB: leave stack-related fields unset, leaving pthread_create
             to fill them in for user threads, leaving them empty for
             other threads.  */
          /* NB: leave stack-related fields unset, leaving pthread_create
             to fill them in for user threads, leaving them empty for
             other threads.  */
-         VERBOSE_TRACE ("identified self as new aux or user thread\n");
+         /* VERBOSE_TRACE ("identified self as new aux or user thread\n"); */
        }
     }
 
   if (last != it)
     {
        }
     }
 
   if (last != it)
     {
-      VERBOSE_TRACE ("found threadinfo for %u, slot %u\n", 
+      /*
+      VERBOSE_TRACE ("found threadinfo for %u, slot %u\n",
                     (unsigned) it,
                     (unsigned) *hash);
                     (unsigned) it,
                     (unsigned) *hash);
+      */
       last = it;
     }
 
       last = it;
     }
 
@@ -263,7 +271,7 @@ __mf_state_perthread ()
 }
 
 
 }
 
 
-static void 
+static void
 __mf_pthread_cleanup (void *arg)
 {
   struct pthread_info *pi = arg;
 __mf_pthread_cleanup (void *arg)
 {
   struct pthread_info *pi = arg;
@@ -271,7 +279,7 @@ __mf_pthread_cleanup (void *arg)
   /* XXX: This unregistration is not safe on platforms where distinct
      threads share errno (or at least its virtual address).  */
   if (pi->thread_errno != NULL)
   /* XXX: This unregistration is not safe on platforms where distinct
      threads share errno (or at least its virtual address).  */
   if (pi->thread_errno != NULL)
-    __mf_unregister (pi->thread_errno, sizeof (int));
+    __mf_unregister (pi->thread_errno, sizeof (int), __MF_TYPE_GUESS);
 
   /* XXX: Only detached threads should designate themselves as dead
      here.  Non-detached threads are marked dead after their
 
   /* XXX: Only detached threads should designate themselves as dead
      here.  Non-detached threads are marked dead after their
@@ -294,11 +302,11 @@ __mf_pthread_spawner (void *arg)
   pi->state = active;
 
   VERBOSE_TRACE ("new user thread\n");
   pi->state = active;
 
   VERBOSE_TRACE ("new user thread\n");
-  
+
   if (__mf_opts.heur_std_data)
     {
       pi->thread_errno = & errno;
   if (__mf_opts.heur_std_data)
     {
       pi->thread_errno = & errno;
-      __mf_register (pi->thread_errno, sizeof (int), 
+      __mf_register (pi->thread_errno, sizeof (int),
                     __MF_TYPE_GUESS, "errno area (thread)");
       /* NB: we could use __MF_TYPE_STATIC above, but we guess that
         the thread errno is coming out of some dynamically allocated
                     __MF_TYPE_GUESS, "errno area (thread)");
       /* NB: we could use __MF_TYPE_STATIC above, but we guess that
         the thread errno is coming out of some dynamically allocated
@@ -319,7 +327,7 @@ __mf_pthread_spawner (void *arg)
 
     /* Signal the main thread to resume.  */
     psi->thread_info = pi;
 
     /* Signal the main thread to resume.  */
     psi->thread_info = pi;
-      
+
     result = (*user_fn)(user_arg);
   }
 
     result = (*user_fn)(user_arg);
   }
 
@@ -337,7 +345,7 @@ __mf_pthread_spawner (void *arg)
 #if PIC
 /* A special bootstrap variant. */
 int
 #if PIC
 /* A special bootstrap variant. */
 int
-__mf_0fn_pthread_create (pthread_t *thr, const pthread_attr_t *attr, 
+__mf_0fn_pthread_create (pthread_t *thr, const pthread_attr_t *attr,
                         void * (*start) (void *), void *arg)
 {
   return -1;
                         void * (*start) (void *), void *arg)
 {
   return -1;
@@ -346,17 +354,19 @@ __mf_0fn_pthread_create (pthread_t *thr, const pthread_attr_t *attr,
 
 
 #undef pthread_create
 
 
 #undef pthread_create
-WRAPPER(int, pthread_create, pthread_t *thr, const pthread_attr_t *attr, 
+WRAPPER(int, pthread_create, pthread_t *thr, const pthread_attr_t *attr,
         void * (*start) (void *), void *arg)
 {
   DECLARE(int, munmap, void *p, size_t l);
   DECLARE(void *, mmap, void *p, size_t l, int prot, int flags, int fd, off_t of);
         void * (*start) (void *), void *arg)
 {
   DECLARE(int, munmap, void *p, size_t l);
   DECLARE(void *, mmap, void *p, size_t l, int prot, int flags, int fd, off_t of);
-  DECLARE(int, pthread_create, pthread_t *thr, const pthread_attr_t *attr, 
+  DECLARE(int, pthread_create, pthread_t *thr, const pthread_attr_t *attr,
          void * (*start) (void *), void *arg);
   int result;
   pthread_attr_t override_attr;
   void *override_stack;
   size_t override_stacksize;
          void * (*start) (void *), void *arg);
   int result;
   pthread_attr_t override_attr;
   void *override_stack;
   size_t override_stacksize;
+  void *override_stack_alloc = (void *) 0;
+  size_t override_stacksize_alloc = 0;
   unsigned i;
 
   TRACE ("pthread_create\n");
   unsigned i;
 
   TRACE ("pthread_create\n");
@@ -373,7 +383,7 @@ WRAPPER(int, pthread_create, pthread_t *thr, const pthread_attr_t *attr,
 
       /* VERBOSE_TRACE ("thread %u pi %p stack cleanup deferred (%u)\n",
         (unsigned) pi->self, pi, pi->dead_p); */
 
       /* VERBOSE_TRACE ("thread %u pi %p stack cleanup deferred (%u)\n",
         (unsigned) pi->self, pi, pi->dead_p); */
-             
+
       /* Delay actual deallocation by a few cycles, try to discourage the
         race mentioned at the end of __mf_pthread_spawner().  */
       if (pi->dead_p)
       /* Delay actual deallocation by a few cycles, try to discourage the
         race mentioned at the end of __mf_pthread_spawner().  */
       if (pi->dead_p)
@@ -381,9 +391,9 @@ WRAPPER(int, pthread_create, pthread_t *thr, const pthread_attr_t *attr,
       if (pi->dead_p >= 10 /* XXX */)
        {
          if (pi->stack)
       if (pi->dead_p >= 10 /* XXX */)
        {
          if (pi->stack)
-           CALL_REAL (munmap, pi->stack, pi->stack_size);
+           CALL_REAL (munmap, pi->stack_alloc, pi->stack_size_alloc);
 
 
-         VERBOSE_TRACE ("slot %u freed, stack %p\n", i, pi->stack);
+         VERBOSE_TRACE ("slot %u freed, stack %p\n", i, pi->stack_alloc);
          memset (pi, 0, sizeof (*pi));
 
          /* One round of garbage collection is enough.  */
          memset (pi, 0, sizeof (*pi));
 
          /* One round of garbage collection is enough.  */
@@ -435,34 +445,57 @@ WRAPPER(int, pthread_create, pthread_t *thr, const pthread_attr_t *attr,
 #define MF_MAP_ANON MAP_ANONYMOUS
 #elif defined(MAP_ANON)
 #define MF_MAP_ANON MAP_ANON
 #define MF_MAP_ANON MAP_ANONYMOUS
 #elif defined(MAP_ANON)
 #define MF_MAP_ANON MAP_ANON
-#else
-#error "Cannot mmap anonymous memory."
 #endif
 
 #endif
 
-      override_stack = CALL_REAL (mmap, NULL, override_stacksize, 
-                                 PROT_READ|PROT_WRITE, 
+#ifndef MAP_FAILED
+#define MAP_FAILED ((void *) -1)
+#endif
+
+#ifdef MF_MAP_ANON
+      override_stack = CALL_REAL (mmap, NULL, override_stacksize,
+                                 PROT_READ|PROT_WRITE,
                                  MAP_PRIVATE|MF_MAP_ANON,
                                  0, 0);
                                  MAP_PRIVATE|MF_MAP_ANON,
                                  0, 0);
+#else
+      /* Try mapping /dev/zero instead.  */
+      {
+        static int zerofd = -1;
+        if (zerofd == -1)
+          zerofd = open ("/dev/zero", O_RDWR);
+        if (zerofd == -1)
+          override_stack = MAP_FAILED;
+        else
+          override_stack = CALL_REAL (mmap, NULL, override_stacksize,
+                                      PROT_READ|PROT_WRITE,
+                                      MAP_PRIVATE, zerofd, 0);
+      }
+#endif
+
       if (override_stack == 0 || override_stack == MAP_FAILED)
        {
          errno = EAGAIN;
          return -1;
        }
 
       if (override_stack == 0 || override_stack == MAP_FAILED)
        {
          errno = EAGAIN;
          return -1;
        }
 
-      VERBOSE_TRACE ("thread stack alloc %p size %lu\n", 
+      VERBOSE_TRACE ("thread stack alloc %p size %lu\n",
                     override_stack, (unsigned long) override_stacksize);
 
                     override_stack, (unsigned long) override_stacksize);
 
+      /* Save the original allocated values for later deallocation.  */
+      override_stack_alloc = override_stack;
+      override_stacksize_alloc = override_stacksize;
+
       /* The stackaddr pthreads attribute is a candidate stack pointer.
         It must point near the top or the bottom of this buffer, depending
         on whether stack grows downward or upward, and suitably aligned.
         On the x86, it grows down, so we set stackaddr near the top.  */
       /* The stackaddr pthreads attribute is a candidate stack pointer.
         It must point near the top or the bottom of this buffer, depending
         on whether stack grows downward or upward, and suitably aligned.
         On the x86, it grows down, so we set stackaddr near the top.  */
+      /* XXX: port logic */
       override_stack = (void *)
        (((uintptr_t) override_stack + override_stacksize - alignment - perturb)
         & (~(uintptr_t)(alignment-1)));
       override_stack = (void *)
        (((uintptr_t) override_stack + override_stacksize - alignment - perturb)
         & (~(uintptr_t)(alignment-1)));
-      
+
       /* XXX: consider using POSIX2K attr_setstack() */
       if (pthread_attr_setstackaddr (& override_attr, override_stack) != 0 ||
       /* XXX: consider using POSIX2K attr_setstack() */
       if (pthread_attr_setstackaddr (& override_attr, override_stack) != 0 ||
-         pthread_attr_setstacksize (& override_attr, 
+         pthread_attr_setstacksize (& override_attr,
                                     override_stacksize - alignment - perturb) != 0)
        {
          /* This should not happen.  */
                                     override_stacksize - alignment - perturb) != 0)
        {
          /* This should not happen.  */
@@ -476,12 +509,12 @@ WRAPPER(int, pthread_create, pthread_t *thr, const pthread_attr_t *attr,
   {
     struct pthread_start_info psi;
     struct pthread_info *pi = NULL;
   {
     struct pthread_start_info psi;
     struct pthread_info *pi = NULL;
-    
+
     /* Fill in startup-control fields.  */
     psi.user_fn = start;
     psi.user_arg = arg;
     psi.thread_info = NULL;
     /* Fill in startup-control fields.  */
     psi.user_fn = start;
     psi.user_arg = arg;
     psi.thread_info = NULL;
-    
+
     /* Actually create the thread.  */
     __mf_state = reentrant;
     result = CALL_REAL (pthread_create, thr, & override_attr,
     /* Actually create the thread.  */
     __mf_state = reentrant;
     result = CALL_REAL (pthread_create, thr, & override_attr,
@@ -496,7 +529,7 @@ WRAPPER(int, pthread_create, pthread_t *thr, const pthread_attr_t *attr,
       {
        volatile struct pthread_start_info *psip = & psi;
        pi = psip->thread_info;
       {
        volatile struct pthread_start_info *psip = & psi;
        pi = psip->thread_info;
-       if (pi != NULL) 
+       if (pi != NULL)
          break;
        sched_yield ();
       }
          break;
        sched_yield ();
       }
@@ -504,6 +537,8 @@ WRAPPER(int, pthread_create, pthread_t *thr, const pthread_attr_t *attr,
     /* Fill in remaining fields in pthread_info. */
     pi->stack = override_stack;
     pi->stack_size = override_stacksize;
     /* Fill in remaining fields in pthread_info. */
     pi->stack = override_stack;
     pi->stack_size = override_stacksize;
+    pi->stack_alloc = override_stack_alloc;
+    pi->stack_size_alloc = override_stacksize_alloc;
     /* XXX: this might be too late for future heuristics that attempt
        to use thread stack bounds.  We may need to put the new thread
        to sleep. */
     /* XXX: this might be too late for future heuristics that attempt
        to use thread stack bounds.  We may need to put the new thread
        to sleep. */
@@ -539,7 +574,7 @@ WRAPPER(int, pthread_join, pthread_t thr, void **rc)
   __mf_state = reentrant;
   result = CALL_REAL (pthread_join, thr, rc);
   __mf_state = active;
   __mf_state = reentrant;
   result = CALL_REAL (pthread_join, thr, rc);
   __mf_state = active;
-  
+
   return result;
 }
 
   return result;
 }
 
@@ -562,12 +597,5 @@ WRAPPER(void, pthread_exit, void *rc)
   /* __mf_state = reentrant; */
   CALL_REAL (pthread_exit, rc);
   /* NOTREACHED */
   /* __mf_state = reentrant; */
   CALL_REAL (pthread_exit, rc);
   /* NOTREACHED */
+  exit (0);  /* Satisfy noreturn attribute of pthread_exit.  */
 }
 }
-
-
-
-
-
-
-
-#endif /* pthreadstuff */