Implementations of concurrent data structures from The Art of Multiprocessor Programming, designed for automatic formal verification.
This repository contains implementations of data structures from The Art of
Multiprocessor Programming in CIVL-C for model checking with CIVL.
A recent installation of the CIVL model checker is required. Installation
directions can be found here: http://vsl.cis.udel.edu:8080/civl/index.html.
To tell AMPVer where to find your CIVL installation, make a copy of
config/config_default.mk
called config/config.mk
and set the CIVL_ROOT
and
VSL_DEPS
arguments appropriately.
Once your CIVL installation is set up and you’ve configured AMPVer to point to
that installation, you can verify any of the implemented data structures using
our Makefile rules, which use various preset bounds as described in the paper.
The Makefile includes rules to run all the experiments in the paper.
The core experiments are divided into four categories: (hash) sets, lists,
queues, and priority queues. Each category has multiple sets of limits, which
are the parameters for the experiments passed to the AMPVer tool. The limits are
defined in the variables HASHSET_LIMITS_n
, LIST_LIMITS_n
, QUEUE_LIMITS_n
,
and PQUEUE_LIMITS_n
, where n is the number of the limit set. For example,
HASHSET_LIMITS_1
is the limit set for the first and smallest core set
experiment. To run all of the core experiments for a particular category and
size, make the corresponding target.
Below is a list of the targets for each category:
hashset_1
, hashset_2
, hashset_3
, hashset_4
list_1
, list_2
, list_3
, list_4
queue_1
, queue_2
, queue_3
pqueue_1
, pqueue_2
, pqueue_3
, pqueue_4
For an example, to verify all lists using the second set of limits, one would
run:
make list_2
The output of each experiment is stored in the out/
directory. The summary
output for each data structure is stored in a file named out/DS_n.out
, where
DS
is the name of the data structure and n
is the limit set. The outputs for
each schedule are stored in separate files in under a directory named
out/DS_n.dir
, following the same naming convention. For example, the output
for the CoarseHashSet
data structure using the first set of limits is stored
in out/CoarseHashSet_1.out
, and the output for the first schedule is stored in
out/CoarseHashSet_1.dir/schedule_1.out
, along with the CIVL schedule
configuration file as schedule_1.cvl
. To run just one data structure and limit
set combination, one can run the corresponding target. For example, to run just
the CoarseHashSet
data structure using the first set of limits, one would run:
make out/CoarseHashSet_1.out
Some data structures have additional variants that can also be verified. The
variant names are appended to the data structure name. The available variants
are listed and described below. These variants are included in the core
experiment targets described above.
LockFreeList
: LockFreeListOriginal
FineGrainedHeap
: FineGrainedHeapFair
, FineGrainedHeapNoCycles
Fair
: uses a fair ReentrantLock
instead of the original ReentrantLock
.-fair
flag to AMPVer, which indicates thread scheduling mustNoCycles
: removes the -checkTermination
flag from AMPVer, which meansSkipQueue
: SkipQueuePatched
Patched
: uses a patched version of the SkipQueue
data structure thatFindAndMarkMin
as described in the paper.In addition to the core experiments above, the Makefile also includes targets
for running particular individual schedules of interest. These targets are
described below. Currently, the only schedules of interest are for priority
queues.
PQUEUE_SCHED_1
: a schedule that reveals the non-linearizable behavior inSkipQueuePatched
.PQUEUE_SCHED_2
: a schedule that reveals the cycle violation in SkipQueue
.PQUEUE_SCHED_3
: same as PQUEUE_SCHED_2
, but one fewer pre-add and onePQUEUE_SCHED_4
: a schedule of similar size to the above that reveals noSkipQueue
or SkipQueuePatched
.Individual schedules can be run using a target of the form out/DS_Sn
, where
DS
is the name of the data structure, including any variants, and n
is the
number of the schedule. Note the use of the letter S
before the schedule number
to indicate that it is a schedule rule. The output of the schedule is stored in
out/DS_Sn
. For example, to run the first schedule for SkipQueuePatched
, one
would run:
make out/SkipQueuePatched_S1
All schedules for all priority queues can be run using the target
pqueue_schedules
:
make pqueue_schedules
All page numbers taken from the 2nd Edition.
CoarseList
:
src/list/CoarseList.cvl
FineList
:
src/list/FineList.cvl
OptimisticList
:
src/list/OptimisticList.cvl
LazyList
:
src/list/LazyList.cvl
LockFreeList
:
src/list/LockFreeList.cvl
BoundedQueue
:
src/queue/BoundedQueue.cvl
UnboundedQueue
:
src/queue/UnboundedQueue.cvl
LockFreeQueue
:
src/queue/LockFreeQueue.cvl
CoarseHashSet
:
src/hashset/CoarseHashSet.cvl
StripedHashSet
:
src/hashset/StripedHashSet.cvl
StripedCuckooHashSet
:
src/hashset/StripedCuckooHashSet.cvl
FineGrainedHeap
:
src/pqueue/FineGrainedHeap.cvl
SkipQueue
:
src/pqueue/SkipQueue.cvl
Note that barrier verification is performed using a separate driver and Makefile
found under src/barrier
.
Sense-reversing Barrier
Combining Tree Barrier
Static Tree Barrier
Reverse Tree Barrier
TODO: