~drizzle-trunk/drizzle/development

1548.2.1 by Barry.Leslie at PrimeBase
Added the PBMS daemon plugin.
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 "CSConfig.h"
31
32
#include <assert.h>
33
#include <string.h>
34
#include <stddef.h>
35
#include <stdlib.h>
1548.2.3 by Barry.Leslie at PrimeBase
Added drizzle event observer class to PBMS as well as a lot of mostly minor changes for drizzle compatability.
36
#include <inttypes.h>
1548.2.1 by Barry.Leslie at PrimeBase
Added the PBMS daemon plugin.
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;
1548.2.2 by Barry.Leslie at PrimeBase
A lot of minor changes to clean up the code and to get it to build with Drizzle.
101
	uint32_t			id;
1548.2.1 by Barry.Leslie at PrimeBase
Added the PBMS daemon plugin.
102
	const char		*func_name;
103
	const char		*file_name;
1548.2.2 by Barry.Leslie at PrimeBase
A lot of minor changes to clean up the code and to get it to build with Drizzle.
104
	uint32_t			line_nr;
1548.2.1 by Barry.Leslie at PrimeBase
Added the PBMS daemon plugin.
105
} MissingMemoryRec, *MissingMemoryPtr;
106
107
static MissingMemoryRec	*mm_addresses = NULL;
1548.2.2 by Barry.Leslie at PrimeBase
A lot of minor changes to clean up the code and to get it to build with Drizzle.
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;
1548.2.1 by Barry.Leslie at PrimeBase
Added the PBMS daemon plugin.
111
static pthread_mutex_t	mm_mutex;
112
113
/* Set this variable to the ID of the memory you want
114
 * to track.
115
 */
1548.2.2 by Barry.Leslie at PrimeBase
A lot of minor changes to clean up the code and to get it to build with Drizzle.
116
static uint32_t			mm_tracking_id = 0;
1548.2.1 by Barry.Leslie at PrimeBase
Added the PBMS daemon plugin.
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) {
1548.2.2 by Barry.Leslie at PrimeBase
A lot of minor changes to clean up the code and to get it to build with Drizzle.
212
		snprintf(str, 200, "MM ERROR: %8p (#%"PRId32") %s:%"PRId32" %s",
1548.2.1 by Barry.Leslie at PrimeBase
Added the PBMS daemon plugin.
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
1548.2.2 by Barry.Leslie at PrimeBase
A lot of minor changes to clean up the code and to get it to build with Drizzle.
220
		snprintf(str, 200, "MM ERROR: %8p %s", p, message);
1548.2.1 by Barry.Leslie at PrimeBase
Added the PBMS daemon plugin.
221
	mm_println(str);
222
}
223
1548.2.2 by Barry.Leslie at PrimeBase
A lot of minor changes to clean up the code and to get it to build with Drizzle.
224
static uint32_t mm_add_core_ptr(void *ptr, const char *func, const char *file, int line)
1548.2.1 by Barry.Leslie at PrimeBase
Added the PBMS daemon plugin.
225
{
226
	long	mm;
1548.2.2 by Barry.Leslie at PrimeBase
A lot of minor changes to clean up the code and to get it to build with Drizzle.
227
	uint32_t	id;
1548.2.1 by Barry.Leslie at PrimeBase
Added the PBMS daemon plugin.
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 {
1548.2.2 by Barry.Leslie at PrimeBase
A lot of minor changes to clean up the code and to get it to build with Drizzle.
303
	uint32_t		check;
304
	uint32_t		md_id;				/* The memory ID! */
305
	uint32_t		size;
1548.2.1 by Barry.Leslie at PrimeBase
Added the PBMS daemon plugin.
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
{
1548.2.2 by Barry.Leslie at PrimeBase
A lot of minor changes to clean up the code and to get it to build with Drizzle.
351
	uint32_t mm;
1548.2.1 by Barry.Leslie at PrimeBase
Added the PBMS daemon plugin.
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;
1548.2.2 by Barry.Leslie at PrimeBase
A lot of minor changes to clean up the code and to get it to build with Drizzle.
446
	((MemoryDebugPtr) p)->size = (uint32_t) size;
1548.2.1 by Barry.Leslie at PrimeBase
Added the PBMS daemon plugin.
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;
1548.2.2 by Barry.Leslie at PrimeBase
A lot of minor changes to clean up the code and to get it to build with Drizzle.
468
	((MemoryDebugPtr) p)->size  = (uint32_t) size;
1548.2.1 by Barry.Leslie at PrimeBase
Added the PBMS daemon plugin.
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;
1548.2.2 by Barry.Leslie at PrimeBase
A lot of minor changes to clean up the code and to get it to build with Drizzle.
543
	((MemoryDebugPtr) pnew)->size = (uint32_t) newsize;
1548.2.1 by Barry.Leslie at PrimeBase
Added the PBMS daemon plugin.
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
1548.2.2 by Barry.Leslie at PrimeBase
A lot of minor changes to clean up the code and to get it to build with Drizzle.
591
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)
1548.2.1 by Barry.Leslie at PrimeBase
Added the PBMS daemon plugin.
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
1548.2.32 by Barry.Leslie at PrimeBase
Bug fix (sort of) for drop database when system tables are still open. The
602
1548.2.1 by Barry.Leslie at PrimeBase
Added the PBMS daemon plugin.
603
	if (func) {
604
		cs_format_context(300, buffer, func, file, line);
1548.2.32 by Barry.Leslie at PrimeBase
Bug fix (sort of) for drop database when system tables are still open. The
605
		fprintf(stderr, "TRACKING (%"PRIu32"): %s %2"PRIu32" %s", debug_ptr->md_id, inc ? "INC" : "DEC", ref_cnt, buffer);
1548.2.1 by Barry.Leslie at PrimeBase
Added the PBMS daemon plugin.
606
	}
607
	else
1548.2.32 by Barry.Leslie at PrimeBase
Bug fix (sort of) for drop database when system tables are still open. The
608
		fprintf(stderr, "TRACKING (%"PRIu32"): %s %2"PRIu32"", debug_ptr->md_id, inc ? "INC" : "DEC", ref_cnt);
1548.2.1 by Barry.Leslie at PrimeBase
Added the PBMS daemon plugin.
609
610
	for (int i = self->callTop-1; i>=0 && cnt < 4; i--) {
611
		cs_format_context(300, buffer, self->callStack[i].cs_func, self->callStack[i].cs_file, self->callStack[i].cs_line);
1548.2.32 by Barry.Leslie at PrimeBase
Bug fix (sort of) for drop database when system tables are still open. The
612
		fprintf(stderr," %s", buffer);
1548.2.1 by Barry.Leslie at PrimeBase
Added the PBMS daemon plugin.
613
		cnt++;
614
	}
1548.2.32 by Barry.Leslie at PrimeBase
Bug fix (sort of) for drop database when system tables are still open. The
615
	fprintf(stderr,"\n");
1548.2.1 by Barry.Leslie at PrimeBase
Added the PBMS daemon plugin.
616
}
617
1548.2.2 by Barry.Leslie at PrimeBase
A lot of minor changes to clean up the code and to get it to build with Drizzle.
618
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)
1548.2.1 by Barry.Leslie at PrimeBase
Added the PBMS daemon plugin.
619
{
620
	unsigned char	*ptr = (unsigned char *) p - MEM_DEBUG_HDR_SIZE;
621
	MemoryDebugPtr	debug_ptr = (MemoryDebugPtr) ptr;
622
623
	if (track_me || (mm_tracking_id && debug_ptr->md_id == mm_tracking_id))
624
		cs_mm_print_track(func, file, line, p, inc, ref_cnt, track_me);
625
}
626
627
#endif
628
629
/*
630
 * -----------------------------------------------------------------------
631
 * INIT/EXIT MEMORY
632
 */
633
634
bool cs_init_memory(void)
635
{
636
#ifdef DEBUG
637
	pthread_mutex_init(&mm_mutex, NULL);
638
	mm_addresses = (MissingMemoryRec *) malloc(sizeof(MissingMemoryRec) * ADD_TOTAL_ALLOCS);
639
	if (!mm_addresses) {
640
		mm_println("MM ERROR: Insuffient memory to allocate MM table");
641
		pthread_mutex_destroy(&mm_mutex);
642
		return false;
643
	}
644
645
	memset(mm_addresses, 0, sizeof(MissingMemoryRec) * ADD_TOTAL_ALLOCS);
646
	mm_total_allocated = ADD_TOTAL_ALLOCS;
647
	mm_nr_in_use = 0L;
648
	mm_alloc_count = 0L;
649
#endif
650
	return true;
651
}
652
653
void cs_exit_memory(void)
654
{
655
#ifdef DEBUG
1548.2.2 by Barry.Leslie at PrimeBase
A lot of minor changes to clean up the code and to get it to build with Drizzle.
656
	uint32_t mm;
1548.2.1 by Barry.Leslie at PrimeBase
Added the PBMS daemon plugin.
657
658
	if (!mm_addresses)
659
		return;
660
661
	pthread_mutex_lock(&mm_mutex);
662
	for (mm=0; mm<mm_nr_in_use; mm++)
663
		mm_throw_assertion(&mm_addresses[mm], mm_addresses[mm].ptr, "Not freed");
664
	free(mm_addresses);
665
	mm_addresses = NULL;
666
	mm_nr_in_use = 0L;
667
	mm_total_allocated = 0L;
668
	mm_alloc_count = 0L;
669
	pthread_mutex_unlock(&mm_mutex);
670
671
	pthread_mutex_destroy(&mm_mutex);
672
#endif
673
}
674