diff options
Diffstat (limited to 'contrib/ntp/libntp/recvbuff.c')
-rw-r--r-- | contrib/ntp/libntp/recvbuff.c | 204 |
1 files changed, 142 insertions, 62 deletions
diff --git a/contrib/ntp/libntp/recvbuff.c b/contrib/ntp/libntp/recvbuff.c index 6665686fe068..83a9ee193a3b 100644 --- a/contrib/ntp/libntp/recvbuff.c +++ b/contrib/ntp/libntp/recvbuff.c @@ -3,27 +3,27 @@ #endif #include <stdio.h> -#include "ntp_machine.h" -#include "ntp_fp.h" + +#include "ntp_assert.h" #include "ntp_syslog.h" #include "ntp_stdlib.h" -#include "ntp_io.h" +#include "ntp_lists.h" #include "recvbuff.h" #include "iosignal.h" -#include <isc/list.h> + /* * Memory allocation */ -static u_long volatile full_recvbufs; /* number of recvbufs on fulllist */ -static u_long volatile free_recvbufs; /* number of recvbufs on freelist */ +static u_long volatile full_recvbufs; /* recvbufs on full_recv_fifo */ +static u_long volatile free_recvbufs; /* recvbufs on free_recv_list */ static u_long volatile total_recvbufs; /* total recvbufs currently in use */ static u_long volatile lowater_adds; /* number of times we have added memory */ static u_long volatile buffer_shortfall;/* number of missed free receive buffers - between replenishments */ + between replenishments */ -static ISC_LIST(recvbuf_t) full_recv_list; /* Currently used recv buffers */ -static ISC_LIST(recvbuf_t) free_recv_list; /* Currently unused buffers */ +static DECL_FIFO_ANCHOR(recvbuf_t) full_recv_fifo; +static recvbuf_t * free_recv_list; #if defined(SYS_WINNT) @@ -36,10 +36,15 @@ static CRITICAL_SECTION RecvLock; # define LOCK() EnterCriticalSection(&RecvLock) # define UNLOCK() LeaveCriticalSection(&RecvLock) #else -# define LOCK() -# define UNLOCK() +# define LOCK() do {} while (FALSE) +# define UNLOCK() do {} while (FALSE) +#endif + +#ifdef DEBUG +static void uninit_recvbuff(void); #endif + u_long free_recvbuffs (void) { @@ -64,15 +69,10 @@ lowater_additions(void) return lowater_adds; } -static void +static inline void initialise_buffer(recvbuf_t *buff) { - memset((char *) buff, 0, sizeof(recvbuf_t)); - -#if defined SYS_WINNT - buff->wsabuff.len = RX_BUFF_SIZE; - buff->wsabuff.buf = (char *) buff->recv_buffer; -#endif + ZERO(*buff); } static void @@ -84,12 +84,20 @@ create_buffers(int nbufs) abuf = nbufs + buffer_shortfall; buffer_shortfall = 0; - bufp = (recvbuf_t *) emalloc(abuf*sizeof(recvbuf_t)); +#ifndef DEBUG + bufp = emalloc_zero(abuf * sizeof(*bufp)); +#endif - for (i = 0; i < abuf; i++) - { - memset((char *) bufp, 0, sizeof(recvbuf_t)); - ISC_LIST_APPEND(free_recv_list, bufp, link); + for (i = 0; i < abuf; i++) { +#ifdef DEBUG + /* + * Allocate each buffer individually so they can be + * free()d during ntpd shutdown on DEBUG builds to + * keep them out of heap leak reports. + */ + bufp = emalloc_zero(sizeof(*bufp)); +#endif + LINK_SLIST(free_recv_list, bufp, link); bufp++; free_recvbufs++; total_recvbufs++; @@ -104,8 +112,6 @@ init_recvbuff(int nbufs) /* * Init buffer free list and stat counters */ - ISC_LIST_INIT(full_recv_list); - ISC_LIST_INIT(free_recv_list); free_recvbufs = total_recvbufs = 0; full_recvbufs = lowater_adds = 0; @@ -115,7 +121,34 @@ init_recvbuff(int nbufs) InitializeCriticalSection(&RecvLock); #endif +#ifdef DEBUG + atexit(&uninit_recvbuff); +#endif +} + + +#ifdef DEBUG +static void +uninit_recvbuff(void) +{ + recvbuf_t *rbunlinked; + + for (;;) { + UNLINK_FIFO(rbunlinked, full_recv_fifo, link); + if (rbunlinked == NULL) + break; + free(rbunlinked); + } + + for (;;) { + UNLINK_HEAD_SLIST(rbunlinked, free_recv_list, link); + if (rbunlinked == NULL) + break; + free(rbunlinked); + } } +#endif /* DEBUG */ + /* * freerecvbuf - make a single recvbuf available for reuse @@ -129,14 +162,10 @@ freerecvbuf(recvbuf_t *rb) } LOCK(); - (rb->used)--; + rb->used--; if (rb->used != 0) msyslog(LOG_ERR, "******** freerecvbuff non-zero usage: %d *******", rb->used); - ISC_LIST_APPEND(free_recv_list, rb, link); -#if defined SYS_WINNT - rb->wsabuff.len = RX_BUFF_SIZE; - rb->wsabuff.buf = (char *) rb->recv_buffer; -#endif + LINK_SLIST(free_recv_list, rb, link); free_recvbufs++; UNLOCK(); } @@ -150,63 +179,66 @@ add_full_recv_buffer(recvbuf_t *rb) return; } LOCK(); - ISC_LIST_APPEND(full_recv_list, rb, link); + LINK_FIFO(full_recv_fifo, rb, link); full_recvbufs++; UNLOCK(); } + recvbuf_t * get_free_recv_buffer(void) { - recvbuf_t * buffer = NULL; + recvbuf_t *buffer; + LOCK(); - buffer = ISC_LIST_HEAD(free_recv_list); - if (buffer != NULL) - { - ISC_LIST_DEQUEUE(free_recv_list, buffer, link); + UNLINK_HEAD_SLIST(buffer, free_recv_list, link); + if (buffer != NULL) { free_recvbufs--; initialise_buffer(buffer); - (buffer->used)++; - } - else - { + buffer->used++; + } else { buffer_shortfall++; } UNLOCK(); - return (buffer); + + return buffer; } + #ifdef HAVE_IO_COMPLETION_PORT recvbuf_t * get_free_recv_buffer_alloc(void) { - recvbuf_t * buffer = get_free_recv_buffer(); - if (buffer == NULL) - { + recvbuf_t *buffer; + + buffer = get_free_recv_buffer(); + if (NULL == buffer) { create_buffers(RECV_INC); buffer = get_free_recv_buffer(); } + NTP_ENSURE(buffer != NULL); return (buffer); } #endif + recvbuf_t * get_full_recv_buffer(void) { - recvbuf_t *rbuf; + recvbuf_t * rbuf; + LOCK(); #ifdef HAVE_SIGNALED_IO /* * make sure there are free buffers when we - * wander off to do lengthy paket processing with + * wander off to do lengthy packet processing with * any buffer we grab from the full list. * * fixes malloc() interrupted by SIGIO risk * (Bug 889) */ - rbuf = ISC_LIST_HEAD(free_recv_list); - if (rbuf == NULL || buffer_shortfall > 0) { + if (NULL == free_recv_list || buffer_shortfall > 0) { /* * try to get us some more buffers */ @@ -217,30 +249,78 @@ get_full_recv_buffer(void) /* * try to grab a full buffer */ - rbuf = ISC_LIST_HEAD(full_recv_list); + UNLINK_FIFO(rbuf, full_recv_fifo, link); if (rbuf != NULL) - { - ISC_LIST_DEQUEUE(full_recv_list, rbuf, link); - --full_recvbufs; - } - else - { - /* - * Make sure we reset the full count to 0 - */ - full_recvbufs = 0; + full_recvbufs--; + UNLOCK(); + + return rbuf; +} + + +/* + * purge_recv_buffers_for_fd() - purges any previously-received input + * from a given file descriptor. + */ +void +purge_recv_buffers_for_fd( + SOCKET fd + ) +{ + recvbuf_t *rbufp; + recvbuf_t *next; + recvbuf_t *punlinked; + + LOCK(); + + for (rbufp = HEAD_FIFO(full_recv_fifo); + rbufp != NULL; + rbufp = next) { + next = rbufp->link; + if (rbufp->fd == fd) { + UNLINK_MID_FIFO(punlinked, full_recv_fifo, + rbufp, link, recvbuf_t); + INSIST(punlinked == rbufp); + full_recvbufs--; + freerecvbuf(rbufp); + } } + UNLOCK(); - return (rbuf); } + /* * Checks to see if there are buffers to process */ isc_boolean_t has_full_recv_buffer(void) { - if (ISC_LIST_HEAD(full_recv_list) != NULL) + if (HEAD_FIFO(full_recv_fifo) != NULL) return (ISC_TRUE); else return (ISC_FALSE); } + + +#ifdef NTP_DEBUG_LISTS_H +void +check_gen_fifo_consistency(void *fifo) +{ + gen_fifo *pf; + gen_node *pthis; + gen_node **pptail; + + pf = fifo; + REQUIRE((NULL == pf->phead && NULL == pf->pptail) || + (NULL != pf->phead && NULL != pf->pptail)); + + pptail = &pf->phead; + for (pthis = pf->phead; + pthis != NULL; + pthis = pthis->link) + if (NULL != pthis->link) + pptail = &pthis->link; + + REQUIRE(NULL == pf->pptail || pptail == pf->pptail); +} +#endif /* NTP_DEBUG_LISTS_H */ |