ARGOBOTS  dce6e727ffc4ca5b3ffc04cb9517c6689be51ec5
abtu.h
Go to the documentation of this file.
1 /* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */
2 /*
3  * See COPYRIGHT in top-level directory.
4  */
5 
6 #ifndef ABTU_H_INCLUDED
7 #define ABTU_H_INCLUDED
8 
9 #include <stdlib.h>
10 #include <string.h>
11 #include <assert.h>
12 #include "abt_config.h"
13 
14 /* Basic math functions */
15 static inline int ABTU_max_int(int a, int b)
16 {
17  return a > b ? a : b;
18 }
19 
20 static inline int32_t ABTU_max_int32(int32_t a, int32_t b)
21 {
22  return a > b ? a : b;
23 }
24 
25 static inline uint32_t ABTU_max_uint32(uint32_t a, uint32_t b)
26 {
27  return a > b ? a : b;
28 }
29 
30 static inline int64_t ABTU_max_int64(int64_t a, int64_t b)
31 {
32  return a > b ? a : b;
33 }
34 
35 static inline uint64_t ABTU_max_uint64(uint64_t a, uint64_t b)
36 {
37  return a > b ? a : b;
38 }
39 
40 static inline size_t ABTU_max_size(size_t a, size_t b)
41 {
42  return a > b ? a : b;
43 }
44 
45 static inline int ABTU_min_int(int a, int b)
46 {
47  return a < b ? a : b;
48 }
49 
50 static inline int32_t ABTU_min_int32(int32_t a, int32_t b)
51 {
52  return a < b ? a : b;
53 }
54 
55 static inline uint32_t ABTU_min_uint32(uint32_t a, uint32_t b)
56 {
57  return a < b ? a : b;
58 }
59 
60 static inline int64_t ABTU_min_int64(int64_t a, int64_t b)
61 {
62  return a < b ? a : b;
63 }
64 
65 static inline uint64_t ABTU_min_uint64(uint64_t a, uint64_t b)
66 {
67  return a < b ? a : b;
68 }
69 
70 static inline size_t ABTU_min_size(size_t a, size_t b)
71 {
72  return a < b ? a : b;
73 }
74 
75 static inline uint32_t ABTU_roundup_uint32(uint32_t val, uint32_t multiple)
76 {
77  if ((multiple & (multiple - 1)) == 0) {
78  /* If multiple is a power of two. */
79  return (val + multiple - 1) & (~(multiple - 1));
80  } else {
81  return ((val + multiple - 1) / multiple) * multiple;
82  }
83 }
84 
85 static inline uint64_t ABTU_roundup_uint64(uint64_t val, uint64_t multiple)
86 {
87  if ((multiple & (multiple - 1)) == 0) {
88  /* If multiple is a power of two. */
89  return (val + multiple - 1) & (~(multiple - 1));
90  } else {
91  return ((val + multiple - 1) / multiple) * multiple;
92  }
93 }
94 
95 static inline size_t ABTU_roundup_size(size_t val, size_t multiple)
96 {
97  if ((multiple & (multiple - 1)) == 0) {
98  /* If multiple is a power of two. */
99  return (val + multiple - 1) & (~(multiple - 1));
100  } else {
101  return ((val + multiple - 1) / multiple) * multiple;
102  }
103 }
104 
105 static inline void *ABTU_roundup_ptr(void *ptr, size_t multiple)
106 {
107  if ((multiple & (multiple - 1)) == 0) {
108  /* If multiple is a power of two. */
109  return (void *)((((uintptr_t)ptr) + multiple - 1) & (~(multiple - 1)));
110  } else {
111  return (void *)(((((uintptr_t)ptr) + multiple - 1) / multiple) *
112  multiple);
113  }
114 }
115 
116 /* Utility feature */
117 
118 #ifdef HAVE___BUILTIN_EXPECT
119 #define ABTU_likely(cond) __builtin_expect(!!(cond), 1)
120 #define ABTU_unlikely(cond) __builtin_expect(!!(cond), 0)
121 #else
122 #define ABTU_likely(cond) (cond)
123 #define ABTU_unlikely(cond) (cond)
124 #endif
125 
126 #ifdef HAVE_FUNC_ATTRIBUTE_NORETURN
127 #define ABTU_noreturn __attribute__((noreturn))
128 #else
129 #define ABTU_noreturn
130 #endif
131 
132 #ifdef HAVE___BUILTIN_UNREACHABLE
133 #define ABTU_unreachable() __builtin_unreachable()
134 #else
135 /* abort is better than entering an unknown area. First assert(0), which shows
136  * something if assert() is enabled. If assert() is disabled, let's abort(). */
137 static inline ABTU_noreturn void ABTU_unreachable(void)
138 {
139  assert(0);
140  abort();
141 }
142 #endif
143 
144 #ifdef ABT_CONFIG_HAVE_ALIGNOF_GCC
145 #define ABTU_alignof(type) (__alignof__(type))
146 #elif defined(ABT_CONFIG_HAVE_ALIGNOF_C11)
147 #define ABTU_alignof(type) (alignof(type))
148 #else
149 #define ABTU_alignof(type) 16 /* 16 bytes would be a good guess. */
150 #endif
151 #define ABTU_MAX_ALIGNMENT \
152  ABTU_max_size(ABTU_alignof(long double), ABTU_alignof(long long))
153 
154 #ifdef HAVE_FUNC_ATTRIBUTE_WARN_UNUSED_RESULT
155 #define ABTU_ret_err __attribute__((warn_unused_result))
156 #else
157 #define ABTU_ret_err
158 #endif
159 
160 /*
161  * An attribute to hint an alignment of a member variable.
162  * Usage:
163  * struct X {
164  * void *obj_1;
165  * ABTU_align_member_var(64)
166  * void *obj_2;
167  * };
168  */
169 #ifndef __SUNPRO_C
170 #define ABTU_align_member_var(size) __attribute__((aligned(size)))
171 #else
172 /* Sun Studio does not support it. */
173 #define ABTU_align_member_var(size)
174 #endif
175 
176 /*
177  * An attribute to suppress address sanitizer warning.
178  */
179 #if defined(__GNUC__) && defined(__SANITIZE_ADDRESS__)
180 /*
181  * Older GCC cannot combine no_sanitize_address + always_inline (e.g., builtin
182  * memcpy on some platforms), which causes *a compilation error*. Let's accept
183  * false-positive warning if used GCC is old. This issue seems fixed between
184  * GCC 7.4.0 and GCC 8.3.0 as far as I checked.
185  * https://gcc.gnu.org/bugzilla/show_bug.cgi?id=59600
186  */
187 #if __GNUC__ >= 8
188 #define ABTU_no_sanitize_address __attribute__((no_sanitize_address))
189 #endif
190 #elif __clang__
191 #if defined(__has_feature)
192 #if __has_feature(address_sanitizer)
193 #if __clang_major__ >= 4 || (__clang_major__ >= 3 && __clang_minor__ >= 7)
194 /* >= Clang 3.7.0 */
195 #define ABTU_no_sanitize_address __attribute__((no_sanitize("address")))
196 #elif (__clang_major__ >= 3 && __clang_minor__ >= 3)
197 /* >= Clang 3.3.0 */
198 #define ABTU_no_sanitize_address __attribute__((no_sanitize_address))
199 #elif (__clang_major__ >= 3 && __clang_minor__ >= 1)
200 /* >= Clang 3.1.0 */
201 #define ABTU_no_sanitize_address __attribute__((no_address_safety_analysis))
202 #else /* Too old clang. */
203 #define ABTU_no_sanitize_address
204 #endif
205 #endif /* __has_feature(address_sanitizer) */
206 #endif /* defined(__has_feature) */
207 #endif
208 
209 #ifndef ABTU_no_sanitize_address
210 /* We do not support other address sanitizers. */
211 #define ABTU_no_sanitize_address
212 #endif
213 
214 /* Utility Functions */
215 
216 ABTU_ret_err static inline int ABTU_memalign(size_t alignment, size_t size,
217  void **p_ptr)
218 {
219  void *ptr;
220  int ret = posix_memalign(&ptr, alignment, size);
221  if (ABTI_IS_ERROR_CHECK_ENABLED && ret != 0) {
222  return ABT_ERR_MEM;
223  }
224  *p_ptr = ptr;
225  return ABT_SUCCESS;
226 }
227 
228 static inline void ABTU_free(void *ptr)
229 {
230  free(ptr);
231 }
232 
233 #ifdef ABT_CONFIG_USE_ALIGNED_ALLOC
234 
235 ABTU_ret_err static inline int ABTU_malloc(size_t size, void **p_ptr)
236 {
237  /* Round up to the smallest multiple of ABT_CONFIG_STATIC_CACHELINE_SIZE
238  * which is greater than or equal to size in order to avoid any
239  * false-sharing. */
241  return ABTU_memalign(ABT_CONFIG_STATIC_CACHELINE_SIZE, size, p_ptr);
242 }
243 
244 ABTU_ret_err static inline int ABTU_calloc(size_t num, size_t size,
245  void **p_ptr)
246 {
247  void *ptr;
248  int ret = ABTU_malloc(num * size, &ptr);
250  return ABT_ERR_MEM;
251  }
252  memset(ptr, 0, num * size);
253  *p_ptr = ptr;
254  return ABT_SUCCESS;
255 }
256 
257 ABTU_ret_err static inline int ABTU_realloc(size_t old_size, size_t new_size,
258  void **p_ptr)
259 {
260  void *new_ptr, *old_ptr = *p_ptr;
261  int ret = ABTU_malloc(new_size, &new_ptr);
263  return ABT_ERR_MEM;
264  }
265  memcpy(new_ptr, old_ptr, ABTU_min_size(old_size, new_size));
266  ABTU_free(old_ptr);
267  *p_ptr = new_ptr;
268  return ABT_SUCCESS;
269 }
270 
271 #else /* ABT_CONFIG_USE_ALIGNED_ALLOC */
272 
273 ABTU_ret_err static inline int ABTU_malloc(size_t size, void **p_ptr)
274 {
275  void *ptr = malloc(size);
276  if (ABTI_IS_ERROR_CHECK_ENABLED && ptr == NULL) {
277  return ABT_ERR_MEM;
278  }
279  *p_ptr = ptr;
280  return ABT_SUCCESS;
281 }
282 
283 ABTU_ret_err static inline int ABTU_calloc(size_t num, size_t size,
284  void **p_ptr)
285 {
286  void *ptr = calloc(num, size);
287  if (ABTI_IS_ERROR_CHECK_ENABLED && ptr == NULL) {
288  return ABT_ERR_MEM;
289  }
290  *p_ptr = ptr;
291  return ABT_SUCCESS;
292 }
293 
294 ABTU_ret_err static inline int ABTU_realloc(size_t old_size, size_t new_size,
295  void **p_ptr)
296 {
297  (void)old_size;
298  void *ptr = realloc(*p_ptr, new_size);
299  if (ABTI_IS_ERROR_CHECK_ENABLED && ptr == NULL) {
300  return ABT_ERR_MEM;
301  }
302  *p_ptr = ptr;
303  return ABT_SUCCESS;
304 }
305 
306 #endif /* !ABT_CONFIG_USE_ALIGNED_ALLOC */
307 
309  ABTU_MEM_LARGEPAGE_MALLOC, /* ABTU_malloc(). */
310  ABTU_MEM_LARGEPAGE_MEMALIGN, /* memalign() */
311  ABTU_MEM_LARGEPAGE_MMAP, /* normal private memory obtained by mmap() */
312  ABTU_MEM_LARGEPAGE_MMAP_HUGEPAGE, /* hugepage obtained by mmap() */
314 
315 /* Returns 1 if a given large page type is supported. */
316 int ABTU_is_supported_largepage_type(size_t size, size_t alignment_hint,
317  ABTU_MEM_LARGEPAGE_TYPE requested);
318 ABTU_ret_err int
319 ABTU_alloc_largepage(size_t size, size_t alignment_hint,
320  const ABTU_MEM_LARGEPAGE_TYPE *requested_types,
321  int num_requested_types, ABTU_MEM_LARGEPAGE_TYPE *p_actual,
322  void **p_ptr);
323 void ABTU_free_largepage(void *ptr, size_t size, ABTU_MEM_LARGEPAGE_TYPE type);
324 
325 /* An error is ignored even if mprotect call fails.
326  * PROT_NONE is set if protect == ABT_TRUE.
327  * (PROT_READ | PROT_WRITE) is permitted if if protect == ABT_FALSE. */
328 ABTU_ret_err int ABTU_mprotect(void *addr, size_t size, ABT_bool protect);
329 
330 /* String-to-integer functions. */
331 ABTU_ret_err int ABTU_atoi(const char *str, int *p_val, ABT_bool *p_overflow);
332 ABTU_ret_err int ABTU_atoui32(const char *str, uint32_t *p_val,
333  ABT_bool *p_overflow);
334 ABTU_ret_err int ABTU_atoui64(const char *str, uint64_t *p_val,
335  ABT_bool *p_overflow);
336 ABTU_ret_err int ABTU_atosz(const char *str, size_t *p_val,
337  ABT_bool *p_overflow);
338 
339 /* Simple hash table */
340 
341 typedef struct ABTU_hashtable_element {
342  int key;
344  char *data;
346 
347 typedef struct ABTU_hashtable {
348  size_t num_entries;
349  size_t data_size;
351 
352 ABTU_ret_err int ABTU_hashtable_create(size_t num_entries, size_t data_size,
353  ABTU_hashtable **pp_hashtable);
354 void ABTU_hashtable_free(ABTU_hashtable *p_hashtable);
355 void ABTU_hashtable_get(const ABTU_hashtable *p_hashtable, int key, void *data,
356  int *found);
357 ABTU_ret_err int ABTU_hashtable_set(ABTU_hashtable *p_hashtable, int key,
358  const void *data, int *overwritten);
359 void ABTU_hashtable_delete(ABTU_hashtable *p_hashtable, int key, int *deleted);
360 
361 #endif /* ABTU_H_INCLUDED */
ABTU_max_size
static size_t ABTU_max_size(size_t a, size_t b)
Definition: abtu.h:40
ABTU_min_int
static int ABTU_min_int(int a, int b)
Definition: abtu.h:45
ABTU_hashtable_create
ABTU_ret_err int ABTU_hashtable_create(size_t num_entries, size_t data_size, ABTU_hashtable **pp_hashtable)
Definition: hashtable.c:21
ABT_bool
int ABT_bool
Boolean type.
Definition: abt.h:1043
ABTU_max_int64
static int64_t ABTU_max_int64(int64_t a, int64_t b)
Definition: abtu.h:30
ABTU_max_uint64
static uint64_t ABTU_max_uint64(uint64_t a, uint64_t b)
Definition: abtu.h:35
ABTU_realloc
static ABTU_ret_err int ABTU_realloc(size_t old_size, size_t new_size, void **p_ptr)
Definition: abtu.h:257
ABTU_max_int
static int ABTU_max_int(int a, int b)
Definition: abtu.h:15
ABTU_is_supported_largepage_type
int ABTU_is_supported_largepage_type(size_t size, size_t alignment_hint, ABTU_MEM_LARGEPAGE_TYPE requested)
Definition: largepage.c:59
ABTU_roundup_ptr
static void * ABTU_roundup_ptr(void *ptr, size_t multiple)
Definition: abtu.h:105
ABTU_roundup_size
static size_t ABTU_roundup_size(size_t val, size_t multiple)
Definition: abtu.h:95
data
Definition: fifo.c:45
ABTU_noreturn
#define ABTU_noreturn
Definition: abtu.h:127
ABTU_min_size
static size_t ABTU_min_size(size_t a, size_t b)
Definition: abtu.h:70
ABTU_memalign
static ABTU_ret_err int ABTU_memalign(size_t alignment, size_t size, void **p_ptr)
Definition: abtu.h:216
ABTU_alloc_largepage
ABTU_ret_err int ABTU_alloc_largepage(size_t size, size_t alignment_hint, const ABTU_MEM_LARGEPAGE_TYPE *requested_types, int num_requested_types, ABTU_MEM_LARGEPAGE_TYPE *p_actual, void **p_ptr)
Definition: largepage.c:90
ABTU_free_largepage
void ABTU_free_largepage(void *ptr, size_t size, ABTU_MEM_LARGEPAGE_TYPE type)
Definition: largepage.c:132
ABTU_MEM_LARGEPAGE_MMAP
@ ABTU_MEM_LARGEPAGE_MMAP
Definition: abtu.h:311
ABTU_hashtable_get
void ABTU_hashtable_get(const ABTU_hashtable *p_hashtable, int key, void *data, int *found)
Definition: hashtable.c:56
ABTU_max_int32
static int32_t ABTU_max_int32(int32_t a, int32_t b)
Definition: abtu.h:20
ABTU_mprotect
ABTU_ret_err int ABTU_mprotect(void *addr, size_t size, ABT_bool protect)
Definition: mprotect.c:9
ABTU_min_uint64
static uint64_t ABTU_min_uint64(uint64_t a, uint64_t b)
Definition: abtu.h:65
ABTI_IS_ERROR_CHECK_ENABLED
#define ABTI_IS_ERROR_CHECK_ENABLED
Definition: abti.h:20
ABTU_hashtable_element::data
char * data
Definition: abtu.h:344
ABTU_hashtable_element
struct ABTU_hashtable_element ABTU_hashtable_element
ABTU_max_uint32
static uint32_t ABTU_max_uint32(uint32_t a, uint32_t b)
Definition: abtu.h:25
ABTU_unreachable
#define ABTU_unreachable()
Definition: abtu.h:133
ABTU_atoui64
ABTU_ret_err int ABTU_atoui64(const char *str, uint64_t *p_val, ABT_bool *p_overflow)
Definition: atoi.c:65
ABTU_MEM_LARGEPAGE_MMAP_HUGEPAGE
@ ABTU_MEM_LARGEPAGE_MMAP_HUGEPAGE
Definition: abtu.h:312
ABTU_hashtable_delete
void ABTU_hashtable_delete(ABTU_hashtable *p_hashtable, int key, int *deleted)
Definition: hashtable.c:144
ABTU_hashtable::num_entries
size_t num_entries
Definition: abtu.h:348
ABTU_malloc
static ABTU_ret_err int ABTU_malloc(size_t size, void **p_ptr)
Definition: abtu.h:235
ABTU_roundup_uint64
static uint64_t ABTU_roundup_uint64(uint64_t val, uint64_t multiple)
Definition: abtu.h:85
ABT_ERR_MEM
#define ABT_ERR_MEM
Error code: Memory allocation failure.
Definition: abt.h:104
abt_config.h
ABTU_hashtable
struct ABTU_hashtable ABTU_hashtable
ABTU_calloc
static ABTU_ret_err int ABTU_calloc(size_t num, size_t size, void **p_ptr)
Definition: abtu.h:244
ABTU_MEM_LARGEPAGE_TYPE
ABTU_MEM_LARGEPAGE_TYPE
Definition: abtu.h:308
ABT_CONFIG_STATIC_CACHELINE_SIZE
#define ABT_CONFIG_STATIC_CACHELINE_SIZE
Definition: abt_config.h:81
ABT_SUCCESS
#define ABT_SUCCESS
Error code: the routine returns successfully.
Definition: abt.h:92
ABTU_atoui32
ABTU_ret_err int ABTU_atoui32(const char *str, uint32_t *p_val, ABT_bool *p_overflow)
Definition: atoi.c:39
ABTU_hashtable_element::key
int key
Definition: abtu.h:342
ABTU_MEM_LARGEPAGE_MALLOC
@ ABTU_MEM_LARGEPAGE_MALLOC
Definition: abtu.h:309
ABTU_ret_err
#define ABTU_ret_err
Definition: abtu.h:155
ABTU_min_int32
static int32_t ABTU_min_int32(int32_t a, int32_t b)
Definition: abtu.h:50
ABTU_atoi
ABTU_ret_err int ABTU_atoi(const char *str, int *p_val, ABT_bool *p_overflow)
Definition: atoi.c:11
ABTU_hashtable_element
Definition: abtu.h:341
ABTU_free
static void ABTU_free(void *ptr)
Definition: abtu.h:228
ABTU_hashtable_free
void ABTU_hashtable_free(ABTU_hashtable *p_hashtable)
Definition: hashtable.c:42
ABTU_hashtable_set
ABTU_ret_err int ABTU_hashtable_set(ABTU_hashtable *p_hashtable, int key, const void *data, int *overwritten)
Definition: hashtable.c:91
ABTU_hashtable_element::p_next
struct ABTU_hashtable_element * p_next
Definition: abtu.h:343
ABTU_MEM_LARGEPAGE_MEMALIGN
@ ABTU_MEM_LARGEPAGE_MEMALIGN
Definition: abtu.h:310
ABTU_hashtable::data_size
size_t data_size
Definition: abtu.h:349
ABTU_atosz
ABTU_ret_err int ABTU_atosz(const char *str, size_t *p_val, ABT_bool *p_overflow)
Definition: atoi.c:85
ABTU_min_int64
static int64_t ABTU_min_int64(int64_t a, int64_t b)
Definition: abtu.h:60
ABTU_min_uint32
static uint32_t ABTU_min_uint32(uint32_t a, uint32_t b)
Definition: abtu.h:55
ABTU_hashtable
Definition: abtu.h:347
ABTU_roundup_uint32
static uint32_t ABTU_roundup_uint32(uint32_t val, uint32_t multiple)
Definition: abtu.h:75