ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/libev/ev_linuxaio.c
(Generate patch)

Comparing libev/ev_linuxaio.c (file contents):
Revision 1.12 by root, Sun Jun 23 23:02:09 2019 UTC vs.
Revision 1.15 by root, Mon Jun 24 00:04:26 2019 UTC

219static int 219static int
220linuxaio_get_events_from_ring (EV_P) 220linuxaio_get_events_from_ring (EV_P)
221{ 221{
222 struct aio_ring *ring = (struct aio_ring *)linuxaio_ctx; 222 struct aio_ring *ring = (struct aio_ring *)linuxaio_ctx;
223 223
224 unsigned head = ring->head; 224 /* the kernel reads and writes both of these variables, */
225 /* as a C extension, we assume that volatile use here */
226 /* both makes reads atomic and once-only */
227 unsigned head = *(volatile unsigned *)&ring->head;
225 unsigned tail = *(volatile unsigned *)&ring->tail; 228 unsigned tail = *(volatile unsigned *)&ring->tail;
226 229
227 if (head == tail) 230 if (head == tail)
228 return 0; 231 return 0;
229 232
243 { 246 {
244 linuxaio_parse_events (EV_A_ ring->io_events + head, ring->nr - head); 247 linuxaio_parse_events (EV_A_ ring->io_events + head, ring->nr - head);
245 linuxaio_parse_events (EV_A_ ring->io_events, tail); 248 linuxaio_parse_events (EV_A_ ring->io_events, tail);
246 } 249 }
247 250
251 /* as an extension to C, we hope that the volatile will makethis atomic and once-only */
248 *(volatile unsigned *)&ring->head = tail; 252 *(volatile unsigned *)&ring->head = tail;
249 /* make sure kernel can see our new head value - probably not required */ 253 /* make sure kernel can see our new head value - probably not required */
250 ECB_MEMORY_FENCE_RELEASE; 254 ECB_MEMORY_FENCE_RELEASE;
251 255
252 return 1; 256 return 1;
332 break; 336 break;
333 } 337 }
334#if EPOLL_FALLBACK 338#if EPOLL_FALLBACK
335 else if (errno == EINVAL) 339 else if (errno == EINVAL)
336 { 340 {
337 /* This hapΓΌpens for unsupported fds, officially, but in my testing, 341 /* This happens for unsupported fds, officially, but in my testing,
338 * also randomly happens for supported fds. We fall back to good old 342 * also randomly happens for supported fds. We fall back to good old
339 * poll() here, under the assumption that this is a very rare case. 343 * poll() here, under the assumption that this is a very rare case.
344 * See https://lore.kernel.org/patchwork/patch/1047453/ for evidence
345 * that the problem is known, but ignored.
340 */ 346 */
341 struct iocb *iocb = linuxaio_submits [submitted]; 347 struct iocb *iocb = linuxaio_submits [submitted];
342 res = 1; /* skip this iocb */ 348 res = 1; /* skip this iocb */
343 349
344 linuxaio_rearm_epoll (EV_A_ iocb, EPOLL_CTL_ADD); 350 linuxaio_rearm_epoll (EV_A_ iocb, EPOLL_CTL_ADD);
400int 406int
401linuxaio_init (EV_P_ int flags) 407linuxaio_init (EV_P_ int flags)
402{ 408{
403 /* would be great to have a nice test for IOCB_CMD_POLL instead */ 409 /* would be great to have a nice test for IOCB_CMD_POLL instead */
404 /* also: test some semi-common fd types, such as files and ttys in recommended_backends */ 410 /* also: test some semi-common fd types, such as files and ttys in recommended_backends */
405 if (ev_linux_version () < 0x041200) /* 4.18 introduced IOCB_CMD_POLL */ 411#if EPOLL_FALLBACK
412 /* 4.19 made epoll work */
413 if (ev_linux_version () < 0x041300)
406 return 0; 414 return 0;
415#else
416 /* 4.18 introduced IOCB_CMD_POLL */
417 if (ev_linux_version () < 0x041200)
418 return 0;
419#endif
407 420
408 linuxaio_ctx = 0; 421 linuxaio_ctx = 0;
409 if (ev_io_setup (EV_LINUXAIO_DEPTH, &linuxaio_ctx) < 0) 422 if (ev_io_setup (EV_LINUXAIO_DEPTH, &linuxaio_ctx) < 0)
410 return 0; 423 return 0;
411 424
417 return 0; 430 return 0;
418 } 431 }
419 432
420 ev_io_init (EV_A_ &linuxaio_epoll_w, linuxaio_epoll_cb, backend_fd, EV_READ); 433 ev_io_init (EV_A_ &linuxaio_epoll_w, linuxaio_epoll_cb, backend_fd, EV_READ);
421 ev_io_start (EV_A_ &linuxaio_epoll_w); 434 ev_io_start (EV_A_ &linuxaio_epoll_w);
435 ev_unref (EV_A); /* watcher should not keep loop alive */
422#endif 436#endif
423 437
424 backend_modify = linuxaio_modify; 438 backend_modify = linuxaio_modify;
425 backend_poll = linuxaio_poll; 439 backend_poll = linuxaio_poll;
426 440
462 ev_syserr ("(libev) linuxaio epoll_create"); 476 ev_syserr ("(libev) linuxaio epoll_create");
463 477
464 ev_io_stop (EV_A_ &linuxaio_epoll_w); 478 ev_io_stop (EV_A_ &linuxaio_epoll_w);
465 ev_io_init (EV_A_ &linuxaio_epoll_w, linuxaio_epoll_cb, backend_fd, EV_READ); 479 ev_io_init (EV_A_ &linuxaio_epoll_w, linuxaio_epoll_cb, backend_fd, EV_READ);
466 ev_io_start (EV_A_ &linuxaio_epoll_w); 480 ev_io_start (EV_A_ &linuxaio_epoll_w);
467 ev_unref (EV_A); /* watcher should not keep loop alive */
468#endif 481#endif
469 482
470 fd_rearm_all (EV_A); 483 fd_rearm_all (EV_A);
471} 484}
472 485

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines