]> 4ch.mooo.com Git - 16.git/blob - 16/v2/source/ENGINE/A_MEMORY.C
9ce7f4c8022e5a89d460d2b945ca1e78b88bea0e
[16.git] / 16 / v2 / source / ENGINE / A_MEMORY.C
1 /*\r
2 Copyright (C) 1998 BJ Eirich (aka vecna)\r
3 This program is free software; you can redistribute it and/or\r
4 modify it under the terms of the GNU General Public License\r
5 as published by the Free Software Foundation; either version 2\r
6 of the License, or (at your option) any later version.\r
7 This program is distributed in the hope that it will be useful,\r
8 but WITHOUT ANY WARRANTY; without even the implied warranty of\r
9 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\r
10 See the GNU General Public Lic\r
11 See the GNU General Public License for more details.\r
12 You should have received a copy of the GNU General Public License\r
13 along with this program; if not, write to the Free Software\r
14 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.\r
15 */\r
16 \r
17 #include <stdio.h>\r
18 #include <string.h>\r
19 \r
20 #include "verge.h"\r
21 \r
22 // *****\r
23 // TODO: Move the chunk list from an array to a linked list?\r
24 //       Would eliminate hardcoded chunk limit, but would make\r
25 //       general operation slower. Probably not The Right Thing,\r
26 //       sides the chunk limit can be interesting sometimes. If\r
27 //       it becomes problematic, consider a Binary Tree.\r
28 // *****\r
29 \r
30 // ***************************** Data *****************************\r
31 \r
32 #define MAXCHUNKS 1000\r
33 #define PARANOID\r
34 #define PADFILLVALUE 254\r
35 #define PADSIZE 256\r
36 \r
37 typedef struct\r
38 {\r
39    void *pointer;\r
40    int  size;\r
41    int  owner;\r
42    char desc[40];\r
43 } memblockType;\r
44 \r
45 memblockType chunks[MAXCHUNKS+1];\r
46 int numchunks=0;\r
47 \r
48 // ***************************** Code *****************************\r
49 \r
50 void *valloc(int amount, char *desc, int owner)\r
51 {\r
52    if (numchunks == MAXCHUNKS)\r
53      err("Failed allocated %d bytes (%s), reason: Out of chunks.",\r
54         amount, desc);\r
55 \r
56 #ifdef PARANOID\r
57    CheckCorruption();\r
58    chunks[numchunks].pointer = (void *) ((int) malloc(amount + (PADSIZE * 2)) + PADSIZE);\r
59    chunks[numchunks].size = amount;\r
60    memset((char *) chunks[numchunks].pointer - PADSIZE, PADFILLVALUE, PADSIZE);\r
61    memset((char *) chunks[numchunks].pointer +\r
62                chunks[numchunks].size, PADFILLVALUE, PADSIZE);\r
63 #else\r
64    chunks[numchunks].pointer = malloc(amount);\r
65    chunks[numchunks].size = amount;\r
66 #endif\r
67    chunks[numchunks].owner = owner;\r
68    strncpy(chunks[numchunks].desc, desc, 39);\r
69    return chunks[numchunks++].pointer;\r
70 }\r
71 \r
72 void *qvalloc(int amount)\r
73 {\r
74    void *ptr;\r
75 \r
76    // Quick and dirty memory allocation. Should be used ONLY\r
77    // for temporary blocks in speed-critical loops.\r
78 \r
79    ptr = malloc(amount);\r
80    if (!ptr) err("qvalloc: Failed allocating %d bytes.", amount);\r
81    return ptr;\r
82 }\r
83 \r
84 void qvfree(void *ptr)\r
85 {\r
86    free(ptr);\r
87 }\r
88 \r
89 int TotalBytesAllocated(void)\r
90 {\r
91    int i, tally=0;\r
92 \r
93    for (i=0; i<numchunks; i++)\r
94       tally += chunks[i].size;\r
95 \r
96    return tally;\r
97 }\r
98 \r
99 int FindChunk(void *pointer)\r
100 {\r
101    int i;\r
102 \r
103    for (i=0; i<numchunks; i++)\r
104       if (chunks[i].pointer == pointer) return i;\r
105    return -1;\r
106 }\r
107 \r
108 void FreeChunk(int i)\r
109 {\r
110 #ifdef PARANOID\r
111    CheckCorruption();\r
112    free((void *) ((int) chunks[i].pointer - PADSIZE));\r
113 #else\r
114    free(chunks[i].pointer);\r
115 #endif\r
116    for (; i<numchunks; i++)\r
117       chunks[i]=chunks[i+1];\r
118    numchunks--;\r
119 }\r
120 \r
121 int v_free(void *ptr)\r
122 {\r
123    int i=FindChunk(ptr);\r
124    if (i == -1)\r
125    {\r
126       Log("vfree: Attempted to free ptr %u that was not allocated. [dumping mem report]", ptr);\r
127       MemReport();\r
128       return -1;\r
129    }\r
130    FreeChunk(i);\r
131 \r
132    return 0;\r
133 }\r
134 \r
135 void FreeByOwner(int owner)\r
136 {\r
137    int i;\r
138 \r
139    for (i=0; i<numchunks; i++)\r
140       if (chunks[i].owner == owner)\r
141          FreeChunk(i--);\r
142 }\r
143 \r
144 void MemReport(void)\r
145 {\r
146    int i;\r
147 \r
148    Log("");\r
149    Log("========================================");\r
150    Log("= Memory usage report for this session =");\r
151    Log("========================================");\r
152    Log("Chunks currently allocated: %d (MAXCHUNKS %d)", numchunks, MAXCHUNKS);\r
153    Log("%d total bytes allocated. ", TotalBytesAllocated());\r
154 #ifdef PARANOID\r
155    Log("PARANOID is ON. (pad size: %d pad value: %d)", PADSIZE, PADFILLVALUE);\r
156 #else\r
157    Log("PARANOID is OFF.");\r
158 #endif\r
159    Log("");\r
160    Log("Per-chunk analysis: ");\r
161 \r
162    for (i=0; i<numchunks; i++)\r
163    {\r
164        Log("[%3d] Ptr at: %8u size: %8d owner: %3d desc: %s",\r
165           i, chunks[i].pointer, chunks[i].size, chunks[i].owner, chunks[i].desc);\r
166    }\r
167 }\r
168 \r
169 #ifdef PARANOID\r
170 int ChunkIntegrity(int i)\r
171 {\r
172    char *tptr;\r
173 \r
174    tptr=(char *) malloc(PADSIZE);\r
175    memset(tptr, PADFILLVALUE, PADSIZE);\r
176    if (memcmp((char *) chunks[i].pointer - PADSIZE, tptr, PADSIZE))\r
177       return -1;      // Prefix corruption\r
178    if (memcmp((char *) chunks[i].pointer + chunks[i].size, tptr, PADSIZE))\r
179       return 1;       // Suffix corruption\r
180    free(tptr);\r
181    return 0;          // no corruption\r
182 }\r
183 \r
184 void CheckCorruption(void)\r
185 {\r
186    int i, j;\r
187 \r
188    for (i=0; i<numchunks; i++)\r
189    {\r
190       j=ChunkIntegrity(i);\r
191       if (!j) continue;\r
192       if (j == -1) { MemReport(); err("Prefix corruption on chunk %d.", i); }\r
193       if (j ==  1) { MemReport(); err("Suffix corruption on chunk %d.", i); }\r
194    }\r
195 }\r
196 #else\r
197 void CheckCorruption(void)\r
198 {\r
199    return;\r
200 }\r
201 #endif\r