"Fossies" - the Fresh Open Source Software Archive  

Source code changes of the file "libntp/recvbuff.c" between
ntp-4.2.8p14.tar.gz and ntp-4.2.8p15.tar.gz

About: NTP is the the Official Reference Implementation of the Network Time Protocol (NTP) that synchronize the clocks of computers over a network.

recvbuff.c  (ntp-4.2.8p14):recvbuff.c  (ntp-4.2.8p15)
skipping to change at line 14 skipping to change at line 14
#include <stdio.h> #include <stdio.h>
#include "ntp_assert.h" #include "ntp_assert.h"
#include "ntp_syslog.h" #include "ntp_syslog.h"
#include "ntp_stdlib.h" #include "ntp_stdlib.h"
#include "ntp_lists.h" #include "ntp_lists.h"
#include "recvbuff.h" #include "recvbuff.h"
#include "iosignal.h" #include "iosignal.h"
#if (RECV_INC & (RECV_INC-1))
# error RECV_INC not a power of 2!
#endif
#if (RECV_BATCH & (RECV_BATCH - 1))
#error RECV_BATCH not a power of 2!
#endif
#if (RECV_BATCH < RECV_INC)
#error RECV_BATCH must be >= RECV_INC!
#endif
/* /*
* Memory allocation * Memory allocation
*/ */
static u_long volatile full_recvbufs; /* recvbufs on full_recv_fifo */ 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 free_recvbufs; /* recvbufs on free_recv_list */
static u_long volatile total_recvbufs; /* total recvbufs currently in use */ 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 lowater_adds; /* number of times we have added memory * /
static u_long volatile buffer_shortfall;/* number of missed free receive buffers static u_long volatile buffer_shortfall;/* number of missed free receive buffers
between replenishments */ between replenishments */
static u_long limit_recvbufs; /* maximum total of receive buffers */
static u_long emerg_recvbufs; /* emergency/urgent buffers to keep */
static DECL_FIFO_ANCHOR(recvbuf_t) full_recv_fifo; static DECL_FIFO_ANCHOR(recvbuf_t) full_recv_fifo;
static recvbuf_t * free_recv_list; static recvbuf_t * free_recv_list;
#if defined(SYS_WINNT) #if defined(SYS_WINNT)
/* /*
* For Windows we need to set up a lock to manipulate the * For Windows we need to set up a lock to manipulate the
* recv buffers to prevent corruption. We keep it lock for as * recv buffers to prevent corruption. We keep it lock for as
* short a time as possible * short a time as possible
*/ */
static CRITICAL_SECTION RecvLock; static CRITICAL_SECTION RecvLock;
# define LOCK() EnterCriticalSection(&RecvLock) static CRITICAL_SECTION FreeLock;
# define UNLOCK() LeaveCriticalSection(&RecvLock) # define LOCK_R() EnterCriticalSection(&RecvLock)
# define UNLOCK_R() LeaveCriticalSection(&RecvLock)
# define LOCK_F() EnterCriticalSection(&FreeLock)
# define UNLOCK_F() LeaveCriticalSection(&FreeLock)
#else #else
# define LOCK() do {} while (FALSE) # define LOCK_R() do {} while (FALSE)
# define UNLOCK() do {} while (FALSE) # define UNLOCK_R() do {} while (FALSE)
# define LOCK_F() do {} while (FALSE)
# define UNLOCK_F() do {} while (FALSE)
#endif #endif
#ifdef DEBUG #ifdef DEBUG
static void uninit_recvbuff(void); static void uninit_recvbuff(void);
#endif #endif
u_long u_long
free_recvbuffs (void) free_recvbuffs (void)
{ {
return free_recvbufs; return free_recvbufs;
skipping to change at line 77 skipping to change at line 94
return lowater_adds; return lowater_adds;
} }
static inline void static inline void
initialise_buffer(recvbuf_t *buff) initialise_buffer(recvbuf_t *buff)
{ {
ZERO(*buff); ZERO(*buff);
} }
static void static void
create_buffers(int nbufs) create_buffers(
size_t nbufs)
{ {
# ifndef DEBUG
static const u_int chunk = RECV_INC;
# else
/* Allocate each buffer individually so they can be free()d
* during ntpd shutdown on DEBUG builds to keep them out of heap
* leak reports.
*/
static const u_int chunk = 1;
# endif
register recvbuf_t *bufp; register recvbuf_t *bufp;
int i, abuf; u_int i;
size_t abuf;
if (limit_recvbufs <= total_recvbufs)
return;
abuf = nbufs + buffer_shortfall; abuf = nbufs + buffer_shortfall;
buffer_shortfall = 0; buffer_shortfall = 0;
#ifndef DEBUG if (abuf < nbufs || abuf > RECV_BATCH)
bufp = eallocarray(abuf, sizeof(*bufp)); abuf = RECV_BATCH; /* clamp on overflow */
#endif else
abuf += (~abuf + 1) & (RECV_INC - 1); /* round up */
for (i = 0; i < abuf; i++) { if (abuf > (limit_recvbufs - total_recvbufs))
#ifdef DEBUG abuf = limit_recvbufs - total_recvbufs;
/* abuf += (~abuf + 1) & (chunk - 1); /* round up */
* Allocate each buffer individually so they can be
* free()d during ntpd shutdown on DEBUG builds to while (abuf) {
* keep them out of heap leak reports. bufp = calloc(chunk, sizeof(*bufp));
*/ if (!bufp) {
bufp = emalloc_zero(sizeof(*bufp)); limit_recvbufs = total_recvbufs;
#endif break;
LINK_SLIST(free_recv_list, bufp, link); }
bufp++; for (i = chunk; i; --i,++bufp) {
free_recvbufs++; LINK_SLIST(free_recv_list, bufp, link);
total_recvbufs++; }
free_recvbufs += chunk;
total_recvbufs += chunk;
abuf -= chunk;
} }
lowater_adds++; ++lowater_adds;
} }
void void
init_recvbuff(int nbufs) init_recvbuff(int nbufs)
{ {
/* /*
* Init buffer free list and stat counters * Init buffer free list and stat counters
*/ */
free_recvbufs = total_recvbufs = 0; free_recvbufs = total_recvbufs = 0;
full_recvbufs = lowater_adds = 0; full_recvbufs = lowater_adds = 0;
limit_recvbufs = RECV_TOOMANY;
emerg_recvbufs = RECV_CLOCK;
create_buffers(nbufs); create_buffers(nbufs);
#if defined(SYS_WINNT) # if defined(SYS_WINNT)
InitializeCriticalSection(&RecvLock); InitializeCriticalSection(&RecvLock);
#endif InitializeCriticalSection(&FreeLock);
# endif
#ifdef DEBUG # ifdef DEBUG
atexit(&uninit_recvbuff); atexit(&uninit_recvbuff);
#endif # endif
} }
#ifdef DEBUG #ifdef DEBUG
static void static void
uninit_recvbuff(void) uninit_recvbuff(void)
{ {
recvbuf_t *rbunlinked; recvbuf_t *rbunlinked;
for (;;) { for (;;) {
UNLINK_FIFO(rbunlinked, full_recv_fifo, link); UNLINK_FIFO(rbunlinked, full_recv_fifo, link);
skipping to change at line 146 skipping to change at line 186
break; break;
free(rbunlinked); free(rbunlinked);
} }
for (;;) { for (;;) {
UNLINK_HEAD_SLIST(rbunlinked, free_recv_list, link); UNLINK_HEAD_SLIST(rbunlinked, free_recv_list, link);
if (rbunlinked == NULL) if (rbunlinked == NULL)
break; break;
free(rbunlinked); free(rbunlinked);
} }
# if defined(SYS_WINNT)
DeleteCriticalSection(&FreeLock);
DeleteCriticalSection(&RecvLock);
# endif
} }
#endif /* DEBUG */ #endif /* DEBUG */
/* /*
* freerecvbuf - make a single recvbuf available for reuse * freerecvbuf - make a single recvbuf available for reuse
*/ */
void void
freerecvbuf(recvbuf_t *rb) freerecvbuf(recvbuf_t *rb)
{ {
if (rb) { if (rb) {
LOCK(); if (--rb->used != 0) {
rb->used--;
if (rb->used != 0)
msyslog(LOG_ERR, "******** freerecvbuff non-zero usage: % d *******", rb->used); msyslog(LOG_ERR, "******** freerecvbuff non-zero usage: % d *******", rb->used);
rb->used = 0;
}
LOCK_F();
LINK_SLIST(free_recv_list, rb, link); LINK_SLIST(free_recv_list, rb, link);
free_recvbufs++; ++free_recvbufs;
UNLOCK(); UNLOCK_F();
} }
} }
void void
add_full_recv_buffer(recvbuf_t *rb) add_full_recv_buffer(recvbuf_t *rb)
{ {
if (rb == NULL) { if (rb == NULL) {
msyslog(LOG_ERR, "add_full_recv_buffer received NULL buffer"); msyslog(LOG_ERR, "add_full_recv_buffer received NULL buffer");
return; return;
} }
LOCK(); LOCK_R();
LINK_FIFO(full_recv_fifo, rb, link); LINK_FIFO(full_recv_fifo, rb, link);
full_recvbufs++; ++full_recvbufs;
UNLOCK(); UNLOCK_R();
} }
recvbuf_t * recvbuf_t *
get_free_recv_buffer(void) get_free_recv_buffer(
{ int /*BOOL*/ urgent
recvbuf_t *buffer; )
{
recvbuf_t *buffer = NULL;
LOCK_F();
if (free_recvbufs > (urgent ? emerg_recvbufs : 0)) {
UNLINK_HEAD_SLIST(buffer, free_recv_list, link);
}
LOCK();
UNLINK_HEAD_SLIST(buffer, free_recv_list, link);
if (buffer != NULL) { if (buffer != NULL) {
free_recvbufs--; if (free_recvbufs)
--free_recvbufs;
initialise_buffer(buffer); initialise_buffer(buffer);
buffer->used++; ++buffer->used;
} else { } else {
buffer_shortfall++; ++buffer_shortfall;
} }
UNLOCK(); UNLOCK_F();
return buffer; return buffer;
} }
#ifdef HAVE_IO_COMPLETION_PORT #ifdef HAVE_IO_COMPLETION_PORT
recvbuf_t * recvbuf_t *
get_free_recv_buffer_alloc(void) get_free_recv_buffer_alloc(
int /*BOOL*/ urgent
)
{ {
recvbuf_t *buffer; LOCK_F();
if (free_recvbufs <= emerg_recvbufs || buffer_shortfall > 0)
buffer = get_free_recv_buffer();
if (NULL == buffer) {
create_buffers(RECV_INC); create_buffers(RECV_INC);
buffer = get_free_recv_buffer(); UNLOCK_F();
} return get_free_recv_buffer(urgent);
ENSURE(buffer != NULL);
return (buffer);
} }
#endif #endif
recvbuf_t * recvbuf_t *
get_full_recv_buffer(void) get_full_recv_buffer(void)
{ {
recvbuf_t * rbuf; recvbuf_t * rbuf;
LOCK();
/* /*
* make sure there are free buffers when we * make sure there are free buffers when we wander off to do
* wander off to do lengthy packet processing with * lengthy packet processing with any buffer we grab from the
* any buffer we grab from the full list. * full list.
* *
* fixes malloc() interrupted by SIGIO risk * fixes malloc() interrupted by SIGIO risk (Bug 889)
* (Bug 889)
*/ */
if (NULL == free_recv_list || buffer_shortfall > 0) { LOCK_F();
/* if (free_recvbufs <= emerg_recvbufs || buffer_shortfall > 0)
* try to get us some more buffers
*/
create_buffers(RECV_INC); create_buffers(RECV_INC);
} UNLOCK_F();
/* /*
* try to grab a full buffer * try to grab a full buffer
*/ */
LOCK_R();
UNLINK_FIFO(rbuf, full_recv_fifo, link); UNLINK_FIFO(rbuf, full_recv_fifo, link);
if (rbuf != NULL) if (rbuf != NULL && full_recvbufs)
full_recvbufs--; --full_recvbufs;
UNLOCK(); UNLOCK_R();
return rbuf; return rbuf;
} }
/* /*
* purge_recv_buffers_for_fd() - purges any previously-received input * purge_recv_buffers_for_fd() - purges any previously-received input
* from a given file descriptor. * from a given file descriptor.
*/ */
void void
purge_recv_buffers_for_fd( purge_recv_buffers_for_fd(
int fd int fd
) )
{ {
recvbuf_t *rbufp; recvbuf_t *rbufp;
recvbuf_t *next; recvbuf_t *next;
recvbuf_t *punlinked; recvbuf_t *punlinked;
recvbuf_t *freelist = NULL;
LOCK(); /* We want to hold only one lock at a time. So we do a scan on
* the full buffer queue, collecting items as we go, and when
* done we spool the the collected items to 'freerecvbuf()'.
*/
LOCK_R();
for (rbufp = HEAD_FIFO(full_recv_fifo); for (rbufp = HEAD_FIFO(full_recv_fifo);
rbufp != NULL; rbufp != NULL;
rbufp = next) { rbufp = next)
{
next = rbufp->link; next = rbufp->link;
# ifdef HAVE_IO_COMPLETION_PORT # ifdef HAVE_IO_COMPLETION_PORT
if (rbufp->dstadr == NULL && rbufp->fd == fd) if (rbufp->dstadr == NULL && rbufp->fd == fd)
# else # else
if (rbufp->fd == fd) if (rbufp->fd == fd)
# endif # endif
{ {
UNLINK_MID_FIFO(punlinked, full_recv_fifo, UNLINK_MID_FIFO(punlinked, full_recv_fifo,
rbufp, link, recvbuf_t); rbufp, link, recvbuf_t);
INSIST(punlinked == rbufp); INSIST(punlinked == rbufp);
full_recvbufs--; if (full_recvbufs)
freerecvbuf(rbufp); --full_recvbufs;
rbufp->link = freelist;
freelist = rbufp;
} }
} }
UNLOCK(); UNLOCK_R();
while (freelist) {
next = freelist->link;
freerecvbuf(freelist);
freelist = next;
}
} }
/* /*
* Checks to see if there are buffers to process * Checks to see if there are buffers to process
*/ */
isc_boolean_t has_full_recv_buffer(void) isc_boolean_t has_full_recv_buffer(void)
{ {
if (HEAD_FIFO(full_recv_fifo) != NULL) if (HEAD_FIFO(full_recv_fifo) != NULL)
return (ISC_TRUE); return (ISC_TRUE);
else else
 End of changes. 42 change blocks. 
73 lines changed or deleted 132 lines changed or added

Home  |  About  |  Features  |  All  |  Newest  |  Dox  |  Diffs  |  RSS Feeds  |  Screenshots  |  Comments  |  Imprint  |  Privacy  |  HTTP(S)