public inbox for gcc-cvs@sourceware.org
help / color / mirror / Atom feed
* [gcc r13-4758] initialize fde objects lazily
@ 2022-12-16 23:49 Thomas Neumann
  0 siblings, 0 replies; only message in thread
From: Thomas Neumann @ 2022-12-16 23:49 UTC (permalink / raw)
  To: gcc-cvs

https://gcc.gnu.org/g:6e56633daae79f514b0e71f4d9849bcd8d9ce71f

commit r13-4758-g6e56633daae79f514b0e71f4d9849bcd8d9ce71f
Author: Thomas Neumann <tneumann@users.sourceforge.net>
Date:   Fri Dec 9 18:23:44 2022 +0100

    initialize fde objects lazily
    
    When registering an unwind frame with __register_frame_info_bases
    we currently initialize that fde object eagerly. This has the
    advantage that it is immutable afterwards and we can safely
    access it from multiple threads, but it has the disadvantage
    that we pay the initialization cost even if the application
    never throws an exception.
    
    This commit changes the logic to initialize the objects lazily.
    The objects themselves are inserted into the b-tree when
    registering the frame, but the sorted fde_vector is
    not constructed yet. Only on the first time that an
    exception tries to pass through the registered code the
    object is initialized. We notice that with a double checking,
    first doing a relaxed load of the sorted bit and then re-checking
    under a mutex when the object was not initialized yet.
    
    Note that the check must implicitly be safe concering a concurrent
    frame deregistration, as trying the deregister a frame that is
    on the unwinding path of a concurrent exception is inherently racy.
    
    libgcc/ChangeLog:
            * unwind-dw2-fde.c: Initialize fde object lazily when
            the first exception tries to pass through.

Diff:
---
 libgcc/unwind-dw2-fde.c | 52 ++++++++++++++++++++++++++++++++++++++-----------
 1 file changed, 41 insertions(+), 11 deletions(-)

diff --git a/libgcc/unwind-dw2-fde.c b/libgcc/unwind-dw2-fde.c
index 8d2eaaa6bc4..b49ee3829d5 100644
--- a/libgcc/unwind-dw2-fde.c
+++ b/libgcc/unwind-dw2-fde.c
@@ -63,8 +63,6 @@ release_registered_frames (void)
 
 static void
 get_pc_range (const struct object *ob, uintptr_type *range);
-static void
-init_object (struct object *ob);
 
 #else
 /* Without fast path frame deregistration must always succeed.  */
@@ -76,6 +74,7 @@ static const int in_shutdown = 0;
    by decreasing value of pc_begin.  */
 static struct object *unseen_objects;
 static struct object *seen_objects;
+#endif
 
 #ifdef __GTHREAD_MUTEX_INIT
 static __gthread_mutex_t object_mutex = __GTHREAD_MUTEX_INIT;
@@ -103,7 +102,6 @@ init_object_mutex_once (void)
 static __gthread_mutex_t object_mutex;
 #endif
 #endif
-#endif
 
 /* Called from crtbegin.o to register the unwind info for an object.  */
 
@@ -126,10 +124,7 @@ __register_frame_info_bases (const void *begin, struct object *ob,
 #endif
 
 #ifdef ATOMIC_FDE_FAST_PATH
-  // Initialize eagerly to avoid locking later
-  init_object (ob);
-
-  // And register the frame
+  // Register the frame in the b-tree
   uintptr_type range[2];
   get_pc_range (ob, range);
   btree_insert (&registered_frames, range[0], range[1] - range[0], ob);
@@ -180,10 +175,7 @@ __register_frame_info_table_bases (void *begin, struct object *ob,
   ob->s.b.encoding = DW_EH_PE_omit;
 
 #ifdef ATOMIC_FDE_FAST_PATH
-  // Initialize eagerly to avoid locking later
-  init_object (ob);
-
-  // And register the frame
+  // Register the frame in the b-tree
   uintptr_type range[2];
   get_pc_range (ob, range);
   btree_insert (&registered_frames, range[0], range[1] - range[0], ob);
@@ -926,7 +918,15 @@ init_object (struct object* ob)
   accu.linear->orig_data = ob->u.single;
   ob->u.sort = accu.linear;
 
+#ifdef ATOMIC_FDE_FAST_PATH
+  // We must update the sorted bit with an atomic operation
+  struct object tmp;
+  tmp.s.b = ob->s.b;
+  tmp.s.b.sorted = 1;
+  __atomic_store (&(ob->s.b), &(tmp.s.b), __ATOMIC_RELEASE);
+#else
   ob->s.b.sorted = 1;
+#endif
 }
 
 #ifdef ATOMIC_FDE_FAST_PATH
@@ -1164,6 +1164,21 @@ search_object (struct object* ob, void *pc)
     }
 }
 
+#ifdef ATOMIC_FDE_FAST_PATH
+
+// Check if the object was already initialized
+static inline bool
+is_object_initialized (struct object *ob)
+{
+  // We have to use acquire atomics for the read, which
+  // is a bit involved as we read from a bitfield
+  struct object tmp;
+  __atomic_load (&(ob->s.b), &(tmp.s.b), __ATOMIC_ACQUIRE);
+  return tmp.s.b.sorted;
+}
+
+#endif
+
 const fde *
 _Unwind_Find_FDE (void *pc, struct dwarf_eh_bases *bases)
 {
@@ -1175,6 +1190,21 @@ _Unwind_Find_FDE (void *pc, struct dwarf_eh_bases *bases)
   if (!ob)
     return NULL;
 
+  // Initialize the object lazily
+  if (!is_object_initialized (ob))
+    {
+      // Check again under mutex
+      init_object_mutex_once ();
+      __gthread_mutex_lock (&object_mutex);
+
+      if (!ob->s.b.sorted)
+	{
+	  init_object (ob);
+	}
+
+      __gthread_mutex_unlock (&object_mutex);
+    }
+
   f = search_object (ob, pc);
 #else

^ permalink raw reply	[flat|nested] only message in thread

only message in thread, other threads:[~2022-12-16 23:49 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-12-16 23:49 [gcc r13-4758] initialize fde objects lazily Thomas Neumann

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).