pool: do poolcheck when free nodes get corrupted instead of assert
doing poolcheck should give us better context to figure out what memory blocks / owners corrupted the blocks after free. this is for hunting down a memory corruption seen in connection with usb serial.
This commit is contained in:
parent
a84c51a1e3
commit
2a94e1fc19
1 changed files with 28 additions and 30 deletions
|
@ -159,7 +159,6 @@ static void poolnewarena(Pool*, ulong);
|
||||||
static void* poolreallocl(Pool*, void*, ulong);
|
static void* poolreallocl(Pool*, void*, ulong);
|
||||||
static Free* treedelete(Free*, Free*);
|
static Free* treedelete(Free*, Free*);
|
||||||
static Free* treeinsert(Free*, Free*);
|
static Free* treeinsert(Free*, Free*);
|
||||||
static Free* treelookup(Free*, ulong);
|
|
||||||
static Free* treelookupgt(Free*, ulong);
|
static Free* treelookupgt(Free*, ulong);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -230,30 +229,21 @@ checktree(Free *t, int a, int b)
|
||||||
static Free**
|
static Free**
|
||||||
ltreewalk(Free **t, ulong size)
|
ltreewalk(Free **t, ulong size)
|
||||||
{
|
{
|
||||||
assert(t != nil /* ltreewalk */);
|
Free *f;
|
||||||
|
|
||||||
for(;;) {
|
for(;;) {
|
||||||
if(*t == nil)
|
f = *t;
|
||||||
|
if(f == nil || f->magic != FREE_MAGIC)
|
||||||
return t;
|
return t;
|
||||||
|
if(size == f->size)
|
||||||
assert((*t)->magic == FREE_MAGIC);
|
|
||||||
|
|
||||||
if(size == (*t)->size)
|
|
||||||
return t;
|
return t;
|
||||||
if(size < (*t)->size)
|
if(size < f->size)
|
||||||
t = &(*t)->left;
|
t = &f->left;
|
||||||
else
|
else
|
||||||
t = &(*t)->right;
|
t = &f->right;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* treelookup: find node in tree with size == size */
|
|
||||||
static Free*
|
|
||||||
treelookup(Free *t, ulong size)
|
|
||||||
{
|
|
||||||
return *ltreewalk(&t, size);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* treeinsert: insert node into tree */
|
/* treeinsert: insert node into tree */
|
||||||
static Free*
|
static Free*
|
||||||
treeinsert(Free *tree, Free *node)
|
treeinsert(Free *tree, Free *node)
|
||||||
|
@ -263,11 +253,11 @@ treeinsert(Free *tree, Free *node)
|
||||||
assert(node != nil /* treeinsert */);
|
assert(node != nil /* treeinsert */);
|
||||||
|
|
||||||
loc = ltreewalk(&tree, node->size);
|
loc = ltreewalk(&tree, node->size);
|
||||||
if(*loc == nil) {
|
repl = *loc;
|
||||||
|
if(repl == nil || repl->magic != FREE_MAGIC) {
|
||||||
node->left = nil;
|
node->left = nil;
|
||||||
node->right = nil;
|
node->right = nil;
|
||||||
} else { /* replace existing node */
|
} else { /* replace existing node */
|
||||||
repl = *loc;
|
|
||||||
node->left = repl->left;
|
node->left = repl->left;
|
||||||
node->right = repl->right;
|
node->right = repl->right;
|
||||||
}
|
}
|
||||||
|
@ -284,7 +274,8 @@ treedelete(Free *tree, Free *node)
|
||||||
assert(node != nil /* treedelete */);
|
assert(node != nil /* treedelete */);
|
||||||
|
|
||||||
loc = ltreewalk(&tree, node->size);
|
loc = ltreewalk(&tree, node->size);
|
||||||
assert(*loc == node);
|
if(*loc != node || node->magic != FREE_MAGIC)
|
||||||
|
return tree; /* free nodes corrupted */
|
||||||
|
|
||||||
if(node->left == nil)
|
if(node->left == nil)
|
||||||
*loc = node->right;
|
*loc = node->right;
|
||||||
|
@ -300,7 +291,6 @@ treedelete(Free *tree, Free *node)
|
||||||
succ->right = node->right;
|
succ->right = node->right;
|
||||||
*loc = succ;
|
*loc = succ;
|
||||||
}
|
}
|
||||||
|
|
||||||
node->left = node->right = Poison;
|
node->left = node->right = Poison;
|
||||||
return tree;
|
return tree;
|
||||||
}
|
}
|
||||||
|
@ -313,7 +303,7 @@ treelookupgt(Free *t, ulong size)
|
||||||
|
|
||||||
lastgood = nil;
|
lastgood = nil;
|
||||||
for(;;) {
|
for(;;) {
|
||||||
if(t == nil)
|
if(t == nil || t->magic != FREE_MAGIC)
|
||||||
return lastgood;
|
return lastgood;
|
||||||
if(size == t->size)
|
if(size == t->size)
|
||||||
return t;
|
return t;
|
||||||
|
@ -387,6 +377,11 @@ pooladd(Pool *p, Alloc *anode)
|
||||||
node->magic = FREE_MAGIC;
|
node->magic = FREE_MAGIC;
|
||||||
parent = ltreewalk(&p->freeroot, node->size);
|
parent = ltreewalk(&p->freeroot, node->size);
|
||||||
olst = *parent;
|
olst = *parent;
|
||||||
|
if(olst != nil && olst->magic != FREE_MAGIC){
|
||||||
|
/* corruption of free nodes */
|
||||||
|
poolcheckl(p);
|
||||||
|
olst = *parent = nil;
|
||||||
|
}
|
||||||
lst = listadd(olst, node);
|
lst = listadd(olst, node);
|
||||||
if(olst != lst) /* need to update tree */
|
if(olst != lst) /* need to update tree */
|
||||||
*parent = treeinsert(*parent, lst);
|
*parent = treeinsert(*parent, lst);
|
||||||
|
@ -403,14 +398,17 @@ pooldel(Pool *p, Free *node)
|
||||||
|
|
||||||
parent = ltreewalk(&p->freeroot, node->size);
|
parent = ltreewalk(&p->freeroot, node->size);
|
||||||
olst = *parent;
|
olst = *parent;
|
||||||
assert(olst != nil /* pooldel */);
|
if(olst == nil || olst->magic != FREE_MAGIC){
|
||||||
|
/* corruption of free nodes */
|
||||||
lst = listdelete(olst, node);
|
poolcheckl(p);
|
||||||
if(lst == nil)
|
*parent = nil;
|
||||||
*parent = treedelete(*parent, olst);
|
} else {
|
||||||
else if(lst != olst)
|
lst = listdelete(olst, node);
|
||||||
*parent = treeinsert(*parent, lst);
|
if(lst == nil)
|
||||||
|
*parent = treedelete(*parent, olst);
|
||||||
|
else if(lst != olst)
|
||||||
|
*parent = treeinsert(*parent, lst);
|
||||||
|
}
|
||||||
node->left = node->right = Poison;
|
node->left = node->right = Poison;
|
||||||
p->curfree -= node->size;
|
p->curfree -= node->size;
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue