1 /*
2 ===========================================================================
3 Copyright (C) 1999-2005 Id Software, Inc.
4
5 This file is part of Quake III Arena source code.
6
7 Quake III Arena source code is free software; you can redistribute it
8 and/or modify it under the terms of the GNU General Public License as
9 published by the Free Software Foundation; either version 2 of the License,
10 or (at your option) any later version.
11
12 Quake III Arena source code is distributed in the hope that it will be
13 useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with Quake III Arena source code; if not, write to the Free Software
19 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
20 ===========================================================================
21 */
22
23 /*****************************************************************************
24 * name: l_memory.c
25 *
26 * desc: memory allocation
27 *
28 * $Archive: /MissionPack/code/botlib/l_memory.c $
29 *
30 *****************************************************************************/
31
32 #include "../qcommon/q_shared.h"
33 #include "botlib.h"
34 #include "l_log.h"
35 #include "be_interface.h"
36
37 //#define MEMDEBUG
38 //#define MEMORYMANEGER
39
40 #define MEM_ID 0x12345678l
41 #define HUNK_ID 0x87654321l
42
43 int allocatedmemory;
44 int totalmemorysize;
45 int numblocks;
46
47 #ifdef MEMORYMANEGER
48
49 typedef struct memoryblock_s
50 {
51 unsigned long int id;
52 void *ptr;
53 int size;
54 #ifdef MEMDEBUG
55 char *label;
56 char *file;
57 int line;
58 #endif //MEMDEBUG
59 struct memoryblock_s *prev, *next;
60 } memoryblock_t;
61
62 memoryblock_t *memory;
63
64 //===========================================================================
65 //
66 // Parameter: -
67 // Returns: -
68 // Changes Globals: -
69 //===========================================================================
LinkMemoryBlock(memoryblock_t * block)70 void LinkMemoryBlock(memoryblock_t *block)
71 {
72 block->prev = NULL;
73 block->next = memory;
74 if (memory) memory->prev = block;
75 memory = block;
76 } //end of the function LinkMemoryBlock
77 //===========================================================================
78 //
79 // Parameter: -
80 // Returns: -
81 // Changes Globals: -
82 //===========================================================================
UnlinkMemoryBlock(memoryblock_t * block)83 void UnlinkMemoryBlock(memoryblock_t *block)
84 {
85 if (block->prev) block->prev->next = block->next;
86 else memory = block->next;
87 if (block->next) block->next->prev = block->prev;
88 } //end of the function UnlinkMemoryBlock
89 //===========================================================================
90 //
91 // Parameter: -
92 // Returns: -
93 // Changes Globals: -
94 //===========================================================================
95 #ifdef MEMDEBUG
GetMemoryDebug(unsigned long size,char * label,char * file,int line)96 void *GetMemoryDebug(unsigned long size, char *label, char *file, int line)
97 #else
98 void *GetMemory(unsigned long size)
99 #endif //MEMDEBUG
100 {
101 void *ptr;
102 memoryblock_t *block;
103 assert(botimport.GetMemory);
104 ptr = botimport.GetMemory(size + sizeof(memoryblock_t));
105 block = (memoryblock_t *) ptr;
106 block->id = MEM_ID;
107 block->ptr = (char *) ptr + sizeof(memoryblock_t);
108 block->size = size + sizeof(memoryblock_t);
109 #ifdef MEMDEBUG
110 block->label = label;
111 block->file = file;
112 block->line = line;
113 #endif //MEMDEBUG
114 LinkMemoryBlock(block);
115 allocatedmemory += block->size;
116 totalmemorysize += block->size + sizeof(memoryblock_t);
117 numblocks++;
118 return block->ptr;
119 } //end of the function GetMemoryDebug
120 //===========================================================================
121 //
122 // Parameter: -
123 // Returns: -
124 // Changes Globals: -
125 //===========================================================================
126 #ifdef MEMDEBUG
GetClearedMemoryDebug(unsigned long size,char * label,char * file,int line)127 void *GetClearedMemoryDebug(unsigned long size, char *label, char *file, int line)
128 #else
129 void *GetClearedMemory(unsigned long size)
130 #endif //MEMDEBUG
131 {
132 void *ptr;
133 #ifdef MEMDEBUG
134 ptr = GetMemoryDebug(size, label, file, line);
135 #else
136 ptr = GetMemory(size);
137 #endif //MEMDEBUG
138 Com_Memset(ptr, 0, size);
139 return ptr;
140 } //end of the function GetClearedMemory
141 //===========================================================================
142 //
143 // Parameter: -
144 // Returns: -
145 // Changes Globals: -
146 //===========================================================================
147 #ifdef MEMDEBUG
GetHunkMemoryDebug(unsigned long size,char * label,char * file,int line)148 void *GetHunkMemoryDebug(unsigned long size, char *label, char *file, int line)
149 #else
150 void *GetHunkMemory(unsigned long size)
151 #endif //MEMDEBUG
152 {
153 void *ptr;
154 memoryblock_t *block;
155
156 ptr = botimport.HunkAlloc(size + sizeof(memoryblock_t));
157 block = (memoryblock_t *) ptr;
158 block->id = HUNK_ID;
159 block->ptr = (char *) ptr + sizeof(memoryblock_t);
160 block->size = size + sizeof(memoryblock_t);
161 #ifdef MEMDEBUG
162 block->label = label;
163 block->file = file;
164 block->line = line;
165 #endif //MEMDEBUG
166 LinkMemoryBlock(block);
167 allocatedmemory += block->size;
168 totalmemorysize += block->size + sizeof(memoryblock_t);
169 numblocks++;
170 return block->ptr;
171 } //end of the function GetHunkMemoryDebug
172 //===========================================================================
173 //
174 // Parameter: -
175 // Returns: -
176 // Changes Globals: -
177 //===========================================================================
178 #ifdef MEMDEBUG
GetClearedHunkMemoryDebug(unsigned long size,char * label,char * file,int line)179 void *GetClearedHunkMemoryDebug(unsigned long size, char *label, char *file, int line)
180 #else
181 void *GetClearedHunkMemory(unsigned long size)
182 #endif //MEMDEBUG
183 {
184 void *ptr;
185 #ifdef MEMDEBUG
186 ptr = GetHunkMemoryDebug(size, label, file, line);
187 #else
188 ptr = GetHunkMemory(size);
189 #endif //MEMDEBUG
190 Com_Memset(ptr, 0, size);
191 return ptr;
192 } //end of the function GetClearedHunkMemory
193 //===========================================================================
194 //
195 // Parameter: -
196 // Returns: -
197 // Changes Globals: -
198 //===========================================================================
BlockFromPointer(void * ptr,char * str)199 memoryblock_t *BlockFromPointer(void *ptr, char *str)
200 {
201 memoryblock_t *block;
202
203 if (!ptr)
204 {
205 #ifdef MEMDEBUG
206 //char *crash = (char *) NULL;
207 //crash[0] = 1;
208 botimport.Print(PRT_FATAL, "%s: NULL pointer\n", str);
209 #endif // MEMDEBUG
210 return NULL;
211 } //end if
212 block = (memoryblock_t *) ((char *) ptr - sizeof(memoryblock_t));
213 if (block->id != MEM_ID && block->id != HUNK_ID)
214 {
215 botimport.Print(PRT_FATAL, "%s: invalid memory block\n", str);
216 return NULL;
217 } //end if
218 if (block->ptr != ptr)
219 {
220 botimport.Print(PRT_FATAL, "%s: memory block pointer invalid\n", str);
221 return NULL;
222 } //end if
223 return block;
224 } //end of the function BlockFromPointer
225 //===========================================================================
226 //
227 // Parameter: -
228 // Returns: -
229 // Changes Globals: -
230 //===========================================================================
FreeMemory(void * ptr)231 void FreeMemory(void *ptr)
232 {
233 memoryblock_t *block;
234
235 block = BlockFromPointer(ptr, "FreeMemory");
236 if (!block) return;
237 UnlinkMemoryBlock(block);
238 allocatedmemory -= block->size;
239 totalmemorysize -= block->size + sizeof(memoryblock_t);
240 numblocks--;
241 //
242 if (block->id == MEM_ID)
243 {
244 botimport.FreeMemory(block);
245 } //end if
246 } //end of the function FreeMemory
247 //===========================================================================
248 //
249 // Parameter: -
250 // Returns: -
251 // Changes Globals: -
252 //===========================================================================
AvailableMemory(void)253 int AvailableMemory(void)
254 {
255 return botimport.AvailableMemory();
256 } //end of the function AvailableMemory
257 //===========================================================================
258 //
259 // Parameter: -
260 // Returns: -
261 // Changes Globals: -
262 //===========================================================================
MemoryByteSize(void * ptr)263 int MemoryByteSize(void *ptr)
264 {
265 memoryblock_t *block;
266
267 block = BlockFromPointer(ptr, "MemoryByteSize");
268 if (!block) return 0;
269 return block->size;
270 } //end of the function MemoryByteSize
271 //===========================================================================
272 //
273 // Parameter: -
274 // Returns: -
275 // Changes Globals: -
276 //===========================================================================
PrintUsedMemorySize(void)277 void PrintUsedMemorySize(void)
278 {
279 botimport.Print(PRT_MESSAGE, "total allocated memory: %d KB\n", allocatedmemory >> 10);
280 botimport.Print(PRT_MESSAGE, "total botlib memory: %d KB\n", totalmemorysize >> 10);
281 botimport.Print(PRT_MESSAGE, "total memory blocks: %d\n", numblocks);
282 } //end of the function PrintUsedMemorySize
283 //===========================================================================
284 //
285 // Parameter: -
286 // Returns: -
287 // Changes Globals: -
288 //===========================================================================
PrintMemoryLabels(void)289 void PrintMemoryLabels(void)
290 {
291 memoryblock_t *block;
292 int i;
293
294 PrintUsedMemorySize();
295 i = 0;
296 Log_Write("============= Botlib memory log ==============\r\n");
297 Log_Write("\r\n");
298 for (block = memory; block; block = block->next)
299 {
300 #ifdef MEMDEBUG
301 if (block->id == HUNK_ID)
302 {
303 Log_Write("%6d, hunk %p, %8d: %24s line %6d: %s\r\n", i, block->ptr, block->size, block->file, block->line, block->label);
304 } //end if
305 else
306 {
307 Log_Write("%6d, %p, %8d: %24s line %6d: %s\r\n", i, block->ptr, block->size, block->file, block->line, block->label);
308 } //end else
309 #endif //MEMDEBUG
310 i++;
311 } //end for
312 } //end of the function PrintMemoryLabels
313 //===========================================================================
314 //
315 // Parameter: -
316 // Returns: -
317 // Changes Globals: -
318 //===========================================================================
DumpMemory(void)319 void DumpMemory(void)
320 {
321 memoryblock_t *block;
322
323 for (block = memory; block; block = memory)
324 {
325 FreeMemory(block->ptr);
326 } //end for
327 totalmemorysize = 0;
328 allocatedmemory = 0;
329 } //end of the function DumpMemory
330
331 #else
332
333 //===========================================================================
334 //
335 // Parameter: -
336 // Returns: -
337 // Changes Globals: -
338 //===========================================================================
339 #ifdef MEMDEBUG
GetMemoryDebug(unsigned long size,char * label,char * file,int line)340 void *GetMemoryDebug(unsigned long size, char *label, char *file, int line)
341 #else
342 void *GetMemory(unsigned long size)
343 #endif //MEMDEBUG
344 {
345 void *ptr;
346 unsigned long int *memid;
347
348 ptr = botimport.GetMemory(size + sizeof(unsigned long int));
349 if (!ptr) return NULL;
350 memid = (unsigned long int *) ptr;
351 *memid = MEM_ID;
352 return (unsigned long int *) ((char *) ptr + sizeof(unsigned long int));
353 } //end of the function GetMemory
354 //===========================================================================
355 //
356 // Parameter: -
357 // Returns: -
358 // Changes Globals: -
359 //===========================================================================
360 #ifdef MEMDEBUG
GetClearedMemoryDebug(unsigned long size,char * label,char * file,int line)361 void *GetClearedMemoryDebug(unsigned long size, char *label, char *file, int line)
362 #else
363 void *GetClearedMemory(unsigned long size)
364 #endif //MEMDEBUG
365 {
366 void *ptr;
367 #ifdef MEMDEBUG
368 ptr = GetMemoryDebug(size, label, file, line);
369 #else
370 ptr = GetMemory(size);
371 #endif //MEMDEBUG
372 Com_Memset(ptr, 0, size);
373 return ptr;
374 } //end of the function GetClearedMemory
375 //===========================================================================
376 //
377 // Parameter: -
378 // Returns: -
379 // Changes Globals: -
380 //===========================================================================
381 #ifdef MEMDEBUG
GetHunkMemoryDebug(unsigned long size,char * label,char * file,int line)382 void *GetHunkMemoryDebug(unsigned long size, char *label, char *file, int line)
383 #else
384 void *GetHunkMemory(unsigned long size)
385 #endif //MEMDEBUG
386 {
387 void *ptr;
388 unsigned long int *memid;
389
390 ptr = botimport.HunkAlloc(size + sizeof(unsigned long int));
391 if (!ptr) return NULL;
392 memid = (unsigned long int *) ptr;
393 *memid = HUNK_ID;
394 return (unsigned long int *) ((char *) ptr + sizeof(unsigned long int));
395 } //end of the function GetHunkMemory
396 //===========================================================================
397 //
398 // Parameter: -
399 // Returns: -
400 // Changes Globals: -
401 //===========================================================================
402 #ifdef MEMDEBUG
GetClearedHunkMemoryDebug(unsigned long size,char * label,char * file,int line)403 void *GetClearedHunkMemoryDebug(unsigned long size, char *label, char *file, int line)
404 #else
405 void *GetClearedHunkMemory(unsigned long size)
406 #endif //MEMDEBUG
407 {
408 void *ptr;
409 #ifdef MEMDEBUG
410 ptr = GetHunkMemoryDebug(size, label, file, line);
411 #else
412 ptr = GetHunkMemory(size);
413 #endif //MEMDEBUG
414 Com_Memset(ptr, 0, size);
415 return ptr;
416 } //end of the function GetClearedHunkMemory
417 //===========================================================================
418 //
419 // Parameter: -
420 // Returns: -
421 // Changes Globals: -
422 //===========================================================================
FreeMemory(void * ptr)423 void FreeMemory(void *ptr)
424 {
425 unsigned long int *memid;
426
427 memid = (unsigned long int *) ((char *) ptr - sizeof(unsigned long int));
428
429 if (*memid == MEM_ID)
430 {
431 botimport.FreeMemory(memid);
432 } //end if
433 } //end of the function FreeMemory
434 //===========================================================================
435 //
436 // Parameter: -
437 // Returns: -
438 // Changes Globals: -
439 //===========================================================================
AvailableMemory(void)440 int AvailableMemory(void)
441 {
442 return botimport.AvailableMemory();
443 } //end of the function AvailableMemory
444 //===========================================================================
445 //
446 // Parameter: -
447 // Returns: -
448 // Changes Globals: -
449 //===========================================================================
PrintUsedMemorySize(void)450 void PrintUsedMemorySize(void)
451 {
452 } //end of the function PrintUsedMemorySize
453 //===========================================================================
454 //
455 // Parameter: -
456 // Returns: -
457 // Changes Globals: -
458 //===========================================================================
PrintMemoryLabels(void)459 void PrintMemoryLabels(void)
460 {
461 } //end of the function PrintMemoryLabels
462
463 #endif
464