summaryrefslogtreecommitdiff
path: root/rts/posix/Itimer.c
diff options
context:
space:
mode:
Diffstat (limited to 'rts/posix/Itimer.c')
-rw-r--r--rts/posix/Itimer.c55
1 files changed, 50 insertions, 5 deletions
diff --git a/rts/posix/Itimer.c b/rts/posix/Itimer.c
index b99ff8970b..4bcc3a1c2e 100644
--- a/rts/posix/Itimer.c
+++ b/rts/posix/Itimer.c
@@ -45,6 +45,20 @@
#include <string.h>
/*
+ * timer_create doesn't exist and setitimer doesn't fire on iOS, so we're using
+ * a pthreads-based implementation. It may be to do with interference with the
+ * signals of the debugger. Revisit. See #7723.
+ */
+#if defined(ios_HOST_OS)
+#define USE_PTHREAD_FOR_ITIMER
+#endif
+
+#if defined(USE_PTHREAD_FOR_ITIMER)
+#include <pthread.h>
+#include <unistd.h>
+#endif
+
+/*
* We use a realtime timer by default. I found this much more
* reliable than a CPU timer:
*
@@ -107,6 +121,7 @@ static timer_t timer;
static Time itimer_interval = DEFAULT_TICK_INTERVAL;
+#if !defined(USE_PTHREAD_FOR_ITIMER)
static void install_vtalrm_handler(TickProc handle_tick)
{
struct sigaction action;
@@ -132,13 +147,33 @@ static void install_vtalrm_handler(TickProc handle_tick)
stg_exit(EXIT_FAILURE);
}
}
+#endif
+
+#if defined(USE_PTHREAD_FOR_ITIMER)
+static volatile int itimer_enabled;
+static void *itimer_thread_func(void *_handle_tick)
+{
+ TickProc handle_tick = _handle_tick;
+ while (1) {
+ usleep(TimeToUS(itimer_interval));
+ switch (itimer_enabled) {
+ case 1: handle_tick(0); break;
+ case 2: itimer_enabled = 0;
+ }
+ }
+ return NULL;
+}
+#endif
void
initTicker (Time interval, TickProc handle_tick)
{
itimer_interval = interval;
-#if defined(USE_TIMER_CREATE)
+#if defined(USE_PTHREAD_FOR_ITIMER)
+ pthread_t tid;
+ pthread_create(&tid, NULL, itimer_thread_func, (void*)handle_tick);
+#elif defined(USE_TIMER_CREATE)
{
struct sigevent ev;
@@ -153,15 +188,18 @@ initTicker (Time interval, TickProc handle_tick)
stg_exit(EXIT_FAILURE);
}
}
-#endif
-
install_vtalrm_handler(handle_tick);
+#else
+ install_vtalrm_handler(handle_tick);
+#endif
}
void
startTicker(void)
{
-#if defined(USE_TIMER_CREATE)
+#if defined(USE_PTHREAD_FOR_ITIMER)
+ itimer_enabled = 1;
+#elif defined(USE_TIMER_CREATE)
{
struct itimerspec it;
@@ -193,7 +231,14 @@ startTicker(void)
void
stopTicker(void)
{
-#if defined(USE_TIMER_CREATE)
+#if defined(USE_PTHREAD_FOR_ITIMER)
+ if (itimer_enabled == 1) {
+ itimer_enabled = 2;
+ /* Wait for the thread to confirm it won't generate another tick. */
+ while (itimer_enabled != 0)
+ sched_yield();
+ }
+#elif defined(USE_TIMER_CREATE)
struct itimerspec it;
it.it_value.tv_sec = 0;