44
55#define IS32BIT (x ) !((x)+0x80000000ULL>>32)
66
7+ #ifdef __EMSCRIPTEN__
8+ #include <signal.h>
9+ #include <stdio.h>
10+ #include <emscripten/emscripten.h>
11+
12+ // Timeouts can either fire directly from the JS event loop (which calls
13+ // `_emscripten_timeout`), or from `_emscripten_check_timers` (which is called
14+ // from `_emscripten_yield`). In order to be able to check the timers here we
15+ // cache the current timeout and interval for each the 3 types of timer
16+ // (ITIMER_PROF/ITIMER_VIRTUAL/ITIMER_REAL).
17+ static double current_timeout_ms [3 ];
18+ static double current_intervals_ms [3 ];
19+
20+ #define MAX (a ,b ) ((a)>(b)?(a):(b))
21+
22+ int _setitimer_js (int which , double timeout );
23+
24+ void __getitimer (int which , struct itimerval * old , double now )
25+ {
26+ double remaining_ms = MAX (current_timeout_ms [which ] - now , 0 );
27+ old -> it_value .tv_sec = remaining_ms / 1000 ;
28+ old -> it_value .tv_usec = remaining_ms * 1000 ;
29+ old -> it_interval .tv_sec = current_intervals_ms [which ] / 1000 ;
30+ old -> it_interval .tv_usec = current_intervals_ms [which ] * 1000 ;
31+ }
32+
33+ void _emscripten_timeout (int which , double now )
34+ {
35+ int signum = SIGALRM ;
36+ if (which == ITIMER_PROF )
37+ signum = SIGPROF ;
38+ else if (which == ITIMER_VIRTUAL )
39+ signum = SIGVTALRM ;
40+ int next_timeout = current_intervals_ms [which ];
41+ if (next_timeout )
42+ current_timeout_ms [which ] = now + next_timeout ;
43+ else
44+ current_timeout_ms [which ] = 0 ;
45+ _setitimer_js (which , next_timeout );
46+ raise (signum );
47+ }
48+
49+ void _emscripten_check_timers (double now )
50+ {
51+ for (int which = 0 ; which < 3 ; which ++ ) {
52+ if (current_timeout_ms [which ]) {
53+ // Only call out to JS to get the current time if it was not passed in
54+ // *and* we have one or more timers set.
55+ if (!now )
56+ now = emscripten_get_now ();
57+ if (now >= current_timeout_ms [which ])
58+ _emscripten_timeout (which , now );
59+ }
60+ }
61+ }
62+ #endif
63+
764int setitimer (int which , const struct itimerval * restrict new , struct itimerval * restrict old )
865{
66+ #ifdef __EMSCRIPTEN__
67+ if (which > ITIMER_PROF ) return EINVAL ;
68+ double now = emscripten_get_now ();
69+ if (old ) {
70+ __getitimer (which , old , now );
71+ }
72+ if (new -> it_value .tv_sec || new -> it_value .tv_usec ) {
73+ current_timeout_ms [which ] = now + new -> it_value .tv_sec * 1000 + new -> it_value .tv_usec / 1000 ;
74+ current_intervals_ms [which ] = new -> it_interval .tv_sec * 1000 + new -> it_interval .tv_usec / 1000 ;
75+ } else {
76+ current_timeout_ms [which ] = 0 ;
77+ current_intervals_ms [which ] = 0 ;
78+ }
79+ return _setitimer_js (which , new -> it_value .tv_sec * 1000 + new -> it_value .tv_usec / 1000 );
80+ #else
981 if (sizeof (time_t ) > sizeof (long )) {
1082 time_t is = new -> it_interval .tv_sec , vs = new -> it_value .tv_sec ;
1183 long ius = new -> it_interval .tv_usec , vus = new -> it_value .tv_usec ;
@@ -23,4 +95,5 @@ int setitimer(int which, const struct itimerval *restrict new, struct itimerval
2395 return __syscall_ret (r );
2496 }
2597 return syscall (SYS_setitimer , which , new , old );
98+ #endif
2699}
0 commit comments