~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to plugin/pbms/src/cslib/CSMemory.cc

  • Committer: Mark Atwood
  • Date: 2011-12-20 02:32:53 UTC
  • mfrom: (2469.1.1 drizzle-build)
  • Revision ID: me@mark.atwood.name-20111220023253-bvu0kr14kwsdvz7g
mergeĀ lp:~brianaker/drizzle/deprecate-pbms

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/* Copyright (C) 2008 PrimeBase Technologies GmbH, Germany
2
 
 *
3
 
 * PrimeBase Media Stream for MySQL
4
 
 *
5
 
 * This program is free software; you can redistribute it and/or modify
6
 
 * it under the terms of the GNU General Public License as published by
7
 
 * the Free Software Foundation; either version 2 of the License, or
8
 
 * (at your option) any later version.
9
 
 *
10
 
 * This program is distributed in the hope that it will be useful,
11
 
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12
 
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13
 
 * GNU General Public License for more details.
14
 
 *
15
 
 * You should have received a copy of the GNU General Public License
16
 
 * along with this program; if not, write to the Free Software
17
 
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18
 
 *
19
 
 * Original author: Paul McCullagh (H&G2JCtL)
20
 
 * Continued development: Barry Leslie
21
 
 *
22
 
 * 2007-06-15
23
 
 *
24
 
 * CORE SYSTEM:
25
 
 * Memory allocation
26
 
 *
27
 
 * For debugging memory leaks search for "DEBUG-BREAK-POINT" and watch mm_tracking_id
28
 
 */
29
 
 
30
 
#include "CSConfig.h"
31
 
 
32
 
#include <assert.h>
33
 
#include <string.h>
34
 
#include <stddef.h>
35
 
#include <stdlib.h>
36
 
#include <inttypes.h>
37
 
 
38
 
#include "CSException.h"
39
 
#include "CSMemory.h"
40
 
#include "CSThread.h"
41
 
#include "CSStrUtil.h"
42
 
#include "CSGlobal.h"
43
 
 
44
 
#ifdef DEBUG
45
 
#undef cs_malloc
46
 
#undef cs_calloc
47
 
#undef cs_realloc
48
 
#undef cs_free
49
 
#undef new
50
 
#endif
51
 
 
52
 
void *cs_malloc(size_t size)
53
 
{
54
 
        void *ptr;
55
 
 
56
 
        if (!(ptr = malloc(size)))
57
 
                CSException::throwOSError(CS_CONTEXT, ENOMEM);
58
 
        return ptr;
59
 
}
60
 
 
61
 
void *cs_calloc(size_t size)
62
 
{
63
 
        void *ptr;
64
 
 
65
 
        if (!(ptr = malloc(size)))
66
 
                CSException::throwOSError(CS_CONTEXT, ENOMEM);
67
 
        memset(ptr, 0, size);
68
 
        return ptr;
69
 
}
70
 
 
71
 
void cs_realloc(void **ptr, size_t size)
72
 
{
73
 
        void *new_ptr;
74
 
        
75
 
        if (!(new_ptr = realloc(*ptr, size)))
76
 
                CSException::throwOSError(CS_CONTEXT, ENOMEM);
77
 
        *ptr = new_ptr;
78
 
}
79
 
 
80
 
void cs_free(void *ptr)
81
 
{
82
 
        free(ptr);
83
 
}
84
 
 
85
 
/*
86
 
 * -----------------------------------------------------------------------
87
 
 * DEBUG MEMORY ALLOCATION AND HEAP CHECKING
88
 
 */
89
 
 
90
 
#ifdef DEBUG
91
 
 
92
 
#define RECORD_MM
93
 
 
94
 
#define ADD_TOTAL_ALLOCS                        4000
95
 
 
96
 
#define SHIFT_RIGHT(ptr, n)                     memmove(((char *) (ptr)) + sizeof(MissingMemoryRec), (ptr), (long) (n) * sizeof(MissingMemoryRec))
97
 
#define SHIFT_LEFT(ptr, n)                      memmove((ptr), ((char *) (ptr)) + sizeof(MissingMemoryRec), (long) (n) * sizeof(MissingMemoryRec))
98
 
 
99
 
typedef struct MissingMemory {
100
 
        void                    *ptr;
101
 
        uint32_t                        id;
102
 
        const char              *func_name;
103
 
        const char              *file_name;
104
 
        uint32_t                        line_nr;
105
 
} MissingMemoryRec, *MissingMemoryPtr;
106
 
 
107
 
static MissingMemoryRec *mm_addresses = NULL;
108
 
static uint32_t                 mm_nr_in_use = 0L;
109
 
static uint32_t                 mm_total_allocated = 0L;
110
 
static uint32_t                 mm_alloc_count = 0;
111
 
static pthread_mutex_t  mm_mutex;
112
 
 
113
 
/* Set this variable to the ID of the memory you want
114
 
 * to track.
115
 
 */
116
 
static uint32_t                 mm_tracking_id = 0;
117
 
 
118
 
static void mm_println(const char *str)
119
 
{
120
 
        printf("%s\n", str);
121
 
}
122
 
 
123
 
static long mm_find_pointer(void *ptr)
124
 
{
125
 
        register long   i, n, guess;
126
 
 
127
 
        i = 0;
128
 
        n = mm_nr_in_use;
129
 
        while (i < n) {
130
 
                guess = (i + n - 1) >> 1;
131
 
                if (ptr == mm_addresses[guess].ptr)
132
 
                        return(guess);
133
 
                if (ptr < mm_addresses[guess].ptr)
134
 
                        n = guess;
135
 
                else
136
 
                        i = guess + 1;
137
 
        }
138
 
        return(-1);
139
 
}
140
 
 
141
 
static long mm_add_pointer(void *ptr)
142
 
{
143
 
        register int    i, n, guess;
144
 
 
145
 
        if (mm_nr_in_use == mm_total_allocated) {
146
 
                /* Not enough space, add more: */
147
 
                MissingMemoryRec *new_addresses;
148
 
 
149
 
                new_addresses = (MissingMemoryRec *) malloc(sizeof(MissingMemoryRec) * (mm_total_allocated + ADD_TOTAL_ALLOCS));
150
 
                if (!new_addresses)
151
 
                        return(-1);
152
 
 
153
 
                if (mm_addresses) {
154
 
                        memcpy(new_addresses, mm_addresses, sizeof(MissingMemoryRec) * mm_total_allocated);
155
 
                        free(mm_addresses);
156
 
                }
157
 
 
158
 
                mm_addresses = new_addresses;
159
 
                mm_total_allocated += ADD_TOTAL_ALLOCS;
160
 
        }
161
 
 
162
 
        i = 0;
163
 
        n = mm_nr_in_use;
164
 
        while (i < n) {
165
 
                guess = (i + n - 1) >> 1;
166
 
                if (ptr < mm_addresses[guess].ptr)
167
 
                        n = guess;
168
 
                else
169
 
                        i = guess + 1;
170
 
        }
171
 
 
172
 
        SHIFT_RIGHT(&mm_addresses[i], mm_nr_in_use - i);
173
 
        mm_nr_in_use++;
174
 
        mm_addresses[i].ptr = ptr;
175
 
        return(i);
176
 
}
177
 
 
178
 
static char *cs_mm_watch_point = 0;
179
 
 
180
 
static long mm_remove_pointer(void *ptr)
181
 
{
182
 
        register int    i, n, guess;
183
 
 
184
 
        if (cs_mm_watch_point == ptr)
185
 
                printf("Hit watch point\n");
186
 
 
187
 
        i = 0;
188
 
        n = mm_nr_in_use;
189
 
        while (i < n) {
190
 
                guess = (i + n - 1) >> 1;
191
 
                if (ptr == mm_addresses[guess].ptr)
192
 
                        goto remove;
193
 
                if (ptr < mm_addresses[guess].ptr)
194
 
                        n = guess;
195
 
                else
196
 
                        i = guess + 1;
197
 
        }
198
 
        return(-1);
199
 
 
200
 
        remove:
201
 
        /* Decrease the number of sets, and shift left: */
202
 
        mm_nr_in_use--;
203
 
        SHIFT_LEFT(&mm_addresses[guess], mm_nr_in_use - guess); 
204
 
        return(guess);
205
 
}
206
 
 
207
 
static void mm_throw_assertion(MissingMemoryPtr mm_ptr, void *p, const char *message)
208
 
{
209
 
        char str[200];
210
 
 
211
 
        if (mm_ptr) {
212
 
                snprintf(str, 200, "MM ERROR: %8p (#%"PRId32") %s:%"PRId32" %s",
213
 
                                           mm_ptr->ptr,
214
 
                                           mm_ptr->id,
215
 
                                           cs_last_name_of_path(mm_ptr->file_name),
216
 
                                           mm_ptr->line_nr,
217
 
                                           message);
218
 
        }
219
 
        else
220
 
                snprintf(str, 200, "MM ERROR: %8p %s", p, message);
221
 
        mm_println(str);
222
 
}
223
 
 
224
 
static uint32_t mm_add_core_ptr(void *ptr, const char *func, const char *file, int line)
225
 
{
226
 
        long    mm;
227
 
        uint32_t        id;
228
 
 
229
 
        mm = mm_add_pointer(ptr);
230
 
        if (mm < 0) {
231
 
                mm_println("MM ERROR: Cannot allocate table big enough!");
232
 
                return 0;
233
 
        }
234
 
 
235
 
        /* Record the pointer: */
236
 
        if (mm_alloc_count == mm_tracking_id) { 
237
 
                /* Enable you to set a breakpoint: */
238
 
                id = mm_alloc_count++; // DEBUG-BREAK-POINT
239
 
        }
240
 
        else {
241
 
                id = mm_alloc_count++;
242
 
        }
243
 
        mm_addresses[mm].ptr = ptr;
244
 
        mm_addresses[mm].id = id;
245
 
        mm_addresses[mm].func_name = func;
246
 
        if (file)
247
 
                mm_addresses[mm].file_name = file;
248
 
        else
249
 
                mm_addresses[mm].file_name = "?";
250
 
        mm_addresses[mm].line_nr = line;
251
 
        return id;
252
 
}
253
 
 
254
 
static void mm_remove_core_ptr(void *ptr)
255
 
{
256
 
        long mm;
257
 
 
258
 
        mm = mm_remove_pointer(ptr);
259
 
        if (mm < 0) {
260
 
                mm_println("MM ERROR: Pointer not allocated");
261
 
                return;
262
 
        }
263
 
}
264
 
 
265
 
static long mm_find_core_ptr(void *ptr)
266
 
{
267
 
        long mm;
268
 
 
269
 
        mm = mm_find_pointer(ptr);
270
 
        if (mm < 0)
271
 
                mm_throw_assertion(NULL, ptr, "Pointer not allocated");
272
 
        return(mm);
273
 
}
274
 
 
275
 
static void mm_replace_core_ptr(long i, void *ptr)
276
 
{
277
 
        MissingMemoryRec        tmp = mm_addresses[i];
278
 
        long                            mm;
279
 
 
280
 
        mm_remove_pointer(mm_addresses[i].ptr);
281
 
        mm = mm_add_pointer(ptr);
282
 
        if (mm < 0) {
283
 
                mm_println("MM ERROR: Cannot allocate table big enough!");
284
 
                return;
285
 
        }
286
 
        mm_addresses[mm] = tmp;
287
 
        mm_addresses[mm].ptr = ptr;
288
 
}
289
 
 
290
 
/*
291
 
 * -----------------------------------------------------------------------
292
 
 * MISSING MEMORY PUBLIC ROUTINES
293
 
 */
294
 
 
295
 
#define MEM_DEBUG_HDR_SIZE              offsetof(MemoryDebugRec, data)
296
 
#define MEM_TRAILER_SIZE                2
297
 
#define MEM_HEADER                              0x01010101
298
 
#define MEM_FREED                               0x03030303
299
 
#define MEM_TRAILER_BYTE                0x02
300
 
#define MEM_FREED_BYTE                  0x03
301
 
 
302
 
typedef struct MemoryDebug {
303
 
        uint32_t                check;
304
 
        uint32_t                md_id;                          /* The memory ID! */
305
 
        uint32_t                size;
306
 
        char            data[200];
307
 
} MemoryDebugRec, *MemoryDebugPtr;
308
 
 
309
 
static size_t mm_check_and_free(MissingMemoryPtr mm_ptr, void *p, bool freeme)
310
 
{
311
 
        unsigned char   *ptr = (unsigned char *) p - MEM_DEBUG_HDR_SIZE;
312
 
        MemoryDebugPtr  debug_ptr = (MemoryDebugPtr) ptr;
313
 
        size_t                  size = debug_ptr->size;
314
 
 
315
 
        if (!ASSERT(p)) 
316
 
                return(0);
317
 
        if (!ASSERT(((size_t) p & 1L) == 0)) 
318
 
                return(0);
319
 
 
320
 
        if (debug_ptr->check == MEM_FREED) { 
321
 
                mm_println("MM ERROR: Pointer already freed 'debug_ptr->check != MEM_FREED'");
322
 
                return(0);
323
 
        }
324
 
 
325
 
        if (debug_ptr->check != MEM_HEADER) {
326
 
                mm_println("MM ERROR: Header not valid 'debug_ptr->check != MEM_HEADER'");
327
 
                return(0);
328
 
        }
329
 
 
330
 
        if (!(*((unsigned char *) ptr + size + MEM_DEBUG_HDR_SIZE) == MEM_TRAILER_BYTE &&
331
 
                        *((unsigned char *) ptr + size + MEM_DEBUG_HDR_SIZE + 1L) == MEM_TRAILER_BYTE)) { 
332
 
                mm_throw_assertion(mm_ptr, p, "Trailer overwritten");
333
 
                return(0);
334
 
        }
335
 
 
336
 
        if (freeme) {
337
 
                debug_ptr->check = MEM_FREED;
338
 
                *((unsigned char *) ptr + size + MEM_DEBUG_HDR_SIZE) = MEM_FREED_BYTE;
339
 
                *((unsigned char *) ptr + size + MEM_DEBUG_HDR_SIZE + 1L) = MEM_FREED_BYTE;
340
 
 
341
 
                memset(((unsigned char *) ptr) + MEM_DEBUG_HDR_SIZE, 0xF5, size);
342
 
                cs_free(ptr);
343
 
        }
344
 
 
345
 
        return size;
346
 
}
347
 
 
348
 
bool cs_mm_scan_core(void)
349
 
{
350
 
        uint32_t mm;
351
 
        bool rtc = true;
352
 
 
353
 
        if (!mm_addresses)
354
 
                return true;
355
 
 
356
 
        pthread_mutex_lock(&mm_mutex);
357
 
 
358
 
        for (mm=0; mm<mm_nr_in_use; mm++)       {
359
 
                if (!mm_check_and_free(&mm_addresses[mm], mm_addresses[mm].ptr, false))
360
 
                        rtc = false;
361
 
        }
362
 
        
363
 
        pthread_mutex_unlock(&mm_mutex);
364
 
        return rtc;
365
 
}
366
 
 
367
 
void cs_mm_memmove(void *block, void *dest, void *source, size_t size)
368
 
{
369
 
        if (block) {
370
 
                MemoryDebugPtr  debug_ptr = (MemoryDebugPtr) ((char *) block - MEM_DEBUG_HDR_SIZE);
371
 
 
372
 
#ifdef RECORD_MM
373
 
                pthread_mutex_lock(&mm_mutex);
374
 
                mm_find_core_ptr(block);
375
 
                pthread_mutex_unlock(&mm_mutex);
376
 
#endif
377
 
                mm_check_and_free(NULL, block, false);
378
 
 
379
 
                if (dest < block || (char *) dest > (char *) block + debug_ptr->size) {
380
 
                        mm_println("MM ERROR: Destination not in block");
381
 
                        return;
382
 
                }
383
 
                if ((char *) dest + size > (char *) block + debug_ptr->size) {
384
 
                        mm_println("MM ERROR: Copy will overwrite memory");
385
 
                        return;
386
 
                }
387
 
        }
388
 
 
389
 
        memmove(dest, source, size);
390
 
}
391
 
 
392
 
void cs_mm_memcpy(void *block, void *dest, void *source, size_t size)
393
 
{
394
 
        if (block) {
395
 
                MemoryDebugPtr  debug_ptr = (MemoryDebugPtr) ((char *) block - MEM_DEBUG_HDR_SIZE);
396
 
 
397
 
#ifdef RECORD_MM
398
 
                pthread_mutex_lock(&mm_mutex);
399
 
                mm_find_core_ptr(block);
400
 
                pthread_mutex_unlock(&mm_mutex);
401
 
#endif
402
 
                mm_check_and_free(NULL, block, false);
403
 
 
404
 
                if (dest < block || (char *) dest > (char *) block + debug_ptr->size)
405
 
                        mm_throw_assertion(NULL, block, "Destination not in block");
406
 
                if ((char *) dest + size > (char *) block + debug_ptr->size)
407
 
                        mm_throw_assertion(NULL, block, "Copy will overwrite memory");
408
 
        }
409
 
 
410
 
        memcpy(dest, source, size);
411
 
}
412
 
 
413
 
void cs_mm_memset(void *block, void *dest, int value, size_t size)
414
 
{
415
 
        if (block) {
416
 
                MemoryDebugPtr  debug_ptr = (MemoryDebugPtr) ((char *) block - MEM_DEBUG_HDR_SIZE);
417
 
 
418
 
#ifdef RECORD_MM
419
 
                pthread_mutex_lock(&mm_mutex);
420
 
                mm_find_core_ptr(block);
421
 
                pthread_mutex_unlock(&mm_mutex);
422
 
#endif
423
 
                mm_check_and_free(NULL, block, false);
424
 
 
425
 
                if (dest < block || (char *) dest > (char *) block + debug_ptr->size)
426
 
                        mm_throw_assertion(NULL, block, "Destination not in block");
427
 
                if ((char *) dest + size > (char *) block + debug_ptr->size)
428
 
                        mm_throw_assertion(NULL, block, "Copy will overwrite memory");
429
 
        }
430
 
 
431
 
        memset(dest, value, size);
432
 
}
433
 
 
434
 
void *cs_mm_malloc(const char *func, const char *file, int line, size_t size)
435
 
{
436
 
        unsigned char *p = (unsigned char *) cs_malloc(size + MEM_DEBUG_HDR_SIZE + MEM_TRAILER_SIZE);
437
 
 
438
 
        if (!p)
439
 
                return NULL;
440
 
 
441
 
        memset(p, 0x55, size + MEM_DEBUG_HDR_SIZE + MEM_TRAILER_SIZE);
442
 
 
443
 
        ((MemoryDebugPtr) p)->check = MEM_HEADER;
444
 
        ((MemoryDebugPtr) p)->md_id = 0;
445
 
        ((MemoryDebugPtr) p)->size = (uint32_t) size;
446
 
        *(p + size + MEM_DEBUG_HDR_SIZE) = MEM_TRAILER_BYTE;
447
 
        *(p + size + MEM_DEBUG_HDR_SIZE + 1L) = MEM_TRAILER_BYTE;
448
 
 
449
 
#ifdef RECORD_MM
450
 
        pthread_mutex_lock(&mm_mutex);
451
 
        ((MemoryDebugPtr) p)->md_id = mm_add_core_ptr(p + MEM_DEBUG_HDR_SIZE, func, file, line);
452
 
        pthread_mutex_unlock(&mm_mutex);
453
 
#endif
454
 
 
455
 
        return p + MEM_DEBUG_HDR_SIZE;
456
 
}
457
 
 
458
 
void *cs_mm_calloc(const char *func, const char *file, int line, size_t size)
459
 
{
460
 
        unsigned char *p = (unsigned char *) cs_calloc(size + MEM_DEBUG_HDR_SIZE + MEM_TRAILER_SIZE);
461
 
 
462
 
        if (!p) 
463
 
                return NULL;
464
 
 
465
 
        ((MemoryDebugPtr) p)->check = MEM_HEADER;
466
 
        ((MemoryDebugPtr) p)->md_id = 0;
467
 
        ((MemoryDebugPtr) p)->size  = (uint32_t) size;
468
 
        *(p + size + MEM_DEBUG_HDR_SIZE) = MEM_TRAILER_BYTE;
469
 
        *(p + size + MEM_DEBUG_HDR_SIZE + 1L) = MEM_TRAILER_BYTE;
470
 
 
471
 
#ifdef RECORD_MM
472
 
        pthread_mutex_lock(&mm_mutex);
473
 
        ((MemoryDebugPtr) p)->md_id = mm_add_core_ptr(p + MEM_DEBUG_HDR_SIZE, func, file, line);
474
 
        pthread_mutex_unlock(&mm_mutex);
475
 
#endif
476
 
 
477
 
        return p + MEM_DEBUG_HDR_SIZE;
478
 
}
479
 
 
480
 
void cs_mm_realloc(const char *func, const char *file, int line, void **ptr, size_t newsize)
481
 
{
482
 
        unsigned char   *oldptr = (unsigned char *) *ptr;
483
 
        size_t                  size;
484
 
        long                    mm;
485
 
        unsigned char   *pnew;
486
 
 
487
 
        if (!oldptr) {
488
 
                *ptr = cs_mm_malloc(func, file, line, newsize);
489
 
                return;
490
 
        }
491
 
 
492
 
#ifdef RECORD_MM
493
 
        // The lock must be held until the realloc has completed otherwise
494
 
        // a scan of the memory may report a bad memory header.
495
 
        pthread_mutex_lock(&mm_mutex);
496
 
        if ((mm = mm_find_core_ptr(oldptr)) < 0) {
497
 
                pthread_mutex_unlock(&mm_mutex);
498
 
                CSException::throwOSError(CS_CONTEXT, ENOMEM);
499
 
        }
500
 
        // pthread_mutex_unlock(&mm_mutex); It will be unlocked below
501
 
#endif
502
 
 
503
 
        oldptr = oldptr - MEM_DEBUG_HDR_SIZE;
504
 
        size = ((MemoryDebugPtr) oldptr)->size;
505
 
 
506
 
        ASSERT(((MemoryDebugPtr) oldptr)->check == MEM_HEADER);
507
 
        ASSERT(*((unsigned char *) oldptr + size + MEM_DEBUG_HDR_SIZE) == MEM_TRAILER_BYTE && 
508
 
                        *((unsigned char *) oldptr + size + MEM_DEBUG_HDR_SIZE + 1L) == MEM_TRAILER_BYTE);
509
 
 
510
 
        /* Grow allways moves! */
511
 
        pnew = (unsigned char *) cs_malloc(newsize + MEM_DEBUG_HDR_SIZE + MEM_TRAILER_SIZE);
512
 
        if (!pnew) {
513
 
#ifdef RECORD_MM
514
 
                pthread_mutex_unlock(&mm_mutex); 
515
 
#endif
516
 
                CSException::throwOSError(CS_CONTEXT, ENOMEM);
517
 
                return;
518
 
        }
519
 
 
520
 
        if (newsize > size) {
521
 
                memcpy(((MemoryDebugPtr) pnew)->data, ((MemoryDebugPtr) oldptr)->data, size);
522
 
                memset(((MemoryDebugPtr) pnew)->data + size, 0x55, newsize - size);
523
 
        }
524
 
        else
525
 
                memcpy(((MemoryDebugPtr) pnew)->data, ((MemoryDebugPtr) oldptr)->data, newsize);
526
 
        memset(oldptr, 0x55, size + MEM_DEBUG_HDR_SIZE + MEM_TRAILER_SIZE);
527
 
 
528
 
#ifdef RECORD_MM
529
 
        // pthread_mutex_lock(&mm_mutex); It was locked above
530
 
        if ((mm = mm_find_core_ptr(oldptr + MEM_DEBUG_HDR_SIZE)) < 0) {
531
 
                pthread_mutex_unlock(&mm_mutex);
532
 
                CSException::throwOSError(CS_CONTEXT, ENOMEM);
533
 
                return;
534
 
        }
535
 
        mm_replace_core_ptr(mm, pnew + MEM_DEBUG_HDR_SIZE);
536
 
        pthread_mutex_unlock(&mm_mutex);
537
 
#endif
538
 
 
539
 
        cs_free(oldptr);
540
 
 
541
 
        ((MemoryDebugPtr) pnew)->check = MEM_HEADER;
542
 
        ((MemoryDebugPtr) pnew)->size = (uint32_t) newsize;
543
 
        *(pnew + newsize + MEM_DEBUG_HDR_SIZE) = MEM_TRAILER_BYTE;
544
 
        *(pnew + newsize + MEM_DEBUG_HDR_SIZE + 1L)     = MEM_TRAILER_BYTE;
545
 
 
546
 
        *ptr = pnew + MEM_DEBUG_HDR_SIZE;
547
 
}
548
 
 
549
 
void cs_mm_free(void *ptr)
550
 
{
551
 
        bool my_pointer = false;
552
 
 
553
 
#ifdef RECORD_MM
554
 
        pthread_mutex_lock(&mm_mutex);
555
 
        if (mm_find_pointer(ptr) >= 0) {
556
 
                my_pointer = true;
557
 
                mm_remove_core_ptr(ptr);
558
 
        }
559
 
        pthread_mutex_unlock(&mm_mutex);
560
 
#endif
561
 
        if (my_pointer)
562
 
                mm_check_and_free(NULL, ptr, true);
563
 
        else
564
 
                free(ptr);
565
 
}
566
 
 
567
 
void cs_mm_pfree(void **ptr)
568
 
{
569
 
        if (*ptr) {
570
 
                void *p = *ptr;
571
 
 
572
 
                *ptr = NULL;
573
 
                cs_mm_free(p);
574
 
        }
575
 
}
576
 
 
577
 
size_t cs_mm_malloc_size(void *ptr)
578
 
{
579
 
        size_t size = 0;
580
 
 
581
 
#ifdef RECORD_MM
582
 
        pthread_mutex_lock(&mm_mutex);
583
 
        mm_find_core_ptr(ptr);
584
 
        pthread_mutex_unlock(&mm_mutex);
585
 
#endif
586
 
        size = mm_check_and_free(NULL, ptr, false);
587
 
        return size;
588
 
}
589
 
 
590
 
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)
591
 
{
592
 
        unsigned char   *ptr = (unsigned char *) p - MEM_DEBUG_HDR_SIZE;
593
 
        MemoryDebugPtr  debug_ptr = (MemoryDebugPtr) ptr;
594
 
        CSThread                *self = CSThread::getSelf();
595
 
        char                    buffer[300];
596
 
        int                             cnt = 0;
597
 
 
598
 
        if (!track_me && !mm_tracking_id)
599
 
                return;
600
 
 
601
 
        if (func) {
602
 
                cs_format_context(300, buffer, func, file, line);
603
 
                fprintf(stderr, "TRACKING (%"PRIu32"): %s %2"PRIu32" %s", debug_ptr->md_id, inc ? "INC" : "DEC", ref_cnt, buffer);
604
 
        }
605
 
        else
606
 
                fprintf(stderr, "TRACKING (%"PRIu32"): %s %2"PRIu32"", debug_ptr->md_id, inc ? "INC" : "DEC", ref_cnt);
607
 
 
608
 
        for (int i = self->callTop-1; i>=0 && cnt < 4; i--) {
609
 
                cs_format_context(300, buffer, self->callStack[i].cs_func, self->callStack[i].cs_file, self->callStack[i].cs_line);
610
 
                fprintf(stderr," %s", buffer);
611
 
                cnt++;
612
 
        }
613
 
        fprintf(stderr,"\n");
614
 
}
615
 
 
616
 
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)
617
 
{
618
 
        unsigned char   *ptr = (unsigned char *) p - MEM_DEBUG_HDR_SIZE;
619
 
        MemoryDebugPtr  debug_ptr = (MemoryDebugPtr) ptr;
620
 
 
621
 
        if (track_me || (mm_tracking_id && debug_ptr->md_id == mm_tracking_id))
622
 
                cs_mm_print_track(func, file, line, p, inc, ref_cnt, track_me);
623
 
}
624
 
 
625
 
#endif
626
 
 
627
 
/*
628
 
 * -----------------------------------------------------------------------
629
 
 * INIT/EXIT MEMORY
630
 
 */
631
 
 
632
 
bool cs_init_memory(void)
633
 
{
634
 
#ifdef DEBUG
635
 
        pthread_mutex_init(&mm_mutex, NULL);
636
 
        mm_addresses = (MissingMemoryRec *) malloc(sizeof(MissingMemoryRec) * ADD_TOTAL_ALLOCS);
637
 
        if (!mm_addresses) {
638
 
                mm_println("MM ERROR: Insuffient memory to allocate MM table");
639
 
                pthread_mutex_destroy(&mm_mutex);
640
 
                return false;
641
 
        }
642
 
 
643
 
        memset(mm_addresses, 0, sizeof(MissingMemoryRec) * ADD_TOTAL_ALLOCS);
644
 
        mm_total_allocated = ADD_TOTAL_ALLOCS;
645
 
        mm_nr_in_use = 0L;
646
 
        mm_alloc_count = 0L;
647
 
#endif
648
 
        return true;
649
 
}
650
 
 
651
 
void cs_exit_memory(void)
652
 
{
653
 
#ifdef DEBUG
654
 
        uint32_t mm;
655
 
 
656
 
        if (!mm_addresses)
657
 
                return;
658
 
 
659
 
        pthread_mutex_lock(&mm_mutex);
660
 
        for (mm=0; mm<mm_nr_in_use; mm++)
661
 
                mm_throw_assertion(&mm_addresses[mm], mm_addresses[mm].ptr, "Not freed");
662
 
        free(mm_addresses);
663
 
        mm_addresses = NULL;
664
 
        mm_nr_in_use = 0L;
665
 
        mm_total_allocated = 0L;
666
 
        mm_alloc_count = 0L;
667
 
        pthread_mutex_unlock(&mm_mutex);
668
 
 
669
 
        pthread_mutex_destroy(&mm_mutex);
670
 
#endif
671
 
}
672
 
 
673
 
#ifdef DEBUG
674
 
uint32_t cs_mm_get_check_point()
675
 
{
676
 
        return mm_alloc_count;
677
 
}
678
 
 
679
 
// Reports any memory allocated after the check_point
680
 
// but has not been freed.
681
 
void cs_mm_assert_check_point(uint32_t check_point)
682
 
{
683
 
        uint32_t mm;
684
 
 
685
 
        if (!mm_addresses)
686
 
                return;
687
 
 
688
 
        pthread_mutex_lock(&mm_mutex);
689
 
        for (mm=0; mm<mm_nr_in_use; mm++) {
690
 
                if (mm_addresses[mm].id >= check_point)
691
 
                        mm_throw_assertion(&mm_addresses[mm], mm_addresses[mm].ptr, "Not freed");
692
 
        }
693
 
 
694
 
        pthread_mutex_unlock(&mm_mutex);
695
 
 
696
 
}
697
 
#endif