summaryrefslogtreecommitdiff
path: root/drivers/dahdi/dahdi_dummy.c
diff options
context:
space:
mode:
authorShaun Ruffell <sruffell@digium.com>2009-08-04 16:22:39 +0000
committerShaun Ruffell <sruffell@digium.com>2009-08-04 16:22:39 +0000
commit32fea6eb04cecfcce4859233394d57dc6042ba34 (patch)
tree63b48af3dd58668c0b9be245419edaca8fa9f5ab /drivers/dahdi/dahdi_dummy.c
parentdfb127aec9eb12562639ce650bdea37354487390 (diff)
dahdi_dummy: Do not allow jumps in system time to lock up the system.
Since dahdi_dummy uses the number of milliseconds that has actually passed to determine how many times to call dahdi_receive, it is possible that if the system time shifts after dahdi is started, that the system can appear to lock up while dahdi_dummy attempts to catch up. This change prevents soft lock ups under these conditions. (closes issue #15647) Reported by: missnebun git-svn-id: http://svn.asterisk.org/svn/dahdi/linux/trunk@6933 a0bf4364-ded3-4de4-8d8a-66a801d63aff
Diffstat (limited to 'drivers/dahdi/dahdi_dummy.c')
-rw-r--r--drivers/dahdi/dahdi_dummy.c19
1 files changed, 19 insertions, 0 deletions
diff --git a/drivers/dahdi/dahdi_dummy.c b/drivers/dahdi/dahdi_dummy.c
index d0297c3..da6fa44 100644
--- a/drivers/dahdi/dahdi_dummy.c
+++ b/drivers/dahdi/dahdi_dummy.c
@@ -161,12 +161,31 @@ static void dahdi_dummy_timer(unsigned long param)
unsigned long ms_since_start;
struct timespec now;
const unsigned long MAX_INTERVAL = 100000L;
+ const unsigned long MS_LIMIT = 3000;
if (!atomic_read(&shutdown))
mod_timer(&timer, jiffies + JIFFIES_INTERVAL);
now = current_kernel_time();
ms_since_start = timespec_diff_ms(&ztd->start_interval, &now);
+
+ /*
+ * If the system time has changed, it is possible for us to be far
+ * behind. If we are more than MS_LIMIT milliseconds behind, just
+ * reset our time base and continue so that we do not hang the system
+ * here.
+ *
+ */
+ if (unlikely((ms_since_start - ztd->calls_since_start) > MS_LIMIT)) {
+ if (printk_ratelimit()) {
+ printk(KERN_INFO
+ "dahdi_dummy: Detected time shift.\n");
+ }
+ ztd->calls_since_start = 0;
+ ztd->start_interval = now;
+ return;
+ }
+
while (ms_since_start > ztd->calls_since_start) {
ztd->calls_since_start++;
dahdi_receive(&ztd->span);