summaryrefslogtreecommitdiff
path: root/common/hooks.c
diff options
context:
space:
mode:
authorRandall Spangler <rspangler@chromium.org>2013-03-18 14:09:03 -0700
committerChromeBot <chrome-bot@google.com>2013-03-19 10:31:10 -0700
commitc196c66432ea9d74a84602f4a49c4fd43de1ddd5 (patch)
treeb582554168921b2e15fcb5a69380c748d9dfa516 /common/hooks.c
parentf2df09d60259eb6abe00899925a64f5131dc2b10 (diff)
downloadchrome-ec-c196c66432ea9d74a84602f4a49c4fd43de1ddd5.tar.gz
Call AC change hook from the hook task
Using code like this, modules which service interrupts and notify hooks will no longer need to have their own tasks to call hook_notify() from. They can share the hook task as long as they don't mind the notification possibly being deferred. BUG=chrome-os-partner:18256 BRANCH=none TEST=add AC power, UI shows charging indicator; remove AC, indicator goes away Change-Id: I1bc32d21b2202c3242d39e0fc533198cd5bb9c66 Signed-off-by: Randall Spangler <rspangler@chromium.org> Reviewed-on: https://gerrit.chromium.org/gerrit/45780
Diffstat (limited to 'common/hooks.c')
-rw-r--r--common/hooks.c45
1 files changed, 40 insertions, 5 deletions
diff --git a/common/hooks.c b/common/hooks.c
index a17cf1ade1..4704992de0 100644
--- a/common/hooks.c
+++ b/common/hooks.c
@@ -1,10 +1,12 @@
-/* Copyright (c) 2012 The Chromium OS Authors. All rights reserved.
+/* Copyright (c) 2013 The Chromium OS Authors. All rights reserved.
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
/* System hooks for Chrome EC */
+#include "atomic.h"
+#include "console.h"
#include "hooks.h"
#include "link_defs.h"
#include "timer.h"
@@ -34,7 +36,12 @@ static const struct hook_ptrs hook_list[] = {
{__hooks_second, __hooks_second_end},
};
-void hook_notify(enum hook_type type)
+static uint32_t pending_hooks;
+
+/**
+ * Actual notification function
+ */
+static void notify(enum hook_type type)
{
const struct hook_data *start, *end, *p;
int count, called = 0;
@@ -63,18 +70,46 @@ void hook_notify(enum hook_type type)
}
}
+void hook_notify(enum hook_type type)
+{
+ if (type == HOOK_AC_CHANGE) {
+ /* Store deferred hook and wake task */
+ atomic_or(&pending_hooks, 1 << type);
+ task_wake(TASK_ID_TICK);
+ } else {
+ /* Notify now */
+ notify(type);
+ }
+}
+
void hook_task(void)
{
- /* Per-second hook will be called first time through the loop */
+ /* Periodic hooks will be called first time through the loop */
static uint64_t last_second = -SECOND;
+ static uint64_t last_tick = -HOOK_TICK_INTERVAL;
while (1) {
uint64_t t = get_time().val;
+ uint32_t pending = atomic_read_clear(&pending_hooks);
+ int i;
+
+ /* Call pending hooks, if any */
+ for (i = 0; pending && i < 32; i++) {
+ const uint32_t mask = 1 << i;
+
+ if (pending & mask) {
+ notify(i);
+ pending ^= mask;
+ }
+ }
- hook_notify(HOOK_TICK);
+ if (t - last_tick >= HOOK_TICK_INTERVAL) {
+ notify(HOOK_TICK);
+ last_tick = t;
+ }
if (t - last_second >= SECOND) {
- hook_notify(HOOK_SECOND);
+ notify(HOOK_SECOND);
last_second = t;
}