зеркало из https://github.com/mozilla/gecko-dev.git
Backout c661f2c5cd87 and bf22fcece06e (from bug 1252639) because NSPR changes aren't supposed to land on mozilla-inbound.
--HG-- extra : rebase_source : 360a3cc50807b991a421e7d163d7d5442eef59e7
This commit is contained in:
Родитель
b954395165
Коммит
1d9d77e07a
|
@ -17,6 +17,8 @@
|
|||
#include "prlock.h"
|
||||
#include "prinit.h"
|
||||
|
||||
static PLArena *arena_freelist;
|
||||
|
||||
#ifdef PL_ARENAMETER
|
||||
static PLArenaStats *arena_stats_list;
|
||||
|
||||
|
@ -27,6 +29,49 @@ static PLArenaStats *arena_stats_list;
|
|||
|
||||
#define PL_ARENA_DEFAULT_ALIGN sizeof(double)
|
||||
|
||||
static PRLock *arenaLock;
|
||||
static PRCallOnceType once;
|
||||
static const PRCallOnceType pristineCallOnce;
|
||||
|
||||
/*
|
||||
** InitializeArenas() -- Initialize arena operations.
|
||||
**
|
||||
** InitializeArenas() is called exactly once and only once from
|
||||
** LockArena(). This function creates the arena protection
|
||||
** lock: arenaLock.
|
||||
**
|
||||
** Note: If the arenaLock cannot be created, InitializeArenas()
|
||||
** fails quietly, returning only PR_FAILURE. This percolates up
|
||||
** to the application using the Arena API. He gets no arena
|
||||
** from PL_ArenaAllocate(). It's up to him to fail gracefully
|
||||
** or recover.
|
||||
**
|
||||
*/
|
||||
static PRStatus InitializeArenas( void )
|
||||
{
|
||||
PR_ASSERT( arenaLock == NULL );
|
||||
arenaLock = PR_NewLock();
|
||||
if ( arenaLock == NULL )
|
||||
return PR_FAILURE;
|
||||
else
|
||||
return PR_SUCCESS;
|
||||
} /* end ArenaInitialize() */
|
||||
|
||||
static PRStatus LockArena( void )
|
||||
{
|
||||
PRStatus rc = PR_CallOnce( &once, InitializeArenas );
|
||||
|
||||
if ( PR_FAILURE != rc )
|
||||
PR_Lock( arenaLock );
|
||||
return(rc);
|
||||
} /* end LockArena() */
|
||||
|
||||
static void UnlockArena( void )
|
||||
{
|
||||
PR_Unlock( arenaLock );
|
||||
return;
|
||||
} /* end UnlockArena() */
|
||||
|
||||
PR_IMPLEMENT(void) PL_InitArenaPool(
|
||||
PLArenaPool *pool, const char *name, PRUint32 size, PRUint32 align)
|
||||
{
|
||||
|
@ -79,7 +124,14 @@ PR_IMPLEMENT(void) PL_InitArenaPool(
|
|||
** pool.
|
||||
**
|
||||
** First, try to satisfy the request from arenas starting at
|
||||
** pool->current. Then try to allocate a new arena from the heap.
|
||||
** pool->current.
|
||||
**
|
||||
** If there is not enough space in the arena pool->current, try
|
||||
** to claim an arena, on a first fit basis, from the global
|
||||
** freelist (arena_freelist).
|
||||
**
|
||||
** If no arena in arena_freelist is suitable, then try to
|
||||
** allocate a new arena from the heap.
|
||||
**
|
||||
** Returns: pointer to allocated space or NULL
|
||||
**
|
||||
|
@ -117,6 +169,37 @@ PR_IMPLEMENT(void *) PL_ArenaAllocate(PLArenaPool *pool, PRUint32 nb)
|
|||
} while( NULL != (a = a->next) );
|
||||
}
|
||||
|
||||
/* attempt to allocate from arena_freelist */
|
||||
{
|
||||
PLArena *p; /* previous pointer, for unlinking from freelist */
|
||||
|
||||
/* lock the arena_freelist. Make access to the freelist MT-Safe */
|
||||
if ( PR_FAILURE == LockArena())
|
||||
return(0);
|
||||
|
||||
for ( a = arena_freelist, p = NULL; a != NULL ; p = a, a = a->next ) {
|
||||
if ( nb <= a->limit - a->base ) {
|
||||
if ( p == NULL )
|
||||
arena_freelist = a->next;
|
||||
else
|
||||
p->next = a->next;
|
||||
UnlockArena();
|
||||
a->avail = a->base;
|
||||
rp = (char *)a->avail;
|
||||
a->avail += nb;
|
||||
/* the newly allocated arena is linked after pool->current
|
||||
* and becomes pool->current */
|
||||
a->next = pool->current->next;
|
||||
pool->current->next = a;
|
||||
pool->current = a;
|
||||
if ( NULL == pool->first.next )
|
||||
pool->first.next = a;
|
||||
return(rp);
|
||||
}
|
||||
}
|
||||
UnlockArena();
|
||||
}
|
||||
|
||||
/* attempt to allocate from the heap */
|
||||
{
|
||||
PRUint32 sz = PR_MAX(pool->arenasize, nb);
|
||||
|
@ -163,11 +246,10 @@ PR_IMPLEMENT(void *) PL_ArenaGrow(
|
|||
return newp;
|
||||
}
|
||||
|
||||
PR_IMPLEMENT(void) PL_ClearArenaPool(PLArenaPool *pool, PRInt32 pattern)
|
||||
static void ClearArenaList(PLArena *a, PRInt32 pattern)
|
||||
{
|
||||
PLArena *a;
|
||||
|
||||
for (a = pool->first.next; a; a = a->next) {
|
||||
for (; a; a = a->next) {
|
||||
PR_ASSERT(a->base <= a->avail && a->avail <= a->limit);
|
||||
a->avail = a->base;
|
||||
PL_CLEAR_UNUSED_PATTERN(a, pattern);
|
||||
|
@ -175,25 +257,48 @@ PR_IMPLEMENT(void) PL_ClearArenaPool(PLArenaPool *pool, PRInt32 pattern)
|
|||
}
|
||||
}
|
||||
|
||||
PR_IMPLEMENT(void) PL_ClearArenaPool(PLArenaPool *pool, PRInt32 pattern)
|
||||
{
|
||||
ClearArenaList(pool->first.next, pattern);
|
||||
}
|
||||
|
||||
/*
|
||||
* Free tail arenas linked after head, which may not be the true list head.
|
||||
* Reset pool->current to point to head in case it pointed at a tail arena.
|
||||
*/
|
||||
static void FreeArenaList(PLArenaPool *pool, PLArena *head)
|
||||
static void FreeArenaList(PLArenaPool *pool, PLArena *head, PRBool reallyFree)
|
||||
{
|
||||
PLArena *a = head->next;
|
||||
PLArena **ap, *a;
|
||||
|
||||
ap = &head->next;
|
||||
a = *ap;
|
||||
if (!a)
|
||||
return;
|
||||
|
||||
head->next = NULL;
|
||||
#ifdef DEBUG
|
||||
ClearArenaList(a, PL_FREE_PATTERN);
|
||||
#endif
|
||||
|
||||
do {
|
||||
PLArena *tmp = a;
|
||||
a = a->next;
|
||||
PL_CLEAR_ARENA(tmp);
|
||||
PL_COUNT_ARENA(pool,--);
|
||||
PR_DELETE(tmp);
|
||||
} while (a);
|
||||
if (reallyFree) {
|
||||
do {
|
||||
*ap = a->next;
|
||||
PL_CLEAR_ARENA(a);
|
||||
PL_COUNT_ARENA(pool,--);
|
||||
PR_DELETE(a);
|
||||
} while ((a = *ap) != 0);
|
||||
} else {
|
||||
/* Insert the whole arena chain at the front of the freelist. */
|
||||
do {
|
||||
PL_MAKE_MEM_NOACCESS((void*)(*ap)->base,
|
||||
(*ap)->limit - (*ap)->base);
|
||||
ap = &(*ap)->next;
|
||||
} while (*ap);
|
||||
LockArena();
|
||||
*ap = arena_freelist;
|
||||
arena_freelist = a;
|
||||
head->next = 0;
|
||||
UnlockArena();
|
||||
}
|
||||
|
||||
pool->current = head;
|
||||
}
|
||||
|
@ -205,7 +310,7 @@ PR_IMPLEMENT(void) PL_ArenaRelease(PLArenaPool *pool, char *mark)
|
|||
for (a = &pool->first; a; a = a->next) {
|
||||
if (PR_UPTRDIFF(mark, a->base) <= PR_UPTRDIFF(a->avail, a->base)) {
|
||||
a->avail = (PRUword)PL_ARENA_ALIGN(pool, mark);
|
||||
FreeArenaList(pool, a);
|
||||
FreeArenaList(pool, a, PR_FALSE);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
@ -213,13 +318,13 @@ PR_IMPLEMENT(void) PL_ArenaRelease(PLArenaPool *pool, char *mark)
|
|||
|
||||
PR_IMPLEMENT(void) PL_FreeArenaPool(PLArenaPool *pool)
|
||||
{
|
||||
FreeArenaList(pool, &pool->first);
|
||||
FreeArenaList(pool, &pool->first, PR_FALSE);
|
||||
COUNT(pool, ndeallocs);
|
||||
}
|
||||
|
||||
PR_IMPLEMENT(void) PL_FinishArenaPool(PLArenaPool *pool)
|
||||
{
|
||||
FreeArenaList(pool, &pool->first);
|
||||
FreeArenaList(pool, &pool->first, PR_TRUE);
|
||||
#ifdef PL_ARENAMETER
|
||||
{
|
||||
PLArenaStats *stats, **statsp;
|
||||
|
@ -243,6 +348,19 @@ PR_IMPLEMENT(void) PL_CompactArenaPool(PLArenaPool *ap)
|
|||
|
||||
PR_IMPLEMENT(void) PL_ArenaFinish(void)
|
||||
{
|
||||
PLArena *a, *next;
|
||||
|
||||
for (a = arena_freelist; a; a = next) {
|
||||
next = a->next;
|
||||
PR_DELETE(a);
|
||||
}
|
||||
arena_freelist = NULL;
|
||||
|
||||
if (arenaLock) {
|
||||
PR_DestroyLock(arenaLock);
|
||||
arenaLock = NULL;
|
||||
}
|
||||
once = pristineCallOnce;
|
||||
}
|
||||
|
||||
PR_IMPLEMENT(size_t) PL_SizeOfArenaPoolExcludingPool(
|
||||
|
|
|
@ -13,6 +13,7 @@
|
|||
* Also supports LIFO allocation (PL_ARENA_MARK/PL_ARENA_RELEASE).
|
||||
*/
|
||||
#include "prtypes.h"
|
||||
#include "plarenas.h"
|
||||
|
||||
PR_BEGIN_EXTERN_C
|
||||
|
||||
|
@ -46,8 +47,6 @@ struct PLArenaStats {
|
|||
};
|
||||
#endif
|
||||
|
||||
typedef struct PLArenaPool PLArenaPool;
|
||||
|
||||
struct PLArenaPool {
|
||||
PLArena first; /* first arena in pool list */
|
||||
PLArena *current; /* arena from which to allocate space */
|
||||
|
@ -226,74 +225,6 @@ PR_IMPORT(void) __asan_unpoison_memory_region(void const volatile *addr, size_t
|
|||
(a) = 0; \
|
||||
PR_END_MACRO
|
||||
|
||||
/*
|
||||
** Initialize an arena pool with the given name for debugging and metering,
|
||||
** with a minimum gross size per arena of size bytes. The net size per arena
|
||||
** is smaller than the gross size by a header of four pointers plus any
|
||||
** necessary padding for alignment.
|
||||
**
|
||||
** Note: choose a gross size that's a power of two to avoid the heap allocator
|
||||
** rounding the size up.
|
||||
**/
|
||||
PR_EXTERN(void) PL_InitArenaPool(
|
||||
PLArenaPool *pool, const char *name, PRUint32 size, PRUint32 align);
|
||||
|
||||
/*
|
||||
** Finish using arenas, freeing all memory associated with them.
|
||||
** NOTE: this function is now a no-op. If you want to free a single
|
||||
** PLArenaPoolUse use PL_FreeArenaPool() or PL_FinishArenaPool().
|
||||
**/
|
||||
PR_EXTERN(void) PL_ArenaFinish(void);
|
||||
|
||||
/*
|
||||
** Free the arenas in pool. The user may continue to allocate from pool
|
||||
** after calling this function. There is no need to call PL_InitArenaPool()
|
||||
** again unless PL_FinishArenaPool(pool) has been called.
|
||||
**/
|
||||
PR_EXTERN(void) PL_FreeArenaPool(PLArenaPool *pool);
|
||||
|
||||
/*
|
||||
** Free the arenas in pool and finish using it altogether.
|
||||
**/
|
||||
PR_EXTERN(void) PL_FinishArenaPool(PLArenaPool *pool);
|
||||
|
||||
/*
|
||||
** Compact all of the arenas in a pool so that no space is wasted.
|
||||
** NOT IMPLEMENTED. Do not use.
|
||||
**/
|
||||
PR_EXTERN(void) PL_CompactArenaPool(PLArenaPool *pool);
|
||||
|
||||
/*
|
||||
** Friend functions used by the PL_ARENA_*() macros.
|
||||
**
|
||||
** WARNING: do not call these functions directly. Always use the
|
||||
** PL_ARENA_*() macros.
|
||||
**/
|
||||
PR_EXTERN(void *) PL_ArenaAllocate(PLArenaPool *pool, PRUint32 nb);
|
||||
|
||||
PR_EXTERN(void *) PL_ArenaGrow(
|
||||
PLArenaPool *pool, void *p, PRUint32 size, PRUint32 incr);
|
||||
|
||||
PR_EXTERN(void) PL_ArenaRelease(PLArenaPool *pool, char *mark);
|
||||
|
||||
/*
|
||||
** memset contents of all arenas in pool to pattern
|
||||
*/
|
||||
PR_EXTERN(void) PL_ClearArenaPool(PLArenaPool *pool, PRInt32 pattern);
|
||||
|
||||
/*
|
||||
** A function like malloc_size() or malloc_usable_size() that measures the
|
||||
** size of a heap block.
|
||||
*/
|
||||
typedef size_t (*PLMallocSizeFn)(const void *ptr);
|
||||
|
||||
/*
|
||||
** Measure all memory used by a PLArenaPool, excluding the PLArenaPool
|
||||
** structure.
|
||||
*/
|
||||
PR_EXTERN(size_t) PL_SizeOfArenaPoolExcludingPool(
|
||||
const PLArenaPool *pool, PLMallocSizeFn mallocSizeOf);
|
||||
|
||||
#ifdef PL_ARENAMETER
|
||||
|
||||
#include <stdio.h>
|
||||
|
|
|
@ -3,10 +3,79 @@
|
|||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#ifndef PLARENAS_H
|
||||
#define PLARENAS_H
|
||||
|
||||
PR_BEGIN_EXTERN_C
|
||||
|
||||
typedef struct PLArenaPool PLArenaPool;
|
||||
|
||||
/*
|
||||
** PLArena-related declarations used to be split between plarenas.h and
|
||||
** plarena.h. That split wasn't useful, so now all the declarations are in
|
||||
** plarena.h. However, this file still exists so that any old code that
|
||||
** includes it will still work.
|
||||
** Initialize an arena pool with the given name for debugging and metering,
|
||||
** with a minimum gross size per arena of size bytes. The net size per arena
|
||||
** is smaller than the gross size by a header of four pointers plus any
|
||||
** necessary padding for alignment.
|
||||
**
|
||||
** Note: choose a gross size that's a power of two to avoid the heap allocator
|
||||
** rounding the size up.
|
||||
**/
|
||||
#include "plarena.h"
|
||||
PR_EXTERN(void) PL_InitArenaPool(
|
||||
PLArenaPool *pool, const char *name, PRUint32 size, PRUint32 align);
|
||||
|
||||
/*
|
||||
** Finish using arenas, freeing all memory associated with them.
|
||||
**/
|
||||
PR_EXTERN(void) PL_ArenaFinish(void);
|
||||
|
||||
/*
|
||||
** Free the arenas in pool. The user may continue to allocate from pool
|
||||
** after calling this function. There is no need to call PL_InitArenaPool()
|
||||
** again unless PL_FinishArenaPool(pool) has been called.
|
||||
**/
|
||||
PR_EXTERN(void) PL_FreeArenaPool(PLArenaPool *pool);
|
||||
|
||||
/*
|
||||
** Free the arenas in pool and finish using it altogether.
|
||||
**/
|
||||
PR_EXTERN(void) PL_FinishArenaPool(PLArenaPool *pool);
|
||||
|
||||
/*
|
||||
** Compact all of the arenas in a pool so that no space is wasted.
|
||||
** NOT IMPLEMENTED. Do not use.
|
||||
**/
|
||||
PR_EXTERN(void) PL_CompactArenaPool(PLArenaPool *pool);
|
||||
|
||||
/*
|
||||
** Friend functions used by the PL_ARENA_*() macros.
|
||||
**
|
||||
** WARNING: do not call these functions directly. Always use the
|
||||
** PL_ARENA_*() macros.
|
||||
**/
|
||||
PR_EXTERN(void *) PL_ArenaAllocate(PLArenaPool *pool, PRUint32 nb);
|
||||
|
||||
PR_EXTERN(void *) PL_ArenaGrow(
|
||||
PLArenaPool *pool, void *p, PRUint32 size, PRUint32 incr);
|
||||
|
||||
PR_EXTERN(void) PL_ArenaRelease(PLArenaPool *pool, char *mark);
|
||||
|
||||
/*
|
||||
** memset contents of all arenas in pool to pattern
|
||||
*/
|
||||
PR_EXTERN(void) PL_ClearArenaPool(PLArenaPool *pool, PRInt32 pattern);
|
||||
|
||||
/*
|
||||
** A function like malloc_size() or malloc_usable_size() that measures the
|
||||
** size of a heap block.
|
||||
*/
|
||||
typedef size_t (*PLMallocSizeFn)(const void *ptr);
|
||||
|
||||
/*
|
||||
** Measure all memory used by a PLArenaPool, excluding the PLArenaPool
|
||||
** structure.
|
||||
*/
|
||||
PR_EXTERN(size_t) PL_SizeOfArenaPoolExcludingPool(
|
||||
const PLArenaPool *pool, PLMallocSizeFn mallocSizeOf);
|
||||
|
||||
PR_END_EXTERN_C
|
||||
|
||||
#endif /* PLARENAS_H */
|
||||
|
|
Загрузка…
Ссылка в новой задаче