Ugh, macOS doesn't support timer_create() and friends :| (Even up to 10.13, it seems; not sure about 10.14!) Switch back to setitimer(). Also rename oldsig to prevSig and remove a needless (for now???) cast.
This commit is contained in:
parent
8655bbf19c
commit
5836a2a236
|
@ -12,15 +12,10 @@ if libui_OS == 'windows'
|
||||||
'testing_windows.c',
|
'testing_windows.c',
|
||||||
'timer_windows.c',
|
'timer_windows.c',
|
||||||
]
|
]
|
||||||
elif libui_OS == 'darwin'
|
|
||||||
libui_test_sources += [
|
|
||||||
'testing_darwin.c',
|
|
||||||
'testing_darwinunix.c',
|
|
||||||
]
|
|
||||||
else
|
else
|
||||||
libui_test_sources += [
|
libui_test_sources += [
|
||||||
'testing_darwinunix.c',
|
'testing_darwinunix.c',
|
||||||
'testing_unix.c',
|
'timer_darwinunix.c'
|
||||||
]
|
]
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
|
|
@ -73,7 +73,7 @@ timerTime timerMonotonicNow(void)
|
||||||
ts.tv_nsec -= base.tv_nsec;
|
ts.tv_nsec -= base.tv_nsec;
|
||||||
if (ts.tv_nsec < 0) { // this is safe because POSIX requires this to be of type long
|
if (ts.tv_nsec < 0) { // this is safe because POSIX requires this to be of type long
|
||||||
ts.tv_sec--;
|
ts.tv_sec--;
|
||||||
ts.tv_nsec += (long) timerSecond;
|
ts.tv_nsec += timerSecond;
|
||||||
}
|
}
|
||||||
ret = ((timerTime) (ts.tv_sec)) * timerSecond;
|
ret = ((timerTime) (ts.tv_sec)) * timerSecond;
|
||||||
ret += (timerTime) (ts.tv_nsec);
|
ret += (timerTime) (ts.tv_nsec);
|
||||||
|
@ -89,8 +89,8 @@ timerDuration timerTimeSub(timerTime end, timerTime start)
|
||||||
|
|
||||||
struct timeoutParams {
|
struct timeoutParams {
|
||||||
jmp_buf retpos;
|
jmp_buf retpos;
|
||||||
timer_t timer;
|
struct itimerval prevDuration;
|
||||||
struct sigaction oldsig;
|
struct sigaction prevSig;
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct timeoutParams p;
|
static struct timeoutParams p;
|
||||||
|
@ -100,20 +100,20 @@ static void onTimeout(int sig, siginfo_t *info, void *ctx)
|
||||||
if (info->si_value.sival_ptr == &p)
|
if (info->si_value.sival_ptr == &p)
|
||||||
longjmp(p.retpos, 1);
|
longjmp(p.retpos, 1);
|
||||||
// otherwise, call the overloaded SIGALRM handler
|
// otherwise, call the overloaded SIGALRM handler
|
||||||
if ((p.oldsig.sa_flags & SA_SIGINFO) != 0) {
|
if ((p.prevSig.sa_flags & SA_SIGINFO) != 0) {
|
||||||
(*(p.oldsig.sa_sigaction))(sig, info, ctx);
|
(*(p.prevSig.sa_sigaction))(sig, info, ctx);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (p.oldsig.sa_handler == SIG_IGN)
|
if (p.prevSig.sa_handler == SIG_IGN)
|
||||||
return;
|
return;
|
||||||
if (p.oldsig.sa_handler == SIG_DFL) {
|
if (p.prevSig.sa_handler == SIG_DFL) {
|
||||||
// SIG_DFL for SIGALRM is to terminate the program
|
// SIG_DFL for SIGALRM is to terminate the program
|
||||||
// because POSIX doesn't specify how to convert from signal number to exit code, we will have to do this instead
|
// because POSIX doesn't specify how to convert from signal number to exit code, we will have to do this instead
|
||||||
// (POSIX does say these should be safe to call unless the signal was explicitly raised, which we aren't doing, and timer_create() isn't documented as doing that either...)
|
// (POSIX does say these should be safe to call unless the signal was explicitly raised, which we aren't doing, and timer_create() isn't documented as doing that either...)
|
||||||
signal(sig, SIG_DFL);
|
signal(sig, SIG_DFL);
|
||||||
raise(sig);
|
raise(sig);
|
||||||
}
|
}
|
||||||
(*(p.oldsig.sa_handler))(sig);
|
(*(p.prevSig.sa_handler))(sig);
|
||||||
}
|
}
|
||||||
|
|
||||||
// POSIX doesn't have atomic operations :|
|
// POSIX doesn't have atomic operations :|
|
||||||
|
@ -172,11 +172,10 @@ timerSysError timerRunWithTimeout(timerDuration d, void (*f)(void *data), void *
|
||||||
sigset_t sigalrm, allsigs;
|
sigset_t sigalrm, allsigs;
|
||||||
sigset_t prevMask;
|
sigset_t prevMask;
|
||||||
volatile int restorePrevMask = 0;
|
volatile int restorePrevMask = 0;
|
||||||
struct sigevent event;
|
|
||||||
volatile int destroyTimer = 0;
|
|
||||||
struct sigaction sig;
|
struct sigaction sig;
|
||||||
volatile int restoreSignal = 0;
|
volatile int restoreSignal = 0;
|
||||||
struct itimerspec duration;
|
struct itimerval duration;
|
||||||
|
volatile int destroyTimer = 0;
|
||||||
int err = 0;
|
int err = 0;
|
||||||
|
|
||||||
*timedOut = 0;
|
*timedOut = 0;
|
||||||
|
@ -201,37 +200,28 @@ timerSysError timerRunWithTimeout(timerDuration d, void (*f)(void *data), void *
|
||||||
return (timerSysError) err;
|
return (timerSysError) err;
|
||||||
restorePrevMask = 1;
|
restorePrevMask = 1;
|
||||||
|
|
||||||
memset(&event, 0, sizeof (struct sigevent));
|
|
||||||
event.sigev_notify = SIGEV_SIGNAL;
|
|
||||||
event.sigev_signo = SIGALRM;
|
|
||||||
event.sigev_value.sival_ptr = &p;
|
|
||||||
errno = 0;
|
|
||||||
if (timer_create(CLOCK_REALTIME, &event, &(p.timer)) != 0) {
|
|
||||||
err = errno;
|
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
destroyTimer = 1;
|
|
||||||
|
|
||||||
if (setjmp(p.retpos) == 0) {
|
if (setjmp(p.retpos) == 0) {
|
||||||
sig.sa_mask = &allsigs;
|
sig.sa_mask = allsigs;
|
||||||
sig.sa_flags = SA_SIGINFO;
|
sig.sa_flags = SA_SIGINFO;
|
||||||
sig.sa_sigaction = onTimeout;
|
sig.sa_sigaction = onTimeout;
|
||||||
errno = 0;
|
errno = 0;
|
||||||
if (sigaction(SIGALRM, &sig, &(p.oldsig)) != 0) {
|
if (sigaction(SIGALRM, &sig, &(p.prevSig)) != 0) {
|
||||||
err = errno;
|
err = errno;
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
restoreSignal = 1;
|
restoreSignal = 1;
|
||||||
|
|
||||||
duration.it_interval.tv_sec = 0;
|
duration.it_interval.tv_sec = 0;
|
||||||
duration.it_interval.tv_nsec = 0;
|
duration.it_interval.tv_usec = 0;
|
||||||
duration.it_value.tv_sec = d / testingNsecPerSec;
|
duration.it_value.tv_sec = d / timerSecond;
|
||||||
duration.it_value.tv_nsec = d % testingNsecPerSec;
|
duration.it_value.tv_usec = (d % timerSecond) / timerMicrosecond;
|
||||||
errno = 0;
|
errno = 0;
|
||||||
if (timer_settimer(p.timer, 0, &duration, NULL) != 0) {
|
if (setitimer(ITIMER_REAL, &duration, &(p.prevDuration)) != 0) {
|
||||||
err = errno;
|
err = errno;
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
destroyTimer = 1;
|
||||||
|
|
||||||
// and fire away
|
// and fire away
|
||||||
err = pthread_sigmask(SIG_UNBLOCK, &sigalrm, NULL);
|
err = pthread_sigmask(SIG_UNBLOCK, &sigalrm, NULL);
|
||||||
if (err != 0)
|
if (err != 0)
|
||||||
|
@ -243,10 +233,10 @@ timerSysError timerRunWithTimeout(timerDuration d, void (*f)(void *data), void *
|
||||||
err = 0;
|
err = 0;
|
||||||
|
|
||||||
out:
|
out:
|
||||||
if (restoreSignal)
|
|
||||||
sigaction(SIGALRM, &(p.oldsig), NULL);
|
|
||||||
if (destroyTimer)
|
if (destroyTimer)
|
||||||
timer_delete(p.timer);
|
setitimer(ITIMER_REAL, &(p.prevDuration), NULL);
|
||||||
|
if (restoreSignal)
|
||||||
|
sigaction(SIGALRM, &(p.prevSig), NULL);
|
||||||
if (restorePrevMask)
|
if (restorePrevMask)
|
||||||
pthread_sigmask(SIG_SETMASK, &prevMask, NULL);
|
pthread_sigmask(SIG_SETMASK, &prevMask, NULL);
|
||||||
teardownNonReentrance();
|
teardownNonReentrance();
|
||||||
|
@ -258,8 +248,8 @@ timerSysError timerSleep(timerDuration d)
|
||||||
struct timespec duration, remaining;
|
struct timespec duration, remaining;
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
duration.tv_sec = d / testingNsecPerSec;
|
duration.tv_sec = d / timerSecond;
|
||||||
duration.tv_nsec = d % testingNsecPerSec;
|
duration.tv_nsec = d % timerSecond;
|
||||||
for (;;) {
|
for (;;) {
|
||||||
errno = 0;
|
errno = 0;
|
||||||
if (nanosleep(&duration, &remaining) == 0)
|
if (nanosleep(&duration, &remaining) == 0)
|
||||||
|
|
Loading…
Reference in New Issue