static void RunBasicTest() { int value; SDL_SpinLock lock = 0; SDL_atomic_t v; SDL_bool tfret = SDL_FALSE; printf("\nspin lock---------------------------------------\n\n"); SDL_AtomicLock(&lock); printf("AtomicLock lock=%d\n", lock); SDL_AtomicUnlock(&lock); printf("AtomicUnlock lock=%d\n", lock); printf("\natomic -----------------------------------------\n\n"); SDL_AtomicSet(&v, 0); tfret = SDL_AtomicSet(&v, 10) == 0; printf("AtomicSet(10) tfret=%s val=%d\n", tf(tfret), SDL_AtomicGet(&v)); tfret = SDL_AtomicAdd(&v, 10) == 10; printf("AtomicAdd(10) tfret=%s val=%d\n", tf(tfret), SDL_AtomicGet(&v)); SDL_AtomicSet(&v, 0); SDL_AtomicIncRef(&v); tfret = (SDL_AtomicGet(&v) == 1); printf("AtomicIncRef() tfret=%s val=%d\n", tf(tfret), SDL_AtomicGet(&v)); SDL_AtomicIncRef(&v); tfret = (SDL_AtomicGet(&v) == 2); printf("AtomicIncRef() tfret=%s val=%d\n", tf(tfret), SDL_AtomicGet(&v)); tfret = (SDL_AtomicDecRef(&v) == SDL_FALSE); printf("AtomicDecRef() tfret=%s val=%d\n", tf(tfret), SDL_AtomicGet(&v)); tfret = (SDL_AtomicDecRef(&v) == SDL_TRUE); printf("AtomicDecRef() tfret=%s val=%d\n", tf(tfret), SDL_AtomicGet(&v)); SDL_AtomicSet(&v, 10); tfret = (SDL_AtomicCAS(&v, 0, 20) == SDL_FALSE); printf("AtomicCAS() tfret=%s val=%d\n", tf(tfret), SDL_AtomicGet(&v)); value = SDL_AtomicGet(&v); tfret = (SDL_AtomicCAS(&v, value, 20) == SDL_TRUE); printf("AtomicCAS() tfret=%s val=%d\n", tf(tfret), SDL_AtomicGet(&v)); }
void jrq_Write( JobRingQueue* queue, Job* jobby ) { // TODO: Test to see if we're writing over the tail, and if we are then fail bool writeSuccess = false; while( !writeSuccess ) { int idx = queue->head.value; if( SDL_AtomicCAS( &( queue->head ), idx, ( idx + 1 ) % queue->size ) ) { queue->ringBuffer[idx] = (*jobby); writeSuccess = true; } } }
static SDL_bool DequeueEvent_LockFree(SDL_EventQueue *queue, SDL_Event *event) { SDL_EventQueueEntry *entry; unsigned queue_pos; unsigned entry_seq; int delta; SDL_bool status; #ifdef TEST_SPINLOCK_FIFO /* This is a gate so an external thread can lock the queue */ SDL_AtomicLock(&queue->lock); SDL_assert(SDL_AtomicGet(&queue->watcher) == 0); SDL_AtomicIncRef(&queue->rwcount); SDL_AtomicUnlock(&queue->lock); #endif queue_pos = (unsigned)SDL_AtomicGet(&queue->dequeue_pos); for ( ; ; ) { entry = &queue->entries[queue_pos & WRAP_MASK]; entry_seq = (unsigned)SDL_AtomicGet(&entry->sequence); delta = (int)(entry_seq - (queue_pos + 1)); if (delta == 0) { /* The entry and the queue position match, try to increment the queue position */ if (SDL_AtomicCAS(&queue->dequeue_pos, (int)queue_pos, (int)(queue_pos+1))) { /* We own the object, fill it! */ *event = entry->event; SDL_AtomicSet(&entry->sequence, (int)(queue_pos+MAX_ENTRIES)); status = SDL_TRUE; break; } } else if (delta < 0) { /* We ran into an old queue entry, which means we've hit empty */ status = SDL_FALSE; break; } else { /* We ran into a new queue entry, get the new queue position */ queue_pos = (unsigned)SDL_AtomicGet(&queue->dequeue_pos); } } #ifdef TEST_SPINLOCK_FIFO SDL_AtomicDecRef(&queue->rwcount); #endif return status; }
// do the next job available in the ring buffer, returns if anything was actually done bool jrq_ProcessNext( JobRingQueue* queue ) { int idx = queue->tail.value; if( idx != queue->head.value ) { if( SDL_AtomicCAS( &( queue->tail ), idx, ( idx + 1 ) % queue->size ) ) { SDL_AtomicAdd( &( queue->busy ), 1 ); if( queue->ringBuffer[idx].process != NULL ) queue->ringBuffer[idx].process( queue->ringBuffer[idx].data ); queue->ringBuffer[idx].process = NULL; // invalidate the job SDL_AtomicAdd( &( queue->busy ), -1 ); return true; } } return false; }
internal bool32 SDLDoNextWorkQueueEntry(platform_work_queue *Queue) { bool32 WeShouldSleep = false; int OriginalNextEntryToRead = Queue->NextEntryToRead.value; int NewNextEntryToRead = (OriginalNextEntryToRead + 1) % ArrayCount(Queue->Entries); if (OriginalNextEntryToRead != Queue->NextEntryToWrite.value) { if (SDL_AtomicCAS(&Queue->NextEntryToRead, OriginalNextEntryToRead, NewNextEntryToRead)) { platform_work_queue_entry Entry = Queue->Entries[OriginalNextEntryToRead]; Entry.Callback(Queue, Entry.Data); SDL_AtomicIncRef(&Queue->CompletionCount); } } else { WeShouldSleep = true; } return WeShouldSleep; }
void SDL_TimerQuit(void) { SDL_TimerData *data = &SDL_timer_data; SDL_Timer *timer; SDL_TimerMap *entry; if (SDL_AtomicCAS(&data->active, 1, 0)) { /* active? Move to inactive. */ /* Shutdown the timer thread */ if (data->thread) { SDL_SemPost(data->sem); SDL_WaitThread(data->thread, NULL); data->thread = NULL; } SDL_DestroySemaphore(data->sem); data->sem = NULL; /* Clean up the timer entries */ while (data->timers) { timer = data->timers; data->timers = timer->next; SDL_free(timer); } while (data->freelist) { timer = data->freelist; data->freelist = timer->next; SDL_free(timer); } while (data->timermap) { entry = data->timermap; data->timermap = entry->next; SDL_free(entry); } SDL_DestroyMutex(data->timermap_lock); data->timermap_lock = NULL; } }
/* * Sys_Atomic_CAS */ bool Sys_Atomic_CAS( volatile int *value, int oldval, int newval, qmutex_t *mutex ) { return SDL_AtomicCAS( ( SDL_atomic_t * )value, newval, oldval ) == SDL_TRUE; }
static void RunEpicTest() { int b; atomicValue v; printf("\nepic test---------------------------------------\n\n"); printf("Size asserted to be >= 32-bit\n"); SDL_assert(sizeof(atomicValue)>=4); printf("Check static initializer\n"); v=SDL_AtomicGet(&good); SDL_assert(v==42); SDL_assert(bad==42); printf("Test negative values\n"); SDL_AtomicSet(&good, -5); v=SDL_AtomicGet(&good); SDL_assert(v==-5); printf("Verify maximum value\n"); SDL_AtomicSet(&good, CountTo); v=SDL_AtomicGet(&good); SDL_assert(v==CountTo); printf("Test compare and exchange\n"); b=SDL_AtomicCAS(&good, 500, 43); SDL_assert(!b); /* no swap since CountTo!=500 */ v=SDL_AtomicGet(&good); SDL_assert(v==CountTo); /* ensure no swap */ b=SDL_AtomicCAS(&good, CountTo, 44); SDL_assert(!!b); /* will swap */ v=SDL_AtomicGet(&good); SDL_assert(v==44); printf("Test Add\n"); v=SDL_AtomicAdd(&good, 1); SDL_assert(v==44); v=SDL_AtomicGet(&good); SDL_assert(v==45); v=SDL_AtomicAdd(&good, 10); SDL_assert(v==45); v=SDL_AtomicGet(&good); SDL_assert(v==55); printf("Test Add (Negative values)\n"); v=SDL_AtomicAdd(&good, -20); SDL_assert(v==55); v=SDL_AtomicGet(&good); SDL_assert(v==35); v=SDL_AtomicAdd(&good, -50); /* crossing zero down */ SDL_assert(v==35); v=SDL_AtomicGet(&good); SDL_assert(v==-15); v=SDL_AtomicAdd(&good, 30); /* crossing zero up */ SDL_assert(v==-15); v=SDL_AtomicGet(&good); SDL_assert(v==15); printf("Reset before count down test\n"); SDL_AtomicSet(&good, CountTo); v=SDL_AtomicGet(&good); SDL_assert(v==CountTo); bad=CountTo; SDL_assert(bad==CountTo); printf("Counting down from %d, Expect %d remaining\n",CountTo,Expect); runAdder(); v=SDL_AtomicGet(&good); printf("Atomic %d Non-Atomic %d\n",v,bad); SDL_assert(v==Expect); SDL_assert(bad!=Expect); }