diff options
| author | Gareth Rees | 2013-05-20 20:45:26 +0100 |
|---|---|---|
| committer | Gareth Rees | 2013-05-20 20:45:26 +0100 |
| commit | 2849a0bd33b8aa80910cb31cbdc25b9177fa9b8b (patch) | |
| tree | 5085f58d805f2570c572bd9148c3059e1a97aedf /mps/code | |
| parent | df1a8a3807db2d085e668aa625a0734d79e46eec (diff) | |
| download | emacs-2849a0bd33b8aa80910cb31cbdc25b9177fa9b8b.tar.gz emacs-2849a0bd33b8aa80910cb31cbdc25b9177fa9b8b.zip | |
Make the cbs module more abstract by removing cbsblock from the public interface. avoid re-entrancy problems by removing the callback interface. public interfaces like cbsiteratemethod now operate in terms of address ranges rather than cbsblocks.
The functions CBSInsert, CBSDelete and CBSFind* now additionally return an "old" address range which gives the former base and limit of the block that has just been updated. This gives clients enough information to update their caches if need be.
Update CBS test and design accordingly.
Copied from Perforce
Change: 182014
ServerID: perforce.ravenbrook.com
Diffstat (limited to 'mps/code')
| -rw-r--r-- | mps/code/cbs.c | 222 | ||||
| -rw-r--r-- | mps/code/cbs.h | 49 | ||||
| -rw-r--r-- | mps/code/cbstest.c | 241 |
3 files changed, 73 insertions, 439 deletions
diff --git a/mps/code/cbs.c b/mps/code/cbs.c index f40d075b27e..7b17d295f32 100644 --- a/mps/code/cbs.c +++ b/mps/code/cbs.c | |||
| @@ -21,6 +21,24 @@ | |||
| 21 | SRCID(cbs, "$Id$"); | 21 | SRCID(cbs, "$Id$"); |
| 22 | 22 | ||
| 23 | 23 | ||
| 24 | typedef struct CBSBlockStruct *CBSBlock; | ||
| 25 | typedef struct CBSBlockStruct { | ||
| 26 | SplayNodeStruct splayNode; | ||
| 27 | Addr base; | ||
| 28 | Addr limit; | ||
| 29 | Size maxSize; /* accurate maximum block size of sub-tree */ | ||
| 30 | } CBSBlockStruct; | ||
| 31 | |||
| 32 | |||
| 33 | extern Bool CBSBlockCheck(CBSBlock block); | ||
| 34 | /* CBSBlockBase -- See <design/cbs/#function.cbs.block.base> */ | ||
| 35 | #define CBSBlockBase(block) ((block)->base) | ||
| 36 | /* CBSBlockLimit -- See <design/cbs/#function.cbs.block.limit> */ | ||
| 37 | #define CBSBlockLimit(block) ((block)->limit) | ||
| 38 | #define CBSBlockSize(block) AddrOffset((block)->base, (block)->limit) | ||
| 39 | extern Size (CBSBlockSize)(CBSBlock block); | ||
| 40 | |||
| 41 | |||
| 24 | #define cbsOfSplayTree(tree) PARENT(CBSStruct, splayTree, (tree)) | 42 | #define cbsOfSplayTree(tree) PARENT(CBSStruct, splayTree, (tree)) |
| 25 | #define cbsBlockOfSplayNode(node) PARENT(CBSBlockStruct, splayNode, (node)) | 43 | #define cbsBlockOfSplayNode(node) PARENT(CBSBlockStruct, splayNode, (node)) |
| 26 | #define splayTreeOfCBS(tree) (&((cbs)->splayTree)) | 44 | #define splayTreeOfCBS(tree) (&((cbs)->splayTree)) |
| @@ -65,10 +83,6 @@ Bool CBSCheck(CBS cbs) | |||
| 65 | CHECKD(Pool, cbs->blockPool); | 83 | CHECKD(Pool, cbs->blockPool); |
| 66 | CHECKL(BoolCheck(cbs->fastFind)); | 84 | CHECKL(BoolCheck(cbs->fastFind)); |
| 67 | CHECKL(BoolCheck(cbs->inCBS)); | 85 | CHECKL(BoolCheck(cbs->inCBS)); |
| 68 | CHECKL(cbs->new == NULL || FUNCHECK(cbs->new)); | ||
| 69 | CHECKL(cbs->delete == NULL || FUNCHECK(cbs->delete)); | ||
| 70 | CHECKL(cbs->grow == NULL || FUNCHECK(cbs->grow)); | ||
| 71 | CHECKL(cbs->shrink == NULL || FUNCHECK(cbs->shrink)); | ||
| 72 | /* No MeterCheck */ | 86 | /* No MeterCheck */ |
| 73 | 87 | ||
| 74 | return TRUE; | 88 | return TRUE; |
| @@ -206,17 +220,11 @@ static void cbsUpdateNode(SplayTree tree, SplayNode node, | |||
| 206 | * See <design/cbs/#function.cbs.init>. | 220 | * See <design/cbs/#function.cbs.init>. |
| 207 | */ | 221 | */ |
| 208 | 222 | ||
| 209 | Res CBSInit(Arena arena, CBS cbs, void *owner, | 223 | Res CBSInit(Arena arena, CBS cbs, void *owner, Align alignment, Bool fastFind) |
| 210 | CBSChangeSizeMethod new, CBSChangeSizeMethod delete, | ||
| 211 | CBSChangeSizeMethod grow, CBSChangeSizeMethod shrink, | ||
| 212 | Size minSize, Align alignment, | ||
| 213 | Bool fastFind) | ||
| 214 | { | 224 | { |
| 215 | Res res; | 225 | Res res; |
| 216 | 226 | ||
| 217 | AVERT(Arena, arena); | 227 | AVERT(Arena, arena); |
| 218 | AVER(new == NULL || FUNCHECK(new)); | ||
| 219 | AVER(delete == NULL || FUNCHECK(delete)); | ||
| 220 | 228 | ||
| 221 | SplayTreeInit(splayTreeOfCBS(cbs), &cbsSplayCompare, | 229 | SplayTreeInit(splayTreeOfCBS(cbs), &cbsSplayCompare, |
| 222 | fastFind ? &cbsUpdateNode : NULL); | 230 | fastFind ? &cbsUpdateNode : NULL); |
| @@ -226,11 +234,6 @@ Res CBSInit(Arena arena, CBS cbs, void *owner, | |||
| 226 | return res; | 234 | return res; |
| 227 | cbs->splayTreeSize = 0; | 235 | cbs->splayTreeSize = 0; |
| 228 | 236 | ||
| 229 | cbs->new = new; | ||
| 230 | cbs->delete = delete; | ||
| 231 | cbs->grow = grow; | ||
| 232 | cbs->shrink = shrink; | ||
| 233 | cbs->minSize = minSize; | ||
| 234 | cbs->fastFind = fastFind; | 237 | cbs->fastFind = fastFind; |
| 235 | cbs->alignment = alignment; | 238 | cbs->alignment = alignment; |
| 236 | cbs->inCBS = TRUE; | 239 | cbs->inCBS = TRUE; |
| @@ -292,9 +295,6 @@ static void cbsBlockDelete(CBS cbs, CBSBlock block) | |||
| 292 | /* make invalid */ | 295 | /* make invalid */ |
| 293 | block->limit = block->base; | 296 | block->limit = block->base; |
| 294 | 297 | ||
| 295 | if (cbs->delete != NULL && oldSize >= cbs->minSize) | ||
| 296 | (*(cbs->delete))(cbs, block, oldSize, (Size)0); | ||
| 297 | |||
| 298 | PoolFree(cbs->blockPool, (Addr)block, sizeof(CBSBlockStruct)); | 298 | PoolFree(cbs->blockPool, (Addr)block, sizeof(CBSBlockStruct)); |
| 299 | 299 | ||
| 300 | return; | 300 | return; |
| @@ -315,11 +315,6 @@ static void cbsBlockShrink(CBS cbs, CBSBlock block, Size oldSize) | |||
| 315 | keyOfCBSBlock(block)); | 315 | keyOfCBSBlock(block)); |
| 316 | AVER(CBSBlockSize(block) <= block->maxSize); | 316 | AVER(CBSBlockSize(block) <= block->maxSize); |
| 317 | } | 317 | } |
| 318 | |||
| 319 | if (cbs->delete != NULL && oldSize >= cbs->minSize && newSize < cbs->minSize) | ||
| 320 | (*(cbs->delete))(cbs, block, oldSize, newSize); | ||
| 321 | else if (cbs->shrink != NULL && newSize >= cbs->minSize) | ||
| 322 | (*(cbs->shrink))(cbs, block, oldSize, newSize); | ||
| 323 | } | 318 | } |
| 324 | 319 | ||
| 325 | static void cbsBlockGrow(CBS cbs, CBSBlock block, Size oldSize) | 320 | static void cbsBlockGrow(CBS cbs, CBSBlock block, Size oldSize) |
| @@ -337,11 +332,6 @@ static void cbsBlockGrow(CBS cbs, CBSBlock block, Size oldSize) | |||
| 337 | keyOfCBSBlock(block)); | 332 | keyOfCBSBlock(block)); |
| 338 | AVER(CBSBlockSize(block) <= block->maxSize); | 333 | AVER(CBSBlockSize(block) <= block->maxSize); |
| 339 | } | 334 | } |
| 340 | |||
| 341 | if (cbs->new != NULL && oldSize < cbs->minSize && newSize >= cbs->minSize) | ||
| 342 | (*(cbs->new))(cbs, block, oldSize, newSize); | ||
| 343 | else if (cbs->grow != NULL && oldSize >= cbs->minSize) | ||
| 344 | (*(cbs->grow))(cbs, block, oldSize, newSize); | ||
| 345 | } | 335 | } |
| 346 | 336 | ||
| 347 | static Res cbsBlockNew(CBS cbs, Addr base, Addr limit) | 337 | static Res cbsBlockNew(CBS cbs, Addr base, Addr limit) |
| @@ -373,9 +363,6 @@ static Res cbsBlockNew(CBS cbs, Addr base, Addr limit) | |||
| 373 | AVER(res == ResOK); | 363 | AVER(res == ResOK); |
| 374 | STATISTIC(++cbs->splayTreeSize); | 364 | STATISTIC(++cbs->splayTreeSize); |
| 375 | 365 | ||
| 376 | if (cbs->new != NULL && newSize >= cbs->minSize) | ||
| 377 | (*(cbs->new))(cbs, block, (Size)0, newSize); | ||
| 378 | |||
| 379 | return ResOK; | 366 | return ResOK; |
| 380 | 367 | ||
| 381 | failPoolAlloc: | 368 | failPoolAlloc: |
| @@ -485,12 +472,14 @@ fail: | |||
| 485 | * See <design/cbs/#functions.cbs.insert>. | 472 | * See <design/cbs/#functions.cbs.insert>. |
| 486 | */ | 473 | */ |
| 487 | 474 | ||
| 488 | Res CBSInsertReturningRange(Addr *baseReturn, Addr *limitReturn, | 475 | Res CBSInsert(Addr *baseReturn, Addr *limitReturn, |
| 489 | CBS cbs, Addr base, Addr limit) | 476 | CBS cbs, Addr base, Addr limit) |
| 490 | { | 477 | { |
| 491 | Addr newBase, newLimit; | 478 | Addr newBase, newLimit; |
| 492 | Res res; | 479 | Res res; |
| 493 | 480 | ||
| 481 | AVER(baseReturn != NULL); | ||
| 482 | AVER(limitReturn != NULL); | ||
| 494 | AVERT(CBS, cbs); | 483 | AVERT(CBS, cbs); |
| 495 | CBSEnter(cbs); | 484 | CBSEnter(cbs); |
| 496 | 485 | ||
| @@ -511,24 +500,11 @@ Res CBSInsertReturningRange(Addr *baseReturn, Addr *limitReturn, | |||
| 511 | return res; | 500 | return res; |
| 512 | } | 501 | } |
| 513 | 502 | ||
| 514 | Res CBSInsert(CBS cbs, Addr base, Addr limit) | ||
| 515 | { | ||
| 516 | Res res; | ||
| 517 | Addr newBase, newLimit; | ||
| 518 | |||
| 519 | /* all parameters checked by CBSInsertReturningRange */ | ||
| 520 | /* CBSEnter/Leave done by CBSInsertReturningRange */ | ||
| 521 | |||
| 522 | res = CBSInsertReturningRange(&newBase, &newLimit, | ||
| 523 | cbs, base, limit); | ||
| 524 | |||
| 525 | return res; | ||
| 526 | } | ||
| 527 | |||
| 528 | 503 | ||
| 529 | /* cbsDeleteFrom* -- delete blocks from different parts of the CBS */ | 504 | /* cbsDeleteFrom* -- delete blocks from different parts of the CBS */ |
| 530 | 505 | ||
| 531 | static Res cbsDeleteFromTree(CBS cbs, Addr base, Addr limit) | 506 | static Res cbsDeleteFromTree(Addr *baseReturn, Addr *limitReturn, |
| 507 | CBS cbs, Addr base, Addr limit) | ||
| 532 | { | 508 | { |
| 533 | Res res; | 509 | Res res; |
| 534 | CBSBlock cbsBlock; | 510 | CBSBlock cbsBlock; |
| @@ -548,6 +524,9 @@ static Res cbsDeleteFromTree(CBS cbs, Addr base, Addr limit) | |||
| 548 | goto failLimitCheck; | 524 | goto failLimitCheck; |
| 549 | } | 525 | } |
| 550 | 526 | ||
| 527 | *baseReturn = cbsBlock->base; | ||
| 528 | *limitReturn = cbsBlock->limit; | ||
| 529 | |||
| 551 | if (base == cbsBlock->base) { | 530 | if (base == cbsBlock->base) { |
| 552 | if (limit == cbsBlock->limit) { /* entire block */ | 531 | if (limit == cbsBlock->limit) { /* entire block */ |
| 553 | cbsBlockDelete(cbs, cbsBlock); | 532 | cbsBlockDelete(cbs, cbsBlock); |
| @@ -609,7 +588,8 @@ failSplayTreeSearch: | |||
| 609 | * See <design/cbs/#function.cbs.delete>. | 588 | * See <design/cbs/#function.cbs.delete>. |
| 610 | */ | 589 | */ |
| 611 | 590 | ||
| 612 | Res CBSDelete(CBS cbs, Addr base, Addr limit) | 591 | Res CBSDelete(Addr *baseReturn, Addr *limitReturn, |
| 592 | CBS cbs, Addr base, Addr limit) | ||
| 613 | { | 593 | { |
| 614 | Res res; | 594 | Res res; |
| 615 | 595 | ||
| @@ -621,14 +601,14 @@ Res CBSDelete(CBS cbs, Addr base, Addr limit) | |||
| 621 | AVER(AddrIsAligned(base, cbs->alignment)); | 601 | AVER(AddrIsAligned(base, cbs->alignment)); |
| 622 | AVER(AddrIsAligned(limit, cbs->alignment)); | 602 | AVER(AddrIsAligned(limit, cbs->alignment)); |
| 623 | 603 | ||
| 624 | res = cbsDeleteFromTree(cbs, base, limit); | 604 | res = cbsDeleteFromTree(baseReturn, limitReturn, cbs, base, limit); |
| 625 | 605 | ||
| 626 | CBSLeave(cbs); | 606 | CBSLeave(cbs); |
| 627 | return res; | 607 | return res; |
| 628 | } | 608 | } |
| 629 | 609 | ||
| 630 | 610 | ||
| 631 | Res CBSBlockDescribe(CBSBlock block, mps_lib_FILE *stream) | 611 | static Res CBSBlockDescribe(CBSBlock block, mps_lib_FILE *stream) |
| 632 | { | 612 | { |
| 633 | Res res; | 613 | Res res; |
| 634 | 614 | ||
| @@ -678,7 +658,7 @@ static void cbsIterateInternal(CBS cbs, CBSIterateMethod iterate, void *closureP | |||
| 678 | splayNode = SplayTreeFirst(splayTree, NULL); | 658 | splayNode = SplayTreeFirst(splayTree, NULL); |
| 679 | while(splayNode != NULL) { | 659 | while(splayNode != NULL) { |
| 680 | cbsBlock = cbsBlockOfSplayNode(splayNode); | 660 | cbsBlock = cbsBlockOfSplayNode(splayNode); |
| 681 | if (!(*iterate)(cbs, cbsBlock, closureP)) { | 661 | if (!(*iterate)(cbs, CBSBlockBase(cbsBlock), CBSBlockLimit(cbsBlock), closureP)) { |
| 682 | break; | 662 | break; |
| 683 | } | 663 | } |
| 684 | METER_ACC(cbs->splaySearch, cbs->splayTreeSize); | 664 | METER_ACC(cbs->splaySearch, cbs->splayTreeSize); |
| @@ -700,110 +680,6 @@ void CBSIterate(CBS cbs, CBSIterateMethod iterate, void *closureP) | |||
| 700 | } | 680 | } |
| 701 | 681 | ||
| 702 | 682 | ||
| 703 | /* CBSIterateLarge -- Iterate only large blocks | ||
| 704 | * | ||
| 705 | * This function iterates only blocks that are larger than or equal | ||
| 706 | * to the minimum size. | ||
| 707 | */ | ||
| 708 | |||
| 709 | typedef struct CBSIterateLargeClosureStruct { | ||
| 710 | void *p; | ||
| 711 | CBSIterateMethod f; | ||
| 712 | } CBSIterateLargeClosureStruct, *CBSIterateLargeClosure; | ||
| 713 | |||
| 714 | static Bool cbsIterateLargeAction(CBS cbs, CBSBlock block, void *p) | ||
| 715 | { | ||
| 716 | Bool b = TRUE; | ||
| 717 | CBSIterateLargeClosure closure; | ||
| 718 | |||
| 719 | closure = (CBSIterateLargeClosure)p; | ||
| 720 | AVER(closure != NULL); | ||
| 721 | |||
| 722 | if (CBSBlockSize(block) >= cbs->minSize) | ||
| 723 | b = (closure->f)(cbs, block, closure->p); | ||
| 724 | |||
| 725 | return b; | ||
| 726 | } | ||
| 727 | |||
| 728 | |||
| 729 | void CBSIterateLarge(CBS cbs, CBSIterateMethod iterate, void *closureP) | ||
| 730 | { | ||
| 731 | CBSIterateLargeClosureStruct closure; | ||
| 732 | |||
| 733 | AVERT(CBS, cbs); | ||
| 734 | CBSEnter(cbs); | ||
| 735 | |||
| 736 | AVER(FUNCHECK(iterate)); | ||
| 737 | |||
| 738 | closure.p = closureP; | ||
| 739 | closure.f = iterate; | ||
| 740 | cbsIterateInternal(cbs, &cbsIterateLargeAction, (void *)&closure); | ||
| 741 | |||
| 742 | CBSLeave(cbs); | ||
| 743 | return; | ||
| 744 | } | ||
| 745 | |||
| 746 | |||
| 747 | /* CBSSetMinSize -- Set minimum interesting size for cbs | ||
| 748 | * | ||
| 749 | * This function may invoke the shrink and grow methods as | ||
| 750 | * appropriate. See <design/cbs/#function.cbs.set.min-size>. | ||
| 751 | */ | ||
| 752 | |||
| 753 | typedef struct { | ||
| 754 | Size old; | ||
| 755 | Size new; | ||
| 756 | } CBSSetMinSizeClosureStruct, *CBSSetMinSizeClosure; | ||
| 757 | |||
| 758 | static Bool cbsSetMinSizeGrow(CBS cbs, CBSBlock block, void *p) | ||
| 759 | { | ||
| 760 | CBSSetMinSizeClosure closure; | ||
| 761 | Size size; | ||
| 762 | |||
| 763 | closure = (CBSSetMinSizeClosure)p; | ||
| 764 | AVER(closure->old > closure->new); | ||
| 765 | size = CBSBlockSize(block); | ||
| 766 | if (size < closure->old && size >= closure->new) | ||
| 767 | (*cbs->new)(cbs, block, size, size); | ||
| 768 | |||
| 769 | return TRUE; | ||
| 770 | } | ||
| 771 | |||
| 772 | static Bool cbsSetMinSizeShrink(CBS cbs, CBSBlock block, void *p) | ||
| 773 | { | ||
| 774 | CBSSetMinSizeClosure closure; | ||
| 775 | Size size; | ||
| 776 | |||
| 777 | closure = (CBSSetMinSizeClosure)p; | ||
| 778 | AVER(closure->old < closure->new); | ||
| 779 | size = CBSBlockSize(block); | ||
| 780 | if (size >= closure->old && size < closure->new) | ||
| 781 | (*cbs->delete)(cbs, block, size, size); | ||
| 782 | |||
| 783 | return TRUE; | ||
| 784 | } | ||
| 785 | |||
| 786 | void CBSSetMinSize(CBS cbs, Size minSize) | ||
| 787 | { | ||
| 788 | CBSSetMinSizeClosureStruct closure; | ||
| 789 | |||
| 790 | AVERT(CBS, cbs); | ||
| 791 | CBSEnter(cbs); | ||
| 792 | |||
| 793 | closure.old = cbs->minSize; | ||
| 794 | closure.new = minSize; | ||
| 795 | |||
| 796 | if (minSize < cbs->minSize) | ||
| 797 | cbsIterateInternal(cbs, &cbsSetMinSizeGrow, (void *)&closure); | ||
| 798 | else if (minSize > cbs->minSize) | ||
| 799 | cbsIterateInternal(cbs, &cbsSetMinSizeShrink, (void *)&closure); | ||
| 800 | |||
| 801 | cbs->minSize = minSize; | ||
| 802 | |||
| 803 | CBSLeave(cbs); | ||
| 804 | } | ||
| 805 | |||
| 806 | |||
| 807 | /* CBSFindDeleteCheck -- check method for a CBSFindDelete value */ | 683 | /* CBSFindDeleteCheck -- check method for a CBSFindDelete value */ |
| 808 | 684 | ||
| 809 | static Bool CBSFindDeleteCheck(CBSFindDelete findDelete) | 685 | static Bool CBSFindDeleteCheck(CBSFindDelete findDelete) |
| @@ -817,13 +693,11 @@ static Bool CBSFindDeleteCheck(CBSFindDelete findDelete) | |||
| 817 | } | 693 | } |
| 818 | 694 | ||
| 819 | 695 | ||
| 820 | /* cbsFindDeleteRange -- delete approriate range of block found */ | 696 | /* cbsFindDeleteRange -- delete appropriate range of block found */ |
| 821 | |||
| 822 | typedef Res (*cbsDeleteMethod)(CBS cbs, Addr base, Addr limit); | ||
| 823 | 697 | ||
| 824 | static void cbsFindDeleteRange(Addr *baseReturn, Addr *limitReturn, | 698 | static void cbsFindDeleteRange(Addr *baseReturn, Addr *limitReturn, |
| 699 | Addr *oldBaseReturn, Addr *oldLimitReturn, | ||
| 825 | CBS cbs, Addr base, Addr limit, Size size, | 700 | CBS cbs, Addr base, Addr limit, Size size, |
| 826 | cbsDeleteMethod delete, | ||
| 827 | CBSFindDelete findDelete) | 701 | CBSFindDelete findDelete) |
| 828 | { | 702 | { |
| 829 | Bool callDelete = TRUE; | 703 | Bool callDelete = TRUE; |
| @@ -834,7 +708,6 @@ static void cbsFindDeleteRange(Addr *baseReturn, Addr *limitReturn, | |||
| 834 | AVER(base < limit); | 708 | AVER(base < limit); |
| 835 | AVER(size > 0); | 709 | AVER(size > 0); |
| 836 | AVER(AddrOffset(base, limit) >= size); | 710 | AVER(AddrOffset(base, limit) >= size); |
| 837 | AVER(FUNCHECK(delete)); | ||
| 838 | AVERT(CBSFindDelete, findDelete); | 711 | AVERT(CBSFindDelete, findDelete); |
| 839 | 712 | ||
| 840 | switch(findDelete) { | 713 | switch(findDelete) { |
| @@ -862,7 +735,7 @@ static void cbsFindDeleteRange(Addr *baseReturn, Addr *limitReturn, | |||
| 862 | 735 | ||
| 863 | if (callDelete) { | 736 | if (callDelete) { |
| 864 | Res res; | 737 | Res res; |
| 865 | res = (*delete)(cbs, base, limit); | 738 | res = cbsDeleteFromTree(oldBaseReturn, oldLimitReturn, cbs, base, limit); |
| 866 | AVER(res == ResOK); | 739 | AVER(res == ResOK); |
| 867 | } | 740 | } |
| 868 | 741 | ||
| @@ -874,11 +747,11 @@ static void cbsFindDeleteRange(Addr *baseReturn, Addr *limitReturn, | |||
| 874 | /* CBSFindFirst -- find the first block of at least the given size */ | 747 | /* CBSFindFirst -- find the first block of at least the given size */ |
| 875 | 748 | ||
| 876 | Bool CBSFindFirst(Addr *baseReturn, Addr *limitReturn, | 749 | Bool CBSFindFirst(Addr *baseReturn, Addr *limitReturn, |
| 750 | Addr *oldBaseReturn, Addr *oldLimitReturn, | ||
| 877 | CBS cbs, Size size, CBSFindDelete findDelete) | 751 | CBS cbs, Size size, CBSFindDelete findDelete) |
| 878 | { | 752 | { |
| 879 | Bool found; | 753 | Bool found; |
| 880 | Addr base = (Addr)0, limit = (Addr)0; /* only defined when found is TRUE */ | 754 | Addr base = (Addr)0, limit = (Addr)0; /* only defined when found is TRUE */ |
| 881 | cbsDeleteMethod deleteMethod = NULL; | ||
| 882 | 755 | ||
| 883 | AVERT(CBS, cbs); | 756 | AVERT(CBS, cbs); |
| 884 | CBSEnter(cbs); | 757 | CBSEnter(cbs); |
| @@ -904,14 +777,13 @@ Bool CBSFindFirst(Addr *baseReturn, Addr *limitReturn, | |||
| 904 | AVER(CBSBlockSize(block) >= size); | 777 | AVER(CBSBlockSize(block) >= size); |
| 905 | base = CBSBlockBase(block); | 778 | base = CBSBlockBase(block); |
| 906 | limit = CBSBlockLimit(block); | 779 | limit = CBSBlockLimit(block); |
| 907 | deleteMethod = &cbsDeleteFromTree; | ||
| 908 | } | 780 | } |
| 909 | } | 781 | } |
| 910 | 782 | ||
| 911 | if (found) { | 783 | if (found) { |
| 912 | AVER(AddrOffset(base, limit) >= size); | 784 | AVER(AddrOffset(base, limit) >= size); |
| 913 | cbsFindDeleteRange(baseReturn, limitReturn, cbs, base, limit, size, | 785 | cbsFindDeleteRange(baseReturn, limitReturn, oldBaseReturn, oldLimitReturn, |
| 914 | deleteMethod, findDelete); | 786 | cbs, base, limit, size, findDelete); |
| 915 | } | 787 | } |
| 916 | 788 | ||
| 917 | CBSLeave(cbs); | 789 | CBSLeave(cbs); |
| @@ -922,11 +794,11 @@ Bool CBSFindFirst(Addr *baseReturn, Addr *limitReturn, | |||
| 922 | /* CBSFindLast -- find the last block of at least the given size */ | 794 | /* CBSFindLast -- find the last block of at least the given size */ |
| 923 | 795 | ||
| 924 | Bool CBSFindLast(Addr *baseReturn, Addr *limitReturn, | 796 | Bool CBSFindLast(Addr *baseReturn, Addr *limitReturn, |
| 797 | Addr *oldBaseReturn, Addr *oldLimitReturn, | ||
| 925 | CBS cbs, Size size, CBSFindDelete findDelete) | 798 | CBS cbs, Size size, CBSFindDelete findDelete) |
| 926 | { | 799 | { |
| 927 | Bool found; | 800 | Bool found; |
| 928 | Addr base = (Addr)0, limit = (Addr)0; /* only defined in found is TRUE */ | 801 | Addr base = (Addr)0, limit = (Addr)0; /* only defined in found is TRUE */ |
| 929 | cbsDeleteMethod deleteMethod = NULL; | ||
| 930 | 802 | ||
| 931 | AVERT(CBS, cbs); | 803 | AVERT(CBS, cbs); |
| 932 | CBSEnter(cbs); | 804 | CBSEnter(cbs); |
| @@ -951,14 +823,13 @@ Bool CBSFindLast(Addr *baseReturn, Addr *limitReturn, | |||
| 951 | AVER(CBSBlockSize(block) >= size); | 823 | AVER(CBSBlockSize(block) >= size); |
| 952 | base = CBSBlockBase(block); | 824 | base = CBSBlockBase(block); |
| 953 | limit = CBSBlockLimit(block); | 825 | limit = CBSBlockLimit(block); |
| 954 | deleteMethod = &cbsDeleteFromTree; | ||
| 955 | } | 826 | } |
| 956 | } | 827 | } |
| 957 | 828 | ||
| 958 | if (found) { | 829 | if (found) { |
| 959 | AVER(AddrOffset(base, limit) >= size); | 830 | AVER(AddrOffset(base, limit) >= size); |
| 960 | cbsFindDeleteRange(baseReturn, limitReturn, cbs, base, limit, size, | 831 | cbsFindDeleteRange(baseReturn, limitReturn, oldBaseReturn, oldLimitReturn, |
| 961 | deleteMethod, findDelete); | 832 | cbs, base, limit, size, findDelete); |
| 962 | } | 833 | } |
| 963 | 834 | ||
| 964 | CBSLeave(cbs); | 835 | CBSLeave(cbs); |
| @@ -969,11 +840,11 @@ Bool CBSFindLast(Addr *baseReturn, Addr *limitReturn, | |||
| 969 | /* CBSFindLargest -- find the largest block in the CBS */ | 840 | /* CBSFindLargest -- find the largest block in the CBS */ |
| 970 | 841 | ||
| 971 | Bool CBSFindLargest(Addr *baseReturn, Addr *limitReturn, | 842 | Bool CBSFindLargest(Addr *baseReturn, Addr *limitReturn, |
| 843 | Addr *oldBaseReturn, Addr *oldLimitReturn, | ||
| 972 | CBS cbs, CBSFindDelete findDelete) | 844 | CBS cbs, CBSFindDelete findDelete) |
| 973 | { | 845 | { |
| 974 | Bool found = FALSE; | 846 | Bool found = FALSE; |
| 975 | Addr base = (Addr)0, limit = (Addr)0; /* only defined when found is TRUE */ | 847 | Addr base = (Addr)0, limit = (Addr)0; /* only defined when found is TRUE */ |
| 976 | cbsDeleteMethod deleteMethod = NULL; | ||
| 977 | Size size = 0; /* suppress bogus warning from MSVC */ | 848 | Size size = 0; /* suppress bogus warning from MSVC */ |
| 978 | 849 | ||
| 979 | AVERT(CBS, cbs); | 850 | AVERT(CBS, cbs); |
| @@ -1002,13 +873,12 @@ Bool CBSFindLargest(Addr *baseReturn, Addr *limitReturn, | |||
| 1002 | AVER(CBSBlockSize(block) >= size); | 873 | AVER(CBSBlockSize(block) >= size); |
| 1003 | base = CBSBlockBase(block); | 874 | base = CBSBlockBase(block); |
| 1004 | limit = CBSBlockLimit(block); | 875 | limit = CBSBlockLimit(block); |
| 1005 | deleteMethod = &cbsDeleteFromTree; | ||
| 1006 | } | 876 | } |
| 1007 | } | 877 | } |
| 1008 | 878 | ||
| 1009 | if (found) { | 879 | if (found) { |
| 1010 | cbsFindDeleteRange(baseReturn, limitReturn, cbs, base, limit, size, | 880 | cbsFindDeleteRange(baseReturn, limitReturn, oldBaseReturn, oldLimitReturn, |
| 1011 | deleteMethod, findDelete); | 881 | cbs, base, limit, size, findDelete); |
| 1012 | } | 882 | } |
| 1013 | 883 | ||
| 1014 | CBSLeave(cbs); | 884 | CBSLeave(cbs); |
| @@ -1031,8 +901,6 @@ Res CBSDescribe(CBS cbs, mps_lib_FILE *stream) | |||
| 1031 | res = WriteF(stream, | 901 | res = WriteF(stream, |
| 1032 | "CBS $P {\n", (WriteFP)cbs, | 902 | "CBS $P {\n", (WriteFP)cbs, |
| 1033 | " blockPool: $P\n", (WriteFP)cbs->blockPool, | 903 | " blockPool: $P\n", (WriteFP)cbs->blockPool, |
| 1034 | " new: $F ", (WriteFF)cbs->new, | ||
| 1035 | " delete: $F \n", (WriteFF)cbs->delete, | ||
| 1036 | NULL); | 904 | NULL); |
| 1037 | if (res != ResOK) return res; | 905 | if (res != ResOK) return res; |
| 1038 | 906 | ||
diff --git a/mps/code/cbs.h b/mps/code/cbs.h index ddbda2343f3..7662c9978ed 100644 --- a/mps/code/cbs.h +++ b/mps/code/cbs.h | |||
| @@ -15,10 +15,7 @@ | |||
| 15 | 15 | ||
| 16 | 16 | ||
| 17 | typedef struct CBSStruct *CBS; | 17 | typedef struct CBSStruct *CBS; |
| 18 | typedef struct CBSBlockStruct *CBSBlock; | 18 | typedef Bool (*CBSIterateMethod)(CBS cbs, Addr base, Addr limit, void *closureP); |
| 19 | typedef void (*CBSChangeSizeMethod)(CBS cbs, CBSBlock block, | ||
| 20 | Size oldSize, Size newSize); | ||
| 21 | typedef Bool (*CBSIterateMethod)(CBS cbs, CBSBlock block, void *closureP); | ||
| 22 | 19 | ||
| 23 | 20 | ||
| 24 | #define CBSSig ((Sig)0x519CB599) /* SIGnature CBS */ | 21 | #define CBSSig ((Sig)0x519CB599) /* SIGnature CBS */ |
| @@ -27,11 +24,6 @@ typedef struct CBSStruct { | |||
| 27 | SplayTreeStruct splayTree; | 24 | SplayTreeStruct splayTree; |
| 28 | Count splayTreeSize; | 25 | Count splayTreeSize; |
| 29 | Pool blockPool; | 26 | Pool blockPool; |
| 30 | CBSChangeSizeMethod new; | ||
| 31 | CBSChangeSizeMethod delete; | ||
| 32 | CBSChangeSizeMethod grow; | ||
| 33 | CBSChangeSizeMethod shrink; | ||
| 34 | Size minSize; | ||
| 35 | Align alignment; | 27 | Align alignment; |
| 36 | Bool fastFind; | 28 | Bool fastFind; |
| 37 | Bool inCBS; /* prevent reentrance */ | 29 | Bool inCBS; /* prevent reentrance */ |
| @@ -40,44 +32,19 @@ typedef struct CBSStruct { | |||
| 40 | Sig sig; /* sig at end because embeded */ | 32 | Sig sig; /* sig at end because embeded */ |
| 41 | } CBSStruct; | 33 | } CBSStruct; |
| 42 | 34 | ||
| 43 | typedef struct CBSBlockStruct { | ||
| 44 | SplayNodeStruct splayNode; | ||
| 45 | Addr base; | ||
| 46 | Addr limit; | ||
| 47 | Size maxSize; /* accurate maximum block size of sub-tree */ | ||
| 48 | } CBSBlockStruct; | ||
| 49 | |||
| 50 | |||
| 51 | extern Bool CBSCheck(CBS cbs); | 35 | extern Bool CBSCheck(CBS cbs); |
| 52 | extern Bool CBSBlockCheck(CBSBlock block); | ||
| 53 | 36 | ||
| 54 | extern Res CBSInit(Arena arena, CBS cbs, void *owner, | 37 | extern Res CBSInit(Arena arena, CBS cbs, void *owner, |
| 55 | CBSChangeSizeMethod new, | 38 | Align alignment, Bool fastFind); |
| 56 | CBSChangeSizeMethod delete, | ||
| 57 | CBSChangeSizeMethod grow, | ||
| 58 | CBSChangeSizeMethod shrink, | ||
| 59 | Size minSize, | ||
| 60 | Align alignment, | ||
| 61 | Bool fastFind); | ||
| 62 | extern void CBSFinish(CBS cbs); | 39 | extern void CBSFinish(CBS cbs); |
| 63 | 40 | ||
| 64 | extern Res CBSInsert(CBS cbs, Addr base, Addr limit); | 41 | extern Res CBSInsert(Addr *baseReturn, Addr *limitReturn, |
| 65 | extern Res CBSInsertReturningRange(Addr *baseReturn, Addr *limitReturn, | 42 | CBS cbs, Addr base, Addr limit); |
| 66 | CBS cbs, Addr base, Addr limit); | 43 | extern Res CBSDelete(Addr *baseReturn, Addr *limitReturn, |
| 67 | extern Res CBSDelete(CBS cbs, Addr base, Addr limit); | 44 | CBS cbs, Addr base, Addr limit); |
| 68 | extern void CBSIterate(CBS cbs, CBSIterateMethod iterate, void *closureP); | 45 | extern void CBSIterate(CBS cbs, CBSIterateMethod iterate, void *closureP); |
| 69 | extern void CBSIterateLarge(CBS cbs, CBSIterateMethod iterate, void *closureP); | ||
| 70 | extern void CBSSetMinSize(CBS cbs, Size minSize); | ||
| 71 | 46 | ||
| 72 | extern Res CBSDescribe(CBS cbs, mps_lib_FILE *stream); | 47 | extern Res CBSDescribe(CBS cbs, mps_lib_FILE *stream); |
| 73 | extern Res CBSBlockDescribe(CBSBlock block, mps_lib_FILE *stream); | ||
| 74 | |||
| 75 | /* CBSBlockBase -- See <design/cbs/#function.cbs.block.base> */ | ||
| 76 | #define CBSBlockBase(block) ((block)->base) | ||
| 77 | /* CBSBlockLimit -- See <design/cbs/#function.cbs.block.limit> */ | ||
| 78 | #define CBSBlockLimit(block) ((block)->limit) | ||
| 79 | #define CBSBlockSize(block) AddrOffset((block)->base, (block)->limit) | ||
| 80 | extern Size (CBSBlockSize)(CBSBlock block); | ||
| 81 | 48 | ||
| 82 | typedef unsigned CBSFindDelete; | 49 | typedef unsigned CBSFindDelete; |
| 83 | enum { | 50 | enum { |
| @@ -88,11 +55,13 @@ enum { | |||
| 88 | }; | 55 | }; |
| 89 | 56 | ||
| 90 | extern Bool CBSFindFirst(Addr *baseReturn, Addr *limitReturn, | 57 | extern Bool CBSFindFirst(Addr *baseReturn, Addr *limitReturn, |
| 58 | Addr *oldBaseReturn, Addr *oldLimitReturn, | ||
| 91 | CBS cbs, Size size, CBSFindDelete findDelete); | 59 | CBS cbs, Size size, CBSFindDelete findDelete); |
| 92 | extern Bool CBSFindLast(Addr *baseReturn, Addr *limitReturn, | 60 | extern Bool CBSFindLast(Addr *baseReturn, Addr *limitReturn, |
| 61 | Addr *oldBaseReturn, Addr *oldLimitReturn, | ||
| 93 | CBS cbs, Size size, CBSFindDelete findDelete); | 62 | CBS cbs, Size size, CBSFindDelete findDelete); |
| 94 | |||
| 95 | extern Bool CBSFindLargest(Addr *baseReturn, Addr *limitReturn, | 63 | extern Bool CBSFindLargest(Addr *baseReturn, Addr *limitReturn, |
| 64 | Addr *oldBaseReturn, Addr *oldLimitReturn, | ||
| 96 | CBS cbs, CBSFindDelete findDelete); | 65 | CBS cbs, CBSFindDelete findDelete); |
| 97 | 66 | ||
| 98 | 67 | ||
diff --git a/mps/code/cbstest.c b/mps/code/cbstest.c index adb976081e2..3b72e875c28 100644 --- a/mps/code/cbstest.c +++ b/mps/code/cbstest.c | |||
| @@ -20,28 +20,11 @@ SRCID(cbstest, "$Id$"); | |||
| 20 | 20 | ||
| 21 | #define ArraySize ((Size)123456) | 21 | #define ArraySize ((Size)123456) |
| 22 | #define NOperations ((Size)125000) | 22 | #define NOperations ((Size)125000) |
| 23 | #define MinSize ((Size)120) /* Arbitrary size */ | ||
| 24 | #define Alignment ((Align)sizeof(void *)) | 23 | #define Alignment ((Align)sizeof(void *)) |
| 25 | 24 | ||
| 26 | 25 | ||
| 27 | static Count NAllocateTried, NAllocateSucceeded, NDeallocateTried, | 26 | static Count NAllocateTried, NAllocateSucceeded, NDeallocateTried, |
| 28 | NDeallocateSucceeded, NNewBlocks, NDeleteBlocks, NGrowBlocks, | 27 | NDeallocateSucceeded; |
| 29 | NShrinkBlocks; | ||
| 30 | |||
| 31 | |||
| 32 | /* Used to predict which callbacks will be called, and with which values. */ | ||
| 33 | /* At most one callback of each type will be called. */ | ||
| 34 | typedef struct CallbackPredictionStruct { | ||
| 35 | Bool shouldBeCalled; | ||
| 36 | Size oldSize; | ||
| 37 | Addr base; | ||
| 38 | Addr limit; | ||
| 39 | } CallbackPredictionStruct, *CallbackPrediction; | ||
| 40 | |||
| 41 | static CallbackPredictionStruct CallbackNew; | ||
| 42 | static CallbackPredictionStruct CallbackDelete; | ||
| 43 | static CallbackPredictionStruct CallbackGrow; | ||
| 44 | static CallbackPredictionStruct CallbackShrink; | ||
| 45 | 28 | ||
| 46 | 29 | ||
| 47 | typedef struct CheckCBSClosureStruct { | 30 | typedef struct CheckCBSClosureStruct { |
| @@ -64,89 +47,14 @@ static Index (indexOfAddr)(Addr block, Addr a) | |||
| 64 | } | 47 | } |
| 65 | 48 | ||
| 66 | 49 | ||
| 67 | /* This function encapsulates the common tests for the callbacks. */ | 50 | static Bool checkCBSAction(CBS cbs, Addr base, Addr limit, void *p) |
| 68 | |||
| 69 | static void testCallback(CBS cbs, CBSBlock cbsBlock, | ||
| 70 | Size oldSize, Size newSize, | ||
| 71 | CallbackPrediction prediction) | ||
| 72 | { | ||
| 73 | Insist(CBSCheck(cbs)); | ||
| 74 | Insist(CBSBlockCheck(cbsBlock)); | ||
| 75 | Insist(prediction->shouldBeCalled); | ||
| 76 | Insist(oldSize == prediction->oldSize); | ||
| 77 | |||
| 78 | if (newSize == 0) { | ||
| 79 | Insist(prediction->base == 0); | ||
| 80 | Insist(prediction->limit == 0); | ||
| 81 | } else { | ||
| 82 | Insist(CBSBlockSize(cbsBlock) == newSize); | ||
| 83 | Insist(newSize == AddrOffset(prediction->base, prediction->limit)); | ||
| 84 | Insist(CBSBlockBase(cbsBlock) == prediction->base); | ||
| 85 | Insist(CBSBlockLimit(cbsBlock) == prediction->limit); | ||
| 86 | } | ||
| 87 | |||
| 88 | prediction->shouldBeCalled = FALSE; | ||
| 89 | } | ||
| 90 | |||
| 91 | |||
| 92 | static void cbsNewCallback(CBS cbs, CBSBlock cbsBlock, | ||
| 93 | Size oldSize, Size newSize) | ||
| 94 | { | 51 | { |
| 95 | testCallback(cbs, cbsBlock, oldSize, newSize, &CallbackNew); | ||
| 96 | Insist(oldSize < cbs->minSize); | ||
| 97 | Insist(newSize >= cbs->minSize); | ||
| 98 | |||
| 99 | NNewBlocks++; | ||
| 100 | } | ||
| 101 | |||
| 102 | |||
| 103 | static void cbsDeleteCallback(CBS cbs, CBSBlock cbsBlock, | ||
| 104 | Size oldSize, Size newSize) | ||
| 105 | { | ||
| 106 | testCallback(cbs, cbsBlock, oldSize, newSize, &CallbackDelete); | ||
| 107 | Insist(oldSize >= cbs->minSize); | ||
| 108 | Insist(newSize < cbs->minSize); | ||
| 109 | |||
| 110 | NDeleteBlocks++; | ||
| 111 | } | ||
| 112 | |||
| 113 | |||
| 114 | static void cbsGrowCallback(CBS cbs, CBSBlock cbsBlock, | ||
| 115 | Size oldSize, Size newSize) | ||
| 116 | { | ||
| 117 | testCallback(cbs, cbsBlock, oldSize, newSize, &CallbackGrow); | ||
| 118 | Insist(oldSize >= cbs->minSize); | ||
| 119 | Insist(newSize >= cbs->minSize); | ||
| 120 | Insist(oldSize < newSize); | ||
| 121 | |||
| 122 | NGrowBlocks++; | ||
| 123 | } | ||
| 124 | |||
| 125 | |||
| 126 | static void cbsShrinkCallback(CBS cbs, CBSBlock cbsBlock, | ||
| 127 | Size oldSize, Size newSize) | ||
| 128 | { | ||
| 129 | testCallback(cbs, cbsBlock, oldSize, newSize, &CallbackShrink); | ||
| 130 | Insist(oldSize >= cbs->minSize); | ||
| 131 | Insist(newSize >= cbs->minSize); | ||
| 132 | Insist(oldSize > newSize); | ||
| 133 | |||
| 134 | NShrinkBlocks++; | ||
| 135 | } | ||
| 136 | |||
| 137 | |||
| 138 | static Bool checkCBSAction(CBS cbs, CBSBlock cbsBlock, void *p) | ||
| 139 | { | ||
| 140 | Addr base, limit; | ||
| 141 | CheckCBSClosure closure = (CheckCBSClosure)p; | 52 | CheckCBSClosure closure = (CheckCBSClosure)p; |
| 142 | 53 | ||
| 143 | /* Don't need to check cbs every time */ | 54 | /* Don't need to check cbs every time */ |
| 144 | UNUSED(cbs); | 55 | UNUSED(cbs); |
| 145 | Insist(closure != NULL); | 56 | Insist(closure != NULL); |
| 146 | 57 | ||
| 147 | base = CBSBlockBase(cbsBlock); | ||
| 148 | limit = CBSBlockLimit(cbsBlock); | ||
| 149 | |||
| 150 | if (base > closure->oldLimit) { | 58 | if (base > closure->oldLimit) { |
| 151 | Insist(BTIsSetRange(closure->allocTable, | 59 | Insist(BTIsSetRange(closure->allocTable, |
| 152 | indexOfAddr(closure->base, closure->oldLimit), | 60 | indexOfAddr(closure->base, closure->oldLimit), |
| @@ -285,46 +193,14 @@ static void randomRange(Addr *baseReturn, Addr *limitReturn, | |||
| 285 | } | 193 | } |
| 286 | 194 | ||
| 287 | 195 | ||
| 288 | /* Set callback expectations */ | ||
| 289 | |||
| 290 | static void clearExpectations(void) | ||
| 291 | { | ||
| 292 | CallbackNew.shouldBeCalled = FALSE; | ||
| 293 | CallbackDelete.shouldBeCalled = FALSE; | ||
| 294 | CallbackGrow.shouldBeCalled = FALSE; | ||
| 295 | CallbackShrink.shouldBeCalled = FALSE; | ||
| 296 | } | ||
| 297 | |||
| 298 | static void expectCallback(CallbackPrediction prediction, | ||
| 299 | Size oldSize, Addr base, Addr limit) | ||
| 300 | { | ||
| 301 | Insist(prediction->shouldBeCalled == FALSE); | ||
| 302 | Insist(base == (Addr)0 || limit > base); | ||
| 303 | Insist(oldSize != (Size)0 || base != (Addr)0); | ||
| 304 | Insist(base != (Addr)0 || limit == (Addr)0); | ||
| 305 | |||
| 306 | prediction->shouldBeCalled = TRUE; | ||
| 307 | prediction->oldSize = oldSize; | ||
| 308 | prediction->base = base; | ||
| 309 | prediction->limit = limit; | ||
| 310 | } | ||
| 311 | |||
| 312 | |||
| 313 | static void checkExpectations(void) | ||
| 314 | { | ||
| 315 | Insist(!CallbackNew.shouldBeCalled); | ||
| 316 | Insist(!CallbackDelete.shouldBeCalled); | ||
| 317 | Insist(!CallbackGrow.shouldBeCalled); | ||
| 318 | Insist(!CallbackShrink.shouldBeCalled); | ||
| 319 | } | ||
| 320 | |||
| 321 | |||
| 322 | static void allocate(CBS cbs, Addr block, BT allocTable, | 196 | static void allocate(CBS cbs, Addr block, BT allocTable, |
| 323 | Addr base, Addr limit) | 197 | Addr base, Addr limit) |
| 324 | { | 198 | { |
| 325 | Res res; | 199 | Res res; |
| 326 | Index ib, il; /* Indexed for base and limit */ | 200 | Index ib, il; /* Indexed for base and limit */ |
| 327 | Bool isFree; | 201 | Bool isFree; |
| 202 | Addr oldBase, oldLimit; | ||
| 203 | Addr outerBase, outerLimit; /* interval containing [ib, il) */ | ||
| 328 | 204 | ||
| 329 | ib = indexOfAddr(block, base); | 205 | ib = indexOfAddr(block, base); |
| 330 | il = indexOfAddr(block, limit); | 206 | il = indexOfAddr(block, limit); |
| @@ -339,7 +215,6 @@ static void allocate(CBS cbs, Addr block, BT allocTable, | |||
| 339 | NAllocateTried++; | 215 | NAllocateTried++; |
| 340 | 216 | ||
| 341 | if (isFree) { | 217 | if (isFree) { |
| 342 | Addr outerBase, outerLimit; /* interval containing [ib, il) */ | ||
| 343 | Size left, right, total; /* Sizes of block and two fragments */ | 218 | Size left, right, total; /* Sizes of block and two fragments */ |
| 344 | 219 | ||
| 345 | outerBase = | 220 | outerBase = |
| @@ -350,39 +225,9 @@ static void allocate(CBS cbs, Addr block, BT allocTable, | |||
| 350 | left = AddrOffset(outerBase, base); | 225 | left = AddrOffset(outerBase, base); |
| 351 | right = AddrOffset(limit, outerLimit); | 226 | right = AddrOffset(limit, outerLimit); |
| 352 | total = AddrOffset(outerBase, outerLimit); | 227 | total = AddrOffset(outerBase, outerLimit); |
| 353 | |||
| 354 | /* based on detailed knowledge of CBS behaviour */ | ||
| 355 | checkExpectations(); | ||
| 356 | if (total >= MinSize && left < MinSize && right < MinSize) { | ||
| 357 | if (left == (Size)0 && right == (Size)0) { | ||
| 358 | expectCallback(&CallbackDelete, total, (Addr)0, (Addr)0); | ||
| 359 | } else if (left >= right) { | ||
| 360 | expectCallback(&CallbackDelete, total, outerBase, base); | ||
| 361 | } else { | ||
| 362 | expectCallback(&CallbackDelete, total, limit, outerLimit); | ||
| 363 | } | ||
| 364 | } else if (left >= MinSize && right >= MinSize) { | ||
| 365 | if (left >= right) { | ||
| 366 | expectCallback(&CallbackShrink, total, outerBase, base); | ||
| 367 | expectCallback(&CallbackNew, (Size)0, limit, outerLimit); | ||
| 368 | } else { | ||
| 369 | expectCallback(&CallbackNew, (Size)0, outerBase, base); | ||
| 370 | expectCallback(&CallbackShrink, total, limit, outerLimit); | ||
| 371 | } | ||
| 372 | } else if (total >= MinSize) { | ||
| 373 | if (left >= right) { | ||
| 374 | Insist(left >= MinSize); | ||
| 375 | Insist(right < MinSize); | ||
| 376 | expectCallback(&CallbackShrink, total, outerBase, base); | ||
| 377 | } else { | ||
| 378 | Insist(left < MinSize); | ||
| 379 | Insist(right >= MinSize); | ||
| 380 | expectCallback(&CallbackShrink, total, limit, outerLimit); | ||
| 381 | } | ||
| 382 | } | ||
| 383 | } | 228 | } |
| 384 | 229 | ||
| 385 | res = CBSDelete(cbs, base, limit); | 230 | res = CBSDelete(&oldBase, &oldLimit, cbs, base, limit); |
| 386 | 231 | ||
| 387 | if (!isFree) { | 232 | if (!isFree) { |
| 388 | die_expect((mps_res_t)res, MPS_RES_FAIL, | 233 | die_expect((mps_res_t)res, MPS_RES_FAIL, |
| @@ -390,9 +235,10 @@ static void allocate(CBS cbs, Addr block, BT allocTable, | |||
| 390 | } else { /* isFree */ | 235 | } else { /* isFree */ |
| 391 | die_expect((mps_res_t)res, MPS_RES_OK, | 236 | die_expect((mps_res_t)res, MPS_RES_OK, |
| 392 | "failed to delete free block"); | 237 | "failed to delete free block"); |
| 238 | Insist(oldBase == outerBase); | ||
| 239 | Insist(oldLimit == outerLimit); | ||
| 393 | NAllocateSucceeded++; | 240 | NAllocateSucceeded++; |
| 394 | BTSetRange(allocTable, ib, il); | 241 | BTSetRange(allocTable, ib, il); |
| 395 | checkExpectations(); | ||
| 396 | } | 242 | } |
| 397 | } | 243 | } |
| 398 | 244 | ||
| @@ -439,36 +285,9 @@ static void deallocate(CBS cbs, Addr block, BT allocTable, | |||
| 439 | left = AddrOffset(outerBase, base); | 285 | left = AddrOffset(outerBase, base); |
| 440 | right = AddrOffset(limit, outerLimit); | 286 | right = AddrOffset(limit, outerLimit); |
| 441 | total = AddrOffset(outerBase, outerLimit); | 287 | total = AddrOffset(outerBase, outerLimit); |
| 442 | |||
| 443 | /* based on detailed knowledge of CBS behaviour */ | ||
| 444 | checkExpectations(); | ||
| 445 | if (total >= MinSize && left < MinSize && right < MinSize) { | ||
| 446 | if (left >= right) | ||
| 447 | expectCallback(&CallbackNew, left, outerBase, outerLimit); | ||
| 448 | else | ||
| 449 | expectCallback(&CallbackNew, right, outerBase, outerLimit); | ||
| 450 | } else if (left >= MinSize && right >= MinSize) { | ||
| 451 | if (left >= right) { | ||
| 452 | expectCallback(&CallbackDelete, right, (Addr)0, (Addr)0); | ||
| 453 | expectCallback(&CallbackGrow, left, outerBase, outerLimit); | ||
| 454 | } else { | ||
| 455 | expectCallback(&CallbackDelete, left, (Addr)0, (Addr)0); | ||
| 456 | expectCallback(&CallbackGrow, right, outerBase, outerLimit); | ||
| 457 | } | ||
| 458 | } else if (total >= MinSize) { | ||
| 459 | if (left >= right) { | ||
| 460 | Insist(left >= MinSize); | ||
| 461 | Insist(right < MinSize); | ||
| 462 | expectCallback(&CallbackGrow, left, outerBase, outerLimit); | ||
| 463 | } else { | ||
| 464 | Insist(left < MinSize); | ||
| 465 | Insist(right >= MinSize); | ||
| 466 | expectCallback(&CallbackGrow, right, outerBase, outerLimit); | ||
| 467 | } | ||
| 468 | } | ||
| 469 | } | 288 | } |
| 470 | 289 | ||
| 471 | res = CBSInsertReturningRange(&freeBase, &freeLimit, cbs, base, limit); | 290 | res = CBSInsert(&freeBase, &freeLimit, cbs, base, limit); |
| 472 | 291 | ||
| 473 | if (!isAllocated) { | 292 | if (!isAllocated) { |
| 474 | die_expect((mps_res_t)res, MPS_RES_FAIL, | 293 | die_expect((mps_res_t)res, MPS_RES_FAIL, |
| @@ -479,7 +298,6 @@ static void deallocate(CBS cbs, Addr block, BT allocTable, | |||
| 479 | 298 | ||
| 480 | NDeallocateSucceeded++; | 299 | NDeallocateSucceeded++; |
| 481 | BTResRange(allocTable, ib, il); | 300 | BTResRange(allocTable, ib, il); |
| 482 | checkExpectations(); | ||
| 483 | Insist(freeBase == outerBase); | 301 | Insist(freeBase == outerBase); |
| 484 | Insist(freeLimit == outerLimit); | 302 | Insist(freeLimit == outerLimit); |
| 485 | } | 303 | } |
| @@ -492,18 +310,17 @@ static void find(CBS cbs, void *block, BT alloc, Size size, Bool high, | |||
| 492 | Bool expected, found; | 310 | Bool expected, found; |
| 493 | Index expectedBase, expectedLimit; | 311 | Index expectedBase, expectedLimit; |
| 494 | Addr foundBase, foundLimit, remainderBase, remainderLimit; | 312 | Addr foundBase, foundLimit, remainderBase, remainderLimit; |
| 313 | Addr oldBase, oldLimit, origBase, origLimit; | ||
| 495 | Size oldSize, newSize; | 314 | Size oldSize, newSize; |
| 496 | 315 | ||
| 497 | checkExpectations(); | ||
| 498 | |||
| 499 | expected = (high ? BTFindLongResRangeHigh : BTFindLongResRange) | 316 | expected = (high ? BTFindLongResRangeHigh : BTFindLongResRange) |
| 500 | (&expectedBase, &expectedLimit, alloc, | 317 | (&expectedBase, &expectedLimit, alloc, |
| 501 | (Index)0, (Index)ArraySize, (Count)size); | 318 | (Index)0, (Index)ArraySize, (Count)size); |
| 502 | 319 | ||
| 503 | if (expected) { | 320 | if (expected) { |
| 504 | oldSize = (expectedLimit - expectedBase) * Alignment; | 321 | oldSize = (expectedLimit - expectedBase) * Alignment; |
| 505 | remainderBase = addrOfIndex(block, expectedBase); | 322 | remainderBase = origBase = addrOfIndex(block, expectedBase); |
| 506 | remainderLimit = addrOfIndex(block, expectedLimit); | 323 | remainderLimit = origLimit = addrOfIndex(block, expectedLimit); |
| 507 | 324 | ||
| 508 | switch(findDelete) { | 325 | switch(findDelete) { |
| 509 | case CBSFindDeleteNONE: { | 326 | case CBSFindDeleteNONE: { |
| @@ -524,32 +341,24 @@ static void find(CBS cbs, void *block, BT alloc, Size size, Bool high, | |||
| 524 | 341 | ||
| 525 | if (findDelete != CBSFindDeleteNONE) { | 342 | if (findDelete != CBSFindDeleteNONE) { |
| 526 | newSize = AddrOffset(remainderBase, remainderLimit); | 343 | newSize = AddrOffset(remainderBase, remainderLimit); |
| 527 | |||
| 528 | if (oldSize >= MinSize) { | ||
| 529 | if (newSize == 0) | ||
| 530 | expectCallback(&CallbackDelete, oldSize, (Addr)0, (Addr)0); | ||
| 531 | else if (newSize < MinSize) | ||
| 532 | expectCallback(&CallbackDelete, oldSize, | ||
| 533 | remainderBase, remainderLimit); | ||
| 534 | else | ||
| 535 | expectCallback(&CallbackShrink, oldSize, | ||
| 536 | remainderBase, remainderLimit); | ||
| 537 | } | ||
| 538 | } | 344 | } |
| 539 | } | 345 | } |
| 540 | 346 | ||
| 541 | found = (high ? CBSFindLast : CBSFindFirst) | 347 | found = (high ? CBSFindLast : CBSFindFirst) |
| 542 | (&foundBase, &foundLimit, cbs, size * Alignment, findDelete); | 348 | (&foundBase, &foundLimit, &oldBase, &oldLimit, |
| 349 | cbs, size * Alignment, findDelete); | ||
| 543 | 350 | ||
| 544 | Insist(found == expected); | 351 | Insist(found == expected); |
| 545 | 352 | ||
| 546 | if (found) { | 353 | if (found) { |
| 547 | Insist(expectedBase == indexOfAddr(block, foundBase)); | 354 | Insist(expectedBase == indexOfAddr(block, foundBase)); |
| 548 | Insist(expectedLimit == indexOfAddr(block, foundLimit)); | 355 | Insist(expectedLimit == indexOfAddr(block, foundLimit)); |
| 549 | checkExpectations(); | ||
| 550 | 356 | ||
| 551 | if (findDelete != CBSFindDeleteNONE) | 357 | if (findDelete != CBSFindDeleteNONE) { |
| 358 | Insist(oldBase == origBase); | ||
| 359 | Insist(oldLimit == origLimit); | ||
| 552 | BTSetRange(alloc, expectedBase, expectedLimit); | 360 | BTSetRange(alloc, expectedBase, expectedLimit); |
| 361 | } | ||
| 553 | } | 362 | } |
| 554 | 363 | ||
| 555 | return; | 364 | return; |
| @@ -576,10 +385,7 @@ extern int main(int argc, char *argv[]) | |||
| 576 | randomize(argc, argv); | 385 | randomize(argc, argv); |
| 577 | 386 | ||
| 578 | NAllocateTried = NAllocateSucceeded = NDeallocateTried = | 387 | NAllocateTried = NAllocateSucceeded = NDeallocateTried = |
| 579 | NDeallocateSucceeded = NNewBlocks = NDeleteBlocks = | 388 | NDeallocateSucceeded = 0; |
| 580 | NGrowBlocks = NShrinkBlocks = 0; | ||
| 581 | |||
| 582 | clearExpectations(); | ||
| 583 | 389 | ||
| 584 | die(mps_arena_create(&mpsArena, mps_arena_class_vm(), testArenaSIZE), | 390 | die(mps_arena_create(&mpsArena, mps_arena_class_vm(), testArenaSIZE), |
| 585 | "mps_arena_create"); | 391 | "mps_arena_create"); |
| @@ -588,10 +394,7 @@ extern int main(int argc, char *argv[]) | |||
| 588 | die((mps_res_t)BTCreate(&allocTable, arena, ArraySize), | 394 | die((mps_res_t)BTCreate(&allocTable, arena, ArraySize), |
| 589 | "failed to create alloc table"); | 395 | "failed to create alloc table"); |
| 590 | 396 | ||
| 591 | die((mps_res_t)CBSInit(arena, &cbsStruct, NULL, &cbsNewCallback, | 397 | die((mps_res_t)CBSInit(arena, &cbsStruct, NULL, Alignment, TRUE), |
| 592 | &cbsDeleteCallback, &cbsGrowCallback, | ||
| 593 | &cbsShrinkCallback, MinSize, | ||
| 594 | Alignment, TRUE), | ||
| 595 | "failed to initialise CBS"); | 398 | "failed to initialise CBS"); |
| 596 | cbs = &cbsStruct; | 399 | cbs = &cbsStruct; |
| 597 | 400 | ||
| @@ -636,8 +439,6 @@ extern int main(int argc, char *argv[]) | |||
| 636 | checkCBS(cbs, allocTable, dummyBlock); | 439 | checkCBS(cbs, allocTable, dummyBlock); |
| 637 | } | 440 | } |
| 638 | 441 | ||
| 639 | checkExpectations(); | ||
| 640 | |||
| 641 | /* CBSDescribe prints a very long line. */ | 442 | /* CBSDescribe prints a very long line. */ |
| 642 | /* CBSDescribe(cbs, mps_lib_get_stdout()); */ | 443 | /* CBSDescribe(cbs, mps_lib_get_stdout()); */ |
| 643 | 444 | ||
| @@ -645,10 +446,6 @@ extern int main(int argc, char *argv[]) | |||
| 645 | printf("Number of allocations succeeded: %ld\n", NAllocateSucceeded); | 446 | printf("Number of allocations succeeded: %ld\n", NAllocateSucceeded); |
| 646 | printf("Number of deallocations attempted: %ld\n", NDeallocateTried); | 447 | printf("Number of deallocations attempted: %ld\n", NDeallocateTried); |
| 647 | printf("Number of deallocations succeeded: %ld\n", NDeallocateSucceeded); | 448 | printf("Number of deallocations succeeded: %ld\n", NDeallocateSucceeded); |
| 648 | printf("Number of new large blocks: %ld\n", NNewBlocks); | ||
| 649 | printf("Number of deleted large blocks: %ld\n", NDeleteBlocks); | ||
| 650 | printf("Number of grown large blocks: %ld\n", NGrowBlocks); | ||
| 651 | printf("Number of shrunk large blocks: %ld\n", NShrinkBlocks); | ||
| 652 | printf("%s: Conclusion: Failed to find any defects.\n", argv[0]); | 449 | printf("%s: Conclusion: Failed to find any defects.\n", argv[0]); |
| 653 | return 0; | 450 | return 0; |
| 654 | } | 451 | } |