initial commit

[ROCm/clr commit: 3694ab2ce8]
This commit is contained in:
foreman committed 2014-07-04 16:17:05 -04:00
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_*/
+102
View File
@@ -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
+182
View File
@@ -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_*/
+197
View File
@@ -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
+248
View File
@@ -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_
+370
View File
@@ -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_