~drizzle-trunk/drizzle/development

« back to all changes in this revision

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

Added the PBMS daemon plugin.

(Augen zu und durch!)

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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 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 <inttypes.h>
 
31
#include "CSConfig.h"
 
32
 
 
33
#include <assert.h>
 
34
#include <string.h>
 
35
#include <stddef.h>
 
36
#include <stdlib.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
        u_int                   id;
 
102
        const char              *func_name;
 
103
        const char              *file_name;
 
104
        u_int                   line_nr;
 
105
} MissingMemoryRec, *MissingMemoryPtr;
 
106
 
 
107
static MissingMemoryRec *mm_addresses = NULL;
 
108
static u_int                    mm_nr_in_use = 0L;
 
109
static u_int                    mm_total_allocated = 0L;
 
110
static u_int                    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 u_int                    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: %08p (#%"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: %08p %s", p, message);
 
221
        mm_println(str);
 
222
}
 
223
 
 
224
static u_int mm_add_core_ptr(void *ptr, const char *func, const char *file, int line)
 
225
{
 
226
        long    mm;
 
227
        u_int   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
        u_int           check;
 
304
        u_int           md_id;                          /* The memory ID! */
 
305
        u_int           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
        long                    a_value;  /* Added to simplfy debugging. */
 
315
 
 
316
        if (!ASSERT(p)) 
 
317
                return(0);
 
318
        if (!ASSERT(((size_t) p & 1L) == 0)) 
 
319
                return(0);
 
320
        a_value = MEM_FREED;
 
321
        if (debug_ptr->check == MEM_FREED) { 
 
322
                mm_println("MM ERROR: Pointer already freed 'debug_ptr->check != MEM_FREED'");
 
323
                return(0);
 
324
        }
 
325
        a_value = MEM_HEADER;
 
326
        if (debug_ptr->check != MEM_HEADER) {
 
327
                mm_println("MM ERROR: Header not valid 'debug_ptr->check != MEM_HEADER'");
 
328
                return(0);
 
329
        }
 
330
        a_value = MEM_TRAILER_BYTE;
 
331
        if (!(*((unsigned char *) ptr + size + MEM_DEBUG_HDR_SIZE) == MEM_TRAILER_BYTE &&
 
332
                        *((unsigned char *) ptr + size + MEM_DEBUG_HDR_SIZE + 1L) == MEM_TRAILER_BYTE)) { 
 
333
                mm_throw_assertion(mm_ptr, p, "Trailer overwritten");
 
334
                return(0);
 
335
        }
 
336
 
 
337
        if (freeme) {
 
338
                debug_ptr->check = MEM_FREED;
 
339
                *((unsigned char *) ptr + size + MEM_DEBUG_HDR_SIZE) = MEM_FREED_BYTE;
 
340
                *((unsigned char *) ptr + size + MEM_DEBUG_HDR_SIZE + 1L) = MEM_FREED_BYTE;
 
341
 
 
342
                memset(((unsigned char *) ptr) + MEM_DEBUG_HDR_SIZE, 0xF5, size);
 
343
                cs_free(ptr);
 
344
        }
 
345
 
 
346
        return size;
 
347
}
 
348
 
 
349
bool cs_mm_scan_core(void)
 
350
{
 
351
        u_int mm;
 
352
        bool rtc = true;
 
353
 
 
354
        if (!mm_addresses)
 
355
                return true;
 
356
 
 
357
        pthread_mutex_lock(&mm_mutex);
 
358
 
 
359
        for (mm=0; mm<mm_nr_in_use; mm++)       {
 
360
                if (!mm_check_and_free(&mm_addresses[mm], mm_addresses[mm].ptr, false))
 
361
                        rtc = false;
 
362
        }
 
363
        
 
364
        pthread_mutex_unlock(&mm_mutex);
 
365
        return rtc;
 
366
}
 
367
 
 
368
void cs_mm_memmove(void *block, void *dest, void *source, size_t size)
 
369
{
 
370
        if (block) {
 
371
                MemoryDebugPtr  debug_ptr = (MemoryDebugPtr) ((char *) block - MEM_DEBUG_HDR_SIZE);
 
372
 
 
373
#ifdef RECORD_MM
 
374
                pthread_mutex_lock(&mm_mutex);
 
375
                mm_find_core_ptr(block);
 
376
                pthread_mutex_unlock(&mm_mutex);
 
377
#endif
 
378
                mm_check_and_free(NULL, block, false);
 
379
 
 
380
                if (dest < block || (char *) dest > (char *) block + debug_ptr->size) {
 
381
                        mm_println("MM ERROR: Destination not in block");
 
382
                        return;
 
383
                }
 
384
                if ((char *) dest + size > (char *) block + debug_ptr->size) {
 
385
                        mm_println("MM ERROR: Copy will overwrite memory");
 
386
                        return;
 
387
                }
 
388
        }
 
389
 
 
390
        memmove(dest, source, size);
 
391
}
 
392
 
 
393
void cs_mm_memcpy(void *block, void *dest, void *source, size_t size)
 
394
{
 
395
        if (block) {
 
396
                MemoryDebugPtr  debug_ptr = (MemoryDebugPtr) ((char *) block - MEM_DEBUG_HDR_SIZE);
 
397
 
 
398
#ifdef RECORD_MM
 
399
                pthread_mutex_lock(&mm_mutex);
 
400
                mm_find_core_ptr(block);
 
401
                pthread_mutex_unlock(&mm_mutex);
 
402
#endif
 
403
                mm_check_and_free(NULL, block, false);
 
404
 
 
405
                if (dest < block || (char *) dest > (char *) block + debug_ptr->size)
 
406
                        mm_throw_assertion(NULL, block, "Destination not in block");
 
407
                if ((char *) dest + size > (char *) block + debug_ptr->size)
 
408
                        mm_throw_assertion(NULL, block, "Copy will overwrite memory");
 
409
        }
 
410
 
 
411
        memcpy(dest, source, size);
 
412
}
 
413
 
 
414
void cs_mm_memset(void *block, void *dest, int value, size_t size)
 
415
{
 
416
        if (block) {
 
417
                MemoryDebugPtr  debug_ptr = (MemoryDebugPtr) ((char *) block - MEM_DEBUG_HDR_SIZE);
 
418
 
 
419
#ifdef RECORD_MM
 
420
                pthread_mutex_lock(&mm_mutex);
 
421
                mm_find_core_ptr(block);
 
422
                pthread_mutex_unlock(&mm_mutex);
 
423
#endif
 
424
                mm_check_and_free(NULL, block, false);
 
425
 
 
426
                if (dest < block || (char *) dest > (char *) block + debug_ptr->size)
 
427
                        mm_throw_assertion(NULL, block, "Destination not in block");
 
428
                if ((char *) dest + size > (char *) block + debug_ptr->size)
 
429
                        mm_throw_assertion(NULL, block, "Copy will overwrite memory");
 
430
        }
 
431
 
 
432
        memset(dest, value, size);
 
433
}
 
434
 
 
435
void *cs_mm_malloc(const char *func, const char *file, int line, size_t size)
 
436
{
 
437
        unsigned char *p = (unsigned char *) cs_malloc(size + MEM_DEBUG_HDR_SIZE + MEM_TRAILER_SIZE);
 
438
 
 
439
        if (!p)
 
440
                return NULL;
 
441
 
 
442
        memset(p, 0x55, size + MEM_DEBUG_HDR_SIZE + MEM_TRAILER_SIZE);
 
443
 
 
444
        ((MemoryDebugPtr) p)->check = MEM_HEADER;
 
445
        ((MemoryDebugPtr) p)->md_id = 0;
 
446
        ((MemoryDebugPtr) p)->size = (u_int) size;
 
447
        *(p + size + MEM_DEBUG_HDR_SIZE) = MEM_TRAILER_BYTE;
 
448
        *(p + size + MEM_DEBUG_HDR_SIZE + 1L) = MEM_TRAILER_BYTE;
 
449
 
 
450
#ifdef RECORD_MM
 
451
        pthread_mutex_lock(&mm_mutex);
 
452
        ((MemoryDebugPtr) p)->md_id = mm_add_core_ptr(p + MEM_DEBUG_HDR_SIZE, func, file, line);
 
453
        pthread_mutex_unlock(&mm_mutex);
 
454
#endif
 
455
 
 
456
        return p + MEM_DEBUG_HDR_SIZE;
 
457
}
 
458
 
 
459
void *cs_mm_calloc(const char *func, const char *file, int line, size_t size)
 
460
{
 
461
        unsigned char *p = (unsigned char *) cs_calloc(size + MEM_DEBUG_HDR_SIZE + MEM_TRAILER_SIZE);
 
462
 
 
463
        if (!p) 
 
464
                return NULL;
 
465
 
 
466
        ((MemoryDebugPtr) p)->check = MEM_HEADER;
 
467
        ((MemoryDebugPtr) p)->md_id = 0;
 
468
        ((MemoryDebugPtr) p)->size  = (u_int) size;
 
469
        *(p + size + MEM_DEBUG_HDR_SIZE) = MEM_TRAILER_BYTE;
 
470
        *(p + size + MEM_DEBUG_HDR_SIZE + 1L) = MEM_TRAILER_BYTE;
 
471
 
 
472
#ifdef RECORD_MM
 
473
        pthread_mutex_lock(&mm_mutex);
 
474
        ((MemoryDebugPtr) p)->md_id = mm_add_core_ptr(p + MEM_DEBUG_HDR_SIZE, func, file, line);
 
475
        pthread_mutex_unlock(&mm_mutex);
 
476
#endif
 
477
 
 
478
        return p + MEM_DEBUG_HDR_SIZE;
 
479
}
 
480
 
 
481
void cs_mm_realloc(const char *func, const char *file, int line, void **ptr, size_t newsize)
 
482
{
 
483
        unsigned char   *oldptr = (unsigned char *) *ptr;
 
484
        size_t                  size;
 
485
        long                    mm;
 
486
        unsigned char   *pnew;
 
487
 
 
488
        if (!oldptr) {
 
489
                *ptr = cs_mm_malloc(func, file, line, newsize);
 
490
                return;
 
491
        }
 
492
 
 
493
#ifdef RECORD_MM
 
494
        // The lock must be held until the realloc has completed otherwise
 
495
        // a scan of the memory may report a bad memory header.
 
496
        pthread_mutex_lock(&mm_mutex);
 
497
        if ((mm = mm_find_core_ptr(oldptr)) < 0) {
 
498
                pthread_mutex_unlock(&mm_mutex);
 
499
                CSException::throwOSError(CS_CONTEXT, ENOMEM);
 
500
        }
 
501
        // pthread_mutex_unlock(&mm_mutex); It will be unlocked below
 
502
#endif
 
503
 
 
504
        oldptr = oldptr - MEM_DEBUG_HDR_SIZE;
 
505
        size = ((MemoryDebugPtr) oldptr)->size;
 
506
 
 
507
        ASSERT(((MemoryDebugPtr) oldptr)->check == MEM_HEADER);
 
508
        ASSERT(*((unsigned char *) oldptr + size + MEM_DEBUG_HDR_SIZE) == MEM_TRAILER_BYTE && 
 
509
                        *((unsigned char *) oldptr + size + MEM_DEBUG_HDR_SIZE + 1L) == MEM_TRAILER_BYTE);
 
510
 
 
511
        /* Grow allways moves! */
 
512
        pnew = (unsigned char *) cs_malloc(newsize + MEM_DEBUG_HDR_SIZE + MEM_TRAILER_SIZE);
 
513
        if (!pnew) {
 
514
#ifdef RECORD_MM
 
515
                pthread_mutex_unlock(&mm_mutex); 
 
516
#endif
 
517
                CSException::throwOSError(CS_CONTEXT, ENOMEM);
 
518
                return;
 
519
        }
 
520
 
 
521
        if (newsize > size) {
 
522
                memcpy(((MemoryDebugPtr) pnew)->data, ((MemoryDebugPtr) oldptr)->data, size);
 
523
                memset(((MemoryDebugPtr) pnew)->data + size, 0x55, newsize - size);
 
524
        }
 
525
        else
 
526
                memcpy(((MemoryDebugPtr) pnew)->data, ((MemoryDebugPtr) oldptr)->data, newsize);
 
527
        memset(oldptr, 0x55, size + MEM_DEBUG_HDR_SIZE + MEM_TRAILER_SIZE);
 
528
 
 
529
#ifdef RECORD_MM
 
530
        // pthread_mutex_lock(&mm_mutex); It was locked above
 
531
        if ((mm = mm_find_core_ptr(oldptr + MEM_DEBUG_HDR_SIZE)) < 0) {
 
532
                pthread_mutex_unlock(&mm_mutex);
 
533
                CSException::throwOSError(CS_CONTEXT, ENOMEM);
 
534
                return;
 
535
        }
 
536
        mm_replace_core_ptr(mm, pnew + MEM_DEBUG_HDR_SIZE);
 
537
        pthread_mutex_unlock(&mm_mutex);
 
538
#endif
 
539
 
 
540
        cs_free(oldptr);
 
541
 
 
542
        ((MemoryDebugPtr) pnew)->check = MEM_HEADER;
 
543
        ((MemoryDebugPtr) pnew)->size = (u_int) newsize;
 
544
        *(pnew + newsize + MEM_DEBUG_HDR_SIZE) = MEM_TRAILER_BYTE;
 
545
        *(pnew + newsize + MEM_DEBUG_HDR_SIZE + 1L)     = MEM_TRAILER_BYTE;
 
546
 
 
547
        *ptr = pnew + MEM_DEBUG_HDR_SIZE;
 
548
}
 
549
 
 
550
void cs_mm_free(void *ptr)
 
551
{
 
552
        bool my_pointer = false;
 
553
 
 
554
#ifdef RECORD_MM
 
555
        pthread_mutex_lock(&mm_mutex);
 
556
        if (mm_find_pointer(ptr) >= 0) {
 
557
                my_pointer = true;
 
558
                mm_remove_core_ptr(ptr);
 
559
        }
 
560
        pthread_mutex_unlock(&mm_mutex);
 
561
#endif
 
562
        if (my_pointer)
 
563
                mm_check_and_free(NULL, ptr, true);
 
564
        else
 
565
                free(ptr);
 
566
}
 
567
 
 
568
void cs_mm_pfree(void **ptr)
 
569
{
 
570
        if (*ptr) {
 
571
                void *p = *ptr;
 
572
 
 
573
                *ptr = NULL;
 
574
                cs_mm_free(p);
 
575
        }
 
576
}
 
577
 
 
578
size_t cs_mm_malloc_size(void *ptr)
 
579
{
 
580
        size_t size = 0;
 
581
 
 
582
#ifdef RECORD_MM
 
583
        pthread_mutex_lock(&mm_mutex);
 
584
        mm_find_core_ptr(ptr);
 
585
        pthread_mutex_unlock(&mm_mutex);
 
586
#endif
 
587
        size = mm_check_and_free(NULL, ptr, false);
 
588
        return size;
 
589
}
 
590
 
 
591
void cs_mm_print_track(const char *func, const char *file, u_int line, void *p, bool inc, u_int ref_cnt, int track_me)
 
592
{
 
593
        unsigned char   *ptr = (unsigned char *) p - MEM_DEBUG_HDR_SIZE;
 
594
        MemoryDebugPtr  debug_ptr = (MemoryDebugPtr) ptr;
 
595
        CSThread                *self = CSThread::getSelf();
 
596
        char                    buffer[300];
 
597
        int                             cnt = 0;
 
598
 
 
599
        if (!track_me && !mm_tracking_id)
 
600
                return;
 
601
 
 
602
        if (func) {
 
603
                cs_format_context(300, buffer, func, file, line);
 
604
                printf("TRACKING (%"PRIu32"): %s %2"PRIu32" %s", debug_ptr->md_id, inc ? "INC" : "DEC", ref_cnt, buffer);
 
605
        }
 
606
        else
 
607
                printf("TRACKING (%"PRIu32"): %s %2"PRIu32"", debug_ptr->md_id, inc ? "INC" : "DEC", ref_cnt);
 
608
 
 
609
        for (int i = self->callTop-1; i>=0 && cnt < 4; i--) {
 
610
                cs_format_context(300, buffer, self->callStack[i].cs_func, self->callStack[i].cs_file, self->callStack[i].cs_line);
 
611
                printf(" %s", buffer);
 
612
                cnt++;
 
613
        }
 
614
        printf("\n");
 
615
}
 
616
 
 
617
void cs_mm_track_memory(const char *func, const char *file, u_int line, void *p, bool inc, u_int ref_cnt, int track_me)
 
618
{
 
619
        unsigned char   *ptr = (unsigned char *) p - MEM_DEBUG_HDR_SIZE;
 
620
        MemoryDebugPtr  debug_ptr = (MemoryDebugPtr) ptr;
 
621
 
 
622
        if (track_me || (mm_tracking_id && debug_ptr->md_id == mm_tracking_id))
 
623
                cs_mm_print_track(func, file, line, p, inc, ref_cnt, track_me);
 
624
}
 
625
 
 
626
#endif
 
627
 
 
628
/*
 
629
 * -----------------------------------------------------------------------
 
630
 * INIT/EXIT MEMORY
 
631
 */
 
632
 
 
633
bool cs_init_memory(void)
 
634
{
 
635
#ifdef DEBUG
 
636
        pthread_mutex_init(&mm_mutex, NULL);
 
637
        mm_addresses = (MissingMemoryRec *) malloc(sizeof(MissingMemoryRec) * ADD_TOTAL_ALLOCS);
 
638
        if (!mm_addresses) {
 
639
                mm_println("MM ERROR: Insuffient memory to allocate MM table");
 
640
                pthread_mutex_destroy(&mm_mutex);
 
641
                return false;
 
642
        }
 
643
 
 
644
        memset(mm_addresses, 0, sizeof(MissingMemoryRec) * ADD_TOTAL_ALLOCS);
 
645
        mm_total_allocated = ADD_TOTAL_ALLOCS;
 
646
        mm_nr_in_use = 0L;
 
647
        mm_alloc_count = 0L;
 
648
#endif
 
649
        return true;
 
650
}
 
651
 
 
652
void cs_exit_memory(void)
 
653
{
 
654
#ifdef DEBUG
 
655
        u_int mm;
 
656
 
 
657
        if (!mm_addresses)
 
658
                return;
 
659
 
 
660
        pthread_mutex_lock(&mm_mutex);
 
661
        for (mm=0; mm<mm_nr_in_use; mm++)
 
662
                mm_throw_assertion(&mm_addresses[mm], mm_addresses[mm].ptr, "Not freed");
 
663
        free(mm_addresses);
 
664
        mm_addresses = NULL;
 
665
        mm_nr_in_use = 0L;
 
666
        mm_total_allocated = 0L;
 
667
        mm_alloc_count = 0L;
 
668
        pthread_mutex_unlock(&mm_mutex);
 
669
 
 
670
        pthread_mutex_destroy(&mm_mutex);
 
671
#endif
 
672
}
 
673