summaryrefslogtreecommitdiff
path: root/src/cpu
diff options
context:
space:
mode:
authorBora Guvendik <bora.guvendik@intel.com>2017-01-04 16:51:31 -0800
committerMartin Roth <martinroth@google.com>2017-03-19 21:40:08 +0100
commit9b76f0b27bbdf4c214f1fe0fdbc81a153b5e9a95 (patch)
tree40a50da23d6872516629b50d3f9bdb30cfd34dde /src/cpu
parent4796c32ad60933bd8c23729684414121097b0445 (diff)
cpu/x86: add a barrier with timeout
In case something goes wrong on one of the cpus, add the ability to use a barrier with timeout so that other cpus don't wait forever. Remove static from barrier wait and release. BUG=chrome-os-partner:59875 BRANCH=reef TEST=None Change-Id: Iab6bd30ddf7632c7a5785b338798960c26016b24 Signed-off-by: Bora Guvendik <bora.guvendik@intel.com> Reviewed-on: https://review.coreboot.org/18107 Tested-by: build bot (Jenkins) Reviewed-by: Martin Roth <martinroth@google.com>
Diffstat (limited to 'src/cpu')
-rw-r--r--src/cpu/x86/mp_init.c27
1 files changed, 25 insertions, 2 deletions
diff --git a/src/cpu/x86/mp_init.c b/src/cpu/x86/mp_init.c
index 57a5648ad4..61f153ea3d 100644
--- a/src/cpu/x86/mp_init.c
+++ b/src/cpu/x86/mp_init.c
@@ -138,14 +138,37 @@ struct cpu_map {
/* Keep track of APIC and device structure for each CPU. */
static struct cpu_map cpus[CONFIG_MAX_CPUS];
-static inline void barrier_wait(atomic_t *b)
+inline void barrier_wait(atomic_t *b)
{
while (atomic_read(b) == 0)
asm ("pause");
mfence();
}
-static inline void release_barrier(atomic_t *b)
+/* Returns 1 if timeout occurs before barier is released.
+ * returns 0 if barrier is released before timeout. */
+int barrier_wait_timeout(atomic_t *b, uint32_t timeout_ms)
+{
+ int timeout = 0;
+ struct mono_time current, end;
+
+ timer_monotonic_get(&current);
+ end = current;
+ mono_time_add_msecs(&end, timeout_ms);
+
+ while ((atomic_read(b) == 0) && (!mono_time_after(&current, &end))) {
+ timer_monotonic_get(&current);
+ asm ("pause");
+ }
+ mfence();
+
+ if (mono_time_after(&current, &end))
+ timeout = 1;
+
+ return timeout;
+}
+
+inline void release_barrier(atomic_t *b)
{
mfence();
atomic_set(b, 1);