aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChris Robinson <[email protected]>2014-04-17 09:03:57 -0700
committerChris Robinson <[email protected]>2014-04-17 09:03:57 -0700
commitd1f1a1d056b654bbe52c0b1ba6752b7a106482e1 (patch)
treee549f65f02cc97be3f42e9165a3407d9fcbc5abe
parent47f5c436c8f5e55ebafd72dcd155b2a762bb18ca (diff)
Make and use a C11-like altimespec_get wrapper function
-rw-r--r--Alc/backends/null.c39
-rw-r--r--Alc/backends/wave.c62
-rw-r--r--Alc/compat.h2
-rw-r--r--Alc/helpers.c39
-rw-r--r--Alc/threads.c60
-rw-r--r--OpenAL32/Include/threads.h6
6 files changed, 110 insertions, 98 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
diff --git a/OpenAL32/Include/threads.h b/OpenAL32/Include/threads.h
index 0c9601c9..e021f7a5 100644
--- a/OpenAL32/Include/threads.h
+++ b/OpenAL32/Include/threads.h
@@ -18,11 +18,13 @@ enum {
almtx_timed = 2
};
-
typedef int (*althrd_start_t)(void*);
typedef void (*altss_dtor_t)(void*);
+#define AL_TIME_UTC 1
+
+
#ifdef _WIN32
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
@@ -208,6 +210,8 @@ int almtx_timedlock(almtx_t *mtx, const struct timespec *ts);
int altss_create(altss_t *tss_id, altss_dtor_t callback);
void altss_delete(altss_t tss_id);
+int altimespec_get(struct timespec *ts, int base);
+
void SetThreadName(const char *name);