1 /*
2  * Copyright (c) 2020 Intel Corporation.
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #include <stdbool.h>
8 #include <kernel.h>
9 #include <sys/atomic.h>
10 #include <timing/timing.h>
11 
12 static bool has_inited;
13 static atomic_val_t started_ref;
14 
timing_init(void)15 void timing_init(void)
16 {
17 	if (has_inited) {
18 		return;
19 	}
20 
21 #if defined(CONFIG_BOARD_HAS_TIMING_FUNCTIONS)
22 	board_timing_init();
23 #elif defined(CONFIG_SOC_HAS_TIMING_FUNCTIONS)
24 	soc_timing_init();
25 #else
26 	arch_timing_init();
27 #endif
28 
29 	has_inited = true;
30 }
31 
timing_start(void)32 void timing_start(void)
33 {
34 	if (atomic_inc(&started_ref) != 0) {
35 		return;
36 	}
37 
38 #if defined(CONFIG_BOARD_HAS_TIMING_FUNCTIONS)
39 	board_timing_start();
40 #elif defined(CONFIG_SOC_HAS_TIMING_FUNCTIONS)
41 	soc_timing_start();
42 #else
43 	arch_timing_start();
44 #endif
45 }
46 
timing_stop(void)47 void timing_stop(void)
48 {
49 	atomic_t old_value, new_value;
50 
51 	/* Make sure this does decrement past zero. */
52 	do {
53 		old_value = atomic_get(&started_ref);
54 		if (old_value <= 0) {
55 			break;
56 		}
57 
58 		new_value = old_value - 1;
59 	} while (atomic_cas(&started_ref, old_value, new_value) == 0);
60 
61 	/*
62 	 * new_value may be uninitialized, so use old_value here.
63 	 */
64 	if (old_value > 1) {
65 		return;
66 	}
67 
68 #if defined(CONFIG_BOARD_HAS_TIMING_FUNCTIONS)
69 	board_timing_stop();
70 #elif defined(CONFIG_SOC_HAS_TIMING_FUNCTIONS)
71 	soc_timing_stop();
72 #else
73 	arch_timing_stop();
74 #endif
75 }
76