]> git.ipfire.org Git - thirdparty/asterisk.git/commitdiff
Merged revisions 294277 via svnmerge from
authorJeff Peeler <jpeeler@digium.com>
Mon, 8 Nov 2010 21:59:45 +0000 (21:59 +0000)
committerJeff Peeler <jpeeler@digium.com>
Mon, 8 Nov 2010 21:59:45 +0000 (21:59 +0000)
https://origsvn.digium.com/svn/asterisk/branches/1.6.2

........
  r294277 | jpeeler | 2010-11-08 15:58:13 -0600 (Mon, 08 Nov 2010) | 16 lines

  Fix playback failure when using IAX with the timerfd module.

  To fix this issue the alert pipe will now be used when the timerfd module is
  in use. There appeared to be a race that was not solved by adding locking in the
  timerfd module, but needed to be there anyway. The race was between the timer
  being put in non-continuous mode in ast_read on the channel thread and the IAX
  frame scheduler queuing a frame which would enable continuous mode before the
  non-continuous mode event was read. This race for now is simply avoided.

  (closes issue #18110)
  Reported by: tpanton
  Tested by: tpanton

  I put tested by tpanton because it was tested on his hardware. Thanks for the
  remote access to debug this issue!
........

git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.8@294278 65c4cc65-6c06-0410-ace0-fbb531ad65f3

include/asterisk/timing.h
main/channel.c
main/timing.c
res/res_timing_timerfd.c

index 7973f365f2f42dcfc6ed5e4bf51368b5cbf2724b..3f4da48ef0e6032341df059da5d06d433f0cc9b6 100644 (file)
@@ -216,6 +216,16 @@ enum ast_timer_event ast_timer_get_event(const struct ast_timer *handle);
  */
 unsigned int ast_timer_get_max_rate(const struct ast_timer *handle);
 
+/*!
+ * \brief Get name of timer in use
+ *
+ * \param handle timer handle returned by timer_open()
+ *
+ * \return name of timer
+ * \since 1.6.2
+ */
+const char *ast_timer_get_name(const struct ast_timer *handle);
+
 #if defined(__cplusplus) || defined(c_plusplus)
 }
 #endif
index daf5b7a8e26b8fe20f35fd70e86f9382d119b85e..7c1e998af14cca363cfdaf5663b5ca58c2782fe2 100644 (file)
@@ -1129,7 +1129,9 @@ __ast_channel_alloc_ap(int needqueue, int state, const char *cid_num, const char
        }
 
        if ((tmp->timer = ast_timer_open())) {
-               needqueue = 0;
+               if (strcmp(ast_timer_get_name(tmp->timer), "timerfd")) {
+                       needqueue = 0;
+               }
                tmp->timingfd = ast_timer_fd(tmp->timer);
        }
 
index d15024b32e638ffedca58df9321e1365e187a22f..23d3cf8eef817993992080df5255a763ccaffabc 100644 (file)
@@ -205,6 +205,11 @@ unsigned int ast_timer_get_max_rate(const struct ast_timer *handle)
        return res;
 }
 
+const char *ast_timer_get_name(const struct ast_timer *handle)
+{
+       return handle->holder->iface->name;
+}
+
 static char *timing_test(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 {
        struct ast_timer *timer;
index bffa007de2b61fda6af92e94d6028a08d24365e0..c9922aabef6ef5d9ea6fe8d1e159b8a4a8fd41e3 100644 (file)
@@ -140,6 +140,7 @@ static int timerfd_timer_set_rate(int handle, unsigned int rate)
                ast_log(LOG_ERROR, "Couldn't find timer with handle %d\n", handle);
                return -1;
        }
+       ao2_lock(our_timer);
 
        our_timer->saved_timer.it_value.tv_sec = 0;
        our_timer->saved_timer.it_value.tv_nsec = rate ? (long) (1000000000 / rate) : 0L;
@@ -150,6 +151,7 @@ static int timerfd_timer_set_rate(int handle, unsigned int rate)
                res = timerfd_settime(handle, 0, &our_timer->saved_timer, NULL);
        }
 
+       ao2_unlock(our_timer);
        ao2_ref(our_timer, -1);
 
        return res;
@@ -191,17 +193,20 @@ static int timerfd_timer_enable_continuous(int handle)
                ast_log(LOG_ERROR, "Couldn't find timer with handle %d\n", handle);
                return -1;
        }
+       ao2_lock(our_timer);
 
        if (our_timer->is_continuous) {
                /*It's already in continous mode, no need to do
                 * anything further
                 */
+               ao2_unlock(our_timer);
                ao2_ref(our_timer, -1);
                return 0;
        }
 
        res = timerfd_settime(handle, 0, &continuous_timer, &our_timer->saved_timer);
        our_timer->is_continuous = 1;
+       ao2_unlock(our_timer);
        ao2_ref(our_timer, -1);
        return res;
 }
@@ -217,6 +222,7 @@ static int timerfd_timer_disable_continuous(int handle)
                ast_log(LOG_ERROR, "Couldn't find timer with handle %d\n", handle);
                return -1;
        }
+       ao2_lock(our_timer);
 
        if(!our_timer->is_continuous) {
                /* No reason to do anything if we're not
@@ -229,6 +235,7 @@ static int timerfd_timer_disable_continuous(int handle)
        res = timerfd_settime(handle, 0, &our_timer->saved_timer, NULL);
        our_timer->is_continuous = 0;
        memset(&our_timer->saved_timer, 0, sizeof(our_timer->saved_timer));
+       ao2_unlock(our_timer);
        ao2_ref(our_timer, -1);
        return res;
 }
@@ -244,6 +251,7 @@ static enum ast_timer_event timerfd_timer_get_event(int handle)
                ast_log(LOG_ERROR, "Couldn't find timer with handle %d\n", handle);
                return -1;
        }
+       ao2_lock(our_timer);
 
        if (our_timer->is_continuous) {
                res = AST_TIMING_EVENT_CONTINUOUS;
@@ -251,6 +259,7 @@ static enum ast_timer_event timerfd_timer_get_event(int handle)
                res = AST_TIMING_EVENT_EXPIRED;
        }
 
+       ao2_unlock(our_timer);
        ao2_ref(our_timer, -1);
        return res;
 }