diff options
Diffstat (limited to 'hifi/xaf/hifi-dpf/core/util/mutex.c')
-rw-r--r-- | hifi/xaf/hifi-dpf/core/util/mutex.c | 156 |
1 files changed, 156 insertions, 0 deletions
diff --git a/hifi/xaf/hifi-dpf/core/util/mutex.c b/hifi/xaf/hifi-dpf/core/util/mutex.c new file mode 100644 index 00000000..d62a6a17 --- /dev/null +++ b/hifi/xaf/hifi-dpf/core/util/mutex.c @@ -0,0 +1,156 @@ +/******************************************************************************* +* Copyright (C) 2018 Cadence Design Systems, Inc. +* +* Permission is hereby granted, free of charge, to any person obtaining +* a copy of this software and associated documentation files (the +* "Software"), to use this Software with Cadence processor cores only and +* not with any other processors and platforms, subject to +* the following conditions: +* +* The above copyright notice and this permission notice shall be included +* in all copies or substantial portions of the Software. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +******************************************************************************/ + +/******************************************************************************* + * mutex.c + * + * Implementation of non-robust Szymanski linear-waiting algorithm. Types of + * failures tolerated by Szymanski's "robust" algorithm are not specific for + * Xtensa DSP cluster and therefore more lightweight version of the algorithm + * is used. FIFO servicing property is of low importance, and faster/smaller + * version with linear-wait property is preferable. + ******************************************************************************/ + +#include "xf.h" + +/******************************************************************************* + * Local constants definitions + ******************************************************************************/ + +/* ...communication variables */ +#define __M_A (1 << 0) +#define __M_W (1 << 1) +#define __M_S (1 << 2) + +/* ...process states (updated atomically) */ +#define M_PASSIVE (0) +#define M_ENTRY (__M_A) +#define M_INSIDE (__M_W) +#define M_TRANSIENT (__M_S | __M_W) +#define M_EXIT (__M_S) + +/* ...total number of cores */ +#define M_N XF_CFG_CORES_NUM + +/* ...do not compile the code if there is just a single core */ +#if M_N > 1 +/******************************************************************************* + * Entry points + ******************************************************************************/ + +void mutex_lock(u32 i) +{ + u32 j; + + /* ...p1: i-th core goes into "entry" state (aws = true,false,false) */ + MUTEX_SHARED_WRITE(i, M_ENTRY); + + /* ...p2: wait all processes have sj=false (waiting room door is open) */ + for (j = 0; j < M_N; j++) + { + /* ...wait until sj = false */ + while (MUTEX_SHARED_READ(j) & __M_S) (void) 0; + } + + /* ...p3: i-th core enters "inside" state (aws = false,true,false) */ + MUTEX_SHARED_WRITE(i, M_INSIDE); + +p4: + /* ...p4: wait in "inside" state */ + for (j = 0; j < M_N; j++) + { + /* ...p5: check if any of the cores appears is in "entry" state (aj=true) */ + if (MUTEX_SHARED_READ(j) & __M_A) + { + /* ...p5: found core in "entry" state (j < n); wait until it enters waiting room */ + goto p7; + } + } + + /* ...p6: j == n; enter into "transient" state (ai=false, wi=true, si=true) */ + MUTEX_SHARED_WRITE(i, M_TRANSIENT); + + /* ...p6.1: check for any core appearing in "entry" room */ + for (j = 0; j < M_N; j++) + { + if (MUTEX_SHARED_READ(j) & __M_A) + { + /* ...p6.2: found core in "entry" state (j < n) */ + MUTEX_SHARED_WRITE(i, M_INSIDE); + + /* ...back of to the "inside" state */ + goto p7; + } + } + + /* ...p6.3: no cores in "entry" room (j == n); go to "exit" state (ai=false, wi=false, si=true) */ + MUTEX_SHARED_WRITE(i, M_EXIT); + + /* ...p6.4: allow all cores to leave "transient" state (i.e. switch to "exit") */ + for (j = 0; j < M_N; j++) + { + while (MUTEX_SHARED_READ(j) & __M_W) (void) 0; + } + + goto p9; + +p7: + /* ...j < n condition is met; find any cores in "inside" state (wj = true, sj = false) */ + for (j = 0; j < M_N; j++) + { + /* ...check if the core is in "exit" state */ + if (MUTEX_SHARED_READ(j) == M_EXIT) + { + /* ...p8.1: different core is a leader; go to "exit" state (ai=false, wi=false, si=true) */ + MUTEX_SHARED_WRITE(i, M_EXIT); + + goto p9; + } + } + + /* ...wait in "inside" state while all transients settle */ + goto p4; + +p9: + /* ...p9: i-th core is in "exit" state; enter critical section in accordance with numbering */ + for (j = 0; j < i; j++) + { + /* ...wait until core with lower number in "inside"/"transient"/"exit" states leaves */ + while (MUTEX_SHARED_READ(j) & (__M_W | __M_S)) (void) 0; + } + + /* ...critical section entered */ +} + +/******************************************************************************* + * mutex_unlock + * + * Release multi-core mutex + ******************************************************************************/ + +void mutex_unlock(u32 i) +{ + /* ...enter into "passive" state (ai=false, wi=false, si=false) */ + MUTEX_SHARED_WRITE(i, M_PASSIVE); +} + +#endif /* M_N > 1 */ |