Revise algorithm used by LightLock_Lock/Unlock to fix potential issues
This commit is contained in:
parent
9b57720cee
commit
58b0b9db4d
@ -32,9 +32,26 @@ _begin:
|
|||||||
val = __ldrex(lock);
|
val = __ldrex(lock);
|
||||||
if (val < 0)
|
if (val < 0)
|
||||||
{
|
{
|
||||||
|
// Add ourselves to the list of threads blocked on this lock
|
||||||
|
if (__strex(lock, val-1))
|
||||||
|
goto _begin; // strex failed, try to lock again
|
||||||
|
|
||||||
|
_wait:
|
||||||
|
// Wait for a thread to wake us up
|
||||||
|
svcArbitrateAddress(arbiter, (u32)lock, ARBITRATION_WAIT_IF_LESS_THAN, 0, 0);
|
||||||
|
|
||||||
|
// Try to lock again
|
||||||
|
do
|
||||||
|
{
|
||||||
|
val = __ldrex(lock);
|
||||||
|
if (val < 0)
|
||||||
|
{
|
||||||
|
// Lock is still locked - keep waiting
|
||||||
__clrex();
|
__clrex();
|
||||||
svcArbitrateAddress(arbiter, (u32)lock, ARBITRATION_DECREMENT_AND_WAIT_IF_LESS_THAN, 0, 0);
|
goto _wait;
|
||||||
goto _begin; // Try locking again
|
}
|
||||||
|
} while (__strex(lock, -(val-1)));
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
} while (__strex(lock, -val));
|
} while (__strex(lock, -val));
|
||||||
}
|
}
|
||||||
@ -60,14 +77,10 @@ void LightLock_Unlock(LightLock* lock)
|
|||||||
do
|
do
|
||||||
val = -__ldrex(lock);
|
val = -__ldrex(lock);
|
||||||
while (__strex(lock, val));
|
while (__strex(lock, val));
|
||||||
|
|
||||||
if (val > 1)
|
if (val > 1)
|
||||||
{
|
|
||||||
// Wake up exactly one thread
|
// Wake up exactly one thread
|
||||||
do
|
|
||||||
val = __ldrex(lock);
|
|
||||||
while (__strex(lock, val >= 0 ? (val-1) : (val+1)));
|
|
||||||
svcArbitrateAddress(arbiter, (u32)lock, ARBITRATION_SIGNAL, 1, 0);
|
svcArbitrateAddress(arbiter, (u32)lock, ARBITRATION_SIGNAL, 1, 0);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void RecursiveLock_Init(RecursiveLock* lock)
|
void RecursiveLock_Init(RecursiveLock* lock)
|
||||||
|
Loading…
Reference in New Issue
Block a user