1 parent
b0b5b33fcf
commit
f80f2f233c
351 files changed
+113713
-1
No files matched your search
@@ -0,0 +1,206 @@
|
||||
//
|
||||
// Copyright (c) 2010 Advanced Micro Devices, Inc. All rights reserved.
|
||||
//
|
||||
|
||||
#ifndef CONCURRENT_HPP_
|
||||
#define CONCURRENT_HPP_
|
||||
|
||||
#include "top.hpp"
|
||||
#include "thread/atomic.hpp"
|
||||
#include "os/alloc.hpp"
|
||||
|
||||
#include <new>
|
||||
|
||||
//! \addtogroup Utils
|
||||
|
||||
namespace amd {/*@{*/
|
||||
|
||||
namespace details {
|
||||
|
||||
template <typename T, int N>
|
||||
struct TaggedPointerHelper
|
||||
{
|
||||
static const uintptr_t TagMask = (1u << N) - 1;
|
||||
|
||||
private:
|
||||
TaggedPointerHelper(); // Cannot instantiate
|
||||
void* operator new(size_t); // allocate or
|
||||
void operator delete(void*); // delete a TaggedPointerHelper.
|
||||
|
||||
public:
|
||||
//! Create a tagged pointer.
|
||||
static TaggedPointerHelper* make(T* ptr, size_t tag)
|
||||
{
|
||||
return reinterpret_cast<TaggedPointerHelper*>(
|
||||
(reinterpret_cast<uintptr_t>(ptr) & ~TagMask) | (tag & TagMask));
|
||||
}
|
||||
|
||||
//! Return the pointer value.
|
||||
T* ptr()
|
||||
{
|
||||
return reinterpret_cast<T*>(
|
||||
reinterpret_cast<uintptr_t>(this) & ~TagMask);
|
||||
}
|
||||
|
||||
//! Return the tag value.
|
||||
size_t tag() const
|
||||
{
|
||||
return reinterpret_cast<uintptr_t>(this) & TagMask;
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace details
|
||||
|
||||
/*! \brief An unbounded thread-safe queue.
|
||||
*
|
||||
* This queue orders elements first-in-first-out. It is based on the algorithm
|
||||
* "Simple, Fast, and Practical Non-Blocking and Blocking Concurrent Queue
|
||||
* Algorithms by Maged M. Michael and Michael L. Scott.".
|
||||
*
|
||||
* FIXME_lmoriche: Implement the new/delete operators for SimplyLinkedNode
|
||||
* using thread-local allocation buffers.
|
||||
*/
|
||||
template <typename T, int N = 5>
|
||||
class ConcurrentLinkedQueue : public HeapObject
|
||||
{
|
||||
//! A simply-linked node
|
||||
struct Node
|
||||
{
|
||||
typedef details::TaggedPointerHelper<Node,N> TaggedPointerHelper;
|
||||
typedef TaggedPointerHelper* Ptr;
|
||||
|
||||
T value_; //!< The value stored in that node.
|
||||
Atomic<Ptr> next_; //!< Pointer to the next node
|
||||
|
||||
//! Create a Node::Ptr
|
||||
static inline Ptr ptr(Node* ptr, size_t counter = 0)
|
||||
{
|
||||
return TaggedPointerHelper::make(ptr, counter);
|
||||
}
|
||||
};
|
||||
|
||||
private:
|
||||
Atomic<typename Node::Ptr> head_; //! Pointer to the oldest element.
|
||||
Atomic<typename Node::Ptr> tail_; //! Pointer to the most recent element.
|
||||
|
||||
private:
|
||||
//! \brief Allocate a free node.
|
||||
static inline Node* allocNode()
|
||||
{
|
||||
return new(AlignedMemory::allocate(sizeof(Node), 1 << N)) Node();
|
||||
}
|
||||
|
||||
//! \brief Return a node to the free list.
|
||||
static inline void reclaimNode(Node* node)
|
||||
{
|
||||
AlignedMemory::deallocate(node);
|
||||
}
|
||||
|
||||
public:
|
||||
//! \brief Initialize a new concurrent linked queue.
|
||||
ConcurrentLinkedQueue();
|
||||
|
||||
//! \brief Destroy this concurrent linked queue.
|
||||
~ConcurrentLinkedQueue();
|
||||
|
||||
//! \brief Enqueue an element to this queue.
|
||||
inline void enqueue(T elem);
|
||||
|
||||
//! \brief Dequeue an element from this queue.
|
||||
inline T dequeue();
|
||||
};
|
||||
|
||||
/*@}*/
|
||||
|
||||
template <typename T, int N>
|
||||
inline
|
||||
ConcurrentLinkedQueue<T,N>::ConcurrentLinkedQueue()
|
||||
{
|
||||
// Create the first "dummy" node.
|
||||
Node* dummy = allocNode();
|
||||
dummy->next_ = NULL;
|
||||
DEBUG_ONLY(dummy->value_ = NULL);
|
||||
|
||||
// Head and tail should now point to it (empty list).
|
||||
head_ = tail_ = Node::ptr(dummy);
|
||||
|
||||
// Make sure the instance is fully initialized before it becomes
|
||||
// globally visible.
|
||||
MemoryOrder::sfence();
|
||||
}
|
||||
|
||||
template <typename T, int N>
|
||||
inline
|
||||
ConcurrentLinkedQueue<T,N>::~ConcurrentLinkedQueue()
|
||||
{
|
||||
typename Node::Ptr head = head_;
|
||||
typename Node::Ptr tail = tail_;
|
||||
while (head->ptr() != tail->ptr()) {
|
||||
Node* node = head->ptr();
|
||||
head = head->ptr()->next_;
|
||||
reclaimNode(node);
|
||||
}
|
||||
reclaimNode(head->ptr());
|
||||
}
|
||||
|
||||
template <typename T, int N>
|
||||
inline void
|
||||
ConcurrentLinkedQueue<T,N>::enqueue(T elem)
|
||||
{
|
||||
Node* node = allocNode();
|
||||
node->value_ = elem;
|
||||
node->next_ = NULL;
|
||||
|
||||
while (true) {
|
||||
typename Node::Ptr tail = tail_;
|
||||
typename Node::Ptr next = tail->ptr()->next_;
|
||||
MemoryOrder::lfence();
|
||||
if (tail == tail_) {
|
||||
if (next->ptr() == NULL) {
|
||||
if (tail->ptr()->next_.compareAndSet(
|
||||
next, Node::ptr(node, next->tag()+1))) {
|
||||
tail_.compareAndSet(tail, Node::ptr(node, tail->tag()+1));
|
||||
return;
|
||||
}
|
||||
}
|
||||
else {
|
||||
tail_.compareAndSet(
|
||||
tail, Node::ptr(next->ptr(), tail->tag()+1));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T, int N>
|
||||
inline T
|
||||
ConcurrentLinkedQueue<T,N>::dequeue()
|
||||
{
|
||||
while (true) {
|
||||
typename Node::Ptr head = head_;
|
||||
typename Node::Ptr tail = tail_;
|
||||
typename Node::Ptr next = head->ptr()->next_;
|
||||
MemoryOrder::lfence();
|
||||
if (head == head_) {
|
||||
if (head->ptr() == tail->ptr()) {
|
||||
if (next->ptr() == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
tail_.compareAndSet(
|
||||
tail, Node::ptr(next->ptr(), tail->tag()+1));
|
||||
}
|
||||
else {
|
||||
T value = next->ptr()->value_;
|
||||
if (head_.compareAndSet(
|
||||
head, Node::ptr(next->ptr(), head->tag()+1))) {
|
||||
// we can reclaim head now
|
||||
reclaimNode(head->ptr());
|
||||
return value;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace amd
|
||||
|
||||
#endif /*CONCURRENT_HPP_*/
|
||||
@@ -0,0 +1,102 @@
|
||||
//
|
||||
// Copyright (c) 2008 Advanced Micro Devices, Inc. All rights reserved.
|
||||
//
|
||||
|
||||
#include "top.hpp"
|
||||
#include "utils/debug.hpp"
|
||||
#include "os/os.hpp"
|
||||
|
||||
#if !defined(LOG_LEVEL)
|
||||
# include "utils/flags.hpp"
|
||||
#endif
|
||||
|
||||
#include <cstdlib>
|
||||
#include <cstdio>
|
||||
#include <cstdarg>
|
||||
|
||||
#ifdef _WIN32
|
||||
#include <windows.h>
|
||||
#endif // _WIN32
|
||||
|
||||
namespace amd {
|
||||
|
||||
//! \cond ignore
|
||||
extern "C" void
|
||||
breakpoint(void)
|
||||
{
|
||||
#ifdef _MSC_VER
|
||||
DebugBreak();
|
||||
#endif // _MSC_VER
|
||||
}
|
||||
//! \endcond
|
||||
|
||||
bool
|
||||
ShouldBreak(LogLevel level)
|
||||
{
|
||||
if ((level == LOG_WARNING && BREAK_ON_LOG_WARNING)
|
||||
|| (level == LOG_ERROR && BREAK_ON_LOG_ERROR)) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void
|
||||
report_fatal(const char* file, int line, const char* message)
|
||||
{
|
||||
// FIXME_lmoriche: Obfuscate the message string
|
||||
fprintf(stderr, "%s:%d: %s\n", file, line, message);
|
||||
::abort();
|
||||
}
|
||||
|
||||
void
|
||||
report_warning(const char* message)
|
||||
{
|
||||
fprintf(stderr, "Warning: %s\n", message);
|
||||
}
|
||||
|
||||
void
|
||||
log_entry(LogLevel level, const char* file, int line, const char* message)
|
||||
{
|
||||
if (level == LOG_NONE) {
|
||||
return;
|
||||
}
|
||||
fprintf(stderr, ":%d:%s:%d: %s\n", level, file, line, message);
|
||||
}
|
||||
|
||||
void
|
||||
log_timestamped(LogLevel level, const char* file, int line, const char* message)
|
||||
{
|
||||
static bool gotstart = false; // not thread-safe, but not scary if fails
|
||||
static uint64_t start;
|
||||
|
||||
if (!gotstart) {
|
||||
start = Os::timeNanos();
|
||||
gotstart = true;
|
||||
}
|
||||
|
||||
uint64_t time = Os::timeNanos() - start;
|
||||
if (level == LOG_NONE) {
|
||||
return;
|
||||
}
|
||||
#if 0
|
||||
fprintf(stderr, ":%d:%s:%d: (%010lld) %s\n", level, file, line, time, message);
|
||||
#else // if you prefer fixed-width fields
|
||||
fprintf(stderr, ":% 2d:%15s:% 5d: (%010lld) %s\n",
|
||||
level, file, line, time/100ULL, message); // timestamp is 100ns units
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
log_printf(LogLevel level, const char* file, int line, const char* format, ...)
|
||||
{
|
||||
va_list ap;
|
||||
|
||||
va_start(ap, format);
|
||||
char message[1024];
|
||||
vsprintf(message, format, ap);
|
||||
va_end(ap);
|
||||
|
||||
fprintf(stderr, ":%d:%s:%d: %s\n", level, file, line, message);
|
||||
}
|
||||
|
||||
} // namespace amd
|
||||
@@ -0,0 +1,182 @@
|
||||
//
|
||||
// Copyright (c) 2008 Advanced Micro Devices, Inc. All rights reserved.
|
||||
//
|
||||
|
||||
#ifndef DEBUG_HPP_
|
||||
#define DEBUG_HPP_
|
||||
|
||||
|
||||
#include <cassert>
|
||||
|
||||
//! \addtogroup Utils
|
||||
|
||||
namespace amd {/*@{*/
|
||||
|
||||
enum LogLevel {
|
||||
LOG_NONE = 0,
|
||||
LOG_ERROR = 1,
|
||||
LOG_WARNING = 2,
|
||||
LOG_INFO = 3,
|
||||
LOG_DEBUG = 4
|
||||
};
|
||||
|
||||
//! \cond ignore
|
||||
extern "C" void
|
||||
breakpoint();
|
||||
//! \endcond
|
||||
|
||||
//! \brief Report a Fatal exception message and abort.
|
||||
extern void
|
||||
report_fatal(const char* file, int line, const char* message);
|
||||
|
||||
//! \brief Display a warning message.
|
||||
extern void
|
||||
report_warning(const char* message);
|
||||
|
||||
//! \brief Insert a log entry.
|
||||
extern void
|
||||
log_entry(LogLevel level, const char* file, int line, const char* messsage);
|
||||
|
||||
//! \brief Insert a timestamped log entry.
|
||||
extern void
|
||||
log_timestamped(LogLevel level, const char* file, int line, const char* messsage);
|
||||
|
||||
//! \brief Insert a printf-style log entry.
|
||||
extern void
|
||||
log_printf(
|
||||
LogLevel level,
|
||||
const char* file,
|
||||
int line,
|
||||
const char* format,
|
||||
...);
|
||||
|
||||
/*@}*/} // namespace amd
|
||||
|
||||
#if __INTEL_COMPILER
|
||||
|
||||
// Disable ICC's warning #279: controlling expression is constant
|
||||
// (0!=1 && "msg")
|
||||
// ^
|
||||
#pragma warning ( disable : 279 )
|
||||
|
||||
#endif // __INTEL_COMPILER
|
||||
|
||||
//! \brief Abort the program if the invariant \a cond is false.
|
||||
#define guarantee(cond) \
|
||||
if (!(cond)) \
|
||||
{ \
|
||||
amd::report_fatal(__FILE__, __LINE__, \
|
||||
"guarantee(" XSTR(cond) ")"); \
|
||||
amd::breakpoint(); \
|
||||
}
|
||||
|
||||
#define fixme_guarantee(cond) guarantee(cond)
|
||||
|
||||
//! \brief Abort the program with a fatal error message.
|
||||
#define fatal(msg) do { assert(false && msg); } while (0)
|
||||
|
||||
|
||||
//! \brief Display a warning message.
|
||||
inline void
|
||||
warning(const char* msg)
|
||||
{
|
||||
amd::report_warning(msg);
|
||||
}
|
||||
|
||||
/*! \brief Abort the program with a "ShouldNotReachHere" message.
|
||||
* \hideinitializer
|
||||
*/
|
||||
#define ShouldNotReachHere() fatal("ShouldNotReachHere()")
|
||||
|
||||
/*! \brief Abort the program with a "ShouldNotCallThis" message.
|
||||
* \hideinitializer
|
||||
*/
|
||||
#define ShouldNotCallThis() fatal("ShouldNotCallThis()")
|
||||
|
||||
/*! \brief Abort the program with an "Unimplemented" message.
|
||||
* \hideinitializer
|
||||
*/
|
||||
#define Unimplemented() fatal("Unimplemented()")
|
||||
|
||||
/*! \brief Display an "Untested" warning message.
|
||||
* \hideinitializer
|
||||
*/
|
||||
#ifndef NDEBUG
|
||||
# define Untested(msg) \
|
||||
warning("Untested(\"" msg "\")")
|
||||
#else /*NDEBUG*/
|
||||
# define Untested(msg) (void)(0)
|
||||
#endif /*NDEBUG*/
|
||||
|
||||
#ifdef DEBUG
|
||||
namespace amd {
|
||||
extern bool ShouldBreak(LogLevel level);
|
||||
} // namespace amd
|
||||
#endif // DEBUG
|
||||
|
||||
#ifdef DEBUG
|
||||
# define Log(level,msg) \
|
||||
do \
|
||||
{ \
|
||||
if (LOG_LEVEL >= level) { \
|
||||
amd::log_entry(level, __FILE__, __LINE__, msg); \
|
||||
if (amd::ShouldBreak(level)) { \
|
||||
amd::breakpoint(); \
|
||||
} \
|
||||
} \
|
||||
} while (false)
|
||||
#else // !DEBUG
|
||||
# define Log(level,msg) (void)(0)
|
||||
#endif // !DEBUG
|
||||
|
||||
#ifdef DEBUG
|
||||
# define LogTS(level,msg) \
|
||||
do \
|
||||
{ \
|
||||
if (LOG_LEVEL >= level) { \
|
||||
amd::log_timestamped(level, __FILE__, __LINE__, msg); \
|
||||
if (amd::ShouldBreak(level)) { \
|
||||
amd::breakpoint(); \
|
||||
} \
|
||||
} \
|
||||
} while (false)
|
||||
#else // !DEBUG
|
||||
# define Log(level,msg) (void)(0)
|
||||
#endif // !DEBUG
|
||||
|
||||
#ifdef DEBUG
|
||||
# define Logf(level, format, ...) \
|
||||
do \
|
||||
{ \
|
||||
if (LOG_LEVEL >= level) { \
|
||||
amd::log_printf(level, __FILE__, __LINE__, format, __VA_ARGS__); \
|
||||
if (amd::ShouldBreak(level)) { \
|
||||
amd::breakpoint(); \
|
||||
} \
|
||||
} \
|
||||
} while (false)
|
||||
#else // !DEBUG
|
||||
# define Logf(level, format, ...) (void)(0)
|
||||
#endif // !DEBUG
|
||||
|
||||
#define CondLog(cond,msg) \
|
||||
do { \
|
||||
if (false DEBUG_ONLY(|| (cond))) { \
|
||||
Log(amd::LOG_INFO,msg); \
|
||||
} \
|
||||
} while (false)
|
||||
|
||||
#define LogInfo(msg) Log(amd::LOG_INFO,msg)
|
||||
#define LogError(msg) Log(amd::LOG_ERROR,msg)
|
||||
#define LogWarning(msg) Log(amd::LOG_WARNING,msg)
|
||||
|
||||
#define LogTSInfo(msg) LogTS(amd::LOG_INFO,msg)
|
||||
#define LogTSError(msg) LogTS(amd::LOG_ERROR,msg)
|
||||
#define LogTSWarning(msg) LogTS(amd::LOG_WARNING,msg)
|
||||
|
||||
#define LogPrintfDebug(format, ...) Logf(amd::LOG_DEBUG, format, __VA_ARGS__)
|
||||
#define LogPrintfError(format, ...) Logf(amd::LOG_ERROR, format, __VA_ARGS__)
|
||||
#define LogPrintfWarning(format, ...) Logf(amd::LOG_WARNING, format, __VA_ARGS__)
|
||||
#define LogPrintfInfo(format, ...) Logf(amd::LOG_INFO, format, __VA_ARGS__)
|
||||
|
||||
#endif /*DEBUG_HPP_*/
|
||||
@@ -0,0 +1,197 @@
|
||||
//
|
||||
// Copyright (c) 2008 Advanced Micro Devices, Inc. All rights reserved.
|
||||
//
|
||||
|
||||
#include "top.hpp"
|
||||
#include "utils/flags.hpp"
|
||||
|
||||
#include <map>
|
||||
#include <string>
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
|
||||
#ifdef _WIN32
|
||||
#include <windows.h>
|
||||
#include <tchar.h>
|
||||
#else
|
||||
#include <unistd.h>
|
||||
#endif // !_WIN32
|
||||
|
||||
namespace {
|
||||
|
||||
const char* removeQuotes(const char* Value)
|
||||
{
|
||||
const char *b, *e, *p;
|
||||
if (Value == NULL) {
|
||||
return Value;
|
||||
}
|
||||
|
||||
// skip the leading blank
|
||||
for (p = Value; *p == ' '; ++p);
|
||||
if (*p != '"') {
|
||||
return Value;
|
||||
}
|
||||
b = p;
|
||||
e = NULL;
|
||||
for (++p; *p != '\0'; ++p) {
|
||||
if (*p == '"') {
|
||||
// e points to the last '"'
|
||||
e = p;
|
||||
}
|
||||
else if ((e != NULL) && (*p != ' ')) {
|
||||
// e isn't last '"' if there is any non-blank following e
|
||||
e = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
if (e == NULL) {
|
||||
return Value;
|
||||
}
|
||||
// Found a valid quoted string "<str>" with b=1st '"' and e=the last '"'
|
||||
size_t len = (e - b - 1) > 0 ? (e - b - 1) : 0;
|
||||
#ifdef _WIN32
|
||||
char* p1 = _strdup(b+1);
|
||||
p1[len] = '\0';
|
||||
p = p1;
|
||||
#else
|
||||
p = strndup(b+1, len);
|
||||
#endif
|
||||
return p;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
namespace amd {
|
||||
|
||||
#ifdef __APPLE__
|
||||
#include <crt_externs.h>
|
||||
#endif // __APPLE__
|
||||
|
||||
//static
|
||||
char* Flag::envstr_;
|
||||
|
||||
void Flag::tearDown()
|
||||
{
|
||||
|
||||
#ifdef _WIN32
|
||||
FreeEnvironmentStringsA(envstr_);
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
bool
|
||||
Flag::init()
|
||||
{
|
||||
typedef std::map<std::string,const char*> vars_type;
|
||||
vars_type vars;
|
||||
|
||||
#ifdef _WIN32
|
||||
char* str = GetEnvironmentStringsA();
|
||||
envstr_ = str;
|
||||
|
||||
for (; *str != '\0'; str += strlen(str) + 1) {
|
||||
// For all environment variables:
|
||||
std::string var = str;
|
||||
size_t pos = var.find('=');
|
||||
if ((pos == std::string::npos) || ((pos + 1) >= var.size())) {
|
||||
continue;
|
||||
}
|
||||
|
||||
std::string name = var.substr(0, pos);
|
||||
vars.insert(std::make_pair(name, &str[pos+1]));
|
||||
}
|
||||
#else // !_WIN32
|
||||
#ifdef __APPLE__
|
||||
char** environ = *_NSGetEnviron();
|
||||
if (environ == NULL) { return false; }
|
||||
#endif // __APPLE__
|
||||
|
||||
for (const char** p = const_cast<const char**>(environ);*p != NULL; ++p) {
|
||||
std::string var = *p;
|
||||
size_t pos = var.find('=');
|
||||
if ((pos == std::string::npos) || ((pos + 1) >= var.size())) {
|
||||
continue;
|
||||
}
|
||||
|
||||
std::string name = var.substr(0, pos);
|
||||
vars.insert(std::make_pair(name, &(*p)[pos+1]));
|
||||
}
|
||||
#endif // !_WIN32
|
||||
|
||||
for (size_t i = 0; i < numFlags_; ++i) {
|
||||
Flag& flag = flags_[i];
|
||||
|
||||
vars_type::iterator it = vars.find(flag.name_);
|
||||
if (it != vars.end()) {
|
||||
flag.setValue(it->second);
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
Flag::setValue(const char* value)
|
||||
{
|
||||
if (value_ == NULL) {
|
||||
return false; // flag is constant.
|
||||
}
|
||||
|
||||
isDefault_ = false;
|
||||
|
||||
switch (type_) {
|
||||
case Tbool:
|
||||
*(bool*) value_ = (strcmp(value, "true") == 0 || atoi(value) != 0) ? true : false;
|
||||
return true;
|
||||
|
||||
case Tint:
|
||||
case Tuint:
|
||||
*(int*) value_ = atoi(value);
|
||||
return true;
|
||||
|
||||
case Tsize_t:
|
||||
*(size_t*) value_ = atol(value);
|
||||
return true;
|
||||
|
||||
case Tcstring:
|
||||
*(const char**) value_ = removeQuotes(value);
|
||||
return true;
|
||||
|
||||
default: break;
|
||||
}
|
||||
ShouldNotReachHere();
|
||||
return false;
|
||||
}
|
||||
|
||||
#define DEFINE_RELEASE_FLAG_STRUCT(type, name, value, help) \
|
||||
{ #name, &name, T##type, true },
|
||||
#define DEFINE_DEBUG_FLAG_STRUCT(type, name, value, help) \
|
||||
{ #name, RELEASE_ONLY(NULL) DEBUG_ONLY(&name), T##type, true },
|
||||
|
||||
Flag
|
||||
Flag::flags_[] =
|
||||
{
|
||||
RUNTIME_FLAGS( \
|
||||
DEFINE_DEBUG_FLAG_STRUCT, \
|
||||
DEFINE_RELEASE_FLAG_STRUCT, \
|
||||
DEFINE_DEBUG_FLAG_STRUCT )
|
||||
{ NULL, NULL, Tinvalid, true }
|
||||
};
|
||||
|
||||
#undef DEFINE_DEBUG_FLAG_STRUCT
|
||||
#undef DEFINE_RELEASE_FLAG_STRUCT
|
||||
|
||||
} // namespace amd
|
||||
|
||||
#define DEFINE_RELEASE_FLAG_VALUE(type, name, value, help) type name = value;
|
||||
#define DEFINE_DEBUG_FLAG_VALUE(type, name, value, help) \
|
||||
DEBUG_ONLY(type name = value);
|
||||
|
||||
RUNTIME_FLAGS( \
|
||||
DEFINE_DEBUG_FLAG_VALUE, \
|
||||
DEFINE_RELEASE_FLAG_VALUE, \
|
||||
DEFINE_DEBUG_FLAG_VALUE );
|
||||
|
||||
#undef DEFINE_DEBUG_FLAG_VALUE
|
||||
#undef DEFINE_RELEASE_FLAG_VALUE
|
||||
|
||||
@@ -0,0 +1,248 @@
|
||||
//
|
||||
// Copyright (c) 2009 Advanced Micro Devices, Inc. All rights reserved.
|
||||
//
|
||||
|
||||
#ifndef FLAGS_HPP_
|
||||
#define FLAGS_HPP_
|
||||
|
||||
|
||||
#define RUNTIME_FLAGS(debug,release,release_on_stg) \
|
||||
\
|
||||
debug(int, LOG_LEVEL, 0, \
|
||||
"The default log level") \
|
||||
debug(bool, BREAK_ON_LOG_WARNING, false, \
|
||||
"Break each time an error is logged") \
|
||||
debug(bool, BREAK_ON_LOG_ERROR, false, \
|
||||
"Break each time an error is logged") \
|
||||
debug(uint, DEBUG_GPU_FLAGS, 0, \
|
||||
"The debug options for GPU device") \
|
||||
debug(uint, GPU_MAX_COMMAND_QUEUES, 80, \
|
||||
"The maximum number of concurrent Virtual GPUs") \
|
||||
release(size_t, CQ_THREAD_STACK_SIZE, 256*Ki, /* @todo: that much! */ \
|
||||
"The default command queue thread stack size") \
|
||||
release(size_t, CPU_WORKER_THREAD_STACK_SIZE, 64*Ki, \
|
||||
"The default CPU worker thread stack size") \
|
||||
release(int, CPU_MAX_COMPUTE_UNITS, -1, \
|
||||
"Override the number of computation units per CPU device") \
|
||||
release(int, GPU_MAX_WORKGROUP_SIZE, 0, \
|
||||
"Maximum number of workitems in a workgroup for GPU, 0 -use default") \
|
||||
release(int, GPU_MAX_WORKGROUP_SIZE_2D_X, 0, \
|
||||
"Maximum number of workitems in a 2D workgroup for GPU, x component, 0 -use default") \
|
||||
release(int, GPU_MAX_WORKGROUP_SIZE_2D_Y, 0, \
|
||||
"Maximum number of workitems in a 2D workgroup for GPU, y component, 0 -use default") \
|
||||
release(int, GPU_MAX_WORKGROUP_SIZE_3D_X, 0, \
|
||||
"Maximum number of workitems in a 3D workgroup for GPU, x component, 0 -use default") \
|
||||
release(int, GPU_MAX_WORKGROUP_SIZE_3D_Y, 0, \
|
||||
"Maximum number of workitems in a 3D workgroup for GPU, y component, 0 -use default") \
|
||||
release(int, GPU_MAX_WORKGROUP_SIZE_3D_Z, 0, \
|
||||
"Maximum number of workitems in a 3D workgroup for GPU, z component, 0 -use default") \
|
||||
release(int, CPU_MAX_WORKGROUP_SIZE, 1024, \
|
||||
"Maximum number of workitems in a workgroup for CPU") \
|
||||
debug(bool, CPU_MEMORY_GUARD_PAGES, false, \
|
||||
"Use guard pages for CPU memory") \
|
||||
debug(size_t, CPU_MEMORY_GUARD_PAGE_SIZE, 64, \
|
||||
"Size in KB of CPU memory guard page") \
|
||||
debug(size_t, CPU_MEMORY_ALIGNMENT_SIZE, 256, \
|
||||
"Size in bytes for the default alignment for guarded memory on CPU") \
|
||||
debug(size_t, PARAMETERS_MIN_ALIGNMENT, 16, \
|
||||
"Minimum alignment required for the abstract parameters stack") \
|
||||
debug(size_t, MEMOBJ_BASE_ADDR_ALIGN, 4*Ki, \
|
||||
"Alignment of the base address of any allocate memory object") \
|
||||
release(cstring, GPU_DEVICE_NAME, "", \
|
||||
"Select the device ordinal (will only report a single device)") \
|
||||
release(cstring, GPU_DEVICE_ORDINAL, "", \
|
||||
"Select the device ordinal (comma seperated list of available devices)") \
|
||||
release(bool, REMOTE_ALLOC, false, \
|
||||
"Use remote memory for the global heap allocation") \
|
||||
release(int, GPU_INITIAL_HEAP_SIZE, 16, \
|
||||
"Initial size of the GPU heap in MiB") \
|
||||
release(uint, GPU_MAX_HEAP_SIZE, 100, \
|
||||
"Set maximum size of the GPU heap to % of board memory") \
|
||||
release(int, GPU_HEAP_GROWTH_INCREMENT, 8, \
|
||||
"Amount to grow the GPU heap by in MiB") \
|
||||
release(uint, GPU_STAGING_BUFFER_SIZE, 512, \
|
||||
"Size of the GPU staging buffer in KiB") \
|
||||
release(bool, GPU_DUMP_BLIT_KERNELS, false, \
|
||||
"Dump the kernels for blit manager") \
|
||||
release(uint, GPU_BLIT_ENGINE_TYPE, 0x0, \
|
||||
"Blit engine type: 0 - Default, 1 - Host, 2 - CAL, 3 - Kernel") \
|
||||
release(bool, GPU_FLUSH_ON_EXECUTION, false, \
|
||||
"Submit commands to HW on every operation. 0 - Disable, 1 - Enable") \
|
||||
release(bool, GPU_USE_SYNC_OBJECTS, true, \
|
||||
"If enabled, use sync objects instead of polling") \
|
||||
release(bool, ENABLE_CAL_SHUTDOWN, false, \
|
||||
"Enable explicit CAL shutdown (for PM4 capture)") \
|
||||
release(bool, CL_KHR_FP64, true, \
|
||||
"Enable/Disable support for double precision") \
|
||||
release(uint, GPU_OPEN_VIDEO, 0, \
|
||||
"Non-zero value allows to report Open Video extension on GPU") \
|
||||
release(cstring, AMD_OCL_BUILD_OPTIONS, 0, \
|
||||
"Set clBuildProgram() and clCompileProgram()'s options (override)") \
|
||||
release(cstring, AMD_OCL_BUILD_OPTIONS_APPEND, 0, \
|
||||
"Append clBuildProgram() and clCompileProgram()'s options") \
|
||||
release(cstring, AMD_OCL_LINK_OPTIONS, 0, \
|
||||
"Set clLinkProgram()'s options (override)") \
|
||||
release(cstring, AMD_OCL_LINK_OPTIONS_APPEND, 0, \
|
||||
"Append clLinkProgram()'s options") \
|
||||
debug(bool, AMD_OCL_SUPPRESS_MESSAGE_BOX, false, \
|
||||
"Suppress the error dialog on Windows") \
|
||||
debug(bool, OCL_STRESS_BINARY_IMAGE, false, \
|
||||
"Exercise the binary image producer and consumer") \
|
||||
release(cstring, GPU_PRE_RA_SCHED, "default", \
|
||||
"Allows setting of alternate pre-RA-sched") \
|
||||
release(size_t, GPU_PINNED_XFER_SIZE, 16, \
|
||||
"The pinned buffer size for pinning in read/write transfers") \
|
||||
release(size_t, GPU_PINNED_MIN_XFER_SIZE, 512, \
|
||||
"The minimal buffer size for pinned read/write transfers in KBytes") \
|
||||
release(size_t, GPU_RESOURCE_CACHE_SIZE, 64, \
|
||||
"The resource cache size in MB") \
|
||||
release(uint, GPU_ASYNC_MEM_COPY, 0, \
|
||||
"Enables async memory transfers with DRM engine") \
|
||||
release(bool, GPU_FORCE_64BIT_PTR, 0, \
|
||||
"Forces 64 bit pointers on GPU") \
|
||||
release(bool, GPU_FORCE_OCL20_32BIT, 0, \
|
||||
"Forces 32 bit apps to take CLANG\HSAIL path") \
|
||||
release(bool, GPU_PREALLOC_ADDR_SPACE, 0, \
|
||||
"Preallocates 4GB address space. Valid for boards > 4GB") \
|
||||
release(bool, GPU_RAW_TIMESTAMP, 0, \
|
||||
"Reports GPU raw timestamps in GPU timeline") \
|
||||
release(bool, CPU_IMAGE_SUPPORT, true, \
|
||||
"Turn on image support on the CPU device") \
|
||||
release(bool, GPU_PARTIAL_DISPATCH, true, \
|
||||
"Enables partial dispatch on GPU") \
|
||||
release(size_t, GPU_NUM_MEM_DEPENDENCY, 256, \
|
||||
"Number of memory objects for dependency tracking") \
|
||||
release(size_t, GPU_XFER_BUFFER_SIZE, 0, \
|
||||
"Transfer buffer size for image copy optimization in KB") \
|
||||
release(bool, GPU_IMAGE_DMA, true, \
|
||||
"Enable DRM DMA for image transfers") \
|
||||
release(uint, CPU_MAX_ALLOC_PERCENT, 25, \
|
||||
"Maximum size of a single allocation in MiB") \
|
||||
release(uint, GPU_MAX_ALLOC_PERCENT, 75, \
|
||||
"Maximum size of a single allocation as percentage of total") \
|
||||
release(uint, GPU_NUM_COMPUTE_RINGS, 2, \
|
||||
"GPU number of compute rings. 0 - disabled, 1 , 2,.. - the number of compute rings") \
|
||||
release_on_stg(bool, C1X_ATOMICS, !IS_MAINLINE, \
|
||||
"Runtime will report c1x atomics support") \
|
||||
release(uint, GPU_WORKLOAD_SPLIT, 22, \
|
||||
"Workload split size") \
|
||||
release(bool, GPU_USE_SINGLE_SCRATCH, false, \
|
||||
"Use single scratch buffer per device instead of per HW ring") \
|
||||
release_on_stg(cstring, GPU_TARGET_INFO_ARCH, "amdil", \
|
||||
"Select the GPU TargetInfo arch (amdil|hsail)") \
|
||||
release(bool, HSA_RUNTIME, 0, \
|
||||
"1 = Enable HSA Runtime, any other value or absence disables it.") \
|
||||
release(bool, AMD_OCL_WAIT_COMMAND, false, \
|
||||
"1 = Enable a wait for every submitted command") \
|
||||
debug(bool, AMD_OCL_DEBUG_LINKER, false, \
|
||||
"Enable debug output in linker") \
|
||||
debug(bool, GPU_SPLIT_LIB, true, \
|
||||
"Enable splitting GPU 32/64 bit library") \
|
||||
release(bool, GPU_STAGING_WRITE_PERSISTENT, false, \
|
||||
"Enable Persistent writes") \
|
||||
release(bool, DRMDMA_FOR_LNX_CF, false, \
|
||||
"Enable DRMDMA for Linux CrossFire") \
|
||||
release(bool, GPU_HSAIL_ENABLE, false, \
|
||||
"Enable HSAIL on dGPU stack (requires CI+ HW)") \
|
||||
release(bool, GPU_ASSUME_ALIASES, false, \
|
||||
"Assume memory aliases in the compilation process") \
|
||||
release(bool, GPU_DIRECT_SRD, true, \
|
||||
"Use indirect SRD access in HSAIL") \
|
||||
release(bool, AMD_DEPTH_MSAA_INTEROP, false, \
|
||||
"Enable depth stencil and MSAA buffer interop") \
|
||||
release(bool, AMD_THREAD_TRACE_ENABLE, false, \
|
||||
"Enable thread trace extension") \
|
||||
release(bool, ENVVAR_HSA_POLL_KERNEL_COMPLETION, false, \
|
||||
"Determines if Hsa runtime should use polling scheme") \
|
||||
release(bool, HSA_LOCAL_MEMORY_ENABLE, false, \
|
||||
"Enable HSA device local memory usage") \
|
||||
release(bool, HSA_ENABLE_ATOMICS_32B, false, \
|
||||
"1 = Enable SVM atomics in 32 bits (HSA backend-only). Any other value keeps then disabled.") \
|
||||
release_on_stg(bool, GPU_ENABLE_HIGH_PERFORMANCE_STATE, false, \
|
||||
"Enable high performance state")
|
||||
|
||||
namespace amd {
|
||||
|
||||
//! \addtogroup Utils
|
||||
// @{
|
||||
|
||||
struct Flag
|
||||
{
|
||||
enum Type
|
||||
{
|
||||
Tinvalid = 0,
|
||||
Tbool, //!< A boolean type flag (true, false).
|
||||
Tint, //!< An integer type flag (signed).
|
||||
Tuint, //!< An integer type flag (unsigned).
|
||||
Tsize_t, //!< A size_t type flag.
|
||||
Tcstring //!< A string type flag.
|
||||
};
|
||||
|
||||
#define DEFINE_FLAG_NAME(type, name, value, help) k##name,
|
||||
enum Name
|
||||
{
|
||||
RUNTIME_FLAGS(DEFINE_FLAG_NAME, DEFINE_FLAG_NAME, DEFINE_FLAG_NAME)
|
||||
numFlags_
|
||||
};
|
||||
#undef DEFINE_FLAG_NAME
|
||||
|
||||
#define CAN_SET(type, name, v, h) static const bool cannotSet##name = false;
|
||||
#define CANNOT_SET(type, name, v, h) static const bool cannotSet##name = true;
|
||||
|
||||
#ifdef DEBUG
|
||||
RUNTIME_FLAGS(CAN_SET, CAN_SET, CAN_SET)
|
||||
#else // !DEBUG
|
||||
RUNTIME_FLAGS(CANNOT_SET, CAN_SET, CANNOT_SET)
|
||||
#endif // !DEBUG
|
||||
|
||||
#undef CAN_SET
|
||||
#undef CANNOT_SET
|
||||
|
||||
private:
|
||||
|
||||
static Flag flags_[];
|
||||
|
||||
public:
|
||||
static char* envstr_;
|
||||
const char* name_;
|
||||
const void* value_;
|
||||
Type type_;
|
||||
bool isDefault_;
|
||||
|
||||
public:
|
||||
|
||||
static bool init();
|
||||
|
||||
static void tearDown();
|
||||
|
||||
bool setValue(const char* value);
|
||||
|
||||
static bool isDefault(Name name) { return flags_[name].isDefault_; }
|
||||
};
|
||||
|
||||
#define flagIsDefault(name) \
|
||||
(amd::Flag::cannotSet##name || amd::Flag::isDefault(amd::Flag::k##name))
|
||||
|
||||
// @}
|
||||
|
||||
} // namespace amd
|
||||
|
||||
#ifdef _WIN32
|
||||
# define EXPORT_FLAG extern "C" __declspec(dllexport)
|
||||
#else // !_WIN32
|
||||
# define EXPORT_FLAG extern "C"
|
||||
#endif // !_WIN32
|
||||
|
||||
#define DECLARE_RELEASE_FLAG(type, name, value, help) EXPORT_FLAG type name;
|
||||
#ifdef DEBUG
|
||||
# define DECLARE_DEBUG_FLAG(type, name, value, help) EXPORT_FLAG type name;
|
||||
#else // !DEBUG
|
||||
# define DECLARE_DEBUG_FLAG(type, name, value, help) const type name = value;
|
||||
#endif // !DEBUG
|
||||
|
||||
RUNTIME_FLAGS(DECLARE_DEBUG_FLAG, DECLARE_RELEASE_FLAG, DECLARE_DEBUG_FLAG);
|
||||
|
||||
#undef DECLARE_DEBUG_FLAG
|
||||
#undef DECLARE_RELEASE_FLAG
|
||||
|
||||
#endif /*FLAGS_HPP_*/
|
||||
@@ -0,0 +1,171 @@
|
||||
//
|
||||
// Copyright (c) 2011 Advanced Micro Devices, Inc. All rights reserved.
|
||||
//
|
||||
|
||||
#ifndef MACROS_HPP_
|
||||
#define MACROS_HPP_
|
||||
|
||||
#ifndef OPENCL_EXPORTS
|
||||
# define OPENCL_EXPORTS 1
|
||||
#endif // OPENCL_EXPORTS
|
||||
|
||||
#if defined(NDEBUG)
|
||||
# define RELEASE 1
|
||||
#else// !NDEBUG
|
||||
# define ASSERT 1
|
||||
# define DEBUG 1
|
||||
#endif // !NDEBUG
|
||||
|
||||
#if defined(_WIN64) && !defined(_LP64)
|
||||
# define _LP64 1
|
||||
#endif
|
||||
|
||||
#if defined(_DEBUG) && !defined(DEBUG)
|
||||
# define DEBUG 1
|
||||
#endif // _DEBUG && !DEBUG
|
||||
|
||||
#if defined(DEBUG) && defined(RELEASE)
|
||||
# error "Build Error: cannot have both -DDEBUG and -DRELEASE"
|
||||
#endif /*DEBUG && RELEASE*/
|
||||
|
||||
#if !defined(DEBUG) && !defined(RELEASE)
|
||||
# error "Build Error: must have either -DDEBUG or -DRELEASE"
|
||||
#endif /*DEBUG && RELEASE*/
|
||||
|
||||
#ifdef DEBUG
|
||||
# define DEBUG_ONLY(x) x
|
||||
# define RELEASE_ONLY(x)
|
||||
# define IS_DEBUG true
|
||||
#else // !DEBUG
|
||||
# define DEBUG_ONLY(x)
|
||||
# define RELEASE_ONLY(x) x
|
||||
# define IS_DEBUG false
|
||||
#endif /*!DEBUG*/
|
||||
#define DEBUG_SWITCH(d,r) DEBUG_ONLY(d)RELEASE_ONLY(r)
|
||||
#define RELEASE_SWITCH(r,d) RELEASE_ONLY(r)DEBUG_ONLY(d)
|
||||
|
||||
//! \brief Make a c-string of __macro__
|
||||
#define STR(__macro__) #__macro__
|
||||
//! \brief Make a c-string of the expansion of __macro__
|
||||
#define XSTR(__macro__) STR(__macro__)
|
||||
//! \brief Concatenate 2 symbols
|
||||
#define CONCAT(a,b) a##b
|
||||
#define XCONCAT(a,b) CONCAT(a,b)
|
||||
|
||||
|
||||
//! \cond ignore
|
||||
#ifdef _LP64
|
||||
# define LP64_ONLY(x) x
|
||||
# define NOT_LP64(x)
|
||||
#else // !_LP64
|
||||
# define LP64_ONLY(x)
|
||||
# define NOT_LP64(x) x
|
||||
#endif /*!_LP64*/
|
||||
#define LP64_SWITCH(lp32,lp64) NOT_LP64(lp32)LP64_ONLY(lp64)
|
||||
|
||||
#ifdef __linux__
|
||||
# define IS_LINUX true
|
||||
# define LINUX_ONLY(x) x
|
||||
# define NOT_LINUX(x)
|
||||
#else // !__linux__
|
||||
# define LINUX_ONLY(x)
|
||||
# define NOT_LINUX(x) x
|
||||
#endif /*!__linux__*/
|
||||
|
||||
#ifdef __APPLE__
|
||||
# define IS_MACOS true
|
||||
# define MACOS_ONLY(x) x
|
||||
# define NOT_MACOS(x)
|
||||
#else // !__APPLE__
|
||||
# define MACOS_ONLY(x)
|
||||
# define NOT_MACOS(x) x
|
||||
#endif /*!__APPLE__*/
|
||||
|
||||
#ifdef _WIN32
|
||||
# define IS_WINDOWS true
|
||||
# define WINDOWS_ONLY(x) x
|
||||
# define NOT_WINDOWS(x)
|
||||
#else // !_WIN32
|
||||
# define WINDOWS_ONLY(x)
|
||||
# define NOT_WINDOWS(x) x
|
||||
#endif /*!_WIN32*/
|
||||
|
||||
#ifdef _WIN64
|
||||
# define WIN64_ONLY(x) x
|
||||
# define NOT_WIN64(x)
|
||||
#else // !_WIN64
|
||||
# define WIN64_ONLY(x)
|
||||
# define NOT_WIN64(x) x
|
||||
#endif /*!_WIN64*/
|
||||
|
||||
#ifndef IS_LINUX
|
||||
# define IS_LINUX false
|
||||
#endif
|
||||
#ifndef IS_MACOS
|
||||
# define IS_MACOS false
|
||||
#endif
|
||||
#ifndef IS_WINDOWS
|
||||
# define IS_WINDOWS false
|
||||
#endif
|
||||
|
||||
#define IF_LEFT_true(x) x
|
||||
#define IF_LEFT_false(x)
|
||||
#define IF_RIGHT_true(x)
|
||||
#define IF_RIGHT_false(x) x
|
||||
|
||||
#define IF_LEFT(cond,x) IF_LEFT_##cond(x)
|
||||
#define IF_RIGHT(cond,x) IF_RIGHT_##cond(x)
|
||||
#define IF(cond,x,y) IF_LEFT(cond,x)IF_RIGHT(cond,y)
|
||||
|
||||
#define LINUX_SWITCH(x,other) LINUX_ONLY(x)NOT_LINUX(other)
|
||||
#define MACOS_SWITCH(x,other) MACOS_ONLY(x)NOT_MACOS(other)
|
||||
#define WINDOWS_SWITCH(x,other) WINDOWS_ONLY(x)NOT_WINDOWS(other)
|
||||
|
||||
#ifdef OPENCL_MAINLINE
|
||||
# define IS_MAINLINE true
|
||||
#else // OPENCL_STAGING
|
||||
# define IS_MAINLINE false
|
||||
#endif
|
||||
|
||||
#ifdef OPTIMIZED
|
||||
# define OPTIMIZED_ONLY(x) x
|
||||
# define NOT_OPTIMIZED(x)
|
||||
# define IS_OPTIMIZED true
|
||||
#else
|
||||
# define OPTIMIZED_ONLY(x)
|
||||
# define NOT_OPTIMIZED(x) x
|
||||
# define IS_OPTIMIZED false
|
||||
#endif
|
||||
|
||||
#if defined(__GNUC__)
|
||||
# define __ALIGNED__(x) __attribute__((aligned(x)))
|
||||
#elif defined(_MSC_VER)
|
||||
# define __ALIGNED__(x) __declspec(align(x))
|
||||
#elif defined(RC_INVOKED)
|
||||
# define __ALIGNED__(x)
|
||||
#else
|
||||
# error
|
||||
#endif /*_MSC_VER*/
|
||||
|
||||
#if defined(__GNUC__)
|
||||
# define likely(cond) __builtin_expect(!!(cond), 1)
|
||||
# define unlikely(cond) __builtin_expect(!!(cond), 0)
|
||||
#else // !__GNUC__
|
||||
# define likely(cond) (cond)
|
||||
# define unlikely(cond) (cond)
|
||||
#endif // !__GNUC__
|
||||
|
||||
#if defined(__GNUC__)
|
||||
# define NOINLINE __attribute__((noinline))
|
||||
# define ALWAYSINLINE __attribute__ ((always_inline))
|
||||
#elif defined(_MSC_VER)
|
||||
# define NOINLINE __declspec(noinline)
|
||||
# define ALWAYSINLINE __forceinline
|
||||
#else // !_MSC_VER
|
||||
# define NOINLINE
|
||||
# define ALWAYSINLINE
|
||||
#endif // !_MSC_VER
|
||||
|
||||
//! \endcond
|
||||
|
||||
#endif // MACROS_HPP_
|
||||
@@ -0,0 +1,370 @@
|
||||
//
|
||||
// Copyright (c) 2008 Advanced Micro Devices, Inc. All rights reserved.
|
||||
//
|
||||
|
||||
#ifndef UTIL_HPP_
|
||||
#define UTIL_HPP_
|
||||
|
||||
#include "top.hpp"
|
||||
#include "thread/atomic.hpp"
|
||||
|
||||
#include <string>
|
||||
|
||||
namespace amd {
|
||||
|
||||
/*! \addtogroup Utils Utilities
|
||||
* @{
|
||||
*/
|
||||
|
||||
//! \brief Check if the given value \a val is a power of 2.
|
||||
template <typename T>
|
||||
static inline bool
|
||||
isPowerOfTwo(T val)
|
||||
{
|
||||
return (val & (val - 1)) == 0;
|
||||
}
|
||||
|
||||
//! \cond ignore
|
||||
|
||||
// Compute the next power of 2 helper.
|
||||
template <uint N>
|
||||
struct NextPowerOfTwoFunction
|
||||
{
|
||||
template <typename T>
|
||||
static T compute(T val)
|
||||
{
|
||||
val = NextPowerOfTwoFunction<N/2>::compute(val);
|
||||
return (val >> N) | val;
|
||||
}
|
||||
};
|
||||
|
||||
// Specialized version for <1> to break the recursion.
|
||||
template <>
|
||||
struct NextPowerOfTwoFunction<1>
|
||||
{
|
||||
template <typename T>
|
||||
static T compute(T val) { return (val >> 1) | val; }
|
||||
};
|
||||
|
||||
template <uint N, int S>
|
||||
struct NextPowerOfTwoHelper
|
||||
{
|
||||
static const uint prev = NextPowerOfTwoHelper<N, S / 2>::value;
|
||||
static const uint value = (prev >> S) | prev;
|
||||
};
|
||||
template <uint N>
|
||||
struct NextPowerOfTwoHelper<N, 1>
|
||||
{
|
||||
static const int value = (N >> 1) | N;
|
||||
};
|
||||
|
||||
template <uint N>
|
||||
struct NextPowerOfTwo
|
||||
{
|
||||
static const uint value = NextPowerOfTwoHelper<N-1, 16>::value + 1;
|
||||
};
|
||||
|
||||
//! \endcond
|
||||
|
||||
/*! \brief Return the next power of two for a value of type T.
|
||||
*
|
||||
* The compute function is (with n = sizeof(T)*8):
|
||||
*
|
||||
* val = (val >> 1) | val;
|
||||
* val = (val >> 2) | val;
|
||||
* ...
|
||||
* val = (val >> n/4) | val;
|
||||
* val = (val >> n/2) | val;
|
||||
*
|
||||
* The next power of two is: 1+compute(val-1)
|
||||
*/
|
||||
template <typename T>
|
||||
inline T
|
||||
nextPowerOfTwo(T val)
|
||||
{
|
||||
return NextPowerOfTwoFunction<sizeof(T)*4>::compute(val - 1) + 1;
|
||||
}
|
||||
|
||||
// Compute log2(N)
|
||||
template <uint N>
|
||||
struct Log2
|
||||
{
|
||||
static const uint value = Log2<N/2>::value + 1;
|
||||
};
|
||||
|
||||
// Break the recursion
|
||||
template <>
|
||||
struct Log2<1>
|
||||
{
|
||||
static const uint value = 0;
|
||||
};
|
||||
|
||||
/*! \brief Return the log2 for a value of type T.
|
||||
*
|
||||
* The compute function is (with n = sizeof(T)*8):
|
||||
*
|
||||
* uint l = 0;
|
||||
* if (val >= 1 << n/2) { val >>= n/2; l |= n/2; }
|
||||
* if (val >= 1 << n/4) { val >>= n/4; l |= n/4; }
|
||||
* ...
|
||||
* if (val >= 1 << 2) { val >>= 2; l |= 2; }
|
||||
* if (val >= 1 << 1) { l |= 1; }
|
||||
* return l;
|
||||
*/
|
||||
template <uint N>
|
||||
struct Log2Function
|
||||
{
|
||||
template <typename T>
|
||||
static uint compute(T val)
|
||||
{
|
||||
uint l = 0;
|
||||
if (val >= T(1) << N) {
|
||||
val >>= N; l = N;
|
||||
}
|
||||
return l + Log2Function<N/2>::compute(val);
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct Log2Function<1>
|
||||
{
|
||||
template <typename T>
|
||||
static uint compute(T val) {
|
||||
return (val >= T(1)<<1) ? 1 : 0;
|
||||
}
|
||||
};
|
||||
|
||||
// log2 helper function
|
||||
template <typename T>
|
||||
inline uint
|
||||
log2(T val)
|
||||
{
|
||||
return Log2Function<sizeof(T)*4>::compute(val);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline T
|
||||
alignDown(T value, size_t alignment)
|
||||
{
|
||||
return (T) (value & ~(alignment - 1));
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline T*
|
||||
alignDown(T* value, size_t alignment)
|
||||
{
|
||||
return (T*) alignDown((intptr_t) value, alignment);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline T
|
||||
alignUp(T value, size_t alignment)
|
||||
{
|
||||
return alignDown((T) (value + alignment - 1), alignment);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline T*
|
||||
alignUp(T* value, size_t alignment)
|
||||
{
|
||||
return (T*) alignDown((intptr_t) (value + alignment - 1), alignment);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
inline bool isMultipleOf(T value, size_t alignment)
|
||||
{
|
||||
if (isPowerOfTwo(alignment)) {
|
||||
// fast path, using logical operators
|
||||
return alignUp(value, alignment) == value;
|
||||
}
|
||||
return value % alignment == 0;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
inline bool isMultipleOf(T* value, size_t alignment)
|
||||
{
|
||||
intptr_t ptr = reinterpret_cast<intptr_t>(value);
|
||||
return isMultipleOf(ptr, alignment);
|
||||
}
|
||||
|
||||
template <class T, class AllocClass = HeapObject>
|
||||
struct SimplyLinkedNode : public AllocClass
|
||||
{
|
||||
typedef SimplyLinkedNode<T, AllocClass> Node;
|
||||
|
||||
protected:
|
||||
Atomic<Node*> next_; /*!< \brief The next element. */
|
||||
T volatile item_;
|
||||
|
||||
public:
|
||||
//! \brief Return the next element in the linked-list.
|
||||
Node* next() const { return next_; }
|
||||
//! \brief Return the item.
|
||||
T item() const { return item_; }
|
||||
|
||||
//! \brief Set the next element pointer.
|
||||
void setNext(Node* next) { next_ = next; }
|
||||
//! \brief Set the item.
|
||||
void setItem(T item) { item_ = item; }
|
||||
|
||||
//! \brief Swap the next element pointer.
|
||||
Node* swapNext(Node* next) { return next_.swap(next); }
|
||||
|
||||
//! \brief Compare and set the next element pointer.
|
||||
bool compareAndSetNext(Node* compare, Node* next)
|
||||
{
|
||||
return next_.compareAndSet(compare, next);
|
||||
}
|
||||
};
|
||||
|
||||
/* For the implementation of a doubly-linked list, check:
|
||||
* Lock-Free and Practical
|
||||
* Deques and Doubly Linked
|
||||
* Lists using Single-Word
|
||||
* Compare-And-Swap
|
||||
*
|
||||
* Hakan Sundell, Philippas Tsigas
|
||||
* Department of Computing Science
|
||||
* Chalmers Univ. of Technol. and Goteborg Univ.
|
||||
*/
|
||||
|
||||
template <class T, class AllocClass = HeapObject>
|
||||
struct DoublyLinkedNode
|
||||
{
|
||||
typedef SimplyLinkedNode<T, AllocClass> Node;
|
||||
|
||||
protected:
|
||||
Atomic<Node*> prev_; //!< The previous element.
|
||||
Atomic<Node*> next_; //!< The next element.
|
||||
T volatile item_;
|
||||
|
||||
public:
|
||||
//! \brief Return the previous element in the linked-list.
|
||||
Node* prev() const { return prev_; }
|
||||
//! \brief Return the next element in the linked-list.
|
||||
Node* next() const { return next_; }
|
||||
//! \brief Return the item.
|
||||
T item() const { return item_; }
|
||||
|
||||
//! \brief Set the previous element pointer.
|
||||
void setPrev(Node* prev) { prev_ = prev; }
|
||||
//! \brief Set the next element pointer.
|
||||
void setNext(Node* next) { next_ = next; }
|
||||
//! \brief Set the item.
|
||||
void setItem(T item) { item_ = item; }
|
||||
|
||||
//! \brief Swap the previous element pointer.
|
||||
Node* swapPrev(Node* prev)
|
||||
{
|
||||
return prev_.swap(prev);
|
||||
}
|
||||
//! \brief Swap the next element pointer.
|
||||
Node* swapNext( Node* next)
|
||||
{
|
||||
return next_.swap(next);
|
||||
}
|
||||
|
||||
//! \brief Compare and set the previous element pointer.
|
||||
bool compareAndSetPrev(Node* compare, Node* prev)
|
||||
{
|
||||
return prev_.compareAndSet(compare, prev, false, false);
|
||||
}
|
||||
//! \brief Compare and set the next element pointer.
|
||||
bool compareAndSetNext(Node* compare, Node* next)
|
||||
{
|
||||
return next_.compareAndSet(compare, next, false, false);
|
||||
}
|
||||
};
|
||||
|
||||
template <class Reference, class Value>
|
||||
struct DeviceMap {
|
||||
Reference ref_;
|
||||
Value value_;
|
||||
};
|
||||
|
||||
|
||||
inline uint
|
||||
countBitsSet32(uint32_t value)
|
||||
{
|
||||
#if __GNUC__ >= 4
|
||||
return (uint)__builtin_popcount(value);
|
||||
#else
|
||||
value = value - ((value >> 1) & 0x55555555);
|
||||
value = (value & 0x33333333) + ((value >> 2) & 0x33333333);
|
||||
return (uint)(((value + (value >> 4) & 0xF0F0F0F) * 0x1010101) >> 24);
|
||||
#endif
|
||||
}
|
||||
|
||||
inline uint
|
||||
countBitsSet64(uint64_t value)
|
||||
{
|
||||
#if __GNUC__ >= 4
|
||||
return (uint)__builtin_popcountll(value);
|
||||
#else
|
||||
value = value - ((value >> 1) & 0x5555555555555555ULL);
|
||||
value = (value & 0x3333333333333333ULL) + ((value >> 2) & 0x3333333333333333ULL);
|
||||
value = (value + (value >> 4)) & 0x0F0F0F0F0F0F0F0FULL;
|
||||
return (uint)((uint64_t)(value * 0x0101010101010101ULL) >> 56);
|
||||
#endif
|
||||
}
|
||||
|
||||
inline uint
|
||||
leastBitSet32(uint32_t value)
|
||||
{
|
||||
#if defined(_WIN32)
|
||||
unsigned long idx;
|
||||
return _BitScanForward(&idx, (unsigned long)value) ? idx : (uint)-1;
|
||||
#else
|
||||
return value ? __builtin_ctz(value) : (uint)-1;
|
||||
#endif
|
||||
}
|
||||
|
||||
inline uint
|
||||
leastBitSet64(uint64_t value)
|
||||
{
|
||||
#if defined(_WIN64)
|
||||
unsigned long idx;
|
||||
return _BitScanForward64(&idx, (unsigned __int64)value) ? idx : (uint)-1;
|
||||
#elif defined (__GNUC__)
|
||||
return value ? __builtin_ctzll(value) : (uint)-1;
|
||||
#else
|
||||
static const uint8_t lookup67[67+1] = {
|
||||
64, 0, 1, 39, 2, 15, 40, 23,
|
||||
3, 12, 16, 59, 41, 19, 24, 54,
|
||||
4, -1, 13, 10, 17, 62, 60, 28,
|
||||
42, 30, 20, 51, 25, 44, 55, 47,
|
||||
5, 32, -1, 38, 14, 22, 11, 58,
|
||||
18, 53, 63, 9, 61, 27, 29, 50,
|
||||
43, 46, 31, 37, 21, 57, 52, 8,
|
||||
26, 49, 45, 36, 56, 7, 48, 35,
|
||||
6, 34, 33, -1
|
||||
};
|
||||
|
||||
return (uint)lookup67[((int64_t)value & -(int64_t)value) % 67];
|
||||
#endif
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline uint countBitsSet(T value)
|
||||
{
|
||||
return (sizeof(T) == 8) ? countBitsSet64((uint64_t)value) :
|
||||
countBitsSet32((uint32_t)value);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline uint leastBitSet(T value)
|
||||
{
|
||||
return (sizeof(T) == 8) ? leastBitSet64((uint64_t)value) :
|
||||
leastBitSet32((uint32_t)value);
|
||||
}
|
||||
|
||||
static inline bool Is32Bits() {
|
||||
return LP64_SWITCH(true, false);
|
||||
}
|
||||
|
||||
static inline bool Is64Bits() {
|
||||
return LP64_SWITCH(false, true);
|
||||
}
|
||||
/*@}*/} // namespace amd
|
||||
|
||||
#endif /*UTIL_HPP_*/
|
||||
@@ -0,0 +1,34 @@
|
||||
//
|
||||
// Copyright (c) 2010 Advanced Micro Devices, Inc. All rights reserved.
|
||||
//
|
||||
|
||||
#ifndef VERSIONS_HPP_
|
||||
#define VERSIONS_HPP_
|
||||
|
||||
#include "utils/macros.hpp"
|
||||
|
||||
#ifndef AMD_PLATFORM_NAME
|
||||
# define AMD_PLATFORM_NAME "AMD Accelerated Parallel Processing"
|
||||
#endif // AMD_PLATFORM_NAME
|
||||
|
||||
#ifndef AMD_PLATFORM_BUILD_NUMBER
|
||||
# define AMD_PLATFORM_BUILD_NUMBER 1579
|
||||
#endif // AMD_PLATFORM_BUILD_NUMBER
|
||||
|
||||
#ifndef AMD_PLATFORM_REVISION_NUMBER
|
||||
# define AMD_PLATFORM_REVISION_NUMBER 0
|
||||
#endif // AMD_PLATFORM_REVISION_NUMBER
|
||||
|
||||
#ifndef AMD_PLATFORM_RELEASE_INFO
|
||||
# define AMD_PLATFORM_RELEASE_INFO
|
||||
#endif // AMD_PLATFORM_RELEASE_INFO
|
||||
|
||||
#define AMD_BUILD_STRING XSTR(AMD_PLATFORM_BUILD_NUMBER) \
|
||||
"." XSTR(AMD_PLATFORM_REVISION_NUMBER)
|
||||
|
||||
#ifndef AMD_PLATFORM_INFO
|
||||
# define AMD_PLATFORM_INFO "AMD-APP" AMD_PLATFORM_RELEASE_INFO \
|
||||
DEBUG_ONLY("." IF(IS_OPTIMIZED,"opt","dbg")) " (" AMD_BUILD_STRING ")"
|
||||
#endif // ATI_PLATFORM_INFO
|
||||
|
||||
#endif // VERSIONS_HPP_
|
||||
Reference in new issue
Block a user