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>