[vlc-commits] commit: vlc_timer_schedule: fix resetting the timer from itself ( =?UTF-8?Q?R=C3=A9mi=20Denis=2DCourmont=20?=)

git at videolan.org git at videolan.org
Wed Nov 24 18:02:58 CET 2010


vlc | branch: master | Rémi Denis-Courmont <remi at remlab.net> | Wed Nov 24 19:01:28 2010 +0200| [66c47c31f0f81448e55100170822fae29e4834ac] | committer: Rémi Denis-Courmont 

vlc_timer_schedule: fix resetting the timer from itself

This also fixes error handling: if the thread cannot be created, we do
fail cleanly.

> http://git.videolan.org/gitweb.cgi/vlc.git/?a=commit;h=66c47c31f0f81448e55100170822fae29e4834ac
---

 src/misc/pthread.c |   68 +++++++++++++++++++++++++++++-----------------------
 1 files changed, 38 insertions(+), 30 deletions(-)

diff --git a/src/misc/pthread.c b/src/misc/pthread.c
index 7603b24..88691c6 100644
--- a/src/misc/pthread.c
+++ b/src/misc/pthread.c
@@ -800,6 +800,7 @@ void vlc_control_cancel (int cmd, ...)
 struct vlc_timer
 {
     vlc_thread_t thread;
+    vlc_cond_t   reschedule;
     vlc_mutex_t  lock;
     void       (*func) (void *);
     void        *data;
@@ -810,37 +811,43 @@ struct vlc_timer
 static void *vlc_timer_thread (void *data)
 {
     struct vlc_timer *timer = data;
-    mtime_t value, interval;
 
     vlc_mutex_lock (&timer->lock);
-    value = timer->value;
-    interval = timer->interval;
-    vlc_mutex_unlock (&timer->lock);
+    mutex_cleanup_push (&timer->lock);
 
     for (;;)
     {
-        mwait (value);
+        while (timer->value == 0)
+            vlc_cond_wait (&timer->reschedule, &timer->lock);
+
+        if (vlc_cond_timedwait (&timer->reschedule, &timer->lock,
+                                timer->value) == 0)
+            continue;
+        vlc_mutex_unlock (&timer->lock);
 
         int canc = vlc_savecancel ();
         timer->func (timer->data);
         vlc_restorecancel (canc);
 
-        if (interval == 0)
-            return NULL;
-
         mtime_t now = mdate ();
-        unsigned misses = (now - value) / interval;
+        unsigned misses;
+
+        vlc_mutex_lock (&timer->lock);
+        misses = (now - timer->value) / timer->interval;
+        timer->value += timer->interval;
         /* Try to compensate for one miss (mwait() will return immediately)
          * but no more. Otherwise, we might busy loop, after extended periods
          * without scheduling (suspend, SIGSTOP, RT preemption, ...). */
         if (misses > 1)
         {
             misses--;
+            timer->value += misses * timer->interval;
             vlc_atomic_add (&timer->overruns, misses);
-            value += misses * interval;
         }
-        value += interval;
     }
+
+    vlc_cleanup_pop ();
+    assert (0);
 }
 
 /**
@@ -861,12 +868,23 @@ int vlc_timer_create (vlc_timer_t *id, void (*func) (void *), void *data)
     if (unlikely(timer == NULL))
         return ENOMEM;
     vlc_mutex_init (&timer->lock);
+    vlc_cond_init (&timer->reschedule);
     assert (func);
     timer->func = func;
     timer->data = data;
     timer->value = 0;
     timer->interval = 0;
     vlc_atomic_set(&timer->overruns, 0);
+
+    if (vlc_clone (&timer->thread, vlc_timer_thread, timer,
+                   VLC_THREAD_PRIORITY_INPUT))
+    {
+        vlc_cond_destroy (&timer->reschedule);
+        vlc_mutex_destroy (&timer->lock);
+        free (timer);
+        return ENOMEM;
+    }
+
     *id = timer;
     return 0;
 }
@@ -882,7 +900,9 @@ int vlc_timer_create (vlc_timer_t *id, void (*func) (void *), void *data)
  */
 void vlc_timer_destroy (vlc_timer_t timer)
 {
-    vlc_timer_schedule (timer, false, 0, 0);
+    vlc_cancel (timer->thread);
+    vlc_join (timer->thread, NULL);
+    vlc_cond_destroy (&timer->reschedule);
     vlc_mutex_destroy (&timer->lock);
     free (timer);
 }
@@ -907,25 +927,13 @@ void vlc_timer_destroy (vlc_timer_t timer)
 void vlc_timer_schedule (vlc_timer_t timer, bool absolute,
                          mtime_t value, mtime_t interval)
 {
-    vlc_mutex_lock (&timer->lock);
-    while (timer->value)
-    {
-        vlc_thread_t thread = timer->thread;
+    if (!absolute && value != 0)
+        value += mdate();
 
-        timer->value = 0;
-        vlc_mutex_unlock (&timer->lock);
-        vlc_cancel (thread);
-        /* cannot keep the lock during vlc_join X( */
-        vlc_join (thread, NULL);
-        vlc_mutex_lock (&timer->lock);
-    }
-    if ((value != 0)
-     && (vlc_clone (&timer->thread, vlc_timer_thread, timer,
-                    VLC_THREAD_PRIORITY_INPUT) == 0))
-    {
-        timer->value = (absolute ? 0 : mdate ()) + value;
-        timer->interval = interval;
-    }
+    vlc_mutex_lock (&timer->lock);
+    timer->value = value;
+    timer->interval = interval;
+    vlc_cond_signal (&timer->reschedule);
     vlc_mutex_unlock (&timer->lock);
 }
 



More information about the vlc-commits mailing list