Annotation of embedaddon/ntp/libntp/recvbuff.c, revision 1.1.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>