… | |
… | |
42 | #include <linux/aio_abi.h> |
42 | #include <linux/aio_abi.h> |
43 | |
43 | |
44 | /* we try to fill 4kB pages exactly. |
44 | /* we try to fill 4kB pages exactly. |
45 | * the ring buffer header is 32 bytes, every io event is 32 bytes. |
45 | * the ring buffer header is 32 bytes, every io event is 32 bytes. |
46 | * the kernel takes the io event number, doubles it, adds 2, adds the ring buffer. |
46 | * the kernel takes the io event number, doubles it, adds 2, adds the ring buffer. |
47 | * therefore the calculation below will use "exactly" 8kB for the ring buffer |
47 | * therefore the calculation below will use "exactly" 4kB for the ring buffer |
48 | */ |
48 | */ |
49 | #define EV_LINUXAIO_DEPTH (256 / 2 - 2 - 1) /* max. number of io events per batch */ |
49 | #define EV_LINUXAIO_DEPTH (128 / 2 - 2 - 1) /* max. number of io events per batch */ |
50 | |
50 | |
51 | /*****************************************************************************/ |
51 | /*****************************************************************************/ |
52 | /* syscall wrapdadoop */ |
52 | /* syscall wrapdadoop */ |
53 | |
53 | |
54 | #include <sys/syscall.h> /* no glibc wrappers */ |
54 | #include <sys/syscall.h> /* no glibc wrappers */ |
… | |
… | |
205 | static int |
205 | static int |
206 | linuxaio_get_events_from_ring (EV_P) |
206 | linuxaio_get_events_from_ring (EV_P) |
207 | { |
207 | { |
208 | struct aio_ring *ring = (struct aio_ring *)linuxaio_ctx; |
208 | struct aio_ring *ring = (struct aio_ring *)linuxaio_ctx; |
209 | |
209 | |
210 | ECB_MEMORY_FENCE_ACQUIRE; |
|
|
211 | |
|
|
212 | unsigned head = ring->head; |
210 | unsigned head = ring->head; |
213 | unsigned tail = *(volatile unsigned *)&ring->tail; |
211 | unsigned tail = *(volatile unsigned *)&ring->tail; |
214 | |
212 | |
215 | if (head == tail) |
213 | if (head == tail) |
216 | return 0; |
214 | return 0; |
… | |
… | |
219 | if (ecb_expect_false (ring->magic != AIO_RING_MAGIC) |
217 | if (ecb_expect_false (ring->magic != AIO_RING_MAGIC) |
220 | || ring->incompat_features != AIO_RING_INCOMPAT_FEATURES |
218 | || ring->incompat_features != AIO_RING_INCOMPAT_FEATURES |
221 | || ring->header_length != sizeof (struct aio_ring)) /* TODO: or use it to find io_event[0]? */ |
219 | || ring->header_length != sizeof (struct aio_ring)) /* TODO: or use it to find io_event[0]? */ |
222 | return 0; |
220 | return 0; |
223 | |
221 | |
|
|
222 | ECB_MEMORY_FENCE_ACQUIRE; |
|
|
223 | |
224 | /* parse all available events, but only once, to avoid starvation */ |
224 | /* parse all available events, but only once, to avoid starvation */ |
225 | if (tail > head) /* normal case around */ |
225 | if (tail > head) /* normal case around */ |
226 | linuxaio_parse_events (EV_A_ ring->io_events + head, tail - head); |
226 | linuxaio_parse_events (EV_A_ ring->io_events + head, tail - head); |
227 | else /* wrapped around */ |
227 | else /* wrapped around */ |
228 | { |
228 | { |
… | |
… | |
255 | ts.tv_nsec = (long)((timeout - ts.tv_sec) * 1e9); |
255 | ts.tv_nsec = (long)((timeout - ts.tv_sec) * 1e9); |
256 | |
256 | |
257 | res = ev_io_getevents (linuxaio_ctx, 1, 1, &ioev, &ts); |
257 | res = ev_io_getevents (linuxaio_ctx, 1, 1, &ioev, &ts); |
258 | |
258 | |
259 | if (res < 0) |
259 | if (res < 0) |
260 | ev_syserr ("(libev) io_getevents"); |
260 | ev_syserr ("(libev) linuxaio io_getevents"); |
261 | else if (res) |
261 | else if (res) |
262 | { |
262 | { |
263 | /* at least one event received, handle it and any remaining ones in the ring buffer */ |
263 | /* at least one event received, handle it and any remaining ones in the ring buffer */ |
264 | linuxaio_parse_events (EV_A_ &ioev, 1); |
264 | linuxaio_parse_events (EV_A_ &ioev, 1); |
265 | linuxaio_get_events_from_ring (EV_A); |
265 | linuxaio_get_events_from_ring (EV_A); |
… | |
… | |
294 | linuxaio_submitcnt -= submitted; |
294 | linuxaio_submitcnt -= submitted; |
295 | timeout = 0; |
295 | timeout = 0; |
296 | break; |
296 | break; |
297 | } |
297 | } |
298 | else |
298 | else |
299 | ev_syserr ("(libev) io_submit"); |
299 | ev_syserr ("(libev) linuxaio io_submit"); |
300 | |
300 | |
301 | submitted += res; |
301 | submitted += res; |
302 | } |
302 | } |
303 | |
303 | |
304 | linuxaio_submitcnt = 0; |
304 | linuxaio_submitcnt = 0; |
… | |
… | |
350 | linuxaio_destroy (EV_A); |
350 | linuxaio_destroy (EV_A); |
351 | linuxaio_submitcnt = 0; /* all pointers were invalidated */ |
351 | linuxaio_submitcnt = 0; /* all pointers were invalidated */ |
352 | |
352 | |
353 | linuxaio_ctx = 0; |
353 | linuxaio_ctx = 0; |
354 | while (ev_io_setup (EV_LINUXAIO_DEPTH, &linuxaio_ctx) < 0) |
354 | while (ev_io_setup (EV_LINUXAIO_DEPTH, &linuxaio_ctx) < 0) |
355 | ev_syserr ("(libev) io_setup"); |
355 | ev_syserr ("(libev) linuxaio io_setup"); |
356 | |
356 | |
357 | fd_rearm_all (EV_A); |
357 | fd_rearm_all (EV_A); |
358 | } |
358 | } |
359 | |
359 | |