- size_t block;//, blocks; unused variable?
- register size_t i;
- struct list *prev, *next;
-
- block = BLOCK (ptr);
-
- type = mdp -> heapinfo[block].busy.type;
- switch (type)
- {
- case 0:
- /* Get as many statistics as early as we can. */
- mdp -> heapstats.chunks_used--;
- mdp -> heapstats.bytes_used -=
- mdp -> heapinfo[block].busy.info.size * BLOCKSIZE;
- mdp -> heapstats.bytes_free +=
- mdp -> heapinfo[block].busy.info.size * BLOCKSIZE;
-
- /* Find the free cluster previous to this one in the free list.
- Start searching at the last block referenced; this may benefit
- programs with locality of allocation. */
- i = mdp -> heapindex;
- if (i > block)
- {
- while (i > block)
- {
- i = mdp -> heapinfo[i].free.prev;
- }
- }
- else
- {
- do
- {
- i = mdp -> heapinfo[i].free.next;
- }
- while ((i != 0) && (i < block));
- i = mdp -> heapinfo[i].free.prev;
- }
-
- /* Determine how to link this block into the free list. */
- if (block == i + mdp -> heapinfo[i].free.size)
- {
- /* Coalesce this block with its predecessor. */
- mdp -> heapinfo[i].free.size +=
- mdp -> heapinfo[block].busy.info.size;
- block = i;
- }
- else
- {
- /* Really link this block back into the free list. */
- mdp -> heapinfo[block].free.size =
- mdp -> heapinfo[block].busy.info.size;
- mdp -> heapinfo[block].free.next = mdp -> heapinfo[i].free.next;
- mdp -> heapinfo[block].free.prev = i;
- mdp -> heapinfo[i].free.next = block;
- mdp -> heapinfo[mdp -> heapinfo[block].free.next].free.prev = block;
- mdp -> heapstats.chunks_free++;
- }
-
- /* Now that the block is linked in, see if we can coalesce it
- with its successor (by deleting its successor from the list
- and adding in its size). */
- if (block + mdp -> heapinfo[block].free.size ==
- mdp -> heapinfo[block].free.next)
- {
- mdp -> heapinfo[block].free.size
- += mdp -> heapinfo[mdp -> heapinfo[block].free.next].free.size;
- mdp -> heapinfo[block].free.next
- = mdp -> heapinfo[mdp -> heapinfo[block].free.next].free.next;
- mdp -> heapinfo[mdp -> heapinfo[block].free.next].free.prev = block;
- mdp -> heapstats.chunks_free--;
- }
-
- /* Now see if we can return stuff to the system. */
- /* blocks = mdp -> heapinfo[block].free.size;
- if (blocks >= FINAL_FREE_BLOCKS && block + blocks == mdp -> heaplimit
- && mdp -> morecore (mdp, 0) == ADDRESS (block + blocks))
- {
- register size_t bytes = blocks * BLOCKSIZE;
- mdp -> heaplimit -= blocks;
- mdp -> morecore (mdp, -bytes);
- mdp -> heapinfo[mdp -> heapinfo[block].free.prev].free.next
- = mdp -> heapinfo[block].free.next;
- mdp -> heapinfo[mdp -> heapinfo[block].free.next].free.prev
- = mdp -> heapinfo[block].free.prev;
- block = mdp -> heapinfo[block].free.prev;
- mdp -> heapstats.chunks_free--;
- mdp -> heapstats.bytes_free -= bytes;
- }*/
-
- /* Set the next search to begin at this block. */
- mdp -> heapindex = block;
- break;
-
- default:
- /* Do some of the statistics. */
- mdp -> heapstats.chunks_used--;
- mdp -> heapstats.bytes_used -= 1 << type;
+ size_t block, frag_nb;
+ size_t i;
+ int it;
+
+ mmalloc_paranoia(mdp);
+// fprintf(stderr,"free(%p)\n",ptr);
+
+ if (ptr == NULL)
+ return;
+
+ block = BLOCK(ptr);
+
+ if ((char *) ptr < (char *) mdp->heapbase || block > mdp->heapsize) {
+ fprintf(stderr,"Ouch, this pointer is not mine, I refuse to free it. Give me valid pointers, or give me death!!\n");
+ abort();
+ }
+
+ type = mdp->heapinfo[block].type;
+
+ switch (type) {
+ case MMALLOC_TYPE_HEAPINFO:
+ UNLOCK(mdp);
+ THROWF(system_error, 0, "Asked to free a fragment in a heapinfo block. I'm confused.\n");
+ break;
+
+ case MMALLOC_TYPE_FREE: /* Already free */
+ UNLOCK(mdp);
+ THROWF(system_error, 0, "Asked to free a fragment in a block that is already free. I'm puzzled.\n");
+ break;
+
+ case MMALLOC_TYPE_UNFRAGMENTED:
+ /* Get as many statistics as early as we can. */
+ mdp -> heapstats.chunks_used--;
+ mdp -> heapstats.bytes_used -=
+ mdp -> heapinfo[block].busy_block.size * BLOCKSIZE;
+ mdp -> heapstats.bytes_free +=
+ mdp -> heapinfo[block].busy_block.size * BLOCKSIZE;
+
+ if(MC_is_active()){
+ if(mdp->heapinfo[block].busy_block.ignore > 0)
+ MC_remove_ignore_heap(ptr, mdp -> heapinfo[block].busy_block.busy_size);
+ }
+
+ /* Find the free cluster previous to this one in the free list.
+ Start searching at the last block referenced; this may benefit
+ programs with locality of allocation. */
+ i = mdp->heapindex;
+ if (i > block) {
+ while (i > block) {
+ i = mdp->heapinfo[i].free_block.prev;
+ }
+ } else {
+ do {
+ i = mdp->heapinfo[i].free_block.next;
+ }
+ while ((i != 0) && (i < block));
+ i = mdp->heapinfo[i].free_block.prev;
+ }
+
+ /* Determine how to link this block into the free list. */
+ if (block == i + mdp->heapinfo[i].free_block.size) {
+
+ /* Coalesce this block with its predecessor. */
+ mdp->heapinfo[i].free_block.size += mdp->heapinfo[block].busy_block.size;
+ /* Mark all my ex-blocks as free */
+ for (it=0; it<mdp->heapinfo[block].busy_block.size; it++) {
+ if (mdp->heapinfo[block+it].type < 0) {
+ fprintf(stderr,"Internal Error: Asked to free a block already marked as free (block=%lu it=%d type=%lu). Please report this bug.\n",
+ (unsigned long)block,it,(unsigned long)mdp->heapinfo[block].type);
+ abort();
+ }
+ mdp->heapinfo[block+it].type = MMALLOC_TYPE_FREE;
+ }
+
+ block = i;
+ } else {
+ //fprintf(stderr,"Free block %d to %d (as a new chunck)\n",block,block+mdp->heapinfo[block].busy_block.size);
+ /* Really link this block back into the free list. */
+ mdp->heapinfo[block].free_block.size = mdp->heapinfo[block].busy_block.size;
+ mdp->heapinfo[block].free_block.next = mdp->heapinfo[i].free_block.next;
+ mdp->heapinfo[block].free_block.prev = i;
+ mdp->heapinfo[i].free_block.next = block;
+ mdp->heapinfo[mdp->heapinfo[block].free_block.next].free_block.prev = block;