Annotation of embedaddon/libpdel/util/typed_mem.c, revision 1.1.1.1
1.1 misho 1:
2: /*
3: * Copyright (c) 2001-2002 Packet Design, LLC.
4: * All rights reserved.
5: *
6: * Subject to the following obligations and disclaimer of warranty,
7: * use and redistribution of this software, in source or object code
8: * forms, with or without modifications are expressly permitted by
9: * Packet Design; provided, however, that:
10: *
11: * (i) Any and all reproductions of the source or object code
12: * must include the copyright notice above and the following
13: * disclaimer of warranties; and
14: * (ii) No rights are granted, in any manner or form, to use
15: * Packet Design trademarks, including the mark "PACKET DESIGN"
16: * on advertising, endorsements, or otherwise except as such
17: * appears in the above copyright notice or in the software.
18: *
19: * THIS SOFTWARE IS BEING PROVIDED BY PACKET DESIGN "AS IS", AND
20: * TO THE MAXIMUM EXTENT PERMITTED BY LAW, PACKET DESIGN MAKES NO
21: * REPRESENTATIONS OR WARRANTIES, EXPRESS OR IMPLIED, REGARDING
22: * THIS SOFTWARE, INCLUDING WITHOUT LIMITATION, ANY AND ALL IMPLIED
23: * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE,
24: * OR NON-INFRINGEMENT. PACKET DESIGN DOES NOT WARRANT, GUARANTEE,
25: * OR MAKE ANY REPRESENTATIONS REGARDING THE USE OF, OR THE RESULTS
26: * OF THE USE OF THIS SOFTWARE IN TERMS OF ITS CORRECTNESS, ACCURACY,
27: * RELIABILITY OR OTHERWISE. IN NO EVENT SHALL PACKET DESIGN BE
28: * LIABLE FOR ANY DAMAGES RESULTING FROM OR ARISING OUT OF ANY USE
29: * OF THIS SOFTWARE, INCLUDING WITHOUT LIMITATION, ANY DIRECT,
30: * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, PUNITIVE, OR CONSEQUENTIAL
31: * DAMAGES, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, LOSS OF
32: * USE, DATA OR PROFITS, HOWEVER CAUSED AND UNDER ANY THEORY OF
33: * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
34: * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
35: * THE USE OF THIS SOFTWARE, EVEN IF PACKET DESIGN IS ADVISED OF
36: * THE POSSIBILITY OF SUCH DAMAGE.
37: *
38: * Author: Archie Cobbs <archie@freebsd.org>
39: */
40:
41: #include <sys/types.h>
42: #include <sys/param.h>
43:
44: #ifndef _KERNEL
45: #include <stdio.h>
46: #include <stddef.h>
47: #include <stdlib.h>
48: #include <stdarg.h>
49: #include <syslog.h>
50: #include <string.h>
51: #include <assert.h>
52: #include <errno.h>
53: #include <pthread.h>
54: #else
55: #include <sys/systm.h>
56: #include <machine/stdarg.h>
57: #include <malloc.h>
58: #include "util/kernelglue.h"
59: #endif
60:
61: #include "structs/structs.h"
62: #include "structs/type/array.h"
63: #include "structs/type/struct.h"
64: #include "structs/type/string.h"
65: #include "structs/type/int.h"
66: #include "util/gtree.h"
67: #include "util/typed_mem.h"
68:
69: /* Alignment, with a minimum of 4 bytes */
70: #if defined(__FreeBSD__)
71: #include <machine/param.h>
72: #define ALIGNMENT (_ALIGNBYTES + 1)
73: #else
74: #define ALIGNMENT 8 /* conservative guess */
75: #endif
76:
77: /* Summary information about a single type of memory */
78: struct mem_type {
79: char name[TYPED_MEM_TYPELEN];/* string for this type */
80: u_int32_t count; /* number of allocated blocks */
81: size_t total; /* total allocated bytes */
82: };
83:
84: /* Information about a single allocated block of memory */
85: struct mem_info {
86: void *mem; /* actual memory block */
87: size_t size; /* size of memory block */
88: struct mem_type *type; /* pointer to type info */
89: };
90:
91: /*
92: * Structs type for 'struct typed_mem_stats'
93: */
94: #define TYPED_MEM_STATS_MTYPE "typed_mem_stats"
95:
96: static const struct structs_type typebuf_type
97: = STRUCTS_FIXEDSTRING_TYPE(TYPED_MEM_TYPELEN);
98: static const struct structs_field typed_mem_typestats_fields[] = {
99: STRUCTS_STRUCT_FIELD(typed_mem_typestats, type, &typebuf_type),
100: STRUCTS_STRUCT_FIELD(typed_mem_typestats, allocs, &structs_type_uint),
101: STRUCTS_STRUCT_FIELD(typed_mem_typestats, bytes, &structs_type_uint),
102: STRUCTS_STRUCT_FIELD_END
103: };
104: static const struct structs_type typed_mem_typestats_type
105: = STRUCTS_STRUCT_TYPE(typed_mem_typestats, typed_mem_typestats_fields);
106: const struct structs_type typed_mem_stats_type
107: = STRUCTS_ARRAY_TYPE(&typed_mem_typestats_type,
108: TYPED_MEM_STATS_MTYPE, "type");
109:
110: /* We need to use the real functions in here */
111: #undef malloc
112: #undef calloc
113: #undef realloc
114: #undef reallocf
115: #undef free
116: #undef asprintf
117: #undef vasprintf
118:
119: /* How to print out problems */
120: #define WHINE(fmt, args...) (void)fprintf(stderr, fmt "\n" , ## args)
121:
122: /*
123: * Kernel glue
124: */
125: #ifdef _KERNEL
126:
127: #if TYPED_MEM_TRACE
128: #error TYPED_MEM_TRACE not supported in kernel mode
129: #endif
130:
131: #define malloc(x) kern_malloc(x)
132: #define realloc(x, y) kern_realloc(x, y)
133: #define free(x) kern_free(x)
134:
135: #define pthread_mutex_lock() 0
136: #define pthread_mutex_unlock() 0
137:
138: #undef WHINE
139: #define WHINE(fmt, args...) log(LOG_CRIT, fmt "\n" , ## args)
140:
141: #endif /* _KERNEL */
142:
143: /*
144: * Internal variables
145: */
146: static u_char typed_mem_started;
147: static u_char typed_mem_enabled;
148: static struct gtree *mem_tree;
149: static struct gtree *type_tree;
150: static u_int tree_node_size;
151:
152: #ifndef _KERNEL
153: static pthread_mutex_t typed_mem_mutex;
154: #endif
155:
156: /* Guard bytes. Should have an "aligned" length. */
157: static const u_char typed_mem_guard_data[] = { 0x34, 0x8e, 0x71, 0x9f };
158: static u_char typed_mem_guard[ALIGNMENT];
159:
160: /*
161: * Internal functions
162: */
163: static gtree_cmp_t type_cmp;
164: static gtree_print_t type_print;
165: static gtree_cmp_t mem_cmp;
166:
167: static struct mem_info *typed_mem_find(
168: #if TYPED_MEM_TRACE
169: const char *file, u_int line,
170: #endif
171: void *mem, const char *typename, const char *func);
172:
173: #ifndef _KERNEL
174: static gtree_print_t mem_print;
175: #else
176: #define mem_print NULL
177: #endif
178:
179: /*
180: * Enable typed memory.
181: */
182: int
183: typed_mem_enable(void)
184: {
185: pthread_mutexattr_t mattr;
186: int i;
187:
188: /* Already enabled? */
189: if (typed_mem_enabled)
190: return (0);
191:
192: /* Already started allocating memory? */
193: if (typed_mem_started) {
194: errno = EALREADY;
195: return (-1);
196: }
197:
198: /* Initialize recursive mutex */
199: if ((errno = pthread_mutexattr_init(&mattr)) != 0)
200: return (-1);
201: if ((errno = pthread_mutexattr_settype(&mattr,
202: PTHREAD_MUTEX_RECURSIVE)) != 0) {
203: pthread_mutexattr_destroy(&mattr);
204: return (-1);
205: }
206: if ((errno = pthread_mutex_init(&typed_mem_mutex, &mattr)) != 0) {
207: pthread_mutexattr_destroy(&mattr);
208: return (-1);
209: }
210: pthread_mutexattr_destroy(&mattr);
211:
212: /* Fill in guard bytes */
213: for (i = 0; i < ALIGNMENT; i++)
214: typed_mem_guard[i] = typed_mem_guard_data[i % ALIGNMENT];
215:
216: /* Done */
217: typed_mem_enabled = 1;
218: return (0);
219: }
220:
221: /*
222: * realloc(3) replacement
223: */
224: void *
225: typed_mem_realloc(
226: #if TYPED_MEM_TRACE
227: const char *file, u_int line,
228: #endif
229: const char *typename, void *mem, size_t size)
230: {
231: #if TYPED_MEM_TRACE
232: void *const omem = mem;
233: #endif
234: struct mem_info *info;
235: void *rtn = NULL;
236: int errno_save;
237: int removed;
238: int r;
239:
240: /* Check if typed memory is active */
241: typed_mem_started = 1;
242: if (!typed_mem_enabled || typename == NULL)
243: return (realloc(mem, size));
244:
245: /* Lock info */
246: r = pthread_mutex_lock(&typed_mem_mutex);
247: assert(r == 0);
248:
249: /* Initialize first */
250: if (mem_tree == NULL) {
251: if ((mem_tree = gtree_create(NULL, NULL,
252: mem_cmp, NULL, NULL, mem_print)) == NULL)
253: goto done;
254: if ((type_tree = gtree_create(NULL, NULL,
255: type_cmp, NULL, NULL, type_print)) == NULL) {
256: gtree_destroy(&mem_tree);
257: goto done;
258: }
259: tree_node_size = gtree_node_size();
260: }
261:
262: /* Find/create the memory descriptor block */
263: if (mem == NULL) {
264: struct mem_type *type;
265: struct mem_type tkey;
266:
267: /* Get memory and new descriptor block */
268: if ((info = malloc(sizeof(*info))) == NULL)
269: goto done;
270: if ((info->mem = malloc(size
271: + 2 * sizeof(typed_mem_guard))) == NULL) {
272: errno_save = errno;
273: free(info);
274: errno = errno_save;
275: goto done;
276: }
277: info->size = size;
278:
279: /* Find/create type descriptor for this memory type */
280: strncpy(tkey.name, typename, sizeof(tkey.name) - 1);
281: tkey.name[sizeof(tkey.name) - 1] = '\0';
282: if ((type = gtree_get(type_tree, &tkey)) == NULL) {
283: if ((type = malloc(sizeof(*type))) == NULL) {
284: errno_save = errno;
285: free(info->mem);
286: free(info);
287: errno = errno_save;
288: goto done;
289: }
290: strcpy(type->name, tkey.name);
291: type->count = 0;
292: type->total = 0;
293: if (gtree_put(type_tree, type) == -1) {
294: errno_save = errno;
295: free(type);
296: free(info->mem);
297: free(info);
298: errno = errno_save;
299: goto done;
300: }
301: }
302: info->type = type;
303:
304: /* Add block descriptor to mem tree */
305: if (gtree_put(mem_tree, info) == -1) {
306: errno_save = errno;
307: if (type->count == 0) { /* was a new type */
308: removed = gtree_remove(type_tree, type);
309: assert(removed);
310: free(type);
311: }
312: free(info->mem);
313: free(info);
314: errno = errno_save;
315: goto done;
316: }
317: } else {
318: void *node;
319:
320: /* Find memory descriptor */
321: #if TYPED_MEM_TRACE
322: info = typed_mem_find(file, line, mem, typename, "REALLOC");
323: #else
324: info = typed_mem_find(mem, typename, "REALLOC");
325: #endif
326:
327: /* Pre-allocate mem tree node */
328: if ((node = malloc(tree_node_size)) == NULL)
329: goto done;
330:
331: /* Get reallocated memory block */
332: if ((mem = realloc(info->mem,
333: size + 2 * sizeof(typed_mem_guard))) == NULL) {
334: errno_save = errno;
335: free(node);
336: errno = errno_save;
337: goto done;
338: }
339:
340: /* Subtract old block from type stats */
341: info->type->total -= info->size;
342: info->type->count--;
343:
344: /* Update block descriptor */
345: info->size = size;
346: if (info->mem != mem) {
347: removed = gtree_remove(mem_tree, info);
348: assert(removed);
349: info->mem = mem;
350: gtree_put_prealloc(mem_tree, info, node);
351: } else
352: free(node); /* we didn't need it */
353: }
354:
355: /* Add new block to type stats */
356: info->type->total += info->size;
357: info->type->count++;
358:
359: /* Install guard bytes */
360: memcpy(info->mem, typed_mem_guard, sizeof(typed_mem_guard));
361: memcpy((u_char *)info->mem + sizeof(typed_mem_guard) + info->size,
362: typed_mem_guard, sizeof(typed_mem_guard));
363:
364: #if TYPED_MEM_TRACE
365: /* Tracing */
366: {
367: const char *basename;
368:
369: if ((basename = strrchr(file, '/')) != NULL)
370: basename++;
371: else
372: basename = file;
373: fprintf(stderr, "%s:%u:ALLOC %p -> %p \"%s\" %u [%u]\n",
374: basename, line, omem, (u_char *)info->mem
375: + sizeof(typed_mem_guard), typename, size,
376: info->type->count);
377: }
378: #endif
379:
380: /* Return memory block */
381: rtn = (u_char *)info->mem + sizeof(typed_mem_guard);
382:
383: done:
384: /* Done */
385: r = pthread_mutex_unlock(&typed_mem_mutex);
386: assert(r == 0);
387: return (rtn);
388: }
389:
390: /*
391: * reallocf(3) replacement
392: */
393: void *
394: typed_mem_reallocf(
395: #if TYPED_MEM_TRACE
396: const char *file, u_int line,
397: #endif
398: const char *typename, void *mem, size_t size)
399: {
400: void *p;
401:
402: #if TYPED_MEM_TRACE
403: if ((p = typed_mem_realloc(file, line, typename, mem, size)) == NULL)
404: typed_mem_free(file, line, typename, mem);
405: #else
406: if ((p = typed_mem_realloc(typename, mem, size)) == NULL)
407: typed_mem_free(typename, mem);
408: #endif
409: return (p);
410: }
411:
412: /*
413: * free(3) replacement
414: *
415: * Note: it is OK if "typedname" points to memory within the region
416: * pointed to by "mem".
417: */
418: void
419: typed_mem_free(
420: #if TYPED_MEM_TRACE
421: const char *file, u_int line,
422: #endif
423: const char *typename, void *mem)
424: {
425: const int errno_save = errno;
426: struct mem_info *info;
427: int removed;
428: int r;
429:
430: /* free(NULL) does nothing */
431: if (mem == NULL)
432: return;
433:
434: /* Check if typed memory is active */
435: typed_mem_started = 1;
436: if (!typed_mem_enabled || typename == NULL) {
437: free(mem);
438: return;
439: }
440:
441: /* Lock info */
442: r = pthread_mutex_lock(&typed_mem_mutex);
443: assert(r == 0);
444:
445: /* Find memory descriptor */
446: #if TYPED_MEM_TRACE
447: info = typed_mem_find(file, line, mem, typename, "FREE");
448: #else
449: info = typed_mem_find(mem, typename, "FREE");
450: #endif
451:
452: #if TYPED_MEM_TRACE
453: /* Tracing */
454: {
455: const char *basename;
456:
457: if ((basename = strrchr(file, '/')) != NULL)
458: basename++;
459: else
460: basename = file;
461: fprintf(stderr, "%s:%u:FREE %p -> %p \"%s\" [%u]\n",
462: basename, line, mem, (void *)0,
463: typename, info->type->count);
464: }
465: #endif
466:
467: /* Subtract block from descriptor info */
468: info->type->total -= info->size;
469: if (--info->type->count == 0) {
470: assert(info->type->total == 0);
471: removed = gtree_remove(type_tree, info->type);
472: assert(removed);
473: free(info->type);
474: }
475:
476: /* Free memory and descriptor block */
477: removed = gtree_remove(mem_tree, info);
478: assert(removed);
479: free(info->mem);
480: free(info);
481:
482: /* Done */
483: r = pthread_mutex_unlock(&typed_mem_mutex);
484: assert(r == 0);
485: errno = errno_save;
486: }
487:
488: /*
489: * calloc(3) replacement
490: */
491: void *
492: typed_mem_calloc(
493: #if TYPED_MEM_TRACE
494: const char *file, u_int line,
495: #endif
496: const char *type, size_t num, size_t size)
497: {
498: void *mem;
499:
500: size *= num;
501: #if TYPED_MEM_TRACE
502: if ((mem = typed_mem_realloc(file, line, type, NULL, size)) == NULL)
503: return (NULL);
504: #else
505: if ((mem = typed_mem_realloc(type, NULL, size)) == NULL)
506: return (NULL);
507: #endif
508: memset(mem, 0, size);
509: return (mem);
510: }
511:
512: /*
513: * strdup(3) replacement
514: */
515: char *
516: typed_mem_strdup(
517: #if TYPED_MEM_TRACE
518: const char *file, u_int line,
519: #endif
520: const char *type, const char *string)
521: {
522: const int slen = strlen(string) + 1;
523: char *result;
524:
525: #if TYPED_MEM_TRACE
526: if ((result = typed_mem_realloc(file, line, type, NULL, slen)) == NULL)
527: return (NULL);
528: #else
529: if ((result = typed_mem_realloc(type, NULL, slen)) == NULL)
530: return (NULL);
531: #endif
532: memcpy(result, string, slen);
533: return (result);
534: }
535:
536: /*
537: * asprintf(3) replacement
538: */
539: int
540: typed_mem_asprintf(
541: #if TYPED_MEM_TRACE
542: const char *file, u_int line,
543: #endif
544: const char *type, char **ret, const char *fmt, ...)
545: {
546: va_list args;
547: int r;
548:
549: va_start(args, fmt);
550: #if TYPED_MEM_TRACE
551: r = typed_mem_vasprintf(file, line, type, ret, fmt, args);
552: #else
553: r = typed_mem_vasprintf(type, ret, fmt, args);
554: #endif
555: va_end(args);
556: return (r);
557: }
558:
559: /*
560: * vasprintf(3) replacement
561: */
562: int
563: typed_mem_vasprintf(
564: #if TYPED_MEM_TRACE
565: const char *file, u_int line,
566: #endif
567: const char *type, char **ret, const char *fmt, va_list args)
568: {
569: int errno_save;
570: char *s;
571: int r;
572:
573: if ((r = vasprintf(ret, fmt, args)) == -1)
574: return (-1);
575: s = *ret;
576: #if TYPED_MEM_TRACE
577: *ret = typed_mem_strdup(file, line, type, s);
578: #else
579: *ret = typed_mem_strdup(type, s);
580: #endif
581: errno_save = errno;
582: free(s);
583: if (*ret == NULL) {
584: errno = errno_save;
585: return (-1);
586: }
587: return (r);
588: }
589:
590: /*
591: * Get type for a memory block.
592: */
593: char *
594: typed_mem_type(const void *mem, char *typebuf)
595: {
596: struct mem_info *info = NULL;
597: struct mem_info ikey;
598: int r;
599:
600: /* Are we enabled? */
601: if (!typed_mem_enabled) {
602: errno = ENXIO;
603: return (NULL);
604: }
605:
606: /* Lock info */
607: r = pthread_mutex_lock(&typed_mem_mutex);
608: assert(r == 0);
609:
610: /* Find memory descriptor */
611: ikey.mem = (u_char *)mem - sizeof(typed_mem_guard);
612: if (mem_tree == NULL || (info = gtree_get(mem_tree, &ikey)) == NULL) {
613: errno = ENOENT;
614: typebuf = NULL;
615: goto done;
616: }
617:
618: /* Copy type */
619: strlcpy(typebuf, info->type->name, TYPED_MEM_TYPELEN);
620:
621: done:
622: /* Unlock info */
623: r = pthread_mutex_unlock(&typed_mem_mutex);
624: assert(r == 0);
625:
626: /* Done */
627: return (typebuf);
628: }
629:
630: /*
631: * Return typed memory usage statistics. The caller must free the
632: * array by calling "structs_free(&typed_mem_stats_type, NULL, stats)".
633: *
634: * Returns zero if successful, -1 (and sets errno) if not.
635: * If typed memory is disabled, errno = ENXIO.
636: */
637: int
638: typed_mem_usage(struct typed_mem_stats *stats)
639: {
640: struct mem_type *type;
641: int i;
642: int r;
643:
644: /* Check if enabled */
645: if (!typed_mem_enabled) {
646: errno = ENXIO;
647: return (-1);
648: }
649:
650: /* Lock info */
651: r = pthread_mutex_lock(&typed_mem_mutex);
652: assert(r == 0);
653:
654: /* Allocate array */
655: memset(stats, 0, sizeof(*stats));
656: if ((stats->elems = typed_mem_realloc(
657: #if TYPED_MEM_TRACE
658: __FILE__, __LINE__,
659: #endif
660: TYPED_MEM_STATS_MTYPE, NULL, (gtree_size(type_tree) + 1)
661: * sizeof(*stats->elems))) == NULL) {
662: r = pthread_mutex_unlock(&typed_mem_mutex);
663: assert(r == 0);
664: return (-1);
665: }
666:
667: /* Copy type stats */
668: for (i = 0, type = gtree_first(type_tree);
669: type != NULL; i++, type = gtree_next(type_tree, type)) {
670: struct typed_mem_typestats *const elem = &stats->elems[i];
671:
672: strlcpy(elem->type, type->name, sizeof(elem->type));
673: elem->allocs = type->count;
674: elem->bytes = type->total;
675: }
676: stats->length = i;
677:
678: /* Unlock info */
679: r = pthread_mutex_unlock(&typed_mem_mutex);
680: assert(r == 0);
681:
682: /* Done */
683: return (0);
684: }
685:
686: #ifndef _KERNEL
687:
688: /*
689: * Return usage statistics in a malloc'd string of the specified type.
690: */
691: void
692: typed_mem_dump(FILE *fp)
693: {
694: u_long total_blocks = 0;
695: u_long total_alloc = 0;
696: struct mem_type *type;
697: int r;
698:
699: /* Check if enabled */
700: if (!typed_mem_enabled) {
701: fprintf(fp, "Typed memory is not enabled.\n");
702: return;
703: }
704:
705: /* Print header */
706: fprintf(fp, " %-28s %10s %10s\n", "Type", "Count", "Total");
707: fprintf(fp, " %-28s %10s %10s\n", "----", "-----", "-----");
708:
709: /* Lock info */
710: r = pthread_mutex_lock(&typed_mem_mutex);
711: assert(r == 0);
712:
713: /* Print allocation types */
714: for (type = gtree_first(type_tree);
715: type != NULL; type = gtree_next(type_tree, type)) {
716: fprintf(fp, " %-28s %10u %10lu\n",
717: type->name, (int)type->count, (u_long)type->total);
718: total_blocks += type->count;
719: total_alloc += type->total;
720: }
721:
722: /* Print totals */
723: fprintf(fp, " %-28s %10s %10s\n", "", "-----", "-----");
724: fprintf(fp, " %-28s %10lu %10lu\n",
725: "Totals", total_blocks, total_alloc);
726:
727: /* Unlock info */
728: r = pthread_mutex_unlock(&typed_mem_mutex);
729: assert(r == 0);
730: }
731:
732: #endif /* !_KERNEL */
733:
734: /*
735: * Find memory block info descriptor and verify guard bytes
736: *
737: * This assumes the mutex is locked.
738: */
739: static struct mem_info *
740: typed_mem_find(
741: #if TYPED_MEM_TRACE
742: const char *file, u_int line,
743: #endif
744: void *mem, const char *typename, const char *func)
745: {
746: struct mem_info *info = NULL;
747: struct mem_info ikey;
748:
749: /* Find memory descriptor which must already exist */
750: ikey.mem = (u_char *)mem - sizeof(typed_mem_guard);
751: if (mem_tree == NULL || (info = gtree_get(mem_tree, &ikey)) == NULL) {
752: #if TYPED_MEM_TRACE
753: WHINE("%s:%u: %s() of unallocated block:"
754: " ptr=%p type=\"%s\"", file, line, func, mem, typename);
755: #else
756: WHINE("%s() of unallocated block:"
757: " ptr=%p type=\"%s\"", func, mem, typename);
758: #endif
759: assert(0);
760: }
761:
762: /* Check type is the same */
763: if (strncmp(info->type->name, typename, TYPED_MEM_TYPELEN - 1) != 0) {
764: #if TYPED_MEM_TRACE
765: WHINE("%s:%u: %s() with wrong type:"
766: " ptr=%p \"%s\" != \"%s\"", file, line,
767: func, mem, typename, info->type->name);
768: #else
769: WHINE("%s() with wrong type:"
770: " ptr=%p \"%s\" != \"%s\"",
771: func, mem, typename, info->type->name);
772: #endif
773: assert(0);
774: }
775:
776: /* Check ref count */
777: assert(info->type->count > 0);
778:
779: /* Check guard bytes */
780: if (memcmp(info->mem, typed_mem_guard, sizeof(typed_mem_guard)) != 0) {
781: #if TYPED_MEM_TRACE
782: WHINE("%s:%u: %s(): %s guard violated ptr=%p type=\"%s\"",
783: file, line, func, "head", mem, typename);
784: #else
785: WHINE("%s(): %s guard violated ptr=%p type=\"%s\"",
786: func, "head", mem, typename);
787: #endif
788: assert(0);
789: }
790: if (memcmp((u_char *)info->mem + sizeof(typed_mem_guard) + info->size,
791: typed_mem_guard, sizeof(typed_mem_guard)) != 0) {
792: #if TYPED_MEM_TRACE
793: WHINE("%s:%u: %s(): %s guard violated ptr=%p type=\"%s\"",
794: file, line, func, "tail", mem, typename);
795: #else
796: WHINE("%s(): %s guard violated ptr=%p type=\"%s\"",
797: func, "tail", mem, typename);
798: #endif
799: assert(0);
800: }
801:
802: /* Done */
803: return (info);
804: }
805:
806: /*
807: * Sort type descriptors by type string.
808: */
809: static int
810: type_cmp(struct gtree *g, const void *item1, const void *item2)
811: {
812: const struct mem_type *const type1 = item1;
813: const struct mem_type *const type2 = item2;
814:
815: return (strcmp(type1->name, type2->name));
816: }
817:
818: /*
819: * Print a type
820: */
821: static const char *
822: type_print(struct gtree *g, const void *item)
823: {
824: const struct mem_type *const type = item;
825:
826: return (type->name);
827: }
828:
829: /*
830: * Sort memory block descriptors by memory address.
831: */
832: static int
833: mem_cmp(struct gtree *g, const void *item1, const void *item2)
834: {
835: const struct mem_info *const info1 = item1;
836: const struct mem_info *const info2 = item2;
837:
838: if (info1->mem < info2->mem)
839: return (-1);
840: if (info1->mem > info2->mem)
841: return (1);
842: return (0);
843: }
844:
845: #ifndef _KERNEL
846:
847: /*
848: * Print a type
849: */
850: static const char *
851: mem_print(struct gtree *g, const void *item)
852: {
853: const struct mem_info *const info = item;
854: static char buf[32];
855:
856: snprintf(buf, sizeof(buf), "%p", info->mem);
857: return (buf);
858: }
859:
860: #endif /* !_KERNEL */
861:
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>