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.10 by root, Sun Jun 23 02:02:24 2019 UTC vs.
Revision 1.14 by root, Sun Jun 23 23:49:56 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
231 if (ecb_expect_false (ring->magic != AIO_RING_MAGIC) 234 if (ecb_expect_false (ring->magic != AIO_RING_MAGIC)
232 || ring->incompat_features != AIO_RING_INCOMPAT_FEATURES 235 || ring->incompat_features != AIO_RING_INCOMPAT_FEATURES
233 || ring->header_length != sizeof (struct aio_ring)) /* TODO: or use it to find io_event[0]? */ 236 || ring->header_length != sizeof (struct aio_ring)) /* TODO: or use it to find io_event[0]? */
234 return 0; 237 return 0;
235 238
239 /* make sure the events up to tail are visible */
236 ECB_MEMORY_FENCE_ACQUIRE; 240 ECB_MEMORY_FENCE_ACQUIRE;
237 241
238 /* parse all available events, but only once, to avoid starvation */ 242 /* parse all available events, but only once, to avoid starvation */
239 if (tail > head) /* normal case around */ 243 if (tail > head) /* normal case around */
240 linuxaio_parse_events (EV_A_ ring->io_events + head, tail - head); 244 linuxaio_parse_events (EV_A_ ring->io_events + head, tail - head);
242 { 246 {
243 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);
244 linuxaio_parse_events (EV_A_ ring->io_events, tail); 248 linuxaio_parse_events (EV_A_ ring->io_events, tail);
245 } 249 }
246 250
247 ring->head = tail; 251 /* as an extension to C, we hope that the volatile will makethis atomic and once-only */
252 *(volatile unsigned *)&ring->head = tail;
253 /* make sure kernel can see our new head value - probably not required */
254 ECB_MEMORY_FENCE_RELEASE;
248 255
249 return 1; 256 return 1;
250} 257}
251 258
252/* read at least one event from kernel, or timeout */ 259/* read at least one event from kernel, or timeout */
414 return 0; 421 return 0;
415 } 422 }
416 423
417 ev_io_init (EV_A_ &linuxaio_epoll_w, linuxaio_epoll_cb, backend_fd, EV_READ); 424 ev_io_init (EV_A_ &linuxaio_epoll_w, linuxaio_epoll_cb, backend_fd, EV_READ);
418 ev_io_start (EV_A_ &linuxaio_epoll_w); 425 ev_io_start (EV_A_ &linuxaio_epoll_w);
426 ev_unref (EV_A); /* watcher should not keep loop alive */
419#endif 427#endif
420 428
421 backend_modify = linuxaio_modify; 429 backend_modify = linuxaio_modify;
422 backend_poll = linuxaio_poll; 430 backend_poll = linuxaio_poll;
423 431
459 ev_syserr ("(libev) linuxaio epoll_create"); 467 ev_syserr ("(libev) linuxaio epoll_create");
460 468
461 ev_io_stop (EV_A_ &linuxaio_epoll_w); 469 ev_io_stop (EV_A_ &linuxaio_epoll_w);
462 ev_io_init (EV_A_ &linuxaio_epoll_w, linuxaio_epoll_cb, backend_fd, EV_READ); 470 ev_io_init (EV_A_ &linuxaio_epoll_w, linuxaio_epoll_cb, backend_fd, EV_READ);
463 ev_io_start (EV_A_ &linuxaio_epoll_w); 471 ev_io_start (EV_A_ &linuxaio_epoll_w);
464 ev_unref (EV_A); /* watcher should not keep loop alive */
465#endif 472#endif
466 473
467 fd_rearm_all (EV_A); 474 fd_rearm_all (EV_A);
468} 475}
469 476

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines