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