aboutsummaryrefslogtreecommitdiffstats
path: root/Alc/threads.c
diff options
context:
space:
mode:
Diffstat (limited to 'Alc/threads.c')
-rw-r--r--Alc/threads.c60
1 files changed, 48 insertions, 12 deletions
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