diff options
Diffstat (limited to 'Alc')
-rw-r--r-- | Alc/backends/null.c | 39 | ||||
-rw-r--r-- | Alc/backends/wave.c | 62 | ||||
-rw-r--r-- | Alc/compat.h | 2 | ||||
-rw-r--r-- | Alc/helpers.c | 39 | ||||
-rw-r--r-- | Alc/threads.c | 60 |
5 files changed, 105 insertions, 97 deletions
diff --git a/Alc/backends/null.c b/Alc/backends/null.c index 26e63b2e..a96ab701 100644 --- a/Alc/backends/null.c +++ b/Alc/backends/null.c @@ -72,38 +72,45 @@ static int ALCnullBackend_mixerProc(void *ptr) { ALCnullBackend *self = (ALCnullBackend*)ptr; ALCdevice *device = STATIC_CAST(ALCbackend, self)->mDevice; - ALuint now, start; + struct timespec now, start; ALuint64 avail, done; + const long restTime = (long)((ALuint64)device->UpdateSize * 1000000000 / + device->Frequency / 2); SetRTPriority(); SetThreadName(MIXER_THREAD_NAME); done = 0; - start = timeGetTime(); + if(altimespec_get(&start, AL_TIME_UTC) != AL_TIME_UTC) + { + ERR("Failed to get starting time\n"); + return 1; + } while(!self->killNow && device->Connected) { - now = timeGetTime(); + if(altimespec_get(&now, AL_TIME_UTC) != AL_TIME_UTC) + { + ERR("Failed to get current time\n"); + return 1; + } - avail = (ALuint64)(now-start) * device->Frequency / 1000; + avail = (now.tv_sec - start.tv_sec) * device->Frequency; + avail += (ALint64)(now.tv_nsec - start.tv_nsec) * device->Frequency / 1000000000; if(avail < done) { - /* Timer wrapped (50 days???). Add the remainder of the cycle to - * the available count and reset the number of samples done */ - avail += (U64(1)<<32)*device->Frequency/1000 - done; - done = 0; + /* 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) - { - long restTime = (long)((device->UpdateSize - (avail-done)) * 1000000000 / - device->Frequency); al_nssleep(0, restTime); - continue; - } - - do { + else while(avail-done >= device->UpdateSize) + { aluMixData(device, NULL, device->UpdateSize); done += device->UpdateSize; - } while(avail-done >= device->UpdateSize); + } } return 0; diff --git a/Alc/backends/wave.c b/Alc/backends/wave.c index 5f5c92c1..343a3cb5 100644 --- a/Alc/backends/wave.c +++ b/Alc/backends/wave.c @@ -87,47 +87,53 @@ static void fwrite32le(ALuint val, FILE *f) static int WaveProc(void *ptr) { - ALCdevice *Device = (ALCdevice*)ptr; - wave_data *data = (wave_data*)Device->ExtraData; + ALCdevice *device = (ALCdevice*)ptr; + wave_data *data = (wave_data*)device->ExtraData; + struct timespec now, start; + ALint64 avail, done; ALuint frameSize; - ALuint now, start; - ALuint64 avail, done; size_t fs; - const long restTime = (long)((ALuint64)Device->UpdateSize * 1000000000 / - Device->Frequency / 2); + const long restTime = (long)((ALuint64)device->UpdateSize * 1000000000 / + device->Frequency / 2); SetThreadName(MIXER_THREAD_NAME); - frameSize = FrameSizeFromDevFmt(Device->FmtChans, Device->FmtType); + frameSize = FrameSizeFromDevFmt(device->FmtChans, device->FmtType); done = 0; - start = timeGetTime(); - while(!data->killNow && Device->Connected) + if(altimespec_get(&start, AL_TIME_UTC) != AL_TIME_UTC) { - now = timeGetTime(); - - avail = (ALuint64)(now-start) * Device->Frequency / 1000; - if(avail < done) + ERR("Failed to get starting time\n"); + return 1; + } + while(!data->killNow && device->Connected) + { + if(altimespec_get(&now, AL_TIME_UTC) != AL_TIME_UTC) { - /* Timer wrapped (50 days???). Add the remainder of the cycle to - * the available count and reset the number of samples done */ - avail += ((ALuint64)1<<32)*Device->Frequency/1000 - done; - done = 0; + ERR("Failed to get current time\n"); + return 1; } - if(avail-done < Device->UpdateSize) + + avail = (now.tv_sec - start.tv_sec) * device->Frequency; + avail += (ALint64)(now.tv_nsec - start.tv_nsec) * device->Frequency / 1000000000; + if(avail < done) { - al_nssleep(0, restTime); - continue; + /* 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; } - while(avail-done >= Device->UpdateSize) + if(avail-done < device->UpdateSize) + al_nssleep(0, restTime); + else while(avail-done >= device->UpdateSize) { - aluMixData(Device, data->buffer, Device->UpdateSize); - done += Device->UpdateSize; + aluMixData(device, data->buffer, device->UpdateSize); + done += device->UpdateSize; if(!IS_LITTLE_ENDIAN) { - ALuint bytesize = BytesFromDevFmt(Device->FmtType); + ALuint bytesize = BytesFromDevFmt(device->FmtType); ALubyte *bytes = data->buffer; ALuint i; @@ -149,16 +155,16 @@ static int WaveProc(void *ptr) } else { - fs = fwrite(data->buffer, frameSize, Device->UpdateSize, + fs = fwrite(data->buffer, frameSize, device->UpdateSize, data->f); (void)fs; } if(ferror(data->f)) { ERR("Error writing to file\n"); - ALCdevice_Lock(Device); - aluHandleDisconnect(Device); - ALCdevice_Unlock(Device); + ALCdevice_Lock(device); + aluHandleDisconnect(device); + ALCdevice_Unlock(device); break; } } diff --git a/Alc/compat.h b/Alc/compat.h index f11de462..50516ce8 100644 --- a/Alc/compat.h +++ b/Alc/compat.h @@ -23,8 +23,6 @@ FILE *al_fopen(const char *fname, const char *mode); #include <pthread.h> -ALuint timeGetTime(void); - #define althread_once_t pthread_once_t #define ALTHREAD_ONCE_INIT PTHREAD_ONCE_INIT #define althread_once pthread_once diff --git a/Alc/helpers.c b/Alc/helpers.c index b8e5be03..e175c195 100644 --- a/Alc/helpers.c +++ b/Alc/helpers.c @@ -387,45 +387,6 @@ FILE *al_fopen(const char *fname, const char *mode) #else -#include <sched.h> -#include <time.h> -#include <sys/time.h> - - -/* NOTE: This wrapper isn't quite accurate as it returns an ALuint, as opposed - * to the expected DWORD. Both are defined as unsigned 32-bit types, however. - * Additionally, Win32 is supposed to measure the time since Windows started, - * as opposed to the actual time. */ -ALuint timeGetTime(void) -{ -#if _POSIX_TIMERS > 0 - struct timespec ts; - int ret = -1; - -#if defined(_POSIX_MONOTONIC_CLOCK) && (_POSIX_MONOTONIC_CLOCK >= 0) -#if _POSIX_MONOTONIC_CLOCK == 0 - static int hasmono = 0; - if(hasmono > 0 || (hasmono == 0 && - (hasmono=sysconf(_SC_MONOTONIC_CLOCK)) > 0)) -#endif - ret = clock_gettime(CLOCK_MONOTONIC, &ts); -#endif - if(ret != 0) - ret = clock_gettime(CLOCK_REALTIME, &ts); - assert(ret == 0); - - return ts.tv_nsec/1000000 + ts.tv_sec*1000; -#else - struct timeval tv; - int ret; - - ret = gettimeofday(&tv, NULL); - assert(ret == 0); - - return tv.tv_usec/1000 + tv.tv_sec*1000; -#endif -} - #ifdef HAVE_DLFCN_H void *LoadLib(const char *name) diff --git a/Alc/threads.c b/Alc/threads.c index 3aef7ae8..b43b1889 100644 --- a/Alc/threads.c +++ b/Alc/threads.c @@ -173,25 +173,22 @@ void almtx_destroy(almtx_t *mtx) int almtx_timedlock(almtx_t *mtx, const struct timespec *ts) { - DWORD start, timelen; int ret; if(!mtx || !ts) return althrd_error; - timelen = ts->tv_sec * 1000; - timelen += (ts->tv_nsec+999999) / 1000000; - - start = timeGetTime(); while((ret=almtx_trylock(mtx)) == althrd_busy) { - DWORD now = timeGetTime(); - if(now-start >= timelen) - { - ret = althrd_timedout; - break; - } - SwitchToThread(); + 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; @@ -257,8 +254,28 @@ void altss_delete(altss_t tss_id) TlsFree(tss_id); } + +int altimespec_get(struct timespec *ts, int base) +{ + if(base == AL_TIME_UTC) + { + union { + FILETIME ftime; + ULARGE_INTEGER ulint; + } systime; + GetSystemTimeAsFileTime(&systime.ftime); + /* FILETIME is in 100-nanosecond units, or 1/10th of a microsecond. */ + ts->tv_sec = systime.ulint.QuadPart/10000000; + ts->tv_nsec = (systime.ulint.QuadPart%10000000) * 100; + return base; + } + + return 0; +} + #else +#include <unistd.h> #include <pthread.h> #ifdef HAVE_PTHREAD_NP_H #include <pthread_np.h> @@ -425,4 +442,23 @@ void altss_delete(altss_t tss_id) pthread_key_delete(tss_id); } + +int altimespec_get(struct timespec *ts, int base) +{ + if(base == AL_TIME_UTC) + { +#if _POSIX_TIMERS > 0 + int ret = clock_gettime(CLOCK_REALTIME, ts); + if(ret == 0) return base; +#else /* _POSIX_TIMERS > 0 */ +#warning "clock_gettime (POSIX.1-2001) is not available, timing resolution will be poor." + ts->tv_sec = time(NULL); + ts->tv_nsec = 0; + return base; +#endif + } + + return 0; +} + #endif |