ref: 2a94e1fc1929746039edc5f2544dd472056cddcc
parent: a84c51a1e3c1e9c7ed8cdaf427cc790dc17854cb
author: cinap_lenrek <[email protected]>
date: Fri May 31 14:55:01 EDT 2013
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.
--- a/sys/src/libc/port/pool.c
+++ b/sys/src/libc/port/pool.c
@@ -159,7 +159,6 @@
static void* poolreallocl(Pool*, void*, ulong);
static Free* treedelete(Free*, Free*);
static Free* treeinsert(Free*, Free*);
-static Free* treelookup(Free*, ulong);
static Free* treelookupgt(Free*, ulong);
/*
@@ -230,30 +229,21 @@
static Free**
ltreewalk(Free **t, ulong size)
{
- assert(t != nil /* ltreewalk */);
+ Free *f;
for(;;) {
- if(*t == nil)
+ f = *t;
+ if(f == nil || f->magic != FREE_MAGIC)
return t;
-
- assert((*t)->magic == FREE_MAGIC);
-
- if(size == (*t)->size)
+ if(size == f->size)
return t;
- if(size < (*t)->size)
- t = &(*t)->left;
+ if(size < f->size)
+ t = &f->left;
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 */
static Free*
treeinsert(Free *tree, Free *node)
@@ -263,11 +253,11 @@
assert(node != nil /* treeinsert */);
loc = ltreewalk(&tree, node->size);
- if(*loc == nil) {
+ repl = *loc;
+ if(repl == nil || repl->magic != FREE_MAGIC) {
node->left = nil;
node->right = nil;
} else { /* replace existing node */
- repl = *loc;
node->left = repl->left;
node->right = repl->right;
}
@@ -284,7 +274,8 @@
assert(node != nil /* treedelete */);
loc = ltreewalk(&tree, node->size);
- assert(*loc == node);
+ if(*loc != node || node->magic != FREE_MAGIC)
+ return tree; /* free nodes corrupted */
if(node->left == nil)
*loc = node->right;
@@ -300,7 +291,6 @@
succ->right = node->right;
*loc = succ;
}
-
node->left = node->right = Poison;
return tree;
}
@@ -313,7 +303,7 @@
lastgood = nil;
for(;;) {
- if(t == nil)
+ if(t == nil || t->magic != FREE_MAGIC)
return lastgood;
if(size == t->size)
return t;
@@ -387,6 +377,11 @@
node->magic = FREE_MAGIC;
parent = ltreewalk(&p->freeroot, node->size);
olst = *parent;
+ if(olst != nil && olst->magic != FREE_MAGIC){
+ /* corruption of free nodes */
+ poolcheckl(p);
+ olst = *parent = nil;
+ }
lst = listadd(olst, node);
if(olst != lst) /* need to update tree */
*parent = treeinsert(*parent, lst);
@@ -403,14 +398,17 @@
parent = ltreewalk(&p->freeroot, node->size);
olst = *parent;
- assert(olst != nil /* pooldel */);
-
- lst = listdelete(olst, node);
- if(lst == nil)
- *parent = treedelete(*parent, olst);
- else if(lst != olst)
- *parent = treeinsert(*parent, lst);
-
+ if(olst == nil || olst->magic != FREE_MAGIC){
+ /* corruption of free nodes */
+ poolcheckl(p);
+ *parent = nil;
+ } else {
+ lst = listdelete(olst, node);
+ if(lst == nil)
+ *parent = treedelete(*parent, olst);
+ else if(lst != olst)
+ *parent = treeinsert(*parent, lst);
+ }
node->left = node->right = Poison;
p->curfree -= node->size;