2004-12-10  Ulrich Drepper  <drepper@redhat.com>

	* malloc/arena.c (arena_get2): Prevent endless loop if arenas and
	list lock are taken.
This commit is contained in:
Ulrich Drepper 2004-12-10 11:42:45 +00:00
parent 410b107177
commit 8c7d3691c4
2 changed files with 25 additions and 13 deletions

View File

@ -1,3 +1,8 @@
2004-12-10 Ulrich Drepper <drepper@redhat.com>
* malloc/arena.c (arena_get2): Prevent endless loop if arenas and
list lock are taken.
2004-12-08 Thorsten Kukuk <kukuk@suse.de> 2004-12-08 Thorsten Kukuk <kukuk@suse.de>
* nis/nss_nisplus/nisplus-netgrp.c (_nss_nisplus_getnetgrent_r): * nis/nss_nisplus/nisplus-netgrp.c (_nss_nisplus_getnetgrent_r):

View File

@ -782,9 +782,12 @@ arena_get2(a_tsd, size) mstate a_tsd; size_t size;
} }
/* Check the global, circularly linked list for available arenas. */ /* Check the global, circularly linked list for available arenas. */
bool retried = false;
repeat: repeat:
do { do {
if(!mutex_trylock(&a->mutex)) { if(!mutex_trylock(&a->mutex)) {
if (retried)
(void)mutex_unlock(&list_lock);
THREAD_STAT(++(a->stat_lock_loop)); THREAD_STAT(++(a->stat_lock_loop));
tsd_setspecific(arena_key, (Void_t *)a); tsd_setspecific(arena_key, (Void_t *)a);
return a; return a;
@ -796,29 +799,33 @@ arena_get2(a_tsd, size) mstate a_tsd; size_t size;
happen during `atfork', or for example on systems where thread happen during `atfork', or for example on systems where thread
creation makes it temporarily impossible to obtain _any_ creation makes it temporarily impossible to obtain _any_
locks. */ locks. */
if(mutex_trylock(&list_lock)) { if(!retried && mutex_trylock(&list_lock)) {
/* We will block to not run in a busy loop. */
(void)mutex_lock(&list_lock);
/* Since we blocked there might be an arena available now. */
retried = true;
a = a_tsd; a = a_tsd;
goto repeat; goto repeat;
} }
(void)mutex_unlock(&list_lock);
/* Nothing immediately available, so generate a new arena. */ /* Nothing immediately available, so generate a new arena. */
a = _int_new_arena(size); a = _int_new_arena(size);
if(!a) if(a)
return 0; {
tsd_setspecific(arena_key, (Void_t *)a); tsd_setspecific(arena_key, (Void_t *)a);
mutex_init(&a->mutex); mutex_init(&a->mutex);
mutex_lock(&a->mutex); /* remember result */ mutex_lock(&a->mutex); /* remember result */
/* Add the new arena to the global list. */ /* Add the new arena to the global list. */
(void)mutex_lock(&list_lock);
a->next = main_arena.next; a->next = main_arena.next;
atomic_write_barrier (); atomic_write_barrier ();
main_arena.next = a; main_arena.next = a;
(void)mutex_unlock(&list_lock);
THREAD_STAT(++(a->stat_lock_loop)); THREAD_STAT(++(a->stat_lock_loop));
}
(void)mutex_unlock(&list_lock);
return a; return a;
} }