Return to typed_mem.c CVS log | Up to [ELWIX - Embedded LightWeight unIX -] / embedaddon / mpd / src / contrib / libpdel / util |
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 */ 1.1.1.2 ! misho 213: for (i = 0; i < (int)ALIGNMENT; i++) { 1.1 misho 214: typed_mem_guard[i] = typed_mem_guard_data[ 215: i % sizeof(typed_mem_guard_data)]; 216: } 217: 218: /* Done */ 219: typed_mem_enabled = 1; 220: return (0); 221: } 222: 223: /* 224: * realloc(3) replacement 225: */ 226: void * 227: typed_mem_realloc( 228: #if TYPED_MEM_TRACE 229: const char *file, u_int line, 230: #endif 231: const char *typename, void *mem, size_t size) 232: { 233: #if TYPED_MEM_TRACE 234: void *const omem = mem; 235: #endif 236: struct mem_info *info; 237: void *rtn = NULL; 238: int errno_save; 239: int removed; 240: int r; 241: 242: /* Check if typed memory is active */ 243: typed_mem_started = 1; 244: if (!typed_mem_enabled || typename == NULL) 245: return (realloc(mem, size)); 246: 247: /* Lock info */ 248: r = pthread_mutex_lock(&typed_mem_mutex); 249: assert(r == 0); 250: 251: /* Initialize first */ 252: if (mem_tree == NULL) { 253: if ((mem_tree = gtree_create(NULL, NULL, 254: mem_cmp, NULL, NULL, mem_print)) == NULL) 255: goto done; 256: if ((type_tree = gtree_create(NULL, NULL, 257: type_cmp, NULL, NULL, type_print)) == NULL) { 258: gtree_destroy(&mem_tree); 259: goto done; 260: } 261: tree_node_size = gtree_node_size(); 262: } 263: 264: /* Find/create the memory descriptor block */ 265: if (mem == NULL) { 266: struct mem_type *type; 267: struct mem_type tkey; 268: 269: /* Get memory and new descriptor block */ 270: if ((info = malloc(sizeof(*info))) == NULL) 271: goto done; 272: if ((info->mem = malloc(size 273: + 2 * sizeof(typed_mem_guard))) == NULL) { 274: errno_save = errno; 275: free(info); 276: errno = errno_save; 277: goto done; 278: } 279: info->size = size; 280: 281: /* Find/create type descriptor for this memory type */ 282: strncpy(tkey.name, typename, sizeof(tkey.name) - 1); 283: tkey.name[sizeof(tkey.name) - 1] = '\0'; 284: if ((type = gtree_get(type_tree, &tkey)) == NULL) { 285: if ((type = malloc(sizeof(*type))) == NULL) { 286: errno_save = errno; 287: free(info->mem); 288: free(info); 289: errno = errno_save; 290: goto done; 291: } 292: strcpy(type->name, tkey.name); 293: type->count = 0; 294: type->total = 0; 295: if (gtree_put(type_tree, type) == -1) { 296: errno_save = errno; 297: free(type); 298: free(info->mem); 299: free(info); 300: errno = errno_save; 301: goto done; 302: } 303: } 304: info->type = type; 305: 306: /* Add block descriptor to mem tree */ 307: if (gtree_put(mem_tree, info) == -1) { 308: errno_save = errno; 309: if (type->count == 0) { /* was a new type */ 310: removed = gtree_remove(type_tree, type); 311: assert(removed); 312: free(type); 313: } 314: free(info->mem); 315: free(info); 316: errno = errno_save; 317: goto done; 318: } 319: } else { 320: void *node; 321: 322: /* Find memory descriptor */ 323: #if TYPED_MEM_TRACE 324: info = typed_mem_find(file, line, mem, typename, "REALLOC"); 325: #else 326: info = typed_mem_find(mem, typename, "REALLOC"); 327: #endif 328: 329: /* Pre-allocate mem tree node */ 330: if ((node = malloc(tree_node_size)) == NULL) 331: goto done; 332: 333: /* Get reallocated memory block */ 334: if ((mem = realloc(info->mem, 335: size + 2 * sizeof(typed_mem_guard))) == NULL) { 336: errno_save = errno; 337: free(node); 338: errno = errno_save; 339: goto done; 340: } 341: 342: /* Subtract old block from type stats */ 343: info->type->total -= info->size; 344: info->type->count--; 345: 346: /* Update block descriptor */ 347: info->size = size; 348: if (info->mem != mem) { 349: removed = gtree_remove(mem_tree, info); 350: assert(removed); 351: info->mem = mem; 352: gtree_put_prealloc(mem_tree, info, node); 353: } else 354: free(node); /* we didn't need it */ 355: } 356: 357: /* Add new block to type stats */ 358: info->type->total += info->size; 359: info->type->count++; 360: 361: /* Install guard bytes */ 362: memcpy(info->mem, typed_mem_guard, sizeof(typed_mem_guard)); 363: memcpy((u_char *)info->mem + sizeof(typed_mem_guard) + info->size, 364: typed_mem_guard, sizeof(typed_mem_guard)); 365: 366: #if TYPED_MEM_TRACE 367: /* Tracing */ 368: { 369: const char *basename; 370: 371: if ((basename = strrchr(file, '/')) != NULL) 372: basename++; 373: else 374: basename = file; 375: fprintf(stderr, "%s:%u:ALLOC %p -> %p \"%s\" %u [%u]\n", 376: basename, line, omem, (u_char *)info->mem 377: + sizeof(typed_mem_guard), typename, size, 378: info->type->count); 379: } 380: #endif 381: 382: /* Return memory block */ 383: rtn = (u_char *)info->mem + sizeof(typed_mem_guard); 384: 385: done: 386: /* Done */ 387: r = pthread_mutex_unlock(&typed_mem_mutex); 388: assert(r == 0); 389: return (rtn); 390: } 391: 392: /* 393: * reallocf(3) replacement 394: */ 395: void * 396: typed_mem_reallocf( 397: #if TYPED_MEM_TRACE 398: const char *file, u_int line, 399: #endif 400: const char *typename, void *mem, size_t size) 401: { 402: void *p; 403: 404: #if TYPED_MEM_TRACE 405: if ((p = typed_mem_realloc(file, line, typename, mem, size)) == NULL) 406: typed_mem_free(file, line, typename, mem); 407: #else 408: if ((p = typed_mem_realloc(typename, mem, size)) == NULL) 409: typed_mem_free(typename, mem); 410: #endif 411: return (p); 412: } 413: 414: /* 415: * free(3) replacement 416: * 417: * Note: it is OK if "typedname" points to memory within the region 418: * pointed to by "mem". 419: */ 420: void 421: typed_mem_free( 422: #if TYPED_MEM_TRACE 423: const char *file, u_int line, 424: #endif 425: const char *typename, void *mem) 426: { 427: const int errno_save = errno; 428: struct mem_info *info; 429: int removed; 430: int r; 431: 432: /* free(NULL) does nothing */ 433: if (mem == NULL) 434: return; 435: 436: /* Check if typed memory is active */ 437: typed_mem_started = 1; 438: if (!typed_mem_enabled || typename == NULL) { 439: free(mem); 440: return; 441: } 442: 443: /* Lock info */ 444: r = pthread_mutex_lock(&typed_mem_mutex); 445: assert(r == 0); 446: 447: /* Find memory descriptor */ 448: #if TYPED_MEM_TRACE 449: info = typed_mem_find(file, line, mem, typename, "FREE"); 450: #else 451: info = typed_mem_find(mem, typename, "FREE"); 452: #endif 453: 454: #if TYPED_MEM_TRACE 455: /* Tracing */ 456: { 457: const char *basename; 458: 459: if ((basename = strrchr(file, '/')) != NULL) 460: basename++; 461: else 462: basename = file; 463: fprintf(stderr, "%s:%u:FREE %p -> %p \"%s\" [%u]\n", 464: basename, line, mem, (void *)0, 465: typename, info->type->count); 466: } 467: #endif 468: 469: /* Subtract block from descriptor info */ 470: info->type->total -= info->size; 471: if (--info->type->count == 0) { 472: assert(info->type->total == 0); 473: removed = gtree_remove(type_tree, info->type); 474: assert(removed); 475: free(info->type); 476: } 477: 478: /* Free memory and descriptor block */ 479: removed = gtree_remove(mem_tree, info); 480: assert(removed); 481: free(info->mem); 482: free(info); 483: 484: /* Done */ 485: r = pthread_mutex_unlock(&typed_mem_mutex); 486: assert(r == 0); 487: errno = errno_save; 488: } 489: 490: /* 491: * calloc(3) replacement 492: */ 493: void * 494: typed_mem_calloc( 495: #if TYPED_MEM_TRACE 496: const char *file, u_int line, 497: #endif 498: const char *type, size_t num, size_t size) 499: { 500: void *mem; 501: 502: size *= num; 503: #if TYPED_MEM_TRACE 504: if ((mem = typed_mem_realloc(file, line, type, NULL, size)) == NULL) 505: return (NULL); 506: #else 507: if ((mem = typed_mem_realloc(type, NULL, size)) == NULL) 508: return (NULL); 509: #endif 510: memset(mem, 0, size); 511: return (mem); 512: } 513: 514: /* 515: * strdup(3) replacement 516: */ 517: char * 518: typed_mem_strdup( 519: #if TYPED_MEM_TRACE 520: const char *file, u_int line, 521: #endif 522: const char *type, const char *string) 523: { 524: const int slen = strlen(string) + 1; 525: char *result; 526: 527: #if TYPED_MEM_TRACE 528: if ((result = typed_mem_realloc(file, line, type, NULL, slen)) == NULL) 529: return (NULL); 530: #else 531: if ((result = typed_mem_realloc(type, NULL, slen)) == NULL) 532: return (NULL); 533: #endif 534: memcpy(result, string, slen); 535: return (result); 536: } 537: 538: /* 539: * asprintf(3) replacement 540: */ 541: int 542: typed_mem_asprintf( 543: #if TYPED_MEM_TRACE 544: const char *file, u_int line, 545: #endif 546: const char *type, char **ret, const char *fmt, ...) 547: { 548: va_list args; 549: int r; 550: 551: va_start(args, fmt); 552: #if TYPED_MEM_TRACE 553: r = typed_mem_vasprintf(file, line, type, ret, fmt, args); 554: #else 555: r = typed_mem_vasprintf(type, ret, fmt, args); 556: #endif 557: va_end(args); 558: return (r); 559: } 560: 561: /* 562: * vasprintf(3) replacement 563: */ 564: int 565: typed_mem_vasprintf( 566: #if TYPED_MEM_TRACE 567: const char *file, u_int line, 568: #endif 569: const char *type, char **ret, const char *fmt, va_list args) 570: { 571: int errno_save; 572: char *s; 573: int r; 574: 575: if ((r = vasprintf(ret, fmt, args)) == -1) { 576: *ret = NULL; 577: return (-1); 578: } 579: if (!typed_mem_enabled) 580: return r; 581: s = *ret; 582: #if TYPED_MEM_TRACE 583: *ret = typed_mem_strdup(file, line, type, s); 584: #else 585: *ret = typed_mem_strdup(type, s); 586: #endif 587: errno_save = errno; 588: free(s); 589: if (*ret == NULL) { 590: errno = errno_save; 591: return (-1); 592: } 593: return (r); 594: } 595: 596: /* 597: * Get type for a memory block. 598: */ 599: char * 1.1.1.2 ! misho 600: typed_mem_type(void *mem, char *typebuf) 1.1 misho 601: { 602: struct mem_info *info = NULL; 603: struct mem_info ikey; 604: int r; 605: 606: /* Are we enabled? */ 607: if (!typed_mem_enabled) { 608: errno = ENXIO; 609: return (NULL); 610: } 611: 612: /* Lock info */ 613: r = pthread_mutex_lock(&typed_mem_mutex); 614: assert(r == 0); 615: 616: /* Find memory descriptor */ 617: ikey.mem = (u_char *)mem - sizeof(typed_mem_guard); 618: if (mem_tree == NULL || (info = gtree_get(mem_tree, &ikey)) == NULL) { 619: errno = ENOENT; 620: typebuf = NULL; 621: goto done; 622: } 623: 624: /* Copy type */ 625: strlcpy(typebuf, info->type->name, TYPED_MEM_TYPELEN); 626: 627: done: 628: /* Unlock info */ 629: r = pthread_mutex_unlock(&typed_mem_mutex); 630: assert(r == 0); 631: 632: /* Done */ 633: return (typebuf); 634: } 635: 636: /* 637: * Return typed memory usage statistics. The caller must free the 638: * array by calling "structs_free(&typed_mem_stats_type, NULL, stats)". 639: * 640: * Returns zero if successful, -1 (and sets errno) if not. 641: * If typed memory is disabled, errno = ENXIO. 642: */ 643: int 644: typed_mem_usage(struct typed_mem_stats *stats) 645: { 646: struct mem_type *type; 647: int i; 648: int r; 649: 650: /* Check if enabled */ 651: if (!typed_mem_enabled) { 652: errno = ENXIO; 653: return (-1); 654: } 655: 656: /* Lock info */ 657: r = pthread_mutex_lock(&typed_mem_mutex); 658: assert(r == 0); 659: 660: /* Allocate array */ 661: memset(stats, 0, sizeof(*stats)); 662: if ((stats->elems = typed_mem_realloc( 663: #if TYPED_MEM_TRACE 664: __FILE__, __LINE__, 665: #endif 666: TYPED_MEM_STATS_MTYPE, NULL, (gtree_size(type_tree) + 1) 667: * sizeof(*stats->elems))) == NULL) { 668: r = pthread_mutex_unlock(&typed_mem_mutex); 669: assert(r == 0); 670: return (-1); 671: } 672: 673: /* Copy type stats */ 674: for (i = 0, type = gtree_first(type_tree); 675: type != NULL; i++, type = gtree_next(type_tree, type)) { 676: struct typed_mem_typestats *const elem = &stats->elems[i]; 677: 678: strlcpy(elem->type, type->name, sizeof(elem->type)); 679: elem->allocs = type->count; 680: elem->bytes = type->total; 681: } 682: stats->length = i; 683: 684: /* Unlock info */ 685: r = pthread_mutex_unlock(&typed_mem_mutex); 686: assert(r == 0); 687: 688: /* Done */ 689: return (0); 690: } 691: 692: #ifndef _KERNEL 693: 694: /* 695: * Return usage statistics in a malloc'd string of the specified type. 696: */ 697: void 698: typed_mem_dump(FILE *fp) 699: { 700: u_long total_blocks = 0; 701: u_long total_alloc = 0; 702: struct mem_type *type; 703: int r; 704: 705: /* Check if enabled */ 706: if (!typed_mem_enabled) { 707: fprintf(fp, "Typed memory is not enabled.\n"); 708: return; 709: } 710: 711: /* Print header */ 712: fprintf(fp, " %-28s %10s %10s\n", "Type", "Count", "Total"); 713: fprintf(fp, " %-28s %10s %10s\n", "----", "-----", "-----"); 714: 715: /* Lock info */ 716: r = pthread_mutex_lock(&typed_mem_mutex); 717: assert(r == 0); 718: 719: /* Print allocation types */ 720: for (type = gtree_first(type_tree); 721: type != NULL; type = gtree_next(type_tree, type)) { 722: fprintf(fp, " %-28s %10u %10lu\n", 723: type->name, (int)type->count, (u_long)type->total); 724: total_blocks += type->count; 725: total_alloc += type->total; 726: } 727: 728: /* Print totals */ 729: fprintf(fp, " %-28s %10s %10s\n", "", "-----", "-----"); 730: fprintf(fp, " %-28s %10lu %10lu\n", 731: "Totals", total_blocks, total_alloc); 732: 733: /* Unlock info */ 734: r = pthread_mutex_unlock(&typed_mem_mutex); 735: assert(r == 0); 736: } 737: 738: #endif /* !_KERNEL */ 739: 740: /* 741: * Find memory block info descriptor and verify guard bytes 742: * 743: * This assumes the mutex is locked. 744: */ 745: static struct mem_info * 746: typed_mem_find( 747: #if TYPED_MEM_TRACE 748: const char *file, u_int line, 749: #endif 750: void *mem, const char *typename, const char *func) 751: { 752: struct mem_info *info = NULL; 753: struct mem_info ikey; 754: 755: /* Find memory descriptor which must already exist */ 756: ikey.mem = (u_char *)mem - sizeof(typed_mem_guard); 757: if (mem_tree == NULL || (info = gtree_get(mem_tree, &ikey)) == NULL) { 758: #if TYPED_MEM_TRACE 759: WHINE("%s:%u: %s() of unallocated block:" 760: " ptr=%p type=\"%s\"", file, line, func, mem, typename); 761: #else 762: WHINE("%s() of unallocated block:" 763: " ptr=%p type=\"%s\"", func, mem, typename); 764: #endif 765: assert(0); 766: } 767: 768: /* Check type is the same */ 769: if (strncmp(info->type->name, typename, TYPED_MEM_TYPELEN - 1) != 0) { 770: #if TYPED_MEM_TRACE 771: WHINE("%s:%u: %s() with wrong type:" 772: " ptr=%p \"%s\" != \"%s\"", file, line, 773: func, mem, typename, info->type->name); 774: #else 775: WHINE("%s() with wrong type:" 776: " ptr=%p \"%s\" != \"%s\"", 777: func, mem, typename, info->type->name); 778: #endif 779: assert(0); 780: } 781: 782: /* Check ref count */ 783: assert(info->type->count > 0); 784: 785: /* Check guard bytes */ 786: if (memcmp(info->mem, typed_mem_guard, sizeof(typed_mem_guard)) != 0) { 787: #if TYPED_MEM_TRACE 788: WHINE("%s:%u: %s(): %s guard violated ptr=%p type=\"%s\"", 789: file, line, func, "head", mem, typename); 790: #else 791: WHINE("%s(): %s guard violated ptr=%p type=\"%s\"", 792: func, "head", mem, typename); 793: #endif 794: assert(0); 795: } 796: if (memcmp((u_char *)info->mem + sizeof(typed_mem_guard) + info->size, 797: typed_mem_guard, sizeof(typed_mem_guard)) != 0) { 798: #if TYPED_MEM_TRACE 799: WHINE("%s:%u: %s(): %s guard violated ptr=%p type=\"%s\"", 800: file, line, func, "tail", mem, typename); 801: #else 802: WHINE("%s(): %s guard violated ptr=%p type=\"%s\"", 803: func, "tail", mem, typename); 804: #endif 805: assert(0); 806: } 807: 808: /* Done */ 809: return (info); 810: } 811: 812: /* 813: * Sort type descriptors by type string. 814: */ 815: static int 816: type_cmp(struct gtree *g, const void *item1, const void *item2) 817: { 818: const struct mem_type *const type1 = item1; 819: const struct mem_type *const type2 = item2; 820: 1.1.1.2 ! misho 821: (void)g; 1.1 misho 822: return (strcmp(type1->name, type2->name)); 823: } 824: 825: /* 826: * Print a type 827: */ 828: static const char * 829: type_print(struct gtree *g, const void *item) 830: { 831: const struct mem_type *const type = item; 832: 1.1.1.2 ! misho 833: (void)g; 1.1 misho 834: return (type->name); 835: } 836: 837: /* 838: * Sort memory block descriptors by memory address. 839: */ 840: static int 841: mem_cmp(struct gtree *g, const void *item1, const void *item2) 842: { 843: const struct mem_info *const info1 = item1; 844: const struct mem_info *const info2 = item2; 845: 1.1.1.2 ! misho 846: (void)g; 1.1 misho 847: if (info1->mem < info2->mem) 848: return (-1); 849: if (info1->mem > info2->mem) 850: return (1); 851: return (0); 852: } 853: 854: #ifndef _KERNEL 855: 856: /* 857: * Print a type 858: */ 859: static const char * 860: mem_print(struct gtree *g, const void *item) 861: { 862: const struct mem_info *const info = item; 863: static char buf[32]; 864: 1.1.1.2 ! misho 865: (void)g; 1.1 misho 866: snprintf(buf, sizeof(buf), "%p", info->mem); 867: return (buf); 868: } 869: 870: #endif /* !_KERNEL */ 871: