mirror of https://github.com/schoebel/mars
brick_mem: improve debugging
This commit is contained in:
parent
9799fe5417
commit
c45f2da80c
|
@ -48,6 +48,16 @@ config MARS_DEBUG_MEM
|
||||||
many errors (including some that are not caught by kmemleak).
|
many errors (including some that are not caught by kmemleak).
|
||||||
Use only for development and thorough testing!
|
Use only for development and thorough testing!
|
||||||
|
|
||||||
|
config MARS_DEBUG_MEM_STRONG
|
||||||
|
bool "intensified debugging of memory operations"
|
||||||
|
depends on MARS_DEBUG_MEM
|
||||||
|
default y
|
||||||
|
---help---
|
||||||
|
Trace all block allocations, find more errors.
|
||||||
|
Adds some overhead.
|
||||||
|
Use for debugging of new bricks or for intensified
|
||||||
|
regression testing.
|
||||||
|
|
||||||
config MARS_DEBUG_ORDER0
|
config MARS_DEBUG_ORDER0
|
||||||
bool "also debug order0 operations"
|
bool "also debug order0 operations"
|
||||||
depends on MARS_DEBUG_MEM
|
depends on MARS_DEBUG_MEM
|
||||||
|
|
|
@ -13,6 +13,7 @@
|
||||||
#include "brick_say.h"
|
#include "brick_say.h"
|
||||||
#include "brick_locks.h"
|
#include "brick_locks.h"
|
||||||
#include "lamport.h"
|
#include "lamport.h"
|
||||||
|
#include "buildtag.h"
|
||||||
|
|
||||||
#define USE_KERNEL_PAGES // currently mandatory (vmalloc does not work)
|
#define USE_KERNEL_PAGES // currently mandatory (vmalloc does not work)
|
||||||
|
|
||||||
|
@ -214,6 +215,32 @@ EXPORT_SYMBOL_GPL(_brick_mem_free);
|
||||||
|
|
||||||
// string memory allocation
|
// string memory allocation
|
||||||
|
|
||||||
|
#ifdef CONFIG_MARS_DEBUG_MEM_STRONG
|
||||||
|
# define STRING_CANARY \
|
||||||
|
"xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" \
|
||||||
|
"yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy" \
|
||||||
|
"zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz" \
|
||||||
|
"xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" \
|
||||||
|
"yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy" \
|
||||||
|
"zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz" \
|
||||||
|
"xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" \
|
||||||
|
"yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy" \
|
||||||
|
"zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz" \
|
||||||
|
" BUILDTAG = " BUILDTAG \
|
||||||
|
" BUILDHOST = " BUILDHOST \
|
||||||
|
" BUILDDATE = " BUILDDATE \
|
||||||
|
" FILE = " __FILE__ \
|
||||||
|
" DATE = " __DATE__ \
|
||||||
|
" TIME = " __TIME__ \
|
||||||
|
" VERSION = " __VERSION__ \
|
||||||
|
" xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx STRING_error xxx\n"
|
||||||
|
# define STRING_PLUS (sizeof(int) * 3 + sizeof(STRING_CANARY))
|
||||||
|
#elif defined(BRICK_DEBUG_MEM)
|
||||||
|
# define STRING_PLUS (sizeof(int) * 4)
|
||||||
|
#else
|
||||||
|
# define STRING_PLUS 0
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef BRICK_DEBUG_MEM
|
#ifdef BRICK_DEBUG_MEM
|
||||||
static atomic_t phys_string_alloc = ATOMIC_INIT(0);
|
static atomic_t phys_string_alloc = ATOMIC_INIT(0);
|
||||||
static atomic_t string_count[BRICK_DEBUG_MEM] = {};
|
static atomic_t string_count[BRICK_DEBUG_MEM] = {};
|
||||||
|
@ -226,24 +253,18 @@ char *_brick_string_alloc(int len, int line)
|
||||||
|
|
||||||
#ifdef CONFIG_MARS_DEBUG
|
#ifdef CONFIG_MARS_DEBUG
|
||||||
might_sleep();
|
might_sleep();
|
||||||
|
if (unlikely(len > PAGE_SIZE)) {
|
||||||
|
BRICK_WRN("line = %d string too long: len = %d\n", line, len);
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (len <= 0) {
|
if (len <= 0) {
|
||||||
len = BRICK_STRING_LEN;
|
len = BRICK_STRING_LEN;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef BRICK_DEBUG_MEM
|
|
||||||
len += sizeof(int) * 4;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef CONFIG_MARS_MEM_RETRY
|
#ifdef CONFIG_MARS_MEM_RETRY
|
||||||
for (;;) {
|
for (;;) {
|
||||||
#endif
|
#endif
|
||||||
#ifdef CONFIG_MARS_DEBUG
|
res = kzalloc(len + STRING_PLUS, GFP_BRICK);
|
||||||
res = kzalloc(len + 1024, GFP_BRICK);
|
|
||||||
#else
|
|
||||||
res = kzalloc(len + 1, GFP_BRICK);
|
|
||||||
#endif
|
|
||||||
#ifdef CONFIG_MARS_MEM_RETRY
|
#ifdef CONFIG_MARS_MEM_RETRY
|
||||||
if (likely(res))
|
if (likely(res))
|
||||||
break;
|
break;
|
||||||
|
@ -253,6 +274,9 @@ char *_brick_string_alloc(int len, int line)
|
||||||
|
|
||||||
#ifdef BRICK_DEBUG_MEM
|
#ifdef BRICK_DEBUG_MEM
|
||||||
if (likely(res)) {
|
if (likely(res)) {
|
||||||
|
#ifdef CONFIG_MARS_DEBUG_MEM_STRONG
|
||||||
|
memset(res + 1, '?', len - 1);
|
||||||
|
#endif
|
||||||
atomic_inc(&phys_string_alloc);
|
atomic_inc(&phys_string_alloc);
|
||||||
if (unlikely(line < 0))
|
if (unlikely(line < 0))
|
||||||
line = 0;
|
line = 0;
|
||||||
|
@ -261,9 +285,13 @@ char *_brick_string_alloc(int len, int line)
|
||||||
INT_ACCESS(res, 0) = MAGIC_STR;
|
INT_ACCESS(res, 0) = MAGIC_STR;
|
||||||
INT_ACCESS(res, sizeof(int)) = len;
|
INT_ACCESS(res, sizeof(int)) = len;
|
||||||
INT_ACCESS(res, sizeof(int) * 2) = line;
|
INT_ACCESS(res, sizeof(int) * 2) = line;
|
||||||
INT_ACCESS(res, len - sizeof(int)) = MAGIC_SEND;
|
|
||||||
atomic_inc(&string_count[line]);
|
|
||||||
res += sizeof(int) * 3;
|
res += sizeof(int) * 3;
|
||||||
|
#ifdef CONFIG_MARS_DEBUG_MEM_STRONG
|
||||||
|
strcpy(res + len, STRING_CANARY);
|
||||||
|
#else
|
||||||
|
INT_ACCESS(res, len) = MAGIC_SEND;
|
||||||
|
#endif
|
||||||
|
atomic_inc(&string_count[line]);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
return res;
|
return res;
|
||||||
|
@ -276,6 +304,7 @@ void _brick_string_free(const char *data, int cline)
|
||||||
int magic;
|
int magic;
|
||||||
int len;
|
int len;
|
||||||
int line;
|
int line;
|
||||||
|
char *orig = (void*)data;
|
||||||
|
|
||||||
data -= sizeof(int) * 3;
|
data -= sizeof(int) * 3;
|
||||||
magic = INT_ACCESS(data, 0);
|
magic = INT_ACCESS(data, 0);
|
||||||
|
@ -285,16 +314,34 @@ void _brick_string_free(const char *data, int cline)
|
||||||
}
|
}
|
||||||
len = INT_ACCESS(data, sizeof(int));
|
len = INT_ACCESS(data, sizeof(int));
|
||||||
line = INT_ACCESS(data, sizeof(int) * 2);
|
line = INT_ACCESS(data, sizeof(int) * 2);
|
||||||
|
if (unlikely(len <= 0)) {
|
||||||
|
BRICK_ERR("cline %d stringmem corruption: line = %d len = %d\n", cline, line, len);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (unlikely(len > PAGE_SIZE)) {
|
||||||
|
BRICK_ERR("cline %d string too long: line = %d len = %d string='%s'\n", cline, line, len, orig);
|
||||||
|
}
|
||||||
if (unlikely(line < 0 || line >= BRICK_DEBUG_MEM)) {
|
if (unlikely(line < 0 || line >= BRICK_DEBUG_MEM)) {
|
||||||
BRICK_ERR("cline %d stringmem corruption: line = %d (len = %d)\n", cline, line, len);
|
BRICK_ERR("cline %d stringmem corruption: line = %d (len = %d)\n", cline, line, len);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
magic = INT_ACCESS(data, len - sizeof(int));
|
#ifdef CONFIG_MARS_DEBUG_MEM_STRONG
|
||||||
if (unlikely(magic != MAGIC_SEND)) {
|
if (unlikely(strcmp(orig + len, STRING_CANARY))) {
|
||||||
BRICK_ERR("cline %d stringmem corruption: end_magix %08x != %08x, line = %d len = %d\n", cline, magic, MAGIC_SEND, len, line);
|
BRICK_ERR("cline %d stringmem corruption: bad canary '%s', line = %d len = %d\n",
|
||||||
|
cline, STRING_CANARY, line, len);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
INT_ACCESS(data, len - sizeof(int)) = 0xffffffff;
|
orig[len]--;
|
||||||
|
memset(orig, '!', len);
|
||||||
|
#else
|
||||||
|
magic = INT_ACCESS(orig, len);
|
||||||
|
if (unlikely(magic != MAGIC_SEND)) {
|
||||||
|
BRICK_ERR("cline %d stringmem corruption: end_magix %08x != %08x, line = %d len = %d\n",
|
||||||
|
cline, magic, MAGIC_SEND, line, len);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
INT_ACCESS(orig, len) = 0xffffffff;
|
||||||
|
#endif
|
||||||
atomic_dec(&string_count[line]);
|
atomic_dec(&string_count[line]);
|
||||||
atomic_inc(&string_free[line]);
|
atomic_inc(&string_free[line]);
|
||||||
atomic_dec(&phys_string_alloc);
|
atomic_dec(&phys_string_alloc);
|
||||||
|
@ -345,8 +392,78 @@ static int alloc_line[BRICK_MAX_ORDER+1] = {};
|
||||||
static int alloc_len[BRICK_MAX_ORDER+1] = {};
|
static int alloc_len[BRICK_MAX_ORDER+1] = {};
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef CONFIG_MARS_DEBUG_MEM_STRONG
|
||||||
|
|
||||||
|
#define MAX_INFO_LISTS 1024
|
||||||
|
|
||||||
|
#define INFO_LIST_HASH(addr) ((unsigned long)(addr) / (PAGE_SIZE * 2) % MAX_INFO_LISTS)
|
||||||
|
|
||||||
|
struct mem_block_info {
|
||||||
|
struct list_head inf_head;
|
||||||
|
void *inf_data;
|
||||||
|
int inf_len;
|
||||||
|
int inf_line;
|
||||||
|
bool inf_used;
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct list_head inf_anchor[MAX_INFO_LISTS];
|
||||||
|
static rwlock_t inf_lock[MAX_INFO_LISTS];
|
||||||
|
|
||||||
|
static
|
||||||
|
void _new_block_info(void *data, int len, int cline)
|
||||||
|
{
|
||||||
|
struct mem_block_info *inf;
|
||||||
|
int hash;
|
||||||
|
|
||||||
|
for (;;) {
|
||||||
|
inf = kmalloc(sizeof(struct mem_block_info), GFP_BRICK);
|
||||||
|
if (likely(inf))
|
||||||
|
break;
|
||||||
|
msleep(1000);
|
||||||
|
}
|
||||||
|
inf->inf_data = data;
|
||||||
|
inf->inf_len = len;
|
||||||
|
inf->inf_line = cline;
|
||||||
|
inf->inf_used = true;
|
||||||
|
|
||||||
|
hash = INFO_LIST_HASH(data);
|
||||||
|
|
||||||
|
write_lock(&inf_lock[hash]);
|
||||||
|
list_add(&inf->inf_head, &inf_anchor[hash]);
|
||||||
|
write_unlock(&inf_lock[hash]);
|
||||||
|
}
|
||||||
|
|
||||||
|
static
|
||||||
|
struct mem_block_info *_find_block_info(void *data, bool remove)
|
||||||
|
{
|
||||||
|
struct mem_block_info *res = NULL;
|
||||||
|
struct list_head *tmp;
|
||||||
|
int hash = INFO_LIST_HASH(data);
|
||||||
|
|
||||||
|
if (remove)
|
||||||
|
write_lock(&inf_lock[hash]);
|
||||||
|
else
|
||||||
|
read_lock(&inf_lock[hash]);
|
||||||
|
for (tmp = inf_anchor[hash].next; tmp != &inf_anchor[hash]; tmp = tmp->next) {
|
||||||
|
struct mem_block_info *inf = container_of(tmp, struct mem_block_info, inf_head);
|
||||||
|
if (inf->inf_data != data)
|
||||||
|
continue;
|
||||||
|
if (remove)
|
||||||
|
list_del_init(tmp);
|
||||||
|
res = inf;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (remove)
|
||||||
|
write_unlock(&inf_lock[hash]);
|
||||||
|
else
|
||||||
|
read_unlock(&inf_lock[hash]);
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // CONFIG_MARS_DEBUG_MEM_STRONG
|
||||||
|
|
||||||
static inline
|
static inline
|
||||||
void *__brick_block_alloc(gfp_t gfp, int order)
|
void *__brick_block_alloc(gfp_t gfp, int order, int cline)
|
||||||
{
|
{
|
||||||
void *res;
|
void *res;
|
||||||
#ifdef CONFIG_MARS_MEM_RETRY
|
#ifdef CONFIG_MARS_MEM_RETRY
|
||||||
|
@ -365,6 +482,9 @@ void *__brick_block_alloc(gfp_t gfp, int order)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (likely(res)) {
|
if (likely(res)) {
|
||||||
|
#ifdef CONFIG_MARS_DEBUG_MEM_STRONG
|
||||||
|
_new_block_info(res, PAGE_SIZE << order, cline);
|
||||||
|
#endif
|
||||||
#ifdef BRICK_DEBUG_MEM
|
#ifdef BRICK_DEBUG_MEM
|
||||||
atomic_inc(&phys_block_alloc);
|
atomic_inc(&phys_block_alloc);
|
||||||
atomic_inc(&raw_count[order]);
|
atomic_inc(&raw_count[order]);
|
||||||
|
@ -376,13 +496,31 @@ void *__brick_block_alloc(gfp_t gfp, int order)
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline
|
static inline
|
||||||
void __brick_block_free(void *data, int order)
|
void __brick_block_free(void *data, int order, int cline)
|
||||||
{
|
{
|
||||||
|
#ifdef CONFIG_MARS_DEBUG_MEM_STRONG
|
||||||
|
struct mem_block_info *inf = _find_block_info(data, true);
|
||||||
|
if (likely(inf)) {
|
||||||
|
int inf_len = inf->inf_len;
|
||||||
|
int inf_line = inf->inf_line;
|
||||||
|
kfree(inf);
|
||||||
|
if (unlikely(inf_len != (PAGE_SIZE << order))) {
|
||||||
|
BRICK_ERR("line %d: address %p: bad freeing size %d (correct should be %d, previous line = %d)\n", cline, data, (int)(PAGE_SIZE << order), inf_len, inf_line);
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
BRICK_ERR("line %d: trying to free non-existent address %p (order = %d)\n", cline, data, order);
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
#ifdef USE_KERNEL_PAGES
|
#ifdef USE_KERNEL_PAGES
|
||||||
__free_pages(virt_to_page((unsigned long)data), order);
|
__free_pages(virt_to_page((unsigned long)data), order);
|
||||||
#else
|
#else
|
||||||
vfree(data);
|
vfree(data);
|
||||||
#endif
|
#endif
|
||||||
|
#ifdef CONFIG_MARS_DEBUG_MEM_STRONG
|
||||||
|
err:
|
||||||
|
#endif
|
||||||
#ifdef BRICK_DEBUG_MEM
|
#ifdef BRICK_DEBUG_MEM
|
||||||
atomic_dec(&phys_block_alloc);
|
atomic_dec(&phys_block_alloc);
|
||||||
atomic_dec(&raw_count[order]);
|
atomic_dec(&raw_count[order]);
|
||||||
|
@ -406,7 +544,7 @@ static void *brick_freelist[BRICK_MAX_ORDER+1] = {};
|
||||||
static atomic_t freelist_count[BRICK_MAX_ORDER+1] = {};
|
static atomic_t freelist_count[BRICK_MAX_ORDER+1] = {};
|
||||||
|
|
||||||
static
|
static
|
||||||
void *_get_free(int order)
|
void *_get_free(int order, int cline)
|
||||||
{
|
{
|
||||||
void *data;
|
void *data;
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
|
@ -422,8 +560,8 @@ void *_get_free(int order)
|
||||||
// prevent further trouble by leaving a memleak
|
// prevent further trouble by leaving a memleak
|
||||||
brick_freelist[order] = NULL;
|
brick_freelist[order] = NULL;
|
||||||
traced_unlock(&freelist_lock[order], flags);
|
traced_unlock(&freelist_lock[order], flags);
|
||||||
BRICK_ERR("freelist corruption at %p (pattern = %lx next %p != %p, murdered = %d), order = %d\n",
|
BRICK_ERR("line %d:freelist corruption at %p (pattern = %lx next %p != %p, murdered = %d), order = %d\n",
|
||||||
data, pattern, next, copy, atomic_read(&freelist_count[order]), order);
|
cline, data, pattern, next, copy, atomic_read(&freelist_count[order]), order);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@ -431,6 +569,21 @@ void *_get_free(int order)
|
||||||
atomic_dec(&freelist_count[order]);
|
atomic_dec(&freelist_count[order]);
|
||||||
}
|
}
|
||||||
traced_unlock(&freelist_lock[order], flags);
|
traced_unlock(&freelist_lock[order], flags);
|
||||||
|
#ifdef CONFIG_MARS_DEBUG_MEM_STRONG
|
||||||
|
if (data) {
|
||||||
|
struct mem_block_info *inf = _find_block_info(data, false);
|
||||||
|
if (likely(inf)) {
|
||||||
|
if (unlikely(inf->inf_len != (PAGE_SIZE << order))) {
|
||||||
|
BRICK_ERR("line %d: address %p: bad freelist size %d (correct should be %d, previous line = %d)\n",
|
||||||
|
cline, data, (int)(PAGE_SIZE << order), inf->inf_len, inf->inf_line);
|
||||||
|
}
|
||||||
|
inf->inf_line = cline;
|
||||||
|
inf->inf_used = true;
|
||||||
|
} else {
|
||||||
|
BRICK_ERR("line %d: freelist address %p is invalid (order = %d)\n", cline, data, order);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -461,10 +614,10 @@ void _free_all(void)
|
||||||
int order;
|
int order;
|
||||||
for (order = BRICK_MAX_ORDER; order >= 0; order--) {
|
for (order = BRICK_MAX_ORDER; order >= 0; order--) {
|
||||||
for (;;) {
|
for (;;) {
|
||||||
void *data = _get_free(order);
|
void *data = _get_free(order, __LINE__);
|
||||||
if (!data)
|
if (!data)
|
||||||
break;
|
break;
|
||||||
__brick_block_free(data, order);
|
__brick_block_free(data, order, __LINE__);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -483,7 +636,7 @@ int brick_mem_reserve(void)
|
||||||
max = brick_mem_freelist_max[order] - atomic_read(&freelist_count[order]);
|
max = brick_mem_freelist_max[order] - atomic_read(&freelist_count[order]);
|
||||||
if (max >= 0) {
|
if (max >= 0) {
|
||||||
for (i = 0; i < max; i++) {
|
for (i = 0; i < max; i++) {
|
||||||
void *data = __brick_block_alloc(GFP_KERNEL, order);
|
void *data = __brick_block_alloc(GFP_KERNEL, order, __LINE__);
|
||||||
if (likely(data)) {
|
if (likely(data)) {
|
||||||
_put_free(data, order);
|
_put_free(data, order);
|
||||||
} else {
|
} else {
|
||||||
|
@ -492,9 +645,9 @@ int brick_mem_reserve(void)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
for (i = 0; i < -max; i++) {
|
for (i = 0; i < -max; i++) {
|
||||||
void *data = _get_free(order);
|
void *data = _get_free(order, __LINE__);
|
||||||
if (likely(data)) {
|
if (likely(data)) {
|
||||||
__brick_block_free(data, order);
|
__brick_block_free(data, order, __LINE__);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -559,10 +712,10 @@ void *_brick_block_alloc(loff_t pos, int len, int line)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef CONFIG_MARS_MEM_PREALLOC
|
#ifdef CONFIG_MARS_MEM_PREALLOC
|
||||||
data = _get_free(order);
|
data = _get_free(order, line);
|
||||||
if (!data)
|
if (!data)
|
||||||
#endif
|
#endif
|
||||||
data = __brick_block_alloc(GFP_BRICK, order);
|
data = __brick_block_alloc(GFP_BRICK, order, line);
|
||||||
|
|
||||||
#ifdef BRICK_DEBUG_MEM
|
#ifdef BRICK_DEBUG_MEM
|
||||||
if (likely(data) && order > 0) {
|
if (likely(data) && order > 0) {
|
||||||
|
@ -593,7 +746,12 @@ EXPORT_SYMBOL_GPL(_brick_block_alloc);
|
||||||
void _brick_block_free(void *data, int len, int cline)
|
void _brick_block_free(void *data, int len, int cline)
|
||||||
{
|
{
|
||||||
int order;
|
int order;
|
||||||
|
#ifdef CONFIG_MARS_DEBUG_MEM_STRONG
|
||||||
|
struct mem_block_info *inf;
|
||||||
|
char *real_data;
|
||||||
|
#endif
|
||||||
#ifdef BRICK_DEBUG_MEM
|
#ifdef BRICK_DEBUG_MEM
|
||||||
|
int prev_line = 0;
|
||||||
#ifdef BRICK_DEBUG_ORDER0
|
#ifdef BRICK_DEBUG_ORDER0
|
||||||
const int plus0 = PAGE_SIZE;
|
const int plus0 = PAGE_SIZE;
|
||||||
#else
|
#else
|
||||||
|
@ -605,6 +763,29 @@ void _brick_block_free(void *data, int len, int cline)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
order = len2order(len + plus);
|
order = len2order(len + plus);
|
||||||
|
#ifdef CONFIG_MARS_DEBUG_MEM_STRONG
|
||||||
|
real_data = data;
|
||||||
|
if (order > 1)
|
||||||
|
real_data -= PAGE_SIZE;
|
||||||
|
inf = _find_block_info(real_data, false);
|
||||||
|
if (likely(inf)) {
|
||||||
|
prev_line = inf->inf_line;
|
||||||
|
if (unlikely(inf->inf_len != (PAGE_SIZE << order))) {
|
||||||
|
BRICK_ERR("line %d: address %p: bad freeing size %d (correct should be %d, previous line = %d)\n",
|
||||||
|
cline, data, (int)(PAGE_SIZE << order), inf->inf_len, prev_line);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (unlikely(!inf->inf_used)) {
|
||||||
|
BRICK_ERR("line %d: address %p: double freeing (previous line = %d)\n", cline, data, prev_line);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
inf->inf_line = cline;
|
||||||
|
inf->inf_used = false;
|
||||||
|
} else {
|
||||||
|
BRICK_ERR("line %d: trying to free non-existent address %p (order = %d)\n", cline, data, order);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
#ifdef BRICK_DEBUG_MEM
|
#ifdef BRICK_DEBUG_MEM
|
||||||
if (order > 1) {
|
if (order > 1) {
|
||||||
void *test = data - PAGE_SIZE;
|
void *test = data - PAGE_SIZE;
|
||||||
|
@ -615,24 +796,24 @@ void _brick_block_free(void *data, int len, int cline)
|
||||||
int magic2;
|
int magic2;
|
||||||
|
|
||||||
if (unlikely(magic1 != MAGIC_BLOCK)) {
|
if (unlikely(magic1 != MAGIC_BLOCK)) {
|
||||||
BRICK_ERR("line %d memory corruption: magix1 %08x != %08x\n", cline, magic1, MAGIC_BLOCK);
|
BRICK_ERR("line %d memory corruption: %p magix1 %08x != %08x (previous line = %d)\n", cline, data, magic1, MAGIC_BLOCK, prev_line);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (unlikely(magic != MAGIC_BLOCK)) {
|
if (unlikely(magic != MAGIC_BLOCK)) {
|
||||||
BRICK_ERR("line %d memory corruption: magix %08x != %08x\n", cline, magic, MAGIC_BLOCK);
|
BRICK_ERR("line %d memory corruption: %p magix %08x != %08x (previous line = %d)\n", cline, data, magic, MAGIC_BLOCK, prev_line);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (unlikely(line < 0 || line >= BRICK_DEBUG_MEM)) {
|
if (unlikely(line < 0 || line >= BRICK_DEBUG_MEM)) {
|
||||||
BRICK_ERR("line %d memory corruption: alloc line = %d\n", cline, line);
|
BRICK_ERR("line %d memory corruption %p: alloc line = %d (previous line = %d)\n", cline, data, line, prev_line);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (unlikely(oldlen != len)) {
|
if (unlikely(oldlen != len)) {
|
||||||
BRICK_ERR("line %d memory corruption: len != oldlen (%d != %d)\n", cline, len, oldlen);
|
BRICK_ERR("line %d memory corruption %p: len != oldlen (%d != %d, previous line = %d))\n", cline, data, len, oldlen, prev_line);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
magic2 = INT_ACCESS(data, len);
|
magic2 = INT_ACCESS(data, len);
|
||||||
if (unlikely(magic2 != MAGIC_BEND)) {
|
if (unlikely(magic2 != MAGIC_BEND)) {
|
||||||
BRICK_ERR("line %d memory corruption: magix %08x != %08x\n", cline, magic, MAGIC_BEND);
|
BRICK_ERR("line %d memory corruption %p: magix %08x != %08x (previous line = %d)\n", cline, data, magic, MAGIC_BEND, prev_line);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
INT_ACCESS(test, 0) = 0xffffffff;
|
INT_ACCESS(test, 0) = 0xffffffff;
|
||||||
|
@ -647,15 +828,15 @@ void _brick_block_free(void *data, int len, int cline)
|
||||||
int oldlen = INT_ACCESS(test, 2 * sizeof(int));
|
int oldlen = INT_ACCESS(test, 2 * sizeof(int));
|
||||||
|
|
||||||
if (unlikely(magic != MAGIC_BLOCK)) {
|
if (unlikely(magic != MAGIC_BLOCK)) {
|
||||||
BRICK_ERR("line %d memory corruption: magix %08x != %08x\n", cline, magic, MAGIC_BLOCK);
|
BRICK_ERR("line %d memory corruption %p: magix %08x != %08x (previous line = %d)\n", cline, data, magic, MAGIC_BLOCK, prev_line);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (unlikely(line < 0 || line >= BRICK_DEBUG_MEM)) {
|
if (unlikely(line < 0 || line >= BRICK_DEBUG_MEM)) {
|
||||||
BRICK_ERR("line %d memory corruption: alloc line = %d\n", cline, line);
|
BRICK_ERR("line %d memory corruption %p: alloc line = %d (previous line = %d)\n", cline, data, line, prev_line);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (unlikely(oldlen != len)) {
|
if (unlikely(oldlen != len)) {
|
||||||
BRICK_ERR("line %d memory corruption: len != oldlen (%d != %d)\n", cline, len, oldlen);
|
BRICK_ERR("line %d memory corruption %p: len != oldlen (%d != %d, previous line = %d))\n", cline, data, len, oldlen, prev_line);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
atomic_dec(&block_count[line]);
|
atomic_dec(&block_count[line]);
|
||||||
|
@ -667,7 +848,7 @@ void _brick_block_free(void *data, int len, int cline)
|
||||||
_put_free(data, order);
|
_put_free(data, order);
|
||||||
} else
|
} else
|
||||||
#endif
|
#endif
|
||||||
__brick_block_free(data, order);
|
__brick_block_free(data, order, cline);
|
||||||
|
|
||||||
#ifdef CONFIG_MARS_MEM_PREALLOC
|
#ifdef CONFIG_MARS_MEM_PREALLOC
|
||||||
brick_mem_alloc_count[order] = atomic_dec_return(&_alloc_count[order]);
|
brick_mem_alloc_count[order] = atomic_dec_return(&_alloc_count[order]);
|
||||||
|
@ -799,12 +980,20 @@ EXPORT_SYMBOL_GPL(brick_mem_statistics);
|
||||||
|
|
||||||
int __init init_brick_mem(void)
|
int __init init_brick_mem(void)
|
||||||
{
|
{
|
||||||
#ifdef CONFIG_MARS_MEM_PREALLOC
|
|
||||||
int i;
|
int i;
|
||||||
|
#ifdef CONFIG_MARS_MEM_PREALLOC
|
||||||
for (i = BRICK_MAX_ORDER; i >= 0; i--) {
|
for (i = BRICK_MAX_ORDER; i >= 0; i--) {
|
||||||
spin_lock_init(&freelist_lock[i]);
|
spin_lock_init(&freelist_lock[i]);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
#ifdef CONFIG_MARS_DEBUG_MEM_STRONG
|
||||||
|
for (i = 0; i < MAX_INFO_LISTS; i++) {
|
||||||
|
INIT_LIST_HEAD(&inf_anchor[i]);
|
||||||
|
rwlock_init(&inf_lock[i]);
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
(void)i;
|
||||||
|
#endif
|
||||||
|
|
||||||
get_total_ram();
|
get_total_ram();
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue