static int ALCnullBackend_mixerProc(void *ptr) { ALCnullBackend *self = (ALCnullBackend*)ptr; ALCdevice *device = STATIC_CAST(ALCbackend, self)->mDevice; struct timespec now, start; ALuint64 avail, done; const long restTime = (long)((ALuint64)device->UpdateSize * 1000000000 / device->Frequency / 2); SetRTPriority(); althrd_setname(althrd_current(), MIXER_THREAD_NAME); done = 0; if(altimespec_get(&start, AL_TIME_UTC) != AL_TIME_UTC) { ERR("Failed to get starting time\n"); return 1; } while(!ATOMIC_LOAD(&self->killNow, almemory_order_acquire) && ATOMIC_LOAD(&device->Connected, almemory_order_acquire)) { if(altimespec_get(&now, AL_TIME_UTC) != AL_TIME_UTC) { ERR("Failed to get current time\n"); return 1; } avail = (now.tv_sec - start.tv_sec) * device->Frequency; avail += (ALint64)(now.tv_nsec - start.tv_nsec) * device->Frequency / 1000000000; if(avail < done) { /* Oops, time skipped backwards. Reset the number of samples done * with one update available since we (likely) just came back from * sleeping. */ done = avail - device->UpdateSize; } if(avail-done < device->UpdateSize) al_nssleep(restTime); else while(avail-done >= device->UpdateSize) { ALCnullBackend_lock(self); aluMixData(device, NULL, device->UpdateSize); ALCnullBackend_unlock(self); done += device->UpdateSize; } } return 0; }
int almtx_timedlock(almtx_t *mtx, const struct timespec *ts) { int ret; #ifdef HAVE_PTHREAD_MUTEX_TIMEDLOCK ret = pthread_mutex_timedlock(mtx, ts); switch(ret) { case 0: return althrd_success; case ETIMEDOUT: return althrd_timedout; case EBUSY: return althrd_busy; } return althrd_error; #else if(!mtx || !ts) return althrd_error; while((ret=almtx_trylock(mtx)) == althrd_busy) { struct timespec now; if(ts->tv_sec < 0 || ts->tv_nsec < 0 || ts->tv_nsec >= 1000000000 || altimespec_get(&now, AL_TIME_UTC) != AL_TIME_UTC) return althrd_error; if(now.tv_sec > ts->tv_sec || (now.tv_sec == ts->tv_sec && now.tv_nsec >= ts->tv_nsec)) return althrd_timedout; althrd_yield(); } return ret; #endif }
int alcnd_timedwait(alcnd_t *cond, almtx_t *mtx, const struct timespec *time_point) { struct timespec curtime; DWORD sleeptime; if(altimespec_get(&curtime, AL_TIME_UTC) != AL_TIME_UTC) return althrd_error; sleeptime = (time_point->tv_nsec - curtime.tv_nsec + 999999)/1000000; sleeptime += (time_point->tv_sec - curtime.tv_sec)*1000; if(SleepConditionVariableCS(cond, mtx, sleeptime) != 0) return althrd_success; return (GetLastError()==ERROR_TIMEOUT) ? althrd_timedout : althrd_error; }
int almtx_timedlock(almtx_t *mtx, const struct timespec *ts) { int ret; if(!mtx || !ts) return althrd_error; while((ret=almtx_trylock(mtx)) == althrd_busy) { struct timespec now; if(ts->tv_sec < 0 || ts->tv_nsec < 0 || ts->tv_nsec >= 1000000000 || altimespec_get(&now, AL_TIME_UTC) != AL_TIME_UTC) return althrd_error; if(now.tv_sec > ts->tv_sec || (now.tv_sec == ts->tv_sec && now.tv_nsec >= ts->tv_nsec)) return althrd_timedout; althrd_yield(); } return ret; }
int alcnd_timedwait(alcnd_t *cond, almtx_t *mtx, const struct timespec *time_point) { _int_alcnd_t *icond = cond->Ptr; struct timespec curtime; DWORD sleeptime; int res; if(altimespec_get(&curtime, AL_TIME_UTC) != AL_TIME_UTC) return althrd_error; sleeptime = (time_point->tv_nsec - curtime.tv_nsec + 999999)/1000000; sleeptime += (time_point->tv_sec - curtime.tv_sec)*1000; IncrementRef(&icond->wait_count); LeaveCriticalSection(mtx); res = WaitForMultipleObjects(2, icond->events, FALSE, sleeptime); if(DecrementRef(&icond->wait_count) == 0 && res == WAIT_OBJECT_0+BROADCAST) ResetEvent(icond->events[BROADCAST]); EnterCriticalSection(mtx); return (res == WAIT_TIMEOUT) ? althrd_timedout : althrd_success; }