Make and use a C11-like altimespec_get wrapper function
This commit is contained in:
+24
-17
@@ -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;
|
||||
}
|
||||
if(avail-done < device->UpdateSize)
|
||||
{
|
||||
long restTime = (long)((device->UpdateSize - (avail-done)) * 1000000000 /
|
||||
device->Frequency);
|
||||
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;
|
||||
}
|
||||
|
||||
do {
|
||||
if(avail-done < device->UpdateSize)
|
||||
al_nssleep(0, restTime);
|
||||
else while(avail-done >= device->UpdateSize)
|
||||
{
|
||||
aluMixData(device, NULL, device->UpdateSize);
|
||||
done += device->UpdateSize;
|
||||
} while(avail-done >= device->UpdateSize);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
+34
-28
@@ -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();
|
||||
ERR("Failed to get starting time\n");
|
||||
return 1;
|
||||
}
|
||||
while(!data->killNow && device->Connected)
|
||||
{
|
||||
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 += ((ALuint64)1<<32)*Device->Frequency/1000 - done;
|
||||
done = 0;
|
||||
}
|
||||
if(avail-done < Device->UpdateSize)
|
||||
{
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
+48
-12
@@ -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
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user