#ifndef _EVENTCOUNT_H
#define _EVENTCOUNT_H
-#include <unrelacy.h>
+//#include <unrelacy.h>
#include <atomic>
#include <mutex>
#include <condition_variable>
void signal()
{
+ // We might be able to use release here because it basically only needs
+ // to synchronize with the get()
unsigned cmp = count.fetch_add(0, std::memory_order_seq_cst);
signal_impl(cmp);
}
~spsc_queue()
{
//RL_ASSERT(head == tail);
- delete ((node*)head($));
+ //delete ((node*)head($));
+ delete ((node*)head);
}
/**
LANG = CPP;
CLASS = spsc_queue;
@Global_define:
- @DeclareStruct:
- typedef struct tag_elem {
- call_id_t id;
- T data;
- } tag_elem_t;
-
@DeclareVar:
- spec_list *__queue;
- id_tag_t *tag;
+ IntegerList *__queue;
@InitVar:
- __queue = new_spec_list();
- tag = new_id_tag();
- @DefineFunc:
- tag_elem_t* new_tag_elem(call_id_t id, T data) {
- tag_elem_t *e = (tag_elem_t*) MODEL_MALLOC(sizeof(tag_elem_t));
- e->id = id;
- e->data = data;
- return e;
- }
- @DefineFunc:
- call_id_t get_id(void *wrapper) {
- return ((tag_elem_t*) wrapper)->id;
- }
- @DefineFunc:
- unsigned int get_data(void *wrapper) {
- return ((tag_elem_t*) wrapper)->data;
- }
- @Happens_before: Enqueue -> Dequeue
+ __queue = createIntegerList();
+ @Finalize:
+ if (__queue)
+ destroyIntegerList(__queue);
+ return true;
+ @Happens_before: Enqueue -> Dequeue
+ @Commutativity: Enqueue <-> Dequeue: true
+ @Commutativity: Dequeue <-> Dequeue: !_Method1.__RET__ || !_Method2.__RET__
+
@End
*/
@Begin
@Interface: Enqueue
@Commit_point_set: Enqueue_Point
- @ID: get_and_inc(tag)
- @Action: push_back(__queue, new_tag_elem(__ID__, data));
- //tag_elem_t *elem = new_tag_elem(__ID__, data);
- //push_back(__queue, elem);
+ @ID: data
+ @Action:
+ push_back(__queue, data);
+ //model_print("Enqueue: val=%d\n", val);
@End
*/
void enqueue(T data)
{
node* n = new node (data);
- head($)->next.store(n, std::memory_order_release);
+ /********** DR & SPEC (sequential) **********/
+ //head($)->next.store(n, std::memory_order_release);
+ head->next.store(n, std::memory_order_release);
/**
@Begin
@Commit_point_define_check: true
@Begin
@Interface: Dequeue
@Commit_point_set: Dequeue_Point
- @ID: get_id(front(__queue))
+ @ID: __RET__ ? __RET__ : 0
@Action:
- T _Old_Val = get_data(front(__queue));
- pop_front(__queue);
- @Post_check: _Old_Val == __RET__
+ int elem = 0;
+ if (__RET__) {
+ elem = front(__queue);
+ pop_front(__queue);
+ }
+ //model_print("Dequeue: __RET__=%d, retVal=%d, elem=%d, \n", __RET__, *retVal, elem);
+ //model_print("Result: %d\n", __RET__ ? *retVal == elem : true);
+ @Post_check: __RET__ ? __RET__ == elem : true
@End
*/
T dequeue()
struct node
{
std::atomic<node*> next;
- rl::var<T> data;
+ //rl::var<T> data;
+ T data;
node(T data = T())
: data(data)
}
};
- rl::var<node*> head;
- rl::var<node*> tail;
+ //rl::var<node*> head;
+ //rl::var<node*> tail;
+ node *head;
+ node *tail;
+
+
eventcount ec;
T try_dequeue()
{
- node* t = tail($);
+ //node* t = tail($);
+ node *t = tail;
+ /********** DR & SPEC (sequential) **********/
node* n = t->next.load(std::memory_order_acquire);
/**
@Begin
*/
if (0 == n)
return 0;
- T data = n->data($);
+ //T data = n->data($);
+ T data = n->data;
delete (t);
tail = n;
return data;
concurrent-hashmap seqlock spsc-example spsc-queue-scfence \
treiber-stack
-DIRS := ms-queue concurrent-hashmap linuxrwlocks mcs-lock read-copy-update chase-lev-deque-bugfix
+DIRS := ms-queue concurrent-hashmap linuxrwlocks mcs-lock read-copy-update \
+ chase-lev-deque-bugfix spsc-bugfix mpmc-queue
.PHONY: $(DIRS)
--- /dev/null
+include ../benchmarks.mk
+
+TESTNAME = mpmc-queue
+TESTS = mpmc-queue mpmc-1r2w mpmc-2r1w mpmc-queue-rdwr
+TESTS += mpmc-queue-noinit mpmc-1r2w-noinit mpmc-2r1w-noinit mpmc-rdwr-noinit
+
+all: $(TESTS)
+
+mpmc-queue: CPPFLAGS += -DCONFIG_MPMC_READERS=2 -DCONFIG_MPMC_WRITERS=2
+mpmc-queue-rdwr: CPPFLAGS += -DCONFIG_MPMC_READERS=0 -DCONFIG_MPMC_WRITERS=0 -DCONFIG_MPMC_RDWR=2
+mpmc-1r2w: CPPFLAGS += -DCONFIG_MPMC_READERS=1 -DCONFIG_MPMC_WRITERS=2
+mpmc-2r1w: CPPFLAGS += -DCONFIG_MPMC_READERS=2 -DCONFIG_MPMC_WRITERS=1
+mpmc-queue-noinit: CPPFLAGS += -DCONFIG_MPMC_READERS=2 -DCONFIG_MPMC_WRITERS=2 -DCONFIG_MPMC_NO_INITIAL_ELEMENT
+mpmc-1r2w-noinit: CPPFLAGS += -DCONFIG_MPMC_READERS=1 -DCONFIG_MPMC_WRITERS=2 -DCONFIG_MPMC_NO_INITIAL_ELEMENT
+mpmc-2r1w-noinit: CPPFLAGS += -DCONFIG_MPMC_READERS=2 -DCONFIG_MPMC_WRITERS=1 -DCONFIG_MPMC_NO_INITIAL_ELEMENT
+mpmc-rdwr-noinit: CPPFLAGS += -DCONFIG_MPMC_READERS=0 -DCONFIG_MPMC_WRITERS=0 -DCONFIG_MPMC_RDWR=2 -DCONFIG_MPMC_NO_INITIAL_ELEMENT
+
+$(TESTS): $(TESTNAME).cc $(TESTNAME).h
+ $(CXX) -o $@ $< $(CXXFLAGS) $(LDFLAGS)
+
+clean:
+ rm -f $(TESTS) *.o
--- /dev/null
+include ../benchmarks.mk
+
+TESTNAME = spsc-queue
+RELACYNAME = spsc-relacy
+
+all: $(TESTNAME)
+
+$(TESTNAME): $(TESTNAME).cc queue.h eventcount.h
+ $(CXX) -o $@ $< $(CXXFLAGS) $(LDFLAGS)
+
+relacy: $(RELACYNAME)
+
+$(RELACYNAME): spsc-relacy.cc queue-relacy.h eventcount-relacy.h
+ifdef RELACYPATH
+ $(CXX) -o $(RELACYNAME) spsc-relacy.cc -I$(RELACYPATH) -Wno-deprecated
+else
+ @echo "Please define RELACYPATH"
+ @echo " e.g., make RELACYPATH=/path-to-relacy"
+ @exit 1
+endif
+
+clean:
+ rm -f $(TESTNAME) $(RELACYNAME) *.o
new File(homeDir + "/benchmark/mcs-lock/mcs-lock.cc"),
new File(homeDir + "/benchmark/mcs-lock/mcs-lock.h") };
//
-// File[] srcSPSCQueue = {
-// new File(homeDir + "/benchmark/spsc-bugfix/spsc-queue.cc"),
-// new File(homeDir + "/benchmark/spsc-bugfix/eventcount.h"),
-// new File(homeDir + "/benchmark/spsc-bugfix/queue.h") };
+ File[] srcSPSCQueue = {
+ new File(homeDir + "/benchmark/spsc-bugfix/spsc-queue.cc"),
+ new File(homeDir + "/benchmark/spsc-bugfix/eventcount.h"),
+ new File(homeDir + "/benchmark/spsc-bugfix/queue.h") };
+
+ File[] srcMPMCQueue = {
+ new File(homeDir + "/benchmark/mpmc-queue/mpmc-queue.h"),
+ new File(homeDir + "/benchmark/mpmc-queue/mpmc-queue.cc") };
//
-// File[] srcMPMCQueue = {
-// new File(homeDir + "/benchmark/mpmc-queue/mpmc-queue.h"),
-// new File(homeDir + "/benchmark/mpmc-queue/mpmc-queue.cc") };
-//
-// File[][] sources = { srcLinuxRWLocks, srcMSQueue, srcRCU,
+// File[][] sources = {srcLinuxRWLock1 , srcMSQueue, srcRCU,
// srcDeque, srcMCSLock, srcSPSCQueue, srcMPMCQueue, srcHashtable };
- File[][] sources = {srcDeque};
+// File[][] sources = {srcDeque, srcLinuxRWLock1, srcLinuxRWLock2, srcLinuxRWLock3, srcMCSLock, srcHashtable, srcRCU};
+ File[][] sources = {srcMPMCQueue};
// Compile all the benchmarks
for (int i = 0; i < sources.length; i++) {
CodeGenerator gen = new CodeGenerator(sources[i]);
newCode.add(DECLARE("void**", varPrefix + "func_ptr_table"));
newCode.add(templateDecl);
newCode.add(DECLARE("hb_rule**", varPrefix + "hb_rule_table"));
+ newCode.add(templateDecl);
newCode.add(DECLARE("commutativity_rule**", varPrefix + "commutativity_rule_table"));
for (int i = 0; i < construct.code.declareVar.size(); i++) {
VariableDeclaration varDecl = construct.code.declareVar.get(i);