1 /*
2 * %CopyrightBegin%
3 *
4 * Copyright Ericsson AB 2015-2018. All Rights Reserved.
5 *
6 * Licensed under the Apache License, Version 2.0 (the "License");
7 * you may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at
9 *
10 * http://www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
17 *
18 * %CopyrightEnd%
19 */
20
21 #ifdef HAVE_CONFIG_H
22 # include "config.h"
23 #endif
24 #include "erl_os_monotonic_time_extender.h"
25
26
os_monotonic_time_extender(void * vstatep)27 static void *os_monotonic_time_extender(void *vstatep)
28 {
29 ErtsOsMonotonicTimeExtendState *state = (ErtsOsMonotonicTimeExtendState *) vstatep;
30 long sleep_time = state->check_interval*1000;
31 Uint32 (*raw_os_mtime)(void) = state->raw_os_monotonic_time;
32 Uint32 last_msb = 0;
33
34 while (1) {
35 Uint32 msb = (*raw_os_mtime)() & (((Uint32) 1) << 31);
36
37 if (msb != last_msb) {
38 int ix = ((int) (last_msb >> 31)) & 1;
39 Uint32 xtnd = (Uint32) erts_atomic32_read_nob(&state->extend[ix]);
40 erts_atomic32_set_nob(&state->extend[ix], (erts_aint32_t) (xtnd + 1));
41 last_msb = msb;
42 }
43 erts_milli_sleep(sleep_time);
44 }
45
46 erts_exit(ERTS_ABORT_EXIT, "os_monotonic_time_extender thread terminating");
47 return NULL;
48 }
49
50 static erts_tid_t os_monotonic_extender_tid;
51
52 void
erts_init_os_monotonic_time_extender(ErtsOsMonotonicTimeExtendState * statep,Uint32 (* raw_os_monotonic_time)(void),int check_seconds)53 erts_init_os_monotonic_time_extender(ErtsOsMonotonicTimeExtendState *statep,
54 Uint32 (*raw_os_monotonic_time)(void),
55 int check_seconds)
56 {
57 statep->raw_os_monotonic_time = raw_os_monotonic_time;
58 erts_atomic32_init_nob(&statep->extend[0], (erts_aint32_t) 0);
59 erts_atomic32_init_nob(&statep->extend[1], (erts_aint32_t) 0);
60 statep->check_interval = check_seconds;
61
62 }
63
64 void
erts_late_init_os_monotonic_time_extender(ErtsOsMonotonicTimeExtendState * statep)65 erts_late_init_os_monotonic_time_extender(ErtsOsMonotonicTimeExtendState *statep)
66 {
67 erts_thr_opts_t thr_opts = ERTS_THR_OPTS_DEFAULT_INITER;
68 thr_opts.detached = 1;
69 thr_opts.suggested_stack_size = 4;
70
71 #if 0
72 thr_opts.name = "os_monotonic_time_extender";
73 #endif
74
75 erts_thr_create(&os_monotonic_extender_tid,
76 os_monotonic_time_extender,
77 (void*) statep,
78 &thr_opts);
79 }
80