X-Git-Url: https://git.gag.com/?a=blobdiff_plain;f=common-src%2Fevent.c;h=436c85bd249e2ba4af58d538b584aeabb3aa2688;hb=d28952249e392eb31bc8eecc53f6c477f30c617b;hp=218d63872fbd0386d9fdf23e65af9f35aa40a3bc;hpb=949b8910a5e23c4285d0b1aedacfc82a14dc97a5;p=debian%2Famanda diff --git a/common-src/event.c b/common-src/event.c index 218d638..436c85b 100644 --- a/common-src/event.c +++ b/common-src/event.c @@ -1,6 +1,7 @@ /* * Amanda, The Advanced Maryland Automatic Network Disk Archiver * Copyright (c) 1999 University of Maryland at College Park + * Copyright (c) 2007-2012 Zmanda, Inc. All Rights Reserved. * All Rights Reserved. * * Permission to use, copy, modify, distribute, and sell this software and its @@ -73,7 +74,16 @@ struct event_handle { /* A list of all extant event_handle objects, used for searching for particular * events and for deleting dead events */ -GSList *all_events; +GSList *all_events = NULL; + +#if (GLIB_MAJOR_VERSION > 2 || (GLIB_MAJOR_VERSION == 2 && GLIB_MINOR_VERSION >= 31)) +# pragma GCC diagnostic push +# pragma GCC diagnostic ignored "-Wmissing-field-initializers" +#endif +GStaticMutex event_mutex = G_STATIC_MUTEX_INIT; +#if (GLIB_MAJOR_VERSION > 2 || (GLIB_MAJOR_VERSION == 2 && GLIB_MINOR_VERSION >= 31)) +# pragma GCC diagnostic pop +#endif /* * Utility functions @@ -118,7 +128,22 @@ event_register( void *arg) { event_handle_t *handle; - GIOCondition cond; + + handle = event_create(data, type, fn, arg); + event_activate(handle); + return handle; +} + +event_handle_t * +event_create( + event_id_t data, + event_type_t type, + event_fn_t fn, + void *arg) +{ + event_handle_t *handle; + + g_static_mutex_lock(&event_mutex); /* sanity-checking */ if ((type == EV_READFD) || (type == EV_WRITEFD)) { @@ -143,21 +168,34 @@ event_register( event_debug(1, _("event: register: %p->data=%jd, type=%s\n"), handle, handle->data, event_type2str(handle->type)); + g_static_mutex_unlock(&event_mutex); + return handle; +} + +void +event_activate( + event_handle_t *handle) +{ + GIOCondition cond; + assert(handle != NULL); + + g_static_mutex_lock(&event_mutex); + /* add to the list of events */ all_events = g_slist_prepend(all_events, (gpointer)handle); /* and set up the GSource for this event */ - switch (type) { + switch (handle->type) { case EV_READFD: case EV_WRITEFD: /* create a new source */ - if (type == EV_READFD) { + if (handle->type == EV_READFD) { cond = G_IO_IN | G_IO_HUP | G_IO_ERR; } else { cond = G_IO_OUT | G_IO_ERR; } - handle->source = new_fdsource(data, cond); + handle->source = new_fdsource(handle->data, cond); /* attach it to the default GMainLoop */ g_source_attach(handle->source, NULL); @@ -175,7 +213,7 @@ event_register( case EV_TIME: /* Glib provides a nice shortcut for timeouts. The *1000 converts * seconds to milliseconds. */ - handle->source_id = g_timeout_add(data * 1000, event_handle_callback, + handle->source_id = g_timeout_add(handle->data * 1000, event_handle_callback, (gpointer)handle); /* But it doesn't give us the source directly.. */ @@ -189,12 +227,14 @@ event_register( break; default: - error(_("Unknown event type %s"), event_type2str(type)); + error(_("Unknown event type %s"), event_type2str(handle->type)); } - return handle; + g_static_mutex_unlock(&event_mutex); + return; } + /* * Mark an event to be released. Because we may be traversing the queue * when this is called, we must wait until later to actually remove @@ -206,6 +246,7 @@ event_release( { assert(handle != NULL); + g_static_mutex_lock(&event_mutex); event_debug(1, _("event: release (mark): %p data=%jd, type=%s\n"), handle, handle->data, event_type2str(handle->type)); @@ -213,6 +254,7 @@ event_release( /* Mark it as dead and leave it for the event_loop to remove */ handle->is_dead = TRUE; + g_static_mutex_unlock(&event_mutex); } /* @@ -226,6 +268,7 @@ event_wakeup( GSList *tofire = NULL; int nwaken = 0; + g_static_mutex_lock(&event_mutex); event_debug(1, _("event: wakeup: enter (%jd)\n"), id); /* search for any and all matching events, and record them. This way @@ -243,7 +286,10 @@ event_wakeup( event_handle_t *eh = (event_handle_t *)iter->data; if (eh->type == EV_WAIT && eh->data == id && !eh->is_dead) { event_debug(1, _("A: event: wakeup triggering: %p id=%jd\n"), eh, id); + /* The lcok must be release before running the event */ + g_static_mutex_unlock(&event_mutex); fire(eh); + g_static_mutex_lock(&event_mutex); nwaken++; } } @@ -251,6 +297,7 @@ event_wakeup( /* and free the temporary list */ g_slist_free(tofire); + g_static_mutex_unlock(&event_mutex); return (nwaken); } @@ -308,15 +355,16 @@ static gboolean any_mainloop_events(void) { GSList *iter; + gboolean ret = FALSE; for (iter = all_events; iter != NULL; iter = g_slist_next(iter)) { event_handle_t *hdl = (event_handle_t *)iter->data; event_debug(2, _("list %p: %s/%jd\n"), hdl, event_type2str((hdl)->type), (hdl)->data); if (hdl->type != EV_WAIT) - return TRUE; + ret = TRUE; } - return FALSE; + return ret; } static void @@ -324,6 +372,7 @@ event_loop_wait( event_handle_t *wait_eh, int nonblock) { + g_static_mutex_lock(&event_mutex); event_debug(1, _("event: loop: enter: nonblockg=%d, eh=%p\n"), nonblock, wait_eh); /* If we're waiting for a specific event, then reset its has_fired flag */ @@ -342,8 +391,11 @@ event_loop_wait( if (!any_mainloop_events()) break; - /* Do an interation */ + /* Do an iteration */ + /* Relese the lock before running an iteration */ + g_static_mutex_unlock(&event_mutex); g_main_context_iteration(NULL, !nonblock); + g_static_mutex_lock(&event_mutex); /* If the event we've been waiting for has fired or been released, as * appropriate, we're done. See the comments for event_wait in event.h @@ -361,6 +413,7 @@ event_loop_wait( * has been released. */ flush_dead_events(NULL); + g_static_mutex_unlock(&event_mutex); } GMainLoop *