]> 4ch.mooo.com Git - 16.git/blob - 16/v2/source/MAPED/A_MEMORY.C
c8f1598b65cd7e51b27a60051dc887061f82b69e
[16.git] / 16 / v2 / source / MAPED / 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 <stdlib.h>\r
19 #include <string.h>\r
20 \r
21 void err(char *str, ...);\r
22 void Log(char *str, ...);\r
23 \r
24 // *****\r
25 // TODO: Move the chunk list from an array to a linked list?\r
26 //       Would eliminate hardcoded chunk limit, but would make\r
27 //       general operation slower. Probably not The Right Thing,\r
28 //       sides the chunk limit can be interesting sometimes. If\r
29 //       it becomes problematic, consider a Binary Tree.\r
30 // *****\r
31 \r
32 // ***************************** Data *****************************\r
33 \r
34 #define MAXCHUNKS 200\r
35 #define PARANOID 1\r
36 #define PADFILLVALUE 254\r
37 #define PADSIZE 256\r
38 \r
39 void MemReport(void);\r
40 \r
41 #define errm MemReport(), err\r
42 \r
43 typedef struct\r
44 {\r
45    void *pointer;\r
46    int  size;\r
47    int  owner;\r
48    char desc[20];\r
49 } memblockType;\r
50 \r
51 memblockType chunks[MAXCHUNKS+1];\r
52 int numchunks=0;\r
53 \r
54 // ***************************** Code *****************************\r
55 \r
56 void *valloc(int amount, char *desc, int owner)\r
57 {\r
58    if (numchunks == MAXCHUNKS)\r
59      err("Failed allocated %d bytes (%s), reason: Out of chunks.",\r
60         amount, desc);\r
61 \r
62 #ifdef PARANOID\r
63    CheckCorruption();\r
64    chunks[numchunks].pointer = (void *) ((int) malloc(amount + (PADSIZE * 2)) + PADSIZE);\r
65    chunks[numchunks].size = amount;\r
66    memset((char *) chunks[numchunks].pointer - PADSIZE, PADFILLVALUE, PADSIZE);\r
67    memset((char *) chunks[numchunks].pointer +\r
68                chunks[numchunks].size, PADFILLVALUE, PADSIZE);\r
69 #else\r
70    chunks[numchunks].pointer = malloc(amount);\r
71    chunks[numchunks].size = amount;\r
72 #endif\r
73    chunks[numchunks].owner = owner;\r
74    strncpy(chunks[numchunks].desc, desc, 19);\r
75    memset(chunks[numchunks].pointer, 0, chunks[numchunks].size);\r
76    return chunks[numchunks++].pointer;\r
77 }\r
78 \r
79 void *qvalloc(int amount)\r
80 {\r
81    void *ptr;\r
82 \r
83    // Quick and dirty memory allocation. Should be used ONLY\r
84    // for temporary blocks in speed-critical loops.\r
85 \r
86    ptr = malloc(amount);\r
87    if (!ptr) errm("qvalloc: Failed allocating %d bytes.", amount);\r
88    return ptr;\r
89 }\r
90 \r
91 void qvfree(void *ptr)\r
92 {\r
93    free(ptr);\r
94 }\r
95 \r
96 int TotalBytesAllocated(void)\r
97 {\r
98    int i, tally=0;\r
99 \r
100    for (i=0; i<numchunks; i++)\r
101       tally += chunks[i].size;\r
102 \r
103    return tally;\r
104 }\r
105 \r
106 int FindChunk(void *pointer)\r
107 {\r
108    int i;\r
109 \r
110    for (i=0; i<numchunks; i++)\r
111       if (chunks[i].pointer == pointer) return i;\r
112    return -1;\r
113 }\r
114 \r
115 void FreeChunk(int i)\r
116 {\r
117 #ifdef PARANOID\r
118    CheckCorruption();\r
119    free((void *) ((int) chunks[i].pointer - PADSIZE));\r
120 #else\r
121    free(chunks[i].pointer);\r
122 #endif\r
123    for (; i<numchunks; i++)\r
124       chunks[i]=chunks[i+1];\r
125    numchunks--;\r
126 }\r
127 \r
128 int vfree(void *pointer)\r
129 {\r
130    int i;\r
131 \r
132    i=FindChunk(pointer);\r
133    if (i == -1)\r
134    {\r
135       Log("vfree: Attempted to free ptr %u that was not allocated. [dumping mem report]", pointer);\r
136       MemReport();\r
137       return -1;\r
138    }\r
139    FreeChunk(i);\r
140 \r
141    return 0;\r
142 }\r
143 \r
144 void FreeByOwner(int owner)\r
145 {\r
146    int i;\r
147 \r
148    for (i=0; i<numchunks; i++)\r
149       if (chunks[i].owner == owner)\r
150          FreeChunk(i--);\r
151 }\r
152 \r
153 void MemReport(void)\r
154 {\r
155    int i;\r
156 \r
157    Log("");\r
158    Log("========================================");\r
159    Log("= Memory usage report for this session =");\r
160    Log("========================================");\r
161    Log("Chunks currently allocated: %d (MAXCHUNKS %d)", numchunks, MAXCHUNKS);\r
162    Log("%d total bytes allocated. ", TotalBytesAllocated());\r
163 #ifdef PARANOID\r
164    Log("PARANOID is ON. (pad size: %d pad value: %d)", PADSIZE, PADFILLVALUE);\r
165 #else\r
166    Log("PARANOID is OFF.");\r
167 #endif\r
168    Log("");\r
169    Log("Per-chunk analysis: ");\r
170 \r
171    for (i=0; i<numchunks; i++)\r
172    {\r
173        Log("[%3d] Ptr at: %8u size: %8d owner: %3d desc: %s",\r
174           i, chunks[i].pointer, chunks[i].size, chunks[i].owner, chunks[i].desc);\r
175    }\r
176 \r
177 }\r
178 \r
179 #ifdef PARANOID\r
180 int ChunkIntegrity(int i)\r
181 {\r
182    char *tptr;\r
183 \r
184    tptr=(char *) malloc(PADSIZE);\r
185    memset(tptr, PADFILLVALUE, PADSIZE);\r
186    if (memcmp((char *) chunks[i].pointer - PADSIZE, tptr, PADSIZE))\r
187       return -1;      // Prefix corruption\r
188    if (memcmp((char *) chunks[i].pointer + chunks[i].size, tptr, PADSIZE))\r
189       return 1;       // Suffix corruption\r
190    free(tptr);\r
191    return 0;          // no corruption\r
192 }\r
193 \r
194 void CheckCorruption(void)\r
195 {\r
196    int i, j;\r
197 \r
198    for (i=0; i<numchunks; i++)\r
199    {\r
200       j=ChunkIntegrity(i);\r
201       if (!j) continue;\r
202       if (j == -1) errm("Prefix corruption on chunk %d.", i);\r
203       if (j ==  1) errm("Suffix corruption on chunk %d.", i);\r
204    }\r
205 }\r
206 #else\r
207 void CheckCorruption(void)\r
208 {\r
209    return;\r
210 }\r
211 #endif\r