Annotation of embedaddon/ntp/libntp/recvbuff.c, revision 1.1

1.1     ! misho       1: #ifdef HAVE_CONFIG_H
        !             2: # include <config.h>
        !             3: #endif
        !             4: 
        !             5: #include <stdio.h>
        !             6: #include "ntp_machine.h"
        !             7: #include "ntp_assert.h"
        !             8: #include "ntp_fp.h"
        !             9: #include "ntp_syslog.h"
        !            10: #include "ntp_stdlib.h"
        !            11: #include "ntp_io.h"
        !            12: #include "ntp_lists.h"
        !            13: #include "recvbuff.h"
        !            14: #include "iosignal.h"
        !            15: 
        !            16: 
        !            17: 
        !            18: #ifdef DEBUG
        !            19: static void uninit_recvbuff(void);
        !            20: #endif
        !            21: 
        !            22: /*
        !            23:  * Memory allocation
        !            24:  */
        !            25: static u_long volatile full_recvbufs;  /* number of recvbufs on fulllist */
        !            26: static u_long volatile free_recvbufs;  /* number of recvbufs on freelist */
        !            27: static u_long volatile total_recvbufs; /* total recvbufs currently in use */
        !            28: static u_long volatile lowater_adds;   /* number of times we have added memory */
        !            29: static u_long volatile buffer_shortfall;/* number of missed free receive buffers
        !            30:                                           between replenishments */
        !            31: 
        !            32: static ISC_LIST(recvbuf_t)     full_recv_list; /* Currently used recv buffers */
        !            33: static recvbuf_t *             free_recv_list; /* Currently unused buffers */
        !            34:        
        !            35: #if defined(SYS_WINNT)
        !            36: 
        !            37: /*
        !            38:  * For Windows we need to set up a lock to manipulate the
        !            39:  * recv buffers to prevent corruption. We keep it lock for as
        !            40:  * short a time as possible
        !            41:  */
        !            42: static CRITICAL_SECTION RecvLock;
        !            43: # define LOCK()                EnterCriticalSection(&RecvLock)
        !            44: # define UNLOCK()      LeaveCriticalSection(&RecvLock)
        !            45: #else
        !            46: # define LOCK()        
        !            47: # define UNLOCK()      
        !            48: #endif
        !            49: 
        !            50: u_long
        !            51: free_recvbuffs (void)
        !            52: {
        !            53:        return free_recvbufs;
        !            54: }
        !            55: 
        !            56: u_long
        !            57: full_recvbuffs (void)
        !            58: {
        !            59:        return full_recvbufs;
        !            60: }
        !            61: 
        !            62: u_long
        !            63: total_recvbuffs (void)
        !            64: {
        !            65:        return total_recvbufs;
        !            66: }
        !            67: 
        !            68: u_long
        !            69: lowater_additions(void)
        !            70: {
        !            71:        return lowater_adds;
        !            72: }
        !            73: 
        !            74: static inline void 
        !            75: initialise_buffer(recvbuf_t *buff)
        !            76: {
        !            77:        memset(buff, 0, sizeof(*buff));
        !            78: }
        !            79: 
        !            80: static void
        !            81: create_buffers(int nbufs)
        !            82: {
        !            83:        register recvbuf_t *bufp;
        !            84:        int i, abuf;
        !            85: 
        !            86:        abuf = nbufs + buffer_shortfall;
        !            87:        buffer_shortfall = 0;
        !            88: 
        !            89: #ifndef DEBUG
        !            90:        bufp = emalloc(abuf * sizeof(*bufp));
        !            91: #endif
        !            92: 
        !            93:        for (i = 0; i < abuf; i++) {
        !            94: #ifdef DEBUG
        !            95:                /*
        !            96:                 * Allocate each buffer individually so they can be
        !            97:                 * free()d during ntpd shutdown on DEBUG builds to
        !            98:                 * keep them out of heap leak reports.
        !            99:                 */
        !           100:                bufp = emalloc(sizeof(*bufp));
        !           101: #endif
        !           102:                memset(bufp, 0, sizeof(*bufp));
        !           103:                LINK_SLIST(free_recv_list, bufp, link.next);
        !           104:                bufp++;
        !           105:                free_recvbufs++;
        !           106:                total_recvbufs++;
        !           107:        }
        !           108:        lowater_adds++;
        !           109: }
        !           110: 
        !           111: void
        !           112: init_recvbuff(int nbufs)
        !           113: {
        !           114: 
        !           115:        /*
        !           116:         * Init buffer free list and stat counters
        !           117:         */
        !           118:        ISC_LIST_INIT(full_recv_list);
        !           119:        free_recvbufs = total_recvbufs = 0;
        !           120:        full_recvbufs = lowater_adds = 0;
        !           121: 
        !           122:        create_buffers(nbufs);
        !           123: 
        !           124: #if defined(SYS_WINNT)
        !           125:        InitializeCriticalSection(&RecvLock);
        !           126: #endif
        !           127: 
        !           128: #ifdef DEBUG
        !           129:        atexit(&uninit_recvbuff);
        !           130: #endif
        !           131: }
        !           132: 
        !           133: 
        !           134: #ifdef DEBUG
        !           135: static void
        !           136: uninit_recvbuff(void)
        !           137: {
        !           138:        recvbuf_t *rbunlinked;
        !           139: 
        !           140:        while ((rbunlinked = ISC_LIST_HEAD(full_recv_list)) != NULL) {
        !           141:                ISC_LIST_DEQUEUE_TYPE(full_recv_list, rbunlinked, link, recvbuf_t);
        !           142:                free(rbunlinked);
        !           143:        }
        !           144: 
        !           145:        do {
        !           146:                UNLINK_HEAD_SLIST(rbunlinked, free_recv_list, link.next);
        !           147:                if (rbunlinked != NULL)
        !           148:                        free(rbunlinked);
        !           149:        } while (rbunlinked != NULL);
        !           150: }
        !           151: #endif /* DEBUG */
        !           152: 
        !           153: 
        !           154: /*
        !           155:  * freerecvbuf - make a single recvbuf available for reuse
        !           156:  */
        !           157: void
        !           158: freerecvbuf(recvbuf_t *rb)
        !           159: {
        !           160:        if (rb == NULL) {
        !           161:                msyslog(LOG_ERR, "freerecvbuff received NULL buffer");
        !           162:                return;
        !           163:        }
        !           164: 
        !           165:        LOCK();
        !           166:        (rb->used)--;
        !           167:        if (rb->used != 0)
        !           168:                msyslog(LOG_ERR, "******** freerecvbuff non-zero usage: %d *******", rb->used);
        !           169:        LINK_SLIST(free_recv_list, rb, link.next);
        !           170:        free_recvbufs++;
        !           171:        UNLOCK();
        !           172: }
        !           173: 
        !           174:        
        !           175: void
        !           176: add_full_recv_buffer(recvbuf_t *rb)
        !           177: {
        !           178:        if (rb == NULL) {
        !           179:                msyslog(LOG_ERR, "add_full_recv_buffer received NULL buffer");
        !           180:                return;
        !           181:        }
        !           182:        LOCK();
        !           183:        ISC_LINK_INIT(rb, link);
        !           184:        ISC_LIST_APPEND(full_recv_list, rb, link);
        !           185:        full_recvbufs++;
        !           186:        UNLOCK();
        !           187: }
        !           188: 
        !           189: recvbuf_t *
        !           190: get_free_recv_buffer(void)
        !           191: {
        !           192:        recvbuf_t *buffer;
        !           193: 
        !           194:        LOCK();
        !           195:        UNLINK_HEAD_SLIST(buffer, free_recv_list, link.next);
        !           196:        if (buffer != NULL) {
        !           197:                free_recvbufs--;
        !           198:                initialise_buffer(buffer);
        !           199:                (buffer->used)++;
        !           200:        } else
        !           201:                buffer_shortfall++;
        !           202:        UNLOCK();
        !           203:        return (buffer);
        !           204: }
        !           205: 
        !           206: #ifdef HAVE_IO_COMPLETION_PORT
        !           207: recvbuf_t *
        !           208: get_free_recv_buffer_alloc(void)
        !           209: {
        !           210:        recvbuf_t *buffer;
        !           211:        
        !           212:        buffer = get_free_recv_buffer();
        !           213:        if (NULL == buffer) {
        !           214:                create_buffers(RECV_INC);
        !           215:                buffer = get_free_recv_buffer();
        !           216:        }
        !           217:        NTP_ENSURE(buffer != NULL);
        !           218:        return (buffer);
        !           219: }
        !           220: #endif
        !           221: 
        !           222: recvbuf_t *
        !           223: get_full_recv_buffer(void)
        !           224: {
        !           225:        recvbuf_t *rbuf;
        !           226:        LOCK();
        !           227:        
        !           228: #ifdef HAVE_SIGNALED_IO
        !           229:        /*
        !           230:         * make sure there are free buffers when we
        !           231:         * wander off to do lengthy packet processing with
        !           232:         * any buffer we grab from the full list.
        !           233:         * 
        !           234:         * fixes malloc() interrupted by SIGIO risk
        !           235:         * (Bug 889)
        !           236:         */
        !           237:        if (NULL == free_recv_list || buffer_shortfall > 0) {
        !           238:                /*
        !           239:                 * try to get us some more buffers
        !           240:                 */
        !           241:                create_buffers(RECV_INC);
        !           242:        }
        !           243: #endif
        !           244: 
        !           245:        /*
        !           246:         * try to grab a full buffer
        !           247:         */
        !           248:        rbuf = ISC_LIST_HEAD(full_recv_list);
        !           249:        if (rbuf != NULL) {
        !           250:                ISC_LIST_DEQUEUE_TYPE(full_recv_list, rbuf, link, recvbuf_t);
        !           251:                --full_recvbufs;
        !           252:        } else
        !           253:                /*
        !           254:                 * Make sure we reset the full count to 0
        !           255:                 */
        !           256:                full_recvbufs = 0;
        !           257:        UNLOCK();
        !           258:        return (rbuf);
        !           259: }
        !           260: 
        !           261: /*
        !           262:  * Checks to see if there are buffers to process
        !           263:  */
        !           264: isc_boolean_t has_full_recv_buffer(void)
        !           265: {
        !           266:        if (ISC_LIST_HEAD(full_recv_list) != NULL)
        !           267:                return (ISC_TRUE);
        !           268:        else
        !           269:                return (ISC_FALSE);
        !           270: }

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>