Annotation of embedaddon/dhcp/omapip/alloc.c, revision 1.1
1.1 ! misho 1: /* alloc.c
! 2:
! 3: Functions supporting memory allocation for the object management
! 4: protocol... */
! 5:
! 6: /*
! 7: * Copyright (c) 2009-2010 by Internet Systems Consortium, Inc. ("ISC")
! 8: * Copyright (c) 2004-2007 by Internet Systems Consortium, Inc. ("ISC")
! 9: * Copyright (c) 1999-2003 by Internet Software Consortium
! 10: *
! 11: * Permission to use, copy, modify, and distribute this software for any
! 12: * purpose with or without fee is hereby granted, provided that the above
! 13: * copyright notice and this permission notice appear in all copies.
! 14: *
! 15: * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
! 16: * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
! 17: * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR
! 18: * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
! 19: * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
! 20: * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
! 21: * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
! 22: *
! 23: * Internet Systems Consortium, Inc.
! 24: * 950 Charter Street
! 25: * Redwood City, CA 94063
! 26: * <info@isc.org>
! 27: * https://www.isc.org/
! 28: *
! 29: * This software has been written for Internet Systems Consortium
! 30: * by Ted Lemon in cooperation with Vixie Enterprises and Nominum, Inc.
! 31: * To learn more about Internet Systems Consortium, see
! 32: * ``https://www.isc.org/''. To learn more about Vixie Enterprises,
! 33: * see ``http://www.vix.com''. To learn more about Nominum, Inc., see
! 34: * ``http://www.nominum.com''.
! 35: */
! 36:
! 37: #include "dhcpd.h"
! 38:
! 39: #include <omapip/omapip_p.h>
! 40:
! 41: #if defined (DEBUG_MEMORY_LEAKAGE) || defined (DEBUG_MALLOC_POOL) || \
! 42: defined (DEBUG_MEMORY_LEAKAGE_ON_EXIT)
! 43: struct dmalloc_preamble *dmalloc_list;
! 44: unsigned long dmalloc_outstanding;
! 45: unsigned long dmalloc_longterm;
! 46: unsigned long dmalloc_generation;
! 47: unsigned long dmalloc_cutoff_generation;
! 48: #endif
! 49:
! 50: #if defined (DEBUG_RC_HISTORY)
! 51: struct rc_history_entry rc_history [RC_HISTORY_MAX];
! 52: int rc_history_index;
! 53: int rc_history_count;
! 54: #endif
! 55:
! 56: #if defined (DEBUG_RC_HISTORY)
! 57: static void print_rc_hist_entry (int);
! 58: #endif
! 59:
! 60: void *
! 61: dmalloc(unsigned size, const char *file, int line) {
! 62: unsigned char *foo;
! 63: unsigned len;
! 64: void **bar;
! 65: #if defined (DEBUG_MEMORY_LEAKAGE) || defined (DEBUG_MALLOC_POOL) || \
! 66: defined (DEBUG_MEMORY_LEAKAGE_ON_EXIT)
! 67: int i;
! 68: struct dmalloc_preamble *dp;
! 69: #endif
! 70:
! 71: len = size + DMDSIZE;
! 72: if (len < size)
! 73: return NULL;
! 74:
! 75: foo = malloc(len);
! 76:
! 77: if (!foo)
! 78: return NULL;
! 79: bar = (void *)(foo + DMDOFFSET);
! 80: memset (bar, 0, size);
! 81:
! 82: #if defined (DEBUG_MEMORY_LEAKAGE) || defined (DEBUG_MALLOC_POOL) || \
! 83: defined (DEBUG_MEMORY_LEAKAGE_ON_EXIT)
! 84: dp = (struct dmalloc_preamble *)foo;
! 85: dp -> prev = dmalloc_list;
! 86: if (dmalloc_list)
! 87: dmalloc_list -> next = dp;
! 88: dmalloc_list = dp;
! 89: dp -> next = (struct dmalloc_preamble *)0;
! 90: dp -> size = size;
! 91: dp -> file = file;
! 92: dp -> line = line;
! 93: dp -> generation = dmalloc_generation++;
! 94: dmalloc_outstanding += size;
! 95: for (i = 0; i < DMLFSIZE; i++)
! 96: dp -> low_fence [i] =
! 97: (((unsigned long)
! 98: (&dp -> low_fence [i])) % 143) + 113;
! 99: for (i = DMDOFFSET; i < DMDSIZE; i++)
! 100: foo [i + size] =
! 101: (((unsigned long)
! 102: (&foo [i + size])) % 143) + 113;
! 103: #if defined (DEBUG_MALLOC_POOL_EXHAUSTIVELY)
! 104: /* Check _every_ entry in the pool! Very expensive. */
! 105: for (dp = dmalloc_list; dp; dp = dp -> prev) {
! 106: for (i = 0; i < DMLFSIZE; i++) {
! 107: if (dp -> low_fence [i] !=
! 108: (((unsigned long)
! 109: (&dp -> low_fence [i])) % 143) + 113)
! 110: {
! 111: log_error ("malloc fence modified: %s(%d)",
! 112: dp -> file, dp -> line);
! 113: abort ();
! 114: }
! 115: }
! 116: foo = (unsigned char *)dp;
! 117: for (i = DMDOFFSET; i < DMDSIZE; i++) {
! 118: if (foo [i + dp -> size] !=
! 119: (((unsigned long)
! 120: (&foo [i + dp -> size])) % 143) + 113) {
! 121: log_error ("malloc fence modified: %s(%d)",
! 122: dp -> file, dp -> line);
! 123: abort ();
! 124: }
! 125: }
! 126: }
! 127: #endif
! 128: #endif
! 129: #ifdef DEBUG_REFCNT_DMALLOC_FREE
! 130: rc_register (file, line, 0, foo + DMDOFFSET, 1, 0, RC_MALLOC);
! 131: #endif
! 132: return bar;
! 133: }
! 134:
! 135: void
! 136: dfree(void *ptr, const char *file, int line) {
! 137: if (!ptr) {
! 138: log_error ("dfree %s(%d): free on null pointer.", file, line);
! 139: return;
! 140: }
! 141: #if defined (DEBUG_MEMORY_LEAKAGE) || defined (DEBUG_MALLOC_POOL) || \
! 142: defined (DEBUG_MEMORY_LEAKAGE_ON_EXIT)
! 143: {
! 144: unsigned char *bar = ptr;
! 145: struct dmalloc_preamble *dp, *cur;
! 146: int i;
! 147: bar -= DMDOFFSET;
! 148: cur = (struct dmalloc_preamble *)bar;
! 149: for (dp = dmalloc_list; dp; dp = dp -> prev)
! 150: if (dp == cur)
! 151: break;
! 152: if (!dp) {
! 153: log_error ("%s(%d): freeing unknown memory: %lx",
! 154: file, line, (unsigned long)cur);
! 155: abort ();
! 156: }
! 157: if (dp -> prev)
! 158: dp -> prev -> next = dp -> next;
! 159: if (dp -> next)
! 160: dp -> next -> prev = dp -> prev;
! 161: if (dp == dmalloc_list)
! 162: dmalloc_list = dp -> prev;
! 163: if (dp -> generation >= dmalloc_cutoff_generation)
! 164: dmalloc_outstanding -= dp -> size;
! 165: else
! 166: dmalloc_longterm -= dp -> size;
! 167:
! 168: for (i = 0; i < DMLFSIZE; i++) {
! 169: if (dp -> low_fence [i] !=
! 170: (((unsigned long)
! 171: (&dp -> low_fence [i])) % 143) + 113)
! 172: {
! 173: log_error ("malloc fence modified: %s(%d)",
! 174: dp -> file, dp -> line);
! 175: abort ();
! 176: }
! 177: }
! 178: for (i = DMDOFFSET; i < DMDSIZE; i++) {
! 179: if (bar [i + dp -> size] !=
! 180: (((unsigned long)
! 181: (&bar [i + dp -> size])) % 143) + 113) {
! 182: log_error ("malloc fence modified: %s(%d)",
! 183: dp -> file, dp -> line);
! 184: abort ();
! 185: }
! 186: }
! 187: ptr = bar;
! 188: }
! 189: #endif
! 190: #ifdef DEBUG_REFCNT_DMALLOC_FREE
! 191: rc_register (file, line,
! 192: 0, (unsigned char *)ptr + DMDOFFSET, 0, 1, RC_MALLOC);
! 193: #endif
! 194: free (ptr);
! 195: }
! 196:
! 197: #if defined (DEBUG_MEMORY_LEAKAGE) || defined (DEBUG_MALLOC_POOL) || \
! 198: defined (DEBUG_MEMORY_LEAKAGE_ON_EXIT)
! 199: /* For allocation functions that keep their own free lists, we want to
! 200: account for the reuse of the memory. */
! 201:
! 202: void
! 203: dmalloc_reuse(void *foo, const char *file, int line, int justref) {
! 204: struct dmalloc_preamble *dp;
! 205:
! 206: /* Get the pointer to the dmalloc header. */
! 207: dp = foo;
! 208: dp--;
! 209:
! 210: /* If we just allocated this and are now referencing it, this
! 211: function would almost be a no-op, except that it would
! 212: increment the generation count needlessly. So just return
! 213: in this case. */
! 214: if (dp -> generation == dmalloc_generation)
! 215: return;
! 216:
! 217: /* If this is longterm data, and we just made reference to it,
! 218: don't put it on the short-term list or change its name -
! 219: we don't need to know about this. */
! 220: if (dp -> generation < dmalloc_cutoff_generation && justref)
! 221: return;
! 222:
! 223: /* Take it out of the place in the allocated list where it was. */
! 224: if (dp -> prev)
! 225: dp -> prev -> next = dp -> next;
! 226: if (dp -> next)
! 227: dp -> next -> prev = dp -> prev;
! 228: if (dp == dmalloc_list)
! 229: dmalloc_list = dp -> prev;
! 230:
! 231: /* Account for its removal. */
! 232: if (dp -> generation >= dmalloc_cutoff_generation)
! 233: dmalloc_outstanding -= dp -> size;
! 234: else
! 235: dmalloc_longterm -= dp -> size;
! 236:
! 237: /* Now put it at the head of the list. */
! 238: dp -> prev = dmalloc_list;
! 239: if (dmalloc_list)
! 240: dmalloc_list -> next = dp;
! 241: dmalloc_list = dp;
! 242: dp -> next = (struct dmalloc_preamble *)0;
! 243:
! 244: /* Change the reference location information. */
! 245: dp -> file = file;
! 246: dp -> line = line;
! 247:
! 248: /* Increment the generation. */
! 249: dp -> generation = dmalloc_generation++;
! 250:
! 251: /* Account for it. */
! 252: dmalloc_outstanding += dp -> size;
! 253: }
! 254:
! 255: void dmalloc_dump_outstanding ()
! 256: {
! 257: static unsigned long dmalloc_cutoff_point;
! 258: struct dmalloc_preamble *dp;
! 259: #if defined(DEBUG_MALLOC_POOL)
! 260: unsigned char *foo;
! 261: int i;
! 262: #endif
! 263:
! 264: if (!dmalloc_cutoff_point)
! 265: dmalloc_cutoff_point = dmalloc_cutoff_generation;
! 266: for (dp = dmalloc_list; dp; dp = dp -> prev) {
! 267: if (dp -> generation <= dmalloc_cutoff_point)
! 268: break;
! 269: #if defined (DEBUG_MALLOC_POOL)
! 270: for (i = 0; i < DMLFSIZE; i++) {
! 271: if (dp -> low_fence [i] !=
! 272: (((unsigned long)
! 273: (&dp -> low_fence [i])) % 143) + 113)
! 274: {
! 275: log_error ("malloc fence modified: %s(%d)",
! 276: dp -> file, dp -> line);
! 277: abort ();
! 278: }
! 279: }
! 280: foo = (unsigned char *)dp;
! 281: for (i = DMDOFFSET; i < DMDSIZE; i++) {
! 282: if (foo [i + dp -> size] !=
! 283: (((unsigned long)
! 284: (&foo [i + dp -> size])) % 143) + 113) {
! 285: log_error ("malloc fence modified: %s(%d)",
! 286: dp -> file, dp -> line);
! 287: abort ();
! 288: }
! 289: }
! 290: #endif
! 291: #if defined (DEBUG_MEMORY_LEAKAGE) || \
! 292: defined (DEBUG_MEMORY_LEAKAGE_ON_EXIT)
! 293: /* Don't count data that's actually on a free list
! 294: somewhere. */
! 295: if (dp -> file) {
! 296: #if defined (DEBUG_RC_HISTORY)
! 297: int i, count, inhistory = 0, noted = 0;
! 298:
! 299: /* If we have the info, see if this is actually
! 300: new garbage. */
! 301: if (rc_history_count < RC_HISTORY_MAX) {
! 302: count = rc_history_count;
! 303: } else
! 304: count = RC_HISTORY_MAX;
! 305: i = rc_history_index - 1;
! 306: if (i < 0)
! 307: i += RC_HISTORY_MAX;
! 308:
! 309: do {
! 310: if (rc_history [i].addr == dp + 1) {
! 311: inhistory = 1;
! 312: if (!noted) {
! 313: log_info (" %s(%d): %ld", dp -> file,
! 314: dp -> line, dp -> size);
! 315: noted = 1;
! 316: }
! 317: print_rc_hist_entry (i);
! 318: if (!rc_history [i].refcnt)
! 319: break;
! 320: }
! 321: if (--i < 0)
! 322: i = RC_HISTORY_MAX - 1;
! 323: } while (count--);
! 324: if (!inhistory)
! 325: #endif
! 326: log_info (" %s(%d): %ld",
! 327: dp -> file, dp -> line, dp -> size);
! 328: }
! 329: #endif
! 330: }
! 331: if (dmalloc_list)
! 332: dmalloc_cutoff_point = dmalloc_list -> generation;
! 333: }
! 334: #endif /* DEBUG_MEMORY_LEAKAGE || DEBUG_MALLOC_POOL */
! 335:
! 336: #if defined (DEBUG_RC_HISTORY)
! 337: static void print_rc_hist_entry (int i)
! 338: {
! 339: log_info (" referenced by %s(%d)[%lx]: addr = %lx refcnt = %x",
! 340: rc_history [i].file, rc_history [i].line,
! 341: (unsigned long)rc_history [i].reference,
! 342: (unsigned long)rc_history [i].addr,
! 343: rc_history [i].refcnt);
! 344: }
! 345:
! 346: void dump_rc_history (void *addr)
! 347: {
! 348: int i;
! 349:
! 350: i = rc_history_index;
! 351: if (!rc_history [i].file)
! 352: i = 0;
! 353: else if (rc_history_count < RC_HISTORY_MAX) {
! 354: i -= rc_history_count;
! 355: if (i < 0)
! 356: i += RC_HISTORY_MAX;
! 357: }
! 358: rc_history_count = 0;
! 359:
! 360: while (rc_history [i].file) {
! 361: if (!addr || addr == rc_history [i].addr)
! 362: print_rc_hist_entry (i);
! 363: ++i;
! 364: if (i == RC_HISTORY_MAX)
! 365: i = 0;
! 366: if (i == rc_history_index)
! 367: break;
! 368: }
! 369: }
! 370: void rc_history_next (int d)
! 371: {
! 372: #if defined (RC_HISTORY_COMPRESSION)
! 373: int i, j = 0, m, n = 0;
! 374: void *ap, *rp;
! 375:
! 376: /* If we are decreasing the reference count, try to find the
! 377: entry where the reference was made and eliminate it; then
! 378: we can also eliminate this reference. */
! 379: if (d) {
! 380: m = rc_history_index - 1000;
! 381: if (m < -1)
! 382: m = -1;
! 383: ap = rc_history [rc_history_index].addr;
! 384: rp = rc_history [rc_history_index].reference;
! 385: for (i = rc_history_index - 1; i > m; i--) {
! 386: if (rc_history [i].addr == ap) {
! 387: if (rc_history [i].reference == rp) {
! 388: if (n > 10) {
! 389: for (n = i; n <= rc_history_index; n++)
! 390: print_rc_hist_entry (n);
! 391: n = 11;
! 392: }
! 393: memmove (&rc_history [i],
! 394: &rc_history [i + 1],
! 395: (unsigned)((rc_history_index - i) *
! 396: sizeof (struct rc_history_entry)));
! 397: --rc_history_count;
! 398: --rc_history_index;
! 399: for (j = i; j < rc_history_count; j++) {
! 400: if (rc_history [j].addr == ap)
! 401: --rc_history [j].refcnt;
! 402: }
! 403: if (n > 10) {
! 404: for (n = i; n <= rc_history_index; n++)
! 405: print_rc_hist_entry (n);
! 406: n = 11;
! 407: exit (0);
! 408: }
! 409: return;
! 410: }
! 411: }
! 412: }
! 413: }
! 414: #endif
! 415: if (++rc_history_index == RC_HISTORY_MAX)
! 416: rc_history_index = 0;
! 417: ++rc_history_count;
! 418: }
! 419: #endif /* DEBUG_RC_HISTORY */
! 420:
! 421: #if defined (DEBUG_MEMORY_LEAKAGE) || defined (DEBUG_MALLOC_POOL) || \
! 422: defined (DEBUG_MEMORY_LEAKAGE_ON_EXIT)
! 423: struct caller {
! 424: struct dmalloc_preamble *dp;
! 425: int count;
! 426: };
! 427:
! 428: static int dmalloc_find_entry (struct dmalloc_preamble *dp,
! 429: struct caller *array,
! 430: int min, int max)
! 431: {
! 432: int middle;
! 433:
! 434: middle = (min + max) / 2;
! 435: if (middle == min)
! 436: return middle;
! 437: if (array [middle].dp -> file == dp -> file) {
! 438: if (array [middle].dp -> line == dp -> line)
! 439: return middle;
! 440: else if (array [middle].dp -> line < dp -> line)
! 441: return dmalloc_find_entry (dp, array, middle, max);
! 442: else
! 443: return dmalloc_find_entry (dp, array, 0, middle);
! 444: } else if (array [middle].dp -> file < dp -> file)
! 445: return dmalloc_find_entry (dp, array, middle, max);
! 446: else
! 447: return dmalloc_find_entry (dp, array, 0, middle);
! 448: }
! 449:
! 450: void omapi_print_dmalloc_usage_by_caller ()
! 451: {
! 452: struct dmalloc_preamble *dp;
! 453: int ccur, cmax, i;
! 454: struct caller cp [1024];
! 455:
! 456: cmax = 1024;
! 457: ccur = 0;
! 458:
! 459: memset (cp, 0, sizeof cp);
! 460: for (dp = dmalloc_list; dp; dp = dp -> prev) {
! 461: i = dmalloc_find_entry (dp, cp, 0, ccur);
! 462: if ((i == ccur ||
! 463: cp [i].dp -> file != dp -> file ||
! 464: cp [i].dp -> line != dp -> line) &&
! 465: ccur == cmax) {
! 466: log_error ("no space for memory usage summary.");
! 467: return;
! 468: }
! 469: if (i == ccur) {
! 470: cp [ccur++].dp = dp;
! 471: cp [i].count = 1;
! 472: } else if (cp [i].dp -> file < dp -> file ||
! 473: (cp [i].dp -> file == dp -> file &&
! 474: cp [i].dp -> line < dp -> line)) {
! 475: if (i + 1 != ccur)
! 476: memmove (cp + i + 2, cp + i + 1,
! 477: (ccur - i) * sizeof *cp);
! 478: cp [i + 1].dp = dp;
! 479: cp [i + 1].count = 1;
! 480: ccur++;
! 481: } else if (cp [i].dp -> file != dp -> file ||
! 482: cp [i].dp -> line != dp -> line) {
! 483: memmove (cp + i + 1,
! 484: cp + i, (ccur - i) * sizeof *cp);
! 485: cp [i].dp = dp;
! 486: cp [i].count = 1;
! 487: ccur++;
! 488: } else
! 489: cp [i].count++;
! 490: #if 0
! 491: printf ("%d\t%s:%d\n", i, dp -> file, dp -> line);
! 492: dump_rc_history (dp + 1);
! 493: #endif
! 494: }
! 495: for (i = 0; i < ccur; i++) {
! 496: printf ("%d\t%s:%d\t%d\n", i,
! 497: cp [i].dp -> file, cp [i].dp -> line, cp [i].count);
! 498: #if defined(DUMP_RC_HISTORY)
! 499: dump_rc_history (cp [i].dp + 1);
! 500: #endif
! 501: }
! 502: }
! 503: #endif /* DEBUG_MEMORY_LEAKAGE || DEBUG_MALLOC_POOL */
! 504:
! 505: isc_result_t omapi_object_allocate (omapi_object_t **o,
! 506: omapi_object_type_t *type,
! 507: size_t size,
! 508: const char *file, int line)
! 509: {
! 510: size_t tsize;
! 511: omapi_object_t *foo;
! 512: isc_result_t status;
! 513:
! 514: if (type -> allocator) {
! 515: foo = (omapi_object_t *)0;
! 516: status = (*type -> allocator) (&foo, file, line);
! 517: tsize = type -> size;
! 518: } else {
! 519: status = ISC_R_NOMEMORY;
! 520: tsize = 0;
! 521: }
! 522:
! 523: if (status == ISC_R_NOMEMORY) {
! 524: if (type -> sizer)
! 525: tsize = (*type -> sizer) (size);
! 526: else
! 527: tsize = type -> size;
! 528:
! 529: /* Sanity check. */
! 530: if (tsize < sizeof (omapi_object_t))
! 531: return ISC_R_INVALIDARG;
! 532:
! 533: foo = dmalloc (tsize, file, line);
! 534: if (!foo)
! 535: return ISC_R_NOMEMORY;
! 536: }
! 537:
! 538: status = omapi_object_initialize (foo, type, size, tsize, file, line);
! 539: if (status != ISC_R_SUCCESS) {
! 540: if (type -> freer)
! 541: (*type -> freer) (foo, file, line);
! 542: else
! 543: dfree (foo, file, line);
! 544: return status;
! 545: }
! 546: return omapi_object_reference (o, foo, file, line);
! 547: }
! 548:
! 549: isc_result_t omapi_object_initialize (omapi_object_t *o,
! 550: omapi_object_type_t *type,
! 551: size_t usize, size_t psize,
! 552: const char *file, int line)
! 553: {
! 554: memset (o, 0, psize);
! 555: o -> type = type;
! 556: if (type -> initialize)
! 557: (*type -> initialize) (o, file, line);
! 558: return ISC_R_SUCCESS;
! 559: }
! 560:
! 561: isc_result_t omapi_object_reference (omapi_object_t **r,
! 562: omapi_object_t *h,
! 563: const char *file, int line)
! 564: {
! 565: if (!h || !r)
! 566: return ISC_R_INVALIDARG;
! 567:
! 568: if (*r) {
! 569: #if defined (POINTER_DEBUG)
! 570: log_error ("%s(%d): reference store into non-null pointer!",
! 571: file, line);
! 572: abort ();
! 573: #else
! 574: return ISC_R_INVALIDARG;
! 575: #endif
! 576: }
! 577: *r = h;
! 578: h -> refcnt++;
! 579: rc_register (file, line, r, h, h -> refcnt, 0, h -> type -> rc_flag);
! 580: return ISC_R_SUCCESS;
! 581: }
! 582:
! 583: isc_result_t omapi_object_dereference (omapi_object_t **h,
! 584: const char *file, int line)
! 585: {
! 586: int outer_reference = 0;
! 587: int inner_reference = 0;
! 588: int handle_reference = 0;
! 589: int extra_references;
! 590: omapi_object_t *p, *hp;
! 591:
! 592: if (!h)
! 593: return ISC_R_INVALIDARG;
! 594:
! 595: if (!*h) {
! 596: #if defined (POINTER_DEBUG)
! 597: log_error ("%s(%d): dereference of null pointer!", file, line);
! 598: abort ();
! 599: #else
! 600: return ISC_R_INVALIDARG;
! 601: #endif
! 602: }
! 603:
! 604: if ((*h) -> refcnt <= 0) {
! 605: #if defined (POINTER_DEBUG)
! 606: log_error ("%s(%d): dereference of pointer with refcnt of zero!",
! 607: file, line);
! 608: #if defined (DEBUG_RC_HISTORY)
! 609: dump_rc_history (*h);
! 610: #endif
! 611: abort ();
! 612: #else
! 613: *h = 0;
! 614: return ISC_R_INVALIDARG;
! 615: #endif
! 616: }
! 617:
! 618: /* See if this object's inner object refers to it, but don't
! 619: count this as a reference if we're being asked to free the
! 620: reference from the inner object. */
! 621: if ((*h) -> inner && (*h) -> inner -> outer &&
! 622: h != &((*h) -> inner -> outer))
! 623: inner_reference = 1;
! 624:
! 625: /* Ditto for the outer object. */
! 626: if ((*h) -> outer && (*h) -> outer -> inner &&
! 627: h != &((*h) -> outer -> inner))
! 628: outer_reference = 1;
! 629:
! 630: /* Ditto for the outer object. The code below assumes that
! 631: the only reason we'd get a dereference from the handle
! 632: table is if this function does it - otherwise we'd have to
! 633: traverse the handle table to find the address where the
! 634: reference is stored and compare against that, and we don't
! 635: want to do that if we can avoid it. */
! 636: if ((*h) -> handle)
! 637: handle_reference = 1;
! 638:
! 639: /* If we are getting rid of the last reference other than
! 640: references to inner and outer objects, or from the handle
! 641: table, then we must examine all the objects in either
! 642: direction to see if they hold any non-inner, non-outer,
! 643: non-handle-table references. If not, we need to free the
! 644: entire chain of objects. */
! 645: if ((*h) -> refcnt ==
! 646: inner_reference + outer_reference + handle_reference + 1) {
! 647: if (inner_reference || outer_reference || handle_reference) {
! 648: /* XXX we could check for a reference from the
! 649: handle table here. */
! 650: extra_references = 0;
! 651: for (p = (*h) -> inner;
! 652: p && !extra_references; p = p -> inner) {
! 653: extra_references += p -> refcnt;
! 654: if (p -> inner && p -> inner -> outer == p)
! 655: --extra_references;
! 656: if (p -> outer)
! 657: --extra_references;
! 658: if (p -> handle)
! 659: --extra_references;
! 660: }
! 661: for (p = (*h) -> outer;
! 662: p && !extra_references; p = p -> outer) {
! 663: extra_references += p -> refcnt;
! 664: if (p -> outer && p -> outer -> inner == p)
! 665: --extra_references;
! 666: if (p -> inner)
! 667: --extra_references;
! 668: if (p -> handle)
! 669: --extra_references;
! 670: }
! 671: } else
! 672: extra_references = 0;
! 673:
! 674: if (!extra_references) {
! 675: hp = *h;
! 676: *h = 0;
! 677: hp -> refcnt--;
! 678: if (inner_reference)
! 679: omapi_object_dereference
! 680: (&hp -> inner, file, line);
! 681: if (outer_reference)
! 682: omapi_object_dereference
! 683: (&hp -> outer, file, line);
! 684: /* if (!hp -> type -> freer) */
! 685: rc_register (file, line, h, hp,
! 686: 0, 1, hp -> type -> rc_flag);
! 687: if (handle_reference) {
! 688: if (omapi_handle_clear(hp->handle) !=
! 689: ISC_R_SUCCESS) {
! 690: log_debug("Attempt to clear null "
! 691: "handle pointer");
! 692: }
! 693: }
! 694: if (hp -> type -> destroy)
! 695: (*(hp -> type -> destroy)) (hp, file, line);
! 696: if (hp -> type -> freer)
! 697: (hp -> type -> freer (hp, file, line));
! 698: else
! 699: dfree (hp, file, line);
! 700: } else {
! 701: (*h) -> refcnt--;
! 702: /* if (!(*h) -> type -> freer) */
! 703: rc_register (file, line,
! 704: h, *h, (*h) -> refcnt, 1,
! 705: (*h) -> type -> rc_flag);
! 706: }
! 707: } else {
! 708: (*h) -> refcnt--;
! 709: /* if (!(*h) -> type -> freer) */
! 710: rc_register (file, line, h, *h, (*h) -> refcnt, 1,
! 711: (*h) -> type -> rc_flag);
! 712: }
! 713: *h = 0;
! 714: return ISC_R_SUCCESS;
! 715: }
! 716:
! 717: isc_result_t omapi_buffer_new (omapi_buffer_t **h,
! 718: const char *file, int line)
! 719: {
! 720: omapi_buffer_t *t;
! 721: isc_result_t status;
! 722:
! 723: t = (omapi_buffer_t *)dmalloc (sizeof *t, file, line);
! 724: if (!t)
! 725: return ISC_R_NOMEMORY;
! 726: memset (t, 0, sizeof *t);
! 727: status = omapi_buffer_reference (h, t, file, line);
! 728: if (status != ISC_R_SUCCESS)
! 729: dfree (t, file, line);
! 730: (*h) -> head = sizeof ((*h) -> buf) - 1;
! 731: return status;
! 732: }
! 733:
! 734: isc_result_t omapi_buffer_reference (omapi_buffer_t **r,
! 735: omapi_buffer_t *h,
! 736: const char *file, int line)
! 737: {
! 738: if (!h || !r)
! 739: return ISC_R_INVALIDARG;
! 740:
! 741: if (*r) {
! 742: #if defined (POINTER_DEBUG)
! 743: log_error ("%s(%d): reference store into non-null pointer!",
! 744: file, line);
! 745: abort ();
! 746: #else
! 747: return ISC_R_INVALIDARG;
! 748: #endif
! 749: }
! 750: *r = h;
! 751: h -> refcnt++;
! 752: rc_register (file, line, r, h, h -> refcnt, 0, RC_MISC);
! 753: return ISC_R_SUCCESS;
! 754: }
! 755:
! 756: isc_result_t omapi_buffer_dereference (omapi_buffer_t **h,
! 757: const char *file, int line)
! 758: {
! 759: if (!h)
! 760: return ISC_R_INVALIDARG;
! 761:
! 762: if (!*h) {
! 763: #if defined (POINTER_DEBUG)
! 764: log_error ("%s(%d): dereference of null pointer!", file, line);
! 765: abort ();
! 766: #else
! 767: return ISC_R_INVALIDARG;
! 768: #endif
! 769: }
! 770:
! 771: if ((*h) -> refcnt <= 0) {
! 772: #if defined (POINTER_DEBUG)
! 773: log_error ("%s(%d): dereference of pointer with refcnt of zero!",
! 774: file, line);
! 775: #if defined (DEBUG_RC_HISTORY)
! 776: dump_rc_history (*h);
! 777: #endif
! 778: abort ();
! 779: #else
! 780: *h = 0;
! 781: return ISC_R_INVALIDARG;
! 782: #endif
! 783: }
! 784:
! 785: --(*h) -> refcnt;
! 786: rc_register (file, line, h, *h, (*h) -> refcnt, 1, RC_MISC);
! 787: if ((*h) -> refcnt == 0)
! 788: dfree (*h, file, line);
! 789: *h = 0;
! 790: return ISC_R_SUCCESS;
! 791: }
! 792:
! 793: isc_result_t omapi_typed_data_new (const char *file, int line,
! 794: omapi_typed_data_t **t,
! 795: omapi_datatype_t type, ...)
! 796: {
! 797: va_list l;
! 798: omapi_typed_data_t *new;
! 799: unsigned len;
! 800: unsigned val = 0;
! 801: int intval = 0;
! 802: char *s = NULL;
! 803: isc_result_t status;
! 804: omapi_object_t *obj = NULL;
! 805:
! 806: va_start (l, type);
! 807:
! 808: switch (type) {
! 809: case omapi_datatype_int:
! 810: len = OMAPI_TYPED_DATA_INT_LEN;
! 811: intval = va_arg (l, int);
! 812: break;
! 813: case omapi_datatype_string:
! 814: s = va_arg (l, char *);
! 815: val = strlen (s);
! 816: len = OMAPI_TYPED_DATA_NOBUFFER_LEN + val;
! 817: if (len < val) {
! 818: va_end(l);
! 819: return ISC_R_INVALIDARG;
! 820: }
! 821: break;
! 822: case omapi_datatype_data:
! 823: val = va_arg (l, unsigned);
! 824: len = OMAPI_TYPED_DATA_NOBUFFER_LEN + val;
! 825: if (len < val) {
! 826: va_end(l);
! 827: return ISC_R_INVALIDARG;
! 828: }
! 829: break;
! 830: case omapi_datatype_object:
! 831: len = OMAPI_TYPED_DATA_OBJECT_LEN;
! 832: obj = va_arg (l, omapi_object_t *);
! 833: break;
! 834: default:
! 835: va_end (l);
! 836: return ISC_R_INVALIDARG;
! 837: }
! 838: va_end (l);
! 839:
! 840: new = dmalloc (len, file, line);
! 841: if (!new)
! 842: return ISC_R_NOMEMORY;
! 843: memset (new, 0, len);
! 844:
! 845: switch (type) {
! 846: case omapi_datatype_int:
! 847: new -> u.integer = intval;
! 848: break;
! 849: case omapi_datatype_string:
! 850: memcpy (new -> u.buffer.value, s, val);
! 851: new -> u.buffer.len = val;
! 852: break;
! 853: case omapi_datatype_data:
! 854: new -> u.buffer.len = val;
! 855: break;
! 856: case omapi_datatype_object:
! 857: status = omapi_object_reference (&new -> u.object, obj,
! 858: file, line);
! 859: if (status != ISC_R_SUCCESS) {
! 860: dfree (new, file, line);
! 861: return status;
! 862: }
! 863: break;
! 864: }
! 865: new -> type = type;
! 866:
! 867: return omapi_typed_data_reference (t, new, file, line);
! 868: }
! 869:
! 870: isc_result_t omapi_typed_data_reference (omapi_typed_data_t **r,
! 871: omapi_typed_data_t *h,
! 872: const char *file, int line)
! 873: {
! 874: if (!h || !r)
! 875: return ISC_R_INVALIDARG;
! 876:
! 877: if (*r) {
! 878: #if defined (POINTER_DEBUG)
! 879: log_error ("%s(%d): reference store into non-null pointer!", file, line);
! 880: abort ();
! 881: #else
! 882: return ISC_R_INVALIDARG;
! 883: #endif
! 884: }
! 885: *r = h;
! 886: h -> refcnt++;
! 887: rc_register (file, line, r, h, h -> refcnt, 0, RC_MISC);
! 888: return ISC_R_SUCCESS;
! 889: }
! 890:
! 891: isc_result_t omapi_typed_data_dereference (omapi_typed_data_t **h,
! 892: const char *file, int line)
! 893: {
! 894: if (!h)
! 895: return ISC_R_INVALIDARG;
! 896:
! 897: if (!*h) {
! 898: #if defined (POINTER_DEBUG)
! 899: log_error ("%s(%d): dereference of null pointer!", file, line);
! 900: abort ();
! 901: #else
! 902: return ISC_R_INVALIDARG;
! 903: #endif
! 904: }
! 905:
! 906: if ((*h) -> refcnt <= 0) {
! 907: #if defined (POINTER_DEBUG)
! 908: log_error ("%s(%d): dereference of pointer with refcnt of zero!",
! 909: file, line);
! 910: #if defined (DEBUG_RC_HISTORY)
! 911: dump_rc_history (*h);
! 912: #endif
! 913: abort ();
! 914: #else
! 915: *h = 0;
! 916: return ISC_R_INVALIDARG;
! 917: #endif
! 918: }
! 919:
! 920: --((*h) -> refcnt);
! 921: rc_register (file, line, h, *h, (*h) -> refcnt, 1, RC_MISC);
! 922: if ((*h) -> refcnt <= 0 ) {
! 923: switch ((*h) -> type) {
! 924: case omapi_datatype_int:
! 925: case omapi_datatype_string:
! 926: case omapi_datatype_data:
! 927: default:
! 928: break;
! 929: case omapi_datatype_object:
! 930: omapi_object_dereference (&(*h) -> u.object,
! 931: file, line);
! 932: break;
! 933: }
! 934: dfree (*h, file, line);
! 935: }
! 936: *h = 0;
! 937: return ISC_R_SUCCESS;
! 938: }
! 939:
! 940: isc_result_t omapi_data_string_new (omapi_data_string_t **d, unsigned len,
! 941: const char *file, int line)
! 942: {
! 943: omapi_data_string_t *new;
! 944: unsigned nlen;
! 945:
! 946: nlen = OMAPI_DATA_STRING_EMPTY_SIZE + len;
! 947: if (nlen < len)
! 948: return ISC_R_INVALIDARG;
! 949: new = dmalloc (nlen, file, line);
! 950: if (!new)
! 951: return ISC_R_NOMEMORY;
! 952: memset (new, 0, OMAPI_DATA_STRING_EMPTY_SIZE);
! 953: new -> len = len;
! 954: return omapi_data_string_reference (d, new, file, line);
! 955: }
! 956:
! 957: isc_result_t omapi_data_string_reference (omapi_data_string_t **r,
! 958: omapi_data_string_t *h,
! 959: const char *file, int line)
! 960: {
! 961: if (!h || !r)
! 962: return ISC_R_INVALIDARG;
! 963:
! 964: if (*r) {
! 965: #if defined (POINTER_DEBUG)
! 966: log_error ("%s(%d): reference store into non-null pointer!", file, line);
! 967: abort ();
! 968: #else
! 969: return ISC_R_INVALIDARG;
! 970: #endif
! 971: }
! 972: *r = h;
! 973: h -> refcnt++;
! 974: rc_register (file, line, r, h, h -> refcnt, 0, RC_MISC);
! 975: return ISC_R_SUCCESS;
! 976: }
! 977:
! 978: isc_result_t omapi_data_string_dereference (omapi_data_string_t **h,
! 979: const char *file, int line)
! 980: {
! 981: if (!h)
! 982: return ISC_R_INVALIDARG;
! 983:
! 984: if (!*h) {
! 985: #if defined (POINTER_DEBUG)
! 986: log_error ("%s(%d): dereference of null pointer!", file, line);
! 987: abort ();
! 988: #else
! 989: return ISC_R_INVALIDARG;
! 990: #endif
! 991: }
! 992:
! 993: if ((*h) -> refcnt <= 0) {
! 994: #if defined (POINTER_DEBUG)
! 995: log_error ("%s(%d): dereference of pointer with refcnt of zero!",
! 996: file, line);
! 997: #if defined (DEBUG_RC_HISTORY)
! 998: dump_rc_history (*h);
! 999: #endif
! 1000: abort ();
! 1001: #else
! 1002: *h = 0;
! 1003: return ISC_R_INVALIDARG;
! 1004: #endif
! 1005: }
! 1006:
! 1007: --((*h) -> refcnt);
! 1008: rc_register (file, line, h, *h, (*h) -> refcnt, 1, RC_MISC);
! 1009: if ((*h) -> refcnt <= 0 ) {
! 1010: dfree (*h, file, line);
! 1011: }
! 1012: *h = 0;
! 1013: return ISC_R_SUCCESS;
! 1014: }
! 1015:
! 1016: isc_result_t omapi_value_new (omapi_value_t **d,
! 1017: const char *file, int line)
! 1018: {
! 1019: omapi_value_t *new;
! 1020:
! 1021: new = dmalloc (sizeof *new, file, line);
! 1022: if (!new)
! 1023: return ISC_R_NOMEMORY;
! 1024: memset (new, 0, sizeof *new);
! 1025: return omapi_value_reference (d, new, file, line);
! 1026: }
! 1027:
! 1028: isc_result_t omapi_value_reference (omapi_value_t **r,
! 1029: omapi_value_t *h,
! 1030: const char *file, int line)
! 1031: {
! 1032: if (!h || !r)
! 1033: return ISC_R_INVALIDARG;
! 1034:
! 1035: if (*r) {
! 1036: #if defined (POINTER_DEBUG)
! 1037: log_error ("%s(%d): reference store into non-null pointer!",
! 1038: file, line);
! 1039: abort ();
! 1040: #else
! 1041: return ISC_R_INVALIDARG;
! 1042: #endif
! 1043: }
! 1044: *r = h;
! 1045: h -> refcnt++;
! 1046: rc_register (file, line, r, h, h -> refcnt, 0, RC_MISC);
! 1047: return ISC_R_SUCCESS;
! 1048: }
! 1049:
! 1050: isc_result_t omapi_value_dereference (omapi_value_t **h,
! 1051: const char *file, int line)
! 1052: {
! 1053: if (!h)
! 1054: return ISC_R_INVALIDARG;
! 1055:
! 1056: if (!*h) {
! 1057: #if defined (POINTER_DEBUG)
! 1058: log_error ("%s(%d): dereference of null pointer!", file, line);
! 1059: abort ();
! 1060: #else
! 1061: return ISC_R_INVALIDARG;
! 1062: #endif
! 1063: }
! 1064:
! 1065: if ((*h) -> refcnt <= 0) {
! 1066: #if defined (POINTER_DEBUG)
! 1067: log_error ("%s(%d): dereference of pointer with refcnt of zero!",
! 1068: file, line);
! 1069: #if defined (DEBUG_RC_HISTORY)
! 1070: dump_rc_history (*h);
! 1071: #endif
! 1072: abort ();
! 1073: #else
! 1074: *h = 0;
! 1075: return ISC_R_INVALIDARG;
! 1076: #endif
! 1077: }
! 1078:
! 1079: --((*h) -> refcnt);
! 1080: rc_register (file, line, h, *h, (*h) -> refcnt, 1, RC_MISC);
! 1081: if ((*h) -> refcnt == 0) {
! 1082: if ((*h) -> name)
! 1083: omapi_data_string_dereference (&(*h) -> name,
! 1084: file, line);
! 1085: if ((*h) -> value)
! 1086: omapi_typed_data_dereference (&(*h) -> value,
! 1087: file, line);
! 1088: dfree (*h, file, line);
! 1089: }
! 1090: *h = 0;
! 1091: return ISC_R_SUCCESS;
! 1092: }
! 1093:
! 1094: isc_result_t omapi_addr_list_new (omapi_addr_list_t **d, unsigned count,
! 1095: const char *file, int line)
! 1096: {
! 1097: omapi_addr_list_t *new;
! 1098:
! 1099: new = dmalloc ((count * sizeof (omapi_addr_t)) +
! 1100: sizeof (omapi_addr_list_t), file, line);
! 1101: if (!new)
! 1102: return ISC_R_NOMEMORY;
! 1103: memset (new, 0, ((count * sizeof (omapi_addr_t)) +
! 1104: sizeof (omapi_addr_list_t)));
! 1105: new -> count = count;
! 1106: new -> addresses = (omapi_addr_t *)(new + 1);
! 1107: return omapi_addr_list_reference (d, new, file, line);
! 1108: }
! 1109:
! 1110: isc_result_t omapi_addr_list_reference (omapi_addr_list_t **r,
! 1111: omapi_addr_list_t *h,
! 1112: const char *file, int line)
! 1113: {
! 1114: if (!h || !r)
! 1115: return ISC_R_INVALIDARG;
! 1116:
! 1117: if (*r) {
! 1118: #if defined (POINTER_DEBUG)
! 1119: log_error ("%s(%d): reference store into non-null pointer!",
! 1120: file, line);
! 1121: abort ();
! 1122: #else
! 1123: return ISC_R_INVALIDARG;
! 1124: #endif
! 1125: }
! 1126: *r = h;
! 1127: h -> refcnt++;
! 1128: rc_register (file, line, r, h, h -> refcnt, 0, RC_MISC);
! 1129: return ISC_R_SUCCESS;
! 1130: }
! 1131:
! 1132: isc_result_t omapi_addr_list_dereference (omapi_addr_list_t **h,
! 1133: const char *file, int line)
! 1134: {
! 1135: if (!h)
! 1136: return ISC_R_INVALIDARG;
! 1137:
! 1138: if (!*h) {
! 1139: #if defined (POINTER_DEBUG)
! 1140: log_error ("%s(%d): dereference of null pointer!", file, line);
! 1141: abort ();
! 1142: #else
! 1143: return ISC_R_INVALIDARG;
! 1144: #endif
! 1145: }
! 1146:
! 1147: if ((*h) -> refcnt <= 0) {
! 1148: #if defined (POINTER_DEBUG)
! 1149: log_error ("%s(%d): dereference of pointer with zero refcnt!",
! 1150: file, line);
! 1151: #if defined (DEBUG_RC_HISTORY)
! 1152: dump_rc_history (*h);
! 1153: #endif
! 1154: abort ();
! 1155: #else
! 1156: *h = 0;
! 1157: return ISC_R_INVALIDARG;
! 1158: #endif
! 1159: }
! 1160:
! 1161: --((*h) -> refcnt);
! 1162: rc_register (file, line, h, *h, (*h) -> refcnt, 1, RC_MISC);
! 1163: if ((*h) -> refcnt <= 0 ) {
! 1164: dfree (*h, file, line);
! 1165: }
! 1166: *h = 0;
! 1167: return ISC_R_SUCCESS;
! 1168: }
! 1169:
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>