Deleted Added
full compact
recvbuff.c (358659) recvbuff.c (362716)
1#ifdef HAVE_CONFIG_H
2# include <config.h>
3#endif
4
5#include <stdio.h>
6
7#include "ntp_assert.h"
8#include "ntp_syslog.h"
9#include "ntp_stdlib.h"
10#include "ntp_lists.h"
11#include "recvbuff.h"
12#include "iosignal.h"
13
1#ifdef HAVE_CONFIG_H
2# include <config.h>
3#endif
4
5#include <stdio.h>
6
7#include "ntp_assert.h"
8#include "ntp_syslog.h"
9#include "ntp_stdlib.h"
10#include "ntp_lists.h"
11#include "recvbuff.h"
12#include "iosignal.h"
13
14#if (RECV_INC & (RECV_INC-1))
15# error RECV_INC not a power of 2!
16#endif
17#if (RECV_BATCH & (RECV_BATCH - 1))
18#error RECV_BATCH not a power of 2!
19#endif
20#if (RECV_BATCH < RECV_INC)
21#error RECV_BATCH must be >= RECV_INC!
22#endif
14
15/*
16 * Memory allocation
17 */
18static u_long volatile full_recvbufs; /* recvbufs on full_recv_fifo */
19static u_long volatile free_recvbufs; /* recvbufs on free_recv_list */
20static u_long volatile total_recvbufs; /* total recvbufs currently in use */
21static u_long volatile lowater_adds; /* number of times we have added memory */
22static u_long volatile buffer_shortfall;/* number of missed free receive buffers
23 between replenishments */
23
24/*
25 * Memory allocation
26 */
27static u_long volatile full_recvbufs; /* recvbufs on full_recv_fifo */
28static u_long volatile free_recvbufs; /* recvbufs on free_recv_list */
29static u_long volatile total_recvbufs; /* total recvbufs currently in use */
30static u_long volatile lowater_adds; /* number of times we have added memory */
31static u_long volatile buffer_shortfall;/* number of missed free receive buffers
32 between replenishments */
33static u_long limit_recvbufs; /* maximum total of receive buffers */
34static u_long emerg_recvbufs; /* emergency/urgent buffers to keep */
24
25static DECL_FIFO_ANCHOR(recvbuf_t) full_recv_fifo;
26static recvbuf_t * free_recv_list;
27
28#if defined(SYS_WINNT)
29
30/*
31 * For Windows we need to set up a lock to manipulate the
32 * recv buffers to prevent corruption. We keep it lock for as
33 * short a time as possible
34 */
35static CRITICAL_SECTION RecvLock;
35
36static DECL_FIFO_ANCHOR(recvbuf_t) full_recv_fifo;
37static recvbuf_t * free_recv_list;
38
39#if defined(SYS_WINNT)
40
41/*
42 * For Windows we need to set up a lock to manipulate the
43 * recv buffers to prevent corruption. We keep it lock for as
44 * short a time as possible
45 */
46static CRITICAL_SECTION RecvLock;
36# define LOCK() EnterCriticalSection(&RecvLock)
37# define UNLOCK() LeaveCriticalSection(&RecvLock)
47static CRITICAL_SECTION FreeLock;
48# define LOCK_R() EnterCriticalSection(&RecvLock)
49# define UNLOCK_R() LeaveCriticalSection(&RecvLock)
50# define LOCK_F() EnterCriticalSection(&FreeLock)
51# define UNLOCK_F() LeaveCriticalSection(&FreeLock)
38#else
52#else
39# define LOCK() do {} while (FALSE)
40# define UNLOCK() do {} while (FALSE)
53# define LOCK_R() do {} while (FALSE)
54# define UNLOCK_R() do {} while (FALSE)
55# define LOCK_F() do {} while (FALSE)
56# define UNLOCK_F() do {} while (FALSE)
41#endif
42
43#ifdef DEBUG
44static void uninit_recvbuff(void);
45#endif
46
47
48u_long

--- 22 unchanged lines hidden (view full) ---

71
72static inline void
73initialise_buffer(recvbuf_t *buff)
74{
75 ZERO(*buff);
76}
77
78static void
57#endif
58
59#ifdef DEBUG
60static void uninit_recvbuff(void);
61#endif
62
63
64u_long

--- 22 unchanged lines hidden (view full) ---

87
88static inline void
89initialise_buffer(recvbuf_t *buff)
90{
91 ZERO(*buff);
92}
93
94static void
79create_buffers(int nbufs)
95create_buffers(
96 size_t nbufs)
80{
97{
98# ifndef DEBUG
99 static const u_int chunk = RECV_INC;
100# else
101 /* Allocate each buffer individually so they can be free()d
102 * during ntpd shutdown on DEBUG builds to keep them out of heap
103 * leak reports.
104 */
105 static const u_int chunk = 1;
106# endif
107
81 register recvbuf_t *bufp;
108 register recvbuf_t *bufp;
82 int i, abuf;
109 u_int i;
110 size_t abuf;
83
111
112 if (limit_recvbufs <= total_recvbufs)
113 return;
114
84 abuf = nbufs + buffer_shortfall;
85 buffer_shortfall = 0;
86
115 abuf = nbufs + buffer_shortfall;
116 buffer_shortfall = 0;
117
87#ifndef DEBUG
88 bufp = eallocarray(abuf, sizeof(*bufp));
89#endif
90
91 for (i = 0; i < abuf; i++) {
92#ifdef DEBUG
93 /*
94 * Allocate each buffer individually so they can be
95 * free()d during ntpd shutdown on DEBUG builds to
96 * keep them out of heap leak reports.
97 */
98 bufp = emalloc_zero(sizeof(*bufp));
99#endif
100 LINK_SLIST(free_recv_list, bufp, link);
101 bufp++;
102 free_recvbufs++;
103 total_recvbufs++;
118 if (abuf < nbufs || abuf > RECV_BATCH)
119 abuf = RECV_BATCH; /* clamp on overflow */
120 else
121 abuf += (~abuf + 1) & (RECV_INC - 1); /* round up */
122
123 if (abuf > (limit_recvbufs - total_recvbufs))
124 abuf = limit_recvbufs - total_recvbufs;
125 abuf += (~abuf + 1) & (chunk - 1); /* round up */
126
127 while (abuf) {
128 bufp = calloc(chunk, sizeof(*bufp));
129 if (!bufp) {
130 limit_recvbufs = total_recvbufs;
131 break;
132 }
133 for (i = chunk; i; --i,++bufp) {
134 LINK_SLIST(free_recv_list, bufp, link);
135 }
136 free_recvbufs += chunk;
137 total_recvbufs += chunk;
138 abuf -= chunk;
104 }
139 }
105 lowater_adds++;
140 ++lowater_adds;
106}
107
108void
109init_recvbuff(int nbufs)
110{
111
112 /*
113 * Init buffer free list and stat counters
114 */
115 free_recvbufs = total_recvbufs = 0;
116 full_recvbufs = lowater_adds = 0;
117
141}
142
143void
144init_recvbuff(int nbufs)
145{
146
147 /*
148 * Init buffer free list and stat counters
149 */
150 free_recvbufs = total_recvbufs = 0;
151 full_recvbufs = lowater_adds = 0;
152
153 limit_recvbufs = RECV_TOOMANY;
154 emerg_recvbufs = RECV_CLOCK;
155
118 create_buffers(nbufs);
119
156 create_buffers(nbufs);
157
120#if defined(SYS_WINNT)
158# if defined(SYS_WINNT)
121 InitializeCriticalSection(&RecvLock);
159 InitializeCriticalSection(&RecvLock);
122#endif
160 InitializeCriticalSection(&FreeLock);
161# endif
123
162
124#ifdef DEBUG
163# ifdef DEBUG
125 atexit(&uninit_recvbuff);
164 atexit(&uninit_recvbuff);
126#endif
165# endif
127}
128
129
130#ifdef DEBUG
131static void
132uninit_recvbuff(void)
133{
134 recvbuf_t *rbunlinked;

--- 6 unchanged lines hidden (view full) ---

141 }
142
143 for (;;) {
144 UNLINK_HEAD_SLIST(rbunlinked, free_recv_list, link);
145 if (rbunlinked == NULL)
146 break;
147 free(rbunlinked);
148 }
166}
167
168
169#ifdef DEBUG
170static void
171uninit_recvbuff(void)
172{
173 recvbuf_t *rbunlinked;

--- 6 unchanged lines hidden (view full) ---

180 }
181
182 for (;;) {
183 UNLINK_HEAD_SLIST(rbunlinked, free_recv_list, link);
184 if (rbunlinked == NULL)
185 break;
186 free(rbunlinked);
187 }
188# if defined(SYS_WINNT)
189 DeleteCriticalSection(&FreeLock);
190 DeleteCriticalSection(&RecvLock);
191# endif
149}
150#endif /* DEBUG */
151
152
153/*
154 * freerecvbuf - make a single recvbuf available for reuse
155 */
156void
157freerecvbuf(recvbuf_t *rb)
158{
159 if (rb) {
192}
193#endif /* DEBUG */
194
195
196/*
197 * freerecvbuf - make a single recvbuf available for reuse
198 */
199void
200freerecvbuf(recvbuf_t *rb)
201{
202 if (rb) {
160 LOCK();
161 rb->used--;
162 if (rb->used != 0)
203 if (--rb->used != 0) {
163 msyslog(LOG_ERR, "******** freerecvbuff non-zero usage: %d *******", rb->used);
204 msyslog(LOG_ERR, "******** freerecvbuff non-zero usage: %d *******", rb->used);
205 rb->used = 0;
206 }
207 LOCK_F();
164 LINK_SLIST(free_recv_list, rb, link);
208 LINK_SLIST(free_recv_list, rb, link);
165 free_recvbufs++;
166 UNLOCK();
209 ++free_recvbufs;
210 UNLOCK_F();
167 }
168}
169
170
171void
172add_full_recv_buffer(recvbuf_t *rb)
173{
174 if (rb == NULL) {
175 msyslog(LOG_ERR, "add_full_recv_buffer received NULL buffer");
176 return;
177 }
211 }
212}
213
214
215void
216add_full_recv_buffer(recvbuf_t *rb)
217{
218 if (rb == NULL) {
219 msyslog(LOG_ERR, "add_full_recv_buffer received NULL buffer");
220 return;
221 }
178 LOCK();
222 LOCK_R();
179 LINK_FIFO(full_recv_fifo, rb, link);
223 LINK_FIFO(full_recv_fifo, rb, link);
180 full_recvbufs++;
181 UNLOCK();
224 ++full_recvbufs;
225 UNLOCK_R();
182}
183
184
185recvbuf_t *
226}
227
228
229recvbuf_t *
186get_free_recv_buffer(void)
230get_free_recv_buffer(
231 int /*BOOL*/ urgent
232 )
187{
233{
188 recvbuf_t *buffer;
234 recvbuf_t *buffer = NULL;
189
235
190 LOCK();
191 UNLINK_HEAD_SLIST(buffer, free_recv_list, link);
236 LOCK_F();
237 if (free_recvbufs > (urgent ? emerg_recvbufs : 0)) {
238 UNLINK_HEAD_SLIST(buffer, free_recv_list, link);
239 }
240
192 if (buffer != NULL) {
241 if (buffer != NULL) {
193 free_recvbufs--;
242 if (free_recvbufs)
243 --free_recvbufs;
194 initialise_buffer(buffer);
244 initialise_buffer(buffer);
195 buffer->used++;
245 ++buffer->used;
196 } else {
246 } else {
197 buffer_shortfall++;
247 ++buffer_shortfall;
198 }
248 }
199 UNLOCK();
249 UNLOCK_F();
200
201 return buffer;
202}
203
204
205#ifdef HAVE_IO_COMPLETION_PORT
206recvbuf_t *
250
251 return buffer;
252}
253
254
255#ifdef HAVE_IO_COMPLETION_PORT
256recvbuf_t *
207get_free_recv_buffer_alloc(void)
257get_free_recv_buffer_alloc(
258 int /*BOOL*/ urgent
259 )
208{
260{
209 recvbuf_t *buffer;
210
211 buffer = get_free_recv_buffer();
212 if (NULL == buffer) {
261 LOCK_F();
262 if (free_recvbufs <= emerg_recvbufs || buffer_shortfall > 0)
213 create_buffers(RECV_INC);
263 create_buffers(RECV_INC);
214 buffer = get_free_recv_buffer();
215 }
216 ENSURE(buffer != NULL);
217 return (buffer);
264 UNLOCK_F();
265 return get_free_recv_buffer(urgent);
218}
219#endif
220
221
222recvbuf_t *
223get_full_recv_buffer(void)
224{
225 recvbuf_t * rbuf;
226
266}
267#endif
268
269
270recvbuf_t *
271get_full_recv_buffer(void)
272{
273 recvbuf_t * rbuf;
274
227 LOCK();
228
229 /*
275 /*
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.
276 * make sure there are free buffers when we wander off to do
277 * lengthy packet processing with any buffer we grab from the
278 * full list.
233 *
279 *
234 * fixes malloc() interrupted by SIGIO risk
235 * (Bug 889)
280 * fixes malloc() interrupted by SIGIO risk (Bug 889)
236 */
281 */
237 if (NULL == free_recv_list || buffer_shortfall > 0) {
238 /*
239 * try to get us some more buffers
240 */
282 LOCK_F();
283 if (free_recvbufs <= emerg_recvbufs || buffer_shortfall > 0)
241 create_buffers(RECV_INC);
284 create_buffers(RECV_INC);
242 }
285 UNLOCK_F();
243
244 /*
245 * try to grab a full buffer
246 */
286
287 /*
288 * try to grab a full buffer
289 */
290 LOCK_R();
247 UNLINK_FIFO(rbuf, full_recv_fifo, link);
291 UNLINK_FIFO(rbuf, full_recv_fifo, link);
248 if (rbuf != NULL)
249 full_recvbufs--;
250 UNLOCK();
292 if (rbuf != NULL && full_recvbufs)
293 --full_recvbufs;
294 UNLOCK_R();
251
252 return rbuf;
253}
254
255
256/*
257 * purge_recv_buffers_for_fd() - purges any previously-received input
258 * from a given file descriptor.
259 */
260void
261purge_recv_buffers_for_fd(
262 int fd
263 )
264{
265 recvbuf_t *rbufp;
266 recvbuf_t *next;
267 recvbuf_t *punlinked;
295
296 return rbuf;
297}
298
299
300/*
301 * purge_recv_buffers_for_fd() - purges any previously-received input
302 * from a given file descriptor.
303 */
304void
305purge_recv_buffers_for_fd(
306 int fd
307 )
308{
309 recvbuf_t *rbufp;
310 recvbuf_t *next;
311 recvbuf_t *punlinked;
312 recvbuf_t *freelist = NULL;
268
313
269 LOCK();
314 /* We want to hold only one lock at a time. So we do a scan on
315 * the full buffer queue, collecting items as we go, and when
316 * done we spool the the collected items to 'freerecvbuf()'.
317 */
318 LOCK_R();
270
271 for (rbufp = HEAD_FIFO(full_recv_fifo);
272 rbufp != NULL;
319
320 for (rbufp = HEAD_FIFO(full_recv_fifo);
321 rbufp != NULL;
273 rbufp = next) {
322 rbufp = next)
323 {
274 next = rbufp->link;
275# ifdef HAVE_IO_COMPLETION_PORT
276 if (rbufp->dstadr == NULL && rbufp->fd == fd)
277# else
278 if (rbufp->fd == fd)
279# endif
280 {
281 UNLINK_MID_FIFO(punlinked, full_recv_fifo,
282 rbufp, link, recvbuf_t);
283 INSIST(punlinked == rbufp);
324 next = rbufp->link;
325# ifdef HAVE_IO_COMPLETION_PORT
326 if (rbufp->dstadr == NULL && rbufp->fd == fd)
327# else
328 if (rbufp->fd == fd)
329# endif
330 {
331 UNLINK_MID_FIFO(punlinked, full_recv_fifo,
332 rbufp, link, recvbuf_t);
333 INSIST(punlinked == rbufp);
284 full_recvbufs--;
285 freerecvbuf(rbufp);
334 if (full_recvbufs)
335 --full_recvbufs;
336 rbufp->link = freelist;
337 freelist = rbufp;
286 }
287 }
288
338 }
339 }
340
289 UNLOCK();
341 UNLOCK_R();
342
343 while (freelist) {
344 next = freelist->link;
345 freerecvbuf(freelist);
346 freelist = next;
347 }
290}
291
292
293/*
294 * Checks to see if there are buffers to process
295 */
296isc_boolean_t has_full_recv_buffer(void)
297{

--- 29 unchanged lines hidden ---
348}
349
350
351/*
352 * Checks to see if there are buffers to process
353 */
354isc_boolean_t has_full_recv_buffer(void)
355{

--- 29 unchanged lines hidden ---