diff --git a/linux-2.6.37.6-antonio/arch/microblaze/boot/dts/system.dts b/linux-2.6.37.6-antonio/arch/microblaze/boot/dts/system.dts
deleted file mode 100755
index 3f85df2..0000000
--- a/linux-2.6.37.6-antonio/arch/microblaze/boot/dts/system.dts
+++ /dev/null
@@ -1,367 +0,0 @@
-/*
- * Device Tree Generator version: 1.1
- *
- * (C) Copyright 2007-2008 Xilinx, Inc.
- * (C) Copyright 2007-2009 Michal Simek
- *
- * Michal SIMEK <monstr@monstr.eu>
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation; either version 2 of
- * the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
- * MA 02111-1307 USA
- *
- * CAUTION: This file is automatically generated by libgen.
- * Version: Xilinx EDK 10.1.03 EDK_K_SP3.6
- *
- * XPS project directory: Xilinx-ML505-ll_temac-sgdma-MMU-FDT-edk101
- */
-
-/dts-v1/;
-/ {
-	#address-cells = <1>;
-	#size-cells = <1>;
-	compatible = "xlnx,microblaze";
-	hard-reset-gpios = <&LEDs_8Bit 2 1>;
-	model = "testing";
-	DDR2_SDRAM: memory@90000000 {
-		device_type = "memory";
-		reg = < 0x90000000 0x10000000 >;
-	} ;
-	aliases {
-		ethernet0 = &Hard_Ethernet_MAC;
-		serial0 = &RS232_Uart_1;
-	} ;
-	chosen {
-		bootargs = "console=ttyUL0,115200 highres=on";
-		linux,stdout-path = "/plb@0/serial@84000000";
-	} ;
-	cpus {
-		#address-cells = <1>;
-		#cpus = <0x1>;
-		#size-cells = <0>;
-		microblaze_0: cpu@0 {
-			clock-frequency = <125000000>;
-			compatible = "xlnx,microblaze-7.10.d";
-			d-cache-baseaddr = <0x90000000>;
-			d-cache-highaddr = <0x9fffffff>;
-			d-cache-line-size = <0x10>;
-			d-cache-size = <0x2000>;
-			device_type = "cpu";
-			i-cache-baseaddr = <0x90000000>;
-			i-cache-highaddr = <0x9fffffff>;
-			i-cache-line-size = <0x10>;
-			i-cache-size = <0x2000>;
-			model = "microblaze,7.10.d";
-			reg = <0>;
-			timebase-frequency = <125000000>;
-			xlnx,addr-tag-bits = <0xf>;
-			xlnx,allow-dcache-wr = <0x1>;
-			xlnx,allow-icache-wr = <0x1>;
-			xlnx,area-optimized = <0x0>;
-			xlnx,cache-byte-size = <0x2000>;
-			xlnx,d-lmb = <0x1>;
-			xlnx,d-opb = <0x0>;
-			xlnx,d-plb = <0x1>;
-			xlnx,data-size = <0x20>;
-			xlnx,dcache-addr-tag = <0xf>;
-			xlnx,dcache-always-used = <0x1>;
-			xlnx,dcache-byte-size = <0x2000>;
-			xlnx,dcache-line-len = <0x4>;
-			xlnx,dcache-use-fsl = <0x1>;
-			xlnx,debug-enabled = <0x1>;
-			xlnx,div-zero-exception = <0x1>;
-			xlnx,dopb-bus-exception = <0x0>;
-			xlnx,dynamic-bus-sizing = <0x1>;
-			xlnx,edge-is-positive = <0x1>;
-			xlnx,family = "virtex5";
-			xlnx,endianness = <0x1>;
-			xlnx,fpu-exception = <0x1>;
-			xlnx,fsl-data-size = <0x20>;
-			xlnx,fsl-exception = <0x0>;
-			xlnx,fsl-links = <0x0>;
-			xlnx,i-lmb = <0x1>;
-			xlnx,i-opb = <0x0>;
-			xlnx,i-plb = <0x1>;
-			xlnx,icache-always-used = <0x1>;
-			xlnx,icache-line-len = <0x4>;
-			xlnx,icache-use-fsl = <0x1>;
-			xlnx,ill-opcode-exception = <0x1>;
-			xlnx,instance = "microblaze_0";
-			xlnx,interconnect = <0x1>;
-			xlnx,interrupt-is-edge = <0x0>;
-			xlnx,iopb-bus-exception = <0x0>;
-			xlnx,mmu-dtlb-size = <0x4>;
-			xlnx,mmu-itlb-size = <0x2>;
-			xlnx,mmu-tlb-access = <0x3>;
-			xlnx,mmu-zones = <0x10>;
-			xlnx,number-of-pc-brk = <0x1>;
-			xlnx,number-of-rd-addr-brk = <0x0>;
-			xlnx,number-of-wr-addr-brk = <0x0>;
-			xlnx,opcode-0x0-illegal = <0x1>;
-			xlnx,pvr = <0x2>;
-			xlnx,pvr-user1 = <0x0>;
-			xlnx,pvr-user2 = <0x0>;
-			xlnx,reset-msr = <0x0>;
-			xlnx,sco = <0x0>;
-			xlnx,unaligned-exceptions = <0x1>;
-			xlnx,use-barrel = <0x1>;
-			xlnx,use-dcache = <0x1>;
-			xlnx,use-div = <0x1>;
-			xlnx,use-ext-brk = <0x1>;
-			xlnx,use-ext-nm-brk = <0x1>;
-			xlnx,use-extended-fsl-instr = <0x0>;
-			xlnx,use-fpu = <0x2>;
-			xlnx,use-hw-mul = <0x2>;
-			xlnx,use-icache = <0x1>;
-			xlnx,use-interrupt = <0x1>;
-			xlnx,use-mmu = <0x3>;
-			xlnx,use-msr-instr = <0x1>;
-			xlnx,use-pcmp-instr = <0x1>;
-		} ;
-	} ;
-	mb_plb: plb@0 {
-		#address-cells = <1>;
-		#size-cells = <1>;
-		compatible = "xlnx,plb-v46-1.03.a", "xlnx,plb-v46-1.00.a", "simple-bus";
-		ranges ;
-		FLASH: flash@a0000000 {
-			bank-width = <2>;
-			compatible = "xlnx,xps-mch-emc-2.00.a", "cfi-flash";
-			reg = < 0xa0000000 0x2000000 >;
-			xlnx,family = "virtex5";
-			xlnx,include-datawidth-matching-0 = <0x1>;
-			xlnx,include-datawidth-matching-1 = <0x0>;
-			xlnx,include-datawidth-matching-2 = <0x0>;
-			xlnx,include-datawidth-matching-3 = <0x0>;
-			xlnx,include-negedge-ioregs = <0x0>;
-			xlnx,include-plb-ipif = <0x1>;
-			xlnx,include-wrbuf = <0x1>;
-			xlnx,max-mem-width = <0x10>;
-			xlnx,mch-native-dwidth = <0x20>;
-			xlnx,mch-plb-clk-period-ps = <0x1f40>;
-			xlnx,mch-splb-awidth = <0x20>;
-			xlnx,mch0-accessbuf-depth = <0x10>;
-			xlnx,mch0-protocol = <0x0>;
-			xlnx,mch0-rddatabuf-depth = <0x10>;
-			xlnx,mch1-accessbuf-depth = <0x10>;
-			xlnx,mch1-protocol = <0x0>;
-			xlnx,mch1-rddatabuf-depth = <0x10>;
-			xlnx,mch2-accessbuf-depth = <0x10>;
-			xlnx,mch2-protocol = <0x0>;
-			xlnx,mch2-rddatabuf-depth = <0x10>;
-			xlnx,mch3-accessbuf-depth = <0x10>;
-			xlnx,mch3-protocol = <0x0>;
-			xlnx,mch3-rddatabuf-depth = <0x10>;
-			xlnx,mem0-width = <0x10>;
-			xlnx,mem1-width = <0x20>;
-			xlnx,mem2-width = <0x20>;
-			xlnx,mem3-width = <0x20>;
-			xlnx,num-banks-mem = <0x1>;
-			xlnx,num-channels = <0x0>;
-			xlnx,priority-mode = <0x0>;
-			xlnx,synch-mem-0 = <0x0>;
-			xlnx,synch-mem-1 = <0x0>;
-			xlnx,synch-mem-2 = <0x0>;
-			xlnx,synch-mem-3 = <0x0>;
-			xlnx,synch-pipedelay-0 = <0x2>;
-			xlnx,synch-pipedelay-1 = <0x2>;
-			xlnx,synch-pipedelay-2 = <0x2>;
-			xlnx,synch-pipedelay-3 = <0x2>;
-			xlnx,tavdv-ps-mem-0 = <0x1adb0>;
-			xlnx,tavdv-ps-mem-1 = <0x3a98>;
-			xlnx,tavdv-ps-mem-2 = <0x3a98>;
-			xlnx,tavdv-ps-mem-3 = <0x3a98>;
-			xlnx,tcedv-ps-mem-0 = <0x1adb0>;
-			xlnx,tcedv-ps-mem-1 = <0x3a98>;
-			xlnx,tcedv-ps-mem-2 = <0x3a98>;
-			xlnx,tcedv-ps-mem-3 = <0x3a98>;
-			xlnx,thzce-ps-mem-0 = <0x88b8>;
-			xlnx,thzce-ps-mem-1 = <0x1b58>;
-			xlnx,thzce-ps-mem-2 = <0x1b58>;
-			xlnx,thzce-ps-mem-3 = <0x1b58>;
-			xlnx,thzoe-ps-mem-0 = <0x1b58>;
-			xlnx,thzoe-ps-mem-1 = <0x1b58>;
-			xlnx,thzoe-ps-mem-2 = <0x1b58>;
-			xlnx,thzoe-ps-mem-3 = <0x1b58>;
-			xlnx,tlzwe-ps-mem-0 = <0x88b8>;
-			xlnx,tlzwe-ps-mem-1 = <0x0>;
-			xlnx,tlzwe-ps-mem-2 = <0x0>;
-			xlnx,tlzwe-ps-mem-3 = <0x0>;
-			xlnx,twc-ps-mem-0 = <0x2af8>;
-			xlnx,twc-ps-mem-1 = <0x3a98>;
-			xlnx,twc-ps-mem-2 = <0x3a98>;
-			xlnx,twc-ps-mem-3 = <0x3a98>;
-			xlnx,twp-ps-mem-0 = <0x11170>;
-			xlnx,twp-ps-mem-1 = <0x2ee0>;
-			xlnx,twp-ps-mem-2 = <0x2ee0>;
-			xlnx,twp-ps-mem-3 = <0x2ee0>;
-			xlnx,xcl0-linesize = <0x4>;
-			xlnx,xcl0-writexfer = <0x1>;
-			xlnx,xcl1-linesize = <0x4>;
-			xlnx,xcl1-writexfer = <0x1>;
-			xlnx,xcl2-linesize = <0x4>;
-			xlnx,xcl2-writexfer = <0x1>;
-			xlnx,xcl3-linesize = <0x4>;
-			xlnx,xcl3-writexfer = <0x1>;
-		} ;
-		Hard_Ethernet_MAC: xps-ll-temac@81c00000 {
-			#address-cells = <1>;
-			#size-cells = <1>;
-			compatible = "xlnx,compound";
-			ranges ;
-			ethernet@81c00000 {
-				compatible = "xlnx,xps-ll-temac-1.01.b", "xlnx,xps-ll-temac-1.00.a";
-				device_type = "network";
-				interrupt-parent = <&xps_intc_0>;
-				interrupts = < 5 2 >;
-				llink-connected = <&PIM3>;
-				local-mac-address = [ 00 0a 35 00 00 00 ];
-				reg = < 0x81c00000 0x40 >;
-				xlnx,bus2core-clk-ratio = <0x1>;
-				xlnx,phy-type = <0x1>;
-				xlnx,phyaddr = <0x1>;
-				xlnx,rxcsum = <0x0>;
-				xlnx,rxfifo = <0x1000>;
-				xlnx,temac-type = <0x0>;
-				xlnx,txcsum = <0x0>;
-				xlnx,txfifo = <0x1000>;
-			} ;
-		} ;
-		IIC_EEPROM: i2c@81600000 {
-			compatible = "xlnx,xps-iic-2.00.a";
-			interrupt-parent = <&xps_intc_0>;
-			interrupts = < 6 2 >;
-			reg = < 0x81600000 0x10000 >;
-			xlnx,clk-freq = <0x7735940>;
-			xlnx,family = "virtex5";
-			xlnx,gpo-width = <0x1>;
-			xlnx,iic-freq = <0x186a0>;
-			xlnx,scl-inertial-delay = <0x0>;
-			xlnx,sda-inertial-delay = <0x0>;
-			xlnx,ten-bit-adr = <0x0>;
-		} ;
-		LEDs_8Bit: gpio@81400000 {
-			compatible = "xlnx,xps-gpio-1.00.a";
-			interrupt-parent = <&xps_intc_0>;
-			interrupts = < 7 2 >;
-			reg = < 0x81400000 0x10000 >;
-			xlnx,all-inputs = <0x0>;
-			xlnx,all-inputs-2 = <0x0>;
-			xlnx,dout-default = <0x0>;
-			xlnx,dout-default-2 = <0x0>;
-			xlnx,family = "virtex5";
-			xlnx,gpio-width = <0x8>;
-			xlnx,interrupt-present = <0x1>;
-			xlnx,is-bidir = <0x1>;
-			xlnx,is-bidir-2 = <0x1>;
-			xlnx,is-dual = <0x0>;
-			xlnx,tri-default = <0xffffffff>;
-			xlnx,tri-default-2 = <0xffffffff>;
-			#gpio-cells = <2>;
-			gpio-controller;
-		} ;
-
-		gpio-leds {
-			compatible = "gpio-leds";
-
-			heartbeat {
-				label = "Heartbeat";
-				gpios = <&LEDs_8Bit 4 1>;
-				linux,default-trigger = "heartbeat";
-			};
-
-			yellow {
-				label = "Yellow";
-				gpios = <&LEDs_8Bit 5 1>;
-			};
-
-			red {
-				label = "Red";
-				gpios = <&LEDs_8Bit 6 1>;
-			};
-
-			green {
-				label = "Green";
-				gpios = <&LEDs_8Bit 7 1>;
-			};
-		} ;
-		RS232_Uart_1: serial@84000000 {
-			clock-frequency = <125000000>;
-			compatible = "xlnx,xps-uartlite-1.00.a";
-			current-speed = <115200>;
-			device_type = "serial";
-			interrupt-parent = <&xps_intc_0>;
-			interrupts = < 8 0 >;
-			port-number = <0>;
-			reg = < 0x84000000 0x10000 >;
-			xlnx,baudrate = <0x1c200>;
-			xlnx,data-bits = <0x8>;
-			xlnx,family = "virtex5";
-			xlnx,odd-parity = <0x0>;
-			xlnx,use-parity = <0x0>;
-		} ;
-		SysACE_CompactFlash: sysace@83600000 {
-			compatible = "xlnx,xps-sysace-1.00.a";
-			interrupt-parent = <&xps_intc_0>;
-			interrupts = < 4 2 >;
-			reg = < 0x83600000 0x10000 >;
-			xlnx,family = "virtex5";
-			xlnx,mem-width = <0x10>;
-		} ;
-		debug_module: debug@84400000 {
-			compatible = "xlnx,mdm-1.00.d";
-			reg = < 0x84400000 0x10000 >;
-			xlnx,family = "virtex5";
-			xlnx,interconnect = <0x1>;
-			xlnx,jtag-chain = <0x2>;
-			xlnx,mb-dbg-ports = <0x1>;
-			xlnx,uart-width = <0x8>;
-			xlnx,use-uart = <0x1>;
-			xlnx,write-fsl-ports = <0x0>;
-		} ;
-		mpmc@90000000 {
-			#address-cells = <1>;
-			#size-cells = <1>;
-			compatible = "xlnx,mpmc-4.02.a";
-			ranges ;
-			PIM3: sdma@84600180 {
-				compatible = "xlnx,ll-dma-1.00.a";
-				interrupt-parent = <&xps_intc_0>;
-				interrupts = < 2 2 1 2 >;
-				reg = < 0x84600180 0x80 >;
-			} ;
-		} ;
-		xps_intc_0: interrupt-controller@81800000 {
-			#interrupt-cells = <0x2>;
-			compatible = "xlnx,xps-intc-1.00.a";
-			interrupt-controller ;
-			reg = < 0x81800000 0x10000 >;
-			xlnx,kind-of-intr = <0x100>;
-			xlnx,num-intr-inputs = <0x9>;
-		} ;
-		xps_timer_1: timer@83c00000 {
-			compatible = "xlnx,xps-timer-1.00.a";
-			interrupt-parent = <&xps_intc_0>;
-			interrupts = < 3 2 >;
-			reg = < 0x83c00000 0x10000 >;
-			xlnx,count-width = <0x20>;
-			xlnx,family = "virtex5";
-			xlnx,gen0-assert = <0x1>;
-			xlnx,gen1-assert = <0x1>;
-			xlnx,one-timer-only = <0x0>;
-			xlnx,trig0-assert = <0x1>;
-			xlnx,trig1-assert = <0x1>;
-		} ;
-	} ;
-}  ;
diff --git a/linux-2.6.37.6-antonio/arch/microblaze/boot/dts/system.dts b/linux-2.6.37.6-antonio/arch/microblaze/boot/dts/system.dts
new file mode 120000
index 0000000..7cb6578
--- /dev/null
+++ b/linux-2.6.37.6-antonio/arch/microblaze/boot/dts/system.dts
@@ -0,0 +1 @@
+../../platform/generic/system.dts
\ No newline at end of file
diff --git a/linux-2.6.37.6-antonio/arch/x86/Kconfig b/linux-2.6.37.6-antonio/arch/x86/Kconfig
index 57e823a..1cb5d8e 100644
--- a/linux-2.6.37.6-antonio/arch/x86/Kconfig
+++ b/linux-2.6.37.6-antonio/arch/x86/Kconfig
@@ -2101,7 +2101,6 @@ config SYSVIPC_COMPAT
 
 endmenu
 
-
 config HAVE_ATOMIC_IOMAP
 	def_bool y
 	depends on X86_32
@@ -2109,6 +2108,81 @@ config HAVE_ATOMIC_IOMAP
 config HAVE_TEXT_POKE_SMP
 	bool
 	select STOP_MACHINE if SMP
+	
+menu "Software Transactional Memory"
+
+config STM_ENABLE
+	bool "Enable Software Transactional Memory support"
+	---help---
+	  In kernel Software Transactional Memory
+	 
+choice
+	prompt "Enable debugging"
+	default STM_NODEBUG
+	depends on STM_ENABLE
+	---help---
+	  disable deugging for preformance measurement
+	  
+	config STM_NODEBUG
+		bool "no debugging support for STM"
+	config STM_DEBUG
+		bool "basic debug support"
+	config STM_DEBUG2
+		bool "a bit more debug support"
+	config STM_DEBUG3
+		bool "debugging support enabled in every submodules"
+endchoice
+
+choice
+	prompt "Contention Manager"
+	default STM_CM_DELAY
+	depends on STM_ENABLE
+	---help---
+	  Suicide is the default contention manager, different options
+	  require the Delay contention manager
+	  
+	config STM_CM_SUICIDE
+		bool "Suicide Contention Manager"
+	config STM_CM_DELAY
+		bool "Delay Contention Manager"
+endchoice
+
+choice
+	prompt "Contention Manager waiting strategy"
+	default STM_WAIT_SPIN
+	depends on STM_ENABLE && STM_CM_DELAY
+	---help---
+	  When a transaction is aborted and is delayed it must wait on 
+	  the winning transaction to commit
+	  
+	config STM_WAIT_SPIN
+		bool "default spinwait for the winning transaction to commit"
+	config STM_WAIT_YIELD
+		bool "Yield instead of spinwaiting delayed aborted transactions"
+	config STM_WAIT_COND
+		bool "Conditional waiting delayed aborted transactions"
+endchoice
+
+config STM_PREEMPT_AVOIDANCE
+	bool "STM Preempt Avoidance"
+	depends on STM_ENABLE
+	---help---
+	  stm preemption avoidance
+
+config STM_PREEMPT_BONUS
+	bool "STM Preempt Bonus"
+	depends on STM_PREEMPT_AVOIDANCE
+	---help---
+	  When a transactional thread avoid to be preempted at least once
+	  on commit it call yield after the commit is done. This happens also on abort. 
+
+config STM_MIGRATION_AVOIDANCE
+	bool "STM Migration Avoidance"
+	depends on STM_ENABLE
+	---help---
+	  stm migration avoidance
+
+endmenu	
 
 source "net/Kconfig"
 
diff --git a/linux-2.6.37.6-antonio/arch/x86/ia32/ia32entry.S b/linux-2.6.37.6-antonio/arch/x86/ia32/ia32entry.S
index 518bb99..030ea90 100644
--- a/linux-2.6.37.6-antonio/arch/x86/ia32/ia32entry.S
+++ b/linux-2.6.37.6-antonio/arch/x86/ia32/ia32entry.S
@@ -851,4 +851,5 @@ ia32_sys_call_table:
 	.quad sys_fanotify_init
 	.quad sys32_fanotify_mark
 	.quad sys_prlimit64		/* 340 */
+	.quad sys_checkpoint
 ia32_syscall_end:
diff --git a/linux-2.6.37.6-antonio/arch/x86/include/asm/unistd_32.h b/linux-2.6.37.6-antonio/arch/x86/include/asm/unistd_32.h
index b766a5e..f1fdb2d 100644
--- a/linux-2.6.37.6-antonio/arch/x86/include/asm/unistd_32.h
+++ b/linux-2.6.37.6-antonio/arch/x86/include/asm/unistd_32.h
@@ -346,10 +346,17 @@
 #define __NR_fanotify_init	338
 #define __NR_fanotify_mark	339
 #define __NR_prlimit64		340
+// checkpoint/rollback antonio old interface
+#define __NR_checkpoint		341
+#define __NR_rollback		342
+// checkpoint/rollback antonio current interface (refactored)
+#define __NR_snapshot		343
+// stm interface
+#define __NR_stm_ctrl		344
 
 #ifdef __KERNEL__
 
-#define NR_syscalls 341
+#define NR_syscalls 345
 
 #define __ARCH_WANT_IPC_PARSE_VERSION
 #define __ARCH_WANT_OLD_READDIR
diff --git a/linux-2.6.37.6-antonio/arch/x86/include/asm/unistd_64.h b/linux-2.6.37.6-antonio/arch/x86/include/asm/unistd_64.h
index 363e9b8..d3a72c1 100644
--- a/linux-2.6.37.6-antonio/arch/x86/include/asm/unistd_64.h
+++ b/linux-2.6.37.6-antonio/arch/x86/include/asm/unistd_64.h
@@ -670,6 +670,18 @@ __SYSCALL(__NR_fanotify_mark, sys_fanotify_mark)
 #define __NR_prlimit64				302
 __SYSCALL(__NR_prlimit64, sys_prlimit64)
 
+// checkpoint/rollback old interface (to be removed)
+#define __NR_checkpoint				303
+__SYSCALL(__NR_checkpoint, sys_checkpoint)
+#define __NR_rollback				304
+__SYSCALL(__NR_rollback, stub_rollback)
+// checkpoint/rollback current interface (refactored)
+#define __NR_snapshot				305
+__SYSCALL(__NR_snapshot, stub_snapshot)
+// stm control interface current
+#define __NR_stm_ctrl				306
+__SYSCALL(__NR_stm_ctrl, stub_stm_ctrl)
+
 #ifndef __NO_STUBS
 #define __ARCH_WANT_OLD_READDIR
 #define __ARCH_WANT_OLD_STAT
diff --git a/linux-2.6.37.6-antonio/arch/x86/kernel/entry_32.S b/linux-2.6.37.6-antonio/arch/x86/kernel/entry_32.S
index 591e601..02bccd1 100644
--- a/linux-2.6.37.6-antonio/arch/x86/kernel/entry_32.S
+++ b/linux-2.6.37.6-antonio/arch/x86/kernel/entry_32.S
@@ -732,6 +732,9 @@ PTREGSCALL0(sigreturn)
 PTREGSCALL0(rt_sigreturn)
 PTREGSCALL2(vm86)
 PTREGSCALL1(vm86old)
+PTREGSCALL1(rollback)
+PTREGSCALL3(snapshot)
+PTREGSCALL3(stm_ctrl)
 
 /* Clone is an oddball.  The 4th arg is in %edi */
 	ALIGN;
diff --git a/linux-2.6.37.6-antonio/arch/x86/kernel/entry_64.S b/linux-2.6.37.6-antonio/arch/x86/kernel/entry_64.S
index b235db9..573255e 100644
--- a/linux-2.6.37.6-antonio/arch/x86/kernel/entry_64.S
+++ b/linux-2.6.37.6-antonio/arch/x86/kernel/entry_64.S
@@ -686,6 +686,7 @@ END(\label)
 	PTREGSCALL stub_vfork, sys_vfork, %rdi
 	PTREGSCALL stub_sigaltstack, sys_sigaltstack, %rdx
 	PTREGSCALL stub_iopl, sys_iopl, %rsi
+	PTREGSCALL stub_rollback, sys_rollback, %rsi
 
 ENTRY(ptregscall_common)
 	DEFAULT_FRAME 1 8	/* offset 8: return address */
@@ -715,6 +716,36 @@ ENTRY(stub_execve)
 	CFI_ENDPROC
 END(stub_execve)
 
+ENTRY(stub_snapshot)
+	CFI_STARTPROC
+	addq $8, %rsp
+	PARTIAL_FRAME 0
+	SAVE_REST
+	FIXUP_TOP_OF_STACK %r11
+	movq %rsp, %rcx
+	call sys_snapshot
+	RESTORE_TOP_OF_STACK %r11
+	movq %rax,RAX(%rsp)
+	RESTORE_REST
+	jmp int_ret_from_sys_call
+	CFI_ENDPROC
+END(stub_snapshot)
+
+ENTRY(stub_stm_ctrl)
+	CFI_STARTPROC
+	addq $8, %rsp
+	PARTIAL_FRAME 0
+	SAVE_REST
+	FIXUP_TOP_OF_STACK %r11
+	movq %rsp, %rcx
+	call sys_stm_ctrl
+	RESTORE_TOP_OF_STACK %r11
+	movq %rax,RAX(%rsp)
+	RESTORE_REST
+	jmp int_ret_from_sys_call
+	CFI_ENDPROC
+END(stub_stm_ctrl)
+
 /*
  * sigreturn is special because it needs to restore all registers on return.
  * This cannot be done with SYSRET, so use the IRET return path instead.
diff --git a/linux-2.6.37.6-antonio/arch/x86/kernel/process_32.c b/linux-2.6.37.6-antonio/arch/x86/kernel/process_32.c
index 96586c3..95ab5ef 100644
--- a/linux-2.6.37.6-antonio/arch/x86/kernel/process_32.c
+++ b/linux-2.6.37.6-antonio/arch/x86/kernel/process_32.c
@@ -136,7 +136,7 @@ void __show_regs(struct pt_regs *regs, int all)
 		gs = get_user_gs(regs);
 	} else {
 		sp = kernel_stack_pointer(regs);
-		savesegment(ss, ss);
+		savesegment(ss, ss); // salva il contenuto del registro ss nella variabile ss
 		savesegment(gs, gs);
 	}
 
diff --git a/linux-2.6.37.6-antonio/arch/x86/kernel/syscall_table_32.S b/linux-2.6.37.6-antonio/arch/x86/kernel/syscall_table_32.S
index b35786d..675f309 100644
--- a/linux-2.6.37.6-antonio/arch/x86/kernel/syscall_table_32.S
+++ b/linux-2.6.37.6-antonio/arch/x86/kernel/syscall_table_32.S
@@ -340,3 +340,7 @@ ENTRY(sys_call_table)
 	.long sys_fanotify_init
 	.long sys_fanotify_mark
 	.long sys_prlimit64		/* 340 */
+	.long sys_checkpoint
+	.long ptregs_rollback
+	.long ptregs_snapshot
+	.long ptregs_stm_ctrl
diff --git a/linux-2.6.37.6-antonio/arch/x86/kvm/emulate.c b/linux-2.6.37.6-antonio/arch/x86/kvm/emulate.c
index 38b6e8d..328e9a7 100644
--- a/linux-2.6.37.6-antonio/arch/x86/kvm/emulate.c
+++ b/linux-2.6.37.6-antonio/arch/x86/kvm/emulate.c
@@ -675,7 +675,7 @@ static int decode_modrm(struct x86_emulate_ctxt *ctxt,
 	c->modrm_rm |= (c->modrm & 0x07);
 	c->modrm_seg = VCPU_SREG_DS;
 
-	if (c->modrm_mod == 3) {
+	if (c->modrm_mod == 3) { // means in register value
 		op->type = OP_REG;
 		op->bytes = (c->d & ByteOp) ? 1 : c->op_bytes;
 		op->addr.reg = decode_register(c->modrm_rm,
@@ -684,7 +684,7 @@ static int decode_modrm(struct x86_emulate_ctxt *ctxt,
 		return rc;
 	}
 
-	op->type = OP_MEM;
+	op->type = OP_MEM; // otherwise mem access
 
 	if (c->ad_bytes == 2) {
 		unsigned bx = c->regs[VCPU_REGS_RBX];
diff --git a/linux-2.6.37.6-antonio/fs/proc/base.c b/linux-2.6.37.6-antonio/fs/proc/base.c
index 1828451..983abc5 100644
--- a/linux-2.6.37.6-antonio/fs/proc/base.c
+++ b/linux-2.6.37.6-antonio/fs/proc/base.c
@@ -362,6 +362,23 @@ static int proc_pid_schedstat(struct task_struct *task, char *buffer)
 }
 #endif
 
+#ifdef CONFIG_STM_ENABLE
+/*
+ * Provides /proc/PID/stm
+ */
+static int proc_pid_stm(struct task_struct *task, char *buffer)
+{
+	return (task->thread_tx) ? sprintf(buffer, "task is tx %s %s %s (%d)\n",
+			(task->thread_tx->status & 0x01) ? "ACTIVE" : "IDLE",
+			((task->thread_tx->status & 0x06) == 0x06) ? "KILL" :
+			  (task->thread_tx->status & 0x02) ? "COMMIT" :
+			    (task->thread_tx->status & 0x04) ? "ABORT" : "none",
+			(task->thread_tx->status & 0x08) ? "IRREVOCABLE" : "none",
+			task->thread_tx->status)
+			: sprintf(buffer, "task is not tx\n");
+}
+#endif
+
 #ifdef CONFIG_LATENCYTOP
 static int lstats_show_proc(struct seq_file *m, void *v)
 {
@@ -2768,6 +2785,9 @@ static const struct pid_entry tgid_base_stuff[] = {
 #ifdef CONFIG_SCHEDSTATS
 	INF("schedstat",  S_IRUGO, proc_pid_schedstat),
 #endif
+#ifdef CONFIG_STM_ENABLE
+	INF("stm",  S_IRUGO, proc_pid_stm),
+#endif
 #ifdef CONFIG_LATENCYTOP
 	REG("latency",  S_IRUGO, proc_lstats_operations),
 #endif
@@ -3104,6 +3124,9 @@ static const struct pid_entry tid_base_stuff[] = {
 #ifdef CONFIG_SCHEDSTATS
 	INF("schedstat", S_IRUGO, proc_pid_schedstat),
 #endif
+#ifdef CONFIG_STM_ENABLE
+	INF("stm", S_IRUGO, proc_pid_stm),
+#endif
 #ifdef CONFIG_LATENCYTOP
 	REG("latency",  S_IRUGO, proc_lstats_operations),
 #endif
diff --git a/linux-2.6.37.6-antonio/include/linux/sched.h b/linux-2.6.37.6-antonio/include/linux/sched.h
index c3dcd7c..54a2967 100644
--- a/linux-2.6.37.6-antonio/include/linux/sched.h
+++ b/linux-2.6.37.6-antonio/include/linux/sched.h
@@ -95,6 +95,7 @@ struct sched_param {
 #include <linux/errno.h>
 #include <linux/nodemask.h>
 #include <linux/mm_types.h>
+#include <linux/stm_types.h>
 
 #include <asm/system.h>
 #include <asm/page.h>
@@ -1147,6 +1148,9 @@ struct sched_statistics {
 	u64			nr_migrations_cold;
 	u64			nr_failed_migrations_affine;
 	u64			nr_failed_migrations_running;
+# ifdef CONFIG_STM_MIGRATION_AVOIDANCE
+	u64			nr_failed_migrations_stm;
+# endif
 	u64			nr_failed_migrations_hot;
 	u64			nr_forced_migrations;
 
@@ -1315,9 +1319,16 @@ struct task_struct {
 	/*
 	 * support for process checkpointing/snapshotting
 	 */
-#ifdef CONFIG_PROCESS_CHECKPOINTING
-	struct list_head checkpoint; /* list of task_struct of this process */
-#endif
+//#ifdef CONFIG_PROCESS_CHECKPOINTING
+//	struct list_head checkpoint; /* list of task_struct of this process */
+//#endif
+	struct hlist_head snapshot; // init the list!!! on process copy/creation
+//	unsigned num_snapshot; // number of snapshots in the list
+
+	/*
+	 * support for STM (codebase TinySTM)
+	 */
+	stm_tx_t* thread_tx;
 
 	/*
 	 * ptraced is the list of tasks this task is using ptrace on.
diff --git a/linux-2.6.37.6-antonio/include/linux/snapshot.h b/linux-2.6.37.6-antonio/include/linux/snapshot.h
new file mode 100644
index 0000000..2dcf345
--- /dev/null
+++ b/linux-2.6.37.6-antonio/include/linux/snapshot.h
@@ -0,0 +1,62 @@
+/*
+ * snapshot.h
+ *
+ *  Created on: Dec 12, 2011
+ *      Author: root
+ */
+
+#ifndef SNAPSHOT_H_
+#define SNAPSHOT_H_
+
+typedef struct __snapshot {
+	struct pt_regs regs;
+	void* usr_stack;
+	int usr_stacksize;
+	int pad_stacksize;
+	unsigned flag; // incremental checkpoints?
+	struct hlist_node next;
+	//TODO
+} snapshot_t;
+
+/* snapshot memory is allocated in kernel snapshot_t first, stack then memory is padded */
+
+/*---------------------*/
+/*   snapshot_t + pad  */
+/*---------------------*/
+/*   usr stack copy    */
+/*---------------------*/
+
+#define SNAP_CREATE_STACK	0x0001
+#define SNAP_CREATE_REGS	0x0002
+#define SNAP_CREATE_FILE	0x0004
+#define SNAP_CREATE_MM		0x0008
+#define SNAP_CREATE_MMIO	0x0010
+#define SNAP_CREATE_		0x0020
+
+/*
+ * SNAP_CREATE_INC create an incremental snapshot
+ * SNAP_CREATE_GZIP saves a compressed copy of the snapshot (to save memory)
+ * SNAP_CREATE_SWAP enforce swapping of the created snapshot (to save memory)
+ */
+#define SNAP_CREATE_INC		0x0100
+#define SNAP_CREATE_GZIP	0x0200
+#define SNAP_CREATE_SWAP	0x0400
+
+#define SNAP_RESTORE_STACK	SNAP_CREATE_STACK
+//same options
+
+#define SNAP_DELETE_OTHER	0x10000
+#define SNAP_DELETE_PREVS	0x20000
+#define SNAP_DELETE_NEXTS	0x40000
+#define SNAP_DELETE_CUR		0x80000
+#define SNAP_DELETE_ALL		(SNAP_DELETE_CUR | SNAP_DELETE_OTHER)
+
+// in task context usage (assume current task context)
+snapshot_t * create_snapshot(__user void * stackaddr, long stacksize, unsigned long flags, struct pt_regs * regs);
+snapshot_t * restore_snapshot (snapshot_t * snap, unsigned long flags, struct pt_regs * regs);
+int delete_snapshot(snapshot_t * psnap, unsigned long flag);
+
+// general usage
+int exit_snapshot(struct task_struct * tsk);
+
+#endif /* SNAPSHOT_H_ */
diff --git a/linux-2.6.37.6-antonio/include/linux/stm.h b/linux-2.6.37.6-antonio/include/linux/stm.h
new file mode 100644
index 0000000..652165c
--- /dev/null
+++ b/linux-2.6.37.6-antonio/include/linux/stm.h
@@ -0,0 +1,437 @@
+/*
+ * File:
+ *   stm.h
+ * Author(s):
+ *   Pascal Felber <pascal.felber@unine.ch>
+ * Description:
+ *   STM functions.
+ *
+ * Copyright (c) 2007-2009.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, version 2
+ * of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+/**
+ * @file
+ *   STM functions.  This library contains the core functions for
+ *   programming with STM.
+ * @author
+ *   Pascal Felber <pascal.felber@unine.ch>
+ * @date
+ *   2007-2009
+ */
+
+/**
+ * @mainpage TinySTM
+ *
+ * @section overview_sec Overview
+ *
+ *   TinySTM is a lightweight but efficient word-based STM
+ *   implementation.  This distribution includes three versions of
+ *   TinySTM: write-back (updates are buffered until commit time),
+ *   write-through (updates are directly written to memory), and
+ *   commit-time locking (locks are only acquired upon commit).  The
+ *   version can be selected by editing the makefile, which documents
+ *   all the different compilation options.
+ *
+ *   TinySTM compiles and runs on 32 or 64-bit architectures.  It was
+ *   tested on various flavors of Unix, on Mac OS X, and on Windows
+ *   using cygwin.  It comes with a few test applications, notably a
+ *   linked list, a skip list, and a red-black tree.
+ *
+ * @section install_sec Installation
+ *
+ *   TinySTM requires the atomic_ops library, freely available from
+ *   http://www.hpl.hp.com/research/linux/atomic_ops/.  A stripped-down
+ *   version of the library is included in the TinySTM distribution.  If you
+ *   wish to use another version, you must set the environment variable
+ *   <c>LIBAO_HOME</c> to the installation directory of atomic_ops.
+ *
+ *   If your system does not support GCC thread-local storage, set the
+ *   environment variable <c>NOTLS</c> to a non-empty value before
+ *   compilation.
+ *
+ *   To compile TinySTM libraries, execute <c>make</c> in the main
+ *   directory.  To compile test applications, execute <c>make test</c>.
+ *
+ * @section contact_sec Contact
+ *
+ *   - E-mail : tinystm@tinystm.org
+ *   - Web    : http://tinystm.org
+ */
+
+#ifndef _STM_H_
+# define _STM_H_
+
+/* ################################################################### *
+ * TYPES
+ * ################################################################### */
+
+#include <linux/stm_types.h>
+
+/* ################################################################### *
+ * FUNCTIONS
+ * ################################################################### */
+
+/**
+ * Initialize the STM library.  This function must be called once, from
+ * the main thread, before any access to the other functions of the
+ * library.
+ */
+int stm_init(void);
+
+/**
+ * Clean up the STM library.  This function must be called once, from
+ * the main thread, after all transactional threads have completed.
+ */
+void stm_exit(void );
+
+
+/**
+ * Start a transaction.
+ *
+ * @param attr
+ *   Specifies optional attributes associated to the transaction.  If
+ *   null, the transaction uses default attributes.
+ * @return
+ *   Environment (stack context) to be used to jump back upon abort.  It
+ *   is the responsibility of the application to call sigsetjmp()
+ *   immediately after starting the transaction.  If the transaction is
+ *   nested, the function returns NULL and one should not call
+ *   sigsetjmp() as an abort will restart the top-level transaction
+ *   (flat nesting).
+ */
+uintptr_t *stm_start(TXPARAMS stm_tx_attr_t *attr);
+
+/**
+ * Try to commit a transaction.  If successful, the function returns 1.
+ * Otherwise, execution continues at the point where sigsetjmp() has
+ * been called after starting the outermost transaction (unless the
+ * attributes indicate that the transaction should not retry).
+ *
+ * @return
+ *   1 upon success, 0 otherwise.
+ */
+//int stm_commit(TXPARAM);
+int stm_commit(void);
+/**
+ * Explicitly abort a transaction.  Execution continues at the point
+ * where sigsetjmp() has been called after starting the outermost
+ * transaction (unless the attributes indicate that the transaction
+ * should not retry).
+ */
+int stm_abort(TXPARAMS int abort_reason);
+
+/**
+ * Transactional load.  Read the specified memory location in the
+ * context of the current transaction and return its value.  Upon
+ * conflict, the transaction may abort while reading the memory
+ * location.  Note that the value returned is consistent with respect to
+ * previous reads from the same transaction.
+ *
+ * @param addr
+ *   Address of the memory location.
+ * @return
+ *   Value read from the specified address.
+ */
+stm_word_t stm_load(TXPARAMS volatile stm_word_t *addr, stm_word_t *value);
+
+/**
+ * Transactional store.  Write a word-sized value to the specified
+ * memory location in the context of the current transaction.  Upon
+ * conflict, the transaction may abort while writing to the memory
+ * location.
+ *
+ * @param addr
+ *   Address of the memory location.
+ * @param value
+ *   Value to be written.
+ */
+int stm_store(TXPARAMS volatile stm_word_t *addr, stm_word_t value);
+
+/**
+ * Transactional store.  Write a value to the specified memory location
+ * in the context of the current transaction.  The value may be smaller
+ * than a word on the target architecture, in which case a mask is used
+ * to indicate the bits of the words that must be updated.  Upon
+ * conflict, the transaction may abort while writing to the memory
+ * location.
+ *
+ * @param addr
+ *   Address of the memory location.
+ * @param value
+ *   Value to be written.
+ * @param mask
+ *   Mask specifying the bits to be written.
+ */
+int stm_store2(TXPARAMS volatile stm_word_t *addr, stm_word_t value, stm_word_t mask);
+
+/**
+ * Check if the current transaction is still active.
+ *
+ * @return
+ *   True (non-zero) if the transaction is active, false (zero) otherwise.
+ */
+//int stm_active(TXPARAM);
+int stm_active(void);
+
+/**
+ * Check if the current transaction has aborted.
+ *
+ * @return
+ *   True (non-zero) if the transaction has aborted, false (zero) otherwise.
+ */
+//int stm_aborted(TXPARAM);
+int stm_aborted(void);
+
+/**
+ * Check if the current transaction is still active and in irrevocable
+ * state.
+ *
+ * @return 
+ *   True (non-zero) if the transaction is active and irrevocable, false
+ *   (zero) otherwise.
+ */
+//int stm_irrevocable(TXPARAM);
+int stm_irrevocable(void);
+
+/**
+ * Get the environment used by the current thread to jump back upon
+ * abort.  This environment should be used when calling sigsetjmp()
+ * before starting the transaction and passed as parameter to
+ * stm_start().  If the current thread is already executing a
+ * transaction, i.e., the new transaction will be nested, the function
+ * returns NULL and one should not call sigsetjmp().
+ *
+ * @return
+ *   The environment to use for saving the stack context, or NULL if the
+ *   transaction is nested.
+ */
+//sigjmp_buf *stm_get_env(TXPARAM);
+
+/**
+ * Get attributes associated with the current transactions, if any.
+ * These attributes were passed as parameters when starting the
+ * transaction.
+ *
+ * @return Attributes associated with the current transaction, or NULL
+ *   if no attributes were specified when starting the transaction.
+ */
+//stm_tx_attr_t *stm_get_attributes(TXPARAM);
+stm_tx_attr_t *stm_get_attributes(void);
+
+/**
+ * Get various statistics about the current thread/transaction.  See the
+ * source code (stm.c) for a list of supported statistics.
+ *
+ * @param name
+ *   Name of the statistics.
+ * @param val
+ *   Pointer to the variable that should hold the value of the
+ *   statistics.
+ * @return
+ *   1 upon success, 0 otherwise.
+ */
+int stm_get_stats(TXPARAMS const char *name, void *val);
+
+/**
+ * Get various parameters of the STM library.  See the source code
+ * (stm.c) for a list of supported parameters.
+ *
+ * @param name
+ *   Name of the parameter.
+ * @param val
+ *   Pointer to the variable that should hold the value of the
+ *   parameter.
+ * @return
+ *   1 upon success, 0 otherwise.
+ */
+int stm_get_parameter(const char *name, void *val);
+
+/**
+ * Set various parameters of the STM library.  See the source code
+ * (stm.c) for a list of supported parameters.
+ *
+ * @param name
+ *   Name of the parameter.
+ * @param val
+ *   Pointer to a variable that holds the new value of the parameter.
+ * @return
+ *   1 upon success, 0 otherwise.
+ */
+int stm_set_parameter(const char *name, void *val);
+
+/**
+ * Create a key to associate application-specific data to the current
+ * thread/transaction.  This mechanism can be combined with callbacks to
+ * write modules.
+ *
+ * @return
+ *   The new key.
+ */
+int stm_create_specific(void);
+
+/**
+ * Get application-specific data associated to the current
+ * thread/transaction and a given key.
+ *
+ * @param key
+ *   Key designating the data to read.
+ * @return
+ *   Data stored under the given key.
+ */
+void *stm_get_specific(TXPARAMS int key);
+
+/**
+ * Set application-specific data associated to the current
+ * thread/transaction and a given key.
+ *
+ * @param key
+ *   Key designating the data to read.
+ * @param data
+ *   Data to store under the given key.
+ */
+void stm_set_specific(TXPARAMS int key, void *data);
+
+/**
+ * Register application-specific callbacks that are triggered each time
+ * particular events occur.
+ *
+ * @param on_thread_init
+ *   Function called upon initialization of a transactional thread.
+ * @param on_thread_exit
+ *   Function called upon cleanup of a transactional thread.
+ * @param on_start
+ *   Function called upon start of a transaction.
+ * @param on_commit
+ *   Function called upon successful transaction commit.
+ * @param on_abort
+ *   Function called upon transaction abort.
+ * @param arg
+ *   Parameter to be passed to the callback functions.
+ * @return
+ *   1 if the callbacks have been successfully registered, 0 otherwise.
+ */
+/*
+int stm_register(void (*on_thread_init)(TXPARAMS void *arg),
+                 void (*on_thread_exit)(TXPARAMS void *arg),
+                 void (*on_start)(TXPARAMS void *arg),
+                 void (*on_commit)(TXPARAMS void *arg),
+                 void (*on_abort)(TXPARAMS void *arg),
+                 void *arg);
+*/
+/**
+ * Transaction-safe load.  Read the specified memory location outside of
+ * the context of any transaction and return its value.  The operation
+ * behaves as if executed in the context of a dedicated transaction
+ * (i.e., it executes atomically and in isolation) that never aborts,
+ * but may get delayed.
+ *
+ * @param addr Address of the memory location.
+
+ * @param timestamp If non-null, the referenced variable is updated to
+ *   hold the timestamp of the memory location being read.
+ * @return
+ *   Value read from the specified address.
+ */
+stm_word_t stm_unit_load(volatile stm_word_t *addr, stm_word_t *timestamp);
+
+/**
+ * Transaction-safe store.  Write a word-sized value to the specified
+ * memory location outside of the context of any transaction.  The
+ * operation behaves as if executed in the context of a dedicated
+ * transaction (i.e., it executes atomically and in isolation) that
+ * never aborts, but may get delayed.
+ *
+ * @param addr
+ *   Address of the memory location.
+ * @param value
+ *   Value to be written.
+ * @param timestamp If non-null and the timestamp in the referenced
+ *   variable is smaller than that of the memory location being written,
+ *   no data is actually written and the variable is updated to hold the
+ *   more recent timestamp. If non-null and the timestamp in the
+ *   referenced variable is not smaller than that of the memory location
+ *   being written, the memory location is written and the variable is
+ *   updated to hold the new timestamp.
+ * @return
+ *   1 if value has been written, 0 otherwise.
+ */
+int stm_unit_store(volatile stm_word_t *addr, stm_word_t value, stm_word_t *timestamp);
+
+/**
+ * Transaction-safe store.  Write a value to the specified memory
+ * location outside of the context of any transaction.  The value may be
+ * smaller than a word on the target architecture, in which case a mask
+ * is used to indicate the bits of the words that must be updated.  The
+ * operation behaves as if executed in the context of a dedicated
+ * transaction (i.e., it executes atomically and in isolation) that
+ * never aborts, but may get delayed.
+ *
+ * @param addr
+ *   Address of the memory location.
+ * @param value
+ *   Value to be written.
+ * @param mask
+ *   Mask specifying the bits to be written.
+ * @param timestamp If non-null and the timestamp in the referenced
+ *   variable is smaller than that of the memory location being written,
+ *   no data is actually written and the variable is updated to hold the
+ *   more recent timestamp. If non-null and the timestamp in the
+ *   referenced variable is not smaller than that of the memory location
+ *   being written, the memory location is written and the variable is
+ *   updated to hold the new timestamp.
+ * @return
+ *   1 if value has been written, 0 otherwise.
+ */
+int stm_unit_store2(volatile stm_word_t *addr, stm_word_t value, stm_word_t mask, stm_word_t *timestamp);
+
+/**
+ * Enable or disable snapshot extensions for the current transaction,
+ * and optionally set an upper bound for the snapshot.  This function is
+ * useful for implementing efficient algorithms with unit loads and
+ * stores while preserving compatibility with with regular transactions.
+ *
+ * @param enable
+ *   True (non-zero) to enable snapshot extensions, false (zero) to
+ *   disable them.
+ * @param timestamp
+ *   If non-null and the timestamp in the referenced variable is smaller
+ *   than the current upper bound of the snapshot, update the upper
+ *   bound to the value of the referenced variable.
+ */
+void stm_set_extension(TXPARAMS int enable, stm_word_t *timestamp);
+
+/**
+ * Read the current value of the global clock (used for timestamps).
+ * This function is useful when programming with unit loads and stores.
+ *
+ * @return
+ *   Value of the global clock.
+ */
+stm_word_t stm_get_clock(void);
+
+/**
+ * Enter irrevokable mode for the current transaction.  If successful,
+ * the function returns 1.  Otherwise, it aborts and execution continues
+ * at the point where sigsetjmp() has been called after starting the
+ * outermost transaction (unless the attributes indicate that the
+ * transaction should not retry).
+ *
+ * @param enable
+ *   True (non-zero) for serial-irrevocable mode (no transaction can
+ *   execute concurrently), false for parallel-irrevocable mode.
+ * @return
+ *   1 upon success, 0 otherwise.
+ */
+int stm_set_irrevocable(TXPARAMS int serial);
+
+#endif /* _STM_H_ */
diff --git a/linux-2.6.37.6-antonio/include/linux/stm_types.h b/linux-2.6.37.6-antonio/include/linux/stm_types.h
new file mode 100644
index 0000000..e661c49
--- /dev/null
+++ b/linux-2.6.37.6-antonio/include/linux/stm_types.h
@@ -0,0 +1,403 @@
+/*
+ * stm_types.h
+ *
+ *  Created on: Jan 5, 2012
+ *      Author: Antonio Barbalace <antoniob@vt.edu>
+ *
+ *  This work is a Linux kernel port of the TinySTM project.
+ */
+/*
+ * STM Types contains:
+ * configuration parameters (must be moved in KConfig)
+ * stm types definition (ok here)
+ */
+
+#ifndef STM_TYPES_H_
+#define STM_TYPES_H_
+
+/* Version string */
+# define STM_VERSION                    "1.0.0"
+/* Version number (times 100) */
+# define STM_VERSION_NB                 100
+
+//-----------------------------------------------------------------------------
+// CONFIGURATION STARTS HERE
+//-----------------------------------------------------------------------------
+
+/* ################################################################### *
+ * Contention managers
+ * ################################################################### */
+#define CM_SUICIDE                      0
+#define CM_DELAY                        1
+#define CM_BACKOFF                      2
+#define CM_MODULAR                      3
+
+#if defined(CONFIG_STM_CM_SUICIDE)
+# define CM                             CM_SUICIDE
+#elif defined(CONFIG_STM_CM_DELAY)
+# define CM                             CM_DELAY
+#else
+# define CM                             CM_SUICIDE
+#endif /* ! CM */
+
+//default WAIT_SPIN
+#undef WAIT_YIELD
+#undef WAIT_COND
+#if defined(CONFIG_STM_WAIT_YIELD)
+# define WAIT_YIELD
+#elif defined(CONFIG_STM_WAIT_COND)
+# define WAIT_COND
+#endif
+
+/* ################################################################### *
+ * DESIGNES
+ * ################################################################### */
+#define WRITE_BACK_ETL                  0
+#define WRITE_BACK_CTL                  1
+#define WRITE_THROUGH                   2
+
+#ifndef DESIGN
+# define DESIGN                         WRITE_BACK_ETL
+#endif /* ! DESIGN */
+
+// the followings cames from src/Makefile, lookup at the Makefile to write
+// the help for each KConfig configuration parameters (some are mod for our impl)
+//we also disable temporary IRREVOCABLE to speed the porting and testing (no test cases)
+//#define IRREVOCABLE_ENABLED
+#undef IRREVOCABLE_ENABLED
+#define INTERNAL_STATS
+#undef USE_BLOOM_FILTER
+#undef CONFLICT_TRACKING
+#undef READ_LOCKED_DATA
+
+#define CLOCK_IN_CACHE_LINE
+#undef NO_DUPLICATES_IN_RW_SETS
+//temporary disable for speed the porting TODO
+//#define EPOCH_GC
+#undef EPOCH_GC
+
+//TODO the following are very critical until not renamed
+//TODO (many other kernel components have the same name)
+//#undef DEBUG
+//#define DEBUG
+//#undef DEBUG2
+//#define DEBUG2
+
+//#define EXPLICIT_TX_PARAMETER
+
+#ifndef RW_SET_SIZE
+# define RW_SET_SIZE                    4096                /* Initial size of read/write sets */
+#endif /* ! RW_SET_SIZE */
+
+#ifndef LOCK_ARRAY_LOG_SIZE
+# define LOCK_ARRAY_LOG_SIZE            20                  /* Size of lock array: 2^20 = 1M */
+#endif /* LOCK_ARRAY_LOG_SIZE */
+
+#ifndef LOCK_SHIFT_EXTRA
+# define LOCK_SHIFT_EXTRA               2                   /* 2 extra shift */
+#endif /* LOCK_SHIFT_EXTRA */
+
+//the followings are too related to the particular choice of
+//the conflict manager so they remain in the ipc/stm.h
+//# DEFINES += -DMIN_BACKOFF=0x04UL
+//# DEFINES += -DMAX_BACKOFF=0x80000000UL
+//# DEFINES += -DVR_THRESHOLD_DEFAULT=3
+
+
+//-----------------------------------------------------------------------------
+// STM TYPES START HERE
+//-----------------------------------------------------------------------------
+
+/*
+ * The library does not require to pass the current transaction as a
+ * parameter to the functions (the current transaction is stored in a
+ * thread-local variable).  One can, however, compile the library with
+ * explicit transaction parameters.  This is useful, for instance, for
+ * performance on architectures that do not support TLS or for easier
+ * compiler integration.
+ */
+# ifdef EXPLICIT_TX_PARAMETER
+struct stm_tx;
+#  define TXTYPE                        struct stm_tx *
+#  define TXPARAM                       struct stm_tx *tx
+#  define TXPARAMS                      struct stm_tx *tx,
+#  define TXARG                         (struct stm_tx *)tx
+#  define TXARGS                        (struct stm_tx *)tx,
+struct stm_tx *stm_current_tx();
+# else /* ! EXPLICIT_TX_PARAMETER */
+#  define TXTYPE                        void
+#  define TXPARAM                       /* Nothing */
+#  define TXPARAMS                      /* Nothing */
+#  define TXARG                         /* Nothing */
+#  define TXARGS                        /* Nothing */
+#endif /* ! EXPLICIT_TX_PARAMETER */
+
+#ifdef EXPLICIT_TX_PARAMETER
+# define TX_RETURN                      return tx
+# define TX_GET                         /* Nothing */
+#else /* ! EXPLICIT_TX_PARAMETER */
+# define TX_RETURN                      /* Nothing */
+# define TX_GET                         stm_tx_t *tx = stm_get_tx()
+#endif /* ! EXPLICIT_TX_PARAMETER */
+
+/**
+ * Size of a word (accessible atomically) on the target architecture.
+ * The library supports 32-bit and 64-bit architectures.
+ */
+// the following is defined in <linux/types.h>
+typedef uintptr_t stm_word_t;
+
+/**
+ * Transaction attributes specified by the application.
+ */
+typedef struct stm_tx_attr {
+  /**
+   * Application-specific identifier for the transaction.  Typically,
+   * each transactional construct (atomic block) should have a different
+   * identifier.  This identifier can be used by the infrastructure for
+   * improving performance, for instance by not scheduling together
+   * atomic blocks that have conflicted often in the past.
+   */
+  int id;
+  /**
+   * Indicates whether the transaction is read-only.  This information
+   * is used as a hint.  If a read-only transaction performs a write, it
+   * is aborted and restarted in read-write mode.  In that case, the
+   * value of the read-only flag is changed to false.  If no attributes
+   * are specified when starting a transaction, it is assumed to be
+   * read-write.
+   */
+  unsigned int read_only : 1;
+  /**
+   * Indicates that the transaction should not retry execution using
+   * sigsetjmp() after abort.  If no attributes are specified when
+   * starting a transaction, the default behavior is to retry.
+   */
+  unsigned int no_retry : 1;
+} stm_tx_attr_t;
+
+typedef struct r_entry {                /* Read set entry */
+  stm_word_t version;                   /* Version read */
+  volatile stm_word_t *lock;            /* Pointer to lock (for fast access) */
+} r_entry_t;
+
+typedef struct r_set {                  /* Read set */
+  r_entry_t *entries;                   /* Array of entries */
+  int nb_entries;                       /* Number of entries */
+  int size;                             /* Size of array */
+} r_set_t;
+
+typedef struct w_entry {                /* Write set entry */
+  union {                               /* For padding... */
+    struct {
+      volatile stm_word_t *addr;        /* Address written */
+      stm_word_t value;                 /* New (write-back) or old (write-through) value */
+      stm_word_t mask;                  /* Write mask */
+      stm_word_t version;               /* Version overwritten */
+      volatile stm_word_t *lock;        /* Pointer to lock (for fast access) */
+#if CM == CM_MODULAR || (defined(CONFLICT_TRACKING) && DESIGN != WRITE_THROUGH)
+      struct stm_tx *tx;                /* Transaction owning the write set */
+#endif /* CM == CM_MODULAR || (defined(CONFLICT_TRACKING) && DESIGN != WRITE_THROUGH) */
+#if DESIGN == WRITE_BACK_ETL
+      struct w_entry *next;             /* Next address covered by same lock (if any) */
+#else /* DESIGN != WRITE_BACK_ETL */
+      int no_drop;                      /* Should we drop lock upon abort? */
+#endif /* DESIGN != WRITE_BACK_ETL */
+    };
+    stm_word_t padding[8];              /* Padding (multiple of a cache line) */
+  };
+} w_entry_t;
+
+typedef struct w_set {                  /* Write set */
+  w_entry_t *entries;                   /* Array of entries */
+  int nb_entries;                       /* Number of entries */
+  int size;                             /* Size of array */
+#if DESIGN == WRITE_BACK_ETL
+  int has_writes;                       /* Has the write set any real write (vs. visible reads) */
+#elif DESIGN == WRITE_BACK_CTL
+  int nb_acquired;                      /* Number of locks acquired */
+# ifdef USE_BLOOM_FILTER
+  stm_word_t bloom;                     /* Same Bloom filter as in TL2 */
+# endif /* USE_BLOOM_FILTER */
+#endif /* DESIGN == WRITE_BACK_CTL */
+} w_set_t;
+
+typedef struct cb_entry {               /* Callback entry */
+  void (*f)(TXPARAMS void *);           /* Function */
+  void *arg;                            /* Argument to be passed to function */
+} cb_entry_t;
+
+#ifndef MAX_SPECIFIC
+# define MAX_SPECIFIC                   64
+#endif /* MAX_SPECIFIC */
+
+/* ################################################################### *
+ * TYPES
+ * ################################################################### */
+
+typedef struct mod_stats_data {         /* Transaction statistics */
+  unsigned long commits;                /* Total number of commits (cumulative) */
+  unsigned long retries;                /* Number of consecutive aborts of current transaction (retries) */
+  unsigned long retries_min;            /* Minimum number of consecutive aborts */
+  unsigned long retries_max;            /* Maximum number of consecutive aborts */
+  unsigned long retries_acc;            /* Total number of aborts (cumulative) */
+  unsigned long retries_cnt;            /* Number of samples for cumulative aborts */
+} mod_stats_data_t;
+
+typedef struct stm_tx {                 /* Transaction descriptor */
+//  sigjmp_buf env;                       /* Environment for setjmp/longjmp (must be first field!) */
+	uintptr_t snapshot;						// snapshot id of the transaction
+
+  stm_tx_attr_t attr;                  /* Transaction attributes (user-specified) */
+  volatile stm_word_t status;           /* Transaction status */
+  stm_word_t start;                     /* Start timestamp */
+  stm_word_t end;                       /* End timestamp (validity range) */
+  r_set_t r_set;                        /* Read set */
+  w_set_t w_set;                        /* Write set */
+  unsigned int ro:1;                    /* Is this execution read-only? */
+  unsigned int can_extend:1;            /* Can this transaction be extended? */
+#ifdef IRREVOCABLE_ENABLED
+  unsigned int irrevocable:4;           /* Is this execution irrevocable? */
+#endif /* IRREVOCABLE_ENABLED */
+  int nesting;                          /* Nesting level */
+#if CM == CM_MODULAR
+  stm_word_t timestamp;                 /* Timestamp (not changed upon restart) */
+#endif /* CM == CM_MODULAR */
+  void *data[MAX_SPECIFIC];             /* Transaction-specific data (fixed-size array for better speed) */
+  struct stm_tx *next;                  /* For keeping track of all transactional threads */
+// TODO
+//#ifdef CONFLICT_TRACKING
+//  pthread_t thread_id;                  /* Thread identifier (immutable) */
+//#endif /* CONFLICT_TRACKING */
+#if CM == CM_DELAY || CM == CM_MODULAR
+  volatile stm_word_t *c_lock;          /* Pointer to contented lock (cause of abort) */
+#endif /* CM == CM_DELAY || CM == CM_MODULAR */
+#if CM == CM_BACKOFF
+  unsigned long backoff;                /* Maximum backoff duration */
+  unsigned long seed;                   /* RNG seed */
+#endif /* CM == CM_BACKOFF */
+#if CM == CM_MODULAR
+  int visible_reads;                    /* Should we use visible reads? */
+#endif /* CM == CM_MODULAR */
+#ifdef CONFIG_STM_PREEMPT_BONUS
+  int bonus;
+#endif /* STM_PREEMPT_AVOIDANCE */
+#if CM == CM_MODULAR || defined(INTERNAL_STATS)
+  unsigned long retries;                /* Number of consecutive aborts (retries) */
+#endif /* CM == CM_MODULAR || defined(INTERNAL_STATS) */
+#ifdef INTERNAL_STATS
+  unsigned long aborts;                 /* Total number of aborts (cumulative) */
+  unsigned long aborts_1;               /* Total number of transactions that abort once or more (cumulative) */
+  unsigned long aborts_2;               /* Total number of transactions that abort twice or more (cumulative) */
+  unsigned long aborts_ro;              /* Aborts due to wrong read-only specification (cumulative) */
+  unsigned long aborts_locked_read;     /* Aborts due to trying to read when locked (cumulative) */
+  unsigned long aborts_locked_write;    /* Aborts due to trying to write when locked (cumulative) */
+  unsigned long aborts_validate_read;   /* Aborts due to failed validation upon read (cumulative) */
+  unsigned long aborts_validate_write;  /* Aborts due to failed validation upon write (cumulative) */
+  unsigned long aborts_validate_commit; /* Aborts due to failed validation upon commit (cumulative) */
+  unsigned long aborts_invalid_memory;  /* Aborts due to invalid memory access (cumulative) */
+# if CM == CM_MODULAR
+  unsigned long aborts_killed;          /* Aborts due to being killed (cumulative) */
+# endif /* CM == CM_MODULAR */
+# ifdef READ_LOCKED_DATA
+  unsigned long locked_reads_ok;        /* Successful reads of previous value */
+  unsigned long locked_reads_failed;    /* Failed reads of previous value */
+# endif /* READ_LOCKED_DATA */
+  unsigned long max_retries;            /* Maximum number of consecutive aborts (retries) */
+#endif /* INTERNAL_STATS */
+  /* local stats*/
+  mod_stats_data_t mod_stats;
+
+  struct {
+  	void * addr;
+  	int size;
+  } stack;
+
+} stm_tx_t;
+
+/**
+ * Reason for aborting (returned by sigsetjmp() upon transaction
+ * restart).
+ */
+enum {
+  /**
+   * Abort due to explicit call from the programmer (no retry).
+   */
+  STM_ABORT_EXPLICIT = (1 << 4),
+  /**
+   * Implicit abort (high order bits indicate more detailed reason).
+   */
+  STM_ABORT_IMPLICIT = (1 << 5),
+  /**
+   * Abort upon reading a memory location being read by another
+   * transaction.
+   */
+  STM_ABORT_RR_CONFLICT = (1 << 5) | (0x01 << 8),
+  /**
+   * Abort upon writing a memory location being read by another
+   * transaction.
+   */
+  STM_ABORT_RW_CONFLICT = (1 << 5) | (0x02 << 8),
+  /**
+   * Abort upon reading a memory location being written by another
+   * transaction.
+   */
+  STM_ABORT_WR_CONFLICT = (1 << 5) | (0x03 << 8),
+  /**
+   * Abort upon writing a memory location being written by another
+   * transaction.
+   */
+  STM_ABORT_WW_CONFLICT = (1 << 5) | (0x04 << 8),
+  /**
+   * Abort upon read due to failed validation.
+   */
+  STM_ABORT_VAL_READ = (1 << 5) | (0x05 << 8),
+  /**
+   * Abort upon write due to failed validation.
+   */
+  STM_ABORT_VAL_WRITE = (1 << 5) | (0x06 << 8),
+  /**
+   * Abort upon commit due to failed validation.
+   */
+  STM_ABORT_VALIDATE = (1 << 5) | (0x07 << 8),
+  /**
+   * Abort upon write from a transaction declared as read-only.
+   */
+  STM_ABORT_RO_WRITE = (1 << 5) | (0x08 << 8),
+  /**
+   * Abort upon deferring to an irrevocable transaction.
+   */
+  STM_ABORT_IRREVOCABLE = (1 << 5) | (0x09 << 8),
+  /**
+   * Abort due to being killed by another transaction.
+   */
+  STM_ABORT_KILLED = (1 << 5) | (0x0A << 8),
+  /**
+   * Abort due to receiving a signal.
+   */
+  STM_ABORT_SIGNAL = (1 << 5) | (0x0B << 8),
+  /**
+   * Abort due to other reasons (internal to the protocol).
+   */
+  STM_ABORT_OTHER = (1 << 5) | (0x0F << 8)
+};
+
+
+/**
+ * Initialize a transactional thread.  This function must be called once
+ * from each thread that performs transactional operations, before the
+ * thread calls any other functions of the library.
+ */
+//TXTYPE stm_init_thread( void);
+stm_tx_t * stm_init_thread( void);
+
+/**
+ * Clean up a transactional thread.  This function must be called once
+ * from each thread that performs transactional operations, upon exit.
+ */
+//void stm_exit_thread(TXPARAM);
+void stm_exit_thread(stm_tx_t * a);
+
+
+
+#endif /* STM_TYPES_H_ */
diff --git a/linux-2.6.37.6-antonio/include/linux/syscalls.h b/linux-2.6.37.6-antonio/include/linux/syscalls.h
index cacc27a..b50ee66 100644
--- a/linux-2.6.37.6-antonio/include/linux/syscalls.h
+++ b/linux-2.6.37.6-antonio/include/linux/syscalls.h
@@ -833,4 +833,6 @@ asmlinkage long sys_mmap_pgoff(unsigned long addr, unsigned long len,
 			unsigned long fd, unsigned long pgoff);
 asmlinkage long sys_old_mmap(struct mmap_arg_struct __user *arg);
 
+asmlinkage long sys_checkpoint(int key, int msgflg);
+
 #endif
diff --git a/linux-2.6.37.6-antonio/ipc/Makefile b/linux-2.6.37.6-antonio/ipc/Makefile
index 9075e17..bd3c6f5 100644
--- a/linux-2.6.37.6-antonio/ipc/Makefile
+++ b/linux-2.6.37.6-antonio/ipc/Makefile
@@ -8,5 +8,5 @@ obj-$(CONFIG_SYSVIPC_SYSCTL) += ipc_sysctl.o
 obj_mq-$(CONFIG_COMPAT) += compat_mq.o
 obj-$(CONFIG_POSIX_MQUEUE) += mqueue.o msgutil.o $(obj_mq-y)
 obj-$(CONFIG_IPC_NS) += namespace.o
-obj-$(CONFIG_POSIX_MQUEUE_SYSCTL) += mq_sysctl.o
+obj-$(CONFIG_POSIX_MQUEUE_SYSCTL) += mq_sysctl.o snapshot.o stm.o
 
diff --git a/linux-2.6.37.6-antonio/ipc/snapshot.c b/linux-2.6.37.6-antonio/ipc/snapshot.c
index 2b6d35c..73afcbf 100644
--- a/linux-2.6.37.6-antonio/ipc/snapshot.c
+++ b/linux-2.6.37.6-antonio/ipc/snapshot.c
@@ -1,15 +1,559 @@
-/* snapshot/checkpoint and rollback
+/* snapshot
+ * checkpoint and rollback system calls
  * snapshot.c
  *
  *  Created on: Dec 7, 2011
  *      Author: Antonio Barbalace
  */
 
+/*
+ * the idea is to rollback kernel and user space components
+ * for user space, library support is required (maybe)
+ * we are going to hack a little bit to find out the best solution
+ * (but this is not on the critical pat for STM in kernel
+ */
+
+// kernel can call this function tring to restore a program that hangs up (this can be done under application control)
+// signals can use this facility. Like browsers
+
 #include <linux/syscalls.h>
 #include <linux/uaccess.h>
 
-SYSCALL_DEFINE6(ipc, unsigned int, call, int, first, unsigned long, second,
-		unsigned long, third, void __user *, ptr, long, fifth)
 
 
+//SYSCALL_DEFINE6(ipc, unsigned int, call, int, first, unsigned long, second,
+		//unsigned long, third, void __user *, ptr, long, fifth)
+
+/*SYSCALL_DEFINE0(getpid)
+{
+	return task_tgid_vnr(current);
+}*/
+
+/*int sys_fork(struct pt_regs *regs)
+{
+	return do_fork(SIGCHLD, regs->sp, regs, 0, NULL, NULL);
+}*/
+
+//syscall 341
+//i386 __NR_checkpoint 341
+/*
+ * TODO (what to do)
+ * arch/x86/kernel/syscall_table_32.S (sys_callback)
+ * arch/x86/include/asm/unistd_32.h REM to increment number
+ */
+//x86_64 __NR_checkpoint ?!?!
+/*
+ * TODO
+ * arch/x86/include/asm/unistd_64.h (__SYSCALL(__NR_checkpoint, sys_checkpoint) )
+ */
+/* experimental checkpoint as the way setjmp/longjmp do*/
+//SYSCALL_DEFINE2(rollback, key_t, key, int, msgflg)
+SYSCALL_DEFINE2(checkpoint, int, key, int, msgflg)
+{
+	/*
+	cosa voglio:
+
+	dettagli sul thread
+	dettagli sui registri
+	mi sa che dobbiamo di nuovo copiare
+	da do_fork
+*/
+	printk("SYSCALL_DEFINE2 checkpoint arg1 %d arg2 %d\n", key, msgflg);
+	return THREAD_SIZE;
+}
+
+
+//syscall 342
+//i386 __NR_rollback
+// pt_regs IS THE LAST ARGUMENT!!!
+/*
+ * TODO (what to do)
+ * arch/x86/kernel/syscall_table_32.S (ptregs_rollback)
+ * arch/x86/include/asm/unistd_32.h REM to increment number
+ * arch/x86/kernel/entry_32.S
+ */
+/*
+ * arch/x86/include/asm/unistd_64.h __SYSCALL(__NR_rollback, stub_rollback)
+ * arch/x86/kernel/entry_64.S
+ */
+//
+//int sys_fork(struct pt_regs *regs)
+//{ return do_fork(SIGCHLD, regs->sp, regs, 0, NULL, NULL); }
+int sys_rollback(int kkey, struct pt_regs *regs)
+{
+	printk("int sys_rollback arg1 %p arg2 %d\n", regs, kkey);
+	//show_regs(regs); //generate troubles
+	show_registers(regs); // still too verbose probably
+	//__show_regs(regs);
+
+	printk("user_mode_vm ret %d\n", user_mode_vm(regs));
+
+	printk("VM total %ld locked %ld shared %ld exec %ld stack %ld reserved %ld\n",
+			current->mm->total_vm, current->mm->locked_vm, current->mm->shared_vm,
+			current->mm->exec_vm, current->mm->stack_vm, current->mm->reserved_vm);
+	printk("def_flags %lx nr_ptes %ld\n",
+			current->mm->def_flags, current->mm->nr_ptes);
+	printk("CODE start %08lx end %08lx DATA start %08lx end %08lx BRK start %08lx %08lx STACK start %08lx\n",
+			current->mm->start_code, current->mm->end_code, current->mm->start_data, current->mm->end_data,
+			current->mm->start_brk, current->mm->brk, current->mm->start_stack);
+	printk("ARG start %08lx end %08lx ENV start %08lx end %08lx\n",
+			current->mm->arg_start, current->mm->arg_end, current->mm->env_start, current->mm->env_end);
+
+	unsigned long start;
+	struct mm_struct * mm = get_task_mm(current); //lock
+	struct vm_area_struct * vma = mm->mmap;
+	do {
+		start = 0;
+		if (vma->vm_flags & VM_GROWSDOWN) //qua assumono sempre che se ce qualcosa che ha l'opzione grows down e stack
+			if (!vma_stack_continue(vma->vm_prev, vma->vm_start))
+				start = vma->vm_start + PAGE_SIZE;
+
+		printk("%08lx-%08lx %c%c%c%c%c %08llx %8lx %s \n",
+				vma->vm_start,
+				vma->vm_end,
+				vma->vm_flags & VM_READ ? 'r' : '-',
+				vma->vm_flags & VM_WRITE ? 'w' : '-',
+				vma->vm_flags & VM_EXEC ? 'x' : '-',
+				vma->vm_flags & VM_MAYSHARE ? 's' : 'p',
+				vma->vm_flags & VM_GROWSDOWN ? 'd' : 'u',
+				vma->vm_file ? ((loff_t)vma->vm_pgoff) << PAGE_SHIFT : 0,
+				start,
+				vma->vm_file ? "file" : "none"
+				);
+	} while ( (vma = vma->vm_next) );
+	mmput(mm); //get_task_mm release mm is mmput
+
+	// NOTA in the file task_mmu.c they understand if the memory is stack or heap comparing it with start_stack or start_brk
+
+	// we need to obtain from user space the stack top address and copy the stack until the current sp,
+	// we cannot relay on kernel values for pthreads.. stack addr and stack size must be readed from user space
+
+	return kkey;
+}
+
+//#include <asm/uaccess.h>
+// copy_from_user
+
+#include <linux/errno.h>
+#include <linux/list.h>
+#include <linux/slab.h>
+
+#include <linux/snapshot.h>
+
+
+#include <asm/page.h>
+
+typedef struct __chk_pnt {
+	int index;
+	long flags;
+} chk_pnt;
+#define DEFAULT_FLAGS 0x0000
+
+//syscall 343
+//i386 __NR_snapshot
+// pt_regs IS THE LAST ARGUMENT!!!
+// TODO: future implementation details:
+/*
+ * future versions will implement
+ * secure page copies in swap o in protected memory areas (no iomapped hw regions)
+ * incremental snapshotting
+ */
+
+/*
+ * TODO (what to do)
+ * arch/x86/kernel/syscall_table_32.S (ptregs_rollback)
+ * arch/x86/include/asm/unistd_32.h REM to increment number
+ * arch/x86/kernel/entry_32.S
+ */
+/*
+ * arch/x86/include/asm/unistd_64.h __SYSCALL(__NR_rollback, stub_rollback)
+ * arch/x86/kernel/entry_64.S
+ */
+int PREVsys_snapshot(void* stackaddr, int stacksize, chk_pnt * chk_user_data, struct pt_regs *regs)
+{
+	chk_pnt user_data;
+	int ret = 0;
+
+	//check user address before access -> done by copy_from_user .. __must_ch
+	if (chk_user_data) { // if this is zero we cannot return index data and read flag data
+		// return bytes that cannot be copied
+		if ( (ret = copy_from_user(&user_data, chk_user_data, sizeof(chk_pnt))) )
+			printk("sys_snapshot error retrieving data from user space ret %d sizeof %d addr %p\n",
+					ret, sizeof(chk_pnt), chk_user_data); // error
+	} else
+		user_data.flags = DEFAULT_FLAGS;
+
+// GOAL: create a generic interface to the take_snapshot/rollback_snapshot
+// TODO move to incremental snapshots (TODO, idea: check last address if < check around last addr if same incremental enabled)
+// ARG: stackaddr, stacksize, flags, pt_regs RETURN handler or error -> 0
+	if (stackaddr) //switch work based on stackaddr
+	{ // if not zero the request is a checkpoint -------- process CHECKPOINT
+		void* stack_top = stackaddr + stacksize;
+		void* stack_curr = (void *) regs->sp;
+		unsigned long size = (unsigned long)stack_top - (unsigned long)stack_curr;
+		snapshot_t * psnap;
+		unsigned snapshot_size = 0;
+
+		//check stack addresses consistency
+		if ((stackaddr <= stack_curr) && (stack_curr <= stack_top))
+			printk("stack curr is in range! addr %p curr %p top %p size %ld\n",
+					stackaddr, stack_curr, stack_top, size);
+		else
+			//error
+			printk("stack curr is NOT in range! addr %p curr %p top %p size %ld\n",
+					stackaddr, stack_curr, stack_top, size);
+
+		// allocate a new checkpoint struct in current task_struct
+		// TODO round up snapshot_t  + round up size to align stack memory size
+		snapshot_size = (sizeof(snapshot_t) + size);
+		psnap = (snapshot_t *) kmalloc(snapshot_size, GFP_KERNEL);
+		if (!psnap) {
+			printk("sys_snapshot error kmalloc failed in requesting %d byte\n",
+					snapshot_size);
+			// something to return?
+			return -1;
+		}
+		memset((void*)psnap, 0, snapshot_size);
+		//INIT_HLIST_NODE()  same as memset..
+
+		psnap->usr_stack = stackaddr;
+		psnap->usr_stacksize = stacksize;
+		psnap->regs = *regs;
+		psnap->pad_stacksize = snapshot_size;
+
+		// stack copy from user space.. this is the only thing that could fail
+		if ( (ret = copy_from_user((void*) &(psnap[1]), stack_curr, size)) ) {
+			printk("sys_snapshot error copying user space stack in kernel ret %d (cannot be copied) size %d to %p from %p\n",
+					ret, size, &(psnap[1]), stack_curr); // error
+			//error
+			kfree((void*) psnap);
+			return -1;
+		}
+
+		hlist_add_head( &(psnap->next), &(current->snapshot) );
+		user_data.index = psnap; // save handler
+
+		// in the case of a checkpoint before returning must write to user the index num
+		if (chk_user_data)
+			if ( (ret = copy_to_user(chk_user_data, &user_data, sizeof(chk_pnt))) )
+				printk("sys_snapshot error writing data to user space ret %d sizeof %d\n",
+						ret, sizeof(chk_pnt)); // error
+
+		return 0; // on checkpoint if no error return is 0
+	} else
+
+//ARG:handler flags pt_regs RETURNS success or error
+	{ // if zero the request is a rollback -------- process ROLLBACK
+		//check if current process has snapshot
+		if (hlist_empty ( &(current->snapshot) ) ) {
+			//error
+			printk("rollback interface no snapshot for the current process\n");
+			return -1;
+		}
+		// we have to walk the list and find the handler
+		snapshot_t * tpos;
+		struct hlist_node * pos, * n;
+		hlist_for_each_entry_safe(tpos, pos, n, &(current->snapshot), next) {
+			if ( tpos == (snapshot_t *)user_data.index ) {
+				break;
+			}
+		}
+		if ( tpos != (snapshot_t *)user_data.index ) {
+			//error
+			printk("rollack interface no snapshots with the current handler %08x\n", user_data.index);
+			return -1;
+		}
+
+		//recalc stack size
+		void* stack_top = tpos->usr_stack + tpos->usr_stacksize;
+		unsigned long size = (unsigned long)stack_top - (unsigned long)tpos->regs.sp;
+
+		// TODO why not to match the current stack data before rollback?!?! (future todo)
+		if ( (ret = copy_to_user((void *) tpos->regs.sp, &(tpos[1]), size)) ) {
+				printk("sys_snapshot error writing STACK data to user space ret %d(cannot be copied). CRITICAL\n",
+						ret); // error
+		}
+
+		// if the handler exist then rollback snapshot user stack + ptregs
+		*regs = tpos->regs;
+
+		// eliminate the checkpoint or all checkpoints following what flags requires...
+		printk("rollback completed with sucess\n");
+
+		return stacksize; // on rollback return value depends on the user request (in stacksize var)
+	}
+}
+
+
+// new data structures from user space
+
+// the following data structures and defines are only reqiured to user space
+// and from the syscall entry point
+typedef struct __stack_struct {
+	void * addr;
+	long size;
+} stack_struct;
+
+typedef struct __user_struct {
+	//int index;
+	uintptr_t hnd; //snapshot handler (i.e. a pointer to snapshot_t -> snapshot_t *)
+	long flags;
+	int data; // return value for rollbacks.. and also for create.. this is specified by the user
+} user_struct;
+
+#define SNAP_CREATE		0x0010
+#define SNAP_DELETE		0x0020
+#define SNAP_RESTORE	0x0030
+
+//#define SNAP_DEBUG(a...) printk(a)
+#define SNAP_DEBUG(a...)
+
+/*
+ * sys_snapshot
+ * entry point for snapshotting functions
+ * NEW VERSION (REFACTORING 28jan2012)
+ * this new version uses stack_struct and user_struct
+ * calls the internal functions take_snapshot/revert_snapshot
+ * @ returns 0 on success otherwise error code
+ */
+//int sys_snapshot(void* stackaddr, int stacksize, chk_pnt * chk_user_data, struct pt_regs *regs)
+int sys_snapshot(int func, __user stack_struct * pstack, __user user_struct * puser, struct pt_regs *regs)
+{
+	snapshot_t * psnap;
+	stack_struct stack;
+	user_struct user;
+	int ret;
+
+	if ( !puser )
+		return -EINVAL;
+
+	// copy_from_user checks for user access consistency and returns bytes that cannot be copied
+	// first copy the stack data structure
+	memset(&stack, 0, sizeof(stack_struct));
+	if (pstack) {
+		if ( (ret = copy_from_user(&stack, pstack, sizeof(stack_struct))) )
+			printk("%s: warn copy_from_user(&stack failed %d (cannot be copied) size %d to %p from %p\n",
+					__func__, ret, sizeof(stack_struct), &stack, pstack);
+	}
+
+	// then copy the user data structure
+	memset(&user, 0, sizeof(user_struct));
+	if (puser) { // if this is zero we cannot return index data and read flag data
+		if ( (ret = copy_from_user(&user, puser, sizeof(user_struct))) )
+			printk("%s: warn copy_from_user(&user failed %d (cannot be copied) size %d to %p from %p\n",
+					__func__, ret, sizeof(user_struct), &user, &puser);
+	}
+
+	// function demultiplexer
+	switch (func) {
+	// snapshot create function, returns error on parameters and memory not allocated
+	case SNAP_CREATE: {
+		if ( !pstack )
+			return -EINVAL;
+		if ( (psnap = create_snapshot(stack.addr, stack.size, user.flags, regs)) == 0)
+			return -ENOMEM;
+
+		user.hnd = psnap;
+			if ( (ret = copy_to_user(puser, &user, sizeof(user_struct))) ) {
+				printk("%s: error copy_to_user failed with %d (cannot be copied) size %d from %p to %p\n",
+						__func__, ret, sizeof(chk_pnt), &user, puser); // error
+				return -ENOMEM;
+			}
+
+		break;
+	}
+	// snapshot restore function, returns error on snapshot not found
+	case SNAP_RESTORE: {
+		if ( (psnap = restore_snapshot(user.hnd, user.flags, regs)) == 0)
+			return -ENODEV;
+		break;
+	}
+	// snapshot delete lets the user delete the recorded snapshot for space efficiency
+	case SNAP_DELETE: {
+		if ( (ret = delete_snapshot(user.hnd, user.flags)) == 0)
+			return -ENODEV;
+		return ret;
+	}
+	// default case we left signaling a warning in the console log message
+	default:
+		printk("%s: warn function %d not supported\n",
+				__func__, func);
+		return -EINVAL;
+	}
+
+	// we save the actual snapshot_t pointer and copy user_data back in user space
+/*	user.hnd = psnap;
+	if ( (ret = copy_to_user(puser, &user, sizeof(user_struct))) ) {
+		printk("%s: critical error copy_to_user failed with %d (cannot be copied) size %d from %p to %p\n",
+				__func__, ret, sizeof(chk_pnt), &user, puser); // error
+		return -ENOMEM;
+	}
+*/	return user.data; // we always return what the user has specified in the .data field
+}
+
+// GOAL: take_snapshot must do the minimum from user space (because must be called from any other kernel point)
+
+// GOAL: create a generic interface to the take_snapshot/rollback_snapshot
+// TODO move to incremental snapshots (TODO, idea: check last address if < check around last addr if same incremental enabled)
+// ARG: stackaddr, stacksize, flags, pt_regs RETURN handler or error -> 0
+//return original pointer to the registered structure
+//we save together regs and stack no memory blocks.. all other stuff contained in the struct_task must be saved
+
+// NEXT VERSION must ensure that no one of the other threads of the process is accessing the memory
+//we are going to copy from user space!
+
+// move documentation in sthe h file
+/**
+ * take_snapshot
+ * @param
+ * @return
+ */
+snapshot_t * create_snapshot(__user void * stackaddr, long stacksize, unsigned long flags, struct pt_regs * regs)
+{
+	void* stack_top = stackaddr + stacksize;
+	void* stack_curr = (void *) regs->sp;
+	unsigned long stack_size = (unsigned long)stack_top - (unsigned long)stack_curr;
+	unsigned snap_size = 0;
+	unsigned ret = 0;
+	snapshot_t * psnap;
+
+	//check stack addresses consistency
+	if ((stackaddr <= stack_curr) && (stack_curr <= stack_top)) {
+		SNAP_DEBUG("%s: info stack curr IS in range addr %p curr %p top %p size %ld pid %d\n",
+			__func__, stackaddr, stack_curr, stack_top, stack_size, current->pid);
+	}
+	else {
+		//error
+		printk("%s: error stack curr IS NOT in range addr %p curr %p top %p size %ld pid %d\n",
+				__func__, stackaddr, stack_curr, stack_top, stack_size, current->pid);
+		return NULL;
+	}
+
+	// allocate a new snapshot struct that holds the stack copy too
+	snap_size = (sizeof(snapshot_t) + stack_size);
+	// roundup to page size (ceil)
+	snap_size = ((snap_size / PAGE_SIZE) +1) << PAGE_SHIFT;
+	// NOTE kmalloc supports maximum of 128kB
+	psnap = (snapshot_t *) kmalloc(snap_size, GFP_KERNEL);
+	if (!psnap) {
+		printk("%s: error kmalloc failed requesting %d byte\n",
+				__func__, snap_size);
+		return NULL;
+	}
+	memset((void*)psnap, 0, snap_size);
+	psnap->usr_stack = stackaddr;
+	psnap->usr_stacksize = stacksize;
+	psnap->regs = *regs;
+	psnap->pad_stacksize = snap_size;
+
+	// TODO incremental stack snapshot support
+
+	// copy stack from user space (this could fail)
+	if ( (ret = copy_from_user((void*) &(psnap[1]), stack_curr, stack_size)) ) {
+		printk("%s: error copy_from_user failed with %d (cannot be copied) size %d to %p from %p pid %d\n",
+				__func__, ret, stack_size, &(psnap[1]), stack_curr, current->pid);
+		//error free the allocated structures
+		kfree((void*) psnap);
+		return NULL;
+	}
+
+	// add the snapshot to the list of snapshot in struct task_struct
+	hlist_add_head( &(psnap->next), &(current->snapshot) );
+	return psnap;
+}
+
+
+//ARG:handler flags pt_regs RETURNS success or error
+// returned/reverted snapshot must be freed?!? --> no add another api to delete snapshot or add flag to revert and delete snapshot
+//
+snapshot_t * restore_snapshot (snapshot_t * snap, unsigned long flags, struct pt_regs * regs)
+{
+	int ret = 0;
+	snapshot_t * tpos;
+	struct hlist_node * pos, * n;
+	void* stack_top;
+	unsigned long stack_size;
+
+	//check if current process has snapshot
+	if (hlist_empty ( &(current->snapshot) ) ) {
+		//error
+		printk("%s: error no snapshot registered in the current process\n",
+				__func__);
+		return NULL;
+	}
+	// we have to walk the list and find the handler
+	hlist_for_each_entry_safe(tpos, pos, n, &(current->snapshot), next) {
+		if ( tpos == snap ) {
+			break;
+		}
+	}
+	// check if the snapshot really exist
+	if ( tpos != snap ) { //error
+		printk("%s: error no snapshots with the current handler %08x\n",
+				__func__, snap);
+		return NULL;
+	}
+
+	// recalc stack size from saved data
+	stack_top = tpos->usr_stack + tpos->usr_stacksize;
+	stack_size = (unsigned long)stack_top - (unsigned long)tpos->regs.sp;
+
+	// TODO why not to match the current stack data before rollback?!?! (future todo)
+	if ( (ret = copy_to_user((void *) tpos->regs.sp, &(tpos[1]), stack_size)) ) {
+		printk("%s: error copy_to_user failed with %d (cannot be copied) size %d from %p to %p pid %d\n",
+				__func__, ret, stack_size, &(tpos[1]), (void *) tpos->regs.sp, current->pid); // error
+		return NULL;
+	}
+	// revert to the previous register set
+	*regs = tpos->regs;
+
+	// we choose to do not eliminate here the checkpoint
+	SNAP_DEBUG("%s: info completed successfully pid %d\n",
+			__func__, current->pid);
+	return tpos;
+}
+
+int delete_snapshot(snapshot_t * psnap, unsigned long flag)
+{
+	int count = 0;
+	snapshot_t * tpos;
+	struct hlist_node * pos, * n;
+
+	// if no elements in the list return error
+	if (hlist_empty ( &(current->snapshot) ) )
+		return -ENODEV;
+
+
+
+	// we have to walk the list and find the handler (_safe against removals)
+	hlist_for_each_entry_safe(tpos, pos, n, &(current->snapshot), next) {
+		hlist_del( &(tpos->next) );
+		kfree(tpos);
+	}
+	return count;
+}
+
+
+// the following is to be used not in task context
+
+
+// TODO flags
+// TODO next release: delete checkpoint list with FLAGS
+// TODO next version incremental snapshots (after full integration)
+// TODO signals rollback
+// TODO file roll back
+
+int exit_snapshot(struct task_struct * tsk)
+{
+	if (hlist_empty ( &(tsk->snapshot) ) )
+		return 0;
 
+	// we have to walk the list and find the handler (_safe against removals)
+	snapshot_t * tpos;
+	struct hlist_node * pos, * n;
+	hlist_for_each_entry_safe(tpos, pos, n, &(tsk->snapshot), next) {
+		hlist_del( &(tpos->next) );
+		kfree(tpos);
+	}
+	return 0;
+}
diff --git a/linux-2.6.37.6-antonio/ipc/stm.c b/linux-2.6.37.6-antonio/ipc/stm.c
new file mode 100644
index 0000000..b871c79
--- /dev/null
+++ b/linux-2.6.37.6-antonio/ipc/stm.c
@@ -0,0 +1,2803 @@
+/*
+ * This code is an adaption of TinyTM for the Linux Kernel
+ *
+ * Author(s):
+ *   Pascal Felber <pascal.felber@unine.ch> Copyright (c) 2007-2009.
+ *   Antonio Barbalace <antoniob@vt.edu> Copyright (c) 2011-2012
+ */
+
+/* TinyTM
+ *
+ * Transaction nesting is supported in a minimalist way (flat nesting):
+ * - When a transaction is started in the context of another
+ *   transaction, we simply increment a nesting counter but do not
+ *   actually start a new transaction.
+ * - The environment to be used for setjmp/longjmp is only returned when
+ *   no transaction is active so that it is not overwritten by nested
+ *   transactions. This allows for composability as the caller does not
+ *   need to know whether it executes inside another transaction.
+ * - The commit of a nested transaction simply decrements the nesting
+ *   counter. Only the commit of the top-level transaction will actually
+ *   carry through updates to shared memory.
+ * - An abort of a nested transaction will rollback the top-level
+ *   transaction and reset the nesting counter. The call to longjmp will
+ *   restart execution before the top-level transaction.
+ * Using nested transactions without setjmp/longjmp is not recommended
+ * as one would need to explicitly jump back outside of the top-level
+ * transaction upon abort of a nested transaction. This breaks
+ * composability.
+ */
+
+/*
+ * Reading from the previous version of locked addresses is implemented
+ * by peeking into the write set of the transaction that owns the
+ * lock. Each transaction has a unique identifier, updated even upon
+ * retry. A special "commit" bit of this identifier is set upon commit,
+ * right before writing the values from the redo log to shared memory. A
+ * transaction can read a locked address if the identifier of the owner
+ * does not change between before and after reading the value and
+ * version, and it does not have the commit bit set.
+ */
+
+
+
+#include <linux/errno.h>
+
+//#include <signal.h>
+//#include <stdio.h>
+
+//memory allocation must be handled by the slab linux allocator
+// we are going to use the kmem cache for stm_tx_t struct
+// and kmalloc/vmalloc for r_entry_t and w_entry_t because they use arrays
+// kmalloc have a 128kB limit do we have to switch to vmalloc?
+//#include <string.h>
+#include <linux/slab.h> // kmalloc
+//#include <linux/malloc.h> // kmem_cache DO NOT EXSIST
+#include <linux/vmalloc.h> // vmalloc
+
+//#include <pthread.h>
+
+//linux/sched.h now is not required but can be necessary
+//#include <sched.h>
+
+
+// original dependencies in TinySTM include/stm.h
+//#include "stm.h"
+#include <linux/stm.h> //new include directive (same as include/stm.h)
+//the following is the local stm.h include (naming convention to be rebuild?)
+#include "stm.h"
+
+#include <linux/stddef.h>
+
+//#include <assert.h>
+#define assert(a) BUG_ON(!(a))
+//#define assert(a) WARN_ON(a)
+
+#include "stm_atomic.h"
+
+
+#define COMPILE_TIME_ASSERT(pred)        switch (0) { case 0: case pred: ; }
+/* included in the linux kernel
+#if defined(__GNUC__) || defined(__INTEL_COMPILER)
+# define likely(x)                      __builtin_expect(!!(x), 1)
+# define unlikely(x)                    __builtin_expect(!!(x), 0)
+//#endif
+*/
+
+#include "stm_design.h"
+#include "stm_cm.h"
+#include "stm.h"
+
+static inline stm_tx_t * stm_get_tx(void);
+
+#include "stm_mod_stats.h"
+#include "stm_syscall.h"
+
+/* ################################################################### *
+ * THREAD-LOCAL
+ * ################################################################### */
+/*
+#ifdef TLS
+static __thread stm_tx_t* thread_tx = NULL;
+#else
+static pthread_key_t thread_tx;
+#endif
+*/
+//move to struct task_struct --> add transaction descriptor to
+
+static struct kmem_cache * stm_tx_cache = 0;
+
+ static inline stm_tx_t * stm_get_tx(void) {
+	 if ( !(current->thread_tx) )
+		 printk("%s: error tx desc is zero [pid %d]\n", __func__, current->pid);
+	 return current->thread_tx; }
+
+#if CM == CM_MODULAR
+#include "stm_cm_modular.h"
+#endif /* CM == CM_MODULAR */
+
+#ifdef LOCK_IDX_SWAP
+/*
+ * Compute index in lock table (swap bytes to avoid consecutive addresses to have neighboring locks).
+ */
+static inline unsigned int lock_idx_swap(unsigned int idx) {
+  return (idx & ~(unsigned int)0xFFFF) | ((idx & 0x00FF) << 8) | ((idx & 0xFF00) >> 8);
+}
+#endif /* LOCK_IDX_SWAP */
+
+#include "stm_quiesce.h"
+
+/*
+ * Reset clock and timestamps
+ */
+static inline void rollover_clock(void *arg)
+{
+  PRINT_DEBUG("==> rollover_clock()\n");
+
+  /* Reset clock */
+  CLOCK = 0;
+  /* Reset timestamps */
+  memset((void *)locks, 0, LOCK_ARRAY_SIZE * sizeof(stm_word_t));
+# ifdef EPOCH_GC
+  /* Reset GC */
+  gc_reset();
+# endif /* EPOCH_GC */
+}
+
+/*
+ * Check if stripe has been read previously.
+ */
+static inline r_entry_t *stm_has_read(stm_tx_t *tx, volatile stm_word_t *lock)
+{
+  r_entry_t *r;
+  int i;
+
+  PRINT_DEBUG("==> stm_has_read(%p[%lu-%lu],%p)\n", tx, (unsigned long)tx->start, (unsigned long)tx->end, lock);
+
+  /* Look for read */
+  r = tx->r_set.entries;
+  for (i = tx->r_set.nb_entries; i > 0; i--, r++) {
+    if (r->lock == lock) {
+      /* Return first match*/
+      return r;
+    }
+  }
+  return NULL;
+}
+
+#if DESIGN == WRITE_BACK_CTL
+/*
+ * Check if address has been written previously.
+ */
+static inline w_entry_t *stm_has_written(stm_tx_t *tx, volatile stm_word_t *addr)
+{
+  w_entry_t *w;
+  int i;
+# ifdef USE_BLOOM_FILTER
+  stm_word_t mask;
+# endif /* USE_BLOOM_FILTER */
+
+  PRINT_DEBUG("==> stm_has_written(%p[%lu-%lu],%p)\n", tx, (unsigned long)tx->start, (unsigned long)tx->end, addr);
+
+# ifdef USE_BLOOM_FILTER
+  mask = FILTER_BITS(addr);
+  if ((tx->w_set.bloom & mask) != mask)
+    return NULL;
+# endif /* USE_BLOOM_FILTER */
+
+  /* Look for write */
+  w = tx->w_set.entries;
+  for (i = tx->w_set.nb_entries; i > 0; i--, w++) {
+    if (w->addr == addr) {
+      return w;
+    }
+  }
+  return NULL;
+}
+#endif /* DESIGN == WRITE_BACK_CTL */
+
+/*
+ * (Re)allocate read set entries.
+ */
+static inline void stm_allocate_rs_entries(stm_tx_t *tx, int extend)
+{
+  PRINT_DEBUG("==> stm_allocate_rs_entries(%p[%lu-%lu],%d) r_set.size %d\n",
+		  tx, (unsigned long)tx->start, (unsigned long)tx->end, extend, tx->r_set.size);
+
+  if (extend) {
+	r_entry_t * entries;
+    /* Extend read set */
+    if ((entries = (r_entry_t *)vmalloc( tx->r_set.size * 2 * sizeof(r_entry_t))) == NULL) {
+      PERROR("%s: realloc read set\n", __func__);
+      BUG();
+//      exit(1); // TODO
+    }
+    // realloc duties
+    memcpy(entries, tx->r_set.entries, tx->r_set.size * sizeof(r_entry_t));
+    vfree(tx->r_set.entries);
+    tx->r_set.entries = entries;
+    tx->r_set.size *= 2;
+  } else {
+    /* Allocate read set */
+    if ((tx->r_set.entries = (r_entry_t *)vmalloc(tx->r_set.size * sizeof(r_entry_t))) == NULL) {
+      PERROR("%s: malloc read set\n", __func__);
+      BUG();
+//      exit(1); // TODO
+    }
+    memset(tx->r_set.entries, 0, (tx->r_set.size * sizeof(r_entry_t)));
+  }
+}
+
+/*
+ * (Re)allocate write set entries.
+ */
+static inline void stm_allocate_ws_entries(stm_tx_t *tx, int extend)
+{
+#if CM == CM_MODULAR || (defined(CONFLICT_TRACKING) && DESIGN != WRITE_THROUGH)
+  int i, first = (extend ? tx->w_set.size : 0);
+#endif /* CM == CM_MODULAR || (defined(CONFLICT_TRACKING) && DESIGN != WRITE_THROUGH) */
+
+  PRINT_DEBUG("==> stm_allocate_ws_entries(%p[%lu-%lu],%d) w_set.size %d\n",
+		  tx, (unsigned long)tx->start, (unsigned long)tx->end, extend, tx->r_set.size);
+
+  if (extend) {
+    /* Extend write set */
+#if DESIGN == WRITE_BACK_ETL
+    int j;
+    w_entry_t *ows, *nws;
+    /* Allocate new write set */
+    ows = tx->w_set.entries;
+    if ((nws = (w_entry_t *)vmalloc(tx->w_set.size * 2 * sizeof(w_entry_t))) == NULL) {
+      PERROR("malloc write set");
+      BUG();
+  //    exit(1);
+    }
+    /* Copy write set */
+    memcpy(nws, ows, tx->w_set.size * sizeof(w_entry_t));
+    /* Update pointers */
+    for (j = 0; j < tx->w_set.nb_entries; j++) {
+      if (ows[j].next != NULL)
+        nws[j].next = nws + (ows[j].next - ows);
+    }
+    /* Update locks */
+    for (j = 0; j < tx->w_set.nb_entries; j++) {
+      if (ows[j].lock == GET_LOCK(ows[j].addr)) 
+        ATOMIC_STORE_REL(ows[j].lock, LOCK_SET_ADDR_WRITE((stm_word_t)&nws[j]));
+    }
+    tx->w_set.entries = nws;
+    tx->w_set.size *= 2;
+# ifdef EPOCH_GC
+    gc_free(ows, tx->start);
+# else /* ! EPOCH_GC */
+    vfree(ows);
+# endif /* ! EPOCH_GC */
+#else /* DESIGN != WRITE_BACK_ETL */
+    w_entry_t * entries
+    if ((entries = (w_entry_t *)vmalloc(tx->w_set.size * 2 * sizeof(w_entry_t))) == NULL) {
+      PERROR("realloc write set");
+      exit(1);
+    }
+    // realloc duties
+    memcpy(entries, tx->w_set.entries, tx->w_set.size * sizeof(w_entry_t));
+    vfree(tx->w_set.entries);
+    tx->w_set.entries = entries;
+    tx->w_set.size *= 2;
+#endif /* DESIGN != WRITE_BACK_ETL */
+  } else {
+    /* Allocate write set */
+    if ((tx->w_set.entries = (w_entry_t *)vmalloc(tx->w_set.size * sizeof(w_entry_t))) == NULL) {
+      PERROR("malloc write set");
+      BUG();
+//      exit(1);
+    }
+    memset(tx->w_set.entries, 0, (tx->w_set.size * sizeof(w_entry_t)));
+  }
+
+#if CM == CM_MODULAR || (defined(CONFLICT_TRACKING) && DESIGN != WRITE_THROUGH)
+  /* Initialize fields */
+  for (i = first; i < tx->w_set.size; i++)
+    tx->w_set.entries[i].tx = tx;
+#endif /* CM == CM_MODULAR || (defined(CONFLICT_TRACKING) && DESIGN != WRITE_THROUGH) */
+}
+
+/*
+ * Validate read set (check if all read addresses are still valid now).
+ */
+static inline int stm_validate(stm_tx_t *tx)
+{
+  r_entry_t *r;
+  int i;
+  stm_word_t l;
+
+  PRINT_DEBUG("==> stm_validate(%p[%lu-%lu])\n", tx, (unsigned long)tx->start, (unsigned long)tx->end);
+
+  /* Validate reads */
+  r = tx->r_set.entries;
+  for (i = tx->r_set.nb_entries; i > 0; i--, r++) {
+    /* Read lock */
+    l = ATOMIC_LOAD(r->lock);
+    /* Unlocked and still the same version? */
+    if (LOCK_GET_OWNED(l)) {
+      /* Do we own the lock? */
+#if DESIGN == WRITE_THROUGH
+      if ((stm_tx_t *)LOCK_GET_ADDR(l) != tx)
+#else /* DESIGN != WRITE_THROUGH */
+      w_entry_t *w = (w_entry_t *)LOCK_GET_ADDR(l);
+      /* Simply check if address falls inside our write set (avoids non-faulting load) */
+      if (!(tx->w_set.entries <= w && w < tx->w_set.entries + tx->w_set.nb_entries))
+#endif /* DESIGN != WRITE_THROUGH */
+      {
+        /* Locked by another transaction: cannot validate */
+#ifdef CONFLICT_TRACKING
+        if (conflict_cb != NULL && l != LOCK_UNIT) {
+          /* Call conflict callback */
+# if DESIGN == WRITE_THROUGH
+          stm_tx_t *other = (stm_tx_t *)LOCK_GET_ADDR(l);
+# else /* DESIGN != WRITE_THROUGH */
+          stm_tx_t *other = ((w_entry_t *)LOCK_GET_ADDR(l))->tx;
+# endif /* DESIGN != WRITE_THROUGH */
+          conflict_cb(tx, other);
+        }
+#endif /* CONFLICT_TRACKING */
+        return 0;
+      }
+      /* We own the lock: OK */
+#if DESIGN == WRITE_BACK_CTL
+      if (w->version != r->version) {
+        /* Other version: cannot validate */
+        return 0;
+      }
+#endif /* DESIGN == WRITE_BACK_CTL */
+    } else {
+      if (LOCK_GET_TIMESTAMP(l) != r->version) {
+        /* Other version: cannot validate */
+        return 0;
+      }
+      /* Same version: OK */
+    }
+  }
+  return 1;
+}
+
+/*
+ * Extend snapshot range.
+ */
+static inline int stm_extend(stm_tx_t *tx)
+{
+  stm_word_t now;
+
+  PRINT_DEBUG("==> stm_extend(%p[%lu-%lu])\n", tx, (unsigned long)tx->start, (unsigned long)tx->end);
+
+  /* Get current time */
+  now = GET_CLOCK;
+  if (now >= VERSION_MAX) {
+    /* Clock overflow */
+    return 0;
+  }
+  /* Try to validate read set */
+  if (stm_validate(tx)) {
+    /* It works: we can extend until now */
+    tx->end = now;
+    return 1;
+  }
+  return 0;
+}
+
+#if CM == CM_MODULAR
+/*
+ * Kill other transaction.
+ */
+static inline int stm_kill(stm_tx_t *tx, stm_tx_t *other, stm_word_t status)
+{
+  stm_word_t c, t;
+
+  PRINT_DEBUG("==> stm_kill(%p[%lu-%lu],%p,s=%d)\n", tx, (unsigned long)tx->start, (unsigned long)tx->end, other, status);
+
+# ifdef CONFLICT_TRACKING
+  if (conflict_cb != NULL)
+    conflict_cb(tx, other);
+# endif /* CONFLICT_TRACKING */
+
+# ifdef IRREVOCABLE_ENABLED
+  if (GET_STATUS(status) == TX_IRREVOCABLE)
+    return 0;
+# endif /* IRREVOCABLE_ENABLED */
+  if (GET_STATUS(status) == TX_ABORTED || GET_STATUS(status) == TX_COMMITTED || GET_STATUS(status) == TX_KILLED)
+    return 0;
+  if (GET_STATUS(status) == TX_ABORTING || GET_STATUS(status) == TX_COMMITTING) {
+    /* Transaction is already aborting or committing: wait */
+    while (other->status == status)
+      ;
+    return 0;
+  }
+  assert(IS_ACTIVE(status));
+  /* Set status to KILLED */
+  //if (ATOMIC_CAS_FULL(&other->status, status, status + (TX_KILLED - TX_ACTIVE)) == 0) {
+  if (ATOMIC_CAS_FULL(&other->status, status, status + (TX_KILLED - TX_ACTIVE)) != status) {
+    /* Transaction is committing/aborting (or has committed/aborted) */
+    c = GET_STATUS_COUNTER(status);
+    do {
+      t = other->status;
+# ifdef IRREVOCABLE_ENABLED
+      if (GET_STATUS(t) == TX_IRREVOCABLE)
+        return 0;
+# endif /* IRREVOCABLE_ENABLED */
+    } while (GET_STATUS(t) != TX_ABORTED && GET_STATUS(t) != TX_COMMITTED && GET_STATUS(t) != TX_KILLED && GET_STATUS_COUNTER(t) == c);
+    return 0;
+  }
+  /* We have killed the transaction: we can steal the lock */
+  return 1;
+}
+
+/*
+ * Drop locks after having been killed.
+ */
+static inline void stm_drop(stm_tx_t *tx)
+{
+  w_entry_t *w;
+  stm_word_t l;
+  int i;
+
+  PRINT_DEBUG("==> stm_drop(%p[%lu-%lu])\n", tx, (unsigned long)tx->start, (unsigned long)tx->end);
+
+  /* Drop locks */
+  i = tx->w_set.nb_entries;
+  if (i > 0) {
+    w = tx->w_set.entries;
+    for (; i > 0; i--, w++) {
+      l = ATOMIC_LOAD_ACQ(w->lock);
+      if (LOCK_GET_OWNED(l) && (w_entry_t *)LOCK_GET_ADDR(l) == w) {
+        /* Drop using CAS */
+        ATOMIC_CAS_FULL(w->lock, l, LOCK_SET_TIMESTAMP(w->version));
+        /* If CAS fail, lock has been stolen or already released in case a lock covers multiple addresses */
+      }
+    }
+    /* We need to reallocate the write set to avoid an ABA problem (the
+     * transaction could reuse the same entry after having been killed
+     * and restarted, and another slow transaction could steal the lock
+     * using CAS without noticing the restart) */
+    gc_free(tx->w_set.entries, tx->start);
+    stm_allocate_ws_entries(tx, 0);
+  }
+}
+#endif /* CM == CM_MODULAR */
+
+/*
+ * Initialize the transaction descriptor before start or restart.
+ */
+// functions called in stm_prepare:
+// stm_quiesce_barrier, stm_set_irrevocable, stm_check_quiesce
+static inline void stm_prepare(stm_tx_t *tx)
+{
+#if CM == CM_MODULAR
+  if (tx->visible_reads >= vr_threshold && vr_threshold >= 0) {
+    /* Use visible read */
+    if (tx->attr != NULL && tx->attr->read_only) {
+      /* Update attributes to inform the caller */
+      tx->attr->read_only = 0;
+    }
+    tx->ro = 0;
+  }
+#endif /* CM == CM_MODULAR */
+ start:
+  /* Start timestamp */
+  tx->start = tx->end = GET_CLOCK; /* OPT: Could be delayed until first read/write */
+
+  /* Allow extensions */
+  tx->can_extend = 1;
+  if (tx->start >= VERSION_MAX) {
+    /* Block all transactions and reset clock */
+    stm_quiesce_barrier(tx, rollover_clock, NULL);
+    goto start;
+  }
+#if CM == CM_MODULAR
+  if (tx->retries == 0)
+    tx->timestamp = tx->start;
+#endif /* CM == CM_MODULAR */
+  /* Read/write set */
+#if DESIGN == WRITE_BACK_ETL
+  tx->w_set.has_writes = 0;
+#elif DESIGN == WRITE_BACK_CTL
+  tx->w_set.nb_acquired = 0;
+# ifdef USE_BLOOM_FILTER
+  tx->w_set.bloom = 0;
+# endif /* USE_BLOOM_FILTER */
+#endif /* DESIGN == WRITE_BACK_CTL */
+  tx->w_set.nb_entries = 0;
+  tx->r_set.nb_entries = 0;
+
+#ifdef STM_PREEMPT_BONUS
+  tx->bonus = 0;
+#endif /* STM_PREEMPT_AVOIDANCE */
+
+#ifdef EPOCH_GC
+  gc_set_epoch(tx->start);
+#endif /* EPOCH_GC */
+
+#ifdef IRREVOCABLE_ENABLED
+  if (tx->irrevocable != 0) {
+    assert(!IS_ACTIVE(tx->status));
+    stm_set_irrevocable(TXARGS -1);
+    UPDATE_STATUS(tx->status, TX_IRREVOCABLE);
+  } else
+    UPDATE_STATUS(tx->status, TX_ACTIVE);
+#else /* ! IRREVOCABLE_ENABLED */
+  /* Set status */
+  UPDATE_STATUS(tx->status, TX_ACTIVE);
+#endif /* ! IRREVOCABLE_ENABLED */
+
+  stm_check_quiesce(tx);
+}
+
+// this is experimental, a trace_printk can be used instead
+void trace_stm_rollback(unsigned long, int, int);
+
+/*
+ * Rollback transaction.
+ */
+//tx is the current transaction descriptor on which the thread is in!
+//rollback means ABORT the current transaction and restructure everything as was before
+//WAS static inline void
+static int stm_rollback(stm_tx_t *tx, int reason)
+{
+  w_entry_t *w;
+#if DESIGN != WRITE_BACK_CTL
+  int i;
+#endif /* DESIGN != WRITE_BACK_CTL */
+#if DESIGN == WRITE_THROUGH || CM == CM_MODULAR
+  stm_word_t t;
+#endif /* DESIGN == WRITE_THROUGH || CM == CM_MODULAR */
+#if CM == CM_BACKOFF
+  unsigned long wait;
+  volatile int j;
+#endif /* CM == CM_BACKOFF */
+
+  PRINT_DEBUG("==> stm_rollback(%p[%lu-%lu]) reason %d\n",
+		  tx, (unsigned long)tx->start, (unsigned long)tx->end, reason);
+
+  assert(IS_ACTIVE(tx->status));
+#if CM == CM_MODULAR
+  /* Set status to ABORTING */
+  t = tx->status;
+  if (GET_STATUS(t) == TX_KILLED || (GET_STATUS(t) == TX_ACTIVE
+		  && ATOMIC_CAS_FULL(&tx->status, t, t + (TX_ABORTING - TX_ACTIVE)) != t)) {
+	  //&& ATOMIC_CAS_FULL(&tx->status, t, t + (TX_ABORTING - TX_ACTIVE)) == 0)) {/
+    /* We have been killed */
+    assert(GET_STATUS(tx->status) == TX_KILLED);
+# ifdef INTERNAL_STATS
+    tx->aborts_killed++;
+# endif /* INTERNAL_STATS */
+    /* Release locks */
+    stm_drop(tx);
+    goto dropped;
+  }
+#endif /* CM == CM_MODULAR */
+
+#if DESIGN == WRITE_THROUGH
+  t = 0;
+  /* Undo writes and drop locks (traverse in reverse order) */
+  w = tx->w_set.entries + tx->w_set.nb_entries;
+  while (w != tx->w_set.entries) {
+    w--;
+    if (w->mask != 0)
+      ATOMIC_STORE(w->addr, w->value);
+    if (w->no_drop)
+      continue;
+    /* Incarnation numbers allow readers to detect dirty reads */
+    i = LOCK_GET_INCARNATION(w->version) + 1;
+    if (i > INCARNATION_MAX) {
+      /* Simple approach: write new version (might trigger unnecessary aborts) */
+      if (t == 0) {
+        /* Get new version (may exceed VERSION_MAX by up to MAX_THREADS) */
+        t = FETCH_INC_CLOCK;
+      }
+      ATOMIC_STORE_REL(w->lock, LOCK_SET_TIMESTAMP(t));
+    } else {
+      /* Use new incarnation number */
+      ATOMIC_STORE_REL(w->lock, LOCK_UPD_INCARNATION(w->version, i));
+    }
+  }
+#elif DESIGN == WRITE_BACK_ETL
+  /* Drop locks */
+  i = tx->w_set.nb_entries;
+  if (i > 0) {
+    w = tx->w_set.entries;
+    for (; i > 0; i--, w++) {
+      if (w->next == NULL) {
+        /* Only drop lock for last covered address in write set */
+#  if CM == CM_DELAY && defined(WAIT_COND)
+    	  mutex_lock(&(locks_mutex[LOCK_IDX(w->addr)]));
+    	  	  *(w->lock) = LOCK_SET_TIMESTAMP(w->version);
+    	  	  cond_broadcast(&(locks_cond[LOCK_IDX(w->addr)]));
+    	  mutex_unlock(&(locks_mutex[LOCK_IDX(w->addr)]));
+#  else /* CM != CM_DELAY && defined(WAIT_COND) */
+        ATOMIC_STORE(w->lock, LOCK_SET_TIMESTAMP(w->version));
+#  endif /* CM != CM_DELAY && defined(WAIT_COND) */
+      }
+    }
+    /* Make sure that all lock releases become visible */
+    ATOMIC_MB_WRITE;
+  }
+#else /* DESIGN == WRITE_BACK_CTL */
+  if (tx->w_set.nb_acquired > 0) {
+    w = tx->w_set.entries + tx->w_set.nb_entries;
+    do {
+      w--;
+      if (!w->no_drop) {
+        if (--tx->w_set.nb_acquired == 0) {
+          /* Make sure that all lock releases become visible to other threads */
+          ATOMIC_STORE_REL(w->lock, LOCK_SET_TIMESTAMP(w->version));
+        } else {
+          ATOMIC_STORE(w->lock, LOCK_SET_TIMESTAMP(w->version));
+        }
+      }
+    } while (tx->w_set.nb_acquired > 0);
+  }
+#endif /* DESIGN == WRITE_BACK_CTL */
+
+#if CM == CM_MODULAR
+ dropped:
+#endif /* CM == CM_MODULAR */
+
+#if CM == CM_MODULAR || defined(INTERNAL_STATS)
+  tx->retries++;
+#endif /* CM == CM_MODULAR || defined(INTERNAL_STATS) */
+#ifdef INTERNAL_STATS
+  tx->aborts++;
+  if (tx->retries == 1)
+    tx->aborts_1++;
+  else if (tx->retries == 2)
+    tx->aborts_2++;
+  if (tx->max_retries < tx->retries)
+    tx->max_retries = tx->retries;
+#endif /* INTERNAL_STATS */
+
+  /* Callbacks */
+/*  if (nb_abort_cb != 0) {
+    int cb;
+    for (cb = 0; cb < nb_abort_cb; cb++)
+      abort_cb[cb].f(TXARGS abort_cb[cb].arg);
+  }
+*/
+  mod_stats_on_abort();
+
+  /* Set status to ABORTED */
+  SET_STATUS(tx->status, TX_ABORTED);
+
+  /* Reset nesting level */
+  tx->nesting = 1; // why not resetted to 0?!?!
+
+#if CM == CM_BACKOFF
+  /* Simple RNG (good enough for backoff) */
+  tx->seed ^= (tx->seed << 17);
+  tx->seed ^= (tx->seed >> 13);
+  tx->seed ^= (tx->seed << 5);
+  wait = tx->seed % tx->backoff;
+  for (j = 0; j < wait; j++) {
+    /* Do nothing */
+  }
+  if (tx->backoff < MAX_BACKOFF)
+    tx->backoff <<= 1;
+#endif /* CM == CM_BACKOFF */
+
+#if CM == CM_DELAY || CM == CM_MODULAR
+  /* Wait until contented lock is free */
+  if (tx->c_lock != NULL) {
+# ifdef WAIT_COND
+	  int lidx = (tx->c_lock - locks);
+	  mutex_lock(&locks_mutex[lidx]);
+	  while (LOCK_GET_OWNED(ATOMIC_LOAD(tx->c_lock)))
+		  cond_wait (&locks_cond[lidx], &locks_mutex[lidx]);
+	  mutex_unlock(&locks_mutex[lidx]);
+# else /* WAIT_COND */
+#if defined (STM_PREEMPT_BONUS) && !defined(WAIT_YIELD)
+  /* if the current transaction receives at least one bonus time slice call schedule */
+  if (tx->bonus)
+	  yield();
+#endif /* !STM_PREEMPTION_AVOIDANCE */
+    /* Busy waiting (yielding is expensive) */
+    while (LOCK_GET_OWNED(ATOMIC_LOAD(tx->c_lock))) {
+#  ifdef WAIT_YIELD
+      yield();
+#  endif /* WAIT_YIELD */
+    }
+# endif /* WAIT_COND */
+    tx->c_lock = NULL;
+  }
+#endif /* CM == CM_DELAY || CM == CM_MODULAR */
+
+  /* Reset field to restart transaction */
+  stm_prepare(tx); //set the status to ACTIVE
+
+  trace_stm_rollback(tx, reason, !tx->attr.no_retry);
+  /* Jump back to transaction start */
+//  if (tx->attr == NULL || !tx->attr->no_retry)
+  if (!tx->attr.no_retry)
+	 //siglongjmp(tx->env, reason);
+	  return ROLLBACK_REQUESTED;
+  else
+      return ROLLBACK_NO_RETRY;
+
+}
+
+/*
+ * Load a word-sized value (invisible read).
+ */
+//WAS static inline stm_word_t stm_read_invisible(stm_tx_t *tx, volatile stm_word_t *addr)
+static int stm_read_invisible(stm_tx_t *tx, volatile stm_word_t *addr, stm_word_t *ptrvalue)
+{
+  volatile stm_word_t *lock;
+  stm_word_t l, l2, value, version;
+  r_entry_t *r;
+#if DESIGN == WRITE_BACK_ETL
+  w_entry_t *w;
+#endif /* DESIGN == WRITE_BACK_ETL */
+#if DESIGN == WRITE_BACK_CTL
+  w_entry_t *written = NULL;
+#endif /* DESIGN == WRITE_BACK_CTL */
+#if CM == CM_MODULAR
+  stm_word_t t;
+  int decision;
+#endif /* CM == CM_MODULAR */
+
+  PRINT_DEBUG2("==> stm_read_invisible(t=%p[%lu-%lu],a=%p)\n", tx, (unsigned long)tx->start, (unsigned long)tx->end, addr);
+
+#if CM != CM_MODULAR
+  assert(IS_ACTIVE(tx->status));
+#endif /* CM != CM_MODULAR */
+
+#if DESIGN == WRITE_BACK_CTL
+  /* Did we previously write the same address? */
+  written = stm_has_written(tx, addr);
+  if (written != NULL) {
+    /* Yes: get value from write set if possible */
+    if (written->mask == ~(stm_word_t)0) {
+      value = written->value;
+      /* No need to add to read set */
+      // return value;
+      *ptrvalue = value;
+      return SUCCESS;
+    }
+  }
+#endif /* DESIGN == WRITE_BACK_CTL */
+
+  /* Get reference to lock */
+  lock = GET_LOCK(addr);
+
+  /* Note: we could check for duplicate reads and get value from read set */
+
+  /* Read lock, value, lock */
+ restart:
+#if CM == CM_DELAY && defined(WAIT_COND)
+  mutex_lock(&(locks_mutex[LOCK_IDX(addr)]));
+ 	  l = *lock;
+  mutex_unlock(&(locks_mutex[LOCK_IDX(addr)]));
+#else /* CM != CM_DELAY && defined(WAIT_COND) */
+  l = ATOMIC_LOAD_ACQ(lock);
+#endif /* CM != CM_DELAY && defined(WAIT_COND) */
+ restart_no_load:
+  if (LOCK_GET_WRITE(l)) {
+    /* Locked */
+    if (l == LOCK_UNIT) {
+      /* Data modified by a unit store: should not last long => retry */
+      goto restart;
+    }
+    /* Do we own the lock? */
+#if DESIGN == WRITE_THROUGH
+    if (tx == (stm_tx_t *)LOCK_GET_ADDR(l)) {
+      /* Yes: we have a version locked by us that was valid at write time */
+      value = ATOMIC_LOAD(addr);
+      /* No need to add to read set (will remain valid) */
+      //return value;
+      *ptrvalue = value;
+      return SUCCESS;
+    }
+#elif DESIGN == WRITE_BACK_ETL
+    w = (w_entry_t *)LOCK_GET_ADDR(l);
+    /* Simply check if address falls inside our write set (avoids non-faulting load) */
+    if (tx->w_set.entries <= w && w < tx->w_set.entries + tx->w_set.nb_entries) {
+      /* Yes: did we previously write the same address? */
+      while (1) {
+        if (addr == w->addr) {
+          /* Yes: get value from write set (or from memory if mask was empty) */
+          if (w->mask == 0) {
+              /* CHECK USER SPACE ADDRESS ACCESS */
+              if (!access_ok(VERIFY_READ, addr, sizeof(value)))
+            	  printk("%s: 1 access_ok addr %p size %d error [%d]\n",__func__, addr, sizeof(value), current->pid);
+              value = ATOMIC_LOAD(addr);
+          } else
+        	  value = w->value;
+          break;
+        }
+        if (w->next == NULL) {
+          /* No: get value from memory */
+          /* CHECK USER SPACE ADDRESS ACCESS */
+          if (!access_ok(VERIFY_READ, addr, sizeof(value)))
+        	  printk("%s: 2 access_ok addr %p size %d error [%d]\n",__func__, addr, sizeof(value), current->pid);
+          value = ATOMIC_LOAD(addr);
+# if CM == CM_MODULAR
+          if (GET_STATUS(tx->status) == TX_KILLED) {
+            *ptrvalue = 0;
+            return stm_rollback(tx, STM_ABORT_KILLED);
+          }
+# endif
+          break;
+        }
+        w = w->next;
+      }
+      /* No need to add to read set (will remain valid) */
+      //return value;
+      *ptrvalue = value;
+      return SUCCESS;
+    }
+#endif /* DESIGN == WRITE_BACK_ETL */
+#if DESIGN == WRITE_BACK_CTL
+    /* Spin while locked (should not last long) */
+    goto restart;
+#else /* DESIGN != WRITE_BACK_CTL */
+    /* Conflict: CM kicks in (we could also check for duplicate reads and get value from read set) */
+# if CM != CM_MODULAR && defined(IRREVOCABLE_ENABLED)
+    if(tx->irrevocable) {
+      /* Spin while locked */
+      goto restart;
+    }
+# endif /* CM != CM_MODULAR && defined(IRREVOCABLE_ENABLED) */
+# if CM == CM_MODULAR
+    t = w->tx->status;
+    l2 = ATOMIC_LOAD_ACQ(lock);
+    if (l != l2) {
+      l = l2;
+      goto restart_no_load;
+    }
+    if (t != w->tx->status) {
+      /* Transaction status has changed: restart the whole procedure */
+      goto restart;
+    }
+#  ifdef READ_LOCKED_DATA
+#   ifdef IRREVOCABLE_ENABLED
+    if (IS_ACTIVE(t) && !tx->irrevocable)
+#   else /* ! IRREVOCABLE_ENABLED */
+    if (GET_STATUS(t) == TX_ACTIVE)
+#   endif /* ! IRREVOCABLE_ENABLED */
+    {
+      /* Read old version */
+      version = ATOMIC_LOAD(&w->version);
+      /* Read data */
+      value = ATOMIC_LOAD(addr);
+      /* Check that data has not been written */
+      if (t != w->tx->status) {
+        /* Data concurrently modified: a new version might be available => retry */
+        goto restart;
+      }
+      if (version >= tx->start && (version <= tx->end || (!tx->ro && tx->can_extend && stm_extend(tx)))) {
+      /* Success */
+#  ifdef INTERNAL_STATS
+        tx->locked_reads_ok++;
+#  endif /* INTERNAL_STATS */
+        goto add_to_read_set;
+      }
+      /* Invalid version: not much we can do => fail */
+#  ifdef INTERNAL_STATS
+      tx->locked_reads_failed++;
+#  endif /* INTERNAL_STATS */
+    }
+#  endif /* READ_LOCKED_DATA */
+    if (GET_STATUS(t) == TX_KILLED) {
+      /* We can safely steal lock */
+      decision = KILL_OTHER;
+    } else {
+      decision =
+#  ifdef IRREVOCABLE_ENABLED
+        GET_STATUS(tx->status) == TX_IRREVOCABLE ? KILL_OTHER :
+        GET_STATUS(t) == TX_IRREVOCABLE ? KILL_SELF :
+#  endif /* IRREVOCABLE_ENABLED */
+        GET_STATUS(tx->status) == TX_KILLED ? KILL_SELF :
+        (contention_manager != NULL ? contention_manager(tx, w->tx, WR_CONFLICT) : KILL_SELF);
+      if (decision == KILL_OTHER) {
+        /* Kill other */
+        if (!stm_kill(tx, w->tx, t)) {
+          /* Transaction may have committed or aborted: retry */
+          goto restart;
+        }
+      }
+    }
+    if (decision == KILL_OTHER) {
+      /* Steal lock */
+      l2 = LOCK_SET_TIMESTAMP(w->version);
+      //if (ATOMIC_CAS_FULL(lock, l, l2) == 0)
+      if (ATOMIC_CAS_FULL(lock, l, l2) != l)
+        goto restart;
+      l = l2;
+      goto restart_no_load;
+    }
+    /* Kill self */
+    if ((decision & DELAY_RESTART) != 0)
+      tx->c_lock = lock;
+# elif CM == CM_DELAY
+    tx->c_lock = lock;
+# endif /* CM == CM_DELAY */
+    /* Abort */
+# ifdef INTERNAL_STATS
+    tx->aborts_locked_read++;
+# endif /* INTERNAL_STATS */
+# ifdef CONFLICT_TRACKING
+    if (conflict_cb != NULL && l != LOCK_UNIT) {
+      /* Call conflict callback */
+#  if DESIGN == WRITE_THROUGH
+      stm_tx_t *other = (stm_tx_t *)LOCK_GET_ADDR(l);
+#  else /* DESIGN != WRITE_THROUGH */
+      stm_tx_t *other = ((w_entry_t *)LOCK_GET_ADDR(l))->tx;
+#  endif /* DESIGN != WRITE_THROUGH */
+      conflict_cb(tx, other);
+    }
+# endif /* CONFLICT_TRACKING */
+    *ptrvalue = 0;
+    return stm_rollback(tx, STM_ABORT_RW_CONFLICT);
+    //return 0;
+#endif /* DESIGN != WRITE_BACK_CTL */
+  } else {
+    /* Not locked */
+    value = ATOMIC_LOAD_ACQ(addr);
+#if CM == CM_DELAY && defined(WAIT_COND)
+    mutex_lock(&(locks_mutex[LOCK_IDX(addr)]));
+   	  l2 = *lock;
+    mutex_unlock(&(locks_mutex[LOCK_IDX(addr)]));
+#else /* CM != CM_DELAY && defined(WAIT_COND) */
+    l2 = ATOMIC_LOAD_ACQ(lock);
+#endif /*  CM != CM_DELAY && defined(WAIT_COND) */
+    if (l != l2) {
+      l = l2;
+      goto restart_no_load;
+    }
+#ifdef IRREVOCABLE_ENABLED
+    /* In irrevocable mode, no need check timestamp nor add entry to read set */
+    if (tx->irrevocable)
+      return value;
+#endif /* IRREVOCABLE_ENABLED */
+    /* Check timestamp */
+#if CM == CM_MODULAR
+    if (LOCK_GET_READ(l))
+      version = ((w_entry_t *)LOCK_GET_ADDR(l))->version;
+    else
+      version = LOCK_GET_TIMESTAMP(l);
+#else /* CM != CM_MODULAR */
+    version = LOCK_GET_TIMESTAMP(l);
+#endif /* CM != CM_MODULAR */
+    PRINT_DEBUG3("version %d > tx->end %d tx->no_retry %d tx->ro %d tx->can_extend %d addr %p l %p lock %p\n",
+    		version, tx->end, tx->attr.no_retry, tx->ro, tx->can_extend, addr, l, lock);
+    /* Valid version? */
+    if (version > tx->end) {
+#ifdef IRREVOCABLE_ENABLED
+      assert(!tx->irrevocable);
+#endif /* IRREVOCABLE_ENABLED */
+      /* No: try to extend first (except for read-only transactions: no read set) */
+      if (tx->ro || !tx->can_extend || !stm_extend(tx)) {
+        /* Not much we can do: abort */
+#if CM == CM_MODULAR
+        /* Abort caused by invisible reads */
+        tx->visible_reads++;
+#endif /* CM == CM_MODULAR */
+#ifdef INTERNAL_STATS
+        tx->aborts_validate_read++;
+#endif /* INTERNAL_STATS */
+        *ptrvalue = value;
+        return stm_rollback(tx, STM_ABORT_VAL_READ);
+        //return 0;
+      }
+      /* Verify that version has not been overwritten (read value has not
+       * yet been added to read set and may have not been checked during
+       * extend) */
+#if CM == CM_DELAY && defined(WAIT_COND)
+      mutex_lock(&(locks_mutex[LOCK_IDX(addr)]));
+      	  l = *lock;
+      mutex_unlock(&(locks_mutex[LOCK_IDX(addr)]));
+#else /* CM == CM_DELAY && defined(WAIT_COND) */
+      l = ATOMIC_LOAD_ACQ(lock);
+#endif /* CM == CM_DELAY && defined(WAIT_COND) */
+      if (l != l2) {
+        l = l2;
+        goto restart_no_load;
+      }
+      /* Worked: we now have a good version (version <= tx->end) */
+    }
+#if CM == CM_MODULAR
+    /* Check if killed (necessary to avoid possible race on read-after-write) */
+    if (GET_STATUS(tx->status) == TX_KILLED) {
+      *ptrvalue = value;
+      return stm_rollback(tx, STM_ABORT_KILLED);
+      //return 0;
+    }
+#endif /* CM == CM_MODULAR */
+  }
+  /* We have a good version: add to read set (update transactions) and return value */
+
+#if DESIGN == WRITE_BACK_CTL
+  /* Did we previously write the same address? */
+  if (written != NULL) {
+    value = (value & ~written->mask) | (written->value & written->mask);
+    /* Must still add to read set */
+  }
+#endif /* DESIGN == WRITE_BACK_CTL */
+#ifdef READ_LOCKED_DATA
+ add_to_read_set:
+#endif /* READ_LOCKED_DATA */
+  if (!tx->ro) {
+#ifdef NO_DUPLICATES_IN_RW_SETS
+    if (stm_has_read(tx, lock) != NULL)
+      //return value;
+      *ptrvalue = value;
+      return SUCCESS;
+#endif /* NO_DUPLICATES_IN_RW_SETS */
+    /* Add address and version to read set */
+    if (tx->r_set.nb_entries == tx->r_set.size)
+      stm_allocate_rs_entries(tx, 1);
+    r = &tx->r_set.entries[tx->r_set.nb_entries++];
+    r->version = version;
+    r->lock = lock;
+  }
+  //return value;
+  *ptrvalue = value;
+  return SUCCESS;
+}
+
+#if CM == CM_MODULAR
+/*
+ * Load a word-sized value (visible read).
+ */
+// WAS static inline stm_word_t stm_read_visible(stm_tx_t *tx, volatile stm_word_t *addr)
+static int stm_read_visible(stm_tx_t *tx, volatile stm_word_t *addr, stm_word_t *ptrvalue)
+{
+  volatile stm_word_t *lock;
+  stm_word_t l, l2, t, value, version;
+  w_entry_t *w;
+  int decision;
+
+  PRINT_DEBUG2("==> stm_read_visible(t=%p[%lu-%lu],a=%p)\n", tx, (unsigned long)tx->start, (unsigned long)tx->end, addr);
+
+  if (GET_STATUS(tx->status) == TX_KILLED) {
+	*ptrvalue = value;
+    return stm_rollback(tx, STM_ABORT_KILLED);
+    //return 0;
+  }
+
+  /* Get reference to lock */
+  lock = GET_LOCK(addr);
+
+  /* Try to acquire lock */
+ restart:
+  l = ATOMIC_LOAD_ACQ(lock);
+ restart_no_load:
+  if (LOCK_GET_OWNED(l)) {
+    /* Locked */
+    if (l == LOCK_UNIT) {
+      /* Data modified by a unit store: should not last long => retry */
+      goto restart;
+    }
+    /* Do we own the lock? */
+    w = (w_entry_t *)LOCK_GET_ADDR(l);
+    /* Simply check if address falls inside our write set (avoids non-faulting load) */
+    if (tx->w_set.entries <= w && w < tx->w_set.entries + tx->w_set.nb_entries) {
+      /* Yes: is it only read-locked? */
+      if (!LOCK_GET_WRITE(l)) {
+        /* Yes: get value from memory */
+        value = ATOMIC_LOAD(addr);
+      } else {
+        /* No: did we previously write the same address? */
+        while (1) {
+          if (addr == w->addr) {
+            /* Yes: get value from write set (or from memory if mask was empty) */
+            value = (w->mask == 0 ? ATOMIC_LOAD(addr) : w->value);
+            break;
+          }
+          if (w->next == NULL) {
+            /* No: get value from memory */
+            value = ATOMIC_LOAD(addr);
+            break;
+          }
+          w = w->next;
+        }
+      }
+# if CM == CM_MODULAR
+      if (GET_STATUS(tx->status) == TX_KILLED) {
+    	*ptrvalue = 0;
+        return stm_rollback(tx, STM_ABORT_KILLED);
+        //return 0;
+      }
+# endif
+      /* No need to add to read set (will remain valid) */
+      //return value;
+      *ptrvalue = value;
+      return SUCCESS;
+    }
+    /* Conflict: CM kicks in */
+    t = w->tx->status;
+    l2 = ATOMIC_LOAD_ACQ(lock);
+    if (l != l2) {
+      l = l2;
+      goto restart_no_load;
+    }
+    if (t != w->tx->status) {
+      /* Transaction status has changed: restart the whole procedure */
+      goto restart;
+    }
+    if (GET_STATUS(t) == TX_KILLED) {
+      /* We can safely steal lock */
+      decision = KILL_OTHER;
+    } else {
+      decision =
+# ifdef IRREVOCABLE_ENABLED
+        GET_STATUS(tx->status) == TX_IRREVOCABLE ? KILL_OTHER :
+        GET_STATUS(t) == TX_IRREVOCABLE ? KILL_SELF :
+# endif /* IRREVOCABLE_ENABLED */
+        GET_STATUS(tx->status) == TX_KILLED ? KILL_SELF :
+        (contention_manager != NULL ? contention_manager(tx, w->tx, (LOCK_GET_WRITE(l) ? WR_CONFLICT : RR_CONFLICT)) : KILL_SELF);
+      if (decision == KILL_OTHER) {
+        /* Kill other */
+        if (!stm_kill(tx, w->tx, t)) {
+          /* Transaction may have committed or aborted: retry */
+          goto restart;
+        }
+      }
+    }
+    if (decision == KILL_OTHER) {
+      version = w->version;
+      goto acquire;
+    }
+    /* Kill self */
+    if ((decision & DELAY_RESTART) != 0)
+      tx->c_lock = lock;
+    /* Abort */
+# ifdef INTERNAL_STATS
+    tx->aborts_locked_read++;
+# endif /* INTERNAL_STATS */
+# ifdef CONFLICT_TRACKING
+    if (conflict_cb != NULL && l != LOCK_UNIT) {
+      /* Call conflict callback */
+      stm_tx_t *other = ((w_entry_t *)LOCK_GET_ADDR(l))->tx;
+      conflict_cb(tx, other);
+    }
+# endif /* CONFLICT_TRACKING */
+    *ptrvalue = 0;
+    return stm_rollback(tx, (LOCK_GET_WRITE(l) ? STM_ABORT_WR_CONFLICT : STM_ABORT_RR_CONFLICT));
+    //return 0;
+  }
+  /* Not locked */
+  version = LOCK_GET_TIMESTAMP(l);
+ acquire:
+  /* Acquire lock (ETL) */
+  if (tx->w_set.nb_entries == tx->w_set.size)
+    stm_allocate_ws_entries(tx, 1);
+  w = &tx->w_set.entries[tx->w_set.nb_entries];
+  w->version = version;
+  value = ATOMIC_LOAD(addr);
+  //if (ATOMIC_CAS_FULL(lock, l, LOCK_SET_ADDR_READ((stm_word_t)w)) == 0)
+  if (ATOMIC_CAS_FULL(lock, l, LOCK_SET_ADDR_READ((stm_word_t)w)) != l)
+    goto restart;
+  /* Add entry to write set */
+  w->addr = addr;
+  w->mask = 0;
+  w->lock = lock;
+  w->value = value;
+  w->next = NULL;
+  tx->w_set.nb_entries++;
+  *ptrvalue = value;
+  //return value;
+  return SUCCESS;
+}
+#endif /* CM == CM_MODULAR */
+
+/*
+ * Store a word-sized value (return write set entry or NULL).
+ */
+// NEW version RETURNS ROLLBACK_ REQUESTED NO_RETRY or SUCCESS
+// NEW version RETURNS ROLLBACK_ REQUESTED NO_RETRY or SUCCESS - TODO
+// WAS static inline w_entry_t *stm_write(stm_tx_t *tx, volatile stm_word_t *addr, stm_word_t value, stm_word_t mask)
+static int stm_write(stm_tx_t *tx, volatile stm_word_t *addr, stm_word_t value, stm_word_t mask)
+{
+  volatile stm_word_t *lock;
+  stm_word_t l, version;
+  w_entry_t *w;
+#if DESIGN == WRITE_BACK_ETL
+  w_entry_t *prev = NULL;
+#elif DESIGN == WRITE_THROUGH
+  int duplicate = 0;
+#endif /* DESIGN == WRITE_THROUGH */
+#if CM == CM_MODULAR
+  int decision;
+  stm_word_t l2, t;
+#endif /* CM == CM_MODULAR */
+
+  PRINT_DEBUG2("==> stm_write(t=%p[%lu-%lu],a=%p,d=%p-%lu,m=0x%lx)\n",
+               tx, (unsigned long)tx->start, (unsigned long)tx->end, addr, (void *)value, (unsigned long)value, (unsigned long)mask);
+
+#if CM == CM_MODULAR
+  if (GET_STATUS(tx->status) == TX_KILLED) {
+    return stm_rollback(tx, STM_ABORT_KILLED);
+//    return NULL;
+  }
+#else /* CM != CM_MODULAR */
+  assert(IS_ACTIVE(tx->status));
+#endif /* CM !=  CM_MODULAR */
+
+  if (tx->ro) {
+    /* Disable read-only and abort */
+  //  assert(tx->attr != NULL);
+    /* Update attributes to inform the caller */ // ---> the caller will never know the difference
+    tx->attr.read_only = 0;
+#ifdef INTERNAL_STATS
+    tx->aborts_ro++;
+#endif /* INTERNAL_STATS */
+    return stm_rollback(tx, STM_ABORT_RO_WRITE);
+//    return NULL;
+  }
+
+  /* Get reference to lock */
+  lock = GET_LOCK(addr);
+
+  /* Try to acquire lock */
+ restart:
+#if CM == CM_DELAY && defined(WAIT_COND)
+  mutex_lock(&(locks_mutex[LOCK_IDX(addr)]));
+ 	  l = *lock;
+  mutex_unlock(&(locks_mutex[LOCK_IDX(addr)]));
+#else /* CM != CM_DELAY && defined(WAIT_COND) */
+  l = ATOMIC_LOAD_ACQ(lock);
+#endif /* CM != CM_DELAY && defined(WAIT_COND) */
+
+  PRINT_DEBUG3("%s: lock %p l %p *lock %d (locks %p %d) init %d\n",
+		  __func__, lock, l, *lock, locks, LOCK_ARRAY_SIZE, initialized);
+
+ restart_no_load:
+  if (LOCK_GET_OWNED(l)) {
+    /* Locked */
+    if (l == LOCK_UNIT) {
+      /* Data modified by a unit store: should not last long => retry */
+      goto restart;
+    }
+    /* Do we own the lock? */
+#if DESIGN == WRITE_THROUGH
+    if (tx == (stm_tx_t *)LOCK_GET_ADDR(l)) {
+      /* Yes */
+# ifdef NO_DUPLICATES_IN_RW_SETS
+      int i;
+      /* Check if address is in write set (a lock may cover multiple addresses) */
+      w = tx->w_set.entries;
+      for (i = tx->w_set.nb_entries; i > 0; i--, w++) {
+        if (w->addr == addr) {
+          if (mask == 0)
+            //return w;
+        	  return SUCCESS;
+          if (w->mask == 0) {
+            /* Remember old value */
+            w->value = ATOMIC_LOAD(addr);
+            w->mask = mask;
+          }
+          /* Yes: only write to memory */
+          if (mask != ~(stm_word_t)0)
+            value = (ATOMIC_LOAD(addr) & ~mask) | (value & mask);
+          ATOMIC_STORE(addr, value);
+          //return w;
+          return SUCCESS;
+        }
+      }
+# endif /* NO_DUPLICATES_IN_RW_SETS */
+      /* Mark entry so that we do not drop the lock upon undo */
+      duplicate = 1;
+      /* Must add to write set (may add entry multiple times) */
+      goto do_write;
+    }
+#elif DESIGN == WRITE_BACK_ETL
+    w = (w_entry_t *)LOCK_GET_ADDR(l);
+    PRINT_DEBUG3("%s: w %p w_set.entries %p w_set.nb_entries %d\n",
+    		__func__, w, tx->w_set.entries, tx->w_set.nb_entries);
+    /* Simply check if address falls inside our write set (avoids non-faulting load) */
+    if (tx->w_set.entries <= w && w < tx->w_set.entries + tx->w_set.nb_entries) {
+      /* Yes */
+#if CM == CM_MODULAR
+      /* If read-locked: upgrade lock */
+      if (!LOCK_GET_WRITE(l)) {
+        //if (ATOMIC_CAS_FULL(lock, l, LOCK_UPGRADE(l)) == 0) {
+        if (ATOMIC_CAS_FULL(lock, l, LOCK_UPGRADE(l)) != l) {
+          /* Lock must have been stolen: abort */
+          return stm_rollback(tx, STM_ABORT_KILLED);
+          //return NULL;
+        }
+        tx->w_set.has_writes++;
+      }
+#endif /* CM == CM_MODULAR */
+      if (mask == 0) {
+        /* No need to insert new entry or modify existing one */
+        //return w;
+    	  return SUCCESS;
+      }
+      prev = w;
+      /* Did we previously write the same address? */
+      while (1) {
+        if (addr == prev->addr) {
+          /* No need to add to write set */
+          if (mask != ~(stm_word_t)0) {
+            if (prev->mask == 0) {
+                /* CHECK USER SPACE ADDRESS ACCESS */
+                if (!access_ok(VERIFY_READ, addr, sizeof(value)))
+              	  printk("%s: access_ok addr %p size %d error [%d]\n",__func__, addr, sizeof(value), current->pid);
+                prev->value = ATOMIC_LOAD(addr);
+            }
+            value = (prev->value & ~mask) | (value & mask);
+          }
+          prev->value = value;
+          prev->mask |= mask;
+          //return prev;
+          return SUCCESS;
+        }
+        if (prev->next == NULL) {
+          /* Remember last entry in linked list (for adding new entry) */
+          break;
+        }
+        prev = prev->next;
+      }
+      /* Get version from previous write set entry (all entries in linked list have same version) */
+      version = prev->version;
+      /* Must add to write set */
+      if (tx->w_set.nb_entries == tx->w_set.size)
+        stm_allocate_ws_entries(tx, 1);
+      w = &tx->w_set.entries[tx->w_set.nb_entries];
+# if CM == CM_MODULAR
+      w->version = version;
+# endif /* CM == CM_MODULAR */
+      goto do_write;
+    }
+#endif /* DESIGN == WRITE_BACK_ETL */
+#if DESIGN == WRITE_BACK_CTL
+    /* Spin while locked (should not last long) */
+    goto restart;
+#else /* DESIGN != WRITE_BACK_CTL */
+    /* Conflict: CM kicks in */
+# if CM != CM_MODULAR && defined(IRREVOCABLE_ENABLED)
+    if (tx->irrevocable) {
+      /* Spin while locked */
+      goto restart;
+    }
+# endif /* CM != CM_MODULAR && defined(IRREVOCABLE_ENABLED) */
+# if CM == CM_MODULAR
+    t = w->tx->status;
+    l2 = ATOMIC_LOAD_ACQ(lock);
+    if (l != l2) {
+      l = l2;
+      goto restart_no_load;
+    }
+    if (t != w->tx->status) {
+      /* Transaction status has changed: restart the whole procedure */
+      goto restart;
+    }
+    if (GET_STATUS(t) == TX_KILLED) {
+      /* We can safely steal lock */
+      decision = KILL_OTHER;
+    } else {
+      decision =
+# ifdef IRREVOCABLE_ENABLED
+        GET_STATUS(tx->status) == TX_IRREVOCABLE ? KILL_OTHER :
+        GET_STATUS(t) == TX_IRREVOCABLE ? KILL_SELF :
+# endif /* IRREVOCABLE_ENABLED */
+        GET_STATUS(tx->status) == TX_KILLED ? KILL_SELF :
+        (contention_manager != NULL ? contention_manager(tx, w->tx, WW_CONFLICT) : KILL_SELF);
+      if (decision == KILL_OTHER) {
+        /* Kill other */
+        if (!stm_kill(tx, w->tx, t)) {
+          /* Transaction may have committed or aborted: retry */
+          goto restart;
+        }
+      }
+    }
+    if (decision == KILL_OTHER) {
+      /* Handle write after reads (before CAS) */
+      version = w->version;
+      goto acquire;
+    }
+    /* Kill self */
+    if ((decision & DELAY_RESTART) != 0)
+      tx->c_lock = lock;
+# elif CM == CM_DELAY
+    tx->c_lock = lock;
+# endif /* CM == CM_DELAY */
+    /* Abort */
+# ifdef INTERNAL_STATS
+    tx->aborts_locked_write++;
+# endif /* INTERNAL_STATS */
+# ifdef CONFLICT_TRACKING
+    if (conflict_cb != NULL && l != LOCK_UNIT) {
+      /* Call conflict callback */
+#  if DESIGN == WRITE_THROUGH
+      stm_tx_t *other = (stm_tx_t *)LOCK_GET_ADDR(l);
+#  else /* DESIGN != WRITE_THROUGH */
+      stm_tx_t *other = ((w_entry_t *)LOCK_GET_ADDR(l))->tx;
+#  endif /* DESIGN != WRITE_THROUGH */
+      conflict_cb(tx, other);
+    }
+# endif /* CONFLICT_TRACKING */
+    return stm_rollback(tx, STM_ABORT_WW_CONFLICT);
+    //return NULL;
+#endif /* DESIGN != WRITE_BACK_CTL */
+  }
+  /* Not locked */
+#if DESIGN == WRITE_BACK_CTL
+  w = stm_has_written(tx, addr);
+  if (w != NULL) {
+    w->value = (w->value & ~mask) | (value & mask);
+    w->mask |= mask;
+    //return w;
+    return SUCCESS;
+  }
+#endif /* DESIGN == WRITE_BACK_CTL */
+  /* Handle write after reads (before CAS) */
+  version = LOCK_GET_TIMESTAMP(l);
+#ifdef IRREVOCABLE_ENABLED
+  /* In irrevocable mode, no need to revalidate */
+  if (tx->irrevocable)
+    goto acquire_no_check;
+#endif /* IRREVOCABLE_ENABLED */
+ acquire:
+  PRINT_DEBUG3("version %d > tx->end %d tx->no_retry %d tx->ro %d tx->can_extend %d addr %p l %p lock %p\n",
+ 		version, tx->end, tx->attr.no_retry, tx->ro, tx->can_extend, addr, l, lock);
+  /* valid version? */
+  if (version > tx->end) {
+    /* We might have read an older version previously */
+    if (!tx->can_extend || stm_has_read(tx, lock) != NULL) {
+      /* Read version must be older (otherwise, tx->end >= version) */
+      /* Not much we can do: abort */
+#if CM == CM_MODULAR
+      /* Abort caused by invisible reads */
+      tx->visible_reads++;
+#endif /* CM == CM_MODULAR */
+#ifdef INTERNAL_STATS
+      tx->aborts_validate_write++;
+#endif /* INTERNAL_STATS */
+      return stm_rollback(tx, STM_ABORT_VAL_WRITE);
+      //return NULL;
+    }
+  }
+  /* Acquire lock (ETL) */
+#ifdef IRREVOCABLE_ENABLED
+ acquire_no_check:
+#endif /* IRREVOCABLE_ENABLED */
+#if DESIGN == WRITE_THROUGH
+  //if (ATOMIC_CAS_FULL(lock, l, LOCK_SET_ADDR_WRITE((stm_word_t)tx)) == 0)
+  if (ATOMIC_CAS_FULL(lock, l, LOCK_SET_ADDR_WRITE((stm_word_t)tx)) != l)
+    goto restart;
+#elif DESIGN == WRITE_BACK_ETL
+  if (tx->w_set.nb_entries == tx->w_set.size)
+    stm_allocate_ws_entries(tx, 1);
+  w = &tx->w_set.entries[tx->w_set.nb_entries];
+# if CM == CM_MODULAR
+  w->version = version;
+# endif /* if CM == CM_MODULAR */
+#if CM == CM_DELAY && defined(WAIT_COND)
+  mutex_lock(&(locks_mutex[LOCK_IDX(addr)]));
+  	  if ( *lock != l ) {
+  		  mutex_unlock(&(locks_mutex[LOCK_IDX(addr)]));
+  		  goto restart;
+  	  }
+  	  *lock = LOCK_SET_ADDR_WRITE((stm_word_t)w);
+  	  //pthread_cond_broadcast(&(locks_cond[LOCK_IDX(addr)])); //we are not releasing but acquiring a lock
+  mutex_unlock(&(locks_mutex[LOCK_IDX(addr)]));
+#else /* CM != CM_DELAY && defined(WAIT_COND) */
+  if (ATOMIC_CAS_FULL(lock, l, LOCK_SET_ADDR_WRITE((stm_word_t)w)) != l) {
+	  //	 printk("%s: failed to Acquire Lock ETL lock %p *lock %d l %d LSAW w %p\n",
+	  //			 __func__, lock, *lock, l, LOCK_SET_ADDR_WRITE((stm_word_t)w));
+    goto restart; }
+#endif /* CM != CM_DELAY && defined(WAIT_COND) */
+#endif /* DESIGN == WRITE_BACK_ETL */
+  /* We own the lock here (ETL) */
+do_write:
+  /* Add address to write set */
+#if DESIGN != WRITE_BACK_ETL
+  if (tx->w_set.nb_entries == tx->w_set.size)
+    stm_allocate_ws_entries(tx, 1);
+  w = &tx->w_set.entries[tx->w_set.nb_entries++];
+#endif /* DESIGN != WRITE_BACK_ETL */
+  w->addr = addr;
+  w->mask = mask;
+  w->lock = lock;
+  if (mask == 0) {
+    /* Do not write anything */
+#ifndef NDEBUG
+    w->value = 0;
+#endif /* ! NDEBUG */
+  } else
+#if DESIGN == WRITE_THROUGH
+  {
+    /* Remember old value */
+    w->value = ATOMIC_LOAD(addr);
+  }
+  /* We store the old value of the lock (timestamp and incarnation) */
+  w->version = l;
+  w->no_drop = duplicate;
+  if (mask != 0) {
+    if (mask != ~(stm_word_t)0)
+      value = (w->value & ~mask) | (value & mask);
+    ATOMIC_STORE(addr, value);
+  }
+#elif DESIGN == WRITE_BACK_ETL
+  {
+    /* Remember new value */
+    if (mask != ~(stm_word_t)0) {
+      /* CHECK USER SPACE ADDRESS ACCESS */
+      if (!access_ok(VERIFY_READ, addr, sizeof(value)))
+    	  printk("%s: access_ok addr %p size %d error [%d]\n",__func__, addr, sizeof(value), current->pid);
+      stm_word_t tmp = ATOMIC_LOAD(addr);
+      value = (tmp & ~mask) | (value & mask);
+    }
+    w->value = value;
+  }
+# if CM != CM_MODULAR
+  w->version = version;
+# endif /* CM != CM_MODULAR */
+  w->next = NULL;
+  if (prev != NULL) {
+    /* Link new entry in list */
+    prev->next = w;
+  }
+  tx->w_set.nb_entries++;
+  tx->w_set.has_writes++;
+#else /* DESIGN == WRITE_BACK_CTL */
+  {
+    /* Remember new value */
+    w->value = value;
+  }
+# ifndef NDEBUG
+  w->version = version;
+# endif
+  w->no_drop = 1;
+# ifdef USE_BLOOM_FILTER
+  tx->w_set.bloom |= FILTER_BITS(addr) ;
+# endif /* USE_BLOOM_FILTER */
+#endif /* DESIGN == WRITE_BACK_CTL */
+
+#ifdef IRREVOCABLE_ENABLED
+  if (!tx->irrevocable && ATOMIC_LOAD_ACQ(&irrevocable)) {
+    return stm_rollback(tx, STM_ABORT_IRREVOCABLE);
+    //return NULL;
+  }
+#endif /* IRREVOCABLE_ENABLED */
+
+//  return w;
+  return SUCCESS;
+}
+
+/*
+ * Store a word-sized value in a unit transaction. -> STRONG ATOMICITY SUPPORT
+ */
+static inline int stm_unit_write(volatile stm_word_t *addr, stm_word_t value, stm_word_t mask, stm_word_t *timestamp)
+{
+  volatile stm_word_t *lock;
+  stm_word_t l;
+
+  PRINT_DEBUG2("==> stm_unit_write(a=%p,d=%p-%lu,m=0x%lx)\n",
+               addr, (void *)value, (unsigned long)value, (unsigned long)mask);
+
+  /* Get reference to lock */
+  lock = GET_LOCK(addr);
+
+  /* Try to acquire lock */
+ restart:
+#if CM == CM_DELAY && defined(WAIT_COND)
+  mutex_lock(&(locks_mutex[LOCK_IDX(addr)]));
+  	  l = *lock;
+  mutex_unlock(&(locks_mutex[LOCK_IDX(addr)]));
+#else /* CM != CM_DELAY && defined(WAIT_COND) */
+  l = ATOMIC_LOAD_ACQ(lock);
+#endif /* CM == CM_DELAY && defined(WAIT_COND) */
+
+  if (LOCK_GET_OWNED(l)) {
+    /* Locked: wait until lock is free */
+#ifdef WAIT_YIELD
+    yield();
+#endif /* WAIT_YIELD */
+    goto restart;
+  }
+  /* Not locked */
+  if (timestamp != NULL && LOCK_GET_TIMESTAMP(l) > *timestamp) {
+    /* Return current timestamp */
+    *timestamp = LOCK_GET_TIMESTAMP(l);
+    return 0;
+  }
+  /* TODO: would need to store thread ID to be able to kill it (for wait freedom) */
+#if CM == CM_DELAY && defined(WAIT_COND)
+  mutex_lock(&(locks_mutex[LOCK_IDX(addr)]));
+  	  if ( *lock != l ) {
+  		  mutex_unlock(&(locks_mutex[LOCK_IDX(addr)]));
+  		  goto restart;
+  	  }
+  	  *lock = LOCK_UNIT;
+  	  //pthread_cond_broadcast(&(locks_cond[LOCK_IDX(addr)])); //we are not releasing but acquiring a lock
+  mutex_unlock(&(locks_mutex[LOCK_IDX(addr)]));
+#else
+  if (ATOMIC_CAS_FULL(lock, l, LOCK_UNIT) == l) // means failure in ATOMIC_CAS_FULL
+	  goto restart;
+#endif
+  ATOMIC_STORE(addr, value);
+  /* Update timestamp with newer value (may exceed VERSION_MAX by up to MAX_THREADS) */
+  l = FETCH_INC_CLOCK;
+  if (timestamp != NULL)
+    *timestamp = l;
+  /* Make sure that lock release becomes visible */
+#if CM == CM_DELAY && defined(WAIT_COND)
+  mutex_lock(&(locks_mutex[LOCK_IDX(addr)]));
+  	  *lock = LOCK_SET_TIMESTAMP(l);
+  	  cond_broadcast(&(locks_cond[LOCK_IDX(addr)]));
+  mutex_unlock(&(locks_mutex[LOCK_IDX(addr)]));
+#else /* CM != CM_DELAY && defined(WAIT_COND) */
+  ATOMIC_STORE_REL(lock, LOCK_SET_TIMESTAMP(l));
+#endif /* CM != CM_DELAY && defined(WAIT_COND) */
+  if (l >= VERSION_MAX) {
+    /* Block all transactions and reset clock (current thread is not in active transaction) */
+    stm_quiesce_barrier(NULL, rollover_clock, NULL);
+  }
+  return 1;
+}
+
+/*
+ * Catch signal (to emulate non-faulting load).
+ */
+static void signal_catcher(int sig)
+{
+  stm_tx_t *tx = stm_get_tx();
+
+  /* A fault might only occur upon a load concurrent with a free (read-after-free) */
+  PRINT_DEBUG("Caught signal: %d\n", sig);
+
+  //if (tx == NULL || (tx->attr != NULL && tx->attr->no_retry)) {
+  if (tx == NULL || ( tx->attr.no_retry)) {
+    /* There is not much we can do: execution will restart at faulty load */
+	  PRINT_ERR( "Error: invalid memory accessed and no longjmp destination\n");
+//    exit(1);
+  }
+
+#ifdef INTERNAL_STATS
+  tx->aborts_invalid_memory++;
+#endif /* INTERNAL_STATS */
+  /* Will cause a longjmp */
+  stm_rollback(tx, STM_ABORT_SIGNAL);
+}
+
+/* ################################################################### *
+ * STM FUNCTIONS
+ * ################################################################### */
+
+/*
+ * Called once (from main) to initialize STM infrastructure.
+ */
+//NOTA
+//if registered at init this will be called just once an not for every process
+//different processes have different addr space with the same ranges of addresses
+int __init stm_init(void)
+{
+#if CM == CM_MODULAR
+  char *s;
+#endif /* CM == CM_MODULAR */
+
+  PRINT_DEBUG("==> stm_init()\n");
+  //printk("==> stm_init()\n"); // add a general message that tell the user that this system run LinuxSTM! :-)
+
+  if (initialized)
+    return -EPERM;
+
+  PRINT_DEBUG("\tsizeof(word)=%d\n", (int)sizeof(stm_word_t));
+  PRINT_DEBUG("\tVERSION_MAX=0x%lx\n", (unsigned long)VERSION_MAX);
+
+  COMPILE_TIME_ASSERT(sizeof(stm_word_t) == sizeof(void *));
+#ifndef CONFIG_64BIT
+  COMPILE_TIME_ASSERT(sizeof(stm_word_t) == sizeof(atomic_t));
+#else
+  COMPILE_TIME_ASSERT(sizeof(stm_word_t) == sizeof(atomic64_t));
+#endif
+
+  //TODO TODO TODO
+  //must be allocated per process, stm_init must be called by the process (to ease all these problems)
+  // but a shared lock part for the kernel will be useful in a futher version of the software
+  memset((void *)locks, 0, LOCK_ARRAY_SIZE * sizeof(stm_word_t));
+
+#if CM == CM_MODULAR
+  s = getenv(VR_THRESHOLD);
+  if (s != NULL)
+    vr_threshold = (int)strtol(s, NULL, 10);
+  else
+    vr_threshold = VR_THRESHOLD_DEFAULT;
+  PRINT_DEBUG("\tVR_THRESHOLD=%d\n", vr_threshold);
+#endif /* CM == CM_MODULAR */
+
+#if CM == CM_DELAY && defined(WAIT_COND)
+  { int i;
+  for (i=0; i<LOCK_ARRAY_SIZE; i++) {
+	  mutex_init(&locks_mutex[i]);
+	  init_waitqueue_head(&locks_cond[i]); }
+  }
+#endif /* CM == CM_DELAY && defined(WAIT_COND) */
+
+  CLOCK = 0;
+  stm_quiesce_init();
+
+/* NOT REQUIRED IN KERNEL
+#ifndef TLS
+  if (pthread_key_create(&thread_tx, NULL) != 0) {
+	  PRINT_ERR( "Error creating thread local\n");
+    exit(1);
+  }
+#endif
+*/
+
+//create the kmem cache for stm_tx_t objects
+//cache usage is tracked by the operating system
+//  kmem_cache_create (const char *name, size_t size,
+ // size_t align, unsigned long flags, void (*ctor)(void *))
+
+  stm_tx_cache = kmem_cache_create("stm_tx_t", sizeof(stm_tx_t),
+		  ARCH_SLAB_MINALIGN, (SLAB_HWCACHE_ALIGN | SLAB_PANIC | SLAB_NOTRACK), NULL);
+  if (!stm_tx_cache) {
+	  printk("ERROR ERROR ERROR kmem_cache_create");
+	  initialized = 0;
+	  return -ENOMEM;
+  }
+
+  memset(locks, 0, (sizeof(stm_word_t)*LOCK_ARRAY_SIZE)); // per process @ least we can support shared memory
+  nb_specific = 0; // per process
+
+  initialized = 1;
+  return 0;
+}
+__initcall(stm_init);
+
+// this is the only place where we used _user because of the signal registration // i.e. still TODO TODO TODO
+static void stm_init_user(void)
+{
+#ifndef EPOCH_GC
+//  struct sigaction act; // TODO
+#endif /* ! EPOCH_GC */
+
+#ifdef EPOCH_GC
+  gc_init(stm_get_clock);
+#endif /* EPOCH_GC */
+
+#ifndef EPOCH_GC
+//  if (getenv(NO_SIGNAL_HANDLER) == NULL) {
+    /* Catch signals for non-faulting load */
+//    act.sa_handler = signal_catcher;
+//    act.sa_flags = 0;
+//    sigemptyset(&act.sa_mask);
+//    if (sigaction(SIGBUS, &act, NULL) < 0 || sigaction(SIGSEGV, &act, NULL) < 0) {
+      PERROR("sigaction");
+//      exit(1);
+//    }
+//  }
+#endif /* ! EPOCH_GC */
+}
+
+/*
+ * Called once (from main) to clean up STM infrastructure.
+ */
+void stm_exit()
+{
+  PRINT_DEBUG("==> stm_exit()\n");
+
+  //delete the kmemcache allocated in stm_init
+  if (stm_tx_cache)
+	  kmem_cache_destroy(stm_tx_cache);
+
+/*#ifndef TLS not required in kernel
+  pthread_key_delete(thread_tx);
+#endif
+*/
+  stm_quiesce_exit();
+
+#if CM == CM_DELAY && defined(WAIT_COND)
+  { int i;
+  for (i=0; i<LOCK_ARRAY_SIZE; i++) {
+//	  cond_destroy(&locks_cond[i]);
+	  mutex_destroy(&locks_mutex[i]);
+  }
+  }
+#endif /* CM == CM_DELAY  && defined(WAIT_COND)*/
+
+#ifdef EPOCH_GC
+  gc_exit();
+#endif /* EPOCH_GC */
+}
+__exitcall(stm_exit);
+
+/*
+ * CALLED by linux/fork.c:1061 copy_process
+ * Called by the CURRENT thread to initialize thread-local STM data.
+ */
+stm_tx_t * stm_init_thread()
+{
+  stm_tx_t *tx;
+
+  PRINT_DEBUG("==> stm_init_thread()\n");
+
+  if ( !initialized )
+	  return 0;
+
+//  if ((tx = stm_get_tx()) != NULL)
+//    TX_RETURN;
+
+#ifdef EPOCH_GC
+  gc_init_thread();
+#endif /* EPOCH_GC */
+
+  /* Allocate descriptor */
+/*  if ((tx = (stm_tx_t *)malloc(sizeof(stm_tx_t))) == NULL) {
+    PERROR("malloc tx");
+    exit(1);
+  }
+  */
+// in kernel we get the descriptor from the kmem cache (statistics in /proc/slab..)
+  //tx = kmem_cache_alloc(stm_tx_cache, GFP_KERNEL);
+  tx = kmem_cache_zalloc(stm_tx_cache, GFP_KERNEL);
+  if (!tx ) {
+	  PERROR("kmem_cache_alloc fails");
+	  return 0;
+  }
+  tx->snapshot = 0;
+
+  /* Set status (no need for CAS or atomic op) */
+  tx->status = TX_IDLE;
+  /* Read set */
+  tx->r_set.nb_entries = 0;
+  tx->r_set.size = RW_SET_SIZE;
+  stm_allocate_rs_entries(tx, 0);
+  /* Write set */
+  tx->w_set.nb_entries = 0;
+  tx->w_set.size = RW_SET_SIZE;
+#if DESIGN == WRITE_BACK_CTL
+  tx->w_set.nb_acquired = 0;
+# ifdef USE_BLOOM_FILTER
+  tx->w_set.bloom = 0;
+# endif /* USE_BLOOM_FILTER */
+#endif /* DESIGN == WRITE_BACK_CTL */
+  stm_allocate_ws_entries(tx, 0);
+  /* Nesting level */
+  tx->nesting = 0; // here reset nesting to 0..
+  /* Transaction-specific data */
+  memset(tx->data, 0, MAX_SPECIFIC * sizeof(void *));
+#ifdef CONFLICT_TRACKING
+  /* Thread identifier */
+  tx->thread_id = pthread_self();
+#endif /* CONFLICT_TRACKING */
+#if CM == CM_DELAY || CM == CM_MODULAR
+  /* Contented lock */
+  tx->c_lock = NULL;
+#endif /* CM == CM_DELAY || CM == CM_MODULAR */
+#if CM == CM_BACKOFF
+  /* Backoff */
+  tx->backoff = MIN_BACKOFF;
+  tx->seed = 123456789UL;
+#endif /* CM == CM_BACKOFF */
+#if CM == CM_MODULAR
+  tx->visible_reads = 0;
+  tx->timestamp = 0;
+#endif /* CM == CM_MODULAR */
+#if CM == CM_MODULAR || defined(INTERNAL_STATS)
+  tx->retries = 0;
+#endif /* CM == CM_MODULAR || defined(INTERNAL_STATS) */
+#ifdef INTERNAL_STATS
+  /* Statistics */
+  tx->aborts = 0;
+  tx->aborts_1 = 0;
+  tx->aborts_2 = 0;
+  tx->aborts_ro = 0;
+  tx->aborts_locked_read = 0;
+  tx->aborts_locked_write = 0;
+  tx->aborts_validate_read = 0;
+  tx->aborts_validate_write = 0;
+  tx->aborts_validate_commit = 0;
+  tx->aborts_invalid_memory = 0;
+# if CM == CM_MODULAR
+  tx->aborts_killed = 0;
+# endif /* CM == CM_MODULAR */
+# ifdef READ_LOCKED_DATA
+  tx->locked_reads_ok = 0;
+  tx->locked_reads_failed = 0;
+# endif /* READ_LOCKED_DATA */
+  tx->max_retries = 0;
+#endif /* INTERNAL_STATS */
+  /* Store as thread-local data */ // NOT REQUIRED IN KERNEL
+/*#ifdef TLS
+  thread_tx = tx;
+#else
+  pthread_setspecific(thread_tx, tx);
+#endif
+*/
+  stm_quiesce_enter_thread(tx);
+
+  /* Callbacks */
+/*  if (nb_init_cb != 0) {
+    int cb;
+    for (cb = 0; cb < nb_init_cb; cb++)
+      init_cb[cb].f(TXARGS init_cb[cb].arg);
+  }
+*/
+  mod_stats_on_thread_init(tx);
+//  TX_RETURN;
+  return tx;
+}
+
+/*
+ * CALLED by linux/exit.c:954 do_exit
+ * Called by the CURRENT thread to cleanup thread-local STM data.
+ */
+//void stm_exit_thread(TXPARAM)
+void stm_exit_thread(stm_tx_t * tx)
+{
+#ifdef EPOCH_GC
+  stm_word_t t;
+#endif /* EPOCH_GC */
+  //TX_GET;
+  if (!initialized)
+	  return;
+  if ( !tx )
+	  return;
+
+  PRINT_DEBUG("==> stm_exit_thread(%p[%lu-%lu])\n", tx, (unsigned long)tx->start, (unsigned long)tx->end);
+
+
+  mod_stats_on_thread_exit();
+  /* Callbacks */
+/*  if (nb_exit_cb != 0) {
+    int cb;
+    for (cb = 0; cb < nb_exit_cb; cb++)
+      exit_cb[cb].f(TXARGS exit_cb[cb].arg);
+  }
+*/
+  stm_quiesce_exit_thread(tx);
+
+// TODO move EPOCH_GC support in user space
+#ifdef EPOCH_GC
+  t = GET_CLOCK;
+  gc_free(tx->r_set.entries, t);
+  gc_free(tx->w_set.entries, t);
+  gc_free(tx, t);
+  gc_exit_thread();
+#else /* ! EPOCH_GC */
+  vfree(tx->r_set.entries);
+  vfree(tx->w_set.entries);
+
+  kmem_cache_free(stm_tx_cache, tx);
+#endif /* ! EPOCH_GC */
+
+/*#ifdef TLS not required in kernel
+  thread_tx = NULL;
+#else
+  pthread_setspecific(thread_tx, NULL);
+#endif
+*/
+}
+
+/*
+ * Called by the CURRENT thread to start a transaction.
+ */
+// in the original version sigsetjmp is called in the main program
+// and siglongjmp is called in from the library by stm_rollback
+//sigjmp_buf *stm_start(TXPARAMS stm_tx_attr_t *attr)
+
+//int stm_start(void* stackaddr, int stacksize, chk_pnt * chk_user_data, struct pt_regs *regs)
+uintptr_t *stm_start(TXPARAMS stm_tx_attr_t *attr)
+{
+  TX_GET;
+  PRINT_DEBUG("==> stm_start(%p)\n", tx);
+
+  /* Increment nesting level */
+  if (tx->nesting++ > 0)
+    return NULL; // do not take the snapshot please! we are using flat nesting
+	// as a first version do use flat nesting
+
+  //first we take a snapshot of the system status then... ----> we took the snapshot in sys_stm_ctrl to mimic TinySTM
+ // int sys_snapshot(void* stackaddr, int stacksize, chk_pnt * chk_user_data, struct pt_regs *regs)
+
+  /* Attributes */
+  tx->attr = *attr;
+  tx->ro = (attr == NULL ? 0 : attr->read_only);
+#ifdef IRREVOCABLE_ENABLED
+  tx->irrevocable = 0;
+#endif /* IRREVOCABLE_ENABLED */
+
+  /* Initialize transaction descriptor */
+  stm_prepare(tx);
+
+  /* Callbacks */
+/*  if (nb_start_cb != 0) {
+    int cb;
+    for (cb = 0; cb < nb_start_cb; cb++)
+      start_cb[cb].f(TXARGS start_cb[cb].arg);
+  }
+*/
+  return &tx->snapshot; // ritorna un indirizzo , i.e. l'address del buffer di salvataggio!
+}
+
+/*
+ * Called by the CURRENT thread to commit a transaction.
+ */
+int stm_commit(TXPARAM)
+{
+  w_entry_t *w;
+  stm_word_t t;
+  int i;
+#if DESIGN == WRITE_BACK_CTL
+  stm_word_t l, value;
+#endif /* DESIGN == WRITE_BACK_CTL */
+  TX_GET;
+
+  PRINT_DEBUG("==> stm_commit(%p[%lu-%lu])\n", tx, (unsigned long)tx->start, (unsigned long)tx->end);
+
+  /* Decrement nesting level */
+  if (--tx->nesting > 0)
+    return SUCCESS; // this means that conflict checking is done at load/store level and on the final commit not partially (flat nesting)
+
+  assert(IS_ACTIVE(tx->status));
+#if CM == CM_MODULAR
+  /* Set status to COMMITTING */
+  t = tx->status;
+  if (GET_STATUS(t) == TX_KILLED
+		  || ATOMIC_CAS_FULL(&tx->status, t, t + (TX_COMMITTING - GET_STATUS(t))) != t) {
+	  //|| ATOMIC_CAS_FULL(&tx->status, t, t + (TX_COMMITTING - GET_STATUS(t))) == 0) {
+    /* We have been killed */
+    assert(GET_STATUS(tx->status) == TX_KILLED);
+    return stm_rollback(tx, STM_ABORT_KILLED);
+//    return 0;
+  }
+#endif /* CM == CM_MODULAR */
+
+  /* A read-only transaction can commit immediately */
+  if (tx->w_set.nb_entries == 0)
+    goto end;
+
+#if CM == CM_MODULAR
+  /* A read-only transaction with visible reads must simply drop locks */
+  if (tx->w_set.has_writes == 0) {
+    w = tx->w_set.entries;
+    for (i = tx->w_set.nb_entries; i > 0; i--, w++) {
+      /* Only drop lock for last covered address in write set */
+      if (w->next == NULL)
+        ATOMIC_STORE_REL(w->lock, LOCK_SET_TIMESTAMP(w->version));
+    }
+    /* Update clock so that future transactions get higher timestamp (liveness of timestamp CM) */
+    FETCH_INC_CLOCK;
+    goto end;
+  }
+#endif /* CM == CM_MODULAR */
+
+  /* Update transaction */
+#if DESIGN == WRITE_BACK_CTL
+# ifdef IRREVOCABLE_ENABLED
+  /* Verify already if there is an irrevocable transaction before acquiring locks */
+  if(!tx->irrevocable && ATOMIC_LOAD(&irrevocable)) {
+    return stm_rollback(tx, STM_ABORT_IRREVOCABLE);
+    //return 0;
+  }
+# endif /* IRREVOCABLE_ENABLED */
+  /* Acquire locks (in reverse order) */
+  w = tx->w_set.entries + tx->w_set.nb_entries;
+  do {
+    w--;
+    /* Try to acquire lock */
+ restart:
+    l = ATOMIC_LOAD(w->lock);
+    if (LOCK_GET_OWNED(l)) {
+      /* Do we already own the lock? */
+      if (tx->w_set.entries <= (w_entry_t *)LOCK_GET_ADDR(l) && (w_entry_t *)LOCK_GET_ADDR(l) < tx->w_set.entries + tx->w_set.nb_entries) {
+        /* Yes: ignore */
+        continue;
+      }
+      /* Conflict: CM kicks in */
+# if CM == CM_DELAY
+      tx->c_lock = w->lock;
+# endif /* CM == CM_DELAY */
+      /* Abort self */
+# ifdef INTERNAL_STATS
+      tx->aborts_locked_write++;
+# endif /* INTERNAL_STATS */
+      return stm_rollback(tx, STM_ABORT_WW_CONFLICT);
+      //return 0;
+    }
+    //if (ATOMIC_CAS_FULL(w->lock, l, LOCK_SET_ADDR_WRITE((stm_word_t)w)) == 0)
+    if (ATOMIC_CAS_FULL(w->lock, l, LOCK_SET_ADDR_WRITE((stm_word_t)w)) != l)
+      goto restart;
+    /* We own the lock here */
+    w->no_drop = 0;
+    /* Store version for validation of read set */
+    w->version = LOCK_GET_TIMESTAMP(l);
+    tx->w_set.nb_acquired++;
+  } while (w > tx->w_set.entries);
+#endif /* DESIGN == WRITE_BACK_CTL */
+
+#ifdef IRREVOCABLE_ENABLED
+  /* Verify if there is an irrevocable transaction once all locks have been acquired */
+  if (!tx->irrevocable && ATOMIC_LOAD(&irrevocable)) {
+    return stm_rollback(tx, STM_ABORT_IRREVOCABLE);
+//    return 0;
+  }
+#endif /* IRREVOCABLE_ENABLED */ 
+  /* Get commit timestamp (may exceed VERSION_MAX by up to MAX_THREADS) */
+  t = FETCH_INC_CLOCK;
+#ifdef IRREVOCABLE_ENABLED
+  if (tx->irrevocable)
+    goto release_locks;
+#endif /* IRREVOCABLE_ENABLED */
+
+  /* Try to validate (only if a concurrent transaction has committed since tx->start) */
+  if (tx->start != t - 1 && !stm_validate(tx)) {
+    /* Cannot commit */
+#if CM == CM_MODULAR
+    /* Abort caused by invisible reads */
+    tx->visible_reads++;
+#endif /* CM == CM_MODULAR */
+#ifdef INTERNAL_STATS
+    tx->aborts_validate_commit++;
+#endif /* INTERNAL_STATS */
+    return stm_rollback(tx, STM_ABORT_VALIDATE);
+    //return 0;
+  }
+
+#ifdef IRREVOCABLE_ENABLED
+  release_locks:
+#endif /* IRREVOCABLE_ENABLED */
+#if DESIGN == WRITE_THROUGH
+  /* Make sure that the updates become visible before releasing locks */
+  ATOMIC_MB_WRITE;
+  /* Drop locks and set new timestamp (traverse in reverse order) */
+  w = tx->w_set.entries + tx->w_set.nb_entries - 1;
+  for (i = tx->w_set.nb_entries; i > 0; i--, w--) {
+    if (w->no_drop)
+      continue;
+    /* No need for CAS (can only be modified by owner transaction) */
+    ATOMIC_STORE(w->lock, LOCK_SET_TIMESTAMP(t));
+  }
+  /* Make sure that all lock releases become visible */
+  ATOMIC_MB_WRITE;
+#elif DESIGN == WRITE_BACK_ETL
+  /* Install new versions, drop locks and set new timestamp */
+  w = tx->w_set.entries;
+  for (i = tx->w_set.nb_entries; i > 0; i--, w++) {
+    if (w->mask != 0) {
+      /* ACCESS CHECK */
+      if (!access_ok(VERIFY_WRITE, w->addr, sizeof(w->value)))
+        printk("%s: 1 access_ok addr %p size %d error [%d]\n",__func__, w->addr, sizeof(w->value), current->pid);
+      ATOMIC_STORE(w->addr, w->value);
+    }
+    /* Only drop lock for last covered address in write set */
+    if (w->next == NULL)
+# if CM == CM_DELAY && defined(WAIT_COND)
+			  mutex_lock(&(locks_mutex[LOCK_IDX(w->addr)]));
+			  *(w->lock) = LOCK_SET_TIMESTAMP(t);
+			  cond_broadcast(&(locks_cond[LOCK_IDX(w->addr)])); //we are not releasing but acquiring a lock
+			  mutex_unlock(&(locks_mutex[LOCK_IDX(w->addr)]));
+# else /* CM != CM_DELAY && defined(WAIT_COND) */
+			  ATOMIC_STORE_REL(w->lock, LOCK_SET_TIMESTAMP(t));
+# endif /* CM != CM_DELAY && defined(WAIT_COND) */
+  }
+#else /* DESIGN == WRITE_BACK_CTL */
+  /* Install new versions, drop locks and set new timestamp */
+  w = tx->w_set.entries;
+  for (i = tx->w_set.nb_entries; i > 0; i--, w++) {
+    if (w->mask == ~(stm_word_t)0) {
+      ATOMIC_STORE(w->addr, w->value);
+    } else if (w->mask != 0) {
+      value = (ATOMIC_LOAD(w->addr) & ~w->mask) | (w->value & w->mask);
+      ATOMIC_STORE(w->addr, w->value);
+    }
+    /* Only drop lock for last covered address in write set (cannot be "no drop") */
+    if (!w->no_drop)
+      ATOMIC_STORE_REL(w->lock, LOCK_SET_TIMESTAMP(t));
+  }
+#endif /* DESIGN == WRITE_BACK_CTL */
+
+ end:
+#if CM == CM_MODULAR || defined(INTERNAL_STATS)
+  tx->retries = 0;
+#endif /* CM == CM_MODULAR || defined(INTERNAL_STATS) */
+
+#if CM == CM_BACKOFF
+  /* Reset backoff */
+  tx->backoff = MIN_BACKOFF;
+#endif /* CM == CM_BACKOFF */
+
+#if CM == CM_MODULAR
+  tx->visible_reads = 0;
+#endif /* CM == CM_MODULAR */
+
+  /* Callbacks */
+/*  if (nb_commit_cb != 0) {
+    int cb;
+    for (cb = 0; cb < nb_commit_cb; cb++)
+      commit_cb[cb].f(TXARGS commit_cb[cb].arg);
+  }
+*/
+  mod_stats_on_commit();
+
+#ifdef IRREVOCABLE_ENABLED
+  if (tx->irrevocable) {
+    ATOMIC_STORE(&irrevocable, 0);
+    if ((tx->irrevocable & 0x08) != 0)
+      stm_quiesce_release(tx);
+  }
+#endif /* IRREVOCABLE_ENABLED */
+
+  /* Set status to COMMITTED */
+  SET_STATUS(tx->status, TX_COMMITTED);
+
+#ifdef STM_PREEMPT_AVOIDANCE
+  /* if the current transaction receives at least one bonus time slice call schedule */
+  if (tx->bonus)
+	  yield();
+#endif /* !STM_PREEMPTION_AVOIDANCE */
+
+  return SUCCESS;
+}
+// end STM_COMMIT
+
+/*
+ * Called by the CURRENT thread to abort a transaction.
+ */
+// returns ROLLBACK_ REQUESTED or NO_RETRY
+int stm_abort(TXPARAMS int reason)
+{
+  TX_GET;
+  return stm_rollback(tx, reason | STM_ABORT_EXPLICIT);
+}
+
+/*
+ * Called by the CURRENT thread to load a word-sized value.
+ */
+stm_word_t stm_load(TXPARAMS volatile stm_word_t *addr, stm_word_t * value)
+{
+  TX_GET;
+
+#ifdef IRREVOCABLE_ENABLED
+  if (unlikely(((tx->irrevocable & 0x08) != 0))) {
+    /* Serial irrevocable mode: direct access to memory */
+    return ATOMIC_LOAD(addr);
+  }
+#endif /* IRREVOCABLE_ENABLED */
+#if CM == CM_MODULAR
+  if (unlikely((tx->visible_reads >= vr_threshold && vr_threshold >= 0))) {
+    /* Use visible read */
+    return stm_read_visible(tx, addr, value);
+  }
+#endif /* CM == CM_MODULAR */
+  return stm_read_invisible(tx, addr, value);
+}
+
+/*
+ * Called by the CURRENT thread to store a word-sized value.
+ */
+int stm_store(TXPARAMS volatile stm_word_t *addr, stm_word_t value)
+{
+  TX_GET;
+
+#ifdef IRREVOCABLE_ENABLED
+  if (unlikely(((tx->irrevocable & 0x08) != 0))) {
+    /* Serial irrevocable mode: direct access to memory */
+    ATOMIC_STORE(addr, value);
+    return SUCCESS;
+  }
+#endif /* IRREVOCABLE_ENABLED */
+  return stm_write(tx, addr, value, ~(stm_word_t)0);
+}
+
+/*
+ * Called by the CURRENT thread to store part of a word-sized value.
+ */
+int stm_store2(TXPARAMS volatile stm_word_t *addr, stm_word_t value, stm_word_t mask)
+{
+  TX_GET;
+
+#ifdef IRREVOCABLE_ENABLED
+  if (unlikely(((tx->irrevocable & 0x08) != 0))) {
+    /* Serial irrevocable mode: direct access to memory */
+    if (mask == ~(stm_word_t)0)
+      ATOMIC_STORE(addr, value);
+    else
+      ATOMIC_STORE(addr, (ATOMIC_LOAD(addr) & ~mask) | (value & mask));
+    return;
+  }
+#endif /* IRREVOCABLE_ENABLED */
+  return stm_write(tx, addr, value, mask);
+}
+
+/*
+ * Called by the CURRENT thread to inquire about the status of a transaction.
+ */
+int stm_active(TXPARAM)
+{
+  TX_GET;
+
+  return IS_ACTIVE(tx->status);
+}
+
+/*
+ * Called by the CURRENT thread to inquire about the status of a transaction.
+ */
+int stm_aborted(TXPARAM)
+{
+  TX_GET;
+
+  return (GET_STATUS(tx->status) == TX_ABORTED);
+}
+
+# ifdef IRREVOCABLE_ENABLED
+/*
+ * Called by the CURRENT thread to inquire about the status of a transaction.
+ */
+int stm_irrevocable(TXPARAM)
+{
+  TX_GET;
+
+  return ((tx->irrevocable & 0x07) == 3);
+}
+# endif /* IRREVOCABLE_ENABLED */
+
+/*
+ * Called by the CURRENT thread to obtain an environment for setjmp/longjmp.
+ */
+//stm_get_env must return the snapshot id (that is what is returned by sys_)
+//the function is never used in the lib - used only for flat nesting support
+/*sigjmp_buf *stm_get_env(TXPARAM)
+{
+  TX_GET;
+
+  // Only return environment for top-level transaction
+  return tx->nesting == 0 ? &tx->env : NULL;
+}*/
+
+/*
+ * Get transaction attributes.
+ */
+// TODO TODO  TODO requires syscall level support
+/*stm_tx_attr_t *stm_get_attributes(TXPARAM)
+{
+  TX_GET;
+
+  return tx->attr;
+}*/
+
+/*
+ * Return statistics about a thread/transaction.
+ */
+int stm_get_stats(TXPARAMS const char *name, void *val)
+{
+  TX_GET;
+
+  if (strcmp("read_set_size", name) == 0) {
+    *(unsigned int *)val = tx->r_set.size;
+    return 1;
+  }
+  if (strcmp("write_set_size", name) == 0) {
+    *(unsigned int *)val = tx->w_set.size;
+    return 1;
+  }
+  if (strcmp("read_set_nb_entries", name) == 0) {
+    *(unsigned int *)val = tx->r_set.nb_entries;
+    return 1;
+  }
+  if (strcmp("write_set_nb_entries", name) == 0) {
+    *(unsigned int *)val = tx->w_set.nb_entries;
+    return 1;
+  }
+  if (strcmp("read_only", name) == 0) {
+    *(unsigned int *)val = tx->ro;
+    return 1;
+  }
+#ifdef INTERNAL_STATS
+  if (strcmp("nb_aborts", name) == 0) {
+    *(unsigned long *)val = tx->aborts;
+    return 1;
+  }
+  if (strcmp("nb_aborts_1", name) == 0) {
+    *(unsigned long *)val = tx->aborts_1;
+    return 1;
+  }
+  if (strcmp("nb_aborts_2", name) == 0) {
+    *(unsigned long *)val = tx->aborts_2;
+    return 1;
+  }
+  if (strcmp("nb_aborts_ro", name) == 0) {
+    *(unsigned long *)val = tx->aborts_ro;
+    return 1;
+  }
+  if (strcmp("nb_aborts_locked_read", name) == 0) {
+    *(unsigned long *)val = tx->aborts_locked_read;
+    return 1;
+  }
+  if (strcmp("nb_aborts_locked_write", name) == 0) {
+    *(unsigned long *)val = tx->aborts_locked_write;
+    return 1;
+  }
+  if (strcmp("nb_aborts_validate_read", name) == 0) {
+    *(unsigned long *)val = tx->aborts_validate_read;
+    return 1;
+  }
+  if (strcmp("nb_aborts_validate_write", name) == 0) {
+    *(unsigned long *)val = tx->aborts_validate_write;
+    return 1;
+  }
+  if (strcmp("nb_aborts_validate_commit", name) == 0) {
+    *(unsigned long *)val = tx->aborts_validate_commit;
+    return 1;
+  }
+  if (strcmp("nb_aborts_invalid_memory", name) == 0) {
+    *(unsigned long *)val = tx->aborts_invalid_memory;
+    return 1;
+  }
+# if CM == CM_MODULAR
+  if (strcmp("nb_aborts_killed", name) == 0) {
+    *(unsigned long *)val = tx->aborts_killed;
+    return 1;
+  }
+# endif /* CM == CM_MODULAR */
+# ifdef READ_LOCKED_DATA
+  if (strcmp("locked_reads_ok", name) == 0) {
+    *(unsigned long *)val = tx->locked_reads_ok;
+    return 1;
+  }
+  if (strcmp("locked_reads_failed", name) == 0) {
+    *(unsigned long *)val = tx->locked_reads_failed;
+    return 1;
+  }
+# endif /* READ_LOCKED_DATA */
+  if (strcmp("max_retries", name) == 0) {
+    *(unsigned long *)val = tx->max_retries;
+    return 1;
+  }
+#endif /* INTERNAL_STATS */
+  return 0;
+}
+
+/*
+ * Return STM parameters.
+ */
+int stm_get_parameter(const char *name, void *val)
+{
+  if (strcmp("contention_manager", name) == 0) {
+    *(const char **)val = cm_names[CM];
+    return 1;
+  }
+  if (strcmp("design", name) == 0) {
+    *(const char **)val = design_names[DESIGN];
+    return 1;
+  }
+  if (strcmp("initial_rw_set_size", name) == 0) {
+    *(int *)val = RW_SET_SIZE;
+    return 1;
+  }
+#if CM == CM_BACKOFF
+  if (strcmp("min_backoff", name) == 0) {
+    *(unsigned long *)val = MIN_BACKOFF;
+    return 1;
+  }
+  if (strcmp("max_backoff", name) == 0) {
+    *(unsigned long *)val = MAX_BACKOFF;
+    return 1;
+  }
+#endif /* CM == CM_BACKOFF */
+#if CM == CM_MODULAR
+  if (strcmp("vr_threshold", name) == 0) {
+    *(int *)val = vr_threshold;
+    return 1;
+  }
+#endif /* CM == CM_MODULAR */
+#ifdef COMPILE_FLAGS
+  if (strcmp("compile_flags", name) == 0) {
+    *(const char **)val = XSTR(COMPILE_FLAGS);
+    return 1;
+  }
+#endif /* COMPILE_FLAGS */
+  return 0;
+}
+
+/*
+ * Set STM parameters.
+ */
+int stm_set_parameter(const char *name, void *val)
+{
+#if CM == CM_MODULAR
+  int i;
+
+  if (strcmp("cm_policy", name) == 0) {
+    for (i = 0; cms[i].name != NULL; i++) {
+      if (strcasecmp(cms[i].name, (const char *)val) == 0) {
+        contention_manager = cms[i].f;
+        return 1;
+      }
+    }
+    return 0;
+  }
+  if (strcmp("cm_function", name) == 0) {
+    contention_manager = (int (*)(stm_tx_t *, stm_tx_t *, int))val;
+    return 1;
+  }
+  if (strcmp("vr_threshold", name) == 0) {
+    vr_threshold = *(int *)val;
+    return 1;
+  }
+#endif /* CM == CM_MODULAR */
+  return 0;
+}
+
+/*
+ * Create transaction-specific data (return -1 on error).
+ */
+int stm_create_specific(void)
+{
+  if (nb_specific >= MAX_SPECIFIC) {
+	  PRINT_ERR( "Error: maximum number of specific slots reached\n");
+    return -1;
+  }
+  return nb_specific++;
+}
+
+/*
+ * Store transaction-specific data.
+ */
+void stm_set_specific(TXPARAMS int key, void *data)
+{
+  TX_GET;
+
+  assert (key >= 0 && key < nb_specific);
+  tx->data[key] = data;
+}
+
+/*
+ * Fetch transaction-specific data.
+ */
+void *stm_get_specific(TXPARAMS int key)
+{
+  TX_GET;
+
+  assert (key >= 0 && key < nb_specific);
+  return tx->data[key];
+}
+
+/*
+ * Register callbacks for an external module (must be called before creating transactions).
+ */
+/*int stm_register(void (*on_thread_init)(TXPARAMS void *arg),
+                 void (*on_thread_exit)(TXPARAMS void *arg),
+                 void (*on_start)(TXPARAMS void *arg),
+                 void (*on_commit)(TXPARAMS void *arg),
+                 void (*on_abort)(TXPARAMS void *arg),
+                 void *arg)
+{
+  if ((on_thread_init != NULL && nb_init_cb >= MAX_CB) ||
+      (on_thread_exit != NULL && nb_exit_cb >= MAX_CB) ||
+      (on_start != NULL && nb_start_cb >= MAX_CB) ||
+      (on_commit != NULL && nb_commit_cb >= MAX_CB) ||
+      (on_abort != NULL && nb_abort_cb >= MAX_CB)) {
+	  PRINT_ERR( "Error: maximum number of modules reached\n");
+    return 0;
+  }
+  // New callback
+  if (on_thread_init != NULL) {
+    init_cb[nb_init_cb].f = on_thread_init;
+    init_cb[nb_init_cb++].arg = arg;
+  }
+  // Delete callback
+  if (on_thread_exit != NULL) {
+    exit_cb[nb_exit_cb].f = on_thread_exit;
+    exit_cb[nb_exit_cb++].arg = arg;
+  }
+  // Start callback
+  if (on_start != NULL) {
+    start_cb[nb_start_cb].f = on_start;
+    start_cb[nb_start_cb++].arg = arg;
+  }
+  // Commit callback
+  if (on_commit != NULL) {
+    commit_cb[nb_commit_cb].f = on_commit;
+    commit_cb[nb_commit_cb++].arg = arg;
+  }
+  // Abort callback
+  if (on_abort != NULL) {
+    abort_cb[nb_abort_cb].f = on_abort;
+    abort_cb[nb_abort_cb++].arg = arg;
+  }
+
+  return 1;
+}
+*/
+/*
+ * Called by the CURRENT thread to load a word-sized value in a unit transaction.
+ */
+stm_word_t stm_unit_load(volatile stm_word_t *addr, stm_word_t *timestamp)
+{
+  volatile stm_word_t *lock;
+  stm_word_t l, l2, value;
+
+  PRINT_DEBUG2("==> stm_unit_load(a=%p)\n", addr);
+
+  /* Get reference to lock */
+  lock = GET_LOCK(addr);
+
+  /* Read lock, value, lock */
+restart:
+#if CM == CM_DELAY && defined(WAIT_COND)
+  mutex_lock(&(locks_mutex[LOCK_IDX(addr)]));
+ 	  l = *lock;
+  mutex_unlock(&(locks_mutex[LOCK_IDX(addr)]));
+#else
+  l = ATOMIC_LOAD_ACQ(lock);
+#endif
+ restart_no_load:
+  if (LOCK_GET_OWNED(l)) {
+    /* Locked: wait until lock is free */
+#ifdef WAIT_YIELD
+    yield();
+#endif /* WAIT_YIELD */
+    goto restart;
+  }
+  /* Not locked */
+  value = ATOMIC_LOAD_ACQ(addr);
+#if CM == CM_DELAY && defined(WAIT_COND)
+  mutex_lock(&(locks_mutex[LOCK_IDX(addr)]));
+  	  l2 = *lock;
+  mutex_unlock(&(locks_mutex[LOCK_IDX(addr)]));
+#else /* CM != CM_DELAY && defined(WAIT_COND) */
+  l2 = ATOMIC_LOAD_ACQ(lock);
+#endif /* CM != CM_DELAY && defined(WAIT_COND) */
+  if (l != l2) {
+    l = l2;
+    goto restart_no_load;
+  }
+
+  if (timestamp != NULL)
+    *timestamp = LOCK_GET_TIMESTAMP(l);
+
+  return value;
+}
+
+/*
+ * Called by the CURRENT thread to store a word-sized value in a unit transaction.
+ */
+int stm_unit_store(volatile stm_word_t *addr, stm_word_t value, stm_word_t *timestamp)
+{
+  return stm_unit_write(addr, value, ~(stm_word_t)0, timestamp);
+}
+
+/*
+ * Called by the CURRENT thread to store part of a word-sized value in a unit transaction.
+ */
+int stm_unit_store2(volatile stm_word_t *addr, stm_word_t value, stm_word_t mask, stm_word_t *timestamp)
+{
+  return stm_unit_write(addr, value, mask, timestamp);
+}
+
+/*
+ * Enable or disable extensions and set upper bound on snapshot.
+ */
+void stm_set_extension(TXPARAMS int enable, stm_word_t *timestamp)
+{
+  TX_GET;
+
+  tx->can_extend = enable;
+  if (timestamp != NULL && *timestamp < tx->end)
+    tx->end = *timestamp;
+}
+
+/*
+ * Get current value of global clock.
+ */
+stm_word_t stm_get_clock()
+{
+  return GET_CLOCK;
+}
+
+/*
+ * Get current transaction descriptor.
+ */
+stm_tx_t *stm_current_tx()
+{
+  return stm_get_tx();
+}
+
+/* ################################################################### *
+ * UNDOCUMENTED STM FUNCTIONS (USE WITH CARE!)
+ * ################################################################### */
+
+#ifdef CONFLICT_TRACKING
+/*
+ * Get thread identifier of other transaction.
+ */
+int stm_get_thread_id(stm_tx_t *tx, pthread_t *id)
+{
+  *id = tx->thread_id;
+  return 1;
+}
+
+/*
+ * Set global conflict callback.
+ */
+int stm_set_conflict_cb(void (*on_conflict)(stm_tx_t *tx1, stm_tx_t *tx2))
+{
+  conflict_cb = on_conflict;
+  return 1;
+}
+#endif /* CONFLICT_TRACKING */
+
+#ifdef IRREVOCABLE_ENABLED
+int stm_set_irrevocable(TXPARAMS int serial)
+{
+# if CM == CM_MODULAR
+  stm_word_t t;
+# endif /* CM == CM_MODULAR */
+  TX_GET;
+
+  /* Are we already in irrevocable mode? */
+  if ((tx->irrevocable & 0x07) == 3) {
+    return 1;
+  }
+
+  if (tx->irrevocable == 0) {
+    /* Acquire irrevocability for the first time */
+    tx->irrevocable = 1 + (serial ? 0x08 : 0);
+    /* Try acquiring global lock */
+    if (irrevocable == 1
+    		|| ATOMIC_CAS_FULL(&irrevocable, 0, 1) != 0) {
+    	//|| ATOMIC_CAS_FULL(&irrevocable, 0, 1) == 0) {
+      /* Transaction will acquire irrevocability after rollback */
+      stm_rollback(tx, STM_ABORT_IRREVOCABLE);
+      return 0;
+    }
+    /* Success: remember we have the lock */
+    tx->irrevocable++;
+    /* Try validating transaction */
+    if (!stm_validate(tx)) {
+      stm_rollback(tx, STM_ABORT_VALIDATE);
+      return 0;
+    }
+# if CM == CM_MODULAR
+   /* We might still abort if we cannot set status (e.g., we are being killed) */
+    t = tx->status;
+    if (GET_STATUS(t) != TX_ACTIVE
+    		|| ATOMIC_CAS_FULL(&tx->status, t, t + (TX_IRREVOCABLE - TX_ACTIVE)) != t) {
+    	//|| (&tx->status, t, t + (TX_IRREVOCABLE - TX_ACTIVE)) == 0) {
+      stm_rollback(tx, STM_ABORT_KILLED);
+      return 0;
+    }
+# endif /* CM == CM_MODULAR */
+    if (serial && tx->w_set.nb_entries != 0) {
+      /* Don't mix transactional and direct accesses => restart with direct accesses */
+      stm_rollback(tx, STM_ABORT_IRREVOCABLE);
+      return 0;
+    }
+  } else if ((tx->irrevocable & 0x07) == 1) {
+    /* Acquire irrevocability after restart (no need to validate) */
+    while (irrevocable == 1
+    		|| ATOMIC_CAS_FULL(&irrevocable, 0, 1) != 0)
+    		//|| ATOMIC_CAS_FULL(&irrevocable, 0, 1) == 0)
+      ;
+    /* Success: remember we have the lock */
+    tx->irrevocable++;
+  }
+  assert((tx->irrevocable & 0x07) == 2);
+
+  /* Are we in serial irrevocable mode? */
+  if ((tx->irrevocable & 0x08) != 0) {
+    /* Stop all other threads */
+    if (stm_quiesce(tx, 1) != 0) {
+      /* Another thread is quiescing and we are active (trying to acquire irrevocability) */
+      assert(serial != -1);
+      stm_rollback(tx, STM_ABORT_IRREVOCABLE);
+      return 0;
+    }
+  }
+
+  /* We are in irrevocable mode */
+  tx->irrevocable++;
+
+  return 1;
+}
+#else /* ! IRREVOCABLE_ENABLED */
+int stm_set_irrevocable(TXPARAMS int serial)
+{
+	PRINT_ERR("Irrevocability is not supported in this configuration\n");
+//  exit(-1);
+  return 1;
+}
+#endif /* ! IRREVOCABLE_ENABLED */
diff --git a/linux-2.6.37.6-antonio/ipc/stm.h b/linux-2.6.37.6-antonio/ipc/stm.h
new file mode 100644
index 0000000..51fe22b
--- /dev/null
+++ b/linux-2.6.37.6-antonio/ipc/stm.h
@@ -0,0 +1,273 @@
+/*
+ * stm.h
+ *
+ *  Created on: Dec 12, 2011
+ *      Author: Antonio Barbalace <antoniob@vt.edu>
+ */
+
+#ifndef STM_H_
+#define STM_H_
+
+#ifdef CONFIG_STM_DEBUG
+# define STM_DEBUG
+#endif /* ! CONFIG_STM_DEBUG */
+#ifdef CONFIG_STM_DEBUG2
+# define STM_DEBUG2
+#endif /* ! CONFIG_STM_DEBUG2 */
+#ifdef CONFIG_STM_DEBUG3
+# define STM_DEBUG3
+#endif /* ! CONFIG_STM_DEBUG3 */
+
+// #undef STM_DEBUG3
+// #undef STM_DEBUG2
+// #undef STM_DEBUG
+//#define STM_DEBUG3
+//#define STM_DEBUG2
+//#define STM_DEBUG
+
+#ifdef STM_DEBUG3
+# ifndef STM_DEBUG2
+#  define STM_DEBUG2
+# endif /* ! DEBUG */
+#endif /* DEBUG2 */
+
+#ifdef STM_DEBUG2
+# ifndef STM_DEBUG
+#  define STM_DEBUG
+# endif /* ! DEBUG */
+#endif /* DEBUG2 */
+
+#ifdef STM_DEBUG
+//# define PRINT_DEBUG(a, args...)			printk("%s: " a , __func__, ##args)
+# define PRINT_DEBUG(...)               trace_printk(__VA_ARGS__)
+#else /* ! DEBUG */
+# define IO_FLUSH
+# define PRINT_DEBUG(...)
+#endif /* ! DEBUG */
+
+#ifdef STM_DEBUG2
+# define PRINT_DEBUG2(...)              PRINT_DEBUG(__VA_ARGS__)
+#else /* ! DEBUG2 */
+# define PRINT_DEBUG2(...)
+#endif /* ! DEBUG2 */
+
+#ifdef STM_DEBUG3
+# define PRINT_DEBUG3(...)              PRINT_DEBUG2(__VA_ARGS__)
+#else /* ! DEBUG3 */
+# define PRINT_DEBUG3(...)
+#endif /* ! DEBUG3 */
+
+#define PRINT_ERR(a, args...)			printk("%s: " a , __func__, ##args)
+#define PERROR(...)						PRINT_ERR(__VA_ARGS__)
+
+#if CM == CM_BACKOFF
+# ifndef MIN_BACKOFF
+#  define MIN_BACKOFF                   (1UL << 2)
+# endif /* MIN_BACKOFF */
+# ifndef MAX_BACKOFF
+#  define MAX_BACKOFF                   (1UL << 31)
+# endif /* MAX_BACKOFF */
+#endif /* CM == CM_BACKOFF */
+
+#if CM == CM_MODULAR
+# define VR_THRESHOLD                   "VR_THRESHOLD"
+# ifndef VR_THRESHOLD_DEFAULT
+#  define VR_THRESHOLD_DEFAULT          3
+# endif /* VR_THRESHOLD_DEFAULT */
+static int vr_threshold;
+#endif /* CM == CM_MODULAR */
+
+#define NO_SIGNAL_HANDLER               "NO_SIGNAL_HANDLER"
+
+#define XSTR(s)                         STR(s)
+#define STR(s)                          #s
+
+/* ################################################################### *
+ * TYPES
+ * ################################################################### */
+
+enum {                                  /* Transaction status */
+  TX_IDLE = 0,
+  TX_ACTIVE = 1,                        /* Lowest bit indicates activity */
+  TX_COMMITTED = (1 << 1),
+  TX_ABORTED = (2 << 1),
+  TX_COMMITTING = (1 << 1) | TX_ACTIVE,
+  TX_ABORTING = (2 << 1) | TX_ACTIVE,
+  TX_KILLED = (3 << 1) | TX_ACTIVE,
+  TX_IRREVOCABLE = 0x08 | TX_ACTIVE     /* Fourth bit indicates irrevocability */
+};
+#define STATUS_BITS                     4
+#define STATUS_MASK                     ((1 << STATUS_BITS) - 1)
+
+#if CM == CM_MODULAR
+# define SET_STATUS(s, v)               ATOMIC_STORE_REL(&(s), ((s) & ~(stm_word_t)STATUS_MASK) | (v))
+# define INC_STATUS_COUNTER(s)          ((((s) >> STATUS_BITS) + 1) << STATUS_BITS)
+# define UPDATE_STATUS(s, v)            ATOMIC_STORE_REL(&(s), INC_STATUS_COUNTER(s) | (v))
+# define GET_STATUS(s)                  ((s) & STATUS_MASK)
+# define GET_STATUS_COUNTER(s)          ((s) >> STATUS_BITS)
+#else /* CM != CM_MODULAR */
+# define SET_STATUS(s, v)               ((s) = (v))
+# define UPDATE_STATUS(s, v)            ((s) = (v))
+# define GET_STATUS(s)                  ((s))
+#endif /* CM != CM_MODULAR */
+#define IS_ACTIVE(s)                    ((GET_STATUS(s) & 0x01) == TX_ACTIVE)
+
+#include <linux/stm_types.h>
+
+static int nb_specific = 0;             /* Number of specific slots used (<= MAX_SPECIFIC) */
+
+static int initialized = 0;             /* Has the library been initialized? */
+
+#ifdef IRREVOCABLE_ENABLED
+static volatile stm_word_t irrevocable = 0;
+#endif /* IRREVOCABLE_ENABLED */
+
+/* ################################################################### *
+ * CALLBACKS
+ * ################################################################### */
+/* functionality disabled for kernel portability (not easy in kernel (at least we can provide a list of in kernel notifiers
+#define MAX_CB                          16
+
+// Declare as static arrays (vs. lists) to improve cache locality
+static cb_entry_t init_cb[MAX_CB];      // Init thread callbacks
+static cb_entry_t exit_cb[MAX_CB];      // Exit thread callbacks
+static cb_entry_t start_cb[MAX_CB];     // Start callbacks
+static cb_entry_t commit_cb[MAX_CB];    // Commit callbacks
+static cb_entry_t abort_cb[MAX_CB];     // Abort callbacks
+*/
+/*
+static int nb_init_cb = 0;
+static int nb_exit_cb = 0;
+static int nb_start_cb = 0;
+static int nb_commit_cb = 0;
+static int nb_abort_cb = 0;
+*/
+#ifdef CONFLICT_TRACKING
+static void (*conflict_cb)(stm_tx_t *, stm_tx_t *) = NULL;
+#endif /* CONFLICT_TRACKING */
+
+/* ################################################################### *
+ * LOCKS
+ * ################################################################### */
+
+/*
+ * A lock is a unsigned int of the size of a pointer.
+ * The LSB is the lock bit. If it is set, this means:
+ * - At least some covered memory addresses is being written.
+ * - Write-back (ETL): all bits of the lock apart from the lock bit form
+ *   a pointer that points to the write log entry holding the new
+ *   value. Multiple values covered by the same log entry and orginized
+ *   in a linked list in the write log.
+ * - Write-through and write-back (CTL): all bits of the lock apart from
+ *   the lock bit form a pointer that points to the transaction
+ *   descriptor containing the write-set.
+ * If the lock bit is not set, then:
+ * - All covered memory addresses contain consistent values.
+ * - Write-back (ETL and CTL): all bits of the lock besides the lock bit
+ *   contain a version number (timestamp).
+ * - Write-through: all bits of the lock besides the lock bit contain a
+ *   version number.
+ *   - The high order bits contain the commit time.
+ *   - The low order bits contain an incarnation number (incremented
+ *     upon abort while writing the covered memory addresses).
+ * When visible reads are enabled, two bits are used as read and write
+ * locks. A read-locked address can be read by an invisible reader.
+ */
+
+#if CM == CM_MODULAR
+# define OWNED_BITS                     2                   /* 2 bits */
+# define WRITE_MASK                     0x01                /* 1 bit */
+# define READ_MASK                      0x02                /* 1 bit */
+# define OWNED_MASK                     (WRITE_MASK | READ_MASK)
+#else /* CM != CM_MODULAR */
+# define OWNED_BITS                     1                   /* 1 bit */
+# define WRITE_MASK                     0x01                /* 1 bit */
+# define OWNED_MASK                     (WRITE_MASK)
+#endif /* CM != CM_MODULAR */
+#if DESIGN == WRITE_THROUGH
+# define INCARNATION_BITS               3                   /* 3 bits */
+# define INCARNATION_MAX                ((1 << INCARNATION_BITS) - 1)
+# define INCARNATION_MASK               (INCARNATION_MAX << 1)
+# define LOCK_BITS                      (OWNED_BITS + INCARNATION_BITS)
+#else /* DESIGN != WRITE_THROUGH */
+# define LOCK_BITS                      (OWNED_BITS)
+#endif /* DESIGN != WRITE_THROUGH */
+#define MAX_THREADS                     8192                /* Upper bound (large enough) */
+#define VERSION_MAX                     ((~(stm_word_t)0 >> LOCK_BITS) - MAX_THREADS)
+#define LOCK_GET_OWNED(l)               (l & OWNED_MASK)
+#define LOCK_GET_WRITE(l)               (l & WRITE_MASK)
+#define LOCK_SET_ADDR_WRITE(a)          (a | WRITE_MASK)    /* WRITE bit set */
+#define LOCK_GET_ADDR(l)                (l & ~(stm_word_t)OWNED_MASK)
+#if CM == CM_MODULAR
+# define LOCK_GET_READ(l)               (l & READ_MASK)
+# define LOCK_SET_ADDR_READ(a)          (a | READ_MASK)     /* READ bit set */
+# define LOCK_UPGRADE(l)                (l | WRITE_MASK)
+#endif /* CM == CM_MODULAR */
+#if DESIGN == WRITE_THROUGH
+# define LOCK_GET_TIMESTAMP(l)          (l >> (1 + INCARNATION_BITS))
+# define LOCK_SET_TIMESTAMP(t)          (t << (1 + INCARNATION_BITS))
+# define LOCK_GET_INCARNATION(l)        ((l & INCARNATION_MASK) >> 1)
+# define LOCK_SET_INCARNATION(i)        (i << 1)            /* OWNED bit not set */
+# define LOCK_UPD_INCARNATION(l, i)     ((l & ~(stm_word_t)(INCARNATION_MASK | OWNED_MASK)) | LOCK_SET_INCARNATION(i))
+#else /* DESIGN != WRITE_THROUGH */
+# define LOCK_GET_TIMESTAMP(l)          (l >> OWNED_BITS)   /* Logical shift (unsigned) */
+# define LOCK_SET_TIMESTAMP(t)          (t << OWNED_BITS)   /* OWNED bits not set */
+#endif /* DESIGN != WRITE_THROUGH */
+#define LOCK_UNIT                       (~(stm_word_t)0)
+
+/*
+ * We use the very same hash functions as TL2 for degenerate Bloom
+ * filters on 32 bits.
+ */
+#ifdef USE_BLOOM_FILTER
+# define FILTER_HASH(a)                 (((stm_word_t)a >> 2) ^ ((stm_word_t)a >> 5))
+# define FILTER_BITS(a)                 (1 << (FILTER_HASH(a) & 0x1F))
+#endif /* USE_BLOOM_FILTER */
+
+/*
+ * We use an array of locks and hash the address to find the location of the lock.
+ * We try to avoid collisions as much as possible (two addresses covered by the same lock).
+ */
+#define LOCK_ARRAY_SIZE                 (1 << LOCK_ARRAY_LOG_SIZE)
+#define LOCK_MASK                       (LOCK_ARRAY_SIZE - 1)
+#define LOCK_SHIFT                      (((sizeof(stm_word_t) == 4) ? 2 : 3) + LOCK_SHIFT_EXTRA)
+#define LOCK_IDX(a)                     (((stm_word_t)(a) >> LOCK_SHIFT) & LOCK_MASK)
+#ifdef LOCK_IDX_SWAP
+# if LOCK_ARRAY_LOG_SIZE < 16
+#  error "LOCK_IDX_SWAP requires LOCK_ARRAY_LOG_SIZE to be at least 16"
+# endif /* LOCK_ARRAY_LOG_SIZE < 16 */
+# define GET_LOCK(a)                    (locks + lock_idx_swap(LOCK_IDX(a)))
+#else /* ! LOCK_IDX_SWAP */
+# define GET_LOCK(a)                    (locks + LOCK_IDX(a))
+#endif /* ! LOCK_IDX_SWAP */
+
+static volatile stm_word_t locks[LOCK_ARRAY_SIZE];
+
+# ifdef WAIT_COND
+  struct mutex locks_mutex[LOCK_ARRAY_SIZE];			/* Mutex to support CM_DELAY*/
+  wait_queue_head_t locks_cond[LOCK_ARRAY_SIZE];			/* Conditional Variable to to support CM_DELAY*/
+# endif /* WAIT_COND */
+
+/* ################################################################### *
+ * CLOCK
+ * ################################################################### */
+
+#ifdef CLOCK_IN_CACHE_LINE
+/* At least twice a cache line (512 bytes to be on the safe side) */
+static volatile stm_word_t gclock[1024 / sizeof(stm_word_t)];
+# define CLOCK                          (gclock[512 / sizeof(stm_word_t)])
+#else /* ! CLOCK_IN_CACHE_LINE */
+static volatile stm_word_t gclock;
+# define CLOCK                          (gclock)
+#endif /* ! CLOCK_IN_CACHE_LINE */
+
+#define GET_CLOCK                       (ATOMIC_LOAD_ACQ(&CLOCK))
+#define FETCH_INC_CLOCK                 (ATOMIC_FETCH_INC_FULL(&CLOCK))
+
+#endif /* STM_H_ */
+
+
+#define ROLLBACK_REQUESTED	-1
+#define ROLLBACK_NO_RETRY	0
+#define SUCCESS				1
+
diff --git a/linux-2.6.37.6-antonio/ipc/stm.readme b/linux-2.6.37.6-antonio/ipc/stm.readme
new file mode 100644
index 0000000..6835403
--- /dev/null
+++ b/linux-2.6.37.6-antonio/ipc/stm.readme
@@ -0,0 +1,50 @@
+VT RTSL Linux TM  
+
+release 0.3 (still buggy) 
+? april 2012 - Antonio Barbalace
+-------------------------------------------------------------------------------
+added support to proc, a lot of improvements and scheduling features were added.
+preemption avoidance with bonus, migration avoidance.
+retry from user space is still not working, todo.
+
+
+
+release 0.2 (first attempt.. much more work is required for a release) 
+? feb 2012 - Antonio Barbalace
+-------------------------------------------------------------------------------
+support stat and param syscalls in krn/user; add mod_stat to kernel space;
+all statistics are collected in kernel space (per thread and global statistics)
+this choice have a lot of sense all statistics are integrated in kernel.
+We can let user space application to register hook to each event as it is in
+TinySTM. This is ok for malloc, but also malloc cam be directly integrated (to
+be decided)..
+mod_log will be supported with ftrace
+
+
+
+release 0.1
+31 jan 2012 - Antonio Barbalace
+-------------------------------------------------------------------------------
+
+This first release does not support system wide (inter process) stm.
+Neither it guarentees support for different process running the stm layer
+concurrently (due to the fact that stm addresses are not grupped by process
+address space).
+The code base from which we started is the open-source TinySTM.
+We are trying to getting around this code in the future versions of our
+implementation. Not all TinySTM functionality are implemented.
+
+TODO
+- user space access from kernel flushing reads and writes
+- add kernel configuration options to kernel configuration
+- group r/w entries per address space ( search for thread in the same process in
+  quiesce support )
+- enable inter process stm (shared memory support)
+- improve quiescence groupping thread with common read/write set (new
+  algorithms are needed)
+- add EPOCH_GC (in user space maybe)
+- add malloc/free support in user space
+- export statistics/parameters and other data from /proc/thread
+- merge local and internal stats
+- move all stats code in one unique file
+
diff --git a/linux-2.6.37.6-antonio/ipc/stm_atomic.h b/linux-2.6.37.6-antonio/ipc/stm_atomic.h
new file mode 100644
index 0000000..61fbae0
--- /dev/null
+++ b/linux-2.6.37.6-antonio/ipc/stm_atomic.h
@@ -0,0 +1,107 @@
+/*
+ * File:
+ *   atomic.h
+ * Author(s):
+ *   Pascal Felber <pascal.felber@unine.ch> - original version
+ *   Antonio Barbalace <antoniob@vt.edu> - Linux Kernel porting
+ * Description:
+ *   Atomic operations.
+ *
+ * Copyright (c) 2007-2009.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, version 2
+ * of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef _ATOMIC_H_
+# define _ATOMIC_H_
+
+
+//# include <atomic_ops.h> //previous version
+//the Linux atomic library makes atomic operations on integers (atomic is 32bit
+//in asm/atomic.h) 64bit support is provided by asm/atomic64_32.h and asm/atomic64_64.h
+//linux/atomic.h includes asm/atomic.h that includes atomic64_32.h or atomic64_64.h
+#include <linux/atomic.h> //Linux kernel version
+
+//memory barriers
+//this is platform specific
+#include <asm/system.h> //Linux kernel version
+//this is more compiler specific, compiler will find the best match (barrier)
+//#include <linux/compiler.h> //Linux kernel version
+
+//#define AO_t uintptr_t
+//typedef AO_t atomic_t;
+
+
+# ifdef NO_AO
+/* Use only for testing purposes (single thread benchmarks) */
+
+// 8/16/32/64 BITS
+#  define ATOMIC_CAS_FULL(a, e, v)      (*(a) = (v), 1)
+#  define ATOMIC_FETCH_INC_FULL(a)      ((*(a))++)
+#  define ATOMIC_FETCH_DEC_FULL(a)      ((*(a))--)
+#  define ATOMIC_FETCH_ADD_FULL(a, v)   ((*(a)) += (v))
+#  define ATOMIC_LOAD_ACQ(a)            (*(a))
+#  define ATOMIC_LOAD(a)                (*(a))
+#  define ATOMIC_STORE_REL(a, v)        (*(a) = (v))
+#  define ATOMIC_STORE(a, v)            (*(a) = (v))
+#  define ATOMIC_MB_READ                /* Nothing */
+#  define ATOMIC_MB_WRITE               /* Nothing */
+#  define ATOMIC_MB_FULL                /* Nothing */
+# else /* ! NO_AO */
+/* the following implementation is a Linux kernel wrapper */
+
+#ifndef CONFIG_64BIT
+// 32 BITS
+//AO_compare_and_swap_full(volatile AO_t *addr, AO_t old, AO_t new_val)
+//#  define ATOMIC_CAS_FULL(a, e, v)      (AO_compare_and_swap_full((volatile AO_t *)(a), (AO_t)(e), (AO_t)(v)))
+#  define ATOMIC_CAS_FULL(a, e, v)      (atomic_cmpxchg((atomic_t *)(a),(int)(e),(int)(v)))
+//AO_fetch_and_add_full (volatile AO_t *p, AO_t incr)
+//#  define AO_fetch_and_add1_full(addr) AO_fetch_and_add_full(addr,1)
+#  define ATOMIC_FETCH_INC_FULL(a)      (atomic_inc_return((atomic_t *)(a)))
+//#  define ATOMIC_FETCH_DEC_FULL(a)      (AO_fetch_and_sub1_full((volatile AO_t *)(a)))
+#  define ATOMIC_FETCH_DEC_FULL(a)      (atomic_dec_return((atomic_t *)(a)))
+//#  define ATOMIC_FETCH_ADD_FULL(a, v)   (AO_fetch_and_add_full((volatile AO_t *)(a), (AO_t)(v)))
+#  define ATOMIC_FETCH_ADD_FULL(a, v)   (atomic_add_return((int)(v),(atomic_t *)(a)))
+//#   define ATOMIC_LOAD(a)               (*((volatile AO_t *)(a)))
+#  define ATOMIC_LOAD(a)               atomic_read((atomic_t *) a)
+//#   define ATOMIC_STORE(a, v)           (*((volatile AO_t *)(a)) = (AO_t)(v))
+#  define ATOMIC_STORE(a, v)           atomic_set((atomic_t *) a, v)
+
+#else /* CONFIG_64BIT */
+// 64 BITS
+#  define ATOMIC_CAS_FULL(a, e, v)      (atomic64_cmpxchg((atomic64_t *)(a),(long)(e),(long)(v)))
+#  define ATOMIC_FETCH_INC_FULL(a)      (atomic64_inc_return((atomic64_t *)(a)))
+#  define ATOMIC_FETCH_DEC_FULL(a)      (atomic64_dec_return((atomic64_t *)(a)))
+#  define ATOMIC_FETCH_ADD_FULL(a, v)   (atomic64_add_return((long)(v),(atomic64_t *)(a)))
+#  define ATOMIC_LOAD(a)               atomic64_read((atomic64_t *) a)
+#  define ATOMIC_STORE(a, v)           atomic64_set((atomic64_t *) a, v)
+
+#endif /* CONFIG_64BIT */
+
+//#  define ATOMIC_MB_READ               AO_nop_read()
+#  define ATOMIC_MB_READ               smp_rmb()
+//#  define ATOMIC_MB_READ               AO_nop_write()
+#  define ATOMIC_MB_WRITE              smp_wmb()
+//#  define ATOMIC_MB_FULL               AO_nop_full()
+#  define ATOMIC_MB_FULL               smp_mb()
+
+#ifndef CONFIG_64BIT
+#   define ATOMIC_LOAD_ACQ(a)           ({int i = ATOMIC_LOAD(a); ATOMIC_MB_READ; i;})
+#else
+#   define ATOMIC_LOAD_ACQ(a)           ({long i = ATOMIC_LOAD(a); ATOMIC_MB_READ; i;})
+#endif
+#   define ATOMIC_STORE_REL(a, v)       ({ATOMIC_MB_WRITE; ATOMIC_STORE(a, v);})
+
+//TODO 64bit version
+
+# endif /* ! NO_AO */
+
+#endif /* _ATOMIC_H_ */
diff --git a/linux-2.6.37.6-antonio/ipc/stm_cm.h b/linux-2.6.37.6-antonio/ipc/stm_cm.h
new file mode 100644
index 0000000..e01e7a9
--- /dev/null
+++ b/linux-2.6.37.6-antonio/ipc/stm_cm.h
@@ -0,0 +1,46 @@
+/*
+ * stm_cm.h
+ *
+ *  Created on: Dec 13, 2011
+ *      Author: root
+ */
+
+#ifndef STM_CM_H_
+#define STM_CM_H_
+
+
+
+
+
+
+
+
+static const char *cm_names[] = {
+  /* 0 */ "SUICIDE",
+  /* 1 */ "DELAY",
+  /* 2 */ "BACKOFF",
+  /* 3 */ "MODULAR"
+};
+
+
+
+#if DESIGN != WRITE_BACK_ETL && CM == CM_MODULAR
+# error "MODULAR contention manager can only be used with WB-ETL design"
+#endif /* DESIGN != WRITE_BACK_ETL && CM == CM_MODULAR */
+
+#if defined(CONFLICT_TRACKING) && ! defined(EPOCH_GC)
+# error "CONFLICT_TRACKING requires EPOCH_GC"
+#endif /* defined(CONFLICT_TRACKING) && ! defined(EPOCH_GC) */
+
+#if CM == CM_MODULAR && ! defined(EPOCH_GC)
+# error "MODULAR contention manager requires EPOCH_GC"
+#endif /* CM == CM_MODULAR && ! defined(EPOCH_GC) */
+
+#if defined(READ_LOCKED_DATA) && CM != CM_MODULAR
+# error "READ_LOCKED_DATA can only be used with MODULAR contention manager"
+#endif /* defined(READ_LOCKED_DATA) && CM != CM_MODULAR */
+
+
+
+
+#endif /* STM_CM_H_ */
diff --git a/linux-2.6.37.6-antonio/ipc/stm_cm_modular.h b/linux-2.6.37.6-antonio/ipc/stm_cm_modular.h
new file mode 100644
index 0000000..5ee1b4c
--- /dev/null
+++ b/linux-2.6.37.6-antonio/ipc/stm_cm_modular.h
@@ -0,0 +1,82 @@
+/*
+ * stm_cm_modular.h
+ *
+ *  Created on: Jan 4, 2012
+ *      Author: root
+ */
+
+#ifndef STM_CM_MODULAR_H_
+#define STM_CM_MODULAR_H_
+
+# define KILL_SELF                      0x00
+# define KILL_OTHER                     0x01
+# define DELAY_RESTART                  0x04
+
+# define RR_CONFLICT                    0x00
+# define RW_CONFLICT                    0x01
+# define WR_CONFLICT                    0x02
+# define WW_CONFLICT                    0x03
+
+static int (*contention_manager)(stm_tx_t *, stm_tx_t *, int) = NULL;
+
+/*
+ * Kill other.
+ */
+int cm_aggressive(struct stm_tx *me, struct stm_tx *other, int conflict)
+{
+  return KILL_OTHER;
+}
+
+/*
+ * Kill self.
+ */
+int cm_suicide(struct stm_tx *me, struct stm_tx *other, int conflict)
+{
+  return KILL_SELF;
+}
+
+/*
+ * Kill self and wait before restart.
+ */
+int cm_delay(struct stm_tx *me, struct stm_tx *other, int conflict)
+{
+  return KILL_SELF | DELAY_RESTART;
+}
+
+/*
+ * Oldest transaction has priority.
+ */
+int cm_timestamp(struct stm_tx *me, struct stm_tx *other, int conflict)
+{
+  if (me->timestamp < other->timestamp)
+    return KILL_OTHER;
+  if (me->timestamp == other->timestamp && (uintptr_t)me < (uintptr_t)other)
+    return KILL_OTHER;
+  return KILL_SELF | DELAY_RESTART;
+}
+
+/*
+ * Transaction with more work done has priority.
+ */
+int cm_karma(struct stm_tx *me, struct stm_tx *other, int conflict)
+{
+  if ((me->w_set.nb_entries << 1) + me->r_set.nb_entries < (other->w_set.nb_entries << 1) + other->r_set.nb_entries)
+    return KILL_OTHER;
+  if (((me->w_set.nb_entries << 1) + me->r_set.nb_entries == (other->w_set.nb_entries << 1) + other->r_set.nb_entries) && (uintptr_t)me < (uintptr_t)other )
+    return KILL_OTHER;
+  return KILL_SELF;
+}
+
+struct {
+  const char *name;
+  int (*f)(stm_tx_t *, stm_tx_t *, int);
+} cms[] = {
+  { "aggressive", cm_aggressive },
+  { "suicide", cm_suicide },
+  { "delay", cm_delay },
+  { "timestamp", cm_timestamp },
+  { "karma", cm_karma },
+  { NULL, NULL }
+};
+
+#endif /* STM_CM_MODULAR_H_ */
diff --git a/linux-2.6.37.6-antonio/ipc/stm_design.h b/linux-2.6.37.6-antonio/ipc/stm_design.h
new file mode 100644
index 0000000..e111208
--- /dev/null
+++ b/linux-2.6.37.6-antonio/ipc/stm_design.h
@@ -0,0 +1,26 @@
+/*
+ * stm_design.h
+ *
+ *  Created on: Dec 13, 2011
+ *      Author: root
+ */
+
+#ifndef STM_DESIGN_H_
+#define STM_DESIGN_H_
+
+
+
+
+
+
+static const char *design_names[] = {
+  /* 0 */ "WRITE-BACK (ETL)",
+  /* 1 */ "WRITE-BACK (CTL)",
+  /* 2 */ "WRITE-THROUGH"
+};
+
+
+
+
+
+#endif /* STM_DESIGN_H_ */
diff --git a/linux-2.6.37.6-antonio/ipc/stm_mod_stats.h b/linux-2.6.37.6-antonio/ipc/stm_mod_stats.h
new file mode 100644
index 0000000..3a82c32
--- /dev/null
+++ b/linux-2.6.37.6-antonio/ipc/stm_mod_stats.h
@@ -0,0 +1,230 @@
+/*
+ * stm_mod_stats.c
+ *
+ *  Created on: Jan 17, 2012
+ *      Author: root
+ */
+
+
+/* WAS
+ * File:
+ *   mod_stats.c
+ * Author(s):
+ *   Pascal Felber <pascal.felber@unine.ch>
+ * Description:
+ *   Module for gathering global statistics about transactions.
+ *
+ * Copyright (c) 2007-2009.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, version 2
+ * of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+//#include <assert.h>
+#include <linux/limits.h>
+//#include <stdio.h>
+//#include <string.h>
+
+//#include "mod_stats.h"
+
+//#include "atomic.h"
+//#include "stm.h"
+
+
+
+//static int mod_stats_key;
+static int mod_stats_initialized = 0;
+
+static mod_stats_data_t mod_stats_global = { 0, 0, ULONG_MAX, 0, 0, 0 };
+
+/* ################################################################### *
+ * GET FUNCTIONS
+ * ################################################################### */
+
+/*
+ * Return aggregate statistics about transactions.
+ */
+int stm_get_global_stats(const char *name, void *val)
+{
+  /*if (!mod_stats_initialized) {
+    fprintf(stderr, "Module mod_stats not initialized\n");
+    exit(1);
+  }
+*/
+  if (strcmp("global_nb_commits", name) == 0) {
+    *(unsigned long *)val = mod_stats_global.commits;
+    return 1;
+  }
+  if (strcmp("global_nb_aborts", name) == 0) {
+    *(unsigned long *)val = mod_stats_global.retries_acc;
+    return 1;
+  }
+  if (strcmp("global_max_retries", name) == 0) {
+    *(unsigned long *)val = mod_stats_global.retries_max;
+    return 1;
+  }
+
+  return 0;
+}
+
+/*
+ * Return statistics about current thread.
+ */
+int stm_get_local_stats(TXPARAMS const char *name, void *val)
+{
+	TX_GET;
+  mod_stats_data_t *stats = &(tx->mod_stats);
+
+/*  if (!mod_stats_initialized) {
+    fprintf(stderr, "Module mod_stats not initialized\n");
+    exit(1);
+  }*/
+
+//  stats = (mod_stats_data_t *)stm_get_specific(TXARGS mod_stats_key);
+//  assert(stats != NULL);
+
+  if (strcmp("nb_commits", name) == 0) {
+    *(unsigned long *)val = stats->commits;
+    return 1;
+  }
+  if (strcmp("nb_aborts", name) == 0) {
+    *(unsigned long *)val = stats->retries_acc;
+    return 1;
+  }
+  if (strcmp("nb_retries_avg", name) == 0) {
+    *(unsigned long *)val = (stats->retries_acc / stats->retries_cnt);
+    return 1;
+  }
+  if (strcmp("nb_retries_min", name) == 0) {
+    *(unsigned long *)val = stats->retries_min;
+    return 1;
+  }
+  if (strcmp("nb_retries_max", name) == 0) {
+    *(unsigned long *)val = stats->retries_max;
+    return 1;
+  }
+
+  return 0;
+}
+
+/* ################################################################### *
+ * Hook FUNCTIONS
+ * ################################################################### */
+
+/*
+ * Called upon thread creation.
+ */
+static inline void mod_stats_on_thread_init(stm_tx_t * tx)
+{
+	//TX_GET; not working in this context!!!
+  mod_stats_data_t *stats = &(tx->mod_stats);
+
+// stats are allocated in the transaction descriptor
+/*  if ((stats = (mod_stats_data_t *)malloc(sizeof(mod_stats_data_t))) == NULL) {
+    perror("malloc");
+    exit(1);
+  }
+*/  stats->commits = 0;
+  stats->retries = 0;
+  stats->retries_acc = 0;
+  stats->retries_cnt = 0;
+  stats->retries_min = ULONG_MAX;
+  stats->retries_max = 0;
+
+//  stm_set_specific(TXARGS mod_stats_key, stats);
+}
+
+/*
+ * Called upon thread deletion.
+ */
+static void mod_stats_on_thread_exit(void)
+{
+	TX_GET;
+  mod_stats_data_t *stats = &(tx->mod_stats);
+
+  unsigned long max, min;
+
+//  stats = (mod_stats_data_t *)stm_get_specific(TXARGS mod_stats_key);
+//  assert(stats != NULL);
+
+  ATOMIC_FETCH_ADD_FULL(&mod_stats_global.commits, stats->commits);
+  ATOMIC_FETCH_ADD_FULL(&mod_stats_global.retries_cnt, stats->retries_cnt);
+  ATOMIC_FETCH_ADD_FULL(&mod_stats_global.retries_acc, stats->retries_acc);
+retry_max:
+  max = ATOMIC_LOAD(&mod_stats_global.retries_max);
+  if (stats->retries_max > max) {
+    if (ATOMIC_CAS_FULL(&mod_stats_global.retries_max, max, stats->retries_max) == 0)
+      goto retry_max;
+  }
+retry_min:
+  min = ATOMIC_LOAD(&mod_stats_global.retries_min);
+  if (stats->retries_min < min) {
+    if (ATOMIC_CAS_FULL(&mod_stats_global.retries_min, min, stats->retries_min) == 0)
+      goto retry_min;
+  }
+
+//  free(stats);
+}
+
+/*
+ * Called upon transaction commit.
+ */
+static void mod_stats_on_commit(void)
+{
+	TX_GET;
+  mod_stats_data_t *stats = &(tx->mod_stats);
+
+
+//  stats = (mod_stats_data_t *)stm_get_specific(TXARGS mod_stats_key);
+//  assert(stats != NULL);
+
+  stats->commits++;
+  stats->retries_acc += stats->retries;
+  stats->retries_cnt++;
+  if (stats->retries_min > stats->retries)
+    stats->retries_min = stats->retries;
+  if (stats->retries_max < stats->retries)
+    stats->retries_max = stats->retries;
+  stats->retries = 0;
+}
+
+/*
+ * Called upon transaction abort.
+ */
+static void mod_stats_on_abort(void)
+{
+	TX_GET;
+  mod_stats_data_t *stats = &(tx->mod_stats);
+
+
+//  stats = (mod_stats_data_t *)stm_get_specific(TXARGS mod_stats_key);
+//  assert(stats != NULL);
+
+  stats->retries++;
+}
+
+/*
+ * Initialize module.
+ */
+/*
+void mod_stats_init()
+{
+  if (mod_stats_initialized)
+    return;
+
+  stm_register(mod_stats_on_thread_init, mod_stats_on_thread_exit, NULL, mod_stats_on_commit, mod_stats_on_abort, NULL);
+  mod_stats_key = stm_create_specific();
+  if (mod_stats_key < 0) {
+    fprintf(stderr, "Cannot create specific key\n");
+    exit(1);
+  }
+  mod_stats_initialized = 1;
+}
+*/
diff --git a/linux-2.6.37.6-antonio/ipc/stm_quiesce.h b/linux-2.6.37.6-antonio/ipc/stm_quiesce.h
new file mode 100644
index 0000000..2a27b1a
--- /dev/null
+++ b/linux-2.6.37.6-antonio/ipc/stm_quiesce.h
@@ -0,0 +1,331 @@
+/*
+ * stm_quiesce.h
+ *
+ *  Created on: Jan 4, 2012
+ *      Author: root
+ */
+
+#ifndef STM_QUIESCE_H_
+#define STM_QUIESCE_H_
+
+// this is something similar to the global run queue lock
+//a list of threads are managed
+
+// RFC from Chris Simmonds
+#include <linux/wait.h>
+#include <linux/mutex.h>
+static void cond_wait (wait_queue_head_t *wq, struct mutex *mutex)
+{
+	DEFINE_WAIT(__wait);
+
+	prepare_to_wait(wq, &__wait, TASK_UNINTERRUPTIBLE);
+	mutex_unlock (mutex);
+	schedule();
+	mutex_lock (mutex);
+	finish_wait(wq, &__wait);
+}
+#define cond_signal(wq) wake_up(wq)
+#define cond_broadcast(wq) wake_up_all(wq)
+
+/**
+ * cond_wait_interruptible - wait for a condition variable
+ * @wq: the wait queue to wait on
+ * @mutex: a locked mutex
+ *
+ * Safely put the calling task into an interruptible sleep on the
+ * wait queue then unlock the mutex. Re-acquire the mutex after waking up
+ */
+int cond_wait_interruptible (wait_queue_head_t *wq, struct mutex *mutex)
+{
+ int ret = 0;
+ DEFINE_WAIT(__wait);
+
+ prepare_to_wait(wq, &__wait, TASK_INTERRUPTIBLE);
+ mutex_unlock (mutex);
+ if (signal_pending(current))
+ ret = -ERESTARTSYS;
+ else
+ schedule();
+ mutex_lock (mutex);
+ finish_wait(wq, &__wait);
+ return ret;
+}
+#define cond_signal_interruptible(wq) wake_up_interruptible(wq)
+#define cond_broadcast_interruptible(wq) wake_up_interruptible_all(wq)
+
+/**
+ * cond_wait_spinlock - wait for a condition variable
+ * @wq: the wait queue to wait on
+ * @sl: a locked spinlock
+ *
+ * Safely put the calling task into an interruptible sleep on the
+ * wait queue then unlock the spinlock. Re-acquire after waking up
+ */
+void cond_wait_spinlock (wait_queue_head_t *wq, spinlock_t *sl)
+{
+ DEFINE_WAIT(__wait);
+
+ prepare_to_wait(wq, &__wait, TASK_UNINTERRUPTIBLE);
+ spin_unlock (sl);
+ schedule();
+ spin_lock (sl);
+ finish_wait(wq, &__wait);
+}
+
+/**
+ * cond_wait_spinlock_irq - wait for a condition variable
+ * @wq: the wait queue to wait on
+ * @sl: a locked spinlock
+ *
+ * Safely put the calling task into an interruptible sleep on the
+ * wait queue then unlock the spinlock and enable irqs. Re-acquire
+ * spinlock and disable irqs after waking up
+ */
+void cond_wait_spinlock_irq (wait_queue_head_t *wq, spinlock_t *sl)
+{
+ DEFINE_WAIT(__wait);
+
+ prepare_to_wait(wq, &__wait, TASK_UNINTERRUPTIBLE);
+ spin_unlock_irq (sl);
+ schedule();
+ spin_lock_irq (sl);
+ finish_wait(wq, &__wait);
+}
+
+//WAS pthread_mutex_t quiesce_mutex;          /* Mutex to support quiescence */
+struct mutex quiesce_mutex;
+//WAS pthread_cond_t quiesce_cond;            /* Condition variable to support quiescence */
+wait_queue_head_t quiesce_cond;
+
+volatile stm_word_t quiesce;            /* Prevent threads from entering transactions upon quiescence */
+volatile stm_word_t threads_count;      /* Number of active threads */
+stm_tx_t *threads;                      /* Head of linked list of threads */
+
+/*
+ * Initialize quiescence support.
+ */
+static inline void stm_quiesce_init(void)
+{
+  PRINT_DEBUG("==> stm_quiesce_init()\n");
+
+/*  if (pthread_mutex_init(&quiesce_mutex, NULL) != 0) {
+    PRINT_ERR( "Error creating mutex\n");
+    exit(1);
+  }
+*/ //in kernel the mutex will be init in unlocked state (void return)
+  mutex_init(&quiesce_mutex);
+
+/*
+  if (pthread_cond_init(&quiesce_cond, NULL) != 0) {
+    PRINT_ERR( "Error creating condition variable\n");
+    exit(1);
+  }
+*/ //in kernel wait queue
+  init_waitqueue_head(&quiesce_cond);
+
+  quiesce = 0;
+  threads_count = 0;
+  threads = NULL;
+}
+
+/*
+ * Clean up quiescence support.
+ */
+static inline void stm_quiesce_exit(void)
+{
+  PRINT_DEBUG("==> stm_quiesce_exit()\n");
+
+// WAS  thread_cond_destroy(&quiesce_cond);
+  // TODOdestroy wait queue
+
+   // WASpthread_mutex_destroy(&quiesce_mutex);
+  mutex_destroy(&quiesce_mutex);
+}
+
+/*
+ * Called by each thread upon initialization for quiescence support.
+ */
+static inline void stm_quiesce_enter_thread(stm_tx_t *tx)
+{
+  PRINT_DEBUG("==> stm_quiesce_enter_thread(%p)\n", tx);
+
+// WAS  pthread_mutex_lock(&quiesce_mutex);
+  mutex_lock(&quiesce_mutex);
+  /* Add new descriptor at head of list */
+  tx->next = threads;
+  threads = tx;
+  threads_count++;
+//WAS  pthread_mutex_unlock(&quiesce_mutex);
+  mutex_unlock(&quiesce_mutex);
+
+}
+
+/*
+ * Called by each thread upon exit for quiescence support.
+ */
+static inline void stm_quiesce_exit_thread(stm_tx_t *tx)
+{
+  stm_tx_t *t, *p;
+
+  PRINT_DEBUG("==> stm_quiesce_exit_thread(%p)\n", tx);
+
+  /* Can only be called if non-active */
+  assert(!IS_ACTIVE(tx->status));
+
+//WAS pthread_mutex_lock(&quiesce_mutex);
+  mutex_lock(&quiesce_mutex);
+  /* Remove descriptor from list */
+  p = NULL;
+  t = threads;
+  while (t != tx) {
+    assert(t != NULL);
+    p = t;
+    t = t->next;
+  }
+  if (p == NULL)
+    threads = t->next;
+  else
+    p->next = t->next;
+  threads_count--;
+  if (quiesce) {
+    /* Wake up someone in case other threads are waiting for us */
+//WAS   pthread_cond_signal(&quiesce_cond);
+	  cond_signal(&quiesce_cond);
+  }
+//WAS  pthread_mutex_unlock(&quiesce_mutex);
+  mutex_unlock(&quiesce_mutex);
+}
+
+/*
+ * Wait for all transactions to be block on a barrier.
+ */
+static inline void stm_quiesce_barrier(stm_tx_t *tx, void (*f)(void *), void *arg)
+{
+  PRINT_DEBUG("==> stm_quiesce_barrier()\n");
+
+  /* Can only be called if non-active */
+  assert(tx == NULL || !IS_ACTIVE(tx->status));
+
+//WAS  pthread_mutex_lock(&quiesce_mutex);
+  mutex_lock(&quiesce_mutex);
+  /* Wait for all other transactions to block on barrier */
+  threads_count--;
+  if (quiesce == 0) {
+    /* We are first on the barrier */
+    quiesce = 1;
+  }
+  while (quiesce) {
+    if (threads_count == 0) {
+      /* Everybody is blocked */
+      if (f != NULL)
+        f(arg);
+      /* Release transactional threads */
+      quiesce = 0;
+  //WAS    pthread_cond_broadcast(&quiesce_cond);
+      cond_broadcast(&quiesce_cond);
+    } else {
+      /* Wait for other transactions to stop */
+  //WAS    pthread_cond_wait(&quiesce_cond, &quiesce_mutex);
+    	cond_wait( &quiesce_cond, &quiesce_mutex);
+    }
+  }
+  threads_count++;
+//WAS  pthread_mutex_unlock(&quiesce_mutex);
+  mutex_unlock(&quiesce_mutex);
+}
+
+/*
+ * Wait for all transactions to be be out of their current transaction.
+ */
+static inline int stm_quiesce(stm_tx_t *tx, int block)
+{
+  stm_tx_t *t;
+#if CM == CM_MODULAR
+  stm_word_t s, c;
+#endif /* CM == CM_MODULAR */
+
+  PRINT_DEBUG("==> stm_quiesce(%p)\n", tx);
+
+  if (IS_ACTIVE(tx->status)) {
+    /* Only one active transaction can quiesce at a time, others must abort */
+// WAS   if (pthread_mutex_trylock(&quiesce_mutex) != 0)
+	  if (mutex_trylock(&quiesce_mutex) != 0)
+		  return 1;
+  } else {
+    // We can safely block because we are inactive
+//WAS    pthread_mutex_lock(&quiesce_mutex);
+	    mutex_lock(&quiesce_mutex);
+  }
+  /* We own the lock at this point */
+  if (block)
+    ATOMIC_STORE_REL(&quiesce, 2);
+  /* Make sure we read latest status data */
+  ATOMIC_MB_FULL;
+  /* Not optimal as we check transaction sequentially and might miss some inactivity states */
+  for (t = threads; t != NULL; t = t->next) {
+    if (t == tx)
+      continue;
+    /* Wait for all other transactions to become inactive */
+#if CM == CM_MODULAR
+    s = t->status;
+    if (IS_ACTIVE(s)) {
+      c = GET_STATUS_COUNTER(s);
+      do {
+        s = t->status;
+      } while (IS_ACTIVE(s) && c == GET_STATUS_COUNTER(s));
+    }
+#else /* CM != CM_MODULAR */
+    while (IS_ACTIVE(t->status))
+      ;
+#endif /* CM != CM_MODULAR */
+  }
+  if (!block)
+//WAS    pthread_mutex_unlock(&quiesce_mutex);
+	    mutex_unlock(&quiesce_mutex);
+  return 0;
+}
+
+/*
+ * Check if transaction must block.
+ */
+static inline int stm_check_quiesce(stm_tx_t * tx)
+{
+  stm_word_t s;
+
+  /* Must be called upon start (while already active but before acquiring any lock) */
+  assert(IS_ACTIVE(tx->status));
+
+#ifdef IRREVOCABLE_ENABLED
+  if ((tx->irrevocable & 0x08) != 0) {
+    /* Serial irrevocable mode: we are executing alone */
+    return 0;
+  }
+#endif
+  ATOMIC_MB_FULL;
+  if (ATOMIC_LOAD_ACQ(&quiesce) == 2) {
+    s = ATOMIC_LOAD(&tx->status);
+    SET_STATUS(tx->status, TX_IDLE);
+    while (ATOMIC_LOAD_ACQ(&quiesce) == 2) {
+#ifdef WAIT_YIELD
+//      sched_yield();
+    	schedule();
+#endif /* WAIT_YIELD */
+    }
+    SET_STATUS(tx->status, GET_STATUS(s));
+    return 1;
+  }
+  return 0;
+}
+
+/*
+ * Release threads blocked after quiescence.
+ */
+static inline void stm_quiesce_release(stm_tx_t *tx)
+{
+  ATOMIC_STORE_REL(&quiesce, 0);
+// WAS  pthread_mutex_unlock(&quiesce_mutex);
+  mutex_unlock(&quiesce_mutex);
+}
+
+
+#endif /* STM_QUIESCE_H_ */
diff --git a/linux-2.6.37.6-antonio/ipc/stm_syscall.h b/linux-2.6.37.6-antonio/ipc/stm_syscall.h
new file mode 100644
index 0000000..ced960a
--- /dev/null
+++ b/linux-2.6.37.6-antonio/ipc/stm_syscall.h
@@ -0,0 +1,294 @@
+/*
+ * stm_syscall.h
+ *
+ *  Created on: Jan 6, 2012
+ *      Author: Antonio Barbalace
+ *
+ * common syscall entry code for stm
+ */
+
+#ifndef STM_SYSCALL_H_
+#define STM_SYSCALL_H_
+
+#include <linux/syscalls.h>
+#include <linux/uaccess.h>
+
+#include <linux/snapshot.h>
+
+
+//che dati mi servono ?!?!
+//call_id, i.e. STM_START, STM_COMMIT, STM_ABORT, STM_LOAD, STM_STORE
+//stack_addr
+//stack_size
+
+//function arguments.. (TXPARAM) +
+//STM_START stm_tx_attr_t
+//STM_COMMIT
+//STM_ABORT reason
+//STM_LOAD stm_word_t*
+//STM_STORE stm_word_t* stm_word_t
+
+//START common user/krn definitions
+//flags can be mixed with func_num
+
+#define SYS_STM_INIT_THREAD	0x008000
+#define SYS_STM_EXIT_THREAD	0x008800
+
+#define SYS_STM_START 		0x008100
+#define SYS_STM_COMMIT		0x008200
+#define SYS_STM_ABORT		0x008400
+//io functions
+#define SYS_STM_LOAD		0x810000
+#define SYS_STM_STORE		0x820000
+
+// generic functions
+#define SYS_STM_GET_STAT		0x81000000
+#define SYS_STM_GET_STAT_GLOBAL	0x82000000
+#define SYS_STM_GET_STAT_LOCAL	0x84000000
+
+#define SYS_STM_GET_PARAM		0x88000000
+
+#define SYS_STM_SPEC_CREATE		0x41000000
+#define SYS_STM_SPEC_SET		0x42000000
+#define SYS_STM_SPEC_GET		0x44000000
+
+//stm_attr_t must be define before (include /include/linux/stm_types.h)
+typedef struct __stack_desc {
+	void * addr;
+	int size;
+//	int index;
+//	long flags;
+} stack_desc;
+
+typedef struct __io_desc {
+	stm_word_t * address;
+	stm_word_t value;
+} io_desc;
+
+typedef struct __spec_desc {
+	int key;
+	void *data;
+} spec_desc;
+
+#define STM_GET_CAP_MAX 64
+
+typedef union __func_desc {
+	stm_tx_attr_t attr;
+	io_desc io;
+	spec_desc spec;
+	int reason; // abort
+	unsigned long value; // stats and param
+	char info[STM_GET_CAP_MAX]; // stats and param
+} func_desc;
+//END
+
+//The data in chk_pnt are data decided by the stm_ interface (flags is the kind of
+//of snapshot and index is the snashot handler that wll be saved in the thread_tx struct)
+// syscall 3 args +ptregs
+
+// only STM_START needs stack_desc the other functions does not require it!
+
+int sys_stm_ctrl (int fnum, func_desc * fdesc, stack_desc * sdesc, struct pt_regs *regs)
+{
+	int ret = 0;
+	func_desc krnfdesc;
+	stack_desc krnsdesc;
+
+	memset((void*) &krnfdesc, 0, sizeof(func_desc));
+	memset((void*) &krnsdesc, 0, sizeof(stack_desc));
+
+//	printk("%s: fnum %d fdesc %p sdesc %p pt_regs %p\n",
+//			__func__, fnum, fdesc, sdesc,regs);
+
+///////////////////////////////////////////////////////////////////////////////
+// copy the two descriptors from user space and if ok make the switch between operations
+///////////////////////////////////////////////////////////////////////////////
+	//check user address before access -> done by copy_from_user .. __must_ch
+	if (fdesc) { // if this is zero we cannot return index data and read flag data
+		// return bytes that cannot be copied
+		if ( (ret = __copy_from_user_inatomic(&krnfdesc, fdesc, sizeof(func_desc))) )
+			printk("%s: error retrieving func_desc from user space ret %d sizeof %d addr %p\n",
+					__func__, ret, sizeof(func_desc), fdesc); // error
+	}
+	if (sdesc) { // if this is zero we cannot return index data and read flag data
+		// return bytes that cannot be copied
+		if ( (ret = __copy_from_user_inatomic(&krnsdesc, sdesc, sizeof(stack_desc))) )
+			printk("%s: error retrieving stack_desc from user space ret %d sizeof %d addr %p\n",
+					__func__, ret, sizeof(stack_desc), sdesc); // error
+	}
+
+///////////////////////////////////////////////////////////////////////////////
+// switch on required function number
+///////////////////////////////////////////////////////////////////////////////
+	switch (fnum)
+	{
+	case SYS_STM_INIT_THREAD: { // TODO error reporting add
+		current->thread_tx = stm_init_thread();
+		if (sdesc) {
+			current->thread_tx->stack.addr = krnsdesc.addr;
+			current->thread_tx->stack.size = krnsdesc.size;
+		}
+		break;
+	}
+	case SYS_STM_EXIT_THREAD: { // TODO error reporting add
+		if (current->thread_tx) {
+			stm_exit_thread(current->thread_tx);
+			current->thread_tx = 0;
+		}
+		break;
+	}
+	case SYS_STM_START: {
+		uintptr_t snp; // must be long on 64bit
+		if ( (snp = stm_start(&(krnfdesc.attr)) )!= NULL ) {
+/*			if (fdesc) {
+				user_data.index = krnsdesc.index;
+				user_data.flags = krnsdesc.flags;
+			}
+*/	//prev		if (sdesc) { // if stack descriptor is not passed by error
+				//*snp = (uintptr_t)create_snapshot(krnsdesc.addr, krnsdesc.size, 0, regs); //save the snapshot number in current->thread_tx
+// the snapshot parameters were passed every start transaction, the new version (to be more efficient will save them on the thread desc)
+//				snp = (uintptr_t)create_snapshot(krnsdesc.addr, krnsdesc.size, 0, regs); //save the snapshot number in current->thread_tx
+				snp = (uintptr_t)create_snapshot(current->thread_tx->stack.addr, current->thread_tx->stack.size, 0, regs); //save the snapshot number in current->thread_tx
+				//save the snapshot
+
+				// TODO
+				// if create_snapshot fails it returns zero, zero it's ok to be saved in snapshot
+				// consider the case when no snapshot is present you cannot simply rollback
+				// the transaction must be switch to irrevocable (error is signaled in dmesg by create_snapshot)
+				current->thread_tx->snapshot = snp;
+/*			}
+			else {
+				printk ("%s: stack descriptor is required from STM_START\n", __func__);
+				return -ENODEV;
+			}
+	*/	}
+		break; }
+	case SYS_STM_COMMIT: {
+		uintptr_t snp;
+		if (current->thread_tx->snapshot == 0) {
+			printk ("%s:stm_commit current (pid %d) has no registered transaction\n",
+					__func__, current->pid);
+			return -ENODEV; }
+		if ( (ret = stm_commit()) == ROLLBACK_REQUESTED ) {
+			// rollback user space state, snapshot can be invalid (dmesg error from restore_)
+			snp = restore_snapshot (current->thread_tx->snapshot, 0x00, regs);
+			return snp; //this return SUCCESS or ROLLBACK_NO_RETRY
+		}
+
+		// TODO
+		// on commit delete the checkpoint (this is true only on flat nesting)
+		delete_snapshot(current->thread_tx->snapshot, 0x00);
+		current->thread_tx->snapshot = 0;
+
+		return ret;
+		break; }
+	case SYS_STM_ABORT: {
+		uintptr_t snp;
+		if (current->thread_tx->snapshot == 0) {
+			printk ("%s:stm_abort current (pid %d) has no registered transaction\n",
+					__func__, current->pid);
+			return -ENODEV; }
+		if ( (ret = stm_abort(krnfdesc.reason)) == ROLLBACK_REQUESTED )
+			if (snp = restore_snapshot (current->thread_tx->snapshot, 0, regs) )
+				return krnfdesc.reason;
+		return ret;
+		break; }
+	case SYS_STM_LOAD: {
+		uintptr_t snp;
+		if (current->thread_tx->snapshot == 0) {
+			printk ("%s:stm_load current (pid %d) has no registered transaction\n",
+					__func__, current->pid);
+			return -ENODEV; }
+
+		stm_word_t value;
+		if ( (ret = stm_load (krnfdesc.io.address, &value)) == ROLLBACK_REQUESTED ) {
+			if (snp = restore_snapshot (current->thread_tx->snapshot, 0, regs) )
+				return 0; // TODO
+		}
+		if ( fdesc  && !put_user(value, &(fdesc->io.value)) ) // put_user returns 0 un success
+			return 0;
+		return value; // return value only on success
+		break;}
+	case SYS_STM_STORE: {  // word size store
+		uintptr_t snp;
+		if (current->thread_tx->snapshot == 0) {
+			printk ("%s:stm_store current (pid %d) has no registered transaction\n",
+					__func__, current->pid);
+			return -ENODEV; }
+
+		if ( (ret = stm_store (krnfdesc.io.address, krnfdesc.io.value)) == ROLLBACK_REQUESTED ) {
+			if (snp = restore_snapshot (current->thread_tx->snapshot, 0, regs) )
+		return ret;}
+		return krnfdesc.io.value;
+		break; }
+		// TODO in the future
+/*	case SYS_STM_STORE2: // part of word size ... probably is much better to always use store2
+
+		if ( (ret = stm_store2 (krnfdesc.io.address, krnfdesc.io.value)) == ROLLBACK_REQUESTED )
+//restore snapshot			sys_snapshot();
+		return ret;
+		break;
+*/
+	case SYS_STM_GET_STAT: {
+		unsigned long value;
+
+		ret =  stm_get_stats(&(krnfdesc.info), &value); // stm_get_stats fails with 0
+		// copy the value to user
+		//printk("stm_get_stats %s %ld %p\n", &(krnfdesc.info), value, &value);
+		if ( fdesc  && !put_user(value, &(fdesc->value)) ) // put_user returns 0 un success
+			return ret;
+		return 0; // we failed with the same error code 0 of stm_get_stats
+		break; }
+	case SYS_STM_GET_STAT_GLOBAL: {
+		unsigned long value;
+
+		ret =  stm_get_global_stats(&(krnfdesc.info), &value); // stm_get_stats fails with 0
+		// copy the value to user
+		if ( fdesc  && !put_user(value, &(fdesc->value)) ) // put_user returns 0 un success
+			return ret;
+		return 0; // we failed with the same error code 0 of stm_get_stats
+		break;}
+	case SYS_STM_GET_STAT_LOCAL: {
+		unsigned long value;
+
+		ret =  stm_get_local_stats(&(krnfdesc.info), &value); // stm_get_stats fails with 0
+		// copy the value to user
+		if ( fdesc  && !put_user(value, &(fdesc->value)) ) // put_user returns 0 un success
+			return ret;
+		return 0; // we failed with the same error code 0 of stm_get_stats
+		break;}
+	case SYS_STM_GET_PARAM: {
+		char buffer[STM_GET_CAP_MAX]; memset(buffer, 0, sizeof(buffer));
+
+		ret =  stm_get_parameter(&(krnfdesc.info), buffer); // fails with zero
+		// copy the value/array/struct to user
+		if ( fdesc && !copy_to_user( &(fdesc->info), buffer, sizeof(buffer)) )
+			return ret;
+		return 0; // we failed with the same error code 0 of stm_get_param
+		break; }
+
+	case SYS_STM_SPEC_CREATE: {
+		return stm_create_specific();
+	break; }
+	case SYS_STM_SPEC_SET: {
+		stm_set_specific(krnfdesc.spec.key, krnfdesc.spec.data);
+		return 0;
+	break; }
+	case SYS_STM_SPEC_GET: {
+		krnfdesc.spec.data = stm_get_specific(krnfdesc.spec.key);
+		put_user(krnfdesc.spec.data, &(fdesc->spec.data));
+		return 0;
+	break; }
+
+	default:
+	printk("%s: function not supported\n", __func__);
+	break;
+	}
+	return 0;
+}
+
+//IDEA for fasten stm IO it is possible to subdivide ctrl and io for each stm
+//this is something could be discussed for speed up devel we just use one syscall
+//sys_stm_io()
+
+#endif /* STM_SYSCALL_H_ */
diff --git a/linux-2.6.37.6-antonio/kernel/exit.c b/linux-2.6.37.6-antonio/kernel/exit.c
index 676149a..108881d 100644
--- a/linux-2.6.37.6-antonio/kernel/exit.c
+++ b/linux-2.6.37.6-antonio/kernel/exit.c
@@ -51,6 +51,7 @@
 #include <trace/events/sched.h>
 #include <linux/hw_breakpoint.h>
 #include <linux/oom.h>
+#include <linux/snapshot.h>
 
 #include <asm/uaccess.h>
 #include <asm/unistd.h>
@@ -949,6 +950,11 @@ NORET_TYPE void do_exit(long code)
 	}
 
 	exit_irq_thread();
+	// exit stm support
+//	stm_exit_thread(tsk->thread_tx);
+	tsk->thread_tx = 0;
+	// exit snapshot/checkpointing
+	exit_snapshot(tsk);
 
 	exit_signals(tsk);  /* sets PF_EXITING */
 	/*
diff --git a/linux-2.6.37.6-antonio/kernel/fork.c b/linux-2.6.37.6-antonio/kernel/fork.c
index a4913e6..d9abe4b 100644
--- a/linux-2.6.37.6-antonio/kernel/fork.c
+++ b/linux-2.6.37.6-antonio/kernel/fork.c
@@ -1055,6 +1055,12 @@ static struct task_struct *copy_process(unsigned long clone_flags,
 	copy_flags(clone_flags, p);
 	INIT_LIST_HEAD(&p->children);
 	INIT_LIST_HEAD(&p->sibling);
+
+	INIT_HLIST_HEAD(&p->snapshot); /* checkpoint/rollback interface */ //hlist is used in hash list
+//	p->num_snapshot = NULL; /* checkpoint/rollback interface */ // not required is_empty is enough
+	//p->thread_tx = stm_init_thread();
+	p->thread_tx = NULL;
+
 	rcu_copy_process(p);
 	p->vfork_done = NULL;
 	spin_lock_init(&p->alloc_lock);
@@ -1344,431 +1350,6 @@ fork_out:
 	return ERR_PTR(retval);
 }
 
-/*
- * This creates a copy of the data strctures related to a process,
- * and save it in the task descriptor.
- *
- * It copies the registers, and all the appropriate
- * parts of the process environment (as per the clone
- * flags). This function derives from copy_process.
- */
-static struct task_struct *checkpoint_process(unsigned long checkpoint_flags,
-					unsigned long stack_start,
-					struct pt_regs *regs,
-					unsigned long stack_size, /* not sure about this option */
-					int __user *child_tidptr,
-					struct pid *pid,
-					int trace)
-{
-	int retval;
-	struct task_struct *p;
-	int cgroup_callbacks_done = 0;
-
-	// TODO i checkpoint vanno copiati o no durante una fork?!?!
-	//questo si va a ripercuotere su fork e non qui pero
-
-
-//	if ((clone_flags & (CLONE_NEWNS|CLONE_FS)) == (CLONE_NEWNS|CLONE_FS))
-//		return ERR_PTR(-EINVAL);
-
-	/*
-	 * Thread groups must share signals as well, and detached threads
-	 * can only be started up within the thread group.
-	 */
-//	if ((clone_flags & CLONE_THREAD) && !(clone_flags & CLONE_SIGHAND))
-//		return ERR_PTR(-EINVAL);
-
-	/*
-	 * Shared signal handlers imply shared VM. By way of the above,
-	 * thread groups also imply shared VM. Blocking this case allows
-	 * for various simplifications in other code.
-	 */
-//	if ((clone_flags & CLONE_SIGHAND) && !(clone_flags & CLONE_VM))
-//		return ERR_PTR(-EINVAL);
-
-	/*
-	 * Siblings of global init remain as zombies on exit since they are
-	 * not reaped by their parent (swapper). To solve this and to avoid
-	 * multi-rooted process trees, prevent global and container-inits
-	 * from creating siblings.
-	 */
-//	if ((clone_flags & CLONE_PARENT) &&
-//				current->signal->flags & SIGNAL_UNKILLABLE)
-//		return ERR_PTR(-EINVAL);
-
-	// TODO probably also security must be integrated, but not at this point
-//	retval = security_task_create(clone_flags);
-//	if (retval)
-//		goto fork_out;
-
-	retval = -ENOMEM;
-	p = dup_task_struct(current); // duplicate task_struct, thread_info and the stack also
-	if (!p)
-		goto fork_out;
-	// Antonio we do not want to reinit the following stuff
-	p->dirties.shift = current->dirties.shift;
-	p->dirties.period = current->dirties.period;
-	p->dirties.events = current->dirties.events;
-	// continue
-	if (test_tsk_need_resched(current))
-		set_tsk_need_resched(p);
-	// continue
-	atomic_set(&(p->usage), current->usage);
-	atomic_set(&(p->fs_excl), current->fs_excl);
-
-//	ftrace_graph_init_task(p); this cannot be done //in any case nothing to do
-
-//	rt_mutex_init_task(p); this cannot be done
-
-//#ifdef CONFIG_PROVE_LOCKING
-//	DEBUG_LOCKS_WARN_ON(!p->hardirqs_enabled);
-//	DEBUG_LOCKS_WARN_ON(!p->softirqs_enabled);
-//#endif
-//	retval = -EAGAIN;
-//	if (atomic_read(&p->real_cred->user->processes) >=
-//			task_rlimit(p, RLIMIT_NPROC)) {
-//		if (!capable(CAP_SYS_ADMIN) && !capable(CAP_SYS_RESOURCE) &&
-//		    p->real_cred->user != INIT_USER)
-//			goto bad_fork_free;
-//	}
-
-	retval = copy_creds(p, clone_flags); // gestisce clone_thread
-	if (retval < 0)
-		goto bad_fork_free;
-
-	/*
-	 * If multiple threads are within copy_process(), then this check
-	 * triggers too late. This doesn't hurt, the check is only there
-	 * to stop root fork bombs.
-	 */
-	retval = -EAGAIN;
-//	if (nr_threads >= max_threads)
-//		goto bad_fork_cleanup_count;
-
-//	if (!try_module_get(task_thread_info(p)->exec_domain->module))
-//		goto bad_fork_cleanup_count;
-
-	p->did_exec = 0;
-	delayacct_tsk_init(p);	/* Must remain after dup_task_struct() */ //fa nulla
-//	copy_flags(clone_flags, p); // which flags are?!?!? not good for us
-	INIT_LIST_HEAD(&p->children); // on restoring this list must be crosscheck to understand if the same task are alive
-//todo 	hlist_for_each entry copy in the new tsk struct
-	INIT_LIST_HEAD(&p->sibling); // idem as above
-//todo hlist_for_each entry copy in the new tsk struct
-
-	//TODO add this line also in copy_process
-	INIT_LIST_HEAD(&p->checkpoint); // init must be done only on create!!!! not here
-
-	rcu_copy_process(p); // nothing to do in this function
-//	p->vfork_done = NULL;
-//	spin_lock_init(&p->alloc_lock);
-
-//	init_sigpending(&p->pending);
-
-	// cpu time must not be altered also restoring (we do not want to
-	// consider the time from a checkpoint restore but we would ALWAYS knoe
-	// the time from the epoch when the task start
-//	p->utime = cputime_zero;
-//	p->stime = cputime_zero;
-//	p->gtime = cputime_zero;
-//	p->utimescaled = cputime_zero;
-//	p->stimescaled = cputime_zero;
-//#ifndef CONFIG_VIRT_CPU_ACCOUNTING
-//	p->prev_utime = cputime_zero;
-//	p->prev_stime = cputime_zero;
-//#endif
-//#if defined(SPLIT_RSS_COUNTING)
-//	memset(&p->rss_stat, 0, sizeof(p->rss_stat));
-//#endif
-
-//	p->default_timer_slack_ns = current->timer_slack_ns;
-
-	task_io_accounting_init(&p->ioac); // init?!?! canot be copied? -- non fa niente
-	acct_clear_integrals(p); // init?!?! cannot be copied? --- non fa niente
-
-	//posix_cpu_timers_init(p); // this function is expanded below
-	INIT_LIST_HEAD(&p->cpu_timers[0]);
-// TODO	 copy all elements
-	INIT_LIST_HEAD(&p->cpu_timers[1]);
-// TODO	 copy all elements
-	INIT_LIST_HEAD(&p->cpu_timers[2]);
-// TODO	 copy all elements
-
-//	p->lock_depth = -1;		/* -1 = no lock */
-//	do_posix_clock_monotonic_gettime(&p->start_time);
-//	p->real_start_time = p->start_time;
-//	monotonic_to_bootbased(&p->real_start_time);
-//	p->io_context = NULL;
-//	p->audit_context = NULL;
-//?!?!	cgroup_fork(p); // TODO understand what a cgroup_fork is
-#ifdef CONFIG_NUMA
-	p->mempolicy = mpol_dup(p->mempolicy);
- 	if (IS_ERR(p->mempolicy)) {
- 		retval = PTR_ERR(p->mempolicy);
- 		p->mempolicy = NULL;
- 		goto bad_fork_cleanup_cgroup;
- 	}
-	mpol_fix_fork_child_flag(p);
-#endif
-#ifdef CONFIG_TRACE_IRQFLAGS
-	p->irq_events = 0;
-#ifdef __ARCH_WANT_INTERRUPTS_ON_CTXSW
-	p->hardirqs_enabled = 1;
-#else
-	p->hardirqs_enabled = 0;
-#endif
-	p->hardirq_enable_ip = 0;
-	p->hardirq_enable_event = 0;
-	p->hardirq_disable_ip = _THIS_IP_;
-	p->hardirq_disable_event = 0;
-	p->softirqs_enabled = 1;
-	p->softirq_enable_ip = _THIS_IP_;
-	p->softirq_enable_event = 0;
-	p->softirq_disable_ip = 0;
-	p->softirq_disable_event = 0;
-	p->hardirq_context = 0;
-	p->softirq_context = 0;
-#endif
-#ifdef CONFIG_LOCKDEP
-	p->lockdep_depth = 0; /* no locks held yet */
-	p->curr_chain_key = 0;
-	p->lockdep_recursion = 0;
-#endif
-
-#ifdef CONFIG_DEBUG_MUTEXES
-	p->blocked_on = NULL; /* not blocked yet */
-#endif
-#ifdef CONFIG_CGROUP_MEM_RES_CTLR
-	p->memcg_batch.do_batch = 0;
-	p->memcg_batch.memcg = NULL;
-#endif
-
-	/* Perform scheduler related setup. Assign this task to a CPU. */
-//	sched_fork(p, clone_flags); // not required, migrations.. and other stuff we do not want
-	INIT_LIST_HEAD(&p->rt.run_list);
-//TODO	 copy list
-	INIT_LIST_HEAD(&p->se.group_node);
-//TODO	 copy list
-
-//	retval = perf_event_init_task(p);
-//	if (retval)
-//		goto bad_fork_cleanup_policy;
-
-//	if ((retval = audit_alloc(p))) //non fa niente quindi non serve
-//		goto bad_fork_cleanup_policy;
-	/* copy all the process information */
-	if ((retval = copy_semundo(clone_flags, p)))
-		goto bad_fork_cleanup_audit;
-	if ((retval = copy_files(clone_flags, p)))
-		goto bad_fork_cleanup_semundo;
-	if ((retval = copy_fs(clone_flags, p)))
-		goto bad_fork_cleanup_files;
-	if ((retval = copy_sighand(clone_flags, p)))
-		goto bad_fork_cleanup_fs;
-	if ((retval = copy_signal(clone_flags, p)))
-		goto bad_fork_cleanup_sighand;
-	if ((retval = copy_mm(clone_flags, p)))
-		goto bad_fork_cleanup_signal;
-	if ((retval = copy_namespaces(clone_flags, p)))
-		goto bad_fork_cleanup_mm;
-	if ((retval = copy_io(clone_flags, p)))
-		goto bad_fork_cleanup_namespaces;
-	// stack_start and stack_size are IN parameters
-	retval = copy_thread(clone_flags, stack_start, stack_size, p, regs);
-// TODO	not easy this could be used to save pt_regs and also copy TLS (user side, copy could be maintained in kernel)
-	if (retval)
-		goto bad_fork_cleanup_io;
-
-	/* we do not want to create a new pid, but only maintain the current pid and tid.. etc..
-	if (pid != &init_struct_pid) {
-		retval = -ENOMEM;
-		pid = alloc_pid(p->nsproxy->pid_ns);
-		if (!pid)
-			goto bad_fork_cleanup_io;
-
-		if (clone_flags & CLONE_NEWPID) {
-			retval = pid_ns_prepare_proc(p->nsproxy->pid_ns);
-			if (retval < 0)
-				goto bad_fork_free_pid;
-		}
-	}
-
-	p->pid = pid_nr(pid);
-	p->tgid = p->pid;
-	if (clone_flags & CLONE_THREAD)
-		p->tgid = current->tgid;
-	*/
-/*
-	if (current->nsproxy != p->nsproxy) {
-		retval = ns_cgroup_clone(p, pid);
-		if (retval)
-			goto bad_fork_free_pid;
-	}
-*/
-//	p->set_child_tid = (clone_flags & CLONE_CHILD_SETTID) ? child_tidptr : NULL;
-	/*
-	 * Clear TID on mm_release()?
-	 */
-//	p->clear_child_tid = (clone_flags & CLONE_CHILD_CLEARTID) ? child_tidptr: NULL;
-#ifdef CONFIG_FUTEX
-	p->robust_list = NULL;
-#ifdef CONFIG_COMPAT
-	p->compat_robust_list = NULL;
-#endif
-	INIT_LIST_HEAD(&p->pi_state_list);
-	p->pi_state_cache = NULL;
-#endif
-	/*
-	 * sigaltstack should be cleared when sharing the same VM
-	 */
-//	if ((clone_flags & (CLONE_VM|CLONE_VFORK)) == CLONE_VM)
-//		p->sas_ss_sp = p->sas_ss_size = 0;
-
-	/*
-	 * Syscall tracing and stepping should be turned off in the
-	 * child regardless of CLONE_PTRACE.
-	 */
-//	user_disable_single_step(p);
-//	clear_tsk_thread_flag(p, TIF_SYSCALL_TRACE);
-//#ifdef TIF_SYSCALL_EMU
-//	clear_tsk_thread_flag(p, TIF_SYSCALL_EMU);
-//#endif
-//	clear_all_latency_tracing(p);
-
-	/* ok, now we should be set up.. */
-//	p->exit_signal = (clone_flags & CLONE_THREAD) ? -1 : (clone_flags & CSIGNAL);
-//	p->pdeath_signal = 0;
-//	p->exit_state = 0;
-
-	/*
-	 * Ok, make it visible to the rest of the system.
-	 * We dont wake it up yet.
-	 */
-//	p->group_leader = p;
-	INIT_LIST_HEAD(&p->thread_group);
-// TODO add all the list
-
-	/* Now that the task is set up, run cgroup callbacks if
-	 * necessary. We need to run them before the task is visible
-	 * on the tasklist. */
-//	cgroup_fork_callbacks(p);
-//	cgroup_callbacks_done = 1;
-
-	/* Need tasklist lock for parent etc handling! */
-//	write_lock_irq(&tasklist_lock);
-
-	/* CLONE_PARENT re-uses the old parent */
-//	if (clone_flags & (CLONE_PARENT|CLONE_THREAD)) {
-		p->real_parent = current->real_parent;
-		p->parent_exec_id = current->parent_exec_id;
-//	} else {
-//		p->real_parent = current;
-//		p->parent_exec_id = current->self_exec_id;
-//	}
-
-//	spin_lock(&current->sighand->siglock);
-
-	/*
-	 * Process group and session signals need to be delivered to just the
-	 * parent before the fork or both the parent and the child after the
-	 * fork. Restart if a signal comes in before we add the new process to
-	 * it's process group.
-	 * A fatal signal pending means that current will exit, so the new
-	 * thread can't slip out of an OOM kill (or normal SIGKILL).
- 	 */
-/*
-	recalc_sigpending();
-	if (signal_pending(current)) {
-		spin_unlock(&current->sighand->siglock);
-		write_unlock_irq(&tasklist_lock);
-		retval = -ERESTARTNOINTR;
-		goto bad_fork_free_pid;
-	}
-
-	if (clone_flags & CLONE_THREAD) {
-		current->signal->nr_threads++;
-		atomic_inc(&current->signal->live);
-		atomic_inc(&current->signal->sigcnt);
-		p->group_leader = current->group_leader;
-		list_add_tail_rcu(&p->thread_group, &p->group_leader->thread_group);
-	}
-
-	if (likely(p->pid)) {
-		tracehook_finish_clone(p, clone_flags, trace);
-
-		if (thread_group_leader(p)) {
-			if (clone_flags & CLONE_NEWPID)
-				p->nsproxy->pid_ns->child_reaper = p;
-
-			p->signal->leader_pid = pid;
-			p->signal->tty = tty_kref_get(current->signal->tty);
-			attach_pid(p, PIDTYPE_PGID, task_pgrp(current));
-			attach_pid(p, PIDTYPE_SID, task_session(current));
-			list_add_tail(&p->sibling, &p->real_parent->children);
-			list_add_tail_rcu(&p->tasks, &init_task.tasks);
-			__get_cpu_var(process_counts)++;
-		}
-		attach_pid(p, PIDTYPE_PID, pid);
-		nr_threads++;
-	}
-*/ //this is stuff that must be considered when resumpt a thread NOT ON CHECKPOINTING
-//	total_forks++;
-//	spin_unlock(&current->sighand->siglock);
-
-//	write_unlock_irq(&tasklist_lock);
-//	proc_fork_connector(p);
-//	cgroup_post_fork(p);
-//	perf_event_fork(p);
-	return p;
-
-bad_fork_free_pid:
-	if (pid != &init_struct_pid)
-		free_pid(pid);
-bad_fork_cleanup_io:
-	if (p->io_context)
-		exit_io_context(p);
-bad_fork_cleanup_namespaces:
-	exit_task_namespaces(p);
-bad_fork_cleanup_mm:
-	if (p->mm) {
-		task_lock(p);
-		if (p->signal->oom_score_adj == OOM_SCORE_ADJ_MIN)
-			atomic_dec(&p->mm->oom_disable_count);
-		task_unlock(p);
-		mmput(p->mm);
-	}
-bad_fork_cleanup_signal:
-	if (!(clone_flags & CLONE_THREAD))
-		free_signal_struct(p->signal);
-bad_fork_cleanup_sighand:
-	__cleanup_sighand(p->sighand);
-bad_fork_cleanup_fs:
-	exit_fs(p); /* blocking */
-bad_fork_cleanup_files:
-	exit_files(p); /* blocking */
-bad_fork_cleanup_semundo:
-	exit_sem(p);
-bad_fork_cleanup_audit:
-	audit_free(p);
-bad_fork_cleanup_policy:
-	perf_event_free_task(p);
-#ifdef CONFIG_NUMA
-	mpol_put(p->mempolicy);
-bad_fork_cleanup_cgroup:
-#endif
-	cgroup_exit(p, cgroup_callbacks_done);
-	delayacct_tsk_free(p);
-	module_put(task_thread_info(p)->exec_domain->module);
-bad_fork_cleanup_count:
-	atomic_dec(&p->cred->user->processes);
-	exit_creds(p);
-bad_fork_free:
-	free_task(p);
-fork_out:
-	return ERR_PTR(retval);
-}
-
-
 noinline struct pt_regs * __cpuinit __attribute__((weak)) idle_regs(struct pt_regs *regs)
 {
 	memset(regs, 0, sizeof(struct pt_regs));
diff --git a/linux-2.6.37.6-antonio/kernel/sched.c b/linux-2.6.37.6-antonio/kernel/sched.c
index 5e0a919..67833d9 100644
--- a/linux-2.6.37.6-antonio/kernel/sched.c
+++ b/linux-2.6.37.6-antonio/kernel/sched.c
@@ -555,6 +555,9 @@ struct rq {
 
 	/* BKL stats */
 	unsigned int bkl_count;
+#ifdef CONFIG_STM_PREEMPT_AVOIDANCE
+	unsigned int sched_preempt;
+#endif
 #endif
 };
 
diff --git a/linux-2.6.37.6-antonio/kernel/sched_debug.c b/linux-2.6.37.6-antonio/kernel/sched_debug.c
index 2e1b0d1..4f11d4c 100644
--- a/linux-2.6.37.6-antonio/kernel/sched_debug.c
+++ b/linux-2.6.37.6-antonio/kernel/sched_debug.c
@@ -377,7 +377,7 @@ static int __init init_sched_debug_procfs(void)
 }
 
 __initcall(init_sched_debug_procfs);
-
+// in /proc/XXX/sched
 void proc_sched_show_task(struct task_struct *p, struct seq_file *m)
 {
 	unsigned long nr_switches;
@@ -419,6 +419,9 @@ void proc_sched_show_task(struct task_struct *p, struct seq_file *m)
 	P(se.statistics.nr_migrations_cold);
 	P(se.statistics.nr_failed_migrations_affine);
 	P(se.statistics.nr_failed_migrations_running);
+# ifdef CONFIG_STM_MIGRATION_AVOIDANCE
+	P(se.statistics.nr_failed_migrations_stm);
+# endif
 	P(se.statistics.nr_failed_migrations_hot);
 	P(se.statistics.nr_forced_migrations);
 	P(se.statistics.nr_wakeups);
diff --git a/linux-2.6.37.6-antonio/kernel/sched_fair.c b/linux-2.6.37.6-antonio/kernel/sched_fair.c
index 00ebd76..6a5fd92 100644
--- a/linux-2.6.37.6-antonio/kernel/sched_fair.c
+++ b/linux-2.6.37.6-antonio/kernel/sched_fair.c
@@ -1716,6 +1716,33 @@ static struct task_struct *pick_next_task_fair(struct rq *rq)
 	if (!cfs_rq->nr_running)
 		return NULL;
 
+#ifdef CONFIG_STM_PREEMPT_AVOIDANCE
+	/* NOTE
+	 * With this code we assume that the STM application runs
+	 * in the CFS scheduler, this is ok for the prototype
+	 * but is not generic enough. The most important point is
+	 * to do not be preempted by another transactional thread.
+	 * In this way we do not modify the behaviour of the other
+	 * applications/threads (especially much more prioritary then tx)
+	 */
+	p = rq->curr;
+	if (p)
+		if ( (p->thread_tx) ) {
+			if ( ((unsigned long)(p->thread_tx->status) & 0x01) ) {
+# ifdef CONFIG_STM_DEBUG3
+				trace_printk("%s:%d %p %p \n", p->comm, p->pid,
+					p->thread_tx, p->thread_tx->status);
+# endif
+				set_next_entity(cfs_rq, &(p->se));
+				schedstat_inc(rq, sched_preempt);
+# ifdef CONFIG_STM_PREEMPT_BONUS
+				p->thread_tx->bonus++;
+# endif /* CONFIG_STM_PREEMPT_BONUS */
+				return p;
+			}
+		}
+#endif
+
 	do {
 		se = pick_next_entity(cfs_rq);
 		set_next_entity(cfs_rq, se);
@@ -1786,6 +1813,18 @@ int can_migrate_task(struct task_struct *p, struct rq *rq, int this_cpu,
 		return 0;
 	}
 
+#ifdef CONFIG_STM_MIGRATION_AVOIDANCE
+	if ( (p->thread_tx) )
+		if ( ((unsigned long)(p->thread_tx->status) & 0x01) ){
+# ifdef CONFIG_STM_DEBUG3
+			trace_printk("%s:%d %p %p \n", p->comm, p->pid,
+				p->thread_tx, p->thread_tx->status);
+# endif
+			schedstat_inc(p, se.statistics.nr_failed_migrations_stm);
+			return 0;
+		}
+#endif
+
 	/*
 	 * Aggressive migration if:
 	 * 1) task is cache cold, or
diff --git a/linux-2.6.37.6-antonio/kernel/sched_stats.h b/linux-2.6.37.6-antonio/kernel/sched_stats.h
index 48ddf43..ea9f9a1 100644
--- a/linux-2.6.37.6-antonio/kernel/sched_stats.h
+++ b/linux-2.6.37.6-antonio/kernel/sched_stats.h
@@ -26,8 +26,13 @@ static int show_schedstat(struct seq_file *seq, void *v)
 
 		/* runqueue-specific stats */
 		seq_printf(seq,
+#ifndef CONFIG_STM_PREEMPT_AVOIDANCE
 		    "cpu%d %u %u %u %u %u %u %llu %llu %lu",
 		    cpu, rq->yld_count,
+#else
+		    "cpu%d %u %u %u %u %u %u %u %llu %llu %lu",
+		    cpu, rq->yld_count, rq->sched_preempt,
+#endif
 		    rq->sched_switch, rq->sched_count, rq->sched_goidle,
 		    rq->ttwu_count, rq->ttwu_local,
 		    rq->rq_cpu_time,
diff --git a/linux-2.6.37.6-antonio/kernel/trace/Makefile b/linux-2.6.37.6-antonio/kernel/trace/Makefile
index 53f3381..9c2f441 100644
--- a/linux-2.6.37.6-antonio/kernel/trace/Makefile
+++ b/linux-2.6.37.6-antonio/kernel/trace/Makefile
@@ -30,6 +30,7 @@ obj-$(CONFIG_TRACING) += trace_output.o
 obj-$(CONFIG_TRACING) += trace_stat.o
 obj-$(CONFIG_TRACING) += trace_printk.o
 obj-$(CONFIG_CONTEXT_SWITCH_TRACER) += trace_sched_switch.o
+obj-$(CONFIG_CONTEXT_SWITCH_TRACER) += trace_stm.o
 obj-$(CONFIG_FUNCTION_TRACER) += trace_functions.o
 obj-$(CONFIG_IRQSOFF_TRACER) += trace_irqsoff.o
 obj-$(CONFIG_PREEMPT_TRACER) += trace_irqsoff.o
diff --git a/linux-2.6.37.6-antonio/kernel/trace/trace.h b/linux-2.6.37.6-antonio/kernel/trace/trace.h
index 9021f8c..527a209 100644
--- a/linux-2.6.37.6-antonio/kernel/trace/trace.h
+++ b/linux-2.6.37.6-antonio/kernel/trace/trace.h
@@ -29,6 +29,7 @@ enum trace_type {
 	TRACE_GRAPH_ENT,
 	TRACE_USER_STACK,
 	TRACE_BLK,
+	TRACE_STM,
 
 	__TRACE_LAST_TYPE,
 };
@@ -97,6 +98,13 @@ struct kretprobe_trace_entry_head {
 	unsigned long		ret_ip;
 };
 
+struct trace_stm {
+	struct trace_entry	ent;
+	unsigned long tx_addr;
+	int reason;
+	int retry;
+};
+
 /*
  * trace_flag_type is an enumeration that holds different
  * states when a trace occurs. These are:
@@ -197,6 +205,7 @@ extern void __ftrace_bad_type(void);
 			  TRACE_GRAPH_ENT);		\
 		IF_ASSIGN(var, ent, struct ftrace_graph_ret_entry,	\
 			  TRACE_GRAPH_RET);		\
+		IF_ASSIGN(var, ent, struct trace_stm, TRACE_STM); \
 		__ftrace_bad_type();					\
 	} while (0)
 
diff --git a/linux-2.6.37.6-antonio/kernel/trace/trace_stm.c b/linux-2.6.37.6-antonio/kernel/trace/trace_stm.c
new file mode 100644
index 0000000..f93dfeb
--- /dev/null
+++ b/linux-2.6.37.6-antonio/kernel/trace/trace_stm.c
@@ -0,0 +1,177 @@
+/*
+ * ring buffer based C-state tracer
+ *
+ * Arjan van de Ven <arjan@linux.intel.com>
+ * Copyright (C) 2008 Intel Corporation
+ *
+ * Much is borrowed from trace_boot.c which is
+ * Copyright (C) 2008 Frederic Weisbecker <fweisbec@gmail.com>
+ *
+ */
+
+#include <linux/init.h>
+#include <linux/debugfs.h>
+#include <linux/ftrace.h>
+#include <linux/kallsyms.h>
+#include <linux/module.h>
+
+#include "trace.h"
+
+static struct trace_array *stm_trace;
+static int __read_mostly trace_stm_enabled;
+
+
+static void start_stm_trace(void)
+{
+	trace_stm_enabled = 1;
+}
+
+static void stop_stm_trace(struct trace_array *tr)
+{
+	trace_stm_enabled = 0;
+}
+
+static void stm_trace_init(struct trace_array *tr)
+{
+	int cpu;
+	stm_trace = tr;
+
+	trace_stm_enabled = 1;
+
+	for_each_cpu_mask(cpu, cpu_possible_map)
+		tracing_reset(tr, cpu);
+}
+
+static void stm_trace_ctrl_update(struct trace_array *tr)
+{
+/*	if (tr->ctrl)
+		start_stm_trace();
+	else
+		stop_stm_trace(tr);
+		*/
+}
+
+static enum print_line_t stm_print_line(struct trace_iterator *iter)
+{
+	int ret = 0;
+	struct trace_entry *entry = iter->ent;
+	struct trace_stm *field ;
+	struct stm_trace *it;
+	struct trace_seq *s = &iter->seq;
+	struct timespec stamp;
+	struct timespec duration;
+
+	trace_assign_type(field, entry);
+//	it = &field->state_data;
+//	stamp = ktime_to_timespec(it->stamp);
+//	duration = ktime_to_timespec(ktime_sub(it->end, it->stamp));
+
+	if (entry->type == TRACE_STM) {
+			ret = trace_seq_printf(s, "stm_rollback: tx desc @ %ld reason %d retry %s (pid %d cpu %d)\n",
+					field->tx_addr, field->reason,
+					(field->retry) ? "YES" : "NO",
+					  entry->pid, iter->cpu);
+		if (!ret)
+			return TRACE_TYPE_PARTIAL_LINE;
+		return TRACE_TYPE_HANDLED;
+	}
+	return TRACE_TYPE_UNHANDLED;
+}
+
+static struct tracer stm_tracer __read_mostly =
+{
+	.name		= "stm",
+	.init		= stm_trace_init,
+	.reset		= stop_stm_trace,
+//	.ctrl_update	= stm_trace_ctrl_update,
+	.print_line	= stm_print_line,
+};
+
+static int init_stm_trace(void)
+{
+	return register_tracer(&stm_tracer);
+}
+device_initcall(init_stm_trace);
+/*
+// TODO this is start transaction
+void trace_stm_start(struct stm_trace *it, unsigned int type,
+			 unsigned int level)
+{
+	if (!trace_stm_enabled)
+		return;
+
+	memset(it, 0, sizeof(struct power_trace));
+	it->state = level;
+	it->type = type;
+	it->stamp = ktime_get();
+}
+EXPORT_SYMBOL_GPL(trace_power_start);
+*/
+/*
+// TODO this is commit (or end transaction)
+void trace_stm_end(struct stm_trace *it)
+{
+	struct ring_buffer_event *event;
+	struct trace_stm *entry;
+	struct trace_array_cpu *data;
+	unsigned long irq_flags;
+	struct trace_array *tr = stm_trace;
+
+	if (!trace_stm_enabled)
+		return;
+
+	preempt_disable();
+	it->end = ktime_get();
+	data = tr->data[smp_processor_id()];
+
+	event = ring_buffer_lock_reserve(tr->buffer, sizeof(*entry),
+					 &irq_flags);
+	if (!event)
+		goto out;
+	entry	= ring_buffer_event_data(event);
+	tracing_generic_entry_update(&entry->ent, 0, 0);
+	entry->ent.type = TRACE_STM;
+	entry->state_data = *it;
+	ring_buffer_unlock_commit(tr->buffer, event, irq_flags);
+
+	trace_wake_up();
+
+out:
+	preempt_enable();
+}
+EXPORT_SYMBOL_GPL(trace_stm_end);
+*/
+// TODO this is whatever could happen in the middle of a transaction i.e. retry or abort
+void trace_stm_rollback(unsigned long tx_addr, int reason, int retry)
+{
+	struct ring_buffer_event *event;
+	struct trace_stm *entry; //defined in trace.h
+	struct trace_array_cpu *data;
+	unsigned long flags;
+	struct trace_array *tr = stm_trace;
+
+	if (!trace_stm_enabled)
+		return;
+
+	preempt_disable();
+	data = tr->data[smp_processor_id()];
+	local_irq_save(flags);
+	event = ring_buffer_lock_reserve(tr->buffer, sizeof(*entry) );
+					 //,&irq_flags);
+	if (!event)
+		goto out;
+	entry	= ring_buffer_event_data(event);
+	tracing_generic_entry_update(&entry->ent, 0, 0);
+	entry->ent.type = TRACE_STM;
+	entry->tx_addr = tx_addr;
+	entry->reason = reason;
+	entry->retry = retry;
+	ring_buffer_unlock_commit(tr->buffer, event); //, irq_flags);
+
+	trace_wake_up();
+
+ out:
+	preempt_enable();
+	local_irq_restore(flags);
+}
+EXPORT_SYMBOL_GPL(trace_stm_rollback);
