├── .gitignore
├── CMakeLists.txt
├── COPYING
├── Makefile
├── README.md
├── bench.py
├── doc
├── .gitignore
├── CMakeLists.txt
└── Doxyfile.in
├── lib
├── capq
│ ├── README
│ ├── binheap.h
│ ├── binheap_test.c
│ ├── capq.c
│ ├── capq.h
│ ├── fat_skiplist.c
│ ├── fat_skiplist.h
│ ├── gc
│ │ ├── gc.c
│ │ ├── gc.h
│ │ ├── intel_defns.h
│ │ ├── portable_defns.h
│ │ ├── ptst.c
│ │ ├── ptst.h
│ │ └── random.h
│ └── qdlocksrc
│ │ ├── LICENSE
│ │ ├── README
│ │ ├── locks
│ │ ├── ccsynch_lock.c
│ │ ├── ccsynch_lock.h
│ │ ├── drmcs_lock.c
│ │ ├── drmcs_lock.h
│ │ ├── hqd_lock.c
│ │ ├── hqd_lock.h
│ │ ├── locks.h
│ │ ├── mcs_lock.c
│ │ ├── mcs_lock.h
│ │ ├── mrqd_lock.c
│ │ ├── mrqd_lock.h
│ │ ├── oo_lock_interface.h
│ │ ├── qd_lock.c
│ │ ├── qd_lock.h
│ │ ├── seq_lock.c
│ │ ├── seq_lock.h
│ │ ├── tatas_lock.c
│ │ ├── tatas_lock.h
│ │ ├── ticket_lock.c
│ │ └── ticket_lock.h
│ │ ├── misc
│ │ ├── bitreversal.h
│ │ ├── bsd_stdatomic.h
│ │ ├── error_help.h
│ │ ├── misc_utils.h
│ │ ├── padded_types.h
│ │ ├── random.h
│ │ └── thread_includes.h
│ │ ├── qd_queues
│ │ └── qd_queue.h
│ │ └── read_indicators
│ │ ├── reader_groups_read_indicator.c
│ │ └── reader_groups_read_indicator.h
├── sequence_heap
│ ├── README
│ ├── heap-CLR.h
│ ├── heap2.h
│ ├── heap4.h
│ ├── hold.C
│ ├── knheap.C
│ ├── knheap.h
│ ├── knupdown3.C
│ ├── knwiggle.C
│ ├── multiMergeUnrolled.C
│ ├── readme.asc
│ └── util.h
├── skip_list
│ ├── .gitignore
│ ├── README.md
│ ├── TODO.md
│ ├── random_access_skip_list.h
│ ├── skip_list.h
│ ├── skip_list_detail.h
│ └── tests
│ │ ├── benchmark.cpp
│ │ ├── catch.hpp
│ │ ├── get_time.h
│ │ ├── test.sh
│ │ ├── test_multi_skip_list.cpp
│ │ ├── test_random_access.cpp
│ │ ├── test_skip_list.cpp
│ │ └── test_types.h
└── spraylist_linden
│ ├── .gitignore
│ ├── GIT_COMMIT_ID
│ ├── LICENSE
│ ├── Makefile
│ ├── README.md
│ ├── atomic_ops
│ ├── AUTHORS
│ ├── COPYING
│ ├── README
│ ├── aligned_atomic_load_store.h
│ ├── all_acquire_release_volatile.h
│ ├── ao_t_is_int.h
│ ├── atomic_ops.h
│ ├── generalize-small.h
│ ├── generalize.h
│ ├── ia64.h
│ ├── ordered_except_wr.h
│ ├── powerpc.h
│ ├── read_ordered.h
│ ├── sparc.h
│ ├── standard_ao_double_t.h
│ ├── test_and_set_t_is_ao_t.h
│ ├── test_and_set_t_is_char.h
│ ├── x86.h
│ └── x86_64.h
│ ├── fraser.c
│ ├── fraser.h
│ ├── gc
│ ├── gc.c
│ ├── gc.h
│ ├── intel_defns.h
│ ├── portable_defns.h
│ ├── ptst.c
│ ├── ptst.h
│ └── random.h
│ ├── include
│ ├── atomic_ops_if.h
│ ├── getticks.h
│ ├── lockfree.h
│ ├── measurements.h
│ ├── random.h
│ ├── sequential.h
│ ├── ssalloc.h
│ ├── ssalloc.h~
│ ├── tm.h
│ └── utils.h
│ ├── intset.c
│ ├── intset.h
│ ├── linden.c
│ ├── linden.h
│ ├── linden_common.c
│ ├── linden_common.h
│ ├── measurements.c
│ ├── pqueue.c
│ ├── pqueue.h
│ ├── skiplist.c
│ ├── skiplist.h
│ ├── ssalloc.c
│ ├── sssp.c
│ └── test.c
├── misc
├── gpl_header
├── plot_quality.R
├── plot_throughput.R
├── pre-commit
└── unpheet.sh
├── src
├── .gitignore
├── CMakeLists.txt
├── bench
│ ├── CMakeLists.txt
│ ├── file_shortest_paths.cpp
│ ├── generate_random_graph.cpp
│ ├── heapsort.cpp
│ ├── itree.cpp
│ ├── itree.h
│ ├── pqs
│ │ ├── CMakeLists.txt
│ │ ├── cheap.h
│ │ ├── cppcapq.h
│ │ ├── cppcapq_inl.h
│ │ ├── globallock.h
│ │ ├── linden.cpp
│ │ ├── linden.h
│ │ ├── multiq.h
│ │ ├── multiq_inl.h
│ │ ├── sequence_heap.cpp
│ │ ├── sequence_heap.h
│ │ ├── skip_queue.cpp
│ │ ├── skip_queue.h
│ │ ├── spraylist.cpp
│ │ └── spraylist.h
│ ├── random.cpp
│ ├── shortest_paths.cpp
│ ├── util.cpp
│ └── util.h
├── components
│ ├── block.h
│ ├── block_inl.h
│ ├── block_storage.h
│ ├── block_storage_inl.h
│ ├── item.h
│ └── item_inl.h
├── dist_lsm
│ ├── dist_lsm.h
│ ├── dist_lsm_inl.h
│ ├── dist_lsm_local.h
│ └── dist_lsm_local_inl.h
├── k_lsm
│ ├── k_lsm.h
│ └── k_lsm_inl.h
├── multi_lsm
│ ├── multi_lsm.h
│ └── multi_lsm_inl.h
├── sequential_lsm
│ ├── CMakeLists.txt
│ ├── lsm.cpp
│ └── lsm.h
├── shared_lsm
│ ├── aligned_block_array.h
│ ├── aligned_block_array_inl.h
│ ├── block_array.h
│ ├── block_array_inl.h
│ ├── block_pivots.h
│ ├── block_pivots_inl.h
│ ├── block_pool.h
│ ├── shared_lsm.h
│ ├── shared_lsm_inl.h
│ ├── shared_lsm_local.h
│ ├── shared_lsm_local_inl.h
│ ├── versioned_array_ptr.h
│ └── versioned_array_ptr_inl.h
└── util
│ ├── CMakeLists.txt
│ ├── counters.h
│ ├── lockfree_vector.h
│ ├── mm.h
│ ├── thread_local_ptr.cpp
│ ├── thread_local_ptr.h
│ └── xorshf96.h
└── test
├── .gitignore
├── CMakeLists.txt
├── pq_par.cpp
├── pq_seq.cpp
├── relaxed_pq_seq.cpp
├── shared_lsm
├── CMakeLists.txt
├── block_array.cpp
└── versioned_array_ptr.cpp
└── util
├── CMakeLists.txt
├── lockfree_vector.cpp
├── mm.cpp
└── thread_local_ptr.cpp
/.gitignore:
--------------------------------------------------------------------------------
1 | *.swp
2 | CMakeLists.txt.user*
3 | build/
4 | callgrind.out.*
5 |
--------------------------------------------------------------------------------
/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | project(kpqueue)
2 | cmake_minimum_required(VERSION 2.8.0)
3 |
4 | find_package(Doxygen)
5 | find_package(Threads REQUIRED)
6 |
7 | include(FindPkgConfig)
8 | pkg_search_module(GSL REQUIRED gsl)
9 | pkg_search_module(HWLOC REQUIRED hwloc)
10 | pkg_search_module(VALGRIND valgrind)
11 |
12 | if(CMAKE_COMPILER_IS_GNUCXX OR CMAKE_CXX_COMPILER_ID STREQUAL "Clang")
13 | add_definitions("-Wall -Wextra -pedantic -std=c++11")
14 | endif()
15 |
16 | # Hacks needed for link-time optimizations (-flto) on mars / debian.
17 | set(CMAKE_AR "gcc-ar")
18 | set(CMAKE_RANLIB "gcc-ranlib")
19 |
20 | if(DOXYGEN_FOUND)
21 | add_subdirectory(doc)
22 | endif()
23 |
24 | if(VALGRIND_FOUND)
25 | add_definitions("-DHAVE_VALGRIND")
26 | endif()
27 |
28 | add_subdirectory(src)
29 |
30 | if(EXISTS /usr/src/gtest)
31 | enable_testing()
32 | add_subdirectory(/usr/src/gtest gtest)
33 | add_subdirectory(test)
34 | endif()
35 |
--------------------------------------------------------------------------------
/Makefile:
--------------------------------------------------------------------------------
1 | all: release
2 |
3 | debug:
4 | mkdir -p build
5 | cd build && cmake -DCMAKE_BUILD_TYPE="Debug" .. && make -j6
6 |
7 | release:
8 | mkdir -p build
9 | cd build && cmake -DCMAKE_BUILD_TYPE="Release" .. && make -j6
10 |
11 | check: debug
12 | cd build && ctest --output-on-failure
13 |
14 | doc:
15 | mkdir -p build
16 | cd build; cmake -DCMAKE_BUILD_TYPE="Debug" ..; make doc
17 |
18 | clean:
19 | rm -rf build
20 |
21 | .PHONY: build check doc clean
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | kpqueue
2 | =======
3 |
4 | This repository hosts development of a stand-alone version of the lock-free
5 | Wimmer k-priority queue (pheet.org).
6 |
7 | Running benchmarks
8 | ==================
9 |
10 | Several benchmarking tools are provided, with the most heavily used and
11 | maintained one being the random throughput benchmark (src/bench/random.cpp).
12 | The simplest way to run benchmarks is by using the provided wrapper script:
13 |
14 | ```bash
15 | $ make && ./bench.py -a klsm128,klsm256 -p 1,2,3,5,10,15,20 -r 5 -o results.csv
16 | ```
17 |
18 | Figures can then be generated by running:
19 |
20 | ```bash
21 | $ Rscript misc/plot.R results.csv && ls -lha fig.png
22 | ```
23 |
24 | Dependencies are of course required but should be simple to determine either
25 | from error messages or the scripts themselves. Most scripts and binaries may be
26 | called with the standard '-h' argument for help.
27 |
--------------------------------------------------------------------------------
/doc/.gitignore:
--------------------------------------------------------------------------------
1 | html/
2 | latex/
3 |
--------------------------------------------------------------------------------
/doc/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | configure_file(${CMAKE_CURRENT_SOURCE_DIR}/Doxyfile.in
2 | ${CMAKE_CURRENT_BINARY_DIR}/Doxyfile @ONLY
3 | )
4 |
5 | add_custom_target(doc
6 | ${DOXYGEN_EXECUTABLE} ${CMAKE_CURRENT_BINARY_DIR}/Doxyfile
7 | WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
8 | COMMENT "Generating API documentation" VERBATIM
9 | )
10 |
--------------------------------------------------------------------------------
/lib/capq/README:
--------------------------------------------------------------------------------
1 | The Contention Avoiding Priority Queue
2 | ======================================
3 |
4 | This folder contains an implementation of the contention avoiding
5 | priority queue (CA-PQ). CA-PQ is described in the paper "The Contention
6 | Avoiding Concurrent Priority Queue" which is published in the 29th
7 | International Workshop on Languages and Compilers for Parallel
8 | Computing (LCPC 2016).
9 |
10 | The official CA-PQ publication can be obtained from:
11 |
12 | * http://link.springer.com/chapter/10.1007/978-3-319-52709-3_23
13 |
14 | A preprint version of the paper is available at:
15 |
16 | * https://www.it.uu.se/research/group/languages/software/ca_pq
17 |
--------------------------------------------------------------------------------
/lib/capq/binheap.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2017 Kjell Winblad (http://winsh.me, kjellwinblad@gmail.com)
3 | *
4 | * This file is part of kpqueue.
5 | *
6 | * kpqueue is free software: you can redistribute it and/or modify
7 | * it under the terms of the GNU General Public License as published by
8 | * the Free Software Foundation, either version 3 of the License, or
9 | * (at your option) any later version.
10 | *
11 | * kpqueue is distributed in the hope that it will be useful,
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | * GNU General Public License for more details.
15 | *
16 | * You should have received a copy of the GNU General Public License
17 | * along with kpqueue. If not, see .
18 | */
19 |
20 | #include
21 | #include
22 |
23 | typedef struct {
24 | unsigned long key;
25 | unsigned long value;
26 | } node_t;
27 |
28 | #define MAX_HEAP_SIZE 8192
29 |
30 | typedef struct {
31 | int len;
32 | int size;
33 | node_t nodes[MAX_HEAP_SIZE];
34 | } heap_t;
35 |
36 | bool push(heap_t *h, unsigned long key, unsigned long value)
37 | {
38 | if (h->len + 1 >= h->size) {
39 | return false;
40 | }
41 | int i = h->len + 1;
42 | int j = i / 2;
43 | while (i > 1 && h->nodes[j].key > key) {
44 | h->nodes[i] = h->nodes[j];
45 | i = j;
46 | j = j / 2;
47 | }
48 | h->nodes[i].key = key;
49 | h->nodes[i].value = value;
50 | h->len++;
51 | return true;
52 | }
53 |
54 | bool peek(heap_t *h, unsigned long *key)
55 | {
56 | if (h->len == 0) {
57 | return false;
58 | }
59 | *key = h->nodes[1].key;
60 | return true;
61 | }
62 |
63 |
64 | bool pop(heap_t *h, unsigned long *key, unsigned long *value)
65 | {
66 | int i, j, k;
67 | if (!h->len) {
68 | return false;
69 | }
70 | h->size--;
71 | *key = h->nodes[1].key;
72 | *value = h->nodes[1].value;
73 | h->nodes[1] = h->nodes[h->len];
74 | h->len--;
75 | i = 1;
76 | while (1) {
77 | k = i;
78 | j = 2 * i;
79 | if (j <= h->len && h->nodes[j].key < h->nodes[k].key) {
80 | k = j;
81 | }
82 | if (j + 1 <= h->len && h->nodes[j + 1].key < h->nodes[k].key) {
83 | k = j + 1;
84 | }
85 | if (k == i) {
86 | break;
87 | }
88 | h->nodes[i] = h->nodes[k];
89 | i = k;
90 | }
91 | h->nodes[i] = h->nodes[h->len + 1];
92 | return true;
93 | }
94 |
95 |
96 |
--------------------------------------------------------------------------------
/lib/capq/binheap_test.c:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2017 Kjell Winblad (http://winsh.me, kjellwinblad@gmail.com)
3 | *
4 | * This file is part of kpqueue.
5 | *
6 | * kpqueue is free software: you can redistribute it and/or modify
7 | * it under the terms of the GNU General Public License as published by
8 | * the Free Software Foundation, either version 3 of the License, or
9 | * (at your option) any later version.
10 | *
11 | * kpqueue is distributed in the hope that it will be useful,
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | * GNU General Public License for more details.
15 | *
16 | * You should have received a copy of the GNU General Public License
17 | * along with kpqueue. If not, see .
18 | */
19 |
20 | #include
21 | #include "binheap.h"
22 |
23 | int main()
24 | {
25 | heap_t *h = malloc(sizeof(heap_t));
26 | h-> len = 0;
27 | h->size = MAX_HEAP_SIZE;
28 | push(h, 3, 3);
29 | push(h, 4, 4);
30 | push(h, 5, 5);
31 | push(h, 1, 1);
32 | push(h, 2, 2);
33 | int i;
34 | for (i = 0; i < 5; i++) {
35 | unsigned long key, value;
36 | pop(h, &key, &value);
37 | printf("%lu %lu\n", key, value);
38 | }
39 | return 0;
40 | }
41 |
--------------------------------------------------------------------------------
/lib/capq/capq.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2017 Kjell Winblad (http://winsh.me, kjellwinblad@gmail.com)
3 | *
4 | * This file is part of kpqueue.
5 | *
6 | * kpqueue is free software: you can redistribute it and/or modify
7 | * it under the terms of the GNU General Public License as published by
8 | * the Free Software Foundation, either version 3 of the License, or
9 | * (at your option) any later version.
10 | *
11 | * kpqueue is distributed in the hope that it will be useful,
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | * GNU General Public License for more details.
15 | *
16 | * You should have received a copy of the GNU General Public License
17 | * along with kpqueue. If not, see .
18 | */
19 |
20 | /*
21 | This file is the header file for an implementation of the contention
22 | avoiding priority queue (CA-PQ). CA-PQ is described in the paper
23 | "The Contention Avoiding Concurrent Priority Queue" which is
24 | published in the 29th International Workshop on Languages and
25 | Compilers for Parallel Computing (LCPC 2016).
26 | */
27 |
28 | #ifndef CAPQ_H
29 | #define CAPQ_H
30 | #include
31 |
32 | #ifndef SLCATREE_MALLOC
33 | # define SLCATREE_MALLOC(size) malloc(size)
34 | #endif
35 |
36 | #ifndef SLCATREE_FREE
37 | # define SLCATREE_FREE(data) free(data)
38 | #endif
39 |
40 | typedef struct fpasl_catree_set CAPQ;
41 |
42 | void capq_put(CAPQ *set,
43 | unsigned long key,
44 | unsigned long value);
45 | void capq_put_param(CAPQ *set,
46 | unsigned long key,
47 | unsigned long value,
48 | bool catree_adapt);
49 | unsigned long capq_remove_min(CAPQ *set, unsigned long *key_write_back);
50 | unsigned long capq_remove_min_param(CAPQ *set,
51 | unsigned long *key_write_back,
52 | bool remove_min_relax,
53 | bool put_relax,
54 | bool catree_adapt);
55 | void capq_delete(CAPQ *setParam);
56 | CAPQ *capq_new();
57 |
58 | #endif
59 |
--------------------------------------------------------------------------------
/lib/capq/fat_skiplist.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2017 Kjell Winblad (http://winsh.me, kjellwinblad@gmail.com)
3 | *
4 | * This file is part of kpqueue.
5 | *
6 | * kpqueue is free software: you can redistribute it and/or modify
7 | * it under the terms of the GNU General Public License as published by
8 | * the Free Software Foundation, either version 3 of the License, or
9 | * (at your option) any later version.
10 | *
11 | * kpqueue is distributed in the hope that it will be useful,
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | * GNU General Public License for more details.
15 | *
16 | * You should have received a copy of the GNU General Public License
17 | * along with kpqueue. If not, see .
18 | */
19 |
20 | #ifndef __FAT_SKIPLIST_H__
21 | #define __FAT_SKIPLIST_H__
22 |
23 | #include
24 |
25 | #ifndef SKIPLIST_MALLOC
26 | #define SKIPLIST_MALLOC(size) malloc(size)
27 | #endif
28 |
29 | #ifndef SKIPLIST_FREE
30 | #define SKIPLIST_FREE free
31 | #endif
32 |
33 |
34 | //Max 255
35 | #define SKIPLIST_MAX_VALUSES_IN_NODE 90
36 |
37 | #define SKIPLIST_NUM_OF_LEVELS 21
38 |
39 | typedef struct key_value_item {
40 | unsigned long key;
41 | unsigned long value;
42 | } KeyValueItem;
43 |
44 | typedef struct skiplist_node {
45 | //contains information about if it is a boarder point
46 | unsigned char info;
47 | bool sorted;
48 | unsigned char num_of_levels;
49 | unsigned char first_key_value_pos;
50 | unsigned long max_key;
51 | KeyValueItem *key_values; //Points to region after lower_lists
52 | struct skiplist_node *lower_lists[];
53 | } SkiplistNode;
54 |
55 | typedef struct skiplist Skiplist;
56 | void skiplist_put(Skiplist *skiplist, unsigned long key, unsigned long value);
57 | unsigned long skiplist_remove_min(Skiplist *skiplist, unsigned long *key_write_back);
58 | Skiplist *new_skiplist();
59 | void skiplist_delete(Skiplist *skiplist);
60 | bool skiplist_is_empty(Skiplist *skiplist);
61 | bool skiplist_more_than_two_keys(Skiplist *skiplist);
62 | unsigned long skiplist_max_key(Skiplist *skiplist);
63 | /* This function assumes that the input skiplist has at least two different keys */
64 | unsigned long skiplist_split(Skiplist *skiplist,
65 | Skiplist **left_writeback,
66 | Skiplist **right_writeback);
67 | Skiplist *skiplist_join(Skiplist *left_skiplist,
68 | Skiplist *right_skiplist);
69 | SkiplistNode *skiplist_remove_head_nodes(Skiplist *skiplist, int number_of_nodes);
70 |
71 | #endif
72 |
--------------------------------------------------------------------------------
/lib/capq/gc/gc.h:
--------------------------------------------------------------------------------
1 | #ifndef __GC_H__
2 | #define __GC_H__
3 |
4 | typedef struct gc_st gc_t;
5 |
6 | /* Most of these functions peek into a per-thread state struct. */
7 | #include "ptst.h"
8 |
9 | /* Initialise GC section of given per-thread state structure. */
10 | gc_t *gc_init(void);
11 |
12 | int gc_add_allocator(int alloc_size);
13 | void gc_remove_allocator(int alloc_id);
14 |
15 | /*
16 | * Memory allocate/free. An unsafe free can be used when an object was
17 | * not made visible to other processes.
18 | */
19 | void *gc_alloc(ptst_t *ptst, int alloc_id);
20 | void gc_free(ptst_t *ptst, void *p, int alloc_id);
21 | void gc_unsafe_free(ptst_t *ptst, void *p, int alloc_id);
22 |
23 | /*
24 | * Hook registry. Allows users to hook in their own per-epoch delay
25 | * lists.
26 | */
27 | typedef void (*hook_fn_t)(ptst_t *, void *);
28 | int gc_add_hook(hook_fn_t fn);
29 | void gc_remove_hook(int hook_id);
30 | void gc_add_ptr_to_hook_list(ptst_t *ptst, void *ptr, int hook_id);
31 |
32 | /* Per-thread entry/exit from critical regions */
33 | void gc_enter(ptst_t *ptst);
34 | void gc_exit(ptst_t *ptst);
35 |
36 | /* Start-of-day initialisation of garbage collector. */
37 | void _init_gc_subsystem(void);
38 | void _destroy_gc_subsystem(void);
39 |
40 | #endif /* __GC_H__ */
41 |
--------------------------------------------------------------------------------
/lib/capq/gc/portable_defns.h:
--------------------------------------------------------------------------------
1 | #ifndef __PORTABLE_DEFNS_H__
2 | #define __PORTABLE_DEFNS_H__
3 |
4 | #define MAX_THREADS 128 /* Nobody will ever have more! */
5 |
6 | #if defined(SPARC)
7 | #include "sparc_defns.h"
8 | #elif defined(INTEL)
9 | #include "intel_defns.h"
10 | #elif defined(PPC)
11 | #include "ppc_defns.h"
12 | #elif defined(IA64)
13 | #include "ia64_defns.h"
14 | #elif defined(MIPS)
15 | #include "mips_defns.h"
16 | #elif defined(ALPHA)
17 | #include "alpha_defns.h"
18 | #else
19 | #error "A valid architecture has not been defined"
20 | #endif
21 |
22 | #include
23 |
24 | #ifndef MB_NEAR_CAS
25 | #define RMB_NEAR_CAS() RMB()
26 | #define WMB_NEAR_CAS() WMB()
27 | #define MB_NEAR_CAS() MB()
28 | #endif
29 |
30 | typedef unsigned long int_addr_t;
31 |
32 | typedef int bool_t;
33 | #define FALSE 0
34 | #define TRUE 1
35 |
36 | #define ADD_TO(_v,_x) \
37 | do { \
38 | int __val = (_v), __newval; \
39 | while ( (__newval = CASIO(&(_v),__val,__val+(_x))) != __val ) \
40 | __val = __newval; \
41 | } while ( 0 )
42 |
43 | /*
44 | * Allow us to efficiently align and pad structures so that shared fields
45 | * don't cause contention on thread-local or read-only fields.
46 | */
47 | #define CACHE_PAD(_n) char __pad ## _n [CACHE_LINE_SIZE]
48 | #define ALIGNED_ALLOC(_s) \
49 | ((void *)(((unsigned long)malloc((_s)+CACHE_LINE_SIZE*2) + \
50 | CACHE_LINE_SIZE - 1) & ~(CACHE_LINE_SIZE-1)))
51 |
52 |
53 | /*
54 | * POINTER MARKING
55 | */
56 | #define get_marked_ref(_p) ((void *)(((unsigned long)(_p)) | 1))
57 | #define get_unmarked_ref(_p) ((void *)(((unsigned long)(_p)) & ~1))
58 | #define is_marked_ref(_p) (((unsigned long)(_p)) & 1)
59 |
60 |
61 |
62 | /* Read field @_f into variable @_x. */
63 | #define READ_FIELD(_x,_f) ((_x) = (_f))
64 |
65 | #define WEAK_DEP_ORDER_RMB() ((void)0)
66 | #define WEAK_DEP_ORDER_WMB() ((void)0)
67 | #define WEAK_DEP_ORDER_MB() ((void)0)
68 |
69 |
70 |
71 | #endif /* __PORTABLE_DEFNS_H__ */
72 |
--------------------------------------------------------------------------------
/lib/capq/gc/ptst.c:
--------------------------------------------------------------------------------
1 | /******************************************************************************
2 | * ptst.c
3 | *
4 | * Per-thread state management. Essentially the state management parts
5 | * of MB's garbage-collection code have been pulled out and placed
6 | * here, for the use of other utility routines.
7 | *
8 | * Copyright (c) 2013, Jonatan Linden
9 | * Copyright (c) 2002-2003, K A Fraser
10 | *
11 | * All rights reserved.
12 | *
13 | * Redistribution and use in source and binary forms, with or without
14 | * modification, are permitted provided that the following conditions
15 | * are met:
16 | *
17 | * * Redistributions of source code must retain the above copyright
18 | * notice, this list of conditions and the following disclaimer.
19 | *
20 | * * Redistributions in binary form must reproduce the above
21 | * copyright notice, this list of conditions and the following
22 | * disclaimer in the documentation and/or other materials provided
23 | * with the distribution.
24 | *
25 | * * The name of the author may not be used to endorse or promote
26 | * products derived from this software without specific prior
27 | * written permission.
28 | *
29 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
30 | * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
31 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
32 | * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
33 | * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
34 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
35 | * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
36 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
37 | * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
38 | * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
39 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
40 | */
41 |
42 | #include
43 | #include
44 | #include
45 | #include "random.h"
46 | #include "portable_defns.h"
47 | #include "ptst.h"
48 |
49 | ptst_t *ptst_list = NULL;
50 | extern __thread ptst_t *ptst;
51 | static unsigned int next_id = 0;
52 |
53 | void
54 | critical_enter()
55 | {
56 | ptst_t *next, *new_next;
57 |
58 | if ( ptst == NULL )
59 | {
60 | ptst = (ptst_t *) ALIGNED_ALLOC(sizeof(ptst_t));
61 | if ( ptst == NULL ) exit(1);
62 |
63 | memset(ptst, 0, sizeof(ptst_t));
64 | ptst->gc = gc_init();
65 | ptst->count = 1;
66 | ptst->id = __sync_fetch_and_add(&next_id, 1);
67 | rand_init(ptst);
68 | new_next = ptst_list;
69 | do {
70 | ptst->next = next = new_next;
71 | }
72 | while ( (new_next = __sync_val_compare_and_swap(&ptst_list, next, ptst)) != next );
73 | }
74 |
75 | gc_enter(ptst);
76 | return;
77 | }
78 |
79 |
80 |
81 | static void ptst_destructor(ptst_t *ptst)
82 | {
83 | ptst->count = 0;
84 | }
85 |
86 |
87 |
--------------------------------------------------------------------------------
/lib/capq/gc/ptst.h:
--------------------------------------------------------------------------------
1 | /******************************************************************************
2 | * ptst.h
3 | *
4 | * Per-thread state management.
5 | *
6 | *
7 | * Copyright (c) 2013, Jonatan Linden
8 | * Copyright (c) 2002-2003, K A Fraser
9 | */
10 |
11 | #ifndef __PTST_H__
12 | #define __PTST_H__
13 |
14 | typedef struct ptst_st ptst_t;
15 |
16 | #include
17 |
18 | #include "gc.h"
19 |
20 | struct ptst_st
21 | {
22 | /* Thread id */
23 | unsigned int id;
24 | /* State management */
25 | ptst_t *next;
26 | unsigned int count;
27 |
28 | /* Utility structures */
29 | gc_t *gc;
30 | char pad[56];
31 | unsigned int rand;
32 | };
33 |
34 | /*
35 | * Enter/leave a critical region. A thread gets a state handle for
36 | * use during critical regions.
37 | */
38 |
39 | void critical_enter(void );
40 |
41 | #define critical_exit() gc_exit(ptst)
42 |
43 | /* Iterators */
44 | extern ptst_t *ptst_list;
45 |
46 | #define ptst_first() (ptst_list)
47 | #define ptst_next(_p) ((_p)->next)
48 |
49 |
50 |
51 | #endif /* __PTST_H__ */
52 |
53 |
54 |
55 |
--------------------------------------------------------------------------------
/lib/capq/gc/random.h:
--------------------------------------------------------------------------------
1 | /******************************************************************************
2 | * random.h
3 | *
4 | * A really simple random-number generator. Crappy linear congruential
5 | * taken from glibc, but has at least a 2^32 period.
6 | */
7 |
8 | #ifndef __RANDOM_H__
9 | #define __RANDOM_H__
10 |
11 | typedef unsigned long rand_t;
12 |
13 | #define rand_init(_ptst) \
14 | ((_ptst)->rand = RDTICK())
15 |
16 | #define rand_next(_ptst) \
17 | ((_ptst)->rand = ((_ptst)->rand * 1103515245) + 12345)
18 |
19 | #endif /* __RANDOM_H__ */
20 |
--------------------------------------------------------------------------------
/lib/capq/qdlocksrc/README:
--------------------------------------------------------------------------------
1 | This directory contains parts of qd_lock_lib
2 |
3 | For more information about qd_lock_lib see:
4 |
5 | * http://www.it.uu.se/research/group/languages/software/qd_lock_lib
6 |
7 | for background information and
8 |
9 | * https://github.com/kjellwinblad/qd_lock_lib
10 |
11 | for source code.
12 |
13 |
14 | License
15 | -------
16 |
17 | This version of qd_lock_lib is licensed under GNU General Public
18 | License version 3. See LICENSE file for more information.
--------------------------------------------------------------------------------
/lib/capq/qdlocksrc/locks/ccsynch_lock.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2017 Kjell Winblad (http://winsh.me, kjellwinblad@gmail.com)
3 | *
4 | * This file is part of qd_lock_lib.
5 | *
6 | * qd_lock_lib is free software: you can redistribute it and/or modify
7 | * it under the terms of the GNU General Public License as published by
8 | * the Free Software Foundation, either version 3 of the License, or
9 | * (at your option) any later version.
10 | *
11 | * qd_lock_lib is distributed in the hope that it will be useful,
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | * GNU General Public License for more details.
15 | *
16 | * You should have received a copy of the GNU General Public License
17 | * along with qd_lock_lib. If not, see .
18 | */
19 |
20 | #ifndef CCSYNCH_LOCK_H
21 | #define CCSYNCH_LOCK_H
22 |
23 | // Implementation of the CC-Synch algorithm as described in the paper:
24 | // Revisiting the combining synchronization technique
25 | // by Panagiota Fatourou and Nikolaos D. Kallimanis
26 | // PPoPP '12 Proceedings of the 17th ACM SIGPLAN symposium on
27 | // Principles and Practice of Parallel Programming
28 |
29 | #include "misc/bsd_stdatomic.h"//Until c11 stdatomic.h is available
30 | #include "misc/thread_includes.h"//Until c11 thread.h is available
31 | #include
32 |
33 | #include "misc/padded_types.h"
34 | #include "locks/oo_lock_interface.h"
35 |
36 | #define CCSYNCH_BUFFER_SIZE 512
37 | #define CCSYNCH_HAND_OFF_LIMIT 512
38 |
39 | typedef struct {
40 | volatile atomic_uintptr_t next;
41 | void (*requestFunction)(unsigned int, void *);
42 | unsigned int messageSize;
43 | unsigned char * buffer;
44 | bool completed;
45 | volatile atomic_int wait;
46 | char pad2[CACHE_LINE_SIZE_PAD(sizeof(void *)*2 +
47 | sizeof(unsigned int) +
48 | CCSYNCH_BUFFER_SIZE +
49 | sizeof(bool) +
50 | sizeof(atomic_int))];
51 | unsigned char tempBuffer[CACHE_LINE_SIZE*8]; //used in ccsynch_delegate_or_lock
52 | } CCSynchLockNode;
53 |
54 | typedef struct {
55 | LLPaddedPointer tailPtr;
56 | } CCSynchLock;
57 |
58 |
59 | // Public interface
60 |
61 | void ccsynch_initialize(CCSynchLock * l);
62 | void ccsynch_lock(void * lock);
63 | void ccsynch_unlock(void * lock);
64 | bool ccsynch_is_locked(void * lock);
65 | bool ccsynch_try_lock(void * lock);
66 | void ccsynch_delegate(void* lock,
67 | void (*funPtr)(unsigned int, void *),
68 | unsigned int messageSize,
69 | void * messageAddress);
70 | void * ccsynch_delegate_or_lock(void* lock,
71 | unsigned int messageSize);
72 | void ccsynch_close_delegate_buffer(void * buffer,
73 | void (*funPtr)(unsigned int, void *));
74 | void ccsynch_delegate_unlock(void* lock);
75 | CCSynchLock * plain_ccsynch_create();
76 | OOLock * oo_ccsynch_create();
77 |
78 | #endif
79 |
--------------------------------------------------------------------------------
/lib/capq/qdlocksrc/locks/drmcs_lock.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2017 Kjell Winblad (http://winsh.me, kjellwinblad@gmail.com)
3 | *
4 | * This file is part of qd_lock_lib.
5 | *
6 | * qd_lock_lib is free software: you can redistribute it and/or modify
7 | * it under the terms of the GNU General Public License as published by
8 | * the Free Software Foundation, either version 3 of the License, or
9 | * (at your option) any later version.
10 | *
11 | * qd_lock_lib is distributed in the hope that it will be useful,
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | * GNU General Public License for more details.
15 | *
16 | * You should have received a copy of the GNU General Public License
17 | * along with qd_lock_lib. If not, see .
18 | */
19 |
20 | #ifndef DRMCS_LOCK_H
21 | #define DRMCS_LOCK_H
22 |
23 | #include "locks/oo_lock_interface.h"
24 | #include "locks/mcs_lock.h"
25 | #include "misc/padded_types.h"
26 | #include "read_indicators/reader_groups_read_indicator.h"
27 |
28 | #include "misc/bsd_stdatomic.h"//Until c11 stdatomic.h is available
29 | #include "misc/thread_includes.h"//Until c11 thread.h is available
30 | #include
31 |
32 | #define DRMCS_READ_PATIENCE_LIMIT 130000
33 |
34 | typedef struct {
35 | MCSLock lock;
36 | LLPaddedInt writeBarrier;
37 | ReaderGroupsReadIndicator readIndicator;
38 | char pad[CACHE_LINE_SIZE];
39 | } DRMCSLock;
40 |
41 | extern
42 | _Alignas(CACHE_LINE_SIZE)
43 | OOLockMethodTable DRMCS_LOCK_METHOD_TABLE;
44 |
45 |
46 | void drmcs_initialize(DRMCSLock * lock);
47 | void drmcs_lock(void * lock);
48 | void drmcs_unlock(void * lock);
49 | bool drmcs_is_locked(void * lock);
50 | bool drmcs_try_lock(void * lock);
51 | void drmcs_rlock(void * lock);
52 | void drmcs_runlock(void * lock);
53 | void drmcs_delegate(void * lock,
54 | void (*funPtr)(unsigned int, void *),
55 | unsigned int messageSize,
56 | void * messageAddress);
57 | void * drmcs_delegate_or_lock(void * lock, unsigned int messageSize);
58 | DRMCSLock * plain_drmcs_create();
59 | OOLock * oo_drmcs_create();
60 |
61 |
62 | #endif
63 |
--------------------------------------------------------------------------------
/lib/capq/qdlocksrc/locks/hqd_lock.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2017 Kjell Winblad (http://winsh.me, kjellwinblad@gmail.com)
3 | *
4 | * This file is part of qd_lock_lib.
5 | *
6 | * qd_lock_lib is free software: you can redistribute it and/or modify
7 | * it under the terms of the GNU General Public License as published by
8 | * the Free Software Foundation, either version 3 of the License, or
9 | * (at your option) any later version.
10 | *
11 | * qd_lock_lib is distributed in the hope that it will be useful,
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | * GNU General Public License for more details.
15 | *
16 | * You should have received a copy of the GNU General Public License
17 | * along with qd_lock_lib. If not, see .
18 | */
19 |
20 | #ifndef HQD_LOCK_H
21 | #define HQD_LOCK_H
22 |
23 |
24 | #include
25 | #ifdef USE_HQD_LOCK
26 | # include
27 | #endif
28 | #include "misc/bsd_stdatomic.h"//Until c11 stdatomic.h is available
29 | #include "misc/thread_includes.h"//Until c11 thread.h is available
30 | #include "misc/padded_types.h"
31 | #include "locks/tatas_lock.h"
32 | #include "locks/ticket_lock.h"
33 | #include "locks/qd_lock.h"
34 | #include "qd_queues/qd_queue.h"
35 |
36 | #ifdef BULLDOZER
37 | #define HQD_NUMBER_OF_NUMA_NODES 8
38 | #else
39 | #define HQD_NUMBER_OF_NUMA_NODES 4
40 | #endif
41 | /* Hierarchical Queue Delegation Lock */
42 |
43 | typedef struct {
44 | TicketLock globalLock;
45 | QDLock qdlocks[HQD_NUMBER_OF_NUMA_NODES];
46 | } HQDLock;
47 |
48 | typedef union {
49 | volatile unsigned value;
50 | char padding[CACHE_LINE_SIZE];
51 | } HQDPaddedUnsigned;
52 |
53 | void hqd_initialize(HQDLock * lock);
54 | void hqd_lock(void * lock);
55 | void hqd_unlock(void * lock);
56 | static inline
57 | bool hqd_is_locked(void * lock){
58 | HQDLock *l = (HQDLock*)lock;
59 | return ticket_is_locked(&l->globalLock);
60 | }
61 | bool hqd_try_lock(void * lock);
62 | void hqd_delegate(void* lock,
63 | void (*funPtr)(unsigned int, void *),
64 | unsigned int messageSize,
65 | void * messageAddress);
66 | void * hqd_delegate_or_lock(void* lock,
67 | unsigned int messageSize);
68 | void * hqd_delegate_or_lock_extra(void* lock,
69 | unsigned int messageSize,
70 | bool openQueue);
71 | void hqd_open_delegation_queue(void* lock);
72 |
73 | void hqd_flush_delegation_queue(void* lock);
74 | void hqd_close_delegate_buffer(void * buffer,
75 | void (*funPtr)(unsigned int, void *));
76 | void hqd_delegate_unlock(void* lock);
77 | void hqd_delegate_wait(void* lock,
78 | void (*funPtr)(unsigned int, void *),
79 | unsigned int messageSize,
80 | void * messageAddress);
81 | HQDLock * plain_hqd_create();
82 | OOLock * oo_hqd_create();
83 |
84 | #endif
85 |
--------------------------------------------------------------------------------
/lib/capq/qdlocksrc/locks/mcs_lock.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2017 Kjell Winblad (http://winsh.me, kjellwinblad@gmail.com)
3 | *
4 | * This file is part of qd_lock_lib.
5 | *
6 | * qd_lock_lib is free software: you can redistribute it and/or modify
7 | * it under the terms of the GNU General Public License as published by
8 | * the Free Software Foundation, either version 3 of the License, or
9 | * (at your option) any later version.
10 | *
11 | * qd_lock_lib is distributed in the hope that it will be useful,
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | * GNU General Public License for more details.
15 | *
16 | * You should have received a copy of the GNU General Public License
17 | * along with qd_lock_lib. If not, see .
18 | */
19 |
20 | #ifndef MCS_LOCK_H
21 | #define MCS_LOCK_H
22 |
23 | #include "locks/oo_lock_interface.h"
24 | #include "misc/padded_types.h"
25 |
26 | #include "misc/bsd_stdatomic.h"//Until c11 stdatomic.h is available
27 | #include "misc/thread_includes.h"//Until c11 thread.h is available
28 | #include
29 |
30 | // WARNING: DOES NOT WORK FOR NESTED LOCKS
31 |
32 | typedef struct {
33 | LLPaddedPointer next;
34 | LLPaddedInt locked;
35 | } MCSNode;
36 |
37 | typedef struct {
38 | LLPaddedPointer endOfQueue;
39 | } MCSLock;
40 |
41 | typedef struct {
42 | char pad1[CACHE_LINE_SIZE];
43 | int index;
44 | char pad2[CACHE_LINE_SIZE*2 - sizeof(int)];
45 | } PaddedCurrentNodeIndex;
46 |
47 |
48 | extern
49 | __thread PaddedCurrentNodeIndex myMCSCurrentNodeIndex;
50 |
51 | void mcs_initialize(MCSLock * lock);
52 | bool mcs_lock_status(void * lock); //Not part of public API but is used by DRMCS
53 | void mcs_lock(void * lock);
54 | void mcs_unlock(void * lock);
55 | static inline
56 | bool mcs_is_locked(void * lock){
57 | MCSLock * l = lock;
58 | return atomic_load(&l->endOfQueue.value) != (intptr_t)NULL;
59 | }
60 | bool mcs_try_lock(void * lock);
61 | void mcs_delegate(void * lock,
62 | void (*funPtr)(unsigned int, void *),
63 | unsigned int messageSize,
64 | void * messageAddress);
65 | void * mcs_delegate_or_lock(void * lock, unsigned int messageSize);
66 | MCSLock * plain_mcs_create();
67 | OOLock * oo_mcs_create();
68 |
69 | #endif
70 |
--------------------------------------------------------------------------------
/lib/capq/qdlocksrc/locks/mrqd_lock.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2017 Kjell Winblad (http://winsh.me, kjellwinblad@gmail.com)
3 | *
4 | * This file is part of qd_lock_lib.
5 | *
6 | * qd_lock_lib is free software: you can redistribute it and/or modify
7 | * it under the terms of the GNU General Public License as published by
8 | * the Free Software Foundation, either version 3 of the License, or
9 | * (at your option) any later version.
10 | *
11 | * qd_lock_lib is distributed in the hope that it will be useful,
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | * GNU General Public License for more details.
15 | *
16 | * You should have received a copy of the GNU General Public License
17 | * along with qd_lock_lib. If not, see .
18 | */
19 |
20 | #ifndef MRQD_LOCK_H
21 | #define MRQD_LOCK_H
22 |
23 | #include "misc/bsd_stdatomic.h"//Until c11 stdatomic.h is available
24 | #include "misc/thread_includes.h"//Until c11 thread.h is available
25 | #include
26 |
27 | #include "misc/padded_types.h"
28 | #include "locks/tatas_lock.h"
29 | #include "qd_queues/qd_queue.h"
30 | #include "read_indicators/reader_groups_read_indicator.h"
31 | #include "locks/oo_lock_interface.h"
32 |
33 | /* Multiple Reader Queue Delegation Lock */
34 |
35 | #ifndef MRQD_READ_PATIENCE_LIMIT
36 | # define MRQD_READ_PATIENCE_LIMIT 1000
37 | #endif
38 |
39 | typedef struct {
40 | TATASLock mutexLock;
41 | QDQueue queue;
42 | ReaderGroupsReadIndicator readIndicator;
43 | LLPaddedUInt writeBarrier;
44 | } MRQDLock;
45 |
46 | void mrqd_initialize(MRQDLock * lock);
47 | void mrqd_lock(void * lock);
48 | void mrqd_unlock(void * lock);
49 | bool mrqd_is_locked(void * lock);
50 | bool mrqd_try_lock(void * lock);
51 | void mrqd_rlock(void * lock);
52 | void mrqd_runlock(void * lock);
53 | void mrqd_delegate(void* lock,
54 | void (*funPtr)(unsigned int, void *),
55 | unsigned int messageSize,
56 | void * messageAddress);
57 | void * mrqd_delegate_or_lock(void* lock,
58 | unsigned int messageSize);
59 | void mrqd_close_delegate_buffer(void * buffer,
60 | void (*funPtr)(unsigned int, void *));
61 | void mrqd_delegate_unlock(void* lock);
62 | void mrqd_executeAndWaitCS(unsigned int size, void * data);
63 | void mrqd_delegate_wait(void* lock,
64 | void (*funPtr)(unsigned int, void *),
65 | unsigned int messageSize,
66 | void * messageAddress);
67 | MRQDLock * plain_mrqd_create();
68 | OOLock * oo_mrqd_create();
69 |
70 | #endif
71 |
--------------------------------------------------------------------------------
/lib/capq/qdlocksrc/locks/oo_lock_interface.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2017 Kjell Winblad (http://winsh.me, kjellwinblad@gmail.com)
3 | *
4 | * This file is part of qd_lock_lib.
5 | *
6 | * qd_lock_lib is free software: you can redistribute it and/or modify
7 | * it under the terms of the GNU General Public License as published by
8 | * the Free Software Foundation, either version 3 of the License, or
9 | * (at your option) any later version.
10 | *
11 | * qd_lock_lib is distributed in the hope that it will be useful,
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | * GNU General Public License for more details.
15 | *
16 | * You should have received a copy of the GNU General Public License
17 | * along with qd_lock_lib. If not, see .
18 | */
19 |
20 | #ifndef OO_LOCK_INTERFACE_H
21 | #define OO_LOCK_INTERFACE_H
22 |
23 | #include
24 | #include
25 | #include "misc/padded_types.h"
26 |
27 | typedef struct {
28 | void (*free)(void*);
29 | void (*lock)(void*);
30 | void (*unlock)(void*);
31 | bool (*is_locked)(void*);
32 | bool (*try_lock)(void*);
33 | void (*rlock)(void*);
34 | void (*runlock)(void*);
35 | void (*delegate)(void*,
36 | void (*funPtr)(unsigned int, void *),
37 | unsigned int messageSize,
38 | void * messageAddress);
39 | void (*delegate_wait)(void*,
40 | void (*funPtr)(unsigned int, void *),
41 | unsigned int messageSize,
42 | void * messageAddress);
43 | void * (*delegate_or_lock)(void* lock,
44 | unsigned int messageSize);
45 | void (*close_delegate_buffer)(void * buffer,
46 | void (*funPtr)(unsigned int, void *));
47 | void (*delegate_unlock)(void* lock);
48 | char pad[CACHE_LINE_SIZE - (8 * sizeof(void*)) % CACHE_LINE_SIZE];
49 | } OOLockMethodTable;
50 |
51 | typedef struct {
52 | OOLockMethodTable * m;
53 | void * lock;
54 | char pad[CACHE_LINE_SIZE - (2 * sizeof(void*)) % CACHE_LINE_SIZE];
55 | } OOLock;
56 |
57 | static inline void oolock_free(OOLock * lock){
58 | lock->m->free(lock->lock);
59 | free(lock);
60 | }
61 |
62 | #endif
63 |
--------------------------------------------------------------------------------
/lib/capq/qdlocksrc/locks/qd_lock.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2017 Kjell Winblad (http://winsh.me, kjellwinblad@gmail.com)
3 | *
4 | * This file is part of qd_lock_lib.
5 | *
6 | * qd_lock_lib is free software: you can redistribute it and/or modify
7 | * it under the terms of the GNU General Public License as published by
8 | * the Free Software Foundation, either version 3 of the License, or
9 | * (at your option) any later version.
10 | *
11 | * qd_lock_lib is distributed in the hope that it will be useful,
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | * GNU General Public License for more details.
15 | *
16 | * You should have received a copy of the GNU General Public License
17 | * along with qd_lock_lib. If not, see .
18 | */
19 |
20 | #ifndef QD_LOCK_H
21 | #define QD_LOCK_H
22 |
23 | #include "misc/bsd_stdatomic.h"//Until c11 stdatomic.h is available
24 | #include "misc/thread_includes.h"//Until c11 thread.h is available
25 | #include
26 |
27 | #include "misc/padded_types.h"
28 | #include "locks/tatas_lock.h"
29 | #include "qd_queues/qd_queue.h"
30 |
31 | /* Queue Delegation Lock */
32 |
33 | typedef struct {
34 | TATASLock mutexLock;
35 | QDQueue queue;
36 | } QDLock;
37 |
38 | void qd_initialize(QDLock * lock);
39 | void qd_lock(void * lock);
40 | void qd_unlock(void * lock);
41 | static inline
42 | bool qd_is_locked(void * lock){
43 | QDLock *l = (QDLock*)lock;
44 | return tatas_is_locked(&l->mutexLock);
45 | }
46 | bool qd_try_lock(void * lock);
47 | void qd_delegate(void* lock,
48 | void (*funPtr)(unsigned int, void *),
49 | unsigned int messageSize,
50 | void * messageAddress);
51 | void * qd_delegate_or_lock(void* lock,
52 | unsigned int messageSize);
53 | void * qd_delegate_or_lock_extra(void* lock,
54 | unsigned int messageSize,
55 | bool openQueue,
56 | bool * contendedWriteBack);
57 | void qd_open_delegation_queue(void* lock);
58 |
59 | void qd_flush_delegation_queue(void* lock);
60 | void qd_close_delegate_buffer(void * buffer,
61 | void (*funPtr)(unsigned int, void *));
62 | void qd_delegate_unlock(void* lock);
63 | void qd_delegate_wait(void* lock,
64 | void (*funPtr)(unsigned int, void *),
65 | unsigned int messageSize,
66 | void * messageAddress);
67 | QDLock * plain_qd_create();
68 | OOLock * oo_qd_create();
69 |
70 | #endif
71 |
--------------------------------------------------------------------------------
/lib/capq/qdlocksrc/locks/seq_lock.c:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2017 Kjell Winblad (http://winsh.me, kjellwinblad@gmail.com)
3 | *
4 | * This file is part of qd_lock_lib.
5 | *
6 | * qd_lock_lib is free software: you can redistribute it and/or modify
7 | * it under the terms of the GNU General Public License as published by
8 | * the Free Software Foundation, either version 3 of the License, or
9 | * (at your option) any later version.
10 | *
11 | * qd_lock_lib is distributed in the hope that it will be useful,
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | * GNU General Public License for more details.
15 | *
16 | * You should have received a copy of the GNU General Public License
17 | * along with qd_lock_lib. If not, see .
18 | */
19 |
20 | #include "seq_lock.h"
21 |
22 | _Alignas(CACHE_LINE_SIZE)
23 | OOLockMethodTable SEQ_LOCK_METHOD_TABLE =
24 | {
25 | .free = &free,
26 | .lock = &seq_lock,
27 | .unlock = &seq_unlock,
28 | .is_locked = &seq_is_locked,
29 | .try_lock = &seq_try_lock,
30 | .rlock = &seq_lock,
31 | .runlock = &seq_unlock,
32 | .delegate = &seq_delegate,
33 | .delegate_wait = &seq_delegate,
34 | .delegate_or_lock = &seq_delegate_or_lock,
35 | .close_delegate_buffer = NULL, /* Should never be called */
36 | .delegate_unlock = &seq_unlock
37 | };
38 |
39 |
40 |
41 | void seq_initialize(SEQLock * lock){
42 | atomic_init( &lock->counter.value, 2 );
43 | }
44 |
45 |
46 | void seq_lock(void * lock) {
47 | SEQLock *l = (SEQLock*)lock;
48 | unsigned long counter;
49 | unsigned long counterCopy;
50 | do{
51 | counter = atomic_load_explicit(&l->counter.value,
52 | memory_order_acquire);
53 | while((counter % 2) == 1){
54 | thread_yield();
55 | counter = atomic_load_explicit(&l->counter.value,
56 | memory_order_acquire);
57 | }
58 | counterCopy = counter;
59 | }while(!atomic_compare_exchange_strong( &l->counter.value,
60 | &counterCopy, counter + 1 ));
61 | }
62 |
63 |
64 | void seq_delegate(void * lock,
65 | void (*funPtr)(unsigned int, void *),
66 | unsigned int messageSize,
67 | void * messageAddress){
68 | SEQLock *l = (SEQLock*)lock;
69 | seq_lock(l);
70 | funPtr(messageSize, messageAddress);
71 | seq_unlock(l);
72 | }
73 |
74 |
75 | void * seq_delegate_or_lock(void * lock, unsigned int messageSize){
76 | (void)messageSize;
77 | SEQLock *l = (SEQLock*)lock;
78 | seq_lock(l);
79 | return NULL;
80 | }
81 |
82 |
83 |
84 | SEQLock * plain_seq_create(){
85 | SEQLock * l = aligned_alloc(CACHE_LINE_SIZE, sizeof(SEQLock));
86 | seq_initialize(l);
87 | return l;
88 | }
89 |
90 |
91 | OOLock * oo_seq_create(){
92 | SEQLock * l = plain_seq_create();
93 | OOLock * ool = aligned_alloc(CACHE_LINE_SIZE, sizeof(OOLock));
94 | ool->lock = l;
95 | ool->m = &SEQ_LOCK_METHOD_TABLE;
96 | return ool;
97 | }
98 |
--------------------------------------------------------------------------------
/lib/capq/qdlocksrc/locks/seq_lock.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2017 Kjell Winblad (http://winsh.me, kjellwinblad@gmail.com)
3 | *
4 | * This file is part of qd_lock_lib.
5 | *
6 | * qd_lock_lib is free software: you can redistribute it and/or modify
7 | * it under the terms of the GNU General Public License as published by
8 | * the Free Software Foundation, either version 3 of the License, or
9 | * (at your option) any later version.
10 | *
11 | * qd_lock_lib is distributed in the hope that it will be useful,
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | * GNU General Public License for more details.
15 | *
16 | * You should have received a copy of the GNU General Public License
17 | * along with qd_lock_lib. If not, see .
18 | */
19 |
20 | #ifndef SEQ_LOCK_H
21 | #define SEQ_LOCK_H
22 |
23 | #include "locks/oo_lock_interface.h"
24 | #include "misc/padded_types.h"
25 |
26 | #include "misc/bsd_stdatomic.h"//Until c11 stdatomic.h is available
27 | #include "misc/thread_includes.h"//Until c11 thread.h is available
28 | #include
29 |
30 |
31 | typedef struct SEQLockImpl {
32 | LLPaddedULong counter;
33 | } SEQLock;
34 |
35 |
36 | void seq_initialize(SEQLock * lock);
37 | void seq_lock(void * lock);
38 |
39 | static inline
40 | void seq_unlock(void * lock) {
41 | SEQLock *l = (SEQLock*)lock;
42 | atomic_fetch_add( &l->counter.value, 1 );
43 | }
44 |
45 | static inline
46 | bool seq_is_locked(void * lock){
47 | SEQLock *l = (SEQLock*)lock;
48 | return (atomic_load(&l->counter.value) % 2) == 1;
49 | }
50 |
51 | static inline
52 | unsigned long seq_start_read(void * lock){
53 | SEQLock *l = (SEQLock*)lock;
54 | unsigned long counter = atomic_load(&l->counter.value);
55 | if((counter % 2) == 0){
56 | return counter;
57 | }else{
58 | return 0;//Means invalid seq number, try again or force lock
59 | }
60 | }
61 |
62 | static inline
63 | bool seq_validate_read(void * lock, unsigned long counterValue){
64 | SEQLock *l = (SEQLock*)lock;
65 | unsigned long counter = atomic_load(&l->counter.value);
66 | return counterValue == counter;
67 | }
68 |
69 | static inline
70 | bool seq_try_lock(void * lock) {
71 | SEQLock *l = (SEQLock*)lock;
72 | unsigned long counter = atomic_load_explicit(&l->counter.value,
73 | memory_order_acquire);
74 | if((counter % 2) == 0){
75 | return atomic_compare_exchange_strong( &l->counter.value,
76 | &counter, counter + 1 );
77 | }else{
78 | return false;
79 | }
80 | }
81 | void seq_delegate(void * lock,
82 | void (*funPtr)(unsigned int, void *),
83 | unsigned int messageSize,
84 | void * messageAddress);
85 | void * seq_delegate_or_lock(void * lock, unsigned int messageSize);
86 | SEQLock * plain_seq_create();
87 | OOLock * oo_seq_create();
88 |
89 | #endif
90 |
--------------------------------------------------------------------------------
/lib/capq/qdlocksrc/locks/tatas_lock.c:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2017 Kjell Winblad (http://winsh.me, kjellwinblad@gmail.com)
3 | *
4 | * This file is part of qd_lock_lib.
5 | *
6 | * qd_lock_lib is free software: you can redistribute it and/or modify
7 | * it under the terms of the GNU General Public License as published by
8 | * the Free Software Foundation, either version 3 of the License, or
9 | * (at your option) any later version.
10 | *
11 | * qd_lock_lib is distributed in the hope that it will be useful,
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | * GNU General Public License for more details.
15 | *
16 | * You should have received a copy of the GNU General Public License
17 | * along with qd_lock_lib. If not, see .
18 | */
19 |
20 | #include "tatas_lock.h"
21 |
22 | _Alignas(CACHE_LINE_SIZE)
23 | OOLockMethodTable TATAS_LOCK_METHOD_TABLE =
24 | {
25 | .free = &free,
26 | .lock = &tatas_lock,
27 | .unlock = &tatas_unlock,
28 | .is_locked = &tatas_is_locked,
29 | .try_lock = &tatas_try_lock,
30 | .rlock = &tatas_lock,
31 | .runlock = &tatas_unlock,
32 | .delegate = &tatas_delegate,
33 | .delegate_wait = &tatas_delegate,
34 | .delegate_or_lock = &tatas_delegate_or_lock,
35 | .close_delegate_buffer = NULL, /* Should never be called */
36 | .delegate_unlock = &tatas_unlock
37 | };
38 |
39 |
40 |
41 | void tatas_initialize(TATASLock * lock){
42 | atomic_init( &lock->lockFlag.value, false );
43 | }
44 |
45 |
46 | void tatas_lock(void * lock) {
47 | TATASLock *l = (TATASLock*)lock;
48 | while(true){
49 | while(atomic_load_explicit(&l->lockFlag.value,
50 | memory_order_acquire)){
51 | thread_yield();
52 | }
53 | if( ! atomic_flag_test_and_set_explicit(&l->lockFlag.value,
54 | memory_order_acquire)){
55 | return;
56 | }
57 | }
58 | }
59 |
60 |
61 | void tatas_delegate(void * lock,
62 | void (*funPtr)(unsigned int, void *),
63 | unsigned int messageSize,
64 | void * messageAddress){
65 | TATASLock *l = (TATASLock*)lock;
66 | tatas_lock(l);
67 | funPtr(messageSize, messageAddress);
68 | tatas_unlock(l);
69 | }
70 |
71 |
72 | void * tatas_delegate_or_lock(void * lock, unsigned int messageSize){
73 | (void)messageSize;
74 | TATASLock *l = (TATASLock*)lock;
75 | tatas_lock(l);
76 | return NULL;
77 | }
78 |
79 |
80 |
81 | TATASLock * plain_tatas_create(){
82 | TATASLock * l = aligned_alloc(CACHE_LINE_SIZE, sizeof(TATASLock));
83 | tatas_initialize(l);
84 | return l;
85 | }
86 |
87 |
88 | OOLock * oo_tatas_create(){
89 | TATASLock * l = plain_tatas_create();
90 | OOLock * ool = aligned_alloc(CACHE_LINE_SIZE, sizeof(OOLock));
91 | ool->lock = l;
92 | ool->m = &TATAS_LOCK_METHOD_TABLE;
93 | return ool;
94 | }
95 |
--------------------------------------------------------------------------------
/lib/capq/qdlocksrc/locks/tatas_lock.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2017 Kjell Winblad (http://winsh.me, kjellwinblad@gmail.com)
3 | *
4 | * This file is part of qd_lock_lib.
5 | *
6 | * qd_lock_lib is free software: you can redistribute it and/or modify
7 | * it under the terms of the GNU General Public License as published by
8 | * the Free Software Foundation, either version 3 of the License, or
9 | * (at your option) any later version.
10 | *
11 | * qd_lock_lib is distributed in the hope that it will be useful,
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | * GNU General Public License for more details.
15 | *
16 | * You should have received a copy of the GNU General Public License
17 | * along with qd_lock_lib. If not, see .
18 | */
19 |
20 | #ifndef TATAS_LOCK_H
21 | #define TATAS_LOCK_H
22 |
23 | #include "locks/oo_lock_interface.h"
24 | #include "misc/padded_types.h"
25 |
26 | #include "misc/bsd_stdatomic.h"//Until c11 stdatomic.h is available
27 | #include "misc/thread_includes.h"//Until c11 thread.h is available
28 | #include
29 |
30 |
31 | typedef struct TATASLockImpl {
32 | LLPaddedFlag lockFlag;
33 | } TATASLock;
34 |
35 |
36 | void tatas_initialize(TATASLock * lock);
37 | void tatas_lock(void * lock);
38 | static inline
39 | void tatas_unlock(void * lock) {
40 | TATASLock *l = (TATASLock*)lock;
41 | atomic_flag_clear_explicit(&l->lockFlag.value, memory_order_release);
42 | }
43 | static inline
44 | bool tatas_is_locked(void * lock){
45 | TATASLock *l = (TATASLock*)lock;
46 | return atomic_load(&l->lockFlag.value);
47 | }
48 | static inline
49 | bool tatas_try_lock(void * lock) {
50 | TATASLock *l = (TATASLock*)lock;
51 | if(!atomic_load_explicit(&l->lockFlag.value, memory_order_acquire)){
52 | return !atomic_flag_test_and_set(&l->lockFlag.value);
53 | } else {
54 | return false;
55 | }
56 | }
57 | void tatas_delegate(void * lock,
58 | void (*funPtr)(unsigned int, void *),
59 | unsigned int messageSize,
60 | void * messageAddress);
61 | void * tatas_delegate_or_lock(void * lock, unsigned int messageSize);
62 | TATASLock * plain_tatas_create();
63 | OOLock * oo_tatas_create();
64 |
65 | #endif
66 |
--------------------------------------------------------------------------------
/lib/capq/qdlocksrc/locks/ticket_lock.c:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2017 Kjell Winblad (http://winsh.me, kjellwinblad@gmail.com)
3 | *
4 | * This file is part of qd_lock_lib.
5 | *
6 | * qd_lock_lib is free software: you can redistribute it and/or modify
7 | * it under the terms of the GNU General Public License as published by
8 | * the Free Software Foundation, either version 3 of the License, or
9 | * (at your option) any later version.
10 | *
11 | * qd_lock_lib is distributed in the hope that it will be useful,
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | * GNU General Public License for more details.
15 | *
16 | * You should have received a copy of the GNU General Public License
17 | * along with qd_lock_lib. If not, see .
18 | */
19 |
20 | #include "ticket_lock.h"
21 |
22 | _Alignas(CACHE_LINE_SIZE)
23 | OOLockMethodTable Ticket_LOCK_METHOD_TABLE =
24 | {
25 | .free = &free,
26 | .lock = &ticket_lock,
27 | .unlock = &ticket_unlock,
28 | .is_locked = &ticket_is_locked,
29 | .try_lock = &ticket_try_lock,
30 | .rlock = &ticket_lock,
31 | .runlock = &ticket_unlock,
32 | .delegate = &ticket_delegate,
33 | .delegate_wait = &ticket_delegate,
34 | .delegate_or_lock = &ticket_delegate_or_lock,
35 | .close_delegate_buffer = NULL, /* Should never be called */
36 | .delegate_unlock = &ticket_unlock
37 | };
38 |
39 |
40 |
41 | void ticket_initialize(TicketLock * lock){
42 | // printf("TICKET LOCK inti %p\n", lock);
43 | atomic_init( &lock->ingress, 0 );
44 | atomic_init( &lock->egress, 0 );
45 | }
46 |
47 | void ticket_delegate(void * lock,
48 | void (*funPtr)(unsigned int, void *),
49 | unsigned int messageSize,
50 | void * messageAddress){
51 | TicketLock *l = (TicketLock*)lock;
52 | ticket_lock(l);
53 | funPtr(messageSize, messageAddress);
54 | ticket_unlock(l);
55 | }
56 |
57 |
58 | void * ticket_delegate_or_lock(void * lock, unsigned int messageSize){
59 | (void)messageSize;
60 | TicketLock *l = (TicketLock*)lock;
61 | ticket_lock(l);
62 | return NULL;
63 | }
64 |
65 |
66 |
67 | TicketLock * plain_ticket_create(){
68 | TicketLock * l = aligned_alloc(CACHE_LINE_SIZE, sizeof(TicketLock));
69 | ticket_initialize(l);
70 | return l;
71 | }
72 |
73 |
74 | OOLock * oo_ticket_create(){
75 | TicketLock * l = plain_ticket_create();
76 | OOLock * ool = aligned_alloc(CACHE_LINE_SIZE, sizeof(OOLock));
77 | ool->lock = l;
78 | ool->m = &Ticket_LOCK_METHOD_TABLE;
79 | return ool;
80 | }
81 |
--------------------------------------------------------------------------------
/lib/capq/qdlocksrc/locks/ticket_lock.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2017 Kjell Winblad (http://winsh.me, kjellwinblad@gmail.com)
3 | *
4 | * This file is part of qd_lock_lib.
5 | *
6 | * qd_lock_lib is free software: you can redistribute it and/or modify
7 | * it under the terms of the GNU General Public License as published by
8 | * the Free Software Foundation, either version 3 of the License, or
9 | * (at your option) any later version.
10 | *
11 | * qd_lock_lib is distributed in the hope that it will be useful,
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | * GNU General Public License for more details.
15 | *
16 | * You should have received a copy of the GNU General Public License
17 | * along with qd_lock_lib. If not, see .
18 | */
19 |
20 | #ifndef Ticket_LOCK_H
21 | #define Ticket_LOCK_H
22 |
23 | #include "locks/oo_lock_interface.h"
24 | #include "misc/padded_types.h"
25 |
26 | #include "misc/bsd_stdatomic.h"//Until c11 stdatomic.h is available
27 | #include "misc/thread_includes.h"//Until c11 thread.h is available
28 | #include
29 |
30 |
31 | typedef struct TicketLockImpl {
32 | volatile atomic_ulong ingress;
33 | volatile atomic_ulong egress;
34 | char pad[CACHE_LINE_SIZE_PAD(2*sizeof(atomic_ulong))];
35 | } TicketLock;
36 |
37 |
38 | void ticket_initialize(TicketLock * lock);
39 | static inline
40 | void ticket_lock(void * lock) {
41 | TicketLock *l = (TicketLock*)lock;
42 | //printf("TICKET LOCK %p\n", l);
43 | unsigned long prevValue = atomic_fetch_add_explicit(&l->ingress, 1, memory_order_acquire);
44 | while(atomic_load_explicit(&l->egress,
45 | memory_order_acquire) != prevValue){
46 | thread_yield();
47 | }
48 | }
49 | static inline
50 | void ticket_unlock(void * lock) {
51 | TicketLock *l = (TicketLock*)lock;
52 | atomic_fetch_add_explicit(&l->egress, 1, memory_order_release);
53 | }
54 | static inline
55 | bool ticket_is_locked(void * lock){
56 | TicketLock *l = (TicketLock*)lock;
57 | return atomic_load(&l->egress) != atomic_load(&l->ingress);
58 | }
59 | static inline
60 | bool ticket_try_lock(void * lock) {
61 | TicketLock *l = (TicketLock*)lock;
62 | unsigned long ingress = atomic_load_explicit(&l->ingress, memory_order_acquire);
63 | if(ingress == atomic_load_explicit(&l->egress, memory_order_acquire)){
64 | return atomic_compare_exchange_strong( &l->ingress,
65 | &ingress,
66 | ingress + 1);
67 | }
68 | return false;
69 | }
70 | void ticket_delegate(void * lock,
71 | void (*funPtr)(unsigned int, void *),
72 | unsigned int messageSize,
73 | void * messageAddress);
74 | void * ticket_delegate_or_lock(void * lock, unsigned int messageSize);
75 | TicketLock * plain_ticket_create();
76 | OOLock * oo_ticket_create();
77 |
78 | #endif
79 |
--------------------------------------------------------------------------------
/lib/capq/qdlocksrc/misc/bitreversal.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2017 Kjell Winblad (http://winsh.me, kjellwinblad@gmail.com)
3 | *
4 | * This file is part of qd_lock_lib.
5 | *
6 | * qd_lock_lib is free software: you can redistribute it and/or modify
7 | * it under the terms of the GNU General Public License as published by
8 | * the Free Software Foundation, either version 3 of the License, or
9 | * (at your option) any later version.
10 | *
11 | * qd_lock_lib is distributed in the hope that it will be useful,
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | * GNU General Public License for more details.
15 | *
16 | * You should have received a copy of the GNU General Public License
17 | * along with qd_lock_lib. If not, see .
18 | */
19 |
20 | #ifndef BITREVERSAL_H
21 | #define BITREVERSAL_H
22 |
23 | static const unsigned char BitReverseTable256[] =
24 | {
25 | 0x00, 0x80, 0x40, 0xC0, 0x20, 0xA0, 0x60, 0xE0, 0x10, 0x90, 0x50, 0xD0, 0x30, 0xB0, 0x70, 0xF0,
26 | 0x08, 0x88, 0x48, 0xC8, 0x28, 0xA8, 0x68, 0xE8, 0x18, 0x98, 0x58, 0xD8, 0x38, 0xB8, 0x78, 0xF8,
27 | 0x04, 0x84, 0x44, 0xC4, 0x24, 0xA4, 0x64, 0xE4, 0x14, 0x94, 0x54, 0xD4, 0x34, 0xB4, 0x74, 0xF4,
28 | 0x0C, 0x8C, 0x4C, 0xCC, 0x2C, 0xAC, 0x6C, 0xEC, 0x1C, 0x9C, 0x5C, 0xDC, 0x3C, 0xBC, 0x7C, 0xFC,
29 | 0x02, 0x82, 0x42, 0xC2, 0x22, 0xA2, 0x62, 0xE2, 0x12, 0x92, 0x52, 0xD2, 0x32, 0xB2, 0x72, 0xF2,
30 | 0x0A, 0x8A, 0x4A, 0xCA, 0x2A, 0xAA, 0x6A, 0xEA, 0x1A, 0x9A, 0x5A, 0xDA, 0x3A, 0xBA, 0x7A, 0xFA,
31 | 0x06, 0x86, 0x46, 0xC6, 0x26, 0xA6, 0x66, 0xE6, 0x16, 0x96, 0x56, 0xD6, 0x36, 0xB6, 0x76, 0xF6,
32 | 0x0E, 0x8E, 0x4E, 0xCE, 0x2E, 0xAE, 0x6E, 0xEE, 0x1E, 0x9E, 0x5E, 0xDE, 0x3E, 0xBE, 0x7E, 0xFE,
33 | 0x01, 0x81, 0x41, 0xC1, 0x21, 0xA1, 0x61, 0xE1, 0x11, 0x91, 0x51, 0xD1, 0x31, 0xB1, 0x71, 0xF1,
34 | 0x09, 0x89, 0x49, 0xC9, 0x29, 0xA9, 0x69, 0xE9, 0x19, 0x99, 0x59, 0xD9, 0x39, 0xB9, 0x79, 0xF9,
35 | 0x05, 0x85, 0x45, 0xC5, 0x25, 0xA5, 0x65, 0xE5, 0x15, 0x95, 0x55, 0xD5, 0x35, 0xB5, 0x75, 0xF5,
36 | 0x0D, 0x8D, 0x4D, 0xCD, 0x2D, 0xAD, 0x6D, 0xED, 0x1D, 0x9D, 0x5D, 0xDD, 0x3D, 0xBD, 0x7D, 0xFD,
37 | 0x03, 0x83, 0x43, 0xC3, 0x23, 0xA3, 0x63, 0xE3, 0x13, 0x93, 0x53, 0xD3, 0x33, 0xB3, 0x73, 0xF3,
38 | 0x0B, 0x8B, 0x4B, 0xCB, 0x2B, 0xAB, 0x6B, 0xEB, 0x1B, 0x9B, 0x5B, 0xDB, 0x3B, 0xBB, 0x7B, 0xFB,
39 | 0x07, 0x87, 0x47, 0xC7, 0x27, 0xA7, 0x67, 0xE7, 0x17, 0x97, 0x57, 0xD7, 0x37, 0xB7, 0x77, 0xF7,
40 | 0x0F, 0x8F, 0x4F, 0xCF, 0x2F, 0xAF, 0x6F, 0xEF, 0x1F, 0x9F, 0x5F, 0xDF, 0x3F, 0xBF, 0x7F, 0xFF
41 | };
42 |
43 | static inline unsigned int reverse_bits(unsigned int v){
44 | return
45 | (BitReverseTable256[v & 0xff] << 24) |
46 | (BitReverseTable256[(v >> 8) & 0xff] << 16) |
47 | (BitReverseTable256[(v >> 16) & 0xff] << 8) |
48 | (BitReverseTable256[(v >> 24) & 0xff]);
49 | }
50 |
51 | #endif
52 |
--------------------------------------------------------------------------------
/lib/capq/qdlocksrc/misc/error_help.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2017 Kjell Winblad (http://winsh.me, kjellwinblad@gmail.com)
3 | *
4 | * This file is part of qd_lock_lib.
5 | *
6 | * qd_lock_lib is free software: you can redistribute it and/or modify
7 | * it under the terms of the GNU General Public License as published by
8 | * the Free Software Foundation, either version 3 of the License, or
9 | * (at your option) any later version.
10 | *
11 | * qd_lock_lib is distributed in the hope that it will be useful,
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | * GNU General Public License for more details.
15 | *
16 | * You should have received a copy of the GNU General Public License
17 | * along with qd_lock_lib. If not, see .
18 | */
19 |
20 | #ifndef ERROR_HELP_H
21 | #define ERROR_HELP_H
22 |
23 | #include
24 | #include
25 |
26 | static inline void LL_error_and_exit_verbose(const char * file, const char * function, int line, char * message){
27 | printf("ERROR IN FILE: %s, FUNCTION: %s, LINE: %d\n", file, function, line);
28 | printf("%s\n", message);
29 | printf("EXITING\n");
30 | exit(1);
31 | }
32 |
33 | #define LL_error_and_exit(message) LL_error_and_exit_verbose(__FILE__, __func__, __LINE__, message)
34 |
35 | #endif
36 |
--------------------------------------------------------------------------------
/lib/capq/qdlocksrc/misc/misc_utils.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2017 Kjell Winblad (http://winsh.me, kjellwinblad@gmail.com)
3 | *
4 | * This file is part of qd_lock_lib.
5 | *
6 | * qd_lock_lib is free software: you can redistribute it and/or modify
7 | * it under the terms of the GNU General Public License as published by
8 | * the Free Software Foundation, either version 3 of the License, or
9 | * (at your option) any later version.
10 | *
11 | * qd_lock_lib is distributed in the hope that it will be useful,
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | * GNU General Public License for more details.
15 | *
16 | * You should have received a copy of the GNU General Public License
17 | * along with qd_lock_lib. If not, see .
18 | */
19 |
20 | #ifndef MISC_UTILS_H
21 | #define MISC_UTILS_H
22 |
23 | #define UNUSED(x) (void)(x)
24 |
25 | #endif
26 |
--------------------------------------------------------------------------------
/lib/capq/qdlocksrc/misc/padded_types.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2017 Kjell Winblad (http://winsh.me, kjellwinblad@gmail.com)
3 | *
4 | * This file is part of qd_lock_lib.
5 | *
6 | * qd_lock_lib is free software: you can redistribute it and/or modify
7 | * it under the terms of the GNU General Public License as published by
8 | * the Free Software Foundation, either version 3 of the License, or
9 | * (at your option) any later version.
10 | *
11 | * qd_lock_lib is distributed in the hope that it will be useful,
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | * GNU General Public License for more details.
15 | *
16 | * You should have received a copy of the GNU General Public License
17 | * along with qd_lock_lib. If not, see .
18 | */
19 |
20 | #ifndef PADDED_TYPES_H
21 | #define PADDED_TYPES_H
22 |
23 | #include "misc/bsd_stdatomic.h"//Until c11 stdatoic.h is available
24 |
25 | #define CACHE_LINE_SIZE 128
26 |
27 | #define CACHE_LINE_SIZE_PAD(size) CACHE_LINE_SIZE - (size) % CACHE_LINE_SIZE
28 |
29 | #ifndef _ISOC11_SOURCE
30 | # if _POSIX_C_SOURCE >= 200112
31 | # include
32 | # define aligned_alloc memalign
33 | # endif
34 | #endif
35 |
36 |
37 | typedef union {
38 | volatile atomic_flag value;
39 | char padding[CACHE_LINE_SIZE];
40 | } LLPaddedFlag;
41 |
42 | typedef union {
43 | volatile atomic_bool value;
44 | char padding[CACHE_LINE_SIZE];
45 | } LLPaddedBool;
46 |
47 | typedef union {
48 | volatile atomic_int value;
49 | char padding[CACHE_LINE_SIZE];
50 | } LLPaddedInt;
51 |
52 | typedef union {
53 | volatile atomic_uint value;
54 | char padding[CACHE_LINE_SIZE];
55 | } LLPaddedUInt;
56 |
57 | typedef union {
58 | volatile atomic_long value;
59 | char padding[CACHE_LINE_SIZE];
60 | } LLPaddedLong;
61 |
62 | typedef union {
63 | volatile atomic_ulong value;
64 | char padding[CACHE_LINE_SIZE];
65 | } LLPaddedULong;
66 |
67 | typedef union {
68 | volatile atomic_intptr_t value;
69 | char padding[CACHE_LINE_SIZE];
70 | } LLPaddedPointer;
71 |
72 | typedef union {
73 | volatile double value;
74 | char padding[CACHE_LINE_SIZE];
75 | } LLPaddedDouble;
76 |
77 | #endif
78 |
--------------------------------------------------------------------------------
/lib/capq/qdlocksrc/misc/random.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2017 Kjell Winblad (http://winsh.me, kjellwinblad@gmail.com)
3 | *
4 | * This file is part of qd_lock_lib.
5 | *
6 | * qd_lock_lib is free software: you can redistribute it and/or modify
7 | * it under the terms of the GNU General Public License as published by
8 | * the Free Software Foundation, either version 3 of the License, or
9 | * (at your option) any later version.
10 | *
11 | * qd_lock_lib is distributed in the hope that it will be useful,
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | * GNU General Public License for more details.
15 | *
16 | * You should have received a copy of the GNU General Public License
17 | * along with qd_lock_lib. If not, see .
18 | */
19 |
20 | #ifndef RANDOM_H
21 | #define RANDOM_H
22 |
23 | #include "stdlib.h"
24 |
25 | static double random_double(unsigned int *seed_ptr){
26 | double randomDouble = (double)rand_r(seed_ptr);
27 | return randomDouble/RAND_MAX;
28 | }
29 |
30 |
31 | #endif
32 |
--------------------------------------------------------------------------------
/lib/capq/qdlocksrc/misc/thread_includes.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2017 Kjell Winblad (http://winsh.me, kjellwinblad@gmail.com)
3 | *
4 | * This file is part of qd_lock_lib.
5 | *
6 | * qd_lock_lib is free software: you can redistribute it and/or modify
7 | * it under the terms of the GNU General Public License as published by
8 | * the Free Software Foundation, either version 3 of the License, or
9 | * (at your option) any later version.
10 | *
11 | * qd_lock_lib is distributed in the hope that it will be useful,
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | * GNU General Public License for more details.
15 | *
16 | * You should have received a copy of the GNU General Public License
17 | * along with qd_lock_lib. If not, see .
18 | */
19 |
20 | #ifndef THREAD_INCLUDES_H
21 | #define THREAD_INCLUDES_H
22 |
23 | #include
24 | #include
25 | #include //Until c11 threads.h is available
26 | #include
27 | #include
28 |
29 | #if defined(__x86_64__) || defined(_M_X64)
30 | #define CPUPAUSE asm("pause");
31 | #else
32 | #define CPUPAUSE
33 | #endif
34 |
35 | static inline void thread_yield(){
36 | //sched_yield();
37 | //atomic_thread_fence(memory_order_seq_cst);
38 | CPUPAUSE;
39 | }
40 |
41 | #ifndef __clang__
42 | # define _Thread_local __thread
43 | #endif
44 |
45 | #endif
46 |
--------------------------------------------------------------------------------
/lib/capq/qdlocksrc/read_indicators/reader_groups_read_indicator.c:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2017 Kjell Winblad (http://winsh.me, kjellwinblad@gmail.com)
3 | *
4 | * This file is part of qd_lock_lib.
5 | *
6 | * qd_lock_lib is free software: you can redistribute it and/or modify
7 | * it under the terms of the GNU General Public License as published by
8 | * the Free Software Foundation, either version 3 of the License, or
9 | * (at your option) any later version.
10 | *
11 | * qd_lock_lib is distributed in the hope that it will be useful,
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | * GNU General Public License for more details.
15 | *
16 | * You should have received a copy of the GNU General Public License
17 | * along with qd_lock_lib. If not, see .
18 | */
19 |
20 | #include "reader_groups_read_indicator.h"
21 |
22 | volatile atomic_int rgri_get_thread_id_counter = ATOMIC_VAR_INIT(0);
23 |
24 | _Alignas(CACHE_LINE_SIZE)
25 | _Thread_local RGRIGetThreadIDVarWrapper rgri_get_thread_id_var = {.value = -1};
26 |
--------------------------------------------------------------------------------
/lib/sequence_heap/README:
--------------------------------------------------------------------------------
1 | Taken from http://www.mpi-inf.mpg.de/~sanders/programs/spq/.
2 |
--------------------------------------------------------------------------------
/lib/sequence_heap/multiMergeUnrolled.C:
--------------------------------------------------------------------------------
1 | // body of the function multiMergeUnrolled
2 | // it will be included multiple times with
3 | // different settings for LogP
4 | // Note that in gcc it is sufficient to simply
5 | // use an addtional argument and to declare things an inline
6 | // function. But I was not able to convince SunCC to
7 | // inline and constant fold it.
8 | // Similarly I tried introducing LogP as a template
9 | // parameter but this did not compile on SunCC
10 | {
11 | Element *done = to + l;
12 | Entry *regEntry = entry;
13 | Element **regCurrent = current;
14 | int winnerIndex = regEntry[0].index;
15 | Key winnerKey = regEntry[0].key;
16 | Element *winnerPos;
17 | Key sup = dummy.key; // supremum
18 |
19 | Assert2(logK >= LogK);
20 | while (to < done)
21 | {
22 | winnerPos = regCurrent[winnerIndex];
23 |
24 | // write result
25 | to->key = winnerKey;
26 | to->value = winnerPos->value;
27 |
28 | // advance winner segment
29 | winnerPos++;
30 | regCurrent[winnerIndex] = winnerPos;
31 | winnerKey = winnerPos->key;
32 |
33 | // remove winner segment if empty now
34 | if (winnerKey == sup) {
35 | deallocateSegment(winnerIndex);
36 | }
37 | to++;
38 |
39 | // update looser tree
40 | #define TreeStep(L)\
41 | if (1 << LogK >= 1 << L) {\
42 | Entry *pos##L = regEntry+((winnerIndex+(1<> ((LogK-L)+1));\
43 | Key key##L = pos##L->key;\
44 | if (key##L < winnerKey) {\
45 | int index##L = pos##L->index;\
46 | pos##L->key = winnerKey;\
47 | pos##L->index = winnerIndex;\
48 | winnerKey = key##L;\
49 | winnerIndex = index##L;\
50 | }\
51 | }
52 | TreeStep(10);
53 | TreeStep(9);
54 | TreeStep(8);
55 | TreeStep(7);
56 | TreeStep(6);
57 | TreeStep(5);
58 | TreeStep(4);
59 | TreeStep(3);
60 | TreeStep(2);
61 | TreeStep(1);
62 | #undef TreeStep
63 | }
64 | regEntry[0].index = winnerIndex;
65 | regEntry[0].key = winnerKey;
66 | }
67 |
--------------------------------------------------------------------------------
/lib/sequence_heap/readme.asc:
--------------------------------------------------------------------------------
1 | # Files in this directory Jun 21, 1999:
2 | knheap.C/h: sequence heaps
3 | heap2.h: fast binary heaps
4 | heap4.h: aligned 4-ary heaps
5 | heap-CLR.h: textbook-like Binary heap
6 | knupdown3.C: program used for the measurements
7 | of the sequence
8 | (insert deleteMin insert)^N(deleteMin insert deleteMin)^N
9 | uncomment one of KNH, H2, H4, or HSLOW to try
10 | one of the above four queue algorithms
11 | knwiggle.C: program used for the measurements of the sequence
12 | (insert (insert delete)^k)^N (delete (insert delete)^k)^N
13 | multiMergeUnrolled.C: unrolled mulit-way merging
14 | using loser trees. Included by knheap.C
15 | util.h basic uttilities included by all codes
16 |
17 | compilation is simply done with g++ or the native compiler.
18 | No make file needed, e.g.,
19 | "g++ knupdown3.C"
20 |
--------------------------------------------------------------------------------
/lib/sequence_heap/util.h:
--------------------------------------------------------------------------------
1 | // this files contains all the application independent little
2 | // functions and macros used for the optimizer.
3 | // In particular Peters debug macros and Dags stuff
4 | // from dbasic.h cdefs, random,...
5 |
6 | //////////////// stuff originally from debug.h ///////////////////////////////
7 | // (c) 1997 Peter Sanders
8 | // some little utilities for debugging adapted
9 | // to the paros conventions
10 |
11 |
12 | #ifndef UTIL
13 | #define UTIL
14 |
15 | #include
16 |
17 | using namespace std;
18 |
19 | // default debug level. will be overidden e.g. if debug.h is included
20 | #ifndef DEBUGLEVEL
21 | #define DEBUGLEVEL 3
22 | #endif
23 |
24 | #if DEBUGLEVEL >= 0
25 | #define Debug0(A) A
26 | #else
27 | #define Debug0(A)
28 | #endif
29 | #if DEBUGLEVEL >= 1
30 | #define Debug1(A) A
31 | #else
32 | #define Debug1(A)
33 | #endif
34 | #if DEBUGLEVEL >= 2
35 | #define Debug2(A) A
36 | #else
37 | #define Debug2(A)
38 | #endif
39 | #if DEBUGLEVEL >= 3
40 | #define Debug3(A) A
41 | #else
42 | #define Debug3(A)
43 | #endif
44 | #if DEBUGLEVEL >= 4
45 | #define Debug4(A) A
46 | #else
47 | #define Debug4(A)
48 | #endif
49 | #if DEBUGLEVEL >= 5
50 | #define Debug5(A) A
51 | #else
52 | #define Debug5(A)
53 | #endif
54 | #if DEBUGLEVEL >= 6
55 | #define Debug6(A) A
56 | #else
57 | #define Debug6(A)
58 | #endif
59 |
60 | #define Assert(c) if(!(c))\
61 | {cout << "\nAssertion violation " << __FILE__ << ":" << __LINE__ << endl;}
62 | #define Assert0(C) Debug0(Assert(C))
63 | #define Assert1(C) Debug1(Assert(C))
64 | #define Assert2(C) Debug2(Assert(C))
65 | #define Assert3(C) Debug3(Assert(C))
66 | #define Assert4(C) Debug4(Assert(C))
67 | #define Assert5(C) Debug5(Assert(C))
68 |
69 | #define Error(s) {cout << "\nError:" << s << " " << __FILE__ << ":" << __LINE__ << endl;}
70 |
71 | ////////////// min, max etc. //////////////////////////////////////
72 |
73 | #ifndef Max
74 | #define Max(x,y) ((x)>=(y)?(x):(y))
75 | #endif
76 |
77 | #ifndef Min
78 | #define Min(x,y) ((x)<=(y)?(x):(y))
79 | #endif
80 |
81 | #ifndef Abs
82 | #define Abs(x) ((x) < 0 ? -(x) : (x))
83 | #endif
84 |
85 | #ifndef PI
86 | #define PI 3.1415927
87 | #endif
88 |
89 | // is this the right definition of limit?
90 | inline double limit(double x, double bound)
91 | {
92 | if (x > bound) {
93 | return bound;
94 | } else if (x < -bound) {
95 | return -bound;
96 | } else {
97 | return x;
98 | }
99 | }
100 |
101 | /////////////////////// timing /////////////////////
102 | #include
103 |
104 | inline double wallClockTime()
105 | {
106 | struct timespec tp;
107 |
108 | clock_gettime(CLOCK_REALTIME, &tp);
109 | return tp.tv_sec + tp.tv_nsec * 1e-9;
110 | }
111 |
112 | // elapsed CPU time see also /usr/include/sys/time.h
113 | inline double cpuTime()
114 | {
115 | return clock() * 1e-6;
116 | // clock_gettime(CLOCK_VIRTUAL, &tp);
117 | // return tp.tv_sec + tp.tv_nsec * 1e-9;
118 | }
119 |
120 | #endif
121 |
--------------------------------------------------------------------------------
/lib/skip_list/.gitignore:
--------------------------------------------------------------------------------
1 | a.out
2 | boost
3 |
4 | build/build
5 | *.mode1v3
6 | *.pbxuser
7 | .DS_Store
8 | xcuserdata
9 | project.xcworkspace
10 |
11 | *.ncb
12 | *.suo
13 | *.vcproj.*.user
14 | build/Debug
15 | build/Release
16 |
--------------------------------------------------------------------------------
/lib/skip_list/TODO.md:
--------------------------------------------------------------------------------
1 | Consider impl held in pointer, so std::swap keeps iterators pointing to right structure
2 | C++11 operations
3 | full unit tests for random skip list now it doesn't inherit
4 | look at a better level generator algorithm (compare in benchmarking)
--------------------------------------------------------------------------------
/lib/skip_list/tests/get_time.h:
--------------------------------------------------------------------------------
1 | //==============================================================================
2 | // get_time.h
3 | // Copyright (c) 2011 Pete Goodliffe. All rights reserved.
4 | //==============================================================================
5 |
6 | #pragma once
7 |
8 | #if defined (WIN32) || defined (WIN64)
9 | #define NOMINMAX
10 | #include "windows.h"
11 | #elif defined(__APPLE__)
12 | #include
13 | #include
14 | #include
15 | #else
16 | #include
17 | #include
18 | #endif
19 |
20 | inline long get_time_ms()
21 | {
22 | #if defined (WIN32) || defined (WIN64)
23 | return GetTickCount();
24 | #elif defined(__APPLE__)
25 | //mach_timebase_info_data_t info;
26 | //kern_return_t err = mach_timebase_info( &info );
27 | static double conversion = 0.0;
28 |
29 | if( conversion == 0.0 )
30 | {
31 | mach_timebase_info_data_t info;
32 | kern_return_t err = mach_timebase_info( &info );
33 |
34 | //Convert the timebase into seconds
35 | if( err == 0 )
36 | {
37 | conversion = 1e-6 * (double) info.numer / (double) info.denom;
38 | }
39 | }
40 | return long(mach_absolute_time() * conversion);
41 | #else
42 | struct timeval t;
43 | gettimeofday(&t, NULL);
44 | return t.tv_sec * 1000 + t.tv_usec/1000;
45 | #endif
46 | }
47 |
48 | inline long get_time_us()
49 | {
50 | #if defined (WIN32) || defined (WIN64)
51 | // TODO: This sucks. We can all see that. :-)
52 | return GetTickCount()*1000;
53 | #else
54 | struct timeval t;
55 | gettimeofday(&t, NULL);
56 | return t.tv_sec * 1000000 + t.tv_usec;
57 | #endif
58 | }
--------------------------------------------------------------------------------
/lib/skip_list/tests/test.sh:
--------------------------------------------------------------------------------
1 | echo "Running unit tests..."
2 | g++ test.cpp -I. -I.. && ./a.out && echo "Tests passed"; rm a.out
3 |
4 | echo "Running benchmarks..."
5 | g++ benchmark.cpp -I.. -I. -DBENCHMARK_WITH_MAIN && ./a.out; rm a.out
6 |
--------------------------------------------------------------------------------
/lib/spraylist_linden/.gitignore:
--------------------------------------------------------------------------------
1 | bin/
2 | build/
3 | *log
4 | *out
5 |
--------------------------------------------------------------------------------
/lib/spraylist_linden/GIT_COMMIT_ID:
--------------------------------------------------------------------------------
1 | The code in this folder is based on the SprayList code with commit id
2 | e6c851d93156646efa4ce0a9dbdb2e1a3e8d3693 (*) but contains a patch that
3 | improves memory handling for the SprayList.
4 |
5 | Without the patch it is only possible to specify how much memory each
6 | thread will be able to allocate. This is problematic for the single
7 | source shortest paths benchmark as it makes it impossible to run the
8 | benchmark with a single thread and many threads using the same
9 | binary. The benchmark would either run out of memory when a single
10 | thread is used or there would not be enough memory on the machine when
11 | many threads are used.
12 |
13 | With the patch one can specify how much memory all threads can
14 | allocated together (the #define SSALLOC_SIZE_ALL in
15 | include/ssalloc.h). The patch makes sure that this amount of memory is
16 | divided between the threads (Note that the global variable
17 | number_of_threads has to be set to the correct value for this to
18 | work).
19 |
20 | (*) https://github.com/jkopinsky/SprayList/tree/e6c851d93156646efa4ce0a9dbdb2e1a3e8d3693
21 |
22 |
23 |
24 |
25 |
--------------------------------------------------------------------------------
/lib/spraylist_linden/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2014 jkopinsky
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
--------------------------------------------------------------------------------
/lib/spraylist_linden/README.md:
--------------------------------------------------------------------------------
1 | SprayList
2 | =========
3 |
4 | The SprayList data structure
5 |
6 | PREREQUISITES
7 | -------------
8 |
9 | gcc 4.6
10 | gsl (should be removed soon)
11 |
12 |
13 | INSTALL
14 | -------
15 |
16 | Compile using make
17 |
18 |
19 | RUN
20 | ---
21 |
22 | Run the executable at
23 | ./bin/spray
24 |
25 | -h option to view parameters
26 | Default experiment uses Fraser's skiplist to alternatingly insert a random value and then remove the successor of another random value.
27 |
28 |
29 | EXPERIMENTS
30 | -----------
31 |
32 | Several run scripts are included to execute the experiments described in the paper. The following do not take any inputs:
33 | --run_throughput.sh: Run the throughput experiment described in Section 4.1 (Figure 3)
34 | --run_sssp_all.sh: Run the SSSP experiments described in Section 4.3 (Figure 5)
35 | --run_des.sh: Run the Discrete Event Simulation experiment described in Section 4.4 (Figure 6)
36 |
--------------------------------------------------------------------------------
/lib/spraylist_linden/atomic_ops/AUTHORS:
--------------------------------------------------------------------------------
1 | Originally written by Hans Boehm, with some platform-dependent code
2 | imported from the Boehm-Demers-Weiser GC, where it was contributed
3 | by many others.
4 |
5 |
--------------------------------------------------------------------------------
/lib/spraylist_linden/atomic_ops/README:
--------------------------------------------------------------------------------
1 | This directory contains a stripped-down (support only gcc) version of libatomic_ops by Hans Boehm.
2 | The official release is available from http://www.hpl.hp.com/research/linux/atomic_ops/.
3 |
--------------------------------------------------------------------------------
/lib/spraylist_linden/atomic_ops/aligned_atomic_load_store.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2003 Hewlett-Packard Development Company, L.P.
3 | *
4 | * Permission is hereby granted, free of charge, to any person obtaining a copy
5 | * of this software and associated documentation files (the "Software"), to deal
6 | * in the Software without restriction, including without limitation the rights
7 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 | * copies of the Software, and to permit persons to whom the Software is
9 | * furnished to do so, subject to the following conditions:
10 | *
11 | * The above copyright notice and this permission notice shall be included in
12 | * all copies or substantial portions of the Software.
13 | *
14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
20 | * SOFTWARE.
21 | */
22 |
23 | /*
24 | * Definitions for architectures on which loads and stores of AO_t are
25 | * atomic fo all legal alignments.
26 | */
27 |
28 | AO_INLINE AO_t
29 | AO_load(const volatile AO_t *addr)
30 | {
31 | assert(((size_t)addr & (sizeof(AO_t) - 1)) == 0);
32 | /* Cast away the volatile for architectures where */
33 | /* volatile adds barrier semantics. */
34 | return *(AO_t *)addr;
35 | }
36 |
37 | #define AO_HAVE_load
38 |
39 | AO_INLINE void
40 | AO_store(volatile AO_t *addr, AO_t new_val)
41 | {
42 | assert(((size_t)addr & (sizeof(AO_t) - 1)) == 0);
43 | (*(AO_t *)addr) = new_val;
44 | }
45 |
46 | #define AO_HAVE_store
47 |
--------------------------------------------------------------------------------
/lib/spraylist_linden/atomic_ops/read_ordered.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2003 by Hewlett-Packard Company. All rights reserved.
3 | *
4 | * Permission is hereby granted, free of charge, to any person obtaining a copy
5 | * of this software and associated documentation files (the "Software"), to deal
6 | * in the Software without restriction, including without limitation the rights
7 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 | * copies of the Software, and to permit persons to whom the Software is
9 | * furnished to do so, subject to the following conditions:
10 | *
11 | * The above copyright notice and this permission notice shall be included in
12 | * all copies or substantial portions of the Software.
13 | *
14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
20 | * SOFTWARE.
21 | */
22 |
23 | /*
24 | * These are common definitions for architectures that provide processor
25 | * ordered memory operations except that a later read may pass an
26 | * earlier write. Real x86 implementations seem to be in this category,
27 | * except apparently for some IDT WinChips, which we ignore.
28 | */
29 |
30 | AO_INLINE void
31 | AO_nop_read(void)
32 | {
33 | AO_compiler_barrier();
34 | }
35 |
36 | #define AO_HAVE_NOP_READ
37 |
38 | #ifdef AO_HAVE_load
39 |
40 | AO_INLINE AO_t
41 | AO_load_read(const volatile AO_t *addr)
42 | {
43 | AO_t result = AO_load(addr);
44 | AO_compiler_barrier();
45 | return result;
46 | }
47 | #define AO_HAVE_load_read
48 |
49 | #define AO_load_acquire(addr) AO_load_read(addr)
50 | #define AO_HAVE_load_acquire
51 |
52 | #endif /* AO_HAVE_load */
53 |
54 | #ifdef AO_HAVE_char_load
55 |
56 | AO_INLINE AO_t
57 | AO_char_load_read(const volatile unsigned char *addr)
58 | {
59 | AO_t result = AO_char_load(addr);
60 | AO_compiler_barrier();
61 | return result;
62 | }
63 | #define AO_HAVE_char_load_read
64 |
65 | #define AO_char_load_acquire(addr) AO_char_load_read(addr)
66 | #define AO_HAVE_char_load_acquire
67 |
68 | #endif /* AO_HAVE_char_load */
69 |
70 | #ifdef AO_HAVE_short_load
71 |
72 | AO_INLINE AO_t
73 | AO_short_load_read(const volatile unsigned short *addr)
74 | {
75 | AO_t result = AO_short_load(addr);
76 | AO_compiler_barrier();
77 | return result;
78 | }
79 | #define AO_HAVE_short_load_read
80 |
81 | #define AO_short_load_acquire(addr) AO_short_load_read(addr)
82 | #define AO_HAVE_short_load_acquire
83 |
84 | #endif /* AO_HAVE_short_load */
85 |
86 | #ifdef AO_HAVE_int_load
87 |
88 | AO_INLINE AO_t
89 | AO_int_load_read(const volatile unsigned int *addr)
90 | {
91 | AO_t result = AO_int_load(addr);
92 | AO_compiler_barrier();
93 | return result;
94 | }
95 | #define AO_HAVE_int_load_read
96 |
97 | #define AO_int_load_acquire(addr) AO_int_load_read(addr)
98 | #define AO_HAVE_int_load_acquire
99 |
100 | #endif /* AO_HAVE_int_load */
101 |
--------------------------------------------------------------------------------
/lib/spraylist_linden/atomic_ops/sparc.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 1991-1994 by Xerox Corporation. All rights reserved.
3 | * Copyright (c) 1996-1999 by Silicon Graphics. All rights reserved.
4 | * Copyright (c) 1999-2003 by Hewlett-Packard Company. All rights reserved.
5 | *
6 | *
7 | * THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED
8 | * OR IMPLIED. ANY USE IS AT YOUR OWN RISK.
9 | *
10 | * Permission is hereby granted to use or copy this program
11 | * for any purpose, provided the above notices are retained on all copies.
12 | * Permission to modify the code and to distribute modified code is granted,
13 | * provided the above notices are retained, and a notice that the code was
14 | * modified is included with the above copyright notice.
15 | *
16 | */
17 |
18 | /* FIXME. Very incomplete. No support for sparc64. */
19 | /* Non-ancient SPARCs provide compare-and-swap (casa). */
20 | /* We should make that available. */
21 |
22 | #include "./aligned_atomic_load_store.h"
23 |
24 | /* Real SPARC code uses TSO: */
25 | #include "./ordered_except_wr.h"
26 |
27 | /* Test_and_set location is just a byte. */
28 | #include "./test_and_set_t_is_char.h"
29 |
30 | AO_INLINE AO_TS_VAL_t
31 | AO_test_and_set_full(volatile AO_TS_t *addr) {
32 | AO_TS_VAL_t oldval;
33 |
34 | __asm__ __volatile__("ldstub %1,%0"
35 | : "=r"(oldval), "=m"(*addr)
36 | : "m"(*addr) : "memory");
37 | return oldval;
38 | }
39 |
40 | #define AO_HAVE_test_and_set_full
41 |
42 | #ifndef AO_NO_SPARC_V9
43 | /* Returns nonzero if the comparison succeeded. */
44 | AO_INLINE int
45 | AO_compare_and_swap_full(volatile AO_t *addr, AO_t old, AO_t new_val) {
46 | char ret;
47 | __asm__ __volatile__ ("membar #StoreLoad | #LoadLoad\n\t"
48 | # if defined(__arch64__)
49 | "casx [%2],%0,%1\n\t"
50 | # else
51 | "cas [%2],%0,%1\n\t" /* 32-bit version */
52 | # endif
53 | "membar #StoreLoad | #StoreStore\n\t"
54 | "cmp %0,%1\n\t"
55 | "be,a 0f\n\t"
56 | "mov 1,%0\n\t"/* one insn after branch always executed */
57 | "clr %0\n\t"
58 | "0:\n\t"
59 | : "=r" (ret), "+r" (new_val)
60 | : "r" (addr), "0" (old)
61 | : "memory", "cc");
62 | return (int)ret;
63 | }
64 |
65 | #define AO_HAVE_compare_and_swap_full
66 | #endif /* AO_NO_SPARC_V9 */
67 |
68 | /* FIXME: This needs to be extended for SPARC v8 and v9. */
69 | /* SPARC V8 also has swap. V9 has CAS. */
70 | /* There are barriers like membar #LoadStore. */
71 | /* CASA (32-bit) and CASXA(64-bit) instructions were */
72 | /* added in V9. */
73 |
--------------------------------------------------------------------------------
/lib/spraylist_linden/atomic_ops/standard_ao_double_t.h:
--------------------------------------------------------------------------------
1 | /* NEC LE-IT: For 64Bit OS we extend the double type to hold two int64's
2 | *
3 | * x86-64: __m128 serves as placeholder which also requires the compiler
4 | * to align it on 16 byte boundary (as required by cmpxchg16.
5 | * Similar things could be done for PowerPC 64bit using a VMX data type... */
6 |
7 | #if (defined(__x86_64__) && defined(__GNUC__)) || defined(_WIN64)
8 | # include
9 | typedef __m128 double_ptr_storage;
10 | #elif defined(_WIN32) && !defined(__GNUC__)
11 | typedef unsigned __int64 double_ptr_storage;
12 | #else
13 | typedef unsigned long long double_ptr_storage;
14 | #endif
15 |
16 | # define AO_HAVE_DOUBLE_PTR_STORAGE
17 |
18 | typedef union {
19 | double_ptr_storage AO_whole;
20 | struct {AO_t AO_v1; AO_t AO_v2;} AO_parts;
21 | } AO_double_t;
22 |
23 | #define AO_HAVE_double_t
24 | #define AO_val1 AO_parts.AO_v1
25 | #define AO_val2 AO_parts.AO_v2
26 |
--------------------------------------------------------------------------------
/lib/spraylist_linden/atomic_ops/test_and_set_t_is_ao_t.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2004 Hewlett-Packard Development Company, L.P.
3 | *
4 | * Permission is hereby granted, free of charge, to any person obtaining a copy
5 | * of this software and associated documentation files (the "Software"), to deal
6 | * in the Software without restriction, including without limitation the rights
7 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 | * copies of the Software, and to permit persons to whom the Software is
9 | * furnished to do so, subject to the following conditions:
10 | *
11 | * The above copyright notice and this permission notice shall be included in
12 | * all copies or substantial portions of the Software.
13 | *
14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
20 | * SOFTWARE.
21 | */
22 |
23 | /*
24 | * These are common definitions for architectures on which test_and_set
25 | * operates on pointer-sized quantities, the "clear" value contains
26 | * all zeroes, and the "set" value contains only one lowest bit set.
27 | * This can be used if test_and_set is synthesized from compare_and_swap.
28 | */
29 | typedef enum {AO_TS_clear = 0, AO_TS_set = 1} AO_TS_val;
30 | #define AO_TS_VAL_t AO_TS_val
31 | #define AO_TS_CLEAR AO_TS_clear
32 | #define AO_TS_SET AO_TS_set
33 |
34 | #define AO_TS_t AO_t
35 |
36 | #define AO_AO_TS_T 1
37 |
--------------------------------------------------------------------------------
/lib/spraylist_linden/atomic_ops/test_and_set_t_is_char.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2004 Hewlett-Packard Development Company, L.P.
3 | *
4 | * Permission is hereby granted, free of charge, to any person obtaining a copy
5 | * of this software and associated documentation files (the "Software"), to deal
6 | * in the Software without restriction, including without limitation the rights
7 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 | * copies of the Software, and to permit persons to whom the Software is
9 | * furnished to do so, subject to the following conditions:
10 | *
11 | * The above copyright notice and this permission notice shall be included in
12 | * all copies or substantial portions of the Software.
13 | *
14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
20 | * SOFTWARE.
21 | */
22 |
23 | /*
24 | * These are common definitions for architectures on which test_and_set
25 | * operates on byte sized quantities, the "clear" value contains
26 | * all zeroes, and the "set" value contains all ones.
27 | */
28 |
29 | #define AO_TS_t unsigned char
30 | typedef enum {AO_BYTE_TS_clear = 0, AO_BYTE_TS_set = 0xff} AO_BYTE_TS_val;
31 | #define AO_TS_VAL_t AO_BYTE_TS_val
32 | #define AO_TS_CLEAR AO_BYTE_TS_clear
33 | #define AO_TS_SET AO_BYTE_TS_set
34 |
35 | #define AO_CHAR_TS_T 1
36 |
37 |
38 |
39 |
--------------------------------------------------------------------------------
/lib/spraylist_linden/fraser.h:
--------------------------------------------------------------------------------
1 | /*
2 | * File:
3 | * fraser.h
4 | * Author(s):
5 | * Vincent Gramoli
6 | * Description:
7 | * Lock-based skip list implementation of the Fraser algorithm
8 | * "Practical Lock Freedom", K. Fraser,
9 | * PhD dissertation, September 2003
10 | * Cambridge University Technical Report UCAM-CL-TR-579
11 | *
12 | * Copyright (c) 2009-2010.
13 | *
14 | * fraser.h is part of Synchrobench
15 | *
16 | * Synchrobench is free software: you can redistribute it and/or
17 | * modify it under the terms of the GNU General Public License
18 | * as published by the Free Software Foundation, version 2
19 | * of the License.
20 | *
21 | * This program is distributed in the hope that it will be useful,
22 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
23 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
24 | * GNU General Public License for more details.
25 | */
26 |
27 | #ifndef FRASER_H_
28 | #define FRASER_H_
29 | #include "skiplist.h"
30 | #include "ssalloc.h"
31 |
32 | int fraser_find(sl_intset_t *set, slkey_t key, val_t *val);
33 | int fraser_remove(sl_intset_t *set, slkey_t key, val_t *val, int remove_succ);
34 | int fraser_insert(sl_intset_t *set, slkey_t key, val_t v);
35 |
36 | inline int is_marked(uintptr_t i);
37 | inline uintptr_t unset_mark(uintptr_t i);
38 | inline uintptr_t set_mark(uintptr_t i);
39 | inline void fraser_search(sl_intset_t *set, slkey_t key, sl_node_t **left_list, sl_node_t **right_list);
40 | inline void mark_node_ptrs(sl_node_t *n);
41 | #endif // FRASER_H_
42 |
--------------------------------------------------------------------------------
/lib/spraylist_linden/gc/gc.h:
--------------------------------------------------------------------------------
1 | #ifndef __GC_H__
2 | #define __GC_H__
3 |
4 | typedef struct gc_st gc_t;
5 |
6 | /* Most of these functions peek into a per-thread state struct. */
7 | #include "ptst.h"
8 |
9 | /* Initialise GC section of given per-thread state structure. */
10 | gc_t *gc_init(void);
11 |
12 | int gc_add_allocator(int alloc_size);
13 | void gc_remove_allocator(int alloc_id);
14 |
15 | /*
16 | * Memory allocate/free. An unsafe free can be used when an object was
17 | * not made visible to other processes.
18 | */
19 | void *gc_alloc(ptst_t *ptst, int alloc_id);
20 | void gc_free(ptst_t *ptst, void *p, int alloc_id);
21 | void gc_unsafe_free(ptst_t *ptst, void *p, int alloc_id);
22 |
23 | /*
24 | * Hook registry. Allows users to hook in their own per-epoch delay
25 | * lists.
26 | */
27 | typedef void (*hook_fn_t)(ptst_t *, void *);
28 | int gc_add_hook(hook_fn_t fn);
29 | void gc_remove_hook(int hook_id);
30 | void gc_add_ptr_to_hook_list(ptst_t *ptst, void *ptr, int hook_id);
31 |
32 | /* Per-thread entry/exit from critical regions */
33 | void gc_enter(ptst_t *ptst);
34 | void gc_exit(ptst_t *ptst);
35 |
36 | /* Start-of-day initialisation of garbage collector. */
37 | void _init_gc_subsystem(void);
38 | void _destroy_gc_subsystem(void);
39 |
40 | #endif /* __GC_H__ */
41 |
--------------------------------------------------------------------------------
/lib/spraylist_linden/gc/portable_defns.h:
--------------------------------------------------------------------------------
1 | #ifndef __PORTABLE_DEFNS_H__
2 | #define __PORTABLE_DEFNS_H__
3 |
4 | #define MAX_THREADS 128 /* Nobody will ever have more! */
5 |
6 | #if defined(SPARC)
7 | #include "sparc_defns.h"
8 | #elif defined(INTEL)
9 | #include "intel_defns.h"
10 | #elif defined(PPC)
11 | #include "ppc_defns.h"
12 | #elif defined(IA64)
13 | #include "ia64_defns.h"
14 | #elif defined(MIPS)
15 | #include "mips_defns.h"
16 | #elif defined(ALPHA)
17 | #include "alpha_defns.h"
18 | #else
19 | #error "A valid architecture has not been defined"
20 | #endif
21 |
22 | #include
23 |
24 | #ifndef MB_NEAR_CAS
25 | #define RMB_NEAR_CAS() RMB()
26 | #define WMB_NEAR_CAS() WMB()
27 | #define MB_NEAR_CAS() MB()
28 | #endif
29 |
30 | typedef unsigned long int_addr_t;
31 |
32 | typedef int bool_t;
33 | #define FALSE 0
34 | #define TRUE 1
35 |
36 | #define ADD_TO(_v,_x) \
37 | do { \
38 | int __val = (_v), __newval; \
39 | while ( (__newval = CASIO(&(_v),__val,__val+(_x))) != __val ) \
40 | __val = __newval; \
41 | } while ( 0 )
42 |
43 | /*
44 | * Allow us to efficiently align and pad structures so that shared fields
45 | * don't cause contention on thread-local or read-only fields.
46 | */
47 | #define CACHE_PAD(_n) char __pad ## _n [CACHE_LINE_SIZE]
48 | #define ALIGNED_ALLOC(_s) \
49 | ((void *)(((unsigned long)malloc((_s)+CACHE_LINE_SIZE*2) + \
50 | CACHE_LINE_SIZE - 1) & ~(CACHE_LINE_SIZE-1)))
51 |
52 |
53 | /*
54 | * POINTER MARKING
55 | */
56 | #define get_marked_ref(_p) ((void *)(((unsigned long)(_p)) | 1))
57 | #define get_unmarked_ref(_p) ((void *)(((unsigned long)(_p)) & ~1))
58 | #define is_marked_ref(_p) (((unsigned long)(_p)) & 1)
59 |
60 |
61 |
62 | /* Read field @_f into variable @_x. */
63 | #define READ_FIELD(_x,_f) ((_x) = (_f))
64 |
65 | #define WEAK_DEP_ORDER_RMB() ((void)0)
66 | #define WEAK_DEP_ORDER_WMB() ((void)0)
67 | #define WEAK_DEP_ORDER_MB() ((void)0)
68 |
69 |
70 |
71 | #endif /* __PORTABLE_DEFNS_H__ */
72 |
--------------------------------------------------------------------------------
/lib/spraylist_linden/gc/ptst.c:
--------------------------------------------------------------------------------
1 | /******************************************************************************
2 | * ptst.c
3 | *
4 | * Per-thread state management. Essentially the state management parts
5 | * of MB's garbage-collection code have been pulled out and placed
6 | * here, for the use of other utility routines.
7 | *
8 | * Copyright (c) 2013, Jonatan Linden
9 | * Copyright (c) 2002-2003, K A Fraser
10 | *
11 | * All rights reserved.
12 | *
13 | * Redistribution and use in source and binary forms, with or without
14 | * modification, are permitted provided that the following conditions
15 | * are met:
16 | *
17 | * * Redistributions of source code must retain the above copyright
18 | * notice, this list of conditions and the following disclaimer.
19 | *
20 | * * Redistributions in binary form must reproduce the above
21 | * copyright notice, this list of conditions and the following
22 | * disclaimer in the documentation and/or other materials provided
23 | * with the distribution.
24 | *
25 | * * The name of the author may not be used to endorse or promote
26 | * products derived from this software without specific prior
27 | * written permission.
28 | *
29 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
30 | * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
31 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
32 | * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
33 | * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
34 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
35 | * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
36 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
37 | * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
38 | * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
39 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
40 | */
41 |
42 | #include
43 | #include
44 | #include
45 | #include "random.h"
46 | #include "portable_defns.h"
47 | #include "ptst.h"
48 |
49 | ptst_t *ptst_list = NULL;
50 | extern __thread ptst_t *ptst;
51 | static unsigned int next_id = 0;
52 |
53 | void
54 | critical_enter()
55 | {
56 | ptst_t *next, *new_next;
57 |
58 | if ( ptst == NULL )
59 | {
60 | ptst = (ptst_t *) ALIGNED_ALLOC(sizeof(ptst_t));
61 | if ( ptst == NULL ) exit(1);
62 |
63 | memset(ptst, 0, sizeof(ptst_t));
64 | ptst->gc = gc_init();
65 | ptst->count = 1;
66 | ptst->id = __sync_fetch_and_add(&next_id, 1);
67 | rand_init(ptst);
68 | new_next = ptst_list;
69 | do {
70 | ptst->next = next = new_next;
71 | }
72 | while ( (new_next = __sync_val_compare_and_swap(&ptst_list, next, ptst)) != next );
73 | }
74 |
75 | gc_enter(ptst);
76 | return;
77 | }
78 |
79 |
80 |
81 | static void ptst_destructor(ptst_t *ptst)
82 | {
83 | ptst->count = 0;
84 | }
85 |
86 |
87 |
--------------------------------------------------------------------------------
/lib/spraylist_linden/gc/ptst.h:
--------------------------------------------------------------------------------
1 | /******************************************************************************
2 | * ptst.h
3 | *
4 | * Per-thread state management.
5 | *
6 | *
7 | * Copyright (c) 2013, Jonatan Linden
8 | * Copyright (c) 2002-2003, K A Fraser
9 | */
10 |
11 | #ifndef __PTST_H__
12 | #define __PTST_H__
13 |
14 | typedef struct ptst_st ptst_t;
15 |
16 | #include
17 |
18 | #include "gc.h"
19 |
20 | struct ptst_st
21 | {
22 | /* Thread id */
23 | unsigned int id;
24 | /* State management */
25 | ptst_t *next;
26 | unsigned int count;
27 |
28 | /* Utility structures */
29 | gc_t *gc;
30 | char pad[56];
31 | unsigned int rand;
32 | };
33 |
34 | /*
35 | * Enter/leave a critical region. A thread gets a state handle for
36 | * use during critical regions.
37 | */
38 |
39 | void critical_enter(void );
40 |
41 | #define critical_exit() gc_exit(ptst)
42 |
43 | /* Iterators */
44 | extern ptst_t *ptst_list;
45 |
46 | #define ptst_first() (ptst_list)
47 | #define ptst_next(_p) ((_p)->next)
48 |
49 |
50 |
51 | #endif /* __PTST_H__ */
52 |
53 |
54 |
55 |
--------------------------------------------------------------------------------
/lib/spraylist_linden/gc/random.h:
--------------------------------------------------------------------------------
1 | /******************************************************************************
2 | * random.h
3 | *
4 | * A really simple random-number generator. Crappy linear congruential
5 | * taken from glibc, but has at least a 2^32 period.
6 | */
7 |
8 | #ifndef __RANDOM_H__
9 | #define __RANDOM_H__
10 |
11 | typedef unsigned long rand_t;
12 |
13 | #define rand_init(_ptst) \
14 | ((_ptst)->rand = RDTICK())
15 |
16 | #define rand_next(_ptst) \
17 | ((_ptst)->rand = ((_ptst)->rand * 1103515245) + 12345)
18 |
19 | #endif /* __RANDOM_H__ */
20 |
--------------------------------------------------------------------------------
/lib/spraylist_linden/include/getticks.h:
--------------------------------------------------------------------------------
1 | #ifndef _H_GETTICKS_
2 | #define _H_GETTICKS_
3 |
4 | #include
5 | typedef uint64_t ticks;
6 |
7 | #if defined(__i386__)
8 | static inline ticks
9 | getticks(void)
10 | {
11 | ticks ret;
12 |
13 | __asm__ __volatile__("rdtsc" : "=A" (ret));
14 | return ret;
15 | }
16 | #elif defined(__x86_64__)
17 | static inline ticks
18 | getticks(void)
19 | {
20 | unsigned hi, lo;
21 | __asm__ __volatile__ ("rdtsc" : "=a"(lo), "=d"(hi));
22 | return ( (unsigned long long)lo)|( ((unsigned long long)hi)<<32 );
23 | }
24 | #elif defined(__sparc__)
25 | static inline ticks
26 | getticks()
27 | {
28 | ticks ret = 0;
29 | __asm__ __volatile__ ("rd %%tick, %0" : "=r" (ret) : "0" (ret));
30 | return ret;
31 | }
32 | #elif defined(__tile__)
33 | # include
34 | static inline ticks
35 | getticks()
36 | {
37 | return get_cycle_count();
38 | }
39 | #endif
40 |
41 | #endif
42 |
--------------------------------------------------------------------------------
/lib/spraylist_linden/include/lockfree.h:
--------------------------------------------------------------------------------
1 |
2 | # define NL 1
3 | # define EL 0
4 | # define TX_START(type) /* nothing */
5 | # define TX_LOAD(addr) (*(addr))
6 | # define TX_STORE(addr, val) (*(addr) = (val))
7 | # define TX_END /* nothing */
8 | # define FREE(addr, size) free(addr)
9 | # define MALLOC(size) malloc(size)
10 | # define TM_CALLABLE /* nothing */
11 | # define TM_ARGDECL_ALONE /* nothing */
12 | # define TM_ARGDECL /* nothing */
13 | # define TM_ARG /* nothing */
14 | # define TM_ARG_ALONE /* nothing */
15 | # define TM_ARG_LAST /* nothing */
16 | # define TM_STARTUP() /* nothing */
17 | # define TM_SHUTDOWN() /* nothing */
18 | # define TM_STARTUP() /* nothing */
19 | # define TM_SHUTDOWN() /* nothing */
20 | #include "utils.h"
21 | # define TM_THREAD_ENTER(id) /* nothing */
22 | # define TM_THREAD_EXIT() /* nothing */
23 |
--------------------------------------------------------------------------------
/lib/spraylist_linden/include/random.h:
--------------------------------------------------------------------------------
1 | #ifndef _H_RANDOM_
2 | #define _H_RANDOM_
3 |
4 | #include
5 | #include "measurements.h"
6 | #include "ssalloc.h"
7 |
8 | #define LOCAL_RAND
9 |
10 | #if defined(LOCAL_RAND)
11 | extern __thread unsigned long* seeds;
12 | #endif
13 |
14 | #define my_random xorshf96
15 |
16 | //fast but weak random number generator for the sparc machine
17 | static inline uint32_t
18 | fast_rand()
19 | {
20 | return ((getticks()&4294967295UL)>>4);
21 | }
22 |
23 |
24 | static inline unsigned long*
25 | seed_rand()
26 | {
27 | unsigned long* seeds;
28 | /* seeds = (unsigned long*) malloc(3 * sizeof(unsigned long)); */
29 | seeds = (unsigned long*) ssalloc(3 * sizeof(unsigned long));
30 | /* seeds = (unsigned long*) memalign(64, 64); */
31 | seeds[0] = getticks() % 123456789;
32 | seeds[1] = getticks() % 362436069;
33 | seeds[2] = getticks() % 521288629;
34 | return seeds;
35 | }
36 |
37 | //Marsaglia's xorshf generator
38 | static inline unsigned long
39 | xorshf96(unsigned long* x, unsigned long* y, unsigned long* z) //period 2^96-1
40 | {
41 | unsigned long t;
42 | (*x) ^= (*x) << 16;
43 | (*x) ^= (*x) >> 5;
44 | (*x) ^= (*x) << 1;
45 |
46 | t = *x;
47 | (*x) = *y;
48 | (*y) = *z;
49 | (*z) = t ^ (*x) ^ (*y);
50 |
51 | return *z;
52 | }
53 |
54 | static inline long
55 | rand_range(long r)
56 | {
57 | /* PF_START(0); */
58 | #if defined(LOCAL_RAND)
59 | long v = xorshf96(seeds, seeds + 1, seeds + 2) % r;
60 | v++;
61 | #else
62 | int m = RAND_MAX;
63 | long d, v = 0;
64 |
65 | do {
66 | d = (m > r ? r : m);
67 | v += 1 + (long)(d * ((double)rand()/((double)(m)+1.0)));
68 | r -= m;
69 | } while (r > 0);
70 | #endif
71 | /* PF_STOP(0); */
72 | return v;
73 | }
74 |
75 | /* Re-entrant version of rand_range(r) */
76 | static inline long
77 | rand_range_re(unsigned int *seed, long r)
78 | {
79 | /* PF_START(0); */
80 | #if defined(LOCAL_RAND)
81 | long v = xorshf96(seeds, seeds + 1, seeds + 2) % r;
82 | v++;
83 | #else
84 | int m = RAND_MAX;
85 | long d, v = 0;
86 |
87 | do {
88 | d = (m > r ? r : m);
89 | v += 1 + (long)(d * ((double)rand_r(seed)/((double)(m)+1.0)));
90 | r -= m;
91 | } while (r > 0);
92 | #endif
93 | /* PF_STOP(0); */
94 | return v;
95 | }
96 |
97 |
98 | #endif
99 |
--------------------------------------------------------------------------------
/lib/spraylist_linden/include/sequential.h:
--------------------------------------------------------------------------------
1 |
2 | # define NL 1
3 | # define EL 0
4 | # define TX_START(type) /* nothing */
5 | # define TX_LOAD(addr) (*(addr))
6 | # define TX_STORE(addr, val) (*(addr) = (val))
7 | # define TX_END /* nothing */
8 | # define FREE(addr, size) free(addr)
9 | # define MALLOC(size) malloc(size)
10 | # define TM_CALLABLE /* nothing */
11 | # define TM_ARGDECL_ALONE /* nothing */
12 | # define TM_ARGDECL /* nothing */
13 | # define TM_ARG /* nothing */
14 | # define TM_ARG_ALONE /* nothing */
15 | # define TM_ARG_LAST /* nothing */
16 | # define TM_STARTUP() /* nothing */
17 | # define TM_SHUTDOWN() /* nothing */
18 | # define TM_STARTUP() /* nothing */
19 | # define TM_SHUTDOWN() /* nothing */
20 | # define TM_THREAD_ENTER() /* nothing */
21 | # define TM_THREAD_EXIT() /* nothing */
22 |
--------------------------------------------------------------------------------
/lib/spraylist_linden/include/ssalloc.h:
--------------------------------------------------------------------------------
1 | #ifndef SSALLOC_H
2 | #define SSALLOC_H
3 |
4 | #include
5 | #include
6 | #include
7 | #include
8 | #include
9 | #include
10 | #include
11 | #include
12 | #include
13 | #include
14 | #include
15 | #include
16 | #include
17 |
18 | /* #define SSALLOC_USE_MALLOC */
19 |
20 | #define SSALLOC_NUM_ALLOCATORS 2
21 |
22 | #undef LAPTOP
23 |
24 | #if defined(__sparc__)
25 | # define SSALLOC_SIZE (128 * 1024 * 1024)
26 | #elif defined(__tile__)
27 | # define SSALLOC_SIZE (100 * 1024 * 1024)
28 | #elif defined(LAPTOP)
29 | # define SSALLOC_SIZE (100 * 1024 * 1024)
30 | #else
31 | # define SSALLOC_SIZE (1024 * 1024 * 1024)
32 | #endif
33 | #define SSALLOC_SIZE_ALL (size_t)((size_t)10 * (size_t)1024 * (size_t)1024 * (size_t)1024)
34 |
35 | /* extern const size_t ssalloc_size_alloc[SSALLOC_NUM_ALLOCATORS]; */
36 | #define LAPTOP
37 |
38 | void ssalloc_set(void* mem);
39 | void ssalloc_init(int number_of_threads);
40 | void ssalloc_align();
41 | void ssalloc_align_alloc(unsigned int allocator);
42 | void ssalloc_offset(size_t size);
43 | void* ssalloc_alloc(unsigned int allocator, size_t size);
44 | void ssfree_alloc(unsigned int allocator, void* ptr);
45 | void* ssalloc(size_t size);
46 | void ssfree(void* ptr);
47 |
48 | #endif
49 |
--------------------------------------------------------------------------------
/lib/spraylist_linden/include/ssalloc.h~:
--------------------------------------------------------------------------------
1 | #ifndef SSALLOC_H
2 | #define SSALLOC_H
3 |
4 | #include
5 | #include
6 | #include
7 | #include
8 | #include
9 | #include
10 | #include
11 | #include
12 | #include
13 | #include
14 | #include
15 | #include
16 | #include
17 |
18 | /* #define SSALLOC_USE_MALLOC */
19 |
20 | #define SSALLOC_NUM_ALLOCATORS 2
21 |
22 | #if defined(__sparc__)
23 | # define SSALLOC_SIZE (128 * 1024 * 1024)
24 | #elif defined(__tile__)
25 | # define SSALLOC_SIZE (100 * 1024 * 1024)
26 | #elif defined(LAPTOP)
27 | # define SSALLOC_SIZE (100 * 1024 * 1024)
28 | #else
29 | # define SSALLOC_SIZE (1024 * 1024 * 1024)
30 | #endif
31 | #define SSALLOC_SIZE_ALL (size_t)((size_t)8 * (size_t)1024 * (size_t)1024 * (size_t)1024)
32 |
33 | /* extern const size_t ssalloc_size_alloc[SSALLOC_NUM_ALLOCATORS]; */
34 |
35 |
36 | void ssalloc_set(void* mem);
37 | void ssalloc_init();
38 | void ssalloc_align();
39 | void ssalloc_align_alloc(unsigned int allocator);
40 | void ssalloc_offset(size_t size);
41 | void* ssalloc_alloc(unsigned int allocator, size_t size);
42 | void ssfree_alloc(unsigned int allocator, void* ptr);
43 | void* ssalloc(size_t size);
44 | void ssfree(void* ptr);
45 |
46 | #endif
47 |
--------------------------------------------------------------------------------
/lib/spraylist_linden/include/tm.h:
--------------------------------------------------------------------------------
1 |
2 | #ifdef ESTM
3 | # include "estm.h"
4 | #elif defined(TINY100) || defined(TINY10B) || defined(TINY099) || defined(TINY098)
5 | # include "tinystm.h"
6 | #elif defined WPLDSTM
7 | # include "wlpdstm.h"
8 | #elif defined LOCKFREE
9 | # include "lockfree.h"
10 | #elif defined TL2
11 | # include "tl2-mbench.h"
12 | #elif defined ICC
13 | # include "icc.h"
14 | #elif defined SEQUENTIAL
15 | # include "sequential.h"
16 | #endif
17 |
--------------------------------------------------------------------------------
/lib/spraylist_linden/intset.c:
--------------------------------------------------------------------------------
1 | /*
2 | * File:
3 | * intset.c
4 | * Author(s):
5 | * Vincent Gramoli
6 | * Description:
7 | * Skip list integer set operations
8 | *
9 | * Copyright (c) 2009-2010.
10 | *
11 | * intset.c is part of Synchrobench
12 | *
13 | * Synchrobench is free software: you can redistribute it and/or
14 | * modify it under the terms of the GNU General Public License
15 | * as published by the Free Software Foundation, version 2
16 | * of the License.
17 | *
18 | * This program is distributed in the hope that it will be useful,
19 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 | * GNU General Public License for more details.
22 | */
23 |
24 | #include "intset.h"
25 |
26 | #define MAXLEVEL 32
27 |
28 | int sl_contains(sl_intset_t *set, slkey_t key, int transactional)
29 | {
30 | val_t val;
31 | return sl_contains_val(set, key, &val, transactional);
32 | }
33 |
34 | int sl_contains_val(sl_intset_t *set, slkey_t key, val_t *val, int transactional)
35 | {
36 | return fraser_find(set, key, val);
37 | }
38 |
39 | int sl_add(sl_intset_t *set, slkey_t key, int transactional)
40 | {
41 | return sl_add_val(set, key, (val_t) key, transactional);
42 | }
43 |
44 | int sl_add_val(sl_intset_t *set, slkey_t key, val_t val, int transactional)
45 | {
46 | return fraser_insert(set, key, val);
47 | }
48 |
49 | int sl_remove(sl_intset_t *set, slkey_t key, int transactional)
50 | {
51 | val_t val;
52 | return sl_remove_val(set, key, &val, transactional);
53 | }
54 |
55 | int sl_remove_val(sl_intset_t *set, slkey_t key, val_t *val, int transactional)
56 | {
57 | return fraser_remove(set, key, val, 0);
58 | }
59 |
60 | int sl_remove_succ(sl_intset_t *set, slkey_t key, int transactional)
61 | {
62 | val_t val;
63 | return sl_remove_succ_val(set, key, &val, transactional);
64 | }
65 |
66 | int sl_remove_succ_val(sl_intset_t *set, slkey_t key, val_t *val, int transactional)
67 | {
68 | return fraser_remove(set, key, val, 1);
69 | }
70 |
--------------------------------------------------------------------------------
/lib/spraylist_linden/intset.h:
--------------------------------------------------------------------------------
1 | /*
2 | * File:
3 | * intset.h
4 | * Author(s):
5 | * Vincent Gramoli
6 | * Description:
7 | * Skip list integer set operations
8 | *
9 | * Copyright (c) 2009-2010.
10 | *
11 | * intset.h is part of Synchrobench
12 | *
13 | * Synchrobench is free software: you can redistribute it and/or
14 | * modify it under the terms of the GNU General Public License
15 | * as published by the Free Software Foundation, version 2
16 | * of the License.
17 | *
18 | * This program is distributed in the hope that it will be useful,
19 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 | * GNU General Public License for more details.
22 | */
23 |
24 | #include "fraser.h"
25 | #include "linden.h"
26 |
27 | int sl_contains(sl_intset_t *set, slkey_t key, int transactional);
28 | int sl_contains_val(sl_intset_t *set, slkey_t key, val_t *val, int transactional);
29 | int sl_add(sl_intset_t *set, slkey_t key, int transactional);
30 | int sl_add_val(sl_intset_t *set, slkey_t key, val_t val, int transactional);
31 | int sl_remove(sl_intset_t *set, slkey_t key, int transactional);
32 | int sl_remove_val(sl_intset_t *set, slkey_t key, val_t *val, int transactional);
33 | int sl_remove_succ(sl_intset_t *set, slkey_t key, int transactional);
34 | int sl_remove_succ_val(sl_intset_t *set, slkey_t key, val_t *val, int transactional);
35 |
36 | // priority queue
37 | int lotan_shavit_delete_min_key(sl_intset_t *set, slkey_t *key, val_t *val, thread_data_t *d);
38 | int lotan_shavit_delete_min(sl_intset_t *set, val_t *val, thread_data_t *d);
39 | int spray_delete_min_key(sl_intset_t *set, slkey_t *key, val_t *val, thread_data_t *d);
40 | int spray_delete_min(sl_intset_t *set, val_t *val, thread_data_t *d);
41 |
--------------------------------------------------------------------------------
/lib/spraylist_linden/linden.h:
--------------------------------------------------------------------------------
1 | #ifndef PRIOQ_H
2 | #define PRIOQ_H
3 |
4 | #include "linden_common.h"
5 |
6 | typedef unsigned long pkey_t;
7 | typedef unsigned long pval_t;
8 |
9 | #define KEY_NULL 0
10 | #define NUM_LEVELS 32
11 | /* Internal key values with special meanings. */
12 | #define SENTINEL_KEYMIN ( 0UL) /* Key value of first dummy node. */
13 | #define SENTINEL_KEYMAX (~1UL) /* Key value of last dummy node. */
14 |
15 |
16 | typedef struct node_s
17 | {
18 | pkey_t k;
19 | int level;
20 | int inserting; //char pad2[4];
21 | pval_t v;
22 | struct node_s *next[1];
23 | } node_t;
24 |
25 | typedef struct
26 | {
27 | int max_offset;
28 | int max_level;
29 | int nthreads;
30 | node_t *head;
31 | node_t *tail;
32 | char pad[128];
33 | } pq_t;
34 |
35 | typedef ALIGNED(64) struct thread_data {
36 | val_t first;
37 | long range;
38 | int update;
39 | int unit_tx;
40 | int alternate;
41 | int randomized;
42 | int pq;
43 | int sl;
44 | int es;
45 | int effective;
46 | int first_remove;
47 | unsigned long nb_collisions;
48 | unsigned long nb_clean;
49 | unsigned long nb_add;
50 | unsigned long nb_added;
51 | unsigned long nb_remove;
52 | unsigned long nb_removed;
53 | unsigned long nb_contains;
54 | unsigned long nb_found;
55 | unsigned long nb_aborts;
56 | unsigned long nb_aborts_locked_read;
57 | unsigned long nb_aborts_locked_write;
58 | unsigned long nb_aborts_validate_read;
59 | unsigned long nb_aborts_validate_write;
60 | unsigned long nb_aborts_validate_commit;
61 | unsigned long nb_aborts_invalid_memory;
62 | unsigned long nb_aborts_double_write;
63 | unsigned long max_retries;
64 | unsigned int nb_threads;
65 | unsigned int seed;
66 | unsigned int seed2;
67 | sl_intset_t *set;
68 | barrier_t *barrier;
69 | unsigned long failures_because_contention;
70 | int id;
71 |
72 | /* LINDEN */
73 | int lin;
74 | pq_t *linden_set;
75 | } thread_data_t;
76 |
77 |
78 | #define get_marked_ref(_p) ((void *)(((uintptr_t)(_p)) | 1))
79 | #define get_unmarked_ref(_p) ((void *)(((uintptr_t)(_p)) & ~1))
80 | #define is_marked_ref(_p) (((uintptr_t)(_p)) & 1)
81 |
82 |
83 | /* Interface */
84 |
85 | extern pq_t *pq_init(int max_offset);
86 |
87 | extern void pq_destroy(pq_t *pq);
88 |
89 | extern int insert(pq_t *pq, pkey_t k, pval_t v);
90 |
91 | extern pval_t deletemin(pq_t *pq/*, thread_data_t *d*/);
92 |
93 | extern pval_t deletemin_key(pq_t *pq, pkey_t *key/*, thread_data_t *d*/);
94 |
95 | extern void sequential_length(pq_t *pq);
96 |
97 | extern int empty(pq_t *pq);
98 |
99 | #endif // PRIOQ_H
100 |
--------------------------------------------------------------------------------
/lib/spraylist_linden/linden_common.c:
--------------------------------------------------------------------------------
1 | #define _GNU_SOURCE
2 | #include "linden_common.h"
3 |
4 | #if defined(__linux__)
5 | pid_t
6 | gettid(void)
7 | {
8 | return (pid_t) syscall(SYS_gettid);
9 | }
10 |
11 | #ifdef LINDEN_PIN // defined in test.c
12 | void
13 | pin(pid_t t, int cpu)
14 | {
15 | cpu_set_t cpuset;
16 | CPU_ZERO(&cpuset);
17 | CPU_SET(cpu, &cpuset);
18 | E_en(sched_setaffinity(t, sizeof(cpu_set_t), &cpuset));
19 | }
20 | #endif // PIN
21 |
22 | void
23 | gettime(struct timespec *ts)
24 | {
25 | E(clock_gettime(CLOCK_MONOTONIC, ts));
26 | }
27 |
28 | #endif
29 |
30 | #if defined(__APPLE__)
31 | void
32 | gettime(struct timespec *ts)
33 | {
34 | uint64_t time = mach_absolute_time();
35 |
36 | static mach_timebase_info_data_t info = {0,0};
37 |
38 | if (info.denom == 0) {
39 | mach_timebase_info(&info);
40 | }
41 |
42 | uint64_t elapsed = time * (info.numer / info.denom);
43 |
44 | ts->tv_sec = elapsed * 1e-9;
45 | ts->tv_nsec = elapsed - (ts->tv_sec * 1e9);
46 | }
47 | #endif
48 |
49 |
50 |
51 |
52 | struct timespec
53 | timediff (struct timespec begin, struct timespec end)
54 | {
55 | struct timespec tmp;
56 | if ((end.tv_nsec - begin.tv_nsec) < 0) {
57 | tmp.tv_sec = end.tv_sec - begin.tv_sec - 1;
58 | tmp.tv_nsec = 1000000000 + end.tv_nsec - begin.tv_nsec;
59 | } else {
60 | tmp.tv_sec = end.tv_sec - begin.tv_sec;
61 | tmp.tv_nsec = end.tv_nsec - begin.tv_nsec;
62 | }
63 | return tmp;
64 | }
65 |
--------------------------------------------------------------------------------
/lib/spraylist_linden/linden_common.h:
--------------------------------------------------------------------------------
1 | #ifndef COMMON_H
2 | #define COMMON_H
3 | #define _GNU_SOURCE
4 | #include
5 | #include
6 | #include
7 | #include
8 | #include
9 | #include
10 | #include
11 | #include
12 | #include
13 | #include "fraser.h"
14 |
15 | #if defined(__linux__)
16 | #include
17 | #include
18 | #include
19 | #endif
20 |
21 | #if defined(__APPLE__)
22 | #include
23 | #endif
24 |
25 |
26 |
27 | #define DCL_ALIGN __attribute__((aligned (2*CACHE_LINE_SIZE)))
28 | #define CACHELINE __attribute__((aligned (1*CACHE_LINE_SIZE)))
29 |
30 | #define ATPAGESIZE __attribute__((aligned (PAGESIZE)))
31 |
32 | #define SQR(x) (x)*(x)
33 |
34 | #define max(a,b) \
35 | ({ __typeof__ (a) _a = (a); \
36 | __typeof__ (b) _b = (b); \
37 | _a > _b ? _a : _b; })
38 |
39 | #define min(a,b) \
40 | ({ __typeof__ (a) _a = (a); \
41 | __typeof__ (b) _b = (b); \
42 | _a < _b ? _a : _b; })
43 |
44 | typedef struct barrier {
45 | pthread_cond_t complete;
46 | pthread_mutex_t mutex;
47 | int count;
48 | int crossing;
49 | } barrier_t;
50 |
51 |
52 | typedef struct thread_args_s
53 | {
54 | pthread_t thread;
55 | int id;
56 | gsl_rng *rng;
57 | int measure;
58 | int cycles;
59 | char pad[128];
60 | } thread_args_t;
61 |
62 |
63 | #define E(c) \
64 | do { \
65 | int _c = (c); \
66 | if (_c < 0) { \
67 | fprintf(stderr, "E: %s: %d: %s\n", \
68 | __FILE__, __LINE__, #c); \
69 | } \
70 | } while (0)
71 |
72 | #define E_en(c) \
73 | do { \
74 | int _c = (c); \
75 | if (_c != 0) { \
76 | fprintf(stderr, strerror(_c)); \
77 | } \
78 | } while (0)
79 |
80 | #define E_NULL(c) \
81 | do { \
82 | if ((c) == NULL) { \
83 | perror("E_NULL"); \
84 | } \
85 | } while (0)
86 |
87 |
88 | #if defined(__x86_64__)
89 | /* accurate time measurements on late recent cpus */
90 | static inline uint64_t __attribute__((always_inline))
91 | read_tsc_p()
92 | {
93 | uint64_t tsc;
94 | __asm__ __volatile__ ("rdtscp\n"
95 | "shl $32, %%rdx\n"
96 | "or %%rdx, %%rax"
97 | : "=a"(tsc)
98 | :
99 | : "%rcx", "%rdx");
100 | return tsc;
101 | }
102 |
103 | #define IMB() __asm__ __volatile__("mfence":::"memory")
104 | #define IRMB() __asm__ __volatile__("lfence":::"memory")
105 | #define IWMB() __asm__ __volatile__("sfence":::"memory")
106 |
107 | #else
108 | #error Unsupported architecture
109 | #endif // __x86_64__
110 |
111 |
112 | #if defined(__linux__)
113 | extern pid_t gettid(void);
114 | #ifdef LINDEN_PIN
115 | extern void pin(pid_t t, int cpu);
116 | #endif
117 | #endif
118 |
119 | extern void gettime(struct timespec *t);
120 | extern struct timespec timediff(struct timespec, struct timespec);
121 |
122 |
123 | #endif
124 |
125 |
--------------------------------------------------------------------------------
/lib/spraylist_linden/pqueue.h:
--------------------------------------------------------------------------------
1 | #include "fraser.h"
2 | /*
3 | int pq_delete_min(sl_intset_t *set, val_t *val, int n, int *seed);
4 | int lotan_shavit_delete_min(sl_intset_t *set, val_t *val);
5 | int spray_delete_min(sl_intset_t *set, val_t *val, int n, int *seed);
6 | */
7 |
--------------------------------------------------------------------------------
/lib/spraylist_linden/skiplist.h:
--------------------------------------------------------------------------------
1 | /*
2 | * File:
3 | * skiplist.h
4 | * Author(s):
5 | * Vincent Gramoli
6 | * Description:
7 | * Stress test of the skip list implementation.
8 | *
9 | * Copyright (c) 2009-2010.
10 | *
11 | * skiplist.h is part of Synchrobench
12 | *
13 | * Synchrobench is free software: you can redistribute it and/or
14 | * modify it under the terms of the GNU General Public License
15 | * as published by the Free Software Foundation, version 2
16 | * of the License.
17 | *
18 | * This program is distributed in the hope that it will be useful,
19 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 | * GNU General Public License for more details.
22 | */
23 |
24 | #include
25 | #include
26 | #include
27 | #include
28 | #include
29 | #include
30 | #include
31 | #include
32 | #include
33 | #include
34 |
35 | #include
36 | #include "atomic_ops_if.h"
37 |
38 | #include "tm.h"
39 | #include "ssalloc.h"
40 | #include "utils.h"
41 |
42 | #define DEFAULT_DURATION 1000
43 | #define DEFAULT_INITIAL 1024
44 | #define DEFAULT_NB_THREADS 1
45 | #define DEFAULT_RANGE (2 * DEFAULT_INITIAL)
46 | #define DEFAULT_SEED 1
47 | #define DEFAULT_UPDATE 20
48 | #define DEFAULT_ELASTICITY 4
49 | #define DEFAULT_ALTERNATE 0
50 | #define DEFAULT_PQ 0
51 | #define DEFAULT_SL 0
52 | #define DEFAULT_ES 0
53 | #define DEFAULT_LIN 0
54 | #define DEFAULT_EFFECTIVE 1
55 |
56 | #define XSTR(s) STR(s)
57 | #define STR(s) #s
58 |
59 | extern uint8_t levelmax[64];
60 |
61 | #define TRANSACTIONAL 4 // TODO: get rid of this
62 |
63 | typedef unsigned long slkey_t;
64 | typedef unsigned long val_t;
65 | typedef intptr_t level_t;
66 | #define KEY_MIN 0
67 | #define KEY_MAX UINT32_MAX
68 | #define DEFAULT_VAL 0
69 |
70 | typedef ALIGNED(64) struct sl_node
71 | {
72 | slkey_t key;
73 | val_t val;
74 |
75 | int toplevel;
76 | intptr_t deleted;
77 | struct sl_node *next[19];
78 | } sl_node_t;
79 |
80 | typedef ALIGNED(64) struct sl_intset
81 | {
82 | sl_node_t *head;
83 | } sl_intset_t;
84 |
85 | int get_rand_level();
86 | int floor_log_2(unsigned int n);
87 |
88 | sl_node_t *sl_new_simple_node(slkey_t key, int toplevel, int transactional);
89 | sl_node_t *sl_new_simple_node_val(slkey_t key, val_t val, int toplevel, int transactional);
90 | sl_node_t *sl_new_node_val(slkey_t key, val_t val, sl_node_t *next, int toplevel, int transactional);
91 | sl_node_t *sl_new_node(slkey_t key, sl_node_t *next, int toplevel, int transactional);
92 | void sl_delete_node(sl_node_t *n);
93 |
94 | sl_intset_t *sl_set_new();
95 | void sl_set_delete(sl_intset_t *set);
96 | int sl_set_size(sl_intset_t *set);
97 |
98 | inline long rand_range(long r); /* declared in test.c */
99 |
--------------------------------------------------------------------------------
/misc/gpl_header:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2014 Jakob Gruber
3 | *
4 | * This file is part of kpqueue.
5 | *
6 | * kpqueue is free software: you can redistribute it and/or modify
7 | * it under the terms of the GNU General Public License as published by
8 | * the Free Software Foundation, either version 3 of the License, or
9 | * (at your option) any later version.
10 | *
11 | * kpqueue is distributed in the hope that it will be useful,
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | * GNU General Public License for more details.
15 | *
16 | * You should have received a copy of the GNU General Public License
17 | * along with kpqueue. If not, see .
18 | */
19 |
20 |
--------------------------------------------------------------------------------
/misc/plot_quality.R:
--------------------------------------------------------------------------------
1 | library(Rmisc)
2 | library(ggplot2)
3 | library(plyr)
4 | library(scales)
5 |
6 | pqplot <- function(infile, outfile) {
7 | # install.packages(c("Rmisc", "ggplot2", "plyr"))
8 |
9 | df <- read.csv(infile, header = FALSE)
10 | colnames(df) <- c("kernel", "p", "mean", "max", "stddev")
11 |
12 | df$upper <- df$mean + df$stddev
13 | df$lower <- df$mean - df$stddev
14 |
15 | p <- ggplot(df, aes(x = p, y = mean, color = kernel, shape = kernel)) +
16 | geom_line() +
17 | geom_point(size = 4) +
18 | geom_errorbar(aes(ymin = lower, ymax = upper), width = 0.4) +
19 | ylab("rank") +
20 | xlab("number of threads") +
21 | theme_bw() +
22 | theme(axis.text = element_text(size = 16),
23 | axis.title = element_text(size = 18),
24 | legend.text = element_text(size = 16),
25 | legend.title = element_text(size = 18),
26 | legend.position = c(1, 1),
27 | legend.justification = c(1, 1),
28 | legend.background = element_rect(fill = alpha("black", 0)))
29 |
30 | png(filename = outfile, width = 1024, height = 768)
31 | plot(p)
32 | invisible(dev.off())
33 | }
34 |
35 | args <- commandArgs(trailingOnly = TRUE)
36 | if (length(args) == 0) {
37 | infile <- file("stdin")
38 | outfile <- "stdin.png"
39 | } else if (length(args) == 1) {
40 | infile <- args[1]
41 | outfile <- paste(basename(args[1]), ".png", sep = "")
42 | } else {
43 | stop("USAGE: Rscript plot_quality.R [filename]")
44 | }
45 |
46 | pqplot(infile, outfile)
47 |
--------------------------------------------------------------------------------
/misc/plot_throughput.R:
--------------------------------------------------------------------------------
1 | library(Rmisc)
2 | library(ggplot2)
3 | library(plyr)
4 | library(scales)
5 |
6 | pqplot <- function(infile, outfile) {
7 | # install.packages(c("Rmisc", "ggplot2", "plyr"))
8 |
9 | df <- read.csv(infile, header = FALSE)
10 | colnames(df) <- c("kernel", "p", "throughput")
11 |
12 | df$throughput <- df$throughput/1E6
13 |
14 | df2 <- ddply(df, .(kernel, p), summarize, mean = mean(throughput),
15 | lower = CI(throughput)[[3]], upper = CI(throughput)[[1]])
16 |
17 | # Bar graph
18 |
19 | # dodge <- position_dodge(width=0.9)
20 | # p <- ggplot(df2, aes(x = factor(p), y = mean, fill = factor(kernel))) +
21 | # geom_bar(stat = "identity", position = dodge) +
22 | # geom_errorbar(aes(ymin = lower, ymax = upper), position = dodge, width = 0.3) +
23 | # ylab("throughput [Mops/s]") +
24 | # xlab("number of threads")
25 |
26 | p <- ggplot(df2, aes(x = p, y = mean, color = kernel, shape = kernel)) +
27 | geom_line() +
28 | geom_point(size = 4) +
29 | geom_errorbar(aes(ymin = lower, ymax = upper), width = 0.3) +
30 | ylab("throughput in Mops/s") +
31 | xlab("number of threads") +
32 | # Themes
33 | theme_bw() +
34 | theme(axis.text = element_text(size = 16),
35 | axis.title = element_text(size = 18),
36 | legend.text = element_text(size = 16),
37 | legend.title = element_text(size = 18),
38 | legend.position = c(1, 1),
39 | legend.justification = c(1, 1),
40 | legend.background = element_rect(fill = alpha("black", 0)))
41 |
42 | png(filename = outfile, width = 1024, height = 768)
43 | plot(p)
44 | invisible(dev.off())
45 | }
46 |
47 | args <- commandArgs(trailingOnly = TRUE)
48 | if (length(args) == 0) {
49 | infile <- file("stdin")
50 | outfile <- "stdin.png"
51 | } else if (length(args) == 1) {
52 | infile <- args[1]
53 | outfile <- paste(basename(args[1]), ".png", sep = "")
54 | } else {
55 | stop("USAGE: Rscript plot_throughput.R [filename]")
56 | }
57 |
58 | pqplot(infile, outfile)
59 |
--------------------------------------------------------------------------------
/misc/pre-commit:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | #
3 | # Check that the code follows a consistant code style
4 | #
5 |
6 | # Check for existence of astyle, and error out if not present.
7 | if [ ! -x $(which astyle) ]; then
8 | echo "git pre-commit hook:"
9 | echo "Did not find astyle, please install it before continuing."
10 | exit 1
11 | fi
12 |
13 | ASTYLE_PARAMETERS="--style=kr -p -H -U -W3 -k3 -c -s -j -xC100 -z2"
14 | FILE_PATTERN="\.(c|cpp|h)$"
15 | IGNORE_PATTERN="^doc/"
16 |
17 | ERRCOUNT=0
18 | for file in `git diff-index --cached --name-only HEAD --diff-filter=ACMR | egrep $FILE_PATTERN | egrep -v $IGNORE_PATTERN`; do
19 | # nf is the temporary checkout. This makes sure we check against the
20 | # revision in the index (and not the checked out version).
21 | nf=`git checkout-index --temp ${file} | cut -f 1`
22 | newfile=`mktemp /tmp/${nf}.XXXXXX` || exit 1
23 | astyle ${ASTYLE_PARAMETERS} < $nf > $newfile 2>> /dev/null
24 | head -c -1 "${newfile}" | diff -u -p "${nf}" -
25 | r=$?
26 | rm "${newfile}"
27 | rm "${nf}"
28 | if [ $r != 0 ] ; then
29 | echo "================================================================================================="
30 | echo " Code style error in: $file "
31 | echo " astyle ${ASTYLE_PARAMETERS} -n $file"
32 | ((ERRCOUNT++))
33 | fi
34 | done
35 |
36 | if [ $ERRCOUNT -gt 0 ]; then
37 | exit 1
38 | fi
39 |
--------------------------------------------------------------------------------
/misc/unpheet.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | # Grabs cpu, pop & push throughput columns, and converts them to ops per second.
4 | sed -e '/^test/d' -e '1d' -e 's/\t/ /g' $1 | awk '{ printf "pheet,%d,%d\n", $7, int(($8 + $9) / 10) }'
5 |
--------------------------------------------------------------------------------
/src/.gitignore:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/klsmpq/klsm/1fa9cd0bd0c63a17844fc2954c52b60d8f71f340/src/.gitignore
--------------------------------------------------------------------------------
/src/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | add_subdirectory(bench)
2 | add_subdirectory(sequential_lsm)
3 | add_subdirectory(util)
4 |
5 | include_directories(
6 | ${CMAKE_CURRENT_SOURCE_DIR}
7 | )
8 |
9 | # A silly hack to make all files (including headers) show up in QtCreator.
10 | file(GLOB_RECURSE ALL_HEADERS *.h)
11 | add_library(qtcreator_dummy ${ALL_HEADERS} util/thread_local_ptr.cpp)
12 |
--------------------------------------------------------------------------------
/src/bench/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | add_subdirectory(pqs)
2 |
3 | include_directories(
4 | ${CMAKE_SOURCE_DIR}/src
5 | )
6 |
7 | if(CMAKE_COMPILER_IS_GNUCXX)
8 | add_definitions("-flto")
9 | endif()
10 |
11 | add_executable(heapsort heapsort.cpp util.cpp)
12 | target_link_libraries(heapsort
13 | ${HWLOC_LIBRARIES}
14 | sequence_heap
15 | sequential_lsm
16 | skip_queue
17 | )
18 |
19 | add_executable(random random.cpp itree.cpp util.cpp)
20 | target_link_libraries(random
21 | ${CMAKE_THREAD_LIBS_INIT}
22 | ${HWLOC_LIBRARIES}
23 | capq
24 | linden
25 | sequence_heap
26 | sequential_lsm
27 | skip_queue
28 | spraylist
29 | thread_local_ptr
30 | )
31 |
32 | add_executable(shortest_paths shortest_paths.cpp util.cpp)
33 | target_link_libraries(shortest_paths
34 | ${CMAKE_THREAD_LIBS_INIT}
35 | ${HWLOC_LIBRARIES}
36 | linden
37 | sequence_heap
38 | sequential_lsm
39 | skip_queue
40 | thread_local_ptr
41 | )
42 |
43 | add_executable(file_shortest_paths file_shortest_paths.cpp util.cpp)
44 | target_link_libraries(file_shortest_paths
45 | ${CMAKE_THREAD_LIBS_INIT}
46 | ${HWLOC_LIBRARIES}
47 | linden
48 | sequence_heap
49 | sequential_lsm
50 | skip_queue
51 | thread_local_ptr
52 | spraylist
53 | capq
54 | #/usr/local/lib/libpapi.a
55 | )
56 |
57 | add_executable(generate_random_graph generate_random_graph.cpp)
58 |
--------------------------------------------------------------------------------
/src/bench/pqs/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | include_directories(
2 | ${CMAKE_CURRENT_SOURCE_DIR}
3 | )
4 |
5 | add_library(linden STATIC
6 | ${CMAKE_SOURCE_DIR}/lib/spraylist_linden/linden_common.c
7 | ${CMAKE_SOURCE_DIR}/lib/spraylist_linden/linden.c
8 | ${CMAKE_SOURCE_DIR}/lib/spraylist_linden/gc/gc.c
9 | ${CMAKE_SOURCE_DIR}/lib/spraylist_linden/gc/ptst.c
10 | linden.cpp
11 | )
12 | execute_process(COMMAND getconf LEVEL1_DCACHE_LINESIZE OUTPUT_VARIABLE CACHE_LINE_SIZE)
13 | set_target_properties(linden PROPERTIES COMPILE_FLAGS
14 | "-w -std=gnu11 -DINTEL -DCACHE_LINE_SIZE=${CACHE_LINE_SIZE}"
15 | )
16 | target_include_directories(linden PUBLIC
17 | ${CMAKE_SOURCE_DIR}/lib
18 | ${CMAKE_SOURCE_DIR}/lib/spraylist_linden/include
19 | )
20 |
21 | add_library(sequence_heap STATIC
22 | ${CMAKE_SOURCE_DIR}/lib/sequence_heap/knheap.C
23 | sequence_heap.cpp
24 | )
25 | set_target_properties(sequence_heap PROPERTIES COMPILE_FLAGS
26 | "-w"
27 | )
28 | target_include_directories(sequence_heap PUBLIC
29 | ${CMAKE_SOURCE_DIR}/lib/sequence_heap
30 | )
31 |
32 | add_library(skip_queue STATIC
33 | skip_queue.cpp
34 | )
35 | target_include_directories(skip_queue PUBLIC
36 | ${CMAKE_SOURCE_DIR}/lib/skip_list
37 | )
38 |
39 | add_library(spraylist STATIC
40 | ${CMAKE_SOURCE_DIR}/lib/spraylist_linden/fraser.c
41 | ${CMAKE_SOURCE_DIR}/lib/spraylist_linden/intset.c
42 | ${CMAKE_SOURCE_DIR}/lib/spraylist_linden/linden_common.c
43 | ${CMAKE_SOURCE_DIR}/lib/spraylist_linden/linden.c
44 | ${CMAKE_SOURCE_DIR}/lib/spraylist_linden/measurements.c
45 | ${CMAKE_SOURCE_DIR}/lib/spraylist_linden/pqueue.c
46 | ${CMAKE_SOURCE_DIR}/lib/spraylist_linden/skiplist.c
47 | ${CMAKE_SOURCE_DIR}/lib/spraylist_linden/ssalloc.c
48 | spraylist.cpp
49 | )
50 | set_target_properties(spraylist PROPERTIES COMPILE_FLAGS
51 | "-w -std=gnu11 -DINTEL -DLOCKFREE -DCACHE_LINE_SIZE=${CACHE_LINE_SIZE}"
52 | )
53 | target_include_directories(spraylist PUBLIC
54 | ${CMAKE_SOURCE_DIR}/lib
55 | ${CMAKE_SOURCE_DIR}/lib/spraylist_linden/atomic_ops
56 | ${CMAKE_SOURCE_DIR}/lib/spraylist_linden/include
57 | )
58 |
59 | add_library(capq STATIC
60 | ${CMAKE_SOURCE_DIR}/lib/capq/capq.c
61 | ${CMAKE_SOURCE_DIR}/lib/capq/fat_skiplist.c
62 | ${CMAKE_SOURCE_DIR}/lib/capq/qdlocksrc/locks/qd_lock.c
63 | ${CMAKE_SOURCE_DIR}/lib/capq/qdlocksrc/locks/tatas_lock.c
64 | ${CMAKE_SOURCE_DIR}/lib/capq/gc/gc.c
65 | ${CMAKE_SOURCE_DIR}/lib/capq/gc/ptst.c
66 | )
67 | set_target_properties(capq PROPERTIES COMPILE_FLAGS
68 | "-w -std=gnu11 -DINTEL -DCACHE_LINE_SIZE=${CACHE_LINE_SIZE}"
69 | )
70 | target_include_directories(capq PUBLIC
71 | ${CMAKE_SOURCE_DIR}/lib
72 | ${CMAKE_SOURCE_DIR}/lib/capq
73 | ${CMAKE_SOURCE_DIR}/lib/capq/qdlocksrc
74 | )
75 |
--------------------------------------------------------------------------------
/src/bench/pqs/cheap.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2014 Jakob Gruber
3 | *
4 | * This file is part of kpqueue.
5 | *
6 | * kpqueue is free software: you can redistribute it and/or modify
7 | * it under the terms of the GNU General Public License as published by
8 | * the Free Software Foundation, either version 3 of the License, or
9 | * (at your option) any later version.
10 | *
11 | * kpqueue is distributed in the hope that it will be useful,
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | * GNU General Public License for more details.
15 | *
16 | * You should have received a copy of the GNU General Public License
17 | * along with kpqueue. If not, see .
18 | */
19 |
20 | #ifndef __CHEAP_H
21 | #define __CHEAP_H
22 |
23 | #include
24 |
25 | #include "util/thread_local_ptr.h"
26 |
27 | using kpq::thread_local_ptr;
28 |
29 | namespace kpqbench
30 | {
31 |
32 | /**
33 | * 'cheap' stands for concurrent heap, and simply consists of a thread-local
34 | * std::priority_queue. Unlike the CLSM, there is no spy() operation, and threads
35 | * may only access elements they added themselves.
36 | */
37 | template
38 | class cheap
39 | {
40 | private:
41 | class entry_t
42 | {
43 | public:
44 | K key;
45 | V value;
46 |
47 | bool operator>(const entry_t &that) const
48 | {
49 | return this->key > that.key;
50 | }
51 | };
52 |
53 | public:
54 | void insert(const K &key, const V &value);
55 | bool delete_min(V &value);
56 |
57 | void print() const;
58 |
59 | void init_thread(const size_t) const { }
60 | constexpr static bool supports_concurrency() { return true; }
61 |
62 | private:
63 | typedef std::priority_queue, std::greater> pq_t;
64 |
65 | thread_local_ptr m_q;
66 | };
67 |
68 | template
69 | bool
70 | cheap::delete_min(V &value)
71 | {
72 | pq_t *pq = m_q.get();
73 | if (pq->empty()) {
74 | return false;
75 | }
76 |
77 | entry_t entry = pq->top();
78 | pq->pop();
79 |
80 | value = entry.value;
81 |
82 | return true;
83 | }
84 |
85 | template
86 | void
87 | cheap::insert(const K &key,
88 | const V &value)
89 | {
90 | pq_t *pq = m_q.get();
91 | pq->push(entry_t { key, value });
92 | }
93 |
94 | template
95 | void cheap::print() const
96 | {
97 | /* NOP */
98 | }
99 |
100 | }
101 |
102 | #endif /* __CHEAP_H */
103 |
--------------------------------------------------------------------------------
/src/bench/pqs/cppcapq.h:
--------------------------------------------------------------------------------
1 | #ifndef __CPPCAPQ_H
2 | #define __CPPCAPQ_H
3 |
4 | #include
5 | #include
6 |
7 | namespace kpqbench
8 | {
9 |
10 | struct capq_t;
11 |
12 | template
13 | class CPPCAPQ
14 | {
15 | public:
16 | CPPCAPQ();
17 | virtual ~CPPCAPQ();
18 |
19 | void insert(const uint32_t &key, const uint32_t &value);
20 | void insert(const size_t &key, const size_t &value);
21 | void flush_insert_cache();
22 | bool delete_min(uint32_t &v);
23 | bool delete_min(size_t &k, size_t &v);
24 |
25 | void signal_waste();
26 | void signal_no_waste();
27 |
28 | void init_thread(const size_t nthreads);
29 | constexpr static bool supports_concurrency()
30 | {
31 | return true;
32 | }
33 |
34 | private:
35 | capq_t *m_q;
36 | };
37 |
38 | #include "cppcapq_inl.h"
39 | }
40 |
41 | #endif /* __CPPCAPQ_H */
42 |
--------------------------------------------------------------------------------
/src/bench/pqs/cppcapq_inl.h:
--------------------------------------------------------------------------------
1 | #include "cppcapq.h"
2 |
3 | extern "C" {
4 | #include "capq.h"
5 | #include "capq/gc/gc.h"
6 | }
7 |
8 |
9 |
10 | struct capq_t {
11 | char pad1[64 - sizeof(CAPQ *)];
12 | CAPQ *pq;
13 | char pad2[64];
14 | };
15 |
16 | static inline void
17 | qdcatree_insert(CAPQ *pq,
18 | const uint32_t k,
19 | const uint32_t v)
20 | {
21 | capq_put(pq,
22 | (unsigned long) k,
23 | (unsigned long) v);
24 | }
25 |
26 | template
27 | CPPCAPQ::CPPCAPQ()
28 | {
29 | _init_gc_subsystem();
30 | init_thread(1);
31 | m_q = new capq_t;
32 | m_q->pq = capq_new();
33 | }
34 |
35 | template
36 | CPPCAPQ::~CPPCAPQ()
37 | {
38 |
39 | }
40 |
41 | template
42 | void
43 | CPPCAPQ::init_thread(const size_t nthreads)
44 | {
45 | (void)nthreads;
46 | }
47 |
48 | template
49 | void
50 | CPPCAPQ::insert(const uint32_t &key,
51 | const uint32_t &value)
52 | {
53 | qdcatree_insert(m_q->pq, key, value);
54 | }
55 |
56 | template
57 | void
58 | CPPCAPQ::insert(const size_t &key,
59 | const size_t &value)
60 | {
61 | capq_put_param(m_q->pq,
62 | (unsigned long) key,
63 | (unsigned long) value,
64 | catree_adapt);
65 | }
66 |
67 | template
68 | void
69 | CPPCAPQ::flush_insert_cache()
70 | {
71 | }
72 |
73 | template
74 | bool
75 | CPPCAPQ::delete_min(uint32_t &v)
76 | {
77 | unsigned long key_write_back;
78 | v = (uint32_t)capq_remove_min(m_q->pq, &key_write_back);
79 | return key_write_back != ((unsigned long) - 1);
80 | }
81 |
82 | template
83 | bool
84 | CPPCAPQ::delete_min(size_t &k, size_t &v)
85 | {
86 | unsigned long key_write_back;
87 | v = (size_t)capq_remove_min_param(m_q->pq, &key_write_back, remove_min_relax, put_relax,
88 | catree_adapt);
89 | k = (size_t)key_write_back;
90 | return key_write_back != ((unsigned long) - 1);
91 | }
92 |
--------------------------------------------------------------------------------
/src/bench/pqs/linden.cpp:
--------------------------------------------------------------------------------
1 | #include "linden.h"
2 |
3 | extern "C" {
4 | #include "spraylist_linden/gc/gc.h"
5 | #include "spraylist_linden/linden.h"
6 | }
7 |
8 | namespace kpqbench
9 | {
10 |
11 | struct linden_t {
12 | pq_t *pq;
13 | };
14 |
15 | static inline void
16 | linden_insert(pq_t *pq,
17 | const uint32_t k,
18 | const uint32_t v)
19 | {
20 | insert(pq, k, v);
21 | }
22 |
23 | Linden::Linden(const int max_offset)
24 | {
25 | _init_gc_subsystem();
26 | m_q = new linden_t;
27 | m_q->pq = pq_init(max_offset);
28 | }
29 |
30 | Linden::~Linden()
31 | {
32 | pq_destroy(m_q->pq);
33 | delete m_q;
34 | _destroy_gc_subsystem();
35 | }
36 |
37 | void
38 | Linden::insert(const uint32_t &key,
39 | const uint32_t &value)
40 | {
41 | /*Add 1 to key to support 0 keys*/
42 | linden_insert(m_q->pq, key+1, value);
43 | }
44 |
45 | void
46 | Linden::insert(const size_t &key,
47 | const size_t &value)
48 | {
49 | /*Add 1 to key to support 0 keys*/
50 | linden_insert(m_q->pq, key+1, value);
51 | }
52 |
53 | bool
54 | Linden::delete_min(size_t &k, size_t &v)
55 | {
56 | unsigned long k_ret;
57 | v = deletemin_key(m_q->pq, &k_ret);
58 | k = k_ret -1;
59 | return k_ret != -1;
60 | }
61 |
62 | bool
63 | Linden::delete_min(uint32_t &v)
64 | {
65 | size_t k_ret;
66 | size_t v_ret;
67 | bool ret = delete_min(k_ret, v_ret);
68 | v = (uint32_t)v_ret;
69 | return ret;
70 | }
71 |
72 | }
73 |
74 |
--------------------------------------------------------------------------------
/src/bench/pqs/linden.h:
--------------------------------------------------------------------------------
1 | #ifndef __LINDEN_H
2 | #define __LINDEN_H
3 |
4 | #include
5 | #include
6 |
7 | namespace kpqbench
8 | {
9 |
10 | struct linden_t;
11 |
12 | class Linden
13 | {
14 | public:
15 | constexpr static int DEFAULT_OFFSET = 32;
16 |
17 | Linden(const int max_offset = DEFAULT_OFFSET);
18 | virtual ~Linden();
19 |
20 | void insert(const uint32_t &key, const uint32_t &value);
21 | void insert(const size_t &key, const size_t &value);
22 | bool delete_min(uint32_t &v);
23 | bool delete_min(size_t &k, size_t &v);
24 |
25 | void init_thread(const size_t) const { }
26 | constexpr static bool supports_concurrency() { return true; }
27 |
28 | private:
29 | linden_t *m_q;
30 | };
31 |
32 | }
33 |
34 | #endif /* __LINDEN_H */
35 |
--------------------------------------------------------------------------------
/src/bench/pqs/multiq.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2015 Jakob Gruber
3 | *
4 | * This file is part of kpqueue.
5 | *
6 | * kpqueue is free software: you can redistribute it and/or modify
7 | * it under the terms of the GNU General Public License as published by
8 | * the Free Software Foundation, either version 3 of the License, or
9 | * (at your option) any later version.
10 | *
11 | * kpqueue is distributed in the hope that it will be useful,
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | * GNU General Public License for more details.
15 | *
16 | * You should have received a copy of the GNU General Public License
17 | * along with kpqueue. If not, see .
18 | */
19 |
20 | #ifndef __MULTIQ_H
21 | #define __MULTIQ_H
22 |
23 | #include
24 | #include
25 |
26 | #include "util/thread_local_ptr.h"
27 | #include "util/xorshf96.h"
28 |
29 | namespace kpqbench
30 | {
31 |
32 | /**
33 | * Reimplementation of a multiqueue as described in Rihani, Sanders, Dementiev:
34 | * "MultiQueues: Simpler, Faster, and Better Relaxed Concurrent Priority Queues".
35 | * C is a tuning parameter specifying the number of internal queues per thread.
36 | */
37 | template
38 | class multiq
39 | {
40 | private:
41 | constexpr static K SENTINEL_KEY = std::numeric_limits::max();
42 | constexpr static int CACHE_LINE_SIZE = 64;
43 |
44 | struct entry
45 | {
46 | entry(K k, V v) : key(k), value(v) { }
47 |
48 | K key;
49 | V value;
50 |
51 | bool operator>(const entry &that) const
52 | {
53 | return this->key > that.key;
54 | }
55 | };
56 |
57 | typedef std::priority_queue, std::greater> pq;
58 |
59 | struct local_queue
60 | {
61 | local_queue()
62 | {
63 | m_pq.push({ SENTINEL_KEY, V { } });
64 | m_top = SENTINEL_KEY;
65 | }
66 |
67 | pq m_pq;
68 | K m_top;
69 |
70 | char m_padding[CACHE_LINE_SIZE - sizeof(m_top) - sizeof(m_pq)];
71 | } __attribute__((aligned(64)));
72 |
73 | struct local_lock
74 | {
75 | local_lock() : m_is_locked(false) { }
76 |
77 | std::atomic m_is_locked;
78 |
79 | char m_padding[CACHE_LINE_SIZE - sizeof(m_is_locked)];
80 | } __attribute__((aligned(64)));
81 |
82 | public:
83 | multiq(const size_t num_threads);
84 | virtual ~multiq();
85 |
86 | void insert(const K &key, const V &value);
87 | bool delete_min(V &value);
88 | bool delete_min(K &key, V &value);
89 | void clear();
90 |
91 | void print() const;
92 |
93 | void init_thread(const size_t) const { }
94 | constexpr static bool supports_concurrency() { return true; }
95 |
96 | private:
97 | size_t num_queues() const { return m_num_threads * C; }
98 | bool lock(const size_t ix);
99 | void unlock(const size_t ix);
100 |
101 | private:
102 | const size_t m_num_threads;
103 |
104 | local_queue *m_queues;
105 | local_lock *m_locks;
106 | };
107 |
108 | #include "multiq_inl.h"
109 |
110 | }
111 |
112 | #endif /* __MULTIQ_H */
113 |
--------------------------------------------------------------------------------
/src/bench/pqs/sequence_heap.cpp:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2014 Jakob Gruber
3 | *
4 | * This file is part of kpqueue.
5 | *
6 | * kpqueue is free software: you can redistribute it and/or modify
7 | * it under the terms of the GNU General Public License as published by
8 | * the Free Software Foundation, either version 3 of the License, or
9 | * (at your option) any later version.
10 | *
11 | * kpqueue is distributed in the hope that it will be useful,
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | * GNU General Public License for more details.
15 | *
16 | * You should have received a copy of the GNU General Public License
17 | * along with kpqueue. If not, see .
18 | */
19 |
20 | #include "sequence_heap.h"
21 |
22 | #include
23 |
24 | #include "knheap.h"
25 |
26 | namespace kpqbench
27 | {
28 |
29 | template
30 | sequence_heap::sequence_heap()
31 | {
32 | m_pq = new KNHeap(std::numeric_limits::max(),
33 | std::numeric_limits::min());
34 | }
35 |
36 | template
37 | void
38 | sequence_heap::insert(const T &key,
39 | const T &value)
40 | {
41 | m_pq->insert(key, value);
42 | }
43 |
44 | template
45 | bool
46 | sequence_heap::delete_min(T &v)
47 | {
48 | if (m_pq->getSize() == 0) {
49 | return false;
50 | }
51 |
52 | T w;
53 | m_pq->deleteMin(&w, &v);
54 |
55 | return true;
56 | }
57 |
58 | template
59 | void
60 | sequence_heap::clear()
61 | {
62 | delete m_pq;
63 | m_pq = new KNHeap(std::numeric_limits::max(),
64 | std::numeric_limits::min());
65 | }
66 |
67 | template class sequence_heap;
68 |
69 | }
70 |
--------------------------------------------------------------------------------
/src/bench/pqs/sequence_heap.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2014 Jakob Gruber
3 | *
4 | * This file is part of kpqueue.
5 | *
6 | * kpqueue is free software: you can redistribute it and/or modify
7 | * it under the terms of the GNU General Public License as published by
8 | * the Free Software Foundation, either version 3 of the License, or
9 | * (at your option) any later version.
10 | *
11 | * kpqueue is distributed in the hope that it will be useful,
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | * GNU General Public License for more details.
15 | *
16 | * You should have received a copy of the GNU General Public License
17 | * along with kpqueue. If not, see .
18 | */
19 |
20 | #ifndef __SEQUENCE_HEAP_H
21 | #define __SEQUENCE_HEAP_H
22 |
23 | #include
24 |
25 | template
26 | class KNHeap;
27 |
28 | namespace kpqbench
29 | {
30 |
31 | template
32 | class sequence_heap
33 | {
34 | public:
35 | sequence_heap();
36 |
37 | void insert(const T &k, const T &v);
38 | bool delete_min(T &v);
39 | void clear();
40 |
41 | void init_thread(const size_t) const { }
42 | constexpr static bool supports_concurrency() { return false; }
43 |
44 | private:
45 | KNHeap *m_pq;
46 | };
47 |
48 | }
49 |
50 | #endif /* __SEQUENCE_HEAP_H */
51 |
--------------------------------------------------------------------------------
/src/bench/pqs/skip_queue.cpp:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2014 Jakob Gruber
3 | *
4 | * This file is part of kpqueue.
5 | *
6 | * kpqueue is free software: you can redistribute it and/or modify
7 | * it under the terms of the GNU General Public License as published by
8 | * the Free Software Foundation, either version 3 of the License, or
9 | * (at your option) any later version.
10 | *
11 | * kpqueue is distributed in the hope that it will be useful,
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | * GNU General Public License for more details.
15 | *
16 | * You should have received a copy of the GNU General Public License
17 | * along with kpqueue. If not, see .
18 | */
19 |
20 | #include "skip_queue.h"
21 |
22 | namespace kpqbench
23 | {
24 |
25 | template
26 | void
27 | skip_queue::insert(const T &key,
28 | const T & /* Unused */)
29 | {
30 | m_pq.insert(key);
31 | }
32 |
33 | template
34 | bool
35 | skip_queue::delete_min(T &v)
36 | {
37 | if (m_pq.empty()) {
38 | return false;
39 | }
40 |
41 | v = m_pq.front();
42 | m_pq.erase(m_pq.begin());
43 |
44 | return true;
45 | }
46 |
47 | template
48 | void
49 | skip_queue::clear()
50 | {
51 | m_pq.clear();
52 | }
53 |
54 | template class skip_queue;
55 |
56 | }
57 |
--------------------------------------------------------------------------------
/src/bench/pqs/skip_queue.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2014 Jakob Gruber
3 | *
4 | * This file is part of kpqueue.
5 | *
6 | * kpqueue is free software: you can redistribute it and/or modify
7 | * it under the terms of the GNU General Public License as published by
8 | * the Free Software Foundation, either version 3 of the License, or
9 | * (at your option) any later version.
10 | *
11 | * kpqueue is distributed in the hope that it will be useful,
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | * GNU General Public License for more details.
15 | *
16 | * You should have received a copy of the GNU General Public License
17 | * along with kpqueue. If not, see .
18 | */
19 |
20 | #ifndef __SKIP_QUEUE_H
21 | #define __SKIP_QUEUE_H
22 |
23 | #include "skip_list.h"
24 |
25 | namespace kpqbench
26 | {
27 |
28 | template
29 | class skip_queue
30 | {
31 | public:
32 | void insert(const T &key, const T &value);
33 | bool delete_min(T &v);
34 | void clear();
35 |
36 | void init_thread(const size_t) const { }
37 | constexpr static bool supports_concurrency() { return false; }
38 |
39 | private:
40 | goodliffe::multi_skip_list m_pq;
41 | };
42 |
43 | }
44 |
45 | #endif /* __SKIP_QUEUE_H */
46 |
--------------------------------------------------------------------------------
/src/bench/pqs/spraylist.cpp:
--------------------------------------------------------------------------------
1 | #include "spraylist.h"
2 |
3 | extern "C" {
4 | #include "spraylist_linden/include/random.h"
5 | #include "spraylist_linden/intset.h"
6 | #include "spraylist_linden/linden.h"
7 | #include "spraylist_linden/pqueue.h"
8 | #include "ssalloc.h"
9 | }
10 |
11 | __thread unsigned long *seeds;
12 |
13 | namespace kpqbench {
14 |
15 | constexpr unsigned int INITIAL_SIZE = 1000000;
16 |
17 | /** See documentation of --elasticity in spraylist/test.c. */
18 | #define READ_ADD_REM_ELASTIC_TX (4)
19 |
20 | static __thread bool initialized = false;
21 | static __thread thread_data_t *d;
22 |
23 |
24 | spraylist::spraylist(const size_t nthreads)
25 | {
26 | init_thread(nthreads);
27 | *levelmax = floor_log_2(INITIAL_SIZE);
28 | m_q = sl_set_new();
29 | }
30 |
31 | spraylist::~spraylist()
32 | {
33 | sl_set_delete(m_q);
34 | delete d;
35 | }
36 |
37 | void
38 | spraylist::init_thread(const size_t nthreads)
39 | {
40 | if (!initialized) {
41 | ssalloc_init(nthreads);
42 | seeds = seed_rand();
43 |
44 | d = new thread_data_t;
45 | d->seed = rand();
46 | d->seed2 = rand();
47 |
48 | initialized = true;
49 | }
50 |
51 | d->nb_threads = nthreads;
52 | }
53 |
54 | void
55 | spraylist::insert(const uint32_t &k,
56 | const uint32_t &v)
57 | {
58 | sl_add_val(m_q, k, v, TRANSACTIONAL);
59 | }
60 |
61 | void
62 | spraylist::insert(const size_t &k,
63 | const size_t &v)
64 | {
65 | sl_add_val(m_q, k, v, TRANSACTIONAL);
66 | }
67 |
68 | bool
69 | spraylist::delete_min(size_t &k, size_t &v)
70 | {
71 | unsigned long k_ret;
72 | unsigned long v_ret;
73 | int ret;
74 | do {
75 | ret = spray_delete_min_key(m_q, &k_ret, &v_ret, d);
76 | } while(ret == 0 && k_ret != -1);
77 | k = k_ret;
78 | v = v_ret;
79 | return k_ret != -1;
80 | }
81 |
82 | bool
83 | spraylist::delete_min(uint32_t &v)
84 | {
85 | size_t k_ret;
86 | size_t v_ret;
87 | const bool ret = delete_min(k_ret, v_ret);
88 | v = (uint32_t)v_ret;
89 | return ret;
90 | }
91 |
92 | }
93 |
--------------------------------------------------------------------------------
/src/bench/pqs/spraylist.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2015 Jakob Gruber
3 | *
4 | * This file is part of kpqueue.
5 | *
6 | * kpqueue is free software: you can redistribute it and/or modify
7 | * it under the terms of the GNU General Public License as published by
8 | * the Free Software Foundation, either version 3 of the License, or
9 | * (at your option) any later version.
10 | *
11 | * kpqueue is distributed in the hope that it will be useful,
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | * GNU General Public License for more details.
15 | *
16 | * You should have received a copy of the GNU General Public License
17 | * along with kpqueue. If not, see .
18 | */
19 |
20 | #ifndef __SPRAYLIST_H
21 | #define __SPRAYLIST_H
22 |
23 | #include
24 |
25 | struct sl_intset;
26 | typedef sl_intset sl_intset_t;
27 |
28 | namespace kpqbench {
29 |
30 | class spraylist
31 | {
32 | public:
33 | spraylist(const size_t nthreads);
34 | virtual ~spraylist();
35 |
36 | void init_thread(const size_t nthreads);
37 |
38 | void insert(const uint32_t &k, const uint32_t &v);
39 | void insert(const size_t &k, const size_t &v);
40 | bool delete_min(uint32_t &v);
41 | bool delete_min(size_t &k, size_t &v);
42 |
43 | static void print_name() { std::cout << "spraylist"; }
44 | constexpr static bool supports_concurrency() { return true; }
45 |
46 | private:
47 | typedef sl_intset_t pq_t;
48 |
49 | pq_t *m_q;
50 | };
51 |
52 | }
53 |
54 | #endif /* __SPRAYLIST_H */
55 |
--------------------------------------------------------------------------------
/src/bench/util.cpp:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2014 Jakob Gruber
3 | *
4 | * This file is part of kpqueue.
5 | *
6 | * kpqueue is free software: you can redistribute it and/or modify
7 | * it under the terms of the GNU General Public License as published by
8 | * the Free Software Foundation, either version 3 of the License, or
9 | * (at your option) any later version.
10 | *
11 | * kpqueue is distributed in the hope that it will be useful,
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | * GNU General Public License for more details.
15 | *
16 | * You should have received a copy of the GNU General Public License
17 | * along with kpqueue. If not, see .
18 | */
19 |
20 | #include "util.h"
21 |
22 | #include
23 | #include
24 | #include
25 |
26 | class hwloc_wrapper_private
27 | {
28 | public:
29 | hwloc_topology_t m_topology;
30 | };
31 |
32 | hwloc_wrapper::hwloc_wrapper()
33 | {
34 | m_p = new hwloc_wrapper_private();
35 |
36 | hwloc_topology_init(&m_p->m_topology);
37 | hwloc_topology_load(m_p->m_topology);
38 | }
39 |
40 | hwloc_wrapper::~hwloc_wrapper()
41 | {
42 | hwloc_topology_destroy(m_p->m_topology);
43 | delete m_p;
44 | }
45 |
46 | void
47 | hwloc_wrapper::pin_to_core(const int id)
48 | {
49 | const int depth = hwloc_get_type_or_below_depth(m_p->m_topology, HWLOC_OBJ_CORE);
50 | const int ncores = hwloc_get_nbobjs_by_depth(m_p->m_topology, depth);
51 |
52 | const hwloc_obj_t obj = hwloc_get_obj_by_depth(m_p->m_topology, depth, id % ncores);
53 |
54 | hwloc_cpuset_t cpuset = hwloc_bitmap_dup(obj->cpuset);
55 | hwloc_bitmap_singlify(cpuset);
56 |
57 | if (hwloc_set_cpubind(m_p->m_topology, cpuset, HWLOC_CPUBIND_THREAD) != 0) {
58 | fprintf(stderr, "Could not bind to core: %s\n", strerror(errno));
59 | }
60 |
61 | hwloc_bitmap_free(cpuset);
62 | }
63 |
64 | double
65 | timediff_in_s(const struct timespec &start,
66 | const struct timespec &end)
67 | {
68 | struct timespec tmp;
69 | if (end.tv_nsec < start.tv_nsec) {
70 | tmp.tv_sec = end.tv_sec - start.tv_sec - 1;
71 | tmp.tv_nsec = 1000000000 + end.tv_nsec - start.tv_nsec;
72 | } else {
73 | tmp.tv_sec = end.tv_sec - start.tv_sec;
74 | tmp.tv_nsec = end.tv_nsec - start.tv_nsec;
75 | }
76 |
77 | return tmp.tv_sec + (double)tmp.tv_nsec / 1000000000.0;
78 | }
79 |
80 | uint64_t
81 | rdtsc()
82 | {
83 | return __rdtsc();
84 | }
85 |
86 | std::vector
87 | random_array(const size_t n,
88 | const int seed)
89 | {
90 | std::vector xs;
91 | xs.reserve(n);
92 |
93 | std::mt19937 gen(seed);
94 | std::uniform_int_distribution<> rand_int;
95 |
96 | for (size_t i = 0; i < n; i++) {
97 | xs.push_back(rand_int(gen));
98 | }
99 |
100 | return xs;
101 | }
102 |
--------------------------------------------------------------------------------
/src/bench/util.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2014 Jakob Gruber
3 | *
4 | * This file is part of kpqueue.
5 | *
6 | * kpqueue is free software: you can redistribute it and/or modify
7 | * it under the terms of the GNU General Public License as published by
8 | * the Free Software Foundation, either version 3 of the License, or
9 | * (at your option) any later version.
10 | *
11 | * kpqueue is distributed in the hope that it will be useful,
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | * GNU General Public License for more details.
15 | *
16 | * You should have received a copy of the GNU General Public License
17 | * along with kpqueue. If not, see .
18 | */
19 |
20 | #ifndef __UTIL_H
21 | #define __UTIL_H
22 |
23 | #include
24 | #include
25 | #include
26 |
27 | class hwloc_wrapper_private;
28 |
29 | class hwloc_wrapper
30 | {
31 | public:
32 | hwloc_wrapper();
33 | virtual ~hwloc_wrapper();
34 |
35 | void pin_to_core(const int id);
36 |
37 | private:
38 | hwloc_wrapper_private *m_p;
39 | };
40 |
41 | double
42 | timediff_in_s(const struct timespec &start,
43 | const struct timespec &end);
44 |
45 | std::vector
46 | random_array(const size_t n,
47 | const int seed);
48 |
49 | uint64_t
50 | rdtsc();
51 |
52 | #endif /* __UTIL_H */
53 |
--------------------------------------------------------------------------------
/src/components/block_storage.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2014 Jakob Gruber
3 | *
4 | * This file is part of kpqueue.
5 | *
6 | * kpqueue is free software: you can redistribute it and/or modify
7 | * it under the terms of the GNU General Public License as published by
8 | * the Free Software Foundation, either version 3 of the License, or
9 | * (at your option) any later version.
10 | *
11 | * kpqueue is distributed in the hope that it will be useful,
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | * GNU General Public License for more details.
15 | *
16 | * You should have received a copy of the GNU General Public License
17 | * along with kpqueue. If not, see .
18 | */
19 |
20 | #ifndef __BLOCK_STORAGE_H
21 | #define __BLOCK_STORAGE_H
22 |
23 | #include
24 |
25 | #include "block.h"
26 |
27 | namespace kpq
28 | {
29 |
30 | /**
31 | * Maintains N-tuples of memory blocks of size 2^i.
32 | */
33 |
34 | template
35 | class block_storage
36 | {
37 | private:
38 | static constexpr size_t MAX_BLOCKS = 32; // TODO: Global setting.
39 |
40 | struct block_tuple {
41 | block *xs[N];
42 | };
43 |
44 | public:
45 | block_storage() : m_blocks { { nullptr } }, m_size(0) { }
46 | virtual ~block_storage();
47 |
48 | /**
49 | * Returns an unused block of size 2^i. If such a block does not exist,
50 | * a new N-tuple of size 2^i is allocated.
51 | */
52 | block *get_block(const size_t i);
53 |
54 | block *get_largest_block();
55 |
56 | void print() const;
57 |
58 | private:
59 | block_tuple m_blocks[MAX_BLOCKS];
60 | size_t m_size;
61 | };
62 |
63 | #include "block_storage_inl.h"
64 |
65 | }
66 |
67 | #endif /* __BLOCK_STORAGE_H */
68 |
--------------------------------------------------------------------------------
/src/components/block_storage_inl.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2014 Jakob Gruber
3 | *
4 | * This file is part of kpqueue.
5 | *
6 | * kpqueue is free software: you can redistribute it and/or modify
7 | * it under the terms of the GNU General Public License as published by
8 | * the Free Software Foundation, either version 3 of the License, or
9 | * (at your option) any later version.
10 | *
11 | * kpqueue is distributed in the hope that it will be useful,
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | * GNU General Public License for more details.
15 | *
16 | * You should have received a copy of the GNU General Public License
17 | * along with kpqueue. If not, see .
18 | */
19 |
20 | template
21 | block_storage::~block_storage()
22 | {
23 | for (size_t i = 0; i < m_size; i++) {
24 | for (int j = 0; j < N; j++) {
25 | delete m_blocks[i].xs[j];
26 | }
27 | }
28 | }
29 |
30 | template
31 | block *
32 | block_storage::get_block(const size_t i)
33 | {
34 | for (; m_size <= i; m_size++) {
35 | /* Alloc new blocks. */
36 | for (int j = 0; j < N; j++) {
37 | m_blocks[m_size].xs[j] = new block(m_size);
38 | }
39 | }
40 |
41 | block *block = m_blocks[i].xs[N - 1];
42 | for (int j = 0; j < N - 1; j++) {
43 | if (!m_blocks[i].xs[j]->used()) {
44 | block = m_blocks[i].xs[j];
45 | break;
46 | }
47 | }
48 |
49 | block->set_used();
50 | return block;
51 | }
52 |
53 | template
54 | block *
55 | block_storage::get_largest_block()
56 | {
57 | return get_block((m_size == 0) ? 0 : m_size - 1);
58 | }
59 |
60 | template
61 | void
62 | block_storage::print() const
63 | {
64 | for (size_t i = 0; i < m_size; i++) {
65 | printf("%zu: {%d", i, m_blocks[i].xs[0]->used());
66 | for (int j = 1; j < N; j++) {
67 | printf(", %d", m_blocks[i].xs[j]->used());
68 | }
69 | printf("}, ");
70 | }
71 | printf("\n");
72 | }
73 |
--------------------------------------------------------------------------------
/src/components/item.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2014 Jakob Gruber
3 | *
4 | * This file is part of kpqueue.
5 | *
6 | * kpqueue is free software: you can redistribute it and/or modify
7 | * it under the terms of the GNU General Public License as published by
8 | * the Free Software Foundation, either version 3 of the License, or
9 | * (at your option) any later version.
10 | *
11 | * kpqueue is distributed in the hope that it will be useful,
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | * GNU General Public License for more details.
15 | *
16 | * You should have received a copy of the GNU General Public License
17 | * along with kpqueue. If not, see .
18 | */
19 |
20 | #ifndef __ITEM_H
21 | #define __ITEM_H
22 |
23 | #include
24 | #include
25 | #include
26 |
27 | namespace kpq
28 | {
29 |
30 | typedef uint32_t version_t;
31 |
32 | template
33 | class item
34 | {
35 | public:
36 | item();
37 |
38 | void initialize(const K &key,
39 | const V &val);
40 | bool take(const version_t version,
41 | V &val);
42 | bool take(const version_t version,
43 | K &key, V &val);
44 |
45 | K key() const;
46 | V val() const;
47 |
48 | version_t version() const;
49 | bool used() const;
50 |
51 | class reuse
52 | {
53 | public:
54 | bool operator()(const item &item) const
55 | {
56 | return !item.used();
57 | }
58 | };
59 |
60 | private:
61 | /** Even versions are reusable, odd versions are in use. */
62 | std::atomic m_version;
63 | K m_key;
64 | V m_val;
65 | };
66 |
67 | #include "item_inl.h"
68 |
69 | }
70 |
71 | #endif /* __ITEM_H */
72 |
--------------------------------------------------------------------------------
/src/components/item_inl.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2014 Jakob Gruber
3 | *
4 | * This file is part of kpqueue.
5 | *
6 | * kpqueue is free software: you can redistribute it and/or modify
7 | * it under the terms of the GNU General Public License as published by
8 | * the Free Software Foundation, either version 3 of the License, or
9 | * (at your option) any later version.
10 | *
11 | * kpqueue is distributed in the hope that it will be useful,
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | * GNU General Public License for more details.
15 | *
16 | * You should have received a copy of the GNU General Public License
17 | * along with kpqueue. If not, see .
18 | */
19 |
20 | template
21 | item::item() :
22 | m_version(0)
23 | {
24 | }
25 |
26 | template
27 | void
28 | item::initialize(const K &key, const V &val)
29 | {
30 | assert(!used());
31 |
32 | m_version.fetch_add(1, std::memory_order_relaxed); /* TODO: Really relaxed? */
33 | m_key = key;
34 | m_val = val;
35 |
36 | assert(used());
37 | }
38 |
39 | template
40 | bool
41 | item::take(const version_t version,
42 | K &key, V &val)
43 | {
44 | key = m_key;
45 | val = m_val;
46 |
47 | version_t expected = version;
48 | return m_version.compare_exchange_strong(expected,
49 | expected + 1,
50 | std::memory_order_relaxed);
51 | }
52 |
53 | template
54 | bool
55 | item::take(const version_t version,
56 | V &val)
57 | {
58 | K key;
59 | return take(version, key, val);
60 | }
61 |
62 | template
63 | K
64 | item::key() const
65 | {
66 | return m_key;
67 | }
68 |
69 | template
70 | V
71 | item::val() const
72 | {
73 | return m_val;
74 | }
75 |
76 | template
77 | version_t
78 | item::version() const
79 | {
80 | return m_version.load(std::memory_order_relaxed);
81 | }
82 |
83 | template
84 | bool
85 | item::used() const
86 | {
87 | return ((version() & 0x1) == 1);
88 | }
89 |
--------------------------------------------------------------------------------
/src/dist_lsm/dist_lsm.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2014 Jakob Gruber
3 | *
4 | * This file is part of kpqueue.
5 | *
6 | * kpqueue is free software: you can redistribute it and/or modify
7 | * it under the terms of the GNU General Public License as published by
8 | * the Free Software Foundation, either version 3 of the License, or
9 | * (at your option) any later version.
10 | *
11 | * kpqueue is distributed in the hope that it will be useful,
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | * GNU General Public License for more details.
15 | *
16 | * You should have received a copy of the GNU General Public License
17 | * along with kpqueue. If not, see .
18 | */
19 |
20 | #ifndef __DIST_LSM_H
21 | #define __DIST_LSM_H
22 |
23 | #include "dist_lsm_local.h"
24 | #include "shared_lsm/shared_lsm.h"
25 |
26 | namespace kpq
27 | {
28 |
29 | template
30 | class dist_lsm
31 | {
32 | friend int dist_lsm_local::spy(dist_lsm *parent);
33 |
34 | public:
35 |
36 | /**
37 | * Inserts a new item into the local LSM.
38 | */
39 | void insert(const K &key);
40 | void insert(const K &key,
41 | const V &val);
42 |
43 | /**
44 | * A special version of insert for use by the k-lsm. Acts like a standard
45 | * insert until the largest block exceeds the relaxation size limit, at which
46 | * point the block is inserted into the shared lsm instead.
47 | */
48 | void insert(const K &key,
49 | const V &val,
50 | shared_lsm *slsm);
51 |
52 | /**
53 | * Attempts to remove the locally (i.e. on the current thread) minimal item.
54 | * If the local LSM is empty, we try to copy items from another active thread.
55 | * In case the local LSM is still empty, false is returned.
56 | * If a locally minimal element is successfully found and removed, true is returned.
57 | */
58 | bool delete_min(V &val);
59 | bool delete_min(K &key, V &val);
60 | void find_min(typename block::peek_t &best);
61 |
62 | int spy();
63 |
64 | void print();
65 |
66 | void init_thread(const size_t) const { }
67 | constexpr static bool supports_concurrency() { return true; }
68 |
69 | private:
70 | thread_local_ptr> m_local;
71 | };
72 |
73 | #include "dist_lsm_inl.h"
74 |
75 | }
76 |
77 | #endif /* __DIST_LSM_H */
78 |
--------------------------------------------------------------------------------
/src/dist_lsm/dist_lsm_inl.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2014 Jakob Gruber
3 | *
4 | * This file is part of kpqueue.
5 | *
6 | * kpqueue is free software: you can redistribute it and/or modify
7 | * it under the terms of the GNU General Public License as published by
8 | * the Free Software Foundation, either version 3 of the License, or
9 | * (at your option) any later version.
10 | *
11 | * kpqueue is distributed in the hope that it will be useful,
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | * GNU General Public License for more details.
15 | *
16 | * You should have received a copy of the GNU General Public License
17 | * along with kpqueue. If not, see .
18 | */
19 |
20 | template
21 | void
22 | dist_lsm::insert(const K &key)
23 | {
24 | insert(key, key);
25 | }
26 |
27 | template
28 | void
29 | dist_lsm::insert(const K &key,
30 | const V &val)
31 | {
32 | m_local.get()->insert(key, val, nullptr);
33 | }
34 |
35 | template
36 | void
37 | dist_lsm::insert(const K &key,
38 | const V &val,
39 | shared_lsm *slsm)
40 | {
41 | m_local.get()->insert(key, val, slsm);
42 | }
43 |
44 | template
45 | bool
46 | dist_lsm::delete_min(V &val)
47 | {
48 | return m_local.get()->delete_min(this, val);
49 | }
50 |
51 | template
52 | bool
53 | dist_lsm::delete_min(K &key, V &val)
54 | {
55 | return m_local.get()->delete_min(this, key, val);
56 | }
57 |
58 | template
59 | void
60 | dist_lsm::find_min(typename block::peek_t &best)
61 | {
62 | m_local.get()->peek(best);
63 | }
64 |
65 | template
66 | int
67 | dist_lsm::spy()
68 | {
69 | return m_local.get()->spy(this);
70 | }
71 |
72 | template
73 | void
74 | dist_lsm::print()
75 | {
76 | for (size_t i = 0; i < m_local.num_threads(); i++) {
77 | m_local.get(i)->print();
78 | }
79 | }
80 |
--------------------------------------------------------------------------------
/src/k_lsm/k_lsm.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2015 Jakob Gruber
3 | *
4 | * This file is part of kpqueue.
5 | *
6 | * kpqueue is free software: you can redistribute it and/or modify
7 | * it under the terms of the GNU General Public License as published by
8 | * the Free Software Foundation, either version 3 of the License, or
9 | * (at your option) any later version.
10 | *
11 | * kpqueue is distributed in the hope that it will be useful,
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | * GNU General Public License for more details.
15 | *
16 | * You should have received a copy of the GNU General Public License
17 | * along with kpqueue. If not, see .
18 | */
19 |
20 | #ifndef __K_LSM_H
21 | #define __K_LSM_H
22 |
23 | #include "dist_lsm/dist_lsm.h"
24 | #include "shared_lsm/shared_lsm.h"
25 | #include "util/counters.h"
26 |
27 | namespace kpq {
28 |
29 | /**
30 | * The k-lsm combines the distributed- and shared lsm data structures
31 | * in order to emphasize their respective strenghts. Items are initially
32 | * inserted into (thread-local) distributed lsm's until the relaxation
33 | * limit is reached, at which point the contained item's are inserted
34 | * into the shared lsm component.
35 | *
36 | * As always, K, V and Rlx denote, respectively, the key, value classes
37 | * and the relaxation parameter.
38 | */
39 |
40 | template
41 | class k_lsm {
42 | public:
43 | k_lsm();
44 | virtual ~k_lsm() { }
45 |
46 | void insert(const K &key);
47 | void insert(const K &key,
48 | const V &val);
49 |
50 | bool delete_min(V &val);
51 | bool delete_min(K &key, V &val);
52 |
53 | void init_thread(const size_t) const { }
54 | constexpr static bool supports_concurrency() { return true; }
55 |
56 | private:
57 | dist_lsm m_dist;
58 | shared_lsm m_shared;
59 | };
60 |
61 | #include "k_lsm_inl.h"
62 |
63 | }
64 |
65 | #endif /* __K_LSM_H */
66 |
--------------------------------------------------------------------------------
/src/multi_lsm/multi_lsm.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2015 Jakob Gruber
3 | *
4 | * This file is part of kpqueue.
5 | *
6 | * kpqueue is free software: you can redistribute it and/or modify
7 | * it under the terms of the GNU General Public License as published by
8 | * the Free Software Foundation, either version 3 of the License, or
9 | * (at your option) any later version.
10 | *
11 | * kpqueue is distributed in the hope that it will be useful,
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | * GNU General Public License for more details.
15 | *
16 | * You should have received a copy of the GNU General Public License
17 | * along with kpqueue. If not, see .
18 | */
19 |
20 | #ifndef __MULTI_LSM_H
21 | #define __MULTI_LSM_H
22 |
23 | #include "dist_lsm/dist_lsm_local.h"
24 | #include "util/counters.h"
25 | #include "util/thread_local_ptr.h"
26 |
27 | namespace kpq {
28 |
29 | template
30 | class multi_lsm {
31 | public:
32 | multi_lsm(const size_t num_threads);
33 | virtual ~multi_lsm();
34 |
35 | void insert(const K &key);
36 | void insert(const K &key,
37 | const V &val);
38 |
39 | bool delete_min(V &val);
40 |
41 | void init_thread(const size_t) const { set_tid(); }
42 | constexpr static bool supports_concurrency() { return true; }
43 |
44 | private:
45 | /** Relaxation is meaningless when there is no slsm. */
46 | static constexpr int DUMMY_RELAXATION = (1 << 20);
47 |
48 | dist_lsm_local *random_local_queue() const;
49 | dist_lsm_local *random_queue() const;
50 |
51 | private:
52 | const size_t m_num_threads;
53 | const size_t m_num_queues;
54 |
55 | dist_lsm_local *m_dist;
56 | };
57 |
58 | #include "multi_lsm_inl.h"
59 |
60 | }
61 |
62 | #endif /* __MULTI_LSM_H */
63 |
--------------------------------------------------------------------------------
/src/sequential_lsm/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | add_library(sequential_lsm STATIC
2 | lsm.cpp
3 | )
--------------------------------------------------------------------------------
/src/sequential_lsm/lsm.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2014 Jakob Gruber
3 | *
4 | * This file is part of kpqueue.
5 | *
6 | * kpqueue is free software: you can redistribute it and/or modify
7 | * it under the terms of the GNU General Public License as published by
8 | * the Free Software Foundation, either version 3 of the License, or
9 | * (at your option) any later version.
10 | *
11 | * kpqueue is distributed in the hope that it will be useful,
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | * GNU General Public License for more details.
15 | *
16 | * You should have received a copy of the GNU General Public License
17 | * along with kpqueue. If not, see .
18 | */
19 |
20 | #ifndef __LSM_H
21 | #define __LSM_H
22 |
23 | #include
24 | #include
25 | #include
26 |
27 | namespace kpq
28 | {
29 |
30 | template
31 | class LSMBlock;
32 |
33 | template
34 | class LSM
35 | {
36 | public:
37 | LSM();
38 | ~LSM();
39 |
40 | void insert(const T &k, const T &v);
41 | bool delete_min(T &v);
42 | void clear();
43 |
44 | void print() const;
45 |
46 | void init_thread(const size_t) const { }
47 | constexpr static bool supports_concurrency() { return false; }
48 |
49 | private:
50 | /** Returns an unused block of size n == 2^i. */
51 | LSMBlock