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.15 by root, Mon Jun 24 00:04:26 2019 UTC vs.
Revision 1.18 by root, Mon Jun 24 04:54:08 2019 UTC

198 linuxaio_iocbps [fd]->io.aio_buf = 0; 198 linuxaio_iocbps [fd]->io.aio_buf = 0;
199 anfds [fd].events = 0; 199 anfds [fd].events = 0;
200 fd_change (EV_A_ fd, 0); 200 fd_change (EV_A_ fd, 0);
201 201
202 /* feed events, we do not expect or handle POLLNVAL */ 202 /* feed events, we do not expect or handle POLLNVAL */
203 if (ecb_expect_false (res & POLLNVAL)) 203 if (expect_false (res & POLLNVAL))
204 fd_kill (EV_A_ fd); 204 fd_kill (EV_A_ fd);
205 else 205 else
206 fd_event ( 206 fd_event (
207 EV_A_ 207 EV_A_
208 fd, 208 fd,
229 229
230 if (head == tail) 230 if (head == tail)
231 return 0; 231 return 0;
232 232
233 /* bail out if the ring buffer doesn't match the expected layout */ 233 /* bail out if the ring buffer doesn't match the expected layout */
234 if (ecb_expect_false (ring->magic != AIO_RING_MAGIC) 234 if (expect_false (ring->magic != AIO_RING_MAGIC)
235 || ring->incompat_features != AIO_RING_INCOMPAT_FEATURES 235 || ring->incompat_features != AIO_RING_INCOMPAT_FEATURES
236 || 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]? */
237 return 0; 237 return 0;
238 238
239 /* make sure the events up to tail are visible */ 239 /* make sure the events up to tail are visible */
240 ECB_MEMORY_FENCE_ACQUIRE; 240 ECB_MEMORY_FENCE_ACQUIRE;
241 241
246 { 246 {
247 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);
248 linuxaio_parse_events (EV_A_ ring->io_events, tail); 248 linuxaio_parse_events (EV_A_ ring->io_events, tail);
249 } 249 }
250 250
251 /* TODO: we only need a compiler barrier here, not a read fence */
252 ECB_MEMORY_FENCE_RELEASE;
251 /* as an extension to C, we hope that the volatile will makethis atomic and once-only */ 253 /* as an extension to C, we hope that the volatile will make this atomic and once-only */
252 *(volatile unsigned *)&ring->head = tail; 254 *(volatile unsigned *)&ring->head = tail;
253 /* make sure kernel can see our new head value - probably not required */ 255 /* make sure kernel can see our new head value - probably not required */
254 ECB_MEMORY_FENCE_RELEASE; 256 ECB_MEMORY_FENCE_RELEASE;
255 257
256 return 1; 258 return 1;
260inline_size 262inline_size
261void 263void
262linuxaio_get_events (EV_P_ ev_tstamp timeout) 264linuxaio_get_events (EV_P_ ev_tstamp timeout)
263{ 265{
264 struct timespec ts; 266 struct timespec ts;
265 struct io_event ioev; 267 struct io_event ioev[1];
266 int res; 268 int res;
267 269
268 if (linuxaio_get_events_from_ring (EV_A)) 270 if (linuxaio_get_events_from_ring (EV_A))
269 return; 271 return;
270 272
273 /* if the ring buffer changes layout, but so be it */ 275 /* if the ring buffer changes layout, but so be it */
274 276
275 ts.tv_sec = (long)timeout; 277 ts.tv_sec = (long)timeout;
276 ts.tv_nsec = (long)((timeout - ts.tv_sec) * 1e9); 278 ts.tv_nsec = (long)((timeout - ts.tv_sec) * 1e9);
277 279
278 res = ev_io_getevents (linuxaio_ctx, 1, 1, &ioev, &ts); 280 res = ev_io_getevents (linuxaio_ctx, 1, sizeof (ioev) / sizeof (ioev [0]), ioev, &ts);
279 281
280 if (res < 0) 282 if (res < 0)
281 if (errno == EINTR) 283 if (errno == EINTR)
282 /* ignored */; 284 /* ignored */;
283 else 285 else
284 ev_syserr ("(libev) linuxaio io_getevents"); 286 ev_syserr ("(libev) linuxaio io_getevents");
285 else if (res) 287 else if (res)
286 { 288 {
287 /* at least one event received, handle it and any remaining ones in the ring buffer */ 289 /* at least one event received, handle it and any remaining ones in the ring buffer */
288 linuxaio_parse_events (EV_A_ &ioev, 1); 290 linuxaio_parse_events (EV_A_ ioev, res);
289 linuxaio_get_events_from_ring (EV_A); 291 linuxaio_get_events_from_ring (EV_A);
290 } 292 }
291} 293}
292 294
293#if EPOLL_FALLBACK 295#if EPOLL_FALLBACK
318 /* which allows us to pinpoint the errornous iocb */ 320 /* which allows us to pinpoint the errornous iocb */
319 for (submitted = 0; submitted < linuxaio_submitcnt; ) 321 for (submitted = 0; submitted < linuxaio_submitcnt; )
320 { 322 {
321 int res = ev_io_submit (linuxaio_ctx, linuxaio_submitcnt - submitted, linuxaio_submits + submitted); 323 int res = ev_io_submit (linuxaio_ctx, linuxaio_submitcnt - submitted, linuxaio_submits + submitted);
322 324
323 if (ecb_expect_false (res < 0)) 325 if (expect_false (res < 0))
324 if (errno == EAGAIN) 326 if (errno == EAGAIN)
325 { 327 {
326 /* This happens when the ring buffer is full, at least. I assume this means 328 /* This happens when the ring buffer is full, at least. I assume this means
327 * that the event was queued synchronously during io_submit, and thus 329 * that the event was queued synchronously during io_submit, and thus
328 * the buffer overflowed. 330 * the buffer overflowed.
374 for (;;) 376 for (;;)
375 { 377 {
376 int idx; 378 int idx;
377 int res = epoll_wait (backend_fd, events, sizeof (events) / sizeof (events [0]), 0); 379 int res = epoll_wait (backend_fd, events, sizeof (events) / sizeof (events [0]), 0);
378 380
379 if (ecb_expect_false (res < 0)) 381 if (expect_false (res < 0))
380 ev_syserr ("(libev) linuxaio epoll_wait"); 382 ev_syserr ("(libev) linuxaio epoll_wait");
381 else if (!res) 383 else if (!res)
382 break; 384 break;
383 385
384 for (idx = res; idx--; ) 386 for (idx = res; idx--; )

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines