mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-11-10 11:29:55 +00:00
clock: use seqlocks to parallellize readers
This commit is contained in:
parent
f83809cf37
commit
bb8f296d45
3 changed files with 83 additions and 28 deletions
|
@ -414,6 +414,7 @@ GST_TYPE_CLOCK_FLAGS
|
|||
GST_TYPE_CLOCK_RETURN
|
||||
GST_TYPE_CLOCK_TIME
|
||||
<SUBSECTION Private>
|
||||
GstClockPrivate
|
||||
GST_CLOCK_SLAVE_LOCK
|
||||
GST_CLOCK_SLAVE_UNLOCK
|
||||
gst_clock_get_type
|
||||
|
|
105
gst/gstclock.c
105
gst/gstclock.c
|
@ -132,6 +132,41 @@ enum
|
|||
PROP_TIMEOUT
|
||||
};
|
||||
|
||||
struct _GstClockPrivate
|
||||
{
|
||||
gint pre_count;
|
||||
gint post_count;
|
||||
};
|
||||
|
||||
/* seqlocks */
|
||||
#define read_seqbegin(clock) \
|
||||
g_atomic_int_get (&clock->priv->post_count);
|
||||
|
||||
static inline gboolean
|
||||
read_seqretry (GstClock * clock, gint seq)
|
||||
{
|
||||
/* no retry if the seqnum did not change */
|
||||
if (G_LIKELY (seq == g_atomic_int_get (&clock->priv->pre_count)))
|
||||
return FALSE;
|
||||
|
||||
/* wait for the writer to finish and retry */
|
||||
GST_OBJECT_LOCK (clock);
|
||||
GST_OBJECT_UNLOCK (clock);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
#define write_seqlock(clock) \
|
||||
G_STMT_START { \
|
||||
GST_OBJECT_LOCK (clock); \
|
||||
g_atomic_int_inc (&clock->priv->pre_count); \
|
||||
} G_STMT_END;
|
||||
|
||||
#define write_sequnlock(clock) \
|
||||
G_STMT_START { \
|
||||
g_atomic_int_inc (&clock->priv->post_count); \
|
||||
GST_OBJECT_UNLOCK (clock); \
|
||||
} G_STMT_END;
|
||||
|
||||
static void gst_clock_class_init (GstClockClass * klass);
|
||||
static void gst_clock_init (GstClock * clock);
|
||||
static void gst_clock_dispose (GObject * object);
|
||||
|
@ -404,7 +439,7 @@ gst_clock_id_wait (GstClockID id, GstClockTimeDiff * jitter)
|
|||
if (entry->type == GST_CLOCK_ENTRY_PERIODIC)
|
||||
entry->time = requested + entry->interval;
|
||||
|
||||
if (clock->stats)
|
||||
if (G_UNLIKELY (clock->stats))
|
||||
gst_clock_update_stats (clock);
|
||||
|
||||
return res;
|
||||
|
@ -560,6 +595,8 @@ gst_clock_class_init (GstClockClass * klass)
|
|||
"The amount of time, in nanoseconds, to sample master and slave clocks",
|
||||
0, G_MAXUINT64, DEFAULT_TIMEOUT,
|
||||
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
|
||||
|
||||
g_type_class_add_private (klass, sizeof (GstClockPrivate));
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -570,6 +607,9 @@ gst_clock_init (GstClock * clock)
|
|||
clock->entries_changed = g_cond_new ();
|
||||
clock->stats = FALSE;
|
||||
|
||||
clock->priv =
|
||||
G_TYPE_INSTANCE_GET_PRIVATE (clock, GST_TYPE_CLOCK, GstClockPrivate);
|
||||
|
||||
clock->internal_calibration = 0;
|
||||
clock->external_calibration = 0;
|
||||
clock->rate_numerator = 1;
|
||||
|
@ -701,7 +741,7 @@ gst_clock_adjust_unlocked (GstClock * clock, GstClockTime internal)
|
|||
cdenom = clock->rate_denominator;
|
||||
|
||||
/* avoid divide by 0 */
|
||||
if (cdenom == 0)
|
||||
if (G_UNLIKELY (cdenom == 0))
|
||||
cnum = cdenom = 1;
|
||||
|
||||
/* The formula is (internal - cinternal) * cnum / cdenom + cexternal
|
||||
|
@ -711,12 +751,14 @@ gst_clock_adjust_unlocked (GstClock * clock, GstClockTime internal)
|
|||
* though.
|
||||
*/
|
||||
if (G_LIKELY (internal >= cinternal)) {
|
||||
ret = gst_util_uint64_scale (internal - cinternal, cnum, cdenom);
|
||||
ret = internal - cinternal;
|
||||
ret = gst_util_uint64_scale (ret, cnum, cdenom);
|
||||
ret += cexternal;
|
||||
} else {
|
||||
ret = gst_util_uint64_scale (cinternal - internal, cnum, cdenom);
|
||||
ret = cinternal - internal;
|
||||
ret = gst_util_uint64_scale (ret, cnum, cdenom);
|
||||
/* clamp to 0 */
|
||||
if (cexternal > ret)
|
||||
if (G_LIKELY (cexternal > ret))
|
||||
ret = cexternal - ret;
|
||||
else
|
||||
ret = 0;
|
||||
|
@ -756,16 +798,18 @@ gst_clock_unadjust_unlocked (GstClock * clock, GstClockTime external)
|
|||
cdenom = clock->rate_denominator;
|
||||
|
||||
/* avoid divide by 0 */
|
||||
if (cnum == 0)
|
||||
if (G_UNLIKELY (cnum == 0))
|
||||
cnum = cdenom = 1;
|
||||
|
||||
/* The formula is (external - cexternal) * cdenom / cnum + cinternal */
|
||||
if (external >= cexternal) {
|
||||
ret = gst_util_uint64_scale (external - cexternal, cdenom, cnum);
|
||||
if (G_LIKELY (external >= cexternal)) {
|
||||
ret = external - cexternal;
|
||||
ret = gst_util_uint64_scale (ret, cdenom, cnum);
|
||||
ret += cinternal;
|
||||
} else {
|
||||
ret = gst_util_uint64_scale (cexternal - external, cdenom, cnum);
|
||||
if (cinternal > ret)
|
||||
ret = cexternal - external;
|
||||
ret = gst_util_uint64_scale (ret, cdenom, cnum);
|
||||
if (G_LIKELY (cinternal > ret))
|
||||
ret = cinternal - ret;
|
||||
else
|
||||
ret = 0;
|
||||
|
@ -831,15 +875,19 @@ GstClockTime
|
|||
gst_clock_get_time (GstClock * clock)
|
||||
{
|
||||
GstClockTime ret;
|
||||
gint seq;
|
||||
|
||||
g_return_val_if_fail (GST_IS_CLOCK (clock), GST_CLOCK_TIME_NONE);
|
||||
|
||||
ret = gst_clock_get_internal_time (clock);
|
||||
do {
|
||||
/* reget the internal time when we retry to get the most current
|
||||
* timevalue */
|
||||
ret = gst_clock_get_internal_time (clock);
|
||||
|
||||
GST_OBJECT_LOCK (clock);
|
||||
/* this will scale for rate and offset */
|
||||
ret = gst_clock_adjust_unlocked (clock, ret);
|
||||
GST_OBJECT_UNLOCK (clock);
|
||||
seq = read_seqbegin (clock);
|
||||
/* this will scale for rate and offset */
|
||||
ret = gst_clock_adjust_unlocked (clock, ret);
|
||||
} while (read_seqretry (clock, seq));
|
||||
|
||||
GST_CAT_DEBUG_OBJECT (GST_CAT_CLOCK, clock, "adjusted time %" GST_TIME_FORMAT,
|
||||
GST_TIME_ARGS (ret));
|
||||
|
@ -889,7 +937,7 @@ gst_clock_set_calibration (GstClock * clock, GstClockTime internal, GstClockTime
|
|||
g_return_if_fail (rate_denom > 0 && rate_denom != GST_CLOCK_TIME_NONE);
|
||||
g_return_if_fail (internal <= gst_clock_get_internal_time (clock));
|
||||
|
||||
GST_OBJECT_LOCK (clock);
|
||||
write_seqlock (clock);
|
||||
GST_CAT_DEBUG_OBJECT (GST_CAT_CLOCK, clock,
|
||||
"internal %" GST_TIME_FORMAT " external %" GST_TIME_FORMAT " %"
|
||||
G_GUINT64_FORMAT "/%" G_GUINT64_FORMAT " = %f", GST_TIME_ARGS (internal),
|
||||
|
@ -900,7 +948,7 @@ gst_clock_set_calibration (GstClock * clock, GstClockTime internal, GstClockTime
|
|||
clock->external_calibration = external;
|
||||
clock->rate_numerator = rate_num;
|
||||
clock->rate_denominator = rate_denom;
|
||||
GST_OBJECT_UNLOCK (clock);
|
||||
write_sequnlock (clock);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -923,18 +971,21 @@ void
|
|||
gst_clock_get_calibration (GstClock * clock, GstClockTime * internal,
|
||||
GstClockTime * external, GstClockTime * rate_num, GstClockTime * rate_denom)
|
||||
{
|
||||
gint seq;
|
||||
|
||||
g_return_if_fail (GST_IS_CLOCK (clock));
|
||||
|
||||
GST_OBJECT_LOCK (clock);
|
||||
if (rate_num)
|
||||
*rate_num = clock->rate_numerator;
|
||||
if (rate_denom)
|
||||
*rate_denom = clock->rate_denominator;
|
||||
if (external)
|
||||
*external = clock->external_calibration;
|
||||
if (internal)
|
||||
*internal = clock->internal_calibration;
|
||||
GST_OBJECT_UNLOCK (clock);
|
||||
do {
|
||||
seq = read_seqbegin (clock);
|
||||
if (rate_num)
|
||||
*rate_num = clock->rate_numerator;
|
||||
if (rate_denom)
|
||||
*rate_denom = clock->rate_denominator;
|
||||
if (external)
|
||||
*external = clock->external_calibration;
|
||||
if (internal)
|
||||
*internal = clock->internal_calibration;
|
||||
} while (read_seqretry (clock, seq));
|
||||
}
|
||||
|
||||
/* will be called repeatedly to sample the master and slave clock
|
||||
|
|
|
@ -235,6 +235,7 @@ G_STMT_START { \
|
|||
typedef struct _GstClockEntry GstClockEntry;
|
||||
typedef struct _GstClock GstClock;
|
||||
typedef struct _GstClockClass GstClockClass;
|
||||
typedef struct _GstClockPrivate GstClockPrivate;
|
||||
|
||||
/* --- prototype for async callbacks --- */
|
||||
/**
|
||||
|
@ -447,7 +448,9 @@ struct _GstClock {
|
|||
GstClockID clockid;
|
||||
|
||||
/*< private >*/
|
||||
GstClockTime _gst_reserved[GST_PADDING];
|
||||
GstClockPrivate *priv;
|
||||
|
||||
GstClockTime _gst_reserved[GST_PADDING-1];
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
Loading…
Reference in a new issue