P4 to Git Change 1082964 by lmoriche@lmoriche_opencl_dev on 2014/09/30 17:09:28

ECR #304775 - Replace amd::Atomic with std::atomic (cont'd)

	Pre-checkin: http://ocltc.amd.com:8111/viewModification.html?modId=40674&personal=true&buildTypeId=&tab=vcsModificationBuilds&show_all_builds=true

Affected files ...

... //depot/stg/opencl/drivers/opencl/runtime/thread/atomic.hpp#6 edit
... //depot/stg/opencl/drivers/opencl/runtime/thread/monitor.cpp#6 edit
... //depot/stg/opencl/drivers/opencl/runtime/thread/monitor.hpp#7 edit
... //depot/stg/opencl/drivers/opencl/runtime/utils/concurrent.hpp#7 edit


[ROCm/clr commit: d780c32a1b]
This commit is contained in:
foreman
2014-09-30 17:40:37 -04:00
parent 5f45d44db6
commit 8f6983d69b
4 changed files with 78 additions and 204 deletions
+54 -46
View File
@@ -15,7 +15,7 @@
namespace amd {
Monitor::Monitor(const char* name, bool recursive) :
contendersList_(NULL), onDeck_(NULL), waitersList_(NULL),
contendersList_(0), onDeck_(0), waitersList_(NULL),
owner_(NULL), recursive_(recursive)
{
const size_t maxNameLen = sizeof(name_);
@@ -68,19 +68,17 @@ Monitor::finishLock()
/* The lock is contended. Push the thread's semaphore onto
* the contention list.
*/
Semaphore& sem = thread->lockSemaphore();
sem.reset();
Semaphore& semaphore = thread->lockSemaphore();
semaphore.reset();
LinkedNode newHead;
newHead.setItem(&sem);
while (true) {
LinkedNode* head; bool isLocked;
newHead.setItem(&semaphore);
intptr_t head = contendersList_.load(std::memory_order_acquire);
for (;;) {
// The assumption is that lockWord is locked. Make sure we do not
// continue unless the lock bit is set.
std::tie(head, isLocked) = contendersList_.get();
if (!isLocked) {
if ((head & kLockBit) == 0) {
if (tryLock()) {
return;
}
@@ -88,8 +86,10 @@ Monitor::finishLock()
}
// Set the new contention list head if lockWord is unchanged.
newHead.setNext(head);
if (contendersList_.compareAndSet(head, &newHead, kLocked, kLocked)) {
newHead.setNext(reinterpret_cast<LinkedNode*>(head & ~kLockBit));
if (contendersList_.compare_exchange_weak(head,
reinterpret_cast<intptr_t>(&newHead) | kLockBit,
std::memory_order_acq_rel, std::memory_order_acquire)) {
break;
}
@@ -99,7 +99,7 @@ Monitor::finishLock()
int32_t spinCount = 0;
// Go to sleep until we become the on-deck thread.
while (onDeck_.getReference() != &sem) {
while ((onDeck_ & ~kLockBit) != reinterpret_cast<intptr_t>(&semaphore)) {
// First, be SMT friendly
if (spinCount < kMaxReadSpinIter) {
Os::spinPause();
@@ -110,7 +110,7 @@ Monitor::finishLock()
}
// now go to sleep
else {
sem.wait();
semaphore.wait();
}
spinCount++;
}
@@ -120,8 +120,9 @@ Monitor::finishLock()
// From now-on, we are the on-deck thread. It will stay that way until
// we successfuly acquire the lock.
//
while (true) {
assert(onDeck_.getReference() == &sem && "just checking");
for (;;) {
assert((onDeck_ & ~kLockBit) == reinterpret_cast<intptr_t>(&semaphore)
&& "just checking");
if (tryLock()) {
break;
}
@@ -138,13 +139,13 @@ Monitor::finishLock()
}
// now go to sleep
else {
sem.wait();
semaphore.wait();
}
spinCount++;
}
assert(newHead.next() == NULL && "Should not be linked");
onDeck_ = NULL;
onDeck_ = 0;
}
void
@@ -154,53 +155,58 @@ Monitor::finishUnlock()
// list waiting to acquire the lock. We need to select a successor and
// place it on-deck.
while (true) {
for (;;) {
// Grab the onDeck_ microlock to protect the next loop (make sure only
// one semaphore is removed from the contention list).
//
if (!onDeck_.compareAndSet(NULL, NULL, kUnlocked, kLocked)) {
intptr_t ptr = 0;
if (!onDeck_.compare_exchange_strong(ptr, ptr | kLockBit,
std::memory_order_acq_rel, std::memory_order_acquire)) {
return; // Somebody else has the microlock, let him select onDeck_
}
LinkedNode* head; bool isLocked;
while (true) {
std::tie(head, isLocked) = contendersList_.get();
if (head == NULL) {
intptr_t head = contendersList_.load(std::memory_order_acquire);
for (;;) {
if (head == 0) {
break; // There's nothing else to do.
}
if (isLocked) {
if ((head & kLockBit) != 0) {
// Somebody could have acquired then released the lock
// and failed to grab the onDeck_ microlock.
head = NULL;
head = 0;
break;
}
if (contendersList_.compareAndSet(
head, head->next(), kUnlocked, kUnlocked)) {
if (contendersList_.compare_exchange_weak(
head, reinterpret_cast<intptr_t>(
reinterpret_cast<LinkedNode*>(head)->next()),
std::memory_order_acq_rel, std::memory_order_acquire)) {
#ifdef ASSERT
head->setNext(NULL);
reinterpret_cast<LinkedNode*>(head)->setNext(NULL);
#endif // ASSERT
break;
}
}
Semaphore* sem = (head != NULL) ? head->item() : NULL;
onDeck_ = sem;
MemoryOrder::fence();
Semaphore* semaphore = (head != 0)
? reinterpret_cast<LinkedNode*>(head)->item()
: NULL;
onDeck_.store(reinterpret_cast<intptr_t>(semaphore),
std::memory_order_release);
//
// Release the onDeck_ microlock (end of critical region);
if (sem != NULL) {
sem->post();
if (semaphore != NULL) {
semaphore->post();
return;
}
// We do not have an on-deck thread (sem == NULL). Return if
// We do not have an on-deck thread (semaphore == NULL). Return if
// the contention list is empty or if the lock got acquired again.
std::tie(head, isLocked) = contendersList_.get();
if (isLocked || head == NULL) {
head = contendersList_;
if (head == 0 || (head & kLockBit) != 0) {
return;
}
}
@@ -230,7 +236,7 @@ Monitor::wait()
// Go to sleep until we become the on-deck thread.
int32_t spinCount = 0;
while (onDeck_.getReference() != &suspend) {
while ((onDeck_ & ~kLockBit) != reinterpret_cast<intptr_t>(&suspend)) {
// First, be SMT friendly
if (spinCount < kMaxReadSpinIter) {
Os::spinPause();
@@ -247,8 +253,9 @@ Monitor::wait()
}
spinCount = 0;
while (true) {
assert(onDeck_.getReference() == &suspend && "just checking");
for (;;) {
assert((onDeck_ & ~kLockBit) == reinterpret_cast<intptr_t>(&suspend)
&& "just checking");
if (trySpinLock()) {
break;
@@ -274,8 +281,7 @@ Monitor::wait()
// Restore the lock count (for recursive mutexes)
lockCount_ = lockCount;
onDeck_ = NULL;
MemoryOrder::fence();
onDeck_.store(0, std::memory_order_release);
}
void
@@ -290,11 +296,13 @@ Monitor::notify()
// Dequeue a waiter from the wait list and add it to the contention list.
waitersList_ = waiter->next();
while (true) {
LinkedNode* node = contendersList_.getReference();
waiter->setNext(node);
if (contendersList_.compareAndSet(node, waiter, kLocked, kLocked)) {
intptr_t node = contendersList_.load(std::memory_order_acquire);
for (;;) {
waiter->setNext(reinterpret_cast<LinkedNode*>(node & ~kLockBit));
if (contendersList_.compare_exchange_weak(node,
reinterpret_cast<intptr_t>(waiter) | kLockBit,
std::memory_order_acq_rel, std::memory_order_acquire)) {
break;
}
}