diff --git a/rocclr/runtime/os/os_posix.cpp b/rocclr/runtime/os/os_posix.cpp index dfe2dd4394..0c2bd457bb 100644 --- a/rocclr/runtime/os/os_posix.cpp +++ b/rocclr/runtime/os/os_posix.cpp @@ -32,6 +32,7 @@ # define DT_GNU_HASH 0x6ffffef5 #endif // DT_GNU_HASH +#include #include #include #include @@ -753,7 +754,7 @@ Os::getTempPath() std::string Os::getTempFileName() { - static amd::Atomic counter = 0; + static std::atomic_size_t counter(0); std::string tempPath = getTempPath(); std::stringstream tempFileName; diff --git a/rocclr/runtime/os/os_win32.cpp b/rocclr/runtime/os/os_win32.cpp index ceb148e73c..afde674399 100644 --- a/rocclr/runtime/os/os_win32.cpp +++ b/rocclr/runtime/os/os_win32.cpp @@ -731,7 +731,7 @@ Os::getTempPath() std::string Os::getTempFileName() { - static amd::Atomic counter = 0; + static std::atomic_size_t counter(0); std::string tempPath = getTempPath(); std::stringstream tempFileName; diff --git a/rocclr/runtime/platform/command.cpp b/rocclr/runtime/platform/command.cpp index 145280f14e..97ac07c7a0 100644 --- a/rocclr/runtime/platform/command.cpp +++ b/rocclr/runtime/platform/command.cpp @@ -29,18 +29,16 @@ Event::Event(HostQueue& queue) : context_(queue.context()) , callbacks_(NULL) , status_(CL_INT_MAX) - , notified_(0) , profilingInfo_( queue.properties().test(CL_QUEUE_PROFILING_ENABLE) || Agent::shouldPostEventEvents()) -{ } +{ notified_.clear(); } Event::Event(Context& context) : context_(context) , callbacks_(NULL) , status_(CL_SUBMITTED) - , notified_(0) -{ } +{ notified_.clear(); } Event::~Event() { @@ -95,7 +93,7 @@ Event::setStatus(cl_int status, uint64_t timeStamp) return false; } - if (callbacks_ != NULL) { + if (callbacks_ != (CallBackEntry*)0) { processCallbacks(status); } @@ -131,14 +129,14 @@ Event::setCallback(cl_int status, Event::CallBackFunction callback, void* data) } entry->next_ = callbacks_; - while (!callbacks_.compareAndSet(entry->next_, entry)) { + while (!callbacks_.compare_exchange_weak(entry->next_, entry)) { // Someone else is also updating the head of the linked list! reload. entry->next_ = callbacks_; } // Check if the event has already reached 'status' - if (status_ <= status && entry->callback_ != NULL) { - if (entry->callback_.swap(NULL) != NULL) { + if (status_ <= status && entry->callback_ != CallBackFunction(0)) { + if (entry->callback_.exchange(NULL) != NULL) { callback(as_cl(this), status, entry->data_); } } @@ -157,9 +155,9 @@ Event::processCallbacks(cl_int status) const CallBackEntry* entry; for (entry = callbacks_; entry != NULL; entry = entry->next_) { // If the entry's status matches the mask, - if (entry->status_ == mask && entry->callback_ != NULL) { + if (entry->status_ == mask && entry->callback_ != CallBackFunction(0)) { // invoke the callback function. - CallBackFunction callback = entry->callback_.swap(NULL); + CallBackFunction callback = entry->callback_.exchange(NULL); if (callback != NULL) { callback(event, status, entry->data_); } @@ -190,14 +188,12 @@ Event::awaitCompletion() bool Event::notifyCmdQueue() { - static uint Notifed = 1; - static uint Empty = 0; HostQueue* queue = command().queue(); - if ((NULL != queue) && notified_.compareAndSet(Empty, Notifed)) { + if ((NULL != queue) && !notified_.test_and_set()) { // Make sure the queue is draining the enqueued commands. amd::Command* command = new amd::Marker(*queue, false, nullWaitList, this); if (command == NULL) { - notified_.compareAndSet(Notifed, Empty); + notified_.clear(); return false; } command->enqueue(); diff --git a/rocclr/runtime/platform/command.hpp b/rocclr/runtime/platform/command.hpp index 2aea1b8018..d630dcc08b 100644 --- a/rocclr/runtime/platform/command.hpp +++ b/rocclr/runtime/platform/command.hpp @@ -13,7 +13,6 @@ #define COMMAND_HPP_ #include "top.hpp" -#include "thread/atomic.hpp" #include "thread/monitor.hpp" #include "thread/thread.hpp" #include "platform/agent.hpp" @@ -28,6 +27,7 @@ #include "CL/cl_ext.h" #include +#include #include #include @@ -58,7 +58,7 @@ class Event : public RuntimeObject { struct CallBackEntry* next_; //!< the next entry in the callback list. - Atomic callback_; //!< callback function pointer. + std::atomic callback_; //!< callback function pointer. void* data_; //!< user data passed to the callback function. cl_int status_; //!< execution status triggering the callback. @@ -76,9 +76,9 @@ private: Monitor lock_; SharedReference context_; //!< context associated with this event. - Atomic callbacks_; //!< linked list of callback entries. - volatile cl_int status_; //!< current execution status. - Atomic notified_; //!< Command queue was notified + std::atomic callbacks_; //!< linked list of callback entries. + volatile cl_int status_; //!< current execution status. + std::atomic_flag notified_; //!< Command queue was notified protected: diff --git a/rocclr/runtime/platform/memory.cpp b/rocclr/runtime/platform/memory.cpp index f13eee6e04..18d742ae07 100644 --- a/rocclr/runtime/platform/memory.cpp +++ b/rocclr/runtime/platform/memory.cpp @@ -87,12 +87,12 @@ Memory::Memory( , isParent_(false) , vDev_(NULL) , forceSysMemAlloc_(false) - , mapCount_(0) , svmHostAddress_(svmPtr) , svmPtrCommited_(false) , canBeCached_(true) , lockMemoryOps_("Memory Ops Lock", true) { + std::atomic_init(&mapCount_, 0u); } Memory::Memory( @@ -117,7 +117,6 @@ Memory::Memory( , isParent_(false) , vDev_(NULL) , forceSysMemAlloc_(false) - , mapCount_(0) , svmHostAddress_(parent.getSvmPtr()) , svmPtrCommited_(parent.isSvmPtrCommited()) , canBeCached_(true) @@ -142,6 +141,8 @@ Memory::Memory( (CL_MEM_HOST_READ_ONLY | CL_MEM_HOST_WRITE_ONLY | CL_MEM_HOST_NO_ACCESS); } + + std::atomic_init(&mapCount_, 0u); } void @@ -438,7 +439,7 @@ Memory::setDestructorCallback(DestructorCallBackFunction callback, void* data) } entry->next_ = destructorCallbacks_; - while (!destructorCallbacks_.compareAndSet(entry->next_, entry)) { + while (!destructorCallbacks_.compare_exchange_weak(entry->next_, entry)) { // Someone else is also updating the head of the linked list! reload. entry->next_ = destructorCallbacks_; } diff --git a/rocclr/runtime/platform/memory.hpp b/rocclr/runtime/platform/memory.hpp index fcf36769f2..b36a286f35 100644 --- a/rocclr/runtime/platform/memory.hpp +++ b/rocclr/runtime/platform/memory.hpp @@ -7,13 +7,13 @@ #include "top.hpp" #include "utils/flags.hpp" -#include "thread/atomic.hpp" #include "thread/monitor.hpp" #include "platform/context.hpp" #include "platform/object.hpp" #include "platform/interop.hpp" #include "device/device.hpp" +#include #include #include #include @@ -155,7 +155,7 @@ protected: std::map deviceAlloced_; //! Linked list of destructor callbacks. - Atomic destructorCallbacks_; + std::atomic destructorCallbacks_; SharedReference context_; //!< Owning context Memory* parent_; @@ -170,7 +170,7 @@ protected: bool isParent_; //!< This object is a parent device::VirtualDevice* vDev_; //!< Memory object belongs to a virtual device only bool forceSysMemAlloc_; //!< Forces system memory allocation - Atomic mapCount_; //!< Keep track of number of mappings for a memory object + std::atomic_uint mapCount_; //!< Keep track of number of mappings for a memory object void * svmHostAddress_; //!< svm host address; bool svmPtrCommited_; //!< svm host address committed flag; bool canBeCached_; //!< flag to if the object can be cached; diff --git a/rocclr/runtime/platform/runtime.cpp b/rocclr/runtime/platform/runtime.cpp index 38f8ab7519..cdbfe127df 100644 --- a/rocclr/runtime/platform/runtime.cpp +++ b/rocclr/runtime/platform/runtime.cpp @@ -3,7 +3,6 @@ // #include "platform/runtime.hpp" -#include "thread/atomic.hpp" #include "os/os.hpp" #include "thread/thread.hpp" #include "device/device.hpp" @@ -24,14 +23,10 @@ #include #endif +#include #include #include -#ifdef TIMEBOMB -# include -# include -#endif // TIMEBOMB - namespace amd { #ifdef __linux__ @@ -60,22 +55,19 @@ Runtime::init() // from concurrently executing the init() routines. We can't use a // Monitor since the system is not yet initialized. - static Atomic lock = 0; + static std::atomic_flag lock = ATOMIC_FLAG_INIT; struct CriticalRegion { - Atomic& lock_; - CriticalRegion(Atomic& lock) : lock_(lock) + std::atomic_flag& lock_; + CriticalRegion(std::atomic_flag& lock) : lock_(lock) { - while (true) { - if (lock == 0 && lock.swap(1) == 0) { - break; - } + while (lock.test_and_set(std::memory_order_acquire)) { Os::yield(); } } ~CriticalRegion() { - lock_.storeRelease(0); + lock_.clear(std::memory_order_release); } } region(lock); @@ -83,20 +75,6 @@ Runtime::init() return true; } -#ifdef TIMEBOMB - time_t current = time(NULL); - time_t expiration = TIMEBOMB; - - if (current > expiration) { - fprintf(stderr, "Expired on %s", asctime(gmtime(&expiration))); - return false; - } - else { - fprintf(stderr, "For test only: Expires on %s", - asctime(gmtime(&expiration))); - } -#endif // TIMEBOMB - if ( !Flag::init() || !option::init() || !Device::init() diff --git a/rocclr/runtime/thread/monitor.hpp b/rocclr/runtime/thread/monitor.hpp index 4a09332464..4729ea0876 100644 --- a/rocclr/runtime/thread/monitor.hpp +++ b/rocclr/runtime/thread/monitor.hpp @@ -6,10 +6,11 @@ #define MONITOR_HPP_ #include "top.hpp" -#include "atomic.hpp" +#include "thread/atomic.hpp" #include "thread/semaphore.hpp" #include "thread/thread.hpp" +#include #include #include @@ -22,9 +23,43 @@ namespace amd { * @{ */ +namespace details { + +template +struct SimplyLinkedNode : public AllocClass +{ + typedef SimplyLinkedNode Node; + +protected: + std::atomic 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_.compare_exchange_strong(compare, next); + } +}; + +} // namespace details + class Monitor : public HeapObject { - typedef SimplyLinkedNode LinkedNode; + typedef details::SimplyLinkedNode LinkedNode; private: static const bool kUnlocked = false; diff --git a/rocclr/runtime/thread/semaphore.cpp b/rocclr/runtime/thread/semaphore.cpp index f6d1a0955b..d1ff87d596 100644 --- a/rocclr/runtime/thread/semaphore.cpp +++ b/rocclr/runtime/thread/semaphore.cpp @@ -3,7 +3,6 @@ // #include "thread/semaphore.hpp" -#include "thread/atomic.hpp" #include "thread/thread.hpp" #if defined(_WIN32) || defined(__CYGWIN__) @@ -16,8 +15,8 @@ namespace amd { Semaphore::Semaphore() - : state_(0) { + std::atomic_init(&state_, 0); #ifdef _WIN32 handle_ = static_cast(CreateSemaphore(NULL, 0, LONG_MAX, NULL)); assert(handle_ != NULL && "CreateSemaphore failed"); @@ -48,14 +47,13 @@ Semaphore::post() while (true) { state = state_; if (state > 0) { - // Do a load acquire. - MemoryOrder::fence(); - if (state == state_) { + if (state == state_.load(std::memory_order_acquire)) { return; } continue; } - if (state_.compareAndSet(state, state+1)) { + if (state_.compare_exchange_weak(state, state+1, + std::memory_order_acq_rel, std::memory_order_acquire)) { break; } } diff --git a/rocclr/runtime/thread/semaphore.hpp b/rocclr/runtime/thread/semaphore.hpp index ede63ff2b5..93c8c0f209 100644 --- a/rocclr/runtime/thread/semaphore.hpp +++ b/rocclr/runtime/thread/semaphore.hpp @@ -6,9 +6,9 @@ #define SEMAPHORE_HPP_ #include "top.hpp" -#include "thread/atomic.hpp" #include "utils/util.hpp" +#include #if defined(__linux__) # include #endif /*linux*/ @@ -29,14 +29,14 @@ class Thread; class Semaphore : public HeapObject { private: - Atomic state_; //!< This semaphore's value. + std::atomic_int state_; //!< This semaphore's value. #ifdef _WIN32 void* handle_; //!< The semaphore object's handle. - char padding_[64-sizeof(void*)-sizeof(Atomic)]; + char padding_[64-sizeof(void*)-sizeof(std::atomic_int)]; #else // !_WIN32 sem_t sem_; //!< The semaphore object's identifier. - char padding_[64-sizeof(sem_t)-sizeof(Atomic)]; + char padding_[64-sizeof(sem_t)-sizeof(std::atomic_int)]; #endif /*!_WIN32*/ public: @@ -52,7 +52,7 @@ public: //! \brief Reset this semaphore. void reset() { - state_.swap(0); + state_.store(0, std::memory_order_release); } }; diff --git a/rocclr/runtime/utils/util.hpp b/rocclr/runtime/utils/util.hpp index c5568ac0f6..efe0d41288 100644 --- a/rocclr/runtime/utils/util.hpp +++ b/rocclr/runtime/utils/util.hpp @@ -6,8 +6,8 @@ #define UTIL_HPP_ #include "top.hpp" -#include "thread/atomic.hpp" +#include #include namespace amd { @@ -187,95 +187,6 @@ inline bool isMultipleOf(T* value, size_t alignment) return isMultipleOf(ptr, alignment); } -template -struct SimplyLinkedNode : public AllocClass -{ - typedef SimplyLinkedNode Node; - -protected: - Atomic 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 -struct DoublyLinkedNode -{ - typedef SimplyLinkedNode Node; - -protected: - Atomic prev_; //!< The previous element. - Atomic 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 struct DeviceMap { Reference ref_;