diff --git a/lib/locks/bakery/bakery_lock_normal.c b/lib/locks/bakery/bakery_lock_normal.c index efc1b57e5..5a2fb0717 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);