libunwind-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Libunwind-devel] x86_64 trace cache and FreeBSD


From: Konstantin Belousov
Subject: [Libunwind-devel] x86_64 trace cache and FreeBSD
Date: Sat, 17 Sep 2011 00:58:57 +0300
User-agent: Mutt/1.4.2.3i

I need the patch below on FreeBSD/amd64, otherwise trace cache
pool is not initialized, and e.g. Gtest-bt loops infinitely in
mempool.c:add_memory() due to obj_size == 0.

commit 6d904047253827a047907a45b67694c17df2c65d
Author: Konstantin Belousov <address@hidden>
Date:   Sat Sep 17 00:47:23 2011 +0300

    On FreeBSD, as well as on the Solaris < 10, weak pthread_once stub is
    always exported from libc. But it does nothing, which means that if
    threaded library is not loaded, then pthread_once() call do not actually
    call the initializer finction. The construct
      if (likely (pthread_once != 0))
      {
        pthread_once(&trace_cache_once, &trace_cache_init_once);
    then fails to initialize the trace cache on x86_64.
    
    Work around by checking that the initializer was indeed called.
    Note that this can break if libthr is loaded dynamically, but my belief
    is that there is no platforms which allow dynamic loading of the threading
    library.

diff --git a/src/x86_64/Gtrace.c b/src/x86_64/Gtrace.c
index 4a5b583..4e8b8af 100644
--- a/src/x86_64/Gtrace.c
+++ b/src/x86_64/Gtrace.c
@@ -50,6 +50,7 @@ typedef struct
 static const unw_tdep_frame_t empty_frame = { 0, UNW_X86_64_FRAME_OTHER, -1, 
-1, 0, -1, -1 };
 static pthread_mutex_t trace_init_lock = PTHREAD_MUTEX_INITIALIZER;
 static pthread_once_t trace_cache_once = PTHREAD_ONCE_INIT;
+static sig_atomic_t trace_cache_once_happen;
 static pthread_key_t trace_cache_key;
 static struct mempool trace_cache_pool;
 
@@ -69,6 +70,7 @@ trace_cache_init_once (void)
 {
   pthread_key_create (&trace_cache_key, &trace_cache_free);
   mempool_init (&trace_cache_pool, sizeof (unw_trace_cache_t), 0);
+  trace_cache_once_happen = 1;
 }
 
 static unw_tdep_frame_t *
@@ -137,6 +139,24 @@ trace_cache_expand (unw_trace_cache_t *cache)
 
 static __thread  unw_trace_cache_t *tls_cache;
 
+static unw_trace_cache_t *
+trace_cache_get_unthreaded (void)
+{
+  unw_trace_cache_t *cache;
+  intrmask_t saved_mask;
+  static unw_trace_cache_t *global_cache = 0;
+  lock_acquire (&trace_init_lock, saved_mask);
+  if (! global_cache)
+  {
+    mempool_init (&trace_cache_pool, sizeof (unw_trace_cache_t), 0);
+    global_cache = trace_cache_create ();
+  }
+  cache = global_cache;
+  lock_release (&trace_init_lock, saved_mask);
+  Debug(5, "using cache %p\n", cache);
+  return cache;
+}
+
 /* Get the frame cache for the current thread. Create it if there is none. */
 static unw_trace_cache_t *
 trace_cache_get (void)
@@ -145,6 +165,10 @@ trace_cache_get (void)
   if (likely (pthread_once != 0))
   {
     pthread_once(&trace_cache_once, &trace_cache_init_once);
+    if (!trace_cache_once_happen)
+    {
+      return trace_cache_get_unthreaded();
+    }
     if (! (cache = tls_cache))
     {
       cache = trace_cache_create();
@@ -156,18 +180,7 @@ trace_cache_get (void)
   }
   else
   {
-    intrmask_t saved_mask;
-    static unw_trace_cache_t *global_cache = 0;
-    lock_acquire (&trace_init_lock, saved_mask);
-    if (! global_cache)
-    {
-      mempool_init (&trace_cache_pool, sizeof (unw_trace_cache_t), 0);
-      global_cache = trace_cache_create ();
-    }
-    cache = global_cache;
-    lock_release (&trace_init_lock, saved_mask);
-    Debug(5, "using cache %p\n", cache);
-    return cache;
+    return trace_cache_get_unthreaded();
   }
 }
 

Attachment: pgpTwm_QIW4iM.pgp
Description: PGP signature


reply via email to

[Prev in Thread] Current Thread [Next in Thread]