Sync usage with man page.
[netbsd-mini2440.git] / dist / ntp / libntp / recvbuff.c
blob87ce2156b19a0d6c0dbf603383ffe7447a1181d6
1 /* $NetBSD: recvbuff.c,v 1.6 2007/08/18 13:18:23 kardel Exp $ */
3 #ifdef HAVE_CONFIG_H
4 # include <config.h>
5 #endif
7 #include <stdio.h>
8 #include "ntp_machine.h"
9 #include "ntp_fp.h"
10 #include "ntp_syslog.h"
11 #include "ntp_stdlib.h"
12 #include "ntp_io.h"
13 #include "recvbuff.h"
14 #include "iosignal.h"
16 #include <isc/list.h>
18 * Memory allocation
20 static u_long volatile full_recvbufs; /* number of recvbufs on fulllist */
21 static u_long volatile free_recvbufs; /* number of recvbufs on freelist */
22 static u_long volatile total_recvbufs; /* total recvbufs currently in use */
23 static u_long volatile lowater_adds; /* number of times we have added memory */
24 static u_long volatile buffer_shortfall;/* number of missed free receive buffers
25 between replenishments */
27 static ISC_LIST(recvbuf_t) full_recv_list; /* Currently used recv buffers */
28 static ISC_LIST(recvbuf_t) free_recv_list; /* Currently unused buffers */
30 #if defined(SYS_WINNT)
33 * For Windows we need to set up a lock to manipulate the
34 * recv buffers to prevent corruption. We keep it lock for as
35 * short a time as possible
37 static CRITICAL_SECTION RecvLock;
38 # define LOCK() EnterCriticalSection(&RecvLock)
39 # define UNLOCK() LeaveCriticalSection(&RecvLock)
40 #else
41 # define LOCK()
42 # define UNLOCK()
43 #endif
45 u_long
46 free_recvbuffs (void)
48 return free_recvbufs;
51 u_long
52 full_recvbuffs (void)
54 return full_recvbufs;
57 u_long
58 total_recvbuffs (void)
60 return total_recvbufs;
63 u_long
64 lowater_additions(void)
66 return lowater_adds;
69 static void
70 initialise_buffer(recvbuf_t *buff)
72 memset((char *) buff, 0, sizeof(recvbuf_t));
74 #if defined SYS_WINNT
75 buff->wsabuff.len = RX_BUFF_SIZE;
76 buff->wsabuff.buf = (char *) buff->recv_buffer;
77 #endif
80 static void
81 create_buffers(int nbufs)
83 register recvbuf_t *bufp;
84 int i, abuf;
86 abuf = nbufs + buffer_shortfall;
87 buffer_shortfall = 0;
89 bufp = (recvbuf_t *) emalloc(abuf*sizeof(recvbuf_t));
91 for (i = 0; i < abuf; i++)
93 memset((char *) bufp, 0, sizeof(recvbuf_t));
94 ISC_LIST_APPEND(free_recv_list, bufp, link);
95 bufp++;
96 free_recvbufs++;
97 total_recvbufs++;
99 lowater_adds++;
102 void
103 init_recvbuff(int nbufs)
107 * Init buffer free list and stat counters
109 ISC_LIST_INIT(full_recv_list);
110 ISC_LIST_INIT(free_recv_list);
111 free_recvbufs = total_recvbufs = 0;
112 full_recvbufs = lowater_adds = 0;
114 create_buffers(nbufs);
116 #if defined(SYS_WINNT)
117 InitializeCriticalSection(&RecvLock);
118 #endif
123 * freerecvbuf - make a single recvbuf available for reuse
125 void
126 freerecvbuf(recvbuf_t *rb)
128 if (rb == NULL) {
129 msyslog(LOG_ERR, "freerecvbuff received NULL buffer");
130 return;
133 LOCK();
134 (rb->used)--;
135 if (rb->used != 0)
136 msyslog(LOG_ERR, "******** freerecvbuff non-zero usage: %d *******", rb->used);
137 ISC_LIST_APPEND(free_recv_list, rb, link);
138 #if defined SYS_WINNT
139 rb->wsabuff.len = RX_BUFF_SIZE;
140 rb->wsabuff.buf = (char *) rb->recv_buffer;
141 #endif
142 free_recvbufs++;
143 UNLOCK();
147 void
148 add_full_recv_buffer(recvbuf_t *rb)
150 if (rb == NULL) {
151 msyslog(LOG_ERR, "add_full_recv_buffer received NULL buffer");
152 return;
154 LOCK();
155 ISC_LIST_APPEND(full_recv_list, rb, link);
156 full_recvbufs++;
157 UNLOCK();
160 recvbuf_t *
161 get_free_recv_buffer(void)
163 recvbuf_t * buffer = NULL;
164 LOCK();
165 buffer = ISC_LIST_HEAD(free_recv_list);
166 if (buffer != NULL)
168 ISC_LIST_DEQUEUE(free_recv_list, buffer, link);
169 free_recvbufs--;
170 initialise_buffer(buffer);
171 (buffer->used)++;
173 else
175 buffer_shortfall++;
177 UNLOCK();
178 return (buffer);
181 #ifdef HAVE_IO_COMPLETION_PORT
182 recvbuf_t *
183 get_free_recv_buffer_alloc(void)
185 recvbuf_t * buffer = get_free_recv_buffer();
186 if (buffer == NULL)
188 create_buffers(RECV_INC);
189 buffer = get_free_recv_buffer();
191 return (buffer);
193 #endif
195 recvbuf_t *
196 get_full_recv_buffer(void)
198 recvbuf_t *rbuf;
199 LOCK();
201 #ifdef HAVE_SIGNALED_IO
203 * make sure there are free buffers when we
204 * wander off to do lengthy paket processing with
205 * any buffer we grab from the full list.
207 * fixes malloc() interrupted by SIGIO risk
208 * (Bug 889)
210 rbuf = ISC_LIST_HEAD(free_recv_list);
211 if (rbuf == NULL || buffer_shortfall > 0) {
213 * try to get us some more buffers
215 create_buffers(RECV_INC);
217 #endif
220 * try to grab a full buffer
222 rbuf = ISC_LIST_HEAD(full_recv_list);
223 if (rbuf != NULL)
225 ISC_LIST_DEQUEUE(full_recv_list, rbuf, link);
226 --full_recvbufs;
228 else
231 * Make sure we reset the full count to 0
233 full_recvbufs = 0;
235 UNLOCK();
236 return (rbuf);
240 * Checks to see if there are buffers to process
242 isc_boolean_t has_full_recv_buffer(void)
244 if (ISC_LIST_HEAD(full_recv_list) != NULL)
245 return (ISC_TRUE);
246 else
247 return (ISC_FALSE);