diff options
author | Shaun Ruffell <sruffell@digium.com> | 2009-10-29 18:26:16 +0000 |
---|---|---|
committer | Shaun Ruffell <sruffell@digium.com> | 2009-10-29 18:26:16 +0000 |
commit | e0591febc6055ed137f3915625c05ccc686fde27 (patch) | |
tree | bdbf3fb259c0dba748f4dc3032ea28c76966ec9b /drivers/dahdi | |
parent | cf2444d2836820acb240f10f5c93b4dec2b68299 (diff) |
dahdi-base: Do not allow jumps in system time to lock up the system w/core_timer
Since dahdi coretimer 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 the core timer attempts to catch up. This change prevents soft lock
ups under these conditions. This is brings the dahdi_dummy changes in r6933
into dahdi-base.
(related to issue #15647)
git-svn-id: http://svn.asterisk.org/svn/dahdi/linux/trunk@7437 a0bf4364-ded3-4de4-8d8a-66a801d63aff
Diffstat (limited to 'drivers/dahdi')
-rw-r--r-- | drivers/dahdi/dahdi-base.c | 18 |
1 files changed, 18 insertions, 0 deletions
diff --git a/drivers/dahdi/dahdi-base.c b/drivers/dahdi/dahdi-base.c index 511f9c1..2c6fc0d 100644 --- a/drivers/dahdi/dahdi-base.c +++ b/drivers/dahdi/dahdi-base.c @@ -8144,6 +8144,7 @@ static void coretimer_func(unsigned long param) const unsigned long MAX_INTERVAL = 100000L; const unsigned long FOURMS_INTERVAL = HZ/250; const unsigned long ONESEC_INTERVAL = HZ; + const unsigned long MS_LIMIT = 3000; now = current_kernel_time(); @@ -8158,6 +8159,23 @@ static void coretimer_func(unsigned long param) mod_timer(&core_timer.timer, jiffies + FOURMS_INTERVAL); ms_since_start = core_diff_ms(&core_timer.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 - atomic_read(&core_timer.count)) > MS_LIMIT)) { + if (printk_ratelimit()) + module_printk(KERN_INFO, "Detected time shift.\n"); + atomic_set(&core_timer.count, 0); + atomic_set(&core_timer.last_count, 0); + core_timer.start_interval = now; + return; + } + while (ms_since_start > atomic_read(&core_timer.count)) process_masterspan(); |