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