00001
00020 #include "mfcpch.h"
00021 #include <stdlib.h>
00022 #ifdef __UNIX__
00023 #include <assert.h>
00024 #endif
00025 #include "stderr.h"
00026 #include "tprintf.h"
00027 #include "memblk.h"
00028 #include "memry.h"
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00060 DLLSYM void check_mem(
00061 const char *string,
00062 INT8 level
00063 ) {
00064 big_mem.check (string, level);
00065 main_mem.check (string, level);
00066 check_structs(level);
00067 }
00068
00069
00083 DLLSYM char *alloc_string(
00084 INT32 count
00085 ) {
00086 #ifdef RAYS_MALLOC
00087 char *string;
00088
00089 if (count < 1 || count > MAX_CHUNK) {
00090 tprintf ("Invalid size %d requested of alloc_string", count);
00091 return NULL;
00092 }
00093
00094 count++;
00095 if (count <= MAX_STRUCTS * sizeof (MEMUNION)) {
00096 string = (char *) alloc_struct (count, "alloc_string");
00097
00098 if (string == NULL) {
00099 tprintf ("No memory for alloc_string");
00100 return NULL;
00101 }
00102 string[0] = (INT8) count;
00103 }
00104 else {
00105
00106 string = (char *) alloc_mem (count);
00107 if (string == NULL) {
00108 tprintf ("No memory for alloc_string");
00109 return NULL;
00110 }
00111 string[0] = 0;
00112 }
00113 return &string[1];
00114 #else
00115 return static_cast<char*>(malloc(count));
00116 #endif
00117 }
00118
00119
00123 DLLSYM void free_string(
00124 char *string
00125 ) {
00126 #ifdef RAYS_MALLOC
00127 if (((ptrdiff_t) string & 3) == 1) {
00128 string--;
00129 if (*string == 0) {
00130 free_mem(string);
00131 return;
00132 }
00133 else if (*string <= MAX_STRUCTS * sizeof (MEMUNION)) {
00134
00135 free_struct (string, *string, "alloc_string");
00136 return;
00137 }
00138 }
00139 tprintf ("Non-string given to free_string");
00140 #else
00141 free(string);
00142 #endif
00143 }
00144
00145
00157 DLLSYM void *
00158 alloc_struct (
00159 INT32 count,
00160 #if defined COUNTING_CLASS_STRUCTURES
00161 const char *name
00162 #else
00163 const char *
00164 #endif
00165 ) {
00166 #ifdef RAYS_MALLOC
00167 MEMUNION *element;
00168 MEMUNION *returnelement;
00169 INT32 struct_count;
00170 INT32 blocksize;
00171 INT32 index;
00172
00173 if (count < 1 || count > MAX_CHUNK) {
00174 tprintf ("Invalid size %d requested of alloc_struct", count);
00175 return NULL;
00176 }
00177
00178
00179
00180 struct_count = (count - 1) / sizeof (MEMUNION);
00181 if (struct_count < MAX_STRUCTS) {
00182
00183 #ifdef COUNTING_CLASS_STRUCTURES
00184 if (name != NULL) {
00185 index = identify_struct_owner (struct_count, name);
00186 if (index < MAX_CLASSES)
00187 owner_counts[struct_count][index]++;
00188 }
00189 #endif
00190
00191 returnelement = free_structs[struct_count];
00192 if (returnelement == NULL) {
00193
00194
00195 element = (MEMUNION *) new_struct_block ();
00196 if (element == NULL) {
00197 tprintf ("No memory to satisfy request for %d", (int) count);
00198 return NULL;
00199 }
00200
00201 element->ptr = struct_blocks[struct_count];
00202 struct_blocks[struct_count] = element;
00203 blocks_in_use[struct_count]++;
00204 element++;
00205 returnelement = element;
00206 blocksize = STRUCT_BLOCK_SIZE / (struct_count + 1) - 1;
00207
00208 for (index = 1; index < blocksize; index++) {
00209
00210 element->ptr = element + struct_count + 1;
00211 element += struct_count + 1;
00212 }
00213 element->ptr = NULL;
00214 }
00215
00216 free_structs[struct_count] = returnelement->ptr;
00217
00218 structs_in_use[struct_count]++;
00219 }
00220 else {
00221
00222 returnelement = (MEMUNION *) alloc_mem (count);
00223 if (returnelement == NULL) {
00224 tprintf ("No memory to satisfy request for %d", (int) count);
00225 return NULL;
00226 }
00227 }
00228 return returnelement;
00229 #else
00230 return malloc(count);
00231 #endif
00232 }
00233
00234
00238 DLLSYM void
00239 free_struct (
00240 void *deadstruct,
00241 INT32 count,
00242 #if defined COUNTING_CLASS_STRUCTURES
00243 const char *name
00244 #else
00245 const char *
00246 #endif
00247 ) {
00248 #ifdef RAYS_MALLOC
00249 MEMUNION *end_element;
00250 MEMUNION *element;
00251 MEMUNION *prev_element;
00252 MEMUNION *prev_block;
00253 MEMUNION *nextblock;
00254 MEMUNION *block;
00255 INT32 struct_count;
00256 INT32 index;
00257
00258 if (count < 1 || count > MAX_CHUNK) {
00259 tprintf ("Invalid size %d requested of free_struct", count);
00260 return;
00261 }
00262
00263
00264
00265 struct_count = (count - 1) / sizeof (MEMUNION);
00266
00267 if (deadstruct == NULL) {
00268
00269 check_struct(MEMCHECKS, count);
00270 }
00271 else {
00272 if (struct_count < MAX_STRUCTS) {
00273
00274 #ifdef COUNTING_CLASS_STRUCTURES
00275 if (name != NULL) {
00276 index = identify_struct_owner (struct_count, name);
00277 if (index < MAX_CLASSES) {
00278 owner_counts[struct_count][index]--;
00279 ASSERT_HOST (owner_counts[struct_count][index] >= 0);
00280 }
00281 }
00282 #endif
00283 element = (MEMUNION *) deadstruct;
00284
00285 element->ptr = free_structs[struct_count];
00286 free_structs[struct_count] = element;
00287
00288 structs_in_use[struct_count]--;
00289 if (structs_in_use[struct_count] == 0) {
00290 index = 0;
00291 for (element = struct_blocks[struct_count];
00292 element != NULL; element = nextblock) {
00293
00294 nextblock = element->ptr;
00295
00296 old_struct_block(element);
00297 index++;
00298 }
00299
00300 struct_blocks[struct_count] = NULL;
00301
00302 free_structs[struct_count] = NULL;
00303 blocks_in_use[struct_count] = 0;
00304 }
00305 else if (structs_in_use[struct_count] < 0) {
00306 tprintf ("Negative number of structs of size %d in use",
00307 (int) count);
00308 }
00309 else if (structs_in_use[struct_count] < blocks_in_use[struct_count]) {
00310 prev_block = NULL;
00311 for (block = struct_blocks[struct_count];
00312 block != NULL; block = nextblock) {
00313 nextblock = block;
00314 index = STRUCT_BLOCK_SIZE / (struct_count + 1) - 1;
00315 end_element = block + STRUCT_BLOCK_SIZE;
00316 for (element = free_structs[struct_count];
00317 element != NULL; element = element->ptr) {
00318 if (element > nextblock && element < end_element) {
00319 index--;
00320 if (index == 0)
00321 break;
00322 }
00323 }
00324 if (index == 0) {
00325 index = STRUCT_BLOCK_SIZE / (struct_count + 1) - 1;
00326 for (element =
00327 free_structs[struct_count], prev_element = NULL;
00328 element != NULL; element = element->ptr) {
00329 if (element > nextblock && element < end_element) {
00330 index--;
00331 if (prev_element != NULL)
00332 prev_element->ptr = element->ptr;
00333 else
00334 free_structs[struct_count] = element->ptr;
00335 if (index == 0)
00336 break;
00337 }
00338 else
00339 prev_element = element;
00340 }
00341 if (prev_block != NULL)
00342 prev_block->ptr = block->ptr;
00343 else
00344 struct_blocks[struct_count] = block->ptr;
00345 nextblock = block->ptr;
00346 blocks_in_use[struct_count]--;
00347
00348 old_struct_block(block);
00349 }
00350 else {
00351 prev_block = block;
00352
00353 nextblock = block->ptr;
00354 }
00355 }
00356 }
00357 }
00358 else
00359 free_mem(deadstruct);
00360 }
00361 #else
00362 free(deadstruct);
00363 #endif // RAYS_MALLOC
00364 }
00365
00366
00367
00368
00369
00370
00378 DLLSYM void *alloc_mem_p(
00379 INT32 count
00380 ) {
00381 #ifdef RAYS_MALLOC
00382 #ifdef TESTING_BIGSTUFF
00383 if (main_mem.biggestblock == 0)
00384 main_mem.init (alloc_big_mem, free_big_mem,
00385 FIRSTSIZE, LASTSIZE, MAX_CHUNK);
00386 #else
00387 if (main_mem.biggestblock == 0)
00388 main_mem.init ((void *(*)(INT32)) malloc, free,
00389 FIRSTSIZE, LASTSIZE, MAX_CHUNK);
00390 #endif
00391 if (mem_mallocdepth > 0)
00392 return main_mem.alloc_p (count, trace_caller (mem_mallocdepth));
00393 else
00394 return main_mem.alloc_p (count, NULL);
00395 #else
00396 return malloc ((size_t) count);
00397 #endif
00398 }
00399
00400
00404 DLLSYM void *alloc_mem(
00405 INT32 count
00406 ) {
00407 #ifdef RAYS_MALLOC
00408 #ifdef TESTING_BIGSTUFF
00409 if (main_mem.biggestblock == 0)
00410 main_mem.init (alloc_big_mem, free_big_mem,
00411 FIRSTSIZE, LASTSIZE, MAX_CHUNK);
00412 #else
00413 if (main_mem.biggestblock == 0)
00414 main_mem.init ((void *(*)(INT32)) malloc, free,
00415 FIRSTSIZE, LASTSIZE, MAX_CHUNK);
00416 #endif
00417 if (mem_mallocdepth > 0)
00418 return main_mem.alloc (count, trace_caller (mem_mallocdepth));
00419 else
00420 return main_mem.alloc (count, NULL);
00421 #else
00422 return malloc ((size_t) count);
00423 #endif
00424 }
00425
00426
00430 DLLSYM void *alloc_big_mem(
00431 INT32 count
00432 ) {
00433 #ifdef TESTING_BIGSTUFF
00434 if (big_mem.biggestblock == 0)
00435 big_mem.init ((void *(*)(INT32)) malloc, free,
00436 BIGSIZE, BIGSIZE, MAX_BIGCHUNK);
00437 if (mem_mallocdepth > 0)
00438 return big_mem.alloc (count, trace_caller (mem_mallocdepth));
00439 else
00440 return big_mem.alloc (count, NULL);
00441 #else
00442 return malloc ((size_t) count);
00443 #endif
00444 }
00445
00446
00450 DLLSYM void *alloc_big_zeros(
00451 INT32 count
00452 ) {
00453 #ifdef TESTING_BIGSTUFF
00454 if (big_mem.biggestblock == 0)
00455 big_mem.init ((void *(*)(INT32)) malloc, free,
00456 BIGSIZE, BIGSIZE, MAX_BIGCHUNK);
00457 void *buf;
00458
00459 if (mem_mallocdepth > 0)
00460 buf = big_mem.alloc (count, trace_caller (mem_mallocdepth));
00461 else
00462 buf = big_mem.alloc (count, NULL);
00463 memset (buf, 0, count);
00464 return buf;
00465 #else
00466 return calloc ((size_t) count, 1);
00467 #endif
00468 }
00469
00470
00477 DLLSYM void free_mem(
00478 void *oldchunk
00479 ) {
00480 #ifdef RAYS_MALLOC
00481 if (mem_freedepth > 0 && main_mem.callers != NULL)
00482 main_mem.dealloc (oldchunk, trace_caller (mem_freedepth));
00483 else
00484 main_mem.dealloc (oldchunk, NULL);
00485 #else
00486 free(oldchunk);
00487 #endif
00488 }
00489
00490
00497 DLLSYM void free_big_mem(
00498 void *oldchunk
00499 ) {
00500 #ifdef TESTING_BIGSTUFF
00501 if (mem_freedepth > 0 && main_mem.callers != NULL)
00502 big_mem.dealloc (oldchunk, trace_caller (mem_freedepth));
00503 else
00504 big_mem.dealloc (oldchunk, NULL);
00505 #else
00506 free(oldchunk);
00507 #endif
00508 }