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