├── .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 *unused_block(const int n); 52 | void prune_last_block(); 53 | 54 | void insert_between(LSMBlock *new_block, 55 | LSMBlock *prev, 56 | LSMBlock *next); 57 | 58 | private: 59 | LSMBlock *m_head; /**< The smallest block in the list. */ 60 | 61 | /** A list of all allocated blocks. The two blocks of size 2^i 62 | * are stored in m_blocks[i]. */ 63 | std::vector *, LSMBlock *>> m_blocks; 64 | }; 65 | 66 | } 67 | 68 | #endif /* __LSM_H */ 69 | -------------------------------------------------------------------------------- /src/shared_lsm/aligned_block_array.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 __ALIGNED_BLOCK_ARRAY_H 21 | #define __ALIGNED_BLOCK_ARRAY_H 22 | 23 | #include 24 | 25 | #include "block_array.h" 26 | 27 | namespace kpq { 28 | 29 | constexpr static int DEFAULT_ALIGNMENT = 2048; 30 | 31 | /** 32 | * Wraps allocation of a block array instance aligned to a specific amount. 33 | * This is needed since we partially pack an array's version into its pointer 34 | * in order to avoid the ABA problem when we compare and swap the global array 35 | * pointer. 36 | * Algn must be a power of two. 37 | */ 38 | template 39 | class aligned_block_array { 40 | public: 41 | aligned_block_array(); 42 | virtual ~aligned_block_array(); 43 | 44 | block_array *ptr() const { return m_ptr; } 45 | 46 | private: 47 | constexpr static size_t ARRAY_SIZE = sizeof(block_array); 48 | constexpr static size_t BUFFER_SIZE = Algn + ARRAY_SIZE; 49 | 50 | block_array *m_ptr; 51 | uint8_t m_buffer[BUFFER_SIZE]; 52 | }; 53 | 54 | #include "aligned_block_array_inl.h" 55 | 56 | } 57 | 58 | #endif /* __ALIGNED_BLOCK_ARRAY_H */ 59 | -------------------------------------------------------------------------------- /src/shared_lsm/aligned_block_array_inl.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 | #ifdef __GNUC__ 21 | #include 22 | #endif 23 | 24 | template 25 | aligned_block_array::aligned_block_array() 26 | { 27 | void *buf_ptr = m_buffer; 28 | 29 | #ifdef __GNUC__ 30 | #if __GNUC_PREREQ(5, 0) 31 | size_t buf_size = BUFFER_SIZE; 32 | void *aligned_ptr = std::align(Algn, ARRAY_SIZE, buf_ptr, buf_size); 33 | #else 34 | void *aligned_ptr = (void *)((((intptr_t) buf_ptr) + Algn - 1) & ~(Algn - 1)); 35 | #endif 36 | #endif 37 | assert(aligned_ptr != nullptr); 38 | assert(((intptr_t)aligned_ptr & (Algn - 1)) == 0); 39 | 40 | m_ptr = new (aligned_ptr) block_array(); 41 | } 42 | 43 | template 44 | aligned_block_array::~aligned_block_array() 45 | { 46 | m_ptr->~block_array(); 47 | } 48 | -------------------------------------------------------------------------------- /src/shared_lsm/block_array.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 __BLOCK_ARRAY_H 21 | #define __BLOCK_ARRAY_H 22 | 23 | #include 24 | #include 25 | #include 26 | 27 | #include "components/block.h" 28 | #include "util/counters.h" 29 | #include "util/xorshf96.h" 30 | #include "block_pivots.h" 31 | #include "block_pool.h" 32 | 33 | namespace kpq { 34 | 35 | template 36 | class block_array { 37 | /* For access to blocks during publishing. */ 38 | template 39 | friend class shared_lsm_local; 40 | public: 41 | static constexpr size_t MAX_BLOCKS = 32; 42 | 43 | block_array(); 44 | virtual ~block_array(); 45 | 46 | /** May only be called when this block is not visible to other threads. */ 47 | void insert(block *block, 48 | block_pool *pool); 49 | 50 | /** Callable from other threads. */ 51 | bool delete_min(V &val); 52 | typename block::peek_t peek(); 53 | 54 | /** Copies the given block array into the current instance. 55 | * The copy is shallow, i.e. only block pointers are copied. */ 56 | void copy_from(const block_array *that); 57 | 58 | version_t version() const { return m_version.load(std::memory_order_relaxed); } 59 | void increment_version() { m_version.fetch_add(1, std::memory_order_relaxed); } 60 | 61 | private: 62 | /** May only be called when this block is not visible to other threads. */ 63 | void compact(block_pool *pool); 64 | void remove_null_blocks(); 65 | 66 | /** Utility functions for mutating blocks together with pivots. */ 67 | void block_insert(const size_t block_ix, block *block); 68 | void block_set(const size_t block_ix, block *block); 69 | 70 | private: 71 | 72 | /** Stores block pointers from largest to smallest (to stay consistent with 73 | * clsm_local). The usual invariants (block size strictly descending, only 74 | * one block of each size in array) are preserved while the block array is 75 | * visible to other threads. 76 | */ 77 | block *m_blocks[MAX_BLOCKS]; 78 | size_t m_size; 79 | 80 | block_pivots m_pivots; 81 | 82 | std::atomic m_version; 83 | 84 | xorshf96 m_gen; 85 | }; 86 | 87 | #include "block_array_inl.h" 88 | 89 | } 90 | 91 | #endif /* __BLOCK_ARRAY_H */ 92 | -------------------------------------------------------------------------------- /src/shared_lsm/shared_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 __SHARED_LSM_H 21 | #define __SHARED_LSM_H 22 | 23 | #include "util/mm.h" 24 | #include "util/thread_local_ptr.h" 25 | #include "block_array.h" 26 | #include "block_pool.h" 27 | #include "shared_lsm_local.h" 28 | #include "versioned_array_ptr.h" 29 | 30 | namespace kpq { 31 | 32 | /** 33 | * The shared lsm is a relaxed priority queue which is based on maintaining 34 | * a single global array of blocks. 35 | * 36 | * TODO: Local ordering semantics using bloom filters. 37 | * TODO: Logical (instead of physical) shrinking of blocks. 38 | */ 39 | 40 | template 41 | class shared_lsm { 42 | public: 43 | shared_lsm(); 44 | virtual ~shared_lsm() { } 45 | 46 | void insert(const K &key); 47 | void insert(const K &key, 48 | const V &val); 49 | void insert(block *b); 50 | 51 | bool delete_min(V &val); 52 | void find_min(typename block::peek_t &best); 53 | 54 | void init_thread(const size_t) const { } 55 | constexpr static bool supports_concurrency() { return true; } 56 | 57 | private: 58 | versioned_array_ptr m_global_array; 59 | thread_local_ptr> m_local_component; 60 | }; 61 | 62 | #include "shared_lsm_inl.h" 63 | 64 | } 65 | 66 | #endif /* __SHARED_LSM_H */ 67 | -------------------------------------------------------------------------------- /src/shared_lsm/shared_lsm_inl.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 | template 21 | shared_lsm::shared_lsm() 22 | { 23 | } 24 | 25 | template 26 | void 27 | shared_lsm::insert(const K &key) 28 | { 29 | insert(key, key); 30 | } 31 | 32 | template 33 | void 34 | shared_lsm::insert(const K &key, 35 | const V &val) 36 | { 37 | auto local = m_local_component.get(); 38 | local->insert(key, val, m_global_array); 39 | } 40 | 41 | template 42 | void 43 | shared_lsm::insert(block *b) 44 | { 45 | auto local = m_local_component.get(); 46 | local->insert(b, m_global_array); 47 | } 48 | 49 | template 50 | bool 51 | shared_lsm::delete_min(V &val) 52 | { 53 | auto local = m_local_component.get(); 54 | return local->delete_min(val, m_global_array); 55 | } 56 | 57 | template 58 | void 59 | shared_lsm::find_min(typename block::peek_t &best) 60 | { 61 | auto local = m_local_component.get(); 62 | local->peek(best, m_global_array); 63 | } 64 | -------------------------------------------------------------------------------- /src/shared_lsm/versioned_array_ptr.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 __VERSIONED_ARRAY_PTR_H 21 | #define __VERSIONED_ARRAY_PTR_H 22 | 23 | #include 24 | 25 | #include "aligned_block_array.h" 26 | #include "block_array.h" 27 | 28 | namespace kpq { 29 | 30 | template 31 | class versioned_array_ptr { 32 | public: 33 | versioned_array_ptr(); 34 | virtual ~versioned_array_ptr(); 35 | 36 | /* Interface subject to change. */ 37 | block_array *load(); 38 | block_array *load_packed(); 39 | bool compare_exchange_strong( 40 | block_array *&expected_packed, 41 | aligned_block_array &desired); 42 | 43 | version_t version(); 44 | 45 | block_array *unpack(block_array *ptr) 46 | { 47 | return unpacked_ptr(ptr); 48 | } 49 | 50 | /** Returns true, iff the packed version in ptr possibly matches the 51 | * given version. */ 52 | static bool matches(block_array *ptr, 53 | version_t version); 54 | 55 | private: 56 | static block_array *packed_ptr(block_array *ptr); 57 | static block_array *unpacked_ptr(block_array *ptr); 58 | 59 | private: 60 | constexpr static int MASK = Algn - 1; 61 | 62 | std::atomic *> m_ptr; 63 | 64 | /** The block array used to initialize the global pointer. */ 65 | aligned_block_array m_initial_value; 66 | }; 67 | 68 | #include "versioned_array_ptr_inl.h" 69 | 70 | } 71 | 72 | #endif /* __VERSIONED_ARRAY_PTR_H */ 73 | -------------------------------------------------------------------------------- /src/shared_lsm/versioned_array_ptr_inl.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 | #include 21 | 22 | template 23 | versioned_array_ptr::versioned_array_ptr() 24 | { 25 | m_ptr = packed_ptr(m_initial_value.ptr()); 26 | } 27 | 28 | template 29 | versioned_array_ptr::~versioned_array_ptr() 30 | { 31 | } 32 | 33 | template 34 | bool 35 | versioned_array_ptr::matches( 36 | block_array *ptr, 37 | version_t version) 38 | { 39 | return ((intptr_t)ptr & MASK) == (version & MASK); 40 | } 41 | 42 | template 43 | block_array * 44 | versioned_array_ptr::packed_ptr( 45 | block_array *ptr) 46 | { 47 | const intptr_t intptr = (intptr_t)ptr; 48 | assert((intptr & MASK) == 0); 49 | return (block_array *)(intptr | (ptr->version() & MASK)); 50 | } 51 | 52 | template 53 | block_array * 54 | versioned_array_ptr::unpacked_ptr( 55 | block_array *ptr) 56 | { 57 | const intptr_t intptr = (intptr_t)ptr; 58 | return (block_array *)(intptr & ~MASK); 59 | } 60 | 61 | template 62 | block_array * 63 | versioned_array_ptr::load() 64 | { 65 | return unpacked_ptr(load_packed()); 66 | } 67 | 68 | template 69 | version_t 70 | versioned_array_ptr::version() 71 | { 72 | return load()->version(); 73 | } 74 | 75 | template 76 | block_array * 77 | versioned_array_ptr::load_packed() 78 | { 79 | return m_ptr.load(std::memory_order_relaxed); 80 | } 81 | 82 | template 83 | bool 84 | versioned_array_ptr::compare_exchange_strong( 85 | block_array *&expected_packed, 86 | aligned_block_array &desired) 87 | { 88 | return m_ptr.compare_exchange_strong(expected_packed, 89 | packed_ptr(desired.ptr()), 90 | std::memory_order_relaxed); 91 | } 92 | -------------------------------------------------------------------------------- /src/util/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | include_directories( 2 | ${CMAKE_CURRENT_SOURCE_DIR} 3 | ) 4 | 5 | if(CMAKE_COMPILER_IS_GNUCXX) 6 | add_definitions("-flto") 7 | endif() 8 | 9 | add_library(thread_local_ptr STATIC 10 | thread_local_ptr.cpp 11 | ) 12 | -------------------------------------------------------------------------------- /src/util/counters.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 __COUNTERS_H 21 | #define __COUNTERS_H 22 | 23 | #include 24 | #include 25 | #include 26 | 27 | #define V(D) \ 28 | D(inserts) \ 29 | D(successful_deletes) \ 30 | D(failed_deletes) \ 31 | D(slsm_inserts) /* Block inserts into shared lsm. */ \ 32 | D(slsm_insert_retries) /* Block insert retries through concurrent modification. */ \ 33 | D(slsm_deletes) \ 34 | D(dlsm_deletes) \ 35 | D(slsm_peek_cache_hit) /* Number of times the cached item is returned by the slsm. */ \ 36 | D(slsm_peeks_performed) /* Number of times we got past the cached item. */ \ 37 | D(slsm_peek_attempts) /* Number of actual block array peek() calls. */ \ 38 | D(block_shrinks) \ 39 | D(pivot_shrinks) \ 40 | D(pivot_grows) \ 41 | D(successful_peeks) \ 42 | D(failed_peeks) \ 43 | D(requested_spies) \ 44 | D(aborted_spies) 45 | 46 | namespace kpq 47 | { 48 | 49 | /** 50 | * Very simple performance counters. 51 | */ 52 | 53 | struct counters 54 | { 55 | counters() 56 | { 57 | memset(this, 0, sizeof(*this)); 58 | } 59 | 60 | counters &operator+=(const counters &that) 61 | { 62 | #define D_OP_ADD(C) C += that.C; 63 | V(D_OP_ADD) 64 | #undef D_OP_ADD 65 | 66 | return *this; 67 | } 68 | 69 | size_t operations() const { 70 | return inserts + successful_deletes + failed_deletes; 71 | } 72 | 73 | void print() const { 74 | #define D_PRINT_FORMAT(C) #C ": %lu\n" 75 | #define D_PRINT_ARGS(C) C, 76 | printf(V(D_PRINT_FORMAT) "%s", 77 | V(D_PRINT_ARGS) ""); 78 | #undef D_PRINT_ARGS 79 | #undef D_PRINT_FORMAT 80 | } 81 | 82 | #define D_DECL(C) size_t C; 83 | V(D_DECL) 84 | #undef D_DECL 85 | 86 | #ifdef ENABLE_QUALITY 87 | /** Two special-case members which are used to store thread-local sequences 88 | * of insertions and deletions for the quality benchmark. */ 89 | void *insertion_sequence; 90 | void *deletion_sequence; 91 | #endif 92 | }; 93 | 94 | thread_local counters COUNTERS; 95 | 96 | #define ENABLE_COUNTERS 1 97 | 98 | #ifndef ENABLE_COUNTERS 99 | #define COUNT_INC(C) 100 | #else 101 | #define COUNT_INC(C) kpq::COUNTERS.C++ 102 | #endif 103 | 104 | } 105 | 106 | #endif /* __COUNTERS_H */ 107 | -------------------------------------------------------------------------------- /src/util/lockfree_vector.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 __LOCKFREE_VECTOR_H 21 | #define __LOCKFREE_VECTOR_H 22 | 23 | #include 24 | #include 25 | 26 | namespace kpq 27 | { 28 | 29 | /** A lock-free vector of dynamic size, capable of holding up to 2^bucket_count 30 | * elements. Allocated memory is freed only on destruction. The amount of memory 31 | * used is determined by the highest n passed to get(). */ 32 | 33 | template 34 | class lockfree_vector 35 | { 36 | public: 37 | static constexpr int bucket_count = 32; 38 | 39 | lockfree_vector() 40 | { 41 | for (int i = 0; i < bucket_count; i++) { 42 | m_buckets[i] = nullptr; 43 | } 44 | } 45 | 46 | virtual ~lockfree_vector() 47 | { 48 | for (int i = 0; i < bucket_count; i++) { 49 | if (m_buckets[i] != nullptr) { 50 | delete[] m_buckets[i]; 51 | } 52 | } 53 | } 54 | 55 | T *get(const int n) 56 | { 57 | const int i = index_of(n); 58 | 59 | T *bucket = m_buckets[i].load(std::memory_order_relaxed); 60 | if (bucket == nullptr) { 61 | bucket = new T[1 << i]; 62 | T *expected = nullptr; 63 | if (!m_buckets[i].compare_exchange_strong(expected, bucket)) { 64 | delete[] bucket; 65 | bucket = expected; 66 | assert(bucket != nullptr); 67 | } 68 | } 69 | 70 | return &bucket[n + 1 - (1 << i)]; 71 | } 72 | 73 | private: 74 | static int index_of(const int n) 75 | { 76 | /* We could optimize this for 64/32 bit ints. */ 77 | 78 | int i = n + 1; 79 | int log = 0; 80 | 81 | while (i > 1) { 82 | i >>= 1; 83 | log++; 84 | } 85 | 86 | assert(log < bucket_count); 87 | 88 | return log; 89 | } 90 | 91 | private: 92 | std::atomic m_buckets[bucket_count]; 93 | }; 94 | 95 | } 96 | 97 | #endif /* __LOCKFREE_VECTOR_H */ 98 | -------------------------------------------------------------------------------- /src/util/thread_local_ptr.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 "thread_local_ptr.h" 21 | 22 | namespace kpq 23 | { 24 | 25 | /** An artificial thread id which can be used to index into the array of items. */ 26 | static constexpr int32_t TID_UNSET = -1; 27 | static thread_local int32_t m_tid = TID_UNSET; 28 | static std::atomic m_max_tid(0); 29 | 30 | void 31 | set_tid() 32 | { 33 | if (m_tid == TID_UNSET) { 34 | m_tid = m_max_tid.fetch_add(1, std::memory_order_relaxed); 35 | } 36 | } 37 | 38 | int32_t 39 | tid() 40 | { 41 | return m_tid; 42 | } 43 | 44 | int32_t 45 | max_tid() 46 | { 47 | return m_max_tid.load(std::memory_order_relaxed); 48 | } 49 | 50 | } 51 | -------------------------------------------------------------------------------- /src/util/thread_local_ptr.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 __THREAD_LOCAL_PTR_H 21 | #define __THREAD_LOCAL_PTR_H 22 | 23 | #include 24 | #include 25 | 26 | #include "lockfree_vector.h" 27 | 28 | namespace kpq 29 | { 30 | 31 | void set_tid(); 32 | int32_t tid(); 33 | int32_t max_tid(); 34 | 35 | /** 36 | * A thread-local pointer to an element of type T, based on a dynamically growing 37 | * array and the current thread id. 38 | */ 39 | 40 | template 41 | class thread_local_ptr 42 | { 43 | public: 44 | T *get() 45 | { 46 | set_tid(); 47 | return get(tid()); 48 | } 49 | 50 | T *get(const int32_t tid) 51 | { 52 | assert(tid < max_tid()); 53 | return m_items.get(tid); 54 | } 55 | 56 | /** Returns the current thread id. */ 57 | static size_t current_thread() 58 | { 59 | return tid(); 60 | } 61 | 62 | /** Returns the current thread count. */ 63 | static size_t num_threads() 64 | { 65 | return max_tid(); 66 | } 67 | 68 | private: 69 | lockfree_vector m_items; 70 | }; 71 | 72 | } 73 | 74 | #endif /* __THREAD_LOCAL_PTR_H */ 75 | -------------------------------------------------------------------------------- /src/util/xorshf96.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 __XORSHF96_H 21 | #define __XORSHF96_H 22 | 23 | #include 24 | #include 25 | 26 | namespace kpq 27 | { 28 | 29 | /** 30 | * Fast Marsaglia xorshf random number generator. 31 | */ 32 | 33 | class xorshf96 34 | { 35 | public: 36 | typedef uint64_t result_type; 37 | static constexpr result_type min() { return std::numeric_limits::min(); } 38 | static constexpr result_type max() { return std::numeric_limits::max(); } 39 | 40 | xorshf96() 41 | { 42 | const auto d = std::chrono::high_resolution_clock::now().time_since_epoch(); 43 | x = std::chrono::duration_cast(d).count(); 44 | } 45 | 46 | xorshf96(const uint64_t seed) 47 | { 48 | x = seed; 49 | } 50 | 51 | uint64_t operator()() 52 | { 53 | x ^= x << 16; 54 | x ^= x >> 5; 55 | x ^= x << 1; 56 | 57 | uint64_t t = x; 58 | x = y; 59 | y = z; 60 | z = t ^ x ^ y; 61 | 62 | return z; 63 | } 64 | 65 | private: 66 | uint64_t x = 123456789; 67 | uint64_t y = 362436069; 68 | uint64_t z = 521288629; 69 | }; 70 | 71 | } 72 | 73 | #endif /* __XORSHF96_H */ 74 | -------------------------------------------------------------------------------- /test/.gitignore: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/klsmpq/klsm/1fa9cd0bd0c63a17844fc2954c52b60d8f71f340/test/.gitignore -------------------------------------------------------------------------------- /test/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | add_subdirectory(shared_lsm) 2 | add_subdirectory(util) 3 | 4 | include_directories( 5 | ${CMAKE_SOURCE_DIR}/src 6 | ${GTEST_INCLUDE_DIR} 7 | ) 8 | 9 | add_executable(pq-par-test pq_par.cpp) 10 | target_link_libraries(pq-par-test 11 | gtest 12 | thread_local_ptr 13 | ) 14 | add_test(NAME pq-par-test COMMAND pq-par-test) 15 | 16 | add_executable(pq-seq-test pq_seq.cpp) 17 | target_link_libraries(pq-seq-test 18 | gtest 19 | skip_queue 20 | sequence_heap 21 | sequential_lsm 22 | thread_local_ptr 23 | ) 24 | add_test(NAME pq-seq-test COMMAND pq-seq-test) 25 | 26 | add_executable(relaxed-pq-seq-test relaxed_pq_seq.cpp) 27 | target_link_libraries(relaxed-pq-seq-test 28 | gtest 29 | thread_local_ptr 30 | ) 31 | add_test(NAME relaxed-pq-seq-test COMMAND relaxed-pq-seq-test) 32 | -------------------------------------------------------------------------------- /test/shared_lsm/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | include_directories( 2 | ${CMAKE_SOURCE_DIR}/src 3 | ${GTEST_INCLUDE_DIR} 4 | ) 5 | 6 | add_executable(block-array-test block_array.cpp) 7 | target_link_libraries(block-array-test 8 | gtest 9 | thread_local_ptr 10 | ) 11 | add_test(NAME block-array-test COMMAND block-array-test) 12 | 13 | add_executable(versioned-array-ptr-test versioned_array_ptr.cpp) 14 | target_link_libraries(versioned-array-ptr-test 15 | gtest 16 | thread_local_ptr 17 | ) 18 | add_test(NAME versioned-array-ptr-test COMMAND versioned-array-ptr-test) 19 | -------------------------------------------------------------------------------- /test/util/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | include_directories( 2 | ${CMAKE_SOURCE_DIR}/src 3 | ${GTEST_INCLUDE_DIR} 4 | ) 5 | 6 | add_executable(lockfree-vector-test lockfree_vector.cpp) 7 | target_link_libraries(lockfree-vector-test 8 | gtest 9 | thread_local_ptr 10 | ) 11 | add_test(NAME lockfree-vector-test COMMAND lockfree-vector-test) 12 | 13 | add_executable(mm-test mm.cpp) 14 | target_link_libraries(mm-test 15 | gtest 16 | ) 17 | add_test(NAME mm-test COMMAND mm-test) 18 | 19 | add_executable(thread-local-ptr-test thread_local_ptr.cpp) 20 | target_link_libraries(thread-local-ptr-test 21 | gtest 22 | thread_local_ptr 23 | ) 24 | add_test(NAME thread-local-ptr-test COMMAND thread-local-ptr-test) 25 | -------------------------------------------------------------------------------- /test/util/mm.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 21 | 22 | #include "util/mm.h" 23 | 24 | struct simple_reuse { 25 | bool operator()(const uint32_t &) const 26 | { 27 | return false; 28 | } 29 | }; 30 | 31 | struct reuse_above_42 { 32 | bool operator()(const uint32_t &v) const 33 | { 34 | return (v > 42); 35 | } 36 | }; 37 | 38 | TEST(MMTest, SanityCheck) 39 | { 40 | kpq::item_allocator alloc; 41 | } 42 | 43 | TEST(MMTest, AllocOne) 44 | { 45 | kpq::item_allocator alloc; 46 | ASSERT_NE(alloc.acquire(), nullptr); 47 | } 48 | 49 | TEST(MMTest, AllocMany) 50 | { 51 | kpq::item_allocator alloc; 52 | 53 | for (int i = 0; i < 66; i++) { 54 | } 55 | } 56 | 57 | /** 58 | * Verifies that a reusable item is actually reused, and non-reusable items 59 | * aren't. The block size is set to ITERATIONS, which should ensure that 60 | * the reusable item (in this case marked as usable by having a value 61 | * greater than 42) is reused. 62 | */ 63 | TEST(MMTest, ReuseCheck) 64 | { 65 | static constexpr size_t ITERATIONS = 42; 66 | kpq::item_allocator alloc; 67 | 68 | std::vector xs; 69 | 70 | for (size_t i = 0; i < ITERATIONS; i++) { 71 | uint32_t *x = alloc.acquire(); 72 | *x = i; 73 | 74 | /* No reuse below 42. */ 75 | for (size_t j = 0; j < i; j++) { 76 | ASSERT_NE(x, xs[j]); 77 | } 78 | 79 | xs.push_back(x); 80 | } 81 | 82 | uint32_t *y = alloc.acquire(); 83 | *y = 66; 84 | 85 | bool reused = false; 86 | for (size_t i = 0; i < ITERATIONS + 1; i++) { 87 | uint32_t *x = alloc.acquire(); 88 | *x = 0; 89 | 90 | if (x == y) { 91 | reused = true; 92 | break; 93 | } 94 | } 95 | 96 | /* No reuse below 42. */ 97 | for (size_t i = 0; i < ITERATIONS; i++) { 98 | ASSERT_EQ(i, *xs[i]); 99 | } 100 | 101 | ASSERT_TRUE(reused); 102 | } 103 | 104 | int 105 | main(int argc, 106 | char **argv) 107 | { 108 | ::testing::InitGoogleTest(&argc, argv); 109 | return RUN_ALL_TESTS(); 110 | } 111 | -------------------------------------------------------------------------------- /test/util/thread_local_ptr.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 21 | #include 22 | 23 | #include "util/thread_local_ptr.h" 24 | 25 | TEST(ThreadLocalPtrTest, SanityCheck) 26 | { 27 | kpq::thread_local_ptr p; 28 | ASSERT_NE(p.get(), nullptr); 29 | } 30 | 31 | static void 32 | write_local(kpq::thread_local_ptr *p, 33 | const int i, 34 | std::atomic *can_continue, 35 | uint32_t **result) 36 | { 37 | while (!can_continue->load(std::memory_order_relaxed)) { 38 | /* Try to start all threads more or less at once to encourage collisions. */ 39 | } 40 | 41 | uint32_t *x = p->get(); 42 | ASSERT_NE(x, nullptr); 43 | 44 | *x = i; 45 | *result = x; 46 | } 47 | 48 | TEST(ThreadLocalPtrTest, ManyThreads) 49 | { 50 | constexpr static int NTHREADS = 1024; 51 | 52 | kpq::thread_local_ptr p; 53 | 54 | std::vector threads(NTHREADS); 55 | std::atomic can_continue(false); 56 | 57 | uint32_t *results[NTHREADS]; 58 | 59 | for (int i = 0; i < NTHREADS; i++) { 60 | threads[i] = std::thread(write_local, &p, i, &can_continue, &results[i]); 61 | } 62 | 63 | can_continue.store(true, std::memory_order_relaxed); 64 | 65 | for (auto &thread : threads) { 66 | thread.join(); 67 | } 68 | 69 | for (int i = 0; i < NTHREADS; i++) { 70 | ASSERT_EQ(*results[i], i); 71 | } 72 | } 73 | 74 | int 75 | main(int argc, 76 | char **argv) 77 | { 78 | ::testing::InitGoogleTest(&argc, argv); 79 | return RUN_ALL_TESTS(); 80 | } 81 | --------------------------------------------------------------------------------