summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authordavidcunado-arm <david.cunado@arm.com>2016-11-30 17:38:41 +0000
committerGitHub <noreply@github.com>2016-11-30 17:38:41 +0000
commitc59428b1502f37c9b2f551613da1b491c4226d10 (patch)
tree97b5271c9d5662fb9691889b774e76cfa1ec288a
parent805972feada77f53344dfb2ef3491e8c1f0dd638 (diff)
parent95c1255967b46efa3e7add1eafd9e35862bfc677 (diff)
Merge pull request #761 from soby-mathew/sm/bakery_lock_fixes
Fix normal memory bakery lock implementation
-rw-r--r--lib/locks/bakery/bakery_lock_normal.c29
1 files changed, 21 insertions, 8 deletions
diff --git a/lib/locks/bakery/bakery_lock_normal.c b/lib/locks/bakery/bakery_lock_normal.c
index efc1b57e..5a2fb071 100644
--- a/lib/locks/bakery/bakery_lock_normal.c
+++ b/lib/locks/bakery/bakery_lock_normal.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2015-2016, ARM Limited and Contributors. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
@@ -90,6 +90,22 @@ extern void *__PERCPU_BAKERY_LOCK_SIZE__;
#define read_cache_op(addr, cached) if (cached) \
dccivac((uintptr_t)addr)
+/* Helper function to check if the lock is acquired */
+static inline int is_lock_acquired(const bakery_info_t *my_bakery_info,
+ int is_cached)
+{
+ /*
+ * Even though lock data is updated only by the owning cpu and
+ * appropriate cache maintenance operations are performed,
+ * if the previous update was done when the cpu was not participating
+ * in coherency, then there is a chance that cache maintenance
+ * operations were not propagated to all the caches in the system.
+ * Hence do a `read_cache_op()` prior to read.
+ */
+ read_cache_op(my_bakery_info, is_cached);
+ return !!(bakery_ticket_number(my_bakery_info->lock_data));
+}
+
static unsigned int bakery_get_ticket(bakery_lock_t *lock,
unsigned int me, int is_cached)
{
@@ -104,12 +120,8 @@ static unsigned int bakery_get_ticket(bakery_lock_t *lock,
my_bakery_info = get_bakery_info(me, lock);
assert(my_bakery_info);
- /*
- * Prevent recursive acquisition.
- * Since lock data is written to and cleaned by the owning cpu, it
- * doesn't require any cache operations prior to reading the lock data.
- */
- assert(!bakery_ticket_number(my_bakery_info->lock_data));
+ /* Prevent recursive acquisition.*/
+ assert(!is_lock_acquired(my_bakery_info, is_cached));
/*
* Tell other contenders that we are through the bakery doorway i.e.
@@ -222,7 +234,8 @@ void bakery_lock_release(bakery_lock_t *lock)
unsigned int is_cached = read_sctlr_el3() & SCTLR_C_BIT;
my_bakery_info = get_bakery_info(plat_my_core_pos(), lock);
- assert(bakery_ticket_number(my_bakery_info->lock_data));
+
+ assert(is_lock_acquired(my_bakery_info, is_cached));
my_bakery_info->lock_data = 0;
write_cache_op(my_bakery_info, is_cached);