recvbuff.c revision 82499
1#ifdef HAVE_CONFIG_H
2# include <config.h>
3#endif
4
5#include <stdio.h>
6#include "ntp_machine.h"
7#include "ntp_fp.h"
8#include "ntp_syslog.h"
9#include "ntp_stdlib.h"
10#include "ntp_io.h"
11#include "recvbuff.h"
12#include "iosignal.h"
13
14/*
15 * Memory allocation
16 */
17static u_long volatile full_recvbufs;		/* number of recvbufs on fulllist */
18static u_long volatile free_recvbufs;		/* number of recvbufs on freelist */
19static u_long volatile total_recvbufs;		/* total recvbufs currently in use */
20static u_long volatile lowater_adds;	/* number of times we have added memory */
21
22static	struct recvbuf *volatile freelist;  /* free buffers */
23static	struct recvbuf *volatile fulllist;  /* lifo buffers with data */
24static	struct recvbuf *volatile beginlist; /* fifo buffers with data */
25
26#if defined(HAVE_IO_COMPLETION_PORT)
27static CRITICAL_SECTION RecvCritSection;
28# define RECV_BLOCK_IO()	EnterCriticalSection(&RecvCritSection)
29# define RECV_UNBLOCK_IO()	LeaveCriticalSection(&RecvCritSection)
30#else
31# define RECV_BLOCK_IO()
32# define RECV_UNBLOCK_IO()
33#endif
34
35u_long
36free_recvbuffs (void)
37{
38	return free_recvbufs;
39}
40
41u_long
42full_recvbuffs (void)
43{
44	return free_recvbufs;
45}
46
47u_long
48total_recvbuffs (void)
49{
50	return free_recvbufs;
51}
52
53u_long
54lowater_additions(void)
55{
56	return lowater_adds;
57}
58
59static void
60initialise_buffer(struct recvbuf *buff)
61{
62	memset((char *) buff, 0, sizeof(struct recvbuf));
63
64#if defined HAVE_IO_COMPLETION_PORT
65	buff->iocompletioninfo.overlapped.hEvent = CreateEvent(NULL, FALSE,FALSE, NULL);
66	buff->wsabuff.len = RX_BUFF_SIZE;
67	buff->wsabuff.buf = (char *) buff->recv_buffer;
68#endif
69}
70
71static void
72create_buffers(void)
73{
74	register struct recvbuf *buf;
75	int i;
76	buf = (struct recvbuf *)
77	    emalloc(RECV_INC*sizeof(struct recvbuf));
78	for (i = 0; i < RECV_INC; i++)
79	{
80		initialise_buffer(buf);
81		buf->next = (struct recvbuf *) freelist;
82		freelist = buf;
83		buf++;
84	}
85
86	free_recvbufs += RECV_INC;
87	total_recvbufs += RECV_INC;
88	lowater_adds++;
89}
90
91void
92init_recvbuff(int nbufs)
93{
94	register struct recvbuf *buf;
95	int i;
96
97	/*
98	 * Init buffer free list and stat counters
99	 */
100	freelist = 0;
101
102	buf = (struct recvbuf *)
103	    emalloc(nbufs*sizeof(struct recvbuf));
104	for (i = 0; i < nbufs; i++)
105	{
106		initialise_buffer(buf);
107		buf->next = (struct recvbuf *) freelist;
108		freelist = buf;
109		buf++;
110	}
111
112	fulllist = 0;
113	free_recvbufs = total_recvbufs = nbufs;
114	full_recvbufs = lowater_adds = 0;
115
116#if defined(HAVE_IO_COMPLETION_PORT)
117	InitializeCriticalSection(&RecvCritSection);
118#endif
119
120}
121
122
123/*
124 * getrecvbufs - get receive buffers which have data in them
125 *
126 *
127 */
128
129struct recvbuf *
130getrecvbufs(void)
131{
132	struct recvbuf *rb = NULL; /* nothing has arrived */;
133
134	RECV_BLOCK_IO();
135	if (full_recvbufs == 0)
136	{
137#ifdef DEBUG
138		if (debug > 4)
139		    printf("getrecvbufs called, no action here\n");
140#endif
141	}
142	else {
143
144		/*
145		 * Get the fulllist chain and mark it empty
146		 */
147#ifdef DEBUG
148		if (debug > 4)
149		    printf("getrecvbufs returning %ld buffers\n", full_recvbufs);
150#endif
151		rb = beginlist;
152		fulllist = 0;
153		full_recvbufs = 0;
154
155		/*
156		 * Check to see if we're below the low water mark.
157		 */
158		if (free_recvbufs <= RECV_LOWAT)
159		{
160			if (total_recvbufs >= RECV_TOOMANY)
161			    msyslog(LOG_ERR, "too many recvbufs allocated (%ld)",
162				    total_recvbufs);
163			else
164			{
165				create_buffers();
166			}
167		}
168	}
169	RECV_UNBLOCK_IO();
170
171	/*
172	 * Return the chain
173	 */
174	return rb;
175}
176
177/*
178 * freerecvbuf - make a single recvbuf available for reuse
179 */
180void
181freerecvbuf(
182	struct recvbuf *rb
183	)
184{
185	RECV_BLOCK_IO();
186	BLOCKIO();
187	rb->next = (struct recvbuf *) freelist;
188	freelist = rb;
189	free_recvbufs++;
190	UNBLOCKIO();
191	RECV_UNBLOCK_IO();
192}
193
194
195void
196add_full_recv_buffer(
197	struct recvbuf *rb
198	)
199{
200	RECV_BLOCK_IO();
201	if (full_recvbufs == 0)
202	{
203		beginlist = rb;
204		rb->next = 0;
205	}
206	else
207	{
208		rb->next = fulllist->next;
209		fulllist->next = rb;
210	}
211	fulllist = rb;
212	full_recvbufs++;
213
214	RECV_UNBLOCK_IO();
215}
216
217struct recvbuf *
218get_free_recv_buffer(void)
219{
220	struct recvbuf * buffer = NULL;
221	RECV_BLOCK_IO();
222	if (free_recvbufs <= RECV_LOWAT)
223		{
224			if (total_recvbufs >= RECV_TOOMANY) {
225			    msyslog(LOG_ERR, "too many recvbufs allocated (%ld)",
226				    total_recvbufs);
227			}
228			else
229			{
230				create_buffers();
231			}
232		}
233
234	if (free_recvbufs > 0)
235	{
236		buffer = freelist;
237		freelist = buffer->next;
238		buffer->next = NULL;
239		--free_recvbufs;
240	}
241
242	RECV_UNBLOCK_IO();
243	return buffer;
244}
245
246struct recvbuf *
247get_full_recv_buffer(void)
248{
249	struct recvbuf * buffer = NULL;
250	RECV_BLOCK_IO();
251	if (full_recvbufs > 0) {
252		--full_recvbufs;
253		buffer = beginlist;
254		beginlist = buffer->next;
255		buffer->next = NULL;
256	}
257	RECV_UNBLOCK_IO();
258	return buffer;
259}
260