Updated some CS:GO gamedata.
1 #include "KePlatform.h"
2 #include <KeLumpAllocator.h>
5 using namespace Knight;
8 * :TODO: don't make this part of the page, because touching it means
9 * dirtying a page. Instead, we should have a separate linked list.
10 * Maybe that linked list itself could be marshalled from one page.
25 KeLumpAllocator() : m_pUsableRegions(NULL), m_pUnusableRegions(NULL)
27 m_DefLumpSize = 65536;
29 #if defined KE_PLATFORM_WINDOWS
33 if (info.dwAllocationGranularity > m_DefLumpSize)
35 m_DefLumpSize = info.dwAllocationGranularity;
42 FreeRegionChain(m_pUsableRegions);
43 FreeRegionChain(m_pUnusableRegions);
50 /* Find the tail of the usable regions. */
51 region = m_pUsableRegions;
52 while (region != NULL)
54 if (region->next == NULL)
60 /* Link the unusable chain into the usable chain. */
63 m_pUsableRegions = m_pUnusableRegions;
67 region->next = m_pUnusableRegions;
68 m_pUnusableRegions->prev = region;
70 m_pUnusableRegions = NULL;
72 region = m_pUsableRegions;
73 while (region != NULL)
75 region->avail = region->size;
76 region->cur = region->base;
77 region = region->next;
81 void FreeRegionChain(KeLumpRegion *region)
85 while (region != NULL)
89 #if defined KE_PLATFORM_WINDOWS
90 VirtualFree(region, 0, MEM_RELEASE);
98 void *Alloc(size_t size)
101 KeLumpRegion *region;
109 region = FindRegionForSize(size);
112 region->avail -= size;
116 * Technically we could make one last small allocation, but
117 * this edge case is not worth the extra work.
119 if (region->avail < 8)
121 /* Unlink us from the usable list */
122 if (region == m_pUsableRegions)
124 m_pUsableRegions = m_pUsableRegions->next;
125 m_pUsableRegions->prev = NULL;
129 region->prev->next = region->next;
130 if (region->next != NULL)
132 region->next->prev = region->prev;
136 /* Link us into the unusable list */
138 region->next = m_pUnusableRegions;
140 if (m_pUnusableRegions != NULL)
142 m_pUnusableRegions->prev = region;
145 m_pUnusableRegions = region;
152 KeLumpRegion *FindRegionForSize(size_t size)
155 KeLumpRegion *region;
156 size_t size_of_region;
159 * :TODO: replace this with a priority queue or something
160 * that's actually fast. Even worse is we dirty pages by
163 region = m_pUsableRegions;
164 while (region != NULL)
166 if (region->avail >= size)
170 region = region->next;
173 /* Make sure regions end at 8-byte alignment. */
174 size_of_region = sizeof(KeLumpRegion);
175 if (size_of_region % 8 != 0)
178 size_of_region -= size_of_region % 8;
181 /* If the size is too big, fix that. */
182 if (size > m_DefLumpSize - size_of_region)
184 size += m_DefLumpSize;
185 size -= size % m_DefLumpSize;
189 size = m_DefLumpSize;
192 #if defined KE_PLATFORM_WINDOWS
193 base = (char *)VirtualAlloc(
196 MEM_COMMIT|MEM_RESERVE,
199 base = (char*)valloc(m_DefLumpSize);
202 /* Initialize the region */
203 region = (KeLumpRegion *)base;
204 region->base = &base[size_of_region];
205 region->size = size - size_of_region;
206 region->cur = region->base;
207 region->avail = region->size;
209 region->next = m_pUsableRegions;
211 if (m_pUsableRegions != NULL)
213 m_pUsableRegions->prev = region;
216 m_pUsableRegions = region;
222 KeLumpRegion *m_pUsableRegions;
223 KeLumpRegion *m_pUnusableRegions;
224 size_t m_DefLumpSize;
227 inline KeLumpAllocator *ke_LumpFromAllocator(ke_allocator_t *arena)
229 return (KeLumpAllocator *)arena->user;
232 void *ke_LumpAlloc(ke_allocator_t *arena, size_t size)
234 return ke_LumpFromAllocator(arena)->Alloc(size);
237 void ke_LumpFree(ke_allocator_t *arena, void *ptr)
241 ke_allocator_t * KE_LINK Knight::KE_CreateLumpAllocator()
243 ke_allocator_t *alloc;
245 alloc = new ke_allocator_t;
246 alloc->alloc = ke_LumpAlloc;
247 alloc->dealloc = ke_LumpFree;
248 alloc->user = new KeLumpAllocator();
253 void KE_LINK Knight::KE_DestroyLumpAllocator(ke_allocator_t *alloc)
255 delete ke_LumpFromAllocator(alloc);
259 void KE_LINK Knight::KE_ResetLumpAllocator(ke_allocator_t *alloc)
261 ke_LumpFromAllocator(alloc)->Reset();