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_yeild`). In order to be able to check the timers here we
15+ // cache the current timeout and intervale 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+ }
41+ int next_timeout = current_intervals_ms [which ];
42+ if (next_timeout ) {
43+ current_timeout_ms [which ] = now + next_timeout ;
44+ } else {
45+ current_timeout_ms [which ] = 0 ;
46+ }
47+ _setitimer_js (which , next_timeout );
48+ raise (signum );
49+ }
50+
51+ void _emscripten_check_timers (double now )
52+ {
53+ if (!now ) now = emscripten_get_now ();
54+ for (int which = 0 ; which < 3 ; which ++ ) {
55+ if (current_timeout_ms [which ] && now >= current_timeout_ms [which ]) {
56+ _emscripten_timeout (which , now );
57+ }
58+ }
59+ }
60+ #endif
61+
762int setitimer (int which , const struct itimerval * restrict new , struct itimerval * restrict old )
863{
64+ #ifdef __EMSCRIPTEN__
65+ if (which > ITIMER_PROF ) return EINVAL ;
66+ double now = emscripten_get_now ();
67+ if (old ) {
68+ __getitimer (which , old , now );
69+ }
70+ if (new -> it_value .tv_sec || new -> it_value .tv_usec ) {
71+ current_timeout_ms [which ] = now + new -> it_value .tv_sec * 1000 + new -> it_value .tv_usec / 1000 ;
72+ current_intervals_ms [which ] = new -> it_interval .tv_sec * 1000 + new -> it_interval .tv_usec / 1000 ;
73+ } else {
74+ current_timeout_ms [which ] = 0 ;
75+ current_intervals_ms [which ] = 0 ;
76+ }
77+ return _setitimer_js (which , new -> it_value .tv_sec * 1000 + new -> it_value .tv_usec / 1000 );
78+ #else
979 if (sizeof (time_t ) > sizeof (long )) {
1080 time_t is = new -> it_interval .tv_sec , vs = new -> it_value .tv_sec ;
1181 long ius = new -> it_interval .tv_usec , vus = new -> it_value .tv_usec ;
@@ -23,4 +93,5 @@ int setitimer(int which, const struct itimerval *restrict new, struct itimerval
2393 return __syscall_ret (r );
2494 }
2595 return syscall (SYS_setitimer , which , new , old );
96+ #endif
2697}
0 commit comments