introduce FT2_ALLOC_{TOTAL,CUR}_MAX_SITE environment to restrict memory allocation locally

This commit is contained in:
suzuki toshiya 2011-01-05 17:58:56 +09:00
parent 6b3bef2b20
commit c6e0cdacfa
6 changed files with 153 additions and 2 deletions

View File

@ -24,6 +24,7 @@ FT_TRACE_DEF( any )
/* base components */
FT_TRACE_DEF( calc ) /* calculations (ftcalc.c) */
FT_TRACE_DEF( memory ) /* memory manager (ftobjs.c) */
FT_TRACE_DEF( dbgmem ) /* memory debugger (ftdbgmem.c) */
FT_TRACE_DEF( stream ) /* stream manager (ftstream.c) */
FT_TRACE_DEF( io ) /* i/o interface (ftsystem.c) */
FT_TRACE_DEF( list ) /* list management (ftlist.c) */

View File

@ -16,6 +16,8 @@
/***************************************************************************/
#include <strings.h>
#include <libgen.h>
#include <ft2build.h>
#include FT_CONFIG_CONFIG_H
#include FT_INTERNAL_DEBUG_H
@ -25,6 +27,10 @@
#include FT_TYPES_H
#undef FT_COMPONENT
#define FT_COMPONENT trace_dbgmem
#ifdef FT_DEBUG_MEMORY
#define KEEPALIVE /* `Keep alive' means that freed blocks aren't released
@ -505,6 +511,47 @@
}
static int
ft_mem_check_site_alloc_environment( FT_MemSource source,
const char* env_var_name )
{
char *source_basename = basename( (char *)source->file_name );
char *c, *c0;
/* environment is unset */
c = c0 = getenv( env_var_name );
if ( !c )
return -1;
/* basename not found */
if ( NULL == ( c = strstr( c, source_basename ) ) )
return -1;
/* found position was substring */
if ( c != c0 && *(c-1) != ',' && *(c-1) != '/' )
return -1;
/* invalid syntax without line number */
c = c + strlen( source_basename );
if ( ':' != *c )
return -1;
/* line number differs */
if ( atoi( c + 1 ) != source->line_no )
return -1;
/* invalid syntax without max memory space */
if ( NULL == index( c + 1, ':' ) )
return -1;
c = index( c + 1, ':' );
if ( !ft_isdigit( c[1] ) )
return -1;
return atoi( c + 1 );
}
static void
ft_mem_table_set( FT_MemTable table,
FT_Byte* address,
@ -680,13 +727,52 @@
ft_mem_debug_alloc( FT_Memory memory,
FT_Long size )
{
FT_MemTable table = (FT_MemTable)memory->user;
FT_Byte* block;
FT_MemTable table = (FT_MemTable)memory->user;
FT_MemSource source = NULL;
FT_Byte* block;
if ( size <= 0 )
ft_mem_debug_panic( "negative block size allocation (%ld)", size );
{
int mem_limit_site_total = -1; /* negative means unlimited */
int mem_limit_site_cur = -1; /* negative means unlimited */
FT_Bool exceeds_limit_site_total = FALSE;
FT_Bool exceeds_limit_site_cur = FALSE;
source = ft_mem_table_get_source( table );
mem_limit_site_total = ft_mem_check_site_alloc_environment( source, "FT2_ALLOC_TOTAL_MAX_SITE" );
mem_limit_site_cur = ft_mem_check_site_alloc_environment( source, "FT2_ALLOC_CUR_MAX_SITE" );
if ( mem_limit_site_total >= 0 || mem_limit_site_cur >= 0 )
FT_TRACE1(("ft_mem_table_set() invoked by %s:%lu, limit:( "));
if ( mem_limit_site_total >= 0 )
FT_TRACE1(("%ld =< %ld", source->all_size + size, mem_limit_site_total ));
if ( mem_limit_site_total >= 0 && mem_limit_site_cur >= 0 )
FT_TRACE1((" && "));
if ( mem_limit_site_cur >= 0 )
FT_TRACE1(("%ld =< %ld", source->cur_size + size, mem_limit_site_cur ));
if ( mem_limit_site_total >= 0 || mem_limit_site_cur >= 0 )
FT_TRACE1((" )\n"));
if ( mem_limit_site_total >= 0 && mem_limit_site_total < ( source->all_size + size ) )
exceeds_limit_site_total = TRUE;
if ( mem_limit_site_cur >= 0 && mem_limit_site_cur < ( source->cur_size + size ) )
exceeds_limit_site_cur = TRUE;
if ( exceeds_limit_site_total || exceeds_limit_site_cur )
{
FT_TRACE1(("ft_mem_table_set() returns NULL to %s:%lu, allocation request exceeds %s-limit (%lu > %lu)\n",
basename( (char*)source->file_name ), source->line_no,
( exceeds_limit_site_total ? "site-total" : "site-current" ),
( exceeds_limit_site_total ? source->all_size : source->cur_size ) + size,
( exceeds_limit_site_total ? mem_limit_site_total : mem_limit_site_cur )
));
return NULL;
}
}
/* return NULL if the maximum number of allocations was reached */
if ( table->bound_count &&
table->alloc_count >= table->alloc_count_max )

23
src/cache/ftccache.c vendored
View File

@ -478,6 +478,29 @@
}
FT_LOCAL_DEF( FT_Size )
ftc_get_list_length( FTC_Cache cache,
FT_PtrDist hash )
{
FT_Size len = 0;
FTC_Node* bucket;
FTC_Node* pnode;
FT_UFast idx;
idx = hash & cache->mask;
if ( idx < cache->p )
idx = hash & ( cache->mask * 2 + 1 );
bucket = cache->buckets + idx;
pnode = bucket;
for ( ; pnode && *pnode; pnode = &((*pnode)->link) )
len++;
return len;
}
#ifndef FTC_INLINE
FT_LOCAL_DEF( FT_Error )

13
src/cache/ftccache.h vendored
View File

@ -210,6 +210,10 @@ FT_BEGIN_HEADER
FTC_Cache_RemoveFaceID( FTC_Cache cache,
FTC_FaceID face_id );
FT_LOCAL( FT_Size )
ftc_get_list_length( FTC_Cache cache,
FT_PtrDist hash );
#ifdef FTC_INLINE
@ -222,6 +226,11 @@ FT_BEGIN_HEADER
FT_Bool _list_changed = FALSE; \
\
\
FT_TRACE7(("FTC_CACHE_LOOKUP_CMP() lookup object for ")); \
FT_TRACE7(("hash=0x%08x in cache ", _hash )); \
FT_TRACE7(("mask=0x%08x p=0x%08x ", _cache->mask, _cache->p )); \
FT_TRACE7(("list length=%d\n", ftc_get_list_length( _cache, _hash ) )); \
\
error = FTC_Err_Ok; \
node = NULL; \
\
@ -245,6 +254,8 @@ FT_BEGIN_HEADER
\
if ( _list_changed ) \
{ \
FT_TRACE7(("(_bucket,_pnode)=(%p,%p)", _bucket, _pnode)); \
\
/* Update _bucket by possibly modified linked list */ \
_bucket = _pnode = FTC_NODE__TOP_FOR_HASH( _cache, _hash ); \
\
@ -259,6 +270,8 @@ FT_BEGIN_HEADER
else \
_pnode = &((*_pnode)->link); \
} \
\
FT_TRACE7(("-> (%p,%p)\n", _bucket, _pnode)); \
} \
\
/* Reorder the list to move the found node to the `top' */ \

24
src/cache/ftcmanag.c vendored
View File

@ -622,6 +622,24 @@
}
static int
ft_get_length_nodes_list( FTC_Node node0 )
{
FTC_Node node = node0;
int len = 0;
while ( node )
{
len ++;
node = node->link;
if ( node == node0 )
return len;
}
return len;
}
FT_LOCAL_DEF( FT_UInt )
FTC_Manager_FlushN( FTC_Manager manager,
FT_UInt count )
@ -631,9 +649,14 @@
FT_UInt result;
FT_TRACE1(("%s() tries to free %d nodes from list length=%d\n", __FUNCTION__, count, ft_get_length_nodes_list( manager->nodes_list ) ));
/* try to remove `count' nodes from the list */
if ( first == NULL ) /* empty list! */
{
FT_TRACE1(("%s() cannot change empty list\n", __FUNCTION__ ));
return 0;
}
/* go to last node - it's a circular list */
node = FTC_NODE__PREV(first);
@ -654,6 +677,7 @@
node = prev;
}
FT_TRACE1(("%s() freed %d nodes, list length=%d\n", __FUNCTION__, result, ft_get_length_nodes_list( manager->nodes_list ) ));
return result;
}

View File

@ -125,6 +125,7 @@
sbit->buffer = 0;
error = clazz->family_load_glyph( family, gindex, manager, &face );
FT_TRACE1(("ftc_snode_load() got error from family_load_glyph() err=0x%02x%s\n", error, error ? " fallback to BadGlyph" : "" ));
if ( error )
goto BadGlyph;
@ -200,6 +201,7 @@
*asize = 0;
}
FT_TRACE7(("ftc_snode_load() load glyph for gid=%d, err=0x%02x\n", gindex, error));
return error;
}
@ -334,6 +336,7 @@
FT_Bool result;
FT_TRACE1(( "ftc_snode_compare() work for gindex=%d\n", gindex ));
if (list_changed)
*list_changed = FALSE;
result = FT_BOOL( gnode->family == gquery->family &&
@ -400,6 +403,7 @@
}
}
FT_TRACE1(("%s() returns %s\n", __FUNCTION__, result ? "TRUE" : "FALSE"));
return result;
}