[Spice-devel] [PATCH 3/9] worker: use glib main loop
Frediano Ziglio
fziglio at redhat.com
Wed Dec 9 04:17:38 PST 2015
From: Marc-André Lureau <marcandre.lureau at gmail.com>
Clean up, more extensible.
---
server/Makefile.am | 2 -
server/red-worker.c | 357 ++++++++++++++++++++++++++++-----------------
server/red-worker.h | 1 +
server/spice_timer_queue.c | 273 ----------------------------------
server/spice_timer_queue.h | 43 ------
5 files changed, 224 insertions(+), 452 deletions(-)
delete mode 100644 server/spice_timer_queue.c
delete mode 100644 server/spice_timer_queue.h
diff --git a/server/Makefile.am b/server/Makefile.am
index d4fc972..88825d8 100644
--- a/server/Makefile.am
+++ b/server/Makefile.am
@@ -121,8 +121,6 @@ libspice_server_la_SOURCES = \
spice.h \
stat.h \
spicevmc.c \
- spice_timer_queue.c \
- spice_timer_queue.h \
zlib-encoder.c \
zlib-encoder.h \
image-cache.h \
diff --git a/server/red-worker.c b/server/red-worker.c
index baa8458..9f2aba1 100644
--- a/server/red-worker.c
+++ b/server/red-worker.c
@@ -49,30 +49,22 @@
#include "spice.h"
#include "red-worker.h"
-#include "spice_timer_queue.h"
#include "cursor-channel.h"
#include "tree.h"
#define CMD_RING_POLL_TIMEOUT 10 //milli
#define CMD_RING_POLL_RETRIES 200
-#define MAX_EVENT_SOURCES 20
#define INF_EVENT_WAIT ~0
-struct SpiceWatch {
- struct RedWorker *worker;
- SpiceWatchFunc watch_func;
- void *watch_func_opaque;
-};
-
struct RedWorker {
pthread_t thread;
clockid_t clockid;
QXLInstance *qxl;
RedDispatcher *red_dispatcher;
int running;
- struct pollfd poll_fds[MAX_EVENT_SOURCES];
- struct SpiceWatch watches[MAX_EVENT_SOURCES];
+
+ GMainContext *main_context;
unsigned int event_timeout;
DisplayChannel *display_channel;
@@ -99,6 +91,13 @@ struct RedWorker {
FILE *record_fd;
};
+GMainContext* red_worker_get_context(RedWorker *worker)
+{
+ spice_return_val_if_fail(worker, NULL);
+
+ return worker->main_context;
+}
+
QXLInstance* red_worker_get_qxl(RedWorker *worker)
{
spice_return_val_if_fail(worker != NULL, NULL);
@@ -510,81 +509,159 @@ static int common_channel_config_socket(RedChannelClient *rcc)
return TRUE;
}
-static void worker_watch_update_mask(SpiceWatch *watch, int event_mask)
+typedef struct SpiceTimer {
+ SpiceTimerFunc func;
+ void *opaque;
+ guint source_id;
+} SpiceTimer;
+
+static SpiceTimer* worker_timer_add(SpiceTimerFunc func, void *opaque)
{
- struct RedWorker *worker;
- int i;
+ SpiceTimer *timer = g_new0(SpiceTimer, 1);
+
+ timer->func = func;
+ timer->opaque = opaque;
+
+ return timer;
+}
+
+static gboolean worker_timer_func(gpointer user_data)
+{
+ SpiceTimer *timer = user_data;
+
+ timer->source_id = 0;
+ timer->func(timer->opaque);
+ /* timer might be free after func(), don't touch */
+
+ return FALSE;
+}
- if (!watch) {
+static void worker_timer_cancel(SpiceTimer *timer)
+{
+ if (timer->source_id == 0)
return;
- }
- worker = watch->worker;
- i = watch - worker->watches;
+ g_source_remove(timer->source_id);
+ timer->source_id = 0;
+}
- worker->poll_fds[i].events = 0;
- if (event_mask & SPICE_WATCH_EVENT_READ) {
- worker->poll_fds[i].events |= POLLIN;
- }
- if (event_mask & SPICE_WATCH_EVENT_WRITE) {
- worker->poll_fds[i].events |= POLLOUT;
+static void worker_timer_start(SpiceTimer *timer, uint32_t ms)
+{
+ worker_timer_cancel(timer);
+
+ timer->source_id = g_timeout_add(ms, worker_timer_func, timer);
+}
+
+static void worker_timer_remove(SpiceTimer *timer)
+{
+ worker_timer_cancel(timer);
+ g_free(timer);
+}
+
+static GIOCondition spice_event_to_giocondition(int event_mask)
+{
+ GIOCondition condition = 0;
+
+ if (event_mask & SPICE_WATCH_EVENT_READ)
+ condition |= G_IO_IN;
+ if (event_mask & SPICE_WATCH_EVENT_WRITE)
+ condition |= G_IO_OUT;
+
+ return condition;
+}
+
+static int giocondition_to_spice_event(GIOCondition condition)
+{
+ int event = 0;
+
+ if (condition & G_IO_IN)
+ event |= SPICE_WATCH_EVENT_READ;
+ if (condition & G_IO_OUT)
+ event |= SPICE_WATCH_EVENT_WRITE;
+
+ return event;
+}
+
+struct SpiceWatch {
+ GIOChannel *channel;
+ GSource *source;
+ RedChannelClient *rcc;
+ SpiceWatchFunc func;
+};
+
+static gboolean watch_func(GIOChannel *source, GIOCondition condition,
+ gpointer data)
+{
+ SpiceWatch *watch = data;
+ int fd = g_io_channel_unix_get_fd(source);
+
+ watch->func(fd, giocondition_to_spice_event(condition), watch->rcc);
+
+ return TRUE;
+}
+
+static void worker_watch_update_mask(SpiceWatch *watch, int events)
+{
+ RedWorker *worker;
+
+ spice_return_if_fail(watch != NULL);
+ worker = SPICE_CONTAINEROF(watch->rcc->channel, CommonChannel, base)->worker;
+
+ if (watch->source) {
+ g_source_destroy(watch->source);
+ watch->source = NULL;
}
+
+ if (!events)
+ return;
+
+ watch->source = g_io_create_watch(watch->channel, spice_event_to_giocondition(events));
+ g_source_set_callback(watch->source, (GSourceFunc)watch_func, watch, NULL);
+ g_source_attach(watch->source, worker->main_context);
}
-static SpiceWatch *worker_watch_add(int fd, int event_mask, SpiceWatchFunc func, void *opaque)
+static SpiceWatch* worker_watch_add(int fd, int events, SpiceWatchFunc func, void *opaque)
{
- /* Since we are a channel core implementation, we always get called from
- red_channel_client_create(), so opaque always is our rcc */
RedChannelClient *rcc = opaque;
- struct RedWorker *worker;
- int i;
+ RedWorker *worker;
+ SpiceWatch *watch;
+
+ spice_return_val_if_fail(rcc != NULL, NULL);
+ spice_return_val_if_fail(fd != -1, NULL);
+ spice_return_val_if_fail(func != NULL, NULL);
/* Since we are called from red_channel_client_create()
CommonChannelClient->worker has not been set yet! */
worker = SPICE_CONTAINEROF(rcc->channel, CommonChannel, base)->worker;
+ spice_return_val_if_fail(worker != NULL, NULL);
+ spice_return_val_if_fail(worker->main_context != NULL, NULL);
- /* Search for a free slot in our poll_fds & watches arrays */
- for (i = 0; i < MAX_EVENT_SOURCES; i++) {
- if (worker->poll_fds[i].fd == -1) {
- break;
- }
- }
- if (i == MAX_EVENT_SOURCES) {
- spice_warning("could not add a watch for channel type %u id %u",
- rcc->channel->type, rcc->channel->id);
- return NULL;
- }
+ watch = g_new0(SpiceWatch, 1);
+ watch->channel = g_io_channel_unix_new(fd);
+ watch->rcc = rcc;
+ watch->func = func;
- worker->poll_fds[i].fd = fd;
- worker->watches[i].worker = worker;
- worker->watches[i].watch_func = func;
- worker->watches[i].watch_func_opaque = opaque;
- worker_watch_update_mask(&worker->watches[i], event_mask);
+ worker_watch_update_mask(watch, events);
- return &worker->watches[i];
+ return watch;
}
static void worker_watch_remove(SpiceWatch *watch)
{
- if (!watch) {
- return;
- }
+ spice_return_if_fail(watch != NULL);
- /* Note we don't touch the poll_fd here, to avoid the
- poll_fds/watches table entry getting re-used in the same
- red_worker_main loop over the fds as it is removed.
+ if (watch->source)
+ g_source_destroy(watch->source);
- This is done because re-using it while events were pending on
- the fd previously occupying the slot would lead to incorrectly
- calling the watch_func for the new fd. */
- memset(watch, 0, sizeof(SpiceWatch));
+ g_io_channel_unref(watch->channel);
+ g_free(watch);
}
-SpiceCoreInterface worker_core = {
- .timer_add = spice_timer_queue_add,
- .timer_start = spice_timer_set,
- .timer_cancel = spice_timer_cancel,
- .timer_remove = spice_timer_remove,
+static const SpiceCoreInterface worker_core = {
+ .timer_add = worker_timer_add,
+ .timer_start = worker_timer_start,
+ .timer_cancel = worker_timer_cancel,
+ .timer_remove = worker_timer_remove,
.watch_update_mask = worker_watch_update_mask,
.watch_add = worker_watch_add,
@@ -1527,24 +1604,91 @@ static void register_callbacks(Dispatcher *dispatcher)
-static void handle_dev_input(int fd, int event, void *opaque)
+static gboolean worker_dispatcher_cb(GIOChannel *source, GIOCondition condition,
+ gpointer data)
{
- RedWorker *worker = opaque;
+ RedWorker *worker = data;
+ spice_debug(NULL);
dispatcher_handle_recv_read(red_dispatcher_get_dispatcher(worker->red_dispatcher));
+
+ return TRUE;
+}
+
+typedef struct RedWorkerSource {
+ GSource source;
+ RedWorker *worker;
+} RedWorkerSource;
+
+static gboolean worker_source_prepare(GSource *source, gint *p_timeout)
+{
+ RedWorkerSource *wsource = (RedWorkerSource *)source;
+ RedWorker *worker = wsource->worker;
+ unsigned int timeout;
+
+ timeout = MIN(worker->event_timeout,
+ display_channel_get_streams_timeout(worker->display_channel));
+
+ *p_timeout = (timeout == INF_EVENT_WAIT) ? -1 : timeout;
+ if (*p_timeout == 0)
+ return TRUE;
+
+ return FALSE; /* do no timeout poll */
+}
+
+static gboolean worker_source_check(GSource *source)
+{
+ RedWorkerSource *wsource = (RedWorkerSource *)source;
+ RedWorker *worker = wsource->worker;
+
+ return worker->running /* TODO && worker->pending_process */;
+}
+
+static gboolean worker_source_dispatch(GSource *source, GSourceFunc callback,
+ gpointer user_data)
+{
+ RedWorkerSource *wsource = (RedWorkerSource *)source;
+ RedWorker *worker = wsource->worker;
+ DisplayChannel *display = worker->display_channel;
+ int ring_is_empty;
+
+ /* during migration, in the dest, the display channel can be initialized
+ while the global lz data not since migrate data msg hasn't been
+ received yet */
+ /* FIXME: why is this here, and not in display_channel_create */
+ display_channel_free_glz_drawables_to_free(display);
+
+ /* FIXME: could use its own source */
+ stream_timeout(display);
+
+ worker->event_timeout = INF_EVENT_WAIT;
+ red_process_cursor(worker, MAX_PIPE_SIZE, &ring_is_empty);
+ red_process_display(worker, MAX_PIPE_SIZE, &ring_is_empty);
+
+ /* FIXME: remove me? that should be handled by watch out condition */
+ red_push(worker);
+
+ return TRUE;
}
+/* cannot be const */
+static GSourceFuncs worker_source_funcs = {
+ .prepare = worker_source_prepare,
+ .check = worker_source_check,
+ .dispatch = worker_source_dispatch,
+};
+
RedWorker* red_worker_new(QXLInstance *qxl, RedDispatcher *red_dispatcher)
{
QXLDevInitInfo init_info;
RedWorker *worker;
Dispatcher *dispatcher;
- int i;
const char *record_filename;
qxl->st->qif->get_init_info(qxl, &init_info);
worker = spice_new0(RedWorker, 1);
+ worker->main_context = g_main_context_new();
record_filename = getenv("SPICE_WORKER_RECORD_FILENAME");
if (record_filename) {
@@ -1578,15 +1722,18 @@ RedWorker* red_worker_new(QXLInstance *qxl, RedDispatcher *red_dispatcher)
worker->wakeup_counter = stat_add_counter(worker->stat, "wakeups", TRUE);
worker->command_counter = stat_add_counter(worker->stat, "commands", TRUE);
#endif
- for (i = 0; i < MAX_EVENT_SOURCES; i++) {
- worker->poll_fds[i].fd = -1;
- }
- worker->poll_fds[0].fd = dispatcher_get_recv_fd(dispatcher);
- worker->poll_fds[0].events = POLLIN;
- worker->watches[0].worker = worker;
- worker->watches[0].watch_func = handle_dev_input;
- worker->watches[0].watch_func_opaque = worker;
+ GIOChannel *channel = g_io_channel_unix_new(dispatcher_get_recv_fd(dispatcher));
+ GSource *source = g_io_create_watch(channel, G_IO_IN);
+ g_source_set_callback(source, (GSourceFunc)worker_dispatcher_cb, worker, NULL);
+ g_source_attach(source, worker->main_context);
+ g_source_unref(source);
+
+ source = g_source_new(&worker_source_funcs, sizeof(RedWorkerSource));
+ RedWorkerSource *wsource = (RedWorkerSource *)source;
+ wsource->worker = worker;
+ g_source_attach(source, worker->main_context);
+ g_source_unref(source);
memslot_info_init(&worker->mem_slots,
init_info.num_memslots_groups,
@@ -1615,10 +1762,6 @@ SPICE_GNUC_NORETURN static void *red_worker_main(void *arg)
spice_assert(MAX_PIPE_SIZE > WIDE_CLIENT_ACK_WINDOW &&
MAX_PIPE_SIZE > NARROW_CLIENT_ACK_WINDOW); //ensure wakeup by ack message
- if (!spice_timer_queue_create()) {
- spice_error("failed to create timer queue");
- }
-
if (pthread_getcpuclockid(pthread_self(), &worker->clockid)) {
spice_warning("getcpuclockid failed");
}
@@ -1626,66 +1769,12 @@ SPICE_GNUC_NORETURN static void *red_worker_main(void *arg)
RED_CHANNEL(worker->cursor_channel)->thread_id = pthread_self();
RED_CHANNEL(worker->display_channel)->thread_id = pthread_self();
- for (;;) {
- int i, num_events;
- unsigned int timeout;
-
- timeout = spice_timer_queue_get_timeout_ms();
- worker->event_timeout = MIN(timeout, worker->event_timeout);
- timeout = display_channel_get_streams_timeout(worker->display_channel);
- worker->event_timeout = MIN(timeout, worker->event_timeout);
- num_events = poll(worker->poll_fds, MAX_EVENT_SOURCES, worker->event_timeout);
- stream_timeout(worker->display_channel);
- spice_timer_queue_cb();
-
- if (worker->display_channel) {
- /* during migration, in the dest, the display channel can be initialized
- while the global lz data not since migrate data msg hasn't been
- received yet */
- display_channel_free_glz_drawables_to_free(worker->display_channel);
- }
-
- worker->event_timeout = INF_EVENT_WAIT;
- if (num_events == -1) {
- if (errno != EINTR) {
- spice_error("poll failed, %s", strerror(errno));
- }
- }
-
- for (i = 0; i < MAX_EVENT_SOURCES; i++) {
- /* The watch may have been removed by the watch-func from
- another fd (ie a disconnect through the dispatcher),
- in this case watch_func is NULL. */
- if (worker->poll_fds[i].revents && worker->watches[i].watch_func) {
- int events = 0;
- if (worker->poll_fds[i].revents & POLLIN) {
- events |= SPICE_WATCH_EVENT_READ;
- }
- if (worker->poll_fds[i].revents & POLLOUT) {
- events |= SPICE_WATCH_EVENT_WRITE;
- }
- worker->watches[i].watch_func(worker->poll_fds[i].fd, events,
- worker->watches[i].watch_func_opaque);
- }
- }
-
- /* Clear the poll_fd for any removed watches, see the comment in
- watch_remove for why we don't do this there. */
- for (i = 0; i < MAX_EVENT_SOURCES; i++) {
- if (!worker->watches[i].watch_func) {
- worker->poll_fds[i].fd = -1;
- }
- }
-
- if (worker->running) {
- int ring_is_empty;
- red_process_cursor(worker, MAX_PIPE_SIZE, &ring_is_empty);
- red_process_display(worker, MAX_PIPE_SIZE, &ring_is_empty);
- }
- red_push(worker);
- }
+ GMainLoop *loop = g_main_loop_new(worker->main_context, FALSE);
+ g_main_loop_run(loop);
+ g_main_loop_unref(loop);
- spice_warn_if_reached();
+ /* FIXME: free worker, and join threads */
+ abort();
}
bool red_worker_run(RedWorker *worker)
diff --git a/server/red-worker.h b/server/red-worker.h
index 44f35f7..b55a45c 100644
--- a/server/red-worker.h
+++ b/server/red-worker.h
@@ -97,6 +97,7 @@ bool red_worker_run(RedWorker *worker);
QXLInstance* red_worker_get_qxl(RedWorker *worker);
RedChannel* red_worker_get_cursor_channel(RedWorker *worker);
RedChannel* red_worker_get_display_channel(RedWorker *worker);
+GMainContext* red_worker_get_context(RedWorker *worker);
clockid_t red_worker_get_clockid(RedWorker *worker);
RedMemSlotInfo* red_worker_get_memslot(RedWorker *worker);
diff --git a/server/spice_timer_queue.c b/server/spice_timer_queue.c
deleted file mode 100644
index 60017cc..0000000
--- a/server/spice_timer_queue.c
+++ /dev/null
@@ -1,273 +0,0 @@
-/* -*- Mode: C; c-basic-offset: 4; indent-tabs-mode: nil -*- */
-/*
- Copyright (C) 2013 Red Hat, Inc.
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Lesser General Public
- License as published by the Free Software Foundation; either
- version 2.1 of the License, or (at your option) any later version.
-
- This library is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public
- License along with this library; if not, see <http://www.gnu.org/licenses/>.
-*/
-#include <config.h>
-#include <pthread.h>
-#include "red-common.h"
-#include "spice_timer_queue.h"
-#include "common/ring.h"
-
-static Ring timer_queue_list;
-static int queue_count = 0;
-static pthread_mutex_t queue_list_lock = PTHREAD_MUTEX_INITIALIZER;
-
-static void spice_timer_queue_init(void)
-{
- ring_init(&timer_queue_list);
-}
-
-struct SpiceTimer {
- RingItem link;
- RingItem active_link;
-
- SpiceTimerFunc func;
- void *opaque;
-
- SpiceTimerQueue *queue;
-
- int is_active;
- uint32_t ms;
- uint64_t expiry_time;
-};
-
-struct SpiceTimerQueue {
- RingItem link;
- pthread_t thread;
- Ring timers;
- Ring active_timers;
-};
-
-static SpiceTimerQueue *spice_timer_queue_find(void)
-{
- pthread_t self = pthread_self();
- RingItem *queue_item;
-
- RING_FOREACH(queue_item, &timer_queue_list) {
- SpiceTimerQueue *queue = SPICE_CONTAINEROF(queue_item, SpiceTimerQueue, link);
-
- if (pthread_equal(self, queue->thread) != 0) {
- return queue;
- }
- }
-
- return NULL;
-}
-
-static SpiceTimerQueue *spice_timer_queue_find_with_lock(void)
-{
- SpiceTimerQueue *queue;
-
- pthread_mutex_lock(&queue_list_lock);
- queue = spice_timer_queue_find();
- pthread_mutex_unlock(&queue_list_lock);
- return queue;
-}
-
-int spice_timer_queue_create(void)
-{
- SpiceTimerQueue *queue;
-
- pthread_mutex_lock(&queue_list_lock);
- if (queue_count == 0) {
- spice_timer_queue_init();
- }
-
- if (spice_timer_queue_find() != NULL) {
- spice_printerr("timer queue was already created for the thread");
- return FALSE;
- }
-
- queue = spice_new0(SpiceTimerQueue, 1);
- queue->thread = pthread_self();
- ring_init(&queue->timers);
- ring_init(&queue->active_timers);
-
- ring_add(&timer_queue_list, &queue->link);
- queue_count++;
-
- pthread_mutex_unlock(&queue_list_lock);
-
- return TRUE;
-}
-
-void spice_timer_queue_destroy(void)
-{
- RingItem *item;
- SpiceTimerQueue *queue;
-
- pthread_mutex_lock(&queue_list_lock);
- queue = spice_timer_queue_find();
-
- spice_assert(queue != NULL);
-
- while ((item = ring_get_head(&queue->timers))) {
- SpiceTimer *timer;
-
- timer = SPICE_CONTAINEROF(item, SpiceTimer, link);
- spice_timer_remove(timer);
- }
-
- ring_remove(&queue->link);
- free(queue);
- queue_count--;
-
- pthread_mutex_unlock(&queue_list_lock);
-}
-
-SpiceTimer *spice_timer_queue_add(SpiceTimerFunc func, void *opaque)
-{
- SpiceTimer *timer = spice_new0(SpiceTimer, 1);
- SpiceTimerQueue *queue = spice_timer_queue_find_with_lock();
-
- spice_assert(queue != NULL);
-
- ring_item_init(&timer->link);
- ring_item_init(&timer->active_link);
-
- timer->opaque = opaque;
- timer->func = func;
- timer->queue = queue;
-
- ring_add(&queue->timers, &timer->link);
-
- return timer;
-}
-
-static void _spice_timer_set(SpiceTimer *timer, uint32_t ms, uint64_t now)
-{
- RingItem *next_item;
- SpiceTimerQueue *queue;
-
- if (timer->is_active) {
- spice_timer_cancel(timer);
- }
-
- queue = timer->queue;
- timer->expiry_time = now + ms;
- timer->ms = ms;
-
- RING_FOREACH(next_item, &queue->active_timers) {
- SpiceTimer *next_timer = SPICE_CONTAINEROF(next_item, SpiceTimer, active_link);
-
- if (timer->expiry_time <= next_timer->expiry_time) {
- break;
- }
- }
-
- if (next_item) {
- ring_add_before(&timer->active_link, next_item);
- } else {
- ring_add_before(&timer->active_link, &queue->active_timers);
- }
- timer->is_active = TRUE;
-}
-
-void spice_timer_set(SpiceTimer *timer, uint32_t ms)
-{
- struct timespec now;
-
- spice_assert(pthread_equal(timer->queue->thread, pthread_self()) != 0);
-
- clock_gettime(CLOCK_MONOTONIC, &now);
- _spice_timer_set(timer, ms,
- (uint64_t)now.tv_sec * 1000 + (now.tv_nsec / 1000 / 1000));
-}
-
-void spice_timer_cancel(SpiceTimer *timer)
-{
- spice_assert(pthread_equal(timer->queue->thread, pthread_self()) != 0);
-
- if (!ring_item_is_linked(&timer->active_link)) {
- spice_assert(!timer->is_active);
- return;
- }
-
- spice_assert(timer->is_active);
- ring_remove(&timer->active_link);
- timer->is_active = FALSE;
-}
-
-void spice_timer_remove(SpiceTimer *timer)
-{
- spice_assert(timer->queue);
- spice_assert(ring_item_is_linked(&timer->link));
- spice_assert(pthread_equal(timer->queue->thread, pthread_self()) != 0);
-
- if (timer->is_active) {
- spice_assert(ring_item_is_linked(&timer->active_link));
- ring_remove(&timer->active_link);
- }
- ring_remove(&timer->link);
- free(timer);
-}
-
-unsigned int spice_timer_queue_get_timeout_ms(void)
-{
- struct timespec now;
- int64_t now_ms;
- RingItem *head;
- SpiceTimer *head_timer;
- SpiceTimerQueue *queue = spice_timer_queue_find_with_lock();
-
- spice_assert(queue != NULL);
-
- if (ring_is_empty(&queue->active_timers)) {
- return -1;
- }
-
- head = ring_get_head(&queue->active_timers);
- head_timer = SPICE_CONTAINEROF(head, SpiceTimer, active_link);
-
- clock_gettime(CLOCK_MONOTONIC, &now);
- now_ms = ((int64_t)now.tv_sec * 1000) + (now.tv_nsec / 1000 / 1000);
-
- return MAX(0, ((int64_t)head_timer->expiry_time - now_ms));
-}
-
-
-void spice_timer_queue_cb(void)
-{
- struct timespec now;
- uint64_t now_ms;
- RingItem *head;
- SpiceTimerQueue *queue = spice_timer_queue_find_with_lock();
-
- spice_assert(queue != NULL);
-
- if (ring_is_empty(&queue->active_timers)) {
- return;
- }
-
- clock_gettime(CLOCK_MONOTONIC, &now);
- now_ms = ((uint64_t)now.tv_sec * 1000) + (now.tv_nsec / 1000 / 1000);
-
- while ((head = ring_get_head(&queue->active_timers))) {
- SpiceTimer *timer = SPICE_CONTAINEROF(head, SpiceTimer, active_link);
-
- if (timer->expiry_time > now_ms) {
- break;
- } else {
- /* Remove active timer before calling the timer function.
- * Timer function could delete the timer making the timer
- * pointer point to freed data.
- */
- spice_timer_cancel(timer);
- timer->func(timer->opaque);
- /* timer could now be invalid ! */
- }
- }
-}
diff --git a/server/spice_timer_queue.h b/server/spice_timer_queue.h
deleted file mode 100644
index a84f6cd..0000000
--- a/server/spice_timer_queue.h
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
- Copyright (C) 2013 Red Hat, Inc.
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Lesser General Public
- License as published by the Free Software Foundation; either
- version 2.1 of the License, or (at your option) any later version.
-
- This library is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public
- License along with this library; if not, see <http://www.gnu.org/licenses/>.
-*/
-
-#ifndef _H_SPICE_TIMER_QUEUE
-#define _H_SPICE_TIMER_QUEUE
-
-#include <stdint.h>
-#include "spice.h"
-
-typedef struct SpiceTimerQueue SpiceTimerQueue;
-
-/* create/destroy a timer queue for the current thread.
- * In order to execute the timers functions, spice_timer_queue_cb should be called
- * periodically, according to spice_timer_queue_get_timeout_ms */
-int spice_timer_queue_create(void);
-void spice_timer_queue_destroy(void);
-
-SpiceTimer *spice_timer_queue_add(SpiceTimerFunc func, void *opaque);
-void spice_timer_set(SpiceTimer *timer, uint32_t ms);
-void spice_timer_cancel(SpiceTimer *timer);
-void spice_timer_remove(SpiceTimer *timer);
-
-/* returns the time left till the earliest timer in the queue expires.
- * returns (unsigned)-1 if there are no active timers */
-unsigned int spice_timer_queue_get_timeout_ms(void);
-/* call the timeout callbacks of all the expired timers */
-void spice_timer_queue_cb(void);
-
-#endif
--
2.4.3
More information about the Spice-devel
mailing list