summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authortim <tim2.lin@ite.corp-partner.google.com>2020-09-29 17:55:22 +0800
committerCommit Bot <commit-bot@chromium.org>2020-10-27 04:54:55 +0000
commit2f686b6904bbaa96f42ea24c1c241c68f9d2f548 (patch)
tree11d5fc11eba387e645760a4fee757edc7c8726ec
parent3fc173abab844b8a4c9238ecf23527d667e0126a (diff)
downloadchrome-ec-2f686b6904bbaa96f42ea24c1c241c68f9d2f548.tar.gz
core/nds32: to avoid race condition
After the program to line 628(original program), we have determined that the local variable of waiter is 0 because a task is getting the mutex lock then clearing waiter to 0(line 608). If another task enters mutex lock at this time, mtx->waiters will be written to 1 and go to sleep waiting, but the local variable of waiter is still 0. This will cause latter task which cannot be woke up when previous task leaves the mutex unlock. BUG=none BRANCH=none TEST=create two tasks and respectively access mutex_lock and mutex_unlock. There would not happen that latter task cannot be woke up when previous task leaves the mutex unlock. Change-Id: I566a14c1120716af8e9ac99e183a989274a4e72e Signed-off-by: tim <tim2.lin@ite.corp-partner.google.com> Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/ec/+/2438084 Reviewed-by: Jett Rink <jettrink@chromium.org>
-rw-r--r--core/nds32/task.c15
1 files changed, 12 insertions, 3 deletions
diff --git a/core/nds32/task.c b/core/nds32/task.c
index 9c3d6357ac..209395e86a 100644
--- a/core/nds32/task.c
+++ b/core/nds32/task.c
@@ -631,9 +631,18 @@ void __ram_code mutex_unlock(struct mutex *mtx)
uint32_t waiters;
task_ *tsk = current_task;
- waiters = mtx->waiters;
- /* give back the lock */
- mtx->lock = 0;
+ /*
+ * we need to read to waiters after giving the lock back
+ * otherwise we might miss a waiter between the two calls.
+ *
+ * prevent compiler reordering
+ */
+ asm volatile(
+ /* give back the lock */
+ "movi %0, #0\n\t"
+ "lwi %1, [%2]\n\t"
+ : "=&r"(mtx->lock), "=&r"(waiters)
+ : "r"(&mtx->waiters));
while (waiters) {
task_id_t id = __fls(waiters);