Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(31)

Side by Side Diff: c/poll.c

Issue 2842333002: Updated netty-tcnative to version 2.0.0.Final (Closed)
Patch Set: Created 3 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « c/os_win32_system.c ('k') | c/pool.c » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 /* Licensed to the Apache Software Foundation (ASF) under one or more
2 * contributor license agreements. See the NOTICE file distributed with
3 * this work for additional information regarding copyright ownership.
4 * The ASF licenses this file to You under the Apache License, Version 2.0
5 * (the "License"); you may not use this file except in compliance with
6 * the License. You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 /*
18 *
19 * @author Mladen Turk
20 * @version $Id: poll.c 1667243 2015-03-17 10:28:05Z markt $
21 */
22
23 #include "tcn.h"
24
25 #ifdef TCN_DO_STATISTICS
26 static int sp_created = 0;
27 static int sp_destroyed = 0;
28 static int sp_cleared = 0;
29 #endif
30
31 /* Internal poll structure for queryset
32 */
33 typedef struct tcn_pollset {
34 apr_pool_t *pool;
35 apr_int32_t nelts;
36 apr_int32_t nalloc;
37 apr_pollset_t *pollset;
38 jlong *set;
39 apr_interval_time_t default_timeout;
40 /* A ring containing all of the pollfd_t that are active
41 */
42 APR_RING_HEAD(pfd_poll_ring_t, tcn_pfde_t) poll_ring;
43 /* A ring of pollfd_t that have been used, and then _remove()'d
44 */
45 APR_RING_HEAD(pfd_free_ring_t, tcn_pfde_t) free_ring;
46 /* A ring of pollfd_t where rings that have been _remove()`ed but
47 * might still be inside a _poll()
48 */
49 APR_RING_HEAD(pfd_dead_ring_t, tcn_pfde_t) dead_ring;
50 #ifdef TCN_DO_STATISTICS
51 int sp_added;
52 int sp_max_count;
53 int sp_poll;
54 int sp_polled;
55 int sp_max_polled;
56 int sp_remove;
57 int sp_removed;
58 int sp_maintained;
59 int sp_max_maintained;
60 int sp_err_poll;
61 int sp_poll_timeout;
62 int sp_overflow;
63 int sp_equals;
64 int sp_eintr;
65 #endif
66 } tcn_pollset_t;
67
68 #ifdef TCN_DO_STATISTICS
69 static void sp_poll_statistics(tcn_pollset_t *p)
70 {
71 fprintf(stderr, "Pollset Statistics ......\n");
72 fprintf(stderr, "Number of added sockets : %d\n", p->sp_added);
73 fprintf(stderr, "Max. number of sockets : %d\n", p->sp_max_count);
74 fprintf(stderr, "Poll calls : %d\n", p->sp_poll);
75 fprintf(stderr, "Poll timeouts : %d\n", p->sp_poll_timeout);
76 fprintf(stderr, "Poll errors : %d\n", p->sp_err_poll);
77 fprintf(stderr, "Poll overflows : %d\n", p->sp_overflow);
78 fprintf(stderr, "Polled sockets : %d\n", p->sp_polled);
79 fprintf(stderr, "Max. Polled sockets : %d\n", p->sp_max_polled);
80 fprintf(stderr, "Poll remove : %d\n", p->sp_remove);
81 fprintf(stderr, "Total removed : %d\n", p->sp_removed);
82 fprintf(stderr, "Maintained : %d\n", p->sp_maintained);
83 fprintf(stderr, "Max. maintained : %d\n", p->sp_max_maintained);
84 fprintf(stderr, "Number of duplicates : %d\n", p->sp_equals);
85 fprintf(stderr, "Number of interrupts : %d\n", p->sp_eintr);
86
87 }
88
89 static apr_status_t sp_poll_cleanup(void *data)
90 {
91 sp_cleared++;
92 sp_poll_statistics(data);
93 return APR_SUCCESS;
94 }
95
96 void sp_poll_dump_statistics()
97 {
98 fprintf(stderr, "Poll Statistics .........\n");
99 fprintf(stderr, "Polls created : %d\n", sp_created);
100 fprintf(stderr, "Polls destroyed : %d\n", sp_destroyed);
101 fprintf(stderr, "Polls cleared : %d\n", sp_cleared);
102 }
103 #endif
104
105 TCN_IMPLEMENT_CALL(jlong, Poll, create)(TCN_STDARGS, jint size,
106 jlong pool, jint flags,
107 jlong default_timeout)
108 {
109 apr_pool_t *p = J2P(pool, apr_pool_t *);
110 apr_pollset_t *pollset = NULL;
111 tcn_pollset_t *tps = NULL;
112 apr_uint32_t f = (apr_uint32_t)flags | APR_POLLSET_NOCOPY;
113 UNREFERENCED(o);
114 TCN_ASSERT(pool != 0);
115
116 if (f & APR_POLLSET_THREADSAFE) {
117 apr_status_t rv = apr_pollset_create(&pollset, (apr_uint32_t)size, p, f) ;
118 if (rv == APR_ENOTIMPL)
119 f &= ~APR_POLLSET_THREADSAFE;
120 else if (rv != APR_SUCCESS) {
121 tcn_ThrowAPRException(e, rv);
122 goto cleanup;
123 }
124 }
125 if (pollset == NULL) {
126 TCN_THROW_IF_ERR(apr_pollset_create(&pollset,
127 (apr_uint32_t)size, p, f), pollset);
128 }
129 tps = apr_pcalloc(p, sizeof(tcn_pollset_t));
130 TCN_CHECK_ALLOCATED(tps);
131 tps->pollset = pollset;
132 tps->set = apr_pcalloc(p, size * sizeof(jlong) * 2);
133 TCN_CHECK_ALLOCATED(tps->set);
134 APR_RING_INIT(&tps->poll_ring, tcn_pfde_t, link);
135 APR_RING_INIT(&tps->free_ring, tcn_pfde_t, link);
136 APR_RING_INIT(&tps->dead_ring, tcn_pfde_t, link);
137
138 tps->nelts = 0;
139 tps->nalloc = size;
140 tps->pool = p;
141 tps->default_timeout = J2T(default_timeout);
142 #ifdef TCN_DO_STATISTICS
143 sp_created++;
144 apr_pool_cleanup_register(p, (const void *)tps,
145 sp_poll_cleanup,
146 apr_pool_cleanup_null);
147 #endif
148 cleanup:
149 return P2J(tps);
150 }
151
152 TCN_IMPLEMENT_CALL(jint, Poll, destroy)(TCN_STDARGS, jlong pollset)
153 {
154 tcn_pollset_t *p = J2P(pollset, tcn_pollset_t *);
155
156 UNREFERENCED_STDARGS;
157 TCN_ASSERT(pollset != 0);
158 #ifdef TCN_DO_STATISTICS
159 sp_destroyed++;
160 apr_pool_cleanup_kill(p->pool, p, sp_poll_cleanup);
161 sp_poll_statistics(p);
162 #endif
163 return (jint)apr_pollset_destroy(p->pollset);
164 }
165
166 static apr_status_t do_add(tcn_pollset_t *p, tcn_socket_t *s,
167 apr_int16_t reqevents,
168 apr_interval_time_t socket_timeout)
169 {
170
171 apr_status_t rv;
172 apr_interval_time_t timeout = socket_timeout;
173 tcn_pfde_t *elem = NULL;
174
175 if (p->nelts == p->nalloc) {
176 #ifdef TCN_DO_STATISTICS
177 p->sp_overflow++;
178 #endif
179 return APR_ENOMEM;
180 }
181 if (s->pe != NULL) {
182 /* Socket is already added to the pollset.
183 */
184 #ifdef TCN_DO_STATISTICS
185 p->sp_equals++;
186 #endif
187 return APR_EEXIST;
188 }
189 if (timeout == TCN_NO_SOCKET_TIMEOUT) {
190 timeout = p->default_timeout;
191 }
192 if (timeout > 0)
193 s->last_active = apr_time_now();
194 else
195 s->last_active = 0;
196 s->timeout = socket_timeout;
197 if (!APR_RING_EMPTY(&p->free_ring, tcn_pfde_t, link)) {
198 elem = APR_RING_FIRST(&p->free_ring);
199 APR_RING_REMOVE(elem, link);
200 }
201 else {
202 elem = (tcn_pfde_t *)apr_palloc(p->pool, sizeof(tcn_pfde_t));
203 APR_RING_ELEM_INIT(elem, link);
204 }
205 elem->fd.reqevents = reqevents;
206 elem->fd.desc_type = APR_POLL_SOCKET;
207 elem->fd.desc.s = s->sock;
208 elem->fd.client_data = s;
209 #ifdef TCN_DO_STATISTICS
210 p->sp_added++;
211 p->sp_max_count = TCN_MAX(p->sp_max_count, p->sp_added);
212 #endif
213 rv = apr_pollset_add(p->pollset, &elem->fd);
214 if (rv != APR_SUCCESS) {
215 APR_RING_INSERT_TAIL(&p->free_ring, elem, tcn_pfde_t, link);
216 }
217 else {
218 APR_RING_INSERT_TAIL(&p->poll_ring, elem, tcn_pfde_t, link);
219 s->pe = elem;
220 }
221 return rv;
222 }
223
224 TCN_IMPLEMENT_CALL(jint, Poll, add)(TCN_STDARGS, jlong pollset,
225 jlong socket, jint reqevents)
226 {
227 tcn_pollset_t *p = J2P(pollset, tcn_pollset_t *);
228 tcn_socket_t *s = J2P(socket, tcn_socket_t *);
229
230 UNREFERENCED_STDARGS;
231 TCN_ASSERT(socket != 0);
232
233 return (jint) do_add(p, s, (apr_int16_t)reqevents, TCN_NO_SOCKET_TIMEOUT);
234 }
235
236 TCN_IMPLEMENT_CALL(jint, Poll, addWithTimeout)(TCN_STDARGS, jlong pollset,
237 jlong socket, jint reqevents,
238 jlong socket_timeout)
239 {
240 tcn_pollset_t *p = J2P(pollset, tcn_pollset_t *);
241 tcn_socket_t *s = J2P(socket, tcn_socket_t *);
242
243 UNREFERENCED_STDARGS;
244 TCN_ASSERT(socket != 0);
245
246 return (jint) do_add(p, s, (apr_int16_t)reqevents, J2T(socket_timeout));
247 }
248
249 TCN_IMPLEMENT_CALL(jint, Poll, remove)(TCN_STDARGS, jlong pollset,
250 jlong socket)
251 {
252 apr_pollfd_t fd;
253 apr_status_t rv;
254 tcn_pollset_t *p = J2P(pollset, tcn_pollset_t *);
255 tcn_socket_t *s = J2P(socket, tcn_socket_t *);
256
257 UNREFERENCED_STDARGS;
258 TCN_ASSERT(socket != 0);
259
260 if (s->pe == NULL) {
261 /* Already removed */
262 return APR_NOTFOUND;
263 }
264 fd.desc_type = APR_POLL_SOCKET;
265 fd.desc.s = s->sock;
266 fd.client_data = s;
267 fd.reqevents = APR_POLLIN | APR_POLLOUT;
268 #ifdef TCN_DO_STATISTICS
269 p->sp_remove++;
270 #endif
271
272 rv = apr_pollset_remove(p->pollset, &fd);
273 APR_RING_REMOVE(s->pe, link);
274 APR_RING_INSERT_TAIL(&p->dead_ring, s->pe, tcn_pfde_t, link);
275 s->pe = NULL;
276 p->nelts--;
277 #ifdef TCN_DO_STATISTICS
278 p->sp_removed++;
279 #endif
280 return rv;
281 }
282
283
284 TCN_IMPLEMENT_CALL(jint, Poll, poll)(TCN_STDARGS, jlong pollset,
285 jlong timeout, jlongArray set,
286 jboolean remove)
287 {
288 const apr_pollfd_t *fd = NULL;
289 tcn_pollset_t *p = J2P(pollset, tcn_pollset_t *);
290 apr_int32_t i, num = 0;
291 apr_status_t rv = APR_SUCCESS;
292 apr_time_t now = 0;
293 apr_interval_time_t ptime = J2T(timeout);
294 UNREFERENCED(o);
295 TCN_ASSERT(pollset != 0);
296
297 #ifdef TCN_DO_STATISTICS
298 p->sp_poll++;
299 #endif
300
301 if (ptime > 0) {
302 tcn_pfde_t *ep;
303
304 now = apr_time_now();
305 /* Find the minimum timeout */
306 APR_RING_FOREACH(ep, &p->poll_ring, tcn_pfde_t, link)
307 {
308 apr_interval_time_t socket_timeout = 0;
309 tcn_socket_t *s = (tcn_socket_t *)ep->fd.client_data;
310 if (s->timeout == TCN_NO_SOCKET_TIMEOUT) {
311 socket_timeout = p->default_timeout;
312 }
313 else {
314 socket_timeout = s->timeout;
315 }
316 if (socket_timeout >= 0) {
317 apr_interval_time_t t = now - s->last_active;
318 if (t >= socket_timeout) {
319 ptime = 0;
320 break;
321 }
322 else {
323 ptime = TCN_MIN(socket_timeout - t, ptime);
324 }
325 }
326 }
327 }
328 else if (ptime < 0)
329 ptime = 0;
330 for (;;) {
331 rv = apr_pollset_poll(p->pollset, ptime, &num, &fd);
332 if (rv != APR_SUCCESS) {
333 if (APR_STATUS_IS_EINTR(rv)) {
334 #ifdef TCN_DO_STATISTICS
335 p->sp_eintr++;
336 #endif
337 continue;
338 }
339 TCN_ERROR_WRAP(rv);
340 #ifdef TCN_DO_STATISTICS
341 if (rv == TCN_TIMEUP)
342 p->sp_poll_timeout++;
343 else
344 p->sp_err_poll++;
345 #endif
346 num = (apr_int32_t)(-rv);
347 }
348 break;
349 }
350 /* Shift all PFDs in the Dead Ring to the Free Ring */
351 APR_RING_CONCAT(&p->free_ring, &p->dead_ring, tcn_pfde_t, link);
352 if (num > 0) {
353 #ifdef TCN_DO_STATISTICS
354 p->sp_polled += num;
355 p->sp_max_polled = TCN_MAX(p->sp_max_polled, num);
356 #endif
357 if (!remove)
358 now = apr_time_now();
359 for (i = 0; i < num; i++) {
360 tcn_socket_t *s = (tcn_socket_t *)fd->client_data;
361 p->set[i*2+0] = (jlong)(fd->rtnevents);
362 p->set[i*2+1] = P2J(s);
363 /* If a socket is registered for multiple events and the poller has
364 multiple events to return it may do as a single pair in this
365 array or as multiple pairs depending on implementation. On OSX at
366 least, multiple pairs have been observed. In this case do not try
367 and remove socket from the pollset for a second time else a crash
368 will result. */
369 if (remove) {
370 if (s->pe) {
371 apr_pollset_remove(p->pollset, fd);
372 APR_RING_REMOVE(s->pe, link);
373 APR_RING_INSERT_TAIL(&p->dead_ring, s->pe, tcn_pfde_t, link) ;
374 s->pe = NULL;
375 p->nelts--;
376 #ifdef TCN_DO_STATISTICS
377 p->sp_removed++;
378 #endif
379 }
380 }
381 else {
382 /* Update last active with the current time
383 * after the poll call.
384 */
385 s->last_active = now;
386 }
387 fd ++;
388 }
389 (*e)->SetLongArrayRegion(e, set, 0, num * 2, p->set);
390 }
391
392 return (jint)num;
393 }
394
395 TCN_IMPLEMENT_CALL(jint, Poll, maintain)(TCN_STDARGS, jlong pollset,
396 jlongArray set, jboolean remove)
397 {
398 tcn_pollset_t *p = J2P(pollset, tcn_pollset_t *);
399 apr_int32_t i = 0, num = 0;
400 apr_time_t now = apr_time_now();
401 tcn_pfde_t *ep, *ip;
402
403 UNREFERENCED(o);
404 TCN_ASSERT(pollset != 0);
405
406 /* Check for timeout sockets */
407 APR_RING_FOREACH_SAFE(ep, ip, &p->poll_ring, tcn_pfde_t, link)
408 {
409 apr_interval_time_t timeout = 0;
410 tcn_socket_t *s = (tcn_socket_t *)ep->fd.client_data;
411 if (s->timeout == TCN_NO_SOCKET_TIMEOUT) {
412 timeout = p->default_timeout;
413 }
414 else {
415 timeout = s->timeout;
416 }
417 if (timeout == -1) {
418 continue;
419 }
420 if ((now - s->last_active) >= timeout) {
421 p->set[num++] = P2J(s);
422 if (remove) {
423 APR_RING_REMOVE(ep, link);
424 APR_RING_INSERT_TAIL(&p->dead_ring, ep, tcn_pfde_t, link);
425 s->pe = NULL;
426 p->nelts--;
427 #ifdef TCN_DO_STATISTICS
428 p->sp_removed++;
429 #endif
430 }
431 }
432 }
433 if (num) {
434 #ifdef TCN_DO_STATISTICS
435 p->sp_maintained += num;
436 p->sp_max_maintained = TCN_MAX(p->sp_max_maintained, num);
437 #endif
438 if (remove) {
439 for (i = 0; i < num; i++) {
440 apr_pollfd_t fd;
441 tcn_socket_t *s = J2P(p->set[i], tcn_socket_t *);
442 fd.desc_type = APR_POLL_SOCKET;
443 fd.desc.s = s->sock;
444 fd.client_data = s;
445 fd.reqevents = APR_POLLIN | APR_POLLOUT;
446 apr_pollset_remove(p->pollset, &fd);
447 }
448 }
449 (*e)->SetLongArrayRegion(e, set, 0, num, p->set);
450 }
451 return (jint)num;
452 }
453
454 TCN_IMPLEMENT_CALL(void, Poll, setTtl)(TCN_STDARGS, jlong pollset,
455 jlong default_timeout)
456 {
457 tcn_pollset_t *p = J2P(pollset, tcn_pollset_t *);
458 UNREFERENCED_STDARGS;
459 p->default_timeout = J2T(default_timeout);
460 }
461
462 TCN_IMPLEMENT_CALL(jlong, Poll, getTtl)(TCN_STDARGS, jlong pollset)
463 {
464 tcn_pollset_t *p = J2P(pollset, tcn_pollset_t *);
465 UNREFERENCED_STDARGS;
466 return (jlong)p->default_timeout;
467 }
468
469 TCN_IMPLEMENT_CALL(jint, Poll, pollset)(TCN_STDARGS, jlong pollset,
470 jlongArray set)
471 {
472 tcn_pollset_t *p = J2P(pollset, tcn_pollset_t *);
473 apr_int32_t n = 0;
474 tcn_pfde_t *ep;
475
476 UNREFERENCED(o);
477 TCN_ASSERT(pollset != 0);
478
479 APR_RING_FOREACH(ep, &p->poll_ring, tcn_pfde_t, link)
480 {
481 apr_pollfd_t *fd = &ep->fd;
482 fd->rtnevents = APR_POLLHUP | APR_POLLIN;
483 p->set[n++] = (jlong)(fd->rtnevents);
484 p->set[n++] = P2J(fd->client_data);
485 }
486 if (n > 0)
487 (*e)->SetLongArrayRegion(e, set, 0, n, p->set);
488 return n / 2;
489 }
OLDNEW
« no previous file with comments | « c/os_win32_system.c ('k') | c/pool.c » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698