diff options
author | Alec Berg <alecaberg@chromium.org> | 2015-02-19 15:03:50 -0800 |
---|---|---|
committer | ChromeOS Commit Bot <chromeos-commit-bot@chromium.org> | 2015-02-21 00:49:32 +0000 |
commit | eb775b49b83e039a92fd67a9b8d6049d0f0cc70d (patch) | |
tree | 717168c65ce3360e98cb185709d361e6ca6ffd4f | |
parent | 44adcf4dd75c553b3b11720693a3f7f07e26d9d4 (diff) | |
download | chrome-ec-eb775b49b83e039a92fd67a9b8d6049d0f0cc70d.tar.gz |
timer: usleep: Use HW clock to detect elapsed sleep time
If a non-timer task event is received while in usleep, we will again
attempt to sleep for the entire duration. This can cause an infinite
sleep in cases where a periodic task event occurs. Fix this by checking
the HW clock for our elapsed duration.
BUG=chrome-os-partner:36864
TEST=Manual on Samus. Verify that we don't get stuck in usleep during
VCORE_PGOOD interrupt storm.
BRANCH=Samus
Change-Id: Ie3ab8ce3c22822095845a3d9a6f33bd4b1273c6e
Signed-off-by: Shawn Nematbakhsh <shawnn@chromium.org>
Reviewed-on: https://chromium-review.googlesource.com/251311
Reviewed-by: Randall Spangler <rspangler@chromium.org>
Reviewed-by: Alec Berg <alecaberg@chromium.org>
Reviewed-by: Vincent Palatin <vpalatin@chromium.org>
-rw-r--r-- | common/timer.c | 10 |
1 files changed, 9 insertions, 1 deletions
diff --git a/common/timer.c b/common/timer.c index 0764fb7e1b..42c08a8de5 100644 --- a/common/timer.c +++ b/common/timer.c @@ -143,9 +143,16 @@ void timer_cancel(task_id_t tskid) */ } +/* + * For us < (2^31 - task scheduling latency)(~ 2147 sec), this function will + * sleep for at least us, and no more than 2*us. As us approaches 2^32-1, the + * probability of delay longer than 2*us (and possibly infinite delay) + * increases. + */ void usleep(unsigned us) { uint32_t evt = 0; + uint32_t t0 = __hw_clock_source_read(); /* If task scheduling has not started, just delay */ if (!task_start_called()) { @@ -156,7 +163,8 @@ void usleep(unsigned us) ASSERT(us); do { evt |= task_wait_event(us); - } while (!(evt & TASK_EVENT_TIMER)); + } while (!(evt & TASK_EVENT_TIMER) && + ((__hw_clock_source_read() - t0) < us)); /* Re-queue other events which happened in the meanwhile */ if (evt) |