Skip to content

Commit

Permalink
rename
Browse files Browse the repository at this point in the history
  • Loading branch information
kimbarrett committed Jun 6, 2021
1 parent 6f2cef7 commit 8fe607c
Show file tree
Hide file tree
Showing 5 changed files with 73 additions and 70 deletions.
6 changes: 3 additions & 3 deletions src/hotspot/share/gc/g1/g1DirtyCardQueue.cpp
Expand Up @@ -45,8 +45,8 @@
#include "runtime/thread.inline.hpp"
#include "runtime/threadSMR.hpp"
#include "utilities/globalCounter.inline.hpp"
#include "utilities/lockFreeQueue.inline.hpp"
#include "utilities/macros.hpp"
#include "utilities/nonblockingQueue.inline.hpp"
#include "utilities/pair.hpp"
#include "utilities/quickSort.hpp"
#include "utilities/ticks.hpp"
Expand Down Expand Up @@ -131,8 +131,8 @@ void G1DirtyCardQueueSet::enqueue_completed_buffer(BufferNode* cbn) {
}

// Thread-safe attempt to remove and return the first buffer from
// the _completed queue, using the LockFreeQueue::try_pop() underneath.
// It has a restriction that it may return NULL when there are objects
// the _completed queue, using the NonblockingQueue::try_pop() underneath.
// It has a limitation that it may return NULL when there are objects
// in the queue if there is a concurrent push/append operation.
BufferNode* G1DirtyCardQueueSet::dequeue_completed_buffer() {
Thread* current_thread = Thread::current();
Expand Down
8 changes: 4 additions & 4 deletions src/hotspot/share/gc/g1/g1DirtyCardQueue.hpp
Expand Up @@ -32,7 +32,7 @@
#include "gc/shared/ptrQueue.hpp"
#include "memory/allocation.hpp"
#include "memory/padded.hpp"
#include "utilities/lockFreeQueue.hpp"
#include "utilities/nonblockingQueue.hpp"

class G1ConcurrentRefineThread;
class G1DirtyCardQueueSet;
Expand Down Expand Up @@ -164,9 +164,9 @@ class G1DirtyCardQueueSet: public PtrQueueSet {
volatile size_t _num_cards;
DEFINE_PAD_MINUS_SIZE(2, DEFAULT_CACHE_LINE_SIZE, sizeof(size_t));
// Buffers ready for refinement.
// LockFreeQueue has inner padding of one cache line.
LockFreeQueue<BufferNode, &BufferNode::next_ptr> _completed;
// Add a trailer padding after LockFreeQueue.
// NonblockingQueue has inner padding of one cache line.
NonblockingQueue<BufferNode, &BufferNode::next_ptr> _completed;
// Add a trailer padding after NonblockingQueue.
DEFINE_PAD_MINUS_SIZE(3, DEFAULT_CACHE_LINE_SIZE, sizeof(BufferNode*));
// Buffers for which refinement is temporarily paused.
// PausedBuffers has inner padding, including trailer.
Expand Down
Expand Up @@ -22,25 +22,28 @@
*
*/

#ifndef SHARE_UTILITIES_LOCKFREEQUEUE_HPP
#define SHARE_UTILITIES_LOCKFREEQUEUE_HPP
#ifndef SHARE_UTILITIES_NONBLOCKINGQUEUE_HPP
#define SHARE_UTILITIES_NONBLOCKINGQUEUE_HPP

#include "memory/padded.hpp"
#include "utilities/globalDefinitions.hpp"
#include "utilities/pair.hpp"

// The LockFreeQueue template provides a non-blocking FIFO. Its structure
// and usage is similar to LockFreeStack. It provides a try_pop() function
// for the client to implement pop() according to its need (e.g., whether
// or not to retry or prevent ABA problem). It has inner padding of one
// cache line between its two internal pointer fields.
// The NonblockingQueue template provides a non-blocking FIFO. It provides a
// try_pop() function for the client to implement pop() according to its
// need (e.g., whether or not to retry or prevent ABA problem). It has inner
// padding of one cache line between its two internal pointer fields.
//
// Internally the queue has a special pseudo-element that marks the end of
// the linked list representing the queue contents. Each queue has its own
// unique special element. A pointer to this element can be recognized
// using the is_end() function. Such a pointer must never be dereferenced.
// This end marker is the value of the next member of the last element in
// the queue, and possibly other elements during modification of the queue.
// The queue is internally represented by a linked list of elements, with
// the link to the next element provided by a member of each element.
// Access to this member is provided by the next_ptr function.
//
// The queue has a special pseudo-element that marks the end of the list.
// Each queue has its own unique special element. A pointer to this element
// can be recognized using the is_end() function. Such a pointer must never
// be dereferenced. This end marker is the value of the next member of the
// last element in the queue, and possibly other elements while modifying
// the queue.
//
// A queue may temporarily appear to be empty even though elements have been
// added and not removed. For example, after running the following program,
Expand All @@ -56,22 +59,22 @@
//
// \tparam next_ptr is a function pointer. Applying this function to
// an object of type T must return a pointer to the list entry member
// of the object associated with the LockFreeQueue type.
// of the object associated with the NonblockingQueue type.
template<typename T, T* volatile* (*next_ptr)(T&)>
class LockFreeQueue {
class NonblockingQueue {
T* volatile _head;
// Padding of one cache line to avoid false sharing.
DEFINE_PAD_MINUS_SIZE(1, DEFAULT_CACHE_LINE_SIZE, sizeof(T*));
T* volatile _tail;

NONCOPYABLE(LockFreeQueue);
NONCOPYABLE(NonblockingQueue);

// Return the entry following node in the list used by the
// specialized LockFreeQueue class.
// specialized NonblockingQueue class.
static inline T* next(const T& node);

// Set the entry following node to new_next in the list used by the
// specialized LockFreeQueue class. Not thread-safe, as it cannot
// specialized NonblockingQueue class. Not thread-safe, as it cannot
// concurrently run with push or try_pop operations that modify this
// node.
static inline void set_next(T& node, T* new_next);
Expand All @@ -81,8 +84,8 @@ class LockFreeQueue {
inline T* end_marker() const;

public:
inline LockFreeQueue();
inline ~LockFreeQueue() NOT_DEBUG(= default);
inline NonblockingQueue();
inline ~NonblockingQueue() NOT_DEBUG(= default);

// Return true if the queue is empty.
// Not thread-safe. There must be no concurrent modification while the
Expand Down Expand Up @@ -130,4 +133,4 @@ class LockFreeQueue {
inline bool is_end(const T* entry) const;
};

#endif // SHARE_UTILITIES_LOCKFREEQUEUE_HPP
#endif // SHARE_UTILITIES_NONBLOCKINGQUEUE_HPP
Expand Up @@ -22,29 +22,29 @@
*
*/

#ifndef SHARE_UTILITIES_LOCKFREEQUEUE_INLINE_HPP
#define SHARE_UTILITIES_LOCKFREEQUEUE_INLINE_HPP
#ifndef SHARE_UTILITIES_NONBLOCKINGQUEUE_INLINE_HPP
#define SHARE_UTILITIES_NONBLOCKINGQUEUE_INLINE_HPP

#include "utilities/lockFreeQueue.hpp"
#include "utilities/nonblockingQueue.hpp"

#include "runtime/atomic.hpp"

template<typename T, T* volatile* (*next_ptr)(T&)>
T* LockFreeQueue<T, next_ptr>::next(const T& node) {
T* NonblockingQueue<T, next_ptr>::next(const T& node) {
return Atomic::load(next_ptr(const_cast<T&>(node)));
}

template<typename T, T* volatile* (*next_ptr)(T&)>
void LockFreeQueue<T, next_ptr>::set_next(T& node, T* new_next) {
Atomic::store(next_ptr(node), new_next);
void NonblockingQueue<T, next_ptr>::set_next(T& node, T* new_next) {
Atomic::store(next_ptr(node), new_next);
}

template<typename T, T* volatile* (*next_ptr)(T&)>
LockFreeQueue<T, next_ptr>::LockFreeQueue() : _head(NULL), _tail(NULL) {}
NonblockingQueue<T, next_ptr>::NonblockingQueue() : _head(NULL), _tail(NULL) {}

#ifdef ASSERT
template<typename T, T* volatile* (*next_ptr)(T&)>
LockFreeQueue<T, next_ptr>::~LockFreeQueue() {
NonblockingQueue<T, next_ptr>::~NonblockingQueue() {
assert(_head == NULL, "precondition");
assert(_tail == NULL, "precondition");
}
Expand All @@ -54,28 +54,28 @@ LockFreeQueue<T, next_ptr>::~LockFreeQueue() {
// case queue elements can make their way through multiple queues. A
// pointer to the queue itself (after casting) satisfies that requirement.
template<typename T, T* volatile* (*next_ptr)(T&)>
T* LockFreeQueue<T, next_ptr>::end_marker() const {
T* NonblockingQueue<T, next_ptr>::end_marker() const {
return const_cast<T*>(reinterpret_cast<const T*>(this));
}

template<typename T, T* volatile* (*next_ptr)(T&)>
T* LockFreeQueue<T, next_ptr>::first() const {
T* NonblockingQueue<T, next_ptr>::first() const {
T* head = Atomic::load(&_head);
return head == NULL ? end_marker() : head;
}

template<typename T, T* volatile* (*next_ptr)(T&)>
bool LockFreeQueue<T, next_ptr>::is_end(const T* entry) const {
bool NonblockingQueue<T, next_ptr>::is_end(const T* entry) const {
return entry == end_marker();
}

template<typename T, T* volatile* (*next_ptr)(T&)>
bool LockFreeQueue<T, next_ptr>::empty() const {
bool NonblockingQueue<T, next_ptr>::empty() const {
return Atomic::load(&_head) == NULL;
}

template<typename T, T* volatile* (*next_ptr)(T&)>
size_t LockFreeQueue<T, next_ptr>::length() const {
size_t NonblockingQueue<T, next_ptr>::length() const {
size_t result = 0;
for (T* cur = first(); !is_end(cur); cur = next(*cur)) {
++result;
Expand All @@ -101,7 +101,7 @@ size_t LockFreeQueue<T, next_ptr>::length() const {
// A push operation is just a degenerate append, where the object being pushed
// is both the head and the tail of the list being appended.
template<typename T, T* volatile* (*next_ptr)(T&)>
void LockFreeQueue<T, next_ptr>::append(T& first, T& last) {
void NonblockingQueue<T, next_ptr>::append(T& first, T& last) {
assert(next(last) == NULL, "precondition");
set_next(last, end_marker());
T* old_tail = Atomic::xchg(&_tail, &last);
Expand All @@ -116,7 +116,7 @@ void LockFreeQueue<T, next_ptr>::append(T& first, T& last) {
}

template<typename T, T* volatile* (*next_ptr)(T&)>
bool LockFreeQueue<T, next_ptr>::try_pop(T** node_ptr) {
bool NonblockingQueue<T, next_ptr>::try_pop(T** node_ptr) {
// We only need memory_order_consume. Upgrade it to "load_acquire"
// as the memory_order_consume API is not ready for use yet.
T* result = Atomic::load_acquire(&_head);
Expand Down Expand Up @@ -177,15 +177,15 @@ bool LockFreeQueue<T, next_ptr>::try_pop(T** node_ptr) {
}

template<typename T, T* volatile* (*next_ptr)(T&)>
T* LockFreeQueue<T, next_ptr>::pop() {
T* NonblockingQueue<T, next_ptr>::pop() {
T* result = NULL;
while (!try_pop(&result)) {}
return result;
}


template<typename T, T* volatile* (*next_ptr)(T&)>
Pair<T*, T*> LockFreeQueue<T, next_ptr>::take_all() {
Pair<T*, T*> NonblockingQueue<T, next_ptr>::take_all() {
T* tail = Atomic::load(&_tail);
if (tail != NULL) set_next(*tail, NULL); // Clear end marker.
Pair<T*, T*> result(Atomic::load(&_head), tail);
Expand All @@ -194,4 +194,4 @@ Pair<T*, T*> LockFreeQueue<T, next_ptr>::take_all() {
return result;
}

#endif // SHARE_UTILITIES_LOCKFREEQUEUE_INLINE_HPP
#endif // SHARE_UTILITIES_NONBLOCKINGQUEUE_INLINE_HPP
Expand Up @@ -25,14 +25,14 @@
#include "memory/allocation.inline.hpp"
#include "runtime/atomic.hpp"
#include "utilities/globalDefinitions.hpp"
#include "utilities/lockFreeQueue.inline.hpp"
#include "utilities/nonblockingQueue.inline.hpp"
#include "utilities/pair.hpp"
#include "threadHelper.inline.hpp"
#include "unittest.hpp"
#include <new>

class LockFreeQueueTestElement {
typedef LockFreeQueueTestElement Element;
class NonblockingQueueTestElement {
typedef NonblockingQueueTestElement Element;

Element* volatile _entry;
Element* volatile _entry1;
Expand All @@ -42,17 +42,17 @@ class LockFreeQueueTestElement {
static Element* volatile* entry1_ptr(Element& e) { return &e._entry1; }

public:
using TestQueue = LockFreeQueue<Element, &entry_ptr>;
using TestQueue1 = LockFreeQueue<Element, &entry1_ptr>;
using TestQueue = NonblockingQueue<Element, &entry_ptr>;
using TestQueue1 = NonblockingQueue<Element, &entry1_ptr>;

LockFreeQueueTestElement(size_t id = 0) : _entry(), _entry1(), _id(id) {}
NonblockingQueueTestElement(size_t id = 0) : _entry(), _entry1(), _id(id) {}
size_t id() const { return _id; }
void set_id(size_t value) { _id = value; }
Element* next() { return _entry; }
Element* next1() { return _entry1; }
};

typedef LockFreeQueueTestElement Element;
typedef NonblockingQueueTestElement Element;
typedef Element::TestQueue TestQueue;
typedef Element::TestQueue1 TestQueue1;

Expand All @@ -76,22 +76,22 @@ static void initialize(Element* elements, size_t size, TestQueue* queue) {
}
}

class LockFreeQueueTestBasics : public ::testing::Test {
class NonblockingQueueTestBasics : public ::testing::Test {
public:
LockFreeQueueTestBasics();
NonblockingQueueTestBasics();

static const size_t nelements = 10;
Element elements[nelements];
TestQueue queue;
};

const size_t LockFreeQueueTestBasics::nelements;
const size_t NonblockingQueueTestBasics::nelements;

LockFreeQueueTestBasics::LockFreeQueueTestBasics() : queue() {
NonblockingQueueTestBasics::NonblockingQueueTestBasics() : queue() {
initialize(elements, nelements, &queue);
}

TEST_F(LockFreeQueueTestBasics, pop) {
TEST_F(NonblockingQueueTestBasics, pop) {
for (size_t i = 0; i < nelements; ++i) {
ASSERT_FALSE(queue.empty());
ASSERT_EQ(nelements - i, queue.length());
Expand All @@ -105,7 +105,7 @@ TEST_F(LockFreeQueueTestBasics, pop) {
ASSERT_TRUE(queue.pop() == NULL);
}

TEST_F(LockFreeQueueTestBasics, append) {
TEST_F(NonblockingQueueTestBasics, append) {
TestQueue other_queue;
ASSERT_TRUE(other_queue.empty());
ASSERT_EQ(0u, other_queue.length());
Expand All @@ -131,7 +131,7 @@ TEST_F(LockFreeQueueTestBasics, append) {
ASSERT_TRUE(other_queue.pop() == NULL);
}

TEST_F(LockFreeQueueTestBasics, two_queues) {
TEST_F(NonblockingQueueTestBasics, two_queues) {
TestQueue1 queue1;
ASSERT_TRUE(queue1.pop() == NULL);

Expand Down Expand Up @@ -175,7 +175,7 @@ TEST_F(LockFreeQueueTestBasics, two_queues) {
ASSERT_TRUE(queue1.pop() == NULL);
}

class LockFreeQueueTestThread : public JavaTestThread {
class NonblockingQueueTestThread : public JavaTestThread {
uint _id;
TestQueue* _from;
TestQueue* _to;
Expand All @@ -185,12 +185,12 @@ class LockFreeQueueTestThread : public JavaTestThread {
volatile bool _ready;

public:
LockFreeQueueTestThread(Semaphore* post,
uint id,
TestQueue* from,
TestQueue* to,
volatile size_t* processed,
size_t process_limit) :
NonblockingQueueTestThread(Semaphore* post,
uint id,
TestQueue* from,
TestQueue* to,
volatile size_t* processed,
size_t process_limit) :
JavaTestThread(post),
_id(id),
_from(from),
Expand Down Expand Up @@ -219,7 +219,7 @@ class LockFreeQueueTestThread : public JavaTestThread {
bool ready() const { return Atomic::load_acquire(&_ready); }
};

TEST_VM(LockFreeQueueTest, stress) {
TEST_VM(NonblockingQueueTest, stress) {
Semaphore post;
TestQueue initial_queue;
TestQueue start_queue;
Expand All @@ -244,7 +244,7 @@ TEST_VM(LockFreeQueueTest, stress) {
const uint stage1_threads = 2;
const uint stage2_threads = 2;
const uint nthreads = stage1_threads + stage2_threads;
LockFreeQueueTestThread* threads[nthreads] = {};
NonblockingQueueTestThread* threads[nthreads] = {};

for (uint i = 0; i < ARRAY_SIZE(threads); ++i) {
TestQueue* from = &start_queue;
Expand All @@ -256,7 +256,7 @@ TEST_VM(LockFreeQueueTest, stress) {
processed = &stage2_processed;
}
threads[i] =
new LockFreeQueueTestThread(&post, i, from, to, processed, nelements);
new NonblockingQueueTestThread(&post, i, from, to, processed, nelements);
threads[i]->doit();
while (!threads[i]->ready()) {} // Wait until ready to start test.
}
Expand Down

0 comments on commit 8fe607c

Please sign in to comment.