├── .gitignore ├── ChangeLog ├── Doxyfile ├── GNU-LICENSE.txt ├── MIT-LICENSE.txt ├── Makefile ├── Makefile.clang ├── Makefile.common ├── Makefile.gcc ├── Makefile.icc ├── Makefile.suncc ├── README.md ├── abi ├── Makefile ├── Makefile.common ├── abi.c ├── arch_x86.S ├── dtmc │ ├── Makefile │ ├── arch.S │ ├── libitm.h │ ├── libtanger-stm.public-symbols │ ├── libtanger-stm.support │ ├── tanger-stm-internal.h │ ├── tanger.c │ ├── tanger.h │ └── tm_macros.h ├── gcc │ ├── Makefile │ ├── alloc_cpp.c │ ├── arch.S │ ├── clone.c │ ├── eh.c │ ├── libitm.h │ └── tm_macros.h ├── intel │ ├── Makefile │ ├── alloc.c │ ├── arch.S │ ├── libitm.h │ └── tm_macros.h ├── lib.map ├── libitm.h.tpl.cpp ├── libitm.h.tpl.footer ├── libitm.h.tpl.header ├── libitm.h.tpl.unifdef ├── oracle │ ├── Makefile │ ├── arch.S │ └── otm.c ├── pthread_wrapper.h ├── test │ └── Makefile └── tm_macros.h ├── include ├── mod_ab.h ├── mod_cb.h ├── mod_log.h ├── mod_mem.h ├── mod_order.h ├── mod_print.h ├── mod_stats.h ├── stm.h └── wrappers.h ├── lib └── .gitignore ├── src ├── atomic.h ├── 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 ├── gc.c ├── gc.h ├── mod_ab.c ├── mod_cb_mem.c ├── mod_log.c ├── mod_order.c ├── mod_print.c ├── mod_stats.c ├── stm.c ├── stm_internal.h ├── stm_wbctl.h ├── stm_wbetl.h ├── stm_wt.h ├── tls.h ├── utils.h └── wrappers.c └── test ├── Makefile ├── bank ├── .gitignore ├── Makefile └── bank.c ├── intset ├── .gitignore ├── Makefile ├── README.rbtree ├── intset.c ├── rbtree.c ├── rbtree.h ├── tm.h └── types.h └── regression ├── .gitignore ├── Makefile ├── irrevocability.c ├── perf.c └── types.c /.gitignore: -------------------------------------------------------------------------------- 1 | # Compiled objects 2 | *.o 3 | *.so 4 | *.a 5 | # Generated documentation 6 | /doc/ 7 | -------------------------------------------------------------------------------- /ChangeLog: -------------------------------------------------------------------------------- 1 | [unreleased] 2 | 3 | 2014-12-01 Patrick Marlier 4 | * Remove hybrid implementation (ASF) 5 | 6 | [1.0.5 release] 7 | 8 | 2013-01-14 Pascal Felber 9 | * Fixed bugs in garbage collection. 10 | * Added module that for to commit in order (mod_order) 11 | * Added stm_get_specific_tx and stm_set_specific_tx for mod_order. 12 | 13 | [1.0.4 release] 14 | 15 | 2012-10-23 Pascal Felber 16 | * Added MIT license (dual license). 17 | 18 | 2012-03-27 Patrick Marlier 19 | * Split stm.c file for the different strategies (wb-etl/wb-ctl/wt). 20 | 21 | [1.0.3 release] 22 | 23 | 2011-11-17 Patrick Marlier 24 | * Fixed stack saving and minor changes for DTMC (tanger). 25 | 26 | 2011-10-20 Patrick Marlier 27 | * Fixed a bug in tanger_stm_realloc (reported by Luke Dalessandro). 28 | 29 | 2011-02-15 Patrick Marlier 30 | * Fixed a bug in stm_rollback (reported by Rahul Gayatri). 31 | 32 | [1.0.2 release] 33 | 34 | 2011-02-07 Patrick Marlier 35 | * Minor fixes. 36 | * Added stm_get_attribute_tx() for Event Processing. 37 | * Added transactional_safe new/delete operators for GCC-TM. 38 | 39 | 2010-08-10 Patrick Marlier 40 | * ABI uses WRITE_THROUGH by default. 41 | * Added irrevocability management for hybrid ASF mode. 42 | * Disable inlining for tanger load/store due to a LLVM bug. 43 | * Fixed a bug in gc.c (thanks to Walther Maldonado). 44 | * Fixed a bug in mod_log.c (thanks to Adam Cozzette). 45 | 46 | 2010-07-08 Patrick Marlier 47 | * Fixed a bug in stm_commit with CTL (thanks to Srđan Stipić). 48 | 49 | 2010-07-07 Pascal Felber 50 | * Fixed a bug in stm_set_irrevoable when using abort handler. 51 | 52 | [1.0.1 release] 53 | 54 | 2010-06-02 Patrick Marlier 55 | * Added Hybrid TM using AMD ASF. 56 | * Added ABI compatability with Intel STM C Compiler, GCC with TM 57 | support and DTMC. 58 | * Removed outdated Tanger support (now DTMC in ABI). 59 | 60 | 2010-04-29 Pascal Felber 61 | * Added mod_ab module (atomic block statistics). 62 | 63 | [1.0.0 release] 64 | 65 | 2010-02-22 Pascal Felber 66 | * Various fixes and cosmetic changes. 67 | 68 | 2010-01-15 Pascal Felber 69 | * Changed rollover code. 70 | * Added quiescence and serial-irrevocable mode. 71 | 72 | 2009-12-18 Pascal Felber 73 | * Added commit/abort callbacks. 74 | * Various fixes. 75 | 76 | 2009-12-15 Pascal Felber 77 | * Updated irrevocability to work with modular contention manager. 78 | 79 | 2009-11-29 Pascal Felber 80 | * Updated modules to avoid name conflicts. 81 | 82 | 2009-11-20 Pascal Felber 83 | * Changed signature of stm_start(). 84 | * Added irrevocability. 85 | * Added ABI for intel compiler and tm-gcc. 86 | * Fixed a bug in mod_log. 87 | 88 | 2009-09-25 Pascal Felber 89 | * Can disable alternation of insertion/removal in intset. 90 | 91 | 2009-06-10 Pascal Felber 92 | * Added customizable (modular) contention manager. 93 | 94 | 2009-03-08 Pascal Felber 95 | * Added some more statistics. 96 | * Added call to conflict callback upon validation. 97 | 98 | 2009-02-06 Pascal Felber 99 | * Added version number. 100 | * Renamed mod_local module to mod_log and updated code. 101 | 102 | 2009-02-06 Pascal Felber 103 | * Added abort reason as parameter of siglongjmp(). 104 | 105 | [0.9.9 release] 106 | 107 | 2009-01-29 Pascal Felber 108 | * Updated TANGER wrappers. 109 | * Prepared new release. 110 | 111 | 2009-01-17 Pascal Felber 112 | * Added content of README as doxygen documentation. 113 | * Added new version of TANGER wrappers (partial). 114 | * Added region load/store and support for misaligned accesses. 115 | * Bug fixes. 116 | 117 | 2009-01-04 Pascal Felber 118 | * Documented APIs (doxygen comments in include files). 119 | * Cleaned up some APIs, changed parameters of stm_start(). 120 | * CTL now spins while address is locked. 121 | 122 | 2008-12-06 Pascal Felber 123 | * Cleaned up atomic operations and memory barriers. 124 | 125 | 2008-11-26 Pascal Felber 126 | * Documented compile-time options in Makefile 127 | 128 | 2008-11-16 Pascal Felber 129 | * Added support to read previous version of locked data. 130 | * Added support in Makefile for unifdef. 131 | 132 | 2008-07-22 Pascal Felber 133 | * Added epoch-based memory allocator. 134 | * Added conflict tracking and callback. 135 | * Added skip list and refactored intset benchmark 136 | * Added mod_local module. 137 | * Added functions to control extensions and read the clock. 138 | * Added support for unit transactions in intset. 139 | * Many other changes and fixes. 140 | 141 | [0.9.5 release] 142 | 143 | 2008-07-07 Pascal Felber 144 | * Added support for the latest version of STAMP. 145 | * Removed TANGER wrappers (distributed separately). 146 | * Many modifications and fixes. 147 | 148 | 2008-05-26 Pascal Felber 149 | * Added CTL. 150 | 151 | 2008-05-20 Pascal Felber 152 | * Major API changes (no more transaction parameters, etc.). 153 | * Added unit transactions. 154 | * Many other changes and fixes. 155 | 156 | [0.9.0 release] 157 | 158 | 2008-04-25 Pascal Felber 159 | * Removed parameter to stm_new() => transaction cannot be on stack. 160 | 161 | 2008-03-27 Pascal Felber 162 | * Added new module for coarse-grain statistics. 163 | * Added new internal statistics. 164 | * Added new support for reading configuration parameters. 165 | 166 | 2008-03-25 Pascal Felber 167 | * Merged write-back and write-through in a single file. 168 | 169 | 2008-03-16 Pascal Felber 170 | * Refactored dynamic memory management as a module. 171 | 172 | 2008-03-15 Pascal Felber 173 | * Added support for modules. 174 | * Added sample mod_print module. 175 | 176 | 2008-02-13 Pascal Felber 177 | * Improvements to PRIORITY contention manager. 178 | 179 | 2008-01-21 Pascal Felber 180 | * Added BACKOFF contention manager. 181 | 182 | 2008-01-03 Pascal Felber 183 | * Added PRIORITY contention manager. 184 | * Added DELAY contention manager. 185 | * Added bank benchmark. 186 | 187 | 2008-01-01 Pascal Felber 188 | * Initial code base for the VELOX project. 189 | -------------------------------------------------------------------------------- /MIT-LICENSE.txt: -------------------------------------------------------------------------------- 1 | Copyright (c) 2007-2011 2 | Pascal Felber 3 | Patrick Marlier 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining 6 | a copy of this software and associated documentation files (the 7 | "Software"), to deal in the Software without restriction, including 8 | without limitation the rights to use, copy, modify, merge, publish, 9 | distribute, sublicense, and/or sell copies of the Software, and to 10 | permit persons to whom the Software is furnished to do so, subject to 11 | the following conditions: 12 | 13 | The above copyright notice and this permission notice shall be 14 | included in all copies or substantial portions of the Software. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 17 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 18 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 19 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 20 | LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 21 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 22 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 23 | -------------------------------------------------------------------------------- /Makefile.clang: -------------------------------------------------------------------------------- 1 | # Debug/optimization flags (optimized by default) 2 | ifeq ($(CFG),debug) 3 | CFLAGS += -O0 -ggdb3 4 | else 5 | # For Link Time Optimization, it requires gold linker and clang compiled with --enable-gold 6 | # CFLAGS += -O4 7 | # LDFLAGS += -use-gold-plugin 8 | CFLAGS += -O3 9 | CFLAGS += -march=native 10 | endif 11 | 12 | # Enable all warnings but unsused functions and labels 13 | CFLAGS += -Wall 14 | CFLAGS += -Werror -Wno-unused-label -Wno-unused-function 15 | -------------------------------------------------------------------------------- /Makefile.common: -------------------------------------------------------------------------------- 1 | # Path to root directory 2 | ROOT ?= . 3 | 4 | # CC, LD and AR are builtin-variables of Make (?= is useless in this case) 5 | # To override these defines, you must use "make CC=cc" or change it here 6 | # Linker set by default to the CC definition 7 | LD = $(CC) 8 | # Other tools 9 | DOXYGEN ?= doxygen 10 | UNIFDEF ?= unifdef 11 | 12 | # Define global parameters 13 | TM = stm 14 | SRCDIR = $(ROOT)/src 15 | INCDIR = $(ROOT)/include 16 | LIBDIR = $(ROOT)/lib 17 | TMLIB = $(LIBDIR)/lib$(TM).a 18 | 19 | # Supposing all compilers has -I -L 20 | # TODO -I$(SRCDIR) only for library build 21 | CPPFLAGS += -I$(INCDIR) -I$(SRCDIR) 22 | 23 | # Disable assert for non-debug build 24 | ifneq ($(CFG),debug) 25 | CPPFLAGS += -DNDEBUG 26 | endif 27 | 28 | # TODO Should be only for test binaries 29 | LDFLAGS += -L$(LIBDIR) -l$(TM) 30 | 31 | # Only on linux / TODO make source compatible with non-pthread OS 32 | LDFLAGS += -lpthread 33 | 34 | # Solaris default memory allocator is quite slow, better use mtmalloc 35 | # LDFLAGS += -lmtmalloc 36 | 37 | # Disable additionnal checks from glibc (__longjmp_chk/__printf_chk) 38 | CPPFLAGS += -U_FORTIFY_SOURCE 39 | # CPPFLAGS += -D_FORTIFY_SOURCE=0 40 | # Enable multi-thread support in glibc 41 | CPPFLAGS += -D_REENTRANT 42 | 43 | # Rely on the definition of CC to determine the compiler 44 | # if the compiler is not detected correctly, use "gmake COMPILER=your_compiler" 45 | # Default: gcc 46 | COMPILER ?= $(CC) 47 | ifeq ($(COMPILER),icc) 48 | include $(ROOT)/Makefile.icc 49 | else 50 | ifeq ($(COMPILER),suncc) 51 | include $(ROOT)/Makefile.suncc 52 | else 53 | ifeq ($(COMPILER),xlc) 54 | else 55 | ifeq ($(COMPILER),llvm-gcc) 56 | else 57 | ifeq ($(COMPILER),clang) 58 | include $(ROOT)/Makefile.clang 59 | else 60 | include $(ROOT)/Makefile.gcc 61 | endif 62 | endif 63 | endif 64 | endif 65 | endif 66 | 67 | ######################################################################## 68 | # libatomic_ops path 69 | # LIBAO_HOME must be set to the path of libatomic_ops 70 | # (use the embedded light libatomic_ops if LIBAO_HOME is not defined) 71 | ######################################################################## 72 | ifndef LIBAO_HOME 73 | LIBAO_HOME = $(SRCDIR)/atomic_ops 74 | LIBAO_INC = $(LIBAO_HOME) 75 | else 76 | LIBAO_INC = $(LIBAO_HOME)/include 77 | endif 78 | CPPFLAGS += -I$(LIBAO_INC) 79 | -------------------------------------------------------------------------------- /Makefile.gcc: -------------------------------------------------------------------------------- 1 | # Debug/optimization flags (optimized by default) 2 | ifeq ($(CFG),debug) 3 | CFLAGS += -O0 -ggdb3 4 | else 5 | CFLAGS += -O2 6 | CFLAGS += -march=native 7 | endif 8 | 9 | # Disable strict aliasing 10 | # TODO: no-strict-aliasing removes some optimizations but seems required for correctness. need more investigation. 11 | CFLAGS += -fno-strict-aliasing 12 | # Disable stack smashing protector (__stack_chk_fail) 13 | CFLAGS += -fno-stack-protector 14 | # Enable all warnings but unsused functions and labels 15 | CFLAGS += -Wall -Wno-unused-function -Wno-unused-label 16 | # Enable extra warnings 17 | # CFLAGS += -Wextra 18 | # Link Time Optimization (LDFLAGS also requires optimization flags) 19 | # CFLAGS += -flto 20 | # LDFLAGS += $(CFLAGS) -fwhole-program -fuse-linker-plugin 21 | 22 | # Enable profiling mode 23 | # CFLAGS += -fprofile-generate 24 | # LDFLAGS += -fprofile-generate 25 | # Run typical program 26 | # Use the profiling information to compile 27 | # CFLAGS += -fprofile-use 28 | # LDFLAGS += -fprofile-use 29 | 30 | -------------------------------------------------------------------------------- /Makefile.icc: -------------------------------------------------------------------------------- 1 | # Intel compiler has a GCC compatibility mode 2 | 3 | # Debug/optimization flags (optimized by default) 4 | ifeq ($(CFG),debug) 5 | CFLAGS += -O0 -ggdb3 6 | else 7 | CFLAGS += -xHOST -O2 8 | endif 9 | 10 | # Full optimizations (IPO, O3, xHOST) 11 | # CFLAGS += -fast 12 | 13 | # Disable strict aliasing (remove some optimization but required for correctness? need more investigation) 14 | CFLAGS += -fno-strict-aliasing 15 | # Disable stack smashing protector (__stack_chk_fail) 16 | CFLAGS += -fno-stack-protector 17 | # Enable all warnings but unsused functions and labels 18 | CFLAGS += -Wall 19 | # Enable inlining information 20 | # CFLAGS += -Winline 21 | # Disable intel builtins like _intel_fast_memset 22 | # CFLAGS += -fno-builtin 23 | # Align functions on 16-bytes boundary 24 | # CFLAGS += -falign-functions=16 25 | 26 | # Enable profiling mode 27 | # CFLAGS += -prof-gen 28 | # LDFLAGS += -prof-gen 29 | # Run typical program 30 | # Use the profiled information to compile 31 | # CFLAGS += -prof-use 32 | # LDFLAGS += -prof-use 33 | 34 | -------------------------------------------------------------------------------- /Makefile.suncc: -------------------------------------------------------------------------------- 1 | # Debug/optimization flags (optimized by default) 2 | ifeq ($(CFG),debug) 3 | CFLAGS += -g 4 | else 5 | CFLAGS += -xO3 6 | CFLAGS += -native 7 | endif 8 | 9 | # Enable all optimizations 10 | # CFLAGS += -fast 11 | # Enable Inter-procedural optimization (LTO) 12 | # CFLAGS += -xipo=2 13 | # Enable profiling mode 14 | # CFLAGS += -xprofile=collect 15 | # Run typical program 16 | # Use the profiling information to compile 17 | # CFLAGS += -xprofile=use 18 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | TinySTM 2 | ======= 3 | 4 | OVERVIEW 5 | -------- 6 | 7 | TinySTM is a lightweight but efficient word-based STM implementation. 8 | This distribution includes three versions of TinySTM: write-back 9 | (updates are buffered until commit time), write-through (updates are 10 | directly written to memory), and commit-time locking (locks are only 11 | acquired upon commit). The version can be selected by editing the 12 | makefile, which documents all the different compilation options. 13 | 14 | TinySTM compiles and runs on 32 or 64-bit architectures. It was tested 15 | on various flavors of Unix, on Mac OS X, and on Windows using cygwin. 16 | It comes with a few test applications, notably a linked list, a skip 17 | list, and a red-black tree. 18 | 19 | 20 | INSTALLATION 21 | ------------ 22 | 23 | TinySTM requires the 'atomic\_ops' library, freely available from 24 | [www.hpl.hp.com](http://www.hpl.hp.com/research/linux/atomic_ops/). 25 | A stripped-down version of the library is included in the TinySTM 26 | distribution. If you wish to use another version, you must set the 27 | environment variable LIBAO\_HOME to the installation directory of 28 | 'atomic\_ops'. 29 | 30 | If your system does not support GCC thread-local storage, modify the 31 | TLS parameter in the 'Makefile' file. 32 | 33 | To compile TinySTM libraries, execute 'make' in the main directory. To 34 | compile test applications, execute 'make test'. To check the compiled 35 | library, execute 'make check'. 'make clean' will remove all compiled 36 | files. 37 | To compile the TinySTM GCC compatible library, execute 'make abi-gcc'. 38 | To compile test applications, execute 'make abi-gcc-test'. 39 | 40 | 41 | CONTACT 42 | ------- 43 | 44 | * E-mail : [tinystm@tinystm.org](mailto:tinystm@tinystm.org) 45 | * Web : [http://tinystm.org](http://tinystm.org) and 46 | [http://www.tmware.org](http://www.tmware.org) 47 | 48 | 49 | ACKNOWLEDGEMENT 50 | --------------- 51 | 52 | This library was supported by the European research consortium 53 | [VELOX](http://www.velox-project.eu). 54 | -------------------------------------------------------------------------------- /abi/Makefile: -------------------------------------------------------------------------------- 1 | 2 | .PHONY: all gcc dtmc intel clean test check 3 | 4 | all: gcc dtmc intel 5 | 6 | gcc: 7 | $(MAKE) -C gcc 8 | 9 | gcc%: 10 | $(MAKE) -C gcc $(subst -, , $(subst gcc,,$@)) 11 | 12 | dtmc: 13 | $(MAKE) -C dtmc 14 | 15 | dtmc%: 16 | $(MAKE) -C dtmc $(subst -, , $(subst dtmc,,$@)) 17 | 18 | intel: 19 | $(MAKE) -C intel 20 | 21 | intel%: 22 | $(MAKE) -C intel $(subst -, , $(subst intel,,$@)) 23 | 24 | clean: 25 | $(MAKE) -C test clean 26 | $(MAKE) -C gcc clean 27 | $(MAKE) -C dtmc clean 28 | $(MAKE) -C intel clean 29 | 30 | # simple test and check that use explicit calls to gcc libitm library 31 | test: 32 | $(MAKE) -C test test 33 | 34 | check: 35 | $(MAKE) -C test check 36 | 37 | # test-all and check-all need TM compilers (INTEL/DTMC/GCC) in the path 38 | test-all: 39 | $(MAKE) -C gcc test 40 | $(MAKE) -C dtmc test 41 | $(MAKE) -C intel test 42 | 43 | check-all: 44 | $(MAKE) -C gcc check 45 | $(MAKE) -C dtmc check 46 | $(MAKE) -C intel check 47 | 48 | gcc/libitm.h: libitm.h.tpl.header libitm.h.tpl.unifdef libitm.h.tpl.cpp libitm.h.tpl.footer 49 | cat libitm.h.tpl.header > $@ 50 | unifdef -DTM_GCC -UTM_INTEL -UTM_DTMC libitm.h.tpl.unifdef >> $@ || true 51 | cat libitm.h.tpl.cpp >> $@ 52 | cat libitm.h.tpl.footer >> $@ 53 | sed -i 's/TX_ARGS //g' $@ 54 | sed -i 's/TX_ARG//g' $@ 55 | 56 | dtmc/libitm.h: libitm.h.tpl.header libitm.h.tpl.unifdef libitm.h.tpl.cpp libitm.h.tpl.footer 57 | cat libitm.h.tpl.header > $@ 58 | unifdef -UTM_GCC -UTM_INTEL -DTM_DTMC libitm.h.tpl.unifdef >> $@ || true 59 | cat libitm.h.tpl.cpp >> $@ 60 | cat libitm.h.tpl.footer >> $@ 61 | sed -i 's/TX_ARGS//g' $@ 62 | sed -i 's/TX_ARG//g' $@ 63 | 64 | intel/libitm.h: libitm.h.tpl.header libitm.h.tpl.unifdef libitm.h.tpl.cpp libitm.h.tpl.footer 65 | cat libitm.h.tpl.header > $@ 66 | unifdef -UTM_GCC -DTM_INTEL -UTM_DTMC libitm.h.tpl.unifdef >> $@ || true 67 | cat libitm.h.tpl.cpp >> $@ 68 | cat libitm.h.tpl.footer >> $@ 69 | sed -i 's/TX_ARGS/_ITM_transaction *,/g' $@ 70 | sed -i 's/TX_ARG/_ITM_transaction */g' $@ 71 | 72 | -------------------------------------------------------------------------------- /abi/Makefile.common: -------------------------------------------------------------------------------- 1 | # Path to tinySTM 2 | ROOT ?= .. 3 | 4 | # ROOT must be defined to include Makefile.common 5 | include $(ROOT)/Makefile.common 6 | 7 | ############################################################################## 8 | # Compilation options. Note that the definitions from the main makefile 9 | # are not used here, so one can use different options here. 10 | ############################################################################## 11 | 12 | #TODO test if function are inline or need a specific header to force inlining 13 | #TODO Flags may changed. I must find a way to keep up to date with current tiny. 14 | 15 | # DEFINES += -DDESIGN=WRITE_BACK_ETL 16 | # DEFINES += -DDESIGN=WRITE_BACK_CTL 17 | DEFINES += -DDESIGN=WRITE_THROUGH 18 | 19 | DEFINES += -DCM=CM_SUICIDE 20 | # DEFINES += -DCM=CM_DELAY 21 | # DEFINES += -DCM=CM_BACKOFF 22 | # DEFINES += -DCM=CM_MODULAR 23 | 24 | #DEFINES += -DEPOCH_GC 25 | DEFINES += -UEPOCH_GC 26 | # DEFINES += -DREAD_LOCKED_DATA 27 | 28 | #DEFINES += -DLOCK_SHIFT_EXTRA=0 29 | DEFINES += -DTM_STATISTICS 30 | DEFINES += -UTM_STATISTICS2 31 | 32 | # DEFINES += -DNO_STACK_CHECK 33 | # DEFINES += -DTANGER_STATS 34 | 35 | DEFINES += -DIRREVOCABLE_ENABLED 36 | # DEFINES += -UIRREVOCABLE_ENABLED 37 | 38 | # Add wrapper for pthread function 39 | # DEFINES += -DPTHREAD_WRAPPER 40 | DEFINES += -UPTHREAD_WRAPPER 41 | # TODO if THREAD_WRAPPER is defined, library must be linked with -ldl 42 | 43 | # Define how TLS is used in ABI (should be removed for next release) 44 | DEFINES += -DTLS_COMPILER 45 | 46 | ############################################################################## 47 | # Do not modify anything below this point! 48 | ############################################################################## 49 | # TODO Use libtool to generate libraries 50 | # libtool --mode=compile 51 | # libtool --mode=link 52 | # libtool --mode=install 53 | 54 | # NOTES 55 | # Use explicit parameters for Tanger and Intel STM Compiler 56 | 57 | # TODO make it MacOS compatible 58 | 59 | # Remove the -DEXPLICIT_TX_PARAMETER flag if defined 60 | # Manage it accordingly to the required library 61 | # TODO is it useful? 62 | DEF_ABI = $(subst -DEXPLICIT_TX_PARAMETER,,$(DEFINES)) 63 | 64 | # Rules for intset benchmarks 65 | BINS = intset-hs intset-ll intset-rb intset-sl bank 66 | 67 | intset-hs.o: $(ROOT)/test/intset/intset.c 68 | $(TESTCC) $(TESTCFLAGS) -DUSE_HASHSET -c -o $@ $< 69 | 70 | intset-ll.o: $(ROOT)/test/intset/intset.c 71 | $(TESTCC) $(TESTCFLAGS) -DUSE_LINKEDLIST -c -o $@ $< 72 | 73 | intset-rb.o: $(ROOT)/test/intset/intset.c 74 | $(TESTCC) $(TESTCFLAGS) -DUSE_RBTREE -c -o $@ $< 75 | 76 | intset-sl.o: $(ROOT)/test/intset/intset.c 77 | $(TESTCC) $(TESTCFLAGS) -DUSE_SKIPLIST -c -o $@ $< 78 | 79 | bank.o: $(ROOT)/test/bank/bank.c 80 | $(TESTCC) $(TESTCFLAGS) -c -o $@ $< 81 | 82 | # FIXME in case of ABI $(TMLIB) must be replaced to abi/... 83 | $(BINS): %: %.o all 84 | $(TESTLD) -o $@ $< $(TESTLDFLAGS) -lpthread 85 | 86 | test: all $(BINS) 87 | 88 | intset-clean: 89 | rm -f $(BINS) 90 | 91 | check: test intset-check 92 | 93 | intset-check: 94 | @echo Testing Linked List \(intset-ll\) 95 | @./intset-ll -d 2000 1>/dev/null 2>&1 96 | @echo Testing Linked List with concurrency \(intset-ll -n 4\) 97 | @./intset-ll -d 2000 -n 4 1>/dev/null 2>&1 98 | @echo Testing Red Black Tree \(intset-rb\) 99 | @./intset-rb -d 2000 1>/dev/null 2>&1 100 | @echo Testing Red Black Tree with concurrency \(intset-rb -n 4\) 101 | @./intset-rb -d 2000 -n 4 1>/dev/null 2>&1 102 | @echo Testing Skip List \(intset-sl\) 103 | @./intset-sl -d 2000 1>/dev/null 2>&1 104 | @echo Testing Skip List with concurrency \(intset-sl -n 4\) 105 | @./intset-sl -d 2000 -n 4 1>/dev/null 2>&1 106 | @echo Testing Hash Set \(intset-hs\) 107 | @./intset-hs -d 2000 1>/dev/null 2>&1 108 | @echo Testing Hash Set with concurrency \(intset-hs -n 4\) 109 | @./intset-hs -d 2000 -n 4 1>/dev/null 2>&1 110 | @echo All tests passed 111 | 112 | -------------------------------------------------------------------------------- /abi/arch_x86.S: -------------------------------------------------------------------------------- 1 | /* Copyright (C) 2008, 2009 Free Software Foundation, Inc. 2 | Contributed by Richard Henderson . 3 | 4 | This file is part of the GNU Transactional Memory Library (libitm). 5 | 6 | Libitm is free software; you can redistribute it and/or modify it 7 | 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 | Libitm is distributed in the hope that it will be useful, but WITHOUT ANY 12 | WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 13 | FOR A PARTICULAR PURPOSE. See the GNU General Public License for 14 | more details. 15 | 16 | Under Section 7 of GPL version 3, you are granted additional 17 | permissions described in the GCC Runtime Library Exception, version 18 | 3.1, as published by the Free Software Foundation. 19 | 20 | You should have received a copy of the GNU General Public License and 21 | a copy of the GCC Runtime Library Exception along with this program; 22 | see the files COPYING3 and COPYING.RUNTIME respectively. If not, see 23 | . */ 24 | /* Modify for TinySTM and Intel STM Compiler */ 25 | 26 | /* Linux specific, Windows uses a different calling convention. */ 27 | #ifndef __linux__ 28 | #error This file is linux specific. 29 | #endif 30 | 31 | 32 | 33 | .text 34 | .p2align 4 35 | .globl _ITM_beginTransaction 36 | .type _ITM_beginTransaction, @function 37 | 38 | _ITM_beginTransaction: 39 | .cfi_startproc 40 | #ifdef __LP64__ 41 | /* Paramters (in order) is in rdi, rsi, rdx, rcx, r8, r9 */ 42 | /* Temporary registers is r10, r11 (not saved) */ 43 | /* To be saved are rbx, rsp, rbp, r12, r13, r14, r15 */ 44 | /* push register can be also used */ 45 | leaq 8(%rsp), %rax /* Save stack pointer */ 46 | movq (%rsp), %r8 /* Save return address */ 47 | #if defined(EXPLICIT_TX_PARAMETER) 48 | /* NOTE we already have transaction descriptor, we copy directly to tx->env (first field of stm_tx_t) and not on the stack */ 49 | movq %rax, (%rdi) /* rax is the original stack pointer */ 50 | movq %r8, 8(%rdi) /* r8 is the return address */ 51 | movq %rbx, 16(%rdi) /* saves all registers needed */ 52 | movq %rbp, 24(%rdi) 53 | movq %r12, 32(%rdi) 54 | movq %r13, 40(%rdi) 55 | movq %r14, 48(%rdi) 56 | movq %r15, 56(%rdi) 57 | movq %rdi, %rdx /* set 3rd parameter, 2nd and 1st is untouched */ 58 | call GTM_begin_transaction 59 | #else 60 | subq $72, %rsp /* Allocate space from the stack */ 61 | .cfi_def_cfa_offset 80 /* Debug info */ 62 | movq %rax, (%rsp) /* rax is the original stack pointer */ 63 | movq %r8, 8(%rsp) /* r8 is the return address */ 64 | movq %rbx, 16(%rsp) /* saves all registers needed */ 65 | movq %rbp, 24(%rsp) 66 | movq %r12, 32(%rsp) 67 | movq %r13, 40(%rsp) 68 | movq %r14, 48(%rsp) 69 | movq %r15, 56(%rsp) 70 | movq %rsp, %rsi /* set 2nd paramter (pointer to the stack where registers are saved), 1st is untouched (rdi) */ 71 | call GTM_begin_transaction 72 | addq $72, %rsp /* Remove allocated space from the stack */ 73 | #endif 74 | .cfi_def_cfa_offset 8 75 | ret 76 | #else /* !LP64 */ 77 | /* NOTE attribute regparm(2) has to be set for all itm function and push 3rd argument on stack with icc */ 78 | /* fastcall convention argument: eax, edx, then on the stack (GCC specific) */ 79 | /* TODO: only tested with Intel (tanger could use another calling convention) */ 80 | /* eax: tx, edx: attr, stack: __src */ 81 | #if defined(EXPLICIT_TX_PARAMETER) 82 | leal 4(%esp), %ecx /* Get esp (stack pointer) */ 83 | movl %ecx, (%eax) /* Save stack pointer */ 84 | movl (%esp), %ecx /* Get return address */ 85 | movl %ebx, 4(%eax) /* Save registers */ 86 | movl %esi, 8(%eax) 87 | movl %edi, 12(%eax) 88 | movl %ebp, 16(%eax) 89 | movl %ecx, 20(%eax) /* Save return address */ 90 | // NOTE third argument is not handle in this case 91 | call GTM_begin_transaction 92 | #else 93 | leal 4(%esp), %ecx 94 | subl $28, %esp /* Reserve space on the stack */ 95 | .cfi_def_cfa_offset 32 96 | movl %ecx, 8(%esp) 97 | movl %ebx, 12(%esp) /* Save registers */ 98 | movl %esi, 16(%esp) 99 | movl %edi, 20(%esp) 100 | movl %ebp, 24(%esp) 101 | leal 8(%esp), %edx 102 | call GTM_begin_transaction 103 | addl $28, %esp 104 | #endif /* EXPLICIT_TX_PARAMETER */ 105 | .cfi_def_cfa_offset 4 106 | ret 107 | #endif /* !LP64 */ 108 | .cfi_endproc 109 | .size _ITM_beginTransaction, .-_ITM_beginTransaction 110 | 111 | 112 | 113 | 114 | .p2align 4 115 | .globl _ITM_siglongjmp 116 | .type _ITM_siglongjmp, @function 117 | .hidden _ITM_siglongjmp 118 | 119 | _ITM_siglongjmp: 120 | .cfi_startproc 121 | #ifdef __LP64__ 122 | movq (%rdi), %rcx 123 | movq 8(%rdi), %rdx 124 | movq 16(%rdi), %rbx /* Restore registers */ 125 | movq 24(%rdi), %rbp 126 | movq 32(%rdi), %r12 127 | movq 40(%rdi), %r13 128 | movq 48(%rdi), %r14 129 | movq 56(%rdi), %r15 130 | movl %esi, %eax /* 2nd paramter (esi) is returned value (eax, int, 32 bit) */ 131 | .cfi_def_cfa %rcx, 0 132 | .cfi_register %rip, %rdx 133 | movq %rcx, %rsp 134 | jmp *%rdx 135 | #else 136 | xchgl %eax, %edx 137 | movl (%edx), %ecx /* esp (stack pointer) will be restored later */ 138 | movl 4(%edx), %ebx /* restore registers */ 139 | movl 8(%edx), %esi 140 | movl 12(%edx), %edi 141 | movl 16(%edx), %ebp 142 | movl 20(%edx), %edx /* eip (instruction pointer) will be restored after */ 143 | .cfi_def_cfa %ecx, 0 144 | .cfi_register %eip, %edx 145 | movl %ecx, %esp /* restore esp, stack pointer */ 146 | jmp *%edx /* restore eip, instruction pointer */ 147 | #endif 148 | .cfi_endproc 149 | .size _ITM_siglongjmp, .-_ITM_siglongjmp 150 | 151 | // TODO Defined this elsewhere 152 | #if defined(TM_INTEL) && !defined(__PIC__) 153 | 154 | .p2align 4 155 | .globl malloc._$WrapTXN 156 | .type malloc._$WrapTXN, @function 157 | .hidden malloc._$WrapTXN 158 | .globl malloc._$TXN 159 | .type malloc._$TXN, @function 160 | .hidden malloc._$TXN 161 | 162 | malloc._$WrapTXN: 163 | malloc._$TXN: 164 | .cfi_startproc 165 | #ifdef __LP64__ 166 | jmp _ITM_malloc 167 | #else 168 | /* NOTE: unfortunately icc-32bit doesn't recognized it as regparm(2) 169 | TODO: a way to defined it? 170 | */ 171 | movl 4(%esp), %eax /* Set 1st param */ 172 | call _ITM_malloc 173 | movl %eax, 4(%esp) /* Set return value */ 174 | ret 175 | #endif 176 | .cfi_endproc 177 | .size malloc._$TXN, .-malloc._$TXN 178 | .size malloc._$WrapTXN, .-malloc._$WrapTXN 179 | 180 | 181 | 182 | .p2align 4 183 | .globl free._$WrapTXN 184 | .type free._$WrapTXN, @function 185 | .hidden free._$WrapTXN 186 | .globl free._$TXN 187 | .type free._$TXN, @function 188 | .hidden free._$TXN 189 | 190 | free._$WrapTXN: 191 | free._$TXN: 192 | .cfi_startproc 193 | #ifdef __LP64__ 194 | jmp _ITM_free 195 | #else 196 | /* NOTE: unfortunately icc-32bit doesn't recognized it as regparm(2) 197 | TODO: a way to defined it? 198 | */ 199 | movl 4(%esp), %eax /* Set 1st param */ 200 | call _ITM_free 201 | movl %eax, 4(%esp) /* Set return value */ 202 | ret 203 | #endif 204 | .cfi_endproc 205 | .size free._$WrapTXN, .-free._$WrapTXN 206 | .size free._$TXN, .-free._$TXN 207 | 208 | #endif 209 | 210 | .section .note.GNU-stack, "", @progbits 211 | -------------------------------------------------------------------------------- /abi/dtmc/Makefile: -------------------------------------------------------------------------------- 1 | # Path to tinySTM 2 | ROOT = ../.. 3 | 4 | .PHONY: dtmc all clean check 5 | 6 | all: dtmc 7 | 8 | # ROOT must be defined to include Makefile.common 9 | include $(ROOT)/abi/Makefile.common 10 | 11 | ############################################################################## 12 | ## DTMC 13 | ############################################################################## 14 | LLVMCC ?= llvm-gcc 15 | LLVMLD ?= llvm-ld 16 | LLC ?= llc 17 | 18 | CPPFLAGS += -DTM_DTMC -I. 19 | 20 | # TODO find a way to avoid compiling not 21 | #LLVMCC_OK = $(shell $(LLVMCC) ; if [ $$? -neq 0 ] ; then echo "no differences" ; fi) 22 | #@$(echo) "TEST" 23 | #if [ $$? -eq 0 ] ; then echo "no differences" ; fi 24 | #$(shell echo $(LLVMCC_OK)) 25 | 26 | # -DNO_STACK_CHECK => shouldn't be used 27 | # TODO Add possibility to create 32 bits lib => llvm-ld needs -m32? 28 | # TODO find a good way to add dependencies abi.c tanger.c arch.S and also the lib (otherwise it will not be built or updated) 29 | #%.bc: ../%.c 30 | # $(LLVMCC) $(CPPFLAGS) $(CFLAGS) $(DEF_ABI) -emit-llvm -c -o $@ $< 31 | 32 | dtmc: dtmc-bc dtmc-static 33 | 34 | libtanger-stm.bc: ../abi.c tanger.c tanger.h 35 | $(LLVMCC) $(CPPFLAGS) $(CFLAGS) $(DEF_ABI) -emit-llvm -c -o abi.bc ../abi.c 36 | $(LLVMLD) -link-as-library -o $@ abi.bc 37 | 38 | arch.o: arch.S 39 | $(CC) $(CPPFLAGS) $(CFLAGS) -o $@ -c $< 40 | 41 | dtmc-static: libtanger-stm.bc arch.o 42 | $(LLC) libtanger-stm.bc -o libtanger-stm.s 43 | $(CC) $(CPPFLAGS) $(CFLAGS) -c libtanger-stm.s -o libtanger-stm.o 44 | $(AR) cru libitm.a libtanger-stm.o arch.o 45 | 46 | dtmc-bc: libtanger-stm.bc arch.o 47 | $(AR) cru libtanger-stm.a arch.o 48 | 49 | ############################################################################## 50 | 51 | TANGERDIR ?= YOU_DID_NOT_SET_TANGERDIR 52 | LLVMBUILD ?= $(shell llvm-config --build-mode) 53 | ifeq ($(shell uname),Darwin) 54 | LIBTYPE ?= dylib 55 | else 56 | LIBTYPE ?= so 57 | endif 58 | #STMLIBDIR ?= $(TANGERDIR)/$(LLVMBUILD)/lib/ 59 | STMLIBDIR ?= . 60 | STMSUPPORTDIR ?= $(TANGERDIR)/$(LLVMBUILD)/lib/ 61 | TANGERPASS ?= $(TANGERDIR)/$(LLVMBUILD)/lib/libtanger.$(LIBTYPE) 62 | TMLINK ?= $(TANGERDIR)/$(LLVMBUILD)/bin/tmlink 63 | TMLINKFLAGS ?= -stmsupport=$(STMSUPPORTDIR) -stmlib=$(STMLIBDIR) 64 | LLVMCCFLAGS ?= --gnu-tm -emit-llvm 65 | 66 | TESTCC ?= $(LLVMCC) 67 | TESTCFLAGS += $(LLVMCCFLAGS) -DTM_DTMC 68 | 69 | TESTLD ?= $(TMLINK) 70 | TESTLDFLAGS := $(TMLINKFLAGS) $(TESTLDFLAGS) 71 | # TESTLDFLAGS += -static 72 | 73 | clean: intset-clean 74 | rm -f *.bc *.o libtanger-stm.bc libtanger-stm.a libitm.a libtanger-stm.s 75 | 76 | -------------------------------------------------------------------------------- /abi/dtmc/arch.S: -------------------------------------------------------------------------------- 1 | #ifndef __linux__ 2 | /* Linux specific, Windows uses a different calling convention. */ 3 | /* TODO probably solaris is fine with it. */ 4 | # error This file is linux specific. 5 | #endif 6 | 7 | .text 8 | 9 | #if defined(__x86_64__) 10 | .align 4 11 | .globl _ITM_beginTransaction 12 | .type _ITM_beginTransaction, @function 13 | 14 | _ITM_beginTransaction: 15 | .cfi_startproc 16 | /* Paramters (in order) is in rdi, rsi, rdx, rcx, r8, r9 */ 17 | /* Temporary registers is r10, r11 (not saved) */ 18 | /* To be saved are rbx, rsp, rbp, r12, r13, r14, r15 */ 19 | leaq 8(%rsp), %rax /* Save stack pointer */ 20 | subq $56, %rsp 21 | .cfi_def_cfa_offset 64 22 | movq %rax, (%rsp) 23 | movq %rbx, 8(%rsp) 24 | movq %rbp, 16(%rsp) 25 | movq %r12, 24(%rsp) 26 | movq %r13, 32(%rsp) 27 | movq %r14, 40(%rsp) 28 | movq %r15, 48(%rsp) 29 | movq %rsp, %rsi 30 | call GTM_begin_transaction 31 | addq $56, %rsp 32 | .cfi_def_cfa_offset 8 33 | ret 34 | .cfi_endproc 35 | .size _ITM_beginTransaction, .-_ITM_beginTransaction 36 | 37 | .align 4 38 | .globl _ITM_siglongjmp 39 | .type _ITM_siglongjmp, @function 40 | .hidden _ITM_siglongjmp 41 | 42 | _ITM_siglongjmp: 43 | .cfi_startproc 44 | movq (%rsi), %rcx 45 | movq 8(%rsi), %rbx 46 | movq 16(%rsi), %rbp 47 | movq 24(%rsi), %r12 48 | movq 32(%rsi), %r13 49 | movq 40(%rsi), %r14 50 | movq 48(%rsi), %r15 51 | movl %edi, %eax 52 | andq $0x03, %rax /* DTMC uses highest bits for multiple code path */ 53 | .cfi_def_cfa %rsi, 0 54 | .cfi_offset %rip, 56 55 | .cfi_register %rsp, %rcx 56 | movq %rcx, %rsp 57 | jmp *56(%rsi) 58 | .cfi_endproc 59 | .size _ITM_siglongjmp, .-_ITM_siglongjmp 60 | 61 | #elif defined(__i386__) 62 | .align 4 63 | .globl _ITM_beginTransaction 64 | .type _ITM_beginTransaction, @function 65 | _ITM_beginTransaction: 66 | .cfi_startproc 67 | leal 4(%esp), %ecx 68 | movl 4(%esp), %eax 69 | subl $28, %esp 70 | .cfi_def_cfa_offset 32 71 | movl %ecx, 8(%esp) 72 | movl %ebx, 12(%esp) 73 | movl %esi, 16(%esp) 74 | movl %edi, 20(%esp) 75 | movl %ebp, 24(%esp) 76 | leal 8(%esp), %edx 77 | call GTM_begin_transaction 78 | addl $28, %esp 79 | .cfi_def_cfa_offset 4 80 | ret 81 | .cfi_endproc 82 | .size _ITM_beginTransaction, .-_ITM_beginTransaction 83 | 84 | 85 | .align 4 86 | .globl _ITM_siglongjmp 87 | .type _ITM_siglongjmp, @function 88 | .hidden _ITM_siglongjmp 89 | _ITM_siglongjmp: 90 | .cfi_startproc 91 | movl (%edx), %ecx 92 | movl 4(%edx), %ebx 93 | movl 8(%edx), %esi 94 | movl 12(%edx), %edi 95 | movl 16(%edx), %ebp 96 | andl $0x03, %eax /* DTMC uses highest bits for multiple code path */ 97 | .cfi_def_cfa %edx, 0 98 | .cfi_offset %eip, 20 99 | .cfi_register %esp, %ecx 100 | movl %ecx, %esp 101 | jmp *20(%edx) 102 | .cfi_endproc 103 | .size _ITM_siglongjmp, .-_ITM_siglongjmp 104 | 105 | #elif defined(__sparc__) 106 | # error SPARC arch is not yet supported 107 | #else 108 | # error Unsupported architecture 109 | #endif 110 | 111 | #ifdef __linux__ 112 | .section .note.GNU-stack, "", @progbits 113 | #endif 114 | -------------------------------------------------------------------------------- /abi/dtmc/libtanger-stm.public-symbols: -------------------------------------------------------------------------------- 1 | main 2 | GTM_begin_transaction 3 | 4 | -------------------------------------------------------------------------------- /abi/dtmc/libtanger-stm.support: -------------------------------------------------------------------------------- 1 | ,1 2 | -------------------------------------------------------------------------------- /abi/dtmc/tanger-stm-internal.h: -------------------------------------------------------------------------------- 1 | /* Copyright (C) 2007-2009 Torvald Riegel 2 | * 3 | * This program is free software; you can redistribute it and/or 4 | * modify it under the terms of the GNU General Public License 5 | * as published by the Free Software Foundation, version 2 6 | * of the License. 7 | * 8 | * This program is distributed in the hope that it will be useful, 9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | * GNU General Public License for more details. 12 | */ 13 | /** 14 | * Internal STM interface. Contains the interface that an STM has to implement 15 | * for Tanger. The part of the interface that is visible in the application is 16 | * in tanger-stm.h. 17 | */ 18 | #ifndef TANGERSTMINTERNAL_H_ 19 | #define TANGERSTMINTERNAL_H_ 20 | 21 | #include 22 | #include 23 | #include 24 | 25 | #ifdef __cplusplus 26 | extern "C" { 27 | #endif 28 | 29 | /** A transaction descriptor/handle/... */ 30 | typedef void tanger_stm_tx_t; 31 | 32 | #ifndef TANGER_LOADSTORE_ATTR 33 | /* FIXME: LLVM seems to have a bug when inlining these functions. Check if fixed with newer version. */ 34 | //#define TANGER_LOADSTORE_ATTR __attribute__((nothrow,always_inline)) 35 | #define TANGER_LOADSTORE_ATTR __attribute__((nothrow,noinline)) 36 | #endif 37 | 38 | #if defined(__i386__) 39 | /* XXX This is not supported by LLVM yet. */ 40 | #define ITM_REGPARM __attribute__((regparm(2))) 41 | #else 42 | #define ITM_REGPARM 43 | #endif 44 | 45 | /* Load and store functions access a certain number of bits. 46 | * 1b loads/stores are currently assumed to actually go to full 8 bits. 47 | * Addresses being accessed are not necessarily aligned (e.g., a 16b load 48 | * might target memory address 1). If it is known at compile time that the 49 | * access is aligned, then different functions are called. 50 | */ 51 | uint8_t tanger_stm_load1(tanger_stm_tx_t* tx, uint8_t *addr) TANGER_LOADSTORE_ATTR; 52 | uint8_t tanger_stm_load8(tanger_stm_tx_t* tx, uint8_t *addr) TANGER_LOADSTORE_ATTR; 53 | uint16_t tanger_stm_load16(tanger_stm_tx_t* tx, uint16_t *addr) TANGER_LOADSTORE_ATTR; 54 | uint32_t tanger_stm_load32(tanger_stm_tx_t* tx, uint32_t *addr) TANGER_LOADSTORE_ATTR; 55 | uint64_t tanger_stm_load64(tanger_stm_tx_t* tx, uint64_t *addr) TANGER_LOADSTORE_ATTR; 56 | uint16_t tanger_stm_load16aligned(tanger_stm_tx_t* tx, uint16_t *addr) TANGER_LOADSTORE_ATTR; 57 | uint32_t tanger_stm_load32aligned(tanger_stm_tx_t* tx, uint32_t *addr) TANGER_LOADSTORE_ATTR; 58 | uint64_t tanger_stm_load64aligned(tanger_stm_tx_t* tx, uint64_t *addr) TANGER_LOADSTORE_ATTR; 59 | 60 | /** Loads a number of bytes from src and copies them to dest 61 | * src is shared data, dest must point to thread-private data */ 62 | void tanger_stm_loadregion(tanger_stm_tx_t* tx, uint8_t *src, uintptr_t bytes, uint8_t *dest); 63 | /** Starts reading a number of bytes from addr. 64 | * Mostly useful for creating wrappers for library functions. Use with care! 65 | * The function returns an address that you can read the data from. Depending 66 | * on the STM algorithm, it might be different from addr or not. 67 | * You must call tanger_stm_loadregionpost after calling this function. 68 | * You must not call any other STM function between the pre and post calls. 69 | * Data read from addr between the two calls is not guaranteed to be a 70 | * consistent snapshot. */ 71 | void* tanger_stm_loadregionpre(tanger_stm_tx_t* tx, uint8_t *addr, uintptr_t bytes); 72 | /** See tanger_stm_loadregionpre */ 73 | void tanger_stm_loadregionpost(tanger_stm_tx_t* tx, uint8_t *addr, uintptr_t bytes); 74 | /** This is like tanger_stm_loadregionpre() except that it assumes that addr 75 | * points to a zero-terminated string and thus reads all bytes up to and 76 | * including the final zero. It returns the size of the string (including the 77 | * terminating zero) in bytes. The size is guaranteed to be derived from a 78 | * consistent snapshot. If you read the strings' contents, you must call 79 | * tanger_stm_loadregionpost() afterwards. 80 | */ 81 | void* tanger_stm_loadregionstring(tanger_stm_tx_t* tx, char *addr, uintptr_t *bytes); 82 | 83 | void tanger_stm_store1(tanger_stm_tx_t* tx, uint8_t *addr, uint8_t value) TANGER_LOADSTORE_ATTR; 84 | void tanger_stm_store8(tanger_stm_tx_t* tx, uint8_t *addr, uint8_t value) TANGER_LOADSTORE_ATTR; 85 | void tanger_stm_store16(tanger_stm_tx_t* tx, uint16_t *addr, uint16_t value) TANGER_LOADSTORE_ATTR; 86 | void tanger_stm_store32(tanger_stm_tx_t* tx, uint32_t *addr, uint32_t value) TANGER_LOADSTORE_ATTR; 87 | void tanger_stm_store64(tanger_stm_tx_t* tx, uint64_t *addr, uint64_t value) TANGER_LOADSTORE_ATTR; 88 | void tanger_stm_store16aligned(tanger_stm_tx_t* tx, uint16_t *addr, uint16_t value) TANGER_LOADSTORE_ATTR; 89 | void tanger_stm_store32aligned(tanger_stm_tx_t* tx, uint32_t *addr, uint32_t value) TANGER_LOADSTORE_ATTR; 90 | void tanger_stm_store64aligned(tanger_stm_tx_t* tx, uint64_t *addr, uint64_t value) TANGER_LOADSTORE_ATTR; 91 | /** Reads a number of bytes from src and writes them to dest 92 | * dest is shared data, src must point to thread-private data */ 93 | void tanger_stm_storeregion(tanger_stm_tx_t* tx, uint8_t *src, uintptr_t bytes, uint8_t *dest); 94 | /** Prepares writing a number of bytes to addr. 95 | * The function returns an address that you can write the data to. Depending 96 | * on the STM algorithm, it might be different from addr or not. 97 | * The memory starting at addr does not necessarily contain a consistent 98 | * snapshot or the data previously located at this memory region. */ 99 | void* tanger_stm_storeregionpre(tanger_stm_tx_t* tx, uint8_t *addr, uintptr_t bytes); 100 | /** Prepares updating a number of bytes starting at addr. 101 | * The function returns an address that you can write the data to. Depending 102 | * on the STM algorithm, it might be different from addr or not. 103 | * The memory starting at the returned address will contain a consistent 104 | * snapshot of the previous values of the region. */ 105 | void* tanger_stm_updateregionpre(tanger_stm_tx_t* tx, uint8_t *addr, uintptr_t bytes); 106 | 107 | 108 | /** 109 | * Returns the calling thread's transaction descriptor. 110 | * ABI note: Remove this once we have efficient TLS. 111 | */ 112 | tanger_stm_tx_t* tanger_stm_get_tx(void); 113 | 114 | /** 115 | * Saves or restores the stack, depending on whether the current txn was 116 | * started or restarted. The STM will save/restore everything in the range 117 | * [low_addr, high_addr). The STM's implementation of this function must be 118 | * marked as no-inline, so it will get a new stack frame that does not 119 | * overlap the [low_addr, high_addr) region. 120 | * To avoid corrupting stack space of rollback functions, the STM should skip 121 | * undoing changes to addresses that are between the current stack pointer 122 | * during execution of the undo function and the [low_addr, high_addr) 123 | * area (i.e., all newer stack frames, including the current one). 124 | */ 125 | void tanger_stm_save_restore_stack(void* low_addr, void* high_addr); 126 | 127 | /** 128 | * Replacement function for malloc calls in transactions. 129 | */ 130 | void *tanger_stm_malloc(size_t size); 131 | 132 | /** 133 | * Replacement function for free calls in transactions. 134 | */ 135 | void tanger_stm_free(void *ptr); 136 | 137 | /** 138 | * Replacement function for calloc calls in transactions. 139 | */ 140 | void *tanger_stm_calloc(size_t nmemb, size_t size); 141 | 142 | /** 143 | * Replacement function for realloc calls in transactions. 144 | */ 145 | void *tanger_stm_realloc(void *ptr, size_t size); 146 | 147 | /** 148 | * Returns the transactional version of the function passed as argument. 149 | * If no transactional version has been registered, it aborts. 150 | */ 151 | void* tanger_stm_indirect_resolve(void *nontxnal_function); 152 | 153 | /** 154 | * Called before transactional versions are registered for nontransactional 155 | * functions. 156 | * The parameter returns the exact number of functions that will be registered. 157 | */ 158 | void tanger_stm_indirect_init(uint32_t number_of_call_targets); 159 | 160 | /** 161 | * Registers a transactional versions for a nontransactional function. 162 | */ 163 | void tanger_stm_indirect_register(void* nontxnal, void* txnal); 164 | 165 | /* ABI: Additionnal declarations */ 166 | void tanger_stm_stack_restorehack(); 167 | void tanger_stm_stack_savehack(); 168 | //void tanger_stm_threadstack_init(); 169 | //void tanger_stm_threadstack_fini(); 170 | 171 | #ifdef __cplusplus 172 | } 173 | #endif 174 | 175 | #endif /*TANGERSTMINTERNAL_H_*/ 176 | -------------------------------------------------------------------------------- /abi/dtmc/tanger.h: -------------------------------------------------------------------------------- 1 | /* 2 | * File: 3 | * tanger.h 4 | * Author(s): 5 | * Pascal Felber 6 | * Patrick Marlier 7 | * Description: 8 | * Tanger adapter for tinySTM. 9 | * 10 | * Copyright (c) 2007-2014. 11 | * 12 | * This program is free software; you can redistribute it and/or 13 | * modify it under the terms of the GNU General Public License 14 | * as published by the Free Software Foundation, version 2 15 | * of the License. 16 | * 17 | * This program is distributed in the hope that it will be useful, 18 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 19 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 20 | * GNU General Public License for more details. 21 | * 22 | * This program has a dual license and can also be distributed 23 | * under the terms of the MIT license. 24 | */ 25 | 26 | #ifndef _TANGER_H_ 27 | # define _TANGER_H_ 28 | 29 | typedef struct { 30 | void *stack_addr; 31 | size_t stack_size; 32 | void *data; 33 | size_t data_size; 34 | } appstack_t; 35 | 36 | extern __thread appstack_t appstack; 37 | 38 | static inline void tanger_stm_save_stack() 39 | { 40 | // Is the data big enough? 41 | if (appstack.stack_size > appstack.data_size) { 42 | // TODO round to 4096+ 43 | appstack.data_size = appstack.stack_size; 44 | appstack.data = realloc(appstack.data, appstack.data_size); 45 | } 46 | __builtin_memcpy(appstack.data, appstack.stack_addr, appstack.stack_size); 47 | } 48 | 49 | static inline void tanger_stm_restore_stack() 50 | { 51 | __builtin_memcpy(appstack.stack_addr, appstack.data, appstack.stack_size); 52 | } 53 | 54 | static inline void tanger_stm_reset_stack() 55 | { 56 | appstack.stack_addr = NULL; 57 | } 58 | 59 | static inline void tanger_stm_free_stack() 60 | { 61 | if (appstack.data) { 62 | free(appstack.data); 63 | appstack.data = NULL; 64 | } 65 | } 66 | 67 | #endif /* _TANGER_H_ */ 68 | 69 | -------------------------------------------------------------------------------- /abi/dtmc/tm_macros.h: -------------------------------------------------------------------------------- 1 | /* 2 | * File: 3 | * tm_macros.h 4 | * Author(s): 5 | * Pascal Felber 6 | * Patrick Marlier 7 | * Description: 8 | * Defines macros for transactional operations. 9 | * 10 | * Copyright (c) 2007-2014. 11 | * 12 | * This program is free software; you can redistribute it and/or 13 | * modify it under the terms of the GNU General Public License 14 | * as published by the Free Software Foundation, version 2 15 | * of the License. 16 | * 17 | * This program is distributed in the hope that it will be useful, 18 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 19 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 20 | * GNU General Public License for more details. 21 | * 22 | * This program has a dual license and can also be distributed 23 | * under the terms of the MIT license. 24 | */ 25 | 26 | #ifndef _TM_MACROS_H_ 27 | # define _TM_MACROS_H_ 28 | 29 | # define TM_START(id,ro) __tm_atomic { 30 | # define TM_LOAD(x) *x 31 | # define TM_STORE(x,y) *x=y 32 | # define TM_COMMIT } 33 | # define TM_MALLOC(size) malloc(size) 34 | # define TM_FREE(addr) free(addr) 35 | # define TM_FREE2(addr, size) free(addr) 36 | 37 | # define TM_INIT 38 | # define TM_EXIT 39 | # define TM_INIT_THREAD 40 | # define TM_EXIT_THREAD 41 | 42 | /* Define Annotations */ 43 | # define TM_PURE __attribute__((tm_pure)) 44 | # define TM_SAFE __attribute__((tm_callable)) 45 | 46 | /* FIXME to be removed when DTMC will support annotations */ 47 | static double tanger_wrapperpure_erand48(unsigned short int __xsubi[3]) __attribute__ ((weakref("erand48"))); 48 | 49 | #endif /* _TM_MACROS_H_ */ 50 | 51 | -------------------------------------------------------------------------------- /abi/gcc/Makefile: -------------------------------------------------------------------------------- 1 | # Path to TinySTM 2 | ROOT = ../.. 3 | 4 | .PHONY: gcc all clean check test 5 | 6 | all: gcc 7 | 8 | # ROOT must be defined to include Makefile.common 9 | include $(ROOT)/abi/Makefile.common 10 | 11 | 12 | ############################################################################## 13 | ## GCC 14 | ############################################################################## 15 | CPPFLAGS += -DTM_GCC -I. 16 | INCLUDES += $(wildcard ../../src/*.h) 17 | 18 | # NOTES 19 | # lib.map enables to export only some functions 20 | gcc: libitm.so libitm.a 21 | 22 | arch.o: arch.S 23 | $(CC) $(CPPFLAGS) $(CFLAGS) $(DEF_ABI) -c -o $@ $< 24 | 25 | %.do: ../%.c $(INCLUDES) 26 | $(CC) -fPIC $(CPPFLAGS) $(CFLAGS) $(DEF_ABI) -c -o $@ $< 27 | 28 | %.o: ../%.c $(INCLUDES) 29 | $(CC) $(CPPFLAGS) $(CFLAGS) $(DEF_ABI) -c -o $@ $< 30 | 31 | %.s: ../%.c 32 | $(CC) $(CPPFLAGS) $(CFLAGS) $(DEF_ABI) -fverbose-asm -S -o $@ $< 33 | 34 | libitm.a: abi.o arch.o 35 | $(AR) cru $@ $^ 36 | 37 | libitm.so: abi.do arch.o 38 | $(CC) -fPIC $(CPPFLAGS) $(CFLAGS) -shared -Wl,--version-script,../lib.map -o $@ $^ 39 | # TODO Check if strip is really needed 40 | # strip $@ 41 | # cp libitm.so libitm.so.1 42 | # ln -s libitm.so libitm.so.1 43 | #TODO for FAT filesystem, ln doesn't work 44 | ############################################################################## 45 | 46 | TESTCC ?= $(CC) 47 | TESTCFLAGS += $(CPPFLAGS) $(CFLAGS) -DTM_GCC -fgnu-tm 48 | TESTLD ?= $(LD) 49 | TESTLDFLAGS += -Wl,-rpath=$(shell pwd) 50 | TESTLDFLAGS += -L$(ROOT)/abi/gcc 51 | TESTLDFLAGS += -static -litm 52 | 53 | clean: intset-clean 54 | rm -f *.o *.do libitm.a libitm.so 55 | 56 | -------------------------------------------------------------------------------- /abi/gcc/alloc_cpp.c: -------------------------------------------------------------------------------- 1 | /* 2 | * File: 3 | * alloc_cpp.c 4 | * Author(s): 5 | * Pascal Felber 6 | * Patrick Marlier 7 | * Description: 8 | * Module for C++ dynamic memory management. 9 | * 10 | * Copyright (c) 2007-2014. 11 | * 12 | * This program is free software; you can redistribute it and/or 13 | * modify it under the terms of the GNU General Public License 14 | * as published by the Free Software Foundation, version 2 15 | * of the License. 16 | * 17 | * This program is distributed in the hope that it will be useful, 18 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 19 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 20 | * GNU General Public License for more details. 21 | * 22 | * This program has a dual license and can also be distributed 23 | * under the terms of the MIT license. 24 | */ 25 | 26 | #include 27 | #include 28 | #include 29 | 30 | #include "stm.h" 31 | 32 | /* ################################################################### * 33 | * TYPES 34 | * ################################################################### */ 35 | 36 | typedef struct mod_alloc_block { /* Block of allocated memory */ 37 | void *addr; /* Address of memory */ 38 | void (*rev_func)(void*); /* Undo/Defered function */ 39 | struct mod_alloc_block *next; /* Next block */ 40 | } mod_alloc_block_t; 41 | 42 | typedef struct mod_alloc_info { /* Memory descriptor */ 43 | mod_alloc_block_t *allocated; /* Memory allocated by this transation (freed upon abort) */ 44 | mod_alloc_block_t *freed; /* Memory freed by this transation (freed upon commit) */ 45 | } mod_alloc_info_t; 46 | 47 | static int mod_alloc_key; 48 | static int mod_alloc_initialized = 0; 49 | 50 | /* ################################################################### * 51 | * FUNCTIONS 52 | * ################################################################### */ 53 | 54 | /* TODO this is only true on linux amd64/ia32 */ 55 | #ifdef __LP64__ 56 | # define CREATENAME(A,B) A##m##B 57 | #else /* ! __LP64__ */ 58 | # define CREATENAME(A,B) A##j##B 59 | #endif /* ! __LP64__ */ 60 | 61 | 62 | typedef const struct nothrow_t { } *c_nothrow_p; 63 | extern void *CREATENAME(_Znw,) (size_t) __attribute__((weak)); 64 | extern void *CREATENAME(_Zna,) (size_t) __attribute__((weak)); 65 | extern void *CREATENAME(_Znw,RKSt9nothrow_t) (size_t, c_nothrow_p) __attribute__((weak)); 66 | extern void *CREATENAME(_Zna,RKSt9nothrow_t) (size_t, c_nothrow_p) __attribute__((weak)); 67 | 68 | extern void _ZdlPv (void *) __attribute__((weak)); 69 | extern void _ZdaPv (void *) __attribute__((weak)); 70 | extern void _ZdlPvRKSt9nothrow_t (void *, c_nothrow_p) __attribute__((weak)); 71 | extern void _ZdaPvRKSt9nothrow_t (void *, c_nothrow_p) __attribute__((weak)); 72 | 73 | static void mod_alloc_record(void *ptr, void (*rev_func)(void*)) 74 | { 75 | /* Memory will be freed upon abort */ 76 | mod_alloc_info_t *mi; 77 | mod_alloc_block_t *mb; 78 | 79 | if (!mod_alloc_initialized) { 80 | fprintf(stderr, "Module mod_alloc not initialized\n"); 81 | exit(1); 82 | } 83 | 84 | mi = (mod_alloc_info_t *)stm_get_specific(mod_alloc_key); 85 | assert(mi != NULL); 86 | 87 | if ((mb = (mod_alloc_block_t *)malloc(sizeof(mod_alloc_block_t))) == NULL) { 88 | perror("malloc"); 89 | exit(1); 90 | } 91 | mb->addr = ptr; 92 | mb->rev_func = rev_func; 93 | mb->next = mi->allocated; 94 | mi->allocated = mb; 95 | } 96 | 97 | static void mod_free_record(void *addr, void (*rev_func)(void*)) 98 | { 99 | /* Memory disposal is delayed until commit */ 100 | mod_alloc_info_t *mi; 101 | mod_alloc_block_t *mb; 102 | 103 | if (!mod_alloc_initialized) { 104 | fprintf(stderr, "Module mod_alloc not mod_alloc_initialized\n"); 105 | exit(1); 106 | } 107 | 108 | mi = (mod_alloc_info_t *)stm_get_specific(mod_alloc_key); 109 | assert(mi != NULL); 110 | 111 | /* Overwrite to prevent inconsistent reads */ 112 | /* TODO delete operators doesn't give the allocated size */ 113 | /* Acquire lock and update version number */ 114 | stm_store2(addr, 0, 0); 115 | /* Schedule for removal */ 116 | if ((mb = (mod_alloc_block_t *)malloc(sizeof(mod_alloc_block_t))) == NULL) { 117 | perror("malloc"); 118 | exit(1); 119 | } 120 | mb->addr = addr; 121 | mb->rev_func = rev_func; 122 | mb->next = mi->freed; 123 | mi->freed = mb; 124 | } 125 | 126 | /* 127 | * Called upon thread creation. 128 | */ 129 | static void mod_alloc_on_thread_init(void *arg) 130 | { 131 | mod_alloc_info_t *mi; 132 | 133 | if ((mi = (mod_alloc_info_t *)malloc(sizeof(mod_alloc_info_t))) == NULL) { 134 | perror("malloc"); 135 | exit(1); 136 | } 137 | mi->allocated = mi->freed = NULL; 138 | 139 | stm_set_specific(mod_alloc_key, mi); 140 | } 141 | 142 | /* 143 | * Called upon thread deletion. 144 | */ 145 | static void mod_alloc_on_thread_exit(void *arg) 146 | { 147 | free(stm_get_specific(mod_alloc_key)); 148 | } 149 | 150 | /* 151 | * Called upon transaction commit. 152 | */ 153 | static void mod_alloc_on_commit(void *arg) 154 | { 155 | mod_alloc_info_t *mi; 156 | mod_alloc_block_t *mb, *next; 157 | 158 | mi = (mod_alloc_info_t *)stm_get_specific(mod_alloc_key); 159 | assert(mi != NULL); 160 | 161 | /* Keep memory allocated during transaction */ 162 | if (mi->allocated != NULL) { 163 | mb = mi->allocated; 164 | while (mb != NULL) { 165 | next = mb->next; 166 | free(mb); 167 | mb = next; 168 | } 169 | mi->allocated = NULL; 170 | } 171 | 172 | /* Dispose of memory freed during transaction */ 173 | if (mi->freed != NULL) { 174 | mb = mi->freed; 175 | while (mb != NULL) { 176 | next = mb->next; 177 | mb->rev_func(mb->addr); 178 | free(mb); 179 | mb = next; 180 | } 181 | mi->freed = NULL; 182 | } 183 | } 184 | 185 | /* 186 | * Called upon transaction abort. 187 | */ 188 | static void mod_alloc_on_abort(void *arg) 189 | { 190 | mod_alloc_info_t *mi; 191 | mod_alloc_block_t *mb, *next; 192 | 193 | mi = (mod_alloc_info_t *)stm_get_specific(mod_alloc_key); 194 | assert (mi != NULL); 195 | 196 | /* Dispose of memory allocated during transaction */ 197 | if (mi->allocated != NULL) { 198 | mb = mi->allocated; 199 | while (mb != NULL) { 200 | next = mb->next; 201 | mb->rev_func(mb->addr); 202 | free(mb); 203 | mb = next; 204 | } 205 | mi->allocated = NULL; 206 | } 207 | 208 | /* Keep memory freed during transaction */ 209 | if (mi->freed != NULL) { 210 | mb = mi->freed; 211 | while (mb != NULL) { 212 | next = mb->next; 213 | free(mb); 214 | mb = next; 215 | } 216 | mi->freed = NULL; 217 | } 218 | } 219 | 220 | /* New operators */ 221 | 222 | void *CREATENAME(_ZGTtnw,) (size_t sz) 223 | { 224 | void *alloc; 225 | alloc = CREATENAME(_Znw,)(sz); 226 | mod_alloc_record(alloc, _ZdlPv); 227 | return alloc; 228 | } 229 | 230 | void *CREATENAME(_ZGTtna,) (size_t sz) 231 | { 232 | void *alloc; 233 | alloc = CREATENAME(_Zna,)(sz); 234 | mod_alloc_record(alloc, _ZdaPv); 235 | return alloc; 236 | } 237 | 238 | static void _ZdlPvRKSt9nothrow_t1(void *ptr) 239 | { 240 | _ZdlPvRKSt9nothrow_t (ptr, NULL); 241 | } 242 | 243 | void *CREATENAME(_ZGTtnw,RKSt9nothrow_t) (size_t sz, c_nothrow_p nt) 244 | { 245 | void *alloc; 246 | alloc = CREATENAME(_Znw,RKSt9nothrow_t)(sz, nt); 247 | mod_alloc_record(alloc, _ZdlPvRKSt9nothrow_t1); 248 | return alloc; 249 | } 250 | 251 | static void _ZdaPvRKSt9nothrow_t1(void *ptr) 252 | { 253 | _ZdaPvRKSt9nothrow_t(ptr, NULL); 254 | } 255 | 256 | void *CREATENAME(_ZGTtna,RKSt9nothrow_t)(size_t sz, c_nothrow_p nt) 257 | { 258 | void *alloc; 259 | alloc = CREATENAME(_Zna,RKSt9nothrow_t)(sz, nt); 260 | mod_alloc_record(alloc, _ZdaPvRKSt9nothrow_t1); 261 | return alloc; 262 | } 263 | 264 | /* Delete operators */ 265 | 266 | void 267 | _ZGTtdlPv (void *ptr) 268 | { 269 | mod_free_record(ptr, _ZdlPv); 270 | } 271 | 272 | void 273 | _ZGTtdlPvRKSt9nothrow_t (void *ptr, c_nothrow_p nt) 274 | { 275 | mod_free_record(ptr, _ZdlPvRKSt9nothrow_t1); 276 | } 277 | 278 | void _ZGTtdaPv(void *ptr) 279 | { 280 | mod_free_record(ptr, _ZdaPv); 281 | } 282 | 283 | void 284 | _ZGTtdaPvRKSt9nothrow_t (void *ptr, c_nothrow_p nt) 285 | { 286 | mod_free_record(ptr, _ZdaPvRKSt9nothrow_t1); 287 | } 288 | 289 | /* 290 | * Initialize module. 291 | */ 292 | void mod_alloc_cpp() 293 | { 294 | if (mod_alloc_initialized) 295 | return; 296 | 297 | stm_register(mod_alloc_on_thread_init, mod_alloc_on_thread_exit, NULL, NULL, mod_alloc_on_commit, mod_alloc_on_abort, NULL); 298 | mod_alloc_key = stm_create_specific(); 299 | if (mod_alloc_key < 0) { 300 | fprintf(stderr, "Cannot create specific key\n"); 301 | exit(1); 302 | } 303 | mod_alloc_initialized = 1; 304 | } 305 | -------------------------------------------------------------------------------- /abi/gcc/arch.S: -------------------------------------------------------------------------------- 1 | #ifndef __linux__ 2 | /* Linux specific, Windows uses a different calling convention. */ 3 | /* TODO probably solaris is fine with it. */ 4 | # error This file is linux specific. 5 | #endif 6 | 7 | .text 8 | 9 | #if defined(__x86_64__) 10 | .align 4 11 | .globl _ITM_beginTransaction 12 | .type _ITM_beginTransaction, @function 13 | 14 | _ITM_beginTransaction: 15 | .cfi_startproc 16 | /* Paramters (in order) is in rdi, rsi, rdx, rcx, r8, r9 */ 17 | /* Temporary registers is r10, r11 (not saved) */ 18 | /* To be saved are rbx, rsp, rbp, r12, r13, r14, r15 */ 19 | leaq 8(%rsp), %rax /* Save stack pointer */ 20 | subq $56, %rsp 21 | .cfi_def_cfa_offset 64 22 | movq %rax, (%rsp) 23 | movq %rbx, 8(%rsp) 24 | movq %rbp, 16(%rsp) 25 | movq %r12, 24(%rsp) 26 | movq %r13, 32(%rsp) 27 | movq %r14, 40(%rsp) 28 | movq %r15, 48(%rsp) 29 | movq %rsp, %rsi 30 | call GTM_begin_transaction 31 | addq $56, %rsp 32 | .cfi_def_cfa_offset 8 33 | ret 34 | .cfi_endproc 35 | .size _ITM_beginTransaction, .-_ITM_beginTransaction 36 | 37 | .align 4 38 | .globl _ITM_siglongjmp 39 | .type _ITM_siglongjmp, @function 40 | .hidden _ITM_siglongjmp 41 | 42 | _ITM_siglongjmp: 43 | .cfi_startproc 44 | movq (%rsi), %rcx 45 | movq 8(%rsi), %rbx 46 | movq 16(%rsi), %rbp 47 | movq 24(%rsi), %r12 48 | movq 32(%rsi), %r13 49 | movq 40(%rsi), %r14 50 | movq 48(%rsi), %r15 51 | movl %edi, %eax 52 | .cfi_def_cfa %rsi, 0 53 | .cfi_offset %rip, 56 54 | .cfi_register %rsp, %rcx 55 | movq %rcx, %rsp 56 | jmp *56(%rsi) 57 | .cfi_endproc 58 | .size _ITM_siglongjmp, .-_ITM_siglongjmp 59 | 60 | #elif defined(__i386__) 61 | .align 4 62 | .globl _ITM_beginTransaction 63 | .type _ITM_beginTransaction, @function 64 | _ITM_beginTransaction: 65 | .cfi_startproc 66 | leal 4(%esp), %ecx 67 | movl 4(%esp), %eax 68 | subl $28, %esp 69 | .cfi_def_cfa_offset 32 70 | movl %ecx, 8(%esp) 71 | movl %ebx, 12(%esp) 72 | movl %esi, 16(%esp) 73 | movl %edi, 20(%esp) 74 | movl %ebp, 24(%esp) 75 | leal 8(%esp), %edx 76 | call GTM_begin_transaction 77 | addl $28, %esp 78 | .cfi_def_cfa_offset 4 79 | ret 80 | .cfi_endproc 81 | .size _ITM_beginTransaction, .-_ITM_beginTransaction 82 | 83 | 84 | .align 4 85 | .globl _ITM_siglongjmp 86 | .type _ITM_siglongjmp, @function 87 | .hidden _ITM_siglongjmp 88 | _ITM_siglongjmp: 89 | .cfi_startproc 90 | movl (%edx), %ecx 91 | movl 4(%edx), %ebx 92 | movl 8(%edx), %esi 93 | movl 12(%edx), %edi 94 | movl 16(%edx), %ebp 95 | .cfi_def_cfa %edx, 0 96 | .cfi_offset %eip, 20 97 | .cfi_register %esp, %ecx 98 | movl %ecx, %esp 99 | jmp *20(%edx) 100 | .cfi_endproc 101 | .size _ITM_siglongjmp, .-_ITM_siglongjmp 102 | 103 | #elif defined(__sparc__) 104 | # error SPARC arch is not yet supported 105 | #else 106 | # error Unsupported architecture 107 | #endif 108 | 109 | #ifdef __linux__ 110 | .section .note.GNU-stack, "", @progbits 111 | #endif 112 | -------------------------------------------------------------------------------- /abi/gcc/clone.c: -------------------------------------------------------------------------------- 1 | /* Copyright (C) 2009, 2010, 2011 Free Software Foundation, Inc. 2 | Contributed by Richard Henderson . 3 | 4 | This file is part of the GNU Transactional Memory Library (libitm). 5 | 6 | Libitm is free software; you can redistribute it and/or modify it 7 | 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 | Libitm is distributed in the hope that it will be useful, but WITHOUT ANY 12 | WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 13 | FOR A PARTICULAR PURPOSE. See the GNU General Public License for 14 | more details. 15 | 16 | Under Section 7 of GPL version 3, you are granted additional 17 | permissions described in the GCC Runtime Library Exception, version 18 | 3.1, as published by the Free Software Foundation. 19 | 20 | You should have received a copy of the GNU General Public License and 21 | a copy of the GCC Runtime Library Exception along with this program; 22 | see the files COPYING3 and COPYING.RUNTIME respectively. If not, see 23 | . 24 | 25 | This file was modified to allow compatibility with the GNU Transactional 26 | Memory Library (libitm). */ 27 | 28 | /* No include needed since the file is included */ 29 | 30 | struct clone_entry 31 | { 32 | void *orig, *clone; 33 | }; 34 | 35 | struct clone_table 36 | { 37 | struct clone_entry *table; 38 | size_t size; 39 | struct clone_table *next; 40 | }; 41 | 42 | static struct clone_table *all_tables; 43 | 44 | static void * 45 | find_clone (void *ptr) 46 | { 47 | struct clone_table *table; 48 | 49 | for (table = all_tables; table ; table = table->next) 50 | { 51 | struct clone_entry *t = table->table; 52 | size_t lo = 0, hi = table->size, i; 53 | 54 | /* Quick test for whether PTR is present in this table. */ 55 | if (ptr < t[0].orig || ptr > t[hi - 1].orig) 56 | continue; 57 | 58 | /* Otherwise binary search. */ 59 | while (lo < hi) 60 | { 61 | i = (lo + hi) / 2; 62 | if (ptr < t[i].orig) 63 | hi = i; 64 | else if (ptr > t[i].orig) 65 | lo = i + 1; 66 | else 67 | { 68 | return t[i].clone; 69 | } 70 | } 71 | 72 | /* Given the quick test above, if we don't find the entry in 73 | this table then it doesn't exist. */ 74 | break; 75 | } 76 | return NULL; 77 | } 78 | 79 | 80 | void * _ITM_CALL_CONVENTION 81 | _ITM_getTMCloneOrIrrevocable (void *ptr) 82 | { 83 | // if the function (ptr) have a TM version, give the pointer to the TM function 84 | // otherwise, set transaction to irrevocable mode 85 | void *ret = find_clone (ptr); 86 | if (ret) 87 | return ret; 88 | 89 | /* TODO Check we are in an active transaction */ 90 | // if (stm_current_tx() != NULL && stm_is_active(tx)) 91 | /* GCC always use implicit transaction descriptor */ 92 | stm_set_irrevocable(1); 93 | 94 | return ptr; 95 | } 96 | 97 | void * _ITM_CALL_CONVENTION 98 | _ITM_getTMCloneSafe (void *ptr) 99 | { 100 | void *ret = find_clone(ptr); 101 | if (ret == NULL) { 102 | fprintf(stderr, "libitm: cannot find clone for %p\n", ptr); 103 | abort(); 104 | } 105 | return ret; 106 | } 107 | 108 | static int 109 | clone_entry_compare (const void *a, const void *b) 110 | { 111 | const struct clone_entry *aa = (const struct clone_entry *)a; 112 | const struct clone_entry *bb = (const struct clone_entry *)b; 113 | 114 | if (aa->orig < bb->orig) 115 | return -1; 116 | else if (aa->orig > bb->orig) 117 | return 1; 118 | else 119 | return 0; 120 | } 121 | 122 | void 123 | _ITM_registerTMCloneTable (void *xent, size_t size) 124 | { 125 | struct clone_entry *ent = (struct clone_entry *)(xent); 126 | struct clone_table *old, *table; 127 | 128 | table = (struct clone_table *) malloc (sizeof (struct clone_table)); 129 | table->table = ent; 130 | table->size = size; 131 | 132 | qsort (ent, size, sizeof (struct clone_entry), clone_entry_compare); 133 | 134 | old = all_tables; 135 | do 136 | { 137 | table->next = old; 138 | /* TODO Change to use AtomicOps wrapper */ 139 | old = __sync_val_compare_and_swap (&all_tables, old, table); 140 | } 141 | while (old != table); 142 | } 143 | 144 | void 145 | _ITM_deregisterTMCloneTable (void *xent) 146 | { 147 | struct clone_entry *ent = (struct clone_entry *)(xent); 148 | struct clone_table **pprev = &all_tables; 149 | struct clone_table *tab; 150 | 151 | /* FIXME: we must make sure that no transaction is active at this point. */ 152 | 153 | for (pprev = &all_tables; 154 | tab = *pprev, tab->table != ent; 155 | pprev = &tab->next) 156 | continue; 157 | *pprev = tab->next; 158 | 159 | free (tab); 160 | } 161 | 162 | -------------------------------------------------------------------------------- /abi/gcc/eh.c: -------------------------------------------------------------------------------- 1 | /* Copyright (C) 2009, 2011, 2012 Free Software Foundation, Inc. 2 | Contributed by Richard Henderson . 3 | 4 | This file is part of the GNU Transactional Memory Library (libitm). 5 | 6 | Libitm is free software; you can redistribute it and/or modify it 7 | 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 | Libitm is distributed in the hope that it will be useful, but WITHOUT ANY 12 | WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 13 | FOR A PARTICULAR PURPOSE. See the GNU General Public License for 14 | more details. 15 | 16 | Under Section 7 of GPL version 3, you are granted additional 17 | permissions described in the GCC Runtime Library Exception, version 18 | 3.1, as published by the Free Software Foundation. 19 | 20 | You should have received a copy of the GNU General Public License and 21 | a copy of the GCC Runtime Library Exception along with this program; 22 | see the files COPYING3 and COPYING.RUNTIME respectively. If not, see 23 | . 24 | 25 | This file was modified to allow compatibility with the GNU Transactional 26 | Memory Library (libitm). */ 27 | 28 | /* FIXME Exception support with GCC is not working. */ 29 | 30 | extern void *__cxa_allocate_exception (size_t) __attribute__((weak)); 31 | extern void __cxa_throw (void *, void *, void *) __attribute__((weak)); 32 | extern void *__cxa_begin_catch (void *) __attribute__((weak)); 33 | extern void *__cxa_end_catch (void) __attribute__((weak)); 34 | /* TODO check if TM_ABI -> no problem of dependancy of gcc-tm */ 35 | extern void __cxa_tm_cleanup (void *, void *, unsigned int) __attribute__((weak)); 36 | 37 | 38 | void *_ITM_cxa_allocate_exception (size_t size) 39 | { 40 | void *r = __cxa_allocate_exception (size); 41 | /*tx->cxa_unthrown = r;*/ 42 | return r; 43 | } 44 | 45 | void _ITM_cxa_throw (void *obj, void *tinfo, void *dest) 46 | { 47 | /*tx->cxa_unthrown = NULL;*/ 48 | __cxa_throw (obj, tinfo, dest); 49 | } 50 | 51 | void *_ITM_cxa_begin_catch (void *exc_ptr) 52 | { 53 | /*tx->cxa_catch_count++;*/ 54 | return __cxa_begin_catch (exc_ptr); 55 | } 56 | 57 | void _ITM_cxa_end_catch (void) 58 | { 59 | /*tx->cxa_catch_count--;*/ 60 | __cxa_end_catch (); 61 | } 62 | 63 | /* On rollback */ 64 | /* 65 | * TODO integrate this to completely makes work exception with GCC-TM 66 | void stm_revert_cpp_exceptions (void) 67 | { 68 | if (tx->cxa_unthrown || tx->cxa_catch_count) { 69 | __cxa_tm_cleanup (tx->cxa_unthrown, tx->eh_in_flight, 70 | tx->cxa_catch_count); 71 | tx->cxa_catch_count = 0; 72 | tx->cxa_unthrown = NULL; 73 | tx->eh_in_flight = NULL; 74 | } 75 | if (tx->eh_in_flight) { 76 | _Unwind_DeleteException ((_Unwind_Exception *) tx->eh_in_flight); 77 | tx->eh_in_flight = NULL; 78 | } 79 | } 80 | 81 | in _ITM_commitTransactionEH 82 | tx->eh_in_flight = exc_ptr; 83 | in _ITM_beginTransaction (no nesting) 84 | tx->eh_in_flight = NULL; 85 | */ 86 | 87 | -------------------------------------------------------------------------------- /abi/gcc/tm_macros.h: -------------------------------------------------------------------------------- 1 | /* 2 | * File: 3 | * tm_macros.h 4 | * Author(s): 5 | * Pascal Felber 6 | * Patrick Marlier 7 | * Description: 8 | * Defines macros for transactional operations. 9 | * 10 | * Copyright (c) 2007-2014. 11 | * 12 | * This program is free software; you can redistribute it and/or 13 | * modify it under the terms of the GNU General Public License 14 | * as published by the Free Software Foundation, version 2 15 | * of the License. 16 | * 17 | * This program is distributed in the hope that it will be useful, 18 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 19 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 20 | * GNU General Public License for more details. 21 | * 22 | * This program has a dual license and can also be distributed 23 | * under the terms of the MIT license. 24 | */ 25 | #ifndef _TM_MACROS_H_ 26 | # define _TM_MACROS_H_ 27 | 28 | # define TM_START(id,ro) __transaction_atomic { 29 | # define TM_LOAD(x) *x 30 | # define TM_STORE(x,y) *x=y 31 | # define TM_COMMIT } 32 | # define TM_MALLOC(size) malloc(size) 33 | // TODO is it possible to do TM_FREE(addr ...) free(addr) ? //__VA_ARGS__ 34 | # define TM_FREE(addr) free(addr) 35 | # define TM_FREE2(addr, size) free(addr) 36 | 37 | # define TM_INIT 38 | # define TM_EXIT 39 | # define TM_INIT_THREAD 40 | # define TM_EXIT_THREAD 41 | 42 | /* Define Annotations */ 43 | # define TM_PURE __attribute__((transaction_pure)) 44 | # define TM_SAFE __attribute__((transaction_safe)) 45 | 46 | #endif /* _TM_MACROS_H_ */ 47 | 48 | -------------------------------------------------------------------------------- /abi/intel/Makefile: -------------------------------------------------------------------------------- 1 | # Path to tinySTM 2 | ROOT = ../.. 3 | 4 | .PHONY: intel all clean check test 5 | 6 | all: intel 7 | 8 | # ROOT must be defined to include Makefile.common 9 | include $(ROOT)/abi/Makefile.common 10 | 11 | 12 | ############################################################################## 13 | ## INTEL 14 | ############################################################################## 15 | CPPFLAGS += -DTM_INTEL -I. 16 | 17 | # NOTES 18 | # Intel STM Compiler uses explicit transaction descriptor 19 | # Two ways to use: 20 | # - Compile STM application using libitm.a 21 | # - Compile STM application using Intel STM and change LD_LIBRARY_PATH to use tiny's libitmdyn.so 22 | # FIXME 23 | # .so version need minor modification to stm_tx_t structure (add vtable at 0x10) 24 | # intel/libitmdyn.so 25 | intel: libitm.a 26 | 27 | %.do: ../%.c 28 | $(CC) -fPIC $(CPPFLAGS) $(CFLAGS) $(DEF_ABI) -c -o $@ $< 29 | 30 | %.o: ../%.c 31 | $(CC) $(CPPFLAGS) $(CFLAGS) $(DEF_ABI) -c -o $@ $< 32 | 33 | # TODO the dependency of arch_x86.S is not set 34 | arch.o: arch.S 35 | $(CC) $(CPPFLAGS) $(CFLAGS) -c -o $@ $< 36 | 37 | libitm.a: abi.o arch.o alloc.o 38 | $(AR) cru $@ $^ 39 | 40 | # TODO check the dynamic version (not really needed) 41 | arch.do: arch.S 42 | $(CC) $(CPPFLAGS) $(CFLAGS) -c -o $@ $< 43 | 44 | abi_dyn.o: abi.c 45 | $(CC) -fPIC $(CPPFLAGS) $(CFLAGS) $(DEF_ABI) -c -o $@ $< 46 | 47 | libitmdyn.so: abi_dyn.o arch.do 48 | $(CC) -fPIC $(CPPFLAGS) $(CFLAGS) -shared -Wl,--version-script,../lib.map -o $@ $^ 49 | ############################################################################## 50 | 51 | TESTCC ?= icc 52 | TESTCFLAGS += -Qtm_enabled -DTM_INTEL 53 | 54 | TESTLD ?= icc 55 | TESTLDFLAGS += -Qtm_enabled -litm -L. 56 | 57 | clean: intset-clean 58 | rm -f *.o *.do libitm.a libitmdyn.so 59 | 60 | -------------------------------------------------------------------------------- /abi/intel/alloc.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "mod_mem.h" 3 | 4 | /* TODO make inline calls */ 5 | 6 | void *malloc_txn(size_t size) __asm__("malloc._$TXN"); 7 | void *malloc_txn(size_t size) 8 | { 9 | return stm_malloc(size); 10 | } 11 | 12 | void *malloc_wraptxn(size_t size) __asm__("malloc._$WrapTXN"); 13 | void *malloc_wraptxn(size_t size) 14 | { 15 | __asm__ __volatile__("jmp 1f\nmov $0xf0f0f0f0,%eax\n1:"); 16 | return malloc_txn(size); 17 | } 18 | 19 | void *calloc_txn(size_t nmemb, size_t size) __asm__("calloc._$TXN"); 20 | void *calloc_txn(size_t nmemb, size_t size) 21 | { 22 | return stm_calloc(nmemb, size); 23 | } 24 | 25 | void *calloc_wraptxn(size_t nmemb, size_t size) __asm__("calloc._$WrapTXN"); 26 | void *calloc_wraptxn(size_t nmemb, size_t size) 27 | { 28 | __asm__ __volatile__("jmp 1f\nmov $0xf0f0f0f0,%eax\n1:"); 29 | return calloc_txn(nmemb, size); 30 | } 31 | 32 | void free_txn(void *addr) __asm__("free._$TXN"); 33 | void free_txn(void *addr) 34 | { 35 | stm_free(addr, sizeof(void *)); 36 | } 37 | 38 | void free_wraptxn(void *addr) __asm__("free._$WrapTXN"); 39 | void free_wraptxn(void *addr) 40 | { 41 | __asm__ __volatile__("jmp 1f\nmov $0xf0f0f0f0,%eax\n1:"); 42 | free_txn(addr); 43 | } 44 | 45 | #if 0 46 | /* TODO */ 47 | _mm_free._$TXN 48 | _mm_free._$WrapTXN 49 | _mm_malloc._$TXN 50 | _mm_malloc._$WrapTXN 51 | 52 | void* _mm_malloc (int size, int align) 53 | void _mm_free (void *p) 54 | 55 | _ZdaPv._$TXN 56 | _ZdaPv._$WrapTXN 57 | _ZdlPv._$TXN 58 | _ZdlPv._$WrapTXN 59 | _Znam._$TXN 60 | _Znam._$WrapTXN 61 | _Znwm._$TXN 62 | _Znwm._$WrapTXN 63 | #endif 64 | 65 | -------------------------------------------------------------------------------- /abi/intel/arch.S: -------------------------------------------------------------------------------- 1 | #ifndef __linux__ 2 | /* Linux specific, Windows uses a different calling convention. */ 3 | /* TODO probably solaris is fine with it. */ 4 | # error This file is linux specific. 5 | #endif 6 | 7 | .text 8 | 9 | #if defined(__x86_64__) 10 | .align 4 11 | .globl _ITM_beginTransaction 12 | .type _ITM_beginTransaction, @function 13 | 14 | _ITM_beginTransaction: 15 | .cfi_startproc 16 | /* Parameters (in order) is in rdi, rsi, rdx, rcx, r8, r9 */ 17 | /* Temporary registers is r10, r11 (not saved) */ 18 | /* To be saved are rbx, rsp, rbp, r12, r13, r14, r15 */ 19 | leaq 8(%rsp), %rax /* Save stack pointer */ 20 | subq $56, %rsp 21 | .cfi_def_cfa_offset 64 22 | movq %rax, (%rsp) 23 | movq %rbx, 8(%rsp) 24 | movq %rbp, 16(%rsp) 25 | movq %r12, 24(%rsp) 26 | movq %r13, 32(%rsp) 27 | movq %r14, 40(%rsp) 28 | movq %r15, 48(%rsp) 29 | movq %rsp, %rdx 30 | call GTM_begin_transaction 31 | addq $56, %rsp 32 | .cfi_def_cfa_offset 8 33 | ret 34 | .cfi_endproc 35 | .size _ITM_beginTransaction, .-_ITM_beginTransaction 36 | 37 | .align 4 38 | .globl _ITM_siglongjmp 39 | .type _ITM_siglongjmp, @function 40 | .hidden _ITM_siglongjmp 41 | 42 | _ITM_siglongjmp: 43 | .cfi_startproc 44 | movq (%rsi), %rcx 45 | movq 8(%rsi), %rbx 46 | movq 16(%rsi), %rbp 47 | movq 24(%rsi), %r12 48 | movq 32(%rsi), %r13 49 | movq 40(%rsi), %r14 50 | movq 48(%rsi), %r15 51 | movl %edi, %eax 52 | .cfi_def_cfa %rsi, 0 53 | .cfi_offset %rip, 56 54 | .cfi_register %rsp, %rcx 55 | movq %rcx, %rsp 56 | /* a_restoreLiveVariables = 0x08 */ 57 | orq $8, %rax 58 | jmp *56(%rsi) 59 | .cfi_endproc 60 | .size _ITM_siglongjmp, .-_ITM_siglongjmp 61 | 62 | #elif defined(__i386__) 63 | .align 4 64 | .globl _ITM_beginTransaction 65 | .type _ITM_beginTransaction, @function 66 | _ITM_beginTransaction: 67 | .cfi_startproc 68 | /* eax: tx, edx: attr, stack: __src */ 69 | leal 4(%esp), %ecx 70 | subl $28, %esp 71 | .cfi_def_cfa_offset 32 72 | movl %ecx, 8(%esp) 73 | movl %ebx, 12(%esp) 74 | movl %esi, 16(%esp) 75 | movl %edi, 20(%esp) 76 | movl %ebp, 24(%esp) 77 | leal 8(%esp), %ecx 78 | push %ecx 79 | /* GTM_begin_transaction(eax: tx, edx: attr, stack: jmp_buf) */ 80 | call GTM_begin_transaction 81 | addl $32, %esp 82 | .cfi_def_cfa_offset 4 83 | ret 84 | .cfi_endproc 85 | .size _ITM_beginTransaction, .-_ITM_beginTransaction 86 | 87 | 88 | .align 4 89 | .globl _ITM_siglongjmp 90 | .type _ITM_siglongjmp, @function 91 | .hidden _ITM_siglongjmp 92 | _ITM_siglongjmp: 93 | .cfi_startproc 94 | movl (%edx), %ecx 95 | movl 4(%edx), %ebx 96 | movl 8(%edx), %esi 97 | movl 12(%edx), %edi 98 | movl 16(%edx), %ebp 99 | .cfi_def_cfa %edx, 0 100 | .cfi_offset %eip, 20 101 | .cfi_register %esp, %ecx 102 | movl %ecx, %esp 103 | /* TODO check correctness of this behaviour, a_restoreLiveVariables = 0x08 */ 104 | orl $8, %eax 105 | jmp *20(%edx) 106 | .cfi_endproc 107 | .size _ITM_siglongjmp, .-_ITM_siglongjmp 108 | 109 | #else 110 | # error Unsupported architecture 111 | #endif 112 | 113 | #ifdef __linux__ 114 | .section .note.GNU-stack, "", @progbits 115 | #endif 116 | -------------------------------------------------------------------------------- /abi/intel/tm_macros.h: -------------------------------------------------------------------------------- 1 | /* 2 | * File: 3 | * tm_macros.h 4 | * Author(s): 5 | * Pascal Felber 6 | * Patrick Marlier 7 | * Description: 8 | * Defines macros for transactional operations. 9 | * 10 | * Copyright (c) 2007-2014. 11 | * 12 | * This program is free software; you can redistribute it and/or 13 | * modify it under the terms of the GNU General Public License 14 | * as published by the Free Software Foundation, version 2 15 | * of the License. 16 | * 17 | * This program is distributed in the hope that it will be useful, 18 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 19 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 20 | * GNU General Public License for more details. 21 | * 22 | * This program has a dual license and can also be distributed 23 | * under the terms of the MIT license. 24 | */ 25 | 26 | #ifndef _TM_MACROS_H_ 27 | # define _TM_MACROS_H_ 28 | /* TODO check for exit() and perror() */ 29 | /* TODO check function pointer in rbtree */ 30 | /* 3.0 #define __INTEL_COMPILER_BUILD_DATE 20081204 */ 31 | /* 4.0 #define __INTEL_COMPILER_BUILD_DATE 20100806 */ 32 | # if __INTEL_COMPILER_BUILD_DATE < 20100806 33 | # define TM_START(id,ro) __tm_atomic { 34 | # else /* __INTEL_COMPILER_BUILD_DATE >= 20100806 */ 35 | # define TM_START(id,ro) __transaction [[atomic]] { 36 | # endif /* __INTEL_COMPILER_BUILD_DATE >= 20100806 */ 37 | # define TM_LOAD(x) *x 38 | # define TM_STORE(x,y) *x=y 39 | # define TM_COMMIT } 40 | # define TM_MALLOC(size) malloc(size) 41 | # define TM_FREE(addr) free(addr) 42 | # define TM_FREE2(addr, size) free(addr) 43 | 44 | # define TM_INIT 45 | # define TM_EXIT 46 | # define TM_INIT_THREAD 47 | # define TM_EXIT_THREAD 48 | 49 | /* Define Annotations */ 50 | # if __INTEL_COMPILER_BUILD_DATE < 20100806 51 | # define TM_PURE __attribute__((tm_pure)) 52 | # define TM_SAFE __attribute__((tm_callable)) 53 | # else /* __INTEL_COMPILER_BUILD_DATE >= 20100806 */ 54 | # define TM_PURE [[transaction_pure]] 55 | # define TM_SAFE [[transaction_safe]] 56 | 57 | /* error: non [[transaction_safe]] function "malloc" called inside [[transaction_safe]] routine */ 58 | TM_SAFE 59 | void *malloc(size_t); 60 | 61 | TM_SAFE 62 | void free(void *); 63 | 64 | # endif /* __INTEL_COMPILER_BUILD_DATE >= 20100806 */ 65 | 66 | #endif /* _TM_MACROS_H_ */ 67 | 68 | -------------------------------------------------------------------------------- /abi/lib.map: -------------------------------------------------------------------------------- 1 | LIBITM_1.0 { 2 | global: 3 | _ITM_abortTransaction; 4 | _ITM_addUserCommitAction; 5 | _ITM_addUserUndoAction; 6 | _ITM_beginTransaction; 7 | _ITM_changeTransactionMode; 8 | _ITM_commitTransaction; 9 | _ITM_commitTransactionEH; 10 | _ITM_error; 11 | _ITM_getThreadnum; 12 | _ITM_getTransactionId; 13 | _ITM_inTransaction; 14 | _ITM_libraryVersion; 15 | _ITM_registerThrownObject; 16 | _ITM_rollbackTransaction; 17 | _ITM_tryCommitTransaction; 18 | _ITM_versionCompatible; 19 | 20 | _ITM_dropReferences; 21 | _ITM_userError; 22 | _ITM_registerThreadFinalization; 23 | _ITM_getTransaction; 24 | _ITM_initializeProcess; 25 | _ITM_initializeThread; 26 | _ITM_finalizeThread; 27 | _ITM_finalizeProcess; 28 | 29 | _ITM_registerTMCloneTable; 30 | _ITM_deregisterTMCloneTable; 31 | _ITM_getTMCloneOrIrrevocable; 32 | _ITM_getTMCloneSafe; 33 | 34 | _ITM_LB; 35 | _ITM_LCD; 36 | _ITM_LCE; 37 | _ITM_LCF; 38 | _ITM_LD; 39 | _ITM_LE; 40 | _ITM_LF; 41 | _ITM_LM128; 42 | _ITM_LM256; 43 | _ITM_LM64; 44 | _ITM_LU1; 45 | _ITM_LU2; 46 | _ITM_LU4; 47 | _ITM_LU8; 48 | 49 | _ITM_RCD; 50 | _ITM_RCE; 51 | _ITM_RCF; 52 | _ITM_RD; 53 | _ITM_RE; 54 | _ITM_RF; 55 | _ITM_RM128; 56 | _ITM_RM256; 57 | _ITM_RM64; 58 | _ITM_RU1; 59 | _ITM_RU2; 60 | _ITM_RU4; 61 | _ITM_RU8; 62 | _ITM_RaRCD; 63 | _ITM_RaRCE; 64 | _ITM_RaRCF; 65 | _ITM_RaRD; 66 | _ITM_RaRE; 67 | _ITM_RaRF; 68 | _ITM_RaRM128; 69 | _ITM_RaRM256; 70 | _ITM_RaRM64; 71 | _ITM_RaRU1; 72 | _ITM_RaRU2; 73 | _ITM_RaRU4; 74 | _ITM_RaRU8; 75 | _ITM_RaWCD; 76 | _ITM_RaWCE; 77 | _ITM_RaWCF; 78 | _ITM_RaWD; 79 | _ITM_RaWE; 80 | _ITM_RaWF; 81 | _ITM_RaWM128; 82 | _ITM_RaWM256; 83 | _ITM_RaWM64; 84 | _ITM_RaWU1; 85 | _ITM_RaWU2; 86 | _ITM_RaWU4; 87 | _ITM_RaWU8; 88 | _ITM_RfWCD; 89 | _ITM_RfWCE; 90 | _ITM_RfWCF; 91 | _ITM_RfWD; 92 | _ITM_RfWE; 93 | _ITM_RfWF; 94 | _ITM_RfWM128; 95 | _ITM_RfWM256; 96 | _ITM_RfWM64; 97 | _ITM_RfWU1; 98 | _ITM_RfWU2; 99 | _ITM_RfWU4; 100 | _ITM_RfWU8; 101 | 102 | _ITM_WCD; 103 | _ITM_WCE; 104 | _ITM_WCF; 105 | _ITM_WD; 106 | _ITM_WE; 107 | _ITM_WF; 108 | _ITM_WM128; 109 | _ITM_WM256; 110 | _ITM_WM64; 111 | _ITM_WU1; 112 | _ITM_WU2; 113 | _ITM_WU4; 114 | _ITM_WU8; 115 | _ITM_WaRCD; 116 | _ITM_WaRCE; 117 | _ITM_WaRCF; 118 | _ITM_WaRD; 119 | _ITM_WaRE; 120 | _ITM_WaRF; 121 | _ITM_WaRM128; 122 | _ITM_WaRM256; 123 | _ITM_WaRM64; 124 | _ITM_WaRU1; 125 | _ITM_WaRU2; 126 | _ITM_WaRU4; 127 | _ITM_WaRU8; 128 | _ITM_WaWCD; 129 | _ITM_WaWCE; 130 | _ITM_WaWCF; 131 | _ITM_WaWD; 132 | _ITM_WaWE; 133 | _ITM_WaWF; 134 | _ITM_WaWM128; 135 | _ITM_WaWM256; 136 | _ITM_WaWM64; 137 | _ITM_WaWU1; 138 | _ITM_WaWU2; 139 | _ITM_WaWU4; 140 | _ITM_WaWU8; 141 | 142 | _ITM_memcpyRnWt; 143 | _ITM_memcpyRnWtaR; 144 | _ITM_memcpyRnWtaW; 145 | _ITM_memcpyRtWn; 146 | _ITM_memcpyRtWt; 147 | _ITM_memcpyRtWtaR; 148 | _ITM_memcpyRtWtaW; 149 | _ITM_memcpyRtaRWn; 150 | _ITM_memcpyRtaRWt; 151 | _ITM_memcpyRtaRWtaR; 152 | _ITM_memcpyRtaRWtaW; 153 | _ITM_memcpyRtaWWn; 154 | _ITM_memcpyRtaWWt; 155 | _ITM_memcpyRtaWWtaR; 156 | _ITM_memcpyRtaWWtaW; 157 | _ITM_memmoveRnWt; 158 | _ITM_memmoveRnWtaR; 159 | _ITM_memmoveRnWtaW; 160 | _ITM_memmoveRtWn; 161 | _ITM_memmoveRtWt; 162 | _ITM_memmoveRtWtaR; 163 | _ITM_memmoveRtWtaW; 164 | _ITM_memmoveRtaRWn; 165 | _ITM_memmoveRtaRWt; 166 | _ITM_memmoveRtaRWtaR; 167 | _ITM_memmoveRtaRWtaW; 168 | _ITM_memmoveRtaWWn; 169 | _ITM_memmoveRtaWWt; 170 | _ITM_memmoveRtaWWtaR; 171 | _ITM_memmoveRtaWWtaW; 172 | _ITM_memsetW; 173 | _ITM_memsetWaR; 174 | _ITM_memsetWaW; 175 | 176 | _ITM_malloc; 177 | _ITM_calloc; 178 | _ITM_realloc; 179 | _ITM_free; 180 | 181 | pthread_create; 182 | 183 | _ZGTtnwm; 184 | _ZGTtnam; 185 | _ZGTtnwj; 186 | _ZGTtnaj; 187 | _ZGTtdlPv; 188 | _ZGTtdaPv; 189 | _ZGTtnwmRKSt9nothrow_t; 190 | _ZGTtnamRKSt9nothrow_t; 191 | _ZGTtnwjRKSt9nothrow_t; 192 | _ZGTtnajRKSt9nothrow_t; 193 | _ZGTtdlPvRKSt9nothrow_t; 194 | _ZGTtdaPvRKSt9nothrow_t; 195 | 196 | _ITM_cxa_allocate_exception; 197 | _ITM_cxa_begin_catch; 198 | _ITM_cxa_end_catch; 199 | _ITM_cxa_throw; 200 | 201 | local: 202 | *; 203 | }; 204 | -------------------------------------------------------------------------------- /abi/libitm.h.tpl.footer: -------------------------------------------------------------------------------- 1 | 2 | #ifdef __cplusplus 3 | } /* extern "C" */ 4 | #endif /* __cplusplus */ 5 | 6 | #endif /* _LIBITM_H_ */ 7 | 8 | -------------------------------------------------------------------------------- /abi/libitm.h.tpl.header: -------------------------------------------------------------------------------- 1 | /* 2 | * File: 3 | * libitm.h 4 | * Author(s): 5 | * Pascal Felber 6 | * Patrick Marlier 7 | * Description: 8 | * ABI for tinySTM. 9 | * 10 | * Copyright (c) 2007-2014. 11 | * 12 | * This program is free software; you can redistribute it and/or 13 | * modify it under the terms of the GNU General Public License 14 | * as published by the Free Software Foundation, version 2 15 | * of the License. 16 | * 17 | * This program is distributed in the hope that it will be useful, 18 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 19 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 20 | * GNU General Public License for more details. 21 | * 22 | * This program has a dual license and can also be distributed 23 | * under the terms of the MIT license. 24 | */ 25 | 26 | #ifndef _LIBITM_H_ 27 | #define _LIBITM_H_ 28 | 29 | #ifdef __cplusplus 30 | extern "C" { 31 | #endif /* __cplusplus */ 32 | 33 | #include 34 | #include 35 | #ifdef __SSE__ 36 | # include 37 | #endif 38 | 39 | /* ################################################################### * 40 | * DEFINES 41 | * ################################################################### */ 42 | #define _ITM_VERSION_NO_STR "1.0.4" 43 | #define _ITM_VERSION_NO 104 44 | 45 | #if defined(__i386__) 46 | # define _ITM_CALL_CONVENTION __attribute__((regparm(2))) 47 | #else 48 | # define _ITM_CALL_CONVENTION 49 | #endif 50 | 51 | #define _ITM_noTransactionId 1 /* Id for non-transactional code. */ 52 | 53 | 54 | -------------------------------------------------------------------------------- /abi/libitm.h.tpl.unifdef: -------------------------------------------------------------------------------- 1 | #if defined(TM_GCC) || defined(TM_DTMC) 2 | #define _ITM_TRANSACTION_PURE __attribute__((transaction_pure)) 3 | #elif defined(TM_INTEL) 4 | #define _ITM_TRANSACTION_PURE __attribute__((tm_pure)) 5 | /* TODO [[transaction_pure]] */ 6 | #endif 7 | 8 | /* ################################################################### * 9 | * TYPES 10 | * ################################################################### */ 11 | 12 | typedef void *_ITM_transaction; 13 | 14 | typedef void (*_ITM_userUndoFunction)(void *); 15 | typedef void (*_ITM_userCommitFunction)(void *); 16 | 17 | typedef uint32_t _ITM_transactionId; 18 | 19 | typedef enum 20 | { 21 | outsideTransaction = 0, 22 | inRetryableTransaction, 23 | inIrrevocableTransaction 24 | } _ITM_howExecuting; 25 | 26 | struct _ITM_srcLocationS 27 | { 28 | int32_t reserved_1; 29 | int32_t flags; 30 | int32_t reserved_2; 31 | int32_t reserved_3; 32 | const char *psource; 33 | }; 34 | 35 | typedef struct _ITM_srcLocationS _ITM_srcLocation; 36 | 37 | typedef enum { 38 | pr_instrumentedCode = 0x0001, 39 | pr_uninstrumentedCode = 0x0002, 40 | pr_multiwayCode = pr_instrumentedCode | pr_uninstrumentedCode, 41 | pr_hasNoXMMUpdate = 0x0004, 42 | pr_hasNoAbort = 0x0008, 43 | pr_hasNoRetry = 0x0010, 44 | pr_hasNoIrrevocable = 0x0020, 45 | pr_doesGoIrrevocable = 0x0040, 46 | pr_hasNoSimpleReads = 0x0080, 47 | pr_aWBarriersOmitted = 0x0100, 48 | pr_RaRBarriersOmitted = 0x0200, 49 | pr_undoLogCode = 0x0400, 50 | pr_preferUninstrumented = 0x0800, 51 | pr_exceptionBlock = 0x1000, 52 | pr_hasElse = 0x2000, 53 | pr_readOnly = 0x4000 /* GNU gcc specific */ 54 | } _ITM_codeProperties; 55 | 56 | typedef enum { 57 | a_runInstrumentedCode = 0x01, 58 | a_runUninstrumentedCode = 0x02, 59 | a_saveLiveVariables = 0x04, 60 | a_restoreLiveVariables = 0x08, 61 | a_abortTransaction = 0x10, 62 | } _ITM_actions; 63 | 64 | typedef enum { 65 | modeSerialIrrevocable, 66 | modeObstinate, 67 | modeOptimistic, 68 | modePessimistic, 69 | } _ITM_transactionState; 70 | 71 | typedef enum { 72 | unknown = 0, 73 | userAbort = 1, 74 | userRetry = 2, 75 | TMConflict= 4, 76 | exceptionBlockAbort = 8 77 | } _ITM_abortReason; 78 | 79 | 80 | /* ################################################################### * 81 | * FUNCTIONS 82 | * ################################################################### */ 83 | 84 | extern _ITM_TRANSACTION_PURE 85 | _ITM_transaction * _ITM_CALL_CONVENTION _ITM_getTransaction(void); 86 | 87 | extern _ITM_TRANSACTION_PURE 88 | _ITM_howExecuting _ITM_CALL_CONVENTION _ITM_inTransaction(TX_ARG); 89 | 90 | extern _ITM_TRANSACTION_PURE 91 | int _ITM_CALL_CONVENTION _ITM_getThreadnum(void); 92 | 93 | extern _ITM_TRANSACTION_PURE 94 | void _ITM_CALL_CONVENTION _ITM_addUserCommitAction(TX_ARGS 95 | _ITM_userCommitFunction __commit, 96 | _ITM_transactionId resumingTransactionId, 97 | void *__arg); 98 | 99 | extern _ITM_TRANSACTION_PURE 100 | void _ITM_CALL_CONVENTION _ITM_addUserUndoAction(TX_ARGS 101 | const _ITM_userUndoFunction __undo, void * __arg); 102 | 103 | extern _ITM_TRANSACTION_PURE 104 | _ITM_transactionId _ITM_CALL_CONVENTION _ITM_getTransactionId(TX_ARG); 105 | 106 | extern _ITM_TRANSACTION_PURE 107 | void _ITM_CALL_CONVENTION _ITM_dropReferences(TX_ARGS 108 | const void *__start, size_t __size); 109 | 110 | extern _ITM_TRANSACTION_PURE 111 | void _ITM_CALL_CONVENTION _ITM_userError(const char *errString, int exitCode); 112 | 113 | extern const char * _ITM_CALL_CONVENTION _ITM_libraryVersion(void); 114 | 115 | extern int _ITM_CALL_CONVENTION _ITM_versionCompatible(int version); 116 | 117 | 118 | extern int _ITM_CALL_CONVENTION _ITM_initializeThread(void); 119 | 120 | extern void _ITM_CALL_CONVENTION _ITM_finalizeThread(void); 121 | 122 | extern void _ITM_CALL_CONVENTION _ITM_finalizeProcess(void); 123 | 124 | extern int _ITM_CALL_CONVENTION _ITM_initializeProcess(void); 125 | 126 | extern void _ITM_CALL_CONVENTION _ITM_error(const _ITM_srcLocation *__src, 127 | int errorCode); 128 | 129 | #if defined(TM_GCC) 130 | extern uint32_t _ITM_beginTransaction(uint32_t __properties, ...) 131 | __attribute__((returns_twice)); 132 | extern void _ITM_CALL_CONVENTION _ITM_commitTransaction(void); 133 | 134 | #elif defined(TM_INTEL) || defined(TM_DTMC) 135 | extern uint32_t _ITM_CALL_CONVENTION _ITM_beginTransaction(TX_ARGS 136 | uint32_t __properties, 137 | const _ITM_srcLocation *__src) 138 | __attribute__((returns_twice)); 139 | 140 | extern void _ITM_CALL_CONVENTION _ITM_commitTransaction(TX_ARGS 141 | const _ITM_srcLocation *__src); 142 | #endif /* TM_INTEL */ 143 | 144 | /* TODO only Intel tryCommit + _ITM_srcLocation */ 145 | extern bool _ITM_CALL_CONVENTION _ITM_tryCommitTransaction(TX_ARGS 146 | const _ITM_srcLocation *__src); 147 | 148 | extern void _ITM_CALL_CONVENTION _ITM_commitTransactionToId(TX_ARGS 149 | const _ITM_transactionId tid, 150 | const _ITM_srcLocation *__src); 151 | 152 | extern void _ITM_CALL_CONVENTION _ITM_abortTransaction(TX_ARGS 153 | _ITM_abortReason __reason, 154 | const _ITM_srcLocation *__src); 155 | 156 | extern void _ITM_CALL_CONVENTION _ITM_rollbackTransaction(TX_ARGS 157 | const _ITM_srcLocation *__src); 158 | 159 | extern void _ITM_CALL_CONVENTION _ITM_registerThrownObject(TX_ARGS 160 | const void *__obj, 161 | size_t __size); 162 | 163 | extern void _ITM_CALL_CONVENTION _ITM_changeTransactionMode(TX_ARGS 164 | _ITM_transactionState __mode, 165 | const _ITM_srcLocation *__loc); 166 | 167 | #if defined(TM_GCC) 168 | /**** GCC Specific ****/ 169 | extern _ITM_CALL_CONVENTION void *_ITM_getTMCloneOrIrrevocable(void *); 170 | extern _ITM_CALL_CONVENTION void *_ITM_getTMCloneSafe(void *); 171 | extern void _ITM_registerTMCloneTable(void *, size_t); 172 | extern void _ITM_deregisterTMCloneTable(void *); 173 | extern _ITM_CALL_CONVENTION void _ITM_commitTransactionEH(void *); 174 | #endif /* defined(TM_GCC) */ 175 | 176 | #if defined(TM_GCC) || defined(TM_DTMC) 177 | extern void * _ITM_malloc(size_t); 178 | extern void * _ITM_calloc(size_t, size_t); 179 | extern void _ITM_free(void *); 180 | #endif /* defined(TM_GCC) || defined(TM_DTMC) */ 181 | 182 | -------------------------------------------------------------------------------- /abi/oracle/Makefile: -------------------------------------------------------------------------------- 1 | # Path to TinySTM 2 | ROOT = ../.. 3 | 4 | .PHONY: oracletm all clean check test 5 | 6 | all: oracletm 7 | 8 | # ROOT must be defined to include Makefile.common 9 | include $(ROOT)/abi/Makefile.common 10 | 11 | 12 | ############################################################################## 13 | ## Oracle TM 14 | ############################################################################## 15 | CPPFLAGS += -DTM_ORACLE -I. 16 | 17 | oracletm: libitm.a 18 | 19 | arch.o: arch.S 20 | $(CC) $(CPPFLAGS) $(CFLAGS) $(DEF_ABI) -c -o $@ $< 21 | 22 | %.o: %.c 23 | $(CC) $(CPPFLAGS) $(CFLAGS) $(DEF_ABI) -c -o $@ $< 24 | 25 | %.s: %.c 26 | $(CC) $(CPPFLAGS) $(CFLAGS) $(DEF_ABI) -fverbose-asm -S -o $@ $< 27 | 28 | libitm.a: otm.o arch.o 29 | $(AR) cru $@ $^ 30 | 31 | clean: 32 | rm -f *.o *.do libitm.a 33 | 34 | -------------------------------------------------------------------------------- /abi/oracle/arch.S: -------------------------------------------------------------------------------- 1 | #ifndef __linux__ 2 | /* Linux specific, Windows uses a different calling convention. */ 3 | /* TODO probably solaris is fine with it. */ 4 | # error This file is linux specific. 5 | #endif 6 | 7 | .text 8 | 9 | #if defined(__x86_64__) 10 | .align 4 11 | .globl STM_BeginTransaction 12 | .type STM_BeginTransaction, @function 13 | 14 | STM_BeginTransaction: 15 | .cfi_startproc 16 | /* Paramters (in order) is in rdi, rsi, rdx, rcx, r8, r9 */ 17 | /* Temporary registers is r10, r11 (not saved) */ 18 | /* To be saved are rbx, rsp, rbp, r12, r13, r14, r15 */ 19 | leaq 8(%rsp), %rax /* Save stack pointer */ 20 | subq $56, %rsp 21 | .cfi_def_cfa_offset 64 22 | movq %rax, (%rsp) 23 | movq %rbx, 8(%rsp) 24 | movq %rbp, 16(%rsp) 25 | movq %r12, 24(%rsp) 26 | movq %r13, 32(%rsp) 27 | movq %r14, 40(%rsp) 28 | movq %r15, 48(%rsp) 29 | movq %rsp, %rsi 30 | call _STM_BeginTransaction 31 | addq $56, %rsp 32 | .cfi_def_cfa_offset 8 33 | ret 34 | .cfi_endproc 35 | .size STM_BeginTransaction, .-STM_BeginTransaction 36 | 37 | .align 4 38 | .globl _ITM_siglongjmp 39 | .type _ITM_siglongjmp, @function 40 | .hidden _ITM_siglongjmp 41 | 42 | _ITM_siglongjmp: 43 | .cfi_startproc 44 | movq (%rsi), %rcx 45 | movq 8(%rsi), %rbx 46 | movq 16(%rsi), %rbp 47 | movq 24(%rsi), %r12 48 | movq 32(%rsi), %r13 49 | movq 40(%rsi), %r14 50 | movq 48(%rsi), %r15 51 | movl %edi, %eax 52 | .cfi_def_cfa %rsi, 0 53 | .cfi_offset %rip, 56 54 | .cfi_register %rsp, %rcx 55 | movq %rcx, %rsp 56 | jmp *56(%rsi) 57 | .cfi_endproc 58 | .size _ITM_siglongjmp, .-_ITM_siglongjmp 59 | 60 | #elif defined(__i386__) 61 | .align 4 62 | .globl STM_BeginTransaction 63 | .type STM_BeginTransaction, @function 64 | STM_BeginTransaction: 65 | .cfi_startproc 66 | leal 4(%esp), %ecx 67 | movl 4(%esp), %eax 68 | subl $28, %esp 69 | .cfi_def_cfa_offset 32 70 | movl %ecx, 8(%esp) 71 | movl %ebx, 12(%esp) 72 | movl %esi, 16(%esp) 73 | movl %edi, 20(%esp) 74 | movl %ebp, 24(%esp) 75 | leal 8(%esp), %edx 76 | call _STM_BeginTransaction 77 | addl $28, %esp 78 | .cfi_def_cfa_offset 4 79 | ret 80 | .cfi_endproc 81 | .size STM_BeginTransaction, .-STM_BeginTransaction 82 | 83 | 84 | .align 4 85 | .globl _ITM_siglongjmp 86 | .type _ITM_siglongjmp, @function 87 | .hidden _ITM_siglongjmp 88 | _ITM_siglongjmp: 89 | .cfi_startproc 90 | movl (%edx), %ecx 91 | movl 4(%edx), %ebx 92 | movl 8(%edx), %esi 93 | movl 12(%edx), %edi 94 | movl 16(%edx), %ebp 95 | .cfi_def_cfa %edx, 0 96 | .cfi_offset %eip, 20 97 | .cfi_register %esp, %ecx 98 | movl %ecx, %esp 99 | jmp *20(%edx) 100 | .cfi_endproc 101 | .size _ITM_siglongjmp, .-_ITM_siglongjmp 102 | 103 | #elif defined(__sparc__) 104 | # error SPARC arch is not yet supported 105 | #else 106 | # error Unsupported architecture 107 | #endif 108 | 109 | #ifdef __linux__ 110 | .section .note.GNU-stack, "", @progbits 111 | #endif 112 | -------------------------------------------------------------------------------- /abi/oracle/otm.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "stm.h" 3 | #include "wrappers.h" 4 | #include "mod_mem.h" 5 | 6 | #define CTX_ITM _ITM_siglongjmp 7 | #define _ITM_CALL_CONVENTION __attribute__((regparm(2))) 8 | extern void _ITM_CALL_CONVENTION _ITM_siglongjmp(int val, sigjmp_buf env) __attribute__ ((noreturn)); 9 | 10 | #include "stm.c" 11 | #include "mod_cb_mem.c" 12 | #include "wrappers.c" 13 | 14 | /* TODO __FUNCTION__ is not available with Oracle Studio if -Xc () and -Xs (K&R mode) but should not be a problem. */ 15 | /* __FUNCTION__ and __PRETTY_FUNCTION__ are predefined identifiers that contain the name of the lexically-enclosing function. They are functionally equivalent to the c99 predefined identifier, __func__. On Solaris platforms, __FUNCTION__ and __PRETTY_FUNCTION__ are not available in -Xs and -Xc modes. */ 16 | 17 | stm_tx_t *STM_GetMyTransId(void) 18 | { 19 | stm_tx_t *tx = stm_current_tx(); 20 | PRINT_DEBUG("==> %s()\n", __FUNCTION__); 21 | if (tx == NULL) { 22 | stm_init(); 23 | mod_mem_init(0); 24 | tx = stm_init_thread(); 25 | /* TODO save stack high and low addr */ 26 | } 27 | PRINT_DEBUG("==> %s() -> 0x%p\n", __FUNCTION__, tx); 28 | return tx; 29 | } 30 | 31 | __attribute__((regparm(2))) 32 | int _STM_BeginTransaction(stm_tx_t *tx, jmp_buf *buf) 33 | { 34 | sigjmp_buf * env; 35 | PRINT_DEBUG("==> %s(0x%p)\n", __FUNCTION__, tx); 36 | /* TODO see how the ctx is saved and rollback. */ 37 | env = int_stm_start(tx, (stm_tx_attr_t)0); 38 | if (likely(env != NULL)) 39 | memcpy(env, buf, sizeof(jmp_buf)); /* TODO limit size to real size */ 40 | return 1; 41 | } 42 | 43 | int STM_ValidateTransaction(stm_tx_t *tx) 44 | { 45 | /*int ret;*/ 46 | PRINT_DEBUG("==> %s(0x%p)\n", __FUNCTION__, tx); 47 | /*ret = stm_validate(tx);*/ 48 | return 1 /*ret*/; 49 | } 50 | 51 | int STM_CommitTransaction(stm_tx_t *tx) 52 | { 53 | int ret; 54 | PRINT_DEBUG("==> %s(tx=0x%p)\n", __FUNCTION__, tx); 55 | ret = stm_commit_tx(tx); 56 | /* Returned value are : Abort no retry=-1 / Abort retry=0 / Committed no retry=1 */ 57 | return ret; 58 | } 59 | 60 | /* API uses many steps: acquisition, then transactional read 61 | * to apply this to tinySTM it requires to split stm_load function in many pieces */ 62 | 63 | typedef void * RdHandle; 64 | typedef void * WrHandle; 65 | 66 | RdHandle *STM_AcquireReadPermission(stm_tx_t *tx, stm_word_t *addr, int valid) 67 | { 68 | PRINT_DEBUG("==> %s(tx=0x%p,addr=0x%p,valid=%d)\n", tx, addr, valid); 69 | return NULL; 70 | } 71 | 72 | WrHandle *STM_AcquireWritePermission(stm_tx_t *tx, stm_word_t *addr, int valid) 73 | { 74 | PRINT_DEBUG("==> %s(tx=0x%p,addr=0x%p,valid=%d)\n", tx, addr, valid); 75 | return NULL; 76 | } 77 | 78 | WrHandle* STM_AcquireReadWritePermission(stm_tx_t *tx, stm_word_t *addr, int valid) 79 | { 80 | PRINT_DEBUG("==> %s(tx=0x%p,addr=0x%p,valid=%d)\n", __FUNCTION__, tx, addr, valid); 81 | return NULL; 82 | } 83 | 84 | 85 | /* Transactional loads */ 86 | 87 | uint8_t STM_TranRead8(stm_tx_t *tx, RdHandle *theRdHandle, uint8_t *addr, int valid) 88 | { 89 | PRINT_DEBUG("==> %s(tx=0x%p,handle=0x%p,addr=0x%p,valid=%d)\n", __FUNCTION__, tx, theRdHandle, addr, valid); 90 | return stm_load_u8(/*tx,*/ addr); 91 | } 92 | 93 | uint16_t STM_TranRead16(stm_tx_t *tx, RdHandle *theRdHandle, uint16_t *addr, int valid) 94 | { 95 | PRINT_DEBUG("==> %s(tx=0x%p,handle=0x%p,addr=0x%p,valid=%d)\n", __FUNCTION__, tx, theRdHandle, addr, valid); 96 | return stm_load_u16(/*tx,*/ addr); 97 | } 98 | 99 | uint32_t STM_TranRead32(stm_tx_t *tx, RdHandle *theRdHandle, uint32_t *addr, int valid) 100 | { 101 | PRINT_DEBUG("==> %s(tx=0x%p,handle=0x%p,addr=0x%p,valid=%d)\n", __FUNCTION__, tx, theRdHandle, addr, valid); 102 | /* TODO can it be more efficient with #ifdef _LP64 and stm_load(). */ 103 | return stm_load_u32(/*tx,*/ addr); 104 | } 105 | 106 | double STM_TranReadFloat32(stm_tx_t *tx, RdHandle *theRdHandle, float *addr, int valid) 107 | { 108 | PRINT_DEBUG("==> %s(tx=0x%p,handle=0x%p,addr=0x%p,valid=%d)\n", __FUNCTION__, tx, theRdHandle, addr, valid); 109 | return stm_load_float(/*tx,*/ addr); 110 | } 111 | 112 | uint64_t STM_TranRead64(stm_tx_t *tx, RdHandle *theRdHandle, uint64_t *addr, int valid) 113 | { 114 | PRINT_DEBUG("==> %s(tx=0x%p,handle=0x%p,addr=0x%p,valid=%d)\n", __FUNCTION__, tx, theRdHandle, addr, valid); 115 | return stm_load_u64(/*tx,*/ addr); 116 | } 117 | 118 | double STM_TranReadFloat64(stm_tx_t *tx, RdHandle *theRdHandle, double *addr, int valid) 119 | { 120 | PRINT_DEBUG("==> %s(tx=0x%p,handle=0x%p,addr=0x%p,valid=%d)\n", __FUNCTION__, tx, theRdHandle, addr, valid); 121 | return stm_load_double(/*tx,*/ addr); 122 | } 123 | 124 | 125 | /* Transactional stores */ 126 | 127 | int STM_TranWrite8(stm_tx_t *tx, WrHandle* theWrHandle, uint8_t *addr, uint8_t val, int valid) 128 | { 129 | PRINT_DEBUG("==> %s(tx=0x%p,handle=0x%p,addr=0x%p,val=%u,valid=%d)\n", __FUNCTION__, tx, theWrHandle, addr, val, valid); 130 | stm_store_u8(/*tx,*/ addr, val); 131 | return 1; 132 | } 133 | int STM_TranWrite16(stm_tx_t *tx, WrHandle* theWrHandle, uint16_t *addr, uint16_t val, int valid) 134 | { 135 | PRINT_DEBUG("==> %s(tx=0x%p,handle=0x%p,addr=0x%p,val=%u,valid=%d)\n", __FUNCTION__, tx, theWrHandle, addr, val, valid); 136 | stm_store_u16(/*tx,*/ addr, val); 137 | return 1; 138 | } 139 | 140 | int STM_TranWrite32(stm_tx_t *tx, WrHandle *theWrHandle, uint32_t *addr, uint32_t val, int valid) 141 | { 142 | PRINT_DEBUG("==> %s(tx=0x%p,handle=0x%p,addr=0x%p,val=%u,valid=%d)\n", __FUNCTION__, tx, theWrHandle, addr, val, valid); 143 | stm_store_u32(/*tx,*/ addr, val); 144 | return 1; 145 | } 146 | 147 | int STM_TranWrite64(stm_tx_t *tx, WrHandle *theWrHandle, uint64_t *addr, uint64_t val, int valid) 148 | { 149 | PRINT_DEBUG("==> %s(tx=0x%p,handle=0x%p,addr=0x%p,val=%lu,valid=%d)\n", __FUNCTION__, tx, theWrHandle, addr, val, valid); 150 | stm_store_u64(/*tx,*/ addr, val); 151 | return 1; 152 | } 153 | 154 | int STM_TranWriteFloat32(stm_tx_t *tx, WrHandle *theWrHandle, float *addr, float val, int valid) 155 | { 156 | PRINT_DEBUG("==> %s(tx=0x%p,handle=0x%p,addr=0x%p,val=%f,valid=%d)\n", __FUNCTION__, tx, theWrHandle, addr, val, valid); 157 | stm_store_float(/*tx,*/ addr, val); 158 | return 1; 159 | } 160 | 161 | int STM_TranWriteFloat64(stm_tx_t *tx, WrHandle *theWrHandle, double *addr, double val, int valid) 162 | { 163 | PRINT_DEBUG("==> %s(tx=0x%p,handle=0x%p,addr=0x%p,val=%f,valid=%d)\n", __FUNCTION__, tx, theWrHandle, addr, val, valid); 164 | stm_store_double(/*tx,*/ addr, val); 165 | return 1; 166 | } 167 | 168 | 169 | /* Transactional memory management */ 170 | 171 | void *STM_TranMalloc(stm_tx_t *tx, size_t sz) 172 | { 173 | PRINT_DEBUG("==> %s(tx=0x%p,size=%d)\n", __FUNCTION__, tx, sz); 174 | return stm_malloc_tx(tx, sz); 175 | } 176 | 177 | void *STM_TranCalloc(stm_tx_t *tx, size_t elem, size_t sz) 178 | { 179 | PRINT_DEBUG("==> %s(tx=0x%p,elem=%d,size=%d)\n", __FUNCTION__, tx, elem, sz); 180 | return stm_calloc_tx(tx, elem, sz); 181 | } 182 | 183 | void STM_TranMFree(stm_tx_t *tx, void *addr) 184 | { 185 | PRINT_DEBUG("==> %s(tx=0x%p,addr=%p)\n", __FUNCTION__, tx, addr); 186 | /* TODO: guess the size... use as in itm block_size(ptr)? is it available in Solaris? */ 187 | stm_free_tx(tx, addr, sizeof(stm_word_t)); 188 | } 189 | 190 | void *STM_TranMemAlign(stm_tx_t *tx, size_t alignment, size_t sz) 191 | { 192 | assert(0); 193 | return NULL; 194 | } 195 | 196 | void *STM_TranValloc(stm_tx_t *tx, size_t sz) 197 | { 198 | assert(0); 199 | return NULL; 200 | } 201 | 202 | /* TODO check if sz is size_t? same for alignment? */ 203 | void STM_TranMemCpy(stm_tx_t *tx, void* src, void* dst, size_t sz, uint32_t alignment) 204 | { 205 | /* TODO what to do with alignment? */ 206 | uint8_t *buf = (uint8_t *)alloca(sz); 207 | stm_load_bytes(/*tx,*/ (volatile uint8_t *)src, buf, sz); 208 | stm_store_bytes(/*tx,*/ (volatile uint8_t *)dst, buf, sz); 209 | } 210 | 211 | int STM_CurrentlyUsingDecoratedPath(stm_tx_t* tx) 212 | { 213 | if (tx == NULL) 214 | return 0; 215 | /* TODO check that the nesting is != 0 */ 216 | return 1; 217 | } 218 | 219 | 220 | -------------------------------------------------------------------------------- /abi/pthread_wrapper.h: -------------------------------------------------------------------------------- 1 | /* 2 | * File: 3 | * pthread_wrapper.h 4 | * Author(s): 5 | * Pascal Felber 6 | * Patrick Marlier 7 | * Description: 8 | * Pthread wrapper to handle thread creation. 9 | * 10 | * Copyright (c) 2007-2014. 11 | * 12 | * This program is free software; you can redistribute it and/or 13 | * modify it under the terms of the GNU General Public License 14 | * as published by the Free Software Foundation, version 2 15 | * of the License. 16 | * 17 | * This program is distributed in the hope that it will be useful, 18 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 19 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 20 | * GNU General Public License for more details. 21 | * 22 | * This program has a dual license and can also be distributed 23 | * under the terms of the MIT license. 24 | */ 25 | 26 | #include 27 | 28 | /* Original pthread function */ 29 | static int (*pthread_create_orig)(pthread_t *__restrict, 30 | __const pthread_attr_t *__restrict, 31 | void *(*)(void *), 32 | void *__restrict) = NULL; 33 | 34 | typedef struct { 35 | void * (*start_routine)(void *); 36 | void * arg; 37 | } wrapper_t; 38 | 39 | static void * wpthread_create(void * data) 40 | { 41 | void * (*start_routine)(void *) = ((wrapper_t*)data)->start_routine; 42 | void * arg = ((wrapper_t*)data)->arg; 43 | void * ret; 44 | /* Free the allocated memory by the wrapper */ 45 | free(data); 46 | /* Initialize thread */ 47 | _ITM_initializeThread(); 48 | /* Call user function */ 49 | ret = start_routine(arg); 50 | /* Finalizing thread */ 51 | _ITM_finalizeThread(); 52 | return ret; 53 | } 54 | 55 | int pthread_create(pthread_t *__restrict thread, 56 | __const pthread_attr_t *__restrict attr, 57 | void * (*start_routine)(void *), 58 | void *__restrict arg) 59 | { 60 | int i_return; 61 | /* Allocate memory to pass as argument (we can't assume that stack will not be modified) */ 62 | wrapper_t * wdata = malloc(sizeof(wrapper_t)); 63 | wdata->start_routine = start_routine; 64 | wdata->arg = arg; 65 | /* Solving link to original pthread_create */ 66 | if (pthread_create_orig == NULL) { 67 | pthread_create_orig = dlsym(RTLD_NEXT, "pthread_create"); 68 | if (pthread_create_orig == NULL) { 69 | char *error = dlerror(); 70 | if (error == NULL) { 71 | error = "pthread_create can't be solved."; 72 | } 73 | fprintf(stderr, "%s\n", error); 74 | exit(EXIT_FAILURE); 75 | } 76 | } 77 | /* Call original pthread function */ 78 | i_return = pthread_create_orig(thread, attr, wpthread_create, wdata); 79 | return i_return; 80 | } 81 | -------------------------------------------------------------------------------- /abi/test/Makefile: -------------------------------------------------------------------------------- 1 | # Path to TinySTM 2 | ROOT = ../.. 3 | 4 | .PHONY: gcc all clean test check 5 | 6 | all: gcc 7 | 8 | # ROOT must be defined to include Makefile.common 9 | include $(ROOT)/abi/Makefile.common 10 | 11 | ############################################################################## 12 | ## GCC 13 | ############################################################################## 14 | # TODO Currently it is a copy of GCC-TM Makefile but I didn't find a best way 15 | # to do that until now 16 | CPPFLAGS += -DTM_GCC -I../gcc 17 | 18 | # NOTES 19 | # lib.map enables to export only some functions 20 | gcc: libitm.so libitm.a 21 | 22 | arch.o: ../gcc/arch.S 23 | $(CC) $(CPPFLAGS) $(CFLAGS) $(DEF_ABI) -c -o $@ $< 24 | 25 | %.do: ../%.c 26 | $(CC) -fPIC $(CPPFLAGS) $(CFLAGS) $(DEF_ABI) -c -o $@ $< 27 | 28 | %.o: ../%.c 29 | $(CC) $(CPPFLAGS) $(CFLAGS) $(DEF_ABI) -c -o $@ $< 30 | 31 | libitm.a: abi.o arch.o 32 | $(AR) cru $@ $^ 33 | 34 | libitm.so: abi.do arch.o 35 | $(CC) -fPIC $(CPPFLAGS) $(CFLAGS) -shared -Wl,--version-script,../lib.map -o $@ $^ 36 | # TODO Check if strip is really needed 37 | # strip $@ 38 | # cp libitm.so libitm.so.1 39 | # ln -s libitm.so libitm.so.1 40 | #TODO for FAT filesystem, ln doesn't work 41 | ############################################################################## 42 | 43 | TESTCC ?= gcc 44 | TESTCFLAGS += -Wall -O2 -march=native -DTM_ABI -I../gcc/ -DTLS 45 | TESTLD ?= gcc 46 | TESTLDFLAGS += -Wl,-rpath=$(shell pwd) 47 | TESTLDFLAGS += -L$(shell pwd) 48 | # TESTLDFLAGS += libitm.a 49 | # FIXME: see why big perf degradation with shared library 50 | TESTLDFLAGS += -litm 51 | 52 | clean: intset-clean 53 | rm -f *.o *.do libitm.a libitm.so 54 | 55 | -------------------------------------------------------------------------------- /abi/tm_macros.h: -------------------------------------------------------------------------------- 1 | /* 2 | * File: 3 | * tm_macros.h 4 | * Author(s): 5 | * Pascal Felber 6 | * Patrick Marlier 7 | * Description: 8 | * Defines macros for transactional operations. 9 | * 10 | * Copyright (c) 2007-2014. 11 | * 12 | * This program is free software; you can redistribute it and/or 13 | * modify it under the terms of the GNU General Public License 14 | * as published by the Free Software Foundation, version 2 15 | * of the License. 16 | * 17 | * This program is distributed in the hope that it will be useful, 18 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 19 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 20 | * GNU General Public License for more details. 21 | * 22 | * This program has a dual license and can also be distributed 23 | * under the terms of the MIT license. 24 | */ 25 | 26 | #ifndef _TM_MACROS_H_ 27 | # define _TM_MACROS_H_ 28 | /* Compile with explicit calls to ITM library */ 29 | # include 30 | # include "libitm.h" 31 | 32 | /* Define TM_MACROS */ 33 | # ifdef EXPLICIT_TX_PARAMETER 34 | # define TXARG __td 35 | # define TXARGS __td, 36 | # define TM_START(id, ro) { _ITM_transaction* __td = _ITM_getTransaction(); \ 37 | _ITM_beginTransaction(TXARGS ro == RO ? pr_readOnly | pr_instrumentedCode : pr_instrumentedCode, NULL); 38 | # else 39 | # define TXARG 40 | # define TXARGS 41 | # define TM_START(id, ro) { _ITM_beginTransaction(ro == RO ? pr_readOnly | pr_instrumentedCode : pr_instrumentedCode, NULL); 42 | # endif 43 | // TODO check if __LP64__ is better? 44 | # if __WORDSIZE == 64 45 | # define TM_LOAD(addr) _ITM_RU8(TXARGS (uint64_t *)addr) 46 | # define TM_STORE(addr, value) _ITM_WU8(TXARGS (uint64_t *)addr, (uint64_t)value) 47 | # else /* __WORDSIZE == 32 */ 48 | # define TM_LOAD(addr) _ITM_RU4(TXARGS (uint32_t *)addr) 49 | # define TM_STORE(addr, value) _ITM_WU4(TXARGS (uint32_t *)addr, (uint32_t)value) 50 | # endif /* __WORDSIZE == 32 */ 51 | # define TM_COMMIT _ITM_commitTransaction(TXARGS); } 52 | /* TODO Wrong for Intel */ 53 | # define TM_MALLOC(size) _ITM_malloc(TXARGS size) 54 | # define TM_FREE(addr) _ITM_free(TXARGS addr) 55 | # define TM_FREE2(addr, size) _ITM_free(TXARGS addr) 56 | 57 | # define TM_INIT _ITM_initializeProcess() 58 | # define TM_EXIT _ITM_finalizeProcess() 59 | # define TM_INIT_THREAD _ITM_initializeThread() 60 | # define TM_EXIT_THREAD _ITM_finalizeThread() 61 | 62 | /* Annotations used in this benchmark */ 63 | # define TM_SAFE 64 | # define TM_PURE 65 | 66 | #endif /* _TM_MACROS_H_ */ 67 | 68 | -------------------------------------------------------------------------------- /include/mod_ab.h: -------------------------------------------------------------------------------- 1 | /* 2 | * File: 3 | * mod_ab.h 4 | * Author(s): 5 | * Pascal Felber 6 | * Patrick Marlier 7 | * Description: 8 | * Module for gathering statistics about atomic blocks. 9 | * 10 | * Copyright (c) 2007-2014. 11 | * 12 | * This program is free software; you can redistribute it and/or 13 | * modify it under the terms of the GNU General Public License 14 | * as published by the Free Software Foundation, version 2 15 | * of the License. 16 | * 17 | * This program is distributed in the hope that it will be useful, 18 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 19 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 20 | * GNU General Public License for more details. 21 | * 22 | * This program has a dual license and can also be distributed 23 | * under the terms of the MIT license. 24 | */ 25 | 26 | /** 27 | * @file 28 | * Module for gathering statistics about transactions. This module 29 | * maintains aggregate statistics about all threads for every atomic 30 | * block in the application (distinguished using the identifier part 31 | * of the transaction attributes). 32 | * @author 33 | * Pascal Felber 34 | * Patrick Marlier 35 | * @date 36 | * 2007-2014 37 | */ 38 | 39 | #ifndef _MOD_AB_H_ 40 | # define _MOD_AB_H_ 41 | 42 | # include "stm.h" 43 | 44 | # ifdef __cplusplus 45 | extern "C" { 46 | # endif 47 | 48 | /** 49 | * Statistics associated with an atomic block. 50 | */ 51 | typedef struct stm_ab_stats { 52 | /** 53 | * Number of samples collected. 54 | */ 55 | unsigned long samples; 56 | /** 57 | * Arithmetic mean of the samples. 58 | */ 59 | double mean; 60 | /** 61 | * Variance of the samples. 62 | */ 63 | double variance; 64 | /** 65 | * Minimum value among all samples. 66 | */ 67 | double min; 68 | /** 69 | * Maximum value among all samples. 70 | */ 71 | double max; 72 | /** 73 | * 75th percentile (median). 74 | */ 75 | double percentile_50; 76 | /** 77 | * 90th percentile. 78 | */ 79 | double percentile_90; 80 | /** 81 | * 95th percentile. 82 | */ 83 | double percentile_95; 84 | /** 85 | * Sorted ramdom subset of the samples (Vitter's reservoir). 86 | */ 87 | double *reservoir; 88 | /** 89 | * Number of smaples in the reservoir. 90 | */ 91 | unsigned int reservoir_size; 92 | } stm_ab_stats_t; 93 | 94 | /** 95 | * Get statistics about an atomic block. 96 | * 97 | * @param id 98 | * Identifier of the atomic block (as specified in transaction 99 | * attributes). 100 | * @param stats 101 | * Pointer to the variable to should hold the statistics of the atomic 102 | * block. 103 | * @return 104 | * 1 upon success, 0 otherwise. 105 | */ 106 | int stm_get_ab_stats(int id, stm_ab_stats_t *stats); 107 | 108 | /** 109 | * Initialize the module. This function must be called once, from the 110 | * main thread, after initializing the STM library and before 111 | * performing any transactional operation. 112 | * 113 | * @param freq 114 | * Inverse sampling frequency (1 to keep all samples). 115 | * @param check 116 | * Pointer to a function that will be called to check if a sample is 117 | * valid and should be kept. The event will be discarded if and only 118 | * if the function returns 0. If no function is provided, all samples 119 | * will be kept. 120 | */ 121 | void mod_ab_init(int freq, int (*check)(void)); 122 | 123 | # ifdef __cplusplus 124 | } 125 | # endif 126 | 127 | #endif /* _MOD_AB_H_ */ 128 | -------------------------------------------------------------------------------- /include/mod_cb.h: -------------------------------------------------------------------------------- 1 | /* 2 | * File: 3 | * mod_cb.h 4 | * Author(s): 5 | * Pascal Felber 6 | * Patrick Marlier 7 | * Description: 8 | * Module for user callbacks. 9 | * 10 | * Copyright (c) 2007-2014. 11 | * 12 | * This program is free software; you can redistribute it and/or 13 | * modify it under the terms of the GNU General Public License 14 | * as published by the Free Software Foundation, version 2 15 | * of the License. 16 | * 17 | * This program is distributed in the hope that it will be useful, 18 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 19 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 20 | * GNU General Public License for more details. 21 | * 22 | * This program has a dual license and can also be distributed 23 | * under the terms of the MIT license. 24 | */ 25 | 26 | /** 27 | * @file 28 | * Module for user callbacks. 29 | * @author 30 | * Pascal Felber 31 | * Patrick Marlier 32 | * @date 33 | * 2007-2014 34 | */ 35 | 36 | #ifndef _MOD_CB_H_ 37 | # define _MOD_CB_H_ 38 | 39 | # include "stm.h" 40 | 41 | # ifdef __cplusplus 42 | extern "C" { 43 | # endif 44 | 45 | /** 46 | * Register an application-specific callback triggered when the current 47 | * transaction commits. The callback is automatically unregistered once 48 | * the transaction commits or aborts. If the transaction aborts, the 49 | * callback is never triggered. 50 | * 51 | * @param on_commit 52 | * Function called upon successful transaction commit. 53 | * @param arg 54 | * Parameter to be passed to the callback function. 55 | * @return 56 | * 1 if the callbacks have been successfully registered, 0 otherwise. 57 | */ 58 | int stm_on_commit(void (*on_commit)(void *arg), void *arg); 59 | 60 | /** 61 | * Register an application-specific callback triggered when the current 62 | * transaction aborts. The callback is automatically unregistered once 63 | * the transaction commits or aborts. If the transaction commits, the 64 | * callback is never triggered. 65 | * 66 | * @param on_abort 67 | * Function called upon transaction abort. 68 | * @param arg 69 | * Parameter to be passed to the callback function. 70 | * @return 71 | * 1 if the callbacks have been successfully registered, 0 otherwise. 72 | */ 73 | int stm_on_abort(void (*on_abort)(void *arg), void *arg); 74 | 75 | /** 76 | * Initialize the module. This function must be called once, from the 77 | * main thread, after initializing the STM library and before 78 | * performing any transactional operation. 79 | * 80 | */ 81 | void mod_cb_init(void); 82 | 83 | # ifdef __cplusplus 84 | } 85 | # endif 86 | 87 | #endif /* _MOD_CB_H_ */ 88 | -------------------------------------------------------------------------------- /include/mod_log.h: -------------------------------------------------------------------------------- 1 | /* 2 | * File: 3 | * mod_log.h 4 | * Author(s): 5 | * Pascal Felber 6 | * Patrick Marlier 7 | * Description: 8 | * Module for logging memory accesses. 9 | * 10 | * Copyright (c) 2007-2014. 11 | * 12 | * This program is free software; you can redistribute it and/or 13 | * modify it under the terms of the GNU General Public License 14 | * as published by the Free Software Foundation, version 2 15 | * of the License. 16 | * 17 | * This program is distributed in the hope that it will be useful, 18 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 19 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 20 | * GNU General Public License for more details. 21 | * 22 | * This program has a dual license and can also be distributed 23 | * under the terms of the MIT license. 24 | */ 25 | 26 | /** 27 | * @file 28 | * Module for logging memory accesses. Data is stored in an undo log. 29 | * Upon abort, modifications are reverted. Note that this module 30 | * should not be used for updating shared data as there are no 31 | * mechanisms to deal with concurrent accesses. 32 | * @author 33 | * Pascal Felber 34 | * Patrick Marlier 35 | * @date 36 | * 2007-2014 37 | */ 38 | 39 | #ifndef _MOD_LOG_H_ 40 | # define _MOD_LOG_H_ 41 | 42 | # include "stm.h" 43 | 44 | # ifdef __cplusplus 45 | extern "C" { 46 | # endif 47 | 48 | /** 49 | * Log word-sized value in transaction log. 50 | * 51 | * @param addr 52 | * Address of the memory location. 53 | */ 54 | void stm_log(stm_word_t *addr); 55 | 56 | /** 57 | * Log char 8-bit value in transaction log. 58 | * 59 | * @param addr 60 | * Address of the memory location. 61 | */ 62 | void stm_log_u8(uint8_t *addr); 63 | 64 | /** 65 | * Log char 16-bit value in transaction log. 66 | * 67 | * @param addr 68 | * Address of the memory location. 69 | */ 70 | void stm_log_u16(uint16_t *addr); 71 | 72 | /** 73 | * Log char 32-bit value in transaction log. 74 | * 75 | * @param addr 76 | * Address of the memory location. 77 | */ 78 | void stm_log_u32(uint32_t *addr); 79 | 80 | /** 81 | * Log char 64-bit value in transaction log. 82 | * 83 | * @param addr 84 | * Address of the memory location. 85 | */ 86 | void stm_log_u64(uint64_t *addr); 87 | 88 | /** 89 | * Log char value in transaction log. 90 | * 91 | * @param addr 92 | * Address of the memory location. 93 | */ 94 | void stm_log_char(char *addr); 95 | 96 | /** 97 | * Log unsigned char value in transaction log. 98 | * 99 | * @param addr 100 | * Address of the memory location. 101 | */ 102 | void stm_log_uchar(unsigned char *addr); 103 | 104 | /** 105 | * Log short value in transaction log. 106 | * 107 | * @param addr 108 | * Address of the memory location. 109 | */ 110 | void stm_log_short(short *addr); 111 | 112 | /** 113 | * Log unsigned short value in transaction log. 114 | * 115 | * @param addr 116 | * Address of the memory location. 117 | */ 118 | void stm_log_ushort(unsigned short *addr); 119 | 120 | /** 121 | * Log int value in transaction log. 122 | * 123 | * @param addr 124 | * Address of the memory location. 125 | */ 126 | void stm_log_int(int *addr); 127 | 128 | /** 129 | * Log unsigned int value in transaction log. 130 | * 131 | * @param addr 132 | * Address of the memory location. 133 | */ 134 | void stm_log_uint(unsigned int *addr); 135 | 136 | /** 137 | * Log long value in transaction log. 138 | * 139 | * @param addr 140 | * Address of the memory location. 141 | */ 142 | void stm_log_long(long *addr); 143 | 144 | /** 145 | * Log unsigned long value in transaction log. 146 | * 147 | * @param addr 148 | * Address of the memory location. 149 | */ 150 | void stm_log_ulong(unsigned long *addr); 151 | 152 | /** 153 | * Log float value in transaction log. 154 | * 155 | * @param addr 156 | * Address of the memory location. 157 | */ 158 | void stm_log_float(float *addr); 159 | 160 | /** 161 | * Log double value in transaction log. 162 | * 163 | * @param addr 164 | * Address of the memory location. 165 | */ 166 | void stm_log_double(double *addr); 167 | 168 | /** 169 | * Log pointer value in transaction log. 170 | * 171 | * @param addr 172 | * Address of the memory location. 173 | */ 174 | void stm_log_ptr(void **addr); 175 | 176 | /** 177 | * Log memory region in transaction log. 178 | * 179 | * @param addr 180 | * Address of the memory location. 181 | * @param size 182 | * Number of bytes to log. 183 | */ 184 | void stm_log_bytes(uint8_t *addr, size_t size); 185 | 186 | /** 187 | * Initialize the module. This function must be called once, from the 188 | * main thread, after initializing the STM library and before performing 189 | * any transactional operation. 190 | */ 191 | void mod_log_init(void); 192 | 193 | # ifdef __cplusplus 194 | } 195 | # endif 196 | 197 | #endif /* _MOD_LOG_H_ */ 198 | -------------------------------------------------------------------------------- /include/mod_mem.h: -------------------------------------------------------------------------------- 1 | /* 2 | * File: 3 | * mod_mem.h 4 | * Author(s): 5 | * Pascal Felber 6 | * Patrick Marlier 7 | * Description: 8 | * Module for dynamic memory management. 9 | * 10 | * Copyright (c) 2007-2014. 11 | * 12 | * This program is free software; you can redistribute it and/or 13 | * modify it under the terms of the GNU General Public License 14 | * as published by the Free Software Foundation, version 2 15 | * of the License. 16 | * 17 | * This program is distributed in the hope that it will be useful, 18 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 19 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 20 | * GNU General Public License for more details. 21 | * 22 | * This program has a dual license and can also be distributed 23 | * under the terms of the MIT license. 24 | */ 25 | 26 | /** 27 | * @file 28 | * Module for dynamic memory management. This module provides 29 | * functions for allocations and freeing memory inside transactions. 30 | * A block allocated inside the transaction will be implicitly freed 31 | * upon abort, and a block freed inside a transaction will only be 32 | * returned to the system upon commit. 33 | * @author 34 | * Pascal Felber 35 | * Patrick Marlier 36 | * @date 37 | * 2007-2014 38 | */ 39 | 40 | #ifndef _MOD_MEM_H_ 41 | # define _MOD_MEM_H_ 42 | 43 | # include "stm.h" 44 | 45 | # ifdef __cplusplus 46 | extern "C" { 47 | # endif 48 | 49 | //@{ 50 | /** 51 | * Allocate memory from inside a transaction. Allocated memory is 52 | * implicitly freed upon abort. 53 | * 54 | * @param size 55 | * Number of bytes to allocate. 56 | * @return 57 | * Pointer to the allocated memory block. 58 | */ 59 | void *stm_malloc(size_t size); 60 | void *stm_malloc_tx(struct stm_tx *tx, size_t size); 61 | //@} 62 | 63 | //@{ 64 | /** 65 | * Allocate initialized memory from inside a transaction. Allocated 66 | * memory is implicitly freed upon abort. 67 | * 68 | * @param nm 69 | * Size of the array to allocate. 70 | * @param size 71 | * Number of bytes to allocate. 72 | * @return 73 | * Pointer to the allocated memory block. 74 | */ 75 | void *stm_calloc(size_t nm, size_t size); 76 | void *stm_calloc_tx(struct stm_tx *tx, size_t nm, size_t size); 77 | //@} 78 | 79 | //@{ 80 | /** 81 | * Free memory from inside a transaction. Freed memory is only returned 82 | * to the system upon commit and can optionally be overwritten (more 83 | * precisely, the locks protecting the memory are acquired) to prevent 84 | * another transaction from accessing the freed memory and observe 85 | * inconsistent states. 86 | * 87 | * @param addr 88 | * Address of the memory block. 89 | * @param size 90 | * Number of bytes to overwrite. 91 | */ 92 | void stm_free(void *addr, size_t size); 93 | void stm_free_tx(struct stm_tx *tx, void *addr, size_t size); 94 | //@} 95 | 96 | //@{ 97 | /** 98 | * Free memory from inside a transaction. Freed memory is only returned 99 | * to the system upon commit and can optionally be overwritten (more 100 | * precisely, the locks protecting the memory are acquired) to prevent 101 | * another transaction from accessing the freed memory and observe 102 | * inconsistent states. 103 | * 104 | * @param addr 105 | * Address of the memory block. 106 | * @param idx 107 | * Index of the first byte to overwrite. 108 | * @param size 109 | * Number of bytes to overwrite. 110 | */ 111 | void stm_free2(void *addr, size_t idx, size_t size); 112 | void stm_free2_tx(struct stm_tx *tx, void *addr, size_t idx, size_t size); 113 | //@} 114 | 115 | /** 116 | * Initialize the module. This function must be called once, from the 117 | * main thread, after initializing the STM library and before 118 | * performing any transactional operation. 119 | * 120 | * @param gc 121 | * True (non-zero) to enable epoch-based garbage collector when 122 | * freeing memory in transactions. 123 | */ 124 | void mod_mem_init(int gc); 125 | 126 | # ifdef __cplusplus 127 | } 128 | # endif 129 | 130 | #endif /* _MOD_MEM_H_ */ 131 | -------------------------------------------------------------------------------- /include/mod_order.h: -------------------------------------------------------------------------------- 1 | /* 2 | * File: 3 | * mod_order.h 4 | * Author(s): 5 | * Pascal Felber 6 | * Patrick Marlier 7 | * Description: 8 | * Module to force transactions to commit in order. 9 | * 10 | * Copyright (c) 2007-2014. 11 | * 12 | * This program is free software; you can redistribute it and/or 13 | * modify it under the terms of the GNU General Public License 14 | * as published by the Free Software Foundation, version 2 15 | * of the License. 16 | * 17 | * This program is distributed in the hope that it will be useful, 18 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 19 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 20 | * GNU General Public License for more details. 21 | * 22 | * This program has a dual license and can also be distributed 23 | * under the terms of the MIT license. 24 | */ 25 | 26 | /** 27 | * @file 28 | * Module to force transactions to commit in order. The first transaction that 29 | * starts will be the first one to commit. This module requires CM_MODULAR. 30 | * @author 31 | * Pascal Felber 32 | * Patrick Marlier 33 | * @date 34 | * 2007-2014 35 | */ 36 | 37 | #ifndef _MOD_PRINT_H_ 38 | # define _MOD_PRINT_H_ 39 | 40 | # ifdef __cplusplus 41 | extern "C" { 42 | # endif 43 | 44 | /** 45 | * Initialize the module. This function must be called once, from the 46 | * main thread, after initializing the STM library and before 47 | * performing any transactional operation. 48 | */ 49 | void mod_order_init(void); 50 | 51 | # ifdef __cplusplus 52 | } 53 | # endif 54 | 55 | #endif /* _MOD_PRINT_H_ */ 56 | -------------------------------------------------------------------------------- /include/mod_print.h: -------------------------------------------------------------------------------- 1 | /* 2 | * File: 3 | * mod_print.h 4 | * Author(s): 5 | * Pascal Felber 6 | * Patrick Marlier 7 | * Description: 8 | * Module to test callbacks. 9 | * 10 | * Copyright (c) 2007-2014. 11 | * 12 | * This program is free software; you can redistribute it and/or 13 | * modify it under the terms of the GNU General Public License 14 | * as published by the Free Software Foundation, version 2 15 | * of the License. 16 | * 17 | * This program is distributed in the hope that it will be useful, 18 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 19 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 20 | * GNU General Public License for more details. 21 | * 22 | * This program has a dual license and can also be distributed 23 | * under the terms of the MIT license. 24 | */ 25 | 26 | /** 27 | * @file 28 | * Module to test callbacks. This module simply prints a message at 29 | * each invocation of a callback. 30 | * @author 31 | * Pascal Felber 32 | * Patrick Marlier 33 | * @date 34 | * 2007-2014 35 | */ 36 | 37 | #ifndef _MOD_PRINT_H_ 38 | # define _MOD_PRINT_H_ 39 | 40 | # ifdef __cplusplus 41 | extern "C" { 42 | # endif 43 | 44 | /** 45 | * Initialize the module. This function must be called once, from the 46 | * main thread, after initializing the STM library and before 47 | * performing any transactional operation. 48 | */ 49 | void mod_print_init(void); 50 | 51 | # ifdef __cplusplus 52 | } 53 | # endif 54 | 55 | #endif /* _MOD_PRINT_H_ */ 56 | -------------------------------------------------------------------------------- /include/mod_stats.h: -------------------------------------------------------------------------------- 1 | /* 2 | * File: 3 | * mod_stats.h 4 | * Author(s): 5 | * Pascal Felber 6 | * Patrick Marlier 7 | * Description: 8 | * Module for gathering statistics about transactions. 9 | * 10 | * Copyright (c) 2007-2014. 11 | * 12 | * This program is free software; you can redistribute it and/or 13 | * modify it under the terms of the GNU General Public License 14 | * as published by the Free Software Foundation, version 2 15 | * of the License. 16 | * 17 | * This program is distributed in the hope that it will be useful, 18 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 19 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 20 | * GNU General Public License for more details. 21 | * 22 | * This program has a dual license and can also be distributed 23 | * under the terms of the MIT license. 24 | */ 25 | 26 | /** 27 | * @file 28 | * Module for gathering statistics about transactions. This module 29 | * maintains both aggregate statistics about all threads (aggregates 30 | * are updated upon thread cleanup) and per-thread statistics. The 31 | * built-in statistics of the core STM library are more efficient and 32 | * detailed but this module is useful in case the library is compiled 33 | * without support for statistics. 34 | * @author 35 | * Pascal Felber 36 | * Patrick Marlier 37 | * @date 38 | * 2007-2014 39 | */ 40 | 41 | #ifndef _MOD_STATS_H_ 42 | # define _MOD_STATS_H_ 43 | 44 | # include "stm.h" 45 | 46 | # ifdef __cplusplus 47 | extern "C" { 48 | # endif 49 | 50 | /** 51 | * Get various statistics about the transactions of all threads. See 52 | * the source code (mod_stats.c) for a list of supported statistics. 53 | * 54 | * @param name 55 | * Name of the statistics. 56 | * @param val 57 | * Pointer to the variable that should hold the value of the 58 | * statistics. 59 | * @return 60 | * 1 upon success, 0 otherwise. 61 | */ 62 | int stm_get_global_stats(const char *name, void *val); 63 | 64 | /** 65 | * Get various statistics about the transactions of the current thread. 66 | * See the source code (mod_stats.c) for a list of supported statistics. 67 | * 68 | * @param name 69 | * Name of the statistics. 70 | * @param val 71 | * Pointer to the variable that should hold the value of the 72 | * statistics. 73 | * @return 74 | * 1 upon success, 0 otherwise. 75 | */ 76 | int stm_get_local_stats(const char *name, void *val); 77 | 78 | /** 79 | * Initialize the module. This function must be called once, from the 80 | * main thread, after initializing the STM library and before 81 | * performing any transactional operation. 82 | */ 83 | void mod_stats_init(void); 84 | 85 | # ifdef __cplusplus 86 | } 87 | # endif 88 | 89 | #endif /* _MOD_STATS_H_ */ 90 | -------------------------------------------------------------------------------- /lib/.gitignore: -------------------------------------------------------------------------------- 1 | # Ignore everything in this directory 2 | * 3 | # Except this file 4 | !.gitignore 5 | -------------------------------------------------------------------------------- /src/atomic.h: -------------------------------------------------------------------------------- 1 | /* 2 | * File: 3 | * atomic.h 4 | * Author(s): 5 | * Pascal Felber 6 | * Patrick Marlier 7 | * Description: 8 | * Atomic operations. 9 | * 10 | * Copyright (c) 2007-2014. 11 | * 12 | * This program is free software; you can redistribute it and/or 13 | * modify it under the terms of the GNU General Public License 14 | * as published by the Free Software Foundation, version 2 15 | * of the License. 16 | * 17 | * This program is distributed in the hope that it will be useful, 18 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 19 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 20 | * GNU General Public License for more details. 21 | * 22 | * This program has a dual license and can also be distributed 23 | * under the terms of the MIT license. 24 | */ 25 | 26 | #ifndef _ATOMIC_H_ 27 | # define _ATOMIC_H_ 28 | 29 | # ifdef ATOMIC_BUILTIN 30 | typedef volatile size_t atomic_t; 31 | # ifdef __INTEL_COMPILER 32 | # define ATOMIC_CB __memory_barrier() 33 | # else /* ! __INTEL_COMPILER, assuming __GNUC__ */ 34 | # define ATOMIC_CB __asm__ __volatile__("": : :"memory") 35 | # endif /* ! __INTEL_COMPILER */ 36 | # ifndef UNSAFE 37 | # warning "This is experimental and shouldn't be used" 38 | /* 39 | Note: __sync_ is available for GCC 4.2+ and ICC 11.1+ 40 | But these definitions are not 100% safe: 41 | * need 'a' to be volatile 42 | * no fence for read/store proposed (only full fence) 43 | C11 and C++11 also propose atomic operations. 44 | */ 45 | # define ATOMIC_CAS_FULL(a, e, v) (__sync_bool_compare_and_swap(a, e, v)) 46 | # define ATOMIC_FETCH_INC_FULL(a) (__sync_fetch_and_add(a, 1)) 47 | # define ATOMIC_FETCH_DEC_FULL(a) (__sync_fetch_and_add(a, -1)) 48 | # define ATOMIC_FETCH_ADD_FULL(a, v) (__sync_fetch_and_add(a, v)) 49 | # define ATOMIC_LOAD_ACQ(a) (*(a)) 50 | # define ATOMIC_LOAD(a) (*(a)) 51 | # define ATOMIC_STORE_REL(a, v) (*(a) = (v)) 52 | # define ATOMIC_STORE(a, v) (*(a) = (v)) 53 | # define ATOMIC_MB_READ /* Nothing */ 54 | # define ATOMIC_MB_WRITE /* Nothing */ 55 | # define ATOMIC_MB_FULL __sync_synchronize() 56 | # else 57 | /* Use only for testing purposes (single thread benchmarks) */ 58 | # define ATOMIC_CAS_FULL(a, e, v) (*(a) = (v), 1) 59 | # define ATOMIC_FETCH_INC_FULL(a) ((*(a))++) 60 | # define ATOMIC_FETCH_DEC_FULL(a) ((*(a))--) 61 | # define ATOMIC_FETCH_ADD_FULL(a, v) ((*(a)) += (v)) 62 | # define ATOMIC_LOAD_ACQ(a) (*(a)) 63 | # define ATOMIC_LOAD(a) (*(a)) 64 | # define ATOMIC_STORE_REL(a, v) (*(a) = (v)) 65 | # define ATOMIC_STORE(a, v) (*(a) = (v)) 66 | # define ATOMIC_MB_READ /* Nothing */ 67 | # define ATOMIC_MB_WRITE /* Nothing */ 68 | # define ATOMIC_MB_FULL /* Nothing */ 69 | # endif /* UNSAFE */ 70 | 71 | # else /* ! ATOMIC_BUILTIN */ 72 | /* NOTE: enable fence instructions for i386 and amd64 but the mfence instructions seems costly. */ 73 | /* # define AO_USE_PENTIUM4_INSTRS */ 74 | # include 75 | typedef AO_t atomic_t; 76 | # define ATOMIC_CB AO_compiler_barrier() 77 | # define ATOMIC_CAS_FULL(a, e, v) (AO_compare_and_swap_full((volatile AO_t *)(a), (AO_t)(e), (AO_t)(v))) 78 | # define ATOMIC_FETCH_INC_FULL(a) (AO_fetch_and_add1_full((volatile AO_t *)(a))) 79 | # define ATOMIC_FETCH_DEC_FULL(a) (AO_fetch_and_sub1_full((volatile AO_t *)(a))) 80 | # define ATOMIC_FETCH_ADD_FULL(a, v) (AO_fetch_and_add_full((volatile AO_t *)(a), (AO_t)(v))) 81 | # ifdef SAFE 82 | # define ATOMIC_LOAD_ACQ(a) (AO_load_full((volatile AO_t *)(a))) 83 | # define ATOMIC_LOAD(a) (AO_load_full((volatile AO_t *)(a))) 84 | # define ATOMIC_STORE_REL(a, v) (AO_store_full((volatile AO_t *)(a), (AO_t)(v))) 85 | # define ATOMIC_STORE(a, v) (AO_store_full((volatile AO_t *)(a), (AO_t)(v))) 86 | # define ATOMIC_MB_READ AO_nop_full() 87 | # define ATOMIC_MB_WRITE AO_nop_full() 88 | # define ATOMIC_MB_FULL AO_nop_full() 89 | # else /* ! SAFE */ 90 | # define ATOMIC_LOAD_ACQ(a) (AO_load_acquire_read((volatile AO_t *)(a))) 91 | # define ATOMIC_LOAD(a) (*((volatile AO_t *)(a))) 92 | # define ATOMIC_STORE_REL(a, v) (AO_store_release((volatile AO_t *)(a), (AO_t)(v))) 93 | # define ATOMIC_STORE(a, v) (*((volatile AO_t *)(a)) = (AO_t)(v)) 94 | # define ATOMIC_MB_READ AO_nop_read() 95 | # define ATOMIC_MB_WRITE AO_nop_write() 96 | # define ATOMIC_MB_FULL AO_nop_full() 97 | # endif /* ! SAFE */ 98 | # endif /* ! NO_AO */ 99 | 100 | #endif /* _ATOMIC_H_ */ 101 | -------------------------------------------------------------------------------- /src/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 | -------------------------------------------------------------------------------- /src/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 | -------------------------------------------------------------------------------- /src/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 | -------------------------------------------------------------------------------- /src/atomic_ops/all_acquire_release_volatile.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 | * Describes architectures on which volatile AO_t, unsigned char, unsigned 25 | * short, and unsigned int loads and stores have acquire/release semantics for 26 | * all normally legal alignments. 27 | */ 28 | //#include "acquire_release_volatile.h" 29 | //#include "char_acquire_release_volatile.h" 30 | //#include "short_acquire_release_volatile.h" 31 | //#include "int_acquire_release_volatile.h" 32 | 33 | /* 34 | * This file adds definitions appropriate for environments in which an AO_t 35 | * volatile load has acquire semantics, and an AO_t volatile store has release 36 | * semantics. This is arguably supposed to be true with the standard Itanium 37 | * software conventions. 38 | */ 39 | 40 | /* 41 | * Empirically gcc/ia64 does some reordering of ordinary operations around volatiles 42 | * even when we think it shouldn't. Gcc 3.3 and earlier could reorder a volatile store 43 | * with another store. As of March 2005, gcc pre-4 reused previously computed 44 | * common subexpressions across a volatile load. 45 | * Hence we now add compiler barriers for gcc. 46 | */ 47 | #if !defined(AO_GCC_BARRIER) 48 | # if defined(__GNUC__) 49 | # define AO_GCC_BARRIER() AO_compiler_barrier() 50 | # else 51 | # define AO_GCC_BARRIER() 52 | # endif 53 | #endif 54 | 55 | AO_INLINE AO_t 56 | AO_load_acquire(const volatile AO_t *p) 57 | { 58 | AO_t result = *p; 59 | /* A normal volatile load generates an ld.acq */ 60 | AO_GCC_BARRIER(); 61 | return result; 62 | } 63 | #define AO_HAVE_load_acquire 64 | 65 | AO_INLINE void 66 | AO_store_release(volatile AO_t *p, AO_t val) 67 | { 68 | AO_GCC_BARRIER(); 69 | /* A normal volatile store generates an st.rel */ 70 | *p = val; 71 | } 72 | #define AO_HAVE_store_release 73 | 74 | /* 75 | * This file adds definitions appropriate for environments in which an unsigned char 76 | * volatile load has acquire semantics, and an unsigned char volatile store has release 77 | * semantics. This is true with the standard Itanium ABI. 78 | */ 79 | #if !defined(AO_GCC_BARRIER) 80 | # if defined(__GNUC__) 81 | # define AO_GCC_BARRIER() AO_compiler_barrier() 82 | # else 83 | # define AO_GCC_BARRIER() 84 | # endif 85 | #endif 86 | 87 | AO_INLINE unsigned char 88 | AO_char_load_acquire(const volatile unsigned char *p) 89 | { 90 | unsigned char result = *p; 91 | /* A normal volatile load generates an ld.acq */ 92 | AO_GCC_BARRIER(); 93 | return result; 94 | } 95 | #define AO_HAVE_char_load_acquire 96 | 97 | AO_INLINE void 98 | AO_char_store_release(volatile unsigned char *p, unsigned char val) 99 | { 100 | AO_GCC_BARRIER(); 101 | /* A normal volatile store generates an st.rel */ 102 | *p = val; 103 | } 104 | #define AO_HAVE_char_store_release 105 | 106 | /* 107 | * This file adds definitions appropriate for environments in which an unsigned short 108 | * volatile load has acquire semantics, and an unsigned short volatile store has release 109 | * semantics. This is true with the standard Itanium ABI. 110 | */ 111 | #if !defined(AO_GCC_BARRIER) 112 | # if defined(__GNUC__) 113 | # define AO_GCC_BARRIER() AO_compiler_barrier() 114 | # else 115 | # define AO_GCC_BARRIER() 116 | # endif 117 | #endif 118 | 119 | AO_INLINE unsigned short 120 | AO_short_load_acquire(const volatile unsigned short *p) 121 | { 122 | unsigned short result = *p; 123 | /* A normal volatile load generates an ld.acq */ 124 | AO_GCC_BARRIER(); 125 | return result; 126 | } 127 | #define AO_HAVE_short_load_acquire 128 | 129 | AO_INLINE void 130 | AO_short_store_release(volatile unsigned short *p, unsigned short val) 131 | { 132 | AO_GCC_BARRIER(); 133 | /* A normal volatile store generates an st.rel */ 134 | *p = val; 135 | } 136 | #define AO_HAVE_short_store_release 137 | 138 | /* 139 | * This file adds definitions appropriate for environments in which an unsigned 140 | * int volatile load has acquire semantics, and an unsigned short volatile 141 | * store has release semantics. This is true with the standard Itanium ABI. 142 | */ 143 | #if !defined(AO_GCC_BARRIER) 144 | # if defined(__GNUC__) 145 | # define AO_GCC_BARRIER() AO_compiler_barrier() 146 | # else 147 | # define AO_GCC_BARRIER() 148 | # endif 149 | #endif 150 | 151 | AO_INLINE unsigned int 152 | AO_int_load_acquire(const volatile unsigned int *p) 153 | { 154 | unsigned int result = *p; 155 | /* A normal volatile load generates an ld.acq */ 156 | AO_GCC_BARRIER(); 157 | return result; 158 | } 159 | #define AO_HAVE_int_load_acquire 160 | 161 | AO_INLINE void 162 | AO_int_store_release(volatile unsigned int *p, unsigned int val) 163 | { 164 | AO_GCC_BARRIER(); 165 | /* A normal volatile store generates an st.rel */ 166 | *p = val; 167 | } 168 | #define AO_HAVE_int_store_release 169 | -------------------------------------------------------------------------------- /src/atomic_ops/ao_t_is_int.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2003-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 | * Inclusion of this file signifies that AO_t is in fact int. Hence 25 | * any AO_... operations can also server as AO_int_... operations. 26 | * We currently define only the more important ones here, and allow for 27 | * the normal generalization process to define the others. 28 | * We should probably add others in the future. 29 | */ 30 | 31 | #if defined(AO_HAVE_compare_and_swap_full) && \ 32 | !defined(AO_HAVE_int_compare_and_swap_full) 33 | # define AO_int_compare_and_swap_full(addr, old, new_val) \ 34 | AO_compare_and_swap_full((volatile AO_t *)(addr), \ 35 | (AO_t)(old), (AO_t)(new_val)) 36 | # define AO_HAVE_int_compare_and_swap_full 37 | # endif 38 | 39 | #if defined(AO_HAVE_compare_and_swap_acquire) && \ 40 | !defined(AO_HAVE_int_compare_and_swap_acquire) 41 | # define AO_int_compare_and_swap_acquire(addr, old, new_val) \ 42 | AO_compare_and_swap_acquire((volatile AO_t *)(addr), \ 43 | (AO_t)(old), (AO_t)(new_val)) 44 | # define AO_HAVE_int_compare_and_swap_acquire 45 | # endif 46 | 47 | #if defined(AO_HAVE_compare_and_swap_release) && \ 48 | !defined(AO_HAVE_int_compare_and_swap_release) 49 | # define AO_int_compare_and_swap_release(addr, old, new_val) \ 50 | AO_compare_and_swap_release((volatile AO_t *)(addr), \ 51 | (AO_t)(old), (AO_t)(new_val)) 52 | # define AO_HAVE_int_compare_and_swap_release 53 | # endif 54 | 55 | #if defined(AO_HAVE_compare_and_swap_write) && \ 56 | !defined(AO_HAVE_int_compare_and_swap_write) 57 | # define AO_int_compare_and_swap_write(addr, old, new_val) \ 58 | AO_compare_and_swap_write((volatile AO_t *)(addr), \ 59 | (AO_t)(old), (AO_t)(new_val)) 60 | # define AO_HAVE_int_compare_and_swap_write 61 | # endif 62 | 63 | #if defined(AO_HAVE_compare_and_swap_read) && \ 64 | !defined(AO_HAVE_int_compare_and_swap_read) 65 | # define AO_int_compare_and_swap_read(addr, old, new_val) \ 66 | AO_compare_and_swap_read((volatile AO_t *)(addr), \ 67 | (AO_t)(old), (AO_t)(new_val)) 68 | # define AO_HAVE_int_compare_and_swap_read 69 | # endif 70 | 71 | #if defined(AO_HAVE_compare_and_swap) && \ 72 | !defined(AO_HAVE_int_compare_and_swap) 73 | # define AO_int_compare_and_swap(addr, old, new_val) \ 74 | AO_compare_and_swap((volatile AO_t *)(addr), \ 75 | (AO_t)(old), (AO_t)(new_val)) 76 | # define AO_HAVE_int_compare_and_swap 77 | # endif 78 | 79 | #if defined(AO_HAVE_load_acquire) && \ 80 | !defined(AO_HAVE_int_load_acquire) 81 | # define AO_int_load_acquire(addr) \ 82 | (int)AO_load_acquire((const volatile AO_t *)(addr)) 83 | # define AO_HAVE_int_load_acquire 84 | # endif 85 | 86 | #if defined(AO_HAVE_store_release) && \ 87 | !defined(AO_HAVE_int_store_release) 88 | # define AO_int_store_release(addr, val) \ 89 | AO_store_release((volatile AO_t *)(addr), (AO_t)(val)) 90 | # define AO_HAVE_int_store_release 91 | # endif 92 | 93 | #if defined(AO_HAVE_fetch_and_add_full) && \ 94 | !defined(AO_HAVE_int_fetch_and_add_full) 95 | # define AO_int_fetch_and_add_full(addr, incr) \ 96 | (int)AO_fetch_and_add_full((volatile AO_t *)(addr), (AO_t)(incr)) 97 | # define AO_HAVE_int_fetch_and_add_full 98 | # endif 99 | 100 | #if defined(AO_HAVE_fetch_and_add1_acquire) && \ 101 | !defined(AO_HAVE_int_fetch_and_add1_acquire) 102 | # define AO_int_fetch_and_add1_acquire(addr) \ 103 | (int)AO_fetch_and_add1_acquire((volatile AO_t *)(addr)) 104 | # define AO_HAVE_int_fetch_and_add1_acquire 105 | # endif 106 | 107 | #if defined(AO_HAVE_fetch_and_add1_release) && \ 108 | !defined(AO_HAVE_int_fetch_and_add1_release) 109 | # define AO_int_fetch_and_add1_release(addr) \ 110 | (int)AO_fetch_and_add1_release((volatile AO_t *)(addr)) 111 | # define AO_HAVE_int_fetch_and_add1_release 112 | # endif 113 | 114 | #if defined(AO_HAVE_fetch_and_sub1_acquire) && \ 115 | !defined(AO_HAVE_int_fetch_and_sub1_acquire) 116 | # define AO_int_fetch_and_sub1_acquire(addr) \ 117 | (int)AO_fetch_and_sub1_acquire((volatile AO_t *)(addr)) 118 | # define AO_HAVE_int_fetch_and_sub1_acquire 119 | # endif 120 | 121 | #if defined(AO_HAVE_fetch_and_sub1_release) && \ 122 | !defined(AO_HAVE_int_fetch_and_sub1_release) 123 | # define AO_int_fetch_and_sub1_release(addr) \ 124 | (int)AO_fetch_and_sub1_release((volatile AO_t *)(addr)) 125 | # define AO_HAVE_int_fetch_and_sub1_release 126 | # endif 127 | -------------------------------------------------------------------------------- /src/atomic_ops/ordered_except_wr.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 | #include "read_ordered.h" 31 | 32 | AO_INLINE void 33 | AO_nop_write(void) 34 | { 35 | AO_compiler_barrier(); 36 | /* sfence according to Intel docs. Pentium 3 and up. */ 37 | /* Unnecessary for cached accesses? */ 38 | } 39 | 40 | #define AO_HAVE_NOP_WRITE 41 | 42 | #if defined(AO_HAVE_store) 43 | 44 | AO_INLINE void 45 | AO_store_write(volatile AO_t *addr, AO_t val) 46 | { 47 | AO_compiler_barrier(); 48 | AO_store(addr, val); 49 | } 50 | # define AO_HAVE_store_write 51 | 52 | # define AO_store_release(addr, val) AO_store_write(addr, val) 53 | # define AO_HAVE_store_release 54 | 55 | #endif /* AO_HAVE_store */ 56 | 57 | #if defined(AO_HAVE_char_store) 58 | 59 | AO_INLINE void 60 | AO_char_store_write(volatile unsigned char *addr, unsigned char val) 61 | { 62 | AO_compiler_barrier(); 63 | AO_char_store(addr, val); 64 | } 65 | # define AO_HAVE_char_store_write 66 | 67 | # define AO_char_store_release(addr, val) AO_char_store_write(addr, val) 68 | # define AO_HAVE_char_store_release 69 | 70 | #endif /* AO_HAVE_char_store */ 71 | 72 | #if defined(AO_HAVE_short_store) 73 | 74 | AO_INLINE void 75 | AO_short_store_write(volatile unsigned short *addr, unsigned short val) 76 | { 77 | AO_compiler_barrier(); 78 | AO_short_store(addr, val); 79 | } 80 | # define AO_HAVE_short_store_write 81 | 82 | # define AO_short_store_release(addr, val) AO_short_store_write(addr, val) 83 | # define AO_HAVE_short_store_release 84 | 85 | #endif /* AO_HAVE_short_store */ 86 | 87 | #if defined(AO_HAVE_int_store) 88 | 89 | AO_INLINE void 90 | AO_int_store_write(volatile unsigned int *addr, unsigned int val) 91 | { 92 | AO_compiler_barrier(); 93 | AO_int_store(addr, val); 94 | } 95 | # define AO_HAVE_int_store_write 96 | 97 | # define AO_int_store_release(addr, val) AO_int_store_write(addr, val) 98 | # define AO_HAVE_int_store_release 99 | 100 | #endif /* AO_HAVE_int_store */ 101 | -------------------------------------------------------------------------------- /src/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 | -------------------------------------------------------------------------------- /src/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 | -------------------------------------------------------------------------------- /src/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 | -------------------------------------------------------------------------------- /src/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 | -------------------------------------------------------------------------------- /src/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 | -------------------------------------------------------------------------------- /src/atomic_ops/x86.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 | * Some of the machine specific code was borrowed from our GC distribution. 17 | */ 18 | 19 | /* The following really assume we have a 486 or better. Unfortunately */ 20 | /* gcc doesn't define a suitable feature test macro based on command */ 21 | /* line options. */ 22 | /* We should perhaps test dynamically. */ 23 | 24 | #include "./aligned_atomic_load_store.h" 25 | 26 | /* Real X86 implementations, except for some old WinChips, appear */ 27 | /* to enforce ordering between memory operations, EXCEPT that a later */ 28 | /* read can pass earlier writes, presumably due to the visible */ 29 | /* presence of store buffers. */ 30 | /* We ignore both the WinChips, and the fact that the official specs */ 31 | /* seem to be much weaker (and arguably too weak to be usable). */ 32 | 33 | #include "./ordered_except_wr.h" 34 | 35 | #include "./test_and_set_t_is_char.h" 36 | 37 | #include "./standard_ao_double_t.h" 38 | 39 | #if defined(AO_USE_PENTIUM4_INSTRS) 40 | AO_INLINE void 41 | AO_nop_full(void) 42 | { 43 | __asm__ __volatile__("mfence" : : : "memory"); 44 | } 45 | 46 | #define AO_HAVE_nop_full 47 | 48 | #else 49 | 50 | /* We could use the cpuid instruction. But that seems to be slower */ 51 | /* than the default implementation based on test_and_set_full. Thus */ 52 | /* we omit that bit of misinformation here. */ 53 | 54 | #endif 55 | 56 | /* As far as we can tell, the lfence and sfence instructions are not */ 57 | /* currently needed or useful for cached memory accesses. */ 58 | 59 | /* Really only works for 486 and later */ 60 | AO_INLINE AO_t 61 | AO_fetch_and_add_full (volatile AO_t *p, AO_t incr) 62 | { 63 | AO_t result; 64 | 65 | __asm__ __volatile__ ("lock; xaddl %0, %1" : 66 | "=r" (result), "=m" (*p) : "0" (incr), "m" (*p) 67 | : "memory"); 68 | return result; 69 | } 70 | 71 | #define AO_HAVE_fetch_and_add_full 72 | 73 | AO_INLINE unsigned char 74 | AO_char_fetch_and_add_full (volatile unsigned char *p, unsigned char incr) 75 | { 76 | unsigned char result; 77 | 78 | __asm__ __volatile__ ("lock; xaddb %0, %1" : 79 | "=q" (result), "=m" (*p) : "0" (incr), "m" (*p) 80 | : "memory"); 81 | return result; 82 | } 83 | 84 | #define AO_HAVE_char_fetch_and_add_full 85 | 86 | AO_INLINE unsigned short 87 | AO_short_fetch_and_add_full (volatile unsigned short *p, unsigned short incr) 88 | { 89 | unsigned short result; 90 | 91 | __asm__ __volatile__ ("lock; xaddw %0, %1" : 92 | "=r" (result), "=m" (*p) : "0" (incr), "m" (*p) 93 | : "memory"); 94 | return result; 95 | } 96 | 97 | #define AO_HAVE_short_fetch_and_add_full 98 | 99 | /* Really only works for 486 and later */ 100 | AO_INLINE void 101 | AO_or_full (volatile AO_t *p, AO_t incr) 102 | { 103 | __asm__ __volatile__ ("lock; orl %1, %0" : 104 | "=m" (*p) : "r" (incr), "m" (*p) : "memory"); 105 | } 106 | 107 | #define AO_HAVE_or_full 108 | 109 | AO_INLINE AO_TS_VAL_t 110 | AO_test_and_set_full(volatile AO_TS_t *addr) 111 | { 112 | unsigned char oldval; 113 | /* Note: the "xchg" instruction does not need a "lock" prefix */ 114 | __asm__ __volatile__("xchgb %0, %1" 115 | : "=q"(oldval), "=m"(*addr) 116 | : "0"((unsigned char)0xff), "m"(*addr) : "memory"); 117 | return (AO_TS_VAL_t)oldval; 118 | } 119 | 120 | #define AO_HAVE_test_and_set_full 121 | 122 | /* Returns nonzero if the comparison succeeded. */ 123 | AO_INLINE int 124 | AO_compare_and_swap_full(volatile AO_t *addr, AO_t old, AO_t new_val) 125 | { 126 | # ifdef AO_USE_SYNC_CAS_BUILTIN 127 | return (int)__sync_bool_compare_and_swap(addr, old, new_val); 128 | # else 129 | char result; 130 | __asm__ __volatile__("lock; cmpxchgl %3, %0; setz %1" 131 | : "=m" (*addr), "=a" (result) 132 | : "m" (*addr), "r" (new_val), "a" (old) : "memory"); 133 | return (int)result; 134 | # endif 135 | } 136 | 137 | #define AO_HAVE_compare_and_swap_full 138 | 139 | /* Returns nonzero if the comparison succeeded. */ 140 | /* Really requires at least a Pentium. */ 141 | AO_INLINE int 142 | AO_compare_double_and_swap_double_full(volatile AO_double_t *addr, 143 | AO_t old_val1, AO_t old_val2, 144 | AO_t new_val1, AO_t new_val2) 145 | { 146 | char result; 147 | #if __PIC__ 148 | /* If PIC is turned on, we can't use %ebx as it is reserved for the 149 | GOT pointer. We can save and restore %ebx because GCC won't be 150 | using it for anything else (such as any of the m operands) */ 151 | __asm__ __volatile__("pushl %%ebx;" /* save ebx used for PIC GOT ptr */ 152 | "movl %6,%%ebx;" /* move new_val2 to %ebx */ 153 | "lock; cmpxchg8b %0; setz %1;" 154 | "pop %%ebx;" /* restore %ebx */ 155 | : "=m"(*addr), "=a"(result) 156 | : "m"(*addr), "d" (old_val2), "a" (old_val1), 157 | "c" (new_val2), "m" (new_val1) : "memory"); 158 | #else 159 | /* We can't just do the same thing in non-PIC mode, because GCC 160 | * might be using %ebx as the memory operand. We could have ifdef'd 161 | * in a clobber, but there's no point doing the push/pop if we don't 162 | * have to. */ 163 | __asm__ __volatile__("lock; cmpxchg8b %0; setz %1;" 164 | : "=m"(*addr), "=a"(result) 165 | : "m"(*addr), "d" (old_val2), "a" (old_val1), 166 | "c" (new_val2), "b" (new_val1) : "memory"); 167 | #endif 168 | return (int) result; 169 | } 170 | 171 | #define AO_HAVE_compare_double_and_swap_double_full 172 | 173 | #include "./ao_t_is_int.h" 174 | -------------------------------------------------------------------------------- /src/atomic_ops/x86_64.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 | * Some of the machine specific code was borrowed from our GC distribution. 17 | */ 18 | 19 | #include "./aligned_atomic_load_store.h" 20 | 21 | /* Real X86 implementations appear */ 22 | /* to enforce ordering between memory operations, EXCEPT that a later */ 23 | /* read can pass earlier writes, presumably due to the visible */ 24 | /* presence of store buffers. */ 25 | /* We ignore the fact that the official specs */ 26 | /* seem to be much weaker (and arguably too weak to be usable). */ 27 | 28 | #include "./ordered_except_wr.h" 29 | 30 | #include "./test_and_set_t_is_char.h" 31 | 32 | #include "./standard_ao_double_t.h" 33 | 34 | AO_INLINE void 35 | AO_nop_full(void) 36 | { 37 | /* Note: "mfence" (SSE2) is supported on all x86_64/amd64 chips. */ 38 | __asm__ __volatile__("mfence" : : : "memory"); 39 | } 40 | 41 | #define AO_HAVE_nop_full 42 | 43 | /* As far as we can tell, the lfence and sfence instructions are not */ 44 | /* currently needed or useful for cached memory accesses. */ 45 | 46 | AO_INLINE AO_t 47 | AO_fetch_and_add_full (volatile AO_t *p, AO_t incr) 48 | { 49 | AO_t result; 50 | 51 | __asm__ __volatile__ ("lock; xaddq %0, %1" : 52 | "=r" (result), "=m" (*p) : "0" (incr), "m" (*p) 53 | : "memory"); 54 | return result; 55 | } 56 | 57 | #define AO_HAVE_fetch_and_add_full 58 | 59 | AO_INLINE unsigned char 60 | AO_char_fetch_and_add_full (volatile unsigned char *p, unsigned char incr) 61 | { 62 | unsigned char result; 63 | 64 | __asm__ __volatile__ ("lock; xaddb %0, %1" : 65 | "=q" (result), "=m" (*p) : "0" (incr), "m" (*p) 66 | : "memory"); 67 | return result; 68 | } 69 | 70 | #define AO_HAVE_char_fetch_and_add_full 71 | 72 | AO_INLINE unsigned short 73 | AO_short_fetch_and_add_full (volatile unsigned short *p, unsigned short incr) 74 | { 75 | unsigned short result; 76 | 77 | __asm__ __volatile__ ("lock; xaddw %0, %1" : 78 | "=r" (result), "=m" (*p) : "0" (incr), "m" (*p) 79 | : "memory"); 80 | return result; 81 | } 82 | 83 | #define AO_HAVE_short_fetch_and_add_full 84 | 85 | AO_INLINE unsigned int 86 | AO_int_fetch_and_add_full (volatile unsigned int *p, unsigned int incr) 87 | { 88 | unsigned int result; 89 | 90 | __asm__ __volatile__ ("lock; xaddl %0, %1" : 91 | "=r" (result), "=m" (*p) : "0" (incr), "m" (*p) 92 | : "memory"); 93 | return result; 94 | } 95 | 96 | #define AO_HAVE_int_fetch_and_add_full 97 | 98 | AO_INLINE void 99 | AO_or_full (volatile AO_t *p, AO_t incr) 100 | { 101 | __asm__ __volatile__ ("lock; orq %1, %0" : 102 | "=m" (*p) : "r" (incr), "m" (*p) : "memory"); 103 | } 104 | 105 | #define AO_HAVE_or_full 106 | 107 | AO_INLINE AO_TS_VAL_t 108 | AO_test_and_set_full(volatile AO_TS_t *addr) 109 | { 110 | unsigned char oldval; 111 | /* Note: the "xchg" instruction does not need a "lock" prefix */ 112 | __asm__ __volatile__("xchgb %0, %1" 113 | : "=q"(oldval), "=m"(*addr) 114 | : "0"((unsigned char)0xff), "m"(*addr) : "memory"); 115 | return (AO_TS_VAL_t)oldval; 116 | } 117 | 118 | #define AO_HAVE_test_and_set_full 119 | 120 | /* Returns nonzero if the comparison succeeded. */ 121 | AO_INLINE int 122 | AO_compare_and_swap_full(volatile AO_t *addr, AO_t old, AO_t new_val) 123 | { 124 | # ifdef AO_USE_SYNC_CAS_BUILTIN 125 | return (int)__sync_bool_compare_and_swap(addr, old, new_val); 126 | # else 127 | char result; 128 | __asm__ __volatile__("lock; cmpxchgq %3, %0; setz %1" 129 | : "=m" (*addr), "=a" (result) 130 | : "m" (*addr), "r" (new_val), "a" (old) : "memory"); 131 | return (int) result; 132 | # endif 133 | } 134 | 135 | #define AO_HAVE_compare_and_swap_full 136 | 137 | #ifdef AO_CMPXCHG16B_AVAILABLE 138 | /* NEC LE-IT: older AMD Opterons are missing this instruction. 139 | * On these machines SIGILL will be thrown. 140 | * Define AO_WEAK_DOUBLE_CAS_EMULATION to have an emulated 141 | * (lock based) version available */ 142 | /* HB: Changed this to not define either by default. There are 143 | * enough machines and tool chains around on which cmpxchg16b 144 | * doesn't work. And the emulation is unsafe by our usual rules. 145 | * Hoewever both are clearly useful in certain cases. 146 | */ 147 | AO_INLINE int 148 | AO_compare_double_and_swap_double_full(volatile AO_double_t *addr, 149 | AO_t old_val1, AO_t old_val2, 150 | AO_t new_val1, AO_t new_val2) 151 | { 152 | char result; 153 | __asm__ __volatile__("lock; cmpxchg16b %0; setz %1" 154 | : "=m"(*addr), "=a"(result) 155 | : "m"(*addr), "d" (old_val2), "a" (old_val1), 156 | "c" (new_val2), "b" (new_val1) : "memory"); 157 | return (int) result; 158 | } 159 | #define AO_HAVE_compare_double_and_swap_double_full 160 | #else 161 | /* this one provides spinlock based emulation of CAS implemented in */ 162 | /* atomic_ops.c. We probably do not want to do this here, since it is */ 163 | /* not atomic with respect to other kinds of updates of *addr. On the */ 164 | /* other hand, this may be a useful facility on occasion. */ 165 | #ifdef AO_WEAK_DOUBLE_CAS_EMULATION 166 | int AO_compare_double_and_swap_double_emulation(volatile AO_double_t *addr, 167 | AO_t old_val1, AO_t old_val2, 168 | AO_t new_val1, AO_t new_val2); 169 | 170 | AO_INLINE int 171 | AO_compare_double_and_swap_double_full(volatile AO_double_t *addr, 172 | AO_t old_val1, AO_t old_val2, 173 | AO_t new_val1, AO_t new_val2) 174 | { 175 | return AO_compare_double_and_swap_double_emulation(addr, 176 | old_val1, old_val2, 177 | new_val1, new_val2); 178 | } 179 | #define AO_HAVE_compare_double_and_swap_double_full 180 | #endif /* AO_WEAK_DOUBLE_CAS_EMULATION */ 181 | #endif /* AO_CMPXCHG16B_AVAILABLE */ 182 | -------------------------------------------------------------------------------- /src/gc.h: -------------------------------------------------------------------------------- 1 | /* 2 | * File: 3 | * gc.h 4 | * Author(s): 5 | * Pascal Felber 6 | * Patrick Marlier 7 | * Description: 8 | * Epoch-based garbage collector. 9 | * 10 | * Copyright (c) 2007-2014. 11 | * 12 | * This program is free software; you can redistribute it and/or 13 | * modify it under the terms of the GNU General Public License 14 | * as published by the Free Software Foundation, version 2 15 | * of the License. 16 | * 17 | * This program is distributed in the hope that it will be useful, 18 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 19 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 20 | * GNU General Public License for more details. 21 | * 22 | * This program has a dual license and can also be distributed 23 | * under the terms of the MIT license. 24 | */ 25 | 26 | #ifndef _GC_H_ 27 | # define _GC_H_ 28 | 29 | # include 30 | # include 31 | 32 | # ifdef __cplusplus 33 | extern "C" { 34 | # endif 35 | 36 | typedef uintptr_t gc_word_t; 37 | 38 | void gc_init(gc_word_t (*epoch)(void)); 39 | void gc_exit(void); 40 | 41 | void gc_init_thread(void); 42 | void gc_exit_thread(void); 43 | 44 | void gc_set_epoch(gc_word_t epoch); 45 | 46 | void gc_free(void *addr, gc_word_t epoch); 47 | 48 | void gc_cleanup(void); 49 | 50 | void gc_cleanup_all(void); 51 | 52 | void gc_reset(void); 53 | 54 | # ifdef __cplusplus 55 | } 56 | # endif 57 | 58 | #endif /* _GC_H_ */ 59 | -------------------------------------------------------------------------------- /src/mod_order.c: -------------------------------------------------------------------------------- 1 | /* 2 | * File: 3 | * mod_order.c 4 | * Author(s): 5 | * Pascal Felber 6 | * Patrick Marlier 7 | * Description: 8 | * Module to force transactions to commit in order. 9 | * 10 | * Copyright (c) 2007-2014. 11 | * 12 | * This program is free software; you can redistribute it and/or 13 | * modify it under the terms of the GNU General Public License 14 | * as published by the Free Software Foundation, version 2 15 | * of the License. 16 | * 17 | * This program is distributed in the hope that it will be useful, 18 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 19 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 20 | * GNU General Public License for more details. 21 | * 22 | * This program has a dual license and can also be distributed 23 | * under the terms of the MIT license. 24 | */ 25 | 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include "atomic.h" 31 | #include "utils.h" 32 | #include "mod_order.h" 33 | 34 | #define KILL_SELF 0x00 35 | #define KILL_OTHER 0x01 36 | 37 | /* XXX Maybe these two could be in the same cacheline. */ 38 | ALIGNED static stm_word_t mod_order_ts_next = 0; 39 | ALIGNED static stm_word_t mod_order_ts_commit = 0; 40 | static int mod_order_key; 41 | static int mod_order_initialized = 0; 42 | 43 | static void mod_order_on_start(void *arg) 44 | { 45 | stm_word_t ts; 46 | /* Get a timestamp for commit */ 47 | ts = ATOMIC_FETCH_INC_FULL(&mod_order_ts_next); 48 | stm_set_specific(mod_order_key, (void *)ts); 49 | } 50 | 51 | static void mod_order_on_precommit(void *arg) 52 | { 53 | stm_word_t my_ts, current_ts; 54 | my_ts = (stm_word_t)stm_get_specific(mod_order_key); 55 | /* Wait its turn... */ 56 | do { 57 | current_ts = ATOMIC_LOAD(&mod_order_ts_commit); 58 | /* Check that we are not killed to keep the liveness, the transaction will 59 | * abort before to commit. Note that if the kill feature is not present, the 60 | * transaction must abort if it is not its turn to guarantee progress. */ 61 | if (stm_killed()) 62 | return; 63 | } while (current_ts != my_ts); 64 | } 65 | 66 | static void mod_order_on_commit(void *arg) 67 | { 68 | /* Release next transaction to commit */ 69 | ATOMIC_FETCH_INC_FULL(&mod_order_ts_commit); 70 | } 71 | 72 | static int mod_order_cm(struct stm_tx *tx, struct stm_tx *other_tx, int conflict) 73 | { 74 | stm_word_t my_order = (stm_word_t)stm_get_specific_tx(tx, mod_order_key); 75 | stm_word_t other_order = (stm_word_t)stm_get_specific_tx(other_tx, mod_order_key); 76 | 77 | if (my_order < other_order) 78 | return KILL_OTHER; 79 | 80 | return KILL_SELF; 81 | } 82 | 83 | /* 84 | * Initialize module. 85 | */ 86 | void mod_order_init(void) 87 | { 88 | if (mod_order_initialized) 89 | return; 90 | #if CM == CM_MODULAR 91 | if (!stm_register(NULL, NULL, mod_order_on_start, mod_order_on_precommit, mod_order_on_commit, NULL, NULL)) { 92 | fprintf(stderr, "Could not set callbacks for module 'mod_order'. Exiting.\n"); 93 | goto err; 94 | } 95 | if (stm_set_parameter("cm_function", mod_order_cm) == 0) { 96 | fprintf(stderr, "Could not set contention manager for module 'mod_order'. Exiting.\n"); 97 | goto err; 98 | } 99 | mod_order_key = stm_create_specific(); 100 | if (mod_order_key < 0) { 101 | fprintf(stderr, "Cannot create specific key\n"); 102 | goto err; 103 | } 104 | mod_order_initialized = 1; 105 | return; 106 | err: 107 | #else /* CM != CM_MODULAR */ 108 | fprintf(stderr, "The 'mod_order' module requires CM_MODULAR.\n"); 109 | #endif /* CM != CM_MODULAR */ 110 | exit(1); 111 | } 112 | -------------------------------------------------------------------------------- /src/mod_print.c: -------------------------------------------------------------------------------- 1 | /* 2 | * File: 3 | * mod_print.c 4 | * Author(s): 5 | * Pascal Felber 6 | * Patrick Marlier 7 | * Description: 8 | * Module to test callbacks. 9 | * 10 | * Copyright (c) 2007-2014. 11 | * 12 | * This program is free software; you can redistribute it and/or 13 | * modify it under the terms of the GNU General Public License 14 | * as published by the Free Software Foundation, version 2 15 | * of the License. 16 | * 17 | * This program is distributed in the hope that it will be useful, 18 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 19 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 20 | * GNU General Public License for more details. 21 | * 22 | * This program has a dual license and can also be distributed 23 | * under the terms of the MIT license. 24 | */ 25 | 26 | #include "mod_print.h" 27 | 28 | #include "stm.h" 29 | 30 | /* 31 | * Called upon thread creation. 32 | */ 33 | static void mod_print_on_thread_init(void *arg) 34 | { 35 | printf("==> on_thread_init()\n"); 36 | fflush(NULL); 37 | } 38 | 39 | /* 40 | * Called upon thread deletion. 41 | */ 42 | static void mod_print_on_thread_exit(void *arg) 43 | { 44 | printf("==> on_thread_exit()\n"); 45 | fflush(NULL); 46 | } 47 | 48 | /* 49 | * Called upon transaction start. 50 | */ 51 | static void mod_print_on_start(void *arg) 52 | { 53 | printf("==> on_start()\n"); 54 | fflush(NULL); 55 | } 56 | 57 | /* 58 | * Called before transaction try to commit. 59 | */ 60 | static void mod_print_on_precommit(void *arg) 61 | { 62 | printf("==> on_precommit()\n"); 63 | fflush(NULL); 64 | } 65 | 66 | /* 67 | * Called upon transaction commit. 68 | */ 69 | static void mod_print_on_commit(void *arg) 70 | { 71 | printf("==> on_commit()\n"); 72 | fflush(NULL); 73 | } 74 | 75 | /* 76 | * Called upon transaction abort. 77 | */ 78 | static void mod_print_on_abort(void *arg) 79 | { 80 | printf("==> on_abort()\n"); 81 | fflush(NULL); 82 | } 83 | 84 | /* 85 | * Initialize module. 86 | */ 87 | void mod_print_init(void) 88 | { 89 | if (!stm_register(mod_print_on_thread_init, mod_print_on_thread_exit, mod_print_on_start, mod_print_on_precommit, mod_print_on_commit, mod_print_on_abort, NULL)) { 90 | fprintf(stderr, "Cannot register callbacks\n"); 91 | exit(1); 92 | } 93 | } 94 | -------------------------------------------------------------------------------- /src/mod_stats.c: -------------------------------------------------------------------------------- 1 | /* 2 | * File: 3 | * mod_stats.c 4 | * Author(s): 5 | * Pascal Felber 6 | * Patrick Marlier 7 | * Description: 8 | * Module for gathering global statistics about transactions. 9 | * 10 | * Copyright (c) 2007-2014. 11 | * 12 | * This program is free software; you can redistribute it and/or 13 | * modify it under the terms of the GNU General Public License 14 | * as published by the Free Software Foundation, version 2 15 | * of the License. 16 | * 17 | * This program is distributed in the hope that it will be useful, 18 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 19 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 20 | * GNU General Public License for more details. 21 | * 22 | * This program has a dual license and can also be distributed 23 | * under the terms of the MIT license. 24 | */ 25 | 26 | #include 27 | #include 28 | #include 29 | #include 30 | 31 | #include "mod_stats.h" 32 | 33 | #include "atomic.h" 34 | #include "stm.h" 35 | #include "utils.h" 36 | 37 | /* ################################################################### * 38 | * TYPES 39 | * ################################################################### */ 40 | 41 | typedef struct mod_stats_data { /* Transaction statistics */ 42 | unsigned long commits; /* Total number of commits (cumulative) */ 43 | unsigned long retries; /* Number of consecutive aborts of current transaction (retries) */ 44 | unsigned long retries_min; /* Minimum number of consecutive aborts */ 45 | unsigned long retries_max; /* Maximum number of consecutive aborts */ 46 | unsigned long retries_acc; /* Total number of aborts (cumulative) */ 47 | unsigned long retries_cnt; /* Number of samples for cumulative aborts */ 48 | } mod_stats_data_t; 49 | 50 | static int mod_stats_key; 51 | static int mod_stats_initialized = 0; 52 | 53 | static mod_stats_data_t mod_stats_global = { 0, 0, ULONG_MAX, 0, 0, 0 }; 54 | 55 | /* ################################################################### * 56 | * FUNCTIONS 57 | * ################################################################### */ 58 | 59 | /* 60 | * Return aggregate statistics about transactions. 61 | */ 62 | int stm_get_global_stats(const char *name, void *val) 63 | { 64 | if (!mod_stats_initialized) { 65 | fprintf(stderr, "Module mod_stats not initialized\n"); 66 | exit(1); 67 | } 68 | 69 | if (strcmp("global_nb_commits", name) == 0) { 70 | *(unsigned long *)val = mod_stats_global.commits; 71 | return 1; 72 | } 73 | if (strcmp("global_nb_aborts", name) == 0) { 74 | *(unsigned long *)val = mod_stats_global.retries_acc; 75 | return 1; 76 | } 77 | if (strcmp("global_max_retries", name) == 0) { 78 | *(unsigned long *)val = mod_stats_global.retries_max; 79 | return 1; 80 | } 81 | 82 | return 0; 83 | } 84 | 85 | /* 86 | * Return statistics about current thread. 87 | */ 88 | int stm_get_local_stats(const char *name, void *val) 89 | { 90 | mod_stats_data_t *stats; 91 | 92 | if (!mod_stats_initialized) { 93 | fprintf(stderr, "Module mod_stats not initialized\n"); 94 | exit(1); 95 | } 96 | 97 | stats = (mod_stats_data_t *)stm_get_specific(mod_stats_key); 98 | assert(stats != NULL); 99 | 100 | if (strcmp("nb_commits", name) == 0) { 101 | *(unsigned long *)val = stats->commits; 102 | return 1; 103 | } 104 | if (strcmp("nb_aborts", name) == 0) { 105 | *(unsigned long *)val = stats->retries_acc; 106 | return 1; 107 | } 108 | if (strcmp("nb_retries_avg", name) == 0) { 109 | *(double *)val = (double)stats->retries_acc / stats->retries_cnt; 110 | return 1; 111 | } 112 | if (strcmp("nb_retries_min", name) == 0) { 113 | *(unsigned long *)val = stats->retries_min; 114 | return 1; 115 | } 116 | if (strcmp("nb_retries_max", name) == 0) { 117 | *(unsigned long *)val = stats->retries_max; 118 | return 1; 119 | } 120 | 121 | return 0; 122 | } 123 | 124 | /* 125 | * Called upon thread creation. 126 | */ 127 | static void mod_stats_on_thread_init(void *arg) 128 | { 129 | mod_stats_data_t *stats; 130 | 131 | stats = (mod_stats_data_t *)xmalloc(sizeof(mod_stats_data_t)); 132 | stats->commits = 0; 133 | stats->retries = 0; 134 | stats->retries_acc = 0; 135 | stats->retries_cnt = 0; 136 | stats->retries_min = ULONG_MAX; 137 | stats->retries_max = 0; 138 | 139 | stm_set_specific(mod_stats_key, stats); 140 | } 141 | 142 | /* 143 | * Called upon thread deletion. 144 | */ 145 | static void mod_stats_on_thread_exit(void *arg) 146 | { 147 | mod_stats_data_t *stats; 148 | unsigned long max, min; 149 | 150 | stats = (mod_stats_data_t *)stm_get_specific(mod_stats_key); 151 | assert(stats != NULL); 152 | 153 | ATOMIC_FETCH_ADD_FULL(&mod_stats_global.commits, stats->commits); 154 | ATOMIC_FETCH_ADD_FULL(&mod_stats_global.retries_cnt, stats->retries_cnt); 155 | ATOMIC_FETCH_ADD_FULL(&mod_stats_global.retries_acc, stats->retries_acc); 156 | retry_max: 157 | max = ATOMIC_LOAD(&mod_stats_global.retries_max); 158 | if (stats->retries_max > max) { 159 | if (ATOMIC_CAS_FULL(&mod_stats_global.retries_max, max, stats->retries_max) == 0) 160 | goto retry_max; 161 | } 162 | retry_min: 163 | min = ATOMIC_LOAD(&mod_stats_global.retries_min); 164 | if (stats->retries_min < min) { 165 | if (ATOMIC_CAS_FULL(&mod_stats_global.retries_min, min, stats->retries_min) == 0) 166 | goto retry_min; 167 | } 168 | 169 | xfree(stats); 170 | } 171 | 172 | /* 173 | * Called upon transaction commit. 174 | */ 175 | static void mod_stats_on_commit(void *arg) 176 | { 177 | mod_stats_data_t *stats; 178 | 179 | stats = (mod_stats_data_t *)stm_get_specific(mod_stats_key); 180 | assert(stats != NULL); 181 | stats->commits++; 182 | stats->retries_acc += stats->retries; 183 | stats->retries_cnt++; 184 | if (stats->retries_min > stats->retries) 185 | stats->retries_min = stats->retries; 186 | if (stats->retries_max < stats->retries) 187 | stats->retries_max = stats->retries; 188 | stats->retries = 0; 189 | } 190 | 191 | /* 192 | * Called upon transaction abort. 193 | */ 194 | static void mod_stats_on_abort(void *arg) 195 | { 196 | mod_stats_data_t *stats; 197 | 198 | stats = (mod_stats_data_t *)stm_get_specific(mod_stats_key); 199 | assert(stats != NULL); 200 | 201 | stats->retries++; 202 | } 203 | 204 | /* 205 | * Initialize module. 206 | */ 207 | void mod_stats_init(void) 208 | { 209 | if (mod_stats_initialized) 210 | return; 211 | 212 | if (!stm_register(mod_stats_on_thread_init, mod_stats_on_thread_exit, NULL, NULL, mod_stats_on_commit, mod_stats_on_abort, NULL)) { 213 | fprintf(stderr, "Cannot register callbacks\n"); 214 | exit(1); 215 | } 216 | mod_stats_key = stm_create_specific(); 217 | if (mod_stats_key < 0) { 218 | fprintf(stderr, "Cannot create specific key\n"); 219 | exit(1); 220 | } 221 | mod_stats_initialized = 1; 222 | } 223 | -------------------------------------------------------------------------------- /src/tls.h: -------------------------------------------------------------------------------- 1 | /* 2 | * File: 3 | * tls.h 4 | * Author(s): 5 | * Pascal Felber 6 | * Patrick Marlier 7 | * Description: 8 | * STM functions. 9 | * 10 | * Copyright (c) 2007-2014. 11 | * 12 | * This program is free software; you can redistribute it and/or 13 | * modify it under the terms of the GNU General Public License 14 | * as published by the Free Software Foundation, version 2 15 | * of the License. 16 | * 17 | * This program is distributed in the hope that it will be useful, 18 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 19 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 20 | * GNU General Public License for more details. 21 | * 22 | * This program has a dual license and can also be distributed 23 | * under the terms of the MIT license. 24 | */ 25 | 26 | /* ################################################################### * 27 | * THREAD-LOCAL 28 | * ################################################################### * 29 | * Some notes about compiler thread local support 30 | * 31 | * __thread keyword supported by: 32 | * * GCC 33 | * * Intel C compiler (linux) 34 | * * Sun CC (-xthreadvar must be specified) 35 | * * IBM XL 36 | * 37 | * __declspec(thread) supported by: 38 | * * Microsoft MSVC 39 | * * Intel C compiler (windows) 40 | * * Borland C 41 | * 42 | * __declspec(__thread) supported by: 43 | * * HP compiler 44 | * 45 | * Another way to support thread locals is POSIX thread library (pthread). 46 | * Darwin (MacOS) has inline version for POSIX thread local. 47 | * 48 | * Finally, the GLIBC has some specific entries for TM in the thread task 49 | * control block (TCB). 50 | * 51 | */ 52 | 53 | #ifndef _TLS_H_ 54 | #define _TLS_H_ 55 | 56 | #if !defined(TLS_COMPILER) && !defined(TLS_POSIX) && !defined(TLS_DARWIN) && !defined(TLS_GLIBC) 57 | # error "TLS is not defined correctly (TLS_COMPILER, TLS_POSIX, TLS_DARWIN, TLS_GLIBC)" 58 | #endif /* !defined(TLS_COMPILER) && !defined(TLS_POSIX) && !defined(TLS_DARWIN) && !defined(TLS_GLIBC) */ 59 | 60 | #include "utils.h" 61 | 62 | struct stm_tx; 63 | 64 | #if defined(TLS_GLIBC) 65 | 66 | /* TODO : this is x86 specific */ 67 | # ifdef __LP64__ 68 | # define SEG_READ(OFS) "movq\t%%fs:(" #OFS "*8),%0" 69 | # define SEG_WRITE(OFS) "movq\t%0,%%fs:(" #OFS "*8)" 70 | # else 71 | # define SEG_READ(OFS) "movl\t%%gs:(" #OFS "*4),%0" 72 | # define SEG_WRITE(OFS) "movl\t%0,%%gs:(" #OFS "*4)" 73 | # endif 74 | 75 | static INLINE void 76 | tls_init(void) 77 | { 78 | } 79 | 80 | static INLINE void 81 | tls_exit(void) 82 | { 83 | } 84 | 85 | static INLINE struct stm_tx * 86 | tls_get_tx(void) 87 | { 88 | struct stm_tx *r; 89 | asm volatile (SEG_READ(10) : "=r"(r)); 90 | return r; 91 | } 92 | 93 | static INLINE long 94 | tls_get_gc(void) 95 | { 96 | long r; 97 | asm volatile (SEG_READ(11) : "=r"(r)); 98 | return r; 99 | } 100 | 101 | static INLINE void 102 | tls_set_tx(struct stm_tx *tx) 103 | { 104 | asm volatile (SEG_WRITE(10) : : "r"(tx)); 105 | } 106 | 107 | static INLINE void 108 | tls_set_gc(long gc) 109 | { 110 | asm volatile (SEG_WRITE(11) : : "r"(gc)); 111 | } 112 | 113 | 114 | #elif defined(TLS_COMPILER) 115 | extern __thread struct stm_tx * thread_tx; 116 | extern __thread long thread_gc; 117 | 118 | static INLINE void 119 | tls_init(void) 120 | { 121 | thread_tx = NULL; 122 | thread_gc = 0; 123 | } 124 | 125 | static INLINE void 126 | tls_exit(void) 127 | { 128 | thread_tx = NULL; 129 | thread_gc = 0; 130 | } 131 | 132 | static INLINE struct stm_tx * 133 | tls_get_tx(void) 134 | { 135 | return thread_tx; 136 | } 137 | 138 | static INLINE long 139 | tls_get_gc(void) 140 | { 141 | return thread_gc; 142 | } 143 | 144 | static INLINE void 145 | tls_set_tx(struct stm_tx *tx) 146 | { 147 | thread_tx = tx; 148 | } 149 | 150 | static INLINE void 151 | tls_set_gc(long gc) 152 | { 153 | thread_gc = gc; 154 | } 155 | 156 | 157 | #elif defined(TLS_POSIX) || defined(TLS_DARWIN) 158 | 159 | #include 160 | #include 161 | # if defined(TLS_DARWIN) 162 | /* Contains inline version for pthread_getspecific. */ 163 | # include 164 | # endif /* defined(TLS_DARWIN) */ 165 | 166 | extern pthread_key_t thread_tx; 167 | extern pthread_key_t thread_gc; 168 | 169 | static INLINE void 170 | tls_init(void) 171 | { 172 | if (pthread_key_create(&thread_tx, NULL) != 0 173 | || pthread_key_create(&thread_gc, NULL) != 0) { 174 | fprintf(stderr, "Error creating thread local\n"); 175 | exit(1); 176 | } 177 | } 178 | 179 | static INLINE void 180 | tls_exit(void) 181 | { 182 | pthread_key_delete(thread_tx); 183 | pthread_key_delete(thread_gc); 184 | } 185 | 186 | /* 187 | * Returns the transaction descriptor for the CURRENT thread. 188 | */ 189 | static INLINE struct stm_tx* 190 | tls_get_tx(void) 191 | { 192 | # if defined(TLS_POSIX) 193 | return (struct stm_tx *)pthread_getspecific(thread_tx); 194 | # elif defined(TLS_DARWIN) 195 | return (struct stm_tx *)_pthread_getspecific_direct(thread_tx); 196 | # endif /* defined(TLS_DARWIN) */ 197 | } 198 | 199 | static INLINE long 200 | tls_get_gc(void) 201 | { 202 | # if defined(TLS_POSIX) 203 | return (long)pthread_getspecific(thread_gc); 204 | # elif defined(TLS_DARWIN) 205 | return (long)_pthread_getspecific_direct(thread_gc); 206 | # endif /* defined(TLS_DARWIN) */ 207 | } 208 | 209 | /* 210 | * Set the transaction descriptor for the CURRENT thread. 211 | */ 212 | static INLINE void 213 | tls_set_tx(struct stm_tx *tx) 214 | { 215 | # if defined(TLS_POSIX) 216 | pthread_setspecific(thread_tx, tx); 217 | # elif defined(TLS_DARWIN) 218 | _pthread_setspecific_direct(thread_tx, tx); 219 | # endif /* defined(TLS_DARWIN) */ 220 | } 221 | 222 | static INLINE void 223 | tls_set_gc(long gc) 224 | { 225 | # if defined(TLS_POSIX) 226 | pthread_setspecific(thread_gc, (void *)gc); 227 | # elif defined(TLS_DARWIN) 228 | _pthread_setspecific_direct(thread_gc, (void *)gc); 229 | # endif /* defined(TLS_DARWIN) */ 230 | } 231 | #endif /* defined(TLS_POSIX) || defined(TLS_DARWIN) */ 232 | 233 | #endif /* _TLS_H_ */ 234 | 235 | -------------------------------------------------------------------------------- /src/utils.h: -------------------------------------------------------------------------------- 1 | /* 2 | * File: 3 | * utils.h 4 | * Author(s): 5 | * Pascal Felber 6 | * Patrick Marlier 7 | * Description: 8 | * Utilities functions. 9 | * 10 | * Copyright (c) 2007-2014. 11 | * 12 | * This program is free software; you can redistribute it and/or 13 | * modify it under the terms of the GNU General Public License 14 | * as published by the Free Software Foundation, version 2 15 | * of the License. 16 | * 17 | * This program is distributed in the hope that it will be useful, 18 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 19 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 20 | * GNU General Public License for more details. 21 | * 22 | * This program has a dual license and can also be distributed 23 | * under the terms of the MIT license. 24 | */ 25 | 26 | #ifndef _UTILS_H_ 27 | #define _UTILS_H_ 28 | 29 | #include 30 | #include 31 | 32 | #define COMPILE_TIME_ASSERT(pred) switch (0) { case 0: case pred: ; } 33 | 34 | #ifdef DEBUG2 35 | # ifndef DEBUG 36 | # define DEBUG 37 | # endif /* ! DEBUG */ 38 | #endif /* DEBUG2 */ 39 | 40 | #ifdef DEBUG 41 | /* Note: stdio is thread-safe */ 42 | # define IO_FLUSH fflush(NULL) 43 | # define PRINT_DEBUG(...) printf(__VA_ARGS__); fflush(NULL) 44 | #else /* ! DEBUG */ 45 | # define IO_FLUSH 46 | # define PRINT_DEBUG(...) 47 | #endif /* ! DEBUG */ 48 | 49 | #ifdef DEBUG2 50 | # define PRINT_DEBUG2(...) PRINT_DEBUG(__VA_ARGS__) 51 | #else /* ! DEBUG2 */ 52 | # define PRINT_DEBUG2(...) 53 | #endif /* ! DEBUG2 */ 54 | 55 | #define XSTR(s) STR(s) 56 | #define STR(s) #s 57 | 58 | #ifndef CACHELINE_SIZE 59 | /* It ensures efficient usage of cache and avoids false sharing. 60 | * It could be defined in an architecture specific file. */ 61 | # define CACHELINE_SIZE 64 62 | #endif 63 | 64 | #if defined(__GNUC__) || defined(__INTEL_COMPILER) 65 | # define likely(x) __builtin_expect(!!(x), 1) 66 | # define unlikely(x) __builtin_expect(!!(x), 0) 67 | # define INLINE inline __attribute__((always_inline)) 68 | # define NOINLINE __attribute__((noinline)) 69 | # if defined(__INTEL_COMPILER) 70 | # define ALIGNED /* Unknown */ 71 | # else /* ! __INTEL_COMPILER */ 72 | # define ALIGNED __attribute__((aligned(CACHELINE_SIZE))) 73 | # endif /* ! __INTEL_COMPILER */ 74 | #else /* ! (defined(__GNUC__) || defined(__INTEL_COMPILER)) */ 75 | # define likely(x) (x) 76 | # define unlikely(x) (x) 77 | # define INLINE inline 78 | # define NOINLINE /* None in the C standard */ 79 | # define ALIGNED /* None in the C standard */ 80 | #endif /* ! (defined(__GNUC__) || defined(__INTEL_COMPILER)) */ 81 | 82 | /* 83 | * malloc/free wrappers. 84 | */ 85 | static INLINE void* 86 | xmalloc(size_t size) 87 | { 88 | void *memptr = malloc(size); 89 | if (unlikely(memptr == NULL)) { 90 | perror("malloc"); 91 | exit(1); 92 | } 93 | return memptr; 94 | } 95 | 96 | static INLINE void* 97 | xcalloc(size_t count, size_t size) 98 | { 99 | void *memptr = calloc(count, size); 100 | if (unlikely(memptr == NULL)) { 101 | perror("calloc"); 102 | exit(1); 103 | } 104 | return memptr; 105 | } 106 | 107 | static INLINE void* 108 | xrealloc(void *addr, size_t size) 109 | { 110 | addr = realloc(addr, size); 111 | if (unlikely(addr == NULL)) { 112 | perror("realloc"); 113 | exit(1); 114 | } 115 | return addr; 116 | } 117 | 118 | static INLINE void 119 | xfree(void *mem) 120 | { 121 | free(mem); 122 | } 123 | 124 | static INLINE void* 125 | xmalloc_aligned(size_t size) 126 | { 127 | void *memptr; 128 | /* TODO is posix_memalign is not available, provide malloc fallback. */ 129 | /* Make sure that the allocation is aligned with cacheline size. */ 130 | #if defined(__CYGWIN__) || defined (__sun__) 131 | memptr = memalign(CACHELINE_SIZE, size); 132 | #elif defined(__APPLE__) 133 | memptr = valloc(size); 134 | #else 135 | if (unlikely(posix_memalign(&memptr, CACHELINE_SIZE, size))) 136 | memptr = NULL; 137 | #endif 138 | if (unlikely(memptr == NULL)) { 139 | fprintf(stderr, "Error allocating aligned memory\n"); 140 | exit(1); 141 | } 142 | return memptr; 143 | } 144 | 145 | #endif /* !_UTILS_H_ */ 146 | 147 | -------------------------------------------------------------------------------- /test/Makefile: -------------------------------------------------------------------------------- 1 | .PHONY: all 2 | 3 | TESTS = bank intset regression 4 | 5 | .PHONY: all $(TESTS) 6 | 7 | all: $(TESTS) 8 | 9 | check: all 10 | @echo Testing load/store \(regression/types\) 11 | @./regression/types 1>/dev/null 2>&1 12 | @echo Testing irrevocability \(regression/irrevocability\) 13 | @./regression/irrevocability 1>/dev/null 2>&1 14 | @echo Testing Linked List \(intset/intset-ll\) 15 | @./intset/intset-ll -d 2000 1>/dev/null 2>&1 16 | @echo Testing Linked List with concurrency \(intset/intset-ll -n 4\) 17 | @./intset/intset-ll -d 2000 -n 4 1>/dev/null 2>&1 18 | @echo Testing Red Black Tree \(intset/intset-rb\) 19 | @./intset/intset-rb -d 2000 1>/dev/null 2>&1 20 | @echo Testing Red Black Tree with concurrency \(intset/intset-rb -n 4\) 21 | @./intset/intset-rb -d 2000 -n 4 1>/dev/null 2>&1 22 | @echo Testing Skip List \(intset/intset-sl\) 23 | @./intset/intset-sl -d 2000 1>/dev/null 2>&1 24 | @echo Testing Skip List with concurrency \(intset/intset-sl -n 4\) 25 | @./intset/intset-sl -d 2000 -n 4 1>/dev/null 2>&1 26 | @echo Testing Hash Set \(intset/intset-hs\) 27 | @./intset/intset-hs -d 2000 1>/dev/null 2>&1 28 | @echo Testing Hash Set with concurrency \(intset/intset-hs -n 4\) 29 | @./intset/intset-hs -d 2000 -n 4 1>/dev/null 2>&1 30 | @echo All tests passed 31 | 32 | $(TESTS): 33 | $(MAKE) -C $@ $(TARGET) 34 | -------------------------------------------------------------------------------- /test/bank/.gitignore: -------------------------------------------------------------------------------- 1 | bank 2 | -------------------------------------------------------------------------------- /test/bank/Makefile: -------------------------------------------------------------------------------- 1 | ROOT = ../.. 2 | 3 | include $(ROOT)/Makefile.common 4 | 5 | BINS = bank 6 | 7 | .PHONY: all clean 8 | 9 | all: $(BINS) 10 | 11 | %.o: %.c 12 | $(CC) $(CPPFLAGS) $(CFLAGS) $(DEFINES) -c -o $@ $< 13 | 14 | $(BINS): %: %.o $(TMLIB) 15 | $(CC) -o $@ $< $(LDFLAGS) 16 | 17 | clean: 18 | rm -f $(BINS) *.o 19 | -------------------------------------------------------------------------------- /test/intset/.gitignore: -------------------------------------------------------------------------------- 1 | intset-ll 2 | intset-hs 3 | intset-sl 4 | intset-rb 5 | -------------------------------------------------------------------------------- /test/intset/Makefile: -------------------------------------------------------------------------------- 1 | ROOT ?= ../.. 2 | 3 | include $(ROOT)/Makefile.common 4 | 5 | BINS = intset-hs intset-ll intset-rb intset-sl 6 | 7 | UNAME := $(shell uname) 8 | ifeq ($(UNAME), SunOS) 9 | # Solaris requires rt lib for nanosleep 10 | LDFLAGS += -lrt 11 | endif 12 | 13 | .PHONY: all clean 14 | 15 | all: $(BINS) 16 | 17 | intset-hs.o: intset.c 18 | $(CC) $(CPPFLAGS) $(CFLAGS) $(DEFINES) -DUSE_HASHSET -c -o $@ $< 19 | 20 | intset-ll.o: intset.c 21 | $(CC) $(CPPFLAGS) $(CFLAGS) $(DEFINES) -DUSE_LINKEDLIST -c -o $@ $< 22 | 23 | intset-rb.o: intset.c rbtree.c rbtree.h 24 | $(CC) $(CPPFLAGS) $(CFLAGS) $(DEFINES) -DUSE_RBTREE -c -o $@ $< 25 | 26 | intset-sl.o: intset.c 27 | $(CC) $(CPPFLAGS) $(CFLAGS) $(DEFINES) -DUSE_SKIPLIST -c -o $@ $< 28 | 29 | # FIXME in case of ABI $(TMLIB) must be replaced to abi/... 30 | $(BINS): %: %.o $(TMLIB) 31 | $(LD) -o $@ $< $(LDFLAGS) 32 | 33 | clean: 34 | rm -f $(BINS) *.o 35 | -------------------------------------------------------------------------------- /test/intset/README.rbtree: -------------------------------------------------------------------------------- 1 | The red-black tree implementation (rbtree.c, rbtree.h, types.h) comes 2 | from the STAMP 0.9.10 distribution available from 3 | . Files have not been modified in any way 4 | besides enabling memory deallocation upon node release. 5 | -------------------------------------------------------------------------------- /test/intset/rbtree.h: -------------------------------------------------------------------------------- 1 | /* ============================================================================= 2 | * 3 | * rbtree.h 4 | * -- Red-black balanced binary search tree 5 | * 6 | * ============================================================================= 7 | * 8 | * Copyright (C) Sun Microsystems Inc., 2006. All Rights Reserved. 9 | * Authors: Dave Dice, Nir Shavit, Ori Shalev. 10 | * 11 | * STM: Transactional Locking for Disjoint Access Parallelism 12 | * 13 | * Transactional Locking II, 14 | * Dave Dice, Ori Shalev, Nir Shavit 15 | * DISC 2006, Sept 2006, Stockholm, Sweden. 16 | * 17 | * ============================================================================= 18 | * 19 | * Modified by Chi Cao Minh 20 | * 21 | * ============================================================================= 22 | * 23 | * For the license of bayes/sort.h and bayes/sort.c, please see the header 24 | * of the files. 25 | * 26 | * ------------------------------------------------------------------------ 27 | * 28 | * For the license of kmeans, please see kmeans/LICENSE.kmeans 29 | * 30 | * ------------------------------------------------------------------------ 31 | * 32 | * For the license of ssca2, please see ssca2/COPYRIGHT 33 | * 34 | * ------------------------------------------------------------------------ 35 | * 36 | * For the license of lib/mt19937ar.c and lib/mt19937ar.h, please see the 37 | * header of the files. 38 | * 39 | * ------------------------------------------------------------------------ 40 | * 41 | * For the license of lib/rbtree.h and lib/rbtree.c, please see 42 | * lib/LEGALNOTICE.rbtree and lib/LICENSE.rbtree 43 | * 44 | * ------------------------------------------------------------------------ 45 | * 46 | * Unless otherwise noted, the following license applies to STAMP files: 47 | * 48 | * Copyright (c) 2007, Stanford University 49 | * All rights reserved. 50 | * 51 | * Redistribution and use in source and binary forms, with or without 52 | * modification, are permitted provided that the following conditions are 53 | * met: 54 | * 55 | * * Redistributions of source code must retain the above copyright 56 | * notice, this list of conditions and the following disclaimer. 57 | * 58 | * * Redistributions in binary form must reproduce the above copyright 59 | * notice, this list of conditions and the following disclaimer in 60 | * the documentation and/or other materials provided with the 61 | * distribution. 62 | * 63 | * * Neither the name of Stanford University nor the names of its 64 | * contributors may be used to endorse or promote products derived 65 | * from this software without specific prior written permission. 66 | * 67 | * THIS SOFTWARE IS PROVIDED BY STANFORD UNIVERSITY ``AS IS'' AND ANY 68 | * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 69 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 70 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL STANFORD UNIVERSITY BE LIABLE 71 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 72 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 73 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 74 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 75 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 76 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 77 | * THE POSSIBILITY OF SUCH DAMAGE. 78 | * 79 | * ============================================================================= 80 | */ 81 | 82 | 83 | #ifndef RBTREE_H 84 | #define RBTREE_H 1 85 | 86 | 87 | #include "tm.h" 88 | #include "types.h" 89 | 90 | 91 | #ifdef __cplusplus 92 | extern "C" { 93 | #endif 94 | 95 | 96 | typedef struct rbtree rbtree_t; 97 | 98 | 99 | /* ============================================================================= 100 | * rbtree_verify 101 | * ============================================================================= 102 | */ 103 | long 104 | rbtree_verify (rbtree_t* s, long verbose); 105 | 106 | 107 | /* ============================================================================= 108 | * rbtree_alloc 109 | * ============================================================================= 110 | */ 111 | rbtree_t* 112 | rbtree_alloc (long (*compare)(const void*, const void*)); 113 | 114 | 115 | /* ============================================================================= 116 | * TMrbtree_alloc 117 | * ============================================================================= 118 | */ 119 | rbtree_t* 120 | TMrbtree_alloc (TM_ARGDECL long (*compare)(const void*, const void*)); 121 | 122 | 123 | /* ============================================================================= 124 | * rbtree_free 125 | * ============================================================================= 126 | */ 127 | void 128 | rbtree_free (rbtree_t* r); 129 | 130 | 131 | /* ============================================================================= 132 | * TMrbtree_free 133 | * ============================================================================= 134 | */ 135 | void 136 | TMrbtree_free (TM_ARGDECL rbtree_t* r); 137 | 138 | 139 | /* ============================================================================= 140 | * rbtree_insert 141 | * -- Returns TRUE on success 142 | * ============================================================================= 143 | */ 144 | bool_t 145 | rbtree_insert (rbtree_t* r, void* key, void* val); 146 | 147 | 148 | /* ============================================================================= 149 | * TMrbtree_insert 150 | * -- Returns TRUE on success 151 | * ============================================================================= 152 | */ 153 | TM_CALLABLE 154 | bool_t 155 | TMrbtree_insert (TM_ARGDECL rbtree_t* r, void* key, void* val); 156 | 157 | 158 | /* ============================================================================= 159 | * rbtree_delete 160 | * ============================================================================= 161 | */ 162 | bool_t 163 | rbtree_delete (rbtree_t* r, void* key); 164 | 165 | 166 | /* ============================================================================= 167 | * TMrbtree_delete 168 | * ============================================================================= 169 | */ 170 | TM_CALLABLE 171 | bool_t 172 | TMrbtree_delete (TM_ARGDECL rbtree_t* r, void* key); 173 | 174 | 175 | /* ============================================================================= 176 | * rbtree_update 177 | * -- Return FALSE if had to insert node first 178 | * ============================================================================= 179 | */ 180 | bool_t 181 | rbtree_update (rbtree_t* r, void* key, void* val); 182 | 183 | 184 | /* ============================================================================= 185 | * TMrbtree_update 186 | * -- Return FALSE if had to insert node first 187 | * ============================================================================= 188 | */ 189 | TM_CALLABLE 190 | bool_t 191 | TMrbtree_update (TM_ARGDECL rbtree_t* r, void* key, void* val); 192 | 193 | 194 | /* ============================================================================= 195 | * rbtree_get 196 | * ============================================================================= 197 | */ 198 | void* 199 | rbtree_get (rbtree_t* r, void* key); 200 | 201 | 202 | /* ============================================================================= 203 | * TMrbtree_get 204 | * ============================================================================= 205 | */ 206 | TM_CALLABLE 207 | void* 208 | TMrbtree_get (TM_ARGDECL rbtree_t* r, void* key); 209 | 210 | 211 | /* ============================================================================= 212 | * rbtree_contains 213 | * ============================================================================= 214 | */ 215 | bool_t 216 | rbtree_contains (rbtree_t* r, void* key); 217 | 218 | 219 | /* ============================================================================= 220 | * TMrbtree_contains 221 | * ============================================================================= 222 | */ 223 | TM_CALLABLE 224 | bool_t 225 | TMrbtree_contains (TM_ARGDECL rbtree_t* r, void* key); 226 | 227 | 228 | #define TMRBTREE_ALLOC() TMrbtree_alloc(TM_ARG_ALONE) 229 | #define TMRBTREE_FREE(r) TMrbtree_free(TM_ARG r) 230 | #define TMRBTREE_INSERT(r, k, v) TMrbtree_insert(TM_ARG r, (void*)(k), (void*)(v)) 231 | #define TMRBTREE_DELETE(r, k) TMrbtree_delete(TM_ARG r, (void*)(k)) 232 | #define TMRBTREE_UPDATE(r, k, v) TMrbtree_update(TM_ARG r, (void*)(k), (void*)(v)) 233 | #define TMRBTREE_GET(r, k) TMrbtree_get(TM_ARG r, (void*)(k)) 234 | #define TMRBTREE_CONTAINS(r, k) TMrbtree_contains(TM_ARG r, (void*)(k)) 235 | 236 | 237 | #ifdef __cplusplus 238 | } 239 | #endif 240 | 241 | 242 | 243 | #endif /* RBTREE_H */ 244 | 245 | 246 | 247 | /* ============================================================================= 248 | * 249 | * End of rbtree.h 250 | * 251 | * ============================================================================= 252 | */ 253 | -------------------------------------------------------------------------------- /test/intset/tm.h: -------------------------------------------------------------------------------- 1 | /* 2 | * File: 3 | * tm.h 4 | * Author(s): 5 | * Pascal Felber 6 | * Patrick Marlier 7 | * Description: 8 | * Empty file (to avoid source modifications red-black tree). 9 | * 10 | * Copyright (c) 2007-2014. 11 | * 12 | * This program is free software; you can redistribute it and/or 13 | * modify it under the terms of the GNU General Public License 14 | * as published by the Free Software Foundation, version 2 15 | * of the License. 16 | * 17 | * This program is distributed in the hope that it will be useful, 18 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 19 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 20 | * GNU General Public License for more details. 21 | * 22 | * This program has a dual license and can also be distributed 23 | * under the terms of the MIT license. 24 | */ 25 | -------------------------------------------------------------------------------- /test/intset/types.h: -------------------------------------------------------------------------------- 1 | /* ============================================================================= 2 | * 3 | * types.h 4 | * -- definitions of some types 5 | * 6 | * ============================================================================= 7 | * 8 | * Copyright (C) Stanford University, 2006. All Rights Reserved. 9 | * Author: Chi Cao Minh 10 | * 11 | * ============================================================================= 12 | * 13 | * For the license of bayes/sort.h and bayes/sort.c, please see the header 14 | * of the files. 15 | * 16 | * ------------------------------------------------------------------------ 17 | * 18 | * For the license of kmeans, please see kmeans/LICENSE.kmeans 19 | * 20 | * ------------------------------------------------------------------------ 21 | * 22 | * For the license of ssca2, please see ssca2/COPYRIGHT 23 | * 24 | * ------------------------------------------------------------------------ 25 | * 26 | * For the license of lib/mt19937ar.c and lib/mt19937ar.h, please see the 27 | * header of the files. 28 | * 29 | * ------------------------------------------------------------------------ 30 | * 31 | * For the license of lib/rbtree.h and lib/rbtree.c, please see 32 | * lib/LEGALNOTICE.rbtree and lib/LICENSE.rbtree 33 | * 34 | * ------------------------------------------------------------------------ 35 | * 36 | * Unless otherwise noted, the following license applies to STAMP files: 37 | * 38 | * Copyright (c) 2007, Stanford University 39 | * All rights reserved. 40 | * 41 | * Redistribution and use in source and binary forms, with or without 42 | * modification, are permitted provided that the following conditions are 43 | * met: 44 | * 45 | * * Redistributions of source code must retain the above copyright 46 | * notice, this list of conditions and the following disclaimer. 47 | * 48 | * * Redistributions in binary form must reproduce the above copyright 49 | * notice, this list of conditions and the following disclaimer in 50 | * the documentation and/or other materials provided with the 51 | * distribution. 52 | * 53 | * * Neither the name of Stanford University nor the names of its 54 | * contributors may be used to endorse or promote products derived 55 | * from this software without specific prior written permission. 56 | * 57 | * THIS SOFTWARE IS PROVIDED BY STANFORD UNIVERSITY ``AS IS'' AND ANY 58 | * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 59 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 60 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL STANFORD UNIVERSITY BE LIABLE 61 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 62 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 63 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 64 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 65 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 66 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 67 | * THE POSSIBILITY OF SUCH DAMAGE. 68 | * 69 | * ============================================================================= 70 | */ 71 | 72 | 73 | #ifndef TYPES_H 74 | #define TYPES_H 1 75 | 76 | 77 | #ifdef __cplusplus 78 | extern "C" { 79 | #endif 80 | 81 | 82 | #ifdef SIMULATOR 83 | # undef TRUE 84 | # undef FALSE 85 | # undef bool 86 | #endif 87 | 88 | 89 | typedef unsigned long ulong_t; 90 | 91 | enum { 92 | FALSE = 0, 93 | TRUE = 1 94 | }; 95 | 96 | typedef long bool_t; 97 | 98 | 99 | #ifdef __cplusplus 100 | } 101 | #endif 102 | 103 | 104 | #endif /* TYPES_H */ 105 | 106 | 107 | /* ============================================================================= 108 | * 109 | * End of types.h 110 | * 111 | * ============================================================================= 112 | */ 113 | -------------------------------------------------------------------------------- /test/regression/.gitignore: -------------------------------------------------------------------------------- 1 | irrevocability 2 | types 3 | -------------------------------------------------------------------------------- /test/regression/Makefile: -------------------------------------------------------------------------------- 1 | ROOT = ../.. 2 | 3 | include $(ROOT)/Makefile.common 4 | 5 | BINS = types irrevocability 6 | 7 | .PHONY: all clean 8 | 9 | all: $(BINS) 10 | 11 | %.o: %.c 12 | $(CC) $(CPPFLAGS) $(CFLAGS) $(DEFINES) -c -o $@ $< 13 | 14 | $(BINS): %: %.o $(TMLIB) 15 | $(CC) -o $@ $< $(LDFLAGS) 16 | 17 | clean: 18 | rm -f $(BINS) *.o 19 | --------------------------------------------------------------------------------