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.
This commit is contained in:
Wim Taymans 2009-03-26 15:55:02 +01:00
parent ea554b1d62
commit df30f60048
2 changed files with 14 additions and 2 deletions

View file

@ -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,

View file

@ -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);