aboutsummaryrefslogtreecommitdiffstats
path: root/mps/code
diff options
context:
space:
mode:
authorGareth Rees2013-05-19 14:27:24 +0100
committerGareth Rees2013-05-19 14:27:24 +0100
commit217831cc47e7b2a4c02513cd8f3dddf32604faa5 (patch)
tree5c6607ef92d226e592c48531423ef675987fd8b8 /mps/code
parent5e28a693442a77bb9d0adb1b00216c50cf6724d4 (diff)
downloademacs-217831cc47e7b2a4c02513cd8f3dddf32604faa5.tar.gz
emacs-217831cc47e7b2a4c02513cd8f3dddf32604faa5.zip
Remove "emergency" free list allocator from the cbs module (it belongs in its own module) and update clients and the design accordingly.
Copied from Perforce Change: 181927 ServerID: perforce.ravenbrook.com
Diffstat (limited to 'mps/code')
-rw-r--r--mps/code/cbs.c613
-rw-r--r--mps/code/cbs.h15
-rw-r--r--mps/code/cbstest.c2
-rw-r--r--mps/code/poolmv2.c2
-rw-r--r--mps/code/poolmvff.c6
5 files changed, 9 insertions, 629 deletions
diff --git a/mps/code/cbs.c b/mps/code/cbs.c
index a9cb0d0b087..f40d075b27e 100644
--- a/mps/code/cbs.c
+++ b/mps/code/cbs.c
@@ -21,9 +21,6 @@
21SRCID(cbs, "$Id$"); 21SRCID(cbs, "$Id$");
22 22
23 23
24/* See <design/cbs/#align> */
25#define cbsMinimumAlignment ((Align)sizeof(void *))
26
27#define cbsOfSplayTree(tree) PARENT(CBSStruct, splayTree, (tree)) 24#define cbsOfSplayTree(tree) PARENT(CBSStruct, splayTree, (tree))
28#define cbsBlockOfSplayNode(node) PARENT(CBSBlockStruct, splayNode, (node)) 25#define cbsBlockOfSplayNode(node) PARENT(CBSBlockStruct, splayNode, (node))
29#define splayTreeOfCBS(tree) (&((cbs)->splayTree)) 26#define splayTreeOfCBS(tree) (&((cbs)->splayTree))
@@ -31,55 +28,6 @@ SRCID(cbs, "$Id$");
31#define keyOfCBSBlock(block) ((void *)&((block)->base)) 28#define keyOfCBSBlock(block) ((void *)&((block)->base))
32 29
33 30
34/* CBSEmergencyBlock* -- Getters and setters for emergency blocks
35 *
36 * See <design/cbs/#impl.low-mem.inline.block>.
37 */
38
39#define CBSEmergencyBlockBase(block) ((Addr)(block))
40#define CBSEmergencyBlockLimit(block) ((Addr)((block)[1]))
41#define CBSEmergencyBlockSize(block) \
42 (AddrOffset(CBSEmergencyBlockBase(block), CBSEmergencyBlockLimit(block)))
43#define CBSEmergencyBlockNext(block) ((CBSEmergencyBlock)((block)[0]))
44
45#define CBSEmergencyBlockSetNext(block, next) \
46 BEGIN (block)[0] = (void *)(next); END
47#define CBSEmergencyBlockSetLimit(block, limit) \
48 BEGIN (block)[1] = (void *)(limit); END
49
50
51/* CBSEmergencyGrain* -- Getters and setters for emergency grains
52 *
53 * See <design/cbs/#impl.low-mem.inline.grain>.
54 */
55
56#define CBSEmergencyGrainBase(grain) ((Addr)(grain))
57#define CBSEmergencyGrainLimit(cbs, grain) \
58 AddrAdd(CBSEmergencyGrainBase(grain), CBSEmergencyGrainSize(cbs))
59#define CBSEmergencyGrainSize(cbs) ((cbs)->alignment)
60#define CBSEmergencyGrainNext(grain) ((CBSEmergencyGrain)((grain)[0]))
61
62#define CBSEmergencyGrainSetNext(grain, next) \
63 BEGIN (grain)[0] = (void *)(next); END
64
65
66static CBSEmergencyBlock CBSEmergencyBlockInit(Addr base, Addr limit)
67{
68 CBSEmergencyBlock block = (CBSEmergencyBlock)base;
69 CBSEmergencyBlockSetNext(block, NULL);
70 CBSEmergencyBlockSetLimit(block, limit);
71 return block;
72}
73
74static CBSEmergencyGrain CBSEmergencyGrainInit(CBS cbs, Addr base, Addr limit)
75{
76 CBSEmergencyGrain grain = (CBSEmergencyGrain)base;
77 AVER(AddrOffset(base, limit) == CBSEmergencyGrainSize(cbs));
78 CBSEmergencyGrainSetNext(grain, NULL);
79 return grain;
80}
81
82
83/* CBSEnter, CBSLeave -- Avoid re-entrance 31/* CBSEnter, CBSLeave -- Avoid re-entrance
84 * 32 *
85 * .enter-leave: The callbacks are restricted in what they may call. 33 * .enter-leave: The callbacks are restricted in what they may call.
@@ -115,20 +63,12 @@ Bool CBSCheck(CBS cbs)
115 CHECKL(SplayTreeCheck(splayTreeOfCBS(cbs))); 63 CHECKL(SplayTreeCheck(splayTreeOfCBS(cbs)));
116 /* nothing to check about splayTreeSize */ 64 /* nothing to check about splayTreeSize */
117 CHECKD(Pool, cbs->blockPool); 65 CHECKD(Pool, cbs->blockPool);
118 CHECKL(BoolCheck(cbs->mayUseInline));
119 CHECKL(BoolCheck(cbs->fastFind)); 66 CHECKL(BoolCheck(cbs->fastFind));
120 CHECKL(BoolCheck(cbs->inCBS)); 67 CHECKL(BoolCheck(cbs->inCBS));
121 CHECKL(cbs->new == NULL || FUNCHECK(cbs->new)); 68 CHECKL(cbs->new == NULL || FUNCHECK(cbs->new));
122 CHECKL(cbs->delete == NULL || FUNCHECK(cbs->delete)); 69 CHECKL(cbs->delete == NULL || FUNCHECK(cbs->delete));
123 CHECKL(cbs->grow == NULL || FUNCHECK(cbs->grow)); 70 CHECKL(cbs->grow == NULL || FUNCHECK(cbs->grow));
124 CHECKL(cbs->shrink == NULL || FUNCHECK(cbs->shrink)); 71 CHECKL(cbs->shrink == NULL || FUNCHECK(cbs->shrink));
125 CHECKL(cbs->mayUseInline || cbs->emergencyBlockList == NULL);
126 CHECKL(cbs->mayUseInline || cbs->emergencyGrainList == NULL);
127 /* See <design/cbs/#align> */
128 CHECKL(!cbs->mayUseInline ||
129 AlignIsAligned(cbs->alignment, cbsMinimumAlignment));
130 /* can't check emergencyBlockList or emergencyGrainList more */
131 /* Checking eblSize and eglSize is too laborious without a List ADT */
132 /* No MeterCheck */ 72 /* No MeterCheck */
133 73
134 return TRUE; 74 return TRUE;
@@ -270,19 +210,13 @@ Res CBSInit(Arena arena, CBS cbs, void *owner,
270 CBSChangeSizeMethod new, CBSChangeSizeMethod delete, 210 CBSChangeSizeMethod new, CBSChangeSizeMethod delete,
271 CBSChangeSizeMethod grow, CBSChangeSizeMethod shrink, 211 CBSChangeSizeMethod grow, CBSChangeSizeMethod shrink,
272 Size minSize, Align alignment, 212 Size minSize, Align alignment,
273 Bool mayUseInline, Bool fastFind) 213 Bool fastFind)
274{ 214{
275 Res res; 215 Res res;
276 216
277 AVERT(Arena, arena); 217 AVERT(Arena, arena);
278 AVER(new == NULL || FUNCHECK(new)); 218 AVER(new == NULL || FUNCHECK(new));
279 AVER(delete == NULL || FUNCHECK(delete)); 219 AVER(delete == NULL || FUNCHECK(delete));
280 AVER(BoolCheck(mayUseInline));
281 if (mayUseInline) {
282 /* See <design/cbs/#align> */
283 if (!AlignIsAligned(alignment, cbsMinimumAlignment))
284 return ResPARAM;
285 }
286 220
287 SplayTreeInit(splayTreeOfCBS(cbs), &cbsSplayCompare, 221 SplayTreeInit(splayTreeOfCBS(cbs), &cbsSplayCompare,
288 fastFind ? &cbsUpdateNode : NULL); 222 fastFind ? &cbsUpdateNode : NULL);
@@ -297,18 +231,11 @@ Res CBSInit(Arena arena, CBS cbs, void *owner,
297 cbs->grow = grow; 231 cbs->grow = grow;
298 cbs->shrink = shrink; 232 cbs->shrink = shrink;
299 cbs->minSize = minSize; 233 cbs->minSize = minSize;
300 cbs->mayUseInline = mayUseInline;
301 cbs->fastFind = fastFind; 234 cbs->fastFind = fastFind;
302 cbs->alignment = alignment; 235 cbs->alignment = alignment;
303 cbs->inCBS = TRUE; 236 cbs->inCBS = TRUE;
304 cbs->emergencyBlockList = NULL;
305 cbs->eblSize = 0;
306 cbs->emergencyGrainList = NULL;
307 cbs->eglSize = 0;
308 237
309 METER_INIT(cbs->splaySearch, "size of splay tree", (void *)cbs); 238 METER_INIT(cbs->splaySearch, "size of splay tree", (void *)cbs);
310 METER_INIT(cbs->eblSearch, "size of emergencyBlockList", (void *)cbs);
311 METER_INIT(cbs->eglSearch, "size of emergencyGrainList", (void *)cbs);
312 239
313 cbs->sig = CBSSig; 240 cbs->sig = CBSSig;
314 241
@@ -330,15 +257,11 @@ void CBSFinish(CBS cbs)
330 CBSEnter(cbs); 257 CBSEnter(cbs);
331 258
332 METER_EMIT(&cbs->splaySearch); 259 METER_EMIT(&cbs->splaySearch);
333 METER_EMIT(&cbs->eblSearch);
334 METER_EMIT(&cbs->eglSearch);
335 260
336 cbs->sig = SigInvalid; 261 cbs->sig = SigInvalid;
337 262
338 SplayTreeFinish(splayTreeOfCBS(cbs)); 263 SplayTreeFinish(splayTreeOfCBS(cbs));
339 PoolDestroy(cbs->blockPool); 264 PoolDestroy(cbs->blockPool);
340 cbs->emergencyBlockList = NULL;
341 cbs->emergencyGrainList = NULL;
342} 265}
343 266
344 267
@@ -557,275 +480,6 @@ fail:
557} 480}
558 481
559 482
560/* cbsCoalesceWithEmergencyLists -- coalesce received range with EBL and EGL
561 *
562 * Attempts to extend the range about to be freed by adding ranges from
563 * the emergency lists. May remove blocks from the emergency list.
564 */
565
566static Res cbsCoalesceWithEmergencyLists(Addr *baseIO, Addr *limitIO, CBS cbs)
567{
568 Addr base, limit;
569 Count nCoalescences = 0;
570
571 AVER(baseIO != NULL);
572 AVER(limitIO != NULL);
573 AVERT(CBS, cbs);
574 AVER(cbs->mayUseInline);
575
576 base = *baseIO;
577 limit = *limitIO;
578 AVER(base < limit);
579
580 if (cbs->emergencyBlockList != NULL) {
581 CBSEmergencyBlock prev, block, next;
582 Addr blockBase, blockLimit;
583
584 METER_ACC(cbs->eblSearch, cbs->eblSize);
585 for(block = cbs->emergencyBlockList, prev = NULL;
586 block != NULL && CBSEmergencyBlockBase(block) <= limit;
587 block = CBSEmergencyBlockNext(block)) {
588
589 blockBase = CBSEmergencyBlockBase(block);
590 blockLimit = CBSEmergencyBlockLimit(block);
591 AVER(blockBase < blockLimit);
592
593 if (prev != NULL)
594 AVER(CBSEmergencyBlockLimit(prev) < blockBase);
595
596 if (blockLimit == base) {
597 base = blockBase;
598 next = CBSEmergencyBlockNext(block);
599 if (prev == NULL)
600 cbs->emergencyBlockList = next;
601 else
602 CBSEmergencyBlockSetNext(prev, next);
603 ++nCoalescences;
604 STATISTIC(--cbs->eblSize);
605 AVER(cbs->emergencyBlockList != NULL || cbs->eblSize == 0);
606 } else if (blockBase == limit) {
607 limit = blockLimit;
608 next = CBSEmergencyBlockNext(block);
609 if (prev == NULL)
610 cbs->emergencyBlockList = next;
611 else
612 CBSEmergencyBlockSetNext(prev, next);
613 ++nCoalescences;
614 STATISTIC(--cbs->eblSize);
615 AVER(cbs->emergencyBlockList != NULL || cbs->eblSize == 0);
616 /* For loop will stop at next test */
617 } else if (blockLimit > base) {
618 return ResFAIL; /* range intersects block */
619 } else {
620 prev = block; /* Only move prev if we didn't delete */
621 }
622 }
623 /* block's next is still valid, even if it's been coalesced */
624 }
625
626 if (cbs->emergencyGrainList != NULL) {
627 CBSEmergencyGrain prev, grain, next;
628 Addr grainBase, grainLimit;
629
630 METER_ACC(cbs->eglSearch, cbs->eglSize);
631 for(grain = cbs->emergencyGrainList, prev = NULL;
632 grain != NULL && CBSEmergencyGrainBase(grain) <= limit &&
633 nCoalescences < 2;
634 grain = CBSEmergencyGrainNext(grain)) {
635 grainBase = CBSEmergencyGrainBase(grain);
636 grainLimit = CBSEmergencyGrainLimit(cbs, grain);
637 AVER(grainBase < grainLimit);
638
639 if (prev != NULL)
640 AVER(CBSEmergencyGrainLimit(cbs, prev) < grainBase);
641
642 if (grainLimit == base) {
643 base = grainBase;
644 next = CBSEmergencyGrainNext(grain);
645 if (prev == NULL)
646 cbs->emergencyGrainList = next;
647 else
648 CBSEmergencyGrainSetNext(prev, next);
649 ++nCoalescences;
650 STATISTIC(--cbs->eglSize);
651 AVER(cbs->emergencyGrainList != NULL || cbs->eglSize == 0);
652 } else if (grainBase == limit) {
653 limit = grainLimit;
654 next = CBSEmergencyGrainNext(grain);
655 if (prev == NULL)
656 cbs->emergencyGrainList = next;
657 else
658 CBSEmergencyGrainSetNext(prev, next);
659 ++nCoalescences;
660 STATISTIC(--cbs->eglSize);
661 AVER(cbs->emergencyGrainList != NULL || cbs->eglSize == 0);
662 break;
663 } else if (grainLimit > base) {
664 return ResFAIL; /* range intersects grain */
665 } else {
666 prev = grain;
667 }
668 }
669 /* grain's next is still valid, even if it's been coalesced */
670 }
671
672 /* Because the lists are known to have isolated ranges, there can */
673 /* be no more than 2 coalescences. */
674 AVER(nCoalescences <= 2);
675
676 *baseIO = base;
677 *limitIO = limit;
678 return ResOK;
679}
680
681
682/* cbsAddToEmergencyLists -- Adds range to emergency lists
683 *
684 * The range must be unadjacent to any items on the emergency lists.
685 */
686
687static Res cbsAddToEmergencyLists(CBS cbs, Addr base, Addr limit)
688{
689 Res res = ResOK;
690 Size size;
691
692 AVERT(CBS, cbs);
693 AVER(base < limit);
694 AVER(cbs->mayUseInline);
695
696 size = AddrOffset(base, limit);
697 /* Use the block list if possible. See <design/cbs/#align>. */
698 if (size > cbsMinimumAlignment) {
699 CBSEmergencyBlock prev, block, new;
700 new = CBSEmergencyBlockInit(base, limit);
701 METER_ACC(cbs->eblSearch, cbs->eblSize);
702 for(prev = NULL, block = cbs->emergencyBlockList;
703 block != NULL && CBSEmergencyBlockBase(block) < base;
704 prev = block, block = CBSEmergencyBlockNext(block)) {
705 if (prev != NULL)
706 AVER(CBSEmergencyBlockLimit(prev) < CBSEmergencyBlockBase(block));
707 AVER(CBSEmergencyBlockBase(block) < CBSEmergencyBlockLimit(block));
708 }
709
710 if (prev != NULL && block != NULL)
711 AVER(CBSEmergencyBlockLimit(prev) < CBSEmergencyBlockBase(block));
712
713 /* check ordering: prev ... new ... block */
714 if (prev != NULL && CBSEmergencyBlockLimit(prev) >= base)
715 return ResFAIL; /* range intersects with existing block */
716
717 if (block != NULL && limit >= CBSEmergencyBlockBase(block))
718 return ResFAIL; /* range intersects with existing block */
719
720 if (prev == NULL)
721 cbs->emergencyBlockList = new;
722 else
723 CBSEmergencyBlockSetNext(prev, new);
724 CBSEmergencyBlockSetNext(new, block); /* may be NULL */
725 STATISTIC(++cbs->eblSize);
726 } else if (size == CBSEmergencyGrainSize(cbs)) {
727 CBSEmergencyGrain prev, grain, new;
728 new = CBSEmergencyGrainInit(cbs, base, limit);
729 METER_ACC(cbs->eglSearch, cbs->eglSize);
730 for(prev = NULL, grain = cbs->emergencyGrainList;
731 grain != NULL && CBSEmergencyGrainBase(grain) < base;
732 prev = grain, grain = CBSEmergencyGrainNext(grain)) {
733 if (prev != NULL)
734 AVER(CBSEmergencyGrainLimit(cbs, prev) <
735 CBSEmergencyGrainBase(grain));
736 }
737
738 if (prev != NULL && grain != NULL)
739 AVER(CBSEmergencyGrainLimit(cbs, prev) < CBSEmergencyGrainBase(grain));
740
741 /* check ordering: prev ... new ... grain */
742 if (prev != NULL && CBSEmergencyGrainLimit(cbs, prev) >= base)
743 return ResFAIL; /* range intersects with existing grain */
744
745 if (grain != NULL && limit >= CBSEmergencyGrainBase(grain))
746 return ResFAIL; /* range intersects with existing grain */
747
748 if (prev == NULL)
749 cbs->emergencyGrainList = new;
750 else
751 CBSEmergencyGrainSetNext(prev, new);
752 CBSEmergencyGrainSetNext(new, grain); /* may be NULL */
753 STATISTIC(++cbs->eglSize);
754 } else {
755 NOTREACHED;
756 res = ResFAIL; /* in case AVERs are compiled out */
757 }
758
759 return res;
760}
761
762
763/* cbsFlushEmergencyLists -- Attempt to move ranges to CBS proper */
764
765static void cbsFlushEmergencyLists(CBS cbs)
766{
767 Res res = ResOK;
768 Addr base, limit;
769
770 AVERT(CBS, cbs);
771 AVER(cbs->mayUseInline);
772
773 if (cbs->emergencyBlockList != NULL) {
774 CBSEmergencyBlock block;
775 METER_ACC(cbs->eblSearch, cbs->eblSize);
776 for(block = cbs->emergencyBlockList;
777 block != NULL;
778 block = CBSEmergencyBlockNext(block)) {
779 AVER(CBSEmergencyBlockBase(block) < CBSEmergencyBlockLimit(block));
780 res = cbsInsertIntoTree(&base, &limit,
781 cbs, CBSEmergencyBlockBase(block),
782 CBSEmergencyBlockLimit(block));
783 if (res == ResOK) {
784 AVER(cbs->emergencyBlockList == block);
785 /* Emergency block is isolated in CBS */
786 AVER(base == CBSEmergencyBlockBase(block));
787 AVER(limit == CBSEmergencyBlockLimit(block));
788
789 cbs->emergencyBlockList = CBSEmergencyBlockNext(block);
790 STATISTIC(--cbs->eblSize);
791 AVER(cbs->emergencyBlockList != NULL || cbs->eblSize == 0);
792 } else {
793 AVER(ResIsAllocFailure(res));
794 goto done;
795 }
796 }
797 }
798
799 if (cbs->emergencyGrainList != NULL) {
800 CBSEmergencyGrain grain;
801 METER_ACC(cbs->eglSearch, cbs->eglSize);
802 for(grain = cbs->emergencyGrainList;
803 grain != NULL;
804 grain = CBSEmergencyGrainNext(grain)) {
805 res = cbsInsertIntoTree(&base, &limit,
806 cbs, CBSEmergencyGrainBase(grain),
807 CBSEmergencyGrainLimit(cbs, grain));
808 if (res == ResOK) {
809 AVER(cbs->emergencyGrainList == grain);
810 /* Emergency grain is isolated in CBS */
811 AVER(base == CBSEmergencyGrainBase(grain));
812 AVER(limit == CBSEmergencyGrainLimit(cbs, grain));
813
814 cbs->emergencyGrainList = CBSEmergencyGrainNext(grain);
815 STATISTIC(--cbs->eglSize);
816 AVER(cbs->emergencyGrainList != NULL || cbs->eglSize == 0);
817 } else {
818 AVER(ResIsAllocFailure(res));
819 goto done;
820 }
821 }
822 }
823
824 done:
825 return;
826}
827
828
829/* CBSInsert -- Insert a range into the CBS 483/* CBSInsert -- Insert a range into the CBS
830 * 484 *
831 * See <design/cbs/#functions.cbs.insert>. 485 * See <design/cbs/#functions.cbs.insert>.
@@ -845,34 +499,7 @@ Res CBSInsertReturningRange(Addr *baseReturn, Addr *limitReturn,
845 AVER(AddrIsAligned(base, cbs->alignment)); 499 AVER(AddrIsAligned(base, cbs->alignment));
846 AVER(AddrIsAligned(limit, cbs->alignment)); 500 AVER(AddrIsAligned(limit, cbs->alignment));
847 501
848 if (cbs->mayUseInline) { 502 res = cbsInsertIntoTree(&newBase, &newLimit, cbs, base, limit);
849 newBase = base;
850 newLimit = limit;
851
852 res = cbsCoalesceWithEmergencyLists(&newBase, &newLimit, cbs);
853 if (res != ResOK) {
854 AVER(res == ResFAIL);
855 goto done;
856 }
857
858 res = cbsInsertIntoTree(&newBase, &newLimit, cbs, newBase, newLimit);
859 /* newBase and newLimit only changed if res == ResOK */
860
861 if (ResIsAllocFailure(res)) {
862 res = cbsAddToEmergencyLists(cbs, newBase, newLimit);
863 if (res != ResOK) {
864 AVER(res == ResFAIL);
865 goto done;
866 }
867 } else {
868 /* Attempt to clear emergency lists */
869 cbsFlushEmergencyLists(cbs);
870 }
871 } else {
872 res = cbsInsertIntoTree(&newBase, &newLimit, cbs, base, limit);
873 }
874
875 done:
876 if (res == ResOK) { 503 if (res == ResOK) {
877 AVER(newBase <= base); 504 AVER(newBase <= base);
878 AVER(limit <= newLimit); 505 AVER(limit <= newLimit);
@@ -950,12 +577,7 @@ static Res cbsDeleteFromTree(CBS cbs, Addr base, Addr limit)
950 res = cbsBlockNew(cbs, limit, oldLimit); 577 res = cbsBlockNew(cbs, limit, oldLimit);
951 if (res != ResOK) { 578 if (res != ResOK) {
952 AVER(ResIsAllocFailure(res)); 579 AVER(ResIsAllocFailure(res));
953 if (cbs->mayUseInline) { 580 goto failNew;
954 res = cbsAddToEmergencyLists(cbs, limit, oldLimit);
955 AVER(res == ResOK);
956 } else {
957 goto failNew;
958 }
959 } 581 }
960 } else { /* right fragment is larger */ 582 } else { /* right fragment is larger */
961 Addr oldBase = cbsBlock->base; 583 Addr oldBase = cbsBlock->base;
@@ -966,12 +588,7 @@ static Res cbsDeleteFromTree(CBS cbs, Addr base, Addr limit)
966 res = cbsBlockNew(cbs, oldBase, base); 588 res = cbsBlockNew(cbs, oldBase, base);
967 if (res != ResOK) { 589 if (res != ResOK) {
968 AVER(ResIsAllocFailure(res)); 590 AVER(ResIsAllocFailure(res));
969 if (cbs->mayUseInline) { 591 goto failNew;
970 res = cbsAddToEmergencyLists(cbs, oldBase, base);
971 AVER(res == ResOK);
972 } else {
973 goto failNew;
974 }
975 } 592 }
976 } 593 }
977 } 594 }
@@ -987,101 +604,6 @@ failSplayTreeSearch:
987} 604}
988 605
989 606
990static Res cbsDeleteFromEmergencyBlockList(CBS cbs, Addr base, Addr limit)
991{
992 Res res;
993 Addr blockBase, blockLimit;
994 CBSEmergencyBlock prev, block;
995
996 /* parameters already checked in caller */
997 AVER(cbs->mayUseInline);
998
999 METER_ACC(cbs->eblSearch, cbs->eblSize);
1000 for(prev = NULL, block = cbs->emergencyBlockList;
1001 block != NULL && CBSEmergencyBlockLimit(block) < limit;
1002 prev = block, block = CBSEmergencyBlockNext(block)) {
1003 AVER(CBSEmergencyBlockBase(block) < CBSEmergencyBlockLimit(block));
1004 if (CBSEmergencyBlockBase(block) >= base)
1005 return ResFAIL;
1006 if (prev != NULL)
1007 AVER(CBSEmergencyBlockLimit(prev) < CBSEmergencyBlockBase(block));
1008 }
1009
1010 if (block != NULL) {
1011 blockBase = CBSEmergencyBlockBase(block);
1012 blockLimit = CBSEmergencyBlockLimit(block);
1013 AVER(blockBase < blockLimit);
1014 AVER(blockLimit >= limit);
1015
1016 if (blockBase <= base && limit <= blockLimit) {
1017 /* remove from list */
1018 if (prev == NULL)
1019 cbs->emergencyBlockList = CBSEmergencyBlockNext(block);
1020 else
1021 CBSEmergencyBlockSetNext(prev, CBSEmergencyBlockNext(block));
1022 STATISTIC(--cbs->eblSize);
1023 AVER(cbs->emergencyBlockList != NULL || cbs->eblSize == 0);
1024 if (blockBase < base) {
1025 res = cbsAddToEmergencyLists(cbs, blockBase, base);
1026 if (res != ResOK)
1027 return res;
1028 }
1029 if (limit < blockLimit) {
1030 res = cbsAddToEmergencyLists(cbs, limit, blockLimit);
1031 if (res != ResOK)
1032 return res;
1033 }
1034 return ResOK;
1035 } else {
1036 return ResFAIL; /* partly in list */
1037 }
1038 }
1039 return ResFAIL; /* not in list at all */
1040}
1041
1042
1043static Res cbsDeleteFromEmergencyGrainList(CBS cbs, Addr base, Addr limit)
1044{
1045 Addr grainBase, grainLimit;
1046 CBSEmergencyGrain prev, grain;
1047
1048 /* parameters already checked in caller */
1049 AVER(cbs->mayUseInline);
1050 if (AddrOffset(base, limit) != CBSEmergencyGrainSize(cbs))
1051 return ResFAIL;
1052
1053 METER_ACC(cbs->eglSearch, cbs->eglSize);
1054 for(prev = NULL, grain = cbs->emergencyGrainList;
1055 grain != NULL && CBSEmergencyGrainLimit(cbs, grain) < limit;
1056 prev = grain, grain = CBSEmergencyGrainNext(grain)) {
1057 if (prev != NULL)
1058 AVER(CBSEmergencyGrainLimit(cbs, prev) < CBSEmergencyGrainBase(grain));
1059 }
1060
1061 if (grain != NULL) {
1062 grainBase = CBSEmergencyGrainBase(grain);
1063 grainLimit = CBSEmergencyGrainLimit(cbs, grain);
1064 AVER(grainLimit >= limit);
1065
1066 if (grainBase <= base && limit <= grainLimit) {
1067 AVER(grainBase == base);
1068 AVER(grainLimit == limit);
1069 /* remove from list */
1070 if (prev == NULL)
1071 cbs->emergencyGrainList = CBSEmergencyGrainNext(grain);
1072 else
1073 CBSEmergencyGrainSetNext(prev, CBSEmergencyGrainNext(grain));
1074 STATISTIC(--cbs->eglSize);
1075 AVER(cbs->emergencyGrainList != NULL || cbs->eglSize == 0);
1076 return ResOK;
1077 } else {
1078 return ResFAIL; /* range is partly in list */
1079 }
1080 }
1081 return ResFAIL; /* range is not in list at all */
1082}
1083
1084
1085/* CBSDelete -- Remove a range from a CBS 607/* CBSDelete -- Remove a range from a CBS
1086 * 608 *
1087 * See <design/cbs/#function.cbs.delete>. 609 * See <design/cbs/#function.cbs.delete>.
@@ -1101,21 +623,6 @@ Res CBSDelete(CBS cbs, Addr base, Addr limit)
1101 623
1102 res = cbsDeleteFromTree(cbs, base, limit); 624 res = cbsDeleteFromTree(cbs, base, limit);
1103 625
1104 /* We rely on the consistency of the three free structures. */
1105 /* These checks don't distinguish "partially in" from "not in". */
1106 if (cbs->mayUseInline) {
1107 AVER(res == ResOK || res == ResFAIL);
1108 if (res == ResFAIL) { /* wasn't in tree */
1109 res = cbsDeleteFromEmergencyBlockList(cbs, base, limit);
1110 if (res == ResFAIL) { /* wasn't in block list */
1111 res = cbsDeleteFromEmergencyGrainList(cbs, base, limit);
1112 }
1113 }
1114 /* always worth trying, wherever we found the deleted block */
1115 if (res == ResOK)
1116 cbsFlushEmergencyLists(cbs);
1117 }
1118
1119 CBSLeave(cbs); 626 CBSLeave(cbs);
1120 return res; 627 return res;
1121} 628}
@@ -1383,8 +890,6 @@ Bool CBSFindFirst(Addr *baseReturn, Addr *limitReturn,
1383 AVER(cbs->fastFind); 890 AVER(cbs->fastFind);
1384 AVERT(CBSFindDelete, findDelete); 891 AVERT(CBSFindDelete, findDelete);
1385 892
1386 cbsFlushEmergencyLists(cbs); /* might do some good */
1387
1388 { 893 {
1389 SplayNode node; 894 SplayNode node;
1390 895
@@ -1403,38 +908,6 @@ Bool CBSFindFirst(Addr *baseReturn, Addr *limitReturn,
1403 } 908 }
1404 } 909 }
1405 910
1406 if (cbs->emergencyBlockList != NULL) {
1407 CBSEmergencyBlock block;
1408
1409 METER_ACC(cbs->eblSearch, cbs->eblSize);
1410 for(block = cbs->emergencyBlockList;
1411 block != NULL &&
1412 (!found || CBSEmergencyBlockBase(block) < base);
1413 block = CBSEmergencyBlockNext(block)) {
1414 if (CBSEmergencyBlockSize(block) >= size) {
1415 found = TRUE;
1416 base = CBSEmergencyBlockBase(block);
1417 limit = CBSEmergencyBlockLimit(block);
1418 deleteMethod = &cbsDeleteFromEmergencyBlockList;
1419 /* @@@@ Could remove in place more efficiently. */
1420 break;
1421 }
1422 }
1423 }
1424
1425 if (cbs->emergencyGrainList != NULL &&
1426 size <= CBSEmergencyGrainSize(cbs)) {
1427 /* Take first grain */
1428 CBSEmergencyGrain grain = cbs->emergencyGrainList;
1429
1430 if (!found || CBSEmergencyGrainBase(grain) < base) {
1431 found = TRUE;
1432 base = CBSEmergencyGrainBase(grain);
1433 limit = CBSEmergencyGrainLimit(cbs, grain);
1434 deleteMethod = &cbsDeleteFromEmergencyGrainList;
1435 }
1436 }
1437
1438 if (found) { 911 if (found) {
1439 AVER(AddrOffset(base, limit) >= size); 912 AVER(AddrOffset(base, limit) >= size);
1440 cbsFindDeleteRange(baseReturn, limitReturn, cbs, base, limit, size, 913 cbsFindDeleteRange(baseReturn, limitReturn, cbs, base, limit, size,
@@ -1465,8 +938,6 @@ Bool CBSFindLast(Addr *baseReturn, Addr *limitReturn,
1465 AVER(cbs->fastFind); 938 AVER(cbs->fastFind);
1466 AVERT(CBSFindDelete, findDelete); 939 AVERT(CBSFindDelete, findDelete);
1467 940
1468 cbsFlushEmergencyLists(cbs); /* might do some good */
1469
1470 { 941 {
1471 SplayNode node; 942 SplayNode node;
1472 943
@@ -1484,44 +955,6 @@ Bool CBSFindLast(Addr *baseReturn, Addr *limitReturn,
1484 } 955 }
1485 } 956 }
1486 957
1487 if (cbs->emergencyBlockList != NULL) {
1488 CBSEmergencyBlock block;
1489
1490 METER_ACC(cbs->eblSearch, cbs->eblSize);
1491 for(block = cbs->emergencyBlockList;
1492 block != NULL;
1493 block = CBSEmergencyBlockNext(block)) {
1494 if (CBSEmergencyBlockSize(block) >= size &&
1495 (!found || CBSEmergencyBlockBase(block) > base)) {
1496 found = TRUE;
1497 base = CBSEmergencyBlockBase(block);
1498 limit = CBSEmergencyBlockLimit(block);
1499 deleteMethod = &cbsDeleteFromEmergencyBlockList;
1500 /* @@@@ Could remove in place more efficiently. */
1501 }
1502 }
1503 }
1504
1505 if (cbs->emergencyGrainList != NULL &&
1506 size <= CBSEmergencyGrainSize(cbs)) {
1507 CBSEmergencyGrain grain;
1508
1509 /* Find last grain */
1510 METER_ACC(cbs->eglSearch, cbs->eglSize);
1511 for(grain = cbs->emergencyGrainList;
1512 CBSEmergencyGrainNext(grain) != NULL;
1513 grain = CBSEmergencyGrainNext(grain))
1514 NOOP;
1515
1516 if (!found || CBSEmergencyGrainBase(grain) > base) {
1517 found = TRUE;
1518 base = CBSEmergencyGrainBase(grain);
1519 limit = CBSEmergencyGrainLimit(cbs, grain);
1520 deleteMethod = &cbsDeleteFromEmergencyGrainList;
1521 /* @@@@ Could remove in place more efficiently */
1522 }
1523 }
1524
1525 if (found) { 958 if (found) {
1526 AVER(AddrOffset(base, limit) >= size); 959 AVER(AddrOffset(base, limit) >= size);
1527 cbsFindDeleteRange(baseReturn, limitReturn, cbs, base, limit, size, 960 cbsFindDeleteRange(baseReturn, limitReturn, cbs, base, limit, size,
@@ -1551,8 +984,6 @@ Bool CBSFindLargest(Addr *baseReturn, Addr *limitReturn,
1551 AVER(cbs->fastFind); 984 AVER(cbs->fastFind);
1552 AVERT(CBSFindDelete, findDelete); 985 AVERT(CBSFindDelete, findDelete);
1553 986
1554 cbsFlushEmergencyLists(cbs); /* might do some good */
1555
1556 { 987 {
1557 SplayNode root; 988 SplayNode root;
1558 Bool notEmpty; 989 Bool notEmpty;
@@ -1575,38 +1006,6 @@ Bool CBSFindLargest(Addr *baseReturn, Addr *limitReturn,
1575 } 1006 }
1576 } 1007 }
1577 1008
1578 if (cbs->emergencyBlockList != NULL) {
1579 CBSEmergencyBlock block;
1580
1581 /* Scan the whole list -- could maintain a maxSize to avoid it. */
1582 METER_ACC(cbs->eblSearch, cbs->eblSize);
1583 for(block = cbs->emergencyBlockList;
1584 block != NULL;
1585 block = CBSEmergencyBlockNext(block)) {
1586 if (CBSEmergencyBlockSize(block) >= size) {
1587 /* .pref: >= so that it prefers the emerg. list to the tree */
1588 found = TRUE;
1589 size = CBSEmergencyBlockSize(block);
1590 base = CBSEmergencyBlockBase(block);
1591 limit = CBSEmergencyBlockLimit(block);
1592 deleteMethod = &cbsDeleteFromEmergencyBlockList;
1593 /* @@@@ Could remove in place more efficiently. */
1594 }
1595 }
1596 }
1597
1598 /* If something was found, it will be larger than an emerg. grain. */
1599 if (!found && cbs->emergencyGrainList != NULL) {
1600 /* Take first grain */
1601 CBSEmergencyGrain grain = cbs->emergencyGrainList;
1602
1603 found = TRUE;
1604 size = CBSEmergencyGrainSize(cbs);
1605 base = CBSEmergencyGrainBase(grain);
1606 limit = CBSEmergencyGrainLimit(cbs, grain);
1607 deleteMethod = &cbsDeleteFromEmergencyGrainList;
1608 }
1609
1610 if (found) { 1009 if (found) {
1611 cbsFindDeleteRange(baseReturn, limitReturn, cbs, base, limit, size, 1010 cbsFindDeleteRange(baseReturn, limitReturn, cbs, base, limit, size,
1612 deleteMethod, findDelete); 1011 deleteMethod, findDelete);
@@ -1642,10 +1041,6 @@ Res CBSDescribe(CBS cbs, mps_lib_FILE *stream)
1642 1041
1643 res = METER_WRITE(cbs->splaySearch, stream); 1042 res = METER_WRITE(cbs->splaySearch, stream);
1644 if (res != ResOK) return res; 1043 if (res != ResOK) return res;
1645 res = METER_WRITE(cbs->eblSearch, stream);
1646 if (res != ResOK) return res;
1647 res = METER_WRITE(cbs->eglSearch, stream);
1648 if (res != ResOK) return res;
1649 1044
1650 res = WriteF(stream, "}\n", NULL); 1045 res = WriteF(stream, "}\n", NULL);
1651 return res; 1046 return res;
diff --git a/mps/code/cbs.h b/mps/code/cbs.h
index b2fe4d0b27f..ddbda2343f3 100644
--- a/mps/code/cbs.h
+++ b/mps/code/cbs.h
@@ -21,13 +21,6 @@ typedef void (*CBSChangeSizeMethod)(CBS cbs, CBSBlock block,
21typedef Bool (*CBSIterateMethod)(CBS cbs, CBSBlock block, void *closureP); 21typedef Bool (*CBSIterateMethod)(CBS cbs, CBSBlock block, void *closureP);
22 22
23 23
24/* See <design/cbs/#impl.low-mem.inline.block> */
25typedef void **CBSEmergencyBlock; /* next, limit */
26
27/* See <design/cbs/#impl.low-mem.inline.block> */
28typedef void **CBSEmergencyGrain; /* next */
29
30
31#define CBSSig ((Sig)0x519CB599) /* SIGnature CBS */ 24#define CBSSig ((Sig)0x519CB599) /* SIGnature CBS */
32 25
33typedef struct CBSStruct { 26typedef struct CBSStruct {
@@ -40,17 +33,10 @@ typedef struct CBSStruct {
40 CBSChangeSizeMethod shrink; 33 CBSChangeSizeMethod shrink;
41 Size minSize; 34 Size minSize;
42 Align alignment; 35 Align alignment;
43 Bool mayUseInline;
44 Bool fastFind; 36 Bool fastFind;
45 Bool inCBS; /* prevent reentrance */ 37 Bool inCBS; /* prevent reentrance */
46 CBSEmergencyBlock emergencyBlockList;
47 Count eblSize;
48 CBSEmergencyGrain emergencyGrainList;
49 Count eglSize;
50 /* meters for sizes of search structures at each op */ 38 /* meters for sizes of search structures at each op */
51 METER_DECL(splaySearch); 39 METER_DECL(splaySearch);
52 METER_DECL(eblSearch);
53 METER_DECL(eglSearch);
54 Sig sig; /* sig at end because embeded */ 40 Sig sig; /* sig at end because embeded */
55} CBSStruct; 41} CBSStruct;
56 42
@@ -72,7 +58,6 @@ extern Res CBSInit(Arena arena, CBS cbs, void *owner,
72 CBSChangeSizeMethod shrink, 58 CBSChangeSizeMethod shrink,
73 Size minSize, 59 Size minSize,
74 Align alignment, 60 Align alignment,
75 Bool mayUseInline,
76 Bool fastFind); 61 Bool fastFind);
77extern void CBSFinish(CBS cbs); 62extern void CBSFinish(CBS cbs);
78 63
diff --git a/mps/code/cbstest.c b/mps/code/cbstest.c
index cb5744238dc..adb976081e2 100644
--- a/mps/code/cbstest.c
+++ b/mps/code/cbstest.c
@@ -591,7 +591,7 @@ extern int main(int argc, char *argv[])
591 die((mps_res_t)CBSInit(arena, &cbsStruct, NULL, &cbsNewCallback, 591 die((mps_res_t)CBSInit(arena, &cbsStruct, NULL, &cbsNewCallback,
592 &cbsDeleteCallback, &cbsGrowCallback, 592 &cbsDeleteCallback, &cbsGrowCallback,
593 &cbsShrinkCallback, MinSize, 593 &cbsShrinkCallback, MinSize,
594 Alignment, TRUE, TRUE), 594 Alignment, TRUE),
595 "failed to initialise CBS"); 595 "failed to initialise CBS");
596 cbs = &cbsStruct; 596 cbs = &cbsStruct;
597 597
diff --git a/mps/code/poolmv2.c b/mps/code/poolmv2.c
index dc10ce990a8..c99a0f0b225 100644
--- a/mps/code/poolmv2.c
+++ b/mps/code/poolmv2.c
@@ -237,7 +237,7 @@ static Res MVTInit(Pool pool, va_list arg)
237 abqDepth = 3; 237 abqDepth = 3;
238 238
239 res = CBSInit(arena, MVTCBS(mvt), (void *)mvt, &MVTNoteNew, &MVTNoteDelete, 239 res = CBSInit(arena, MVTCBS(mvt), (void *)mvt, &MVTNoteNew, &MVTNoteDelete,
240 NULL, NULL, reuseSize, MPS_PF_ALIGN, TRUE, FALSE); 240 NULL, NULL, reuseSize, MPS_PF_ALIGN, FALSE);
241 if (res != ResOK) 241 if (res != ResOK)
242 goto failCBS; 242 goto failCBS;
243 243
diff --git a/mps/code/poolmvff.c b/mps/code/poolmvff.c
index a2647608187..eea4e197911 100644
--- a/mps/code/poolmvff.c
+++ b/mps/code/poolmvff.c
@@ -466,7 +466,7 @@ static Res MVFFInit(Pool pool, va_list arg)
466 mvff->free = 0; 466 mvff->free = 0;
467 467
468 res = CBSInit(arena, CBSOfMVFF(mvff), (void *)mvff, NULL, NULL, NULL, NULL, 468 res = CBSInit(arena, CBSOfMVFF(mvff), (void *)mvff, NULL, NULL, NULL, NULL,
469 mvff->extendBy, align, TRUE, TRUE); 469 mvff->extendBy, align, TRUE);
470 470
471 if (res != ResOK) 471 if (res != ResOK)
472 goto failInit; 472 goto failInit;
@@ -686,8 +686,8 @@ void mps_mvff_stat(mps_pool_t mps_pool)
686 AVERT(MVFF, mvff); 686 AVERT(MVFF, mvff);
687 687
688 METER_EMIT(&CBSOfMVFF(mvff)->splaySearch); 688 METER_EMIT(&CBSOfMVFF(mvff)->splaySearch);
689 METER_EMIT(&CBSOfMVFF(mvff)->eblSearch); 689 /* FIXME: METER_EMIT(&CBSOfMVFF(mvff)->eblSearch); */
690 METER_EMIT(&CBSOfMVFF(mvff)->eglSearch); 690 /* FIXME: METER_EMIT(&CBSOfMVFF(mvff)->eglSearch); */
691} 691}
692 692
693 693