Add light events
This commit is contained in:
parent
2f6a28f1e3
commit
bac12e19bb
@ -11,6 +11,13 @@ typedef _LOCK_T LightLock;
|
|||||||
/// A recursive lock.
|
/// A recursive lock.
|
||||||
typedef _LOCK_RECURSIVE_T RecursiveLock;
|
typedef _LOCK_RECURSIVE_T RecursiveLock;
|
||||||
|
|
||||||
|
/// A light event.
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
s32 state; ///< State of the event: -2=cleared sticky, -1=cleared oneshot, 0=signaled oneshot, 1=signaled sticky
|
||||||
|
LightLock lock; ///< Lock used for sticky timer operation
|
||||||
|
} LightEvent;
|
||||||
|
|
||||||
/// Performs a Data Synchronization Barrier operation.
|
/// Performs a Data Synchronization Barrier operation.
|
||||||
static inline void __dsb(void)
|
static inline void __dsb(void)
|
||||||
{
|
{
|
||||||
@ -114,3 +121,41 @@ int RecursiveLock_TryLock(RecursiveLock* lock);
|
|||||||
* @param lock Pointer to the lock.
|
* @param lock Pointer to the lock.
|
||||||
*/
|
*/
|
||||||
void RecursiveLock_Unlock(RecursiveLock* lock);
|
void RecursiveLock_Unlock(RecursiveLock* lock);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Initializes a light event.
|
||||||
|
* @param event Pointer to the event.
|
||||||
|
* @param reset_type Type of reset the event uses (RESET_ONESHOT/RESET_STICKY).
|
||||||
|
*/
|
||||||
|
void LightEvent_Init(LightEvent* event, ResetType reset_type);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Clears a light event.
|
||||||
|
* @param event Pointer to the event.
|
||||||
|
*/
|
||||||
|
void LightEvent_Clear(LightEvent* event);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Wakes up threads waiting on a sticky light event without signaling it. If the event had been signaled before, it is cleared instead.
|
||||||
|
* @param event Pointer to the event.
|
||||||
|
*/
|
||||||
|
void LightEvent_Pulse(LightEvent* event);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Signals a light event, waking up threads waiting on it.
|
||||||
|
* @param event Pointer to the event.
|
||||||
|
*/
|
||||||
|
void LightEvent_Signal(LightEvent* event);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Attempts to wait on a light event.
|
||||||
|
* @param event Pointer to the event.
|
||||||
|
* @return Non-zero if the event was signaled, zero otherwise.
|
||||||
|
*/
|
||||||
|
int LightEvent_TryWait(LightEvent* event);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Waits on a light event.
|
||||||
|
* @param event Pointer to the event.
|
||||||
|
*/
|
||||||
|
void LightEvent_Wait(LightEvent* event);
|
||||||
|
@ -127,3 +127,92 @@ void RecursiveLock_Unlock(RecursiveLock* lock)
|
|||||||
LightLock_Unlock(&lock->lock);
|
LightLock_Unlock(&lock->lock);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline void LightEvent_SetState(LightEvent* event, int state)
|
||||||
|
{
|
||||||
|
do
|
||||||
|
__ldrex(&event->state);
|
||||||
|
while (__strex(&event->state, state));
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int LightEvent_TryReset(LightEvent* event)
|
||||||
|
{
|
||||||
|
do
|
||||||
|
{
|
||||||
|
if (__ldrex(&event->state))
|
||||||
|
{
|
||||||
|
__clrex();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
} while (__strex(&event->state, -1));
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void LightEvent_Init(LightEvent* event, ResetType reset_type)
|
||||||
|
{
|
||||||
|
LightLock_Init(&event->lock);
|
||||||
|
LightEvent_SetState(event, reset_type == RESET_STICKY ? -2 : -1);
|
||||||
|
}
|
||||||
|
|
||||||
|
void LightEvent_Clear(LightEvent* event)
|
||||||
|
{
|
||||||
|
if (event->state == 1)
|
||||||
|
{
|
||||||
|
LightLock_Lock(&event->lock);
|
||||||
|
LightEvent_SetState(event, -2);
|
||||||
|
LightLock_Unlock(&event->lock);
|
||||||
|
} else if (event->state == 0)
|
||||||
|
LightEvent_SetState(event, -1);
|
||||||
|
}
|
||||||
|
|
||||||
|
void LightEvent_Pulse(LightEvent* event)
|
||||||
|
{
|
||||||
|
if (event->state == -2)
|
||||||
|
svcArbitrateAddress(arbiter, (u32)event, ARBITRATION_SIGNAL, -1, 0);
|
||||||
|
else if (event->state == -1)
|
||||||
|
svcArbitrateAddress(arbiter, (u32)event, ARBITRATION_SIGNAL, 1, 0);
|
||||||
|
else
|
||||||
|
LightEvent_Clear(event);
|
||||||
|
}
|
||||||
|
|
||||||
|
void LightEvent_Signal(LightEvent* event)
|
||||||
|
{
|
||||||
|
if (event->state == -1)
|
||||||
|
{
|
||||||
|
LightEvent_SetState(event, 0);
|
||||||
|
svcArbitrateAddress(arbiter, (u32)event, ARBITRATION_SIGNAL, 1, 0);
|
||||||
|
} else if (event->state == -2)
|
||||||
|
{
|
||||||
|
LightLock_Lock(&event->lock);
|
||||||
|
LightEvent_SetState(event, 1);
|
||||||
|
svcArbitrateAddress(arbiter, (u32)event, ARBITRATION_SIGNAL, -1, 0);
|
||||||
|
LightLock_Unlock(&event->lock);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int LightEvent_TryWait(LightEvent* event)
|
||||||
|
{
|
||||||
|
if (event->state == 1)
|
||||||
|
return 1;
|
||||||
|
return LightEvent_TryReset(event);
|
||||||
|
}
|
||||||
|
|
||||||
|
void LightEvent_Wait(LightEvent* event)
|
||||||
|
{
|
||||||
|
for (;;)
|
||||||
|
{
|
||||||
|
if (event->state == -2)
|
||||||
|
{
|
||||||
|
svcArbitrateAddress(arbiter, (u32)event, ARBITRATION_WAIT_IF_LESS_THAN, 0, 0);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (event->state != -1)
|
||||||
|
{
|
||||||
|
if (event->state == 1)
|
||||||
|
return;
|
||||||
|
if (event->state == 0 && LightEvent_TryReset(event))
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
svcArbitrateAddress(arbiter, (u32)event, ARBITRATION_WAIT_IF_LESS_THAN, 0, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user