8 #include "ntp_machine.h"
9 #include "ntp_assert.h"
11 #include "ntp_syslog.h"
12 #include "ntp_stdlib.h"
14 #include "ntp_lists.h"
21 static void uninit_recvbuff(void);
27 static u_long
volatile full_recvbufs
; /* number of recvbufs on fulllist */
28 static u_long
volatile free_recvbufs
; /* number of recvbufs on freelist */
29 static u_long
volatile total_recvbufs
; /* total recvbufs currently in use */
30 static u_long
volatile lowater_adds
; /* number of times we have added memory */
31 static u_long
volatile buffer_shortfall
;/* number of missed free receive buffers
32 between replenishments */
34 static ISC_LIST(recvbuf_t
) full_recv_list
; /* Currently used recv buffers */
35 static recvbuf_t
* free_recv_list
; /* Currently unused buffers */
37 #if defined(SYS_WINNT)
40 * For Windows we need to set up a lock to manipulate the
41 * recv buffers to prevent corruption. We keep it lock for as
42 * short a time as possible
44 static CRITICAL_SECTION RecvLock
;
45 # define LOCK() EnterCriticalSection(&RecvLock)
46 # define UNLOCK() LeaveCriticalSection(&RecvLock)
65 total_recvbuffs (void)
67 return total_recvbufs
;
71 lowater_additions(void)
77 initialise_buffer(recvbuf_t
*buff
)
79 memset(buff
, 0, sizeof(*buff
));
83 create_buffers(int nbufs
)
85 register recvbuf_t
*bufp
;
88 abuf
= nbufs
+ buffer_shortfall
;
92 bufp
= emalloc(abuf
* sizeof(*bufp
));
95 for (i
= 0; i
< abuf
; i
++) {
98 * Allocate each buffer individually so they can be
99 * free()d during ntpd shutdown on DEBUG builds to
100 * keep them out of heap leak reports.
102 bufp
= emalloc(sizeof(*bufp
));
104 memset(bufp
, 0, sizeof(*bufp
));
105 LINK_SLIST(free_recv_list
, bufp
, link
.next
);
114 init_recvbuff(int nbufs
)
118 * Init buffer free list and stat counters
120 ISC_LIST_INIT(full_recv_list
);
121 free_recvbufs
= total_recvbufs
= 0;
122 full_recvbufs
= lowater_adds
= 0;
124 create_buffers(nbufs
);
126 #if defined(SYS_WINNT)
127 InitializeCriticalSection(&RecvLock
);
131 atexit(&uninit_recvbuff
);
138 uninit_recvbuff(void)
140 recvbuf_t
*rbunlinked
;
142 while ((rbunlinked
= ISC_LIST_HEAD(full_recv_list
)) != NULL
) {
143 ISC_LIST_DEQUEUE_TYPE(full_recv_list
, rbunlinked
, link
, recvbuf_t
);
148 UNLINK_HEAD_SLIST(rbunlinked
, free_recv_list
, link
.next
);
149 if (rbunlinked
!= NULL
)
151 } while (rbunlinked
!= NULL
);
157 * freerecvbuf - make a single recvbuf available for reuse
160 freerecvbuf(recvbuf_t
*rb
)
163 msyslog(LOG_ERR
, "freerecvbuff received NULL buffer");
170 msyslog(LOG_ERR
, "******** freerecvbuff non-zero usage: %d *******", rb
->used
);
171 LINK_SLIST(free_recv_list
, rb
, link
.next
);
178 add_full_recv_buffer(recvbuf_t
*rb
)
181 msyslog(LOG_ERR
, "add_full_recv_buffer received NULL buffer");
185 ISC_LINK_INIT(rb
, link
);
186 ISC_LIST_APPEND(full_recv_list
, rb
, link
);
192 get_free_recv_buffer(void)
197 UNLINK_HEAD_SLIST(buffer
, free_recv_list
, link
.next
);
198 if (buffer
!= NULL
) {
200 initialise_buffer(buffer
);
208 #ifdef HAVE_IO_COMPLETION_PORT
210 get_free_recv_buffer_alloc(void)
214 buffer
= get_free_recv_buffer();
215 if (NULL
== buffer
) {
216 create_buffers(RECV_INC
);
217 buffer
= get_free_recv_buffer();
219 NTP_ENSURE(buffer
!= NULL
);
225 get_full_recv_buffer(void)
230 #ifdef HAVE_SIGNALED_IO
232 * make sure there are free buffers when we
233 * wander off to do lengthy packet processing with
234 * any buffer we grab from the full list.
236 * fixes malloc() interrupted by SIGIO risk
239 if (NULL
== free_recv_list
|| buffer_shortfall
> 0) {
241 * try to get us some more buffers
243 create_buffers(RECV_INC
);
248 * try to grab a full buffer
250 rbuf
= ISC_LIST_HEAD(full_recv_list
);
252 ISC_LIST_DEQUEUE_TYPE(full_recv_list
, rbuf
, link
, recvbuf_t
);
256 * Make sure we reset the full count to 0
264 * Checks to see if there are buffers to process
266 isc_boolean_t
has_full_recv_buffer(void)
268 if (ISC_LIST_HEAD(full_recv_list
) != NULL
)