From a02bcc05b75bd2b7cfe283a79f356661d47706d6 Mon Sep 17 00:00:00 2001
From: Mark Reynolds <mreynolds@redhat.com>
Date: Tue, 3 Mar 2015 16:46:33 -0500
Subject: [PATCH] Ticket 48047 - include liblfds in nunc-stans

Description:  Add liblfds source to nunc-stans

https://fedorahosted.org/389/ticket/48047

Reviewed by: ?
---
 liblfds/building.txt                               |  38 +
 liblfds/dirs                                       |   2 +
 liblfds/inc/liblfds.h                              | 282 +++++++
 liblfds/liblfds.def                                |  46 ++
 liblfds/liblfds.sln                                |  38 +
 liblfds/liblfds.vcproj                             | 808 +++++++++++++++++++++
 liblfds/makefile.linux                             | 105 +++
 liblfds/makefile.windows                           |  94 +++
 liblfds/readme.txt                                 | 131 ++++
 liblfds/runme_before_win_kernel_build_readme.txt   |  32 +
 .../runme_before_win_kernel_dynamic_lib_build.bat  |  14 +
 .../runme_before_win_kernel_static_lib_build.bat   |  14 +
 liblfds/sources.dynamic                            |  37 +
 liblfds/sources.static                             |  35 +
 liblfds/src/abstraction/abstraction_aligned_free.c |  72 ++
 .../src/abstraction/abstraction_aligned_malloc.c   |  97 +++
 liblfds/src/abstraction/abstraction_cas.c          | 109 +++
 liblfds/src/abstraction/abstraction_dcas.c         | 356 +++++++++
 liblfds/src/abstraction/abstraction_increment.c    | 136 ++++
 liblfds/src/abstraction/abstraction_internal.h     |   5 +
 liblfds/src/dirs                                   |   3 +
 liblfds/src/driver_entry.c                         |  16 +
 liblfds/src/driver_entry_readme.txt                |   4 +
 liblfds/src/freelist/freelist_delete.c             |  35 +
 liblfds/src/freelist/freelist_get_and_set.c        |  33 +
 liblfds/src/freelist/freelist_internal.h           |  42 ++
 liblfds/src/freelist/freelist_new.c                | 123 ++++
 liblfds/src/freelist/freelist_pop_push.c           |  88 +++
 liblfds/src/freelist/freelist_query.c              | 113 +++
 liblfds/src/liblfds_internal.h                     |  12 +
 liblfds/src/queue/queue_delete.c                   |  55 ++
 liblfds/src/queue/queue_internal.h                 |  60 ++
 liblfds/src/queue/queue_new.c                      | 140 ++++
 liblfds/src/queue/queue_query.c                    | 153 ++++
 liblfds/src/queue/queue_queue.c                    | 181 +++++
 liblfds/src/ringbuffer/ringbuffer_delete.c         |  22 +
 liblfds/src/ringbuffer/ringbuffer_get_and_put.c    | 108 +++
 liblfds/src/ringbuffer/ringbuffer_internal.h       |  24 +
 liblfds/src/ringbuffer/ringbuffer_new.c            |  47 ++
 liblfds/src/ringbuffer/ringbuffer_query.c          |  64 ++
 liblfds/src/slist/slist_delete.c                   |  79 ++
 liblfds/src/slist/slist_get_and_set.c              | 124 ++++
 liblfds/src/slist/slist_internal.h                 |  55 ++
 liblfds/src/slist/slist_link.c                     |  53 ++
 liblfds/src/slist/slist_new.c                      |  97 +++
 liblfds/src/stack/stack_delete.c                   |  67 ++
 liblfds/src/stack/stack_internal.h                 |  50 ++
 liblfds/src/stack/stack_new.c                      | 139 ++++
 liblfds/src/stack/stack_push_pop.c                 | 110 +++
 liblfds/src/stack/stack_query.c                    |  30 +
 liblfds/test/building.txt                          |  25 +
 liblfds/test/makefile.linux                        |  81 +++
 liblfds/test/makefile.windows                      |  64 ++
 liblfds/test/src/abstraction.h                     |  50 ++
 liblfds/test/src/abstraction_cpu_count.c           |  81 +++
 liblfds/test/src/abstraction_thread_start.c        | 127 ++++
 liblfds/test/src/abstraction_thread_wait.c         |  71 ++
 liblfds/test/src/benchmark_freelist.c              | 138 ++++
 liblfds/test/src/benchmark_queue.c                 | 142 ++++
 liblfds/test/src/benchmark_ringbuffer.c            | 141 ++++
 liblfds/test/src/benchmark_stack.c                 | 138 ++++
 liblfds/test/src/internal.h                        | 104 +++
 liblfds/test/src/main.c                            |  74 ++
 liblfds/test/src/misc.c                            | 124 ++++
 liblfds/test/src/structures.h                      | 190 +++++
 liblfds/test/src/test_abstraction.c                | 246 +++++++
 liblfds/test/src/test_freelist.c                   | 662 +++++++++++++++++
 liblfds/test/src/test_queue.c                      | 519 +++++++++++++
 liblfds/test/src/test_ringbuffer.c                 | 467 ++++++++++++
 liblfds/test/src/test_slist.c                      | 513 +++++++++++++
 liblfds/test/src/test_stack.c                      | 223 ++++++
 liblfds/test/test.sln                              |  39 +
 liblfds/test/test.vcproj                           | 415 +++++++++++
 73 files changed, 9212 insertions(+)
 create mode 100644 liblfds/building.txt
 create mode 100644 liblfds/dirs
 create mode 100644 liblfds/inc/liblfds.h
 create mode 100644 liblfds/liblfds.def
 create mode 100644 liblfds/liblfds.sln
 create mode 100644 liblfds/liblfds.vcproj
 create mode 100644 liblfds/makefile.linux
 create mode 100644 liblfds/makefile.windows
 create mode 100644 liblfds/readme.txt
 create mode 100644 liblfds/runme_before_win_kernel_build_readme.txt
 create mode 100644 liblfds/runme_before_win_kernel_dynamic_lib_build.bat
 create mode 100644 liblfds/runme_before_win_kernel_static_lib_build.bat
 create mode 100644 liblfds/sources.dynamic
 create mode 100644 liblfds/sources.static
 create mode 100644 liblfds/src/abstraction/abstraction_aligned_free.c
 create mode 100644 liblfds/src/abstraction/abstraction_aligned_malloc.c
 create mode 100644 liblfds/src/abstraction/abstraction_cas.c
 create mode 100644 liblfds/src/abstraction/abstraction_dcas.c
 create mode 100644 liblfds/src/abstraction/abstraction_increment.c
 create mode 100644 liblfds/src/abstraction/abstraction_internal.h
 create mode 100644 liblfds/src/dirs
 create mode 100644 liblfds/src/driver_entry.c
 create mode 100644 liblfds/src/driver_entry_readme.txt
 create mode 100644 liblfds/src/freelist/freelist_delete.c
 create mode 100644 liblfds/src/freelist/freelist_get_and_set.c
 create mode 100644 liblfds/src/freelist/freelist_internal.h
 create mode 100644 liblfds/src/freelist/freelist_new.c
 create mode 100644 liblfds/src/freelist/freelist_pop_push.c
 create mode 100644 liblfds/src/freelist/freelist_query.c
 create mode 100644 liblfds/src/liblfds_internal.h
 create mode 100644 liblfds/src/queue/queue_delete.c
 create mode 100644 liblfds/src/queue/queue_internal.h
 create mode 100644 liblfds/src/queue/queue_new.c
 create mode 100644 liblfds/src/queue/queue_query.c
 create mode 100644 liblfds/src/queue/queue_queue.c
 create mode 100644 liblfds/src/ringbuffer/ringbuffer_delete.c
 create mode 100644 liblfds/src/ringbuffer/ringbuffer_get_and_put.c
 create mode 100644 liblfds/src/ringbuffer/ringbuffer_internal.h
 create mode 100644 liblfds/src/ringbuffer/ringbuffer_new.c
 create mode 100644 liblfds/src/ringbuffer/ringbuffer_query.c
 create mode 100644 liblfds/src/slist/slist_delete.c
 create mode 100644 liblfds/src/slist/slist_get_and_set.c
 create mode 100644 liblfds/src/slist/slist_internal.h
 create mode 100644 liblfds/src/slist/slist_link.c
 create mode 100644 liblfds/src/slist/slist_new.c
 create mode 100644 liblfds/src/stack/stack_delete.c
 create mode 100644 liblfds/src/stack/stack_internal.h
 create mode 100644 liblfds/src/stack/stack_new.c
 create mode 100644 liblfds/src/stack/stack_push_pop.c
 create mode 100644 liblfds/src/stack/stack_query.c
 create mode 100644 liblfds/test/building.txt
 create mode 100644 liblfds/test/makefile.linux
 create mode 100644 liblfds/test/makefile.windows
 create mode 100644 liblfds/test/src/abstraction.h
 create mode 100644 liblfds/test/src/abstraction_cpu_count.c
 create mode 100644 liblfds/test/src/abstraction_thread_start.c
 create mode 100644 liblfds/test/src/abstraction_thread_wait.c
 create mode 100644 liblfds/test/src/benchmark_freelist.c
 create mode 100644 liblfds/test/src/benchmark_queue.c
 create mode 100644 liblfds/test/src/benchmark_ringbuffer.c
 create mode 100644 liblfds/test/src/benchmark_stack.c
 create mode 100644 liblfds/test/src/internal.h
 create mode 100644 liblfds/test/src/main.c
 create mode 100644 liblfds/test/src/misc.c
 create mode 100644 liblfds/test/src/structures.h
 create mode 100644 liblfds/test/src/test_abstraction.c
 create mode 100644 liblfds/test/src/test_freelist.c
 create mode 100644 liblfds/test/src/test_queue.c
 create mode 100644 liblfds/test/src/test_ringbuffer.c
 create mode 100644 liblfds/test/src/test_slist.c
 create mode 100644 liblfds/test/src/test_stack.c
 create mode 100644 liblfds/test/test.sln
 create mode 100644 liblfds/test/test.vcproj

diff --git a/liblfds/building.txt b/liblfds/building.txt
new file mode 100644
index 0000000..df5a0e3
--- /dev/null
+++ b/liblfds/building.txt
@@ -0,0 +1,38 @@
+building liblfds
+================
+
+Windows (user-mode)
+===================
+1. Use Microsoft Visual Studio 2008 or Visual C++ 2008 Express Edition
+   to load "liblfds.sln".
+
+2. Use Microsoft Windows SDK and GNUmake to run makefile.windows (obviously
+   you'll need to have run the appropriate vcvars*.bat first; you can build
+   for both IA64, 64-bit and 32-bit - just run the correct vcvars batch file).
+
+   Targets are "librel", "libdbg", "dllrel", "dlldbg" and "clean".  You need
+   to clean between switching targets.
+
+Windows (kernel)
+================
+Use the Windows Driver Kit "build" command.  Prior to running "build",
+if you wish to build a static library, run the batch file
+"runme_before_win_kernel_static_lib_build.bat"; if you wish to
+build a dynamic library, instead run "runme_before_win_kernel_dynamic_lib_build.bat".
+
+The Windows kernel build system is rather limited and rather than
+really rather messing up the directory/file structure just for the
+Windows kernel platform, I've instead arranged it that these batch
+files do the necessary work so that "build" will work.
+
+The batch files are idempotent; you can run them as often as you
+like, in any order, at any time (before or after builds), and they'll
+do the right thing.
+
+Linux
+=====
+Use GNUmake to run "makefile.linux".  Targets are "arrel", "ardbg",
+"sorel", "sodbg" and "clean".  You need to clean between switching
+targets.
+
+
diff --git a/liblfds/dirs b/liblfds/dirs
new file mode 100644
index 0000000..0be5295
--- /dev/null
+++ b/liblfds/dirs
@@ -0,0 +1,2 @@
+DIRS = src
+
diff --git a/liblfds/inc/liblfds.h b/liblfds/inc/liblfds.h
new file mode 100644
index 0000000..b183c75
--- /dev/null
+++ b/liblfds/inc/liblfds.h
@@ -0,0 +1,282 @@
+#ifndef __LIBLFDS_H
+
+  /***** library header *****/
+  #define LIBLFDS_RELEASE_NUMBER 6
+
+
+
+
+  /***** abstraction *****/
+
+  /***** defines *****/
+  #if (defined _WIN64 && defined _MSC_VER && !defined WIN_KERNEL_BUILD)
+    // TRD : 64-bit Windows user-mode with the Microsoft C compiler, any CPU
+    #include <assert.h>
+    #include <stdio.h>
+    #include <stdlib.h>
+    #include <windows.h>
+    #include <intrin.h>
+    typedef unsigned __int64      atom_t;
+    #define INLINE                extern __forceinline
+    #define ALIGN(alignment)      __declspec( align(alignment) )
+    #define ALIGN_SINGLE_POINTER  8
+    #define ALIGN_DOUBLE_POINTER  16
+  #endif
+
+  #if (!defined _WIN64 && defined _WIN32 && defined _MSC_VER && !defined WIN_KERNEL_BUILD)
+    // TRD : 32-bit Windows user-mode with the Microsoft C compiler, any CPU
+    #include <assert.h>
+    #include <stdio.h>
+    #include <stdlib.h>
+    #include <windows.h>
+    #include <intrin.h>
+    typedef unsigned long int     atom_t;
+    #define INLINE                extern __forceinline
+    #define ALIGN(alignment)      __declspec( align(alignment) )
+    #define ALIGN_SINGLE_POINTER  4
+    #define ALIGN_DOUBLE_POINTER  8
+
+    // TRD : this define is documented but missing in Microsoft Platform SDK v7.0
+    #define _InterlockedCompareExchangePointer(destination, exchange, compare) _InterlockedCompareExchange((volatile long *) destination, (long) exchange, (long) compare)
+  #endif
+
+  #if (defined _WIN64 && defined _MSC_VER && defined WIN_KERNEL_BUILD)
+    // TRD : 64-bit Windows kernel with the Microsoft C compiler, any CPU
+    #include <assert.h>
+    #include <stdio.h>
+    #include <stdlib.h>
+    #include <wdm.h>
+    typedef unsigned __int64      atom_t;
+    #define INLINE                extern __forceinline
+    #define ALIGN(alignment)      __declspec( align(alignment) )
+    #define ALIGN_SINGLE_POINTER  8
+    #define ALIGN_DOUBLE_POINTER  16
+  #endif
+
+  #if (!defined _WIN64 && defined _WIN32 && defined _MSC_VER && defined WIN_KERNEL_BUILD)
+    // TRD : 32-bit Windows kernel with the Microsoft C compiler, any CPU
+    #include <assert.h>
+    #include <stdio.h>
+    #include <stdlib.h>
+    #include <wdm.h>
+    typedef unsigned long int     atom_t;
+    #define INLINE                extern __forceinline
+    #define ALIGN(alignment)      __declspec( align(alignment) )
+    #define ALIGN_SINGLE_POINTER  4
+    #define ALIGN_DOUBLE_POINTER  8
+
+    // TRD : this define is documented but missing in Microsoft Platform SDK v7.0
+    #define _InterlockedCompareExchangePointer(destination, exchange, compare) _InterlockedCompareExchange((volatile long *) destination, (long) exchange, (long) compare)
+  #endif
+
+  #if (defined __unix__ && defined __x86_64__ && __GNUC__)
+    // TRD : any UNIX with GCC on x64
+    #define _XOPEN_SOURCE 600
+    #include <assert.h>
+    #include <stdio.h>
+    #include <stdlib.h>
+    typedef unsigned long long int  atom_t;
+    #define INLINE                  inline
+    #define ALIGN(alignment)        __attribute__( (aligned(alignment)) )
+    #define ALIGN_SINGLE_POINTER    8
+    #define ALIGN_DOUBLE_POINTER    16
+  #endif
+
+  #if (defined __unix__ && defined __i686__ && __GNUC__)
+    // TRD : any UNIX with GCC on x86
+    #define _XOPEN_SOURCE 600
+    #include <assert.h>
+    #include <stdio.h>
+    #include <stdlib.h>
+    typedef unsigned long int     atom_t;
+    #define INLINE                inline
+    #define ALIGN(alignment)      __attribute__( (aligned(alignment)) )
+    #define ALIGN_SINGLE_POINTER  4
+    #define ALIGN_DOUBLE_POINTER  8
+  #endif
+
+  #if (defined __unix__ && defined __arm__ && __GNUC__)
+    // TRD : any UNIX with GCC on ARM
+    #define _XOPEN_SOURCE 600
+    #include <assert.h>
+    #include <stdio.h>
+    #include <stdlib.h>
+    typedef unsigned long int     atom_t;
+    #define INLINE                inline
+    #define ALIGN(alignment)      __attribute__( (aligned(alignment)) )
+    #define ALIGN_SINGLE_POINTER  4
+    #define ALIGN_DOUBLE_POINTER  8
+  #endif
+
+  /***** enums *****/
+  enum data_structure_validity
+  {
+    VALIDITY_VALID,
+    VALIDITY_INVALID_LOOP,
+    VALIDITY_INVALID_MISSING_ELEMENTS,
+    VALIDITY_INVALID_ADDITIONAL_ELEMENTS,
+    VALIDITY_INVALID_TEST_DATA
+  };
+
+  /***** structs *****/
+  struct validation_info
+  {
+    atom_t
+      min_elements,
+      max_elements;
+  };
+
+  /***** public prototypes *****/
+  void abstraction_aligned_free( void *memory );
+  void *abstraction_aligned_malloc( size_t size, size_t align_in_bytes );
+  atom_t abstraction_cas( volatile atom_t *destination, atom_t exchange, atom_t compare );
+  unsigned char abstraction_dcas( volatile atom_t *destination, atom_t *exchange, atom_t *compare );
+  atom_t abstraction_increment( atom_t *value );
+
+
+
+
+
+  /***** freelist *****/
+
+  /***** enums *****/
+  enum freelist_query_type
+  {
+    FREELIST_QUERY_ELEMENT_COUNT,
+    FREELIST_QUERY_VALIDATE
+  };
+
+  /***** incomplete types *****/
+  struct freelist_state;
+  struct freelist_element;
+
+  /***** public prototypes *****/
+  int freelist_new( struct freelist_state **fs, atom_t number_elements, int (*user_data_init_function)(void **user_data, void *user_state), void *user_state );
+  void freelist_delete( struct freelist_state *fs, void (*user_data_delete_function)(void *user_data, void *user_state), void *user_state );
+
+  atom_t freelist_new_elements( struct freelist_state *fs, atom_t number_elements );
+
+  struct freelist_element *freelist_pop( struct freelist_state *fs, struct freelist_element **fe );
+  struct freelist_element *freelist_guaranteed_pop( struct freelist_state *fs, struct freelist_element **fe );
+  void freelist_push( struct freelist_state *fs, struct freelist_element *fe );
+
+  void *freelist_get_user_data_from_element( struct freelist_element *fe, void **user_data );
+  void freelist_set_user_data_in_element( struct freelist_element *fe, void *user_data );
+
+  void freelist_query( struct freelist_state *fs, enum freelist_query_type query_type, void *query_input, void *query_output );
+
+
+
+
+
+  /***** queue *****/
+
+  /***** enums *****/
+  enum queue_query_type
+  {
+    QUEUE_QUERY_ELEMENT_COUNT,
+    QUEUE_QUERY_VALIDATE
+  };
+
+  /***** incomplete types *****/
+  struct queue_state;
+
+  /***** public prototypes *****/
+  int queue_new( struct queue_state **sq, atom_t number_elements );
+  void queue_delete( struct queue_state *qs, void (*user_data_delete_function)(void *user_data, void *user_state), void *user_state );
+
+  int queue_enqueue( struct queue_state *qs, void *user_data );
+  int queue_guaranteed_enqueue( struct queue_state *qs, void *user_data );
+  int queue_dequeue( struct queue_state *qs, void **user_data );
+
+  void queue_query( struct queue_state *qs, enum queue_query_type query_type, void *query_input, void *query_output );
+
+
+
+
+
+  /***** ringbuffer *****/
+
+  /***** enums *****/
+  enum ringbuffer_query_type
+  {
+    RINGBUFFER_QUERY_VALIDATE
+  };
+
+  /***** incomplete types *****/
+  struct ringbuffer_state;
+
+  /***** public prototypes *****/
+  int ringbuffer_new( struct ringbuffer_state **rs, atom_t number_elements, int (*user_data_init_function)(void **user_data, void *user_state), void *user_state );
+  void ringbuffer_delete( struct ringbuffer_state *rs, void (*user_data_delete_function)(void *user_data, void *user_state), void *user_state );
+
+  struct freelist_element *ringbuffer_get_read_element( struct ringbuffer_state *rs, struct freelist_element **fe );
+  struct freelist_element *ringbuffer_get_write_element( struct ringbuffer_state *rs, struct freelist_element **fe, int *overwrite_flag );
+
+  void ringbuffer_put_read_element( struct ringbuffer_state *rs, struct freelist_element *fe );
+  void ringbuffer_put_write_element( struct ringbuffer_state *rs, struct freelist_element *fe );
+
+  void ringbuffer_query( struct ringbuffer_state *rs, enum ringbuffer_query_type query_type, void *query_input, void *query_output );
+
+
+
+
+
+  /***** slist *****/
+
+  /***** incomplete types *****/
+  struct slist_state;
+  struct slist_element;
+
+  /***** public prototypes *****/
+  int slist_new( struct slist_state **ss, void (*user_data_delete_function)(void *user_data, void *user_state), void *user_state );
+  void slist_delete( struct slist_state *ss );
+
+  struct slist_element *slist_new_head( struct slist_state *ss, void *user_data );
+  struct slist_element *slist_new_next( struct slist_element *se, void *user_data );
+
+  void slist_delete_element( struct slist_state *ss, struct slist_element *se );
+  void slist_delete_all_elements( struct slist_state *ss );
+
+  int slist_get_user_data_from_element( struct slist_element *se, void **user_data );
+  int slist_set_user_data_in_element( struct slist_element *se, void *user_data );
+
+  struct slist_element *slist_get_head( struct slist_state *ss, struct slist_element **se );
+  struct slist_element *slist_get_next( struct slist_element *se, struct slist_element **next_se );
+  struct slist_element *slist_get_head_and_then_next( struct slist_state *ss, struct slist_element **se );
+
+
+
+
+
+  /***** stack *****/
+
+  /***** enums *****/
+  enum stack_query_type
+  {
+    STACK_QUERY_ELEMENT_COUNT
+  };
+
+  /***** incomplete types *****/
+  struct stack_state;
+
+  /***** public prototypes *****/
+  int stack_new( struct stack_state **ss, atom_t number_elements );
+  void stack_delete( struct stack_state *ss, void (*user_data_delete_function)(void *user_data, void *user_state), void *user_state );
+
+  void stack_clear( struct stack_state *ss, void (*user_data_clear_function)(void *user_data, void *user_state), void *user_state );
+
+  int stack_push( struct stack_state *ss, void *user_data );
+  int stack_guaranteed_push( struct stack_state *ss, void *user_data );
+  int stack_pop( struct stack_state *ss, void **user_data );
+
+  void stack_query( struct stack_state *ss, enum stack_query_type query_type, void *query_input, void *query_output );
+
+
+
+
+
+  #define __LIBLFDS_H
+
+#endif
+
diff --git a/liblfds/liblfds.def b/liblfds/liblfds.def
new file mode 100644
index 0000000..c9e8c8c
--- /dev/null
+++ b/liblfds/liblfds.def
@@ -0,0 +1,46 @@
+EXPORTS
+
+freelist_delete = freelist_delete @1
+freelist_get_user_data_from_element = freelist_get_user_data_from_element @2
+freelist_guaranteed_pop = freelist_guaranteed_pop @3
+freelist_new = freelist_new @4
+freelist_new_elements = freelist_new_elements @5
+freelist_pop = freelist_pop @6
+freelist_push = freelist_push @7
+freelist_query = freelist_query @8
+freelist_set_user_data_in_element = freelist_set_user_data_in_element @9
+
+queue_delete = queue_delete @10
+queue_dequeue = queue_dequeue @11
+queue_enqueue = queue_enqueue @12
+queue_guaranteed_enqueue = queue_guaranteed_enqueue @13
+queue_new = queue_new @14
+queue_query = queue_query @15
+
+ringbuffer_delete = ringbuffer_delete @16
+ringbuffer_get_read_element = ringbuffer_get_read_element @17
+ringbuffer_get_write_element = ringbuffer_get_write_element @18
+ringbuffer_new = ringbuffer_new @19
+ringbuffer_put_read_element = ringbuffer_put_read_element @20
+ringbuffer_put_write_element = ringbuffer_put_write_element @21
+
+slist_delete = slist_delete @ 22
+slist_delete_all_elements = slist_delete_all_elements @ 23
+slist_delete_element = slist_delete_element @ 24
+slist_get_head = slist_get_head @ 25
+slist_get_head_and_then_next = slist_get_head_and_then_next @ 26
+slist_get_next = slist_get_next @ 27
+slist_get_user_data_from_element = slist_get_user_data_from_element @ 28
+slist_new = slist_new @ 29
+slist_new_head = slist_new_head @ 30
+slist_new_next = slist_new_next @ 31
+slist_set_user_data_in_element = slist_set_user_data_in_element @ 32
+
+stack_clear = stack_clear @33
+stack_delete = stack_delete @34
+stack_guaranteed_push = stack_guaranteed_push @35
+stack_new = stack_new @36
+stack_pop = stack_pop @37
+stack_push = stack_push @38
+stack_query = stack_query @39
+
diff --git a/liblfds/liblfds.sln b/liblfds/liblfds.sln
new file mode 100644
index 0000000..d76d9db
--- /dev/null
+++ b/liblfds/liblfds.sln
@@ -0,0 +1,38 @@
+﻿
+Microsoft Visual Studio Solution File, Format Version 10.00
+# Visual Studio 2008
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "liblfds", "liblfds.vcproj", "{F73AE755-F6D8-4C3A-977D-FBB40DC0ED05}"
+EndProject
+Global
+	GlobalSection(SolutionConfigurationPlatforms) = preSolution
+		Debug DLL|Win32 = Debug DLL|Win32
+		Debug DLL|x64 = Debug DLL|x64
+		Debug Lib|Win32 = Debug Lib|Win32
+		Debug Lib|x64 = Debug Lib|x64
+		Release DLL|Win32 = Release DLL|Win32
+		Release DLL|x64 = Release DLL|x64
+		Release Lib|Win32 = Release Lib|Win32
+		Release Lib|x64 = Release Lib|x64
+	EndGlobalSection
+	GlobalSection(ProjectConfigurationPlatforms) = postSolution
+		{F73AE755-F6D8-4C3A-977D-FBB40DC0ED05}.Debug DLL|Win32.ActiveCfg = Release DLL|Win32
+		{F73AE755-F6D8-4C3A-977D-FBB40DC0ED05}.Debug DLL|Win32.Build.0 = Release DLL|Win32
+		{F73AE755-F6D8-4C3A-977D-FBB40DC0ED05}.Debug DLL|x64.ActiveCfg = Debug DLL|x64
+		{F73AE755-F6D8-4C3A-977D-FBB40DC0ED05}.Debug DLL|x64.Build.0 = Debug DLL|x64
+		{F73AE755-F6D8-4C3A-977D-FBB40DC0ED05}.Debug Lib|Win32.ActiveCfg = Debug Lib|Win32
+		{F73AE755-F6D8-4C3A-977D-FBB40DC0ED05}.Debug Lib|Win32.Build.0 = Debug Lib|Win32
+		{F73AE755-F6D8-4C3A-977D-FBB40DC0ED05}.Debug Lib|x64.ActiveCfg = Debug Lib|x64
+		{F73AE755-F6D8-4C3A-977D-FBB40DC0ED05}.Debug Lib|x64.Build.0 = Debug Lib|x64
+		{F73AE755-F6D8-4C3A-977D-FBB40DC0ED05}.Release DLL|Win32.ActiveCfg = Release DLL|Win32
+		{F73AE755-F6D8-4C3A-977D-FBB40DC0ED05}.Release DLL|Win32.Build.0 = Release DLL|Win32
+		{F73AE755-F6D8-4C3A-977D-FBB40DC0ED05}.Release DLL|x64.ActiveCfg = Release DLL|x64
+		{F73AE755-F6D8-4C3A-977D-FBB40DC0ED05}.Release DLL|x64.Build.0 = Release DLL|x64
+		{F73AE755-F6D8-4C3A-977D-FBB40DC0ED05}.Release Lib|Win32.ActiveCfg = Release Lib|Win32
+		{F73AE755-F6D8-4C3A-977D-FBB40DC0ED05}.Release Lib|Win32.Build.0 = Release Lib|Win32
+		{F73AE755-F6D8-4C3A-977D-FBB40DC0ED05}.Release Lib|x64.ActiveCfg = Release Lib|x64
+		{F73AE755-F6D8-4C3A-977D-FBB40DC0ED05}.Release Lib|x64.Build.0 = Release Lib|x64
+	EndGlobalSection
+	GlobalSection(SolutionProperties) = preSolution
+		HideSolutionNode = FALSE
+	EndGlobalSection
+EndGlobal
diff --git a/liblfds/liblfds.vcproj b/liblfds/liblfds.vcproj
new file mode 100644
index 0000000..b5c2382
--- /dev/null
+++ b/liblfds/liblfds.vcproj
@@ -0,0 +1,808 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+	ProjectType="Visual C++"
+	Version="9.00"
+	Name="liblfds"
+	ProjectGUID="{F73AE755-F6D8-4C3A-977D-FBB40DC0ED05}"
+	RootNamespace="liblfds"
+	TargetFrameworkVersion="196613"
+	>
+	<Platforms>
+		<Platform
+			Name="Win32"
+		/>
+		<Platform
+			Name="x64"
+		/>
+	</Platforms>
+	<ToolFiles>
+	</ToolFiles>
+	<Configurations>
+		<Configuration
+			Name="Debug Lib|Win32"
+			OutputDirectory="$(ProjectDir)\bin\$(PlatformName)\$(ConfigurationName)"
+			IntermediateDirectory="$(ProjectDir)\obj\$(PlatformName)\$(ConfigurationName)"
+			ConfigurationType="4"
+			CharacterSet="1"
+			WholeProgramOptimization="0"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+				AdditionalOptions="/DWIN32_LEAN_AND_MEAN /D_DEBUG"
+				Optimization="0"
+				EnableIntrinsicFunctions="true"
+				AdditionalIncludeDirectories="&quot;$(ProjectDir)\src&quot;;&quot;$(ProjectDir)\inc&quot;"
+				MinimalRebuild="true"
+				ExceptionHandling="0"
+				BasicRuntimeChecks="3"
+				EnableFunctionLevelLinking="true"
+				BrowseInformation="1"
+				WarningLevel="4"
+				WarnAsError="true"
+				DebugInformationFormat="3"
+				CompileAs="1"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLibrarianTool"
+				AdditionalOptions="/wx"
+				AdditionalLibraryDirectories=""
+				IgnoreAllDefaultLibraries="true"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+			/>
+			<Tool
+				Name="VCFxCopTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+			/>
+		</Configuration>
+		<Configuration
+			Name="Debug Lib|x64"
+			OutputDirectory="$(ProjectDir)\bin\$(PlatformName)\$(ConfigurationName)"
+			IntermediateDirectory="$(ProjectDir)\obj\$(PlatformName)\$(ConfigurationName)"
+			ConfigurationType="4"
+			CharacterSet="1"
+			WholeProgramOptimization="0"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+				AdditionalOptions="/DWIN32_LEAN_AND_MEAN /D_DEBUG"
+				Optimization="0"
+				EnableIntrinsicFunctions="true"
+				AdditionalIncludeDirectories="&quot;$(ProjectDir)\src&quot;;&quot;$(ProjectDir)\inc&quot;"
+				ExceptionHandling="0"
+				BasicRuntimeChecks="3"
+				SmallerTypeCheck="true"
+				EnableFunctionLevelLinking="true"
+				BrowseInformation="1"
+				WarningLevel="4"
+				WarnAsError="true"
+				DebugInformationFormat="3"
+				CompileAs="1"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLibrarianTool"
+				AdditionalOptions="/wx"
+				AdditionalLibraryDirectories=""
+				IgnoreAllDefaultLibraries="true"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+			/>
+			<Tool
+				Name="VCFxCopTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+			/>
+		</Configuration>
+		<Configuration
+			Name="Release Lib|Win32"
+			OutputDirectory="$(ProjectDir)\bin\$(PlatformName)\$(ConfigurationName)"
+			IntermediateDirectory="$(ProjectDir)\obj\$(PlatformName)\$(ConfigurationName)"
+			ConfigurationType="4"
+			CharacterSet="1"
+			WholeProgramOptimization="0"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+				AdditionalOptions="/DWIN32_LEAN_AND_MEAN /DNDEBUG"
+				Optimization="3"
+				EnableIntrinsicFunctions="true"
+				FavorSizeOrSpeed="1"
+				AdditionalIncludeDirectories="&quot;$(ProjectDir)\src&quot;;&quot;$(ProjectDir)\inc&quot;"
+				StringPooling="true"
+				ExceptionHandling="0"
+				BufferSecurityCheck="false"
+				EnableFunctionLevelLinking="true"
+				WarningLevel="4"
+				WarnAsError="true"
+				DebugInformationFormat="0"
+				CompileAs="1"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLibrarianTool"
+				AdditionalOptions="/wx"
+				AdditionalLibraryDirectories=""
+				IgnoreAllDefaultLibraries="true"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+			/>
+			<Tool
+				Name="VCFxCopTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+			/>
+		</Configuration>
+		<Configuration
+			Name="Release Lib|x64"
+			OutputDirectory="$(ProjectDir)\bin\$(PlatformName)\$(ConfigurationName)"
+			IntermediateDirectory="$(ProjectDir)\obj\$(PlatformName)\$(ConfigurationName)"
+			ConfigurationType="4"
+			CharacterSet="1"
+			WholeProgramOptimization="0"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+				AdditionalOptions="/DWIN32_LEAN_AND_MEAN /DNDEBUG"
+				Optimization="3"
+				EnableIntrinsicFunctions="true"
+				FavorSizeOrSpeed="1"
+				AdditionalIncludeDirectories="&quot;$(ProjectDir)\src&quot;;&quot;$(ProjectDir)\inc&quot;"
+				StringPooling="true"
+				ExceptionHandling="0"
+				BufferSecurityCheck="false"
+				EnableFunctionLevelLinking="true"
+				WarningLevel="4"
+				WarnAsError="true"
+				DebugInformationFormat="0"
+				CompileAs="1"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLibrarianTool"
+				AdditionalOptions="/wx"
+				AdditionalLibraryDirectories=""
+				IgnoreAllDefaultLibraries="true"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+			/>
+			<Tool
+				Name="VCFxCopTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+			/>
+		</Configuration>
+		<Configuration
+			Name="Debug DLL|Win32"
+			OutputDirectory="$(ProjectDir)\bin\$(PlatformName)\$(ConfigurationName)"
+			IntermediateDirectory="$(ProjectDir)\obj\$(PlatformName)\$(ConfigurationName)"
+			ConfigurationType="2"
+			CharacterSet="1"
+			WholeProgramOptimization="0"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+				AdditionalOptions="/DWIN32_LEAN_AND_MEAN /D_DEBUG"
+				Optimization="0"
+				EnableIntrinsicFunctions="true"
+				AdditionalIncludeDirectories="&quot;$(ProjectDir)\src&quot;;&quot;$(ProjectDir)\inc&quot;"
+				MinimalRebuild="true"
+				ExceptionHandling="0"
+				BasicRuntimeChecks="3"
+				RuntimeLibrary="3"
+				EnableFunctionLevelLinking="true"
+				BrowseInformation="1"
+				WarningLevel="4"
+				WarnAsError="true"
+				DebugInformationFormat="3"
+				CompileAs="1"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalDependencies="msvcrtd.lib"
+				IgnoreAllDefaultLibraries="true"
+				ModuleDefinitionFile="$(ProjectDir)\liblfds.def"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCManifestTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+			/>
+			<Tool
+				Name="VCFxCopTool"
+			/>
+			<Tool
+				Name="VCAppVerifierTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+			/>
+		</Configuration>
+		<Configuration
+			Name="Debug DLL|x64"
+			OutputDirectory="$(ProjectDir)\bin\$(PlatformName)\$(ConfigurationName)"
+			IntermediateDirectory="$(ProjectDir)\obj\$(PlatformName)\$(ConfigurationName)"
+			ConfigurationType="2"
+			CharacterSet="1"
+			WholeProgramOptimization="0"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+				TargetEnvironment="3"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+				AdditionalOptions="/DWIN32_LEAN_AND_MEAN /D_DEBUG"
+				Optimization="0"
+				EnableIntrinsicFunctions="true"
+				AdditionalIncludeDirectories="&quot;$(ProjectDir)\src&quot;;&quot;$(ProjectDir)\inc&quot;"
+				ExceptionHandling="0"
+				BasicRuntimeChecks="3"
+				SmallerTypeCheck="true"
+				RuntimeLibrary="3"
+				EnableFunctionLevelLinking="true"
+				BrowseInformation="1"
+				WarningLevel="4"
+				WarnAsError="true"
+				DebugInformationFormat="3"
+				CompileAs="1"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalDependencies="msvcrtd.lib"
+				IgnoreAllDefaultLibraries="true"
+				ModuleDefinitionFile="$(ProjectDir)\liblfds.def"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCManifestTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+			/>
+			<Tool
+				Name="VCFxCopTool"
+			/>
+			<Tool
+				Name="VCAppVerifierTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+			/>
+		</Configuration>
+		<Configuration
+			Name="Release DLL|Win32"
+			OutputDirectory="$(ProjectDir)\bin\$(PlatformName)\$(ConfigurationName)"
+			IntermediateDirectory="$(ProjectDir)\obj\$(PlatformName)\$(ConfigurationName)"
+			ConfigurationType="2"
+			CharacterSet="1"
+			WholeProgramOptimization="0"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+				AdditionalOptions="/DWIN32_LEAN_AND_MEAN /DNDEBUG"
+				Optimization="3"
+				EnableIntrinsicFunctions="true"
+				FavorSizeOrSpeed="1"
+				AdditionalIncludeDirectories="&quot;$(ProjectDir)\src&quot;;&quot;$(ProjectDir)\inc&quot;"
+				StringPooling="true"
+				ExceptionHandling="0"
+				RuntimeLibrary="2"
+				BufferSecurityCheck="false"
+				EnableFunctionLevelLinking="true"
+				WarningLevel="4"
+				WarnAsError="true"
+				DebugInformationFormat="0"
+				CompileAs="1"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalDependencies="msvcrt.lib"
+				IgnoreAllDefaultLibraries="true"
+				ModuleDefinitionFile="$(ProjectDir)\liblfds.def"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCManifestTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+			/>
+			<Tool
+				Name="VCFxCopTool"
+			/>
+			<Tool
+				Name="VCAppVerifierTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+			/>
+		</Configuration>
+		<Configuration
+			Name="Release DLL|x64"
+			OutputDirectory="$(ProjectDir)\bin\$(PlatformName)\$(ConfigurationName)"
+			IntermediateDirectory="$(ProjectDir)\obj\$(PlatformName)\$(ConfigurationName)"
+			ConfigurationType="2"
+			CharacterSet="1"
+			WholeProgramOptimization="0"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+				TargetEnvironment="3"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+				AdditionalOptions="/DWIN32_LEAN_AND_MEAN /DNDEBUG"
+				Optimization="3"
+				EnableIntrinsicFunctions="true"
+				FavorSizeOrSpeed="1"
+				AdditionalIncludeDirectories="&quot;$(ProjectDir)\src&quot;;&quot;$(ProjectDir)\inc&quot;"
+				StringPooling="true"
+				ExceptionHandling="0"
+				RuntimeLibrary="2"
+				BufferSecurityCheck="false"
+				EnableFunctionLevelLinking="true"
+				WarningLevel="4"
+				WarnAsError="true"
+				DebugInformationFormat="0"
+				CompileAs="1"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalDependencies="msvcrt.lib"
+				IgnoreAllDefaultLibraries="true"
+				ModuleDefinitionFile="$(ProjectDir)\liblfds.def"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCManifestTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+			/>
+			<Tool
+				Name="VCFxCopTool"
+			/>
+			<Tool
+				Name="VCAppVerifierTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+			/>
+		</Configuration>
+	</Configurations>
+	<References>
+	</References>
+	<Files>
+		<Filter
+			Name="inc"
+			Filter="h;hpp;hxx;hm;inl;inc;xsd"
+			UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
+			>
+			<File
+				RelativePath=".\inc\abstraction.h"
+				>
+			</File>
+			<File
+				RelativePath=".\inc\freelist.h"
+				>
+			</File>
+			<File
+				RelativePath=".\inc\liblfds.h"
+				>
+			</File>
+			<File
+				RelativePath=".\inc\queue.h"
+				>
+			</File>
+			<File
+				RelativePath=".\inc\ringbuffer.h"
+				>
+			</File>
+			<File
+				RelativePath=".\inc\stack.h"
+				>
+			</File>
+		</Filter>
+		<Filter
+			Name="src"
+			>
+			<File
+				RelativePath=".\src\liblfds_internal.h"
+				>
+			</File>
+			<Filter
+				Name="abstraction"
+				>
+				<File
+					RelativePath=".\src\abstraction\abstraction_aligned_free.c"
+					>
+				</File>
+				<File
+					RelativePath=".\src\abstraction\abstraction_aligned_malloc.c"
+					>
+				</File>
+				<File
+					RelativePath=".\src\abstraction\abstraction_cas.c"
+					>
+				</File>
+				<File
+					RelativePath=".\src\abstraction\abstraction_dcas.c"
+					>
+				</File>
+				<File
+					RelativePath=".\src\abstraction\abstraction_increment.c"
+					>
+				</File>
+				<File
+					RelativePath=".\src\abstraction\abstraction_internal.h"
+					>
+				</File>
+			</Filter>
+			<Filter
+				Name="freelist"
+				>
+				<File
+					RelativePath=".\src\freelist\freelist_delete.c"
+					>
+				</File>
+				<File
+					RelativePath=".\src\freelist\freelist_get_and_set.c"
+					>
+				</File>
+				<File
+					RelativePath=".\src\freelist\freelist_internal.h"
+					>
+				</File>
+				<File
+					RelativePath=".\src\freelist\freelist_new.c"
+					>
+				</File>
+				<File
+					RelativePath=".\src\freelist\freelist_pop_push.c"
+					>
+				</File>
+				<File
+					RelativePath=".\src\freelist\freelist_query.c"
+					>
+				</File>
+			</Filter>
+			<Filter
+				Name="stack"
+				>
+				<File
+					RelativePath=".\src\stack\stack_delete.c"
+					>
+				</File>
+				<File
+					RelativePath=".\src\stack\stack_internal.h"
+					>
+				</File>
+				<File
+					RelativePath=".\src\stack\stack_new.c"
+					>
+				</File>
+				<File
+					RelativePath=".\src\stack\stack_push_pop.c"
+					>
+				</File>
+				<File
+					RelativePath=".\src\stack\stack_query.c"
+					>
+				</File>
+			</Filter>
+			<Filter
+				Name="ringbuffer"
+				>
+				<File
+					RelativePath=".\src\ringbuffer\ringbuffer_delete.c"
+					>
+				</File>
+				<File
+					RelativePath=".\src\ringbuffer\ringbuffer_get_and_put.c"
+					>
+				</File>
+				<File
+					RelativePath=".\src\ringbuffer\ringbuffer_internal.h"
+					>
+				</File>
+				<File
+					RelativePath=".\src\ringbuffer\ringbuffer_new.c"
+					>
+				</File>
+				<File
+					RelativePath=".\src\ringbuffer\ringbuffer_query.c"
+					>
+				</File>
+			</Filter>
+			<Filter
+				Name="queue"
+				>
+				<File
+					RelativePath=".\src\queue\queue_delete.c"
+					>
+				</File>
+				<File
+					RelativePath=".\src\queue\queue_internal.h"
+					>
+				</File>
+				<File
+					RelativePath=".\src\queue\queue_new.c"
+					>
+				</File>
+				<File
+					RelativePath=".\src\queue\queue_query.c"
+					>
+				</File>
+				<File
+					RelativePath=".\src\queue\queue_queue.c"
+					>
+				</File>
+			</Filter>
+			<Filter
+				Name="slist"
+				>
+				<File
+					RelativePath=".\src\slist\slist_delete.c"
+					>
+				</File>
+				<File
+					RelativePath=".\src\slist\slist_get_and_set.c"
+					>
+				</File>
+				<File
+					RelativePath=".\src\slist\slist_internal.h"
+					>
+				</File>
+				<File
+					RelativePath=".\src\slist\slist_link.c"
+					>
+				</File>
+				<File
+					RelativePath=".\src\slist\slist_new.c"
+					>
+				</File>
+			</Filter>
+		</Filter>
+	</Files>
+	<Globals>
+	</Globals>
+</VisualStudioProject>
diff --git a/liblfds/makefile.linux b/liblfds/makefile.linux
new file mode 100644
index 0000000..d75bf8b
--- /dev/null
+++ b/liblfds/makefile.linux
@@ -0,0 +1,105 @@
+##### paths #####
+BINDIR  = bin
+INCDIR  = inc
+OBJDIR  = obj
+SRCDIR  = src
+
+##### misc #####
+QUIETLY = 1>/dev/null 2>/dev/null
+
+##### sources, objects and libraries #####
+BINNAME = liblfds
+AR_BINARY = $(BINDIR)/$(BINNAME).a
+SO_BINARY = $(BINDIR)/$(BINNAME).so
+SRCDIRS = abstraction freelist queue ringbuffer slist stack
+# TRD : be aware - in the linux makefile, with the one-pass linking behaviour of the GNU linker, the order
+#       of source files matters!  this is because it leads to the ordering of objects in the library and
+#       that in turn, since the data structures all use the freelist API and the abstraction API, has to be
+#       correct 
+SOURCES = queue_delete.c queue_new.c queue_query.c queue_queue.c \
+          ringbuffer_delete.c ringbuffer_get_and_put.c ringbuffer_new.c ringbuffer_query.c \
+          slist_delete.c slist_get_and_set.c slist_link.c slist_new.c \
+          stack_delete.c stack_new.c stack_push_pop.c stack_query.c \
+          freelist_delete.c freelist_get_and_set.c freelist_new.c freelist_query.c freelist_pop_push.c \
+          abstraction_aligned_free.c abstraction_aligned_malloc.c abstraction_cas.c abstraction_dcas.c abstraction_increment.c
+OBJECTS = $(patsubst %.c,$(OBJDIR)/%.o,$(notdir $(SOURCES)))
+
+##### CPU variants #####
+GCCARCH = $(shell uname -m)
+
+ifeq ($(GCCARCH),x86_64)
+  GCCARCH = core2
+endif
+
+ifeq ($(findstring arm,$(GCCARCH)),arm)
+  GCCARCH = armv6k
+endif
+
+##### tools #####
+MAKE    = make
+MFLAGS  = 
+
+DG      = gcc
+DGFLAGS = -MM -std=c99 -I"$(SRCDIR)" -I"$(INCDIR)"
+
+CC      = gcc
+CBASE   = -Wall -Wno-unknown-pragmas -std=c99 -march=$(GCCARCH) -c -I"$(SRCDIR)" -I"$(INCDIR)"
+CFREL   = -O2 -finline-functions -Wno-strict-aliasing
+CFDBG   = -O0 -g
+
+AR      = ar
+AFLAGS  = -rcs
+
+LD      = gcc
+LFBASE  = -Wall -std=c99 -shared
+LFREL   = -O2 -s
+LFDBG   = -O0 -g
+
+##### rel/dbg .a/.so variants #####
+ifeq ($(findstring so,$(MAKECMDGOALS)),so)
+  CBASE := $(CBASE) -fpic
+endif
+
+CFLAGS  = $(CBASE) $(CFDBG)
+LFLAGS  = $(LFBASE) $(LFDBG)
+
+ifeq ($(findstring rel,$(MAKECMDGOALS)),rel)
+  CFLAGS  = $(CBASE) $(CFREL)
+  LFLAGS  = $(LFBASE) $(LFREL)
+endif
+
+##### search paths #####
+vpath %.c $(patsubst %,$(SRCDIR)/%:,$(SRCDIRS))
+
+##### implicit rules #####
+$(OBJDIR)/%.o : %.c
+	mkdir -p bin
+	mkdir -p obj
+	$(DG) $(DGFLAGS) $< >$(OBJDIR)/$*.d
+	$(CC) $(CFLAGS) -o $@ $<
+
+##### explicit rules #####
+$(AR_BINARY) : $(OBJECTS)
+	$(AR) $(AFLAGS) $(AR_BINARY) $(OBJECTS)
+
+$(SO_BINARY) : $(OBJECTS)
+	$(LD) $(LFLAGS) $(SYSLIBS) $(OBJECTS) -o $(SO_BINARY)
+
+##### phony #####
+.PHONY : clean arrel ardbg sorel sodbg
+
+clean : 
+	@rm -f $(BINDIR)/$(BINNAME).* $(OBJDIR)/*.o $(OBJDIR)/*.d
+
+arrel : $(AR_BINARY)
+ardbg : $(AR_BINARY)
+
+sorel : $(SO_BINARY)
+sodbg : $(SO_BINARY)
+
+##### dependencies #####
+-include $(DEPENDS)
+
+##### notes #####
+# TRD : we use -std=c99 purely to permit C++ style comments
+
diff --git a/liblfds/makefile.windows b/liblfds/makefile.windows
new file mode 100644
index 0000000..ec292cb
--- /dev/null
+++ b/liblfds/makefile.windows
@@ -0,0 +1,94 @@
+##### paths #####
+BINDIR  = bin
+INCDIR  = inc
+OBJDIR  = obj
+SRCDIR  = src
+
+##### misc #####
+QUIETLY = 1>nul 2>nul
+
+##### sources, objects and libraries #####
+BINNAME = liblfds
+LIB_BINARY = $(BINDIR)\$(BINNAME).lib
+DLL_BINARY = $(BINDIR)\$(BINNAME).dll
+SRCDIRS = abstraction freelist queue ringbuffer slist stack
+SOURCES = abstraction_aligned_free.c abstraction_aligned_malloc.c abstraction_cas.c abstraction_dcas.c abstraction_increment.c \
+          freelist_delete.c freelist_get_and_set.c freelist_new.c freelist_query.c freelist_pop_push.c \
+          queue_delete.c queue_new.c queue_query.c queue_queue.c \
+          ringbuffer_delete.c ringbuffer_get_and_put.c ringbuffer_new.c ringbuffer_query.c \
+          slist_delete.c slist_get_and_set.c slist_link.c slist_new.c \
+          stack_delete.c stack_new.c stack_push_pop.c stack_query.c
+OBJECTS = $(patsubst %.c,$(OBJDIR)/%.obj,$(notdir $(SOURCES)))
+
+##### tools #####
+MAKE    = make
+MFLAGS  = 
+
+CC      = cl
+CBASE   = /nologo /W4 /WX /c "-I$(SRCDIR)" "-I$(INCDIR)" "/Fd$(BINDIR)\$(BINNAME).pdb" /DUNICODE /D_UNICODE /DWIN32_LEAN_AND_MEAN
+CFREL   = /Ox /DNDEBUG
+CFDBG   = /Od /Gm /Zi /D_DEBUG
+
+AR      = lib
+AFLAGS  = /nologo /subsystem:console /wx /verbose
+
+LD      = link
+LFBASE  = /dll /def:$(BINNAME).def /nologo /subsystem:console /wx /nodefaultlib /nxcompat
+LFREL   = /incremental:no
+LFDBG   = /debug "/pdb:$(BINDIR)\$(BINNAME).pdb"
+
+##### variants #####
+CFLAGS  = $(CBASE) $(CFDBG) /MTd
+LFLAGS  = $(LFBASE) $(LFDBG)
+CLIB    = libcmtd.lib
+
+ifeq ($(MAKECMDGOALS),librel)
+  CFLAGS  = $(CBASE) $(CFREL) /MT
+  LFLAGS  = $(LFBASE) $(LFREL)
+  CLIB    = libcmt.lib
+endif
+
+ifeq ($(MAKECMDGOALS),libdbg)
+  CFLAGS  = $(CBASE) $(CFDBG) /MTd
+  LFLAGS  = $(LFBASE) $(LFDBG)
+  CLIB    = libcmtd.lib
+endif
+
+ifeq ($(MAKECMDGOALS),dllrel)
+  CFLAGS  = $(CBASE) $(CFREL) /MD
+  LFLAGS  = $(LFBASE) $(LFREL)
+  CLIB    = msvcrt.lib
+endif
+
+ifeq ($(MAKECMDGOALS),dlldbg)
+  CFLAGS  = $(CBASE) $(CFDBG) /MDd
+  LFLAGS  = $(LFBASE) $(LFDBG)
+  CLIB    = msvcrtd.lib
+endif
+
+##### search paths #####
+vpath %.c $(patsubst %,$(SRCDIR)/%;,$(SRCDIRS))
+
+##### implicit rules #####
+$(OBJDIR)/%.obj : %.c
+	$(CC) $(CFLAGS) "/Fo$@" $<
+
+##### explicit rules #####
+$(LIB_BINARY) : $(OBJECTS)
+	$(AR) $(AFLAGS) $(OBJECTS) /out:$(LIB_BINARY)
+
+$(DLL_BINARY) : $(OBJECTS)
+	$(LD) $(LFLAGS) $(CLIB) $(OBJECTS) /out:$(DLL_BINARY)
+
+##### phony #####
+.PHONY : clean librel libdbg dllrel dlldbg
+
+clean : 
+	@erase /Q $(BINDIR)\$(BINNAME).* $(OBJDIR)\*.obj $(QUIETLY)
+
+librel : $(LIB_BINARY)
+libdbg : $(LIB_BINARY)
+
+dllrel : $(DLL_BINARY)
+dlldbg : $(DLL_BINARY)
+
diff --git a/liblfds/readme.txt b/liblfds/readme.txt
new file mode 100644
index 0000000..db68274
--- /dev/null
+++ b/liblfds/readme.txt
@@ -0,0 +1,131 @@
+introduction
+============
+Welcome to liblfds, a portable, license-free, lock-free data structure
+library written in C.
+
+platforms
+=========
+Currently liblfds out-of-the-box supports;
+
+Operating System  CPU         Toolset
+================  ==========  =======
+Windows 64-bit    IA64 & x64  1. Microsoft Visual Studio 2008
+                              2. Microsoft Windows SDK and GNUmake >= 3.8.1
+
+Windows 32-bit 	  x64 & x86   1. Microsoft Visual Studio 2008
+                              2. Visual C++ 2008 Express Edition
+                              3. Microsoft Windows SDK and GNUmake >= 3.8.1
+
+Windows Kernel    IA64, x64,  1. Windows Driver Kit >= 7.0.0
+                  x86
+
+Linux 64-bit      x64         1. GCC >= 4.1.0 and GNUmake >= 3.8.1
+
+Linux 32-bit      x64, x86,   1. GCC >= 4.1.0 and GNUmake >= 3.8.1 
+                  ARM
+
+data structures
+===============
+Currently liblfds provides the following;
+
+* Freelist
+* Queue
+* Ringbuffer
+* Singly linked list (logical delete only)
+* Stack
+
+liblfds on-line
+===============
+On the liblfds home page, you will find the blog, a bugzilla, a forum, a
+wikipedia and the current and all historical source releases.
+
+The wikipedia contains comprehensive documentation for development,
+building, testing and porting.
+
+http://www.liblfds.org
+
+license
+=======
+There is no license.  You are free to use this code in any way.
+
+building
+========
+On Windows, depending on your target platform, one of the following toolchains
+is required;
+
+    * Microsoft Visual Studio 2008 (expensive)
+    * Visual C++ 2008 Express Edition (free, but no 64 bit support)
+    * Microsoft Windows SDK (free, no GUI, has 64 bit support) and GNUmake 3.81 
+
+On Windows (kernel-mode), the following toolchain is required; 
+
+    * Windows Driver Kit 7.0.0 or later
+
+On Linux, the following toolchain is required;
+
+    * gcc 4.1.0 or later and GNUmake 3.81 
+
+For documentation, see the building guide in the wikipedia.
+
+using
+=====
+Once built, there is a single header file, /inc/liblfds.h, which you must include
+in your source code, and a single library file /bin/liblfds.*, where the suffix
+depends on your platform and your build choice (static or dynamic), to which,
+if statically built, you must link directly or, if dynamically built, you must
+arrange your system such that the library can be found by the loader at run-time. 
+
+testing
+=======
+The library comes with a command line test and benchmark program.  This
+program requires threads.  As such, it is only suitable for platforms providing
+thread support and which can execute a command line binary.  Currently this
+means the test and benchmark program works for all platforms except the Windows
+Kernel.
+
+For documentation, see the testing and benchmarking guide in the wikipedia.
+
+porting
+=======
+Both the test program and liblfds provide an abstraction layer which acts to
+mask platform differences. Porting is the act of implementing on your platform
+the functions which make up the abstraction layers.  You do not need to port
+the test program to port liblfds, but obviously it is recommended, so you can
+test your port.
+
+To support liblfds, your platform must support either contigious double-word
+compare-and-swap (e.g. x86/x64) or contigious double-word load-link/conditional-store
+where normal loads cannot occur inside the LL/CS pair (e.g. ARM) or single word
+load-link/conditional-store where normal loads can occur inside the LL/CS pair.
+
+For documentation, see the porting guide in the wikipedia.
+
+release history
+===============
+release 1, 25th September 2009, svn revision 1574.
+  - initial release
+
+release 2, 5th October 2009, svn revision 1599.
+  - added abstraction layer for Windows kernel
+  - minor code tidyups/fixes
+
+release 3, 25th October 2009, svn revision 1652.
+  - added singly linked list (logical delete only)
+  - minor code tidyups/fixes
+
+release 4, 7th December 2009, svn revision 1716.
+  - added ARM support
+  - added benchmarking functionality to the test program
+  - fixed a profound and pervasive pointer
+    decleration bug; earlier releases of liblfds
+    *should not be used*
+
+release 5, 19th December 2009, svn revision 1738.
+  - fixed subtle queue bug, which also affected ringbuffer
+    and caused data re-ordering under high load
+  - added benchmarks for freelist, ringbuffer and stack
+
+release 6, 29th December 2009, svn revision 1746.
+  - fixed two implementation errors, which reduced performance,
+    spotted by Codeplug from "http://cboard.cprogramming.com".
+ 
diff --git a/liblfds/runme_before_win_kernel_build_readme.txt b/liblfds/runme_before_win_kernel_build_readme.txt
new file mode 100644
index 0000000..1481c8d
--- /dev/null
+++ b/liblfds/runme_before_win_kernel_build_readme.txt
@@ -0,0 +1,32 @@
+The Windows kernel build environment is primitive and has a number
+of severe limitations; in particular, all source files must be in
+one directory and it is not possible to choose the output binary type
+(static or dynamic library) from the build command line; rather,
+a string has to be modified in a text file used by the build (!)
+
+To deal with these limitations, it is necessary for a Windows kernel
+build to run a batch file prior to building.
+
+There are two batch files, one for static library builds and the other
+for dynamic library builds.
+
+They are both idempotent; you can run them as often as you like and
+switch between them as often as you want.  It's all fine; whenever
+you run one of them, it will take you from whatever state you were
+previously in, into the state you want to be in.
+
+Both batch files copy all the sources file into a single directory,
+"/src/single_dir_for_windows_kernel/".
+
+The static library batch file will then copy "/sources.static" into
+"/src/single_dir_for_windows_kernel/", which will cause a static
+library to be built.
+
+The dynamic library batch file will then copy "/sources.dynamic" into
+"/src/single_dir_for_windows_kernel/", which will cause a dynamic
+library to be built.  It will also copy "src/driver_entry.c" into
+"/src/single_dir_for_windows_kernel/", since the linker requires
+the DriverEntry function to exist for dynamic libraries, even
+though it's not used.
+
+
diff --git a/liblfds/runme_before_win_kernel_dynamic_lib_build.bat b/liblfds/runme_before_win_kernel_dynamic_lib_build.bat
new file mode 100644
index 0000000..7443a7f
--- /dev/null
+++ b/liblfds/runme_before_win_kernel_dynamic_lib_build.bat
@@ -0,0 +1,14 @@
+@echo off
+rmdir /q /s src\single_dir_for_windows_kernel 1>nul 2>nul
+mkdir src\single_dir_for_windows_kernel 1>nul 2>nul
+copy /y src\abstraction\* src\single_dir_for_windows_kernel 1>nul 2>nul
+copy /y src\freelist\* src\single_dir_for_windows_kernel 1>nul 2>nul
+copy /y src\queue\* src\single_dir_for_windows_kernel 1>nul 2>nul
+copy /y src\ringbuffer\* src\single_dir_for_windows_kernel 1>nul 2>nul
+copy /y src\slist\* src\single_dir_for_windows_kernel 1>nul 2>nul
+copy /y src\stack\* src\single_dir_for_windows_kernel 1>nul 2>nul
+copy /y sources.dynamic src\single_dir_for_windows_kernel\sources 1>nul 2>nul
+copy /y src\driver_entry.c src\single_dir_for_windows_kernel 1>nul 2>nul
+echo Windows kernel dynamic library build directory structure created.
+echo (Note the effects of this batch file are idempotent).
+
diff --git a/liblfds/runme_before_win_kernel_static_lib_build.bat b/liblfds/runme_before_win_kernel_static_lib_build.bat
new file mode 100644
index 0000000..e5cc54f
--- /dev/null
+++ b/liblfds/runme_before_win_kernel_static_lib_build.bat
@@ -0,0 +1,14 @@
+@echo off
+rmdir /q /s src\single_dir_for_windows_kernel 1>nul 2>nul
+mkdir src\single_dir_for_windows_kernel 1>nul 2>nul
+copy /y src\abstraction\* src\single_dir_for_windows_kernel 1>nul 2>nul
+copy /y src\freelist\* src\single_dir_for_windows_kernel 1>nul 2>nul
+copy /y src\queue\* src\single_dir_for_windows_kernel 1>nul 2>nul
+copy /y src\ringbuffer\* src\single_dir_for_windows_kernel 1>nul 2>nul
+copy /y src\slist\* src\single_dir_for_windows_kernel 1>nul 2>nul
+copy /y src\stack\* src\single_dir_for_windows_kernel 1>nul 2>nul
+copy /y sources.static src\single_dir_for_windows_kernel\sources 1>nul 2>nul
+erase /f src\single_dir_for_windows_kernel\driver_entry.c 1>nul 2>nul
+echo Windows kernel static library build directory structure created.
+echo (Note the effects of this batch file are idempotent).
+
diff --git a/liblfds/sources.dynamic b/liblfds/sources.dynamic
new file mode 100644
index 0000000..b89f1a9
--- /dev/null
+++ b/liblfds/sources.dynamic
@@ -0,0 +1,37 @@
+MSC_WARNING_LEVEL = /WX /W4
+DLLDEF            = ../../liblfds.def
+TARGETNAME        = liblfds
+TARGETPATH        = ../../bin/
+TARGETTYPE        = EXPORT_DRIVER
+UMTYPE            = nt
+USER_C_FLAGS      = /DWIN_KERNEL_BUILD
+
+INCLUDES = ..;../../inc/
+SOURCES  = abstraction_aligned_free.c \
+           abstraction_aligned_malloc.c \
+           abstraction_cas.c \
+           abstraction_dcas.c \
+           abstraction_increment.c \
+           freelist_delete.c \
+           freelist_get_and_set.c \
+           freelist_new.c \
+           freelist_pop_push.c \
+           freelist_query.c \
+           queue_delete.c \
+           queue_new.c \
+           queue_query.c \
+           queue_queue.c \
+           ringbuffer_delete.c \
+           ringbuffer_get_and_put.c \
+           ringbuffer_new.c \
+           ringbuffer_query.c \
+           slist_delete.c \
+           slist_get_and_set.c \
+           slist_link.c \
+           slist_new.c \
+           stack_delete.c \
+           stack_new.c \
+           stack_push_pop.c \
+           stack_query.c \
+           driver_entry.c
+
diff --git a/liblfds/sources.static b/liblfds/sources.static
new file mode 100644
index 0000000..3369c40
--- /dev/null
+++ b/liblfds/sources.static
@@ -0,0 +1,35 @@
+MSC_WARNING_LEVEL = /WX /W4
+TARGETNAME        = liblfds
+TARGETPATH        = ../../bin/
+TARGETTYPE        = DRIVER_LIBRARY
+UMTYPE            = nt
+USER_C_FLAGS      = /DWIN_KERNEL_BUILD
+
+INCLUDES = ..;../../inc/
+SOURCES  = abstraction_aligned_free.c \
+           abstraction_aligned_malloc.c \
+           abstraction_cas.c \
+           abstraction_dcas.c \
+           abstraction_increment.c \
+           freelist_delete.c \
+           freelist_get_and_set.c \
+           freelist_new.c \
+           freelist_pop_push.c \
+           freelist_query.c \
+           queue_delete.c \
+           queue_new.c \
+           queue_query.c \
+           queue_queue.c \
+           ringbuffer_delete.c \
+           ringbuffer_get_and_put.c \
+           ringbuffer_new.c \
+           ringbuffer_query.c \
+           slist_delete.c \
+           slist_get_and_set.c \
+           slist_link.c \
+           slist_new.c \
+           stack_delete.c \
+           stack_new.c \
+           stack_push_pop.c \
+           stack_query.c
+
diff --git a/liblfds/src/abstraction/abstraction_aligned_free.c b/liblfds/src/abstraction/abstraction_aligned_free.c
new file mode 100644
index 0000000..5cb8c0f
--- /dev/null
+++ b/liblfds/src/abstraction/abstraction_aligned_free.c
@@ -0,0 +1,72 @@
+#include "abstraction_internal.h"
+
+
+
+
+
+/****************************************************************************/
+#if (defined _WIN32 && defined _MSC_VER && !defined WIN_KERNEL_BUILD)
+
+  /* TRD : any Windows (user-mode) on any CPU with the Microsoft C compiler
+
+           _WIN32             indicates 64-bit or 32-bit Windows
+           _MSC_VER           indicates Microsoft C compiler
+           !WIN_KERNEL_BUILD  indicates Windows user-mode
+  */
+
+  void abstraction_aligned_free( void *memory )
+  {
+    _aligned_free( memory );
+
+    return;
+  }
+
+#endif
+
+
+
+
+
+/****************************************************************************/
+#if (_XOPEN_SOURCE >= 600)
+
+  /* TRD : any OS on any CPU with any compiler with POSIX 6.00 or better
+
+           _XOPEN_SOURCE  is actually set by the user, not by the compiler
+                          it is the way the user signals to the compiler what
+                          level of POSIX should be available
+                          (it assumes of course the compiler has support for the given level of POSIX requested)
+  */
+
+  void abstraction_aligned_free( void *memory )
+  {
+    free( memory );
+
+    return;
+  }
+
+#endif
+
+
+
+
+
+/****************************************************************************/
+#if (defined _WIN32 && defined _MSC_VER && defined WIN_KERNEL_BUILD)
+
+  /* TRD : any Windows (kernel) on any CPU with the Microsoft C compiler
+
+           _WIN32            indicates 64-bit or 32-bit Windows
+           _MSC_VER          indicates Microsoft C compiler
+           WIN_KERNEL_BUILD  indicates Windows kernel
+  */
+
+  void abstraction_aligned_free( void *memory )
+  {
+    ExFreePoolWithTag( memory, 'sdfl' );
+
+    return;
+  }
+
+#endif
+
diff --git a/liblfds/src/abstraction/abstraction_aligned_malloc.c b/liblfds/src/abstraction/abstraction_aligned_malloc.c
new file mode 100644
index 0000000..9501ccd
--- /dev/null
+++ b/liblfds/src/abstraction/abstraction_aligned_malloc.c
@@ -0,0 +1,97 @@
+#include "abstraction_internal.h"
+
+
+
+
+
+/****************************************************************************/
+#if (defined _WIN32 && defined _MSC_VER && !defined WIN_KERNEL_BUILD)
+
+  /* TRD : any Windows (user-mode) on any CPU with the Microsoft C compiler
+
+           _WIN32             indicates 64-bit or 32-bit Windows
+           _MSC_VER           indicates Microsoft C compiler
+           !WIN_KERNEL_BUILD  indicates Windows user-mode
+  */
+
+  void *abstraction_aligned_malloc( size_t size, size_t align_in_bytes )
+  {
+    void
+      *rv;
+
+    rv = _aligned_malloc( size, align_in_bytes );
+
+    return( rv );
+  }
+
+#endif
+
+
+
+
+
+/****************************************************************************/
+#if (_XOPEN_SOURCE >= 600)
+
+  /* TRD : any OS on any CPU with any compiler with POSIX 6.00 or better
+
+           _XOPEN_SOURCE  is actually set by the user, not by the compiler
+                          it is the way the user signals to the compiler what
+                          level of POSIX should be available
+                          (it assumes of course the compiler has support for the given level of POSIX requested)
+  */
+
+  void *abstraction_aligned_malloc( size_t size, size_t align_in_bytes )
+  {
+    int
+      rv;
+
+    void
+      *memory;
+
+    rv = posix_memalign( &memory, align_in_bytes, size );
+
+    // TRD : posix_memalign returns 0 on success, docs do not say *memory == NULL on fail
+    if( rv != 0 )
+      memory = NULL;
+
+    return( memory );
+  }
+
+#endif
+
+
+
+
+
+/****************************************************************************/
+#if (defined _WIN32 && defined _MSC_VER && defined WIN_KERNEL_BUILD)
+
+  /* TRD : any Windows (kernel) on any CPU with the Microsoft C compiler
+
+           _WIN32            indicates 64-bit or 32-bit Windows
+           _MSC_VER          indicates Microsoft C compiler
+           WIN_KERNEL_BUILD  indicates Windows kernel
+  */
+
+  void *abstraction_aligned_malloc( size_t size, size_t align_in_bytes )
+  {
+    void
+      *rv;
+
+    /* TRD : ExAllocatePoolWithTag() allocates memory aligned on 8 bytes on 32-bit CPUs
+             and on 16 bytes on 64-bit CPUs, which is what we want
+
+             as such, align_in_bytes is not needed; we must refer to it to avoid the
+             compiler warning
+    */
+
+    align_in_bytes;
+
+    rv = ExAllocatePoolWithTag( NonPagedPool, size, 'sdfl' );
+
+    return( rv );
+  }
+
+#endif
+
diff --git a/liblfds/src/abstraction/abstraction_cas.c b/liblfds/src/abstraction/abstraction_cas.c
new file mode 100644
index 0000000..aec51bb
--- /dev/null
+++ b/liblfds/src/abstraction/abstraction_cas.c
@@ -0,0 +1,109 @@
+#include "abstraction_internal.h"
+
+
+
+
+
+/****************************************************************************/
+#if (defined _WIN32 && defined _MSC_VER)
+
+  /* TRD : 64 bit and 32 bit Windows (user-mode or kernel) on any CPU with the Microsoft C compiler
+
+           _WIN32    indicates 64-bit or 32-bit Windows
+           _MSC_VER  indicates Microsoft C compiler
+  */
+
+  INLINE atom_t abstraction_cas( volatile atom_t *destination, atom_t exchange, atom_t compare )
+  {
+    assert( destination != NULL );
+    // TRD : exchange can be any value in its range
+    // TRD : compare can be any value in its range
+
+    return( (atom_t) _InterlockedCompareExchangePointer((void * volatile *) destination, (void *) exchange, (void *) compare) );
+  }
+
+#endif
+
+
+
+
+
+/****************************************************************************/
+#if (!defined __arm__ && __GNUC__ >= 4 && __GNUC_MINOR__ >= 1 && __GNUC_PATCHLEVEL__ >= 0)
+
+  /* TRD : any OS on any CPU except ARM with GCC 4.1.0 or better
+
+           GCC 4.1.0 introduced the __sync_*() atomic intrinsics
+
+           __GNUC__ / __GNUC_MINOR__ / __GNUC_PATCHLEVEL__  indicates GCC and which version
+  */
+
+  INLINE atom_t abstraction_cas( volatile atom_t *destination, atom_t exchange, atom_t compare )
+  {
+    assert( destination != NULL );
+    // TRD : exchange can be any value in its range
+    // TRD : compare can be any value in its range
+
+    // TRD : note the different argument order for the GCC instrinsic to the MSVC instrinsic
+
+    return( (atom_t) __sync_val_compare_and_swap(destination, compare, exchange) );
+  }
+
+#endif
+
+
+
+
+
+/****************************************************************************/
+#if (defined __arm__ && __GNUC__)
+
+  /* TRD : any OS on any ARM with GCC
+
+           Remember however we need to set into compare the original value of destination.
+
+           __arm__   indicates ARM
+           __GNUC__  indicates GCC
+  */
+
+  INLINE atom_t abstraction_cas( volatile atom_t *destination, atom_t exchange, atom_t compare )
+  {
+    atom_t
+      stored_flag,
+      original_destination;
+
+    assert( destination != NULL );
+    // TRD : exchange can be any value in its range
+    // TRD : compare can be any value in its range
+
+    /* TRD : this is a standard, plain CAS, vulnerable to ABA */
+
+    __asm__ __volatile__
+    (
+      "  mov    %[stored_flag], #1;"                             // put 1 into stored_flag
+      "  mcr    p15, 0, %[zero], c7, c10, 5;"                    // memory barrier (ARM v6 compatible)
+      "atomic_cas:;"
+      "  ldrex  %[original_destination], [%[destination]];"      // load *destination into original_destination
+      "  teq    %[original_destination], %[compare];"            // compare original_destination with compare
+      "  bne    exit;"                                           // if not equal, exit
+      "  strex  %[stored_flag], %[exchange], [%[destination]];"  // if equal, try to store exchange into *destination (on success, strex puts 0 into stored_flag)
+      "  teq    %[stored_flag], #0;"                             // check if stored_flag is 0
+      "  bne    atomic_cas;"                                     // if not 0, retry (someone else touched *destination after we loaded but before we stored)
+      "  mcr    p15, 0, %[zero], c7, c10, 5;"                    // memory barrier (ARM v6 compatible)
+      "exit:;"
+
+      // output
+      : "+m" (*destination), [original_destination] "=&r" (original_destination), [stored_flag] "=&r" (stored_flag)
+
+      // input
+      : [destination] "r" (destination), [compare] "r" (compare), [exchange] "r" (exchange), [zero] "r" (0)
+
+      // clobbered
+      : "cc", "memory"                                           // memory is clobbered because we issue a memory barrier
+    );
+
+    return( original_destination );
+  }
+
+#endif
+
diff --git a/liblfds/src/abstraction/abstraction_dcas.c b/liblfds/src/abstraction/abstraction_dcas.c
new file mode 100644
index 0000000..48fbad5
--- /dev/null
+++ b/liblfds/src/abstraction/abstraction_dcas.c
@@ -0,0 +1,356 @@
+#include "abstraction_internal.h"
+
+
+
+
+
+/****************************************************************************/
+#if (defined _WIN64 && defined _MSC_VER)
+
+  /* TRD : 64 bit Windows (user-mode or kernel) on any CPU with the Microsoft C compiler
+
+           _WIN64    indicates 64 bit Windows
+           _MSC_VER  indicates Microsoft C compiler
+  */
+
+  INLINE unsigned char abstraction_dcas( volatile atom_t *destination, atom_t *exchange, atom_t *compare )
+  {
+    unsigned char
+      cas_result;
+
+    assert( destination != NULL );
+    assert( exchange != NULL );
+    assert( compare != NULL );
+
+    cas_result = _InterlockedCompareExchange128( (volatile __int64 *) destination, (__int64) *(exchange+1), (__int64) *exchange, (__int64 *) compare );
+
+    return( cas_result );
+  }
+
+#endif
+
+
+
+
+
+/****************************************************************************/
+#if (!defined _WIN64 && defined _WIN32 && defined _MSC_VER)
+
+  /* TRD : 32 bit Windows (user-mode or kernel) on any CPU with the Microsoft C compiler
+
+           (!defined _WIN64 && defined _WIN32)  indicates 32 bit Windows
+           _MSC_VER                             indicates Microsoft C compiler
+  */
+
+  INLINE unsigned char abstraction_dcas( volatile atom_t *destination, atom_t *exchange, atom_t *compare )
+  {
+    __int64
+      original_compare;
+
+    assert( destination != NULL );
+    assert( exchange != NULL );
+    assert( compare != NULL );
+
+    *(__int64 *) &original_compare = *(__int64 *) compare;
+
+    *(__int64 *) compare = _InterlockedCompareExchange64( (volatile __int64 *) destination, *(__int64 *) exchange, *(__int64 *) compare );
+
+    return( (unsigned char) (*(__int64 *) compare == *(__int64 *) &original_compare) );
+  }
+
+#endif
+
+
+
+
+
+/****************************************************************************/
+#if (defined __x86_64__ && __GNUC__ && !defined __pic__)
+
+  /* TRD : any OS on x64 with GCC for statically linked code
+
+           __x86_64__  indicates x64
+           __GNUC__    indicates GCC
+  */
+
+  INLINE unsigned char abstraction_dcas( volatile atom_t *destination, atom_t *exchange, atom_t *compare )
+  {
+    unsigned char
+      cas_result;
+
+    assert( destination != NULL );
+    assert( exchange != NULL );
+    assert( compare != NULL );
+
+    __asm__ __volatile__
+    (
+      "lock;"           // make cmpxchg16b atomic
+      "cmpxchg16b %0;"  // cmpxchg16b sets ZF on success
+      "setz       %3;"  // if ZF set, set cas_result to 1
+
+      // output
+      : "+m" (*(volatile atom_t (*)[2]) destination), "+a" (*compare), "+d" (*(compare+1)), "=q" (cas_result)
+
+      // input
+      : "b" (*exchange), "c" (*(exchange+1))
+
+      // clobbered
+      : "cc", "memory"
+    );
+
+    return( cas_result );
+  }
+
+#endif
+
+
+
+
+
+
+/****************************************************************************/
+#if (defined __i686__ && __GNUC__ && !defined __pic__)
+
+  /* TRD : any OS on x86 with GCC for statically linked code
+
+           __i686__  indicates x86
+           __GNUC__  indicates GCC
+  */
+
+  INLINE unsigned char abstraction_dcas( volatile atom_t *destination, atom_t *exchange, atom_t *compare )
+  {
+    unsigned char
+      cas_result;
+
+    assert( destination != NULL );
+    assert( exchange != NULL );
+    assert( compare != NULL );
+
+    __asm__ __volatile__
+    (
+      "lock;"          // make cmpxchg8b atomic
+      "cmpxchg8b %0;"  // cmpxchg8b sets ZF on success
+      "setz      %3;"  // if ZF set, set cas_result to 1
+
+      // output
+      : "+m" (*(volatile atom_t (*)[2]) destination), "+a" (*compare), "+d" (*(compare+1)), "=q" (cas_result)
+
+      // input
+      : "b" (*exchange), "c" (*(exchange+1))
+
+      // clobbered
+      : "cc", "memory"
+    );
+
+    return( cas_result );
+  }
+
+#endif
+
+
+
+
+
+/****************************************************************************/
+#if (defined __x86_64__ && __GNUC__ && defined __pic__)
+
+  /* TRD : any OS on x64 with GCC for position independent code (e.g. a shared object)
+
+           __x86_64__  indicates x64
+           __GNUC__    indicates GCC
+  */
+
+  INLINE unsigned char abstraction_dcas( volatile atom_t *destination, atom_t *exchange, atom_t *compare )
+  {
+    unsigned char
+      cas_result;
+
+    assert( destination != NULL );
+    assert( exchange != NULL );
+    assert( compare != NULL );
+
+    /* TRD : with a shared object, we cannot clobber RBX
+             as such, we borrow RSI - we load half of the exchange value into it
+             then swap it with RBX
+             then do the compare-and-swap
+             then swap the original value of RBX back from RSI
+    */
+
+    __asm__ __volatile__
+    (
+      "xchg %%rsi, %%rbx;"  // swap RBI and RBX 
+      "lock;"               // make cmpxchg16b atomic
+      "cmpxchg16b %0;"      // cmpxchg16b sets ZF on success
+      "setz       %3;"      // if ZF set, set cas_result to 1
+      "xchg %%rbx, %%rsi;"  // re-swap RBI and RBX
+
+      // output
+      : "+m" (*(volatile atom_t (*)[2]) destination), "+a" (*compare), "+d" (*(compare+1)), "=q" (cas_result)
+
+      // input
+      : "S" (*exchange), "c" (*(exchange+1))
+
+      // clobbered
+      : "cc", "memory"
+    );
+
+    return( cas_result );
+  }
+
+#endif
+
+
+
+
+
+
+/****************************************************************************/
+#if (defined __i686__ && __GNUC__ && defined __pic__)
+
+  /* TRD : any OS on x86 with GCC for position independent code (e.g. a shared object)
+
+           __i686__  indicates x86
+           __GNUC__  indicates GCC
+  */
+
+  INLINE unsigned char abstraction_dcas( volatile atom_t *destination, atom_t *exchange, atom_t *compare )
+  {
+    unsigned char
+      cas_result;
+
+    assert( destination != NULL );
+    assert( exchange != NULL );
+    assert( compare != NULL );
+
+    /* TRD : with a shared object, we cannot clobber EBX
+             as such, we borrow ESI - we load half of the exchange value into it
+             then swap it with EBX
+             then do the compare-and-swap
+             then swap the original value of EBX back from ESI
+    */
+
+    __asm__ __volatile__
+    (
+      "xchg %%esi, %%ebx;"  // swap EBI and EBX
+      "lock;"               // make cmpxchg8b atomic
+      "cmpxchg8b %0;"       // cmpxchg8b sets ZF on success
+      "setz      %3;"       // if ZF set, set cas_result to 1
+      "xchg %%ebx, %%esi;"  // re-swap EBI and EBX
+
+      // output
+      : "+m" (*(volatile atom_t (*)[2]) destination), "+a" (*compare), "+d" (*(compare+1)), "=q" (cas_result)
+
+      // input
+      : "S" (*exchange), "c" (*(exchange+1))
+
+      // clobbered
+      : "cc", "memory"
+    );
+
+    return( cas_result );
+  }
+
+#endif
+
+
+
+
+
+/****************************************************************************/
+#if (defined __arm__ && __GNUC__)
+
+  /* TRD : any OS on any ARM with GCC
+
+           Remember however we need to set into compare the original value of destination.
+
+           __arm__   indicates ARM
+           __GNUC__  indicates GCC
+  */
+
+  INLINE unsigned char abstraction_dcas( volatile atom_t *destination, atom_t *exchange, atom_t *compare )
+  {
+    atom_t
+      *local_compare = compare,
+      stored_flag = 1;
+
+    register atom_t
+      local_exchange_a __asm("r2"),
+      local_exchange_b __asm("r3"),
+      local_compare_a __asm("r4"),
+      local_compare_b __asm("r5"),
+      original_destination_a __asm("r6"),
+      original_destination_b __asm("r7");
+
+    assert( destination != NULL );
+    assert( exchange != NULL );
+    assert( compare != NULL );
+
+    /* TRD : some notes
+
+             the double word ldr and str instructions require contigous registers
+             where the first register is an even number
+
+             honouring this requirement requires us to specifically specify
+             the registers to use (which is why we're using register __asm("rN")
+             in the declerations above
+
+             the arguments to the function occupy registers r0, r1 and r2
+
+             we can use up to and including r8, but r9 can have a frame pointer in it
+
+             so we make a copy of compare (freeing up r2, so we can use it for a double
+             word load) but use destination (r0) and exchange (r1) directly
+
+             note LDRD and STRD became available in armv6k
+
+             apologies for the trickery with the mcr register variable - the code runs
+             out of registers on armv6k
+    */
+
+    __asm__ __volatile__
+    (
+      "  mov     %[stored_flag], #1;"                                                                // put 1 into stored_flag
+      "  mov     %[local_exchange_a], #0;"                                                           // borrow local_exchange_a for mcr, to save a register
+      "  mcr     p15, 0, %[local_exchange_a], c7, c10, 5;"                                           // memory barrier (ARM v6 compatible)
+      "  ldrd    %[local_exchange_a], %[local_exchange_b], [%[exchange]];"                           // load exchange into local_exchange_a and local_exchange_b (which are r2 and r3, respectively)
+      "  ldrd    %[local_compare_a], %[local_compare_b], [%[local_compare]];"                        // load compare into local_compare_a and local_compare_b (which are r4 and r5, respectively)
+      "atomic_dcas:;"
+      "  ldrexd  %[original_destination_a], %[original_destination_b], [%[destination]];"            // load destination into original_destination_a and original_destination_b (which are r6 and r7, respectively)
+      "  teq     %[original_destination_a], %[local_compare_a];"                                     // compare the first word of destination with the first word of compare
+      "  teqeq   %[original_destination_b], %[local_compare_b];"                                     // if they're equal, compare the second word of destination with the second word of compare
+      "  bne     exit;"                                                                              // if either word of destination does not match its respective word of compare, exit
+      "  strexd  %[stored_flag], %[local_exchange_a], %[local_exchange_b], [%[destination]];"        // if both words were equal, try to store local_exchange_a and local_exchange_b into *destination (on success, strexed puts 0 into stored_flag)
+      "  teq     %[stored_flag], #0;"                                                                // check if stored_flag is 0
+      "  bne     atomic_dcas;"                                                                       // if not 0, retry (someone else touched *destination after we loaded but before we stored)
+      "exit:;"
+      "  strd    %[original_destination_a], %[original_destination_b], [%[local_compare]];"          // whether or not the CAS swapped, we always write the original value of destination into *compare
+      "  mov     %[local_exchange_a], #0;"                                                           // borrow local_exchange_a for mcr, to save a register
+      "  mcr     p15, 0, %[local_exchange_a], c7, c10, 5;"                                           // memory barrier (ARM v6 compatible)
+
+      // output
+      : "+m" (*(volatile atom_t (*)[2]) destination), "+m" (*(atom_t (*)[2]) local_compare),
+        [stored_flag] "+&r" (stored_flag),
+        [original_destination_a] "+&r" (original_destination_a), [original_destination_b] "+&r" (original_destination_b),
+        [local_compare_a] "+&r" (local_compare_a), [local_compare_b] "+&r" (local_compare_b),
+        [local_exchange_a] "+&r" (local_exchange_a), [local_exchange_b] "+&r" (local_exchange_b)
+
+      // input
+      : "m" (*(atom_t (*)[2]) exchange),
+        [destination] "r" (destination),
+        [local_compare] "r" (local_compare),
+        [exchange] "r" (exchange)
+
+      // clobbered
+      : "cc", "memory"                                                                               // memory is clobbered because we issue a memory barrier
+    );
+
+    /* TRD : stored_flag is set to 0 on store, 1 on fail
+             we need to return 1 on success, 0 on fail
+    */
+
+    return( (unsigned char) !stored_flag  );
+  }
+
+#endif
+
+
diff --git a/liblfds/src/abstraction/abstraction_increment.c b/liblfds/src/abstraction/abstraction_increment.c
new file mode 100644
index 0000000..eebbc3b
--- /dev/null
+++ b/liblfds/src/abstraction/abstraction_increment.c
@@ -0,0 +1,136 @@
+#include "abstraction_internal.h"
+
+
+
+
+
+/****************************************************************************/
+#if (defined _WIN64 && defined _MSC_VER)
+
+  /* TRD : 64 bit Windows (user-mode or kernel) on any CPU with the Microsoft C compiler
+
+           _WIN64    indicates 64 bit Windows
+           _MSC_VER  indicates Microsoft C compiler
+  */
+
+  INLINE atom_t abstraction_increment( atom_t *value )
+  {
+    __int64
+      rv;
+
+    assert( value != NULL );
+
+    rv = _InterlockedIncrement64( (__int64 *) value );
+
+    return( (atom_t) rv );
+  }
+
+#endif
+
+
+
+
+
+/****************************************************************************/
+#if (!defined _WIN64 && defined _WIN32 && defined _MSC_VER)
+
+  /* TRD : 32 bit Windows (user-mode or kernel) on any CPU with the Microsoft C compiler
+
+           (!defined _WIN64 && defined _WIN32)  indicates 32 bit Windows
+           _MSC_VER                             indicates Microsoft C compiler
+  */
+
+  INLINE atom_t abstraction_increment( atom_t *value )
+  {
+    long int
+      rv;
+
+    assert( value != NULL );
+
+    rv = _InterlockedIncrement( (long int *) value );
+
+    return( (atom_t) rv );
+  }
+
+#endif
+
+
+
+
+
+/****************************************************************************/
+#if (!defined __arm__ && __GNUC__ >= 4 && __GNUC_MINOR__ >= 1 && __GNUC_PATCHLEVEL__ >= 0)
+
+  /* TRD : any OS on any CPU with GCC 4.1.0 or better
+
+           GCC 4.1.0 introduced the __sync_*() atomic intrinsics
+
+           __GNUC__ / __GNUC_MINOR__ / __GNUC_PATCHLEVEL__  indicates GCC and which version
+  */
+
+  INLINE atom_t abstraction_increment( atom_t *value )
+  {
+    atom_t
+      rv;
+
+    assert( value != NULL );
+
+    // TRD : no need for casting here, GCC has a __sync_add_and_fetch() for all native types
+
+    rv = __sync_add_and_fetch( value, 1 );
+
+    return( rv );
+  }
+
+#endif
+
+
+
+
+
+/****************************************************************************/
+#if (defined __arm__ && __GNUC__ >= 4)
+
+  /* TRD : any OS on any CPU with GCC 4.1.0 or better
+
+           GCC 4.1.0 introduced the __sync_*() atomic intrinsics
+
+           __arm__   indicates ARM
+           __GNUC__  indicates GCC
+  */
+
+  INLINE atom_t abstraction_increment( atom_t *value )
+  {
+    atom_t
+      stored_flag = 0,
+      new_value = 0;
+
+    assert( value != NULL );
+
+    __asm__ __volatile__
+    (
+      "  mov    %[stored_flag], #1;"                        // move 1 into stored_flag
+      "  mcr    p15, 0, %[zero], c7, c10, 5;"               // memory barrier (ARM v6 compatible)
+      "atomic_add:;"
+      "  ldrex  %[new_value], [%[value]];  "                // load *value into new_value
+      "  add    %[new_value], #1;"                          // add 1 to new_value
+      "  strex  %[stored_flag], %[new_value], [%[value]];"  // try to store new_value into *value (on success, strex puts 0 into stored_flag)
+      "  teq    %[stored_flag], #0;"                        // check if stored_flag is 0
+      "  bne    atomic_add;"                                // if not 0, retry (someone else touched *value after we loaded but before we stored)
+      "  mcr    p15, 0, %[zero], c7, c10, 5;"               // memory barrier (ARM v6 compatible)
+
+      // output
+      : "+m" (*value), [new_value] "+&r" (new_value), [stored_flag] "+&r" (stored_flag)
+
+      // input
+      : [value] "r" (value), [zero] "r" (0)
+
+      // clobbered
+      : "cc", "memory"                                      // memory is clobbered because we issue a memory barrier
+    );
+
+    return( new_value );
+  }
+
+#endif
+
diff --git a/liblfds/src/abstraction/abstraction_internal.h b/liblfds/src/abstraction/abstraction_internal.h
new file mode 100644
index 0000000..0a4d29d
--- /dev/null
+++ b/liblfds/src/abstraction/abstraction_internal.h
@@ -0,0 +1,5 @@
+/***** the library wide include file *****/
+#include "liblfds_internal.h"
+
+/***** private prototypes *****/
+
diff --git a/liblfds/src/dirs b/liblfds/src/dirs
new file mode 100644
index 0000000..64e002c
--- /dev/null
+++ b/liblfds/src/dirs
@@ -0,0 +1,3 @@
+DIRS = single_dir_for_windows_kernel
+
+
diff --git a/liblfds/src/driver_entry.c b/liblfds/src/driver_entry.c
new file mode 100644
index 0000000..6813ff6
--- /dev/null
+++ b/liblfds/src/driver_entry.c
@@ -0,0 +1,16 @@
+#include "stack_internal.h"
+
+
+
+
+
+/****************************************************************************/
+#pragma warning( disable : 4100 )
+
+NTSTATUS DriverEntry( struct _DRIVER_OBJECT *DriverObject, PUNICODE_STRING RegistryPath )
+{
+  return( STATUS_SUCCESS );
+}
+
+#pragma warning( default : 4100 )
+
diff --git a/liblfds/src/driver_entry_readme.txt b/liblfds/src/driver_entry_readme.txt
new file mode 100644
index 0000000..bff054b
--- /dev/null
+++ b/liblfds/src/driver_entry_readme.txt
@@ -0,0 +1,4 @@
+This C file (driver_entry.c) is used when building a dynamic library for
+the Windows kernel.  It exists to work around one of the limitations of
+that build environment.  It is not used  by any other build; just ignore it.
+
diff --git a/liblfds/src/freelist/freelist_delete.c b/liblfds/src/freelist/freelist_delete.c
new file mode 100644
index 0000000..944ffb3
--- /dev/null
+++ b/liblfds/src/freelist/freelist_delete.c
@@ -0,0 +1,35 @@
+#include "freelist_internal.h"
+
+
+
+
+
+/****************************************************************************/
+void freelist_delete( struct freelist_state *fs, void (*user_data_delete_function)(void *user_data, void *user_state), void *user_state )
+{
+  struct freelist_element
+    *fe;
+
+  void
+    *user_data;
+
+  assert( fs != NULL );
+  // TRD : user_data_delete_function can be NULL
+  // TRD : user_state can be NULL
+
+  while( freelist_pop(fs, &fe) )
+  {
+    if( user_data_delete_function != NULL )
+    {
+      freelist_get_user_data_from_element( fe, &user_data );
+      user_data_delete_function( user_data, user_state );
+    }
+
+    abstraction_aligned_free( fe );
+  }
+
+  abstraction_aligned_free( fs );
+
+  return;
+}
+
diff --git a/liblfds/src/freelist/freelist_get_and_set.c b/liblfds/src/freelist/freelist_get_and_set.c
new file mode 100644
index 0000000..a0b2a5a
--- /dev/null
+++ b/liblfds/src/freelist/freelist_get_and_set.c
@@ -0,0 +1,33 @@
+#include "freelist_internal.h"
+
+
+
+
+
+/****************************************************************************/
+void *freelist_get_user_data_from_element( struct freelist_element *fe, void **user_data )
+{
+  assert( fe != NULL );
+  // TRD : user_data can be NULL
+
+  if( user_data != NULL )
+    *user_data = fe->user_data;
+
+  return( fe->user_data );
+}
+
+
+
+
+
+/****************************************************************************/
+void freelist_set_user_data_in_element( struct freelist_element *fe, void *user_data )
+{
+  assert( fe != NULL );
+  // TRD : user_data can be NULL
+
+  fe->user_data = user_data;
+
+  return;
+}
+
diff --git a/liblfds/src/freelist/freelist_internal.h b/liblfds/src/freelist/freelist_internal.h
new file mode 100644
index 0000000..8d8550a
--- /dev/null
+++ b/liblfds/src/freelist/freelist_internal.h
@@ -0,0 +1,42 @@
+/***** the library wide include file *****/
+#include "liblfds_internal.h"
+
+/***** defines *****/
+#define FREELIST_POINTER 0
+#define FREELIST_COUNTER 1
+#define FREELIST_PAC_SIZE 2
+
+/***** structures *****/
+#pragma pack( push, ALIGN_DOUBLE_POINTER )
+
+struct freelist_state
+{
+  struct freelist_element
+    *volatile top[FREELIST_PAC_SIZE];
+
+  int
+    (*user_data_init_function)( void **user_data, void *user_state );
+
+  void
+    *user_state;
+
+  atom_t
+    aba_counter,
+    element_count;
+};
+
+struct freelist_element
+{
+  struct freelist_element
+    *next[FREELIST_PAC_SIZE];
+
+  void
+    *user_data;
+};
+
+#pragma pack( pop )
+
+/***** private prototypes *****/
+atom_t freelist_internal_new_element( struct freelist_state *fs, struct freelist_element **fe );
+void freelist_internal_validate( struct freelist_state *fs, struct validation_info *vi, enum data_structure_validity *freelist_validity );
+
diff --git a/liblfds/src/freelist/freelist_new.c b/liblfds/src/freelist/freelist_new.c
new file mode 100644
index 0000000..c730623
--- /dev/null
+++ b/liblfds/src/freelist/freelist_new.c
@@ -0,0 +1,123 @@
+#include "freelist_internal.h"
+
+
+
+
+
+/****************************************************************************/
+int freelist_new( struct freelist_state **fs, atom_t number_elements, int (*user_data_init_function)(void **user_data, void *user_state), void *user_state )
+{
+  int
+    rv = 0;
+
+  atom_t
+    element_count;
+
+  assert( fs != NULL );
+  // TRD : number_elements can be any value in its range
+  // TRD : user_data_init_function can be NULL
+
+  *fs = (struct freelist_state *) abstraction_aligned_malloc( sizeof(struct freelist_state), ALIGN_DOUBLE_POINTER );
+
+  if( (*fs) != NULL )
+  {
+    (*fs)->top[FREELIST_POINTER] = NULL;
+    (*fs)->top[FREELIST_COUNTER] = 0;
+    (*fs)->user_data_init_function = user_data_init_function;
+    (*fs)->user_state = user_state;
+    (*fs)->aba_counter = 0;
+    (*fs)->element_count = 0;
+
+    element_count = freelist_new_elements( *fs, number_elements );
+
+    if( element_count == number_elements )
+      rv = 1;
+
+    if( element_count != number_elements )
+    {
+      abstraction_aligned_free( (*fs) );
+      *fs = NULL;
+    }
+  }
+
+  return( rv );
+}
+
+
+
+
+
+/****************************************************************************/
+atom_t freelist_new_elements( struct freelist_state *fs, atom_t number_elements )
+{
+  struct freelist_element
+    *fe;
+
+  atom_t
+    loop,
+    count = 0;
+
+  assert( fs != NULL );
+  // TRD : number_elements can be any value in its range
+  // TRD : user_data_init_function can be NULL
+
+  for( loop = 0 ; loop < number_elements ; loop++ )
+    if( freelist_internal_new_element(fs, &fe) )
+    {
+      freelist_push( fs, fe );
+      count++;
+    }
+
+  return( count );
+}
+
+
+
+
+
+/****************************************************************************/
+atom_t freelist_internal_new_element( struct freelist_state *fs, struct freelist_element **fe )
+{
+  atom_t
+    rv = 0;
+
+  assert( fs != NULL );
+  assert( fe != NULL );
+
+  /* TRD : basically, does what you'd expect;
+
+           allocates an element
+           calls the user init function
+           if anything fails, cleans up,
+           sets *fe to NULL
+           and returns 0
+  */
+
+  *fe = (struct freelist_element *) abstraction_aligned_malloc( sizeof(struct freelist_element), ALIGN_DOUBLE_POINTER );
+
+  if( *fe != NULL )
+  {
+    if( fs->user_data_init_function == NULL )
+    {
+      (*fe)->user_data = NULL;
+      rv = 1;
+    }
+
+    if( fs->user_data_init_function != NULL )
+    {
+      rv = fs->user_data_init_function( &(*fe)->user_data, fs->user_state );
+
+      if( rv == 0 )
+      {
+        abstraction_aligned_free( *fe );
+        *fe = NULL;
+      }
+    }
+  }
+
+  if( rv == 1 )
+    abstraction_increment( (atom_t *) &fs->element_count );
+
+  return( rv );
+}
+
diff --git a/liblfds/src/freelist/freelist_pop_push.c b/liblfds/src/freelist/freelist_pop_push.c
new file mode 100644
index 0000000..b49af56
--- /dev/null
+++ b/liblfds/src/freelist/freelist_pop_push.c
@@ -0,0 +1,88 @@
+#include "freelist_internal.h"
+
+
+
+
+
+/****************************************************************************/
+struct freelist_element *freelist_pop( struct freelist_state *fs, struct freelist_element **fe )
+{
+  ALIGN(ALIGN_DOUBLE_POINTER) struct freelist_element
+    *fe_local[FREELIST_PAC_SIZE];
+
+  assert( fs != NULL );
+  assert( fe != NULL );
+
+  fe_local[FREELIST_COUNTER] = fs->top[FREELIST_COUNTER];
+  fe_local[FREELIST_POINTER] = fs->top[FREELIST_POINTER];
+
+  /* TRD : note that abstraction_dcas loads the original value of the destination (fs->top) into the compare (fe_local)
+           (this happens of course after the CAS itself has occurred inside abstraction_dcas)
+  */
+
+  do
+  {
+    if( fe_local[FREELIST_POINTER] == NULL )
+    {
+      *fe = NULL;
+      return( *fe );
+    }
+  }
+  while( 0 == abstraction_dcas((volatile atom_t *) fs->top, (atom_t *) fe_local[FREELIST_POINTER]->next, (atom_t *) fe_local) );
+
+  *fe = (struct freelist_element *) fe_local[FREELIST_POINTER];
+
+  return( *fe );
+}
+
+
+
+
+
+/****************************************************************************/
+struct freelist_element *freelist_guaranteed_pop( struct freelist_state *fs, struct freelist_element **fe )
+{
+  assert( fs != NULL );
+  assert( fe != NULL );
+
+  freelist_internal_new_element( fs, fe );
+
+  return( *fe );
+}
+
+
+
+
+
+/****************************************************************************/
+void freelist_push( struct freelist_state *fs, struct freelist_element *fe )
+{
+  ALIGN(ALIGN_DOUBLE_POINTER) struct freelist_element
+    *fe_local[FREELIST_PAC_SIZE],
+    *original_fe_next[FREELIST_PAC_SIZE];
+
+  assert( fs != NULL );
+  assert( fe != NULL );
+
+  fe_local[FREELIST_POINTER] = fe;
+  fe_local[FREELIST_COUNTER] = (struct freelist_element *) abstraction_increment( (atom_t *) &fs->aba_counter );
+
+  original_fe_next[FREELIST_POINTER] = fs->top[FREELIST_POINTER];
+  original_fe_next[FREELIST_COUNTER] = fs->top[FREELIST_COUNTER];
+
+  /* TRD : note that abstraction_dcas loads the original value of the destination (fs->top) into the compare (original_fe_next)
+           (this happens of course after the CAS itself has occurred inside abstraction_dcas)
+           this then causes us in our loop, should we repeat it, to update fe_local->next to a more
+           up-to-date version of the head of the freelist
+  */
+
+  do
+  {
+    fe_local[FREELIST_POINTER]->next[FREELIST_POINTER] = original_fe_next[FREELIST_POINTER];
+    fe_local[FREELIST_POINTER]->next[FREELIST_COUNTER] = original_fe_next[FREELIST_COUNTER];
+  }
+  while( 0 == abstraction_dcas((volatile atom_t *) fs->top, (atom_t *) fe_local, (atom_t *) original_fe_next) );
+
+  return;
+}
+
diff --git a/liblfds/src/freelist/freelist_query.c b/liblfds/src/freelist/freelist_query.c
new file mode 100644
index 0000000..7d7a7fb
--- /dev/null
+++ b/liblfds/src/freelist/freelist_query.c
@@ -0,0 +1,113 @@
+#include "freelist_internal.h"
+
+
+
+
+
+/****************************************************************************/
+void freelist_query( struct freelist_state *fs, enum freelist_query_type query_type, void *query_input, void *query_output )
+{
+  assert( fs != NULL );
+  // TRD : query type can be any value in its range
+  // TRD : query_input can be NULL in some cases
+  assert( query_output != NULL );
+
+  switch( query_type )
+  {
+    case FREELIST_QUERY_ELEMENT_COUNT:
+      assert( query_input == NULL );
+
+      *(atom_t *) query_output = fs->element_count;
+    break;
+
+    case FREELIST_QUERY_VALIDATE:
+      // TRD : query_input can be NULL
+
+      freelist_internal_validate( fs, (struct validation_info *) query_input, (enum data_structure_validity *) query_output );
+    break;
+  }
+
+  return;
+}
+
+
+
+
+
+/****************************************************************************/
+void freelist_internal_validate( struct freelist_state *fs, struct validation_info *vi, enum data_structure_validity *freelist_validity )
+{
+  struct freelist_element
+    *fe,
+    *fe_slow,
+    *fe_fast;
+
+  atom_t
+    element_count = 0;
+
+  assert( fs != NULL );
+  // TRD : vi can be NULL
+  assert( freelist_validity != NULL );
+
+  *freelist_validity = VALIDITY_VALID;
+
+  fe_slow = fe_fast = (struct freelist_element *) fs->top[FREELIST_POINTER];
+
+  /* TRD : first, check for a loop
+           we have two pointers
+           both of which start at the top of the freelist
+           we enter a loop
+           and on each iteration
+           we advance one pointer by one element
+           and the other by two
+
+           we exit the loop when both pointers are NULL
+           (have reached the end of the freelist)
+
+           or
+
+           if we fast pointer 'sees' the slow pointer
+           which means we have a loop
+  */
+
+  if( fe_slow != NULL )
+    do
+    {
+      fe_slow = fe_slow->next[FREELIST_POINTER];
+
+      if( fe_fast != NULL )
+        fe_fast = fe_fast->next[FREELIST_POINTER];
+
+      if( fe_fast != NULL )
+        fe_fast = fe_fast->next[FREELIST_POINTER];
+    }
+    while( fe_slow != NULL and fe_fast != fe_slow );
+
+  if( fe_fast != NULL and fe_slow != NULL and fe_fast == fe_slow )
+    *freelist_validity = VALIDITY_INVALID_LOOP;
+
+  /* TRD : now check for expected number of elements
+           vi can be NULL, in which case we do not check
+           we know we don't have a loop from our earlier check
+  */
+
+  if( *freelist_validity == VALIDITY_VALID and vi != NULL )
+  {
+    fe = (struct freelist_element *) fs->top[FREELIST_POINTER];
+
+    while( fe != NULL )
+    {
+      element_count++;
+      fe = (struct freelist_element *) fe->next[FREELIST_POINTER];
+    }
+
+    if( element_count < vi->min_elements )
+      *freelist_validity = VALIDITY_INVALID_MISSING_ELEMENTS;
+
+    if( element_count > vi->max_elements )
+      *freelist_validity = VALIDITY_INVALID_ADDITIONAL_ELEMENTS;
+  }
+
+  return;
+}
+
diff --git a/liblfds/src/liblfds_internal.h b/liblfds/src/liblfds_internal.h
new file mode 100644
index 0000000..cab1b10
--- /dev/null
+++ b/liblfds/src/liblfds_internal.h
@@ -0,0 +1,12 @@
+/***** public prototypes *****/
+#include "liblfds.h"
+
+/***** defines *****/
+#define and &&
+#define or  ||
+
+#define RAISED   1
+#define LOWERED  0
+
+#define NO_FLAGS 0x0
+
diff --git a/liblfds/src/queue/queue_delete.c b/liblfds/src/queue/queue_delete.c
new file mode 100644
index 0000000..619db92
--- /dev/null
+++ b/liblfds/src/queue/queue_delete.c
@@ -0,0 +1,55 @@
+#include "queue_internal.h"
+
+
+
+
+
+/****************************************************************************/
+void queue_delete( struct queue_state *qs, void (*user_data_delete_function)(void *user_data, void *user_state), void *user_state )
+{
+  void
+    *user_data;
+
+  assert( qs != NULL );
+  // TRD : user_data_delete_function can be NULL
+  // TRD : user_state can be NULL
+
+  while( queue_dequeue(qs, &user_data) )
+    if( user_data_delete_function != NULL )
+      user_data_delete_function( user_data, user_state );
+
+  /* TRD : fully dequeuing will leave us
+           with a single dummy element
+           which both qs->enqueue and qs->dequeue point at
+           we push this back onto the freelist
+           before we delete the freelist
+  */
+
+  freelist_push( qs->fs, qs->enqueue[QUEUE_POINTER]->fe );
+
+  freelist_delete( qs->fs, queue_internal_freelist_delete_function, NULL );
+
+  abstraction_aligned_free( qs );
+
+  return;
+}
+
+
+
+
+
+/****************************************************************************/
+#pragma warning( disable : 4100 )
+
+void queue_internal_freelist_delete_function( void *user_data, void *user_state )
+{
+  assert( user_data != NULL );
+  assert( user_state == NULL );
+
+  abstraction_aligned_free( user_data );
+
+  return;
+}
+
+#pragma warning( default : 4100 )
+
diff --git a/liblfds/src/queue/queue_internal.h b/liblfds/src/queue/queue_internal.h
new file mode 100644
index 0000000..7954e17
--- /dev/null
+++ b/liblfds/src/queue/queue_internal.h
@@ -0,0 +1,60 @@
+/***** the library wide include file *****/
+#include "liblfds_internal.h"
+
+/***** pragmas *****/
+
+/***** defines *****/
+#define QUEUE_STATE_UNKNOWN               -1
+#define QUEUE_STATE_EMPTY                  0
+#define QUEUE_STATE_ENQUEUE_OUT_OF_PLACE   1
+#define QUEUE_STATE_ATTEMPT_DEQUEUE        2
+
+#define QUEUE_POINTER 0
+#define QUEUE_COUNTER 1
+#define QUEUE_PAC_SIZE 2
+
+/***** structures *****/
+#pragma pack( push, ALIGN_DOUBLE_POINTER )
+
+struct queue_state
+{
+  struct queue_element
+    *volatile enqueue[QUEUE_PAC_SIZE],
+    *volatile dequeue[QUEUE_PAC_SIZE];
+
+  atom_t
+    aba_counter;
+
+  struct freelist_state
+    *fs;
+};
+
+struct queue_element
+{
+  // TRD : next in a queue requires volatile as it is target of CAS
+  struct queue_element
+    *volatile next[QUEUE_PAC_SIZE];
+
+  struct freelist_element
+    *fe;
+
+  void
+    *user_data;
+};
+
+#pragma pack( pop )
+
+/***** externs *****/
+
+/***** private prototypes *****/
+int queue_internal_freelist_init_function( void **user_data, void *user_state );
+void queue_internal_freelist_delete_function( void *user_data, void *user_state );
+
+void queue_internal_new_element_from_freelist( struct queue_state *qs, struct queue_element *qe[QUEUE_PAC_SIZE], void *user_data );
+void queue_internal_guaranteed_new_element_from_freelist( struct queue_state *qs, struct queue_element * qe[QUEUE_PAC_SIZE], void *user_data );
+void queue_internal_init_element( struct queue_state *qs, struct queue_element *qe[QUEUE_PAC_SIZE], struct freelist_element *fe, void *user_data );
+
+void queue_internal_queue( struct queue_state *qs, struct queue_element *qe[QUEUE_PAC_SIZE] );
+
+void queue_internal_validate( struct queue_state *qs, struct validation_info *vi, enum data_structure_validity *queue_validity, enum data_structure_validity *freelist_validity );
+
diff --git a/liblfds/src/queue/queue_new.c b/liblfds/src/queue/queue_new.c
new file mode 100644
index 0000000..bbda55b
--- /dev/null
+++ b/liblfds/src/queue/queue_new.c
@@ -0,0 +1,140 @@
+#include "queue_internal.h"
+
+
+
+
+
+/****************************************************************************/
+int queue_new( struct queue_state **qs, atom_t number_elements )
+{
+  int
+    rv = 0;
+
+  struct queue_element
+    *qe[QUEUE_PAC_SIZE];
+
+  assert( qs != NULL );
+  // TRD : number_elements can be any value in its range
+
+  *qs = (struct queue_state *) abstraction_aligned_malloc( sizeof(struct queue_state), ALIGN_DOUBLE_POINTER );
+
+  if( *qs != NULL )
+  {
+    // TRD : the size of the freelist is the size of the queue (+1 for the leading dummy element, which is hidden from the caller)
+    freelist_new( &(*qs)->fs, number_elements+1, queue_internal_freelist_init_function, NULL );
+
+    if( (*qs)->fs != NULL )
+    {
+      queue_internal_new_element_from_freelist( *qs, qe, NULL );
+      (*qs)->enqueue[QUEUE_POINTER] = (*qs)->dequeue[QUEUE_POINTER] = qe[QUEUE_POINTER];
+      (*qs)->aba_counter = 0;
+      rv = 1;
+    }
+
+    if( (*qs)->fs == NULL )
+    {
+      abstraction_aligned_free( *qs );
+      *qs = NULL;
+    }
+  }
+
+  return( rv );
+}
+
+
+
+
+
+/****************************************************************************/
+#pragma warning( disable : 4100 )
+
+int queue_internal_freelist_init_function( void **user_data, void *user_state )
+{
+  int
+    rv = 0;
+
+  assert( user_data != NULL );
+  assert( user_state == NULL );
+
+  *user_data = abstraction_aligned_malloc( sizeof(struct queue_element), ALIGN_DOUBLE_POINTER );
+
+  if( *user_data != NULL )
+    rv = 1;
+
+  return( rv );
+}
+
+#pragma warning( default : 4100 )
+
+
+
+
+
+/****************************************************************************/
+void queue_internal_new_element_from_freelist( struct queue_state *qs, struct queue_element *qe[QUEUE_PAC_SIZE], void *user_data )
+{
+  struct freelist_element
+    *fe;
+
+  assert( qs != NULL );
+  assert( qe != NULL );
+  // TRD : user_data can be any value in its range
+
+  qe[QUEUE_POINTER] = NULL;
+
+  freelist_pop( qs->fs, &fe );
+
+  if( fe != NULL )
+    queue_internal_init_element( qs, qe, fe, user_data );
+
+  return;
+}
+
+
+
+
+
+/****************************************************************************/
+void queue_internal_guaranteed_new_element_from_freelist( struct queue_state *qs, struct queue_element *qe[QUEUE_PAC_SIZE], void *user_data )
+{
+  struct freelist_element
+    *fe;
+
+  assert( qs != NULL );
+  assert( qe != NULL );
+  // TRD : user_data can be any value in its range
+
+  qe[QUEUE_POINTER] = NULL;
+
+  freelist_guaranteed_pop( qs->fs, &fe );
+
+  if( fe != NULL )
+    queue_internal_init_element( qs, qe, fe, user_data );
+
+  return;
+}
+
+
+
+
+
+/****************************************************************************/
+void queue_internal_init_element( struct queue_state *qs, struct queue_element *qe[QUEUE_PAC_SIZE], struct freelist_element *fe, void *user_data )
+{
+  assert( qs != NULL );
+  assert( qe != NULL );
+  assert( fe != NULL );
+  // TRD : user_data can be any value in its range
+
+  freelist_get_user_data_from_element( fe, (void **) &qe[QUEUE_POINTER] );
+  qe[QUEUE_COUNTER] = (struct queue_element *) abstraction_increment( (atom_t *) &qs->aba_counter );
+
+  qe[QUEUE_POINTER]->next[QUEUE_POINTER] = NULL;
+  qe[QUEUE_POINTER]->next[QUEUE_COUNTER] = (struct queue_element *) abstraction_increment( (atom_t *) &qs->aba_counter );
+
+  qe[QUEUE_POINTER]->fe = fe;
+  qe[QUEUE_POINTER]->user_data = user_data;
+
+  return;
+}
+
diff --git a/liblfds/src/queue/queue_query.c b/liblfds/src/queue/queue_query.c
new file mode 100644
index 0000000..ae61fed
--- /dev/null
+++ b/liblfds/src/queue/queue_query.c
@@ -0,0 +1,153 @@
+#include "queue_internal.h"
+
+
+
+
+
+/****************************************************************************/
+#pragma warning( disable : 4100 )
+
+void queue_query( struct queue_state *qs, enum queue_query_type query_type, void *query_input, void *query_output )
+{
+  assert( qs != NULL );
+  // TRD : query_type can be any value in its range
+  // TRD : query_input can be NULL
+  assert( query_output != NULL );
+
+  switch( query_type )
+  {
+    case QUEUE_QUERY_ELEMENT_COUNT:
+      assert( query_input == NULL );
+
+      freelist_query( qs->fs, FREELIST_QUERY_ELEMENT_COUNT, NULL, query_output );
+    break;
+
+    case QUEUE_QUERY_VALIDATE:
+      // TRD : query_input can be NULL
+
+      queue_internal_validate( qs, (struct validation_info *) query_input, (enum data_structure_validity *) query_output, ((enum data_structure_validity *) query_output)+1 );
+    break;
+  }
+
+  return;
+}
+
+#pragma warning( default : 4100 )
+
+
+
+
+
+/****************************************************************************/
+void queue_internal_validate( struct queue_state *qs, struct validation_info *vi, enum data_structure_validity *queue_validity, enum data_structure_validity *freelist_validity )
+{
+  struct queue_element
+    *qe,
+    *qe_slow,
+    *qe_fast;
+
+  atom_t
+    element_count = 0,
+    total_elements;
+
+  struct validation_info
+    freelist_vi;
+
+  assert( qs != NULL );
+  // TRD : vi can be NULL
+  assert( queue_validity != NULL );
+  assert( freelist_validity != NULL );
+
+  *queue_validity = VALIDITY_VALID;
+
+  qe_slow = qe_fast = (struct queue_element *) qs->dequeue[QUEUE_POINTER];
+
+  /* TRD : first, check for a loop
+           we have two pointers
+           both of which start at the dequeue end of the queue
+           we enter a loop
+           and on each iteration
+           we advance one pointer by one element
+           and the other by two
+
+           we exit the loop when both pointers are NULL
+           (have reached the end of the queue)
+
+           or
+
+           if we fast pointer 'sees' the slow pointer
+           which means we have a loop
+  */
+
+  if( qe_slow != NULL )
+    do
+    {
+      qe_slow = qe_slow->next[QUEUE_POINTER];
+
+      if( qe_fast != NULL )
+        qe_fast = qe_fast->next[QUEUE_POINTER];
+
+      if( qe_fast != NULL )
+        qe_fast = qe_fast->next[QUEUE_POINTER];
+    }
+    while( qe_slow != NULL and qe_fast != qe_slow );
+
+  if( qe_fast != NULL and qe_slow != NULL and qe_fast == qe_slow )
+    *queue_validity = VALIDITY_INVALID_LOOP;
+
+  /* TRD : now check for expected number of elements
+           vi can be NULL, in which case we do not check
+           we know we don't have a loop from our earlier check
+  */
+
+  if( *queue_validity == VALIDITY_VALID and vi != NULL )
+  {
+    qe = (struct queue_element *) qs->dequeue[QUEUE_POINTER];
+
+    while( qe != NULL )
+    {
+      element_count++;
+      qe = (struct queue_element *) qe->next[QUEUE_POINTER];
+    }
+
+    /* TRD : remember there is a dummy element in the queue */
+    element_count--;
+
+    if( element_count < vi->min_elements )
+      *queue_validity = VALIDITY_INVALID_MISSING_ELEMENTS;
+
+    if( element_count > vi->max_elements )
+      *queue_validity = VALIDITY_INVALID_ADDITIONAL_ELEMENTS;
+  }
+
+  /* TRD : now we validate the freelist
+
+           we may be able to check for the expected number of
+           elements in the freelist
+
+           if the caller has given us an expected min and max
+           number of elements in the queue, then the total number
+           of elements in the freelist, minus that min and max,
+           gives us the expected number of elements in the
+           freelist
+  */
+
+  if( vi != NULL )
+  {
+    freelist_query( qs->fs, FREELIST_QUERY_ELEMENT_COUNT, NULL, (void *) &total_elements );
+
+    /* TRD : remember there is a dummy element in the queue */
+    total_elements--;
+
+    freelist_vi.min_elements = total_elements - vi->max_elements;
+    freelist_vi.max_elements = total_elements - vi->min_elements;
+
+    freelist_query( qs->fs, FREELIST_QUERY_VALIDATE, (void *) &freelist_vi, (void *) freelist_validity );
+  }
+
+  if( vi == NULL )
+    freelist_query( qs->fs, FREELIST_QUERY_VALIDATE, NULL, (void *) freelist_validity );
+
+  return;
+}
+
diff --git a/liblfds/src/queue/queue_queue.c b/liblfds/src/queue/queue_queue.c
new file mode 100644
index 0000000..2b2b0a6
--- /dev/null
+++ b/liblfds/src/queue/queue_queue.c
@@ -0,0 +1,181 @@
+#include "queue_internal.h"
+
+
+
+
+
+/****************************************************************************/
+int queue_enqueue( struct queue_state *qs, void *user_data )
+{
+  ALIGN(ALIGN_DOUBLE_POINTER) struct queue_element
+    *qe[QUEUE_PAC_SIZE];
+
+  assert( qs != NULL );
+  // TRD : user_data can be NULL
+
+  queue_internal_new_element_from_freelist( qs, qe, user_data );
+
+  if( qe[QUEUE_POINTER] == NULL )
+    return( 0 );
+
+  queue_internal_queue( qs, qe );
+
+  return( 1 );
+}
+
+
+
+
+
+/****************************************************************************/
+int queue_guaranteed_enqueue( struct queue_state *qs, void *user_data )
+{
+  ALIGN(ALIGN_DOUBLE_POINTER) struct queue_element
+    *qe[QUEUE_PAC_SIZE];
+
+  assert( qs != NULL );
+  // TRD : user_data can be NULL
+
+  queue_internal_guaranteed_new_element_from_freelist( qs, qe, user_data );
+
+  if( qe[QUEUE_POINTER] == NULL )
+    return( 0 );
+
+  queue_internal_queue( qs, qe );
+
+  return( 1 );
+}
+
+
+
+
+
+/****************************************************************************/
+void queue_internal_queue( struct queue_state *qs, struct queue_element *qe[QUEUE_PAC_SIZE] )
+{
+  ALIGN(ALIGN_DOUBLE_POINTER) struct queue_element
+    *enqueue[QUEUE_PAC_SIZE],
+    *next[QUEUE_PAC_SIZE];
+
+  unsigned char
+    cas_result = 0;
+
+  assert( qs != NULL );
+  assert( qe != NULL );
+
+  do
+  {
+    enqueue[QUEUE_POINTER] = qs->enqueue[QUEUE_POINTER];
+    enqueue[QUEUE_COUNTER] = qs->enqueue[QUEUE_COUNTER];
+
+    next[QUEUE_POINTER] = enqueue[QUEUE_POINTER]->next[QUEUE_POINTER];
+    next[QUEUE_COUNTER] = enqueue[QUEUE_POINTER]->next[QUEUE_COUNTER];
+
+    /* TRD : this if() ensures that the next we read, just above,
+             really is from qs->enqueue (which we copied into enqueue)
+    */
+
+    if( qs->enqueue[QUEUE_POINTER] == enqueue[QUEUE_POINTER] and qs->enqueue[QUEUE_COUNTER] == enqueue[QUEUE_COUNTER] )
+    {
+      if( next[QUEUE_POINTER] == NULL )
+      {
+        qe[QUEUE_COUNTER] = next[QUEUE_COUNTER] + 1;
+        cas_result = abstraction_dcas( (volatile atom_t *) enqueue[QUEUE_POINTER]->next, (atom_t *) qe, (atom_t *) next );
+      }
+      else
+      {
+        next[QUEUE_COUNTER] = enqueue[QUEUE_COUNTER] + 1;
+        abstraction_dcas( (volatile atom_t *) qs->enqueue, (atom_t *) next, (atom_t *) enqueue );
+      }
+    }
+  }
+  while( cas_result == 0 );
+
+  qe[QUEUE_COUNTER] = enqueue[QUEUE_COUNTER] + 1;
+  abstraction_dcas( (volatile atom_t *) qs->enqueue, (atom_t *) qe, (atom_t *) enqueue );
+
+  return;
+}
+
+
+
+
+
+/****************************************************************************/
+int queue_dequeue( struct queue_state *qs, void **user_data )
+{
+  ALIGN(ALIGN_DOUBLE_POINTER) struct queue_element
+    *enqueue[QUEUE_PAC_SIZE],
+    *dequeue[QUEUE_PAC_SIZE],
+    *next[QUEUE_PAC_SIZE];
+
+  unsigned char
+    cas_result = 0;
+
+  int
+    rv = 1,
+    state = QUEUE_STATE_UNKNOWN,
+    finished_flag = LOWERED;
+
+  assert( qs != NULL );
+  assert( user_data != NULL );
+
+  do
+  {
+    dequeue[QUEUE_POINTER] = qs->dequeue[QUEUE_POINTER];
+    dequeue[QUEUE_COUNTER] = qs->dequeue[QUEUE_COUNTER];
+
+    enqueue[QUEUE_POINTER] = qs->enqueue[QUEUE_POINTER];
+    enqueue[QUEUE_COUNTER] = qs->enqueue[QUEUE_COUNTER];
+
+    next[QUEUE_POINTER] = dequeue[QUEUE_POINTER]->next[QUEUE_POINTER];
+    next[QUEUE_COUNTER] = dequeue[QUEUE_POINTER]->next[QUEUE_COUNTER];
+
+    /* TRD : confirm that dequeue didn't move between reading it
+             and reading its next pointer
+    */
+
+    if( dequeue[QUEUE_POINTER] == qs->dequeue[QUEUE_POINTER] and dequeue[QUEUE_COUNTER] == qs->dequeue[QUEUE_COUNTER] )
+    {
+      if( enqueue[QUEUE_POINTER] == dequeue[QUEUE_POINTER] and next[QUEUE_POINTER] == NULL )
+        state = QUEUE_STATE_EMPTY;
+
+      if( enqueue[QUEUE_POINTER] == dequeue[QUEUE_POINTER] and next[QUEUE_POINTER] != NULL )
+        state = QUEUE_STATE_ENQUEUE_OUT_OF_PLACE;
+
+      if( enqueue[QUEUE_POINTER] != dequeue[QUEUE_POINTER] )
+        state = QUEUE_STATE_ATTEMPT_DEQUEUE;
+
+      switch( state )
+      {
+        case QUEUE_STATE_EMPTY:
+          *user_data = NULL;
+          rv = 0;
+          finished_flag = RAISED;
+        break;
+
+        case QUEUE_STATE_ENQUEUE_OUT_OF_PLACE:
+          next[QUEUE_COUNTER] = enqueue[QUEUE_COUNTER] + 1;
+          abstraction_dcas( (volatile atom_t *) qs->enqueue, (atom_t *) next, (atom_t *) enqueue );
+        break;
+
+        case QUEUE_STATE_ATTEMPT_DEQUEUE:
+          *user_data = next[QUEUE_POINTER]->user_data;
+
+          next[QUEUE_COUNTER] = dequeue[QUEUE_COUNTER] + 1;
+          cas_result = abstraction_dcas( (volatile atom_t *) qs->dequeue, (atom_t *) next, (atom_t *) dequeue );
+
+          if( cas_result == 1 )
+            finished_flag = RAISED;
+        break;
+      }
+    }
+  }
+  while( finished_flag == LOWERED );
+
+  if( cas_result == 1 )
+    freelist_push( qs->fs, dequeue[QUEUE_POINTER]->fe );
+
+  return( rv );
+}
+
diff --git a/liblfds/src/ringbuffer/ringbuffer_delete.c b/liblfds/src/ringbuffer/ringbuffer_delete.c
new file mode 100644
index 0000000..8509b79
--- /dev/null
+++ b/liblfds/src/ringbuffer/ringbuffer_delete.c
@@ -0,0 +1,22 @@
+#include "ringbuffer_internal.h"
+
+
+
+
+
+/****************************************************************************/
+void ringbuffer_delete( struct ringbuffer_state *rs, void (*user_data_delete_function)(void *user_data, void *user_state), void *user_state )
+{
+  assert( rs != NULL );
+  // TRD : user_data_delete_function can be NULL
+  // TRD : user_state can be NULL
+
+  queue_delete( rs->qs, NULL, NULL );
+
+  freelist_delete( rs->fs, user_data_delete_function, user_state );
+
+  abstraction_aligned_free( rs );
+
+  return;
+}
+
diff --git a/liblfds/src/ringbuffer/ringbuffer_get_and_put.c b/liblfds/src/ringbuffer/ringbuffer_get_and_put.c
new file mode 100644
index 0000000..b7b6e9f
--- /dev/null
+++ b/liblfds/src/ringbuffer/ringbuffer_get_and_put.c
@@ -0,0 +1,108 @@
+#include "ringbuffer_internal.h"
+
+
+
+
+
+/****************************************************************************/
+struct freelist_element *ringbuffer_get_read_element( struct ringbuffer_state *rs, struct freelist_element **fe )
+{
+  assert( rs != NULL );
+  assert( fe != NULL );
+
+  queue_dequeue( rs->qs, (void **) fe );
+
+  return( *fe );
+}
+
+
+
+
+
+/****************************************************************************/
+struct freelist_element *ringbuffer_get_write_element( struct ringbuffer_state *rs, struct freelist_element **fe, int *overwrite_flag )
+{
+  assert( rs != NULL );
+  assert( fe != NULL );
+  // TRD : overwrite_flag can be NULL
+
+  /* TRD : we try to obtain an element from the freelist
+           if we can, we populate it and add it to the queue
+
+           if we cannot, then the ringbuffer is full
+           so instead we grab the current read element and
+           use that instead
+
+           dequeue may fail since the queue may be emptied
+           during our dequeue attempt
+
+           so what we actually do here is a loop, attempting
+           the freelist and if it fails then a dequeue, until
+           we obtain an element
+
+           once we have an element, we queue it
+
+           you may be wondering why this operation is in a loop
+           remember - these operations are lock-free; anything
+           can happen in between
+
+           so for example the pop could fail because the freelist
+           is empty; but by the time we go to get an element from
+           the queue, the whole queue has been emptied back into
+           the freelist!
+
+           if overwrite_flag is provided, we set it to 0 if we
+           obtained a new element from the freelist, 1 if we
+           stole an element from the queue
+  */
+
+  do
+  {
+    if( overwrite_flag != NULL )
+      *overwrite_flag = 0;
+
+    freelist_pop( rs->fs, fe );
+
+    if( *fe == NULL )
+    {
+      ringbuffer_get_read_element( rs, fe );
+
+      if( overwrite_flag != NULL and *fe != NULL )
+        *overwrite_flag = 1;
+    }
+  }
+  while( *fe == NULL );
+
+  return( *fe );
+}
+
+
+
+
+
+/****************************************************************************/
+void ringbuffer_put_read_element( struct ringbuffer_state *rs, struct freelist_element *fe )
+{
+  assert( rs != NULL );
+  assert( fe != NULL );
+
+  freelist_push( rs->fs, fe );
+
+  return;
+}
+
+
+
+
+
+/****************************************************************************/
+void ringbuffer_put_write_element( struct ringbuffer_state *rs, struct freelist_element *fe )
+{
+  assert( rs != NULL );
+  assert( fe != NULL );
+
+  queue_enqueue( rs->qs, fe );
+
+  return;
+}
+
diff --git a/liblfds/src/ringbuffer/ringbuffer_internal.h b/liblfds/src/ringbuffer/ringbuffer_internal.h
new file mode 100644
index 0000000..4ab74cd
--- /dev/null
+++ b/liblfds/src/ringbuffer/ringbuffer_internal.h
@@ -0,0 +1,24 @@
+/***** the library wide include file *****/
+#include "liblfds_internal.h"
+
+/***** defines *****/
+
+/***** structures *****/
+#pragma pack( push, ALIGN_DOUBLE_POINTER )
+
+struct ringbuffer_state
+{
+  struct queue_state
+    *qs;
+
+  struct freelist_state
+    *fs;
+};
+
+#pragma pack( pop )
+
+/***** externs *****/
+
+/***** private prototypes *****/
+void ringbuffer_internal_validate( struct ringbuffer_state *rs, struct validation_info *vi, enum data_structure_validity *queue_validity, enum data_structure_validity *freelist_validity );
+
diff --git a/liblfds/src/ringbuffer/ringbuffer_new.c b/liblfds/src/ringbuffer/ringbuffer_new.c
new file mode 100644
index 0000000..a9cea77
--- /dev/null
+++ b/liblfds/src/ringbuffer/ringbuffer_new.c
@@ -0,0 +1,47 @@
+#include "ringbuffer_internal.h"
+
+
+
+
+
+/****************************************************************************/
+int ringbuffer_new( struct ringbuffer_state **rs, atom_t number_elements, int (*user_data_init_function)(void **user_data, void *user_state), void *user_state )
+{
+  int
+    rv = 0;
+
+  assert( rs != NULL );
+  // TRD : number_elements can be any value in its range
+  // TRD : user_data_init_function can be NULL
+  // TRD : user_state can be NULL
+
+  *rs = (struct ringbuffer_state *) abstraction_aligned_malloc( sizeof(struct ringbuffer_state), ALIGN_DOUBLE_POINTER );
+
+  if( *rs != NULL )
+  {
+    freelist_new( &(*rs)->fs, number_elements, user_data_init_function, user_state );
+
+    if( (*rs)->fs != NULL )
+    {
+      queue_new( &(*rs)->qs, number_elements );
+
+      if( (*rs)->qs != NULL )
+        rv = 1;
+
+      if( (*rs)->qs == NULL )
+      {
+        abstraction_aligned_free( *rs );
+        *rs = NULL;
+      }
+    }
+
+    if( (*rs)->fs == NULL )
+    {
+      abstraction_aligned_free( *rs );
+      *rs = NULL;
+    }
+  }
+
+  return( rv );
+}
+
diff --git a/liblfds/src/ringbuffer/ringbuffer_query.c b/liblfds/src/ringbuffer/ringbuffer_query.c
new file mode 100644
index 0000000..240819a
--- /dev/null
+++ b/liblfds/src/ringbuffer/ringbuffer_query.c
@@ -0,0 +1,64 @@
+#include "ringbuffer_internal.h"
+
+
+
+
+
+/****************************************************************************/
+#pragma warning( disable : 4100 )
+
+void ringbuffer_query( struct ringbuffer_state *rs, enum ringbuffer_query_type query_type, void *query_input, void *query_output )
+{
+  assert( rs != NULL );
+  // TRD : query_type can be any value in its range
+  // TRD : query_input can be NULL
+  assert( query_output != NULL );
+
+  switch( query_type )
+  {
+    case RINGBUFFER_QUERY_VALIDATE:
+      // TRD : query_input can be NULL
+
+      ringbuffer_internal_validate( rs, (struct validation_info *) query_input, (enum data_structure_validity *) query_output, ((enum data_structure_validity *) query_output)+2 );
+    break;
+  }
+
+  return;
+}
+
+#pragma warning( default : 4100 )
+
+
+
+
+
+/****************************************************************************/
+void ringbuffer_internal_validate( struct ringbuffer_state *rs, struct validation_info *vi, enum data_structure_validity *queue_validity, enum data_structure_validity *freelist_validity )
+{
+  assert( rs != NULL );
+  // TRD : vi can be NULL
+  assert( queue_validity != NULL );
+  assert( freelist_validity != NULL );
+
+  queue_query( rs->qs, QUEUE_QUERY_VALIDATE, vi, queue_validity );
+
+  if( vi != NULL )
+  {
+    struct validation_info
+      freelist_vi;
+
+    atom_t
+      total_elements;
+
+    freelist_query( rs->fs, FREELIST_QUERY_ELEMENT_COUNT, NULL, (void *) &total_elements );
+    freelist_vi.min_elements = total_elements - vi->max_elements;
+    freelist_vi.max_elements = total_elements - vi->min_elements;
+    freelist_query( rs->fs, FREELIST_QUERY_VALIDATE, (void *) &freelist_vi, (void *) freelist_validity );
+  }
+
+  if( vi == NULL )
+    freelist_query( rs->fs, FREELIST_QUERY_VALIDATE, NULL, (void *) freelist_validity );
+
+  return;
+}
+
diff --git a/liblfds/src/slist/slist_delete.c b/liblfds/src/slist/slist_delete.c
new file mode 100644
index 0000000..7cea64c
--- /dev/null
+++ b/liblfds/src/slist/slist_delete.c
@@ -0,0 +1,79 @@
+#include "slist_internal.h"
+
+
+
+
+
+/****************************************************************************/
+void slist_delete( struct slist_state *ss )
+{
+  slist_delete_all_elements( ss );
+
+  abstraction_aligned_free( ss );
+
+  return;
+}
+
+
+
+
+
+/****************************************************************************/
+void slist_delete_element( struct slist_state *ss, struct slist_element *se )
+{
+  ALIGN(ALIGN_DOUBLE_POINTER) void
+    *volatile user_data_and_flags[2],
+    *volatile new_user_data_and_flags[2];
+
+  unsigned char
+    cas_rv = 0;
+
+  assert( ss != NULL );
+  assert( se != NULL );
+
+  user_data_and_flags[SLIST_USER_DATA] = se->user_data_and_flags[SLIST_USER_DATA];
+  user_data_and_flags[SLIST_FLAGS] = se->user_data_and_flags[SLIST_FLAGS];
+
+  do
+  {
+    new_user_data_and_flags[SLIST_USER_DATA] = user_data_and_flags[SLIST_USER_DATA];
+    new_user_data_and_flags[SLIST_FLAGS] = (void *) ((atom_t) user_data_and_flags[SLIST_FLAGS] | SLIST_FLAG_DELETED);
+  }
+  while( !((atom_t) user_data_and_flags[SLIST_FLAGS] & SLIST_FLAG_DELETED) and 0 == (cas_rv = abstraction_dcas((volatile atom_t *) se->user_data_and_flags, (atom_t *) new_user_data_and_flags, (atom_t *) user_data_and_flags)) );
+
+  if( cas_rv == 1 )
+    if( ss->user_data_delete_function != NULL )
+      ss->user_data_delete_function( (void *) user_data_and_flags[SLIST_USER_DATA], ss->user_state );
+
+  return;
+}
+
+
+
+
+
+/****************************************************************************/
+void slist_delete_all_elements( struct slist_state *ss )
+{
+  struct slist_element
+    *volatile se,
+    *volatile se_temp;
+
+  se = ss->head;
+
+  while( se != NULL )
+  {
+    // TRD : if a non-deleted element and there is a delete function, call the delete function
+    if( ss->user_data_delete_function != NULL )
+      ss->user_data_delete_function( (void *) se->user_data_and_flags[SLIST_USER_DATA], ss->user_state );
+
+    se_temp = se;
+    se = se->next;
+    abstraction_aligned_free( (void *) se_temp );
+  }
+
+  slist_internal_init_slist( ss, ss->user_data_delete_function, ss->user_state );
+
+  return;
+}
+
diff --git a/liblfds/src/slist/slist_get_and_set.c b/liblfds/src/slist/slist_get_and_set.c
new file mode 100644
index 0000000..2d6b54e
--- /dev/null
+++ b/liblfds/src/slist/slist_get_and_set.c
@@ -0,0 +1,124 @@
+#include "slist_internal.h"
+
+
+
+
+
+/****************************************************************************/
+int slist_get_user_data_from_element( struct slist_element *se, void **user_data )
+{
+  int
+    rv = 1;
+
+  assert( se != NULL );
+  assert( user_data != NULL );
+
+  *user_data = (void *) se->user_data_and_flags[SLIST_USER_DATA];
+
+  if( (atom_t) se->user_data_and_flags[SLIST_FLAGS] & SLIST_FLAG_DELETED )
+    rv = 0;
+
+  return( rv );
+}
+
+
+
+
+
+/****************************************************************************/
+int slist_set_user_data_in_element( struct slist_element *se, void *user_data )
+{
+  ALIGN(ALIGN_DOUBLE_POINTER) volatile void
+    *user_data_and_flags[2],
+    *new_user_data_and_flags[2];
+
+  int
+    rv = 1;
+
+  assert( se != NULL );
+  // TRD : user_data can be NULL
+
+  user_data_and_flags[SLIST_USER_DATA] = se->user_data_and_flags[SLIST_USER_DATA];
+  user_data_and_flags[SLIST_FLAGS] = se->user_data_and_flags[SLIST_FLAGS];
+
+  new_user_data_and_flags[SLIST_USER_DATA] = user_data;
+
+  do
+  {
+    new_user_data_and_flags[SLIST_FLAGS] = user_data_and_flags[SLIST_FLAGS];
+  }
+  while( !((atom_t) user_data_and_flags[SLIST_FLAGS] & SLIST_FLAG_DELETED) and 0 == abstraction_dcas((volatile atom_t *) se->user_data_and_flags, (atom_t *) new_user_data_and_flags, (atom_t *) user_data_and_flags) );
+
+  if( (atom_t) user_data_and_flags[SLIST_FLAGS] & SLIST_FLAG_DELETED )
+    rv = 0;
+
+  return( rv );
+}
+
+
+
+
+
+/****************************************************************************/
+struct slist_element *slist_get_head( struct slist_state *ss, struct slist_element **se )
+{
+  assert( ss != NULL );
+  assert( se != NULL );
+
+  *se = (struct slist_element *) ss->head;
+
+  slist_internal_move_to_first_undeleted_element( se );
+
+  return( *se );
+}
+
+
+
+
+
+/****************************************************************************/
+struct slist_element *slist_get_next( struct slist_element *se, struct slist_element **next_se )
+{
+  assert( se != NULL );
+  assert( next_se != NULL );
+
+  *next_se = (struct slist_element *) se->next;
+
+  slist_internal_move_to_first_undeleted_element( next_se );
+
+  return( *next_se );
+}
+
+
+
+
+
+/****************************************************************************/
+struct slist_element *slist_get_head_and_then_next( struct slist_state *ss, struct slist_element **se )
+{
+  assert( ss != NULL );
+  assert( se != NULL );
+
+  if( *se == NULL )
+    slist_get_head( ss, se );
+  else
+    slist_get_next( *se, se );
+
+  return( *se );
+}
+
+
+
+
+
+/****************************************************************************/
+void slist_internal_move_to_first_undeleted_element( struct slist_element **se )
+{
+  assert( se != NULL );
+
+  while( *se != NULL and (atom_t) (*se)->user_data_and_flags[SLIST_FLAGS] & SLIST_FLAG_DELETED )
+    (*se) = (struct slist_element *) (*se)->next;
+
+  return;
+}
+
diff --git a/liblfds/src/slist/slist_internal.h b/liblfds/src/slist/slist_internal.h
new file mode 100644
index 0000000..6ffa4ed
--- /dev/null
+++ b/liblfds/src/slist/slist_internal.h
@@ -0,0 +1,55 @@
+/***** the library wide include file *****/
+#include "liblfds_internal.h"
+
+/***** defines *****/
+#define SLIST_USER_DATA  0
+#define SLIST_FLAGS      1
+
+#define SLIST_NO_FLAGS      0x0
+#define SLIST_FLAG_DELETED  0x1
+
+/***** structures *****/
+#pragma pack( push, ALIGN_SINGLE_POINTER )
+
+struct slist_state
+{
+  struct slist_element
+    *volatile head;
+
+  void
+    (*user_data_delete_function)( void *user_data, void *user_state ),
+    *user_state;
+};
+
+#pragma pack( pop )
+
+#pragma pack( push, ALIGN_DOUBLE_POINTER )
+
+/* TRD : this pragma pack doesn't seem to work under Windows
+         if the structure members are the correct way round
+         (next first), then user_data_and_flags ends up on
+         a single pointer boundary and DCAS crashes
+
+         accordingly, I've moved user_data_and_flags first
+*/
+
+struct slist_element
+{
+  void
+    *volatile user_data_and_flags[2];
+
+  // TRD : requires volatile as is target of CAS
+  struct slist_element
+    *volatile next;
+};
+
+#pragma pack( pop )
+
+/***** private prototypes *****/
+void slist_internal_init_slist( struct slist_state *ss, void (*user_data_delete_function)(void *user_data, void *user_state), void *user_state );
+
+void slist_internal_link_element_to_head( struct slist_state *slist_state, struct slist_element *volatile se );
+void slist_internal_link_element_after_element( struct slist_element *volatile slist_in_list_element, struct slist_element *volatile se );
+
+void slist_internal_move_to_first_undeleted_element( struct slist_element **se );
+
diff --git a/liblfds/src/slist/slist_link.c b/liblfds/src/slist/slist_link.c
new file mode 100644
index 0000000..b60725e
--- /dev/null
+++ b/liblfds/src/slist/slist_link.c
@@ -0,0 +1,53 @@
+#include "slist_internal.h"
+
+
+
+
+
+/****************************************************************************/
+void slist_internal_link_element_to_head( struct slist_state *ss, struct slist_element *volatile se )
+{
+  ALIGN(ALIGN_SINGLE_POINTER) struct slist_element
+    *se_next;
+
+  assert( ss != NULL );
+  assert( se != NULL );
+
+  se_next = ss->head;
+
+  do
+  {
+    se->next = se_next;
+  }
+  while( se->next != (se_next = (struct slist_element *) abstraction_cas((volatile atom_t *) &ss->head, (atom_t) se, (atom_t) se->next)) );
+
+  return;
+}
+
+
+
+
+
+/****************************************************************************/
+void slist_internal_link_element_after_element( struct slist_element *volatile slist_in_list_element, struct slist_element *volatile se )
+{
+  ALIGN(ALIGN_SINGLE_POINTER) struct slist_element
+    *se_prev,
+    *se_next;
+
+  assert( slist_in_list_element != NULL );
+  assert( se != NULL );
+
+  se_prev = (struct slist_element *) slist_in_list_element;
+
+  se_next = se_prev->next;
+
+  do
+  {
+    se->next = se_next;
+  }
+  while( se->next != (se_next = (struct slist_element *) abstraction_cas((volatile atom_t *) &se_prev->next, (atom_t) se, (atom_t) se->next)) );
+
+  return;
+}
+
diff --git a/liblfds/src/slist/slist_new.c b/liblfds/src/slist/slist_new.c
new file mode 100644
index 0000000..440c4c8
--- /dev/null
+++ b/liblfds/src/slist/slist_new.c
@@ -0,0 +1,97 @@
+#include "slist_internal.h"
+
+
+
+
+
+/****************************************************************************/
+int slist_new( struct slist_state **ss, void (*user_data_delete_function)(void *user_data, void *user_state), void *user_state )
+{
+  int
+    rv = 0;
+
+  assert( ss != NULL );
+  // TRD : user_data_delete_function can be NULL
+  // TRD : user_state can be NULL
+
+  *ss = (struct slist_state *) abstraction_aligned_malloc( sizeof(struct slist_state), ALIGN_SINGLE_POINTER );
+
+  if( *ss != NULL )
+  {
+    slist_internal_init_slist( *ss, user_data_delete_function, user_state );
+    rv = 1;
+  }
+
+  return( rv );
+}
+
+
+
+
+
+/****************************************************************************/
+void slist_internal_init_slist( struct slist_state *ss, void (*user_data_delete_function)(void *user_data, void *user_state), void *user_state )
+{
+  assert( ss != NULL );
+  // TRD : user_data_delete_function can be NULL
+  // TRD : user_state can be NULL
+
+  ss->head = NULL;
+  ss->user_data_delete_function = user_data_delete_function;
+  ss->user_state = user_state;
+
+  return;
+}
+
+
+
+
+
+/****************************************************************************/
+struct slist_element *slist_new_head( struct slist_state *ss, void *user_data )
+{
+  ALIGN(ALIGN_SINGLE_POINTER) struct slist_element
+    *volatile se;
+
+  assert( ss != NULL );
+  // TRD : user_data can be NULL
+
+  se = (struct slist_element *) abstraction_aligned_malloc( sizeof(struct slist_element), ALIGN_DOUBLE_POINTER );
+
+  if( se != NULL )
+  {
+    se->user_data_and_flags[SLIST_USER_DATA] = user_data;
+    se->user_data_and_flags[SLIST_FLAGS] = SLIST_NO_FLAGS;
+
+    slist_internal_link_element_to_head( ss, se );
+  }
+
+  return( (struct slist_element *) se );
+}
+
+
+
+
+
+/****************************************************************************/
+struct slist_element *slist_new_next( struct slist_element *se, void *user_data )
+{
+  ALIGN(ALIGN_SINGLE_POINTER) struct slist_element
+    *volatile se_next;
+
+  assert( se != NULL );
+  // TRD : user_data can be NULL
+
+  se_next = (struct slist_element *) abstraction_aligned_malloc( sizeof(struct slist_element), ALIGN_DOUBLE_POINTER );
+
+  if( se_next != NULL )
+  {
+    se_next->user_data_and_flags[SLIST_USER_DATA] = user_data;
+    se_next->user_data_and_flags[SLIST_FLAGS] = SLIST_NO_FLAGS;
+
+    slist_internal_link_element_after_element( se, se_next );
+  }
+
+  return( (struct slist_element *) se_next );
+}
+
diff --git a/liblfds/src/stack/stack_delete.c b/liblfds/src/stack/stack_delete.c
new file mode 100644
index 0000000..92dbc96
--- /dev/null
+++ b/liblfds/src/stack/stack_delete.c
@@ -0,0 +1,67 @@
+#include "stack_internal.h"
+
+
+
+
+
+/****************************************************************************/
+void stack_delete( struct stack_state *ss, void (*user_data_delete_function)(void *user_data, void *user_state), void *user_state )
+{
+  void
+    *user_data;
+
+  assert( ss != NULL );
+  // TRD : user_data_delete_function can be NULL
+  // TRD : user_state can be NULL
+
+  while( stack_pop(ss, &user_data) )
+    if( user_data_delete_function != NULL )
+      user_data_delete_function( user_data, user_state );
+
+  freelist_delete( ss->fs, stack_internal_freelist_delete_function, NULL );
+
+  abstraction_aligned_free( ss );
+
+  return;
+}
+
+
+
+
+
+/****************************************************************************/
+void stack_clear( struct stack_state *ss, void (*user_data_clear_function)(void *user_data, void *user_state), void *user_state )
+{
+  void
+    *user_data;
+
+  assert( ss != NULL );
+  // TRD : user_data_clear_function can be NULL
+  // TRD : user_state can be NULL
+
+  while( stack_pop(ss, &user_data) )
+    if( user_data_clear_function != NULL )
+      user_data_clear_function( user_data, user_state );
+
+  return;
+}
+
+
+
+
+
+/****************************************************************************/
+#pragma warning( disable : 4100 )
+
+void stack_internal_freelist_delete_function( void *user_data, void *user_state )
+{
+  assert( user_data != NULL );
+  assert( user_state == NULL );
+
+  abstraction_aligned_free( user_data );
+
+  return;
+}
+
+#pragma warning( default : 4100 )
+
diff --git a/liblfds/src/stack/stack_internal.h b/liblfds/src/stack/stack_internal.h
new file mode 100644
index 0000000..4602020
--- /dev/null
+++ b/liblfds/src/stack/stack_internal.h
@@ -0,0 +1,50 @@
+/***** the library wide include file *****/
+#include "liblfds_internal.h"
+
+/***** pragmas *****/
+
+/***** defines *****/
+#define STACK_POINTER 0
+#define STACK_COUNTER 1
+#define STACK_PAC_SIZE 2
+
+/***** structures *****/
+#pragma pack( push, ALIGN_DOUBLE_POINTER )
+
+struct stack_state
+{
+  // TRD : must come first for alignment
+  struct stack_element
+    *volatile top[STACK_PAC_SIZE];
+
+  atom_t
+    aba_counter;
+
+  struct freelist_state
+    *fs;
+};
+
+struct stack_element
+{
+  struct stack_element
+    *next[STACK_PAC_SIZE];
+
+  struct freelist_element
+    *fe;
+
+  void
+    *user_data;
+};
+
+#pragma pack( pop )
+
+/***** private prototypes *****/
+int stack_internal_freelist_init_function( void **user_data, void *user_state );
+void stack_internal_freelist_delete_function( void *user_data, void *user_state );
+
+void stack_internal_new_element_from_freelist( struct stack_state *ss, struct stack_element *se[STACK_PAC_SIZE], void *user_data );
+void stack_internal_new_element( struct stack_state *ss, struct stack_element *se[STACK_PAC_SIZE], void *user_data );
+void stack_internal_init_element( struct stack_state *ss, struct stack_element *se[STACK_PAC_SIZE], struct freelist_element *fe, void *user_data );
+
+void stack_internal_push( struct stack_state *ss, struct stack_element *se[STACK_PAC_SIZE] );
+
diff --git a/liblfds/src/stack/stack_new.c b/liblfds/src/stack/stack_new.c
new file mode 100644
index 0000000..24572f6
--- /dev/null
+++ b/liblfds/src/stack/stack_new.c
@@ -0,0 +1,139 @@
+#include "stack_internal.h"
+
+
+
+
+
+/****************************************************************************/
+int stack_new( struct stack_state **ss, atom_t number_elements )
+{
+  int
+    rv = 0;
+
+  assert( ss != NULL );
+  // TRD : number_elements can be any value in its range
+
+  *ss = (struct stack_state *) abstraction_aligned_malloc( sizeof(struct stack_state), ALIGN_DOUBLE_POINTER );
+
+  if( *ss != NULL )
+  {
+    // TRD : the size of the freelist is the size of the stack
+    freelist_new( &(*ss)->fs, number_elements, stack_internal_freelist_init_function, NULL );
+
+    if( (*ss)->fs == NULL )
+    {
+      abstraction_aligned_free( *ss );
+      *ss = NULL;
+    }
+
+    if( (*ss)->fs != NULL )
+    {
+      (*ss)->top[STACK_POINTER] = NULL;
+      (*ss)->top[STACK_COUNTER] = 0;
+      (*ss)->aba_counter = 0;
+      rv = 1;
+    }
+  }
+
+  return( rv );
+}
+
+
+
+
+
+/****************************************************************************/
+#pragma warning( disable : 4100 )
+
+int stack_internal_freelist_init_function( void **user_data, void *user_state )
+{
+  int
+    rv = 0;
+
+  assert( user_data != NULL );
+  assert( user_state == NULL );
+
+  *user_data = abstraction_aligned_malloc( sizeof(struct stack_element), ALIGN_DOUBLE_POINTER );
+
+  if( *user_data != NULL )
+    rv = 1;
+
+  return( rv );
+}
+
+#pragma warning( default : 4100 )
+
+
+
+
+
+/****************************************************************************/
+void stack_internal_new_element_from_freelist( struct stack_state *ss, struct stack_element *se[STACK_PAC_SIZE], void *user_data )
+{
+  struct freelist_element
+    *fe;
+
+  assert( ss != NULL );
+  assert( se != NULL );
+  // TRD : user_data can be any value in its range
+
+  freelist_pop( ss->fs, &fe );
+
+  if( fe == NULL )
+    se[STACK_POINTER] = NULL;
+
+  if( fe != NULL )
+    stack_internal_init_element( ss, se, fe, user_data );
+
+  return;
+}
+
+
+
+
+
+/****************************************************************************/
+void stack_internal_new_element( struct stack_state *ss, struct stack_element *se[STACK_PAC_SIZE], void *user_data )
+{
+  struct freelist_element
+    *fe;
+
+  assert( ss != NULL );
+  assert( se != NULL );
+  // TRD : user_data can be any value in its range
+
+  freelist_guaranteed_pop( ss->fs, &fe );
+
+  if( fe == NULL )
+    se[STACK_POINTER] = NULL;
+
+  if( fe != NULL )
+    stack_internal_init_element( ss, se, fe, user_data );
+
+  return;
+}
+
+
+
+
+
+/****************************************************************************/
+void stack_internal_init_element( struct stack_state *ss, struct stack_element *se[STACK_PAC_SIZE], struct freelist_element *fe, void *user_data )
+{
+  assert( ss != NULL );
+  assert( se != NULL );
+  assert( fe != NULL );
+  // TRD : user_data can be any value in its range
+
+  freelist_get_user_data_from_element( fe, (void **) &se[STACK_POINTER] );
+
+  se[STACK_COUNTER] = (struct stack_element *) abstraction_increment( (atom_t *) &ss->aba_counter );
+
+  se[STACK_POINTER]->next[STACK_POINTER] = NULL;
+  se[STACK_POINTER]->next[STACK_COUNTER] = 0;
+  se[STACK_POINTER]->fe = fe;
+  se[STACK_POINTER]->user_data = user_data;
+
+  return;
+}
+
diff --git a/liblfds/src/stack/stack_push_pop.c b/liblfds/src/stack/stack_push_pop.c
new file mode 100644
index 0000000..6fb789e
--- /dev/null
+++ b/liblfds/src/stack/stack_push_pop.c
@@ -0,0 +1,110 @@
+#include "stack_internal.h"
+
+
+
+
+
+/****************************************************************************/
+int stack_push( struct stack_state *ss, void *user_data )
+{
+  ALIGN(ALIGN_DOUBLE_POINTER) struct stack_element
+    *se[STACK_PAC_SIZE];
+
+  assert( ss != NULL );
+  // TRD : user_data can be NULL
+
+  stack_internal_new_element_from_freelist( ss, se, user_data );
+
+  if( se[STACK_POINTER] == NULL )
+    return( 0 );
+
+  stack_internal_push( ss, se );
+
+  return( 1 );
+}
+
+
+
+
+
+/****************************************************************************/
+int stack_guaranteed_push( struct stack_state *ss, void *user_data )
+{
+  ALIGN(ALIGN_DOUBLE_POINTER) struct stack_element
+    *se[STACK_PAC_SIZE];
+
+  assert( ss != NULL );
+  // TRD : user_data can be NULL
+
+  /* TRD : this function allocated a new freelist element and uses that
+           to push onto the stack, guaranteeing success (unless malloc()
+           fails of course)
+  */
+
+  stack_internal_new_element( ss, se, user_data );
+
+  // TRD : malloc failed
+  if( se[STACK_POINTER] == NULL )
+    return( 0 );
+
+  stack_internal_push( ss, se );
+
+  return( 1 );
+}
+
+
+
+
+
+/****************************************************************************/
+void stack_internal_push( struct stack_state *ss, struct stack_element *se[STACK_PAC_SIZE] )
+{
+  ALIGN(ALIGN_DOUBLE_POINTER) struct stack_element
+    *original_se_next[STACK_PAC_SIZE];
+
+  assert( ss != NULL );
+  assert( se != NULL );
+
+  original_se_next[STACK_POINTER] = ss->top[STACK_POINTER];
+  original_se_next[STACK_COUNTER] = ss->top[STACK_COUNTER];
+
+  do
+  {
+    se[STACK_POINTER]->next[STACK_POINTER] = original_se_next[STACK_POINTER];
+    se[STACK_POINTER]->next[STACK_COUNTER] = original_se_next[STACK_COUNTER];
+  }
+  while( 0 == abstraction_dcas((volatile atom_t *) ss->top, (atom_t *) se, (atom_t *) original_se_next) );
+
+  return;
+}
+
+
+
+
+
+/****************************************************************************/
+int stack_pop( struct stack_state *ss, void **user_data )
+{
+  ALIGN(ALIGN_DOUBLE_POINTER) struct stack_element
+    *se[STACK_PAC_SIZE];
+
+  assert( ss != NULL );
+  assert( user_data != NULL );
+
+  se[STACK_COUNTER] = ss->top[STACK_COUNTER];
+  se[STACK_POINTER] = ss->top[STACK_POINTER];
+
+  do
+  {
+    if( se[STACK_POINTER] == NULL )
+      return( 0 );
+  }
+  while( 0 == abstraction_dcas((volatile atom_t *) ss->top, (atom_t *) se[STACK_POINTER]->next, (atom_t *) se) );
+
+  *user_data = se[STACK_POINTER]->user_data;
+
+  freelist_push( ss->fs, se[STACK_POINTER]->fe );
+
+  return( 1 );
+}
+
diff --git a/liblfds/src/stack/stack_query.c b/liblfds/src/stack/stack_query.c
new file mode 100644
index 0000000..c890ae1
--- /dev/null
+++ b/liblfds/src/stack/stack_query.c
@@ -0,0 +1,30 @@
+#include "stack_internal.h"
+
+
+
+
+
+/****************************************************************************/
+#pragma warning( disable : 4100 )
+
+void stack_query( struct stack_state *ss, enum stack_query_type query_type, void *query_input, void *query_output )
+{
+  assert( ss != NULL );
+  // TRD : query_type can be any value in its range
+  // TRD : query_iput can be NULL
+  assert( query_output != NULL );
+
+  switch( query_type )
+  {
+    case STACK_QUERY_ELEMENT_COUNT:
+      assert( query_input == NULL );
+
+      freelist_query( ss->fs, FREELIST_QUERY_ELEMENT_COUNT, NULL, query_output );
+    break;
+  }
+
+  return;
+}
+
+#pragma warning( default : 4100 )
+
diff --git a/liblfds/test/building.txt b/liblfds/test/building.txt
new file mode 100644
index 0000000..4f8c9bb
--- /dev/null
+++ b/liblfds/test/building.txt
@@ -0,0 +1,25 @@
+building test
+=============
+
+Windows (user-mode)
+===================
+1. Use Microsoft Visual Studio 2008 or Visual C++ 2008 Express Edition
+   to load "test.sln".
+
+2. Use Microsoft Windows SDK and GNUmake to run makefile.windows (obviously
+   you'll need to have run the appropriate vcvars*.bat first; you can build
+   for both IA64, 64-bit and 32-bit - just run the correct vcvars batch file).
+
+   Targets are "rel", "dbg" and "clean".  You need to clean between switching
+   targets.
+
+Windows (kernel)
+================
+No build supported, since this is a command line utility.
+
+Linux
+=====
+Use GNUmake to run "makefile.linux".  Targets are "rel", "dbg" and
+"clean".  You need to clean between switching targets.
+
+
diff --git a/liblfds/test/makefile.linux b/liblfds/test/makefile.linux
new file mode 100644
index 0000000..ba45cdc
--- /dev/null
+++ b/liblfds/test/makefile.linux
@@ -0,0 +1,81 @@
+##### paths #####
+BINDIR = bin
+INCDIR = ../inc
+LIBDIR = ../bin
+OBJDIR = obj
+SRCDIR = src
+
+##### misc #####
+QUIETLY = 1>nul 2>nul
+
+##### sources, objects and libraries #####
+BINNAME = test
+BINARY  = $(BINDIR)/$(BINNAME)
+SRCDIRS = .
+SOURCES = abstraction_cpu_count.c test_abstraction.c abstraction_thread_start.c abstraction_thread_wait.c benchmark_freelist.c benchmark_queue.c benchmark_ringbuffer.c benchmark_stack.c test_freelist.c main.c misc.c test_queue.c test_ringbuffer.c test_slist.c test_stack.c
+OBJECTS = $(patsubst %.c,$(OBJDIR)/%.o,$(notdir $(SOURCES)))
+SYSLIBS = -lpthread -lc -lm
+USRLIBS = -llfds
+
+##### CPU variants #####
+GCCARCH = $(shell uname -m)
+
+ifeq ($(GCCARCH),x86_64)
+  GCCARCH = core2
+endif
+
+ifeq ($(findstring arm,$(GCCARCH)),arm)
+  GCCARCH = armv6k
+endif
+
+##### tools #####
+MAKE    = make
+MFLAGS  = 
+
+DG      = gcc
+DGFLAGS = -MM -std=c99 -I"$(SRCDIR)" -I"$(INCDIR)" 
+
+CC      = gcc
+CFBASE  = -Wall -Wno-unknown-pragmas -std=c99 -march=$(GCCARCH) -c -I"$(SRCDIR)" -I"$(INCDIR)"
+CFREL   = -O2 -Wno-strict-aliasing
+CFDBG   = -O0 -g
+
+LD      = gcc
+LFBASE  = -L"$(LIBDIR)"
+LFREL   = -O2 -s
+LFDBG   = -O0 -g
+
+##### variants #####
+CFLAGS  = $(CFBASE) $(CFDBG)
+LFLAGS  = $(LFBASE) $(LFDBG)
+
+ifeq ($(MAKECMDGOALS),rel)
+  CFLAGS  = $(CFBASE) $(CFREL)
+  LFLAGS  = $(LFBASE) $(LFREL)
+endif
+
+##### search paths #####
+vpath %.c $(patsubst %,$(SRCDIR)/%:,$(SRCDIRS))
+
+##### implicit rules #####
+$(OBJDIR)/%.o : %.c
+	$(DG) $(DGFLAGS) $< >$(OBJDIR)/$*.d
+	$(CC) $(CFLAGS) -o $@ $<
+
+##### explicit rules #####
+$(BINARY) : $(OBJECTS)
+	$(LD) -o $(BINARY) $(LFLAGS) $(OBJECTS) $(USRLIBS) $(SYSLIBS)
+	chmod +x $(BINARY)
+
+##### phony #####
+.PHONY : clean rel dbg
+
+clean : 
+	@rm -f $(BINDIR)/$(BINNAME) $(OBJDIR)/*.o $(OBJDIR)/*.d
+
+rel : $(BINARY)
+dbg : $(BINARY)
+
+##### dependencies #####
+-include $(DEPENDS)
+
diff --git a/liblfds/test/makefile.windows b/liblfds/test/makefile.windows
new file mode 100644
index 0000000..ef134fc
--- /dev/null
+++ b/liblfds/test/makefile.windows
@@ -0,0 +1,64 @@
+##### paths #####
+BINDIR = bin
+INCDIR = ../inc
+LIBDIR = ../bin
+OBJDIR = obj
+SRCDIR = src
+
+##### misc #####
+QUIETLY = 1>nul 2>nul
+
+##### sources, objects and libraries #####
+BINNAME = test
+BINARY  = $(BINDIR)\$(BINNAME).exe
+SRCDIRS = .
+SOURCES = abstraction_cpu_count.c test_abstraction.c abstraction_thread_start.c abstraction_thread_wait.c benchmark_freelist.c benchmark_queue.c benchmark_ringbuffer.c benchmark_stack.c test_freelist.c main.c misc.c test_queue.c test_ringbuffer.c test_slist.c test_stack.c
+OBJECTS = $(patsubst %.c,$(OBJDIR)/%.obj,$(notdir $(SOURCES)))
+SYSLIBS = kernel32.lib
+USRLIBS = liblfds.lib
+
+##### tools #####
+MAKE    = make
+MFLAGS  = 
+
+CC      = cl
+CFBASE  = /nologo /W4 /WX /c "-I$(SRCDIR)" "-I$(INCLUDE)" "-I$(INCDIR)" "/Fd$(BINDIR)\$(BINNAME).pdb" /D UNICODE /D _UNICODE /DWIN32_LEAN_AND_MEAN /D_CRT_SECURE_NO_WARNINGS
+CFREL   = /Ox /DNDEBUG /MT
+CFDBG   = /Od /Gm /Zi /D_DEBUG /MTd
+
+LD      = link
+LFBASE  = "/libpath:$(LIB)" "/libpath:$(LIBDIR)" /nologo /subsystem:console /nodefaultlib /nxcompat /wx
+LFREL   = /incremental:no
+LFDBG   = /debug "/pdb:$(BINDIR)\$(BINNAME).pdb"
+
+##### variants #####
+CFLAGS  = $(CFBASE) $(CFDBG)
+LFLAGS  = $(LFBASE) $(LFDBG)
+CLIB    = libcmtd.lib
+
+ifeq ($(MAKECMDGOALS),rel)
+  CFLAGS  = $(CFBASE) $(CFREL)
+  LFLAGS  = $(LFBASE) $(LFREL)
+  CLIB    = libcmt.lib
+endif
+
+##### search paths #####
+vpath %.c $(patsubst %,$(SRCDIR)/%;,$(SRCDIRS))
+
+##### implicit rules #####
+$(OBJDIR)/%.obj : %.c
+	$(CC) $(CFLAGS) "/Fo$@" $<
+
+##### explicit rules #####
+$(BINARY) : $(OBJECTS)
+	$(LD) $(LFLAGS) $(CLIB) $(SYSLIBS) $(USRLIBS) $(OBJECTS) /out:$(BINARY)
+
+##### phony #####
+.PHONY : clean rel dbg
+
+clean : 
+	@erase /Q $(OBJDIR)\*.obj $(BINDIR)\$(BINNAME).* $(QUIETLY)
+
+rel : $(BINARY)
+dbg : $(BINARY)
+
diff --git a/liblfds/test/src/abstraction.h b/liblfds/test/src/abstraction.h
new file mode 100644
index 0000000..e601f36
--- /dev/null
+++ b/liblfds/test/src/abstraction.h
@@ -0,0 +1,50 @@
+/***** defines *****/
+#if (defined _WIN32 && defined _MSC_VER && !defined WIN_KERNEL_BUILD)
+  /* TRD : any Windows (user-mode) on any CPU with the Microsoft C compiler
+
+           _WIN32             indicates 64-bit or 32-bit Windows
+           _MSC_VER           indicates Microsoft C compiler
+           !WIN_KERNEL_BUILD  indicates Windows user-mode
+  */
+
+  #include <windows.h>
+  typedef HANDLE              thread_state_t;
+  typedef DWORD               thread_return_t;
+  #define CALLING_CONVENTION  WINAPI
+#endif
+
+#if (defined _WIN32 && defined _MSC_VER && defined WIN_KERNEL_BUILD)
+  /* TRD : any Windows (kernel-mode) on any CPU with the Microsoft C compiler
+
+           _WIN32            indicates 64-bit or 32-bit Windows
+           _MSC_VER          indicates Microsoft C compiler
+           WIN_KERNEL_BUILD  indicates Windows kernel
+  */
+
+  #include <wdm.h>
+  typedef HANDLE              thread_state_t;
+  typedef VOID                thread_return_t;
+  #define CALLING_CONVENTION  
+#endif
+
+#if (defined __unix__ && __GNUC__)
+  /* TRD : any UNIX on any CPU with GCC
+
+           __unix__   indicates Solaris, Linux, HPUX, etc
+           __GNUC__   indicates GCC
+  */
+
+  #include <unistd.h>
+  #include <pthread.h>
+  typedef pthread_t           thread_state_t;
+  typedef void *              thread_return_t;
+  #define CALLING_CONVENTION  
+#endif
+
+typedef thread_return_t (CALLING_CONVENTION *thread_function_t)( void *thread_user_state );
+
+/***** public prototypes *****/
+unsigned int abstraction_cpu_count( void );
+int abstraction_thread_start( thread_state_t *thread_state, unsigned int cpu, thread_function_t thread_function, void *thread_user_state );
+void abstraction_thread_wait( thread_state_t thread_state );
+
diff --git a/liblfds/test/src/abstraction_cpu_count.c b/liblfds/test/src/abstraction_cpu_count.c
new file mode 100644
index 0000000..42c3e13
--- /dev/null
+++ b/liblfds/test/src/abstraction_cpu_count.c
@@ -0,0 +1,81 @@
+#include "internal.h"
+
+
+
+
+
+/****************************************************************************/
+#if (defined _WIN32 && defined _MSC_VER && !defined WIN_KERNEL_BUILD)
+
+  /* TRD : any Windows (user-mode) on any CPU with the Microsoft C compiler
+
+           _WIN32             indicates 64-bit or 32-bit Windows
+           _MSC_VER           indicates Microsoft C compiler
+           !WIN_KERNEL_BUILD  indicates Windows user-mode
+  */
+
+  unsigned int abstraction_cpu_count()
+  {
+    SYSTEM_INFO
+      si;
+
+    GetNativeSystemInfo( &si );
+
+    return( (unsigned int) si.dwNumberOfProcessors );
+  }
+
+#endif
+
+
+
+
+
+/****************************************************************************/
+#if (defined _WIN32 && defined _MSC_VER && defined WIN_KERNEL_BUILD)
+
+  /* TRD : any Windows on any CPU with the Microsoft C compiler
+
+           _WIN32            indicates 64-bit or 32-bit Windows
+           _MSC_VER          indicates Microsoft C compiler
+           WIN_KERNEL_BUILD  indicates Windows kernel
+  */
+
+  unsigned int abstraction_cpu_count()
+  {
+    unsigned int
+      active_processor_count;
+
+    active_processor_count = KeQueryActiveProcessorCount( NULL );
+
+    return( active_processor_count );
+  }
+
+#endif
+
+
+
+
+
+/****************************************************************************/
+#if (defined __linux__ && __GNUC__)
+
+  /* TRD : Linux on any CPU with GCC
+
+           this function I believe is Linux specific and varies by UNIX flavour
+
+           __linux__  indicates Linux
+           __GNUC__   indicates GCC
+  */
+
+  unsigned int abstraction_cpu_count()
+  {
+    long int
+      cpu_count;
+
+    cpu_count = sysconf( _SC_NPROCESSORS_ONLN );
+
+    return( (unsigned int) cpu_count );
+  }
+
+#endif
+
diff --git a/liblfds/test/src/abstraction_thread_start.c b/liblfds/test/src/abstraction_thread_start.c
new file mode 100644
index 0000000..cdba0ce
--- /dev/null
+++ b/liblfds/test/src/abstraction_thread_start.c
@@ -0,0 +1,127 @@
+#include "internal.h"
+
+
+
+
+
+/****************************************************************************/
+#if (defined _WIN32 && defined _MSC_VER && !defined WIN_KERNEL_BUILD)
+
+  /* TRD : any Windows (user-mode) on any CPU with the Microsoft C compiler
+
+           _WIN32             indicates 64-bit or 32-bit Windows
+           _MSC_VER           indicates Microsoft C compiler
+           !WIN_KERNEL_BUILD  indicates Windows user-mode
+  */
+
+  int abstraction_thread_start( thread_state_t *thread_state, unsigned int cpu, thread_function_t thread_function, void *thread_user_state )
+  {
+    int
+      rv = 0;
+
+    DWORD
+      thread_id;
+
+    DWORD_PTR
+      affinity_mask,
+      result;
+
+    assert( thread_state != NULL );
+    // TRD : cpu can be any value in its range
+    assert( thread_function != NULL );
+    // TRD : thread_user_state can be NULL
+
+    affinity_mask = (DWORD_PTR) (1 << cpu);
+
+    *thread_state = CreateThread( NULL, 0, thread_function, thread_user_state, NO_FLAGS, &thread_id );
+
+    result = SetThreadAffinityMask( *thread_state, affinity_mask );
+
+    if( *thread_state != NULL and result != 0 )
+      rv = 1;
+
+    return( rv );
+  }
+
+#endif
+
+
+
+
+
+/****************************************************************************/
+#if (defined _WIN32 && defined _MSC_VER && defined WIN_KERNEL_BUILD)
+
+  /* TRD : any Windows on any CPU with the Microsoft C compiler
+
+           _WIN32            indicates 64-bit or 32-bit Windows
+           _MSC_VER          indicates Microsoft C compiler
+           WIN_KERNEL_BUILD  indicates Windows kernel
+  */
+
+  int abstraction_thread_start( thread_state_t *thread_state, unsigned int cpu, thread_function_t thread_function, void *thread_user_state )
+  {
+    int
+      rv = 0;
+
+    KAFFINITY
+      affinity_mask
+
+    NTSTATUS
+      nts_create,
+      nts_affinity;
+
+    assert( thread_state != NULL );
+    // TRD : cpu can be any value in its range
+    assert( thread_function != NULL );
+    // TRD : thread_user_state can be NULL
+
+    affinity_mask = 1 << cpu;
+
+    nts_create = PsCreateSystemThread( thread_state, THREAD_ALL_ACCESS, NULL, NULL, NULL, thread_function, thread_user_state );
+
+    nts_affinity = ZwSetInformationThread( thread_state, ThreadAffinityMask, &affinity_mask, sizeof(KAFFINITY) );
+
+    if( nts_create == STATUS_SUCCESS and nts_affinity == STATUS_SUCCESS )
+      rv = 1;
+
+    return( rv );
+  }
+
+#endif
+
+
+
+
+
+/****************************************************************************/
+#if (defined __unix__)
+
+  /* TRD : any UNIX on any CPU with any compiler
+
+           I assumed pthreads is available on any UNIX.
+
+           __unix__   indicates Solaris, Linux, HPUX, etc
+  */
+
+  int abstraction_thread_start( thread_state_t *thread_state, unsigned int cpu, thread_function_t thread_function, void *thread_user_state )
+  {
+    int
+      rv = 0,
+      rv_create;
+
+    assert( thread_state != NULL );
+    // TRD : cpu can be any value in its range
+    assert( thread_function != NULL );
+    // TRD : thread_user_state can be NULL
+
+    rv_create = pthread_create( thread_state, NULL, thread_function, thread_user_state );
+
+    if( rv_create == 0 )
+      rv = 1;
+
+    return( rv );
+  }
+
+#endif
+
diff --git a/liblfds/test/src/abstraction_thread_wait.c b/liblfds/test/src/abstraction_thread_wait.c
new file mode 100644
index 0000000..ced5a5e
--- /dev/null
+++ b/liblfds/test/src/abstraction_thread_wait.c
@@ -0,0 +1,71 @@
+#include "internal.h"
+
+
+
+
+
+/****************************************************************************/
+#if (defined _WIN32 && defined _MSC_VER && !defined WIN_KERNEL_BUILD)
+
+  /* TRD : any Windows (user-mode) on any CPU with the Microsoft C compiler
+
+           _WIN32             indicates 64-bit or 32-bit Windows
+           _MSC_VER           indicates Microsoft C compiler
+           !WIN_KERNEL_BUILD  indicates Windows user-mode
+  */
+
+  void abstraction_thread_wait( thread_state_t thread_state )
+  {
+    WaitForSingleObject( thread_state, INFINITE );
+
+    return;
+  }
+
+#endif
+
+
+
+
+
+/****************************************************************************/
+#if (defined _WIN32 && defined _MSC_VER && defined WIN_KERNEL_BUILD)
+
+  /* TRD : any Windows on any CPU with the Microsoft C compiler
+
+           _WIN32            indicates 64-bit or 32-bit Windows
+           _MSC_VER          indicates Microsoft C compiler
+           WIN_KERNEL_BUILD  indicates Windows kernel
+  */
+
+  void abstraction_thread_wait( thread_state_t thread_state )
+  {
+    KeWaitForSingleObject( thread_state, Executive, KernelMode, FALSE, NULL );
+
+    return;
+  }
+
+#endif
+
+
+
+
+
+/****************************************************************************/
+#if (defined __unix__)
+
+  /* TRD : any UNIX on any CPU with any compiler
+
+           I assumed pthreads is available on any UNIX.
+
+           __unix__   indicates Solaris, Linux, HPUX, etc
+  */
+
+  void abstraction_thread_wait( thread_state_t thread_state )
+  {
+    pthread_join( thread_state,  NULL );
+
+    return;
+  }
+
+#endif
+
diff --git a/liblfds/test/src/benchmark_freelist.c b/liblfds/test/src/benchmark_freelist.c
new file mode 100644
index 0000000..c82e628
--- /dev/null
+++ b/liblfds/test/src/benchmark_freelist.c
@@ -0,0 +1,138 @@
+#include "internal.h"
+
+
+
+
+
+/****************************************************************************/
+void benchmark_freelist( void )
+{
+  unsigned int
+    loop,
+    thread_count,
+    cpu_count;
+
+  struct freelist_state
+    *fs;
+
+  struct freelist_benchmark
+    *fb;
+
+  thread_state_t
+    *thread_handles;
+
+  atom_t
+    total_operations_for_full_test_for_all_cpus,
+    total_operations_for_full_test_for_all_cpus_for_one_cpu = 0;
+
+  double
+    mean_operations_per_second_per_cpu,
+    difference_per_second_per_cpu,
+    total_difference_per_second_per_cpu,
+    std_dev_per_second_per_cpu,
+    scalability;
+
+  /* TRD : here we benchmark the freelist
+
+           the benchmark is to have a single freelist
+           where a worker thread busy-works popping and then pushing
+  */
+
+  cpu_count = abstraction_cpu_count();
+
+  thread_handles = (thread_state_t *) malloc( sizeof(thread_state_t) * cpu_count );
+
+  fb = (struct freelist_benchmark *) malloc( sizeof(struct freelist_benchmark) * cpu_count );
+
+  // TRD : print the benchmark ID and CSV header
+  printf( "\n"
+          "Release %d Freelist Benchmark #1\n"
+          "CPUs,total ops,mean ops/sec per CPU,standard deviation,scalability\n", LIBLFDS_RELEASE_NUMBER );
+
+  // TRD : we run CPU count times for scalability
+  for( thread_count = 1 ; thread_count <= cpu_count ; thread_count++ )
+  {
+    // TRD : initialisation
+    freelist_new( &fs, 1000, NULL, NULL );
+
+    for( loop = 0 ; loop < cpu_count ; loop++ )
+    {
+      (fb+loop)->fs = fs;
+      (fb+loop)->operation_count = 0;
+    }
+
+    // TRD : main test
+    for( loop = 0 ; loop < thread_count ; loop++ )
+      abstraction_thread_start( &thread_handles[loop], loop, benchmark_freelist_thread_pop_and_push, fb+loop );
+
+    for( loop = 0 ; loop < thread_count ; loop++ )
+      abstraction_thread_wait( thread_handles[loop] );
+
+    // TRD : post test math
+    total_operations_for_full_test_for_all_cpus = 0;
+    total_difference_per_second_per_cpu = 0;
+
+    for( loop = 0 ; loop < thread_count ; loop++ )
+      total_operations_for_full_test_for_all_cpus += (fb+loop)->operation_count;
+
+    mean_operations_per_second_per_cpu = ((double) total_operations_for_full_test_for_all_cpus / (double) thread_count) / (double) 10;
+
+    if( thread_count == 1 )
+      total_operations_for_full_test_for_all_cpus_for_one_cpu = total_operations_for_full_test_for_all_cpus;
+
+    for( loop = 0 ; loop < thread_count ; loop++ )
+    {
+      difference_per_second_per_cpu = ((double) (fb+loop)->operation_count / (double) 10) - mean_operations_per_second_per_cpu;
+      total_difference_per_second_per_cpu += difference_per_second_per_cpu * difference_per_second_per_cpu;
+    }
+
+    std_dev_per_second_per_cpu = sqrt( (double) total_difference_per_second_per_cpu );
+
+    scalability = (double) total_operations_for_full_test_for_all_cpus / (double) (total_operations_for_full_test_for_all_cpus_for_one_cpu * thread_count);
+
+    printf( "%u,%u,%.0f,%.0f,%0.2f\n", thread_count, (unsigned int) total_operations_for_full_test_for_all_cpus, mean_operations_per_second_per_cpu, std_dev_per_second_per_cpu, scalability );
+
+    // TRD : cleanup
+    freelist_delete( fs, NULL, NULL );
+  }
+
+  free( fb );
+
+  free( thread_handles );
+
+  return;
+}
+
+
+
+
+
+/****************************************************************************/
+thread_return_t CALLING_CONVENTION benchmark_freelist_thread_pop_and_push( void *freelist_benchmark )
+{
+  struct freelist_benchmark
+    *fb;
+
+  struct freelist_element
+    *fe;
+
+  time_t
+    start_time;
+
+  assert( freelist_benchmark != NULL );
+
+  fb = (struct freelist_benchmark *) freelist_benchmark;
+
+  time( &start_time );
+
+  while( time(NULL) < start_time + 10 )
+  {
+    freelist_pop( fb->fs, &fe );
+    freelist_push( fb->fs, fe );
+
+    fb->operation_count += 2;
+  }
+
+  return( (thread_return_t) EXIT_SUCCESS );
+}
+
diff --git a/liblfds/test/src/benchmark_queue.c b/liblfds/test/src/benchmark_queue.c
new file mode 100644
index 0000000..c073e6b
--- /dev/null
+++ b/liblfds/test/src/benchmark_queue.c
@@ -0,0 +1,142 @@
+#include "internal.h"
+
+
+
+
+
+/****************************************************************************/
+void benchmark_queue( void )
+{
+  unsigned int
+    loop,
+    thread_count,
+    cpu_count;
+
+  struct queue_state
+    *qs;
+
+  struct queue_benchmark
+    *qb;
+
+  thread_state_t
+    *thread_handles;
+
+  atom_t
+    total_operations_for_full_test_for_all_cpus,
+    total_operations_for_full_test_for_all_cpus_for_one_cpu = 0;
+
+  double
+    mean_operations_per_second_per_cpu,
+    difference_per_second_per_cpu,
+    total_difference_per_second_per_cpu,
+    std_dev_per_second_per_cpu,
+    scalability;
+
+  /* TRD : here we benchmark the queue
+
+           the benchmark is to have a single queue
+           where a worker thread busy-works dequeuing and then queuing
+  */
+
+  cpu_count = abstraction_cpu_count();
+
+  thread_handles = (thread_state_t *) malloc( sizeof(thread_state_t) * cpu_count );
+
+  qb = (struct queue_benchmark *) malloc( sizeof(struct queue_benchmark) * cpu_count );
+
+  // TRD : print the benchmark ID and CSV header
+  printf( "\n"
+          "Release %d Queue Benchmark #1\n"
+          "CPUs,total ops,mean ops/sec per CPU,standard deviation,scalability\n", LIBLFDS_RELEASE_NUMBER );
+
+  // TRD : we run CPU count times for scalability
+  for( thread_count = 1 ; thread_count <= cpu_count ; thread_count++ )
+  {
+    // TRD : initialisation
+    queue_new( &qs, 1000 );
+
+    for( loop = 0 ; loop < cpu_count ; loop++ )
+    {
+      (qb+loop)->qs = qs;
+      (qb+loop)->operation_count = 0;
+    }
+
+    // TRD : populate the queue (we don't actually use the user data)
+    for( loop = 0 ; loop < 500 ; loop++ )
+      queue_enqueue( qs, (void *) (atom_t) loop );
+
+    // TRD : main test
+    for( loop = 0 ; loop < thread_count ; loop++ )
+      abstraction_thread_start( &thread_handles[loop], loop, benchmark_queue_thread_dequeue_and_enqueue, qb+loop );
+
+    for( loop = 0 ; loop < thread_count ; loop++ )
+      abstraction_thread_wait( thread_handles[loop] );
+
+    // TRD : post test math
+    total_operations_for_full_test_for_all_cpus = 0;
+    total_difference_per_second_per_cpu = 0;
+
+    for( loop = 0 ; loop < thread_count ; loop++ )
+      total_operations_for_full_test_for_all_cpus += (qb+loop)->operation_count;
+
+    mean_operations_per_second_per_cpu = ((double) total_operations_for_full_test_for_all_cpus / (double) thread_count) / (double) 10;
+
+    if( thread_count == 1 )
+      total_operations_for_full_test_for_all_cpus_for_one_cpu = total_operations_for_full_test_for_all_cpus;
+
+    for( loop = 0 ; loop < thread_count ; loop++ )
+    {
+      difference_per_second_per_cpu = ((double) (qb+loop)->operation_count / (double) 10) - mean_operations_per_second_per_cpu;
+      total_difference_per_second_per_cpu += difference_per_second_per_cpu * difference_per_second_per_cpu;
+    }
+
+    std_dev_per_second_per_cpu = sqrt( (double) total_difference_per_second_per_cpu );
+
+    scalability = (double) total_operations_for_full_test_for_all_cpus / (double) (total_operations_for_full_test_for_all_cpus_for_one_cpu * thread_count);
+
+    printf( "%u,%u,%.0f,%.0f,%0.2f\n", thread_count, (unsigned int) total_operations_for_full_test_for_all_cpus, mean_operations_per_second_per_cpu, std_dev_per_second_per_cpu, scalability );
+
+    // TRD : cleanup
+    queue_delete( qs, NULL, NULL );
+  }
+
+  free( qb );
+
+  free( thread_handles );
+
+  return;
+}
+
+
+
+
+
+/****************************************************************************/
+thread_return_t CALLING_CONVENTION benchmark_queue_thread_dequeue_and_enqueue( void *queue_benchmark )
+{
+  struct queue_benchmark
+    *qb;
+
+  void
+    *user_data;
+
+  time_t
+    start_time;
+
+  assert( queue_benchmark != NULL );
+
+  qb = (struct queue_benchmark *) queue_benchmark;
+
+  time( &start_time );
+
+  while( time(NULL) < start_time + 10 )
+  {
+    queue_dequeue( qb->qs, &user_data );
+    queue_enqueue( qb->qs, user_data );
+
+    qb->operation_count += 2;
+  }
+
+  return( (thread_return_t) EXIT_SUCCESS );
+}
+
diff --git a/liblfds/test/src/benchmark_ringbuffer.c b/liblfds/test/src/benchmark_ringbuffer.c
new file mode 100644
index 0000000..a76b972
--- /dev/null
+++ b/liblfds/test/src/benchmark_ringbuffer.c
@@ -0,0 +1,141 @@
+#include "internal.h"
+
+
+
+
+
+/****************************************************************************/
+void benchmark_ringbuffer( void )
+{
+  unsigned int
+    loop,
+    thread_count,
+    cpu_count;
+
+  struct ringbuffer_state
+    *rs;
+
+  struct ringbuffer_benchmark
+    *rb;
+
+  thread_state_t
+    *thread_handles;
+
+  atom_t
+    total_operations_for_full_test_for_all_cpus,
+    total_operations_for_full_test_for_all_cpus_for_one_cpu = 0;
+
+  double
+    mean_operations_per_second_per_cpu,
+    difference_per_second_per_cpu,
+    total_difference_per_second_per_cpu,
+    std_dev_per_second_per_cpu,
+    scalability;
+
+  /* TRD : here we benchmark the ringbuffer
+
+           the benchmark is to have a single ringbuffer
+           where a worker thread busy-works writing and then reading
+  */
+
+  cpu_count = abstraction_cpu_count();
+
+  thread_handles = (thread_state_t *) malloc( sizeof(thread_state_t) * cpu_count );
+
+  rb = (struct ringbuffer_benchmark *) malloc( sizeof(struct ringbuffer_benchmark) * cpu_count );
+
+  // TRD : print the benchmark ID and CSV header
+  printf( "\n"
+          "Release %d Ringbuffer Benchmark #1\n"
+          "CPUs,total ops,mean ops/sec per CPU,standard deviation,scalability\n", LIBLFDS_RELEASE_NUMBER );
+
+  // TRD : we run CPU count times for scalability
+  for( thread_count = 1 ; thread_count <= cpu_count ; thread_count++ )
+  {
+    // TRD : initialisation
+    ringbuffer_new( &rs, 1000, NULL, NULL );
+
+    for( loop = 0 ; loop < cpu_count ; loop++ )
+    {
+      (rb+loop)->rs = rs;
+      (rb+loop)->operation_count = 0;
+    }
+
+    // TRD : main test
+    for( loop = 0 ; loop < thread_count ; loop++ )
+      abstraction_thread_start( &thread_handles[loop], loop, benchmark_ringbuffer_thread_write_and_read, rb+loop );
+
+    for( loop = 0 ; loop < thread_count ; loop++ )
+      abstraction_thread_wait( thread_handles[loop] );
+
+    // TRD : post test math
+    total_operations_for_full_test_for_all_cpus = 0;
+    total_difference_per_second_per_cpu = 0;
+
+    for( loop = 0 ; loop < thread_count ; loop++ )
+      total_operations_for_full_test_for_all_cpus += (rb+loop)->operation_count;
+
+    mean_operations_per_second_per_cpu = ((double) total_operations_for_full_test_for_all_cpus / (double) thread_count) / (double) 10;
+
+    if( thread_count == 1 )
+      total_operations_for_full_test_for_all_cpus_for_one_cpu = total_operations_for_full_test_for_all_cpus;
+
+    for( loop = 0 ; loop < thread_count ; loop++ )
+    {
+      difference_per_second_per_cpu = ((double) (rb+loop)->operation_count / (double) 10) - mean_operations_per_second_per_cpu;
+      total_difference_per_second_per_cpu += difference_per_second_per_cpu * difference_per_second_per_cpu;
+    }
+
+    std_dev_per_second_per_cpu = sqrt( (double) total_difference_per_second_per_cpu );
+
+    scalability = (double) total_operations_for_full_test_for_all_cpus / (double) (total_operations_for_full_test_for_all_cpus_for_one_cpu * thread_count);
+
+    printf( "%u,%u,%.0f,%.0f,%0.2f\n", thread_count, (unsigned int) total_operations_for_full_test_for_all_cpus, mean_operations_per_second_per_cpu, std_dev_per_second_per_cpu, scalability );
+
+    // TRD : cleanup
+    ringbuffer_delete( rs, NULL, NULL );
+  }
+
+  free( rb );
+
+  free( thread_handles );
+
+  return;
+}
+
+
+
+
+
+/****************************************************************************/
+thread_return_t CALLING_CONVENTION benchmark_ringbuffer_thread_write_and_read( void *ringbuffer_benchmark )
+{
+  struct ringbuffer_benchmark
+    *rb;
+
+  struct freelist_element
+    *fe;
+
+  time_t
+    start_time;
+
+  assert( ringbuffer_benchmark != NULL );
+
+  rb = (struct ringbuffer_benchmark *) ringbuffer_benchmark;
+
+  time( &start_time );
+
+  while( time(NULL) < start_time + 10 )
+  {
+    ringbuffer_get_write_element( rb->rs, &fe, NULL );
+    ringbuffer_put_write_element( rb->rs, fe );
+
+    ringbuffer_get_read_element( rb->rs, &fe );
+    ringbuffer_put_read_element( rb->rs, fe );
+
+    rb->operation_count += 2;
+  }
+
+  return( (thread_return_t) EXIT_SUCCESS );
+}
+
diff --git a/liblfds/test/src/benchmark_stack.c b/liblfds/test/src/benchmark_stack.c
new file mode 100644
index 0000000..b335983
--- /dev/null
+++ b/liblfds/test/src/benchmark_stack.c
@@ -0,0 +1,138 @@
+#include "internal.h"
+
+
+
+
+
+/****************************************************************************/
+void benchmark_stack( void )
+{
+  unsigned int
+    loop,
+    thread_count,
+    cpu_count;
+
+  struct stack_state
+    *ss;
+
+  struct stack_benchmark
+    *sb;
+
+  thread_state_t
+    *thread_handles;
+
+  atom_t
+    total_operations_for_full_test_for_all_cpus,
+    total_operations_for_full_test_for_all_cpus_for_one_cpu = 0;
+
+  double
+    mean_operations_per_second_per_cpu,
+    difference_per_second_per_cpu,
+    total_difference_per_second_per_cpu,
+    std_dev_per_second_per_cpu,
+    scalability;
+
+  /* TRD : here we benchmark the stack
+
+           the benchmark is to have a single stack
+           where a worker thread busy-works pushing then popping
+  */
+
+  cpu_count = abstraction_cpu_count();
+
+  thread_handles = (thread_state_t *) malloc( sizeof(thread_state_t) * cpu_count );
+
+  sb = (struct stack_benchmark *) malloc( sizeof(struct stack_benchmark) * cpu_count );
+
+  // TRD : print the benchmark ID and CSV header
+  printf( "\n"
+          "Release %d Stack Benchmark #1\n"
+          "CPUs,total ops,mean ops/sec per CPU,standard deviation,scalability\n", LIBLFDS_RELEASE_NUMBER );
+
+  // TRD : we run CPU count times for scalability
+  for( thread_count = 1 ; thread_count <= cpu_count ; thread_count++ )
+  {
+    // TRD : initialisation
+    stack_new( &ss, 1000 );
+
+    for( loop = 0 ; loop < cpu_count ; loop++ )
+    {
+      (sb+loop)->ss = ss;
+      (sb+loop)->operation_count = 0;
+    }
+
+    // TRD : main test
+    for( loop = 0 ; loop < thread_count ; loop++ )
+      abstraction_thread_start( &thread_handles[loop], loop, benchmark_stack_thread_push_and_pop, sb+loop );
+
+    for( loop = 0 ; loop < thread_count ; loop++ )
+      abstraction_thread_wait( thread_handles[loop] );
+
+    // TRD : post test math
+    total_operations_for_full_test_for_all_cpus = 0;
+    total_difference_per_second_per_cpu = 0;
+
+    for( loop = 0 ; loop < thread_count ; loop++ )
+      total_operations_for_full_test_for_all_cpus += (sb+loop)->operation_count;
+
+    mean_operations_per_second_per_cpu = ((double) total_operations_for_full_test_for_all_cpus / (double) thread_count) / (double) 10;
+
+    if( thread_count == 1 )
+      total_operations_for_full_test_for_all_cpus_for_one_cpu = total_operations_for_full_test_for_all_cpus;
+
+    for( loop = 0 ; loop < thread_count ; loop++ )
+    {
+      difference_per_second_per_cpu = ((double) (sb+loop)->operation_count / (double) 10) - mean_operations_per_second_per_cpu;
+      total_difference_per_second_per_cpu += difference_per_second_per_cpu * difference_per_second_per_cpu;
+    }
+
+    std_dev_per_second_per_cpu = sqrt( (double) total_difference_per_second_per_cpu );
+
+    scalability = (double) total_operations_for_full_test_for_all_cpus / (double) (total_operations_for_full_test_for_all_cpus_for_one_cpu * thread_count);
+
+    printf( "%u,%u,%.0f,%.0f,%0.2f\n", thread_count, (unsigned int) total_operations_for_full_test_for_all_cpus, mean_operations_per_second_per_cpu, std_dev_per_second_per_cpu, scalability );
+
+    // TRD : cleanup
+    stack_delete( ss, NULL, NULL );
+  }
+
+  free( sb );
+
+  free( thread_handles );
+
+  return;
+}
+
+
+
+
+
+/****************************************************************************/
+thread_return_t CALLING_CONVENTION benchmark_stack_thread_push_and_pop( void *stack_benchmark )
+{
+  struct stack_benchmark
+    *sb;
+
+  void
+    *user_data = NULL;
+
+  time_t
+    start_time;
+
+  assert( stack_benchmark != NULL );
+
+  sb = (struct stack_benchmark *) stack_benchmark;
+
+  time( &start_time );
+
+  while( time(NULL) < start_time + 10 )
+  {
+    stack_push( sb->ss, user_data );
+    stack_pop( sb->ss, &user_data );
+
+    sb->operation_count += 2;
+  }
+
+  return( (thread_return_t) EXIT_SUCCESS );
+}
+
diff --git a/liblfds/test/src/internal.h b/liblfds/test/src/internal.h
new file mode 100644
index 0000000..8948fcc
--- /dev/null
+++ b/liblfds/test/src/internal.h
@@ -0,0 +1,104 @@
+/***** ANSI includes *****/
+#include <assert.h>
+#include <math.h>
+#include <stdio.h>
+#include <stdarg.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+
+/***** internal includes *****/
+#include "abstraction.h"
+
+/***** external includes *****/
+#include "liblfds.h"
+
+/***** defines *****/
+#define and &&
+#define or  ||
+
+#define RAISED   1
+#define LOWERED  0
+
+#define NO_FLAGS 0x0
+
+/***** enums *****/
+enum test_operation
+{
+  UNKNOWN,
+  HELP,
+  TEST,
+  BENCHMARK
+};
+
+/***** structs *****/
+#include "structures.h"
+
+/***** prototypes *****/
+int main( int argc, char **argv );
+
+void internal_display_test_name( char *test_name );
+void internal_display_test_result( unsigned int number_name_dvs_pairs, ... );
+void internal_display_data_structure_validity( enum data_structure_validity dvs );
+
+void benchmark_freelist( void );
+  thread_return_t CALLING_CONVENTION benchmark_freelist_thread_pop_and_push( void *freelist_benchmark );
+
+void benchmark_queue( void );
+  thread_return_t CALLING_CONVENTION benchmark_queue_thread_dequeue_and_enqueue( void *queue_benchmark );
+
+void benchmark_ringbuffer( void );
+  thread_return_t CALLING_CONVENTION benchmark_ringbuffer_thread_write_and_read( void *ringbuffer_benchmark );
+
+void benchmark_stack( void );
+  thread_return_t CALLING_CONVENTION benchmark_stack_thread_push_and_pop( void *stack_benchmark );
+
+void test_abstraction( void );
+  void abstraction_test_increment( void );
+    thread_return_t CALLING_CONVENTION abstraction_test_internal_thread_increment( void *shared_counter );
+    thread_return_t CALLING_CONVENTION abstraction_test_internal_thread_atomic_increment( void *shared_counter );
+  void abstraction_test_dcas( void );
+    thread_return_t CALLING_CONVENTION abstraction_test_internal_thread_dcas( void *abstraction_test_dcas_state );
+
+void test_freelist( void );
+  void freelist_test_internal_popping( void );
+    int freelist_test_internal_popping_init( void **user_data, void *user_state );
+    thread_return_t CALLING_CONVENTION freelist_test_internal_thread_popping( void *freelist_test_popping_state );
+  void freelist_test_internal_pushing( void );
+    int freelist_test_internal_pushing_init( void **user_data, void *user_state );
+    void freelist_test_internal_pushing_delete( void *user_data, void *user_state );
+    thread_return_t CALLING_CONVENTION freelist_test_internal_thread_pushing( void *freelist_test_pushing_state );
+  void freelist_test_internal_popping_and_pushing( void );
+    thread_return_t CALLING_CONVENTION freelist_test_internal_thread_popping_and_pushing_start_popping( void *freelist_test_popping_and_pushing_state );
+    thread_return_t CALLING_CONVENTION freelist_test_internal_thread_popping_and_pushing_start_pushing( void *freelist_test_popping_and_pushing_state );
+  void freelist_test_internal_rapid_popping_and_pushing( void );
+    thread_return_t CALLING_CONVENTION freelist_test_internal_thread_rapid_popping_and_pushing( void *freelist_state );
+
+void test_queue( void );
+  void queue_test_enqueuing( void );
+    thread_return_t CALLING_CONVENTION queue_test_internal_thread_simple_enqueuer( void *queue_test_enqueuing_state );
+  void queue_test_dequeuing( void );
+    thread_return_t CALLING_CONVENTION queue_test_internal_thread_simple_dequeuer( void *queue_test_dequeuing_state );
+  void queue_test_enqueuing_and_dequeuing( void );
+    thread_return_t CALLING_CONVENTION queue_test_internal_thread_enqueuer_and_dequeuer( void *queue_test_rapid_enqueuing_and_dequeuing_state );
+  void queue_test_rapid_enqueuing_and_dequeuing( void );
+    thread_return_t CALLING_CONVENTION queue_test_internal_thread_rapid_enqueuer_and_dequeuer( void *queue_test_rapid_enqueuing_and_dequeuing_state );
+
+void test_ringbuffer( void );
+  void ringbuffer_test_reading( void );
+    thread_return_t CALLING_CONVENTION ringbuffer_test_thread_simple_reader( void *ringbuffer_test_reading_state );
+  void ringbuffer_test_writing( void );
+    thread_return_t CALLING_CONVENTION ringbuffer_test_thread_simple_writer( void *ringbuffer_test_writing_state );
+  void ringbuffer_test_reading_and_writing( void );
+    thread_return_t CALLING_CONVENTION ringbuffer_test_thread_reader_writer( void *ringbuffer_test_reading_and_writing_state );
+
+void test_slist( void );
+  thread_return_t CALLING_CONVENTION slist_internal_thread_head_writer( void *slist_thread_start_state );
+  thread_return_t CALLING_CONVENTION slist_internal_thread_after_writer( void *slist_thread_start_state );
+  thread_return_t CALLING_CONVENTION slist_internal_thread_traverser( void *slist_thread_start_state );
+  thread_return_t CALLING_CONVENTION slist_internal_thread_deleter_traverser( void *slist_thread_start_state );
+
+void test_stack( void );
+  thread_return_t CALLING_CONVENTION stack_internal_thread_reader( void *stack_state );
+  thread_return_t CALLING_CONVENTION stack_internal_thread_writer( void *stack_state );
+
diff --git a/liblfds/test/src/main.c b/liblfds/test/src/main.c
new file mode 100644
index 0000000..565c0df
--- /dev/null
+++ b/liblfds/test/src/main.c
@@ -0,0 +1,74 @@
+#include "internal.h"
+
+
+
+
+
+/****************************************************************************/
+int main( int argc, char **argv )
+{
+  enum test_operation
+    operation = UNKNOWN;
+
+  unsigned int
+    loop,
+    iterations = 1;
+
+  assert( argc >= 1 );
+  assert( argv != NULL );
+
+  if( argc == 1 or argc >= 4 )
+    operation = HELP;
+
+  if( operation == UNKNOWN )
+  {
+    if( 0 == strcmp(*(argv+1), "test") )
+    {
+      operation = TEST;
+
+      // TRD : sscanf() may fail, but iterations is initialised to 1, so it's okay
+      if( argc == 3 )
+        sscanf( *(argv+2), "%u", &iterations );
+    }
+
+    if( 0 == strcmp(*(argv+1), "benchmark") )
+      operation = BENCHMARK;
+  }
+
+  switch( operation )
+  {
+    case UNKNOWN:
+    case HELP:
+      printf( "test [test|benchmark] [iterations]\n"
+              "  test       : run the test suite\n"
+              "  benchmark  : run the benchmark suite\n"
+              "  iterations : optional, only applies to tests, default is 1\n" );
+    break;
+
+    case TEST:
+      for( loop = 1 ; loop < iterations+1 ; loop++ )
+      {
+        printf( "\n"
+                "Test Iteration %02u\n"
+                "=================\n", loop );
+
+        test_abstraction();
+        test_freelist();
+        test_queue();
+        test_ringbuffer();
+        test_slist();
+        test_stack();
+      }
+    break;
+
+    case BENCHMARK:
+      benchmark_freelist();
+      benchmark_queue();
+      benchmark_ringbuffer();
+      benchmark_stack();
+    break;
+  }
+
+  return( EXIT_SUCCESS );
+}
+
diff --git a/liblfds/test/src/misc.c b/liblfds/test/src/misc.c
new file mode 100644
index 0000000..9e8e5d7
--- /dev/null
+++ b/liblfds/test/src/misc.c
@@ -0,0 +1,124 @@
+#include "internal.h"
+
+
+
+
+
+/****************************************************************************/
+void internal_display_test_name( char *test_name )
+{
+  assert( test_name != NULL );
+
+  printf( "%s...", test_name );
+  fflush( stdout );
+
+  return;
+}
+
+
+
+
+
+/****************************************************************************/
+void internal_display_test_result( unsigned int number_name_dvs_pairs, ... )
+{
+  va_list
+    va;
+
+  int
+    passed_flag = RAISED;
+
+  unsigned int
+    loop;
+
+  char
+    *name;
+
+  enum data_structure_validity
+    dvs;
+
+  // TRD : number_name_dvs_pairs can be any value in its range
+
+  va_start( va, number_name_dvs_pairs );
+
+  for( loop = 0 ; loop < number_name_dvs_pairs ; loop++ )
+  {
+    name = va_arg( va, char * );
+    dvs = va_arg( va, enum data_structure_validity );
+
+    if( dvs != VALIDITY_VALID )
+    {
+      passed_flag = LOWERED;
+      break;
+    }
+  }
+
+  va_end( va );
+
+  if( passed_flag == RAISED )
+    puts( "passed" );
+
+  if( passed_flag == LOWERED )
+  {
+    printf( "failed (" );
+
+    va_start( va, number_name_dvs_pairs );
+
+    for( loop = 0 ; loop < number_name_dvs_pairs ; loop++ )
+    {
+      name = va_arg( va, char * );
+      dvs = va_arg( va, enum data_structure_validity );
+
+      printf( "%s ", name );
+      internal_display_data_structure_validity( dvs );
+
+      if( loop+1 < number_name_dvs_pairs )
+        printf( ", " );
+    }
+
+    va_end( va );
+
+    printf( ")\n" );
+  }
+
+  return;
+}
+
+
+
+
+
+/****************************************************************************/
+void internal_display_data_structure_validity( enum data_structure_validity dvs )
+{
+  char
+    *string = NULL;
+
+  switch( dvs )
+  {
+    case VALIDITY_VALID:
+      string = "valid";
+    break;
+
+    case VALIDITY_INVALID_LOOP:
+      string = "invalid - loop detected";
+    break;
+
+    case VALIDITY_INVALID_MISSING_ELEMENTS:
+      string = "invalid - missing elements";
+    break;
+
+    case VALIDITY_INVALID_ADDITIONAL_ELEMENTS:
+      string = "invalid - additional elements";
+    break;
+
+    case VALIDITY_INVALID_TEST_DATA:
+      string = "invalid - invalid test data";
+    break;
+  }
+
+  printf( "%s", string );
+
+  return;
+}
+
diff --git a/liblfds/test/src/structures.h b/liblfds/test/src/structures.h
new file mode 100644
index 0000000..0fd21f2
--- /dev/null
+++ b/liblfds/test/src/structures.h
@@ -0,0 +1,190 @@
+/***** structs *****/
+#pragma pack( push, ALIGN_DOUBLE_POINTER )
+
+/***** abstraction tests *****/
+struct abstraction_test_dcas_state
+{
+  volatile atom_t
+    *shared_counter;
+
+  atom_t
+    local_counter;
+};
+
+/***** freelist tests *****/
+struct freelist_test_popping_state
+{
+  struct freelist_state
+    *fs,
+    *fs_thread_local;
+};
+
+struct freelist_test_pushing_state
+{
+  atom_t
+    thread_number;
+
+  struct freelist_state
+    *source_fs,
+    *fs;
+};
+
+struct freelist_test_popping_and_pushing_state
+{
+  struct freelist_state
+    *local_fs,
+    *fs;
+};
+
+struct freelist_test_counter_and_thread_number
+{
+  atom_t
+    thread_number;
+
+  unsigned long long int
+    counter;
+};
+
+/***** queue tests *****/
+struct queue_test_enqueuing_state
+{
+  struct queue_state
+    *qs;
+
+  atom_t
+    counter;
+};
+
+struct queue_test_dequeuing_state
+{
+  struct queue_state
+    *qs;
+
+  int
+    error_flag;
+};
+
+struct queue_test_enqueuing_and_dequeuing_state
+{
+  struct queue_state
+    *qs;
+
+  atom_t
+    counter,
+    thread_number,
+    *per_thread_counters;
+
+  unsigned int
+    cpu_count;
+
+  int
+    error_flag;
+};
+
+struct queue_test_rapid_enqueuing_and_dequeuing_state
+{
+  struct queue_state
+    *qs;
+
+  atom_t
+    counter;
+};
+
+/***** ringbuffer tests *****/
+struct ringbuffer_test_reading_state
+{
+  struct ringbuffer_state
+    *rs;
+
+  int
+    error_flag;
+
+  atom_t
+    read_count;
+};
+
+struct ringbuffer_test_writing_state
+{
+  struct ringbuffer_state
+    *rs;
+
+  atom_t
+    write_count;
+};
+
+struct ringbuffer_test_reading_and_writing_state
+{
+  struct ringbuffer_state
+    *rs;
+
+  atom_t
+    counter,
+    *per_thread_counters;
+
+  unsigned int
+    cpu_count;
+
+  int
+    error_flag;
+};
+
+/***** slist tests *****/
+struct slist_thread_start_state
+{
+  struct slist_state
+    *ss;
+
+  struct slist_element
+    *se;
+
+  time_t
+    duration;
+
+  unsigned long int
+    iteration_modulo;
+};
+
+/***** stack tests *****/
+
+/***** freelist benchmarks *****/
+struct freelist_benchmark
+{
+  struct freelist_state
+    *fs;
+
+  atom_t
+    operation_count;
+};
+
+/***** queue benchmarks *****/
+struct queue_benchmark
+{
+  struct queue_state
+    *qs;
+
+  atom_t
+    operation_count;
+};
+
+/***** ringbuffer benchmarks *****/
+struct ringbuffer_benchmark
+{
+  struct ringbuffer_state
+    *rs;
+
+  atom_t
+    operation_count;
+};
+
+/***** stack benchmarks *****/
+struct stack_benchmark
+{
+  struct stack_state
+    *ss;
+
+  atom_t
+    operation_count;
+};
+
+#pragma pack( pop )
+
diff --git a/liblfds/test/src/test_abstraction.c b/liblfds/test/src/test_abstraction.c
new file mode 100644
index 0000000..7093cf9
--- /dev/null
+++ b/liblfds/test/src/test_abstraction.c
@@ -0,0 +1,246 @@
+#include "internal.h"
+
+
+
+
+
+/****************************************************************************/
+void test_abstraction( void )
+{
+  printf( "\n"
+          "Abstraction Tests\n"
+          "=================\n" );
+
+  abstraction_test_increment();
+  abstraction_test_dcas();
+
+  return;
+}
+
+
+
+
+
+/****************************************************************************/
+void abstraction_test_increment( void )
+{
+  unsigned int
+    loop,
+    cpu_count;
+
+  thread_state_t
+    *thread_handles;
+
+  atom_t
+    shared_counter = 0,
+    atomic_shared_counter = 0;
+
+  /* TRD : here we test abstraction_increment
+
+           first, we run one thread per CPU where each thread increments
+           a shared counter 10,000,000 times - however, this first test
+           does NOT use atomic increment; it uses "++"
+
+           second, we repeat the exercise, but this time using
+           abstraction_increment()
+
+           if the final value in the first test is less than (10,000,000*cpu_count)
+           then the system is sensitive to non-atomic increments; this means if
+           our atomic version of the test passes, we can have some degree of confidence
+           that it works
+
+           if the final value in the first test is in fact correct, then we can't know
+           that our atomic version has changed anything
+
+           and of course if the final value in the atomic test is wrong, we know things
+           are broken
+  */
+
+  internal_display_test_name( "Atomic increment" );
+
+  cpu_count = abstraction_cpu_count();
+
+  thread_handles = malloc( sizeof(thread_state_t) * cpu_count );
+
+  // TRD : non-atomic
+  for( loop = 0 ; loop < cpu_count ; loop++ )
+    abstraction_thread_start( &thread_handles[loop], loop, abstraction_test_internal_thread_increment, &shared_counter );
+
+  for( loop = 0 ; loop < cpu_count ; loop++ )
+    abstraction_thread_wait( thread_handles[loop] );
+
+  // TRD : atomic
+  for( loop = 0 ; loop < cpu_count ; loop++ )
+    abstraction_thread_start( &thread_handles[loop], loop, abstraction_test_internal_thread_atomic_increment, &atomic_shared_counter );
+
+  for( loop = 0 ; loop < cpu_count ; loop++ )
+    abstraction_thread_wait( thread_handles[loop] );
+
+  free( thread_handles );
+
+  // TRD : results
+  if( shared_counter < (10000000 * cpu_count) and atomic_shared_counter == (10000000 * cpu_count) )
+    puts( "passed" );
+
+  if( shared_counter == (10000000 * cpu_count) and atomic_shared_counter == (10000000 * cpu_count) )
+    puts( "indeterminate" );
+
+  if( atomic_shared_counter < (10000000 * cpu_count) )
+    puts( "failed" );
+
+  return;
+}
+
+
+
+
+
+/****************************************************************************/
+thread_return_t CALLING_CONVENTION abstraction_test_internal_thread_increment( void *shared_counter )
+{
+  volatile atom_t
+    count = 0;
+
+  /* TRD : atom_t must be volatile or the compiler
+           optimizes it away into a single store
+  */
+
+  assert( shared_counter != NULL );
+
+  while( count++ < 10000000 )
+    (*(atom_t *) shared_counter)++;
+
+  return( (thread_return_t) EXIT_SUCCESS );
+}
+
+
+
+
+
+/****************************************************************************/
+thread_return_t CALLING_CONVENTION abstraction_test_internal_thread_atomic_increment( void *shared_counter )
+{
+  atom_t
+    count = 0;
+
+  assert( shared_counter != NULL );
+
+  while( count++ < 10000000 )
+    abstraction_increment( shared_counter );
+
+  return( (thread_return_t) EXIT_SUCCESS );
+}
+
+
+
+
+
+/****************************************************************************/
+void abstraction_test_dcas( void )
+{
+  unsigned int
+    loop,
+    cpu_count;
+
+  thread_state_t
+    *thread_handles;
+
+  struct abstraction_test_dcas_state
+    *atds;
+
+  ALIGN(ALIGN_DOUBLE_POINTER) volatile atom_t
+    shared_counter[2] = { 0, 0 };
+
+  atom_t
+    local_total = 0;
+
+  /* TRD : here we test abstraction_dcas
+
+           we run one thread per CPU
+           we use abstraction_dcas() to increment a shared counter
+           every time a thread successfully increments the counter,
+           it increments a thread local counter
+           the threads run for ten seconds
+           after the threads finish, we total the local counters
+           they should equal the shared counter
+  */
+
+  internal_display_test_name( "Atomic DCAS" );
+
+  cpu_count = abstraction_cpu_count();
+
+  atds = malloc( sizeof(struct abstraction_test_dcas_state) * cpu_count );
+
+  for( loop = 0 ; loop < cpu_count ; loop++ )
+  {
+    (atds+loop)->shared_counter = shared_counter;
+    (atds+loop)->local_counter = 0;
+  }
+
+  thread_handles = malloc( sizeof(thread_state_t) * cpu_count );
+
+  for( loop = 0 ; loop < cpu_count ; loop++ )
+    abstraction_thread_start( &thread_handles[loop], loop, abstraction_test_internal_thread_dcas, atds+loop );
+
+  for( loop = 0 ; loop < cpu_count ; loop++ )
+    abstraction_thread_wait( thread_handles[loop] );
+
+  free( thread_handles );
+
+  // TRD : results
+  for( loop = 0 ; loop < cpu_count ; loop++ )
+    local_total += (atds+loop)->local_counter;
+
+  if( local_total == shared_counter[0] )
+    puts( "passed" );
+
+  if( local_total != shared_counter[0] )
+    puts( "failed" );
+
+  // TRD : cleanup
+  free( atds );
+
+  return;
+}
+
+
+
+
+
+/****************************************************************************/
+thread_return_t CALLING_CONVENTION abstraction_test_internal_thread_dcas( void *abstraction_test_dcas_state )
+{
+  struct abstraction_test_dcas_state
+    *atds;
+
+  time_t
+    start_time;
+
+  ALIGN(ALIGN_DOUBLE_POINTER) atom_t
+    exchange[2],
+    compare[2];
+
+  assert( abstraction_test_dcas_state != NULL );
+
+  atds = (struct abstraction_test_dcas_state *) abstraction_test_dcas_state;
+
+  time( &start_time );
+
+  while( time(NULL) < start_time + 10 )
+  {
+    compare[0] = *atds->shared_counter;
+    compare[1] = *(atds->shared_counter+1);
+
+    do
+    {
+      exchange[0] = compare[0] + 1;
+      exchange[1] = compare[1];
+    }
+    while( 0 == abstraction_dcas(atds->shared_counter, exchange, compare) );
+
+    atds->local_counter++;
+  }
+
+  return( (thread_return_t) EXIT_SUCCESS );
+}
+
diff --git a/liblfds/test/src/test_freelist.c b/liblfds/test/src/test_freelist.c
new file mode 100644
index 0000000..687d833
--- /dev/null
+++ b/liblfds/test/src/test_freelist.c
@@ -0,0 +1,662 @@
+#include "internal.h"
+
+
+
+
+
+/****************************************************************************/
+void test_freelist( void )
+{
+  printf( "\n"
+          "Freelist Tests\n"
+          "==============\n" );
+
+  freelist_test_internal_popping();
+  freelist_test_internal_pushing();
+  freelist_test_internal_popping_and_pushing();
+  freelist_test_internal_rapid_popping_and_pushing();
+
+  return;
+}
+
+
+
+
+
+/****************************************************************************/
+void freelist_test_internal_popping( void )
+{
+  unsigned int
+    loop,
+    cpu_count,
+    count;
+
+  thread_state_t
+    *thread_handles;
+
+  enum data_structure_validity
+    dvs = VALIDITY_VALID;
+
+  struct freelist_state
+    *fs;
+
+  struct freelist_element
+    *fe;
+
+  struct freelist_test_popping_state
+    *ftps;
+
+  unsigned int
+    *found_count;
+
+  /* TRD : we create a freelist with 1,000,000 elements
+
+           the creation function runs in a single thread and creates
+           and pushes those elements onto the freelist
+
+           each element contains a void pointer which is its element number
+
+           we then run one thread per CPU
+           where each thread loops, popping as quickly as possible
+           each popped element is pushed onto a thread-local freelist
+
+           the threads run till the source freelist is empty
+
+           we then check the thread-local freelists
+           we should find we have every element
+
+           then tidy up
+  */
+
+  internal_display_test_name( "Popping" );
+
+  cpu_count = abstraction_cpu_count();
+
+  freelist_new( &fs, 1000000, freelist_test_internal_popping_init, NULL );
+  ftps = malloc( sizeof(struct freelist_test_popping_state) * cpu_count );
+  for( loop = 0 ; loop < cpu_count ; loop++ )
+  {
+    (ftps+loop)->fs = fs;
+    freelist_new( &(ftps+loop)->fs_thread_local, 0, NULL, NULL );
+  }
+
+  thread_handles = malloc( sizeof(thread_state_t) * cpu_count );
+
+  for( loop = 0 ; loop < cpu_count ; loop++ )
+    abstraction_thread_start( &thread_handles[loop], loop, freelist_test_internal_thread_popping, ftps+loop );
+
+  for( loop = 0 ; loop < cpu_count ; loop++ )
+    abstraction_thread_wait( thread_handles[loop] );
+
+  free( thread_handles );
+
+  // TRD : now we check the thread-local freelists
+  found_count = malloc( sizeof(unsigned int) * 1000000 );
+  for( loop = 0 ; loop < 1000000 ; loop++ )
+    *(found_count+loop) = 0;
+
+  for( loop = 0 ; loop < cpu_count ; loop++ )
+  {
+    while( freelist_pop((ftps+loop)->fs_thread_local, &fe) )
+    {
+      freelist_get_user_data_from_element( fe, (void **) &count );
+      (*(found_count+count))++;
+      freelist_push( fs, fe );
+    }
+  }
+
+  for( loop = 0 ; loop < 1000000 and dvs == VALIDITY_VALID ; loop++ )
+  {
+    if( *(found_count+loop) == 0 )
+      dvs = VALIDITY_INVALID_MISSING_ELEMENTS;
+
+    if( *(found_count+loop) > 1 )
+      dvs = VALIDITY_INVALID_ADDITIONAL_ELEMENTS;
+  }
+
+  // TRD : cleanup
+  free( found_count );
+  for( loop = 0 ; loop < cpu_count ; loop++ )
+    freelist_delete( (ftps+loop)->fs_thread_local, NULL, NULL );
+  freelist_delete( fs, NULL, NULL );
+
+  // TRD : print the test result
+  internal_display_test_result( 1, "freelist", dvs );
+
+  return;
+}
+
+
+
+
+
+/****************************************************************************/
+#pragma warning( disable : 4100 )
+
+int freelist_test_internal_popping_init( void **user_data, void *user_state )
+{
+  static atom_t
+    count = 0;
+
+  assert( user_data != NULL );
+  assert( user_state == NULL );
+
+  *(atom_t *) user_data = count++;
+
+  return( 1 );
+}
+
+#pragma warning( default : 4100 )
+
+
+
+
+
+/****************************************************************************/
+thread_return_t CALLING_CONVENTION freelist_test_internal_thread_popping( void *freelist_test_popping_state )
+{
+  struct freelist_test_popping_state
+    *ftps;
+
+  struct freelist_element
+    *fe;
+
+  assert( freelist_test_popping_state != NULL );
+
+  ftps = (struct freelist_test_popping_state *) freelist_test_popping_state;
+
+  while( freelist_pop(ftps->fs, &fe) )
+    freelist_push( ftps->fs_thread_local, fe );
+
+  return( (thread_return_t) EXIT_SUCCESS );
+}
+
+
+
+
+
+/****************************************************************************/
+void freelist_test_internal_pushing( void )
+{
+  unsigned int
+    loop,
+    cpu_count;
+
+  thread_state_t
+    *thread_handles;
+
+  enum data_structure_validity
+    dvs;
+
+  struct freelist_test_pushing_state
+    *ftps;
+
+  struct freelist_element
+    *fe;
+
+  struct freelist_state
+    *fs,
+    *cleanup_fs;
+
+  struct freelist_test_counter_and_thread_number
+    *cnt,
+    *counter_and_number_trackers;
+
+  struct validation_info
+    vi = { 1000000, 1000000 };
+
+  /* TRD : we create an empty freelist, which we will push to
+
+           we then create one freelist per CPU, where this freelist
+           contains 1,000,000/cpu_count number of elements and
+           each element is an incrementing counter and unique ID
+           (from 0 to number of CPUs)
+
+           we then start one thread per CPU, where each thread is
+           given one of the populated freelists and pops from that
+           to push to the empty freelist
+
+           the reason for this is to achieve memory pre-allocation
+           which allows the pushing threads to run at maximum speed
+
+           the threads end when their freelists are empty
+
+           we then fully pop the now populated main freelist (onto
+           a second freelist, so we can cleanly free all memory),
+           checking that the counts increment on a per unique ID basis
+           and that the number of elements we pop equals 1,000,000
+           (since each element has an incrementing counter which is
+            unique on a per unique ID basis, we can know we didn't lose
+            any elements)
+  */
+
+  internal_display_test_name( "Pushing" );
+
+  cpu_count = abstraction_cpu_count();
+
+  ftps = malloc( sizeof(struct freelist_test_pushing_state) * cpu_count );
+
+  freelist_new( &fs, 0, NULL, NULL );
+
+  for( loop = 0 ; loop < cpu_count ; loop++ )
+  {
+    (ftps+loop)->thread_number = (atom_t) loop;
+    freelist_new( &(ftps+loop)->source_fs, 1000000 / cpu_count, freelist_test_internal_pushing_init, (void *) (atom_t) loop );
+    (ftps+loop)->fs = fs;
+  }
+
+  thread_handles = malloc( sizeof(thread_state_t) * cpu_count );
+
+  for( loop = 0 ; loop < cpu_count ; loop++ )
+    abstraction_thread_start( &thread_handles[loop], loop, freelist_test_internal_thread_pushing, ftps+loop );
+
+  for( loop = 0 ; loop < cpu_count ; loop++ )
+    abstraction_thread_wait( thread_handles[loop] );
+
+  free( thread_handles );
+
+  // TRD : now fully pop and verify the main freelist
+  freelist_new( &cleanup_fs, 0, NULL, NULL );
+
+  counter_and_number_trackers = malloc( sizeof(struct freelist_test_counter_and_thread_number) * cpu_count );
+
+  for( loop = 0 ; loop < cpu_count ; loop++ )
+  {
+    (counter_and_number_trackers+loop)->counter = (1000000 / cpu_count) * loop;
+    (counter_and_number_trackers+loop)->thread_number = (atom_t) loop;
+  }
+
+  freelist_query( fs, FREELIST_QUERY_VALIDATE, &vi, (void *) &dvs );
+
+  while( dvs == VALIDITY_VALID and freelist_pop(fs, &fe) )
+  {
+    static int count = 0;
+
+    freelist_get_user_data_from_element( fe, (void **) &cnt );
+
+    if( cnt->counter != (counter_and_number_trackers+cnt->thread_number)->counter++ )
+      dvs = VALIDITY_INVALID_MISSING_ELEMENTS;
+
+    freelist_push( cleanup_fs, fe );
+
+    count++;
+  }
+
+  // TRD : clean up
+  free( counter_and_number_trackers );
+
+  for( loop = 0 ; loop < cpu_count ; loop++ )
+    freelist_delete( (ftps+loop)->source_fs, NULL, NULL );
+
+  free( ftps );
+
+  freelist_delete( cleanup_fs, freelist_test_internal_pushing_delete, NULL );
+  freelist_delete( fs, NULL, NULL );
+
+  // TRD : print the test result
+  internal_display_test_result( 1, "freelist", dvs );
+
+  return;
+}
+
+
+
+
+
+/****************************************************************************/
+int freelist_test_internal_pushing_init( void **user_data, void *user_state )
+{
+  struct freelist_test_counter_and_thread_number
+    *ftcatn;
+
+  static atom_t
+    counter = 0;
+
+  assert( user_data != NULL );
+  // TRD : user_state is being used as an integer type
+
+  *user_data = malloc( sizeof(struct freelist_test_counter_and_thread_number) );
+
+  ftcatn = (struct freelist_test_counter_and_thread_number *) *user_data;
+
+  ftcatn->counter = counter++;
+  ftcatn->thread_number = (atom_t) user_state;
+
+  return( 1 );
+}
+
+
+
+
+
+/****************************************************************************/
+#pragma warning( disable : 4100 )
+
+void freelist_test_internal_pushing_delete( void *user_data, void *user_state )
+{
+  assert( user_data != NULL );
+  assert( user_state == NULL );
+
+  free( user_data );
+
+  return;
+}
+
+#pragma warning( default : 4100 )
+
+
+
+
+
+/****************************************************************************/
+thread_return_t CALLING_CONVENTION freelist_test_internal_thread_pushing( void *freelist_test_pushing_state )
+{
+  struct freelist_test_pushing_state
+    *ftps;
+
+  struct freelist_element
+    *fe;
+
+  assert( freelist_test_pushing_state != NULL );
+
+  ftps = (struct freelist_test_pushing_state *) freelist_test_pushing_state;
+
+  while( freelist_pop(ftps->source_fs, &fe) )
+    freelist_push( ftps->fs, fe );
+
+  return( (thread_return_t) EXIT_SUCCESS );
+}
+
+
+
+
+
+/****************************************************************************/
+void freelist_test_internal_popping_and_pushing( void )
+{
+  unsigned int
+    loop,
+    cpu_count;
+
+  thread_state_t
+    *thread_handles;
+
+  enum data_structure_validity
+    dvs;
+
+  struct freelist_state
+    *fs;
+
+  struct freelist_test_popping_and_pushing_state
+    *pps;
+
+  struct validation_info
+    vi;
+
+  /* TRD : we have two threads per CPU
+           the threads loop for ten seconds
+           the first thread pushes 100000 elements then pops 100000 elements
+           the second thread pops 100000 elements then pushes 100000 elements
+           all pushes and pops go onto the single main freelist
+
+           after time is up, all threads push what they have remaining onto
+           the main freelist
+
+           we then validate the main freelist
+  */
+
+  internal_display_test_name( "Popping and pushing (10 seconds)" );
+
+  cpu_count = abstraction_cpu_count();
+
+  freelist_new( &fs, 100000 * cpu_count, NULL, NULL );
+
+  pps = malloc( sizeof(struct freelist_test_popping_and_pushing_state) * cpu_count * 2 );
+
+  for( loop = 0 ; loop < cpu_count ; loop++ )
+  {
+    (pps+loop)->fs = fs;
+    freelist_new( &(pps+loop)->local_fs, 0, NULL, NULL );
+
+    (pps+loop+cpu_count)->fs = fs;
+    freelist_new( &(pps+loop+cpu_count)->local_fs, 100000, NULL, NULL );
+  }
+
+  thread_handles = malloc( sizeof(thread_state_t) * cpu_count * 2 );
+
+  for( loop = 0 ; loop < cpu_count ; loop++ )
+  {
+    abstraction_thread_start( &thread_handles[loop], loop, freelist_test_internal_thread_popping_and_pushing_start_popping, pps+loop );
+    abstraction_thread_start( &thread_handles[loop+cpu_count], loop, freelist_test_internal_thread_popping_and_pushing_start_pushing, pps+loop+cpu_count );
+  }
+
+  for( loop = 0 ; loop < cpu_count * 2 ; loop++ )
+    abstraction_thread_wait( thread_handles[loop] );
+
+  free( thread_handles );
+
+  for( loop = 0 ; loop < cpu_count * 2 ; loop++ )
+    freelist_delete( (pps+loop)->local_fs, NULL, NULL );
+
+  free( pps );
+
+  vi.min_elements = vi.max_elements = 100000 * cpu_count * 2;
+
+  freelist_query( fs, FREELIST_QUERY_VALIDATE, (void *) &vi, (void *) &dvs );
+
+  freelist_delete( fs, NULL, NULL );
+
+  // TRD : print the test result
+  internal_display_test_result( 1, "freelist", dvs );
+
+  return;
+}
+
+
+
+
+
+
+/****************************************************************************/
+thread_return_t CALLING_CONVENTION freelist_test_internal_thread_popping_and_pushing_start_popping( void *freelist_test_popping_and_pushing_state )
+{
+  struct freelist_test_popping_and_pushing_state
+    *pps;
+
+  struct freelist_element
+    *fe;
+
+  time_t
+    start_time;
+
+  unsigned int
+    count;
+
+  assert( freelist_test_popping_and_pushing_state != NULL );
+
+  pps = (struct freelist_test_popping_and_pushing_state *) freelist_test_popping_and_pushing_state;
+
+  time( &start_time );
+
+  while( time(NULL) < start_time + 10 )
+  {
+    count = 0;
+
+    while( count < 100000 )
+    {
+      freelist_pop( pps->fs, &fe );
+
+      if( fe != NULL )
+      {
+        freelist_push( pps->local_fs, fe );
+        count++;
+      }
+    }
+
+    while( freelist_pop(pps->local_fs, &fe) )
+      freelist_push( pps->fs, fe );
+  }
+
+  return( (thread_return_t) EXIT_SUCCESS );
+}
+
+
+
+
+
+/****************************************************************************/
+thread_return_t CALLING_CONVENTION freelist_test_internal_thread_popping_and_pushing_start_pushing( void *freelist_test_popping_and_pushing_state )
+{
+  struct freelist_test_popping_and_pushing_state
+    *pps;
+
+  struct freelist_element
+    *fe;
+
+  time_t
+    start_time;
+
+  unsigned int
+    count;
+
+  assert( freelist_test_popping_and_pushing_state != NULL );
+
+  pps = (struct freelist_test_popping_and_pushing_state *) freelist_test_popping_and_pushing_state;
+
+  time( &start_time );
+
+  while( time(NULL) < start_time + 10 )
+  {
+    while( freelist_pop(pps->local_fs, &fe) )
+      freelist_push( pps->fs, fe );
+
+    count = 0;
+
+    while( count < 1000 )
+    {
+      freelist_pop( pps->fs, &fe );
+
+      if( fe != NULL )
+      {
+        freelist_push( pps->local_fs, fe );
+        count++;
+      }
+    }
+  }
+
+  // TRD : now push whatever we have in our local freelist
+  while( freelist_pop(pps->local_fs, &fe) )
+    freelist_push( pps->fs, fe );
+
+  return( (thread_return_t) EXIT_SUCCESS );
+}
+
+
+
+
+
+/****************************************************************************/
+void freelist_test_internal_rapid_popping_and_pushing( void )
+{
+  unsigned int
+    loop,
+    cpu_count;
+
+  thread_state_t
+    *thread_handles;
+
+  struct freelist_state
+    *fs;
+
+  struct validation_info
+    vi;
+
+  enum data_structure_validity
+    dvs;
+
+  /* TRD : in these tests there is a fundamental antagonism between
+           how much checking/memory clean up that we do and the
+           likelyhood of collisions between threads in their lock-free
+           operations
+
+           the lock-free operations are very quick; if we do anything
+           much at all between operations, we greatly reduce the chance
+           of threads colliding
+
+           so we have some tests which do enough checking/clean up that
+           they can tell the freelist is valid and don't leak memory
+           and here, this test now is one of those which does minimal
+           checking - in fact, the nature of the test is that you can't
+           do any real checking - but goes very quickly
+
+           what we do is create a small freelist and then run one thread
+           per CPU, where each thread simply pops and then immediately
+           pushes
+
+           the test runs for ten seconds
+
+           after the test is done, the only check we do is to traverse
+           the freelist, checking for loops and ensuring the number of
+           elements is correct
+  */
+
+  internal_display_test_name( "Rapid popping and pushing (10 seconds)" );
+
+  cpu_count = abstraction_cpu_count();
+
+  freelist_new( &fs, cpu_count, NULL, NULL );
+
+  thread_handles = malloc( sizeof(thread_state_t) * cpu_count );
+
+  for( loop = 0 ; loop < cpu_count ; loop++ )
+    abstraction_thread_start( &thread_handles[loop], loop, freelist_test_internal_thread_rapid_popping_and_pushing, fs );
+
+  for( loop = 0 ; loop < cpu_count ; loop++ )
+    abstraction_thread_wait( thread_handles[loop] );
+
+  free( thread_handles );
+
+  vi.min_elements = cpu_count;
+  vi.max_elements = cpu_count;
+
+  freelist_query( fs, FREELIST_QUERY_VALIDATE, (void *) &vi, (void *) &dvs );
+
+  freelist_delete( fs, NULL, NULL );
+
+  // TRD : print the test result
+  internal_display_test_result( 1, "freelist", dvs );
+
+  return;
+}
+
+
+
+
+
+/****************************************************************************/
+thread_return_t CALLING_CONVENTION freelist_test_internal_thread_rapid_popping_and_pushing( void *freelist_state )
+{
+  struct freelist_state
+    *fs;
+
+  struct freelist_element
+    *fe;
+
+  time_t
+    start_time;
+
+  assert( freelist_state != NULL );
+
+  fs = (struct freelist_state *) freelist_state;
+
+  time( &start_time );
+
+  while( time(NULL) < start_time + 10 )
+  {
+    freelist_pop( fs, &fe );
+    freelist_push( fs, fe );
+  }
+
+  return( (thread_return_t) EXIT_SUCCESS );
+}
+
diff --git a/liblfds/test/src/test_queue.c b/liblfds/test/src/test_queue.c
new file mode 100644
index 0000000..7b227c4
--- /dev/null
+++ b/liblfds/test/src/test_queue.c
@@ -0,0 +1,519 @@
+#include "internal.h"
+
+
+
+
+
+/****************************************************************************/
+void test_queue( void )
+{
+  printf( "\n"
+          "Queue Tests\n"
+          "===========\n" );
+
+  queue_test_enqueuing();
+  queue_test_dequeuing();
+  queue_test_enqueuing_and_dequeuing();
+  queue_test_rapid_enqueuing_and_dequeuing();
+
+  return;
+}
+
+
+
+
+
+/****************************************************************************/
+void queue_test_enqueuing( void )
+{
+  unsigned int
+    loop,
+    cpu_count;
+
+  thread_state_t
+    *thread_handles;
+
+  struct queue_state
+    *qs;
+
+  struct queue_test_enqueuing_state
+    *qtes;
+
+  atom_t
+    user_data,
+    thread,
+    count,
+    *per_thread_counters;
+
+  struct validation_info
+    vi = { 1000000, 1000000 };
+
+  enum data_structure_validity
+    dvs[2];
+
+  /* TRD : create an empty queue with 1,000,000 elements in its freelist
+           then run one thread per CPU
+           where each thread busy-works, enqueuing elements (until there are no more elements)
+           each element's void pointer of user data is (thread number | element number)
+           where element_number is a thread-local counter starting at 0
+           where the thread_number occupies the top byte
+
+           when we're done, we check that all the elements are present
+           and increment on a per-thread basis
+  */
+
+  internal_display_test_name( "Enqueuing" );
+
+  cpu_count = abstraction_cpu_count();
+
+  queue_new( &qs, 1000000 );
+
+  qtes = malloc( sizeof(struct queue_test_enqueuing_state) * cpu_count );
+
+  for( loop = 0 ; loop < cpu_count ; loop++ )
+  {
+    (qtes+loop)->qs = qs;
+    (qtes+loop)->counter = (atom_t) loop << (sizeof(atom_t)*8-8);
+  }
+
+  thread_handles = malloc( sizeof(thread_state_t) * cpu_count );
+
+  for( loop = 0 ; loop < cpu_count ; loop++ )
+    abstraction_thread_start( &thread_handles[loop], loop, queue_test_internal_thread_simple_enqueuer, qtes+loop );
+
+  for( loop = 0 ; loop < cpu_count ; loop++ )
+    abstraction_thread_wait( thread_handles[loop] );
+
+  free( thread_handles );
+
+  free( qtes );
+
+  /* TRD : first, validate the queue
+
+           then dequeue
+           we expect to find element numbers increment on a per thread basis
+  */
+
+  queue_query( qs, QUEUE_QUERY_VALIDATE, &vi, dvs );
+
+  per_thread_counters = malloc( sizeof(atom_t) * cpu_count );
+
+  for( loop = 0 ; loop < cpu_count ; loop++ )
+    *(per_thread_counters+loop) = 0;
+
+  while( dvs[0] == VALIDITY_VALID and dvs[1] == VALIDITY_VALID and queue_dequeue(qs, (void *) &user_data) )
+  {
+    thread = user_data >> (sizeof(atom_t)*8-8);
+    count = (user_data << 8) >> 8;
+
+    if( thread >= cpu_count )
+    {
+      dvs[0] = VALIDITY_INVALID_TEST_DATA;
+      break;
+    }
+
+    if( count < per_thread_counters[thread] )
+      dvs[0] = VALIDITY_INVALID_ADDITIONAL_ELEMENTS;
+
+    if( count > per_thread_counters[thread] )
+      dvs[0] = VALIDITY_INVALID_MISSING_ELEMENTS;
+
+    if( count == per_thread_counters[thread] )
+      per_thread_counters[thread]++;
+  }
+
+  free( per_thread_counters );
+
+  queue_delete( qs, NULL, NULL );
+
+  internal_display_test_result( 2, "queue", dvs[0], "queue freelist", dvs[1] );
+
+  return;
+}
+
+
+
+
+
+/****************************************************************************/
+thread_return_t CALLING_CONVENTION queue_test_internal_thread_simple_enqueuer( void *queue_test_enqueuing_state )
+{
+  struct queue_test_enqueuing_state
+    *qtes;
+
+  assert( queue_test_enqueuing_state != NULL );
+
+  qtes = (struct queue_test_enqueuing_state *) queue_test_enqueuing_state;
+
+  // TRD : top byte of counter is already our thread number
+  while( queue_enqueue(qtes->qs, (void *) qtes->counter++) );
+
+  return( (thread_return_t) EXIT_SUCCESS );
+}
+
+
+
+
+
+/****************************************************************************/
+void queue_test_dequeuing( void )
+{
+  unsigned int
+    loop,
+    cpu_count;
+
+  thread_state_t
+    *thread_handles;
+
+  struct queue_state
+    *qs;
+
+  struct queue_test_dequeuing_state
+    *qtds;
+
+  struct validation_info
+    vi = { 0, 0 };
+
+  enum data_structure_validity
+    dvs[2];
+
+  /* TRD : create a queue with 1,000,000 elements
+
+           use a single thread to enqueue every element
+           each elements user data is an incrementing counter
+
+           then run one thread per CPU
+           where each busy-works dequeuing
+
+           when an element is dequeued, we check (on a per-thread basis) the
+           value deqeued is greater than the element previously dequeued
+  */
+
+  internal_display_test_name( "Dequeuing" );
+
+  cpu_count = abstraction_cpu_count();
+
+  queue_new( &qs, 1000000 );
+
+  for( loop = 0 ; loop < 1000000 ; loop++ )
+    queue_enqueue( qs, (void *) (atom_t) loop );
+
+  qtds = malloc( sizeof(struct queue_test_dequeuing_state) * cpu_count );
+
+  for( loop = 0 ; loop < cpu_count ; loop++ )
+  {
+    (qtds+loop)->qs = qs;
+    (qtds+loop)->error_flag = LOWERED;
+  }
+
+  thread_handles = malloc( sizeof(thread_state_t) * cpu_count );
+
+  for( loop = 0 ; loop < cpu_count ; loop++ )
+    abstraction_thread_start( &thread_handles[loop], loop, queue_test_internal_thread_simple_dequeuer, qtds+loop );
+
+  for( loop = 0 ; loop < cpu_count ; loop++ )
+    abstraction_thread_wait( thread_handles[loop] );
+
+  free( thread_handles );
+
+  // TRD : check queue is empty
+  queue_query( qs, QUEUE_QUERY_VALIDATE, (void *) &vi, (void *) dvs );
+
+  // TRD : check for raised error flags
+  for( loop = 0 ; loop < cpu_count ; loop++ )
+    if( (qtds+loop)->error_flag == RAISED )
+      dvs[0] = VALIDITY_INVALID_TEST_DATA;
+
+  free( qtds );
+
+  queue_delete( qs, NULL, NULL );
+
+  internal_display_test_result( 2, "queue", dvs[0], "queue freelist", dvs[1] );
+
+  return;
+}
+
+
+
+
+
+/****************************************************************************/
+thread_return_t CALLING_CONVENTION queue_test_internal_thread_simple_dequeuer( void *queue_test_dequeuing_state )
+{
+  struct queue_test_dequeuing_state
+    *qtds;
+
+  atom_t
+    *prev_user_data,
+    *user_data;
+
+  assert( queue_test_dequeuing_state != NULL );
+
+  qtds = (struct queue_test_dequeuing_state *) queue_test_dequeuing_state;
+
+  queue_dequeue( qtds->qs, (void *) &prev_user_data );
+
+  while( queue_dequeue(qtds->qs, (void *) &user_data) )
+  {
+    if( user_data <= prev_user_data )
+      qtds->error_flag = RAISED;
+
+    prev_user_data = user_data;
+  }
+
+  return( (thread_return_t) EXIT_SUCCESS );
+}
+
+
+
+
+
+/****************************************************************************/
+void queue_test_enqueuing_and_dequeuing( void )
+{
+  unsigned int
+    loop,
+    subloop,
+    cpu_count;
+
+  thread_state_t
+    *thread_handles;
+
+  struct queue_state
+    *qs;
+
+  struct queue_test_enqueuing_and_dequeuing_state
+    *qteds;
+
+  struct validation_info
+    vi = { 0, 0 };
+
+  enum data_structure_validity
+    dvs[2];
+
+  internal_display_test_name( "Enqueuing and dequeuing (10 seconds)" );
+
+  cpu_count = abstraction_cpu_count();
+
+  queue_new( &qs, cpu_count );
+
+  qteds = malloc( sizeof(struct queue_test_enqueuing_and_dequeuing_state) * cpu_count );
+
+  for( loop = 0 ; loop < cpu_count ; loop++ )
+  {
+    (qteds+loop)->qs = qs;
+    (qteds+loop)->thread_number = loop;
+    (qteds+loop)->counter = (atom_t) loop << (sizeof(atom_t)*8-8);
+    (qteds+loop)->cpu_count = cpu_count;
+    (qteds+loop)->error_flag = LOWERED;
+    (qteds+loop)->per_thread_counters = malloc( sizeof(atom_t) * cpu_count );
+
+    for( subloop = 0 ; subloop < cpu_count ; subloop++ )
+      *((qteds+loop)->per_thread_counters+subloop) = 0;
+  }
+
+  thread_handles = malloc( sizeof(thread_state_t) * cpu_count );
+
+  for( loop = 0 ; loop < cpu_count ; loop++ )
+    abstraction_thread_start( &thread_handles[loop], loop, queue_test_internal_thread_enqueuer_and_dequeuer, qteds+loop );
+
+  for( loop = 0 ; loop < cpu_count ; loop++ )
+    abstraction_thread_wait( thread_handles[loop] );
+
+  free( thread_handles );
+
+  queue_query( qs, QUEUE_QUERY_VALIDATE, (void *) &vi, (void *) dvs );
+
+  for( loop = 0 ; loop < cpu_count ; loop++ )
+    if( (qteds+loop)->error_flag == RAISED )
+      dvs[0] = VALIDITY_INVALID_TEST_DATA;
+
+  for( loop = 0 ; loop < cpu_count ; loop++ )
+    free( (qteds+loop)->per_thread_counters );
+
+  free( qteds );
+
+  queue_delete( qs, NULL, NULL );
+
+  internal_display_test_result( 2, "queue", dvs[0], "queue freelist", dvs[1] );
+
+  return;
+}
+
+
+
+
+
+/****************************************************************************/
+thread_return_t CALLING_CONVENTION queue_test_internal_thread_enqueuer_and_dequeuer( void *queue_test_enqueuing_and_dequeuing_state )
+{
+  struct queue_test_enqueuing_and_dequeuing_state
+    *qteds;
+
+  time_t
+    start_time;
+
+  atom_t
+    thread,
+    count,
+    user_data;
+
+  assert( queue_test_enqueuing_and_dequeuing_state != NULL );
+
+  qteds = (struct queue_test_enqueuing_and_dequeuing_state *) queue_test_enqueuing_and_dequeuing_state;
+
+  time( &start_time );
+
+  while( time(NULL) < start_time + 10 )
+  {
+    queue_enqueue( qteds->qs, (void *) (qteds->counter++) );
+    queue_dequeue( qteds->qs, (void *) &user_data );
+
+    thread = user_data >> (sizeof(atom_t)*8-8);
+    count = (user_data << 8) >> 8;
+
+    if( thread >= qteds->cpu_count )
+      qteds->error_flag = RAISED;
+    else
+    {
+      if( count < qteds->per_thread_counters[thread] )
+        qteds->error_flag = RAISED;
+
+      if( count >= qteds->per_thread_counters[thread] )
+        qteds->per_thread_counters[thread] = count+1;
+    }
+  }
+
+  return( (thread_return_t) EXIT_SUCCESS );
+}
+
+
+
+
+
+/****************************************************************************/
+void queue_test_rapid_enqueuing_and_dequeuing( void )
+{
+  unsigned int
+    loop,
+    cpu_count;
+
+  thread_state_t
+    *thread_handles;
+
+  struct queue_state
+    *qs;
+
+  struct queue_test_rapid_enqueuing_and_dequeuing_state
+    *qtreds;
+
+  struct validation_info
+    vi = { 50000, 50000 };
+
+  atom_t
+    user_data,
+    thread,
+    count,
+    *per_thread_counters;
+
+  enum data_structure_validity
+    dvs[2];
+
+  internal_display_test_name( "Rapid enqueuing and dequeuing (10 seconds)" );
+
+  cpu_count = abstraction_cpu_count();
+
+  queue_new( &qs, 100000 );
+
+  for( loop = 0 ; loop < 50000 ; loop++ )
+    queue_enqueue( qs, NULL );
+
+  qtreds = malloc( sizeof(struct queue_test_rapid_enqueuing_and_dequeuing_state) * cpu_count );
+
+  for( loop = 0 ; loop < cpu_count ; loop++ )
+  {
+    (qtreds+loop)->qs = qs;
+    (qtreds+loop)->counter = (atom_t) loop << (sizeof(atom_t)*8-8);
+  }
+
+  thread_handles = malloc( sizeof(thread_state_t) * cpu_count );
+
+  for( loop = 0 ; loop < cpu_count ; loop++ )
+    abstraction_thread_start( &thread_handles[loop], loop, queue_test_internal_thread_rapid_enqueuer_and_dequeuer, qtreds+loop );
+
+  for( loop = 0 ; loop < cpu_count ; loop++ )
+    abstraction_thread_wait( thread_handles[loop] );
+
+  free( thread_handles );
+
+  queue_query( qs, QUEUE_QUERY_VALIDATE, (void *) &vi, (void *) dvs );
+
+  // TRD : now check results
+  per_thread_counters = malloc( sizeof(atom_t) * cpu_count );
+
+  for( loop = 0 ; loop < cpu_count ; loop++ )
+    *(per_thread_counters+loop) = 0;
+
+  while( dvs[0] == VALIDITY_VALID and dvs[1] == VALIDITY_VALID and queue_dequeue(qs, (void *) &user_data) )
+  {
+    thread = user_data >> (sizeof(atom_t)*8-8);
+    count = (user_data << 8) >> 8;
+
+    if( thread >= cpu_count )
+    {
+      dvs[0] = VALIDITY_INVALID_TEST_DATA;
+      break;
+    }
+
+    if( per_thread_counters[thread] == 0 )
+      per_thread_counters[thread] = count;
+
+    if( count < per_thread_counters[thread] )
+      dvs[0] = VALIDITY_INVALID_ADDITIONAL_ELEMENTS;
+
+    if( count >= per_thread_counters[thread] )
+      per_thread_counters[thread] = count+1;
+  }
+
+  free( per_thread_counters );
+
+  free( qtreds );
+
+  queue_delete( qs, NULL, NULL );
+
+  internal_display_test_result( 2, "queue", dvs[0], "queue freelist", dvs[1] );
+
+  return;
+}
+
+
+
+
+
+/****************************************************************************/
+thread_return_t CALLING_CONVENTION queue_test_internal_thread_rapid_enqueuer_and_dequeuer( void *queue_test_rapid_enqueuing_and_dequeuing_state )
+{
+  struct queue_test_rapid_enqueuing_and_dequeuing_state
+    *qtreds;
+
+  time_t
+    start_time;
+
+  atom_t
+    user_data;
+
+  assert( queue_test_rapid_enqueuing_and_dequeuing_state != NULL );
+
+  qtreds = (struct queue_test_rapid_enqueuing_and_dequeuing_state *) queue_test_rapid_enqueuing_and_dequeuing_state;
+
+  time( &start_time );
+
+  while( time(NULL) < start_time + 10 )
+  {
+    queue_enqueue( qtreds->qs, (void *) (qtreds->counter++) );
+    queue_dequeue( qtreds->qs, (void *) &user_data );
+  }
+
+  return( (thread_return_t) EXIT_SUCCESS );
+}
+
diff --git a/liblfds/test/src/test_ringbuffer.c b/liblfds/test/src/test_ringbuffer.c
new file mode 100644
index 0000000..431f84c
--- /dev/null
+++ b/liblfds/test/src/test_ringbuffer.c
@@ -0,0 +1,467 @@
+#include "internal.h"
+
+
+
+
+
+/****************************************************************************/
+void test_ringbuffer( void )
+{
+  printf( "\n"
+          "Ringbuffer Tests\n"
+          "================\n" );
+
+  ringbuffer_test_reading();
+  ringbuffer_test_writing();
+  ringbuffer_test_reading_and_writing();
+
+  return;
+}
+
+
+
+
+
+/****************************************************************************/
+void ringbuffer_test_reading( void )
+{
+  unsigned int
+    loop,
+    cpu_count;
+
+  thread_state_t
+    *thread_handles;
+
+  struct ringbuffer_state
+    *rs;
+
+  struct freelist_element
+    *fe;
+
+  struct ringbuffer_test_reading_state
+    *rtrs;
+
+  struct validation_info
+    vi = { 0, 0 };
+
+  enum data_structure_validity
+    dvs[3];
+
+  atom_t
+    total_read = 0;
+
+  /* TRD : we create a single ringbuffer
+           with 1,000,000 elements
+           we populate the ringbuffer, where the
+           user data is an incrementing counter
+
+           we create one thread per CPU
+           where each thread busy-works,
+           reading until the ringbuffer is empty
+
+           each thread keep track of the number of reads it manages
+           and that each user data it reads is greater than the
+           previous user data that was read
+  */
+
+  internal_display_test_name( "Reading" );
+
+  cpu_count = abstraction_cpu_count();
+
+  ringbuffer_new( &rs, 1000000, NULL, NULL );
+
+  for( loop = 0 ; loop < 1000000 ; loop++ )
+  {
+    ringbuffer_get_write_element( rs, &fe, NULL );
+    freelist_set_user_data_in_element( fe, (void *) (atom_t) loop );
+    ringbuffer_put_write_element( rs, fe );
+  }
+
+  rtrs = malloc( sizeof(struct ringbuffer_test_reading_state) * cpu_count );
+
+  for( loop = 0 ; loop < cpu_count ; loop++ )
+  {
+    (rtrs+loop)->rs = rs;
+    (rtrs+loop)->read_count = 0;
+    (rtrs+loop)->error_flag = LOWERED;
+  }
+
+  thread_handles = malloc( sizeof(thread_state_t) * cpu_count );
+
+  for( loop = 0 ; loop < cpu_count ; loop++ )
+    abstraction_thread_start( &thread_handles[loop], loop, ringbuffer_test_thread_simple_reader, rtrs+loop );
+
+  for( loop = 0 ; loop < cpu_count ; loop++ )
+    abstraction_thread_wait( thread_handles[loop] );
+
+  free( thread_handles );
+
+  ringbuffer_query( rs, RINGBUFFER_QUERY_VALIDATE, (void *) &vi, (void *) dvs );
+
+  // TRD : check for raised error flags
+  for( loop = 0 ; loop < cpu_count ; loop++ )
+    if( (rtrs+loop)->error_flag == RAISED )
+      dvs[0] = VALIDITY_INVALID_TEST_DATA;
+
+  // TRD : check thread reads total to 1,000,000
+  for( loop = 0 ; loop < cpu_count ; loop++ )
+    total_read += (rtrs+loop)->read_count;
+
+  if( total_read < 1000000 )
+    dvs[0] = VALIDITY_INVALID_MISSING_ELEMENTS;
+
+  if( total_read > 1000000 )
+    dvs[0] = VALIDITY_INVALID_ADDITIONAL_ELEMENTS;
+
+  free( rtrs );
+
+  ringbuffer_delete( rs, NULL, NULL );
+
+  internal_display_test_result( 3, "queue", dvs[0], "queue freelist", dvs[1], "freelist", dvs[2] );
+
+  return;
+}
+
+
+
+
+
+/****************************************************************************/
+thread_return_t CALLING_CONVENTION ringbuffer_test_thread_simple_reader( void *ringbuffer_test_reading_state )
+{
+  struct ringbuffer_test_reading_state
+    *rtrs;
+
+  struct freelist_element
+    *fe;
+
+  atom_t
+    *prev_user_data,
+    *user_data;
+
+  assert( ringbuffer_test_reading_state != NULL );
+
+  rtrs = (struct ringbuffer_test_reading_state *) ringbuffer_test_reading_state;
+
+  ringbuffer_get_read_element( rtrs->rs, &fe );
+  freelist_get_user_data_from_element( fe, (void **) &prev_user_data );
+  ringbuffer_put_read_element( rtrs->rs, fe );
+
+  rtrs->read_count++;
+
+  while( ringbuffer_get_read_element(rtrs->rs, &fe) )
+  {
+    freelist_get_user_data_from_element( fe, (void **) &user_data );
+    ringbuffer_put_read_element( rtrs->rs, fe );
+
+    if( user_data <= prev_user_data )
+      rtrs->error_flag = RAISED;
+
+    prev_user_data = user_data;
+
+    rtrs->read_count++;
+  }
+
+  return( (thread_return_t) EXIT_SUCCESS );
+}
+
+
+
+
+
+/****************************************************************************/
+void ringbuffer_test_writing( void )
+{
+  unsigned int
+    loop,
+    cpu_count;
+
+  thread_state_t
+    *thread_handles;
+
+  struct ringbuffer_state
+    *rs;
+
+  struct freelist_element
+    *fe;
+
+  struct ringbuffer_test_writing_state
+    *rtws;
+
+  struct validation_info
+    vi = { 100000, 100000 };
+
+  enum data_structure_validity
+    dvs[3];
+
+  atom_t
+    thread,
+    count,
+    user_data,
+    *per_thread_counters;
+
+  /* TRD : we create a single ringbuffer
+           with 100000 elements
+           the ringbuffers starts empty
+
+           we create one thread per CPU
+           where each thread busy-works writing
+           for ten seconds
+
+           the user data in each written element is a combination
+           of the thread number and the counter
+
+           after the threads are complete, we validate by
+           checking the user data counters increment on a per thread
+           basis
+  */
+
+  internal_display_test_name( "Writing (10 seconds)" );
+
+  cpu_count = abstraction_cpu_count();
+
+  ringbuffer_new( &rs, 100000, NULL, NULL );
+
+  rtws = malloc( sizeof(struct ringbuffer_test_writing_state) * cpu_count );
+
+  for( loop = 0 ; loop < cpu_count ; loop++ )
+  {
+    (rtws+loop)->rs = rs;
+    (rtws+loop)->write_count = (atom_t) loop << (sizeof(atom_t)*8-8);
+  }
+
+  thread_handles = malloc( sizeof(thread_state_t) * cpu_count );
+
+  for( loop = 0 ; loop < cpu_count ; loop++ )
+    abstraction_thread_start( &thread_handles[loop], loop, ringbuffer_test_thread_simple_writer, rtws+loop );
+
+  for( loop = 0 ; loop < cpu_count ; loop++ )
+    abstraction_thread_wait( thread_handles[loop] );
+
+  free( thread_handles );
+
+  // TRD : now check results
+  per_thread_counters = malloc( sizeof(atom_t) * cpu_count );
+
+  for( loop = 0 ; loop < cpu_count ; loop++ )
+    *(per_thread_counters+loop) = 0;
+
+  ringbuffer_query( rs, RINGBUFFER_QUERY_VALIDATE, (void *) &vi, (void *) dvs );
+
+  while( dvs[0] == VALIDITY_VALID and dvs[1] == VALIDITY_VALID and dvs[2] == VALIDITY_VALID and ringbuffer_get_read_element(rs, &fe) )
+  {
+    freelist_get_user_data_from_element( fe, (void *) &user_data );
+
+    thread = user_data >> (sizeof(atom_t)*8-8);
+    count = (user_data << 8) >> 8;
+
+    if( thread >= cpu_count )
+    {
+      dvs[0] = VALIDITY_INVALID_TEST_DATA;
+      ringbuffer_put_read_element( rs, fe );
+      break;
+    }
+
+    if( per_thread_counters[thread] == 0 )
+      per_thread_counters[thread] = count;
+
+    if( count < per_thread_counters[thread] )
+      dvs[0] = VALIDITY_INVALID_ADDITIONAL_ELEMENTS;
+
+    if( count >= per_thread_counters[thread] )
+      per_thread_counters[thread] = count+1;
+
+    ringbuffer_put_read_element( rs, fe );
+  }
+
+  free( per_thread_counters );
+
+  free( rtws );
+
+  ringbuffer_delete( rs, NULL, NULL );
+
+  internal_display_test_result( 3, "queue", dvs[0], "queue freelist", dvs[1], "freelist", dvs[2] );
+
+  return;
+}
+
+
+
+
+
+/****************************************************************************/
+thread_return_t CALLING_CONVENTION ringbuffer_test_thread_simple_writer( void *ringbuffer_test_writing_state )
+{
+  struct ringbuffer_test_writing_state
+    *rtws;
+
+  struct freelist_element
+    *fe;
+
+  time_t
+    start_time;
+
+  assert( ringbuffer_test_writing_state != NULL );
+
+  rtws = (struct ringbuffer_test_writing_state *) ringbuffer_test_writing_state;
+
+  time( &start_time );
+
+  while( time(NULL) < start_time + 10 )
+  {
+    ringbuffer_get_write_element( rtws->rs, &fe, NULL );
+    freelist_set_user_data_in_element( fe, (void *) (atom_t) (rtws->write_count++) );
+    ringbuffer_put_write_element( rtws->rs, fe );
+  }
+
+  return( (thread_return_t) EXIT_SUCCESS );
+}
+
+
+
+
+
+/****************************************************************************/
+void ringbuffer_test_reading_and_writing( void )
+{
+  unsigned int
+    loop,
+    subloop,
+    cpu_count;
+
+  thread_state_t
+    *thread_handles;
+
+  struct ringbuffer_state
+    *rs;
+
+  struct ringbuffer_test_reading_and_writing_state
+    *rtrws;
+
+  struct validation_info
+    vi = { 0, 0 };
+
+  enum data_structure_validity
+    dvs[3];
+
+  /* TRD : we create a single ringbuffer
+           with 100000 elements
+           the ringbuffers starts empty
+
+           we create one thread per CPU
+           where each thread busy-works writing
+           and then immediately reading
+           for ten seconds
+
+           the user data in each written element is a combination
+           of the thread number and the counter
+
+           while a thread runs, it keeps track of the
+           counters for the other threads and throws an error
+           if it sees the number stay the same or decrease
+  */
+
+  internal_display_test_name( "Reading and writing (10 seconds)" );
+
+  cpu_count = abstraction_cpu_count();
+
+  ringbuffer_new( &rs, 100000, NULL, NULL );
+
+  rtrws = malloc( sizeof(struct ringbuffer_test_reading_and_writing_state) * cpu_count );
+
+  for( loop = 0 ; loop < cpu_count ; loop++ )
+  {
+    (rtrws+loop)->rs = rs;
+    (rtrws+loop)->counter = (atom_t) loop << (sizeof(atom_t)*8-8);
+    (rtrws+loop)->cpu_count = cpu_count;
+    (rtrws+loop)->error_flag = LOWERED;
+    (rtrws+loop)->per_thread_counters = malloc( sizeof(atom_t) * cpu_count );
+
+    for( subloop = 0 ; subloop < cpu_count ; subloop++ )
+      *((rtrws+loop)->per_thread_counters+subloop) = 0;
+  }
+
+  thread_handles = malloc( sizeof(thread_state_t) * cpu_count );
+
+  for( loop = 0 ; loop < cpu_count ; loop++ )
+    abstraction_thread_start( &thread_handles[loop], loop, ringbuffer_test_thread_reader_writer, rtrws+loop );
+
+  for( loop = 0 ; loop < cpu_count ; loop++ )
+    abstraction_thread_wait( thread_handles[loop] );
+
+  free( thread_handles );
+
+  ringbuffer_query( rs, RINGBUFFER_QUERY_VALIDATE, (void *) &vi, (void *) dvs );
+
+  for( loop = 0 ; loop < cpu_count ; loop++ )
+    if( (rtrws+loop)->error_flag == RAISED )
+      dvs[0] = VALIDITY_INVALID_TEST_DATA;
+
+  for( loop = 0 ; loop < cpu_count ; loop++ )
+    free( (rtrws+loop)->per_thread_counters );
+
+  free( rtrws );
+
+  ringbuffer_delete( rs, NULL, NULL );
+
+  internal_display_test_result( 3, "queue", dvs[0], "queue freelist", dvs[1], "freelist", dvs[2] );
+
+  return;
+}
+
+
+
+
+
+/****************************************************************************/
+thread_return_t CALLING_CONVENTION ringbuffer_test_thread_reader_writer( void *ringbuffer_test_reading_and_writing_state )
+{
+  struct ringbuffer_test_reading_and_writing_state
+    *rtrws;
+
+  struct freelist_element
+    *fe;
+
+  atom_t
+    user_data,
+    thread,
+    count;
+
+  time_t
+    start_time;
+
+  assert( ringbuffer_test_reading_and_writing_state != NULL );
+
+  rtrws = (struct ringbuffer_test_reading_and_writing_state *) ringbuffer_test_reading_and_writing_state;
+
+  time( &start_time );
+
+  while( time(NULL) < start_time + 10 )
+  {
+    ringbuffer_get_write_element( rtrws->rs, &fe, NULL );
+    freelist_set_user_data_in_element( fe, (void *) (atom_t) (rtrws->counter++) );
+    ringbuffer_put_write_element( rtrws->rs, fe );
+
+    ringbuffer_get_read_element( rtrws->rs, &fe );
+    freelist_get_user_data_from_element( fe, (void *) &user_data );
+
+    thread = user_data >> (sizeof(atom_t)*8-8);
+    count = (user_data << 8) >> 8;
+
+    if( thread >= rtrws->cpu_count )
+      rtrws->error_flag = RAISED;
+    else
+    {
+      if( count < rtrws->per_thread_counters[thread] )
+        rtrws->error_flag = RAISED;
+
+      if( count >= rtrws->per_thread_counters[thread] )
+        rtrws->per_thread_counters[thread] = count+1;
+    }
+
+    ringbuffer_put_read_element( rtrws->rs, fe );
+  }
+
+  return( (thread_return_t) EXIT_SUCCESS );
+}
+
diff --git a/liblfds/test/src/test_slist.c b/liblfds/test/src/test_slist.c
new file mode 100644
index 0000000..26241c3
--- /dev/null
+++ b/liblfds/test/src/test_slist.c
@@ -0,0 +1,513 @@
+#include "internal.h"
+
+
+
+
+
+/****************************************************************************/
+void test_slist( void )
+{
+  unsigned int
+    loop,
+    cpu_count;
+
+  thread_state_t
+    *thread_handles;
+
+  struct slist_thread_start_state
+    stss;
+
+  /* TRD : 1. one head writer per CPU
+           2. make one element, then one after writer per CPU
+           3. make a list, then one list traverser per CPU
+           4. one head writer and one list traverser per CPU
+           5. make one element, then one after writer and one list traverser per CPU
+           6. make a list, then one 100% deleter-traverser per CPU
+           7. make a list, then one 25% deleter-traverser per CPU
+           8. one head writer and one 100% deleter-traverse per CPU
+           9. one head writer and one 25% deleter-traverse per CPU
+           10. make one element, then one after writer and one 100% deleter-traverser per CPU
+           11. make one element, then one after writer and one 25% deleter-traverser per CPU
+           12. one head writer, one after writer, one traverser and one 25% deleter-traverser per CPU
+  */
+
+  cpu_count = abstraction_cpu_count();
+
+  printf( "\n"
+          "SList Test\n"
+          "==========\n" );
+
+  // TRD : 1. one head writer per CPU
+
+  printf( "\n"
+          "1. one head writer per CPU\n"
+          "==========================\n" );
+
+  slist_new( &stss.ss, NULL, NULL );
+  stss.iteration_modulo = 1;
+  stss.se = NULL;
+  stss.duration = 1;
+
+  thread_handles = (thread_state_t *) malloc( sizeof(thread_state_t) * cpu_count * 1 );
+
+  for( loop = 0 ; loop < cpu_count ; loop++ )
+    abstraction_thread_start( &thread_handles[loop], loop, slist_internal_thread_head_writer, &stss );
+
+  for( loop = 0 ; loop < cpu_count ; loop++ )
+    abstraction_thread_wait( thread_handles[loop] );
+
+  slist_delete( stss.ss );
+
+  free( thread_handles );
+
+  // TRD : 2. make one element, then one after writer per CPU
+
+  printf( "\n"
+          "2. make one element, then one after writer per CPU\n"
+          "==================================================\n" );
+
+  slist_new( &stss.ss, NULL, NULL );
+  stss.iteration_modulo = 1;
+  stss.se = slist_new_head( stss.ss, (void *) NULL );
+  stss.duration = 1;
+
+  thread_handles = (thread_state_t *) malloc( sizeof(thread_state_t) * cpu_count * 1 );
+
+  for( loop = 0 ; loop < cpu_count ; loop++ )
+    abstraction_thread_start( &thread_handles[loop], loop, slist_internal_thread_after_writer, &stss );
+
+  for( loop = 0 ; loop < cpu_count ; loop++ )
+    abstraction_thread_wait( thread_handles[loop] );
+
+  slist_delete( stss.ss );
+
+  free( thread_handles );
+
+  // TRD : 3. make a list, then one list traverser per CPU
+
+  printf( "\n"
+          "3. make a list, then one list traverser per CPU\n"
+          "===============================================\n" );
+
+  slist_new( &stss.ss, NULL, NULL );
+  stss.iteration_modulo = 1;
+  stss.se = NULL;
+  stss.duration = 10;
+
+  // TRD : small list so we get collisions
+  for( loop = 0 ; loop < 10 ; loop++ )
+    slist_new_head( stss.ss, (void *) 0 );
+
+  thread_handles = (thread_state_t *) malloc( sizeof(thread_state_t) * cpu_count * 1 );
+
+  for( loop = 0 ; loop < cpu_count ; loop++ )
+    abstraction_thread_start( &thread_handles[loop], loop, slist_internal_thread_traverser, &stss );
+
+  for( loop = 0 ; loop < cpu_count ; loop++ )
+    abstraction_thread_wait( thread_handles[loop] );
+
+  slist_delete( stss.ss );
+
+  free( thread_handles );
+
+  // TRD : 4. one head writer and one list traverser per CPU
+
+  printf( "\n"
+          "4. one head writer and one list traverser per CPU\n"
+          "=================================================\n" );
+
+  slist_new( &stss.ss, NULL, NULL );
+  stss.iteration_modulo = 1;
+  stss.se = NULL;
+  stss.duration = 1;
+
+  thread_handles = (thread_state_t *) malloc( sizeof(thread_state_t) * cpu_count * 2 );
+
+  for( loop = 0 ; loop < cpu_count ; loop++ )\
+  {
+    abstraction_thread_start( &thread_handles[loop], loop, slist_internal_thread_head_writer, &stss );
+    abstraction_thread_start( &thread_handles[loop+cpu_count], loop, slist_internal_thread_traverser, &stss );
+  }
+
+  for( loop = 0 ; loop < cpu_count * 2 ; loop++ )
+    abstraction_thread_wait( thread_handles[loop] );
+
+  slist_delete( stss.ss );
+
+  free( thread_handles );
+
+  // TRD : 5. make one element, then one after writer and one list traverser per CPU
+
+  printf( "\n"
+          "5. make one element, then one after writer and one list traverser per CPU\n"
+          "=========================================================================\n" );
+
+  slist_new( &stss.ss, NULL, NULL );
+  stss.iteration_modulo = 1;
+  stss.se = slist_new_head( stss.ss, (void *) NULL );
+  stss.duration = 1;
+
+  thread_handles = (thread_state_t *) malloc( sizeof(thread_state_t) * cpu_count * 2 );
+
+  for( loop = 0 ; loop < cpu_count ; loop++ )\
+  {
+    abstraction_thread_start( &thread_handles[loop], loop, slist_internal_thread_after_writer, &stss );
+    abstraction_thread_start( &thread_handles[loop+cpu_count], loop, slist_internal_thread_traverser, &stss );
+  }
+
+  for( loop = 0 ; loop < cpu_count * 2 ; loop++ )
+    abstraction_thread_wait( thread_handles[loop] );
+
+  slist_delete( stss.ss );
+
+  free( thread_handles );
+
+  // TRD : 6. make a list, then one 100% deleter-traverser per CPU
+
+  printf( "\n"
+          "6. make a list, then one 100%% deleter-traverser per CPU\n"
+          "=======================================================\n" );
+
+  slist_new( &stss.ss, NULL, NULL );
+  stss.iteration_modulo = 1;
+  stss.se = NULL;
+  stss.duration = 1;
+
+  for( loop = 0 ; loop < 10000 ; loop++ )
+    slist_new_head( stss.ss, (void *) 0 );
+
+  thread_handles = (thread_state_t *) malloc( sizeof(thread_state_t) * cpu_count * 1 );
+
+  for( loop = 0 ; loop < cpu_count ; loop++ )
+    abstraction_thread_start( &thread_handles[loop], loop, slist_internal_thread_deleter_traverser, &stss );
+
+  for( loop = 0 ; loop < cpu_count ; loop++ )
+    abstraction_thread_wait( thread_handles[loop] );
+
+  slist_delete( stss.ss );
+
+  free( thread_handles );
+
+  // TRD : 7. make a list, then one 25% deleter-traverser per CPU
+
+  printf( "\n"
+          "7. make a list, then one 25%% deleter-traverser per CPU\n"
+          "======================================================\n" );
+
+  slist_new( &stss.ss, NULL, NULL );
+  stss.iteration_modulo = 4;
+  stss.se = NULL;
+  stss.duration = 1;
+
+  for( loop = 0 ; loop < 10000 ; loop++ )
+    slist_new_head( stss.ss, (void *) 0 );
+
+  thread_handles = (thread_state_t *) malloc( sizeof(thread_state_t) * cpu_count * 1 );
+
+  for( loop = 0 ; loop < cpu_count ; loop++ )
+    abstraction_thread_start( &thread_handles[loop], loop, slist_internal_thread_deleter_traverser, &stss );
+
+  for( loop = 0 ; loop < cpu_count ; loop++ )
+    abstraction_thread_wait( thread_handles[loop] );
+
+  slist_delete( stss.ss );
+
+  free( thread_handles );
+
+  // TRD : 8. one head writer and one 100% deleter-traverse per CPU
+
+  printf( "\n"
+          "8. one head writer and one 100%% deleter-traverse per CPU\n"
+          "========================================================\n" );
+
+  slist_new( &stss.ss, NULL, NULL );
+  stss.iteration_modulo = 1;
+  stss.se = NULL;
+  stss.duration = 10;
+
+  thread_handles = (thread_state_t *) malloc( sizeof(thread_state_t) * cpu_count * 2 );
+
+  for( loop = 0 ; loop < cpu_count ; loop++ )
+  {
+    abstraction_thread_start( &thread_handles[loop], loop, slist_internal_thread_head_writer, &stss );
+    abstraction_thread_start( &thread_handles[loop+cpu_count], loop, slist_internal_thread_deleter_traverser, &stss );
+  }
+
+  for( loop = 0 ; loop < cpu_count * 2 ; loop++ )
+    abstraction_thread_wait( thread_handles[loop] );
+
+  slist_delete( stss.ss );
+
+  free( thread_handles );
+
+  // TRD : 9. one head writer and one 25% deleter-traverse per CPU
+
+  printf( "\n"
+          "9. one head writer and one 25%% deleter-traverse per CPU\n"
+          "=======================================================\n" );
+
+  slist_new( &stss.ss, NULL, NULL );
+  stss.iteration_modulo = 4;
+  stss.se = NULL;
+  stss.duration = 1;
+
+  thread_handles = (thread_state_t *) malloc( sizeof(thread_state_t) * cpu_count * 2 );
+
+  for( loop = 0 ; loop < cpu_count ; loop++ )
+  {
+    abstraction_thread_start( &thread_handles[loop], loop, slist_internal_thread_head_writer, &stss );
+    abstraction_thread_start( &thread_handles[loop+cpu_count], loop, slist_internal_thread_deleter_traverser, &stss );
+  }
+
+  for( loop = 0 ; loop < cpu_count * 2 ; loop++ )
+    abstraction_thread_wait( thread_handles[loop] );
+
+  slist_delete( stss.ss );
+
+  free( thread_handles );
+
+  // TRD : 10. make one element, then one after writer and one 100% deleter-traverser per CPU
+
+  printf( "\n"
+          "10. make one element, then one after writer and one 100%% deleter-traverser per CPU\n"
+          "==================================================================================\n" );
+
+  slist_new( &stss.ss, NULL, NULL );
+  stss.iteration_modulo = 1;
+  stss.se = slist_new_head( stss.ss, (void *) NULL );
+  stss.duration = 10;
+
+  thread_handles = (thread_state_t *) malloc( sizeof(thread_state_t) * cpu_count * 2 );
+
+  for( loop = 0 ; loop < cpu_count ; loop++ )
+  {
+    abstraction_thread_start( &thread_handles[loop], loop, slist_internal_thread_after_writer, &stss );
+    abstraction_thread_start( &thread_handles[loop+cpu_count], loop, slist_internal_thread_deleter_traverser, &stss );
+  }
+
+  for( loop = 0 ; loop < cpu_count * 2 ; loop++ )
+    abstraction_thread_wait( thread_handles[loop] );
+
+  slist_delete( stss.ss );
+
+  free( thread_handles );
+
+  // TRD : 11. make one element, then one after writer and one 25% deleter-traverser per CPU
+
+  printf( "\n"
+          "11. make one element, then one after writer and one 25%% deleter-traverser per CPU\n"
+          "=================================================================================\n" );
+
+  slist_new( &stss.ss, NULL, NULL );
+  stss.iteration_modulo = 4;
+  stss.se = slist_new_head( stss.ss, (void *) NULL );
+  stss.duration = 1;
+
+  thread_handles = (thread_state_t *) malloc( sizeof(thread_state_t) * cpu_count * 2 );
+
+  for( loop = 0 ; loop < cpu_count ; loop++ )
+  {
+    abstraction_thread_start( &thread_handles[loop], loop, slist_internal_thread_after_writer, &stss );
+    abstraction_thread_start( &thread_handles[loop+cpu_count], loop, slist_internal_thread_deleter_traverser, &stss );
+  }
+
+  for( loop = 0 ; loop < cpu_count * 2 ; loop++ )
+    abstraction_thread_wait( thread_handles[loop] );
+
+  slist_delete( stss.ss );
+
+  free( thread_handles );
+
+  // TRD : 12. one head writer, one after writer, one traverser and one 25% deleter-traverser per CPU
+
+  printf( "\n"
+          "12. one head writer, one after writer, one traverser and one 25%% deleter-traverser per CPU\n"
+          "==========================================================================================\n" );
+
+  slist_new( &stss.ss, NULL, NULL );
+  stss.iteration_modulo = 4;
+  stss.se = slist_new_head( stss.ss, (void *) NULL );
+  stss.duration = 1;
+
+  thread_handles = (thread_state_t *) malloc( sizeof(thread_state_t) * cpu_count * 4 );
+
+  for( loop = 0 ; loop < cpu_count ; loop++ )
+  {
+    abstraction_thread_start( &thread_handles[loop], loop, slist_internal_thread_head_writer, &stss );
+    abstraction_thread_start( &thread_handles[loop+cpu_count], loop, slist_internal_thread_after_writer, &stss );
+    abstraction_thread_start( &thread_handles[loop+cpu_count*2], loop, slist_internal_thread_traverser, &stss );
+    abstraction_thread_start( &thread_handles[loop+cpu_count*3], loop, slist_internal_thread_deleter_traverser, &stss );
+  }
+
+  for( loop = 0 ; loop < cpu_count * 4 ; loop++ )
+    abstraction_thread_wait( thread_handles[loop] );
+
+  slist_delete( stss.ss );
+
+  free( thread_handles );
+
+  return;
+}
+
+
+
+
+
+/****************************************************************************/
+thread_return_t CALLING_CONVENTION slist_internal_thread_head_writer( void *slist_thread_start_state )
+{
+  struct slist_thread_start_state
+    *stss;
+
+  time_t
+    start_time;
+
+  unsigned long int
+    count = 0;
+
+  assert( slist_thread_start_state != NULL );
+
+  stss = (struct slist_thread_start_state *) slist_thread_start_state;
+
+  time( &start_time );
+
+  while( time(NULL) < start_time + stss->duration )
+    if( slist_new_head(stss->ss, (void *) 0) )
+      count++;
+
+  printf( "head writer count = %lu\n", count );
+
+  return( (thread_return_t) EXIT_SUCCESS );
+}
+
+
+
+
+
+/****************************************************************************/
+thread_return_t CALLING_CONVENTION slist_internal_thread_after_writer( void *slist_thread_start_state )
+{
+  struct slist_thread_start_state
+    *stss;
+
+  time_t
+    start_time;
+
+  unsigned long int
+    count = 0;
+
+  assert( slist_thread_start_state != NULL );
+
+  stss = (struct slist_thread_start_state *) slist_thread_start_state;
+
+  time( &start_time );
+
+  while( time(NULL) < start_time + stss->duration )
+    if( slist_new_next(stss->se, (void *) 0) )
+      count++;
+
+  printf( "after writer count = %lu\n", count );
+
+  return( (thread_return_t) EXIT_SUCCESS );
+}
+
+
+
+
+
+/****************************************************************************/
+thread_return_t CALLING_CONVENTION slist_internal_thread_traverser( void *slist_thread_start_state )
+{
+  struct slist_thread_start_state
+    *stss;
+
+  time_t
+    start_time;
+
+  unsigned long int
+    count = 0,
+    iteration = 0;
+
+  struct slist_element
+    *se;
+
+  assert( slist_thread_start_state != NULL );
+
+  stss = (struct slist_thread_start_state *) slist_thread_start_state;
+
+  time( &start_time );
+
+  slist_get_head( stss->ss, &se );
+
+  while( time(NULL) < start_time + stss->duration )
+  {
+    if( !(iteration % stss->iteration_modulo) )
+    {
+      slist_get_next( se, &se );
+      count++;
+    }
+
+    if( se == NULL )
+    {
+      slist_get_head( stss->ss, &se );
+      count++;
+    }
+
+    iteration++;
+  }
+
+  printf( "traverser count = %lu\n", count );
+
+  return( (thread_return_t) EXIT_SUCCESS );
+}
+
+
+
+
+
+/****************************************************************************/
+thread_return_t CALLING_CONVENTION slist_internal_thread_deleter_traverser( void *slist_thread_start_state )
+{
+  struct slist_thread_start_state
+    *stss;
+
+  time_t
+    start_time;
+
+  unsigned long int
+    count = 0,
+    iteration = 0;
+
+  struct slist_element
+    *se;
+
+  assert( slist_thread_start_state != NULL );
+
+  stss = (struct slist_thread_start_state *) slist_thread_start_state;
+
+  time( &start_time );
+
+  slist_get_head( stss->ss, &se );
+
+  while( time(NULL) < start_time + stss->duration )
+  {
+    if( se != NULL and !(iteration % stss->iteration_modulo) )
+    {
+      slist_delete_element( stss->ss, se );
+      count++;
+    }
+
+    if( se != NULL )
+      slist_get_next( se, &se );
+
+    if( se == NULL )
+      slist_get_head( stss->ss, &se );
+
+    iteration++;
+  }
+
+  printf( "deleter-traverser count = %lu\n", count );
+
+  return( (thread_return_t) EXIT_SUCCESS );
+}
+
diff --git a/liblfds/test/src/test_stack.c b/liblfds/test/src/test_stack.c
new file mode 100644
index 0000000..446da25
--- /dev/null
+++ b/liblfds/test/src/test_stack.c
@@ -0,0 +1,223 @@
+#include "internal.h"
+
+
+
+
+
+/****************************************************************************/
+void test_stack( void )
+{
+  unsigned int
+    loop,
+    cpu_count;
+
+  struct stack_state
+    *ss;
+
+  thread_state_t
+    *thread_handles;
+
+  /* TRD : there are 5 tests
+
+           1. single reader thread per CPU
+              - stack always empty
+           2. single writer thread per CPU
+              - stack always full
+           3. one reader and one writer thread per CPU
+              - stack balanced
+           4. one reader and two writer threads per CPU
+              - stack grows
+           5. two reader and one writer thread per CPU
+              - stack tends to empty
+  */
+
+  cpu_count = abstraction_cpu_count();
+
+  printf( "\n"
+          "Stack Test\n"
+          "==========\n" );
+
+  // TRD : 1. single reader thread per CPU
+
+  printf( "\n"
+          "1. single reader thread per CPU\n"
+          "===============================\n" );
+
+  stack_new( &ss, 10000 );
+
+  thread_handles = (thread_state_t *) malloc( sizeof(thread_state_t) * cpu_count * 1 );
+
+  for( loop = 0 ; loop < cpu_count ; loop++ )
+    abstraction_thread_start( &thread_handles[loop], loop, stack_internal_thread_reader, ss );
+
+  for( loop = 0 ; loop < cpu_count ; loop++ )
+    abstraction_thread_wait( thread_handles[loop] );
+
+  stack_delete( ss, NULL, NULL );
+
+  free( thread_handles );
+
+  // TRD : 2. single writer thread per CPU
+
+  printf( "\n"
+          "2. single writer thread per CPU\n"
+          "===============================\n" );
+
+  stack_new( &ss, 10000 );
+
+  thread_handles = (thread_state_t *) malloc( sizeof(thread_state_t) * cpu_count * 1 );
+
+  for( loop = 0 ; loop < cpu_count ; loop++ )
+    abstraction_thread_start( &thread_handles[loop], loop, stack_internal_thread_writer, ss );
+
+  for( loop = 0 ; loop < cpu_count ; loop++ )
+    abstraction_thread_wait( thread_handles[loop] );
+
+  stack_delete( ss, NULL, NULL );
+
+  free( thread_handles );
+
+  // TRD : 3. one reader and one writer thread per CPU
+
+  printf( "\n"
+          "3. one reader and one writer thread per CPU\n"
+          "===========================================\n" );
+
+  stack_new( &ss, 10000 );
+
+  thread_handles = (thread_state_t *) malloc( sizeof(thread_state_t) * cpu_count * 2 );
+
+  for( loop = 0 ; loop < cpu_count ; loop++ )
+  {
+    abstraction_thread_start( &thread_handles[loop], loop, stack_internal_thread_reader, ss );
+    abstraction_thread_start( &thread_handles[loop+cpu_count], loop, stack_internal_thread_writer, ss );
+  }
+
+  for( loop = 0 ; loop < cpu_count * 2 ; loop++ )
+    abstraction_thread_wait( thread_handles[loop] );
+
+  stack_delete( ss, NULL, NULL );
+
+  free( thread_handles );
+
+  // TRD : 4. one reader and two writer threads per CPU
+
+  printf( "\n"
+          "4. one reader and two writer threads per CPU\n"
+          "============================================\n" );
+
+  stack_new( &ss, 10000 );
+
+  thread_handles = (thread_state_t *) malloc( sizeof(thread_state_t) * cpu_count * 3 );
+
+  for( loop = 0 ; loop < cpu_count ; loop++ )
+  {
+    abstraction_thread_start( &thread_handles[loop], loop, stack_internal_thread_reader, ss );
+    abstraction_thread_start( &thread_handles[loop+cpu_count], loop, stack_internal_thread_writer, ss );
+    abstraction_thread_start( &thread_handles[loop+cpu_count*2], loop, stack_internal_thread_writer, ss );
+  }
+
+  for( loop = 0 ; loop < cpu_count * 3 ; loop++ )
+    abstraction_thread_wait( thread_handles[loop] );
+
+  stack_delete( ss, NULL, NULL );
+
+  free( thread_handles );
+
+  // TRD : 5. two reader and one writer thread per CPU
+
+  printf( "\n"
+          "5. two reader and one writer thread per CPU\n"
+          "===========================================\n" );
+
+  stack_new( &ss, 10000 );
+
+  thread_handles = (thread_state_t *) malloc( sizeof(thread_state_t) * cpu_count * 3 );
+
+  for( loop = 0 ; loop < cpu_count ; loop++ )
+  {
+    abstraction_thread_start( &thread_handles[loop], loop, stack_internal_thread_reader, ss );
+    abstraction_thread_start( &thread_handles[loop+cpu_count], loop, stack_internal_thread_reader, ss );
+    abstraction_thread_start( &thread_handles[loop+cpu_count*2], loop, stack_internal_thread_writer, ss );
+  }
+
+  for( loop = 0 ; loop < cpu_count * 3 ; loop++ )
+    abstraction_thread_wait( thread_handles[loop] );
+
+  stack_delete( ss, NULL, NULL );
+
+  free( thread_handles );
+
+  return;
+}
+
+
+
+
+
+/****************************************************************************/
+thread_return_t CALLING_CONVENTION stack_internal_thread_reader( void *stack_state )
+{
+  struct stack_state
+    *ss;
+
+  void
+    *user_data;
+
+  time_t
+    start_time;
+
+  unsigned long long int
+    count = 0;
+
+  assert( stack_state != NULL );
+
+  ss = (struct stack_state *) stack_state;
+
+  time( &start_time );
+
+  while( time(NULL) < start_time + 10 )
+  {
+    if( stack_pop(ss, &user_data) )
+      count++;
+  }
+
+  printf( "read count = %llu\n", count );
+
+  return( (thread_return_t) EXIT_SUCCESS );
+}
+
+
+
+
+
+/****************************************************************************/
+thread_return_t CALLING_CONVENTION stack_internal_thread_writer( void *stack_state )
+{
+  struct stack_state
+    *ss;
+
+  time_t
+    start_time;
+
+  unsigned long long int
+    count = 0;
+
+  assert( stack_state != NULL );
+
+  ss = (struct stack_state *) stack_state;
+
+  time( &start_time );
+
+  while( time(NULL) < start_time + 10 )
+  {
+    // TRD : we don't store any user data
+    if( stack_push(ss, NULL) )
+      count++;
+  }
+
+  printf( "write count = %llu\n", count );
+
+  return( (thread_return_t) EXIT_SUCCESS );
+}
+
diff --git a/liblfds/test/test.sln b/liblfds/test/test.sln
new file mode 100644
index 0000000..f8a8d04
--- /dev/null
+++ b/liblfds/test/test.sln
@@ -0,0 +1,39 @@
+﻿
+Microsoft Visual Studio Solution File, Format Version 10.00
+# Visual Studio 2008
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "test", "test.vcproj", "{6E4CBF20-DF1A-4FA0-8A90-58E2A3A5CF09}"
+	ProjectSection(ProjectDependencies) = postProject
+		{F73AE755-F6D8-4C3A-977D-FBB40DC0ED05} = {F73AE755-F6D8-4C3A-977D-FBB40DC0ED05}
+	EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "liblfds", "..\liblfds.vcproj", "{F73AE755-F6D8-4C3A-977D-FBB40DC0ED05}"
+EndProject
+Global
+	GlobalSection(SolutionConfigurationPlatforms) = preSolution
+		Debug|Win32 = Debug|Win32
+		Debug|x64 = Debug|x64
+		Release|Win32 = Release|Win32
+		Release|x64 = Release|x64
+	EndGlobalSection
+	GlobalSection(ProjectConfigurationPlatforms) = postSolution
+		{6E4CBF20-DF1A-4FA0-8A90-58E2A3A5CF09}.Debug|Win32.ActiveCfg = Debug|x64
+		{6E4CBF20-DF1A-4FA0-8A90-58E2A3A5CF09}.Debug|Win32.Build.0 = Debug|x64
+		{6E4CBF20-DF1A-4FA0-8A90-58E2A3A5CF09}.Debug|x64.ActiveCfg = Debug|x64
+		{6E4CBF20-DF1A-4FA0-8A90-58E2A3A5CF09}.Debug|x64.Build.0 = Debug|x64
+		{6E4CBF20-DF1A-4FA0-8A90-58E2A3A5CF09}.Release|Win32.ActiveCfg = Release|Win32
+		{6E4CBF20-DF1A-4FA0-8A90-58E2A3A5CF09}.Release|Win32.Build.0 = Release|Win32
+		{6E4CBF20-DF1A-4FA0-8A90-58E2A3A5CF09}.Release|x64.ActiveCfg = Release|x64
+		{6E4CBF20-DF1A-4FA0-8A90-58E2A3A5CF09}.Release|x64.Build.0 = Release|x64
+		{F73AE755-F6D8-4C3A-977D-FBB40DC0ED05}.Debug|Win32.ActiveCfg = Debug Lib|x64
+		{F73AE755-F6D8-4C3A-977D-FBB40DC0ED05}.Debug|Win32.Build.0 = Debug Lib|x64
+		{F73AE755-F6D8-4C3A-977D-FBB40DC0ED05}.Debug|x64.ActiveCfg = Debug Lib|x64
+		{F73AE755-F6D8-4C3A-977D-FBB40DC0ED05}.Debug|x64.Build.0 = Debug Lib|x64
+		{F73AE755-F6D8-4C3A-977D-FBB40DC0ED05}.Release|Win32.ActiveCfg = Release Lib|Win32
+		{F73AE755-F6D8-4C3A-977D-FBB40DC0ED05}.Release|Win32.Build.0 = Release Lib|Win32
+		{F73AE755-F6D8-4C3A-977D-FBB40DC0ED05}.Release|x64.ActiveCfg = Release Lib|x64
+		{F73AE755-F6D8-4C3A-977D-FBB40DC0ED05}.Release|x64.Build.0 = Release Lib|x64
+	EndGlobalSection
+	GlobalSection(SolutionProperties) = preSolution
+		HideSolutionNode = FALSE
+	EndGlobalSection
+EndGlobal
diff --git a/liblfds/test/test.vcproj b/liblfds/test/test.vcproj
new file mode 100644
index 0000000..9f7ef0a
--- /dev/null
+++ b/liblfds/test/test.vcproj
@@ -0,0 +1,415 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+	ProjectType="Visual C++"
+	Version="9.00"
+	Name="test"
+	ProjectGUID="{6E4CBF20-DF1A-4FA0-8A90-58E2A3A5CF09}"
+	RootNamespace="test"
+	TargetFrameworkVersion="196613"
+	>
+	<Platforms>
+		<Platform
+			Name="Win32"
+		/>
+		<Platform
+			Name="x64"
+		/>
+	</Platforms>
+	<ToolFiles>
+	</ToolFiles>
+	<Configurations>
+		<Configuration
+			Name="Debug|Win32"
+			OutputDirectory="$(ProjectDir)\bin\$(PlatformName)\$(ConfigurationName)"
+			IntermediateDirectory="$(ProjectDir)\obj\$(PlatformName)\$(ConfigurationName)"
+			ConfigurationType="1"
+			CharacterSet="1"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+				AdditionalOptions="/DWIN32_LEAN_AND_MEAN /D_DEBUG /D_CRT_SECURE_NO_WARNINGS"
+				Optimization="0"
+				EnableIntrinsicFunctions="true"
+				AdditionalIncludeDirectories="&quot;$(ProjectDir)\src&quot;;&quot;$(ProjectDir)\..\inc&quot;"
+				MinimalRebuild="true"
+				ExceptionHandling="0"
+				BasicRuntimeChecks="3"
+				RuntimeLibrary="1"
+				EnableFunctionLevelLinking="true"
+				BrowseInformation="1"
+				WarningLevel="4"
+				WarnAsError="true"
+				DebugInformationFormat="4"
+				CompileAs="1"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalDependencies="libcmtd.lib"
+				IgnoreAllDefaultLibraries="true"
+				GenerateDebugInformation="true"
+				SubSystem="1"
+				TargetMachine="1"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCManifestTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+			/>
+			<Tool
+				Name="VCFxCopTool"
+			/>
+			<Tool
+				Name="VCAppVerifierTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+			/>
+		</Configuration>
+		<Configuration
+			Name="Debug|x64"
+			OutputDirectory="$(ProjectDir)\bin\$(PlatformName)\$(ConfigurationName)"
+			IntermediateDirectory="$(ProjectDir)\obj\$(PlatformName)\$(ConfigurationName)"
+			ConfigurationType="1"
+			CharacterSet="1"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+				AdditionalOptions="/DWIN32_LEAN_AND_MEAN /D_DEBUG /D_CRT_SECURE_NO_WARNINGS"
+				Optimization="0"
+				EnableIntrinsicFunctions="true"
+				AdditionalIncludeDirectories="&quot;$(ProjectDir)\src&quot;;&quot;$(ProjectDir)\..\inc&quot;"
+				ExceptionHandling="0"
+				RuntimeLibrary="1"
+				EnableFunctionLevelLinking="true"
+				BrowseInformation="1"
+				WarningLevel="4"
+				WarnAsError="true"
+				DebugInformationFormat="3"
+				CompileAs="1"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalDependencies="libcmtd.lib"
+				IgnoreAllDefaultLibraries="true"
+				GenerateDebugInformation="true"
+				SubSystem="1"
+				TargetMachine="17"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCManifestTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+			/>
+			<Tool
+				Name="VCFxCopTool"
+			/>
+			<Tool
+				Name="VCAppVerifierTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+			/>
+		</Configuration>
+		<Configuration
+			Name="Release|Win32"
+			OutputDirectory="$(ProjectDir)\bin\$(PlatformName)\$(ConfigurationName)"
+			IntermediateDirectory="$(ProjectDir)\obj\$(PlatformName)\$(ConfigurationName)"
+			ConfigurationType="1"
+			CharacterSet="1"
+			WholeProgramOptimization="1"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+				AdditionalOptions="/DWIN32_LEAN_AND_MEAN /DNDEBUG /D_CRT_SECURE_NO_WARNINGS"
+				Optimization="3"
+				EnableIntrinsicFunctions="true"
+				FavorSizeOrSpeed="1"
+				AdditionalIncludeDirectories="&quot;$(ProjectDir)\src&quot;;&quot;$(ProjectDir)\..\inc&quot;"
+				ExceptionHandling="0"
+				RuntimeLibrary="0"
+				EnableFunctionLevelLinking="true"
+				WarningLevel="4"
+				WarnAsError="true"
+				DebugInformationFormat="0"
+				CompileAs="1"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalDependencies="libcmt.lib"
+				IgnoreAllDefaultLibraries="true"
+				GenerateDebugInformation="false"
+				SubSystem="1"
+				OptimizeReferences="2"
+				EnableCOMDATFolding="2"
+				TargetMachine="1"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCManifestTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+			/>
+			<Tool
+				Name="VCFxCopTool"
+			/>
+			<Tool
+				Name="VCAppVerifierTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+			/>
+		</Configuration>
+		<Configuration
+			Name="Release|x64"
+			OutputDirectory="$(ProjectDir)\bin\$(PlatformName)\$(ConfigurationName)"
+			IntermediateDirectory="$(ProjectDir)\obj\$(PlatformName)\$(ConfigurationName)"
+			ConfigurationType="1"
+			CharacterSet="1"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+				AdditionalOptions="/DWIN32_LEAN_AND_MEAN /DNDEBUG /D_CRT_SECURE_NO_WARNINGS"
+				Optimization="3"
+				EnableIntrinsicFunctions="true"
+				FavorSizeOrSpeed="1"
+				AdditionalIncludeDirectories="&quot;$(ProjectDir)\src&quot;;&quot;$(ProjectDir)\..\inc&quot;"
+				ExceptionHandling="0"
+				EnableFunctionLevelLinking="true"
+				WarningLevel="4"
+				WarnAsError="true"
+				CompileAs="1"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalDependencies="libcmt.lib"
+				IgnoreAllDefaultLibraries="true"
+				GenerateDebugInformation="false"
+				SubSystem="1"
+				OptimizeReferences="2"
+				EnableCOMDATFolding="2"
+				TargetMachine="17"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCManifestTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+			/>
+			<Tool
+				Name="VCFxCopTool"
+			/>
+			<Tool
+				Name="VCAppVerifierTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+			/>
+		</Configuration>
+	</Configurations>
+	<References>
+	</References>
+	<Files>
+		<Filter
+			Name="src"
+			Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx"
+			UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
+			>
+			<File
+				RelativePath=".\src\abstraction.h"
+				>
+			</File>
+			<File
+				RelativePath=".\src\abstraction_cpu_count.c"
+				>
+			</File>
+			<File
+				RelativePath=".\src\abstraction_thread_start.c"
+				>
+			</File>
+			<File
+				RelativePath=".\src\abstraction_thread_wait.c"
+				>
+			</File>
+			<File
+				RelativePath=".\src\benchmark_freelist.c"
+				>
+			</File>
+			<File
+				RelativePath=".\src\benchmark_queue.c"
+				>
+			</File>
+			<File
+				RelativePath=".\src\benchmark_ringbuffer.c"
+				>
+			</File>
+			<File
+				RelativePath=".\src\benchmark_stack.c"
+				>
+			</File>
+			<File
+				RelativePath=".\src\internal.h"
+				>
+			</File>
+			<File
+				RelativePath=".\src\main.c"
+				>
+			</File>
+			<File
+				RelativePath=".\src\misc.c"
+				>
+			</File>
+			<File
+				RelativePath=".\src\structures.h"
+				>
+			</File>
+			<File
+				RelativePath=".\src\test_abstraction.c"
+				>
+			</File>
+			<File
+				RelativePath=".\src\test_freelist.c"
+				>
+			</File>
+			<File
+				RelativePath=".\src\test_queue.c"
+				>
+			</File>
+			<File
+				RelativePath=".\src\test_ringbuffer.c"
+				>
+			</File>
+			<File
+				RelativePath=".\src\test_slist.c"
+				>
+			</File>
+			<File
+				RelativePath=".\src\test_stack.c"
+				>
+			</File>
+		</Filter>
+	</Files>
+	<Globals>
+	</Globals>
+</VisualStudioProject>
-- 
1.9.3

