Initial import from FreeBSD RELENG_4:
[games.git] / contrib / ntp / libntp / recvbuff.c
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 }