mirror of
https://github.com/JakeHillion/drgn.git
synced 2024-12-23 01:33:06 +00:00
761da83ddd
min() and max() from the Linux kernel go through the trouble of resulting in a constant expression if the arguments are constant expressions, but they can't be used outside of a function due to their use of ({ }). This means that they can't be used for, e.g., enumerators or global arrays. Let's simplify min() and max() and instead add explicit min_iconst() and max_iconst() macros that can be used everywhere that an integer constant expression is required. We can then use it in hash_table.h. While we're here, let's split these into their own header file and document them better. Signed-off-by: Omar Sandoval <osandov@osandov.com>
94 lines
2.5 KiB
C
94 lines
2.5 KiB
C
// Copyright (c) Facebook, Inc. and its affiliates.
|
|
// SPDX-License-Identifier: GPL-3.0+
|
|
|
|
/**
|
|
* @file
|
|
*
|
|
* Miscellanous utility functions.
|
|
*
|
|
* Several of these are taken from the Linux kernel source.
|
|
*/
|
|
|
|
#ifndef DRGN_UTIL_H
|
|
#define DRGN_UTIL_H
|
|
|
|
#include <assert.h>
|
|
#include <errno.h>
|
|
#include <stdbool.h>
|
|
#include <stdint.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
|
|
#ifndef LIBDRGN_PUBLIC
|
|
#define LIBDRGN_PUBLIC __attribute__((visibility("default")))
|
|
#endif
|
|
|
|
#ifdef NDEBUG
|
|
#define UNREACHABLE() __builtin_unreachable()
|
|
#else
|
|
#define UNREACHABLE() assert(!"reachable")
|
|
#endif
|
|
|
|
#define likely(x) __builtin_expect(!!(x), 1)
|
|
#define unlikely(x) __builtin_expect(!!(x), 0)
|
|
|
|
#if defined(__GNUC__) && !defined(__clang__) && !defined(__INTEL_COMPILER)
|
|
#define __compiletime_error(message) __attribute__((__error__(message)))
|
|
#else
|
|
#define __compiletime_error(message)
|
|
#endif
|
|
#ifdef __OPTIMIZE__
|
|
# define __compiletime_assert(condition, msg, prefix, suffix) \
|
|
do { \
|
|
extern void prefix ## suffix(void) __compiletime_error(msg); \
|
|
if (!(condition)) \
|
|
prefix ## suffix(); \
|
|
} while (0)
|
|
#else
|
|
# define __compiletime_assert(condition, msg, prefix, suffix) do { } while (0)
|
|
#endif
|
|
#define _compiletime_assert(condition, msg, prefix, suffix) \
|
|
__compiletime_assert(condition, msg, prefix, suffix)
|
|
#define compiletime_assert(condition, msg) \
|
|
_compiletime_assert(condition, msg, __compiletime_assert_, __LINE__)
|
|
|
|
#define BUILD_BUG_ON_ZERO(e) (sizeof(struct { int:(-!!(e)); }))
|
|
#define BUILD_BUG_ON_MSG(cond, msg) compiletime_assert(!(cond), msg)
|
|
|
|
#define __same_type(a, b) __builtin_types_compatible_p(typeof(a), typeof(b))
|
|
|
|
#define __must_be_array(a) BUILD_BUG_ON_ZERO(__same_type((a), &(a)[0]))
|
|
#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]) + __must_be_array(arr))
|
|
|
|
#define container_of(ptr, type, member) ({ \
|
|
void *__mptr = (void *)(ptr); \
|
|
BUILD_BUG_ON_MSG(!__same_type(*(ptr), ((type *)0)->member) && \
|
|
!__same_type(*(ptr), void), \
|
|
"pointer type mismatch in container_of()"); \
|
|
((type *)(__mptr - offsetof(type, member))); })
|
|
|
|
static inline bool strstartswith(const char *s, const char *prefix)
|
|
{
|
|
return strncmp(s, prefix, strlen(prefix)) == 0;
|
|
}
|
|
|
|
static inline void *malloc_array(size_t nmemb, size_t size)
|
|
{
|
|
size_t bytes;
|
|
|
|
if (__builtin_mul_overflow(nmemb, size, &bytes)) {
|
|
errno = ENOMEM;
|
|
return NULL;
|
|
}
|
|
return malloc(bytes);
|
|
}
|
|
|
|
static inline void *malloc64(uint64_t size)
|
|
{
|
|
if (size > SIZE_MAX)
|
|
return NULL;
|
|
return malloc(size);
|
|
}
|
|
|
|
#endif /* DRGN_UTIL_H */
|