Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
142777b290e60e5da25dfa423f8847edf797e745
[simgrid.git] / src / xbt / mmalloc / mfree.c
1 /* Free a block of memory allocated by `mmalloc'.
2    Copyright 1990, 1991, 1992 Free Software Foundation
3
4    Written May 1989 by Mike Haertel.
5    Heavily modified Mar 1992 by Fred Fish.  (fnf@cygnus.com) */
6
7 /* Copyright (c) 2010. The SimGrid Team.
8  * All rights reserved.                                                     */
9
10 /* This program is free software; you can redistribute it and/or modify it
11  * under the terms of the license (GNU LGPL) which comes with this package. */
12
13 #include "mmprivate.h"
14
15 /* Return memory to the heap.
16    Like `mfree' but don't call a mfree_hook if there is one.  */
17
18 void
19 __mmalloc_free (struct mdesc *mdp, void *ptr)
20 {
21   int type;
22   size_t block;//, blocks; unused variable?
23   register size_t i;
24   struct list *prev, *next;
25
26   block = BLOCK (ptr);
27
28   if ((char*)ptr < (char*)mdp->heapbase || block > mdp->heapsize ) {
29     printf("Ouch, this pointer is not mine. I refuse to free it.\n");
30     return;
31   }
32
33
34   type = mdp -> heapinfo[block].busy.type;
35   switch (type)
36   {
37   case 0:
38     /* Get as many statistics as early as we can.  */
39     mdp -> heapstats.chunks_used--;
40     mdp -> heapstats.bytes_used -=
41         mdp -> heapinfo[block].busy.info.size * BLOCKSIZE;
42     mdp -> heapstats.bytes_free +=
43         mdp -> heapinfo[block].busy.info.size * BLOCKSIZE;
44
45     /* Find the free cluster previous to this one in the free list.
46          Start searching at the last block referenced; this may benefit
47          programs with locality of allocation.  */
48     i = mdp -> heapindex;
49     if (i > block)
50     {
51       while (i > block)
52       {
53         i = mdp -> heapinfo[i].free.prev;
54       }
55     }
56     else
57     {
58       do
59       {
60         i = mdp -> heapinfo[i].free.next;
61       }
62       while ((i != 0) && (i < block));
63       i = mdp -> heapinfo[i].free.prev;
64     }
65
66     /* Determine how to link this block into the free list.  */
67     if (block == i + mdp -> heapinfo[i].free.size)
68     {
69       /* Coalesce this block with its predecessor.  */
70       mdp -> heapinfo[i].free.size +=
71           mdp -> heapinfo[block].busy.info.size;
72       block = i;
73     }
74     else
75     {
76       /* Really link this block back into the free list.  */
77       mdp -> heapinfo[block].free.size =
78           mdp -> heapinfo[block].busy.info.size;
79       mdp -> heapinfo[block].free.next = mdp -> heapinfo[i].free.next;
80       mdp -> heapinfo[block].free.prev = i;
81       mdp -> heapinfo[i].free.next = block;
82       mdp -> heapinfo[mdp -> heapinfo[block].free.next].free.prev = block;
83       mdp -> heapstats.chunks_free++;
84     }
85
86     /* Now that the block is linked in, see if we can coalesce it
87          with its successor (by deleting its successor from the list
88          and adding in its size).  */
89     if (block + mdp -> heapinfo[block].free.size ==
90         mdp -> heapinfo[block].free.next)
91     {
92       mdp -> heapinfo[block].free.size
93       += mdp -> heapinfo[mdp -> heapinfo[block].free.next].free.size;
94       mdp -> heapinfo[block].free.next
95       = mdp -> heapinfo[mdp -> heapinfo[block].free.next].free.next;
96       mdp -> heapinfo[mdp -> heapinfo[block].free.next].free.prev = block;
97       mdp -> heapstats.chunks_free--;
98     }
99
100     /* Now see if we can return stuff to the system.  */
101     /*    blocks = mdp -> heapinfo[block].free.size;
102       if (blocks >= FINAL_FREE_BLOCKS && block + blocks == mdp -> heaplimit
103           && mdp -> morecore (mdp, 0) == ADDRESS (block + blocks))
104         {
105           register size_t bytes = blocks * BLOCKSIZE;
106           mdp -> heaplimit -= blocks;
107           mdp -> morecore (mdp, -bytes);
108           mdp -> heapinfo[mdp -> heapinfo[block].free.prev].free.next
109             = mdp -> heapinfo[block].free.next;
110           mdp -> heapinfo[mdp -> heapinfo[block].free.next].free.prev
111             = mdp -> heapinfo[block].free.prev;
112           block = mdp -> heapinfo[block].free.prev;
113           mdp -> heapstats.chunks_free--;
114           mdp -> heapstats.bytes_free -= bytes;
115         }*/
116
117     /* Set the next search to begin at this block.  */
118     mdp -> heapindex = block;
119     break;
120
121   default:
122     /* Do some of the statistics.  */
123     mdp -> heapstats.chunks_used--;
124     mdp -> heapstats.bytes_used -= 1 << type;
125     mdp -> heapstats.chunks_free++;
126     mdp -> heapstats.bytes_free += 1 << type;
127
128     /* Get the address of the first free fragment in this block.  */
129     prev = (struct list *)
130             ((char*) ADDRESS(block) +
131                 ( mdp -> heapinfo[block].busy.info.frag.first << type));
132
133     if (mdp -> heapinfo[block].busy.info.frag.nfree ==
134         (BLOCKSIZE >> type) - 1)
135     {
136       /* If all fragments of this block are free, remove them
137              from the fragment list and free the whole block.  */
138       next = prev;
139       for (i = 1; i < (size_t) (BLOCKSIZE >> type); ++i)
140       {
141         next = next -> next;
142       }
143       prev -> prev -> next = next;
144       if (next != NULL)
145       {
146         next -> prev = prev -> prev;
147       }
148       mdp -> heapinfo[block].busy.type = 0;
149       mdp -> heapinfo[block].busy.info.size = 1;
150
151       /* Keep the statistics accurate.  */
152       mdp -> heapstats.chunks_used++;
153       mdp -> heapstats.bytes_used += BLOCKSIZE;
154       mdp -> heapstats.chunks_free -= BLOCKSIZE >> type;
155       mdp -> heapstats.bytes_free -= BLOCKSIZE;
156
157       mfree ((void*) mdp, (void*) ADDRESS(block));
158     }
159     else if (mdp -> heapinfo[block].busy.info.frag.nfree != 0)
160     {
161       /* If some fragments of this block are free, link this
162              fragment into the fragment list after the first free
163              fragment of this block. */
164       next = (struct list *) ptr;
165       next -> next = prev -> next;
166       next -> prev = prev;
167       prev -> next = next;
168       if (next -> next != NULL)
169       {
170         next -> next -> prev = next;
171       }
172       ++mdp -> heapinfo[block].busy.info.frag.nfree;
173     }
174     else
175     {
176       /* No fragments of this block are free, so link this
177              fragment into the fragment list and announce that
178              it is the first free fragment of this block. */
179       prev = (struct list *) ptr;
180       mdp -> heapinfo[block].busy.info.frag.nfree = 1;
181       mdp -> heapinfo[block].busy.info.frag.first =
182           RESIDUAL (ptr, BLOCKSIZE) >> type;
183       prev -> next = mdp -> fraghead[type].next;
184       prev -> prev = &mdp -> fraghead[type];
185       prev -> prev -> next = prev;
186       if (prev -> next != NULL)
187       {
188         prev -> next -> prev = prev;
189       }
190     }
191     break;
192   }
193 }
194
195 /* Return memory to the heap.  */
196
197 void mfree (void *md, void *ptr) {
198   struct mdesc *mdp;
199   register struct alignlist *l;
200
201   if (ptr != NULL) {
202     mdp = MD_TO_MDP (md);
203     LOCK(mdp);
204     for (l = mdp -> aligned_blocks; l != NULL; l = l -> next)   {
205       if (l -> aligned == ptr) {
206         l -> aligned = NULL;  /* Mark the slot in the list as free. */
207         ptr = l -> exact;
208         break;
209       }
210     }
211     if (mdp -> mfree_hook != NULL) {
212       (*mdp -> mfree_hook) (mdp, ptr);
213     } else {
214       __mmalloc_free (mdp, ptr);
215     }
216     UNLOCK(mdp);
217   }
218 }
219