| 112 | } |
| 113 | |
| 114 | void* Alloc(int size) |
| 115 | { |
| 116 | int numPages = (size + sizeof(SA_AllocHeader) + PAGE_SIZE - 1) / PAGE_SIZE; |
| 117 | |
| 118 | int startIdx = FindFreeRange(numPages, mLastUsedIdx + 1, NUM_PAGES); |
| 119 | if (startIdx == -1) |
| 120 | startIdx = FindFreeRange(numPages, 0, mLastUsedIdx); |
| 121 | if (startIdx == -1) |
| 122 | return NULL; |
| 123 | |
| 124 | mLastUsedIdx = startIdx + numPages - 1; |
| 125 | for (int markIdx = startIdx; markIdx < startIdx + numPages; markIdx++) |
| 126 | { |
| 127 | mUsedBits.Set(markIdx); |
| 128 | } |
| 129 | |
| 130 | uint8* ptr = mMemory + startIdx*PAGE_SIZE; |
| 131 | auto allocHeader = (SA_AllocHeader*)ptr; |
| 132 | ::VirtualAlloc(ptr, numPages * PAGE_SIZE, MEM_COMMIT, PAGE_READWRITE); |
| 133 | |
| 134 | allocHeader->mNumPages = numPages; |
| 135 | allocHeader->mMagic = STOMP_MAGIC; |
| 136 | |
| 137 | int alignedOffset = sizeof(SA_AllocHeader); |
| 138 | bool alignAtEnd = true; |
| 139 | if (alignAtEnd) |
| 140 | { |
| 141 | alignedOffset = (PAGE_SIZE - (size % PAGE_SIZE)); |
| 142 | if (alignedOffset < sizeof(SA_AllocHeader)) |
| 143 | { |
| 144 | // For cases where the alloc size (mod PAGE_SIZE) is almost equal to the page size, we need to bump the offset into the next page |
| 145 | // so we don't clobber the SA_AllocHeader |
| 146 | alignedOffset += PAGE_SIZE; |
| 147 | } |
| 148 | } |
| 149 | return ptr + alignedOffset; |
| 150 | } |
| 151 | |
| 152 | bool Free(void* ptr, bool leaveAllocated = false) |
| 153 | { |