summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlon Levy <alevy@redhat.com>2011-10-08 19:35:14 +0200
committerAlon Levy <alevy@redhat.com>2011-10-08 19:35:14 +0200
commite8e2e58423fd2678ef67145d0a918172bba6d412 (patch)
treeb2f837a9531640a6e2bc0421476f6ffaff674bc3
parentc3e80476294f13babc9637dc22e0a58af95c366a (diff)
red_dispatcher: support concurrent asyncsupdate_area_async_dirty
-rw-r--r--server/red_dispatcher.c70
1 files changed, 50 insertions, 20 deletions
diff --git a/server/red_dispatcher.c b/server/red_dispatcher.c
index a9982384..8289c6bb 100644
--- a/server/red_dispatcher.c
+++ b/server/red_dispatcher.c
@@ -40,6 +40,13 @@ static int num_active_workers = 0;
//volatile
+typedef struct AsyncCommand AsyncCommand;
+struct AsyncCommand {
+ AsyncCommand *next;
+ RedWorkerMessage message;
+ uint64_t cookie;
+};
+
struct RedDispatcher {
QXLWorker base;
QXLInstance *qxl;
@@ -51,7 +58,7 @@ struct RedDispatcher {
int y_res;
int use_hardware_cursor;
RedDispatcher *next;
- RedWorkerMessage async_message;
+ AsyncCommand* async_commands;
pthread_mutex_t async_lock;
QXLDevSurfaceCreate surface_create;
};
@@ -224,17 +231,27 @@ static void red_dispatcher_update_area(RedDispatcher *dispatcher, uint32_t surfa
ASSERT(message == RED_WORKER_MESSAGE_READY);
}
+static AsyncCommand *push_async_command(RedDispatcher *dispatcher,
+ RedWorkerMessage message,
+ uint64_t cookie)
+{
+ AsyncCommand *async_command = spice_new(AsyncCommand, 1);
+
+ async_command->cookie = cookie;
+ async_command->message = message;
+ if (dispatcher->async_commands) {
+ async_command->next = dispatcher->async_commands;
+ }
+ dispatcher->async_commands = async_command;
+ return async_command;
+}
+
static RedWorkerMessage red_dispatcher_async_start(RedDispatcher *dispatcher,
- RedWorkerMessage message)
+ RedWorkerMessage message,
+ uint64_t cookie)
{
pthread_mutex_lock(&dispatcher->async_lock);
- if (dispatcher->async_message != RED_WORKER_MESSAGE_NOP) {
- red_warn("warning: async clash. have %d, ignoring %d",
- dispatcher->async_message, message);
- pthread_mutex_unlock(&dispatcher->async_lock);
- return RED_WORKER_MESSAGE_NOP;
- }
- dispatcher->async_message = message;
+ push_async_command(dispatcher, message, cookie);
pthread_mutex_unlock(&dispatcher->async_lock);
return message;
}
@@ -246,7 +263,8 @@ static void red_dispatcher_update_area_async(RedDispatcher *dispatcher,
uint64_t cookie)
{
RedWorkerMessage message = red_dispatcher_async_start(dispatcher,
- RED_WORKER_MESSAGE_UPDATE_ASYNC);
+ RED_WORKER_MESSAGE_UPDATE_ASYNC,
+ cookie);
if (message == RED_WORKER_MESSAGE_NOP) {
return;
@@ -265,7 +283,7 @@ static void red_dispatcher_update_area_dirty_async(RedDispatcher *dispatcher,
uint32_t clear_dirty_region, uint64_t cookie)
{
RedWorkerMessage message = red_dispatcher_async_start(
- dispatcher, RED_WORKER_MESSAGE_UPDATE_DIRTY_ASYNC);
+ dispatcher, RED_WORKER_MESSAGE_UPDATE_DIRTY_ASYNC, cookie);
if (message == RED_WORKER_MESSAGE_NOP) {
return;
@@ -306,7 +324,8 @@ static void qxl_worker_add_memslot(QXLWorker *qxl_worker, QXLDevMemSlot *mem_slo
static void red_dispatcher_add_memslot_async(RedDispatcher *dispatcher, QXLDevMemSlot *mem_slot, uint64_t cookie)
{
RedWorkerMessage message = red_dispatcher_async_start(dispatcher,
- RED_WORKER_MESSAGE_ADD_MEMSLOT_ASYNC);
+ RED_WORKER_MESSAGE_ADD_MEMSLOT_ASYNC,
+ cookie);
if (message == RED_WORKER_MESSAGE_NOP) {
return;
@@ -347,7 +366,8 @@ static void qxl_worker_destroy_surfaces(QXLWorker *qxl_worker)
static void red_dispatcher_destroy_surfaces_async(RedDispatcher *dispatcher, uint64_t cookie)
{
RedWorkerMessage message = red_dispatcher_async_start(dispatcher,
- RED_WORKER_MESSAGE_DESTROY_SURFACES_ASYNC);
+ RED_WORKER_MESSAGE_DESTROY_SURFACES_ASYNC,
+ cookie);
if (message == RED_WORKER_MESSAGE_NOP) {
return;
@@ -374,7 +394,8 @@ red_dispatcher_destroy_primary_surface(RedDispatcher *dispatcher,
if (async) {
message = red_dispatcher_async_start(dispatcher,
- RED_WORKER_MESSAGE_DESTROY_PRIMARY_SURFACE_ASYNC);
+ RED_WORKER_MESSAGE_DESTROY_PRIMARY_SURFACE_ASYNC,
+ cookie);
if (message == RED_WORKER_MESSAGE_NOP) {
return;
}
@@ -420,7 +441,8 @@ red_dispatcher_create_primary_surface(RedDispatcher *dispatcher, uint32_t surfac
if (async) {
message = red_dispatcher_async_start(dispatcher,
- RED_WORKER_MESSAGE_CREATE_PRIMARY_SURFACE_ASYNC);
+ RED_WORKER_MESSAGE_CREATE_PRIMARY_SURFACE_ASYNC,
+ cookie);
if (message == RED_WORKER_MESSAGE_NOP) {
return;
}
@@ -483,7 +505,8 @@ static void red_dispatcher_destroy_surface_wait(RedDispatcher *dispatcher, uint3
if (async ) {
message = red_dispatcher_async_start(dispatcher,
- RED_WORKER_MESSAGE_DESTROY_SURFACE_WAIT_ASYNC);
+ RED_WORKER_MESSAGE_DESTROY_SURFACE_WAIT_ASYNC,
+ cookie);
if (message == RED_WORKER_MESSAGE_NOP) {
return;
}
@@ -563,7 +586,8 @@ static void qxl_worker_start(QXLWorker *qxl_worker)
static void red_dispatcher_flush_surfaces_async(RedDispatcher *dispatcher, uint64_t cookie)
{
RedWorkerMessage message = red_dispatcher_async_start(dispatcher,
- RED_WORKER_MESSAGE_FLUSH_SURFACES_ASYNC);
+ RED_WORKER_MESSAGE_FLUSH_SURFACES_ASYNC,
+ cookie);
if (message == RED_WORKER_MESSAGE_NOP) {
return;
@@ -836,8 +860,15 @@ void spice_qxl_flush_surfaces_async(QXLInstance *instance, uint64_t cookie)
void red_dispatcher_async_complete(struct RedDispatcher *dispatcher, uint64_t cookie)
{
+ AsyncCommand *async_command;
pthread_mutex_lock(&dispatcher->async_lock);
- switch (dispatcher->async_message) {
+ for (async_command = dispatcher->async_commands;
+ async_command && async_command->cookie != cookie && async_command->next;
+ async_command = async_command->next) {};
+ if (!async_command || async_command->cookie != cookie) {
+ red_warn("unknown cookie");
+ }
+ switch (async_command->message) {
case RED_WORKER_MESSAGE_UPDATE_ASYNC:
case RED_WORKER_MESSAGE_UPDATE_DIRTY_ASYNC:
break;
@@ -858,7 +889,7 @@ void red_dispatcher_async_complete(struct RedDispatcher *dispatcher, uint64_t co
default:
red_warn("unexpected message");
}
- dispatcher->async_message = RED_WORKER_MESSAGE_NOP;
+ free(async_command);
pthread_mutex_unlock(&dispatcher->async_lock);
dispatcher->qxl->st->qif->async_complete(dispatcher->qxl, cookie);
}
@@ -895,7 +926,6 @@ RedDispatcher *red_dispatcher_init(QXLInstance *qxl)
init_data.num_renderers = num_renderers;
memcpy(init_data.renderers, renderers, sizeof(init_data.renderers));
- dispatcher->async_message = RED_WORKER_MESSAGE_NOP;
pthread_mutex_init(&dispatcher->async_lock, NULL);
init_data.image_compression = image_compression;
init_data.jpeg_state = jpeg_state;