Introduce syncArbitrateAddress/WithTimeout (replaces __sync_get_arbiter)

This commit is contained in:
fincs 2020-06-12 20:40:47 +02:00
parent 528f8feb0b
commit 9c1c847388
No known key found for this signature in database
GPG Key ID: 62C7609ADA219C60
4 changed files with 49 additions and 29 deletions

View File

@ -915,16 +915,7 @@ Result svcCreateAddressArbiter(Handle *arbiter);
* @param addr A pointer to a s32 value. * @param addr A pointer to a s32 value.
* @param type Type of action to be performed by the arbiter * @param type Type of action to be performed by the arbiter
* @param value Number of threads to signal if using @ref ARBITRATION_SIGNAL, or the value used for comparison. * @param value Number of threads to signal if using @ref ARBITRATION_SIGNAL, or the value used for comparison.
* * @warning Please use \ref syncArbitrateAddress or \ref syncArbitrateAddressWithTimeout instead.
* This will perform an arbitration based on #type. The comparisons are done between #value and the value at the address #addr.
*
* @code
* s32 val=0;
* // Does *nothing* since val >= 0
* svcCreateAddressArbiter(arbiter,&val,ARBITRATION_WAIT_IF_LESS_THAN,0,0);
* // Thread will wait for a signal or wake up after 10000000 nanoseconds because val < 1.
* svcCreateAddressArbiter(arbiter,&val,ARBITRATION_WAIT_IF_LESS_THAN_TIMEOUT,1,10000000ULL);
* @endcode
*/ */
Result svcArbitrateAddress(Handle arbiter, u32 addr, ArbitrationType type, s32 value, s64 nanoseconds); Result svcArbitrateAddress(Handle arbiter, u32 addr, ArbitrationType type, s32 value, s64 nanoseconds);

View File

@ -126,10 +126,36 @@ static inline bool __strexb(u8* addr, u8 val)
#define AtomicSwap(ptr, value) __atomic_exchange_n((u32*)(ptr), (value), __ATOMIC_SEQ_CST) #define AtomicSwap(ptr, value) __atomic_exchange_n((u32*)(ptr), (value), __ATOMIC_SEQ_CST)
/** /**
* @brief Retrieves the synchronization subsystem's address arbiter handle. * @brief Function used to implement user-mode synchronization primitives.
* @return The synchronization subsystem's address arbiter handle. * @param addr Pointer to a signed 32-bit value whose address will be used to identify waiting threads.
* @param type Type of action to be performed by the arbiter
* @param value Number of threads to signal if using @ref ARBITRATION_SIGNAL, or the value used for comparison.
*
* This will perform an arbitration based on #type. The comparisons are done between #value and the value at the address #addr.
*
* @code
* s32 val=0;
* // Does *nothing* since val >= 0
* syncArbitrateAddress(&val,ARBITRATION_WAIT_IF_LESS_THAN,0);
* @endcode
*/ */
Handle __sync_get_arbiter(void); Result syncArbitrateAddress(s32* addr, ArbitrationType type, s32 value);
/**
* @brief Function used to implement user-mode synchronization primitives (with timeout).
* @param addr Pointer to a signed 32-bit value whose address will be used to identify waiting threads.
* @param type Type of action to be performed by the arbiter (must use \ref ARBITRATION_WAIT_IF_LESS_THAN_TIMEOUT or \ref ARBITRATION_DECREMENT_AND_WAIT_IF_LESS_THAN_TIMEOUT)
* @param value Number of threads to signal if using @ref ARBITRATION_SIGNAL, or the value used for comparison.
*
* This will perform an arbitration based on #type. The comparisons are done between #value and the value at the address #addr.
*
* @code
* s32 val=0;
* // Thread will wait for a signal or wake up after 10000000 nanoseconds because val < 1.
* syncArbitrateAddressWithTimeout(&val,ARBITRATION_WAIT_IF_LESS_THAN_TIMEOUT,1,10000000LL);
* @endcode
*/
Result syncArbitrateAddressWithTimeout(s32* addr, ArbitrationType type, s32 value, s64 timeout_ns);
/** /**
* @brief Initializes a light lock. * @brief Initializes a light lock.

View File

@ -28,8 +28,6 @@ static vu8* gspEventData;
static void gspEventThreadMain(void *arg); static void gspEventThreadMain(void *arg);
Handle __sync_get_arbiter(void);
Result gspInit(void) Result gspInit(void)
{ {
Result res=0; Result res=0;
@ -103,7 +101,7 @@ GSPGPU_Event gspWaitForAnyEvent(void)
} }
} while (__strex(&gspLastEvent, -1)); } while (__strex(&gspLastEvent, -1));
if (x < 0) if (x < 0)
svcArbitrateAddress(__sync_get_arbiter(), (u32)&gspLastEvent, ARBITRATION_WAIT_IF_LESS_THAN, 0, 0); syncArbitrateAddress(&gspLastEvent, ARBITRATION_WAIT_IF_LESS_THAN, 0);
} while (x < 0); } while (x < 0);
return (GSPGPU_Event)x; return (GSPGPU_Event)x;
} }
@ -177,7 +175,7 @@ void gspEventThreadMain(void *arg)
do do
__ldrex(&gspLastEvent); __ldrex(&gspLastEvent);
while (__strex(&gspLastEvent, curEvt)); while (__strex(&gspLastEvent, curEvt));
svcArbitrateAddress(__sync_get_arbiter(), (u32)&gspLastEvent, ARBITRATION_SIGNAL, 1, 0); syncArbitrateAddress(&gspLastEvent, ARBITRATION_SIGNAL, 1);
gspEventCounts[curEvt]++; gspEventCounts[curEvt]++;
} }
} }

View File

@ -16,9 +16,14 @@ void __sync_fini(void)
svcCloseHandle(arbiter); svcCloseHandle(arbiter);
} }
Handle __sync_get_arbiter(void) Result syncArbitrateAddress(s32* addr, ArbitrationType type, s32 value)
{ {
return arbiter; return svcArbitrateAddress(arbiter, (u32)addr, type, value, 0);
}
Result syncArbitrateAddressWithTimeout(s32* addr, ArbitrationType type, s32 value, s64 timeout_ns)
{
return svcArbitrateAddress(arbiter, (u32)addr, type, value, timeout_ns);
} }
void LightLock_Init(LightLock* lock) void LightLock_Init(LightLock* lock)
@ -51,7 +56,7 @@ void LightLock_Lock(LightLock* lock)
while (bAlreadyLocked) while (bAlreadyLocked)
{ {
// Wait for the lock holder thread to wake us up // Wait for the lock holder thread to wake us up
svcArbitrateAddress(arbiter, (u32)lock, ARBITRATION_WAIT_IF_LESS_THAN, 0, 0); syncArbitrateAddress(lock, ARBITRATION_WAIT_IF_LESS_THAN, 0);
// Try to lock again // Try to lock again
do do
@ -97,7 +102,7 @@ void LightLock_Unlock(LightLock* lock)
if (val > 1) if (val > 1)
// Wake up exactly one thread // Wake up exactly one thread
svcArbitrateAddress(arbiter, (u32)lock, ARBITRATION_SIGNAL, 1, 0); syncArbitrateAddress(lock, ARBITRATION_SIGNAL, 1);
} }
void RecursiveLock_Init(RecursiveLock* lock) void RecursiveLock_Init(RecursiveLock* lock)
@ -180,9 +185,9 @@ void LightEvent_Clear(LightEvent* event)
void LightEvent_Pulse(LightEvent* event) void LightEvent_Pulse(LightEvent* event)
{ {
if (event->state == -2) if (event->state == -2)
svcArbitrateAddress(arbiter, (u32)event, ARBITRATION_SIGNAL, -1, 0); syncArbitrateAddress(&event->state, ARBITRATION_SIGNAL, -1);
else if (event->state == -1) else if (event->state == -1)
svcArbitrateAddress(arbiter, (u32)event, ARBITRATION_SIGNAL, 1, 0); syncArbitrateAddress(&event->state, ARBITRATION_SIGNAL, 1);
else else
LightEvent_Clear(event); LightEvent_Clear(event);
} }
@ -192,12 +197,12 @@ void LightEvent_Signal(LightEvent* event)
if (event->state == -1) if (event->state == -1)
{ {
LightEvent_SetState(event, 0); LightEvent_SetState(event, 0);
svcArbitrateAddress(arbiter, (u32)event, ARBITRATION_SIGNAL, 1, 0); syncArbitrateAddress(&event->state, ARBITRATION_SIGNAL, 1);
} else if (event->state == -2) } else if (event->state == -2)
{ {
LightLock_Lock(&event->lock); LightLock_Lock(&event->lock);
LightEvent_SetState(event, 1); LightEvent_SetState(event, 1);
svcArbitrateAddress(arbiter, (u32)event, ARBITRATION_SIGNAL, -1, 0); syncArbitrateAddress(&event->state, ARBITRATION_SIGNAL, -1);
LightLock_Unlock(&event->lock); LightLock_Unlock(&event->lock);
} }
} }
@ -215,7 +220,7 @@ void LightEvent_Wait(LightEvent* event)
{ {
if (event->state == -2) if (event->state == -2)
{ {
svcArbitrateAddress(arbiter, (u32)event, ARBITRATION_WAIT_IF_LESS_THAN, 0, 0); syncArbitrateAddress(&event->state, ARBITRATION_WAIT_IF_LESS_THAN, 0);
return; return;
} }
if (event->state != -1) if (event->state != -1)
@ -225,7 +230,7 @@ void LightEvent_Wait(LightEvent* event)
if (event->state == 0 && LightEvent_TryReset(event)) if (event->state == 0 && LightEvent_TryReset(event))
return; return;
} }
svcArbitrateAddress(arbiter, (u32)event, ARBITRATION_WAIT_IF_LESS_THAN, 0, 0); syncArbitrateAddress(&event->state, ARBITRATION_WAIT_IF_LESS_THAN, 0);
} }
} }
@ -254,7 +259,7 @@ void LightSemaphore_Acquire(LightSemaphore* semaphore, s32 count)
num_threads_acq = (s16)__ldrexh((u16 *)&semaphore->num_threads_acq); num_threads_acq = (s16)__ldrexh((u16 *)&semaphore->num_threads_acq);
while (__strexh((u16 *)&semaphore->num_threads_acq, num_threads_acq + 1)); while (__strexh((u16 *)&semaphore->num_threads_acq, num_threads_acq + 1));
svcArbitrateAddress(arbiter, (u32)semaphore, ARBITRATION_WAIT_IF_LESS_THAN, count, 0); syncArbitrateAddress(&semaphore->current_count, ARBITRATION_WAIT_IF_LESS_THAN, count);
do do
num_threads_acq = (s16)__ldrexh((u16 *)&semaphore->num_threads_acq); num_threads_acq = (s16)__ldrexh((u16 *)&semaphore->num_threads_acq);
@ -275,5 +280,5 @@ void LightSemaphore_Release(LightSemaphore* semaphore, s32 count)
} while (__strex(&semaphore->current_count, new_count)); } while (__strex(&semaphore->current_count, new_count));
if(old_count <= 0 || semaphore->num_threads_acq > 0) if(old_count <= 0 || semaphore->num_threads_acq > 0)
svcArbitrateAddress(arbiter, (u32)semaphore, ARBITRATION_SIGNAL, count, 0); syncArbitrateAddress(&semaphore->current_count, ARBITRATION_SIGNAL, count);
} }