File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / ntp / libntp / recvbuff.c
Revision 1.1.1.1 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Tue May 29 12:08:38 2012 UTC (12 years, 5 months ago) by misho
Branches: ntp, MAIN
CVS tags: v4_2_6p5p0, v4_2_6p5, HEAD
ntp 4.2.6p5

    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>