forked from minhngoc25a/freetype2
introduce FT2_ALLOC_{TOTAL,CUR}_MAX_SITE environment to restrict memory allocation locally
This commit is contained in:
parent
6b3bef2b20
commit
c6e0cdacfa
|
@ -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) */
|
||||
|
|
|
@ -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 )
|
||||
|
|
|
@ -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 )
|
||||
|
|
|
@ -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' */ \
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue