win-pvdrivers

changeset 766:6300617040e0

Big changes - not ready for production use.
Removed all the custom DMA handling code as it was completely incompatible with the Windows verifier.
Added liblfds (using the lock free stack) from liblfds.org so that grant's can be obtained at DIRQL.
Fixed xennet and xenvbd to support the changes.
xenusb and xenscsi almost certainly will not yet work after the changes.
author James Harper <james.harper@bendigoit.com.au>
date Sun Jan 31 21:28:42 2010 +1100 (2010-01-31)
parents 7e756e306e3d
children 3e2651f9c739
files common.inc dirs installer.wxs liblfds.6/building.txt liblfds.6/dirs liblfds.6/inc/liblfds.h liblfds.6/liblfds.def liblfds.6/liblfds.sln liblfds.6/liblfds.vcproj liblfds.6/makefile.linux liblfds.6/makefile.windows liblfds.6/readme.txt liblfds.6/runme_before_win_kernel_build_readme.txt liblfds.6/runme_before_win_kernel_dynamic_lib_build.bat liblfds.6/runme_before_win_kernel_static_lib_build.bat liblfds.6/sources.dynamic liblfds.6/sources.static liblfds.6/src/abstraction/abstraction_aligned_free.c liblfds.6/src/abstraction/abstraction_aligned_malloc.c liblfds.6/src/abstraction/abstraction_cas.c liblfds.6/src/abstraction/abstraction_dcas.c liblfds.6/src/abstraction/abstraction_increment.c liblfds.6/src/abstraction/abstraction_internal.h liblfds.6/src/dirs liblfds.6/src/driver_entry.c liblfds.6/src/driver_entry_readme.txt liblfds.6/src/freelist/freelist_delete.c liblfds.6/src/freelist/freelist_get_and_set.c liblfds.6/src/freelist/freelist_internal.h liblfds.6/src/freelist/freelist_new.c liblfds.6/src/freelist/freelist_pop_push.c liblfds.6/src/freelist/freelist_query.c liblfds.6/src/liblfds_internal.h liblfds.6/src/queue/queue_delete.c liblfds.6/src/queue/queue_internal.h liblfds.6/src/queue/queue_new.c liblfds.6/src/queue/queue_query.c liblfds.6/src/queue/queue_queue.c liblfds.6/src/ringbuffer/ringbuffer_delete.c liblfds.6/src/ringbuffer/ringbuffer_get_and_put.c liblfds.6/src/ringbuffer/ringbuffer_internal.h liblfds.6/src/ringbuffer/ringbuffer_new.c liblfds.6/src/ringbuffer/ringbuffer_query.c liblfds.6/src/single_dir_for_windows_kernel/abstraction_aligned_free.c liblfds.6/src/single_dir_for_windows_kernel/abstraction_aligned_malloc.c liblfds.6/src/single_dir_for_windows_kernel/abstraction_cas.c liblfds.6/src/single_dir_for_windows_kernel/abstraction_dcas.c liblfds.6/src/single_dir_for_windows_kernel/abstraction_increment.c liblfds.6/src/single_dir_for_windows_kernel/abstraction_internal.h liblfds.6/src/single_dir_for_windows_kernel/freelist_delete.c liblfds.6/src/single_dir_for_windows_kernel/freelist_get_and_set.c liblfds.6/src/single_dir_for_windows_kernel/freelist_internal.h liblfds.6/src/single_dir_for_windows_kernel/freelist_new.c liblfds.6/src/single_dir_for_windows_kernel/freelist_pop_push.c liblfds.6/src/single_dir_for_windows_kernel/freelist_query.c liblfds.6/src/single_dir_for_windows_kernel/objchk_wnet_x86/i386/_objects.mac liblfds.6/src/single_dir_for_windows_kernel/objchk_wnet_x86/i386/abstraction_aligned_free.obj liblfds.6/src/single_dir_for_windows_kernel/objchk_wnet_x86/i386/abstraction_aligned_malloc.obj liblfds.6/src/single_dir_for_windows_kernel/objchk_wnet_x86/i386/abstraction_cas.obj liblfds.6/src/single_dir_for_windows_kernel/objchk_wnet_x86/i386/abstraction_dcas.obj liblfds.6/src/single_dir_for_windows_kernel/objchk_wnet_x86/i386/abstraction_increment.obj liblfds.6/src/single_dir_for_windows_kernel/objchk_wnet_x86/i386/freelist_delete.obj liblfds.6/src/single_dir_for_windows_kernel/objchk_wnet_x86/i386/freelist_get_and_set.obj liblfds.6/src/single_dir_for_windows_kernel/objchk_wnet_x86/i386/freelist_new.obj liblfds.6/src/single_dir_for_windows_kernel/objchk_wnet_x86/i386/freelist_pop_push.obj liblfds.6/src/single_dir_for_windows_kernel/objchk_wnet_x86/i386/freelist_query.obj liblfds.6/src/single_dir_for_windows_kernel/objchk_wnet_x86/i386/queue_delete.obj liblfds.6/src/single_dir_for_windows_kernel/objchk_wnet_x86/i386/queue_new.obj liblfds.6/src/single_dir_for_windows_kernel/objchk_wnet_x86/i386/queue_query.obj liblfds.6/src/single_dir_for_windows_kernel/objchk_wnet_x86/i386/queue_queue.obj liblfds.6/src/single_dir_for_windows_kernel/objchk_wnet_x86/i386/ringbuffer_delete.obj liblfds.6/src/single_dir_for_windows_kernel/objchk_wnet_x86/i386/ringbuffer_get_and_put.obj liblfds.6/src/single_dir_for_windows_kernel/objchk_wnet_x86/i386/ringbuffer_new.obj liblfds.6/src/single_dir_for_windows_kernel/objchk_wnet_x86/i386/ringbuffer_query.obj liblfds.6/src/single_dir_for_windows_kernel/objchk_wnet_x86/i386/slist_delete.obj liblfds.6/src/single_dir_for_windows_kernel/objchk_wnet_x86/i386/slist_get_and_set.obj liblfds.6/src/single_dir_for_windows_kernel/objchk_wnet_x86/i386/slist_link.obj liblfds.6/src/single_dir_for_windows_kernel/objchk_wnet_x86/i386/slist_new.obj liblfds.6/src/single_dir_for_windows_kernel/objchk_wnet_x86/i386/stack_delete.obj liblfds.6/src/single_dir_for_windows_kernel/objchk_wnet_x86/i386/stack_new.obj liblfds.6/src/single_dir_for_windows_kernel/objchk_wnet_x86/i386/stack_push_pop.obj liblfds.6/src/single_dir_for_windows_kernel/objchk_wnet_x86/i386/stack_query.obj liblfds.6/src/single_dir_for_windows_kernel/queue_delete.c liblfds.6/src/single_dir_for_windows_kernel/queue_internal.h liblfds.6/src/single_dir_for_windows_kernel/queue_new.c liblfds.6/src/single_dir_for_windows_kernel/queue_query.c liblfds.6/src/single_dir_for_windows_kernel/queue_queue.c liblfds.6/src/single_dir_for_windows_kernel/ringbuffer_delete.c liblfds.6/src/single_dir_for_windows_kernel/ringbuffer_get_and_put.c liblfds.6/src/single_dir_for_windows_kernel/ringbuffer_internal.h liblfds.6/src/single_dir_for_windows_kernel/ringbuffer_new.c liblfds.6/src/single_dir_for_windows_kernel/ringbuffer_query.c liblfds.6/src/single_dir_for_windows_kernel/slist_delete.c liblfds.6/src/single_dir_for_windows_kernel/slist_get_and_set.c liblfds.6/src/single_dir_for_windows_kernel/slist_internal.h liblfds.6/src/single_dir_for_windows_kernel/slist_link.c liblfds.6/src/single_dir_for_windows_kernel/slist_new.c liblfds.6/src/single_dir_for_windows_kernel/sources liblfds.6/src/single_dir_for_windows_kernel/stack_delete.c liblfds.6/src/single_dir_for_windows_kernel/stack_internal.h liblfds.6/src/single_dir_for_windows_kernel/stack_new.c liblfds.6/src/single_dir_for_windows_kernel/stack_push_pop.c liblfds.6/src/single_dir_for_windows_kernel/stack_query.c liblfds.6/src/slist/slist_delete.c liblfds.6/src/slist/slist_get_and_set.c liblfds.6/src/slist/slist_internal.h liblfds.6/src/slist/slist_link.c liblfds.6/src/slist/slist_new.c liblfds.6/src/stack/stack_delete.c liblfds.6/src/stack/stack_internal.h liblfds.6/src/stack/stack_new.c liblfds.6/src/stack/stack_push_pop.c liblfds.6/src/stack/stack_query.c liblfds.6/test/buildchk_wnet_x86.err liblfds.6/test/buildchk_wnet_x86.log liblfds.6/test/buildchk_wnet_x86.wrn liblfds.6/test/building.txt liblfds.6/test/makefile.linux liblfds.6/test/makefile.windows liblfds.6/test/src/abstraction.h liblfds.6/test/src/abstraction_cpu_count.c liblfds.6/test/src/abstraction_thread_start.c liblfds.6/test/src/abstraction_thread_wait.c liblfds.6/test/src/benchmark_freelist.c liblfds.6/test/src/benchmark_queue.c liblfds.6/test/src/benchmark_ringbuffer.c liblfds.6/test/src/benchmark_stack.c liblfds.6/test/src/internal.h liblfds.6/test/src/main.c liblfds.6/test/src/misc.c liblfds.6/test/src/structures.h liblfds.6/test/src/test_abstraction.c liblfds.6/test/src/test_freelist.c liblfds.6/test/src/test_queue.c liblfds.6/test/src/test_ringbuffer.c liblfds.6/test/src/test_slist.c liblfds.6/test/src/test_stack.c liblfds.6/test/test.sln liblfds.6/test/test.vcproj xennet/xennet.c xennet/xennet.h xennet/xennet_rx.c xennet/xennet_tx.c xenpci/gnttbl.c xenpci/sources xenpci/xenpci.h xenpci/xenpci_dma.c xenpci/xenpci_pdo.c xenvbd/xenvbd.c xenvbd/xenvbd.h
line diff
     1.1 --- a/common.inc	Sun Jan 17 15:16:50 2010 +1100
     1.2 +++ b/common.inc	Sun Jan 31 21:28:42 2010 +1100
     1.3 @@ -2,6 +2,8 @@
     1.4  C_DEFINES=$(C_DEFINES) -DBUILD_NUMBER=$(BUILD_NUMBER)
     1.5  !ENDIF
     1.6  MSC_WARNING_LEVEL=/W4
     1.7 -INCLUDES = ..\common\include;..\common\include\public
     1.8 +C_DEFINES=$(C_DEFINES) -DWIN_KERNEL_BUILD
     1.9 +LIBLFDS_DIR = ..\liblfds.6
    1.10 +INCLUDES = ..\common\include;..\common\include\public;$(LIBLFDS_DIR)\inc
    1.11  TARGETLIBS=$(TARGETLIBS) $(DDK_LIB_PATH)\ntstrsafe.lib
    1.12  NTTARGETFILES=
     2.1 --- a/dirs	Sun Jan 17 15:16:50 2010 +1100
     2.2 +++ b/dirs	Sun Jan 31 21:28:42 2010 +1100
     2.3 @@ -1,2 +1,2 @@
     2.4  
     2.5 -DIRS=xenpci xenvbd xennet xenscsi xenusb copyconfig shutdownmon coinst waitnopendinginstallevents
     2.6 +DIRS=liblfds.6 xenpci xenvbd xennet xenscsi xenusb copyconfig shutdownmon coinst waitnopendinginstallevents
     3.1 --- a/installer.wxs	Sun Jan 17 15:16:50 2010 +1100
     3.2 +++ b/installer.wxs	Sun Jan 31 21:28:42 2010 +1100
     3.3 @@ -41,7 +41,7 @@
     3.4  
     3.5      <?if $(env._BUILDARCH) = AMD64 ?>
     3.6        <Condition Message="Testsigning must be on for x64 when installing on Vista or newer.">
     3.7 -        <![CDATA[(VersionNT < 600) OR (SYSTEMSTARTOPTIONS >< "/TESTSIGNING")]]>
     3.8 +        <![CDATA[(VersionNT < 600) OR (SYSTEMSTARTOPTIONS >< "TESTSIGNING")]]>
     3.9        </Condition>
    3.10      <?endif ?>
    3.11  
     4.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     4.2 +++ b/liblfds.6/building.txt	Sun Jan 31 21:28:42 2010 +1100
     4.3 @@ -0,0 +1,38 @@
     4.4 +building liblfds
     4.5 +================
     4.6 +
     4.7 +Windows (user-mode)
     4.8 +===================
     4.9 +1. Use Microsoft Visual Studio 2008 or Visual C++ 2008 Express Edition
    4.10 +   to load "liblfds.sln".
    4.11 +
    4.12 +2. Use Microsoft Windows SDK and GNUmake to run makefile.windows (obviously
    4.13 +   you'll need to have run the appropriate vcvars*.bat first; you can build
    4.14 +   for both IA64, 64-bit and 32-bit - just run the correct vcvars batch file).
    4.15 +
    4.16 +   Targets are "librel", "libdbg", "dllrel", "dlldbg" and "clean".  You need
    4.17 +   to clean between switching targets.
    4.18 +
    4.19 +Windows (kernel)
    4.20 +================
    4.21 +Use the Windows Driver Kit "build" command.  Prior to running "build",
    4.22 +if you wish to build a static library, run the batch file
    4.23 +"runme_before_win_kernel_static_lib_build.bat"; if you wish to
    4.24 +build a dynamic library, instead run "runme_before_win_kernel_dynamic_lib_build.bat".
    4.25 +
    4.26 +The Windows kernel build system is rather limited and rather than
    4.27 +really rather messing up the directory/file structure just for the
    4.28 +Windows kernel platform, I've instead arranged it that these batch
    4.29 +files do the necessary work so that "build" will work.
    4.30 +
    4.31 +The batch files are idempotent; you can run them as often as you
    4.32 +like, in any order, at any time (before or after builds), and they'll
    4.33 +do the right thing.
    4.34 +
    4.35 +Linux
    4.36 +=====
    4.37 +Use GNUmake to run "makefile.linux".  Targets are "arrel", "ardbg",
    4.38 +"sorel", "sodbg" and "clean".  You need to clean between switching
    4.39 +targets.
    4.40 +
    4.41 +
     5.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     5.2 +++ b/liblfds.6/dirs	Sun Jan 31 21:28:42 2010 +1100
     5.3 @@ -0,0 +1,2 @@
     5.4 +DIRS = src
     5.5 +
     6.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     6.2 +++ b/liblfds.6/inc/liblfds.h	Sun Jan 31 21:28:42 2010 +1100
     6.3 @@ -0,0 +1,282 @@
     6.4 +#ifndef __LIBLFDS_H
     6.5 +
     6.6 +  /***** library header *****/
     6.7 +  #define LIBLFDS_RELEASE_NUMBER 6
     6.8 +
     6.9 +
    6.10 +
    6.11 +
    6.12 +  /***** abstraction *****/
    6.13 +
    6.14 +  /***** defines *****/
    6.15 +  #if (defined _WIN64 && defined _MSC_VER && !defined WIN_KERNEL_BUILD)
    6.16 +    // TRD : 64-bit Windows user-mode with the Microsoft C compiler, any CPU
    6.17 +    #include <assert.h>
    6.18 +    #include <stdio.h>
    6.19 +    #include <stdlib.h>
    6.20 +    #include <windows.h>
    6.21 +    #include <intrin.h>
    6.22 +    typedef unsigned __int64      atom_t;
    6.23 +    #define INLINE                extern __forceinline
    6.24 +    #define ALIGN(alignment)      __declspec( align(alignment) )
    6.25 +    #define ALIGN_SINGLE_POINTER  8
    6.26 +    #define ALIGN_DOUBLE_POINTER  16
    6.27 +  #endif
    6.28 +
    6.29 +  #if (!defined _WIN64 && defined _WIN32 && defined _MSC_VER && !defined WIN_KERNEL_BUILD)
    6.30 +    // TRD : 32-bit Windows user-mode with the Microsoft C compiler, any CPU
    6.31 +    #include <assert.h>
    6.32 +    #include <stdio.h>
    6.33 +    #include <stdlib.h>
    6.34 +    #include <windows.h>
    6.35 +    #include <intrin.h>
    6.36 +    typedef unsigned long int     atom_t;
    6.37 +    #define INLINE                extern __forceinline
    6.38 +    #define ALIGN(alignment)      __declspec( align(alignment) )
    6.39 +    #define ALIGN_SINGLE_POINTER  4
    6.40 +    #define ALIGN_DOUBLE_POINTER  8
    6.41 +
    6.42 +    // TRD : this define is documented but missing in Microsoft Platform SDK v7.0
    6.43 +    #define _InterlockedCompareExchangePointer(destination, exchange, compare) _InterlockedCompareExchange((volatile long *) destination, (long) exchange, (long) compare)
    6.44 +  #endif
    6.45 +
    6.46 +  #if (defined _WIN64 && defined _MSC_VER && defined WIN_KERNEL_BUILD)
    6.47 +    // TRD : 64-bit Windows kernel with the Microsoft C compiler, any CPU
    6.48 +    #include <assert.h>
    6.49 +    #include <stdio.h>
    6.50 +    #include <stdlib.h>
    6.51 +    #include <wdm.h>
    6.52 +    typedef unsigned __int64      atom_t;
    6.53 +    #define INLINE                extern __forceinline
    6.54 +    #define ALIGN(alignment)      __declspec( align(alignment) )
    6.55 +    #define ALIGN_SINGLE_POINTER  8
    6.56 +    #define ALIGN_DOUBLE_POINTER  16
    6.57 +  #endif
    6.58 +
    6.59 +  #if (!defined _WIN64 && defined _WIN32 && defined _MSC_VER && defined WIN_KERNEL_BUILD)
    6.60 +    // TRD : 32-bit Windows kernel with the Microsoft C compiler, any CPU
    6.61 +    #include <assert.h>
    6.62 +    #include <stdio.h>
    6.63 +    #include <stdlib.h>
    6.64 +    #include <wdm.h>
    6.65 +    typedef unsigned long int     atom_t;
    6.66 +    #define INLINE                extern __forceinline
    6.67 +    #define ALIGN(alignment)      __declspec( align(alignment) )
    6.68 +    #define ALIGN_SINGLE_POINTER  4
    6.69 +    #define ALIGN_DOUBLE_POINTER  8
    6.70 +
    6.71 +    // TRD : this define is documented but missing in Microsoft Platform SDK v7.0
    6.72 +    #define _InterlockedCompareExchangePointer(destination, exchange, compare) _InterlockedCompareExchange((volatile long *) destination, (long) exchange, (long) compare)
    6.73 +  #endif
    6.74 +
    6.75 +  #if (defined __unix__ && defined __x86_64__ && __GNUC__)
    6.76 +    // TRD : any UNIX with GCC on x64
    6.77 +    #define _XOPEN_SOURCE 600
    6.78 +    #include <assert.h>
    6.79 +    #include <stdio.h>
    6.80 +    #include <stdlib.h>
    6.81 +    typedef unsigned long long int  atom_t;
    6.82 +    #define INLINE                  inline
    6.83 +    #define ALIGN(alignment)        __attribute__( (aligned(alignment)) )
    6.84 +    #define ALIGN_SINGLE_POINTER    8
    6.85 +    #define ALIGN_DOUBLE_POINTER    16
    6.86 +  #endif
    6.87 +
    6.88 +  #if (defined __unix__ && defined __i686__ && __GNUC__)
    6.89 +    // TRD : any UNIX with GCC on x86
    6.90 +    #define _XOPEN_SOURCE 600
    6.91 +    #include <assert.h>
    6.92 +    #include <stdio.h>
    6.93 +    #include <stdlib.h>
    6.94 +    typedef unsigned long int     atom_t;
    6.95 +    #define INLINE                inline
    6.96 +    #define ALIGN(alignment)      __attribute__( (aligned(alignment)) )
    6.97 +    #define ALIGN_SINGLE_POINTER  4
    6.98 +    #define ALIGN_DOUBLE_POINTER  8
    6.99 +  #endif
   6.100 +
   6.101 +  #if (defined __unix__ && defined __arm__ && __GNUC__)
   6.102 +    // TRD : any UNIX with GCC on ARM
   6.103 +    #define _XOPEN_SOURCE 600
   6.104 +    #include <assert.h>
   6.105 +    #include <stdio.h>
   6.106 +    #include <stdlib.h>
   6.107 +    typedef unsigned long int     atom_t;
   6.108 +    #define INLINE                inline
   6.109 +    #define ALIGN(alignment)      __attribute__( (aligned(alignment)) )
   6.110 +    #define ALIGN_SINGLE_POINTER  4
   6.111 +    #define ALIGN_DOUBLE_POINTER  8
   6.112 +  #endif
   6.113 +
   6.114 +  /***** enums *****/
   6.115 +  enum data_structure_validity
   6.116 +  {
   6.117 +    VALIDITY_VALID,
   6.118 +    VALIDITY_INVALID_LOOP,
   6.119 +    VALIDITY_INVALID_MISSING_ELEMENTS,
   6.120 +    VALIDITY_INVALID_ADDITIONAL_ELEMENTS,
   6.121 +    VALIDITY_INVALID_TEST_DATA
   6.122 +  };
   6.123 +
   6.124 +  /***** structs *****/
   6.125 +  struct validation_info
   6.126 +  {
   6.127 +    atom_t
   6.128 +      min_elements,
   6.129 +      max_elements;
   6.130 +  };
   6.131 +
   6.132 +  /***** public prototypes *****/
   6.133 +  void abstraction_aligned_free( void *memory );
   6.134 +  void *abstraction_aligned_malloc( size_t size, size_t align_in_bytes );
   6.135 +  atom_t abstraction_cas( volatile atom_t *destination, atom_t exchange, atom_t compare );
   6.136 +  unsigned char abstraction_dcas( volatile atom_t *destination, atom_t *exchange, atom_t *compare );
   6.137 +  atom_t abstraction_increment( atom_t *value );
   6.138 +
   6.139 +
   6.140 +
   6.141 +
   6.142 +
   6.143 +  /***** freelist *****/
   6.144 +
   6.145 +  /***** enums *****/
   6.146 +  enum freelist_query_type
   6.147 +  {
   6.148 +    FREELIST_QUERY_ELEMENT_COUNT,
   6.149 +    FREELIST_QUERY_VALIDATE
   6.150 +  };
   6.151 +
   6.152 +  /***** incomplete types *****/
   6.153 +  struct freelist_state;
   6.154 +  struct freelist_element;
   6.155 +
   6.156 +  /***** public prototypes *****/
   6.157 +  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 );
   6.158 +  void freelist_delete( struct freelist_state *fs, void (*user_data_delete_function)(void *user_data, void *user_state), void *user_state );
   6.159 +
   6.160 +  atom_t freelist_new_elements( struct freelist_state *fs, atom_t number_elements );
   6.161 +
   6.162 +  struct freelist_element *freelist_pop( struct freelist_state *fs, struct freelist_element **fe );
   6.163 +  struct freelist_element *freelist_guaranteed_pop( struct freelist_state *fs, struct freelist_element **fe );
   6.164 +  void freelist_push( struct freelist_state *fs, struct freelist_element *fe );
   6.165 +
   6.166 +  void *freelist_get_user_data_from_element( struct freelist_element *fe, void **user_data );
   6.167 +  void freelist_set_user_data_in_element( struct freelist_element *fe, void *user_data );
   6.168 +
   6.169 +  void freelist_query( struct freelist_state *fs, enum freelist_query_type query_type, void *query_input, void *query_output );
   6.170 +
   6.171 +
   6.172 +
   6.173 +
   6.174 +
   6.175 +  /***** queue *****/
   6.176 +
   6.177 +  /***** enums *****/
   6.178 +  enum queue_query_type
   6.179 +  {
   6.180 +    QUEUE_QUERY_ELEMENT_COUNT,
   6.181 +    QUEUE_QUERY_VALIDATE
   6.182 +  };
   6.183 +
   6.184 +  /***** incomplete types *****/
   6.185 +  struct queue_state;
   6.186 +
   6.187 +  /***** public prototypes *****/
   6.188 +  int queue_new( struct queue_state **sq, atom_t number_elements );
   6.189 +  void queue_delete( struct queue_state *qs, void (*user_data_delete_function)(void *user_data, void *user_state), void *user_state );
   6.190 +
   6.191 +  int queue_enqueue( struct queue_state *qs, void *user_data );
   6.192 +  int queue_guaranteed_enqueue( struct queue_state *qs, void *user_data );
   6.193 +  int queue_dequeue( struct queue_state *qs, void **user_data );
   6.194 +
   6.195 +  void queue_query( struct queue_state *qs, enum queue_query_type query_type, void *query_input, void *query_output );
   6.196 +
   6.197 +
   6.198 +
   6.199 +
   6.200 +
   6.201 +  /***** ringbuffer *****/
   6.202 +
   6.203 +  /***** enums *****/
   6.204 +  enum ringbuffer_query_type
   6.205 +  {
   6.206 +    RINGBUFFER_QUERY_VALIDATE
   6.207 +  };
   6.208 +
   6.209 +  /***** incomplete types *****/
   6.210 +  struct ringbuffer_state;
   6.211 +
   6.212 +  /***** public prototypes *****/
   6.213 +  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 );
   6.214 +  void ringbuffer_delete( struct ringbuffer_state *rs, void (*user_data_delete_function)(void *user_data, void *user_state), void *user_state );
   6.215 +
   6.216 +  struct freelist_element *ringbuffer_get_read_element( struct ringbuffer_state *rs, struct freelist_element **fe );
   6.217 +  struct freelist_element *ringbuffer_get_write_element( struct ringbuffer_state *rs, struct freelist_element **fe, int *overwrite_flag );
   6.218 +
   6.219 +  void ringbuffer_put_read_element( struct ringbuffer_state *rs, struct freelist_element *fe );
   6.220 +  void ringbuffer_put_write_element( struct ringbuffer_state *rs, struct freelist_element *fe );
   6.221 +
   6.222 +  void ringbuffer_query( struct ringbuffer_state *rs, enum ringbuffer_query_type query_type, void *query_input, void *query_output );
   6.223 +
   6.224 +
   6.225 +
   6.226 +
   6.227 +
   6.228 +  /***** slist *****/
   6.229 +
   6.230 +  /***** incomplete types *****/
   6.231 +  struct slist_state;
   6.232 +  struct slist_element;
   6.233 +
   6.234 +  /***** public prototypes *****/
   6.235 +  int slist_new( struct slist_state **ss, void (*user_data_delete_function)(void *user_data, void *user_state), void *user_state );
   6.236 +  void slist_delete( struct slist_state *ss );
   6.237 +
   6.238 +  struct slist_element *slist_new_head( struct slist_state *ss, void *user_data );
   6.239 +  struct slist_element *slist_new_next( struct slist_element *se, void *user_data );
   6.240 +
   6.241 +  void slist_delete_element( struct slist_state *ss, struct slist_element *se );
   6.242 +  void slist_delete_all_elements( struct slist_state *ss );
   6.243 +
   6.244 +  int slist_get_user_data_from_element( struct slist_element *se, void **user_data );
   6.245 +  int slist_set_user_data_in_element( struct slist_element *se, void *user_data );
   6.246 +
   6.247 +  struct slist_element *slist_get_head( struct slist_state *ss, struct slist_element **se );
   6.248 +  struct slist_element *slist_get_next( struct slist_element *se, struct slist_element **next_se );
   6.249 +  struct slist_element *slist_get_head_and_then_next( struct slist_state *ss, struct slist_element **se );
   6.250 +
   6.251 +
   6.252 +
   6.253 +
   6.254 +
   6.255 +  /***** stack *****/
   6.256 +
   6.257 +  /***** enums *****/
   6.258 +  enum stack_query_type
   6.259 +  {
   6.260 +    STACK_QUERY_ELEMENT_COUNT
   6.261 +  };
   6.262 +
   6.263 +  /***** incomplete types *****/
   6.264 +  struct stack_state;
   6.265 +
   6.266 +  /***** public prototypes *****/
   6.267 +  int stack_new( struct stack_state **ss, atom_t number_elements );
   6.268 +  void stack_delete( struct stack_state *ss, void (*user_data_delete_function)(void *user_data, void *user_state), void *user_state );
   6.269 +
   6.270 +  void stack_clear( struct stack_state *ss, void (*user_data_clear_function)(void *user_data, void *user_state), void *user_state );
   6.271 +
   6.272 +  int stack_push( struct stack_state *ss, void *user_data );
   6.273 +  int stack_guaranteed_push( struct stack_state *ss, void *user_data );
   6.274 +  int stack_pop( struct stack_state *ss, void **user_data );
   6.275 +
   6.276 +  void stack_query( struct stack_state *ss, enum stack_query_type query_type, void *query_input, void *query_output );
   6.277 +
   6.278 +
   6.279 +
   6.280 +
   6.281 +
   6.282 +  #define __LIBLFDS_H
   6.283 +
   6.284 +#endif
   6.285 +
     7.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     7.2 +++ b/liblfds.6/liblfds.def	Sun Jan 31 21:28:42 2010 +1100
     7.3 @@ -0,0 +1,46 @@
     7.4 +EXPORTS
     7.5 +
     7.6 +freelist_delete = freelist_delete @1
     7.7 +freelist_get_user_data_from_element = freelist_get_user_data_from_element @2
     7.8 +freelist_guaranteed_pop = freelist_guaranteed_pop @3
     7.9 +freelist_new = freelist_new @4
    7.10 +freelist_new_elements = freelist_new_elements @5
    7.11 +freelist_pop = freelist_pop @6
    7.12 +freelist_push = freelist_push @7
    7.13 +freelist_query = freelist_query @8
    7.14 +freelist_set_user_data_in_element = freelist_set_user_data_in_element @9
    7.15 +
    7.16 +queue_delete = queue_delete @10
    7.17 +queue_dequeue = queue_dequeue @11
    7.18 +queue_enqueue = queue_enqueue @12
    7.19 +queue_guaranteed_enqueue = queue_guaranteed_enqueue @13
    7.20 +queue_new = queue_new @14
    7.21 +queue_query = queue_query @15
    7.22 +
    7.23 +ringbuffer_delete = ringbuffer_delete @16
    7.24 +ringbuffer_get_read_element = ringbuffer_get_read_element @17
    7.25 +ringbuffer_get_write_element = ringbuffer_get_write_element @18
    7.26 +ringbuffer_new = ringbuffer_new @19
    7.27 +ringbuffer_put_read_element = ringbuffer_put_read_element @20
    7.28 +ringbuffer_put_write_element = ringbuffer_put_write_element @21
    7.29 +
    7.30 +slist_delete = slist_delete @ 22
    7.31 +slist_delete_all_elements = slist_delete_all_elements @ 23
    7.32 +slist_delete_element = slist_delete_element @ 24
    7.33 +slist_get_head = slist_get_head @ 25
    7.34 +slist_get_head_and_then_next = slist_get_head_and_then_next @ 26
    7.35 +slist_get_next = slist_get_next @ 27
    7.36 +slist_get_user_data_from_element = slist_get_user_data_from_element @ 28
    7.37 +slist_new = slist_new @ 29
    7.38 +slist_new_head = slist_new_head @ 30
    7.39 +slist_new_next = slist_new_next @ 31
    7.40 +slist_set_user_data_in_element = slist_set_user_data_in_element @ 32
    7.41 +
    7.42 +stack_clear = stack_clear @33
    7.43 +stack_delete = stack_delete @34
    7.44 +stack_guaranteed_push = stack_guaranteed_push @35
    7.45 +stack_new = stack_new @36
    7.46 +stack_pop = stack_pop @37
    7.47 +stack_push = stack_push @38
    7.48 +stack_query = stack_query @39
    7.49 +
     8.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     8.2 +++ b/liblfds.6/liblfds.sln	Sun Jan 31 21:28:42 2010 +1100
     8.3 @@ -0,0 +1,38 @@
     8.4 +
     8.5 +Microsoft Visual Studio Solution File, Format Version 10.00
     8.6 +# Visual Studio 2008
     8.7 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "liblfds", "liblfds.vcproj", "{F73AE755-F6D8-4C3A-977D-FBB40DC0ED05}"
     8.8 +EndProject
     8.9 +Global
    8.10 +	GlobalSection(SolutionConfigurationPlatforms) = preSolution
    8.11 +		Debug DLL|Win32 = Debug DLL|Win32
    8.12 +		Debug DLL|x64 = Debug DLL|x64
    8.13 +		Debug Lib|Win32 = Debug Lib|Win32
    8.14 +		Debug Lib|x64 = Debug Lib|x64
    8.15 +		Release DLL|Win32 = Release DLL|Win32
    8.16 +		Release DLL|x64 = Release DLL|x64
    8.17 +		Release Lib|Win32 = Release Lib|Win32
    8.18 +		Release Lib|x64 = Release Lib|x64
    8.19 +	EndGlobalSection
    8.20 +	GlobalSection(ProjectConfigurationPlatforms) = postSolution
    8.21 +		{F73AE755-F6D8-4C3A-977D-FBB40DC0ED05}.Debug DLL|Win32.ActiveCfg = Release DLL|Win32
    8.22 +		{F73AE755-F6D8-4C3A-977D-FBB40DC0ED05}.Debug DLL|Win32.Build.0 = Release DLL|Win32
    8.23 +		{F73AE755-F6D8-4C3A-977D-FBB40DC0ED05}.Debug DLL|x64.ActiveCfg = Debug DLL|x64
    8.24 +		{F73AE755-F6D8-4C3A-977D-FBB40DC0ED05}.Debug DLL|x64.Build.0 = Debug DLL|x64
    8.25 +		{F73AE755-F6D8-4C3A-977D-FBB40DC0ED05}.Debug Lib|Win32.ActiveCfg = Debug Lib|Win32
    8.26 +		{F73AE755-F6D8-4C3A-977D-FBB40DC0ED05}.Debug Lib|Win32.Build.0 = Debug Lib|Win32
    8.27 +		{F73AE755-F6D8-4C3A-977D-FBB40DC0ED05}.Debug Lib|x64.ActiveCfg = Debug Lib|x64
    8.28 +		{F73AE755-F6D8-4C3A-977D-FBB40DC0ED05}.Debug Lib|x64.Build.0 = Debug Lib|x64
    8.29 +		{F73AE755-F6D8-4C3A-977D-FBB40DC0ED05}.Release DLL|Win32.ActiveCfg = Release DLL|Win32
    8.30 +		{F73AE755-F6D8-4C3A-977D-FBB40DC0ED05}.Release DLL|Win32.Build.0 = Release DLL|Win32
    8.31 +		{F73AE755-F6D8-4C3A-977D-FBB40DC0ED05}.Release DLL|x64.ActiveCfg = Release DLL|x64
    8.32 +		{F73AE755-F6D8-4C3A-977D-FBB40DC0ED05}.Release DLL|x64.Build.0 = Release DLL|x64
    8.33 +		{F73AE755-F6D8-4C3A-977D-FBB40DC0ED05}.Release Lib|Win32.ActiveCfg = Release Lib|Win32
    8.34 +		{F73AE755-F6D8-4C3A-977D-FBB40DC0ED05}.Release Lib|Win32.Build.0 = Release Lib|Win32
    8.35 +		{F73AE755-F6D8-4C3A-977D-FBB40DC0ED05}.Release Lib|x64.ActiveCfg = Release Lib|x64
    8.36 +		{F73AE755-F6D8-4C3A-977D-FBB40DC0ED05}.Release Lib|x64.Build.0 = Release Lib|x64
    8.37 +	EndGlobalSection
    8.38 +	GlobalSection(SolutionProperties) = preSolution
    8.39 +		HideSolutionNode = FALSE
    8.40 +	EndGlobalSection
    8.41 +EndGlobal
     9.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     9.2 +++ b/liblfds.6/liblfds.vcproj	Sun Jan 31 21:28:42 2010 +1100
     9.3 @@ -0,0 +1,808 @@
     9.4 +<?xml version="1.0" encoding="Windows-1252"?>
     9.5 +<VisualStudioProject
     9.6 +	ProjectType="Visual C++"
     9.7 +	Version="9.00"
     9.8 +	Name="liblfds"
     9.9 +	ProjectGUID="{F73AE755-F6D8-4C3A-977D-FBB40DC0ED05}"
    9.10 +	RootNamespace="liblfds"
    9.11 +	TargetFrameworkVersion="196613"
    9.12 +	>
    9.13 +	<Platforms>
    9.14 +		<Platform
    9.15 +			Name="Win32"
    9.16 +		/>
    9.17 +		<Platform
    9.18 +			Name="x64"
    9.19 +		/>
    9.20 +	</Platforms>
    9.21 +	<ToolFiles>
    9.22 +	</ToolFiles>
    9.23 +	<Configurations>
    9.24 +		<Configuration
    9.25 +			Name="Debug Lib|Win32"
    9.26 +			OutputDirectory="$(ProjectDir)\bin\$(PlatformName)\$(ConfigurationName)"
    9.27 +			IntermediateDirectory="$(ProjectDir)\obj\$(PlatformName)\$(ConfigurationName)"
    9.28 +			ConfigurationType="4"
    9.29 +			CharacterSet="1"
    9.30 +			WholeProgramOptimization="0"
    9.31 +			>
    9.32 +			<Tool
    9.33 +				Name="VCPreBuildEventTool"
    9.34 +			/>
    9.35 +			<Tool
    9.36 +				Name="VCCustomBuildTool"
    9.37 +			/>
    9.38 +			<Tool
    9.39 +				Name="VCXMLDataGeneratorTool"
    9.40 +			/>
    9.41 +			<Tool
    9.42 +				Name="VCWebServiceProxyGeneratorTool"
    9.43 +			/>
    9.44 +			<Tool
    9.45 +				Name="VCMIDLTool"
    9.46 +			/>
    9.47 +			<Tool
    9.48 +				Name="VCCLCompilerTool"
    9.49 +				AdditionalOptions="/DWIN32_LEAN_AND_MEAN /D_DEBUG"
    9.50 +				Optimization="0"
    9.51 +				EnableIntrinsicFunctions="true"
    9.52 +				AdditionalIncludeDirectories="&quot;$(ProjectDir)\src&quot;;&quot;$(ProjectDir)\inc&quot;"
    9.53 +				MinimalRebuild="true"
    9.54 +				ExceptionHandling="0"
    9.55 +				BasicRuntimeChecks="3"
    9.56 +				EnableFunctionLevelLinking="true"
    9.57 +				BrowseInformation="1"
    9.58 +				WarningLevel="4"
    9.59 +				WarnAsError="true"
    9.60 +				DebugInformationFormat="3"
    9.61 +				CompileAs="1"
    9.62 +			/>
    9.63 +			<Tool
    9.64 +				Name="VCManagedResourceCompilerTool"
    9.65 +			/>
    9.66 +			<Tool
    9.67 +				Name="VCResourceCompilerTool"
    9.68 +			/>
    9.69 +			<Tool
    9.70 +				Name="VCPreLinkEventTool"
    9.71 +			/>
    9.72 +			<Tool
    9.73 +				Name="VCLibrarianTool"
    9.74 +				AdditionalOptions="/wx"
    9.75 +				AdditionalLibraryDirectories=""
    9.76 +				IgnoreAllDefaultLibraries="true"
    9.77 +			/>
    9.78 +			<Tool
    9.79 +				Name="VCALinkTool"
    9.80 +			/>
    9.81 +			<Tool
    9.82 +				Name="VCXDCMakeTool"
    9.83 +			/>
    9.84 +			<Tool
    9.85 +				Name="VCBscMakeTool"
    9.86 +			/>
    9.87 +			<Tool
    9.88 +				Name="VCFxCopTool"
    9.89 +			/>
    9.90 +			<Tool
    9.91 +				Name="VCPostBuildEventTool"
    9.92 +			/>
    9.93 +		</Configuration>
    9.94 +		<Configuration
    9.95 +			Name="Debug Lib|x64"
    9.96 +			OutputDirectory="$(ProjectDir)\bin\$(PlatformName)\$(ConfigurationName)"
    9.97 +			IntermediateDirectory="$(ProjectDir)\obj\$(PlatformName)\$(ConfigurationName)"
    9.98 +			ConfigurationType="4"
    9.99 +			CharacterSet="1"
   9.100 +			WholeProgramOptimization="0"
   9.101 +			>
   9.102 +			<Tool
   9.103 +				Name="VCPreBuildEventTool"
   9.104 +			/>
   9.105 +			<Tool
   9.106 +				Name="VCCustomBuildTool"
   9.107 +			/>
   9.108 +			<Tool
   9.109 +				Name="VCXMLDataGeneratorTool"
   9.110 +			/>
   9.111 +			<Tool
   9.112 +				Name="VCWebServiceProxyGeneratorTool"
   9.113 +			/>
   9.114 +			<Tool
   9.115 +				Name="VCMIDLTool"
   9.116 +			/>
   9.117 +			<Tool
   9.118 +				Name="VCCLCompilerTool"
   9.119 +				AdditionalOptions="/DWIN32_LEAN_AND_MEAN /D_DEBUG"
   9.120 +				Optimization="0"
   9.121 +				EnableIntrinsicFunctions="true"
   9.122 +				AdditionalIncludeDirectories="&quot;$(ProjectDir)\src&quot;;&quot;$(ProjectDir)\inc&quot;"
   9.123 +				ExceptionHandling="0"
   9.124 +				BasicRuntimeChecks="3"
   9.125 +				SmallerTypeCheck="true"
   9.126 +				EnableFunctionLevelLinking="true"
   9.127 +				BrowseInformation="1"
   9.128 +				WarningLevel="4"
   9.129 +				WarnAsError="true"
   9.130 +				DebugInformationFormat="3"
   9.131 +				CompileAs="1"
   9.132 +			/>
   9.133 +			<Tool
   9.134 +				Name="VCManagedResourceCompilerTool"
   9.135 +			/>
   9.136 +			<Tool
   9.137 +				Name="VCResourceCompilerTool"
   9.138 +			/>
   9.139 +			<Tool
   9.140 +				Name="VCPreLinkEventTool"
   9.141 +			/>
   9.142 +			<Tool
   9.143 +				Name="VCLibrarianTool"
   9.144 +				AdditionalOptions="/wx"
   9.145 +				AdditionalLibraryDirectories=""
   9.146 +				IgnoreAllDefaultLibraries="true"
   9.147 +			/>
   9.148 +			<Tool
   9.149 +				Name="VCALinkTool"
   9.150 +			/>
   9.151 +			<Tool
   9.152 +				Name="VCXDCMakeTool"
   9.153 +			/>
   9.154 +			<Tool
   9.155 +				Name="VCBscMakeTool"
   9.156 +			/>
   9.157 +			<Tool
   9.158 +				Name="VCFxCopTool"
   9.159 +			/>
   9.160 +			<Tool
   9.161 +				Name="VCPostBuildEventTool"
   9.162 +			/>
   9.163 +		</Configuration>
   9.164 +		<Configuration
   9.165 +			Name="Release Lib|Win32"
   9.166 +			OutputDirectory="$(ProjectDir)\bin\$(PlatformName)\$(ConfigurationName)"
   9.167 +			IntermediateDirectory="$(ProjectDir)\obj\$(PlatformName)\$(ConfigurationName)"
   9.168 +			ConfigurationType="4"
   9.169 +			CharacterSet="1"
   9.170 +			WholeProgramOptimization="0"
   9.171 +			>
   9.172 +			<Tool
   9.173 +				Name="VCPreBuildEventTool"
   9.174 +			/>
   9.175 +			<Tool
   9.176 +				Name="VCCustomBuildTool"
   9.177 +			/>
   9.178 +			<Tool
   9.179 +				Name="VCXMLDataGeneratorTool"
   9.180 +			/>
   9.181 +			<Tool
   9.182 +				Name="VCWebServiceProxyGeneratorTool"
   9.183 +			/>
   9.184 +			<Tool
   9.185 +				Name="VCMIDLTool"
   9.186 +			/>
   9.187 +			<Tool
   9.188 +				Name="VCCLCompilerTool"
   9.189 +				AdditionalOptions="/DWIN32_LEAN_AND_MEAN /DNDEBUG"
   9.190 +				Optimization="3"
   9.191 +				EnableIntrinsicFunctions="true"
   9.192 +				FavorSizeOrSpeed="1"
   9.193 +				AdditionalIncludeDirectories="&quot;$(ProjectDir)\src&quot;;&quot;$(ProjectDir)\inc&quot;"
   9.194 +				StringPooling="true"
   9.195 +				ExceptionHandling="0"
   9.196 +				BufferSecurityCheck="false"
   9.197 +				EnableFunctionLevelLinking="true"
   9.198 +				WarningLevel="4"
   9.199 +				WarnAsError="true"
   9.200 +				DebugInformationFormat="0"
   9.201 +				CompileAs="1"
   9.202 +			/>
   9.203 +			<Tool
   9.204 +				Name="VCManagedResourceCompilerTool"
   9.205 +			/>
   9.206 +			<Tool
   9.207 +				Name="VCResourceCompilerTool"
   9.208 +			/>
   9.209 +			<Tool
   9.210 +				Name="VCPreLinkEventTool"
   9.211 +			/>
   9.212 +			<Tool
   9.213 +				Name="VCLibrarianTool"
   9.214 +				AdditionalOptions="/wx"
   9.215 +				AdditionalLibraryDirectories=""
   9.216 +				IgnoreAllDefaultLibraries="true"
   9.217 +			/>
   9.218 +			<Tool
   9.219 +				Name="VCALinkTool"
   9.220 +			/>
   9.221 +			<Tool
   9.222 +				Name="VCXDCMakeTool"
   9.223 +			/>
   9.224 +			<Tool
   9.225 +				Name="VCBscMakeTool"
   9.226 +			/>
   9.227 +			<Tool
   9.228 +				Name="VCFxCopTool"
   9.229 +			/>
   9.230 +			<Tool
   9.231 +				Name="VCPostBuildEventTool"
   9.232 +			/>
   9.233 +		</Configuration>
   9.234 +		<Configuration
   9.235 +			Name="Release Lib|x64"
   9.236 +			OutputDirectory="$(ProjectDir)\bin\$(PlatformName)\$(ConfigurationName)"
   9.237 +			IntermediateDirectory="$(ProjectDir)\obj\$(PlatformName)\$(ConfigurationName)"
   9.238 +			ConfigurationType="4"
   9.239 +			CharacterSet="1"
   9.240 +			WholeProgramOptimization="0"
   9.241 +			>
   9.242 +			<Tool
   9.243 +				Name="VCPreBuildEventTool"
   9.244 +			/>
   9.245 +			<Tool
   9.246 +				Name="VCCustomBuildTool"
   9.247 +			/>
   9.248 +			<Tool
   9.249 +				Name="VCXMLDataGeneratorTool"
   9.250 +			/>
   9.251 +			<Tool
   9.252 +				Name="VCWebServiceProxyGeneratorTool"
   9.253 +			/>
   9.254 +			<Tool
   9.255 +				Name="VCMIDLTool"
   9.256 +			/>
   9.257 +			<Tool
   9.258 +				Name="VCCLCompilerTool"
   9.259 +				AdditionalOptions="/DWIN32_LEAN_AND_MEAN /DNDEBUG"
   9.260 +				Optimization="3"
   9.261 +				EnableIntrinsicFunctions="true"
   9.262 +				FavorSizeOrSpeed="1"
   9.263 +				AdditionalIncludeDirectories="&quot;$(ProjectDir)\src&quot;;&quot;$(ProjectDir)\inc&quot;"
   9.264 +				StringPooling="true"
   9.265 +				ExceptionHandling="0"
   9.266 +				BufferSecurityCheck="false"
   9.267 +				EnableFunctionLevelLinking="true"
   9.268 +				WarningLevel="4"
   9.269 +				WarnAsError="true"
   9.270 +				DebugInformationFormat="0"
   9.271 +				CompileAs="1"
   9.272 +			/>
   9.273 +			<Tool
   9.274 +				Name="VCManagedResourceCompilerTool"
   9.275 +			/>
   9.276 +			<Tool
   9.277 +				Name="VCResourceCompilerTool"
   9.278 +			/>
   9.279 +			<Tool
   9.280 +				Name="VCPreLinkEventTool"
   9.281 +			/>
   9.282 +			<Tool
   9.283 +				Name="VCLibrarianTool"
   9.284 +				AdditionalOptions="/wx"
   9.285 +				AdditionalLibraryDirectories=""
   9.286 +				IgnoreAllDefaultLibraries="true"
   9.287 +			/>
   9.288 +			<Tool
   9.289 +				Name="VCALinkTool"
   9.290 +			/>
   9.291 +			<Tool
   9.292 +				Name="VCXDCMakeTool"
   9.293 +			/>
   9.294 +			<Tool
   9.295 +				Name="VCBscMakeTool"
   9.296 +			/>
   9.297 +			<Tool
   9.298 +				Name="VCFxCopTool"
   9.299 +			/>
   9.300 +			<Tool
   9.301 +				Name="VCPostBuildEventTool"
   9.302 +			/>
   9.303 +		</Configuration>
   9.304 +		<Configuration
   9.305 +			Name="Debug DLL|Win32"
   9.306 +			OutputDirectory="$(ProjectDir)\bin\$(PlatformName)\$(ConfigurationName)"
   9.307 +			IntermediateDirectory="$(ProjectDir)\obj\$(PlatformName)\$(ConfigurationName)"
   9.308 +			ConfigurationType="2"
   9.309 +			CharacterSet="1"
   9.310 +			WholeProgramOptimization="0"
   9.311 +			>
   9.312 +			<Tool
   9.313 +				Name="VCPreBuildEventTool"
   9.314 +			/>
   9.315 +			<Tool
   9.316 +				Name="VCCustomBuildTool"
   9.317 +			/>
   9.318 +			<Tool
   9.319 +				Name="VCXMLDataGeneratorTool"
   9.320 +			/>
   9.321 +			<Tool
   9.322 +				Name="VCWebServiceProxyGeneratorTool"
   9.323 +			/>
   9.324 +			<Tool
   9.325 +				Name="VCMIDLTool"
   9.326 +			/>
   9.327 +			<Tool
   9.328 +				Name="VCCLCompilerTool"
   9.329 +				AdditionalOptions="/DWIN32_LEAN_AND_MEAN /D_DEBUG"
   9.330 +				Optimization="0"
   9.331 +				EnableIntrinsicFunctions="true"
   9.332 +				AdditionalIncludeDirectories="&quot;$(ProjectDir)\src&quot;;&quot;$(ProjectDir)\inc&quot;"
   9.333 +				MinimalRebuild="true"
   9.334 +				ExceptionHandling="0"
   9.335 +				BasicRuntimeChecks="3"
   9.336 +				RuntimeLibrary="3"
   9.337 +				EnableFunctionLevelLinking="true"
   9.338 +				BrowseInformation="1"
   9.339 +				WarningLevel="4"
   9.340 +				WarnAsError="true"
   9.341 +				DebugInformationFormat="3"
   9.342 +				CompileAs="1"
   9.343 +			/>
   9.344 +			<Tool
   9.345 +				Name="VCManagedResourceCompilerTool"
   9.346 +			/>
   9.347 +			<Tool
   9.348 +				Name="VCResourceCompilerTool"
   9.349 +			/>
   9.350 +			<Tool
   9.351 +				Name="VCPreLinkEventTool"
   9.352 +			/>
   9.353 +			<Tool
   9.354 +				Name="VCLinkerTool"
   9.355 +				AdditionalDependencies="msvcrtd.lib"
   9.356 +				IgnoreAllDefaultLibraries="true"
   9.357 +				ModuleDefinitionFile="$(ProjectDir)\liblfds.def"
   9.358 +			/>
   9.359 +			<Tool
   9.360 +				Name="VCALinkTool"
   9.361 +			/>
   9.362 +			<Tool
   9.363 +				Name="VCManifestTool"
   9.364 +			/>
   9.365 +			<Tool
   9.366 +				Name="VCXDCMakeTool"
   9.367 +			/>
   9.368 +			<Tool
   9.369 +				Name="VCBscMakeTool"
   9.370 +			/>
   9.371 +			<Tool
   9.372 +				Name="VCFxCopTool"
   9.373 +			/>
   9.374 +			<Tool
   9.375 +				Name="VCAppVerifierTool"
   9.376 +			/>
   9.377 +			<Tool
   9.378 +				Name="VCPostBuildEventTool"
   9.379 +			/>
   9.380 +		</Configuration>
   9.381 +		<Configuration
   9.382 +			Name="Debug DLL|x64"
   9.383 +			OutputDirectory="$(ProjectDir)\bin\$(PlatformName)\$(ConfigurationName)"
   9.384 +			IntermediateDirectory="$(ProjectDir)\obj\$(PlatformName)\$(ConfigurationName)"
   9.385 +			ConfigurationType="2"
   9.386 +			CharacterSet="1"
   9.387 +			WholeProgramOptimization="0"
   9.388 +			>
   9.389 +			<Tool
   9.390 +				Name="VCPreBuildEventTool"
   9.391 +			/>
   9.392 +			<Tool
   9.393 +				Name="VCCustomBuildTool"
   9.394 +			/>
   9.395 +			<Tool
   9.396 +				Name="VCXMLDataGeneratorTool"
   9.397 +			/>
   9.398 +			<Tool
   9.399 +				Name="VCWebServiceProxyGeneratorTool"
   9.400 +			/>
   9.401 +			<Tool
   9.402 +				Name="VCMIDLTool"
   9.403 +				TargetEnvironment="3"
   9.404 +			/>
   9.405 +			<Tool
   9.406 +				Name="VCCLCompilerTool"
   9.407 +				AdditionalOptions="/DWIN32_LEAN_AND_MEAN /D_DEBUG"
   9.408 +				Optimization="0"
   9.409 +				EnableIntrinsicFunctions="true"
   9.410 +				AdditionalIncludeDirectories="&quot;$(ProjectDir)\src&quot;;&quot;$(ProjectDir)\inc&quot;"
   9.411 +				ExceptionHandling="0"
   9.412 +				BasicRuntimeChecks="3"
   9.413 +				SmallerTypeCheck="true"
   9.414 +				RuntimeLibrary="3"
   9.415 +				EnableFunctionLevelLinking="true"
   9.416 +				BrowseInformation="1"
   9.417 +				WarningLevel="4"
   9.418 +				WarnAsError="true"
   9.419 +				DebugInformationFormat="3"
   9.420 +				CompileAs="1"
   9.421 +			/>
   9.422 +			<Tool
   9.423 +				Name="VCManagedResourceCompilerTool"
   9.424 +			/>
   9.425 +			<Tool
   9.426 +				Name="VCResourceCompilerTool"
   9.427 +			/>
   9.428 +			<Tool
   9.429 +				Name="VCPreLinkEventTool"
   9.430 +			/>
   9.431 +			<Tool
   9.432 +				Name="VCLinkerTool"
   9.433 +				AdditionalDependencies="msvcrtd.lib"
   9.434 +				IgnoreAllDefaultLibraries="true"
   9.435 +				ModuleDefinitionFile="$(ProjectDir)\liblfds.def"
   9.436 +			/>
   9.437 +			<Tool
   9.438 +				Name="VCALinkTool"
   9.439 +			/>
   9.440 +			<Tool
   9.441 +				Name="VCManifestTool"
   9.442 +			/>
   9.443 +			<Tool
   9.444 +				Name="VCXDCMakeTool"
   9.445 +			/>
   9.446 +			<Tool
   9.447 +				Name="VCBscMakeTool"
   9.448 +			/>
   9.449 +			<Tool
   9.450 +				Name="VCFxCopTool"
   9.451 +			/>
   9.452 +			<Tool
   9.453 +				Name="VCAppVerifierTool"
   9.454 +			/>
   9.455 +			<Tool
   9.456 +				Name="VCPostBuildEventTool"
   9.457 +			/>
   9.458 +		</Configuration>
   9.459 +		<Configuration
   9.460 +			Name="Release DLL|Win32"
   9.461 +			OutputDirectory="$(ProjectDir)\bin\$(PlatformName)\$(ConfigurationName)"
   9.462 +			IntermediateDirectory="$(ProjectDir)\obj\$(PlatformName)\$(ConfigurationName)"
   9.463 +			ConfigurationType="2"
   9.464 +			CharacterSet="1"
   9.465 +			WholeProgramOptimization="0"
   9.466 +			>
   9.467 +			<Tool
   9.468 +				Name="VCPreBuildEventTool"
   9.469 +			/>
   9.470 +			<Tool
   9.471 +				Name="VCCustomBuildTool"
   9.472 +			/>
   9.473 +			<Tool
   9.474 +				Name="VCXMLDataGeneratorTool"
   9.475 +			/>
   9.476 +			<Tool
   9.477 +				Name="VCWebServiceProxyGeneratorTool"
   9.478 +			/>
   9.479 +			<Tool
   9.480 +				Name="VCMIDLTool"
   9.481 +			/>
   9.482 +			<Tool
   9.483 +				Name="VCCLCompilerTool"
   9.484 +				AdditionalOptions="/DWIN32_LEAN_AND_MEAN /DNDEBUG"
   9.485 +				Optimization="3"
   9.486 +				EnableIntrinsicFunctions="true"
   9.487 +				FavorSizeOrSpeed="1"
   9.488 +				AdditionalIncludeDirectories="&quot;$(ProjectDir)\src&quot;;&quot;$(ProjectDir)\inc&quot;"
   9.489 +				StringPooling="true"
   9.490 +				ExceptionHandling="0"
   9.491 +				RuntimeLibrary="2"
   9.492 +				BufferSecurityCheck="false"
   9.493 +				EnableFunctionLevelLinking="true"
   9.494 +				WarningLevel="4"
   9.495 +				WarnAsError="true"
   9.496 +				DebugInformationFormat="0"
   9.497 +				CompileAs="1"
   9.498 +			/>
   9.499 +			<Tool
   9.500 +				Name="VCManagedResourceCompilerTool"
   9.501 +			/>
   9.502 +			<Tool
   9.503 +				Name="VCResourceCompilerTool"
   9.504 +			/>
   9.505 +			<Tool
   9.506 +				Name="VCPreLinkEventTool"
   9.507 +			/>
   9.508 +			<Tool
   9.509 +				Name="VCLinkerTool"
   9.510 +				AdditionalDependencies="msvcrt.lib"
   9.511 +				IgnoreAllDefaultLibraries="true"
   9.512 +				ModuleDefinitionFile="$(ProjectDir)\liblfds.def"
   9.513 +			/>
   9.514 +			<Tool
   9.515 +				Name="VCALinkTool"
   9.516 +			/>
   9.517 +			<Tool
   9.518 +				Name="VCManifestTool"
   9.519 +			/>
   9.520 +			<Tool
   9.521 +				Name="VCXDCMakeTool"
   9.522 +			/>
   9.523 +			<Tool
   9.524 +				Name="VCBscMakeTool"
   9.525 +			/>
   9.526 +			<Tool
   9.527 +				Name="VCFxCopTool"
   9.528 +			/>
   9.529 +			<Tool
   9.530 +				Name="VCAppVerifierTool"
   9.531 +			/>
   9.532 +			<Tool
   9.533 +				Name="VCPostBuildEventTool"
   9.534 +			/>
   9.535 +		</Configuration>
   9.536 +		<Configuration
   9.537 +			Name="Release DLL|x64"
   9.538 +			OutputDirectory="$(ProjectDir)\bin\$(PlatformName)\$(ConfigurationName)"
   9.539 +			IntermediateDirectory="$(ProjectDir)\obj\$(PlatformName)\$(ConfigurationName)"
   9.540 +			ConfigurationType="2"
   9.541 +			CharacterSet="1"
   9.542 +			WholeProgramOptimization="0"
   9.543 +			>
   9.544 +			<Tool
   9.545 +				Name="VCPreBuildEventTool"
   9.546 +			/>
   9.547 +			<Tool
   9.548 +				Name="VCCustomBuildTool"
   9.549 +			/>
   9.550 +			<Tool
   9.551 +				Name="VCXMLDataGeneratorTool"
   9.552 +			/>
   9.553 +			<Tool
   9.554 +				Name="VCWebServiceProxyGeneratorTool"
   9.555 +			/>
   9.556 +			<Tool
   9.557 +				Name="VCMIDLTool"
   9.558 +				TargetEnvironment="3"
   9.559 +			/>
   9.560 +			<Tool
   9.561 +				Name="VCCLCompilerTool"
   9.562 +				AdditionalOptions="/DWIN32_LEAN_AND_MEAN /DNDEBUG"
   9.563 +				Optimization="3"
   9.564 +				EnableIntrinsicFunctions="true"
   9.565 +				FavorSizeOrSpeed="1"
   9.566 +				AdditionalIncludeDirectories="&quot;$(ProjectDir)\src&quot;;&quot;$(ProjectDir)\inc&quot;"
   9.567 +				StringPooling="true"
   9.568 +				ExceptionHandling="0"
   9.569 +				RuntimeLibrary="2"
   9.570 +				BufferSecurityCheck="false"
   9.571 +				EnableFunctionLevelLinking="true"
   9.572 +				WarningLevel="4"
   9.573 +				WarnAsError="true"
   9.574 +				DebugInformationFormat="0"
   9.575 +				CompileAs="1"
   9.576 +			/>
   9.577 +			<Tool
   9.578 +				Name="VCManagedResourceCompilerTool"
   9.579 +			/>
   9.580 +			<Tool
   9.581 +				Name="VCResourceCompilerTool"
   9.582 +			/>
   9.583 +			<Tool
   9.584 +				Name="VCPreLinkEventTool"
   9.585 +			/>
   9.586 +			<Tool
   9.587 +				Name="VCLinkerTool"
   9.588 +				AdditionalDependencies="msvcrt.lib"
   9.589 +				IgnoreAllDefaultLibraries="true"
   9.590 +				ModuleDefinitionFile="$(ProjectDir)\liblfds.def"
   9.591 +			/>
   9.592 +			<Tool
   9.593 +				Name="VCALinkTool"
   9.594 +			/>
   9.595 +			<Tool
   9.596 +				Name="VCManifestTool"
   9.597 +			/>
   9.598 +			<Tool
   9.599 +				Name="VCXDCMakeTool"
   9.600 +			/>
   9.601 +			<Tool
   9.602 +				Name="VCBscMakeTool"
   9.603 +			/>
   9.604 +			<Tool
   9.605 +				Name="VCFxCopTool"
   9.606 +			/>
   9.607 +			<Tool
   9.608 +				Name="VCAppVerifierTool"
   9.609 +			/>
   9.610 +			<Tool
   9.611 +				Name="VCPostBuildEventTool"
   9.612 +			/>
   9.613 +		</Configuration>
   9.614 +	</Configurations>
   9.615 +	<References>
   9.616 +	</References>
   9.617 +	<Files>
   9.618 +		<Filter
   9.619 +			Name="inc"
   9.620 +			Filter="h;hpp;hxx;hm;inl;inc;xsd"
   9.621 +			UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
   9.622 +			>
   9.623 +			<File
   9.624 +				RelativePath=".\inc\abstraction.h"
   9.625 +				>
   9.626 +			</File>
   9.627 +			<File
   9.628 +				RelativePath=".\inc\freelist.h"
   9.629 +				>
   9.630 +			</File>
   9.631 +			<File
   9.632 +				RelativePath=".\inc\liblfds.h"
   9.633 +				>
   9.634 +			</File>
   9.635 +			<File
   9.636 +				RelativePath=".\inc\queue.h"
   9.637 +				>
   9.638 +			</File>
   9.639 +			<File
   9.640 +				RelativePath=".\inc\ringbuffer.h"
   9.641 +				>
   9.642 +			</File>
   9.643 +			<File
   9.644 +				RelativePath=".\inc\stack.h"
   9.645 +				>
   9.646 +			</File>
   9.647 +		</Filter>
   9.648 +		<Filter
   9.649 +			Name="src"
   9.650 +			>
   9.651 +			<File
   9.652 +				RelativePath=".\src\liblfds_internal.h"
   9.653 +				>
   9.654 +			</File>
   9.655 +			<Filter
   9.656 +				Name="abstraction"
   9.657 +				>
   9.658 +				<File
   9.659 +					RelativePath=".\src\abstraction\abstraction_aligned_free.c"
   9.660 +					>
   9.661 +				</File>
   9.662 +				<File
   9.663 +					RelativePath=".\src\abstraction\abstraction_aligned_malloc.c"
   9.664 +					>
   9.665 +				</File>
   9.666 +				<File
   9.667 +					RelativePath=".\src\abstraction\abstraction_cas.c"
   9.668 +					>
   9.669 +				</File>
   9.670 +				<File
   9.671 +					RelativePath=".\src\abstraction\abstraction_dcas.c"
   9.672 +					>
   9.673 +				</File>
   9.674 +				<File
   9.675 +					RelativePath=".\src\abstraction\abstraction_increment.c"
   9.676 +					>
   9.677 +				</File>
   9.678 +				<File
   9.679 +					RelativePath=".\src\abstraction\abstraction_internal.h"
   9.680 +					>
   9.681 +				</File>
   9.682 +			</Filter>
   9.683 +			<Filter
   9.684 +				Name="freelist"
   9.685 +				>
   9.686 +				<File
   9.687 +					RelativePath=".\src\freelist\freelist_delete.c"
   9.688 +					>
   9.689 +				</File>
   9.690 +				<File
   9.691 +					RelativePath=".\src\freelist\freelist_get_and_set.c"
   9.692 +					>
   9.693 +				</File>
   9.694 +				<File
   9.695 +					RelativePath=".\src\freelist\freelist_internal.h"
   9.696 +					>
   9.697 +				</File>
   9.698 +				<File
   9.699 +					RelativePath=".\src\freelist\freelist_new.c"
   9.700 +					>
   9.701 +				</File>
   9.702 +				<File
   9.703 +					RelativePath=".\src\freelist\freelist_pop_push.c"
   9.704 +					>
   9.705 +				</File>
   9.706 +				<File
   9.707 +					RelativePath=".\src\freelist\freelist_query.c"
   9.708 +					>
   9.709 +				</File>
   9.710 +			</Filter>
   9.711 +			<Filter
   9.712 +				Name="stack"
   9.713 +				>
   9.714 +				<File
   9.715 +					RelativePath=".\src\stack\stack_delete.c"
   9.716 +					>
   9.717 +				</File>
   9.718 +				<File
   9.719 +					RelativePath=".\src\stack\stack_internal.h"
   9.720 +					>
   9.721 +				</File>
   9.722 +				<File
   9.723 +					RelativePath=".\src\stack\stack_new.c"
   9.724 +					>
   9.725 +				</File>
   9.726 +				<File
   9.727 +					RelativePath=".\src\stack\stack_push_pop.c"
   9.728 +					>
   9.729 +				</File>
   9.730 +				<File
   9.731 +					RelativePath=".\src\stack\stack_query.c"
   9.732 +					>
   9.733 +				</File>
   9.734 +			</Filter>
   9.735 +			<Filter
   9.736 +				Name="ringbuffer"
   9.737 +				>
   9.738 +				<File
   9.739 +					RelativePath=".\src\ringbuffer\ringbuffer_delete.c"
   9.740 +					>
   9.741 +				</File>
   9.742 +				<File
   9.743 +					RelativePath=".\src\ringbuffer\ringbuffer_get_and_put.c"
   9.744 +					>
   9.745 +				</File>
   9.746 +				<File
   9.747 +					RelativePath=".\src\ringbuffer\ringbuffer_internal.h"
   9.748 +					>
   9.749 +				</File>
   9.750 +				<File
   9.751 +					RelativePath=".\src\ringbuffer\ringbuffer_new.c"
   9.752 +					>
   9.753 +				</File>
   9.754 +				<File
   9.755 +					RelativePath=".\src\ringbuffer\ringbuffer_query.c"
   9.756 +					>
   9.757 +				</File>
   9.758 +			</Filter>
   9.759 +			<Filter
   9.760 +				Name="queue"
   9.761 +				>
   9.762 +				<File
   9.763 +					RelativePath=".\src\queue\queue_delete.c"
   9.764 +					>
   9.765 +				</File>
   9.766 +				<File
   9.767 +					RelativePath=".\src\queue\queue_internal.h"
   9.768 +					>
   9.769 +				</File>
   9.770 +				<File
   9.771 +					RelativePath=".\src\queue\queue_new.c"
   9.772 +					>
   9.773 +				</File>
   9.774 +				<File
   9.775 +					RelativePath=".\src\queue\queue_query.c"
   9.776 +					>
   9.777 +				</File>
   9.778 +				<File
   9.779 +					RelativePath=".\src\queue\queue_queue.c"
   9.780 +					>
   9.781 +				</File>
   9.782 +			</Filter>
   9.783 +			<Filter
   9.784 +				Name="slist"
   9.785 +				>
   9.786 +				<File
   9.787 +					RelativePath=".\src\slist\slist_delete.c"
   9.788 +					>
   9.789 +				</File>
   9.790 +				<File
   9.791 +					RelativePath=".\src\slist\slist_get_and_set.c"
   9.792 +					>
   9.793 +				</File>
   9.794 +				<File
   9.795 +					RelativePath=".\src\slist\slist_internal.h"
   9.796 +					>
   9.797 +				</File>
   9.798 +				<File
   9.799 +					RelativePath=".\src\slist\slist_link.c"
   9.800 +					>
   9.801 +				</File>
   9.802 +				<File
   9.803 +					RelativePath=".\src\slist\slist_new.c"
   9.804 +					>
   9.805 +				</File>
   9.806 +			</Filter>
   9.807 +		</Filter>
   9.808 +	</Files>
   9.809 +	<Globals>
   9.810 +	</Globals>
   9.811 +</VisualStudioProject>
    10.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    10.2 +++ b/liblfds.6/makefile.linux	Sun Jan 31 21:28:42 2010 +1100
    10.3 @@ -0,0 +1,103 @@
    10.4 +##### paths #####
    10.5 +BINDIR  = bin
    10.6 +INCDIR  = inc
    10.7 +OBJDIR  = obj
    10.8 +SRCDIR  = src
    10.9 +
   10.10 +##### misc #####
   10.11 +QUIETLY = 1>/dev/null 2>/dev/null
   10.12 +
   10.13 +##### sources, objects and libraries #####
   10.14 +BINNAME = liblfds
   10.15 +AR_BINARY = $(BINDIR)/$(BINNAME).a
   10.16 +SO_BINARY = $(BINDIR)/$(BINNAME).so
   10.17 +SRCDIRS = abstraction freelist queue ringbuffer slist stack
   10.18 +# TRD : be aware - in the linux makefile, with the one-pass linking behaviour of the GNU linker, the order
   10.19 +#       of source files matters!  this is because it leads to the ordering of objects in the library and
   10.20 +#       that in turn, since the data structures all use the freelist API and the abstraction API, has to be
   10.21 +#       correct 
   10.22 +SOURCES = queue_delete.c queue_new.c queue_query.c queue_queue.c \
   10.23 +          ringbuffer_delete.c ringbuffer_get_and_put.c ringbuffer_new.c ringbuffer_query.c \
   10.24 +          slist_delete.c slist_get_and_set.c slist_link.c slist_new.c \
   10.25 +          stack_delete.c stack_new.c stack_push_pop.c stack_query.c \
   10.26 +          freelist_delete.c freelist_get_and_set.c freelist_new.c freelist_query.c freelist_pop_push.c \
   10.27 +          abstraction_aligned_free.c abstraction_aligned_malloc.c abstraction_cas.c abstraction_dcas.c abstraction_increment.c
   10.28 +OBJECTS = $(patsubst %.c,$(OBJDIR)/%.o,$(notdir $(SOURCES)))
   10.29 +
   10.30 +##### CPU variants #####
   10.31 +GCCARCH = $(shell uname -m)
   10.32 +
   10.33 +ifeq ($(GCCARCH),x86_64)
   10.34 +  GCCARCH = core2
   10.35 +endif
   10.36 +
   10.37 +ifeq ($(findstring arm,$(GCCARCH)),arm)
   10.38 +  GCCARCH = armv6k
   10.39 +endif
   10.40 +
   10.41 +##### tools #####
   10.42 +MAKE    = make
   10.43 +MFLAGS  = 
   10.44 +
   10.45 +DG      = gcc
   10.46 +DGFLAGS = -MM -std=c99 -I"$(SRCDIR)" -I"$(INCDIR)"
   10.47 +
   10.48 +CC      = gcc
   10.49 +CBASE   = -Wall -Wno-unknown-pragmas -std=c99 -march=$(GCCARCH) -c -I"$(SRCDIR)" -I"$(INCDIR)"
   10.50 +CFREL   = -O2 -finline-functions -Wno-strict-aliasing
   10.51 +CFDBG   = -O0 -g
   10.52 +
   10.53 +AR      = ar
   10.54 +AFLAGS  = -rcs
   10.55 +
   10.56 +LD      = gcc
   10.57 +LFBASE  = -Wall -std=c99 -shared
   10.58 +LFREL   = -O2 -s
   10.59 +LFDBG   = -O0 -g
   10.60 +
   10.61 +##### rel/dbg .a/.so variants #####
   10.62 +ifeq ($(findstring so,$(MAKECMDGOALS)),so)
   10.63 +  CBASE := $(CBASE) -fpic
   10.64 +endif
   10.65 +
   10.66 +CFLAGS  = $(CBASE) $(CFDBG)
   10.67 +LFLAGS  = $(LFBASE) $(LFDBG)
   10.68 +
   10.69 +ifeq ($(findstring rel,$(MAKECMDGOALS)),rel)
   10.70 +  CFLAGS  = $(CBASE) $(CFREL)
   10.71 +  LFLAGS  = $(LFBASE) $(LFREL)
   10.72 +endif
   10.73 +
   10.74 +##### search paths #####
   10.75 +vpath %.c $(patsubst %,$(SRCDIR)/%:,$(SRCDIRS))
   10.76 +
   10.77 +##### implicit rules #####
   10.78 +$(OBJDIR)/%.o : %.c
   10.79 +	$(DG) $(DGFLAGS) $< >$(OBJDIR)/$*.d
   10.80 +	$(CC) $(CFLAGS) -o $@ $<
   10.81 +
   10.82 +##### explicit rules #####
   10.83 +$(AR_BINARY) : $(OBJECTS)
   10.84 +	$(AR) $(AFLAGS) $(AR_BINARY) $(OBJECTS)
   10.85 +
   10.86 +$(SO_BINARY) : $(OBJECTS)
   10.87 +	$(LD) $(LFLAGS) $(SYSLIBS) $(OBJECTS) -o $(SO_BINARY)
   10.88 +
   10.89 +##### phony #####
   10.90 +.PHONY : clean arrel ardbg sorel sodbg
   10.91 +
   10.92 +clean : 
   10.93 +	@rm -f $(BINDIR)/$(BINNAME).* $(OBJDIR)/*.o $(OBJDIR)/*.d
   10.94 +
   10.95 +arrel : $(AR_BINARY)
   10.96 +ardbg : $(AR_BINARY)
   10.97 +
   10.98 +sorel : $(SO_BINARY)
   10.99 +sodbg : $(SO_BINARY)
  10.100 +
  10.101 +##### dependencies #####
  10.102 +-include $(DEPENDS)
  10.103 +
  10.104 +##### notes #####
  10.105 +# TRD : we use -std=c99 purely to permit C++ style comments
  10.106 +
    11.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    11.2 +++ b/liblfds.6/makefile.windows	Sun Jan 31 21:28:42 2010 +1100
    11.3 @@ -0,0 +1,94 @@
    11.4 +##### paths #####
    11.5 +BINDIR  = bin
    11.6 +INCDIR  = inc
    11.7 +OBJDIR  = obj
    11.8 +SRCDIR  = src
    11.9 +
   11.10 +##### misc #####
   11.11 +QUIETLY = 1>nul 2>nul
   11.12 +
   11.13 +##### sources, objects and libraries #####
   11.14 +BINNAME = liblfds
   11.15 +LIB_BINARY = $(BINDIR)\$(BINNAME).lib
   11.16 +DLL_BINARY = $(BINDIR)\$(BINNAME).dll
   11.17 +SRCDIRS = abstraction freelist queue ringbuffer slist stack
   11.18 +SOURCES = abstraction_aligned_free.c abstraction_aligned_malloc.c abstraction_cas.c abstraction_dcas.c abstraction_increment.c \
   11.19 +          freelist_delete.c freelist_get_and_set.c freelist_new.c freelist_query.c freelist_pop_push.c \
   11.20 +          queue_delete.c queue_new.c queue_query.c queue_queue.c \
   11.21 +          ringbuffer_delete.c ringbuffer_get_and_put.c ringbuffer_new.c ringbuffer_query.c \
   11.22 +          slist_delete.c slist_get_and_set.c slist_link.c slist_new.c \
   11.23 +          stack_delete.c stack_new.c stack_push_pop.c stack_query.c
   11.24 +OBJECTS = $(patsubst %.c,$(OBJDIR)/%.obj,$(notdir $(SOURCES)))
   11.25 +
   11.26 +##### tools #####
   11.27 +MAKE    = make
   11.28 +MFLAGS  = 
   11.29 +
   11.30 +CC      = cl
   11.31 +CBASE   = /nologo /W4 /WX /c "-I$(SRCDIR)" "-I$(INCDIR)" "/Fd$(BINDIR)\$(BINNAME).pdb" /DUNICODE /D_UNICODE /DWIN32_LEAN_AND_MEAN
   11.32 +CFREL   = /Ox /DNDEBUG
   11.33 +CFDBG   = /Od /Gm /Zi /D_DEBUG
   11.34 +
   11.35 +AR      = lib
   11.36 +AFLAGS  = /nologo /subsystem:console /wx /verbose
   11.37 +
   11.38 +LD      = link
   11.39 +LFBASE  = /dll /def:$(BINNAME).def /nologo /subsystem:console /wx /nodefaultlib /nxcompat
   11.40 +LFREL   = /incremental:no
   11.41 +LFDBG   = /debug "/pdb:$(BINDIR)\$(BINNAME).pdb"
   11.42 +
   11.43 +##### variants #####
   11.44 +CFLAGS  = $(CBASE) $(CFDBG) /MTd
   11.45 +LFLAGS  = $(LFBASE) $(LFDBG)
   11.46 +CLIB    = libcmtd.lib
   11.47 +
   11.48 +ifeq ($(MAKECMDGOALS),librel)
   11.49 +  CFLAGS  = $(CBASE) $(CFREL) /MT
   11.50 +  LFLAGS  = $(LFBASE) $(LFREL)
   11.51 +  CLIB    = libcmt.lib
   11.52 +endif
   11.53 +
   11.54 +ifeq ($(MAKECMDGOALS),libdbg)
   11.55 +  CFLAGS  = $(CBASE) $(CFDBG) /MTd
   11.56 +  LFLAGS  = $(LFBASE) $(LFDBG)
   11.57 +  CLIB    = libcmtd.lib
   11.58 +endif
   11.59 +
   11.60 +ifeq ($(MAKECMDGOALS),dllrel)
   11.61 +  CFLAGS  = $(CBASE) $(CFREL) /MD
   11.62 +  LFLAGS  = $(LFBASE) $(LFREL)
   11.63 +  CLIB    = msvcrt.lib
   11.64 +endif
   11.65 +
   11.66 +ifeq ($(MAKECMDGOALS),dlldbg)
   11.67 +  CFLAGS  = $(CBASE) $(CFDBG) /MDd
   11.68 +  LFLAGS  = $(LFBASE) $(LFDBG)
   11.69 +  CLIB    = msvcrtd.lib
   11.70 +endif
   11.71 +
   11.72 +##### search paths #####
   11.73 +vpath %.c $(patsubst %,$(SRCDIR)/%;,$(SRCDIRS))
   11.74 +
   11.75 +##### implicit rules #####
   11.76 +$(OBJDIR)/%.obj : %.c
   11.77 +	$(CC) $(CFLAGS) "/Fo$@" $<
   11.78 +
   11.79 +##### explicit rules #####
   11.80 +$(LIB_BINARY) : $(OBJECTS)
   11.81 +	$(AR) $(AFLAGS) $(OBJECTS) /out:$(LIB_BINARY)
   11.82 +
   11.83 +$(DLL_BINARY) : $(OBJECTS)
   11.84 +	$(LD) $(LFLAGS) $(CLIB) $(OBJECTS) /out:$(DLL_BINARY)
   11.85 +
   11.86 +##### phony #####
   11.87 +.PHONY : clean librel libdbg dllrel dlldbg
   11.88 +
   11.89 +clean : 
   11.90 +	@erase /Q $(BINDIR)\$(BINNAME).* $(OBJDIR)\*.obj $(QUIETLY)
   11.91 +
   11.92 +librel : $(LIB_BINARY)
   11.93 +libdbg : $(LIB_BINARY)
   11.94 +
   11.95 +dllrel : $(DLL_BINARY)
   11.96 +dlldbg : $(DLL_BINARY)
   11.97 +
    12.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    12.2 +++ b/liblfds.6/readme.txt	Sun Jan 31 21:28:42 2010 +1100
    12.3 @@ -0,0 +1,131 @@
    12.4 +introduction
    12.5 +============
    12.6 +Welcome to liblfds, a portable, license-free, lock-free data structure
    12.7 +library written in C.
    12.8 +
    12.9 +platforms
   12.10 +=========
   12.11 +Currently liblfds out-of-the-box supports;
   12.12 +
   12.13 +Operating System  CPU         Toolset
   12.14 +================  ==========  =======
   12.15 +Windows 64-bit    IA64 & x64  1. Microsoft Visual Studio 2008
   12.16 +                              2. Microsoft Windows SDK and GNUmake >= 3.8.1
   12.17 +
   12.18 +Windows 32-bit 	  x64 & x86   1. Microsoft Visual Studio 2008
   12.19 +                              2. Visual C++ 2008 Express Edition
   12.20 +                              3. Microsoft Windows SDK and GNUmake >= 3.8.1
   12.21 +
   12.22 +Windows Kernel    IA64, x64,  1. Windows Driver Kit >= 7.0.0
   12.23 +                  x86
   12.24 +
   12.25 +Linux 64-bit      x64         1. GCC >= 4.1.0 and GNUmake >= 3.8.1
   12.26 +
   12.27 +Linux 32-bit      x64, x86,   1. GCC >= 4.1.0 and GNUmake >= 3.8.1 
   12.28 +                  ARM
   12.29 +
   12.30 +data structures
   12.31 +===============
   12.32 +Currently liblfds provides the following;
   12.33 +
   12.34 +* Freelist
   12.35 +* Queue
   12.36 +* Ringbuffer
   12.37 +* Singly linked list (logical delete only)
   12.38 +* Stack
   12.39 +
   12.40 +liblfds on-line
   12.41 +===============
   12.42 +On the liblfds home page, you will find the blog, a bugzilla, a forum, a
   12.43 +wikipedia and the current and all historical source releases.
   12.44 +
   12.45 +The wikipedia contains comprehensive documentation for development,
   12.46 +building, testing and porting.
   12.47 +
   12.48 +http://www.liblfds.org
   12.49 +
   12.50 +license
   12.51 +=======
   12.52 +There is no license.  You are free to use this code in any way.
   12.53 +
   12.54 +building
   12.55 +========
   12.56 +On Windows, depending on your target platform, one of the following toolchains
   12.57 +is required;
   12.58 +
   12.59 +    * Microsoft Visual Studio 2008 (expensive)
   12.60 +    * Visual C++ 2008 Express Edition (free, but no 64 bit support)
   12.61 +    * Microsoft Windows SDK (free, no GUI, has 64 bit support) and GNUmake 3.81 
   12.62 +
   12.63 +On Windows (kernel-mode), the following toolchain is required; 
   12.64 +
   12.65 +    * Windows Driver Kit 7.0.0 or later
   12.66 +
   12.67 +On Linux, the following toolchain is required;
   12.68 +
   12.69 +    * gcc 4.1.0 or later and GNUmake 3.81 
   12.70 +
   12.71 +For documentation, see the building guide in the wikipedia.
   12.72 +
   12.73 +using
   12.74 +=====
   12.75 +Once built, there is a single header file, /inc/liblfds.h, which you must include
   12.76 +in your source code, and a single library file /bin/liblfds.*, where the suffix
   12.77 +depends on your platform and your build choice (static or dynamic), to which,
   12.78 +if statically built, you must link directly or, if dynamically built, you must
   12.79 +arrange your system such that the library can be found by the loader at run-time. 
   12.80 +
   12.81 +testing
   12.82 +=======
   12.83 +The library comes with a command line test and benchmark program.  This
   12.84 +program requires threads.  As such, it is only suitable for platforms providing
   12.85 +thread support and which can execute a command line binary.  Currently this
   12.86 +means the test and benchmark program works for all platforms except the Windows
   12.87 +Kernel.
   12.88 +
   12.89 +For documentation, see the testing and benchmarking guide in the wikipedia.
   12.90 +
   12.91 +porting
   12.92 +=======
   12.93 +Both the test program and liblfds provide an abstraction layer which acts to
   12.94 +mask platform differences. Porting is the act of implementing on your platform
   12.95 +the functions which make up the abstraction layers.  You do not need to port
   12.96 +the test program to port liblfds, but obviously it is recommended, so you can
   12.97 +test your port.
   12.98 +
   12.99 +To support liblfds, your platform must support either contigious double-word
  12.100 +compare-and-swap (e.g. x86/x64) or contigious double-word load-link/conditional-store
  12.101 +where normal loads cannot occur inside the LL/CS pair (e.g. ARM) or single word
  12.102 +load-link/conditional-store where normal loads can occur inside the LL/CS pair.
  12.103 +
  12.104 +For documentation, see the porting guide in the wikipedia.
  12.105 +
  12.106 +release history
  12.107 +===============
  12.108 +release 1, 25th September 2009, svn revision 1574.
  12.109 +  - initial release
  12.110 +
  12.111 +release 2, 5th October 2009, svn revision 1599.
  12.112 +  - added abstraction layer for Windows kernel
  12.113 +  - minor code tidyups/fixes
  12.114 +
  12.115 +release 3, 25th October 2009, svn revision 1652.
  12.116 +  - added singly linked list (logical delete only)
  12.117 +  - minor code tidyups/fixes
  12.118 +
  12.119 +release 4, 7th December 2009, svn revision 1716.
  12.120 +  - added ARM support
  12.121 +  - added benchmarking functionality to the test program
  12.122 +  - fixed a profound and pervasive pointer
  12.123 +    decleration bug; earlier releases of liblfds
  12.124 +    *should not be used*
  12.125 +
  12.126 +release 5, 19th December 2009, svn revision 1738.
  12.127 +  - fixed subtle queue bug, which also affected ringbuffer
  12.128 +    and caused data re-ordering under high load
  12.129 +  - added benchmarks for freelist, ringbuffer and stack
  12.130 +
  12.131 +release 6, 29th December 2009, svn revision 1746.
  12.132 +  - fixed two implementation errors, which reduced performance,
  12.133 +    spotted by Codeplug from "http://cboard.cprogramming.com".
  12.134 + 
    13.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    13.2 +++ b/liblfds.6/runme_before_win_kernel_build_readme.txt	Sun Jan 31 21:28:42 2010 +1100
    13.3 @@ -0,0 +1,32 @@
    13.4 +The Windows kernel build environment is primitive and has a number
    13.5 +of severe limitations; in particular, all source files must be in
    13.6 +one directory and it is not possible to choose the output binary type
    13.7 +(static or dynamic library) from the build command line; rather,
    13.8 +a string has to be modified in a text file used by the build (!)
    13.9 +
   13.10 +To deal with these limitations, it is necessary for a Windows kernel
   13.11 +build to run a batch file prior to building.
   13.12 +
   13.13 +There are two batch files, one for static library builds and the other
   13.14 +for dynamic library builds.
   13.15 +
   13.16 +They are both idempotent; you can run them as often as you like and
   13.17 +switch between them as often as you want.  It's all fine; whenever
   13.18 +you run one of them, it will take you from whatever state you were
   13.19 +previously in, into the state you want to be in.
   13.20 +
   13.21 +Both batch files copy all the sources file into a single directory,
   13.22 +"/src/single_dir_for_windows_kernel/".
   13.23 +
   13.24 +The static library batch file will then copy "/sources.static" into
   13.25 +"/src/single_dir_for_windows_kernel/", which will cause a static
   13.26 +library to be built.
   13.27 +
   13.28 +The dynamic library batch file will then copy "/sources.dynamic" into
   13.29 +"/src/single_dir_for_windows_kernel/", which will cause a dynamic
   13.30 +library to be built.  It will also copy "src/driver_entry.c" into
   13.31 +"/src/single_dir_for_windows_kernel/", since the linker requires
   13.32 +the DriverEntry function to exist for dynamic libraries, even
   13.33 +though it's not used.
   13.34 +
   13.35 +
    14.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    14.2 +++ b/liblfds.6/runme_before_win_kernel_dynamic_lib_build.bat	Sun Jan 31 21:28:42 2010 +1100
    14.3 @@ -0,0 +1,14 @@
    14.4 +@echo off
    14.5 +rmdir /q /s src\single_dir_for_windows_kernel 1>nul 2>nul
    14.6 +mkdir src\single_dir_for_windows_kernel 1>nul 2>nul
    14.7 +copy /y src\abstraction\* src\single_dir_for_windows_kernel 1>nul 2>nul
    14.8 +copy /y src\freelist\* src\single_dir_for_windows_kernel 1>nul 2>nul
    14.9 +copy /y src\queue\* src\single_dir_for_windows_kernel 1>nul 2>nul
   14.10 +copy /y src\ringbuffer\* src\single_dir_for_windows_kernel 1>nul 2>nul
   14.11 +copy /y src\slist\* src\single_dir_for_windows_kernel 1>nul 2>nul
   14.12 +copy /y src\stack\* src\single_dir_for_windows_kernel 1>nul 2>nul
   14.13 +copy /y sources.dynamic src\single_dir_for_windows_kernel\sources 1>nul 2>nul
   14.14 +copy /y src\driver_entry.c src\single_dir_for_windows_kernel 1>nul 2>nul
   14.15 +echo Windows kernel dynamic library build directory structure created.
   14.16 +echo (Note the effects of this batch file are idempotent).
   14.17 +
    15.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    15.2 +++ b/liblfds.6/runme_before_win_kernel_static_lib_build.bat	Sun Jan 31 21:28:42 2010 +1100
    15.3 @@ -0,0 +1,14 @@
    15.4 +@echo off
    15.5 +rmdir /q /s src\single_dir_for_windows_kernel 1>nul 2>nul
    15.6 +mkdir src\single_dir_for_windows_kernel 1>nul 2>nul
    15.7 +copy /y src\abstraction\* src\single_dir_for_windows_kernel 1>nul 2>nul
    15.8 +copy /y src\freelist\* src\single_dir_for_windows_kernel 1>nul 2>nul
    15.9 +copy /y src\queue\* src\single_dir_for_windows_kernel 1>nul 2>nul
   15.10 +copy /y src\ringbuffer\* src\single_dir_for_windows_kernel 1>nul 2>nul
   15.11 +copy /y src\slist\* src\single_dir_for_windows_kernel 1>nul 2>nul
   15.12 +copy /y src\stack\* src\single_dir_for_windows_kernel 1>nul 2>nul
   15.13 +copy /y sources.static src\single_dir_for_windows_kernel\sources 1>nul 2>nul
   15.14 +erase /f src\single_dir_for_windows_kernel\driver_entry.c 1>nul 2>nul
   15.15 +echo Windows kernel static library build directory structure created.
   15.16 +echo (Note the effects of this batch file are idempotent).
   15.17 +
    16.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    16.2 +++ b/liblfds.6/sources.dynamic	Sun Jan 31 21:28:42 2010 +1100
    16.3 @@ -0,0 +1,37 @@
    16.4 +MSC_WARNING_LEVEL = /WX /W4
    16.5 +DLLDEF            = ../../liblfds.def
    16.6 +TARGETNAME        = liblfds
    16.7 +TARGETPATH        = ../../bin/
    16.8 +TARGETTYPE        = EXPORT_DRIVER
    16.9 +UMTYPE            = nt
   16.10 +USER_C_FLAGS      = /DWIN_KERNEL_BUILD
   16.11 +
   16.12 +INCLUDES = ..;../../inc/
   16.13 +SOURCES  = abstraction_aligned_free.c \
   16.14 +           abstraction_aligned_malloc.c \
   16.15 +           abstraction_cas.c \
   16.16 +           abstraction_dcas.c \
   16.17 +           abstraction_increment.c \
   16.18 +           freelist_delete.c \
   16.19 +           freelist_get_and_set.c \
   16.20 +           freelist_new.c \
   16.21 +           freelist_pop_push.c \
   16.22 +           freelist_query.c \
   16.23 +           queue_delete.c \
   16.24 +           queue_new.c \
   16.25 +           queue_query.c \
   16.26 +           queue_queue.c \
   16.27 +           ringbuffer_delete.c \
   16.28 +           ringbuffer_get_and_put.c \
   16.29 +           ringbuffer_new.c \
   16.30 +           ringbuffer_query.c \
   16.31 +           slist_delete.c \
   16.32 +           slist_get_and_set.c \
   16.33 +           slist_link.c \
   16.34 +           slist_new.c \
   16.35 +           stack_delete.c \
   16.36 +           stack_new.c \
   16.37 +           stack_push_pop.c \
   16.38 +           stack_query.c \
   16.39 +           driver_entry.c
   16.40 +
    17.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    17.2 +++ b/liblfds.6/sources.static	Sun Jan 31 21:28:42 2010 +1100
    17.3 @@ -0,0 +1,35 @@
    17.4 +MSC_WARNING_LEVEL = /WX /W4
    17.5 +TARGETNAME        = liblfds
    17.6 +TARGETPATH        = ../../bin/
    17.7 +TARGETTYPE        = DRIVER_LIBRARY
    17.8 +UMTYPE            = nt
    17.9 +USER_C_FLAGS      = /DWIN_KERNEL_BUILD
   17.10 +
   17.11 +INCLUDES = ..;../../inc/
   17.12 +SOURCES  = abstraction_aligned_free.c \
   17.13 +           abstraction_aligned_malloc.c \
   17.14 +           abstraction_cas.c \
   17.15 +           abstraction_dcas.c \
   17.16 +           abstraction_increment.c \
   17.17 +           freelist_delete.c \
   17.18 +           freelist_get_and_set.c \
   17.19 +           freelist_new.c \
   17.20 +           freelist_pop_push.c \
   17.21 +           freelist_query.c \
   17.22 +           queue_delete.c \
   17.23 +           queue_new.c \
   17.24 +           queue_query.c \
   17.25 +           queue_queue.c \
   17.26 +           ringbuffer_delete.c \
   17.27 +           ringbuffer_get_and_put.c \
   17.28 +           ringbuffer_new.c \
   17.29 +           ringbuffer_query.c \
   17.30 +           slist_delete.c \
   17.31 +           slist_get_and_set.c \
   17.32 +           slist_link.c \
   17.33 +           slist_new.c \
   17.34 +           stack_delete.c \
   17.35 +           stack_new.c \
   17.36 +           stack_push_pop.c \
   17.37 +           stack_query.c
   17.38 +
    18.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    18.2 +++ b/liblfds.6/src/abstraction/abstraction_aligned_free.c	Sun Jan 31 21:28:42 2010 +1100
    18.3 @@ -0,0 +1,72 @@
    18.4 +#include "abstraction_internal.h"
    18.5 +
    18.6 +
    18.7 +
    18.8 +
    18.9 +
   18.10 +/****************************************************************************/
   18.11 +#if (defined _WIN32 && defined _MSC_VER && !defined WIN_KERNEL_BUILD)
   18.12 +
   18.13 +  /* TRD : any Windows (user-mode) on any CPU with the Microsoft C compiler
   18.14 +
   18.15 +           _WIN32             indicates 64-bit or 32-bit Windows
   18.16 +           _MSC_VER           indicates Microsoft C compiler
   18.17 +           !WIN_KERNEL_BUILD  indicates Windows user-mode
   18.18 +  */
   18.19 +
   18.20 +  void abstraction_aligned_free( void *memory )
   18.21 +  {
   18.22 +    _aligned_free( memory );
   18.23 +
   18.24 +    return;
   18.25 +  }
   18.26 +
   18.27 +#endif
   18.28 +
   18.29 +
   18.30 +
   18.31 +
   18.32 +
   18.33 +/****************************************************************************/
   18.34 +#if (_XOPEN_SOURCE >= 600)
   18.35 +
   18.36 +  /* TRD : any OS on any CPU with any compiler with POSIX 6.00 or better
   18.37 +
   18.38 +           _XOPEN_SOURCE  is actually set by the user, not by the compiler
   18.39 +                          it is the way the user signals to the compiler what
   18.40 +                          level of POSIX should be available
   18.41 +                          (it assumes of course the compiler has support for the given level of POSIX requested)
   18.42 +  */
   18.43 +
   18.44 +  void abstraction_aligned_free( void *memory )
   18.45 +  {
   18.46 +    free( memory );
   18.47 +
   18.48 +    return;
   18.49 +  }
   18.50 +
   18.51 +#endif
   18.52 +
   18.53 +
   18.54 +
   18.55 +
   18.56 +
   18.57 +/****************************************************************************/
   18.58 +#if (defined _WIN32 && defined _MSC_VER && defined WIN_KERNEL_BUILD)
   18.59 +
   18.60 +  /* TRD : any Windows (kernel) on any CPU with the Microsoft C compiler
   18.61 +
   18.62 +           _WIN32            indicates 64-bit or 32-bit Windows
   18.63 +           _MSC_VER          indicates Microsoft C compiler
   18.64 +           WIN_KERNEL_BUILD  indicates Windows kernel
   18.65 +  */
   18.66 +
   18.67 +  void abstraction_aligned_free( void *memory )
   18.68 +  {
   18.69 +    ExFreePoolWithTag( memory, 'sdfl' );
   18.70 +
   18.71 +    return;
   18.72 +  }
   18.73 +
   18.74 +#endif
   18.75 +
    19.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    19.2 +++ b/liblfds.6/src/abstraction/abstraction_aligned_malloc.c	Sun Jan 31 21:28:42 2010 +1100
    19.3 @@ -0,0 +1,97 @@
    19.4 +#include "abstraction_internal.h"
    19.5 +
    19.6 +
    19.7 +
    19.8 +
    19.9 +
   19.10 +/****************************************************************************/
   19.11 +#if (defined _WIN32 && defined _MSC_VER && !defined WIN_KERNEL_BUILD)
   19.12 +
   19.13 +  /* TRD : any Windows (user-mode) on any CPU with the Microsoft C compiler
   19.14 +
   19.15 +           _WIN32             indicates 64-bit or 32-bit Windows
   19.16 +           _MSC_VER           indicates Microsoft C compiler
   19.17 +           !WIN_KERNEL_BUILD  indicates Windows user-mode
   19.18 +  */
   19.19 +
   19.20 +  void *abstraction_aligned_malloc( size_t size, size_t align_in_bytes )
   19.21 +  {
   19.22 +    void
   19.23 +      *rv;
   19.24 +
   19.25 +    rv = _aligned_malloc( size, align_in_bytes );
   19.26 +
   19.27 +    return( rv );
   19.28 +  }
   19.29 +
   19.30 +#endif
   19.31 +
   19.32 +
   19.33 +
   19.34 +
   19.35 +
   19.36 +/****************************************************************************/
   19.37 +#if (_XOPEN_SOURCE >= 600)
   19.38 +
   19.39 +  /* TRD : any OS on any CPU with any compiler with POSIX 6.00 or better
   19.40 +
   19.41 +           _XOPEN_SOURCE  is actually set by the user, not by the compiler
   19.42 +                          it is the way the user signals to the compiler what
   19.43 +                          level of POSIX should be available
   19.44 +                          (it assumes of course the compiler has support for the given level of POSIX requested)
   19.45 +  */
   19.46 +
   19.47 +  void *abstraction_aligned_malloc( size_t size, size_t align_in_bytes )
   19.48 +  {
   19.49 +    int
   19.50 +      rv;
   19.51 +
   19.52 +    void
   19.53 +      *memory;
   19.54 +
   19.55 +    rv = posix_memalign( &memory, align_in_bytes, size );
   19.56 +
   19.57 +    // TRD : posix_memalign returns 0 on success, docs do not say *memory == NULL on fail
   19.58 +    if( rv != 0 )
   19.59 +      memory = NULL;
   19.60 +
   19.61 +    return( memory );
   19.62 +  }
   19.63 +
   19.64 +#endif
   19.65 +
   19.66 +
   19.67 +
   19.68 +
   19.69 +
   19.70 +/****************************************************************************/
   19.71 +#if (defined _WIN32 && defined _MSC_VER && defined WIN_KERNEL_BUILD)
   19.72 +
   19.73 +  /* TRD : any Windows (kernel) on any CPU with the Microsoft C compiler
   19.74 +
   19.75 +           _WIN32            indicates 64-bit or 32-bit Windows
   19.76 +           _MSC_VER          indicates Microsoft C compiler
   19.77 +           WIN_KERNEL_BUILD  indicates Windows kernel
   19.78 +  */
   19.79 +
   19.80 +  void *abstraction_aligned_malloc( size_t size, size_t align_in_bytes )
   19.81 +  {
   19.82 +    void
   19.83 +      *rv;
   19.84 +
   19.85 +    /* TRD : ExAllocatePoolWithTag() allocates memory aligned on 8 bytes on 32-bit CPUs
   19.86 +             and on 16 bytes on 64-bit CPUs, which is what we want
   19.87 +
   19.88 +             as such, align_in_bytes is not needed; we must refer to it to avoid the
   19.89 +             compiler warning
   19.90 +    */
   19.91 +
   19.92 +    align_in_bytes;
   19.93 +
   19.94 +    rv = ExAllocatePoolWithTag( NonPagedPool, size, 'sdfl' );
   19.95 +
   19.96 +    return( rv );
   19.97 +  }
   19.98 +
   19.99 +#endif
  19.100 +
    20.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    20.2 +++ b/liblfds.6/src/abstraction/abstraction_cas.c	Sun Jan 31 21:28:42 2010 +1100
    20.3 @@ -0,0 +1,109 @@
    20.4 +#include "abstraction_internal.h"
    20.5 +
    20.6 +
    20.7 +
    20.8 +
    20.9 +
   20.10 +/****************************************************************************/
   20.11 +#if (defined _WIN32 && defined _MSC_VER)
   20.12 +
   20.13 +  /* TRD : 64 bit and 32 bit Windows (user-mode or kernel) on any CPU with the Microsoft C compiler
   20.14 +
   20.15 +           _WIN32    indicates 64-bit or 32-bit Windows
   20.16 +           _MSC_VER  indicates Microsoft C compiler
   20.17 +  */
   20.18 +
   20.19 +  INLINE atom_t abstraction_cas( volatile atom_t *destination, atom_t exchange, atom_t compare )
   20.20 +  {
   20.21 +    assert( destination != NULL );
   20.22 +    // TRD : exchange can be any value in its range
   20.23 +    // TRD : compare can be any value in its range
   20.24 +
   20.25 +    return( (atom_t) _InterlockedCompareExchangePointer((void * volatile *) destination, (void *) exchange, (void *) compare) );
   20.26 +  }
   20.27 +
   20.28 +#endif
   20.29 +
   20.30 +
   20.31 +
   20.32 +
   20.33 +
   20.34 +/****************************************************************************/
   20.35 +#if (!defined __arm__ && __GNUC__ >= 4 && __GNUC_MINOR__ >= 1 && __GNUC_PATCHLEVEL__ >= 0)
   20.36 +
   20.37 +  /* TRD : any OS on any CPU except ARM with GCC 4.1.0 or better
   20.38 +
   20.39 +           GCC 4.1.0 introduced the __sync_*() atomic intrinsics
   20.40 +
   20.41 +           __GNUC__ / __GNUC_MINOR__ / __GNUC_PATCHLEVEL__  indicates GCC and which version
   20.42 +  */
   20.43 +
   20.44 +  INLINE atom_t abstraction_cas( volatile atom_t *destination, atom_t exchange, atom_t compare )
   20.45 +  {
   20.46 +    assert( destination != NULL );
   20.47 +    // TRD : exchange can be any value in its range
   20.48 +    // TRD : compare can be any value in its range
   20.49 +
   20.50 +    // TRD : note the different argument order for the GCC instrinsic to the MSVC instrinsic
   20.51 +
   20.52 +    return( (atom_t) __sync_val_compare_and_swap(destination, compare, exchange) );
   20.53 +  }
   20.54 +
   20.55 +#endif
   20.56 +
   20.57 +
   20.58 +
   20.59 +
   20.60 +
   20.61 +/****************************************************************************/
   20.62 +#if (defined __arm__ && __GNUC__)
   20.63 +
   20.64 +  /* TRD : any OS on any ARM with GCC
   20.65 +
   20.66 +           Remember however we need to set into compare the original value of destination.
   20.67 +
   20.68 +           __arm__   indicates ARM
   20.69 +           __GNUC__  indicates GCC
   20.70 +  */
   20.71 +
   20.72 +  INLINE atom_t abstraction_cas( volatile atom_t *destination, atom_t exchange, atom_t compare )
   20.73 +  {
   20.74 +    atom_t
   20.75 +      stored_flag,
   20.76 +      original_destination;
   20.77 +
   20.78 +    assert( destination != NULL );
   20.79 +    // TRD : exchange can be any value in its range
   20.80 +    // TRD : compare can be any value in its range
   20.81 +
   20.82 +    /* TRD : this is a standard, plain CAS, vulnerable to ABA */
   20.83 +
   20.84 +    __asm__ __volatile__
   20.85 +    (
   20.86 +      "  mov    %[stored_flag], #1;"                             // put 1 into stored_flag
   20.87 +      "  mcr    p15, 0, %[zero], c7, c10, 5;"                    // memory barrier (ARM v6 compatible)
   20.88 +      "atomic_cas:;"
   20.89 +      "  ldrex  %[original_destination], [%[destination]];"      // load *destination into original_destination
   20.90 +      "  teq    %[original_destination], %[compare];"            // compare original_destination with compare
   20.91 +      "  bne    exit;"                                           // if not equal, exit
   20.92 +      "  strex  %[stored_flag], %[exchange], [%[destination]];"  // if equal, try to store exchange into *destination (on success, strex puts 0 into stored_flag)
   20.93 +      "  teq    %[stored_flag], #0;"                             // check if stored_flag is 0
   20.94 +      "  bne    atomic_cas;"                                     // if not 0, retry (someone else touched *destination after we loaded but before we stored)
   20.95 +      "  mcr    p15, 0, %[zero], c7, c10, 5;"                    // memory barrier (ARM v6 compatible)
   20.96 +      "exit:;"
   20.97 +
   20.98 +      // output
   20.99 +      : "+m" (*destination), [original_destination] "=&r" (original_destination), [stored_flag] "=&r" (stored_flag)
  20.100 +
  20.101 +      // input
  20.102 +      : [destination] "r" (destination), [compare] "r" (compare), [exchange] "r" (exchange), [zero] "r" (0)
  20.103 +
  20.104 +      // clobbered
  20.105 +      : "cc", "memory"                                           // memory is clobbered because we issue a memory barrier
  20.106 +    );
  20.107 +
  20.108 +    return( original_destination );
  20.109 +  }
  20.110 +
  20.111 +#endif
  20.112 +
    21.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    21.2 +++ b/liblfds.6/src/abstraction/abstraction_dcas.c	Sun Jan 31 21:28:42 2010 +1100
    21.3 @@ -0,0 +1,356 @@
    21.4 +#include "abstraction_internal.h"
    21.5 +
    21.6 +
    21.7 +
    21.8 +
    21.9 +
   21.10 +/****************************************************************************/
   21.11 +#if (defined _WIN64 && defined _MSC_VER)
   21.12 +
   21.13 +  /* TRD : 64 bit Windows (user-mode or kernel) on any CPU with the Microsoft C compiler
   21.14 +
   21.15 +           _WIN64    indicates 64 bit Windows
   21.16 +           _MSC_VER  indicates Microsoft C compiler
   21.17 +  */
   21.18 +
   21.19 +  INLINE unsigned char abstraction_dcas( volatile atom_t *destination, atom_t *exchange, atom_t *compare )
   21.20 +  {
   21.21 +    unsigned char
   21.22 +      cas_result;
   21.23 +
   21.24 +    assert( destination != NULL );
   21.25 +    assert( exchange != NULL );
   21.26 +    assert( compare != NULL );
   21.27 +
   21.28 +    cas_result = _InterlockedCompareExchange128( (volatile __int64 *) destination, (__int64) *(exchange+1), (__int64) *exchange, (__int64 *) compare );
   21.29 +
   21.30 +    return( cas_result );
   21.31 +  }
   21.32 +
   21.33 +#endif
   21.34 +
   21.35 +
   21.36 +
   21.37 +
   21.38 +
   21.39 +/****************************************************************************/
   21.40 +#if (!defined _WIN64 && defined _WIN32 && defined _MSC_VER)
   21.41 +
   21.42 +  /* TRD : 32 bit Windows (user-mode or kernel) on any CPU with the Microsoft C compiler
   21.43 +
   21.44 +           (!defined _WIN64 && defined _WIN32)  indicates 32 bit Windows
   21.45 +           _MSC_VER                             indicates Microsoft C compiler
   21.46 +  */
   21.47 +
   21.48 +  INLINE unsigned char abstraction_dcas( volatile atom_t *destination, atom_t *exchange, atom_t *compare )
   21.49 +  {
   21.50 +    __int64
   21.51 +      original_compare;
   21.52 +
   21.53 +    assert( destination != NULL );
   21.54 +    assert( exchange != NULL );
   21.55 +    assert( compare != NULL );
   21.56 +
   21.57 +    *(__int64 *) &original_compare = *(__int64 *) compare;
   21.58 +
   21.59 +    *(__int64 *) compare = _InterlockedCompareExchange64( (volatile __int64 *) destination, *(__int64 *) exchange, *(__int64 *) compare );
   21.60 +
   21.61 +    return( (unsigned char) (*(__int64 *) compare == *(__int64 *) &original_compare) );
   21.62 +  }
   21.63 +
   21.64 +#endif
   21.65 +
   21.66 +
   21.67 +
   21.68 +
   21.69 +
   21.70 +/****************************************************************************/
   21.71 +#if (defined __x86_64__ && __GNUC__ && !defined __pic__)
   21.72 +
   21.73 +  /* TRD : any OS on x64 with GCC for statically linked code
   21.74 +
   21.75 +           __x86_64__  indicates x64
   21.76 +           __GNUC__    indicates GCC
   21.77 +  */
   21.78 +
   21.79 +  INLINE unsigned char abstraction_dcas( volatile atom_t *destination, atom_t *exchange, atom_t *compare )
   21.80 +  {
   21.81 +    unsigned char
   21.82 +      cas_result;
   21.83 +
   21.84 +    assert( destination != NULL );
   21.85 +    assert( exchange != NULL );
   21.86 +    assert( compare != NULL );
   21.87 +
   21.88 +    __asm__ __volatile__
   21.89 +    (
   21.90 +      "lock;"           // make cmpxchg16b atomic
   21.91 +      "cmpxchg16b %0;"  // cmpxchg16b sets ZF on success
   21.92 +      "setz       %3;"  // if ZF set, set cas_result to 1
   21.93 +
   21.94 +      // output
   21.95 +      : "+m" (*(volatile atom_t (*)[2]) destination), "+a" (*compare), "+d" (*(compare+1)), "=q" (cas_result)
   21.96 +
   21.97 +      // input
   21.98 +      : "b" (*exchange), "c" (*(exchange+1))
   21.99 +
  21.100 +      // clobbered
  21.101 +      : "cc", "memory"
  21.102 +    );
  21.103 +
  21.104 +    return( cas_result );
  21.105 +  }
  21.106 +
  21.107 +#endif
  21.108 +
  21.109 +
  21.110 +
  21.111 +
  21.112 +
  21.113 +
  21.114 +/****************************************************************************/
  21.115 +#if (defined __i686__ && __GNUC__ && !defined __pic__)
  21.116 +
  21.117 +  /* TRD : any OS on x86 with GCC for statically linked code
  21.118 +
  21.119 +           __i686__  indicates x86
  21.120 +           __GNUC__  indicates GCC
  21.121 +  */
  21.122 +
  21.123 +  INLINE unsigned char abstraction_dcas( volatile atom_t *destination, atom_t *exchange, atom_t *compare )
  21.124 +  {
  21.125 +    unsigned char
  21.126 +      cas_result;
  21.127 +
  21.128 +    assert( destination != NULL );
  21.129 +    assert( exchange != NULL );
  21.130 +    assert( compare != NULL );
  21.131 +
  21.132 +    __asm__ __volatile__
  21.133 +    (
  21.134 +      "lock;"          // make cmpxchg8b atomic
  21.135 +      "cmpxchg8b %0;"  // cmpxchg8b sets ZF on success
  21.136 +      "setz      %3;"  // if ZF set, set cas_result to 1
  21.137 +
  21.138 +      // output
  21.139 +      : "+m" (*(volatile atom_t (*)[2]) destination), "+a" (*compare), "+d" (*(compare+1)), "=q" (cas_result)
  21.140 +
  21.141 +      // input
  21.142 +      : "b" (*exchange), "c" (*(exchange+1))
  21.143 +
  21.144 +      // clobbered
  21.145 +      : "cc", "memory"
  21.146 +    );
  21.147 +
  21.148 +    return( cas_result );
  21.149 +  }
  21.150 +
  21.151 +#endif
  21.152 +
  21.153 +
  21.154 +
  21.155 +
  21.156 +
  21.157 +/****************************************************************************/
  21.158 +#if (defined __x86_64__ && __GNUC__ && defined __pic__)
  21.159 +
  21.160 +  /* TRD : any OS on x64 with GCC for position independent code (e.g. a shared object)
  21.161 +
  21.162 +           __x86_64__  indicates x64
  21.163 +           __GNUC__    indicates GCC
  21.164 +  */
  21.165 +
  21.166 +  INLINE unsigned char abstraction_dcas( volatile atom_t *destination, atom_t *exchange, atom_t *compare )
  21.167 +  {
  21.168 +    unsigned char
  21.169 +      cas_result;
  21.170 +
  21.171 +    assert( destination != NULL );
  21.172 +    assert( exchange != NULL );
  21.173 +    assert( compare != NULL );
  21.174 +
  21.175 +    /* TRD : with a shared object, we cannot clobber RBX
  21.176 +             as such, we borrow RSI - we load half of the exchange value into it
  21.177 +             then swap it with RBX
  21.178 +             then do the compare-and-swap
  21.179 +             then swap the original value of RBX back from RSI
  21.180 +    */
  21.181 +
  21.182 +    __asm__ __volatile__
  21.183 +    (
  21.184 +      "xchg %%rsi, %%rbx;"  // swap RBI and RBX 
  21.185 +      "lock;"               // make cmpxchg16b atomic
  21.186 +      "cmpxchg16b %0;"      // cmpxchg16b sets ZF on success
  21.187 +      "setz       %3;"      // if ZF set, set cas_result to 1
  21.188 +      "xchg %%rbx, %%rsi;"  // re-swap RBI and RBX
  21.189 +
  21.190 +      // output
  21.191 +      : "+m" (*(volatile atom_t (*)[2]) destination), "+a" (*compare), "+d" (*(compare+1)), "=q" (cas_result)
  21.192 +
  21.193 +      // input
  21.194 +      : "S" (*exchange), "c" (*(exchange+1))
  21.195 +
  21.196 +      // clobbered
  21.197 +      : "cc", "memory"
  21.198 +    );
  21.199 +
  21.200 +    return( cas_result );
  21.201 +  }
  21.202 +
  21.203 +#endif
  21.204 +
  21.205 +
  21.206 +
  21.207 +
  21.208 +
  21.209 +
  21.210 +/****************************************************************************/
  21.211 +#if (defined __i686__ && __GNUC__ && defined __pic__)
  21.212 +
  21.213 +  /* TRD : any OS on x86 with GCC for position independent code (e.g. a shared object)
  21.214 +
  21.215 +           __i686__  indicates x86
  21.216 +           __GNUC__  indicates GCC
  21.217 +  */
  21.218 +
  21.219 +  INLINE unsigned char abstraction_dcas( volatile atom_t *destination, atom_t *exchange, atom_t *compare )
  21.220 +  {
  21.221 +    unsigned char
  21.222 +      cas_result;
  21.223 +
  21.224 +    assert( destination != NULL );
  21.225 +    assert( exchange != NULL );
  21.226 +    assert( compare != NULL );
  21.227 +
  21.228 +    /* TRD : with a shared object, we cannot clobber EBX
  21.229 +             as such, we borrow ESI - we load half of the exchange value into it
  21.230 +             then swap it with EBX
  21.231 +             then do the compare-and-swap
  21.232 +             then swap the original value of EBX back from ESI
  21.233 +    */
  21.234 +
  21.235 +    __asm__ __volatile__
  21.236 +    (
  21.237 +      "xchg %%esi, %%ebx;"  // swap EBI and EBX
  21.238 +      "lock;"               // make cmpxchg8b atomic
  21.239 +      "cmpxchg8b %0;"       // cmpxchg8b sets ZF on success
  21.240 +      "setz      %3;"       // if ZF set, set cas_result to 1
  21.241 +      "xchg %%ebx, %%esi;"  // re-swap EBI and EBX
  21.242 +
  21.243 +      // output
  21.244 +      : "+m" (*(volatile atom_t (*)[2]) destination), "+a" (*compare), "+d" (*(compare+1)), "=q" (cas_result)
  21.245 +
  21.246 +      // input
  21.247 +      : "S" (*exchange), "c" (*(exchange+1))
  21.248 +
  21.249 +      // clobbered
  21.250 +      : "cc", "memory"
  21.251 +    );
  21.252 +
  21.253 +    return( cas_result );
  21.254 +  }
  21.255 +
  21.256 +#endif
  21.257 +
  21.258 +
  21.259 +
  21.260 +
  21.261 +
  21.262 +/****************************************************************************/
  21.263 +#if (defined __arm__ && __GNUC__)
  21.264 +
  21.265 +  /* TRD : any OS on any ARM with GCC
  21.266 +
  21.267 +           Remember however we need to set into compare the original value of destination.
  21.268 +
  21.269 +           __arm__   indicates ARM
  21.270 +           __GNUC__  indicates GCC
  21.271 +  */
  21.272 +
  21.273 +  INLINE unsigned char abstraction_dcas( volatile atom_t *destination, atom_t *exchange, atom_t *compare )
  21.274 +  {
  21.275 +    atom_t
  21.276 +      *local_compare = compare,
  21.277 +      stored_flag = 1;
  21.278 +
  21.279 +    register atom_t
  21.280 +      local_exchange_a __asm("r2"),
  21.281 +      local_exchange_b __asm("r3"),
  21.282 +      local_compare_a __asm("r4"),
  21.283 +      local_compare_b __asm("r5"),
  21.284 +      original_destination_a __asm("r6"),
  21.285 +      original_destination_b __asm("r7");
  21.286 +
  21.287 +    assert( destination != NULL );
  21.288 +    assert( exchange != NULL );
  21.289 +    assert( compare != NULL );
  21.290 +
  21.291 +    /* TRD : some notes
  21.292 +
  21.293 +             the double word ldr and str instructions require contigous registers
  21.294 +             where the first register is an even number
  21.295 +
  21.296 +             honouring this requirement requires us to specifically specify
  21.297 +             the registers to use (which is why we're using register __asm("rN")
  21.298 +             in the declerations above
  21.299 +
  21.300 +             the arguments to the function occupy registers r0, r1 and r2
  21.301 +
  21.302 +             we can use up to and including r8, but r9 can have a frame pointer in it
  21.303 +
  21.304 +             so we make a copy of compare (freeing up r2, so we can use it for a double
  21.305 +             word load) but use destination (r0) and exchange (r1) directly
  21.306 +
  21.307 +             note LDRD and STRD became available in armv6k
  21.308 +
  21.309 +             apologies for the trickery with the mcr register variable - the code runs
  21.310 +             out of registers on armv6k
  21.311 +    */
  21.312 +
  21.313 +    __asm__ __volatile__
  21.314 +    (
  21.315 +      "  mov     %[stored_flag], #1;"                                                                // put 1 into stored_flag
  21.316 +      "  mov     %[local_exchange_a], #0;"                                                           // borrow local_exchange_a for mcr, to save a register
  21.317 +      "  mcr     p15, 0, %[local_exchange_a], c7, c10, 5;"                                           // memory barrier (ARM v6 compatible)
  21.318 +      "  ldrd    %[local_exchange_a], %[local_exchange_b], [%[exchange]];"                           // load exchange into local_exchange_a and local_exchange_b (which are r2 and r3, respectively)
  21.319 +      "  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)
  21.320 +      "atomic_dcas:;"
  21.321 +      "  ldrexd  %[original_destination_a], %[original_destination_b], [%[destination]];"            // load destination into original_destination_a and original_destination_b (which are r6 and r7, respectively)
  21.322 +      "  teq     %[original_destination_a], %[local_compare_a];"                                     // compare the first word of destination with the first word of compare
  21.323 +      "  teqeq   %[original_destination_b], %[local_compare_b];"                                     // if they're equal, compare the second word of destination with the second word of compare
  21.324 +      "  bne     exit;"                                                                              // if either word of destination does not match its respective word of compare, exit
  21.325 +      "  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)
  21.326 +      "  teq     %[stored_flag], #0;"                                                                // check if stored_flag is 0
  21.327 +      "  bne     atomic_dcas;"                                                                       // if not 0, retry (someone else touched *destination after we loaded but before we stored)
  21.328 +      "exit:;"
  21.329 +      "  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
  21.330 +      "  mov     %[local_exchange_a], #0;"                                                           // borrow local_exchange_a for mcr, to save a register
  21.331 +      "  mcr     p15, 0, %[local_exchange_a], c7, c10, 5;"                                           // memory barrier (ARM v6 compatible)
  21.332 +
  21.333 +      // output
  21.334 +      : "+m" (*(volatile atom_t (*)[2]) destination), "+m" (*(atom_t (*)[2]) local_compare),
  21.335 +        [stored_flag] "+&r" (stored_flag),
  21.336 +        [original_destination_a] "+&r" (original_destination_a), [original_destination_b] "+&r" (original_destination_b),
  21.337 +        [local_compare_a] "+&r" (local_compare_a), [local_compare_b] "+&r" (local_compare_b),
  21.338 +        [local_exchange_a] "+&r" (local_exchange_a), [local_exchange_b] "+&r" (local_exchange_b)
  21.339 +
  21.340 +      // input
  21.341 +      : "m" (*(atom_t (*)[2]) exchange),
  21.342 +        [destination] "r" (destination),
  21.343 +        [local_compare] "r" (local_compare),
  21.344 +        [exchange] "r" (exchange)
  21.345 +
  21.346 +      // clobbered
  21.347 +      : "cc", "memory"                                                                               // memory is clobbered because we issue a memory barrier
  21.348 +    );
  21.349 +
  21.350 +    /* TRD : stored_flag is set to 0 on store, 1 on fail
  21.351 +             we need to return 1 on success, 0 on fail
  21.352 +    */
  21.353 +
  21.354 +    return( (unsigned char) !stored_flag  );
  21.355 +  }
  21.356 +
  21.357 +#endif
  21.358 +
  21.359 +
    22.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    22.2 +++ b/liblfds.6/src/abstraction/abstraction_increment.c	Sun Jan 31 21:28:42 2010 +1100
    22.3 @@ -0,0 +1,136 @@
    22.4 +#include "abstraction_internal.h"
    22.5 +
    22.6 +
    22.7 +
    22.8 +
    22.9 +
   22.10 +/****************************************************************************/
   22.11 +#if (defined _WIN64 && defined _MSC_VER)
   22.12 +
   22.13 +  /* TRD : 64 bit Windows (user-mode or kernel) on any CPU with the Microsoft C compiler
   22.14 +
   22.15 +           _WIN64    indicates 64 bit Windows
   22.16 +           _MSC_VER  indicates Microsoft C compiler
   22.17 +  */
   22.18 +
   22.19 +  INLINE atom_t abstraction_increment( atom_t *value )
   22.20 +  {
   22.21 +    __int64
   22.22 +      rv;
   22.23 +
   22.24 +    assert( value != NULL );
   22.25 +
   22.26 +    rv = _InterlockedIncrement64( (__int64 *) value );
   22.27 +
   22.28 +    return( (atom_t) rv );
   22.29 +  }
   22.30 +
   22.31 +#endif
   22.32 +
   22.33 +
   22.34 +
   22.35 +
   22.36 +
   22.37 +/****************************************************************************/
   22.38 +#if (!defined _WIN64 && defined _WIN32 && defined _MSC_VER)
   22.39 +
   22.40 +  /* TRD : 32 bit Windows (user-mode or kernel) on any CPU with the Microsoft C compiler
   22.41 +
   22.42 +           (!defined _WIN64 && defined _WIN32)  indicates 32 bit Windows
   22.43 +           _MSC_VER                             indicates Microsoft C compiler
   22.44 +  */
   22.45 +
   22.46 +  INLINE atom_t abstraction_increment( atom_t *value )
   22.47 +  {
   22.48 +    long int
   22.49 +      rv;
   22.50 +
   22.51 +    assert( value != NULL );
   22.52 +
   22.53 +    rv = _InterlockedIncrement( (long int *) value );
   22.54 +
   22.55 +    return( (atom_t) rv );
   22.56 +  }
   22.57 +
   22.58 +#endif
   22.59 +
   22.60 +
   22.61 +
   22.62 +
   22.63 +
   22.64 +/****************************************************************************/
   22.65 +#if (!defined __arm__ && __GNUC__ >= 4 && __GNUC_MINOR__ >= 1 && __GNUC_PATCHLEVEL__ >= 0)
   22.66 +
   22.67 +  /* TRD : any OS on any CPU with GCC 4.1.0 or better
   22.68 +
   22.69 +           GCC 4.1.0 introduced the __sync_*() atomic intrinsics
   22.70 +
   22.71 +           __GNUC__ / __GNUC_MINOR__ / __GNUC_PATCHLEVEL__  indicates GCC and which version
   22.72 +  */
   22.73 +
   22.74 +  INLINE atom_t abstraction_increment( atom_t *value )
   22.75 +  {
   22.76 +    atom_t
   22.77 +      rv;
   22.78 +
   22.79 +    assert( value != NULL );
   22.80 +
   22.81 +    // TRD : no need for casting here, GCC has a __sync_add_and_fetch() for all native types
   22.82 +
   22.83 +    rv = __sync_add_and_fetch( value, 1 );
   22.84 +
   22.85 +    return( rv );
   22.86 +  }
   22.87 +
   22.88 +#endif
   22.89 +
   22.90 +
   22.91 +
   22.92 +
   22.93 +
   22.94 +/****************************************************************************/
   22.95 +#if (defined __arm__ && __GNUC__ >= 4)
   22.96 +
   22.97 +  /* TRD : any OS on any CPU with GCC 4.1.0 or better
   22.98 +
   22.99 +           GCC 4.1.0 introduced the __sync_*() atomic intrinsics
  22.100 +
  22.101 +           __arm__   indicates ARM
  22.102 +           __GNUC__  indicates GCC
  22.103 +  */
  22.104 +
  22.105 +  INLINE atom_t abstraction_increment( atom_t *value )
  22.106 +  {
  22.107 +    atom_t
  22.108 +      stored_flag = 0,
  22.109 +      new_value = 0;
  22.110 +
  22.111 +    assert( value != NULL );
  22.112 +
  22.113 +    __asm__ __volatile__
  22.114 +    (
  22.115 +      "  mov    %[stored_flag], #1;"                        // move 1 into stored_flag
  22.116 +      "  mcr    p15, 0, %[zero], c7, c10, 5;"               // memory barrier (ARM v6 compatible)
  22.117 +      "atomic_add:;"
  22.118 +      "  ldrex  %[new_value], [%[value]];  "                // load *value into new_value
  22.119 +      "  add    %[new_value], #1;"                          // add 1 to new_value
  22.120 +      "  strex  %[stored_flag], %[new_value], [%[value]];"  // try to store new_value into *value (on success, strex puts 0 into stored_flag)
  22.121 +      "  teq    %[stored_flag], #0;"                        // check if stored_flag is 0
  22.122 +      "  bne    atomic_add;"                                // if not 0, retry (someone else touched *value after we loaded but before we stored)
  22.123 +      "  mcr    p15, 0, %[zero], c7, c10, 5;"               // memory barrier (ARM v6 compatible)
  22.124 +
  22.125 +      // output
  22.126 +      : "+m" (*value), [new_value] "+&r" (new_value), [stored_flag] "+&r" (stored_flag)
  22.127 +
  22.128 +      // input
  22.129 +      : [value] "r" (value), [zero] "r" (0)
  22.130 +
  22.131 +      // clobbered
  22.132 +      : "cc", "memory"                                      // memory is clobbered because we issue a memory barrier
  22.133 +    );
  22.134 +
  22.135 +    return( new_value );
  22.136 +  }
  22.137 +
  22.138 +#endif
  22.139 +
    23.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    23.2 +++ b/liblfds.6/src/abstraction/abstraction_internal.h	Sun Jan 31 21:28:42 2010 +1100
    23.3 @@ -0,0 +1,5 @@
    23.4 +/***** the library wide include file *****/
    23.5 +#include "liblfds_internal.h"
    23.6 +
    23.7 +/***** private prototypes *****/
    23.8 +
    24.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    24.2 +++ b/liblfds.6/src/dirs	Sun Jan 31 21:28:42 2010 +1100
    24.3 @@ -0,0 +1,3 @@
    24.4 +DIRS = single_dir_for_windows_kernel
    24.5 +
    24.6 +
    25.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    25.2 +++ b/liblfds.6/src/driver_entry.c	Sun Jan 31 21:28:42 2010 +1100
    25.3 @@ -0,0 +1,16 @@
    25.4 +#include "stack_internal.h"
    25.5 +
    25.6 +
    25.7 +
    25.8 +
    25.9 +
   25.10 +/****************************************************************************/
   25.11 +#pragma warning( disable : 4100 )
   25.12 +
   25.13 +NTSTATUS DriverEntry( struct _DRIVER_OBJECT *DriverObject, PUNICODE_STRING RegistryPath )
   25.14 +{
   25.15 +  return( STATUS_SUCCESS );
   25.16 +}
   25.17 +
   25.18 +#pragma warning( default : 4100 )
   25.19 +
    26.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    26.2 +++ b/liblfds.6/src/driver_entry_readme.txt	Sun Jan 31 21:28:42 2010 +1100
    26.3 @@ -0,0 +1,4 @@
    26.4 +This C file (driver_entry.c) is used when building a dynamic library for
    26.5 +the Windows kernel.  It exists to work around one of the limitations of
    26.6 +that build environment.  It is not used  by any other build; just ignore it.
    26.7 +
    27.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    27.2 +++ b/liblfds.6/src/freelist/freelist_delete.c	Sun Jan 31 21:28:42 2010 +1100
    27.3 @@ -0,0 +1,35 @@
    27.4 +#include "freelist_internal.h"
    27.5 +
    27.6 +
    27.7 +
    27.8 +
    27.9 +
   27.10 +/****************************************************************************/
   27.11 +void freelist_delete( struct freelist_state *fs, void (*user_data_delete_function)(void *user_data, void *user_state), void *user_state )
   27.12 +{
   27.13 +  struct freelist_element
   27.14 +    *fe;
   27.15 +
   27.16 +  void
   27.17 +    *user_data;
   27.18 +
   27.19 +  assert( fs != NULL );
   27.20 +  // TRD : user_data_delete_function can be NULL
   27.21 +  // TRD : user_state can be NULL
   27.22 +
   27.23 +  while( freelist_pop(fs, &fe) )
   27.24 +  {
   27.25 +    if( user_data_delete_function != NULL )
   27.26 +    {
   27.27 +      freelist_get_user_data_from_element( fe, &user_data );
   27.28 +      user_data_delete_function( user_data, user_state );
   27.29 +    }
   27.30 +
   27.31 +    abstraction_aligned_free( fe );
   27.32 +  }
   27.33 +
   27.34 +  abstraction_aligned_free( fs );
   27.35 +
   27.36 +  return;
   27.37 +}
   27.38 +
    28.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    28.2 +++ b/liblfds.6/src/freelist/freelist_get_and_set.c	Sun Jan 31 21:28:42 2010 +1100
    28.3 @@ -0,0 +1,33 @@
    28.4 +#include "freelist_internal.h"
    28.5 +
    28.6 +
    28.7 +
    28.8 +
    28.9 +
   28.10 +/****************************************************************************/
   28.11 +void *freelist_get_user_data_from_element( struct freelist_element *fe, void **user_data )
   28.12 +{
   28.13 +  assert( fe != NULL );
   28.14 +  // TRD : user_data can be NULL
   28.15 +
   28.16 +  if( user_data != NULL )
   28.17 +    *user_data = fe->user_data;
   28.18 +
   28.19 +  return( fe->user_data );
   28.20 +}
   28.21 +
   28.22 +
   28.23 +
   28.24 +
   28.25 +
   28.26 +/****************************************************************************/
   28.27 +void freelist_set_user_data_in_element( struct freelist_element *fe, void *user_data )
   28.28 +{
   28.29 +  assert( fe != NULL );
   28.30 +  // TRD : user_data can be NULL
   28.31 +
   28.32 +  fe->user_data = user_data;
   28.33 +
   28.34 +  return;
   28.35 +}
   28.36 +
    29.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    29.2 +++ b/liblfds.6/src/freelist/freelist_internal.h	Sun Jan 31 21:28:42 2010 +1100
    29.3 @@ -0,0 +1,42 @@
    29.4 +/***** the library wide include file *****/
    29.5 +#include "liblfds_internal.h"
    29.6 +
    29.7 +/***** defines *****/
    29.8 +#define FREELIST_POINTER 0
    29.9 +#define FREELIST_COUNTER 1
   29.10 +#define FREELIST_PAC_SIZE 2
   29.11 +
   29.12 +/***** structures *****/
   29.13 +#pragma pack( push, ALIGN_DOUBLE_POINTER )
   29.14 +
   29.15 +struct freelist_state
   29.16 +{
   29.17 +  struct freelist_element
   29.18 +    *volatile top[FREELIST_PAC_SIZE];
   29.19 +
   29.20 +  int
   29.21 +    (*user_data_init_function)( void **user_data, void *user_state );
   29.22 +
   29.23 +  void
   29.24 +    *user_state;
   29.25 +
   29.26 +  atom_t
   29.27 +    aba_counter,
   29.28 +    element_count;
   29.29 +};
   29.30 +
   29.31 +struct freelist_element
   29.32 +{
   29.33 +  struct freelist_element
   29.34 +    *next[FREELIST_PAC_SIZE];
   29.35 +
   29.36 +  void
   29.37 +    *user_data;
   29.38 +};
   29.39 +
   29.40 +#pragma pack( pop )
   29.41 +
   29.42 +/***** private prototypes *****/
   29.43 +atom_t freelist_internal_new_element( struct freelist_state *fs, struct freelist_element **fe );
   29.44 +void freelist_internal_validate( struct freelist_state *fs, struct validation_info *vi, enum data_structure_validity *freelist_validity );
   29.45 +
    30.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    30.2 +++ b/liblfds.6/src/freelist/freelist_new.c	Sun Jan 31 21:28:42 2010 +1100
    30.3 @@ -0,0 +1,123 @@
    30.4 +#include "freelist_internal.h"
    30.5 +
    30.6 +
    30.7 +
    30.8 +
    30.9 +
   30.10 +/****************************************************************************/
   30.11 +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 )
   30.12 +{
   30.13 +  int
   30.14 +    rv = 0;
   30.15 +
   30.16 +  atom_t
   30.17 +    element_count;
   30.18 +
   30.19 +  assert( fs != NULL );
   30.20 +  // TRD : number_elements can be any value in its range
   30.21 +  // TRD : user_data_init_function can be NULL
   30.22 +
   30.23 +  *fs = (struct freelist_state *) abstraction_aligned_malloc( sizeof(struct freelist_state), ALIGN_DOUBLE_POINTER );
   30.24 +
   30.25 +  if( (*fs) != NULL )
   30.26 +  {
   30.27 +    (*fs)->top[FREELIST_POINTER] = NULL;
   30.28 +    (*fs)->top[FREELIST_COUNTER] = 0;
   30.29 +    (*fs)->user_data_init_function = user_data_init_function;
   30.30 +    (*fs)->user_state = user_state;
   30.31 +    (*fs)->aba_counter = 0;
   30.32 +    (*fs)->element_count = 0;
   30.33 +
   30.34 +    element_count = freelist_new_elements( *fs, number_elements );
   30.35 +
   30.36 +    if( element_count == number_elements )
   30.37 +      rv = 1;
   30.38 +
   30.39 +    if( element_count != number_elements )
   30.40 +    {
   30.41 +      abstraction_aligned_free( (*fs) );
   30.42 +      *fs = NULL;
   30.43 +    }
   30.44 +  }
   30.45 +
   30.46 +  return( rv );
   30.47 +}
   30.48 +
   30.49 +
   30.50 +
   30.51 +
   30.52 +
   30.53 +/****************************************************************************/
   30.54 +atom_t freelist_new_elements( struct freelist_state *fs, atom_t number_elements )
   30.55 +{
   30.56 +  struct freelist_element
   30.57 +    *fe;
   30.58 +
   30.59 +  atom_t
   30.60 +    loop,
   30.61 +    count = 0;
   30.62 +
   30.63 +  assert( fs != NULL );
   30.64 +  // TRD : number_elements can be any value in its range
   30.65 +  // TRD : user_data_init_function can be NULL
   30.66 +
   30.67 +  for( loop = 0 ; loop < number_elements ; loop++ )
   30.68 +    if( freelist_internal_new_element(fs, &fe) )
   30.69 +    {
   30.70 +      freelist_push( fs, fe );
   30.71 +      count++;
   30.72 +    }
   30.73 +
   30.74 +  return( count );
   30.75 +}
   30.76 +
   30.77 +
   30.78 +
   30.79 +
   30.80 +
   30.81 +/****************************************************************************/
   30.82 +atom_t freelist_internal_new_element( struct freelist_state *fs, struct freelist_element **fe )
   30.83 +{
   30.84 +  atom_t
   30.85 +    rv = 0;
   30.86 +
   30.87 +  assert( fs != NULL );
   30.88 +  assert( fe != NULL );
   30.89 +
   30.90 +  /* TRD : basically, does what you'd expect;
   30.91 +
   30.92 +           allocates an element
   30.93 +           calls the user init function
   30.94 +           if anything fails, cleans up,
   30.95 +           sets *fe to NULL
   30.96 +           and returns 0
   30.97 +  */
   30.98 +
   30.99 +  *fe = (struct freelist_element *) abstraction_aligned_malloc( sizeof(struct freelist_element), ALIGN_DOUBLE_POINTER );
  30.100 +
  30.101 +  if( *fe != NULL )
  30.102 +  {
  30.103 +    if( fs->user_data_init_function == NULL )
  30.104 +    {
  30.105 +      (*fe)->user_data = NULL;
  30.106 +      rv = 1;
  30.107 +    }
  30.108 +
  30.109 +    if( fs->user_data_init_function != NULL )
  30.110 +    {
  30.111 +      rv = fs->user_data_init_function( &(*fe)->user_data, fs->user_state );
  30.112 +
  30.113 +      if( rv == 0 )
  30.114 +      {
  30.115 +        abstraction_aligned_free( *fe );
  30.116 +        *fe = NULL;
  30.117 +      }
  30.118 +    }
  30.119 +  }
  30.120 +
  30.121 +  if( rv == 1 )
  30.122 +    abstraction_increment( (atom_t *) &fs->element_count );
  30.123 +
  30.124 +  return( rv );
  30.125 +}
  30.126 +
    31.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    31.2 +++ b/liblfds.6/src/freelist/freelist_pop_push.c	Sun Jan 31 21:28:42 2010 +1100
    31.3 @@ -0,0 +1,88 @@
    31.4 +#include "freelist_internal.h"
    31.5 +
    31.6 +
    31.7 +
    31.8 +
    31.9 +
   31.10 +/****************************************************************************/
   31.11 +struct freelist_element *freelist_pop( struct freelist_state *fs, struct freelist_element **fe )
   31.12 +{
   31.13 +  ALIGN(ALIGN_DOUBLE_POINTER) struct freelist_element
   31.14 +    *fe_local[FREELIST_PAC_SIZE];
   31.15 +
   31.16 +  assert( fs != NULL );
   31.17 +  assert( fe != NULL );
   31.18 +
   31.19 +  fe_local[FREELIST_COUNTER] = fs->top[FREELIST_COUNTER];
   31.20 +  fe_local[FREELIST_POINTER] = fs->top[FREELIST_POINTER];
   31.21 +
   31.22 +  /* TRD : note that abstraction_dcas loads the original value of the destination (fs->top) into the compare (fe_local)
   31.23 +           (this happens of course after the CAS itself has occurred inside abstraction_dcas)
   31.24 +  */
   31.25 +
   31.26 +  do
   31.27 +  {
   31.28 +    if( fe_local[FREELIST_POINTER] == NULL )
   31.29 +    {
   31.30 +      *fe = NULL;
   31.31 +      return( *fe );
   31.32 +    }
   31.33 +  }
   31.34 +  while( 0 == abstraction_dcas((volatile atom_t *) fs->top, (atom_t *) fe_local[FREELIST_POINTER]->next, (atom_t *) fe_local) );
   31.35 +
   31.36 +  *fe = (struct freelist_element *) fe_local[FREELIST_POINTER];
   31.37 +
   31.38 +  return( *fe );
   31.39 +}
   31.40 +
   31.41 +
   31.42 +
   31.43 +
   31.44 +
   31.45 +/****************************************************************************/
   31.46 +struct freelist_element *freelist_guaranteed_pop( struct freelist_state *fs, struct freelist_element **fe )
   31.47 +{
   31.48 +  assert( fs != NULL );
   31.49 +  assert( fe != NULL );
   31.50 +
   31.51 +  freelist_internal_new_element( fs, fe );
   31.52 +
   31.53 +  return( *fe );
   31.54 +}
   31.55 +
   31.56 +
   31.57 +
   31.58 +
   31.59 +
   31.60 +/****************************************************************************/
   31.61 +void freelist_push( struct freelist_state *fs, struct freelist_element *fe )
   31.62 +{
   31.63 +  ALIGN(ALIGN_DOUBLE_POINTER) struct freelist_element
   31.64 +    *fe_local[FREELIST_PAC_SIZE],
   31.65 +    *original_fe_next[FREELIST_PAC_SIZE];
   31.66 +
   31.67 +  assert( fs != NULL );
   31.68 +  assert( fe != NULL );
   31.69 +
   31.70 +  fe_local[FREELIST_POINTER] = fe;
   31.71 +  fe_local[FREELIST_COUNTER] = (struct freelist_element *) abstraction_increment( (atom_t *) &fs->aba_counter );
   31.72 +
   31.73 +  original_fe_next[FREELIST_POINTER] = fs->top[FREELIST_POINTER];
   31.74 +  original_fe_next[FREELIST_COUNTER] = fs->top[FREELIST_COUNTER];
   31.75 +
   31.76 +  /* TRD : note that abstraction_dcas loads the original value of the destination (fs->top) into the compare (original_fe_next)
   31.77 +           (this happens of course after the CAS itself has occurred inside abstraction_dcas)
   31.78 +           this then causes us in our loop, should we repeat it, to update fe_local->next to a more
   31.79 +           up-to-date version of the head of the freelist
   31.80 +  */
   31.81 +
   31.82 +  do
   31.83 +  {
   31.84 +    fe_local[FREELIST_POINTER]->next[FREELIST_POINTER] = original_fe_next[FREELIST_POINTER];
   31.85 +    fe_local[FREELIST_POINTER]->next[FREELIST_COUNTER] = original_fe_next[FREELIST_COUNTER];
   31.86 +  }
   31.87 +  while( 0 == abstraction_dcas((volatile atom_t *) fs->top, (atom_t *) fe_local, (atom_t *) original_fe_next) );
   31.88 +
   31.89 +  return;
   31.90 +}
   31.91 +
    32.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    32.2 +++ b/liblfds.6/src/freelist/freelist_query.c	Sun Jan 31 21:28:42 2010 +1100
    32.3 @@ -0,0 +1,113 @@
    32.4 +#include "freelist_internal.h"
    32.5 +
    32.6 +
    32.7 +
    32.8 +
    32.9 +
   32.10 +/****************************************************************************/
   32.11 +void freelist_query( struct freelist_state *fs, enum freelist_query_type query_type, void *query_input, void *query_output )
   32.12 +{
   32.13 +  assert( fs != NULL );
   32.14 +  // TRD : query type can be any value in its range
   32.15 +  // TRD : query_input can be NULL in some cases
   32.16 +  assert( query_output != NULL );
   32.17 +
   32.18 +  switch( query_type )
   32.19 +  {
   32.20 +    case FREELIST_QUERY_ELEMENT_COUNT:
   32.21 +      assert( query_input == NULL );
   32.22 +
   32.23 +      *(atom_t *) query_output = fs->element_count;
   32.24 +    break;
   32.25 +
   32.26 +    case FREELIST_QUERY_VALIDATE:
   32.27 +      // TRD : query_input can be NULL
   32.28 +
   32.29 +      freelist_internal_validate( fs, (struct validation_info *) query_input, (enum data_structure_validity *) query_output );
   32.30 +    break;
   32.31 +  }
   32.32 +
   32.33 +  return;
   32.34 +}
   32.35 +
   32.36 +
   32.37 +
   32.38 +
   32.39 +
   32.40 +/****************************************************************************/
   32.41 +void freelist_internal_validate( struct freelist_state *fs, struct validation_info *vi, enum data_structure_validity *freelist_validity )
   32.42 +{
   32.43 +  struct freelist_element
   32.44 +    *fe,
   32.45 +    *fe_slow,
   32.46 +    *fe_fast;
   32.47 +
   32.48 +  atom_t
   32.49 +    element_count = 0;
   32.50 +
   32.51 +  assert( fs != NULL );
   32.52 +  // TRD : vi can be NULL
   32.53 +  assert( freelist_validity != NULL );
   32.54 +
   32.55 +  *freelist_validity = VALIDITY_VALID;
   32.56 +
   32.57 +  fe_slow = fe_fast = (struct freelist_element *) fs->top[FREELIST_POINTER];
   32.58 +
   32.59 +  /* TRD : first, check for a loop
   32.60 +           we have two pointers
   32.61 +           both of which start at the top of the freelist
   32.62 +           we enter a loop
   32.63 +           and on each iteration
   32.64 +           we advance one pointer by one element
   32.65 +           and the other by two
   32.66 +
   32.67 +           we exit the loop when both pointers are NULL
   32.68 +           (have reached the end of the freelist)
   32.69 +
   32.70 +           or
   32.71 +
   32.72 +           if we fast pointer 'sees' the slow pointer
   32.73 +           which means we have a loop
   32.74 +  */
   32.75 +
   32.76 +  if( fe_slow != NULL )
   32.77 +    do
   32.78 +    {
   32.79 +      fe_slow = fe_slow->next[FREELIST_POINTER];
   32.80 +
   32.81 +      if( fe_fast != NULL )
   32.82 +        fe_fast = fe_fast->next[FREELIST_POINTER];
   32.83 +
   32.84 +      if( fe_fast != NULL )
   32.85 +        fe_fast = fe_fast->next[FREELIST_POINTER];
   32.86 +    }
   32.87 +    while( fe_slow != NULL and fe_fast != fe_slow );
   32.88 +
   32.89 +  if( fe_fast != NULL and fe_slow != NULL and fe_fast == fe_slow )
   32.90 +    *freelist_validity = VALIDITY_INVALID_LOOP;
   32.91 +
   32.92 +  /* TRD : now check for expected number of elements
   32.93 +           vi can be NULL, in which case we do not check
   32.94 +           we know we don't have a loop from our earlier check
   32.95 +  */
   32.96 +
   32.97 +  if( *freelist_validity == VALIDITY_VALID and vi != NULL )
   32.98 +  {
   32.99 +    fe = (struct freelist_element *) fs->top[FREELIST_POINTER];
  32.100 +
  32.101 +    while( fe != NULL )
  32.102 +    {
  32.103 +      element_count++;
  32.104 +      fe = (struct freelist_element *) fe->next[FREELIST_POINTER];
  32.105 +    }
  32.106 +
  32.107 +    if( element_count < vi->min_elements )
  32.108 +      *freelist_validity = VALIDITY_INVALID_MISSING_ELEMENTS;
  32.109 +
  32.110 +    if( element_count > vi->max_elements )
  32.111 +      *freelist_validity = VALIDITY_INVALID_ADDITIONAL_ELEMENTS;
  32.112 +  }
  32.113 +
  32.114 +  return;
  32.115 +}
  32.116 +
    33.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    33.2 +++ b/liblfds.6/src/liblfds_internal.h	Sun Jan 31 21:28:42 2010 +1100
    33.3 @@ -0,0 +1,12 @@
    33.4 +/***** public prototypes *****/
    33.5 +#include "liblfds.h"
    33.6 +
    33.7 +/***** defines *****/
    33.8 +#define and &&
    33.9 +#define or  ||
   33.10 +
   33.11 +#define RAISED   1
   33.12 +#define LOWERED  0
   33.13 +
   33.14 +#define NO_FLAGS 0x0
   33.15 +
    34.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    34.2 +++ b/liblfds.6/src/queue/queue_delete.c	Sun Jan 31 21:28:42 2010 +1100
    34.3 @@ -0,0 +1,55 @@
    34.4 +#include "queue_internal.h"
    34.5 +
    34.6 +
    34.7 +
    34.8 +
    34.9 +
   34.10 +/****************************************************************************/
   34.11 +void queue_delete( struct queue_state *qs, void (*user_data_delete_function)(void *user_data, void *user_state), void *user_state )
   34.12 +{
   34.13 +  void
   34.14 +    *user_data;
   34.15 +
   34.16 +  assert( qs != NULL );
   34.17 +  // TRD : user_data_delete_function can be NULL
   34.18 +  // TRD : user_state can be NULL
   34.19 +
   34.20 +  while( queue_dequeue(qs, &user_data) )
   34.21 +    if( user_data_delete_function != NULL )
   34.22 +      user_data_delete_function( user_data, user_state );
   34.23 +
   34.24 +  /* TRD : fully dequeuing will leave us
   34.25 +           with a single dummy element
   34.26 +           which both qs->enqueue and qs->dequeue point at
   34.27 +           we push this back onto the freelist
   34.28 +           before we delete the freelist
   34.29 +  */
   34.30 +
   34.31 +  freelist_push( qs->fs, qs->enqueue[QUEUE_POINTER]->fe );
   34.32 +
   34.33 +  freelist_delete( qs->fs, queue_internal_freelist_delete_function, NULL );
   34.34 +
   34.35 +  abstraction_aligned_free( qs );
   34.36 +
   34.37 +  return;
   34.38 +}
   34.39 +
   34.40 +
   34.41 +
   34.42 +
   34.43 +
   34.44 +/****************************************************************************/
   34.45 +#pragma warning( disable : 4100 )
   34.46 +
   34.47 +void queue_internal_freelist_delete_function( void *user_data, void *user_state )
   34.48 +{
   34.49 +  assert( user_data != NULL );
   34.50 +  assert( user_state == NULL );
   34.51 +
   34.52 +  abstraction_aligned_free( user_data );
   34.53 +
   34.54 +  return;
   34.55 +}
   34.56 +
   34.57 +#pragma warning( default : 4100 )
   34.58 +
    35.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    35.2 +++ b/liblfds.6/src/queue/queue_internal.h	Sun Jan 31 21:28:42 2010 +1100
    35.3 @@ -0,0 +1,60 @@
    35.4 +/***** the library wide include file *****/
    35.5 +#include "liblfds_internal.h"
    35.6 +
    35.7 +/***** pragmas *****/
    35.8 +
    35.9 +/***** defines *****/
   35.10 +#define QUEUE_STATE_UNKNOWN               -1
   35.11 +#define QUEUE_STATE_EMPTY                  0
   35.12 +#define QUEUE_STATE_ENQUEUE_OUT_OF_PLACE   1
   35.13 +#define QUEUE_STATE_ATTEMPT_DEQUEUE        2
   35.14 +
   35.15 +#define QUEUE_POINTER 0
   35.16 +#define QUEUE_COUNTER 1
   35.17 +#define QUEUE_PAC_SIZE 2
   35.18 +
   35.19 +/***** structures *****/
   35.20 +#pragma pack( push, ALIGN_DOUBLE_POINTER )
   35.21 +
   35.22 +struct queue_state
   35.23 +{
   35.24 +  struct queue_element
   35.25 +    *volatile enqueue[QUEUE_PAC_SIZE],
   35.26 +    *volatile dequeue[QUEUE_PAC_SIZE];
   35.27 +
   35.28 +  atom_t
   35.29 +    aba_counter;
   35.30 +
   35.31 +  struct freelist_state
   35.32 +    *fs;
   35.33 +};
   35.34 +
   35.35 +struct queue_element
   35.36 +{
   35.37 +  // TRD : next in a queue requires volatile as it is target of CAS
   35.38 +  struct queue_element
   35.39 +    *volatile next[QUEUE_PAC_SIZE];
   35.40 +
   35.41 +  struct freelist_element
   35.42 +    *fe;
   35.43 +
   35.44 +  void
   35.45 +    *user_data;
   35.46 +};
   35.47 +
   35.48 +#pragma pack( pop )
   35.49 +
   35.50 +/***** externs *****/
   35.51 +
   35.52 +/***** private prototypes *****/
   35.53 +int queue_internal_freelist_init_function( void **user_data, void *user_state );
   35.54 +void queue_internal_freelist_delete_function( void *user_data, void *user_state );
   35.55 +
   35.56 +void queue_internal_new_element_from_freelist( struct queue_state *qs, struct queue_element *qe[QUEUE_PAC_SIZE], void *user_data );
   35.57 +void queue_internal_guaranteed_new_element_from_freelist( struct queue_state *qs, struct queue_element * qe[QUEUE_PAC_SIZE], void *user_data );
   35.58 +void queue_internal_init_element( struct queue_state *qs, struct queue_element *qe[QUEUE_PAC_SIZE], struct freelist_element *fe, void *user_data );
   35.59 +
   35.60 +void queue_internal_queue( struct queue_state *qs, struct queue_element *qe[QUEUE_PAC_SIZE] );
   35.61 +
   35.62 +void queue_internal_validate( struct queue_state *qs, struct validation_info *vi, enum data_structure_validity *queue_validity, enum data_structure_validity *freelist_validity );
   35.63 +
    36.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    36.2 +++ b/liblfds.6/src/queue/queue_new.c	Sun Jan 31 21:28:42 2010 +1100
    36.3 @@ -0,0 +1,140 @@
    36.4 +#include "queue_internal.h"
    36.5 +
    36.6 +
    36.7 +
    36.8 +
    36.9 +
   36.10 +/****************************************************************************/
   36.11 +int queue_new( struct queue_state **qs, atom_t number_elements )
   36.12 +{
   36.13 +  int
   36.14 +    rv = 0;
   36.15 +
   36.16 +  struct queue_element
   36.17 +    *qe[QUEUE_PAC_SIZE];
   36.18 +
   36.19 +  assert( qs != NULL );
   36.20 +  // TRD : number_elements can be any value in its range
   36.21 +
   36.22 +  *qs = (struct queue_state *) abstraction_aligned_malloc( sizeof(struct queue_state), ALIGN_DOUBLE_POINTER );
   36.23 +
   36.24 +  if( *qs != NULL )
   36.25 +  {
   36.26 +    // TRD : the size of the freelist is the size of the queue (+1 for the leading dummy element, which is hidden from the caller)
   36.27 +    freelist_new( &(*qs)->fs, number_elements+1, queue_internal_freelist_init_function, NULL );
   36.28 +
   36.29 +    if( (*qs)->fs != NULL )
   36.30 +    {
   36.31 +      queue_internal_new_element_from_freelist( *qs, qe, NULL );
   36.32 +      (*qs)->enqueue[QUEUE_POINTER] = (*qs)->dequeue[QUEUE_POINTER] = qe[QUEUE_POINTER];
   36.33 +      (*qs)->aba_counter = 0;
   36.34 +      rv = 1;
   36.35 +    }
   36.36 +
   36.37 +    if( (*qs)->fs == NULL )
   36.38 +    {
   36.39 +      abstraction_aligned_free( *qs );
   36.40 +      *qs = NULL;
   36.41 +    }
   36.42 +  }
   36.43 +
   36.44 +  return( rv );
   36.45 +}
   36.46 +
   36.47 +
   36.48 +
   36.49 +
   36.50 +
   36.51 +/****************************************************************************/
   36.52 +#pragma warning( disable : 4100 )
   36.53 +
   36.54 +int queue_internal_freelist_init_function( void **user_data, void *user_state )
   36.55 +{
   36.56 +  int
   36.57 +    rv = 0;
   36.58 +
   36.59 +  assert( user_data != NULL );
   36.60 +  assert( user_state == NULL );
   36.61 +
   36.62 +  *user_data = abstraction_aligned_malloc( sizeof(struct queue_element), ALIGN_DOUBLE_POINTER );
   36.63 +
   36.64 +  if( *user_data != NULL )
   36.65 +    rv = 1;
   36.66 +
   36.67 +  return( rv );
   36.68 +}
   36.69 +
   36.70 +#pragma warning( default : 4100 )
   36.71 +
   36.72 +
   36.73 +
   36.74 +
   36.75 +
   36.76 +/****************************************************************************/
   36.77 +void queue_internal_new_element_from_freelist( struct queue_state *qs, struct queue_element *qe[QUEUE_PAC_SIZE], void *user_data )
   36.78 +{
   36.79 +  struct freelist_element
   36.80 +    *fe;
   36.81 +
   36.82 +  assert( qs != NULL );
   36.83 +  assert( qe != NULL );
   36.84 +  // TRD : user_data can be any value in its range
   36.85 +
   36.86 +  qe[QUEUE_POINTER] = NULL;
   36.87 +
   36.88 +  freelist_pop( qs->fs, &fe );
   36.89 +
   36.90 +  if( fe != NULL )
   36.91 +    queue_internal_init_element( qs, qe, fe, user_data );
   36.92 +
   36.93 +  return;
   36.94 +}
   36.95 +
   36.96 +
   36.97 +
   36.98 +
   36.99 +
  36.100 +/****************************************************************************/
  36.101 +void queue_internal_guaranteed_new_element_from_freelist( struct queue_state *qs, struct queue_element *qe[QUEUE_PAC_SIZE], void *user_data )
  36.102 +{
  36.103 +  struct freelist_element
  36.104 +    *fe;
  36.105 +
  36.106 +  assert( qs != NULL );
  36.107 +  assert( qe != NULL );
  36.108 +  // TRD : user_data can be any value in its range
  36.109 +
  36.110 +  qe[QUEUE_POINTER] = NULL;
  36.111 +
  36.112 +  freelist_guaranteed_pop( qs->fs, &fe );
  36.113 +
  36.114 +  if( fe != NULL )
  36.115 +    queue_internal_init_element( qs, qe, fe, user_data );
  36.116 +
  36.117 +  return;
  36.118 +}
  36.119 +
  36.120 +
  36.121 +
  36.122 +
  36.123 +
  36.124 +/****************************************************************************/
  36.125 +void queue_internal_init_element( struct queue_state *qs, struct queue_element *qe[QUEUE_PAC_SIZE], struct freelist_element *fe, void *user_data )
  36.126 +{
  36.127 +  assert( qs != NULL );
  36.128 +  assert( qe != NULL );
  36.129 +  assert( fe != NULL );
  36.130 +  // TRD : user_data can be any value in its range
  36.131 +
  36.132 +  freelist_get_user_data_from_element( fe, (void **) &qe[QUEUE_POINTER] );
  36.133 +  qe[QUEUE_COUNTER] = (struct queue_element *) abstraction_increment( (atom_t *) &qs->aba_counter );
  36.134 +
  36.135 +  qe[QUEUE_POINTER]->next[QUEUE_POINTER] = NULL;
  36.136 +  qe[QUEUE_POINTER]->next[QUEUE_COUNTER] = (struct queue_element *) abstraction_increment( (atom_t *) &qs->aba_counter );
  36.137 +
  36.138 +  qe[QUEUE_POINTER]->fe = fe;
  36.139 +  qe[QUEUE_POINTER]->user_data = user_data;
  36.140 +
  36.141 +  return;
  36.142 +}
  36.143 +
    37.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    37.2 +++ b/liblfds.6/src/queue/queue_query.c	Sun Jan 31 21:28:42 2010 +1100
    37.3 @@ -0,0 +1,153 @@
    37.4 +#include "queue_internal.h"
    37.5 +
    37.6 +
    37.7 +
    37.8 +
    37.9 +
   37.10 +/****************************************************************************/
   37.11 +#pragma warning( disable : 4100 )
   37.12 +
   37.13 +void queue_query( struct queue_state *qs, enum queue_query_type query_type, void *query_input, void *query_output )
   37.14 +{
   37.15 +  assert( qs != NULL );
   37.16 +  // TRD : query_type can be any value in its range
   37.17 +  // TRD : query_input can be NULL
   37.18 +  assert( query_output != NULL );
   37.19 +
   37.20 +  switch( query_type )
   37.21 +  {
   37.22 +    case QUEUE_QUERY_ELEMENT_COUNT:
   37.23 +      assert( query_input == NULL );
   37.24 +
   37.25 +      freelist_query( qs->fs, FREELIST_QUERY_ELEMENT_COUNT, NULL, query_output );
   37.26 +    break;
   37.27 +
   37.28 +    case QUEUE_QUERY_VALIDATE:
   37.29 +      // TRD : query_input can be NULL
   37.30 +
   37.31 +      queue_internal_validate( qs, (struct validation_info *) query_input, (enum data_structure_validity *) query_output, ((enum data_structure_validity *) query_output)+1 );
   37.32 +    break;
   37.33 +  }
   37.34 +
   37.35 +  return;
   37.36 +}
   37.37 +
   37.38 +#pragma warning( default : 4100 )
   37.39 +
   37.40 +
   37.41 +
   37.42 +
   37.43 +
   37.44 +/****************************************************************************/
   37.45 +void queue_internal_validate( struct queue_state *qs, struct validation_info *vi, enum data_structure_validity *queue_validity, enum data_structure_validity *freelist_validity )
   37.46 +{
   37.47 +  struct queue_element
   37.48 +    *qe,
   37.49 +    *qe_slow,
   37.50 +    *qe_fast;
   37.51 +
   37.52 +  atom_t
   37.53 +    element_count = 0,
   37.54 +    total_elements;
   37.55 +
   37.56 +  struct validation_info
   37.57 +    freelist_vi;
   37.58 +
   37.59 +  assert( qs != NULL );
   37.60 +  // TRD : vi can be NULL
   37.61 +  assert( queue_validity != NULL );
   37.62 +  assert( freelist_validity != NULL );
   37.63 +
   37.64 +  *queue_validity = VALIDITY_VALID;
   37.65 +
   37.66 +  qe_slow = qe_fast = (struct queue_element *) qs->dequeue[QUEUE_POINTER];
   37.67 +
   37.68 +  /* TRD : first, check for a loop
   37.69 +           we have two pointers
   37.70 +           both of which start at the dequeue end of the queue
   37.71 +           we enter a loop
   37.72 +           and on each iteration
   37.73 +           we advance one pointer by one element
   37.74 +           and the other by two
   37.75 +
   37.76 +           we exit the loop when both pointers are NULL
   37.77 +           (have reached the end of the queue)
   37.78 +
   37.79 +           or
   37.80 +
   37.81 +           if we fast pointer 'sees' the slow pointer
   37.82 +           which means we have a loop
   37.83 +  */
   37.84 +
   37.85 +  if( qe_slow != NULL )
   37.86 +    do
   37.87 +    {
   37.88 +      qe_slow = qe_slow->next[QUEUE_POINTER];
   37.89 +
   37.90 +      if( qe_fast != NULL )
   37.91 +        qe_fast = qe_fast->next[QUEUE_POINTER];
   37.92 +
   37.93 +      if( qe_fast != NULL )
   37.94 +        qe_fast = qe_fast->next[QUEUE_POINTER];
   37.95 +    }
   37.96 +    while( qe_slow != NULL and qe_fast != qe_slow );
   37.97 +
   37.98 +  if( qe_fast != NULL and qe_slow != NULL and qe_fast == qe_slow )
   37.99 +    *queue_validity = VALIDITY_INVALID_LOOP;
  37.100 +
  37.101 +  /* TRD : now check for expected number of elements
  37.102 +           vi can be NULL, in which case we do not check
  37.103 +           we know we don't have a loop from our earlier check
  37.104 +  */
  37.105 +
  37.106 +  if( *queue_validity == VALIDITY_VALID and vi != NULL )
  37.107 +  {
  37.108 +    qe = (struct queue_element *) qs->dequeue[QUEUE_POINTER];
  37.109 +
  37.110 +    while( qe != NULL )
  37.111 +    {
  37.112 +      element_count++;
  37.113 +      qe = (struct queue_element *) qe->next[QUEUE_POINTER];
  37.114 +    }
  37.115 +
  37.116 +    /* TRD : remember there is a dummy element in the queue */
  37.117 +    element_count--;
  37.118 +
  37.119 +    if( element_count < vi->min_elements )
  37.120 +      *queue_validity = VALIDITY_INVALID_MISSING_ELEMENTS;
  37.121 +
  37.122 +    if( element_count > vi->max_elements )
  37.123 +      *queue_validity = VALIDITY_INVALID_ADDITIONAL_ELEMENTS;
  37.124 +  }
  37.125 +
  37.126 +  /* TRD : now we validate the freelist
  37.127 +
  37.128 +           we may be able to check for the expected number of
  37.129 +           elements in the freelist
  37.130 +
  37.131 +           if the caller has given us an expected min and max
  37.132 +           number of elements in the queue, then the total number
  37.133 +           of elements in the freelist, minus that min and max,
  37.134 +           gives us the expected number of elements in the
  37.135 +           freelist
  37.136 +  */
  37.137 +
  37.138 +  if( vi != NULL )
  37.139 +  {
  37.140 +    freelist_query( qs->fs, FREELIST_QUERY_ELEMENT_COUNT, NULL, (void *) &total_elements );
  37.141 +
  37.142 +    /* TRD : remember there is a dummy element in the queue */
  37.143 +    total_elements--;
  37.144 +
  37.145 +    freelist_vi.min_elements = total_elements - vi->max_elements;
  37.146 +    freelist_vi.max_elements = total_elements - vi->min_elements;
  37.147 +
  37.148 +    freelist_query( qs->fs, FREELIST_QUERY_VALIDATE, (void *) &freelist_vi, (void *) freelist_validity );
  37.149 +  }
  37.150 +
  37.151 +  if( vi == NULL )
  37.152 +    freelist_query( qs->fs, FREELIST_QUERY_VALIDATE, NULL, (void *) freelist_validity );
  37.153 +
  37.154 +  return;
  37.155 +}
  37.156 +
    38.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    38.2 +++ b/liblfds.6/src/queue/queue_queue.c	Sun Jan 31 21:28:42 2010 +1100
    38.3 @@ -0,0 +1,181 @@
    38.4 +#include "queue_internal.h"
    38.5 +
    38.6 +
    38.7 +
    38.8 +
    38.9 +
   38.10 +/****************************************************************************/
   38.11 +int queue_enqueue( struct queue_state *qs, void *user_data )
   38.12 +{
   38.13 +  ALIGN(ALIGN_DOUBLE_POINTER) struct queue_element
   38.14 +    *qe[QUEUE_PAC_SIZE];
   38.15 +
   38.16 +  assert( qs != NULL );
   38.17 +  // TRD : user_data can be NULL
   38.18 +
   38.19 +  queue_internal_new_element_from_freelist( qs, qe, user_data );
   38.20 +
   38.21 +  if( qe[QUEUE_POINTER] == NULL )
   38.22 +    return( 0 );
   38.23 +
   38.24 +  queue_internal_queue( qs, qe );
   38.25 +
   38.26 +  return( 1 );
   38.27 +}
   38.28 +
   38.29 +
   38.30 +
   38.31 +
   38.32 +
   38.33 +/****************************************************************************/
   38.34 +int queue_guaranteed_enqueue( struct queue_state *qs, void *user_data )
   38.35 +{
   38.36 +  ALIGN(ALIGN_DOUBLE_POINTER) struct queue_element
   38.37 +    *qe[QUEUE_PAC_SIZE];
   38.38 +
   38.39 +  assert( qs != NULL );
   38.40 +  // TRD : user_data can be NULL
   38.41 +
   38.42 +  queue_internal_guaranteed_new_element_from_freelist( qs, qe, user_data );
   38.43 +
   38.44 +  if( qe[QUEUE_POINTER] == NULL )
   38.45 +    return( 0 );
   38.46 +
   38.47 +  queue_internal_queue( qs, qe );
   38.48 +
   38.49 +  return( 1 );
   38.50 +}
   38.51 +
   38.52 +
   38.53 +
   38.54 +
   38.55 +
   38.56 +/****************************************************************************/
   38.57 +void queue_internal_queue( struct queue_state *qs, struct queue_element *qe[QUEUE_PAC_SIZE] )
   38.58 +{
   38.59 +  ALIGN(ALIGN_DOUBLE_POINTER) struct queue_element
   38.60 +    *enqueue[QUEUE_PAC_SIZE],
   38.61 +    *next[QUEUE_PAC_SIZE];
   38.62 +
   38.63 +  unsigned char
   38.64 +    cas_result = 0;
   38.65 +
   38.66 +  assert( qs != NULL );
   38.67 +  assert( qe != NULL );
   38.68 +
   38.69 +  do
   38.70 +  {
   38.71 +    enqueue[QUEUE_POINTER] = qs->enqueue[QUEUE_POINTER];
   38.72 +    enqueue[QUEUE_COUNTER] = qs->enqueue[QUEUE_COUNTER];
   38.73 +
   38.74 +    next[QUEUE_POINTER] = enqueue[QUEUE_POINTER]->next[QUEUE_POINTER];
   38.75 +    next[QUEUE_COUNTER] = enqueue[QUEUE_POINTER]->next[QUEUE_COUNTER];
   38.76 +
   38.77 +    /* TRD : this if() ensures that the next we read, just above,
   38.78 +             really is from qs->enqueue (which we copied into enqueue)
   38.79 +    */
   38.80 +
   38.81 +    if( qs->enqueue[QUEUE_POINTER] == enqueue[QUEUE_POINTER] and qs->enqueue[QUEUE_COUNTER] == enqueue[QUEUE_COUNTER] )
   38.82 +    {
   38.83 +      if( next[QUEUE_POINTER] == NULL )
   38.84 +      {
   38.85 +        qe[QUEUE_COUNTER] = next[QUEUE_COUNTER] + 1;
   38.86 +        cas_result = abstraction_dcas( (volatile atom_t *) enqueue[QUEUE_POINTER]->next, (atom_t *) qe, (atom_t *) next );
   38.87 +      }
   38.88 +      else
   38.89 +      {
   38.90 +        next[QUEUE_COUNTER] = enqueue[QUEUE_COUNTER] + 1;
   38.91 +        abstraction_dcas( (volatile atom_t *) qs->enqueue, (atom_t *) next, (atom_t *) enqueue );
   38.92 +      }
   38.93 +    }
   38.94 +  }
   38.95 +  while( cas_result == 0 );
   38.96 +
   38.97 +  qe[QUEUE_COUNTER] = enqueue[QUEUE_COUNTER] + 1;
   38.98 +  abstraction_dcas( (volatile atom_t *) qs->enqueue, (atom_t *) qe, (atom_t *) enqueue );
   38.99 +
  38.100 +  return;
  38.101 +}
  38.102 +
  38.103 +
  38.104 +
  38.105 +
  38.106 +
  38.107 +/****************************************************************************/
  38.108 +int queue_dequeue( struct queue_state *qs, void **user_data )
  38.109 +{
  38.110 +  ALIGN(ALIGN_DOUBLE_POINTER) struct queue_element
  38.111 +    *enqueue[QUEUE_PAC_SIZE],
  38.112 +    *dequeue[QUEUE_PAC_SIZE],
  38.113 +    *next[QUEUE_PAC_SIZE];
  38.114 +
  38.115 +  unsigned char
  38.116 +    cas_result = 0;
  38.117 +
  38.118 +  int
  38.119 +    rv = 1,
  38.120 +    state = QUEUE_STATE_UNKNOWN,
  38.121 +    finished_flag = LOWERED;
  38.122 +
  38.123 +  assert( qs != NULL );
  38.124 +  assert( user_data != NULL );
  38.125 +
  38.126 +  do
  38.127 +  {
  38.128 +    dequeue[QUEUE_POINTER] = qs->dequeue[QUEUE_POINTER];
  38.129 +    dequeue[QUEUE_COUNTER] = qs->dequeue[QUEUE_COUNTER];
  38.130 +
  38.131 +    enqueue[QUEUE_POINTER] = qs->enqueue[QUEUE_POINTER];
  38.132 +    enqueue[QUEUE_COUNTER] = qs->enqueue[QUEUE_COUNTER];
  38.133 +
  38.134 +    next[QUEUE_POINTER] = dequeue[QUEUE_POINTER]->next[QUEUE_POINTER];
  38.135 +    next[QUEUE_COUNTER] = dequeue[QUEUE_POINTER]->next[QUEUE_COUNTER];
  38.136 +
  38.137 +    /* TRD : confirm that dequeue didn't move between reading it
  38.138 +             and reading its next pointer
  38.139 +    */
  38.140 +
  38.141 +    if( dequeue[QUEUE_POINTER] == qs->dequeue[QUEUE_POINTER] and dequeue[QUEUE_COUNTER] == qs->dequeue[QUEUE_COUNTER] )
  38.142 +    {
  38.143 +      if( enqueue[QUEUE_POINTER] == dequeue[QUEUE_POINTER] and next[QUEUE_POINTER] == NULL )
  38.144 +        state = QUEUE_STATE_EMPTY;
  38.145 +
  38.146 +      if( enqueue[QUEUE_POINTER] == dequeue[QUEUE_POINTER] and next[QUEUE_POINTER] != NULL )
  38.147 +        state = QUEUE_STATE_ENQUEUE_OUT_OF_PLACE;
  38.148 +
  38.149 +      if( enqueue[QUEUE_POINTER] != dequeue[QUEUE_POINTER] )
  38.150 +        state = QUEUE_STATE_ATTEMPT_DEQUEUE;
  38.151 +
  38.152 +      switch( state )
  38.153 +      {
  38.154 +        case QUEUE_STATE_EMPTY:
  38.155 +          *user_data = NULL;
  38.156 +          rv = 0;
  38.157 +          finished_flag = RAISED;
  38.158 +        break;
  38.159 +
  38.160 +        case QUEUE_STATE_ENQUEUE_OUT_OF_PLACE:
  38.161 +          next[QUEUE_COUNTER] = enqueue[QUEUE_COUNTER] + 1;
  38.162 +          abstraction_dcas( (volatile atom_t *) qs->enqueue, (atom_t *) next, (atom_t *) enqueue );
  38.163 +        break;
  38.164 +
  38.165 +        case QUEUE_STATE_ATTEMPT_DEQUEUE:
  38.166 +          *user_data = next[QUEUE_POINTER]->user_data;
  38.167 +
  38.168 +          next[QUEUE_COUNTER] = dequeue[QUEUE_COUNTER] + 1;
  38.169 +          cas_result = abstraction_dcas( (volatile atom_t *) qs->dequeue, (atom_t *) next, (atom_t *) dequeue );
  38.170 +
  38.171 +          if( cas_result == 1 )
  38.172 +            finished_flag = RAISED;
  38.173 +        break;
  38.174 +      }
  38.175 +    }
  38.176 +  }
  38.177 +  while( finished_flag == LOWERED );
  38.178 +
  38.179 +  if( cas_result == 1 )
  38.180 +    freelist_push( qs->fs, dequeue[QUEUE_POINTER]->fe );
  38.181 +
  38.182 +  return( rv );
  38.183 +}
  38.184 +
    39.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    39.2 +++ b/liblfds.6/src/ringbuffer/ringbuffer_delete.c	Sun Jan 31 21:28:42 2010 +1100
    39.3 @@ -0,0 +1,22 @@
    39.4 +#include "ringbuffer_internal.h"
    39.5 +
    39.6 +
    39.7 +
    39.8 +
    39.9 +
   39.10 +/****************************************************************************/
   39.11 +void ringbuffer_delete( struct ringbuffer_state *rs, void (*user_data_delete_function)(void *user_data, void *user_state), void *user_state )
   39.12 +{
   39.13 +  assert( rs != NULL );
   39.14 +  // TRD : user_data_delete_function can be NULL
   39.15 +  // TRD : user_state can be NULL
   39.16 +
   39.17 +  queue_delete( rs->qs, NULL, NULL );
   39.18 +
   39.19 +  freelist_delete( rs->fs, user_data_delete_function, user_state );
   39.20 +
   39.21 +  abstraction_aligned_free( rs );
   39.22 +
   39.23 +  return;
   39.24 +}
   39.25 +
    40.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    40.2 +++ b/liblfds.6/src/ringbuffer/ringbuffer_get_and_put.c	Sun Jan 31 21:28:42 2010 +1100
    40.3 @@ -0,0 +1,108 @@
    40.4 +#include "ringbuffer_internal.h"
    40.5 +
    40.6 +
    40.7 +
    40.8 +
    40.9 +
   40.10 +/****************************************************************************/
   40.11 +struct freelist_element *ringbuffer_get_read_element( struct ringbuffer_state *rs, struct freelist_element **fe )
   40.12 +{
   40.13 +  assert( rs != NULL );
   40.14 +  assert( fe != NULL );
   40.15 +
   40.16 +  queue_dequeue( rs->qs, (void **) fe );
   40.17 +
   40.18 +  return( *fe );
   40.19 +}
   40.20 +
   40.21 +
   40.22 +
   40.23 +
   40.24 +
   40.25 +/****************************************************************************/
   40.26 +struct freelist_element *ringbuffer_get_write_element( struct ringbuffer_state *rs, struct freelist_element **fe, int *overwrite_flag )
   40.27 +{
   40.28 +  assert( rs != NULL );
   40.29 +  assert( fe != NULL );
   40.30 +  // TRD : overwrite_flag can be NULL
   40.31 +
   40.32 +  /* TRD : we try to obtain an element from the freelist
   40.33 +           if we can, we populate it and add it to the queue
   40.34 +
   40.35 +           if we cannot, then the ringbuffer is full
   40.36 +           so instead we grab the current read element and
   40.37 +           use that instead
   40.38 +
   40.39 +           dequeue may fail since the queue may be emptied
   40.40 +           during our dequeue attempt
   40.41 +
   40.42 +           so what we actually do here is a loop, attempting
   40.43 +           the freelist and if it fails then a dequeue, until
   40.44 +           we obtain an element
   40.45 +
   40.46 +           once we have an element, we queue it
   40.47 +
   40.48 +           you may be wondering why this operation is in a loop
   40.49 +           remember - these operations are lock-free; anything
   40.50 +           can happen in between
   40.51 +
   40.52 +           so for example the pop could fail because the freelist
   40.53 +           is empty; but by the time we go to get an element from
   40.54 +           the queue, the whole queue has been emptied back into
   40.55 +           the freelist!
   40.56 +
   40.57 +           if overwrite_flag is provided, we set it to 0 if we
   40.58 +           obtained a new element from the freelist, 1 if we
   40.59 +           stole an element from the queue
   40.60 +  */
   40.61 +
   40.62 +  do
   40.63 +  {
   40.64 +    if( overwrite_flag != NULL )
   40.65 +      *overwrite_flag = 0;
   40.66 +
   40.67 +    freelist_pop( rs->fs, fe );
   40.68 +
   40.69 +    if( *fe == NULL )
   40.70 +    {
   40.71 +      ringbuffer_get_read_element( rs, fe );
   40.72 +
   40.73 +      if( overwrite_flag != NULL and *fe != NULL )
   40.74 +        *overwrite_flag = 1;
   40.75 +    }
   40.76 +  }
   40.77 +  while( *fe == NULL );
   40.78 +
   40.79 +  return( *fe );
   40.80 +}
   40.81 +
   40.82 +
   40.83 +
   40.84 +
   40.85 +
   40.86 +/****************************************************************************/
   40.87 +void ringbuffer_put_read_element( struct ringbuffer_state *rs, struct freelist_element *fe )
   40.88 +{
   40.89 +  assert( rs != NULL );
   40.90 +  assert( fe != NULL );
   40.91 +
   40.92 +  freelist_push( rs->fs, fe );
   40.93 +
   40.94 +  return;
   40.95 +}
   40.96 +
   40.97 +
   40.98 +
   40.99 +
  40.100 +
  40.101 +/****************************************************************************/
  40.102 +void ringbuffer_put_write_element( struct ringbuffer_state *rs, struct freelist_element *fe )
  40.103 +{
  40.104 +  assert( rs != NULL );
  40.105 +  assert( fe != NULL );
  40.106 +
  40.107 +  queue_enqueue( rs->qs, fe );
  40.108 +
  40.109 +  return;
  40.110 +}
  40.111 +
    41.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    41.2 +++ b/liblfds.6/src/ringbuffer/ringbuffer_internal.h	Sun Jan 31 21:28:42 2010 +1100
    41.3 @@ -0,0 +1,24 @@
    41.4 +/***** the library wide include file *****/
    41.5 +#include "liblfds_internal.h"
    41.6 +
    41.7 +/***** defines *****/
    41.8 +
    41.9 +/***** structures *****/
   41.10 +#pragma pack( push, ALIGN_DOUBLE_POINTER )
   41.11 +
   41.12 +struct ringbuffer_state
   41.13 +{
   41.14 +  struct queue_state
   41.15 +    *qs;
   41.16 +
   41.17 +  struct freelist_state
   41.18 +    *fs;
   41.19 +};
   41.20 +
   41.21 +#pragma pack( pop )
   41.22 +
   41.23 +/***** externs *****/
   41.24 +
   41.25 +/***** private prototypes *****/
   41.26 +void ringbuffer_internal_validate( struct ringbuffer_state *rs, struct validation_info *vi, enum data_structure_validity *queue_validity, enum data_structure_validity *freelist_validity );
   41.27 +
    42.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    42.2 +++ b/liblfds.6/src/ringbuffer/ringbuffer_new.c	Sun Jan 31 21:28:42 2010 +1100
    42.3 @@ -0,0 +1,47 @@
    42.4 +#include "ringbuffer_internal.h"
    42.5 +
    42.6 +
    42.7 +
    42.8 +
    42.9 +
   42.10 +/****************************************************************************/
   42.11 +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 )
   42.12 +{
   42.13 +  int
   42.14 +    rv = 0;
   42.15 +
   42.16 +  assert( rs != NULL );
   42.17 +  // TRD : number_elements can be any value in its range
   42.18 +  // TRD : user_data_init_function can be NULL
   42.19 +  // TRD : user_state can be NULL
   42.20 +
   42.21 +  *rs = (struct ringbuffer_state *) abstraction_aligned_malloc( sizeof(struct ringbuffer_state), ALIGN_DOUBLE_POINTER );
   42.22 +
   42.23 +  if( *rs != NULL )
   42.24 +  {
   42.25 +    freelist_new( &(*rs)->fs, number_elements, user_data_init_function, user_state );
   42.26 +
   42.27 +    if( (*rs)->fs != NULL )
   42.28 +    {
   42.29 +      queue_new( &(*rs)->qs, number_elements );
   42.30 +
   42.31 +      if( (*rs)->qs != NULL )
   42.32 +        rv = 1;
   42.33 +
   42.34 +      if( (*rs)->qs == NULL )
   42.35 +      {
   42.36 +        abstraction_aligned_free( *rs );
   42.37 +        *rs = NULL;
   42.38 +      }
   42.39 +    }
   42.40 +
   42.41 +    if( (*rs)->fs == NULL )
   42.42 +    {
   42.43 +      abstraction_aligned_free( *rs );
   42.44 +      *rs = NULL;
   42.45 +    }
   42.46 +  }
   42.47 +
   42.48 +  return( rv );
   42.49 +}
   42.50 +
    43.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    43.2 +++ b/liblfds.6/src/ringbuffer/ringbuffer_query.c	Sun Jan 31 21:28:42 2010 +1100
    43.3 @@ -0,0 +1,64 @@
    43.4 +#include "ringbuffer_internal.h"
    43.5 +
    43.6 +
    43.7 +
    43.8 +
    43.9 +
   43.10 +/****************************************************************************/
   43.11 +#pragma warning( disable : 4100 )
   43.12 +
   43.13 +void ringbuffer_query( struct ringbuffer_state *rs, enum ringbuffer_query_type query_type, void *query_input, void *query_output )
   43.14 +{
   43.15 +  assert( rs != NULL );
   43.16 +  // TRD : query_type can be any value in its range
   43.17 +  // TRD : query_input can be NULL
   43.18 +  assert( query_output != NULL );
   43.19 +
   43.20 +  switch( query_type )
   43.21 +  {
   43.22 +    case RINGBUFFER_QUERY_VALIDATE:
   43.23 +      // TRD : query_input can be NULL
   43.24 +
   43.25 +      ringbuffer_internal_validate( rs, (struct validation_info *) query_input, (enum data_structure_validity *) query_output, ((enum data_structure_validity *) query_output)+2 );
   43.26 +    break;
   43.27 +  }
   43.28 +
   43.29 +  return;
   43.30 +}
   43.31 +
   43.32 +#pragma warning( default : 4100 )
   43.33 +
   43.34 +
   43.35 +
   43.36 +
   43.37 +
   43.38 +/****************************************************************************/
   43.39 +void ringbuffer_internal_validate( struct ringbuffer_state *rs, struct validation_info *vi, enum data_structure_validity *queue_validity, enum data_structure_validity *freelist_validity )
   43.40 +{
   43.41 +  assert( rs != NULL );
   43.42 +  // TRD : vi can be NULL
   43.43 +  assert( queue_validity != NULL );
   43.44 +  assert( freelist_validity != NULL );
   43.45 +
   43.46 +  queue_query( rs->qs, QUEUE_QUERY_VALIDATE, vi, queue_validity );
   43.47 +
   43.48 +  if( vi != NULL )
   43.49 +  {
   43.50 +    struct validation_info
   43.51 +      freelist_vi;
   43.52 +
   43.53 +    atom_t
   43.54 +      total_elements;
   43.55 +
   43.56 +    freelist_query( rs->fs, FREELIST_QUERY_ELEMENT_COUNT, NULL, (void *) &total_elements );
   43.57 +    freelist_vi.min_elements = total_elements - vi->max_elements;
   43.58 +    freelist_vi.max_elements = total_elements - vi->min_elements;
   43.59 +    freelist_query( rs->fs, FREELIST_QUERY_VALIDATE, (void *) &freelist_vi, (void *) freelist_validity );
   43.60 +  }
   43.61 +
   43.62 +  if( vi == NULL )
   43.63 +    freelist_query( rs->fs, FREELIST_QUERY_VALIDATE, NULL, (void *) freelist_validity );
   43.64 +
   43.65 +  return;
   43.66 +}
   43.67 +
    44.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    44.2 +++ b/liblfds.6/src/single_dir_for_windows_kernel/abstraction_aligned_free.c	Sun Jan 31 21:28:42 2010 +1100
    44.3 @@ -0,0 +1,72 @@
    44.4 +#include "abstraction_internal.h"
    44.5 +
    44.6 +
    44.7 +
    44.8 +
    44.9 +
   44.10 +/****************************************************************************/
   44.11 +#if (defined _WIN32 && defined _MSC_VER && !defined WIN_KERNEL_BUILD)
   44.12 +
   44.13 +  /* TRD : any Windows (user-mode) on any CPU with the Microsoft C compiler
   44.14 +
   44.15 +           _WIN32             indicates 64-bit or 32-bit Windows
   44.16 +           _MSC_VER           indicates Microsoft C compiler
   44.17 +           !WIN_KERNEL_BUILD  indicates Windows user-mode
   44.18 +  */
   44.19 +
   44.20 +  void abstraction_aligned_free( void *memory )
   44.21 +  {
   44.22 +    _aligned_free( memory );
   44.23 +
   44.24 +    return;
   44.25 +  }
   44.26 +
   44.27 +#endif
   44.28 +
   44.29 +
   44.30 +
   44.31 +
   44.32 +
   44.33 +/****************************************************************************/
   44.34 +#if (_XOPEN_SOURCE >= 600)
   44.35 +
   44.36 +  /* TRD : any OS on any CPU with any compiler with POSIX 6.00 or better
   44.37 +
   44.38 +           _XOPEN_SOURCE  is actually set by the user, not by the compiler
   44.39 +                          it is the way the user signals to the compiler what
   44.40 +                          level of POSIX should be available
   44.41 +                          (it assumes of course the compiler has support for the given level of POSIX requested)
   44.42 +  */
   44.43 +
   44.44 +  void abstraction_aligned_free( void *memory )
   44.45 +  {
   44.46 +    free( memory );
   44.47 +
   44.48 +    return;
   44.49 +  }
   44.50 +
   44.51 +#endif
   44.52 +
   44.53 +
   44.54 +
   44.55 +
   44.56 +
   44.57 +/****************************************************************************/
   44.58 +#if (defined _WIN32 && defined _MSC_VER && defined WIN_KERNEL_BUILD)
   44.59 +
   44.60 +  /* TRD : any Windows (kernel) on any CPU with the Microsoft C compiler
   44.61 +
   44.62 +           _WIN32            indicates 64-bit or 32-bit Windows
   44.63 +           _MSC_VER          indicates Microsoft C compiler
   44.64 +           WIN_KERNEL_BUILD  indicates Windows kernel
   44.65 +  */
   44.66 +
   44.67 +  void abstraction_aligned_free( void *memory )
   44.68 +  {
   44.69 +    ExFreePoolWithTag( memory, 'sdfl' );
   44.70 +
   44.71 +    return;
   44.72 +  }
   44.73 +
   44.74 +#endif
   44.75 +
    45.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    45.2 +++ b/liblfds.6/src/single_dir_for_windows_kernel/abstraction_aligned_malloc.c	Sun Jan 31 21:28:42 2010 +1100
    45.3 @@ -0,0 +1,97 @@
    45.4 +#include "abstraction_internal.h"
    45.5 +
    45.6 +
    45.7 +
    45.8 +
    45.9 +
   45.10 +/****************************************************************************/
   45.11 +#if (defined _WIN32 && defined _MSC_VER && !defined WIN_KERNEL_BUILD)
   45.12 +
   45.13 +  /* TRD : any Windows (user-mode) on any CPU with the Microsoft C compiler
   45.14 +
   45.15 +           _WIN32             indicates 64-bit or 32-bit Windows
   45.16 +           _MSC_VER           indicates Microsoft C compiler
   45.17 +           !WIN_KERNEL_BUILD  indicates Windows user-mode
   45.18 +  */
   45.19 +
   45.20 +  void *abstraction_aligned_malloc( size_t size, size_t align_in_bytes )
   45.21 +  {
   45.22 +    void
   45.23 +      *rv;
   45.24 +
   45.25 +    rv = _aligned_malloc( size, align_in_bytes );
   45.26 +
   45.27 +    return( rv );
   45.28 +  }
   45.29 +
   45.30 +#endif
   45.31 +
   45.32 +
   45.33 +
   45.34 +
   45.35 +
   45.36 +/****************************************************************************/
   45.37 +#if (_XOPEN_SOURCE >= 600)
   45.38 +
   45.39 +  /* TRD : any OS on any CPU with any compiler with POSIX 6.00 or better
   45.40 +
   45.41 +           _XOPEN_SOURCE  is actually set by the user, not by the compiler
   45.42 +                          it is the way the user signals to the compiler what
   45.43 +                          level of POSIX should be available
   45.44 +                          (it assumes of course the compiler has support for the given level of POSIX requested)
   45.45 +  */
   45.46 +
   45.47 +  void *abstraction_aligned_malloc( size_t size, size_t align_in_bytes )
   45.48 +  {
   45.49 +    int
   45.50 +      rv;
   45.51 +
   45.52 +    void
   45.53 +      *memory;
   45.54 +
   45.55 +    rv = posix_memalign( &memory, align_in_bytes, size );
   45.56 +
   45.57 +    // TRD : posix_memalign returns 0 on success, docs do not say *memory == NULL on fail
   45.58 +    if( rv != 0 )
   45.59 +      memory = NULL;
   45.60 +
   45.61 +    return( memory );
   45.62 +  }
   45.63 +
   45.64 +#endif
   45.65 +
   45.66 +
   45.67 +
   45.68 +
   45.69 +
   45.70 +/****************************************************************************/
   45.71 +#if (defined _WIN32 && defined _MSC_VER && defined WIN_KERNEL_BUILD)
   45.72 +
   45.73 +  /* TRD : any Windows (kernel) on any CPU with the Microsoft C compiler
   45.74 +
   45.75 +           _WIN32            indicates 64-bit or 32-bit Windows
   45.76 +           _MSC_VER          indicates Microsoft C compiler
   45.77 +           WIN_KERNEL_BUILD  indicates Windows kernel
   45.78 +  */
   45.79 +
   45.80 +  void *abstraction_aligned_malloc( size_t size, size_t align_in_bytes )
   45.81 +  {
   45.82 +    void
   45.83 +      *rv;
   45.84 +
   45.85 +    /* TRD : ExAllocatePoolWithTag() allocates memory aligned on 8 bytes on 32-bit CPUs
   45.86 +             and on 16 bytes on 64-bit CPUs, which is what we want
   45.87 +
   45.88 +             as such, align_in_bytes is not needed; we must refer to it to avoid the
   45.89 +             compiler warning
   45.90 +    */
   45.91 +
   45.92 +    align_in_bytes;
   45.93 +
   45.94 +    rv = ExAllocatePoolWithTag( NonPagedPool, size, 'sdfl' );
   45.95 +
   45.96 +    return( rv );
   45.97 +  }
   45.98 +
   45.99 +#endif
  45.100 +
    46.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    46.2 +++ b/liblfds.6/src/single_dir_for_windows_kernel/abstraction_cas.c	Sun Jan 31 21:28:42 2010 +1100
    46.3 @@ -0,0 +1,109 @@
    46.4 +#include "abstraction_internal.h"
    46.5 +
    46.6 +
    46.7 +
    46.8 +
    46.9 +
   46.10 +/****************************************************************************/
   46.11 +#if (defined _WIN32 && defined _MSC_VER)
   46.12 +
   46.13 +  /* TRD : 64 bit and 32 bit Windows (user-mode or kernel) on any CPU with the Microsoft C compiler
   46.14 +
   46.15 +           _WIN32    indicates 64-bit or 32-bit Windows
   46.16 +           _MSC_VER  indicates Microsoft C compiler
   46.17 +  */
   46.18 +
   46.19 +  INLINE atom_t abstraction_cas( volatile atom_t *destination, atom_t exchange, atom_t compare )
   46.20 +  {
   46.21 +    assert( destination != NULL );
   46.22 +    // TRD : exchange can be any value in its range
   46.23 +    // TRD : compare can be any value in its range
   46.24 +
   46.25 +    return( (atom_t) _InterlockedCompareExchangePointer((void * volatile *) destination, (void *) exchange, (void *) compare) );
   46.26 +  }
   46.27 +
   46.28 +#endif
   46.29 +
   46.30 +
   46.31 +
   46.32 +
   46.33 +
   46.34 +/****************************************************************************/
   46.35 +#if (!defined __arm__ && __GNUC__ >= 4 && __GNUC_MINOR__ >= 1 && __GNUC_PATCHLEVEL__ >= 0)
   46.36 +
   46.37 +  /* TRD : any OS on any CPU except ARM with GCC 4.1.0 or better
   46.38 +
   46.39 +           GCC 4.1.0 introduced the __sync_*() atomic intrinsics
   46.40 +
   46.41 +           __GNUC__ / __GNUC_MINOR__ / __GNUC_PATCHLEVEL__  indicates GCC and which version
   46.42 +  */
   46.43 +
   46.44 +  INLINE atom_t abstraction_cas( volatile atom_t *destination, atom_t exchange, atom_t compare )
   46.45 +  {
   46.46 +    assert( destination != NULL );
   46.47 +    // TRD : exchange can be any value in its range
   46.48 +    // TRD : compare can be any value in its range
   46.49 +
   46.50 +    // TRD : note the different argument order for the GCC instrinsic to the MSVC instrinsic
   46.51 +
   46.52 +    return( (atom_t) __sync_val_compare_and_swap(destination, compare, exchange) );
   46.53 +  }
   46.54 +
   46.55 +#endif
   46.56 +
   46.57 +
   46.58 +
   46.59 +
   46.60 +
   46.61 +/****************************************************************************/
   46.62 +#if (defined __arm__ && __GNUC__)
   46.63 +
   46.64 +  /* TRD : any OS on any ARM with GCC
   46.65 +
   46.66 +           Remember however we need to set into compare the original value of destination.
   46.67 +
   46.68 +           __arm__   indicates ARM
   46.69 +           __GNUC__  indicates GCC
   46.70 +  */
   46.71 +
   46.72 +  INLINE atom_t abstraction_cas( volatile atom_t *destination, atom_t exchange, atom_t compare )
   46.73 +  {
   46.74 +    atom_t
   46.75 +      stored_flag,
   46.76 +      original_destination;
   46.77 +
   46.78 +    assert( destination != NULL );
   46.79 +    // TRD : exchange can be any value in its range
   46.80 +    // TRD : compare can be any value in its range
   46.81 +
   46.82 +    /* TRD : this is a standard, plain CAS, vulnerable to ABA */
   46.83 +
   46.84 +    __asm__ __volatile__
   46.85 +    (
   46.86 +      "  mov    %[stored_flag], #1;"                             // put 1 into stored_flag
   46.87 +      "  mcr    p15, 0, %[zero], c7, c10, 5;"                    // memory barrier (ARM v6 compatible)
   46.88 +      "atomic_cas:;"
   46.89 +      "  ldrex  %[original_destination], [%[destination]];"      // load *destination into original_destination
   46.90 +      "  teq    %[original_destination], %[compare];"            // compare original_destination with compare
   46.91 +      "  bne    exit;"                                           // if not equal, exit
   46.92 +      "  strex  %[stored_flag], %[exchange], [%[destination]];"  // if equal, try to store exchange into *destination (on success, strex puts 0 into stored_flag)
   46.93 +      "  teq    %[stored_flag], #0;"                             // check if stored_flag is 0
   46.94 +      "  bne    atomic_cas;"                                     // if not 0, retry (someone else touched *destination after we loaded but before we stored)
   46.95 +      "  mcr    p15, 0, %[zero], c7, c10, 5;"                    // memory barrier (ARM v6 compatible)
   46.96 +      "exit:;"
   46.97 +
   46.98 +      // output
   46.99 +      : "+m" (*destination), [original_destination] "=&r" (original_destination), [stored_flag] "=&r" (stored_flag)
  46.100 +
  46.101 +      // input
  46.102 +      : [destination] "r" (destination), [compare] "r" (compare), [exchange] "r" (exchange), [zero] "r" (0)
  46.103 +
  46.104 +      // clobbered
  46.105 +      : "cc", "memory"                                           // memory is clobbered because we issue a memory barrier
  46.106 +    );
  46.107 +
  46.108 +    return( original_destination );
  46.109 +  }
  46.110 +
  46.111 +#endif
  46.112 +
    47.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    47.2 +++ b/liblfds.6/src/single_dir_for_windows_kernel/abstraction_dcas.c	Sun Jan 31 21:28:42 2010 +1100
    47.3 @@ -0,0 +1,356 @@
    47.4 +#include "abstraction_internal.h"
    47.5 +
    47.6 +
    47.7 +
    47.8 +
    47.9 +
   47.10 +/****************************************************************************/
   47.11 +#if (defined _WIN64 && defined _MSC_VER)
   47.12 +
   47.13 +  /* TRD : 64 bit Windows (user-mode or kernel) on any CPU with the Microsoft C compiler
   47.14 +
   47.15 +           _WIN64    indicates 64 bit Windows
   47.16 +           _MSC_VER  indicates Microsoft C compiler
   47.17 +  */
   47.18 +
   47.19 +  INLINE unsigned char abstraction_dcas( volatile atom_t *destination, atom_t *exchange, atom_t *compare )
   47.20 +  {
   47.21 +    unsigned char
   47.22 +      cas_result;
   47.23 +
   47.24 +    assert( destination != NULL );
   47.25 +    assert( exchange != NULL );
   47.26 +    assert( compare != NULL );
   47.27 +
   47.28 +    cas_result = _InterlockedCompareExchange128( (volatile __int64 *) destination, (__int64) *(exchange+1), (__int64) *exchange, (__int64 *) compare );
   47.29 +
   47.30 +    return( cas_result );
   47.31 +  }
   47.32 +
   47.33 +#endif
   47.34 +
   47.35 +
   47.36 +
   47.37 +
   47.38 +
   47.39 +/****************************************************************************/
   47.40 +#if (!defined _WIN64 && defined _WIN32 && defined _MSC_VER)
   47.41 +
   47.42 +  /* TRD : 32 bit Windows (user-mode or kernel) on any CPU with the Microsoft C compiler
   47.43 +
   47.44 +           (!defined _WIN64 && defined _WIN32)  indicates 32 bit Windows
   47.45 +           _MSC_VER                             indicates Microsoft C compiler
   47.46 +  */
   47.47 +
   47.48 +  INLINE unsigned char abstraction_dcas( volatile atom_t *destination, atom_t *exchange, atom_t *compare )
   47.49 +  {
   47.50 +    __int64
   47.51 +      original_compare;
   47.52 +
   47.53 +    assert( destination != NULL );
   47.54 +    assert( exchange != NULL );
   47.55 +    assert( compare != NULL );
   47.56 +
   47.57 +    *(__int64 *) &original_compare = *(__int64 *) compare;
   47.58 +
   47.59 +    *(__int64 *) compare = _InterlockedCompareExchange64( (volatile __int64 *) destination, *(__int64 *) exchange, *(__int64 *) compare );
   47.60 +
   47.61 +    return( (unsigned char) (*(__int64 *) compare == *(__int64 *) &original_compare) );
   47.62 +  }
   47.63 +
   47.64 +#endif
   47.65 +
   47.66 +
   47.67 +
   47.68 +
   47.69 +
   47.70 +/****************************************************************************/
   47.71 +#if (defined __x86_64__ && __GNUC__ && !defined __pic__)
   47.72 +
   47.73 +  /* TRD : any OS on x64 with GCC for statically linked code
   47.74 +
   47.75 +           __x86_64__  indicates x64
   47.76 +           __GNUC__    indicates GCC
   47.77 +  */
   47.78 +
   47.79 +  INLINE unsigned char abstraction_dcas( volatile atom_t *destination, atom_t *exchange, atom_t *compare )
   47.80 +  {
   47.81 +    unsigned char
   47.82 +      cas_result;
   47.83 +
   47.84 +    assert( destination != NULL );
   47.85 +    assert( exchange != NULL );
   47.86 +    assert( compare != NULL );
   47.87 +
   47.88 +    __asm__ __volatile__
   47.89 +    (
   47.90 +      "lock;"           // make cmpxchg16b atomic
   47.91 +      "cmpxchg16b %0;"  // cmpxchg16b sets ZF on success
   47.92 +      "setz       %3;"  // if ZF set, set cas_result to 1
   47.93 +
   47.94 +      // output
   47.95 +      : "+m" (*(volatile atom_t (*)[2]) destination), "+a" (*compare), "+d" (*(compare+1)), "=q" (cas_result)
   47.96 +
   47.97 +      // input
   47.98 +      : "b" (*exchange), "c" (*(exchange+1))
   47.99 +
  47.100 +      // clobbered
  47.101 +      : "cc", "memory"
  47.102 +    );
  47.103 +
  47.104 +    return( cas_result );
  47.105 +  }
  47.106 +
  47.107 +#endif
  47.108 +
  47.109 +
  47.110 +
  47.111 +
  47.112 +
  47.113 +
  47.114 +/****************************************************************************/
  47.115 +#if (defined __i686__ && __GNUC__ && !defined __pic__)
  47.116 +
  47.117 +  /* TRD : any OS on x86 with GCC for statically linked code
  47.118 +
  47.119 +           __i686__  indicates x86
  47.120 +           __GNUC__  indicates GCC
  47.121 +  */
  47.122 +
  47.123 +  INLINE unsigned char abstraction_dcas( volatile atom_t *destination, atom_t *exchange, atom_t *compare )
  47.124 +  {
  47.125 +    unsigned char
  47.126 +      cas_result;
  47.127 +
  47.128 +    assert( destination != NULL );
  47.129 +    assert( exchange != NULL );
  47.130 +    assert( compare != NULL );
  47.131 +
  47.132 +    __asm__ __volatile__
  47.133 +    (
  47.134 +      "lock;"          // make cmpxchg8b atomic
  47.135 +      "cmpxchg8b %0;"  // cmpxchg8b sets ZF on success
  47.136 +      "setz      %3;"  // if ZF set, set cas_result to 1
  47.137 +
  47.138 +      // output
  47.139 +      : "+m" (*(volatile atom_t (*)[2]) destination), "+a" (*compare), "+d" (*(compare+1)), "=q" (cas_result)
  47.140 +
  47.141 +      // input
  47.142 +      : "b" (*exchange), "c" (*(exchange+1))
  47.143 +
  47.144 +      // clobbered
  47.145 +      : "cc", "memory"
  47.146 +    );
  47.147 +
  47.148 +    return( cas_result );
  47.149 +  }
  47.150 +
  47.151 +#endif
  47.152 +
  47.153 +
  47.154 +
  47.155 +
  47.156 +
  47.157 +/****************************************************************************/
  47.158 +#if (defined __x86_64__ && __GNUC__ && defined __pic__)
  47.159 +
  47.160 +  /* TRD : any OS on x64 with GCC for position independent code (e.g. a shared object)
  47.161 +
  47.162 +           __x86_64__  indicates x64
  47.163 +           __GNUC__    indicates GCC
  47.164 +  */
  47.165 +
  47.166 +  INLINE unsigned char abstraction_dcas( volatile atom_t *destination, atom_t *exchange, atom_t *compare )
  47.167 +  {
  47.168 +    unsigned char
  47.169 +      cas_result;
  47.170 +
  47.171 +    assert( destination != NULL );
  47.172 +    assert( exchange != NULL );
  47.173 +    assert( compare != NULL );
  47.174 +
  47.175 +    /* TRD : with a shared object, we cannot clobber RBX
  47.176 +             as such, we borrow RSI - we load half of the exchange value into it
  47.177 +             then swap it with RBX
  47.178 +             then do the compare-and-swap
  47.179 +             then swap the original value of RBX back from RSI
  47.180 +    */
  47.181 +
  47.182 +    __asm__ __volatile__
  47.183 +    (
  47.184 +      "xchg %%rsi, %%rbx;"  // swap RBI and RBX 
  47.185 +      "lock;"               // make cmpxchg16b atomic
  47.186 +      "cmpxchg16b %0;"      // cmpxchg16b sets ZF on success
  47.187 +      "setz       %3;"      // if ZF set, set cas_result to 1
  47.188 +      "xchg %%rbx, %%rsi;"  // re-swap RBI and RBX
  47.189 +
  47.190 +      // output
  47.191 +      : "+m" (*(volatile atom_t (*)[2]) destination), "+a" (*compare), "+d" (*(compare+1)), "=q" (cas_result)
  47.192 +
  47.193 +      // input
  47.194 +      : "S" (*exchange), "c" (*(exchange+1))
  47.195 +
  47.196 +      // clobbered
  47.197 +      : "cc", "memory"
  47.198 +    );
  47.199 +
  47.200 +    return( cas_result );
  47.201 +  }
  47.202 +
  47.203 +#endif
  47.204 +
  47.205 +
  47.206 +
  47.207 +
  47.208 +
  47.209 +
  47.210 +/****************************************************************************/
  47.211 +#if (defined __i686__ && __GNUC__ && defined __pic__)
  47.212 +
  47.213 +  /* TRD : any OS on x86 with GCC for position independent code (e.g. a shared object)
  47.214 +
  47.215 +           __i686__  indicates x86
  47.216 +           __GNUC__  indicates GCC
  47.217 +  */
  47.218 +
  47.219 +  INLINE unsigned char abstraction_dcas( volatile atom_t *destination, atom_t *exchange, atom_t *compare )
  47.220 +  {
  47.221 +    unsigned char
  47.222 +      cas_result;
  47.223 +
  47.224 +    assert( destination != NULL );
  47.225 +    assert( exchange != NULL );
  47.226 +    assert( compare != NULL );
  47.227 +
  47.228 +    /* TRD : with a shared object, we cannot clobber EBX
  47.229 +             as such, we borrow ESI - we load half of the exchange value into it
  47.230 +             then swap it with EBX
  47.231 +             then do the compare-and-swap
  47.232 +             then swap the original value of EBX back from ESI
  47.233 +    */
  47.234 +
  47.235 +    __asm__ __volatile__
  47.236 +    (
  47.237 +      "xchg %%esi, %%ebx;"  // swap EBI and EBX
  47.238 +      "lock;"               // make cmpxchg8b atomic
  47.239 +      "cmpxchg8b %0;"       // cmpxchg8b sets ZF on success
  47.240 +      "setz      %3;"       // if ZF set, set cas_result to 1
  47.241 +      "xchg %%ebx, %%esi;"  // re-swap EBI and EBX
  47.242 +
  47.243 +      // output
  47.244 +      : "+m" (*(volatile atom_t (*)[2]) destination), "+a" (*compare), "+d" (*(compare+1)), "=q" (cas_result)
  47.245 +
  47.246 +      // input
  47.247 +      : "S" (*exchange), "c" (*(exchange+1))
  47.248 +
  47.249 +      // clobbered
  47.250 +      : "cc", "memory"
  47.251 +    );
  47.252 +
  47.253 +    return( cas_result );
  47.254 +  }
  47.255 +
  47.256 +#endif
  47.257 +
  47.258 +
  47.259 +
  47.260 +
  47.261 +
  47.262 +/****************************************************************************/
  47.263 +#if (defined __arm__ && __GNUC__)
  47.264 +
  47.265 +  /* TRD : any OS on any ARM with GCC
  47.266 +
  47.267 +           Remember however we need to set into compare the original value of destination.
  47.268 +
  47.269 +           __arm__   indicates ARM
  47.270 +           __GNUC__  indicates GCC
  47.271 +  */
  47.272 +
  47.273 +  INLINE unsigned char abstraction_dcas( volatile atom_t *destination, atom_t *exchange, atom_t *compare )
  47.274 +  {
  47.275 +    atom_t
  47.276 +      *local_compare = compare,
  47.277 +      stored_flag = 1;
  47.278 +
  47.279 +    register atom_t
  47.280 +      local_exchange_a __asm("r2"),
  47.281 +      local_exchange_b __asm("r3"),
  47.282 +      local_compare_a __asm("r4"),
  47.283 +      local_compare_b __asm("r5"),
  47.284 +      original_destination_a __asm("r6"),
  47.285 +      original_destination_b __asm("r7");
  47.286 +
  47.287 +    assert( destination != NULL );
  47.288 +    assert( exchange != NULL );
  47.289 +    assert( compare != NULL );
  47.290 +
  47.291 +    /* TRD : some notes
  47.292 +
  47.293 +             the double word ldr and str instructions require contigous registers
  47.294 +             where the first register is an even number
  47.295 +
  47.296 +             honouring this requirement requires us to specifically specify
  47.297 +             the registers to use (which is why we're using register __asm("rN")
  47.298 +             in the declerations above
  47.299 +
  47.300 +             the arguments to the function occupy registers r0, r1 and r2
  47.301 +
  47.302 +             we can use up to and including r8, but r9 can have a frame pointer in it
  47.303 +
  47.304 +             so we make a copy of compare (freeing up r2, so we can use it for a double
  47.305 +             word load) but use destination (r0) and exchange (r1) directly
  47.306 +
  47.307 +             note LDRD and STRD became available in armv6k
  47.308 +
  47.309 +             apologies for the trickery with the mcr register variable - the code runs
  47.310 +             out of registers on armv6k
  47.311 +    */
  47.312 +
  47.313 +    __asm__ __volatile__
  47.314 +    (
  47.315 +      "  mov     %[stored_flag], #1;"                                                                // put 1 into stored_flag
  47.316 +      "  mov     %[local_exchange_a], #0;"                                                           // borrow local_exchange_a for mcr, to save a register
  47.317 +      "  mcr     p15, 0, %[local_exchange_a], c7, c10, 5;"                                           // memory barrier (ARM v6 compatible)
  47.318 +      "  ldrd    %[local_exchange_a], %[local_exchange_b], [%[exchange]];"                           // load exchange into local_exchange_a and local_exchange_b (which are r2 and r3, respectively)
  47.319 +      "  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)
  47.320 +      "atomic_dcas:;"
  47.321 +      "  ldrexd  %[original_destination_a], %[original_destination_b], [%[destination]];"            // load destination into original_destination_a and original_destination_b (which are r6 and r7, respectively)
  47.322 +      "  teq     %[original_destination_a], %[local_compare_a];"                                     // compare the first word of destination with the first word of compare
  47.323 +      "  teqeq   %[original_destination_b], %[local_compare_b];"                                     // if they're equal, compare the second word of destination with the second word of compare
  47.324 +      "  bne     exit;"                                                                              // if either word of destination does not match its respective word of compare, exit
  47.325 +      "  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)
  47.326 +      "  teq     %[stored_flag], #0;"                                                                // check if stored_flag is 0
  47.327 +      "  bne     atomic_dcas;"                                                                       // if not 0, retry (someone else touched *destination after we loaded but before we stored)
  47.328 +      "exit:;"
  47.329 +      "  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
  47.330 +      "  mov     %[local_exchange_a], #0;"                                                           // borrow local_exchange_a for mcr, to save a register
  47.331 +      "  mcr     p15, 0, %[local_exchange_a], c7, c10, 5;"                                           // memory barrier (ARM v6 compatible)
  47.332 +
  47.333 +      // output
  47.334 +      : "+m" (*(volatile atom_t (*)[2]) destination), "+m" (*(atom_t (*)[2]) local_compare),
  47.335 +        [stored_flag] "+&r" (stored_flag),
  47.336 +        [original_destination_a] "+&r" (original_destination_a), [original_destination_b] "+&r" (original_destination_b),
  47.337 +        [local_compare_a] "+&r" (local_compare_a), [local_compare_b] "+&r" (local_compare_b),
  47.338 +        [local_exchange_a] "+&r" (local_exchange_a), [local_exchange_b] "+&r" (local_exchange_b)
  47.339 +
  47.340 +      // input
  47.341 +      : "m" (*(atom_t (*)[2]) exchange),
  47.342 +        [destination] "r" (destination),
  47.343 +        [local_compare] "r" (local_compare),
  47.344 +        [exchange] "r" (exchange)
  47.345 +
  47.346 +      // clobbered
  47.347 +      : "cc", "memory"                                                                               // memory is clobbered because we issue a memory barrier
  47.348 +    );
  47.349 +
  47.350 +    /* TRD : stored_flag is set to 0 on store, 1 on fail
  47.351 +             we need to return 1 on success, 0 on fail
  47.352 +    */
  47.353 +
  47.354 +    return( (unsigned char) !stored_flag  );
  47.355 +  }
  47.356 +
  47.357 +#endif
  47.358 +
  47.359 +
    48.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    48.2 +++ b/liblfds.6/src/single_dir_for_windows_kernel/abstraction_increment.c	Sun Jan 31 21:28:42 2010 +1100
    48.3 @@ -0,0 +1,136 @@
    48.4 +#include "abstraction_internal.h"
    48.5 +
    48.6 +
    48.7 +
    48.8 +
    48.9 +
   48.10 +/****************************************************************************/
   48.11 +#if (defined _WIN64 && defined _MSC_VER)
   48.12 +
   48.13 +  /* TRD : 64 bit Windows (user-mode or kernel) on any CPU with the Microsoft C compiler
   48.14 +
   48.15 +           _WIN64    indicates 64 bit Windows
   48.16 +           _MSC_VER  indicates Microsoft C compiler
   48.17 +  */
   48.18 +
   48.19 +  INLINE atom_t abstraction_increment( atom_t *value )
   48.20 +  {
   48.21 +    __int64
   48.22 +      rv;
   48.23 +
   48.24 +    assert( value != NULL );
   48.25 +
   48.26 +    rv = _InterlockedIncrement64( (__int64 *) value );
   48.27 +
   48.28 +    return( (atom_t) rv );
   48.29 +  }
   48.30 +
   48.31 +#endif
   48.32 +
   48.33 +
   48.34 +
   48.35 +
   48.36 +
   48.37 +/****************************************************************************/
   48.38 +#if (!defined _WIN64 && defined _WIN32 && defined _MSC_VER)
   48.39 +
   48.40 +  /* TRD : 32 bit Windows (user-mode or kernel) on any CPU with the Microsoft C compiler
   48.41 +
   48.42 +           (!defined _WIN64 && defined _WIN32)  indicates 32 bit Windows
   48.43 +           _MSC_VER                             indicates Microsoft C compiler
   48.44 +  */
   48.45 +
   48.46 +  INLINE atom_t abstraction_increment( atom_t *value )
   48.47 +  {
   48.48 +    long int
   48.49 +      rv;
   48.50 +
   48.51 +    assert( value != NULL );
   48.52 +
   48.53 +    rv = _InterlockedIncrement( (long int *) value );
   48.54 +
   48.55 +    return( (atom_t) rv );
   48.56 +  }
   48.57 +
   48.58 +#endif
   48.59 +
   48.60 +
   48.61 +
   48.62 +
   48.63 +
   48.64 +/****************************************************************************/
   48.65 +#if (!defined __arm__ && __GNUC__ >= 4 && __GNUC_MINOR__ >= 1 && __GNUC_PATCHLEVEL__ >= 0)
   48.66 +
   48.67 +  /* TRD : any OS on any CPU with GCC 4.1.0 or better
   48.68 +
   48.69 +           GCC 4.1.0 introduced the __sync_*() atomic intrinsics
   48.70 +
   48.71 +           __GNUC__ / __GNUC_MINOR__ / __GNUC_PATCHLEVEL__  indicates GCC and which version
   48.72 +  */
   48.73 +
   48.74 +  INLINE atom_t abstraction_increment( atom_t *value )
   48.75 +  {
   48.76 +    atom_t
   48.77 +      rv;
   48.78 +
   48.79 +    assert( value != NULL );
   48.80 +
   48.81 +    // TRD : no need for casting here, GCC has a __sync_add_and_fetch() for all native types
   48.82 +
   48.83 +    rv = __sync_add_and_fetch( value, 1 );
   48.84 +
   48.85 +    return( rv );
   48.86 +  }
   48.87 +
   48.88 +#endif
   48.89 +
   48.90 +
   48.91 +
   48.92 +
   48.93 +
   48.94 +/****************************************************************************/
   48.95 +#if (defined __arm__ && __GNUC__ >= 4)
   48.96 +
   48.97 +  /* TRD : any OS on any CPU with GCC 4.1.0 or better
   48.98 +
   48.99 +           GCC 4.1.0 introduced the __sync_*() atomic intrinsics
  48.100 +
  48.101 +           __arm__   indicates ARM
  48.102 +           __GNUC__  indicates GCC
  48.103 +  */
  48.104 +
  48.105 +  INLINE atom_t abstraction_increment( atom_t *value )
  48.106 +  {
  48.107 +    atom_t
  48.108 +      stored_flag = 0,
  48.109 +      new_value = 0;
  48.110 +
  48.111 +    assert( value != NULL );
  48.112 +
  48.113 +    __asm__ __volatile__
  48.114 +    (
  48.115 +      "  mov    %[stored_flag], #1;"                        // move 1 into stored_flag
  48.116 +      "  mcr    p15, 0, %[zero], c7, c10, 5;"               // memory barrier (ARM v6 compatible)
  48.117 +      "atomic_add:;"
  48.118 +      "  ldrex  %[new_value], [%[value]];  "                // load *value into new_value
  48.119 +      "  add    %[new_value], #1;"                          // add 1 to new_value
  48.120 +      "  strex  %[stored_flag], %[new_value], [%[value]];"  // try to store new_value into *value (on success, strex puts 0 into stored_flag)
  48.121 +      "  teq    %[stored_flag], #0;"                        // check if stored_flag is 0
  48.122 +      "  bne    atomic_add;"                                // if not 0, retry (someone else touched *value after we loaded but before we stored)
  48.123 +      "  mcr    p15, 0, %[zero], c7, c10, 5;"               // memory barrier (ARM v6 compatible)
  48.124 +
  48.125 +      // output
  48.126 +      : "+m" (*value), [new_value] "+&r" (new_value), [stored_flag] "+&r" (stored_flag)
  48.127 +
  48.128 +      // input
  48.129 +      : [value] "r" (value), [zero] "r" (0)
  48.130 +
  48.131 +      // clobbered
  48.132 +      : "cc", "memory"                                      // memory is clobbered because we issue a memory barrier
  48.133 +    );
  48.134 +
  48.135 +    return( new_value );
  48.136 +  }
  48.137 +
  48.138 +#endif
  48.139 +
    49.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    49.2 +++ b/liblfds.6/src/single_dir_for_windows_kernel/abstraction_internal.h	Sun Jan 31 21:28:42 2010 +1100
    49.3 @@ -0,0 +1,5 @@
    49.4 +/***** the library wide include file *****/
    49.5 +#include "liblfds_internal.h"
    49.6 +
    49.7 +/***** private prototypes *****/
    49.8 +
    50.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    50.2 +++ b/liblfds.6/src/single_dir_for_windows_kernel/freelist_delete.c	Sun Jan 31 21:28:42 2010 +1100
    50.3 @@ -0,0 +1,35 @@
    50.4 +#include "freelist_internal.h"
    50.5 +
    50.6 +
    50.7 +
    50.8 +
    50.9 +
   50.10 +/****************************************************************************/
   50.11 +void freelist_delete( struct freelist_state *fs, void (*user_data_delete_function)(void *user_data, void *user_state), void *user_state )
   50.12 +{
   50.13 +  struct freelist_element
   50.14 +    *fe;
   50.15 +
   50.16 +  void
   50.17 +    *user_data;
   50.18 +
   50.19 +  assert( fs != NULL );
   50.20 +  // TRD : user_data_delete_function can be NULL
   50.21 +  // TRD : user_state can be NULL
   50.22 +
   50.23 +  while( freelist_pop(fs, &fe) )
   50.24 +  {
   50.25 +    if( user_data_delete_function != NULL )
   50.26 +    {
   50.27 +      freelist_get_user_data_from_element( fe, &user_data );
   50.28 +      user_data_delete_function( user_data, user_state );
   50.29 +    }
   50.30 +
   50.31 +    abstraction_aligned_free( fe );
   50.32 +  }
   50.33 +
   50.34 +  abstraction_aligned_free( fs );
   50.35 +
   50.36 +  return;
   50.37 +}
   50.38 +
    51.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    51.2 +++ b/liblfds.6/src/single_dir_for_windows_kernel/freelist_get_and_set.c	Sun Jan 31 21:28:42 2010 +1100
    51.3 @@ -0,0 +1,33 @@
    51.4 +#include "freelist_internal.h"
    51.5 +
    51.6 +
    51.7 +
    51.8 +
    51.9 +
   51.10 +/****************************************************************************/
   51.11 +void *freelist_get_user_data_from_element( struct freelist_element *fe, void **user_data )
   51.12 +{
   51.13 +  assert( fe != NULL );
   51.14 +  // TRD : user_data can be NULL
   51.15 +
   51.16 +  if( user_data != NULL )
   51.17 +    *user_data = fe->user_data;
   51.18 +
   51.19 +  return( fe->user_data );
   51.20 +}
   51.21 +
   51.22 +
   51.23 +
   51.24 +
   51.25 +
   51.26 +/****************************************************************************/
   51.27 +void freelist_set_user_data_in_element( struct freelist_element *fe, void *user_data )
   51.28 +{
   51.29 +  assert( fe != NULL );
   51.30 +  // TRD : user_data can be NULL
   51.31 +
   51.32 +  fe->user_data = user_data;
   51.33 +
   51.34 +  return;
   51.35 +}
   51.36 +
    52.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    52.2 +++ b/liblfds.6/src/single_dir_for_windows_kernel/freelist_internal.h	Sun Jan 31 21:28:42 2010 +1100
    52.3 @@ -0,0 +1,42 @@
    52.4 +/***** the library wide include file *****/
    52.5 +#include "liblfds_internal.h"
    52.6 +
    52.7 +/***** defines *****/
    52.8 +#define FREELIST_POINTER 0
    52.9 +#define FREELIST_COUNTER 1
   52.10 +#define FREELIST_PAC_SIZE 2
   52.11 +
   52.12 +/***** structures *****/
   52.13 +#pragma pack( push, ALIGN_DOUBLE_POINTER )
   52.14 +
   52.15 +struct freelist_state
   52.16 +{
   52.17 +  struct freelist_element
   52.18 +    *volatile top[FREELIST_PAC_SIZE];
   52.19 +
   52.20 +  int
   52.21 +    (*user_data_init_function)( void **user_data, void *user_state );
   52.22 +
   52.23 +  void
   52.24 +    *user_state;
   52.25 +
   52.26 +  atom_t
   52.27 +    aba_counter,
   52.28 +    element_count;
   52.29 +};
   52.30 +
   52.31 +struct freelist_element
   52.32 +{
   52.33 +  struct freelist_element
   52.34 +    *next[FREELIST_PAC_SIZE];
   52.35 +
   52.36 +  void
   52.37 +    *user_data;
   52.38 +};
   52.39 +
   52.40 +#pragma pack( pop )
   52.41 +
   52.42 +/***** private prototypes *****/
   52.43 +atom_t freelist_internal_new_element( struct freelist_state *fs, struct freelist_element **fe );
   52.44 +void freelist_internal_validate( struct freelist_state *fs, struct validation_info *vi, enum data_structure_validity *freelist_validity );
   52.45 +
    53.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    53.2 +++ b/liblfds.6/src/single_dir_for_windows_kernel/freelist_new.c	Sun Jan 31 21:28:42 2010 +1100
    53.3 @@ -0,0 +1,123 @@
    53.4 +#include "freelist_internal.h"
    53.5 +
    53.6 +
    53.7 +
    53.8 +
    53.9 +
   53.10 +/****************************************************************************/
   53.11 +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 )
   53.12 +{
   53.13 +  int
   53.14 +    rv = 0;
   53.15 +
   53.16 +  atom_t
   53.17 +    element_count;
   53.18 +
   53.19 +  assert( fs != NULL );
   53.20 +  // TRD : number_elements can be any value in its range
   53.21 +  // TRD : user_data_init_function can be NULL
   53.22 +
   53.23 +  *fs = (struct freelist_state *) abstraction_aligned_malloc( sizeof(struct freelist_state), ALIGN_DOUBLE_POINTER );
   53.24 +
   53.25 +  if( (*fs) != NULL )
   53.26 +  {
   53.27 +    (*fs)->top[FREELIST_POINTER] = NULL;
   53.28 +    (*fs)->top[FREELIST_COUNTER] = 0;
   53.29 +    (*fs)->user_data_init_function = user_data_init_function;
   53.30 +    (*fs)->user_state = user_state;
   53.31 +    (*fs)->aba_counter = 0;
   53.32 +    (*fs)->element_count = 0;
   53.33 +
   53.34 +    element_count = freelist_new_elements( *fs, number_elements );
   53.35 +
   53.36 +    if( element_count == number_elements )
   53.37 +      rv = 1;
   53.38 +
   53.39 +    if( element_count != number_elements )
   53.40 +    {
   53.41 +      abstraction_aligned_free( (*fs) );
   53.42 +      *fs = NULL;
   53.43 +    }
   53.44 +  }
   53.45 +
   53.46 +  return( rv );
   53.47 +}
   53.48 +
   53.49 +
   53.50 +
   53.51 +
   53.52 +
   53.53 +/****************************************************************************/
   53.54 +atom_t freelist_new_elements( struct freelist_state *fs, atom_t number_elements )
   53.55 +{
   53.56 +  struct freelist_element
   53.57 +    *fe;
   53.58 +
   53.59 +  atom_t
   53.60 +    loop,
   53.61 +    count = 0;
   53.62 +
   53.63 +  assert( fs != NULL );
   53.64 +  // TRD : number_elements can be any value in its range
   53.65 +  // TRD : user_data_init_function can be NULL
   53.66 +
   53.67 +  for( loop = 0 ; loop < number_elements ; loop++ )
   53.68 +    if( freelist_internal_new_element(fs, &fe) )
   53.69 +    {
   53.70 +      freelist_push( fs, fe );
   53.71 +      count++;
   53.72 +    }
   53.73 +
   53.74 +  return( count );
   53.75 +}
   53.76 +
   53.77 +
   53.78 +
   53.79 +
   53.80 +
   53.81 +/****************************************************************************/
   53.82 +atom_t freelist_internal_new_element( struct freelist_state *fs, struct freelist_element **fe )
   53.83 +{
   53.84 +  atom_t
   53.85 +    rv = 0;
   53.86 +
   53.87 +  assert( fs != NULL );
   53.88 +  assert( fe != NULL );
   53.89 +
   53.90 +  /* TRD : basically, does what you'd expect;
   53.91 +
   53.92 +           allocates an element
   53.93 +           calls the user init function
   53.94 +           if anything fails, cleans up,
   53.95 +           sets *fe to NULL
   53.96 +           and returns 0
   53.97 +  */
   53.98 +
   53.99 +  *fe = (struct freelist_element *) abstraction_aligned_malloc( sizeof(struct freelist_element), ALIGN_DOUBLE_POINTER );
  53.100 +
  53.101 +  if( *fe != NULL )
  53.102 +  {
  53.103 +    if( fs->user_data_init_function == NULL )
  53.104 +    {
  53.105 +      (*fe)->user_data = NULL;
  53.106 +      rv = 1;
  53.107 +    }
  53.108 +
  53.109 +    if( fs->user_data_init_function != NULL )
  53.110 +    {
  53.111 +      rv = fs->user_data_init_function( &(*fe)->user_data, fs->user_state );
  53.112 +
  53.113 +      if( rv == 0 )
  53.114 +      {
  53.115 +        abstraction_aligned_free( *fe );
  53.116 +        *fe = NULL;
  53.117 +      }
  53.118 +    }
  53.119 +  }
  53.120 +
  53.121 +  if( rv == 1 )
  53.122 +    abstraction_increment( (atom_t *) &fs->element_count );
  53.123 +
  53.124 +  return( rv );
  53.125 +}
  53.126 +
    54.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    54.2 +++ b/liblfds.6/src/single_dir_for_windows_kernel/freelist_pop_push.c	Sun Jan 31 21:28:42 2010 +1100
    54.3 @@ -0,0 +1,88 @@
    54.4 +#include "freelist_internal.h"
    54.5 +
    54.6 +
    54.7 +
    54.8 +
    54.9 +
   54.10 +/****************************************************************************/
   54.11 +struct freelist_element *freelist_pop( struct freelist_state *fs, struct freelist_element **fe )
   54.12 +{
   54.13 +  ALIGN(ALIGN_DOUBLE_POINTER) struct freelist_element
   54.14 +    *fe_local[FREELIST_PAC_SIZE];
   54.15 +
   54.16 +  assert( fs != NULL );
   54.17 +  assert( fe != NULL );
   54.18 +
   54.19 +  fe_local[FREELIST_COUNTER] = fs->top[FREELIST_COUNTER];
   54.20 +  fe_local[FREELIST_POINTER] = fs->top[FREELIST_POINTER];
   54.21 +
   54.22 +  /* TRD : note that abstraction_dcas loads the original value of the destination (fs->top) into the compare (fe_local)
   54.23 +           (this happens of course after the CAS itself has occurred inside abstraction_dcas)
   54.24 +  */
   54.25 +
   54.26 +  do
   54.27 +  {
   54.28 +    if( fe_local[FREELIST_POINTER] == NULL )
   54.29 +    {
   54.30 +      *fe = NULL;
   54.31 +      return( *fe );
   54.32 +    }
   54.33 +  }
   54.34 +  while( 0 == abstraction_dcas((volatile atom_t *) fs->top, (atom_t *) fe_local[FREELIST_POINTER]->next, (atom_t *) fe_local) );
   54.35 +
   54.36 +  *fe = (struct freelist_element *) fe_local[FREELIST_POINTER];
   54.37 +
   54.38 +  return( *fe );
   54.39 +}
   54.40 +
   54.41 +
   54.42 +
   54.43 +
   54.44 +
   54.45 +/****************************************************************************/
   54.46 +struct freelist_element *freelist_guaranteed_pop( struct freelist_state *fs, struct freelist_element **fe )
   54.47 +{
   54.48 +  assert( fs != NULL );
   54.49 +  assert( fe != NULL );
   54.50 +
   54.51 +  freelist_internal_new_element( fs, fe );
   54.52 +
   54.53 +  return( *fe );
   54.54 +}
   54.55 +
   54.56 +
   54.57 +
   54.58 +
   54.59 +
   54.60 +/****************************************************************************/
   54.61 +void freelist_push( struct freelist_state *fs, struct freelist_element *fe )
   54.62 +{
   54.63 +  ALIGN(ALIGN_DOUBLE_POINTER) struct freelist_element
   54.64 +    *fe_local[FREELIST_PAC_SIZE],
   54.65 +    *original_fe_next[FREELIST_PAC_SIZE];
   54.66 +
   54.67 +  assert( fs != NULL );
   54.68 +  assert( fe != NULL );
   54.69 +
   54.70 +  fe_local[FREELIST_POINTER] = fe;
   54.71 +  fe_local[FREELIST_COUNTER] = (struct freelist_element *) abstraction_increment( (atom_t *) &fs->aba_counter );
   54.72 +
   54.73 +  original_fe_next[FREELIST_POINTER] = fs->top[FREELIST_POINTER];
   54.74 +  original_fe_next[FREELIST_COUNTER] = fs->top[FREELIST_COUNTER];
   54.75 +
   54.76 +  /* TRD : note that abstraction_dcas loads the original value of the destination (fs->top) into the compare (original_fe_next)
   54.77 +           (this happens of course after the CAS itself has occurred inside abstraction_dcas)
   54.78 +           this then causes us in our loop, should we repeat it, to update fe_local->next to a more
   54.79 +           up-to-date version of the head of the freelist
   54.80 +  */
   54.81 +
   54.82 +  do
   54.83 +  {
   54.84 +    fe_local[FREELIST_POINTER]->next[FREELIST_POINTER] = original_fe_next[FREELIST_POINTER];
   54.85 +    fe_local[FREELIST_POINTER]->next[FREELIST_COUNTER] = original_fe_next[FREELIST_COUNTER];
   54.86 +  }
   54.87 +  while( 0 == abstraction_dcas((volatile atom_t *) fs->top, (atom_t *) fe_local, (atom_t *) original_fe_next) );
   54.88 +
   54.89 +  return;
   54.90 +}
   54.91 +
    55.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    55.2 +++ b/liblfds.6/src/single_dir_for_windows_kernel/freelist_query.c	Sun Jan 31 21:28:42 2010 +1100
    55.3 @@ -0,0 +1,113 @@
    55.4 +#include "freelist_internal.h"
    55.5 +
    55.6 +
    55.7 +
    55.8 +
    55.9 +
   55.10 +/****************************************************************************/
   55.11 +void freelist_query( struct freelist_state *fs, enum freelist_query_type query_type, void *query_input, void *query_output )
   55.12 +{
   55.13 +  assert( fs != NULL );
   55.14 +  // TRD : query type can be any value in its range
   55.15 +  // TRD : query_input can be NULL in some cases
   55.16 +  assert( query_output != NULL );
   55.17 +
   55.18 +  switch( query_type )
   55.19 +  {
   55.20 +    case FREELIST_QUERY_ELEMENT_COUNT:
   55.21 +      assert( query_input == NULL );
   55.22 +
   55.23 +      *(atom_t *) query_output = fs->element_count;
   55.24 +    break;
   55.25 +
   55.26 +    case FREELIST_QUERY_VALIDATE:
   55.27 +      // TRD : query_input can be NULL
   55.28 +
   55.29 +      freelist_internal_validate( fs, (struct validation_info *) query_input, (enum data_structure_validity *) query_output );
   55.30 +    break;
   55.31 +  }
   55.32 +
   55.33 +  return;
   55.34 +}
   55.35 +
   55.36 +
   55.37 +
   55.38 +
   55.39 +
   55.40 +/****************************************************************************/
   55.41 +void freelist_internal_validate( struct freelist_state *fs, struct validation_info *vi, enum data_structure_validity *freelist_validity )
   55.42 +{
   55.43 +  struct freelist_element
   55.44 +    *fe,
   55.45 +    *fe_slow,
   55.46 +    *fe_fast;
   55.47 +
   55.48 +  atom_t
   55.49 +    element_count = 0;
   55.50 +
   55.51 +  assert( fs != NULL );
   55.52 +  // TRD : vi can be NULL
   55.53 +  assert( freelist_validity != NULL );
   55.54 +
   55.55 +  *freelist_validity = VALIDITY_VALID;
   55.56 +
   55.57 +  fe_slow = fe_fast = (struct freelist_element *) fs->top[FREELIST_POINTER];
   55.58 +
   55.59 +  /* TRD : first, check for a loop
   55.60 +           we have two pointers
   55.61 +           both of which start at the top of the freelist
   55.62 +           we enter a loop
   55.63 +           and on each iteration
   55.64 +           we advance one pointer by one element
   55.65 +           and the other by two
   55.66 +
   55.67 +           we exit the loop when both pointers are NULL
   55.68 +           (have reached the end of the freelist)
   55.69 +
   55.70 +           or
   55.71 +
   55.72 +           if we fast pointer 'sees' the slow pointer
   55.73 +           which means we have a loop
   55.74 +  */
   55.75 +
   55.76 +  if( fe_slow != NULL )
   55.77 +    do
   55.78 +    {
   55.79 +      fe_slow = fe_slow->next[FREELIST_POINTER];
   55.80 +
   55.81 +      if( fe_fast != NULL )
   55.82 +        fe_fast = fe_fast->next[FREELIST_POINTER];
   55.83 +
   55.84 +      if( fe_fast != NULL )
   55.85 +        fe_fast = fe_fast->next[FREELIST_POINTER];
   55.86 +    }
   55.87 +    while( fe_slow != NULL and fe_fast != fe_slow );
   55.88 +
   55.89 +  if( fe_fast != NULL and fe_slow != NULL and fe_fast == fe_slow )
   55.90 +    *freelist_validity = VALIDITY_INVALID_LOOP;
   55.91 +
   55.92 +  /* TRD : now check for expected number of elements
   55.93 +           vi can be NULL, in which case we do not check
   55.94 +           we know we don't have a loop from our earlier check
   55.95 +  */
   55.96 +
   55.97 +  if( *freelist_validity == VALIDITY_VALID and vi != NULL )
   55.98 +  {
   55.99 +    fe = (struct freelist_element *) fs->top[FREELIST_POINTER];
  55.100 +
  55.101 +    while( fe != NULL )
  55.102 +    {
  55.103 +      element_count++;
  55.104 +      fe = (struct freelist_element *) fe->next[FREELIST_POINTER];
  55.105 +    }
  55.106 +
  55.107 +    if( element_count < vi->min_elements )
  55.108 +      *freelist_validity = VALIDITY_INVALID_MISSING_ELEMENTS;
  55.109 +
  55.110 +    if( element_count > vi->max_elements )
  55.111 +      *freelist_validity = VALIDITY_INVALID_ADDITIONAL_ELEMENTS;
  55.112 +  }
  55.113 +
  55.114 +  return;
  55.115 +}
  55.116 +
    56.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    56.2 +++ b/liblfds.6/src/single_dir_for_windows_kernel/objchk_wnet_x86/i386/_objects.mac	Sun Jan 31 21:28:42 2010 +1100
    56.3 @@ -0,0 +1,41 @@
    56.4 +
    56.5 +
    56.6 +386_OBJECTS=\
    56.7 + $(OBJ_PATH)\$O\abstraction_aligned_free.obj \
    56.8 + $(OBJ_PATH)\$O\abstraction_aligned_malloc.obj \
    56.9 + $(OBJ_PATH)\$O\abstraction_cas.obj \
   56.10 + $(OBJ_PATH)\$O\abstraction_dcas.obj \
   56.11 + $(OBJ_PATH)\$O\abstraction_increment.obj \
   56.12 + $(OBJ_PATH)\$O\freelist_delete.obj \
   56.13 + $(OBJ_PATH)\$O\freelist_get_and_set.obj \
   56.14 + $(OBJ_PATH)\$O\freelist_new.obj \
   56.15 + $(OBJ_PATH)\$O\freelist_pop_push.obj \
   56.16 + $(OBJ_PATH)\$O\freelist_query.obj \
   56.17 + $(OBJ_PATH)\$O\queue_delete.obj \
   56.18 + $(OBJ_PATH)\$O\queue_new.obj \
   56.19 + $(OBJ_PATH)\$O\queue_query.obj \
   56.20 + $(OBJ_PATH)\$O\queue_queue.obj \
   56.21 + $(OBJ_PATH)\$O\ringbuffer_delete.obj \
   56.22 + $(OBJ_PATH)\$O\ringbuffer_get_and_put.obj \
   56.23 + $(OBJ_PATH)\$O\ringbuffer_new.obj \
   56.24 + $(OBJ_PATH)\$O\ringbuffer_query.obj \
   56.25 + $(OBJ_PATH)\$O\slist_delete.obj \
   56.26 + $(OBJ_PATH)\$O\slist_get_and_set.obj \
   56.27 + $(OBJ_PATH)\$O\slist_link.obj \
   56.28 + $(OBJ_PATH)\$O\slist_new.obj \
   56.29 + $(OBJ_PATH)\$O\stack_delete.obj \
   56.30 + $(OBJ_PATH)\$O\stack_new.obj \
   56.31 + $(OBJ_PATH)\$O\stack_push_pop.obj \
   56.32 + $(OBJ_PATH)\$O\stack_query.obj \
   56.33 +
   56.34 +
   56.35 +
   56.36 +
   56.37 +
   56.38 +# lowercased
   56.39 +BASEDIR=c:\winddk\7600.16385.0
   56.40 +OBJECT_ROOT=c:\winddk\7600.16385.0
   56.41 +MAKEDIR_LOWERCASE=c:\projects\win-pvdrivers.hg\liblfds.6\src\single_dir_for_windows_kernel
   56.42 +OBJ_PATH=c:\projects\win-pvdrivers.hg\liblfds.6\src\single_dir_for_windows_kernel
   56.43 +CONCURRENT_MIDL=0
   56.44 +CONCURRENT_MANIFEST_BUILD=0
    57.1 Binary file liblfds.6/src/single_dir_for_windows_kernel/objchk_wnet_x86/i386/abstraction_aligned_free.obj has changed
    58.1 Binary file liblfds.6/src/single_dir_for_windows_kernel/objchk_wnet_x86/i386/abstraction_aligned_malloc.obj has changed
    59.1 Binary file liblfds.6/src/single_dir_for_windows_kernel/objchk_wnet_x86/i386/abstraction_cas.obj has changed
    60.1 Binary file liblfds.6/src/single_dir_for_windows_kernel/objchk_wnet_x86/i386/abstraction_dcas.obj has changed
    61.1 Binary file liblfds.6/src/single_dir_for_windows_kernel/objchk_wnet_x86/i386/abstraction_increment.obj has changed
    62.1 Binary file liblfds.6/src/single_dir_for_windows_kernel/objchk_wnet_x86/i386/freelist_delete.obj has changed
    63.1 Binary file liblfds.6/src/single_dir_for_windows_kernel/objchk_wnet_x86/i386/freelist_get_and_set.obj has changed
    64.1 Binary file liblfds.6/src/single_dir_for_windows_kernel/objchk_wnet_x86/i386/freelist_new.obj has changed
    65.1 Binary file liblfds.6/src/single_dir_for_windows_kernel/objchk_wnet_x86/i386/freelist_pop_push.obj has changed
    66.1 Binary file liblfds.6/src/single_dir_for_windows_kernel/objchk_wnet_x86/i386/freelist_query.obj has changed
    67.1 Binary file liblfds.6/src/single_dir_for_windows_kernel/objchk_wnet_x86/i386/queue_delete.obj has changed
    68.1 Binary file liblfds.6/src/single_dir_for_windows_kernel/objchk_wnet_x86/i386/queue_new.obj has changed
    69.1 Binary file liblfds.6/src/single_dir_for_windows_kernel/objchk_wnet_x86/i386/queue_query.obj has changed
    70.1 Binary file liblfds.6/src/single_dir_for_windows_kernel/objchk_wnet_x86/i386/queue_queue.obj has changed
    71.1 Binary file liblfds.6/src/single_dir_for_windows_kernel/objchk_wnet_x86/i386/ringbuffer_delete.obj has changed
    72.1 Binary file liblfds.6/src/single_dir_for_windows_kernel/objchk_wnet_x86/i386/ringbuffer_get_and_put.obj has changed
    73.1 Binary file liblfds.6/src/single_dir_for_windows_kernel/objchk_wnet_x86/i386/ringbuffer_new.obj has changed
    74.1 Binary file liblfds.6/src/single_dir_for_windows_kernel/objchk_wnet_x86/i386/ringbuffer_query.obj has changed
    75.1 Binary file liblfds.6/src/single_dir_for_windows_kernel/objchk_wnet_x86/i386/slist_delete.obj has changed
    76.1 Binary file liblfds.6/src/single_dir_for_windows_kernel/objchk_wnet_x86/i386/slist_get_and_set.obj has changed
    77.1 Binary file liblfds.6/src/single_dir_for_windows_kernel/objchk_wnet_x86/i386/slist_link.obj has changed
    78.1 Binary file liblfds.6/src/single_dir_for_windows_kernel/objchk_wnet_x86/i386/slist_new.obj has changed
    79.1 Binary file liblfds.6/src/single_dir_for_windows_kernel/objchk_wnet_x86/i386/stack_delete.obj has changed
    80.1 Binary file liblfds.6/src/single_dir_for_windows_kernel/objchk_wnet_x86/i386/stack_new.obj has changed
    81.1 Binary file liblfds.6/src/single_dir_for_windows_kernel/objchk_wnet_x86/i386/stack_push_pop.obj has changed
    82.1 Binary file liblfds.6/src/single_dir_for_windows_kernel/objchk_wnet_x86/i386/stack_query.obj has changed
    83.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    83.2 +++ b/liblfds.6/src/single_dir_for_windows_kernel/queue_delete.c	Sun Jan 31 21:28:42 2010 +1100
    83.3 @@ -0,0 +1,55 @@
    83.4 +#include "queue_internal.h"
    83.5 +
    83.6 +
    83.7 +
    83.8 +
    83.9 +
   83.10 +/****************************************************************************/
   83.11 +void queue_delete( struct queue_state *qs, void (*user_data_delete_function)(void *user_data, void *user_state), void *user_state )
   83.12 +{
   83.13 +  void
   83.14 +    *user_data;
   83.15 +
   83.16 +  assert( qs != NULL );
   83.17 +  // TRD : user_data_delete_function can be NULL
   83.18 +  // TRD : user_state can be NULL
   83.19 +
   83.20 +  while( queue_dequeue(qs, &user_data) )
   83.21 +    if( user_data_delete_function != NULL )
   83.22 +      user_data_delete_function( user_data, user_state );
   83.23 +
   83.24 +  /* TRD : fully dequeuing will leave us
   83.25 +           with a single dummy element
   83.26 +           which both qs->enqueue and qs->dequeue point at
   83.27 +           we push this back onto the freelist
   83.28 +           before we delete the freelist
   83.29 +  */
   83.30 +
   83.31 +  freelist_push( qs->fs, qs->enqueue[QUEUE_POINTER]->fe );
   83.32 +
   83.33 +  freelist_delete( qs->fs, queue_internal_freelist_delete_function, NULL );
   83.34 +
   83.35 +  abstraction_aligned_free( qs );
   83.36 +
   83.37 +  return;
   83.38 +}
   83.39 +
   83.40 +
   83.41 +
   83.42 +
   83.43 +
   83.44 +/****************************************************************************/
   83.45 +#pragma warning( disable : 4100 )
   83.46 +
   83.47 +void queue_internal_freelist_delete_function( void *user_data, void *user_state )
   83.48 +{
   83.49 +  assert( user_data != NULL );
   83.50 +  assert( user_state == NULL );
   83.51 +
   83.52 +  abstraction_aligned_free( user_data );
   83.53 +
   83.54 +  return;
   83.55 +}
   83.56 +
   83.57 +#pragma warning( default : 4100 )
   83.58 +
    84.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    84.2 +++ b/liblfds.6/src/single_dir_for_windows_kernel/queue_internal.h	Sun Jan 31 21:28:42 2010 +1100
    84.3 @@ -0,0 +1,60 @@
    84.4 +/***** the library wide include file *****/
    84.5 +#include "liblfds_internal.h"
    84.6 +
    84.7 +/***** pragmas *****/
    84.8 +
    84.9 +/***** defines *****/
   84.10 +#define QUEUE_STATE_UNKNOWN               -1
   84.11 +#define QUEUE_STATE_EMPTY                  0
   84.12 +#define QUEUE_STATE_ENQUEUE_OUT_OF_PLACE   1
   84.13 +#define QUEUE_STATE_ATTEMPT_DEQUEUE        2
   84.14 +
   84.15 +#define QUEUE_POINTER 0
   84.16 +#define QUEUE_COUNTER 1
   84.17 +#define QUEUE_PAC_SIZE 2
   84.18 +
   84.19 +/***** structures *****/
   84.20 +#pragma pack( push, ALIGN_DOUBLE_POINTER )
   84.21 +
   84.22 +struct queue_state
   84.23 +{
   84.24 +  struct queue_element
   84.25 +    *volatile enqueue[QUEUE_PAC_SIZE],
   84.26 +    *volatile dequeue[QUEUE_PAC_SIZE];
   84.27 +
   84.28 +  atom_t
   84.29 +    aba_counter;
   84.30 +
   84.31 +  struct freelist_state
   84.32 +    *fs;
   84.33 +};
   84.34 +
   84.35 +struct queue_element
   84.36 +{
   84.37 +  // TRD : next in a queue requires volatile as it is target of CAS
   84.38 +  struct queue_element
   84.39 +    *volatile next[QUEUE_PAC_SIZE];
   84.40 +
   84.41 +  struct freelist_element
   84.42 +    *fe;
   84.43 +
   84.44 +  void
   84.45 +    *user_data;
   84.46 +};
   84.47 +
   84.48 +#pragma pack( pop )
   84.49 +
   84.50 +/***** externs *****/
   84.51 +
   84.52 +/***** private prototypes *****/
   84.53 +int queue_internal_freelist_init_function( void **user_data, void *user_state );
   84.54 +void queue_internal_freelist_delete_function( void *user_data, void *user_state );
   84.55 +
   84.56 +void queue_internal_new_element_from_freelist( struct queue_state *qs, struct queue_element *qe[QUEUE_PAC_SIZE], void *user_data );
   84.57 +void queue_internal_guaranteed_new_element_from_freelist( struct queue_state *qs, struct queue_element * qe[QUEUE_PAC_SIZE], void *user_data );
   84.58 +void queue_internal_init_element( struct queue_state *qs, struct queue_element *qe[QUEUE_PAC_SIZE], struct freelist_element *fe, void *user_data );
   84.59 +
   84.60 +void queue_internal_queue( struct queue_state *qs, struct queue_element *qe[QUEUE_PAC_SIZE] );
   84.61 +
   84.62 +void queue_internal_validate( struct queue_state *qs, struct validation_info *vi, enum data_structure_validity *queue_validity, enum data_structure_validity *freelist_validity );
   84.63 +
    85.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    85.2 +++ b/liblfds.6/src/single_dir_for_windows_kernel/queue_new.c	Sun Jan 31 21:28:42 2010 +1100
    85.3 @@ -0,0 +1,140 @@
    85.4 +#include "queue_internal.h"
    85.5 +
    85.6 +
    85.7 +
    85.8 +
    85.9 +
   85.10 +/****************************************************************************/
   85.11 +int queue_new( struct queue_state **qs, atom_t number_elements )
   85.12 +{
   85.13 +  int
   85.14 +    rv = 0;
   85.15 +
   85.16 +  struct queue_element
   85.17 +    *qe[QUEUE_PAC_SIZE];
   85.18 +
   85.19 +  assert( qs != NULL );
   85.20 +  // TRD : number_elements can be any value in its range
   85.21 +
   85.22 +  *qs = (struct queue_state *) abstraction_aligned_malloc( sizeof(struct queue_state), ALIGN_DOUBLE_POINTER );
   85.23 +
   85.24 +  if( *qs != NULL )
   85.25 +  {
   85.26 +    // TRD : the size of the freelist is the size of the queue (+1 for the leading dummy element, which is hidden from the caller)
   85.27 +    freelist_new( &(*qs)->fs, number_elements+1, queue_internal_freelist_init_function, NULL );
   85.28 +
   85.29 +    if( (*qs)->fs != NULL )
   85.30 +    {
   85.31 +      queue_internal_new_element_from_freelist( *qs, qe, NULL );
   85.32 +      (*qs)->enqueue[QUEUE_POINTER] = (*qs)->dequeue[QUEUE_POINTER] = qe[QUEUE_POINTER];
   85.33 +      (*qs)->aba_counter = 0;
   85.34 +      rv = 1;
   85.35 +    }
   85.36 +
   85.37 +    if( (*qs)->fs == NULL )
   85.38 +    {
   85.39 +      abstraction_aligned_free( *qs );
   85.40 +      *qs = NULL;
   85.41 +    }
   85.42 +  }
   85.43 +
   85.44 +  return( rv );
   85.45 +}
   85.46 +
   85.47 +
   85.48 +
   85.49 +
   85.50 +
   85.51 +/****************************************************************************/
   85.52 +#pragma warning( disable : 4100 )
   85.53 +
   85.54 +int queue_internal_freelist_init_function( void **user_data, void *user_state )
   85.55 +{
   85.56 +  int
   85.57 +    rv = 0;
   85.58 +
   85.59 +  assert( user_data != NULL );
   85.60 +  assert( user_state == NULL );
   85.61 +
   85.62 +  *user_data = abstraction_aligned_malloc( sizeof(struct queue_element), ALIGN_DOUBLE_POINTER );
   85.63 +
   85.64 +  if( *user_data != NULL )
   85.65 +    rv = 1;
   85.66 +
   85.67 +  return( rv );
   85.68 +}
   85.69 +
   85.70 +#pragma warning( default : 4100 )
   85.71 +
   85.72 +
   85.73 +
   85.74 +
   85.75 +
   85.76 +/****************************************************************************/
   85.77 +void queue_internal_new_element_from_freelist( struct queue_state *qs, struct queue_element *qe[QUEUE_PAC_SIZE], void *user_data )
   85.78 +{
   85.79 +  struct freelist_element
   85.80 +    *fe;
   85.81 +
   85.82 +  assert( qs != NULL );
   85.83 +  assert( qe != NULL );
   85.84 +  // TRD : user_data can be any value in its range
   85.85 +
   85.86 +  qe[QUEUE_POINTER] = NULL;
   85.87 +
   85.88 +  freelist_pop( qs->fs, &fe );
   85.89 +
   85.90 +  if( fe != NULL )
   85.91 +    queue_internal_init_element( qs, qe, fe, user_data );
   85.92 +
   85.93 +  return;
   85.94 +}
   85.95 +
   85.96 +
   85.97 +
   85.98 +
   85.99 +
  85.100 +/****************************************************************************/
  85.101 +void queue_internal_guaranteed_new_element_from_freelist( struct queue_state *qs, struct queue_element *qe[QUEUE_PAC_SIZE], void *user_data )
  85.102 +{
  85.103 +  struct freelist_element
  85.104 +    *fe;
  85.105 +
  85.106 +  assert( qs != NULL );
  85.107 +  assert( qe != NULL );
  85.108 +  // TRD : user_data can be any value in its range
  85.109 +
  85.110 +  qe[QUEUE_POINTER] = NULL;
  85.111 +
  85.112 +  freelist_guaranteed_pop( qs->fs, &fe );
  85.113 +
  85.114 +  if( fe != NULL )
  85.115 +    queue_internal_init_element( qs, qe, fe, user_data );
  85.116 +
  85.117 +  return;
  85.118 +}
  85.119 +
  85.120 +
  85.121 +
  85.122 +
  85.123 +
  85.124 +/****************************************************************************/
  85.125 +void queue_internal_init_element( struct queue_state *qs, struct queue_element *qe[QUEUE_PAC_SIZE], struct freelist_element *fe, void *user_data )
  85.126 +{
  85.127 +  assert( qs != NULL );
  85.128 +  assert( qe != NULL );
  85.129 +  assert( fe != NULL );
  85.130 +  // TRD : user_data can be any value in its range
  85.131 +
  85.132 +  freelist_get_user_data_from_element( fe, (void **) &qe[QUEUE_POINTER] );
  85.133 +  qe[QUEUE_COUNTER] = (struct queue_element *) abstraction_increment( (atom_t *) &qs->aba_counter );
  85.134 +
  85.135 +  qe[QUEUE_POINTER]->next[QUEUE_POINTER] = NULL;
  85.136 +  qe[QUEUE_POINTER]->next[QUEUE_COUNTER] = (struct queue_element *) abstraction_increment( (atom_t *) &qs->aba_counter );
  85.137 +
  85.138 +  qe[QUEUE_POINTER]->fe = fe;
  85.139 +  qe[QUEUE_POINTER]->user_data = user_data;
  85.140 +
  85.141 +  return;
  85.142 +}
  85.143 +
    86.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    86.2 +++ b/liblfds.6/src/single_dir_for_windows_kernel/queue_query.c	Sun Jan 31 21:28:42 2010 +1100
    86.3 @@ -0,0 +1,153 @@
    86.4 +#include "queue_internal.h"
    86.5 +
    86.6 +
    86.7 +
    86.8 +
    86.9 +
   86.10 +/****************************************************************************/
   86.11 +#pragma warning( disable : 4100 )
   86.12 +
   86.13 +void queue_query( struct queue_state *qs, enum queue_query_type query_type, void *query_input, void *query_output )
   86.14 +{
   86.15 +  assert( qs != NULL );
   86.16 +  // TRD : query_type can be any value in its range
   86.17 +  // TRD : query_input can be NULL
   86.18 +  assert( query_output != NULL );
   86.19 +
   86.20 +  switch( query_type )
   86.21 +  {
   86.22 +    case QUEUE_QUERY_ELEMENT_COUNT:
   86.23 +      assert( query_input == NULL );
   86.24 +
   86.25 +      freelist_query( qs->fs, FREELIST_QUERY_ELEMENT_COUNT, NULL, query_output );
   86.26 +    break;
   86.27 +
   86.28 +    case QUEUE_QUERY_VALIDATE:
   86.29 +      // TRD : query_input can be NULL
   86.30 +
   86.31 +      queue_internal_validate( qs, (struct validation_info *) query_input, (enum data_structure_validity *) query_output, ((enum data_structure_validity *) query_output)+1 );
   86.32 +    break;
   86.33 +  }
   86.34 +
   86.35 +  return;
   86.36 +}
   86.37 +
   86.38 +#pragma warning( default : 4100 )
   86.39 +
   86.40 +
   86.41 +
   86.42 +
   86.43 +
   86.44 +/****************************************************************************/
   86.45 +void queue_internal_validate( struct queue_state *qs, struct validation_info *vi, enum data_structure_validity *queue_validity, enum data_structure_validity *freelist_validity )
   86.46 +{
   86.47 +  struct queue_element
   86.48 +    *qe,
   86.49 +    *qe_slow,
   86.50 +    *qe_fast;
   86.51 +
   86.52 +  atom_t
   86.53 +    element_count = 0,
   86.54 +    total_elements;
   86.55 +
   86.56 +  struct validation_info
   86.57 +    freelist_vi;
   86.58 +
   86.59 +  assert( qs != NULL );
   86.60 +  // TRD : vi can be NULL
   86.61 +  assert( queue_validity != NULL );
   86.62 +  assert( freelist_validity != NULL );
   86.63 +
   86.64 +  *queue_validity = VALIDITY_VALID;
   86.65 +
   86.66 +  qe_slow = qe_fast = (struct queue_element *) qs->dequeue[QUEUE_POINTER];
   86.67 +
   86.68 +  /* TRD : first, check for a loop
   86.69 +           we have two pointers
   86.70 +           both of which start at the dequeue end of the queue
   86.71 +           we enter a loop
   86.72 +           and on each iteration
   86.73 +           we advance one pointer by one element
   86.74 +           and the other by two
   86.75 +
   86.76 +           we exit the loop when both pointers are NULL
   86.77 +           (have reached the end of the queue)
   86.78 +
   86.79 +           or
   86.80 +
   86.81 +           if we fast pointer 'sees' the slow pointer
   86.82 +           which means we have a loop
   86.83 +  */
   86.84 +
   86.85 +  if( qe_slow != NULL )
   86.86 +    do
   86.87 +    {
   86.88 +      qe_slow = qe_slow->next[QUEUE_POINTER];
   86.89 +
   86.90 +      if( qe_fast != NULL )
   86.91 +        qe_fast = qe_fast->next[QUEUE_POINTER];
   86.92 +
   86.93 +      if( qe_fast != NULL )
   86.94 +        qe_fast = qe_fast->next[QUEUE_POINTER];
   86.95 +    }
   86.96 +    while( qe_slow != NULL and qe_fast != qe_slow );
   86.97 +
   86.98 +  if( qe_fast != NULL and qe_slow != NULL and qe_fast == qe_slow )
   86.99 +    *queue_validity = VALIDITY_INVALID_LOOP;
  86.100 +
  86.101 +  /* TRD : now check for expected number of elements
  86.102 +           vi can be NULL, in which case we do not check
  86.103 +           we know we don't have a loop from our earlier check
  86.104 +  */
  86.105 +
  86.106 +  if( *queue_validity == VALIDITY_VALID and vi != NULL )
  86.107 +  {
  86.108 +    qe = (struct queue_element *) qs->dequeue[QUEUE_POINTER];
  86.109 +
  86.110 +    while( qe != NULL )
  86.111 +    {
  86.112 +      element_count++;
  86.113 +      qe = (struct queue_element *) qe->next[QUEUE_POINTER];
  86.114 +    }
  86.115 +
  86.116 +    /* TRD : remember there is a dummy element in the queue */
  86.117 +    element_count--;
  86.118 +
  86.119 +    if( element_count < vi->min_elements )
  86.120 +      *queue_validity = VALIDITY_INVALID_MISSING_ELEMENTS;
  86.121 +
  86.122 +    if( element_count > vi->max_elements )
  86.123 +      *queue_validity = VALIDITY_INVALID_ADDITIONAL_ELEMENTS;
  86.124 +  }
  86.125 +
  86.126 +  /* TRD : now we validate the freelist
  86.127 +
  86.128 +           we may be able to check for the expected number of
  86.129 +           elements in the freelist
  86.130 +
  86.131 +           if the caller has given us an expected min and max
  86.132 +           number of elements in the queue, then the total number
  86.133 +           of elements in the freelist, minus that min and max,
  86.134 +           gives us the expected number of elements in the
  86.135 +           freelist
  86.136 +  */
  86.137 +
  86.138 +  if( vi != NULL )
  86.139 +  {
  86.140 +    freelist_query( qs->fs, FREELIST_QUERY_ELEMENT_COUNT, NULL, (void *) &total_elements );
  86.141 +
  86.142 +    /* TRD : remember there is a dummy element in the queue */
  86.143 +    total_elements--;
  86.144 +
  86.145 +    freelist_vi.min_elements = total_elements - vi->max_elements;
  86.146 +    freelist_vi.max_elements = total_elements - vi->min_elements;
  86.147 +
  86.148 +    freelist_query( qs->fs, FREELIST_QUERY_VALIDATE, (void *) &freelist_vi, (void *) freelist_validity );
  86.149 +  }
  86.150 +
  86.151 +  if( vi == NULL )
  86.152 +    freelist_query( qs->fs, FREELIST_QUERY_VALIDATE, NULL, (void *) freelist_validity );
  86.153 +
  86.154 +  return;
  86.155 +}
  86.156 +
    87.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    87.2 +++ b/liblfds.6/src/single_dir_for_windows_kernel/queue_queue.c	Sun Jan 31 21:28:42 2010 +1100
    87.3 @@ -0,0 +1,181 @@
    87.4 +#include "queue_internal.h"
    87.5 +
    87.6 +
    87.7 +
    87.8 +
    87.9 +
   87.10 +/****************************************************************************/
   87.11 +int queue_enqueue( struct queue_state *qs, void *user_data )
   87.12 +{
   87.13 +  ALIGN(ALIGN_DOUBLE_POINTER) struct queue_element
   87.14 +    *qe[QUEUE_PAC_SIZE];
   87.15 +
   87.16 +  assert( qs != NULL );
   87.17 +  // TRD : user_data can be NULL
   87.18 +
   87.19 +  queue_internal_new_element_from_freelist( qs, qe, user_data );
   87.20 +
   87.21 +  if( qe[QUEUE_POINTER] == NULL )
   87.22 +    return( 0 );
   87.23 +
   87.24 +  queue_internal_queue( qs, qe );
   87.25 +
   87.26 +  return( 1 );
   87.27 +}
   87.28 +
   87.29 +
   87.30 +
   87.31 +
   87.32 +
   87.33 +/****************************************************************************/
   87.34 +int queue_guaranteed_enqueue( struct queue_state *qs, void *user_data )
   87.35 +{
   87.36 +  ALIGN(ALIGN_DOUBLE_POINTER) struct queue_element
   87.37 +    *qe[QUEUE_PAC_SIZE];
   87.38 +
   87.39 +  assert( qs != NULL );
   87.40 +  // TRD : user_data can be NULL
   87.41 +
   87.42 +  queue_internal_guaranteed_new_element_from_freelist( qs, qe, user_data );
   87.43 +
   87.44 +  if( qe[QUEUE_POINTER] == NULL )
   87.45 +    return( 0 );
   87.46 +
   87.47 +  queue_internal_queue( qs, qe );
   87.48 +
   87.49 +  return( 1 );
   87.50 +}
   87.51 +
   87.52 +
   87.53 +
   87.54 +
   87.55 +
   87.56 +/****************************************************************************/
   87.57 +void queue_internal_queue( struct queue_state *qs, struct queue_element *qe[QUEUE_PAC_SIZE] )
   87.58 +{
   87.59 +  ALIGN(ALIGN_DOUBLE_POINTER) struct queue_element
   87.60 +    *enqueue[QUEUE_PAC_SIZE],
   87.61 +    *next[QUEUE_PAC_SIZE];
   87.62 +
   87.63 +  unsigned char
   87.64 +    cas_result = 0;
   87.65 +
   87.66 +  assert( qs != NULL );
   87.67 +  assert( qe != NULL );
   87.68 +
   87.69 +  do
   87.70 +  {
   87.71 +    enqueue[QUEUE_POINTER] = qs->enqueue[QUEUE_POINTER];
   87.72 +    enqueue[QUEUE_COUNTER] = qs->enqueue[QUEUE_COUNTER];
   87.73 +
   87.74 +    next[QUEUE_POINTER] = enqueue[QUEUE_POINTER]->next[QUEUE_POINTER];
   87.75 +    next[QUEUE_COUNTER] = enqueue[QUEUE_POINTER]->next[QUEUE_COUNTER];
   87.76 +
   87.77 +    /* TRD : this if() ensures that the next we read, just above,
   87.78 +             really is from qs->enqueue (which we copied into enqueue)
   87.79 +    */
   87.80 +
   87.81 +    if( qs->enqueue[QUEUE_POINTER] == enqueue[QUEUE_POINTER] and qs->enqueue[QUEUE_COUNTER] == enqueue[QUEUE_COUNTER] )
   87.82 +    {
   87.83 +      if( next[QUEUE_POINTER] == NULL )
   87.84 +      {
   87.85 +        qe[QUEUE_COUNTER] = next[QUEUE_COUNTER] + 1;
   87.86 +        cas_result = abstraction_dcas( (volatile atom_t *) enqueue[QUEUE_POINTER]->next, (atom_t *) qe, (atom_t *) next );
   87.87 +      }
   87.88 +      else
   87.89 +      {
   87.90 +        next[QUEUE_COUNTER] = enqueue[QUEUE_COUNTER] + 1;
   87.91 +        abstraction_dcas( (volatile atom_t *) qs->enqueue, (atom_t *) next, (atom_t *) enqueue );
   87.92 +      }
   87.93 +    }
   87.94 +  }
   87.95 +  while( cas_result == 0 );
   87.96 +
   87.97 +  qe[QUEUE_COUNTER] = enqueue[QUEUE_COUNTER] + 1;
   87.98 +  abstraction_dcas( (volatile atom_t *) qs->enqueue, (atom_t *) qe, (atom_t *) enqueue );
   87.99 +
  87.100 +  return;
  87.101 +}
  87.102 +
  87.103 +
  87.104 +
  87.105 +
  87.106 +
  87.107 +/****************************************************************************/
  87.108 +int queue_dequeue( struct queue_state *qs, void **user_data )
  87.109 +{
  87.110 +  ALIGN(ALIGN_DOUBLE_POINTER) struct queue_element
  87.111 +    *enqueue[QUEUE_PAC_SIZE],
  87.112 +    *dequeue[QUEUE_PAC_SIZE],
  87.113 +    *next[QUEUE_PAC_SIZE];
  87.114 +
  87.115 +  unsigned char
  87.116 +    cas_result = 0;
  87.117 +
  87.118 +  int
  87.119 +    rv = 1,
  87.120 +    state = QUEUE_STATE_UNKNOWN,
  87.121 +    finished_flag = LOWERED;
  87.122 +
  87.123 +  assert( qs != NULL );
  87.124 +  assert( user_data != NULL );
  87.125 +
  87.126 +  do
  87.127 +  {
  87.128 +    dequeue[QUEUE_POINTER] = qs->dequeue[QUEUE_POINTER];
  87.129 +    dequeue[QUEUE_COUNTER] = qs->dequeue[QUEUE_COUNTER];
  87.130 +
  87.131 +    enqueue[QUEUE_POINTER] = qs->enqueue[QUEUE_POINTER];
  87.132 +    enqueue[QUEUE_COUNTER] = qs->enqueue[QUEUE_COUNTER];
  87.133 +
  87.134 +    next[QUEUE_POINTER] = dequeue[QUEUE_POINTER]->next[QUEUE_POINTER];
  87.135 +    next[QUEUE_COUNTER] = dequeue[QUEUE_POINTER]->next[QUEUE_COUNTER];
  87.136 +
  87.137 +    /* TRD : confirm that dequeue didn't move between reading it
  87.138 +             and reading its next pointer
  87.139 +    */
  87.140 +
  87.141 +    if( dequeue[QUEUE_POINTER] == qs->dequeue[QUEUE_POINTER] and dequeue[QUEUE_COUNTER] == qs->dequeue[QUEUE_COUNTER] )
  87.142 +    {
  87.143 +      if( enqueue[QUEUE_POINTER] == dequeue[QUEUE_POINTER] and next[QUEUE_POINTER] == NULL )
  87.144 +        state = QUEUE_STATE_EMPTY;
  87.145 +
  87.146 +      if( enqueue[QUEUE_POINTER] == dequeue[QUEUE_POINTER] and next[QUEUE_POINTER] != NULL )
  87.147 +        state = QUEUE_STATE_ENQUEUE_OUT_OF_PLACE;
  87.148 +
  87.149 +      if( enqueue[QUEUE_POINTER] != dequeue[QUEUE_POINTER] )
  87.150 +        state = QUEUE_STATE_ATTEMPT_DEQUEUE;
  87.151 +
  87.152 +      switch( state )
  87.153 +      {
  87.154 +        case QUEUE_STATE_EMPTY:
  87.155 +          *user_data = NULL;
  87.156 +          rv = 0;
  87.157 +          finished_flag = RAISED;
  87.158 +        break;
  87.159 +
  87.160 +        case QUEUE_STATE_ENQUEUE_OUT_OF_PLACE:
  87.161 +          next[QUEUE_COUNTER] = enqueue[QUEUE_COUNTER] + 1;
  87.162 +          abstraction_dcas( (volatile atom_t *) qs->enqueue, (atom_t *) next, (atom_t *) enqueue );
  87.163 +        break;
  87.164 +
  87.165 +        case QUEUE_STATE_ATTEMPT_DEQUEUE:
  87.166 +          *user_data = next[QUEUE_POINTER]->user_data;
  87.167 +
  87.168 +          next[QUEUE_COUNTER] = dequeue[QUEUE_COUNTER] + 1;
  87.169 +          cas_result = abstraction_dcas( (volatile atom_t *) qs->dequeue, (atom_t *) next, (atom_t *) dequeue );
  87.170 +
  87.171 +          if( cas_result == 1 )
  87.172 +            finished_flag = RAISED;
  87.173 +        break;
  87.174 +      }
  87.175 +    }
  87.176 +  }
  87.177 +  while( finished_flag == LOWERED );
  87.178 +
  87.179 +  if( cas_result == 1 )
  87.180 +    freelist_push( qs->fs, dequeue[QUEUE_POINTER]->fe );
  87.181 +
  87.182 +  return( rv );
  87.183 +}
  87.184 +
    88.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    88.2 +++ b/liblfds.6/src/single_dir_for_windows_kernel/ringbuffer_delete.c	Sun Jan 31 21:28:42 2010 +1100
    88.3 @@ -0,0 +1,22 @@
    88.4 +#include "ringbuffer_internal.h"
    88.5 +
    88.6 +
    88.7 +
    88.8 +
    88.9 +
   88.10 +/****************************************************************************/
   88.11 +void ringbuffer_delete( struct ringbuffer_state *rs, void (*user_data_delete_function)(void *user_data, void *user_state), void *user_state )
   88.12 +{
   88.13 +  assert( rs != NULL );
   88.14 +  // TRD : user_data_delete_function can be NULL
   88.15 +  // TRD : user_state can be NULL
   88.16 +
   88.17 +  queue_delete( rs->qs, NULL, NULL );
   88.18 +
   88.19 +  freelist_delete( rs->fs, user_data_delete_function, user_state );
   88.20 +
   88.21 +  abstraction_aligned_free( rs );
   88.22 +
   88.23 +  return;
   88.24 +}
   88.25 +
    89.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    89.2 +++ b/liblfds.6/src/single_dir_for_windows_kernel/ringbuffer_get_and_put.c	Sun Jan 31 21:28:42 2010 +1100
    89.3 @@ -0,0 +1,108 @@
    89.4 +#include "ringbuffer_internal.h"
    89.5 +
    89.6 +
    89.7 +
    89.8 +
    89.9 +
   89.10 +/****************************************************************************/
   89.11 +struct freelist_element *ringbuffer_get_read_element( struct ringbuffer_state *rs, struct freelist_element **fe )
   89.12 +{
   89.13 +  assert( rs != NULL );
   89.14 +  assert( fe != NULL );
   89.15 +
   89.16 +  queue_dequeue( rs->qs, (void **) fe );
   89.17 +
   89.18 +  return( *fe );
   89.19 +}
   89.20 +
   89.21 +
   89.22 +
   89.23 +
   89.24 +
   89.25 +/****************************************************************************/
   89.26 +struct freelist_element *ringbuffer_get_write_element( struct ringbuffer_state *rs, struct freelist_element **fe, int *overwrite_flag )
   89.27 +{
   89.28 +  assert( rs != NULL );
   89.29 +  assert( fe != NULL );
   89.30 +  // TRD : overwrite_flag can be NULL
   89.31 +
   89.32 +  /* TRD : we try to obtain an element from the freelist
   89.33 +           if we can, we populate it and add it to the queue
   89.34 +
   89.35 +           if we cannot, then the ringbuffer is full
   89.36 +           so instead we grab the current read element and
   89.37 +           use that instead
   89.38 +
   89.39 +           dequeue may fail since the queue may be emptied
   89.40 +           during our dequeue attempt
   89.41 +
   89.42 +           so what we actually do here is a loop, attempting
   89.43 +           the freelist and if it fails then a dequeue, until
   89.44 +           we obtain an element
   89.45 +
   89.46 +           once we have an element, we queue it
   89.47 +
   89.48 +           you may be wondering why this operation is in a loop
   89.49 +           remember - these operations are lock-free; anything
   89.50 +           can happen in between
   89.51 +
   89.52 +           so for example the pop could fail because the freelist
   89.53 +           is empty; but by the time we go to get an element from
   89.54 +           the queue, the whole queue has been emptied back into
   89.55 +           the freelist!
   89.56 +
   89.57 +           if overwrite_flag is provided, we set it to 0 if we
   89.58 +           obtained a new element from the freelist, 1 if we
   89.59 +           stole an element from the queue
   89.60 +  */
   89.61 +
   89.62 +  do
   89.63 +  {
   89.64 +    if( overwrite_flag != NULL )
   89.65 +      *overwrite_flag = 0;
   89.66 +
   89.67 +    freelist_pop( rs->fs, fe );
   89.68 +
   89.69 +    if( *fe == NULL )
   89.70 +    {
   89.71 +      ringbuffer_get_read_element( rs, fe );
   89.72 +
   89.73 +      if( overwrite_flag != NULL and *fe != NULL )
   89.74 +        *overwrite_flag = 1;
   89.75 +    }
   89.76 +  }
   89.77 +  while( *fe == NULL );
   89.78 +
   89.79 +  return( *fe );
   89.80 +}
   89.81 +
   89.82 +
   89.83 +
   89.84 +
   89.85 +
   89.86 +/****************************************************************************/
   89.87 +void ringbuffer_put_read_element( struct ringbuffer_state *rs, struct freelist_element *fe )
   89.88 +{
   89.89 +  assert( rs != NULL );
   89.90 +  assert( fe != NULL );
   89.91 +
   89.92 +  freelist_push( rs->fs, fe );
   89.93 +
   89.94 +  return;
   89.95 +}
   89.96 +
   89.97 +
   89.98 +
   89.99 +
  89.100 +
  89.101 +/****************************************************************************/
  89.102 +void ringbuffer_put_write_element( struct ringbuffer_state *rs, struct freelist_element *fe )
  89.103 +{
  89.104 +  assert( rs != NULL );
  89.105 +  assert( fe != NULL );
  89.106 +
  89.107 +  queue_enqueue( rs->qs, fe );
  89.108 +
  89.109 +  return;
  89.110 +}
  89.111 +
    90.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    90.2 +++ b/liblfds.6/src/single_dir_for_windows_kernel/ringbuffer_internal.h	Sun Jan 31 21:28:42 2010 +1100
    90.3 @@ -0,0 +1,24 @@
    90.4 +/***** the library wide include file *****/
    90.5 +#include "liblfds_internal.h"
    90.6 +
    90.7 +/***** defines *****/
    90.8 +
    90.9 +/***** structures *****/
   90.10 +#pragma pack( push, ALIGN_DOUBLE_POINTER )
   90.11 +
   90.12 +struct ringbuffer_state
   90.13 +{
   90.14 +  struct queue_state
   90.15 +    *qs;
   90.16 +
   90.17 +  struct freelist_state
   90.18 +    *fs;
   90.19 +};
   90.20 +
   90.21 +#pragma pack( pop )
   90.22 +
   90.23 +/***** externs *****/
   90.24 +
   90.25 +/***** private prototypes *****/
   90.26 +void ringbuffer_internal_validate( struct ringbuffer_state *rs, struct validation_info *vi, enum data_structure_validity *queue_validity, enum data_structure_validity *freelist_validity );
   90.27 +
    91.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    91.2 +++ b/liblfds.6/src/single_dir_for_windows_kernel/ringbuffer_new.c	Sun Jan 31 21:28:42 2010 +1100
    91.3 @@ -0,0 +1,47 @@
    91.4 +#include "ringbuffer_internal.h"
    91.5 +
    91.6 +
    91.7 +
    91.8 +
    91.9 +
   91.10 +/****************************************************************************/
   91.11 +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 )
   91.12 +{
   91.13 +  int
   91.14 +    rv = 0;
   91.15 +
   91.16 +  assert( rs != NULL );
   91.17 +  // TRD : number_elements can be any value in its range
   91.18 +  // TRD : user_data_init_function can be NULL
   91.19 +  // TRD : user_state can be NULL
   91.20 +
   91.21 +  *rs = (struct ringbuffer_state *) abstraction_aligned_malloc( sizeof(struct ringbuffer_state), ALIGN_DOUBLE_POINTER );
   91.22 +
   91.23 +  if( *rs != NULL )
   91.24 +  {
   91.25 +    freelist_new( &(*rs)->fs, number_elements, user_data_init_function, user_state );
   91.26 +
   91.27 +    if( (*rs)->fs != NULL )
   91.28 +    {
   91.29 +      queue_new( &(*rs)->qs, number_elements );
   91.30 +
   91.31 +      if( (*rs)->qs != NULL )
   91.32 +        rv = 1;
   91.33 +
   91.34 +      if( (*rs)->qs == NULL )
   91.35 +      {
   91.36 +        abstraction_aligned_free( *rs );
   91.37 +        *rs = NULL;
   91.38 +      }
   91.39 +    }
   91.40 +
   91.41 +    if( (*rs)->fs == NULL )
   91.42 +    {
   91.43 +      abstraction_aligned_free( *rs );
   91.44 +      *rs = NULL;
   91.45 +    }
   91.46 +  }
   91.47 +
   91.48 +  return( rv );
   91.49 +}
   91.50 +
    92.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    92.2 +++ b/liblfds.6/src/single_dir_for_windows_kernel/ringbuffer_query.c	Sun Jan 31 21:28:42 2010 +1100
    92.3 @@ -0,0 +1,64 @@
    92.4 +#include "ringbuffer_internal.h"
    92.5 +
    92.6 +
    92.7 +
    92.8 +
    92.9 +
   92.10 +/****************************************************************************/
   92.11 +#pragma warning( disable : 4100 )
   92.12 +
   92.13 +void ringbuffer_query( struct ringbuffer_state *rs, enum ringbuffer_query_type query_type, void *query_input, void *query_output )
   92.14 +{
   92.15 +  assert( rs != NULL );
   92.16 +  // TRD : query_type can be any value in its range
   92.17 +  // TRD : query_input can be NULL
   92.18 +  assert( query_output != NULL );
   92.19 +
   92.20 +  switch( query_type )
   92.21 +  {
   92.22 +    case RINGBUFFER_QUERY_VALIDATE:
   92.23 +      // TRD : query_input can be NULL
   92.24 +
   92.25 +      ringbuffer_internal_validate( rs, (struct validation_info *) query_input, (enum data_structure_validity *) query_output, ((enum data_structure_validity *) query_output)+2 );
   92.26 +    break;
   92.27 +  }
   92.28 +
   92.29 +  return;
   92.30 +}
   92.31 +
   92.32 +#pragma warning( default : 4100 )
   92.33 +
   92.34 +
   92.35 +
   92.36 +
   92.37 +
   92.38 +/****************************************************************************/
   92.39 +void ringbuffer_internal_validate( struct ringbuffer_state *rs, struct validation_info *vi, enum data_structure_validity *queue_validity, enum data_structure_validity *freelist_validity )
   92.40 +{
   92.41 +  assert( rs != NULL );
   92.42 +  // TRD : vi can be NULL
   92.43 +  assert( queue_validity != NULL );
   92.44 +  assert( freelist_validity != NULL );
   92.45 +
   92.46 +  queue_query( rs->qs, QUEUE_QUERY_VALIDATE, vi, queue_validity );
   92.47 +
   92.48 +  if( vi != NULL )
   92.49 +  {
   92.50 +    struct validation_info
   92.51 +      freelist_vi;
   92.52 +
   92.53 +    atom_t
   92.54 +      total_elements;
   92.55 +
   92.56 +    freelist_query( rs->fs, FREELIST_QUERY_ELEMENT_COUNT, NULL, (void *) &total_elements );
   92.57 +    freelist_vi.min_elements = total_elements - vi->max_elements;
   92.58 +    freelist_vi.max_elements = total_elements - vi->min_elements;
   92.59 +    freelist_query( rs->fs, FREELIST_QUERY_VALIDATE, (void *) &freelist_vi, (void *) freelist_validity );
   92.60 +  }
   92.61 +
   92.62 +  if( vi == NULL )
   92.63 +    freelist_query( rs->fs, FREELIST_QUERY_VALIDATE, NULL, (void *) freelist_validity );
   92.64 +
   92.65 +  return;
   92.66 +}
   92.67 +
    93.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    93.2 +++ b/liblfds.6/src/single_dir_for_windows_kernel/slist_delete.c	Sun Jan 31 21:28:42 2010 +1100
    93.3 @@ -0,0 +1,79 @@
    93.4 +#include "slist_internal.h"
    93.5 +
    93.6 +
    93.7 +
    93.8 +
    93.9 +
   93.10 +/****************************************************************************/
   93.11 +void slist_delete( struct slist_state *ss )
   93.12 +{
   93.13 +  slist_delete_all_elements( ss );
   93.14 +
   93.15 +  abstraction_aligned_free( ss );
   93.16 +
   93.17 +  return;
   93.18 +}
   93.19 +
   93.20 +
   93.21 +
   93.22 +
   93.23 +
   93.24 +/****************************************************************************/
   93.25 +void slist_delete_element( struct slist_state *ss, struct slist_element *se )
   93.26 +{
   93.27 +  ALIGN(ALIGN_DOUBLE_POINTER) void
   93.28 +    *volatile user_data_and_flags[2],
   93.29 +    *volatile new_user_data_and_flags[2];
   93.30 +
   93.31 +  unsigned char
   93.32 +    cas_rv = 0;
   93.33 +
   93.34 +  assert( ss != NULL );
   93.35 +  assert( se != NULL );
   93.36 +
   93.37 +  user_data_and_flags[SLIST_USER_DATA] = se->user_data_and_flags[SLIST_USER_DATA];
   93.38 +  user_data_and_flags[SLIST_FLAGS] = se->user_data_and_flags[SLIST_FLAGS];
   93.39 +
   93.40 +  do
   93.41 +  {
   93.42 +    new_user_data_and_flags[SLIST_USER_DATA] = user_data_and_flags[SLIST_USER_DATA];
   93.43 +    new_user_data_and_flags[SLIST_FLAGS] = (void *) ((atom_t) user_data_and_flags[SLIST_FLAGS] | SLIST_FLAG_DELETED);
   93.44 +  }
   93.45 +  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)) );
   93.46 +
   93.47 +  if( cas_rv == 1 )
   93.48 +    if( ss->user_data_delete_function != NULL )
   93.49 +      ss->user_data_delete_function( (void *) user_data_and_flags[SLIST_USER_DATA], ss->user_state );
   93.50 +
   93.51 +  return;
   93.52 +}
   93.53 +
   93.54 +
   93.55 +
   93.56 +
   93.57 +
   93.58 +/****************************************************************************/
   93.59 +void slist_delete_all_elements( struct slist_state *ss )
   93.60 +{
   93.61 +  struct slist_element
   93.62 +    *volatile se,
   93.63 +    *volatile se_temp;
   93.64 +
   93.65 +  se = ss->head;
   93.66 +
   93.67 +  while( se != NULL )
   93.68 +  {
   93.69 +    // TRD : if a non-deleted element and there is a delete function, call the delete function
   93.70 +    if( ss->user_data_delete_function != NULL )
   93.71 +      ss->user_data_delete_function( (void *) se->user_data_and_flags[SLIST_USER_DATA], ss->user_state );
   93.72 +
   93.73 +    se_temp = se;
   93.74 +    se = se->next;
   93.75 +    abstraction_aligned_free( (void *) se_temp );
   93.76 +  }
   93.77 +
   93.78 +  slist_internal_init_slist( ss, ss->user_data_delete_function, ss->user_state );
   93.79 +
   93.80 +  return;
   93.81 +}
   93.82 +
    94.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    94.2 +++ b/liblfds.6/src/single_dir_for_windows_kernel/slist_get_and_set.c	Sun Jan 31 21:28:42 2010 +1100
    94.3 @@ -0,0 +1,124 @@
    94.4 +#include "slist_internal.h"
    94.5 +
    94.6 +
    94.7 +
    94.8 +
    94.9 +
   94.10 +/****************************************************************************/
   94.11 +int slist_get_user_data_from_element( struct slist_element *se, void **user_data )
   94.12 +{
   94.13 +  int
   94.14 +    rv = 1;
   94.15 +
   94.16 +  assert( se != NULL );
   94.17 +  assert( user_data != NULL );
   94.18 +
   94.19 +  *user_data = (void *) se->user_data_and_flags[SLIST_USER_DATA];
   94.20 +
   94.21 +  if( (atom_t) se->user_data_and_flags[SLIST_FLAGS] & SLIST_FLAG_DELETED )
   94.22 +    rv = 0;
   94.23 +
   94.24 +  return( rv );
   94.25 +}
   94.26 +
   94.27 +
   94.28 +
   94.29 +
   94.30 +
   94.31 +/****************************************************************************/
   94.32 +int slist_set_user_data_in_element( struct slist_element *se, void *user_data )
   94.33 +{
   94.34 +  ALIGN(ALIGN_DOUBLE_POINTER) volatile void
   94.35 +    *user_data_and_flags[2],
   94.36 +    *new_user_data_and_flags[2];
   94.37 +
   94.38 +  int
   94.39 +    rv = 1;
   94.40 +
   94.41 +  assert( se != NULL );
   94.42 +  // TRD : user_data can be NULL
   94.43 +
   94.44 +  user_data_and_flags[SLIST_USER_DATA] = se->user_data_and_flags[SLIST_USER_DATA];
   94.45 +  user_data_and_flags[SLIST_FLAGS] = se->user_data_and_flags[SLIST_FLAGS];
   94.46 +
   94.47 +  new_user_data_and_flags[SLIST_USER_DATA] = user_data;
   94.48 +
   94.49 +  do
   94.50 +  {
   94.51 +    new_user_data_and_flags[SLIST_FLAGS] = user_data_and_flags[SLIST_FLAGS];
   94.52 +  }
   94.53 +  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) );
   94.54 +
   94.55 +  if( (atom_t) user_data_and_flags[SLIST_FLAGS] & SLIST_FLAG_DELETED )
   94.56 +    rv = 0;
   94.57 +
   94.58 +  return( rv );
   94.59 +}
   94.60 +
   94.61 +
   94.62 +
   94.63 +
   94.64 +
   94.65 +/****************************************************************************/
   94.66 +struct slist_element *slist_get_head( struct slist_state *ss, struct slist_element **se )
   94.67 +{
   94.68 +  assert( ss != NULL );
   94.69 +  assert( se != NULL );
   94.70 +
   94.71 +  *se = (struct slist_element *) ss->head;
   94.72 +
   94.73 +  slist_internal_move_to_first_undeleted_element( se );
   94.74 +
   94.75 +  return( *se );
   94.76 +}
   94.77 +
   94.78 +
   94.79 +
   94.80 +
   94.81 +
   94.82 +/****************************************************************************/
   94.83 +struct slist_element *slist_get_next( struct slist_element *se, struct slist_element **next_se )
   94.84 +{
   94.85 +  assert( se != NULL );
   94.86 +  assert( next_se != NULL );
   94.87 +
   94.88 +  *next_se = (struct slist_element *) se->next;
   94.89 +
   94.90 +  slist_internal_move_to_first_undeleted_element( next_se );
   94.91 +
   94.92 +  return( *next_se );
   94.93 +}
   94.94 +
   94.95 +
   94.96 +
   94.97 +
   94.98 +
   94.99 +/****************************************************************************/
  94.100 +struct slist_element *slist_get_head_and_then_next( struct slist_state *ss, struct slist_element **se )
  94.101 +{
  94.102 +  assert( ss != NULL );
  94.103 +  assert( se != NULL );
  94.104 +
  94.105 +  if( *se == NULL )
  94.106 +    slist_get_head( ss, se );
  94.107 +  else
  94.108 +    slist_get_next( *se, se );
  94.109 +
  94.110 +  return( *se );
  94.111 +}
  94.112 +
  94.113 +
  94.114 +
  94.115 +
  94.116 +
  94.117 +/****************************************************************************/
  94.118 +void slist_internal_move_to_first_undeleted_element( struct slist_element **se )
  94.119 +{
  94.120 +  assert( se != NULL );
  94.121 +
  94.122 +  while( *se != NULL and (atom_t) (*se)->user_data_and_flags[SLIST_FLAGS] & SLIST_FLAG_DELETED )
  94.123 +    (*se) = (struct slist_element *) (*se)->next;
  94.124 +
  94.125 +  return;
  94.126 +}
  94.127 +
    95.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    95.2 +++ b/liblfds.6/src/single_dir_for_windows_kernel/slist_internal.h	Sun Jan 31 21:28:42 2010 +1100
    95.3 @@ -0,0 +1,55 @@
    95.4 +/***** the library wide include file *****/
    95.5 +#include "liblfds_internal.h"
    95.6 +
    95.7 +/***** defines *****/
    95.8 +#define SLIST_USER_DATA  0
    95.9 +#define SLIST_FLAGS      1
   95.10 +
   95.11 +#define SLIST_NO_FLAGS      0x0
   95.12 +#define SLIST_FLAG_DELETED  0x1
   95.13 +
   95.14 +/***** structures *****/
   95.15 +#pragma pack( push, ALIGN_SINGLE_POINTER )
   95.16 +
   95.17 +struct slist_state
   95.18 +{
   95.19 +  struct slist_element
   95.20 +    *volatile head;
   95.21 +
   95.22 +  void
   95.23 +    (*user_data_delete_function)( void *user_data, void *user_state ),
   95.24 +    *user_state;
   95.25 +};
   95.26 +
   95.27 +#pragma pack( pop )
   95.28 +
   95.29 +#pragma pack( push, ALIGN_DOUBLE_POINTER )
   95.30 +
   95.31 +/* TRD : this pragma pack doesn't seem to work under Windows
   95.32 +         if the structure members are the correct way round
   95.33 +         (next first), then user_data_and_flags ends up on
   95.34 +         a single pointer boundary and DCAS crashes
   95.35 +
   95.36 +         accordingly, I've moved user_data_and_flags first
   95.37 +*/
   95.38 +
   95.39 +struct slist_element
   95.40 +{
   95.41 +  void
   95.42 +    *volatile user_data_and_flags[2];
   95.43 +
   95.44 +  // TRD : requires volatile as is target of CAS
   95.45 +  struct slist_element
   95.46 +    *volatile next;
   95.47 +};
   95.48 +
   95.49 +#pragma pack( pop )
   95.50 +
   95.51 +/***** private prototypes *****/
   95.52 +void slist_internal_init_slist( struct slist_state *ss, void (*user_data_delete_function)(void *user_data, void *user_state), void *user_state );
   95.53 +
   95.54 +void slist_internal_link_element_to_head( struct slist_state *slist_state, struct slist_element *volatile se );
   95.55 +void slist_internal_link_element_after_element( struct slist_element *volatile slist_in_list_element, struct slist_element *volatile se );
   95.56 +
   95.57 +void slist_internal_move_to_first_undeleted_element( struct slist_element **se );
   95.58 +
    96.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    96.2 +++ b/liblfds.6/src/single_dir_for_windows_kernel/slist_link.c	Sun Jan 31 21:28:42 2010 +1100
    96.3 @@ -0,0 +1,53 @@
    96.4 +#include "slist_internal.h"
    96.5 +
    96.6 +
    96.7 +
    96.8 +
    96.9 +
   96.10 +/****************************************************************************/
   96.11 +void slist_internal_link_element_to_head( struct slist_state *ss, struct slist_element *volatile se )
   96.12 +{
   96.13 +  ALIGN(ALIGN_SINGLE_POINTER) struct slist_element
   96.14 +    *se_next;
   96.15 +
   96.16 +  assert( ss != NULL );
   96.17 +  assert( se != NULL );
   96.18 +
   96.19 +  se_next = ss->head;
   96.20 +
   96.21 +  do
   96.22 +  {
   96.23 +    se->next = se_next;
   96.24 +  }
   96.25 +  while( se->next != (se_next = (struct slist_element *) abstraction_cas((volatile atom_t *) &ss->head, (atom_t) se, (atom_t) se->next)) );
   96.26 +
   96.27 +  return;
   96.28 +}
   96.29 +
   96.30 +
   96.31 +
   96.32 +
   96.33 +
   96.34 +/****************************************************************************/
   96.35 +void slist_internal_link_element_after_element( struct slist_element *volatile slist_in_list_element, struct slist_element *volatile se )
   96.36 +{
   96.37 +  ALIGN(ALIGN_SINGLE_POINTER) struct slist_element
   96.38 +    *se_prev,
   96.39 +    *se_next;
   96.40 +
   96.41 +  assert( slist_in_list_element != NULL );
   96.42 +  assert( se != NULL );
   96.43 +
   96.44 +  se_prev = (struct slist_element *) slist_in_list_element;
   96.45 +
   96.46 +  se_next = se_prev->next;
   96.47 +
   96.48 +  do
   96.49 +  {
   96.50 +    se->next = se_next;
   96.51 +  }
   96.52 +  while( se->next != (se_next = (struct slist_element *) abstraction_cas((volatile atom_t *) &se_prev->next, (atom_t) se, (atom_t) se->next)) );
   96.53 +
   96.54 +  return;
   96.55 +}
   96.56 +
    97.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    97.2 +++ b/liblfds.6/src/single_dir_for_windows_kernel/slist_new.c	Sun Jan 31 21:28:42 2010 +1100
    97.3 @@ -0,0 +1,97 @@
    97.4 +#include "slist_internal.h"
    97.5 +
    97.6 +
    97.7 +
    97.8 +
    97.9 +
   97.10 +/****************************************************************************/
   97.11 +int slist_new( struct slist_state **ss, void (*user_data_delete_function)(void *user_data, void *user_state), void *user_state )
   97.12 +{
   97.13 +  int
   97.14 +    rv = 0;
   97.15 +
   97.16 +  assert( ss != NULL );
   97.17 +  // TRD : user_data_delete_function can be NULL
   97.18 +  // TRD : user_state can be NULL
   97.19 +
   97.20 +  *ss = (struct slist_state *) abstraction_aligned_malloc( sizeof(struct slist_state), ALIGN_SINGLE_POINTER );
   97.21 +
   97.22 +  if( *ss != NULL )
   97.23 +  {
   97.24 +    slist_internal_init_slist( *ss, user_data_delete_function, user_state );
   97.25 +    rv = 1;
   97.26 +  }
   97.27 +
   97.28 +  return( rv );
   97.29 +}
   97.30 +
   97.31 +
   97.32 +
   97.33 +
   97.34 +
   97.35 +/****************************************************************************/
   97.36 +void slist_internal_init_slist( struct slist_state *ss, void (*user_data_delete_function)(void *user_data, void *user_state), void *user_state )
   97.37 +{
   97.38 +  assert( ss != NULL );
   97.39 +  // TRD : user_data_delete_function can be NULL
   97.40 +  // TRD : user_state can be NULL
   97.41 +
   97.42 +  ss->head = NULL;
   97.43 +  ss->user_data_delete_function = user_data_delete_function;
   97.44 +  ss->user_state = user_state;
   97.45 +
   97.46 +  return;
   97.47 +}
   97.48 +
   97.49 +
   97.50 +
   97.51 +
   97.52 +
   97.53 +/****************************************************************************/
   97.54 +struct slist_element *slist_new_head( struct slist_state *ss, void *user_data )
   97.55 +{
   97.56 +  ALIGN(ALIGN_SINGLE_POINTER) struct slist_element
   97.57 +    *volatile se;
   97.58 +
   97.59 +  assert( ss != NULL );
   97.60 +  // TRD : user_data can be NULL
   97.61 +
   97.62 +  se = (struct slist_element *) abstraction_aligned_malloc( sizeof(struct slist_element), ALIGN_DOUBLE_POINTER );
   97.63 +
   97.64 +  if( se != NULL )
   97.65 +  {
   97.66 +    se->user_data_and_flags[SLIST_USER_DATA] = user_data;
   97.67 +    se->user_data_and_flags[SLIST_FLAGS] = SLIST_NO_FLAGS;
   97.68 +
   97.69 +    slist_internal_link_element_to_head( ss, se );
   97.70 +  }
   97.71 +
   97.72 +  return( (struct slist_element *) se );
   97.73 +}
   97.74 +
   97.75 +
   97.76 +
   97.77 +
   97.78 +
   97.79 +/****************************************************************************/
   97.80 +struct slist_element *slist_new_next( struct slist_element *se, void *user_data )
   97.81 +{
   97.82 +  ALIGN(ALIGN_SINGLE_POINTER) struct slist_element
   97.83 +    *volatile se_next;
   97.84 +
   97.85 +  assert( se != NULL );
   97.86 +  // TRD : user_data can be NULL
   97.87 +
   97.88 +  se_next = (struct slist_element *) abstraction_aligned_malloc( sizeof(struct slist_element), ALIGN_DOUBLE_POINTER );
   97.89 +
   97.90 +  if( se_next != NULL )
   97.91 +  {
   97.92 +    se_next->user_data_and_flags[SLIST_USER_DATA] = user_data;
   97.93 +    se_next->user_data_and_flags[SLIST_FLAGS] = SLIST_NO_FLAGS;
   97.94 +
   97.95 +    slist_internal_link_element_after_element( se, se_next );
   97.96 +  }
   97.97 +
   97.98 +  return( (struct slist_element *) se_next );
   97.99 +}
  97.100 +
    98.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    98.2 +++ b/liblfds.6/src/single_dir_for_windows_kernel/sources	Sun Jan 31 21:28:42 2010 +1100
    98.3 @@ -0,0 +1,35 @@
    98.4 +MSC_WARNING_LEVEL = /WX /W4
    98.5 +TARGETNAME        = liblfds
    98.6 +TARGETPATH        = ../../bin/
    98.7 +TARGETTYPE        = DRIVER_LIBRARY
    98.8 +UMTYPE            = nt
    98.9 +USER_C_FLAGS      = /DWIN_KERNEL_BUILD
   98.10 +
   98.11 +INCLUDES = ..;../../inc/
   98.12 +SOURCES  = abstraction_aligned_free.c \
   98.13 +           abstraction_aligned_malloc.c \
   98.14 +           abstraction_cas.c \
   98.15 +           abstraction_dcas.c \
   98.16 +           abstraction_increment.c \
   98.17 +           freelist_delete.c \
   98.18 +           freelist_get_and_set.c \
   98.19 +           freelist_new.c \
   98.20 +           freelist_pop_push.c \
   98.21 +           freelist_query.c \
   98.22 +           queue_delete.c \
   98.23 +           queue_new.c \
   98.24 +           queue_query.c \
   98.25 +           queue_queue.c \
   98.26 +           ringbuffer_delete.c \
   98.27 +           ringbuffer_get_and_put.c \
   98.28 +           ringbuffer_new.c \
   98.29 +           ringbuffer_query.c \
   98.30 +           slist_delete.c \
   98.31 +           slist_get_and_set.c \
   98.32 +           slist_link.c \
   98.33 +           slist_new.c \
   98.34 +           stack_delete.c \
   98.35 +           stack_new.c \
   98.36 +           stack_push_pop.c \
   98.37 +           stack_query.c
   98.38 +
    99.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    99.2 +++ b/liblfds.6/src/single_dir_for_windows_kernel/stack_delete.c	Sun Jan 31 21:28:42 2010 +1100
    99.3 @@ -0,0 +1,67 @@
    99.4 +#include "stack_internal.h"
    99.5 +
    99.6 +
    99.7 +
    99.8 +
    99.9 +
   99.10 +/****************************************************************************/
   99.11 +void stack_delete( struct stack_state *ss, void (*user_data_delete_function)(void *user_data, void *user_state), void *user_state )
   99.12 +{
   99.13 +  void
   99.14 +    *user_data;
   99.15 +
   99.16 +  assert( ss != NULL );
   99.17 +  // TRD : user_data_delete_function can be NULL
   99.18 +  // TRD : user_state can be NULL
   99.19 +
   99.20 +  while( stack_pop(ss, &user_data) )
   99.21 +    if( user_data_delete_function != NULL )
   99.22 +      user_data_delete_function( user_data, user_state );
   99.23 +
   99.24 +  freelist_delete( ss->fs, stack_internal_freelist_delete_function, NULL );
   99.25 +
   99.26 +  abstraction_aligned_free( ss );
   99.27 +
   99.28 +  return;
   99.29 +}
   99.30 +
   99.31 +
   99.32 +
   99.33 +
   99.34 +
   99.35 +/****************************************************************************/
   99.36 +void stack_clear( struct stack_state *ss, void (*user_data_clear_function)(void *user_data, void *user_state), void *user_state )
   99.37 +{
   99.38 +  void
   99.39 +    *user_data;
   99.40 +
   99.41 +  assert( ss != NULL );
   99.42 +  // TRD : user_data_clear_function can be NULL
   99.43 +  // TRD : user_state can be NULL
   99.44 +
   99.45 +  while( stack_pop(ss, &user_data) )
   99.46 +    if( user_data_clear_function != NULL )
   99.47 +      user_data_clear_function( user_data, user_state );
   99.48 +
   99.49 +  return;
   99.50 +}
   99.51 +
   99.52 +
   99.53 +
   99.54 +
   99.55 +
   99.56 +/****************************************************************************/
   99.57 +#pragma warning( disable : 4100 )
   99.58 +
   99.59 +void stack_internal_freelist_delete_function( void *user_data, void *user_state )
   99.60 +{
   99.61 +  assert( user_data != NULL );
   99.62 +  assert( user_state == NULL );
   99.63 +
   99.64 +  abstraction_aligned_free( user_data );
   99.65 +
   99.66 +  return;
   99.67 +}
   99.68 +
   99.69 +#pragma warning( default : 4100 )
   99.70 +
   100.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   100.2 +++ b/liblfds.6/src/single_dir_for_windows_kernel/stack_internal.h	Sun Jan 31 21:28:42 2010 +1100
   100.3 @@ -0,0 +1,50 @@
   100.4 +/***** the library wide include file *****/
   100.5 +#include "liblfds_internal.h"
   100.6 +
   100.7 +/***** pragmas *****/
   100.8 +
   100.9 +/***** defines *****/
  100.10 +#define STACK_POINTER 0
  100.11 +#define STACK_COUNTER 1
  100.12 +#define STACK_PAC_SIZE 2
  100.13 +
  100.14 +/***** structures *****/
  100.15 +#pragma pack( push, ALIGN_DOUBLE_POINTER )
  100.16 +
  100.17 +struct stack_state
  100.18 +{
  100.19 +  // TRD : must come first for alignment
  100.20 +  struct stack_element
  100.21 +    *volatile top[STACK_PAC_SIZE];
  100.22 +
  100.23 +  atom_t
  100.24 +    aba_counter;
  100.25 +
  100.26 +  struct freelist_state
  100.27 +    *fs;
  100.28 +};
  100.29 +
  100.30 +struct stack_element
  100.31 +{
  100.32 +  struct stack_element
  100.33 +    *next[STACK_PAC_SIZE];
  100.34 +
  100.35 +  struct freelist_element
  100.36 +    *fe;
  100.37 +
  100.38 +  void
  100.39 +    *user_data;
  100.40 +};
  100.41 +
  100.42 +#pragma pack( pop )
  100.43 +
  100.44 +/***** private prototypes *****/
  100.45 +int stack_internal_freelist_init_function( void **user_data, void *user_state );
  100.46 +void stack_internal_freelist_delete_function( void *user_data, void *user_state );
  100.47 +
  100.48 +void stack_internal_new_element_from_freelist( struct stack_state *ss, struct stack_element *se[STACK_PAC_SIZE], void *user_data );
  100.49 +void stack_internal_new_element( struct stack_state *ss, struct stack_element *se[STACK_PAC_SIZE], void *user_data );
  100.50 +void stack_internal_init_element( struct stack_state *ss, struct stack_element *se[STACK_PAC_SIZE], struct freelist_element *fe, void *user_data );
  100.51 +
  100.52 +void stack_internal_push( struct stack_state *ss, struct stack_element *se[STACK_PAC_SIZE] );
  100.53 +
   101.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   101.2 +++ b/liblfds.6/src/single_dir_for_windows_kernel/stack_new.c	Sun Jan 31 21:28:42 2010 +1100
   101.3 @@ -0,0 +1,139 @@
   101.4 +#include "stack_internal.h"
   101.5 +
   101.6 +
   101.7 +
   101.8 +
   101.9 +
  101.10 +/****************************************************************************/
  101.11 +int stack_new( struct stack_state **ss, atom_t number_elements )
  101.12 +{
  101.13 +  int
  101.14 +    rv = 0;
  101.15 +
  101.16 +  assert( ss != NULL );
  101.17 +  // TRD : number_elements can be any value in its range
  101.18 +
  101.19 +  *ss = (struct stack_state *) abstraction_aligned_malloc( sizeof(struct stack_state), ALIGN_DOUBLE_POINTER );
  101.20 +
  101.21 +  if( *ss != NULL )
  101.22 +  {
  101.23 +    // TRD : the size of the freelist is the size of the stack
  101.24 +    freelist_new( &(*ss)->fs, number_elements, stack_internal_freelist_init_function, NULL );
  101.25 +
  101.26 +    if( (*ss)->fs == NULL )
  101.27 +    {
  101.28 +      abstraction_aligned_free( *ss );
  101.29 +      *ss = NULL;
  101.30 +    }
  101.31 +
  101.32 +    if( (*ss)->fs != NULL )
  101.33 +    {
  101.34 +      (*ss)->top[STACK_POINTER] = NULL;
  101.35 +      (*ss)->top[STACK_COUNTER] = 0;
  101.36 +      (*ss)->aba_counter = 0;
  101.37 +      rv = 1;
  101.38 +    }
  101.39 +  }
  101.40 +
  101.41 +  return( rv );
  101.42 +}
  101.43 +
  101.44 +
  101.45 +
  101.46 +
  101.47 +
  101.48 +/****************************************************************************/
  101.49 +#pragma warning( disable : 4100 )
  101.50 +
  101.51 +int stack_internal_freelist_init_function( void **user_data, void *user_state )
  101.52 +{
  101.53 +  int
  101.54 +    rv = 0;
  101.55 +
  101.56 +  assert( user_data != NULL );
  101.57 +  assert( user_state == NULL );
  101.58 +
  101.59 +  *user_data = abstraction_aligned_malloc( sizeof(struct stack_element), ALIGN_DOUBLE_POINTER );
  101.60 +
  101.61 +  if( *user_data != NULL )
  101.62 +    rv = 1;
  101.63 +
  101.64 +  return( rv );
  101.65 +}
  101.66 +
  101.67 +#pragma warning( default : 4100 )
  101.68 +
  101.69 +
  101.70 +
  101.71 +
  101.72 +
  101.73 +/****************************************************************************/
  101.74 +void stack_internal_new_element_from_freelist( struct stack_state *ss, struct stack_element *se[STACK_PAC_SIZE], void *user_data )
  101.75 +{
  101.76 +  struct freelist_element
  101.77 +    *fe;
  101.78 +
  101.79 +  assert( ss != NULL );
  101.80 +  assert( se != NULL );
  101.81 +  // TRD : user_data can be any value in its range
  101.82 +
  101.83 +  freelist_pop( ss->fs, &fe );
  101.84 +
  101.85 +  if( fe == NULL )
  101.86 +    se[STACK_POINTER] = NULL;
  101.87 +
  101.88 +  if( fe != NULL )
  101.89 +    stack_internal_init_element( ss, se, fe, user_data );
  101.90 +
  101.91 +  return;
  101.92 +}
  101.93 +
  101.94 +
  101.95 +
  101.96 +
  101.97 +
  101.98 +/****************************************************************************/
  101.99 +void stack_internal_new_element( struct stack_state *ss, struct stack_element *se[STACK_PAC_SIZE], void *user_data )
 101.100 +{
 101.101 +  struct freelist_element
 101.102 +    *fe;
 101.103 +
 101.104 +  assert( ss != NULL );
 101.105 +  assert( se != NULL );
 101.106 +  // TRD : user_data can be any value in its range
 101.107 +
 101.108 +  freelist_guaranteed_pop( ss->fs, &fe );
 101.109 +
 101.110 +  if( fe == NULL )
 101.111 +    se[STACK_POINTER] = NULL;
 101.112 +
 101.113 +  if( fe != NULL )
 101.114 +    stack_internal_init_element( ss, se, fe, user_data );
 101.115 +
 101.116 +  return;
 101.117 +}
 101.118 +
 101.119 +
 101.120 +
 101.121 +
 101.122 +
 101.123 +/****************************************************************************/
 101.124 +void stack_internal_init_element( struct stack_state *ss, struct stack_element *se[STACK_PAC_SIZE], struct freelist_element *fe, void *user_data )
 101.125 +{
 101.126 +  assert( ss != NULL );
 101.127 +  assert( se != NULL );
 101.128 +  assert( fe != NULL );
 101.129 +  // TRD : user_data can be any value in its range
 101.130 +
 101.131 +  freelist_get_user_data_from_element( fe, (void **) &se[STACK_POINTER] );
 101.132 +
 101.133 +  se[STACK_COUNTER] = (struct stack_element *) abstraction_increment( (atom_t *) &ss->aba_counter );
 101.134 +
 101.135 +  se[STACK_POINTER]->next[STACK_POINTER] = NULL;
 101.136 +  se[STACK_POINTER]->next[STACK_COUNTER] = 0;
 101.137 +  se[STACK_POINTER]->fe = fe;
 101.138 +  se[STACK_POINTER]->user_data = user_data;
 101.139 +
 101.140 +  return;
 101.141 +}
 101.142 +
   102.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   102.2 +++ b/liblfds.6/src/single_dir_for_windows_kernel/stack_push_pop.c	Sun Jan 31 21:28:42 2010 +1100
   102.3 @@ -0,0 +1,110 @@
   102.4 +#include "stack_internal.h"
   102.5 +
   102.6 +
   102.7 +
   102.8 +
   102.9 +
  102.10 +/****************************************************************************/
  102.11 +int stack_push( struct stack_state *ss, void *user_data )
  102.12 +{
  102.13 +  ALIGN(ALIGN_DOUBLE_POINTER) struct stack_element
  102.14 +    *se[STACK_PAC_SIZE];
  102.15 +
  102.16 +  assert( ss != NULL );
  102.17 +  // TRD : user_data can be NULL
  102.18 +
  102.19 +  stack_internal_new_element_from_freelist( ss, se, user_data );
  102.20 +
  102.21 +  if( se[STACK_POINTER] == NULL )
  102.22 +    return( 0 );
  102.23 +
  102.24 +  stack_internal_push( ss, se );
  102.25 +
  102.26 +  return( 1 );
  102.27 +}
  102.28 +
  102.29 +
  102.30 +
  102.31 +
  102.32 +
  102.33 +/****************************************************************************/
  102.34 +int stack_guaranteed_push( struct stack_state *ss, void *user_data )
  102.35 +{
  102.36 +  ALIGN(ALIGN_DOUBLE_POINTER) struct stack_element
  102.37 +    *se[STACK_PAC_SIZE];
  102.38 +
  102.39 +  assert( ss != NULL );
  102.40 +  // TRD : user_data can be NULL
  102.41 +
  102.42 +  /* TRD : this function allocated a new freelist element and uses that
  102.43 +           to push onto the stack, guaranteeing success (unless malloc()
  102.44 +           fails of course)
  102.45 +  */
  102.46 +
  102.47 +  stack_internal_new_element( ss, se, user_data );
  102.48 +
  102.49 +  // TRD : malloc failed
  102.50 +  if( se[STACK_POINTER] == NULL )
  102.51 +    return( 0 );
  102.52 +
  102.53 +  stack_internal_push( ss, se );
  102.54 +
  102.55 +  return( 1 );
  102.56 +}
  102.57 +
  102.58 +
  102.59 +
  102.60 +
  102.61 +
  102.62 +/****************************************************************************/
  102.63 +void stack_internal_push( struct stack_state *ss, struct stack_element *se[STACK_PAC_SIZE] )
  102.64 +{
  102.65 +  ALIGN(ALIGN_DOUBLE_POINTER) struct stack_element
  102.66 +    *original_se_next[STACK_PAC_SIZE];
  102.67 +
  102.68 +  assert( ss != NULL );
  102.69 +  assert( se != NULL );
  102.70 +
  102.71 +  original_se_next[STACK_POINTER] = ss->top[STACK_POINTER];
  102.72 +  original_se_next[STACK_COUNTER] = ss->top[STACK_COUNTER];
  102.73 +
  102.74 +  do
  102.75 +  {
  102.76 +    se[STACK_POINTER]->next[STACK_POINTER] = original_se_next[STACK_POINTER];
  102.77 +    se[STACK_POINTER]->next[STACK_COUNTER] = original_se_next[STACK_COUNTER];
  102.78 +  }
  102.79 +  while( 0 == abstraction_dcas((volatile atom_t *) ss->top, (atom_t *) se, (atom_t *) original_se_next) );
  102.80 +
  102.81 +  return;
  102.82 +}
  102.83 +
  102.84 +
  102.85 +
  102.86 +
  102.87 +
  102.88 +/****************************************************************************/
  102.89 +int stack_pop( struct stack_state *ss, void **user_data )
  102.90 +{
  102.91 +  ALIGN(ALIGN_DOUBLE_POINTER) struct stack_element
  102.92 +    *se[STACK_PAC_SIZE];
  102.93 +
  102.94 +  assert( ss != NULL );
  102.95 +  assert( user_data != NULL );
  102.96 +
  102.97 +  se[STACK_COUNTER] = ss->top[STACK_COUNTER];
  102.98 +  se[STACK_POINTER] = ss->top[STACK_POINTER];
  102.99 +
 102.100 +  do
 102.101 +  {
 102.102 +    if( se[STACK_POINTER] == NULL )
 102.103 +      return( 0 );
 102.104 +  }
 102.105 +  while( 0 == abstraction_dcas((volatile atom_t *) ss->top, (atom_t *) se[STACK_POINTER]->next, (atom_t *) se) );
 102.106 +
 102.107 +  *user_data = se[STACK_POINTER]->user_data;
 102.108 +
 102.109 +  freelist_push( ss->fs, se[STACK_POINTER]->fe );
 102.110 +
 102.111 +  return( 1 );
 102.112 +}
 102.113 +
   103.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   103.2 +++ b/liblfds.6/src/single_dir_for_windows_kernel/stack_query.c	Sun Jan 31 21:28:42 2010 +1100
   103.3 @@ -0,0 +1,30 @@
   103.4 +#include "stack_internal.h"
   103.5 +
   103.6 +
   103.7 +
   103.8 +
   103.9 +
  103.10 +/****************************************************************************/
  103.11 +#pragma warning( disable : 4100 )
  103.12 +
  103.13 +void stack_query( struct stack_state *ss, enum stack_query_type query_type, void *query_input, void *query_output )
  103.14 +{
  103.15 +  assert( ss != NULL );
  103.16 +  // TRD : query_type can be any value in its range
  103.17 +  // TRD : query_iput can be NULL
  103.18 +  assert( query_output != NULL );
  103.19 +
  103.20 +  switch( query_type )
  103.21 +  {
  103.22 +    case STACK_QUERY_ELEMENT_COUNT:
  103.23 +      assert( query_input == NULL );
  103.24 +
  103.25 +      freelist_query( ss->fs, FREELIST_QUERY_ELEMENT_COUNT, NULL, query_output );
  103.26 +    break;
  103.27 +  }
  103.28 +
  103.29 +  return;
  103.30 +}
  103.31 +
  103.32 +#pragma warning( default : 4100 )
  103.33 +
   104.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   104.2 +++ b/liblfds.6/src/slist/slist_delete.c	Sun Jan 31 21:28:42 2010 +1100
   104.3 @@ -0,0 +1,79 @@
   104.4 +#include "slist_internal.h"
   104.5 +
   104.6 +
   104.7 +
   104.8 +
   104.9 +
  104.10 +/****************************************************************************/
  104.11 +void slist_delete( struct slist_state *ss )
  104.12 +{
  104.13 +  slist_delete_all_elements( ss );
  104.14 +
  104.15 +  abstraction_aligned_free( ss );
  104.16 +
  104.17 +  return;
  104.18 +}
  104.19 +
  104.20 +
  104.21 +
  104.22 +
  104.23 +
  104.24 +/****************************************************************************/
  104.25 +void slist_delete_element( struct slist_state *ss, struct slist_element *se )
  104.26 +{
  104.27 +  ALIGN(ALIGN_DOUBLE_POINTER) void
  104.28 +    *volatile user_data_and_flags[2],
  104.29 +    *volatile new_user_data_and_flags[2];
  104.30 +
  104.31 +  unsigned char
  104.32 +    cas_rv = 0;
  104.33 +
  104.34 +  assert( ss != NULL );
  104.35 +  assert( se != NULL );
  104.36 +
  104.37 +  user_data_and_flags[SLIST_USER_DATA] = se->user_data_and_flags[SLIST_USER_DATA];
  104.38 +  user_data_and_flags[SLIST_FLAGS] = se->user_data_and_flags[SLIST_FLAGS];
  104.39 +
  104.40 +  do
  104.41 +  {
  104.42 +    new_user_data_and_flags[SLIST_USER_DATA] = user_data_and_flags[SLIST_USER_DATA];
  104.43 +    new_user_data_and_flags[SLIST_FLAGS] = (void *) ((atom_t) user_data_and_flags[SLIST_FLAGS] | SLIST_FLAG_DELETED);
  104.44 +  }
  104.45 +  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)) );
  104.46 +
  104.47 +  if( cas_rv == 1 )
  104.48 +    if( ss->user_data_delete_function != NULL )
  104.49 +      ss->user_data_delete_function( (void *) user_data_and_flags[SLIST_USER_DATA], ss->user_state );
  104.50 +
  104.51 +  return;
  104.52 +}
  104.53 +
  104.54 +
  104.55 +
  104.56 +
  104.57 +
  104.58 +/****************************************************************************/
  104.59 +void slist_delete_all_elements( struct slist_state *ss )
  104.60 +{
  104.61 +  struct slist_element
  104.62 +    *volatile se,
  104.63 +    *volatile se_temp;
  104.64 +
  104.65 +  se = ss->head;
  104.66 +
  104.67 +  while( se != NULL )
  104.68 +  {
  104.69 +    // TRD : if a non-deleted element and there is a delete function, call the delete function
  104.70 +    if( ss->user_data_delete_function != NULL )
  104.71 +      ss->user_data_delete_function( (void *) se->user_data_and_flags[SLIST_USER_DATA], ss->user_state );
  104.72 +
  104.73 +    se_temp = se;
  104.74 +    se = se->next;
  104.75 +    abstraction_aligned_free( (void *) se_temp );
  104.76 +  }
  104.77 +
  104.78 +  slist_internal_init_slist( ss, ss->user_data_delete_function, ss->user_state );
  104.79 +
  104.80 +  return;
  104.81 +}
  104.82 +
   105.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   105.2 +++ b/liblfds.6/src/slist/slist_get_and_set.c	Sun Jan 31 21:28:42 2010 +1100
   105.3 @@ -0,0 +1,124 @@
   105.4 +#include "slist_internal.h"
   105.5 +
   105.6 +
   105.7 +
   105.8 +
   105.9 +
  105.10 +/****************************************************************************/
  105.11 +int slist_get_user_data_from_element( struct slist_element *se, void **user_data )
  105.12 +{
  105.13 +  int
  105.14 +    rv = 1;
  105.15 +
  105.16 +  assert( se != NULL );
  105.17 +  assert( user_data != NULL );
  105.18 +
  105.19 +  *user_data = (void *) se->user_data_and_flags[SLIST_USER_DATA];
  105.20 +
  105.21 +  if( (atom_t) se->user_data_and_flags[SLIST_FLAGS] & SLIST_FLAG_DELETED )
  105.22 +    rv = 0;
  105.23 +
  105.24 +  return( rv );
  105.25 +}
  105.26 +
  105.27 +
  105.28 +
  105.29 +
  105.30 +
  105.31 +/****************************************************************************/
  105.32 +int slist_set_user_data_in_element( struct slist_element *se, void *user_data )
  105.33 +{
  105.34 +  ALIGN(ALIGN_DOUBLE_POINTER) volatile void
  105.35 +    *user_data_and_flags[2],
  105.36 +    *new_user_data_and_flags[2];
  105.37 +
  105.38 +  int
  105.39 +    rv = 1;
  105.40 +
  105.41 +  assert( se != NULL );
  105.42 +  // TRD : user_data can be NULL
  105.43 +
  105.44 +  user_data_and_flags[SLIST_USER_DATA] = se->user_data_and_flags[SLIST_USER_DATA];
  105.45 +  user_data_and_flags[SLIST_FLAGS] = se->user_data_and_flags[SLIST_FLAGS];
  105.46 +
  105.47 +  new_user_data_and_flags[SLIST_USER_DATA] = user_data;
  105.48 +
  105.49 +  do
  105.50 +  {
  105.51 +    new_user_data_and_flags[SLIST_FLAGS] = user_data_and_flags[SLIST_FLAGS];
  105.52 +  }
  105.53 +  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) );
  105.54 +
  105.55 +  if( (atom_t) user_data_and_flags[SLIST_FLAGS] & SLIST_FLAG_DELETED )
  105.56 +    rv = 0;
  105.57 +
  105.58 +  return( rv );
  105.59 +}
  105.60 +
  105.61 +
  105.62 +
  105.63 +
  105.64 +
  105.65 +/****************************************************************************/
  105.66 +struct slist_element *slist_get_head( struct slist_state *ss, struct slist_element **se )
  105.67 +{
  105.68 +  assert( ss != NULL );
  105.69 +  assert( se != NULL );
  105.70 +
  105.71 +  *se = (struct slist_element *) ss->head;
  105.72 +
  105.73 +  slist_internal_move_to_first_undeleted_element( se );
  105.74 +
  105.75 +  return( *se );
  105.76 +}
  105.77 +
  105.78 +
  105.79 +
  105.80 +
  105.81 +
  105.82 +/****************************************************************************/
  105.83 +struct slist_element *slist_get_next( struct slist_element *se, struct slist_element **next_se )
  105.84 +{
  105.85 +  assert( se != NULL );
  105.86 +  assert( next_se != NULL );
  105.87 +
  105.88 +  *next_se = (struct slist_element *) se->next;
  105.89 +
  105.90 +  slist_internal_move_to_first_undeleted_element( next_se );
  105.91 +
  105.92 +  return( *next_se );
  105.93 +}
  105.94 +
  105.95 +
  105.96 +
  105.97 +
  105.98 +
  105.99 +/****************************************************************************/
 105.100 +struct slist_element *slist_get_head_and_then_next( struct slist_state *ss, struct slist_element **se )
 105.101 +{
 105.102 +  assert( ss != NULL );
 105.103 +  assert( se != NULL );
 105.104 +
 105.105 +  if( *se == NULL )
 105.106 +    slist_get_head( ss, se );
 105.107 +  else
 105.108 +    slist_get_next( *se, se );
 105.109 +
 105.110 +  return( *se );
 105.111 +}
 105.112 +
 105.113 +
 105.114 +
 105.115 +
 105.116 +
 105.117 +/****************************************************************************/
 105.118 +void slist_internal_move_to_first_undeleted_element( struct slist_element **se )
 105.119 +{
 105.120 +  assert( se != NULL );
 105.121 +
 105.122 +  while( *se != NULL and (atom_t) (*se)->user_data_and_flags[SLIST_FLAGS] & SLIST_FLAG_DELETED )
 105.123 +    (*se) = (struct slist_element *) (*se)->next;
 105.124 +
 105.125 +  return;
 105.126 +}
 105.127 +
   106.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   106.2 +++ b/liblfds.6/src/slist/slist_internal.h	Sun Jan 31 21:28:42 2010 +1100
   106.3 @@ -0,0 +1,55 @@
   106.4 +/***** the library wide include file *****/
   106.5 +#include "liblfds_internal.h"
   106.6 +
   106.7 +/***** defines *****/
   106.8 +#define SLIST_USER_DATA  0
   106.9 +#define SLIST_FLAGS      1
  106.10 +
  106.11 +#define SLIST_NO_FLAGS      0x0
  106.12 +#define SLIST_FLAG_DELETED  0x1
  106.13 +
  106.14 +/***** structures *****/
  106.15 +#pragma pack( push, ALIGN_SINGLE_POINTER )
  106.16 +
  106.17 +struct slist_state
  106.18 +{
  106.19 +  struct slist_element
  106.20 +    *volatile head;
  106.21 +
  106.22 +  void
  106.23 +    (*user_data_delete_function)( void *user_data, void *user_state ),
  106.24 +    *user_state;
  106.25 +};
  106.26 +
  106.27 +#pragma pack( pop )
  106.28 +
  106.29 +#pragma pack( push, ALIGN_DOUBLE_POINTER )
  106.30 +
  106.31 +/* TRD : this pragma pack doesn't seem to work under Windows
  106.32 +         if the structure members are the correct way round
  106.33 +         (next first), then user_data_and_flags ends up on
  106.34 +         a single pointer boundary and DCAS crashes
  106.35 +
  106.36 +         accordingly, I've moved user_data_and_flags first
  106.37 +*/
  106.38 +
  106.39 +struct slist_element
  106.40 +{
  106.41 +  void
  106.42 +    *volatile user_data_and_flags[2];
  106.43 +
  106.44 +  // TRD : requires volatile as is target of CAS
  106.45 +  struct slist_element
  106.46 +    *volatile next;
  106.47 +};
  106.48 +
  106.49 +#pragma pack( pop )
  106.50 +
  106.51 +/***** private prototypes *****/
  106.52 +void slist_internal_init_slist( struct slist_state *ss, void (*user_data_delete_function)(void *user_data, void *user_state), void *user_state );
  106.53 +
  106.54 +void slist_internal_link_element_to_head( struct slist_state *slist_state, struct slist_element *volatile se );
  106.55 +void slist_internal_link_element_after_element( struct slist_element *volatile slist_in_list_element, struct slist_element *volatile se );
  106.56 +
  106.57 +void slist_internal_move_to_first_undeleted_element( struct slist_element **se );
  106.58 +
   107.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   107.2 +++ b/liblfds.6/src/slist/slist_link.c	Sun Jan 31 21:28:42 2010 +1100
   107.3 @@ -0,0 +1,53 @@
   107.4 +#include "slist_internal.h"
   107.5 +
   107.6 +
   107.7 +
   107.8 +
   107.9 +
  107.10 +/****************************************************************************/
  107.11 +void slist_internal_link_element_to_head( struct slist_state *ss, struct slist_element *volatile se )
  107.12 +{
  107.13 +  ALIGN(ALIGN_SINGLE_POINTER) struct slist_element
  107.14 +    *se_next;
  107.15 +
  107.16 +  assert( ss != NULL );
  107.17 +  assert( se != NULL );
  107.18 +
  107.19 +  se_next = ss->head;
  107.20 +
  107.21 +  do
  107.22 +  {
  107.23 +    se->next = se_next;
  107.24 +  }
  107.25 +  while( se->next != (se_next = (struct slist_element *) abstraction_cas((volatile atom_t *) &ss->head, (atom_t) se, (atom_t) se->next)) );
  107.26 +
  107.27 +  return;
  107.28 +}
  107.29 +
  107.30 +
  107.31 +
  107.32 +
  107.33 +
  107.34 +/****************************************************************************/
  107.35 +void slist_internal_link_element_after_element( struct slist_element *volatile slist_in_list_element, struct slist_element *volatile se )
  107.36 +{
  107.37 +  ALIGN(ALIGN_SINGLE_POINTER) struct slist_element
  107.38 +    *se_prev,
  107.39 +    *se_next;
  107.40 +
  107.41 +  assert( slist_in_list_element != NULL );
  107.42 +  assert( se != NULL );
  107.43 +
  107.44 +  se_prev = (struct slist_element *) slist_in_list_element;
  107.45 +
  107.46 +  se_next = se_prev->next;
  107.47 +
  107.48 +  do
  107.49 +  {
  107.50 +    se->next = se_next;
  107.51 +  }
  107.52 +  while( se->next != (se_next = (struct slist_element *) abstraction_cas((volatile atom_t *) &se_prev->next, (atom_t) se, (atom_t) se->next)) );
  107.53 +
  107.54 +  return;
  107.55 +}
  107.56 +
   108.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   108.2 +++ b/liblfds.6/src/slist/slist_new.c	Sun Jan 31 21:28:42 2010 +1100
   108.3 @@ -0,0 +1,97 @@
   108.4 +#include "slist_internal.h"
   108.5 +
   108.6 +
   108.7 +
   108.8 +
   108.9 +
  108.10 +/****************************************************************************/
  108.11 +int slist_new( struct slist_state **ss, void (*user_data_delete_function)(void *user_data, void *user_state), void *user_state )
  108.12 +{
  108.13 +  int
  108.14 +    rv = 0;
  108.15 +
  108.16 +  assert( ss != NULL );
  108.17 +  // TRD : user_data_delete_function can be NULL
  108.18 +  // TRD : user_state can be NULL
  108.19 +
  108.20 +  *ss = (struct slist_state *) abstraction_aligned_malloc( sizeof(struct slist_state), ALIGN_SINGLE_POINTER );
  108.21 +
  108.22 +  if( *ss != NULL )
  108.23 +  {
  108.24 +    slist_internal_init_slist( *ss, user_data_delete_function, user_state );
  108.25 +    rv = 1;
  108.26 +  }
  108.27 +
  108.28 +  return( rv );
  108.29 +}
  108.30 +
  108.31 +
  108.32 +
  108.33 +
  108.34 +
  108.35 +/****************************************************************************/
  108.36 +void slist_internal_init_slist( struct slist_state *ss, void (*user_data_delete_function)(void *user_data, void *user_state), void *user_state )
  108.37 +{
  108.38 +  assert( ss != NULL );
  108.39 +  // TRD : user_data_delete_function can be NULL
  108.40 +  // TRD : user_state can be NULL
  108.41 +
  108.42 +  ss->head = NULL;
  108.43 +  ss->user_data_delete_function = user_data_delete_function;
  108.44 +  ss->user_state = user_state;
  108.45 +
  108.46 +  return;
  108.47 +}
  108.48 +
  108.49 +
  108.50 +
  108.51 +
  108.52 +
  108.53 +/****************************************************************************/
  108.54 +struct slist_element *slist_new_head( struct slist_state *ss, void *user_data )
  108.55 +{
  108.56 +  ALIGN(ALIGN_SINGLE_POINTER) struct slist_element
  108.57 +    *volatile se;
  108.58 +
  108.59 +  assert( ss != NULL );
  108.60 +  // TRD : user_data can be NULL
  108.61 +
  108.62 +  se = (struct slist_element *) abstraction_aligned_malloc( sizeof(struct slist_element), ALIGN_DOUBLE_POINTER );
  108.63 +
  108.64 +  if( se != NULL )
  108.65 +  {
  108.66 +    se->user_data_and_flags[SLIST_USER_DATA] = user_data;
  108.67 +    se->user_data_and_flags[SLIST_FLAGS] = SLIST_NO_FLAGS;
  108.68 +
  108.69 +    slist_internal_link_element_to_head( ss, se );
  108.70 +  }
  108.71 +
  108.72 +  return( (struct slist_element *) se );
  108.73 +}
  108.74 +
  108.75 +
  108.76 +
  108.77 +
  108.78 +
  108.79 +/****************************************************************************/
  108.80 +struct slist_element *slist_new_next( struct slist_element *se, void *user_data )
  108.81 +{
  108.82 +  ALIGN(ALIGN_SINGLE_POINTER) struct slist_element
  108.83 +    *volatile se_next;
  108.84 +
  108.85 +  assert( se != NULL );
  108.86 +  // TRD : user_data can be NULL
  108.87 +
  108.88 +  se_next = (struct slist_element *) abstraction_aligned_malloc( sizeof(struct slist_element), ALIGN_DOUBLE_POINTER );
  108.89 +
  108.90 +  if( se_next != NULL )
  108.91 +  {
  108.92 +    se_next->user_data_and_flags[SLIST_USER_DATA] = user_data;
  108.93 +    se_next->user_data_and_flags[SLIST_FLAGS] = SLIST_NO_FLAGS;
  108.94 +
  108.95 +    slist_internal_link_element_after_element( se, se_next );
  108.96 +  }
  108.97 +
  108.98 +  return( (struct slist_element *) se_next );
  108.99 +}
 108.100 +
   109.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   109.2 +++ b/liblfds.6/src/stack/stack_delete.c	Sun Jan 31 21:28:42 2010 +1100
   109.3 @@ -0,0 +1,67 @@
   109.4 +#include "stack_internal.h"
   109.5 +
   109.6 +
   109.7 +
   109.8 +
   109.9 +
  109.10 +/****************************************************************************/
  109.11 +void stack_delete( struct stack_state *ss, void (*user_data_delete_function)(void *user_data, void *user_state), void *user_state )
  109.12 +{
  109.13 +  void
  109.14 +    *user_data;
  109.15 +
  109.16 +  assert( ss != NULL );
  109.17 +  // TRD : user_data_delete_function can be NULL
  109.18 +  // TRD : user_state can be NULL
  109.19 +
  109.20 +  while( stack_pop(ss, &user_data) )
  109.21 +    if( user_data_delete_function != NULL )
  109.22 +      user_data_delete_function( user_data, user_state );
  109.23 +
  109.24 +  freelist_delete( ss->fs, stack_internal_freelist_delete_function, NULL );
  109.25 +
  109.26 +  abstraction_aligned_free( ss );
  109.27 +
  109.28 +  return;
  109.29 +}
  109.30 +
  109.31 +
  109.32 +
  109.33 +
  109.34 +
  109.35 +/****************************************************************************/
  109.36 +void stack_clear( struct stack_state *ss, void (*user_data_clear_function)(void *user_data, void *user_state), void *user_state )
  109.37 +{
  109.38 +  void
  109.39 +    *user_data;
  109.40 +
  109.41 +  assert( ss != NULL );
  109.42 +  // TRD : user_data_clear_function can be NULL
  109.43 +  // TRD : user_state can be NULL
  109.44 +
  109.45 +  while( stack_pop(ss, &user_data) )
  109.46 +    if( user_data_clear_function != NULL )
  109.47 +      user_data_clear_function( user_data, user_state );
  109.48 +
  109.49 +  return;
  109.50 +}
  109.51 +
  109.52 +
  109.53 +
  109.54 +
  109.55 +
  109.56 +/****************************************************************************/
  109.57 +#pragma warning( disable : 4100 )
  109.58 +
  109.59 +void stack_internal_freelist_delete_function( void *user_data, void *user_state )
  109.60 +{
  109.61 +  assert( user_data != NULL );
  109.62 +  assert( user_state == NULL );
  109.63 +
  109.64 +  abstraction_aligned_free( user_data );
  109.65 +
  109.66 +  return;
  109.67 +}
  109.68 +
  109.69 +#pragma warning( default : 4100 )
  109.70 +
   110.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   110.2 +++ b/liblfds.6/src/stack/stack_internal.h	Sun Jan 31 21:28:42 2010 +1100
   110.3 @@ -0,0 +1,50 @@
   110.4 +/***** the library wide include file *****/
   110.5 +#include "liblfds_internal.h"
   110.6 +
   110.7 +/***** pragmas *****/
   110.8 +
   110.9 +/***** defines *****/
  110.10 +#define STACK_POINTER 0
  110.11 +#define STACK_COUNTER 1
  110.12 +#define STACK_PAC_SIZE 2
  110.13 +
  110.14 +/***** structures *****/
  110.15 +#pragma pack( push, ALIGN_DOUBLE_POINTER )
  110.16 +
  110.17 +struct stack_state
  110.18 +{
  110.19 +  // TRD : must come first for alignment
  110.20 +  struct stack_element
  110.21 +    *volatile top[STACK_PAC_SIZE];
  110.22 +
  110.23 +  atom_t
  110.24 +    aba_counter;
  110.25 +
  110.26 +  struct freelist_state
  110.27 +    *fs;
  110.28 +};
  110.29 +
  110.30 +struct stack_element
  110.31 +{
  110.32 +  struct stack_element
  110.33 +    *next[STACK_PAC_SIZE];
  110.34 +
  110.35 +  struct freelist_element
  110.36 +    *fe;
  110.37 +
  110.38 +  void
  110.39 +    *user_data;
  110.40 +};
  110.41 +
  110.42 +#pragma pack( pop )
  110.43 +
  110.44 +/***** private prototypes *****/
  110.45 +int stack_internal_freelist_init_function( void **user_data, void *user_state );
  110.46 +void stack_internal_freelist_delete_function( void *user_data, void *user_state );
  110.47 +
  110.48 +void stack_internal_new_element_from_freelist( struct stack_state *ss, struct stack_element *se[STACK_PAC_SIZE], void *user_data );
  110.49 +void stack_internal_new_element( struct stack_state *ss, struct stack_element *se[STACK_PAC_SIZE], void *user_data );
  110.50 +void stack_internal_init_element( struct stack_state *ss, struct stack_element *se[STACK_PAC_SIZE], struct freelist_element *fe, void *user_data );
  110.51 +
  110.52 +void stack_internal_push( struct stack_state *ss, struct stack_element *se[STACK_PAC_SIZE] );
  110.53 +
   111.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   111.2 +++ b/liblfds.6/src/stack/stack_new.c	Sun Jan 31 21:28:42 2010 +1100
   111.3 @@ -0,0 +1,139 @@
   111.4 +#include "stack_internal.h"
   111.5 +
   111.6 +
   111.7 +
   111.8 +
   111.9 +
  111.10 +/****************************************************************************/
  111.11 +int stack_new( struct stack_state **ss, atom_t number_elements )
  111.12 +{
  111.13 +  int
  111.14 +    rv = 0;
  111.15 +
  111.16 +  assert( ss != NULL );
  111.17 +  // TRD : number_elements can be any value in its range
  111.18 +
  111.19 +  *ss = (struct stack_state *) abstraction_aligned_malloc( sizeof(struct stack_state), ALIGN_DOUBLE_POINTER );
  111.20 +
  111.21 +  if( *ss != NULL )
  111.22 +  {
  111.23 +    // TRD : the size of the freelist is the size of the stack
  111.24 +    freelist_new( &(*ss)->fs, number_elements, stack_internal_freelist_init_function, NULL );
  111.25 +
  111.26 +    if( (*ss)->fs == NULL )
  111.27 +    {
  111.28 +      abstraction_aligned_free( *ss );
  111.29 +      *ss = NULL;
  111.30 +    }
  111.31 +
  111.32 +    if( (*ss)->fs != NULL )
  111.33 +    {
  111.34 +      (*ss)->top[STACK_POINTER] = NULL;
  111.35 +      (*ss)->top[STACK_COUNTER] = 0;
  111.36 +      (*ss)->aba_counter = 0;
  111.37 +      rv = 1;
  111.38 +    }
  111.39 +  }
  111.40 +
  111.41 +  return( rv );
  111.42 +}
  111.43 +
  111.44 +
  111.45 +
  111.46 +
  111.47 +
  111.48 +/****************************************************************************/
  111.49 +#pragma warning( disable : 4100 )
  111.50 +
  111.51 +int stack_internal_freelist_init_function( void **user_data, void *user_state )
  111.52 +{
  111.53 +  int
  111.54 +    rv = 0;
  111.55 +
  111.56 +  assert( user_data != NULL );
  111.57 +  assert( user_state == NULL );
  111.58 +
  111.59 +  *user_data = abstraction_aligned_malloc( sizeof(struct stack_element), ALIGN_DOUBLE_POINTER );
  111.60 +
  111.61 +  if( *user_data != NULL )
  111.62 +    rv = 1;
  111.63 +
  111.64 +  return( rv );
  111.65 +}
  111.66 +
  111.67 +#pragma warning( default : 4100 )
  111.68 +
  111.69 +
  111.70 +
  111.71 +
  111.72 +
  111.73 +/****************************************************************************/
  111.74 +void stack_internal_new_element_from_freelist( struct stack_state *ss, struct stack_element *se[STACK_PAC_SIZE], void *user_data )
  111.75 +{
  111.76 +  struct freelist_element
  111.77 +    *fe;
  111.78 +
  111.79 +  assert( ss != NULL );
  111.80 +  assert( se != NULL );
  111.81 +  // TRD : user_data can be any value in its range
  111.82 +
  111.83 +  freelist_pop( ss->fs, &fe );
  111.84 +
  111.85 +  if( fe == NULL )
  111.86 +    se[STACK_POINTER] = NULL;
  111.87 +
  111.88 +  if( fe != NULL )
  111.89 +    stack_internal_init_element( ss, se, fe, user_data );
  111.90 +
  111.91 +  return;
  111.92 +}
  111.93 +
  111.94 +
  111.95 +
  111.96 +
  111.97 +
  111.98 +/****************************************************************************/
  111.99 +void stack_internal_new_element( struct stack_state *ss, struct stack_element *se[STACK_PAC_SIZE], void *user_data )
 111.100 +{
 111.101 +  struct freelist_element
 111.102 +    *fe;
 111.103 +
 111.104 +  assert( ss != NULL );
 111.105 +  assert( se != NULL );
 111.106 +  // TRD : user_data can be any value in its range
 111.107 +
 111.108 +  freelist_guaranteed_pop( ss->fs, &fe );
 111.109 +
 111.110 +  if( fe == NULL )
 111.111 +    se[STACK_POINTER] = NULL;
 111.112 +
 111.113 +  if( fe != NULL )
 111.114 +    stack_internal_init_element( ss, se, fe, user_data );
 111.115 +
 111.116 +  return;
 111.117 +}
 111.118 +
 111.119 +
 111.120 +
 111.121 +
 111.122 +
 111.123 +/****************************************************************************/
 111.124 +void stack_internal_init_element( struct stack_state *ss, struct stack_element *se[STACK_PAC_SIZE], struct freelist_element *fe, void *user_data )
 111.125 +{
 111.126 +  assert( ss != NULL );
 111.127 +  assert( se != NULL );
 111.128 +  assert( fe != NULL );
 111.129 +  // TRD : user_data can be any value in its range
 111.130 +
 111.131 +  freelist_get_user_data_from_element( fe, (void **) &se[STACK_POINTER] );
 111.132 +
 111.133 +  se[STACK_COUNTER] = (struct stack_element *) abstraction_increment( (atom_t *) &ss->aba_counter );
 111.134 +
 111.135 +  se[STACK_POINTER]->next[STACK_POINTER] = NULL;
 111.136 +  se[STACK_POINTER]->next[STACK_COUNTER] = 0;
 111.137 +  se[STACK_POINTER]->fe = fe;
 111.138 +  se[STACK_POINTER]->user_data = user_data;
 111.139 +
 111.140 +  return;
 111.141 +}
 111.142 +
   112.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   112.2 +++ b/liblfds.6/src/stack/stack_push_pop.c	Sun Jan 31 21:28:42 2010 +1100
   112.3 @@ -0,0 +1,110 @@
   112.4 +#include "stack_internal.h"
   112.5 +
   112.6 +
   112.7 +
   112.8 +
   112.9 +
  112.10 +/****************************************************************************/
  112.11 +int stack_push( struct stack_state *ss, void *user_data )
  112.12 +{
  112.13 +  ALIGN(ALIGN_DOUBLE_POINTER) struct stack_element
  112.14 +    *se[STACK_PAC_SIZE];
  112.15 +
  112.16 +  assert( ss != NULL );
  112.17 +  // TRD : user_data can be NULL
  112.18 +
  112.19 +  stack_internal_new_element_from_freelist( ss, se, user_data );
  112.20 +
  112.21 +  if( se[STACK_POINTER] == NULL )
  112.22 +    return( 0 );
  112.23 +
  112.24 +  stack_internal_push( ss, se );
  112.25 +
  112.26 +  return( 1 );
  112.27 +}
  112.28 +
  112.29 +
  112.30 +
  112.31 +
  112.32 +
  112.33 +/****************************************************************************/
  112.34 +int stack_guaranteed_push( struct stack_state *ss, void *user_data )
  112.35 +{
  112.36 +  ALIGN(ALIGN_DOUBLE_POINTER) struct stack_element
  112.37 +    *se[STACK_PAC_SIZE];
  112.38 +
  112.39 +  assert( ss != NULL );
  112.40 +  // TRD : user_data can be NULL
  112.41 +
  112.42 +  /* TRD : this function allocated a new freelist element and uses that
  112.43 +           to push onto the stack, guaranteeing success (unless malloc()
  112.44 +           fails of course)
  112.45 +  */
  112.46 +
  112.47 +  stack_internal_new_element( ss, se, user_data );
  112.48 +
  112.49 +  // TRD : malloc failed
  112.50 +  if( se[STACK_POINTER] == NULL )
  112.51 +    return( 0 );
  112.52 +
  112.53 +  stack_internal_push( ss, se );
  112.54 +
  112.55 +  return( 1 );
  112.56 +}
  112.57 +
  112.58 +
  112.59 +
  112.60 +
  112.61 +
  112.62 +/****************************************************************************/
  112.63 +void stack_internal_push( struct stack_state *ss, struct stack_element *se[STACK_PAC_SIZE] )
  112.64 +{
  112.65 +  ALIGN(ALIGN_DOUBLE_POINTER) struct stack_element
  112.66 +    *original_se_next[STACK_PAC_SIZE];
  112.67 +
  112.68 +  assert( ss != NULL );
  112.69 +  assert( se != NULL );
  112.70 +
  112.71 +  original_se_next[STACK_POINTER] = ss->top[STACK_POINTER];
  112.72 +  original_se_next[STACK_COUNTER] = ss->top[STACK_COUNTER];
  112.73 +
  112.74 +  do
  112.75 +  {
  112.76 +    se[STACK_POINTER]->next[STACK_POINTER] = original_se_next[STACK_POINTER];
  112.77 +    se[STACK_POINTER]->next[STACK_COUNTER] = original_se_next[STACK_COUNTER];
  112.78 +  }
  112.79 +  while( 0 == abstraction_dcas((volatile atom_t *) ss->top, (atom_t *) se, (atom_t *) original_se_next) );
  112.80 +
  112.81 +  return;
  112.82 +}
  112.83 +
  112.84 +
  112.85 +
  112.86 +
  112.87 +
  112.88 +/****************************************************************************/
  112.89 +int stack_pop( struct stack_state *ss, void **user_data )
  112.90 +{
  112.91 +  ALIGN(ALIGN_DOUBLE_POINTER) struct stack_element
  112.92 +    *se[STACK_PAC_SIZE];
  112.93 +
  112.94 +  assert( ss != NULL );
  112.95 +  assert( user_data != NULL );
  112.96 +
  112.97 +  se[STACK_COUNTER] = ss->top[STACK_COUNTER];
  112.98 +  se[STACK_POINTER] = ss->top[STACK_POINTER];
  112.99 +
 112.100 +  do
 112.101 +  {
 112.102 +    if( se[STACK_POINTER] == NULL )
 112.103 +      return( 0 );
 112.104 +  }
 112.105 +  while( 0 == abstraction_dcas((volatile atom_t *) ss->top, (atom_t *) se[STACK_POINTER]->next, (atom_t *) se) );
 112.106 +
 112.107 +  *user_data = se[STACK_POINTER]->user_data;
 112.108 +
 112.109 +  freelist_push( ss->fs, se[STACK_POINTER]->fe );
 112.110 +
 112.111 +  return( 1 );
 112.112 +}
 112.113 +
   113.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   113.2 +++ b/liblfds.6/src/stack/stack_query.c	Sun Jan 31 21:28:42 2010 +1100
   113.3 @@ -0,0 +1,30 @@
   113.4 +#include "stack_internal.h"
   113.5 +
   113.6 +
   113.7 +
   113.8 +
   113.9 +
  113.10 +/****************************************************************************/
  113.11 +#pragma warning( disable : 4100 )
  113.12 +
  113.13 +void stack_query( struct stack_state *ss, enum stack_query_type query_type, void *query_input, void *query_output )
  113.14 +{
  113.15 +  assert( ss != NULL );
  113.16 +  // TRD : query_type can be any value in its range
  113.17 +  // TRD : query_iput can be NULL
  113.18 +  assert( query_output != NULL );
  113.19 +
  113.20 +  switch( query_type )
  113.21 +  {
  113.22 +    case STACK_QUERY_ELEMENT_COUNT:
  113.23 +      assert( query_input == NULL );
  113.24 +
  113.25 +      freelist_query( ss->fs, FREELIST_QUERY_ELEMENT_COUNT, NULL, query_output );
  113.26 +    break;
  113.27 +  }
  113.28 +
  113.29 +  return;
  113.30 +}
  113.31 +
  113.32 +#pragma warning( default : 4100 )
  113.33 +
   114.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   114.2 +++ b/liblfds.6/test/buildchk_wnet_x86.log	Sun Jan 31 21:28:42 2010 +1100
   114.3 @@ -0,0 +1,1 @@
   114.4 +BUILD: Computing Include file dependencies:
   115.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   115.2 +++ b/liblfds.6/test/building.txt	Sun Jan 31 21:28:42 2010 +1100
   115.3 @@ -0,0 +1,25 @@
   115.4 +building test
   115.5 +=============
   115.6 +
   115.7 +Windows (user-mode)
   115.8 +===================
   115.9 +1. Use Microsoft Visual Studio 2008 or Visual C++ 2008 Express Edition
  115.10 +   to load "test.sln".
  115.11 +
  115.12 +2. Use Microsoft Windows SDK and GNUmake to run makefile.windows (obviously
  115.13 +   you'll need to have run the appropriate vcvars*.bat first; you can build
  115.14 +   for both IA64, 64-bit and 32-bit - just run the correct vcvars batch file).
  115.15 +
  115.16 +   Targets are "rel", "dbg" and "clean".  You need to clean between switching
  115.17 +   targets.
  115.18 +
  115.19 +Windows (kernel)
  115.20 +================
  115.21 +No build supported, since this is a command line utility.
  115.22 +
  115.23 +Linux
  115.24 +=====
  115.25 +Use GNUmake to run "makefile.linux".  Targets are "rel", "dbg" and
  115.26 +"clean".  You need to clean between switching targets.
  115.27 +
  115.28 +
   116.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   116.2 +++ b/liblfds.6/test/makefile.linux	Sun Jan 31 21:28:42 2010 +1100
   116.3 @@ -0,0 +1,81 @@
   116.4 +##### paths #####
   116.5 +BINDIR = bin
   116.6 +INCDIR = ../inc
   116.7 +LIBDIR = ../bin
   116.8 +OBJDIR = obj
   116.9 +SRCDIR = src
  116.10 +
  116.11 +##### misc #####
  116.12 +QUIETLY = 1>nul 2>nul
  116.13 +
  116.14 +##### sources, objects and libraries #####
  116.15 +BINNAME = test
  116.16 +BINARY  = $(BINDIR)/$(BINNAME)
  116.17 +SRCDIRS = .
  116.18 +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
  116.19 +OBJECTS = $(patsubst %.c,$(OBJDIR)/%.o,$(notdir $(SOURCES)))
  116.20 +SYSLIBS = -lpthread -lc -lm
  116.21 +USRLIBS = -llfds
  116.22 +
  116.23 +##### CPU variants #####
  116.24 +GCCARCH = $(shell uname -m)
  116.25 +
  116.26 +ifeq ($(GCCARCH),x86_64)
  116.27 +  GCCARCH = core2
  116.28 +endif
  116.29 +
  116.30 +ifeq ($(findstring arm,$(GCCARCH)),arm)
  116.31 +  GCCARCH = armv6k
  116.32 +endif
  116.33 +
  116.34 +##### tools #####
  116.35 +MAKE    = make
  116.36 +MFLAGS  = 
  116.37 +
  116.38 +DG      = gcc
  116.39 +DGFLAGS = -MM -std=c99 -I"$(SRCDIR)" -I"$(INCDIR)" 
  116.40 +
  116.41 +CC      = gcc
  116.42 +CFBASE  = -Wall -Wno-unknown-pragmas -std=c99 -march=$(GCCARCH) -c -I"$(SRCDIR)" -I"$(INCDIR)"
  116.43 +CFREL   = -O2 -Wno-strict-aliasing
  116.44 +CFDBG   = -O0 -g
  116.45 +
  116.46 +LD      = gcc
  116.47 +LFBASE  = -L"$(LIBDIR)"
  116.48 +LFREL   = -O2 -s
  116.49 +LFDBG   = -O0 -g
  116.50 +
  116.51 +##### variants #####
  116.52 +CFLAGS  = $(CFBASE) $(CFDBG)
  116.53 +LFLAGS  = $(LFBASE) $(LFDBG)
  116.54 +
  116.55 +ifeq ($(MAKECMDGOALS),rel)
  116.56 +  CFLAGS  = $(CFBASE) $(CFREL)
  116.57 +  LFLAGS  = $(LFBASE) $(LFREL)
  116.58 +endif
  116.59 +
  116.60 +##### search paths #####
  116.61 +vpath %.c $(patsubst %,$(SRCDIR)/%:,$(SRCDIRS))
  116.62 +
  116.63 +##### implicit rules #####
  116.64 +$(OBJDIR)/%.o : %.c
  116.65 +	$(DG) $(DGFLAGS) $< >$(OBJDIR)/$*.d
  116.66 +	$(CC) $(CFLAGS) -o $@ $<
  116.67 +
  116.68 +##### explicit rules #####
  116.69 +$(BINARY) : $(OBJECTS)
  116.70 +	$(LD) -o $(BINARY) $(LFLAGS) $(OBJECTS) $(USRLIBS) $(SYSLIBS)
  116.71 +	chmod +x $(BINARY)
  116.72 +
  116.73 +##### phony #####
  116.74 +.PHONY : clean rel dbg
  116.75 +
  116.76 +clean : 
  116.77 +	@rm -f $(BINDIR)/$(BINNAME) $(OBJDIR)/*.o $(OBJDIR)/*.d
  116.78 +
  116.79 +rel : $(BINARY)
  116.80 +dbg : $(BINARY)
  116.81 +
  116.82 +##### dependencies #####
  116.83 +-include $(DEPENDS)
  116.84 +
   117.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   117.2 +++ b/liblfds.6/test/makefile.windows	Sun Jan 31 21:28:42 2010 +1100
   117.3 @@ -0,0 +1,64 @@
   117.4 +##### paths #####
   117.5 +BINDIR = bin
   117.6 +INCDIR = ../inc
   117.7 +LIBDIR = ../bin
   117.8 +OBJDIR = obj
   117.9 +SRCDIR = src
  117.10 +
  117.11 +##### misc #####
  117.12 +QUIETLY = 1>nul 2>nul
  117.13 +
  117.14 +##### sources, objects and libraries #####
  117.15 +BINNAME = test
  117.16 +BINARY  = $(BINDIR)\$(BINNAME).exe
  117.17 +SRCDIRS = .
  117.18 +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
  117.19 +OBJECTS = $(patsubst %.c,$(OBJDIR)/%.obj,$(notdir $(SOURCES)))
  117.20 +SYSLIBS = kernel32.lib
  117.21 +USRLIBS = liblfds.lib
  117.22 +
  117.23 +##### tools #####
  117.24 +MAKE    = make
  117.25 +MFLAGS  = 
  117.26 +
  117.27 +CC      = cl
  117.28 +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
  117.29 +CFREL   = /Ox /DNDEBUG /MT
  117.30 +CFDBG   = /Od /Gm /Zi /D_DEBUG /MTd
  117.31 +
  117.32 +LD      = link
  117.33 +LFBASE  = "/libpath:$(LIB)" "/libpath:$(LIBDIR)" /nologo /subsystem:console /nodefaultlib /nxcompat /wx
  117.34 +LFREL   = /incremental:no
  117.35 +LFDBG   = /debug "/pdb:$(BINDIR)\$(BINNAME).pdb"
  117.36 +
  117.37 +##### variants #####
  117.38 +CFLAGS  = $(CFBASE) $(CFDBG)
  117.39 +LFLAGS  = $(LFBASE) $(LFDBG)
  117.40 +CLIB    = libcmtd.lib
  117.41 +
  117.42 +ifeq ($(MAKECMDGOALS),rel)
  117.43 +  CFLAGS  = $(CFBASE) $(CFREL)
  117.44 +  LFLAGS  = $(LFBASE) $(LFREL)
  117.45 +  CLIB    = libcmt.lib
  117.46 +endif
  117.47 +
  117.48 +##### search paths #####
  117.49 +vpath %.c $(patsubst %,$(SRCDIR)/%;,$(SRCDIRS))
  117.50 +
  117.51 +##### implicit rules #####
  117.52 +$(OBJDIR)/%.obj : %.c
  117.53 +	$(CC) $(CFLAGS) "/Fo$@" $<
  117.54 +
  117.55 +##### explicit rules #####
  117.56 +$(BINARY) : $(OBJECTS)
  117.57 +	$(LD) $(LFLAGS) $(CLIB) $(SYSLIBS) $(USRLIBS) $(OBJECTS) /out:$(BINARY)
  117.58 +
  117.59 +##### phony #####
  117.60 +.PHONY : clean rel dbg
  117.61 +
  117.62 +clean : 
  117.63 +	@erase /Q $(OBJDIR)\*.obj $(BINDIR)\$(BINNAME).* $(QUIETLY)
  117.64 +
  117.65 +rel : $(BINARY)
  117.66 +dbg : $(BINARY)
  117.67 +
   118.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   118.2 +++ b/liblfds.6/test/src/abstraction.h	Sun Jan 31 21:28:42 2010 +1100
   118.3 @@ -0,0 +1,50 @@
   118.4 +/***** defines *****/
   118.5 +#if (defined _WIN32 && defined _MSC_VER && !defined WIN_KERNEL_BUILD)
   118.6 +  /* TRD : any Windows (user-mode) on any CPU with the Microsoft C compiler
   118.7 +
   118.8 +           _WIN32             indicates 64-bit or 32-bit Windows
   118.9 +           _MSC_VER           indicates Microsoft C compiler
  118.10 +           !WIN_KERNEL_BUILD  indicates Windows user-mode
  118.11 +  */
  118.12 +
  118.13 +  #include <windows.h>
  118.14 +  typedef HANDLE              thread_state_t;
  118.15 +  typedef DWORD               thread_return_t;
  118.16 +  #define CALLING_CONVENTION  WINAPI
  118.17 +#endif
  118.18 +
  118.19 +#if (defined _WIN32 && defined _MSC_VER && defined WIN_KERNEL_BUILD)
  118.20 +  /* TRD : any Windows (kernel-mode) on any CPU with the Microsoft C compiler
  118.21 +
  118.22 +           _WIN32            indicates 64-bit or 32-bit Windows
  118.23 +           _MSC_VER          indicates Microsoft C compiler
  118.24 +           WIN_KERNEL_BUILD  indicates Windows kernel
  118.25 +  */
  118.26 +
  118.27 +  #include <wdm.h>
  118.28 +  typedef HANDLE              thread_state_t;
  118.29 +  typedef VOID                thread_return_t;
  118.30 +  #define CALLING_CONVENTION  
  118.31 +#endif
  118.32 +
  118.33 +#if (defined __unix__ && __GNUC__)
  118.34 +  /* TRD : any UNIX on any CPU with GCC
  118.35 +
  118.36 +           __unix__   indicates Solaris, Linux, HPUX, etc
  118.37 +           __GNUC__   indicates GCC
  118.38 +  */
  118.39 +
  118.40 +  #include <unistd.h>
  118.41 +  #include <pthread.h>
  118.42 +  typedef pthread_t           thread_state_t;
  118.43 +  typedef void *              thread_return_t;
  118.44 +  #define CALLING_CONVENTION  
  118.45 +#endif
  118.46 +
  118.47 +typedef thread_return_t (CALLING_CONVENTION *thread_function_t)( void *thread_user_state );
  118.48 +
  118.49 +/***** public prototypes *****/
  118.50 +unsigned int abstraction_cpu_count( void );
  118.51 +int abstraction_thread_start( thread_state_t *thread_state, unsigned int cpu, thread_function_t thread_function, void *thread_user_state );
  118.52 +void abstraction_thread_wait( thread_state_t thread_state );
  118.53 +
   119.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   119.2 +++ b/liblfds.6/test/src/abstraction_cpu_count.c	Sun Jan 31 21:28:42 2010 +1100
   119.3 @@ -0,0 +1,81 @@
   119.4 +#include "internal.h"
   119.5 +
   119.6 +
   119.7 +
   119.8 +
   119.9 +
  119.10 +/****************************************************************************/
  119.11 +#if (defined _WIN32 && defined _MSC_VER && !defined WIN_KERNEL_BUILD)
  119.12 +
  119.13 +  /* TRD : any Windows (user-mode) on any CPU with the Microsoft C compiler
  119.14 +
  119.15 +           _WIN32             indicates 64-bit or 32-bit Windows
  119.16 +           _MSC_VER           indicates Microsoft C compiler
  119.17 +           !WIN_KERNEL_BUILD  indicates Windows user-mode
  119.18 +  */
  119.19 +
  119.20 +  unsigned int abstraction_cpu_count()
  119.21 +  {
  119.22 +    SYSTEM_INFO
  119.23 +      si;
  119.24 +
  119.25 +    GetNativeSystemInfo( &si );
  119.26 +
  119.27 +    return( (unsigned int) si.dwNumberOfProcessors );
  119.28 +  }
  119.29 +
  119.30 +#endif
  119.31 +
  119.32 +
  119.33 +
  119.34 +
  119.35 +
  119.36 +/****************************************************************************/
  119.37 +#if (defined _WIN32 && defined _MSC_VER && defined WIN_KERNEL_BUILD)
  119.38 +
  119.39 +  /* TRD : any Windows on any CPU with the Microsoft C compiler
  119.40 +
  119.41 +           _WIN32            indicates 64-bit or 32-bit Windows
  119.42 +           _MSC_VER          indicates Microsoft C compiler
  119.43 +           WIN_KERNEL_BUILD  indicates Windows kernel
  119.44 +  */
  119.45 +
  119.46 +  unsigned int abstraction_cpu_count()
  119.47 +  {
  119.48 +    unsigned int
  119.49 +      active_processor_count;
  119.50 +
  119.51 +    active_processor_count = KeQueryActiveProcessorCount( NULL );
  119.52 +
  119.53 +    return( active_processor_count );
  119.54 +  }
  119.55 +
  119.56 +#endif
  119.57 +
  119.58 +
  119.59 +
  119.60 +
  119.61 +
  119.62 +/****************************************************************************/
  119.63 +#if (defined __linux__ && __GNUC__)
  119.64 +
  119.65 +  /* TRD : Linux on any CPU with GCC
  119.66 +
  119.67 +           this function I believe is Linux specific and varies by UNIX flavour
  119.68 +
  119.69 +           __linux__  indicates Linux
  119.70 +           __GNUC__   indicates GCC
  119.71 +  */
  119.72 +
  119.73 +  unsigned int abstraction_cpu_count()
  119.74 +  {
  119.75 +    long int
  119.76 +      cpu_count;
  119.77 +
  119.78 +    cpu_count = sysconf( _SC_NPROCESSORS_ONLN );
  119.79 +
  119.80 +    return( (unsigned int) cpu_count );
  119.81 +  }
  119.82 +
  119.83 +#endif
  119.84 +
   120.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   120.2 +++ b/liblfds.6/test/src/abstraction_thread_start.c	Sun Jan 31 21:28:42 2010 +1100
   120.3 @@ -0,0 +1,127 @@
   120.4 +#include "internal.h"
   120.5 +
   120.6 +
   120.7 +
   120.8 +
   120.9 +
  120.10 +/****************************************************************************/
  120.11 +#if (defined _WIN32 && defined _MSC_VER && !defined WIN_KERNEL_BUILD)
  120.12 +
  120.13 +  /* TRD : any Windows (user-mode) on any CPU with the Microsoft C compiler
  120.14 +
  120.15 +           _WIN32             indicates 64-bit or 32-bit Windows
  120.16 +           _MSC_VER           indicates Microsoft C compiler
  120.17 +           !WIN_KERNEL_BUILD  indicates Windows user-mode
  120.18 +  */
  120.19 +
  120.20 +  int abstraction_thread_start( thread_state_t *thread_state, unsigned int cpu, thread_function_t thread_function, void *thread_user_state )
  120.21 +  {
  120.22 +    int
  120.23 +      rv = 0;
  120.24 +
  120.25 +    DWORD
  120.26 +      thread_id;
  120.27 +
  120.28 +    DWORD_PTR
  120.29 +      affinity_mask,
  120.30 +      result;
  120.31 +
  120.32 +    assert( thread_state != NULL );
  120.33 +    // TRD : cpu can be any value in its range
  120.34 +    assert( thread_function != NULL );
  120.35 +    // TRD : thread_user_state can be NULL
  120.36 +
  120.37 +    affinity_mask = (DWORD_PTR) (1 << cpu);
  120.38 +
  120.39 +    *thread_state = CreateThread( NULL, 0, thread_function, thread_user_state, NO_FLAGS, &thread_id );
  120.40 +
  120.41 +    result = SetThreadAffinityMask( *thread_state, affinity_mask );
  120.42 +
  120.43 +    if( *thread_state != NULL and result != 0 )
  120.44 +      rv = 1;
  120.45 +
  120.46 +    return( rv );
  120.47 +  }
  120.48 +
  120.49 +#endif
  120.50 +
  120.51 +
  120.52 +
  120.53 +
  120.54 +
  120.55 +/****************************************************************************/
  120.56 +#if (defined _WIN32 && defined _MSC_VER && defined WIN_KERNEL_BUILD)
  120.57 +
  120.58 +  /* TRD : any Windows on any CPU with the Microsoft C compiler
  120.59 +
  120.60 +           _WIN32            indicates 64-bit or 32-bit Windows
  120.61 +           _MSC_VER          indicates Microsoft C compiler
  120.62 +           WIN_KERNEL_BUILD  indicates Windows kernel
  120.63 +  */
  120.64 +
  120.65 +  int abstraction_thread_start( thread_state_t *thread_state, unsigned int cpu, thread_function_t thread_function, void *thread_user_state )
  120.66 +  {
  120.67 +    int
  120.68 +      rv = 0;
  120.69 +
  120.70 +    KAFFINITY
  120.71 +      affinity_mask
  120.72 +
  120.73 +    NTSTATUS
  120.74 +      nts_create,
  120.75 +      nts_affinity;
  120.76 +
  120.77 +    assert( thread_state != NULL );
  120.78 +    // TRD : cpu can be any value in its range
  120.79 +    assert( thread_function != NULL );
  120.80 +    // TRD : thread_user_state can be NULL
  120.81 +
  120.82 +    affinity_mask = 1 << cpu;
  120.83 +
  120.84 +    nts_create = PsCreateSystemThread( thread_state, THREAD_ALL_ACCESS, NULL, NULL, NULL, thread_function, thread_user_state );
  120.85 +
  120.86 +    nts_affinity = ZwSetInformationThread( thread_state, ThreadAffinityMask, &affinity_mask, sizeof(KAFFINITY) );
  120.87 +
  120.88 +    if( nts_create == STATUS_SUCCESS and nts_affinity == STATUS_SUCCESS )
  120.89 +      rv = 1;
  120.90 +
  120.91 +    return( rv );
  120.92 +  }
  120.93 +
  120.94 +#endif
  120.95 +
  120.96 +
  120.97 +
  120.98 +
  120.99 +
 120.100 +/****************************************************************************/
 120.101 +#if (defined __unix__)
 120.102 +
 120.103 +  /* TRD : any UNIX on any CPU with any compiler
 120.104 +
 120.105 +           I assumed pthreads is available on any UNIX.
 120.106 +
 120.107 +           __unix__   indicates Solaris, Linux, HPUX, etc
 120.108 +  */
 120.109 +
 120.110 +  int abstraction_thread_start( thread_state_t *thread_state, unsigned int cpu, thread_function_t thread_function, void *thread_user_state )
 120.111 +  {
 120.112 +    int
 120.113 +      rv = 0,
 120.114 +      rv_create;
 120.115 +
 120.116 +    assert( thread_state != NULL );
 120.117 +    // TRD : cpu can be any value in its range
 120.118 +    assert( thread_function != NULL );
 120.119 +    // TRD : thread_user_state can be NULL
 120.120 +
 120.121 +    rv_create = pthread_create( thread_state, NULL, thread_function, thread_user_state );
 120.122 +
 120.123 +    if( rv_create == 0 )
 120.124 +      rv = 1;
 120.125 +
 120.126 +    return( rv );
 120.127 +  }
 120.128 +
 120.129 +#endif
 120.130 +
   121.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   121.2 +++ b/liblfds.6/test/src/abstraction_thread_wait.c	Sun Jan 31 21:28:42 2010 +1100
   121.3 @@ -0,0 +1,71 @@
   121.4 +#include "internal.h"
   121.5 +
   121.6 +
   121.7 +
   121.8 +
   121.9 +
  121.10 +/****************************************************************************/
  121.11 +#if (defined _WIN32 && defined _MSC_VER && !defined WIN_KERNEL_BUILD)
  121.12 +
  121.13 +  /* TRD : any Windows (user-mode) on any CPU with the Microsoft C compiler
  121.14 +
  121.15 +           _WIN32             indicates 64-bit or 32-bit Windows
  121.16 +           _MSC_VER           indicates Microsoft C compiler
  121.17 +           !WIN_KERNEL_BUILD  indicates Windows user-mode
  121.18 +  */
  121.19 +
  121.20 +  void abstraction_thread_wait( thread_state_t thread_state )
  121.21 +  {
  121.22 +    WaitForSingleObject( thread_state, INFINITE );
  121.23 +
  121.24 +    return;
  121.25 +  }
  121.26 +
  121.27 +#endif
  121.28 +
  121.29 +
  121.30 +
  121.31 +
  121.32 +
  121.33 +/****************************************************************************/
  121.34 +#if (defined _WIN32 && defined _MSC_VER && defined WIN_KERNEL_BUILD)
  121.35 +
  121.36 +  /* TRD : any Windows on any CPU with the Microsoft C compiler
  121.37 +
  121.38 +           _WIN32            indicates 64-bit or 32-bit Windows
  121.39 +           _MSC_VER          indicates Microsoft C compiler
  121.40 +           WIN_KERNEL_BUILD  indicates Windows kernel
  121.41 +  */
  121.42 +
  121.43 +  void abstraction_thread_wait( thread_state_t thread_state )
  121.44 +  {
  121.45 +    KeWaitForSingleObject( thread_state, Executive, KernelMode, FALSE, NULL );
  121.46 +
  121.47 +    return;
  121.48 +  }
  121.49 +
  121.50 +#endif
  121.51 +
  121.52 +
  121.53 +
  121.54 +
  121.55 +
  121.56 +/****************************************************************************/
  121.57 +#if (defined __unix__)
  121.58 +
  121.59 +  /* TRD : any UNIX on any CPU with any compiler
  121.60 +
  121.61 +           I assumed pthreads is available on any UNIX.
  121.62 +
  121.63 +           __unix__   indicates Solaris, Linux, HPUX, etc
  121.64 +  */
  121.65 +
  121.66 +  void abstraction_thread_wait( thread_state_t thread_state )
  121.67 +  {
  121.68 +    pthread_join( thread_state,  NULL );
  121.69 +
  121.70 +    return;
  121.71 +  }
  121.72 +
  121.73 +#endif
  121.74 +
   122.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   122.2 +++ b/liblfds.6/test/src/benchmark_freelist.c	Sun Jan 31 21:28:42 2010 +1100
   122.3 @@ -0,0 +1,138 @@
   122.4 +#include "internal.h"
   122.5 +
   122.6 +
   122.7 +
   122.8 +
   122.9 +
  122.10 +/****************************************************************************/
  122.11 +void benchmark_freelist( void )
  122.12 +{
  122.13 +  unsigned int
  122.14 +    loop,
  122.15 +    thread_count,
  122.16 +    cpu_count;
  122.17 +
  122.18 +  struct freelist_state
  122.19 +    *fs;
  122.20 +
  122.21 +  struct freelist_benchmark
  122.22 +    *fb;
  122.23 +
  122.24 +  thread_state_t
  122.25 +    *thread_handles;
  122.26 +
  122.27 +  atom_t
  122.28 +    total_operations_for_full_test_for_all_cpus,
  122.29 +    total_operations_for_full_test_for_all_cpus_for_one_cpu = 0;
  122.30 +
  122.31 +  double
  122.32 +    mean_operations_per_second_per_cpu,
  122.33 +    difference_per_second_per_cpu,
  122.34 +    total_difference_per_second_per_cpu,
  122.35 +    std_dev_per_second_per_cpu,
  122.36 +    scalability;
  122.37 +
  122.38 +  /* TRD : here we benchmark the freelist
  122.39 +
  122.40 +           the benchmark is to have a single freelist
  122.41 +           where a worker thread busy-works popping and then pushing
  122.42 +  */
  122.43 +
  122.44 +  cpu_count = abstraction_cpu_count();
  122.45 +
  122.46 +  thread_handles = (thread_state_t *) malloc( sizeof(thread_state_t) * cpu_count );
  122.47 +
  122.48 +  fb = (struct freelist_benchmark *) malloc( sizeof(struct freelist_benchmark) * cpu_count );
  122.49 +
  122.50 +  // TRD : print the benchmark ID and CSV header
  122.51 +  printf( "\n"
  122.52 +          "Release %d Freelist Benchmark #1\n"
  122.53 +          "CPUs,total ops,mean ops/sec per CPU,standard deviation,scalability\n", LIBLFDS_RELEASE_NUMBER );
  122.54 +
  122.55 +  // TRD : we run CPU count times for scalability
  122.56 +  for( thread_count = 1 ; thread_count <= cpu_count ; thread_count++ )
  122.57 +  {
  122.58 +    // TRD : initialisation
  122.59 +    freelist_new( &fs, 1000, NULL, NULL );
  122.60 +
  122.61 +    for( loop = 0 ; loop < cpu_count ; loop++ )
  122.62 +    {
  122.63 +      (fb+loop)->fs = fs;
  122.64 +      (fb+loop)->operation_count = 0;
  122.65 +    }
  122.66 +
  122.67 +    // TRD : main test
  122.68 +    for( loop = 0 ; loop < thread_count ; loop++ )
  122.69 +      abstraction_thread_start( &thread_handles[loop], loop, benchmark_freelist_thread_pop_and_push, fb+loop );
  122.70 +
  122.71 +    for( loop = 0 ; loop < thread_count ; loop++ )
  122.72 +      abstraction_thread_wait( thread_handles[loop] );
  122.73 +
  122.74 +    // TRD : post test math
  122.75 +    total_operations_for_full_test_for_all_cpus = 0;
  122.76 +    total_difference_per_second_per_cpu = 0;
  122.77 +
  122.78 +    for( loop = 0 ; loop < thread_count ; loop++ )
  122.79 +      total_operations_for_full_test_for_all_cpus += (fb+loop)->operation_count;
  122.80 +
  122.81 +    mean_operations_per_second_per_cpu = ((double) total_operations_for_full_test_for_all_cpus / (double) thread_count) / (double) 10;
  122.82 +
  122.83 +    if( thread_count == 1 )
  122.84 +      total_operations_for_full_test_for_all_cpus_for_one_cpu = total_operations_for_full_test_for_all_cpus;
  122.85 +
  122.86 +    for( loop = 0 ; loop < thread_count ; loop++ )
  122.87 +    {
  122.88 +      difference_per_second_per_cpu = ((double) (fb+loop)->operation_count / (double) 10) - mean_operations_per_second_per_cpu;
  122.89 +      total_difference_per_second_per_cpu += difference_per_second_per_cpu * difference_per_second_per_cpu;
  122.90 +    }
  122.91 +
  122.92 +    std_dev_per_second_per_cpu = sqrt( (double) total_difference_per_second_per_cpu );
  122.93 +
  122.94 +    scalability = (double) total_operations_for_full_test_for_all_cpus / (double) (total_operations_for_full_test_for_all_cpus_for_one_cpu * thread_count);
  122.95 +
  122.96 +    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 );
  122.97 +
  122.98 +    // TRD : cleanup
  122.99 +    freelist_delete( fs, NULL, NULL );
 122.100 +  }
 122.101 +
 122.102 +  free( fb );
 122.103 +
 122.104 +  free( thread_handles );
 122.105 +
 122.106 +  return;
 122.107 +}
 122.108 +
 122.109 +
 122.110 +
 122.111 +
 122.112 +
 122.113 +/****************************************************************************/
 122.114 +thread_return_t CALLING_CONVENTION benchmark_freelist_thread_pop_and_push( void *freelist_benchmark )
 122.115 +{
 122.116 +  struct freelist_benchmark
 122.117 +    *fb;
 122.118 +
 122.119 +  struct freelist_element
 122.120 +    *fe;
 122.121 +
 122.122 +  time_t
 122.123 +    start_time;
 122.124 +
 122.125 +  assert( freelist_benchmark != NULL );
 122.126 +
 122.127 +  fb = (struct freelist_benchmark *) freelist_benchmark;
 122.128 +
 122.129 +  time( &start_time );
 122.130 +
 122.131 +  while( time(NULL) < start_time + 10 )
 122.132 +  {
 122.133 +    freelist_pop( fb->fs, &fe );
 122.134 +    freelist_push( fb->fs, fe );
 122.135 +
 122.136 +    fb->operation_count += 2;
 122.137 +  }
 122.138 +
 122.139 +  return( (thread_return_t) EXIT_SUCCESS );
 122.140 +}
 122.141 +
   123.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   123.2 +++ b/liblfds.6/test/src/benchmark_queue.c	Sun Jan 31 21:28:42 2010 +1100
   123.3 @@ -0,0 +1,142 @@
   123.4 +#include "internal.h"
   123.5 +
   123.6 +
   123.7 +
   123.8 +
   123.9 +
  123.10 +/****************************************************************************/
  123.11 +void benchmark_queue( void )
  123.12 +{
  123.13 +  unsigned int
  123.14 +    loop,
  123.15 +    thread_count,
  123.16 +    cpu_count;
  123.17 +
  123.18 +  struct queue_state
  123.19 +    *qs;
  123.20 +
  123.21 +  struct queue_benchmark
  123.22 +    *qb;
  123.23 +
  123.24 +  thread_state_t
  123.25 +    *thread_handles;
  123.26 +
  123.27 +  atom_t
  123.28 +    total_operations_for_full_test_for_all_cpus,
  123.29 +    total_operations_for_full_test_for_all_cpus_for_one_cpu = 0;
  123.30 +
  123.31 +  double
  123.32 +    mean_operations_per_second_per_cpu,
  123.33 +    difference_per_second_per_cpu,
  123.34 +    total_difference_per_second_per_cpu,
  123.35 +    std_dev_per_second_per_cpu,
  123.36 +    scalability;
  123.37 +
  123.38 +  /* TRD : here we benchmark the queue
  123.39 +
  123.40 +           the benchmark is to have a single queue
  123.41 +           where a worker thread busy-works dequeuing and then queuing
  123.42 +  */
  123.43 +
  123.44 +  cpu_count = abstraction_cpu_count();
  123.45 +
  123.46 +  thread_handles = (thread_state_t *) malloc( sizeof(thread_state_t) * cpu_count );
  123.47 +
  123.48 +  qb = (struct queue_benchmark *) malloc( sizeof(struct queue_benchmark) * cpu_count );
  123.49 +
  123.50 +  // TRD : print the benchmark ID and CSV header
  123.51 +  printf( "\n"
  123.52 +          "Release %d Queue Benchmark #1\n"
  123.53 +          "CPUs,total ops,mean ops/sec per CPU,standard deviation,scalability\n", LIBLFDS_RELEASE_NUMBER );
  123.54 +
  123.55 +  // TRD : we run CPU count times for scalability
  123.56 +  for( thread_count = 1 ; thread_count <= cpu_count ; thread_count++ )
  123.57 +  {
  123.58 +    // TRD : initialisation
  123.59 +    queue_new( &qs, 1000 );
  123.60 +
  123.61 +    for( loop = 0 ; loop < cpu_count ; loop++ )
  123.62 +    {
  123.63 +      (qb+loop)->qs = qs;
  123.64 +      (qb+loop)->operation_count = 0;
  123.65 +    }
  123.66 +
  123.67 +    // TRD : populate the queue (we don't actually use the user data)
  123.68 +    for( loop = 0 ; loop < 500 ; loop++ )
  123.69 +      queue_enqueue( qs, (void *) (atom_t) loop );
  123.70 +
  123.71 +    // TRD : main test
  123.72 +    for( loop = 0 ; loop < thread_count ; loop++ )
  123.73 +      abstraction_thread_start( &thread_handles[loop], loop, benchmark_queue_thread_dequeue_and_enqueue, qb+loop );
  123.74 +
  123.75 +    for( loop = 0 ; loop < thread_count ; loop++ )
  123.76 +      abstraction_thread_wait( thread_handles[loop] );
  123.77 +
  123.78 +    // TRD : post test math
  123.79 +    total_operations_for_full_test_for_all_cpus = 0;
  123.80 +    total_difference_per_second_per_cpu = 0;
  123.81 +
  123.82 +    for( loop = 0 ; loop < thread_count ; loop++ )
  123.83 +      total_operations_for_full_test_for_all_cpus += (qb+loop)->operation_count;
  123.84 +
  123.85 +    mean_operations_per_second_per_cpu = ((double) total_operations_for_full_test_for_all_cpus / (double) thread_count) / (double) 10;
  123.86 +
  123.87 +    if( thread_count == 1 )
  123.88 +      total_operations_for_full_test_for_all_cpus_for_one_cpu = total_operations_for_full_test_for_all_cpus;
  123.89 +
  123.90 +    for( loop = 0 ; loop < thread_count ; loop++ )
  123.91 +    {
  123.92 +      difference_per_second_per_cpu = ((double) (qb+loop)->operation_count / (double) 10) - mean_operations_per_second_per_cpu;
  123.93 +      total_difference_per_second_per_cpu += difference_per_second_per_cpu * difference_per_second_per_cpu;
  123.94 +    }
  123.95 +
  123.96 +    std_dev_per_second_per_cpu = sqrt( (double) total_difference_per_second_per_cpu );
  123.97 +
  123.98 +    scalability = (double) total_operations_for_full_test_for_all_cpus / (double) (total_operations_for_full_test_for_all_cpus_for_one_cpu * thread_count);
  123.99 +
 123.100 +    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 );
 123.101 +
 123.102 +    // TRD : cleanup
 123.103 +    queue_delete( qs, NULL, NULL );
 123.104 +  }
 123.105 +
 123.106 +  free( qb );
 123.107 +
 123.108 +  free( thread_handles );
 123.109 +
 123.110 +  return;
 123.111 +}
 123.112 +
 123.113 +
 123.114 +
 123.115 +
 123.116 +
 123.117 +/****************************************************************************/
 123.118 +thread_return_t CALLING_CONVENTION benchmark_queue_thread_dequeue_and_enqueue( void *queue_benchmark )
 123.119 +{
 123.120 +  struct queue_benchmark
 123.121 +    *qb;
 123.122 +
 123.123 +  void
 123.124 +    *user_data;
 123.125 +
 123.126 +  time_t
 123.127 +    start_time;
 123.128 +
 123.129 +  assert( queue_benchmark != NULL );
 123.130 +
 123.131 +  qb = (struct queue_benchmark *) queue_benchmark;
 123.132 +
 123.133 +  time( &start_time );
 123.134 +
 123.135 +  while( time(NULL) < start_time + 10 )
 123.136 +  {
 123.137 +    queue_dequeue( qb->qs, &user_data );
 123.138 +    queue_enqueue( qb->qs, user_data );
 123.139 +
 123.140 +    qb->operation_count += 2;
 123.141 +  }
 123.142 +
 123.143 +  return( (thread_return_t) EXIT_SUCCESS );
 123.144 +}
 123.145 +
   124.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   124.2 +++ b/liblfds.6/test/src/benchmark_ringbuffer.c	Sun Jan 31 21:28:42 2010 +1100
   124.3 @@ -0,0 +1,141 @@
   124.4 +#include "internal.h"
   124.5 +
   124.6 +
   124.7 +
   124.8 +
   124.9 +
  124.10 +/****************************************************************************/
  124.11 +void benchmark_ringbuffer( void )
  124.12 +{
  124.13 +  unsigned int
  124.14 +    loop,
  124.15 +    thread_count,
  124.16 +    cpu_count;
  124.17 +
  124.18 +  struct ringbuffer_state
  124.19 +    *rs;
  124.20 +
  124.21 +  struct ringbuffer_benchmark
  124.22 +    *rb;
  124.23 +
  124.24 +  thread_state_t
  124.25 +    *thread_handles;
  124.26 +
  124.27 +  atom_t
  124.28 +    total_operations_for_full_test_for_all_cpus,
  124.29 +    total_operations_for_full_test_for_all_cpus_for_one_cpu = 0;
  124.30 +
  124.31 +  double
  124.32 +    mean_operations_per_second_per_cpu,
  124.33 +    difference_per_second_per_cpu,
  124.34 +    total_difference_per_second_per_cpu,
  124.35 +    std_dev_per_second_per_cpu,
  124.36 +    scalability;
  124.37 +
  124.38 +  /* TRD : here we benchmark the ringbuffer
  124.39 +
  124.40 +           the benchmark is to have a single ringbuffer
  124.41 +           where a worker thread busy-works writing and then reading
  124.42 +  */
  124.43 +
  124.44 +  cpu_count = abstraction_cpu_count();
  124.45 +
  124.46 +  thread_handles = (thread_state_t *) malloc( sizeof(thread_state_t) * cpu_count );
  124.47 +
  124.48 +  rb = (struct ringbuffer_benchmark *) malloc( sizeof(struct ringbuffer_benchmark) * cpu_count );
  124.49 +
  124.50 +  // TRD : print the benchmark ID and CSV header
  124.51 +  printf( "\n"
  124.52 +          "Release %d Ringbuffer Benchmark #1\n"
  124.53 +          "CPUs,total ops,mean ops/sec per CPU,standard deviation,scalability\n", LIBLFDS_RELEASE_NUMBER );
  124.54 +
  124.55 +  // TRD : we run CPU count times for scalability
  124.56 +  for( thread_count = 1 ; thread_count <= cpu_count ; thread_count++ )
  124.57 +  {
  124.58 +    // TRD : initialisation
  124.59 +    ringbuffer_new( &rs, 1000, NULL, NULL );
  124.60 +
  124.61 +    for( loop = 0 ; loop < cpu_count ; loop++ )
  124.62 +    {
  124.63 +      (rb+loop)->rs = rs;
  124.64 +      (rb+loop)->operation_count = 0;
  124.65 +    }
  124.66 +
  124.67 +    // TRD : main test
  124.68 +    for( loop = 0 ; loop < thread_count ; loop++ )
  124.69 +      abstraction_thread_start( &thread_handles[loop], loop, benchmark_ringbuffer_thread_write_and_read, rb+loop );
  124.70 +
  124.71 +    for( loop = 0 ; loop < thread_count ; loop++ )
  124.72 +      abstraction_thread_wait( thread_handles[loop] );
  124.73 +
  124.74 +    // TRD : post test math
  124.75 +    total_operations_for_full_test_for_all_cpus = 0;
  124.76 +    total_difference_per_second_per_cpu = 0;
  124.77 +
  124.78 +    for( loop = 0 ; loop < thread_count ; loop++ )
  124.79 +      total_operations_for_full_test_for_all_cpus += (rb+loop)->operation_count;
  124.80 +
  124.81 +    mean_operations_per_second_per_cpu = ((double) total_operations_for_full_test_for_all_cpus / (double) thread_count) / (double) 10;
  124.82 +
  124.83 +    if( thread_count == 1 )
  124.84 +      total_operations_for_full_test_for_all_cpus_for_one_cpu = total_operations_for_full_test_for_all_cpus;
  124.85 +
  124.86 +    for( loop = 0 ; loop < thread_count ; loop++ )
  124.87 +    {
  124.88 +      difference_per_second_per_cpu = ((double) (rb+loop)->operation_count / (double) 10) - mean_operations_per_second_per_cpu;
  124.89 +      total_difference_per_second_per_cpu += difference_per_second_per_cpu * difference_per_second_per_cpu;
  124.90 +    }
  124.91 +
  124.92 +    std_dev_per_second_per_cpu = sqrt( (double) total_difference_per_second_per_cpu );
  124.93 +
  124.94 +    scalability = (double) total_operations_for_full_test_for_all_cpus / (double) (total_operations_for_full_test_for_all_cpus_for_one_cpu * thread_count);
  124.95 +
  124.96 +    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 );
  124.97 +
  124.98 +    // TRD : cleanup
  124.99 +    ringbuffer_delete( rs, NULL, NULL );
 124.100 +  }
 124.101 +
 124.102 +  free( rb );
 124.103 +
 124.104 +  free( thread_handles );
 124.105 +
 124.106 +  return;
 124.107 +}
 124.108 +
 124.109 +
 124.110 +
 124.111 +
 124.112 +
 124.113 +/****************************************************************************/
 124.114 +thread_return_t CALLING_CONVENTION benchmark_ringbuffer_thread_write_and_read( void *ringbuffer_benchmark )
 124.115 +{
 124.116 +  struct ringbuffer_benchmark
 124.117 +    *rb;
 124.118 +
 124.119 +  struct freelist_element
 124.120 +    *fe;
 124.121 +
 124.122 +  time_t
 124.123 +    start_time;
 124.124 +
 124.125 +  assert( ringbuffer_benchmark != NULL );
 124.126 +
 124.127 +  rb = (struct ringbuffer_benchmark *) ringbuffer_benchmark;
 124.128 +
 124.129 +  time( &start_time );
 124.130 +
 124.131 +  while( time(NULL) < start_time + 10 )
 124.132 +  {
 124.133 +    ringbuffer_get_write_element( rb->rs, &fe, NULL );
 124.134 +    ringbuffer_put_write_element( rb->rs, fe );
 124.135 +
 124.136 +    ringbuffer_get_read_element( rb->rs, &fe );
 124.137 +    ringbuffer_put_read_element( rb->rs, fe );
 124.138 +
 124.139 +    rb->operation_count += 2;
 124.140 +  }
 124.141 +
 124.142 +  return( (thread_return_t) EXIT_SUCCESS );
 124.143 +}
 124.144 +
   125.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   125.2 +++ b/liblfds.6/test/src/benchmark_stack.c	Sun Jan 31 21:28:42 2010 +1100
   125.3 @@ -0,0 +1,138 @@
   125.4 +#include "internal.h"
   125.5 +
   125.6 +
   125.7 +
   125.8 +
   125.9 +
  125.10 +/****************************************************************************/
  125.11 +void benchmark_stack( void )
  125.12 +{
  125.13 +  unsigned int
  125.14 +    loop,
  125.15 +    thread_count,
  125.16 +    cpu_count;
  125.17 +
  125.18 +  struct stack_state
  125.19 +    *ss;
  125.20 +
  125.21 +  struct stack_benchmark
  125.22 +    *sb;
  125.23 +
  125.24 +  thread_state_t
  125.25 +    *thread_handles;
  125.26 +
  125.27 +  atom_t
  125.28 +    total_operations_for_full_test_for_all_cpus,
  125.29 +    total_operations_for_full_test_for_all_cpus_for_one_cpu = 0;
  125.30 +
  125.31 +  double
  125.32 +    mean_operations_per_second_per_cpu,
  125.33 +    difference_per_second_per_cpu,
  125.34 +    total_difference_per_second_per_cpu,
  125.35 +    std_dev_per_second_per_cpu,
  125.36 +    scalability;
  125.37 +
  125.38 +  /* TRD : here we benchmark the stack
  125.39 +
  125.40 +           the benchmark is to have a single stack
  125.41 +           where a worker thread busy-works pushing then popping
  125.42 +  */
  125.43 +
  125.44 +  cpu_count = abstraction_cpu_count();
  125.45 +
  125.46 +  thread_handles = (thread_state_t *) malloc( sizeof(thread_state_t) * cpu_count );
  125.47 +
  125.48 +  sb = (struct stack_benchmark *) malloc( sizeof(struct stack_benchmark) * cpu_count );
  125.49 +
  125.50 +  // TRD : print the benchmark ID and CSV header
  125.51 +  printf( "\n"
  125.52 +          "Release %d Stack Benchmark #1\n"
  125.53 +          "CPUs,total ops,mean ops/sec per CPU,standard deviation,scalability\n", LIBLFDS_RELEASE_NUMBER );
  125.54 +
  125.55 +  // TRD : we run CPU count times for scalability
  125.56 +  for( thread_count = 1 ; thread_count <= cpu_count ; thread_count++ )
  125.57 +  {
  125.58 +    // TRD : initialisation
  125.59 +    stack_new( &ss, 1000 );
  125.60 +
  125.61 +    for( loop = 0 ; loop < cpu_count ; loop++ )
  125.62 +    {
  125.63 +      (sb+loop)->ss = ss;
  125.64 +      (sb+loop)->operation_count = 0;
  125.65 +    }
  125.66 +
  125.67 +    // TRD : main test
  125.68 +    for( loop = 0 ; loop < thread_count ; loop++ )
  125.69 +      abstraction_thread_start( &thread_handles[loop], loop, benchmark_stack_thread_push_and_pop, sb+loop );
  125.70 +
  125.71 +    for( loop = 0 ; loop < thread_count ; loop++ )
  125.72 +      abstraction_thread_wait( thread_handles[loop] );
  125.73 +
  125.74 +    // TRD : post test math
  125.75 +    total_operations_for_full_test_for_all_cpus = 0;
  125.76 +    total_difference_per_second_per_cpu = 0;
  125.77 +
  125.78 +    for( loop = 0 ; loop < thread_count ; loop++ )
  125.79 +      total_operations_for_full_test_for_all_cpus += (sb+loop)->operation_count;
  125.80 +
  125.81 +    mean_operations_per_second_per_cpu = ((double) total_operations_for_full_test_for_all_cpus / (double) thread_count) / (double) 10;
  125.82 +
  125.83 +    if( thread_count == 1 )
  125.84 +      total_operations_for_full_test_for_all_cpus_for_one_cpu = total_operations_for_full_test_for_all_cpus;
  125.85 +
  125.86 +    for( loop = 0 ; loop < thread_count ; loop++ )
  125.87 +    {
  125.88 +      difference_per_second_per_cpu = ((double) (sb+loop)->operation_count / (double) 10) - mean_operations_per_second_per_cpu;
  125.89 +      total_difference_per_second_per_cpu += difference_per_second_per_cpu * difference_per_second_per_cpu;
  125.90 +    }
  125.91 +
  125.92 +    std_dev_per_second_per_cpu = sqrt( (double) total_difference_per_second_per_cpu );
  125.93 +
  125.94 +    scalability = (double) total_operations_for_full_test_for_all_cpus / (double) (total_operations_for_full_test_for_all_cpus_for_one_cpu * thread_count);
  125.95 +
  125.96 +    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 );
  125.97 +
  125.98 +    // TRD : cleanup
  125.99 +    stack_delete( ss, NULL, NULL );
 125.100 +  }
 125.101 +
 125.102 +  free( sb );
 125.103 +
 125.104 +  free( thread_handles );
 125.105 +
 125.106 +  return;
 125.107 +}
 125.108 +
 125.109 +
 125.110 +
 125.111 +
 125.112 +
 125.113 +/****************************************************************************/
 125.114 +thread_return_t CALLING_CONVENTION benchmark_stack_thread_push_and_pop( void *stack_benchmark )
 125.115 +{
 125.116 +  struct stack_benchmark
 125.117 +    *sb;
 125.118 +
 125.119 +  void
 125.120 +    *user_data = NULL;
 125.121 +
 125.122 +  time_t
 125.123 +    start_time;
 125.124 +
 125.125 +  assert( stack_benchmark != NULL );
 125.126 +
 125.127 +  sb = (struct stack_benchmark *) stack_benchmark;
 125.128 +
 125.129 +  time( &start_time );
 125.130 +
 125.131 +  while( time(NULL) < start_time + 10 )
 125.132 +  {
 125.133 +    stack_push( sb->ss, user_data );
 125.134 +    stack_pop( sb->ss, &user_data );
 125.135 +
 125.136 +    sb->operation_count += 2;
 125.137 +  }
 125.138 +
 125.139 +  return( (thread_return_t) EXIT_SUCCESS );
 125.140 +}
 125.141 +
   126.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   126.2 +++ b/liblfds.6/test/src/internal.h	Sun Jan 31 21:28:42 2010 +1100
   126.3 @@ -0,0 +1,104 @@
   126.4 +/***** ANSI includes *****/
   126.5 +#include <assert.h>
   126.6 +#include <math.h>
   126.7 +#include <stdio.h>
   126.8 +#include <stdarg.h>
   126.9 +#include <stdlib.h>
  126.10 +#include <string.h>
  126.11 +#include <time.h>
  126.12 +
  126.13 +/***** internal includes *****/
  126.14 +#include "abstraction.h"
  126.15 +
  126.16 +/***** external includes *****/
  126.17 +#include "liblfds.h"
  126.18 +
  126.19 +/***** defines *****/
  126.20 +#define and &&
  126.21 +#define or  ||
  126.22 +
  126.23 +#define RAISED   1
  126.24 +#define LOWERED  0
  126.25 +
  126.26 +#define NO_FLAGS 0x0
  126.27 +
  126.28 +/***** enums *****/
  126.29 +enum test_operation
  126.30 +{
  126.31 +  UNKNOWN,
  126.32 +  HELP,
  126.33 +  TEST,
  126.34 +  BENCHMARK
  126.35 +};
  126.36 +
  126.37 +/***** structs *****/
  126.38 +#include "structures.h"
  126.39 +
  126.40 +/***** prototypes *****/
  126.41 +int main( int argc, char **argv );
  126.42 +
  126.43 +void internal_display_test_name( char *test_name );
  126.44 +void internal_display_test_result( unsigned int number_name_dvs_pairs, ... );
  126.45 +void internal_display_data_structure_validity( enum data_structure_validity dvs );
  126.46 +
  126.47 +void benchmark_freelist( void );
  126.48 +  thread_return_t CALLING_CONVENTION benchmark_freelist_thread_pop_and_push( void *freelist_benchmark );
  126.49 +
  126.50 +void benchmark_queue( void );
  126.51 +  thread_return_t CALLING_CONVENTION benchmark_queue_thread_dequeue_and_enqueue( void *queue_benchmark );
  126.52 +
  126.53 +void benchmark_ringbuffer( void );
  126.54 +  thread_return_t CALLING_CONVENTION benchmark_ringbuffer_thread_write_and_read( void *ringbuffer_benchmark );
  126.55 +
  126.56 +void benchmark_stack( void );
  126.57 +  thread_return_t CALLING_CONVENTION benchmark_stack_thread_push_and_pop( void *stack_benchmark );
  126.58 +
  126.59 +void test_abstraction( void );
  126.60 +  void abstraction_test_increment( void );
  126.61 +    thread_return_t CALLING_CONVENTION abstraction_test_internal_thread_increment( void *shared_counter );
  126.62 +    thread_return_t CALLING_CONVENTION abstraction_test_internal_thread_atomic_increment( void *shared_counter );
  126.63 +  void abstraction_test_dcas( void );
  126.64 +    thread_return_t CALLING_CONVENTION abstraction_test_internal_thread_dcas( void *abstraction_test_dcas_state );
  126.65 +
  126.66 +void test_freelist( void );
  126.67 +  void freelist_test_internal_popping( void );
  126.68 +    int freelist_test_internal_popping_init( void **user_data, void *user_state );
  126.69 +    thread_return_t CALLING_CONVENTION freelist_test_internal_thread_popping( void *freelist_test_popping_state );
  126.70 +  void freelist_test_internal_pushing( void );
  126.71 +    int freelist_test_internal_pushing_init( void **user_data, void *user_state );
  126.72 +    void freelist_test_internal_pushing_delete( void *user_data, void *user_state );
  126.73 +    thread_return_t CALLING_CONVENTION freelist_test_internal_thread_pushing( void *freelist_test_pushing_state );
  126.74 +  void freelist_test_internal_popping_and_pushing( void );
  126.75 +    thread_return_t CALLING_CONVENTION freelist_test_internal_thread_popping_and_pushing_start_popping( void *freelist_test_popping_and_pushing_state );
  126.76 +    thread_return_t CALLING_CONVENTION freelist_test_internal_thread_popping_and_pushing_start_pushing( void *freelist_test_popping_and_pushing_state );
  126.77 +  void freelist_test_internal_rapid_popping_and_pushing( void );
  126.78 +    thread_return_t CALLING_CONVENTION freelist_test_internal_thread_rapid_popping_and_pushing( void *freelist_state );
  126.79 +
  126.80 +void test_queue( void );
  126.81 +  void queue_test_enqueuing( void );
  126.82 +    thread_return_t CALLING_CONVENTION queue_test_internal_thread_simple_enqueuer( void *queue_test_enqueuing_state );
  126.83 +  void queue_test_dequeuing( void );
  126.84 +    thread_return_t CALLING_CONVENTION queue_test_internal_thread_simple_dequeuer( void *queue_test_dequeuing_state );
  126.85 +  void queue_test_enqueuing_and_dequeuing( void );
  126.86 +    thread_return_t CALLING_CONVENTION queue_test_internal_thread_enqueuer_and_dequeuer( void *queue_test_rapid_enqueuing_and_dequeuing_state );
  126.87 +  void queue_test_rapid_enqueuing_and_dequeuing( void );
  126.88 +    thread_return_t CALLING_CONVENTION queue_test_internal_thread_rapid_enqueuer_and_dequeuer( void *queue_test_rapid_enqueuing_and_dequeuing_state );
  126.89 +
  126.90 +void test_ringbuffer( void );
  126.91 +  void ringbuffer_test_reading( void );
  126.92 +    thread_return_t CALLING_CONVENTION ringbuffer_test_thread_simple_reader( void *ringbuffer_test_reading_state );
  126.93 +  void ringbuffer_test_writing( void );
  126.94 +    thread_return_t CALLING_CONVENTION ringbuffer_test_thread_simple_writer( void *ringbuffer_test_writing_state );
  126.95 +  void ringbuffer_test_reading_and_writing( void );
  126.96 +    thread_return_t CALLING_CONVENTION ringbuffer_test_thread_reader_writer( void *ringbuffer_test_reading_and_writing_state );
  126.97 +
  126.98 +void test_slist( void );
  126.99 +  thread_return_t CALLING_CONVENTION slist_internal_thread_head_writer( void *slist_thread_start_state );
 126.100 +  thread_return_t CALLING_CONVENTION slist_internal_thread_after_writer( void *slist_thread_start_state );
 126.101 +  thread_return_t CALLING_CONVENTION slist_internal_thread_traverser( void *slist_thread_start_state );
 126.102 +  thread_return_t CALLING_CONVENTION slist_internal_thread_deleter_traverser( void *slist_thread_start_state );
 126.103 +
 126.104 +void test_stack( void );
 126.105 +  thread_return_t CALLING_CONVENTION stack_internal_thread_reader( void *stack_state );
 126.106 +  thread_return_t CALLING_CONVENTION stack_internal_thread_writer( void *stack_state );
 126.107 +
   127.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   127.2 +++ b/liblfds.6/test/src/main.c	Sun Jan 31 21:28:42 2010 +1100
   127.3 @@ -0,0 +1,74 @@
   127.4 +#include "internal.h"
   127.5 +
   127.6 +
   127.7 +
   127.8 +
   127.9 +
  127.10 +/****************************************************************************/
  127.11 +int main( int argc, char **argv )
  127.12 +{
  127.13 +  enum test_operation
  127.14 +    operation = UNKNOWN;
  127.15 +
  127.16 +  unsigned int
  127.17 +    loop,
  127.18 +    iterations = 1;
  127.19 +
  127.20 +  assert( argc >= 1 );
  127.21 +  assert( argv != NULL );
  127.22 +
  127.23 +  if( argc == 1 or argc >= 4 )
  127.24 +    operation = HELP;
  127.25 +
  127.26 +  if( operation == UNKNOWN )
  127.27 +  {
  127.28 +    if( 0 == strcmp(*(argv+1), "test") )
  127.29 +    {
  127.30 +      operation = TEST;
  127.31 +
  127.32 +      // TRD : sscanf() may fail, but iterations is initialised to 1, so it's okay
  127.33 +      if( argc == 3 )
  127.34 +        sscanf( *(argv+2), "%u", &iterations );
  127.35 +    }
  127.36 +
  127.37 +    if( 0 == strcmp(*(argv+1), "benchmark") )
  127.38 +      operation = BENCHMARK;
  127.39 +  }
  127.40 +
  127.41 +  switch( operation )
  127.42 +  {
  127.43 +    case UNKNOWN:
  127.44 +    case HELP:
  127.45 +      printf( "test [test|benchmark] [iterations]\n"
  127.46 +              "  test       : run the test suite\n"
  127.47 +              "  benchmark  : run the benchmark suite\n"
  127.48 +              "  iterations : optional, only applies to tests, default is 1\n" );
  127.49 +    break;
  127.50 +
  127.51 +    case TEST:
  127.52 +      for( loop = 1 ; loop < iterations+1 ; loop++ )
  127.53 +      {
  127.54 +        printf( "\n"
  127.55 +                "Test Iteration %02u\n"
  127.56 +                "=================\n", loop );
  127.57 +
  127.58 +        test_abstraction();
  127.59 +        test_freelist();
  127.60 +        test_queue();
  127.61 +        test_ringbuffer();
  127.62 +        test_slist();
  127.63 +        test_stack();
  127.64 +      }
  127.65 +    break;
  127.66 +
  127.67 +    case BENCHMARK:
  127.68 +      benchmark_freelist();
  127.69 +      benchmark_queue();
  127.70 +      benchmark_ringbuffer();
  127.71 +      benchmark_stack();
  127.72 +    break;
  127.73 +  }
  127.74 +
  127.75 +  return( EXIT_SUCCESS );
  127.76 +}
  127.77 +
   128.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   128.2 +++ b/liblfds.6/test/src/misc.c	Sun Jan 31 21:28:42 2010 +1100
   128.3 @@ -0,0 +1,124 @@
   128.4 +#include "internal.h"
   128.5 +
   128.6 +
   128.7 +
   128.8 +
   128.9 +
  128.10 +/****************************************************************************/
  128.11 +void internal_display_test_name( char *test_name )
  128.12 +{
  128.13 +  assert( test_name != NULL );
  128.14 +
  128.15 +  printf( "%s...", test_name );
  128.16 +  fflush( stdout );
  128.17 +
  128.18 +  return;
  128.19 +}
  128.20 +
  128.21 +
  128.22 +
  128.23 +
  128.24 +
  128.25 +/****************************************************************************/
  128.26 +void internal_display_test_result( unsigned int number_name_dvs_pairs, ... )
  128.27 +{
  128.28 +  va_list
  128.29 +    va;
  128.30 +
  128.31 +  int
  128.32 +    passed_flag = RAISED;
  128.33 +
  128.34 +  unsigned int
  128.35 +    loop;
  128.36 +
  128.37 +  char
  128.38 +    *name;
  128.39 +
  128.40 +  enum data_structure_validity
  128.41 +    dvs;
  128.42 +
  128.43 +  // TRD : number_name_dvs_pairs can be any value in its range
  128.44 +
  128.45 +  va_start( va, number_name_dvs_pairs );
  128.46 +
  128.47 +  for( loop = 0 ; loop < number_name_dvs_pairs ; loop++ )
  128.48 +  {
  128.49 +    name = va_arg( va, char * );
  128.50 +    dvs = va_arg( va, enum data_structure_validity );
  128.51 +
  128.52 +    if( dvs != VALIDITY_VALID )
  128.53 +    {
  128.54 +      passed_flag = LOWERED;
  128.55 +      break;
  128.56 +    }
  128.57 +  }
  128.58 +
  128.59 +  va_end( va );
  128.60 +
  128.61 +  if( passed_flag == RAISED )
  128.62 +    puts( "passed" );
  128.63 +
  128.64 +  if( passed_flag == LOWERED )
  128.65 +  {
  128.66 +    printf( "failed (" );
  128.67 +
  128.68 +    va_start( va, number_name_dvs_pairs );
  128.69 +
  128.70 +    for( loop = 0 ; loop < number_name_dvs_pairs ; loop++ )
  128.71 +    {
  128.72 +      name = va_arg( va, char * );
  128.73 +      dvs = va_arg( va, enum data_structure_validity );
  128.74 +
  128.75 +      printf( "%s ", name );
  128.76 +      internal_display_data_structure_validity( dvs );
  128.77 +
  128.78 +      if( loop+1 < number_name_dvs_pairs )
  128.79 +        printf( ", " );
  128.80 +    }
  128.81 +
  128.82 +    va_end( va );
  128.83 +
  128.84 +    printf( ")\n" );
  128.85 +  }
  128.86 +
  128.87 +  return;
  128.88 +}
  128.89 +
  128.90 +
  128.91 +
  128.92 +
  128.93 +
  128.94 +/****************************************************************************/
  128.95 +void internal_display_data_structure_validity( enum data_structure_validity dvs )
  128.96 +{
  128.97 +  char
  128.98 +    *string = NULL;
  128.99 +
 128.100 +  switch( dvs )
 128.101 +  {
 128.102 +    case VALIDITY_VALID:
 128.103 +      string = "valid";
 128.104 +    break;
 128.105 +
 128.106 +    case VALIDITY_INVALID_LOOP:
 128.107 +      string = "invalid - loop detected";
 128.108 +    break;
 128.109 +
 128.110 +    case VALIDITY_INVALID_MISSING_ELEMENTS:
 128.111 +      string = "invalid - missing elements";
 128.112 +    break;
 128.113 +
 128.114 +    case VALIDITY_INVALID_ADDITIONAL_ELEMENTS:
 128.115 +      string = "invalid - additional elements";
 128.116 +    break;
 128.117 +
 128.118 +    case VALIDITY_INVALID_TEST_DATA:
 128.119 +      string = "invalid - invalid test data";
 128.120 +    break;
 128.121 +  }
 128.122 +
 128.123 +  printf( "%s", string );
 128.124 +
 128.125 +  return;
 128.126 +}
 128.127 +
   129.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   129.2 +++ b/liblfds.6/test/src/structures.h	Sun Jan 31 21:28:42 2010 +1100
   129.3 @@ -0,0 +1,190 @@
   129.4 +/***** structs *****/
   129.5 +#pragma pack( push, ALIGN_DOUBLE_POINTER )
   129.6 +
   129.7 +/***** abstraction tests *****/
   129.8 +struct abstraction_test_dcas_state
   129.9 +{
  129.10 +  volatile atom_t
  129.11 +    *shared_counter;
  129.12 +
  129.13 +  atom_t
  129.14 +    local_counter;
  129.15 +};
  129.16 +
  129.17 +/***** freelist tests *****/
  129.18 +struct freelist_test_popping_state
  129.19 +{
  129.20 +  struct freelist_state
  129.21 +    *fs,
  129.22 +    *fs_thread_local;
  129.23 +};
  129.24 +
  129.25 +struct freelist_test_pushing_state
  129.26 +{
  129.27 +  atom_t
  129.28 +    thread_number;
  129.29 +
  129.30 +  struct freelist_state
  129.31 +    *source_fs,
  129.32 +    *fs;
  129.33 +};
  129.34 +
  129.35 +struct freelist_test_popping_and_pushing_state
  129.36 +{
  129.37 +  struct freelist_state
  129.38 +    *local_fs,
  129.39 +    *fs;
  129.40 +};
  129.41 +
  129.42 +struct freelist_test_counter_and_thread_number
  129.43 +{
  129.44 +  atom_t
  129.45 +    thread_number;
  129.46 +
  129.47 +  unsigned long long int
  129.48 +    counter;
  129.49 +};
  129.50 +
  129.51 +/***** queue tests *****/
  129.52 +struct queue_test_enqueuing_state
  129.53 +{
  129.54 +  struct queue_state
  129.55 +    *qs;
  129.56 +
  129.57 +  atom_t
  129.58 +    counter;
  129.59 +};
  129.60 +
  129.61 +struct queue_test_dequeuing_state
  129.62 +{
  129.63 +  struct queue_state
  129.64 +    *qs;
  129.65 +
  129.66 +  int
  129.67 +    error_flag;
  129.68 +};
  129.69 +
  129.70 +struct queue_test_enqueuing_and_dequeuing_state
  129.71 +{
  129.72 +  struct queue_state
  129.73 +    *qs;
  129.74 +
  129.75 +  atom_t
  129.76 +    counter,
  129.77 +    thread_number,
  129.78 +    *per_thread_counters;
  129.79 +
  129.80 +  unsigned int
  129.81 +    cpu_count;
  129.82 +
  129.83 +  int
  129.84 +    error_flag;
  129.85 +};
  129.86 +
  129.87 +struct queue_test_rapid_enqueuing_and_dequeuing_state
  129.88 +{
  129.89 +  struct queue_state
  129.90 +    *qs;
  129.91 +
  129.92 +  atom_t
  129.93 +    counter;
  129.94 +};
  129.95 +
  129.96 +/***** ringbuffer tests *****/
  129.97 +struct ringbuffer_test_reading_state
  129.98 +{
  129.99 +  struct ringbuffer_state
 129.100 +    *rs;
 129.101 +
 129.102 +  int
 129.103 +    error_flag;
 129.104 +
 129.105 +  atom_t
 129.106 +    read_count;
 129.107 +};
 129.108 +
 129.109 +struct ringbuffer_test_writing_state
 129.110 +{
 129.111 +  struct ringbuffer_state
 129.112 +    *rs;
 129.113 +
 129.114 +  atom_t
 129.115 +    write_count;
 129.116 +};
 129.117 +
 129.118 +struct ringbuffer_test_reading_and_writing_state
 129.119 +{
 129.120 +  struct ringbuffer_state
 129.121 +    *rs;
 129.122 +
 129.123 +  atom_t
 129.124 +    counter,
 129.125 +    *per_thread_counters;
 129.126 +
 129.127 +  unsigned int
 129.128 +    cpu_count;
 129.129 +
 129.130 +  int
 129.131 +    error_flag;
 129.132 +};
 129.133 +
 129.134 +/***** slist tests *****/
 129.135 +struct slist_thread_start_state
 129.136 +{
 129.137 +  struct slist_state
 129.138 +    *ss;
 129.139 +
 129.140 +  struct slist_element
 129.141 +    *se;
 129.142 +
 129.143 +  time_t
 129.144 +    duration;
 129.145 +
 129.146 +  unsigned long int
 129.147 +    iteration_modulo;
 129.148 +};
 129.149 +
 129.150 +/***** stack tests *****/
 129.151 +
 129.152 +/***** freelist benchmarks *****/
 129.153 +struct freelist_benchmark
 129.154 +{
 129.155 +  struct freelist_state
 129.156 +    *fs;
 129.157 +
 129.158 +  atom_t
 129.159 +    operation_count;
 129.160 +};
 129.161 +
 129.162 +/***** queue benchmarks *****/
 129.163 +struct queue_benchmark
 129.164 +{
 129.165 +  struct queue_state
 129.166 +    *qs;
 129.167 +
 129.168 +  atom_t
 129.169 +    operation_count;
 129.170 +};
 129.171 +
 129.172 +/***** ringbuffer benchmarks *****/
 129.173 +struct ringbuffer_benchmark
 129.174 +{
 129.175 +  struct ringbuffer_state
 129.176 +    *rs;
 129.177 +
 129.178 +  atom_t
 129.179 +    operation_count;
 129.180 +};
 129.181 +
 129.182 +/***** stack benchmarks *****/
 129.183 +struct stack_benchmark
 129.184 +{
 129.185 +  struct stack_state
 129.186 +    *ss;
 129.187 +
 129.188 +  atom_t
 129.189 +    operation_count;
 129.190 +};
 129.191 +
 129.192 +#pragma pack( pop )
 129.193 +
   130.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   130.2 +++ b/liblfds.6/test/src/test_abstraction.c	Sun Jan 31 21:28:42 2010 +1100
   130.3 @@ -0,0 +1,246 @@
   130.4 +#include "internal.h"
   130.5 +
   130.6 +
   130.7 +
   130.8 +
   130.9 +
  130.10 +/****************************************************************************/
  130.11 +void test_abstraction( void )
  130.12 +{
  130.13 +  printf( "\n"
  130.14 +          "Abstraction Tests\n"
  130.15 +          "=================\n" );
  130.16 +
  130.17 +  abstraction_test_increment();
  130.18 +  abstraction_test_dcas();
  130.19 +
  130.20 +  return;
  130.21 +}
  130.22 +
  130.23 +
  130.24 +
  130.25 +
  130.26 +
  130.27 +/****************************************************************************/
  130.28 +void abstraction_test_increment( void )
  130.29 +{
  130.30 +  unsigned int
  130.31 +    loop,
  130.32 +    cpu_count;
  130.33 +
  130.34 +  thread_state_t
  130.35 +    *thread_handles;
  130.36 +
  130.37 +  atom_t
  130.38 +    shared_counter = 0,
  130.39 +    atomic_shared_counter = 0;
  130.40 +
  130.41 +  /* TRD : here we test abstraction_increment
  130.42 +
  130.43 +           first, we run one thread per CPU where each thread increments
  130.44 +           a shared counter 10,000,000 times - however, this first test
  130.45 +           does NOT use atomic increment; it uses "++"
  130.46 +
  130.47 +           second, we repeat the exercise, but this time using
  130.48 +           abstraction_increment()
  130.49 +
  130.50 +           if the final value in the first test is less than (10,000,000*cpu_count)
  130.51 +           then the system is sensitive to non-atomic increments; this means if
  130.52 +           our atomic version of the test passes, we can have some degree of confidence
  130.53 +           that it works
  130.54 +
  130.55 +           if the final value in the first test is in fact correct, then we can't know
  130.56 +           that our atomic version has changed anything
  130.57 +
  130.58 +           and of course if the final value in the atomic test is wrong, we know things
  130.59 +           are broken
  130.60 +  */
  130.61 +
  130.62 +  internal_display_test_name( "Atomic increment" );
  130.63 +
  130.64 +  cpu_count = abstraction_cpu_count();
  130.65 +
  130.66 +  thread_handles = malloc( sizeof(thread_state_t) * cpu_count );
  130.67 +
  130.68 +  // TRD : non-atomic
  130.69 +  for( loop = 0 ; loop < cpu_count ; loop++ )
  130.70 +    abstraction_thread_start( &thread_handles[loop], loop, abstraction_test_internal_thread_increment, &shared_counter );
  130.71 +
  130.72 +  for( loop = 0 ; loop < cpu_count ; loop++ )
  130.73 +    abstraction_thread_wait( thread_handles[loop] );
  130.74 +
  130.75 +  // TRD : atomic
  130.76 +  for( loop = 0 ; loop < cpu_count ; loop++ )
  130.77 +    abstraction_thread_start( &thread_handles[loop], loop, abstraction_test_internal_thread_atomic_increment, &atomic_shared_counter );
  130.78 +
  130.79 +  for( loop = 0 ; loop < cpu_count ; loop++ )
  130.80 +    abstraction_thread_wait( thread_handles[loop] );
  130.81 +
  130.82 +  free( thread_handles );
  130.83 +
  130.84 +  // TRD : results
  130.85 +  if( shared_counter < (10000000 * cpu_count) and atomic_shared_counter == (10000000 * cpu_count) )
  130.86 +    puts( "passed" );
  130.87 +
  130.88 +  if( shared_counter == (10000000 * cpu_count) and atomic_shared_counter == (10000000 * cpu_count) )
  130.89 +    puts( "indeterminate" );
  130.90 +
  130.91 +  if( atomic_shared_counter < (10000000 * cpu_count) )
  130.92 +    puts( "failed" );
  130.93 +
  130.94 +  return;
  130.95 +}
  130.96 +
  130.97 +
  130.98 +
  130.99 +
 130.100 +
 130.101 +/****************************************************************************/
 130.102 +thread_return_t CALLING_CONVENTION abstraction_test_internal_thread_increment( void *shared_counter )
 130.103 +{
 130.104 +  volatile atom_t
 130.105 +    count = 0;
 130.106 +
 130.107 +  /* TRD : atom_t must be volatile or the compiler
 130.108 +           optimizes it away into a single store
 130.109 +  */
 130.110 +
 130.111 +  assert( shared_counter != NULL );
 130.112 +
 130.113 +  while( count++ < 10000000 )
 130.114 +    (*(atom_t *) shared_counter)++;
 130.115 +
 130.116 +  return( (thread_return_t) EXIT_SUCCESS );
 130.117 +}
 130.118 +
 130.119 +
 130.120 +
 130.121 +
 130.122 +
 130.123 +/****************************************************************************/
 130.124 +thread_return_t CALLING_CONVENTION abstraction_test_internal_thread_atomic_increment( void *shared_counter )
 130.125 +{
 130.126 +  atom_t
 130.127 +    count = 0;
 130.128 +
 130.129 +  assert( shared_counter != NULL );
 130.130 +
 130.131 +  while( count++ < 10000000 )
 130.132 +    abstraction_increment( shared_counter );
 130.133 +
 130.134 +  return( (thread_return_t) EXIT_SUCCESS );
 130.135 +}
 130.136 +
 130.137 +
 130.138 +
 130.139 +
 130.140 +
 130.141 +/****************************************************************************/
 130.142 +void abstraction_test_dcas( void )
 130.143 +{
 130.144 +  unsigned int
 130.145 +    loop,
 130.146 +    cpu_count;
 130.147 +
 130.148 +  thread_state_t
 130.149 +    *thread_handles;
 130.150 +
 130.151 +  struct abstraction_test_dcas_state
 130.152 +    *atds;
 130.153 +
 130.154 +  ALIGN(ALIGN_DOUBLE_POINTER) volatile atom_t
 130.155 +    shared_counter[2] = { 0, 0 };
 130.156 +
 130.157 +  atom_t
 130.158 +    local_total = 0;
 130.159 +
 130.160 +  /* TRD : here we test abstraction_dcas
 130.161 +
 130.162 +           we run one thread per CPU
 130.163 +           we use abstraction_dcas() to increment a shared counter
 130.164 +           every time a thread successfully increments the counter,
 130.165 +           it increments a thread local counter
 130.166 +           the threads run for ten seconds
 130.167 +           after the threads finish, we total the local counters
 130.168 +           they should equal the shared counter
 130.169 +  */
 130.170 +
 130.171 +  internal_display_test_name( "Atomic DCAS" );
 130.172 +
 130.173 +  cpu_count = abstraction_cpu_count();
 130.174 +
 130.175 +  atds = malloc( sizeof(struct abstraction_test_dcas_state) * cpu_count );
 130.176 +
 130.177 +  for( loop = 0 ; loop < cpu_count ; loop++ )
 130.178 +  {
 130.179 +    (atds+loop)->shared_counter = shared_counter;
 130.180 +    (atds+loop)->local_counter = 0;
 130.181 +  }
 130.182 +
 130.183 +  thread_handles = malloc( sizeof(thread_state_t) * cpu_count );
 130.184 +
 130.185 +  for( loop = 0 ; loop < cpu_count ; loop++ )
 130.186 +    abstraction_thread_start( &thread_handles[loop], loop, abstraction_test_internal_thread_dcas, atds+loop );
 130.187 +
 130.188 +  for( loop = 0 ; loop < cpu_count ; loop++ )
 130.189 +    abstraction_thread_wait( thread_handles[loop] );
 130.190 +
 130.191 +  free( thread_handles );
 130.192 +
 130.193 +  // TRD : results
 130.194 +  for( loop = 0 ; loop < cpu_count ; loop++ )
 130.195 +    local_total += (atds+loop)->local_counter;
 130.196 +
 130.197 +  if( local_total == shared_counter[0] )
 130.198 +    puts( "passed" );
 130.199 +
 130.200 +  if( local_total != shared_counter[0] )
 130.201 +    puts( "failed" );
 130.202 +
 130.203 +  // TRD : cleanup
 130.204 +  free( atds );
 130.205 +
 130.206 +  return;
 130.207 +}
 130.208 +
 130.209 +
 130.210 +
 130.211 +
 130.212 +
 130.213 +/****************************************************************************/
 130.214 +thread_return_t CALLING_CONVENTION abstraction_test_internal_thread_dcas( void *abstraction_test_dcas_state )
 130.215 +{
 130.216 +  struct abstraction_test_dcas_state
 130.217 +    *atds;
 130.218 +
 130.219 +  time_t
 130.220 +    start_time;
 130.221 +
 130.222 +  ALIGN(ALIGN_DOUBLE_POINTER) atom_t
 130.223 +    exchange[2],
 130.224 +    compare[2];
 130.225 +
 130.226 +  assert( abstraction_test_dcas_state != NULL );
 130.227 +
 130.228 +  atds = (struct abstraction_test_dcas_state *) abstraction_test_dcas_state;
 130.229 +
 130.230 +  time( &start_time );
 130.231 +
 130.232 +  while( time(NULL) < start_time + 10 )
 130.233 +  {
 130.234 +    compare[0] = *atds->shared_counter;
 130.235 +    compare[1] = *(atds->shared_counter+1);
 130.236 +
 130.237 +    do
 130.238 +    {
 130.239 +      exchange[0] = compare[0] + 1;
 130.240 +      exchange[1] = compare[1];
 130.241 +    }
 130.242 +    while( 0 == abstraction_dcas(atds->shared_counter, exchange, compare) );
 130.243 +
 130.244 +    atds->local_counter++;
 130.245 +  }
 130.246 +
 130.247 +  return( (thread_return_t) EXIT_SUCCESS );
 130.248 +}
 130.249 +
   131.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   131.2 +++ b/liblfds.6/test/src/test_freelist.c	Sun Jan 31 21:28:42 2010 +1100
   131.3 @@ -0,0 +1,662 @@
   131.4 +#include "internal.h"
   131.5 +
   131.6 +
   131.7 +
   131.8 +
   131.9 +
  131.10 +/****************************************************************************/
  131.11 +void test_freelist( void )
  131.12 +{
  131.13 +  printf( "\n"
  131.14 +          "Freelist Tests\n"
  131.15 +          "==============\n" );
  131.16 +
  131.17 +  freelist_test_internal_popping();
  131.18 +  freelist_test_internal_pushing();
  131.19 +  freelist_test_internal_popping_and_pushing();
  131.20 +  freelist_test_internal_rapid_popping_and_pushing();
  131.21 +
  131.22 +  return;
  131.23 +}
  131.24 +
  131.25 +
  131.26 +
  131.27 +
  131.28 +
  131.29 +/****************************************************************************/
  131.30 +void freelist_test_internal_popping( void )
  131.31 +{
  131.32 +  unsigned int
  131.33 +    loop,
  131.34 +    cpu_count,
  131.35 +    count;
  131.36 +
  131.37 +  thread_state_t
  131.38 +    *thread_handles;
  131.39 +
  131.40 +  enum data_structure_validity
  131.41 +    dvs = VALIDITY_VALID;
  131.42 +
  131.43 +  struct freelist_state
  131.44 +    *fs;
  131.45 +
  131.46 +  struct freelist_element
  131.47 +    *fe;
  131.48 +
  131.49 +  struct freelist_test_popping_state
  131.50 +    *ftps;
  131.51 +
  131.52 +  unsigned int
  131.53 +    *found_count;
  131.54 +
  131.55 +  /* TRD : we create a freelist with 1,000,000 elements
  131.56 +
  131.57 +           the creation function runs in a single thread and creates
  131.58 +           and pushes those elements onto the freelist
  131.59 +
  131.60 +           each element contains a void pointer which is its element number
  131.61 +
  131.62 +           we then run one thread per CPU
  131.63 +           where each thread loops, popping as quickly as possible
  131.64 +           each popped element is pushed onto a thread-local freelist
  131.65 +
  131.66 +           the threads run till the source freelist is empty
  131.67 +
  131.68 +           we then check the thread-local freelists
  131.69 +           we should find we have every element
  131.70 +
  131.71 +           then tidy up
  131.72 +  */
  131.73 +
  131.74 +  internal_display_test_name( "Popping" );
  131.75 +
  131.76 +  cpu_count = abstraction_cpu_count();
  131.77 +
  131.78 +  freelist_new( &fs, 1000000, freelist_test_internal_popping_init, NULL );
  131.79 +  ftps = malloc( sizeof(struct freelist_test_popping_state) * cpu_count );
  131.80 +  for( loop = 0 ; loop < cpu_count ; loop++ )
  131.81 +  {
  131.82 +    (ftps+loop)->fs = fs;
  131.83 +    freelist_new( &(ftps+loop)->fs_thread_local, 0, NULL, NULL );
  131.84 +  }
  131.85 +
  131.86 +  thread_handles = malloc( sizeof(thread_state_t) * cpu_count );
  131.87 +
  131.88 +  for( loop = 0 ; loop < cpu_count ; loop++ )
  131.89 +    abstraction_thread_start( &thread_handles[loop], loop, freelist_test_internal_thread_popping, ftps+loop );
  131.90 +
  131.91 +  for( loop = 0 ; loop < cpu_count ; loop++ )
  131.92 +    abstraction_thread_wait( thread_handles[loop] );
  131.93 +
  131.94 +  free( thread_handles );
  131.95 +
  131.96 +  // TRD : now we check the thread-local freelists
  131.97 +  found_count = malloc( sizeof(unsigned int) * 1000000 );
  131.98 +  for( loop = 0 ; loop < 1000000 ; loop++ )
  131.99 +    *(found_count+loop) = 0;
 131.100 +
 131.101 +  for( loop = 0 ; loop < cpu_count ; loop++ )
 131.102 +  {
 131.103 +    while( freelist_pop((ftps+loop)->fs_thread_local, &fe) )
 131.104 +    {
 131.105 +      freelist_get_user_data_from_element( fe, (void **) &count );
 131.106 +      (*(found_count+count))++;
 131.107 +      freelist_push( fs, fe );
 131.108 +    }
 131.109 +  }
 131.110 +
 131.111 +  for( loop = 0 ; loop < 1000000 and dvs == VALIDITY_VALID ; loop++ )
 131.112 +  {
 131.113 +    if( *(found_count+loop) == 0 )
 131.114 +      dvs = VALIDITY_INVALID_MISSING_ELEMENTS;
 131.115 +
 131.116 +    if( *(found_count+loop) > 1 )
 131.117 +      dvs = VALIDITY_INVALID_ADDITIONAL_ELEMENTS;
 131.118 +  }
 131.119 +
 131.120 +  // TRD : cleanup
 131.121 +  free( found_count );
 131.122 +  for( loop = 0 ; loop < cpu_count ; loop++ )
 131.123 +    freelist_delete( (ftps+loop)->fs_thread_local, NULL, NULL );
 131.124 +  freelist_delete( fs, NULL, NULL );
 131.125 +
 131.126 +  // TRD : print the test result
 131.127 +  internal_display_test_result( 1, "freelist", dvs );
 131.128 +
 131.129 +  return;
 131.130 +}
 131.131 +
 131.132 +
 131.133 +
 131.134 +
 131.135 +
 131.136 +/****************************************************************************/
 131.137 +#pragma warning( disable : 4100 )
 131.138 +
 131.139 +int freelist_test_internal_popping_init( void **user_data, void *user_state )
 131.140 +{
 131.141 +  static atom_t
 131.142 +    count = 0;
 131.143 +
 131.144 +  assert( user_data != NULL );
 131.145 +  assert( user_state == NULL );
 131.146 +
 131.147 +  *(atom_t *) user_data = count++;
 131.148 +
 131.149 +  return( 1 );
 131.150 +}
 131.151 +
 131.152 +#pragma warning( default : 4100 )
 131.153 +
 131.154 +
 131.155 +
 131.156 +
 131.157 +
 131.158 +/****************************************************************************/
 131.159 +thread_return_t CALLING_CONVENTION freelist_test_internal_thread_popping( void *freelist_test_popping_state )
 131.160 +{
 131.161 +  struct freelist_test_popping_state
 131.162 +    *ftps;
 131.163 +
 131.164 +  struct freelist_element
 131.165 +    *fe;
 131.166 +
 131.167 +  assert( freelist_test_popping_state != NULL );
 131.168 +
 131.169 +  ftps