From df30f6004827a674e9e70d1c15a468871abc4ba1 Mon Sep 17 00:00:00 2001 From: Wim Taymans Date: Thu, 26 Mar 2009 15:55:02 +0100 Subject: [PATCH] clock: fix 2 wakeup races. when an entry being waited on in the async thread is unscheduled, clear the wakeup queue so we can continue waiting on other entries. When an entry being waited on in the async thread is unlocked because an earlier entry was added to the list, set the entry to OK again. This makes sure that only the entries being waited on have the BUSY flag set and wake up the timer poll when they are unscheduled. --- gst/gstsystemclock.c | 9 +++++++++ tests/check/gst/gstsystemclock.c | 7 +++++-- 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/gst/gstsystemclock.c b/gst/gstsystemclock.c index bc4fe2b05d..b65c0d877b 100644 --- a/gst/gstsystemclock.c +++ b/gst/gstsystemclock.c @@ -374,6 +374,7 @@ gst_system_clock_async_thread (GstClock * clock) /* if it was unscheduled, just move on to the next entry */ if (entry->status == GST_CLOCK_UNSCHEDULED) { GST_CAT_DEBUG (GST_CAT_CLOCK, "entry %p was unscheduled", entry); + gst_system_clock_clear_async_wakeups_unlocked (sysclock); goto next_entry; } @@ -407,6 +408,7 @@ gst_system_clock_async_thread (GstClock * clock) gst_system_clock_clear_async_wakeups_unlocked (sysclock); } if (entry->type == GST_CLOCK_ENTRY_PERIODIC) { + GST_CAT_DEBUG (GST_CAT_CLOCK, "updating periodic entry %p", entry); /* adjust time now */ entry->time = requested + entry->interval; /* and resort the list now */ @@ -426,6 +428,13 @@ gst_system_clock_async_thread (GstClock * clock) GST_CAT_DEBUG (GST_CAT_CLOCK, "async entry %p needs restart", entry); /* clear async wakeups, if any */ gst_system_clock_clear_async_wakeups_unlocked (sysclock); + + if (clock->entries->data != entry) { + /* if the new head is not this entry, we set the entry back to the OK + * state. This is needed so that the _unschedule() code can see if an + * entry is currently being waited on (when its state is BUSY). */ + entry->status = GST_CLOCK_OK; + } continue; default: GST_CAT_DEBUG (GST_CAT_CLOCK, diff --git a/tests/check/gst/gstsystemclock.c b/tests/check/gst/gstsystemclock.c index 52406e0591..53cb5779b1 100644 --- a/tests/check/gst/gstsystemclock.c +++ b/tests/check/gst/gstsystemclock.c @@ -169,6 +169,7 @@ GST_START_TEST (test_single_shot) GST_DEBUG ("waiting id %p", id); result = gst_clock_id_wait_async (id, ok_callback, NULL); fail_unless (result == GST_CLOCK_OK, "Waiting did not return OK"); + GST_DEBUG ("waiting id %p", id2); result = gst_clock_id_wait_async (id2, error_callback, NULL); fail_unless (result == GST_CLOCK_OK, "Waiting did not return OK"); @@ -177,9 +178,11 @@ GST_START_TEST (test_single_shot) gst_clock_id_unschedule (id2); GST_DEBUG ("canceled id %p", id2); gst_clock_id_unref (id2); - g_usleep (TIME_UNIT / (2 * 1000)); - gst_clock_id_unschedule (id); + /* wait for the entry to time out */ + g_usleep (TIME_UNIT / 1000 * 5); + fail_unless (((GstClockEntry *) id)->status == GST_CLOCK_OK, + "Waiting did not finish"); gst_clock_id_unref (id); gst_object_unref (clock);