blob: 4a1c1972daec0773c7dfab74eb8d38a71cfd7f34 [file] [log] [blame]
// Copyright 2016 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef SRC_GRAPHICS_LIB_MAGMA_SRC_MAGMA_UTIL_MACROS_H_
#define SRC_GRAPHICS_LIB_MAGMA_SRC_MAGMA_UTIL_MACROS_H_
#include <assert.h>
#include <limits.h> // PAGE_SIZE
#include <stdarg.h>
#include <stdio.h>
#include <time.h>
#include <unistd.h>
#include <limits>
// Files #including macros.h may assume that it #includes inttypes.h.
// So, for convenience, they don't need to follow "#include-what-you-use" for that header.
#include <inttypes.h>
#include "platform_logger.h"
#ifndef MAGMA_DEBUG_INTERNAL_USE_ONLY
#error MAGMA_DEBUG_INTERNAL_USE_ONLY not defined, your gn foo needs magma_util_config
#endif
namespace magma {
static constexpr bool kDebug = MAGMA_DEBUG_INTERNAL_USE_ONLY;
#define DASSERT(x) \
do { \
if (magma::kDebug && !(x)) { \
magma::PlatformLogger::Log(magma::PlatformLogger::LOG_ERROR, __FILE__, __LINE__, \
"DASSERT: %s", #x); \
abort(); \
} \
} while (0)
#define DMESSAGE(format, ...) \
do { \
if (magma::kDebug) { \
magma::PlatformLogger::Log(magma::PlatformLogger::LOG_INFO, __FILE__, __LINE__, format, \
##__VA_ARGS__); \
} \
} while (0)
static constexpr bool kMagmaDretEnable = kDebug;
#define DRET(ret) \
(magma::kMagmaDretEnable && (ret) != 0 \
? magma::PlatformLogger::Log(magma::PlatformLogger::LOG_ERROR, __FILE__, __LINE__, \
"Returning error %" PRId64, (int64_t)(ret)), \
(ret) : (ret))
#define DRET_MSG(ret, format, ...) \
(magma::kMagmaDretEnable && (ret) != 0 \
? magma::PlatformLogger::Log(magma::PlatformLogger::LOG_ERROR, __FILE__, __LINE__, \
"Returning error %" PRId64 ": " format, (int64_t)(ret), \
##__VA_ARGS__), \
(ret) : (ret))
#define DRETF(ret, format, ...) \
(magma::kMagmaDretEnable && !(ret) \
? magma::PlatformLogger::Log(magma::PlatformLogger::LOG_ERROR, __FILE__, __LINE__, \
"Returning false: " format, ##__VA_ARGS__), \
(ret) : (ret))
#define DRETP(ret, format, ...) \
(magma::kMagmaDretEnable && ((ret) == nullptr) \
? magma::PlatformLogger::Log(magma::PlatformLogger::LOG_ERROR, __FILE__, __LINE__, \
"Returning null: " format, ##__VA_ARGS__), \
(ret) : (ret))
enum LogLevel { LOG_WARNING, LOG_INFO };
// TODO(fxbug.dev/13095) - replace with MAGMA_LOG
__attribute__((format(printf, 2, 3))) static inline void log(LogLevel level, const char* msg, ...) {
switch (level) {
case LOG_WARNING:
printf("[WARNING] ");
break;
case LOG_INFO:
printf("[INFO] ");
break;
}
va_list args;
va_start(args, msg);
vprintf(msg, args);
va_end(args);
printf("\n");
}
#define UNIMPLEMENTED(...) \
do { \
DLOG("UNIMPLEMENTED: " #__VA_ARGS__); \
DASSERT(false); \
} while (0)
#define ATTRIBUTE_UNUSED __attribute__((unused))
#ifndef DISALLOW_COPY_AND_ASSIGN
#define DISALLOW_COPY_AND_ASSIGN(TypeName) \
TypeName(const TypeName&) = delete; \
void operator=(const TypeName&) = delete
#endif
static inline uint32_t to_uint32(uint64_t val) {
DASSERT(val <= std::numeric_limits<uint32_t>::max());
return static_cast<uint32_t>(val);
}
static inline uint32_t page_size() {
#ifdef PAGE_SIZE
return PAGE_SIZE;
#else
long page_size = sysconf(_SC_PAGESIZE);
DASSERT(page_size > 0);
return to_uint32(page_size);
#endif
}
static inline uint32_t page_shift() {
#if PAGE_SIZE == 4096
return 12;
#else
return __builtin_ctz(::magma::page_size());
#endif
}
static inline bool is_page_aligned(uint64_t val) { return (val & (::magma::page_size() - 1)) == 0; }
static inline uint32_t upper_32_bits(uint64_t n) { return static_cast<uint32_t>(n >> 32); }
static inline uint32_t lower_32_bits(uint64_t n) { return static_cast<uint32_t>(n); }
static inline bool get_pow2(uint64_t val, uint64_t* pow2_out) {
if (val == 0)
return DRETF(false, "zero is not a power of two");
uint64_t result = 0;
while ((val & 1) == 0) {
val >>= 1;
result++;
}
if (val >> 1)
return DRETF(false, "not a power of 2");
*pow2_out = result;
return true;
}
static inline bool is_pow2(uint64_t val) {
uint64_t out;
return get_pow2(val, &out);
}
// Note, alignment must be a power of 2
template <class T, class U>
static inline T round_up(T val, U alignment) {
DASSERT(is_pow2(alignment));
return ((val - 1) | (alignment - 1)) + 1;
}
static inline uint64_t ns_to_ms(uint64_t ns) { return ns / 1000000ull; }
static inline int64_t ms_to_signed_ns(uint64_t ms) {
if (ms > INT64_MAX / 1000000)
return INT64_MAX;
return static_cast<int64_t>(ms) * 1000000;
}
static inline uint64_t get_monotonic_ns() {
timespec time;
if (clock_gettime(CLOCK_MONOTONIC, &time) != 0) {
DASSERT(false);
return 0;
}
return static_cast<uint64_t>(time.tv_sec) * 1000000000ull + time.tv_nsec;
}
#define MAGMA_THREAD_ANNOTATION(x) __attribute__((x))
#define MAGMA_CAPABILITY(x) MAGMA_THREAD_ANNOTATION(__capability__(x))
#define MAGMA_GUARDED(x) MAGMA_THREAD_ANNOTATION(__guarded_by__(x))
#define MAGMA_ACQUIRE(...) MAGMA_THREAD_ANNOTATION(__acquire_capability__(__VA_ARGS__))
#define MAGMA_TRY_ACQUIRE(...) MAGMA_THREAD_ANNOTATION(__try_acquire_capability__(__VA_ARGS__))
#define MAGMA_ACQUIRED_BEFORE(...) MAGMA_THREAD_ANNOTATION(__acquired_before__(__VA_ARGS__))
#define MAGMA_ACQUIRED_AFTER(...) MAGMA_THREAD_ANNOTATION(__acquired_after__(__VA_ARGS__))
#define MAGMA_RELEASE(...) MAGMA_THREAD_ANNOTATION(__release_capability__(__VA_ARGS__))
#define MAGMA_REQUIRES(...) MAGMA_THREAD_ANNOTATION(__requires_capability__(__VA_ARGS__))
#define MAGMA_EXCLUDES(...) MAGMA_THREAD_ANNOTATION(__locks_excluded__(__VA_ARGS__))
#define MAGMA_RETURN_CAPABILITY(x) MAGMA_THREAD_ANNOTATION(__lock_returned__(x))
#define MAGMA_SCOPED_CAPABILITY MAGMA_THREAD_ANNOTATION(__scoped_lockable__)
#define MAGMA_NO_THREAD_SAFETY_ANALYSIS MAGMA_THREAD_ANNOTATION(__no_thread_safety_analysis__)
} // namespace magma
#endif // SRC_GRAPHICS_LIB_MAGMA_SRC_MAGMA_UTIL_MACROS_H_