~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
1802.10.2 by Monty Taylor
Update all of the copyright headers to include the correct address.
17
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1548.2.1 by Barry.Leslie at PrimeBase
Added the PBMS daemon plugin.
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
602
	if (func) {
603
		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
604
		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.
605
	}
606
	else
1548.2.32 by Barry.Leslie at PrimeBase
Bug fix (sort of) for drop database when system tables are still open. The
607
		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.
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);
1548.2.32 by Barry.Leslie at PrimeBase
Bug fix (sort of) for drop database when system tables are still open. The
611
		fprintf(stderr," %s", buffer);
1548.2.1 by Barry.Leslie at PrimeBase
Added the PBMS daemon plugin.
612
		cnt++;
613
	}
1548.2.32 by Barry.Leslie at PrimeBase
Bug fix (sort of) for drop database when system tables are still open. The
614
	fprintf(stderr,"\n");
1548.2.1 by Barry.Leslie at PrimeBase
Added the PBMS daemon plugin.
615
}
616
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.
617
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.
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
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.
655
	uint32_t mm;
1548.2.1 by Barry.Leslie at PrimeBase
Added the PBMS daemon plugin.
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
1841.1.3 by Barry.Leslie at PrimeBase
Merged changes from lp:pbms. These changes should remove any danger
674
#ifdef DEBUG
675
uint32_t cs_mm_get_check_point()
676
{
677
	return mm_alloc_count;
678
}
679
680
// Reports any memory allocated after the check_point
681
// but has not been freed.
682
void cs_mm_assert_check_point(uint32_t check_point)
683
{
684
	uint32_t mm;
685
686
	if (!mm_addresses)
687
		return;
688
689
	pthread_mutex_lock(&mm_mutex);
690
	for (mm=0; mm<mm_nr_in_use; mm++) {
691
		if (mm_addresses[mm].id >= check_point)
692
			mm_throw_assertion(&mm_addresses[mm], mm_addresses[mm].ptr, "Not freed");
693
	}
694
695
	pthread_mutex_unlock(&mm_mutex);
696
697
}
698
#endif