summaryrefslogtreecommitdiffstats
path: root/common
diff options
context:
space:
mode:
authorSascha Hauer <s.hauer@pengutronix.de>2012-01-03 09:39:16 +0100
committerSascha Hauer <s.hauer@pengutronix.de>2012-01-03 09:39:16 +0100
commit2071c5dcfb59d592bf37f190c92eb3bd8eeb2cb9 (patch)
tree53d0771b3d487d342d150e54d7174c13ce392588 /common
parenta135624e2769c87ebb0125821d8427edd5ad9fb4 (diff)
parentc09fdea2c0f7fd4c27b029a3c4b76bb161f63dca (diff)
downloadbarebox-2071c5dcfb59d592bf37f190c92eb3bd8eeb2cb9.tar.gz
barebox-2071c5dcfb59d592bf37f190c92eb3bd8eeb2cb9.tar.xz
Merge branch 'pu/tlsf' into next
Diffstat (limited to 'common')
-rw-r--r--common/tlsf.c17
-rw-r--r--common/tlsf_malloc.c25
-rw-r--r--common/tlsfbits.h55
3 files changed, 85 insertions, 12 deletions
diff --git a/common/tlsf.c b/common/tlsf.c
index b3de9765c4..c810e8dafe 100644
--- a/common/tlsf.c
+++ b/common/tlsf.c
@@ -1,20 +1,17 @@
-#ifndef __BAREBOX__
-#include <assert.h>
-#include <limits.h>
-#endif
#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
+#include <linux/stringify.h>
#include "tlsf.h"
#include "tlsfbits.h"
-#ifdef __BAREBOX__
-#ifndef _DEBUG
-#define _DEBUG 0
-#endif
-#define tlsf_assert(expr) ((void) (0))
+#ifdef DEBUG
+#define tlsf_assert(expr) \
+ ((expr) ? (void)(0) : printf("%s\n", __stringify(expr)))
+#else
+#define tlsf_assert(expr) (void)(0)
#endif
/*
@@ -759,7 +756,7 @@ tlsf_pool tlsf_create(void* mem, size_t bytes)
const size_t pool_bytes = align_down(bytes - pool_overhead, ALIGN_SIZE);
pool_t* pool = tlsf_cast(pool_t*, mem);
-#if _DEBUG
+#ifdef DEBUG
/* Verify ffs/fls work properly. */
int rv = 0;
rv += (tlsf_ffs(0) == -1) ? 0 : 0x1;
diff --git a/common/tlsf_malloc.c b/common/tlsf_malloc.c
index a6f82ba58d..2fe443bf2b 100644
--- a/common/tlsf_malloc.c
+++ b/common/tlsf_malloc.c
@@ -71,8 +71,29 @@ void *memalign(size_t alignment, size_t bytes)
}
EXPORT_SYMBOL(memalign);
-#ifdef CONFIG_CMD_MEMINFO
+struct malloc_stats {
+ size_t free;
+ size_t used;
+};
+
+static void malloc_walker(void* ptr, size_t size, int used, void *user)
+{
+ struct malloc_stats *s = user;
+
+ if (used)
+ s->used += size;
+ else
+ s->free += size;
+}
+
void malloc_stats(void)
{
+ struct malloc_stats s;
+
+ s.used = 0;
+ s.free = 0;
+
+ tlsf_walk_heap(tlsf_mem_pool, malloc_walker, &s);
+
+ printf("used: %10d\nfree: %10d\n", s.used, s.free);
}
-#endif /* CONFIG_CMD_MEMINFO */
diff --git a/common/tlsfbits.h b/common/tlsfbits.h
new file mode 100644
index 0000000000..93466e46a8
--- /dev/null
+++ b/common/tlsfbits.h
@@ -0,0 +1,55 @@
+#ifndef INCLUDED_tlsfbits
+#define INCLUDED_tlsfbits
+
+#include <linux/bitops.h>
+
+/*
+** Architecture-specific bit manipulation routines.
+**
+** TLSF achieves O(1) cost for malloc and free operations by limiting
+** the search for a free block to a free list of guaranteed size
+** adequate to fulfill the request, combined with efficient free list
+** queries using bitmasks and architecture-specific bit-manipulation
+** routines.
+**
+** Most modern processors provide instructions to count leading zeroes
+** in a word, find the lowest and highest set bit, etc. These
+** specific implementations will be used when available, falling back
+** to a reasonably efficient generic implementation.
+**
+** NOTE: TLSF spec relies on ffs/fls returning value 0..31.
+** ffs/fls return 1-32 by default, returning 0 for error.
+*/
+
+static int tlsf_ffs(unsigned int word)
+{
+ return ffs(word) - 1;
+}
+
+static int tlsf_fls(unsigned int word)
+{
+ return fls(word) - 1;
+}
+
+/* Possibly 64-bit version of tlsf_fls. */
+#if defined (TLSF_64BIT)
+tlsf_decl int tlsf_fls_sizet(size_t size)
+{
+ int high = (int)(size >> 32);
+ int bits = 0;
+ if (high)
+ {
+ bits = 32 + tlsf_fls(high);
+ }
+ else
+ {
+ bits = tlsf_fls((int)size & 0xffffffff);
+
+ }
+ return bits;
+}
+#else
+#define tlsf_fls_sizet tlsf_fls
+#endif
+
+#endif