Pārlūkot izejas kodu

Merge pull request #164 from kamailio/tmp/tlsf_debug

mem: TLSF memory summary and sums implementation
Camille Oudot 10 gadi atpakaļ
vecāks
revīzija
fbbadfde17
7 mainītis faili ar 248 papildinājumiem un 77 dzēšanām
  1. 3 0
      Makefile.defs
  2. 18 3
      mem/mem.h
  3. 1 1
      mem/q_malloc.c
  4. 1 1
      mem/q_malloc.h
  5. 10 2
      mem/shm_mem.h
  6. 204 69
      mem/tlsf.c
  7. 11 1
      mem/tlsf.h

+ 3 - 0
Makefile.defs

@@ -668,6 +668,9 @@ endif
 else ifeq ($(MEMMNG), 2)
 #	use tlsf malloc
 	C_DEFS+= -DTLSF_MALLOC=1
+ifeq 	($(MEMDBG), 1)
+		C_DEFS+= -DDBG_TLSF_MALLOC
+endif
 else
 #	use f_malloc
 	C_DEFS+= -DF_MALLOC

+ 18 - 3
mem/mem.h

@@ -49,6 +49,14 @@
 	#elif defined(DBG_QM_MALLOC)
 		#define DBG_F_MALLOC
 	#endif
+#elif defined TLSF_MALLOC
+	#ifdef DBG_TLSF_MALLOC
+		#ifndef DBG_QM_MALLOC
+			#define DBG_QM_MALLOC
+		#endif
+	#elif defined(DBG_QM_MALLOC)
+		#define DBG_TLSF_MALLOC
+	#endif
 #endif
 
 #ifdef PKG_MALLOC
@@ -78,6 +86,13 @@
 				_SRC_FUNCTION_, _SRC_LINE_)
 #			define pkg_realloc(p, s) fm_realloc(mem_block, (p), (s), \
 					_SRC_LOC_, _SRC_FUNCTION_, _SRC_LINE_)
+#		elif defined TLSF_MALLOC
+#			define pkg_malloc(s) tlsf_malloc(mem_block, (s), _SRC_LOC_, \
+				_SRC_FUNCTION_, _SRC_LINE_)
+#			define pkg_free(p)   tlsf_free(mem_block, (p), _SRC_LOC_,  \
+				_SRC_FUNCTION_, _SRC_LINE_)
+#			define pkg_realloc(p, s) tlsf_realloc(mem_block, (p), (s), \
+					_SRC_LOC_, _SRC_FUNCTION_, _SRC_LINE_)
 #		else
 #			define pkg_malloc(s) qm_malloc(mem_block, (s),_SRC_LOC_, \
 				_SRC_FUNCTION_, _SRC_LINE_)
@@ -116,10 +131,10 @@
 #		define pkg_available()  0
 #		define pkg_sums()  0
 #	elif defined TLSF_MALLOC
-#		define pkg_status()  ((void) 0)
+#		define pkg_status()  tlsf_status(mem_block)
 #		define pkg_info(mi)  tlsf_meminfo(mem_block, (mi))
-#		define pkg_available()  ((void) 0)
-#		define pkg_sums()  ((void) 0)
+#		define pkg_available()  tlsf_available(mem_block)
+#		define pkg_sums()  tlsf_sums(mem_block)
 #	else
 #		define pkg_status()    qm_status(mem_block)
 #		define pkg_info(mi)    qm_info(mem_block, mi)

+ 1 - 1
mem/q_malloc.c

@@ -23,7 +23,7 @@
  */
 
 
-#if !defined(q_malloc) && !(defined F_MALLOC)
+#if !defined(q_malloc) && !(defined F_MALLOC) && !defined(TLSF_MALLOC)
 #define q_malloc
 
 #include <stdlib.h>

+ 1 - 1
mem/q_malloc.h

@@ -22,7 +22,7 @@
  * \ingroup mem
  */
 
-#if !defined(q_malloc_h) && !defined(F_MALLOC)
+#if !defined(q_malloc_h) && !defined(F_MALLOC) && !defined(TLSF_MALLOC)
 #define q_malloc_h
 
 #include "meminfo.h"

+ 10 - 2
mem/shm_mem.h

@@ -57,6 +57,14 @@
 	#elif defined(DBG_QM_MALLOC)
 		#define DBG_F_MALLOC
 	#endif
+#elif defined TLSF_MALLOC
+	#ifdef DBG_TLSF_MALLOC
+		#ifndef DBG_QM_MALLOC
+			#define DBG_QM_MALLOC
+		#endif
+	#elif defined(DBG_QM_MALLOC)
+		#define DBG_TLSF_MALLOC
+	#endif
 #endif
 
 
@@ -149,9 +157,9 @@
 #	define MY_MALLOC tlsf_malloc
 #	define MY_FREE tlsf_free
 #	define MY_REALLOC tlsf_realloc
-#	define MY_STATUS(...) ((void) 0)
+#	define MY_STATUS tlsf_status
 #	define MY_MEMINFO	tlsf_meminfo
-#	define MY_SUMS(...) ((void) 0)
+#	define MY_SUMS tlsf_sums
 #	define shm_malloc_init(mem, bytes, type) tlsf_create_with_pool((void*) mem, bytes)
 #	define shm_malloc_destroy(b) do{}while(0)
 #	define shm_available() tlsf_available(shm_block)

+ 204 - 69
mem/tlsf.c

@@ -7,6 +7,9 @@
 
 #include "tlsf.h"
 #include "tlsfbits.h"
+#include "src_loc.h"
+#include "../dprint.h"
+#include "../cfg/cfg.h"
 
 /*
 ** Constants.
@@ -96,7 +99,13 @@ tlsf_static_assert(ALIGN_SIZE == SMALL_BLOCK_SIZE / SL_INDEX_COUNT);
 /*
 ** Data structures and associated constants.
 */
-
+#ifdef DBG_TLSF_MALLOC
+typedef struct {
+	const char* file;
+	const char* func;
+	unsigned long line;
+} alloc_info_t;
+#endif
 /*
 ** Block header structure.
 **
@@ -112,6 +121,10 @@ typedef struct block_header_t
 	/* Points to the previous physical block. */
 	struct block_header_t* prev_phys_block;
 
+#ifdef DBG_TLSF_MALLOC
+	alloc_info_t alloc_info;
+#endif
+
 	/* The size of this block, excluding the block header. */
 	size_t size;
 
@@ -133,7 +146,11 @@ static const size_t block_header_prev_free_bit = 1 << 1;
 ** The size of the block header exposed to used blocks is the size field.
 ** The prev_phys_block field is stored *inside* the previous free block.
 */
+#ifdef DBG_TLSF_MALLOC
+static const size_t block_header_overhead = sizeof(size_t) + sizeof(alloc_info_t);
+#else
 static const size_t block_header_overhead = sizeof(size_t);
+#endif
 
 /* User data starts directly after the size field in a used block. */
 static const size_t block_start_offset =
@@ -144,7 +161,7 @@ static const size_t block_start_offset =
 ** the prev_phys_block field, and no larger than the number of addressable
 ** bits for FL_INDEX.
 */
-static const size_t block_size_min = 
+static const size_t block_size_min =
 	sizeof(block_header_t) - sizeof(block_header_t*);
 static const size_t block_size_max = tlsf_cast(size_t, 1) << FL_INDEX_MAX;
 
@@ -255,7 +272,7 @@ static block_header_t* block_prev(const block_header_t* block)
 static block_header_t* block_next(const block_header_t* block)
 {
 	block_header_t* next = offset_to_block(block_to_ptr(block),
-		block_size(block) - block_header_overhead);
+		block_size(block) - sizeof(block_header_t*));
 	tlsf_assert(!block_is_last(block));
 	return next;
 }
@@ -467,7 +484,7 @@ static block_header_t* block_split(block_header_t* block, size_t size)
 {
 	/* Calculate the amount of space left in the remaining block. */
 	block_header_t* remaining =
-		offset_to_block(block_to_ptr(block), size - block_header_overhead);
+		offset_to_block(block_to_ptr(block), size - sizeof(block_header_t*));
 
 	const size_t remain_size = block_size(block) - (size + block_header_overhead);
 
@@ -476,7 +493,7 @@ static block_header_t* block_split(block_header_t* block, size_t size)
 
 	tlsf_assert(block_size(block) == remain_size + size + block_header_overhead);
 	block_set_size(remaining, remain_size);
-	tlsf_assert(block_size(remaining) >= block_size_min && "block split with invalid size");
+	tlsf_assert(block_size(remaining) >= 0 && "block split with invalid size");
 
 	block_set_size(block, size);
 	block_mark_as_free(remaining);
@@ -534,6 +551,11 @@ static void block_trim_free(control_t* control, block_header_t* block, size_t si
 		block_header_t* remaining_block = block_split(block, size);
 		block_link_next(block);
 		block_set_prev_free(remaining_block);
+#ifdef DBG_TLSF_MALLOC
+		remaining_block->alloc_info.file = _SRC_LOC_;
+		remaining_block->alloc_info.func = _SRC_FUNCTION_;
+		remaining_block->alloc_info.line = _SRC_LINE_;
+#endif
 		block_insert(control, remaining_block);
 	}
 }
@@ -549,6 +571,11 @@ static void block_trim_used(control_t* control, block_header_t* block, size_t si
 		block_set_prev_used(remaining_block);
 
 		remaining_block = block_merge_next(control, remaining_block);
+#ifdef DBG_TLSF_MALLOC
+		remaining_block->alloc_info.file = _SRC_LOC_;
+		remaining_block->alloc_info.func = _SRC_FUNCTION_;
+		remaining_block->alloc_info.line = _SRC_LINE_;
+#endif
 		block_insert(control, remaining_block);
 	}
 }
@@ -588,8 +615,12 @@ static block_header_t* block_locate_free(control_t* control, size_t size)
 
 	return block;
 }
-
+#ifdef DBG_TLSF_MALLOC
+static void* block_prepare_used(control_t* control, block_header_t* block, size_t size,
+		const char *file, const char *function, unsigned long line)
+#else
 static void* block_prepare_used(control_t* control, block_header_t* block, size_t size)
+#endif
 {
 	void* p = 0;
 	if (block)
@@ -600,6 +631,11 @@ static void* block_prepare_used(control_t* control, block_header_t* block, size_
 #ifdef TLSF_STATS
 		TLSF_INCREASE_REAL_USED(control, block->size + (p - (void *)block));
 		control->allocated += block->size;
+#endif
+#ifdef DBG_TLSF_MALLOC
+		block->alloc_info.file = file;
+		block->alloc_info.func = function;
+		block->alloc_info.line = line;
 #endif
 	}
 	return p;
@@ -715,8 +751,7 @@ static void default_walker(void* ptr, size_t size, int used, void* user)
 void tlsf_walk_pool(pool_t pool, tlsf_walker walker, void* user)
 {
 	tlsf_walker pool_walker = walker ? walker : default_walker;
-	block_header_t* block =
-		offset_to_block(pool, -(int)block_header_overhead);
+	block_header_t* block = pool + tlsf_size() - sizeof(block_header_t*);
 
 	while (block && !block_is_last(block))
 	{
@@ -806,11 +841,11 @@ pool_t tlsf_add_pool(tlsf_t tlsf, void* mem, size_t bytes)
 	if (pool_bytes < block_size_min || pool_bytes > block_size_max)
 	{
 #if defined (TLSF_64BIT)
-		printf("tlsf_add_pool: Memory size must be between 0x%x and 0x%x00 bytes.\n", 
+		printf("tlsf_add_pool: Memory size must be between 0x%x and 0x%x00 bytes.\n",
 			(unsigned int)(pool_overhead + block_size_min),
 			(unsigned int)((pool_overhead + block_size_max) / 256));
 #else
-		printf("tlsf_add_pool: Memory size must be between %u and %u bytes.\n", 
+		printf("tlsf_add_pool: Memory size must be between %u and %u bytes.\n",
 			(unsigned int)(pool_overhead + block_size_min),
 			(unsigned int)(pool_overhead + block_size_max));
 #endif
@@ -822,13 +857,18 @@ pool_t tlsf_add_pool(tlsf_t tlsf, void* mem, size_t bytes)
 	** so that the prev_phys_block field falls outside of the pool -
 	** it will never be used.
 	*/
-	block = offset_to_block(mem, -(tlsfptr_t)block_header_overhead);
+	block = mem - sizeof (size_t);/*offset_to_block(mem, -(tlsfptr_t)block_header_overhead);*/
 	block_set_size(block, pool_bytes);
 	block_set_free(block);
 	block_set_prev_used(block);
 	block_insert(tlsf_cast(control_t*, tlsf), block);
 #ifdef TLSF_STATS
 	tlsf_cast(control_t*, tlsf)->total_size += block->size;
+#endif
+#ifdef DBG_TLSF_MALLOC
+	block->alloc_info.file = _SRC_LOC_;
+	block->alloc_info.func = _SRC_FUNCTION_;
+	block->alloc_info.line = _SRC_LINE_;
 #endif
 	/* Split the block to create a zero-size sentinel block. */
 	next = block_link_next(block);
@@ -878,7 +918,7 @@ int test_ffs_fls()
 #if defined (TLSF_64BIT)
 	rv += (tlsf_fls_sizet(0x80000000) == 31) ? 0 : 0x100;
 	rv += (tlsf_fls_sizet(0x100000000) == 32) ? 0 : 0x200;
-	rv += (tlsf_fls_sizet(0xffffffffffffffff) == 63) ? 0 : 0x400; 
+	rv += (tlsf_fls_sizet(0xffffffffffffffff) == 63) ? 0 : 0x400;
 #endif
 
 	if (rv)
@@ -935,73 +975,29 @@ pool_t tlsf_get_pool(tlsf_t tlsf)
 	return tlsf_cast(pool_t, (char*)tlsf + tlsf_size());
 }
 
+#ifdef DBG_TLSF_MALLOC
+void* tlsf_malloc(tlsf_t tlsf, size_t size,
+		const char *file, const char *function, unsigned long line)
+#else
 void* tlsf_malloc(tlsf_t tlsf, size_t size)
+#endif
 {
 	control_t* control = tlsf_cast(control_t*, tlsf);
 	const size_t adjust = adjust_request_size(size, ALIGN_SIZE);
 	block_header_t* block = block_locate_free(control, adjust);
+#ifdef DBG_TLSF_MALLOC
+	return block_prepare_used(control, block, adjust, file, function, line);
+#else
 	return block_prepare_used(control, block, adjust);
-}
-
-void* tlsf_memalign(tlsf_t tlsf, size_t align, size_t size)
-{
-	control_t* control = tlsf_cast(control_t*, tlsf);
-	const size_t adjust = adjust_request_size(size, ALIGN_SIZE);
-
-	/*
-	** We must allocate an additional minimum block size bytes so that if
-	** our free block will leave an alignment gap which is smaller, we can
-	** trim a leading free block and release it back to the pool. We must
-	** do this because the previous physical block is in use, therefore
-	** the prev_phys_block field is not valid, and we can't simply adjust
-	** the size of that block.
-	*/
-	const size_t gap_minimum = sizeof(block_header_t);
-	const size_t size_with_gap = adjust_request_size(adjust + align + gap_minimum, align);
-
-	/* If alignment is less than or equals base alignment, we're done. */
-	const size_t aligned_size = (align <= ALIGN_SIZE) ? adjust : size_with_gap;
-
-	block_header_t* block = block_locate_free(control, aligned_size);
-
-	/* This can't be a static assert. */
-	tlsf_assert(sizeof(block_header_t) == block_size_min + block_header_overhead);
-
-	if (block)
-	{
-		void* ptr = block_to_ptr(block);
-		void* aligned = align_ptr(ptr, align);
-		size_t gap = tlsf_cast(size_t,
-			tlsf_cast(tlsfptr_t, aligned) - tlsf_cast(tlsfptr_t, ptr));
-
-		/* If gap size is too small, offset to next aligned boundary. */
-		if (gap && gap < gap_minimum)
-		{
-			const size_t gap_remain = gap_minimum - gap;
-			const size_t offset = tlsf_max(gap_remain, align);
-			const void* next_aligned = tlsf_cast(void*,
-				tlsf_cast(tlsfptr_t, aligned) + offset);
-
-			aligned = align_ptr(next_aligned, align);
-			gap = tlsf_cast(size_t,
-				tlsf_cast(tlsfptr_t, aligned) - tlsf_cast(tlsfptr_t, ptr));
-		}
-
-		if (gap)
-		{
-			tlsf_assert(gap >= gap_minimum && "gap size too small");
-			block = block_trim_free_leading(control, block, gap);
-		}
-	}
-
-#ifdef TLSF_STATS
-	/* TODO */
 #endif
-
-	return block_prepare_used(control, block, adjust);
 }
 
+#ifdef DBG_TLSF_MALLOC
+void tlsf_free(tlsf_t tlsf, void* ptr,
+		const char *file, const char *function, unsigned long line)
+#else
 void tlsf_free(tlsf_t tlsf, void* ptr)
+#endif
 {
 	/* Don't attempt to free a NULL pointer. */
 	if (ptr)
@@ -1012,6 +1008,11 @@ void tlsf_free(tlsf_t tlsf, void* ptr)
 #if defined TLSF_STATS
 		control->allocated -= block->size;
 		control->real_used -= (block->size + (ptr - (void *)block));
+#endif
+#ifdef DBG_TLSF_MALLOC
+		block->alloc_info.file = file;
+		block->alloc_info.func = function;
+		block->alloc_info.line = line;
 #endif
 		block_mark_as_free(block);
 		block = block_merge_prev(control, block);
@@ -1033,7 +1034,12 @@ void tlsf_free(tlsf_t tlsf, void* ptr)
 ** - an extended buffer size will leave the newly-allocated area with
 **   contents undefined
 */
+#ifdef DBG_TLSF_MALLOC
+void* tlsf_realloc(tlsf_t tlsf, void* ptr, size_t size,
+		const char *file, const char *function, unsigned long line)
+#else
 void* tlsf_realloc(tlsf_t tlsf, void* ptr, size_t size)
+#endif
 {
 	control_t* control = tlsf_cast(control_t*, tlsf);
 	void* p = 0;
@@ -1041,12 +1047,20 @@ void* tlsf_realloc(tlsf_t tlsf, void* ptr, size_t size)
 	/* Zero-size requests are treated as free. */
 	if (ptr && size == 0)
 	{
+#ifdef DBG_TLSF_MALLOC
+		tlsf_free(tlsf, ptr, file, function, line);
+#else
 		tlsf_free(tlsf, ptr);
+#endif
 	}
 	/* Requests with NULL pointers are treated as malloc. */
 	else if (!ptr)
 	{
+#ifdef DBG_TLSF_MALLOC
+		p = tlsf_malloc(tlsf, size, file, function, line);
+#else
 		p = tlsf_malloc(tlsf, size);
+#endif
 	}
 	else
 	{
@@ -1065,12 +1079,20 @@ void* tlsf_realloc(tlsf_t tlsf, void* ptr, size_t size)
 		*/
 		if (adjust > cursize && (!block_is_free(next) || adjust > combined))
 		{
+#ifdef DBG_TLSF_MALLOC
+			p = tlsf_malloc(tlsf, size, file, function, line);
+#else
 			p = tlsf_malloc(tlsf, size);
+#endif
 			if (p)
 			{
 				const size_t minsize = tlsf_min(cursize, size);
 				memcpy(p, ptr, minsize);
+#ifdef DBG_TLSF_MALLOC
+				tlsf_free(tlsf, ptr, file, function, line);
+#else
 				tlsf_free(tlsf, ptr);
+#endif
 			}
 		}
 		else
@@ -1118,5 +1140,118 @@ size_t tlsf_available(tlsf_t pool)
 	control_t* control = tlsf_cast(control_t*, pool);
 	return control->total_size - control->real_used;
 }
+
+static void tlsf_status_cb(void* ptr, size_t size, int used, void* user)
+{
+#ifdef DBG_TLSF_MALLOC
+	block_header_t* block = block_from_ptr(ptr);
+#endif
+
+#ifdef DBG_TLSF_MALLOC
+	LOG_(DEFAULT_FACILITY, *(int*)user, "tlsf_status: ", "(%p): used=%s size=%zu was %s from %s: %s(%ld)\n",
+			ptr, used ? "true" : "false", size, used ? "alloc'd" : "free'd", block->alloc_info.file, block->alloc_info.func, block->alloc_info.line);
+#else
+	LOG_(DEFAULT_FACILITY, *(int*)user, "tlsf_status: ", "(%p): used=%s size=%zu\n",
+			ptr, used ? "true" : "false", size);
+#endif
+
+
+}
+
+void tlsf_status(tlsf_t pool)
+{
+	int memlog;
+	control_t* control = tlsf_cast(control_t*, pool);
+
+	memlog=cfg_get(core, core_cfg, memlog);
+	LOG_(DEFAULT_FACILITY, memlog, "tlsf_status: ", "status of pool (%p):\n", pool);
+#ifdef TLSF_STATS
+	LOG_(DEFAULT_FACILITY, memlog, "tlsf_status: ", "heap size= %zu\n",
+			control->total_size);
+	LOG_(DEFAULT_FACILITY, memlog, "tlsf_status: ",
+			"used= %zu, used+overhead=%zu, free=%zu, fragments=%zu\n",
+			control->allocated, control->real_used, control->total_size - control->real_used, control->fragments);
+	LOG_(DEFAULT_FACILITY, memlog, "tlsf_status: ",
+			"max used (+overhead)=%zu, max fragments=%zu\n", control->max_used, control->max_fragments);
+#endif
+	LOG_(DEFAULT_FACILITY, memlog, "tlsf_status: ",
+			"dumping all fragments:\n");
+	tlsf_walk_pool(pool, tlsf_status_cb, (void *) &memlog);
+}
+
+#ifdef DBG_TLSF_MALLOC
+typedef struct _mem_counter{
+	const char *file;
+	const char *func;
+	unsigned long line;
+
+	unsigned long size;
+	int count;
+
+	struct _mem_counter *next;
+} mem_counter;
+
+static mem_counter* get_mem_counter(mem_counter **root, block_header_t* f)
+{
+	mem_counter *x;
+	if (!*root) goto make_new;
+	for(x=*root;x;x=x->next)
+		if (x->file == f->alloc_info.file && x->func == f->alloc_info.func && x->line == f->alloc_info.line)
+			return x;
+make_new:
+	x = malloc(sizeof(mem_counter));
+	x->file = f->alloc_info.file;
+	x->func = f->alloc_info.func;
+	x->line = f->alloc_info.line;
+	x->count = 0;
+	x->size = 0;
+	x->next = *root;
+	*root = x;
+	return x;
+}
+
+
+void tlsf_sums(tlsf_t pool)
+{
+	int memlog;
+	block_header_t* block = pool + tlsf_size() - sizeof(block_header_t*);
+	mem_counter *root = NULL, *x;
+
+	memlog=cfg_get(core, core_cfg, memlog);
+
+	LOG_(DEFAULT_FACILITY, memlog, "tlsf_sums: ",
+			"pool (%p) summarizing all alloc'ed. fragments:\n", pool);
+
+
+	while (block && !block_is_last(block))
+	{
+		if(!block_is_free(block)) {
+			x = get_mem_counter(&root, block);
+			x->count++;
+			x->size+=block_size(block);
+		}
+
+		block = block_next(block);
+	}
+
+	x = root;
+	while(x){
+		LOG_(DEFAULT_FACILITY, memlog, "tlsf_sums: ",
+				" count=%6d size=%10lu bytes from %s: %s(%ld)\n",
+			x->count,x->size,
+			x->file, x->func, x->line
+			);
+		root = x->next;
+		free(x);
+		x = root;
+	}
+	LOG_(DEFAULT_FACILITY, memlog, "tlsf_sums: ",
+			"-----------------------------\n");
+}
+#else
+void tlsf_sums(tlsf_t pool)
+{}
+#endif /* defined DBG_TLSF_MALLOC */
+
 #endif
 

+ 11 - 1
mem/tlsf.h

@@ -40,10 +40,18 @@ pool_t tlsf_add_pool(tlsf_t tlsf, void* mem, size_t bytes);
 void tlsf_remove_pool(tlsf_t tlsf, pool_t pool);
 
 /* malloc/memalign/realloc/free replacements. */
+#ifdef DBG_TLSF_MALLOC
+void* tlsf_malloc(tlsf_t tlsf, size_t size,
+		const char *file, const char *function, unsigned long line);
+void* tlsf_realloc(tlsf_t tlsf, void* ptr, size_t size,
+		const char *file, const char *function, unsigned long line);
+void tlsf_free(tlsf_t tlsf, void* ptr,
+		const char *file, const char *function, unsigned long line);
+#else
 void* tlsf_malloc(tlsf_t tlsf, size_t bytes);
-void* tlsf_memalign(tlsf_t tlsf, size_t align, size_t bytes);
 void* tlsf_realloc(tlsf_t tlsf, void* ptr, size_t size);
 void tlsf_free(tlsf_t tlsf, void* ptr);
+#endif
 
 /* Returns internal block size, not original request size */
 size_t tlsf_block_size(void* ptr);
@@ -64,6 +72,8 @@ int tlsf_check(tlsf_t tlsf);
 int tlsf_check_pool(pool_t pool);
 
 void tlsf_meminfo(tlsf_t pool, struct mem_info *info);
+void tlsf_status(tlsf_t pool);
+void tlsf_sums(tlsf_t pool);
 size_t tlsf_available(tlsf_t pool);
 
 #if defined(__cplusplus)