cpp-common/bt2c/fmt.hpp: use `wise_enum::string_type` in `EnableIfIsWiseEnum` definition
[babeltrace.git] / src / lib / trace-ir / utils.h
1 /*
2 * SPDX-License-Identifier: MIT
3 *
4 * Copyright 2017-2018 Philippe Proulx <pproulx@efficios.com>
5 */
6
7 #ifndef BABELTRACE_TRACE_IR_UTILS_INTERNAL_H
8 #define BABELTRACE_TRACE_IR_UTILS_INTERNAL_H
9
10 #include <babeltrace2/trace-ir/field-class.h>
11 #include <stdbool.h>
12 #include <stdint.h>
13
14 #include "clock-class.h"
15
16 struct search_query {
17 gpointer value;
18 int found;
19 };
20
21 static inline
22 uint64_t bt_util_ns_from_value(uint64_t frequency, uint64_t value_cycles)
23 {
24 uint64_t ns;
25
26 if (frequency == UINT64_C(1000000000)) {
27 ns = value_cycles;
28 } else {
29 double dblres = ((1e9 * (double) value_cycles) / (double) frequency);
30
31 if (dblres >= (double) UINT64_MAX) {
32 /* Overflows uint64_t */
33 ns = UINT64_C(-1);
34 } else {
35 ns = (uint64_t) dblres;
36 }
37 }
38
39 return ns;
40 }
41
42 static inline
43 bool bt_util_get_base_offset_ns(int64_t offset_seconds, uint64_t offset_cycles,
44 uint64_t frequency, int64_t *base_offset_ns)
45 {
46 bool overflows = false;
47 uint64_t offset_cycles_ns;
48
49 BT_ASSERT_DBG(base_offset_ns);
50
51 /* Initialize nanosecond timestamp to clock's offset in seconds */
52 if (offset_seconds <= (INT64_MIN / INT64_C(1000000000) - 1) ||
53 offset_seconds >= (INT64_MAX / INT64_C(1000000000)) - 1) {
54 /*
55 * Overflow: offset in seconds converted to nanoseconds
56 * is outside the int64_t range. We also subtract 1 here
57 * to leave "space" for the offset in cycles converted
58 * to nanoseconds (which is always less than 1 second by
59 * contract).
60 */
61 overflows = true;
62 goto end;
63 }
64
65 /* Offset (seconds) to nanoseconds */
66 *base_offset_ns = offset_seconds * INT64_C(1000000000);
67
68 /* Add offset in cycles */
69 BT_ASSERT_DBG(offset_cycles < frequency);
70 offset_cycles_ns = bt_util_ns_from_value(frequency,
71 offset_cycles);
72 BT_ASSERT_DBG(offset_cycles_ns < 1000000000);
73 *base_offset_ns += (int64_t) offset_cycles_ns;
74
75 end:
76 return overflows;
77 }
78
79 static inline
80 int bt_util_ns_from_origin_inline(int64_t base_offset_ns,
81 uint64_t frequency, uint64_t value, int64_t *ns_from_origin)
82 {
83 int ret = 0;
84 uint64_t value_ns_unsigned;
85 int64_t value_ns_signed;
86
87 /* Initialize to clock class's base offset */
88 *ns_from_origin = base_offset_ns;
89
90 /* Add given value in cycles */
91 value_ns_unsigned = bt_util_ns_from_value(frequency, value);
92 if (value_ns_unsigned >= (uint64_t) INT64_MAX) {
93 /*
94 * FIXME: `value_ns_unsigned` could be greater than
95 * `INT64_MAX` in fact: in this case, we need to
96 * subtract `INT64_MAX` from `value_ns_unsigned`, make
97 * sure that the difference is less than `INT64_MAX`,
98 * and try to add them one after the other to
99 * `*ns_from_origin`.
100 */
101 ret = -1;
102 goto end;
103 }
104
105 value_ns_signed = (int64_t) value_ns_unsigned;
106 BT_ASSERT_DBG(value_ns_signed >= 0);
107
108 if (*ns_from_origin <= 0) {
109 goto add_value;
110 }
111
112 if (value_ns_signed > INT64_MAX - *ns_from_origin) {
113 ret = -1;
114 goto end;
115 }
116
117 add_value:
118 *ns_from_origin += value_ns_signed;
119
120 end:
121 return ret;
122 }
123
124 static inline
125 int bt_util_ns_from_origin_clock_class(const struct bt_clock_class *clock_class,
126 uint64_t value, int64_t *ns_from_origin)
127 {
128 int ret = 0;
129
130 if (clock_class->base_offset.overflows) {
131 ret = -1;
132 goto end;
133 }
134
135 ret = bt_util_ns_from_origin_inline(clock_class->base_offset.value_ns,
136 clock_class->frequency, value, ns_from_origin);
137
138 end:
139 return ret;
140 }
141
142 static inline
143 bool bt_util_value_is_in_range_signed(uint64_t size, int64_t value)
144 {
145 int64_t min_value = UINT64_C(-1) << (size - 1);
146 int64_t max_value = (UINT64_C(1) << (size - 1)) - 1;
147 return value >= min_value && value <= max_value;
148 }
149
150 static inline
151 bool bt_util_value_is_in_range_unsigned(unsigned int size, uint64_t value)
152 {
153 uint64_t max_value = (size == 64) ? UINT64_MAX :
154 (UINT64_C(1) << size) - 1;
155 return value <= max_value;
156 }
157
158 #endif /* BABELTRACE_TRACE_IR_UTILS_INTERNAL_H */
This page took 0.033028 seconds and 4 git commands to generate.