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>