Annotation of embedaddon/dhcp/omapip/alloc.c, revision 1.1.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>