summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorsuzuki toshiya <mpsuzuki@hiroshima-u.ac.jp>2011-01-05 17:58:56 +0900
committersuzuki toshiya <mpsuzuki@hiroshima-u.ac.jp>2011-01-09 23:31:35 +0900
commitc6e0cdacfac27326ae4221a047650939c1ec96cc (patch)
tree5da521ff35d348a736c9288b53700b62e8a11674
parent6b3bef2b207df92775cf5ddd316eda29bd21b477 (diff)
downloadfreetype2-c6e0cdacfac27326ae4221a047650939c1ec96cc.tar.gz
introduce FT2_ALLOC_{TOTAL,CUR}_MAX_SITE environment to restrict memory allocation locally
-rw-r--r--include/freetype/internal/fttrace.h1
-rw-r--r--src/base/ftdbgmem.c90
-rw-r--r--src/cache/ftccache.c23
-rw-r--r--src/cache/ftccache.h13
-rw-r--r--src/cache/ftcmanag.c24
-rw-r--r--src/cache/ftcsbits.c4
6 files changed, 153 insertions, 2 deletions
diff --git a/include/freetype/internal/fttrace.h b/include/freetype/internal/fttrace.h
index e9b383a58..5d2decc82 100644
--- a/include/freetype/internal/fttrace.h
+++ b/include/freetype/internal/fttrace.h
@@ -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) */
diff --git a/src/base/ftdbgmem.c b/src/base/ftdbgmem.c
index 12fed04bb..16620afa2 100644
--- a/src/base/ftdbgmem.c
+++ b/src/base/ftdbgmem.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 )
diff --git a/src/cache/ftccache.c b/src/cache/ftccache.c
index ad1c5c307..a72af5809 100644
--- a/src/cache/ftccache.c
+++ b/src/cache/ftccache.c
@@ -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 )
diff --git a/src/cache/ftccache.h b/src/cache/ftccache.h
index d696621e7..323892a02 100644
--- a/src/cache/ftccache.h
+++ b/src/cache/ftccache.h
@@ -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' */ \
diff --git a/src/cache/ftcmanag.c b/src/cache/ftcmanag.c
index 548ebe951..827dd5e4e 100644
--- a/src/cache/ftcmanag.c
+++ b/src/cache/ftcmanag.c
@@ -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;
}
diff --git a/src/cache/ftcsbits.c b/src/cache/ftcsbits.c
index d4db99416..097c8d84c 100644
--- a/src/cache/ftcsbits.c
+++ b/src/cache/ftcsbits.c
@@ -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;
}