Merge branch 'master' into 0.11
[platform/upstream/gstreamer.git] / gst / gstsystemclock.c
1 /* GStreamer
2  * Copyright (C) 1999,2000 Erik Walthinsen <omega@cse.ogi.edu>
3  *                    2004 Wim Taymans <wim@fluendo.com>
4  *
5  * gstsystemclock.c: Default clock, uses the system clock
6  *
7  * This library is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Library General Public
9  * License as published by the Free Software Foundation; either
10  * version 2 of the License, or (at your option) any later version.
11  *
12  * This library is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * Library General Public License for more details.
16  *
17  * You should have received a copy of the GNU Library General Public
18  * License along with this library; if not, write to the
19  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
20  * Boston, MA 02111-1307, USA.
21  */
22
23 /**
24  * SECTION:gstsystemclock
25  * @short_description: Default clock that uses the current system time
26  * @see_also: #GstClock
27  *
28  * The GStreamer core provides a GstSystemClock based on the system time.
29  * Asynchronous callbacks are scheduled from an internal thread.
30  *
31  * Clock implementors are encouraged to subclass this systemclock as it
32  * implements the async notification.
33  *
34  * Subclasses can however override all of the important methods for sync and
35  * async notifications to implement their own callback methods or blocking
36  * wait operations.
37  *
38  * Last reviewed on 2006-03-08 (0.10.4)
39  */
40
41 #include "gst_private.h"
42 #include "gstinfo.h"
43 #include "gstsystemclock.h"
44 #include "gstenumtypes.h"
45 #include "gstpoll.h"
46 #include "gstutils.h"
47
48 #include <errno.h>
49
50 #ifdef G_OS_WIN32
51 #  define WIN32_LEAN_AND_MEAN   /* prevents from including too many things */
52 #  include <windows.h>          /* QueryPerformance* stuff */
53 #  undef WIN32_LEAN_AND_MEAN
54 #  define EWOULDBLOCK EAGAIN    /* This is just to placate gcc */
55 #endif /* G_OS_WIN32 */
56
57 #define GET_ENTRY_STATUS(e)          (g_atomic_int_get(&GST_CLOCK_ENTRY_STATUS(e)))
58 #define SET_ENTRY_STATUS(e,val)      (g_atomic_int_set(&GST_CLOCK_ENTRY_STATUS(e),(val)))
59 #define CAS_ENTRY_STATUS(e,old,val)  (g_atomic_int_compare_and_exchange(\
60                                        ((volatile gint *)&GST_CLOCK_ENTRY_STATUS(e)), (old), (val)))
61
62 /* Define this to get some extra debug about jitter from each clock_wait */
63 #undef WAIT_DEBUGGING
64
65 struct _GstSystemClockPrivate
66 {
67   GstClockType clock_type;
68   GstPoll *timer;
69   gint wakeup_count;            /* the number of entries with a pending wakeup */
70   gboolean async_wakeup;        /* if the wakeup was because of a async list change */
71
72 #ifdef G_OS_WIN32
73   LARGE_INTEGER start;
74   LARGE_INTEGER frequency;
75 #endif                          /* G_OS_WIN32 */
76 };
77
78 #define GST_SYSTEM_CLOCK_GET_PRIVATE(obj)  \
79    (G_TYPE_INSTANCE_GET_PRIVATE ((obj), GST_TYPE_SYSTEM_CLOCK, \
80         GstSystemClockPrivate))
81
82 #ifdef HAVE_POSIX_TIMERS
83 # ifdef HAVE_MONOTONIC_CLOCK
84 #  define DEFAULT_CLOCK_TYPE GST_CLOCK_TYPE_MONOTONIC
85 # else
86 #  define DEFAULT_CLOCK_TYPE GST_CLOCK_TYPE_REALTIME
87 # endif
88 #else
89 #define DEFAULT_CLOCK_TYPE GST_CLOCK_TYPE_REALTIME
90 #endif
91
92 enum
93 {
94   PROP_0,
95   PROP_CLOCK_TYPE,
96   /* FILL ME */
97 };
98
99 /* the one instance of the systemclock */
100 static GstClock *_the_system_clock = NULL;
101
102 static void gst_system_clock_dispose (GObject * object);
103 static void gst_system_clock_set_property (GObject * object, guint prop_id,
104     const GValue * value, GParamSpec * pspec);
105 static void gst_system_clock_get_property (GObject * object, guint prop_id,
106     GValue * value, GParamSpec * pspec);
107
108 static GstClockTime gst_system_clock_get_internal_time (GstClock * clock);
109 static guint64 gst_system_clock_get_resolution (GstClock * clock);
110 static GstClockReturn gst_system_clock_id_wait_jitter (GstClock * clock,
111     GstClockEntry * entry, GstClockTimeDiff * jitter);
112 static GstClockReturn gst_system_clock_id_wait_jitter_unlocked
113     (GstClock * clock, GstClockEntry * entry, GstClockTimeDiff * jitter,
114     gboolean restart);
115 static GstClockReturn gst_system_clock_id_wait_async (GstClock * clock,
116     GstClockEntry * entry);
117 static void gst_system_clock_id_unschedule (GstClock * clock,
118     GstClockEntry * entry);
119 static void gst_system_clock_async_thread (GstClock * clock);
120 static gboolean gst_system_clock_start_async (GstSystemClock * clock);
121 static void gst_system_clock_add_wakeup (GstSystemClock * sysclock);
122
123 static GStaticMutex _gst_sysclock_mutex = G_STATIC_MUTEX_INIT;
124
125 static GstClockClass *parent_class = NULL;
126
127 /* static guint gst_system_clock_signals[LAST_SIGNAL] = { 0 }; */
128
129 G_DEFINE_TYPE (GstSystemClock, gst_system_clock, GST_TYPE_CLOCK);
130
131 static void
132 gst_system_clock_class_init (GstSystemClockClass * klass)
133 {
134   GObjectClass *gobject_class;
135   GstClockClass *gstclock_class;
136
137   gobject_class = (GObjectClass *) klass;
138   gstclock_class = (GstClockClass *) klass;
139
140   parent_class = g_type_class_peek_parent (klass);
141
142   g_type_class_add_private (klass, sizeof (GstSystemClockPrivate));
143
144   gobject_class->dispose = gst_system_clock_dispose;
145   gobject_class->set_property = gst_system_clock_set_property;
146   gobject_class->get_property = gst_system_clock_get_property;
147
148   g_object_class_install_property (gobject_class, PROP_CLOCK_TYPE,
149       g_param_spec_enum ("clock-type", "Clock type",
150           "The type of underlying clock implementation used",
151           GST_TYPE_CLOCK_TYPE, DEFAULT_CLOCK_TYPE,
152           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
153
154   gstclock_class->get_internal_time = gst_system_clock_get_internal_time;
155   gstclock_class->get_resolution = gst_system_clock_get_resolution;
156   gstclock_class->wait = gst_system_clock_id_wait_jitter;
157   gstclock_class->wait_async = gst_system_clock_id_wait_async;
158   gstclock_class->unschedule = gst_system_clock_id_unschedule;
159 }
160
161 static void
162 gst_system_clock_init (GstSystemClock * clock)
163 {
164   GST_OBJECT_FLAG_SET (clock,
165       GST_CLOCK_FLAG_CAN_DO_SINGLE_SYNC |
166       GST_CLOCK_FLAG_CAN_DO_SINGLE_ASYNC |
167       GST_CLOCK_FLAG_CAN_DO_PERIODIC_SYNC |
168       GST_CLOCK_FLAG_CAN_DO_PERIODIC_ASYNC);
169
170   clock->priv = GST_SYSTEM_CLOCK_GET_PRIVATE (clock);
171
172   clock->priv->clock_type = DEFAULT_CLOCK_TYPE;
173   clock->priv->timer = gst_poll_new_timer ();
174
175 #ifdef G_OS_WIN32
176   QueryPerformanceFrequency (&clock->priv->frequency);
177   /* can be 0 if the hardware does not have hardware support */
178   if (clock->priv->frequency.QuadPart != 0)
179     /* we take a base time so that time starts from 0 to ease debugging */
180     QueryPerformanceCounter (&clock->priv->start);
181 #endif /* G_OS_WIN32 */
182
183 #if 0
184   /* Uncomment this to start the async clock thread straight away */
185   GST_OBJECT_LOCK (clock);
186   gst_system_clock_start_async (clock);
187   GST_OBJECT_UNLOCK (clock);
188 #endif
189 }
190
191 static void
192 gst_system_clock_dispose (GObject * object)
193 {
194   GstClock *clock = (GstClock *) object;
195   GstSystemClock *sysclock = GST_SYSTEM_CLOCK_CAST (clock);
196   GList *entries;
197
198   /* else we have to stop the thread */
199   GST_OBJECT_LOCK (clock);
200   sysclock->stopping = TRUE;
201   /* unschedule all entries */
202   for (entries = clock->entries; entries; entries = g_list_next (entries)) {
203     GstClockEntry *entry = (GstClockEntry *) entries->data;
204
205     GST_CAT_DEBUG (GST_CAT_CLOCK, "unscheduling entry %p", entry);
206     SET_ENTRY_STATUS (entry, GST_CLOCK_UNSCHEDULED);
207   }
208   GST_CLOCK_BROADCAST (clock);
209   gst_system_clock_add_wakeup (sysclock);
210   GST_OBJECT_UNLOCK (clock);
211
212   if (sysclock->thread)
213     g_thread_join (sysclock->thread);
214   sysclock->thread = NULL;
215   GST_CAT_DEBUG (GST_CAT_CLOCK, "joined thread");
216
217   g_list_foreach (clock->entries, (GFunc) gst_clock_id_unref, NULL);
218   g_list_free (clock->entries);
219   clock->entries = NULL;
220
221   gst_poll_free (sysclock->priv->timer);
222
223   G_OBJECT_CLASS (parent_class)->dispose (object);
224
225   if (_the_system_clock == clock) {
226     _the_system_clock = NULL;
227     GST_CAT_DEBUG (GST_CAT_CLOCK, "disposed system clock");
228   }
229 }
230
231 static void
232 gst_system_clock_set_property (GObject * object, guint prop_id,
233     const GValue * value, GParamSpec * pspec)
234 {
235   GstSystemClock *sysclock = GST_SYSTEM_CLOCK (object);
236
237   switch (prop_id) {
238     case PROP_CLOCK_TYPE:
239       sysclock->priv->clock_type = g_value_get_enum (value);
240       GST_CAT_DEBUG (GST_CAT_CLOCK, "clock-type set to %d",
241           sysclock->priv->clock_type);
242       break;
243     default:
244       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
245       break;
246   }
247 }
248
249 static void
250 gst_system_clock_get_property (GObject * object, guint prop_id, GValue * value,
251     GParamSpec * pspec)
252 {
253   GstSystemClock *sysclock = GST_SYSTEM_CLOCK (object);
254
255   switch (prop_id) {
256     case PROP_CLOCK_TYPE:
257       g_value_set_enum (value, sysclock->priv->clock_type);
258       break;
259     default:
260       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
261       break;
262   }
263 }
264
265 /**
266  * gst_system_clock_obtain:
267  *
268  * Get a handle to the default system clock. The refcount of the
269  * clock will be increased so you need to unref the clock after
270  * usage.
271  *
272  * Returns: (transfer full): the default clock.
273  *
274  * MT safe.
275  */
276 GstClock *
277 gst_system_clock_obtain (void)
278 {
279   GstClock *clock;
280
281   g_static_mutex_lock (&_gst_sysclock_mutex);
282   clock = _the_system_clock;
283
284   if (clock == NULL) {
285     GST_CAT_DEBUG (GST_CAT_CLOCK, "creating new static system clock");
286     clock = g_object_new (GST_TYPE_SYSTEM_CLOCK,
287         "name", "GstSystemClock", NULL);
288
289     /* we created the global clock; take ownership so
290      * we can hand out instances later */
291     gst_object_ref_sink (clock);
292
293     _the_system_clock = clock;
294     g_static_mutex_unlock (&_gst_sysclock_mutex);
295   } else {
296     g_static_mutex_unlock (&_gst_sysclock_mutex);
297     GST_CAT_DEBUG (GST_CAT_CLOCK, "returning static system clock");
298   }
299
300   /* we ref it since we are a clock factory. */
301   gst_object_ref (clock);
302   return clock;
303 }
304
305 static void
306 gst_system_clock_remove_wakeup (GstSystemClock * sysclock)
307 {
308   g_return_if_fail (sysclock->priv->wakeup_count > 0);
309
310   sysclock->priv->wakeup_count--;
311   if (sysclock->priv->wakeup_count == 0) {
312     /* read the control socket byte when we removed the last wakeup count */
313     GST_CAT_DEBUG (GST_CAT_CLOCK, "reading control");
314     while (!gst_poll_read_control (sysclock->priv->timer)) {
315       g_warning ("gstsystemclock: read control failed, trying again\n");
316     }
317     GST_CLOCK_BROADCAST (sysclock);
318   }
319   GST_CAT_DEBUG (GST_CAT_CLOCK, "wakeup count %d",
320       sysclock->priv->wakeup_count);
321 }
322
323 static void
324 gst_system_clock_add_wakeup (GstSystemClock * sysclock)
325 {
326   /* only write the control socket for the first wakeup */
327   if (sysclock->priv->wakeup_count == 0) {
328     GST_CAT_DEBUG (GST_CAT_CLOCK, "writing control");
329     while (!gst_poll_write_control (sysclock->priv->timer)) {
330       if (errno == EAGAIN || errno == EWOULDBLOCK || errno == EINTR) {
331         g_warning
332             ("gstsystemclock: write control failed in wakeup_async, trying again: %d:%s\n",
333             errno, g_strerror (errno));
334       } else {
335         g_critical
336             ("gstsystemclock: write control failed in wakeup_async: %d:%s\n",
337             errno, g_strerror (errno));
338         return;
339       }
340     }
341   }
342   sysclock->priv->wakeup_count++;
343   GST_CAT_DEBUG (GST_CAT_CLOCK, "wakeup count %d",
344       sysclock->priv->wakeup_count);
345 }
346
347 static void
348 gst_system_clock_wait_wakeup (GstSystemClock * sysclock)
349 {
350   while (sysclock->priv->wakeup_count > 0) {
351     GST_CLOCK_WAIT (sysclock);
352   }
353 }
354
355 /* this thread reads the sorted clock entries from the queue.
356  *
357  * It waits on each of them and fires the callback when the timeout occurs.
358  *
359  * When an entry in the queue was canceled before we wait for it, it is
360  * simply skipped.
361  *
362  * When waiting for an entry, it can become canceled, in that case we don't
363  * call the callback but move to the next item in the queue.
364  *
365  * MT safe.
366  */
367 static void
368 gst_system_clock_async_thread (GstClock * clock)
369 {
370   GstSystemClock *sysclock = GST_SYSTEM_CLOCK_CAST (clock);
371
372   GST_CAT_DEBUG (GST_CAT_CLOCK, "enter system clock thread");
373   GST_OBJECT_LOCK (clock);
374   /* signal spinup */
375   GST_CLOCK_BROADCAST (clock);
376   /* now enter our (almost) infinite loop */
377   while (!sysclock->stopping) {
378     GstClockEntry *entry;
379     GstClockTime requested;
380     GstClockReturn res;
381
382     /* check if something to be done */
383     while (clock->entries == NULL) {
384       GST_CAT_DEBUG (GST_CAT_CLOCK, "no clock entries, waiting..");
385       /* wait for work to do */
386       GST_CLOCK_WAIT (clock);
387       GST_CAT_DEBUG (GST_CAT_CLOCK, "got signal");
388       /* clock was stopping, exit */
389       if (sysclock->stopping)
390         goto exit;
391     }
392
393     /* see if we have a pending wakeup because the order of the list
394      * changed. */
395     if (sysclock->priv->async_wakeup) {
396       GST_CAT_DEBUG (GST_CAT_CLOCK, "clear async wakeup");
397       gst_system_clock_remove_wakeup (sysclock);
398       sysclock->priv->async_wakeup = FALSE;
399     }
400
401     /* pick the next entry */
402     entry = clock->entries->data;
403     GST_OBJECT_UNLOCK (clock);
404
405     requested = entry->time;
406
407     /* now wait for the entry, we already hold the lock */
408     res =
409         gst_system_clock_id_wait_jitter_unlocked (clock, (GstClockID) entry,
410         NULL, FALSE);
411
412     GST_OBJECT_LOCK (clock);
413
414     switch (res) {
415       case GST_CLOCK_UNSCHEDULED:
416         /* entry was unscheduled, move to the next */
417         GST_CAT_DEBUG (GST_CAT_CLOCK, "async entry %p unscheduled", entry);
418         goto next_entry;
419       case GST_CLOCK_OK:
420       case GST_CLOCK_EARLY:
421       {
422         /* entry timed out normally, fire the callback and move to the next
423          * entry */
424         GST_CAT_DEBUG (GST_CAT_CLOCK, "async entry %p timed out", entry);
425         if (entry->func) {
426           /* unlock before firing the callback */
427           GST_OBJECT_UNLOCK (clock);
428           entry->func (clock, entry->time, (GstClockID) entry,
429               entry->user_data);
430           GST_OBJECT_LOCK (clock);
431         }
432         if (entry->type == GST_CLOCK_ENTRY_PERIODIC) {
433           GST_CAT_DEBUG (GST_CAT_CLOCK, "updating periodic entry %p", entry);
434           /* adjust time now */
435           entry->time = requested + entry->interval;
436           /* and resort the list now */
437           clock->entries =
438               g_list_sort (clock->entries, gst_clock_id_compare_func);
439           /* and restart */
440           continue;
441         } else {
442           GST_CAT_DEBUG (GST_CAT_CLOCK, "moving to next entry");
443           goto next_entry;
444         }
445       }
446       case GST_CLOCK_BUSY:
447         /* somebody unlocked the entry but is was not canceled, This means that
448          * either a new entry was added in front of the queue or some other entry
449          * was canceled. Whatever it is, pick the head entry of the list and
450          * continue waiting. */
451         GST_CAT_DEBUG (GST_CAT_CLOCK, "async entry %p needs restart", entry);
452
453         /* we set the entry back to the OK state. This is needed so that the
454          * _unschedule() code can see if an entry is currently being waited
455          * on (when its state is BUSY). */
456         SET_ENTRY_STATUS (entry, GST_CLOCK_OK);
457         continue;
458       default:
459         GST_CAT_DEBUG (GST_CAT_CLOCK,
460             "strange result %d waiting for %p, skipping", res, entry);
461         g_warning ("%s: strange result %d waiting for %p, skipping",
462             GST_OBJECT_NAME (clock), res, entry);
463         goto next_entry;
464     }
465   next_entry:
466     /* we remove the current entry and unref it */
467     clock->entries = g_list_remove (clock->entries, entry);
468     gst_clock_id_unref ((GstClockID) entry);
469   }
470 exit:
471   /* signal exit */
472   GST_CLOCK_BROADCAST (clock);
473   GST_OBJECT_UNLOCK (clock);
474   GST_CAT_DEBUG (GST_CAT_CLOCK, "exit system clock thread");
475 }
476
477 #ifdef HAVE_POSIX_TIMERS
478 static inline clockid_t
479 clock_type_to_posix_id (GstClockType clock_type)
480 {
481 #ifdef HAVE_MONOTONIC_CLOCK
482   if (clock_type == GST_CLOCK_TYPE_MONOTONIC)
483     return CLOCK_MONOTONIC;
484   else
485 #endif
486     return CLOCK_REALTIME;
487 }
488 #endif
489
490 /* MT safe */
491 static GstClockTime
492 gst_system_clock_get_internal_time (GstClock * clock)
493 {
494 #ifdef G_OS_WIN32
495   GstSystemClock *sysclock = GST_SYSTEM_CLOCK_CAST (clock);
496
497   if (sysclock->priv->frequency.QuadPart != 0) {
498     LARGE_INTEGER now;
499
500     /* we prefer the highly accurate performance counters on windows */
501     QueryPerformanceCounter (&now);
502
503     return gst_util_uint64_scale (now.QuadPart - sysclock->priv->start.QuadPart,
504         GST_SECOND, sysclock->priv->frequency.QuadPart);
505   } else
506 #endif /* G_OS_WIN32 */
507 #if !defined HAVE_POSIX_TIMERS
508   {
509     GTimeVal timeval;
510
511     g_get_current_time (&timeval);
512
513     return GST_TIMEVAL_TO_TIME (timeval);
514   }
515 #else
516   {
517     GstSystemClock *sysclock = GST_SYSTEM_CLOCK_CAST (clock);
518     clockid_t ptype;
519     struct timespec ts;
520
521     ptype = clock_type_to_posix_id (sysclock->priv->clock_type);
522
523     if (G_UNLIKELY (clock_gettime (ptype, &ts)))
524       return GST_CLOCK_TIME_NONE;
525
526     return GST_TIMESPEC_TO_TIME (ts);
527   }
528 #endif
529 }
530
531 static guint64
532 gst_system_clock_get_resolution (GstClock * clock)
533 {
534 #ifdef G_OS_WIN32
535   GstSystemClock *sysclock = GST_SYSTEM_CLOCK_CAST (clock);
536
537   if (sysclock->priv->frequency.QuadPart != 0) {
538     return GST_SECOND / sysclock->priv->frequency.QuadPart;
539   } else
540 #endif /* G_OS_WIN32 */
541 #ifdef HAVE_POSIX_TIMERS
542   {
543     GstSystemClock *sysclock = GST_SYSTEM_CLOCK_CAST (clock);
544     clockid_t ptype;
545     struct timespec ts;
546
547     ptype = clock_type_to_posix_id (sysclock->priv->clock_type);
548
549     if (G_UNLIKELY (clock_getres (ptype, &ts)))
550       return GST_CLOCK_TIME_NONE;
551
552     return GST_TIMESPEC_TO_TIME (ts);
553   }
554 #else
555   {
556     return 1 * GST_USECOND;
557   }
558 #endif
559 }
560
561 /* synchronously wait on the given GstClockEntry.
562  *
563  * We do this by blocking on the global GstPoll timer with
564  * the requested timeout. This allows us to unblock the
565  * entry by writing on the control fd.
566  *
567  * Note that writing the global GstPoll unlocks all waiting entries. So
568  * we need to check if an unlocked entry has changed when it unlocks.
569  *
570  * Entries that arrive too late are simply not waited on and a
571  * GST_CLOCK_EARLY result is returned.
572  *
573  * MT safe.
574  */
575 static GstClockReturn
576 gst_system_clock_id_wait_jitter_unlocked (GstClock * clock,
577     GstClockEntry * entry, GstClockTimeDiff * jitter, gboolean restart)
578 {
579   GstSystemClock *sysclock = GST_SYSTEM_CLOCK_CAST (clock);
580   GstClockTime entryt, now;
581   GstClockTimeDiff diff;
582   GstClockReturn status;
583
584   if (G_UNLIKELY (GET_ENTRY_STATUS (entry) == GST_CLOCK_UNSCHEDULED))
585     return GST_CLOCK_UNSCHEDULED;
586
587   /* need to call the overridden method because we want to sync against the time
588    * of the clock, whatever the subclass uses as a clock. */
589   now = gst_clock_get_time (clock);
590
591   /* get the time of the entry */
592   entryt = GST_CLOCK_ENTRY_TIME (entry);
593
594   /* the diff of the entry with the clock is the amount of time we have to
595    * wait */
596   diff = GST_CLOCK_DIFF (now, entryt);
597   if (G_LIKELY (jitter))
598     *jitter = -diff;
599
600   GST_CAT_DEBUG (GST_CAT_CLOCK, "entry %p"
601       " time %" GST_TIME_FORMAT
602       " now %" GST_TIME_FORMAT
603       " diff (time-now) %" G_GINT64_FORMAT,
604       entry, GST_TIME_ARGS (entryt), GST_TIME_ARGS (now), diff);
605
606   if (G_LIKELY (diff > 0)) {
607 #ifdef WAIT_DEBUGGING
608     GstClockTime final;
609 #endif
610
611     while (TRUE) {
612       gint pollret;
613
614       do {
615         status = GET_ENTRY_STATUS (entry);
616
617         /* stop when we are unscheduled */
618         if (G_UNLIKELY (status == GST_CLOCK_UNSCHEDULED))
619           goto done;
620
621         /* mark the entry as busy but watch out for intermediate unscheduled
622          * statuses */
623       } while (G_UNLIKELY (!CAS_ENTRY_STATUS (entry, status, GST_CLOCK_BUSY)));
624
625       /* now wait on the entry, it either times out or the fd is written. The
626        * status of the entry is only BUSY around the poll. */
627       pollret = gst_poll_wait (sysclock->priv->timer, diff);
628
629       /* get the new status, mark as DONE. We do this so that the unschedule
630        * function knows when we left the poll and doesn't need to wakeup the
631        * poll anymore. */
632       do {
633         status = GET_ENTRY_STATUS (entry);
634         /* we were unscheduled, exit immediately */
635         if (G_UNLIKELY (status == GST_CLOCK_UNSCHEDULED))
636           break;
637       } while (G_UNLIKELY (!CAS_ENTRY_STATUS (entry, status, GST_CLOCK_DONE)));
638
639       GST_CAT_DEBUG (GST_CAT_CLOCK, "entry %p unlocked, status %d, ret %d",
640           entry, status, pollret);
641
642       if (G_UNLIKELY (status == GST_CLOCK_UNSCHEDULED)) {
643         /* try to clean up The unschedule function managed to set the status to
644          * unscheduled. We now take the lock and mark the entry as unscheduled.
645          * This makes sure that the unschedule function doesn't perform a
646          * wakeup anymore. If the unschedule function has a change to perform
647          * the wakeup before us, we clean up here */
648         GST_OBJECT_LOCK (sysclock);
649         entry->unscheduled = TRUE;
650         if (entry->woken_up) {
651           gst_system_clock_remove_wakeup (sysclock);
652         }
653         GST_OBJECT_UNLOCK (sysclock);
654         goto done;
655       } else {
656         if (G_UNLIKELY (pollret != 0)) {
657           /* some other id got unlocked */
658           if (!restart) {
659             /* this can happen if the entry got unlocked because of an async
660              * entry was added to the head of the async queue. */
661             GST_CAT_DEBUG (GST_CAT_CLOCK, "wakeup waiting for entry %p", entry);
662             goto done;
663           }
664
665           /* wait till all the entries got woken up */
666           GST_OBJECT_LOCK (sysclock);
667           gst_system_clock_wait_wakeup (sysclock);
668           GST_OBJECT_UNLOCK (sysclock);
669
670           GST_CAT_DEBUG (GST_CAT_CLOCK, "entry %p needs to be restarted",
671               entry);
672         } else {
673           GST_CAT_DEBUG (GST_CAT_CLOCK, "entry %p unlocked after timeout",
674               entry);
675         }
676
677         /* reschedule if gst_poll_wait returned early or we have to reschedule after
678          * an unlock*/
679         now = gst_clock_get_time (clock);
680         diff = GST_CLOCK_DIFF (now, entryt);
681
682         if (diff <= 0) {
683           /* timeout, this is fine, we can report success now */
684           status = GST_CLOCK_OK;
685           SET_ENTRY_STATUS (entry, status);
686
687           GST_CAT_DEBUG (GST_CAT_CLOCK,
688               "entry %p finished, diff %" G_GINT64_FORMAT, entry, diff);
689
690 #ifdef WAIT_DEBUGGING
691           final = gst_system_clock_get_internal_time (clock);
692           GST_CAT_DEBUG (GST_CAT_CLOCK, "Waited for %" G_GINT64_FORMAT
693               " got %" G_GINT64_FORMAT " diff %" G_GINT64_FORMAT
694               " %g target-offset %" G_GINT64_FORMAT " %g", entryt, now,
695               now - entryt,
696               (double) (GstClockTimeDiff) (now - entryt) / GST_SECOND,
697               (final - target),
698               ((double) (GstClockTimeDiff) (final - target)) / GST_SECOND);
699 #endif
700           goto done;
701         } else {
702           GST_CAT_DEBUG (GST_CAT_CLOCK,
703               "entry %p restart, diff %" G_GINT64_FORMAT, entry, diff);
704         }
705       }
706     }
707   } else {
708     /* we are right on time or too late */
709     if (G_UNLIKELY (diff == 0))
710       status = GST_CLOCK_OK;
711     else
712       status = GST_CLOCK_EARLY;
713
714     SET_ENTRY_STATUS (entry, status);
715   }
716 done:
717   return status;
718 }
719
720 static GstClockReturn
721 gst_system_clock_id_wait_jitter (GstClock * clock, GstClockEntry * entry,
722     GstClockTimeDiff * jitter)
723 {
724   return gst_system_clock_id_wait_jitter_unlocked (clock, entry, jitter, TRUE);
725 }
726
727 /* Start the async clock thread. Must be called with the object lock
728  * held */
729 static gboolean
730 gst_system_clock_start_async (GstSystemClock * clock)
731 {
732   GError *error = NULL;
733
734   if (G_LIKELY (clock->thread != NULL))
735     return TRUE;                /* Thread already running. Nothing to do */
736
737   clock->thread = g_thread_create ((GThreadFunc) gst_system_clock_async_thread,
738       clock, TRUE, &error);
739   if (G_UNLIKELY (error))
740     goto no_thread;
741
742   /* wait for it to spin up */
743   GST_CLOCK_WAIT (clock);
744
745   return TRUE;
746
747   /* ERRORS */
748 no_thread:
749   {
750     g_warning ("could not create async clock thread: %s", error->message);
751     g_error_free (error);
752   }
753   return FALSE;
754 }
755
756 /* Add an entry to the list of pending async waits. The entry is inserted
757  * in sorted order. If we inserted the entry at the head of the list, we
758  * need to signal the thread as it might either be waiting on it or waiting
759  * for a new entry.
760  *
761  * MT safe.
762  */
763 static GstClockReturn
764 gst_system_clock_id_wait_async (GstClock * clock, GstClockEntry * entry)
765 {
766   GstSystemClock *sysclock;
767   GstClockEntry *head;
768
769   sysclock = GST_SYSTEM_CLOCK_CAST (clock);
770
771   GST_CAT_DEBUG (GST_CAT_CLOCK, "adding async entry %p", entry);
772
773   GST_OBJECT_LOCK (clock);
774   /* Start the clock async thread if needed */
775   if (G_UNLIKELY (!gst_system_clock_start_async (sysclock)))
776     goto thread_error;
777
778   if (G_UNLIKELY (GET_ENTRY_STATUS (entry) == GST_CLOCK_UNSCHEDULED))
779     goto was_unscheduled;
780
781   if (clock->entries)
782     head = clock->entries->data;
783   else
784     head = NULL;
785
786   /* need to take a ref */
787   gst_clock_id_ref ((GstClockID) entry);
788   /* insert the entry in sorted order */
789   clock->entries = g_list_insert_sorted (clock->entries, entry,
790       gst_clock_id_compare_func);
791
792   /* only need to send the signal if the entry was added to the
793    * front, else the thread is just waiting for another entry and
794    * will get to this entry automatically. */
795   if (clock->entries->data == entry) {
796     GST_CAT_DEBUG (GST_CAT_CLOCK, "async entry added to head %p", head);
797     if (head == NULL) {
798       /* the list was empty before, signal the cond so that the async thread can
799        * start taking a look at the queue */
800       GST_CAT_DEBUG (GST_CAT_CLOCK, "first entry, sending signal");
801       GST_CLOCK_BROADCAST (clock);
802     } else {
803       GstClockReturn status;
804
805       status = GET_ENTRY_STATUS (head);
806       GST_CAT_DEBUG (GST_CAT_CLOCK, "head entry %p status %d", head, status);
807
808       if (status == GST_CLOCK_BUSY) {
809         GST_CAT_DEBUG (GST_CAT_CLOCK, "head entry is busy");
810         /* the async thread was waiting for an entry, unlock the wait so that it
811          * looks at the new head entry instead, we only need to do this once */
812         if (!sysclock->priv->async_wakeup) {
813           GST_CAT_DEBUG (GST_CAT_CLOCK, "wakeup async thread");
814           sysclock->priv->async_wakeup = TRUE;
815           gst_system_clock_add_wakeup (sysclock);
816         }
817       }
818     }
819   }
820   GST_OBJECT_UNLOCK (clock);
821
822   return GST_CLOCK_OK;
823
824   /* ERRORS */
825 thread_error:
826   {
827     /* Could not start the async clock thread */
828     GST_OBJECT_UNLOCK (clock);
829     return GST_CLOCK_ERROR;
830   }
831 was_unscheduled:
832   {
833     GST_OBJECT_UNLOCK (clock);
834     return GST_CLOCK_UNSCHEDULED;
835   }
836 }
837
838 /* unschedule an entry. This will set the state of the entry to GST_CLOCK_UNSCHEDULED
839  * and will signal any thread waiting for entries to recheck their entry.
840  * We cannot really decide if the signal is needed or not because the entry
841  * could be waited on in async or sync mode.
842  *
843  * MT safe.
844  */
845 static void
846 gst_system_clock_id_unschedule (GstClock * clock, GstClockEntry * entry)
847 {
848   GstSystemClock *sysclock;
849   GstClockReturn status;
850
851   sysclock = GST_SYSTEM_CLOCK_CAST (clock);
852
853   GST_CAT_DEBUG (GST_CAT_CLOCK, "unscheduling entry %p", entry);
854
855   GST_OBJECT_LOCK (clock);
856   /* change the entry status to unscheduled */
857   do {
858     status = GET_ENTRY_STATUS (entry);
859   } while (G_UNLIKELY (!CAS_ENTRY_STATUS (entry, status,
860               GST_CLOCK_UNSCHEDULED)));
861
862   if (G_LIKELY (status == GST_CLOCK_BUSY)) {
863     /* the entry was being busy, wake up all entries so that they recheck their
864      * status. We cannot wake up just one entry because allocating such a
865      * datastructure for each entry would be too heavy and unlocking an entry
866      * is usually done when shutting down or some other exceptional case. */
867     GST_CAT_DEBUG (GST_CAT_CLOCK, "entry was BUSY, doing wakeup");
868     if (!entry->unscheduled && !entry->woken_up) {
869       gst_system_clock_add_wakeup (sysclock);
870       entry->woken_up = TRUE;
871     }
872   }
873   GST_OBJECT_UNLOCK (clock);
874 }