Reduce code duplication in atfork
authorDavid Bartley <dtbartle@csclub.uwaterloo.ca>
Tue, 12 Aug 2008 06:59:47 +0000 (02:59 -0400)
committerDavid Bartley <dtbartle@csclub.uwaterloo.ca>
Tue, 12 Aug 2008 06:59:47 +0000 (02:59 -0400)
nptl/sysdeps/unix/sysv/linux/register-atfork.c
nptl/sysdeps/unix/sysv/linux/unregister-atfork.c
nptl/sysdeps/unix/sysv/solaris2/opensolaris-gnu/register-atfork.c
nptl/sysdeps/unix/sysv/solaris2/opensolaris-gnu/unregister-atfork.c

index 231fc9b..9ab59b1 100644 (file)
 #include <stdlib.h>
 #include <string.h>
 #include <fork.h>
 #include <stdlib.h>
 #include <string.h>
 #include <fork.h>
+#include <pthreadP.h>
 
 
 /* Lock to protect allocation and deallocation of fork handlers.  */
 
 
 /* Lock to protect allocation and deallocation of fork handlers.  */
+#ifndef lll_define_initialized
 int __fork_lock = LLL_LOCK_INITIALIZER;
 int __fork_lock = LLL_LOCK_INITIALIZER;
+#else
+lll_define_initialized (, __fork_lock);
+#endif
 
 
 /* Number of pre-allocated handler entries.  */
 
 
 /* Number of pre-allocated handler entries.  */
index 56a4f14..d9a7436 100644 (file)
@@ -21,6 +21,7 @@
 #include <stdlib.h>
 #include <fork.h>
 #include <atomic.h>
 #include <stdlib.h>
 #include <fork.h>
 #include <atomic.h>
+#include <pthreadP.h>
 
 
 void
 
 
 void
@@ -104,7 +105,10 @@ __unregister_atfork (dso_handle)
       atomic_decrement (&deleted->handler->refcntr);
       unsigned int val;
       while ((val = deleted->handler->refcntr) != 0)
       atomic_decrement (&deleted->handler->refcntr);
       unsigned int val;
       while ((val = deleted->handler->refcntr) != 0)
+        ; // TODO
+#if 0 // TODO
        lll_futex_wait (&deleted->handler->refcntr, val, LLL_PRIVATE);
        lll_futex_wait (&deleted->handler->refcntr, val, LLL_PRIVATE);
+#endif
 
       deleted = deleted->next;
     }
 
       deleted = deleted->next;
     }
index 35deaf8..50331dd 100644 (file)
@@ -1,137 +1 @@
-/* Copyright (C) 2002, 2003, 2005, 2007, 2008 Free Software Foundation, Inc.
-   This file is part of the GNU C Library.
-   Contributed by Ulrich Drepper <drepper@redhat.com>, 2002.
-   OpenSolaris bits contributed by David Bartley
-    <dtbartle@csclub.uwaterloo.ca>, 2008.
-
-   The GNU C Library is free software; you can redistribute it and/or
-   modify it under the terms of the GNU Lesser General Public
-   License as published by the Free Software Foundation; either
-   version 2.1 of the License, or (at your option) any later version.
-
-   The GNU C Library is distributed in the hope that it will be useful,
-   but WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-   Lesser General Public License for more details.
-
-   You should have received a copy of the GNU Lesser General Public
-   License along with the GNU C Library; if not, write to the Free
-   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
-   02111-1307 USA.  */
-
-#include <errno.h>
-#include <stdlib.h>
-#include <string.h>
-#include <fork.h>
-
-
-/* Lock to protect allocation and deallocation of fork handlers.  */
-__libc_lock_define_initialized (, __fork_lock);
-
-
-/* Number of pre-allocated handler entries.  */
-#define NHANDLER 48
-
-/* Memory pool for fork handler structures.  */
-static struct fork_handler_pool
-{
-  struct fork_handler_pool *next;
-  struct fork_handler mem[NHANDLER];
-} fork_handler_pool;
-
-
-static struct fork_handler *
-fork_handler_alloc (void)
-{
-  struct fork_handler_pool *runp = &fork_handler_pool;
-  struct fork_handler *result = NULL;
-  unsigned int i;
-
-  do
-    {
-      /* Search for an empty entry.  */
-      for (i = 0; i < NHANDLER; ++i)
-       if (runp->mem[i].refcntr == 0)
-         goto found;
-    }
-  while ((runp = runp->next) != NULL);
-
-  /* We have to allocate a new entry.  */
-  runp = (struct fork_handler_pool *) calloc (1, sizeof (*runp));
-  if (runp != NULL)
-    {
-      /* Enqueue the new memory pool into the list.  */
-      runp->next = fork_handler_pool.next;
-      fork_handler_pool.next = runp;
-
-      /* We use the last entry on the page.  This means when we start
-        searching from the front the next time we will find the first
-        entry unused.  */
-      i = NHANDLER - 1;
-
-    found:
-      result = &runp->mem[i];
-      result->refcntr = 1;
-      result->need_signal = 0;
-    }
-
-  return result;
-}
-
-
-int
-__register_atfork (prepare, parent, child, dso_handle)
-     void (*prepare) (void);
-     void (*parent) (void);
-     void (*child) (void);
-     void *dso_handle;
-{
-  /* Get the lock to not conflict with other allocations.  */
-  __libc_lock_lock (__fork_lock);
-
-  struct fork_handler *newp = fork_handler_alloc ();
-
-  if (newp != NULL)
-    {
-      /* Initialize the new record.  */
-      newp->prepare_handler = prepare;
-      newp->parent_handler = parent;
-      newp->child_handler = child;
-      newp->dso_handle = dso_handle;
-
-      newp->next = __fork_handlers;
-      __fork_handlers = newp;
-    }
-
-  /* Release the lock.  */
-  __libc_lock_unlock (__fork_lock);
-
-  return newp == NULL ? ENOMEM : 0;
-}
-libc_hidden_def (__register_atfork)
-
-
-libc_freeres_fn (free_mem)
-{
-  /* Get the lock to not conflict with running forks.  */
-  __libc_lock_lock (__fork_lock);
-
-  /* No more fork handlers.  */
-  __fork_handlers = NULL;
-
-  /* Free eventually alloated memory blocks for the object pool.  */
-  struct fork_handler_pool *runp = fork_handler_pool.next;
-
-  memset (&fork_handler_pool, '\0', sizeof (fork_handler_pool));
-
-  /* Release the lock.  */
-  __libc_lock_unlock (__fork_lock);
-
-  /* We can free the memory after releasing the lock.  */
-  while (runp != NULL)
-    {
-      struct fork_handler_pool *oldp = runp;
-      runp = runp->next;
-      free (oldp);
-    }
-}
+#include <nptl/sysdeps/unix/sysv/linux/register-atfork.c>
index 6a9157a..696dda0 100644 (file)
@@ -1,116 +1 @@
-/* Copyright (C) 2002, 2003, 2005, 2007, 2008 Free Software Foundation, Inc.
-   This file is part of the GNU C Library.
-   Contributed by Ulrich Drepper <drepper@redhat.com>, 2002.
-   OpenSolaris bits contributed by David Bartley
-    <dtbartle@csclub.uwaterloo.ca>, 2008.
-
-   The GNU C Library is free software; you can redistribute it and/or
-   modify it under the terms of the GNU Lesser General Public
-   License as published by the Free Software Foundation; either
-   version 2.1 of the License, or (at your option) any later version.
-
-   The GNU C Library is distributed in the hope that it will be useful,
-   but WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-   Lesser General Public License for more details.
-
-   You should have received a copy of the GNU Lesser General Public
-   License along with the GNU C Library; if not, write to the Free
-   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
-   02111-1307 USA.  */
-
-#include <errno.h>
-#include <stdlib.h>
-#include <fork.h>
-#include <atomic.h>
-#include <stdio.h>
-
-
-void
-__unregister_atfork (dso_handle)
-     void *dso_handle;
-{
-  /* Check whether there is any entry in the list which we have to
-     remove.  It is likely that this is not the case so don't bother
-     getting the lock.
-
-     We do not worry about other threads adding entries for this DSO
-     right this moment.  If this happens this is a race and we can do
-     whatever we please.  The program will crash anyway seen.  */
-  struct fork_handler *runp = __fork_handlers;
-  struct fork_handler *lastp = NULL;
-
-  while (runp != NULL)
-    if (runp->dso_handle == dso_handle)
-      break;
-    else
-      {
-       lastp = runp;
-       runp = runp->next;
-      }
-
-  if (runp == NULL)
-    /* Nothing to do.  */
-    return;
-
-  /* Get the lock to not conflict with additions or deletions.  Note
-     that there couldn't have been another thread deleting something.
-     The __unregister_atfork function is only called from the
-     dlclose() code which itself serializes the operations.  */
-  __libc_lock_lock (__fork_lock);
-
-  /* We have to create a new list with all the entries we don't remove.  */
-  struct deleted_handler
-  {
-    struct fork_handler *handler;
-    struct deleted_handler *next;
-  } *deleted = NULL;
-
-  /* Remove the entries for the DSO which is unloaded from the list.
-     It's a single linked list so readers are.  */
-  do
-    {
-      if (runp->dso_handle == dso_handle)
-       {
-         if (lastp == NULL)
-           __fork_handlers = runp->next;
-         else
-           lastp->next = runp->next;
-
-         /* We cannot overwrite the ->next element now.  Put the deleted
-            entries in a separate list.  */
-         struct deleted_handler *newp = alloca (sizeof (*newp));
-         newp->handler = runp;
-         newp->next = deleted;
-         deleted = newp;
-       }
-      else
-       lastp = runp;
-
-      runp = runp->next;
-    }
-  while (runp != NULL);
-
-  /* Release the lock.  */
-  __libc_lock_unlock (__fork_lock);
-
-  /* Walk the list of all entries which have to be deleted.  */
-  while (deleted != NULL)
-    {
-      /* We need to be informed by possible current users.  */
-      deleted->handler->need_signal = 1;
-      /* Make sure this gets written out first.  */
-      atomic_write_barrier ();
-
-      /* Decrement the reference counter.  If it does not reach zero
-        wait for the last user.  */
-      atomic_decrement (&deleted->handler->refcntr);
-      unsigned int val;
-#if 0 // TODO
-      while ((val = deleted->handler->refcntr) != 0)
-       lll_futex_wait (&deleted->handler->refcntr, val, LLL_PRIVATE);
-#endif
-
-      deleted = deleted->next;
-    }
-}
+#include <nptl/sysdeps/unix/sysv/linux/unregister-atfork.c>