void LightLock_Lock(LightLock* lock) { s32 val; _begin: do { val = __ldrex(lock); 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(); goto _wait; } } while (__strex(lock, -(val-1))); return; } } while (__strex(lock, -val)); }
void LightSemaphore_Acquire(LightSemaphore* semaphore, s32 count) { s32 old_count; s16 num_threads_acq; do { for (;;) { old_count = __ldrex(&semaphore->current_count); if (old_count > 0) break; __clrex(); do num_threads_acq = (s16)__ldrexh((u16 *)&semaphore->num_threads_acq); while (__strexh((u16 *)&semaphore->num_threads_acq, num_threads_acq + 1)); svcArbitrateAddress(arbiter, (u32)semaphore, ARBITRATION_WAIT_IF_LESS_THAN, count, 0); do num_threads_acq = (s16)__ldrexh((u16 *)&semaphore->num_threads_acq); while (__strexh((u16 *)&semaphore->num_threads_acq, num_threads_acq - 1)); } } while (__strex(&semaphore->current_count, old_count - count)); }
void *rt_alloc_box (void *box_mem) { /* Allocate a memory block and return start address. */ void **free; #ifndef __USE_EXCLUSIVE_ACCESS int irq_dis; #if defined (__ICCARM__) irq_dis = __disable_irq_iar(); #else irq_dis = __disable_irq (); #endif /* __ICCARM__ */ free = ((P_BM) box_mem)->free; if (free) { ((P_BM) box_mem)->free = *free; } if (!irq_dis) __enable_irq (); #else do { if ((free = (void **)__ldrex(&((P_BM) box_mem)->free)) == 0) { __clrex(); break; } } while (__strex((U32)*free, &((P_BM) box_mem)->free)); #endif return (free); }
static int popInterrupt() { int curEvt; bool strexFailed; do { union { struct { u8 cur; u8 count; u8 err; u8 unused; }; u32 as_u32; } header; // Do a load on all header fields as an atomic unit header.as_u32 = __ldrex((s32*)gspEventData); if (__builtin_expect(header.count == 0, 0)) { __clrex(); return -1; } curEvt = gspEventData[0xC + header.cur]; header.cur += 1; if (header.cur >= 0x34) header.cur -= 0x34; header.count -= 1; header.err = 0; // Should this really be set? strexFailed = __strex((s32*)gspEventData, header.as_u32); } while (__builtin_expect(strexFailed, 0)); return curEvt; }
static inline int LightEvent_TryReset(LightEvent* event) { do { if (__ldrex(&event->state)) { __clrex(); return 0; } } while (__strex(&event->state, -1)); return 1; }
int LightLock_TryLock(LightLock* lock) { s32 val; do { val = __ldrex(lock); if (val < 0) { __clrex(); return 1; // Failure } } while (__strex(lock, -val)); return 0; // Success }
/*----------------------------------------------------------------------------*/ bool spinTryLock(spinlock_t *lock) { if (__ldrexb(lock) == SPIN_UNLOCKED) /* Check current state */ { if (!__strexb(SPIN_LOCKED, lock)) { __dmb(); return true; } else return false; } __clrex(); return false; /* Lock is not free */ }
GSPGPU_Event gspWaitForAnyEvent(void) { s32 x; do { do { x = __ldrex(&gspLastEvent); if (x < 0) { __clrex(); break; } } while (__strex(&gspLastEvent, -1)); if (x < 0) svcArbitrateAddress(__sync_get_arbiter(), (u32)&gspLastEvent, ARBITRATION_WAIT_IF_LESS_THAN, 0, 0); } while (x < 0); return (GSPGPU_Event)x; }