1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
|
#include <errno.h>
#include <pthread.h>
#include <sys/time.h>
#include "WAVM/Inline/Assert.h"
#include "WAVM/Inline/Errors.h"
#include "WAVM/Inline/I128.h"
#include "WAVM/Inline/Time.h"
#include "WAVM/Platform/Clock.h"
#include "WAVM/Platform/Defines.h"
#include "WAVM/Platform/Event.h"
using namespace WAVM;
using namespace WAVM::Platform;
Platform::Event::Event()
{
static_assert(sizeof(pthreadMutex) == sizeof(pthread_mutex_t), "");
static_assert(alignof(PthreadMutex) >= alignof(pthread_mutex_t), "");
static_assert(sizeof(pthreadCond) == sizeof(pthread_cond_t), "");
static_assert(alignof(PthreadCond) >= alignof(pthread_cond_t), "");
pthread_condattr_t conditionVariableAttr;
WAVM_ERROR_UNLESS(!pthread_condattr_init(&conditionVariableAttr));
// Set the condition variable to use the monotonic clock for wait timeouts.
#ifndef __APPLE__
WAVM_ERROR_UNLESS(!pthread_condattr_setclock(&conditionVariableAttr, CLOCK_MONOTONIC));
#endif
WAVM_ERROR_UNLESS(!pthread_cond_init((pthread_cond_t*)&pthreadCond, nullptr));
WAVM_ERROR_UNLESS(!pthread_mutex_init((pthread_mutex_t*)&pthreadMutex, nullptr));
WAVM_ERROR_UNLESS(!pthread_condattr_destroy(&conditionVariableAttr));
}
Platform::Event::~Event()
{
pthread_cond_destroy((pthread_cond_t*)&pthreadCond);
WAVM_ERROR_UNLESS(!pthread_mutex_destroy((pthread_mutex_t*)&pthreadMutex));
}
bool Platform::Event::wait(Time waitDuration)
{
WAVM_ERROR_UNLESS(!pthread_mutex_lock((pthread_mutex_t*)&pthreadMutex));
int result;
if(isInfinity(waitDuration))
{
result = pthread_cond_wait((pthread_cond_t*)&pthreadCond, (pthread_mutex_t*)&pthreadMutex);
}
else
{
// Use the non-POSIX relative time wait on Mac, and an absolute monotonic clock timeout on
// other POSIX systems.
#ifdef __APPLE__
timespec waitTimeSpec;
waitTimeSpec.tv_sec = U64(waitDuration.ns / 1000000000);
waitTimeSpec.tv_nsec = U64(waitDuration.ns % 1000000000);
result = pthread_cond_timedwait_relative_np(
(pthread_cond_t*)&pthreadCond, (pthread_mutex_t*)&pthreadMutex, &waitTimeSpec);
#else
const I128 untilTimeNS = getClockTime(Clock::monotonic).ns + waitDuration.ns;
timespec untilTimeSpec;
untilTimeSpec.tv_sec = U64(untilTimeNS / 1000000000);
untilTimeSpec.tv_nsec = U64(untilTimeNS % 1000000000);
result = pthread_cond_timedwait(
(pthread_cond_t*)&pthreadCond, (pthread_mutex_t*)&pthreadMutex, &untilTimeSpec);
#endif
}
WAVM_ERROR_UNLESS(!pthread_mutex_unlock((pthread_mutex_t*)&pthreadMutex));
if(result == ETIMEDOUT) { return false; }
else
{
WAVM_ERROR_UNLESS(!result);
return true;
}
}
void Platform::Event::signal()
{
WAVM_ERROR_UNLESS(!pthread_cond_signal((pthread_cond_t*)&pthreadCond));
}
|