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 */ 17 static u_long volatile full_recvbufs; /* number of recvbufs on fulllist */ 18 static u_long volatile free_recvbufs; /* number of recvbufs on freelist */ 19 static u_long volatile total_recvbufs; /* total recvbufs currently in use */ 20 static u_long volatile lowater_adds; /* number of times we have added memory */ 21 22 static struct recvbuf *volatile freelist; /* free buffers */ 23 static struct recvbuf *volatile fulllist; /* lifo buffers with data */ 24 static struct recvbuf *volatile beginlist; /* fifo buffers with data */ 25 26 #if defined(HAVE_IO_COMPLETION_PORT) 27 static 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 35 u_long 36 free_recvbuffs (void) 37 { 38 return free_recvbufs; 39 } 40 41 u_long 42 full_recvbuffs (void) 43 { 44 return free_recvbufs; 45 } 46 47 u_long 48 total_recvbuffs (void) 49 { 50 return free_recvbufs; 51 } 52 53 u_long 54 lowater_additions(void) 55 { 56 return lowater_adds; 57 } 58 59 static void 60 initialise_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 71 static void 72 create_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 91 void 92 init_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 129 struct recvbuf * 130 getrecvbufs(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 */ 180 void 181 freerecvbuf( 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 195 void 196 add_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 217 struct recvbuf * 218 get_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 246 struct recvbuf * 247 get_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