File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / dhcp / omapip / alloc.c
Revision 1.1.1.1 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Tue Oct 9 09:06:54 2012 UTC (11 years, 9 months ago) by misho
Branches: dhcp, MAIN
CVS tags: v4_1_R7p0, v4_1_R7, v4_1_R4, HEAD
dhcp 4.1 r7

    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>