Dispatcher: remove async_done callback

This callback was only executed for message types that were registered
with DISPATCHER_ASYNC ack type. However, the async_done handler was
called immediately after the message-specific handler and was called in
the same thread, so the async_done stuff can just as easily be done from
within the message-specific handler. This allows to simplify the
dispatcher_register_handler() method to simply require a boolean
argument for whether the message type requires an ACK or not.

Signed-off-by: Jonathon Jongsma <jjongsma@redhat.com>
This commit is contained in:
Jonathon Jongsma 2017-09-06 14:11:59 -05:00
parent 037dedf5f6
commit 439fa1574f
3 changed files with 58 additions and 99 deletions

View File

@ -40,7 +40,7 @@ static void setup_dummy_signal_handler(void);
typedef struct DispatcherMessage {
size_t size;
int ack;
bool ack;
dispatcher_handle_message handler;
} DispatcherMessage;
@ -60,7 +60,6 @@ struct DispatcherPrivate {
void *payload; /* allocated as max of message sizes */
size_t payload_size; /* used to track realloc calls */
void *opaque;
dispatcher_handle_async_done handle_async_done;
dispatcher_handle_any_message any_handler;
};
@ -286,14 +285,12 @@ static int dispatcher_handle_single_read(Dispatcher *dispatcher)
} else {
spice_printerr("error: no handler for message type %d", type);
}
if (msg->ack == DISPATCHER_ACK) {
if (msg->ack) {
if (write_safe(dispatcher->priv->recv_fd,
(uint8_t*)&ack, sizeof(ack)) == -1) {
spice_printerr("error writing ack for message %d", type);
/* TODO: close socketpair? */
}
} else if (msg->ack == DISPATCHER_ASYNC && dispatcher->priv->handle_async_done) {
dispatcher->priv->handle_async_done(dispatcher->priv->opaque, type, payload);
}
return 1;
}
@ -329,7 +326,7 @@ void dispatcher_send_message(Dispatcher *dispatcher, uint32_t message_type,
message_type);
goto unlock;
}
if (msg->ack == DISPATCHER_ACK) {
if (msg->ack) {
if (read_safe(send_fd, (uint8_t*)&ack, sizeof(ack), 1) == -1) {
spice_printerr("error: failed to read ack");
} else if (ack != ACK) {
@ -342,17 +339,9 @@ unlock:
pthread_mutex_unlock(&dispatcher->priv->lock);
}
void dispatcher_register_async_done_callback(
Dispatcher *dispatcher,
dispatcher_handle_async_done handler)
{
assert(dispatcher->priv->handle_async_done == NULL);
dispatcher->priv->handle_async_done = handler;
}
void dispatcher_register_handler(Dispatcher *dispatcher, uint32_t message_type,
dispatcher_handle_message handler,
size_t size, int ack)
size_t size, bool ack)
{
DispatcherMessage *msg;

View File

@ -59,11 +59,6 @@ typedef void (*dispatcher_handle_any_message)(void *opaque,
uint32_t message_type,
void *payload);
typedef void (*dispatcher_handle_async_done)(void *opaque,
uint32_t message_type,
void *payload);
/*
* dispatcher_send_message
* @message_type: message type
@ -72,38 +67,17 @@ typedef void (*dispatcher_handle_async_done)(void *opaque,
void dispatcher_send_message(Dispatcher *dispatcher, uint32_t message_type,
void *payload);
enum {
DISPATCHER_NONE = 0,
DISPATCHER_ACK,
DISPATCHER_ASYNC
};
/*
* dispatcher_register_handler
* @dispatcher: dispatcher
* @messsage_type: message type
* @handler: message handler
* @size: message size. Each type has a fixed associated size.
* @ack: One of DISPATCHER_NONE, DISPATCHER_ACK, DISPATCHER_ASYNC.
* DISPATCHER_NONE - only send the message
* DISPATCHER_ACK - send an ack after the message
* DISPATCHER_ASYNC - call send an ack. This is per message type - you can't send the
* same message type with and without. Register two different
* messages if that is what you want.
* @ack: whether the dispatcher should send an ACK to the sender
*/
void dispatcher_register_handler(Dispatcher *dispatcher, uint32_t message_type,
dispatcher_handle_message handler, size_t size,
int ack);
/*
* dispatcher_register_async_done_callback
* @dispatcher: dispatcher
* @handler: callback on the receiver side called *after* the
* message callback in case ack == DISPATCHER_ASYNC.
*/
void dispatcher_register_async_done_callback(
Dispatcher *dispatcher,
dispatcher_handle_async_done handler);
bool ack);
/*
* Hack to allow red_record to see the message being sent so it can record

View File

@ -432,6 +432,7 @@ static void handle_dev_update_async(void *opaque, void *payload)
red_qxl_update_area_complete(worker->qxl, msg->surface_id,
qxl_dirty_rects, num_dirty_rects);
free(qxl_dirty_rects);
red_qxl_async_complete(worker->qxl, msg->base.cmd);
}
static void handle_dev_update(void *opaque, void *payload)
@ -582,14 +583,17 @@ static void handle_dev_destroy_primary_surface_async(void *opaque, void *payload
uint32_t surface_id = msg->surface_id;
destroy_primary_surface(worker, surface_id);
red_qxl_async_complete(worker->qxl, msg->base.cmd);
}
static void handle_dev_flush_surfaces_async(void *opaque, void *payload)
{
RedWorker *worker = opaque;
RedWorkerMessageFlushSurfacesAsync *msg = payload;
flush_all_qxl_commands(worker);
display_channel_flush_all_surfaces(worker->display_channel);
red_qxl_async_complete(worker->qxl, msg->base.cmd);
}
static void handle_dev_stop(void *opaque, void *payload)
@ -689,15 +693,18 @@ static void handle_dev_destroy_surface_wait_async(void *opaque, void *payload)
RedWorker *worker = opaque;
display_channel_destroy_surface_wait(worker->display_channel, msg->surface_id);
red_qxl_async_complete(worker->qxl, msg->base.cmd);
}
static void handle_dev_destroy_surfaces_async(void *opaque, void *payload)
{
RedWorker *worker = opaque;
RedWorkerMessageDestroySurfacesAsync *msg = payload;
flush_all_qxl_commands(worker);
display_channel_destroy_surfaces(worker->display_channel);
cursor_channel_reset(worker->cursor_channel);
red_qxl_async_complete(worker->qxl, msg->base.cmd);
}
static void handle_dev_create_primary_surface_async(void *opaque, void *payload)
@ -706,6 +713,7 @@ static void handle_dev_create_primary_surface_async(void *opaque, void *payload)
RedWorker *worker = opaque;
dev_create_primary_surface(worker, msg->surface_id, msg->surface);
red_qxl_async_complete(worker->qxl, msg->base.cmd);
}
static void handle_dev_display_connect(void *opaque, void *payload)
@ -774,21 +782,21 @@ static void handle_dev_monitors_config_async(void *opaque, void *payload)
if (error) {
/* TODO: raise guest bug (requires added QXL interface) */
return;
goto async_complete;
}
worker->driver_cap_monitors_config = 1;
count = dev_monitors_config->count;
max_allowed = dev_monitors_config->max_allowed;
if (count == 0) {
spice_warning("ignoring an empty monitors config message from driver");
return;
goto async_complete;
}
if (count > max_allowed) {
spice_warning("ignoring malformed monitors_config from driver, "
"count > max_allowed %d > %d",
count,
max_allowed);
return;
goto async_complete;
}
/* get pointer again to check virtual size */
dev_monitors_config =
@ -797,11 +805,13 @@ static void handle_dev_monitors_config_async(void *opaque, void *payload)
msg->group_id, &error);
if (error) {
/* TODO: raise guest bug (requires added QXL interface) */
return;
goto async_complete;
}
display_channel_update_monitors_config(worker->display_channel, dev_monitors_config,
MIN(count, msg->max_monitors),
MIN(max_allowed, msg->max_monitors));
async_complete:
red_qxl_async_complete(worker->qxl, msg->base.cmd);
}
/* TODO: special, perhaps use another dispatcher? */
@ -928,6 +938,7 @@ static void handle_dev_add_memslot_async(void *opaque, void *payload)
RedWorker *worker = opaque;
dev_add_memslot(worker, msg->mem_slot);
red_qxl_async_complete(worker->qxl, msg->base.cmd);
}
static void handle_dev_reset_memslots(void *opaque, void *payload)
@ -1000,17 +1011,6 @@ static void handle_dev_loadvm_commands(void *opaque, void *payload)
}
}
static void worker_handle_dispatcher_async_done(void *opaque,
uint32_t message_type,
void *payload)
{
RedWorker *worker = opaque;
RedWorkerMessageAsync *msg_async = payload;
spice_debug("trace");
red_qxl_async_complete(worker->qxl, msg_async->cmd);
}
static void worker_dispatcher_record(void *opaque, uint32_t message_type, void *payload)
{
RedWorker *worker = opaque;
@ -1020,196 +1020,192 @@ static void worker_dispatcher_record(void *opaque, uint32_t message_type, void *
static void register_callbacks(Dispatcher *dispatcher)
{
dispatcher_register_async_done_callback(
dispatcher,
worker_handle_dispatcher_async_done);
/* TODO: register cursor & display specific msg in respective channel files */
dispatcher_register_handler(dispatcher,
RED_WORKER_MESSAGE_DISPLAY_CONNECT,
handle_dev_display_connect,
sizeof(RedWorkerMessageDisplayConnect),
DISPATCHER_NONE);
false);
dispatcher_register_handler(dispatcher,
RED_WORKER_MESSAGE_DISPLAY_DISCONNECT,
handle_dev_display_disconnect,
sizeof(RedWorkerMessageDisplayDisconnect),
DISPATCHER_ACK);
true);
dispatcher_register_handler(dispatcher,
RED_WORKER_MESSAGE_DISPLAY_MIGRATE,
handle_dev_display_migrate,
sizeof(RedWorkerMessageDisplayMigrate),
DISPATCHER_NONE);
false);
dispatcher_register_handler(dispatcher,
RED_WORKER_MESSAGE_CURSOR_CONNECT,
handle_dev_cursor_connect,
sizeof(RedWorkerMessageCursorConnect),
DISPATCHER_NONE);
false);
dispatcher_register_handler(dispatcher,
RED_WORKER_MESSAGE_CURSOR_DISCONNECT,
handle_dev_cursor_disconnect,
sizeof(RedWorkerMessageCursorDisconnect),
DISPATCHER_ACK);
true);
dispatcher_register_handler(dispatcher,
RED_WORKER_MESSAGE_CURSOR_MIGRATE,
handle_dev_cursor_migrate,
sizeof(RedWorkerMessageCursorMigrate),
DISPATCHER_NONE);
false);
dispatcher_register_handler(dispatcher,
RED_WORKER_MESSAGE_UPDATE,
handle_dev_update,
sizeof(RedWorkerMessageUpdate),
DISPATCHER_ACK);
true);
dispatcher_register_handler(dispatcher,
RED_WORKER_MESSAGE_UPDATE_ASYNC,
handle_dev_update_async,
sizeof(RedWorkerMessageUpdateAsync),
DISPATCHER_ASYNC);
false);
dispatcher_register_handler(dispatcher,
RED_WORKER_MESSAGE_ADD_MEMSLOT,
handle_dev_add_memslot,
sizeof(RedWorkerMessageAddMemslot),
DISPATCHER_ACK);
true);
dispatcher_register_handler(dispatcher,
RED_WORKER_MESSAGE_ADD_MEMSLOT_ASYNC,
handle_dev_add_memslot_async,
sizeof(RedWorkerMessageAddMemslotAsync),
DISPATCHER_ASYNC);
false);
dispatcher_register_handler(dispatcher,
RED_WORKER_MESSAGE_DEL_MEMSLOT,
handle_dev_del_memslot,
sizeof(RedWorkerMessageDelMemslot),
DISPATCHER_NONE);
false);
dispatcher_register_handler(dispatcher,
RED_WORKER_MESSAGE_DESTROY_SURFACES,
handle_dev_destroy_surfaces,
sizeof(RedWorkerMessageDestroySurfaces),
DISPATCHER_ACK);
true);
dispatcher_register_handler(dispatcher,
RED_WORKER_MESSAGE_DESTROY_SURFACES_ASYNC,
handle_dev_destroy_surfaces_async,
sizeof(RedWorkerMessageDestroySurfacesAsync),
DISPATCHER_ASYNC);
false);
dispatcher_register_handler(dispatcher,
RED_WORKER_MESSAGE_DESTROY_PRIMARY_SURFACE,
handle_dev_destroy_primary_surface,
sizeof(RedWorkerMessageDestroyPrimarySurface),
DISPATCHER_ACK);
true);
dispatcher_register_handler(dispatcher,
RED_WORKER_MESSAGE_DESTROY_PRIMARY_SURFACE_ASYNC,
handle_dev_destroy_primary_surface_async,
sizeof(RedWorkerMessageDestroyPrimarySurfaceAsync),
DISPATCHER_ASYNC);
false);
dispatcher_register_handler(dispatcher,
RED_WORKER_MESSAGE_CREATE_PRIMARY_SURFACE_ASYNC,
handle_dev_create_primary_surface_async,
sizeof(RedWorkerMessageCreatePrimarySurfaceAsync),
DISPATCHER_ASYNC);
false);
dispatcher_register_handler(dispatcher,
RED_WORKER_MESSAGE_CREATE_PRIMARY_SURFACE,
handle_dev_create_primary_surface,
sizeof(RedWorkerMessageCreatePrimarySurface),
DISPATCHER_ACK);
true);
dispatcher_register_handler(dispatcher,
RED_WORKER_MESSAGE_RESET_IMAGE_CACHE,
handle_dev_reset_image_cache,
sizeof(RedWorkerMessageResetImageCache),
DISPATCHER_ACK);
true);
dispatcher_register_handler(dispatcher,
RED_WORKER_MESSAGE_RESET_CURSOR,
handle_dev_reset_cursor,
sizeof(RedWorkerMessageResetCursor),
DISPATCHER_ACK);
true);
dispatcher_register_handler(dispatcher,
RED_WORKER_MESSAGE_WAKEUP,
handle_dev_wakeup,
sizeof(RedWorkerMessageWakeup),
DISPATCHER_NONE);
false);
dispatcher_register_handler(dispatcher,
RED_WORKER_MESSAGE_OOM,
handle_dev_oom,
sizeof(RedWorkerMessageOom),
DISPATCHER_NONE);
false);
dispatcher_register_handler(dispatcher,
RED_WORKER_MESSAGE_START,
handle_dev_start,
sizeof(RedWorkerMessageStart),
DISPATCHER_NONE);
false);
dispatcher_register_handler(dispatcher,
RED_WORKER_MESSAGE_FLUSH_SURFACES_ASYNC,
handle_dev_flush_surfaces_async,
sizeof(RedWorkerMessageFlushSurfacesAsync),
DISPATCHER_ASYNC);
false);
dispatcher_register_handler(dispatcher,
RED_WORKER_MESSAGE_STOP,
handle_dev_stop,
sizeof(RedWorkerMessageStop),
DISPATCHER_ACK);
true);
dispatcher_register_handler(dispatcher,
RED_WORKER_MESSAGE_LOADVM_COMMANDS,
handle_dev_loadvm_commands,
sizeof(RedWorkerMessageLoadvmCommands),
DISPATCHER_ACK);
true);
dispatcher_register_handler(dispatcher,
RED_WORKER_MESSAGE_SET_COMPRESSION,
handle_dev_set_compression,
sizeof(RedWorkerMessageSetCompression),
DISPATCHER_NONE);
false);
dispatcher_register_handler(dispatcher,
RED_WORKER_MESSAGE_SET_STREAMING_VIDEO,
handle_dev_set_streaming_video,
sizeof(RedWorkerMessageSetStreamingVideo),
DISPATCHER_NONE);
false);
dispatcher_register_handler(dispatcher,
RED_WORKER_MESSAGE_SET_VIDEO_CODECS,
handle_dev_set_video_codecs,
sizeof(RedWorkerMessageSetVideoCodecs),
DISPATCHER_NONE);
false);
dispatcher_register_handler(dispatcher,
RED_WORKER_MESSAGE_SET_MOUSE_MODE,
handle_dev_set_mouse_mode,
sizeof(RedWorkerMessageSetMouseMode),
DISPATCHER_NONE);
false);
dispatcher_register_handler(dispatcher,
RED_WORKER_MESSAGE_DESTROY_SURFACE_WAIT,
handle_dev_destroy_surface_wait,
sizeof(RedWorkerMessageDestroySurfaceWait),
DISPATCHER_ACK);
true);
dispatcher_register_handler(dispatcher,
RED_WORKER_MESSAGE_DESTROY_SURFACE_WAIT_ASYNC,
handle_dev_destroy_surface_wait_async,
sizeof(RedWorkerMessageDestroySurfaceWaitAsync),
DISPATCHER_ASYNC);
false);
dispatcher_register_handler(dispatcher,
RED_WORKER_MESSAGE_RESET_MEMSLOTS,
handle_dev_reset_memslots,
sizeof(RedWorkerMessageResetMemslots),
DISPATCHER_NONE);
false);
dispatcher_register_handler(dispatcher,
RED_WORKER_MESSAGE_MONITORS_CONFIG_ASYNC,
handle_dev_monitors_config_async,
sizeof(RedWorkerMessageMonitorsConfigAsync),
DISPATCHER_ASYNC);
false);
dispatcher_register_handler(dispatcher,
RED_WORKER_MESSAGE_DRIVER_UNLOAD,
handle_dev_driver_unload,
sizeof(RedWorkerMessageDriverUnload),
DISPATCHER_NONE);
false);
dispatcher_register_handler(dispatcher,
RED_WORKER_MESSAGE_GL_SCANOUT,
handle_dev_gl_scanout,
sizeof(RedWorkerMessageGlScanout),
DISPATCHER_NONE);
false);
dispatcher_register_handler(dispatcher,
RED_WORKER_MESSAGE_GL_DRAW_ASYNC,
handle_dev_gl_draw_async,
sizeof(RedWorkerMessageGlDraw),
DISPATCHER_NONE);
false);
dispatcher_register_handler(dispatcher,
RED_WORKER_MESSAGE_CLOSE_WORKER,
handle_dev_close,
sizeof(RedWorkerMessageClose),
DISPATCHER_NONE);
false);
}