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