diff options
| author | Nick Barnes | 2001-10-31 14:40:56 +0000 |
|---|---|---|
| committer | Nick Barnes | 2001-10-31 14:40:56 +0000 |
| commit | 7acfca905d76140f4cc0b09c9a12de237de364cd (patch) | |
| tree | 3ed8babfa3a73d30f29e08ca5d5adcda4ca4e826 /mps/code/boot.c | |
| parent | b7ce4893f9902d57cd67ac9a92fa6c3d5a8fc833 (diff) | |
| download | emacs-7acfca905d76140f4cc0b09c9a12de237de364cd.tar.gz emacs-7acfca905d76140f4cc0b09c9a12de237de364cd.zip | |
Branch imports for masters.
Copied from Perforce
Change: 23678
ServerID: perforce.ravenbrook.com
Diffstat (limited to 'mps/code/boot.c')
| -rw-r--r-- | mps/code/boot.c | 125 |
1 files changed, 125 insertions, 0 deletions
diff --git a/mps/code/boot.c b/mps/code/boot.c new file mode 100644 index 00000000000..7888c8e381e --- /dev/null +++ b/mps/code/boot.c | |||
| @@ -0,0 +1,125 @@ | |||
| 1 | /* impl.c.boot: BOOTSTRAP ALLOCATOR | ||
| 2 | * | ||
| 3 | * $HopeName: MMsrc!boot.c(MMdevel_pekka_locus.2) $ | ||
| 4 | * Copyright (C) 1999 Harlequin Limited. All rights reserved. | ||
| 5 | * | ||
| 6 | * .overview: A structure and protocols for allocating memory from a | ||
| 7 | * given block. Very simple, it basically just increments a pointer. | ||
| 8 | * | ||
| 9 | * .boot.c: The Bootstrap Allocator is used to allocate C structures | ||
| 10 | * for use in the implementation, not client objects. Therefore, | ||
| 11 | * we use "C types" (void *, size_t) not "client types" (Addr, Size). | ||
| 12 | */ | ||
| 13 | |||
| 14 | #include "boot.h" | ||
| 15 | #include "mpm.h" | ||
| 16 | |||
| 17 | SRCID(boot, "$HopeName: MMsrc!boot.c(MMdevel_pekka_locus.2) $"); | ||
| 18 | |||
| 19 | |||
| 20 | #define BootBlockSig ((Sig)0x519B002B) /* SIGnature BOOT Block */ | ||
| 21 | |||
| 22 | |||
| 23 | /* BootBlockCheck -- check a BootBlock structure */ | ||
| 24 | |||
| 25 | Bool BootBlockCheck(BootBlock boot) | ||
| 26 | { | ||
| 27 | CHECKS(BootBlock, boot); | ||
| 28 | CHECKL(boot->base != NULL); | ||
| 29 | CHECKL(boot->alloc != NULL); | ||
| 30 | CHECKL(boot->limit != NULL); | ||
| 31 | CHECKL(boot->base <= boot->alloc); | ||
| 32 | CHECKL(boot->alloc <= boot->limit); | ||
| 33 | CHECKL(boot->alloc < boot->limit); | ||
| 34 | |||
| 35 | return TRUE; | ||
| 36 | } | ||
| 37 | |||
| 38 | |||
| 39 | /* BootBlockInit -- initialize a BootBlock | ||
| 40 | * | ||
| 41 | * boot: a pointer to the structure to be initialized | ||
| 42 | * (must have been allocated by the caller, probably on the stack). | ||
| 43 | * base: a pointer to the base of the memory to be allocated from | ||
| 44 | * from (the memory need not be committed) | ||
| 45 | * limit: a pointer to the limit of the memory to be allocated from | ||
| 46 | */ | ||
| 47 | |||
| 48 | Res BootBlockInit(BootBlockStruct *boot, void *base, void *limit) | ||
| 49 | { | ||
| 50 | /* Can't check boot as we are supposed to be initializing it */ | ||
| 51 | AVER(boot != NULL); | ||
| 52 | AVER(base != NULL); | ||
| 53 | AVER(limit != NULL); | ||
| 54 | AVER(base < limit); | ||
| 55 | |||
| 56 | boot->base = base; | ||
| 57 | boot->alloc = base; | ||
| 58 | boot->limit = limit; | ||
| 59 | boot->sig = BootBlockSig; | ||
| 60 | |||
| 61 | AVERT(BootBlock, boot); | ||
| 62 | return ResOK; | ||
| 63 | } | ||
| 64 | |||
| 65 | |||
| 66 | /* BootBlockFinish -- finish a BootBlock structure */ | ||
| 67 | |||
| 68 | void BootBlockFinish(BootBlock boot) | ||
| 69 | { | ||
| 70 | AVERT(BootBlock, boot); | ||
| 71 | |||
| 72 | boot->base = boot->alloc = boot->limit = NULL; | ||
| 73 | boot->sig = SigInvalid; | ||
| 74 | } | ||
| 75 | |||
| 76 | |||
| 77 | /* BootAllocated | ||
| 78 | * | ||
| 79 | * Returns the total amount allocated using this descriptor | ||
| 80 | */ | ||
| 81 | size_t BootAllocated(BootBlock boot) | ||
| 82 | { | ||
| 83 | AVERT(BootBlock, boot); | ||
| 84 | |||
| 85 | return PointerOffset(boot->base, boot->alloc); | ||
| 86 | } | ||
| 87 | |||
| 88 | |||
| 89 | /* BootAlloc -- allocate from BootBlock structure | ||
| 90 | * | ||
| 91 | * preturn: The returned pointer, see .boot.c. | ||
| 92 | * boot: must have been initialized with BootBlockInit(). | ||
| 93 | * size: size of requested object, see .boot.c. | ||
| 94 | * align: required alignment of object, see .boot.c. | ||
| 95 | */ | ||
| 96 | |||
| 97 | Res BootAlloc(void **pReturn, BootBlock boot, size_t size, size_t align) | ||
| 98 | { | ||
| 99 | void *blockBase, *blockLimit; /* base, limit of candidate block */ | ||
| 100 | |||
| 101 | AVER(pReturn != NULL); | ||
| 102 | AVERT(BootBlock, boot); | ||
| 103 | AVER(size > 0); | ||
| 104 | AVER(AlignCheck((Align)align)); | ||
| 105 | |||
| 106 | /* Align alloc pointer up and bounds check. */ | ||
| 107 | blockBase = PointerAlignUp(boot->alloc, align); | ||
| 108 | if(boot->limit <= blockBase || blockBase < boot->alloc) { | ||
| 109 | return ResMEMORY; | ||
| 110 | } | ||
| 111 | blockLimit = PointerAdd(blockBase, size); | ||
| 112 | /* Following checks that the ordering constraint holds: */ | ||
| 113 | /* boot->alloc <= blockBase < blockLimit <= boot->limit */ | ||
| 114 | /* (if it doesn't hold then something overallocated/wrapped round) */ | ||
| 115 | if(blockBase < boot->alloc || | ||
| 116 | blockLimit <= blockBase || | ||
| 117 | boot->limit < blockLimit) { | ||
| 118 | return ResMEMORY; | ||
| 119 | } | ||
| 120 | |||
| 121 | /* Fits! So allocate it */ | ||
| 122 | boot->alloc = blockLimit; | ||
| 123 | *pReturn = blockBase; | ||
| 124 | return ResOK; | ||
| 125 | } | ||