Skip to content

Commit

Permalink
FIXED: Race conditions in FIQ synchronization
Browse files Browse the repository at this point in the history
Affected using FIQ together with EnterCritical() or class CSpinLock.

Issue #87
Reported by @stephanedamo
  • Loading branch information
rsta2 committed Nov 8, 2018
1 parent 66909aa commit 81c910e
Show file tree
Hide file tree
Showing 4 changed files with 25 additions and 33 deletions.
3 changes: 3 additions & 0 deletions CREDITS
Expand Up @@ -46,3 +46,6 @@ USB HID class gamepad driver

@Matheus-Garbelini
Adding bootloader support and tools

Stephane Damo
Helping to fix FIQ synchronization issue
3 changes: 1 addition & 2 deletions include/circle/spinlock.h
Expand Up @@ -2,7 +2,7 @@
// spinlock.h
//
// Circle - A C++ bare metal environment for Raspberry Pi
// Copyright (C) 2015-2017 R. Stange <rsta2@o2online.de>
// Copyright (C) 2015-2018 R. Stange <rsta2@o2online.de>
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
Expand Down Expand Up @@ -43,7 +43,6 @@ class CSpinLock

private:
unsigned m_nTargetLevel;
u32 m_nCPSR[CORES];

u32 m_nLocked;

Expand Down
24 changes: 4 additions & 20 deletions lib/spinlock.cpp
Expand Up @@ -2,7 +2,7 @@
// spinlock.cpp
//
// Circle - A C++ bare metal environment for Raspberry Pi
// Copyright (C) 2015-2017 R. Stange <rsta2@o2online.de>
// Copyright (C) 2015-2018 R. Stange <rsta2@o2online.de>
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
Expand Down Expand Up @@ -44,18 +44,7 @@ void CSpinLock::Acquire (void)
{
if (m_nTargetLevel >= IRQ_LEVEL)
{
asm volatile
(
"mrs %0, cpsr\n"
"cpsid i\n"

: "=r" (m_nCPSR[CMultiCoreSupport::ThisCore ()])
);

if (m_nTargetLevel == FIQ_LEVEL)
{
DisableFIQs ();
}
EnterCritical (m_nTargetLevel);
}

if (s_bEnabled)
Expand Down Expand Up @@ -102,13 +91,8 @@ void CSpinLock::Release (void)

if (m_nTargetLevel >= IRQ_LEVEL)
{
asm volatile
(
"msr cpsr_c, %0\n"

: : "r" (m_nCPSR[CMultiCoreSupport::ThisCore ()])
);
};
LeaveCritical ();
}
}

void CSpinLock::Enable (void)
Expand Down
28 changes: 17 additions & 11 deletions lib/synchronize.cpp
Expand Up @@ -2,7 +2,7 @@
// synchronize.cpp
//
// Circle - A C++ bare metal environment for Raspberry Pi
// Copyright (C) 2014-2017 R. Stange <rsta2@o2online.de>
// Copyright (C) 2014-2018 R. Stange <rsta2@o2online.de>
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
Expand Down Expand Up @@ -61,15 +61,16 @@ void EnterCritical (unsigned nTargetLevel)
// if we are already on FIQ_LEVEL, we must not go back to IRQ_LEVEL here
assert (nTargetLevel == FIQ_LEVEL || !(nCPSR & 0x40));

DisableIRQs ();
if (nTargetLevel == FIQ_LEVEL)
{
DisableFIQs ();
}
asm volatile ("cpsid if"); // disable both IRQ and FIQ

assert (s_nCriticalLevel[nCore] < MAX_CRITICAL_LEVEL);
s_nCPSR[nCore][s_nCriticalLevel[nCore]++] = nCPSR;

if (nTargetLevel == IRQ_LEVEL)
{
EnableFIQs ();
}

DataMemBarrier ();
}

Expand All @@ -81,6 +82,8 @@ void LeaveCritical (void)

DataMemBarrier ();

DisableFIQs ();

assert (s_nCriticalLevel[nCore] > 0);
u32 nCPSR = s_nCPSR[nCore][--s_nCriticalLevel[nCore]];

Expand All @@ -102,22 +105,25 @@ void EnterCritical (unsigned nTargetLevel)
// if we are already on FIQ_LEVEL, we must not go back to IRQ_LEVEL here
assert (nTargetLevel == FIQ_LEVEL || !(nCPSR & 0x40));

DisableIRQs ();
if (nTargetLevel == FIQ_LEVEL)
{
DisableFIQs ();
}
asm volatile ("cpsid if"); // disable both IRQ and FIQ

assert (s_nCriticalLevel < MAX_CRITICAL_LEVEL);
s_nCPSR[s_nCriticalLevel++] = nCPSR;

if (nTargetLevel == IRQ_LEVEL)
{
EnableFIQs ();
}

DataMemBarrier ();
}

void LeaveCritical (void)
{
DataMemBarrier ();

DisableFIQs ();

assert (s_nCriticalLevel > 0);
u32 nCPSR = s_nCPSR[--s_nCriticalLevel];

Expand Down

0 comments on commit 81c910e

Please sign in to comment.