Skip to content
Snippets Groups Projects

Add new argument to info fibres to enable grouping by line/stack

Merged Mohammed Bilal Akhtar requested to merge mbakhtar/KOS:fibre-grouping-initial into master
Files
16
@@ -362,20 +362,18 @@ private:
public:
IntrusiveQueueNemesis(): head(nullptr), tail(nullptr) {}
bool push(T& first, T& last) {
void push(T& first, T& last) {
last.link[NUM].next = nullptr;
// make sure previous write to 'next' and following write to 'head' are not reordered with this update
T* prev = __atomic_exchange_n(&tail, &last, __ATOMIC_SEQ_CST); // swing tail to last of new element(s)
if (prev) {
prev->link[NUM].next = &first;
return false;
} else {
head = &first;
return true;
}
}
bool push(T& elem) { return push(elem, elem); }
void push(T& elem) { push(elem, elem); }
T* peek() { return head; }
@@ -400,30 +398,29 @@ public:
return element;
}
bool transferAllFrom(IntrusiveQueue<T,NUM,CNT,LT>& eq) {
if (eq.empty()) return false;
void transferAllFrom(IntrusiveQueue<T,NUM,CNT,LT>& eq) {
if (eq.empty()) return;
T* first = eq.front();
T* last = eq.popAll();
return push(*first, *last);
push(*first, *last);
}
};
// NOTE WELL: This simple design using Link* for 'head' and 'tail' and downcasting
// only works, if Link is the first class that T inherits from.
//
// http://doc.cat-v.org/inferno/concurrent_gc/concurrent_gc.pdf
// https://www.cs.rice.edu/~johnmc/papers/cqueues-mellor-crummey-TR229-1987.pdf
// http://www.1024cores.net/home/lock-free-algorithms/queues/intrusive-mpsc-node-based-queue
// https://github.com/samanbarghi/MPSCQ/blob/master/src/MPSCQueue.h
//
// NOTE WELL: Downcasting 'stub' only works, if Link is the first class that T inherits from.
template<typename T, size_t NUM, size_t CNT, typename LT, bool Blocking> class IntrusiveQueueStub {
static_assert(NUM < CNT, "NUM >= CNT");
public:
typedef LT Link;
private:
Link stub;
Link* head;
Link* tail;
Link stub;
T* head;
T* tail;
// peek/pop operate in chunks of elements and re-append stub after each chunk
// after re-appending stub, tail points to stub, if no further insertions -> empty!
@@ -446,8 +443,9 @@ private:
}
public:
IntrusiveQueueStub() : head(&stub), tail(&stub) {
if (Blocking) tail = (Link*)(uintptr_t(tail) | 1); // mark queue empty
IntrusiveQueueStub() {
head = tail = stub.link[NUM].next = stub.link[NUM].prev = static_cast<T*>(&stub);
if (Blocking) tail = (T*)(uintptr_t(tail) | 1); // mark queue empty
}
bool push(Link& first, Link& last) {
@@ -458,7 +456,7 @@ public:
empty = uintptr_t(prev) & 1; // check empty marking
prev = (Link*)(uintptr_t(prev) & ~uintptr_t(1)); // clear marking
}
prev->link[NUM].next = &static_cast<T&>(first); // append segments to previous tail
prev->link[NUM].next = static_cast<T*>(&first); // append segments to previous tail
return empty;
}
@@ -466,13 +464,13 @@ public:
T* peek() {
if (!checkStub()) return nullptr;
return static_cast<T*>(head);
return head;
}
template<bool Peeked = false>
T* pop() {
if (!Peeked && !checkStub()) return nullptr;
T* retval = static_cast<T*>(head); // head will be returned
T* retval = head; // head will be returned
while (!(T* volatile)head->link[NUM].next) Pause(); // producer in push()
head = head->link[NUM].next; // remove head
#if TESTING_ENABLE_ASSERTIONS
@@ -483,8 +481,8 @@ public:
bool transferAllFrom(IntrusiveQueue<T,NUM,CNT,LT>& eq) {
if (eq.empty()) return false;
Link* first = eq.front();
Link* last = eq.popAll();
T* first = eq.front();
T* last = eq.popAll();
return push(*first, *last);
}
};
Loading