systemclock: fix multi-thread entry status issue

Running two threads, one executing the timer and one unscheduling it, the
unscheduled status set by the second thread is sometimes overwritten by the
first one.

https://bugzilla.gnome.org/show_bug.cgi?id=737999
This commit is contained in:
Nicolas Huet 2014-10-06 13:38:21 +02:00 committed by Sebastian Dröge
parent 64a0abb0f4
commit 00bcd94723

View file

@ -637,7 +637,8 @@ gst_system_clock_id_wait_jitter_unlocked (GstClock * clock,
GstClockTimeDiff diff; GstClockTimeDiff diff;
GstClockReturn status; GstClockReturn status;
if (G_UNLIKELY (GET_ENTRY_STATUS (entry) == GST_CLOCK_UNSCHEDULED)) status = GET_ENTRY_STATUS (entry);
if (G_UNLIKELY (status == GST_CLOCK_UNSCHEDULED))
return GST_CLOCK_UNSCHEDULED; return GST_CLOCK_UNSCHEDULED;
/* need to call the overridden method because we want to sync against the time /* need to call the overridden method because we want to sync against the time
@ -737,8 +738,13 @@ gst_system_clock_id_wait_jitter_unlocked (GstClock * clock,
if (diff <= 0) { if (diff <= 0) {
/* timeout, this is fine, we can report success now */ /* timeout, this is fine, we can report success now */
status = GST_CLOCK_OK; if (G_UNLIKELY (!CAS_ENTRY_STATUS (entry, GST_CLOCK_DONE, GST_CLOCK_OK))) {
SET_ENTRY_STATUS (entry, status); GST_CAT_DEBUG (GST_CAT_CLOCK, "unexpected status for entry %p", entry);
status = GET_ENTRY_STATUS (entry);
goto done;
} else {
status = GST_CLOCK_OK;
}
GST_CAT_DEBUG (GST_CAT_CLOCK, GST_CAT_DEBUG (GST_CAT_CLOCK,
"entry %p finished, diff %" G_GINT64_FORMAT, entry, diff); "entry %p finished, diff %" G_GINT64_FORMAT, entry, diff);
@ -762,12 +768,21 @@ gst_system_clock_id_wait_jitter_unlocked (GstClock * clock,
} }
} else { } else {
/* we are right on time or too late */ /* we are right on time or too late */
if (G_UNLIKELY (diff == 0)) if (G_UNLIKELY (diff == 0)) {
status = GST_CLOCK_OK; if (G_UNLIKELY (!CAS_ENTRY_STATUS (entry, status, GST_CLOCK_OK))) {
else GST_CAT_DEBUG (GST_CAT_CLOCK, "unexpected status for entry %p", entry);
status = GST_CLOCK_EARLY; status = GET_ENTRY_STATUS (entry);
} else {
SET_ENTRY_STATUS (entry, status); status = GST_CLOCK_OK;
}
} else {
if (G_UNLIKELY (!CAS_ENTRY_STATUS (entry, status, GST_CLOCK_EARLY))) {
GST_CAT_DEBUG (GST_CAT_CLOCK, "unexpected status for entry %p", entry);
status = GET_ENTRY_STATUS (entry);
} else {
status = GST_CLOCK_EARLY;
}
}
} }
done: done:
return status; return status;