omapip/alloc.c

Go to the documentation of this file.
00001 /* alloc.c
00002 
00003    Functions supporting memory allocation for the object management
00004    protocol... */
00005 
00006 /*
00007  * Copyright (c) 2012,2014 by Internet Systems Consortium, Inc. ("ISC")
00008  * Copyright (c) 2009-2010 by Internet Systems Consortium, Inc. ("ISC")
00009  * Copyright (c) 2004-2007 by Internet Systems Consortium, Inc. ("ISC")
00010  * Copyright (c) 1999-2003 by Internet Software Consortium
00011  *
00012  * Permission to use, copy, modify, and distribute this software for any
00013  * purpose with or without fee is hereby granted, provided that the above
00014  * copyright notice and this permission notice appear in all copies.
00015  *
00016  * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
00017  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
00018  * MERCHANTABILITY AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR
00019  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
00020  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
00021  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
00022  * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
00023  *
00024  *   Internet Systems Consortium, Inc.
00025  *   950 Charter Street
00026  *   Redwood City, CA 94063
00027  *   <info@isc.org>
00028  *   https://www.isc.org/
00029  *
00030  */
00031 
00032 #include "dhcpd.h"
00033 
00034 #include <omapip/omapip_p.h>
00035 
00036 #if defined (DEBUG_MEMORY_LEAKAGE) || defined (DEBUG_MALLOC_POOL) || \
00037                 defined (DEBUG_MEMORY_LEAKAGE_ON_EXIT)
00038 struct dmalloc_preamble *dmalloc_list;
00039 unsigned long dmalloc_outstanding;
00040 unsigned long dmalloc_longterm;
00041 unsigned long dmalloc_generation;
00042 unsigned long dmalloc_cutoff_generation;
00043 #endif
00044 
00045 #if defined (DEBUG_RC_HISTORY)
00046 struct rc_history_entry rc_history [RC_HISTORY_MAX];
00047 int rc_history_index;
00048 int rc_history_count;
00049 #endif
00050 
00051 #if defined (DEBUG_RC_HISTORY)
00052 static void print_rc_hist_entry (int);
00053 #endif
00054 
00055 void *
00056 dmalloc(unsigned size, const char *file, int line) {
00057         unsigned char *foo;
00058         unsigned len;
00059         void **bar;
00060 #if defined (DEBUG_MEMORY_LEAKAGE) || defined (DEBUG_MALLOC_POOL) || \
00061                 defined (DEBUG_MEMORY_LEAKAGE_ON_EXIT)
00062         int i;
00063         struct dmalloc_preamble *dp;
00064 #endif
00065 
00066         len = size + DMDSIZE;
00067         if (len < size)
00068                 return NULL;
00069 
00070         foo = malloc(len);
00071 
00072         if (!foo)
00073                 return NULL;
00074         bar = (void *)(foo + DMDOFFSET);
00075         memset (bar, 0, size);
00076 
00077 #if defined (DEBUG_MEMORY_LEAKAGE) || defined (DEBUG_MALLOC_POOL) || \
00078                 defined (DEBUG_MEMORY_LEAKAGE_ON_EXIT)
00079         dp = (struct dmalloc_preamble *)foo;
00080         dp -> prev = dmalloc_list;
00081         if (dmalloc_list)
00082                 dmalloc_list -> next = dp;
00083         dmalloc_list = dp;
00084         dp -> next = (struct dmalloc_preamble *)0;
00085         dp -> size = size;
00086         dp -> file = file;
00087         dp -> line = line;
00088         dp -> generation = dmalloc_generation++;
00089         dmalloc_outstanding += size;
00090         for (i = 0; i < DMLFSIZE; i++)
00091                 dp -> low_fence [i] =
00092                         (((unsigned long)
00093                           (&dp -> low_fence [i])) % 143) + 113;
00094         for (i = DMDOFFSET; i < DMDSIZE; i++)
00095                 foo [i + size] =
00096                         (((unsigned long)
00097                           (&foo [i + size])) % 143) + 113;
00098 #if defined (DEBUG_MALLOC_POOL_EXHAUSTIVELY)
00099         /* Check _every_ entry in the pool!   Very expensive. */
00100         for (dp = dmalloc_list; dp; dp = dp -> prev) {
00101                 for (i = 0; i < DMLFSIZE; i++) {
00102                         if (dp -> low_fence [i] !=
00103                                 (((unsigned long)
00104                                   (&dp -> low_fence [i])) % 143) + 113)
00105                         {
00106                                 log_error ("malloc fence modified: %s(%d)",
00107                                            dp -> file, dp -> line);
00108                                 abort ();
00109                         }
00110                 }
00111                 foo = (unsigned char *)dp;
00112                 for (i = DMDOFFSET; i < DMDSIZE; i++) {
00113                         if (foo [i + dp -> size] !=
00114                                 (((unsigned long)
00115                                   (&foo [i + dp -> size])) % 143) + 113) {
00116                                 log_error ("malloc fence modified: %s(%d)",
00117                                            dp -> file, dp -> line);
00118                                 abort ();
00119                         }
00120                 }
00121         }
00122 #endif
00123 #endif
00124 #ifdef DEBUG_REFCNT_DMALLOC_FREE
00125         rc_register (file, line, 0, foo + DMDOFFSET, 1, 0, RC_MALLOC);
00126 #endif
00127         return bar;
00128 }
00129 
00130 void 
00131 dfree(void *ptr, const char *file, int line) {
00132         if (!ptr) {
00133                 log_error ("dfree %s(%d): free on null pointer.", file, line);
00134                 return;
00135         }
00136 #if defined (DEBUG_MEMORY_LEAKAGE) || defined (DEBUG_MALLOC_POOL) || \
00137                 defined (DEBUG_MEMORY_LEAKAGE_ON_EXIT)
00138         {
00139                 unsigned char *bar = ptr;
00140                 struct dmalloc_preamble *dp, *cur;
00141                 int i;
00142                 bar -= DMDOFFSET;
00143                 cur = (struct dmalloc_preamble *)bar;
00144                 for (dp = dmalloc_list; dp; dp = dp -> prev)
00145                         if (dp == cur)
00146                                 break;
00147                 if (!dp) {
00148                         log_error ("%s(%d): freeing unknown memory: %lx",
00149                                    file, line, (unsigned long)cur);
00150                         abort ();
00151                 }
00152                 if (dp -> prev)
00153                         dp -> prev -> next = dp -> next;
00154                 if (dp -> next)
00155                         dp -> next -> prev = dp -> prev;
00156                 if (dp == dmalloc_list)
00157                         dmalloc_list = dp -> prev;
00158                 if (dp -> generation >= dmalloc_cutoff_generation)
00159                         dmalloc_outstanding -= dp -> size;
00160                 else
00161                         dmalloc_longterm -= dp -> size;
00162 
00163                 for (i = 0; i < DMLFSIZE; i++) {
00164                         if (dp -> low_fence [i] !=
00165                                 (((unsigned long)
00166                                   (&dp -> low_fence [i])) % 143) + 113)
00167                         {
00168                                 log_error ("malloc fence modified: %s(%d)",
00169                                            dp -> file, dp -> line);
00170                                 abort ();
00171                         }
00172                 }
00173                 for (i = DMDOFFSET; i < DMDSIZE; i++) {
00174                         if (bar [i + dp -> size] !=
00175                                 (((unsigned long)
00176                                   (&bar [i + dp -> size])) % 143) + 113) {
00177                                 log_error ("malloc fence modified: %s(%d)",
00178                                            dp -> file, dp -> line);
00179                                 abort ();
00180                         }
00181                 }
00182                 ptr = bar;
00183         }
00184 #endif
00185 #ifdef DEBUG_REFCNT_DMALLOC_FREE
00186         rc_register (file, line,
00187                      0, (unsigned char *)ptr + DMDOFFSET, 0, 1, RC_MALLOC);
00188 #endif
00189         free (ptr);
00190 }
00191 
00192 #if defined (DEBUG_MEMORY_LEAKAGE) || defined (DEBUG_MALLOC_POOL) || \
00193                 defined (DEBUG_MEMORY_LEAKAGE_ON_EXIT)
00194 /* For allocation functions that keep their own free lists, we want to
00195    account for the reuse of the memory. */
00196 
00197 void 
00198 dmalloc_reuse(void *foo, const char *file, int line, int justref) {
00199         struct dmalloc_preamble *dp;
00200 
00201         /* Get the pointer to the dmalloc header. */
00202         dp = foo;
00203         dp--;
00204 
00205         /* If we just allocated this and are now referencing it, this
00206            function would almost be a no-op, except that it would
00207            increment the generation count needlessly.  So just return
00208            in this case. */
00209         if (dp -> generation == dmalloc_generation)
00210                 return;
00211 
00212         /* If this is longterm data, and we just made reference to it,
00213            don't put it on the short-term list or change its name -
00214            we don't need to know about this. */
00215         if (dp -> generation < dmalloc_cutoff_generation && justref)
00216                 return;
00217 
00218         /* Take it out of the place in the allocated list where it was. */
00219         if (dp -> prev)
00220                 dp -> prev -> next = dp -> next;
00221         if (dp -> next)
00222                 dp -> next -> prev = dp -> prev;
00223         if (dp == dmalloc_list)
00224                 dmalloc_list = dp -> prev;
00225 
00226         /* Account for its removal. */
00227         if (dp -> generation >= dmalloc_cutoff_generation)
00228                 dmalloc_outstanding -= dp -> size;
00229         else
00230                 dmalloc_longterm -= dp -> size;
00231 
00232         /* Now put it at the head of the list. */
00233         dp -> prev = dmalloc_list;
00234         if (dmalloc_list)
00235                 dmalloc_list -> next = dp;
00236         dmalloc_list = dp;
00237         dp -> next = (struct dmalloc_preamble *)0;
00238 
00239         /* Change the reference location information. */
00240         dp -> file = file;
00241         dp -> line = line;
00242 
00243         /* Increment the generation. */
00244         dp -> generation = dmalloc_generation++;
00245 
00246         /* Account for it. */
00247         dmalloc_outstanding += dp -> size;
00248 }
00249 
00250 void dmalloc_dump_outstanding ()
00251 {
00252         static unsigned long dmalloc_cutoff_point;
00253         struct dmalloc_preamble *dp;
00254 #if defined(DEBUG_MALLOC_POOL)
00255         unsigned char *foo;
00256         int i;
00257 #endif
00258 
00259         if (!dmalloc_cutoff_point)
00260                 dmalloc_cutoff_point = dmalloc_cutoff_generation;
00261         for (dp = dmalloc_list; dp; dp = dp -> prev) {
00262                 if (dp -> generation <= dmalloc_cutoff_point)
00263                         break;
00264 #if defined (DEBUG_MALLOC_POOL)
00265                 for (i = 0; i < DMLFSIZE; i++) {
00266                         if (dp -> low_fence [i] !=
00267                                 (((unsigned long)
00268                                   (&dp -> low_fence [i])) % 143) + 113)
00269                         {
00270                                 log_error ("malloc fence modified: %s(%d)",
00271                                            dp -> file, dp -> line);
00272                                 abort ();
00273                         }
00274                 }
00275                 foo = (unsigned char *)dp;
00276                 for (i = DMDOFFSET; i < DMDSIZE; i++) {
00277                         if (foo [i + dp -> size] !=
00278                                 (((unsigned long)
00279                                   (&foo [i + dp -> size])) % 143) + 113) {
00280                                 log_error ("malloc fence modified: %s(%d)",
00281                                            dp -> file, dp -> line);
00282                                 abort ();
00283                         }
00284                 }
00285 #endif
00286 #if defined (DEBUG_MEMORY_LEAKAGE) || \
00287                 defined (DEBUG_MEMORY_LEAKAGE_ON_EXIT)
00288                 /* Don't count data that's actually on a free list
00289                    somewhere. */
00290                 if (dp -> file) {
00291 #if defined (DEBUG_RC_HISTORY)
00292                         int i, count, inhistory = 0, noted = 0;
00293 
00294                         /* If we have the info, see if this is actually
00295                            new garbage. */
00296                         if (rc_history_count < RC_HISTORY_MAX) {
00297                             count = rc_history_count;
00298                         } else
00299                             count = RC_HISTORY_MAX;
00300                         i = rc_history_index - 1;
00301                         if (i < 0)
00302                                 i += RC_HISTORY_MAX;
00303 
00304                         do {
00305                             if (rc_history [i].addr == dp + 1) {
00306                                 inhistory = 1;
00307                                 if (!noted) {
00308                                     log_info ("  %s(%d): %ld", dp -> file,
00309                                               dp -> line, (long) dp -> size);
00310                                     noted = 1;
00311                                 }
00312                                 print_rc_hist_entry (i);
00313                                 if (!rc_history [i].refcnt)
00314                                     break;
00315                             }
00316                             if (--i < 0)
00317                                 i = RC_HISTORY_MAX - 1;
00318                         } while (count--);
00319                         if (!inhistory)
00320 #endif
00321                                 log_info ("  %s(%d): %ld",
00322                                           dp -> file, dp -> line, 
00323                                           (long) dp -> size);
00324                 }
00325 #endif
00326         }
00327         if (dmalloc_list)
00328                 dmalloc_cutoff_point = dmalloc_list -> generation;
00329 }
00330 #endif /* DEBUG_MEMORY_LEAKAGE || DEBUG_MALLOC_POOL */
00331 
00332 #if defined (DEBUG_RC_HISTORY)
00333 static void print_rc_hist_entry (int i)
00334 {
00335         log_info ("   referenced by %s(%d)[%lx]: addr = %lx  refcnt = %x",
00336                   rc_history [i].file, rc_history [i].line,
00337                   (unsigned long)rc_history [i].reference,
00338                   (unsigned long)rc_history [i].addr,
00339                   rc_history [i].refcnt);
00340 }
00341 
00342 void dump_rc_history (void *addr)
00343 {
00344         int i;
00345 
00346         i = rc_history_index;
00347         if (!rc_history [i].file)
00348                 i = 0;
00349         else if (rc_history_count < RC_HISTORY_MAX) {
00350                 i -= rc_history_count;
00351                 if (i < 0)
00352                         i += RC_HISTORY_MAX;
00353         }
00354         rc_history_count = 0;
00355 
00356         while (rc_history [i].file) {
00357                 if (!addr || addr == rc_history [i].addr)
00358                         print_rc_hist_entry (i);
00359                 ++i;
00360                 if (i == RC_HISTORY_MAX)
00361                         i = 0;
00362                 if (i == rc_history_index)
00363                         break;
00364         }
00365 }
00366 void rc_history_next (int d)
00367 {
00368 #if defined (RC_HISTORY_COMPRESSION)
00369         int i, j = 0, m, n = 0;
00370         void *ap, *rp;
00371 
00372         /* If we are decreasing the reference count, try to find the
00373            entry where the reference was made and eliminate it; then
00374            we can also eliminate this reference. */
00375         if (d) {
00376             m = rc_history_index - 1000;
00377             if (m < -1)
00378                 m = -1;
00379             ap = rc_history [rc_history_index].addr;
00380             rp = rc_history [rc_history_index].reference;
00381             for (i = rc_history_index - 1; i > m; i--) {
00382                 if (rc_history [i].addr == ap) {
00383                     if (rc_history [i].reference == rp) {
00384                         if (n > 10) {
00385                             for (n = i; n <= rc_history_index; n++)
00386                                     print_rc_hist_entry (n);
00387                             n = 11;
00388                         }
00389                         memmove (&rc_history [i],
00390                                  &rc_history [i + 1],
00391                                  (unsigned)((rc_history_index - i) *
00392                                             sizeof (struct rc_history_entry)));
00393                         --rc_history_count;
00394                         --rc_history_index;
00395                         for (j = i; j < rc_history_count; j++) {
00396                             if (rc_history [j].addr == ap)
00397                                 --rc_history [j].refcnt;
00398                         }
00399                         if (n > 10) {
00400                             for (n = i; n <= rc_history_index; n++)
00401                                     print_rc_hist_entry (n);
00402                             n = 11;
00403                             exit (0);
00404                         }
00405                         return;
00406                     }
00407                 }
00408             }
00409         }
00410 #endif
00411         if (++rc_history_index == RC_HISTORY_MAX)
00412                 rc_history_index = 0;
00413         ++rc_history_count;
00414 }
00415 #endif /* DEBUG_RC_HISTORY */
00416 
00417 #if defined (DEBUG_MEMORY_LEAKAGE) || defined (DEBUG_MALLOC_POOL) || \
00418                 defined (DEBUG_MEMORY_LEAKAGE_ON_EXIT)
00419 struct caller {
00420         struct dmalloc_preamble *dp;
00421         int count;
00422 };
00423 
00424 static int dmalloc_find_entry (struct dmalloc_preamble *dp,
00425                                struct caller *array,
00426                                int min, int max)
00427 {
00428         int middle;
00429 
00430         middle = (min + max) / 2;
00431         if (middle == min)
00432                 return middle;
00433         if (array [middle].dp -> file == dp -> file) {
00434                 if (array [middle].dp -> line == dp -> line)
00435                         return middle;
00436                 else if (array [middle].dp -> line < dp -> line)
00437                         return dmalloc_find_entry (dp, array, middle, max);
00438                 else
00439                         return dmalloc_find_entry (dp, array, 0, middle);
00440         } else if (array [middle].dp -> file < dp -> file)
00441                 return dmalloc_find_entry (dp, array, middle, max);
00442         else
00443                 return dmalloc_find_entry (dp, array, 0, middle);
00444 }
00445 
00446 void omapi_print_dmalloc_usage_by_caller ()
00447 {
00448         struct dmalloc_preamble *dp;
00449         int ccur, cmax, i;
00450         struct caller cp [1024];
00451 
00452         cmax = 1024;
00453         ccur = 0;
00454 
00455         memset (cp, 0, sizeof cp);
00456         for (dp = dmalloc_list; dp; dp = dp -> prev) {
00457                 i = dmalloc_find_entry (dp, cp, 0, ccur);
00458                 if ((i == ccur ||
00459                      cp [i].dp -> file != dp -> file ||
00460                      cp [i].dp -> line != dp -> line) &&
00461                     ccur == cmax) {
00462                         log_error ("no space for memory usage summary.");
00463                         return;
00464                 }
00465                 if (i == ccur) {
00466                         cp [ccur++].dp = dp;
00467                         cp [i].count = 1;
00468                 } else if (cp [i].dp -> file < dp -> file ||
00469                            (cp [i].dp -> file == dp -> file &&
00470                             cp [i].dp -> line < dp -> line)) {
00471                         if (i + 1 != ccur)
00472                                 memmove (cp + i + 2, cp + i + 1,
00473                                          (ccur - i) * sizeof *cp);
00474                         cp [i + 1].dp = dp;
00475                         cp [i + 1].count = 1;
00476                         ccur++;
00477                 } else if (cp [i].dp -> file != dp -> file ||
00478                            cp [i].dp -> line != dp -> line) {
00479                         memmove (cp + i + 1,
00480                                  cp + i, (ccur - i) * sizeof *cp);
00481                         cp [i].dp = dp;
00482                         cp [i].count = 1;
00483                         ccur++;
00484                 } else
00485                         cp [i].count++;
00486 #if 0
00487                 printf ("%d\t%s:%d\n", i, dp -> file, dp -> line);
00488                 dump_rc_history (dp + 1);
00489 #endif
00490         }
00491         for (i = 0; i < ccur; i++) {
00492                 printf ("%d\t%s:%d\t%d\n", i,
00493                         cp [i].dp -> file, cp [i].dp -> line, cp [i].count);
00494 #if defined(DUMP_RC_HISTORY)
00495                 dump_rc_history (cp [i].dp + 1);
00496 #endif
00497         }
00498 }
00499 #endif /* DEBUG_MEMORY_LEAKAGE || DEBUG_MALLOC_POOL */
00500 
00501 isc_result_t omapi_object_allocate (omapi_object_t **o,
00502                                     omapi_object_type_t *type,
00503                                     size_t size,
00504                                     const char *file, int line)
00505 {
00506         size_t tsize;
00507         omapi_object_t *foo;
00508         isc_result_t status;
00509 
00510         if (type -> allocator) {
00511                 foo = (omapi_object_t *)0;
00512                 status = (*type -> allocator) (&foo, file, line);
00513                 tsize = type -> size;
00514         } else {
00515                 status = ISC_R_NOMEMORY;
00516                 tsize = 0;
00517         }
00518 
00519         if (status == ISC_R_NOMEMORY) {
00520                 if (type -> sizer)
00521                         tsize = (*type -> sizer) (size);
00522                 else
00523                         tsize = type -> size;
00524                 
00525                 /* Sanity check. */
00526                 if (tsize < sizeof (omapi_object_t))
00527                         return DHCP_R_INVALIDARG;
00528                 
00529                 foo = dmalloc (tsize, file, line);
00530                 if (!foo)
00531                         return ISC_R_NOMEMORY;
00532         }
00533 
00534         status = omapi_object_initialize (foo, type, size, tsize, file, line);
00535         if (status != ISC_R_SUCCESS) {
00536                 if (type -> freer)
00537                         (*type -> freer) (foo, file, line);
00538                 else
00539                         dfree (foo, file, line);
00540                 return status;
00541         }
00542         return omapi_object_reference (o, foo, file, line);
00543 }
00544 
00545 isc_result_t omapi_object_initialize (omapi_object_t *o,
00546                                       omapi_object_type_t *type,
00547                                       size_t usize, size_t psize,
00548                                       const char *file, int line)
00549 {
00550         memset (o, 0, psize);
00551         o -> type = type;
00552         if (type -> initialize)
00553                 (*type -> initialize) (o, file, line);
00554         return ISC_R_SUCCESS;
00555 }
00556 
00557 isc_result_t omapi_object_reference (omapi_object_t **r,
00558                                      omapi_object_t *h,
00559                                      const char *file, int line)
00560 {
00561         if (!h || !r)
00562                 return DHCP_R_INVALIDARG;
00563 
00564         if (*r) {
00565 #if defined (POINTER_DEBUG)
00566                 log_error ("%s(%d): reference store into non-null pointer!",
00567                            file, line);
00568                 abort ();
00569 #else
00570                 return DHCP_R_INVALIDARG;
00571 #endif
00572         }
00573         *r = h;
00574         h -> refcnt++;
00575         rc_register (file, line, r, h, h -> refcnt, 0, h -> type -> rc_flag);
00576         return ISC_R_SUCCESS;
00577 }
00578 
00579 isc_result_t omapi_object_dereference (omapi_object_t **h,
00580                                        const char *file, int line)
00581 {
00582         int outer_reference = 0;
00583         int inner_reference = 0;
00584         int handle_reference = 0;
00585         int extra_references;
00586         omapi_object_t *p, *hp;
00587 
00588         if (!h)
00589                 return DHCP_R_INVALIDARG;
00590 
00591         if (!*h) {
00592 #if defined (POINTER_DEBUG)
00593                 log_error ("%s(%d): dereference of null pointer!", file, line);
00594                 abort ();
00595 #else
00596                 return DHCP_R_INVALIDARG;
00597 #endif
00598         }
00599         
00600         if ((*h) -> refcnt <= 0) {
00601 #if defined (POINTER_DEBUG)
00602                 log_error ("%s(%d): dereference of pointer with refcnt of zero!",
00603                            file, line);
00604 #if defined (DEBUG_RC_HISTORY)
00605                 dump_rc_history (*h);
00606 #endif
00607                 abort ();
00608 #else
00609                 *h = 0;
00610                 return DHCP_R_INVALIDARG;
00611 #endif
00612         }
00613         
00614         /* See if this object's inner object refers to it, but don't
00615            count this as a reference if we're being asked to free the
00616            reference from the inner object. */
00617         if ((*h) -> inner && (*h) -> inner -> outer &&
00618             h != &((*h) -> inner -> outer))
00619                 inner_reference = 1;
00620 
00621         /* Ditto for the outer object. */
00622         if ((*h) -> outer && (*h) -> outer -> inner &&
00623             h != &((*h) -> outer -> inner))
00624                 outer_reference = 1;
00625 
00626         /* Ditto for the outer object.  The code below assumes that
00627            the only reason we'd get a dereference from the handle
00628            table is if this function does it - otherwise we'd have to
00629            traverse the handle table to find the address where the
00630            reference is stored and compare against that, and we don't
00631            want to do that if we can avoid it. */
00632         if ((*h) -> handle)
00633                 handle_reference = 1;
00634 
00635         /* If we are getting rid of the last reference other than
00636            references to inner and outer objects, or from the handle
00637            table, then we must examine all the objects in either
00638            direction to see if they hold any non-inner, non-outer,
00639            non-handle-table references.  If not, we need to free the
00640            entire chain of objects. */
00641         if ((*h) -> refcnt ==
00642             inner_reference + outer_reference + handle_reference + 1) {
00643                 if (inner_reference || outer_reference || handle_reference) {
00644                         /* XXX we could check for a reference from the
00645                            handle table here. */
00646                         extra_references = 0;
00647                         for (p = (*h) -> inner;
00648                              p && !extra_references; p = p -> inner) {
00649                                 extra_references += p -> refcnt;
00650                                 if (p -> inner && p -> inner -> outer == p)
00651                                         --extra_references;
00652                                 if (p -> outer)
00653                                         --extra_references;
00654                                 if (p -> handle)
00655                                         --extra_references;
00656                         }
00657                         for (p = (*h) -> outer;
00658                              p && !extra_references; p = p -> outer) {
00659                                 extra_references += p -> refcnt;
00660                                 if (p -> outer && p -> outer -> inner == p)
00661                                         --extra_references;
00662                                 if (p -> inner)
00663                                         --extra_references;
00664                                 if (p -> handle)
00665                                         --extra_references;
00666                         }
00667                 } else
00668                         extra_references = 0;
00669 
00670                 if (!extra_references) {
00671                         hp = *h;
00672                         *h = 0;
00673                         hp -> refcnt--;
00674                         if (inner_reference)
00675                                 omapi_object_dereference
00676                                         (&hp -> inner, file, line);
00677                         if (outer_reference)
00678                                 omapi_object_dereference
00679                                         (&hp -> outer, file, line);
00680 /*                      if (!hp -> type -> freer) */
00681                                 rc_register (file, line, h, hp,
00682                                              0, 1, hp -> type -> rc_flag);
00683                         if (handle_reference) {
00684                                 if (omapi_handle_clear(hp->handle) != 
00685                                     ISC_R_SUCCESS) {
00686                                         log_debug("Attempt to clear null "
00687                                                   "handle pointer");
00688                                 }
00689                         }
00690                         if (hp -> type -> destroy)
00691                                 (*(hp -> type -> destroy)) (hp, file, line);
00692                         if (hp -> type -> freer)
00693                                 (hp -> type -> freer (hp, file, line));
00694                         else
00695                                 dfree (hp, file, line);
00696                 } else {
00697                         (*h) -> refcnt--;
00698 /*                      if (!(*h) -> type -> freer) */
00699                                 rc_register (file, line,
00700                                              h, *h, (*h) -> refcnt, 1,
00701                                              (*h) -> type -> rc_flag);
00702                 }
00703         } else {
00704                 (*h) -> refcnt--;
00705 /*              if (!(*h) -> type -> freer) */
00706                         rc_register (file, line, h, *h, (*h) -> refcnt, 1,
00707                                      (*h) -> type -> rc_flag);
00708         }
00709         *h = 0;
00710         return ISC_R_SUCCESS;
00711 }
00712 
00713 isc_result_t omapi_buffer_new (omapi_buffer_t **h,
00714                                const char *file, int line)
00715 {
00716         omapi_buffer_t *t;
00717         isc_result_t status;
00718         
00719         t = (omapi_buffer_t *)dmalloc (sizeof *t, file, line);
00720         if (!t)
00721                 return ISC_R_NOMEMORY;
00722         memset (t, 0, sizeof *t);
00723         status = omapi_buffer_reference (h, t, file, line);
00724         if (status != ISC_R_SUCCESS)
00725                 dfree (t, file, line);
00726         (*h) -> head = sizeof ((*h) -> buf) - 1;
00727         return status;
00728 }
00729 
00730 isc_result_t omapi_buffer_reference (omapi_buffer_t **r,
00731                                      omapi_buffer_t *h,
00732                                      const char *file, int line)
00733 {
00734         if (!h || !r)
00735                 return DHCP_R_INVALIDARG;
00736 
00737         if (*r) {
00738 #if defined (POINTER_DEBUG)
00739                 log_error ("%s(%d): reference store into non-null pointer!",
00740                            file, line);
00741                 abort ();
00742 #else
00743                 return DHCP_R_INVALIDARG;
00744 #endif
00745         }
00746         *r = h;
00747         h -> refcnt++;
00748         rc_register (file, line, r, h, h -> refcnt, 0, RC_MISC);
00749         return ISC_R_SUCCESS;
00750 }
00751 
00752 isc_result_t omapi_buffer_dereference (omapi_buffer_t **h,
00753                                        const char *file, int line)
00754 {
00755         if (!h)
00756                 return DHCP_R_INVALIDARG;
00757 
00758         if (!*h) {
00759 #if defined (POINTER_DEBUG)
00760                 log_error ("%s(%d): dereference of null pointer!", file, line);
00761                 abort ();
00762 #else
00763                 return DHCP_R_INVALIDARG;
00764 #endif
00765         }
00766         
00767         if ((*h) -> refcnt <= 0) {
00768 #if defined (POINTER_DEBUG)
00769                 log_error ("%s(%d): dereference of pointer with refcnt of zero!",
00770                            file, line);
00771 #if defined (DEBUG_RC_HISTORY)
00772                 dump_rc_history (*h);
00773 #endif
00774                 abort ();
00775 #else
00776                 *h = 0;
00777                 return DHCP_R_INVALIDARG;
00778 #endif
00779         }
00780 
00781         --(*h) -> refcnt;
00782         rc_register (file, line, h, *h, (*h) -> refcnt, 1, RC_MISC);
00783         if ((*h) -> refcnt == 0)
00784                 dfree (*h, file, line);
00785         *h = 0;
00786         return ISC_R_SUCCESS;
00787 }
00788 
00789 isc_result_t omapi_typed_data_new (const char *file, int line,
00790                                    omapi_typed_data_t **t,
00791                                    omapi_datatype_t type, ...)
00792 {
00793         va_list l;
00794         omapi_typed_data_t *new;
00795         unsigned len;
00796         unsigned val = 0;
00797         int intval = 0;
00798         char *s = NULL;
00799         isc_result_t status;
00800         omapi_object_t *obj = NULL;
00801 
00802         va_start (l, type);
00803 
00804         switch (type) {
00805               case omapi_datatype_int:
00806                 len = OMAPI_TYPED_DATA_INT_LEN;
00807                 intval = va_arg (l, int);
00808                 break;
00809               case omapi_datatype_string:
00810                 s = va_arg (l, char *);
00811                 val = strlen (s);
00812                 len = OMAPI_TYPED_DATA_NOBUFFER_LEN + val;
00813                 if (len < val) {
00814                         va_end(l);
00815                         return DHCP_R_INVALIDARG;
00816                 }
00817                 break;
00818               case omapi_datatype_data:
00819                 val = va_arg (l, unsigned);
00820                 len = OMAPI_TYPED_DATA_NOBUFFER_LEN + val;
00821                 if (len < val) {
00822                         va_end(l);
00823                         return DHCP_R_INVALIDARG;
00824                 }
00825                 break;
00826               case omapi_datatype_object:
00827                 len = OMAPI_TYPED_DATA_OBJECT_LEN;
00828                 obj = va_arg (l, omapi_object_t *);
00829                 break;
00830               default:
00831                 va_end (l);
00832                 return DHCP_R_INVALIDARG;
00833         }
00834         va_end (l);
00835 
00836         new = dmalloc (len, file, line);
00837         if (!new)
00838                 return ISC_R_NOMEMORY;
00839         memset (new, 0, len);
00840 
00841         switch (type) {
00842               case omapi_datatype_int:
00843                 new -> u.integer = intval;
00844                 break;
00845               case omapi_datatype_string:
00846                 memcpy (new -> u.buffer.value, s, val);
00847                 new -> u.buffer.len = val;
00848                 break;
00849               case omapi_datatype_data:
00850                 new -> u.buffer.len = val;
00851                 break;
00852               case omapi_datatype_object:
00853                 status = omapi_object_reference (&new -> u.object, obj,
00854                                                  file, line);
00855                 if (status != ISC_R_SUCCESS) {
00856                         dfree (new, file, line);
00857                         return status;
00858                 }
00859                 break;
00860         }
00861         new -> type = type;
00862 
00863         return omapi_typed_data_reference (t, new, file, line);
00864 }
00865 
00866 isc_result_t omapi_typed_data_reference (omapi_typed_data_t **r,
00867                                          omapi_typed_data_t *h,
00868                                          const char *file, int line)
00869 {
00870         if (!h || !r)
00871                 return DHCP_R_INVALIDARG;
00872 
00873         if (*r) {
00874 #if defined (POINTER_DEBUG)
00875                 log_error ("%s(%d): reference store into non-null pointer!", file, line);
00876                 abort ();
00877 #else
00878                 return DHCP_R_INVALIDARG;
00879 #endif
00880         }
00881         *r = h;
00882         h -> refcnt++;
00883         rc_register (file, line, r, h, h -> refcnt, 0, RC_MISC);
00884         return ISC_R_SUCCESS;
00885 }
00886 
00887 isc_result_t omapi_typed_data_dereference (omapi_typed_data_t **h,
00888                                            const char *file, int line)
00889 {
00890         if (!h)
00891                 return DHCP_R_INVALIDARG;
00892 
00893         if (!*h) {
00894 #if defined (POINTER_DEBUG)
00895                 log_error ("%s(%d): dereference of null pointer!", file, line);
00896                 abort ();
00897 #else
00898                 return DHCP_R_INVALIDARG;
00899 #endif
00900         }
00901         
00902         if ((*h) -> refcnt <= 0) {
00903 #if defined (POINTER_DEBUG)
00904                 log_error ("%s(%d): dereference of pointer with refcnt of zero!",
00905                            file, line);
00906 #if defined (DEBUG_RC_HISTORY)
00907                 dump_rc_history (*h);
00908 #endif
00909                 abort ();
00910 #else
00911                 *h = 0;
00912                 return DHCP_R_INVALIDARG;
00913 #endif
00914         }
00915         
00916         --((*h) -> refcnt);
00917         rc_register (file, line, h, *h, (*h) -> refcnt, 1, RC_MISC);
00918         if ((*h) -> refcnt <= 0 ) {
00919                 switch ((*h) -> type) {
00920                       case omapi_datatype_int:
00921                       case omapi_datatype_string:
00922                       case omapi_datatype_data:
00923                       default:
00924                         break;
00925                       case omapi_datatype_object:
00926                         omapi_object_dereference (&(*h) -> u.object,
00927                                                   file, line);
00928                         break;
00929                 }
00930                 dfree (*h, file, line);
00931         }
00932         *h = 0;
00933         return ISC_R_SUCCESS;
00934 }
00935 
00936 isc_result_t omapi_data_string_new (omapi_data_string_t **d, unsigned len,
00937                                     const char *file, int line)
00938 {
00939         omapi_data_string_t *new;
00940         unsigned nlen;
00941 
00942         nlen = OMAPI_DATA_STRING_EMPTY_SIZE + len;
00943         if (nlen < len)
00944                 return DHCP_R_INVALIDARG;
00945         new = dmalloc (nlen, file, line);
00946         if (!new)
00947                 return ISC_R_NOMEMORY;
00948         memset (new, 0, OMAPI_DATA_STRING_EMPTY_SIZE);
00949         new -> len = len;
00950         return omapi_data_string_reference (d, new, file, line);
00951 }
00952 
00953 isc_result_t omapi_data_string_reference (omapi_data_string_t **r,
00954                                           omapi_data_string_t *h,
00955                                           const char *file, int line)
00956 {
00957         if (!h || !r)
00958                 return DHCP_R_INVALIDARG;
00959 
00960         if (*r) {
00961 #if defined (POINTER_DEBUG)
00962                 log_error ("%s(%d): reference store into non-null pointer!", file, line);
00963                 abort ();
00964 #else
00965                 return DHCP_R_INVALIDARG;
00966 #endif
00967         }
00968         *r = h;
00969         h -> refcnt++;
00970         rc_register (file, line, r, h, h -> refcnt, 0, RC_MISC);
00971         return ISC_R_SUCCESS;
00972 }
00973 
00974 isc_result_t omapi_data_string_dereference (omapi_data_string_t **h,
00975                                             const char *file, int line)
00976 {
00977         if (!h)
00978                 return DHCP_R_INVALIDARG;
00979 
00980         if (!*h) {
00981 #if defined (POINTER_DEBUG)
00982                 log_error ("%s(%d): dereference of null pointer!", file, line);
00983                 abort ();
00984 #else
00985                 return DHCP_R_INVALIDARG;
00986 #endif
00987         }
00988         
00989         if ((*h) -> refcnt <= 0) {
00990 #if defined (POINTER_DEBUG)
00991                 log_error ("%s(%d): dereference of pointer with refcnt of zero!",
00992                            file, line);
00993 #if defined (DEBUG_RC_HISTORY)
00994                 dump_rc_history (*h);
00995 #endif
00996                 abort ();
00997 #else
00998                 *h = 0;
00999                 return DHCP_R_INVALIDARG;
01000 #endif
01001         }
01002 
01003         --((*h) -> refcnt);
01004         rc_register (file, line, h, *h, (*h) -> refcnt, 1, RC_MISC);
01005         if ((*h) -> refcnt <= 0 ) {
01006                 dfree (*h, file, line);
01007         }
01008         *h = 0;
01009         return ISC_R_SUCCESS;
01010 }
01011 
01012 isc_result_t omapi_value_new (omapi_value_t **d,
01013                               const char *file, int line)
01014 {
01015         omapi_value_t *new;
01016 
01017         new = dmalloc (sizeof *new, file, line);
01018         if (!new)
01019                 return ISC_R_NOMEMORY;
01020         memset (new, 0, sizeof *new);
01021         return omapi_value_reference (d, new, file, line);
01022 }
01023 
01024 isc_result_t omapi_value_reference (omapi_value_t **r,
01025                                     omapi_value_t *h,
01026                                     const char *file, int line)
01027 {
01028         if (!h || !r)
01029                 return DHCP_R_INVALIDARG;
01030 
01031         if (*r) {
01032 #if defined (POINTER_DEBUG)
01033                 log_error ("%s(%d): reference store into non-null pointer!",
01034                            file, line);
01035                 abort ();
01036 #else
01037                 return DHCP_R_INVALIDARG;
01038 #endif
01039         }
01040         *r = h;
01041         h -> refcnt++;
01042         rc_register (file, line, r, h, h -> refcnt, 0, RC_MISC);
01043         return ISC_R_SUCCESS;
01044 }
01045 
01046 isc_result_t omapi_value_dereference (omapi_value_t **h,
01047                                       const char *file, int line)
01048 {
01049         if (!h)
01050                 return DHCP_R_INVALIDARG;
01051 
01052         if (!*h) {
01053 #if defined (POINTER_DEBUG)
01054                 log_error ("%s(%d): dereference of null pointer!", file, line);
01055                 abort ();
01056 #else
01057                 return DHCP_R_INVALIDARG;
01058 #endif
01059         }
01060         
01061         if ((*h) -> refcnt <= 0) {
01062 #if defined (POINTER_DEBUG)
01063                 log_error ("%s(%d): dereference of pointer with refcnt of zero!",
01064                            file, line);
01065 #if defined (DEBUG_RC_HISTORY)
01066                 dump_rc_history (*h);
01067 #endif
01068                 abort ();
01069 #else
01070                 *h = 0;
01071                 return DHCP_R_INVALIDARG;
01072 #endif
01073         }
01074         
01075         --((*h) -> refcnt);
01076         rc_register (file, line, h, *h, (*h) -> refcnt, 1, RC_MISC);
01077         if ((*h) -> refcnt == 0) {
01078                 if ((*h) -> name)
01079                         omapi_data_string_dereference (&(*h) -> name,
01080                                                        file, line);
01081                 if ((*h) -> value)
01082                         omapi_typed_data_dereference (&(*h) -> value,
01083                                                       file, line);
01084                 dfree (*h, file, line);
01085         }
01086         *h = 0;
01087         return ISC_R_SUCCESS;
01088 }
01089 
01090 isc_result_t omapi_addr_list_new (omapi_addr_list_t **d, unsigned count,
01091                                   const char *file, int line)
01092 {
01093         omapi_addr_list_t *new;
01094 
01095         new = dmalloc ((count * sizeof (omapi_addr_t)) +
01096                        sizeof (omapi_addr_list_t), file, line);
01097         if (!new)
01098                 return ISC_R_NOMEMORY;
01099         memset (new, 0, ((count * sizeof (omapi_addr_t)) +
01100                          sizeof (omapi_addr_list_t)));
01101         new -> count = count;
01102         new -> addresses = (omapi_addr_t *)(new + 1);
01103         return omapi_addr_list_reference (d, new, file, line);
01104 }
01105 
01106 isc_result_t omapi_addr_list_reference (omapi_addr_list_t **r,
01107                                           omapi_addr_list_t *h,
01108                                           const char *file, int line)
01109 {
01110         if (!h || !r)
01111                 return DHCP_R_INVALIDARG;
01112 
01113         if (*r) {
01114 #if defined (POINTER_DEBUG)
01115                 log_error ("%s(%d): reference store into non-null pointer!",
01116                            file, line);
01117                 abort ();
01118 #else
01119                 return DHCP_R_INVALIDARG;
01120 #endif
01121         }
01122         *r = h;
01123         h -> refcnt++;
01124         rc_register (file, line, r, h, h -> refcnt, 0, RC_MISC);
01125         return ISC_R_SUCCESS;
01126 }
01127 
01128 isc_result_t omapi_addr_list_dereference (omapi_addr_list_t **h,
01129                                             const char *file, int line)
01130 {
01131         if (!h)
01132                 return DHCP_R_INVALIDARG;
01133 
01134         if (!*h) {
01135 #if defined (POINTER_DEBUG)
01136                 log_error ("%s(%d): dereference of null pointer!", file, line);
01137                 abort ();
01138 #else
01139                 return DHCP_R_INVALIDARG;
01140 #endif
01141         }
01142         
01143         if ((*h) -> refcnt <= 0) {
01144 #if defined (POINTER_DEBUG)
01145                 log_error ("%s(%d): dereference of pointer with zero refcnt!",
01146                            file, line);
01147 #if defined (DEBUG_RC_HISTORY)
01148                 dump_rc_history (*h);
01149 #endif
01150                 abort ();
01151 #else
01152                 *h = 0;
01153                 return DHCP_R_INVALIDARG;
01154 #endif
01155         }
01156 
01157         --((*h) -> refcnt);
01158         rc_register (file, line, h, *h, (*h) -> refcnt, 1, RC_MISC);
01159         if ((*h) -> refcnt <= 0 ) {
01160                 dfree (*h, file, line);
01161         }
01162         *h = 0;
01163         return ISC_R_SUCCESS;
01164 }
01165 

Generated on 5 Apr 2014 for ISC DHCP by  doxygen 1.6.1