summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlec Berg <alecaberg@chromium.org>2015-02-19 15:03:50 -0800
committerChromeOS Commit Bot <chromeos-commit-bot@chromium.org>2015-02-21 00:49:32 +0000
commiteb775b49b83e039a92fd67a9b8d6049d0f0cc70d (patch)
tree717168c65ce3360e98cb185709d361e6ca6ffd4f
parent44adcf4dd75c553b3b11720693a3f7f07e26d9d4 (diff)
downloadchrome-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.c10
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)