aio: convert aio_poll() to g_poll(3)
AioHandler already has a GPollFD so we can directly use its events/revents. Add the int pollfds_idx field to AioContext so we can map g_poll(3) results back to AioHandlers. Reuse aio_dispatch() to invoke handlers after g_poll(3). Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com> Reviewed-by: Laszlo Ersek <lersek@redhat.com> Message-id: 1361356113-11049-10-git-send-email-stefanha@redhat.com Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
This commit is contained in:
		
							parent
							
								
									d0c8d2c05f
								
							
						
					
					
						commit
						6b5f876252
					
				
							
								
								
									
										67
									
								
								aio-posix.c
									
									
									
									
									
								
							
							
						
						
									
										67
									
								
								aio-posix.c
									
									
									
									
									
								
							| @ -25,6 +25,7 @@ struct AioHandler | ||||
|     IOHandler *io_write; | ||||
|     AioFlushHandler *io_flush; | ||||
|     int deleted; | ||||
|     int pollfds_idx; | ||||
|     void *opaque; | ||||
|     QLIST_ENTRY(AioHandler) node; | ||||
| }; | ||||
| @ -85,6 +86,7 @@ void aio_set_fd_handler(AioContext *ctx, | ||||
|         node->io_write = io_write; | ||||
|         node->io_flush = io_flush; | ||||
|         node->opaque = opaque; | ||||
|         node->pollfds_idx = -1; | ||||
| 
 | ||||
|         node->pfd.events = (io_read ? G_IO_IN | G_IO_HUP : 0); | ||||
|         node->pfd.events |= (io_write ? G_IO_OUT : 0); | ||||
| @ -177,10 +179,7 @@ static bool aio_dispatch(AioContext *ctx) | ||||
| 
 | ||||
| bool aio_poll(AioContext *ctx, bool blocking) | ||||
| { | ||||
|     static struct timeval tv0; | ||||
|     AioHandler *node; | ||||
|     fd_set rdfds, wrfds; | ||||
|     int max_fd = -1; | ||||
|     int ret; | ||||
|     bool busy, progress; | ||||
| 
 | ||||
| @ -206,12 +205,13 @@ bool aio_poll(AioContext *ctx, bool blocking) | ||||
| 
 | ||||
|     ctx->walking_handlers++; | ||||
| 
 | ||||
|     FD_ZERO(&rdfds); | ||||
|     FD_ZERO(&wrfds); | ||||
|     g_array_set_size(ctx->pollfds, 0); | ||||
| 
 | ||||
|     /* fill fd sets */ | ||||
|     /* fill pollfds */ | ||||
|     busy = false; | ||||
|     QLIST_FOREACH(node, &ctx->aio_handlers, node) { | ||||
|         node->pollfds_idx = -1; | ||||
| 
 | ||||
|         /* If there aren't pending AIO operations, don't invoke callbacks.
 | ||||
|          * Otherwise, if there are no AIO requests, qemu_aio_wait() would | ||||
|          * wait indefinitely. | ||||
| @ -222,13 +222,13 @@ bool aio_poll(AioContext *ctx, bool blocking) | ||||
|             } | ||||
|             busy = true; | ||||
|         } | ||||
|         if (!node->deleted && node->io_read) { | ||||
|             FD_SET(node->pfd.fd, &rdfds); | ||||
|             max_fd = MAX(max_fd, node->pfd.fd + 1); | ||||
|         } | ||||
|         if (!node->deleted && node->io_write) { | ||||
|             FD_SET(node->pfd.fd, &wrfds); | ||||
|             max_fd = MAX(max_fd, node->pfd.fd + 1); | ||||
|         if (!node->deleted && node->pfd.events) { | ||||
|             GPollFD pfd = { | ||||
|                 .fd = node->pfd.fd, | ||||
|                 .events = node->pfd.events, | ||||
|             }; | ||||
|             node->pollfds_idx = ctx->pollfds->len; | ||||
|             g_array_append_val(ctx->pollfds, pfd); | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
| @ -240,41 +240,22 @@ bool aio_poll(AioContext *ctx, bool blocking) | ||||
|     } | ||||
| 
 | ||||
|     /* wait until next event */ | ||||
|     ret = select(max_fd, &rdfds, &wrfds, NULL, blocking ? NULL : &tv0); | ||||
|     ret = g_poll((GPollFD *)ctx->pollfds->data, | ||||
|                  ctx->pollfds->len, | ||||
|                  blocking ? -1 : 0); | ||||
| 
 | ||||
|     /* if we have any readable fds, dispatch event */ | ||||
|     if (ret > 0) { | ||||
|         /* we have to walk very carefully in case
 | ||||
|          * qemu_aio_set_fd_handler is called while we're walking */ | ||||
|         node = QLIST_FIRST(&ctx->aio_handlers); | ||||
|         while (node) { | ||||
|             AioHandler *tmp; | ||||
| 
 | ||||
|             ctx->walking_handlers++; | ||||
| 
 | ||||
|             if (!node->deleted && | ||||
|                 FD_ISSET(node->pfd.fd, &rdfds) && | ||||
|                 node->io_read) { | ||||
|                 node->io_read(node->opaque); | ||||
|                 progress = true; | ||||
|             } | ||||
|             if (!node->deleted && | ||||
|                 FD_ISSET(node->pfd.fd, &wrfds) && | ||||
|                 node->io_write) { | ||||
|                 node->io_write(node->opaque); | ||||
|                 progress = true; | ||||
|             } | ||||
| 
 | ||||
|             tmp = node; | ||||
|             node = QLIST_NEXT(node, node); | ||||
| 
 | ||||
|             ctx->walking_handlers--; | ||||
| 
 | ||||
|             if (!ctx->walking_handlers && tmp->deleted) { | ||||
|                 QLIST_REMOVE(tmp, node); | ||||
|                 g_free(tmp); | ||||
|         QLIST_FOREACH(node, &ctx->aio_handlers, node) { | ||||
|             if (node->pollfds_idx != -1) { | ||||
|                 GPollFD *pfd = &g_array_index(ctx->pollfds, GPollFD, | ||||
|                                               node->pollfds_idx); | ||||
|                 node->pfd.revents = pfd->revents; | ||||
|             } | ||||
|         } | ||||
|         if (aio_dispatch(ctx)) { | ||||
|             progress = true; | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     assert(progress || busy); | ||||
|  | ||||
							
								
								
									
										2
									
								
								async.c
									
									
									
									
									
								
							
							
						
						
									
										2
									
								
								async.c
									
									
									
									
									
								
							| @ -174,6 +174,7 @@ aio_ctx_finalize(GSource     *source) | ||||
| 
 | ||||
|     aio_set_event_notifier(ctx, &ctx->notifier, NULL, NULL); | ||||
|     event_notifier_cleanup(&ctx->notifier); | ||||
|     g_array_free(ctx->pollfds, TRUE); | ||||
| } | ||||
| 
 | ||||
| static GSourceFuncs aio_source_funcs = { | ||||
| @ -198,6 +199,7 @@ AioContext *aio_context_new(void) | ||||
| { | ||||
|     AioContext *ctx; | ||||
|     ctx = (AioContext *) g_source_new(&aio_source_funcs, sizeof(AioContext)); | ||||
|     ctx->pollfds = g_array_new(FALSE, FALSE, sizeof(GPollFD)); | ||||
|     event_notifier_init(&ctx->notifier, false); | ||||
|     aio_set_event_notifier(ctx, &ctx->notifier,  | ||||
|                            (EventNotifierHandler *) | ||||
|  | ||||
| @ -63,6 +63,9 @@ typedef struct AioContext { | ||||
| 
 | ||||
|     /* Used for aio_notify.  */ | ||||
|     EventNotifier notifier; | ||||
| 
 | ||||
|     /* GPollFDs for aio_poll() */ | ||||
|     GArray *pollfds; | ||||
| } AioContext; | ||||
| 
 | ||||
| /* Returns 1 if there are still outstanding AIO requests; 0 otherwise */ | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user
	 Stefan Hajnoczi
						Stefan Hajnoczi