diff options
author | tim <tim2.lin@ite.corp-partner.google.com> | 2020-09-29 17:55:22 +0800 |
---|---|---|
committer | Commit Bot <commit-bot@chromium.org> | 2020-10-27 04:54:55 +0000 |
commit | 2f686b6904bbaa96f42ea24c1c241c68f9d2f548 (patch) | |
tree | 11d5fc11eba387e645760a4fee757edc7c8726ec | |
parent | 3fc173abab844b8a4c9238ecf23527d667e0126a (diff) | |
download | chrome-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.c | 15 |
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); |