00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030 #include "CSConfig.h"
00031
00032 #include <assert.h>
00033 #include <string.h>
00034 #include <stddef.h>
00035 #include <stdlib.h>
00036 #include <inttypes.h>
00037
00038 #include "CSException.h"
00039 #include "CSMemory.h"
00040 #include "CSThread.h"
00041 #include "CSStrUtil.h"
00042 #include "CSGlobal.h"
00043
00044 #ifdef DEBUG
00045 #undef cs_malloc
00046 #undef cs_calloc
00047 #undef cs_realloc
00048 #undef cs_free
00049 #undef new
00050 #endif
00051
00052 void *cs_malloc(size_t size)
00053 {
00054 void *ptr;
00055
00056 if (!(ptr = malloc(size)))
00057 CSException::throwOSError(CS_CONTEXT, ENOMEM);
00058 return ptr;
00059 }
00060
00061 void *cs_calloc(size_t size)
00062 {
00063 void *ptr;
00064
00065 if (!(ptr = malloc(size)))
00066 CSException::throwOSError(CS_CONTEXT, ENOMEM);
00067 memset(ptr, 0, size);
00068 return ptr;
00069 }
00070
00071 void cs_realloc(void **ptr, size_t size)
00072 {
00073 void *new_ptr;
00074
00075 if (!(new_ptr = realloc(*ptr, size)))
00076 CSException::throwOSError(CS_CONTEXT, ENOMEM);
00077 *ptr = new_ptr;
00078 }
00079
00080 void cs_free(void *ptr)
00081 {
00082 free(ptr);
00083 }
00084
00085
00086
00087
00088
00089
00090 #ifdef DEBUG
00091
00092 #define RECORD_MM
00093
00094 #define ADD_TOTAL_ALLOCS 4000
00095
00096 #define SHIFT_RIGHT(ptr, n) memmove(((char *) (ptr)) + sizeof(MissingMemoryRec), (ptr), (long) (n) * sizeof(MissingMemoryRec))
00097 #define SHIFT_LEFT(ptr, n) memmove((ptr), ((char *) (ptr)) + sizeof(MissingMemoryRec), (long) (n) * sizeof(MissingMemoryRec))
00098
00099 typedef struct MissingMemory {
00100 void *ptr;
00101 uint32_t id;
00102 const char *func_name;
00103 const char *file_name;
00104 uint32_t line_nr;
00105 } MissingMemoryRec, *MissingMemoryPtr;
00106
00107 static MissingMemoryRec *mm_addresses = NULL;
00108 static uint32_t mm_nr_in_use = 0L;
00109 static uint32_t mm_total_allocated = 0L;
00110 static uint32_t mm_alloc_count = 0;
00111 static pthread_mutex_t mm_mutex;
00112
00113
00114
00115
00116 static uint32_t mm_tracking_id = 0;
00117
00118 static void mm_println(const char *str)
00119 {
00120 printf("%s\n", str);
00121 }
00122
00123 static long mm_find_pointer(void *ptr)
00124 {
00125 register long i, n, guess;
00126
00127 i = 0;
00128 n = mm_nr_in_use;
00129 while (i < n) {
00130 guess = (i + n - 1) >> 1;
00131 if (ptr == mm_addresses[guess].ptr)
00132 return(guess);
00133 if (ptr < mm_addresses[guess].ptr)
00134 n = guess;
00135 else
00136 i = guess + 1;
00137 }
00138 return(-1);
00139 }
00140
00141 static long mm_add_pointer(void *ptr)
00142 {
00143 register int i, n, guess;
00144
00145 if (mm_nr_in_use == mm_total_allocated) {
00146
00147 MissingMemoryRec *new_addresses;
00148
00149 new_addresses = (MissingMemoryRec *) malloc(sizeof(MissingMemoryRec) * (mm_total_allocated + ADD_TOTAL_ALLOCS));
00150 if (!new_addresses)
00151 return(-1);
00152
00153 if (mm_addresses) {
00154 memcpy(new_addresses, mm_addresses, sizeof(MissingMemoryRec) * mm_total_allocated);
00155 free(mm_addresses);
00156 }
00157
00158 mm_addresses = new_addresses;
00159 mm_total_allocated += ADD_TOTAL_ALLOCS;
00160 }
00161
00162 i = 0;
00163 n = mm_nr_in_use;
00164 while (i < n) {
00165 guess = (i + n - 1) >> 1;
00166 if (ptr < mm_addresses[guess].ptr)
00167 n = guess;
00168 else
00169 i = guess + 1;
00170 }
00171
00172 SHIFT_RIGHT(&mm_addresses[i], mm_nr_in_use - i);
00173 mm_nr_in_use++;
00174 mm_addresses[i].ptr = ptr;
00175 return(i);
00176 }
00177
00178 static char *cs_mm_watch_point = 0;
00179
00180 static long mm_remove_pointer(void *ptr)
00181 {
00182 register int i, n, guess;
00183
00184 if (cs_mm_watch_point == ptr)
00185 printf("Hit watch point\n");
00186
00187 i = 0;
00188 n = mm_nr_in_use;
00189 while (i < n) {
00190 guess = (i + n - 1) >> 1;
00191 if (ptr == mm_addresses[guess].ptr)
00192 goto remove;
00193 if (ptr < mm_addresses[guess].ptr)
00194 n = guess;
00195 else
00196 i = guess + 1;
00197 }
00198 return(-1);
00199
00200 remove:
00201
00202 mm_nr_in_use--;
00203 SHIFT_LEFT(&mm_addresses[guess], mm_nr_in_use - guess);
00204 return(guess);
00205 }
00206
00207 static void mm_throw_assertion(MissingMemoryPtr mm_ptr, void *p, const char *message)
00208 {
00209 char str[200];
00210
00211 if (mm_ptr) {
00212 snprintf(str, 200, "MM ERROR: %8p (#%"PRId32") %s:%"PRId32" %s",
00213 mm_ptr->ptr,
00214 mm_ptr->id,
00215 cs_last_name_of_path(mm_ptr->file_name),
00216 mm_ptr->line_nr,
00217 message);
00218 }
00219 else
00220 snprintf(str, 200, "MM ERROR: %8p %s", p, message);
00221 mm_println(str);
00222 }
00223
00224 static uint32_t mm_add_core_ptr(void *ptr, const char *func, const char *file, int line)
00225 {
00226 long mm;
00227 uint32_t id;
00228
00229 mm = mm_add_pointer(ptr);
00230 if (mm < 0) {
00231 mm_println("MM ERROR: Cannot allocate table big enough!");
00232 return 0;
00233 }
00234
00235
00236 if (mm_alloc_count == mm_tracking_id) {
00237
00238 id = mm_alloc_count++;
00239 }
00240 else {
00241 id = mm_alloc_count++;
00242 }
00243 mm_addresses[mm].ptr = ptr;
00244 mm_addresses[mm].id = id;
00245 mm_addresses[mm].func_name = func;
00246 if (file)
00247 mm_addresses[mm].file_name = file;
00248 else
00249 mm_addresses[mm].file_name = "?";
00250 mm_addresses[mm].line_nr = line;
00251 return id;
00252 }
00253
00254 static void mm_remove_core_ptr(void *ptr)
00255 {
00256 long mm;
00257
00258 mm = mm_remove_pointer(ptr);
00259 if (mm < 0) {
00260 mm_println("MM ERROR: Pointer not allocated");
00261 return;
00262 }
00263 }
00264
00265 static long mm_find_core_ptr(void *ptr)
00266 {
00267 long mm;
00268
00269 mm = mm_find_pointer(ptr);
00270 if (mm < 0)
00271 mm_throw_assertion(NULL, ptr, "Pointer not allocated");
00272 return(mm);
00273 }
00274
00275 static void mm_replace_core_ptr(long i, void *ptr)
00276 {
00277 MissingMemoryRec tmp = mm_addresses[i];
00278 long mm;
00279
00280 mm_remove_pointer(mm_addresses[i].ptr);
00281 mm = mm_add_pointer(ptr);
00282 if (mm < 0) {
00283 mm_println("MM ERROR: Cannot allocate table big enough!");
00284 return;
00285 }
00286 mm_addresses[mm] = tmp;
00287 mm_addresses[mm].ptr = ptr;
00288 }
00289
00290
00291
00292
00293
00294
00295 #define MEM_DEBUG_HDR_SIZE offsetof(MemoryDebugRec, data)
00296 #define MEM_TRAILER_SIZE 2
00297 #define MEM_HEADER 0x01010101
00298 #define MEM_FREED 0x03030303
00299 #define MEM_TRAILER_BYTE 0x02
00300 #define MEM_FREED_BYTE 0x03
00301
00302 typedef struct MemoryDebug {
00303 uint32_t check;
00304 uint32_t md_id;
00305 uint32_t size;
00306 char data[200];
00307 } MemoryDebugRec, *MemoryDebugPtr;
00308
00309 static size_t mm_check_and_free(MissingMemoryPtr mm_ptr, void *p, bool freeme)
00310 {
00311 unsigned char *ptr = (unsigned char *) p - MEM_DEBUG_HDR_SIZE;
00312 MemoryDebugPtr debug_ptr = (MemoryDebugPtr) ptr;
00313 size_t size = debug_ptr->size;
00314 long a_value;
00315
00316 if (!ASSERT(p))
00317 return(0);
00318 if (!ASSERT(((size_t) p & 1L) == 0))
00319 return(0);
00320 a_value = MEM_FREED;
00321 if (debug_ptr->check == MEM_FREED) {
00322 mm_println("MM ERROR: Pointer already freed 'debug_ptr->check != MEM_FREED'");
00323 return(0);
00324 }
00325 a_value = MEM_HEADER;
00326 if (debug_ptr->check != MEM_HEADER) {
00327 mm_println("MM ERROR: Header not valid 'debug_ptr->check != MEM_HEADER'");
00328 return(0);
00329 }
00330 a_value = MEM_TRAILER_BYTE;
00331 if (!(*((unsigned char *) ptr + size + MEM_DEBUG_HDR_SIZE) == MEM_TRAILER_BYTE &&
00332 *((unsigned char *) ptr + size + MEM_DEBUG_HDR_SIZE + 1L) == MEM_TRAILER_BYTE)) {
00333 mm_throw_assertion(mm_ptr, p, "Trailer overwritten");
00334 return(0);
00335 }
00336
00337 if (freeme) {
00338 debug_ptr->check = MEM_FREED;
00339 *((unsigned char *) ptr + size + MEM_DEBUG_HDR_SIZE) = MEM_FREED_BYTE;
00340 *((unsigned char *) ptr + size + MEM_DEBUG_HDR_SIZE + 1L) = MEM_FREED_BYTE;
00341
00342 memset(((unsigned char *) ptr) + MEM_DEBUG_HDR_SIZE, 0xF5, size);
00343 cs_free(ptr);
00344 }
00345
00346 return size;
00347 }
00348
00349 bool cs_mm_scan_core(void)
00350 {
00351 uint32_t mm;
00352 bool rtc = true;
00353
00354 if (!mm_addresses)
00355 return true;
00356
00357 pthread_mutex_lock(&mm_mutex);
00358
00359 for (mm=0; mm<mm_nr_in_use; mm++) {
00360 if (!mm_check_and_free(&mm_addresses[mm], mm_addresses[mm].ptr, false))
00361 rtc = false;
00362 }
00363
00364 pthread_mutex_unlock(&mm_mutex);
00365 return rtc;
00366 }
00367
00368 void cs_mm_memmove(void *block, void *dest, void *source, size_t size)
00369 {
00370 if (block) {
00371 MemoryDebugPtr debug_ptr = (MemoryDebugPtr) ((char *) block - MEM_DEBUG_HDR_SIZE);
00372
00373 #ifdef RECORD_MM
00374 pthread_mutex_lock(&mm_mutex);
00375 mm_find_core_ptr(block);
00376 pthread_mutex_unlock(&mm_mutex);
00377 #endif
00378 mm_check_and_free(NULL, block, false);
00379
00380 if (dest < block || (char *) dest > (char *) block + debug_ptr->size) {
00381 mm_println("MM ERROR: Destination not in block");
00382 return;
00383 }
00384 if ((char *) dest + size > (char *) block + debug_ptr->size) {
00385 mm_println("MM ERROR: Copy will overwrite memory");
00386 return;
00387 }
00388 }
00389
00390 memmove(dest, source, size);
00391 }
00392
00393 void cs_mm_memcpy(void *block, void *dest, void *source, size_t size)
00394 {
00395 if (block) {
00396 MemoryDebugPtr debug_ptr = (MemoryDebugPtr) ((char *) block - MEM_DEBUG_HDR_SIZE);
00397
00398 #ifdef RECORD_MM
00399 pthread_mutex_lock(&mm_mutex);
00400 mm_find_core_ptr(block);
00401 pthread_mutex_unlock(&mm_mutex);
00402 #endif
00403 mm_check_and_free(NULL, block, false);
00404
00405 if (dest < block || (char *) dest > (char *) block + debug_ptr->size)
00406 mm_throw_assertion(NULL, block, "Destination not in block");
00407 if ((char *) dest + size > (char *) block + debug_ptr->size)
00408 mm_throw_assertion(NULL, block, "Copy will overwrite memory");
00409 }
00410
00411 memcpy(dest, source, size);
00412 }
00413
00414 void cs_mm_memset(void *block, void *dest, int value, size_t size)
00415 {
00416 if (block) {
00417 MemoryDebugPtr debug_ptr = (MemoryDebugPtr) ((char *) block - MEM_DEBUG_HDR_SIZE);
00418
00419 #ifdef RECORD_MM
00420 pthread_mutex_lock(&mm_mutex);
00421 mm_find_core_ptr(block);
00422 pthread_mutex_unlock(&mm_mutex);
00423 #endif
00424 mm_check_and_free(NULL, block, false);
00425
00426 if (dest < block || (char *) dest > (char *) block + debug_ptr->size)
00427 mm_throw_assertion(NULL, block, "Destination not in block");
00428 if ((char *) dest + size > (char *) block + debug_ptr->size)
00429 mm_throw_assertion(NULL, block, "Copy will overwrite memory");
00430 }
00431
00432 memset(dest, value, size);
00433 }
00434
00435 void *cs_mm_malloc(const char *func, const char *file, int line, size_t size)
00436 {
00437 unsigned char *p = (unsigned char *) cs_malloc(size + MEM_DEBUG_HDR_SIZE + MEM_TRAILER_SIZE);
00438
00439 if (!p)
00440 return NULL;
00441
00442 memset(p, 0x55, size + MEM_DEBUG_HDR_SIZE + MEM_TRAILER_SIZE);
00443
00444 ((MemoryDebugPtr) p)->check = MEM_HEADER;
00445 ((MemoryDebugPtr) p)->md_id = 0;
00446 ((MemoryDebugPtr) p)->size = (uint32_t) size;
00447 *(p + size + MEM_DEBUG_HDR_SIZE) = MEM_TRAILER_BYTE;
00448 *(p + size + MEM_DEBUG_HDR_SIZE + 1L) = MEM_TRAILER_BYTE;
00449
00450 #ifdef RECORD_MM
00451 pthread_mutex_lock(&mm_mutex);
00452 ((MemoryDebugPtr) p)->md_id = mm_add_core_ptr(p + MEM_DEBUG_HDR_SIZE, func, file, line);
00453 pthread_mutex_unlock(&mm_mutex);
00454 #endif
00455
00456 return p + MEM_DEBUG_HDR_SIZE;
00457 }
00458
00459 void *cs_mm_calloc(const char *func, const char *file, int line, size_t size)
00460 {
00461 unsigned char *p = (unsigned char *) cs_calloc(size + MEM_DEBUG_HDR_SIZE + MEM_TRAILER_SIZE);
00462
00463 if (!p)
00464 return NULL;
00465
00466 ((MemoryDebugPtr) p)->check = MEM_HEADER;
00467 ((MemoryDebugPtr) p)->md_id = 0;
00468 ((MemoryDebugPtr) p)->size = (uint32_t) size;
00469 *(p + size + MEM_DEBUG_HDR_SIZE) = MEM_TRAILER_BYTE;
00470 *(p + size + MEM_DEBUG_HDR_SIZE + 1L) = MEM_TRAILER_BYTE;
00471
00472 #ifdef RECORD_MM
00473 pthread_mutex_lock(&mm_mutex);
00474 ((MemoryDebugPtr) p)->md_id = mm_add_core_ptr(p + MEM_DEBUG_HDR_SIZE, func, file, line);
00475 pthread_mutex_unlock(&mm_mutex);
00476 #endif
00477
00478 return p + MEM_DEBUG_HDR_SIZE;
00479 }
00480
00481 void cs_mm_realloc(const char *func, const char *file, int line, void **ptr, size_t newsize)
00482 {
00483 unsigned char *oldptr = (unsigned char *) *ptr;
00484 size_t size;
00485 long mm;
00486 unsigned char *pnew;
00487
00488 if (!oldptr) {
00489 *ptr = cs_mm_malloc(func, file, line, newsize);
00490 return;
00491 }
00492
00493 #ifdef RECORD_MM
00494
00495
00496 pthread_mutex_lock(&mm_mutex);
00497 if ((mm = mm_find_core_ptr(oldptr)) < 0) {
00498 pthread_mutex_unlock(&mm_mutex);
00499 CSException::throwOSError(CS_CONTEXT, ENOMEM);
00500 }
00501
00502 #endif
00503
00504 oldptr = oldptr - MEM_DEBUG_HDR_SIZE;
00505 size = ((MemoryDebugPtr) oldptr)->size;
00506
00507 ASSERT(((MemoryDebugPtr) oldptr)->check == MEM_HEADER);
00508 ASSERT(*((unsigned char *) oldptr + size + MEM_DEBUG_HDR_SIZE) == MEM_TRAILER_BYTE &&
00509 *((unsigned char *) oldptr + size + MEM_DEBUG_HDR_SIZE + 1L) == MEM_TRAILER_BYTE);
00510
00511
00512 pnew = (unsigned char *) cs_malloc(newsize + MEM_DEBUG_HDR_SIZE + MEM_TRAILER_SIZE);
00513 if (!pnew) {
00514 #ifdef RECORD_MM
00515 pthread_mutex_unlock(&mm_mutex);
00516 #endif
00517 CSException::throwOSError(CS_CONTEXT, ENOMEM);
00518 return;
00519 }
00520
00521 if (newsize > size) {
00522 memcpy(((MemoryDebugPtr) pnew)->data, ((MemoryDebugPtr) oldptr)->data, size);
00523 memset(((MemoryDebugPtr) pnew)->data + size, 0x55, newsize - size);
00524 }
00525 else
00526 memcpy(((MemoryDebugPtr) pnew)->data, ((MemoryDebugPtr) oldptr)->data, newsize);
00527 memset(oldptr, 0x55, size + MEM_DEBUG_HDR_SIZE + MEM_TRAILER_SIZE);
00528
00529 #ifdef RECORD_MM
00530
00531 if ((mm = mm_find_core_ptr(oldptr + MEM_DEBUG_HDR_SIZE)) < 0) {
00532 pthread_mutex_unlock(&mm_mutex);
00533 CSException::throwOSError(CS_CONTEXT, ENOMEM);
00534 return;
00535 }
00536 mm_replace_core_ptr(mm, pnew + MEM_DEBUG_HDR_SIZE);
00537 pthread_mutex_unlock(&mm_mutex);
00538 #endif
00539
00540 cs_free(oldptr);
00541
00542 ((MemoryDebugPtr) pnew)->check = MEM_HEADER;
00543 ((MemoryDebugPtr) pnew)->size = (uint32_t) newsize;
00544 *(pnew + newsize + MEM_DEBUG_HDR_SIZE) = MEM_TRAILER_BYTE;
00545 *(pnew + newsize + MEM_DEBUG_HDR_SIZE + 1L) = MEM_TRAILER_BYTE;
00546
00547 *ptr = pnew + MEM_DEBUG_HDR_SIZE;
00548 }
00549
00550 void cs_mm_free(void *ptr)
00551 {
00552 bool my_pointer = false;
00553
00554 #ifdef RECORD_MM
00555 pthread_mutex_lock(&mm_mutex);
00556 if (mm_find_pointer(ptr) >= 0) {
00557 my_pointer = true;
00558 mm_remove_core_ptr(ptr);
00559 }
00560 pthread_mutex_unlock(&mm_mutex);
00561 #endif
00562 if (my_pointer)
00563 mm_check_and_free(NULL, ptr, true);
00564 else
00565 free(ptr);
00566 }
00567
00568 void cs_mm_pfree(void **ptr)
00569 {
00570 if (*ptr) {
00571 void *p = *ptr;
00572
00573 *ptr = NULL;
00574 cs_mm_free(p);
00575 }
00576 }
00577
00578 size_t cs_mm_malloc_size(void *ptr)
00579 {
00580 size_t size = 0;
00581
00582 #ifdef RECORD_MM
00583 pthread_mutex_lock(&mm_mutex);
00584 mm_find_core_ptr(ptr);
00585 pthread_mutex_unlock(&mm_mutex);
00586 #endif
00587 size = mm_check_and_free(NULL, ptr, false);
00588 return size;
00589 }
00590
00591 void cs_mm_print_track(const char *func, const char *file, uint32_t line, void *p, bool inc, uint32_t ref_cnt, int track_me)
00592 {
00593 unsigned char *ptr = (unsigned char *) p - MEM_DEBUG_HDR_SIZE;
00594 MemoryDebugPtr debug_ptr = (MemoryDebugPtr) ptr;
00595 CSThread *self = CSThread::getSelf();
00596 char buffer[300];
00597 int cnt = 0;
00598
00599 if (!track_me && !mm_tracking_id)
00600 return;
00601
00602 if (func) {
00603 cs_format_context(300, buffer, func, file, line);
00604 fprintf(stderr, "TRACKING (%"PRIu32"): %s %2"PRIu32" %s", debug_ptr->md_id, inc ? "INC" : "DEC", ref_cnt, buffer);
00605 }
00606 else
00607 fprintf(stderr, "TRACKING (%"PRIu32"): %s %2"PRIu32"", debug_ptr->md_id, inc ? "INC" : "DEC", ref_cnt);
00608
00609 for (int i = self->callTop-1; i>=0 && cnt < 4; i--) {
00610 cs_format_context(300, buffer, self->callStack[i].cs_func, self->callStack[i].cs_file, self->callStack[i].cs_line);
00611 fprintf(stderr," %s", buffer);
00612 cnt++;
00613 }
00614 fprintf(stderr,"\n");
00615 }
00616
00617 void cs_mm_track_memory(const char *func, const char *file, uint32_t line, void *p, bool inc, uint32_t ref_cnt, int track_me)
00618 {
00619 unsigned char *ptr = (unsigned char *) p - MEM_DEBUG_HDR_SIZE;
00620 MemoryDebugPtr debug_ptr = (MemoryDebugPtr) ptr;
00621
00622 if (track_me || (mm_tracking_id && debug_ptr->md_id == mm_tracking_id))
00623 cs_mm_print_track(func, file, line, p, inc, ref_cnt, track_me);
00624 }
00625
00626 #endif
00627
00628
00629
00630
00631
00632
00633 bool cs_init_memory(void)
00634 {
00635 #ifdef DEBUG
00636 pthread_mutex_init(&mm_mutex, NULL);
00637 mm_addresses = (MissingMemoryRec *) malloc(sizeof(MissingMemoryRec) * ADD_TOTAL_ALLOCS);
00638 if (!mm_addresses) {
00639 mm_println("MM ERROR: Insuffient memory to allocate MM table");
00640 pthread_mutex_destroy(&mm_mutex);
00641 return false;
00642 }
00643
00644 memset(mm_addresses, 0, sizeof(MissingMemoryRec) * ADD_TOTAL_ALLOCS);
00645 mm_total_allocated = ADD_TOTAL_ALLOCS;
00646 mm_nr_in_use = 0L;
00647 mm_alloc_count = 0L;
00648 #endif
00649 return true;
00650 }
00651
00652 void cs_exit_memory(void)
00653 {
00654 #ifdef DEBUG
00655 uint32_t mm;
00656
00657 if (!mm_addresses)
00658 return;
00659
00660 pthread_mutex_lock(&mm_mutex);
00661 for (mm=0; mm<mm_nr_in_use; mm++)
00662 mm_throw_assertion(&mm_addresses[mm], mm_addresses[mm].ptr, "Not freed");
00663 free(mm_addresses);
00664 mm_addresses = NULL;
00665 mm_nr_in_use = 0L;
00666 mm_total_allocated = 0L;
00667 mm_alloc_count = 0L;
00668 pthread_mutex_unlock(&mm_mutex);
00669
00670 pthread_mutex_destroy(&mm_mutex);
00671 #endif
00672 }
00673
00674 #ifdef DEBUG
00675 uint32_t cs_mm_get_check_point()
00676 {
00677 return mm_alloc_count;
00678 }
00679
00680
00681
00682 void cs_mm_assert_check_point(uint32_t check_point)
00683 {
00684 uint32_t mm;
00685
00686 if (!mm_addresses)
00687 return;
00688
00689 pthread_mutex_lock(&mm_mutex);
00690 for (mm=0; mm<mm_nr_in_use; mm++) {
00691 if (mm_addresses[mm].id >= check_point)
00692 mm_throw_assertion(&mm_addresses[mm], mm_addresses[mm].ptr, "Not freed");
00693 }
00694
00695 pthread_mutex_unlock(&mm_mutex);
00696
00697 }
00698 #endif