void freePool(MemPool **pmp) { MemPool *mp; while ((mp = *pmp) != NULL) { *pmp = mp->mp_Next; pagefree(mp->mp_Base, mp->mp_Size); free(mp); } }
void free(void *ptr) { struct pagel *pl, *pp; struct block *b, *p; bool palign, nalign; if (ptr == nil) return; b = (struct block *) ((reg_t) ptr - sizeof(size_t)); lock(&heaplock); if (b < heap) { if ((reg_t) b + sizeof(size_t) + b->size == (reg_t) heap) { /* block lines up with start of heap. */ b->size += sizeof(size_t) + heap->size; b->next = heap->next; } else { b->next = heap; } heap = b; goto done; } for (p = heap; p != nil && p->next != nil; p = p->next) { if ((void *) p->next > ptr && ptr < (void *) p->next->next) { break; } } if (p == nil) { printf("Are you sure 0x%h is from the heap?\n", ptr); unlock(&heaplock); return; } palign = (reg_t) p + sizeof(size_t) + p->size == (reg_t) b; if (p->next) { nalign = (reg_t) b + sizeof(size_t) + b->size == (reg_t) p->next; } else { nalign = false; } if (palign && nalign) { /* b lines up with p and p->next, join them all. */ p->size += sizeof(size_t) * 2 + b->size + p->next->size; p->next = p->next->next; b = p; } else if (nalign) { /* b lines up with p->next, join them. */ b->size += sizeof(size_t) + p->next->size; b->next = p->next->next; p->next = b; } else if (palign) { /* b lines up with end of p, join them. */ p->size += sizeof(size_t) + b->size; b = p; } else { /* b is somewhere between p and p->next. */ b->next = p->next; p->next = b; } done: pp = nil; for (pl = pages; pl != nil; pp = pl, pl = pl->next) { if (pl->p->pa == (reg_t) b) { if (b->size + sizeof(size_t) == PAGE_SIZE) { printf("heap can free a page ! 0x%h\n", pl->p->pa); if (pp == nil) { pages = pl->next; } else { pp->next = pl->next; } pagefree(pl->p); free(pl); break; } } } unlock(&heaplock); }