public inbox for libc-alpha@sourceware.org
 help / color / mirror / Atom feed
* [PATCH] malloc: Remove malloc hooks from fork handler
@ 2016-02-10 21:48 Florian Weimer
  2016-02-16 10:24 ` Torvald Riegel
  2016-03-10 13:34 ` Florian Weimer
  0 siblings, 2 replies; 6+ messages in thread
From: Florian Weimer @ 2016-02-10 21:48 UTC (permalink / raw)
  To: GNU C Library; +Cc: Torvald Riegel

[-- Attachment #1: Type: text/plain, Size: 268 bytes --]

The fork handler now runs so late that there is no risk anymore that
other fork handlers in the same thread use malloc, so it is no
longer necessary to install malloc hooks which made a subset
of malloc functionality available to the thread that called fork.

Florian

[-- Attachment #2: 0006-malloc-Remove-malloc-hooks-from-fork-handler.patch --]
[-- Type: text/x-patch, Size: 6514 bytes --]

2016-02-10  Florian Weimer  <fweimer@redhat.com>

	Remove malloc hooks from fork handler.  They are no longer needed
	because malloc runs right before fork, and no malloc calls from
	other fork handlers are possible anymore.
	* malloc/malloc.c (malloc_atfork, free_atfork): Remove
	declarations.
	* malloc/arena.c (save_malloc_hook, save_free_hook, save_arena)
	(ATFORK_ARENA_PTR, malloc_atfork, free_atfork)
	(atfork_recursive_cntr): Remove.
	(__malloc_fork_lock_parent): Do not override malloc hooks and
	thread_arena.
	(__malloc_fork_unlock_parent): Do not restore malloc hooks and
	thread_arena.
	(__malloc_fork_unlock_child): Do not restore malloc hooks.  Use
	thread_arena instead of save_arena.

diff --git a/malloc/arena.c b/malloc/arena.c
index 8c3c3a5..c6ac0bd 100644
--- a/malloc/arena.c
+++ b/malloc/arena.c
@@ -129,75 +129,6 @@ int __malloc_initialized = -1;
 
 /* atfork support.  */
 
-static void *(*save_malloc_hook)(size_t __size, const void *);
-static void (*save_free_hook) (void *__ptr, const void *);
-static void *save_arena;
-
-/* Magic value for the thread-specific arena pointer when
-   malloc_atfork() is in use.  */
-
-# define ATFORK_ARENA_PTR ((void *) -1)
-
-/* The following hooks are used while the `atfork' handling mechanism
-   is active. */
-
-static void *
-malloc_atfork (size_t sz, const void *caller)
-{
-  void *victim;
-
-  if (thread_arena == ATFORK_ARENA_PTR)
-    {
-      /* We are the only thread that may allocate at all.  */
-      if (save_malloc_hook != malloc_check)
-        {
-          return _int_malloc (&main_arena, sz);
-        }
-      else
-        {
-          if (top_check () < 0)
-            return 0;
-
-          victim = _int_malloc (&main_arena, sz + 1);
-          return mem2mem_check (victim, sz);
-        }
-    }
-  else
-    {
-      /* Suspend the thread until the `atfork' handlers have completed.
-         By that time, the hooks will have been reset as well, so that
-         mALLOc() can be used again. */
-      (void) mutex_lock (&list_lock);
-      (void) mutex_unlock (&list_lock);
-      return __libc_malloc (sz);
-    }
-}
-
-static void
-free_atfork (void *mem, const void *caller)
-{
-  mstate ar_ptr;
-  mchunkptr p;                          /* chunk corresponding to mem */
-
-  if (mem == 0)                              /* free(0) has no effect */
-    return;
-
-  p = mem2chunk (mem);         /* do not bother to replicate free_check here */
-
-  if (chunk_is_mmapped (p))                       /* release mmapped memory. */
-    {
-      munmap_chunk (p);
-      return;
-    }
-
-  ar_ptr = arena_for_chunk (p);
-  _int_free (ar_ptr, p, thread_arena == ATFORK_ARENA_PTR);
-}
-
-
-/* Counter for number of times the list is locked by the same thread.  */
-static unsigned int atfork_recursive_cntr;
-
 /* The following three functions are called around fork from a
    multi-threaded process.  We do not use the general fork handler
    mechanism to make sure that our handlers are the last ones being
@@ -206,63 +137,30 @@ static unsigned int atfork_recursive_cntr;
 void
 __malloc_fork_lock_parent (void)
 {
-  mstate ar_ptr;
-
   if (__malloc_initialized < 1)
     return;
 
   /* We do not acquire free_list_lock here because we completely
      reconstruct free_list in __malloc_fork_unlock_child.  */
 
-  if (mutex_trylock (&list_lock))
-    {
-      if (thread_arena == ATFORK_ARENA_PTR)
-        /* This is the same thread which already locks the global list.
-           Just bump the counter.  */
-        goto out;
+  (void) mutex_lock (&list_lock);
 
-      /* This thread has to wait its turn.  */
-      (void) mutex_lock (&list_lock);
-    }
-  for (ar_ptr = &main_arena;; )
+  for (mstate ar_ptr = &main_arena;; )
     {
       (void) mutex_lock (&ar_ptr->mutex);
       ar_ptr = ar_ptr->next;
       if (ar_ptr == &main_arena)
         break;
     }
-  save_malloc_hook = __malloc_hook;
-  save_free_hook = __free_hook;
-  __malloc_hook = malloc_atfork;
-  __free_hook = free_atfork;
-  /* Only the current thread may perform malloc/free calls now.
-     save_arena will be reattached to the current thread, in
-     __malloc_fork_lock_parent, so save_arena->attached_threads is not
-     updated.  */
-  save_arena = thread_arena;
-  thread_arena = ATFORK_ARENA_PTR;
-out:
-  ++atfork_recursive_cntr;
 }
 
 void
 __malloc_fork_unlock_parent (void)
 {
-  mstate ar_ptr;
-
   if (__malloc_initialized < 1)
     return;
 
-  if (--atfork_recursive_cntr != 0)
-    return;
-
-  /* Replace ATFORK_ARENA_PTR with save_arena.
-     save_arena->attached_threads was not changed in
-     __malloc_fork_lock_parent and is still correct.  */
-  thread_arena = save_arena;
-  __malloc_hook = save_malloc_hook;
-  __free_hook = save_free_hook;
-  for (ar_ptr = &main_arena;; )
+  for (mstate ar_ptr = &main_arena;; )
     {
       (void) mutex_unlock (&ar_ptr->mutex);
       ar_ptr = ar_ptr->next;
@@ -275,25 +173,19 @@ __malloc_fork_unlock_parent (void)
 void
 __malloc_fork_unlock_child (void)
 {
-  mstate ar_ptr;
-
   if (__malloc_initialized < 1)
     return;
 
-  thread_arena = save_arena;
-  __malloc_hook = save_malloc_hook;
-  __free_hook = save_free_hook;
-
-  /* Push all arenas to the free list, except save_arena, which is
+  /* Push all arenas to the free list, except thread_arena, which is
      attached to the current thread.  */
   mutex_init (&free_list_lock);
-  if (save_arena != NULL)
-    ((mstate) save_arena)->attached_threads = 1;
+  if (thread_arena != NULL)
+    thread_arena->attached_threads = 1;
   free_list = NULL;
-  for (ar_ptr = &main_arena;; )
+  for (mstate ar_ptr = &main_arena;; )
     {
       mutex_init (&ar_ptr->mutex);
-      if (ar_ptr != save_arena)
+      if (ar_ptr != thread_arena)
         {
 	  /* This arena is no longer attached to any thread.  */
 	  ar_ptr->attached_threads = 0;
@@ -306,7 +198,6 @@ __malloc_fork_unlock_child (void)
     }
 
   mutex_init (&list_lock);
-  atfork_recursive_cntr = 0;
 }
 
 /* Initialization routine. */
diff --git a/malloc/malloc.c b/malloc/malloc.c
index 527332f..809512c 100644
--- a/malloc/malloc.c
+++ b/malloc/malloc.c
@@ -1074,8 +1074,6 @@ static void*   realloc_check(void* oldmem, size_t bytes,
 			       const void *caller);
 static void*   memalign_check(size_t alignment, size_t bytes,
 				const void *caller);
-static void*   malloc_atfork(size_t sz, const void *caller);
-static void      free_atfork(void* mem, const void *caller);
 
 /* ------------------ MMAP support ------------------  */
 

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [PATCH] malloc: Remove malloc hooks from fork handler
  2016-02-10 21:48 [PATCH] malloc: Remove malloc hooks from fork handler Florian Weimer
@ 2016-02-16 10:24 ` Torvald Riegel
  2016-02-19 16:32   ` Florian Weimer
  2016-03-10 13:34 ` Florian Weimer
  1 sibling, 1 reply; 6+ messages in thread
From: Torvald Riegel @ 2016-02-16 10:24 UTC (permalink / raw)
  To: Florian Weimer; +Cc: GNU C Library

LGTM with one question.

On Wed, 2016-02-10 at 22:48 +0100, Florian Weimer wrote:
> @@ -206,63 +137,30 @@ static unsigned int atfork_recursive_cntr;
>  void
>  __malloc_fork_lock_parent (void)
>  {
> -  mstate ar_ptr;
> -
>    if (__malloc_initialized < 1)
>      return;
>  
>    /* We do not acquire free_list_lock here because we completely
>       reconstruct free_list in __malloc_fork_unlock_child.  */
>  
> -  if (mutex_trylock (&list_lock))
> -    {
> -      if (thread_arena == ATFORK_ARENA_PTR)
> -        /* This is the same thread which already locks the global list.
> -           Just bump the counter.  */
> -        goto out;
> +  (void) mutex_lock (&list_lock);

Is it obvious why the recursive case that the previous code tried to
handle can't happen anymore?  If not, a comment might be useful.

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [PATCH] malloc: Remove malloc hooks from fork handler
  2016-02-16 10:24 ` Torvald Riegel
@ 2016-02-19 16:32   ` Florian Weimer
  0 siblings, 0 replies; 6+ messages in thread
From: Florian Weimer @ 2016-02-19 16:32 UTC (permalink / raw)
  To: Torvald Riegel; +Cc: GNU C Library

On 02/15/2016 06:07 PM, Torvald Riegel wrote:
> LGTM with one question.
> 
> On Wed, 2016-02-10 at 22:48 +0100, Florian Weimer wrote:
>> @@ -206,63 +137,30 @@ static unsigned int atfork_recursive_cntr;
>>  void
>>  __malloc_fork_lock_parent (void)
>>  {
>> -  mstate ar_ptr;
>> -
>>    if (__malloc_initialized < 1)
>>      return;
>>  
>>    /* We do not acquire free_list_lock here because we completely
>>       reconstruct free_list in __malloc_fork_unlock_child.  */
>>  
>> -  if (mutex_trylock (&list_lock))
>> -    {
>> -      if (thread_arena == ATFORK_ARENA_PTR)
>> -        /* This is the same thread which already locks the global list.
>> -           Just bump the counter.  */
>> -        goto out;
>> +  (void) mutex_lock (&list_lock);
> 
> Is it obvious why the recursive case that the previous code tried to
> handle can't happen anymore?  If not, a comment might be useful.

I think it is obvious with the previous change (which runs the fork
handler as late as possible).

The opposite was actually true—it's hard to see why the recursive lock
was ever needed because the need depended on fork handler ordering.

Thanks,
Florian

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [PATCH] malloc: Remove malloc hooks from fork handler
  2016-02-10 21:48 [PATCH] malloc: Remove malloc hooks from fork handler Florian Weimer
  2016-02-16 10:24 ` Torvald Riegel
@ 2016-03-10 13:34 ` Florian Weimer
  2016-04-12 18:19   ` Torvald Riegel
  1 sibling, 1 reply; 6+ messages in thread
From: Florian Weimer @ 2016-03-10 13:34 UTC (permalink / raw)
  To: libc-alpha

On 02/10/2016 10:48 PM, Florian Weimer wrote:
> 2016-02-10  Florian Weimer  <fweimer@redhat.com>
> 
> 	Remove malloc hooks from fork handler.  They are no longer needed
> 	because malloc runs right before fork, and no malloc calls from
> 	other fork handlers are possible anymore.
> 	* malloc/malloc.c (malloc_atfork, free_atfork): Remove
> 	declarations.
> 	* malloc/arena.c (save_malloc_hook, save_free_hook, save_arena)
> 	(ATFORK_ARENA_PTR, malloc_atfork, free_atfork)
> 	(atfork_recursive_cntr): Remove.
> 	(__malloc_fork_lock_parent): Do not override malloc hooks and
> 	thread_arena.
> 	(__malloc_fork_unlock_parent): Do not restore malloc hooks and
> 	thread_arena.
> 	(__malloc_fork_unlock_child): Do not restore malloc hooks.  Use
> 	thread_arena i

Ping?

Thanks,
Florian

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [PATCH] malloc: Remove malloc hooks from fork handler
  2016-03-10 13:34 ` Florian Weimer
@ 2016-04-12 18:19   ` Torvald Riegel
  2016-04-14  8:38     ` Florian Weimer
  0 siblings, 1 reply; 6+ messages in thread
From: Torvald Riegel @ 2016-04-12 18:19 UTC (permalink / raw)
  To: Florian Weimer; +Cc: libc-alpha

On Thu, 2016-03-10 at 14:34 +0100, Florian Weimer wrote:
> On 02/10/2016 10:48 PM, Florian Weimer wrote:
> > 2016-02-10  Florian Weimer  <fweimer@redhat.com>
> > 
> > 	Remove malloc hooks from fork handler.  They are no longer needed
> > 	because malloc runs right before fork, and no malloc calls from
> > 	other fork handlers are possible anymore.
> > 	* malloc/malloc.c (malloc_atfork, free_atfork): Remove
> > 	declarations.
> > 	* malloc/arena.c (save_malloc_hook, save_free_hook, save_arena)
> > 	(ATFORK_ARENA_PTR, malloc_atfork, free_atfork)
> > 	(atfork_recursive_cntr): Remove.
> > 	(__malloc_fork_lock_parent): Do not override malloc hooks and
> > 	thread_arena.
> > 	(__malloc_fork_unlock_parent): Do not restore malloc hooks and
> > 	thread_arena.
> > 	(__malloc_fork_unlock_child): Do not restore malloc hooks.  Use
> > 	thread_arena i
> 
> Ping?

You answered the only question that I had, and it looked good to me
otherwise.

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [PATCH] malloc: Remove malloc hooks from fork handler
  2016-04-12 18:19   ` Torvald Riegel
@ 2016-04-14  8:38     ` Florian Weimer
  0 siblings, 0 replies; 6+ messages in thread
From: Florian Weimer @ 2016-04-14  8:38 UTC (permalink / raw)
  To: libc-alpha

On 04/12/2016 08:19 PM, Torvald Riegel wrote:
> On Thu, 2016-03-10 at 14:34 +0100, Florian Weimer wrote:
>> On 02/10/2016 10:48 PM, Florian Weimer wrote:
>>> 2016-02-10  Florian Weimer  <fweimer@redhat.com>
>>>
>>> 	Remove malloc hooks from fork handler.  They are no longer needed
>>> 	because malloc runs right before fork, and no malloc calls from
>>> 	other fork handlers are possible anymore.
>>> 	* malloc/malloc.c (malloc_atfork, free_atfork): Remove
>>> 	declarations.
>>> 	* malloc/arena.c (save_malloc_hook, save_free_hook, save_arena)
>>> 	(ATFORK_ARENA_PTR, malloc_atfork, free_atfork)
>>> 	(atfork_recursive_cntr): Remove.
>>> 	(__malloc_fork_lock_parent): Do not override malloc hooks and
>>> 	thread_arena.
>>> 	(__malloc_fork_unlock_parent): Do not restore malloc hooks and
>>> 	thread_arena.
>>> 	(__malloc_fork_unlock_child): Do not restore malloc hooks.  Use
>>> 	thread_arena i
>>
>> Ping?
>
> You answered the only question that I had, and it looked good to me
> otherwise.

Thanks, committed.

Florian

^ permalink raw reply	[flat|nested] 6+ messages in thread

end of thread, other threads:[~2016-04-14  8:38 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2016-02-10 21:48 [PATCH] malloc: Remove malloc hooks from fork handler Florian Weimer
2016-02-16 10:24 ` Torvald Riegel
2016-02-19 16:32   ` Florian Weimer
2016-03-10 13:34 ` Florian Weimer
2016-04-12 18:19   ` Torvald Riegel
2016-04-14  8:38     ` Florian Weimer

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).