211 lines
3.7 KiB
C
211 lines
3.7 KiB
C
/* $NetBSD: recvbuff.c,v 1.3 2006/06/11 19:34:10 kardel Exp $ */
|
|
|
|
#ifdef HAVE_CONFIG_H
|
|
# include <config.h>
|
|
#endif
|
|
|
|
#include <stdio.h>
|
|
#include "ntp_machine.h"
|
|
#include "ntp_fp.h"
|
|
#include "ntp_syslog.h"
|
|
#include "ntp_stdlib.h"
|
|
#include "ntp_io.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 total_recvbufs; /* total recvbufs currently in use */
|
|
static u_long volatile lowater_adds; /* number of times we have added memory */
|
|
|
|
|
|
static ISC_LIST(recvbuf_t) full_list; /* Currently used recv buffers */
|
|
static ISC_LIST(recvbuf_t) free_list; /* Currently unused buffers */
|
|
|
|
#if defined(SYS_WINNT)
|
|
|
|
/*
|
|
* For Windows we need to set up a lock to manipulate the
|
|
* recv buffers to prevent corruption. We keep it lock for as
|
|
* short a time as possible
|
|
*/
|
|
static CRITICAL_SECTION RecvLock;
|
|
# define LOCK() EnterCriticalSection(&RecvLock)
|
|
# define UNLOCK() LeaveCriticalSection(&RecvLock)
|
|
#else
|
|
# define LOCK()
|
|
# define UNLOCK()
|
|
#endif
|
|
|
|
u_long
|
|
free_recvbuffs (void)
|
|
{
|
|
return free_recvbufs;
|
|
}
|
|
|
|
u_long
|
|
full_recvbuffs (void)
|
|
{
|
|
return full_recvbufs;
|
|
}
|
|
|
|
u_long
|
|
total_recvbuffs (void)
|
|
{
|
|
return total_recvbufs;
|
|
}
|
|
|
|
u_long
|
|
lowater_additions(void)
|
|
{
|
|
return lowater_adds;
|
|
}
|
|
|
|
static 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
|
|
}
|
|
|
|
static int
|
|
create_buffers(int nbufs)
|
|
{
|
|
register recvbuf_t *buf;
|
|
int i;
|
|
buf = (recvbuf_t *) emalloc(nbufs*sizeof(recvbuf_t));
|
|
/*
|
|
* If no memory available, Bail
|
|
*/
|
|
if (buf == NULL)
|
|
return (0);
|
|
for (i = 0; i < nbufs; i++)
|
|
{
|
|
ISC_LIST_APPEND(free_list, buf, link);
|
|
buf++;
|
|
free_recvbufs++;
|
|
total_recvbufs++;
|
|
}
|
|
lowater_adds++;
|
|
return (nbufs);
|
|
}
|
|
|
|
void
|
|
init_recvbuff(int nbufs)
|
|
{
|
|
|
|
/*
|
|
* Init buffer free list and stat counters
|
|
*/
|
|
ISC_LIST_INIT(full_list);
|
|
ISC_LIST_INIT(free_list);
|
|
free_recvbufs = total_recvbufs = 0;
|
|
full_recvbufs = lowater_adds = 0;
|
|
|
|
create_buffers(nbufs);
|
|
|
|
#if defined(SYS_WINNT)
|
|
InitializeCriticalSection(&RecvLock);
|
|
#endif
|
|
|
|
}
|
|
|
|
/*
|
|
* freerecvbuf - make a single recvbuf available for reuse
|
|
*/
|
|
void
|
|
freerecvbuf(recvbuf_t *rb)
|
|
{
|
|
LOCK();
|
|
ISC_LIST_APPEND(free_list, rb, link);
|
|
#if defined SYS_WINNT
|
|
rb->wsabuff.len = RX_BUFF_SIZE;
|
|
rb->wsabuff.buf = (char *) rb->recv_buffer;
|
|
#endif
|
|
free_recvbufs++;
|
|
UNLOCK();
|
|
}
|
|
|
|
|
|
void
|
|
add_full_recv_buffer(recvbuf_t *rb)
|
|
{
|
|
LOCK();
|
|
ISC_LIST_APPEND(full_list, rb, link);
|
|
full_recvbufs++;
|
|
UNLOCK();
|
|
}
|
|
|
|
recvbuf_t *
|
|
get_free_recv_buffer(void)
|
|
{
|
|
recvbuf_t * buffer = NULL;
|
|
LOCK();
|
|
buffer = ISC_LIST_HEAD(free_list);
|
|
if (buffer == NULL)
|
|
{
|
|
/*
|
|
* See if more are available
|
|
*/
|
|
if (create_buffers(RECV_INC) <= 0)
|
|
{
|
|
msyslog(LOG_ERR, "No more memory for recvufs");
|
|
UNLOCK();
|
|
return (NULL);
|
|
}
|
|
buffer = ISC_LIST_HEAD(free_list);
|
|
if (buffer == NULL)
|
|
{
|
|
msyslog(LOG_ERR, "Failed to obtain more memory for recvbufs");
|
|
UNLOCK();
|
|
return (NULL);
|
|
}
|
|
}
|
|
ISC_LIST_DEQUEUE(free_list, buffer, link);
|
|
free_recvbufs--;
|
|
initialise_buffer(buffer);
|
|
UNLOCK();
|
|
return (buffer);
|
|
}
|
|
|
|
recvbuf_t *
|
|
get_full_recv_buffer(void)
|
|
{
|
|
recvbuf_t *rbuf;
|
|
LOCK();
|
|
rbuf = ISC_LIST_HEAD(full_list);
|
|
if (rbuf != NULL)
|
|
{
|
|
ISC_LIST_DEQUEUE(full_list, rbuf, link);
|
|
--full_recvbufs;
|
|
}
|
|
else
|
|
{
|
|
/*
|
|
* Make sure we reset the full count to 0
|
|
*/
|
|
full_recvbufs = 0;
|
|
}
|
|
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_list) != NULL)
|
|
return (ISC_TRUE);
|
|
else
|
|
return (ISC_FALSE);
|
|
}
|