fix: handle EINTR correctly in get_cpu_mask_from_sysfs
[librseq.git] / src / rseq-utils.h
1 // SPDX-License-Identifier: MIT
2 // SPDX-FileCopyrightText: 2024 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
3
4 #ifndef _RSEQ_COMMON_UTILS_H
5 #define _RSEQ_COMMON_UTILS_H
6
7 #include <stdbool.h>
8 #include <stdint.h>
9
10 #define RSEQ_ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]))
11
12 #define __rseq_align_mask(v, mask) (((v) + (mask)) & ~(mask))
13 #define rseq_align(v, align) __rseq_align_mask(v, (__typeof__(v)) (align) - 1)
14
15 static inline
16 unsigned int rseq_fls_u64(uint64_t x)
17 {
18 unsigned int r = 64;
19
20 if (!x)
21 return 0;
22
23 if (!(x & 0xFFFFFFFF00000000ULL)) {
24 x <<= 32;
25 r -= 32;
26 }
27 if (!(x & 0xFFFF000000000000ULL)) {
28 x <<= 16;
29 r -= 16;
30 }
31 if (!(x & 0xFF00000000000000ULL)) {
32 x <<= 8;
33 r -= 8;
34 }
35 if (!(x & 0xF000000000000000ULL)) {
36 x <<= 4;
37 r -= 4;
38 }
39 if (!(x & 0xC000000000000000ULL)) {
40 x <<= 2;
41 r -= 2;
42 }
43 if (!(x & 0x8000000000000000ULL)) {
44 x <<= 1;
45 r -= 1;
46 }
47 return r;
48 }
49
50 static inline
51 unsigned int rseq_fls_u32(uint32_t x)
52 {
53 unsigned int r = 32;
54
55 if (!x)
56 return 0;
57 if (!(x & 0xFFFF0000U)) {
58 x <<= 16;
59 r -= 16;
60 }
61 if (!(x & 0xFF000000U)) {
62 x <<= 8;
63 r -= 8;
64 }
65 if (!(x & 0xF0000000U)) {
66 x <<= 4;
67 r -= 4;
68 }
69 if (!(x & 0xC0000000U)) {
70 x <<= 2;
71 r -= 2;
72 }
73 if (!(x & 0x80000000U)) {
74 x <<= 1;
75 r -= 1;
76 }
77 return r;
78 }
79
80 static inline
81 unsigned int rseq_fls_ulong(unsigned long x)
82 {
83 #if RSEQ_BITS_PER_LONG == 32
84 return rseq_fls_u32(x);
85 #else
86 return rseq_fls_u64(x);
87 #endif
88 }
89
90 /*
91 * Return the minimum order for which x <= (1UL << order).
92 * Return -1 if x is 0.
93 */
94 static inline
95 int rseq_get_count_order_ulong(unsigned long x)
96 {
97 if (!x)
98 return -1;
99
100 return rseq_fls_ulong(x - 1);
101 }
102
103 #define RSEQ_DEFAULT_PAGE_SIZE 4096
104
105 static inline
106 unsigned long rseq_get_page_len(void)
107 {
108 long page_len = sysconf(_SC_PAGE_SIZE);
109
110 if (page_len < 0)
111 page_len = RSEQ_DEFAULT_PAGE_SIZE;
112 return (unsigned long) page_len;
113 }
114
115 static inline
116 int rseq_hweight_ulong(unsigned long v)
117 {
118 return __builtin_popcountl(v);
119 }
120
121 static inline
122 bool is_pow2(uint64_t x)
123 {
124 return !(x & (x - 1));
125 }
126
127 /*
128 * Calculate offset needed to align p on alignment towards higher
129 * addresses. Alignment must be a power of 2
130 */
131 static inline
132 off_t offset_align(uintptr_t p, size_t alignment)
133 {
134 return (alignment - p) & (alignment - 1);
135 }
136
137 #endif /* _RSEQ_COMMON_UTILS_H */
This page took 0.039545 seconds and 4 git commands to generate.