diff options
| author | Gareth Rees | 2013-05-31 13:41:36 +0100 |
|---|---|---|
| committer | Gareth Rees | 2013-05-31 13:41:36 +0100 |
| commit | 83aff660e27fe56ba6f5c4b898aa00da206c6c9e (patch) | |
| tree | 8a324c5520c20c8a824c979291d4fbf8602b2faa /mps/code | |
| parent | 915a41123cdc078220b43fed8d9d44b0845c9493 (diff) | |
| download | emacs-83aff660e27fe56ba6f5c4b898aa00da206c6c9e.tar.gz emacs-83aff660e27fe56ba6f5c4b898aa00da206c6c9e.zip | |
Use a tag in the bottom bit to distinguish grains and blocks in the free list. this results in much simplification of the code.
Copied from Perforce
Change: 182362
ServerID: perforce.ravenbrook.com
Diffstat (limited to 'mps/code')
| -rw-r--r-- | mps/code/freelist.c | 611 | ||||
| -rw-r--r-- | mps/code/freelist.h | 8 |
2 files changed, 161 insertions, 458 deletions
diff --git a/mps/code/freelist.c b/mps/code/freelist.c index 79d10409469..f6e86ddf958 100644 --- a/mps/code/freelist.c +++ b/mps/code/freelist.c | |||
| @@ -15,83 +15,78 @@ SRCID(freelist, "$Id$"); | |||
| 15 | /* See <design/freelist/#impl.grain.align> */ | 15 | /* See <design/freelist/#impl.grain.align> */ |
| 16 | #define freelistMinimumAlignment ((Align)sizeof(void *)) | 16 | #define freelistMinimumAlignment ((Align)sizeof(void *)) |
| 17 | 17 | ||
| 18 | #define FreelistBlock(addr) ((Addr *)(addr)) | ||
| 18 | 19 | ||
| 19 | /* See <design/freelist/#impl.grain> */ | 20 | #define FreelistTag(addr) ((Word)(addr) & 1) |
| 20 | typedef struct FreelistGrainStruct { | 21 | #define FreelistTagSet(addr) ((Addr)((Word)(addr) | 1)) |
| 21 | Addr next; | 22 | #define FreelistTagReset(addr) ((Addr)((Word)(addr) & ~1)) |
| 22 | } FreelistGrainStruct; | 23 | #define FreelistTagCopy(to, from) ((Addr)((Word)(to) | FreelistTag(from))) |
| 23 | 24 | ||
| 24 | |||
| 25 | /* FreelistGrain* -- Getters and setters for grains | ||
| 26 | * | ||
| 27 | * See <design/freelist/#impl.grain>. | ||
| 28 | */ | ||
| 29 | #define FreelistGrainBase(grain) ((Addr)(grain)) | ||
| 30 | #define FreelistGrainLimit(fl, grain) \ | ||
| 31 | AddrAdd(FreelistGrainBase(grain), FreelistGrainSize(fl)) | ||
| 32 | #define FreelistGrainSize(fl) ((fl)->alignment) | 25 | #define FreelistGrainSize(fl) ((fl)->alignment) |
| 33 | #define FreelistGrainNext(grain) \ | ||
| 34 | ((FreelistGrain)(((FreelistGrain)(grain))->next)) | ||
| 35 | #define FreelistGrainSetNext(grain, _next) \ | ||
| 36 | BEGIN ((FreelistGrain)(grain))->next = (void *)(_next); END | ||
| 37 | 26 | ||
| 38 | 27 | ||
| 39 | /* FreelistGrainInit -- return grain for the range [base, limit). */ | 28 | /* FreelistBlockLimit -- return the limit of a block. */ |
| 40 | 29 | ||
| 41 | static FreelistGrain FreelistGrainInit(Freelist fl, Addr base, Addr limit) | 30 | static Addr FreelistBlockLimit(Freelist fl, Addr addr) |
| 42 | { | 31 | { |
| 43 | FreelistGrain grain = (FreelistGrain)base; | 32 | Addr *block = FreelistBlock(addr); |
| 44 | AVER(AddrOffset(base, limit) == FreelistGrainSize(fl)); | 33 | if (FreelistTag(block[0])) { |
| 45 | FreelistGrainSetNext(grain, NULL); | 34 | return AddrAdd(addr, FreelistGrainSize(fl)); |
| 46 | return grain; | 35 | } else { |
| 36 | return block[1]; | ||
| 37 | } | ||
| 47 | } | 38 | } |
| 48 | 39 | ||
| 49 | 40 | ||
| 50 | /* See <design/freelist/#impl.block> */ | 41 | /* FreelistBlockNext -- return the next block in the list, or NULL if |
| 51 | typedef struct FreelistBlockStruct { | 42 | * there are no more blocks. |
| 52 | Addr next; | 43 | */ |
| 53 | Addr limit; | 44 | static Addr FreelistBlockNext(Freelist fl, Addr addr) |
| 54 | } FreelistBlockStruct; | 45 | { |
| 46 | Addr *block = FreelistBlock(addr); | ||
| 47 | return FreelistTagReset(block[0]); | ||
| 48 | } | ||
| 55 | 49 | ||
| 56 | 50 | ||
| 57 | /* FreelistBlock* -- Getters and setters for blocks | 51 | /* FreelistBlockSize -- return the size of a block. */ |
| 58 | * | 52 | |
| 59 | * See <design/freelist/#impl.block>. | 53 | #define FreelistBlockSize(fl, block) \ |
| 60 | */ | 54 | AddrOffset(block, FreelistBlockLimit(fl, block)) |
| 61 | #define FreelistBlockBase(block) ((Addr)(block)) | 55 | |
| 62 | #define FreelistBlockLimit(block) (((FreelistBlock)(block))->limit) | 56 | |
| 63 | #define FreelistBlockSize(block) \ | 57 | /* FreelistBlockSetNext -- update the next block in the list */ |
| 64 | AddrOffset(FreelistBlockBase(block), FreelistBlockLimit(block)) | 58 | |
| 65 | #define FreelistBlockNext(block) \ | 59 | static void FreelistBlockSetNext(Freelist fl, Addr addr, Addr next) |
| 66 | ((FreelistBlock)(((FreelistBlock)(block))->next)) | ||
| 67 | #define FreelistBlockSetNext(block, _next) \ | ||
| 68 | BEGIN ((FreelistBlock)(block))->next = (void *)(_next); END | ||
| 69 | #define FreelistBlockSetLimit(block, _limit) \ | ||
| 70 | BEGIN { \ | ||
| 71 | AVER(AddrOffset(block, _limit) >= sizeof(FreelistBlockStruct)); \ | ||
| 72 | ((FreelistBlock)(block))->limit = (void *)(_limit); \ | ||
| 73 | } END | ||
| 74 | |||
| 75 | |||
| 76 | /* FreelistBlockCheck -- check block. */ | ||
| 77 | |||
| 78 | static Bool FreelistBlockCheck(FreelistBlock block) | ||
| 79 | { | 60 | { |
| 80 | CHECKL(FreelistBlockBase(block) < FreelistBlockLimit(block)); | 61 | Addr *block = FreelistBlock(addr); |
| 81 | return TRUE; | 62 | block[0] = FreelistTagCopy(next, block[0]); |
| 63 | } | ||
| 64 | |||
| 65 | |||
| 66 | /* FreelistBlockSetLimit -- update the limit of a block */ | ||
| 67 | |||
| 68 | static void FreelistBlockSetLimit(Freelist fl, Addr addr, Addr limit) | ||
| 69 | { | ||
| 70 | Addr *block = FreelistBlock(addr); | ||
| 71 | Size size = size; | ||
| 72 | if (size > FreelistGrainSize(fl)) { | ||
| 73 | block[0] = FreelistTagReset(block[0]); | ||
| 74 | block[1] = limit; | ||
| 75 | } else { | ||
| 76 | AVER(size == FreelistGrainSize(fl)); | ||
| 77 | block[0] = FreelistTagSet(block[0]); | ||
| 78 | } | ||
| 82 | } | 79 | } |
| 83 | 80 | ||
| 84 | 81 | ||
| 85 | /* FreelistBlockInit -- return block for the range [base, limit). */ | 82 | /* FreelistBlockInit -- return block for the range [base, limit). */ |
| 86 | 83 | ||
| 87 | static FreelistBlock FreelistBlockInit(Addr base, Addr limit) | 84 | static Addr FreelistBlockInit(Freelist fl, Addr base, Addr limit) |
| 88 | { | 85 | { |
| 89 | FreelistBlock block; | 86 | Addr *block = FreelistBlock(base); |
| 90 | AVER(AddrOffset(base, limit) >= sizeof(FreelistBlockStruct)); | 87 | block[0] = NULL; |
| 91 | block = (FreelistBlock)base; | 88 | FreelistBlockSetLimit(fl, base, limit); |
| 92 | FreelistBlockSetNext(block, NULL); | 89 | return base; |
| 93 | FreelistBlockSetLimit(block, limit); | ||
| 94 | return block; | ||
| 95 | } | 90 | } |
| 96 | 91 | ||
| 97 | 92 | ||
| @@ -100,24 +95,20 @@ Bool FreelistCheck(Freelist fl) | |||
| 100 | CHECKS(Freelist, fl); | 95 | CHECKS(Freelist, fl); |
| 101 | /* See <design/freelist/#impl.grain.align> */ | 96 | /* See <design/freelist/#impl.grain.align> */ |
| 102 | CHECKL(AlignIsAligned(fl->alignment, freelistMinimumAlignment)); | 97 | CHECKL(AlignIsAligned(fl->alignment, freelistMinimumAlignment)); |
| 103 | /* can't check blockList or grainList more */ | 98 | /* can't check list or listSize */ |
| 104 | /* Checking blockListSize and grainListSize is too laborious without | ||
| 105 | a List ADT */ | ||
| 106 | return TRUE; | 99 | return TRUE; |
| 107 | } | 100 | } |
| 108 | 101 | ||
| 109 | 102 | ||
| 110 | Res FreelistInit(Freelist fl, Align alignment) | 103 | Res FreelistInit(Freelist fl, Align alignment) |
| 111 | { | 104 | { |
| 112 | /* See <design/freelist/#impl.grain.align> */ | 105 | /* See <design/freelist/#impl.grain> */ |
| 113 | if (!AlignIsAligned(alignment, freelistMinimumAlignment)) | 106 | if (!AlignIsAligned(alignment, freelistMinimumAlignment)) |
| 114 | return ResPARAM; | 107 | return ResPARAM; |
| 115 | 108 | ||
| 116 | fl->alignment = alignment; | 109 | fl->alignment = alignment; |
| 117 | fl->blockList = NULL; | 110 | fl->list = NULL; |
| 118 | fl->blockListSize = 0; | 111 | fl->listSize = 0; |
| 119 | fl->grainList = NULL; | ||
| 120 | fl->grainListSize = 0; | ||
| 121 | 112 | ||
| 122 | fl->sig = FreelistSig; | 113 | fl->sig = FreelistSig; |
| 123 | AVERT(Freelist, fl); | 114 | AVERT(Freelist, fl); |
| @@ -129,27 +120,7 @@ void FreelistFinish(Freelist fl) | |||
| 129 | { | 120 | { |
| 130 | AVERT(Freelist, fl); | 121 | AVERT(Freelist, fl); |
| 131 | fl->sig = SigInvalid; | 122 | fl->sig = SigInvalid; |
| 132 | 123 | fl->list = NULL; | |
| 133 | fl->blockList = NULL; | ||
| 134 | fl->grainList = NULL; | ||
| 135 | } | ||
| 136 | |||
| 137 | |||
| 138 | /* freelistGrainSetPrevNext -- make 'next' be the next grain in the | ||
| 139 | * list after 'prev', or make it the first grain in the list if 'prev' | ||
| 140 | * is NULL. Update the count of grains by 'delta'. | ||
| 141 | */ | ||
| 142 | static void freelistGrainSetPrevNext(Freelist fl, FreelistGrain prev, | ||
| 143 | FreelistGrain next, int delta) | ||
| 144 | { | ||
| 145 | if (prev) { | ||
| 146 | FreelistGrainSetNext(prev, next); | ||
| 147 | } else { | ||
| 148 | fl->grainList = next; | ||
| 149 | } | ||
| 150 | if (delta < 0) | ||
| 151 | AVER(fl->grainListSize >= -delta); | ||
| 152 | fl->grainListSize += delta; | ||
| 153 | } | 124 | } |
| 154 | 125 | ||
| 155 | 126 | ||
| @@ -157,26 +128,24 @@ static void freelistGrainSetPrevNext(Freelist fl, FreelistGrain prev, | |||
| 157 | * list after 'prev', or make it the first block in the list if 'prev' | 128 | * list after 'prev', or make it the first block in the list if 'prev' |
| 158 | * is NULL. Update the count of blocks by 'delta'. | 129 | * is NULL. Update the count of blocks by 'delta'. |
| 159 | */ | 130 | */ |
| 160 | static void freelistBlockSetPrevNext(Freelist fl, FreelistBlock prev, | 131 | static void freelistBlockSetPrevNext(Freelist fl, Addr prev, |
| 161 | FreelistBlock next, int delta) | 132 | Addr next, int delta) |
| 162 | { | 133 | { |
| 163 | if (prev) { | 134 | if (prev) { |
| 164 | FreelistBlockSetNext(prev, next); | 135 | FreelistBlockSetNext(fl, prev, next); |
| 165 | } else { | 136 | } else { |
| 166 | fl->blockList = next; | 137 | fl->list = next; |
| 167 | } | 138 | } |
| 168 | if (delta < 0) | 139 | if (delta < 0) |
| 169 | AVER(fl->blockListSize >= -delta); | 140 | AVER(fl->listSize >= -delta); |
| 170 | fl->blockListSize += delta; | 141 | fl->listSize += delta; |
| 171 | } | 142 | } |
| 172 | 143 | ||
| 173 | 144 | ||
| 174 | Res FreelistInsert(Range rangeReturn, Freelist fl, Range range) | 145 | Res FreelistInsert(Range rangeReturn, Freelist fl, Range range) |
| 175 | { | 146 | { |
| 176 | FreelistGrain grainPrev, grainCur, grainNext, grainNew; | 147 | Addr prev, cur, next, new; |
| 177 | FreelistBlock blockPrev, blockCur, blockNext, blockNew; | ||
| 178 | Addr base, limit; | 148 | Addr base, limit; |
| 179 | Size size; | ||
| 180 | Bool coalesceLeft, coalesceRight; | 149 | Bool coalesceLeft, coalesceRight; |
| 181 | Res res = ResOK; | 150 | Res res = ResOK; |
| 182 | 151 | ||
| @@ -184,115 +153,53 @@ Res FreelistInsert(Range rangeReturn, Freelist fl, Range range) | |||
| 184 | AVERT(Freelist, fl); | 153 | AVERT(Freelist, fl); |
| 185 | AVERT(Range, range); | 154 | AVERT(Range, range); |
| 186 | AVER(RangeIsAligned(range, fl->alignment)); | 155 | AVER(RangeIsAligned(range, fl->alignment)); |
| 156 | AVER(RangeSize(range) >= FreelistGrainSize(fl)); | ||
| 187 | 157 | ||
| 188 | size = RangeSize(range); | ||
| 189 | AVER(size >= FreelistGrainSize(fl)); | ||
| 190 | base = RangeBase(range); | 158 | base = RangeBase(range); |
| 191 | limit = RangeLimit(range); | 159 | limit = RangeLimit(range); |
| 192 | 160 | ||
| 193 | /* In order to correctly detect erroneous input (that is, range | 161 | prev = NULL; |
| 194 | * overlapping with some existing block or grain), we must check for | 162 | cur = fl->list; |
| 195 | * overlap with both the block list and the grain list *before* | 163 | while (cur) { |
| 196 | * trying to coalesce with either, lest we find ourselves in the | 164 | if (base < FreelistBlockLimit(fl, cur) && cur < limit) |
| 197 | * embarrassing position of having coalesced the range with a block | 165 | return ResFAIL; /* range overlaps with cur */ |
| 198 | * only to find that it overlaps with a grain (or vice versa). | 166 | if (limit <= cur) |
| 199 | */ | ||
| 200 | grainPrev = NULL; | ||
| 201 | grainCur = fl->grainList; | ||
| 202 | grainNext = NULL; | ||
| 203 | while (grainCur) { | ||
| 204 | if (base < FreelistGrainLimit(fl, grainCur) | ||
| 205 | && FreelistGrainBase(grainCur) < limit) | ||
| 206 | return ResFAIL; /* range overlaps with grainCur */ | ||
| 207 | if (limit <= FreelistGrainBase(grainCur)) | ||
| 208 | break; | ||
| 209 | /* The following test is a special case for grains. In the block | ||
| 210 | * case we can safely wait until the next time around the loop | ||
| 211 | * because if range coalesces on the left with blockPrev then | ||
| 212 | * blockPrev->limit can be adjusted. But in the grain case if we | ||
| 213 | * coalesce we remove the grain from the grain list, so we have to | ||
| 214 | * ensure that we retain a pointer to the previous grain so that | ||
| 215 | * we can update grainPrev->next. | ||
| 216 | */ | ||
| 217 | if (base == FreelistGrainLimit(fl, grainCur)) | ||
| 218 | break; | ||
| 219 | grainNext = FreelistGrainNext(grainCur); | ||
| 220 | if (grainNext) | ||
| 221 | AVER(FreelistGrainLimit(fl, grainCur) < FreelistGrainBase(grainNext)); | ||
| 222 | grainPrev = grainCur; | ||
| 223 | grainCur = grainNext; | ||
| 224 | } | ||
| 225 | |||
| 226 | blockPrev = NULL; | ||
| 227 | blockCur = fl->blockList; | ||
| 228 | while (blockCur) { | ||
| 229 | AVERT(FreelistBlock, blockCur); | ||
| 230 | if (base < FreelistBlockLimit(blockCur) | ||
| 231 | && FreelistBlockBase(blockCur) < limit) | ||
| 232 | return ResFAIL; /* range overlaps with blockCur */ | ||
| 233 | if (limit <= FreelistBlockBase(blockCur)) | ||
| 234 | break; | 167 | break; |
| 235 | blockNext = FreelistBlockNext(blockCur); | 168 | next = FreelistBlockNext(fl, cur); |
| 236 | if (blockNext) | 169 | if (next) |
| 237 | AVER(FreelistBlockLimit(blockCur) < FreelistBlockBase(blockNext)); | 170 | /* Isolated range invariant (design.mps.freelist.impl.invariant). */ |
| 238 | blockPrev = blockCur; | 171 | AVER(FreelistBlockLimit(fl, cur) < next); |
| 239 | blockCur = blockNext; | 172 | prev = cur; |
| 173 | cur = next; | ||
| 240 | } | 174 | } |
| 241 | 175 | ||
| 242 | /* Now we know that range does not overlap with any block or grain, | 176 | /* Now we know that range does not overlap with any block, and if it |
| 243 | * and if it coalesces then it does so with blockPrev on the left, | 177 | * coalesces then it does so with prev on the left, and cur on the |
| 244 | * with blockCur on the right, with grainCur on either side, and/or | 178 | * right. |
| 245 | * with grainNext on the right. Try the grains first. | ||
| 246 | */ | 179 | */ |
| 247 | if (grainCur && limit == FreelistGrainBase(grainCur)) { | 180 | coalesceLeft = (prev && base == FreelistBlockLimit(fl, prev)); |
| 248 | /* Coalesce with grainCur on the right and delete grainCur */ | 181 | coalesceRight = (cur && limit == cur); |
| 249 | limit = FreelistGrainLimit(fl, grainCur); | ||
| 250 | freelistGrainSetPrevNext(fl, grainPrev, grainNext, -1); | ||
| 251 | |||
| 252 | } else if (grainCur && base == FreelistGrainLimit(fl, grainCur) | ||
| 253 | && grainNext && limit == FreelistGrainBase(grainNext)) { | ||
| 254 | /* Coalesce with grainCur on the left and grainNext on the right | ||
| 255 | * and delete both grains. */ | ||
| 256 | base = FreelistGrainBase(grainCur); | ||
| 257 | limit = FreelistGrainLimit(fl, grainNext); | ||
| 258 | freelistGrainSetPrevNext(fl, grainPrev, FreelistGrainNext(grainNext), -2); | ||
| 259 | |||
| 260 | } else if (grainCur && base == FreelistGrainLimit(fl, grainCur)) { | ||
| 261 | /* Coalesce with grainCur on the left and delete grainCur */ | ||
| 262 | base = FreelistGrainBase(grainCur); | ||
| 263 | freelistGrainSetPrevNext(fl, grainPrev, grainNext, -1); | ||
| 264 | } | ||
| 265 | |||
| 266 | /* now try to coalesce with blocks */ | ||
| 267 | coalesceLeft = (blockPrev && base == FreelistBlockLimit(blockPrev)); | ||
| 268 | coalesceRight = (blockCur && limit == FreelistBlockBase(blockCur)); | ||
| 269 | 182 | ||
| 270 | if (coalesceLeft && coalesceRight) { | 183 | if (coalesceLeft && coalesceRight) { |
| 271 | base = FreelistBlockBase(blockPrev); | 184 | base = prev; |
| 272 | limit = FreelistBlockLimit(blockCur); | 185 | limit = FreelistBlockLimit(fl, cur); |
| 273 | FreelistBlockSetLimit(blockPrev, limit); | 186 | FreelistBlockSetLimit(fl, prev, limit); |
| 274 | freelistBlockSetPrevNext(fl, blockPrev, blockNext, -1); | 187 | freelistBlockSetPrevNext(fl, prev, next, -1); |
| 275 | 188 | ||
| 276 | } else if (coalesceLeft) { | 189 | } else if (coalesceLeft) { |
| 277 | base = FreelistBlockBase(blockPrev); | 190 | base = prev; |
| 278 | FreelistBlockSetLimit(blockPrev, limit); | 191 | FreelistBlockSetLimit(fl, prev, limit); |
| 279 | 192 | ||
| 280 | } else if (coalesceRight) { | 193 | } else if (coalesceRight) { |
| 281 | limit = FreelistBlockLimit(blockCur); | 194 | limit = FreelistBlockLimit(fl, cur); |
| 282 | blockCur = FreelistBlockInit(base, limit); | 195 | cur = FreelistBlockInit(fl, base, limit); |
| 283 | FreelistBlockSetNext(blockCur, blockNext); | 196 | FreelistBlockSetNext(fl, cur, next); |
| 284 | |||
| 285 | } else if (size > FreelistGrainSize(fl)) { | ||
| 286 | /* failed to coalesce: add new block */ | ||
| 287 | blockNew = FreelistBlockInit(base, limit); | ||
| 288 | FreelistBlockSetNext(blockNew, blockCur); | ||
| 289 | freelistBlockSetPrevNext(fl, blockPrev, blockNew, +1); | ||
| 290 | 197 | ||
| 291 | } else { | 198 | } else { |
| 292 | /* failed to coalesce: add new grain */ | 199 | /* failed to coalesce: add new block */ |
| 293 | grainNew = FreelistGrainInit(fl, base, limit); | 200 | new = FreelistBlockInit(fl, base, limit); |
| 294 | FreelistGrainSetNext(grainNew, grainNext); | 201 | FreelistBlockSetNext(fl, new, cur); |
| 295 | freelistGrainSetPrevNext(fl, grainPrev, grainNew, +1); | 202 | freelistBlockSetPrevNext(fl, prev, new, +1); |
| 296 | } | 203 | } |
| 297 | 204 | ||
| 298 | RangeInit(rangeReturn, base, limit); | 205 | RangeInit(rangeReturn, base, limit); |
| @@ -300,34 +207,6 @@ Res FreelistInsert(Range rangeReturn, Freelist fl, Range range) | |||
| 300 | } | 207 | } |
| 301 | 208 | ||
| 302 | 209 | ||
| 303 | /* freelistInsertGrain -- Insert a grain (that is known to be isolated | ||
| 304 | * from all blocks and grains) into the free list. | ||
| 305 | */ | ||
| 306 | static void freelistInsertGrain(Freelist fl, FreelistGrain grain) | ||
| 307 | { | ||
| 308 | FreelistGrain prev, cur, next; | ||
| 309 | |||
| 310 | prev = NULL; | ||
| 311 | cur = fl->grainList; | ||
| 312 | while (cur) { | ||
| 313 | if (prev) | ||
| 314 | AVER(FreelistGrainLimit(fl, prev) < FreelistGrainBase(cur)); | ||
| 315 | if ((prev == NULL | ||
| 316 | || FreelistGrainLimit(fl, prev) < FreelistGrainBase(grain)) | ||
| 317 | && FreelistGrainLimit(fl, grain) < FreelistGrainBase(cur)) | ||
| 318 | break; | ||
| 319 | AVER(FreelistGrainLimit(fl, grain) != FreelistGrainBase(cur)); | ||
| 320 | AVER(FreelistGrainBase(grain) != FreelistGrainLimit(fl, cur)); | ||
| 321 | next = FreelistGrainNext(cur); | ||
| 322 | prev = cur; | ||
| 323 | cur = next; | ||
| 324 | } | ||
| 325 | |||
| 326 | FreelistGrainSetNext(grain, cur); | ||
| 327 | freelistGrainSetPrevNext(fl, prev, grain, +1); | ||
| 328 | } | ||
| 329 | |||
| 330 | |||
| 331 | /* freelistDeleteFromBlock -- delete 'range' from 'block' (it is known | 210 | /* freelistDeleteFromBlock -- delete 'range' from 'block' (it is known |
| 332 | * to be a subset of that block); update 'rangeReturn' to the original | 211 | * to be a subset of that block); update 'rangeReturn' to the original |
| 333 | * range of 'block' and update the block list accordingly: 'prev' is | 212 | * range of 'block' and update the block list accordingly: 'prev' is |
| @@ -335,103 +214,57 @@ static void freelistInsertGrain(Freelist fl, FreelistGrain grain) | |||
| 335 | * the first block on the list. | 214 | * the first block on the list. |
| 336 | */ | 215 | */ |
| 337 | static void freelistDeleteFromBlock(Range rangeReturn, Freelist fl, | 216 | static void freelistDeleteFromBlock(Range rangeReturn, Freelist fl, |
| 338 | Range range, FreelistBlock prev, | 217 | Range range, Addr prev, Addr block) |
| 339 | FreelistBlock block) | ||
| 340 | { | 218 | { |
| 341 | FreelistBlock next, blockNew; | 219 | Addr next, new; |
| 342 | Addr base, limit, blockBase, blockLimit; | 220 | Addr base, limit, blockBase, blockLimit; |
| 343 | 221 | ||
| 344 | AVER(rangeReturn != NULL); | 222 | AVER(rangeReturn != NULL); |
| 345 | AVERT(Freelist, fl); | 223 | AVERT(Freelist, fl); |
| 346 | AVERT(Range, range); | 224 | AVERT(Range, range); |
| 347 | AVER(RangeIsAligned(range, fl->alignment)); | 225 | AVER(RangeIsAligned(range, fl->alignment)); |
| 348 | AVER(prev == NULL || FreelistBlockNext(prev) == block); | 226 | AVER(prev == NULL || FreelistBlockNext(fl, prev) == block); |
| 349 | AVER(block != NULL); | 227 | AVER(block != NULL); |
| 350 | 228 | ||
| 351 | AVER(FreelistBlockBase(block) <= RangeBase(range)); | 229 | AVER(block <= RangeBase(range)); |
| 352 | AVER(RangeLimit(range) <= FreelistBlockLimit(block)); | 230 | AVER(RangeLimit(range) <= FreelistBlockLimit(fl, block)); |
| 353 | 231 | ||
| 354 | base = RangeBase(range); | 232 | base = RangeBase(range); |
| 355 | limit = RangeLimit(range); | 233 | limit = RangeLimit(range); |
| 356 | blockBase = FreelistBlockBase(block); | 234 | blockBase = block; |
| 357 | blockLimit = FreelistBlockLimit(block); | 235 | blockLimit = FreelistBlockLimit(fl, block); |
| 358 | next = FreelistBlockNext(block); | 236 | next = FreelistBlockNext(fl, block); |
| 359 | |||
| 360 | /* There are NINE (count 'em!) cases here, because on both sides | ||
| 361 | * the deletion might leave no fragment, a grain, or a block. */ | ||
| 362 | 237 | ||
| 363 | if (base == blockBase && limit == blockLimit) { | 238 | if (base == blockBase && limit == blockLimit) { |
| 364 | /* No fragment at left; no fragment at right. */ | 239 | /* No fragment at left; no fragment at right. */ |
| 365 | freelistBlockSetPrevNext(fl, prev, next, -1); | 240 | freelistBlockSetPrevNext(fl, prev, next, -1); |
| 366 | 241 | ||
| 367 | } else if (base == blockBase | ||
| 368 | && FreelistGrainLimit(fl, limit) == blockLimit) | ||
| 369 | { | ||
| 370 | /* No fragment at left; grain at right. */ | ||
| 371 | freelistBlockSetPrevNext(fl, prev, next, -1); | ||
| 372 | freelistInsertGrain(fl, FreelistGrainInit(fl, limit, blockLimit)); | ||
| 373 | |||
| 374 | } else if (base == blockBase) { | 242 | } else if (base == blockBase) { |
| 375 | /* No fragment at left; block at right. */ | 243 | /* No fragment at left; block at right. */ |
| 376 | block = FreelistBlockInit(limit, blockLimit); | 244 | block = FreelistBlockInit(fl, limit, blockLimit); |
| 377 | FreelistBlockSetNext(block, next); | 245 | FreelistBlockSetNext(fl, block, next); |
| 378 | freelistBlockSetPrevNext(fl, prev, block, 0); | 246 | freelistBlockSetPrevNext(fl, prev, block, 0); |
| 379 | 247 | ||
| 380 | } else if (FreelistGrainLimit(fl, blockBase) == base | ||
| 381 | && limit == blockLimit) | ||
| 382 | { | ||
| 383 | /* Grain at left; no fragment at right. */ | ||
| 384 | freelistBlockSetPrevNext(fl, prev, next, -1); | ||
| 385 | freelistInsertGrain(fl, FreelistGrainInit(fl, blockBase, base)); | ||
| 386 | |||
| 387 | } else if (limit == blockLimit) { | 248 | } else if (limit == blockLimit) { |
| 388 | /* Block at left; no frament at right. */ | 249 | /* Block at left; no fragment at right. */ |
| 389 | FreelistBlockSetLimit(block, base); | 250 | FreelistBlockSetLimit(fl, block, base); |
| 390 | |||
| 391 | } else if (FreelistGrainLimit(fl, blockBase) == base | ||
| 392 | && FreelistGrainLimit(fl, limit) == blockLimit) | ||
| 393 | { | ||
| 394 | /* Grain at left; grain at right. */ | ||
| 395 | freelistBlockSetPrevNext(fl, prev, next, -1); | ||
| 396 | freelistInsertGrain(fl, FreelistGrainInit(fl, blockBase, base)); | ||
| 397 | freelistInsertGrain(fl, FreelistGrainInit(fl, limit, blockLimit)); | ||
| 398 | |||
| 399 | } else if (FreelistGrainLimit(fl, blockBase) == base) { | ||
| 400 | /* Grain at left; block at right. */ | ||
| 401 | block = FreelistBlockInit(limit, blockLimit); | ||
| 402 | FreelistBlockSetNext(block, next); | ||
| 403 | freelistBlockSetPrevNext(fl, prev, block, 0); | ||
| 404 | freelistInsertGrain(fl, FreelistGrainInit(fl, blockBase, base)); | ||
| 405 | |||
| 406 | } else if (FreelistGrainLimit(fl, limit) == blockLimit) { | ||
| 407 | /* Block at left; grain at right. */ | ||
| 408 | AVER(FreelistGrainLimit(fl, blockBase) < base); | ||
| 409 | FreelistBlockSetLimit(block, base); | ||
| 410 | freelistInsertGrain(fl, FreelistGrainInit(fl, limit, blockLimit)); | ||
| 411 | 251 | ||
| 412 | } else { | 252 | } else { |
| 413 | /* Block at left; block at right. */ | 253 | /* Block at left; block at right. */ |
| 414 | FreelistBlockSetLimit(block, base); | 254 | FreelistBlockSetLimit(fl, block, base); |
| 415 | blockNew = FreelistBlockInit(limit, blockLimit); | 255 | new = FreelistBlockInit(fl, limit, blockLimit); |
| 416 | FreelistBlockSetNext(blockNew, next); | 256 | FreelistBlockSetNext(fl, new, next); |
| 417 | freelistBlockSetPrevNext(fl, block, blockNew, +1); | 257 | freelistBlockSetPrevNext(fl, block, new, +1); |
| 418 | } | 258 | } |
| 419 | 259 | ||
| 420 | RangeInit(rangeReturn, blockBase, blockLimit); | 260 | RangeInit(rangeReturn, blockBase, blockLimit); |
| 421 | } | 261 | } |
| 422 | 262 | ||
| 423 | 263 | ||
| 424 | /* freelistDeleteFromBlockList -- if 'range' is found in the block | 264 | Res FreelistDelete(Range rangeReturn, Freelist fl, Range range) |
| 425 | * list, delete it, update 'rangeReturn' to the range of the block | ||
| 426 | * that contained 'range' and return ResOK. Otherwise, return ResFAIL. | ||
| 427 | * (This might mean that the range was not found at all in the block | ||
| 428 | * list, or that it was only partially found.) | ||
| 429 | */ | ||
| 430 | static Res freelistDeleteFromBlockList(Range rangeReturn, Freelist fl, | ||
| 431 | Range range) | ||
| 432 | { | 265 | { |
| 433 | Res res; | 266 | Res res; |
| 434 | FreelistBlock prev, cur, next, blockNew; | 267 | Addr prev, cur, next, new; |
| 435 | Addr base, limit; | 268 | Addr base, limit; |
| 436 | 269 | ||
| 437 | AVER(rangeReturn != NULL); | 270 | AVER(rangeReturn != NULL); |
| @@ -442,12 +275,11 @@ static Res freelistDeleteFromBlockList(Range rangeReturn, Freelist fl, | |||
| 442 | limit = RangeLimit(range); | 275 | limit = RangeLimit(range); |
| 443 | 276 | ||
| 444 | prev = NULL; | 277 | prev = NULL; |
| 445 | cur = fl->blockList; | 278 | cur = fl->list; |
| 446 | while (cur) { | 279 | while (cur) { |
| 447 | Addr blockBase, blockLimit; | 280 | Addr blockBase, blockLimit; |
| 448 | AVERT(FreelistBlock, cur); | 281 | blockBase = cur; |
| 449 | blockBase = FreelistBlockBase(cur); | 282 | blockLimit = FreelistBlockLimit(fl, cur); |
| 450 | blockLimit = FreelistBlockLimit(cur); | ||
| 451 | 283 | ||
| 452 | if (limit <= blockBase) | 284 | if (limit <= blockBase) |
| 453 | return ResFAIL; /* not found */ | 285 | return ResFAIL; /* not found */ |
| @@ -458,7 +290,7 @@ static Res freelistDeleteFromBlockList(Range rangeReturn, Freelist fl, | |||
| 458 | return ResOK; | 290 | return ResOK; |
| 459 | } | 291 | } |
| 460 | 292 | ||
| 461 | next = FreelistBlockNext(cur); | 293 | next = FreelistBlockNext(fl, cur); |
| 462 | prev = cur; | 294 | prev = cur; |
| 463 | cur = next; | 295 | cur = next; |
| 464 | } | 296 | } |
| @@ -468,118 +300,29 @@ static Res freelistDeleteFromBlockList(Range rangeReturn, Freelist fl, | |||
| 468 | } | 300 | } |
| 469 | 301 | ||
| 470 | 302 | ||
| 471 | /* freelistDeleteFromGrainList -- if 'range' is found in the grain | ||
| 472 | * list, delete it, update 'rangeReturn' to the range of the grain | ||
| 473 | * that contained 'range' and return ResOK. Otherwise, return ResFAIL. | ||
| 474 | */ | ||
| 475 | static Res freelistDeleteFromGrainList(Range rangeReturn, Freelist fl, | ||
| 476 | Range range) | ||
| 477 | { | ||
| 478 | Addr base, limit; | ||
| 479 | FreelistGrain prev, cur, next; | ||
| 480 | |||
| 481 | AVER(rangeReturn != NULL); | ||
| 482 | AVERT(Freelist, fl); | ||
| 483 | AVERT(Range, range); | ||
| 484 | |||
| 485 | if (RangeSize(range) != FreelistGrainSize(fl)) | ||
| 486 | return ResFAIL; | ||
| 487 | |||
| 488 | base = RangeBase(range); | ||
| 489 | limit = RangeLimit(range); | ||
| 490 | |||
| 491 | prev = NULL; | ||
| 492 | cur = fl->grainList; | ||
| 493 | while (cur) { | ||
| 494 | Addr grainBase, grainLimit; | ||
| 495 | grainBase = FreelistGrainBase(cur); | ||
| 496 | grainLimit = FreelistGrainLimit(fl, cur); | ||
| 497 | next = FreelistGrainNext(cur); | ||
| 498 | |||
| 499 | if (prev != NULL) | ||
| 500 | AVER(FreelistGrainLimit(fl, prev) < grainBase); | ||
| 501 | if (limit <= grainBase) | ||
| 502 | return ResFAIL; /* not found */ | ||
| 503 | if (base == grainBase && limit == grainLimit) { | ||
| 504 | freelistGrainSetPrevNext(fl, prev, next, -1); | ||
| 505 | RangeInit(rangeReturn, grainBase, grainLimit); | ||
| 506 | return ResOK; | ||
| 507 | } | ||
| 508 | /* Partial overlap can't happen if everything's aligned. */ | ||
| 509 | AVER(base >= grainLimit); | ||
| 510 | |||
| 511 | prev = cur; | ||
| 512 | cur = next; | ||
| 513 | } | ||
| 514 | |||
| 515 | return ResFAIL; /* not found */ | ||
| 516 | } | ||
| 517 | |||
| 518 | |||
| 519 | Res FreelistDelete(Range rangeReturn, Freelist fl, Range range) | ||
| 520 | { | ||
| 521 | Res res; | ||
| 522 | |||
| 523 | AVER(rangeReturn != NULL); | ||
| 524 | AVERT(Freelist, fl); | ||
| 525 | AVERT(Range, range); | ||
| 526 | AVER(RangeIsAligned(range, fl->alignment)); | ||
| 527 | |||
| 528 | if (RangeSize(range) == FreelistGrainSize(fl)) { | ||
| 529 | res = freelistDeleteFromGrainList(rangeReturn, fl, range); | ||
| 530 | } else { | ||
| 531 | res = freelistDeleteFromBlockList(rangeReturn, fl, range); | ||
| 532 | } | ||
| 533 | return res; | ||
| 534 | } | ||
| 535 | |||
| 536 | |||
| 537 | void FreelistIterate(Freelist fl, FreelistIterateMethod iterate, | 303 | void FreelistIterate(Freelist fl, FreelistIterateMethod iterate, |
| 538 | void *closureP, Size closureS) | 304 | void *closureP, Size closureS) |
| 539 | { | 305 | { |
| 540 | FreelistBlock blockPrev, blockCur, blockNext; | 306 | Addr prev, cur, next; |
| 541 | FreelistGrain grainPrev, grainCur, grainNext; | ||
| 542 | 307 | ||
| 543 | AVERT(Freelist, fl); | 308 | AVERT(Freelist, fl); |
| 544 | AVER(FUNCHECK(iterate)); | 309 | AVER(FUNCHECK(iterate)); |
| 545 | 310 | ||
| 546 | blockPrev = NULL; | 311 | prev = NULL; |
| 547 | blockCur = fl->blockList; | 312 | cur = fl->list; |
| 548 | grainPrev = NULL; | 313 | while (cur) { |
| 549 | grainCur = fl->grainList; | ||
| 550 | while (blockCur || grainCur) { | ||
| 551 | Bool delete = FALSE; | 314 | Bool delete = FALSE; |
| 552 | RangeStruct range; | 315 | RangeStruct range; |
| 553 | Bool cont; | 316 | Bool cont; |
| 554 | if (blockCur == NULL || (void *)grainCur < (void *)blockCur) { | 317 | RangeInit(&range, cur, FreelistBlockLimit(fl, cur)); |
| 555 | AVER(grainCur); | 318 | cont = (*iterate)(&delete, &range, closureP, closureS); |
| 556 | RangeInit(&range, FreelistGrainBase(grainCur), | 319 | next = FreelistBlockNext(fl, cur); |
| 557 | FreelistGrainLimit(fl, grainCur)); | 320 | if (delete) { |
| 558 | cont = (*iterate)(&delete, &range, closureP, closureS); | 321 | freelistBlockSetPrevNext(fl, prev, next, -1); |
| 559 | AVERT(Bool, cont); | ||
| 560 | AVERT(Bool, delete); | ||
| 561 | grainNext = FreelistGrainNext(grainCur); | ||
| 562 | if (delete) { | ||
| 563 | freelistGrainSetPrevNext(fl, grainPrev, grainNext, -1); | ||
| 564 | } else { | ||
| 565 | grainPrev = grainCur; | ||
| 566 | } | ||
| 567 | grainCur = grainNext; | ||
| 568 | } else { | 322 | } else { |
| 569 | AVER(blockCur); | 323 | prev = cur; |
| 570 | RangeInit(&range, FreelistBlockBase(blockCur), | ||
| 571 | FreelistBlockLimit(blockCur)); | ||
| 572 | cont = (*iterate)(&delete, &range, closureP, closureS); | ||
| 573 | AVERT(Bool, cont); | ||
| 574 | AVERT(Bool, delete); | ||
| 575 | blockNext = FreelistBlockNext(blockCur); | ||
| 576 | if (delete) { | ||
| 577 | freelistBlockSetPrevNext(fl, blockPrev, blockNext, -1); | ||
| 578 | } else { | ||
| 579 | blockPrev = blockCur; | ||
| 580 | } | ||
| 581 | blockCur = blockNext; | ||
| 582 | } | 324 | } |
| 325 | cur = next; | ||
| 583 | if (!cont) | 326 | if (!cont) |
| 584 | break; | 327 | break; |
| 585 | } | 328 | } |
| @@ -597,22 +340,22 @@ void FreelistIterate(Freelist fl, FreelistIterateMethod iterate, | |||
| 597 | static void freelistFindDeleteFromBlock(Range rangeReturn, Range oldRangeReturn, | 340 | static void freelistFindDeleteFromBlock(Range rangeReturn, Range oldRangeReturn, |
| 598 | Freelist fl, Size size, | 341 | Freelist fl, Size size, |
| 599 | FindDelete findDelete, | 342 | FindDelete findDelete, |
| 600 | FreelistBlock prev, FreelistBlock block) | 343 | Addr prev, Addr block) |
| 601 | { | 344 | { |
| 602 | Bool callDelete = TRUE; | 345 | Bool callDelete = TRUE; |
| 603 | Addr base, limit; | 346 | Addr base, limit; |
| 604 | 347 | ||
| 605 | AVER(rangeReturn != NULL); | 348 | AVER(rangeReturn != NULL); |
| 606 | AVER(oldRangeReturn != NULL); | 349 | AVER(oldRangeReturn != NULL); |
| 607 | AVER(SizeIsAligned(size, fl->alignment)); | ||
| 608 | AVERT(Freelist, fl); | 350 | AVERT(Freelist, fl); |
| 351 | AVER(SizeIsAligned(size, fl->alignment)); | ||
| 609 | AVERT(FindDelete, findDelete); | 352 | AVERT(FindDelete, findDelete); |
| 610 | AVER(prev == NULL || FreelistBlockNext(prev) == block); | 353 | AVER(prev == NULL || FreelistBlockNext(fl, prev) == block); |
| 611 | AVER(block != NULL); | 354 | AVER(block != NULL); |
| 612 | AVER(FreelistBlockSize(block) >= size); | 355 | AVER(FreelistBlockSize(fl, block) >= size); |
| 613 | 356 | ||
| 614 | base = FreelistBlockBase(block); | 357 | base = block; |
| 615 | limit = FreelistBlockLimit(block); | 358 | limit = FreelistBlockLimit(fl, block); |
| 616 | 359 | ||
| 617 | switch (findDelete) { | 360 | switch (findDelete) { |
| 618 | case FindDeleteNONE: | 361 | case FindDeleteNONE: |
| @@ -645,42 +388,11 @@ static void freelistFindDeleteFromBlock(Range rangeReturn, Range oldRangeReturn, | |||
| 645 | } | 388 | } |
| 646 | 389 | ||
| 647 | 390 | ||
| 648 | /* freelistTakeGrain -- If there are any grains in the free list, find | ||
| 649 | * the first grain; return its range in 'rangeReturn' and | ||
| 650 | * 'oldRangeReturn'; possibly delete it from the list according to the | ||
| 651 | * instruction in 'findDelete'; and return TRUE. If the grain list is | ||
| 652 | * empty, return FALSE. | ||
| 653 | */ | ||
| 654 | static Bool freelistTakeGrain(Range rangeReturn, Range oldRangeReturn, | ||
| 655 | Freelist fl, FindDelete findDelete) | ||
| 656 | { | ||
| 657 | FreelistGrain grain; | ||
| 658 | |||
| 659 | AVER(rangeReturn != NULL); | ||
| 660 | AVER(oldRangeReturn != NULL); | ||
| 661 | AVERT(Freelist, fl); | ||
| 662 | AVERT(FindDelete, findDelete); | ||
| 663 | |||
| 664 | grain = fl->grainList; | ||
| 665 | if (grain) { | ||
| 666 | RangeInit(rangeReturn, FreelistGrainBase(grain), | ||
| 667 | FreelistGrainLimit(fl, grain)); | ||
| 668 | RangeInit(oldRangeReturn, FreelistGrainBase(grain), | ||
| 669 | FreelistGrainLimit(fl, grain)); | ||
| 670 | if (findDelete != FindDeleteNONE) | ||
| 671 | freelistGrainSetPrevNext(fl, NULL, FreelistGrainNext(grain), -1); | ||
| 672 | return TRUE; | ||
| 673 | } | ||
| 674 | |||
| 675 | return FALSE; | ||
| 676 | } | ||
| 677 | |||
| 678 | |||
| 679 | Bool FreelistFind(Range rangeReturn, Range oldRangeReturn, | 391 | Bool FreelistFind(Range rangeReturn, Range oldRangeReturn, |
| 680 | Freelist fl, Size size, FindDelete findDelete) | 392 | Freelist fl, Size size, FindDelete findDelete) |
| 681 | { | 393 | { |
| 682 | Res res; | 394 | Res res; |
| 683 | FreelistBlock blockPrev, blockCur, blockNext; | 395 | Addr prev, cur, next; |
| 684 | 396 | ||
| 685 | AVER(rangeReturn != NULL); | 397 | AVER(rangeReturn != NULL); |
| 686 | AVER(oldRangeReturn != NULL); | 398 | AVER(oldRangeReturn != NULL); |
| @@ -688,20 +400,17 @@ Bool FreelistFind(Range rangeReturn, Range oldRangeReturn, | |||
| 688 | AVER(SizeIsAligned(size, fl->alignment)); | 400 | AVER(SizeIsAligned(size, fl->alignment)); |
| 689 | AVERT(FindDelete, findDelete); | 401 | AVERT(FindDelete, findDelete); |
| 690 | 402 | ||
| 691 | if (size == FreelistGrainSize(fl)) | 403 | prev = NULL; |
| 692 | return freelistTakeGrain(rangeReturn, oldRangeReturn, fl, findDelete); | 404 | cur = fl->list; |
| 693 | 405 | while (cur) { | |
| 694 | blockPrev = NULL; | 406 | if (FreelistBlockSize(fl, cur) >= size) { |
| 695 | blockCur = fl->blockList; | ||
| 696 | while (blockCur) { | ||
| 697 | if (FreelistBlockSize(blockCur) >= size) { | ||
| 698 | freelistFindDeleteFromBlock(rangeReturn, oldRangeReturn, fl, size, | 407 | freelistFindDeleteFromBlock(rangeReturn, oldRangeReturn, fl, size, |
| 699 | findDelete, blockPrev, blockCur); | 408 | findDelete, prev, cur); |
| 700 | return TRUE; | 409 | return TRUE; |
| 701 | } | 410 | } |
| 702 | blockNext = FreelistBlockNext(blockCur); | 411 | next = FreelistBlockNext(fl, cur); |
| 703 | blockPrev = blockCur; | 412 | prev = cur; |
| 704 | blockCur = blockNext; | 413 | cur = next; |
| 705 | } | 414 | } |
| 706 | 415 | ||
| 707 | return FALSE; | 416 | return FALSE; |
| @@ -713,36 +422,35 @@ Bool FreelistFindLargest(Range rangeReturn, Range oldRangeReturn, | |||
| 713 | { | 422 | { |
| 714 | Bool found = FALSE; | 423 | Bool found = FALSE; |
| 715 | Size size = 0; | 424 | Size size = 0; |
| 716 | FreelistBlock blockPrev, blockCur, blockNext; | 425 | Addr prev, cur, next; |
| 717 | FreelistBlock bestBlockPrev, bestBlockCur; | 426 | Addr bestPrev, bestCur; |
| 718 | 427 | ||
| 719 | AVER(rangeReturn != NULL); | 428 | AVER(rangeReturn != NULL); |
| 720 | AVER(oldRangeReturn != NULL); | 429 | AVER(oldRangeReturn != NULL); |
| 721 | AVERT(Freelist, fl); | 430 | AVERT(Freelist, fl); |
| 722 | AVERT(FindDelete, findDelete); | 431 | AVERT(FindDelete, findDelete); |
| 723 | 432 | ||
| 724 | blockPrev = NULL; | 433 | prev = NULL; |
| 725 | blockCur = fl->blockList; | 434 | cur = fl->list; |
| 726 | while (blockCur) { | 435 | while (cur) { |
| 727 | if (FreelistBlockSize(blockCur) > size) { | 436 | if (FreelistBlockSize(fl, cur) > size) { |
| 728 | found = TRUE; | 437 | found = TRUE; |
| 729 | size = FreelistBlockSize(blockCur); | 438 | size = FreelistBlockSize(fl, cur); |
| 730 | bestBlockPrev = blockPrev; | 439 | bestPrev = prev; |
| 731 | bestBlockCur = blockCur; | 440 | bestCur = cur; |
| 732 | } | 441 | } |
| 733 | blockNext = FreelistBlockNext(blockCur); | 442 | next = FreelistBlockNext(fl, cur); |
| 734 | blockPrev = blockCur; | 443 | prev = cur; |
| 735 | blockCur = blockNext; | 444 | cur = next; |
| 736 | } | 445 | } |
| 737 | 446 | ||
| 738 | if (found) { | 447 | if (found) { |
| 739 | /* No need to search the grain list. */ | ||
| 740 | freelistFindDeleteFromBlock(rangeReturn, oldRangeReturn, fl, size, | 448 | freelistFindDeleteFromBlock(rangeReturn, oldRangeReturn, fl, size, |
| 741 | findDelete, bestBlockPrev, bestBlockCur); | 449 | findDelete, bestPrev, bestCur); |
| 742 | return TRUE; | 450 | return TRUE; |
| 743 | } | 451 | } |
| 744 | 452 | ||
| 745 | return freelistTakeGrain(rangeReturn, oldRangeReturn, fl, findDelete); | 453 | return FALSE; |
| 746 | } | 454 | } |
| 747 | 455 | ||
| 748 | 456 | ||
| @@ -780,8 +488,7 @@ Res FreelistDescribe(Freelist fl, mps_lib_FILE *stream) | |||
| 780 | res = WriteF(stream, | 488 | res = WriteF(stream, |
| 781 | "Freelist $P {\n", (WriteFP)fl, | 489 | "Freelist $P {\n", (WriteFP)fl, |
| 782 | " alignment = $U\n", (WriteFU)fl->alignment, | 490 | " alignment = $U\n", (WriteFU)fl->alignment, |
| 783 | " blockListSize = $U\n", (WriteFU)fl->blockListSize, | 491 | " listSize = $U\n", (WriteFU)fl->listSize, |
| 784 | " grainListSize = $U\n", (WriteFU)fl->grainListSize, | ||
| 785 | NULL); | 492 | NULL); |
| 786 | 493 | ||
| 787 | FreelistIterate(fl, freelistDescribeIterateMethod, stream, 0); | 494 | FreelistIterate(fl, freelistDescribeIterateMethod, stream, 0); |
diff --git a/mps/code/freelist.h b/mps/code/freelist.h index b0f047840a3..467ed80f3c2 100644 --- a/mps/code/freelist.h +++ b/mps/code/freelist.h | |||
| @@ -15,8 +15,6 @@ | |||
| 15 | #define FreelistSig ((Sig)0x519F6331) /* SIGnature FREEL */ | 15 | #define FreelistSig ((Sig)0x519F6331) /* SIGnature FREEL */ |
| 16 | 16 | ||
| 17 | typedef struct FreelistStruct *Freelist; | 17 | typedef struct FreelistStruct *Freelist; |
| 18 | typedef struct FreelistBlockStruct *FreelistBlock; | ||
| 19 | typedef struct FreelistGrainStruct *FreelistGrain; | ||
| 20 | 18 | ||
| 21 | typedef Bool (*FreelistIterateMethod)(Bool *deleteReturn, Range range, | 19 | typedef Bool (*FreelistIterateMethod)(Bool *deleteReturn, Range range, |
| 22 | void *closureP, Size closureS); | 20 | void *closureP, Size closureS); |
| @@ -24,10 +22,8 @@ typedef Bool (*FreelistIterateMethod)(Bool *deleteReturn, Range range, | |||
| 24 | typedef struct FreelistStruct { | 22 | typedef struct FreelistStruct { |
| 25 | Sig sig; | 23 | Sig sig; |
| 26 | Align alignment; | 24 | Align alignment; |
| 27 | FreelistBlock blockList; | 25 | Addr list; |
| 28 | Count blockListSize; | 26 | Count listSize; |
| 29 | FreelistGrain grainList; | ||
| 30 | Count grainListSize; | ||
| 31 | } FreelistStruct; | 27 | } FreelistStruct; |
| 32 | 28 | ||
| 33 | extern Bool FreelistCheck(Freelist fl); | 29 | extern Bool FreelistCheck(Freelist fl); |