diff -ruN -x .svn stamp-0.9.6/AUTHORS trunk/AUTHORS
--- stamp-0.9.6/AUTHORS	2007-12-01 19:31:26.000000000 +0100
+++ trunk/AUTHORS	2007-11-02 11:48:07.000000000 +0100
@@ -18,7 +18,6 @@
 
     Others
     ------
-    bayes/sort:    Michael Ringgaard
     kmeans:        Wei-keng Liao, Brendan McCane 
     lib/avltree:   Julienne Walker
     lib/mt19937ar: Makoto Matsumoto, Takuji Nishimura
diff -ruN -x .svn stamp-0.9.6/bayes/bayes.c trunk/bayes/bayes.c
--- stamp-0.9.6/bayes/bayes.c	2007-12-01 19:31:26.000000000 +0100
+++ trunk/bayes/bayes.c	2008-01-29 17:09:32.000000000 +0100
@@ -196,6 +196,7 @@
  */
 MAIN(argc, argv)
 {
+    thread_pool_t* threadpool;
     GOTO_REAL();
 
     /*
@@ -212,7 +213,7 @@
     SIM_GET_NUM_CPU(numThread);
     TM_STARTUP(numThread);
     P_MEMORY_STARTUP(numThread);
-    thread_startup(numThread);
+    threadpool = thread_startup(numThread);
 
     printf("Random seed        = %li\n", randomSeed);
     printf("Number of vars     = %li\n", numVar);
@@ -284,7 +285,7 @@
     TIMER_READ(learnStartTime);
     GOTO_SIM();
 
-    learner_run(learnerPtr);
+    learner_run(learnerPtr, threadpool);
 
     GOTO_REAL();
     TIMER_T learnStopTime;
@@ -322,7 +323,7 @@
 
     GOTO_SIM();
 
-    thread_shutdown();
+    thread_shutdown(threadpool);
 
     MAIN_RETURN(0);
 }
diff -ruN -x .svn stamp-0.9.6/bayes/learner.c trunk/bayes/learner.c
--- stamp-0.9.6/bayes/learner.c	2007-12-01 19:31:27.000000000 +0100
+++ trunk/bayes/learner.c	2008-01-29 17:08:22.000000000 +0100
@@ -1436,10 +1436,10 @@
  * =============================================================================
  */
 void
-learner_run (learner_t* learnerPtr)
+learner_run (learner_t* learnerPtr, thread_pool_t* threadpool)
 {
-    thread_start(&createTaskList, (void*)learnerPtr);
-    thread_start(&learnStructure, (void*)learnerPtr);
+    thread_start(&createTaskList, (void*)learnerPtr, threadpool);
+    thread_start(&learnStructure, (void*)learnerPtr, threadpool);
 }
 
 
diff -ruN -x .svn stamp-0.9.6/bayes/learner.h trunk/bayes/learner.h
--- stamp-0.9.6/bayes/learner.h	2007-12-01 19:31:27.000000000 +0100
+++ trunk/bayes/learner.h	2008-01-29 17:08:06.000000000 +0100
@@ -107,7 +107,7 @@
  * =============================================================================
  */
 void
-learner_run (learner_t* learnerPtr);
+learner_run (learner_t* learnerPtr, thread_pool_t* threadpool);
 
 
 /* =============================================================================
diff -ruN -x .svn stamp-0.9.6/bayes/Makefile.tanger trunk/bayes/Makefile.tanger
--- stamp-0.9.6/bayes/Makefile.tanger	1970-01-01 01:00:00.000000000 +0100
+++ trunk/bayes/Makefile.tanger	2008-01-29 17:02:14.000000000 +0100
@@ -0,0 +1,17 @@
+# ==============================================================================
+#
+# Makefile.stm
+#
+# ==============================================================================
+
+
+include ../common/Defines.common.tanger
+include ./Defines.common.mk
+include ../common/Makefile.tanger
+
+
+# ==============================================================================
+#
+# End of Makefile.stm
+#
+# ==============================================================================
diff -ruN -x .svn stamp-0.9.6/common/Defines.common.tanger trunk/common/Defines.common.tanger
--- stamp-0.9.6/common/Defines.common.tanger	1970-01-01 01:00:00.000000000 +0100
+++ trunk/common/Defines.common.tanger	2008-01-29 16:27:03.000000000 +0100
@@ -0,0 +1,34 @@
+
+MAKEFILEREL ?= ..
+
+TANGERINCLUDE ?= $(TANGER_HOME)/include
+TANGERLIB     ?= $(TANGER_HOME)/lib
+INCLUDE     += -I $(TANGERINCLUDE) -I ../lib
+STMLIBDIR   ?= $(TANGERLIB)/stmdummy
+STMSUPPORT  ?= $(TANGERLIB)/stmsupport
+SEQUENTIALLIB ?= $(TANGERLIB)/stmdummy/no-tanger.bc
+LLVMBUILD ?= $(shell llvm-config --build-mode)
+TANGERPASS  ?= $(TANGER_HOME)/$(LLVMBUILD)/lib/libtanger.so
+EXTRAPASSES ?=
+PASSESTORUN ?= -tanger
+PASSESTORUNPOST ?= 
+EXTRASTMLIBS ?=
+BASELINKOPTS ?=
+NATIVELIBS  += -lpthread
+NATIVELINKOPTS ?= -g
+HEADERS     ?= $(wildcard $(INCLUDE)/*.h)
+#CFLAGS      ?= -Wall -g
+CFLAGS      += -Wall
+LINKOPTS    ?=
+OPT         ?= opt
+LLVMLD      ?= llvm-ld
+LLVMGCC     ?= llvm-gcc
+LLVMDIS     ?= llvm-dis
+LLC         ?= llc
+GCC         ?= gcc
+# Set this to enable debug output and statistics for the LLVM pass
+#TANGERPASSOPTS ?= -debug -stats
+
+# STAMP:
+LIB := ../lib
+
diff -ruN -x .svn stamp-0.9.6/common/Makefile.tanger trunk/common/Makefile.tanger
--- stamp-0.9.6/common/Makefile.tanger	1970-01-01 01:00:00.000000000 +0100
+++ trunk/common/Makefile.tanger	2008-01-29 17:41:23.000000000 +0100
@@ -0,0 +1,84 @@
+# ==============================================================================
+#
+# Makefile.stm
+#
+# ==============================================================================
+
+
+# ==============================================================================
+# Variables
+# ==============================================================================
+
+CFLAGS   += -DTANGER -I$(TANGER_HOME)/include
+LDFLAGS  += -L$(TANGER_HOME)/lib
+
+
+# ==============================================================================
+# Rules
+# ==============================================================================
+
+BCOBJS := ${SRCS:.c=.bc}
+
+.PHONY: default
+default: $(PROG)
+
+.PHONY: clean
+clean:
+	$(RM) $(OBJS) $(BCOBJS) $(PROG) $(OUTPUT)
+
+# native binary from .bc:
+$(PROG): %: %-tangerstm.bc $(STMLIBDIR)/libtanger-stm.a
+	$(LLC) -f -o $(patsubst %.bc, %.s, $<) $<
+	$(GCC) -o $@ $(patsubst %.bc, %.s, $<) $(STMLIBDIR)/libtanger-stm.a $(NATIVELIBS) $(NATIVELINKOPTS) -lm
+
+# link in .bc parts of STM
+%-tangerstm.bc: %-tanger.bc $(STMLIBDIR)/libtanger-stm.bc
+	$(LLVMLD) -link-as-library -o $@ $< $(STMLIBDIR)/libtanger-stm.bc
+#%-tangerstm.bc: %-tanger.bc $(STMLIBDIR)/libtanger-stm.bc $(EXTRASTMLIBS)
+#	$(LLVMLD) -link-as-library -o $@ $< $(STMLIBDIR)/libtanger-stm.bc $(EXTRASTMLIBS)
+
+
+# run pass over combined
+#%-tanger.bc: %-tangerbase.bc $(TANGERPASS)
+#		$(OPT) -load $(TANGERPASS) -tanger -tanger-stats $< -o $@ -f $(TANGERPASSOPTS)
+#		$(OPT) -load $(TANGERPASS) -tanger $< -o $@ -f $(TANGERPASSOPTS)
+#%-tanger.bc: %-tangerbase.bc $(TANGERPASS)
+%-tanger.bc: %-tangerbase.bc $(TANGERPASS)
+	$(OPT) $(EXTRAPASSES) -load $(TANGERPASS) -internalize -mem2reg -raiseallocs \
+		$(PASSESTORUN) -globaldce $< -o $@.tmp.bc -f $(TANGERPASSOPTS)
+	$(OPT) $(EXTRAPASSES) -load $(TANGERPASS) -deadargelim \
+		$(PASSESTORUNPOST) $@.tmp.bc -o $@ -f $(TANGERPASSOPTS)
+
+
+
+# .bc from sources
+%.bc: %.c $(HEADERS)
+	$(LLVMGCC) $(INCLUDE) -emit-llvm -c $(CFLAGS) -o $@ $<
+
+# disassemble all .bc
+dis: $(patsubst %.bc, %.ll, $(wildcard *.bc)) \
+    $(patsubst %-tangerbase.bc, %-tanger.ll, $(wildcard *.bc))
+%.ll: %.bc
+	$(LLVMDIS) $< -f -o $@
+
+# create sequential versions (use with care!)
+seq: $(patsubst %, %-sequential, $(PROG))
+
+$(patsubst %, %-sequential, $(PROG)): %-sequential: %-tangerbase.bc $(SEQUENTIALLIB)
+	$(LLVMLD) -link-as-library -o $@.bc $^
+	$(LLC) -f -o $@.s $@.bc
+	$(GCC) -o $@ $@.s $(NATIVELIBS) $(NATIVELINKOPTS)
+
+
+$(PROG)-tangerbase.bc: $(BCOBJS)
+	$(LLVMLD) -link-as-library -internalize -o $@ $^ $(BASELINKOPTS)
+#	$(LLVMLD) -link-as-library -disable-inlining -o $@ $^
+
+include ../common/Makefile.common
+
+
+# ==============================================================================
+#
+# End of Makefile.stm
+#
+# ==============================================================================
diff -ruN -x .svn stamp-0.9.6/genome/Defines.common.mk trunk/genome/Defines.common.mk
--- stamp-0.9.6/genome/Defines.common.mk	2007-12-01 19:31:27.000000000 +0100
+++ trunk/genome/Defines.common.mk	2008-01-29 16:43:25.000000000 +0100
@@ -16,6 +16,7 @@
 	segments.c \
 	sequencer.c \
 	table.c \
+	tanger_adapter.c \
 	$(LIB)/bitmap.c \
 	$(LIB)/hash.c \
 	$(LIB)/hashtable.c \
diff -ruN -x .svn stamp-0.9.6/genome/genome.c trunk/genome/genome.c
--- stamp-0.9.6/genome/genome.c	2007-12-01 19:31:27.000000000 +0100
+++ trunk/genome/genome.c	2008-01-29 17:41:42.000000000 +0100
@@ -179,6 +179,7 @@
 {
     TIMER_T start;
     TIMER_T stop;
+    thread_pool_t* threadpool;
 
     GOTO_REAL();
 
@@ -196,7 +197,7 @@
 
     TM_STARTUP(numThread);
     P_MEMORY_STARTUP(numThread);
-    thread_startup(numThread);
+    threadpool = thread_startup(numThread);
 
     random_t* randomPtr = random_alloc();
     assert(randomPtr != NULL);
@@ -224,7 +225,7 @@
     fflush(stdout);
     TIMER_READ(start);
     GOTO_SIM();
-    thread_start(sequencer_run, (void*)sequencerPtr);
+    thread_start(sequencer_run, (void*)sequencerPtr, threadpool);
     GOTO_REAL();
     TIMER_READ(stop);
     puts("done.");
@@ -258,7 +259,7 @@
 
     GOTO_SIM();
 
-    thread_shutdown();
+    thread_shutdown(threadpool);
 
     MAIN_RETURN(0);
 }
diff -ruN -x .svn stamp-0.9.6/genome/Makefile.tanger trunk/genome/Makefile.tanger
--- stamp-0.9.6/genome/Makefile.tanger	1970-01-01 01:00:00.000000000 +0100
+++ trunk/genome/Makefile.tanger	2007-11-02 11:47:37.000000000 +0100
@@ -0,0 +1,17 @@
+# ==============================================================================
+#
+# Makefile.stm
+#
+# ==============================================================================
+
+
+include ../common/Defines.common.tanger
+include ./Defines.common.mk
+include ../common/Makefile.tanger
+
+
+# ==============================================================================
+#
+# End of Makefile.stm
+#
+# ==============================================================================
diff -ruN -x .svn stamp-0.9.6/genome/sequencer.c trunk/genome/sequencer.c
--- stamp-0.9.6/genome/sequencer.c	2007-12-01 19:31:28.000000000 +0100
+++ trunk/genome/sequencer.c	2008-01-29 17:42:13.000000000 +0100
@@ -132,7 +132,10 @@
  * -- For hashtable
  * =============================================================================
  */
-static ulong_t
+#ifndef TANGER
+static 
+#endif 
+ulong_t
 hashSegment (const void* keyPtr)
 {
     return (ulong_t)hash_sdbm((char*)keyPtr); /* can be any "good" hash function */
@@ -144,11 +147,20 @@
  * -- For hashtable
  * =============================================================================
  */
-static long
-compareSegment (const pair_t* a, const pair_t* b)
+#ifndef TANGER
+static long compareSegment (const pair_t* a, const pair_t* b)
 {
     return strcmp((char*)(a->firstPtr), (char*)(b->firstPtr));
 }
+#else
+int tanger_hack_strcmp(const char* s1, const char* s2);
+int tanger_hack_strncmp(const char* s1, const char* s2, int n);
+
+extern long compareSegment (const pair_t* a, const pair_t* b)
+{
+    return tanger_hack_strcmp((char*)(a->firstPtr), (char*)(b->firstPtr));
+}
+#endif
 
 
 /* =============================================================================
@@ -228,11 +240,10 @@
  * sequencer_run
  * =============================================================================
  */
-void
+void*
 sequencer_run (void* argPtr)
 {
     TM_THREAD_ENTER();
-
     long threadId = thread_getId();
 
     sequencer_t* sequencerPtr = (sequencer_t*)argPtr;
@@ -266,7 +277,7 @@
     /*
      * Step 1: Remove duplicate segments
      */
-#if defined(HTM) || defined(STM)
+#if defined(HTM) || defined(STM) || defined(TANGER)
     long numThread = thread_getNumThread();
     {
         /* Choose disjoint segments [i_start,i_stop) for each thread */
@@ -278,10 +289,10 @@
             i_stop = i_start + partitionSize;
         }
     }
-#else /* !(HTM || STM) */
+#else /* !(HTM || STM || TANGER) */
     i_start = 0;
     i_stop = numSegment;
-#endif /* !(HTM || STM) */
+#endif /* !(HTM || STM || TANGER) */
     for (i = i_start; i < i_stop; i+=CHUNK_STEP1) {
         TM_BEGIN();
         {
@@ -322,7 +333,7 @@
     numUniqueSegment = hashtable_getSize(uniqueSegmentsPtr);
     entryIndex = 0;
 
-#if defined(HTM) || defined(STM)
+#if defined(HTM) || defined(STM) || defined(TANGER)
     {
         /* Choose disjoint segments [i_start,i_stop) for each thread */
         long num = uniqueSegmentsPtr->numBucket;
@@ -339,11 +350,11 @@
         long partitionSize = (numUniqueSegment + numThread/2) / numThread; /* with rounding */
         entryIndex = threadId * partitionSize;
     }
-#else /* !(HTM || STM) */
+#else /* !(HTM || STM || TANGER) */
     i_start = 0;
     i_stop = uniqueSegmentsPtr->numBucket;
     entryIndex = 0;
-#endif /* !(HTM || STM) */
+#endif /* !(HTM || STM || TANGER) */
 
     for (i = i_start; i < i_stop; i++) {
 
@@ -403,7 +414,7 @@
                                     (ulong_t)startHash,
                                     (void*)constructEntryPtr);
             TM_END();
-            assert(status);
+            assert(status); /* TODO: What is this for ? */
         }
     }
 
@@ -422,7 +433,7 @@
         long index_start;
         long index_stop;
 
-#if defined(HTM) || defined(STM)
+#if defined(HTM) || defined(STM) || defined(TANGER)
         {
             /* Choose disjoint segments [index_start,index_stop) for each thread */
             long partitionSize = (numUniqueSegment + numThread/2) / numThread; /* with rounding */
@@ -433,10 +444,10 @@
                 index_stop = index_start + partitionSize;
             }
         }
-#else /* !(HTM || STM) */
+#else /* !(HTM || STM || TANGER) */
         index_start = 0;
         index_stop = numUniqueSegment;
-#endif /* !(HTM || STM) */
+#endif /* !(HTM || STM || TANGER) */
 
         /* Iterating over disjoint itervals in the range [0, numUniqueSegment) */
         for (entryIndex = index_start;
@@ -475,7 +486,11 @@
                 /* Check if matches */
                 if (TM_SHARED_READ(startConstructEntryPtr->isStart) &&
                     (TM_SHARED_READ_P(endConstructEntryPtr->startPtr) != startConstructEntryPtr) &&
+#ifndef TANGER
                     (strncmp(startSegment,
+#else
+                    (tanger_hack_strncmp(startSegment,
+#endif
                              &endSegment[segmentLength - substringLength],
                              substringLength) == 0))
                 {
@@ -612,6 +627,7 @@
     }
 
     TM_THREAD_EXIT();
+    return 0;
 }
 
 
diff -ruN -x .svn stamp-0.9.6/genome/sequencer.h trunk/genome/sequencer.h
--- stamp-0.9.6/genome/sequencer.h	2007-12-01 19:31:28.000000000 +0100
+++ trunk/genome/sequencer.h	2008-01-29 15:14:32.000000000 +0100
@@ -128,7 +128,7 @@
  * =============================================================================
  */
 
-void
+void*
 sequencer_run (void* argPtr);
 
 
diff -ruN -x .svn stamp-0.9.6/genome/tanger_adapter.c trunk/genome/tanger_adapter.c
--- stamp-0.9.6/genome/tanger_adapter.c	1970-01-01 01:00:00.000000000 +0100
+++ trunk/genome/tanger_adapter.c	2008-01-29 15:52:50.000000000 +0100
@@ -0,0 +1,117 @@
+#ifdef TANGER
+#warning Workarounds for tanger being used...
+
+#include <assert.h>
+
+/* 
+ * THREAD
+ */
+extern void sequencer_run(void *);
+void __inline__
+thread_translate_funcptr_workaround(void (*f)(void*), void* argPtr) {
+    sequencer_run(argPtr);
+}
+
+#include "../lib/pair.h"
+
+/*
+ * LIST 
+ */
+extern long compareDataPtrAddresses (const void* a, const void* b);
+extern long compareSegment (const pair_t* a, const pair_t* b);
+long __inline__
+list_translate_compare_workaround(long (*f)(const void*, const void*), const void *a, const void *b) {
+	if (f == (long (*)(const void*, const void*))compareSegment) 
+		return compareSegment((pair_t *) a, (pair_t *) b);
+	else if (f == compareDataPtrAddresses) return compareDataPtrAddresses(a, b);
+	else if (f == NULL) assert(0 && "NULL indirect call target");
+  	else assert(0);
+}
+
+/* 
+ * HASHTABLE
+ */
+extern ulong_t hashSegment(const void *keyPtr);
+
+ulong_t __inline__
+hashtable_translate_hash_workaround(ulong_t (*f)(const void *), const void *k) {
+	if (f == hashSegment) 
+		return hashSegment (k);
+	else assert(0);
+}
+
+/*
+ * STR(N)CMP
+ */
+//int 
+//tanger_hack_strncmp(const char* s1, const char* s2, int n){
+//	int i = 0;
+//	while(*s1 && *s2 && *s1 == *s2 && n>i++){
+//		s1++; s2++;
+//	}
+//	if (i == n) return 0;
+//	return (int)*s1 - (int)*s2;
+//}
+int
+tanger_hack_strncmp (const char *s1, const char *s2, int n)
+{
+  unsigned c1 = '\0';
+  unsigned c2 = '\0';
+
+  if (n >= 4)
+    {
+      size_t n4 = n >> 2;
+      do
+        {
+          c1 = (unsigned char) *s1++;
+          c2 = (unsigned char) *s2++;
+          if (c1 == '\0' || c1 != c2)
+            return c1 - c2;
+          c1 = (unsigned char) *s1++;
+          c2 = (unsigned char) *s2++;
+          if (c1 == '\0' || c1 != c2)
+            return c1 - c2;
+          c1 = (unsigned char) *s1++;
+          c2 = (unsigned char) *s2++;
+          if (c1 == '\0' || c1 != c2)
+            return c1 - c2;
+          c1 = (unsigned char) *s1++;
+          c2 = (unsigned char) *s2++;
+          if (c1 == '\0' || c1 != c2)
+            return c1 - c2;
+        } while (--n4 > 0);
+      n &= 3;
+    }
+
+  while (n > 0)
+    {
+      c1 = (unsigned char) *s1++;
+      c2 = (unsigned char) *s2++;
+      if (c1 == '\0' || c1 != c2)
+        return c1 - c2;
+      n--;
+    }
+
+  return c1 - c2;
+}
+
+
+int
+tanger_hack_strcmp (const char *p1, const char *p2)
+{
+  register const unsigned char *s1 = (const unsigned char *) p1;
+  register const unsigned char *s2 = (const unsigned char *) p2;
+  unsigned c1, c2;
+
+  do
+    {
+      c1 = (unsigned char) *s1++;
+      c2 = (unsigned char) *s2++;
+      if (c1 == '\0')
+        return c1 - c2;
+    }
+  while (c1 == c2);
+
+  return c1 - c2;
+}
+#endif /* ! TANGER */
diff -ruN -x .svn stamp-0.9.6/kmeans/cluster.c trunk/kmeans/cluster.c
--- stamp-0.9.6/kmeans/cluster.c	2007-12-01 19:31:28.000000000 +0100
+++ trunk/kmeans/cluster.c	2008-01-29 17:42:27.000000000 +0100
@@ -166,6 +166,7 @@
 int
 cluster_exec (
     int      nthreads,             /* in: number of threads*/
+    void* threadpool,
     int      numObjects,           /* number of input objects */
     int      numAttributes,        /* size of attribute of each object */
     float**  attributes,           /* [numObjects][numAttributes] */
@@ -204,6 +205,7 @@
         random_seed(randomPtr, 7);
 
         tmp_cluster_centres = normal_exec(nthreads,
+                                          threadpool,
                                           attributes,
                                           numAttributes,
                                           numObjects,
diff -ruN -x .svn stamp-0.9.6/kmeans/cluster.h trunk/kmeans/cluster.h
--- stamp-0.9.6/kmeans/cluster.h	2007-12-01 19:31:28.000000000 +0100
+++ trunk/kmeans/cluster.h	2008-01-29 16:17:16.000000000 +0100
@@ -71,6 +71,7 @@
 int
 cluster_exec (
     int      nthreads,             /* in: number of threads*/
+    void* threadpool,
     int      numObjects,           /* number of input objects */
     int      numAttributes,        /* size of attribute of each object */
     float**  attributes,           /* [numObjects][numAttributes] */
diff -ruN -x .svn stamp-0.9.6/kmeans/Defines.common.mk trunk/kmeans/Defines.common.mk
--- stamp-0.9.6/kmeans/Defines.common.mk	2007-12-01 19:31:28.000000000 +0100
+++ trunk/kmeans/Defines.common.mk	2008-01-29 15:16:06.000000000 +0100
@@ -14,6 +14,7 @@
 	common.c \
 	kmeans.c \
 	normal.c \
+	tanger_adapter.c \
 	$(LIB)/mt19937ar.c \
 	$(LIB)/random.c \
 	$(LIB)/thread.c \
diff -ruN -x .svn stamp-0.9.6/kmeans/kmeans.c trunk/kmeans/kmeans.c
--- stamp-0.9.6/kmeans/kmeans.c	2007-12-01 19:31:28.000000000 +0100
+++ trunk/kmeans/kmeans.c	2008-01-29 17:42:34.000000000 +0100
@@ -157,6 +157,7 @@
     int     nthreads;
     float   threshold = 0.001;
     int     opt;
+    thread_pool_t* threadpool;
 
     GOTO_REAL();
 
@@ -271,7 +272,7 @@
     }
 
     TM_STARTUP(nthreads);
-    thread_startup(nthreads);
+    threadpool = thread_startup(nthreads);
 
     /*
      * The core of the clustering
@@ -291,6 +292,7 @@
 
         cluster_centres = NULL;
         cluster_exec(nthreads,
+                     threadpool,
                      numObjects,
                      numAttributes,
                      attributes,           /* [numObjects][numAttributes] */
@@ -376,10 +378,11 @@
     free(buf);
 
     TM_SHUTDOWN();
+    
 
     GOTO_SIM();
 
-    thread_shutdown();
+    thread_shutdown(threadpool);
 
     MAIN_RETURN(0);
 }
diff -ruN -x .svn stamp-0.9.6/kmeans/Makefile.tanger trunk/kmeans/Makefile.tanger
--- stamp-0.9.6/kmeans/Makefile.tanger	1970-01-01 01:00:00.000000000 +0100
+++ trunk/kmeans/Makefile.tanger	2007-11-02 11:48:06.000000000 +0100
@@ -0,0 +1,17 @@
+# ==============================================================================
+#
+# Makefile.stm
+#
+# ==============================================================================
+
+
+include ../common/Defines.common.tanger
+include ./Defines.common.mk
+include ../common/Makefile.tanger
+
+
+# ==============================================================================
+#
+# End of Makefile.stm
+#
+# ==============================================================================
diff -ruN -x .svn stamp-0.9.6/kmeans/normal.c trunk/kmeans/normal.c
--- stamp-0.9.6/kmeans/normal.c	2007-12-01 19:31:29.000000000 +0100
+++ trunk/kmeans/normal.c	2008-01-29 17:42:48.000000000 +0100
@@ -114,7 +114,10 @@
  * work
  * =============================================================================
  */
-static void
+#ifndef TANGER
+static 
+#endif
+void*
 work (void* argPtr)
 {
     TM_THREAD_ENTER();
@@ -136,6 +139,7 @@
     int stop;
     int myId;
 
+
     myId = thread_getId();
 
     start = myId * CHUNK;
@@ -189,6 +193,7 @@
     TM_END();
 
     TM_THREAD_EXIT();
+    return 0;
 }
 
 
@@ -198,6 +203,7 @@
  */
 float**
 normal_exec (int       nthreads,
+             void* threadpool,
              float**   feature,    /* in: [npoints][nfeatures] */
              int       nfeatures,
              int       npoints,
@@ -276,7 +282,7 @@
         global_i = nthreads * CHUNK;
         global_delta = delta;
 
-        thread_start(work, &args);
+        thread_start(work, &args, (thread_pool_t*)threadpool);
 
         delta = global_delta;
 
diff -ruN -x .svn stamp-0.9.6/kmeans/normal.h trunk/kmeans/normal.h
--- stamp-0.9.6/kmeans/normal.h	2007-12-01 19:31:29.000000000 +0100
+++ trunk/kmeans/normal.h	2008-01-29 16:17:16.000000000 +0100
@@ -77,6 +77,7 @@
  */
 float**
 normal_exec (int       nthreads,
+             void* threadpool,
              float**   feature,    /* in: [npoints][nfeatures] */
              int       nfeatures,
              int       npoints,
diff -ruN -x .svn stamp-0.9.6/kmeans/tanger_adapter.c trunk/kmeans/tanger_adapter.c
--- stamp-0.9.6/kmeans/tanger_adapter.c	1970-01-01 01:00:00.000000000 +0100
+++ trunk/kmeans/tanger_adapter.c	2008-01-29 15:53:14.000000000 +0100
@@ -0,0 +1,15 @@
+#ifdef TANGER
+#warning Workarounds for tanger being used...
+
+#include <assert.h>
+
+extern void* work(void *);
+
+__inline__ void*
+thread_translate_funcptr_workaround(void* (*f)(void*), void* argPtr) {
+    assert(f == work && "bad func");
+	return work(argPtr);
+}
+
+
+#endif /* ! TANGER */
diff -ruN -x .svn stamp-0.9.6/labyrinth/Defines.common.mk trunk/labyrinth/Defines.common.mk
--- stamp-0.9.6/labyrinth/Defines.common.mk	2007-12-01 19:31:44.000000000 +0100
+++ trunk/labyrinth/Defines.common.mk	2008-01-29 17:00:38.000000000 +0100
@@ -15,6 +15,7 @@
 	labyrinth.c \
 	maze.c \
 	router.c \
+	tanger_adapter.c \
 	$(LIB)/list.c \
 	$(LIB)/mt19937ar.c \
 	$(LIB)/pair.c \
diff -ruN -x .svn stamp-0.9.6/labyrinth/labyrinth.c trunk/labyrinth/labyrinth.c
--- stamp-0.9.6/labyrinth/labyrinth.c	2007-12-01 19:31:45.000000000 +0100
+++ trunk/labyrinth/labyrinth.c	2008-01-29 16:56:11.000000000 +0100
@@ -174,6 +174,7 @@
  */
 MAIN(argc, argv)
 {
+    thread_pool_t* threadpool;
     GOTO_REAL();
 
     /*
@@ -184,7 +185,7 @@
     SIM_GET_NUM_CPU(numThread);
     TM_STARTUP(numThread);
     P_MEMORY_STARTUP(numThread);
-    thread_startup(numThread);
+    threadpool = thread_startup(numThread);
     maze_t* mazePtr = maze_alloc();
     assert(mazePtr);
     long numPathToRoute = maze_read(mazePtr, global_inputFile);
@@ -203,7 +204,7 @@
     TIMER_T startTime;
     TIMER_READ(startTime);
     GOTO_SIM();
-    thread_start(router_solve, (void*)&routerArg);
+    thread_start(router_solve, (void*)&routerArg, threadpool);
     GOTO_REAL();
     TIMER_T stopTime;
     TIMER_READ(stopTime);
@@ -233,7 +234,7 @@
 
     GOTO_SIM();
 
-    thread_shutdown();
+    thread_shutdown(threadpool);
 
 
     MAIN_RETURN(0);
diff -ruN -x .svn stamp-0.9.6/labyrinth/Makefile.tanger trunk/labyrinth/Makefile.tanger
--- stamp-0.9.6/labyrinth/Makefile.tanger	1970-01-01 01:00:00.000000000 +0100
+++ trunk/labyrinth/Makefile.tanger	2007-11-02 11:47:37.000000000 +0100
@@ -0,0 +1,17 @@
+# ==============================================================================
+#
+# Makefile.stm
+#
+# ==============================================================================
+
+
+include ../common/Defines.common.tanger
+include ./Defines.common.mk
+include ../common/Makefile.tanger
+
+
+# ==============================================================================
+#
+# End of Makefile.stm
+#
+# ==============================================================================
diff -ruN -x .svn stamp-0.9.6/labyrinth/tanger_adapter.c trunk/labyrinth/tanger_adapter.c
--- stamp-0.9.6/labyrinth/tanger_adapter.c	1970-01-01 01:00:00.000000000 +0100
+++ trunk/labyrinth/tanger_adapter.c	2008-01-29 17:00:59.000000000 +0100
@@ -0,0 +1,18 @@
+#ifdef TANGER
+#warning Workarounds for tanger being used...
+
+#include <assert.h>
+#include <stddef.h>
+
+/*
+ * LIST 
+ */
+extern long coordinate_comparePair (const void* aPtr, const void* bPtr);
+long __inline__
+list_translate_compare_workaround(long (*f)(const void*, const void*), const void *a, const void *b) {
+	if (f == coordinate_comparePair) return coordinate_comparePair(a, b);
+	else if (f == NULL) assert(0 && "NULL indirect call target");
+  	else assert(0);
+}
+
+#endif /* ! TANGER */
diff -ruN -x .svn stamp-0.9.6/lib/hashtable.c trunk/lib/hashtable.c
--- stamp-0.9.6/lib/hashtable.c	2007-12-01 19:31:48.000000000 +0100
+++ trunk/lib/hashtable.c	2008-01-29 15:21:11.000000000 +0100
@@ -86,11 +86,18 @@
 #include "pair.h"
 #include "types.h"
 
+#ifdef TANGER
+#define HASHTABLEPTR_HASH(ptr) hashtable_translate_hash_workaround(hashtablePtr->hash, ptr)
+extern ulong_t hashtable_translate_hash_workaround(ulong_t (*)(const void*), const void*);
+#else
+#define HASHTABLEPTR_HASH hashtablePtr->hash
+#endif /* ! TANGER */
+
 #ifdef HAVE_CONFIG_H
 # include "STAMP_config.h"
 #endif
 
-#if defined(HASHTABLE_RESIZABLE) && (defined(HTM) || defined(STM))
+#if defined(HASHTABLE_RESIZABLE) && (defined(HTM) || defined(STM) || defined(TANGER))
 #  warning "hash table resizing currently disabled for TM"
 #endif
 
@@ -541,7 +548,7 @@
 bool_t
 hashtable_containsKey (hashtable_t* hashtablePtr, void* keyPtr)
 {
-    long i = hashtablePtr->hash(keyPtr) % hashtablePtr->numBucket;
+    long i = HASHTABLEPTR_HASH(keyPtr) % hashtablePtr->numBucket;
     pair_t* pairPtr;
     pair_t findPair;
 
@@ -559,7 +566,7 @@
 bool_t
 TMhashtable_containsKey (TM_ARGDECL  hashtable_t* hashtablePtr, void* keyPtr)
 {
-    long i = hashtablePtr->hash(keyPtr) % hashtablePtr->numBucket;
+    long i = HASHTABLEPTR_HASH(keyPtr) % hashtablePtr->numBucket;
     pair_t* pairPtr;
     pair_t findPair;
 
@@ -578,7 +585,7 @@
 void*
 hashtable_find (hashtable_t* hashtablePtr, void* keyPtr)
 {
-    long i = hashtablePtr->hash(keyPtr) % hashtablePtr->numBucket;
+    long i = HASHTABLEPTR_HASH(keyPtr) % hashtablePtr->numBucket;
     pair_t* pairPtr;
     pair_t findPair;
 
@@ -600,7 +607,7 @@
 void*
 TMhashtable_find (TM_ARGDECL  hashtable_t* hashtablePtr, void* keyPtr)
 {
-    long i = hashtablePtr->hash(keyPtr) % hashtablePtr->numBucket;
+    long i = HASHTABLEPTR_HASH(keyPtr) % hashtablePtr->numBucket;
     pair_t* pairPtr;
     pair_t findPair;
 
@@ -614,7 +621,7 @@
 }
 
 
-#if defined(HASHTABLE_RESIZABLE) && !(defined(HTM) || defined(STM))
+#if defined(HASHTABLE_RESIZABLE) && !(defined(HTM) || defined(STM) || defined(TANGER))
 /* =============================================================================
  * rehash
  * =============================================================================
@@ -639,7 +646,7 @@
         list_iter_reset(&it, chainPtr);
         while (list_iter_hasNext(&it, chainPtr)) {
             pair_t* transferPtr = (pair_t*)list_iter_next(&it, chainPtr);
-            long j = hashtablePtr->hash(transferPtr->firstPtr) % newNumBucket;
+            long j = HASHTABLEPTR_HASH(transferPtr->firstPtr) % newNumBucket;
             if (list_insert(newBuckets[j], (void*)transferPtr) == FALSE) {
                 return NULL;
             }
@@ -659,7 +666,7 @@
 hashtable_insert (hashtable_t* hashtablePtr, void* keyPtr, void* dataPtr)
 {
     long numBucket = hashtablePtr->numBucket;
-    long i = hashtablePtr->hash(keyPtr) % numBucket;
+    long i = HASHTABLEPTR_HASH(keyPtr) % numBucket;
 #if defined(HASHTABLE_SIZE_FIELD) || defined(HASHTABLE_RESIZABLE)
     long newSize;
 #endif
@@ -695,7 +702,7 @@
         numBucket *= hashtablePtr->growthFactor;
         hashtablePtr->buckets = newBuckets;
         hashtablePtr->numBucket = numBucket;
-        i = hashtablePtr->hash(keyPtr) % numBucket;
+        i = HASHTABLEPTR_HASH(keyPtr) % numBucket;
 
     }
 #endif
@@ -722,7 +729,7 @@
                     hashtable_t* hashtablePtr, void* keyPtr, void* dataPtr)
 {
     long numBucket = hashtablePtr->numBucket;
-    long i = hashtablePtr->hash(keyPtr) % numBucket;
+    long i = HASHTABLEPTR_HASH(keyPtr) % numBucket;
 
     pair_t findPair;
     findPair.firstPtr = keyPtr;
@@ -761,7 +768,7 @@
 hashtable_remove (hashtable_t* hashtablePtr, void* keyPtr)
 {
     long numBucket = hashtablePtr->numBucket;
-    long i = hashtablePtr->hash(keyPtr) % numBucket;
+    long i = HASHTABLEPTR_HASH(keyPtr) % numBucket;
     list_t* chainPtr = hashtablePtr->buckets[i];
     pair_t* pairPtr;
     pair_t removePair;
@@ -794,7 +801,7 @@
 TMhashtable_remove (TM_ARGDECL  hashtable_t* hashtablePtr, void* keyPtr)
 {
     long numBucket = hashtablePtr->numBucket;
-    long i = hashtablePtr->hash(keyPtr) % numBucket;
+    long i = HASHTABLEPTR_HASH(keyPtr) % numBucket;
     list_t* chainPtr = hashtablePtr->buckets[i];
     pair_t* pairPtr;
     pair_t removePair;
diff -ruN -x .svn stamp-0.9.6/lib/list.c trunk/lib/list.c
--- stamp-0.9.6/lib/list.c	2007-12-01 19:31:48.000000000 +0100
+++ trunk/lib/list.c	2008-01-29 15:55:39.000000000 +0100
@@ -75,12 +75,21 @@
 #include "tm.h"
 
 
+#ifdef TANGER
+extern long list_translate_compare_workaround(long (*)(const void*, const void*), const void *, const void *);
+#define LISTPTR_COMPARE(A,B) compareDefault(listPtr->compare, A,B)
+long __inline__ compareDefault(long (*c)(const void*, const void*), const void *a, const void *b) {
+	return list_translate_compare_workaround(c, a, b);
+}       
+#else
+#define LISTPTR_COMPARE listPtr->compare
+#endif /* ! TANGER */
 /* =============================================================================
  * compareDataPtrAddresses
  * -- Default compare function
  * =============================================================================
  */
-static long
+extern long
 compareDataPtrAddresses (const void* a, const void* b)
 {
     return (long)(a - b);
@@ -499,7 +508,7 @@
          nodePtr != NULL;
          nodePtr = (list_node_t*)TM_SHARED_READ_P(nodePtr->nextPtr))
     {
-        if (listPtr->compare(nodePtr->dataPtr, dataPtr) >= 0) {
+        if (LISTPTR_COMPARE(nodePtr->dataPtr, dataPtr) >= 0) {
             return prevPtr;
         }
         prevPtr = nodePtr;
@@ -545,7 +554,7 @@
     nodePtr = (list_node_t*)TM_SHARED_READ_P(prevPtr->nextPtr);
 
     if ((nodePtr == NULL) ||
-        (listPtr->compare(nodePtr->dataPtr, dataPtr) != 0)) {
+        (LISTPTR_COMPARE(nodePtr->dataPtr, dataPtr) != 0)) {
         return NULL;
     }
 
@@ -639,14 +648,16 @@
     currPtr = (list_node_t*)TM_SHARED_READ_P(prevPtr->nextPtr);
 
 #ifdef LIST_NO_DUPLICATES
-    if ((currPtr != NULL) &&
-        listPtr->compare(currPtr->dataPtr, dataPtr) == 0) {
-        return FALSE;
-    }
+    if ((currPtr != NULL))  // && 
+    	if (LISTPTR_COMPARE(currPtr->dataPtr, dataPtr) == 0) {
+        	return FALSE;
+    	}
+     
 #endif
 
     nodePtr = TMallocNode(TM_ARG  dataPtr);
     if (nodePtr == NULL) {
+    	assert(0);
         return FALSE;
     }
 
@@ -731,7 +742,7 @@
 
     nodePtr = (list_node_t*)TM_SHARED_READ_P(prevPtr->nextPtr);
     if ((nodePtr != NULL) &&
-        (listPtr->compare(nodePtr->dataPtr, dataPtr) == 0))
+        (LISTPTR_COMPARE(nodePtr->dataPtr, dataPtr) == 0))
     {
         TM_SHARED_WRITE_P(prevPtr->nextPtr, TM_SHARED_READ_P(nodePtr->nextPtr));
         TM_SHARED_WRITE_P(nodePtr->nextPtr, (struct list_node*)NULL);
diff -ruN -x .svn stamp-0.9.6/lib/maprbtree-int-void.h trunk/lib/maprbtree-int-void.h
--- stamp-0.9.6/lib/maprbtree-int-void.h	1970-01-01 01:00:00.000000000 +0100
+++ trunk/lib/maprbtree-int-void.h	2008-01-29 16:00:28.000000000 +0100
@@ -0,0 +1,120 @@
+/* =============================================================================
+ *
+ * map.h
+ * -- Utility defines to use hashtable as map
+ *
+ * =============================================================================
+ *
+ * Copyright (C) Stanford University, 2006.  All Rights Reserved.
+ * Author: Chi Cao Minh
+ *
+ * =============================================================================
+ *
+ * For the license of kmeans, please see kmeans/LICENSE.kmeans
+ * 
+ * ------------------------------------------------------------------------
+ * 
+ * For the license of lib/mt19937ar.c and lib/mt19937ar.h, please see the
+ * header of the files.
+ * 
+ * ------------------------------------------------------------------------
+ * 
+ * For the license of lib/rbtree.h and lib/rbtree.c, please see
+ * lib/LEGALNOTICE.rbtree and lib/LICENSE.rbtree
+ * 
+ * ------------------------------------------------------------------------
+ * 
+ * Unless otherwise noted, the following license applies to STAMP files:
+ * 
+ * Copyright (c) 2007, Stanford University
+ * All rights reserved.
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ * 
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ * 
+ *     * Redistributions in binary form must reproduce the above copyright
+ *       notice, this list of conditions and the following disclaimer in
+ *       the documentation and/or other materials provided with the
+ *       distribution.
+ * 
+ *     * Neither the name of Stanford University nor the names of its
+ *       contributors may be used to endorse or promote products derived
+ *       from this software without specific prior written permission.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY STANFORD UNIVERSITY ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL STANFORD UNIVERSITY BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * =============================================================================
+ */
+
+
+#ifndef MAP_H
+#define MAP_H 1
+
+
+#include <stdlib.h>
+#include "pair.h"
+#include "types.h"
+
+
+#if defined(MAP_USE_RBTREE)
+
+#  include "rbtree-int-void.h"
+
+#  define MAP_T                       rbtree_t
+#  define MAP_ALLOC(hash, cmp)        rbtree_alloc()
+#  define MAP_FREE(map)               rbtree_free(map)
+#  define MAP_CONTAINS(map, key)      rbtree_contains(map, (key))
+#  define MAP_FIND(map, key)          rbtree_get(map, (key))
+#  define MAP_INSERT(map, key, data) \
+      ({ \
+          bool_t success = FALSE; \
+          if (rbtree_insert(map, (key), (data)) == 0) { \
+              success = TRUE; \
+          } \
+          success; \
+       })
+#  define MAP_REMOVE(map, key)        rbtree_delete(map, (key))
+
+#  define TMMAP_CONTAINS(map, key)    TMRBTREE_CONTAINS(map, (key))
+#  define TMMAP_FIND(map, key)        TMRBTREE_GET(map, (key))
+#  define TMMAP_INSERT(map, key, data) \
+    ({ \
+        bool_t success = FALSE; \
+        if (TMRBTREE_INSERT(map, (key), (data)) == 0) { \
+            success = TRUE; \
+        } \
+        success; \
+     })
+#  define TMMAP_REMOVE(map, key)      TMRBTREE_DELETE(map, (key))
+
+
+#else
+
+#  error "MAP type is not specified"
+
+#endif
+
+
+#endif /* MAP_H */
+
+
+/* =============================================================================
+ *
+ * End of map.h
+ *
+ * =============================================================================
+ */
diff -ruN -x .svn stamp-0.9.6/lib/memory.h trunk/lib/memory.h
--- stamp-0.9.6/lib/memory.h	2007-12-01 19:31:48.000000000 +0100
+++ trunk/lib/memory.h	2008-01-29 15:55:39.000000000 +0100
@@ -99,7 +99,7 @@
  * =============================================================================
  */
 void
-memory_destroy ();
+memory_destroy (void);
 
 
 /* =============================================================================
diff -ruN -x .svn stamp-0.9.6/lib/queue.h trunk/lib/queue.h
--- stamp-0.9.6/lib/queue.h	2007-12-01 19:31:48.000000000 +0100
+++ trunk/lib/queue.h	2008-01-29 15:55:39.000000000 +0100
@@ -87,7 +87,7 @@
  * =============================================================================
  */
 queue_t*
-queue_alloc ();
+queue_alloc (void);
 
 
 /* =============================================================================
@@ -95,7 +95,7 @@
  * =============================================================================
  */
 queue_t*
-Pqueue_alloc ();
+Pqueue_alloc (void);
 
 
 /* =============================================================================
diff -ruN -x .svn stamp-0.9.6/lib/random.h trunk/lib/random.h
--- stamp-0.9.6/lib/random.h	2007-12-01 19:31:48.000000000 +0100
+++ trunk/lib/random.h	2008-01-29 15:55:39.000000000 +0100
@@ -93,7 +93,7 @@
  * =============================================================================
  */
 random_t*
-random_alloc ();
+random_alloc (void);
 
 
 /* =============================================================================
diff -ruN -x .svn stamp-0.9.6/lib/rbtree.h trunk/lib/rbtree.h
--- stamp-0.9.6/lib/rbtree.h	2007-12-01 19:31:48.000000000 +0100
+++ trunk/lib/rbtree.h	2008-01-29 15:55:39.000000000 +0100
@@ -117,7 +117,7 @@
  * =============================================================================
  */
 rbtree_t*
-rbtree_alloc ();
+rbtree_alloc (void);
 
 
 /* =============================================================================
diff -ruN -x .svn stamp-0.9.6/lib/rbtree-int-void.c trunk/lib/rbtree-int-void.c
--- stamp-0.9.6/lib/rbtree-int-void.c	1970-01-01 01:00:00.000000000 +0100
+++ trunk/lib/rbtree-int-void.c	2008-01-29 15:55:39.000000000 +0100
@@ -0,0 +1,1439 @@
+/* =============================================================================
+ *
+ * rbtree.c
+ * -- Red-black balanced binary search tree
+ *
+ * =============================================================================
+ *
+ * Copyright (C) Sun Microsystems Inc., 2006.  All Rights Reserved.
+ * Authors: Dave Dice, Nir Shavit, Ori Shalev.
+ *
+ * STM: Transactional Locking for Disjoint Access Parallelism
+ *
+ * Transactional Locking II,
+ * Dave Dice, Ori Shalev, Nir Shavit
+ * DISC 2006, Sept 2006, Stockholm, Sweden.
+ *
+ * =============================================================================
+ *
+ * Modified by Chi Cao Minh, Aug 2006
+ *
+ * =============================================================================
+ *
+ * For the license of kmeans, please see kmeans/LICENSE.kmeans
+ * 
+ * ------------------------------------------------------------------------
+ * 
+ * For the license of lib/mt19937ar.c and lib/mt19937ar.h, please see the
+ * header of the files.
+ * 
+ * ------------------------------------------------------------------------
+ * 
+ * For the license of lib/rbtree.h and lib/rbtree.c, please see
+ * lib/LEGALNOTICE.rbtree and lib/LICENSE.rbtree
+ * 
+ * ------------------------------------------------------------------------
+ * 
+ * Unless otherwise noted, the following license applies to STAMP files:
+ * 
+ * Copyright (c) 2007, Stanford University
+ * All rights reserved.
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ * 
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ * 
+ *     * Redistributions in binary form must reproduce the above copyright
+ *       notice, this list of conditions and the following disclaimer in
+ *       the documentation and/or other materials provided with the
+ *       distribution.
+ * 
+ *     * Neither the name of Stanford University nor the names of its
+ *       contributors may be used to endorse or promote products derived
+ *       from this software without specific prior written permission.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY STANFORD UNIVERSITY ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL STANFORD UNIVERSITY BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * =============================================================================
+ */
+
+
+#include <string.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <inttypes.h>
+#include "memory.h"
+#include "rbtree-int-void.h"
+#include "tm.h"
+
+#define LDA(a)              *(a)
+#define STA(a,v)            *(a) = (v)
+#define LDV(a)              (a)
+#define STV(a,v)            (a) = (v)
+#define LDF(o,f)            ((o)->f)
+#define STF(o,f,v)          ((o)->f) = (v)
+//#define LDNODE(o,f)         ((node_t*) (LDF((o),f)))
+#define LDNODE(o,f)         ((LDF((o),f)))
+
+#define TX_LDA(a)           TM_SHARED_READ(*(a))
+#define TX_STA(a,v)         TM_SHARED_WRITE(*(a), v)
+#define TX_LDV(a)           TM_SHARED_READ(a)
+#define TX_STV(a,v)         TM_SHARED_WRITE_P(a, v)
+#define TX_LDF(o,f)         TM_SHARED_READ((o)->f)
+#define TX_LDF_P(o,f)       TM_SHARED_READ_P((o)->f)
+#define TX_STF(o,f,v)       TM_SHARED_WRITE((o)->f, v)
+#define TX_STF_P(o,f,v)     TM_SHARED_WRITE_P((o)->f, v)
+//#define TX_LDNODE(o,f)      ((node_t*) (TX_LDF_P((o),f)))
+#define TX_LDNODE(o,f)      ((TX_LDF_P((o),f)))
+
+enum {
+    RED   = 0,
+    BLACK = 1
+};
+
+
+/*
+ * See also:
+ * - Doug Lea's j.u.TreeMap
+ * - Keir Fraser's rb_stm.c and rb_lock_serialisedwriters.c in libLtx.
+ *
+ * Following Doug Lea's TreeMap example, we avoid the use of the magic
+ * "nil" sentinel pointers.  The sentinel is simply a convenience and
+ * is not fundamental to the algorithm.  We forgo the sentinel as
+ * it is a source of false+ data conflicts in transactions.  Relatedly,
+ * even with locks, use of a nil sentil can result in considerable
+ * cache coherency traffic on traditional SMPs.
+ */
+
+
+/* =============================================================================
+ * lookup
+ * =============================================================================
+ */
+static node_t*
+lookup (rbtree_t* s, long k)
+{
+    node_t* p = LDNODE(s, root);
+
+    while (p != NULL) {
+        long cmp = k - LDF(p, k);
+        if (cmp == 0) {
+            return p;
+        }
+        p = ((cmp < 0) ? LDNODE(p, l) : LDNODE(p, r));
+    }
+
+    return NULL;
+}
+#define LOOKUP(set, key)  lookup(set, key)
+
+
+/* =============================================================================
+ * TMlookup
+ * =============================================================================
+ */
+static node_t*
+TMlookup (TM_ARGDECL  rbtree_t* s, long k)
+{
+    node_t* p = TX_LDNODE(s, root);
+
+    while (p != NULL) {
+        long cmp = k - TX_LDF(p, k);
+        if (cmp == 0) {
+            return p;
+        }
+        p = ((cmp < 0) ? TX_LDNODE(p, l) : TX_LDNODE(p, r));
+    }
+
+    return NULL;
+}
+#define TX_LOOKUP(set, key)  TMlookup(TM_ARG  set, key)
+
+
+/*
+ * Balancing operations.
+ *
+ * Implementations of rebalancings during insertion and deletion are
+ * slightly different than the CLR version.  Rather than using dummy
+ * nilnodes, we use a set of accessors that deal properly with null.  They
+ * are used to avoid messiness surrounding nullness checks in the main
+ * algorithms.
+ *
+ * From CLR
+ */
+
+
+/* =============================================================================
+ * rotateLeft
+ * =============================================================================
+ */
+static void
+rotateLeft (rbtree_t* s, node_t* x )
+{
+    node_t* r = LDNODE(x, r); /* AKA r, y */
+    node_t* rl = LDNODE(r, l);
+    STF(x, r, rl);
+    if (rl != NULL) {
+        STF(rl, p, x);
+    }
+    /* TODO: compute p = xp = x->p.  Use xp for R-Values in following */
+    node_t* xp = LDNODE(x, p);
+    STF(r, p, xp);
+    if (xp == NULL) {
+        STF(s, root, r);
+    } else if (LDNODE(xp, l) == x) {
+        STF(xp, l, r);
+    } else {
+        STF(xp, r, r);
+    }
+    STF(r, l, x);
+    STF(x, p, r);
+}
+#define ROTATE_LEFT(set, node)  rotateLeft(set, node)
+
+
+/* =============================================================================
+ * TMrotateLeft
+ * =============================================================================
+ */
+static void
+TMrotateLeft (TM_ARGDECL  rbtree_t* s, node_t* x)
+{
+    node_t* r = TX_LDNODE(x, r); /* AKA r, y */
+    node_t* rl = TX_LDNODE(r, l);
+    TX_STF_P(x, r, rl);
+    if (rl != NULL) {
+        TX_STF_P(rl, p, x);
+    }
+    /* TODO: compute p = xp = x->p.  Use xp for R-Values in following */
+    node_t* xp = TX_LDNODE(x, p);
+    TX_STF_P(r, p, xp);
+    if (xp == NULL) {
+        TX_STF_P(s, root, r);
+    } else if (TX_LDNODE(xp, l) == x) {
+        TX_STF_P(xp, l, r);
+    } else {
+        TX_STF_P(xp, r, r);
+    }
+    TX_STF_P(r, l, x);
+    TX_STF_P(x, p, r);
+}
+#define TX_ROTATE_LEFT(set, node)  TMrotateLeft(TM_ARG  set, node)
+
+
+/* =============================================================================
+ * rotateRight
+ * =============================================================================
+ */
+static void
+rotateRight (rbtree_t* s, node_t* x)
+{
+    node_t* l = LDNODE(x, l); /* AKA l,y */
+    node_t* lr = LDNODE(l, r);
+    STF(x, l, lr);
+    if (lr != NULL) {
+        STF(lr, p, x);
+    }
+    node_t* xp = LDNODE(x, p);
+    STF(l, p, xp);
+    if (xp == NULL) {
+        STF(s, root, l);
+    } else if (LDNODE(xp, r) == x) {
+        STF(xp, r, l);
+    } else {
+        STF(xp, l, l);
+    }
+    STF(l, r, x);
+    STF(x, p, l);
+}
+#define ROTATE_RIGHT(set, node)  rotateRight(set, node)
+
+
+/* =============================================================================
+ * TMrotateRight
+ * =============================================================================
+ */
+static void
+TMrotateRight (TM_ARGDECL  rbtree_t* s, node_t* x)
+{
+    node_t* l = TX_LDNODE(x, l); /* AKA l,y */
+    node_t* lr = TX_LDNODE(l, r);
+    TX_STF_P(x, l, lr);
+    if (lr != NULL) {
+        TX_STF_P(lr, p, x);
+    }
+    node_t* xp = TX_LDNODE(x, p);
+    TX_STF_P(l, p, xp);
+    if (xp == NULL) {
+        TX_STF_P(s, root, l);
+    } else if (TX_LDNODE(xp, r) == x) {
+        TX_STF_P(xp, r, l);
+    } else {
+        TX_STF_P(xp, l, l);
+    }
+    TX_STF_P(l, r, x);
+    TX_STF_P(x, p, l);
+}
+#define TX_ROTATE_RIGHT(set, node)  TMrotateRight(TM_ARG  set, node)
+
+
+/* =============================================================================
+ * parentOf
+ * =============================================================================
+ */
+static inline node_t*
+parentOf (node_t* n)
+{
+   return (n ? LDNODE(n,p) : NULL);
+}
+#define PARENT_OF(n) parentOf(n)
+
+
+/* =============================================================================
+ * TMparentOf
+ * =============================================================================
+ */
+static inline node_t*
+TMparentOf (TM_ARGDECL  node_t* n)
+{
+   return (n ? TX_LDNODE(n,p) : NULL);
+}
+#define TX_PARENT_OF(n)  TMparentOf(TM_ARG  n)
+
+
+/* =============================================================================
+ * leftOf
+ * =============================================================================
+ */
+static inline node_t*
+leftOf (node_t* n)
+{
+   return (n ? LDNODE(n, l) : NULL);
+}
+#define LEFT_OF(n)  leftOf(n)
+
+
+/* =============================================================================
+ * TMleftOf
+ * =============================================================================
+ */
+static inline node_t*
+TMleftOf (TM_ARGDECL  node_t* n)
+{
+   return (n ? TX_LDNODE(n, l) : NULL);
+}
+#define TX_LEFT_OF(n)  TMleftOf(TM_ARG  n)
+
+
+/* =============================================================================
+ * rightOf
+ * =============================================================================
+ */
+static inline node_t*
+rightOf (node_t* n)
+{
+    return (n ? LDNODE(n, r) : NULL);
+}
+#define RIGHT_OF(n)  rightOf(n)
+
+
+/* =============================================================================
+ * TMrightOf
+ * =============================================================================
+ */
+static inline node_t*
+TMrightOf (TM_ARGDECL  node_t* n)
+{
+    return (n ? TX_LDNODE(n, r) : NULL);
+}
+#define TX_RIGHT_OF(n)  TMrightOf(TM_ARG  n)
+
+
+/* =============================================================================
+ * colorOf
+ * =============================================================================
+ */
+static inline long
+colorOf (node_t* n)
+{
+    return (n ? LDNODE(n, c) : BLACK);
+}
+#define COLOR_OF(n)  colorOf(n)
+
+
+/* =============================================================================
+ * TMcolorOf
+ * =============================================================================
+ */
+static inline long
+TMcolorOf (TM_ARGDECL  node_t* n)
+{
+    return (n ? TX_LDF(n, c) : BLACK);
+}
+#define TX_COLOR_OF(n)  TMcolorOf(TM_ARG  n)
+
+
+/* =============================================================================
+ * setColor
+ * =============================================================================
+ */
+static inline void
+setColor (node_t* n, long c)
+{
+    if (n != NULL) {
+        STF(n, c, c);
+    }
+}
+#define SET_COLOR(n, c)  setColor(n, c)
+
+
+/* =============================================================================
+ * TMsetColor
+ * =============================================================================
+ */
+static inline void
+TMsetColor (TM_ARGDECL  node_t* n, long c)
+{
+    if (n != NULL) {
+        TX_STF(n, c, c);
+    }
+}
+#define TX_SET_COLOR(n, c)  TMsetColor(TM_ARG  n, c)
+
+
+/* =============================================================================
+ * fixAfterInsertion
+ * =============================================================================
+ */
+static void
+fixAfterInsertion (rbtree_t* s, node_t* x)
+{
+    STF(x, c, RED);
+    while (x != NULL && x != LDNODE(s, root)) {
+        node_t* xp = LDNODE(x, p);
+        if (LDF(xp, c) != RED) {
+            break;
+        }
+        /* TODO: cache g = ppx = PARENT_OF(PARENT_OF(x)) */
+        if (PARENT_OF(x) == LEFT_OF(PARENT_OF(PARENT_OF(x)))) {
+            node_t*  y = RIGHT_OF(PARENT_OF(PARENT_OF(x)));
+            if (COLOR_OF(y) == RED) {
+                SET_COLOR(PARENT_OF(x), BLACK);
+                SET_COLOR(y, BLACK);
+                SET_COLOR(PARENT_OF(PARENT_OF(x)), RED);
+                x = PARENT_OF(PARENT_OF(x));
+            } else {
+                if (x == RIGHT_OF(PARENT_OF(x))) {
+                    x = PARENT_OF(x);
+                    ROTATE_LEFT(s, x);
+                }
+                SET_COLOR(PARENT_OF(x), BLACK);
+                SET_COLOR(PARENT_OF(PARENT_OF(x)), RED);
+                if (PARENT_OF(PARENT_OF(x)) != NULL) {
+                    ROTATE_RIGHT(s, PARENT_OF(PARENT_OF(x)));
+                }
+            }
+        } else {
+            node_t* y = LEFT_OF(PARENT_OF(PARENT_OF(x)));
+            if (COLOR_OF(y) == RED) {
+                SET_COLOR(PARENT_OF(x), BLACK);
+                SET_COLOR(y, BLACK);
+                SET_COLOR(PARENT_OF(PARENT_OF(x)), RED);
+                x = PARENT_OF(PARENT_OF(x));
+            } else {
+                if (x == LEFT_OF(PARENT_OF(x))) {
+                    x = PARENT_OF(x);
+                    ROTATE_RIGHT(s, x);
+                }
+                SET_COLOR(PARENT_OF(x),  BLACK);
+                SET_COLOR(PARENT_OF(PARENT_OF(x)), RED);
+                if (PARENT_OF(PARENT_OF(x)) != NULL) {
+                    ROTATE_LEFT(s, PARENT_OF(PARENT_OF(x)));
+                }
+            }
+        }
+    }
+    node_t* ro = LDNODE(s, root);
+    if (LDF(ro, c) != BLACK) {
+        STF(ro, c, BLACK);
+    }
+}
+#define FIX_AFTER_INSERTION(s, x)  fixAfterInsertion(s, x)
+
+
+/* =============================================================================
+ * TMfixAfterInsertion
+ * =============================================================================
+ */
+static void
+TMfixAfterInsertion (TM_ARGDECL  rbtree_t* s, node_t* x)
+{
+    TX_STF(x, c, RED);
+    while (x != NULL && x != TX_LDNODE(s, root)) {
+        node_t* xp = TX_LDNODE(x, p);
+        if (TX_LDF(xp, c) != RED) {
+            break;
+        }
+        /* TODO: cache g = ppx = TX_PARENT_OF(TX_PARENT_OF(x)) */
+        if (TX_PARENT_OF(x) == TX_LEFT_OF(TX_PARENT_OF(TX_PARENT_OF(x)))) {
+            node_t*  y = TX_RIGHT_OF(TX_PARENT_OF(TX_PARENT_OF(x)));
+            if (TX_COLOR_OF(y) == RED) {
+                TX_SET_COLOR(TX_PARENT_OF(x), BLACK);
+                TX_SET_COLOR(y, BLACK);
+                TX_SET_COLOR(TX_PARENT_OF(TX_PARENT_OF(x)), RED);
+                x = TX_PARENT_OF(TX_PARENT_OF(x));
+            } else {
+                if (x == TX_RIGHT_OF(TX_PARENT_OF(x))) {
+                    x = TX_PARENT_OF(x);
+                    TX_ROTATE_LEFT(s, x);
+                }
+                TX_SET_COLOR(TX_PARENT_OF(x), BLACK);
+                TX_SET_COLOR(TX_PARENT_OF(TX_PARENT_OF(x)), RED);
+                if (TX_PARENT_OF(TX_PARENT_OF(x)) != NULL) {
+                    TX_ROTATE_RIGHT(s, TX_PARENT_OF(TX_PARENT_OF(x)));
+                }
+            }
+        } else {
+            node_t* y = TX_LEFT_OF(TX_PARENT_OF(TX_PARENT_OF(x)));
+            if (TX_COLOR_OF(y) == RED) {
+                TX_SET_COLOR(TX_PARENT_OF(x), BLACK);
+                TX_SET_COLOR(y, BLACK);
+                TX_SET_COLOR(TX_PARENT_OF(TX_PARENT_OF(x)), RED);
+                x = TX_PARENT_OF(TX_PARENT_OF(x));
+            } else {
+                if (x == TX_LEFT_OF(TX_PARENT_OF(x))) {
+                    x = TX_PARENT_OF(x);
+                    TX_ROTATE_RIGHT(s, x);
+                }
+                TX_SET_COLOR(TX_PARENT_OF(x),  BLACK);
+                TX_SET_COLOR(TX_PARENT_OF(TX_PARENT_OF(x)), RED);
+                if (TX_PARENT_OF(TX_PARENT_OF(x)) != NULL) {
+                    TX_ROTATE_LEFT(s, TX_PARENT_OF(TX_PARENT_OF(x)));
+                }
+            }
+        }
+    }
+    node_t* ro = TX_LDNODE(s, root);
+    if (TX_LDF(ro, c) != BLACK) {
+        TX_STF(ro, c, BLACK);
+    }
+}
+#define TX_FIX_AFTER_INSERTION(s, x)  TMfixAfterInsertion(TM_ARG  s, x)
+
+
+/* =============================================================================
+ * insert
+ * =============================================================================
+ */
+static node_t*
+insert (rbtree_t* s, long k, void* v, node_t* n)
+{
+    node_t* t  = LDNODE(s, root);
+    if (t == NULL) {
+        if (n == NULL) {
+            return NULL;
+        }
+        /* Note: the following STs don't really need to be transactional */
+        STF(n, l, NULL);
+        STF(n, r, NULL);
+        STF(n, p, NULL);
+        STF(n, k, k);
+        STF(n, v, v);
+        STF(n, c, BLACK);
+        STF(s, root, n);
+        return NULL;
+    }
+
+    for (;;) {
+        long cmp = k - LDF(t, k);
+        if (cmp == 0) {
+            return t;
+        } else if (cmp < 0) {
+            node_t* tl = LDNODE(t, l);
+            if (tl != NULL) {
+                t = tl;
+            } else {
+                STF(n, l, NULL);
+                STF(n, r, NULL);
+                STF(n, k, k);
+                STF(n, v, v);
+                STF(n, p, t);
+                STF(t, l, n);
+                FIX_AFTER_INSERTION(s, n);
+                return NULL;
+            }
+        } else { /* cmp > 0 */
+            node_t* tr = LDNODE(t, r);
+            if (tr != NULL) {
+                t = tr;
+            } else {
+                STF(n, l, NULL);
+                STF(n, r, NULL);
+                STF(n, k, k);
+                STF(n, v, v);
+                STF(n, p, t);
+                STF(t, r, n);
+                FIX_AFTER_INSERTION(s, n);
+                return NULL;
+            }
+        }
+    }
+}
+#define INSERT(s, k, v, n)  insert(s, k, v, n)
+
+
+/* =============================================================================
+ * TMinsert
+ * =============================================================================
+ */
+static node_t*
+TMinsert (TM_ARGDECL  rbtree_t* s, long k, void* v, node_t* n)
+{
+    node_t* t  = TX_LDNODE(s, root);
+    if (t == NULL) {
+        if (n == NULL) {
+            return NULL;
+        }
+        /* Note: the following STs don't really need to be transactional */
+        TX_STF_P(n, l, (node_t*)NULL);
+        TX_STF_P(n, r, (node_t*)NULL);
+        TX_STF_P(n, p, (node_t*)NULL);
+        TX_STF(n, k, k);
+        TX_STF(n, v, v);
+        TX_STF(n, c, BLACK);
+        TX_STF_P(s, root, n);
+        return NULL;
+    }
+
+    for (;;) {
+        long cmp = k - TX_LDF(t, k);
+        if (cmp == 0) {
+            return t;
+        } else if (cmp < 0) {
+            node_t* tl = TX_LDNODE(t, l);
+            if (tl != NULL) {
+                t = tl;
+            } else {
+                TX_STF_P(n, l, (node_t*)NULL);
+                TX_STF_P(n, r, (node_t*)NULL);
+                TX_STF(n, k, k);
+                TX_STF(n, v, v);
+                TX_STF_P(n, p, t);
+                TX_STF_P(t, l, n);
+                TX_FIX_AFTER_INSERTION(s, n);
+                return NULL;
+            }
+        } else { /* cmp > 0 */
+            node_t* tr = TX_LDNODE(t, r);
+            if (tr != NULL) {
+                t = tr;
+            } else {
+                TX_STF_P(n, l, (node_t*)NULL);
+                TX_STF_P(n, r, (node_t*)NULL);
+                TX_STF(n, k, k);
+                TX_STF(n, v, v);
+                TX_STF_P(n, p, t);
+                TX_STF_P(t, r, n);
+                TX_FIX_AFTER_INSERTION(s, n);
+                return NULL;
+            }
+        }
+    }
+}
+#define TX_INSERT(s, k, v, n)  TMinsert(TM_ARG  s, k, v, n)
+
+
+/*
+ * Return the given node's successor node---the node which has the
+ * next key in the the left to right ordering. If the node has
+ * no successor, a null pointer is returned rather than a pointer to
+ * the nil node
+ */
+
+
+/* =============================================================================
+ * successor
+ * =============================================================================
+ */
+static node_t*
+successor (node_t* t)
+{
+    if (t == NULL) {
+        return NULL;
+    } else if (LDNODE(t, r) != NULL) {
+        node_t* p = LDNODE(t, r);
+        while (LDNODE(p, l) != NULL) {
+            p = LDNODE(p, l);
+        }
+        return p;
+    } else {
+        node_t* p = LDNODE(t, p);
+        node_t* ch = t;
+        while (p != NULL && ch == LDNODE(p, r)) {
+            ch = p;
+            p = LDNODE(p, p);
+        }
+        return p;
+    }
+}
+#define SUCCESSOR(n)  successor(n)
+
+
+/* =============================================================================
+ * TMsuccessor
+ * =============================================================================
+ */
+static node_t*
+TMsuccessor  (TM_ARGDECL  node_t* t)
+{
+    if (t == NULL) {
+        return NULL;
+    } else if (TX_LDNODE(t, r) != NULL) {
+        node_t* p = TX_LDNODE(t,r);
+        while (TX_LDNODE(p, l) != NULL) {
+            p = TX_LDNODE(p, l);
+        }
+        return p;
+    } else {
+        node_t* p = TX_LDNODE(t, p);
+        node_t* ch = t;
+        while (p != NULL && ch == TX_LDNODE(p, r)) {
+            ch = p;
+            p = TX_LDNODE(p, p);
+        }
+        return p;
+    }
+}
+#define TX_SUCCESSOR(n)  TMsuccessor(TM_ARG  n)
+
+
+/* =============================================================================
+ * fixAfterDeletion
+ * =============================================================================
+ */
+static void
+fixAfterDeletion (rbtree_t* s, node_t*  x)
+{
+    while (x != LDNODE(s,root) && COLOR_OF(x) == BLACK) {
+        if (x == LEFT_OF(PARENT_OF(x))) {
+            node_t* sib = RIGHT_OF(PARENT_OF(x));
+            if (COLOR_OF(sib) == RED) {
+                SET_COLOR(sib, BLACK);
+                SET_COLOR(PARENT_OF(x), RED);
+                ROTATE_LEFT(s, PARENT_OF(x));
+                sib = RIGHT_OF(PARENT_OF(x));
+            }
+
+            if (COLOR_OF(LEFT_OF(sib))  == BLACK &&
+                COLOR_OF(RIGHT_OF(sib)) == BLACK) {
+                SET_COLOR(sib, RED);
+                x = PARENT_OF(x);
+            } else {
+                if (COLOR_OF(RIGHT_OF(sib)) == BLACK) {
+                    SET_COLOR(LEFT_OF(sib), BLACK);
+                    SET_COLOR(sib, RED);
+                    ROTATE_RIGHT(s, sib);
+                    sib = RIGHT_OF(PARENT_OF(x));
+                }
+                SET_COLOR(sib, COLOR_OF(PARENT_OF(x)));
+                SET_COLOR(PARENT_OF(x), BLACK);
+                SET_COLOR(RIGHT_OF(sib), BLACK);
+                ROTATE_LEFT(s, PARENT_OF(x));
+                /* TODO: consider break ... */
+                x = LDNODE(s,root);
+            }
+        } else { /* symmetric */
+            node_t* sib = LEFT_OF(PARENT_OF(x));
+
+            if (COLOR_OF(sib) == RED) {
+                SET_COLOR(sib, BLACK);
+                SET_COLOR(PARENT_OF(x), RED);
+                ROTATE_RIGHT(s, PARENT_OF(x));
+                sib = LEFT_OF(PARENT_OF(x));
+            }
+
+            if (COLOR_OF(RIGHT_OF(sib)) == BLACK &&
+                COLOR_OF(LEFT_OF(sib)) == BLACK) {
+                SET_COLOR(sib,  RED);
+                x = PARENT_OF(x);
+            } else {
+                if (COLOR_OF(LEFT_OF(sib)) == BLACK) {
+                    SET_COLOR(RIGHT_OF(sib), BLACK);
+                    SET_COLOR(sib, RED);
+                    ROTATE_LEFT(s, sib);
+                    sib = LEFT_OF(PARENT_OF(x));
+                }
+                SET_COLOR(sib, COLOR_OF(PARENT_OF(x)));
+                SET_COLOR(PARENT_OF(x), BLACK);
+                SET_COLOR(LEFT_OF(sib), BLACK);
+                ROTATE_RIGHT(s, PARENT_OF(x));
+                /* TODO: consider break ... */
+                x = LDNODE(s, root);
+            }
+        }
+    }
+
+    if (x != NULL && LDF(x,c) != BLACK) {
+       STF(x, c, BLACK);
+    }
+}
+#define FIX_AFTER_DELETION(s, n)  fixAfterDeletion(s, n)
+
+
+/* =============================================================================
+ * TMfixAfterDeletion
+ * =============================================================================
+ */
+static void
+TMfixAfterDeletion  (TM_ARGDECL  rbtree_t* s, node_t*  x)
+{
+    while (x != TX_LDNODE(s,root) && TX_COLOR_OF(x) == BLACK) {
+        if (x == TX_LEFT_OF(TX_PARENT_OF(x))) {
+            node_t* sib = TX_RIGHT_OF(TX_PARENT_OF(x));
+            if (TX_COLOR_OF(sib) == RED) {
+                TX_SET_COLOR(sib, BLACK);
+                TX_SET_COLOR(TX_PARENT_OF(x), RED);
+                TX_ROTATE_LEFT(s, TX_PARENT_OF(x));
+                sib = TX_RIGHT_OF(TX_PARENT_OF(x));
+            }
+
+            if (TX_COLOR_OF(TX_LEFT_OF(sib))  == BLACK &&
+                TX_COLOR_OF(TX_RIGHT_OF(sib)) == BLACK) {
+                TX_SET_COLOR(sib, RED);
+                x = TX_PARENT_OF(x);
+            } else {
+                if (TX_COLOR_OF(TX_RIGHT_OF(sib)) == BLACK) {
+                    TX_SET_COLOR(TX_LEFT_OF(sib), BLACK);
+                    TX_SET_COLOR(sib, RED);
+                    TX_ROTATE_RIGHT(s, sib);
+                    sib = TX_RIGHT_OF(TX_PARENT_OF(x));
+                }
+                TX_SET_COLOR(sib, TX_COLOR_OF(TX_PARENT_OF(x)));
+                TX_SET_COLOR(TX_PARENT_OF(x), BLACK);
+                TX_SET_COLOR(TX_RIGHT_OF(sib), BLACK);
+                TX_ROTATE_LEFT(s, TX_PARENT_OF(x));
+                /* TODO: consider break ... */
+                x = TX_LDNODE(s,root);
+            }
+        } else { /* symmetric */
+            node_t* sib = TX_LEFT_OF(TX_PARENT_OF(x));
+
+            if (TX_COLOR_OF(sib) == RED) {
+                TX_SET_COLOR(sib, BLACK);
+                TX_SET_COLOR(TX_PARENT_OF(x), RED);
+                TX_ROTATE_RIGHT(s, TX_PARENT_OF(x));
+                sib = TX_LEFT_OF(TX_PARENT_OF(x));
+            }
+
+            if (TX_COLOR_OF(TX_RIGHT_OF(sib)) == BLACK &&
+                TX_COLOR_OF(TX_LEFT_OF(sib)) == BLACK) {
+                TX_SET_COLOR(sib,  RED);
+                x = TX_PARENT_OF(x);
+            } else {
+                if (TX_COLOR_OF(TX_LEFT_OF(sib)) == BLACK) {
+                    TX_SET_COLOR(TX_RIGHT_OF(sib), BLACK);
+                    TX_SET_COLOR(sib, RED);
+                    TX_ROTATE_LEFT(s, sib);
+                    sib = TX_LEFT_OF(TX_PARENT_OF(x));
+                }
+                TX_SET_COLOR(sib, TX_COLOR_OF(TX_PARENT_OF(x)));
+                TX_SET_COLOR(TX_PARENT_OF(x), BLACK);
+                TX_SET_COLOR(TX_LEFT_OF(sib), BLACK);
+                TX_ROTATE_RIGHT(s, TX_PARENT_OF(x));
+                /* TODO: consider break ... */
+                x = TX_LDNODE(s, root);
+            }
+        }
+    }
+
+    if (x != NULL && TX_LDF(x,c) != BLACK) {
+       TX_STF(x, c, BLACK);
+    }
+}
+#define TX_FIX_AFTER_DELETION(s, n)  TMfixAfterDeletion(TM_ARG  s, n )
+
+
+/* =============================================================================
+ * delete_node
+ * =============================================================================
+ */
+static node_t*
+delete_node (rbtree_t* s, node_t* p)
+{
+    /*
+     * If strictly internal, copy successor's element to p and then make p
+     * point to successor
+     */
+    if (LDNODE(p, l) != NULL && LDNODE(p, r) != NULL) {
+        node_t* s = SUCCESSOR(p);
+        STF(p, k, LDNODE(s, k));
+        STF(p, v, LDNODE(s, v));
+        p = s;
+    } /* p has 2 children */
+
+    /* Start fixup at replacement node, if it exists */
+    node_t* replacement =
+        ((LDNODE(p, l) != NULL) ? LDNODE(p, l) : LDNODE(p, r));
+
+    if (replacement != NULL) {
+        /* Link replacement to parent */
+        /* TODO: precompute pp = p->p and substitute below ... */
+        STF (replacement, p, LDNODE(p, p));
+        node_t* pp = LDNODE(p, p);
+        if (pp == NULL) {
+            STF(s, root, replacement);
+        } else if (p == LDNODE(pp, l)) {
+            STF(pp, l, replacement);
+        } else {
+            STF(pp, r, replacement);
+        }
+
+        /* Null out links so they are OK to use by fixAfterDeletion */
+        STF(p, l, NULL);
+        STF(p, r, NULL);
+        STF(p, p, NULL);
+
+        /* Fix replacement */
+        if (LDF(p,c) == BLACK) {
+            FIX_AFTER_DELETION(s, replacement);
+        }
+    } else if (LDNODE(p, p) == NULL) { /* return if we are the only node */
+        STF(s, root, NULL);
+    } else { /* No children. Use self as phantom replacement and unlink */
+        if (LDF(p, c) == BLACK) {
+            FIX_AFTER_DELETION(s, p);
+        }
+        node_t* pp = LDNODE(p, p);
+        if (pp != NULL) {
+            if (p == LDNODE(pp, l)) {
+                STF(pp,l, NULL);
+            } else if (p == LDNODE(pp, r)) {
+                STF(pp, r, NULL);
+            }
+            STF(p, p, NULL);
+        }
+    }
+    return p;
+}
+#define DELETE(s, n)  delete_node(s, n)
+
+
+/* =============================================================================
+ * TMdelete
+ * =============================================================================
+ */
+static node_t*
+TMdelete (TM_ARGDECL  rbtree_t* s, node_t* p)
+{
+    /*
+     * If strictly internal, copy successor's element to p and then make p
+     * point to successor
+     */
+    if (TX_LDNODE(p, l) != NULL && TX_LDNODE(p, r) != NULL) {
+        node_t* s = TX_SUCCESSOR(p);
+        TX_STF(p,k, TX_LDF(s, k));
+        TX_STF(p,v, TX_LDF(s, v));
+        p = s;
+    } /* p has 2 children */
+
+    /* Start fixup at replacement node, if it exists */
+    node_t* replacement =
+        ((TX_LDNODE(p, l) != NULL) ? TX_LDNODE(p, l) : TX_LDNODE(p, r));
+
+    if (replacement != NULL) {
+        /* Link replacement to parent */
+        /* TODO: precompute pp = p->p and substitute below ... */
+        TX_STF_P(replacement, p, TX_LDNODE(p, p));
+        node_t* pp = TX_LDNODE(p, p);
+        if (pp == NULL) {
+            TX_STF_P(s, root, replacement);
+        } else if (p == TX_LDNODE(pp, l)) {
+            TX_STF_P(pp, l, replacement);
+        } else {
+            TX_STF_P(pp, r, replacement);
+        }
+
+        /* Null out links so they are OK to use by fixAfterDeletion */
+        TX_STF_P(p, l, (node_t*)NULL);
+        TX_STF_P(p, r, (node_t*)NULL);
+        TX_STF_P(p, p, (node_t*)NULL);
+
+        /* Fix replacement */
+        if (TX_LDF(p,c) == BLACK) {
+            TX_FIX_AFTER_DELETION(s, replacement);
+        }
+    } else if (TX_LDNODE(p,p) == NULL) { /* return if we are the only node */
+        TX_STF_P(s, root, (node_t*)NULL);
+    } else { /* No children. Use self as phantom replacement and unlink */
+        if (TX_LDF(p,c) == BLACK) {
+            TX_FIX_AFTER_DELETION(s, p);
+        }
+        node_t* pp = TX_LDNODE(p, p);
+        if (pp != NULL) {
+            if (p == TX_LDNODE(pp, l)) {
+                TX_STF_P(pp,l, (node_t*)NULL);
+            } else if (p == TX_LDNODE(pp, r)) {
+                TX_STF_P(pp, r, (node_t*)NULL);
+            }
+            TX_STF_P(p, p, (node_t*)NULL);
+        }
+    }
+    return p;
+}
+#define TX_DELETE(s, n)  TMdelete(TM_ARG  s, n)
+
+
+/*
+ * Diagnostic section
+ */
+
+
+/* =============================================================================
+ * firstEntry
+ * =============================================================================
+ */
+static node_t*
+firstEntry (rbtree_t* s)
+{
+    node_t* p = s->root;
+    if (p != NULL) {
+        while (p->l != NULL) {
+            p = p->l;
+        }
+    }
+    return p;
+}
+
+
+#if 0
+/* =============================================================================
+ * predecessor
+ * =============================================================================
+ */
+static node_t*
+predecessor (node_t* t)
+{
+    if (t == NULL)
+        return NULL;
+    else if (t->l != NULL) {
+        node_t* p = t->l;
+        while (p->r != NULL) {
+            p = p->r;
+        }
+        return p;
+    } else {
+        node_t* p = t->p;
+        node_t* ch = t;
+        while (p != NULL && ch == p->l) {
+            ch = p;
+            p = p->p;
+        }
+        return p;
+    }
+}
+#endif
+
+
+/*
+ * Compute the BH (BlackHeight) and validate the tree.
+ *
+ * This function recursively verifies that the given binary subtree satisfies
+ * three of the red black properties. It checks that every red node has only
+ * black children. It makes sure that each node is either red or black. And it
+ * checks that every path has the same count of black nodes from root to leaf.
+ * It returns the blackheight of the given subtree; this allows blackheights to
+ * be computed recursively and compared for left and right siblings for
+ * mismatches. It does not check for every nil node being black, because there
+ * is only one sentinel nil node. The return value of this function is the
+ * black height of the subtree rooted at the node ``root'', or zero if the
+ * subtree is not red-black.
+ *
+ */
+
+
+/* =============================================================================
+ * verifyRedBlack
+ * =============================================================================
+ */
+static long
+verifyRedBlack (node_t* root, long depth)
+{
+    long height_left;
+    long height_right;
+
+    if (root == NULL) {
+        return 1;
+    }
+
+    height_left  = verifyRedBlack(root->l, depth+1);
+    height_right = verifyRedBlack(root->r, depth+1);
+    if (height_left == 0 || height_right == 0) {
+        return 0;
+    }
+    if (height_left != height_right) {
+        printf(" Imbalance @depth=%ld : %ld %ld\n", depth, height_left, height_right);
+    }
+
+    if (root->l != NULL && root->l->p != root) {
+       printf(" lineage\n");
+    }
+    if (root->r != NULL && root->r->p != root) {
+       printf(" lineage\n");
+    }
+
+    /* Red-Black alternation */
+    if (root->c == RED) {
+        if (root->l != NULL && root->l->c != BLACK) {
+          printf("VERIFY %d\n", __LINE__);
+          return 0;
+        }
+        if (root->r != NULL && root->r->c != BLACK) {
+          printf("VERIFY %d\n", __LINE__);
+          return 0;
+        }
+        return height_left;
+    }
+    if (root->c != BLACK) {
+        printf("VERIFY %d\n", __LINE__);
+        return 0;
+    }
+
+    return (height_left + 1);
+}
+
+
+/* =============================================================================
+ * rbtree_verify
+ * =============================================================================
+ */
+long
+rbtree_verify (rbtree_t* s, long verbose)
+{
+    node_t* root = s->root;
+    if (root == NULL) {
+        return 1;
+    }
+    if (verbose) {
+       printf("Integrity check: ");
+    }
+
+    if (root->p != NULL) {
+        printf("  (WARNING) root %lX parent=%lX\n",
+               (unsigned long)root, (unsigned long)root->p);
+        return -1;
+    }
+    if (root->c != BLACK) {
+        printf("  (WARNING) root %lX color=%lX\n",
+               (unsigned long)root, (unsigned long)root->c);
+    }
+
+    /* Weak check of binary-tree property */
+    long ctr = 0;
+    node_t* its = firstEntry(s);
+    while (its != NULL) {
+        ctr++;
+        node_t* child = its->l;
+        if (child != NULL && child->p != its) {
+            printf("Bad parent\n");
+        }
+        child = its->r;
+        if (child != NULL && child->p != its) {
+            printf("Bad parent\n");
+        }
+        node_t* nxt = successor(its);
+        if (nxt == NULL) {
+            break;
+        }
+        if (its->k >= nxt->k) {
+            printf("Key order %lX (%ld %p) %lX (%ld %p)\n",
+                   (unsigned long)its, its->k, its->v,
+                   (unsigned long)nxt, nxt->k, nxt->v);
+            return -3;
+        }
+        its = nxt;
+    }
+
+    long vfy = verifyRedBlack(root, 0);
+    if (verbose) {
+        printf(" Nodes=%ld Depth=%ld\n", ctr, vfy);
+    }
+
+    return vfy;
+}
+
+
+/* =============================================================================
+ * rbtree_alloc
+ * =============================================================================
+ */
+rbtree_t*
+rbtree_alloc ()
+{
+    rbtree_t* n = (rbtree_t* )malloc(sizeof(*n));
+    n->root = NULL;
+    return n;
+}
+
+
+/* =============================================================================
+ * TMrbtree_alloc
+ * =============================================================================
+ */
+rbtree_t*
+TMrbtree_alloc (TM_ARGDECL_ALONE)
+{
+    rbtree_t* n = (rbtree_t* )TM_MALLOC(sizeof(*n));
+    n->root = NULL;
+    return n;
+}
+
+
+/* =============================================================================
+ * rbtree_free
+ * =============================================================================
+ */
+void
+rbtree_free (rbtree_t* r)
+{
+    free(r);
+}
+
+
+/* =============================================================================
+ * TMrbtree_free
+ * =============================================================================
+ */
+void
+TMrbtree_free (TM_ARGDECL  rbtree_t* r)
+{
+    TM_FREE(r);
+}
+
+
+/* =============================================================================
+ * getNode
+ * =============================================================================
+ */
+static node_t*
+getNode ()
+{
+    node_t* n = (node_t*)malloc(sizeof(*n));
+    return n;
+}
+
+
+/* =============================================================================
+ * TMgetNode
+ * =============================================================================
+ */
+static node_t*
+TMgetNode (TM_ARGDECL_ALONE)
+{
+    node_t* n = (node_t*)TM_MALLOC(sizeof(*n));
+    return n;
+}
+
+
+/* =============================================================================
+ * releaseNode
+ * =============================================================================
+ */
+static void
+releaseNode (node_t* n)
+{
+/* TODO: enable this
+    free(n);
+*/
+}
+
+
+/* =============================================================================
+ * TMreleaseNode
+ * =============================================================================
+ */
+static void
+TMreleaseNode  (TM_ARGDECL  node_t* n)
+{
+    TM_FREE(n);
+}
+
+
+/* =============================================================================
+ * rbtree_insert
+ * =============================================================================
+ */
+long
+rbtree_insert (rbtree_t* r, long key, void* val)
+{
+    node_t* node = getNode();
+    node_t* ex = INSERT(r, key, val, node);
+    if (ex != NULL) {
+        releaseNode(node);
+    }
+    return (ex != NULL);
+}
+
+
+/* =============================================================================
+ * TMrbtree_insert
+ * =============================================================================
+ */
+long
+TMrbtree_insert (TM_ARGDECL  rbtree_t* r, long key, void* val)
+{
+    node_t* node = TMgetNode(TM_ARG_ALONE);
+    node_t* ex = TX_INSERT(r, key, val, node);
+    if (ex != NULL) {
+        TMreleaseNode(TM_ARG  node);
+    }
+    return (ex != NULL);
+}
+
+
+/* =============================================================================
+ * rbtree_delete
+ * =============================================================================
+ */
+long
+rbtree_delete (rbtree_t* r, long key)
+{
+    node_t* node = NULL;
+    node = LOOKUP(r, key);
+    if (node != NULL) {
+        node = DELETE(r, node);
+    }
+    if (node != NULL) {
+        releaseNode(node);
+    }
+    return (node != NULL);
+}
+
+
+/* =============================================================================
+ * TMrbtree_delete
+ * =============================================================================
+ */
+long
+TMrbtree_delete (TM_ARGDECL  rbtree_t* r, long key)
+{
+    node_t* node = NULL;
+    node = TX_LOOKUP(r, key);
+    if (node != NULL) {
+        node = TX_DELETE(r, node);
+    }
+    if (node != NULL) {
+        TMreleaseNode(TM_ARG  node);
+    }
+    return (node != NULL);
+}
+
+
+/* =============================================================================
+ * rbtree_update
+ * =============================================================================
+ */
+long
+rbtree_update (rbtree_t* r, long key, void* val)
+{
+    node_t* nn = getNode();
+    node_t* ex = INSERT(r, key, val, nn);
+    if (ex != NULL) {
+        STF(ex, v, val);
+        releaseNode(nn);
+        return 0;
+    }
+    return 1;
+}
+
+
+/* =============================================================================
+ * TMrbtree_update
+ * =============================================================================
+ */
+long
+TMrbtree_update (TM_ARGDECL  rbtree_t* r, long key, void* val)
+{
+    node_t* nn = TMgetNode(TM_ARG_ALONE);
+    node_t* ex = TX_INSERT(r, key, val, nn);
+    if (ex != NULL) {
+        TX_STF(ex, v, val);
+        TMreleaseNode(TM_ARG  nn);
+        return 0;
+    }
+    return 1;
+}
+
+
+/* =============================================================================
+ * rbtree_get
+ * =============================================================================
+ */
+void*
+rbtree_get (rbtree_t* r, long key) {
+    node_t* n = LOOKUP(r, key);
+    if (n != NULL) {
+        void* val = LDF(n, v);
+        return val;
+    }
+    return 0;
+}
+
+
+/* =============================================================================
+ * TMrbtree_get
+ * =============================================================================
+ */
+void*
+TMrbtree_get (TM_ARGDECL  rbtree_t* r, long key) {
+    node_t* n = TX_LOOKUP(r, key);
+    if (n != NULL) {
+        void* val = TX_LDF(n, v);
+        return val;
+    }
+    return 0;
+}
+
+
+/* =============================================================================
+ * rbtree_contains
+ * =============================================================================
+ */
+long
+rbtree_contains (rbtree_t* r, long key)
+{
+    node_t* n = LOOKUP(r, key);
+    return (n != NULL);
+}
+
+
+/* =============================================================================
+ * TMrbtree_contains
+ * =============================================================================
+ */
+long
+TMrbtree_contains (TM_ARGDECL  rbtree_t* r, long key)
+{
+    node_t* n = TX_LOOKUP(r, key);
+    return (n != NULL);
+}
+
+
+/* =============================================================================
+ *
+ * End of rbtree.c
+ *
+ * =============================================================================
+ */
diff -ruN -x .svn stamp-0.9.6/lib/rbtree-int-void.h trunk/lib/rbtree-int-void.h
--- stamp-0.9.6/lib/rbtree-int-void.h	1970-01-01 01:00:00.000000000 +0100
+++ trunk/lib/rbtree-int-void.h	2008-01-29 15:55:39.000000000 +0100
@@ -0,0 +1,246 @@
+/* =============================================================================
+ *
+ * rbtree.h
+ * -- Red-black balanced binary search tree
+ *
+ * =============================================================================
+ *
+ * Copyright (C) Sun Microsystems Inc., 2006.  All Rights Reserved.
+ * Authors: Dave Dice, Nir Shavit, Ori Shalev.
+ *
+ * STM: Transactional Locking for Disjoint Access Parallelism
+ *
+ * Transactional Locking II,
+ * Dave Dice, Ori Shalev, Nir Shavit
+ * DISC 2006, Sept 2006, Stockholm, Sweden.
+ *
+ * =============================================================================
+ *
+ * Modified by Chi Cao Minh
+ *
+ * =============================================================================
+ *
+ * For the license of kmeans, please see kmeans/LICENSE.kmeans
+ * 
+ * ------------------------------------------------------------------------
+ * 
+ * For the license of lib/mt19937ar.c and lib/mt19937ar.h, please see the
+ * header of the files.
+ * 
+ * ------------------------------------------------------------------------
+ * 
+ * For the license of lib/rbtree.h and lib/rbtree.c, please see
+ * lib/LEGALNOTICE.rbtree and lib/LICENSE.rbtree
+ * 
+ * ------------------------------------------------------------------------
+ * 
+ * Unless otherwise noted, the following license applies to STAMP files:
+ * 
+ * Copyright (c) 2007, Stanford University
+ * All rights reserved.
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ * 
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ * 
+ *     * Redistributions in binary form must reproduce the above copyright
+ *       notice, this list of conditions and the following disclaimer in
+ *       the documentation and/or other materials provided with the
+ *       distribution.
+ * 
+ *     * Neither the name of Stanford University nor the names of its
+ *       contributors may be used to endorse or promote products derived
+ *       from this software without specific prior written permission.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY STANFORD UNIVERSITY ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL STANFORD UNIVERSITY BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * =============================================================================
+ */
+
+
+#ifndef RBTREE_H
+#define RBTREE_H 1
+
+
+#include <inttypes.h>
+#include "tm.h"
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+typedef struct node {
+    long k;
+    void* v;
+    struct node* p;
+    struct node* l;
+    struct node* r;
+    long c;
+} node_t;
+
+
+typedef struct rbtree {
+    node_t* root;
+} rbtree_t;
+
+
+/* =============================================================================
+ * rbtree_verify
+ * =============================================================================
+ */
+long
+rbtree_verify (rbtree_t* s, long verbose);
+
+
+/* =============================================================================
+ * rbtree_alloc
+ * =============================================================================
+ */
+rbtree_t*
+rbtree_alloc (void);
+
+
+/* =============================================================================
+ * TMrbtree_alloc
+ * =============================================================================
+ */
+rbtree_t*
+TMrbtree_alloc (TM_ARGDECL_ALONE);
+
+
+/* =============================================================================
+ * rbtree_free
+ * =============================================================================
+ */
+void
+rbtree_free (rbtree_t* r);
+
+
+/* =============================================================================
+ * TMrbtree_free
+ * =============================================================================
+ */
+void
+TMrbtree_free (TM_ARGDECL  rbtree_t* r);
+
+
+/* =============================================================================
+ * rbtree_insert
+ * =============================================================================
+ */
+long
+rbtree_insert (rbtree_t* r, long key, void* val);
+
+
+/* =============================================================================
+ * TMrbtree_insert
+ * =============================================================================
+ */
+long
+TMrbtree_insert (TM_ARGDECL  rbtree_t* r, long key, void* val);
+
+
+/* =============================================================================
+ * rbtree_delete
+ * =============================================================================
+ */
+long
+rbtree_delete (rbtree_t* r, long key);
+
+
+/* =============================================================================
+ * TMrbtree_delete
+ * =============================================================================
+ */
+long
+TMrbtree_delete (TM_ARGDECL  rbtree_t* r, long key);
+
+
+/* =============================================================================
+ * rbtree_update
+ * =============================================================================
+ */
+long
+rbtree_update (rbtree_t* r, long key, void* val);
+
+
+/* =============================================================================
+ * TMrbtree_update
+ * =============================================================================
+ */
+long
+TMrbtree_update (TM_ARGDECL  rbtree_t* r, long key, void* val);
+
+
+/* =============================================================================
+ * rbtree_get
+ * =============================================================================
+ */
+void*
+rbtree_get (rbtree_t* r, long key);
+
+
+/* =============================================================================
+ * TMrbtree_get
+ * =============================================================================
+ */
+void*
+TMrbtree_get (TM_ARGDECL  rbtree_t* r, long key);
+
+
+/* =============================================================================
+ * rbtree_contains
+ * =============================================================================
+ */
+long
+rbtree_contains (rbtree_t* r, long key);
+
+
+/* =============================================================================
+ * TMrbtree_contains
+ * =============================================================================
+ */
+long
+TMrbtree_contains (TM_ARGDECL  rbtree_t* r, long key);
+
+
+#define TMRBTREE_ALLOC()          TMrbtree_alloc(TM_ARG_ALONE)
+#define TMRBTREE_FREE(r)          TMrbtree_free(TM_ARG  r)
+#define TMRBTREE_INSERT(r, k, v)  TMrbtree_insert(TM_ARG  r, (k), (v))
+#define TMRBTREE_DELETE(r, k)     TMrbtree_delete(TM_ARG  r, (k))
+#define TMRBTREE_UPDATE(r, k, v)  TMrbtree_update(TM_ARG  r, (k), (v))
+#define TMRBTREE_GET(r, k)        TMrbtree_get(TM_ARG  r, (k))
+#define TMRBTREE_CONTAINS(r, k)   TMrbtree_contains(TM_ARG  r, (k))
+
+
+#ifdef __cplusplus
+}
+#endif
+
+
+
+#endif /* RBTREE_H */
+
+
+
+/* =============================================================================
+ *
+ * End of rbtree.h
+ *
+ * =============================================================================
+ */
diff -ruN -x .svn stamp-0.9.6/lib/thread.c trunk/lib/thread.c
--- stamp-0.9.6/lib/thread.c	2007-12-01 19:31:49.000000000 +0100
+++ trunk/lib/thread.c	2008-01-29 16:17:16.000000000 +0100
@@ -67,6 +67,7 @@
 
 #include <assert.h>
 #include <stdlib.h>
+#include <stdio.h>
 #include "thread.h"
 #include "types.h"
 
@@ -76,20 +77,39 @@
 static long*             global_threadIds       = NULL;
 static THREAD_ATTR_T     global_threadAttr;
 static THREAD_T*         global_threads         = NULL;
-static void            (*global_funcPtr)(void*) = NULL;
-static void*             global_argPtr          = NULL;
+static void*            (*global_funcPtr)(void*) = NULL;
+//static void*             global_argPtr          = NULL;
 static volatile bool_t   global_doShutdown      = FALSE;
 
 
+//#ifdef TANGER
+//#define GLOBAL_FUNCPTR(A) thread_translate_funcptr_workaround(global_funcPtr, A)
+//extern void* thread_translate_funcptr_workaround(void* (*)(void*), void *);
+//#else
+#define GLOBAL_FUNCPTR global_funcPtr
+//#endif /* ! TANGER */
+
+struct thread_pool {
+    void* arg;
+};
+
+typedef struct thread_start_info {
+    long* threadId;
+    thread_pool_t* threadpool;
+} thread_start_info_t;
+
 /* =============================================================================
  * threadWait
  * -- Synchronizes all threads to start/stop parallel section
  * =============================================================================
  */
-static void
+static void*
 threadWait (void* argPtr)
 {
-    long threadId = *(long*)argPtr;
+    thread_start_info_t* tsi = (thread_start_info_t*)argPtr;
+    long threadId = *tsi->threadId;
+    thread_pool_t* threadpool = tsi->threadpool;
+    free(tsi);
 
     THREAD_LOCAL_SET(global_threadId, (long)threadId);
 
@@ -98,12 +118,13 @@
         if (global_doShutdown) {
             break;
         }
-        global_funcPtr(global_argPtr);
+        GLOBAL_FUNCPTR(threadpool->arg);
         THREAD_BARRIER(global_barrierPtr, threadId); /* wait for end parallel */
         if (threadId == 0) {
             break;
         }
     }
+    return 0;
 }
 
 
@@ -113,10 +134,11 @@
  * -- numThread is total number of threads (primary + secondaries)
  * =============================================================================
  */
-void
+thread_pool_t*
 thread_startup (long numThread)
 {
     long i;
+    thread_pool_t* threadpool;
 
     global_numThread = numThread;
     global_doShutdown = FALSE;
@@ -141,18 +163,26 @@
     global_threads = (THREAD_T*)malloc(numThread * sizeof(THREAD_T));
     assert(global_threads);
 
+    /* Set up thread pool */
+    threadpool = (thread_pool_t*)malloc(sizeof(thread_pool_t));
+    threadpool->arg = NULL;
+
     /* Set up pool */
     THREAD_ATTR_INIT(global_threadAttr);
     for (i = 1; i < numThread; i++) {
+        thread_start_info_t* tsi = (thread_start_info_t*)malloc(sizeof(thread_start_info_t));
+        tsi->threadId = &global_threadIds[i];
+        tsi->threadpool = threadpool;
         THREAD_CREATE(global_threads[i],
                       global_threadAttr,
                       &threadWait,
-                      &global_threadIds[i]);
+                      tsi);
     }
 
     /*
      * Wait for primary thread to call thread_start
      */
+    return threadpool;
 }
 
 
@@ -164,13 +194,16 @@
  * =============================================================================
  */
 void
-thread_start (void (*funcPtr)(void*), void* argPtr)
+thread_start (void* (*funcPtr)(void*), void* argPtr, thread_pool_t* threadpool)
 {
+    long threadId = 0; 
     global_funcPtr = funcPtr;
-    global_argPtr = argPtr;
-
-    long threadId = 0; /* primary */
-    threadWait((void*)&threadId);
+    
+    thread_start_info_t* tsi = (thread_start_info_t*)malloc(sizeof(thread_start_info_t));
+    tsi->threadId = &threadId; /* primary */
+    tsi->threadpool = threadpool;
+    tsi->threadpool->arg = argPtr;
+    threadWait(tsi);
 }
 
 
@@ -180,7 +213,7 @@
  * =============================================================================
  */
 void
-thread_shutdown ()
+thread_shutdown (thread_pool_t* threadpool)
 {
     /* Make secondary threads exit wait() */
     global_doShutdown = TRUE;
@@ -203,6 +236,7 @@
     global_threads = NULL;
 
     global_numThread = 1;
+    free(threadpool);
 }
 
 
diff -ruN -x .svn stamp-0.9.6/lib/thread.h trunk/lib/thread.h
--- stamp-0.9.6/lib/thread.h	2007-12-01 19:31:49.000000000 +0100
+++ trunk/lib/thread.h	2008-01-29 16:17:16.000000000 +0100
@@ -127,14 +127,16 @@
     long numThread;
 } thread_barrier_t;
 
+typedef struct thread_pool thread_pool_t;
 
 /* =============================================================================
  * thread_startup
  * -- Create pool of secondary threads
  * -- numThread is total number of threads (primary + secondary)
+ * returns a thread pool
  * =============================================================================
  */
-void
+thread_pool_t*
 thread_startup (long numThread);
 
 
@@ -146,7 +148,7 @@
  * =============================================================================
  */
 void
-thread_start (void (*funcPtr)(void*), void* argPtr);
+thread_start (void* (*funcPtr)(void*), void* argPtr, thread_pool_t* threadpool);
 
 
 /* =============================================================================
@@ -155,7 +157,7 @@
  * =============================================================================
  */
 void
-thread_shutdown ();
+thread_shutdown (thread_pool_t* threadpool);
 
 
 /* =============================================================================
@@ -197,7 +199,7 @@
  * =============================================================================
  */
 long
-thread_getId();
+thread_getId(void);
 
 
 /* =============================================================================
@@ -206,7 +208,7 @@
  * =============================================================================
  */
 long
-thread_getNumThread();
+thread_getNumThread(void);
 
 
 /* =============================================================================
@@ -215,7 +217,7 @@
  * =============================================================================
  */
 void
-thread_barrier_wait();
+thread_barrier_wait(void);
 
 
 #ifdef __cplusplus
diff -ruN -x .svn stamp-0.9.6/lib/tm.h trunk/lib/tm.h
--- stamp-0.9.6/lib/tm.h	2007-12-01 19:31:49.000000000 +0100
+++ trunk/lib/tm.h	2008-01-29 15:56:01.000000000 +0100
@@ -355,6 +355,96 @@
 
 
 /* =============================================================================
+ * Tanger 
+ * =============================================================================
+ */
+
+#elif defined(TANGER)
+
+#  include "thread.h"
+#  include <tanger-stm.h>
+#  define TM_ARGDECL           /* nothing */
+#  define TM_ARGDECL_ALONE     void /* nothing */
+#  define TM_ARGDECL_END       /* nothing */
+#  define TM_ARG               /* nothing */
+#  define TM_ARG_ALONE         /* nothing */
+#  define TM_ARG_END           /* nothing */
+#  define TM_NO_ARG            /* nothing */
+#  define TM_NO_ARG_ALONE      /* nothing */
+#  define TM_NO_ARG_END        /* nothing */
+#  define TM_CONSTRUCTOR_ARG   /* nothing */
+#  define TM_THREAD_ARGDECL    //void* _tm_thread_arg
+#  define TM_MEMBERDECL        /* nothing */
+#  define TM_MEMBER_INIT()     /* nothing */
+#  define TM_MEMBER_DISABLE()  /* nothing */
+
+#  define TM_STARTUP(n)        tanger_init()
+#  define TM_SHUTDOWN()        tanger_shutdown()
+
+#  define TM_THREAD_ENTER()    tanger_thread_init(); 
+#  define TM_THREAD_EXIT()     tanger_thread_shutdown()
+#  define TM_BEGIN()           tanger_begin()
+#  define TM_BEGIN_RO()        tanger_begin()
+#  define TM_END()             tanger_commit()
+#  define TM_RESTART()         /* TODO: ??? */
+
+#  define P_MALLOC(size)	   malloc(size)
+#  define P_FREE(ptr)		   free(ptr)
+#  define TM_MALLOC(size)      malloc(size)
+#  define TM_FREE(ptr)         free(ptr)
+
+#  define __TM_INLINE__  static __inline__
+
+
+//#  include "memory.h"
+//extern THREAD_BARRIER_T _tm_global_barrier;
+////extern int _tm_initial_memory_per_thread;
+//extern __thread int _tm_thread_id;
+//extern __thread int _tm_thread_num;
+//
+//#ifndef TM_CACHE_LINE_SIZE
+//#  define TM_CACHE_LINE_SIZE  (64)
+//#endif
+//
+//typedef struct {
+//  int threadId;
+//  int numThread;
+//  void* arg;
+//  THREAD_BARRIER_T *barrier;
+//  char dummy[TM_CACHE_LINE_SIZE]; /* avoid false sharing */
+//} _tm_thread_context_t;
+
+
+/* store size in variable within memory.c */
+//#  define TM_HINT_MEMORY_PER_THREAD(size)  _tm_initial_memory_per_thread=size
+
+//#  define TM_PARALLEL(function,arg_ptr, numThread) 
+//_tm_parallel(function, (void*)arg_ptr, numThread)
+
+
+/*#  define TM_GET_ARG()         _tm_thread_arg
+#  define TM_GET_THREAD_ID()   _tm_thread_id
+#  define TM_GET_NUM_THREAD()  _tm_thread_num
+
+#  define TM_BARRIER() \
+THREAD_BARRIER(&_tm_global_barrier, TM_GET_THREAD_ID());
+*/
+
+//#  define TM_MIXED_MALLOC_SEQ(size)  malloc(size)
+//#  define TM_MIXED_MALLOC_PAR(size)  malloc(size)
+//#  define TM_MIXED_FREE_SEQ(ptr)     free(ptr)
+//#  define TM_MIXED_FREE_PAR(ptr)     free(ptr)
+
+ 
+//__TM_INLINE__ void
+//_tm_parallel (void(*parallel_region)(TM_THREAD_ARGDECL), void* arg, int numThread);
+
+//__TM_INLINE__ void* _tm_mixed_malloc_seq (unsigned int size);
+//__TM_INLINE__ void* _tm_mixed_malloc_par (TM_ARGDECL  unsigned int size);
+//__TM_INLINE__ void _tm_mixed_free_seq (void* ptr);
+//__TM_INLINE__ void _tm_mixed_free_par (TM_ARGDECL  void* ptr);
+
+/* =============================================================================
  * Sequential execution
  * =============================================================================
  */
diff -ruN -x .svn stamp-0.9.6/README.Tanger trunk/README.Tanger
--- stamp-0.9.6/README.Tanger	1970-01-01 01:00:00.000000000 +0100
+++ trunk/README.Tanger	2008-01-29 17:38:06.000000000 +0100
@@ -0,0 +1,23 @@
+To build the benchmarks using Tanger, change into the respective benchmark's
+directory and call:
+
+make -f Makefile.tanger TANGER_HOME=/path/to/Tanger \
+  STMLIBDIR=/path/to/libtanger-stm.{bc,a}
+
+If STMLIBDIR is omitted, Tanger's dummy STM will be used.
+The current set of changes serves three goals:
+1) Work around current limitations in Tanger (e.g., no indirect call support)
+2) Provide transactional versions of library functions (e.g., strncmp())
+3) Improve the precision of DSA (a pointer analysis for LLVM). For example,
+   the "foo()" to "foo(void)" change and the threadpool changes work around
+   limitations in DSA's current implementation. 
+
+Current state:
+-Bayes: not working, needs memset() support by Tanger and transaction qsort()
+-Genome: working (uses transactional strncmp and is thus slower)
+-KMeans: working
+-Labyrinth: not working, needs memcpy() support by Tanger
+-Vacation: working
+
+Changes:
+2008/01/29: upgraded to STAMP 0.9.6, created README.Tanger
\ No newline at end of file
diff -ruN -x .svn stamp-0.9.6/vacation/client.c trunk/vacation/client.c
--- stamp-0.9.6/vacation/client.c	2007-12-01 19:31:43.000000000 +0100
+++ trunk/vacation/client.c	2008-01-29 17:42:58.000000000 +0100
@@ -147,11 +147,10 @@
  * -- Execute list operations on the database
  * =============================================================================
  */
-void
+void*
 client_run (void* argPtr)
 {
     TM_THREAD_ENTER();
-
     long myId = thread_getId();
     client_t* clientPtr = ((client_t**)argPtr)[myId];
 
@@ -303,6 +302,7 @@
     } /* for i */
 
     TM_THREAD_EXIT();
+    return 0;
 }
 
 
diff -ruN -x .svn stamp-0.9.6/vacation/client.h trunk/vacation/client.h
--- stamp-0.9.6/vacation/client.h	2007-12-01 19:31:43.000000000 +0100
+++ trunk/vacation/client.h	2008-01-29 15:33:48.000000000 +0100
@@ -112,7 +112,7 @@
  * -- Execute list operations on the database
  * =============================================================================
  */
-void
+void*
 client_run (void* argPtr);
 
 
diff -ruN -x .svn stamp-0.9.6/vacation/customer.c trunk/vacation/customer.c
--- stamp-0.9.6/vacation/customer.c	2007-12-01 19:31:43.000000000 +0100
+++ trunk/vacation/customer.c	2008-01-29 15:33:48.000000000 +0100
@@ -80,7 +80,10 @@
  * compareReservationInfo
  * =============================================================================
  */
-static long
+#ifndef TANGER
+static 
+#endif
+long
 compareReservationInfo (const void* aPtr, const void* bPtr)
 {
     return reservation_info_compare((reservation_info_t*)aPtr,
diff -ruN -x .svn stamp-0.9.6/vacation/Defines.common.mk trunk/vacation/Defines.common.mk
--- stamp-0.9.6/vacation/Defines.common.mk	2007-12-01 19:31:43.000000000 +0100
+++ trunk/vacation/Defines.common.mk	2008-01-29 16:00:28.000000000 +0100
@@ -16,11 +16,12 @@
 	manager.c \
 	reservation.c \
 	vacation.c \
+	tanger_adapter.c\
 	$(LIB)/list.c \
 	$(LIB)/pair.c \
 	$(LIB)/mt19937ar.c \
 	$(LIB)/random.c \
-	$(LIB)/rbtree.c \
+	$(LIB)/rbtree-int-void.c \
 	$(LIB)/thread.c \
 #
 OBJS := ${SRCS:.c=.o}
diff -ruN -x .svn stamp-0.9.6/vacation/Makefile.tanger trunk/vacation/Makefile.tanger
--- stamp-0.9.6/vacation/Makefile.tanger	1970-01-01 01:00:00.000000000 +0100
+++ trunk/vacation/Makefile.tanger	2007-11-02 11:47:33.000000000 +0100
@@ -0,0 +1,17 @@
+# ==============================================================================
+#
+# Makefile.stm
+#
+# ==============================================================================
+
+
+include ../common/Defines.common.tanger
+include ./Defines.common.mk
+include ../common/Makefile.tanger
+
+
+# ==============================================================================
+#
+# End of Makefile.stm
+#
+# ==============================================================================
diff -ruN -x .svn stamp-0.9.6/vacation/manager.c trunk/vacation/manager.c
--- stamp-0.9.6/vacation/manager.c	2007-12-01 19:31:43.000000000 +0100
+++ trunk/vacation/manager.c	2008-01-29 16:00:28.000000000 +0100
@@ -391,7 +391,8 @@
 manager_deleteCustomer (TM_ARGDECL  manager_t* managerPtr, long customerId)
 {
     customer_t* customerPtr;
-    MAP_T* reservationTables[NUM_RESERVATION_TYPE];
+//    for DSA:
+//    MAP_T* reservationTables[NUM_RESERVATION_TYPE];
     list_t* reservationInfoListPtr;
     list_iter_t it;
     bool_t status;
@@ -401,9 +402,9 @@
         return FALSE;
     }
 
-    reservationTables[RESERVATION_CAR] = managerPtr->carTablePtr;
-    reservationTables[RESERVATION_ROOM] = managerPtr->roomTablePtr;
-    reservationTables[RESERVATION_FLIGHT] = managerPtr->flightTablePtr;
+//    reservationTables[RESERVATION_CAR] = managerPtr->carTablePtr;
+//    reservationTables[RESERVATION_ROOM] = managerPtr->roomTablePtr;
+//    reservationTables[RESERVATION_FLIGHT] = managerPtr->flightTablePtr;
 
     /* Cancel this customer's reservations */
     reservationInfoListPtr = customerPtr->reservationInfoListPtr;
@@ -413,9 +414,17 @@
         reservation_t* reservationPtr;
         reservationInfoPtr =
             (reservation_info_t*)TMLIST_ITER_NEXT(&it, reservationInfoListPtr);
-        reservationPtr =
-            (reservation_t*)TMMAP_FIND(reservationTables[reservationInfoPtr->type],
-                                     reservationInfoPtr->id);
+//            for DSA:
+//        reservationPtr =
+//            (reservation_t*)TMMAP_FIND(reservationTables[reservationInfoPtr->type],
+//                                     reservationInfoPtr->id);
+        if (reservationInfoPtr->type == RESERVATION_CAR)
+            reservationPtr = (reservation_t*)TMMAP_FIND(managerPtr->carTablePtr, reservationInfoPtr->id);
+        else if (reservationInfoPtr->type == RESERVATION_ROOM)
+            reservationPtr = (reservation_t*)TMMAP_FIND(managerPtr->roomTablePtr, reservationInfoPtr->id);
+        else if (reservationInfoPtr->type == RESERVATION_FLIGHT)
+            reservationPtr = (reservation_t*)TMMAP_FIND(managerPtr->flightTablePtr, reservationInfoPtr->id);
+        else assert(0 && "unknown table type");
         if (reservationPtr == NULL) {
             TM_RESTART();
         }
diff -ruN -x .svn stamp-0.9.6/vacation/manager.h trunk/vacation/manager.h
--- stamp-0.9.6/vacation/manager.h	2007-12-01 19:31:44.000000000 +0100
+++ trunk/vacation/manager.h	2008-01-29 16:06:24.000000000 +0100
@@ -70,7 +70,7 @@
 #define MANAGER_H 1
 
 
-#include "map.h"
+#include "maprbtree-int-void.h"
 #include "tm.h"
 #include "types.h"
 
@@ -87,7 +87,7 @@
  * =============================================================================
  */
 manager_t*
-manager_alloc ();
+manager_alloc (void);
 
 
 /* =============================================================================
diff -ruN -x .svn stamp-0.9.6/vacation/tanger_adapter.c trunk/vacation/tanger_adapter.c
--- stamp-0.9.6/vacation/tanger_adapter.c	1970-01-01 01:00:00.000000000 +0100
+++ trunk/vacation/tanger_adapter.c	2007-11-08 11:56:59.000000000 +0100
@@ -0,0 +1,25 @@
+#ifdef TANGER
+#warning Workarounds for tanger being used...
+
+#include <assert.h>
+
+/* 
+ * THREAD WORKAROUND
+ */
+extern void* client_run(void *);
+__inline__ void*
+thread_translate_funcptr_workaround(void* (*f)(void*), void* argPtr) {
+    return client_run(argPtr);
+}
+
+/*
+ * LIST WORKAROUND 
+ */
+extern long compareReservationInfo (const void* aPtr, const void* bPtr);
+long __inline__
+list_translate_compare_workaround(long (*f)(const void*, const void*), const void *a, const void *b) {
+  	if (f == compareReservationInfo){
+ 	 	return compareReservationInfo(a,b);
+  	} else assert(0);
+}
+#endif /* ! TANGER */
diff -ruN -x .svn stamp-0.9.6/vacation/vacation.c trunk/vacation/vacation.c
--- stamp-0.9.6/vacation/vacation.c	2007-12-01 19:31:44.000000000 +0100
+++ trunk/vacation/vacation.c	2008-01-29 17:43:10.000000000 +0100
@@ -73,7 +73,7 @@
 #include "customer.h"
 #include "list.h"
 #include "manager.h"
-#include "map.h"
+#include "maprbtree-int-void.h"
 #include "memory.h"
 #include "operation.h"
 #include "random.h"
@@ -198,13 +198,19 @@
     long numRelation;
     random_t* randomPtr;
     long* ids;
+#ifndef TANGER
     bool_t (*manager_add[])(manager_t*, long, long, long) = {
         &manager_addCar_seq,
         &manager_addFlight_seq,
         &manager_addRoom_seq
     };
+#endif
     long t;
+#ifndef TANGER
     long numTable = sizeof(manager_add) / sizeof(manager_add[0]);
+#else
+	long numTable = NUM_RESERVATION_TYPE;
+#endif
 
     printf("Initializing manager... ");
     fflush(stdout);
@@ -238,7 +244,21 @@
             long id = ids[i];
             long num = ((random_generate(randomPtr) % 5) + 1) * 100;
             long price = ((random_generate(randomPtr) % 5) * 10) + 50;
+#ifdef TANGER
+			switch(t) {
+				case 0:
+					status = manager_addCar_seq   (managerPtr, id, num, price);
+					break;
+				case 1:
+					status = manager_addFlight_seq(managerPtr, id, num, price);
+					break;
+				case 2:
+					status = manager_addRoom_seq  (managerPtr, id, num, price);
+					break;
+			}
+#else
             status = manager_add[t](managerPtr, id, num, price);
+#endif /* ! TANGER */            	            
             assert(status);
         }
 
@@ -323,6 +343,7 @@
     long i;
     long numRelation = (long)global_params[PARAM_RELATIONS];
     MAP_T* customerTablePtr = managerPtr->customerTablePtr;
+#ifndef TANGER
     MAP_T* tables[] = {
         managerPtr->carTablePtr,
         managerPtr->flightTablePtr,
@@ -334,6 +355,9 @@
         &manager_addFlight_seq,
         &manager_addRoom_seq
     };
+#else
+	long numTable = NUM_RESERVATION_TYPE;
+#endif
     long t;
 
     printf("Checking tables... ");
@@ -353,6 +377,41 @@
 
     /* Check reservation tables for consistency and unique ids */
     for (t = 0; t < numTable; t++) {
+#ifdef TANGER
+		if (t == RESERVATION_CAR) {
+        	MAP_T* tablePtr = managerPtr->carTablePtr;
+	        for (i = 1; i <= numRelation; i++) {
+    	        if (MAP_FIND(tablePtr, i)) {
+    	        	assert(manager_addCar_seq(managerPtr, i, 0, 0));
+    	        	if (MAP_REMOVE(tablePtr, i)) {
+                 	   assert(!MAP_REMOVE(tablePtr, i));
+                	}
+    	        }
+	        }
+		}
+		else if (t == RESERVATION_FLIGHT) {
+        	MAP_T* tablePtr = managerPtr->flightTablePtr;
+	        for (i = 1; i <= numRelation; i++) {
+    	        if (MAP_FIND(tablePtr, i)) {
+    	        	assert(manager_addFlight_seq(managerPtr, i, 0, 0));
+    	        	if (MAP_REMOVE(tablePtr, i)) {
+                 	   assert(!MAP_REMOVE(tablePtr, i));
+                	}
+    	        }
+	        }
+		}
+		else if (t == RESERVATION_ROOM) {
+        	MAP_T* tablePtr = managerPtr->roomTablePtr;
+	        for (i = 1; i <= numRelation; i++) {
+    	        if (MAP_FIND(tablePtr, i)) {
+    	        	assert(manager_addRoom_seq(managerPtr, i, 0, 0));
+    	        	if (MAP_REMOVE(tablePtr, i)) {
+                 	   assert(!MAP_REMOVE(tablePtr, i));
+                	}
+    	        }
+	        }
+		}
+#else
         MAP_T* tablePtr = tables[t];
         for (i = 1; i <= numRelation; i++) {
             if (MAP_FIND(tablePtr, i)) {
@@ -362,6 +421,7 @@
                 }
             }
         }
+#endif
     }
 
     puts("done.");
@@ -396,6 +456,7 @@
     client_t** clients;
     TIMER_T start;
     TIMER_T stop;
+    thread_pool_t* threadpool;
 
     GOTO_REAL();
 
@@ -409,14 +470,14 @@
     long numThread = global_params[PARAM_CLIENTS];
     TM_STARTUP(numThread);
     P_MEMORY_STARTUP(numThread);
-    thread_startup(numThread);
+    threadpool = thread_startup(numThread);
 
     /* Run transactions */
     printf("Running clients... ");
     fflush(stdout);
     TIMER_READ(start);
     GOTO_SIM();
-    thread_start(client_run, (void*)clients);
+    thread_start(client_run, (void*)clients, threadpool);
     GOTO_REAL();
     TIMER_READ(stop);
     puts("done.");
@@ -441,7 +502,7 @@
 
     GOTO_SIM();
 
-    thread_shutdown();
+    thread_shutdown(threadpool);
 
     MAIN_RETURN(0);
 }
