From b813a0e546ed54e54b3873bdf180cf885c39bbca Mon Sep 17 00:00:00 2001 From: Toby Douglass Date: Tue, 31 May 2016 11:07:07 +0300 Subject: [PATCH 1/1] Initial import (all versions, including the new 7.1.0) --- .../bin/empty_dir_placeholder_for_git | 0 liblfds/liblfds6.0.0/liblfds600/building.txt | 38 + liblfds/liblfds6.0.0/liblfds600/dirs | 2 + .../liblfds6.0.0/liblfds600/inc/liblfds600.h | 282 ++++ .../liblfds6.0.0/liblfds600/liblfds600.def | 46 + .../liblfds6.0.0/liblfds600/liblfds600.sln | 38 + .../liblfds6.0.0/liblfds600/liblfds600.vcproj | 808 ++++++++++++ .../liblfds6.0.0/liblfds600/makefile.linux | 103 ++ .../liblfds6.0.0/liblfds600/makefile.windows | 94 ++ .../obj/empty_dir_placeholder_for_git | 0 liblfds/liblfds6.0.0/liblfds600/readme.txt | 136 ++ .../runme_before_win_kernel_build_readme.txt | 32 + ...me_before_win_kernel_dynamic_lib_build.bat | 14 + ...nme_before_win_kernel_static_lib_build.bat | 14 + .../liblfds6.0.0/liblfds600/sources.dynamic | 37 + .../liblfds6.0.0/liblfds600/sources.static | 35 + liblfds/liblfds6.0.0/liblfds600/src/dirs | 3 + .../liblfds600/src/driver_entry.c | 16 + .../liblfds600/src/driver_entry_readme.txt | 4 + .../lfds600_abstraction_aligned_free.c | 72 ++ .../lfds600_abstraction_aligned_malloc.c | 97 ++ .../lfds600_abstraction_cas.c | 109 ++ .../lfds600_abstraction_dcas.c | 356 +++++ .../lfds600_abstraction_increment.c | 136 ++ .../lfds600_abstraction_internal.h | 5 + .../lfds600_freelist_delete.c | 35 + .../lfds600_freelist_get_and_set.c | 33 + .../lfds600_freelist_internal.h | 42 + .../lfds600_freelist/lfds600_freelist_new.c | 123 ++ .../lfds600_freelist_pop_push.c | 88 ++ .../lfds600_freelist/lfds600_freelist_query.c | 113 ++ .../liblfds600/src/lfds600_internal.h | 12 + .../src/lfds600_queue/lfds600_queue_delete.c | 55 + .../lfds600_queue/lfds600_queue_internal.h | 60 + .../src/lfds600_queue/lfds600_queue_new.c | 140 ++ .../src/lfds600_queue/lfds600_queue_query.c | 153 +++ .../src/lfds600_queue/lfds600_queue_queue.c | 181 +++ .../lfds600_ringbuffer_delete.c | 22 + .../lfds600_ringbuffer_get_and_put.c | 108 ++ .../lfds600_ringbuffer_internal.h | 24 + .../lfds600_ringbuffer_new.c | 47 + .../lfds600_ringbuffer_query.c | 64 + .../src/lfds600_slist/lfds600_slist_delete.c | 79 ++ .../lfds600_slist/lfds600_slist_get_and_set.c | 124 ++ .../lfds600_slist/lfds600_slist_internal.h | 55 + .../src/lfds600_slist/lfds600_slist_link.c | 53 + .../src/lfds600_slist/lfds600_slist_new.c | 97 ++ .../src/lfds600_stack/lfds600_stack_delete.c | 67 + .../lfds600_stack/lfds600_stack_internal.h | 50 + .../src/lfds600_stack/lfds600_stack_new.c | 139 ++ .../lfds600_stack/lfds600_stack_push_pop.c | 110 ++ .../src/lfds600_stack/lfds600_stack_query.c | 30 + .../test/bin/empty_dir_placeholder_for_git | 0 liblfds/liblfds6.0.0/test/building.txt | 25 + liblfds/liblfds6.0.0/test/makefile.linux | 81 ++ liblfds/liblfds6.0.0/test/makefile.windows | 64 + .../test/obj/empty_dir_placeholder_for_git | 0 liblfds/liblfds6.0.0/test/src/abstraction.h | 50 + .../test/src/abstraction_cpu_count.c | 81 ++ .../test/src/abstraction_thread_start.c | 127 ++ .../test/src/abstraction_thread_wait.c | 71 + .../test/src/benchmark_freelist.c | 138 ++ .../liblfds6.0.0/test/src/benchmark_queue.c | 142 ++ .../test/src/benchmark_ringbuffer.c | 141 ++ .../liblfds6.0.0/test/src/benchmark_stack.c | 138 ++ liblfds/liblfds6.0.0/test/src/internal.h | 104 ++ liblfds/liblfds6.0.0/test/src/main.c | 74 ++ liblfds/liblfds6.0.0/test/src/misc.c | 124 ++ liblfds/liblfds6.0.0/test/src/structures.h | 190 +++ .../liblfds6.0.0/test/src/test_abstraction.c | 246 ++++ liblfds/liblfds6.0.0/test/src/test_freelist.c | 662 ++++++++++ liblfds/liblfds6.0.0/test/src/test_queue.c | 519 ++++++++ .../liblfds6.0.0/test/src/test_ringbuffer.c | 467 +++++++ liblfds/liblfds6.0.0/test/src/test_slist.c | 513 ++++++++ liblfds/liblfds6.0.0/test/src/test_stack.c | 223 ++++ liblfds/liblfds6.0.0/test/test.sln | 71 + liblfds/liblfds6.0.0/test/test.vcproj | 415 ++++++ .../bin/empty_dir_placeholder_for_git | 0 liblfds/liblfds6.0.1/liblfds601/building.txt | 38 + liblfds/liblfds6.0.1/liblfds601/dirs | 2 + .../liblfds6.0.1/liblfds601/inc/liblfds601.h | 282 ++++ .../liblfds6.0.1/liblfds601/liblfds601.def | 46 + .../liblfds6.0.1/liblfds601/liblfds601.sln | 38 + .../liblfds6.0.1/liblfds601/liblfds601.vcproj | 808 ++++++++++++ .../liblfds6.0.1/liblfds601/makefile.linux | 103 ++ .../liblfds6.0.1/liblfds601/makefile.windows | 94 ++ .../obj/empty_dir_placeholder_for_git | 0 liblfds/liblfds6.0.1/liblfds601/readme.txt | 139 ++ .../runme_before_win_kernel_build_readme.txt | 32 + ...me_before_win_kernel_dynamic_lib_build.bat | 14 + ...nme_before_win_kernel_static_lib_build.bat | 14 + .../liblfds6.0.1/liblfds601/sources.dynamic | 37 + .../liblfds6.0.1/liblfds601/sources.static | 35 + liblfds/liblfds6.0.1/liblfds601/src/dirs | 3 + .../liblfds601/src/driver_entry.c | 16 + .../liblfds601/src/driver_entry_readme.txt | 4 + .../lfds601_abstraction_aligned_free.c | 72 ++ .../lfds601_abstraction_aligned_malloc.c | 97 ++ .../lfds601_abstraction_cas.c | 109 ++ .../lfds601_abstraction_dcas.c | 356 +++++ .../lfds601_abstraction_increment.c | 136 ++ .../lfds601_abstraction_internal.h | 5 + .../lfds601_freelist_delete.c | 35 + .../lfds601_freelist_get_and_set.c | 33 + .../lfds601_freelist_internal.h | 42 + .../lfds601_freelist/lfds601_freelist_new.c | 123 ++ .../lfds601_freelist_pop_push.c | 88 ++ .../lfds601_freelist/lfds601_freelist_query.c | 113 ++ .../liblfds601/src/lfds601_internal.h | 12 + .../src/lfds601_queue/lfds601_queue_delete.c | 55 + .../lfds601_queue/lfds601_queue_internal.h | 60 + .../src/lfds601_queue/lfds601_queue_new.c | 140 ++ .../src/lfds601_queue/lfds601_queue_query.c | 153 +++ .../src/lfds601_queue/lfds601_queue_queue.c | 181 +++ .../lfds601_ringbuffer_delete.c | 22 + .../lfds601_ringbuffer_get_and_put.c | 108 ++ .../lfds601_ringbuffer_internal.h | 24 + .../lfds601_ringbuffer_new.c | 47 + .../lfds601_ringbuffer_query.c | 64 + .../src/lfds601_slist/lfds601_slist_delete.c | 79 ++ .../lfds601_slist/lfds601_slist_get_and_set.c | 124 ++ .../lfds601_slist/lfds601_slist_internal.h | 55 + .../src/lfds601_slist/lfds601_slist_link.c | 53 + .../src/lfds601_slist/lfds601_slist_new.c | 97 ++ .../src/lfds601_stack/lfds601_stack_delete.c | 67 + .../lfds601_stack/lfds601_stack_internal.h | 50 + .../src/lfds601_stack/lfds601_stack_new.c | 139 ++ .../lfds601_stack/lfds601_stack_push_pop.c | 110 ++ .../src/lfds601_stack/lfds601_stack_query.c | 30 + .../test/bin/empty_dir_placeholder_for_git | 0 liblfds/liblfds6.0.1/test/building.txt | 25 + liblfds/liblfds6.0.1/test/makefile.linux | 81 ++ liblfds/liblfds6.0.1/test/makefile.windows | 64 + .../test/obj/empty_dir_placeholder_for_git | 0 liblfds/liblfds6.0.1/test/src/abstraction.h | 50 + .../test/src/abstraction_cpu_count.c | 81 ++ .../test/src/abstraction_thread_start.c | 127 ++ .../test/src/abstraction_thread_wait.c | 71 + .../test/src/benchmark_freelist.c | 138 ++ .../liblfds6.0.1/test/src/benchmark_queue.c | 142 ++ .../test/src/benchmark_ringbuffer.c | 141 ++ .../liblfds6.0.1/test/src/benchmark_stack.c | 138 ++ liblfds/liblfds6.0.1/test/src/internal.h | 104 ++ liblfds/liblfds6.0.1/test/src/main.c | 74 ++ liblfds/liblfds6.0.1/test/src/misc.c | 124 ++ liblfds/liblfds6.0.1/test/src/structures.h | 190 +++ .../liblfds6.0.1/test/src/test_abstraction.c | 246 ++++ liblfds/liblfds6.0.1/test/src/test_freelist.c | 662 ++++++++++ liblfds/liblfds6.0.1/test/src/test_queue.c | 519 ++++++++ .../liblfds6.0.1/test/src/test_ringbuffer.c | 467 +++++++ liblfds/liblfds6.0.1/test/src/test_slist.c | 513 ++++++++ liblfds/liblfds6.0.1/test/src/test_stack.c | 223 ++++ liblfds/liblfds6.0.1/test/test.sln | 71 + liblfds/liblfds6.0.1/test/test.vcproj | 415 ++++++ .../bin/empty_dir_placeholder_for_git | 0 liblfds/liblfds6.1.0/liblfds610/building.txt | 40 + liblfds/liblfds6.1.0/liblfds610/dirs | 2 + .../liblfds6.1.0/liblfds610/inc/liblfds610.h | 340 +++++ .../liblfds6.1.0/liblfds610/liblfds610.def | 57 + .../liblfds6.1.0/liblfds610/liblfds610.sln | 38 + .../liblfds6.1.0/liblfds610/liblfds610.vcproj | 800 ++++++++++++ .../liblfds6.1.0/liblfds610/makefile.linux | 106 ++ .../liblfds6.1.0/liblfds610/makefile.windows | 97 ++ .../obj/empty_dir_placeholder_for_git | 0 liblfds/liblfds6.1.0/liblfds610/readme.txt | 139 ++ .../runme_before_win_kernel_build_readme.txt | 32 + ...me_before_win_kernel_dynamic_lib_build.bat | 15 + ...nme_before_win_kernel_static_lib_build.bat | 15 + .../liblfds6.1.0/liblfds610/sources.dynamic | 37 + .../liblfds6.1.0/liblfds610/sources.static | 35 + liblfds/liblfds6.1.0/liblfds610/src/dirs | 3 + .../liblfds610/src/driver_entry.c | 16 + .../liblfds610/src/driver_entry_readme.txt | 4 + .../lfds610_abstraction_cas.c | 53 + .../lfds610_abstraction_dcas.c | 139 ++ .../lfds610_abstraction_free.c | 44 + .../lfds610_abstraction_increment.c | 71 + .../lfds610_abstraction_internal_body.h | 2 + .../lfds610_abstraction_internal_wrapper.h | 6 + .../lfds610_abstraction_malloc.c | 40 + .../lfds610_freelist_delete.c | 37 + .../lfds610_freelist_get_and_set.c | 37 + .../lfds610_freelist_internal.h | 42 + .../lfds610_freelist/lfds610_freelist_new.c | 143 ++ .../lfds610_freelist_pop_push.c | 92 ++ .../lfds610_freelist/lfds610_freelist_query.c | 115 ++ ...lfds610_liblfds_abstraction_test_helpers.c | 112 ++ .../lfds610_liblfds_aligned_free.c | 17 + .../lfds610_liblfds_aligned_malloc.c | 32 + .../lfds610_liblfds_internal.h | 4 + .../lfds610_liblfds_readme.txt | 2 + .../src/lfds610_queue/lfds610_queue_delete.c | 57 + .../lfds610_queue/lfds610_queue_internal.h | 60 + .../src/lfds610_queue/lfds610_queue_new.c | 161 +++ .../src/lfds610_queue/lfds610_queue_query.c | 155 +++ .../src/lfds610_queue/lfds610_queue_queue.c | 193 +++ .../lfds610_ringbuffer_delete.c | 22 + .../lfds610_ringbuffer_get_and_put.c | 108 ++ .../lfds610_ringbuffer_internal.h | 24 + .../lfds610_ringbuffer_new.c | 67 + .../lfds610_ringbuffer_query.c | 64 + .../src/lfds610_slist/lfds610_slist_delete.c | 85 ++ .../lfds610_slist/lfds610_slist_get_and_set.c | 135 ++ .../lfds610_slist/lfds610_slist_internal.h | 55 + .../src/lfds610_slist/lfds610_slist_link.c | 57 + .../src/lfds610_slist/lfds610_slist_new.c | 117 ++ .../src/lfds610_stack/lfds610_stack_delete.c | 67 + .../lfds610_stack/lfds610_stack_internal.h | 52 + .../src/lfds610_stack/lfds610_stack_new.c | 159 +++ .../lfds610_stack/lfds610_stack_push_pop.c | 114 ++ .../src/lfds610_stack/lfds610_stack_query.c | 158 +++ .../liblfds610/src/liblfds610_internal.h | 25 + .../test/bin/empty_dir_placeholder_for_git | 0 liblfds/liblfds6.1.0/test/building.txt | 51 + liblfds/liblfds6.1.0/test/makefile.linux | 82 ++ liblfds/liblfds6.1.0/test/makefile.windows | 64 + .../test/obj/empty_dir_placeholder_for_git | 0 liblfds/liblfds6.1.0/test/src/abstraction.h | 50 + .../test/src/abstraction_cpu_count.c | 81 ++ .../test/src/abstraction_thread_start.c | 141 ++ .../test/src/abstraction_thread_wait.c | 71 + .../test/src/benchmark_freelist.c | 138 ++ .../liblfds6.1.0/test/src/benchmark_queue.c | 142 ++ .../test/src/benchmark_ringbuffer.c | 141 ++ .../liblfds6.1.0/test/src/benchmark_stack.c | 138 ++ liblfds/liblfds6.1.0/test/src/internal.h | 124 ++ liblfds/liblfds6.1.0/test/src/main.c | 87 ++ liblfds/liblfds6.1.0/test/src/misc.c | 124 ++ liblfds/liblfds6.1.0/test/src/structures.h | 227 ++++ .../liblfds6.1.0/test/src/test_abstraction.c | 321 +++++ liblfds/liblfds6.1.0/test/src/test_freelist.c | 685 ++++++++++ liblfds/liblfds6.1.0/test/src/test_queue.c | 527 ++++++++ .../liblfds6.1.0/test/src/test_ringbuffer.c | 480 +++++++ liblfds/liblfds6.1.0/test/src/test_slist.c | 402 ++++++ liblfds/liblfds6.1.0/test/src/test_stack.c | 590 +++++++++ liblfds/liblfds6.1.0/test/test.sln | 79 ++ liblfds/liblfds6.1.0/test/test.vcproj | 415 ++++++ .../bin/empty_dir_placeholder_for_git | 0 liblfds/liblfds6.1.1/liblfds611/building.txt | 40 + liblfds/liblfds6.1.1/liblfds611/dirs | 2 + .../liblfds6.1.1/liblfds611/inc/liblfds611.h | 340 +++++ .../liblfds6.1.1/liblfds611/liblfds611.def | 57 + .../liblfds6.1.1/liblfds611/liblfds611.sln | 38 + .../liblfds6.1.1/liblfds611/liblfds611.vcproj | 800 ++++++++++++ .../liblfds6.1.1/liblfds611/makefile.linux | 106 ++ .../liblfds6.1.1/liblfds611/makefile.windows | 97 ++ .../obj/empty_dir_placeholder_for_git | 0 liblfds/liblfds6.1.1/liblfds611/readme.txt | 147 +++ .../runme_before_win_kernel_build_readme.txt | 32 + ...me_before_win_kernel_dynamic_lib_build.bat | 15 + ...nme_before_win_kernel_static_lib_build.bat | 15 + .../liblfds6.1.1/liblfds611/sources.dynamic | 37 + .../liblfds6.1.1/liblfds611/sources.static | 35 + liblfds/liblfds6.1.1/liblfds611/src/dirs | 3 + .../liblfds611/src/driver_entry.c | 16 + .../liblfds611/src/driver_entry_readme.txt | 4 + .../lfds611_abstraction_cas.c | 71 + .../lfds611_abstraction_dcas.c | 157 +++ .../lfds611_abstraction_free.c | 44 + .../lfds611_abstraction_increment.c | 98 ++ .../lfds611_abstraction_internal_body.h | 2 + .../lfds611_abstraction_internal_wrapper.h | 6 + .../lfds611_abstraction_malloc.c | 40 + .../lfds611_freelist_delete.c | 37 + .../lfds611_freelist_get_and_set.c | 37 + .../lfds611_freelist_internal.h | 42 + .../lfds611_freelist/lfds611_freelist_new.c | 143 ++ .../lfds611_freelist_pop_push.c | 92 ++ .../lfds611_freelist/lfds611_freelist_query.c | 115 ++ ...lfds611_liblfds_abstraction_test_helpers.c | 112 ++ .../lfds611_liblfds_aligned_free.c | 17 + .../lfds611_liblfds_aligned_malloc.c | 32 + .../lfds611_liblfds_internal.h | 4 + .../lfds611_liblfds_readme.txt | 2 + .../src/lfds611_queue/lfds611_queue_delete.c | 57 + .../lfds611_queue/lfds611_queue_internal.h | 60 + .../src/lfds611_queue/lfds611_queue_new.c | 161 +++ .../src/lfds611_queue/lfds611_queue_query.c | 155 +++ .../src/lfds611_queue/lfds611_queue_queue.c | 193 +++ .../lfds611_ringbuffer_delete.c | 22 + .../lfds611_ringbuffer_get_and_put.c | 108 ++ .../lfds611_ringbuffer_internal.h | 24 + .../lfds611_ringbuffer_new.c | 67 + .../lfds611_ringbuffer_query.c | 64 + .../src/lfds611_slist/lfds611_slist_delete.c | 85 ++ .../lfds611_slist/lfds611_slist_get_and_set.c | 135 ++ .../lfds611_slist/lfds611_slist_internal.h | 55 + .../src/lfds611_slist/lfds611_slist_link.c | 57 + .../src/lfds611_slist/lfds611_slist_new.c | 117 ++ .../src/lfds611_stack/lfds611_stack_delete.c | 67 + .../lfds611_stack/lfds611_stack_internal.h | 52 + .../src/lfds611_stack/lfds611_stack_new.c | 159 +++ .../lfds611_stack/lfds611_stack_push_pop.c | 114 ++ .../src/lfds611_stack/lfds611_stack_query.c | 158 +++ .../liblfds611/src/liblfds611_internal.h | 25 + .../test/bin/empty_dir_placeholder_for_git | 0 liblfds/liblfds6.1.1/test/building.txt | 51 + liblfds/liblfds6.1.1/test/makefile.linux | 82 ++ liblfds/liblfds6.1.1/test/makefile.windows | 64 + .../test/obj/empty_dir_placeholder_for_git | 0 liblfds/liblfds6.1.1/test/src/abstraction.h | 50 + .../test/src/abstraction_cpu_count.c | 81 ++ .../test/src/abstraction_thread_start.c | 141 ++ .../test/src/abstraction_thread_wait.c | 71 + .../test/src/benchmark_freelist.c | 138 ++ .../liblfds6.1.1/test/src/benchmark_queue.c | 142 ++ .../test/src/benchmark_ringbuffer.c | 141 ++ .../liblfds6.1.1/test/src/benchmark_stack.c | 138 ++ liblfds/liblfds6.1.1/test/src/internal.h | 124 ++ liblfds/liblfds6.1.1/test/src/main.c | 87 ++ liblfds/liblfds6.1.1/test/src/misc.c | 124 ++ liblfds/liblfds6.1.1/test/src/structures.h | 227 ++++ .../liblfds6.1.1/test/src/test_abstraction.c | 325 +++++ liblfds/liblfds6.1.1/test/src/test_freelist.c | 685 ++++++++++ liblfds/liblfds6.1.1/test/src/test_queue.c | 527 ++++++++ .../liblfds6.1.1/test/src/test_ringbuffer.c | 480 +++++++ liblfds/liblfds6.1.1/test/src/test_slist.c | 402 ++++++ liblfds/liblfds6.1.1/test/src/test_stack.c | 590 +++++++++ liblfds/liblfds6.1.1/test/test.sln | 79 ++ liblfds/liblfds6.1.1/test/test.vcproj | 415 ++++++ .../bin/empty_dir_placeholder_for_git | 0 .../liblfds700/build/gcc_and_gnumake/Makefile | 168 +++ .../build/gcc_kbuild_and_gnumake/Kbuild | 76 ++ .../build/gcc_kbuild_and_gnumake/Makefile | 14 + .../liblfds700.def | 69 + .../sdk_for_windows_7_and_gnumake/makefile | 114 ++ .../liblfds700.def | 69 + .../liblfds700.sln | 46 + .../liblfds700.vcxproj | 705 ++++++++++ .../liblfds700.vcxproj.filters | 279 ++++ .../liblfds700.vcxproj.user | 4 + .../driver_entry.c | 1 + .../liblfds700.def | 69 + .../liblfds700.sln | 46 + .../liblfds700.vcxproj | 733 +++++++++++ .../liblfds700.vcxproj.filters | 279 ++++ .../liblfds700.vcxproj.user | 4 + .../driver_entry.c | 1 + .../liblfds700.def | 69 + .../liblfds700.sln | 59 + .../liblfds700.vcxproj | 1054 +++++++++++++++ .../liblfds700.vcxproj.filters | 279 ++++ .../liblfds700.vcxproj.user | 4 + .../liblfds700/build/wdk_7.1/dirs | 3 + ..._entry_renamed_to_avoid_compiler_warning.c | 23 + .../liblfds700/build/wdk_7.1/liblfds700.def | 69 + .../readme_before_win_kernel_build.txt | 32 + ...me_before_win_kernel_dynamic_lib_build.bat | 22 + ...nme_before_win_kernel_static_lib_build.bat | 21 + .../liblfds700/build/wdk_7.1/sources.dynamic | 62 + .../liblfds700/build/wdk_7.1/sources.static | 60 + .../liblfds7.0.0/liblfds700/inc/liblfds700.h | 31 + .../lfds700_btree_addonly_unbalanced.h | 113 ++ .../inc/liblfds700/lfds700_freelist.h | 54 + .../inc/liblfds700/lfds700_hash_addonly.h | 127 ++ ...fds700_list_addonly_ordered_singlylinked.h | 85 ++ ...s700_list_addonly_singlylinked_unordered.h | 90 ++ .../liblfds700/inc/liblfds700/lfds700_misc.h | 192 +++ ...ds700_porting_abstraction_layer_compiler.h | 478 +++++++ ...rting_abstraction_layer_operating_system.h | 133 ++ ...s700_porting_abstraction_layer_processor.h | 544 ++++++++ .../liblfds700/inc/liblfds700/lfds700_queue.h | 60 + ...ue_bounded_singleconsumer_singleproducer.h | 59 + .../inc/liblfds700/lfds700_ringbuffer.h | 69 + .../liblfds700/inc/liblfds700/lfds700_stack.h | 55 + .../obj/empty_dir_placeholder_for_git | 0 ...lfds700_btree_addonly_unbalanced_cleanup.c | 117 ++ .../lfds700_btree_addonly_unbalanced_get.c | 467 +++++++ .../lfds700_btree_addonly_unbalanced_init.c | 32 + .../lfds700_btree_addonly_unbalanced_insert.c | 156 +++ ...fds700_btree_addonly_unbalanced_internal.h | 23 + .../lfds700_btree_addonly_unbalanced_query.c | 121 ++ .../lfds700_freelist_cleanup.c | 36 + .../lfds700_freelist/lfds700_freelist_init.c | 27 + .../lfds700_freelist_internal.h | 5 + .../lfds700_freelist/lfds700_freelist_pop.c | 52 + .../lfds700_freelist/lfds700_freelist_push.c | 42 + .../lfds700_freelist/lfds700_freelist_query.c | 123 ++ .../lfds700_hash_addonly_cleanup.c | 61 + .../lfds700_hash_addonly_get.c | 37 + .../lfds700_hash_addonly_init.c | 54 + .../lfds700_hash_addonly_insert.c | 62 + .../lfds700_hash_addonly_internal.h | 5 + .../lfds700_hash_addonly_iterate.c | 58 + .../lfds700_hash_addonly_query.c | 112 ++ ...ist_addonly_ordered_singlylinked_cleanup.c | 37 + ...00_list_addonly_ordered_singlylinked_get.c | 29 + ...0_list_addonly_ordered_singlylinked_init.c | 37 + ...list_addonly_ordered_singlylinked_insert.c | 134 ++ ...st_addonly_ordered_singlylinked_internal.h | 5 + ..._list_addonly_ordered_singlylinked_query.c | 121 ++ ...t_addonly_singlylinked_unordered_cleanup.c | 37 + ..._list_addonly_singlylinked_unordered_get.c | 31 + ...list_addonly_singlylinked_unordered_init.c | 35 + ...st_addonly_singlylinked_unordered_insert.c | 193 +++ ..._addonly_singlylinked_unordered_internal.h | 5 + ...ist_addonly_singlylinked_unordered_query.c | 121 ++ .../src/lfds700_misc/lfds700_misc_cleanup.c | 15 + .../src/lfds700_misc/lfds700_misc_globals.c | 11 + .../src/lfds700_misc/lfds700_misc_init.c | 53 + .../src/lfds700_misc/lfds700_misc_internal.h | 10 + .../src/lfds700_misc/lfds700_misc_prng.c | 144 +++ .../src/lfds700_misc/lfds700_misc_query.c | 48 + .../src/lfds700_queue/lfds700_queue_cleanup.c | 48 + .../src/lfds700_queue/lfds700_queue_dequeue.c | 109 ++ .../src/lfds700_queue/lfds700_queue_enqueue.c | 74 ++ .../src/lfds700_queue/lfds700_queue_init.c | 43 + .../lfds700_queue/lfds700_queue_internal.h | 14 + .../src/lfds700_queue/lfds700_queue_query.c | 126 ++ ...ed_singleconsumer_singleproducer_cleanup.c | 30 + ...ed_singleconsumer_singleproducer_dequeue.c | 42 + ...ed_singleconsumer_singleproducer_enqueue.c | 39 + ...unded_singleconsumer_singleproducer_init.c | 63 + ...d_singleconsumer_singleproducer_internal.h | 5 + ...nded_singleconsumer_singleproducer_query.c | 70 + .../lfds700_ringbuffer_cleanup.c | 86 ++ .../lfds700_ringbuffer_init.c | 51 + .../lfds700_ringbuffer_internal.h | 5 + .../lfds700_ringbuffer_query.c | 72 ++ .../lfds700_ringbuffer_read.c | 44 + .../lfds700_ringbuffer_write.c | 78 ++ .../src/lfds700_stack/lfds700_stack_cleanup.c | 36 + .../src/lfds700_stack/lfds700_stack_init.c | 27 + .../lfds700_stack/lfds700_stack_internal.h | 5 + .../src/lfds700_stack/lfds700_stack_pop.c | 52 + .../src/lfds700_stack/lfds700_stack_push.c | 42 + .../src/lfds700_stack/lfds700_stack_query.c | 123 ++ .../liblfds700/src/liblfds700_internal.h | 93 ++ .../test/bin/empty_dir_placeholder_for_git | 0 .../test/build/gcc_and_gnumake/Makefile | 129 ++ .../sdk_for_windows_7_and_gnumake/makefile | 106 ++ .../visual_studio_professional_2012/test.sln | 67 + .../test.vcxproj | 554 ++++++++ .../test.vcxproj.filters | 216 ++++ .../test.vcxproj.user | 4 + .../test/obj/empty_dir_placeholder_for_git | 0 liblfds/liblfds7.0.0/test/src/internal.h | 157 +++ liblfds/liblfds7.0.0/test/src/main.c | 135 ++ liblfds/liblfds7.0.0/test/src/misc.c | 191 +++ .../test_lfds700_btree_addonly_unbalanced.c | 32 + ...ds700_btree_addonly_unbalanced_alignment.c | 64 + ...tree_addonly_unbalanced_random_adds_fail.c | 319 +++++ ...nbalanced_random_adds_fail_and_overwrite.c | 140 ++ ...addonly_unbalanced_random_adds_overwrite.c | 322 +++++ .../test/src/test_lfds700_freelist.c | 33 + .../src/test_lfds700_freelist_alignment.c | 43 + .../test/src/test_lfds700_freelist_popping.c | 205 +++ ...est_lfds700_freelist_popping_and_pushing.c | 319 +++++ .../test/src/test_lfds700_freelist_pushing.c | 246 ++++ ...ds700_freelist_rapid_popping_and_pushing.c | 216 ++++ .../test/src/test_lfds700_hash_addonly.c | 33 + .../src/test_lfds700_hash_addonly_alignment.c | 40 + .../src/test_lfds700_hash_addonly_iterate.c | 224 ++++ ...st_lfds700_hash_addonly_random_adds_fail.c | 314 +++++ ...h_addonly_random_adds_fail_and_overwrite.c | 137 ++ ...ds700_hash_addonly_random_adds_overwrite.c | 388 ++++++ ...fds700_list_addonly_ordered_singlylinked.c | 31 + ...t_addonly_ordered_singlylinked_alignment.c | 58 + ...addonly_ordered_singlylinked_new_ordered.c | 278 ++++ ...red_singlylinked_new_ordered_with_cursor.c | 366 ++++++ ...s700_list_addonly_singlylinked_unordered.c | 32 + ...addonly_singlylinked_unordered_alignment.c | 61 + ...addonly_singlylinked_unordered_new_after.c | 254 ++++ ...t_addonly_singlylinked_unordered_new_end.c | 229 ++++ ...addonly_singlylinked_unordered_new_start.c | 229 ++++ ...lfds700_porting_abstraction_layer_atomic.c | 33 + ...700_porting_abstraction_layer_atomic_cas.c | 176 +++ ...00_porting_abstraction_layer_atomic_dcas.c | 177 +++ ...orting_abstraction_layer_atomic_exchange.c | 333 +++++ .../test/src/test_lfds700_queue.c | 35 + .../test/src/test_lfds700_queue_alignment.c | 55 + ...ue_bounded_singleconsumer_singleproducer.c | 25 + ..._singleconsumer_singleproducer_dequeuing.c | 61 + ..._singleconsumer_singleproducer_enqueuing.c | 59 + ...r_singleproducer_enqueuing_and_dequeuing.c | 260 ++++ .../test/src/test_lfds700_queue_dequeuing.c | 215 ++++ .../test/src/test_lfds700_queue_enqueuing.c | 239 ++++ ...st_lfds700_queue_enqueuing_and_dequeuing.c | 250 ++++ ..._queue_enqueuing_and_dequeuing_with_free.c | 241 ++++ ...uing_with_malloc_and_dequeuing_with_free.c | 208 +++ ...s700_queue_rapid_enqueuing_and_dequeuing.c | 264 ++++ .../test/src/test_lfds700_ringbuffer.c | 31 + .../src/test_lfds700_ringbuffer_reading.c | 217 ++++ ...t_lfds700_ringbuffer_reading_and_writing.c | 261 ++++ .../src/test_lfds700_ringbuffer_writing.c | 272 ++++ .../test/src/test_lfds700_stack.c | 33 + .../test/src/test_lfds700_stack_alignment.c | 43 + .../test/src/test_lfds700_stack_popping.c | 202 +++ .../test_lfds700_stack_popping_and_pushing.c | 316 +++++ .../test/src/test_lfds700_stack_pushing.c | 251 ++++ ..._lfds700_stack_rapid_popping_and_pushing.c | 217 ++++ ...g_abstraction_layer_get_logical_core_ids.c | 245 ++++ ...rting_abstraction_layer_operating_system.h | 82 ++ ...t_porting_abstraction_layer_thread_start.c | 336 +++++ ...st_porting_abstraction_layer_thread_wait.c | 69 + liblfds/liblfds7.0.0/test/src/util_cmdline.c | 184 +++ liblfds/liblfds7.0.0/test/src/util_cmdline.h | 69 + .../test/src/util_memory_helpers.c | 75 ++ .../test/src/util_memory_helpers.h | 5 + .../test/src/util_thread_starter.c | 151 +++ .../test/src/util_thread_starter.h | 41 + .../bin/empty_dir_placeholder_for_git | 0 .../liblfds710/build/gcc_gnumake/Makefile | 176 +++ .../build/gcc_gnumake_kbuild/Kbuild | 86 ++ .../build/gcc_gnumake_kbuild/Makefile | 14 + .../build/msvc_gnumake/liblfds710.def | 75 ++ .../liblfds710/build/msvc_gnumake/makefile | 113 ++ .../liblfds710/build/wdk_7.1/dirs | 3 + ..._entry_renamed_to_avoid_compiler_warning.c | 23 + .../liblfds710/build/wdk_7.1/liblfds710.def | 75 ++ .../readme_before_win_kernel_build.txt | 32 + ...me_before_win_kernel_dynamic_lib_build.bat | 24 + ...nme_before_win_kernel_static_lib_build.bat | 23 + .../liblfds710/build/wdk_7.1/sources.dynamic | 66 + .../liblfds710/build/wdk_7.1/sources.static | 64 + .../liblfds7.1.0/liblfds710/inc/liblfds710.h | 33 + .../lfds710_btree_addonly_unbalanced.h | 121 ++ .../inc/liblfds710/lfds710_freelist.h | 70 + .../inc/liblfds710/lfds710_hash_addonly.h | 136 ++ ...fds710_list_addonly_singlylinked_ordered.h | 87 ++ ...s710_list_addonly_singlylinked_unordered.h | 90 ++ .../liblfds710/inc/liblfds710/lfds710_misc.h | 233 ++++ ...ds710_porting_abstraction_layer_compiler.h | 446 +++++++ ...rting_abstraction_layer_operating_system.h | 86 ++ ...s710_porting_abstraction_layer_processor.h | 459 +++++++ .../liblfds710/inc/liblfds710/lfds710_prng.h | 74 ++ ..._queue_bounded_manyproducer_manyconsumer.h | 66 + ...ue_bounded_singleproducer_singleconsumer.h | 59 + ...ueue_unbounded_manyproducer_manyconsumer.h | 62 + .../inc/liblfds710/lfds710_ringbuffer.h | 66 + .../liblfds710/inc/liblfds710/lfds710_stack.h | 58 + .../obj/empty_dir_placeholder_for_git | 0 ...lfds710_btree_addonly_unbalanced_cleanup.c | 117 ++ .../lfds710_btree_addonly_unbalanced_get.c | 482 +++++++ .../lfds710_btree_addonly_unbalanced_init.c | 33 + .../lfds710_btree_addonly_unbalanced_insert.c | 158 +++ ...fds710_btree_addonly_unbalanced_internal.h | 23 + .../lfds710_btree_addonly_unbalanced_query.c | 126 ++ .../lfds710_freelist_cleanup.c | 36 + .../lfds710_freelist/lfds710_freelist_init.c | 48 + .../lfds710_freelist_internal.h | 7 + .../lfds710_freelist/lfds710_freelist_pop.c | 89 ++ .../lfds710_freelist/lfds710_freelist_push.c | 123 ++ .../lfds710_freelist/lfds710_freelist_query.c | 152 +++ .../lfds710_hash_addonly_cleanup.c | 63 + .../lfds710_hash_addonly_get.c | 47 + .../lfds710_hash_addonly_init.c | 54 + .../lfds710_hash_addonly_insert.c | 60 + .../lfds710_hash_addonly_internal.h | 5 + .../lfds710_hash_addonly_iterate.c | 60 + .../lfds710_hash_addonly_query.c | 119 ++ ...ist_addonly_singlylinked_ordered_cleanup.c | 37 + ...10_list_addonly_singlylinked_ordered_get.c | 29 + ...0_list_addonly_singlylinked_ordered_init.c | 38 + ...list_addonly_singlylinked_ordered_insert.c | 136 ++ ...st_addonly_singlylinked_ordered_internal.h | 5 + ..._list_addonly_singlylinked_ordered_query.c | 128 ++ ...t_addonly_singlylinked_unordered_cleanup.c | 37 + ..._list_addonly_singlylinked_unordered_get.c | 33 + ...list_addonly_singlylinked_unordered_init.c | 35 + ...st_addonly_singlylinked_unordered_insert.c | 193 +++ ..._addonly_singlylinked_unordered_internal.h | 5 + ...ist_addonly_singlylinked_unordered_query.c | 128 ++ .../src/lfds710_misc/lfds710_misc_globals.c | 14 + .../src/lfds710_misc/lfds710_misc_internal.h | 5 + .../lfds710_misc_internal_backoff_init.c | 22 + .../src/lfds710_misc/lfds710_misc_query.c | 38 + .../src/lfds710_prng/lfds710_prng_init.c | 42 + .../src/lfds710_prng/lfds710_prng_internal.h | 5 + ...ounded_manyproducer_manyconsumer_cleanup.c | 27 + ...ounded_manyproducer_manyconsumer_dequeue.c | 86 ++ ...ounded_manyproducer_manyconsumer_enqueue.c | 84 ++ ...e_bounded_manyproducer_manyconsumer_init.c | 42 + ...unded_manyproducer_manyconsumer_internal.h | 5 + ..._bounded_manyproducer_manyconsumer_query.c | 129 ++ ...ed_singleproducer_singleconsumer_cleanup.c | 30 + ...ed_singleproducer_singleconsumer_dequeue.c | 41 + ...ed_singleproducer_singleconsumer_enqueue.c | 38 + ...unded_singleproducer_singleconsumer_init.c | 63 + ...d_singleproducer_singleconsumer_internal.h | 5 + ...nded_singleproducer_singleconsumer_query.c | 87 ++ ...ounded_manyproducer_manyconsumer_cleanup.c | 48 + ...ounded_manyproducer_manyconsumer_dequeue.c | 128 ++ ...ounded_manyproducer_manyconsumer_enqueue.c | 96 ++ ...unbounded_manyproducer_manyconsumer_init.c | 50 + ...unded_manyproducer_manyconsumer_internal.h | 14 + ...nbounded_manyproducer_manyconsumer_query.c | 133 ++ .../lfds710_ringbuffer_cleanup.c | 92 ++ .../lfds710_ringbuffer_init.c | 42 + .../lfds710_ringbuffer_internal.h | 5 + .../lfds710_ringbuffer_query.c | 81 ++ .../lfds710_ringbuffer_read.c | 43 + .../lfds710_ringbuffer_write.c | 77 ++ .../src/lfds710_stack/lfds710_stack_cleanup.c | 36 + .../src/lfds710_stack/lfds710_stack_init.c | 31 + .../lfds710_stack/lfds710_stack_internal.h | 5 + .../src/lfds710_stack/lfds710_stack_pop.c | 57 + .../src/lfds710_stack/lfds710_stack_push.c | 47 + .../src/lfds710_stack/lfds710_stack_query.c | 130 ++ .../liblfds710/src/liblfds710_internal.h | 102 ++ .../bin/empty_dir_placeholder_for_git | 0 .../Makefile | 107 ++ .../Makefile | 107 ++ .../makefile | 87 ++ .../obj/empty_dir_placeholder_for_git | 0 .../benchmark/src/internal.h | 67 + .../test_and_benchmark/benchmark/src/main.c | 489 +++++++ .../test_and_benchmark/benchmark/src/misc.c | 37 + .../benchmark/src/porting_abstraction_layer.h | 5 + .../src/porting_abstraction_layer_numa_free.c | 60 + .../porting_abstraction_layer_numa_malloc.c | 89 ++ ...rting_abstraction_layer_operating_system.h | 111 ++ .../benchmark/src/util_cmdline.c | 193 +++ .../benchmark/src/util_cmdline.h | 82 ++ .../bin/empty_dir_placeholder_for_git | 0 .../libbenchmark/build/gcc_gnumake/Makefile | 174 +++ .../build/gcc_gnumake_kbuild/Kbuild | 130 ++ .../build/gcc_gnumake_kbuild/Makefile | 14 + .../this build is currently broken.txt | 11 + .../build/msvc_gnumake/libbenchmark.def | 25 + .../libbenchmark/build/msvc_gnumake/makefile | 117 ++ .../libbenchmark/build/wdk_7.1/dirs | 3 + ..._entry_renamed_to_avoid_compiler_warning.c | 23 + .../build/wdk_7.1/libbenchmark.def | 25 + .../readme_before_win_kernel_build.txt | 32 + ...me_before_win_kernel_dynamic_lib_build.bat | 27 + ...nme_before_win_kernel_static_lib_build.bat | 26 + .../build/wdk_7.1/sources.dynamic | 109 ++ .../libbenchmark/build/wdk_7.1/sources.static | 107 ++ .../libbenchmark/inc/libbenchmark.h | 82 ++ .../libbenchmark_benchmarkinstance.h | 62 + ...nchmark_benchmarks_btree_au_readn_writen.h | 37 + ...mark_benchmarks_freelist_push1_then_pop1.h | 37 + ...chmarks_queue_umm_enqueue1_then_dequeue1.h | 37 + .../libbenchmark/libbenchmark_benchmarkset.h | 66 + .../libbenchmark_benchmarksuite.h | 42 + ...tastructure_btree_au_gcc_spinlock_atomic.h | 101 ++ ...datastructure_btree_au_gcc_spinlock_sync.h | 101 ++ ...ark_datastructure_btree_au_msvc_spinlock.h | 101 ++ ...ark_datastructure_btree_au_pthread_mutex.h | 101 ++ ...rk_datastructure_btree_au_pthread_rwlock.h | 106 ++ ...tree_au_pthread_spinlock_process_private.h | 101 ++ ...btree_au_pthread_spinlock_process_shared.h | 101 ++ ...ucture_btree_au_windows_critical_section.h | 101 ++ ...ark_datastructure_btree_au_windows_mutex.h | 101 ++ ...tastructure_freelist_gcc_spinlock_atomic.h | 37 + ...datastructure_freelist_gcc_spinlock_sync.h | 37 + ...ark_datastructure_freelist_msvc_spinlock.h | 37 + ...ark_datastructure_freelist_pthread_mutex.h | 37 + ...rk_datastructure_freelist_pthread_rwlock.h | 37 + ...reelist_pthread_spinlock_process_private.h | 37 + ...freelist_pthread_spinlock_process_shared.h | 37 + ...ucture_freelist_windows_critical_section.h | 37 + ...ark_datastructure_freelist_windows_mutex.h | 37 + ...astructure_queue_umm_gcc_spinlock_atomic.h | 47 + ...atastructure_queue_umm_gcc_spinlock_sync.h | 47 + ...rk_datastructure_queue_umm_msvc_spinlock.h | 47 + ...rk_datastructure_queue_umm_pthread_mutex.h | 47 + ...k_datastructure_queue_umm_pthread_rwlock.h | 47 + ...eue_umm_pthread_spinlock_process_private.h | 47 + ...ueue_umm_pthread_spinlock_process_shared.h | 47 + ...cture_queue_umm_windows_critical_section.h | 47 + ...rk_datastructure_queue_umm_windows_mutex.h | 47 + .../inc/libbenchmark/libbenchmark_enums.h | 32 + .../inc/libbenchmark/libbenchmark_gnuplot.h | 30 + .../inc/libbenchmark/libbenchmark_misc.h | 56 + .../libbenchmark_porting_abstraction_layer.h | 18 + ...straction_layer_lock_gcc_spinlock_atomic.h | 57 + ...abstraction_layer_lock_gcc_spinlock_sync.h | 53 + ...ing_abstraction_layer_lock_msvc_spinlock.h | 80 ++ ...ing_abstraction_layer_lock_pthread_mutex.h | 45 + ...ng_abstraction_layer_lock_pthread_rwlock.h | 47 + ...er_lock_pthread_spinlock_process_private.h | 45 + ...yer_lock_pthread_spinlock_process_shared.h | 45 + ...tion_layer_lock_windows_critical_section.h | 46 + ...ing_abstraction_layer_lock_windows_mutex.h | 46 + ...rting_abstraction_layer_operating_system.h | 118 ++ .../inc/libbenchmark/libbenchmark_prng.h | 64 + .../inc/libbenchmark/libbenchmark_results.h | 67 + .../inc/libbenchmark/libbenchmark_threadset.h | 75 ++ .../inc/libbenchmark/libbenchmark_topology.h | 81 ++ .../libbenchmark/libbenchmark_topology_node.h | 114 ++ .../obj/empty_dir_placeholder_for_git | 0 .../libbenchmark_benchmarkinstance_cleanup.c | 21 + .../libbenchmark_benchmarkinstance_init.c | 41 + .../libbenchmark_benchmarkinstance_internal.h | 5 + .../libbenchmark_benchmarkinstance_run.c | 99 ++ ...tree_au_gcc_spinlock_atomic_readn_writen.c | 550 ++++++++ ..._btree_au_gcc_spinlock_sync_readn_writen.c | 550 ++++++++ ...ibbenchmark_benchmarks_btree_au_internal.h | 5 + ...tree_au_liblfds700_lockfree_readn_writen.c | 554 ++++++++ ...tree_au_liblfds710_lockfree_readn_writen.c | 549 ++++++++ ...arks_btree_au_msvc_spinlock_readn_writen.c | 550 ++++++++ ...arks_btree_au_pthread_mutex_readn_writen.c | 550 ++++++++ ...rks_btree_au_pthread_rwlock_readn_writen.c | 550 ++++++++ ...ad_spinlock_process_private_readn_writen.c | 550 ++++++++ ...ead_spinlock_process_shared_readn_writen.c | 550 ++++++++ ...au_windows_critical_section_readn_writen.c | 551 ++++++++ ...arks_btree_au_windows_mutex_readn_writen.c | 550 ++++++++ ...list_gcc_spinlock_atomic_push1_then_pop1.c | 316 +++++ ...eelist_gcc_spinlock_sync_push1_then_pop1.c | 316 +++++ ...ibbenchmark_benchmarks_freelist_internal.h | 5 + ...list_liblfds700_lockfree_push1_then_pop1.c | 380 ++++++ ...list_liblfds710_lockfree_push1_then_pop1.c | 430 +++++++ ...s_freelist_msvc_spinlock_push1_then_pop1.c | 316 +++++ ...s_freelist_pthread_mutex_push1_then_pop1.c | 316 +++++ ..._freelist_pthread_rwlock_push1_then_pop1.c | 316 +++++ ...spinlock_process_private_push1_then_pop1.c | 316 +++++ ..._spinlock_process_shared_push1_then_pop1.c | 316 +++++ ...windows_critical_section_push1_then_pop1.c | 316 +++++ ...s_freelist_windows_mutex_push1_then_pop1.c | 316 +++++ ...mm_gcc_spinlock_atomic_enqueue1_dequeue1.c | 344 +++++ ..._umm_gcc_spinlock_sync_enqueue1_dequeue1.c | 344 +++++ ...bbenchmark_benchmarks_queue_umm_internal.h | 5 + ...mm_liblfds700_lockfree_enqueue1_dequeue1.c | 368 ++++++ ...mm_liblfds710_lockfree_enqueue1_dequeue1.c | 358 ++++++ ...ueue_umm_msvc_spinlock_enqueue1_dequeue1.c | 344 +++++ ...ueue_umm_pthread_mutex_enqueue1_dequeue1.c | 344 +++++ ...eue_umm_pthread_rwlock_enqueue1_dequeue1.c | 344 +++++ ...inlock_process_private_enqueue1_dequeue1.c | 344 +++++ ...pinlock_process_shared_enqueue1_dequeue1.c | 344 +++++ ...ndows_critical_section_enqueue1_dequeue1.c | 344 +++++ ...ueue_umm_windows_mutex_enqueue1_dequeue1.c | 344 +++++ .../libbenchmark_benchmarkset_add.c | 19 + .../libbenchmark_benchmarkset_cleanup.c | 19 + .../libbenchmark_benchmarkset_gnuplot.c | 594 +++++++++ .../libbenchmark_benchmarkset_init.c | 35 + .../libbenchmark_benchmarkset_internal.h | 5 + .../libbenchmark_benchmarkset_run.c | 54 + .../libbenchmark_benchmarksuite_add.c | 20 + .../libbenchmark_benchmarksuite_cleanup.c | 19 + .../libbenchmark_benchmarksuite_gnuplot.c | 57 + .../libbenchmark_benchmarksuite_init.c | 286 ++++ .../libbenchmark_benchmarksuite_internal.h | 5 + .../libbenchmark_benchmarksuite_run.c | 37 + ...tastructure_btree_au_gcc_spinlock_atomic.c | 564 ++++++++ ...datastructure_btree_au_gcc_spinlock_sync.c | 564 ++++++++ ...enchmark_datastructure_btree_au_internal.h | 23 + ...ark_datastructure_btree_au_msvc_spinlock.c | 564 ++++++++ ...ark_datastructure_btree_au_pthread_mutex.c | 564 ++++++++ ...rk_datastructure_btree_au_pthread_rwlock.c | 609 +++++++++ ...tree_au_pthread_spinlock_process_private.c | 572 ++++++++ ...btree_au_pthread_spinlock_process_shared.c | 572 ++++++++ ...ucture_btree_au_windows_critical_section.c | 563 ++++++++ ...ark_datastructure_btree_au_windows_mutex.c | 564 ++++++++ ...tastructure_freelist_gcc_spinlock_atomic.c | 110 ++ ...datastructure_freelist_gcc_spinlock_sync.c | 110 ++ ...enchmark_datastructure_freelist_internal.h | 5 + ...ark_datastructure_freelist_msvc_spinlock.c | 110 ++ ...ark_datastructure_freelist_pthread_mutex.c | 110 ++ ...rk_datastructure_freelist_pthread_rwlock.c | 110 ++ ...reelist_pthread_spinlock_process_private.c | 110 ++ ...freelist_pthread_spinlock_process_shared.c | 110 ++ ...ucture_freelist_windows_critical_section.c | 110 ++ ...ark_datastructure_freelist_windows_mutex.c | 110 ++ ...astructure_queue_umm_gcc_spinlock_atomic.c | 112 ++ ...atastructure_queue_umm_gcc_spinlock_sync.c | 112 ++ ...nchmark_datastructure_queue_umm_internal.h | 5 + ...rk_datastructure_queue_umm_msvc_spinlock.c | 112 ++ ...rk_datastructure_queue_umm_pthread_mutex.c | 112 ++ ...k_datastructure_queue_umm_pthread_rwlock.c | 112 ++ ...eue_umm_pthread_spinlock_process_private.c | 112 ++ ...ueue_umm_pthread_spinlock_process_shared.c | 112 ++ ...cture_queue_umm_windows_critical_section.c | 112 ++ ...rk_datastructure_queue_umm_windows_mutex.c | 112 ++ .../libbenchmark/src/libbenchmark_internal.h | 52 + .../libbenchmark_misc_globals.c | 46 + .../libbenchmark_misc_internal.h | 5 + .../libbenchmark_misc_pal_helpers.c | 192 +++ .../libbenchmark_misc_query.c | 36 + ...hmark_porting_abstraction_layer_internal.h | 5 + ...ting_abstraction_layer_populate_topology.c | 1145 +++++++++++++++++ ...k_porting_abstraction_layer_print_string.c | 64 + .../libbenchmark_results_cleanup.c | 19 + .../libbenchmark_results_compare.c | 58 + .../libbenchmark_results_get_result.c | 54 + .../libbenchmark_results_init.c | 21 + .../libbenchmark_results_internal.h | 5 + .../libbenchmark_results_put_result.c | 50 + .../libbenchmark_threadset_cleanup.c | 21 + .../libbenchmark_threadset_init.c | 105 ++ .../libbenchmark_threadset_internal.h | 5 + .../libbenchmark_threadset_operations.c | 66 + .../libbenchmark_topology_cleanup.c | 19 + .../libbenchmark_topology_compare.c | 55 + .../libbenchmark_topology_init.c | 65 + .../libbenchmark_topology_insert.c | 20 + .../libbenchmark_topology_internal.h | 19 + .../libbenchmark_topology_iterate.c | 50 + .../libbenchmark_topology_lpsets.c | 515 ++++++++ .../libbenchmark_topology_numa.c | 65 + .../libbenchmark_topology_query.c | 87 ++ .../libbenchmark_topology_string.c | 399 ++++++ .../libbenchmark_topology_node_cleanup.c | 18 + .../libbenchmark_topology_node_compare.c | 487 +++++++ .../libbenchmark_topology_node_init.c | 18 + .../libbenchmark_topology_node_internal.h | 5 + .../bin/empty_dir_placeholder_for_git | 0 .../libshared/build/gcc_gnumake/Makefile | 161 +++ .../libshared/build/gcc_gnumake_kbuild/Kbuild | 32 + .../build/gcc_gnumake_kbuild/Makefile | 14 + .../this build is currently broken.txt | 9 + .../build/msvc_gnumake/libshared.def | 26 + .../libshared/build/msvc_gnumake/makefile | 106 ++ .../libshared/build/wdk_7.1/dirs | 3 + ..._entry_renamed_to_avoid_compiler_warning.c | 23 + .../libshared/build/wdk_7.1/libshared.def | 26 + .../readme_before_win_kernel_build.txt | 32 + ...me_before_win_kernel_dynamic_lib_build.bat | 16 + ...nme_before_win_kernel_static_lib_build.bat | 15 + .../libshared/build/wdk_7.1/sources.dynamic | 25 + .../libshared/build/wdk_7.1/sources.static | 23 + .../libshared/inc/libshared.h | 26 + .../libshared/inc/libshared/libshared_ansi.h | 14 + .../inc/libshared/libshared_memory.h | 63 + .../libshared/inc/libshared/libshared_misc.h | 15 + .../libshared_porting_abstraction_layer.h | 30 + ...rting_abstraction_layer_operating_system.h | 126 ++ .../obj/empty_dir_placeholder_for_git | 0 .../libshared_ansi/libshared_ansi_internal.h | 5 + .../libshared_ansi/libshared_ansi_strcat.c | 20 + .../libshared_ansi_strcat_char.c | 21 + .../libshared_ansi_strcat_number.c | 111 ++ .../libshared_ansi/libshared_ansi_strcpy.c | 22 + .../libshared_ansi/libshared_ansi_strlen.c | 22 + .../libshared/src/libshared_internal.h | 45 + .../libshared_memory/libshared_memory_add.c | 93 ++ .../libshared_memory/libshared_memory_alloc.c | 194 +++ .../libshared_memory_cleanup.c | 40 + .../libshared_memory/libshared_memory_init.c | 17 + .../libshared_memory_internal.h | 5 + .../libshared_memory/libshared_memory_query.c | 49 + .../libshared_memory_rollback.c | 55 + .../libshared_misc/libshared_misc_internal.h | 5 + .../src/libshared_misc/libshared_misc_query.c | 36 + ...hared_porting_abstraction_layer_internal.h | 5 + ...d_porting_abstraction_layer_thread_start.c | 430 +++++++ ...ed_porting_abstraction_layer_thread_wait.c | 115 ++ .../libtest/bin/empty_dir_placeholder_for_git | 0 .../libtest/build/gcc_gnumake_hosted/Makefile | 174 +++ .../libtest/build/gcc_gnumake_kbuild/Kbuild | 99 ++ .../libtest/build/gcc_gnumake_kbuild/Makefile | 14 + .../libtest/build/msvc_gnumake/libtest.def | 14 + .../libtest/build/msvc_gnumake/makefile | 120 ++ .../libtest/build/wdk_7.1/dirs | 3 + ..._entry_renamed_to_avoid_compiler_warning.c | 23 + .../libtest/build/wdk_7.1/libtest.def | 14 + .../readme_before_win_kernel_build.txt | 32 + ...me_before_win_kernel_dynamic_lib_build.bat | 19 + ...nme_before_win_kernel_static_lib_build.bat | 18 + .../libtest/build/wdk_7.1/sources.dynamic | 87 ++ .../libtest/build/wdk_7.1/sources.static | 85 ++ .../test_and_benchmark/libtest/inc/libtest.h | 26 + .../libtest/inc/libtest/libtest_misc.h | 43 + .../libtest_porting_abstraction_layer.h | 36 + ...btest_porting_abstraction_layer_compiler.h | 63 + ...rting_abstraction_layer_operating_system.h | 92 ++ .../libtest/inc/libtest/libtest_results.h | 22 + .../libtest/inc/libtest/libtest_test.h | 28 + .../libtest/inc/libtest/libtest_tests.h | 140 ++ .../libtest/inc/libtest/libtest_testsuite.h | 34 + .../libtest/inc/libtest/libtest_threadset.h | 56 + .../libtest/obj/empty_dir_placeholder_for_git | 0 .../libtest/src/libtest_internal.h | 47 + .../libtest_misc/libtest_misc_determine_erg.c | 300 +++++ .../src/libtest_misc/libtest_misc_globals.c | 22 + .../src/libtest_misc/libtest_misc_internal.h | 5 + .../libtest_misc_memory_helpers.c | 52 + .../libtest_misc/libtest_misc_pal_helpers.c | 32 + .../src/libtest_misc/libtest_misc_query.c | 36 + .../libtest_porting_abstraction_layer_free.c | 116 ++ ...ion_layer_get_full_logical_processor_set.c | 285 ++++ ...btest_porting_abstraction_layer_internal.h | 5 + ...libtest_porting_abstraction_layer_malloc.c | 132 ++ .../libtest_results/libtest_results_cleanup.c | 19 + .../libtest_results_get_result.c | 19 + .../libtest_results/libtest_results_init.c | 21 + .../libtest_results_internal.h | 5 + .../libtest_results_put_result.c | 19 + .../src/libtest_test/libtest_test_cleanup.c | 21 + .../src/libtest_test/libtest_test_init.c | 25 + .../src/libtest_test/libtest_test_internal.h | 5 + .../src/libtest_test/libtest_test_run.c | 23 + ...tests_btree_addonly_unbalanced_alignment.c | 49 + ...tree_addonly_unbalanced_random_adds_fail.c | 299 +++++ ...nbalanced_random_adds_fail_and_overwrite.c | 135 ++ ...addonly_unbalanced_random_adds_overwrite.c | 304 +++++ .../libtest_tests_freelist_alignment.c | 37 + .../libtest_tests_freelist_ea_popping.c | 222 ++++ ...st_tests_freelist_ea_popping_and_pushing.c | 310 +++++ .../libtest_tests_freelist_ea_pushing.c | 210 +++ ...ts_freelist_ea_rapid_popping_and_pushing.c | 222 ++++ ...ibtest_tests_freelist_without_ea_popping.c | 180 +++ ..._freelist_without_ea_popping_and_pushing.c | 279 ++++ ...ibtest_tests_freelist_without_ea_pushing.c | 222 ++++ ...ist_without_ea_rapid_popping_and_pushing.c | 189 +++ .../libtest_tests_hash_addonly_alignment.c | 34 + ...st_tests_hash_addonly_fail_and_overwrite.c | 124 ++ .../libtest_tests_hash_addonly_iterate.c | 191 +++ ...test_tests_hash_addonly_random_adds_fail.c | 292 +++++ ...tests_hash_addonly_random_adds_overwrite.c | 359 ++++++ .../libtest_tests/libtest_tests_internal.h | 10 + ...t_addonly_singlylinked_ordered_alignment.c | 46 + ...addonly_singlylinked_ordered_new_ordered.c | 256 ++++ ...lylinked_ordered_new_ordered_with_cursor.c | 342 +++++ ...addonly_singlylinked_unordered_alignment.c | 49 + ...addonly_singlylinked_unordered_new_after.c | 226 ++++ ...t_addonly_singlylinked_unordered_new_end.c | 205 +++ ...addonly_singlylinked_unordered_new_start.c | 205 +++ ...sts_porting_abstraction_layer_atomic_add.c | 202 +++ ...sts_porting_abstraction_layer_atomic_cas.c | 166 +++ ...s_porting_abstraction_layer_atomic_dwcas.c | 163 +++ ...orting_abstraction_layer_atomic_exchange.c | 324 +++++ .../libtest_tests_prng_alignment.c | 27 + .../libtest_tests_prng_generate.c | 217 ++++ ...nded_manyproducer_manyconsumer_alignment.c | 37 + ..._bounded_manyproducer_manyconsumer_count.c | 80 ++ ...nded_manyproducer_manyconsumer_dequeuing.c | 175 +++ ...nded_manyproducer_manyconsumer_enqueuing.c | 183 +++ ...cer_manyconsumer_enqueuing_and_dequeuing.c | 226 ++++ ...nyconsumer_rapid_enqueuing_and_dequeuing.c | 213 +++ ..._singleproducer_singleconsumer_dequeuing.c | 63 + ..._singleproducer_singleconsumer_enqueuing.c | 62 + ...r_singleconsumer_enqueuing_and_dequeuing.c | 247 ++++ ...nded_manyproducer_manyconsumer_alignment.c | 49 + ...nded_manyproducer_manyconsumer_dequeuing.c | 180 +++ ...nded_manyproducer_manyconsumer_enqueuing.c | 212 +++ ...cer_manyconsumer_enqueuing_and_dequeuing.c | 223 ++++ ...uing_with_malloc_and_dequeuing_with_free.c | 161 +++ ...nyconsumer_rapid_enqueuing_and_dequeuing.c | 223 ++++ .../libtest_tests_ringbuffer_reading.c | 196 +++ ...est_tests_ringbuffer_reading_and_writing.c | 235 ++++ .../libtest_tests_ringbuffer_writing.c | 242 ++++ .../libtest_tests_stack_alignment.c | 37 + .../libtest_tests_stack_popping.c | 179 +++ .../libtest_tests_stack_popping_and_pushing.c | 275 ++++ .../libtest_tests_stack_pushing.c | 213 +++ ...st_tests_stack_rapid_popping_and_pushing.c | 185 +++ .../libtest_testsuite_cleanup.c | 17 + .../libtest_testsuite_init.c | 188 +++ .../libtest_testsuite_internal.h | 5 + .../libtest_testsuite/libtest_testsuite_run.c | 35 + .../libtest_threadset/libtest_threadset_add.c | 35 + .../libtest_threadset_cleanup.c | 21 + .../libtest_threadset_init.c | 22 + .../libtest_threadset_internal.h | 5 + .../libtest_threadset_operations.c | 60 + .../test/bin/empty_dir_placeholder_for_git | 0 .../test/build/gcc_gnumake_hosted/Makefile | 112 ++ .../test/build/msvc_gnumake/makefile | 93 ++ .../test/obj/empty_dir_placeholder_for_git | 0 .../test_and_benchmark/test/src/callbacks.c | 32 + .../test_and_benchmark/test/src/internal.h | 67 + .../test_and_benchmark/test/src/main.c | 282 ++++ .../test_and_benchmark/test/src/misc.c | 33 + .../test/src/util_cmdline.c | 184 +++ .../test/src/util_cmdline.h | 69 + .../what do we have here.txt | 16 + liblfds/versioning.txt | 7 + 959 files changed, 115245 insertions(+) create mode 100644 liblfds/liblfds6.0.0/liblfds600/bin/empty_dir_placeholder_for_git create mode 100644 liblfds/liblfds6.0.0/liblfds600/building.txt create mode 100644 liblfds/liblfds6.0.0/liblfds600/dirs create mode 100644 liblfds/liblfds6.0.0/liblfds600/inc/liblfds600.h create mode 100644 liblfds/liblfds6.0.0/liblfds600/liblfds600.def create mode 100644 liblfds/liblfds6.0.0/liblfds600/liblfds600.sln create mode 100644 liblfds/liblfds6.0.0/liblfds600/liblfds600.vcproj create mode 100644 liblfds/liblfds6.0.0/liblfds600/makefile.linux create mode 100644 liblfds/liblfds6.0.0/liblfds600/makefile.windows create mode 100644 liblfds/liblfds6.0.0/liblfds600/obj/empty_dir_placeholder_for_git create mode 100644 liblfds/liblfds6.0.0/liblfds600/readme.txt create mode 100644 liblfds/liblfds6.0.0/liblfds600/runme_before_win_kernel_build_readme.txt create mode 100644 liblfds/liblfds6.0.0/liblfds600/runme_before_win_kernel_dynamic_lib_build.bat create mode 100644 liblfds/liblfds6.0.0/liblfds600/runme_before_win_kernel_static_lib_build.bat create mode 100644 liblfds/liblfds6.0.0/liblfds600/sources.dynamic create mode 100644 liblfds/liblfds6.0.0/liblfds600/sources.static create mode 100644 liblfds/liblfds6.0.0/liblfds600/src/dirs create mode 100644 liblfds/liblfds6.0.0/liblfds600/src/driver_entry.c create mode 100644 liblfds/liblfds6.0.0/liblfds600/src/driver_entry_readme.txt create mode 100644 liblfds/liblfds6.0.0/liblfds600/src/lfds600_abstraction/lfds600_abstraction_aligned_free.c create mode 100644 liblfds/liblfds6.0.0/liblfds600/src/lfds600_abstraction/lfds600_abstraction_aligned_malloc.c create mode 100644 liblfds/liblfds6.0.0/liblfds600/src/lfds600_abstraction/lfds600_abstraction_cas.c create mode 100644 liblfds/liblfds6.0.0/liblfds600/src/lfds600_abstraction/lfds600_abstraction_dcas.c create mode 100644 liblfds/liblfds6.0.0/liblfds600/src/lfds600_abstraction/lfds600_abstraction_increment.c create mode 100644 liblfds/liblfds6.0.0/liblfds600/src/lfds600_abstraction/lfds600_abstraction_internal.h create mode 100644 liblfds/liblfds6.0.0/liblfds600/src/lfds600_freelist/lfds600_freelist_delete.c create mode 100644 liblfds/liblfds6.0.0/liblfds600/src/lfds600_freelist/lfds600_freelist_get_and_set.c create mode 100644 liblfds/liblfds6.0.0/liblfds600/src/lfds600_freelist/lfds600_freelist_internal.h create mode 100644 liblfds/liblfds6.0.0/liblfds600/src/lfds600_freelist/lfds600_freelist_new.c create mode 100644 liblfds/liblfds6.0.0/liblfds600/src/lfds600_freelist/lfds600_freelist_pop_push.c create mode 100644 liblfds/liblfds6.0.0/liblfds600/src/lfds600_freelist/lfds600_freelist_query.c create mode 100644 liblfds/liblfds6.0.0/liblfds600/src/lfds600_internal.h create mode 100644 liblfds/liblfds6.0.0/liblfds600/src/lfds600_queue/lfds600_queue_delete.c create mode 100644 liblfds/liblfds6.0.0/liblfds600/src/lfds600_queue/lfds600_queue_internal.h create mode 100644 liblfds/liblfds6.0.0/liblfds600/src/lfds600_queue/lfds600_queue_new.c create mode 100644 liblfds/liblfds6.0.0/liblfds600/src/lfds600_queue/lfds600_queue_query.c create mode 100644 liblfds/liblfds6.0.0/liblfds600/src/lfds600_queue/lfds600_queue_queue.c create mode 100644 liblfds/liblfds6.0.0/liblfds600/src/lfds600_ringbuffer/lfds600_ringbuffer_delete.c create mode 100644 liblfds/liblfds6.0.0/liblfds600/src/lfds600_ringbuffer/lfds600_ringbuffer_get_and_put.c create mode 100644 liblfds/liblfds6.0.0/liblfds600/src/lfds600_ringbuffer/lfds600_ringbuffer_internal.h create mode 100644 liblfds/liblfds6.0.0/liblfds600/src/lfds600_ringbuffer/lfds600_ringbuffer_new.c create mode 100644 liblfds/liblfds6.0.0/liblfds600/src/lfds600_ringbuffer/lfds600_ringbuffer_query.c create mode 100644 liblfds/liblfds6.0.0/liblfds600/src/lfds600_slist/lfds600_slist_delete.c create mode 100644 liblfds/liblfds6.0.0/liblfds600/src/lfds600_slist/lfds600_slist_get_and_set.c create mode 100644 liblfds/liblfds6.0.0/liblfds600/src/lfds600_slist/lfds600_slist_internal.h create mode 100644 liblfds/liblfds6.0.0/liblfds600/src/lfds600_slist/lfds600_slist_link.c create mode 100644 liblfds/liblfds6.0.0/liblfds600/src/lfds600_slist/lfds600_slist_new.c create mode 100644 liblfds/liblfds6.0.0/liblfds600/src/lfds600_stack/lfds600_stack_delete.c create mode 100644 liblfds/liblfds6.0.0/liblfds600/src/lfds600_stack/lfds600_stack_internal.h create mode 100644 liblfds/liblfds6.0.0/liblfds600/src/lfds600_stack/lfds600_stack_new.c create mode 100644 liblfds/liblfds6.0.0/liblfds600/src/lfds600_stack/lfds600_stack_push_pop.c create mode 100644 liblfds/liblfds6.0.0/liblfds600/src/lfds600_stack/lfds600_stack_query.c create mode 100644 liblfds/liblfds6.0.0/test/bin/empty_dir_placeholder_for_git create mode 100644 liblfds/liblfds6.0.0/test/building.txt create mode 100644 liblfds/liblfds6.0.0/test/makefile.linux create mode 100644 liblfds/liblfds6.0.0/test/makefile.windows create mode 100644 liblfds/liblfds6.0.0/test/obj/empty_dir_placeholder_for_git create mode 100644 liblfds/liblfds6.0.0/test/src/abstraction.h create mode 100644 liblfds/liblfds6.0.0/test/src/abstraction_cpu_count.c create mode 100644 liblfds/liblfds6.0.0/test/src/abstraction_thread_start.c create mode 100644 liblfds/liblfds6.0.0/test/src/abstraction_thread_wait.c create mode 100644 liblfds/liblfds6.0.0/test/src/benchmark_freelist.c create mode 100644 liblfds/liblfds6.0.0/test/src/benchmark_queue.c create mode 100644 liblfds/liblfds6.0.0/test/src/benchmark_ringbuffer.c create mode 100644 liblfds/liblfds6.0.0/test/src/benchmark_stack.c create mode 100644 liblfds/liblfds6.0.0/test/src/internal.h create mode 100644 liblfds/liblfds6.0.0/test/src/main.c create mode 100644 liblfds/liblfds6.0.0/test/src/misc.c create mode 100644 liblfds/liblfds6.0.0/test/src/structures.h create mode 100644 liblfds/liblfds6.0.0/test/src/test_abstraction.c create mode 100644 liblfds/liblfds6.0.0/test/src/test_freelist.c create mode 100644 liblfds/liblfds6.0.0/test/src/test_queue.c create mode 100644 liblfds/liblfds6.0.0/test/src/test_ringbuffer.c create mode 100644 liblfds/liblfds6.0.0/test/src/test_slist.c create mode 100644 liblfds/liblfds6.0.0/test/src/test_stack.c create mode 100644 liblfds/liblfds6.0.0/test/test.sln create mode 100644 liblfds/liblfds6.0.0/test/test.vcproj create mode 100644 liblfds/liblfds6.0.1/liblfds601/bin/empty_dir_placeholder_for_git create mode 100644 liblfds/liblfds6.0.1/liblfds601/building.txt create mode 100644 liblfds/liblfds6.0.1/liblfds601/dirs create mode 100644 liblfds/liblfds6.0.1/liblfds601/inc/liblfds601.h create mode 100644 liblfds/liblfds6.0.1/liblfds601/liblfds601.def create mode 100644 liblfds/liblfds6.0.1/liblfds601/liblfds601.sln create mode 100644 liblfds/liblfds6.0.1/liblfds601/liblfds601.vcproj create mode 100644 liblfds/liblfds6.0.1/liblfds601/makefile.linux create mode 100644 liblfds/liblfds6.0.1/liblfds601/makefile.windows create mode 100644 liblfds/liblfds6.0.1/liblfds601/obj/empty_dir_placeholder_for_git create mode 100644 liblfds/liblfds6.0.1/liblfds601/readme.txt create mode 100644 liblfds/liblfds6.0.1/liblfds601/runme_before_win_kernel_build_readme.txt create mode 100644 liblfds/liblfds6.0.1/liblfds601/runme_before_win_kernel_dynamic_lib_build.bat create mode 100644 liblfds/liblfds6.0.1/liblfds601/runme_before_win_kernel_static_lib_build.bat create mode 100644 liblfds/liblfds6.0.1/liblfds601/sources.dynamic create mode 100644 liblfds/liblfds6.0.1/liblfds601/sources.static create mode 100644 liblfds/liblfds6.0.1/liblfds601/src/dirs create mode 100644 liblfds/liblfds6.0.1/liblfds601/src/driver_entry.c create mode 100644 liblfds/liblfds6.0.1/liblfds601/src/driver_entry_readme.txt create mode 100644 liblfds/liblfds6.0.1/liblfds601/src/lfds601_abstraction/lfds601_abstraction_aligned_free.c create mode 100644 liblfds/liblfds6.0.1/liblfds601/src/lfds601_abstraction/lfds601_abstraction_aligned_malloc.c create mode 100644 liblfds/liblfds6.0.1/liblfds601/src/lfds601_abstraction/lfds601_abstraction_cas.c create mode 100644 liblfds/liblfds6.0.1/liblfds601/src/lfds601_abstraction/lfds601_abstraction_dcas.c create mode 100644 liblfds/liblfds6.0.1/liblfds601/src/lfds601_abstraction/lfds601_abstraction_increment.c create mode 100644 liblfds/liblfds6.0.1/liblfds601/src/lfds601_abstraction/lfds601_abstraction_internal.h create mode 100644 liblfds/liblfds6.0.1/liblfds601/src/lfds601_freelist/lfds601_freelist_delete.c create mode 100644 liblfds/liblfds6.0.1/liblfds601/src/lfds601_freelist/lfds601_freelist_get_and_set.c create mode 100644 liblfds/liblfds6.0.1/liblfds601/src/lfds601_freelist/lfds601_freelist_internal.h create mode 100644 liblfds/liblfds6.0.1/liblfds601/src/lfds601_freelist/lfds601_freelist_new.c create mode 100644 liblfds/liblfds6.0.1/liblfds601/src/lfds601_freelist/lfds601_freelist_pop_push.c create mode 100644 liblfds/liblfds6.0.1/liblfds601/src/lfds601_freelist/lfds601_freelist_query.c create mode 100644 liblfds/liblfds6.0.1/liblfds601/src/lfds601_internal.h create mode 100644 liblfds/liblfds6.0.1/liblfds601/src/lfds601_queue/lfds601_queue_delete.c create mode 100644 liblfds/liblfds6.0.1/liblfds601/src/lfds601_queue/lfds601_queue_internal.h create mode 100644 liblfds/liblfds6.0.1/liblfds601/src/lfds601_queue/lfds601_queue_new.c create mode 100644 liblfds/liblfds6.0.1/liblfds601/src/lfds601_queue/lfds601_queue_query.c create mode 100644 liblfds/liblfds6.0.1/liblfds601/src/lfds601_queue/lfds601_queue_queue.c create mode 100644 liblfds/liblfds6.0.1/liblfds601/src/lfds601_ringbuffer/lfds601_ringbuffer_delete.c create mode 100644 liblfds/liblfds6.0.1/liblfds601/src/lfds601_ringbuffer/lfds601_ringbuffer_get_and_put.c create mode 100644 liblfds/liblfds6.0.1/liblfds601/src/lfds601_ringbuffer/lfds601_ringbuffer_internal.h create mode 100644 liblfds/liblfds6.0.1/liblfds601/src/lfds601_ringbuffer/lfds601_ringbuffer_new.c create mode 100644 liblfds/liblfds6.0.1/liblfds601/src/lfds601_ringbuffer/lfds601_ringbuffer_query.c create mode 100644 liblfds/liblfds6.0.1/liblfds601/src/lfds601_slist/lfds601_slist_delete.c create mode 100644 liblfds/liblfds6.0.1/liblfds601/src/lfds601_slist/lfds601_slist_get_and_set.c create mode 100644 liblfds/liblfds6.0.1/liblfds601/src/lfds601_slist/lfds601_slist_internal.h create mode 100644 liblfds/liblfds6.0.1/liblfds601/src/lfds601_slist/lfds601_slist_link.c create mode 100644 liblfds/liblfds6.0.1/liblfds601/src/lfds601_slist/lfds601_slist_new.c create mode 100644 liblfds/liblfds6.0.1/liblfds601/src/lfds601_stack/lfds601_stack_delete.c create mode 100644 liblfds/liblfds6.0.1/liblfds601/src/lfds601_stack/lfds601_stack_internal.h create mode 100644 liblfds/liblfds6.0.1/liblfds601/src/lfds601_stack/lfds601_stack_new.c create mode 100644 liblfds/liblfds6.0.1/liblfds601/src/lfds601_stack/lfds601_stack_push_pop.c create mode 100644 liblfds/liblfds6.0.1/liblfds601/src/lfds601_stack/lfds601_stack_query.c create mode 100644 liblfds/liblfds6.0.1/test/bin/empty_dir_placeholder_for_git create mode 100644 liblfds/liblfds6.0.1/test/building.txt create mode 100644 liblfds/liblfds6.0.1/test/makefile.linux create mode 100644 liblfds/liblfds6.0.1/test/makefile.windows create mode 100644 liblfds/liblfds6.0.1/test/obj/empty_dir_placeholder_for_git create mode 100644 liblfds/liblfds6.0.1/test/src/abstraction.h create mode 100644 liblfds/liblfds6.0.1/test/src/abstraction_cpu_count.c create mode 100644 liblfds/liblfds6.0.1/test/src/abstraction_thread_start.c create mode 100644 liblfds/liblfds6.0.1/test/src/abstraction_thread_wait.c create mode 100644 liblfds/liblfds6.0.1/test/src/benchmark_freelist.c create mode 100644 liblfds/liblfds6.0.1/test/src/benchmark_queue.c create mode 100644 liblfds/liblfds6.0.1/test/src/benchmark_ringbuffer.c create mode 100644 liblfds/liblfds6.0.1/test/src/benchmark_stack.c create mode 100644 liblfds/liblfds6.0.1/test/src/internal.h create mode 100644 liblfds/liblfds6.0.1/test/src/main.c create mode 100644 liblfds/liblfds6.0.1/test/src/misc.c create mode 100644 liblfds/liblfds6.0.1/test/src/structures.h create mode 100644 liblfds/liblfds6.0.1/test/src/test_abstraction.c create mode 100644 liblfds/liblfds6.0.1/test/src/test_freelist.c create mode 100644 liblfds/liblfds6.0.1/test/src/test_queue.c create mode 100644 liblfds/liblfds6.0.1/test/src/test_ringbuffer.c create mode 100644 liblfds/liblfds6.0.1/test/src/test_slist.c create mode 100644 liblfds/liblfds6.0.1/test/src/test_stack.c create mode 100644 liblfds/liblfds6.0.1/test/test.sln create mode 100644 liblfds/liblfds6.0.1/test/test.vcproj create mode 100644 liblfds/liblfds6.1.0/liblfds610/bin/empty_dir_placeholder_for_git create mode 100644 liblfds/liblfds6.1.0/liblfds610/building.txt create mode 100644 liblfds/liblfds6.1.0/liblfds610/dirs create mode 100644 liblfds/liblfds6.1.0/liblfds610/inc/liblfds610.h create mode 100644 liblfds/liblfds6.1.0/liblfds610/liblfds610.def create mode 100644 liblfds/liblfds6.1.0/liblfds610/liblfds610.sln create mode 100644 liblfds/liblfds6.1.0/liblfds610/liblfds610.vcproj create mode 100644 liblfds/liblfds6.1.0/liblfds610/makefile.linux create mode 100644 liblfds/liblfds6.1.0/liblfds610/makefile.windows create mode 100644 liblfds/liblfds6.1.0/liblfds610/obj/empty_dir_placeholder_for_git create mode 100644 liblfds/liblfds6.1.0/liblfds610/readme.txt create mode 100644 liblfds/liblfds6.1.0/liblfds610/runme_before_win_kernel_build_readme.txt create mode 100644 liblfds/liblfds6.1.0/liblfds610/runme_before_win_kernel_dynamic_lib_build.bat create mode 100644 liblfds/liblfds6.1.0/liblfds610/runme_before_win_kernel_static_lib_build.bat create mode 100644 liblfds/liblfds6.1.0/liblfds610/sources.dynamic create mode 100644 liblfds/liblfds6.1.0/liblfds610/sources.static create mode 100644 liblfds/liblfds6.1.0/liblfds610/src/dirs create mode 100644 liblfds/liblfds6.1.0/liblfds610/src/driver_entry.c create mode 100644 liblfds/liblfds6.1.0/liblfds610/src/driver_entry_readme.txt create mode 100644 liblfds/liblfds6.1.0/liblfds610/src/lfds610_abstraction/lfds610_abstraction_cas.c create mode 100644 liblfds/liblfds6.1.0/liblfds610/src/lfds610_abstraction/lfds610_abstraction_dcas.c create mode 100644 liblfds/liblfds6.1.0/liblfds610/src/lfds610_abstraction/lfds610_abstraction_free.c create mode 100644 liblfds/liblfds6.1.0/liblfds610/src/lfds610_abstraction/lfds610_abstraction_increment.c create mode 100644 liblfds/liblfds6.1.0/liblfds610/src/lfds610_abstraction/lfds610_abstraction_internal_body.h create mode 100644 liblfds/liblfds6.1.0/liblfds610/src/lfds610_abstraction/lfds610_abstraction_internal_wrapper.h create mode 100644 liblfds/liblfds6.1.0/liblfds610/src/lfds610_abstraction/lfds610_abstraction_malloc.c create mode 100644 liblfds/liblfds6.1.0/liblfds610/src/lfds610_freelist/lfds610_freelist_delete.c create mode 100644 liblfds/liblfds6.1.0/liblfds610/src/lfds610_freelist/lfds610_freelist_get_and_set.c create mode 100644 liblfds/liblfds6.1.0/liblfds610/src/lfds610_freelist/lfds610_freelist_internal.h create mode 100644 liblfds/liblfds6.1.0/liblfds610/src/lfds610_freelist/lfds610_freelist_new.c create mode 100644 liblfds/liblfds6.1.0/liblfds610/src/lfds610_freelist/lfds610_freelist_pop_push.c create mode 100644 liblfds/liblfds6.1.0/liblfds610/src/lfds610_freelist/lfds610_freelist_query.c create mode 100644 liblfds/liblfds6.1.0/liblfds610/src/lfds610_liblfds/lfds610_liblfds_abstraction_test_helpers.c create mode 100644 liblfds/liblfds6.1.0/liblfds610/src/lfds610_liblfds/lfds610_liblfds_aligned_free.c create mode 100644 liblfds/liblfds6.1.0/liblfds610/src/lfds610_liblfds/lfds610_liblfds_aligned_malloc.c create mode 100644 liblfds/liblfds6.1.0/liblfds610/src/lfds610_liblfds/lfds610_liblfds_internal.h create mode 100644 liblfds/liblfds6.1.0/liblfds610/src/lfds610_liblfds/lfds610_liblfds_readme.txt create mode 100644 liblfds/liblfds6.1.0/liblfds610/src/lfds610_queue/lfds610_queue_delete.c create mode 100644 liblfds/liblfds6.1.0/liblfds610/src/lfds610_queue/lfds610_queue_internal.h create mode 100644 liblfds/liblfds6.1.0/liblfds610/src/lfds610_queue/lfds610_queue_new.c create mode 100644 liblfds/liblfds6.1.0/liblfds610/src/lfds610_queue/lfds610_queue_query.c create mode 100644 liblfds/liblfds6.1.0/liblfds610/src/lfds610_queue/lfds610_queue_queue.c create mode 100644 liblfds/liblfds6.1.0/liblfds610/src/lfds610_ringbuffer/lfds610_ringbuffer_delete.c create mode 100644 liblfds/liblfds6.1.0/liblfds610/src/lfds610_ringbuffer/lfds610_ringbuffer_get_and_put.c create mode 100644 liblfds/liblfds6.1.0/liblfds610/src/lfds610_ringbuffer/lfds610_ringbuffer_internal.h create mode 100644 liblfds/liblfds6.1.0/liblfds610/src/lfds610_ringbuffer/lfds610_ringbuffer_new.c create mode 100644 liblfds/liblfds6.1.0/liblfds610/src/lfds610_ringbuffer/lfds610_ringbuffer_query.c create mode 100644 liblfds/liblfds6.1.0/liblfds610/src/lfds610_slist/lfds610_slist_delete.c create mode 100644 liblfds/liblfds6.1.0/liblfds610/src/lfds610_slist/lfds610_slist_get_and_set.c create mode 100644 liblfds/liblfds6.1.0/liblfds610/src/lfds610_slist/lfds610_slist_internal.h create mode 100644 liblfds/liblfds6.1.0/liblfds610/src/lfds610_slist/lfds610_slist_link.c create mode 100644 liblfds/liblfds6.1.0/liblfds610/src/lfds610_slist/lfds610_slist_new.c create mode 100644 liblfds/liblfds6.1.0/liblfds610/src/lfds610_stack/lfds610_stack_delete.c create mode 100644 liblfds/liblfds6.1.0/liblfds610/src/lfds610_stack/lfds610_stack_internal.h create mode 100644 liblfds/liblfds6.1.0/liblfds610/src/lfds610_stack/lfds610_stack_new.c create mode 100644 liblfds/liblfds6.1.0/liblfds610/src/lfds610_stack/lfds610_stack_push_pop.c create mode 100644 liblfds/liblfds6.1.0/liblfds610/src/lfds610_stack/lfds610_stack_query.c create mode 100644 liblfds/liblfds6.1.0/liblfds610/src/liblfds610_internal.h create mode 100644 liblfds/liblfds6.1.0/test/bin/empty_dir_placeholder_for_git create mode 100644 liblfds/liblfds6.1.0/test/building.txt create mode 100644 liblfds/liblfds6.1.0/test/makefile.linux create mode 100644 liblfds/liblfds6.1.0/test/makefile.windows create mode 100644 liblfds/liblfds6.1.0/test/obj/empty_dir_placeholder_for_git create mode 100644 liblfds/liblfds6.1.0/test/src/abstraction.h create mode 100644 liblfds/liblfds6.1.0/test/src/abstraction_cpu_count.c create mode 100644 liblfds/liblfds6.1.0/test/src/abstraction_thread_start.c create mode 100644 liblfds/liblfds6.1.0/test/src/abstraction_thread_wait.c create mode 100644 liblfds/liblfds6.1.0/test/src/benchmark_freelist.c create mode 100644 liblfds/liblfds6.1.0/test/src/benchmark_queue.c create mode 100644 liblfds/liblfds6.1.0/test/src/benchmark_ringbuffer.c create mode 100644 liblfds/liblfds6.1.0/test/src/benchmark_stack.c create mode 100644 liblfds/liblfds6.1.0/test/src/internal.h create mode 100644 liblfds/liblfds6.1.0/test/src/main.c create mode 100644 liblfds/liblfds6.1.0/test/src/misc.c create mode 100644 liblfds/liblfds6.1.0/test/src/structures.h create mode 100644 liblfds/liblfds6.1.0/test/src/test_abstraction.c create mode 100644 liblfds/liblfds6.1.0/test/src/test_freelist.c create mode 100644 liblfds/liblfds6.1.0/test/src/test_queue.c create mode 100644 liblfds/liblfds6.1.0/test/src/test_ringbuffer.c create mode 100644 liblfds/liblfds6.1.0/test/src/test_slist.c create mode 100644 liblfds/liblfds6.1.0/test/src/test_stack.c create mode 100644 liblfds/liblfds6.1.0/test/test.sln create mode 100644 liblfds/liblfds6.1.0/test/test.vcproj create mode 100644 liblfds/liblfds6.1.1/liblfds611/bin/empty_dir_placeholder_for_git create mode 100644 liblfds/liblfds6.1.1/liblfds611/building.txt create mode 100644 liblfds/liblfds6.1.1/liblfds611/dirs create mode 100644 liblfds/liblfds6.1.1/liblfds611/inc/liblfds611.h create mode 100644 liblfds/liblfds6.1.1/liblfds611/liblfds611.def create mode 100644 liblfds/liblfds6.1.1/liblfds611/liblfds611.sln create mode 100644 liblfds/liblfds6.1.1/liblfds611/liblfds611.vcproj create mode 100644 liblfds/liblfds6.1.1/liblfds611/makefile.linux create mode 100644 liblfds/liblfds6.1.1/liblfds611/makefile.windows create mode 100644 liblfds/liblfds6.1.1/liblfds611/obj/empty_dir_placeholder_for_git create mode 100644 liblfds/liblfds6.1.1/liblfds611/readme.txt create mode 100644 liblfds/liblfds6.1.1/liblfds611/runme_before_win_kernel_build_readme.txt create mode 100644 liblfds/liblfds6.1.1/liblfds611/runme_before_win_kernel_dynamic_lib_build.bat create mode 100644 liblfds/liblfds6.1.1/liblfds611/runme_before_win_kernel_static_lib_build.bat create mode 100644 liblfds/liblfds6.1.1/liblfds611/sources.dynamic create mode 100644 liblfds/liblfds6.1.1/liblfds611/sources.static create mode 100644 liblfds/liblfds6.1.1/liblfds611/src/dirs create mode 100644 liblfds/liblfds6.1.1/liblfds611/src/driver_entry.c create mode 100644 liblfds/liblfds6.1.1/liblfds611/src/driver_entry_readme.txt create mode 100644 liblfds/liblfds6.1.1/liblfds611/src/lfds611_abstraction/lfds611_abstraction_cas.c create mode 100644 liblfds/liblfds6.1.1/liblfds611/src/lfds611_abstraction/lfds611_abstraction_dcas.c create mode 100644 liblfds/liblfds6.1.1/liblfds611/src/lfds611_abstraction/lfds611_abstraction_free.c create mode 100644 liblfds/liblfds6.1.1/liblfds611/src/lfds611_abstraction/lfds611_abstraction_increment.c create mode 100644 liblfds/liblfds6.1.1/liblfds611/src/lfds611_abstraction/lfds611_abstraction_internal_body.h create mode 100644 liblfds/liblfds6.1.1/liblfds611/src/lfds611_abstraction/lfds611_abstraction_internal_wrapper.h create mode 100644 liblfds/liblfds6.1.1/liblfds611/src/lfds611_abstraction/lfds611_abstraction_malloc.c create mode 100644 liblfds/liblfds6.1.1/liblfds611/src/lfds611_freelist/lfds611_freelist_delete.c create mode 100644 liblfds/liblfds6.1.1/liblfds611/src/lfds611_freelist/lfds611_freelist_get_and_set.c create mode 100644 liblfds/liblfds6.1.1/liblfds611/src/lfds611_freelist/lfds611_freelist_internal.h create mode 100644 liblfds/liblfds6.1.1/liblfds611/src/lfds611_freelist/lfds611_freelist_new.c create mode 100644 liblfds/liblfds6.1.1/liblfds611/src/lfds611_freelist/lfds611_freelist_pop_push.c create mode 100644 liblfds/liblfds6.1.1/liblfds611/src/lfds611_freelist/lfds611_freelist_query.c create mode 100644 liblfds/liblfds6.1.1/liblfds611/src/lfds611_liblfds/lfds611_liblfds_abstraction_test_helpers.c create mode 100644 liblfds/liblfds6.1.1/liblfds611/src/lfds611_liblfds/lfds611_liblfds_aligned_free.c create mode 100644 liblfds/liblfds6.1.1/liblfds611/src/lfds611_liblfds/lfds611_liblfds_aligned_malloc.c create mode 100644 liblfds/liblfds6.1.1/liblfds611/src/lfds611_liblfds/lfds611_liblfds_internal.h create mode 100644 liblfds/liblfds6.1.1/liblfds611/src/lfds611_liblfds/lfds611_liblfds_readme.txt create mode 100644 liblfds/liblfds6.1.1/liblfds611/src/lfds611_queue/lfds611_queue_delete.c create mode 100644 liblfds/liblfds6.1.1/liblfds611/src/lfds611_queue/lfds611_queue_internal.h create mode 100644 liblfds/liblfds6.1.1/liblfds611/src/lfds611_queue/lfds611_queue_new.c create mode 100644 liblfds/liblfds6.1.1/liblfds611/src/lfds611_queue/lfds611_queue_query.c create mode 100644 liblfds/liblfds6.1.1/liblfds611/src/lfds611_queue/lfds611_queue_queue.c create mode 100644 liblfds/liblfds6.1.1/liblfds611/src/lfds611_ringbuffer/lfds611_ringbuffer_delete.c create mode 100644 liblfds/liblfds6.1.1/liblfds611/src/lfds611_ringbuffer/lfds611_ringbuffer_get_and_put.c create mode 100644 liblfds/liblfds6.1.1/liblfds611/src/lfds611_ringbuffer/lfds611_ringbuffer_internal.h create mode 100644 liblfds/liblfds6.1.1/liblfds611/src/lfds611_ringbuffer/lfds611_ringbuffer_new.c create mode 100644 liblfds/liblfds6.1.1/liblfds611/src/lfds611_ringbuffer/lfds611_ringbuffer_query.c create mode 100644 liblfds/liblfds6.1.1/liblfds611/src/lfds611_slist/lfds611_slist_delete.c create mode 100644 liblfds/liblfds6.1.1/liblfds611/src/lfds611_slist/lfds611_slist_get_and_set.c create mode 100644 liblfds/liblfds6.1.1/liblfds611/src/lfds611_slist/lfds611_slist_internal.h create mode 100644 liblfds/liblfds6.1.1/liblfds611/src/lfds611_slist/lfds611_slist_link.c create mode 100644 liblfds/liblfds6.1.1/liblfds611/src/lfds611_slist/lfds611_slist_new.c create mode 100644 liblfds/liblfds6.1.1/liblfds611/src/lfds611_stack/lfds611_stack_delete.c create mode 100644 liblfds/liblfds6.1.1/liblfds611/src/lfds611_stack/lfds611_stack_internal.h create mode 100644 liblfds/liblfds6.1.1/liblfds611/src/lfds611_stack/lfds611_stack_new.c create mode 100644 liblfds/liblfds6.1.1/liblfds611/src/lfds611_stack/lfds611_stack_push_pop.c create mode 100644 liblfds/liblfds6.1.1/liblfds611/src/lfds611_stack/lfds611_stack_query.c create mode 100644 liblfds/liblfds6.1.1/liblfds611/src/liblfds611_internal.h create mode 100644 liblfds/liblfds6.1.1/test/bin/empty_dir_placeholder_for_git create mode 100644 liblfds/liblfds6.1.1/test/building.txt create mode 100644 liblfds/liblfds6.1.1/test/makefile.linux create mode 100644 liblfds/liblfds6.1.1/test/makefile.windows create mode 100644 liblfds/liblfds6.1.1/test/obj/empty_dir_placeholder_for_git create mode 100644 liblfds/liblfds6.1.1/test/src/abstraction.h create mode 100644 liblfds/liblfds6.1.1/test/src/abstraction_cpu_count.c create mode 100644 liblfds/liblfds6.1.1/test/src/abstraction_thread_start.c create mode 100644 liblfds/liblfds6.1.1/test/src/abstraction_thread_wait.c create mode 100644 liblfds/liblfds6.1.1/test/src/benchmark_freelist.c create mode 100644 liblfds/liblfds6.1.1/test/src/benchmark_queue.c create mode 100644 liblfds/liblfds6.1.1/test/src/benchmark_ringbuffer.c create mode 100644 liblfds/liblfds6.1.1/test/src/benchmark_stack.c create mode 100644 liblfds/liblfds6.1.1/test/src/internal.h create mode 100644 liblfds/liblfds6.1.1/test/src/main.c create mode 100644 liblfds/liblfds6.1.1/test/src/misc.c create mode 100644 liblfds/liblfds6.1.1/test/src/structures.h create mode 100644 liblfds/liblfds6.1.1/test/src/test_abstraction.c create mode 100644 liblfds/liblfds6.1.1/test/src/test_freelist.c create mode 100644 liblfds/liblfds6.1.1/test/src/test_queue.c create mode 100644 liblfds/liblfds6.1.1/test/src/test_ringbuffer.c create mode 100644 liblfds/liblfds6.1.1/test/src/test_slist.c create mode 100644 liblfds/liblfds6.1.1/test/src/test_stack.c create mode 100644 liblfds/liblfds6.1.1/test/test.sln create mode 100644 liblfds/liblfds6.1.1/test/test.vcproj create mode 100644 liblfds/liblfds7.0.0/liblfds700/bin/empty_dir_placeholder_for_git create mode 100644 liblfds/liblfds7.0.0/liblfds700/build/gcc_and_gnumake/Makefile create mode 100644 liblfds/liblfds7.0.0/liblfds700/build/gcc_kbuild_and_gnumake/Kbuild create mode 100644 liblfds/liblfds7.0.0/liblfds700/build/gcc_kbuild_and_gnumake/Makefile create mode 100644 liblfds/liblfds7.0.0/liblfds700/build/sdk_for_windows_7_and_gnumake/liblfds700.def create mode 100644 liblfds/liblfds7.0.0/liblfds700/build/sdk_for_windows_7_and_gnumake/makefile create mode 100644 liblfds/liblfds7.0.0/liblfds700/build/visual_studio_professional_2012/liblfds700.def create mode 100644 liblfds/liblfds7.0.0/liblfds700/build/visual_studio_professional_2012/liblfds700.sln create mode 100644 liblfds/liblfds7.0.0/liblfds700/build/visual_studio_professional_2012/liblfds700.vcxproj create mode 100644 liblfds/liblfds7.0.0/liblfds700/build/visual_studio_professional_2012/liblfds700.vcxproj.filters create mode 100644 liblfds/liblfds7.0.0/liblfds700/build/visual_studio_professional_2012/liblfds700.vcxproj.user create mode 100644 liblfds/liblfds7.0.0/liblfds700/build/visual_studio_professional_2012_and_wdk_8.0/driver_entry.c create mode 100644 liblfds/liblfds7.0.0/liblfds700/build/visual_studio_professional_2012_and_wdk_8.0/liblfds700.def create mode 100644 liblfds/liblfds7.0.0/liblfds700/build/visual_studio_professional_2012_and_wdk_8.0/liblfds700.sln create mode 100644 liblfds/liblfds7.0.0/liblfds700/build/visual_studio_professional_2012_and_wdk_8.0/liblfds700.vcxproj create mode 100644 liblfds/liblfds7.0.0/liblfds700/build/visual_studio_professional_2012_and_wdk_8.0/liblfds700.vcxproj.filters create mode 100644 liblfds/liblfds7.0.0/liblfds700/build/visual_studio_professional_2012_and_wdk_8.0/liblfds700.vcxproj.user create mode 100644 liblfds/liblfds7.0.0/liblfds700/build/visual_studio_professional_2013_and_wdk_8.1/driver_entry.c create mode 100644 liblfds/liblfds7.0.0/liblfds700/build/visual_studio_professional_2013_and_wdk_8.1/liblfds700.def create mode 100644 liblfds/liblfds7.0.0/liblfds700/build/visual_studio_professional_2013_and_wdk_8.1/liblfds700.sln create mode 100644 liblfds/liblfds7.0.0/liblfds700/build/visual_studio_professional_2013_and_wdk_8.1/liblfds700.vcxproj create mode 100644 liblfds/liblfds7.0.0/liblfds700/build/visual_studio_professional_2013_and_wdk_8.1/liblfds700.vcxproj.filters create mode 100644 liblfds/liblfds7.0.0/liblfds700/build/visual_studio_professional_2013_and_wdk_8.1/liblfds700.vcxproj.user create mode 100644 liblfds/liblfds7.0.0/liblfds700/build/wdk_7.1/dirs create mode 100644 liblfds/liblfds7.0.0/liblfds700/build/wdk_7.1/driver_entry_renamed_to_avoid_compiler_warning.c create mode 100644 liblfds/liblfds7.0.0/liblfds700/build/wdk_7.1/liblfds700.def create mode 100644 liblfds/liblfds7.0.0/liblfds700/build/wdk_7.1/readme_before_win_kernel_build.txt create mode 100644 liblfds/liblfds7.0.0/liblfds700/build/wdk_7.1/runme_before_win_kernel_dynamic_lib_build.bat create mode 100644 liblfds/liblfds7.0.0/liblfds700/build/wdk_7.1/runme_before_win_kernel_static_lib_build.bat create mode 100644 liblfds/liblfds7.0.0/liblfds700/build/wdk_7.1/sources.dynamic create mode 100644 liblfds/liblfds7.0.0/liblfds700/build/wdk_7.1/sources.static create mode 100644 liblfds/liblfds7.0.0/liblfds700/inc/liblfds700.h create mode 100644 liblfds/liblfds7.0.0/liblfds700/inc/liblfds700/lfds700_btree_addonly_unbalanced.h create mode 100644 liblfds/liblfds7.0.0/liblfds700/inc/liblfds700/lfds700_freelist.h create mode 100644 liblfds/liblfds7.0.0/liblfds700/inc/liblfds700/lfds700_hash_addonly.h create mode 100644 liblfds/liblfds7.0.0/liblfds700/inc/liblfds700/lfds700_list_addonly_ordered_singlylinked.h create mode 100644 liblfds/liblfds7.0.0/liblfds700/inc/liblfds700/lfds700_list_addonly_singlylinked_unordered.h create mode 100644 liblfds/liblfds7.0.0/liblfds700/inc/liblfds700/lfds700_misc.h create mode 100644 liblfds/liblfds7.0.0/liblfds700/inc/liblfds700/lfds700_porting_abstraction_layer_compiler.h create mode 100644 liblfds/liblfds7.0.0/liblfds700/inc/liblfds700/lfds700_porting_abstraction_layer_operating_system.h create mode 100644 liblfds/liblfds7.0.0/liblfds700/inc/liblfds700/lfds700_porting_abstraction_layer_processor.h create mode 100644 liblfds/liblfds7.0.0/liblfds700/inc/liblfds700/lfds700_queue.h create mode 100644 liblfds/liblfds7.0.0/liblfds700/inc/liblfds700/lfds700_queue_bounded_singleconsumer_singleproducer.h create mode 100644 liblfds/liblfds7.0.0/liblfds700/inc/liblfds700/lfds700_ringbuffer.h create mode 100644 liblfds/liblfds7.0.0/liblfds700/inc/liblfds700/lfds700_stack.h create mode 100644 liblfds/liblfds7.0.0/liblfds700/obj/empty_dir_placeholder_for_git create mode 100644 liblfds/liblfds7.0.0/liblfds700/src/lfds700_btree_addonly_unbalanced/lfds700_btree_addonly_unbalanced_cleanup.c create mode 100644 liblfds/liblfds7.0.0/liblfds700/src/lfds700_btree_addonly_unbalanced/lfds700_btree_addonly_unbalanced_get.c create mode 100644 liblfds/liblfds7.0.0/liblfds700/src/lfds700_btree_addonly_unbalanced/lfds700_btree_addonly_unbalanced_init.c create mode 100644 liblfds/liblfds7.0.0/liblfds700/src/lfds700_btree_addonly_unbalanced/lfds700_btree_addonly_unbalanced_insert.c create mode 100644 liblfds/liblfds7.0.0/liblfds700/src/lfds700_btree_addonly_unbalanced/lfds700_btree_addonly_unbalanced_internal.h create mode 100644 liblfds/liblfds7.0.0/liblfds700/src/lfds700_btree_addonly_unbalanced/lfds700_btree_addonly_unbalanced_query.c create mode 100644 liblfds/liblfds7.0.0/liblfds700/src/lfds700_freelist/lfds700_freelist_cleanup.c create mode 100644 liblfds/liblfds7.0.0/liblfds700/src/lfds700_freelist/lfds700_freelist_init.c create mode 100644 liblfds/liblfds7.0.0/liblfds700/src/lfds700_freelist/lfds700_freelist_internal.h create mode 100644 liblfds/liblfds7.0.0/liblfds700/src/lfds700_freelist/lfds700_freelist_pop.c create mode 100644 liblfds/liblfds7.0.0/liblfds700/src/lfds700_freelist/lfds700_freelist_push.c create mode 100644 liblfds/liblfds7.0.0/liblfds700/src/lfds700_freelist/lfds700_freelist_query.c create mode 100644 liblfds/liblfds7.0.0/liblfds700/src/lfds700_hash_addonly/lfds700_hash_addonly_cleanup.c create mode 100644 liblfds/liblfds7.0.0/liblfds700/src/lfds700_hash_addonly/lfds700_hash_addonly_get.c create mode 100644 liblfds/liblfds7.0.0/liblfds700/src/lfds700_hash_addonly/lfds700_hash_addonly_init.c create mode 100644 liblfds/liblfds7.0.0/liblfds700/src/lfds700_hash_addonly/lfds700_hash_addonly_insert.c create mode 100644 liblfds/liblfds7.0.0/liblfds700/src/lfds700_hash_addonly/lfds700_hash_addonly_internal.h create mode 100644 liblfds/liblfds7.0.0/liblfds700/src/lfds700_hash_addonly/lfds700_hash_addonly_iterate.c create mode 100644 liblfds/liblfds7.0.0/liblfds700/src/lfds700_hash_addonly/lfds700_hash_addonly_query.c create mode 100644 liblfds/liblfds7.0.0/liblfds700/src/lfds700_list_addonly_ordered_singlylinked/lfds700_list_addonly_ordered_singlylinked_cleanup.c create mode 100644 liblfds/liblfds7.0.0/liblfds700/src/lfds700_list_addonly_ordered_singlylinked/lfds700_list_addonly_ordered_singlylinked_get.c create mode 100644 liblfds/liblfds7.0.0/liblfds700/src/lfds700_list_addonly_ordered_singlylinked/lfds700_list_addonly_ordered_singlylinked_init.c create mode 100644 liblfds/liblfds7.0.0/liblfds700/src/lfds700_list_addonly_ordered_singlylinked/lfds700_list_addonly_ordered_singlylinked_insert.c create mode 100644 liblfds/liblfds7.0.0/liblfds700/src/lfds700_list_addonly_ordered_singlylinked/lfds700_list_addonly_ordered_singlylinked_internal.h create mode 100644 liblfds/liblfds7.0.0/liblfds700/src/lfds700_list_addonly_ordered_singlylinked/lfds700_list_addonly_ordered_singlylinked_query.c create mode 100644 liblfds/liblfds7.0.0/liblfds700/src/lfds700_list_addonly_singlylinked_unordered/lfds700_list_addonly_singlylinked_unordered_cleanup.c create mode 100644 liblfds/liblfds7.0.0/liblfds700/src/lfds700_list_addonly_singlylinked_unordered/lfds700_list_addonly_singlylinked_unordered_get.c create mode 100644 liblfds/liblfds7.0.0/liblfds700/src/lfds700_list_addonly_singlylinked_unordered/lfds700_list_addonly_singlylinked_unordered_init.c create mode 100644 liblfds/liblfds7.0.0/liblfds700/src/lfds700_list_addonly_singlylinked_unordered/lfds700_list_addonly_singlylinked_unordered_insert.c create mode 100644 liblfds/liblfds7.0.0/liblfds700/src/lfds700_list_addonly_singlylinked_unordered/lfds700_list_addonly_singlylinked_unordered_internal.h create mode 100644 liblfds/liblfds7.0.0/liblfds700/src/lfds700_list_addonly_singlylinked_unordered/lfds700_list_addonly_singlylinked_unordered_query.c create mode 100644 liblfds/liblfds7.0.0/liblfds700/src/lfds700_misc/lfds700_misc_cleanup.c create mode 100644 liblfds/liblfds7.0.0/liblfds700/src/lfds700_misc/lfds700_misc_globals.c create mode 100644 liblfds/liblfds7.0.0/liblfds700/src/lfds700_misc/lfds700_misc_init.c create mode 100644 liblfds/liblfds7.0.0/liblfds700/src/lfds700_misc/lfds700_misc_internal.h create mode 100644 liblfds/liblfds7.0.0/liblfds700/src/lfds700_misc/lfds700_misc_prng.c create mode 100644 liblfds/liblfds7.0.0/liblfds700/src/lfds700_misc/lfds700_misc_query.c create mode 100644 liblfds/liblfds7.0.0/liblfds700/src/lfds700_queue/lfds700_queue_cleanup.c create mode 100644 liblfds/liblfds7.0.0/liblfds700/src/lfds700_queue/lfds700_queue_dequeue.c create mode 100644 liblfds/liblfds7.0.0/liblfds700/src/lfds700_queue/lfds700_queue_enqueue.c create mode 100644 liblfds/liblfds7.0.0/liblfds700/src/lfds700_queue/lfds700_queue_init.c create mode 100644 liblfds/liblfds7.0.0/liblfds700/src/lfds700_queue/lfds700_queue_internal.h create mode 100644 liblfds/liblfds7.0.0/liblfds700/src/lfds700_queue/lfds700_queue_query.c create mode 100644 liblfds/liblfds7.0.0/liblfds700/src/lfds700_queue_bounded_singleconsumer_singleproducer/lfds700_queue_bounded_singleconsumer_singleproducer_cleanup.c create mode 100644 liblfds/liblfds7.0.0/liblfds700/src/lfds700_queue_bounded_singleconsumer_singleproducer/lfds700_queue_bounded_singleconsumer_singleproducer_dequeue.c create mode 100644 liblfds/liblfds7.0.0/liblfds700/src/lfds700_queue_bounded_singleconsumer_singleproducer/lfds700_queue_bounded_singleconsumer_singleproducer_enqueue.c create mode 100644 liblfds/liblfds7.0.0/liblfds700/src/lfds700_queue_bounded_singleconsumer_singleproducer/lfds700_queue_bounded_singleconsumer_singleproducer_init.c create mode 100644 liblfds/liblfds7.0.0/liblfds700/src/lfds700_queue_bounded_singleconsumer_singleproducer/lfds700_queue_bounded_singleconsumer_singleproducer_internal.h create mode 100644 liblfds/liblfds7.0.0/liblfds700/src/lfds700_queue_bounded_singleconsumer_singleproducer/lfds700_queue_bounded_singleconsumer_singleproducer_query.c create mode 100644 liblfds/liblfds7.0.0/liblfds700/src/lfds700_ringbuffer/lfds700_ringbuffer_cleanup.c create mode 100644 liblfds/liblfds7.0.0/liblfds700/src/lfds700_ringbuffer/lfds700_ringbuffer_init.c create mode 100644 liblfds/liblfds7.0.0/liblfds700/src/lfds700_ringbuffer/lfds700_ringbuffer_internal.h create mode 100644 liblfds/liblfds7.0.0/liblfds700/src/lfds700_ringbuffer/lfds700_ringbuffer_query.c create mode 100644 liblfds/liblfds7.0.0/liblfds700/src/lfds700_ringbuffer/lfds700_ringbuffer_read.c create mode 100644 liblfds/liblfds7.0.0/liblfds700/src/lfds700_ringbuffer/lfds700_ringbuffer_write.c create mode 100644 liblfds/liblfds7.0.0/liblfds700/src/lfds700_stack/lfds700_stack_cleanup.c create mode 100644 liblfds/liblfds7.0.0/liblfds700/src/lfds700_stack/lfds700_stack_init.c create mode 100644 liblfds/liblfds7.0.0/liblfds700/src/lfds700_stack/lfds700_stack_internal.h create mode 100644 liblfds/liblfds7.0.0/liblfds700/src/lfds700_stack/lfds700_stack_pop.c create mode 100644 liblfds/liblfds7.0.0/liblfds700/src/lfds700_stack/lfds700_stack_push.c create mode 100644 liblfds/liblfds7.0.0/liblfds700/src/lfds700_stack/lfds700_stack_query.c create mode 100644 liblfds/liblfds7.0.0/liblfds700/src/liblfds700_internal.h create mode 100644 liblfds/liblfds7.0.0/test/bin/empty_dir_placeholder_for_git create mode 100644 liblfds/liblfds7.0.0/test/build/gcc_and_gnumake/Makefile create mode 100644 liblfds/liblfds7.0.0/test/build/sdk_for_windows_7_and_gnumake/makefile create mode 100644 liblfds/liblfds7.0.0/test/build/visual_studio_professional_2012/test.sln create mode 100644 liblfds/liblfds7.0.0/test/build/visual_studio_professional_2012/test.vcxproj create mode 100644 liblfds/liblfds7.0.0/test/build/visual_studio_professional_2012/test.vcxproj.filters create mode 100644 liblfds/liblfds7.0.0/test/build/visual_studio_professional_2012/test.vcxproj.user create mode 100644 liblfds/liblfds7.0.0/test/obj/empty_dir_placeholder_for_git create mode 100644 liblfds/liblfds7.0.0/test/src/internal.h create mode 100644 liblfds/liblfds7.0.0/test/src/main.c create mode 100644 liblfds/liblfds7.0.0/test/src/misc.c create mode 100644 liblfds/liblfds7.0.0/test/src/test_lfds700_btree_addonly_unbalanced.c create mode 100644 liblfds/liblfds7.0.0/test/src/test_lfds700_btree_addonly_unbalanced_alignment.c create mode 100644 liblfds/liblfds7.0.0/test/src/test_lfds700_btree_addonly_unbalanced_random_adds_fail.c create mode 100644 liblfds/liblfds7.0.0/test/src/test_lfds700_btree_addonly_unbalanced_random_adds_fail_and_overwrite.c create mode 100644 liblfds/liblfds7.0.0/test/src/test_lfds700_btree_addonly_unbalanced_random_adds_overwrite.c create mode 100644 liblfds/liblfds7.0.0/test/src/test_lfds700_freelist.c create mode 100644 liblfds/liblfds7.0.0/test/src/test_lfds700_freelist_alignment.c create mode 100644 liblfds/liblfds7.0.0/test/src/test_lfds700_freelist_popping.c create mode 100644 liblfds/liblfds7.0.0/test/src/test_lfds700_freelist_popping_and_pushing.c create mode 100644 liblfds/liblfds7.0.0/test/src/test_lfds700_freelist_pushing.c create mode 100644 liblfds/liblfds7.0.0/test/src/test_lfds700_freelist_rapid_popping_and_pushing.c create mode 100644 liblfds/liblfds7.0.0/test/src/test_lfds700_hash_addonly.c create mode 100644 liblfds/liblfds7.0.0/test/src/test_lfds700_hash_addonly_alignment.c create mode 100644 liblfds/liblfds7.0.0/test/src/test_lfds700_hash_addonly_iterate.c create mode 100644 liblfds/liblfds7.0.0/test/src/test_lfds700_hash_addonly_random_adds_fail.c create mode 100644 liblfds/liblfds7.0.0/test/src/test_lfds700_hash_addonly_random_adds_fail_and_overwrite.c create mode 100644 liblfds/liblfds7.0.0/test/src/test_lfds700_hash_addonly_random_adds_overwrite.c create mode 100644 liblfds/liblfds7.0.0/test/src/test_lfds700_list_addonly_ordered_singlylinked.c create mode 100644 liblfds/liblfds7.0.0/test/src/test_lfds700_list_addonly_ordered_singlylinked_alignment.c create mode 100644 liblfds/liblfds7.0.0/test/src/test_lfds700_list_addonly_ordered_singlylinked_new_ordered.c create mode 100644 liblfds/liblfds7.0.0/test/src/test_lfds700_list_addonly_ordered_singlylinked_new_ordered_with_cursor.c create mode 100644 liblfds/liblfds7.0.0/test/src/test_lfds700_list_addonly_singlylinked_unordered.c create mode 100644 liblfds/liblfds7.0.0/test/src/test_lfds700_list_addonly_singlylinked_unordered_alignment.c create mode 100644 liblfds/liblfds7.0.0/test/src/test_lfds700_list_addonly_singlylinked_unordered_new_after.c create mode 100644 liblfds/liblfds7.0.0/test/src/test_lfds700_list_addonly_singlylinked_unordered_new_end.c create mode 100644 liblfds/liblfds7.0.0/test/src/test_lfds700_list_addonly_singlylinked_unordered_new_start.c create mode 100644 liblfds/liblfds7.0.0/test/src/test_lfds700_porting_abstraction_layer_atomic.c create mode 100644 liblfds/liblfds7.0.0/test/src/test_lfds700_porting_abstraction_layer_atomic_cas.c create mode 100644 liblfds/liblfds7.0.0/test/src/test_lfds700_porting_abstraction_layer_atomic_dcas.c create mode 100644 liblfds/liblfds7.0.0/test/src/test_lfds700_porting_abstraction_layer_atomic_exchange.c create mode 100644 liblfds/liblfds7.0.0/test/src/test_lfds700_queue.c create mode 100644 liblfds/liblfds7.0.0/test/src/test_lfds700_queue_alignment.c create mode 100644 liblfds/liblfds7.0.0/test/src/test_lfds700_queue_bounded_singleconsumer_singleproducer.c create mode 100644 liblfds/liblfds7.0.0/test/src/test_lfds700_queue_bounded_singleconsumer_singleproducer_dequeuing.c create mode 100644 liblfds/liblfds7.0.0/test/src/test_lfds700_queue_bounded_singleconsumer_singleproducer_enqueuing.c create mode 100644 liblfds/liblfds7.0.0/test/src/test_lfds700_queue_bounded_singleconsumer_singleproducer_enqueuing_and_dequeuing.c create mode 100644 liblfds/liblfds7.0.0/test/src/test_lfds700_queue_dequeuing.c create mode 100644 liblfds/liblfds7.0.0/test/src/test_lfds700_queue_enqueuing.c create mode 100644 liblfds/liblfds7.0.0/test/src/test_lfds700_queue_enqueuing_and_dequeuing.c create mode 100644 liblfds/liblfds7.0.0/test/src/test_lfds700_queue_enqueuing_and_dequeuing_with_free.c create mode 100644 liblfds/liblfds7.0.0/test/src/test_lfds700_queue_enqueuing_with_malloc_and_dequeuing_with_free.c create mode 100644 liblfds/liblfds7.0.0/test/src/test_lfds700_queue_rapid_enqueuing_and_dequeuing.c create mode 100644 liblfds/liblfds7.0.0/test/src/test_lfds700_ringbuffer.c create mode 100644 liblfds/liblfds7.0.0/test/src/test_lfds700_ringbuffer_reading.c create mode 100644 liblfds/liblfds7.0.0/test/src/test_lfds700_ringbuffer_reading_and_writing.c create mode 100644 liblfds/liblfds7.0.0/test/src/test_lfds700_ringbuffer_writing.c create mode 100644 liblfds/liblfds7.0.0/test/src/test_lfds700_stack.c create mode 100644 liblfds/liblfds7.0.0/test/src/test_lfds700_stack_alignment.c create mode 100644 liblfds/liblfds7.0.0/test/src/test_lfds700_stack_popping.c create mode 100644 liblfds/liblfds7.0.0/test/src/test_lfds700_stack_popping_and_pushing.c create mode 100644 liblfds/liblfds7.0.0/test/src/test_lfds700_stack_pushing.c create mode 100644 liblfds/liblfds7.0.0/test/src/test_lfds700_stack_rapid_popping_and_pushing.c create mode 100644 liblfds/liblfds7.0.0/test/src/test_porting_abstraction_layer_get_logical_core_ids.c create mode 100644 liblfds/liblfds7.0.0/test/src/test_porting_abstraction_layer_operating_system.h create mode 100644 liblfds/liblfds7.0.0/test/src/test_porting_abstraction_layer_thread_start.c create mode 100644 liblfds/liblfds7.0.0/test/src/test_porting_abstraction_layer_thread_wait.c create mode 100644 liblfds/liblfds7.0.0/test/src/util_cmdline.c create mode 100644 liblfds/liblfds7.0.0/test/src/util_cmdline.h create mode 100644 liblfds/liblfds7.0.0/test/src/util_memory_helpers.c create mode 100644 liblfds/liblfds7.0.0/test/src/util_memory_helpers.h create mode 100644 liblfds/liblfds7.0.0/test/src/util_thread_starter.c create mode 100644 liblfds/liblfds7.0.0/test/src/util_thread_starter.h create mode 100644 liblfds/liblfds7.1.0/liblfds710/bin/empty_dir_placeholder_for_git create mode 100644 liblfds/liblfds7.1.0/liblfds710/build/gcc_gnumake/Makefile create mode 100644 liblfds/liblfds7.1.0/liblfds710/build/gcc_gnumake_kbuild/Kbuild create mode 100644 liblfds/liblfds7.1.0/liblfds710/build/gcc_gnumake_kbuild/Makefile create mode 100644 liblfds/liblfds7.1.0/liblfds710/build/msvc_gnumake/liblfds710.def create mode 100644 liblfds/liblfds7.1.0/liblfds710/build/msvc_gnumake/makefile create mode 100644 liblfds/liblfds7.1.0/liblfds710/build/wdk_7.1/dirs create mode 100644 liblfds/liblfds7.1.0/liblfds710/build/wdk_7.1/driver_entry_renamed_to_avoid_compiler_warning.c create mode 100644 liblfds/liblfds7.1.0/liblfds710/build/wdk_7.1/liblfds710.def create mode 100644 liblfds/liblfds7.1.0/liblfds710/build/wdk_7.1/readme_before_win_kernel_build.txt create mode 100644 liblfds/liblfds7.1.0/liblfds710/build/wdk_7.1/runme_before_win_kernel_dynamic_lib_build.bat create mode 100644 liblfds/liblfds7.1.0/liblfds710/build/wdk_7.1/runme_before_win_kernel_static_lib_build.bat create mode 100644 liblfds/liblfds7.1.0/liblfds710/build/wdk_7.1/sources.dynamic create mode 100644 liblfds/liblfds7.1.0/liblfds710/build/wdk_7.1/sources.static create mode 100644 liblfds/liblfds7.1.0/liblfds710/inc/liblfds710.h create mode 100644 liblfds/liblfds7.1.0/liblfds710/inc/liblfds710/lfds710_btree_addonly_unbalanced.h create mode 100644 liblfds/liblfds7.1.0/liblfds710/inc/liblfds710/lfds710_freelist.h create mode 100644 liblfds/liblfds7.1.0/liblfds710/inc/liblfds710/lfds710_hash_addonly.h create mode 100644 liblfds/liblfds7.1.0/liblfds710/inc/liblfds710/lfds710_list_addonly_singlylinked_ordered.h create mode 100644 liblfds/liblfds7.1.0/liblfds710/inc/liblfds710/lfds710_list_addonly_singlylinked_unordered.h create mode 100644 liblfds/liblfds7.1.0/liblfds710/inc/liblfds710/lfds710_misc.h create mode 100644 liblfds/liblfds7.1.0/liblfds710/inc/liblfds710/lfds710_porting_abstraction_layer_compiler.h create mode 100644 liblfds/liblfds7.1.0/liblfds710/inc/liblfds710/lfds710_porting_abstraction_layer_operating_system.h create mode 100644 liblfds/liblfds7.1.0/liblfds710/inc/liblfds710/lfds710_porting_abstraction_layer_processor.h create mode 100644 liblfds/liblfds7.1.0/liblfds710/inc/liblfds710/lfds710_prng.h create mode 100644 liblfds/liblfds7.1.0/liblfds710/inc/liblfds710/lfds710_queue_bounded_manyproducer_manyconsumer.h create mode 100644 liblfds/liblfds7.1.0/liblfds710/inc/liblfds710/lfds710_queue_bounded_singleproducer_singleconsumer.h create mode 100644 liblfds/liblfds7.1.0/liblfds710/inc/liblfds710/lfds710_queue_unbounded_manyproducer_manyconsumer.h create mode 100644 liblfds/liblfds7.1.0/liblfds710/inc/liblfds710/lfds710_ringbuffer.h create mode 100644 liblfds/liblfds7.1.0/liblfds710/inc/liblfds710/lfds710_stack.h create mode 100644 liblfds/liblfds7.1.0/liblfds710/obj/empty_dir_placeholder_for_git create mode 100644 liblfds/liblfds7.1.0/liblfds710/src/lfds710_btree_addonly_unbalanced/lfds710_btree_addonly_unbalanced_cleanup.c create mode 100644 liblfds/liblfds7.1.0/liblfds710/src/lfds710_btree_addonly_unbalanced/lfds710_btree_addonly_unbalanced_get.c create mode 100644 liblfds/liblfds7.1.0/liblfds710/src/lfds710_btree_addonly_unbalanced/lfds710_btree_addonly_unbalanced_init.c create mode 100644 liblfds/liblfds7.1.0/liblfds710/src/lfds710_btree_addonly_unbalanced/lfds710_btree_addonly_unbalanced_insert.c create mode 100644 liblfds/liblfds7.1.0/liblfds710/src/lfds710_btree_addonly_unbalanced/lfds710_btree_addonly_unbalanced_internal.h create mode 100644 liblfds/liblfds7.1.0/liblfds710/src/lfds710_btree_addonly_unbalanced/lfds710_btree_addonly_unbalanced_query.c create mode 100644 liblfds/liblfds7.1.0/liblfds710/src/lfds710_freelist/lfds710_freelist_cleanup.c create mode 100644 liblfds/liblfds7.1.0/liblfds710/src/lfds710_freelist/lfds710_freelist_init.c create mode 100644 liblfds/liblfds7.1.0/liblfds710/src/lfds710_freelist/lfds710_freelist_internal.h create mode 100644 liblfds/liblfds7.1.0/liblfds710/src/lfds710_freelist/lfds710_freelist_pop.c create mode 100644 liblfds/liblfds7.1.0/liblfds710/src/lfds710_freelist/lfds710_freelist_push.c create mode 100644 liblfds/liblfds7.1.0/liblfds710/src/lfds710_freelist/lfds710_freelist_query.c create mode 100644 liblfds/liblfds7.1.0/liblfds710/src/lfds710_hash_addonly/lfds710_hash_addonly_cleanup.c create mode 100644 liblfds/liblfds7.1.0/liblfds710/src/lfds710_hash_addonly/lfds710_hash_addonly_get.c create mode 100644 liblfds/liblfds7.1.0/liblfds710/src/lfds710_hash_addonly/lfds710_hash_addonly_init.c create mode 100644 liblfds/liblfds7.1.0/liblfds710/src/lfds710_hash_addonly/lfds710_hash_addonly_insert.c create mode 100644 liblfds/liblfds7.1.0/liblfds710/src/lfds710_hash_addonly/lfds710_hash_addonly_internal.h create mode 100644 liblfds/liblfds7.1.0/liblfds710/src/lfds710_hash_addonly/lfds710_hash_addonly_iterate.c create mode 100644 liblfds/liblfds7.1.0/liblfds710/src/lfds710_hash_addonly/lfds710_hash_addonly_query.c create mode 100644 liblfds/liblfds7.1.0/liblfds710/src/lfds710_list_addonly_singlylinked_ordered/lfds710_list_addonly_singlylinked_ordered_cleanup.c create mode 100644 liblfds/liblfds7.1.0/liblfds710/src/lfds710_list_addonly_singlylinked_ordered/lfds710_list_addonly_singlylinked_ordered_get.c create mode 100644 liblfds/liblfds7.1.0/liblfds710/src/lfds710_list_addonly_singlylinked_ordered/lfds710_list_addonly_singlylinked_ordered_init.c create mode 100644 liblfds/liblfds7.1.0/liblfds710/src/lfds710_list_addonly_singlylinked_ordered/lfds710_list_addonly_singlylinked_ordered_insert.c create mode 100644 liblfds/liblfds7.1.0/liblfds710/src/lfds710_list_addonly_singlylinked_ordered/lfds710_list_addonly_singlylinked_ordered_internal.h create mode 100644 liblfds/liblfds7.1.0/liblfds710/src/lfds710_list_addonly_singlylinked_ordered/lfds710_list_addonly_singlylinked_ordered_query.c create mode 100644 liblfds/liblfds7.1.0/liblfds710/src/lfds710_list_addonly_singlylinked_unordered/lfds710_list_addonly_singlylinked_unordered_cleanup.c create mode 100644 liblfds/liblfds7.1.0/liblfds710/src/lfds710_list_addonly_singlylinked_unordered/lfds710_list_addonly_singlylinked_unordered_get.c create mode 100644 liblfds/liblfds7.1.0/liblfds710/src/lfds710_list_addonly_singlylinked_unordered/lfds710_list_addonly_singlylinked_unordered_init.c create mode 100644 liblfds/liblfds7.1.0/liblfds710/src/lfds710_list_addonly_singlylinked_unordered/lfds710_list_addonly_singlylinked_unordered_insert.c create mode 100644 liblfds/liblfds7.1.0/liblfds710/src/lfds710_list_addonly_singlylinked_unordered/lfds710_list_addonly_singlylinked_unordered_internal.h create mode 100644 liblfds/liblfds7.1.0/liblfds710/src/lfds710_list_addonly_singlylinked_unordered/lfds710_list_addonly_singlylinked_unordered_query.c create mode 100644 liblfds/liblfds7.1.0/liblfds710/src/lfds710_misc/lfds710_misc_globals.c create mode 100644 liblfds/liblfds7.1.0/liblfds710/src/lfds710_misc/lfds710_misc_internal.h create mode 100644 liblfds/liblfds7.1.0/liblfds710/src/lfds710_misc/lfds710_misc_internal_backoff_init.c create mode 100644 liblfds/liblfds7.1.0/liblfds710/src/lfds710_misc/lfds710_misc_query.c create mode 100644 liblfds/liblfds7.1.0/liblfds710/src/lfds710_prng/lfds710_prng_init.c create mode 100644 liblfds/liblfds7.1.0/liblfds710/src/lfds710_prng/lfds710_prng_internal.h create mode 100644 liblfds/liblfds7.1.0/liblfds710/src/lfds710_queue_bounded_manyproducer_manyconsumer/lfds710_queue_bounded_manyproducer_manyconsumer_cleanup.c create mode 100644 liblfds/liblfds7.1.0/liblfds710/src/lfds710_queue_bounded_manyproducer_manyconsumer/lfds710_queue_bounded_manyproducer_manyconsumer_dequeue.c create mode 100644 liblfds/liblfds7.1.0/liblfds710/src/lfds710_queue_bounded_manyproducer_manyconsumer/lfds710_queue_bounded_manyproducer_manyconsumer_enqueue.c create mode 100644 liblfds/liblfds7.1.0/liblfds710/src/lfds710_queue_bounded_manyproducer_manyconsumer/lfds710_queue_bounded_manyproducer_manyconsumer_init.c create mode 100644 liblfds/liblfds7.1.0/liblfds710/src/lfds710_queue_bounded_manyproducer_manyconsumer/lfds710_queue_bounded_manyproducer_manyconsumer_internal.h create mode 100644 liblfds/liblfds7.1.0/liblfds710/src/lfds710_queue_bounded_manyproducer_manyconsumer/lfds710_queue_bounded_manyproducer_manyconsumer_query.c create mode 100644 liblfds/liblfds7.1.0/liblfds710/src/lfds710_queue_bounded_singleproducer_singleconsumer/lfds710_queue_bounded_singleproducer_singleconsumer_cleanup.c create mode 100644 liblfds/liblfds7.1.0/liblfds710/src/lfds710_queue_bounded_singleproducer_singleconsumer/lfds710_queue_bounded_singleproducer_singleconsumer_dequeue.c create mode 100644 liblfds/liblfds7.1.0/liblfds710/src/lfds710_queue_bounded_singleproducer_singleconsumer/lfds710_queue_bounded_singleproducer_singleconsumer_enqueue.c create mode 100644 liblfds/liblfds7.1.0/liblfds710/src/lfds710_queue_bounded_singleproducer_singleconsumer/lfds710_queue_bounded_singleproducer_singleconsumer_init.c create mode 100644 liblfds/liblfds7.1.0/liblfds710/src/lfds710_queue_bounded_singleproducer_singleconsumer/lfds710_queue_bounded_singleproducer_singleconsumer_internal.h create mode 100644 liblfds/liblfds7.1.0/liblfds710/src/lfds710_queue_bounded_singleproducer_singleconsumer/lfds710_queue_bounded_singleproducer_singleconsumer_query.c create mode 100644 liblfds/liblfds7.1.0/liblfds710/src/lfds710_queue_unbounded_manyproducer_manyconsumer/lfds710_queue_unbounded_manyproducer_manyconsumer_cleanup.c create mode 100644 liblfds/liblfds7.1.0/liblfds710/src/lfds710_queue_unbounded_manyproducer_manyconsumer/lfds710_queue_unbounded_manyproducer_manyconsumer_dequeue.c create mode 100644 liblfds/liblfds7.1.0/liblfds710/src/lfds710_queue_unbounded_manyproducer_manyconsumer/lfds710_queue_unbounded_manyproducer_manyconsumer_enqueue.c create mode 100644 liblfds/liblfds7.1.0/liblfds710/src/lfds710_queue_unbounded_manyproducer_manyconsumer/lfds710_queue_unbounded_manyproducer_manyconsumer_init.c create mode 100644 liblfds/liblfds7.1.0/liblfds710/src/lfds710_queue_unbounded_manyproducer_manyconsumer/lfds710_queue_unbounded_manyproducer_manyconsumer_internal.h create mode 100644 liblfds/liblfds7.1.0/liblfds710/src/lfds710_queue_unbounded_manyproducer_manyconsumer/lfds710_queue_unbounded_manyproducer_manyconsumer_query.c create mode 100644 liblfds/liblfds7.1.0/liblfds710/src/lfds710_ringbuffer/lfds710_ringbuffer_cleanup.c create mode 100644 liblfds/liblfds7.1.0/liblfds710/src/lfds710_ringbuffer/lfds710_ringbuffer_init.c create mode 100644 liblfds/liblfds7.1.0/liblfds710/src/lfds710_ringbuffer/lfds710_ringbuffer_internal.h create mode 100644 liblfds/liblfds7.1.0/liblfds710/src/lfds710_ringbuffer/lfds710_ringbuffer_query.c create mode 100644 liblfds/liblfds7.1.0/liblfds710/src/lfds710_ringbuffer/lfds710_ringbuffer_read.c create mode 100644 liblfds/liblfds7.1.0/liblfds710/src/lfds710_ringbuffer/lfds710_ringbuffer_write.c create mode 100644 liblfds/liblfds7.1.0/liblfds710/src/lfds710_stack/lfds710_stack_cleanup.c create mode 100644 liblfds/liblfds7.1.0/liblfds710/src/lfds710_stack/lfds710_stack_init.c create mode 100644 liblfds/liblfds7.1.0/liblfds710/src/lfds710_stack/lfds710_stack_internal.h create mode 100644 liblfds/liblfds7.1.0/liblfds710/src/lfds710_stack/lfds710_stack_pop.c create mode 100644 liblfds/liblfds7.1.0/liblfds710/src/lfds710_stack/lfds710_stack_push.c create mode 100644 liblfds/liblfds7.1.0/liblfds710/src/lfds710_stack/lfds710_stack_query.c create mode 100644 liblfds/liblfds7.1.0/liblfds710/src/liblfds710_internal.h create mode 100644 liblfds/liblfds7.1.0/test_and_benchmark/benchmark/bin/empty_dir_placeholder_for_git create mode 100644 liblfds/liblfds7.1.0/test_and_benchmark/benchmark/build/gcc_gnumake_hosted_liblfds710_liblfds700/Makefile create mode 100644 liblfds/liblfds7.1.0/test_and_benchmark/benchmark/build/gcc_gnumake_hosted_liblfds710_liblfds700_libnuma/Makefile create mode 100644 liblfds/liblfds7.1.0/test_and_benchmark/benchmark/build/msvc_gnumake_liblfds710_liblfds700/makefile create mode 100644 liblfds/liblfds7.1.0/test_and_benchmark/benchmark/obj/empty_dir_placeholder_for_git create mode 100644 liblfds/liblfds7.1.0/test_and_benchmark/benchmark/src/internal.h create mode 100644 liblfds/liblfds7.1.0/test_and_benchmark/benchmark/src/main.c create mode 100644 liblfds/liblfds7.1.0/test_and_benchmark/benchmark/src/misc.c create mode 100644 liblfds/liblfds7.1.0/test_and_benchmark/benchmark/src/porting_abstraction_layer.h create mode 100644 liblfds/liblfds7.1.0/test_and_benchmark/benchmark/src/porting_abstraction_layer_numa_free.c create mode 100644 liblfds/liblfds7.1.0/test_and_benchmark/benchmark/src/porting_abstraction_layer_numa_malloc.c create mode 100644 liblfds/liblfds7.1.0/test_and_benchmark/benchmark/src/porting_abstraction_layer_operating_system.h create mode 100644 liblfds/liblfds7.1.0/test_and_benchmark/benchmark/src/util_cmdline.c create mode 100644 liblfds/liblfds7.1.0/test_and_benchmark/benchmark/src/util_cmdline.h create mode 100644 liblfds/liblfds7.1.0/test_and_benchmark/libbenchmark/bin/empty_dir_placeholder_for_git create mode 100644 liblfds/liblfds7.1.0/test_and_benchmark/libbenchmark/build/gcc_gnumake/Makefile create mode 100644 liblfds/liblfds7.1.0/test_and_benchmark/libbenchmark/build/gcc_gnumake_kbuild/Kbuild create mode 100644 liblfds/liblfds7.1.0/test_and_benchmark/libbenchmark/build/gcc_gnumake_kbuild/Makefile create mode 100644 liblfds/liblfds7.1.0/test_and_benchmark/libbenchmark/build/gcc_gnumake_kbuild/this build is currently broken.txt create mode 100644 liblfds/liblfds7.1.0/test_and_benchmark/libbenchmark/build/msvc_gnumake/libbenchmark.def create mode 100644 liblfds/liblfds7.1.0/test_and_benchmark/libbenchmark/build/msvc_gnumake/makefile create mode 100644 liblfds/liblfds7.1.0/test_and_benchmark/libbenchmark/build/wdk_7.1/dirs create mode 100644 liblfds/liblfds7.1.0/test_and_benchmark/libbenchmark/build/wdk_7.1/driver_entry_renamed_to_avoid_compiler_warning.c create mode 100644 liblfds/liblfds7.1.0/test_and_benchmark/libbenchmark/build/wdk_7.1/libbenchmark.def create mode 100644 liblfds/liblfds7.1.0/test_and_benchmark/libbenchmark/build/wdk_7.1/readme_before_win_kernel_build.txt create mode 100644 liblfds/liblfds7.1.0/test_and_benchmark/libbenchmark/build/wdk_7.1/runme_before_win_kernel_dynamic_lib_build.bat create mode 100644 liblfds/liblfds7.1.0/test_and_benchmark/libbenchmark/build/wdk_7.1/runme_before_win_kernel_static_lib_build.bat create mode 100644 liblfds/liblfds7.1.0/test_and_benchmark/libbenchmark/build/wdk_7.1/sources.dynamic create mode 100644 liblfds/liblfds7.1.0/test_and_benchmark/libbenchmark/build/wdk_7.1/sources.static create mode 100644 liblfds/liblfds7.1.0/test_and_benchmark/libbenchmark/inc/libbenchmark.h create mode 100644 liblfds/liblfds7.1.0/test_and_benchmark/libbenchmark/inc/libbenchmark/libbenchmark_benchmarkinstance.h create mode 100644 liblfds/liblfds7.1.0/test_and_benchmark/libbenchmark/inc/libbenchmark/libbenchmark_benchmarks_btree_au_readn_writen.h create mode 100644 liblfds/liblfds7.1.0/test_and_benchmark/libbenchmark/inc/libbenchmark/libbenchmark_benchmarks_freelist_push1_then_pop1.h create mode 100644 liblfds/liblfds7.1.0/test_and_benchmark/libbenchmark/inc/libbenchmark/libbenchmark_benchmarks_queue_umm_enqueue1_then_dequeue1.h create mode 100644 liblfds/liblfds7.1.0/test_and_benchmark/libbenchmark/inc/libbenchmark/libbenchmark_benchmarkset.h create mode 100644 liblfds/liblfds7.1.0/test_and_benchmark/libbenchmark/inc/libbenchmark/libbenchmark_benchmarksuite.h create mode 100644 liblfds/liblfds7.1.0/test_and_benchmark/libbenchmark/inc/libbenchmark/libbenchmark_datastructure_btree_au_gcc_spinlock_atomic.h create mode 100644 liblfds/liblfds7.1.0/test_and_benchmark/libbenchmark/inc/libbenchmark/libbenchmark_datastructure_btree_au_gcc_spinlock_sync.h create mode 100644 liblfds/liblfds7.1.0/test_and_benchmark/libbenchmark/inc/libbenchmark/libbenchmark_datastructure_btree_au_msvc_spinlock.h create mode 100644 liblfds/liblfds7.1.0/test_and_benchmark/libbenchmark/inc/libbenchmark/libbenchmark_datastructure_btree_au_pthread_mutex.h create mode 100644 liblfds/liblfds7.1.0/test_and_benchmark/libbenchmark/inc/libbenchmark/libbenchmark_datastructure_btree_au_pthread_rwlock.h create mode 100644 liblfds/liblfds7.1.0/test_and_benchmark/libbenchmark/inc/libbenchmark/libbenchmark_datastructure_btree_au_pthread_spinlock_process_private.h create mode 100644 liblfds/liblfds7.1.0/test_and_benchmark/libbenchmark/inc/libbenchmark/libbenchmark_datastructure_btree_au_pthread_spinlock_process_shared.h create mode 100644 liblfds/liblfds7.1.0/test_and_benchmark/libbenchmark/inc/libbenchmark/libbenchmark_datastructure_btree_au_windows_critical_section.h create mode 100644 liblfds/liblfds7.1.0/test_and_benchmark/libbenchmark/inc/libbenchmark/libbenchmark_datastructure_btree_au_windows_mutex.h create mode 100644 liblfds/liblfds7.1.0/test_and_benchmark/libbenchmark/inc/libbenchmark/libbenchmark_datastructure_freelist_gcc_spinlock_atomic.h create mode 100644 liblfds/liblfds7.1.0/test_and_benchmark/libbenchmark/inc/libbenchmark/libbenchmark_datastructure_freelist_gcc_spinlock_sync.h create mode 100644 liblfds/liblfds7.1.0/test_and_benchmark/libbenchmark/inc/libbenchmark/libbenchmark_datastructure_freelist_msvc_spinlock.h create mode 100644 liblfds/liblfds7.1.0/test_and_benchmark/libbenchmark/inc/libbenchmark/libbenchmark_datastructure_freelist_pthread_mutex.h create mode 100644 liblfds/liblfds7.1.0/test_and_benchmark/libbenchmark/inc/libbenchmark/libbenchmark_datastructure_freelist_pthread_rwlock.h create mode 100644 liblfds/liblfds7.1.0/test_and_benchmark/libbenchmark/inc/libbenchmark/libbenchmark_datastructure_freelist_pthread_spinlock_process_private.h create mode 100644 liblfds/liblfds7.1.0/test_and_benchmark/libbenchmark/inc/libbenchmark/libbenchmark_datastructure_freelist_pthread_spinlock_process_shared.h create mode 100644 liblfds/liblfds7.1.0/test_and_benchmark/libbenchmark/inc/libbenchmark/libbenchmark_datastructure_freelist_windows_critical_section.h create mode 100644 liblfds/liblfds7.1.0/test_and_benchmark/libbenchmark/inc/libbenchmark/libbenchmark_datastructure_freelist_windows_mutex.h create mode 100644 liblfds/liblfds7.1.0/test_and_benchmark/libbenchmark/inc/libbenchmark/libbenchmark_datastructure_queue_umm_gcc_spinlock_atomic.h create mode 100644 liblfds/liblfds7.1.0/test_and_benchmark/libbenchmark/inc/libbenchmark/libbenchmark_datastructure_queue_umm_gcc_spinlock_sync.h create mode 100644 liblfds/liblfds7.1.0/test_and_benchmark/libbenchmark/inc/libbenchmark/libbenchmark_datastructure_queue_umm_msvc_spinlock.h create mode 100644 liblfds/liblfds7.1.0/test_and_benchmark/libbenchmark/inc/libbenchmark/libbenchmark_datastructure_queue_umm_pthread_mutex.h create mode 100644 liblfds/liblfds7.1.0/test_and_benchmark/libbenchmark/inc/libbenchmark/libbenchmark_datastructure_queue_umm_pthread_rwlock.h create mode 100644 liblfds/liblfds7.1.0/test_and_benchmark/libbenchmark/inc/libbenchmark/libbenchmark_datastructure_queue_umm_pthread_spinlock_process_private.h create mode 100644 liblfds/liblfds7.1.0/test_and_benchmark/libbenchmark/inc/libbenchmark/libbenchmark_datastructure_queue_umm_pthread_spinlock_process_shared.h create mode 100644 liblfds/liblfds7.1.0/test_and_benchmark/libbenchmark/inc/libbenchmark/libbenchmark_datastructure_queue_umm_windows_critical_section.h create mode 100644 liblfds/liblfds7.1.0/test_and_benchmark/libbenchmark/inc/libbenchmark/libbenchmark_datastructure_queue_umm_windows_mutex.h create mode 100644 liblfds/liblfds7.1.0/test_and_benchmark/libbenchmark/inc/libbenchmark/libbenchmark_enums.h create mode 100644 liblfds/liblfds7.1.0/test_and_benchmark/libbenchmark/inc/libbenchmark/libbenchmark_gnuplot.h create mode 100644 liblfds/liblfds7.1.0/test_and_benchmark/libbenchmark/inc/libbenchmark/libbenchmark_misc.h create mode 100644 liblfds/liblfds7.1.0/test_and_benchmark/libbenchmark/inc/libbenchmark/libbenchmark_porting_abstraction_layer.h create mode 100644 liblfds/liblfds7.1.0/test_and_benchmark/libbenchmark/inc/libbenchmark/libbenchmark_porting_abstraction_layer_lock_gcc_spinlock_atomic.h create mode 100644 liblfds/liblfds7.1.0/test_and_benchmark/libbenchmark/inc/libbenchmark/libbenchmark_porting_abstraction_layer_lock_gcc_spinlock_sync.h create mode 100644 liblfds/liblfds7.1.0/test_and_benchmark/libbenchmark/inc/libbenchmark/libbenchmark_porting_abstraction_layer_lock_msvc_spinlock.h create mode 100644 liblfds/liblfds7.1.0/test_and_benchmark/libbenchmark/inc/libbenchmark/libbenchmark_porting_abstraction_layer_lock_pthread_mutex.h create mode 100644 liblfds/liblfds7.1.0/test_and_benchmark/libbenchmark/inc/libbenchmark/libbenchmark_porting_abstraction_layer_lock_pthread_rwlock.h create mode 100644 liblfds/liblfds7.1.0/test_and_benchmark/libbenchmark/inc/libbenchmark/libbenchmark_porting_abstraction_layer_lock_pthread_spinlock_process_private.h create mode 100644 liblfds/liblfds7.1.0/test_and_benchmark/libbenchmark/inc/libbenchmark/libbenchmark_porting_abstraction_layer_lock_pthread_spinlock_process_shared.h create mode 100644 liblfds/liblfds7.1.0/test_and_benchmark/libbenchmark/inc/libbenchmark/libbenchmark_porting_abstraction_layer_lock_windows_critical_section.h create mode 100644 liblfds/liblfds7.1.0/test_and_benchmark/libbenchmark/inc/libbenchmark/libbenchmark_porting_abstraction_layer_lock_windows_mutex.h create mode 100644 liblfds/liblfds7.1.0/test_and_benchmark/libbenchmark/inc/libbenchmark/libbenchmark_porting_abstraction_layer_operating_system.h create mode 100644 liblfds/liblfds7.1.0/test_and_benchmark/libbenchmark/inc/libbenchmark/libbenchmark_prng.h create mode 100644 liblfds/liblfds7.1.0/test_and_benchmark/libbenchmark/inc/libbenchmark/libbenchmark_results.h create mode 100644 liblfds/liblfds7.1.0/test_and_benchmark/libbenchmark/inc/libbenchmark/libbenchmark_threadset.h create mode 100644 liblfds/liblfds7.1.0/test_and_benchmark/libbenchmark/inc/libbenchmark/libbenchmark_topology.h create mode 100644 liblfds/liblfds7.1.0/test_and_benchmark/libbenchmark/inc/libbenchmark/libbenchmark_topology_node.h create mode 100644 liblfds/liblfds7.1.0/test_and_benchmark/libbenchmark/obj/empty_dir_placeholder_for_git create mode 100644 liblfds/liblfds7.1.0/test_and_benchmark/libbenchmark/src/libbenchmark_benchmarkinstance/libbenchmark_benchmarkinstance_cleanup.c create mode 100644 liblfds/liblfds7.1.0/test_and_benchmark/libbenchmark/src/libbenchmark_benchmarkinstance/libbenchmark_benchmarkinstance_init.c create mode 100644 liblfds/liblfds7.1.0/test_and_benchmark/libbenchmark/src/libbenchmark_benchmarkinstance/libbenchmark_benchmarkinstance_internal.h create mode 100644 liblfds/liblfds7.1.0/test_and_benchmark/libbenchmark/src/libbenchmark_benchmarkinstance/libbenchmark_benchmarkinstance_run.c create mode 100644 liblfds/liblfds7.1.0/test_and_benchmark/libbenchmark/src/libbenchmark_benchmarks_btree_au_readn_writen/libbenchmark_benchmarks_btree_au_gcc_spinlock_atomic_readn_writen.c create mode 100644 liblfds/liblfds7.1.0/test_and_benchmark/libbenchmark/src/libbenchmark_benchmarks_btree_au_readn_writen/libbenchmark_benchmarks_btree_au_gcc_spinlock_sync_readn_writen.c create mode 100644 liblfds/liblfds7.1.0/test_and_benchmark/libbenchmark/src/libbenchmark_benchmarks_btree_au_readn_writen/libbenchmark_benchmarks_btree_au_internal.h create mode 100644 liblfds/liblfds7.1.0/test_and_benchmark/libbenchmark/src/libbenchmark_benchmarks_btree_au_readn_writen/libbenchmark_benchmarks_btree_au_liblfds700_lockfree_readn_writen.c create mode 100644 liblfds/liblfds7.1.0/test_and_benchmark/libbenchmark/src/libbenchmark_benchmarks_btree_au_readn_writen/libbenchmark_benchmarks_btree_au_liblfds710_lockfree_readn_writen.c create mode 100644 liblfds/liblfds7.1.0/test_and_benchmark/libbenchmark/src/libbenchmark_benchmarks_btree_au_readn_writen/libbenchmark_benchmarks_btree_au_msvc_spinlock_readn_writen.c create mode 100644 liblfds/liblfds7.1.0/test_and_benchmark/libbenchmark/src/libbenchmark_benchmarks_btree_au_readn_writen/libbenchmark_benchmarks_btree_au_pthread_mutex_readn_writen.c create mode 100644 liblfds/liblfds7.1.0/test_and_benchmark/libbenchmark/src/libbenchmark_benchmarks_btree_au_readn_writen/libbenchmark_benchmarks_btree_au_pthread_rwlock_readn_writen.c create mode 100644 liblfds/liblfds7.1.0/test_and_benchmark/libbenchmark/src/libbenchmark_benchmarks_btree_au_readn_writen/libbenchmark_benchmarks_btree_au_pthread_spinlock_process_private_readn_writen.c create mode 100644 liblfds/liblfds7.1.0/test_and_benchmark/libbenchmark/src/libbenchmark_benchmarks_btree_au_readn_writen/libbenchmark_benchmarks_btree_au_pthread_spinlock_process_shared_readn_writen.c create mode 100644 liblfds/liblfds7.1.0/test_and_benchmark/libbenchmark/src/libbenchmark_benchmarks_btree_au_readn_writen/libbenchmark_benchmarks_btree_au_windows_critical_section_readn_writen.c create mode 100644 liblfds/liblfds7.1.0/test_and_benchmark/libbenchmark/src/libbenchmark_benchmarks_btree_au_readn_writen/libbenchmark_benchmarks_btree_au_windows_mutex_readn_writen.c create mode 100644 liblfds/liblfds7.1.0/test_and_benchmark/libbenchmark/src/libbenchmark_benchmarks_freelist_push1_then_pop1/libbenchmark_benchmarks_freelist_gcc_spinlock_atomic_push1_then_pop1.c create mode 100644 liblfds/liblfds7.1.0/test_and_benchmark/libbenchmark/src/libbenchmark_benchmarks_freelist_push1_then_pop1/libbenchmark_benchmarks_freelist_gcc_spinlock_sync_push1_then_pop1.c create mode 100644 liblfds/liblfds7.1.0/test_and_benchmark/libbenchmark/src/libbenchmark_benchmarks_freelist_push1_then_pop1/libbenchmark_benchmarks_freelist_internal.h create mode 100644 liblfds/liblfds7.1.0/test_and_benchmark/libbenchmark/src/libbenchmark_benchmarks_freelist_push1_then_pop1/libbenchmark_benchmarks_freelist_liblfds700_lockfree_push1_then_pop1.c create mode 100644 liblfds/liblfds7.1.0/test_and_benchmark/libbenchmark/src/libbenchmark_benchmarks_freelist_push1_then_pop1/libbenchmark_benchmarks_freelist_liblfds710_lockfree_push1_then_pop1.c create mode 100644 liblfds/liblfds7.1.0/test_and_benchmark/libbenchmark/src/libbenchmark_benchmarks_freelist_push1_then_pop1/libbenchmark_benchmarks_freelist_msvc_spinlock_push1_then_pop1.c create mode 100644 liblfds/liblfds7.1.0/test_and_benchmark/libbenchmark/src/libbenchmark_benchmarks_freelist_push1_then_pop1/libbenchmark_benchmarks_freelist_pthread_mutex_push1_then_pop1.c create mode 100644 liblfds/liblfds7.1.0/test_and_benchmark/libbenchmark/src/libbenchmark_benchmarks_freelist_push1_then_pop1/libbenchmark_benchmarks_freelist_pthread_rwlock_push1_then_pop1.c create mode 100644 liblfds/liblfds7.1.0/test_and_benchmark/libbenchmark/src/libbenchmark_benchmarks_freelist_push1_then_pop1/libbenchmark_benchmarks_freelist_pthread_spinlock_process_private_push1_then_pop1.c create mode 100644 liblfds/liblfds7.1.0/test_and_benchmark/libbenchmark/src/libbenchmark_benchmarks_freelist_push1_then_pop1/libbenchmark_benchmarks_freelist_pthread_spinlock_process_shared_push1_then_pop1.c create mode 100644 liblfds/liblfds7.1.0/test_and_benchmark/libbenchmark/src/libbenchmark_benchmarks_freelist_push1_then_pop1/libbenchmark_benchmarks_freelist_windows_critical_section_push1_then_pop1.c create mode 100644 liblfds/liblfds7.1.0/test_and_benchmark/libbenchmark/src/libbenchmark_benchmarks_freelist_push1_then_pop1/libbenchmark_benchmarks_freelist_windows_mutex_push1_then_pop1.c create mode 100644 liblfds/liblfds7.1.0/test_and_benchmark/libbenchmark/src/libbenchmark_benchmarks_queue_umm_enqueue1_then_dequeue1/libbenchmark_benchmarks_queue_umm_gcc_spinlock_atomic_enqueue1_dequeue1.c create mode 100644 liblfds/liblfds7.1.0/test_and_benchmark/libbenchmark/src/libbenchmark_benchmarks_queue_umm_enqueue1_then_dequeue1/libbenchmark_benchmarks_queue_umm_gcc_spinlock_sync_enqueue1_dequeue1.c create mode 100644 liblfds/liblfds7.1.0/test_and_benchmark/libbenchmark/src/libbenchmark_benchmarks_queue_umm_enqueue1_then_dequeue1/libbenchmark_benchmarks_queue_umm_internal.h create mode 100644 liblfds/liblfds7.1.0/test_and_benchmark/libbenchmark/src/libbenchmark_benchmarks_queue_umm_enqueue1_then_dequeue1/libbenchmark_benchmarks_queue_umm_liblfds700_lockfree_enqueue1_dequeue1.c create mode 100644 liblfds/liblfds7.1.0/test_and_benchmark/libbenchmark/src/libbenchmark_benchmarks_queue_umm_enqueue1_then_dequeue1/libbenchmark_benchmarks_queue_umm_liblfds710_lockfree_enqueue1_dequeue1.c create mode 100644 liblfds/liblfds7.1.0/test_and_benchmark/libbenchmark/src/libbenchmark_benchmarks_queue_umm_enqueue1_then_dequeue1/libbenchmark_benchmarks_queue_umm_msvc_spinlock_enqueue1_dequeue1.c create mode 100644 liblfds/liblfds7.1.0/test_and_benchmark/libbenchmark/src/libbenchmark_benchmarks_queue_umm_enqueue1_then_dequeue1/libbenchmark_benchmarks_queue_umm_pthread_mutex_enqueue1_dequeue1.c create mode 100644 liblfds/liblfds7.1.0/test_and_benchmark/libbenchmark/src/libbenchmark_benchmarks_queue_umm_enqueue1_then_dequeue1/libbenchmark_benchmarks_queue_umm_pthread_rwlock_enqueue1_dequeue1.c create mode 100644 liblfds/liblfds7.1.0/test_and_benchmark/libbenchmark/src/libbenchmark_benchmarks_queue_umm_enqueue1_then_dequeue1/libbenchmark_benchmarks_queue_umm_pthread_spinlock_process_private_enqueue1_dequeue1.c create mode 100644 liblfds/liblfds7.1.0/test_and_benchmark/libbenchmark/src/libbenchmark_benchmarks_queue_umm_enqueue1_then_dequeue1/libbenchmark_benchmarks_queue_umm_pthread_spinlock_process_shared_enqueue1_dequeue1.c create mode 100644 liblfds/liblfds7.1.0/test_and_benchmark/libbenchmark/src/libbenchmark_benchmarks_queue_umm_enqueue1_then_dequeue1/libbenchmark_benchmarks_queue_umm_windows_critical_section_enqueue1_dequeue1.c create mode 100644 liblfds/liblfds7.1.0/test_and_benchmark/libbenchmark/src/libbenchmark_benchmarks_queue_umm_enqueue1_then_dequeue1/libbenchmark_benchmarks_queue_umm_windows_mutex_enqueue1_dequeue1.c create mode 100644 liblfds/liblfds7.1.0/test_and_benchmark/libbenchmark/src/libbenchmark_benchmarkset/libbenchmark_benchmarkset_add.c create mode 100644 liblfds/liblfds7.1.0/test_and_benchmark/libbenchmark/src/libbenchmark_benchmarkset/libbenchmark_benchmarkset_cleanup.c create mode 100644 liblfds/liblfds7.1.0/test_and_benchmark/libbenchmark/src/libbenchmark_benchmarkset/libbenchmark_benchmarkset_gnuplot.c create mode 100644 liblfds/liblfds7.1.0/test_and_benchmark/libbenchmark/src/libbenchmark_benchmarkset/libbenchmark_benchmarkset_init.c create mode 100644 liblfds/liblfds7.1.0/test_and_benchmark/libbenchmark/src/libbenchmark_benchmarkset/libbenchmark_benchmarkset_internal.h create mode 100644 liblfds/liblfds7.1.0/test_and_benchmark/libbenchmark/src/libbenchmark_benchmarkset/libbenchmark_benchmarkset_run.c create mode 100644 liblfds/liblfds7.1.0/test_and_benchmark/libbenchmark/src/libbenchmark_benchmarksuite/libbenchmark_benchmarksuite_add.c create mode 100644 liblfds/liblfds7.1.0/test_and_benchmark/libbenchmark/src/libbenchmark_benchmarksuite/libbenchmark_benchmarksuite_cleanup.c create mode 100644 liblfds/liblfds7.1.0/test_and_benchmark/libbenchmark/src/libbenchmark_benchmarksuite/libbenchmark_benchmarksuite_gnuplot.c create mode 100644 liblfds/liblfds7.1.0/test_and_benchmark/libbenchmark/src/libbenchmark_benchmarksuite/libbenchmark_benchmarksuite_init.c create mode 100644 liblfds/liblfds7.1.0/test_and_benchmark/libbenchmark/src/libbenchmark_benchmarksuite/libbenchmark_benchmarksuite_internal.h create mode 100644 liblfds/liblfds7.1.0/test_and_benchmark/libbenchmark/src/libbenchmark_benchmarksuite/libbenchmark_benchmarksuite_run.c create mode 100644 liblfds/liblfds7.1.0/test_and_benchmark/libbenchmark/src/libbenchmark_datastructures_btree_au/libbenchmark_datastructure_btree_au_gcc_spinlock_atomic.c create mode 100644 liblfds/liblfds7.1.0/test_and_benchmark/libbenchmark/src/libbenchmark_datastructures_btree_au/libbenchmark_datastructure_btree_au_gcc_spinlock_sync.c create mode 100644 liblfds/liblfds7.1.0/test_and_benchmark/libbenchmark/src/libbenchmark_datastructures_btree_au/libbenchmark_datastructure_btree_au_internal.h create mode 100644 liblfds/liblfds7.1.0/test_and_benchmark/libbenchmark/src/libbenchmark_datastructures_btree_au/libbenchmark_datastructure_btree_au_msvc_spinlock.c create mode 100644 liblfds/liblfds7.1.0/test_and_benchmark/libbenchmark/src/libbenchmark_datastructures_btree_au/libbenchmark_datastructure_btree_au_pthread_mutex.c create mode 100644 liblfds/liblfds7.1.0/test_and_benchmark/libbenchmark/src/libbenchmark_datastructures_btree_au/libbenchmark_datastructure_btree_au_pthread_rwlock.c create mode 100644 liblfds/liblfds7.1.0/test_and_benchmark/libbenchmark/src/libbenchmark_datastructures_btree_au/libbenchmark_datastructure_btree_au_pthread_spinlock_process_private.c create mode 100644 liblfds/liblfds7.1.0/test_and_benchmark/libbenchmark/src/libbenchmark_datastructures_btree_au/libbenchmark_datastructure_btree_au_pthread_spinlock_process_shared.c create mode 100644 liblfds/liblfds7.1.0/test_and_benchmark/libbenchmark/src/libbenchmark_datastructures_btree_au/libbenchmark_datastructure_btree_au_windows_critical_section.c create mode 100644 liblfds/liblfds7.1.0/test_and_benchmark/libbenchmark/src/libbenchmark_datastructures_btree_au/libbenchmark_datastructure_btree_au_windows_mutex.c create mode 100644 liblfds/liblfds7.1.0/test_and_benchmark/libbenchmark/src/libbenchmark_datastructures_freelist/libbenchmark_datastructure_freelist_gcc_spinlock_atomic.c create mode 100644 liblfds/liblfds7.1.0/test_and_benchmark/libbenchmark/src/libbenchmark_datastructures_freelist/libbenchmark_datastructure_freelist_gcc_spinlock_sync.c create mode 100644 liblfds/liblfds7.1.0/test_and_benchmark/libbenchmark/src/libbenchmark_datastructures_freelist/libbenchmark_datastructure_freelist_internal.h create mode 100644 liblfds/liblfds7.1.0/test_and_benchmark/libbenchmark/src/libbenchmark_datastructures_freelist/libbenchmark_datastructure_freelist_msvc_spinlock.c create mode 100644 liblfds/liblfds7.1.0/test_and_benchmark/libbenchmark/src/libbenchmark_datastructures_freelist/libbenchmark_datastructure_freelist_pthread_mutex.c create mode 100644 liblfds/liblfds7.1.0/test_and_benchmark/libbenchmark/src/libbenchmark_datastructures_freelist/libbenchmark_datastructure_freelist_pthread_rwlock.c create mode 100644 liblfds/liblfds7.1.0/test_and_benchmark/libbenchmark/src/libbenchmark_datastructures_freelist/libbenchmark_datastructure_freelist_pthread_spinlock_process_private.c create mode 100644 liblfds/liblfds7.1.0/test_and_benchmark/libbenchmark/src/libbenchmark_datastructures_freelist/libbenchmark_datastructure_freelist_pthread_spinlock_process_shared.c create mode 100644 liblfds/liblfds7.1.0/test_and_benchmark/libbenchmark/src/libbenchmark_datastructures_freelist/libbenchmark_datastructure_freelist_windows_critical_section.c create mode 100644 liblfds/liblfds7.1.0/test_and_benchmark/libbenchmark/src/libbenchmark_datastructures_freelist/libbenchmark_datastructure_freelist_windows_mutex.c create mode 100644 liblfds/liblfds7.1.0/test_and_benchmark/libbenchmark/src/libbenchmark_datastructures_queue_umm/libbenchmark_datastructure_queue_umm_gcc_spinlock_atomic.c create mode 100644 liblfds/liblfds7.1.0/test_and_benchmark/libbenchmark/src/libbenchmark_datastructures_queue_umm/libbenchmark_datastructure_queue_umm_gcc_spinlock_sync.c create mode 100644 liblfds/liblfds7.1.0/test_and_benchmark/libbenchmark/src/libbenchmark_datastructures_queue_umm/libbenchmark_datastructure_queue_umm_internal.h create mode 100644 liblfds/liblfds7.1.0/test_and_benchmark/libbenchmark/src/libbenchmark_datastructures_queue_umm/libbenchmark_datastructure_queue_umm_msvc_spinlock.c create mode 100644 liblfds/liblfds7.1.0/test_and_benchmark/libbenchmark/src/libbenchmark_datastructures_queue_umm/libbenchmark_datastructure_queue_umm_pthread_mutex.c create mode 100644 liblfds/liblfds7.1.0/test_and_benchmark/libbenchmark/src/libbenchmark_datastructures_queue_umm/libbenchmark_datastructure_queue_umm_pthread_rwlock.c create mode 100644 liblfds/liblfds7.1.0/test_and_benchmark/libbenchmark/src/libbenchmark_datastructures_queue_umm/libbenchmark_datastructure_queue_umm_pthread_spinlock_process_private.c create mode 100644 liblfds/liblfds7.1.0/test_and_benchmark/libbenchmark/src/libbenchmark_datastructures_queue_umm/libbenchmark_datastructure_queue_umm_pthread_spinlock_process_shared.c create mode 100644 liblfds/liblfds7.1.0/test_and_benchmark/libbenchmark/src/libbenchmark_datastructures_queue_umm/libbenchmark_datastructure_queue_umm_windows_critical_section.c create mode 100644 liblfds/liblfds7.1.0/test_and_benchmark/libbenchmark/src/libbenchmark_datastructures_queue_umm/libbenchmark_datastructure_queue_umm_windows_mutex.c create mode 100644 liblfds/liblfds7.1.0/test_and_benchmark/libbenchmark/src/libbenchmark_internal.h create mode 100644 liblfds/liblfds7.1.0/test_and_benchmark/libbenchmark/src/libbenchmark_misc/libbenchmark_misc_globals.c create mode 100644 liblfds/liblfds7.1.0/test_and_benchmark/libbenchmark/src/libbenchmark_misc/libbenchmark_misc_internal.h create mode 100644 liblfds/liblfds7.1.0/test_and_benchmark/libbenchmark/src/libbenchmark_misc/libbenchmark_misc_pal_helpers.c create mode 100644 liblfds/liblfds7.1.0/test_and_benchmark/libbenchmark/src/libbenchmark_misc/libbenchmark_misc_query.c create mode 100644 liblfds/liblfds7.1.0/test_and_benchmark/libbenchmark/src/libbenchmark_porting_abstraction_layer/libbenchmark_porting_abstraction_layer_internal.h create mode 100644 liblfds/liblfds7.1.0/test_and_benchmark/libbenchmark/src/libbenchmark_porting_abstraction_layer/libbenchmark_porting_abstraction_layer_populate_topology.c create mode 100644 liblfds/liblfds7.1.0/test_and_benchmark/libbenchmark/src/libbenchmark_porting_abstraction_layer/libbenchmark_porting_abstraction_layer_print_string.c create mode 100644 liblfds/liblfds7.1.0/test_and_benchmark/libbenchmark/src/libbenchmark_results/libbenchmark_results_cleanup.c create mode 100644 liblfds/liblfds7.1.0/test_and_benchmark/libbenchmark/src/libbenchmark_results/libbenchmark_results_compare.c create mode 100644 liblfds/liblfds7.1.0/test_and_benchmark/libbenchmark/src/libbenchmark_results/libbenchmark_results_get_result.c create mode 100644 liblfds/liblfds7.1.0/test_and_benchmark/libbenchmark/src/libbenchmark_results/libbenchmark_results_init.c create mode 100644 liblfds/liblfds7.1.0/test_and_benchmark/libbenchmark/src/libbenchmark_results/libbenchmark_results_internal.h create mode 100644 liblfds/liblfds7.1.0/test_and_benchmark/libbenchmark/src/libbenchmark_results/libbenchmark_results_put_result.c create mode 100644 liblfds/liblfds7.1.0/test_and_benchmark/libbenchmark/src/libbenchmark_threadset/libbenchmark_threadset_cleanup.c create mode 100644 liblfds/liblfds7.1.0/test_and_benchmark/libbenchmark/src/libbenchmark_threadset/libbenchmark_threadset_init.c create mode 100644 liblfds/liblfds7.1.0/test_and_benchmark/libbenchmark/src/libbenchmark_threadset/libbenchmark_threadset_internal.h create mode 100644 liblfds/liblfds7.1.0/test_and_benchmark/libbenchmark/src/libbenchmark_threadset/libbenchmark_threadset_operations.c create mode 100644 liblfds/liblfds7.1.0/test_and_benchmark/libbenchmark/src/libbenchmark_topology/libbenchmark_topology_cleanup.c create mode 100644 liblfds/liblfds7.1.0/test_and_benchmark/libbenchmark/src/libbenchmark_topology/libbenchmark_topology_compare.c create mode 100644 liblfds/liblfds7.1.0/test_and_benchmark/libbenchmark/src/libbenchmark_topology/libbenchmark_topology_init.c create mode 100644 liblfds/liblfds7.1.0/test_and_benchmark/libbenchmark/src/libbenchmark_topology/libbenchmark_topology_insert.c create mode 100644 liblfds/liblfds7.1.0/test_and_benchmark/libbenchmark/src/libbenchmark_topology/libbenchmark_topology_internal.h create mode 100644 liblfds/liblfds7.1.0/test_and_benchmark/libbenchmark/src/libbenchmark_topology/libbenchmark_topology_iterate.c create mode 100644 liblfds/liblfds7.1.0/test_and_benchmark/libbenchmark/src/libbenchmark_topology/libbenchmark_topology_lpsets.c create mode 100644 liblfds/liblfds7.1.0/test_and_benchmark/libbenchmark/src/libbenchmark_topology/libbenchmark_topology_numa.c create mode 100644 liblfds/liblfds7.1.0/test_and_benchmark/libbenchmark/src/libbenchmark_topology/libbenchmark_topology_query.c create mode 100644 liblfds/liblfds7.1.0/test_and_benchmark/libbenchmark/src/libbenchmark_topology/libbenchmark_topology_string.c create mode 100644 liblfds/liblfds7.1.0/test_and_benchmark/libbenchmark/src/libbenchmark_topology_node/libbenchmark_topology_node_cleanup.c create mode 100644 liblfds/liblfds7.1.0/test_and_benchmark/libbenchmark/src/libbenchmark_topology_node/libbenchmark_topology_node_compare.c create mode 100644 liblfds/liblfds7.1.0/test_and_benchmark/libbenchmark/src/libbenchmark_topology_node/libbenchmark_topology_node_init.c create mode 100644 liblfds/liblfds7.1.0/test_and_benchmark/libbenchmark/src/libbenchmark_topology_node/libbenchmark_topology_node_internal.h create mode 100644 liblfds/liblfds7.1.0/test_and_benchmark/libshared/bin/empty_dir_placeholder_for_git create mode 100644 liblfds/liblfds7.1.0/test_and_benchmark/libshared/build/gcc_gnumake/Makefile create mode 100644 liblfds/liblfds7.1.0/test_and_benchmark/libshared/build/gcc_gnumake_kbuild/Kbuild create mode 100644 liblfds/liblfds7.1.0/test_and_benchmark/libshared/build/gcc_gnumake_kbuild/Makefile create mode 100644 liblfds/liblfds7.1.0/test_and_benchmark/libshared/build/gcc_gnumake_kbuild/this build is currently broken.txt create mode 100644 liblfds/liblfds7.1.0/test_and_benchmark/libshared/build/msvc_gnumake/libshared.def create mode 100644 liblfds/liblfds7.1.0/test_and_benchmark/libshared/build/msvc_gnumake/makefile create mode 100644 liblfds/liblfds7.1.0/test_and_benchmark/libshared/build/wdk_7.1/dirs create mode 100644 liblfds/liblfds7.1.0/test_and_benchmark/libshared/build/wdk_7.1/driver_entry_renamed_to_avoid_compiler_warning.c create mode 100644 liblfds/liblfds7.1.0/test_and_benchmark/libshared/build/wdk_7.1/libshared.def create mode 100644 liblfds/liblfds7.1.0/test_and_benchmark/libshared/build/wdk_7.1/readme_before_win_kernel_build.txt create mode 100644 liblfds/liblfds7.1.0/test_and_benchmark/libshared/build/wdk_7.1/runme_before_win_kernel_dynamic_lib_build.bat create mode 100644 liblfds/liblfds7.1.0/test_and_benchmark/libshared/build/wdk_7.1/runme_before_win_kernel_static_lib_build.bat create mode 100644 liblfds/liblfds7.1.0/test_and_benchmark/libshared/build/wdk_7.1/sources.dynamic create mode 100644 liblfds/liblfds7.1.0/test_and_benchmark/libshared/build/wdk_7.1/sources.static create mode 100644 liblfds/liblfds7.1.0/test_and_benchmark/libshared/inc/libshared.h create mode 100644 liblfds/liblfds7.1.0/test_and_benchmark/libshared/inc/libshared/libshared_ansi.h create mode 100644 liblfds/liblfds7.1.0/test_and_benchmark/libshared/inc/libshared/libshared_memory.h create mode 100644 liblfds/liblfds7.1.0/test_and_benchmark/libshared/inc/libshared/libshared_misc.h create mode 100644 liblfds/liblfds7.1.0/test_and_benchmark/libshared/inc/libshared/libshared_porting_abstraction_layer.h create mode 100644 liblfds/liblfds7.1.0/test_and_benchmark/libshared/inc/libshared/libshared_porting_abstraction_layer_operating_system.h create mode 100644 liblfds/liblfds7.1.0/test_and_benchmark/libshared/obj/empty_dir_placeholder_for_git create mode 100644 liblfds/liblfds7.1.0/test_and_benchmark/libshared/src/libshared_ansi/libshared_ansi_internal.h create mode 100644 liblfds/liblfds7.1.0/test_and_benchmark/libshared/src/libshared_ansi/libshared_ansi_strcat.c create mode 100644 liblfds/liblfds7.1.0/test_and_benchmark/libshared/src/libshared_ansi/libshared_ansi_strcat_char.c create mode 100644 liblfds/liblfds7.1.0/test_and_benchmark/libshared/src/libshared_ansi/libshared_ansi_strcat_number.c create mode 100644 liblfds/liblfds7.1.0/test_and_benchmark/libshared/src/libshared_ansi/libshared_ansi_strcpy.c create mode 100644 liblfds/liblfds7.1.0/test_and_benchmark/libshared/src/libshared_ansi/libshared_ansi_strlen.c create mode 100644 liblfds/liblfds7.1.0/test_and_benchmark/libshared/src/libshared_internal.h create mode 100644 liblfds/liblfds7.1.0/test_and_benchmark/libshared/src/libshared_memory/libshared_memory_add.c create mode 100644 liblfds/liblfds7.1.0/test_and_benchmark/libshared/src/libshared_memory/libshared_memory_alloc.c create mode 100644 liblfds/liblfds7.1.0/test_and_benchmark/libshared/src/libshared_memory/libshared_memory_cleanup.c create mode 100644 liblfds/liblfds7.1.0/test_and_benchmark/libshared/src/libshared_memory/libshared_memory_init.c create mode 100644 liblfds/liblfds7.1.0/test_and_benchmark/libshared/src/libshared_memory/libshared_memory_internal.h create mode 100644 liblfds/liblfds7.1.0/test_and_benchmark/libshared/src/libshared_memory/libshared_memory_query.c create mode 100644 liblfds/liblfds7.1.0/test_and_benchmark/libshared/src/libshared_memory/libshared_memory_rollback.c create mode 100644 liblfds/liblfds7.1.0/test_and_benchmark/libshared/src/libshared_misc/libshared_misc_internal.h create mode 100644 liblfds/liblfds7.1.0/test_and_benchmark/libshared/src/libshared_misc/libshared_misc_query.c create mode 100644 liblfds/liblfds7.1.0/test_and_benchmark/libshared/src/libshared_porting_abstraction_layer/libshared_porting_abstraction_layer_internal.h create mode 100644 liblfds/liblfds7.1.0/test_and_benchmark/libshared/src/libshared_porting_abstraction_layer/libshared_porting_abstraction_layer_thread_start.c create mode 100644 liblfds/liblfds7.1.0/test_and_benchmark/libshared/src/libshared_porting_abstraction_layer/libshared_porting_abstraction_layer_thread_wait.c create mode 100644 liblfds/liblfds7.1.0/test_and_benchmark/libtest/bin/empty_dir_placeholder_for_git create mode 100644 liblfds/liblfds7.1.0/test_and_benchmark/libtest/build/gcc_gnumake_hosted/Makefile create mode 100644 liblfds/liblfds7.1.0/test_and_benchmark/libtest/build/gcc_gnumake_kbuild/Kbuild create mode 100644 liblfds/liblfds7.1.0/test_and_benchmark/libtest/build/gcc_gnumake_kbuild/Makefile create mode 100644 liblfds/liblfds7.1.0/test_and_benchmark/libtest/build/msvc_gnumake/libtest.def create mode 100644 liblfds/liblfds7.1.0/test_and_benchmark/libtest/build/msvc_gnumake/makefile create mode 100644 liblfds/liblfds7.1.0/test_and_benchmark/libtest/build/wdk_7.1/dirs create mode 100644 liblfds/liblfds7.1.0/test_and_benchmark/libtest/build/wdk_7.1/driver_entry_renamed_to_avoid_compiler_warning.c create mode 100644 liblfds/liblfds7.1.0/test_and_benchmark/libtest/build/wdk_7.1/libtest.def create mode 100644 liblfds/liblfds7.1.0/test_and_benchmark/libtest/build/wdk_7.1/readme_before_win_kernel_build.txt create mode 100644 liblfds/liblfds7.1.0/test_and_benchmark/libtest/build/wdk_7.1/runme_before_win_kernel_dynamic_lib_build.bat create mode 100644 liblfds/liblfds7.1.0/test_and_benchmark/libtest/build/wdk_7.1/runme_before_win_kernel_static_lib_build.bat create mode 100644 liblfds/liblfds7.1.0/test_and_benchmark/libtest/build/wdk_7.1/sources.dynamic create mode 100644 liblfds/liblfds7.1.0/test_and_benchmark/libtest/build/wdk_7.1/sources.static create mode 100644 liblfds/liblfds7.1.0/test_and_benchmark/libtest/inc/libtest.h create mode 100644 liblfds/liblfds7.1.0/test_and_benchmark/libtest/inc/libtest/libtest_misc.h create mode 100644 liblfds/liblfds7.1.0/test_and_benchmark/libtest/inc/libtest/libtest_porting_abstraction_layer.h create mode 100644 liblfds/liblfds7.1.0/test_and_benchmark/libtest/inc/libtest/libtest_porting_abstraction_layer_compiler.h create mode 100644 liblfds/liblfds7.1.0/test_and_benchmark/libtest/inc/libtest/libtest_porting_abstraction_layer_operating_system.h create mode 100644 liblfds/liblfds7.1.0/test_and_benchmark/libtest/inc/libtest/libtest_results.h create mode 100644 liblfds/liblfds7.1.0/test_and_benchmark/libtest/inc/libtest/libtest_test.h create mode 100644 liblfds/liblfds7.1.0/test_and_benchmark/libtest/inc/libtest/libtest_tests.h create mode 100644 liblfds/liblfds7.1.0/test_and_benchmark/libtest/inc/libtest/libtest_testsuite.h create mode 100644 liblfds/liblfds7.1.0/test_and_benchmark/libtest/inc/libtest/libtest_threadset.h create mode 100644 liblfds/liblfds7.1.0/test_and_benchmark/libtest/obj/empty_dir_placeholder_for_git create mode 100644 liblfds/liblfds7.1.0/test_and_benchmark/libtest/src/libtest_internal.h create mode 100644 liblfds/liblfds7.1.0/test_and_benchmark/libtest/src/libtest_misc/libtest_misc_determine_erg.c create mode 100644 liblfds/liblfds7.1.0/test_and_benchmark/libtest/src/libtest_misc/libtest_misc_globals.c create mode 100644 liblfds/liblfds7.1.0/test_and_benchmark/libtest/src/libtest_misc/libtest_misc_internal.h create mode 100644 liblfds/liblfds7.1.0/test_and_benchmark/libtest/src/libtest_misc/libtest_misc_memory_helpers.c create mode 100644 liblfds/liblfds7.1.0/test_and_benchmark/libtest/src/libtest_misc/libtest_misc_pal_helpers.c create mode 100644 liblfds/liblfds7.1.0/test_and_benchmark/libtest/src/libtest_misc/libtest_misc_query.c create mode 100644 liblfds/liblfds7.1.0/test_and_benchmark/libtest/src/libtest_porting_abstraction_layer/libtest_porting_abstraction_layer_free.c create mode 100644 liblfds/liblfds7.1.0/test_and_benchmark/libtest/src/libtest_porting_abstraction_layer/libtest_porting_abstraction_layer_get_full_logical_processor_set.c create mode 100644 liblfds/liblfds7.1.0/test_and_benchmark/libtest/src/libtest_porting_abstraction_layer/libtest_porting_abstraction_layer_internal.h create mode 100644 liblfds/liblfds7.1.0/test_and_benchmark/libtest/src/libtest_porting_abstraction_layer/libtest_porting_abstraction_layer_malloc.c create mode 100644 liblfds/liblfds7.1.0/test_and_benchmark/libtest/src/libtest_results/libtest_results_cleanup.c create mode 100644 liblfds/liblfds7.1.0/test_and_benchmark/libtest/src/libtest_results/libtest_results_get_result.c create mode 100644 liblfds/liblfds7.1.0/test_and_benchmark/libtest/src/libtest_results/libtest_results_init.c create mode 100644 liblfds/liblfds7.1.0/test_and_benchmark/libtest/src/libtest_results/libtest_results_internal.h create mode 100644 liblfds/liblfds7.1.0/test_and_benchmark/libtest/src/libtest_results/libtest_results_put_result.c create mode 100644 liblfds/liblfds7.1.0/test_and_benchmark/libtest/src/libtest_test/libtest_test_cleanup.c create mode 100644 liblfds/liblfds7.1.0/test_and_benchmark/libtest/src/libtest_test/libtest_test_init.c create mode 100644 liblfds/liblfds7.1.0/test_and_benchmark/libtest/src/libtest_test/libtest_test_internal.h create mode 100644 liblfds/liblfds7.1.0/test_and_benchmark/libtest/src/libtest_test/libtest_test_run.c create mode 100644 liblfds/liblfds7.1.0/test_and_benchmark/libtest/src/libtest_tests/libtest_tests_btree_addonly_unbalanced_alignment.c create mode 100644 liblfds/liblfds7.1.0/test_and_benchmark/libtest/src/libtest_tests/libtest_tests_btree_addonly_unbalanced_random_adds_fail.c create mode 100644 liblfds/liblfds7.1.0/test_and_benchmark/libtest/src/libtest_tests/libtest_tests_btree_addonly_unbalanced_random_adds_fail_and_overwrite.c create mode 100644 liblfds/liblfds7.1.0/test_and_benchmark/libtest/src/libtest_tests/libtest_tests_btree_addonly_unbalanced_random_adds_overwrite.c create mode 100644 liblfds/liblfds7.1.0/test_and_benchmark/libtest/src/libtest_tests/libtest_tests_freelist_alignment.c create mode 100644 liblfds/liblfds7.1.0/test_and_benchmark/libtest/src/libtest_tests/libtest_tests_freelist_ea_popping.c create mode 100644 liblfds/liblfds7.1.0/test_and_benchmark/libtest/src/libtest_tests/libtest_tests_freelist_ea_popping_and_pushing.c create mode 100644 liblfds/liblfds7.1.0/test_and_benchmark/libtest/src/libtest_tests/libtest_tests_freelist_ea_pushing.c create mode 100644 liblfds/liblfds7.1.0/test_and_benchmark/libtest/src/libtest_tests/libtest_tests_freelist_ea_rapid_popping_and_pushing.c create mode 100644 liblfds/liblfds7.1.0/test_and_benchmark/libtest/src/libtest_tests/libtest_tests_freelist_without_ea_popping.c create mode 100644 liblfds/liblfds7.1.0/test_and_benchmark/libtest/src/libtest_tests/libtest_tests_freelist_without_ea_popping_and_pushing.c create mode 100644 liblfds/liblfds7.1.0/test_and_benchmark/libtest/src/libtest_tests/libtest_tests_freelist_without_ea_pushing.c create mode 100644 liblfds/liblfds7.1.0/test_and_benchmark/libtest/src/libtest_tests/libtest_tests_freelist_without_ea_rapid_popping_and_pushing.c create mode 100644 liblfds/liblfds7.1.0/test_and_benchmark/libtest/src/libtest_tests/libtest_tests_hash_addonly_alignment.c create mode 100644 liblfds/liblfds7.1.0/test_and_benchmark/libtest/src/libtest_tests/libtest_tests_hash_addonly_fail_and_overwrite.c create mode 100644 liblfds/liblfds7.1.0/test_and_benchmark/libtest/src/libtest_tests/libtest_tests_hash_addonly_iterate.c create mode 100644 liblfds/liblfds7.1.0/test_and_benchmark/libtest/src/libtest_tests/libtest_tests_hash_addonly_random_adds_fail.c create mode 100644 liblfds/liblfds7.1.0/test_and_benchmark/libtest/src/libtest_tests/libtest_tests_hash_addonly_random_adds_overwrite.c create mode 100644 liblfds/liblfds7.1.0/test_and_benchmark/libtest/src/libtest_tests/libtest_tests_internal.h create mode 100644 liblfds/liblfds7.1.0/test_and_benchmark/libtest/src/libtest_tests/libtest_tests_list_addonly_singlylinked_ordered_alignment.c create mode 100644 liblfds/liblfds7.1.0/test_and_benchmark/libtest/src/libtest_tests/libtest_tests_list_addonly_singlylinked_ordered_new_ordered.c create mode 100644 liblfds/liblfds7.1.0/test_and_benchmark/libtest/src/libtest_tests/libtest_tests_list_addonly_singlylinked_ordered_new_ordered_with_cursor.c create mode 100644 liblfds/liblfds7.1.0/test_and_benchmark/libtest/src/libtest_tests/libtest_tests_list_addonly_singlylinked_unordered_alignment.c create mode 100644 liblfds/liblfds7.1.0/test_and_benchmark/libtest/src/libtest_tests/libtest_tests_list_addonly_singlylinked_unordered_new_after.c create mode 100644 liblfds/liblfds7.1.0/test_and_benchmark/libtest/src/libtest_tests/libtest_tests_list_addonly_singlylinked_unordered_new_end.c create mode 100644 liblfds/liblfds7.1.0/test_and_benchmark/libtest/src/libtest_tests/libtest_tests_list_addonly_singlylinked_unordered_new_start.c create mode 100644 liblfds/liblfds7.1.0/test_and_benchmark/libtest/src/libtest_tests/libtest_tests_porting_abstraction_layer_atomic_add.c create mode 100644 liblfds/liblfds7.1.0/test_and_benchmark/libtest/src/libtest_tests/libtest_tests_porting_abstraction_layer_atomic_cas.c create mode 100644 liblfds/liblfds7.1.0/test_and_benchmark/libtest/src/libtest_tests/libtest_tests_porting_abstraction_layer_atomic_dwcas.c create mode 100644 liblfds/liblfds7.1.0/test_and_benchmark/libtest/src/libtest_tests/libtest_tests_porting_abstraction_layer_atomic_exchange.c create mode 100644 liblfds/liblfds7.1.0/test_and_benchmark/libtest/src/libtest_tests/libtest_tests_prng_alignment.c create mode 100644 liblfds/liblfds7.1.0/test_and_benchmark/libtest/src/libtest_tests/libtest_tests_prng_generate.c create mode 100644 liblfds/liblfds7.1.0/test_and_benchmark/libtest/src/libtest_tests/libtest_tests_queue_bounded_manyproducer_manyconsumer_alignment.c create mode 100644 liblfds/liblfds7.1.0/test_and_benchmark/libtest/src/libtest_tests/libtest_tests_queue_bounded_manyproducer_manyconsumer_count.c create mode 100644 liblfds/liblfds7.1.0/test_and_benchmark/libtest/src/libtest_tests/libtest_tests_queue_bounded_manyproducer_manyconsumer_dequeuing.c create mode 100644 liblfds/liblfds7.1.0/test_and_benchmark/libtest/src/libtest_tests/libtest_tests_queue_bounded_manyproducer_manyconsumer_enqueuing.c create mode 100644 liblfds/liblfds7.1.0/test_and_benchmark/libtest/src/libtest_tests/libtest_tests_queue_bounded_manyproducer_manyconsumer_enqueuing_and_dequeuing.c create mode 100644 liblfds/liblfds7.1.0/test_and_benchmark/libtest/src/libtest_tests/libtest_tests_queue_bounded_manyproducer_manyconsumer_rapid_enqueuing_and_dequeuing.c create mode 100644 liblfds/liblfds7.1.0/test_and_benchmark/libtest/src/libtest_tests/libtest_tests_queue_bounded_singleproducer_singleconsumer_dequeuing.c create mode 100644 liblfds/liblfds7.1.0/test_and_benchmark/libtest/src/libtest_tests/libtest_tests_queue_bounded_singleproducer_singleconsumer_enqueuing.c create mode 100644 liblfds/liblfds7.1.0/test_and_benchmark/libtest/src/libtest_tests/libtest_tests_queue_bounded_singleproducer_singleconsumer_enqueuing_and_dequeuing.c create mode 100644 liblfds/liblfds7.1.0/test_and_benchmark/libtest/src/libtest_tests/libtest_tests_queue_unbounded_manyproducer_manyconsumer_alignment.c create mode 100644 liblfds/liblfds7.1.0/test_and_benchmark/libtest/src/libtest_tests/libtest_tests_queue_unbounded_manyproducer_manyconsumer_dequeuing.c create mode 100644 liblfds/liblfds7.1.0/test_and_benchmark/libtest/src/libtest_tests/libtest_tests_queue_unbounded_manyproducer_manyconsumer_enqueuing.c create mode 100644 liblfds/liblfds7.1.0/test_and_benchmark/libtest/src/libtest_tests/libtest_tests_queue_unbounded_manyproducer_manyconsumer_enqueuing_and_dequeuing.c create mode 100644 liblfds/liblfds7.1.0/test_and_benchmark/libtest/src/libtest_tests/libtest_tests_queue_unbounded_manyproducer_manyconsumer_enqueuing_with_malloc_and_dequeuing_with_free.c create mode 100644 liblfds/liblfds7.1.0/test_and_benchmark/libtest/src/libtest_tests/libtest_tests_queue_unbounded_manyproducer_manyconsumer_rapid_enqueuing_and_dequeuing.c create mode 100644 liblfds/liblfds7.1.0/test_and_benchmark/libtest/src/libtest_tests/libtest_tests_ringbuffer_reading.c create mode 100644 liblfds/liblfds7.1.0/test_and_benchmark/libtest/src/libtest_tests/libtest_tests_ringbuffer_reading_and_writing.c create mode 100644 liblfds/liblfds7.1.0/test_and_benchmark/libtest/src/libtest_tests/libtest_tests_ringbuffer_writing.c create mode 100644 liblfds/liblfds7.1.0/test_and_benchmark/libtest/src/libtest_tests/libtest_tests_stack_alignment.c create mode 100644 liblfds/liblfds7.1.0/test_and_benchmark/libtest/src/libtest_tests/libtest_tests_stack_popping.c create mode 100644 liblfds/liblfds7.1.0/test_and_benchmark/libtest/src/libtest_tests/libtest_tests_stack_popping_and_pushing.c create mode 100644 liblfds/liblfds7.1.0/test_and_benchmark/libtest/src/libtest_tests/libtest_tests_stack_pushing.c create mode 100644 liblfds/liblfds7.1.0/test_and_benchmark/libtest/src/libtest_tests/libtest_tests_stack_rapid_popping_and_pushing.c create mode 100644 liblfds/liblfds7.1.0/test_and_benchmark/libtest/src/libtest_testsuite/libtest_testsuite_cleanup.c create mode 100644 liblfds/liblfds7.1.0/test_and_benchmark/libtest/src/libtest_testsuite/libtest_testsuite_init.c create mode 100644 liblfds/liblfds7.1.0/test_and_benchmark/libtest/src/libtest_testsuite/libtest_testsuite_internal.h create mode 100644 liblfds/liblfds7.1.0/test_and_benchmark/libtest/src/libtest_testsuite/libtest_testsuite_run.c create mode 100644 liblfds/liblfds7.1.0/test_and_benchmark/libtest/src/libtest_threadset/libtest_threadset_add.c create mode 100644 liblfds/liblfds7.1.0/test_and_benchmark/libtest/src/libtest_threadset/libtest_threadset_cleanup.c create mode 100644 liblfds/liblfds7.1.0/test_and_benchmark/libtest/src/libtest_threadset/libtest_threadset_init.c create mode 100644 liblfds/liblfds7.1.0/test_and_benchmark/libtest/src/libtest_threadset/libtest_threadset_internal.h create mode 100644 liblfds/liblfds7.1.0/test_and_benchmark/libtest/src/libtest_threadset/libtest_threadset_operations.c create mode 100644 liblfds/liblfds7.1.0/test_and_benchmark/test/bin/empty_dir_placeholder_for_git create mode 100644 liblfds/liblfds7.1.0/test_and_benchmark/test/build/gcc_gnumake_hosted/Makefile create mode 100644 liblfds/liblfds7.1.0/test_and_benchmark/test/build/msvc_gnumake/makefile create mode 100644 liblfds/liblfds7.1.0/test_and_benchmark/test/obj/empty_dir_placeholder_for_git create mode 100644 liblfds/liblfds7.1.0/test_and_benchmark/test/src/callbacks.c create mode 100644 liblfds/liblfds7.1.0/test_and_benchmark/test/src/internal.h create mode 100644 liblfds/liblfds7.1.0/test_and_benchmark/test/src/main.c create mode 100644 liblfds/liblfds7.1.0/test_and_benchmark/test/src/misc.c create mode 100644 liblfds/liblfds7.1.0/test_and_benchmark/test/src/util_cmdline.c create mode 100644 liblfds/liblfds7.1.0/test_and_benchmark/test/src/util_cmdline.h create mode 100644 liblfds/liblfds7.1.0/test_and_benchmark/what do we have here.txt create mode 100644 liblfds/versioning.txt diff --git a/liblfds/liblfds6.0.0/liblfds600/bin/empty_dir_placeholder_for_git b/liblfds/liblfds6.0.0/liblfds600/bin/empty_dir_placeholder_for_git new file mode 100644 index 0000000..e69de29 diff --git a/liblfds/liblfds6.0.0/liblfds600/building.txt b/liblfds/liblfds6.0.0/liblfds600/building.txt new file mode 100644 index 0000000..df5a0e3 --- /dev/null +++ b/liblfds/liblfds6.0.0/liblfds600/building.txt @@ -0,0 +1,38 @@ +building liblfds +================ + +Windows (user-mode) +=================== +1. Use Microsoft Visual Studio 2008 or Visual C++ 2008 Express Edition + to load "liblfds.sln". + +2. Use Microsoft Windows SDK and GNUmake to run makefile.windows (obviously + you'll need to have run the appropriate vcvars*.bat first; you can build + for both IA64, 64-bit and 32-bit - just run the correct vcvars batch file). + + Targets are "librel", "libdbg", "dllrel", "dlldbg" and "clean". You need + to clean between switching targets. + +Windows (kernel) +================ +Use the Windows Driver Kit "build" command. Prior to running "build", +if you wish to build a static library, run the batch file +"runme_before_win_kernel_static_lib_build.bat"; if you wish to +build a dynamic library, instead run "runme_before_win_kernel_dynamic_lib_build.bat". + +The Windows kernel build system is rather limited and rather than +really rather messing up the directory/file structure just for the +Windows kernel platform, I've instead arranged it that these batch +files do the necessary work so that "build" will work. + +The batch files are idempotent; you can run them as often as you +like, in any order, at any time (before or after builds), and they'll +do the right thing. + +Linux +===== +Use GNUmake to run "makefile.linux". Targets are "arrel", "ardbg", +"sorel", "sodbg" and "clean". You need to clean between switching +targets. + + diff --git a/liblfds/liblfds6.0.0/liblfds600/dirs b/liblfds/liblfds6.0.0/liblfds600/dirs new file mode 100644 index 0000000..0be5295 --- /dev/null +++ b/liblfds/liblfds6.0.0/liblfds600/dirs @@ -0,0 +1,2 @@ +DIRS = src + diff --git a/liblfds/liblfds6.0.0/liblfds600/inc/liblfds600.h b/liblfds/liblfds6.0.0/liblfds600/inc/liblfds600.h new file mode 100644 index 0000000..c3db041 --- /dev/null +++ b/liblfds/liblfds6.0.0/liblfds600/inc/liblfds600.h @@ -0,0 +1,282 @@ +#ifndef __LIBLFDS600_H + + /***** library header *****/ + #define LFDS600_RELEASE_NUMBER 1 + + + + + /***** lfds600_abstraction *****/ + + /***** defines *****/ + #if (defined _WIN64 && defined _MSC_VER && !defined WIN_KERNEL_BUILD) + // TRD : 64-bit Windows user-mode with the Microsoft C compiler, any CPU + #include + #include + #include + #include + #include + typedef unsigned __int64 lfds600_atom_t; + #define LFDS600_INLINE extern __forceinline + #define LFDS600_ALIGN(alignment) __declspec( align(alignment) ) + #define LFDS600_ALIGN_SINGLE_POINTER 8 + #define LFDS600_ALIGN_DOUBLE_POINTER 16 + #endif + + #if (!defined _WIN64 && defined _WIN32 && defined _MSC_VER && !defined WIN_KERNEL_BUILD) + // TRD : 32-bit Windows user-mode with the Microsoft C compiler, any CPU + #include + #include + #include + #include + #include + typedef unsigned long int lfds600_atom_t; + #define LFDS600_INLINE extern __forceinline + #define LFDS600_ALIGN(alignment) __declspec( align(alignment) ) + #define LFDS600_ALIGN_SINGLE_POINTER 4 + #define LFDS600_ALIGN_DOUBLE_POINTER 8 + + // TRD : this define is documented but missing in Microsoft Platform SDK v7.0 + #define _InterlockedCompareExchangePointer(destination, exchange, compare) _InterlockedCompareExchange((volatile long *) destination, (long) exchange, (long) compare) + #endif + + #if (defined _WIN64 && defined _MSC_VER && defined WIN_KERNEL_BUILD) + // TRD : 64-bit Windows kernel with the Microsoft C compiler, any CPU + #include + #include + #include + #include + typedef unsigned __int64 lfds600_atom_t; + #define LFDS600_INLINE extern __forceinline + #define LFDS600_ALIGN(alignment) __declspec( align(alignment) ) + #define LFDS600_ALIGN_SINGLE_POINTER 8 + #define LFDS600_ALIGN_DOUBLE_POINTER 16 + #endif + + #if (!defined _WIN64 && defined _WIN32 && defined _MSC_VER && defined WIN_KERNEL_BUILD) + // TRD : 32-bit Windows kernel with the Microsoft C compiler, any CPU + #include + #include + #include + #include + typedef unsigned long int lfds600_atom_t; + #define LFDS600_INLINE extern __forceinline + #define LFDS600_ALIGN(alignment) __declspec( align(alignment) ) + #define LFDS600_ALIGN_SINGLE_POINTER 4 + #define LFDS600_ALIGN_DOUBLE_POINTER 8 + + // TRD : this define is documented but missing in Microsoft Platform SDK v7.0 + #define _InterlockedCompareExchangePointer(destination, exchange, compare) _InterlockedCompareExchange((volatile long *) destination, (long) exchange, (long) compare) + #endif + + #if (defined __unix__ && defined __x86_64__ && __GNUC__) + // TRD : any UNIX with GCC on x64 + #define _XOPEN_SOURCE 600 + #include + #include + #include + typedef unsigned long long int lfds600_atom_t; + #define LFDS600_INLINE inline + #define LFDS600_ALIGN(alignment) __attribute__( (aligned(alignment)) ) + #define LFDS600_ALIGN_SINGLE_POINTER 8 + #define LFDS600_ALIGN_DOUBLE_POINTER 16 + #endif + + #if (defined __unix__ && defined __i686__ && __GNUC__) + // TRD : any UNIX with GCC on x86 + #define _XOPEN_SOURCE 600 + #include + #include + #include + typedef unsigned long int lfds600_atom_t; + #define LFDS600_INLINE inline + #define LFDS600_ALIGN(alignment) __attribute__( (aligned(alignment)) ) + #define LFDS600_ALIGN_SINGLE_POINTER 4 + #define LFDS600_ALIGN_DOUBLE_POINTER 8 + #endif + + #if (defined __unix__ && defined __arm__ && __GNUC__) + // TRD : any UNIX with GCC on ARM + #define _XOPEN_SOURCE 600 + #include + #include + #include + typedef unsigned long int lfds600_atom_t; + #define LFDS600_INLINE inline + #define LFDS600_ALIGN(alignment) __attribute__( (aligned(alignment)) ) + #define LFDS600_ALIGN_SINGLE_POINTER 4 + #define LFDS600_ALIGN_DOUBLE_POINTER 8 + #endif + + /***** enums *****/ + enum data_structure_validity + { + VALIDITY_VALID, + VALIDITY_INVALID_LOOP, + VALIDITY_INVALID_MISSING_ELEMENTS, + VALIDITY_INVALID_ADDITIONAL_ELEMENTS, + VALIDITY_INVALID_TEST_DATA + }; + + /***** structs *****/ + struct lfds600_validation_info + { + lfds600_atom_t + min_elements, + max_elements; + }; + + /***** public prototypes *****/ + void lfds600_abstraction_aligned_free( void *memory ); + void *lfds600_abstraction_aligned_malloc( size_t size, size_t align_in_bytes ); + lfds600_atom_t lfds600_abstraction_cas( volatile lfds600_atom_t *destination, lfds600_atom_t exchange, lfds600_atom_t compare ); + unsigned char lfds600_abstraction_dcas( volatile lfds600_atom_t *destination, lfds600_atom_t *exchange, lfds600_atom_t *compare ); + lfds600_atom_t lfds600_abstraction_increment( lfds600_atom_t *value ); + + + + + + /***** lfds600_freelist *****/ + + /***** enums *****/ + enum lfds600_freelist_query_type + { + LFDS600_FREELIST_QUERY_ELEMENT_COUNT, + LFDS600_FREELIST_QUERY_VALIDATE + }; + + /***** incomplete types *****/ + struct lfds600_freelist_state; + struct lfds600_freelist_element; + + /***** public prototypes *****/ + int lfds600_freelist_new( struct lfds600_freelist_state **fs, lfds600_atom_t number_elements, int (*user_data_init_function)(void **user_data, void *user_state), void *user_state ); + void lfds600_freelist_delete( struct lfds600_freelist_state *fs, void (*user_data_delete_function)(void *user_data, void *user_state), void *user_state ); + + lfds600_atom_t lfds600_freelist_new_elements( struct lfds600_freelist_state *fs, lfds600_atom_t number_elements ); + + struct lfds600_freelist_element *lfds600_freelist_pop( struct lfds600_freelist_state *fs, struct lfds600_freelist_element **fe ); + struct lfds600_freelist_element *lfds600_freelist_guaranteed_pop( struct lfds600_freelist_state *fs, struct lfds600_freelist_element **fe ); + void lfds600_freelist_push( struct lfds600_freelist_state *fs, struct lfds600_freelist_element *fe ); + + void *lfds600_freelist_get_user_data_from_element( struct lfds600_freelist_element *fe, void **user_data ); + void lfds600_freelist_set_user_data_in_element( struct lfds600_freelist_element *fe, void *user_data ); + + void lfds600_freelist_query( struct lfds600_freelist_state *fs, enum lfds600_freelist_query_type query_type, void *query_input, void *query_output ); + + + + + + /***** lfds600_queue *****/ + + /***** enums *****/ + enum lfds600_queue_query_type + { + LFDS600_QUEUE_QUERY_ELEMENT_COUNT, + LFDS600_QUEUE_QUERY_VALIDATE + }; + + /***** incomplete types *****/ + struct lfds600_queue_state; + + /***** public prototypes *****/ + int lfds600_queue_new( struct lfds600_queue_state **sq, lfds600_atom_t number_elements ); + void lfds600_queue_delete( struct lfds600_queue_state *qs, void (*user_data_delete_function)(void *user_data, void *user_state), void *user_state ); + + int lfds600_queue_enqueue( struct lfds600_queue_state *qs, void *user_data ); + int lfds600_queue_guaranteed_enqueue( struct lfds600_queue_state *qs, void *user_data ); + int lfds600_queue_dequeue( struct lfds600_queue_state *qs, void **user_data ); + + void lfds600_queue_query( struct lfds600_queue_state *qs, enum lfds600_queue_query_type query_type, void *query_input, void *query_output ); + + + + + + /***** lfds600_ringbuffer *****/ + + /***** enums *****/ + enum lfds600_ringbuffer_query_type + { + LFDS600_RINGBUFFER_QUERY_VALIDATE + }; + + /***** incomplete types *****/ + struct lfds600_ringbuffer_state; + + /***** public prototypes *****/ + int lfds600_ringbuffer_new( struct lfds600_ringbuffer_state **rs, lfds600_atom_t number_elements, int (*user_data_init_function)(void **user_data, void *user_state), void *user_state ); + void lfds600_ringbuffer_delete( struct lfds600_ringbuffer_state *rs, void (*user_data_delete_function)(void *user_data, void *user_state), void *user_state ); + + struct lfds600_freelist_element *lfds600_ringbuffer_get_read_element( struct lfds600_ringbuffer_state *rs, struct lfds600_freelist_element **fe ); + struct lfds600_freelist_element *lfds600_ringbuffer_get_write_element( struct lfds600_ringbuffer_state *rs, struct lfds600_freelist_element **fe, int *overwrite_flag ); + + void lfds600_ringbuffer_put_read_element( struct lfds600_ringbuffer_state *rs, struct lfds600_freelist_element *fe ); + void lfds600_ringbuffer_put_write_element( struct lfds600_ringbuffer_state *rs, struct lfds600_freelist_element *fe ); + + void lfds600_ringbuffer_query( struct lfds600_ringbuffer_state *rs, enum lfds600_ringbuffer_query_type query_type, void *query_input, void *query_output ); + + + + + + /***** lfds600_slist *****/ + + /***** incomplete types *****/ + struct lfds600_slist_state; + struct lfds600_slist_element; + + /***** public prototypes *****/ + int lfds600_slist_new( struct lfds600_slist_state **ss, void (*user_data_delete_function)(void *user_data, void *user_state), void *user_state ); + void lfds600_slist_delete( struct lfds600_slist_state *ss ); + + struct lfds600_slist_element *lfds600_slist_new_head( struct lfds600_slist_state *ss, void *user_data ); + struct lfds600_slist_element *lfds600_slist_new_next( struct lfds600_slist_element *se, void *user_data ); + + void lfds600_slist_delete_element( struct lfds600_slist_state *ss, struct lfds600_slist_element *se ); + void lfds600_slist_delete_all_elements( struct lfds600_slist_state *ss ); + + int lfds600_slist_get_user_data_from_element( struct lfds600_slist_element *se, void **user_data ); + int lfds600_slist_set_user_data_in_element( struct lfds600_slist_element *se, void *user_data ); + + struct lfds600_slist_element *lfds600_slist_get_head( struct lfds600_slist_state *ss, struct lfds600_slist_element **se ); + struct lfds600_slist_element *lfds600_slist_get_next( struct lfds600_slist_element *se, struct lfds600_slist_element **next_se ); + struct lfds600_slist_element *lfds600_slist_get_head_and_then_next( struct lfds600_slist_state *ss, struct lfds600_slist_element **se ); + + + + + + /***** lfds600_stack *****/ + + /***** enums *****/ + enum lfds600_stack_query_type + { + LFDS600_STACK_QUERY_ELEMENT_COUNT + }; + + /***** incomplete types *****/ + struct lfds600_stack_state; + + /***** public prototypes *****/ + int lfds600_stack_new( struct lfds600_stack_state **ss, lfds600_atom_t number_elements ); + void lfds600_stack_delete( struct lfds600_stack_state *ss, void (*user_data_delete_function)(void *user_data, void *user_state), void *user_state ); + + void lfds600_stack_clear( struct lfds600_stack_state *ss, void (*user_data_clear_function)(void *user_data, void *user_state), void *user_state ); + + int lfds600_stack_push( struct lfds600_stack_state *ss, void *user_data ); + int lfds600_stack_guaranteed_push( struct lfds600_stack_state *ss, void *user_data ); + int lfds600_stack_pop( struct lfds600_stack_state *ss, void **user_data ); + + void lfds600_stack_query( struct lfds600_stack_state *ss, enum lfds600_stack_query_type query_type, void *query_input, void *query_output ); + + + + + + #define __LIBLFDS600_H + +#endif + diff --git a/liblfds/liblfds6.0.0/liblfds600/liblfds600.def b/liblfds/liblfds6.0.0/liblfds600/liblfds600.def new file mode 100644 index 0000000..37e0b40 --- /dev/null +++ b/liblfds/liblfds6.0.0/liblfds600/liblfds600.def @@ -0,0 +1,46 @@ +EXPORTS + +lfds600_freelist_delete = lfds600_freelist_delete @1 +lfds600_freelist_get_user_data_from_element = lfds600_freelist_get_user_data_from_element @2 +lfds600_freelist_guaranteed_pop = lfds600_freelist_guaranteed_pop @3 +lfds600_freelist_new = lfds600_freelist_new @4 +lfds600_freelist_new_elements = lfds600_freelist_new_elements @5 +lfds600_freelist_pop = lfds600_freelist_pop @6 +lfds600_freelist_push = lfds600_freelist_push @7 +lfds600_freelist_query = lfds600_freelist_query @8 +lfds600_freelist_set_user_data_in_element = lfds600_freelist_set_user_data_in_element @9 + +lfds600_queue_delete = lfds600_queue_delete @10 +lfds600_queue_dequeue = lfds600_queue_dequeue @11 +lfds600_queue_enqueue = lfds600_queue_enqueue @12 +lfds600_queue_guaranteed_enqueue = lfds600_queue_guaranteed_enqueue @13 +lfds600_queue_new = lfds600_queue_new @14 +lfds600_queue_query = lfds600_queue_query @15 + +lfds600_ringbuffer_delete = lfds600_ringbuffer_delete @16 +lfds600_ringbuffer_get_read_element = lfds600_ringbuffer_get_read_element @17 +lfds600_ringbuffer_get_write_element = lfds600_ringbuffer_get_write_element @18 +lfds600_ringbuffer_new = lfds600_ringbuffer_new @19 +lfds600_ringbuffer_put_read_element = lfds600_ringbuffer_put_read_element @20 +lfds600_ringbuffer_put_write_element = lfds600_ringbuffer_put_write_element @21 + +lfds600_slist_delete = lfds600_slist_delete @ 22 +lfds600_slist_delete_all_elements = lfds600_slist_delete_all_elements @ 23 +lfds600_slist_delete_element = lfds600_slist_delete_element @ 24 +lfds600_slist_get_head = lfds600_slist_get_head @ 25 +lfds600_slist_get_head_and_then_next = lfds600_slist_get_head_and_then_next @ 26 +lfds600_slist_get_next = lfds600_slist_get_next @ 27 +lfds600_slist_get_user_data_from_element = lfds600_slist_get_user_data_from_element @ 28 +lfds600_slist_new = lfds600_slist_new @ 29 +lfds600_slist_new_head = lfds600_slist_new_head @ 30 +lfds600_slist_new_next = lfds600_slist_new_next @ 31 +lfds600_slist_set_user_data_in_element = lfds600_slist_set_user_data_in_element @ 32 + +lfds600_stack_clear = lfds600_stack_clear @33 +lfds600_stack_delete = lfds600_stack_delete @34 +lfds600_stack_guaranteed_push = lfds600_stack_guaranteed_push @35 +lfds600_stack_new = lfds600_stack_new @36 +lfds600_stack_pop = lfds600_stack_pop @37 +lfds600_stack_push = lfds600_stack_push @38 +lfds600_stack_query = lfds600_stack_query @39 + diff --git a/liblfds/liblfds6.0.0/liblfds600/liblfds600.sln b/liblfds/liblfds6.0.0/liblfds600/liblfds600.sln new file mode 100644 index 0000000..44a21ad --- /dev/null +++ b/liblfds/liblfds6.0.0/liblfds600/liblfds600.sln @@ -0,0 +1,38 @@ + +Microsoft Visual Studio Solution File, Format Version 10.00 +# Visual Studio 2008 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "liblfds600", "liblfds600.vcproj", "{F73AE755-F6D8-4C3A-977D-FBB40DC0ED05}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug DLL|Win32 = Debug DLL|Win32 + Debug DLL|x64 = Debug DLL|x64 + Debug Lib|Win32 = Debug Lib|Win32 + Debug Lib|x64 = Debug Lib|x64 + Release DLL|Win32 = Release DLL|Win32 + Release DLL|x64 = Release DLL|x64 + Release Lib|Win32 = Release Lib|Win32 + Release Lib|x64 = Release Lib|x64 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {F73AE755-F6D8-4C3A-977D-FBB40DC0ED05}.Debug DLL|Win32.ActiveCfg = Debug DLL|Win32 + {F73AE755-F6D8-4C3A-977D-FBB40DC0ED05}.Debug DLL|Win32.Build.0 = Debug DLL|Win32 + {F73AE755-F6D8-4C3A-977D-FBB40DC0ED05}.Debug DLL|x64.ActiveCfg = Debug DLL|x64 + {F73AE755-F6D8-4C3A-977D-FBB40DC0ED05}.Debug DLL|x64.Build.0 = Debug DLL|x64 + {F73AE755-F6D8-4C3A-977D-FBB40DC0ED05}.Debug Lib|Win32.ActiveCfg = Debug Lib|Win32 + {F73AE755-F6D8-4C3A-977D-FBB40DC0ED05}.Debug Lib|Win32.Build.0 = Debug Lib|Win32 + {F73AE755-F6D8-4C3A-977D-FBB40DC0ED05}.Debug Lib|x64.ActiveCfg = Debug Lib|x64 + {F73AE755-F6D8-4C3A-977D-FBB40DC0ED05}.Debug Lib|x64.Build.0 = Debug Lib|x64 + {F73AE755-F6D8-4C3A-977D-FBB40DC0ED05}.Release DLL|Win32.ActiveCfg = Release DLL|Win32 + {F73AE755-F6D8-4C3A-977D-FBB40DC0ED05}.Release DLL|Win32.Build.0 = Release DLL|Win32 + {F73AE755-F6D8-4C3A-977D-FBB40DC0ED05}.Release DLL|x64.ActiveCfg = Release DLL|x64 + {F73AE755-F6D8-4C3A-977D-FBB40DC0ED05}.Release DLL|x64.Build.0 = Release DLL|x64 + {F73AE755-F6D8-4C3A-977D-FBB40DC0ED05}.Release Lib|Win32.ActiveCfg = Release Lib|Win32 + {F73AE755-F6D8-4C3A-977D-FBB40DC0ED05}.Release Lib|Win32.Build.0 = Release Lib|Win32 + {F73AE755-F6D8-4C3A-977D-FBB40DC0ED05}.Release Lib|x64.ActiveCfg = Release Lib|x64 + {F73AE755-F6D8-4C3A-977D-FBB40DC0ED05}.Release Lib|x64.Build.0 = Release Lib|x64 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/liblfds/liblfds6.0.0/liblfds600/liblfds600.vcproj b/liblfds/liblfds6.0.0/liblfds600/liblfds600.vcproj new file mode 100644 index 0000000..3c81177 --- /dev/null +++ b/liblfds/liblfds6.0.0/liblfds600/liblfds600.vcproj @@ -0,0 +1,808 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/liblfds/liblfds6.0.0/liblfds600/makefile.linux b/liblfds/liblfds6.0.0/liblfds600/makefile.linux new file mode 100644 index 0000000..55308b0 --- /dev/null +++ b/liblfds/liblfds6.0.0/liblfds600/makefile.linux @@ -0,0 +1,103 @@ +##### paths ##### +BINDIR = bin +INCDIR = inc +OBJDIR = obj +SRCDIR = src + +##### misc ##### +QUIETLY = 1>/dev/null 2>/dev/null + +##### sources, objects and libraries ##### +BINNAME = liblfds600 +AR_BINARY = $(BINDIR)/$(BINNAME).a +SO_BINARY = $(BINDIR)/$(BINNAME).so +SRCDIRS = lfds600_abstraction lfds600_freelist lfds600_queue lfds600_ringbuffer lfds600_slist lfds600_stack +# TRD : be aware - in the linux makefile, with the one-pass linking behaviour of the GNU linker, the order +# of source files matters! this is because it leads to the ordering of objects in the library and +# that in turn, since the data structures all use the freelist API and the abstraction API, has to be +# correct +SOURCES = lfds600_queue_delete.c lfds600_queue_new.c lfds600_queue_query.c lfds600_queue_queue.c \ + lfds600_ringbuffer_delete.c lfds600_ringbuffer_get_and_put.c lfds600_ringbuffer_new.c lfds600_ringbuffer_query.c \ + lfds600_slist_delete.c lfds600_slist_get_and_set.c lfds600_slist_link.c lfds600_slist_new.c \ + lfds600_stack_delete.c lfds600_stack_new.c lfds600_stack_push_pop.c lfds600_stack_query.c \ + lfds600_freelist_delete.c lfds600_freelist_get_and_set.c lfds600_freelist_new.c lfds600_freelist_query.c lfds600_freelist_pop_push.c \ + lfds600_abstraction_aligned_free.c lfds600_abstraction_aligned_malloc.c lfds600_abstraction_cas.c lfds600_abstraction_dcas.c lfds600_abstraction_increment.c +OBJECTS = $(patsubst %.c,$(OBJDIR)/%.o,$(notdir $(SOURCES))) + +##### CPU variants ##### +GCCARCH = $(shell uname -m) + +ifeq ($(GCCARCH),x86_64) + GCCARCH = core2 +endif + +ifeq ($(findstring arm,$(GCCARCH)),arm) + GCCARCH = armv6k +endif + +##### tools ##### +MAKE = make +MFLAGS = + +DG = gcc +DGFLAGS = -MM -std=c99 -I"$(SRCDIR)" -I"$(INCDIR)" + +CC = gcc +CBASE = -Wall -Wno-unknown-pragmas -std=c99 -march=$(GCCARCH) -c -I"$(SRCDIR)" -I"$(INCDIR)" +CFREL = -O2 -finline-functions -Wno-strict-aliasing +CFDBG = -O0 -g + +AR = ar +AFLAGS = -rcs + +LD = gcc +LFBASE = -Wall -std=c99 -shared +LFREL = -O2 -s +LFDBG = -O0 -g + +##### rel/dbg .a/.so variants ##### +ifeq ($(findstring so,$(MAKECMDGOALS)),so) + CBASE := $(CBASE) -fpic +endif + +CFLAGS = $(CBASE) $(CFDBG) +LFLAGS = $(LFBASE) $(LFDBG) + +ifeq ($(findstring rel,$(MAKECMDGOALS)),rel) + CFLAGS = $(CBASE) $(CFREL) + LFLAGS = $(LFBASE) $(LFREL) +endif + +##### search paths ##### +vpath %.c $(patsubst %,$(SRCDIR)/%:,$(SRCDIRS)) + +##### implicit rules ##### +$(OBJDIR)/%.o : %.c + $(DG) $(DGFLAGS) $< >$(OBJDIR)/$*.d + $(CC) $(CFLAGS) -o $@ $< + +##### explicit rules ##### +$(AR_BINARY) : $(OBJECTS) + $(AR) $(AFLAGS) $(AR_BINARY) $(OBJECTS) + +$(SO_BINARY) : $(OBJECTS) + $(LD) $(LFLAGS) $(SYSLIBS) $(OBJECTS) -o $(SO_BINARY) + +##### phony ##### +.PHONY : clean arrel ardbg sorel sodbg + +clean : + @rm -f $(BINDIR)/$(BINNAME).* $(OBJDIR)/*.o $(OBJDIR)/*.d + +arrel : $(AR_BINARY) +ardbg : $(AR_BINARY) + +sorel : $(SO_BINARY) +sodbg : $(SO_BINARY) + +##### dependencies ##### +-include $(DEPENDS) + +##### notes ##### +# TRD : we use -std=c99 purely to permit C++ style comments + diff --git a/liblfds/liblfds6.0.0/liblfds600/makefile.windows b/liblfds/liblfds6.0.0/liblfds600/makefile.windows new file mode 100644 index 0000000..29f7406 --- /dev/null +++ b/liblfds/liblfds6.0.0/liblfds600/makefile.windows @@ -0,0 +1,94 @@ +##### paths ##### +BINDIR = bin +INCDIR = inc +OBJDIR = obj +SRCDIR = src + +##### misc ##### +QUIETLY = 1>nul 2>nul + +##### sources, objects and libraries ##### +BINNAME = liblfds600 +LIB_BINARY = $(BINDIR)\$(BINNAME).lib +DLL_BINARY = $(BINDIR)\$(BINNAME).dll +SRCDIRS = lfds600_abstraction lfds600_freelist lfds600_queue lfds600_ringbuffer lfds600_slist lfds600_stack +SOURCES = lfds600_abstraction_aligned_free.c lfds600_abstraction_aligned_malloc.c lfds600_abstraction_cas.c lfds600_abstraction_dcas.c lfds600_abstraction_increment.c \ + lfds600_freelist_delete.c lfds600_freelist_get_and_set.c lfds600_freelist_new.c lfds600_freelist_query.c lfds600_freelist_pop_push.c \ + lfds600_queue_delete.c lfds600_queue_new.c lfds600_queue_query.c lfds600_queue_queue.c \ + lfds600_ringbuffer_delete.c lfds600_ringbuffer_get_and_put.c lfds600_ringbuffer_new.c lfds600_ringbuffer_query.c \ + lfds600_slist_delete.c lfds600_slist_get_and_set.c lfds600_slist_link.c lfds600_slist_new.c \ + lfds600_stack_delete.c lfds600_stack_new.c lfds600_stack_push_pop.c lfds600_stack_query.c +OBJECTS = $(patsubst %.c,$(OBJDIR)/%.obj,$(notdir $(SOURCES))) + +##### tools ##### +MAKE = make +MFLAGS = + +CC = cl +CBASE = /nologo /W4 /WX /c "-I$(SRCDIR)" "-I$(INCDIR)" "/Fd$(BINDIR)\$(BINNAME).pdb" /DUNICODE /D_UNICODE /DWIN32_LEAN_AND_MEAN +CFREL = /Ox /DNDEBUG +CFDBG = /Od /Gm /Zi /D_DEBUG + +AR = lib +AFLAGS = /nologo /subsystem:console /wx /verbose + +LD = link +LFBASE = /dll /def:$(BINNAME).def /nologo /subsystem:console /wx /nodefaultlib /nxcompat +LFREL = /incremental:no +LFDBG = /debug "/pdb:$(BINDIR)\$(BINNAME).pdb" + +##### variants ##### +CFLAGS = $(CBASE) $(CFDBG) /MTd +LFLAGS = $(LFBASE) $(LFDBG) +CLIB = libcmtd.lib + +ifeq ($(MAKECMDGOALS),librel) + CFLAGS = $(CBASE) $(CFREL) /MT + LFLAGS = $(LFBASE) $(LFREL) + CLIB = libcmt.lib +endif + +ifeq ($(MAKECMDGOALS),libdbg) + CFLAGS = $(CBASE) $(CFDBG) /MTd + LFLAGS = $(LFBASE) $(LFDBG) + CLIB = libcmtd.lib +endif + +ifeq ($(MAKECMDGOALS),dllrel) + CFLAGS = $(CBASE) $(CFREL) /MD + LFLAGS = $(LFBASE) $(LFREL) + CLIB = msvcrt.lib +endif + +ifeq ($(MAKECMDGOALS),dlldbg) + CFLAGS = $(CBASE) $(CFDBG) /MDd + LFLAGS = $(LFBASE) $(LFDBG) + CLIB = msvcrtd.lib +endif + +##### search paths ##### +vpath %.c $(patsubst %,$(SRCDIR)/%;,$(SRCDIRS)) + +##### implicit rules ##### +$(OBJDIR)/%.obj : %.c + $(CC) $(CFLAGS) "/Fo$@" $< + +##### explicit rules ##### +$(LIB_BINARY) : $(OBJECTS) + $(AR) $(AFLAGS) $(OBJECTS) /out:$(LIB_BINARY) + +$(DLL_BINARY) : $(OBJECTS) + $(LD) $(LFLAGS) $(CLIB) $(OBJECTS) /out:$(DLL_BINARY) + +##### phony ##### +.PHONY : clean librel libdbg dllrel dlldbg + +clean : + @erase /Q $(BINDIR)\$(BINNAME).* $(OBJDIR)\*.obj $(QUIETLY) + +librel : $(LIB_BINARY) +libdbg : $(LIB_BINARY) + +dllrel : $(DLL_BINARY) +dlldbg : $(DLL_BINARY) + diff --git a/liblfds/liblfds6.0.0/liblfds600/obj/empty_dir_placeholder_for_git b/liblfds/liblfds6.0.0/liblfds600/obj/empty_dir_placeholder_for_git new file mode 100644 index 0000000..e69de29 diff --git a/liblfds/liblfds6.0.0/liblfds600/readme.txt b/liblfds/liblfds6.0.0/liblfds600/readme.txt new file mode 100644 index 0000000..15f5ffe --- /dev/null +++ b/liblfds/liblfds6.0.0/liblfds600/readme.txt @@ -0,0 +1,136 @@ +introduction +============ +Welcome to liblfds, a portable, license-free, lock-free data structure +library written in C. + +platforms +========= +Currently liblfds out-of-the-box supports; + +Operating System CPU Toolset +================ ========== ======= +Windows 64-bit IA64 & x64 1. Microsoft Visual Studio 2008 + 2. Microsoft Windows SDK and GNUmake >= 3.8.1 + +Windows 32-bit x64 & x86 1. Microsoft Visual Studio 2008 + 2. Visual C++ 2008 Express Edition + 3. Microsoft Windows SDK and GNUmake >= 3.8.1 + +Windows Kernel IA64, x64, 1. Windows Driver Kit >= 7.0.0 + x86 + +Linux 64-bit x64 1. GCC >= 4.1.0 and GNUmake >= 3.8.1 + +Linux 32-bit x64, x86, 1. GCC >= 4.1.0 and GNUmake >= 3.8.1 + ARM + +data structures +=============== +Currently liblfds provides the following; + +* Freelist +* Queue +* Ringbuffer +* Singly linked list (logical delete only) +* Stack + +liblfds on-line +=============== +On the liblfds home page, you will find the blog, a bugzilla, a forum, a +wikipedia and the current and all historical source releases. + +The wikipedia contains comprehensive documentation for development, +building, testing and porting. + +http://www.liblfds.org + +license +======= +There is no license. You are free to use this code in any way. + +building +======== +On Windows, depending on your target platform, one of the following toolchains +is required; + + * Microsoft Visual Studio 2008 (expensive) + * Visual C++ 2008 Express Edition (free, but no 64 bit support) + * Microsoft Windows SDK (free, no GUI, has 64 bit support) and GNUmake 3.81 + +On Windows (kernel-mode), the following toolchain is required; + + * Windows Driver Kit 7.0.0 or later + +On Linux, the following toolchain is required; + + * gcc 4.1.0 or later and GNUmake 3.81 + +For documentation, see the building guide in the wikipedia. + +using +===== +Once built, there is a single header file, /inc/liblfds.h, which you must include +in your source code, and a single library file /bin/liblfds.*, where the suffix +depends on your platform and your build choice (static or dynamic), to which, +if statically built, you must link directly or, if dynamically built, you must +arrange your system such that the library can be found by the loader at run-time. + +testing +======= +The library comes with a command line test and benchmark program. This +program requires threads. As such, it is only suitable for platforms providing +thread support and which can execute a command line binary. Currently this +means the test and benchmark program works for all platforms except the Windows +Kernel. + +For documentation, see the testing and benchmarking guide in the wikipedia. + +porting +======= +Both the test program and liblfds provide an abstraction layer which acts to +mask platform differences. Porting is the act of implementing on your platform +the functions which make up the abstraction layers. You do not need to port +the test program to port liblfds, but obviously it is recommended, so you can +test your port. + +To support liblfds, your platform must support either contigious double-word +compare-and-swap (e.g. x86/x64) or contigious double-word load-link/conditional-store +where normal loads cannot occur inside the LL/CS pair (e.g. ARM) or single word +load-link/conditional-store where normal loads can occur inside the LL/CS pair. + +For documentation, see the porting guide in the wikipedia. + +release history +=============== +release 1, 25th September 2009, svn revision 1574. + - initial release + +release 2, 5th October 2009, svn revision 1599. + - added abstraction layer for Windows kernel + - minor code tidyups/fixes + +release 3, 25th October 2009, svn revision 1652. + - added singly linked list (logical delete only) + - minor code tidyups/fixes + +release 4, 7th December 2009, svn revision 1716. + - added ARM support + - added benchmarking functionality to the test program + - fixed a profound and pervasive pointer + decleration bug; earlier releases of liblfds + *should not be used* + +release 5, 19th December 2009, svn revision 1738. + - fixed subtle queue bug, which also affected ringbuffer + and caused data re-ordering under high load + - added benchmarks for freelist, ringbuffer and stack + +release 6, 29th December 2009, svn revision 1746. + - fixed two implementation errors, which reduced performance, + spotted by Codeplug from "http://cboard.cprogramming.com". + +release 6.0.0, 18th December 2012, svn revision 2537 + - introduction of namespaces, e.g. the "lfds600_" prefix + code otherwise COMPLETE AND WHOLLY UNCHANGED + this release is a stepping-stone to 6.1.0 + diff --git a/liblfds/liblfds6.0.0/liblfds600/runme_before_win_kernel_build_readme.txt b/liblfds/liblfds6.0.0/liblfds600/runme_before_win_kernel_build_readme.txt new file mode 100644 index 0000000..1481c8d --- /dev/null +++ b/liblfds/liblfds6.0.0/liblfds600/runme_before_win_kernel_build_readme.txt @@ -0,0 +1,32 @@ +The Windows kernel build environment is primitive and has a number +of severe limitations; in particular, all source files must be in +one directory and it is not possible to choose the output binary type +(static or dynamic library) from the build command line; rather, +a string has to be modified in a text file used by the build (!) + +To deal with these limitations, it is necessary for a Windows kernel +build to run a batch file prior to building. + +There are two batch files, one for static library builds and the other +for dynamic library builds. + +They are both idempotent; you can run them as often as you like and +switch between them as often as you want. It's all fine; whenever +you run one of them, it will take you from whatever state you were +previously in, into the state you want to be in. + +Both batch files copy all the sources file into a single directory, +"/src/single_dir_for_windows_kernel/". + +The static library batch file will then copy "/sources.static" into +"/src/single_dir_for_windows_kernel/", which will cause a static +library to be built. + +The dynamic library batch file will then copy "/sources.dynamic" into +"/src/single_dir_for_windows_kernel/", which will cause a dynamic +library to be built. It will also copy "src/driver_entry.c" into +"/src/single_dir_for_windows_kernel/", since the linker requires +the DriverEntry function to exist for dynamic libraries, even +though it's not used. + + diff --git a/liblfds/liblfds6.0.0/liblfds600/runme_before_win_kernel_dynamic_lib_build.bat b/liblfds/liblfds6.0.0/liblfds600/runme_before_win_kernel_dynamic_lib_build.bat new file mode 100644 index 0000000..fb0eaf7 --- /dev/null +++ b/liblfds/liblfds6.0.0/liblfds600/runme_before_win_kernel_dynamic_lib_build.bat @@ -0,0 +1,14 @@ +@echo off +rmdir /q /s src\single_dir_for_windows_kernel 1>nul 2>nul +mkdir src\single_dir_for_windows_kernel 1>nul 2>nul +copy /y src\lfds600_abstraction\* src\single_dir_for_windows_kernel 1>nul 2>nul +copy /y src\lfds600_freelist\* src\single_dir_for_windows_kernel 1>nul 2>nul +copy /y src\lfds600_queue\* src\single_dir_for_windows_kernel 1>nul 2>nul +copy /y src\lfds600_ringbuffer\* src\single_dir_for_windows_kernel 1>nul 2>nul +copy /y src\lfds600_slist\* src\single_dir_for_windows_kernel 1>nul 2>nul +copy /y src\lfds600_stack\* src\single_dir_for_windows_kernel 1>nul 2>nul +copy /y sources.dynamic src\single_dir_for_windows_kernel\sources 1>nul 2>nul +copy /y src\driver_entry.c src\single_dir_for_windows_kernel 1>nul 2>nul +echo Windows kernel dynamic library build directory structure created. +echo (Note the effects of this batch file are idempotent). + diff --git a/liblfds/liblfds6.0.0/liblfds600/runme_before_win_kernel_static_lib_build.bat b/liblfds/liblfds6.0.0/liblfds600/runme_before_win_kernel_static_lib_build.bat new file mode 100644 index 0000000..e8356fc --- /dev/null +++ b/liblfds/liblfds6.0.0/liblfds600/runme_before_win_kernel_static_lib_build.bat @@ -0,0 +1,14 @@ +@echo off +rmdir /q /s src\single_dir_for_windows_kernel 1>nul 2>nul +mkdir src\single_dir_for_windows_kernel 1>nul 2>nul +copy /y src\lfds600_abstraction\* src\single_dir_for_windows_kernel 1>nul 2>nul +copy /y src\lfds600_freelist\* src\single_dir_for_windows_kernel 1>nul 2>nul +copy /y src\lfds600_queue\* src\single_dir_for_windows_kernel 1>nul 2>nul +copy /y src\lfds600_ringbuffer\* src\single_dir_for_windows_kernel 1>nul 2>nul +copy /y src\lfds600_slist\* src\single_dir_for_windows_kernel 1>nul 2>nul +copy /y src\lfds600_stack\* src\single_dir_for_windows_kernel 1>nul 2>nul +copy /y sources.static src\single_dir_for_windows_kernel\sources 1>nul 2>nul +erase /f src\single_dir_for_windows_kernel\driver_entry.c 1>nul 2>nul +echo Windows kernel static library build directory structure created. +echo (Note the effects of this batch file are idempotent). + diff --git a/liblfds/liblfds6.0.0/liblfds600/sources.dynamic b/liblfds/liblfds6.0.0/liblfds600/sources.dynamic new file mode 100644 index 0000000..1f570c4 --- /dev/null +++ b/liblfds/liblfds6.0.0/liblfds600/sources.dynamic @@ -0,0 +1,37 @@ +MSC_WARNING_LEVEL = /WX /W4 +DLLDEF = ../../liblfds600.def +TARGETNAME = liblfds600 +TARGETPATH = ../../bin/ +TARGETTYPE = EXPORT_DRIVER +UMTYPE = nt +USER_C_FLAGS = /DWIN_KERNEL_BUILD + +INCLUDES = ..;../../inc/ +SOURCES = lfds600_abstraction_aligned_free.c \ + lfds600_abstraction_aligned_malloc.c \ + lfds600_abstraction_cas.c \ + lfds600_abstraction_dcas.c \ + lfds600_abstraction_increment.c \ + lfds600_freelist_delete.c \ + lfds600_freelist_get_and_set.c \ + lfds600_freelist_new.c \ + lfds600_freelist_pop_push.c \ + lfds600_freelist_query.c \ + lfds600_queue_delete.c \ + lfds600_queue_new.c \ + lfds600_queue_query.c \ + lfds600_queue_queue.c \ + lfds600_ringbuffer_delete.c \ + lfds600_ringbuffer_get_and_put.c \ + lfds600_ringbuffer_new.c \ + lfds600_ringbuffer_query.c \ + lfds600_slist_delete.c \ + lfds600_slist_get_and_set.c \ + lfds600_slist_link.c \ + lfds600_slist_new.c \ + lfds600_stack_delete.c \ + lfds600_stack_new.c \ + lfds600_stack_push_pop.c \ + lfds600_stack_query.c \ + driver_entry.c + diff --git a/liblfds/liblfds6.0.0/liblfds600/sources.static b/liblfds/liblfds6.0.0/liblfds600/sources.static new file mode 100644 index 0000000..dff7cfe --- /dev/null +++ b/liblfds/liblfds6.0.0/liblfds600/sources.static @@ -0,0 +1,35 @@ +MSC_WARNING_LEVEL = /WX /W4 +TARGETNAME = liblfds600 +TARGETPATH = ../../bin/ +TARGETTYPE = DRIVER_LIBRARY +UMTYPE = nt +USER_C_FLAGS = /DWIN_KERNEL_BUILD + +INCLUDES = ..;../../inc/ +SOURCES = lfds600_abstraction_aligned_free.c \ + lfds600_abstraction_aligned_malloc.c \ + lfds600_abstraction_cas.c \ + lfds600_abstraction_dcas.c \ + lfds600_abstraction_increment.c \ + lfds600_freelist_delete.c \ + lfds600_freelist_get_and_set.c \ + lfds600_freelist_new.c \ + lfds600_freelist_pop_push.c \ + lfds600_freelist_query.c \ + lfds600_queue_delete.c \ + lfds600_queue_new.c \ + lfds600_queue_query.c \ + lfds600_queue_queue.c \ + lfds600_ringbuffer_delete.c \ + lfds600_ringbuffer_get_and_put.c \ + lfds600_ringbuffer_new.c \ + lfds600_ringbuffer_query.c \ + lfds600_slist_delete.c \ + lfds600_slist_get_and_set.c \ + lfds600_slist_link.c \ + lfds600_slist_new.c \ + lfds600_stack_delete.c \ + lfds600_stack_new.c \ + lfds600_stack_push_pop.c \ + lfds600_stack_query.c + diff --git a/liblfds/liblfds6.0.0/liblfds600/src/dirs b/liblfds/liblfds6.0.0/liblfds600/src/dirs new file mode 100644 index 0000000..64e002c --- /dev/null +++ b/liblfds/liblfds6.0.0/liblfds600/src/dirs @@ -0,0 +1,3 @@ +DIRS = single_dir_for_windows_kernel + + diff --git a/liblfds/liblfds6.0.0/liblfds600/src/driver_entry.c b/liblfds/liblfds6.0.0/liblfds600/src/driver_entry.c new file mode 100644 index 0000000..07da76c --- /dev/null +++ b/liblfds/liblfds6.0.0/liblfds600/src/driver_entry.c @@ -0,0 +1,16 @@ +#include "lfds600_stack_internal.h" + + + + + +/****************************************************************************/ +#pragma warning( disable : 4100 ) + +NTSTATUS DriverEntry( struct _DRIVER_OBJECT *DriverObject, PUNICODE_STRING RegistryPath ) +{ + return( STATUS_SUCCESS ); +} + +#pragma warning( default : 4100 ) + diff --git a/liblfds/liblfds6.0.0/liblfds600/src/driver_entry_readme.txt b/liblfds/liblfds6.0.0/liblfds600/src/driver_entry_readme.txt new file mode 100644 index 0000000..bff054b --- /dev/null +++ b/liblfds/liblfds6.0.0/liblfds600/src/driver_entry_readme.txt @@ -0,0 +1,4 @@ +This C file (driver_entry.c) is used when building a dynamic library for +the Windows kernel. It exists to work around one of the limitations of +that build environment. It is not used by any other build; just ignore it. + diff --git a/liblfds/liblfds6.0.0/liblfds600/src/lfds600_abstraction/lfds600_abstraction_aligned_free.c b/liblfds/liblfds6.0.0/liblfds600/src/lfds600_abstraction/lfds600_abstraction_aligned_free.c new file mode 100644 index 0000000..fcc4b7c --- /dev/null +++ b/liblfds/liblfds6.0.0/liblfds600/src/lfds600_abstraction/lfds600_abstraction_aligned_free.c @@ -0,0 +1,72 @@ +#include "lfds600_abstraction_internal.h" + + + + + +/****************************************************************************/ +#if (defined _WIN32 && defined _MSC_VER && !defined WIN_KERNEL_BUILD) + + /* TRD : any Windows (user-mode) on any CPU with the Microsoft C compiler + + _WIN32 indicates 64-bit or 32-bit Windows + _MSC_VER indicates Microsoft C compiler + !WIN_KERNEL_BUILD indicates Windows user-mode + */ + + void lfds600_abstraction_aligned_free( void *memory ) + { + _aligned_free( memory ); + + return; + } + +#endif + + + + + +/****************************************************************************/ +#if (_XOPEN_SOURCE >= 600) + + /* TRD : any OS on any CPU with any compiler with POSIX 6.00 or better + + _XOPEN_SOURCE is actually set by the user, not by the compiler + it is the way the user signals to the compiler what + level of POSIX should be available + (it assumes of course the compiler has support for the given level of POSIX requested) + */ + + void lfds600_abstraction_aligned_free( void *memory ) + { + free( memory ); + + return; + } + +#endif + + + + + +/****************************************************************************/ +#if (defined _WIN32 && defined _MSC_VER && defined WIN_KERNEL_BUILD) + + /* TRD : any Windows (kernel) on any CPU with the Microsoft C compiler + + _WIN32 indicates 64-bit or 32-bit Windows + _MSC_VER indicates Microsoft C compiler + WIN_KERNEL_BUILD indicates Windows kernel + */ + + void lfds600_abstraction_aligned_free( void *memory ) + { + ExFreePoolWithTag( memory, 'sdfl' ); + + return; + } + +#endif + diff --git a/liblfds/liblfds6.0.0/liblfds600/src/lfds600_abstraction/lfds600_abstraction_aligned_malloc.c b/liblfds/liblfds6.0.0/liblfds600/src/lfds600_abstraction/lfds600_abstraction_aligned_malloc.c new file mode 100644 index 0000000..c09ccc5 --- /dev/null +++ b/liblfds/liblfds6.0.0/liblfds600/src/lfds600_abstraction/lfds600_abstraction_aligned_malloc.c @@ -0,0 +1,97 @@ +#include "lfds600_abstraction_internal.h" + + + + + +/****************************************************************************/ +#if (defined _WIN32 && defined _MSC_VER && !defined WIN_KERNEL_BUILD) + + /* TRD : any Windows (user-mode) on any CPU with the Microsoft C compiler + + _WIN32 indicates 64-bit or 32-bit Windows + _MSC_VER indicates Microsoft C compiler + !WIN_KERNEL_BUILD indicates Windows user-mode + */ + + void *lfds600_abstraction_aligned_malloc( size_t size, size_t align_in_bytes ) + { + void + *rv; + + rv = _aligned_malloc( size, align_in_bytes ); + + return( rv ); + } + +#endif + + + + + +/****************************************************************************/ +#if (_XOPEN_SOURCE >= 600) + + /* TRD : any OS on any CPU with any compiler with POSIX 6.00 or better + + _XOPEN_SOURCE is actually set by the user, not by the compiler + it is the way the user signals to the compiler what + level of POSIX should be available + (it assumes of course the compiler has support for the given level of POSIX requested) + */ + + void *lfds600_abstraction_aligned_malloc( size_t size, size_t align_in_bytes ) + { + int + rv; + + void + *memory; + + rv = posix_memalign( &memory, align_in_bytes, size ); + + // TRD : posix_memalign returns 0 on success, docs do not say *memory == NULL on fail + if( rv != 0 ) + memory = NULL; + + return( memory ); + } + +#endif + + + + + +/****************************************************************************/ +#if (defined _WIN32 && defined _MSC_VER && defined WIN_KERNEL_BUILD) + + /* TRD : any Windows (kernel) on any CPU with the Microsoft C compiler + + _WIN32 indicates 64-bit or 32-bit Windows + _MSC_VER indicates Microsoft C compiler + WIN_KERNEL_BUILD indicates Windows kernel + */ + + void *lfds600_abstraction_aligned_malloc( size_t size, size_t align_in_bytes ) + { + void + *rv; + + /* TRD : ExAllocatePoolWithTag() allocates memory aligned on 8 bytes on 32-bit CPUs + and on 16 bytes on 64-bit CPUs, which is what we want + + as such, align_in_bytes is not needed; we must refer to it to avoid the + compiler warning + */ + + align_in_bytes; + + rv = ExAllocatePoolWithTag( NonPagedPool, size, 'sdfl' ); + + return( rv ); + } + +#endif + diff --git a/liblfds/liblfds6.0.0/liblfds600/src/lfds600_abstraction/lfds600_abstraction_cas.c b/liblfds/liblfds6.0.0/liblfds600/src/lfds600_abstraction/lfds600_abstraction_cas.c new file mode 100644 index 0000000..4bf295a --- /dev/null +++ b/liblfds/liblfds6.0.0/liblfds600/src/lfds600_abstraction/lfds600_abstraction_cas.c @@ -0,0 +1,109 @@ +#include "lfds600_abstraction_internal.h" + + + + + +/****************************************************************************/ +#if (defined _WIN32 && defined _MSC_VER) + + /* TRD : 64 bit and 32 bit Windows (user-mode or kernel) on any CPU with the Microsoft C compiler + + _WIN32 indicates 64-bit or 32-bit Windows + _MSC_VER indicates Microsoft C compiler + */ + + LFDS600_INLINE lfds600_atom_t lfds600_abstraction_cas( volatile lfds600_atom_t *destination, lfds600_atom_t exchange, lfds600_atom_t compare ) + { + assert( destination != NULL ); + // TRD : exchange can be any value in its range + // TRD : compare can be any value in its range + + return( (lfds600_atom_t) _InterlockedCompareExchangePointer((void * volatile *) destination, (void *) exchange, (void *) compare) ); + } + +#endif + + + + + +/****************************************************************************/ +#if (!defined __arm__ && __GNUC__ >= 4 && __GNUC_MINOR__ >= 1 && __GNUC_PATCHLEVEL__ >= 0) + + /* TRD : any OS on any CPU except ARM with GCC 4.1.0 or better + + GCC 4.1.0 introduced the __sync_*() atomic intrinsics + + __GNUC__ / __GNUC_MINOR__ / __GNUC_PATCHLEVEL__ indicates GCC and which version + */ + + LFDS600_INLINE lfds600_atom_t lfds600_abstraction_cas( volatile lfds600_atom_t *destination, lfds600_atom_t exchange, lfds600_atom_t compare ) + { + assert( destination != NULL ); + // TRD : exchange can be any value in its range + // TRD : compare can be any value in its range + + // TRD : note the different argument order for the GCC instrinsic to the MSVC instrinsic + + return( (lfds600_atom_t) __sync_val_compare_and_swap(destination, compare, exchange) ); + } + +#endif + + + + + +/****************************************************************************/ +#if (defined __arm__ && __GNUC__) + + /* TRD : any OS on any ARM with GCC + + Remember however we need to set into compare the original value of destination. + + __arm__ indicates ARM + __GNUC__ indicates GCC + */ + + LFDS600_INLINE lfds600_atom_t lfds600_abstraction_cas( volatile lfds600_atom_t *destination, lfds600_atom_t exchange, lfds600_atom_t compare ) + { + lfds600_atom_t + stored_flag, + original_destination; + + assert( destination != NULL ); + // TRD : exchange can be any value in its range + // TRD : compare can be any value in its range + + /* TRD : this is a standard, plain CAS, vulnerable to ABA */ + + __asm__ __volatile__ + ( + " mov %[stored_flag], #1;" // put 1 into stored_flag + " mcr p15, 0, %[zero], c7, c10, 5;" // memory barrier (ARM v6 compatible) + "atomic_cas:;" + " ldrex %[original_destination], [%[destination]];" // load *destination into original_destination + " teq %[original_destination], %[compare];" // compare original_destination with compare + " bne exit;" // if not equal, exit + " strex %[stored_flag], %[exchange], [%[destination]];" // if equal, try to store exchange into *destination (on success, strex puts 0 into stored_flag) + " teq %[stored_flag], #0;" // check if stored_flag is 0 + " bne atomic_cas;" // if not 0, retry (someone else touched *destination after we loaded but before we stored) + " mcr p15, 0, %[zero], c7, c10, 5;" // memory barrier (ARM v6 compatible) + "exit:;" + + // output + : "+m" (*destination), [original_destination] "=&r" (original_destination), [stored_flag] "=&r" (stored_flag) + + // input + : [destination] "r" (destination), [compare] "r" (compare), [exchange] "r" (exchange), [zero] "r" (0) + + // clobbered + : "cc", "memory" // memory is clobbered because we issue a memory barrier + ); + + return( original_destination ); + } + +#endif + diff --git a/liblfds/liblfds6.0.0/liblfds600/src/lfds600_abstraction/lfds600_abstraction_dcas.c b/liblfds/liblfds6.0.0/liblfds600/src/lfds600_abstraction/lfds600_abstraction_dcas.c new file mode 100644 index 0000000..14108ce --- /dev/null +++ b/liblfds/liblfds6.0.0/liblfds600/src/lfds600_abstraction/lfds600_abstraction_dcas.c @@ -0,0 +1,356 @@ +#include "lfds600_abstraction_internal.h" + + + + + +/****************************************************************************/ +#if (defined _WIN64 && defined _MSC_VER) + + /* TRD : 64 bit Windows (user-mode or kernel) on any CPU with the Microsoft C compiler + + _WIN64 indicates 64 bit Windows + _MSC_VER indicates Microsoft C compiler + */ + + LFDS600_INLINE unsigned char lfds600_abstraction_dcas( volatile lfds600_atom_t *destination, lfds600_atom_t *exchange, lfds600_atom_t *compare ) + { + unsigned char + cas_result; + + assert( destination != NULL ); + assert( exchange != NULL ); + assert( compare != NULL ); + + cas_result = _InterlockedCompareExchange128( (volatile __int64 *) destination, (__int64) *(exchange+1), (__int64) *exchange, (__int64 *) compare ); + + return( cas_result ); + } + +#endif + + + + + +/****************************************************************************/ +#if (!defined _WIN64 && defined _WIN32 && defined _MSC_VER) + + /* TRD : 32 bit Windows (user-mode or kernel) on any CPU with the Microsoft C compiler + + (!defined _WIN64 && defined _WIN32) indicates 32 bit Windows + _MSC_VER indicates Microsoft C compiler + */ + + LFDS600_INLINE unsigned char lfds600_abstraction_dcas( volatile lfds600_atom_t *destination, lfds600_atom_t *exchange, lfds600_atom_t *compare ) + { + __int64 + original_compare; + + assert( destination != NULL ); + assert( exchange != NULL ); + assert( compare != NULL ); + + *(__int64 *) &original_compare = *(__int64 *) compare; + + *(__int64 *) compare = _InterlockedCompareExchange64( (volatile __int64 *) destination, *(__int64 *) exchange, *(__int64 *) compare ); + + return( (unsigned char) (*(__int64 *) compare == *(__int64 *) &original_compare) ); + } + +#endif + + + + + +/****************************************************************************/ +#if (defined __x86_64__ && __GNUC__ && !defined __pic__) + + /* TRD : any OS on x64 with GCC for statically linked code + + __x86_64__ indicates x64 + __GNUC__ indicates GCC + */ + + LFDS600_INLINE unsigned char lfds600_abstraction_dcas( volatile lfds600_atom_t *destination, lfds600_atom_t *exchange, lfds600_atom_t *compare ) + { + unsigned char + cas_result; + + assert( destination != NULL ); + assert( exchange != NULL ); + assert( compare != NULL ); + + __asm__ __volatile__ + ( + "lock;" // make cmpxchg16b atomic + "cmpxchg16b %0;" // cmpxchg16b sets ZF on success + "setz %3;" // if ZF set, set cas_result to 1 + + // output + : "+m" (*(volatile lfds600_atom_t (*)[2]) destination), "+a" (*compare), "+d" (*(compare+1)), "=q" (cas_result) + + // input + : "b" (*exchange), "c" (*(exchange+1)) + + // clobbered + : "cc", "memory" + ); + + return( cas_result ); + } + +#endif + + + + + + +/****************************************************************************/ +#if (defined __i686__ && __GNUC__ && !defined __pic__) + + /* TRD : any OS on x86 with GCC for statically linked code + + __i686__ indicates x86 + __GNUC__ indicates GCC + */ + + LFDS600_INLINE unsigned char lfds600_abstraction_dcas( volatile lfds600_atom_t *destination, lfds600_atom_t *exchange, lfds600_atom_t *compare ) + { + unsigned char + cas_result; + + assert( destination != NULL ); + assert( exchange != NULL ); + assert( compare != NULL ); + + __asm__ __volatile__ + ( + "lock;" // make cmpxchg8b atomic + "cmpxchg8b %0;" // cmpxchg8b sets ZF on success + "setz %3;" // if ZF set, set cas_result to 1 + + // output + : "+m" (*(volatile lfds600_atom_t (*)[2]) destination), "+a" (*compare), "+d" (*(compare+1)), "=q" (cas_result) + + // input + : "b" (*exchange), "c" (*(exchange+1)) + + // clobbered + : "cc", "memory" + ); + + return( cas_result ); + } + +#endif + + + + + +/****************************************************************************/ +#if (defined __x86_64__ && __GNUC__ && defined __pic__) + + /* TRD : any OS on x64 with GCC for position independent code (e.g. a shared object) + + __x86_64__ indicates x64 + __GNUC__ indicates GCC + */ + + LFDS600_INLINE unsigned char lfds600_abstraction_dcas( volatile lfds600_atom_t *destination, lfds600_atom_t *exchange, lfds600_atom_t *compare ) + { + unsigned char + cas_result; + + assert( destination != NULL ); + assert( exchange != NULL ); + assert( compare != NULL ); + + /* TRD : with a shared object, we cannot clobber RBX + as such, we borrow RSI - we load half of the exchange value into it + then swap it with RBX + then do the compare-and-swap + then swap the original value of RBX back from RSI + */ + + __asm__ __volatile__ + ( + "xchg %%rsi, %%rbx;" // swap RBI and RBX + "lock;" // make cmpxchg16b atomic + "cmpxchg16b %0;" // cmpxchg16b sets ZF on success + "setz %3;" // if ZF set, set cas_result to 1 + "xchg %%rbx, %%rsi;" // re-swap RBI and RBX + + // output + : "+m" (*(volatile lfds600_atom_t (*)[2]) destination), "+a" (*compare), "+d" (*(compare+1)), "=q" (cas_result) + + // input + : "S" (*exchange), "c" (*(exchange+1)) + + // clobbered + : "cc", "memory" + ); + + return( cas_result ); + } + +#endif + + + + + + +/****************************************************************************/ +#if (defined __i686__ && __GNUC__ && defined __pic__) + + /* TRD : any OS on x86 with GCC for position independent code (e.g. a shared object) + + __i686__ indicates x86 + __GNUC__ indicates GCC + */ + + LFDS600_INLINE unsigned char lfds600_abstraction_dcas( volatile lfds600_atom_t *destination, lfds600_atom_t *exchange, lfds600_atom_t *compare ) + { + unsigned char + cas_result; + + assert( destination != NULL ); + assert( exchange != NULL ); + assert( compare != NULL ); + + /* TRD : with a shared object, we cannot clobber EBX + as such, we borrow ESI - we load half of the exchange value into it + then swap it with EBX + then do the compare-and-swap + then swap the original value of EBX back from ESI + */ + + __asm__ __volatile__ + ( + "xchg %%esi, %%ebx;" // swap EBI and EBX + "lock;" // make cmpxchg8b atomic + "cmpxchg8b %0;" // cmpxchg8b sets ZF on success + "setz %3;" // if ZF set, set cas_result to 1 + "xchg %%ebx, %%esi;" // re-swap EBI and EBX + + // output + : "+m" (*(volatile lfds600_atom_t (*)[2]) destination), "+a" (*compare), "+d" (*(compare+1)), "=q" (cas_result) + + // input + : "S" (*exchange), "c" (*(exchange+1)) + + // clobbered + : "cc", "memory" + ); + + return( cas_result ); + } + +#endif + + + + + +/****************************************************************************/ +#if (defined __arm__ && __GNUC__) + + /* TRD : any OS on any ARM with GCC + + Remember however we need to set into compare the original value of destination. + + __arm__ indicates ARM + __GNUC__ indicates GCC + */ + + LFDS600_INLINE unsigned char lfds600_abstraction_dcas( volatile lfds600_atom_t *destination, lfds600_atom_t *exchange, lfds600_atom_t *compare ) + { + lfds600_atom_t + *local_compare = compare, + stored_flag = 1; + + register lfds600_atom_t + local_exchange_a __asm("r2"), + local_exchange_b __asm("r3"), + local_compare_a __asm("r4"), + local_compare_b __asm("r5"), + original_destination_a __asm("r6"), + original_destination_b __asm("r7"); + + assert( destination != NULL ); + assert( exchange != NULL ); + assert( compare != NULL ); + + /* TRD : some notes + + the double word ldr and str instructions require contigous registers + where the first register is an even number + + honouring this requirement requires us to specifically specify + the registers to use (which is why we're using register __asm("rN") + in the declerations above + + the arguments to the function occupy registers r0, r1 and r2 + + we can use up to and including r8, but r9 can have a frame pointer in it + + so we make a copy of compare (freeing up r2, so we can use it for a double + word load) but use destination (r0) and exchange (r1) directly + + note LDRD and STRD became available in armv6k + + apologies for the trickery with the mcr register variable - the code runs + out of registers on armv6k + */ + + __asm__ __volatile__ + ( + " mov %[stored_flag], #1;" // put 1 into stored_flag + " mov %[local_exchange_a], #0;" // borrow local_exchange_a for mcr, to save a register + " mcr p15, 0, %[local_exchange_a], c7, c10, 5;" // memory barrier (ARM v6 compatible) + " ldrd %[local_exchange_a], %[local_exchange_b], [%[exchange]];" // load exchange into local_exchange_a and local_exchange_b (which are r2 and r3, respectively) + " ldrd %[local_compare_a], %[local_compare_b], [%[local_compare]];" // load compare into local_compare_a and local_compare_b (which are r4 and r5, respectively) + "atomic_dcas:;" + " ldrexd %[original_destination_a], %[original_destination_b], [%[destination]];" // load destination into original_destination_a and original_destination_b (which are r6 and r7, respectively) + " teq %[original_destination_a], %[local_compare_a];" // compare the first word of destination with the first word of compare + " teqeq %[original_destination_b], %[local_compare_b];" // if they're equal, compare the second word of destination with the second word of compare + " bne exit;" // if either word of destination does not match its respective word of compare, exit + " strexd %[stored_flag], %[local_exchange_a], %[local_exchange_b], [%[destination]];" // if both words were equal, try to store local_exchange_a and local_exchange_b into *destination (on success, strexed puts 0 into stored_flag) + " teq %[stored_flag], #0;" // check if stored_flag is 0 + " bne atomic_dcas;" // if not 0, retry (someone else touched *destination after we loaded but before we stored) + "exit:;" + " strd %[original_destination_a], %[original_destination_b], [%[local_compare]];" // whether or not the CAS swapped, we always write the original value of destination into *compare + " mov %[local_exchange_a], #0;" // borrow local_exchange_a for mcr, to save a register + " mcr p15, 0, %[local_exchange_a], c7, c10, 5;" // memory barrier (ARM v6 compatible) + + // output + : "+m" (*(volatile lfds600_atom_t (*)[2]) destination), "+m" (*(lfds600_atom_t (*)[2]) local_compare), + [stored_flag] "+&r" (stored_flag), + [original_destination_a] "+&r" (original_destination_a), [original_destination_b] "+&r" (original_destination_b), + [local_compare_a] "+&r" (local_compare_a), [local_compare_b] "+&r" (local_compare_b), + [local_exchange_a] "+&r" (local_exchange_a), [local_exchange_b] "+&r" (local_exchange_b) + + // input + : "m" (*(lfds600_atom_t (*)[2]) exchange), + [destination] "r" (destination), + [local_compare] "r" (local_compare), + [exchange] "r" (exchange) + + // clobbered + : "cc", "memory" // memory is clobbered because we issue a memory barrier + ); + + /* TRD : stored_flag is set to 0 on store, 1 on fail + we need to return 1 on success, 0 on fail + */ + + return( (unsigned char) !stored_flag ); + } + +#endif + + diff --git a/liblfds/liblfds6.0.0/liblfds600/src/lfds600_abstraction/lfds600_abstraction_increment.c b/liblfds/liblfds6.0.0/liblfds600/src/lfds600_abstraction/lfds600_abstraction_increment.c new file mode 100644 index 0000000..fc1d66c --- /dev/null +++ b/liblfds/liblfds6.0.0/liblfds600/src/lfds600_abstraction/lfds600_abstraction_increment.c @@ -0,0 +1,136 @@ +#include "lfds600_abstraction_internal.h" + + + + + +/****************************************************************************/ +#if (defined _WIN64 && defined _MSC_VER) + + /* TRD : 64 bit Windows (user-mode or kernel) on any CPU with the Microsoft C compiler + + _WIN64 indicates 64 bit Windows + _MSC_VER indicates Microsoft C compiler + */ + + LFDS600_INLINE lfds600_atom_t lfds600_abstraction_increment( lfds600_atom_t *value ) + { + __int64 + rv; + + assert( value != NULL ); + + rv = _InterlockedIncrement64( (__int64 *) value ); + + return( (lfds600_atom_t) rv ); + } + +#endif + + + + + +/****************************************************************************/ +#if (!defined _WIN64 && defined _WIN32 && defined _MSC_VER) + + /* TRD : 32 bit Windows (user-mode or kernel) on any CPU with the Microsoft C compiler + + (!defined _WIN64 && defined _WIN32) indicates 32 bit Windows + _MSC_VER indicates Microsoft C compiler + */ + + LFDS600_INLINE lfds600_atom_t lfds600_abstraction_increment( lfds600_atom_t *value ) + { + long int + rv; + + assert( value != NULL ); + + rv = _InterlockedIncrement( (long int *) value ); + + return( (lfds600_atom_t) rv ); + } + +#endif + + + + + +/****************************************************************************/ +#if (!defined __arm__ && __GNUC__ >= 4 && __GNUC_MINOR__ >= 1 && __GNUC_PATCHLEVEL__ >= 0) + + /* TRD : any OS on any CPU with GCC 4.1.0 or better + + GCC 4.1.0 introduced the __sync_*() atomic intrinsics + + __GNUC__ / __GNUC_MINOR__ / __GNUC_PATCHLEVEL__ indicates GCC and which version + */ + + LFDS600_INLINE lfds600_atom_t lfds600_abstraction_increment( lfds600_atom_t *value ) + { + lfds600_atom_t + rv; + + assert( value != NULL ); + + // TRD : no need for casting here, GCC has a __sync_add_and_fetch() for all native types + + rv = __sync_add_and_fetch( value, 1 ); + + return( rv ); + } + +#endif + + + + + +/****************************************************************************/ +#if (defined __arm__ && __GNUC__ >= 4) + + /* TRD : any OS on any CPU with GCC 4.1.0 or better + + GCC 4.1.0 introduced the __sync_*() atomic intrinsics + + __arm__ indicates ARM + __GNUC__ indicates GCC + */ + + LFDS600_INLINE lfds600_atom_t lfds600_abstraction_increment( lfds600_atom_t *value ) + { + lfds600_atom_t + stored_flag = 0, + new_value = 0; + + assert( value != NULL ); + + __asm__ __volatile__ + ( + " mov %[stored_flag], #1;" // move 1 into stored_flag + " mcr p15, 0, %[zero], c7, c10, 5;" // memory barrier (ARM v6 compatible) + "atomic_add:;" + " ldrex %[new_value], [%[value]]; " // load *value into new_value + " add %[new_value], #1;" // add 1 to new_value + " strex %[stored_flag], %[new_value], [%[value]];" // try to store new_value into *value (on success, strex puts 0 into stored_flag) + " teq %[stored_flag], #0;" // check if stored_flag is 0 + " bne atomic_add;" // if not 0, retry (someone else touched *value after we loaded but before we stored) + " mcr p15, 0, %[zero], c7, c10, 5;" // memory barrier (ARM v6 compatible) + + // output + : "+m" (*value), [new_value] "+&r" (new_value), [stored_flag] "+&r" (stored_flag) + + // input + : [value] "r" (value), [zero] "r" (0) + + // clobbered + : "cc", "memory" // memory is clobbered because we issue a memory barrier + ); + + return( new_value ); + } + +#endif + diff --git a/liblfds/liblfds6.0.0/liblfds600/src/lfds600_abstraction/lfds600_abstraction_internal.h b/liblfds/liblfds6.0.0/liblfds600/src/lfds600_abstraction/lfds600_abstraction_internal.h new file mode 100644 index 0000000..d479a2f --- /dev/null +++ b/liblfds/liblfds6.0.0/liblfds600/src/lfds600_abstraction/lfds600_abstraction_internal.h @@ -0,0 +1,5 @@ +/***** the library wide include file *****/ +#include "lfds600_internal.h" + +/***** private prototypes *****/ + diff --git a/liblfds/liblfds6.0.0/liblfds600/src/lfds600_freelist/lfds600_freelist_delete.c b/liblfds/liblfds6.0.0/liblfds600/src/lfds600_freelist/lfds600_freelist_delete.c new file mode 100644 index 0000000..36337c8 --- /dev/null +++ b/liblfds/liblfds6.0.0/liblfds600/src/lfds600_freelist/lfds600_freelist_delete.c @@ -0,0 +1,35 @@ +#include "lfds600_freelist_internal.h" + + + + + +/****************************************************************************/ +void lfds600_freelist_delete( struct lfds600_freelist_state *fs, void (*user_data_delete_function)(void *user_data, void *user_state), void *user_state ) +{ + struct lfds600_freelist_element + *fe; + + void + *user_data; + + assert( fs != NULL ); + // TRD : user_data_delete_function can be NULL + // TRD : user_state can be NULL + + while( lfds600_freelist_pop(fs, &fe) ) + { + if( user_data_delete_function != NULL ) + { + lfds600_freelist_get_user_data_from_element( fe, &user_data ); + user_data_delete_function( user_data, user_state ); + } + + lfds600_abstraction_aligned_free( fe ); + } + + lfds600_abstraction_aligned_free( fs ); + + return; +} + diff --git a/liblfds/liblfds6.0.0/liblfds600/src/lfds600_freelist/lfds600_freelist_get_and_set.c b/liblfds/liblfds6.0.0/liblfds600/src/lfds600_freelist/lfds600_freelist_get_and_set.c new file mode 100644 index 0000000..f408213 --- /dev/null +++ b/liblfds/liblfds6.0.0/liblfds600/src/lfds600_freelist/lfds600_freelist_get_and_set.c @@ -0,0 +1,33 @@ +#include "lfds600_freelist_internal.h" + + + + + +/****************************************************************************/ +void *lfds600_freelist_get_user_data_from_element( struct lfds600_freelist_element *fe, void **user_data ) +{ + assert( fe != NULL ); + // TRD : user_data can be NULL + + if( user_data != NULL ) + *user_data = fe->user_data; + + return( fe->user_data ); +} + + + + + +/****************************************************************************/ +void lfds600_freelist_set_user_data_in_element( struct lfds600_freelist_element *fe, void *user_data ) +{ + assert( fe != NULL ); + // TRD : user_data can be NULL + + fe->user_data = user_data; + + return; +} + diff --git a/liblfds/liblfds6.0.0/liblfds600/src/lfds600_freelist/lfds600_freelist_internal.h b/liblfds/liblfds6.0.0/liblfds600/src/lfds600_freelist/lfds600_freelist_internal.h new file mode 100644 index 0000000..1e7d07d --- /dev/null +++ b/liblfds/liblfds6.0.0/liblfds600/src/lfds600_freelist/lfds600_freelist_internal.h @@ -0,0 +1,42 @@ +/***** the library wide include file *****/ +#include "lfds600_internal.h" + +/***** defines *****/ +#define LFDS600_FREELIST_POINTER 0 +#define LFDS600_FREELIST_COUNTER 1 +#define LFDS600_FREELIST_PAC_SIZE 2 + +/***** structures *****/ +#pragma pack( push, LFDS600_ALIGN_DOUBLE_POINTER ) + +struct lfds600_freelist_state +{ + struct lfds600_freelist_element + *volatile top[LFDS600_FREELIST_PAC_SIZE]; + + int + (*user_data_init_function)( void **user_data, void *user_state ); + + void + *user_state; + + lfds600_atom_t + aba_counter, + element_count; +}; + +struct lfds600_freelist_element +{ + struct lfds600_freelist_element + *next[LFDS600_FREELIST_PAC_SIZE]; + + void + *user_data; +}; + +#pragma pack( pop ) + +/***** private prototypes *****/ +lfds600_atom_t lfds600_freelist_internal_new_element( struct lfds600_freelist_state *fs, struct lfds600_freelist_element **fe ); +void lfds600_freelist_internal_validate( struct lfds600_freelist_state *fs, struct lfds600_validation_info *vi, enum data_structure_validity *lfds600_freelist_validity ); + diff --git a/liblfds/liblfds6.0.0/liblfds600/src/lfds600_freelist/lfds600_freelist_new.c b/liblfds/liblfds6.0.0/liblfds600/src/lfds600_freelist/lfds600_freelist_new.c new file mode 100644 index 0000000..b2b6085 --- /dev/null +++ b/liblfds/liblfds6.0.0/liblfds600/src/lfds600_freelist/lfds600_freelist_new.c @@ -0,0 +1,123 @@ +#include "lfds600_freelist_internal.h" + + + + + +/****************************************************************************/ +int lfds600_freelist_new( struct lfds600_freelist_state **fs, lfds600_atom_t number_elements, int (*user_data_init_function)(void **user_data, void *user_state), void *user_state ) +{ + int + rv = 0; + + lfds600_atom_t + element_count; + + assert( fs != NULL ); + // TRD : number_elements can be any value in its range + // TRD : user_data_init_function can be NULL + + *fs = (struct lfds600_freelist_state *) lfds600_abstraction_aligned_malloc( sizeof(struct lfds600_freelist_state), LFDS600_ALIGN_DOUBLE_POINTER ); + + if( (*fs) != NULL ) + { + (*fs)->top[LFDS600_FREELIST_POINTER] = NULL; + (*fs)->top[LFDS600_FREELIST_COUNTER] = 0; + (*fs)->user_data_init_function = user_data_init_function; + (*fs)->user_state = user_state; + (*fs)->aba_counter = 0; + (*fs)->element_count = 0; + + element_count = lfds600_freelist_new_elements( *fs, number_elements ); + + if( element_count == number_elements ) + rv = 1; + + if( element_count != number_elements ) + { + lfds600_abstraction_aligned_free( (*fs) ); + *fs = NULL; + } + } + + return( rv ); +} + + + + + +/****************************************************************************/ +lfds600_atom_t lfds600_freelist_new_elements( struct lfds600_freelist_state *fs, lfds600_atom_t number_elements ) +{ + struct lfds600_freelist_element + *fe; + + lfds600_atom_t + loop, + count = 0; + + assert( fs != NULL ); + // TRD : number_elements can be any value in its range + // TRD : user_data_init_function can be NULL + + for( loop = 0 ; loop < number_elements ; loop++ ) + if( lfds600_freelist_internal_new_element(fs, &fe) ) + { + lfds600_freelist_push( fs, fe ); + count++; + } + + return( count ); +} + + + + + +/****************************************************************************/ +lfds600_atom_t lfds600_freelist_internal_new_element( struct lfds600_freelist_state *fs, struct lfds600_freelist_element **fe ) +{ + lfds600_atom_t + rv = 0; + + assert( fs != NULL ); + assert( fe != NULL ); + + /* TRD : basically, does what you'd expect; + + allocates an element + calls the user init function + if anything fails, cleans up, + sets *fe to NULL + and returns 0 + */ + + *fe = (struct lfds600_freelist_element *) lfds600_abstraction_aligned_malloc( sizeof(struct lfds600_freelist_element), LFDS600_ALIGN_DOUBLE_POINTER ); + + if( *fe != NULL ) + { + if( fs->user_data_init_function == NULL ) + { + (*fe)->user_data = NULL; + rv = 1; + } + + if( fs->user_data_init_function != NULL ) + { + rv = fs->user_data_init_function( &(*fe)->user_data, fs->user_state ); + + if( rv == 0 ) + { + lfds600_abstraction_aligned_free( *fe ); + *fe = NULL; + } + } + } + + if( rv == 1 ) + lfds600_abstraction_increment( (lfds600_atom_t *) &fs->element_count ); + + return( rv ); +} + diff --git a/liblfds/liblfds6.0.0/liblfds600/src/lfds600_freelist/lfds600_freelist_pop_push.c b/liblfds/liblfds6.0.0/liblfds600/src/lfds600_freelist/lfds600_freelist_pop_push.c new file mode 100644 index 0000000..c35a765 --- /dev/null +++ b/liblfds/liblfds6.0.0/liblfds600/src/lfds600_freelist/lfds600_freelist_pop_push.c @@ -0,0 +1,88 @@ +#include "lfds600_freelist_internal.h" + + + + + +/****************************************************************************/ +struct lfds600_freelist_element *lfds600_freelist_pop( struct lfds600_freelist_state *fs, struct lfds600_freelist_element **fe ) +{ + LFDS600_ALIGN(LFDS600_ALIGN_DOUBLE_POINTER) struct lfds600_freelist_element + *fe_local[LFDS600_FREELIST_PAC_SIZE]; + + assert( fs != NULL ); + assert( fe != NULL ); + + fe_local[LFDS600_FREELIST_COUNTER] = fs->top[LFDS600_FREELIST_COUNTER]; + fe_local[LFDS600_FREELIST_POINTER] = fs->top[LFDS600_FREELIST_POINTER]; + + /* TRD : note that lfds600_abstraction_dcas loads the original value of the destination (fs->top) into the compare (fe_local) + (this happens of course after the CAS itself has occurred inside lfds600_abstraction_dcas) + */ + + do + { + if( fe_local[LFDS600_FREELIST_POINTER] == NULL ) + { + *fe = NULL; + return( *fe ); + } + } + while( 0 == lfds600_abstraction_dcas((volatile lfds600_atom_t *) fs->top, (lfds600_atom_t *) fe_local[LFDS600_FREELIST_POINTER]->next, (lfds600_atom_t *) fe_local) ); + + *fe = (struct lfds600_freelist_element *) fe_local[LFDS600_FREELIST_POINTER]; + + return( *fe ); +} + + + + + +/****************************************************************************/ +struct lfds600_freelist_element *lfds600_freelist_guaranteed_pop( struct lfds600_freelist_state *fs, struct lfds600_freelist_element **fe ) +{ + assert( fs != NULL ); + assert( fe != NULL ); + + lfds600_freelist_internal_new_element( fs, fe ); + + return( *fe ); +} + + + + + +/****************************************************************************/ +void lfds600_freelist_push( struct lfds600_freelist_state *fs, struct lfds600_freelist_element *fe ) +{ + LFDS600_ALIGN(LFDS600_ALIGN_DOUBLE_POINTER) struct lfds600_freelist_element + *fe_local[LFDS600_FREELIST_PAC_SIZE], + *original_fe_next[LFDS600_FREELIST_PAC_SIZE]; + + assert( fs != NULL ); + assert( fe != NULL ); + + fe_local[LFDS600_FREELIST_POINTER] = fe; + fe_local[LFDS600_FREELIST_COUNTER] = (struct lfds600_freelist_element *) lfds600_abstraction_increment( (lfds600_atom_t *) &fs->aba_counter ); + + original_fe_next[LFDS600_FREELIST_POINTER] = fs->top[LFDS600_FREELIST_POINTER]; + original_fe_next[LFDS600_FREELIST_COUNTER] = fs->top[LFDS600_FREELIST_COUNTER]; + + /* TRD : note that lfds600_abstraction_dcas loads the original value of the destination (fs->top) into the compare (original_fe_next) + (this happens of course after the CAS itself has occurred inside lfds600_abstraction_dcas) + this then causes us in our loop, should we repeat it, to update fe_local->next to a more + up-to-date version of the head of the lfds600_freelist + */ + + do + { + fe_local[LFDS600_FREELIST_POINTER]->next[LFDS600_FREELIST_POINTER] = original_fe_next[LFDS600_FREELIST_POINTER]; + fe_local[LFDS600_FREELIST_POINTER]->next[LFDS600_FREELIST_COUNTER] = original_fe_next[LFDS600_FREELIST_COUNTER]; + } + while( 0 == lfds600_abstraction_dcas((volatile lfds600_atom_t *) fs->top, (lfds600_atom_t *) fe_local, (lfds600_atom_t *) original_fe_next) ); + + return; +} + diff --git a/liblfds/liblfds6.0.0/liblfds600/src/lfds600_freelist/lfds600_freelist_query.c b/liblfds/liblfds6.0.0/liblfds600/src/lfds600_freelist/lfds600_freelist_query.c new file mode 100644 index 0000000..dac6bdd --- /dev/null +++ b/liblfds/liblfds6.0.0/liblfds600/src/lfds600_freelist/lfds600_freelist_query.c @@ -0,0 +1,113 @@ +#include "lfds600_freelist_internal.h" + + + + + +/****************************************************************************/ +void lfds600_freelist_query( struct lfds600_freelist_state *fs, enum lfds600_freelist_query_type query_type, void *query_input, void *query_output ) +{ + assert( fs != NULL ); + // TRD : query type can be any value in its range + // TRD : query_input can be NULL in some cases + assert( query_output != NULL ); + + switch( query_type ) + { + case LFDS600_FREELIST_QUERY_ELEMENT_COUNT: + assert( query_input == NULL ); + + *(lfds600_atom_t *) query_output = fs->element_count; + break; + + case LFDS600_FREELIST_QUERY_VALIDATE: + // TRD : query_input can be NULL + + lfds600_freelist_internal_validate( fs, (struct lfds600_validation_info *) query_input, (enum data_structure_validity *) query_output ); + break; + } + + return; +} + + + + + +/****************************************************************************/ +void lfds600_freelist_internal_validate( struct lfds600_freelist_state *fs, struct lfds600_validation_info *vi, enum data_structure_validity *lfds600_freelist_validity ) +{ + struct lfds600_freelist_element + *fe, + *fe_slow, + *fe_fast; + + lfds600_atom_t + element_count = 0; + + assert( fs != NULL ); + // TRD : vi can be NULL + assert( lfds600_freelist_validity != NULL ); + + *lfds600_freelist_validity = VALIDITY_VALID; + + fe_slow = fe_fast = (struct lfds600_freelist_element *) fs->top[LFDS600_FREELIST_POINTER]; + + /* TRD : first, check for a loop + we have two pointers + both of which start at the top of the lfds600_freelist + we enter a loop + and on each iteration + we advance one pointer by one element + and the other by two + + we exit the loop when both pointers are NULL + (have reached the end of the lfds600_freelist) + + or + + if we fast pointer 'sees' the slow pointer + which means we have a loop + */ + + if( fe_slow != NULL ) + do + { + fe_slow = fe_slow->next[LFDS600_FREELIST_POINTER]; + + if( fe_fast != NULL ) + fe_fast = fe_fast->next[LFDS600_FREELIST_POINTER]; + + if( fe_fast != NULL ) + fe_fast = fe_fast->next[LFDS600_FREELIST_POINTER]; + } + while( fe_slow != NULL and fe_fast != fe_slow ); + + if( fe_fast != NULL and fe_slow != NULL and fe_fast == fe_slow ) + *lfds600_freelist_validity = VALIDITY_INVALID_LOOP; + + /* TRD : now check for expected number of elements + vi can be NULL, in which case we do not check + we know we don't have a loop from our earlier check + */ + + if( *lfds600_freelist_validity == VALIDITY_VALID and vi != NULL ) + { + fe = (struct lfds600_freelist_element *) fs->top[LFDS600_FREELIST_POINTER]; + + while( fe != NULL ) + { + element_count++; + fe = (struct lfds600_freelist_element *) fe->next[LFDS600_FREELIST_POINTER]; + } + + if( element_count < vi->min_elements ) + *lfds600_freelist_validity = VALIDITY_INVALID_MISSING_ELEMENTS; + + if( element_count > vi->max_elements ) + *lfds600_freelist_validity = VALIDITY_INVALID_ADDITIONAL_ELEMENTS; + } + + return; +} + diff --git a/liblfds/liblfds6.0.0/liblfds600/src/lfds600_internal.h b/liblfds/liblfds6.0.0/liblfds600/src/lfds600_internal.h new file mode 100644 index 0000000..cd0a9e6 --- /dev/null +++ b/liblfds/liblfds6.0.0/liblfds600/src/lfds600_internal.h @@ -0,0 +1,12 @@ +/***** public prototypes *****/ +#include "liblfds600.h" + +/***** defines *****/ +#define and && +#define or || + +#define RAISED 1 +#define LOWERED 0 + +#define NO_FLAGS 0x0 + diff --git a/liblfds/liblfds6.0.0/liblfds600/src/lfds600_queue/lfds600_queue_delete.c b/liblfds/liblfds6.0.0/liblfds600/src/lfds600_queue/lfds600_queue_delete.c new file mode 100644 index 0000000..5a4d7ee --- /dev/null +++ b/liblfds/liblfds6.0.0/liblfds600/src/lfds600_queue/lfds600_queue_delete.c @@ -0,0 +1,55 @@ +#include "lfds600_queue_internal.h" + + + + + +/****************************************************************************/ +void lfds600_queue_delete( struct lfds600_queue_state *qs, void (*user_data_delete_function)(void *user_data, void *user_state), void *user_state ) +{ + void + *user_data; + + assert( qs != NULL ); + // TRD : user_data_delete_function can be NULL + // TRD : user_state can be NULL + + while( lfds600_queue_dequeue(qs, &user_data) ) + if( user_data_delete_function != NULL ) + user_data_delete_function( user_data, user_state ); + + /* TRD : fully dequeuing will leave us + with a single dummy element + which both qs->enqueue and qs->dequeue point at + we push this back onto the lfds600_freelist + before we delete the lfds600_freelist + */ + + lfds600_freelist_push( qs->fs, qs->enqueue[LFDS600_QUEUE_POINTER]->fe ); + + lfds600_freelist_delete( qs->fs, lfds600_queue_internal_freelist_delete_function, NULL ); + + lfds600_abstraction_aligned_free( qs ); + + return; +} + + + + + +/****************************************************************************/ +#pragma warning( disable : 4100 ) + +void lfds600_queue_internal_freelist_delete_function( void *user_data, void *user_state ) +{ + assert( user_data != NULL ); + assert( user_state == NULL ); + + lfds600_abstraction_aligned_free( user_data ); + + return; +} + +#pragma warning( default : 4100 ) + diff --git a/liblfds/liblfds6.0.0/liblfds600/src/lfds600_queue/lfds600_queue_internal.h b/liblfds/liblfds6.0.0/liblfds600/src/lfds600_queue/lfds600_queue_internal.h new file mode 100644 index 0000000..8701b2d --- /dev/null +++ b/liblfds/liblfds6.0.0/liblfds600/src/lfds600_queue/lfds600_queue_internal.h @@ -0,0 +1,60 @@ +/***** the library wide include file *****/ +#include "lfds600_internal.h" + +/***** pragmas *****/ + +/***** defines *****/ +#define LFDS600_QUEUE_STATE_UNKNOWN -1 +#define LFDS600_QUEUE_STATE_EMPTY 0 +#define LFDS600_QUEUE_STATE_ENQUEUE_OUT_OF_PLACE 1 +#define LFDS600_QUEUE_STATE_ATTEMPT_DELFDS600_QUEUE 2 + +#define LFDS600_QUEUE_POINTER 0 +#define LFDS600_QUEUE_COUNTER 1 +#define LFDS600_QUEUE_PAC_SIZE 2 + +/***** structures *****/ +#pragma pack( push, LFDS600_ALIGN_DOUBLE_POINTER ) + +struct lfds600_queue_state +{ + struct lfds600_queue_element + *volatile enqueue[LFDS600_QUEUE_PAC_SIZE], + *volatile dequeue[LFDS600_QUEUE_PAC_SIZE]; + + lfds600_atom_t + aba_counter; + + struct lfds600_freelist_state + *fs; +}; + +struct lfds600_queue_element +{ + // TRD : next in a lfds600_queue requires volatile as it is target of CAS + struct lfds600_queue_element + *volatile next[LFDS600_QUEUE_PAC_SIZE]; + + struct lfds600_freelist_element + *fe; + + void + *user_data; +}; + +#pragma pack( pop ) + +/***** externs *****/ + +/***** private prototypes *****/ +int lfds600_queue_internal_freelist_init_function( void **user_data, void *user_state ); +void lfds600_queue_internal_freelist_delete_function( void *user_data, void *user_state ); + +void lfds600_queue_internal_new_element_from_freelist( struct lfds600_queue_state *qs, struct lfds600_queue_element *qe[LFDS600_QUEUE_PAC_SIZE], void *user_data ); +void lfds600_queue_internal_guaranteed_new_element_from_freelist( struct lfds600_queue_state *qs, struct lfds600_queue_element * qe[LFDS600_QUEUE_PAC_SIZE], void *user_data ); +void lfds600_queue_internal_init_element( struct lfds600_queue_state *qs, struct lfds600_queue_element *qe[LFDS600_QUEUE_PAC_SIZE], struct lfds600_freelist_element *fe, void *user_data ); + +void lfds600_queue_internal_queue( struct lfds600_queue_state *qs, struct lfds600_queue_element *qe[LFDS600_QUEUE_PAC_SIZE] ); + +void lfds600_queue_internal_validate( struct lfds600_queue_state *qs, struct lfds600_validation_info *vi, enum data_structure_validity *lfds600_queue_validity, enum data_structure_validity *lfds600_freelist_validity ); + diff --git a/liblfds/liblfds6.0.0/liblfds600/src/lfds600_queue/lfds600_queue_new.c b/liblfds/liblfds6.0.0/liblfds600/src/lfds600_queue/lfds600_queue_new.c new file mode 100644 index 0000000..635b2cd --- /dev/null +++ b/liblfds/liblfds6.0.0/liblfds600/src/lfds600_queue/lfds600_queue_new.c @@ -0,0 +1,140 @@ +#include "lfds600_queue_internal.h" + + + + + +/****************************************************************************/ +int lfds600_queue_new( struct lfds600_queue_state **qs, lfds600_atom_t number_elements ) +{ + int + rv = 0; + + struct lfds600_queue_element + *qe[LFDS600_QUEUE_PAC_SIZE]; + + assert( qs != NULL ); + // TRD : number_elements can be any value in its range + + *qs = (struct lfds600_queue_state *) lfds600_abstraction_aligned_malloc( sizeof(struct lfds600_queue_state), LFDS600_ALIGN_DOUBLE_POINTER ); + + if( *qs != NULL ) + { + // TRD : the size of the lfds600_freelist is the size of the lfds600_queue (+1 for the leading dummy element, which is hidden from the caller) + lfds600_freelist_new( &(*qs)->fs, number_elements+1, lfds600_queue_internal_freelist_init_function, NULL ); + + if( (*qs)->fs != NULL ) + { + lfds600_queue_internal_new_element_from_freelist( *qs, qe, NULL ); + (*qs)->enqueue[LFDS600_QUEUE_POINTER] = (*qs)->dequeue[LFDS600_QUEUE_POINTER] = qe[LFDS600_QUEUE_POINTER]; + (*qs)->aba_counter = 0; + rv = 1; + } + + if( (*qs)->fs == NULL ) + { + lfds600_abstraction_aligned_free( *qs ); + *qs = NULL; + } + } + + return( rv ); +} + + + + + +/****************************************************************************/ +#pragma warning( disable : 4100 ) + +int lfds600_queue_internal_freelist_init_function( void **user_data, void *user_state ) +{ + int + rv = 0; + + assert( user_data != NULL ); + assert( user_state == NULL ); + + *user_data = lfds600_abstraction_aligned_malloc( sizeof(struct lfds600_queue_element), LFDS600_ALIGN_DOUBLE_POINTER ); + + if( *user_data != NULL ) + rv = 1; + + return( rv ); +} + +#pragma warning( default : 4100 ) + + + + + +/****************************************************************************/ +void lfds600_queue_internal_new_element_from_freelist( struct lfds600_queue_state *qs, struct lfds600_queue_element *qe[LFDS600_QUEUE_PAC_SIZE], void *user_data ) +{ + struct lfds600_freelist_element + *fe; + + assert( qs != NULL ); + assert( qe != NULL ); + // TRD : user_data can be any value in its range + + qe[LFDS600_QUEUE_POINTER] = NULL; + + lfds600_freelist_pop( qs->fs, &fe ); + + if( fe != NULL ) + lfds600_queue_internal_init_element( qs, qe, fe, user_data ); + + return; +} + + + + + +/****************************************************************************/ +void lfds600_queue_internal_guaranteed_new_element_from_freelist( struct lfds600_queue_state *qs, struct lfds600_queue_element *qe[LFDS600_QUEUE_PAC_SIZE], void *user_data ) +{ + struct lfds600_freelist_element + *fe; + + assert( qs != NULL ); + assert( qe != NULL ); + // TRD : user_data can be any value in its range + + qe[LFDS600_QUEUE_POINTER] = NULL; + + lfds600_freelist_guaranteed_pop( qs->fs, &fe ); + + if( fe != NULL ) + lfds600_queue_internal_init_element( qs, qe, fe, user_data ); + + return; +} + + + + + +/****************************************************************************/ +void lfds600_queue_internal_init_element( struct lfds600_queue_state *qs, struct lfds600_queue_element *qe[LFDS600_QUEUE_PAC_SIZE], struct lfds600_freelist_element *fe, void *user_data ) +{ + assert( qs != NULL ); + assert( qe != NULL ); + assert( fe != NULL ); + // TRD : user_data can be any value in its range + + lfds600_freelist_get_user_data_from_element( fe, (void **) &qe[LFDS600_QUEUE_POINTER] ); + qe[LFDS600_QUEUE_COUNTER] = (struct lfds600_queue_element *) lfds600_abstraction_increment( (lfds600_atom_t *) &qs->aba_counter ); + + qe[LFDS600_QUEUE_POINTER]->next[LFDS600_QUEUE_POINTER] = NULL; + qe[LFDS600_QUEUE_POINTER]->next[LFDS600_QUEUE_COUNTER] = (struct lfds600_queue_element *) lfds600_abstraction_increment( (lfds600_atom_t *) &qs->aba_counter ); + + qe[LFDS600_QUEUE_POINTER]->fe = fe; + qe[LFDS600_QUEUE_POINTER]->user_data = user_data; + + return; +} + diff --git a/liblfds/liblfds6.0.0/liblfds600/src/lfds600_queue/lfds600_queue_query.c b/liblfds/liblfds6.0.0/liblfds600/src/lfds600_queue/lfds600_queue_query.c new file mode 100644 index 0000000..47e6c44 --- /dev/null +++ b/liblfds/liblfds6.0.0/liblfds600/src/lfds600_queue/lfds600_queue_query.c @@ -0,0 +1,153 @@ +#include "lfds600_queue_internal.h" + + + + + +/****************************************************************************/ +#pragma warning( disable : 4100 ) + +void lfds600_queue_query( struct lfds600_queue_state *qs, enum lfds600_queue_query_type query_type, void *query_input, void *query_output ) +{ + assert( qs != NULL ); + // TRD : query_type can be any value in its range + // TRD : query_input can be NULL + assert( query_output != NULL ); + + switch( query_type ) + { + case LFDS600_QUEUE_QUERY_ELEMENT_COUNT: + assert( query_input == NULL ); + + lfds600_freelist_query( qs->fs, LFDS600_FREELIST_QUERY_ELEMENT_COUNT, NULL, query_output ); + break; + + case LFDS600_QUEUE_QUERY_VALIDATE: + // TRD : query_input can be NULL + + lfds600_queue_internal_validate( qs, (struct lfds600_validation_info *) query_input, (enum data_structure_validity *) query_output, ((enum data_structure_validity *) query_output)+1 ); + break; + } + + return; +} + +#pragma warning( default : 4100 ) + + + + + +/****************************************************************************/ +void lfds600_queue_internal_validate( struct lfds600_queue_state *qs, struct lfds600_validation_info *vi, enum data_structure_validity *lfds600_queue_validity, enum data_structure_validity *lfds600_freelist_validity ) +{ + struct lfds600_queue_element + *qe, + *qe_slow, + *qe_fast; + + lfds600_atom_t + element_count = 0, + total_elements; + + struct lfds600_validation_info + lfds600_freelist_vi; + + assert( qs != NULL ); + // TRD : vi can be NULL + assert( lfds600_queue_validity != NULL ); + assert( lfds600_freelist_validity != NULL ); + + *lfds600_queue_validity = VALIDITY_VALID; + + qe_slow = qe_fast = (struct lfds600_queue_element *) qs->dequeue[LFDS600_QUEUE_POINTER]; + + /* TRD : first, check for a loop + we have two pointers + both of which start at the dequeue end of the lfds600_queue + we enter a loop + and on each iteration + we advance one pointer by one element + and the other by two + + we exit the loop when both pointers are NULL + (have reached the end of the lfds600_queue) + + or + + if we fast pointer 'sees' the slow pointer + which means we have a loop + */ + + if( qe_slow != NULL ) + do + { + qe_slow = qe_slow->next[LFDS600_QUEUE_POINTER]; + + if( qe_fast != NULL ) + qe_fast = qe_fast->next[LFDS600_QUEUE_POINTER]; + + if( qe_fast != NULL ) + qe_fast = qe_fast->next[LFDS600_QUEUE_POINTER]; + } + while( qe_slow != NULL and qe_fast != qe_slow ); + + if( qe_fast != NULL and qe_slow != NULL and qe_fast == qe_slow ) + *lfds600_queue_validity = VALIDITY_INVALID_LOOP; + + /* TRD : now check for expected number of elements + vi can be NULL, in which case we do not check + we know we don't have a loop from our earlier check + */ + + if( *lfds600_queue_validity == VALIDITY_VALID and vi != NULL ) + { + qe = (struct lfds600_queue_element *) qs->dequeue[LFDS600_QUEUE_POINTER]; + + while( qe != NULL ) + { + element_count++; + qe = (struct lfds600_queue_element *) qe->next[LFDS600_QUEUE_POINTER]; + } + + /* TRD : remember there is a dummy element in the lfds600_queue */ + element_count--; + + if( element_count < vi->min_elements ) + *lfds600_queue_validity = VALIDITY_INVALID_MISSING_ELEMENTS; + + if( element_count > vi->max_elements ) + *lfds600_queue_validity = VALIDITY_INVALID_ADDITIONAL_ELEMENTS; + } + + /* TRD : now we validate the lfds600_freelist + + we may be able to check for the expected number of + elements in the lfds600_freelist + + if the caller has given us an expected min and max + number of elements in the lfds600_queue, then the total number + of elements in the lfds600_freelist, minus that min and max, + gives us the expected number of elements in the + lfds600_freelist + */ + + if( vi != NULL ) + { + lfds600_freelist_query( qs->fs, LFDS600_FREELIST_QUERY_ELEMENT_COUNT, NULL, (void *) &total_elements ); + + /* TRD : remember there is a dummy element in the lfds600_queue */ + total_elements--; + + lfds600_freelist_vi.min_elements = total_elements - vi->max_elements; + lfds600_freelist_vi.max_elements = total_elements - vi->min_elements; + + lfds600_freelist_query( qs->fs, LFDS600_FREELIST_QUERY_VALIDATE, (void *) &lfds600_freelist_vi, (void *) lfds600_freelist_validity ); + } + + if( vi == NULL ) + lfds600_freelist_query( qs->fs, LFDS600_FREELIST_QUERY_VALIDATE, NULL, (void *) lfds600_freelist_validity ); + + return; +} + diff --git a/liblfds/liblfds6.0.0/liblfds600/src/lfds600_queue/lfds600_queue_queue.c b/liblfds/liblfds6.0.0/liblfds600/src/lfds600_queue/lfds600_queue_queue.c new file mode 100644 index 0000000..19ee3f3 --- /dev/null +++ b/liblfds/liblfds6.0.0/liblfds600/src/lfds600_queue/lfds600_queue_queue.c @@ -0,0 +1,181 @@ +#include "lfds600_queue_internal.h" + + + + + +/****************************************************************************/ +int lfds600_queue_enqueue( struct lfds600_queue_state *qs, void *user_data ) +{ + LFDS600_ALIGN(LFDS600_ALIGN_DOUBLE_POINTER) struct lfds600_queue_element + *qe[LFDS600_QUEUE_PAC_SIZE]; + + assert( qs != NULL ); + // TRD : user_data can be NULL + + lfds600_queue_internal_new_element_from_freelist( qs, qe, user_data ); + + if( qe[LFDS600_QUEUE_POINTER] == NULL ) + return( 0 ); + + lfds600_queue_internal_queue( qs, qe ); + + return( 1 ); +} + + + + + +/****************************************************************************/ +int lfds600_queue_guaranteed_enqueue( struct lfds600_queue_state *qs, void *user_data ) +{ + LFDS600_ALIGN(LFDS600_ALIGN_DOUBLE_POINTER) struct lfds600_queue_element + *qe[LFDS600_QUEUE_PAC_SIZE]; + + assert( qs != NULL ); + // TRD : user_data can be NULL + + lfds600_queue_internal_guaranteed_new_element_from_freelist( qs, qe, user_data ); + + if( qe[LFDS600_QUEUE_POINTER] == NULL ) + return( 0 ); + + lfds600_queue_internal_queue( qs, qe ); + + return( 1 ); +} + + + + + +/****************************************************************************/ +void lfds600_queue_internal_queue( struct lfds600_queue_state *qs, struct lfds600_queue_element *qe[LFDS600_QUEUE_PAC_SIZE] ) +{ + LFDS600_ALIGN(LFDS600_ALIGN_DOUBLE_POINTER) struct lfds600_queue_element + *enqueue[LFDS600_QUEUE_PAC_SIZE], + *next[LFDS600_QUEUE_PAC_SIZE]; + + unsigned char + cas_result = 0; + + assert( qs != NULL ); + assert( qe != NULL ); + + do + { + enqueue[LFDS600_QUEUE_POINTER] = qs->enqueue[LFDS600_QUEUE_POINTER]; + enqueue[LFDS600_QUEUE_COUNTER] = qs->enqueue[LFDS600_QUEUE_COUNTER]; + + next[LFDS600_QUEUE_POINTER] = enqueue[LFDS600_QUEUE_POINTER]->next[LFDS600_QUEUE_POINTER]; + next[LFDS600_QUEUE_COUNTER] = enqueue[LFDS600_QUEUE_POINTER]->next[LFDS600_QUEUE_COUNTER]; + + /* TRD : this if() ensures that the next we read, just above, + really is from qs->enqueue (which we copied into enqueue) + */ + + if( qs->enqueue[LFDS600_QUEUE_POINTER] == enqueue[LFDS600_QUEUE_POINTER] and qs->enqueue[LFDS600_QUEUE_COUNTER] == enqueue[LFDS600_QUEUE_COUNTER] ) + { + if( next[LFDS600_QUEUE_POINTER] == NULL ) + { + qe[LFDS600_QUEUE_COUNTER] = next[LFDS600_QUEUE_COUNTER] + 1; + cas_result = lfds600_abstraction_dcas( (volatile lfds600_atom_t *) enqueue[LFDS600_QUEUE_POINTER]->next, (lfds600_atom_t *) qe, (lfds600_atom_t *) next ); + } + else + { + next[LFDS600_QUEUE_COUNTER] = enqueue[LFDS600_QUEUE_COUNTER] + 1; + lfds600_abstraction_dcas( (volatile lfds600_atom_t *) qs->enqueue, (lfds600_atom_t *) next, (lfds600_atom_t *) enqueue ); + } + } + } + while( cas_result == 0 ); + + qe[LFDS600_QUEUE_COUNTER] = enqueue[LFDS600_QUEUE_COUNTER] + 1; + lfds600_abstraction_dcas( (volatile lfds600_atom_t *) qs->enqueue, (lfds600_atom_t *) qe, (lfds600_atom_t *) enqueue ); + + return; +} + + + + + +/****************************************************************************/ +int lfds600_queue_dequeue( struct lfds600_queue_state *qs, void **user_data ) +{ + LFDS600_ALIGN(LFDS600_ALIGN_DOUBLE_POINTER) struct lfds600_queue_element + *enqueue[LFDS600_QUEUE_PAC_SIZE], + *dequeue[LFDS600_QUEUE_PAC_SIZE], + *next[LFDS600_QUEUE_PAC_SIZE]; + + unsigned char + cas_result = 0; + + int + rv = 1, + state = LFDS600_QUEUE_STATE_UNKNOWN, + finished_flag = LOWERED; + + assert( qs != NULL ); + assert( user_data != NULL ); + + do + { + dequeue[LFDS600_QUEUE_POINTER] = qs->dequeue[LFDS600_QUEUE_POINTER]; + dequeue[LFDS600_QUEUE_COUNTER] = qs->dequeue[LFDS600_QUEUE_COUNTER]; + + enqueue[LFDS600_QUEUE_POINTER] = qs->enqueue[LFDS600_QUEUE_POINTER]; + enqueue[LFDS600_QUEUE_COUNTER] = qs->enqueue[LFDS600_QUEUE_COUNTER]; + + next[LFDS600_QUEUE_POINTER] = dequeue[LFDS600_QUEUE_POINTER]->next[LFDS600_QUEUE_POINTER]; + next[LFDS600_QUEUE_COUNTER] = dequeue[LFDS600_QUEUE_POINTER]->next[LFDS600_QUEUE_COUNTER]; + + /* TRD : confirm that dequeue didn't move between reading it + and reading its next pointer + */ + + if( dequeue[LFDS600_QUEUE_POINTER] == qs->dequeue[LFDS600_QUEUE_POINTER] and dequeue[LFDS600_QUEUE_COUNTER] == qs->dequeue[LFDS600_QUEUE_COUNTER] ) + { + if( enqueue[LFDS600_QUEUE_POINTER] == dequeue[LFDS600_QUEUE_POINTER] and next[LFDS600_QUEUE_POINTER] == NULL ) + state = LFDS600_QUEUE_STATE_EMPTY; + + if( enqueue[LFDS600_QUEUE_POINTER] == dequeue[LFDS600_QUEUE_POINTER] and next[LFDS600_QUEUE_POINTER] != NULL ) + state = LFDS600_QUEUE_STATE_ENQUEUE_OUT_OF_PLACE; + + if( enqueue[LFDS600_QUEUE_POINTER] != dequeue[LFDS600_QUEUE_POINTER] ) + state = LFDS600_QUEUE_STATE_ATTEMPT_DELFDS600_QUEUE; + + switch( state ) + { + case LFDS600_QUEUE_STATE_EMPTY: + *user_data = NULL; + rv = 0; + finished_flag = RAISED; + break; + + case LFDS600_QUEUE_STATE_ENQUEUE_OUT_OF_PLACE: + next[LFDS600_QUEUE_COUNTER] = enqueue[LFDS600_QUEUE_COUNTER] + 1; + lfds600_abstraction_dcas( (volatile lfds600_atom_t *) qs->enqueue, (lfds600_atom_t *) next, (lfds600_atom_t *) enqueue ); + break; + + case LFDS600_QUEUE_STATE_ATTEMPT_DELFDS600_QUEUE: + *user_data = next[LFDS600_QUEUE_POINTER]->user_data; + + next[LFDS600_QUEUE_COUNTER] = dequeue[LFDS600_QUEUE_COUNTER] + 1; + cas_result = lfds600_abstraction_dcas( (volatile lfds600_atom_t *) qs->dequeue, (lfds600_atom_t *) next, (lfds600_atom_t *) dequeue ); + + if( cas_result == 1 ) + finished_flag = RAISED; + break; + } + } + } + while( finished_flag == LOWERED ); + + if( cas_result == 1 ) + lfds600_freelist_push( qs->fs, dequeue[LFDS600_QUEUE_POINTER]->fe ); + + return( rv ); +} + diff --git a/liblfds/liblfds6.0.0/liblfds600/src/lfds600_ringbuffer/lfds600_ringbuffer_delete.c b/liblfds/liblfds6.0.0/liblfds600/src/lfds600_ringbuffer/lfds600_ringbuffer_delete.c new file mode 100644 index 0000000..4c9d5be --- /dev/null +++ b/liblfds/liblfds6.0.0/liblfds600/src/lfds600_ringbuffer/lfds600_ringbuffer_delete.c @@ -0,0 +1,22 @@ +#include "lfds600_ringbuffer_internal.h" + + + + + +/****************************************************************************/ +void lfds600_ringbuffer_delete( struct lfds600_ringbuffer_state *rs, void (*user_data_delete_function)(void *user_data, void *user_state), void *user_state ) +{ + assert( rs != NULL ); + // TRD : user_data_delete_function can be NULL + // TRD : user_state can be NULL + + lfds600_queue_delete( rs->qs, NULL, NULL ); + + lfds600_freelist_delete( rs->fs, user_data_delete_function, user_state ); + + lfds600_abstraction_aligned_free( rs ); + + return; +} + diff --git a/liblfds/liblfds6.0.0/liblfds600/src/lfds600_ringbuffer/lfds600_ringbuffer_get_and_put.c b/liblfds/liblfds6.0.0/liblfds600/src/lfds600_ringbuffer/lfds600_ringbuffer_get_and_put.c new file mode 100644 index 0000000..4799b22 --- /dev/null +++ b/liblfds/liblfds6.0.0/liblfds600/src/lfds600_ringbuffer/lfds600_ringbuffer_get_and_put.c @@ -0,0 +1,108 @@ +#include "lfds600_ringbuffer_internal.h" + + + + + +/****************************************************************************/ +struct lfds600_freelist_element *lfds600_ringbuffer_get_read_element( struct lfds600_ringbuffer_state *rs, struct lfds600_freelist_element **fe ) +{ + assert( rs != NULL ); + assert( fe != NULL ); + + lfds600_queue_dequeue( rs->qs, (void **) fe ); + + return( *fe ); +} + + + + + +/****************************************************************************/ +struct lfds600_freelist_element *lfds600_ringbuffer_get_write_element( struct lfds600_ringbuffer_state *rs, struct lfds600_freelist_element **fe, int *overwrite_flag ) +{ + assert( rs != NULL ); + assert( fe != NULL ); + // TRD : overwrite_flag can be NULL + + /* TRD : we try to obtain an element from the lfds600_freelist + if we can, we populate it and add it to the lfds600_queue + + if we cannot, then the lfds600_ringbuffer is full + so instead we grab the current read element and + use that instead + + dequeue may fail since the lfds600_queue may be emptied + during our dequeue attempt + + so what we actually do here is a loop, attempting + the lfds600_freelist and if it fails then a dequeue, until + we obtain an element + + once we have an element, we lfds600_queue it + + you may be wondering why this operation is in a loop + remember - these operations are lock-free; anything + can happen in between + + so for example the pop could fail because the lfds600_freelist + is empty; but by the time we go to get an element from + the lfds600_queue, the whole lfds600_queue has been emptied back into + the lfds600_freelist! + + if overwrite_flag is provided, we set it to 0 if we + obtained a new element from the lfds600_freelist, 1 if we + stole an element from the lfds600_queue + */ + + do + { + if( overwrite_flag != NULL ) + *overwrite_flag = 0; + + lfds600_freelist_pop( rs->fs, fe ); + + if( *fe == NULL ) + { + lfds600_ringbuffer_get_read_element( rs, fe ); + + if( overwrite_flag != NULL and *fe != NULL ) + *overwrite_flag = 1; + } + } + while( *fe == NULL ); + + return( *fe ); +} + + + + + +/****************************************************************************/ +void lfds600_ringbuffer_put_read_element( struct lfds600_ringbuffer_state *rs, struct lfds600_freelist_element *fe ) +{ + assert( rs != NULL ); + assert( fe != NULL ); + + lfds600_freelist_push( rs->fs, fe ); + + return; +} + + + + + +/****************************************************************************/ +void lfds600_ringbuffer_put_write_element( struct lfds600_ringbuffer_state *rs, struct lfds600_freelist_element *fe ) +{ + assert( rs != NULL ); + assert( fe != NULL ); + + lfds600_queue_enqueue( rs->qs, fe ); + + return; +} + diff --git a/liblfds/liblfds6.0.0/liblfds600/src/lfds600_ringbuffer/lfds600_ringbuffer_internal.h b/liblfds/liblfds6.0.0/liblfds600/src/lfds600_ringbuffer/lfds600_ringbuffer_internal.h new file mode 100644 index 0000000..04329d2 --- /dev/null +++ b/liblfds/liblfds6.0.0/liblfds600/src/lfds600_ringbuffer/lfds600_ringbuffer_internal.h @@ -0,0 +1,24 @@ +/***** the library wide include file *****/ +#include "lfds600_internal.h" + +/***** defines *****/ + +/***** structures *****/ +#pragma pack( push, LFDS600_ALIGN_DOUBLE_POINTER ) + +struct lfds600_ringbuffer_state +{ + struct lfds600_queue_state + *qs; + + struct lfds600_freelist_state + *fs; +}; + +#pragma pack( pop ) + +/***** externs *****/ + +/***** private prototypes *****/ +void lfds600_ringbuffer_internal_validate( struct lfds600_ringbuffer_state *rs, struct lfds600_validation_info *vi, enum data_structure_validity *lfds600_queue_validity, enum data_structure_validity *lfds600_freelist_validity ); + diff --git a/liblfds/liblfds6.0.0/liblfds600/src/lfds600_ringbuffer/lfds600_ringbuffer_new.c b/liblfds/liblfds6.0.0/liblfds600/src/lfds600_ringbuffer/lfds600_ringbuffer_new.c new file mode 100644 index 0000000..e87c0bb --- /dev/null +++ b/liblfds/liblfds6.0.0/liblfds600/src/lfds600_ringbuffer/lfds600_ringbuffer_new.c @@ -0,0 +1,47 @@ +#include "lfds600_ringbuffer_internal.h" + + + + + +/****************************************************************************/ +int lfds600_ringbuffer_new( struct lfds600_ringbuffer_state **rs, lfds600_atom_t number_elements, int (*user_data_init_function)(void **user_data, void *user_state), void *user_state ) +{ + int + rv = 0; + + assert( rs != NULL ); + // TRD : number_elements can be any value in its range + // TRD : user_data_init_function can be NULL + // TRD : user_state can be NULL + + *rs = (struct lfds600_ringbuffer_state *) lfds600_abstraction_aligned_malloc( sizeof(struct lfds600_ringbuffer_state), LFDS600_ALIGN_DOUBLE_POINTER ); + + if( *rs != NULL ) + { + lfds600_freelist_new( &(*rs)->fs, number_elements, user_data_init_function, user_state ); + + if( (*rs)->fs != NULL ) + { + lfds600_queue_new( &(*rs)->qs, number_elements ); + + if( (*rs)->qs != NULL ) + rv = 1; + + if( (*rs)->qs == NULL ) + { + lfds600_abstraction_aligned_free( *rs ); + *rs = NULL; + } + } + + if( (*rs)->fs == NULL ) + { + lfds600_abstraction_aligned_free( *rs ); + *rs = NULL; + } + } + + return( rv ); +} + diff --git a/liblfds/liblfds6.0.0/liblfds600/src/lfds600_ringbuffer/lfds600_ringbuffer_query.c b/liblfds/liblfds6.0.0/liblfds600/src/lfds600_ringbuffer/lfds600_ringbuffer_query.c new file mode 100644 index 0000000..0589da1 --- /dev/null +++ b/liblfds/liblfds6.0.0/liblfds600/src/lfds600_ringbuffer/lfds600_ringbuffer_query.c @@ -0,0 +1,64 @@ +#include "lfds600_ringbuffer_internal.h" + + + + + +/****************************************************************************/ +#pragma warning( disable : 4100 ) + +void lfds600_ringbuffer_query( struct lfds600_ringbuffer_state *rs, enum lfds600_ringbuffer_query_type query_type, void *query_input, void *query_output ) +{ + assert( rs != NULL ); + // TRD : query_type can be any value in its range + // TRD : query_input can be NULL + assert( query_output != NULL ); + + switch( query_type ) + { + case LFDS600_RINGBUFFER_QUERY_VALIDATE: + // TRD : query_input can be NULL + + lfds600_ringbuffer_internal_validate( rs, (struct lfds600_validation_info *) query_input, (enum data_structure_validity *) query_output, ((enum data_structure_validity *) query_output)+2 ); + break; + } + + return; +} + +#pragma warning( default : 4100 ) + + + + + +/****************************************************************************/ +void lfds600_ringbuffer_internal_validate( struct lfds600_ringbuffer_state *rs, struct lfds600_validation_info *vi, enum data_structure_validity *lfds600_queue_validity, enum data_structure_validity *lfds600_freelist_validity ) +{ + assert( rs != NULL ); + // TRD : vi can be NULL + assert( lfds600_queue_validity != NULL ); + assert( lfds600_freelist_validity != NULL ); + + lfds600_queue_query( rs->qs, LFDS600_QUEUE_QUERY_VALIDATE, vi, lfds600_queue_validity ); + + if( vi != NULL ) + { + struct lfds600_validation_info + lfds600_freelist_vi; + + lfds600_atom_t + total_elements; + + lfds600_freelist_query( rs->fs, LFDS600_FREELIST_QUERY_ELEMENT_COUNT, NULL, (void *) &total_elements ); + lfds600_freelist_vi.min_elements = total_elements - vi->max_elements; + lfds600_freelist_vi.max_elements = total_elements - vi->min_elements; + lfds600_freelist_query( rs->fs, LFDS600_FREELIST_QUERY_VALIDATE, (void *) &lfds600_freelist_vi, (void *) lfds600_freelist_validity ); + } + + if( vi == NULL ) + lfds600_freelist_query( rs->fs, LFDS600_FREELIST_QUERY_VALIDATE, NULL, (void *) lfds600_freelist_validity ); + + return; +} + diff --git a/liblfds/liblfds6.0.0/liblfds600/src/lfds600_slist/lfds600_slist_delete.c b/liblfds/liblfds6.0.0/liblfds600/src/lfds600_slist/lfds600_slist_delete.c new file mode 100644 index 0000000..17a9bfe --- /dev/null +++ b/liblfds/liblfds6.0.0/liblfds600/src/lfds600_slist/lfds600_slist_delete.c @@ -0,0 +1,79 @@ +#include "lfds600_slist_internal.h" + + + + + +/****************************************************************************/ +void lfds600_slist_delete( struct lfds600_slist_state *ss ) +{ + lfds600_slist_delete_all_elements( ss ); + + lfds600_abstraction_aligned_free( ss ); + + return; +} + + + + + +/****************************************************************************/ +void lfds600_slist_delete_element( struct lfds600_slist_state *ss, struct lfds600_slist_element *se ) +{ + LFDS600_ALIGN(LFDS600_ALIGN_DOUBLE_POINTER) void + *volatile user_data_and_flags[2], + *volatile new_user_data_and_flags[2]; + + unsigned char + cas_rv = 0; + + assert( ss != NULL ); + assert( se != NULL ); + + user_data_and_flags[LFDS600_SLIST_USER_DATA] = se->user_data_and_flags[LFDS600_SLIST_USER_DATA]; + user_data_and_flags[LFDS600_SLIST_FLAGS] = se->user_data_and_flags[LFDS600_SLIST_FLAGS]; + + do + { + new_user_data_and_flags[LFDS600_SLIST_USER_DATA] = user_data_and_flags[LFDS600_SLIST_USER_DATA]; + new_user_data_and_flags[LFDS600_SLIST_FLAGS] = (void *) ((lfds600_atom_t) user_data_and_flags[LFDS600_SLIST_FLAGS] | LFDS600_SLIST_FLAG_DELETED); + } + while( !((lfds600_atom_t) user_data_and_flags[LFDS600_SLIST_FLAGS] & LFDS600_SLIST_FLAG_DELETED) and 0 == (cas_rv = lfds600_abstraction_dcas((volatile lfds600_atom_t *) se->user_data_and_flags, (lfds600_atom_t *) new_user_data_and_flags, (lfds600_atom_t *) user_data_and_flags)) ); + + if( cas_rv == 1 ) + if( ss->user_data_delete_function != NULL ) + ss->user_data_delete_function( (void *) user_data_and_flags[LFDS600_SLIST_USER_DATA], ss->user_state ); + + return; +} + + + + + +/****************************************************************************/ +void lfds600_slist_delete_all_elements( struct lfds600_slist_state *ss ) +{ + struct lfds600_slist_element + *volatile se, + *volatile se_temp; + + se = ss->head; + + while( se != NULL ) + { + // TRD : if a non-deleted element and there is a delete function, call the delete function + if( ss->user_data_delete_function != NULL ) + ss->user_data_delete_function( (void *) se->user_data_and_flags[LFDS600_SLIST_USER_DATA], ss->user_state ); + + se_temp = se; + se = se->next; + lfds600_abstraction_aligned_free( (void *) se_temp ); + } + + lfds600_slist_internal_init_slist( ss, ss->user_data_delete_function, ss->user_state ); + + return; +} + diff --git a/liblfds/liblfds6.0.0/liblfds600/src/lfds600_slist/lfds600_slist_get_and_set.c b/liblfds/liblfds6.0.0/liblfds600/src/lfds600_slist/lfds600_slist_get_and_set.c new file mode 100644 index 0000000..9ebb214 --- /dev/null +++ b/liblfds/liblfds6.0.0/liblfds600/src/lfds600_slist/lfds600_slist_get_and_set.c @@ -0,0 +1,124 @@ +#include "lfds600_slist_internal.h" + + + + + +/****************************************************************************/ +int lfds600_slist_get_user_data_from_element( struct lfds600_slist_element *se, void **user_data ) +{ + int + rv = 1; + + assert( se != NULL ); + assert( user_data != NULL ); + + *user_data = (void *) se->user_data_and_flags[LFDS600_SLIST_USER_DATA]; + + if( (lfds600_atom_t) se->user_data_and_flags[LFDS600_SLIST_FLAGS] & LFDS600_SLIST_FLAG_DELETED ) + rv = 0; + + return( rv ); +} + + + + + +/****************************************************************************/ +int lfds600_slist_set_user_data_in_element( struct lfds600_slist_element *se, void *user_data ) +{ + LFDS600_ALIGN(LFDS600_ALIGN_DOUBLE_POINTER) volatile void + *user_data_and_flags[2], + *new_user_data_and_flags[2]; + + int + rv = 1; + + assert( se != NULL ); + // TRD : user_data can be NULL + + user_data_and_flags[LFDS600_SLIST_USER_DATA] = se->user_data_and_flags[LFDS600_SLIST_USER_DATA]; + user_data_and_flags[LFDS600_SLIST_FLAGS] = se->user_data_and_flags[LFDS600_SLIST_FLAGS]; + + new_user_data_and_flags[LFDS600_SLIST_USER_DATA] = user_data; + + do + { + new_user_data_and_flags[LFDS600_SLIST_FLAGS] = user_data_and_flags[LFDS600_SLIST_FLAGS]; + } + while( !((lfds600_atom_t) user_data_and_flags[LFDS600_SLIST_FLAGS] & LFDS600_SLIST_FLAG_DELETED) and 0 == lfds600_abstraction_dcas((volatile lfds600_atom_t *) se->user_data_and_flags, (lfds600_atom_t *) new_user_data_and_flags, (lfds600_atom_t *) user_data_and_flags) ); + + if( (lfds600_atom_t) user_data_and_flags[LFDS600_SLIST_FLAGS] & LFDS600_SLIST_FLAG_DELETED ) + rv = 0; + + return( rv ); +} + + + + + +/****************************************************************************/ +struct lfds600_slist_element *lfds600_slist_get_head( struct lfds600_slist_state *ss, struct lfds600_slist_element **se ) +{ + assert( ss != NULL ); + assert( se != NULL ); + + *se = (struct lfds600_slist_element *) ss->head; + + lfds600_slist_internal_move_to_first_undeleted_element( se ); + + return( *se ); +} + + + + + +/****************************************************************************/ +struct lfds600_slist_element *lfds600_slist_get_next( struct lfds600_slist_element *se, struct lfds600_slist_element **next_se ) +{ + assert( se != NULL ); + assert( next_se != NULL ); + + *next_se = (struct lfds600_slist_element *) se->next; + + lfds600_slist_internal_move_to_first_undeleted_element( next_se ); + + return( *next_se ); +} + + + + + +/****************************************************************************/ +struct lfds600_slist_element *lfds600_slist_get_head_and_then_next( struct lfds600_slist_state *ss, struct lfds600_slist_element **se ) +{ + assert( ss != NULL ); + assert( se != NULL ); + + if( *se == NULL ) + lfds600_slist_get_head( ss, se ); + else + lfds600_slist_get_next( *se, se ); + + return( *se ); +} + + + + + +/****************************************************************************/ +void lfds600_slist_internal_move_to_first_undeleted_element( struct lfds600_slist_element **se ) +{ + assert( se != NULL ); + + while( *se != NULL and (lfds600_atom_t) (*se)->user_data_and_flags[LFDS600_SLIST_FLAGS] & LFDS600_SLIST_FLAG_DELETED ) + (*se) = (struct lfds600_slist_element *) (*se)->next; + + return; +} + diff --git a/liblfds/liblfds6.0.0/liblfds600/src/lfds600_slist/lfds600_slist_internal.h b/liblfds/liblfds6.0.0/liblfds600/src/lfds600_slist/lfds600_slist_internal.h new file mode 100644 index 0000000..02dba68 --- /dev/null +++ b/liblfds/liblfds6.0.0/liblfds600/src/lfds600_slist/lfds600_slist_internal.h @@ -0,0 +1,55 @@ +/***** the library wide include file *****/ +#include "lfds600_internal.h" + +/***** defines *****/ +#define LFDS600_SLIST_USER_DATA 0 +#define LFDS600_SLIST_FLAGS 1 + +#define LFDS600_SLIST_NO_FLAGS 0x0 +#define LFDS600_SLIST_FLAG_DELETED 0x1 + +/***** structures *****/ +#pragma pack( push, LFDS600_ALIGN_SINGLE_POINTER ) + +struct lfds600_slist_state +{ + struct lfds600_slist_element + *volatile head; + + void + (*user_data_delete_function)( void *user_data, void *user_state ), + *user_state; +}; + +#pragma pack( pop ) + +#pragma pack( push, LFDS600_ALIGN_DOUBLE_POINTER ) + +/* TRD : this pragma pack doesn't seem to work under Windows + if the structure members are the correct way round + (next first), then user_data_and_flags ends up on + a single pointer boundary and DCAS crashes + + accordingly, I've moved user_data_and_flags first +*/ + +struct lfds600_slist_element +{ + void + *volatile user_data_and_flags[2]; + + // TRD : requires volatile as is target of CAS + struct lfds600_slist_element + *volatile next; +}; + +#pragma pack( pop ) + +/***** private prototypes *****/ +void lfds600_slist_internal_init_slist( struct lfds600_slist_state *ss, void (*user_data_delete_function)(void *user_data, void *user_state), void *user_state ); + +void lfds600_slist_internal_link_element_to_head( struct lfds600_slist_state *lfds600_slist_state, struct lfds600_slist_element *volatile se ); +void lfds600_slist_internal_link_element_after_element( struct lfds600_slist_element *volatile lfds600_slist_in_list_element, struct lfds600_slist_element *volatile se ); + +void lfds600_slist_internal_move_to_first_undeleted_element( struct lfds600_slist_element **se ); + diff --git a/liblfds/liblfds6.0.0/liblfds600/src/lfds600_slist/lfds600_slist_link.c b/liblfds/liblfds6.0.0/liblfds600/src/lfds600_slist/lfds600_slist_link.c new file mode 100644 index 0000000..5000d00 --- /dev/null +++ b/liblfds/liblfds6.0.0/liblfds600/src/lfds600_slist/lfds600_slist_link.c @@ -0,0 +1,53 @@ +#include "lfds600_slist_internal.h" + + + + + +/****************************************************************************/ +void lfds600_slist_internal_link_element_to_head( struct lfds600_slist_state *ss, struct lfds600_slist_element *volatile se ) +{ + LFDS600_ALIGN(LFDS600_ALIGN_SINGLE_POINTER) struct lfds600_slist_element + *se_next; + + assert( ss != NULL ); + assert( se != NULL ); + + se_next = ss->head; + + do + { + se->next = se_next; + } + while( se->next != (se_next = (struct lfds600_slist_element *) lfds600_abstraction_cas((volatile lfds600_atom_t *) &ss->head, (lfds600_atom_t) se, (lfds600_atom_t) se->next)) ); + + return; +} + + + + + +/****************************************************************************/ +void lfds600_slist_internal_link_element_after_element( struct lfds600_slist_element *volatile lfds600_slist_in_list_element, struct lfds600_slist_element *volatile se ) +{ + LFDS600_ALIGN(LFDS600_ALIGN_SINGLE_POINTER) struct lfds600_slist_element + *se_prev, + *se_next; + + assert( lfds600_slist_in_list_element != NULL ); + assert( se != NULL ); + + se_prev = (struct lfds600_slist_element *) lfds600_slist_in_list_element; + + se_next = se_prev->next; + + do + { + se->next = se_next; + } + while( se->next != (se_next = (struct lfds600_slist_element *) lfds600_abstraction_cas((volatile lfds600_atom_t *) &se_prev->next, (lfds600_atom_t) se, (lfds600_atom_t) se->next)) ); + + return; +} + diff --git a/liblfds/liblfds6.0.0/liblfds600/src/lfds600_slist/lfds600_slist_new.c b/liblfds/liblfds6.0.0/liblfds600/src/lfds600_slist/lfds600_slist_new.c new file mode 100644 index 0000000..baaf68e --- /dev/null +++ b/liblfds/liblfds6.0.0/liblfds600/src/lfds600_slist/lfds600_slist_new.c @@ -0,0 +1,97 @@ +#include "lfds600_slist_internal.h" + + + + + +/****************************************************************************/ +int lfds600_slist_new( struct lfds600_slist_state **ss, void (*user_data_delete_function)(void *user_data, void *user_state), void *user_state ) +{ + int + rv = 0; + + assert( ss != NULL ); + // TRD : user_data_delete_function can be NULL + // TRD : user_state can be NULL + + *ss = (struct lfds600_slist_state *) lfds600_abstraction_aligned_malloc( sizeof(struct lfds600_slist_state), LFDS600_ALIGN_SINGLE_POINTER ); + + if( *ss != NULL ) + { + lfds600_slist_internal_init_slist( *ss, user_data_delete_function, user_state ); + rv = 1; + } + + return( rv ); +} + + + + + +/****************************************************************************/ +void lfds600_slist_internal_init_slist( struct lfds600_slist_state *ss, void (*user_data_delete_function)(void *user_data, void *user_state), void *user_state ) +{ + assert( ss != NULL ); + // TRD : user_data_delete_function can be NULL + // TRD : user_state can be NULL + + ss->head = NULL; + ss->user_data_delete_function = user_data_delete_function; + ss->user_state = user_state; + + return; +} + + + + + +/****************************************************************************/ +struct lfds600_slist_element *lfds600_slist_new_head( struct lfds600_slist_state *ss, void *user_data ) +{ + LFDS600_ALIGN(LFDS600_ALIGN_SINGLE_POINTER) struct lfds600_slist_element + *volatile se; + + assert( ss != NULL ); + // TRD : user_data can be NULL + + se = (struct lfds600_slist_element *) lfds600_abstraction_aligned_malloc( sizeof(struct lfds600_slist_element), LFDS600_ALIGN_DOUBLE_POINTER ); + + if( se != NULL ) + { + se->user_data_and_flags[LFDS600_SLIST_USER_DATA] = user_data; + se->user_data_and_flags[LFDS600_SLIST_FLAGS] = LFDS600_SLIST_NO_FLAGS; + + lfds600_slist_internal_link_element_to_head( ss, se ); + } + + return( (struct lfds600_slist_element *) se ); +} + + + + + +/****************************************************************************/ +struct lfds600_slist_element *lfds600_slist_new_next( struct lfds600_slist_element *se, void *user_data ) +{ + LFDS600_ALIGN(LFDS600_ALIGN_SINGLE_POINTER) struct lfds600_slist_element + *volatile se_next; + + assert( se != NULL ); + // TRD : user_data can be NULL + + se_next = (struct lfds600_slist_element *) lfds600_abstraction_aligned_malloc( sizeof(struct lfds600_slist_element), LFDS600_ALIGN_DOUBLE_POINTER ); + + if( se_next != NULL ) + { + se_next->user_data_and_flags[LFDS600_SLIST_USER_DATA] = user_data; + se_next->user_data_and_flags[LFDS600_SLIST_FLAGS] = LFDS600_SLIST_NO_FLAGS; + + lfds600_slist_internal_link_element_after_element( se, se_next ); + } + + return( (struct lfds600_slist_element *) se_next ); +} + diff --git a/liblfds/liblfds6.0.0/liblfds600/src/lfds600_stack/lfds600_stack_delete.c b/liblfds/liblfds6.0.0/liblfds600/src/lfds600_stack/lfds600_stack_delete.c new file mode 100644 index 0000000..18ec098 --- /dev/null +++ b/liblfds/liblfds6.0.0/liblfds600/src/lfds600_stack/lfds600_stack_delete.c @@ -0,0 +1,67 @@ +#include "lfds600_stack_internal.h" + + + + + +/****************************************************************************/ +void lfds600_stack_delete( struct lfds600_stack_state *ss, void (*user_data_delete_function)(void *user_data, void *user_state), void *user_state ) +{ + void + *user_data; + + assert( ss != NULL ); + // TRD : user_data_delete_function can be NULL + // TRD : user_state can be NULL + + while( lfds600_stack_pop(ss, &user_data) ) + if( user_data_delete_function != NULL ) + user_data_delete_function( user_data, user_state ); + + lfds600_freelist_delete( ss->fs, lfds600_stack_internal_freelist_delete_function, NULL ); + + lfds600_abstraction_aligned_free( ss ); + + return; +} + + + + + +/****************************************************************************/ +void lfds600_stack_clear( struct lfds600_stack_state *ss, void (*user_data_clear_function)(void *user_data, void *user_state), void *user_state ) +{ + void + *user_data; + + assert( ss != NULL ); + // TRD : user_data_clear_function can be NULL + // TRD : user_state can be NULL + + while( lfds600_stack_pop(ss, &user_data) ) + if( user_data_clear_function != NULL ) + user_data_clear_function( user_data, user_state ); + + return; +} + + + + + +/****************************************************************************/ +#pragma warning( disable : 4100 ) + +void lfds600_stack_internal_freelist_delete_function( void *user_data, void *user_state ) +{ + assert( user_data != NULL ); + assert( user_state == NULL ); + + lfds600_abstraction_aligned_free( user_data ); + + return; +} + +#pragma warning( default : 4100 ) + diff --git a/liblfds/liblfds6.0.0/liblfds600/src/lfds600_stack/lfds600_stack_internal.h b/liblfds/liblfds6.0.0/liblfds600/src/lfds600_stack/lfds600_stack_internal.h new file mode 100644 index 0000000..928e829 --- /dev/null +++ b/liblfds/liblfds6.0.0/liblfds600/src/lfds600_stack/lfds600_stack_internal.h @@ -0,0 +1,50 @@ +/***** the library wide include file *****/ +#include "lfds600_internal.h" + +/***** pragmas *****/ + +/***** defines *****/ +#define LFDS600_STACK_POINTER 0 +#define LFDS600_STACK_COUNTER 1 +#define LFDS600_STACK_PAC_SIZE 2 + +/***** structures *****/ +#pragma pack( push, LFDS600_ALIGN_DOUBLE_POINTER ) + +struct lfds600_stack_state +{ + // TRD : must come first for alignment + struct lfds600_stack_element + *volatile top[LFDS600_STACK_PAC_SIZE]; + + lfds600_atom_t + aba_counter; + + struct lfds600_freelist_state + *fs; +}; + +struct lfds600_stack_element +{ + struct lfds600_stack_element + *next[LFDS600_STACK_PAC_SIZE]; + + struct lfds600_freelist_element + *fe; + + void + *user_data; +}; + +#pragma pack( pop ) + +/***** private prototypes *****/ +int lfds600_stack_internal_freelist_init_function( void **user_data, void *user_state ); +void lfds600_stack_internal_freelist_delete_function( void *user_data, void *user_state ); + +void lfds600_stack_internal_new_element_from_freelist( struct lfds600_stack_state *ss, struct lfds600_stack_element *se[LFDS600_STACK_PAC_SIZE], void *user_data ); +void lfds600_stack_internal_new_element( struct lfds600_stack_state *ss, struct lfds600_stack_element *se[LFDS600_STACK_PAC_SIZE], void *user_data ); +void lfds600_stack_internal_init_element( struct lfds600_stack_state *ss, struct lfds600_stack_element *se[LFDS600_STACK_PAC_SIZE], struct lfds600_freelist_element *fe, void *user_data ); + +void lfds600_stack_internal_push( struct lfds600_stack_state *ss, struct lfds600_stack_element *se[LFDS600_STACK_PAC_SIZE] ); + diff --git a/liblfds/liblfds6.0.0/liblfds600/src/lfds600_stack/lfds600_stack_new.c b/liblfds/liblfds6.0.0/liblfds600/src/lfds600_stack/lfds600_stack_new.c new file mode 100644 index 0000000..f93a71c --- /dev/null +++ b/liblfds/liblfds6.0.0/liblfds600/src/lfds600_stack/lfds600_stack_new.c @@ -0,0 +1,139 @@ +#include "lfds600_stack_internal.h" + + + + + +/****************************************************************************/ +int lfds600_stack_new( struct lfds600_stack_state **ss, lfds600_atom_t number_elements ) +{ + int + rv = 0; + + assert( ss != NULL ); + // TRD : number_elements can be any value in its range + + *ss = (struct lfds600_stack_state *) lfds600_abstraction_aligned_malloc( sizeof(struct lfds600_stack_state), LFDS600_ALIGN_DOUBLE_POINTER ); + + if( *ss != NULL ) + { + // TRD : the size of the lfds600_freelist is the size of the lfds600_stack + lfds600_freelist_new( &(*ss)->fs, number_elements, lfds600_stack_internal_freelist_init_function, NULL ); + + if( (*ss)->fs == NULL ) + { + lfds600_abstraction_aligned_free( *ss ); + *ss = NULL; + } + + if( (*ss)->fs != NULL ) + { + (*ss)->top[LFDS600_STACK_POINTER] = NULL; + (*ss)->top[LFDS600_STACK_COUNTER] = 0; + (*ss)->aba_counter = 0; + rv = 1; + } + } + + return( rv ); +} + + + + + +/****************************************************************************/ +#pragma warning( disable : 4100 ) + +int lfds600_stack_internal_freelist_init_function( void **user_data, void *user_state ) +{ + int + rv = 0; + + assert( user_data != NULL ); + assert( user_state == NULL ); + + *user_data = lfds600_abstraction_aligned_malloc( sizeof(struct lfds600_stack_element), LFDS600_ALIGN_DOUBLE_POINTER ); + + if( *user_data != NULL ) + rv = 1; + + return( rv ); +} + +#pragma warning( default : 4100 ) + + + + + +/****************************************************************************/ +void lfds600_stack_internal_new_element_from_freelist( struct lfds600_stack_state *ss, struct lfds600_stack_element *se[LFDS600_STACK_PAC_SIZE], void *user_data ) +{ + struct lfds600_freelist_element + *fe; + + assert( ss != NULL ); + assert( se != NULL ); + // TRD : user_data can be any value in its range + + lfds600_freelist_pop( ss->fs, &fe ); + + if( fe == NULL ) + se[LFDS600_STACK_POINTER] = NULL; + + if( fe != NULL ) + lfds600_stack_internal_init_element( ss, se, fe, user_data ); + + return; +} + + + + + +/****************************************************************************/ +void lfds600_stack_internal_new_element( struct lfds600_stack_state *ss, struct lfds600_stack_element *se[LFDS600_STACK_PAC_SIZE], void *user_data ) +{ + struct lfds600_freelist_element + *fe; + + assert( ss != NULL ); + assert( se != NULL ); + // TRD : user_data can be any value in its range + + lfds600_freelist_guaranteed_pop( ss->fs, &fe ); + + if( fe == NULL ) + se[LFDS600_STACK_POINTER] = NULL; + + if( fe != NULL ) + lfds600_stack_internal_init_element( ss, se, fe, user_data ); + + return; +} + + + + + +/****************************************************************************/ +void lfds600_stack_internal_init_element( struct lfds600_stack_state *ss, struct lfds600_stack_element *se[LFDS600_STACK_PAC_SIZE], struct lfds600_freelist_element *fe, void *user_data ) +{ + assert( ss != NULL ); + assert( se != NULL ); + assert( fe != NULL ); + // TRD : user_data can be any value in its range + + lfds600_freelist_get_user_data_from_element( fe, (void **) &se[LFDS600_STACK_POINTER] ); + + se[LFDS600_STACK_COUNTER] = (struct lfds600_stack_element *) lfds600_abstraction_increment( (lfds600_atom_t *) &ss->aba_counter ); + + se[LFDS600_STACK_POINTER]->next[LFDS600_STACK_POINTER] = NULL; + se[LFDS600_STACK_POINTER]->next[LFDS600_STACK_COUNTER] = 0; + se[LFDS600_STACK_POINTER]->fe = fe; + se[LFDS600_STACK_POINTER]->user_data = user_data; + + return; +} + diff --git a/liblfds/liblfds6.0.0/liblfds600/src/lfds600_stack/lfds600_stack_push_pop.c b/liblfds/liblfds6.0.0/liblfds600/src/lfds600_stack/lfds600_stack_push_pop.c new file mode 100644 index 0000000..7345ea1 --- /dev/null +++ b/liblfds/liblfds6.0.0/liblfds600/src/lfds600_stack/lfds600_stack_push_pop.c @@ -0,0 +1,110 @@ +#include "lfds600_stack_internal.h" + + + + + +/****************************************************************************/ +int lfds600_stack_push( struct lfds600_stack_state *ss, void *user_data ) +{ + LFDS600_ALIGN(LFDS600_ALIGN_DOUBLE_POINTER) struct lfds600_stack_element + *se[LFDS600_STACK_PAC_SIZE]; + + assert( ss != NULL ); + // TRD : user_data can be NULL + + lfds600_stack_internal_new_element_from_freelist( ss, se, user_data ); + + if( se[LFDS600_STACK_POINTER] == NULL ) + return( 0 ); + + lfds600_stack_internal_push( ss, se ); + + return( 1 ); +} + + + + + +/****************************************************************************/ +int lfds600_stack_guaranteed_push( struct lfds600_stack_state *ss, void *user_data ) +{ + LFDS600_ALIGN(LFDS600_ALIGN_DOUBLE_POINTER) struct lfds600_stack_element + *se[LFDS600_STACK_PAC_SIZE]; + + assert( ss != NULL ); + // TRD : user_data can be NULL + + /* TRD : this function allocated a new lfds600_freelist element and uses that + to push onto the lfds600_stack, guaranteeing success (unless malloc() + fails of course) + */ + + lfds600_stack_internal_new_element( ss, se, user_data ); + + // TRD : malloc failed + if( se[LFDS600_STACK_POINTER] == NULL ) + return( 0 ); + + lfds600_stack_internal_push( ss, se ); + + return( 1 ); +} + + + + + +/****************************************************************************/ +void lfds600_stack_internal_push( struct lfds600_stack_state *ss, struct lfds600_stack_element *se[LFDS600_STACK_PAC_SIZE] ) +{ + LFDS600_ALIGN(LFDS600_ALIGN_DOUBLE_POINTER) struct lfds600_stack_element + *original_se_next[LFDS600_STACK_PAC_SIZE]; + + assert( ss != NULL ); + assert( se != NULL ); + + original_se_next[LFDS600_STACK_POINTER] = ss->top[LFDS600_STACK_POINTER]; + original_se_next[LFDS600_STACK_COUNTER] = ss->top[LFDS600_STACK_COUNTER]; + + do + { + se[LFDS600_STACK_POINTER]->next[LFDS600_STACK_POINTER] = original_se_next[LFDS600_STACK_POINTER]; + se[LFDS600_STACK_POINTER]->next[LFDS600_STACK_COUNTER] = original_se_next[LFDS600_STACK_COUNTER]; + } + while( 0 == lfds600_abstraction_dcas((volatile lfds600_atom_t *) ss->top, (lfds600_atom_t *) se, (lfds600_atom_t *) original_se_next) ); + + return; +} + + + + + +/****************************************************************************/ +int lfds600_stack_pop( struct lfds600_stack_state *ss, void **user_data ) +{ + LFDS600_ALIGN(LFDS600_ALIGN_DOUBLE_POINTER) struct lfds600_stack_element + *se[LFDS600_STACK_PAC_SIZE]; + + assert( ss != NULL ); + assert( user_data != NULL ); + + se[LFDS600_STACK_COUNTER] = ss->top[LFDS600_STACK_COUNTER]; + se[LFDS600_STACK_POINTER] = ss->top[LFDS600_STACK_POINTER]; + + do + { + if( se[LFDS600_STACK_POINTER] == NULL ) + return( 0 ); + } + while( 0 == lfds600_abstraction_dcas((volatile lfds600_atom_t *) ss->top, (lfds600_atom_t *) se[LFDS600_STACK_POINTER]->next, (lfds600_atom_t *) se) ); + + *user_data = se[LFDS600_STACK_POINTER]->user_data; + + lfds600_freelist_push( ss->fs, se[LFDS600_STACK_POINTER]->fe ); + + return( 1 ); +} + diff --git a/liblfds/liblfds6.0.0/liblfds600/src/lfds600_stack/lfds600_stack_query.c b/liblfds/liblfds6.0.0/liblfds600/src/lfds600_stack/lfds600_stack_query.c new file mode 100644 index 0000000..d792bb0 --- /dev/null +++ b/liblfds/liblfds6.0.0/liblfds600/src/lfds600_stack/lfds600_stack_query.c @@ -0,0 +1,30 @@ +#include "lfds600_stack_internal.h" + + + + + +/****************************************************************************/ +#pragma warning( disable : 4100 ) + +void lfds600_stack_query( struct lfds600_stack_state *ss, enum lfds600_stack_query_type query_type, void *query_input, void *query_output ) +{ + assert( ss != NULL ); + // TRD : query_type can be any value in its range + // TRD : query_iput can be NULL + assert( query_output != NULL ); + + switch( query_type ) + { + case LFDS600_STACK_QUERY_ELEMENT_COUNT: + assert( query_input == NULL ); + + lfds600_freelist_query( ss->fs, LFDS600_FREELIST_QUERY_ELEMENT_COUNT, NULL, query_output ); + break; + } + + return; +} + +#pragma warning( default : 4100 ) + diff --git a/liblfds/liblfds6.0.0/test/bin/empty_dir_placeholder_for_git b/liblfds/liblfds6.0.0/test/bin/empty_dir_placeholder_for_git new file mode 100644 index 0000000..e69de29 diff --git a/liblfds/liblfds6.0.0/test/building.txt b/liblfds/liblfds6.0.0/test/building.txt new file mode 100644 index 0000000..4f8c9bb --- /dev/null +++ b/liblfds/liblfds6.0.0/test/building.txt @@ -0,0 +1,25 @@ +building test +============= + +Windows (user-mode) +=================== +1. Use Microsoft Visual Studio 2008 or Visual C++ 2008 Express Edition + to load "test.sln". + +2. Use Microsoft Windows SDK and GNUmake to run makefile.windows (obviously + you'll need to have run the appropriate vcvars*.bat first; you can build + for both IA64, 64-bit and 32-bit - just run the correct vcvars batch file). + + Targets are "rel", "dbg" and "clean". You need to clean between switching + targets. + +Windows (kernel) +================ +No build supported, since this is a command line utility. + +Linux +===== +Use GNUmake to run "makefile.linux". Targets are "rel", "dbg" and +"clean". You need to clean between switching targets. + + diff --git a/liblfds/liblfds6.0.0/test/makefile.linux b/liblfds/liblfds6.0.0/test/makefile.linux new file mode 100644 index 0000000..540dbf1 --- /dev/null +++ b/liblfds/liblfds6.0.0/test/makefile.linux @@ -0,0 +1,81 @@ +##### paths ##### +BINDIR = bin +INCDIR = ../liblfds600/inc +LIBDIR = ../liblfds600/bin +OBJDIR = obj +SRCDIR = src + +##### misc ##### +QUIETLY = 1>nul 2>nul + +##### sources, objects and libraries ##### +BINNAME = test +BINARY = $(BINDIR)/$(BINNAME) +SRCDIRS = . +SOURCES = abstraction_cpu_count.c test_abstraction.c abstraction_thread_start.c abstraction_thread_wait.c benchmark_freelist.c benchmark_queue.c benchmark_ringbuffer.c benchmark_stack.c test_freelist.c main.c misc.c test_queue.c test_ringbuffer.c test_slist.c test_stack.c +OBJECTS = $(patsubst %.c,$(OBJDIR)/%.o,$(notdir $(SOURCES))) +SYSLIBS = -lpthread -lc -lm +USRLIBS = -llfds600 + +##### CPU variants ##### +GCCARCH = $(shell uname -m) + +ifeq ($(GCCARCH),x86_64) + GCCARCH = core2 +endif + +ifeq ($(findstring arm,$(GCCARCH)),arm) + GCCARCH = armv6k +endif + +##### tools ##### +MAKE = make +MFLAGS = + +DG = gcc +DGFLAGS = -MM -std=c99 -I"$(SRCDIR)" -I"$(INCDIR)" + +CC = gcc +CFBASE = -Wall -Wno-unknown-pragmas -std=c99 -march=$(GCCARCH) -c -I"$(SRCDIR)" -I"$(INCDIR)" +CFREL = -O2 -Wno-strict-aliasing +CFDBG = -O0 -g + +LD = gcc +LFBASE = -L"$(LIBDIR)" +LFREL = -O2 -s +LFDBG = -O0 -g + +##### variants ##### +CFLAGS = $(CFBASE) $(CFDBG) +LFLAGS = $(LFBASE) $(LFDBG) + +ifeq ($(MAKECMDGOALS),rel) + CFLAGS = $(CFBASE) $(CFREL) + LFLAGS = $(LFBASE) $(LFREL) +endif + +##### search paths ##### +vpath %.c $(patsubst %,$(SRCDIR)/%:,$(SRCDIRS)) + +##### implicit rules ##### +$(OBJDIR)/%.o : %.c + $(DG) $(DGFLAGS) $< >$(OBJDIR)/$*.d + $(CC) $(CFLAGS) -o $@ $< + +##### explicit rules ##### +$(BINARY) : $(OBJECTS) + $(LD) -o $(BINARY) $(LFLAGS) $(OBJECTS) $(USRLIBS) $(SYSLIBS) + chmod +x $(BINARY) + +##### phony ##### +.PHONY : clean rel dbg + +clean : + @rm -f $(BINDIR)/$(BINNAME) $(OBJDIR)/*.o $(OBJDIR)/*.d + +rel : $(BINARY) +dbg : $(BINARY) + +##### dependencies ##### +-include $(DEPENDS) + diff --git a/liblfds/liblfds6.0.0/test/makefile.windows b/liblfds/liblfds6.0.0/test/makefile.windows new file mode 100644 index 0000000..2c94a7a --- /dev/null +++ b/liblfds/liblfds6.0.0/test/makefile.windows @@ -0,0 +1,64 @@ +##### paths ##### +BINDIR = bin +INCDIR = ../liblfds600/inc +LIBDIR = ../liblfds600/bin +OBJDIR = obj +SRCDIR = src + +##### misc ##### +QUIETLY = 1>nul 2>nul + +##### sources, objects and libraries ##### +BINNAME = test +BINARY = $(BINDIR)\$(BINNAME).exe +SRCDIRS = . +SOURCES = abstraction_cpu_count.c test_abstraction.c abstraction_thread_start.c abstraction_thread_wait.c benchmark_freelist.c benchmark_queue.c benchmark_ringbuffer.c benchmark_stack.c test_freelist.c main.c misc.c test_queue.c test_ringbuffer.c test_slist.c test_stack.c +OBJECTS = $(patsubst %.c,$(OBJDIR)/%.obj,$(notdir $(SOURCES))) +SYSLIBS = kernel32.lib +USRLIBS = liblfds600.lib + +##### tools ##### +MAKE = make +MFLAGS = + +CC = cl +CFBASE = /nologo /W4 /WX /c "-I$(SRCDIR)" "-I$(INCLUDE)" "-I$(INCDIR)" "/Fd$(BINDIR)\$(BINNAME).pdb" /D UNICODE /D _UNICODE /DWIN32_LEAN_AND_MEAN /D_CRT_SECURE_NO_WARNINGS +CFREL = /Ox /DNDEBUG /MT +CFDBG = /Od /Gm /Zi /D_DEBUG /MTd + +LD = link +LFBASE = "/libpath:$(LIB)" "/libpath:$(LIBDIR)" /nologo /subsystem:console /nodefaultlib /nxcompat /wx +LFREL = /incremental:no +LFDBG = /debug "/pdb:$(BINDIR)\$(BINNAME).pdb" + +##### variants ##### +CFLAGS = $(CFBASE) $(CFDBG) +LFLAGS = $(LFBASE) $(LFDBG) +CLIB = libcmtd.lib + +ifeq ($(MAKECMDGOALS),rel) + CFLAGS = $(CFBASE) $(CFREL) + LFLAGS = $(LFBASE) $(LFREL) + CLIB = libcmt.lib +endif + +##### search paths ##### +vpath %.c $(patsubst %,$(SRCDIR)/%;,$(SRCDIRS)) + +##### implicit rules ##### +$(OBJDIR)/%.obj : %.c + $(CC) $(CFLAGS) "/Fo$@" $< + +##### explicit rules ##### +$(BINARY) : $(OBJECTS) + $(LD) $(LFLAGS) $(CLIB) $(SYSLIBS) $(USRLIBS) $(OBJECTS) /out:$(BINARY) + +##### phony ##### +.PHONY : clean rel dbg + +clean : + @erase /Q $(OBJDIR)\*.obj $(BINDIR)\$(BINNAME).* $(QUIETLY) + +rel : $(BINARY) +dbg : $(BINARY) + diff --git a/liblfds/liblfds6.0.0/test/obj/empty_dir_placeholder_for_git b/liblfds/liblfds6.0.0/test/obj/empty_dir_placeholder_for_git new file mode 100644 index 0000000..e69de29 diff --git a/liblfds/liblfds6.0.0/test/src/abstraction.h b/liblfds/liblfds6.0.0/test/src/abstraction.h new file mode 100644 index 0000000..e601f36 --- /dev/null +++ b/liblfds/liblfds6.0.0/test/src/abstraction.h @@ -0,0 +1,50 @@ +/***** defines *****/ +#if (defined _WIN32 && defined _MSC_VER && !defined WIN_KERNEL_BUILD) + /* TRD : any Windows (user-mode) on any CPU with the Microsoft C compiler + + _WIN32 indicates 64-bit or 32-bit Windows + _MSC_VER indicates Microsoft C compiler + !WIN_KERNEL_BUILD indicates Windows user-mode + */ + + #include + typedef HANDLE thread_state_t; + typedef DWORD thread_return_t; + #define CALLING_CONVENTION WINAPI +#endif + +#if (defined _WIN32 && defined _MSC_VER && defined WIN_KERNEL_BUILD) + /* TRD : any Windows (kernel-mode) on any CPU with the Microsoft C compiler + + _WIN32 indicates 64-bit or 32-bit Windows + _MSC_VER indicates Microsoft C compiler + WIN_KERNEL_BUILD indicates Windows kernel + */ + + #include + typedef HANDLE thread_state_t; + typedef VOID thread_return_t; + #define CALLING_CONVENTION +#endif + +#if (defined __unix__ && __GNUC__) + /* TRD : any UNIX on any CPU with GCC + + __unix__ indicates Solaris, Linux, HPUX, etc + __GNUC__ indicates GCC + */ + + #include + #include + typedef pthread_t thread_state_t; + typedef void * thread_return_t; + #define CALLING_CONVENTION +#endif + +typedef thread_return_t (CALLING_CONVENTION *thread_function_t)( void *thread_user_state ); + +/***** public prototypes *****/ +unsigned int abstraction_cpu_count( void ); +int abstraction_thread_start( thread_state_t *thread_state, unsigned int cpu, thread_function_t thread_function, void *thread_user_state ); +void abstraction_thread_wait( thread_state_t thread_state ); + diff --git a/liblfds/liblfds6.0.0/test/src/abstraction_cpu_count.c b/liblfds/liblfds6.0.0/test/src/abstraction_cpu_count.c new file mode 100644 index 0000000..42c3e13 --- /dev/null +++ b/liblfds/liblfds6.0.0/test/src/abstraction_cpu_count.c @@ -0,0 +1,81 @@ +#include "internal.h" + + + + + +/****************************************************************************/ +#if (defined _WIN32 && defined _MSC_VER && !defined WIN_KERNEL_BUILD) + + /* TRD : any Windows (user-mode) on any CPU with the Microsoft C compiler + + _WIN32 indicates 64-bit or 32-bit Windows + _MSC_VER indicates Microsoft C compiler + !WIN_KERNEL_BUILD indicates Windows user-mode + */ + + unsigned int abstraction_cpu_count() + { + SYSTEM_INFO + si; + + GetNativeSystemInfo( &si ); + + return( (unsigned int) si.dwNumberOfProcessors ); + } + +#endif + + + + + +/****************************************************************************/ +#if (defined _WIN32 && defined _MSC_VER && defined WIN_KERNEL_BUILD) + + /* TRD : any Windows on any CPU with the Microsoft C compiler + + _WIN32 indicates 64-bit or 32-bit Windows + _MSC_VER indicates Microsoft C compiler + WIN_KERNEL_BUILD indicates Windows kernel + */ + + unsigned int abstraction_cpu_count() + { + unsigned int + active_processor_count; + + active_processor_count = KeQueryActiveProcessorCount( NULL ); + + return( active_processor_count ); + } + +#endif + + + + + +/****************************************************************************/ +#if (defined __linux__ && __GNUC__) + + /* TRD : Linux on any CPU with GCC + + this function I believe is Linux specific and varies by UNIX flavour + + __linux__ indicates Linux + __GNUC__ indicates GCC + */ + + unsigned int abstraction_cpu_count() + { + long int + cpu_count; + + cpu_count = sysconf( _SC_NPROCESSORS_ONLN ); + + return( (unsigned int) cpu_count ); + } + +#endif + diff --git a/liblfds/liblfds6.0.0/test/src/abstraction_thread_start.c b/liblfds/liblfds6.0.0/test/src/abstraction_thread_start.c new file mode 100644 index 0000000..cdba0ce --- /dev/null +++ b/liblfds/liblfds6.0.0/test/src/abstraction_thread_start.c @@ -0,0 +1,127 @@ +#include "internal.h" + + + + + +/****************************************************************************/ +#if (defined _WIN32 && defined _MSC_VER && !defined WIN_KERNEL_BUILD) + + /* TRD : any Windows (user-mode) on any CPU with the Microsoft C compiler + + _WIN32 indicates 64-bit or 32-bit Windows + _MSC_VER indicates Microsoft C compiler + !WIN_KERNEL_BUILD indicates Windows user-mode + */ + + int abstraction_thread_start( thread_state_t *thread_state, unsigned int cpu, thread_function_t thread_function, void *thread_user_state ) + { + int + rv = 0; + + DWORD + thread_id; + + DWORD_PTR + affinity_mask, + result; + + assert( thread_state != NULL ); + // TRD : cpu can be any value in its range + assert( thread_function != NULL ); + // TRD : thread_user_state can be NULL + + affinity_mask = (DWORD_PTR) (1 << cpu); + + *thread_state = CreateThread( NULL, 0, thread_function, thread_user_state, NO_FLAGS, &thread_id ); + + result = SetThreadAffinityMask( *thread_state, affinity_mask ); + + if( *thread_state != NULL and result != 0 ) + rv = 1; + + return( rv ); + } + +#endif + + + + + +/****************************************************************************/ +#if (defined _WIN32 && defined _MSC_VER && defined WIN_KERNEL_BUILD) + + /* TRD : any Windows on any CPU with the Microsoft C compiler + + _WIN32 indicates 64-bit or 32-bit Windows + _MSC_VER indicates Microsoft C compiler + WIN_KERNEL_BUILD indicates Windows kernel + */ + + int abstraction_thread_start( thread_state_t *thread_state, unsigned int cpu, thread_function_t thread_function, void *thread_user_state ) + { + int + rv = 0; + + KAFFINITY + affinity_mask + + NTSTATUS + nts_create, + nts_affinity; + + assert( thread_state != NULL ); + // TRD : cpu can be any value in its range + assert( thread_function != NULL ); + // TRD : thread_user_state can be NULL + + affinity_mask = 1 << cpu; + + nts_create = PsCreateSystemThread( thread_state, THREAD_ALL_ACCESS, NULL, NULL, NULL, thread_function, thread_user_state ); + + nts_affinity = ZwSetInformationThread( thread_state, ThreadAffinityMask, &affinity_mask, sizeof(KAFFINITY) ); + + if( nts_create == STATUS_SUCCESS and nts_affinity == STATUS_SUCCESS ) + rv = 1; + + return( rv ); + } + +#endif + + + + + +/****************************************************************************/ +#if (defined __unix__) + + /* TRD : any UNIX on any CPU with any compiler + + I assumed pthreads is available on any UNIX. + + __unix__ indicates Solaris, Linux, HPUX, etc + */ + + int abstraction_thread_start( thread_state_t *thread_state, unsigned int cpu, thread_function_t thread_function, void *thread_user_state ) + { + int + rv = 0, + rv_create; + + assert( thread_state != NULL ); + // TRD : cpu can be any value in its range + assert( thread_function != NULL ); + // TRD : thread_user_state can be NULL + + rv_create = pthread_create( thread_state, NULL, thread_function, thread_user_state ); + + if( rv_create == 0 ) + rv = 1; + + return( rv ); + } + +#endif + diff --git a/liblfds/liblfds6.0.0/test/src/abstraction_thread_wait.c b/liblfds/liblfds6.0.0/test/src/abstraction_thread_wait.c new file mode 100644 index 0000000..ced5a5e --- /dev/null +++ b/liblfds/liblfds6.0.0/test/src/abstraction_thread_wait.c @@ -0,0 +1,71 @@ +#include "internal.h" + + + + + +/****************************************************************************/ +#if (defined _WIN32 && defined _MSC_VER && !defined WIN_KERNEL_BUILD) + + /* TRD : any Windows (user-mode) on any CPU with the Microsoft C compiler + + _WIN32 indicates 64-bit or 32-bit Windows + _MSC_VER indicates Microsoft C compiler + !WIN_KERNEL_BUILD indicates Windows user-mode + */ + + void abstraction_thread_wait( thread_state_t thread_state ) + { + WaitForSingleObject( thread_state, INFINITE ); + + return; + } + +#endif + + + + + +/****************************************************************************/ +#if (defined _WIN32 && defined _MSC_VER && defined WIN_KERNEL_BUILD) + + /* TRD : any Windows on any CPU with the Microsoft C compiler + + _WIN32 indicates 64-bit or 32-bit Windows + _MSC_VER indicates Microsoft C compiler + WIN_KERNEL_BUILD indicates Windows kernel + */ + + void abstraction_thread_wait( thread_state_t thread_state ) + { + KeWaitForSingleObject( thread_state, Executive, KernelMode, FALSE, NULL ); + + return; + } + +#endif + + + + + +/****************************************************************************/ +#if (defined __unix__) + + /* TRD : any UNIX on any CPU with any compiler + + I assumed pthreads is available on any UNIX. + + __unix__ indicates Solaris, Linux, HPUX, etc + */ + + void abstraction_thread_wait( thread_state_t thread_state ) + { + pthread_join( thread_state, NULL ); + + return; + } + +#endif + diff --git a/liblfds/liblfds6.0.0/test/src/benchmark_freelist.c b/liblfds/liblfds6.0.0/test/src/benchmark_freelist.c new file mode 100644 index 0000000..0683354 --- /dev/null +++ b/liblfds/liblfds6.0.0/test/src/benchmark_freelist.c @@ -0,0 +1,138 @@ +#include "internal.h" + + + + + +/****************************************************************************/ +void benchmark_lfds600_freelist( void ) +{ + unsigned int + loop, + thread_count, + cpu_count; + + struct lfds600_freelist_state + *fs; + + struct lfds600_freelist_benchmark + *fb; + + thread_state_t + *thread_handles; + + lfds600_atom_t + total_operations_for_full_test_for_all_cpus, + total_operations_for_full_test_for_all_cpus_for_one_cpu = 0; + + double + mean_operations_per_second_per_cpu, + difference_per_second_per_cpu, + total_difference_per_second_per_cpu, + std_dev_per_second_per_cpu, + scalability; + + /* TRD : here we benchmark the freelist + + the benchmark is to have a single freelist + where a worker thread busy-works popping and then pushing + */ + + cpu_count = abstraction_cpu_count(); + + thread_handles = (thread_state_t *) malloc( sizeof(thread_state_t) * cpu_count ); + + fb = (struct lfds600_freelist_benchmark *) malloc( sizeof(struct lfds600_freelist_benchmark) * cpu_count ); + + // TRD : print the benchmark ID and CSV header + printf( "\n" + "Release %d Freelist Benchmark #1\n" + "CPUs,total ops,mean ops/sec per CPU,standard deviation,scalability\n", LFDS600_RELEASE_NUMBER ); + + // TRD : we run CPU count times for scalability + for( thread_count = 1 ; thread_count <= cpu_count ; thread_count++ ) + { + // TRD : initialisation + lfds600_freelist_new( &fs, 1000, NULL, NULL ); + + for( loop = 0 ; loop < cpu_count ; loop++ ) + { + (fb+loop)->fs = fs; + (fb+loop)->operation_count = 0; + } + + // TRD : main test + for( loop = 0 ; loop < thread_count ; loop++ ) + abstraction_thread_start( &thread_handles[loop], loop, benchmark_lfds600_freelist_thread_pop_and_push, fb+loop ); + + for( loop = 0 ; loop < thread_count ; loop++ ) + abstraction_thread_wait( thread_handles[loop] ); + + // TRD : post test math + total_operations_for_full_test_for_all_cpus = 0; + total_difference_per_second_per_cpu = 0; + + for( loop = 0 ; loop < thread_count ; loop++ ) + total_operations_for_full_test_for_all_cpus += (fb+loop)->operation_count; + + mean_operations_per_second_per_cpu = ((double) total_operations_for_full_test_for_all_cpus / (double) thread_count) / (double) 10; + + if( thread_count == 1 ) + total_operations_for_full_test_for_all_cpus_for_one_cpu = total_operations_for_full_test_for_all_cpus; + + for( loop = 0 ; loop < thread_count ; loop++ ) + { + difference_per_second_per_cpu = ((double) (fb+loop)->operation_count / (double) 10) - mean_operations_per_second_per_cpu; + total_difference_per_second_per_cpu += difference_per_second_per_cpu * difference_per_second_per_cpu; + } + + std_dev_per_second_per_cpu = sqrt( (double) total_difference_per_second_per_cpu ); + + scalability = (double) total_operations_for_full_test_for_all_cpus / (double) (total_operations_for_full_test_for_all_cpus_for_one_cpu * thread_count); + + printf( "%u,%u,%.0f,%.0f,%0.2f\n", thread_count, (unsigned int) total_operations_for_full_test_for_all_cpus, mean_operations_per_second_per_cpu, std_dev_per_second_per_cpu, scalability ); + + // TRD : cleanup + lfds600_freelist_delete( fs, NULL, NULL ); + } + + free( fb ); + + free( thread_handles ); + + return; +} + + + + + +/****************************************************************************/ +thread_return_t CALLING_CONVENTION benchmark_lfds600_freelist_thread_pop_and_push( void *lfds600_freelist_benchmark ) +{ + struct lfds600_freelist_benchmark + *fb; + + struct lfds600_freelist_element + *fe; + + time_t + start_time; + + assert( lfds600_freelist_benchmark != NULL ); + + fb = (struct lfds600_freelist_benchmark *) lfds600_freelist_benchmark; + + time( &start_time ); + + while( time(NULL) < start_time + 10 ) + { + lfds600_freelist_pop( fb->fs, &fe ); + lfds600_freelist_push( fb->fs, fe ); + + fb->operation_count += 2; + } + + return( (thread_return_t) EXIT_SUCCESS ); +} + diff --git a/liblfds/liblfds6.0.0/test/src/benchmark_queue.c b/liblfds/liblfds6.0.0/test/src/benchmark_queue.c new file mode 100644 index 0000000..9e61a7c --- /dev/null +++ b/liblfds/liblfds6.0.0/test/src/benchmark_queue.c @@ -0,0 +1,142 @@ +#include "internal.h" + + + + + +/****************************************************************************/ +void benchmark_lfds600_queue( void ) +{ + unsigned int + loop, + thread_count, + cpu_count; + + struct lfds600_queue_state + *qs; + + struct lfds600_queue_benchmark + *qb; + + thread_state_t + *thread_handles; + + lfds600_atom_t + total_operations_for_full_test_for_all_cpus, + total_operations_for_full_test_for_all_cpus_for_one_cpu = 0; + + double + mean_operations_per_second_per_cpu, + difference_per_second_per_cpu, + total_difference_per_second_per_cpu, + std_dev_per_second_per_cpu, + scalability; + + /* TRD : here we benchmark the queue + + the benchmark is to have a single queue + where a worker thread busy-works dequeuing and then queuing + */ + + cpu_count = abstraction_cpu_count(); + + thread_handles = (thread_state_t *) malloc( sizeof(thread_state_t) * cpu_count ); + + qb = (struct lfds600_queue_benchmark *) malloc( sizeof(struct lfds600_queue_benchmark) * cpu_count ); + + // TRD : print the benchmark ID and CSV header + printf( "\n" + "Release %d Queue Benchmark #1\n" + "CPUs,total ops,mean ops/sec per CPU,standard deviation,scalability\n", LFDS600_RELEASE_NUMBER ); + + // TRD : we run CPU count times for scalability + for( thread_count = 1 ; thread_count <= cpu_count ; thread_count++ ) + { + // TRD : initialisation + lfds600_queue_new( &qs, 1000 ); + + for( loop = 0 ; loop < cpu_count ; loop++ ) + { + (qb+loop)->qs = qs; + (qb+loop)->operation_count = 0; + } + + // TRD : populate the queue (we don't actually use the user data) + for( loop = 0 ; loop < 500 ; loop++ ) + lfds600_queue_enqueue( qs, (void *) (lfds600_atom_t) loop ); + + // TRD : main test + for( loop = 0 ; loop < thread_count ; loop++ ) + abstraction_thread_start( &thread_handles[loop], loop, benchmark_lfds600_queue_thread_delfds600_queue_and_enqueue, qb+loop ); + + for( loop = 0 ; loop < thread_count ; loop++ ) + abstraction_thread_wait( thread_handles[loop] ); + + // TRD : post test math + total_operations_for_full_test_for_all_cpus = 0; + total_difference_per_second_per_cpu = 0; + + for( loop = 0 ; loop < thread_count ; loop++ ) + total_operations_for_full_test_for_all_cpus += (qb+loop)->operation_count; + + mean_operations_per_second_per_cpu = ((double) total_operations_for_full_test_for_all_cpus / (double) thread_count) / (double) 10; + + if( thread_count == 1 ) + total_operations_for_full_test_for_all_cpus_for_one_cpu = total_operations_for_full_test_for_all_cpus; + + for( loop = 0 ; loop < thread_count ; loop++ ) + { + difference_per_second_per_cpu = ((double) (qb+loop)->operation_count / (double) 10) - mean_operations_per_second_per_cpu; + total_difference_per_second_per_cpu += difference_per_second_per_cpu * difference_per_second_per_cpu; + } + + std_dev_per_second_per_cpu = sqrt( (double) total_difference_per_second_per_cpu ); + + scalability = (double) total_operations_for_full_test_for_all_cpus / (double) (total_operations_for_full_test_for_all_cpus_for_one_cpu * thread_count); + + printf( "%u,%u,%.0f,%.0f,%0.2f\n", thread_count, (unsigned int) total_operations_for_full_test_for_all_cpus, mean_operations_per_second_per_cpu, std_dev_per_second_per_cpu, scalability ); + + // TRD : cleanup + lfds600_queue_delete( qs, NULL, NULL ); + } + + free( qb ); + + free( thread_handles ); + + return; +} + + + + + +/****************************************************************************/ +thread_return_t CALLING_CONVENTION benchmark_lfds600_queue_thread_delfds600_queue_and_enqueue( void *lfds600_queue_benchmark ) +{ + struct lfds600_queue_benchmark + *qb; + + void + *user_data; + + time_t + start_time; + + assert( lfds600_queue_benchmark != NULL ); + + qb = (struct lfds600_queue_benchmark *) lfds600_queue_benchmark; + + time( &start_time ); + + while( time(NULL) < start_time + 10 ) + { + lfds600_queue_dequeue( qb->qs, &user_data ); + lfds600_queue_enqueue( qb->qs, user_data ); + + qb->operation_count += 2; + } + + return( (thread_return_t) EXIT_SUCCESS ); +} + diff --git a/liblfds/liblfds6.0.0/test/src/benchmark_ringbuffer.c b/liblfds/liblfds6.0.0/test/src/benchmark_ringbuffer.c new file mode 100644 index 0000000..7943268 --- /dev/null +++ b/liblfds/liblfds6.0.0/test/src/benchmark_ringbuffer.c @@ -0,0 +1,141 @@ +#include "internal.h" + + + + + +/****************************************************************************/ +void benchmark_lfds600_ringbuffer( void ) +{ + unsigned int + loop, + thread_count, + cpu_count; + + struct lfds600_ringbuffer_state + *rs; + + struct lfds600_ringbuffer_benchmark + *rb; + + thread_state_t + *thread_handles; + + lfds600_atom_t + total_operations_for_full_test_for_all_cpus, + total_operations_for_full_test_for_all_cpus_for_one_cpu = 0; + + double + mean_operations_per_second_per_cpu, + difference_per_second_per_cpu, + total_difference_per_second_per_cpu, + std_dev_per_second_per_cpu, + scalability; + + /* TRD : here we benchmark the ringbuffer + + the benchmark is to have a single ringbuffer + where a worker thread busy-works writing and then reading + */ + + cpu_count = abstraction_cpu_count(); + + thread_handles = (thread_state_t *) malloc( sizeof(thread_state_t) * cpu_count ); + + rb = (struct lfds600_ringbuffer_benchmark *) malloc( sizeof(struct lfds600_ringbuffer_benchmark) * cpu_count ); + + // TRD : print the benchmark ID and CSV header + printf( "\n" + "Release %d Ringbuffer Benchmark #1\n" + "CPUs,total ops,mean ops/sec per CPU,standard deviation,scalability\n", LFDS600_RELEASE_NUMBER ); + + // TRD : we run CPU count times for scalability + for( thread_count = 1 ; thread_count <= cpu_count ; thread_count++ ) + { + // TRD : initialisation + lfds600_ringbuffer_new( &rs, 1000, NULL, NULL ); + + for( loop = 0 ; loop < cpu_count ; loop++ ) + { + (rb+loop)->rs = rs; + (rb+loop)->operation_count = 0; + } + + // TRD : main test + for( loop = 0 ; loop < thread_count ; loop++ ) + abstraction_thread_start( &thread_handles[loop], loop, benchmark_lfds600_ringbuffer_thread_write_and_read, rb+loop ); + + for( loop = 0 ; loop < thread_count ; loop++ ) + abstraction_thread_wait( thread_handles[loop] ); + + // TRD : post test math + total_operations_for_full_test_for_all_cpus = 0; + total_difference_per_second_per_cpu = 0; + + for( loop = 0 ; loop < thread_count ; loop++ ) + total_operations_for_full_test_for_all_cpus += (rb+loop)->operation_count; + + mean_operations_per_second_per_cpu = ((double) total_operations_for_full_test_for_all_cpus / (double) thread_count) / (double) 10; + + if( thread_count == 1 ) + total_operations_for_full_test_for_all_cpus_for_one_cpu = total_operations_for_full_test_for_all_cpus; + + for( loop = 0 ; loop < thread_count ; loop++ ) + { + difference_per_second_per_cpu = ((double) (rb+loop)->operation_count / (double) 10) - mean_operations_per_second_per_cpu; + total_difference_per_second_per_cpu += difference_per_second_per_cpu * difference_per_second_per_cpu; + } + + std_dev_per_second_per_cpu = sqrt( (double) total_difference_per_second_per_cpu ); + + scalability = (double) total_operations_for_full_test_for_all_cpus / (double) (total_operations_for_full_test_for_all_cpus_for_one_cpu * thread_count); + + printf( "%u,%u,%.0f,%.0f,%0.2f\n", thread_count, (unsigned int) total_operations_for_full_test_for_all_cpus, mean_operations_per_second_per_cpu, std_dev_per_second_per_cpu, scalability ); + + // TRD : cleanup + lfds600_ringbuffer_delete( rs, NULL, NULL ); + } + + free( rb ); + + free( thread_handles ); + + return; +} + + + + + +/****************************************************************************/ +thread_return_t CALLING_CONVENTION benchmark_lfds600_ringbuffer_thread_write_and_read( void *lfds600_ringbuffer_benchmark ) +{ + struct lfds600_ringbuffer_benchmark + *rb; + + struct lfds600_freelist_element + *fe; + + time_t + start_time; + + assert( lfds600_ringbuffer_benchmark != NULL ); + + rb = (struct lfds600_ringbuffer_benchmark *) lfds600_ringbuffer_benchmark; + + time( &start_time ); + + while( time(NULL) < start_time + 10 ) + { + lfds600_ringbuffer_get_write_element( rb->rs, &fe, NULL ); + lfds600_ringbuffer_put_write_element( rb->rs, fe ); + + lfds600_ringbuffer_get_read_element( rb->rs, &fe ); + lfds600_ringbuffer_put_read_element( rb->rs, fe ); + + rb->operation_count += 2; + } + + return( (thread_return_t) EXIT_SUCCESS ); +} + diff --git a/liblfds/liblfds6.0.0/test/src/benchmark_stack.c b/liblfds/liblfds6.0.0/test/src/benchmark_stack.c new file mode 100644 index 0000000..da9bcf8 --- /dev/null +++ b/liblfds/liblfds6.0.0/test/src/benchmark_stack.c @@ -0,0 +1,138 @@ +#include "internal.h" + + + + + +/****************************************************************************/ +void benchmark_lfds600_stack( void ) +{ + unsigned int + loop, + thread_count, + cpu_count; + + struct lfds600_stack_state + *ss; + + struct lfds600_stack_benchmark + *sb; + + thread_state_t + *thread_handles; + + lfds600_atom_t + total_operations_for_full_test_for_all_cpus, + total_operations_for_full_test_for_all_cpus_for_one_cpu = 0; + + double + mean_operations_per_second_per_cpu, + difference_per_second_per_cpu, + total_difference_per_second_per_cpu, + std_dev_per_second_per_cpu, + scalability; + + /* TRD : here we benchmark the stack + + the benchmark is to have a single stack + where a worker thread busy-works pushing then popping + */ + + cpu_count = abstraction_cpu_count(); + + thread_handles = (thread_state_t *) malloc( sizeof(thread_state_t) * cpu_count ); + + sb = (struct lfds600_stack_benchmark *) malloc( sizeof(struct lfds600_stack_benchmark) * cpu_count ); + + // TRD : print the benchmark ID and CSV header + printf( "\n" + "Release %d Stack Benchmark #1\n" + "CPUs,total ops,mean ops/sec per CPU,standard deviation,scalability\n", LFDS600_RELEASE_NUMBER ); + + // TRD : we run CPU count times for scalability + for( thread_count = 1 ; thread_count <= cpu_count ; thread_count++ ) + { + // TRD : initialisation + lfds600_stack_new( &ss, 1000 ); + + for( loop = 0 ; loop < cpu_count ; loop++ ) + { + (sb+loop)->ss = ss; + (sb+loop)->operation_count = 0; + } + + // TRD : main test + for( loop = 0 ; loop < thread_count ; loop++ ) + abstraction_thread_start( &thread_handles[loop], loop, benchmark_lfds600_stack_thread_push_and_pop, sb+loop ); + + for( loop = 0 ; loop < thread_count ; loop++ ) + abstraction_thread_wait( thread_handles[loop] ); + + // TRD : post test math + total_operations_for_full_test_for_all_cpus = 0; + total_difference_per_second_per_cpu = 0; + + for( loop = 0 ; loop < thread_count ; loop++ ) + total_operations_for_full_test_for_all_cpus += (sb+loop)->operation_count; + + mean_operations_per_second_per_cpu = ((double) total_operations_for_full_test_for_all_cpus / (double) thread_count) / (double) 10; + + if( thread_count == 1 ) + total_operations_for_full_test_for_all_cpus_for_one_cpu = total_operations_for_full_test_for_all_cpus; + + for( loop = 0 ; loop < thread_count ; loop++ ) + { + difference_per_second_per_cpu = ((double) (sb+loop)->operation_count / (double) 10) - mean_operations_per_second_per_cpu; + total_difference_per_second_per_cpu += difference_per_second_per_cpu * difference_per_second_per_cpu; + } + + std_dev_per_second_per_cpu = sqrt( (double) total_difference_per_second_per_cpu ); + + scalability = (double) total_operations_for_full_test_for_all_cpus / (double) (total_operations_for_full_test_for_all_cpus_for_one_cpu * thread_count); + + printf( "%u,%u,%.0f,%.0f,%0.2f\n", thread_count, (unsigned int) total_operations_for_full_test_for_all_cpus, mean_operations_per_second_per_cpu, std_dev_per_second_per_cpu, scalability ); + + // TRD : cleanup + lfds600_stack_delete( ss, NULL, NULL ); + } + + free( sb ); + + free( thread_handles ); + + return; +} + + + + + +/****************************************************************************/ +thread_return_t CALLING_CONVENTION benchmark_lfds600_stack_thread_push_and_pop( void *lfds600_stack_benchmark ) +{ + struct lfds600_stack_benchmark + *sb; + + void + *user_data = NULL; + + time_t + start_time; + + assert( lfds600_stack_benchmark != NULL ); + + sb = (struct lfds600_stack_benchmark *) lfds600_stack_benchmark; + + time( &start_time ); + + while( time(NULL) < start_time + 10 ) + { + lfds600_stack_push( sb->ss, user_data ); + lfds600_stack_pop( sb->ss, &user_data ); + + sb->operation_count += 2; + } + + return( (thread_return_t) EXIT_SUCCESS ); +} + diff --git a/liblfds/liblfds6.0.0/test/src/internal.h b/liblfds/liblfds6.0.0/test/src/internal.h new file mode 100644 index 0000000..b0df332 --- /dev/null +++ b/liblfds/liblfds6.0.0/test/src/internal.h @@ -0,0 +1,104 @@ +/***** ANSI includes *****/ +#include +#include +#include +#include +#include +#include +#include + +/***** internal includes *****/ +#include "abstraction.h" + +/***** external includes *****/ +#include "liblfds600.h" + +/***** defines *****/ +#define and && +#define or || + +#define RAISED 1 +#define LOWERED 0 + +#define NO_FLAGS 0x0 + +/***** enums *****/ +enum lfds600_test_operation +{ + UNKNOWN, + HELP, + TEST, + BENCHMARK +}; + +/***** structs *****/ +#include "structures.h" + +/***** prototypes *****/ +int main( int argc, char **argv ); + +void internal_display_test_name( char *test_name ); +void internal_display_test_result( unsigned int number_name_dvs_pairs, ... ); +void internal_display_data_structure_validity( enum data_structure_validity dvs ); + +void benchmark_lfds600_freelist( void ); + thread_return_t CALLING_CONVENTION benchmark_lfds600_freelist_thread_pop_and_push( void *lfds600_freelist_benchmark ); + +void benchmark_lfds600_queue( void ); + thread_return_t CALLING_CONVENTION benchmark_lfds600_queue_thread_delfds600_queue_and_enqueue( void *lfds600_queue_benchmark ); + +void benchmark_lfds600_ringbuffer( void ); + thread_return_t CALLING_CONVENTION benchmark_lfds600_ringbuffer_thread_write_and_read( void *lfds600_ringbuffer_benchmark ); + +void benchmark_lfds600_stack( void ); + thread_return_t CALLING_CONVENTION benchmark_lfds600_stack_thread_push_and_pop( void *lfds600_stack_benchmark ); + +void test_lfds600_abstraction( void ); + void abstraction_test_increment( void ); + thread_return_t CALLING_CONVENTION abstraction_test_internal_thread_increment( void *shared_counter ); + thread_return_t CALLING_CONVENTION abstraction_test_internal_thread_atomic_increment( void *shared_counter ); + void abstraction_test_dcas( void ); + thread_return_t CALLING_CONVENTION abstraction_test_internal_thread_dcas( void *abstraction_test_dcas_state ); + +void test_lfds600_freelist( void ); + void freelist_test_internal_popping( void ); + int freelist_test_internal_popping_init( void **user_data, void *user_state ); + thread_return_t CALLING_CONVENTION freelist_test_internal_thread_popping( void *freelist_test_popping_state ); + void freelist_test_internal_pushing( void ); + int freelist_test_internal_pushing_init( void **user_data, void *user_state ); + void freelist_test_internal_pushing_delete( void *user_data, void *user_state ); + thread_return_t CALLING_CONVENTION freelist_test_internal_thread_pushing( void *freelist_test_pushing_state ); + void freelist_test_internal_popping_and_pushing( void ); + thread_return_t CALLING_CONVENTION freelist_test_internal_thread_popping_and_pushing_start_popping( void *freelist_test_popping_and_pushing_state ); + thread_return_t CALLING_CONVENTION freelist_test_internal_thread_popping_and_pushing_start_pushing( void *freelist_test_popping_and_pushing_state ); + void freelist_test_internal_rapid_popping_and_pushing( void ); + thread_return_t CALLING_CONVENTION freelist_test_internal_thread_rapid_popping_and_pushing( void *lfds600_freelist_state ); + +void test_lfds600_queue( void ); + void queue_test_enqueuing( void ); + thread_return_t CALLING_CONVENTION queue_test_internal_thread_simple_enqueuer( void *queue_test_enqueuing_state ); + void queue_test_dequeuing( void ); + thread_return_t CALLING_CONVENTION queue_test_internal_thread_simple_dequeuer( void *queue_test_dequeuing_state ); + void queue_test_enqueuing_and_dequeuing( void ); + thread_return_t CALLING_CONVENTION queue_test_internal_thread_enqueuer_and_dequeuer( void *queue_test_rapid_enqueuing_and_dequeuing_state ); + void queue_test_rapid_enqueuing_and_dequeuing( void ); + thread_return_t CALLING_CONVENTION queue_test_internal_thread_rapid_enqueuer_and_dequeuer( void *queue_test_rapid_enqueuing_and_dequeuing_state ); + +void test_lfds600_ringbuffer( void ); + void ringbuffer_test_reading( void ); + thread_return_t CALLING_CONVENTION ringbuffer_test_thread_simple_reader( void *ringbuffer_test_reading_state ); + void ringbuffer_test_writing( void ); + thread_return_t CALLING_CONVENTION ringbuffer_test_thread_simple_writer( void *ringbuffer_test_writing_state ); + void ringbuffer_test_reading_and_writing( void ); + thread_return_t CALLING_CONVENTION ringbuffer_test_thread_reader_writer( void *ringbuffer_test_reading_and_writing_state ); + +void test_lfds600_slist( void ); + thread_return_t CALLING_CONVENTION lfds600_slist_internal_thread_head_writer( void *lfds600_slist_thread_start_state ); + thread_return_t CALLING_CONVENTION lfds600_slist_internal_thread_after_writer( void *lfds600_slist_thread_start_state ); + thread_return_t CALLING_CONVENTION lfds600_slist_internal_thread_traverser( void *lfds600_slist_thread_start_state ); + thread_return_t CALLING_CONVENTION lfds600_slist_internal_thread_deleter_traverser( void *lfds600_slist_thread_start_state ); + +void test_lfds600_stack( void ); + thread_return_t CALLING_CONVENTION lfds600_stack_internal_thread_reader( void *lfds600_stack_state ); + thread_return_t CALLING_CONVENTION lfds600_stack_internal_thread_writer( void *lfds600_stack_state ); + diff --git a/liblfds/liblfds6.0.0/test/src/main.c b/liblfds/liblfds6.0.0/test/src/main.c new file mode 100644 index 0000000..e4a248e --- /dev/null +++ b/liblfds/liblfds6.0.0/test/src/main.c @@ -0,0 +1,74 @@ +#include "internal.h" + + + + + +/****************************************************************************/ +int main( int argc, char **argv ) +{ + enum lfds600_test_operation + operation = UNKNOWN; + + unsigned int + loop, + iterations = 1; + + assert( argc >= 1 ); + assert( argv != NULL ); + + if( argc == 1 or argc >= 4 ) + operation = HELP; + + if( operation == UNKNOWN ) + { + if( 0 == strcmp(*(argv+1), "test") ) + { + operation = TEST; + + // TRD : sscanf() may fail, but iterations is initialised to 1, so it's okay + if( argc == 3 ) + sscanf( *(argv+2), "%u", &iterations ); + } + + if( 0 == strcmp(*(argv+1), "benchmark") ) + operation = BENCHMARK; + } + + switch( operation ) + { + case UNKNOWN: + case HELP: + printf( "test [test|benchmark] [iterations]\n" + " test : run the test suite\n" + " benchmark : run the benchmark suite\n" + " iterations : optional, only applies to tests, default is 1\n" ); + break; + + case TEST: + for( loop = 1 ; loop < iterations+1 ; loop++ ) + { + printf( "\n" + "Test Iteration %02u\n" + "=================\n", loop ); + + test_lfds600_abstraction(); + test_lfds600_freelist(); + test_lfds600_queue(); + test_lfds600_ringbuffer(); + test_lfds600_slist(); + test_lfds600_stack(); + } + break; + + case BENCHMARK: + benchmark_lfds600_freelist(); + benchmark_lfds600_queue(); + benchmark_lfds600_ringbuffer(); + benchmark_lfds600_stack(); + break; + } + + return( EXIT_SUCCESS ); +} + diff --git a/liblfds/liblfds6.0.0/test/src/misc.c b/liblfds/liblfds6.0.0/test/src/misc.c new file mode 100644 index 0000000..9e8e5d7 --- /dev/null +++ b/liblfds/liblfds6.0.0/test/src/misc.c @@ -0,0 +1,124 @@ +#include "internal.h" + + + + + +/****************************************************************************/ +void internal_display_test_name( char *test_name ) +{ + assert( test_name != NULL ); + + printf( "%s...", test_name ); + fflush( stdout ); + + return; +} + + + + + +/****************************************************************************/ +void internal_display_test_result( unsigned int number_name_dvs_pairs, ... ) +{ + va_list + va; + + int + passed_flag = RAISED; + + unsigned int + loop; + + char + *name; + + enum data_structure_validity + dvs; + + // TRD : number_name_dvs_pairs can be any value in its range + + va_start( va, number_name_dvs_pairs ); + + for( loop = 0 ; loop < number_name_dvs_pairs ; loop++ ) + { + name = va_arg( va, char * ); + dvs = va_arg( va, enum data_structure_validity ); + + if( dvs != VALIDITY_VALID ) + { + passed_flag = LOWERED; + break; + } + } + + va_end( va ); + + if( passed_flag == RAISED ) + puts( "passed" ); + + if( passed_flag == LOWERED ) + { + printf( "failed (" ); + + va_start( va, number_name_dvs_pairs ); + + for( loop = 0 ; loop < number_name_dvs_pairs ; loop++ ) + { + name = va_arg( va, char * ); + dvs = va_arg( va, enum data_structure_validity ); + + printf( "%s ", name ); + internal_display_data_structure_validity( dvs ); + + if( loop+1 < number_name_dvs_pairs ) + printf( ", " ); + } + + va_end( va ); + + printf( ")\n" ); + } + + return; +} + + + + + +/****************************************************************************/ +void internal_display_data_structure_validity( enum data_structure_validity dvs ) +{ + char + *string = NULL; + + switch( dvs ) + { + case VALIDITY_VALID: + string = "valid"; + break; + + case VALIDITY_INVALID_LOOP: + string = "invalid - loop detected"; + break; + + case VALIDITY_INVALID_MISSING_ELEMENTS: + string = "invalid - missing elements"; + break; + + case VALIDITY_INVALID_ADDITIONAL_ELEMENTS: + string = "invalid - additional elements"; + break; + + case VALIDITY_INVALID_TEST_DATA: + string = "invalid - invalid test data"; + break; + } + + printf( "%s", string ); + + return; +} + diff --git a/liblfds/liblfds6.0.0/test/src/structures.h b/liblfds/liblfds6.0.0/test/src/structures.h new file mode 100644 index 0000000..00dd5c5 --- /dev/null +++ b/liblfds/liblfds6.0.0/test/src/structures.h @@ -0,0 +1,190 @@ +/***** structs *****/ +#pragma pack( push, LFDS600_ALIGN_DOUBLE_POINTER ) + +/***** abstraction tests *****/ +struct abstraction_test_dcas_state +{ + volatile lfds600_atom_t + *shared_counter; + + lfds600_atom_t + local_counter; +}; + +/***** freelist tests *****/ +struct freelist_test_popping_state +{ + struct lfds600_freelist_state + *fs, + *fs_thread_local; +}; + +struct freelist_test_pushing_state +{ + lfds600_atom_t + thread_number; + + struct lfds600_freelist_state + *source_fs, + *fs; +}; + +struct freelist_test_popping_and_pushing_state +{ + struct lfds600_freelist_state + *local_fs, + *fs; +}; + +struct freelist_test_counter_and_thread_number +{ + lfds600_atom_t + thread_number; + + unsigned long long int + counter; +}; + +/***** queue tests *****/ +struct queue_test_enqueuing_state +{ + struct lfds600_queue_state + *qs; + + lfds600_atom_t + counter; +}; + +struct queue_test_dequeuing_state +{ + struct lfds600_queue_state + *qs; + + int + error_flag; +}; + +struct queue_test_enqueuing_and_dequeuing_state +{ + struct lfds600_queue_state + *qs; + + lfds600_atom_t + counter, + thread_number, + *per_thread_counters; + + unsigned int + cpu_count; + + int + error_flag; +}; + +struct queue_test_rapid_enqueuing_and_dequeuing_state +{ + struct lfds600_queue_state + *qs; + + lfds600_atom_t + counter; +}; + +/***** ringbuffer tests *****/ +struct ringbuffer_test_reading_state +{ + struct lfds600_ringbuffer_state + *rs; + + int + error_flag; + + lfds600_atom_t + read_count; +}; + +struct ringbuffer_test_writing_state +{ + struct lfds600_ringbuffer_state + *rs; + + lfds600_atom_t + write_count; +}; + +struct ringbuffer_test_reading_and_writing_state +{ + struct lfds600_ringbuffer_state + *rs; + + lfds600_atom_t + counter, + *per_thread_counters; + + unsigned int + cpu_count; + + int + error_flag; +}; + +/***** slist tests *****/ +struct lfds600_slist_thread_start_state +{ + struct lfds600_slist_state + *ss; + + struct lfds600_slist_element + *se; + + time_t + duration; + + unsigned long int + iteration_modulo; +}; + +/***** stack tests *****/ + +/***** freelist benchmarks *****/ +struct lfds600_freelist_benchmark +{ + struct lfds600_freelist_state + *fs; + + lfds600_atom_t + operation_count; +}; + +/***** queue benchmarks *****/ +struct lfds600_queue_benchmark +{ + struct lfds600_queue_state + *qs; + + lfds600_atom_t + operation_count; +}; + +/***** ringbuffer benchmarks *****/ +struct lfds600_ringbuffer_benchmark +{ + struct lfds600_ringbuffer_state + *rs; + + lfds600_atom_t + operation_count; +}; + +/***** stack benchmarks *****/ +struct lfds600_stack_benchmark +{ + struct lfds600_stack_state + *ss; + + lfds600_atom_t + operation_count; +}; + +#pragma pack( pop ) + diff --git a/liblfds/liblfds6.0.0/test/src/test_abstraction.c b/liblfds/liblfds6.0.0/test/src/test_abstraction.c new file mode 100644 index 0000000..2bb2f46 --- /dev/null +++ b/liblfds/liblfds6.0.0/test/src/test_abstraction.c @@ -0,0 +1,246 @@ +#include "internal.h" + + + + + +/****************************************************************************/ +void test_lfds600_abstraction( void ) +{ + printf( "\n" + "Abstraction Tests\n" + "=================\n" ); + + abstraction_test_increment(); + abstraction_test_dcas(); + + return; +} + + + + + +/****************************************************************************/ +void abstraction_test_increment( void ) +{ + unsigned int + loop, + cpu_count; + + thread_state_t + *thread_handles; + + lfds600_atom_t + shared_counter = 0, + atomic_shared_counter = 0; + + /* TRD : here we test lfds600_abstraction_increment + + first, we run one thread per CPU where each thread increments + a shared counter 10,000,000 times - however, this first test + does NOT use atomic increment; it uses "++" + + second, we repeat the exercise, but this time using + lfds600_abstraction_increment() + + if the final value in the first test is less than (10,000,000*cpu_count) + then the system is sensitive to non-atomic increments; this means if + our atomic version of the test passes, we can have some degree of confidence + that it works + + if the final value in the first test is in fact correct, then we can't know + that our atomic version has changed anything + + and of course if the final value in the atomic test is wrong, we know things + are broken + */ + + internal_display_test_name( "Atomic increment" ); + + cpu_count = abstraction_cpu_count(); + + thread_handles = malloc( sizeof(thread_state_t) * cpu_count ); + + // TRD : non-atomic + for( loop = 0 ; loop < cpu_count ; loop++ ) + abstraction_thread_start( &thread_handles[loop], loop, abstraction_test_internal_thread_increment, &shared_counter ); + + for( loop = 0 ; loop < cpu_count ; loop++ ) + abstraction_thread_wait( thread_handles[loop] ); + + // TRD : atomic + for( loop = 0 ; loop < cpu_count ; loop++ ) + abstraction_thread_start( &thread_handles[loop], loop, abstraction_test_internal_thread_atomic_increment, &atomic_shared_counter ); + + for( loop = 0 ; loop < cpu_count ; loop++ ) + abstraction_thread_wait( thread_handles[loop] ); + + free( thread_handles ); + + // TRD : results + if( shared_counter < (10000000 * cpu_count) and atomic_shared_counter == (10000000 * cpu_count) ) + puts( "passed" ); + + if( shared_counter == (10000000 * cpu_count) and atomic_shared_counter == (10000000 * cpu_count) ) + puts( "indeterminate" ); + + if( atomic_shared_counter < (10000000 * cpu_count) ) + puts( "failed" ); + + return; +} + + + + + +/****************************************************************************/ +thread_return_t CALLING_CONVENTION abstraction_test_internal_thread_increment( void *shared_counter ) +{ + volatile lfds600_atom_t + count = 0; + + /* TRD : lfds600_atom_t must be volatile or the compiler + optimizes it away into a single store + */ + + assert( shared_counter != NULL ); + + while( count++ < 10000000 ) + (*(lfds600_atom_t *) shared_counter)++; + + return( (thread_return_t) EXIT_SUCCESS ); +} + + + + + +/****************************************************************************/ +thread_return_t CALLING_CONVENTION abstraction_test_internal_thread_atomic_increment( void *shared_counter ) +{ + lfds600_atom_t + count = 0; + + assert( shared_counter != NULL ); + + while( count++ < 10000000 ) + lfds600_abstraction_increment( shared_counter ); + + return( (thread_return_t) EXIT_SUCCESS ); +} + + + + + +/****************************************************************************/ +void abstraction_test_dcas( void ) +{ + unsigned int + loop, + cpu_count; + + thread_state_t + *thread_handles; + + struct abstraction_test_dcas_state + *atds; + + LFDS600_ALIGN(LFDS600_ALIGN_DOUBLE_POINTER) volatile lfds600_atom_t + shared_counter[2] = { 0, 0 }; + + lfds600_atom_t + local_total = 0; + + /* TRD : here we test lfds600_abstraction_dcas + + we run one thread per CPU + we use lfds600_abstraction_dcas() to increment a shared counter + every time a thread successfully increments the counter, + it increments a thread local counter + the threads run for ten seconds + after the threads finish, we total the local counters + they should equal the shared counter + */ + + internal_display_test_name( "Atomic DCAS" ); + + cpu_count = abstraction_cpu_count(); + + atds = malloc( sizeof(struct abstraction_test_dcas_state) * cpu_count ); + + for( loop = 0 ; loop < cpu_count ; loop++ ) + { + (atds+loop)->shared_counter = shared_counter; + (atds+loop)->local_counter = 0; + } + + thread_handles = malloc( sizeof(thread_state_t) * cpu_count ); + + for( loop = 0 ; loop < cpu_count ; loop++ ) + abstraction_thread_start( &thread_handles[loop], loop, abstraction_test_internal_thread_dcas, atds+loop ); + + for( loop = 0 ; loop < cpu_count ; loop++ ) + abstraction_thread_wait( thread_handles[loop] ); + + free( thread_handles ); + + // TRD : results + for( loop = 0 ; loop < cpu_count ; loop++ ) + local_total += (atds+loop)->local_counter; + + if( local_total == shared_counter[0] ) + puts( "passed" ); + + if( local_total != shared_counter[0] ) + puts( "failed" ); + + // TRD : cleanup + free( atds ); + + return; +} + + + + + +/****************************************************************************/ +thread_return_t CALLING_CONVENTION abstraction_test_internal_thread_dcas( void *abstraction_test_dcas_state ) +{ + struct abstraction_test_dcas_state + *atds; + + time_t + start_time; + + LFDS600_ALIGN(LFDS600_ALIGN_DOUBLE_POINTER) lfds600_atom_t + exchange[2], + compare[2]; + + assert( abstraction_test_dcas_state != NULL ); + + atds = (struct abstraction_test_dcas_state *) abstraction_test_dcas_state; + + time( &start_time ); + + while( time(NULL) < start_time + 10 ) + { + compare[0] = *atds->shared_counter; + compare[1] = *(atds->shared_counter+1); + + do + { + exchange[0] = compare[0] + 1; + exchange[1] = compare[1]; + } + while( 0 == lfds600_abstraction_dcas(atds->shared_counter, exchange, compare) ); + + atds->local_counter++; + } + + return( (thread_return_t) EXIT_SUCCESS ); +} + diff --git a/liblfds/liblfds6.0.0/test/src/test_freelist.c b/liblfds/liblfds6.0.0/test/src/test_freelist.c new file mode 100644 index 0000000..6714c2e --- /dev/null +++ b/liblfds/liblfds6.0.0/test/src/test_freelist.c @@ -0,0 +1,662 @@ +#include "internal.h" + + + + + +/****************************************************************************/ +void test_lfds600_freelist( void ) +{ + printf( "\n" + "Freelist Tests\n" + "==============\n" ); + + freelist_test_internal_popping(); + freelist_test_internal_pushing(); + freelist_test_internal_popping_and_pushing(); + freelist_test_internal_rapid_popping_and_pushing(); + + return; +} + + + + + +/****************************************************************************/ +void freelist_test_internal_popping( void ) +{ + unsigned int + loop, + cpu_count, + count; + + thread_state_t + *thread_handles; + + enum data_structure_validity + dvs = VALIDITY_VALID; + + struct lfds600_freelist_state + *fs; + + struct lfds600_freelist_element + *fe; + + struct freelist_test_popping_state + *ftps; + + unsigned int + *found_count; + + /* TRD : we create a freelist with 1,000,000 elements + + the creation function runs in a single thread and creates + and pushes those elements onto the freelist + + each element contains a void pointer which is its element number + + we then run one thread per CPU + where each thread loops, popping as quickly as possible + each popped element is pushed onto a thread-local freelist + + the threads run till the source freelist is empty + + we then check the thread-local freelists + we should find we have every element + + then tidy up + */ + + internal_display_test_name( "Popping" ); + + cpu_count = abstraction_cpu_count(); + + lfds600_freelist_new( &fs, 1000000, freelist_test_internal_popping_init, NULL ); + ftps = malloc( sizeof(struct freelist_test_popping_state) * cpu_count ); + for( loop = 0 ; loop < cpu_count ; loop++ ) + { + (ftps+loop)->fs = fs; + lfds600_freelist_new( &(ftps+loop)->fs_thread_local, 0, NULL, NULL ); + } + + thread_handles = malloc( sizeof(thread_state_t) * cpu_count ); + + for( loop = 0 ; loop < cpu_count ; loop++ ) + abstraction_thread_start( &thread_handles[loop], loop, freelist_test_internal_thread_popping, ftps+loop ); + + for( loop = 0 ; loop < cpu_count ; loop++ ) + abstraction_thread_wait( thread_handles[loop] ); + + free( thread_handles ); + + // TRD : now we check the thread-local freelists + found_count = malloc( sizeof(unsigned int) * 1000000 ); + for( loop = 0 ; loop < 1000000 ; loop++ ) + *(found_count+loop) = 0; + + for( loop = 0 ; loop < cpu_count ; loop++ ) + { + while( lfds600_freelist_pop((ftps+loop)->fs_thread_local, &fe) ) + { + lfds600_freelist_get_user_data_from_element( fe, (void **) &count ); + (*(found_count+count))++; + lfds600_freelist_push( fs, fe ); + } + } + + for( loop = 0 ; loop < 1000000 and dvs == VALIDITY_VALID ; loop++ ) + { + if( *(found_count+loop) == 0 ) + dvs = VALIDITY_INVALID_MISSING_ELEMENTS; + + if( *(found_count+loop) > 1 ) + dvs = VALIDITY_INVALID_ADDITIONAL_ELEMENTS; + } + + // TRD : cleanup + free( found_count ); + for( loop = 0 ; loop < cpu_count ; loop++ ) + lfds600_freelist_delete( (ftps+loop)->fs_thread_local, NULL, NULL ); + lfds600_freelist_delete( fs, NULL, NULL ); + + // TRD : print the test result + internal_display_test_result( 1, "freelist", dvs ); + + return; +} + + + + + +/****************************************************************************/ +#pragma warning( disable : 4100 ) + +int freelist_test_internal_popping_init( void **user_data, void *user_state ) +{ + static lfds600_atom_t + count = 0; + + assert( user_data != NULL ); + assert( user_state == NULL ); + + *(lfds600_atom_t *) user_data = count++; + + return( 1 ); +} + +#pragma warning( default : 4100 ) + + + + + +/****************************************************************************/ +thread_return_t CALLING_CONVENTION freelist_test_internal_thread_popping( void *freelist_test_popping_state ) +{ + struct freelist_test_popping_state + *ftps; + + struct lfds600_freelist_element + *fe; + + assert( freelist_test_popping_state != NULL ); + + ftps = (struct freelist_test_popping_state *) freelist_test_popping_state; + + while( lfds600_freelist_pop(ftps->fs, &fe) ) + lfds600_freelist_push( ftps->fs_thread_local, fe ); + + return( (thread_return_t) EXIT_SUCCESS ); +} + + + + + +/****************************************************************************/ +void freelist_test_internal_pushing( void ) +{ + unsigned int + loop, + cpu_count; + + thread_state_t + *thread_handles; + + enum data_structure_validity + dvs; + + struct freelist_test_pushing_state + *ftps; + + struct lfds600_freelist_element + *fe; + + struct lfds600_freelist_state + *fs, + *cleanup_fs; + + struct freelist_test_counter_and_thread_number + *cnt, + *counter_and_number_trackers; + + struct lfds600_validation_info + vi = { 1000000, 1000000 }; + + /* TRD : we create an empty freelist, which we will push to + + we then create one freelist per CPU, where this freelist + contains 1,000,000/cpu_count number of elements and + each element is an incrementing counter and unique ID + (from 0 to number of CPUs) + + we then start one thread per CPU, where each thread is + given one of the populated freelists and pops from that + to push to the empty freelist + + the reason for this is to achieve memory pre-allocation + which allows the pushing threads to run at maximum speed + + the threads end when their freelists are empty + + we then fully pop the now populated main freelist (onto + a second freelist, so we can cleanly free all memory), + checking that the counts increment on a per unique ID basis + and that the number of elements we pop equals 1,000,000 + (since each element has an incrementing counter which is + unique on a per unique ID basis, we can know we didn't lose + any elements) + */ + + internal_display_test_name( "Pushing" ); + + cpu_count = abstraction_cpu_count(); + + ftps = malloc( sizeof(struct freelist_test_pushing_state) * cpu_count ); + + lfds600_freelist_new( &fs, 0, NULL, NULL ); + + for( loop = 0 ; loop < cpu_count ; loop++ ) + { + (ftps+loop)->thread_number = (lfds600_atom_t) loop; + lfds600_freelist_new( &(ftps+loop)->source_fs, 1000000 / cpu_count, freelist_test_internal_pushing_init, (void *) (lfds600_atom_t) loop ); + (ftps+loop)->fs = fs; + } + + thread_handles = malloc( sizeof(thread_state_t) * cpu_count ); + + for( loop = 0 ; loop < cpu_count ; loop++ ) + abstraction_thread_start( &thread_handles[loop], loop, freelist_test_internal_thread_pushing, ftps+loop ); + + for( loop = 0 ; loop < cpu_count ; loop++ ) + abstraction_thread_wait( thread_handles[loop] ); + + free( thread_handles ); + + // TRD : now fully pop and verify the main freelist + lfds600_freelist_new( &cleanup_fs, 0, NULL, NULL ); + + counter_and_number_trackers = malloc( sizeof(struct freelist_test_counter_and_thread_number) * cpu_count ); + + for( loop = 0 ; loop < cpu_count ; loop++ ) + { + (counter_and_number_trackers+loop)->counter = (1000000 / cpu_count) * loop; + (counter_and_number_trackers+loop)->thread_number = (lfds600_atom_t) loop; + } + + lfds600_freelist_query( fs, LFDS600_FREELIST_QUERY_VALIDATE, &vi, (void *) &dvs ); + + while( dvs == VALIDITY_VALID and lfds600_freelist_pop(fs, &fe) ) + { + static int count = 0; + + lfds600_freelist_get_user_data_from_element( fe, (void **) &cnt ); + + if( cnt->counter != (counter_and_number_trackers+cnt->thread_number)->counter++ ) + dvs = VALIDITY_INVALID_MISSING_ELEMENTS; + + lfds600_freelist_push( cleanup_fs, fe ); + + count++; + } + + // TRD : clean up + free( counter_and_number_trackers ); + + for( loop = 0 ; loop < cpu_count ; loop++ ) + lfds600_freelist_delete( (ftps+loop)->source_fs, NULL, NULL ); + + free( ftps ); + + lfds600_freelist_delete( cleanup_fs, freelist_test_internal_pushing_delete, NULL ); + lfds600_freelist_delete( fs, NULL, NULL ); + + // TRD : print the test result + internal_display_test_result( 1, "freelist", dvs ); + + return; +} + + + + + +/****************************************************************************/ +int freelist_test_internal_pushing_init( void **user_data, void *user_state ) +{ + struct freelist_test_counter_and_thread_number + *ftcatn; + + static lfds600_atom_t + counter = 0; + + assert( user_data != NULL ); + // TRD : user_state is being used as an integer type + + *user_data = malloc( sizeof(struct freelist_test_counter_and_thread_number) ); + + ftcatn = (struct freelist_test_counter_and_thread_number *) *user_data; + + ftcatn->counter = counter++; + ftcatn->thread_number = (lfds600_atom_t) user_state; + + return( 1 ); +} + + + + + +/****************************************************************************/ +#pragma warning( disable : 4100 ) + +void freelist_test_internal_pushing_delete( void *user_data, void *user_state ) +{ + assert( user_data != NULL ); + assert( user_state == NULL ); + + free( user_data ); + + return; +} + +#pragma warning( default : 4100 ) + + + + + +/****************************************************************************/ +thread_return_t CALLING_CONVENTION freelist_test_internal_thread_pushing( void *freelist_test_pushing_state ) +{ + struct freelist_test_pushing_state + *ftps; + + struct lfds600_freelist_element + *fe; + + assert( freelist_test_pushing_state != NULL ); + + ftps = (struct freelist_test_pushing_state *) freelist_test_pushing_state; + + while( lfds600_freelist_pop(ftps->source_fs, &fe) ) + lfds600_freelist_push( ftps->fs, fe ); + + return( (thread_return_t) EXIT_SUCCESS ); +} + + + + + +/****************************************************************************/ +void freelist_test_internal_popping_and_pushing( void ) +{ + unsigned int + loop, + cpu_count; + + thread_state_t + *thread_handles; + + enum data_structure_validity + dvs; + + struct lfds600_freelist_state + *fs; + + struct freelist_test_popping_and_pushing_state + *pps; + + struct lfds600_validation_info + vi; + + /* TRD : we have two threads per CPU + the threads loop for ten seconds + the first thread pushes 100000 elements then pops 100000 elements + the second thread pops 100000 elements then pushes 100000 elements + all pushes and pops go onto the single main freelist + + after time is up, all threads push what they have remaining onto + the main freelist + + we then validate the main freelist + */ + + internal_display_test_name( "Popping and pushing (10 seconds)" ); + + cpu_count = abstraction_cpu_count(); + + lfds600_freelist_new( &fs, 100000 * cpu_count, NULL, NULL ); + + pps = malloc( sizeof(struct freelist_test_popping_and_pushing_state) * cpu_count * 2 ); + + for( loop = 0 ; loop < cpu_count ; loop++ ) + { + (pps+loop)->fs = fs; + lfds600_freelist_new( &(pps+loop)->local_fs, 0, NULL, NULL ); + + (pps+loop+cpu_count)->fs = fs; + lfds600_freelist_new( &(pps+loop+cpu_count)->local_fs, 100000, NULL, NULL ); + } + + thread_handles = malloc( sizeof(thread_state_t) * cpu_count * 2 ); + + for( loop = 0 ; loop < cpu_count ; loop++ ) + { + abstraction_thread_start( &thread_handles[loop], loop, freelist_test_internal_thread_popping_and_pushing_start_popping, pps+loop ); + abstraction_thread_start( &thread_handles[loop+cpu_count], loop, freelist_test_internal_thread_popping_and_pushing_start_pushing, pps+loop+cpu_count ); + } + + for( loop = 0 ; loop < cpu_count * 2 ; loop++ ) + abstraction_thread_wait( thread_handles[loop] ); + + free( thread_handles ); + + for( loop = 0 ; loop < cpu_count * 2 ; loop++ ) + lfds600_freelist_delete( (pps+loop)->local_fs, NULL, NULL ); + + free( pps ); + + vi.min_elements = vi.max_elements = 100000 * cpu_count * 2; + + lfds600_freelist_query( fs, LFDS600_FREELIST_QUERY_VALIDATE, (void *) &vi, (void *) &dvs ); + + lfds600_freelist_delete( fs, NULL, NULL ); + + // TRD : print the test result + internal_display_test_result( 1, "freelist", dvs ); + + return; +} + + + + + + +/****************************************************************************/ +thread_return_t CALLING_CONVENTION freelist_test_internal_thread_popping_and_pushing_start_popping( void *freelist_test_popping_and_pushing_state ) +{ + struct freelist_test_popping_and_pushing_state + *pps; + + struct lfds600_freelist_element + *fe; + + time_t + start_time; + + unsigned int + count; + + assert( freelist_test_popping_and_pushing_state != NULL ); + + pps = (struct freelist_test_popping_and_pushing_state *) freelist_test_popping_and_pushing_state; + + time( &start_time ); + + while( time(NULL) < start_time + 10 ) + { + count = 0; + + while( count < 100000 ) + { + lfds600_freelist_pop( pps->fs, &fe ); + + if( fe != NULL ) + { + lfds600_freelist_push( pps->local_fs, fe ); + count++; + } + } + + while( lfds600_freelist_pop(pps->local_fs, &fe) ) + lfds600_freelist_push( pps->fs, fe ); + } + + return( (thread_return_t) EXIT_SUCCESS ); +} + + + + + +/****************************************************************************/ +thread_return_t CALLING_CONVENTION freelist_test_internal_thread_popping_and_pushing_start_pushing( void *freelist_test_popping_and_pushing_state ) +{ + struct freelist_test_popping_and_pushing_state + *pps; + + struct lfds600_freelist_element + *fe; + + time_t + start_time; + + unsigned int + count; + + assert( freelist_test_popping_and_pushing_state != NULL ); + + pps = (struct freelist_test_popping_and_pushing_state *) freelist_test_popping_and_pushing_state; + + time( &start_time ); + + while( time(NULL) < start_time + 10 ) + { + while( lfds600_freelist_pop(pps->local_fs, &fe) ) + lfds600_freelist_push( pps->fs, fe ); + + count = 0; + + while( count < 1000 ) + { + lfds600_freelist_pop( pps->fs, &fe ); + + if( fe != NULL ) + { + lfds600_freelist_push( pps->local_fs, fe ); + count++; + } + } + } + + // TRD : now push whatever we have in our local freelist + while( lfds600_freelist_pop(pps->local_fs, &fe) ) + lfds600_freelist_push( pps->fs, fe ); + + return( (thread_return_t) EXIT_SUCCESS ); +} + + + + + +/****************************************************************************/ +void freelist_test_internal_rapid_popping_and_pushing( void ) +{ + unsigned int + loop, + cpu_count; + + thread_state_t + *thread_handles; + + struct lfds600_freelist_state + *fs; + + struct lfds600_validation_info + vi; + + enum data_structure_validity + dvs; + + /* TRD : in these tests there is a fundamental antagonism between + how much checking/memory clean up that we do and the + likelyhood of collisions between threads in their lock-free + operations + + the lock-free operations are very quick; if we do anything + much at all between operations, we greatly reduce the chance + of threads colliding + + so we have some tests which do enough checking/clean up that + they can tell the freelist is valid and don't leak memory + and here, this test now is one of those which does minimal + checking - in fact, the nature of the test is that you can't + do any real checking - but goes very quickly + + what we do is create a small freelist and then run one thread + per CPU, where each thread simply pops and then immediately + pushes + + the test runs for ten seconds + + after the test is done, the only check we do is to traverse + the freelist, checking for loops and ensuring the number of + elements is correct + */ + + internal_display_test_name( "Rapid popping and pushing (10 seconds)" ); + + cpu_count = abstraction_cpu_count(); + + lfds600_freelist_new( &fs, cpu_count, NULL, NULL ); + + thread_handles = malloc( sizeof(thread_state_t) * cpu_count ); + + for( loop = 0 ; loop < cpu_count ; loop++ ) + abstraction_thread_start( &thread_handles[loop], loop, freelist_test_internal_thread_rapid_popping_and_pushing, fs ); + + for( loop = 0 ; loop < cpu_count ; loop++ ) + abstraction_thread_wait( thread_handles[loop] ); + + free( thread_handles ); + + vi.min_elements = cpu_count; + vi.max_elements = cpu_count; + + lfds600_freelist_query( fs, LFDS600_FREELIST_QUERY_VALIDATE, (void *) &vi, (void *) &dvs ); + + lfds600_freelist_delete( fs, NULL, NULL ); + + // TRD : print the test result + internal_display_test_result( 1, "freelist", dvs ); + + return; +} + + + + + +/****************************************************************************/ +thread_return_t CALLING_CONVENTION freelist_test_internal_thread_rapid_popping_and_pushing( void *lfds600_freelist_state ) +{ + struct lfds600_freelist_state + *fs; + + struct lfds600_freelist_element + *fe; + + time_t + start_time; + + assert( lfds600_freelist_state != NULL ); + + fs = (struct lfds600_freelist_state *) lfds600_freelist_state; + + time( &start_time ); + + while( time(NULL) < start_time + 10 ) + { + lfds600_freelist_pop( fs, &fe ); + lfds600_freelist_push( fs, fe ); + } + + return( (thread_return_t) EXIT_SUCCESS ); +} + diff --git a/liblfds/liblfds6.0.0/test/src/test_queue.c b/liblfds/liblfds6.0.0/test/src/test_queue.c new file mode 100644 index 0000000..d41f8d2 --- /dev/null +++ b/liblfds/liblfds6.0.0/test/src/test_queue.c @@ -0,0 +1,519 @@ +#include "internal.h" + + + + + +/****************************************************************************/ +void test_lfds600_queue( void ) +{ + printf( "\n" + "Queue Tests\n" + "===========\n" ); + + queue_test_enqueuing(); + queue_test_dequeuing(); + queue_test_enqueuing_and_dequeuing(); + queue_test_rapid_enqueuing_and_dequeuing(); + + return; +} + + + + + +/****************************************************************************/ +void queue_test_enqueuing( void ) +{ + unsigned int + loop, + cpu_count; + + thread_state_t + *thread_handles; + + struct lfds600_queue_state + *qs; + + struct queue_test_enqueuing_state + *qtes; + + lfds600_atom_t + user_data, + thread, + count, + *per_thread_counters; + + struct lfds600_validation_info + vi = { 1000000, 1000000 }; + + enum data_structure_validity + dvs[2]; + + /* TRD : create an empty queue with 1,000,000 elements in its freelist + then run one thread per CPU + where each thread busy-works, enqueuing elements (until there are no more elements) + each element's void pointer of user data is (thread number | element number) + where element_number is a thread-local counter starting at 0 + where the thread_number occupies the top byte + + when we're done, we check that all the elements are present + and increment on a per-thread basis + */ + + internal_display_test_name( "Enqueuing" ); + + cpu_count = abstraction_cpu_count(); + + lfds600_queue_new( &qs, 1000000 ); + + qtes = malloc( sizeof(struct queue_test_enqueuing_state) * cpu_count ); + + for( loop = 0 ; loop < cpu_count ; loop++ ) + { + (qtes+loop)->qs = qs; + (qtes+loop)->counter = (lfds600_atom_t) loop << (sizeof(lfds600_atom_t)*8-8); + } + + thread_handles = malloc( sizeof(thread_state_t) * cpu_count ); + + for( loop = 0 ; loop < cpu_count ; loop++ ) + abstraction_thread_start( &thread_handles[loop], loop, queue_test_internal_thread_simple_enqueuer, qtes+loop ); + + for( loop = 0 ; loop < cpu_count ; loop++ ) + abstraction_thread_wait( thread_handles[loop] ); + + free( thread_handles ); + + free( qtes ); + + /* TRD : first, validate the queue + + then dequeue + we expect to find element numbers increment on a per thread basis + */ + + lfds600_queue_query( qs, LFDS600_QUEUE_QUERY_VALIDATE, &vi, dvs ); + + per_thread_counters = malloc( sizeof(lfds600_atom_t) * cpu_count ); + + for( loop = 0 ; loop < cpu_count ; loop++ ) + *(per_thread_counters+loop) = 0; + + while( dvs[0] == VALIDITY_VALID and dvs[1] == VALIDITY_VALID and lfds600_queue_dequeue(qs, (void *) &user_data) ) + { + thread = user_data >> (sizeof(lfds600_atom_t)*8-8); + count = (user_data << 8) >> 8; + + if( thread >= cpu_count ) + { + dvs[0] = VALIDITY_INVALID_TEST_DATA; + break; + } + + if( count < per_thread_counters[thread] ) + dvs[0] = VALIDITY_INVALID_ADDITIONAL_ELEMENTS; + + if( count > per_thread_counters[thread] ) + dvs[0] = VALIDITY_INVALID_MISSING_ELEMENTS; + + if( count == per_thread_counters[thread] ) + per_thread_counters[thread]++; + } + + free( per_thread_counters ); + + lfds600_queue_delete( qs, NULL, NULL ); + + internal_display_test_result( 2, "queue", dvs[0], "queue freelist", dvs[1] ); + + return; +} + + + + + +/****************************************************************************/ +thread_return_t CALLING_CONVENTION queue_test_internal_thread_simple_enqueuer( void *queue_test_enqueuing_state ) +{ + struct queue_test_enqueuing_state + *qtes; + + assert( queue_test_enqueuing_state != NULL ); + + qtes = (struct queue_test_enqueuing_state *) queue_test_enqueuing_state; + + // TRD : top byte of counter is already our thread number + while( lfds600_queue_enqueue(qtes->qs, (void *) qtes->counter++) ); + + return( (thread_return_t) EXIT_SUCCESS ); +} + + + + + +/****************************************************************************/ +void queue_test_dequeuing( void ) +{ + unsigned int + loop, + cpu_count; + + thread_state_t + *thread_handles; + + struct lfds600_queue_state + *qs; + + struct queue_test_dequeuing_state + *qtds; + + struct lfds600_validation_info + vi = { 0, 0 }; + + enum data_structure_validity + dvs[2]; + + /* TRD : create a queue with 1,000,000 elements + + use a single thread to enqueue every element + each elements user data is an incrementing counter + + then run one thread per CPU + where each busy-works dequeuing + + when an element is dequeued, we check (on a per-thread basis) the + value deqeued is greater than the element previously dequeued + */ + + internal_display_test_name( "Dequeuing" ); + + cpu_count = abstraction_cpu_count(); + + lfds600_queue_new( &qs, 1000000 ); + + for( loop = 0 ; loop < 1000000 ; loop++ ) + lfds600_queue_enqueue( qs, (void *) (lfds600_atom_t) loop ); + + qtds = malloc( sizeof(struct queue_test_dequeuing_state) * cpu_count ); + + for( loop = 0 ; loop < cpu_count ; loop++ ) + { + (qtds+loop)->qs = qs; + (qtds+loop)->error_flag = LOWERED; + } + + thread_handles = malloc( sizeof(thread_state_t) * cpu_count ); + + for( loop = 0 ; loop < cpu_count ; loop++ ) + abstraction_thread_start( &thread_handles[loop], loop, queue_test_internal_thread_simple_dequeuer, qtds+loop ); + + for( loop = 0 ; loop < cpu_count ; loop++ ) + abstraction_thread_wait( thread_handles[loop] ); + + free( thread_handles ); + + // TRD : check queue is empty + lfds600_queue_query( qs, LFDS600_QUEUE_QUERY_VALIDATE, (void *) &vi, (void *) dvs ); + + // TRD : check for raised error flags + for( loop = 0 ; loop < cpu_count ; loop++ ) + if( (qtds+loop)->error_flag == RAISED ) + dvs[0] = VALIDITY_INVALID_TEST_DATA; + + free( qtds ); + + lfds600_queue_delete( qs, NULL, NULL ); + + internal_display_test_result( 2, "queue", dvs[0], "queue freelist", dvs[1] ); + + return; +} + + + + + +/****************************************************************************/ +thread_return_t CALLING_CONVENTION queue_test_internal_thread_simple_dequeuer( void *queue_test_dequeuing_state ) +{ + struct queue_test_dequeuing_state + *qtds; + + lfds600_atom_t + *prev_user_data, + *user_data; + + assert( queue_test_dequeuing_state != NULL ); + + qtds = (struct queue_test_dequeuing_state *) queue_test_dequeuing_state; + + lfds600_queue_dequeue( qtds->qs, (void *) &prev_user_data ); + + while( lfds600_queue_dequeue(qtds->qs, (void *) &user_data) ) + { + if( user_data <= prev_user_data ) + qtds->error_flag = RAISED; + + prev_user_data = user_data; + } + + return( (thread_return_t) EXIT_SUCCESS ); +} + + + + + +/****************************************************************************/ +void queue_test_enqueuing_and_dequeuing( void ) +{ + unsigned int + loop, + subloop, + cpu_count; + + thread_state_t + *thread_handles; + + struct lfds600_queue_state + *qs; + + struct queue_test_enqueuing_and_dequeuing_state + *qteds; + + struct lfds600_validation_info + vi = { 0, 0 }; + + enum data_structure_validity + dvs[2]; + + internal_display_test_name( "Enqueuing and dequeuing (10 seconds)" ); + + cpu_count = abstraction_cpu_count(); + + lfds600_queue_new( &qs, cpu_count ); + + qteds = malloc( sizeof(struct queue_test_enqueuing_and_dequeuing_state) * cpu_count ); + + for( loop = 0 ; loop < cpu_count ; loop++ ) + { + (qteds+loop)->qs = qs; + (qteds+loop)->thread_number = loop; + (qteds+loop)->counter = (lfds600_atom_t) loop << (sizeof(lfds600_atom_t)*8-8); + (qteds+loop)->cpu_count = cpu_count; + (qteds+loop)->error_flag = LOWERED; + (qteds+loop)->per_thread_counters = malloc( sizeof(lfds600_atom_t) * cpu_count ); + + for( subloop = 0 ; subloop < cpu_count ; subloop++ ) + *((qteds+loop)->per_thread_counters+subloop) = 0; + } + + thread_handles = malloc( sizeof(thread_state_t) * cpu_count ); + + for( loop = 0 ; loop < cpu_count ; loop++ ) + abstraction_thread_start( &thread_handles[loop], loop, queue_test_internal_thread_enqueuer_and_dequeuer, qteds+loop ); + + for( loop = 0 ; loop < cpu_count ; loop++ ) + abstraction_thread_wait( thread_handles[loop] ); + + free( thread_handles ); + + lfds600_queue_query( qs, LFDS600_QUEUE_QUERY_VALIDATE, (void *) &vi, (void *) dvs ); + + for( loop = 0 ; loop < cpu_count ; loop++ ) + if( (qteds+loop)->error_flag == RAISED ) + dvs[0] = VALIDITY_INVALID_TEST_DATA; + + for( loop = 0 ; loop < cpu_count ; loop++ ) + free( (qteds+loop)->per_thread_counters ); + + free( qteds ); + + lfds600_queue_delete( qs, NULL, NULL ); + + internal_display_test_result( 2, "queue", dvs[0], "queue freelist", dvs[1] ); + + return; +} + + + + + +/****************************************************************************/ +thread_return_t CALLING_CONVENTION queue_test_internal_thread_enqueuer_and_dequeuer( void *queue_test_enqueuing_and_dequeuing_state ) +{ + struct queue_test_enqueuing_and_dequeuing_state + *qteds; + + time_t + start_time; + + lfds600_atom_t + thread, + count, + user_data; + + assert( queue_test_enqueuing_and_dequeuing_state != NULL ); + + qteds = (struct queue_test_enqueuing_and_dequeuing_state *) queue_test_enqueuing_and_dequeuing_state; + + time( &start_time ); + + while( time(NULL) < start_time + 10 ) + { + lfds600_queue_enqueue( qteds->qs, (void *) (qteds->counter++) ); + lfds600_queue_dequeue( qteds->qs, (void *) &user_data ); + + thread = user_data >> (sizeof(lfds600_atom_t)*8-8); + count = (user_data << 8) >> 8; + + if( thread >= qteds->cpu_count ) + qteds->error_flag = RAISED; + else + { + if( count < qteds->per_thread_counters[thread] ) + qteds->error_flag = RAISED; + + if( count >= qteds->per_thread_counters[thread] ) + qteds->per_thread_counters[thread] = count+1; + } + } + + return( (thread_return_t) EXIT_SUCCESS ); +} + + + + + +/****************************************************************************/ +void queue_test_rapid_enqueuing_and_dequeuing( void ) +{ + unsigned int + loop, + cpu_count; + + thread_state_t + *thread_handles; + + struct lfds600_queue_state + *qs; + + struct queue_test_rapid_enqueuing_and_dequeuing_state + *qtreds; + + struct lfds600_validation_info + vi = { 50000, 50000 }; + + lfds600_atom_t + user_data, + thread, + count, + *per_thread_counters; + + enum data_structure_validity + dvs[2]; + + internal_display_test_name( "Rapid enqueuing and dequeuing (10 seconds)" ); + + cpu_count = abstraction_cpu_count(); + + lfds600_queue_new( &qs, 100000 ); + + for( loop = 0 ; loop < 50000 ; loop++ ) + lfds600_queue_enqueue( qs, NULL ); + + qtreds = malloc( sizeof(struct queue_test_rapid_enqueuing_and_dequeuing_state) * cpu_count ); + + for( loop = 0 ; loop < cpu_count ; loop++ ) + { + (qtreds+loop)->qs = qs; + (qtreds+loop)->counter = (lfds600_atom_t) loop << (sizeof(lfds600_atom_t)*8-8); + } + + thread_handles = malloc( sizeof(thread_state_t) * cpu_count ); + + for( loop = 0 ; loop < cpu_count ; loop++ ) + abstraction_thread_start( &thread_handles[loop], loop, queue_test_internal_thread_rapid_enqueuer_and_dequeuer, qtreds+loop ); + + for( loop = 0 ; loop < cpu_count ; loop++ ) + abstraction_thread_wait( thread_handles[loop] ); + + free( thread_handles ); + + lfds600_queue_query( qs, LFDS600_QUEUE_QUERY_VALIDATE, (void *) &vi, (void *) dvs ); + + // TRD : now check results + per_thread_counters = malloc( sizeof(lfds600_atom_t) * cpu_count ); + + for( loop = 0 ; loop < cpu_count ; loop++ ) + *(per_thread_counters+loop) = 0; + + while( dvs[0] == VALIDITY_VALID and dvs[1] == VALIDITY_VALID and lfds600_queue_dequeue(qs, (void *) &user_data) ) + { + thread = user_data >> (sizeof(lfds600_atom_t)*8-8); + count = (user_data << 8) >> 8; + + if( thread >= cpu_count ) + { + dvs[0] = VALIDITY_INVALID_TEST_DATA; + break; + } + + if( per_thread_counters[thread] == 0 ) + per_thread_counters[thread] = count; + + if( count < per_thread_counters[thread] ) + dvs[0] = VALIDITY_INVALID_ADDITIONAL_ELEMENTS; + + if( count >= per_thread_counters[thread] ) + per_thread_counters[thread] = count+1; + } + + free( per_thread_counters ); + + free( qtreds ); + + lfds600_queue_delete( qs, NULL, NULL ); + + internal_display_test_result( 2, "queue", dvs[0], "queue freelist", dvs[1] ); + + return; +} + + + + + +/****************************************************************************/ +thread_return_t CALLING_CONVENTION queue_test_internal_thread_rapid_enqueuer_and_dequeuer( void *queue_test_rapid_enqueuing_and_dequeuing_state ) +{ + struct queue_test_rapid_enqueuing_and_dequeuing_state + *qtreds; + + time_t + start_time; + + lfds600_atom_t + user_data; + + assert( queue_test_rapid_enqueuing_and_dequeuing_state != NULL ); + + qtreds = (struct queue_test_rapid_enqueuing_and_dequeuing_state *) queue_test_rapid_enqueuing_and_dequeuing_state; + + time( &start_time ); + + while( time(NULL) < start_time + 10 ) + { + lfds600_queue_enqueue( qtreds->qs, (void *) (qtreds->counter++) ); + lfds600_queue_dequeue( qtreds->qs, (void *) &user_data ); + } + + return( (thread_return_t) EXIT_SUCCESS ); +} + diff --git a/liblfds/liblfds6.0.0/test/src/test_ringbuffer.c b/liblfds/liblfds6.0.0/test/src/test_ringbuffer.c new file mode 100644 index 0000000..a2c3094 --- /dev/null +++ b/liblfds/liblfds6.0.0/test/src/test_ringbuffer.c @@ -0,0 +1,467 @@ +#include "internal.h" + + + + + +/****************************************************************************/ +void test_lfds600_ringbuffer( void ) +{ + printf( "\n" + "Ringbuffer Tests\n" + "================\n" ); + + ringbuffer_test_reading(); + ringbuffer_test_writing(); + ringbuffer_test_reading_and_writing(); + + return; +} + + + + + +/****************************************************************************/ +void ringbuffer_test_reading( void ) +{ + unsigned int + loop, + cpu_count; + + thread_state_t + *thread_handles; + + struct lfds600_ringbuffer_state + *rs; + + struct lfds600_freelist_element + *fe; + + struct ringbuffer_test_reading_state + *rtrs; + + struct lfds600_validation_info + vi = { 0, 0 }; + + enum data_structure_validity + dvs[3]; + + lfds600_atom_t + total_read = 0; + + /* TRD : we create a single ringbuffer + with 1,000,000 elements + we populate the ringbuffer, where the + user data is an incrementing counter + + we create one thread per CPU + where each thread busy-works, + reading until the ringbuffer is empty + + each thread keep track of the number of reads it manages + and that each user data it reads is greater than the + previous user data that was read + */ + + internal_display_test_name( "Reading" ); + + cpu_count = abstraction_cpu_count(); + + lfds600_ringbuffer_new( &rs, 1000000, NULL, NULL ); + + for( loop = 0 ; loop < 1000000 ; loop++ ) + { + lfds600_ringbuffer_get_write_element( rs, &fe, NULL ); + lfds600_freelist_set_user_data_in_element( fe, (void *) (lfds600_atom_t) loop ); + lfds600_ringbuffer_put_write_element( rs, fe ); + } + + rtrs = malloc( sizeof(struct ringbuffer_test_reading_state) * cpu_count ); + + for( loop = 0 ; loop < cpu_count ; loop++ ) + { + (rtrs+loop)->rs = rs; + (rtrs+loop)->read_count = 0; + (rtrs+loop)->error_flag = LOWERED; + } + + thread_handles = malloc( sizeof(thread_state_t) * cpu_count ); + + for( loop = 0 ; loop < cpu_count ; loop++ ) + abstraction_thread_start( &thread_handles[loop], loop, ringbuffer_test_thread_simple_reader, rtrs+loop ); + + for( loop = 0 ; loop < cpu_count ; loop++ ) + abstraction_thread_wait( thread_handles[loop] ); + + free( thread_handles ); + + lfds600_ringbuffer_query( rs, LFDS600_RINGBUFFER_QUERY_VALIDATE, (void *) &vi, (void *) dvs ); + + // TRD : check for raised error flags + for( loop = 0 ; loop < cpu_count ; loop++ ) + if( (rtrs+loop)->error_flag == RAISED ) + dvs[0] = VALIDITY_INVALID_TEST_DATA; + + // TRD : check thread reads total to 1,000,000 + for( loop = 0 ; loop < cpu_count ; loop++ ) + total_read += (rtrs+loop)->read_count; + + if( total_read < 1000000 ) + dvs[0] = VALIDITY_INVALID_MISSING_ELEMENTS; + + if( total_read > 1000000 ) + dvs[0] = VALIDITY_INVALID_ADDITIONAL_ELEMENTS; + + free( rtrs ); + + lfds600_ringbuffer_delete( rs, NULL, NULL ); + + internal_display_test_result( 3, "queue", dvs[0], "queue freelist", dvs[1], "freelist", dvs[2] ); + + return; +} + + + + + +/****************************************************************************/ +thread_return_t CALLING_CONVENTION ringbuffer_test_thread_simple_reader( void *ringbuffer_test_reading_state ) +{ + struct ringbuffer_test_reading_state + *rtrs; + + struct lfds600_freelist_element + *fe; + + lfds600_atom_t + *prev_user_data, + *user_data; + + assert( ringbuffer_test_reading_state != NULL ); + + rtrs = (struct ringbuffer_test_reading_state *) ringbuffer_test_reading_state; + + lfds600_ringbuffer_get_read_element( rtrs->rs, &fe ); + lfds600_freelist_get_user_data_from_element( fe, (void **) &prev_user_data ); + lfds600_ringbuffer_put_read_element( rtrs->rs, fe ); + + rtrs->read_count++; + + while( lfds600_ringbuffer_get_read_element(rtrs->rs, &fe) ) + { + lfds600_freelist_get_user_data_from_element( fe, (void **) &user_data ); + lfds600_ringbuffer_put_read_element( rtrs->rs, fe ); + + if( user_data <= prev_user_data ) + rtrs->error_flag = RAISED; + + prev_user_data = user_data; + + rtrs->read_count++; + } + + return( (thread_return_t) EXIT_SUCCESS ); +} + + + + + +/****************************************************************************/ +void ringbuffer_test_writing( void ) +{ + unsigned int + loop, + cpu_count; + + thread_state_t + *thread_handles; + + struct lfds600_ringbuffer_state + *rs; + + struct lfds600_freelist_element + *fe; + + struct ringbuffer_test_writing_state + *rtws; + + struct lfds600_validation_info + vi = { 100000, 100000 }; + + enum data_structure_validity + dvs[3]; + + lfds600_atom_t + thread, + count, + user_data, + *per_thread_counters; + + /* TRD : we create a single ringbuffer + with 100000 elements + the ringbuffers starts empty + + we create one thread per CPU + where each thread busy-works writing + for ten seconds + + the user data in each written element is a combination + of the thread number and the counter + + after the threads are complete, we validate by + checking the user data counters increment on a per thread + basis + */ + + internal_display_test_name( "Writing (10 seconds)" ); + + cpu_count = abstraction_cpu_count(); + + lfds600_ringbuffer_new( &rs, 100000, NULL, NULL ); + + rtws = malloc( sizeof(struct ringbuffer_test_writing_state) * cpu_count ); + + for( loop = 0 ; loop < cpu_count ; loop++ ) + { + (rtws+loop)->rs = rs; + (rtws+loop)->write_count = (lfds600_atom_t) loop << (sizeof(lfds600_atom_t)*8-8); + } + + thread_handles = malloc( sizeof(thread_state_t) * cpu_count ); + + for( loop = 0 ; loop < cpu_count ; loop++ ) + abstraction_thread_start( &thread_handles[loop], loop, ringbuffer_test_thread_simple_writer, rtws+loop ); + + for( loop = 0 ; loop < cpu_count ; loop++ ) + abstraction_thread_wait( thread_handles[loop] ); + + free( thread_handles ); + + // TRD : now check results + per_thread_counters = malloc( sizeof(lfds600_atom_t) * cpu_count ); + + for( loop = 0 ; loop < cpu_count ; loop++ ) + *(per_thread_counters+loop) = 0; + + lfds600_ringbuffer_query( rs, LFDS600_RINGBUFFER_QUERY_VALIDATE, (void *) &vi, (void *) dvs ); + + while( dvs[0] == VALIDITY_VALID and dvs[1] == VALIDITY_VALID and dvs[2] == VALIDITY_VALID and lfds600_ringbuffer_get_read_element(rs, &fe) ) + { + lfds600_freelist_get_user_data_from_element( fe, (void *) &user_data ); + + thread = user_data >> (sizeof(lfds600_atom_t)*8-8); + count = (user_data << 8) >> 8; + + if( thread >= cpu_count ) + { + dvs[0] = VALIDITY_INVALID_TEST_DATA; + lfds600_ringbuffer_put_read_element( rs, fe ); + break; + } + + if( per_thread_counters[thread] == 0 ) + per_thread_counters[thread] = count; + + if( count < per_thread_counters[thread] ) + dvs[0] = VALIDITY_INVALID_ADDITIONAL_ELEMENTS; + + if( count >= per_thread_counters[thread] ) + per_thread_counters[thread] = count+1; + + lfds600_ringbuffer_put_read_element( rs, fe ); + } + + free( per_thread_counters ); + + free( rtws ); + + lfds600_ringbuffer_delete( rs, NULL, NULL ); + + internal_display_test_result( 3, "queue", dvs[0], "queue freelist", dvs[1], "freelist", dvs[2] ); + + return; +} + + + + + +/****************************************************************************/ +thread_return_t CALLING_CONVENTION ringbuffer_test_thread_simple_writer( void *ringbuffer_test_writing_state ) +{ + struct ringbuffer_test_writing_state + *rtws; + + struct lfds600_freelist_element + *fe; + + time_t + start_time; + + assert( ringbuffer_test_writing_state != NULL ); + + rtws = (struct ringbuffer_test_writing_state *) ringbuffer_test_writing_state; + + time( &start_time ); + + while( time(NULL) < start_time + 10 ) + { + lfds600_ringbuffer_get_write_element( rtws->rs, &fe, NULL ); + lfds600_freelist_set_user_data_in_element( fe, (void *) (lfds600_atom_t) (rtws->write_count++) ); + lfds600_ringbuffer_put_write_element( rtws->rs, fe ); + } + + return( (thread_return_t) EXIT_SUCCESS ); +} + + + + + +/****************************************************************************/ +void ringbuffer_test_reading_and_writing( void ) +{ + unsigned int + loop, + subloop, + cpu_count; + + thread_state_t + *thread_handles; + + struct lfds600_ringbuffer_state + *rs; + + struct ringbuffer_test_reading_and_writing_state + *rtrws; + + struct lfds600_validation_info + vi = { 0, 0 }; + + enum data_structure_validity + dvs[3]; + + /* TRD : we create a single ringbuffer + with 100000 elements + the ringbuffers starts empty + + we create one thread per CPU + where each thread busy-works writing + and then immediately reading + for ten seconds + + the user data in each written element is a combination + of the thread number and the counter + + while a thread runs, it keeps track of the + counters for the other threads and throws an error + if it sees the number stay the same or decrease + */ + + internal_display_test_name( "Reading and writing (10 seconds)" ); + + cpu_count = abstraction_cpu_count(); + + lfds600_ringbuffer_new( &rs, 100000, NULL, NULL ); + + rtrws = malloc( sizeof(struct ringbuffer_test_reading_and_writing_state) * cpu_count ); + + for( loop = 0 ; loop < cpu_count ; loop++ ) + { + (rtrws+loop)->rs = rs; + (rtrws+loop)->counter = (lfds600_atom_t) loop << (sizeof(lfds600_atom_t)*8-8); + (rtrws+loop)->cpu_count = cpu_count; + (rtrws+loop)->error_flag = LOWERED; + (rtrws+loop)->per_thread_counters = malloc( sizeof(lfds600_atom_t) * cpu_count ); + + for( subloop = 0 ; subloop < cpu_count ; subloop++ ) + *((rtrws+loop)->per_thread_counters+subloop) = 0; + } + + thread_handles = malloc( sizeof(thread_state_t) * cpu_count ); + + for( loop = 0 ; loop < cpu_count ; loop++ ) + abstraction_thread_start( &thread_handles[loop], loop, ringbuffer_test_thread_reader_writer, rtrws+loop ); + + for( loop = 0 ; loop < cpu_count ; loop++ ) + abstraction_thread_wait( thread_handles[loop] ); + + free( thread_handles ); + + lfds600_ringbuffer_query( rs, LFDS600_RINGBUFFER_QUERY_VALIDATE, (void *) &vi, (void *) dvs ); + + for( loop = 0 ; loop < cpu_count ; loop++ ) + if( (rtrws+loop)->error_flag == RAISED ) + dvs[0] = VALIDITY_INVALID_TEST_DATA; + + for( loop = 0 ; loop < cpu_count ; loop++ ) + free( (rtrws+loop)->per_thread_counters ); + + free( rtrws ); + + lfds600_ringbuffer_delete( rs, NULL, NULL ); + + internal_display_test_result( 3, "queue", dvs[0], "queue freelist", dvs[1], "freelist", dvs[2] ); + + return; +} + + + + + +/****************************************************************************/ +thread_return_t CALLING_CONVENTION ringbuffer_test_thread_reader_writer( void *ringbuffer_test_reading_and_writing_state ) +{ + struct ringbuffer_test_reading_and_writing_state + *rtrws; + + struct lfds600_freelist_element + *fe; + + lfds600_atom_t + user_data, + thread, + count; + + time_t + start_time; + + assert( ringbuffer_test_reading_and_writing_state != NULL ); + + rtrws = (struct ringbuffer_test_reading_and_writing_state *) ringbuffer_test_reading_and_writing_state; + + time( &start_time ); + + while( time(NULL) < start_time + 10 ) + { + lfds600_ringbuffer_get_write_element( rtrws->rs, &fe, NULL ); + lfds600_freelist_set_user_data_in_element( fe, (void *) (lfds600_atom_t) (rtrws->counter++) ); + lfds600_ringbuffer_put_write_element( rtrws->rs, fe ); + + lfds600_ringbuffer_get_read_element( rtrws->rs, &fe ); + lfds600_freelist_get_user_data_from_element( fe, (void *) &user_data ); + + thread = user_data >> (sizeof(lfds600_atom_t)*8-8); + count = (user_data << 8) >> 8; + + if( thread >= rtrws->cpu_count ) + rtrws->error_flag = RAISED; + else + { + if( count < rtrws->per_thread_counters[thread] ) + rtrws->error_flag = RAISED; + + if( count >= rtrws->per_thread_counters[thread] ) + rtrws->per_thread_counters[thread] = count+1; + } + + lfds600_ringbuffer_put_read_element( rtrws->rs, fe ); + } + + return( (thread_return_t) EXIT_SUCCESS ); +} + diff --git a/liblfds/liblfds6.0.0/test/src/test_slist.c b/liblfds/liblfds6.0.0/test/src/test_slist.c new file mode 100644 index 0000000..e8afced --- /dev/null +++ b/liblfds/liblfds6.0.0/test/src/test_slist.c @@ -0,0 +1,513 @@ +#include "internal.h" + + + + + +/****************************************************************************/ +void test_lfds600_slist( void ) +{ + unsigned int + loop, + cpu_count; + + thread_state_t + *thread_handles; + + struct lfds600_slist_thread_start_state + stss; + + /* TRD : 1. one head writer per CPU + 2. make one element, then one after writer per CPU + 3. make a list, then one list traverser per CPU + 4. one head writer and one list traverser per CPU + 5. make one element, then one after writer and one list traverser per CPU + 6. make a list, then one 100% deleter-traverser per CPU + 7. make a list, then one 25% deleter-traverser per CPU + 8. one head writer and one 100% deleter-traverse per CPU + 9. one head writer and one 25% deleter-traverse per CPU + 10. make one element, then one after writer and one 100% deleter-traverser per CPU + 11. make one element, then one after writer and one 25% deleter-traverser per CPU + 12. one head writer, one after writer, one traverser and one 25% deleter-traverser per CPU + */ + + cpu_count = abstraction_cpu_count(); + + printf( "\n" + "SList Test\n" + "==========\n" ); + + // TRD : 1. one head writer per CPU + + printf( "\n" + "1. one head writer per CPU\n" + "==========================\n" ); + + lfds600_slist_new( &stss.ss, NULL, NULL ); + stss.iteration_modulo = 1; + stss.se = NULL; + stss.duration = 1; + + thread_handles = (thread_state_t *) malloc( sizeof(thread_state_t) * cpu_count * 1 ); + + for( loop = 0 ; loop < cpu_count ; loop++ ) + abstraction_thread_start( &thread_handles[loop], loop, lfds600_slist_internal_thread_head_writer, &stss ); + + for( loop = 0 ; loop < cpu_count ; loop++ ) + abstraction_thread_wait( thread_handles[loop] ); + + lfds600_slist_delete( stss.ss ); + + free( thread_handles ); + + // TRD : 2. make one element, then one after writer per CPU + + printf( "\n" + "2. make one element, then one after writer per CPU\n" + "==================================================\n" ); + + lfds600_slist_new( &stss.ss, NULL, NULL ); + stss.iteration_modulo = 1; + stss.se = lfds600_slist_new_head( stss.ss, (void *) NULL ); + stss.duration = 1; + + thread_handles = (thread_state_t *) malloc( sizeof(thread_state_t) * cpu_count * 1 ); + + for( loop = 0 ; loop < cpu_count ; loop++ ) + abstraction_thread_start( &thread_handles[loop], loop, lfds600_slist_internal_thread_after_writer, &stss ); + + for( loop = 0 ; loop < cpu_count ; loop++ ) + abstraction_thread_wait( thread_handles[loop] ); + + lfds600_slist_delete( stss.ss ); + + free( thread_handles ); + + // TRD : 3. make a list, then one list traverser per CPU + + printf( "\n" + "3. make a list, then one list traverser per CPU\n" + "===============================================\n" ); + + lfds600_slist_new( &stss.ss, NULL, NULL ); + stss.iteration_modulo = 1; + stss.se = NULL; + stss.duration = 10; + + // TRD : small list so we get collisions + for( loop = 0 ; loop < 10 ; loop++ ) + lfds600_slist_new_head( stss.ss, (void *) 0 ); + + thread_handles = (thread_state_t *) malloc( sizeof(thread_state_t) * cpu_count * 1 ); + + for( loop = 0 ; loop < cpu_count ; loop++ ) + abstraction_thread_start( &thread_handles[loop], loop, lfds600_slist_internal_thread_traverser, &stss ); + + for( loop = 0 ; loop < cpu_count ; loop++ ) + abstraction_thread_wait( thread_handles[loop] ); + + lfds600_slist_delete( stss.ss ); + + free( thread_handles ); + + // TRD : 4. one head writer and one list traverser per CPU + + printf( "\n" + "4. one head writer and one list traverser per CPU\n" + "=================================================\n" ); + + lfds600_slist_new( &stss.ss, NULL, NULL ); + stss.iteration_modulo = 1; + stss.se = NULL; + stss.duration = 1; + + thread_handles = (thread_state_t *) malloc( sizeof(thread_state_t) * cpu_count * 2 ); + + for( loop = 0 ; loop < cpu_count ; loop++ )\ + { + abstraction_thread_start( &thread_handles[loop], loop, lfds600_slist_internal_thread_head_writer, &stss ); + abstraction_thread_start( &thread_handles[loop+cpu_count], loop, lfds600_slist_internal_thread_traverser, &stss ); + } + + for( loop = 0 ; loop < cpu_count * 2 ; loop++ ) + abstraction_thread_wait( thread_handles[loop] ); + + lfds600_slist_delete( stss.ss ); + + free( thread_handles ); + + // TRD : 5. make one element, then one after writer and one list traverser per CPU + + printf( "\n" + "5. make one element, then one after writer and one list traverser per CPU\n" + "=========================================================================\n" ); + + lfds600_slist_new( &stss.ss, NULL, NULL ); + stss.iteration_modulo = 1; + stss.se = lfds600_slist_new_head( stss.ss, (void *) NULL ); + stss.duration = 1; + + thread_handles = (thread_state_t *) malloc( sizeof(thread_state_t) * cpu_count * 2 ); + + for( loop = 0 ; loop < cpu_count ; loop++ )\ + { + abstraction_thread_start( &thread_handles[loop], loop, lfds600_slist_internal_thread_after_writer, &stss ); + abstraction_thread_start( &thread_handles[loop+cpu_count], loop, lfds600_slist_internal_thread_traverser, &stss ); + } + + for( loop = 0 ; loop < cpu_count * 2 ; loop++ ) + abstraction_thread_wait( thread_handles[loop] ); + + lfds600_slist_delete( stss.ss ); + + free( thread_handles ); + + // TRD : 6. make a list, then one 100% deleter-traverser per CPU + + printf( "\n" + "6. make a list, then one 100%% deleter-traverser per CPU\n" + "=======================================================\n" ); + + lfds600_slist_new( &stss.ss, NULL, NULL ); + stss.iteration_modulo = 1; + stss.se = NULL; + stss.duration = 1; + + for( loop = 0 ; loop < 10000 ; loop++ ) + lfds600_slist_new_head( stss.ss, (void *) 0 ); + + thread_handles = (thread_state_t *) malloc( sizeof(thread_state_t) * cpu_count * 1 ); + + for( loop = 0 ; loop < cpu_count ; loop++ ) + abstraction_thread_start( &thread_handles[loop], loop, lfds600_slist_internal_thread_deleter_traverser, &stss ); + + for( loop = 0 ; loop < cpu_count ; loop++ ) + abstraction_thread_wait( thread_handles[loop] ); + + lfds600_slist_delete( stss.ss ); + + free( thread_handles ); + + // TRD : 7. make a list, then one 25% deleter-traverser per CPU + + printf( "\n" + "7. make a list, then one 25%% deleter-traverser per CPU\n" + "======================================================\n" ); + + lfds600_slist_new( &stss.ss, NULL, NULL ); + stss.iteration_modulo = 4; + stss.se = NULL; + stss.duration = 1; + + for( loop = 0 ; loop < 10000 ; loop++ ) + lfds600_slist_new_head( stss.ss, (void *) 0 ); + + thread_handles = (thread_state_t *) malloc( sizeof(thread_state_t) * cpu_count * 1 ); + + for( loop = 0 ; loop < cpu_count ; loop++ ) + abstraction_thread_start( &thread_handles[loop], loop, lfds600_slist_internal_thread_deleter_traverser, &stss ); + + for( loop = 0 ; loop < cpu_count ; loop++ ) + abstraction_thread_wait( thread_handles[loop] ); + + lfds600_slist_delete( stss.ss ); + + free( thread_handles ); + + // TRD : 8. one head writer and one 100% deleter-traverse per CPU + + printf( "\n" + "8. one head writer and one 100%% deleter-traverse per CPU\n" + "========================================================\n" ); + + lfds600_slist_new( &stss.ss, NULL, NULL ); + stss.iteration_modulo = 1; + stss.se = NULL; + stss.duration = 10; + + thread_handles = (thread_state_t *) malloc( sizeof(thread_state_t) * cpu_count * 2 ); + + for( loop = 0 ; loop < cpu_count ; loop++ ) + { + abstraction_thread_start( &thread_handles[loop], loop, lfds600_slist_internal_thread_head_writer, &stss ); + abstraction_thread_start( &thread_handles[loop+cpu_count], loop, lfds600_slist_internal_thread_deleter_traverser, &stss ); + } + + for( loop = 0 ; loop < cpu_count * 2 ; loop++ ) + abstraction_thread_wait( thread_handles[loop] ); + + lfds600_slist_delete( stss.ss ); + + free( thread_handles ); + + // TRD : 9. one head writer and one 25% deleter-traverse per CPU + + printf( "\n" + "9. one head writer and one 25%% deleter-traverse per CPU\n" + "=======================================================\n" ); + + lfds600_slist_new( &stss.ss, NULL, NULL ); + stss.iteration_modulo = 4; + stss.se = NULL; + stss.duration = 1; + + thread_handles = (thread_state_t *) malloc( sizeof(thread_state_t) * cpu_count * 2 ); + + for( loop = 0 ; loop < cpu_count ; loop++ ) + { + abstraction_thread_start( &thread_handles[loop], loop, lfds600_slist_internal_thread_head_writer, &stss ); + abstraction_thread_start( &thread_handles[loop+cpu_count], loop, lfds600_slist_internal_thread_deleter_traverser, &stss ); + } + + for( loop = 0 ; loop < cpu_count * 2 ; loop++ ) + abstraction_thread_wait( thread_handles[loop] ); + + lfds600_slist_delete( stss.ss ); + + free( thread_handles ); + + // TRD : 10. make one element, then one after writer and one 100% deleter-traverser per CPU + + printf( "\n" + "10. make one element, then one after writer and one 100%% deleter-traverser per CPU\n" + "==================================================================================\n" ); + + lfds600_slist_new( &stss.ss, NULL, NULL ); + stss.iteration_modulo = 1; + stss.se = lfds600_slist_new_head( stss.ss, (void *) NULL ); + stss.duration = 10; + + thread_handles = (thread_state_t *) malloc( sizeof(thread_state_t) * cpu_count * 2 ); + + for( loop = 0 ; loop < cpu_count ; loop++ ) + { + abstraction_thread_start( &thread_handles[loop], loop, lfds600_slist_internal_thread_after_writer, &stss ); + abstraction_thread_start( &thread_handles[loop+cpu_count], loop, lfds600_slist_internal_thread_deleter_traverser, &stss ); + } + + for( loop = 0 ; loop < cpu_count * 2 ; loop++ ) + abstraction_thread_wait( thread_handles[loop] ); + + lfds600_slist_delete( stss.ss ); + + free( thread_handles ); + + // TRD : 11. make one element, then one after writer and one 25% deleter-traverser per CPU + + printf( "\n" + "11. make one element, then one after writer and one 25%% deleter-traverser per CPU\n" + "=================================================================================\n" ); + + lfds600_slist_new( &stss.ss, NULL, NULL ); + stss.iteration_modulo = 4; + stss.se = lfds600_slist_new_head( stss.ss, (void *) NULL ); + stss.duration = 1; + + thread_handles = (thread_state_t *) malloc( sizeof(thread_state_t) * cpu_count * 2 ); + + for( loop = 0 ; loop < cpu_count ; loop++ ) + { + abstraction_thread_start( &thread_handles[loop], loop, lfds600_slist_internal_thread_after_writer, &stss ); + abstraction_thread_start( &thread_handles[loop+cpu_count], loop, lfds600_slist_internal_thread_deleter_traverser, &stss ); + } + + for( loop = 0 ; loop < cpu_count * 2 ; loop++ ) + abstraction_thread_wait( thread_handles[loop] ); + + lfds600_slist_delete( stss.ss ); + + free( thread_handles ); + + // TRD : 12. one head writer, one after writer, one traverser and one 25% deleter-traverser per CPU + + printf( "\n" + "12. one head writer, one after writer, one traverser and one 25%% deleter-traverser per CPU\n" + "==========================================================================================\n" ); + + lfds600_slist_new( &stss.ss, NULL, NULL ); + stss.iteration_modulo = 4; + stss.se = lfds600_slist_new_head( stss.ss, (void *) NULL ); + stss.duration = 1; + + thread_handles = (thread_state_t *) malloc( sizeof(thread_state_t) * cpu_count * 4 ); + + for( loop = 0 ; loop < cpu_count ; loop++ ) + { + abstraction_thread_start( &thread_handles[loop], loop, lfds600_slist_internal_thread_head_writer, &stss ); + abstraction_thread_start( &thread_handles[loop+cpu_count], loop, lfds600_slist_internal_thread_after_writer, &stss ); + abstraction_thread_start( &thread_handles[loop+cpu_count*2], loop, lfds600_slist_internal_thread_traverser, &stss ); + abstraction_thread_start( &thread_handles[loop+cpu_count*3], loop, lfds600_slist_internal_thread_deleter_traverser, &stss ); + } + + for( loop = 0 ; loop < cpu_count * 4 ; loop++ ) + abstraction_thread_wait( thread_handles[loop] ); + + lfds600_slist_delete( stss.ss ); + + free( thread_handles ); + + return; +} + + + + + +/****************************************************************************/ +thread_return_t CALLING_CONVENTION lfds600_slist_internal_thread_head_writer( void *lfds600_slist_thread_start_state ) +{ + struct lfds600_slist_thread_start_state + *stss; + + time_t + start_time; + + unsigned long int + count = 0; + + assert( lfds600_slist_thread_start_state != NULL ); + + stss = (struct lfds600_slist_thread_start_state *) lfds600_slist_thread_start_state; + + time( &start_time ); + + while( time(NULL) < start_time + stss->duration ) + if( lfds600_slist_new_head(stss->ss, (void *) 0) ) + count++; + + printf( "head writer count = %lu\n", count ); + + return( (thread_return_t) EXIT_SUCCESS ); +} + + + + + +/****************************************************************************/ +thread_return_t CALLING_CONVENTION lfds600_slist_internal_thread_after_writer( void *lfds600_slist_thread_start_state ) +{ + struct lfds600_slist_thread_start_state + *stss; + + time_t + start_time; + + unsigned long int + count = 0; + + assert( lfds600_slist_thread_start_state != NULL ); + + stss = (struct lfds600_slist_thread_start_state *) lfds600_slist_thread_start_state; + + time( &start_time ); + + while( time(NULL) < start_time + stss->duration ) + if( lfds600_slist_new_next(stss->se, (void *) 0) ) + count++; + + printf( "after writer count = %lu\n", count ); + + return( (thread_return_t) EXIT_SUCCESS ); +} + + + + + +/****************************************************************************/ +thread_return_t CALLING_CONVENTION lfds600_slist_internal_thread_traverser( void *lfds600_slist_thread_start_state ) +{ + struct lfds600_slist_thread_start_state + *stss; + + time_t + start_time; + + unsigned long int + count = 0, + iteration = 0; + + struct lfds600_slist_element + *se; + + assert( lfds600_slist_thread_start_state != NULL ); + + stss = (struct lfds600_slist_thread_start_state *) lfds600_slist_thread_start_state; + + time( &start_time ); + + lfds600_slist_get_head( stss->ss, &se ); + + while( time(NULL) < start_time + stss->duration ) + { + if( !(iteration % stss->iteration_modulo) ) + { + lfds600_slist_get_next( se, &se ); + count++; + } + + if( se == NULL ) + { + lfds600_slist_get_head( stss->ss, &se ); + count++; + } + + iteration++; + } + + printf( "traverser count = %lu\n", count ); + + return( (thread_return_t) EXIT_SUCCESS ); +} + + + + + +/****************************************************************************/ +thread_return_t CALLING_CONVENTION lfds600_slist_internal_thread_deleter_traverser( void *lfds600_slist_thread_start_state ) +{ + struct lfds600_slist_thread_start_state + *stss; + + time_t + start_time; + + unsigned long int + count = 0, + iteration = 0; + + struct lfds600_slist_element + *se; + + assert( lfds600_slist_thread_start_state != NULL ); + + stss = (struct lfds600_slist_thread_start_state *) lfds600_slist_thread_start_state; + + time( &start_time ); + + lfds600_slist_get_head( stss->ss, &se ); + + while( time(NULL) < start_time + stss->duration ) + { + if( se != NULL and !(iteration % stss->iteration_modulo) ) + { + lfds600_slist_delete_element( stss->ss, se ); + count++; + } + + if( se != NULL ) + lfds600_slist_get_next( se, &se ); + + if( se == NULL ) + lfds600_slist_get_head( stss->ss, &se ); + + iteration++; + } + + printf( "deleter-traverser count = %lu\n", count ); + + return( (thread_return_t) EXIT_SUCCESS ); +} + diff --git a/liblfds/liblfds6.0.0/test/src/test_stack.c b/liblfds/liblfds6.0.0/test/src/test_stack.c new file mode 100644 index 0000000..36d4674 --- /dev/null +++ b/liblfds/liblfds6.0.0/test/src/test_stack.c @@ -0,0 +1,223 @@ +#include "internal.h" + + + + + +/****************************************************************************/ +void test_lfds600_stack( void ) +{ + unsigned int + loop, + cpu_count; + + struct lfds600_stack_state + *ss; + + thread_state_t + *thread_handles; + + /* TRD : there are 5 tests + + 1. single reader thread per CPU + - stack always empty + 2. single writer thread per CPU + - stack always full + 3. one reader and one writer thread per CPU + - stack balanced + 4. one reader and two writer threads per CPU + - stack grows + 5. two reader and one writer thread per CPU + - stack tends to empty + */ + + cpu_count = abstraction_cpu_count(); + + printf( "\n" + "Stack Test\n" + "==========\n" ); + + // TRD : 1. single reader thread per CPU + + printf( "\n" + "1. single reader thread per CPU\n" + "===============================\n" ); + + lfds600_stack_new( &ss, 10000 ); + + thread_handles = (thread_state_t *) malloc( sizeof(thread_state_t) * cpu_count * 1 ); + + for( loop = 0 ; loop < cpu_count ; loop++ ) + abstraction_thread_start( &thread_handles[loop], loop, lfds600_stack_internal_thread_reader, ss ); + + for( loop = 0 ; loop < cpu_count ; loop++ ) + abstraction_thread_wait( thread_handles[loop] ); + + lfds600_stack_delete( ss, NULL, NULL ); + + free( thread_handles ); + + // TRD : 2. single writer thread per CPU + + printf( "\n" + "2. single writer thread per CPU\n" + "===============================\n" ); + + lfds600_stack_new( &ss, 10000 ); + + thread_handles = (thread_state_t *) malloc( sizeof(thread_state_t) * cpu_count * 1 ); + + for( loop = 0 ; loop < cpu_count ; loop++ ) + abstraction_thread_start( &thread_handles[loop], loop, lfds600_stack_internal_thread_writer, ss ); + + for( loop = 0 ; loop < cpu_count ; loop++ ) + abstraction_thread_wait( thread_handles[loop] ); + + lfds600_stack_delete( ss, NULL, NULL ); + + free( thread_handles ); + + // TRD : 3. one reader and one writer thread per CPU + + printf( "\n" + "3. one reader and one writer thread per CPU\n" + "===========================================\n" ); + + lfds600_stack_new( &ss, 10000 ); + + thread_handles = (thread_state_t *) malloc( sizeof(thread_state_t) * cpu_count * 2 ); + + for( loop = 0 ; loop < cpu_count ; loop++ ) + { + abstraction_thread_start( &thread_handles[loop], loop, lfds600_stack_internal_thread_reader, ss ); + abstraction_thread_start( &thread_handles[loop+cpu_count], loop, lfds600_stack_internal_thread_writer, ss ); + } + + for( loop = 0 ; loop < cpu_count * 2 ; loop++ ) + abstraction_thread_wait( thread_handles[loop] ); + + lfds600_stack_delete( ss, NULL, NULL ); + + free( thread_handles ); + + // TRD : 4. one reader and two writer threads per CPU + + printf( "\n" + "4. one reader and two writer threads per CPU\n" + "============================================\n" ); + + lfds600_stack_new( &ss, 10000 ); + + thread_handles = (thread_state_t *) malloc( sizeof(thread_state_t) * cpu_count * 3 ); + + for( loop = 0 ; loop < cpu_count ; loop++ ) + { + abstraction_thread_start( &thread_handles[loop], loop, lfds600_stack_internal_thread_reader, ss ); + abstraction_thread_start( &thread_handles[loop+cpu_count], loop, lfds600_stack_internal_thread_writer, ss ); + abstraction_thread_start( &thread_handles[loop+cpu_count*2], loop, lfds600_stack_internal_thread_writer, ss ); + } + + for( loop = 0 ; loop < cpu_count * 3 ; loop++ ) + abstraction_thread_wait( thread_handles[loop] ); + + lfds600_stack_delete( ss, NULL, NULL ); + + free( thread_handles ); + + // TRD : 5. two reader and one writer thread per CPU + + printf( "\n" + "5. two reader and one writer thread per CPU\n" + "===========================================\n" ); + + lfds600_stack_new( &ss, 10000 ); + + thread_handles = (thread_state_t *) malloc( sizeof(thread_state_t) * cpu_count * 3 ); + + for( loop = 0 ; loop < cpu_count ; loop++ ) + { + abstraction_thread_start( &thread_handles[loop], loop, lfds600_stack_internal_thread_reader, ss ); + abstraction_thread_start( &thread_handles[loop+cpu_count], loop, lfds600_stack_internal_thread_reader, ss ); + abstraction_thread_start( &thread_handles[loop+cpu_count*2], loop, lfds600_stack_internal_thread_writer, ss ); + } + + for( loop = 0 ; loop < cpu_count * 3 ; loop++ ) + abstraction_thread_wait( thread_handles[loop] ); + + lfds600_stack_delete( ss, NULL, NULL ); + + free( thread_handles ); + + return; +} + + + + + +/****************************************************************************/ +thread_return_t CALLING_CONVENTION lfds600_stack_internal_thread_reader( void *lfds600_stack_state ) +{ + struct lfds600_stack_state + *ss; + + void + *user_data; + + time_t + start_time; + + unsigned long long int + count = 0; + + assert( lfds600_stack_state != NULL ); + + ss = (struct lfds600_stack_state *) lfds600_stack_state; + + time( &start_time ); + + while( time(NULL) < start_time + 10 ) + { + if( lfds600_stack_pop(ss, &user_data) ) + count++; + } + + printf( "read count = %llu\n", count ); + + return( (thread_return_t) EXIT_SUCCESS ); +} + + + + + +/****************************************************************************/ +thread_return_t CALLING_CONVENTION lfds600_stack_internal_thread_writer( void *lfds600_stack_state ) +{ + struct lfds600_stack_state + *ss; + + time_t + start_time; + + unsigned long long int + count = 0; + + assert( lfds600_stack_state != NULL ); + + ss = (struct lfds600_stack_state *) lfds600_stack_state; + + time( &start_time ); + + while( time(NULL) < start_time + 10 ) + { + // TRD : we don't store any user data + if( lfds600_stack_push(ss, NULL) ) + count++; + } + + printf( "write count = %llu\n", count ); + + return( (thread_return_t) EXIT_SUCCESS ); +} + diff --git a/liblfds/liblfds6.0.0/test/test.sln b/liblfds/liblfds6.0.0/test/test.sln new file mode 100644 index 0000000..85311a0 --- /dev/null +++ b/liblfds/liblfds6.0.0/test/test.sln @@ -0,0 +1,71 @@ + +Microsoft Visual Studio Solution File, Format Version 10.00 +# Visual Studio 2008 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "test", "test.vcproj", "{6E4CBF20-DF1A-4FA0-8A90-58E2A3A5CF09}" + ProjectSection(ProjectDependencies) = postProject + {F73AE755-F6D8-4C3A-977D-FBB40DC0ED05} = {F73AE755-F6D8-4C3A-977D-FBB40DC0ED05} + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "liblfds600", "..\liblfds600\liblfds600.vcproj", "{F73AE755-F6D8-4C3A-977D-FBB40DC0ED05}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug DLL|Win32 = Debug DLL|Win32 + Debug DLL|x64 = Debug DLL|x64 + Debug Lib|Win32 = Debug Lib|Win32 + Debug Lib|x64 = Debug Lib|x64 + Debug|Win32 = Debug|Win32 + Debug|x64 = Debug|x64 + Release DLL|Win32 = Release DLL|Win32 + Release DLL|x64 = Release DLL|x64 + Release Lib|Win32 = Release Lib|Win32 + Release Lib|x64 = Release Lib|x64 + Release|Win32 = Release|Win32 + Release|x64 = Release|x64 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {6E4CBF20-DF1A-4FA0-8A90-58E2A3A5CF09}.Debug DLL|Win32.ActiveCfg = Debug|Win32 + {6E4CBF20-DF1A-4FA0-8A90-58E2A3A5CF09}.Debug DLL|x64.ActiveCfg = Debug|x64 + {6E4CBF20-DF1A-4FA0-8A90-58E2A3A5CF09}.Debug Lib|Win32.ActiveCfg = Debug|Win32 + {6E4CBF20-DF1A-4FA0-8A90-58E2A3A5CF09}.Debug Lib|x64.ActiveCfg = Debug|x64 + {6E4CBF20-DF1A-4FA0-8A90-58E2A3A5CF09}.Debug|Win32.ActiveCfg = Debug|Win32 + {6E4CBF20-DF1A-4FA0-8A90-58E2A3A5CF09}.Debug|Win32.Build.0 = Debug|Win32 + {6E4CBF20-DF1A-4FA0-8A90-58E2A3A5CF09}.Debug|x64.ActiveCfg = Debug|x64 + {6E4CBF20-DF1A-4FA0-8A90-58E2A3A5CF09}.Debug|x64.Build.0 = Debug|x64 + {6E4CBF20-DF1A-4FA0-8A90-58E2A3A5CF09}.Release DLL|Win32.ActiveCfg = Release|Win32 + {6E4CBF20-DF1A-4FA0-8A90-58E2A3A5CF09}.Release DLL|x64.ActiveCfg = Release|x64 + {6E4CBF20-DF1A-4FA0-8A90-58E2A3A5CF09}.Release Lib|Win32.ActiveCfg = Release|Win32 + {6E4CBF20-DF1A-4FA0-8A90-58E2A3A5CF09}.Release Lib|x64.ActiveCfg = Release|x64 + {6E4CBF20-DF1A-4FA0-8A90-58E2A3A5CF09}.Release|Win32.ActiveCfg = Release|Win32 + {6E4CBF20-DF1A-4FA0-8A90-58E2A3A5CF09}.Release|Win32.Build.0 = Release|Win32 + {6E4CBF20-DF1A-4FA0-8A90-58E2A3A5CF09}.Release|x64.ActiveCfg = Release|x64 + {6E4CBF20-DF1A-4FA0-8A90-58E2A3A5CF09}.Release|x64.Build.0 = Release|x64 + {F73AE755-F6D8-4C3A-977D-FBB40DC0ED05}.Debug DLL|Win32.ActiveCfg = Debug DLL|Win32 + {F73AE755-F6D8-4C3A-977D-FBB40DC0ED05}.Debug DLL|Win32.Build.0 = Debug DLL|Win32 + {F73AE755-F6D8-4C3A-977D-FBB40DC0ED05}.Debug DLL|x64.ActiveCfg = Debug DLL|x64 + {F73AE755-F6D8-4C3A-977D-FBB40DC0ED05}.Debug DLL|x64.Build.0 = Debug DLL|x64 + {F73AE755-F6D8-4C3A-977D-FBB40DC0ED05}.Debug Lib|Win32.ActiveCfg = Debug Lib|Win32 + {F73AE755-F6D8-4C3A-977D-FBB40DC0ED05}.Debug Lib|Win32.Build.0 = Debug Lib|Win32 + {F73AE755-F6D8-4C3A-977D-FBB40DC0ED05}.Debug Lib|x64.ActiveCfg = Debug Lib|x64 + {F73AE755-F6D8-4C3A-977D-FBB40DC0ED05}.Debug Lib|x64.Build.0 = Debug Lib|x64 + {F73AE755-F6D8-4C3A-977D-FBB40DC0ED05}.Debug|Win32.ActiveCfg = Debug Lib|Win32 + {F73AE755-F6D8-4C3A-977D-FBB40DC0ED05}.Debug|Win32.Build.0 = Debug Lib|Win32 + {F73AE755-F6D8-4C3A-977D-FBB40DC0ED05}.Debug|x64.ActiveCfg = Debug Lib|x64 + {F73AE755-F6D8-4C3A-977D-FBB40DC0ED05}.Debug|x64.Build.0 = Debug Lib|x64 + {F73AE755-F6D8-4C3A-977D-FBB40DC0ED05}.Release DLL|Win32.ActiveCfg = Release DLL|Win32 + {F73AE755-F6D8-4C3A-977D-FBB40DC0ED05}.Release DLL|Win32.Build.0 = Release DLL|Win32 + {F73AE755-F6D8-4C3A-977D-FBB40DC0ED05}.Release DLL|x64.ActiveCfg = Release DLL|x64 + {F73AE755-F6D8-4C3A-977D-FBB40DC0ED05}.Release DLL|x64.Build.0 = Release DLL|x64 + {F73AE755-F6D8-4C3A-977D-FBB40DC0ED05}.Release Lib|Win32.ActiveCfg = Release Lib|Win32 + {F73AE755-F6D8-4C3A-977D-FBB40DC0ED05}.Release Lib|Win32.Build.0 = Release Lib|Win32 + {F73AE755-F6D8-4C3A-977D-FBB40DC0ED05}.Release Lib|x64.ActiveCfg = Release Lib|x64 + {F73AE755-F6D8-4C3A-977D-FBB40DC0ED05}.Release Lib|x64.Build.0 = Release Lib|x64 + {F73AE755-F6D8-4C3A-977D-FBB40DC0ED05}.Release|Win32.ActiveCfg = Release Lib|Win32 + {F73AE755-F6D8-4C3A-977D-FBB40DC0ED05}.Release|Win32.Build.0 = Release Lib|Win32 + {F73AE755-F6D8-4C3A-977D-FBB40DC0ED05}.Release|x64.ActiveCfg = Release Lib|x64 + {F73AE755-F6D8-4C3A-977D-FBB40DC0ED05}.Release|x64.Build.0 = Release Lib|x64 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/liblfds/liblfds6.0.0/test/test.vcproj b/liblfds/liblfds6.0.0/test/test.vcproj new file mode 100644 index 0000000..80685f9 --- /dev/null +++ b/liblfds/liblfds6.0.0/test/test.vcproj @@ -0,0 +1,415 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/liblfds/liblfds6.0.1/liblfds601/bin/empty_dir_placeholder_for_git b/liblfds/liblfds6.0.1/liblfds601/bin/empty_dir_placeholder_for_git new file mode 100644 index 0000000..e69de29 diff --git a/liblfds/liblfds6.0.1/liblfds601/building.txt b/liblfds/liblfds6.0.1/liblfds601/building.txt new file mode 100644 index 0000000..6d6a8b7 --- /dev/null +++ b/liblfds/liblfds6.0.1/liblfds601/building.txt @@ -0,0 +1,38 @@ +building liblfds +================ + +Windows (user-mode) +=================== +1. Use Microsoft Visual Studio 2008 or Visual C++ 2008 Express Edition + to load "liblfds.sln". + +2. Use Microsoft Windows SDK and GNUmake to run makefile.windows (obviously + you'll need to have run the appropriate vcvars*.bat first; you can build + for both IA64, 64-bit and 32-bit - just run the correct vcvars batch file). + + Targets are "librel", "libdbg", "dllrel", "dlldbg" and "clean". You need + to clean between switching targets. + +Windows (kernel) +================ +Use the Windows Driver Kit "build" command. Prior to running "build", +if you wish to build a static library, run the batch file +"runme_before_win_kernel_static_lib_build.bat"; if you wish to +build a dynamic library, instead run "runme_before_win_kernel_dynamic_lib_build.bat". + +The Windows kernel build system is rather limited and rather than +really rather messing up the directory/file structure just for the +Windows kernel platform, I've instead arranged it that these batch +files do the necessary work so that "build" will work. + +The batch files are idempotent; you can run them as often as you +like, in any order, at any time (before or after builds), and they'll +do the right thing. + +Linux +===== +Use GNUmake to run "makefile.linux". Targets are "arrel", "ardbg", +"sorel", "sodbg" and "clean". You need to clean between switching +targets. + + diff --git a/liblfds/liblfds6.0.1/liblfds601/dirs b/liblfds/liblfds6.0.1/liblfds601/dirs new file mode 100644 index 0000000..0be5295 --- /dev/null +++ b/liblfds/liblfds6.0.1/liblfds601/dirs @@ -0,0 +1,2 @@ +DIRS = src + diff --git a/liblfds/liblfds6.0.1/liblfds601/inc/liblfds601.h b/liblfds/liblfds6.0.1/liblfds601/inc/liblfds601.h new file mode 100644 index 0000000..a6cd58b --- /dev/null +++ b/liblfds/liblfds6.0.1/liblfds601/inc/liblfds601.h @@ -0,0 +1,282 @@ +#ifndef __LIBLFDS601_H + + /***** library header *****/ + #define LFDS601_RELEASE_NUMBER_STRING "6.0.1" + + + + + /***** lfds601_abstraction *****/ + + /***** defines *****/ + #if (defined _WIN64 && defined _MSC_VER && !defined WIN_KERNEL_BUILD) + // TRD : 64-bit Windows user-mode with the Microsoft C compiler, any CPU + #include + #include + #include + #include + #include + typedef unsigned __int64 lfds601_atom_t; + #define LFDS601_INLINE extern __forceinline + #define LFDS601_ALIGN(alignment) __declspec( align(alignment) ) + #define LFDS601_ALIGN_SINGLE_POINTER 8 + #define LFDS601_ALIGN_DOUBLE_POINTER 16 + #endif + + #if (!defined _WIN64 && defined _WIN32 && defined _MSC_VER && !defined WIN_KERNEL_BUILD) + // TRD : 32-bit Windows user-mode with the Microsoft C compiler, any CPU + #include + #include + #include + #include + #include + typedef unsigned long int lfds601_atom_t; + #define LFDS601_INLINE extern __forceinline + #define LFDS601_ALIGN(alignment) __declspec( align(alignment) ) + #define LFDS601_ALIGN_SINGLE_POINTER 4 + #define LFDS601_ALIGN_DOUBLE_POINTER 8 + + // TRD : this define is documented but missing in Microsoft Platform SDK v7.0 + #define _InterlockedCompareExchangePointer(destination, exchange, compare) _InterlockedCompareExchange((volatile long *) destination, (long) exchange, (long) compare) + #endif + + #if (defined _WIN64 && defined _MSC_VER && defined WIN_KERNEL_BUILD) + // TRD : 64-bit Windows kernel with the Microsoft C compiler, any CPU + #include + #include + #include + #include + typedef unsigned __int64 lfds601_atom_t; + #define LFDS601_INLINE extern __forceinline + #define LFDS601_ALIGN(alignment) __declspec( align(alignment) ) + #define LFDS601_ALIGN_SINGLE_POINTER 8 + #define LFDS601_ALIGN_DOUBLE_POINTER 16 + #endif + + #if (!defined _WIN64 && defined _WIN32 && defined _MSC_VER && defined WIN_KERNEL_BUILD) + // TRD : 32-bit Windows kernel with the Microsoft C compiler, any CPU + #include + #include + #include + #include + typedef unsigned long int lfds601_atom_t; + #define LFDS601_INLINE extern __forceinline + #define LFDS601_ALIGN(alignment) __declspec( align(alignment) ) + #define LFDS601_ALIGN_SINGLE_POINTER 4 + #define LFDS601_ALIGN_DOUBLE_POINTER 8 + + // TRD : this define is documented but missing in Microsoft Platform SDK v7.0 + #define _InterlockedCompareExchangePointer(destination, exchange, compare) _InterlockedCompareExchange((volatile long *) destination, (long) exchange, (long) compare) + #endif + + #if (defined __unix__ && defined __x86_64__ && __GNUC__) + // TRD : any UNIX with GCC on x64 + #define _XOPEN_SOURCE 600 + #include + #include + #include + typedef unsigned long long int lfds601_atom_t; + #define LFDS601_INLINE inline + #define LFDS601_ALIGN(alignment) __attribute__( (aligned(alignment)) ) + #define LFDS601_ALIGN_SINGLE_POINTER 8 + #define LFDS601_ALIGN_DOUBLE_POINTER 16 + #endif + + #if (defined __unix__ && defined __i686__ && __GNUC__) + // TRD : any UNIX with GCC on x86 + #define _XOPEN_SOURCE 600 + #include + #include + #include + typedef unsigned long int lfds601_atom_t; + #define LFDS601_INLINE inline + #define LFDS601_ALIGN(alignment) __attribute__( (aligned(alignment)) ) + #define LFDS601_ALIGN_SINGLE_POINTER 4 + #define LFDS601_ALIGN_DOUBLE_POINTER 8 + #endif + + #if (defined __unix__ && defined __arm__ && __GNUC__) + // TRD : any UNIX with GCC on ARM + #define _XOPEN_SOURCE 600 + #include + #include + #include + typedef unsigned long int lfds601_atom_t; + #define LFDS601_INLINE inline + #define LFDS601_ALIGN(alignment) __attribute__( (aligned(alignment)) ) + #define LFDS601_ALIGN_SINGLE_POINTER 4 + #define LFDS601_ALIGN_DOUBLE_POINTER 8 + #endif + + /***** enums *****/ + enum lfds601_data_structure_validity + { + LFDS601_VALIDITY_VALID, + LFDS601_VALIDITY_INVALID_LOOP, + LFDS601_VALIDITY_INVALID_MISSING_ELEMENTS, + LFDS601_VALIDITY_INVALID_ADDITIONAL_ELEMENTS, + LFDS601_VALIDITY_INVALID_TEST_DATA + }; + + /***** structs *****/ + struct lfds601_validation_info + { + lfds601_atom_t + min_elements, + max_elements; + }; + + /***** public prototypes *****/ + void lfds601_abstraction_aligned_free( void *memory ); + void *lfds601_abstraction_aligned_malloc( size_t size, size_t align_in_bytes ); + lfds601_atom_t lfds601_abstraction_cas( volatile lfds601_atom_t *destination, lfds601_atom_t exchange, lfds601_atom_t compare ); + unsigned char lfds601_abstraction_dcas( volatile lfds601_atom_t *destination, lfds601_atom_t *exchange, lfds601_atom_t *compare ); + lfds601_atom_t lfds601_abstraction_increment( lfds601_atom_t *value ); + + + + + + /***** lfds601_freelist *****/ + + /***** enums *****/ + enum lfds601_freelist_query_type + { + LFDS601_FREELIST_QUERY_ELEMENT_COUNT, + LFDS601_FREELIST_QUERY_VALIDATE + }; + + /***** incomplete types *****/ + struct lfds601_freelist_state; + struct lfds601_freelist_element; + + /***** public prototypes *****/ + int lfds601_freelist_new( struct lfds601_freelist_state **fs, lfds601_atom_t number_elements, int (*user_data_init_function)(void **user_data, void *user_state), void *user_state ); + void lfds601_freelist_delete( struct lfds601_freelist_state *fs, void (*user_data_delete_function)(void *user_data, void *user_state), void *user_state ); + + lfds601_atom_t lfds601_freelist_new_elements( struct lfds601_freelist_state *fs, lfds601_atom_t number_elements ); + + struct lfds601_freelist_element *lfds601_freelist_pop( struct lfds601_freelist_state *fs, struct lfds601_freelist_element **fe ); + struct lfds601_freelist_element *lfds601_freelist_guaranteed_pop( struct lfds601_freelist_state *fs, struct lfds601_freelist_element **fe ); + void lfds601_freelist_push( struct lfds601_freelist_state *fs, struct lfds601_freelist_element *fe ); + + void *lfds601_freelist_get_user_data_from_element( struct lfds601_freelist_element *fe, void **user_data ); + void lfds601_freelist_set_user_data_in_element( struct lfds601_freelist_element *fe, void *user_data ); + + void lfds601_freelist_query( struct lfds601_freelist_state *fs, enum lfds601_freelist_query_type query_type, void *query_input, void *query_output ); + + + + + + /***** lfds601_queue *****/ + + /***** enums *****/ + enum lfds601_queue_query_type + { + LFDS601_QUEUE_QUERY_ELEMENT_COUNT, + LFDS601_QUEUE_QUERY_VALIDATE + }; + + /***** incomplete types *****/ + struct lfds601_queue_state; + + /***** public prototypes *****/ + int lfds601_queue_new( struct lfds601_queue_state **sq, lfds601_atom_t number_elements ); + void lfds601_queue_delete( struct lfds601_queue_state *qs, void (*user_data_delete_function)(void *user_data, void *user_state), void *user_state ); + + int lfds601_queue_enqueue( struct lfds601_queue_state *qs, void *user_data ); + int lfds601_queue_guaranteed_enqueue( struct lfds601_queue_state *qs, void *user_data ); + int lfds601_queue_dequeue( struct lfds601_queue_state *qs, void **user_data ); + + void lfds601_queue_query( struct lfds601_queue_state *qs, enum lfds601_queue_query_type query_type, void *query_input, void *query_output ); + + + + + + /***** lfds601_ringbuffer *****/ + + /***** enums *****/ + enum lfds601_ringbuffer_query_type + { + LFDS601_RINGBUFFER_QUERY_VALIDATE + }; + + /***** incomplete types *****/ + struct lfds601_ringbuffer_state; + + /***** public prototypes *****/ + int lfds601_ringbuffer_new( struct lfds601_ringbuffer_state **rs, lfds601_atom_t number_elements, int (*user_data_init_function)(void **user_data, void *user_state), void *user_state ); + void lfds601_ringbuffer_delete( struct lfds601_ringbuffer_state *rs, void (*user_data_delete_function)(void *user_data, void *user_state), void *user_state ); + + struct lfds601_freelist_element *lfds601_ringbuffer_get_read_element( struct lfds601_ringbuffer_state *rs, struct lfds601_freelist_element **fe ); + struct lfds601_freelist_element *lfds601_ringbuffer_get_write_element( struct lfds601_ringbuffer_state *rs, struct lfds601_freelist_element **fe, int *overwrite_flag ); + + void lfds601_ringbuffer_put_read_element( struct lfds601_ringbuffer_state *rs, struct lfds601_freelist_element *fe ); + void lfds601_ringbuffer_put_write_element( struct lfds601_ringbuffer_state *rs, struct lfds601_freelist_element *fe ); + + void lfds601_ringbuffer_query( struct lfds601_ringbuffer_state *rs, enum lfds601_ringbuffer_query_type query_type, void *query_input, void *query_output ); + + + + + + /***** lfds601_slist *****/ + + /***** incomplete types *****/ + struct lfds601_slist_state; + struct lfds601_slist_element; + + /***** public prototypes *****/ + int lfds601_slist_new( struct lfds601_slist_state **ss, void (*user_data_delete_function)(void *user_data, void *user_state), void *user_state ); + void lfds601_slist_delete( struct lfds601_slist_state *ss ); + + struct lfds601_slist_element *lfds601_slist_new_head( struct lfds601_slist_state *ss, void *user_data ); + struct lfds601_slist_element *lfds601_slist_new_next( struct lfds601_slist_element *se, void *user_data ); + + void lfds601_slist_delete_element( struct lfds601_slist_state *ss, struct lfds601_slist_element *se ); + void lfds601_slist_delete_all_elements( struct lfds601_slist_state *ss ); + + int lfds601_slist_get_user_data_from_element( struct lfds601_slist_element *se, void **user_data ); + int lfds601_slist_set_user_data_in_element( struct lfds601_slist_element *se, void *user_data ); + + struct lfds601_slist_element *lfds601_slist_get_head( struct lfds601_slist_state *ss, struct lfds601_slist_element **se ); + struct lfds601_slist_element *lfds601_slist_get_next( struct lfds601_slist_element *se, struct lfds601_slist_element **next_se ); + struct lfds601_slist_element *lfds601_slist_get_head_and_then_next( struct lfds601_slist_state *ss, struct lfds601_slist_element **se ); + + + + + + /***** lfds601_stack *****/ + + /***** enums *****/ + enum lfds601_stack_query_type + { + LFDS601_STACK_QUERY_ELEMENT_COUNT + }; + + /***** incomplete types *****/ + struct lfds601_stack_state; + + /***** public prototypes *****/ + int lfds601_stack_new( struct lfds601_stack_state **ss, lfds601_atom_t number_elements ); + void lfds601_stack_delete( struct lfds601_stack_state *ss, void (*user_data_delete_function)(void *user_data, void *user_state), void *user_state ); + + void lfds601_stack_clear( struct lfds601_stack_state *ss, void (*user_data_clear_function)(void *user_data, void *user_state), void *user_state ); + + int lfds601_stack_push( struct lfds601_stack_state *ss, void *user_data ); + int lfds601_stack_guaranteed_push( struct lfds601_stack_state *ss, void *user_data ); + int lfds601_stack_pop( struct lfds601_stack_state *ss, void **user_data ); + + void lfds601_stack_query( struct lfds601_stack_state *ss, enum lfds601_stack_query_type query_type, void *query_input, void *query_output ); + + + + + + #define __LIBLFDS601_H + +#endif + diff --git a/liblfds/liblfds6.0.1/liblfds601/liblfds601.def b/liblfds/liblfds6.0.1/liblfds601/liblfds601.def new file mode 100644 index 0000000..65e8288 --- /dev/null +++ b/liblfds/liblfds6.0.1/liblfds601/liblfds601.def @@ -0,0 +1,46 @@ +EXPORTS + +lfds601_freelist_delete = lfds601_freelist_delete @1 +lfds601_freelist_get_user_data_from_element = lfds601_freelist_get_user_data_from_element @2 +lfds601_freelist_guaranteed_pop = lfds601_freelist_guaranteed_pop @3 +lfds601_freelist_new = lfds601_freelist_new @4 +lfds601_freelist_new_elements = lfds601_freelist_new_elements @5 +lfds601_freelist_pop = lfds601_freelist_pop @6 +lfds601_freelist_push = lfds601_freelist_push @7 +lfds601_freelist_query = lfds601_freelist_query @8 +lfds601_freelist_set_user_data_in_element = lfds601_freelist_set_user_data_in_element @9 + +lfds601_queue_delete = lfds601_queue_delete @10 +lfds601_queue_dequeue = lfds601_queue_dequeue @11 +lfds601_queue_enqueue = lfds601_queue_enqueue @12 +lfds601_queue_guaranteed_enqueue = lfds601_queue_guaranteed_enqueue @13 +lfds601_queue_new = lfds601_queue_new @14 +lfds601_queue_query = lfds601_queue_query @15 + +lfds601_ringbuffer_delete = lfds601_ringbuffer_delete @16 +lfds601_ringbuffer_get_read_element = lfds601_ringbuffer_get_read_element @17 +lfds601_ringbuffer_get_write_element = lfds601_ringbuffer_get_write_element @18 +lfds601_ringbuffer_new = lfds601_ringbuffer_new @19 +lfds601_ringbuffer_put_read_element = lfds601_ringbuffer_put_read_element @20 +lfds601_ringbuffer_put_write_element = lfds601_ringbuffer_put_write_element @21 + +lfds601_slist_delete = lfds601_slist_delete @ 22 +lfds601_slist_delete_all_elements = lfds601_slist_delete_all_elements @ 23 +lfds601_slist_delete_element = lfds601_slist_delete_element @ 24 +lfds601_slist_get_head = lfds601_slist_get_head @ 25 +lfds601_slist_get_head_and_then_next = lfds601_slist_get_head_and_then_next @ 26 +lfds601_slist_get_next = lfds601_slist_get_next @ 27 +lfds601_slist_get_user_data_from_element = lfds601_slist_get_user_data_from_element @ 28 +lfds601_slist_new = lfds601_slist_new @ 29 +lfds601_slist_new_head = lfds601_slist_new_head @ 30 +lfds601_slist_new_next = lfds601_slist_new_next @ 31 +lfds601_slist_set_user_data_in_element = lfds601_slist_set_user_data_in_element @ 32 + +lfds601_stack_clear = lfds601_stack_clear @33 +lfds601_stack_delete = lfds601_stack_delete @34 +lfds601_stack_guaranteed_push = lfds601_stack_guaranteed_push @35 +lfds601_stack_new = lfds601_stack_new @36 +lfds601_stack_pop = lfds601_stack_pop @37 +lfds601_stack_push = lfds601_stack_push @38 +lfds601_stack_query = lfds601_stack_query @39 + diff --git a/liblfds/liblfds6.0.1/liblfds601/liblfds601.sln b/liblfds/liblfds6.0.1/liblfds601/liblfds601.sln new file mode 100644 index 0000000..e8904d7 --- /dev/null +++ b/liblfds/liblfds6.0.1/liblfds601/liblfds601.sln @@ -0,0 +1,38 @@ + +Microsoft Visual Studio Solution File, Format Version 10.00 +# Visual Studio 2008 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "liblfds601", "liblfds601.vcproj", "{F73AE755-F6D8-4C3A-977D-FBB40DC0ED05}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug DLL|Win32 = Debug DLL|Win32 + Debug DLL|x64 = Debug DLL|x64 + Debug Lib|Win32 = Debug Lib|Win32 + Debug Lib|x64 = Debug Lib|x64 + Release DLL|Win32 = Release DLL|Win32 + Release DLL|x64 = Release DLL|x64 + Release Lib|Win32 = Release Lib|Win32 + Release Lib|x64 = Release Lib|x64 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {F73AE755-F6D8-4C3A-977D-FBB40DC0ED05}.Debug DLL|Win32.ActiveCfg = Debug DLL|Win32 + {F73AE755-F6D8-4C3A-977D-FBB40DC0ED05}.Debug DLL|Win32.Build.0 = Debug DLL|Win32 + {F73AE755-F6D8-4C3A-977D-FBB40DC0ED05}.Debug DLL|x64.ActiveCfg = Debug DLL|x64 + {F73AE755-F6D8-4C3A-977D-FBB40DC0ED05}.Debug DLL|x64.Build.0 = Debug DLL|x64 + {F73AE755-F6D8-4C3A-977D-FBB40DC0ED05}.Debug Lib|Win32.ActiveCfg = Debug Lib|Win32 + {F73AE755-F6D8-4C3A-977D-FBB40DC0ED05}.Debug Lib|Win32.Build.0 = Debug Lib|Win32 + {F73AE755-F6D8-4C3A-977D-FBB40DC0ED05}.Debug Lib|x64.ActiveCfg = Debug Lib|x64 + {F73AE755-F6D8-4C3A-977D-FBB40DC0ED05}.Debug Lib|x64.Build.0 = Debug Lib|x64 + {F73AE755-F6D8-4C3A-977D-FBB40DC0ED05}.Release DLL|Win32.ActiveCfg = Release DLL|Win32 + {F73AE755-F6D8-4C3A-977D-FBB40DC0ED05}.Release DLL|Win32.Build.0 = Release DLL|Win32 + {F73AE755-F6D8-4C3A-977D-FBB40DC0ED05}.Release DLL|x64.ActiveCfg = Release DLL|x64 + {F73AE755-F6D8-4C3A-977D-FBB40DC0ED05}.Release DLL|x64.Build.0 = Release DLL|x64 + {F73AE755-F6D8-4C3A-977D-FBB40DC0ED05}.Release Lib|Win32.ActiveCfg = Release Lib|Win32 + {F73AE755-F6D8-4C3A-977D-FBB40DC0ED05}.Release Lib|Win32.Build.0 = Release Lib|Win32 + {F73AE755-F6D8-4C3A-977D-FBB40DC0ED05}.Release Lib|x64.ActiveCfg = Release Lib|x64 + {F73AE755-F6D8-4C3A-977D-FBB40DC0ED05}.Release Lib|x64.Build.0 = Release Lib|x64 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/liblfds/liblfds6.0.1/liblfds601/liblfds601.vcproj b/liblfds/liblfds6.0.1/liblfds601/liblfds601.vcproj new file mode 100644 index 0000000..297fc09 --- /dev/null +++ b/liblfds/liblfds6.0.1/liblfds601/liblfds601.vcproj @@ -0,0 +1,808 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/liblfds/liblfds6.0.1/liblfds601/makefile.linux b/liblfds/liblfds6.0.1/liblfds601/makefile.linux new file mode 100644 index 0000000..b428cbf --- /dev/null +++ b/liblfds/liblfds6.0.1/liblfds601/makefile.linux @@ -0,0 +1,103 @@ +##### paths ##### +BINDIR = bin +INCDIR = inc +OBJDIR = obj +SRCDIR = src + +##### misc ##### +QUIETLY = 1>/dev/null 2>/dev/null + +##### sources, objects and libraries ##### +BINNAME = liblfds601 +AR_BINARY = $(BINDIR)/$(BINNAME).a +SO_BINARY = $(BINDIR)/$(BINNAME).so +SRCDIRS = lfds601_abstraction lfds601_freelist lfds601_queue lfds601_ringbuffer lfds601_slist lfds601_stack +# TRD : be aware - in the linux makefile, with the one-pass linking behaviour of the GNU linker, the order +# of source files matters! this is because it leads to the ordering of objects in the library and +# that in turn, since the data structures all use the freelist API and the abstraction API, has to be +# correct +SOURCES = lfds601_queue_delete.c lfds601_queue_new.c lfds601_queue_query.c lfds601_queue_queue.c \ + lfds601_ringbuffer_delete.c lfds601_ringbuffer_get_and_put.c lfds601_ringbuffer_new.c lfds601_ringbuffer_query.c \ + lfds601_slist_delete.c lfds601_slist_get_and_set.c lfds601_slist_link.c lfds601_slist_new.c \ + lfds601_stack_delete.c lfds601_stack_new.c lfds601_stack_push_pop.c lfds601_stack_query.c \ + lfds601_freelist_delete.c lfds601_freelist_get_and_set.c lfds601_freelist_new.c lfds601_freelist_query.c lfds601_freelist_pop_push.c \ + lfds601_abstraction_aligned_free.c lfds601_abstraction_aligned_malloc.c lfds601_abstraction_cas.c lfds601_abstraction_dcas.c lfds601_abstraction_increment.c +OBJECTS = $(patsubst %.c,$(OBJDIR)/%.o,$(notdir $(SOURCES))) + +##### CPU variants ##### +GCCARCH = $(shell uname -m) + +ifeq ($(GCCARCH),x86_64) + GCCARCH = core2 +endif + +ifeq ($(findstring arm,$(GCCARCH)),arm) + GCCARCH = armv6k +endif + +##### tools ##### +MAKE = make +MFLAGS = + +DG = gcc +DGFLAGS = -MM -std=c99 -I"$(SRCDIR)" -I"$(INCDIR)" + +CC = gcc +CBASE = -Wall -Wno-unknown-pragmas -std=c99 -march=$(GCCARCH) -c -I"$(SRCDIR)" -I"$(INCDIR)" +CFREL = -O2 -finline-functions -Wno-strict-aliasing +CFDBG = -O0 -g + +AR = ar +AFLAGS = -rcs + +LD = gcc +LFBASE = -Wall -std=c99 -shared +LFREL = -O2 -s +LFDBG = -O0 -g + +##### rel/dbg .a/.so variants ##### +ifeq ($(findstring so,$(MAKECMDGOALS)),so) + CBASE := $(CBASE) -fpic +endif + +CFLAGS = $(CBASE) $(CFDBG) +LFLAGS = $(LFBASE) $(LFDBG) + +ifeq ($(findstring rel,$(MAKECMDGOALS)),rel) + CFLAGS = $(CBASE) $(CFREL) + LFLAGS = $(LFBASE) $(LFREL) +endif + +##### search paths ##### +vpath %.c $(patsubst %,$(SRCDIR)/%:,$(SRCDIRS)) + +##### implicit rules ##### +$(OBJDIR)/%.o : %.c + $(DG) $(DGFLAGS) $< >$(OBJDIR)/$*.d + $(CC) $(CFLAGS) -o $@ $< + +##### explicit rules ##### +$(AR_BINARY) : $(OBJECTS) + $(AR) $(AFLAGS) $(AR_BINARY) $(OBJECTS) + +$(SO_BINARY) : $(OBJECTS) + $(LD) $(LFLAGS) $(SYSLIBS) $(OBJECTS) -o $(SO_BINARY) + +##### phony ##### +.PHONY : clean arrel ardbg sorel sodbg + +clean : + @rm -f $(BINDIR)/$(BINNAME).* $(OBJDIR)/*.o $(OBJDIR)/*.d + +arrel : $(AR_BINARY) +ardbg : $(AR_BINARY) + +sorel : $(SO_BINARY) +sodbg : $(SO_BINARY) + +##### dependencies ##### +-include $(DEPENDS) + +##### notes ##### +# TRD : we use -std=c99 purely to permit C++ style comments + diff --git a/liblfds/liblfds6.0.1/liblfds601/makefile.windows b/liblfds/liblfds6.0.1/liblfds601/makefile.windows new file mode 100644 index 0000000..2ce1e3d --- /dev/null +++ b/liblfds/liblfds6.0.1/liblfds601/makefile.windows @@ -0,0 +1,94 @@ +##### paths ##### +BINDIR = bin +INCDIR = inc +OBJDIR = obj +SRCDIR = src + +##### misc ##### +QUIETLY = 1>nul 2>nul + +##### sources, objects and libraries ##### +BINNAME = liblfds601 +LIB_BINARY = $(BINDIR)\$(BINNAME).lib +DLL_BINARY = $(BINDIR)\$(BINNAME).dll +SRCDIRS = lfds601_abstraction lfds601_freelist lfds601_queue lfds601_ringbuffer lfds601_slist lfds601_stack +SOURCES = lfds601_abstraction_aligned_free.c lfds601_abstraction_aligned_malloc.c lfds601_abstraction_cas.c lfds601_abstraction_dcas.c lfds601_abstraction_increment.c \ + lfds601_freelist_delete.c lfds601_freelist_get_and_set.c lfds601_freelist_new.c lfds601_freelist_query.c lfds601_freelist_pop_push.c \ + lfds601_queue_delete.c lfds601_queue_new.c lfds601_queue_query.c lfds601_queue_queue.c \ + lfds601_ringbuffer_delete.c lfds601_ringbuffer_get_and_put.c lfds601_ringbuffer_new.c lfds601_ringbuffer_query.c \ + lfds601_slist_delete.c lfds601_slist_get_and_set.c lfds601_slist_link.c lfds601_slist_new.c \ + lfds601_stack_delete.c lfds601_stack_new.c lfds601_stack_push_pop.c lfds601_stack_query.c +OBJECTS = $(patsubst %.c,$(OBJDIR)/%.obj,$(notdir $(SOURCES))) + +##### tools ##### +MAKE = make +MFLAGS = + +CC = cl +CBASE = /nologo /W4 /WX /c "-I$(SRCDIR)" "-I$(INCDIR)" "/Fd$(BINDIR)\$(BINNAME).pdb" /DUNICODE /D_UNICODE /DWIN32_LEAN_AND_MEAN +CFREL = /Ox /DNDEBUG +CFDBG = /Od /Gm /Zi /D_DEBUG + +AR = lib +AFLAGS = /nologo /subsystem:console /wx /verbose + +LD = link +LFBASE = /dll /def:$(BINNAME).def /nologo /subsystem:console /wx /nodefaultlib /nxcompat +LFREL = /incremental:no +LFDBG = /debug "/pdb:$(BINDIR)\$(BINNAME).pdb" + +##### variants ##### +CFLAGS = $(CBASE) $(CFDBG) /MTd +LFLAGS = $(LFBASE) $(LFDBG) +CLIB = libcmtd.lib + +ifeq ($(MAKECMDGOALS),librel) + CFLAGS = $(CBASE) $(CFREL) /MT + LFLAGS = $(LFBASE) $(LFREL) + CLIB = libcmt.lib +endif + +ifeq ($(MAKECMDGOALS),libdbg) + CFLAGS = $(CBASE) $(CFDBG) /MTd + LFLAGS = $(LFBASE) $(LFDBG) + CLIB = libcmtd.lib +endif + +ifeq ($(MAKECMDGOALS),dllrel) + CFLAGS = $(CBASE) $(CFREL) /MD + LFLAGS = $(LFBASE) $(LFREL) + CLIB = msvcrt.lib +endif + +ifeq ($(MAKECMDGOALS),dlldbg) + CFLAGS = $(CBASE) $(CFDBG) /MDd + LFLAGS = $(LFBASE) $(LFDBG) + CLIB = msvcrtd.lib +endif + +##### search paths ##### +vpath %.c $(patsubst %,$(SRCDIR)/%;,$(SRCDIRS)) + +##### implicit rules ##### +$(OBJDIR)/%.obj : %.c + $(CC) $(CFLAGS) "/Fo$@" $< + +##### explicit rules ##### +$(LIB_BINARY) : $(OBJECTS) + $(AR) $(AFLAGS) $(OBJECTS) /out:$(LIB_BINARY) + +$(DLL_BINARY) : $(OBJECTS) + $(LD) $(LFLAGS) $(CLIB) $(OBJECTS) /out:$(DLL_BINARY) + +##### phony ##### +.PHONY : clean librel libdbg dllrel dlldbg + +clean : + @erase /Q $(BINDIR)\$(BINNAME).* $(OBJDIR)\*.obj $(QUIETLY) + +librel : $(LIB_BINARY) +libdbg : $(LIB_BINARY) + +dllrel : $(DLL_BINARY) +dlldbg : $(DLL_BINARY) + diff --git a/liblfds/liblfds6.0.1/liblfds601/obj/empty_dir_placeholder_for_git b/liblfds/liblfds6.0.1/liblfds601/obj/empty_dir_placeholder_for_git new file mode 100644 index 0000000..e69de29 diff --git a/liblfds/liblfds6.0.1/liblfds601/readme.txt b/liblfds/liblfds6.0.1/liblfds601/readme.txt new file mode 100644 index 0000000..4d55b06 --- /dev/null +++ b/liblfds/liblfds6.0.1/liblfds601/readme.txt @@ -0,0 +1,139 @@ +introduction +============ +Welcome to liblfds, a portable, license-free, lock-free data structure +library written in C. + +platforms +========= +Currently liblfds out-of-the-box supports; + +Operating System CPU Toolset +================ ========== ======= +Windows 64-bit IA64 & x64 1. Microsoft Visual Studio 2008 + 2. Microsoft Windows SDK and GNUmake >= 3.8.1 + +Windows 32-bit x64 & x86 1. Microsoft Visual Studio 2008 + 2. Visual C++ 2008 Express Edition + 3. Microsoft Windows SDK and GNUmake >= 3.8.1 + +Windows Kernel IA64, x64, 1. Windows Driver Kit >= 7.0.0 + x86 + +Linux 64-bit x64 1. GCC >= 4.1.0 and GNUmake >= 3.8.1 + +Linux 32-bit x64, x86, 1. GCC >= 4.1.0 and GNUmake >= 3.8.1 + ARM + +data structures +=============== +Currently liblfds provides the following; + +* Freelist +* Queue +* Ringbuffer +* Singly linked list (logical delete only) +* Stack + +liblfds on-line +=============== +On the liblfds home page, you will find the blog, a bugzilla, a forum, a +wikipedia and the current and all historical source releases. + +The wikipedia contains comprehensive documentation for development, +building, testing and porting. + +http://www.liblfds.org + +license +======= +There is no license. You are free to use this code in any way. + +building +======== +On Windows, depending on your target platform, one of the following toolchains +is required; + + * Microsoft Visual Studio 2008 (expensive) + * Visual C++ 2008 Express Edition (free, but no 64 bit support) + * Microsoft Windows SDK (free, no GUI, has 64 bit support) and GNUmake 3.81 + +On Windows (kernel-mode), the following toolchain is required; + + * Windows Driver Kit 7.0.0 or later + +On Linux, the following toolchain is required; + + * gcc 4.1.0 or later and GNUmake 3.81 + +For documentation, see the building guide in the wikipedia. + +using +===== +Once built, there is a single header file, /inc/liblfds.h, which you must include +in your source code, and a single library file /bin/liblfds.*, where the suffix +depends on your platform and your build choice (static or dynamic), to which, +if statically built, you must link directly or, if dynamically built, you must +arrange your system such that the library can be found by the loader at run-time. + +testing +======= +The library comes with a command line test and benchmark program. This +program requires threads. As such, it is only suitable for platforms providing +thread support and which can execute a command line binary. Currently this +means the test and benchmark program works for all platforms except the Windows +Kernel. + +For documentation, see the testing and benchmarking guide in the wikipedia. + +porting +======= +Both the test program and liblfds provide an abstraction layer which acts to +mask platform differences. Porting is the act of implementing on your platform +the functions which make up the abstraction layers. You do not need to port +the test program to port liblfds, but obviously it is recommended, so you can +test your port. + +To support liblfds, your platform must support either contigious double-word +compare-and-swap (e.g. x86/x64) or contigious double-word load-link/conditional-store +where normal loads cannot occur inside the LL/CS pair (e.g. ARM) or single word +load-link/conditional-store where normal loads can occur inside the LL/CS pair. + +For documentation, see the porting guide in the wikipedia. + +release history +=============== +release 1, 25th September 2009, svn revision 1574. + - initial release + +release 2, 5th October 2009, svn revision 1599. + - added abstraction layer for Windows kernel + - minor code tidyups/fixes + +release 3, 25th October 2009, svn revision 1652. + - added singly linked list (logical delete only) + - minor code tidyups/fixes + +release 4, 7th December 2009, svn revision 1716. + - added ARM support + - added benchmarking functionality to the test program + - fixed a profound and pervasive pointer + decleration bug; earlier releases of liblfds + *should not be used* + +release 5, 19th December 2009, svn revision 1738. + - fixed subtle queue bug, which also affected ringbuffer + and caused data re-ordering under high load + - added benchmarks for freelist, ringbuffer and stack + +release 6, 29th December 2009, svn revision 1746. + - fixed two implementation errors, which reduced performance, + spotted by Codeplug from "http://cboard.cprogramming.com". + +release 6.0.0, 18th December 2012, svn revision 2537 + - introduction of namespaces, e.g. the "lfds601_" prefix + code otherwise COMPLETE AND WHOLLY UNCHANGED + this release is a stepping-stone to 6.1.0 + +release 6.0.1, 2nd January 2013, svn revision 3296 + - bug fix where an enum wasn't moved into the new namespacing policy + diff --git a/liblfds/liblfds6.0.1/liblfds601/runme_before_win_kernel_build_readme.txt b/liblfds/liblfds6.0.1/liblfds601/runme_before_win_kernel_build_readme.txt new file mode 100644 index 0000000..d7087ec --- /dev/null +++ b/liblfds/liblfds6.0.1/liblfds601/runme_before_win_kernel_build_readme.txt @@ -0,0 +1,32 @@ +The Windows kernel build environment is primitive and has a number +of severe limitations; in particular, all source files must be in +one directory and it is not possible to choose the output binary type +(static or dynamic library) from the build command line; rather, +a string has to be modified in a text file used by the build (!) + +To deal with these limitations, it is necessary for a Windows kernel +build to run a batch file prior to building. + +There are two batch files, one for static library builds and the other +for dynamic library builds. + +They are both idempotent; you can run them as often as you like and +switch between them as often as you want. It's all fine; whenever +you run one of them, it will take you from whatever state you were +previously in, into the state you want to be in. + +Both batch files copy all the sources file into a single directory, +"/src/single_dir_for_windows_kernel/". + +The static library batch file will then copy "/sources.static" into +"/src/single_dir_for_windows_kernel/", which will cause a static +library to be built. + +The dynamic library batch file will then copy "/sources.dynamic" into +"/src/single_dir_for_windows_kernel/", which will cause a dynamic +library to be built. It will also copy "src/driver_entry.c" into +"/src/single_dir_for_windows_kernel/", since the linker requires +the DriverEntry function to exist for dynamic libraries, even +though it's not used. + + diff --git a/liblfds/liblfds6.0.1/liblfds601/runme_before_win_kernel_dynamic_lib_build.bat b/liblfds/liblfds6.0.1/liblfds601/runme_before_win_kernel_dynamic_lib_build.bat new file mode 100644 index 0000000..e0e3a15 --- /dev/null +++ b/liblfds/liblfds6.0.1/liblfds601/runme_before_win_kernel_dynamic_lib_build.bat @@ -0,0 +1,14 @@ +@echo off +rmdir /q /s src\single_dir_for_windows_kernel 1>nul 2>nul +mkdir src\single_dir_for_windows_kernel 1>nul 2>nul +copy /y src\lfds601_abstraction\* src\single_dir_for_windows_kernel 1>nul 2>nul +copy /y src\lfds601_freelist\* src\single_dir_for_windows_kernel 1>nul 2>nul +copy /y src\lfds601_queue\* src\single_dir_for_windows_kernel 1>nul 2>nul +copy /y src\lfds601_ringbuffer\* src\single_dir_for_windows_kernel 1>nul 2>nul +copy /y src\lfds601_slist\* src\single_dir_for_windows_kernel 1>nul 2>nul +copy /y src\lfds601_stack\* src\single_dir_for_windows_kernel 1>nul 2>nul +copy /y sources.dynamic src\single_dir_for_windows_kernel\sources 1>nul 2>nul +copy /y src\driver_entry.c src\single_dir_for_windows_kernel 1>nul 2>nul +echo Windows kernel dynamic library build directory structure created. +echo (Note the effects of this batch file are idempotent). + diff --git a/liblfds/liblfds6.0.1/liblfds601/runme_before_win_kernel_static_lib_build.bat b/liblfds/liblfds6.0.1/liblfds601/runme_before_win_kernel_static_lib_build.bat new file mode 100644 index 0000000..00dd8a5 --- /dev/null +++ b/liblfds/liblfds6.0.1/liblfds601/runme_before_win_kernel_static_lib_build.bat @@ -0,0 +1,14 @@ +@echo off +rmdir /q /s src\single_dir_for_windows_kernel 1>nul 2>nul +mkdir src\single_dir_for_windows_kernel 1>nul 2>nul +copy /y src\lfds601_abstraction\* src\single_dir_for_windows_kernel 1>nul 2>nul +copy /y src\lfds601_freelist\* src\single_dir_for_windows_kernel 1>nul 2>nul +copy /y src\lfds601_queue\* src\single_dir_for_windows_kernel 1>nul 2>nul +copy /y src\lfds601_ringbuffer\* src\single_dir_for_windows_kernel 1>nul 2>nul +copy /y src\lfds601_slist\* src\single_dir_for_windows_kernel 1>nul 2>nul +copy /y src\lfds601_stack\* src\single_dir_for_windows_kernel 1>nul 2>nul +copy /y sources.static src\single_dir_for_windows_kernel\sources 1>nul 2>nul +erase /f src\single_dir_for_windows_kernel\driver_entry.c 1>nul 2>nul +echo Windows kernel static library build directory structure created. +echo (Note the effects of this batch file are idempotent). + diff --git a/liblfds/liblfds6.0.1/liblfds601/sources.dynamic b/liblfds/liblfds6.0.1/liblfds601/sources.dynamic new file mode 100644 index 0000000..4b5328e --- /dev/null +++ b/liblfds/liblfds6.0.1/liblfds601/sources.dynamic @@ -0,0 +1,37 @@ +MSC_WARNING_LEVEL = /WX /W4 +DLLDEF = ../../liblfds601.def +TARGETNAME = liblfds601 +TARGETPATH = ../../bin/ +TARGETTYPE = EXPORT_DRIVER +UMTYPE = nt +USER_C_FLAGS = /DWIN_KERNEL_BUILD + +INCLUDES = ..;../../inc/ +SOURCES = lfds601_abstraction_aligned_free.c \ + lfds601_abstraction_aligned_malloc.c \ + lfds601_abstraction_cas.c \ + lfds601_abstraction_dcas.c \ + lfds601_abstraction_increment.c \ + lfds601_freelist_delete.c \ + lfds601_freelist_get_and_set.c \ + lfds601_freelist_new.c \ + lfds601_freelist_pop_push.c \ + lfds601_freelist_query.c \ + lfds601_queue_delete.c \ + lfds601_queue_new.c \ + lfds601_queue_query.c \ + lfds601_queue_queue.c \ + lfds601_ringbuffer_delete.c \ + lfds601_ringbuffer_get_and_put.c \ + lfds601_ringbuffer_new.c \ + lfds601_ringbuffer_query.c \ + lfds601_slist_delete.c \ + lfds601_slist_get_and_set.c \ + lfds601_slist_link.c \ + lfds601_slist_new.c \ + lfds601_stack_delete.c \ + lfds601_stack_new.c \ + lfds601_stack_push_pop.c \ + lfds601_stack_query.c \ + driver_entry.c + diff --git a/liblfds/liblfds6.0.1/liblfds601/sources.static b/liblfds/liblfds6.0.1/liblfds601/sources.static new file mode 100644 index 0000000..fd6135d --- /dev/null +++ b/liblfds/liblfds6.0.1/liblfds601/sources.static @@ -0,0 +1,35 @@ +MSC_WARNING_LEVEL = /WX /W4 +TARGETNAME = liblfds601 +TARGETPATH = ../../bin/ +TARGETTYPE = DRIVER_LIBRARY +UMTYPE = nt +USER_C_FLAGS = /DWIN_KERNEL_BUILD + +INCLUDES = ..;../../inc/ +SOURCES = lfds601_abstraction_aligned_free.c \ + lfds601_abstraction_aligned_malloc.c \ + lfds601_abstraction_cas.c \ + lfds601_abstraction_dcas.c \ + lfds601_abstraction_increment.c \ + lfds601_freelist_delete.c \ + lfds601_freelist_get_and_set.c \ + lfds601_freelist_new.c \ + lfds601_freelist_pop_push.c \ + lfds601_freelist_query.c \ + lfds601_queue_delete.c \ + lfds601_queue_new.c \ + lfds601_queue_query.c \ + lfds601_queue_queue.c \ + lfds601_ringbuffer_delete.c \ + lfds601_ringbuffer_get_and_put.c \ + lfds601_ringbuffer_new.c \ + lfds601_ringbuffer_query.c \ + lfds601_slist_delete.c \ + lfds601_slist_get_and_set.c \ + lfds601_slist_link.c \ + lfds601_slist_new.c \ + lfds601_stack_delete.c \ + lfds601_stack_new.c \ + lfds601_stack_push_pop.c \ + lfds601_stack_query.c + diff --git a/liblfds/liblfds6.0.1/liblfds601/src/dirs b/liblfds/liblfds6.0.1/liblfds601/src/dirs new file mode 100644 index 0000000..64e002c --- /dev/null +++ b/liblfds/liblfds6.0.1/liblfds601/src/dirs @@ -0,0 +1,3 @@ +DIRS = single_dir_for_windows_kernel + + diff --git a/liblfds/liblfds6.0.1/liblfds601/src/driver_entry.c b/liblfds/liblfds6.0.1/liblfds601/src/driver_entry.c new file mode 100644 index 0000000..96f1c80 --- /dev/null +++ b/liblfds/liblfds6.0.1/liblfds601/src/driver_entry.c @@ -0,0 +1,16 @@ +#include "lfds601_stack_internal.h" + + + + + +/****************************************************************************/ +#pragma warning( disable : 4100 ) + +NTSTATUS DriverEntry( struct _DRIVER_OBJECT *DriverObject, PUNICODE_STRING RegistryPath ) +{ + return( STATUS_SUCCESS ); +} + +#pragma warning( default : 4100 ) + diff --git a/liblfds/liblfds6.0.1/liblfds601/src/driver_entry_readme.txt b/liblfds/liblfds6.0.1/liblfds601/src/driver_entry_readme.txt new file mode 100644 index 0000000..a397977 --- /dev/null +++ b/liblfds/liblfds6.0.1/liblfds601/src/driver_entry_readme.txt @@ -0,0 +1,4 @@ +This C file (driver_entry.c) is used when building a dynamic library for +the Windows kernel. It exists to work around one of the limitations of +that build environment. It is not used by any other build; just ignore it. + diff --git a/liblfds/liblfds6.0.1/liblfds601/src/lfds601_abstraction/lfds601_abstraction_aligned_free.c b/liblfds/liblfds6.0.1/liblfds601/src/lfds601_abstraction/lfds601_abstraction_aligned_free.c new file mode 100644 index 0000000..735313c --- /dev/null +++ b/liblfds/liblfds6.0.1/liblfds601/src/lfds601_abstraction/lfds601_abstraction_aligned_free.c @@ -0,0 +1,72 @@ +#include "lfds601_abstraction_internal.h" + + + + + +/****************************************************************************/ +#if (defined _WIN32 && defined _MSC_VER && !defined WIN_KERNEL_BUILD) + + /* TRD : any Windows (user-mode) on any CPU with the Microsoft C compiler + + _WIN32 indicates 64-bit or 32-bit Windows + _MSC_VER indicates Microsoft C compiler + !WIN_KERNEL_BUILD indicates Windows user-mode + */ + + void lfds601_abstraction_aligned_free( void *memory ) + { + _aligned_free( memory ); + + return; + } + +#endif + + + + + +/****************************************************************************/ +#if (_XOPEN_SOURCE >= 600) + + /* TRD : any OS on any CPU with any compiler with POSIX 6.00 or better + + _XOPEN_SOURCE is actually set by the user, not by the compiler + it is the way the user signals to the compiler what + level of POSIX should be available + (it assumes of course the compiler has support for the given level of POSIX requested) + */ + + void lfds601_abstraction_aligned_free( void *memory ) + { + free( memory ); + + return; + } + +#endif + + + + + +/****************************************************************************/ +#if (defined _WIN32 && defined _MSC_VER && defined WIN_KERNEL_BUILD) + + /* TRD : any Windows (kernel) on any CPU with the Microsoft C compiler + + _WIN32 indicates 64-bit or 32-bit Windows + _MSC_VER indicates Microsoft C compiler + WIN_KERNEL_BUILD indicates Windows kernel + */ + + void lfds601_abstraction_aligned_free( void *memory ) + { + ExFreePoolWithTag( memory, 'sdfl' ); + + return; + } + +#endif + diff --git a/liblfds/liblfds6.0.1/liblfds601/src/lfds601_abstraction/lfds601_abstraction_aligned_malloc.c b/liblfds/liblfds6.0.1/liblfds601/src/lfds601_abstraction/lfds601_abstraction_aligned_malloc.c new file mode 100644 index 0000000..0d6ff9c --- /dev/null +++ b/liblfds/liblfds6.0.1/liblfds601/src/lfds601_abstraction/lfds601_abstraction_aligned_malloc.c @@ -0,0 +1,97 @@ +#include "lfds601_abstraction_internal.h" + + + + + +/****************************************************************************/ +#if (defined _WIN32 && defined _MSC_VER && !defined WIN_KERNEL_BUILD) + + /* TRD : any Windows (user-mode) on any CPU with the Microsoft C compiler + + _WIN32 indicates 64-bit or 32-bit Windows + _MSC_VER indicates Microsoft C compiler + !WIN_KERNEL_BUILD indicates Windows user-mode + */ + + void *lfds601_abstraction_aligned_malloc( size_t size, size_t align_in_bytes ) + { + void + *rv; + + rv = _aligned_malloc( size, align_in_bytes ); + + return( rv ); + } + +#endif + + + + + +/****************************************************************************/ +#if (_XOPEN_SOURCE >= 600) + + /* TRD : any OS on any CPU with any compiler with POSIX 6.00 or better + + _XOPEN_SOURCE is actually set by the user, not by the compiler + it is the way the user signals to the compiler what + level of POSIX should be available + (it assumes of course the compiler has support for the given level of POSIX requested) + */ + + void *lfds601_abstraction_aligned_malloc( size_t size, size_t align_in_bytes ) + { + int + rv; + + void + *memory; + + rv = posix_memalign( &memory, align_in_bytes, size ); + + // TRD : posix_memalign returns 0 on success, docs do not say *memory == NULL on fail + if( rv != 0 ) + memory = NULL; + + return( memory ); + } + +#endif + + + + + +/****************************************************************************/ +#if (defined _WIN32 && defined _MSC_VER && defined WIN_KERNEL_BUILD) + + /* TRD : any Windows (kernel) on any CPU with the Microsoft C compiler + + _WIN32 indicates 64-bit or 32-bit Windows + _MSC_VER indicates Microsoft C compiler + WIN_KERNEL_BUILD indicates Windows kernel + */ + + void *lfds601_abstraction_aligned_malloc( size_t size, size_t align_in_bytes ) + { + void + *rv; + + /* TRD : ExAllocatePoolWithTag() allocates memory aligned on 8 bytes on 32-bit CPUs + and on 16 bytes on 64-bit CPUs, which is what we want + + as such, align_in_bytes is not needed; we must refer to it to avoid the + compiler warning + */ + + align_in_bytes; + + rv = ExAllocatePoolWithTag( NonPagedPool, size, 'sdfl' ); + + return( rv ); + } + +#endif + diff --git a/liblfds/liblfds6.0.1/liblfds601/src/lfds601_abstraction/lfds601_abstraction_cas.c b/liblfds/liblfds6.0.1/liblfds601/src/lfds601_abstraction/lfds601_abstraction_cas.c new file mode 100644 index 0000000..18b1590 --- /dev/null +++ b/liblfds/liblfds6.0.1/liblfds601/src/lfds601_abstraction/lfds601_abstraction_cas.c @@ -0,0 +1,109 @@ +#include "lfds601_abstraction_internal.h" + + + + + +/****************************************************************************/ +#if (defined _WIN32 && defined _MSC_VER) + + /* TRD : 64 bit and 32 bit Windows (user-mode or kernel) on any CPU with the Microsoft C compiler + + _WIN32 indicates 64-bit or 32-bit Windows + _MSC_VER indicates Microsoft C compiler + */ + + LFDS601_INLINE lfds601_atom_t lfds601_abstraction_cas( volatile lfds601_atom_t *destination, lfds601_atom_t exchange, lfds601_atom_t compare ) + { + assert( destination != NULL ); + // TRD : exchange can be any value in its range + // TRD : compare can be any value in its range + + return( (lfds601_atom_t) _InterlockedCompareExchangePointer((void * volatile *) destination, (void *) exchange, (void *) compare) ); + } + +#endif + + + + + +/****************************************************************************/ +#if (!defined __arm__ && __GNUC__ >= 4 && __GNUC_MINOR__ >= 1 && __GNUC_PATCHLEVEL__ >= 0) + + /* TRD : any OS on any CPU except ARM with GCC 4.1.0 or better + + GCC 4.1.0 introduced the __sync_*() atomic intrinsics + + __GNUC__ / __GNUC_MINOR__ / __GNUC_PATCHLEVEL__ indicates GCC and which version + */ + + LFDS601_INLINE lfds601_atom_t lfds601_abstraction_cas( volatile lfds601_atom_t *destination, lfds601_atom_t exchange, lfds601_atom_t compare ) + { + assert( destination != NULL ); + // TRD : exchange can be any value in its range + // TRD : compare can be any value in its range + + // TRD : note the different argument order for the GCC instrinsic to the MSVC instrinsic + + return( (lfds601_atom_t) __sync_val_compare_and_swap(destination, compare, exchange) ); + } + +#endif + + + + + +/****************************************************************************/ +#if (defined __arm__ && __GNUC__) + + /* TRD : any OS on any ARM with GCC + + Remember however we need to set into compare the original value of destination. + + __arm__ indicates ARM + __GNUC__ indicates GCC + */ + + LFDS601_INLINE lfds601_atom_t lfds601_abstraction_cas( volatile lfds601_atom_t *destination, lfds601_atom_t exchange, lfds601_atom_t compare ) + { + lfds601_atom_t + stored_flag, + original_destination; + + assert( destination != NULL ); + // TRD : exchange can be any value in its range + // TRD : compare can be any value in its range + + /* TRD : this is a standard, plain CAS, vulnerable to ABA */ + + __asm__ __volatile__ + ( + " mov %[stored_flag], #1;" // put 1 into stored_flag + " mcr p15, 0, %[zero], c7, c10, 5;" // memory barrier (ARM v6 compatible) + "atomic_cas:;" + " ldrex %[original_destination], [%[destination]];" // load *destination into original_destination + " teq %[original_destination], %[compare];" // compare original_destination with compare + " bne exit;" // if not equal, exit + " strex %[stored_flag], %[exchange], [%[destination]];" // if equal, try to store exchange into *destination (on success, strex puts 0 into stored_flag) + " teq %[stored_flag], #0;" // check if stored_flag is 0 + " bne atomic_cas;" // if not 0, retry (someone else touched *destination after we loaded but before we stored) + " mcr p15, 0, %[zero], c7, c10, 5;" // memory barrier (ARM v6 compatible) + "exit:;" + + // output + : "+m" (*destination), [original_destination] "=&r" (original_destination), [stored_flag] "=&r" (stored_flag) + + // input + : [destination] "r" (destination), [compare] "r" (compare), [exchange] "r" (exchange), [zero] "r" (0) + + // clobbered + : "cc", "memory" // memory is clobbered because we issue a memory barrier + ); + + return( original_destination ); + } + +#endif + diff --git a/liblfds/liblfds6.0.1/liblfds601/src/lfds601_abstraction/lfds601_abstraction_dcas.c b/liblfds/liblfds6.0.1/liblfds601/src/lfds601_abstraction/lfds601_abstraction_dcas.c new file mode 100644 index 0000000..6da4c7a --- /dev/null +++ b/liblfds/liblfds6.0.1/liblfds601/src/lfds601_abstraction/lfds601_abstraction_dcas.c @@ -0,0 +1,356 @@ +#include "lfds601_abstraction_internal.h" + + + + + +/****************************************************************************/ +#if (defined _WIN64 && defined _MSC_VER) + + /* TRD : 64 bit Windows (user-mode or kernel) on any CPU with the Microsoft C compiler + + _WIN64 indicates 64 bit Windows + _MSC_VER indicates Microsoft C compiler + */ + + LFDS601_INLINE unsigned char lfds601_abstraction_dcas( volatile lfds601_atom_t *destination, lfds601_atom_t *exchange, lfds601_atom_t *compare ) + { + unsigned char + cas_result; + + assert( destination != NULL ); + assert( exchange != NULL ); + assert( compare != NULL ); + + cas_result = _InterlockedCompareExchange128( (volatile __int64 *) destination, (__int64) *(exchange+1), (__int64) *exchange, (__int64 *) compare ); + + return( cas_result ); + } + +#endif + + + + + +/****************************************************************************/ +#if (!defined _WIN64 && defined _WIN32 && defined _MSC_VER) + + /* TRD : 32 bit Windows (user-mode or kernel) on any CPU with the Microsoft C compiler + + (!defined _WIN64 && defined _WIN32) indicates 32 bit Windows + _MSC_VER indicates Microsoft C compiler + */ + + LFDS601_INLINE unsigned char lfds601_abstraction_dcas( volatile lfds601_atom_t *destination, lfds601_atom_t *exchange, lfds601_atom_t *compare ) + { + __int64 + original_compare; + + assert( destination != NULL ); + assert( exchange != NULL ); + assert( compare != NULL ); + + *(__int64 *) &original_compare = *(__int64 *) compare; + + *(__int64 *) compare = _InterlockedCompareExchange64( (volatile __int64 *) destination, *(__int64 *) exchange, *(__int64 *) compare ); + + return( (unsigned char) (*(__int64 *) compare == *(__int64 *) &original_compare) ); + } + +#endif + + + + + +/****************************************************************************/ +#if (defined __x86_64__ && __GNUC__ && !defined __pic__) + + /* TRD : any OS on x64 with GCC for statically linked code + + __x86_64__ indicates x64 + __GNUC__ indicates GCC + */ + + LFDS601_INLINE unsigned char lfds601_abstraction_dcas( volatile lfds601_atom_t *destination, lfds601_atom_t *exchange, lfds601_atom_t *compare ) + { + unsigned char + cas_result; + + assert( destination != NULL ); + assert( exchange != NULL ); + assert( compare != NULL ); + + __asm__ __volatile__ + ( + "lock;" // make cmpxchg16b atomic + "cmpxchg16b %0;" // cmpxchg16b sets ZF on success + "setz %3;" // if ZF set, set cas_result to 1 + + // output + : "+m" (*(volatile lfds601_atom_t (*)[2]) destination), "+a" (*compare), "+d" (*(compare+1)), "=q" (cas_result) + + // input + : "b" (*exchange), "c" (*(exchange+1)) + + // clobbered + : "cc", "memory" + ); + + return( cas_result ); + } + +#endif + + + + + + +/****************************************************************************/ +#if (defined __i686__ && __GNUC__ && !defined __pic__) + + /* TRD : any OS on x86 with GCC for statically linked code + + __i686__ indicates x86 + __GNUC__ indicates GCC + */ + + LFDS601_INLINE unsigned char lfds601_abstraction_dcas( volatile lfds601_atom_t *destination, lfds601_atom_t *exchange, lfds601_atom_t *compare ) + { + unsigned char + cas_result; + + assert( destination != NULL ); + assert( exchange != NULL ); + assert( compare != NULL ); + + __asm__ __volatile__ + ( + "lock;" // make cmpxchg8b atomic + "cmpxchg8b %0;" // cmpxchg8b sets ZF on success + "setz %3;" // if ZF set, set cas_result to 1 + + // output + : "+m" (*(volatile lfds601_atom_t (*)[2]) destination), "+a" (*compare), "+d" (*(compare+1)), "=q" (cas_result) + + // input + : "b" (*exchange), "c" (*(exchange+1)) + + // clobbered + : "cc", "memory" + ); + + return( cas_result ); + } + +#endif + + + + + +/****************************************************************************/ +#if (defined __x86_64__ && __GNUC__ && defined __pic__) + + /* TRD : any OS on x64 with GCC for position independent code (e.g. a shared object) + + __x86_64__ indicates x64 + __GNUC__ indicates GCC + */ + + LFDS601_INLINE unsigned char lfds601_abstraction_dcas( volatile lfds601_atom_t *destination, lfds601_atom_t *exchange, lfds601_atom_t *compare ) + { + unsigned char + cas_result; + + assert( destination != NULL ); + assert( exchange != NULL ); + assert( compare != NULL ); + + /* TRD : with a shared object, we cannot clobber RBX + as such, we borrow RSI - we load half of the exchange value into it + then swap it with RBX + then do the compare-and-swap + then swap the original value of RBX back from RSI + */ + + __asm__ __volatile__ + ( + "xchg %%rsi, %%rbx;" // swap RBI and RBX + "lock;" // make cmpxchg16b atomic + "cmpxchg16b %0;" // cmpxchg16b sets ZF on success + "setz %3;" // if ZF set, set cas_result to 1 + "xchg %%rbx, %%rsi;" // re-swap RBI and RBX + + // output + : "+m" (*(volatile lfds601_atom_t (*)[2]) destination), "+a" (*compare), "+d" (*(compare+1)), "=q" (cas_result) + + // input + : "S" (*exchange), "c" (*(exchange+1)) + + // clobbered + : "cc", "memory" + ); + + return( cas_result ); + } + +#endif + + + + + + +/****************************************************************************/ +#if (defined __i686__ && __GNUC__ && defined __pic__) + + /* TRD : any OS on x86 with GCC for position independent code (e.g. a shared object) + + __i686__ indicates x86 + __GNUC__ indicates GCC + */ + + LFDS601_INLINE unsigned char lfds601_abstraction_dcas( volatile lfds601_atom_t *destination, lfds601_atom_t *exchange, lfds601_atom_t *compare ) + { + unsigned char + cas_result; + + assert( destination != NULL ); + assert( exchange != NULL ); + assert( compare != NULL ); + + /* TRD : with a shared object, we cannot clobber EBX + as such, we borrow ESI - we load half of the exchange value into it + then swap it with EBX + then do the compare-and-swap + then swap the original value of EBX back from ESI + */ + + __asm__ __volatile__ + ( + "xchg %%esi, %%ebx;" // swap EBI and EBX + "lock;" // make cmpxchg8b atomic + "cmpxchg8b %0;" // cmpxchg8b sets ZF on success + "setz %3;" // if ZF set, set cas_result to 1 + "xchg %%ebx, %%esi;" // re-swap EBI and EBX + + // output + : "+m" (*(volatile lfds601_atom_t (*)[2]) destination), "+a" (*compare), "+d" (*(compare+1)), "=q" (cas_result) + + // input + : "S" (*exchange), "c" (*(exchange+1)) + + // clobbered + : "cc", "memory" + ); + + return( cas_result ); + } + +#endif + + + + + +/****************************************************************************/ +#if (defined __arm__ && __GNUC__) + + /* TRD : any OS on any ARM with GCC + + Remember however we need to set into compare the original value of destination. + + __arm__ indicates ARM + __GNUC__ indicates GCC + */ + + LFDS601_INLINE unsigned char lfds601_abstraction_dcas( volatile lfds601_atom_t *destination, lfds601_atom_t *exchange, lfds601_atom_t *compare ) + { + lfds601_atom_t + *local_compare = compare, + stored_flag = 1; + + register lfds601_atom_t + local_exchange_a __asm("r2"), + local_exchange_b __asm("r3"), + local_compare_a __asm("r4"), + local_compare_b __asm("r5"), + original_destination_a __asm("r6"), + original_destination_b __asm("r7"); + + assert( destination != NULL ); + assert( exchange != NULL ); + assert( compare != NULL ); + + /* TRD : some notes + + the double word ldr and str instructions require contigous registers + where the first register is an even number + + honouring this requirement requires us to specifically specify + the registers to use (which is why we're using register __asm("rN") + in the declerations above + + the arguments to the function occupy registers r0, r1 and r2 + + we can use up to and including r8, but r9 can have a frame pointer in it + + so we make a copy of compare (freeing up r2, so we can use it for a double + word load) but use destination (r0) and exchange (r1) directly + + note LDRD and STRD became available in armv6k + + apologies for the trickery with the mcr register variable - the code runs + out of registers on armv6k + */ + + __asm__ __volatile__ + ( + " mov %[stored_flag], #1;" // put 1 into stored_flag + " mov %[local_exchange_a], #0;" // borrow local_exchange_a for mcr, to save a register + " mcr p15, 0, %[local_exchange_a], c7, c10, 5;" // memory barrier (ARM v6 compatible) + " ldrd %[local_exchange_a], %[local_exchange_b], [%[exchange]];" // load exchange into local_exchange_a and local_exchange_b (which are r2 and r3, respectively) + " ldrd %[local_compare_a], %[local_compare_b], [%[local_compare]];" // load compare into local_compare_a and local_compare_b (which are r4 and r5, respectively) + "atomic_dcas:;" + " ldrexd %[original_destination_a], %[original_destination_b], [%[destination]];" // load destination into original_destination_a and original_destination_b (which are r6 and r7, respectively) + " teq %[original_destination_a], %[local_compare_a];" // compare the first word of destination with the first word of compare + " teqeq %[original_destination_b], %[local_compare_b];" // if they're equal, compare the second word of destination with the second word of compare + " bne exit;" // if either word of destination does not match its respective word of compare, exit + " strexd %[stored_flag], %[local_exchange_a], %[local_exchange_b], [%[destination]];" // if both words were equal, try to store local_exchange_a and local_exchange_b into *destination (on success, strexed puts 0 into stored_flag) + " teq %[stored_flag], #0;" // check if stored_flag is 0 + " bne atomic_dcas;" // if not 0, retry (someone else touched *destination after we loaded but before we stored) + "exit:;" + " strd %[original_destination_a], %[original_destination_b], [%[local_compare]];" // whether or not the CAS swapped, we always write the original value of destination into *compare + " mov %[local_exchange_a], #0;" // borrow local_exchange_a for mcr, to save a register + " mcr p15, 0, %[local_exchange_a], c7, c10, 5;" // memory barrier (ARM v6 compatible) + + // output + : "+m" (*(volatile lfds601_atom_t (*)[2]) destination), "+m" (*(lfds601_atom_t (*)[2]) local_compare), + [stored_flag] "+&r" (stored_flag), + [original_destination_a] "+&r" (original_destination_a), [original_destination_b] "+&r" (original_destination_b), + [local_compare_a] "+&r" (local_compare_a), [local_compare_b] "+&r" (local_compare_b), + [local_exchange_a] "+&r" (local_exchange_a), [local_exchange_b] "+&r" (local_exchange_b) + + // input + : "m" (*(lfds601_atom_t (*)[2]) exchange), + [destination] "r" (destination), + [local_compare] "r" (local_compare), + [exchange] "r" (exchange) + + // clobbered + : "cc", "memory" // memory is clobbered because we issue a memory barrier + ); + + /* TRD : stored_flag is set to 0 on store, 1 on fail + we need to return 1 on success, 0 on fail + */ + + return( (unsigned char) !stored_flag ); + } + +#endif + + diff --git a/liblfds/liblfds6.0.1/liblfds601/src/lfds601_abstraction/lfds601_abstraction_increment.c b/liblfds/liblfds6.0.1/liblfds601/src/lfds601_abstraction/lfds601_abstraction_increment.c new file mode 100644 index 0000000..6907be4 --- /dev/null +++ b/liblfds/liblfds6.0.1/liblfds601/src/lfds601_abstraction/lfds601_abstraction_increment.c @@ -0,0 +1,136 @@ +#include "lfds601_abstraction_internal.h" + + + + + +/****************************************************************************/ +#if (defined _WIN64 && defined _MSC_VER) + + /* TRD : 64 bit Windows (user-mode or kernel) on any CPU with the Microsoft C compiler + + _WIN64 indicates 64 bit Windows + _MSC_VER indicates Microsoft C compiler + */ + + LFDS601_INLINE lfds601_atom_t lfds601_abstraction_increment( lfds601_atom_t *value ) + { + __int64 + rv; + + assert( value != NULL ); + + rv = _InterlockedIncrement64( (__int64 *) value ); + + return( (lfds601_atom_t) rv ); + } + +#endif + + + + + +/****************************************************************************/ +#if (!defined _WIN64 && defined _WIN32 && defined _MSC_VER) + + /* TRD : 32 bit Windows (user-mode or kernel) on any CPU with the Microsoft C compiler + + (!defined _WIN64 && defined _WIN32) indicates 32 bit Windows + _MSC_VER indicates Microsoft C compiler + */ + + LFDS601_INLINE lfds601_atom_t lfds601_abstraction_increment( lfds601_atom_t *value ) + { + long int + rv; + + assert( value != NULL ); + + rv = _InterlockedIncrement( (long int *) value ); + + return( (lfds601_atom_t) rv ); + } + +#endif + + + + + +/****************************************************************************/ +#if (!defined __arm__ && __GNUC__ >= 4 && __GNUC_MINOR__ >= 1 && __GNUC_PATCHLEVEL__ >= 0) + + /* TRD : any OS on any CPU with GCC 4.1.0 or better + + GCC 4.1.0 introduced the __sync_*() atomic intrinsics + + __GNUC__ / __GNUC_MINOR__ / __GNUC_PATCHLEVEL__ indicates GCC and which version + */ + + LFDS601_INLINE lfds601_atom_t lfds601_abstraction_increment( lfds601_atom_t *value ) + { + lfds601_atom_t + rv; + + assert( value != NULL ); + + // TRD : no need for casting here, GCC has a __sync_add_and_fetch() for all native types + + rv = __sync_add_and_fetch( value, 1 ); + + return( rv ); + } + +#endif + + + + + +/****************************************************************************/ +#if (defined __arm__ && __GNUC__ >= 4) + + /* TRD : any OS on any CPU with GCC 4.1.0 or better + + GCC 4.1.0 introduced the __sync_*() atomic intrinsics + + __arm__ indicates ARM + __GNUC__ indicates GCC + */ + + LFDS601_INLINE lfds601_atom_t lfds601_abstraction_increment( lfds601_atom_t *value ) + { + lfds601_atom_t + stored_flag = 0, + new_value = 0; + + assert( value != NULL ); + + __asm__ __volatile__ + ( + " mov %[stored_flag], #1;" // move 1 into stored_flag + " mcr p15, 0, %[zero], c7, c10, 5;" // memory barrier (ARM v6 compatible) + "atomic_add:;" + " ldrex %[new_value], [%[value]]; " // load *value into new_value + " add %[new_value], #1;" // add 1 to new_value + " strex %[stored_flag], %[new_value], [%[value]];" // try to store new_value into *value (on success, strex puts 0 into stored_flag) + " teq %[stored_flag], #0;" // check if stored_flag is 0 + " bne atomic_add;" // if not 0, retry (someone else touched *value after we loaded but before we stored) + " mcr p15, 0, %[zero], c7, c10, 5;" // memory barrier (ARM v6 compatible) + + // output + : "+m" (*value), [new_value] "+&r" (new_value), [stored_flag] "+&r" (stored_flag) + + // input + : [value] "r" (value), [zero] "r" (0) + + // clobbered + : "cc", "memory" // memory is clobbered because we issue a memory barrier + ); + + return( new_value ); + } + +#endif + diff --git a/liblfds/liblfds6.0.1/liblfds601/src/lfds601_abstraction/lfds601_abstraction_internal.h b/liblfds/liblfds6.0.1/liblfds601/src/lfds601_abstraction/lfds601_abstraction_internal.h new file mode 100644 index 0000000..a864189 --- /dev/null +++ b/liblfds/liblfds6.0.1/liblfds601/src/lfds601_abstraction/lfds601_abstraction_internal.h @@ -0,0 +1,5 @@ +/***** the library wide include file *****/ +#include "lfds601_internal.h" + +/***** private prototypes *****/ + diff --git a/liblfds/liblfds6.0.1/liblfds601/src/lfds601_freelist/lfds601_freelist_delete.c b/liblfds/liblfds6.0.1/liblfds601/src/lfds601_freelist/lfds601_freelist_delete.c new file mode 100644 index 0000000..c0e2416 --- /dev/null +++ b/liblfds/liblfds6.0.1/liblfds601/src/lfds601_freelist/lfds601_freelist_delete.c @@ -0,0 +1,35 @@ +#include "lfds601_freelist_internal.h" + + + + + +/****************************************************************************/ +void lfds601_freelist_delete( struct lfds601_freelist_state *fs, void (*user_data_delete_function)(void *user_data, void *user_state), void *user_state ) +{ + struct lfds601_freelist_element + *fe; + + void + *user_data; + + assert( fs != NULL ); + // TRD : user_data_delete_function can be NULL + // TRD : user_state can be NULL + + while( lfds601_freelist_pop(fs, &fe) ) + { + if( user_data_delete_function != NULL ) + { + lfds601_freelist_get_user_data_from_element( fe, &user_data ); + user_data_delete_function( user_data, user_state ); + } + + lfds601_abstraction_aligned_free( fe ); + } + + lfds601_abstraction_aligned_free( fs ); + + return; +} + diff --git a/liblfds/liblfds6.0.1/liblfds601/src/lfds601_freelist/lfds601_freelist_get_and_set.c b/liblfds/liblfds6.0.1/liblfds601/src/lfds601_freelist/lfds601_freelist_get_and_set.c new file mode 100644 index 0000000..4c5e884 --- /dev/null +++ b/liblfds/liblfds6.0.1/liblfds601/src/lfds601_freelist/lfds601_freelist_get_and_set.c @@ -0,0 +1,33 @@ +#include "lfds601_freelist_internal.h" + + + + + +/****************************************************************************/ +void *lfds601_freelist_get_user_data_from_element( struct lfds601_freelist_element *fe, void **user_data ) +{ + assert( fe != NULL ); + // TRD : user_data can be NULL + + if( user_data != NULL ) + *user_data = fe->user_data; + + return( fe->user_data ); +} + + + + + +/****************************************************************************/ +void lfds601_freelist_set_user_data_in_element( struct lfds601_freelist_element *fe, void *user_data ) +{ + assert( fe != NULL ); + // TRD : user_data can be NULL + + fe->user_data = user_data; + + return; +} + diff --git a/liblfds/liblfds6.0.1/liblfds601/src/lfds601_freelist/lfds601_freelist_internal.h b/liblfds/liblfds6.0.1/liblfds601/src/lfds601_freelist/lfds601_freelist_internal.h new file mode 100644 index 0000000..28a498b --- /dev/null +++ b/liblfds/liblfds6.0.1/liblfds601/src/lfds601_freelist/lfds601_freelist_internal.h @@ -0,0 +1,42 @@ +/***** the library wide include file *****/ +#include "lfds601_internal.h" + +/***** defines *****/ +#define LFDS601_FREELIST_POINTER 0 +#define LFDS601_FREELIST_COUNTER 1 +#define LFDS601_FREELIST_PAC_SIZE 2 + +/***** structures *****/ +#pragma pack( push, LFDS601_ALIGN_DOUBLE_POINTER ) + +struct lfds601_freelist_state +{ + struct lfds601_freelist_element + *volatile top[LFDS601_FREELIST_PAC_SIZE]; + + int + (*user_data_init_function)( void **user_data, void *user_state ); + + void + *user_state; + + lfds601_atom_t + aba_counter, + element_count; +}; + +struct lfds601_freelist_element +{ + struct lfds601_freelist_element + *next[LFDS601_FREELIST_PAC_SIZE]; + + void + *user_data; +}; + +#pragma pack( pop ) + +/***** private prototypes *****/ +lfds601_atom_t lfds601_freelist_internal_new_element( struct lfds601_freelist_state *fs, struct lfds601_freelist_element **fe ); +void lfds601_freelist_internal_validate( struct lfds601_freelist_state *fs, struct lfds601_validation_info *vi, enum lfds601_data_structure_validity *lfds601_freelist_validity ); + diff --git a/liblfds/liblfds6.0.1/liblfds601/src/lfds601_freelist/lfds601_freelist_new.c b/liblfds/liblfds6.0.1/liblfds601/src/lfds601_freelist/lfds601_freelist_new.c new file mode 100644 index 0000000..9b09e0c --- /dev/null +++ b/liblfds/liblfds6.0.1/liblfds601/src/lfds601_freelist/lfds601_freelist_new.c @@ -0,0 +1,123 @@ +#include "lfds601_freelist_internal.h" + + + + + +/****************************************************************************/ +int lfds601_freelist_new( struct lfds601_freelist_state **fs, lfds601_atom_t number_elements, int (*user_data_init_function)(void **user_data, void *user_state), void *user_state ) +{ + int + rv = 0; + + lfds601_atom_t + element_count; + + assert( fs != NULL ); + // TRD : number_elements can be any value in its range + // TRD : user_data_init_function can be NULL + + *fs = (struct lfds601_freelist_state *) lfds601_abstraction_aligned_malloc( sizeof(struct lfds601_freelist_state), LFDS601_ALIGN_DOUBLE_POINTER ); + + if( (*fs) != NULL ) + { + (*fs)->top[LFDS601_FREELIST_POINTER] = NULL; + (*fs)->top[LFDS601_FREELIST_COUNTER] = 0; + (*fs)->user_data_init_function = user_data_init_function; + (*fs)->user_state = user_state; + (*fs)->aba_counter = 0; + (*fs)->element_count = 0; + + element_count = lfds601_freelist_new_elements( *fs, number_elements ); + + if( element_count == number_elements ) + rv = 1; + + if( element_count != number_elements ) + { + lfds601_abstraction_aligned_free( (*fs) ); + *fs = NULL; + } + } + + return( rv ); +} + + + + + +/****************************************************************************/ +lfds601_atom_t lfds601_freelist_new_elements( struct lfds601_freelist_state *fs, lfds601_atom_t number_elements ) +{ + struct lfds601_freelist_element + *fe; + + lfds601_atom_t + loop, + count = 0; + + assert( fs != NULL ); + // TRD : number_elements can be any value in its range + // TRD : user_data_init_function can be NULL + + for( loop = 0 ; loop < number_elements ; loop++ ) + if( lfds601_freelist_internal_new_element(fs, &fe) ) + { + lfds601_freelist_push( fs, fe ); + count++; + } + + return( count ); +} + + + + + +/****************************************************************************/ +lfds601_atom_t lfds601_freelist_internal_new_element( struct lfds601_freelist_state *fs, struct lfds601_freelist_element **fe ) +{ + lfds601_atom_t + rv = 0; + + assert( fs != NULL ); + assert( fe != NULL ); + + /* TRD : basically, does what you'd expect; + + allocates an element + calls the user init function + if anything fails, cleans up, + sets *fe to NULL + and returns 0 + */ + + *fe = (struct lfds601_freelist_element *) lfds601_abstraction_aligned_malloc( sizeof(struct lfds601_freelist_element), LFDS601_ALIGN_DOUBLE_POINTER ); + + if( *fe != NULL ) + { + if( fs->user_data_init_function == NULL ) + { + (*fe)->user_data = NULL; + rv = 1; + } + + if( fs->user_data_init_function != NULL ) + { + rv = fs->user_data_init_function( &(*fe)->user_data, fs->user_state ); + + if( rv == 0 ) + { + lfds601_abstraction_aligned_free( *fe ); + *fe = NULL; + } + } + } + + if( rv == 1 ) + lfds601_abstraction_increment( (lfds601_atom_t *) &fs->element_count ); + + return( rv ); +} + diff --git a/liblfds/liblfds6.0.1/liblfds601/src/lfds601_freelist/lfds601_freelist_pop_push.c b/liblfds/liblfds6.0.1/liblfds601/src/lfds601_freelist/lfds601_freelist_pop_push.c new file mode 100644 index 0000000..e8a2f2a --- /dev/null +++ b/liblfds/liblfds6.0.1/liblfds601/src/lfds601_freelist/lfds601_freelist_pop_push.c @@ -0,0 +1,88 @@ +#include "lfds601_freelist_internal.h" + + + + + +/****************************************************************************/ +struct lfds601_freelist_element *lfds601_freelist_pop( struct lfds601_freelist_state *fs, struct lfds601_freelist_element **fe ) +{ + LFDS601_ALIGN(LFDS601_ALIGN_DOUBLE_POINTER) struct lfds601_freelist_element + *fe_local[LFDS601_FREELIST_PAC_SIZE]; + + assert( fs != NULL ); + assert( fe != NULL ); + + fe_local[LFDS601_FREELIST_COUNTER] = fs->top[LFDS601_FREELIST_COUNTER]; + fe_local[LFDS601_FREELIST_POINTER] = fs->top[LFDS601_FREELIST_POINTER]; + + /* TRD : note that lfds601_abstraction_dcas loads the original value of the destination (fs->top) into the compare (fe_local) + (this happens of course after the CAS itself has occurred inside lfds601_abstraction_dcas) + */ + + do + { + if( fe_local[LFDS601_FREELIST_POINTER] == NULL ) + { + *fe = NULL; + return( *fe ); + } + } + while( 0 == lfds601_abstraction_dcas((volatile lfds601_atom_t *) fs->top, (lfds601_atom_t *) fe_local[LFDS601_FREELIST_POINTER]->next, (lfds601_atom_t *) fe_local) ); + + *fe = (struct lfds601_freelist_element *) fe_local[LFDS601_FREELIST_POINTER]; + + return( *fe ); +} + + + + + +/****************************************************************************/ +struct lfds601_freelist_element *lfds601_freelist_guaranteed_pop( struct lfds601_freelist_state *fs, struct lfds601_freelist_element **fe ) +{ + assert( fs != NULL ); + assert( fe != NULL ); + + lfds601_freelist_internal_new_element( fs, fe ); + + return( *fe ); +} + + + + + +/****************************************************************************/ +void lfds601_freelist_push( struct lfds601_freelist_state *fs, struct lfds601_freelist_element *fe ) +{ + LFDS601_ALIGN(LFDS601_ALIGN_DOUBLE_POINTER) struct lfds601_freelist_element + *fe_local[LFDS601_FREELIST_PAC_SIZE], + *original_fe_next[LFDS601_FREELIST_PAC_SIZE]; + + assert( fs != NULL ); + assert( fe != NULL ); + + fe_local[LFDS601_FREELIST_POINTER] = fe; + fe_local[LFDS601_FREELIST_COUNTER] = (struct lfds601_freelist_element *) lfds601_abstraction_increment( (lfds601_atom_t *) &fs->aba_counter ); + + original_fe_next[LFDS601_FREELIST_POINTER] = fs->top[LFDS601_FREELIST_POINTER]; + original_fe_next[LFDS601_FREELIST_COUNTER] = fs->top[LFDS601_FREELIST_COUNTER]; + + /* TRD : note that lfds601_abstraction_dcas loads the original value of the destination (fs->top) into the compare (original_fe_next) + (this happens of course after the CAS itself has occurred inside lfds601_abstraction_dcas) + this then causes us in our loop, should we repeat it, to update fe_local->next to a more + up-to-date version of the head of the lfds601_freelist + */ + + do + { + fe_local[LFDS601_FREELIST_POINTER]->next[LFDS601_FREELIST_POINTER] = original_fe_next[LFDS601_FREELIST_POINTER]; + fe_local[LFDS601_FREELIST_POINTER]->next[LFDS601_FREELIST_COUNTER] = original_fe_next[LFDS601_FREELIST_COUNTER]; + } + while( 0 == lfds601_abstraction_dcas((volatile lfds601_atom_t *) fs->top, (lfds601_atom_t *) fe_local, (lfds601_atom_t *) original_fe_next) ); + + return; +} + diff --git a/liblfds/liblfds6.0.1/liblfds601/src/lfds601_freelist/lfds601_freelist_query.c b/liblfds/liblfds6.0.1/liblfds601/src/lfds601_freelist/lfds601_freelist_query.c new file mode 100644 index 0000000..3c3e80a --- /dev/null +++ b/liblfds/liblfds6.0.1/liblfds601/src/lfds601_freelist/lfds601_freelist_query.c @@ -0,0 +1,113 @@ +#include "lfds601_freelist_internal.h" + + + + + +/****************************************************************************/ +void lfds601_freelist_query( struct lfds601_freelist_state *fs, enum lfds601_freelist_query_type query_type, void *query_input, void *query_output ) +{ + assert( fs != NULL ); + // TRD : query type can be any value in its range + // TRD : query_input can be NULL in some cases + assert( query_output != NULL ); + + switch( query_type ) + { + case LFDS601_FREELIST_QUERY_ELEMENT_COUNT: + assert( query_input == NULL ); + + *(lfds601_atom_t *) query_output = fs->element_count; + break; + + case LFDS601_FREELIST_QUERY_VALIDATE: + // TRD : query_input can be NULL + + lfds601_freelist_internal_validate( fs, (struct lfds601_validation_info *) query_input, (enum lfds601_data_structure_validity *) query_output ); + break; + } + + return; +} + + + + + +/****************************************************************************/ +void lfds601_freelist_internal_validate( struct lfds601_freelist_state *fs, struct lfds601_validation_info *vi, enum lfds601_data_structure_validity *lfds601_freelist_validity ) +{ + struct lfds601_freelist_element + *fe, + *fe_slow, + *fe_fast; + + lfds601_atom_t + element_count = 0; + + assert( fs != NULL ); + // TRD : vi can be NULL + assert( lfds601_freelist_validity != NULL ); + + *lfds601_freelist_validity = LFDS601_VALIDITY_VALID; + + fe_slow = fe_fast = (struct lfds601_freelist_element *) fs->top[LFDS601_FREELIST_POINTER]; + + /* TRD : first, check for a loop + we have two pointers + both of which start at the top of the lfds601_freelist + we enter a loop + and on each iteration + we advance one pointer by one element + and the other by two + + we exit the loop when both pointers are NULL + (have reached the end of the lfds601_freelist) + + or + + if we fast pointer 'sees' the slow pointer + which means we have a loop + */ + + if( fe_slow != NULL ) + do + { + fe_slow = fe_slow->next[LFDS601_FREELIST_POINTER]; + + if( fe_fast != NULL ) + fe_fast = fe_fast->next[LFDS601_FREELIST_POINTER]; + + if( fe_fast != NULL ) + fe_fast = fe_fast->next[LFDS601_FREELIST_POINTER]; + } + while( fe_slow != NULL and fe_fast != fe_slow ); + + if( fe_fast != NULL and fe_slow != NULL and fe_fast == fe_slow ) + *lfds601_freelist_validity = LFDS601_VALIDITY_INVALID_LOOP; + + /* TRD : now check for expected number of elements + vi can be NULL, in which case we do not check + we know we don't have a loop from our earlier check + */ + + if( *lfds601_freelist_validity == LFDS601_VALIDITY_VALID and vi != NULL ) + { + fe = (struct lfds601_freelist_element *) fs->top[LFDS601_FREELIST_POINTER]; + + while( fe != NULL ) + { + element_count++; + fe = (struct lfds601_freelist_element *) fe->next[LFDS601_FREELIST_POINTER]; + } + + if( element_count < vi->min_elements ) + *lfds601_freelist_validity = LFDS601_VALIDITY_INVALID_MISSING_ELEMENTS; + + if( element_count > vi->max_elements ) + *lfds601_freelist_validity = LFDS601_VALIDITY_INVALID_ADDITIONAL_ELEMENTS; + } + + return; +} + diff --git a/liblfds/liblfds6.0.1/liblfds601/src/lfds601_internal.h b/liblfds/liblfds6.0.1/liblfds601/src/lfds601_internal.h new file mode 100644 index 0000000..9c8b2d9 --- /dev/null +++ b/liblfds/liblfds6.0.1/liblfds601/src/lfds601_internal.h @@ -0,0 +1,12 @@ +/***** public prototypes *****/ +#include "liblfds601.h" + +/***** defines *****/ +#define and && +#define or || + +#define RAISED 1 +#define LOWERED 0 + +#define NO_FLAGS 0x0 + diff --git a/liblfds/liblfds6.0.1/liblfds601/src/lfds601_queue/lfds601_queue_delete.c b/liblfds/liblfds6.0.1/liblfds601/src/lfds601_queue/lfds601_queue_delete.c new file mode 100644 index 0000000..873bc1d --- /dev/null +++ b/liblfds/liblfds6.0.1/liblfds601/src/lfds601_queue/lfds601_queue_delete.c @@ -0,0 +1,55 @@ +#include "lfds601_queue_internal.h" + + + + + +/****************************************************************************/ +void lfds601_queue_delete( struct lfds601_queue_state *qs, void (*user_data_delete_function)(void *user_data, void *user_state), void *user_state ) +{ + void + *user_data; + + assert( qs != NULL ); + // TRD : user_data_delete_function can be NULL + // TRD : user_state can be NULL + + while( lfds601_queue_dequeue(qs, &user_data) ) + if( user_data_delete_function != NULL ) + user_data_delete_function( user_data, user_state ); + + /* TRD : fully dequeuing will leave us + with a single dummy element + which both qs->enqueue and qs->dequeue point at + we push this back onto the lfds601_freelist + before we delete the lfds601_freelist + */ + + lfds601_freelist_push( qs->fs, qs->enqueue[LFDS601_QUEUE_POINTER]->fe ); + + lfds601_freelist_delete( qs->fs, lfds601_queue_internal_freelist_delete_function, NULL ); + + lfds601_abstraction_aligned_free( qs ); + + return; +} + + + + + +/****************************************************************************/ +#pragma warning( disable : 4100 ) + +void lfds601_queue_internal_freelist_delete_function( void *user_data, void *user_state ) +{ + assert( user_data != NULL ); + assert( user_state == NULL ); + + lfds601_abstraction_aligned_free( user_data ); + + return; +} + +#pragma warning( default : 4100 ) + diff --git a/liblfds/liblfds6.0.1/liblfds601/src/lfds601_queue/lfds601_queue_internal.h b/liblfds/liblfds6.0.1/liblfds601/src/lfds601_queue/lfds601_queue_internal.h new file mode 100644 index 0000000..7a9464a --- /dev/null +++ b/liblfds/liblfds6.0.1/liblfds601/src/lfds601_queue/lfds601_queue_internal.h @@ -0,0 +1,60 @@ +/***** the library wide include file *****/ +#include "lfds601_internal.h" + +/***** pragmas *****/ + +/***** defines *****/ +#define LFDS601_QUEUE_STATE_UNKNOWN -1 +#define LFDS601_QUEUE_STATE_EMPTY 0 +#define LFDS601_QUEUE_STATE_ENQUEUE_OUT_OF_PLACE 1 +#define LFDS601_QUEUE_STATE_ATTEMPT_DELFDS601_QUEUE 2 + +#define LFDS601_QUEUE_POINTER 0 +#define LFDS601_QUEUE_COUNTER 1 +#define LFDS601_QUEUE_PAC_SIZE 2 + +/***** structures *****/ +#pragma pack( push, LFDS601_ALIGN_DOUBLE_POINTER ) + +struct lfds601_queue_state +{ + struct lfds601_queue_element + *volatile enqueue[LFDS601_QUEUE_PAC_SIZE], + *volatile dequeue[LFDS601_QUEUE_PAC_SIZE]; + + lfds601_atom_t + aba_counter; + + struct lfds601_freelist_state + *fs; +}; + +struct lfds601_queue_element +{ + // TRD : next in a lfds601_queue requires volatile as it is target of CAS + struct lfds601_queue_element + *volatile next[LFDS601_QUEUE_PAC_SIZE]; + + struct lfds601_freelist_element + *fe; + + void + *user_data; +}; + +#pragma pack( pop ) + +/***** externs *****/ + +/***** private prototypes *****/ +int lfds601_queue_internal_freelist_init_function( void **user_data, void *user_state ); +void lfds601_queue_internal_freelist_delete_function( void *user_data, void *user_state ); + +void lfds601_queue_internal_new_element_from_freelist( struct lfds601_queue_state *qs, struct lfds601_queue_element *qe[LFDS601_QUEUE_PAC_SIZE], void *user_data ); +void lfds601_queue_internal_guaranteed_new_element_from_freelist( struct lfds601_queue_state *qs, struct lfds601_queue_element * qe[LFDS601_QUEUE_PAC_SIZE], void *user_data ); +void lfds601_queue_internal_init_element( struct lfds601_queue_state *qs, struct lfds601_queue_element *qe[LFDS601_QUEUE_PAC_SIZE], struct lfds601_freelist_element *fe, void *user_data ); + +void lfds601_queue_internal_queue( struct lfds601_queue_state *qs, struct lfds601_queue_element *qe[LFDS601_QUEUE_PAC_SIZE] ); + +void lfds601_queue_internal_validate( struct lfds601_queue_state *qs, struct lfds601_validation_info *vi, enum lfds601_data_structure_validity *lfds601_queue_validity, enum lfds601_data_structure_validity *lfds601_freelist_validity ); + diff --git a/liblfds/liblfds6.0.1/liblfds601/src/lfds601_queue/lfds601_queue_new.c b/liblfds/liblfds6.0.1/liblfds601/src/lfds601_queue/lfds601_queue_new.c new file mode 100644 index 0000000..cd4e182 --- /dev/null +++ b/liblfds/liblfds6.0.1/liblfds601/src/lfds601_queue/lfds601_queue_new.c @@ -0,0 +1,140 @@ +#include "lfds601_queue_internal.h" + + + + + +/****************************************************************************/ +int lfds601_queue_new( struct lfds601_queue_state **qs, lfds601_atom_t number_elements ) +{ + int + rv = 0; + + struct lfds601_queue_element + *qe[LFDS601_QUEUE_PAC_SIZE]; + + assert( qs != NULL ); + // TRD : number_elements can be any value in its range + + *qs = (struct lfds601_queue_state *) lfds601_abstraction_aligned_malloc( sizeof(struct lfds601_queue_state), LFDS601_ALIGN_DOUBLE_POINTER ); + + if( *qs != NULL ) + { + // TRD : the size of the lfds601_freelist is the size of the lfds601_queue (+1 for the leading dummy element, which is hidden from the caller) + lfds601_freelist_new( &(*qs)->fs, number_elements+1, lfds601_queue_internal_freelist_init_function, NULL ); + + if( (*qs)->fs != NULL ) + { + lfds601_queue_internal_new_element_from_freelist( *qs, qe, NULL ); + (*qs)->enqueue[LFDS601_QUEUE_POINTER] = (*qs)->dequeue[LFDS601_QUEUE_POINTER] = qe[LFDS601_QUEUE_POINTER]; + (*qs)->aba_counter = 0; + rv = 1; + } + + if( (*qs)->fs == NULL ) + { + lfds601_abstraction_aligned_free( *qs ); + *qs = NULL; + } + } + + return( rv ); +} + + + + + +/****************************************************************************/ +#pragma warning( disable : 4100 ) + +int lfds601_queue_internal_freelist_init_function( void **user_data, void *user_state ) +{ + int + rv = 0; + + assert( user_data != NULL ); + assert( user_state == NULL ); + + *user_data = lfds601_abstraction_aligned_malloc( sizeof(struct lfds601_queue_element), LFDS601_ALIGN_DOUBLE_POINTER ); + + if( *user_data != NULL ) + rv = 1; + + return( rv ); +} + +#pragma warning( default : 4100 ) + + + + + +/****************************************************************************/ +void lfds601_queue_internal_new_element_from_freelist( struct lfds601_queue_state *qs, struct lfds601_queue_element *qe[LFDS601_QUEUE_PAC_SIZE], void *user_data ) +{ + struct lfds601_freelist_element + *fe; + + assert( qs != NULL ); + assert( qe != NULL ); + // TRD : user_data can be any value in its range + + qe[LFDS601_QUEUE_POINTER] = NULL; + + lfds601_freelist_pop( qs->fs, &fe ); + + if( fe != NULL ) + lfds601_queue_internal_init_element( qs, qe, fe, user_data ); + + return; +} + + + + + +/****************************************************************************/ +void lfds601_queue_internal_guaranteed_new_element_from_freelist( struct lfds601_queue_state *qs, struct lfds601_queue_element *qe[LFDS601_QUEUE_PAC_SIZE], void *user_data ) +{ + struct lfds601_freelist_element + *fe; + + assert( qs != NULL ); + assert( qe != NULL ); + // TRD : user_data can be any value in its range + + qe[LFDS601_QUEUE_POINTER] = NULL; + + lfds601_freelist_guaranteed_pop( qs->fs, &fe ); + + if( fe != NULL ) + lfds601_queue_internal_init_element( qs, qe, fe, user_data ); + + return; +} + + + + + +/****************************************************************************/ +void lfds601_queue_internal_init_element( struct lfds601_queue_state *qs, struct lfds601_queue_element *qe[LFDS601_QUEUE_PAC_SIZE], struct lfds601_freelist_element *fe, void *user_data ) +{ + assert( qs != NULL ); + assert( qe != NULL ); + assert( fe != NULL ); + // TRD : user_data can be any value in its range + + lfds601_freelist_get_user_data_from_element( fe, (void **) &qe[LFDS601_QUEUE_POINTER] ); + qe[LFDS601_QUEUE_COUNTER] = (struct lfds601_queue_element *) lfds601_abstraction_increment( (lfds601_atom_t *) &qs->aba_counter ); + + qe[LFDS601_QUEUE_POINTER]->next[LFDS601_QUEUE_POINTER] = NULL; + qe[LFDS601_QUEUE_POINTER]->next[LFDS601_QUEUE_COUNTER] = (struct lfds601_queue_element *) lfds601_abstraction_increment( (lfds601_atom_t *) &qs->aba_counter ); + + qe[LFDS601_QUEUE_POINTER]->fe = fe; + qe[LFDS601_QUEUE_POINTER]->user_data = user_data; + + return; +} + diff --git a/liblfds/liblfds6.0.1/liblfds601/src/lfds601_queue/lfds601_queue_query.c b/liblfds/liblfds6.0.1/liblfds601/src/lfds601_queue/lfds601_queue_query.c new file mode 100644 index 0000000..3428b69 --- /dev/null +++ b/liblfds/liblfds6.0.1/liblfds601/src/lfds601_queue/lfds601_queue_query.c @@ -0,0 +1,153 @@ +#include "lfds601_queue_internal.h" + + + + + +/****************************************************************************/ +#pragma warning( disable : 4100 ) + +void lfds601_queue_query( struct lfds601_queue_state *qs, enum lfds601_queue_query_type query_type, void *query_input, void *query_output ) +{ + assert( qs != NULL ); + // TRD : query_type can be any value in its range + // TRD : query_input can be NULL + assert( query_output != NULL ); + + switch( query_type ) + { + case LFDS601_QUEUE_QUERY_ELEMENT_COUNT: + assert( query_input == NULL ); + + lfds601_freelist_query( qs->fs, LFDS601_FREELIST_QUERY_ELEMENT_COUNT, NULL, query_output ); + break; + + case LFDS601_QUEUE_QUERY_VALIDATE: + // TRD : query_input can be NULL + + lfds601_queue_internal_validate( qs, (struct lfds601_validation_info *) query_input, (enum lfds601_data_structure_validity *) query_output, ((enum lfds601_data_structure_validity *) query_output)+1 ); + break; + } + + return; +} + +#pragma warning( default : 4100 ) + + + + + +/****************************************************************************/ +void lfds601_queue_internal_validate( struct lfds601_queue_state *qs, struct lfds601_validation_info *vi, enum lfds601_data_structure_validity *lfds601_queue_validity, enum lfds601_data_structure_validity *lfds601_freelist_validity ) +{ + struct lfds601_queue_element + *qe, + *qe_slow, + *qe_fast; + + lfds601_atom_t + element_count = 0, + total_elements; + + struct lfds601_validation_info + lfds601_freelist_vi; + + assert( qs != NULL ); + // TRD : vi can be NULL + assert( lfds601_queue_validity != NULL ); + assert( lfds601_freelist_validity != NULL ); + + *lfds601_queue_validity = LFDS601_VALIDITY_VALID; + + qe_slow = qe_fast = (struct lfds601_queue_element *) qs->dequeue[LFDS601_QUEUE_POINTER]; + + /* TRD : first, check for a loop + we have two pointers + both of which start at the dequeue end of the lfds601_queue + we enter a loop + and on each iteration + we advance one pointer by one element + and the other by two + + we exit the loop when both pointers are NULL + (have reached the end of the lfds601_queue) + + or + + if we fast pointer 'sees' the slow pointer + which means we have a loop + */ + + if( qe_slow != NULL ) + do + { + qe_slow = qe_slow->next[LFDS601_QUEUE_POINTER]; + + if( qe_fast != NULL ) + qe_fast = qe_fast->next[LFDS601_QUEUE_POINTER]; + + if( qe_fast != NULL ) + qe_fast = qe_fast->next[LFDS601_QUEUE_POINTER]; + } + while( qe_slow != NULL and qe_fast != qe_slow ); + + if( qe_fast != NULL and qe_slow != NULL and qe_fast == qe_slow ) + *lfds601_queue_validity = LFDS601_VALIDITY_INVALID_LOOP; + + /* TRD : now check for expected number of elements + vi can be NULL, in which case we do not check + we know we don't have a loop from our earlier check + */ + + if( *lfds601_queue_validity == LFDS601_VALIDITY_VALID and vi != NULL ) + { + qe = (struct lfds601_queue_element *) qs->dequeue[LFDS601_QUEUE_POINTER]; + + while( qe != NULL ) + { + element_count++; + qe = (struct lfds601_queue_element *) qe->next[LFDS601_QUEUE_POINTER]; + } + + /* TRD : remember there is a dummy element in the lfds601_queue */ + element_count--; + + if( element_count < vi->min_elements ) + *lfds601_queue_validity = LFDS601_VALIDITY_INVALID_MISSING_ELEMENTS; + + if( element_count > vi->max_elements ) + *lfds601_queue_validity = LFDS601_VALIDITY_INVALID_ADDITIONAL_ELEMENTS; + } + + /* TRD : now we validate the lfds601_freelist + + we may be able to check for the expected number of + elements in the lfds601_freelist + + if the caller has given us an expected min and max + number of elements in the lfds601_queue, then the total number + of elements in the lfds601_freelist, minus that min and max, + gives us the expected number of elements in the + lfds601_freelist + */ + + if( vi != NULL ) + { + lfds601_freelist_query( qs->fs, LFDS601_FREELIST_QUERY_ELEMENT_COUNT, NULL, (void *) &total_elements ); + + /* TRD : remember there is a dummy element in the lfds601_queue */ + total_elements--; + + lfds601_freelist_vi.min_elements = total_elements - vi->max_elements; + lfds601_freelist_vi.max_elements = total_elements - vi->min_elements; + + lfds601_freelist_query( qs->fs, LFDS601_FREELIST_QUERY_VALIDATE, (void *) &lfds601_freelist_vi, (void *) lfds601_freelist_validity ); + } + + if( vi == NULL ) + lfds601_freelist_query( qs->fs, LFDS601_FREELIST_QUERY_VALIDATE, NULL, (void *) lfds601_freelist_validity ); + + return; +} + diff --git a/liblfds/liblfds6.0.1/liblfds601/src/lfds601_queue/lfds601_queue_queue.c b/liblfds/liblfds6.0.1/liblfds601/src/lfds601_queue/lfds601_queue_queue.c new file mode 100644 index 0000000..943e141 --- /dev/null +++ b/liblfds/liblfds6.0.1/liblfds601/src/lfds601_queue/lfds601_queue_queue.c @@ -0,0 +1,181 @@ +#include "lfds601_queue_internal.h" + + + + + +/****************************************************************************/ +int lfds601_queue_enqueue( struct lfds601_queue_state *qs, void *user_data ) +{ + LFDS601_ALIGN(LFDS601_ALIGN_DOUBLE_POINTER) struct lfds601_queue_element + *qe[LFDS601_QUEUE_PAC_SIZE]; + + assert( qs != NULL ); + // TRD : user_data can be NULL + + lfds601_queue_internal_new_element_from_freelist( qs, qe, user_data ); + + if( qe[LFDS601_QUEUE_POINTER] == NULL ) + return( 0 ); + + lfds601_queue_internal_queue( qs, qe ); + + return( 1 ); +} + + + + + +/****************************************************************************/ +int lfds601_queue_guaranteed_enqueue( struct lfds601_queue_state *qs, void *user_data ) +{ + LFDS601_ALIGN(LFDS601_ALIGN_DOUBLE_POINTER) struct lfds601_queue_element + *qe[LFDS601_QUEUE_PAC_SIZE]; + + assert( qs != NULL ); + // TRD : user_data can be NULL + + lfds601_queue_internal_guaranteed_new_element_from_freelist( qs, qe, user_data ); + + if( qe[LFDS601_QUEUE_POINTER] == NULL ) + return( 0 ); + + lfds601_queue_internal_queue( qs, qe ); + + return( 1 ); +} + + + + + +/****************************************************************************/ +void lfds601_queue_internal_queue( struct lfds601_queue_state *qs, struct lfds601_queue_element *qe[LFDS601_QUEUE_PAC_SIZE] ) +{ + LFDS601_ALIGN(LFDS601_ALIGN_DOUBLE_POINTER) struct lfds601_queue_element + *enqueue[LFDS601_QUEUE_PAC_SIZE], + *next[LFDS601_QUEUE_PAC_SIZE]; + + unsigned char + cas_result = 0; + + assert( qs != NULL ); + assert( qe != NULL ); + + do + { + enqueue[LFDS601_QUEUE_POINTER] = qs->enqueue[LFDS601_QUEUE_POINTER]; + enqueue[LFDS601_QUEUE_COUNTER] = qs->enqueue[LFDS601_QUEUE_COUNTER]; + + next[LFDS601_QUEUE_POINTER] = enqueue[LFDS601_QUEUE_POINTER]->next[LFDS601_QUEUE_POINTER]; + next[LFDS601_QUEUE_COUNTER] = enqueue[LFDS601_QUEUE_POINTER]->next[LFDS601_QUEUE_COUNTER]; + + /* TRD : this if() ensures that the next we read, just above, + really is from qs->enqueue (which we copied into enqueue) + */ + + if( qs->enqueue[LFDS601_QUEUE_POINTER] == enqueue[LFDS601_QUEUE_POINTER] and qs->enqueue[LFDS601_QUEUE_COUNTER] == enqueue[LFDS601_QUEUE_COUNTER] ) + { + if( next[LFDS601_QUEUE_POINTER] == NULL ) + { + qe[LFDS601_QUEUE_COUNTER] = next[LFDS601_QUEUE_COUNTER] + 1; + cas_result = lfds601_abstraction_dcas( (volatile lfds601_atom_t *) enqueue[LFDS601_QUEUE_POINTER]->next, (lfds601_atom_t *) qe, (lfds601_atom_t *) next ); + } + else + { + next[LFDS601_QUEUE_COUNTER] = enqueue[LFDS601_QUEUE_COUNTER] + 1; + lfds601_abstraction_dcas( (volatile lfds601_atom_t *) qs->enqueue, (lfds601_atom_t *) next, (lfds601_atom_t *) enqueue ); + } + } + } + while( cas_result == 0 ); + + qe[LFDS601_QUEUE_COUNTER] = enqueue[LFDS601_QUEUE_COUNTER] + 1; + lfds601_abstraction_dcas( (volatile lfds601_atom_t *) qs->enqueue, (lfds601_atom_t *) qe, (lfds601_atom_t *) enqueue ); + + return; +} + + + + + +/****************************************************************************/ +int lfds601_queue_dequeue( struct lfds601_queue_state *qs, void **user_data ) +{ + LFDS601_ALIGN(LFDS601_ALIGN_DOUBLE_POINTER) struct lfds601_queue_element + *enqueue[LFDS601_QUEUE_PAC_SIZE], + *dequeue[LFDS601_QUEUE_PAC_SIZE], + *next[LFDS601_QUEUE_PAC_SIZE]; + + unsigned char + cas_result = 0; + + int + rv = 1, + state = LFDS601_QUEUE_STATE_UNKNOWN, + finished_flag = LOWERED; + + assert( qs != NULL ); + assert( user_data != NULL ); + + do + { + dequeue[LFDS601_QUEUE_POINTER] = qs->dequeue[LFDS601_QUEUE_POINTER]; + dequeue[LFDS601_QUEUE_COUNTER] = qs->dequeue[LFDS601_QUEUE_COUNTER]; + + enqueue[LFDS601_QUEUE_POINTER] = qs->enqueue[LFDS601_QUEUE_POINTER]; + enqueue[LFDS601_QUEUE_COUNTER] = qs->enqueue[LFDS601_QUEUE_COUNTER]; + + next[LFDS601_QUEUE_POINTER] = dequeue[LFDS601_QUEUE_POINTER]->next[LFDS601_QUEUE_POINTER]; + next[LFDS601_QUEUE_COUNTER] = dequeue[LFDS601_QUEUE_POINTER]->next[LFDS601_QUEUE_COUNTER]; + + /* TRD : confirm that dequeue didn't move between reading it + and reading its next pointer + */ + + if( dequeue[LFDS601_QUEUE_POINTER] == qs->dequeue[LFDS601_QUEUE_POINTER] and dequeue[LFDS601_QUEUE_COUNTER] == qs->dequeue[LFDS601_QUEUE_COUNTER] ) + { + if( enqueue[LFDS601_QUEUE_POINTER] == dequeue[LFDS601_QUEUE_POINTER] and next[LFDS601_QUEUE_POINTER] == NULL ) + state = LFDS601_QUEUE_STATE_EMPTY; + + if( enqueue[LFDS601_QUEUE_POINTER] == dequeue[LFDS601_QUEUE_POINTER] and next[LFDS601_QUEUE_POINTER] != NULL ) + state = LFDS601_QUEUE_STATE_ENQUEUE_OUT_OF_PLACE; + + if( enqueue[LFDS601_QUEUE_POINTER] != dequeue[LFDS601_QUEUE_POINTER] ) + state = LFDS601_QUEUE_STATE_ATTEMPT_DELFDS601_QUEUE; + + switch( state ) + { + case LFDS601_QUEUE_STATE_EMPTY: + *user_data = NULL; + rv = 0; + finished_flag = RAISED; + break; + + case LFDS601_QUEUE_STATE_ENQUEUE_OUT_OF_PLACE: + next[LFDS601_QUEUE_COUNTER] = enqueue[LFDS601_QUEUE_COUNTER] + 1; + lfds601_abstraction_dcas( (volatile lfds601_atom_t *) qs->enqueue, (lfds601_atom_t *) next, (lfds601_atom_t *) enqueue ); + break; + + case LFDS601_QUEUE_STATE_ATTEMPT_DELFDS601_QUEUE: + *user_data = next[LFDS601_QUEUE_POINTER]->user_data; + + next[LFDS601_QUEUE_COUNTER] = dequeue[LFDS601_QUEUE_COUNTER] + 1; + cas_result = lfds601_abstraction_dcas( (volatile lfds601_atom_t *) qs->dequeue, (lfds601_atom_t *) next, (lfds601_atom_t *) dequeue ); + + if( cas_result == 1 ) + finished_flag = RAISED; + break; + } + } + } + while( finished_flag == LOWERED ); + + if( cas_result == 1 ) + lfds601_freelist_push( qs->fs, dequeue[LFDS601_QUEUE_POINTER]->fe ); + + return( rv ); +} + diff --git a/liblfds/liblfds6.0.1/liblfds601/src/lfds601_ringbuffer/lfds601_ringbuffer_delete.c b/liblfds/liblfds6.0.1/liblfds601/src/lfds601_ringbuffer/lfds601_ringbuffer_delete.c new file mode 100644 index 0000000..8e76b9a --- /dev/null +++ b/liblfds/liblfds6.0.1/liblfds601/src/lfds601_ringbuffer/lfds601_ringbuffer_delete.c @@ -0,0 +1,22 @@ +#include "lfds601_ringbuffer_internal.h" + + + + + +/****************************************************************************/ +void lfds601_ringbuffer_delete( struct lfds601_ringbuffer_state *rs, void (*user_data_delete_function)(void *user_data, void *user_state), void *user_state ) +{ + assert( rs != NULL ); + // TRD : user_data_delete_function can be NULL + // TRD : user_state can be NULL + + lfds601_queue_delete( rs->qs, NULL, NULL ); + + lfds601_freelist_delete( rs->fs, user_data_delete_function, user_state ); + + lfds601_abstraction_aligned_free( rs ); + + return; +} + diff --git a/liblfds/liblfds6.0.1/liblfds601/src/lfds601_ringbuffer/lfds601_ringbuffer_get_and_put.c b/liblfds/liblfds6.0.1/liblfds601/src/lfds601_ringbuffer/lfds601_ringbuffer_get_and_put.c new file mode 100644 index 0000000..3cc8d5d --- /dev/null +++ b/liblfds/liblfds6.0.1/liblfds601/src/lfds601_ringbuffer/lfds601_ringbuffer_get_and_put.c @@ -0,0 +1,108 @@ +#include "lfds601_ringbuffer_internal.h" + + + + + +/****************************************************************************/ +struct lfds601_freelist_element *lfds601_ringbuffer_get_read_element( struct lfds601_ringbuffer_state *rs, struct lfds601_freelist_element **fe ) +{ + assert( rs != NULL ); + assert( fe != NULL ); + + lfds601_queue_dequeue( rs->qs, (void **) fe ); + + return( *fe ); +} + + + + + +/****************************************************************************/ +struct lfds601_freelist_element *lfds601_ringbuffer_get_write_element( struct lfds601_ringbuffer_state *rs, struct lfds601_freelist_element **fe, int *overwrite_flag ) +{ + assert( rs != NULL ); + assert( fe != NULL ); + // TRD : overwrite_flag can be NULL + + /* TRD : we try to obtain an element from the lfds601_freelist + if we can, we populate it and add it to the lfds601_queue + + if we cannot, then the lfds601_ringbuffer is full + so instead we grab the current read element and + use that instead + + dequeue may fail since the lfds601_queue may be emptied + during our dequeue attempt + + so what we actually do here is a loop, attempting + the lfds601_freelist and if it fails then a dequeue, until + we obtain an element + + once we have an element, we lfds601_queue it + + you may be wondering why this operation is in a loop + remember - these operations are lock-free; anything + can happen in between + + so for example the pop could fail because the lfds601_freelist + is empty; but by the time we go to get an element from + the lfds601_queue, the whole lfds601_queue has been emptied back into + the lfds601_freelist! + + if overwrite_flag is provided, we set it to 0 if we + obtained a new element from the lfds601_freelist, 1 if we + stole an element from the lfds601_queue + */ + + do + { + if( overwrite_flag != NULL ) + *overwrite_flag = 0; + + lfds601_freelist_pop( rs->fs, fe ); + + if( *fe == NULL ) + { + lfds601_ringbuffer_get_read_element( rs, fe ); + + if( overwrite_flag != NULL and *fe != NULL ) + *overwrite_flag = 1; + } + } + while( *fe == NULL ); + + return( *fe ); +} + + + + + +/****************************************************************************/ +void lfds601_ringbuffer_put_read_element( struct lfds601_ringbuffer_state *rs, struct lfds601_freelist_element *fe ) +{ + assert( rs != NULL ); + assert( fe != NULL ); + + lfds601_freelist_push( rs->fs, fe ); + + return; +} + + + + + +/****************************************************************************/ +void lfds601_ringbuffer_put_write_element( struct lfds601_ringbuffer_state *rs, struct lfds601_freelist_element *fe ) +{ + assert( rs != NULL ); + assert( fe != NULL ); + + lfds601_queue_enqueue( rs->qs, fe ); + + return; +} + diff --git a/liblfds/liblfds6.0.1/liblfds601/src/lfds601_ringbuffer/lfds601_ringbuffer_internal.h b/liblfds/liblfds6.0.1/liblfds601/src/lfds601_ringbuffer/lfds601_ringbuffer_internal.h new file mode 100644 index 0000000..445da0a --- /dev/null +++ b/liblfds/liblfds6.0.1/liblfds601/src/lfds601_ringbuffer/lfds601_ringbuffer_internal.h @@ -0,0 +1,24 @@ +/***** the library wide include file *****/ +#include "lfds601_internal.h" + +/***** defines *****/ + +/***** structures *****/ +#pragma pack( push, LFDS601_ALIGN_DOUBLE_POINTER ) + +struct lfds601_ringbuffer_state +{ + struct lfds601_queue_state + *qs; + + struct lfds601_freelist_state + *fs; +}; + +#pragma pack( pop ) + +/***** externs *****/ + +/***** private prototypes *****/ +void lfds601_ringbuffer_internal_validate( struct lfds601_ringbuffer_state *rs, struct lfds601_validation_info *vi, enum lfds601_data_structure_validity *lfds601_queue_validity, enum lfds601_data_structure_validity *lfds601_freelist_validity ); + diff --git a/liblfds/liblfds6.0.1/liblfds601/src/lfds601_ringbuffer/lfds601_ringbuffer_new.c b/liblfds/liblfds6.0.1/liblfds601/src/lfds601_ringbuffer/lfds601_ringbuffer_new.c new file mode 100644 index 0000000..e7f0288 --- /dev/null +++ b/liblfds/liblfds6.0.1/liblfds601/src/lfds601_ringbuffer/lfds601_ringbuffer_new.c @@ -0,0 +1,47 @@ +#include "lfds601_ringbuffer_internal.h" + + + + + +/****************************************************************************/ +int lfds601_ringbuffer_new( struct lfds601_ringbuffer_state **rs, lfds601_atom_t number_elements, int (*user_data_init_function)(void **user_data, void *user_state), void *user_state ) +{ + int + rv = 0; + + assert( rs != NULL ); + // TRD : number_elements can be any value in its range + // TRD : user_data_init_function can be NULL + // TRD : user_state can be NULL + + *rs = (struct lfds601_ringbuffer_state *) lfds601_abstraction_aligned_malloc( sizeof(struct lfds601_ringbuffer_state), LFDS601_ALIGN_DOUBLE_POINTER ); + + if( *rs != NULL ) + { + lfds601_freelist_new( &(*rs)->fs, number_elements, user_data_init_function, user_state ); + + if( (*rs)->fs != NULL ) + { + lfds601_queue_new( &(*rs)->qs, number_elements ); + + if( (*rs)->qs != NULL ) + rv = 1; + + if( (*rs)->qs == NULL ) + { + lfds601_abstraction_aligned_free( *rs ); + *rs = NULL; + } + } + + if( (*rs)->fs == NULL ) + { + lfds601_abstraction_aligned_free( *rs ); + *rs = NULL; + } + } + + return( rv ); +} + diff --git a/liblfds/liblfds6.0.1/liblfds601/src/lfds601_ringbuffer/lfds601_ringbuffer_query.c b/liblfds/liblfds6.0.1/liblfds601/src/lfds601_ringbuffer/lfds601_ringbuffer_query.c new file mode 100644 index 0000000..8deb09e --- /dev/null +++ b/liblfds/liblfds6.0.1/liblfds601/src/lfds601_ringbuffer/lfds601_ringbuffer_query.c @@ -0,0 +1,64 @@ +#include "lfds601_ringbuffer_internal.h" + + + + + +/****************************************************************************/ +#pragma warning( disable : 4100 ) + +void lfds601_ringbuffer_query( struct lfds601_ringbuffer_state *rs, enum lfds601_ringbuffer_query_type query_type, void *query_input, void *query_output ) +{ + assert( rs != NULL ); + // TRD : query_type can be any value in its range + // TRD : query_input can be NULL + assert( query_output != NULL ); + + switch( query_type ) + { + case LFDS601_RINGBUFFER_QUERY_VALIDATE: + // TRD : query_input can be NULL + + lfds601_ringbuffer_internal_validate( rs, (struct lfds601_validation_info *) query_input, (enum lfds601_data_structure_validity *) query_output, ((enum lfds601_data_structure_validity *) query_output)+2 ); + break; + } + + return; +} + +#pragma warning( default : 4100 ) + + + + + +/****************************************************************************/ +void lfds601_ringbuffer_internal_validate( struct lfds601_ringbuffer_state *rs, struct lfds601_validation_info *vi, enum lfds601_data_structure_validity *lfds601_queue_validity, enum lfds601_data_structure_validity *lfds601_freelist_validity ) +{ + assert( rs != NULL ); + // TRD : vi can be NULL + assert( lfds601_queue_validity != NULL ); + assert( lfds601_freelist_validity != NULL ); + + lfds601_queue_query( rs->qs, LFDS601_QUEUE_QUERY_VALIDATE, vi, lfds601_queue_validity ); + + if( vi != NULL ) + { + struct lfds601_validation_info + lfds601_freelist_vi; + + lfds601_atom_t + total_elements; + + lfds601_freelist_query( rs->fs, LFDS601_FREELIST_QUERY_ELEMENT_COUNT, NULL, (void *) &total_elements ); + lfds601_freelist_vi.min_elements = total_elements - vi->max_elements; + lfds601_freelist_vi.max_elements = total_elements - vi->min_elements; + lfds601_freelist_query( rs->fs, LFDS601_FREELIST_QUERY_VALIDATE, (void *) &lfds601_freelist_vi, (void *) lfds601_freelist_validity ); + } + + if( vi == NULL ) + lfds601_freelist_query( rs->fs, LFDS601_FREELIST_QUERY_VALIDATE, NULL, (void *) lfds601_freelist_validity ); + + return; +} + diff --git a/liblfds/liblfds6.0.1/liblfds601/src/lfds601_slist/lfds601_slist_delete.c b/liblfds/liblfds6.0.1/liblfds601/src/lfds601_slist/lfds601_slist_delete.c new file mode 100644 index 0000000..072b923 --- /dev/null +++ b/liblfds/liblfds6.0.1/liblfds601/src/lfds601_slist/lfds601_slist_delete.c @@ -0,0 +1,79 @@ +#include "lfds601_slist_internal.h" + + + + + +/****************************************************************************/ +void lfds601_slist_delete( struct lfds601_slist_state *ss ) +{ + lfds601_slist_delete_all_elements( ss ); + + lfds601_abstraction_aligned_free( ss ); + + return; +} + + + + + +/****************************************************************************/ +void lfds601_slist_delete_element( struct lfds601_slist_state *ss, struct lfds601_slist_element *se ) +{ + LFDS601_ALIGN(LFDS601_ALIGN_DOUBLE_POINTER) void + *volatile user_data_and_flags[2], + *volatile new_user_data_and_flags[2]; + + unsigned char + cas_rv = 0; + + assert( ss != NULL ); + assert( se != NULL ); + + user_data_and_flags[LFDS601_SLIST_USER_DATA] = se->user_data_and_flags[LFDS601_SLIST_USER_DATA]; + user_data_and_flags[LFDS601_SLIST_FLAGS] = se->user_data_and_flags[LFDS601_SLIST_FLAGS]; + + do + { + new_user_data_and_flags[LFDS601_SLIST_USER_DATA] = user_data_and_flags[LFDS601_SLIST_USER_DATA]; + new_user_data_and_flags[LFDS601_SLIST_FLAGS] = (void *) ((lfds601_atom_t) user_data_and_flags[LFDS601_SLIST_FLAGS] | LFDS601_SLIST_FLAG_DELETED); + } + while( !((lfds601_atom_t) user_data_and_flags[LFDS601_SLIST_FLAGS] & LFDS601_SLIST_FLAG_DELETED) and 0 == (cas_rv = lfds601_abstraction_dcas((volatile lfds601_atom_t *) se->user_data_and_flags, (lfds601_atom_t *) new_user_data_and_flags, (lfds601_atom_t *) user_data_and_flags)) ); + + if( cas_rv == 1 ) + if( ss->user_data_delete_function != NULL ) + ss->user_data_delete_function( (void *) user_data_and_flags[LFDS601_SLIST_USER_DATA], ss->user_state ); + + return; +} + + + + + +/****************************************************************************/ +void lfds601_slist_delete_all_elements( struct lfds601_slist_state *ss ) +{ + struct lfds601_slist_element + *volatile se, + *volatile se_temp; + + se = ss->head; + + while( se != NULL ) + { + // TRD : if a non-deleted element and there is a delete function, call the delete function + if( ss->user_data_delete_function != NULL ) + ss->user_data_delete_function( (void *) se->user_data_and_flags[LFDS601_SLIST_USER_DATA], ss->user_state ); + + se_temp = se; + se = se->next; + lfds601_abstraction_aligned_free( (void *) se_temp ); + } + + lfds601_slist_internal_init_slist( ss, ss->user_data_delete_function, ss->user_state ); + + return; +} + diff --git a/liblfds/liblfds6.0.1/liblfds601/src/lfds601_slist/lfds601_slist_get_and_set.c b/liblfds/liblfds6.0.1/liblfds601/src/lfds601_slist/lfds601_slist_get_and_set.c new file mode 100644 index 0000000..0ce86a4 --- /dev/null +++ b/liblfds/liblfds6.0.1/liblfds601/src/lfds601_slist/lfds601_slist_get_and_set.c @@ -0,0 +1,124 @@ +#include "lfds601_slist_internal.h" + + + + + +/****************************************************************************/ +int lfds601_slist_get_user_data_from_element( struct lfds601_slist_element *se, void **user_data ) +{ + int + rv = 1; + + assert( se != NULL ); + assert( user_data != NULL ); + + *user_data = (void *) se->user_data_and_flags[LFDS601_SLIST_USER_DATA]; + + if( (lfds601_atom_t) se->user_data_and_flags[LFDS601_SLIST_FLAGS] & LFDS601_SLIST_FLAG_DELETED ) + rv = 0; + + return( rv ); +} + + + + + +/****************************************************************************/ +int lfds601_slist_set_user_data_in_element( struct lfds601_slist_element *se, void *user_data ) +{ + LFDS601_ALIGN(LFDS601_ALIGN_DOUBLE_POINTER) volatile void + *user_data_and_flags[2], + *new_user_data_and_flags[2]; + + int + rv = 1; + + assert( se != NULL ); + // TRD : user_data can be NULL + + user_data_and_flags[LFDS601_SLIST_USER_DATA] = se->user_data_and_flags[LFDS601_SLIST_USER_DATA]; + user_data_and_flags[LFDS601_SLIST_FLAGS] = se->user_data_and_flags[LFDS601_SLIST_FLAGS]; + + new_user_data_and_flags[LFDS601_SLIST_USER_DATA] = user_data; + + do + { + new_user_data_and_flags[LFDS601_SLIST_FLAGS] = user_data_and_flags[LFDS601_SLIST_FLAGS]; + } + while( !((lfds601_atom_t) user_data_and_flags[LFDS601_SLIST_FLAGS] & LFDS601_SLIST_FLAG_DELETED) and 0 == lfds601_abstraction_dcas((volatile lfds601_atom_t *) se->user_data_and_flags, (lfds601_atom_t *) new_user_data_and_flags, (lfds601_atom_t *) user_data_and_flags) ); + + if( (lfds601_atom_t) user_data_and_flags[LFDS601_SLIST_FLAGS] & LFDS601_SLIST_FLAG_DELETED ) + rv = 0; + + return( rv ); +} + + + + + +/****************************************************************************/ +struct lfds601_slist_element *lfds601_slist_get_head( struct lfds601_slist_state *ss, struct lfds601_slist_element **se ) +{ + assert( ss != NULL ); + assert( se != NULL ); + + *se = (struct lfds601_slist_element *) ss->head; + + lfds601_slist_internal_move_to_first_undeleted_element( se ); + + return( *se ); +} + + + + + +/****************************************************************************/ +struct lfds601_slist_element *lfds601_slist_get_next( struct lfds601_slist_element *se, struct lfds601_slist_element **next_se ) +{ + assert( se != NULL ); + assert( next_se != NULL ); + + *next_se = (struct lfds601_slist_element *) se->next; + + lfds601_slist_internal_move_to_first_undeleted_element( next_se ); + + return( *next_se ); +} + + + + + +/****************************************************************************/ +struct lfds601_slist_element *lfds601_slist_get_head_and_then_next( struct lfds601_slist_state *ss, struct lfds601_slist_element **se ) +{ + assert( ss != NULL ); + assert( se != NULL ); + + if( *se == NULL ) + lfds601_slist_get_head( ss, se ); + else + lfds601_slist_get_next( *se, se ); + + return( *se ); +} + + + + + +/****************************************************************************/ +void lfds601_slist_internal_move_to_first_undeleted_element( struct lfds601_slist_element **se ) +{ + assert( se != NULL ); + + while( *se != NULL and (lfds601_atom_t) (*se)->user_data_and_flags[LFDS601_SLIST_FLAGS] & LFDS601_SLIST_FLAG_DELETED ) + (*se) = (struct lfds601_slist_element *) (*se)->next; + + return; +} + diff --git a/liblfds/liblfds6.0.1/liblfds601/src/lfds601_slist/lfds601_slist_internal.h b/liblfds/liblfds6.0.1/liblfds601/src/lfds601_slist/lfds601_slist_internal.h new file mode 100644 index 0000000..b5d1016 --- /dev/null +++ b/liblfds/liblfds6.0.1/liblfds601/src/lfds601_slist/lfds601_slist_internal.h @@ -0,0 +1,55 @@ +/***** the library wide include file *****/ +#include "lfds601_internal.h" + +/***** defines *****/ +#define LFDS601_SLIST_USER_DATA 0 +#define LFDS601_SLIST_FLAGS 1 + +#define LFDS601_SLIST_NO_FLAGS 0x0 +#define LFDS601_SLIST_FLAG_DELETED 0x1 + +/***** structures *****/ +#pragma pack( push, LFDS601_ALIGN_SINGLE_POINTER ) + +struct lfds601_slist_state +{ + struct lfds601_slist_element + *volatile head; + + void + (*user_data_delete_function)( void *user_data, void *user_state ), + *user_state; +}; + +#pragma pack( pop ) + +#pragma pack( push, LFDS601_ALIGN_DOUBLE_POINTER ) + +/* TRD : this pragma pack doesn't seem to work under Windows + if the structure members are the correct way round + (next first), then user_data_and_flags ends up on + a single pointer boundary and DCAS crashes + + accordingly, I've moved user_data_and_flags first +*/ + +struct lfds601_slist_element +{ + void + *volatile user_data_and_flags[2]; + + // TRD : requires volatile as is target of CAS + struct lfds601_slist_element + *volatile next; +}; + +#pragma pack( pop ) + +/***** private prototypes *****/ +void lfds601_slist_internal_init_slist( struct lfds601_slist_state *ss, void (*user_data_delete_function)(void *user_data, void *user_state), void *user_state ); + +void lfds601_slist_internal_link_element_to_head( struct lfds601_slist_state *lfds601_slist_state, struct lfds601_slist_element *volatile se ); +void lfds601_slist_internal_link_element_after_element( struct lfds601_slist_element *volatile lfds601_slist_in_list_element, struct lfds601_slist_element *volatile se ); + +void lfds601_slist_internal_move_to_first_undeleted_element( struct lfds601_slist_element **se ); + diff --git a/liblfds/liblfds6.0.1/liblfds601/src/lfds601_slist/lfds601_slist_link.c b/liblfds/liblfds6.0.1/liblfds601/src/lfds601_slist/lfds601_slist_link.c new file mode 100644 index 0000000..4917520 --- /dev/null +++ b/liblfds/liblfds6.0.1/liblfds601/src/lfds601_slist/lfds601_slist_link.c @@ -0,0 +1,53 @@ +#include "lfds601_slist_internal.h" + + + + + +/****************************************************************************/ +void lfds601_slist_internal_link_element_to_head( struct lfds601_slist_state *ss, struct lfds601_slist_element *volatile se ) +{ + LFDS601_ALIGN(LFDS601_ALIGN_SINGLE_POINTER) struct lfds601_slist_element + *se_next; + + assert( ss != NULL ); + assert( se != NULL ); + + se_next = ss->head; + + do + { + se->next = se_next; + } + while( se->next != (se_next = (struct lfds601_slist_element *) lfds601_abstraction_cas((volatile lfds601_atom_t *) &ss->head, (lfds601_atom_t) se, (lfds601_atom_t) se->next)) ); + + return; +} + + + + + +/****************************************************************************/ +void lfds601_slist_internal_link_element_after_element( struct lfds601_slist_element *volatile lfds601_slist_in_list_element, struct lfds601_slist_element *volatile se ) +{ + LFDS601_ALIGN(LFDS601_ALIGN_SINGLE_POINTER) struct lfds601_slist_element + *se_prev, + *se_next; + + assert( lfds601_slist_in_list_element != NULL ); + assert( se != NULL ); + + se_prev = (struct lfds601_slist_element *) lfds601_slist_in_list_element; + + se_next = se_prev->next; + + do + { + se->next = se_next; + } + while( se->next != (se_next = (struct lfds601_slist_element *) lfds601_abstraction_cas((volatile lfds601_atom_t *) &se_prev->next, (lfds601_atom_t) se, (lfds601_atom_t) se->next)) ); + + return; +} + diff --git a/liblfds/liblfds6.0.1/liblfds601/src/lfds601_slist/lfds601_slist_new.c b/liblfds/liblfds6.0.1/liblfds601/src/lfds601_slist/lfds601_slist_new.c new file mode 100644 index 0000000..8151b45 --- /dev/null +++ b/liblfds/liblfds6.0.1/liblfds601/src/lfds601_slist/lfds601_slist_new.c @@ -0,0 +1,97 @@ +#include "lfds601_slist_internal.h" + + + + + +/****************************************************************************/ +int lfds601_slist_new( struct lfds601_slist_state **ss, void (*user_data_delete_function)(void *user_data, void *user_state), void *user_state ) +{ + int + rv = 0; + + assert( ss != NULL ); + // TRD : user_data_delete_function can be NULL + // TRD : user_state can be NULL + + *ss = (struct lfds601_slist_state *) lfds601_abstraction_aligned_malloc( sizeof(struct lfds601_slist_state), LFDS601_ALIGN_SINGLE_POINTER ); + + if( *ss != NULL ) + { + lfds601_slist_internal_init_slist( *ss, user_data_delete_function, user_state ); + rv = 1; + } + + return( rv ); +} + + + + + +/****************************************************************************/ +void lfds601_slist_internal_init_slist( struct lfds601_slist_state *ss, void (*user_data_delete_function)(void *user_data, void *user_state), void *user_state ) +{ + assert( ss != NULL ); + // TRD : user_data_delete_function can be NULL + // TRD : user_state can be NULL + + ss->head = NULL; + ss->user_data_delete_function = user_data_delete_function; + ss->user_state = user_state; + + return; +} + + + + + +/****************************************************************************/ +struct lfds601_slist_element *lfds601_slist_new_head( struct lfds601_slist_state *ss, void *user_data ) +{ + LFDS601_ALIGN(LFDS601_ALIGN_SINGLE_POINTER) struct lfds601_slist_element + *volatile se; + + assert( ss != NULL ); + // TRD : user_data can be NULL + + se = (struct lfds601_slist_element *) lfds601_abstraction_aligned_malloc( sizeof(struct lfds601_slist_element), LFDS601_ALIGN_DOUBLE_POINTER ); + + if( se != NULL ) + { + se->user_data_and_flags[LFDS601_SLIST_USER_DATA] = user_data; + se->user_data_and_flags[LFDS601_SLIST_FLAGS] = LFDS601_SLIST_NO_FLAGS; + + lfds601_slist_internal_link_element_to_head( ss, se ); + } + + return( (struct lfds601_slist_element *) se ); +} + + + + + +/****************************************************************************/ +struct lfds601_slist_element *lfds601_slist_new_next( struct lfds601_slist_element *se, void *user_data ) +{ + LFDS601_ALIGN(LFDS601_ALIGN_SINGLE_POINTER) struct lfds601_slist_element + *volatile se_next; + + assert( se != NULL ); + // TRD : user_data can be NULL + + se_next = (struct lfds601_slist_element *) lfds601_abstraction_aligned_malloc( sizeof(struct lfds601_slist_element), LFDS601_ALIGN_DOUBLE_POINTER ); + + if( se_next != NULL ) + { + se_next->user_data_and_flags[LFDS601_SLIST_USER_DATA] = user_data; + se_next->user_data_and_flags[LFDS601_SLIST_FLAGS] = LFDS601_SLIST_NO_FLAGS; + + lfds601_slist_internal_link_element_after_element( se, se_next ); + } + + return( (struct lfds601_slist_element *) se_next ); +} + diff --git a/liblfds/liblfds6.0.1/liblfds601/src/lfds601_stack/lfds601_stack_delete.c b/liblfds/liblfds6.0.1/liblfds601/src/lfds601_stack/lfds601_stack_delete.c new file mode 100644 index 0000000..aff9790 --- /dev/null +++ b/liblfds/liblfds6.0.1/liblfds601/src/lfds601_stack/lfds601_stack_delete.c @@ -0,0 +1,67 @@ +#include "lfds601_stack_internal.h" + + + + + +/****************************************************************************/ +void lfds601_stack_delete( struct lfds601_stack_state *ss, void (*user_data_delete_function)(void *user_data, void *user_state), void *user_state ) +{ + void + *user_data; + + assert( ss != NULL ); + // TRD : user_data_delete_function can be NULL + // TRD : user_state can be NULL + + while( lfds601_stack_pop(ss, &user_data) ) + if( user_data_delete_function != NULL ) + user_data_delete_function( user_data, user_state ); + + lfds601_freelist_delete( ss->fs, lfds601_stack_internal_freelist_delete_function, NULL ); + + lfds601_abstraction_aligned_free( ss ); + + return; +} + + + + + +/****************************************************************************/ +void lfds601_stack_clear( struct lfds601_stack_state *ss, void (*user_data_clear_function)(void *user_data, void *user_state), void *user_state ) +{ + void + *user_data; + + assert( ss != NULL ); + // TRD : user_data_clear_function can be NULL + // TRD : user_state can be NULL + + while( lfds601_stack_pop(ss, &user_data) ) + if( user_data_clear_function != NULL ) + user_data_clear_function( user_data, user_state ); + + return; +} + + + + + +/****************************************************************************/ +#pragma warning( disable : 4100 ) + +void lfds601_stack_internal_freelist_delete_function( void *user_data, void *user_state ) +{ + assert( user_data != NULL ); + assert( user_state == NULL ); + + lfds601_abstraction_aligned_free( user_data ); + + return; +} + +#pragma warning( default : 4100 ) + diff --git a/liblfds/liblfds6.0.1/liblfds601/src/lfds601_stack/lfds601_stack_internal.h b/liblfds/liblfds6.0.1/liblfds601/src/lfds601_stack/lfds601_stack_internal.h new file mode 100644 index 0000000..5157412 --- /dev/null +++ b/liblfds/liblfds6.0.1/liblfds601/src/lfds601_stack/lfds601_stack_internal.h @@ -0,0 +1,50 @@ +/***** the library wide include file *****/ +#include "lfds601_internal.h" + +/***** pragmas *****/ + +/***** defines *****/ +#define LFDS601_STACK_POINTER 0 +#define LFDS601_STACK_COUNTER 1 +#define LFDS601_STACK_PAC_SIZE 2 + +/***** structures *****/ +#pragma pack( push, LFDS601_ALIGN_DOUBLE_POINTER ) + +struct lfds601_stack_state +{ + // TRD : must come first for alignment + struct lfds601_stack_element + *volatile top[LFDS601_STACK_PAC_SIZE]; + + lfds601_atom_t + aba_counter; + + struct lfds601_freelist_state + *fs; +}; + +struct lfds601_stack_element +{ + struct lfds601_stack_element + *next[LFDS601_STACK_PAC_SIZE]; + + struct lfds601_freelist_element + *fe; + + void + *user_data; +}; + +#pragma pack( pop ) + +/***** private prototypes *****/ +int lfds601_stack_internal_freelist_init_function( void **user_data, void *user_state ); +void lfds601_stack_internal_freelist_delete_function( void *user_data, void *user_state ); + +void lfds601_stack_internal_new_element_from_freelist( struct lfds601_stack_state *ss, struct lfds601_stack_element *se[LFDS601_STACK_PAC_SIZE], void *user_data ); +void lfds601_stack_internal_new_element( struct lfds601_stack_state *ss, struct lfds601_stack_element *se[LFDS601_STACK_PAC_SIZE], void *user_data ); +void lfds601_stack_internal_init_element( struct lfds601_stack_state *ss, struct lfds601_stack_element *se[LFDS601_STACK_PAC_SIZE], struct lfds601_freelist_element *fe, void *user_data ); + +void lfds601_stack_internal_push( struct lfds601_stack_state *ss, struct lfds601_stack_element *se[LFDS601_STACK_PAC_SIZE] ); + diff --git a/liblfds/liblfds6.0.1/liblfds601/src/lfds601_stack/lfds601_stack_new.c b/liblfds/liblfds6.0.1/liblfds601/src/lfds601_stack/lfds601_stack_new.c new file mode 100644 index 0000000..c0a20b6 --- /dev/null +++ b/liblfds/liblfds6.0.1/liblfds601/src/lfds601_stack/lfds601_stack_new.c @@ -0,0 +1,139 @@ +#include "lfds601_stack_internal.h" + + + + + +/****************************************************************************/ +int lfds601_stack_new( struct lfds601_stack_state **ss, lfds601_atom_t number_elements ) +{ + int + rv = 0; + + assert( ss != NULL ); + // TRD : number_elements can be any value in its range + + *ss = (struct lfds601_stack_state *) lfds601_abstraction_aligned_malloc( sizeof(struct lfds601_stack_state), LFDS601_ALIGN_DOUBLE_POINTER ); + + if( *ss != NULL ) + { + // TRD : the size of the lfds601_freelist is the size of the lfds601_stack + lfds601_freelist_new( &(*ss)->fs, number_elements, lfds601_stack_internal_freelist_init_function, NULL ); + + if( (*ss)->fs == NULL ) + { + lfds601_abstraction_aligned_free( *ss ); + *ss = NULL; + } + + if( (*ss)->fs != NULL ) + { + (*ss)->top[LFDS601_STACK_POINTER] = NULL; + (*ss)->top[LFDS601_STACK_COUNTER] = 0; + (*ss)->aba_counter = 0; + rv = 1; + } + } + + return( rv ); +} + + + + + +/****************************************************************************/ +#pragma warning( disable : 4100 ) + +int lfds601_stack_internal_freelist_init_function( void **user_data, void *user_state ) +{ + int + rv = 0; + + assert( user_data != NULL ); + assert( user_state == NULL ); + + *user_data = lfds601_abstraction_aligned_malloc( sizeof(struct lfds601_stack_element), LFDS601_ALIGN_DOUBLE_POINTER ); + + if( *user_data != NULL ) + rv = 1; + + return( rv ); +} + +#pragma warning( default : 4100 ) + + + + + +/****************************************************************************/ +void lfds601_stack_internal_new_element_from_freelist( struct lfds601_stack_state *ss, struct lfds601_stack_element *se[LFDS601_STACK_PAC_SIZE], void *user_data ) +{ + struct lfds601_freelist_element + *fe; + + assert( ss != NULL ); + assert( se != NULL ); + // TRD : user_data can be any value in its range + + lfds601_freelist_pop( ss->fs, &fe ); + + if( fe == NULL ) + se[LFDS601_STACK_POINTER] = NULL; + + if( fe != NULL ) + lfds601_stack_internal_init_element( ss, se, fe, user_data ); + + return; +} + + + + + +/****************************************************************************/ +void lfds601_stack_internal_new_element( struct lfds601_stack_state *ss, struct lfds601_stack_element *se[LFDS601_STACK_PAC_SIZE], void *user_data ) +{ + struct lfds601_freelist_element + *fe; + + assert( ss != NULL ); + assert( se != NULL ); + // TRD : user_data can be any value in its range + + lfds601_freelist_guaranteed_pop( ss->fs, &fe ); + + if( fe == NULL ) + se[LFDS601_STACK_POINTER] = NULL; + + if( fe != NULL ) + lfds601_stack_internal_init_element( ss, se, fe, user_data ); + + return; +} + + + + + +/****************************************************************************/ +void lfds601_stack_internal_init_element( struct lfds601_stack_state *ss, struct lfds601_stack_element *se[LFDS601_STACK_PAC_SIZE], struct lfds601_freelist_element *fe, void *user_data ) +{ + assert( ss != NULL ); + assert( se != NULL ); + assert( fe != NULL ); + // TRD : user_data can be any value in its range + + lfds601_freelist_get_user_data_from_element( fe, (void **) &se[LFDS601_STACK_POINTER] ); + + se[LFDS601_STACK_COUNTER] = (struct lfds601_stack_element *) lfds601_abstraction_increment( (lfds601_atom_t *) &ss->aba_counter ); + + se[LFDS601_STACK_POINTER]->next[LFDS601_STACK_POINTER] = NULL; + se[LFDS601_STACK_POINTER]->next[LFDS601_STACK_COUNTER] = 0; + se[LFDS601_STACK_POINTER]->fe = fe; + se[LFDS601_STACK_POINTER]->user_data = user_data; + + return; +} + diff --git a/liblfds/liblfds6.0.1/liblfds601/src/lfds601_stack/lfds601_stack_push_pop.c b/liblfds/liblfds6.0.1/liblfds601/src/lfds601_stack/lfds601_stack_push_pop.c new file mode 100644 index 0000000..7be548c --- /dev/null +++ b/liblfds/liblfds6.0.1/liblfds601/src/lfds601_stack/lfds601_stack_push_pop.c @@ -0,0 +1,110 @@ +#include "lfds601_stack_internal.h" + + + + + +/****************************************************************************/ +int lfds601_stack_push( struct lfds601_stack_state *ss, void *user_data ) +{ + LFDS601_ALIGN(LFDS601_ALIGN_DOUBLE_POINTER) struct lfds601_stack_element + *se[LFDS601_STACK_PAC_SIZE]; + + assert( ss != NULL ); + // TRD : user_data can be NULL + + lfds601_stack_internal_new_element_from_freelist( ss, se, user_data ); + + if( se[LFDS601_STACK_POINTER] == NULL ) + return( 0 ); + + lfds601_stack_internal_push( ss, se ); + + return( 1 ); +} + + + + + +/****************************************************************************/ +int lfds601_stack_guaranteed_push( struct lfds601_stack_state *ss, void *user_data ) +{ + LFDS601_ALIGN(LFDS601_ALIGN_DOUBLE_POINTER) struct lfds601_stack_element + *se[LFDS601_STACK_PAC_SIZE]; + + assert( ss != NULL ); + // TRD : user_data can be NULL + + /* TRD : this function allocated a new lfds601_freelist element and uses that + to push onto the lfds601_stack, guaranteeing success (unless malloc() + fails of course) + */ + + lfds601_stack_internal_new_element( ss, se, user_data ); + + // TRD : malloc failed + if( se[LFDS601_STACK_POINTER] == NULL ) + return( 0 ); + + lfds601_stack_internal_push( ss, se ); + + return( 1 ); +} + + + + + +/****************************************************************************/ +void lfds601_stack_internal_push( struct lfds601_stack_state *ss, struct lfds601_stack_element *se[LFDS601_STACK_PAC_SIZE] ) +{ + LFDS601_ALIGN(LFDS601_ALIGN_DOUBLE_POINTER) struct lfds601_stack_element + *original_se_next[LFDS601_STACK_PAC_SIZE]; + + assert( ss != NULL ); + assert( se != NULL ); + + original_se_next[LFDS601_STACK_POINTER] = ss->top[LFDS601_STACK_POINTER]; + original_se_next[LFDS601_STACK_COUNTER] = ss->top[LFDS601_STACK_COUNTER]; + + do + { + se[LFDS601_STACK_POINTER]->next[LFDS601_STACK_POINTER] = original_se_next[LFDS601_STACK_POINTER]; + se[LFDS601_STACK_POINTER]->next[LFDS601_STACK_COUNTER] = original_se_next[LFDS601_STACK_COUNTER]; + } + while( 0 == lfds601_abstraction_dcas((volatile lfds601_atom_t *) ss->top, (lfds601_atom_t *) se, (lfds601_atom_t *) original_se_next) ); + + return; +} + + + + + +/****************************************************************************/ +int lfds601_stack_pop( struct lfds601_stack_state *ss, void **user_data ) +{ + LFDS601_ALIGN(LFDS601_ALIGN_DOUBLE_POINTER) struct lfds601_stack_element + *se[LFDS601_STACK_PAC_SIZE]; + + assert( ss != NULL ); + assert( user_data != NULL ); + + se[LFDS601_STACK_COUNTER] = ss->top[LFDS601_STACK_COUNTER]; + se[LFDS601_STACK_POINTER] = ss->top[LFDS601_STACK_POINTER]; + + do + { + if( se[LFDS601_STACK_POINTER] == NULL ) + return( 0 ); + } + while( 0 == lfds601_abstraction_dcas((volatile lfds601_atom_t *) ss->top, (lfds601_atom_t *) se[LFDS601_STACK_POINTER]->next, (lfds601_atom_t *) se) ); + + *user_data = se[LFDS601_STACK_POINTER]->user_data; + + lfds601_freelist_push( ss->fs, se[LFDS601_STACK_POINTER]->fe ); + + return( 1 ); +} + diff --git a/liblfds/liblfds6.0.1/liblfds601/src/lfds601_stack/lfds601_stack_query.c b/liblfds/liblfds6.0.1/liblfds601/src/lfds601_stack/lfds601_stack_query.c new file mode 100644 index 0000000..5f5b72f --- /dev/null +++ b/liblfds/liblfds6.0.1/liblfds601/src/lfds601_stack/lfds601_stack_query.c @@ -0,0 +1,30 @@ +#include "lfds601_stack_internal.h" + + + + + +/****************************************************************************/ +#pragma warning( disable : 4100 ) + +void lfds601_stack_query( struct lfds601_stack_state *ss, enum lfds601_stack_query_type query_type, void *query_input, void *query_output ) +{ + assert( ss != NULL ); + // TRD : query_type can be any value in its range + // TRD : query_iput can be NULL + assert( query_output != NULL ); + + switch( query_type ) + { + case LFDS601_STACK_QUERY_ELEMENT_COUNT: + assert( query_input == NULL ); + + lfds601_freelist_query( ss->fs, LFDS601_FREELIST_QUERY_ELEMENT_COUNT, NULL, query_output ); + break; + } + + return; +} + +#pragma warning( default : 4100 ) + diff --git a/liblfds/liblfds6.0.1/test/bin/empty_dir_placeholder_for_git b/liblfds/liblfds6.0.1/test/bin/empty_dir_placeholder_for_git new file mode 100644 index 0000000..e69de29 diff --git a/liblfds/liblfds6.0.1/test/building.txt b/liblfds/liblfds6.0.1/test/building.txt new file mode 100644 index 0000000..76bdb3a --- /dev/null +++ b/liblfds/liblfds6.0.1/test/building.txt @@ -0,0 +1,25 @@ +building test +============= + +Windows (user-mode) +=================== +1. Use Microsoft Visual Studio 2008 or Visual C++ 2008 Express Edition + to load "test.sln". + +2. Use Microsoft Windows SDK and GNUmake to run makefile.windows (obviously + you'll need to have run the appropriate vcvars*.bat first; you can build + for both IA64, 64-bit and 32-bit - just run the correct vcvars batch file). + + Targets are "rel", "dbg" and "clean". You need to clean between switching + targets. + +Windows (kernel) +================ +No build supported, since this is a command line utility. + +Linux +===== +Use GNUmake to run "makefile.linux". Targets are "rel", "dbg" and +"clean". You need to clean between switching targets. + + diff --git a/liblfds/liblfds6.0.1/test/makefile.linux b/liblfds/liblfds6.0.1/test/makefile.linux new file mode 100644 index 0000000..efba275 --- /dev/null +++ b/liblfds/liblfds6.0.1/test/makefile.linux @@ -0,0 +1,81 @@ +##### paths ##### +BINDIR = bin +INCDIR = ../liblfds601/inc +LIBDIR = ../liblfds601/bin +OBJDIR = obj +SRCDIR = src + +##### misc ##### +QUIETLY = 1>nul 2>nul + +##### sources, objects and libraries ##### +BINNAME = test +BINARY = $(BINDIR)/$(BINNAME) +SRCDIRS = . +SOURCES = abstraction_cpu_count.c test_abstraction.c abstraction_thread_start.c abstraction_thread_wait.c benchmark_freelist.c benchmark_queue.c benchmark_ringbuffer.c benchmark_stack.c test_freelist.c main.c misc.c test_queue.c test_ringbuffer.c test_slist.c test_stack.c +OBJECTS = $(patsubst %.c,$(OBJDIR)/%.o,$(notdir $(SOURCES))) +SYSLIBS = -lpthread -lc -lm +USRLIBS = -llfds601 + +##### CPU variants ##### +GCCARCH = $(shell uname -m) + +ifeq ($(GCCARCH),x86_64) + GCCARCH = core2 +endif + +ifeq ($(findstring arm,$(GCCARCH)),arm) + GCCARCH = armv6k +endif + +##### tools ##### +MAKE = make +MFLAGS = + +DG = gcc +DGFLAGS = -MM -std=c99 -I"$(SRCDIR)" -I"$(INCDIR)" + +CC = gcc +CFBASE = -Wall -Wno-unknown-pragmas -std=c99 -march=$(GCCARCH) -c -I"$(SRCDIR)" -I"$(INCDIR)" +CFREL = -O2 -Wno-strict-aliasing +CFDBG = -O0 -g + +LD = gcc +LFBASE = -L"$(LIBDIR)" +LFREL = -O2 -s +LFDBG = -O0 -g + +##### variants ##### +CFLAGS = $(CFBASE) $(CFDBG) +LFLAGS = $(LFBASE) $(LFDBG) + +ifeq ($(MAKECMDGOALS),rel) + CFLAGS = $(CFBASE) $(CFREL) + LFLAGS = $(LFBASE) $(LFREL) +endif + +##### search paths ##### +vpath %.c $(patsubst %,$(SRCDIR)/%:,$(SRCDIRS)) + +##### implicit rules ##### +$(OBJDIR)/%.o : %.c + $(DG) $(DGFLAGS) $< >$(OBJDIR)/$*.d + $(CC) $(CFLAGS) -o $@ $< + +##### explicit rules ##### +$(BINARY) : $(OBJECTS) + $(LD) -o $(BINARY) $(LFLAGS) $(OBJECTS) $(USRLIBS) $(SYSLIBS) + chmod +x $(BINARY) + +##### phony ##### +.PHONY : clean rel dbg + +clean : + @rm -f $(BINDIR)/$(BINNAME) $(OBJDIR)/*.o $(OBJDIR)/*.d + +rel : $(BINARY) +dbg : $(BINARY) + +##### dependencies ##### +-include $(DEPENDS) + diff --git a/liblfds/liblfds6.0.1/test/makefile.windows b/liblfds/liblfds6.0.1/test/makefile.windows new file mode 100644 index 0000000..bf810a9 --- /dev/null +++ b/liblfds/liblfds6.0.1/test/makefile.windows @@ -0,0 +1,64 @@ +##### paths ##### +BINDIR = bin +INCDIR = ../liblfds601/inc +LIBDIR = ../liblfds601/bin +OBJDIR = obj +SRCDIR = src + +##### misc ##### +QUIETLY = 1>nul 2>nul + +##### sources, objects and libraries ##### +BINNAME = test +BINARY = $(BINDIR)\$(BINNAME).exe +SRCDIRS = . +SOURCES = abstraction_cpu_count.c test_abstraction.c abstraction_thread_start.c abstraction_thread_wait.c benchmark_freelist.c benchmark_queue.c benchmark_ringbuffer.c benchmark_stack.c test_freelist.c main.c misc.c test_queue.c test_ringbuffer.c test_slist.c test_stack.c +OBJECTS = $(patsubst %.c,$(OBJDIR)/%.obj,$(notdir $(SOURCES))) +SYSLIBS = kernel32.lib +USRLIBS = liblfds601.lib + +##### tools ##### +MAKE = make +MFLAGS = + +CC = cl +CFBASE = /nologo /W4 /WX /c "-I$(SRCDIR)" "-I$(INCLUDE)" "-I$(INCDIR)" "/Fd$(BINDIR)\$(BINNAME).pdb" /D UNICODE /D _UNICODE /DWIN32_LEAN_AND_MEAN /D_CRT_SECURE_NO_WARNINGS +CFREL = /Ox /DNDEBUG /MT +CFDBG = /Od /Gm /Zi /D_DEBUG /MTd + +LD = link +LFBASE = "/libpath:$(LIB)" "/libpath:$(LIBDIR)" /nologo /subsystem:console /nodefaultlib /nxcompat /wx +LFREL = /incremental:no +LFDBG = /debug "/pdb:$(BINDIR)\$(BINNAME).pdb" + +##### variants ##### +CFLAGS = $(CFBASE) $(CFDBG) +LFLAGS = $(LFBASE) $(LFDBG) +CLIB = libcmtd.lib + +ifeq ($(MAKECMDGOALS),rel) + CFLAGS = $(CFBASE) $(CFREL) + LFLAGS = $(LFBASE) $(LFREL) + CLIB = libcmt.lib +endif + +##### search paths ##### +vpath %.c $(patsubst %,$(SRCDIR)/%;,$(SRCDIRS)) + +##### implicit rules ##### +$(OBJDIR)/%.obj : %.c + $(CC) $(CFLAGS) "/Fo$@" $< + +##### explicit rules ##### +$(BINARY) : $(OBJECTS) + $(LD) $(LFLAGS) $(CLIB) $(SYSLIBS) $(USRLIBS) $(OBJECTS) /out:$(BINARY) + +##### phony ##### +.PHONY : clean rel dbg + +clean : + @erase /Q $(OBJDIR)\*.obj $(BINDIR)\$(BINNAME).* $(QUIETLY) + +rel : $(BINARY) +dbg : $(BINARY) + diff --git a/liblfds/liblfds6.0.1/test/obj/empty_dir_placeholder_for_git b/liblfds/liblfds6.0.1/test/obj/empty_dir_placeholder_for_git new file mode 100644 index 0000000..e69de29 diff --git a/liblfds/liblfds6.0.1/test/src/abstraction.h b/liblfds/liblfds6.0.1/test/src/abstraction.h new file mode 100644 index 0000000..d0138ed --- /dev/null +++ b/liblfds/liblfds6.0.1/test/src/abstraction.h @@ -0,0 +1,50 @@ +/***** defines *****/ +#if (defined _WIN32 && defined _MSC_VER && !defined WIN_KERNEL_BUILD) + /* TRD : any Windows (user-mode) on any CPU with the Microsoft C compiler + + _WIN32 indicates 64-bit or 32-bit Windows + _MSC_VER indicates Microsoft C compiler + !WIN_KERNEL_BUILD indicates Windows user-mode + */ + + #include + typedef HANDLE thread_state_t; + typedef DWORD thread_return_t; + #define CALLING_CONVENTION WINAPI +#endif + +#if (defined _WIN32 && defined _MSC_VER && defined WIN_KERNEL_BUILD) + /* TRD : any Windows (kernel-mode) on any CPU with the Microsoft C compiler + + _WIN32 indicates 64-bit or 32-bit Windows + _MSC_VER indicates Microsoft C compiler + WIN_KERNEL_BUILD indicates Windows kernel + */ + + #include + typedef HANDLE thread_state_t; + typedef VOID thread_return_t; + #define CALLING_CONVENTION +#endif + +#if (defined __unix__ && __GNUC__) + /* TRD : any UNIX on any CPU with GCC + + __unix__ indicates Solaris, Linux, HPUX, etc + __GNUC__ indicates GCC + */ + + #include + #include + typedef pthread_t thread_state_t; + typedef void * thread_return_t; + #define CALLING_CONVENTION +#endif + +typedef thread_return_t (CALLING_CONVENTION *thread_function_t)( void *thread_user_state ); + +/***** public prototypes *****/ +unsigned int abstraction_cpu_count( void ); +int abstraction_thread_start( thread_state_t *thread_state, unsigned int cpu, thread_function_t thread_function, void *thread_user_state ); +void abstraction_thread_wait( thread_state_t thread_state ); + diff --git a/liblfds/liblfds6.0.1/test/src/abstraction_cpu_count.c b/liblfds/liblfds6.0.1/test/src/abstraction_cpu_count.c new file mode 100644 index 0000000..bf18bfb --- /dev/null +++ b/liblfds/liblfds6.0.1/test/src/abstraction_cpu_count.c @@ -0,0 +1,81 @@ +#include "internal.h" + + + + + +/****************************************************************************/ +#if (defined _WIN32 && defined _MSC_VER && !defined WIN_KERNEL_BUILD) + + /* TRD : any Windows (user-mode) on any CPU with the Microsoft C compiler + + _WIN32 indicates 64-bit or 32-bit Windows + _MSC_VER indicates Microsoft C compiler + !WIN_KERNEL_BUILD indicates Windows user-mode + */ + + unsigned int abstraction_cpu_count() + { + SYSTEM_INFO + si; + + GetNativeSystemInfo( &si ); + + return( (unsigned int) si.dwNumberOfProcessors ); + } + +#endif + + + + + +/****************************************************************************/ +#if (defined _WIN32 && defined _MSC_VER && defined WIN_KERNEL_BUILD) + + /* TRD : any Windows on any CPU with the Microsoft C compiler + + _WIN32 indicates 64-bit or 32-bit Windows + _MSC_VER indicates Microsoft C compiler + WIN_KERNEL_BUILD indicates Windows kernel + */ + + unsigned int abstraction_cpu_count() + { + unsigned int + active_processor_count; + + active_processor_count = KeQueryActiveProcessorCount( NULL ); + + return( active_processor_count ); + } + +#endif + + + + + +/****************************************************************************/ +#if (defined __linux__ && __GNUC__) + + /* TRD : Linux on any CPU with GCC + + this function I believe is Linux specific and varies by UNIX flavour + + __linux__ indicates Linux + __GNUC__ indicates GCC + */ + + unsigned int abstraction_cpu_count() + { + long int + cpu_count; + + cpu_count = sysconf( _SC_NPROCESSORS_ONLN ); + + return( (unsigned int) cpu_count ); + } + +#endif + diff --git a/liblfds/liblfds6.0.1/test/src/abstraction_thread_start.c b/liblfds/liblfds6.0.1/test/src/abstraction_thread_start.c new file mode 100644 index 0000000..363833e --- /dev/null +++ b/liblfds/liblfds6.0.1/test/src/abstraction_thread_start.c @@ -0,0 +1,127 @@ +#include "internal.h" + + + + + +/****************************************************************************/ +#if (defined _WIN32 && defined _MSC_VER && !defined WIN_KERNEL_BUILD) + + /* TRD : any Windows (user-mode) on any CPU with the Microsoft C compiler + + _WIN32 indicates 64-bit or 32-bit Windows + _MSC_VER indicates Microsoft C compiler + !WIN_KERNEL_BUILD indicates Windows user-mode + */ + + int abstraction_thread_start( thread_state_t *thread_state, unsigned int cpu, thread_function_t thread_function, void *thread_user_state ) + { + int + rv = 0; + + DWORD + thread_id; + + DWORD_PTR + affinity_mask, + result; + + assert( thread_state != NULL ); + // TRD : cpu can be any value in its range + assert( thread_function != NULL ); + // TRD : thread_user_state can be NULL + + affinity_mask = (DWORD_PTR) (1 << cpu); + + *thread_state = CreateThread( NULL, 0, thread_function, thread_user_state, NO_FLAGS, &thread_id ); + + result = SetThreadAffinityMask( *thread_state, affinity_mask ); + + if( *thread_state != NULL and result != 0 ) + rv = 1; + + return( rv ); + } + +#endif + + + + + +/****************************************************************************/ +#if (defined _WIN32 && defined _MSC_VER && defined WIN_KERNEL_BUILD) + + /* TRD : any Windows on any CPU with the Microsoft C compiler + + _WIN32 indicates 64-bit or 32-bit Windows + _MSC_VER indicates Microsoft C compiler + WIN_KERNEL_BUILD indicates Windows kernel + */ + + int abstraction_thread_start( thread_state_t *thread_state, unsigned int cpu, thread_function_t thread_function, void *thread_user_state ) + { + int + rv = 0; + + KAFFINITY + affinity_mask + + NTSTATUS + nts_create, + nts_affinity; + + assert( thread_state != NULL ); + // TRD : cpu can be any value in its range + assert( thread_function != NULL ); + // TRD : thread_user_state can be NULL + + affinity_mask = 1 << cpu; + + nts_create = PsCreateSystemThread( thread_state, THREAD_ALL_ACCESS, NULL, NULL, NULL, thread_function, thread_user_state ); + + nts_affinity = ZwSetInformationThread( thread_state, ThreadAffinityMask, &affinity_mask, sizeof(KAFFINITY) ); + + if( nts_create == STATUS_SUCCESS and nts_affinity == STATUS_SUCCESS ) + rv = 1; + + return( rv ); + } + +#endif + + + + + +/****************************************************************************/ +#if (defined __unix__) + + /* TRD : any UNIX on any CPU with any compiler + + I assumed pthreads is available on any UNIX. + + __unix__ indicates Solaris, Linux, HPUX, etc + */ + + int abstraction_thread_start( thread_state_t *thread_state, unsigned int cpu, thread_function_t thread_function, void *thread_user_state ) + { + int + rv = 0, + rv_create; + + assert( thread_state != NULL ); + // TRD : cpu can be any value in its range + assert( thread_function != NULL ); + // TRD : thread_user_state can be NULL + + rv_create = pthread_create( thread_state, NULL, thread_function, thread_user_state ); + + if( rv_create == 0 ) + rv = 1; + + return( rv ); + } + +#endif + diff --git a/liblfds/liblfds6.0.1/test/src/abstraction_thread_wait.c b/liblfds/liblfds6.0.1/test/src/abstraction_thread_wait.c new file mode 100644 index 0000000..572fb5d --- /dev/null +++ b/liblfds/liblfds6.0.1/test/src/abstraction_thread_wait.c @@ -0,0 +1,71 @@ +#include "internal.h" + + + + + +/****************************************************************************/ +#if (defined _WIN32 && defined _MSC_VER && !defined WIN_KERNEL_BUILD) + + /* TRD : any Windows (user-mode) on any CPU with the Microsoft C compiler + + _WIN32 indicates 64-bit or 32-bit Windows + _MSC_VER indicates Microsoft C compiler + !WIN_KERNEL_BUILD indicates Windows user-mode + */ + + void abstraction_thread_wait( thread_state_t thread_state ) + { + WaitForSingleObject( thread_state, INFINITE ); + + return; + } + +#endif + + + + + +/****************************************************************************/ +#if (defined _WIN32 && defined _MSC_VER && defined WIN_KERNEL_BUILD) + + /* TRD : any Windows on any CPU with the Microsoft C compiler + + _WIN32 indicates 64-bit or 32-bit Windows + _MSC_VER indicates Microsoft C compiler + WIN_KERNEL_BUILD indicates Windows kernel + */ + + void abstraction_thread_wait( thread_state_t thread_state ) + { + KeWaitForSingleObject( thread_state, Executive, KernelMode, FALSE, NULL ); + + return; + } + +#endif + + + + + +/****************************************************************************/ +#if (defined __unix__) + + /* TRD : any UNIX on any CPU with any compiler + + I assumed pthreads is available on any UNIX. + + __unix__ indicates Solaris, Linux, HPUX, etc + */ + + void abstraction_thread_wait( thread_state_t thread_state ) + { + pthread_join( thread_state, NULL ); + + return; + } + +#endif + diff --git a/liblfds/liblfds6.0.1/test/src/benchmark_freelist.c b/liblfds/liblfds6.0.1/test/src/benchmark_freelist.c new file mode 100644 index 0000000..3551d0b --- /dev/null +++ b/liblfds/liblfds6.0.1/test/src/benchmark_freelist.c @@ -0,0 +1,138 @@ +#include "internal.h" + + + + + +/****************************************************************************/ +void benchmark_lfds601_freelist( void ) +{ + unsigned int + loop, + thread_count, + cpu_count; + + struct lfds601_freelist_state + *fs; + + struct lfds601_freelist_benchmark + *fb; + + thread_state_t + *thread_handles; + + lfds601_atom_t + total_operations_for_full_test_for_all_cpus, + total_operations_for_full_test_for_all_cpus_for_one_cpu = 0; + + double + mean_operations_per_second_per_cpu, + difference_per_second_per_cpu, + total_difference_per_second_per_cpu, + std_dev_per_second_per_cpu, + scalability; + + /* TRD : here we benchmark the freelist + + the benchmark is to have a single freelist + where a worker thread busy-works popping and then pushing + */ + + cpu_count = abstraction_cpu_count(); + + thread_handles = (thread_state_t *) malloc( sizeof(thread_state_t) * cpu_count ); + + fb = (struct lfds601_freelist_benchmark *) malloc( sizeof(struct lfds601_freelist_benchmark) * cpu_count ); + + // TRD : print the benchmark ID and CSV header + printf( "\n" + "Release %s Freelist Benchmark #1\n" + "CPUs,total ops,mean ops/sec per CPU,standard deviation,scalability\n", LFDS601_RELEASE_NUMBER_STRING ); + + // TRD : we run CPU count times for scalability + for( thread_count = 1 ; thread_count <= cpu_count ; thread_count++ ) + { + // TRD : initialisation + lfds601_freelist_new( &fs, 1000, NULL, NULL ); + + for( loop = 0 ; loop < cpu_count ; loop++ ) + { + (fb+loop)->fs = fs; + (fb+loop)->operation_count = 0; + } + + // TRD : main test + for( loop = 0 ; loop < thread_count ; loop++ ) + abstraction_thread_start( &thread_handles[loop], loop, benchmark_lfds601_freelist_thread_pop_and_push, fb+loop ); + + for( loop = 0 ; loop < thread_count ; loop++ ) + abstraction_thread_wait( thread_handles[loop] ); + + // TRD : post test math + total_operations_for_full_test_for_all_cpus = 0; + total_difference_per_second_per_cpu = 0; + + for( loop = 0 ; loop < thread_count ; loop++ ) + total_operations_for_full_test_for_all_cpus += (fb+loop)->operation_count; + + mean_operations_per_second_per_cpu = ((double) total_operations_for_full_test_for_all_cpus / (double) thread_count) / (double) 10; + + if( thread_count == 1 ) + total_operations_for_full_test_for_all_cpus_for_one_cpu = total_operations_for_full_test_for_all_cpus; + + for( loop = 0 ; loop < thread_count ; loop++ ) + { + difference_per_second_per_cpu = ((double) (fb+loop)->operation_count / (double) 10) - mean_operations_per_second_per_cpu; + total_difference_per_second_per_cpu += difference_per_second_per_cpu * difference_per_second_per_cpu; + } + + std_dev_per_second_per_cpu = sqrt( (double) total_difference_per_second_per_cpu ); + + scalability = (double) total_operations_for_full_test_for_all_cpus / (double) (total_operations_for_full_test_for_all_cpus_for_one_cpu * thread_count); + + printf( "%u,%u,%.0f,%.0f,%0.2f\n", thread_count, (unsigned int) total_operations_for_full_test_for_all_cpus, mean_operations_per_second_per_cpu, std_dev_per_second_per_cpu, scalability ); + + // TRD : cleanup + lfds601_freelist_delete( fs, NULL, NULL ); + } + + free( fb ); + + free( thread_handles ); + + return; +} + + + + + +/****************************************************************************/ +thread_return_t CALLING_CONVENTION benchmark_lfds601_freelist_thread_pop_and_push( void *lfds601_freelist_benchmark ) +{ + struct lfds601_freelist_benchmark + *fb; + + struct lfds601_freelist_element + *fe; + + time_t + start_time; + + assert( lfds601_freelist_benchmark != NULL ); + + fb = (struct lfds601_freelist_benchmark *) lfds601_freelist_benchmark; + + time( &start_time ); + + while( time(NULL) < start_time + 10 ) + { + lfds601_freelist_pop( fb->fs, &fe ); + lfds601_freelist_push( fb->fs, fe ); + + fb->operation_count += 2; + } + + return( (thread_return_t) EXIT_SUCCESS ); +} + diff --git a/liblfds/liblfds6.0.1/test/src/benchmark_queue.c b/liblfds/liblfds6.0.1/test/src/benchmark_queue.c new file mode 100644 index 0000000..940adf7 --- /dev/null +++ b/liblfds/liblfds6.0.1/test/src/benchmark_queue.c @@ -0,0 +1,142 @@ +#include "internal.h" + + + + + +/****************************************************************************/ +void benchmark_lfds601_queue( void ) +{ + unsigned int + loop, + thread_count, + cpu_count; + + struct lfds601_queue_state + *qs; + + struct lfds601_queue_benchmark + *qb; + + thread_state_t + *thread_handles; + + lfds601_atom_t + total_operations_for_full_test_for_all_cpus, + total_operations_for_full_test_for_all_cpus_for_one_cpu = 0; + + double + mean_operations_per_second_per_cpu, + difference_per_second_per_cpu, + total_difference_per_second_per_cpu, + std_dev_per_second_per_cpu, + scalability; + + /* TRD : here we benchmark the queue + + the benchmark is to have a single queue + where a worker thread busy-works dequeuing and then queuing + */ + + cpu_count = abstraction_cpu_count(); + + thread_handles = (thread_state_t *) malloc( sizeof(thread_state_t) * cpu_count ); + + qb = (struct lfds601_queue_benchmark *) malloc( sizeof(struct lfds601_queue_benchmark) * cpu_count ); + + // TRD : print the benchmark ID and CSV header + printf( "\n" + "Release %s Queue Benchmark #1\n" + "CPUs,total ops,mean ops/sec per CPU,standard deviation,scalability\n", LFDS601_RELEASE_NUMBER_STRING ); + + // TRD : we run CPU count times for scalability + for( thread_count = 1 ; thread_count <= cpu_count ; thread_count++ ) + { + // TRD : initialisation + lfds601_queue_new( &qs, 1000 ); + + for( loop = 0 ; loop < cpu_count ; loop++ ) + { + (qb+loop)->qs = qs; + (qb+loop)->operation_count = 0; + } + + // TRD : populate the queue (we don't actually use the user data) + for( loop = 0 ; loop < 500 ; loop++ ) + lfds601_queue_enqueue( qs, (void *) (lfds601_atom_t) loop ); + + // TRD : main test + for( loop = 0 ; loop < thread_count ; loop++ ) + abstraction_thread_start( &thread_handles[loop], loop, benchmark_lfds601_queue_thread_delfds601_queue_and_enqueue, qb+loop ); + + for( loop = 0 ; loop < thread_count ; loop++ ) + abstraction_thread_wait( thread_handles[loop] ); + + // TRD : post test math + total_operations_for_full_test_for_all_cpus = 0; + total_difference_per_second_per_cpu = 0; + + for( loop = 0 ; loop < thread_count ; loop++ ) + total_operations_for_full_test_for_all_cpus += (qb+loop)->operation_count; + + mean_operations_per_second_per_cpu = ((double) total_operations_for_full_test_for_all_cpus / (double) thread_count) / (double) 10; + + if( thread_count == 1 ) + total_operations_for_full_test_for_all_cpus_for_one_cpu = total_operations_for_full_test_for_all_cpus; + + for( loop = 0 ; loop < thread_count ; loop++ ) + { + difference_per_second_per_cpu = ((double) (qb+loop)->operation_count / (double) 10) - mean_operations_per_second_per_cpu; + total_difference_per_second_per_cpu += difference_per_second_per_cpu * difference_per_second_per_cpu; + } + + std_dev_per_second_per_cpu = sqrt( (double) total_difference_per_second_per_cpu ); + + scalability = (double) total_operations_for_full_test_for_all_cpus / (double) (total_operations_for_full_test_for_all_cpus_for_one_cpu * thread_count); + + printf( "%u,%u,%.0f,%.0f,%0.2f\n", thread_count, (unsigned int) total_operations_for_full_test_for_all_cpus, mean_operations_per_second_per_cpu, std_dev_per_second_per_cpu, scalability ); + + // TRD : cleanup + lfds601_queue_delete( qs, NULL, NULL ); + } + + free( qb ); + + free( thread_handles ); + + return; +} + + + + + +/****************************************************************************/ +thread_return_t CALLING_CONVENTION benchmark_lfds601_queue_thread_delfds601_queue_and_enqueue( void *lfds601_queue_benchmark ) +{ + struct lfds601_queue_benchmark + *qb; + + void + *user_data; + + time_t + start_time; + + assert( lfds601_queue_benchmark != NULL ); + + qb = (struct lfds601_queue_benchmark *) lfds601_queue_benchmark; + + time( &start_time ); + + while( time(NULL) < start_time + 10 ) + { + lfds601_queue_dequeue( qb->qs, &user_data ); + lfds601_queue_enqueue( qb->qs, user_data ); + + qb->operation_count += 2; + } + + return( (thread_return_t) EXIT_SUCCESS ); +} + diff --git a/liblfds/liblfds6.0.1/test/src/benchmark_ringbuffer.c b/liblfds/liblfds6.0.1/test/src/benchmark_ringbuffer.c new file mode 100644 index 0000000..ad02d7a --- /dev/null +++ b/liblfds/liblfds6.0.1/test/src/benchmark_ringbuffer.c @@ -0,0 +1,141 @@ +#include "internal.h" + + + + + +/****************************************************************************/ +void benchmark_lfds601_ringbuffer( void ) +{ + unsigned int + loop, + thread_count, + cpu_count; + + struct lfds601_ringbuffer_state + *rs; + + struct lfds601_ringbuffer_benchmark + *rb; + + thread_state_t + *thread_handles; + + lfds601_atom_t + total_operations_for_full_test_for_all_cpus, + total_operations_for_full_test_for_all_cpus_for_one_cpu = 0; + + double + mean_operations_per_second_per_cpu, + difference_per_second_per_cpu, + total_difference_per_second_per_cpu, + std_dev_per_second_per_cpu, + scalability; + + /* TRD : here we benchmark the ringbuffer + + the benchmark is to have a single ringbuffer + where a worker thread busy-works writing and then reading + */ + + cpu_count = abstraction_cpu_count(); + + thread_handles = (thread_state_t *) malloc( sizeof(thread_state_t) * cpu_count ); + + rb = (struct lfds601_ringbuffer_benchmark *) malloc( sizeof(struct lfds601_ringbuffer_benchmark) * cpu_count ); + + // TRD : print the benchmark ID and CSV header + printf( "\n" + "Release %s Ringbuffer Benchmark #1\n" + "CPUs,total ops,mean ops/sec per CPU,standard deviation,scalability\n", LFDS601_RELEASE_NUMBER_STRING ); + + // TRD : we run CPU count times for scalability + for( thread_count = 1 ; thread_count <= cpu_count ; thread_count++ ) + { + // TRD : initialisation + lfds601_ringbuffer_new( &rs, 1000, NULL, NULL ); + + for( loop = 0 ; loop < cpu_count ; loop++ ) + { + (rb+loop)->rs = rs; + (rb+loop)->operation_count = 0; + } + + // TRD : main test + for( loop = 0 ; loop < thread_count ; loop++ ) + abstraction_thread_start( &thread_handles[loop], loop, benchmark_lfds601_ringbuffer_thread_write_and_read, rb+loop ); + + for( loop = 0 ; loop < thread_count ; loop++ ) + abstraction_thread_wait( thread_handles[loop] ); + + // TRD : post test math + total_operations_for_full_test_for_all_cpus = 0; + total_difference_per_second_per_cpu = 0; + + for( loop = 0 ; loop < thread_count ; loop++ ) + total_operations_for_full_test_for_all_cpus += (rb+loop)->operation_count; + + mean_operations_per_second_per_cpu = ((double) total_operations_for_full_test_for_all_cpus / (double) thread_count) / (double) 10; + + if( thread_count == 1 ) + total_operations_for_full_test_for_all_cpus_for_one_cpu = total_operations_for_full_test_for_all_cpus; + + for( loop = 0 ; loop < thread_count ; loop++ ) + { + difference_per_second_per_cpu = ((double) (rb+loop)->operation_count / (double) 10) - mean_operations_per_second_per_cpu; + total_difference_per_second_per_cpu += difference_per_second_per_cpu * difference_per_second_per_cpu; + } + + std_dev_per_second_per_cpu = sqrt( (double) total_difference_per_second_per_cpu ); + + scalability = (double) total_operations_for_full_test_for_all_cpus / (double) (total_operations_for_full_test_for_all_cpus_for_one_cpu * thread_count); + + printf( "%u,%u,%.0f,%.0f,%0.2f\n", thread_count, (unsigned int) total_operations_for_full_test_for_all_cpus, mean_operations_per_second_per_cpu, std_dev_per_second_per_cpu, scalability ); + + // TRD : cleanup + lfds601_ringbuffer_delete( rs, NULL, NULL ); + } + + free( rb ); + + free( thread_handles ); + + return; +} + + + + + +/****************************************************************************/ +thread_return_t CALLING_CONVENTION benchmark_lfds601_ringbuffer_thread_write_and_read( void *lfds601_ringbuffer_benchmark ) +{ + struct lfds601_ringbuffer_benchmark + *rb; + + struct lfds601_freelist_element + *fe; + + time_t + start_time; + + assert( lfds601_ringbuffer_benchmark != NULL ); + + rb = (struct lfds601_ringbuffer_benchmark *) lfds601_ringbuffer_benchmark; + + time( &start_time ); + + while( time(NULL) < start_time + 10 ) + { + lfds601_ringbuffer_get_write_element( rb->rs, &fe, NULL ); + lfds601_ringbuffer_put_write_element( rb->rs, fe ); + + lfds601_ringbuffer_get_read_element( rb->rs, &fe ); + lfds601_ringbuffer_put_read_element( rb->rs, fe ); + + rb->operation_count += 2; + } + + return( (thread_return_t) EXIT_SUCCESS ); +} + diff --git a/liblfds/liblfds6.0.1/test/src/benchmark_stack.c b/liblfds/liblfds6.0.1/test/src/benchmark_stack.c new file mode 100644 index 0000000..38f0329 --- /dev/null +++ b/liblfds/liblfds6.0.1/test/src/benchmark_stack.c @@ -0,0 +1,138 @@ +#include "internal.h" + + + + + +/****************************************************************************/ +void benchmark_lfds601_stack( void ) +{ + unsigned int + loop, + thread_count, + cpu_count; + + struct lfds601_stack_state + *ss; + + struct lfds601_stack_benchmark + *sb; + + thread_state_t + *thread_handles; + + lfds601_atom_t + total_operations_for_full_test_for_all_cpus, + total_operations_for_full_test_for_all_cpus_for_one_cpu = 0; + + double + mean_operations_per_second_per_cpu, + difference_per_second_per_cpu, + total_difference_per_second_per_cpu, + std_dev_per_second_per_cpu, + scalability; + + /* TRD : here we benchmark the stack + + the benchmark is to have a single stack + where a worker thread busy-works pushing then popping + */ + + cpu_count = abstraction_cpu_count(); + + thread_handles = (thread_state_t *) malloc( sizeof(thread_state_t) * cpu_count ); + + sb = (struct lfds601_stack_benchmark *) malloc( sizeof(struct lfds601_stack_benchmark) * cpu_count ); + + // TRD : print the benchmark ID and CSV header + printf( "\n" + "Release %s Stack Benchmark #1\n" + "CPUs,total ops,mean ops/sec per CPU,standard deviation,scalability\n", LFDS601_RELEASE_NUMBER_STRING ); + + // TRD : we run CPU count times for scalability + for( thread_count = 1 ; thread_count <= cpu_count ; thread_count++ ) + { + // TRD : initialisation + lfds601_stack_new( &ss, 1000 ); + + for( loop = 0 ; loop < cpu_count ; loop++ ) + { + (sb+loop)->ss = ss; + (sb+loop)->operation_count = 0; + } + + // TRD : main test + for( loop = 0 ; loop < thread_count ; loop++ ) + abstraction_thread_start( &thread_handles[loop], loop, benchmark_lfds601_stack_thread_push_and_pop, sb+loop ); + + for( loop = 0 ; loop < thread_count ; loop++ ) + abstraction_thread_wait( thread_handles[loop] ); + + // TRD : post test math + total_operations_for_full_test_for_all_cpus = 0; + total_difference_per_second_per_cpu = 0; + + for( loop = 0 ; loop < thread_count ; loop++ ) + total_operations_for_full_test_for_all_cpus += (sb+loop)->operation_count; + + mean_operations_per_second_per_cpu = ((double) total_operations_for_full_test_for_all_cpus / (double) thread_count) / (double) 10; + + if( thread_count == 1 ) + total_operations_for_full_test_for_all_cpus_for_one_cpu = total_operations_for_full_test_for_all_cpus; + + for( loop = 0 ; loop < thread_count ; loop++ ) + { + difference_per_second_per_cpu = ((double) (sb+loop)->operation_count / (double) 10) - mean_operations_per_second_per_cpu; + total_difference_per_second_per_cpu += difference_per_second_per_cpu * difference_per_second_per_cpu; + } + + std_dev_per_second_per_cpu = sqrt( (double) total_difference_per_second_per_cpu ); + + scalability = (double) total_operations_for_full_test_for_all_cpus / (double) (total_operations_for_full_test_for_all_cpus_for_one_cpu * thread_count); + + printf( "%u,%u,%.0f,%.0f,%0.2f\n", thread_count, (unsigned int) total_operations_for_full_test_for_all_cpus, mean_operations_per_second_per_cpu, std_dev_per_second_per_cpu, scalability ); + + // TRD : cleanup + lfds601_stack_delete( ss, NULL, NULL ); + } + + free( sb ); + + free( thread_handles ); + + return; +} + + + + + +/****************************************************************************/ +thread_return_t CALLING_CONVENTION benchmark_lfds601_stack_thread_push_and_pop( void *lfds601_stack_benchmark ) +{ + struct lfds601_stack_benchmark + *sb; + + void + *user_data = NULL; + + time_t + start_time; + + assert( lfds601_stack_benchmark != NULL ); + + sb = (struct lfds601_stack_benchmark *) lfds601_stack_benchmark; + + time( &start_time ); + + while( time(NULL) < start_time + 10 ) + { + lfds601_stack_push( sb->ss, user_data ); + lfds601_stack_pop( sb->ss, &user_data ); + + sb->operation_count += 2; + } + + return( (thread_return_t) EXIT_SUCCESS ); +} + diff --git a/liblfds/liblfds6.0.1/test/src/internal.h b/liblfds/liblfds6.0.1/test/src/internal.h new file mode 100644 index 0000000..cbdee11 --- /dev/null +++ b/liblfds/liblfds6.0.1/test/src/internal.h @@ -0,0 +1,104 @@ +/***** ANSI includes *****/ +#include +#include +#include +#include +#include +#include +#include + +/***** internal includes *****/ +#include "abstraction.h" + +/***** external includes *****/ +#include "liblfds601.h" + +/***** defines *****/ +#define and && +#define or || + +#define RAISED 1 +#define LOWERED 0 + +#define NO_FLAGS 0x0 + +/***** enums *****/ +enum lfds601_test_operation +{ + UNKNOWN, + HELP, + TEST, + BENCHMARK +}; + +/***** structs *****/ +#include "structures.h" + +/***** prototypes *****/ +int main( int argc, char **argv ); + +void internal_display_test_name( char *test_name ); +void internal_display_test_result( unsigned int number_name_dvs_pairs, ... ); +void internal_display_data_structure_validity( enum lfds601_data_structure_validity dvs ); + +void benchmark_lfds601_freelist( void ); + thread_return_t CALLING_CONVENTION benchmark_lfds601_freelist_thread_pop_and_push( void *lfds601_freelist_benchmark ); + +void benchmark_lfds601_queue( void ); + thread_return_t CALLING_CONVENTION benchmark_lfds601_queue_thread_delfds601_queue_and_enqueue( void *lfds601_queue_benchmark ); + +void benchmark_lfds601_ringbuffer( void ); + thread_return_t CALLING_CONVENTION benchmark_lfds601_ringbuffer_thread_write_and_read( void *lfds601_ringbuffer_benchmark ); + +void benchmark_lfds601_stack( void ); + thread_return_t CALLING_CONVENTION benchmark_lfds601_stack_thread_push_and_pop( void *lfds601_stack_benchmark ); + +void test_lfds601_abstraction( void ); + void abstraction_test_increment( void ); + thread_return_t CALLING_CONVENTION abstraction_test_internal_thread_increment( void *shared_counter ); + thread_return_t CALLING_CONVENTION abstraction_test_internal_thread_atomic_increment( void *shared_counter ); + void abstraction_test_dcas( void ); + thread_return_t CALLING_CONVENTION abstraction_test_internal_thread_dcas( void *abstraction_test_dcas_state ); + +void test_lfds601_freelist( void ); + void freelist_test_internal_popping( void ); + int freelist_test_internal_popping_init( void **user_data, void *user_state ); + thread_return_t CALLING_CONVENTION freelist_test_internal_thread_popping( void *freelist_test_popping_state ); + void freelist_test_internal_pushing( void ); + int freelist_test_internal_pushing_init( void **user_data, void *user_state ); + void freelist_test_internal_pushing_delete( void *user_data, void *user_state ); + thread_return_t CALLING_CONVENTION freelist_test_internal_thread_pushing( void *freelist_test_pushing_state ); + void freelist_test_internal_popping_and_pushing( void ); + thread_return_t CALLING_CONVENTION freelist_test_internal_thread_popping_and_pushing_start_popping( void *freelist_test_popping_and_pushing_state ); + thread_return_t CALLING_CONVENTION freelist_test_internal_thread_popping_and_pushing_start_pushing( void *freelist_test_popping_and_pushing_state ); + void freelist_test_internal_rapid_popping_and_pushing( void ); + thread_return_t CALLING_CONVENTION freelist_test_internal_thread_rapid_popping_and_pushing( void *lfds601_freelist_state ); + +void test_lfds601_queue( void ); + void queue_test_enqueuing( void ); + thread_return_t CALLING_CONVENTION queue_test_internal_thread_simple_enqueuer( void *queue_test_enqueuing_state ); + void queue_test_dequeuing( void ); + thread_return_t CALLING_CONVENTION queue_test_internal_thread_simple_dequeuer( void *queue_test_dequeuing_state ); + void queue_test_enqueuing_and_dequeuing( void ); + thread_return_t CALLING_CONVENTION queue_test_internal_thread_enqueuer_and_dequeuer( void *queue_test_rapid_enqueuing_and_dequeuing_state ); + void queue_test_rapid_enqueuing_and_dequeuing( void ); + thread_return_t CALLING_CONVENTION queue_test_internal_thread_rapid_enqueuer_and_dequeuer( void *queue_test_rapid_enqueuing_and_dequeuing_state ); + +void test_lfds601_ringbuffer( void ); + void ringbuffer_test_reading( void ); + thread_return_t CALLING_CONVENTION ringbuffer_test_thread_simple_reader( void *ringbuffer_test_reading_state ); + void ringbuffer_test_writing( void ); + thread_return_t CALLING_CONVENTION ringbuffer_test_thread_simple_writer( void *ringbuffer_test_writing_state ); + void ringbuffer_test_reading_and_writing( void ); + thread_return_t CALLING_CONVENTION ringbuffer_test_thread_reader_writer( void *ringbuffer_test_reading_and_writing_state ); + +void test_lfds601_slist( void ); + thread_return_t CALLING_CONVENTION lfds601_slist_internal_thread_head_writer( void *lfds601_slist_thread_start_state ); + thread_return_t CALLING_CONVENTION lfds601_slist_internal_thread_after_writer( void *lfds601_slist_thread_start_state ); + thread_return_t CALLING_CONVENTION lfds601_slist_internal_thread_traverser( void *lfds601_slist_thread_start_state ); + thread_return_t CALLING_CONVENTION lfds601_slist_internal_thread_deleter_traverser( void *lfds601_slist_thread_start_state ); + +void test_lfds601_stack( void ); + thread_return_t CALLING_CONVENTION lfds601_stack_internal_thread_reader( void *lfds601_stack_state ); + thread_return_t CALLING_CONVENTION lfds601_stack_internal_thread_writer( void *lfds601_stack_state ); + diff --git a/liblfds/liblfds6.0.1/test/src/main.c b/liblfds/liblfds6.0.1/test/src/main.c new file mode 100644 index 0000000..c7a7b1e --- /dev/null +++ b/liblfds/liblfds6.0.1/test/src/main.c @@ -0,0 +1,74 @@ +#include "internal.h" + + + + + +/****************************************************************************/ +int main( int argc, char **argv ) +{ + enum lfds601_test_operation + operation = UNKNOWN; + + unsigned int + loop, + iterations = 1; + + assert( argc >= 1 ); + assert( argv != NULL ); + + if( argc == 1 or argc >= 4 ) + operation = HELP; + + if( operation == UNKNOWN ) + { + if( 0 == strcmp(*(argv+1), "test") ) + { + operation = TEST; + + // TRD : sscanf() may fail, but iterations is initialised to 1, so it's okay + if( argc == 3 ) + sscanf( *(argv+2), "%u", &iterations ); + } + + if( 0 == strcmp(*(argv+1), "benchmark") ) + operation = BENCHMARK; + } + + switch( operation ) + { + case UNKNOWN: + case HELP: + printf( "test [test|benchmark] [iterations]\n" + " test : run the test suite\n" + " benchmark : run the benchmark suite\n" + " iterations : optional, only applies to tests, default is 1\n" ); + break; + + case TEST: + for( loop = 1 ; loop < iterations+1 ; loop++ ) + { + printf( "\n" + "Test Iteration %02u\n" + "=================\n", loop ); + + test_lfds601_abstraction(); + test_lfds601_freelist(); + test_lfds601_queue(); + test_lfds601_ringbuffer(); + test_lfds601_slist(); + test_lfds601_stack(); + } + break; + + case BENCHMARK: + benchmark_lfds601_freelist(); + benchmark_lfds601_queue(); + benchmark_lfds601_ringbuffer(); + benchmark_lfds601_stack(); + break; + } + + return( EXIT_SUCCESS ); +} + diff --git a/liblfds/liblfds6.0.1/test/src/misc.c b/liblfds/liblfds6.0.1/test/src/misc.c new file mode 100644 index 0000000..4492115 --- /dev/null +++ b/liblfds/liblfds6.0.1/test/src/misc.c @@ -0,0 +1,124 @@ +#include "internal.h" + + + + + +/****************************************************************************/ +void internal_display_test_name( char *test_name ) +{ + assert( test_name != NULL ); + + printf( "%s...", test_name ); + fflush( stdout ); + + return; +} + + + + + +/****************************************************************************/ +void internal_display_test_result( unsigned int number_name_dvs_pairs, ... ) +{ + va_list + va; + + int + passed_flag = RAISED; + + unsigned int + loop; + + char + *name; + + enum lfds601_data_structure_validity + dvs; + + // TRD : number_name_dvs_pairs can be any value in its range + + va_start( va, number_name_dvs_pairs ); + + for( loop = 0 ; loop < number_name_dvs_pairs ; loop++ ) + { + name = va_arg( va, char * ); + dvs = va_arg( va, enum lfds601_data_structure_validity ); + + if( dvs != LFDS601_VALIDITY_VALID ) + { + passed_flag = LOWERED; + break; + } + } + + va_end( va ); + + if( passed_flag == RAISED ) + puts( "passed" ); + + if( passed_flag == LOWERED ) + { + printf( "failed (" ); + + va_start( va, number_name_dvs_pairs ); + + for( loop = 0 ; loop < number_name_dvs_pairs ; loop++ ) + { + name = va_arg( va, char * ); + dvs = va_arg( va, enum lfds601_data_structure_validity ); + + printf( "%s ", name ); + internal_display_data_structure_validity( dvs ); + + if( loop+1 < number_name_dvs_pairs ) + printf( ", " ); + } + + va_end( va ); + + printf( ")\n" ); + } + + return; +} + + + + + +/****************************************************************************/ +void internal_display_data_structure_validity( enum lfds601_data_structure_validity dvs ) +{ + char + *string = NULL; + + switch( dvs ) + { + case LFDS601_VALIDITY_VALID: + string = "valid"; + break; + + case LFDS601_VALIDITY_INVALID_LOOP: + string = "invalid - loop detected"; + break; + + case LFDS601_VALIDITY_INVALID_MISSING_ELEMENTS: + string = "invalid - missing elements"; + break; + + case LFDS601_VALIDITY_INVALID_ADDITIONAL_ELEMENTS: + string = "invalid - additional elements"; + break; + + case LFDS601_VALIDITY_INVALID_TEST_DATA: + string = "invalid - invalid test data"; + break; + } + + printf( "%s", string ); + + return; +} + diff --git a/liblfds/liblfds6.0.1/test/src/structures.h b/liblfds/liblfds6.0.1/test/src/structures.h new file mode 100644 index 0000000..4a48da1 --- /dev/null +++ b/liblfds/liblfds6.0.1/test/src/structures.h @@ -0,0 +1,190 @@ +/***** structs *****/ +#pragma pack( push, LFDS601_ALIGN_DOUBLE_POINTER ) + +/***** abstraction tests *****/ +struct abstraction_test_dcas_state +{ + volatile lfds601_atom_t + *shared_counter; + + lfds601_atom_t + local_counter; +}; + +/***** freelist tests *****/ +struct freelist_test_popping_state +{ + struct lfds601_freelist_state + *fs, + *fs_thread_local; +}; + +struct freelist_test_pushing_state +{ + lfds601_atom_t + thread_number; + + struct lfds601_freelist_state + *source_fs, + *fs; +}; + +struct freelist_test_popping_and_pushing_state +{ + struct lfds601_freelist_state + *local_fs, + *fs; +}; + +struct freelist_test_counter_and_thread_number +{ + lfds601_atom_t + thread_number; + + unsigned long long int + counter; +}; + +/***** queue tests *****/ +struct queue_test_enqueuing_state +{ + struct lfds601_queue_state + *qs; + + lfds601_atom_t + counter; +}; + +struct queue_test_dequeuing_state +{ + struct lfds601_queue_state + *qs; + + int + error_flag; +}; + +struct queue_test_enqueuing_and_dequeuing_state +{ + struct lfds601_queue_state + *qs; + + lfds601_atom_t + counter, + thread_number, + *per_thread_counters; + + unsigned int + cpu_count; + + int + error_flag; +}; + +struct queue_test_rapid_enqueuing_and_dequeuing_state +{ + struct lfds601_queue_state + *qs; + + lfds601_atom_t + counter; +}; + +/***** ringbuffer tests *****/ +struct ringbuffer_test_reading_state +{ + struct lfds601_ringbuffer_state + *rs; + + int + error_flag; + + lfds601_atom_t + read_count; +}; + +struct ringbuffer_test_writing_state +{ + struct lfds601_ringbuffer_state + *rs; + + lfds601_atom_t + write_count; +}; + +struct ringbuffer_test_reading_and_writing_state +{ + struct lfds601_ringbuffer_state + *rs; + + lfds601_atom_t + counter, + *per_thread_counters; + + unsigned int + cpu_count; + + int + error_flag; +}; + +/***** slist tests *****/ +struct lfds601_slist_thread_start_state +{ + struct lfds601_slist_state + *ss; + + struct lfds601_slist_element + *se; + + time_t + duration; + + unsigned long int + iteration_modulo; +}; + +/***** stack tests *****/ + +/***** freelist benchmarks *****/ +struct lfds601_freelist_benchmark +{ + struct lfds601_freelist_state + *fs; + + lfds601_atom_t + operation_count; +}; + +/***** queue benchmarks *****/ +struct lfds601_queue_benchmark +{ + struct lfds601_queue_state + *qs; + + lfds601_atom_t + operation_count; +}; + +/***** ringbuffer benchmarks *****/ +struct lfds601_ringbuffer_benchmark +{ + struct lfds601_ringbuffer_state + *rs; + + lfds601_atom_t + operation_count; +}; + +/***** stack benchmarks *****/ +struct lfds601_stack_benchmark +{ + struct lfds601_stack_state + *ss; + + lfds601_atom_t + operation_count; +}; + +#pragma pack( pop ) + diff --git a/liblfds/liblfds6.0.1/test/src/test_abstraction.c b/liblfds/liblfds6.0.1/test/src/test_abstraction.c new file mode 100644 index 0000000..5a0f7e9 --- /dev/null +++ b/liblfds/liblfds6.0.1/test/src/test_abstraction.c @@ -0,0 +1,246 @@ +#include "internal.h" + + + + + +/****************************************************************************/ +void test_lfds601_abstraction( void ) +{ + printf( "\n" + "Abstraction Tests\n" + "=================\n" ); + + abstraction_test_increment(); + abstraction_test_dcas(); + + return; +} + + + + + +/****************************************************************************/ +void abstraction_test_increment( void ) +{ + unsigned int + loop, + cpu_count; + + thread_state_t + *thread_handles; + + lfds601_atom_t + shared_counter = 0, + atomic_shared_counter = 0; + + /* TRD : here we test lfds601_abstraction_increment + + first, we run one thread per CPU where each thread increments + a shared counter 10,000,000 times - however, this first test + does NOT use atomic increment; it uses "++" + + second, we repeat the exercise, but this time using + lfds601_abstraction_increment() + + if the final value in the first test is less than (10,000,000*cpu_count) + then the system is sensitive to non-atomic increments; this means if + our atomic version of the test passes, we can have some degree of confidence + that it works + + if the final value in the first test is in fact correct, then we can't know + that our atomic version has changed anything + + and of course if the final value in the atomic test is wrong, we know things + are broken + */ + + internal_display_test_name( "Atomic increment" ); + + cpu_count = abstraction_cpu_count(); + + thread_handles = malloc( sizeof(thread_state_t) * cpu_count ); + + // TRD : non-atomic + for( loop = 0 ; loop < cpu_count ; loop++ ) + abstraction_thread_start( &thread_handles[loop], loop, abstraction_test_internal_thread_increment, &shared_counter ); + + for( loop = 0 ; loop < cpu_count ; loop++ ) + abstraction_thread_wait( thread_handles[loop] ); + + // TRD : atomic + for( loop = 0 ; loop < cpu_count ; loop++ ) + abstraction_thread_start( &thread_handles[loop], loop, abstraction_test_internal_thread_atomic_increment, &atomic_shared_counter ); + + for( loop = 0 ; loop < cpu_count ; loop++ ) + abstraction_thread_wait( thread_handles[loop] ); + + free( thread_handles ); + + // TRD : results + if( shared_counter < (10000000 * cpu_count) and atomic_shared_counter == (10000000 * cpu_count) ) + puts( "passed" ); + + if( shared_counter == (10000000 * cpu_count) and atomic_shared_counter == (10000000 * cpu_count) ) + puts( "indeterminate" ); + + if( atomic_shared_counter < (10000000 * cpu_count) ) + puts( "failed" ); + + return; +} + + + + + +/****************************************************************************/ +thread_return_t CALLING_CONVENTION abstraction_test_internal_thread_increment( void *shared_counter ) +{ + volatile lfds601_atom_t + count = 0; + + /* TRD : lfds601_atom_t must be volatile or the compiler + optimizes it away into a single store + */ + + assert( shared_counter != NULL ); + + while( count++ < 10000000 ) + (*(lfds601_atom_t *) shared_counter)++; + + return( (thread_return_t) EXIT_SUCCESS ); +} + + + + + +/****************************************************************************/ +thread_return_t CALLING_CONVENTION abstraction_test_internal_thread_atomic_increment( void *shared_counter ) +{ + lfds601_atom_t + count = 0; + + assert( shared_counter != NULL ); + + while( count++ < 10000000 ) + lfds601_abstraction_increment( shared_counter ); + + return( (thread_return_t) EXIT_SUCCESS ); +} + + + + + +/****************************************************************************/ +void abstraction_test_dcas( void ) +{ + unsigned int + loop, + cpu_count; + + thread_state_t + *thread_handles; + + struct abstraction_test_dcas_state + *atds; + + LFDS601_ALIGN(LFDS601_ALIGN_DOUBLE_POINTER) volatile lfds601_atom_t + shared_counter[2] = { 0, 0 }; + + lfds601_atom_t + local_total = 0; + + /* TRD : here we test lfds601_abstraction_dcas + + we run one thread per CPU + we use lfds601_abstraction_dcas() to increment a shared counter + every time a thread successfully increments the counter, + it increments a thread local counter + the threads run for ten seconds + after the threads finish, we total the local counters + they should equal the shared counter + */ + + internal_display_test_name( "Atomic DCAS" ); + + cpu_count = abstraction_cpu_count(); + + atds = malloc( sizeof(struct abstraction_test_dcas_state) * cpu_count ); + + for( loop = 0 ; loop < cpu_count ; loop++ ) + { + (atds+loop)->shared_counter = shared_counter; + (atds+loop)->local_counter = 0; + } + + thread_handles = malloc( sizeof(thread_state_t) * cpu_count ); + + for( loop = 0 ; loop < cpu_count ; loop++ ) + abstraction_thread_start( &thread_handles[loop], loop, abstraction_test_internal_thread_dcas, atds+loop ); + + for( loop = 0 ; loop < cpu_count ; loop++ ) + abstraction_thread_wait( thread_handles[loop] ); + + free( thread_handles ); + + // TRD : results + for( loop = 0 ; loop < cpu_count ; loop++ ) + local_total += (atds+loop)->local_counter; + + if( local_total == shared_counter[0] ) + puts( "passed" ); + + if( local_total != shared_counter[0] ) + puts( "failed" ); + + // TRD : cleanup + free( atds ); + + return; +} + + + + + +/****************************************************************************/ +thread_return_t CALLING_CONVENTION abstraction_test_internal_thread_dcas( void *abstraction_test_dcas_state ) +{ + struct abstraction_test_dcas_state + *atds; + + time_t + start_time; + + LFDS601_ALIGN(LFDS601_ALIGN_DOUBLE_POINTER) lfds601_atom_t + exchange[2], + compare[2]; + + assert( abstraction_test_dcas_state != NULL ); + + atds = (struct abstraction_test_dcas_state *) abstraction_test_dcas_state; + + time( &start_time ); + + while( time(NULL) < start_time + 10 ) + { + compare[0] = *atds->shared_counter; + compare[1] = *(atds->shared_counter+1); + + do + { + exchange[0] = compare[0] + 1; + exchange[1] = compare[1]; + } + while( 0 == lfds601_abstraction_dcas(atds->shared_counter, exchange, compare) ); + + atds->local_counter++; + } + + return( (thread_return_t) EXIT_SUCCESS ); +} + diff --git a/liblfds/liblfds6.0.1/test/src/test_freelist.c b/liblfds/liblfds6.0.1/test/src/test_freelist.c new file mode 100644 index 0000000..6c28e03 --- /dev/null +++ b/liblfds/liblfds6.0.1/test/src/test_freelist.c @@ -0,0 +1,662 @@ +#include "internal.h" + + + + + +/****************************************************************************/ +void test_lfds601_freelist( void ) +{ + printf( "\n" + "Freelist Tests\n" + "==============\n" ); + + freelist_test_internal_popping(); + freelist_test_internal_pushing(); + freelist_test_internal_popping_and_pushing(); + freelist_test_internal_rapid_popping_and_pushing(); + + return; +} + + + + + +/****************************************************************************/ +void freelist_test_internal_popping( void ) +{ + unsigned int + loop, + cpu_count, + count; + + thread_state_t + *thread_handles; + + enum lfds601_data_structure_validity + dvs = LFDS601_VALIDITY_VALID; + + struct lfds601_freelist_state + *fs; + + struct lfds601_freelist_element + *fe; + + struct freelist_test_popping_state + *ftps; + + unsigned int + *found_count; + + /* TRD : we create a freelist with 1,000,000 elements + + the creation function runs in a single thread and creates + and pushes those elements onto the freelist + + each element contains a void pointer which is its element number + + we then run one thread per CPU + where each thread loops, popping as quickly as possible + each popped element is pushed onto a thread-local freelist + + the threads run till the source freelist is empty + + we then check the thread-local freelists + we should find we have every element + + then tidy up + */ + + internal_display_test_name( "Popping" ); + + cpu_count = abstraction_cpu_count(); + + lfds601_freelist_new( &fs, 1000000, freelist_test_internal_popping_init, NULL ); + ftps = malloc( sizeof(struct freelist_test_popping_state) * cpu_count ); + for( loop = 0 ; loop < cpu_count ; loop++ ) + { + (ftps+loop)->fs = fs; + lfds601_freelist_new( &(ftps+loop)->fs_thread_local, 0, NULL, NULL ); + } + + thread_handles = malloc( sizeof(thread_state_t) * cpu_count ); + + for( loop = 0 ; loop < cpu_count ; loop++ ) + abstraction_thread_start( &thread_handles[loop], loop, freelist_test_internal_thread_popping, ftps+loop ); + + for( loop = 0 ; loop < cpu_count ; loop++ ) + abstraction_thread_wait( thread_handles[loop] ); + + free( thread_handles ); + + // TRD : now we check the thread-local freelists + found_count = malloc( sizeof(unsigned int) * 1000000 ); + for( loop = 0 ; loop < 1000000 ; loop++ ) + *(found_count+loop) = 0; + + for( loop = 0 ; loop < cpu_count ; loop++ ) + { + while( lfds601_freelist_pop((ftps+loop)->fs_thread_local, &fe) ) + { + lfds601_freelist_get_user_data_from_element( fe, (void **) &count ); + (*(found_count+count))++; + lfds601_freelist_push( fs, fe ); + } + } + + for( loop = 0 ; loop < 1000000 and dvs == LFDS601_VALIDITY_VALID ; loop++ ) + { + if( *(found_count+loop) == 0 ) + dvs = LFDS601_VALIDITY_INVALID_MISSING_ELEMENTS; + + if( *(found_count+loop) > 1 ) + dvs = LFDS601_VALIDITY_INVALID_ADDITIONAL_ELEMENTS; + } + + // TRD : cleanup + free( found_count ); + for( loop = 0 ; loop < cpu_count ; loop++ ) + lfds601_freelist_delete( (ftps+loop)->fs_thread_local, NULL, NULL ); + lfds601_freelist_delete( fs, NULL, NULL ); + + // TRD : print the test result + internal_display_test_result( 1, "freelist", dvs ); + + return; +} + + + + + +/****************************************************************************/ +#pragma warning( disable : 4100 ) + +int freelist_test_internal_popping_init( void **user_data, void *user_state ) +{ + static lfds601_atom_t + count = 0; + + assert( user_data != NULL ); + assert( user_state == NULL ); + + *(lfds601_atom_t *) user_data = count++; + + return( 1 ); +} + +#pragma warning( default : 4100 ) + + + + + +/****************************************************************************/ +thread_return_t CALLING_CONVENTION freelist_test_internal_thread_popping( void *freelist_test_popping_state ) +{ + struct freelist_test_popping_state + *ftps; + + struct lfds601_freelist_element + *fe; + + assert( freelist_test_popping_state != NULL ); + + ftps = (struct freelist_test_popping_state *) freelist_test_popping_state; + + while( lfds601_freelist_pop(ftps->fs, &fe) ) + lfds601_freelist_push( ftps->fs_thread_local, fe ); + + return( (thread_return_t) EXIT_SUCCESS ); +} + + + + + +/****************************************************************************/ +void freelist_test_internal_pushing( void ) +{ + unsigned int + loop, + cpu_count; + + thread_state_t + *thread_handles; + + enum lfds601_data_structure_validity + dvs; + + struct freelist_test_pushing_state + *ftps; + + struct lfds601_freelist_element + *fe; + + struct lfds601_freelist_state + *fs, + *cleanup_fs; + + struct freelist_test_counter_and_thread_number + *cnt, + *counter_and_number_trackers; + + struct lfds601_validation_info + vi = { 1000000, 1000000 }; + + /* TRD : we create an empty freelist, which we will push to + + we then create one freelist per CPU, where this freelist + contains 1,000,000/cpu_count number of elements and + each element is an incrementing counter and unique ID + (from 0 to number of CPUs) + + we then start one thread per CPU, where each thread is + given one of the populated freelists and pops from that + to push to the empty freelist + + the reason for this is to achieve memory pre-allocation + which allows the pushing threads to run at maximum speed + + the threads end when their freelists are empty + + we then fully pop the now populated main freelist (onto + a second freelist, so we can cleanly free all memory), + checking that the counts increment on a per unique ID basis + and that the number of elements we pop equals 1,000,000 + (since each element has an incrementing counter which is + unique on a per unique ID basis, we can know we didn't lose + any elements) + */ + + internal_display_test_name( "Pushing" ); + + cpu_count = abstraction_cpu_count(); + + ftps = malloc( sizeof(struct freelist_test_pushing_state) * cpu_count ); + + lfds601_freelist_new( &fs, 0, NULL, NULL ); + + for( loop = 0 ; loop < cpu_count ; loop++ ) + { + (ftps+loop)->thread_number = (lfds601_atom_t) loop; + lfds601_freelist_new( &(ftps+loop)->source_fs, 1000000 / cpu_count, freelist_test_internal_pushing_init, (void *) (lfds601_atom_t) loop ); + (ftps+loop)->fs = fs; + } + + thread_handles = malloc( sizeof(thread_state_t) * cpu_count ); + + for( loop = 0 ; loop < cpu_count ; loop++ ) + abstraction_thread_start( &thread_handles[loop], loop, freelist_test_internal_thread_pushing, ftps+loop ); + + for( loop = 0 ; loop < cpu_count ; loop++ ) + abstraction_thread_wait( thread_handles[loop] ); + + free( thread_handles ); + + // TRD : now fully pop and verify the main freelist + lfds601_freelist_new( &cleanup_fs, 0, NULL, NULL ); + + counter_and_number_trackers = malloc( sizeof(struct freelist_test_counter_and_thread_number) * cpu_count ); + + for( loop = 0 ; loop < cpu_count ; loop++ ) + { + (counter_and_number_trackers+loop)->counter = (1000000 / cpu_count) * loop; + (counter_and_number_trackers+loop)->thread_number = (lfds601_atom_t) loop; + } + + lfds601_freelist_query( fs, LFDS601_FREELIST_QUERY_VALIDATE, &vi, (void *) &dvs ); + + while( dvs == LFDS601_VALIDITY_VALID and lfds601_freelist_pop(fs, &fe) ) + { + static int count = 0; + + lfds601_freelist_get_user_data_from_element( fe, (void **) &cnt ); + + if( cnt->counter != (counter_and_number_trackers+cnt->thread_number)->counter++ ) + dvs = LFDS601_VALIDITY_INVALID_MISSING_ELEMENTS; + + lfds601_freelist_push( cleanup_fs, fe ); + + count++; + } + + // TRD : clean up + free( counter_and_number_trackers ); + + for( loop = 0 ; loop < cpu_count ; loop++ ) + lfds601_freelist_delete( (ftps+loop)->source_fs, NULL, NULL ); + + free( ftps ); + + lfds601_freelist_delete( cleanup_fs, freelist_test_internal_pushing_delete, NULL ); + lfds601_freelist_delete( fs, NULL, NULL ); + + // TRD : print the test result + internal_display_test_result( 1, "freelist", dvs ); + + return; +} + + + + + +/****************************************************************************/ +int freelist_test_internal_pushing_init( void **user_data, void *user_state ) +{ + struct freelist_test_counter_and_thread_number + *ftcatn; + + static lfds601_atom_t + counter = 0; + + assert( user_data != NULL ); + // TRD : user_state is being used as an integer type + + *user_data = malloc( sizeof(struct freelist_test_counter_and_thread_number) ); + + ftcatn = (struct freelist_test_counter_and_thread_number *) *user_data; + + ftcatn->counter = counter++; + ftcatn->thread_number = (lfds601_atom_t) user_state; + + return( 1 ); +} + + + + + +/****************************************************************************/ +#pragma warning( disable : 4100 ) + +void freelist_test_internal_pushing_delete( void *user_data, void *user_state ) +{ + assert( user_data != NULL ); + assert( user_state == NULL ); + + free( user_data ); + + return; +} + +#pragma warning( default : 4100 ) + + + + + +/****************************************************************************/ +thread_return_t CALLING_CONVENTION freelist_test_internal_thread_pushing( void *freelist_test_pushing_state ) +{ + struct freelist_test_pushing_state + *ftps; + + struct lfds601_freelist_element + *fe; + + assert( freelist_test_pushing_state != NULL ); + + ftps = (struct freelist_test_pushing_state *) freelist_test_pushing_state; + + while( lfds601_freelist_pop(ftps->source_fs, &fe) ) + lfds601_freelist_push( ftps->fs, fe ); + + return( (thread_return_t) EXIT_SUCCESS ); +} + + + + + +/****************************************************************************/ +void freelist_test_internal_popping_and_pushing( void ) +{ + unsigned int + loop, + cpu_count; + + thread_state_t + *thread_handles; + + enum lfds601_data_structure_validity + dvs; + + struct lfds601_freelist_state + *fs; + + struct freelist_test_popping_and_pushing_state + *pps; + + struct lfds601_validation_info + vi; + + /* TRD : we have two threads per CPU + the threads loop for ten seconds + the first thread pushes 100000 elements then pops 100000 elements + the second thread pops 100000 elements then pushes 100000 elements + all pushes and pops go onto the single main freelist + + after time is up, all threads push what they have remaining onto + the main freelist + + we then validate the main freelist + */ + + internal_display_test_name( "Popping and pushing (10 seconds)" ); + + cpu_count = abstraction_cpu_count(); + + lfds601_freelist_new( &fs, 100000 * cpu_count, NULL, NULL ); + + pps = malloc( sizeof(struct freelist_test_popping_and_pushing_state) * cpu_count * 2 ); + + for( loop = 0 ; loop < cpu_count ; loop++ ) + { + (pps+loop)->fs = fs; + lfds601_freelist_new( &(pps+loop)->local_fs, 0, NULL, NULL ); + + (pps+loop+cpu_count)->fs = fs; + lfds601_freelist_new( &(pps+loop+cpu_count)->local_fs, 100000, NULL, NULL ); + } + + thread_handles = malloc( sizeof(thread_state_t) * cpu_count * 2 ); + + for( loop = 0 ; loop < cpu_count ; loop++ ) + { + abstraction_thread_start( &thread_handles[loop], loop, freelist_test_internal_thread_popping_and_pushing_start_popping, pps+loop ); + abstraction_thread_start( &thread_handles[loop+cpu_count], loop, freelist_test_internal_thread_popping_and_pushing_start_pushing, pps+loop+cpu_count ); + } + + for( loop = 0 ; loop < cpu_count * 2 ; loop++ ) + abstraction_thread_wait( thread_handles[loop] ); + + free( thread_handles ); + + for( loop = 0 ; loop < cpu_count * 2 ; loop++ ) + lfds601_freelist_delete( (pps+loop)->local_fs, NULL, NULL ); + + free( pps ); + + vi.min_elements = vi.max_elements = 100000 * cpu_count * 2; + + lfds601_freelist_query( fs, LFDS601_FREELIST_QUERY_VALIDATE, (void *) &vi, (void *) &dvs ); + + lfds601_freelist_delete( fs, NULL, NULL ); + + // TRD : print the test result + internal_display_test_result( 1, "freelist", dvs ); + + return; +} + + + + + + +/****************************************************************************/ +thread_return_t CALLING_CONVENTION freelist_test_internal_thread_popping_and_pushing_start_popping( void *freelist_test_popping_and_pushing_state ) +{ + struct freelist_test_popping_and_pushing_state + *pps; + + struct lfds601_freelist_element + *fe; + + time_t + start_time; + + unsigned int + count; + + assert( freelist_test_popping_and_pushing_state != NULL ); + + pps = (struct freelist_test_popping_and_pushing_state *) freelist_test_popping_and_pushing_state; + + time( &start_time ); + + while( time(NULL) < start_time + 10 ) + { + count = 0; + + while( count < 100000 ) + { + lfds601_freelist_pop( pps->fs, &fe ); + + if( fe != NULL ) + { + lfds601_freelist_push( pps->local_fs, fe ); + count++; + } + } + + while( lfds601_freelist_pop(pps->local_fs, &fe) ) + lfds601_freelist_push( pps->fs, fe ); + } + + return( (thread_return_t) EXIT_SUCCESS ); +} + + + + + +/****************************************************************************/ +thread_return_t CALLING_CONVENTION freelist_test_internal_thread_popping_and_pushing_start_pushing( void *freelist_test_popping_and_pushing_state ) +{ + struct freelist_test_popping_and_pushing_state + *pps; + + struct lfds601_freelist_element + *fe; + + time_t + start_time; + + unsigned int + count; + + assert( freelist_test_popping_and_pushing_state != NULL ); + + pps = (struct freelist_test_popping_and_pushing_state *) freelist_test_popping_and_pushing_state; + + time( &start_time ); + + while( time(NULL) < start_time + 10 ) + { + while( lfds601_freelist_pop(pps->local_fs, &fe) ) + lfds601_freelist_push( pps->fs, fe ); + + count = 0; + + while( count < 1000 ) + { + lfds601_freelist_pop( pps->fs, &fe ); + + if( fe != NULL ) + { + lfds601_freelist_push( pps->local_fs, fe ); + count++; + } + } + } + + // TRD : now push whatever we have in our local freelist + while( lfds601_freelist_pop(pps->local_fs, &fe) ) + lfds601_freelist_push( pps->fs, fe ); + + return( (thread_return_t) EXIT_SUCCESS ); +} + + + + + +/****************************************************************************/ +void freelist_test_internal_rapid_popping_and_pushing( void ) +{ + unsigned int + loop, + cpu_count; + + thread_state_t + *thread_handles; + + struct lfds601_freelist_state + *fs; + + struct lfds601_validation_info + vi; + + enum lfds601_data_structure_validity + dvs; + + /* TRD : in these tests there is a fundamental antagonism between + how much checking/memory clean up that we do and the + likelyhood of collisions between threads in their lock-free + operations + + the lock-free operations are very quick; if we do anything + much at all between operations, we greatly reduce the chance + of threads colliding + + so we have some tests which do enough checking/clean up that + they can tell the freelist is valid and don't leak memory + and here, this test now is one of those which does minimal + checking - in fact, the nature of the test is that you can't + do any real checking - but goes very quickly + + what we do is create a small freelist and then run one thread + per CPU, where each thread simply pops and then immediately + pushes + + the test runs for ten seconds + + after the test is done, the only check we do is to traverse + the freelist, checking for loops and ensuring the number of + elements is correct + */ + + internal_display_test_name( "Rapid popping and pushing (10 seconds)" ); + + cpu_count = abstraction_cpu_count(); + + lfds601_freelist_new( &fs, cpu_count, NULL, NULL ); + + thread_handles = malloc( sizeof(thread_state_t) * cpu_count ); + + for( loop = 0 ; loop < cpu_count ; loop++ ) + abstraction_thread_start( &thread_handles[loop], loop, freelist_test_internal_thread_rapid_popping_and_pushing, fs ); + + for( loop = 0 ; loop < cpu_count ; loop++ ) + abstraction_thread_wait( thread_handles[loop] ); + + free( thread_handles ); + + vi.min_elements = cpu_count; + vi.max_elements = cpu_count; + + lfds601_freelist_query( fs, LFDS601_FREELIST_QUERY_VALIDATE, (void *) &vi, (void *) &dvs ); + + lfds601_freelist_delete( fs, NULL, NULL ); + + // TRD : print the test result + internal_display_test_result( 1, "freelist", dvs ); + + return; +} + + + + + +/****************************************************************************/ +thread_return_t CALLING_CONVENTION freelist_test_internal_thread_rapid_popping_and_pushing( void *lfds601_freelist_state ) +{ + struct lfds601_freelist_state + *fs; + + struct lfds601_freelist_element + *fe; + + time_t + start_time; + + assert( lfds601_freelist_state != NULL ); + + fs = (struct lfds601_freelist_state *) lfds601_freelist_state; + + time( &start_time ); + + while( time(NULL) < start_time + 10 ) + { + lfds601_freelist_pop( fs, &fe ); + lfds601_freelist_push( fs, fe ); + } + + return( (thread_return_t) EXIT_SUCCESS ); +} + diff --git a/liblfds/liblfds6.0.1/test/src/test_queue.c b/liblfds/liblfds6.0.1/test/src/test_queue.c new file mode 100644 index 0000000..832e182 --- /dev/null +++ b/liblfds/liblfds6.0.1/test/src/test_queue.c @@ -0,0 +1,519 @@ +#include "internal.h" + + + + + +/****************************************************************************/ +void test_lfds601_queue( void ) +{ + printf( "\n" + "Queue Tests\n" + "===========\n" ); + + queue_test_enqueuing(); + queue_test_dequeuing(); + queue_test_enqueuing_and_dequeuing(); + queue_test_rapid_enqueuing_and_dequeuing(); + + return; +} + + + + + +/****************************************************************************/ +void queue_test_enqueuing( void ) +{ + unsigned int + loop, + cpu_count; + + thread_state_t + *thread_handles; + + struct lfds601_queue_state + *qs; + + struct queue_test_enqueuing_state + *qtes; + + lfds601_atom_t + user_data, + thread, + count, + *per_thread_counters; + + struct lfds601_validation_info + vi = { 1000000, 1000000 }; + + enum lfds601_data_structure_validity + dvs[2]; + + /* TRD : create an empty queue with 1,000,000 elements in its freelist + then run one thread per CPU + where each thread busy-works, enqueuing elements (until there are no more elements) + each element's void pointer of user data is (thread number | element number) + where element_number is a thread-local counter starting at 0 + where the thread_number occupies the top byte + + when we're done, we check that all the elements are present + and increment on a per-thread basis + */ + + internal_display_test_name( "Enqueuing" ); + + cpu_count = abstraction_cpu_count(); + + lfds601_queue_new( &qs, 1000000 ); + + qtes = malloc( sizeof(struct queue_test_enqueuing_state) * cpu_count ); + + for( loop = 0 ; loop < cpu_count ; loop++ ) + { + (qtes+loop)->qs = qs; + (qtes+loop)->counter = (lfds601_atom_t) loop << (sizeof(lfds601_atom_t)*8-8); + } + + thread_handles = malloc( sizeof(thread_state_t) * cpu_count ); + + for( loop = 0 ; loop < cpu_count ; loop++ ) + abstraction_thread_start( &thread_handles[loop], loop, queue_test_internal_thread_simple_enqueuer, qtes+loop ); + + for( loop = 0 ; loop < cpu_count ; loop++ ) + abstraction_thread_wait( thread_handles[loop] ); + + free( thread_handles ); + + free( qtes ); + + /* TRD : first, validate the queue + + then dequeue + we expect to find element numbers increment on a per thread basis + */ + + lfds601_queue_query( qs, LFDS601_QUEUE_QUERY_VALIDATE, &vi, dvs ); + + per_thread_counters = malloc( sizeof(lfds601_atom_t) * cpu_count ); + + for( loop = 0 ; loop < cpu_count ; loop++ ) + *(per_thread_counters+loop) = 0; + + while( dvs[0] == LFDS601_VALIDITY_VALID and dvs[1] == LFDS601_VALIDITY_VALID and lfds601_queue_dequeue(qs, (void *) &user_data) ) + { + thread = user_data >> (sizeof(lfds601_atom_t)*8-8); + count = (user_data << 8) >> 8; + + if( thread >= cpu_count ) + { + dvs[0] = LFDS601_VALIDITY_INVALID_TEST_DATA; + break; + } + + if( count < per_thread_counters[thread] ) + dvs[0] = LFDS601_VALIDITY_INVALID_ADDITIONAL_ELEMENTS; + + if( count > per_thread_counters[thread] ) + dvs[0] = LFDS601_VALIDITY_INVALID_MISSING_ELEMENTS; + + if( count == per_thread_counters[thread] ) + per_thread_counters[thread]++; + } + + free( per_thread_counters ); + + lfds601_queue_delete( qs, NULL, NULL ); + + internal_display_test_result( 2, "queue", dvs[0], "queue freelist", dvs[1] ); + + return; +} + + + + + +/****************************************************************************/ +thread_return_t CALLING_CONVENTION queue_test_internal_thread_simple_enqueuer( void *queue_test_enqueuing_state ) +{ + struct queue_test_enqueuing_state + *qtes; + + assert( queue_test_enqueuing_state != NULL ); + + qtes = (struct queue_test_enqueuing_state *) queue_test_enqueuing_state; + + // TRD : top byte of counter is already our thread number + while( lfds601_queue_enqueue(qtes->qs, (void *) qtes->counter++) ); + + return( (thread_return_t) EXIT_SUCCESS ); +} + + + + + +/****************************************************************************/ +void queue_test_dequeuing( void ) +{ + unsigned int + loop, + cpu_count; + + thread_state_t + *thread_handles; + + struct lfds601_queue_state + *qs; + + struct queue_test_dequeuing_state + *qtds; + + struct lfds601_validation_info + vi = { 0, 0 }; + + enum lfds601_data_structure_validity + dvs[2]; + + /* TRD : create a queue with 1,000,000 elements + + use a single thread to enqueue every element + each elements user data is an incrementing counter + + then run one thread per CPU + where each busy-works dequeuing + + when an element is dequeued, we check (on a per-thread basis) the + value deqeued is greater than the element previously dequeued + */ + + internal_display_test_name( "Dequeuing" ); + + cpu_count = abstraction_cpu_count(); + + lfds601_queue_new( &qs, 1000000 ); + + for( loop = 0 ; loop < 1000000 ; loop++ ) + lfds601_queue_enqueue( qs, (void *) (lfds601_atom_t) loop ); + + qtds = malloc( sizeof(struct queue_test_dequeuing_state) * cpu_count ); + + for( loop = 0 ; loop < cpu_count ; loop++ ) + { + (qtds+loop)->qs = qs; + (qtds+loop)->error_flag = LOWERED; + } + + thread_handles = malloc( sizeof(thread_state_t) * cpu_count ); + + for( loop = 0 ; loop < cpu_count ; loop++ ) + abstraction_thread_start( &thread_handles[loop], loop, queue_test_internal_thread_simple_dequeuer, qtds+loop ); + + for( loop = 0 ; loop < cpu_count ; loop++ ) + abstraction_thread_wait( thread_handles[loop] ); + + free( thread_handles ); + + // TRD : check queue is empty + lfds601_queue_query( qs, LFDS601_QUEUE_QUERY_VALIDATE, (void *) &vi, (void *) dvs ); + + // TRD : check for raised error flags + for( loop = 0 ; loop < cpu_count ; loop++ ) + if( (qtds+loop)->error_flag == RAISED ) + dvs[0] = LFDS601_VALIDITY_INVALID_TEST_DATA; + + free( qtds ); + + lfds601_queue_delete( qs, NULL, NULL ); + + internal_display_test_result( 2, "queue", dvs[0], "queue freelist", dvs[1] ); + + return; +} + + + + + +/****************************************************************************/ +thread_return_t CALLING_CONVENTION queue_test_internal_thread_simple_dequeuer( void *queue_test_dequeuing_state ) +{ + struct queue_test_dequeuing_state + *qtds; + + lfds601_atom_t + *prev_user_data, + *user_data; + + assert( queue_test_dequeuing_state != NULL ); + + qtds = (struct queue_test_dequeuing_state *) queue_test_dequeuing_state; + + lfds601_queue_dequeue( qtds->qs, (void *) &prev_user_data ); + + while( lfds601_queue_dequeue(qtds->qs, (void *) &user_data) ) + { + if( user_data <= prev_user_data ) + qtds->error_flag = RAISED; + + prev_user_data = user_data; + } + + return( (thread_return_t) EXIT_SUCCESS ); +} + + + + + +/****************************************************************************/ +void queue_test_enqueuing_and_dequeuing( void ) +{ + unsigned int + loop, + subloop, + cpu_count; + + thread_state_t + *thread_handles; + + struct lfds601_queue_state + *qs; + + struct queue_test_enqueuing_and_dequeuing_state + *qteds; + + struct lfds601_validation_info + vi = { 0, 0 }; + + enum lfds601_data_structure_validity + dvs[2]; + + internal_display_test_name( "Enqueuing and dequeuing (10 seconds)" ); + + cpu_count = abstraction_cpu_count(); + + lfds601_queue_new( &qs, cpu_count ); + + qteds = malloc( sizeof(struct queue_test_enqueuing_and_dequeuing_state) * cpu_count ); + + for( loop = 0 ; loop < cpu_count ; loop++ ) + { + (qteds+loop)->qs = qs; + (qteds+loop)->thread_number = loop; + (qteds+loop)->counter = (lfds601_atom_t) loop << (sizeof(lfds601_atom_t)*8-8); + (qteds+loop)->cpu_count = cpu_count; + (qteds+loop)->error_flag = LOWERED; + (qteds+loop)->per_thread_counters = malloc( sizeof(lfds601_atom_t) * cpu_count ); + + for( subloop = 0 ; subloop < cpu_count ; subloop++ ) + *((qteds+loop)->per_thread_counters+subloop) = 0; + } + + thread_handles = malloc( sizeof(thread_state_t) * cpu_count ); + + for( loop = 0 ; loop < cpu_count ; loop++ ) + abstraction_thread_start( &thread_handles[loop], loop, queue_test_internal_thread_enqueuer_and_dequeuer, qteds+loop ); + + for( loop = 0 ; loop < cpu_count ; loop++ ) + abstraction_thread_wait( thread_handles[loop] ); + + free( thread_handles ); + + lfds601_queue_query( qs, LFDS601_QUEUE_QUERY_VALIDATE, (void *) &vi, (void *) dvs ); + + for( loop = 0 ; loop < cpu_count ; loop++ ) + if( (qteds+loop)->error_flag == RAISED ) + dvs[0] = LFDS601_VALIDITY_INVALID_TEST_DATA; + + for( loop = 0 ; loop < cpu_count ; loop++ ) + free( (qteds+loop)->per_thread_counters ); + + free( qteds ); + + lfds601_queue_delete( qs, NULL, NULL ); + + internal_display_test_result( 2, "queue", dvs[0], "queue freelist", dvs[1] ); + + return; +} + + + + + +/****************************************************************************/ +thread_return_t CALLING_CONVENTION queue_test_internal_thread_enqueuer_and_dequeuer( void *queue_test_enqueuing_and_dequeuing_state ) +{ + struct queue_test_enqueuing_and_dequeuing_state + *qteds; + + time_t + start_time; + + lfds601_atom_t + thread, + count, + user_data; + + assert( queue_test_enqueuing_and_dequeuing_state != NULL ); + + qteds = (struct queue_test_enqueuing_and_dequeuing_state *) queue_test_enqueuing_and_dequeuing_state; + + time( &start_time ); + + while( time(NULL) < start_time + 10 ) + { + lfds601_queue_enqueue( qteds->qs, (void *) (qteds->counter++) ); + lfds601_queue_dequeue( qteds->qs, (void *) &user_data ); + + thread = user_data >> (sizeof(lfds601_atom_t)*8-8); + count = (user_data << 8) >> 8; + + if( thread >= qteds->cpu_count ) + qteds->error_flag = RAISED; + else + { + if( count < qteds->per_thread_counters[thread] ) + qteds->error_flag = RAISED; + + if( count >= qteds->per_thread_counters[thread] ) + qteds->per_thread_counters[thread] = count+1; + } + } + + return( (thread_return_t) EXIT_SUCCESS ); +} + + + + + +/****************************************************************************/ +void queue_test_rapid_enqueuing_and_dequeuing( void ) +{ + unsigned int + loop, + cpu_count; + + thread_state_t + *thread_handles; + + struct lfds601_queue_state + *qs; + + struct queue_test_rapid_enqueuing_and_dequeuing_state + *qtreds; + + struct lfds601_validation_info + vi = { 50000, 50000 }; + + lfds601_atom_t + user_data, + thread, + count, + *per_thread_counters; + + enum lfds601_data_structure_validity + dvs[2]; + + internal_display_test_name( "Rapid enqueuing and dequeuing (10 seconds)" ); + + cpu_count = abstraction_cpu_count(); + + lfds601_queue_new( &qs, 100000 ); + + for( loop = 0 ; loop < 50000 ; loop++ ) + lfds601_queue_enqueue( qs, NULL ); + + qtreds = malloc( sizeof(struct queue_test_rapid_enqueuing_and_dequeuing_state) * cpu_count ); + + for( loop = 0 ; loop < cpu_count ; loop++ ) + { + (qtreds+loop)->qs = qs; + (qtreds+loop)->counter = (lfds601_atom_t) loop << (sizeof(lfds601_atom_t)*8-8); + } + + thread_handles = malloc( sizeof(thread_state_t) * cpu_count ); + + for( loop = 0 ; loop < cpu_count ; loop++ ) + abstraction_thread_start( &thread_handles[loop], loop, queue_test_internal_thread_rapid_enqueuer_and_dequeuer, qtreds+loop ); + + for( loop = 0 ; loop < cpu_count ; loop++ ) + abstraction_thread_wait( thread_handles[loop] ); + + free( thread_handles ); + + lfds601_queue_query( qs, LFDS601_QUEUE_QUERY_VALIDATE, (void *) &vi, (void *) dvs ); + + // TRD : now check results + per_thread_counters = malloc( sizeof(lfds601_atom_t) * cpu_count ); + + for( loop = 0 ; loop < cpu_count ; loop++ ) + *(per_thread_counters+loop) = 0; + + while( dvs[0] == LFDS601_VALIDITY_VALID and dvs[1] == LFDS601_VALIDITY_VALID and lfds601_queue_dequeue(qs, (void *) &user_data) ) + { + thread = user_data >> (sizeof(lfds601_atom_t)*8-8); + count = (user_data << 8) >> 8; + + if( thread >= cpu_count ) + { + dvs[0] = LFDS601_VALIDITY_INVALID_TEST_DATA; + break; + } + + if( per_thread_counters[thread] == 0 ) + per_thread_counters[thread] = count; + + if( count < per_thread_counters[thread] ) + dvs[0] = LFDS601_VALIDITY_INVALID_ADDITIONAL_ELEMENTS; + + if( count >= per_thread_counters[thread] ) + per_thread_counters[thread] = count+1; + } + + free( per_thread_counters ); + + free( qtreds ); + + lfds601_queue_delete( qs, NULL, NULL ); + + internal_display_test_result( 2, "queue", dvs[0], "queue freelist", dvs[1] ); + + return; +} + + + + + +/****************************************************************************/ +thread_return_t CALLING_CONVENTION queue_test_internal_thread_rapid_enqueuer_and_dequeuer( void *queue_test_rapid_enqueuing_and_dequeuing_state ) +{ + struct queue_test_rapid_enqueuing_and_dequeuing_state + *qtreds; + + time_t + start_time; + + lfds601_atom_t + user_data; + + assert( queue_test_rapid_enqueuing_and_dequeuing_state != NULL ); + + qtreds = (struct queue_test_rapid_enqueuing_and_dequeuing_state *) queue_test_rapid_enqueuing_and_dequeuing_state; + + time( &start_time ); + + while( time(NULL) < start_time + 10 ) + { + lfds601_queue_enqueue( qtreds->qs, (void *) (qtreds->counter++) ); + lfds601_queue_dequeue( qtreds->qs, (void *) &user_data ); + } + + return( (thread_return_t) EXIT_SUCCESS ); +} + diff --git a/liblfds/liblfds6.0.1/test/src/test_ringbuffer.c b/liblfds/liblfds6.0.1/test/src/test_ringbuffer.c new file mode 100644 index 0000000..565f3c2 --- /dev/null +++ b/liblfds/liblfds6.0.1/test/src/test_ringbuffer.c @@ -0,0 +1,467 @@ +#include "internal.h" + + + + + +/****************************************************************************/ +void test_lfds601_ringbuffer( void ) +{ + printf( "\n" + "Ringbuffer Tests\n" + "================\n" ); + + ringbuffer_test_reading(); + ringbuffer_test_writing(); + ringbuffer_test_reading_and_writing(); + + return; +} + + + + + +/****************************************************************************/ +void ringbuffer_test_reading( void ) +{ + unsigned int + loop, + cpu_count; + + thread_state_t + *thread_handles; + + struct lfds601_ringbuffer_state + *rs; + + struct lfds601_freelist_element + *fe; + + struct ringbuffer_test_reading_state + *rtrs; + + struct lfds601_validation_info + vi = { 0, 0 }; + + enum lfds601_data_structure_validity + dvs[3]; + + lfds601_atom_t + total_read = 0; + + /* TRD : we create a single ringbuffer + with 1,000,000 elements + we populate the ringbuffer, where the + user data is an incrementing counter + + we create one thread per CPU + where each thread busy-works, + reading until the ringbuffer is empty + + each thread keep track of the number of reads it manages + and that each user data it reads is greater than the + previous user data that was read + */ + + internal_display_test_name( "Reading" ); + + cpu_count = abstraction_cpu_count(); + + lfds601_ringbuffer_new( &rs, 1000000, NULL, NULL ); + + for( loop = 0 ; loop < 1000000 ; loop++ ) + { + lfds601_ringbuffer_get_write_element( rs, &fe, NULL ); + lfds601_freelist_set_user_data_in_element( fe, (void *) (lfds601_atom_t) loop ); + lfds601_ringbuffer_put_write_element( rs, fe ); + } + + rtrs = malloc( sizeof(struct ringbuffer_test_reading_state) * cpu_count ); + + for( loop = 0 ; loop < cpu_count ; loop++ ) + { + (rtrs+loop)->rs = rs; + (rtrs+loop)->read_count = 0; + (rtrs+loop)->error_flag = LOWERED; + } + + thread_handles = malloc( sizeof(thread_state_t) * cpu_count ); + + for( loop = 0 ; loop < cpu_count ; loop++ ) + abstraction_thread_start( &thread_handles[loop], loop, ringbuffer_test_thread_simple_reader, rtrs+loop ); + + for( loop = 0 ; loop < cpu_count ; loop++ ) + abstraction_thread_wait( thread_handles[loop] ); + + free( thread_handles ); + + lfds601_ringbuffer_query( rs, LFDS601_RINGBUFFER_QUERY_VALIDATE, (void *) &vi, (void *) dvs ); + + // TRD : check for raised error flags + for( loop = 0 ; loop < cpu_count ; loop++ ) + if( (rtrs+loop)->error_flag == RAISED ) + dvs[0] = LFDS601_VALIDITY_INVALID_TEST_DATA; + + // TRD : check thread reads total to 1,000,000 + for( loop = 0 ; loop < cpu_count ; loop++ ) + total_read += (rtrs+loop)->read_count; + + if( total_read < 1000000 ) + dvs[0] = LFDS601_VALIDITY_INVALID_MISSING_ELEMENTS; + + if( total_read > 1000000 ) + dvs[0] = LFDS601_VALIDITY_INVALID_ADDITIONAL_ELEMENTS; + + free( rtrs ); + + lfds601_ringbuffer_delete( rs, NULL, NULL ); + + internal_display_test_result( 3, "queue", dvs[0], "queue freelist", dvs[1], "freelist", dvs[2] ); + + return; +} + + + + + +/****************************************************************************/ +thread_return_t CALLING_CONVENTION ringbuffer_test_thread_simple_reader( void *ringbuffer_test_reading_state ) +{ + struct ringbuffer_test_reading_state + *rtrs; + + struct lfds601_freelist_element + *fe; + + lfds601_atom_t + *prev_user_data, + *user_data; + + assert( ringbuffer_test_reading_state != NULL ); + + rtrs = (struct ringbuffer_test_reading_state *) ringbuffer_test_reading_state; + + lfds601_ringbuffer_get_read_element( rtrs->rs, &fe ); + lfds601_freelist_get_user_data_from_element( fe, (void **) &prev_user_data ); + lfds601_ringbuffer_put_read_element( rtrs->rs, fe ); + + rtrs->read_count++; + + while( lfds601_ringbuffer_get_read_element(rtrs->rs, &fe) ) + { + lfds601_freelist_get_user_data_from_element( fe, (void **) &user_data ); + lfds601_ringbuffer_put_read_element( rtrs->rs, fe ); + + if( user_data <= prev_user_data ) + rtrs->error_flag = RAISED; + + prev_user_data = user_data; + + rtrs->read_count++; + } + + return( (thread_return_t) EXIT_SUCCESS ); +} + + + + + +/****************************************************************************/ +void ringbuffer_test_writing( void ) +{ + unsigned int + loop, + cpu_count; + + thread_state_t + *thread_handles; + + struct lfds601_ringbuffer_state + *rs; + + struct lfds601_freelist_element + *fe; + + struct ringbuffer_test_writing_state + *rtws; + + struct lfds601_validation_info + vi = { 100000, 100000 }; + + enum lfds601_data_structure_validity + dvs[3]; + + lfds601_atom_t + thread, + count, + user_data, + *per_thread_counters; + + /* TRD : we create a single ringbuffer + with 100000 elements + the ringbuffers starts empty + + we create one thread per CPU + where each thread busy-works writing + for ten seconds + + the user data in each written element is a combination + of the thread number and the counter + + after the threads are complete, we validate by + checking the user data counters increment on a per thread + basis + */ + + internal_display_test_name( "Writing (10 seconds)" ); + + cpu_count = abstraction_cpu_count(); + + lfds601_ringbuffer_new( &rs, 100000, NULL, NULL ); + + rtws = malloc( sizeof(struct ringbuffer_test_writing_state) * cpu_count ); + + for( loop = 0 ; loop < cpu_count ; loop++ ) + { + (rtws+loop)->rs = rs; + (rtws+loop)->write_count = (lfds601_atom_t) loop << (sizeof(lfds601_atom_t)*8-8); + } + + thread_handles = malloc( sizeof(thread_state_t) * cpu_count ); + + for( loop = 0 ; loop < cpu_count ; loop++ ) + abstraction_thread_start( &thread_handles[loop], loop, ringbuffer_test_thread_simple_writer, rtws+loop ); + + for( loop = 0 ; loop < cpu_count ; loop++ ) + abstraction_thread_wait( thread_handles[loop] ); + + free( thread_handles ); + + // TRD : now check results + per_thread_counters = malloc( sizeof(lfds601_atom_t) * cpu_count ); + + for( loop = 0 ; loop < cpu_count ; loop++ ) + *(per_thread_counters+loop) = 0; + + lfds601_ringbuffer_query( rs, LFDS601_RINGBUFFER_QUERY_VALIDATE, (void *) &vi, (void *) dvs ); + + while( dvs[0] == LFDS601_VALIDITY_VALID and dvs[1] == LFDS601_VALIDITY_VALID and dvs[2] == LFDS601_VALIDITY_VALID and lfds601_ringbuffer_get_read_element(rs, &fe) ) + { + lfds601_freelist_get_user_data_from_element( fe, (void *) &user_data ); + + thread = user_data >> (sizeof(lfds601_atom_t)*8-8); + count = (user_data << 8) >> 8; + + if( thread >= cpu_count ) + { + dvs[0] = LFDS601_VALIDITY_INVALID_TEST_DATA; + lfds601_ringbuffer_put_read_element( rs, fe ); + break; + } + + if( per_thread_counters[thread] == 0 ) + per_thread_counters[thread] = count; + + if( count < per_thread_counters[thread] ) + dvs[0] = LFDS601_VALIDITY_INVALID_ADDITIONAL_ELEMENTS; + + if( count >= per_thread_counters[thread] ) + per_thread_counters[thread] = count+1; + + lfds601_ringbuffer_put_read_element( rs, fe ); + } + + free( per_thread_counters ); + + free( rtws ); + + lfds601_ringbuffer_delete( rs, NULL, NULL ); + + internal_display_test_result( 3, "queue", dvs[0], "queue freelist", dvs[1], "freelist", dvs[2] ); + + return; +} + + + + + +/****************************************************************************/ +thread_return_t CALLING_CONVENTION ringbuffer_test_thread_simple_writer( void *ringbuffer_test_writing_state ) +{ + struct ringbuffer_test_writing_state + *rtws; + + struct lfds601_freelist_element + *fe; + + time_t + start_time; + + assert( ringbuffer_test_writing_state != NULL ); + + rtws = (struct ringbuffer_test_writing_state *) ringbuffer_test_writing_state; + + time( &start_time ); + + while( time(NULL) < start_time + 10 ) + { + lfds601_ringbuffer_get_write_element( rtws->rs, &fe, NULL ); + lfds601_freelist_set_user_data_in_element( fe, (void *) (lfds601_atom_t) (rtws->write_count++) ); + lfds601_ringbuffer_put_write_element( rtws->rs, fe ); + } + + return( (thread_return_t) EXIT_SUCCESS ); +} + + + + + +/****************************************************************************/ +void ringbuffer_test_reading_and_writing( void ) +{ + unsigned int + loop, + subloop, + cpu_count; + + thread_state_t + *thread_handles; + + struct lfds601_ringbuffer_state + *rs; + + struct ringbuffer_test_reading_and_writing_state + *rtrws; + + struct lfds601_validation_info + vi = { 0, 0 }; + + enum lfds601_data_structure_validity + dvs[3]; + + /* TRD : we create a single ringbuffer + with 100000 elements + the ringbuffers starts empty + + we create one thread per CPU + where each thread busy-works writing + and then immediately reading + for ten seconds + + the user data in each written element is a combination + of the thread number and the counter + + while a thread runs, it keeps track of the + counters for the other threads and throws an error + if it sees the number stay the same or decrease + */ + + internal_display_test_name( "Reading and writing (10 seconds)" ); + + cpu_count = abstraction_cpu_count(); + + lfds601_ringbuffer_new( &rs, 100000, NULL, NULL ); + + rtrws = malloc( sizeof(struct ringbuffer_test_reading_and_writing_state) * cpu_count ); + + for( loop = 0 ; loop < cpu_count ; loop++ ) + { + (rtrws+loop)->rs = rs; + (rtrws+loop)->counter = (lfds601_atom_t) loop << (sizeof(lfds601_atom_t)*8-8); + (rtrws+loop)->cpu_count = cpu_count; + (rtrws+loop)->error_flag = LOWERED; + (rtrws+loop)->per_thread_counters = malloc( sizeof(lfds601_atom_t) * cpu_count ); + + for( subloop = 0 ; subloop < cpu_count ; subloop++ ) + *((rtrws+loop)->per_thread_counters+subloop) = 0; + } + + thread_handles = malloc( sizeof(thread_state_t) * cpu_count ); + + for( loop = 0 ; loop < cpu_count ; loop++ ) + abstraction_thread_start( &thread_handles[loop], loop, ringbuffer_test_thread_reader_writer, rtrws+loop ); + + for( loop = 0 ; loop < cpu_count ; loop++ ) + abstraction_thread_wait( thread_handles[loop] ); + + free( thread_handles ); + + lfds601_ringbuffer_query( rs, LFDS601_RINGBUFFER_QUERY_VALIDATE, (void *) &vi, (void *) dvs ); + + for( loop = 0 ; loop < cpu_count ; loop++ ) + if( (rtrws+loop)->error_flag == RAISED ) + dvs[0] = LFDS601_VALIDITY_INVALID_TEST_DATA; + + for( loop = 0 ; loop < cpu_count ; loop++ ) + free( (rtrws+loop)->per_thread_counters ); + + free( rtrws ); + + lfds601_ringbuffer_delete( rs, NULL, NULL ); + + internal_display_test_result( 3, "queue", dvs[0], "queue freelist", dvs[1], "freelist", dvs[2] ); + + return; +} + + + + + +/****************************************************************************/ +thread_return_t CALLING_CONVENTION ringbuffer_test_thread_reader_writer( void *ringbuffer_test_reading_and_writing_state ) +{ + struct ringbuffer_test_reading_and_writing_state + *rtrws; + + struct lfds601_freelist_element + *fe; + + lfds601_atom_t + user_data, + thread, + count; + + time_t + start_time; + + assert( ringbuffer_test_reading_and_writing_state != NULL ); + + rtrws = (struct ringbuffer_test_reading_and_writing_state *) ringbuffer_test_reading_and_writing_state; + + time( &start_time ); + + while( time(NULL) < start_time + 10 ) + { + lfds601_ringbuffer_get_write_element( rtrws->rs, &fe, NULL ); + lfds601_freelist_set_user_data_in_element( fe, (void *) (lfds601_atom_t) (rtrws->counter++) ); + lfds601_ringbuffer_put_write_element( rtrws->rs, fe ); + + lfds601_ringbuffer_get_read_element( rtrws->rs, &fe ); + lfds601_freelist_get_user_data_from_element( fe, (void *) &user_data ); + + thread = user_data >> (sizeof(lfds601_atom_t)*8-8); + count = (user_data << 8) >> 8; + + if( thread >= rtrws->cpu_count ) + rtrws->error_flag = RAISED; + else + { + if( count < rtrws->per_thread_counters[thread] ) + rtrws->error_flag = RAISED; + + if( count >= rtrws->per_thread_counters[thread] ) + rtrws->per_thread_counters[thread] = count+1; + } + + lfds601_ringbuffer_put_read_element( rtrws->rs, fe ); + } + + return( (thread_return_t) EXIT_SUCCESS ); +} + diff --git a/liblfds/liblfds6.0.1/test/src/test_slist.c b/liblfds/liblfds6.0.1/test/src/test_slist.c new file mode 100644 index 0000000..b2c21b4 --- /dev/null +++ b/liblfds/liblfds6.0.1/test/src/test_slist.c @@ -0,0 +1,513 @@ +#include "internal.h" + + + + + +/****************************************************************************/ +void test_lfds601_slist( void ) +{ + unsigned int + loop, + cpu_count; + + thread_state_t + *thread_handles; + + struct lfds601_slist_thread_start_state + stss; + + /* TRD : 1. one head writer per CPU + 2. make one element, then one after writer per CPU + 3. make a list, then one list traverser per CPU + 4. one head writer and one list traverser per CPU + 5. make one element, then one after writer and one list traverser per CPU + 6. make a list, then one 100% deleter-traverser per CPU + 7. make a list, then one 25% deleter-traverser per CPU + 8. one head writer and one 100% deleter-traverse per CPU + 9. one head writer and one 25% deleter-traverse per CPU + 10. make one element, then one after writer and one 100% deleter-traverser per CPU + 11. make one element, then one after writer and one 25% deleter-traverser per CPU + 12. one head writer, one after writer, one traverser and one 25% deleter-traverser per CPU + */ + + cpu_count = abstraction_cpu_count(); + + printf( "\n" + "SList Test\n" + "==========\n" ); + + // TRD : 1. one head writer per CPU + + printf( "\n" + "1. one head writer per CPU\n" + "==========================\n" ); + + lfds601_slist_new( &stss.ss, NULL, NULL ); + stss.iteration_modulo = 1; + stss.se = NULL; + stss.duration = 1; + + thread_handles = (thread_state_t *) malloc( sizeof(thread_state_t) * cpu_count * 1 ); + + for( loop = 0 ; loop < cpu_count ; loop++ ) + abstraction_thread_start( &thread_handles[loop], loop, lfds601_slist_internal_thread_head_writer, &stss ); + + for( loop = 0 ; loop < cpu_count ; loop++ ) + abstraction_thread_wait( thread_handles[loop] ); + + lfds601_slist_delete( stss.ss ); + + free( thread_handles ); + + // TRD : 2. make one element, then one after writer per CPU + + printf( "\n" + "2. make one element, then one after writer per CPU\n" + "==================================================\n" ); + + lfds601_slist_new( &stss.ss, NULL, NULL ); + stss.iteration_modulo = 1; + stss.se = lfds601_slist_new_head( stss.ss, (void *) NULL ); + stss.duration = 1; + + thread_handles = (thread_state_t *) malloc( sizeof(thread_state_t) * cpu_count * 1 ); + + for( loop = 0 ; loop < cpu_count ; loop++ ) + abstraction_thread_start( &thread_handles[loop], loop, lfds601_slist_internal_thread_after_writer, &stss ); + + for( loop = 0 ; loop < cpu_count ; loop++ ) + abstraction_thread_wait( thread_handles[loop] ); + + lfds601_slist_delete( stss.ss ); + + free( thread_handles ); + + // TRD : 3. make a list, then one list traverser per CPU + + printf( "\n" + "3. make a list, then one list traverser per CPU\n" + "===============================================\n" ); + + lfds601_slist_new( &stss.ss, NULL, NULL ); + stss.iteration_modulo = 1; + stss.se = NULL; + stss.duration = 10; + + // TRD : small list so we get collisions + for( loop = 0 ; loop < 10 ; loop++ ) + lfds601_slist_new_head( stss.ss, (void *) 0 ); + + thread_handles = (thread_state_t *) malloc( sizeof(thread_state_t) * cpu_count * 1 ); + + for( loop = 0 ; loop < cpu_count ; loop++ ) + abstraction_thread_start( &thread_handles[loop], loop, lfds601_slist_internal_thread_traverser, &stss ); + + for( loop = 0 ; loop < cpu_count ; loop++ ) + abstraction_thread_wait( thread_handles[loop] ); + + lfds601_slist_delete( stss.ss ); + + free( thread_handles ); + + // TRD : 4. one head writer and one list traverser per CPU + + printf( "\n" + "4. one head writer and one list traverser per CPU\n" + "=================================================\n" ); + + lfds601_slist_new( &stss.ss, NULL, NULL ); + stss.iteration_modulo = 1; + stss.se = NULL; + stss.duration = 1; + + thread_handles = (thread_state_t *) malloc( sizeof(thread_state_t) * cpu_count * 2 ); + + for( loop = 0 ; loop < cpu_count ; loop++ )\ + { + abstraction_thread_start( &thread_handles[loop], loop, lfds601_slist_internal_thread_head_writer, &stss ); + abstraction_thread_start( &thread_handles[loop+cpu_count], loop, lfds601_slist_internal_thread_traverser, &stss ); + } + + for( loop = 0 ; loop < cpu_count * 2 ; loop++ ) + abstraction_thread_wait( thread_handles[loop] ); + + lfds601_slist_delete( stss.ss ); + + free( thread_handles ); + + // TRD : 5. make one element, then one after writer and one list traverser per CPU + + printf( "\n" + "5. make one element, then one after writer and one list traverser per CPU\n" + "=========================================================================\n" ); + + lfds601_slist_new( &stss.ss, NULL, NULL ); + stss.iteration_modulo = 1; + stss.se = lfds601_slist_new_head( stss.ss, (void *) NULL ); + stss.duration = 1; + + thread_handles = (thread_state_t *) malloc( sizeof(thread_state_t) * cpu_count * 2 ); + + for( loop = 0 ; loop < cpu_count ; loop++ )\ + { + abstraction_thread_start( &thread_handles[loop], loop, lfds601_slist_internal_thread_after_writer, &stss ); + abstraction_thread_start( &thread_handles[loop+cpu_count], loop, lfds601_slist_internal_thread_traverser, &stss ); + } + + for( loop = 0 ; loop < cpu_count * 2 ; loop++ ) + abstraction_thread_wait( thread_handles[loop] ); + + lfds601_slist_delete( stss.ss ); + + free( thread_handles ); + + // TRD : 6. make a list, then one 100% deleter-traverser per CPU + + printf( "\n" + "6. make a list, then one 100%% deleter-traverser per CPU\n" + "=======================================================\n" ); + + lfds601_slist_new( &stss.ss, NULL, NULL ); + stss.iteration_modulo = 1; + stss.se = NULL; + stss.duration = 1; + + for( loop = 0 ; loop < 10000 ; loop++ ) + lfds601_slist_new_head( stss.ss, (void *) 0 ); + + thread_handles = (thread_state_t *) malloc( sizeof(thread_state_t) * cpu_count * 1 ); + + for( loop = 0 ; loop < cpu_count ; loop++ ) + abstraction_thread_start( &thread_handles[loop], loop, lfds601_slist_internal_thread_deleter_traverser, &stss ); + + for( loop = 0 ; loop < cpu_count ; loop++ ) + abstraction_thread_wait( thread_handles[loop] ); + + lfds601_slist_delete( stss.ss ); + + free( thread_handles ); + + // TRD : 7. make a list, then one 25% deleter-traverser per CPU + + printf( "\n" + "7. make a list, then one 25%% deleter-traverser per CPU\n" + "======================================================\n" ); + + lfds601_slist_new( &stss.ss, NULL, NULL ); + stss.iteration_modulo = 4; + stss.se = NULL; + stss.duration = 1; + + for( loop = 0 ; loop < 10000 ; loop++ ) + lfds601_slist_new_head( stss.ss, (void *) 0 ); + + thread_handles = (thread_state_t *) malloc( sizeof(thread_state_t) * cpu_count * 1 ); + + for( loop = 0 ; loop < cpu_count ; loop++ ) + abstraction_thread_start( &thread_handles[loop], loop, lfds601_slist_internal_thread_deleter_traverser, &stss ); + + for( loop = 0 ; loop < cpu_count ; loop++ ) + abstraction_thread_wait( thread_handles[loop] ); + + lfds601_slist_delete( stss.ss ); + + free( thread_handles ); + + // TRD : 8. one head writer and one 100% deleter-traverse per CPU + + printf( "\n" + "8. one head writer and one 100%% deleter-traverse per CPU\n" + "========================================================\n" ); + + lfds601_slist_new( &stss.ss, NULL, NULL ); + stss.iteration_modulo = 1; + stss.se = NULL; + stss.duration = 10; + + thread_handles = (thread_state_t *) malloc( sizeof(thread_state_t) * cpu_count * 2 ); + + for( loop = 0 ; loop < cpu_count ; loop++ ) + { + abstraction_thread_start( &thread_handles[loop], loop, lfds601_slist_internal_thread_head_writer, &stss ); + abstraction_thread_start( &thread_handles[loop+cpu_count], loop, lfds601_slist_internal_thread_deleter_traverser, &stss ); + } + + for( loop = 0 ; loop < cpu_count * 2 ; loop++ ) + abstraction_thread_wait( thread_handles[loop] ); + + lfds601_slist_delete( stss.ss ); + + free( thread_handles ); + + // TRD : 9. one head writer and one 25% deleter-traverse per CPU + + printf( "\n" + "9. one head writer and one 25%% deleter-traverse per CPU\n" + "=======================================================\n" ); + + lfds601_slist_new( &stss.ss, NULL, NULL ); + stss.iteration_modulo = 4; + stss.se = NULL; + stss.duration = 1; + + thread_handles = (thread_state_t *) malloc( sizeof(thread_state_t) * cpu_count * 2 ); + + for( loop = 0 ; loop < cpu_count ; loop++ ) + { + abstraction_thread_start( &thread_handles[loop], loop, lfds601_slist_internal_thread_head_writer, &stss ); + abstraction_thread_start( &thread_handles[loop+cpu_count], loop, lfds601_slist_internal_thread_deleter_traverser, &stss ); + } + + for( loop = 0 ; loop < cpu_count * 2 ; loop++ ) + abstraction_thread_wait( thread_handles[loop] ); + + lfds601_slist_delete( stss.ss ); + + free( thread_handles ); + + // TRD : 10. make one element, then one after writer and one 100% deleter-traverser per CPU + + printf( "\n" + "10. make one element, then one after writer and one 100%% deleter-traverser per CPU\n" + "==================================================================================\n" ); + + lfds601_slist_new( &stss.ss, NULL, NULL ); + stss.iteration_modulo = 1; + stss.se = lfds601_slist_new_head( stss.ss, (void *) NULL ); + stss.duration = 10; + + thread_handles = (thread_state_t *) malloc( sizeof(thread_state_t) * cpu_count * 2 ); + + for( loop = 0 ; loop < cpu_count ; loop++ ) + { + abstraction_thread_start( &thread_handles[loop], loop, lfds601_slist_internal_thread_after_writer, &stss ); + abstraction_thread_start( &thread_handles[loop+cpu_count], loop, lfds601_slist_internal_thread_deleter_traverser, &stss ); + } + + for( loop = 0 ; loop < cpu_count * 2 ; loop++ ) + abstraction_thread_wait( thread_handles[loop] ); + + lfds601_slist_delete( stss.ss ); + + free( thread_handles ); + + // TRD : 11. make one element, then one after writer and one 25% deleter-traverser per CPU + + printf( "\n" + "11. make one element, then one after writer and one 25%% deleter-traverser per CPU\n" + "=================================================================================\n" ); + + lfds601_slist_new( &stss.ss, NULL, NULL ); + stss.iteration_modulo = 4; + stss.se = lfds601_slist_new_head( stss.ss, (void *) NULL ); + stss.duration = 1; + + thread_handles = (thread_state_t *) malloc( sizeof(thread_state_t) * cpu_count * 2 ); + + for( loop = 0 ; loop < cpu_count ; loop++ ) + { + abstraction_thread_start( &thread_handles[loop], loop, lfds601_slist_internal_thread_after_writer, &stss ); + abstraction_thread_start( &thread_handles[loop+cpu_count], loop, lfds601_slist_internal_thread_deleter_traverser, &stss ); + } + + for( loop = 0 ; loop < cpu_count * 2 ; loop++ ) + abstraction_thread_wait( thread_handles[loop] ); + + lfds601_slist_delete( stss.ss ); + + free( thread_handles ); + + // TRD : 12. one head writer, one after writer, one traverser and one 25% deleter-traverser per CPU + + printf( "\n" + "12. one head writer, one after writer, one traverser and one 25%% deleter-traverser per CPU\n" + "==========================================================================================\n" ); + + lfds601_slist_new( &stss.ss, NULL, NULL ); + stss.iteration_modulo = 4; + stss.se = lfds601_slist_new_head( stss.ss, (void *) NULL ); + stss.duration = 1; + + thread_handles = (thread_state_t *) malloc( sizeof(thread_state_t) * cpu_count * 4 ); + + for( loop = 0 ; loop < cpu_count ; loop++ ) + { + abstraction_thread_start( &thread_handles[loop], loop, lfds601_slist_internal_thread_head_writer, &stss ); + abstraction_thread_start( &thread_handles[loop+cpu_count], loop, lfds601_slist_internal_thread_after_writer, &stss ); + abstraction_thread_start( &thread_handles[loop+cpu_count*2], loop, lfds601_slist_internal_thread_traverser, &stss ); + abstraction_thread_start( &thread_handles[loop+cpu_count*3], loop, lfds601_slist_internal_thread_deleter_traverser, &stss ); + } + + for( loop = 0 ; loop < cpu_count * 4 ; loop++ ) + abstraction_thread_wait( thread_handles[loop] ); + + lfds601_slist_delete( stss.ss ); + + free( thread_handles ); + + return; +} + + + + + +/****************************************************************************/ +thread_return_t CALLING_CONVENTION lfds601_slist_internal_thread_head_writer( void *lfds601_slist_thread_start_state ) +{ + struct lfds601_slist_thread_start_state + *stss; + + time_t + start_time; + + unsigned long int + count = 0; + + assert( lfds601_slist_thread_start_state != NULL ); + + stss = (struct lfds601_slist_thread_start_state *) lfds601_slist_thread_start_state; + + time( &start_time ); + + while( time(NULL) < start_time + stss->duration ) + if( lfds601_slist_new_head(stss->ss, (void *) 0) ) + count++; + + printf( "head writer count = %lu\n", count ); + + return( (thread_return_t) EXIT_SUCCESS ); +} + + + + + +/****************************************************************************/ +thread_return_t CALLING_CONVENTION lfds601_slist_internal_thread_after_writer( void *lfds601_slist_thread_start_state ) +{ + struct lfds601_slist_thread_start_state + *stss; + + time_t + start_time; + + unsigned long int + count = 0; + + assert( lfds601_slist_thread_start_state != NULL ); + + stss = (struct lfds601_slist_thread_start_state *) lfds601_slist_thread_start_state; + + time( &start_time ); + + while( time(NULL) < start_time + stss->duration ) + if( lfds601_slist_new_next(stss->se, (void *) 0) ) + count++; + + printf( "after writer count = %lu\n", count ); + + return( (thread_return_t) EXIT_SUCCESS ); +} + + + + + +/****************************************************************************/ +thread_return_t CALLING_CONVENTION lfds601_slist_internal_thread_traverser( void *lfds601_slist_thread_start_state ) +{ + struct lfds601_slist_thread_start_state + *stss; + + time_t + start_time; + + unsigned long int + count = 0, + iteration = 0; + + struct lfds601_slist_element + *se; + + assert( lfds601_slist_thread_start_state != NULL ); + + stss = (struct lfds601_slist_thread_start_state *) lfds601_slist_thread_start_state; + + time( &start_time ); + + lfds601_slist_get_head( stss->ss, &se ); + + while( time(NULL) < start_time + stss->duration ) + { + if( !(iteration % stss->iteration_modulo) ) + { + lfds601_slist_get_next( se, &se ); + count++; + } + + if( se == NULL ) + { + lfds601_slist_get_head( stss->ss, &se ); + count++; + } + + iteration++; + } + + printf( "traverser count = %lu\n", count ); + + return( (thread_return_t) EXIT_SUCCESS ); +} + + + + + +/****************************************************************************/ +thread_return_t CALLING_CONVENTION lfds601_slist_internal_thread_deleter_traverser( void *lfds601_slist_thread_start_state ) +{ + struct lfds601_slist_thread_start_state + *stss; + + time_t + start_time; + + unsigned long int + count = 0, + iteration = 0; + + struct lfds601_slist_element + *se; + + assert( lfds601_slist_thread_start_state != NULL ); + + stss = (struct lfds601_slist_thread_start_state *) lfds601_slist_thread_start_state; + + time( &start_time ); + + lfds601_slist_get_head( stss->ss, &se ); + + while( time(NULL) < start_time + stss->duration ) + { + if( se != NULL and !(iteration % stss->iteration_modulo) ) + { + lfds601_slist_delete_element( stss->ss, se ); + count++; + } + + if( se != NULL ) + lfds601_slist_get_next( se, &se ); + + if( se == NULL ) + lfds601_slist_get_head( stss->ss, &se ); + + iteration++; + } + + printf( "deleter-traverser count = %lu\n", count ); + + return( (thread_return_t) EXIT_SUCCESS ); +} + diff --git a/liblfds/liblfds6.0.1/test/src/test_stack.c b/liblfds/liblfds6.0.1/test/src/test_stack.c new file mode 100644 index 0000000..8162493 --- /dev/null +++ b/liblfds/liblfds6.0.1/test/src/test_stack.c @@ -0,0 +1,223 @@ +#include "internal.h" + + + + + +/****************************************************************************/ +void test_lfds601_stack( void ) +{ + unsigned int + loop, + cpu_count; + + struct lfds601_stack_state + *ss; + + thread_state_t + *thread_handles; + + /* TRD : there are 5 tests + + 1. single reader thread per CPU + - stack always empty + 2. single writer thread per CPU + - stack always full + 3. one reader and one writer thread per CPU + - stack balanced + 4. one reader and two writer threads per CPU + - stack grows + 5. two reader and one writer thread per CPU + - stack tends to empty + */ + + cpu_count = abstraction_cpu_count(); + + printf( "\n" + "Stack Test\n" + "==========\n" ); + + // TRD : 1. single reader thread per CPU + + printf( "\n" + "1. single reader thread per CPU\n" + "===============================\n" ); + + lfds601_stack_new( &ss, 10000 ); + + thread_handles = (thread_state_t *) malloc( sizeof(thread_state_t) * cpu_count * 1 ); + + for( loop = 0 ; loop < cpu_count ; loop++ ) + abstraction_thread_start( &thread_handles[loop], loop, lfds601_stack_internal_thread_reader, ss ); + + for( loop = 0 ; loop < cpu_count ; loop++ ) + abstraction_thread_wait( thread_handles[loop] ); + + lfds601_stack_delete( ss, NULL, NULL ); + + free( thread_handles ); + + // TRD : 2. single writer thread per CPU + + printf( "\n" + "2. single writer thread per CPU\n" + "===============================\n" ); + + lfds601_stack_new( &ss, 10000 ); + + thread_handles = (thread_state_t *) malloc( sizeof(thread_state_t) * cpu_count * 1 ); + + for( loop = 0 ; loop < cpu_count ; loop++ ) + abstraction_thread_start( &thread_handles[loop], loop, lfds601_stack_internal_thread_writer, ss ); + + for( loop = 0 ; loop < cpu_count ; loop++ ) + abstraction_thread_wait( thread_handles[loop] ); + + lfds601_stack_delete( ss, NULL, NULL ); + + free( thread_handles ); + + // TRD : 3. one reader and one writer thread per CPU + + printf( "\n" + "3. one reader and one writer thread per CPU\n" + "===========================================\n" ); + + lfds601_stack_new( &ss, 10000 ); + + thread_handles = (thread_state_t *) malloc( sizeof(thread_state_t) * cpu_count * 2 ); + + for( loop = 0 ; loop < cpu_count ; loop++ ) + { + abstraction_thread_start( &thread_handles[loop], loop, lfds601_stack_internal_thread_reader, ss ); + abstraction_thread_start( &thread_handles[loop+cpu_count], loop, lfds601_stack_internal_thread_writer, ss ); + } + + for( loop = 0 ; loop < cpu_count * 2 ; loop++ ) + abstraction_thread_wait( thread_handles[loop] ); + + lfds601_stack_delete( ss, NULL, NULL ); + + free( thread_handles ); + + // TRD : 4. one reader and two writer threads per CPU + + printf( "\n" + "4. one reader and two writer threads per CPU\n" + "============================================\n" ); + + lfds601_stack_new( &ss, 10000 ); + + thread_handles = (thread_state_t *) malloc( sizeof(thread_state_t) * cpu_count * 3 ); + + for( loop = 0 ; loop < cpu_count ; loop++ ) + { + abstraction_thread_start( &thread_handles[loop], loop, lfds601_stack_internal_thread_reader, ss ); + abstraction_thread_start( &thread_handles[loop+cpu_count], loop, lfds601_stack_internal_thread_writer, ss ); + abstraction_thread_start( &thread_handles[loop+cpu_count*2], loop, lfds601_stack_internal_thread_writer, ss ); + } + + for( loop = 0 ; loop < cpu_count * 3 ; loop++ ) + abstraction_thread_wait( thread_handles[loop] ); + + lfds601_stack_delete( ss, NULL, NULL ); + + free( thread_handles ); + + // TRD : 5. two reader and one writer thread per CPU + + printf( "\n" + "5. two reader and one writer thread per CPU\n" + "===========================================\n" ); + + lfds601_stack_new( &ss, 10000 ); + + thread_handles = (thread_state_t *) malloc( sizeof(thread_state_t) * cpu_count * 3 ); + + for( loop = 0 ; loop < cpu_count ; loop++ ) + { + abstraction_thread_start( &thread_handles[loop], loop, lfds601_stack_internal_thread_reader, ss ); + abstraction_thread_start( &thread_handles[loop+cpu_count], loop, lfds601_stack_internal_thread_reader, ss ); + abstraction_thread_start( &thread_handles[loop+cpu_count*2], loop, lfds601_stack_internal_thread_writer, ss ); + } + + for( loop = 0 ; loop < cpu_count * 3 ; loop++ ) + abstraction_thread_wait( thread_handles[loop] ); + + lfds601_stack_delete( ss, NULL, NULL ); + + free( thread_handles ); + + return; +} + + + + + +/****************************************************************************/ +thread_return_t CALLING_CONVENTION lfds601_stack_internal_thread_reader( void *lfds601_stack_state ) +{ + struct lfds601_stack_state + *ss; + + void + *user_data; + + time_t + start_time; + + unsigned long long int + count = 0; + + assert( lfds601_stack_state != NULL ); + + ss = (struct lfds601_stack_state *) lfds601_stack_state; + + time( &start_time ); + + while( time(NULL) < start_time + 10 ) + { + if( lfds601_stack_pop(ss, &user_data) ) + count++; + } + + printf( "read count = %llu\n", count ); + + return( (thread_return_t) EXIT_SUCCESS ); +} + + + + + +/****************************************************************************/ +thread_return_t CALLING_CONVENTION lfds601_stack_internal_thread_writer( void *lfds601_stack_state ) +{ + struct lfds601_stack_state + *ss; + + time_t + start_time; + + unsigned long long int + count = 0; + + assert( lfds601_stack_state != NULL ); + + ss = (struct lfds601_stack_state *) lfds601_stack_state; + + time( &start_time ); + + while( time(NULL) < start_time + 10 ) + { + // TRD : we don't store any user data + if( lfds601_stack_push(ss, NULL) ) + count++; + } + + printf( "write count = %llu\n", count ); + + return( (thread_return_t) EXIT_SUCCESS ); +} + diff --git a/liblfds/liblfds6.0.1/test/test.sln b/liblfds/liblfds6.0.1/test/test.sln new file mode 100644 index 0000000..897240f --- /dev/null +++ b/liblfds/liblfds6.0.1/test/test.sln @@ -0,0 +1,71 @@ + +Microsoft Visual Studio Solution File, Format Version 10.00 +# Visual Studio 2008 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "test", "test.vcproj", "{6E4CBF20-DF1A-4FA0-8A90-58E2A3A5CF09}" + ProjectSection(ProjectDependencies) = postProject + {F73AE755-F6D8-4C3A-977D-FBB40DC0ED05} = {F73AE755-F6D8-4C3A-977D-FBB40DC0ED05} + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "liblfds601", "..\liblfds601\liblfds601.vcproj", "{F73AE755-F6D8-4C3A-977D-FBB40DC0ED05}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug DLL|Win32 = Debug DLL|Win32 + Debug DLL|x64 = Debug DLL|x64 + Debug Lib|Win32 = Debug Lib|Win32 + Debug Lib|x64 = Debug Lib|x64 + Debug|Win32 = Debug|Win32 + Debug|x64 = Debug|x64 + Release DLL|Win32 = Release DLL|Win32 + Release DLL|x64 = Release DLL|x64 + Release Lib|Win32 = Release Lib|Win32 + Release Lib|x64 = Release Lib|x64 + Release|Win32 = Release|Win32 + Release|x64 = Release|x64 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {6E4CBF20-DF1A-4FA0-8A90-58E2A3A5CF09}.Debug DLL|Win32.ActiveCfg = Debug|Win32 + {6E4CBF20-DF1A-4FA0-8A90-58E2A3A5CF09}.Debug DLL|x64.ActiveCfg = Debug|x64 + {6E4CBF20-DF1A-4FA0-8A90-58E2A3A5CF09}.Debug Lib|Win32.ActiveCfg = Debug|Win32 + {6E4CBF20-DF1A-4FA0-8A90-58E2A3A5CF09}.Debug Lib|x64.ActiveCfg = Debug|x64 + {6E4CBF20-DF1A-4FA0-8A90-58E2A3A5CF09}.Debug|Win32.ActiveCfg = Debug|Win32 + {6E4CBF20-DF1A-4FA0-8A90-58E2A3A5CF09}.Debug|Win32.Build.0 = Debug|Win32 + {6E4CBF20-DF1A-4FA0-8A90-58E2A3A5CF09}.Debug|x64.ActiveCfg = Debug|x64 + {6E4CBF20-DF1A-4FA0-8A90-58E2A3A5CF09}.Debug|x64.Build.0 = Debug|x64 + {6E4CBF20-DF1A-4FA0-8A90-58E2A3A5CF09}.Release DLL|Win32.ActiveCfg = Release|Win32 + {6E4CBF20-DF1A-4FA0-8A90-58E2A3A5CF09}.Release DLL|x64.ActiveCfg = Release|x64 + {6E4CBF20-DF1A-4FA0-8A90-58E2A3A5CF09}.Release Lib|Win32.ActiveCfg = Release|Win32 + {6E4CBF20-DF1A-4FA0-8A90-58E2A3A5CF09}.Release Lib|x64.ActiveCfg = Release|x64 + {6E4CBF20-DF1A-4FA0-8A90-58E2A3A5CF09}.Release|Win32.ActiveCfg = Release|Win32 + {6E4CBF20-DF1A-4FA0-8A90-58E2A3A5CF09}.Release|Win32.Build.0 = Release|Win32 + {6E4CBF20-DF1A-4FA0-8A90-58E2A3A5CF09}.Release|x64.ActiveCfg = Release|x64 + {6E4CBF20-DF1A-4FA0-8A90-58E2A3A5CF09}.Release|x64.Build.0 = Release|x64 + {F73AE755-F6D8-4C3A-977D-FBB40DC0ED05}.Debug DLL|Win32.ActiveCfg = Debug DLL|Win32 + {F73AE755-F6D8-4C3A-977D-FBB40DC0ED05}.Debug DLL|Win32.Build.0 = Debug DLL|Win32 + {F73AE755-F6D8-4C3A-977D-FBB40DC0ED05}.Debug DLL|x64.ActiveCfg = Debug DLL|x64 + {F73AE755-F6D8-4C3A-977D-FBB40DC0ED05}.Debug DLL|x64.Build.0 = Debug DLL|x64 + {F73AE755-F6D8-4C3A-977D-FBB40DC0ED05}.Debug Lib|Win32.ActiveCfg = Debug Lib|Win32 + {F73AE755-F6D8-4C3A-977D-FBB40DC0ED05}.Debug Lib|Win32.Build.0 = Debug Lib|Win32 + {F73AE755-F6D8-4C3A-977D-FBB40DC0ED05}.Debug Lib|x64.ActiveCfg = Debug Lib|x64 + {F73AE755-F6D8-4C3A-977D-FBB40DC0ED05}.Debug Lib|x64.Build.0 = Debug Lib|x64 + {F73AE755-F6D8-4C3A-977D-FBB40DC0ED05}.Debug|Win32.ActiveCfg = Debug Lib|Win32 + {F73AE755-F6D8-4C3A-977D-FBB40DC0ED05}.Debug|Win32.Build.0 = Debug Lib|Win32 + {F73AE755-F6D8-4C3A-977D-FBB40DC0ED05}.Debug|x64.ActiveCfg = Debug Lib|x64 + {F73AE755-F6D8-4C3A-977D-FBB40DC0ED05}.Debug|x64.Build.0 = Debug Lib|x64 + {F73AE755-F6D8-4C3A-977D-FBB40DC0ED05}.Release DLL|Win32.ActiveCfg = Release DLL|Win32 + {F73AE755-F6D8-4C3A-977D-FBB40DC0ED05}.Release DLL|Win32.Build.0 = Release DLL|Win32 + {F73AE755-F6D8-4C3A-977D-FBB40DC0ED05}.Release DLL|x64.ActiveCfg = Release DLL|x64 + {F73AE755-F6D8-4C3A-977D-FBB40DC0ED05}.Release DLL|x64.Build.0 = Release DLL|x64 + {F73AE755-F6D8-4C3A-977D-FBB40DC0ED05}.Release Lib|Win32.ActiveCfg = Release Lib|Win32 + {F73AE755-F6D8-4C3A-977D-FBB40DC0ED05}.Release Lib|Win32.Build.0 = Release Lib|Win32 + {F73AE755-F6D8-4C3A-977D-FBB40DC0ED05}.Release Lib|x64.ActiveCfg = Release Lib|x64 + {F73AE755-F6D8-4C3A-977D-FBB40DC0ED05}.Release Lib|x64.Build.0 = Release Lib|x64 + {F73AE755-F6D8-4C3A-977D-FBB40DC0ED05}.Release|Win32.ActiveCfg = Release Lib|Win32 + {F73AE755-F6D8-4C3A-977D-FBB40DC0ED05}.Release|Win32.Build.0 = Release Lib|Win32 + {F73AE755-F6D8-4C3A-977D-FBB40DC0ED05}.Release|x64.ActiveCfg = Release Lib|x64 + {F73AE755-F6D8-4C3A-977D-FBB40DC0ED05}.Release|x64.Build.0 = Release Lib|x64 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/liblfds/liblfds6.0.1/test/test.vcproj b/liblfds/liblfds6.0.1/test/test.vcproj new file mode 100644 index 0000000..92e21f0 --- /dev/null +++ b/liblfds/liblfds6.0.1/test/test.vcproj @@ -0,0 +1,415 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/liblfds/liblfds6.1.0/liblfds610/bin/empty_dir_placeholder_for_git b/liblfds/liblfds6.1.0/liblfds610/bin/empty_dir_placeholder_for_git new file mode 100644 index 0000000..e69de29 diff --git a/liblfds/liblfds6.1.0/liblfds610/building.txt b/liblfds/liblfds6.1.0/liblfds610/building.txt new file mode 100644 index 0000000..2463c93 --- /dev/null +++ b/liblfds/liblfds6.1.0/liblfds610/building.txt @@ -0,0 +1,40 @@ +building liblfds +================ + +Windows (user-mode) +=================== +1. Use Microsoft Visual Studio 2008 or Visual C++ 2008 Express Edition (or + later versions) to load "liblfds.sln". The "Win32" platform is x86, + the "x64" platform is x64. + +2. Use Microsoft Windows SDK and GNUmake to run makefile.windows (obviously + you'll need to have run setenv.bat or the appropriate vcvars*.bat first; + you can build for x64/64-bit and x86/32-bit - just run the correct batch + file). + + Targets are "librel", "libdbg", "dllrel", "dlldbg" and "clean". You need + to clean between switching targets. + +Windows (kernel) +================ +Use the Windows Driver Kit "build" command. Prior to running "build", +if you wish to build a static library, run the batch file +"runme_before_win_kernel_static_lib_build.bat"; if you wish to +build a dynamic library, instead run "runme_before_win_kernel_dynamic_lib_build.bat". + +The Windows kernel build system is rather limited and rather than +really rather messing up the directory/file structure just for the +Windows kernel platform, I've instead arranged it that these batch +files do the necessary work so that "build" will work. + +The batch files are idempotent; you can run them as often as you +like, in any order, at any time (before or after builds), and they'll +do the right thing. You need to clean between switching targets. + +Linux +===== +Use GNUmake to run "makefile.linux". Targets are "arrel", "ardbg", +"sorel", "sodbg" and "clean". You need to clean between switching +targets. + + diff --git a/liblfds/liblfds6.1.0/liblfds610/dirs b/liblfds/liblfds6.1.0/liblfds610/dirs new file mode 100644 index 0000000..0be5295 --- /dev/null +++ b/liblfds/liblfds6.1.0/liblfds610/dirs @@ -0,0 +1,2 @@ +DIRS = src + diff --git a/liblfds/liblfds6.1.0/liblfds610/inc/liblfds610.h b/liblfds/liblfds6.1.0/liblfds610/inc/liblfds610.h new file mode 100644 index 0000000..9748619 --- /dev/null +++ b/liblfds/liblfds6.1.0/liblfds610/inc/liblfds610.h @@ -0,0 +1,340 @@ +#ifndef __LIBLFDS610_H + + /***** library header *****/ + #define LFDS610_RELEASE_NUMBER_STRING "6.1.0" + + + + + /***** lfds610_abstraction *****/ + + /***** defines *****/ + #if (defined _WIN64 && defined _MSC_VER && !defined WIN_KERNEL_BUILD) + // TRD : 64-bit Windows user-mode with the Microsoft C compiler, any CPU + #include + #include + #include + #include + #include + typedef unsigned __int64 lfds610_atom_t; + #define LFDS610_INLINE __forceinline + #define LFDS610_ALIGN(alignment) __declspec( align(alignment) ) + #define LFDS610_ALIGN_SINGLE_POINTER 8 + #define LFDS610_ALIGN_DOUBLE_POINTER 16 + #define LFDS610_BARRIER_COMPILER_LOAD _ReadBarrier() + #define LFDS610_BARRIER_COMPILER_STORE _WriteBarrier() + #define LFDS610_BARRIER_COMPILER_FULL _ReadWriteBarrier() + #define LFDS610_BARRIER_PROCESSOR_LOAD _mm_lfence() + #define LFDS610_BARRIER_PROCESSOR_STORE _mm_sfence() + #define LFDS610_BARRIER_PROCESSOR_FULL _mm_mfence() + #endif + + #if (!defined _WIN64 && defined _WIN32 && defined _MSC_VER && !defined WIN_KERNEL_BUILD) + // TRD : 32-bit Windows user-mode with the Microsoft C compiler, any CPU + #include + #include + #include + #include + #include + typedef unsigned long int lfds610_atom_t; + #define LFDS610_INLINE __forceinline + #define LFDS610_ALIGN(alignment) __declspec( align(alignment) ) + #define LFDS610_ALIGN_SINGLE_POINTER 4 + #define LFDS610_ALIGN_DOUBLE_POINTER 8 + #define LFDS610_BARRIER_COMPILER_LOAD _ReadBarrier() + #define LFDS610_BARRIER_COMPILER_STORE _WriteBarrier() + #define LFDS610_BARRIER_COMPILER_FULL _ReadWriteBarrier() + #define LFDS610_BARRIER_PROCESSOR_LOAD _mm_lfence() + #define LFDS610_BARRIER_PROCESSOR_STORE _mm_sfence() + #define LFDS610_BARRIER_PROCESSOR_FULL _mm_mfence() + + // TRD : this define is documented but missing in Microsoft Platform SDK v7.0 + #define _InterlockedCompareExchangePointer(destination, exchange, compare) _InterlockedCompareExchange((volatile long *) destination, (long) exchange, (long) compare) + #endif + + #if (defined _WIN64 && defined _MSC_VER && defined WIN_KERNEL_BUILD) + // TRD : 64-bit Windows kernel with the Microsoft C compiler, any CPU + #include + #include + #include + #include + typedef unsigned __int64 lfds610_atom_t; + #define LFDS610_INLINE __forceinline + #define LFDS610_ALIGN(alignment) __declspec( align(alignment) ) + #define LFDS610_ALIGN_SINGLE_POINTER 8 + #define LFDS610_ALIGN_DOUBLE_POINTER 16 + #define LFDS610_BARRIER_COMPILER_LOAD _ReadBarrier() + #define LFDS610_BARRIER_COMPILER_STORE _WriteBarrier() + #define LFDS610_BARRIER_COMPILER_FULL _ReadWriteBarrier() + #define LFDS610_BARRIER_PROCESSOR_LOAD _mm_lfence() + #define LFDS610_BARRIER_PROCESSOR_STORE _mm_sfence() + #define LFDS610_BARRIER_PROCESSOR_FULL _mm_mfence() + #endif + + #if (!defined _WIN64 && defined _WIN32 && defined _MSC_VER && defined WIN_KERNEL_BUILD) + // TRD : 32-bit Windows kernel with the Microsoft C compiler, any CPU + #include + #include + #include + #include + typedef unsigned long int lfds610_atom_t; + #define LFDS610_INLINE __forceinline + #define LFDS610_ALIGN(alignment) __declspec( align(alignment) ) + #define LFDS610_ALIGN_SINGLE_POINTER 4 + #define LFDS610_ALIGN_DOUBLE_POINTER 8 + #define LFDS610_BARRIER_COMPILER_LOAD _ReadBarrier() + #define LFDS610_BARRIER_COMPILER_STORE _WriteBarrier() + #define LFDS610_BARRIER_COMPILER_FULL _ReadWriteBarrier() + #define LFDS610_BARRIER_PROCESSOR_LOAD _mm_lfence() + #define LFDS610_BARRIER_PROCESSOR_STORE _mm_sfence() + #define LFDS610_BARRIER_PROCESSOR_FULL _mm_mfence() + + // TRD : this define is documented but missing in Microsoft Platform SDK v7.0 + #define _InterlockedCompareExchangePointer(destination, exchange, compare) _InterlockedCompareExchange((volatile long *) destination, (long) exchange, (long) compare) + #endif + + #if (defined __unix__ && defined __x86_64__ && __GNUC__) + // TRD : any UNIX with GCC on x64 + #include + #include + #include + typedef unsigned long long int lfds610_atom_t; + #define LFDS610_INLINE inline + #define LFDS610_ALIGN(alignment) __attribute__( (aligned(alignment)) ) + #define LFDS610_ALIGN_SINGLE_POINTER 8 + #define LFDS610_ALIGN_DOUBLE_POINTER 16 + #define LFDS610_BARRIER_COMPILER_LOAD __asm__ __volatile__ ( "" : : : "memory" ) + #define LFDS610_BARRIER_COMPILER_STORE __asm__ __volatile__ ( "" : : : "memory" ) + #define LFDS610_BARRIER_COMPILER_FULL __asm__ __volatile__ ( "" : : : "memory" ) + #define LFDS610_BARRIER_PROCESSOR_LOAD __sync_synchronize() + #define LFDS610_BARRIER_PROCESSOR_STORE __sync_synchronize() + #define LFDS610_BARRIER_PROCESSOR_FULL __sync_synchronize() + #endif + + #if (defined __unix__ && defined __i686__ && __GNUC__) + // TRD : any UNIX with GCC on x86 + #include + #include + #include + typedef unsigned long int lfds610_atom_t; + #define LFDS610_INLINE inline + #define LFDS610_ALIGN(alignment) __attribute__( (aligned(alignment)) ) + #define LFDS610_ALIGN_SINGLE_POINTER 4 + #define LFDS610_ALIGN_DOUBLE_POINTER 8 + #define LFDS610_BARRIER_COMPILER_LOAD __asm__ __volatile__ ( "" : : : "memory" ) + #define LFDS610_BARRIER_COMPILER_STORE __asm__ __volatile__ ( "" : : : "memory" ) + #define LFDS610_BARRIER_COMPILER_FULL __asm__ __volatile__ ( "" : : : "memory" ) + #define LFDS610_BARRIER_PROCESSOR_LOAD __sync_synchronize() + #define LFDS610_BARRIER_PROCESSOR_STORE __sync_synchronize() + #define LFDS610_BARRIER_PROCESSOR_FULL __sync_synchronize() + #endif + + #if (defined __unix__ && defined __arm__ && __GNUC__) + // TRD : any UNIX with GCC on ARM + #include + #include + #include + typedef unsigned long int lfds610_atom_t; + #define LFDS610_INLINE inline + #define LFDS610_ALIGN(alignment) __attribute__( (aligned(alignment)) ) + #define LFDS610_ALIGN_SINGLE_POINTER 4 + #define LFDS610_ALIGN_DOUBLE_POINTER 8 + #define LFDS610_BARRIER_COMPILER_LOAD __asm__ __volatile__ ( "" : : : "memory" ) + #define LFDS610_BARRIER_COMPILER_STORE __asm__ __volatile__ ( "" : : : "memory" ) + #define LFDS610_BARRIER_COMPILER_FULL __asm__ __volatile__ ( "" : : : "memory" ) + #define LFDS610_BARRIER_PROCESSOR_LOAD __sync_synchronize() + #define LFDS610_BARRIER_PROCESSOR_STORE __sync_synchronize() + #define LFDS610_BARRIER_PROCESSOR_FULL __sync_synchronize() + #endif + + #define LFDS610_BARRIER_LOAD LFDS610_BARRIER_COMPILER_LOAD; LFDS610_BARRIER_PROCESSOR_LOAD; LFDS610_BARRIER_COMPILER_LOAD + #define LFDS610_BARRIER_STORE LFDS610_BARRIER_COMPILER_STORE; LFDS610_BARRIER_PROCESSOR_STORE; LFDS610_BARRIER_COMPILER_STORE + #define LFDS610_BARRIER_FULL LFDS610_BARRIER_COMPILER_FULL; LFDS610_BARRIER_PROCESSOR_FULL; LFDS610_BARRIER_COMPILER_FULL + + /***** enums *****/ + enum lfds610_data_structure_validity + { + LFDS610_VALIDITY_VALID, + LFDS610_VALIDITY_INVALID_LOOP, + LFDS610_VALIDITY_INVALID_MISSING_ELEMENTS, + LFDS610_VALIDITY_INVALID_ADDITIONAL_ELEMENTS, + LFDS610_VALIDITY_INVALID_TEST_DATA + }; + + /***** structs *****/ + struct lfds610_validation_info + { + lfds610_atom_t + min_elements, + max_elements; + }; + + /***** public prototypes *****/ + void *lfds610_abstraction_malloc( size_t size ); + void lfds610_abstraction_free( void *memory ); + + + + + + /***** lfds610_freelist *****/ + + /***** enums *****/ + enum lfds610_freelist_query_type + { + LFDS610_FREELIST_QUERY_ELEMENT_COUNT, + LFDS610_FREELIST_QUERY_VALIDATE + }; + + /***** incomplete types *****/ + struct lfds610_freelist_state; + struct lfds610_freelist_element; + + /***** public prototypes *****/ + int lfds610_freelist_new( struct lfds610_freelist_state **fs, lfds610_atom_t number_elements, int (*user_data_init_function)(void **user_data, void *user_state), void *user_state ); + void lfds610_freelist_use( struct lfds610_freelist_state *fs ); + void lfds610_freelist_delete( struct lfds610_freelist_state *fs, void (*user_data_delete_function)(void *user_data, void *user_state), void *user_state ); + + lfds610_atom_t lfds610_freelist_new_elements( struct lfds610_freelist_state *fs, lfds610_atom_t number_elements ); + + struct lfds610_freelist_element *lfds610_freelist_pop( struct lfds610_freelist_state *fs, struct lfds610_freelist_element **fe ); + struct lfds610_freelist_element *lfds610_freelist_guaranteed_pop( struct lfds610_freelist_state *fs, struct lfds610_freelist_element **fe ); + void lfds610_freelist_push( struct lfds610_freelist_state *fs, struct lfds610_freelist_element *fe ); + + void *lfds610_freelist_get_user_data_from_element( struct lfds610_freelist_element *fe, void **user_data ); + void lfds610_freelist_set_user_data_in_element( struct lfds610_freelist_element *fe, void *user_data ); + + void lfds610_freelist_query( struct lfds610_freelist_state *fs, enum lfds610_freelist_query_type query_type, void *query_input, void *query_output ); + + + + + + /***** lfds610_liblfds *****/ + + /***** public prototypes *****/ + void lfds610_liblfds_abstraction_test_helper_increment_non_atomic( lfds610_atom_t *shared_counter ); + void lfds610_liblfds_abstraction_test_helper_increment_atomic( volatile lfds610_atom_t *shared_counter ); + void lfds610_liblfds_abstraction_test_helper_cas( volatile lfds610_atom_t *shared_counter, lfds610_atom_t *local_counter ); + void lfds610_liblfds_abstraction_test_helper_dcas( volatile lfds610_atom_t *shared_counter, lfds610_atom_t *local_counter ); + + + + + + /***** lfds610_queue *****/ + + /***** enums *****/ + enum lfds610_queue_query_type + { + LFDS610_QUEUE_QUERY_ELEMENT_COUNT, + LFDS610_QUEUE_QUERY_VALIDATE + }; + + /***** incomplete types *****/ + struct lfds610_queue_state; + + /***** public prototypes *****/ + int lfds610_queue_new( struct lfds610_queue_state **sq, lfds610_atom_t number_elements ); + void lfds610_queue_use( struct lfds610_queue_state *qs ); + void lfds610_queue_delete( struct lfds610_queue_state *qs, void (*user_data_delete_function)(void *user_data, void *user_state), void *user_state ); + + int lfds610_queue_enqueue( struct lfds610_queue_state *qs, void *user_data ); + int lfds610_queue_guaranteed_enqueue( struct lfds610_queue_state *qs, void *user_data ); + int lfds610_queue_dequeue( struct lfds610_queue_state *qs, void **user_data ); + + void lfds610_queue_query( struct lfds610_queue_state *qs, enum lfds610_queue_query_type query_type, void *query_input, void *query_output ); + + + + + + /***** lfds610_ringbuffer *****/ + + /***** enums *****/ + enum lfds610_ringbuffer_query_type + { + LFDS610_RINGBUFFER_QUERY_VALIDATE + }; + + /***** incomplete types *****/ + struct lfds610_ringbuffer_state; + + /***** public prototypes *****/ + int lfds610_ringbuffer_new( struct lfds610_ringbuffer_state **rs, lfds610_atom_t number_elements, int (*user_data_init_function)(void **user_data, void *user_state), void *user_state ); + void lfds610_ringbuffer_use( struct lfds610_ringbuffer_state *rs ); + void lfds610_ringbuffer_delete( struct lfds610_ringbuffer_state *rs, void (*user_data_delete_function)(void *user_data, void *user_state), void *user_state ); + + struct lfds610_freelist_element *lfds610_ringbuffer_get_read_element( struct lfds610_ringbuffer_state *rs, struct lfds610_freelist_element **fe ); + struct lfds610_freelist_element *lfds610_ringbuffer_get_write_element( struct lfds610_ringbuffer_state *rs, struct lfds610_freelist_element **fe, int *overwrite_flag ); + + void lfds610_ringbuffer_put_read_element( struct lfds610_ringbuffer_state *rs, struct lfds610_freelist_element *fe ); + void lfds610_ringbuffer_put_write_element( struct lfds610_ringbuffer_state *rs, struct lfds610_freelist_element *fe ); + + void lfds610_ringbuffer_query( struct lfds610_ringbuffer_state *rs, enum lfds610_ringbuffer_query_type query_type, void *query_input, void *query_output ); + + + + + + /***** lfds610_slist *****/ + + /***** incomplete types *****/ + struct lfds610_slist_state; + struct lfds610_slist_element; + + /***** public prototypes *****/ + int lfds610_slist_new( struct lfds610_slist_state **ss, void (*user_data_delete_function)(void *user_data, void *user_state), void *user_state ); + void lfds610_slist_use( struct lfds610_slist_state *ss ); + void lfds610_slist_delete( struct lfds610_slist_state *ss ); + + struct lfds610_slist_element *lfds610_slist_new_head( struct lfds610_slist_state *ss, void *user_data ); + struct lfds610_slist_element *lfds610_slist_new_next( struct lfds610_slist_element *se, void *user_data ); + + int lfds610_slist_logically_delete_element( struct lfds610_slist_state *ss, struct lfds610_slist_element *se ); + void lfds610_slist_single_threaded_physically_delete_all_elements( struct lfds610_slist_state *ss ); + + int lfds610_slist_get_user_data_from_element( struct lfds610_slist_element *se, void **user_data ); + int lfds610_slist_set_user_data_in_element( struct lfds610_slist_element *se, void *user_data ); + + struct lfds610_slist_element *lfds610_slist_get_head( struct lfds610_slist_state *ss, struct lfds610_slist_element **se ); + struct lfds610_slist_element *lfds610_slist_get_next( struct lfds610_slist_element *se, struct lfds610_slist_element **next_se ); + struct lfds610_slist_element *lfds610_slist_get_head_and_then_next( struct lfds610_slist_state *ss, struct lfds610_slist_element **se ); + + + + + + /***** lfds610_stack *****/ + + /***** enums *****/ + enum lfds610_stack_query_type + { + LFDS610_STACK_QUERY_ELEMENT_COUNT, + LFDS610_STACK_QUERY_VALIDATE + }; + + /***** incomplete types *****/ + struct lfds610_stack_state; + + /***** public prototypes *****/ + int lfds610_stack_new( struct lfds610_stack_state **ss, lfds610_atom_t number_elements ); + void lfds610_stack_use( struct lfds610_stack_state *ss ); + void lfds610_stack_delete( struct lfds610_stack_state *ss, void (*user_data_delete_function)(void *user_data, void *user_state), void *user_state ); + + void lfds610_stack_clear( struct lfds610_stack_state *ss, void (*user_data_clear_function)(void *user_data, void *user_state), void *user_state ); + + int lfds610_stack_push( struct lfds610_stack_state *ss, void *user_data ); + int lfds610_stack_guaranteed_push( struct lfds610_stack_state *ss, void *user_data ); + int lfds610_stack_pop( struct lfds610_stack_state *ss, void **user_data ); + + void lfds610_stack_query( struct lfds610_stack_state *ss, enum lfds610_stack_query_type query_type, void *query_input, void *query_output ); + + + + + + #define __LIBLFDS610_H + +#endif + diff --git a/liblfds/liblfds6.1.0/liblfds610/liblfds610.def b/liblfds/liblfds6.1.0/liblfds610/liblfds610.def new file mode 100644 index 0000000..c8eaf97 --- /dev/null +++ b/liblfds/liblfds6.1.0/liblfds610/liblfds610.def @@ -0,0 +1,57 @@ +EXPORTS + +lfds610_liblfds_abstraction_test_helper_increment_non_atomic = lfds610_liblfds_abstraction_test_helper_increment_non_atomic @1 +lfds610_liblfds_abstraction_test_helper_increment_atomic = lfds610_liblfds_abstraction_test_helper_increment_atomic @2 +lfds610_liblfds_abstraction_test_helper_cas = lfds610_liblfds_abstraction_test_helper_cas @3 +lfds610_liblfds_abstraction_test_helper_dcas = lfds610_liblfds_abstraction_test_helper_dcas @4 + +lfds610_freelist_delete = lfds610_freelist_delete @5 +lfds610_freelist_get_user_data_from_element = lfds610_freelist_get_user_data_from_element @6 +lfds610_freelist_guaranteed_pop = lfds610_freelist_guaranteed_pop @7 +lfds610_freelist_new = lfds610_freelist_new @8 +lfds610_freelist_new_elements = lfds610_freelist_new_elements @9 +lfds610_freelist_pop = lfds610_freelist_pop @10 +lfds610_freelist_push = lfds610_freelist_push @11 +lfds610_freelist_query = lfds610_freelist_query @12 +lfds610_freelist_set_user_data_in_element = lfds610_freelist_set_user_data_in_element @13 +lfds610_freelist_use = lfds610_freelist_use @14 + +lfds610_queue_delete = lfds610_queue_delete @15 +lfds610_queue_dequeue = lfds610_queue_dequeue @16 +lfds610_queue_enqueue = lfds610_queue_enqueue @17 +lfds610_queue_guaranteed_enqueue = lfds610_queue_guaranteed_enqueue @18 +lfds610_queue_new = lfds610_queue_new @19 +lfds610_queue_query = lfds610_queue_query @20 +lfds610_queue_use = lfds610_queue_use @21 + +lfds610_ringbuffer_delete = lfds610_ringbuffer_delete @22 +lfds610_ringbuffer_get_read_element = lfds610_ringbuffer_get_read_element @23 +lfds610_ringbuffer_get_write_element = lfds610_ringbuffer_get_write_element @24 +lfds610_ringbuffer_new = lfds610_ringbuffer_new @25 +lfds610_ringbuffer_put_read_element = lfds610_ringbuffer_put_read_element @26 +lfds610_ringbuffer_put_write_element = lfds610_ringbuffer_put_write_element @27 +lfds610_ringbuffer_query = lfds610_ringbuffer_query @28 +lfds610_ringbuffer_use = lfds610_ringbuffer_use @29 + +lfds610_slist_delete = lfds610_slist_delete @30 +lfds610_slist_get_head = lfds610_slist_get_head @31 +lfds610_slist_get_head_and_then_next = lfds610_slist_get_head_and_then_next @32 +lfds610_slist_get_next = lfds610_slist_get_next @33 +lfds610_slist_get_user_data_from_element = lfds610_slist_get_user_data_from_element @34 +lfds610_slist_logically_delete_element = lfds610_slist_logically_delete_element @35 +lfds610_slist_new = lfds610_slist_new @36 +lfds610_slist_new_head = lfds610_slist_new_head @37 +lfds610_slist_new_next = lfds610_slist_new_next @38 +lfds610_slist_set_user_data_in_element = lfds610_slist_set_user_data_in_element @39 +lfds610_slist_single_threaded_physically_delete_all_elements = lfds610_slist_single_threaded_physically_delete_all_elements @40 +lfds610_slist_use = lfds610_slist_use @41 + +lfds610_stack_clear = lfds610_stack_clear @42 +lfds610_stack_delete = lfds610_stack_delete @43 +lfds610_stack_guaranteed_push = lfds610_stack_guaranteed_push @44 +lfds610_stack_new = lfds610_stack_new @45 +lfds610_stack_pop = lfds610_stack_pop @46 +lfds610_stack_push = lfds610_stack_push @47 +lfds610_stack_query = lfds610_stack_query @48 +lfds610_stack_use = lfds610_stack_use @49 + diff --git a/liblfds/liblfds6.1.0/liblfds610/liblfds610.sln b/liblfds/liblfds6.1.0/liblfds610/liblfds610.sln new file mode 100644 index 0000000..1be564d --- /dev/null +++ b/liblfds/liblfds6.1.0/liblfds610/liblfds610.sln @@ -0,0 +1,38 @@ + +Microsoft Visual Studio Solution File, Format Version 10.00 +# Visual Studio 2008 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "liblfds610", "liblfds610.vcproj", "{F73AE755-F6D8-4C3A-977D-FBB40DC0ED05}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug DLL|Win32 = Debug DLL|Win32 + Debug DLL|x64 = Debug DLL|x64 + Debug Lib|Win32 = Debug Lib|Win32 + Debug Lib|x64 = Debug Lib|x64 + Release DLL|Win32 = Release DLL|Win32 + Release DLL|x64 = Release DLL|x64 + Release Lib|Win32 = Release Lib|Win32 + Release Lib|x64 = Release Lib|x64 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {F73AE755-F6D8-4C3A-977D-FBB40DC0ED05}.Debug DLL|Win32.ActiveCfg = Debug DLL|Win32 + {F73AE755-F6D8-4C3A-977D-FBB40DC0ED05}.Debug DLL|Win32.Build.0 = Debug DLL|Win32 + {F73AE755-F6D8-4C3A-977D-FBB40DC0ED05}.Debug DLL|x64.ActiveCfg = Debug DLL|x64 + {F73AE755-F6D8-4C3A-977D-FBB40DC0ED05}.Debug DLL|x64.Build.0 = Debug DLL|x64 + {F73AE755-F6D8-4C3A-977D-FBB40DC0ED05}.Debug Lib|Win32.ActiveCfg = Debug Lib|Win32 + {F73AE755-F6D8-4C3A-977D-FBB40DC0ED05}.Debug Lib|Win32.Build.0 = Debug Lib|Win32 + {F73AE755-F6D8-4C3A-977D-FBB40DC0ED05}.Debug Lib|x64.ActiveCfg = Debug Lib|x64 + {F73AE755-F6D8-4C3A-977D-FBB40DC0ED05}.Debug Lib|x64.Build.0 = Debug Lib|x64 + {F73AE755-F6D8-4C3A-977D-FBB40DC0ED05}.Release DLL|Win32.ActiveCfg = Release DLL|Win32 + {F73AE755-F6D8-4C3A-977D-FBB40DC0ED05}.Release DLL|Win32.Build.0 = Release DLL|Win32 + {F73AE755-F6D8-4C3A-977D-FBB40DC0ED05}.Release DLL|x64.ActiveCfg = Release DLL|x64 + {F73AE755-F6D8-4C3A-977D-FBB40DC0ED05}.Release DLL|x64.Build.0 = Release DLL|x64 + {F73AE755-F6D8-4C3A-977D-FBB40DC0ED05}.Release Lib|Win32.ActiveCfg = Release Lib|Win32 + {F73AE755-F6D8-4C3A-977D-FBB40DC0ED05}.Release Lib|Win32.Build.0 = Release Lib|Win32 + {F73AE755-F6D8-4C3A-977D-FBB40DC0ED05}.Release Lib|x64.ActiveCfg = Release Lib|x64 + {F73AE755-F6D8-4C3A-977D-FBB40DC0ED05}.Release Lib|x64.Build.0 = Release Lib|x64 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/liblfds/liblfds6.1.0/liblfds610/liblfds610.vcproj b/liblfds/liblfds6.1.0/liblfds610/liblfds610.vcproj new file mode 100644 index 0000000..3eb9ab0 --- /dev/null +++ b/liblfds/liblfds6.1.0/liblfds610/liblfds610.vcproj @@ -0,0 +1,800 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/liblfds/liblfds6.1.0/liblfds610/makefile.linux b/liblfds/liblfds6.1.0/liblfds610/makefile.linux new file mode 100644 index 0000000..a395567 --- /dev/null +++ b/liblfds/liblfds6.1.0/liblfds610/makefile.linux @@ -0,0 +1,106 @@ +##### paths ##### +BINDIR = bin +INCDIR = inc +OBJDIR = obj +SRCDIR = src + +##### misc ##### +QUIETLY = 1>/dev/null 2>/dev/null + +##### sources, objects and libraries ##### +BINNAME = liblfds610 +AR_BINARY = $(BINDIR)/$(BINNAME).a +SO_BINARY = $(BINDIR)/$(BINNAME).so +SRCDIRS = lfds610_abstraction lfds610_freelist lfds610_liblfds lfds610_queue lfds610_ringbuffer lfds610_slist lfds610_stack +# TRD : be aware - in the linux makefile, with the one-pass linking behaviour of the GNU linker, the order +# of source files matters! this is because it leads to the ordering of objects in the library and +# that in turn, since the data structures all use the freelist API and the abstraction API, has to be +# correct +# TRD : lfds610_abstraction_cas.c lfds610_abstraction_dcas.c lfds610_abstraction_increment.c are inlined and are compiled by every C file +SOURCES = lfds610_queue_delete.c lfds610_queue_new.c lfds610_queue_query.c lfds610_queue_queue.c \ + lfds610_ringbuffer_delete.c lfds610_ringbuffer_get_and_put.c lfds610_ringbuffer_new.c lfds610_ringbuffer_query.c \ + lfds610_slist_delete.c lfds610_slist_get_and_set.c lfds610_slist_link.c lfds610_slist_new.c \ + lfds610_stack_delete.c lfds610_stack_new.c lfds610_stack_push_pop.c lfds610_stack_query.c \ + lfds610_freelist_delete.c lfds610_freelist_get_and_set.c lfds610_freelist_new.c lfds610_freelist_query.c lfds610_freelist_pop_push.c \ + lfds610_liblfds_abstraction_test_helpers.c lfds610_liblfds_aligned_free.c lfds610_liblfds_aligned_malloc.c \ + lfds610_abstraction_free.c lfds610_abstraction_malloc.c +OBJECTS = $(patsubst %.c,$(OBJDIR)/%.o,$(notdir $(SOURCES))) + +##### CPU variants ##### +UNAME = $(shell uname -m) +GCCARCH = -march=$(UNAME) + +ifeq ($(UNAME),x86_64) + GCCARCH = -march=core2 +endif + +ifeq ($(findstring arm,$(UNAME)),arm) + GCCARCH = -march=armv6k -marm +endif + +##### tools ##### +MAKE = make +MFLAGS = + +DG = gcc +DGFLAGS = -MM -std=c99 -I"$(SRCDIR)" -I"$(INCDIR)" + +CC = gcc +CBASE = -Wall -Wno-unknown-pragmas -std=c99 $(GCCARCH) -pthread -c -I"$(SRCDIR)" -I"$(INCDIR)" +CFREL = -O2 -finline-functions -Wno-strict-aliasing +CFDBG = -O0 -g + +AR = ar +AFLAGS = -rcs + +LD = gcc +LFBASE = -Wall -std=c99 -shared +LFREL = -O2 -s +LFDBG = -O0 -g + +##### rel/dbg .a/.so variants ##### +ifeq ($(findstring so,$(MAKECMDGOALS)),so) + CBASE := $(CBASE) -fpic +endif + +CFLAGS = $(CBASE) $(CFDBG) +LFLAGS = $(LFBASE) $(LFDBG) + +ifeq ($(findstring rel,$(MAKECMDGOALS)),rel) + CFLAGS = $(CBASE) $(CFREL) + LFLAGS = $(LFBASE) $(LFREL) +endif + +##### search paths ##### +vpath %.c $(patsubst %,$(SRCDIR)/%:,$(SRCDIRS)) + +##### implicit rules ##### +$(OBJDIR)/%.o : %.c + $(DG) $(DGFLAGS) $< >$(OBJDIR)/$*.d + $(CC) $(CFLAGS) -o $@ $< + +##### explicit rules ##### +$(AR_BINARY) : $(OBJECTS) + $(AR) $(AFLAGS) $(AR_BINARY) $(OBJECTS) + +$(SO_BINARY) : $(OBJECTS) + $(LD) $(LFLAGS) $(SYSLIBS) $(OBJECTS) -o $(SO_BINARY) + +##### phony ##### +.PHONY : clean arrel ardbg sorel sodbg + +clean : + @rm -f $(BINDIR)/$(BINNAME).* $(OBJDIR)/*.o $(OBJDIR)/*.d + +arrel : $(AR_BINARY) +ardbg : $(AR_BINARY) + +sorel : $(SO_BINARY) +sodbg : $(SO_BINARY) + +##### dependencies ##### +-include $(DEPENDS) + +##### notes ##### +# TRD : we use -std=c99 purely to permit C++ style comments + diff --git a/liblfds/liblfds6.1.0/liblfds610/makefile.windows b/liblfds/liblfds6.1.0/liblfds610/makefile.windows new file mode 100644 index 0000000..31455a3 --- /dev/null +++ b/liblfds/liblfds6.1.0/liblfds610/makefile.windows @@ -0,0 +1,97 @@ +##### paths ##### +BINDIR = bin +INCDIR = inc +OBJDIR = obj +SRCDIR = src + +##### misc ##### +QUIETLY = 1>nul 2>nul + +##### sources, objects and libraries ##### +BINNAME = liblfds610 +LIB_BINARY = $(BINDIR)\$(BINNAME).lib +DLL_BINARY = $(BINDIR)\$(BINNAME).dll +SRCDIRS = lfds610_abstraction lfds610_freelist lfds610_liblfds lfds610_queue lfds610_ringbuffer lfds610_slist lfds610_stack +# TRD : lfds610_abstraction_cas.c lfds610_abstraction_dcas.c lfds610_abstraction_increment.c are inlined and are compiled by every C file +SOURCES = lfds610_abstraction_free.c lfds610_abstraction_malloc.c \ + lfds610_freelist_delete.c lfds610_freelist_get_and_set.c lfds610_freelist_new.c lfds610_freelist_query.c lfds610_freelist_pop_push.c \ + lfds610_liblfds_abstraction_test_helpers.c lfds610_liblfds_aligned_free.c lfds610_liblfds_aligned_malloc.c \ + lfds610_queue_delete.c lfds610_queue_new.c lfds610_queue_query.c lfds610_queue_queue.c \ + lfds610_ringbuffer_delete.c lfds610_ringbuffer_get_and_put.c lfds610_ringbuffer_new.c lfds610_ringbuffer_query.c \ + lfds610_slist_delete.c lfds610_slist_get_and_set.c lfds610_slist_link.c lfds610_slist_new.c \ + lfds610_stack_delete.c lfds610_stack_new.c lfds610_stack_push_pop.c lfds610_stack_query.c +OBJECTS = $(patsubst %.c,$(OBJDIR)/%.obj,$(notdir $(SOURCES))) +SYSLIBS = kernel32.lib + +##### tools ##### +MAKE = make +MFLAGS = + +CC = cl +CBASE = /nologo /W4 /WX /c "-I$(SRCDIR)" "-I$(INCDIR)" "/Fd$(BINDIR)\$(BINNAME).pdb" /DUNICODE /D_UNICODE /DWIN32_LEAN_AND_MEAN +CFREL = /Ox /DNDEBUG +CFDBG = /Od /Gm /Zi /D_DEBUG + +AR = lib +AFLAGS = /nologo /subsystem:console /wx /verbose + +LD = link +LFBASE = /dll /def:$(BINNAME).def /nologo /subsystem:console /wx /nodefaultlib /nxcompat +LFREL = /incremental:no +LFDBG = /debug "/pdb:$(BINDIR)\$(BINNAME).pdb" + +##### variants ##### +CFLAGS = $(CBASE) $(CFDBG) /MTd +LFLAGS = $(LFBASE) $(LFDBG) +CLIB = libcmtd.lib + +ifeq ($(MAKECMDGOALS),librel) + CFLAGS = $(CBASE) $(CFREL) /MT + LFLAGS = $(LFBASE) $(LFREL) + CLIB = libcmt.lib +endif + +ifeq ($(MAKECMDGOALS),libdbg) + CFLAGS = $(CBASE) $(CFDBG) /MTd + LFLAGS = $(LFBASE) $(LFDBG) + CLIB = libcmtd.lib +endif + +ifeq ($(MAKECMDGOALS),dllrel) + CFLAGS = $(CBASE) $(CFREL) /MD + LFLAGS = $(LFBASE) $(LFREL) + CLIB = msvcrt.lib +endif + +ifeq ($(MAKECMDGOALS),dlldbg) + CFLAGS = $(CBASE) $(CFDBG) /MDd + LFLAGS = $(LFBASE) $(LFDBG) + CLIB = msvcrtd.lib +endif + +##### search paths ##### +vpath %.c $(patsubst %,$(SRCDIR)/%;,$(SRCDIRS)) + +##### implicit rules ##### +$(OBJDIR)/%.obj : %.c + $(CC) $(CFLAGS) "/Fo$@" $< + +##### explicit rules ##### +$(LIB_BINARY) : $(OBJECTS) + $(AR) $(AFLAGS) $(OBJECTS) /out:$(LIB_BINARY) + +$(DLL_BINARY) : $(OBJECTS) + $(LD) $(LFLAGS) $(CLIB) $(SYSLIBS) $(OBJECTS) /out:$(DLL_BINARY) + +##### phony ##### +.PHONY : clean librel libdbg dllrel dlldbg + +clean : + @erase /Q $(BINDIR)\$(BINNAME).* $(OBJDIR)\*.obj $(QUIETLY) + +librel : $(LIB_BINARY) +libdbg : $(LIB_BINARY) + +dllrel : $(DLL_BINARY) +dlldbg : $(DLL_BINARY) + diff --git a/liblfds/liblfds6.1.0/liblfds610/obj/empty_dir_placeholder_for_git b/liblfds/liblfds6.1.0/liblfds610/obj/empty_dir_placeholder_for_git new file mode 100644 index 0000000..e69de29 diff --git a/liblfds/liblfds6.1.0/liblfds610/readme.txt b/liblfds/liblfds6.1.0/liblfds610/readme.txt new file mode 100644 index 0000000..78370bc --- /dev/null +++ b/liblfds/liblfds6.1.0/liblfds610/readme.txt @@ -0,0 +1,139 @@ +introduction +============ +Welcome to liblfds, a portable, license-free, lock-free data structure library +written in C. + +supported platforms +=================== +Out-of-the-box ports are provided for; + +Operating System CPU Toolchain Choices +================ ============= ================= +Windows 64-bit x64 1. Microsoft Visual Studio + 2. Microsoft Windows SDK and GNUmake + +Windows 32-bit x64, x86 1. Microsoft Visual Studio + 2. Visual C++ Express Edition + 3. Microsoft Windows SDK and GNUmake + +Windows Kernel x64, x86 1. Windows Driver Kit + +Linux 64-bit x64 1. GCC and GNUmake + +Linux 32-bit x64, x86, ARM 1. GCC and GNUmake + +For more information including version requirements, see the building guide (lfds). + +data structures +=============== +This release of liblfds provides the following; + + * Freelist + * Queue + * Ringbuffer (each element read by a single reader) + * Singly-linked list (logical delete only) + * Stack + +These are all many-readers, many-writers. + +liblfds on-line +=============== +On the liblfds home page, you will find the blog, a bugzilla, a forum, a +mediawiki and the current and all historical releases. + +The mediawiki contains comprehensive documentation for development, building, +testing and porting. + +http://www.liblfds.org + +license +======= +There is no license. You are free to use this code in any way. + +using +===== +Once built, there is a single header file, /inc/liblfds.h, which you must include +in your source code, and a single library file /bin/liblfds.*, where the suffix +depends on your platform and your build choice (static or dynamic), to which, +if statically built, you must link directly or, if dynamically built, you must +arrange your system such that the library can be found by the loader at run-time. + +testing +======= +The library comes with a command line test and benchmark program. This program +requires threads. As such, it is only suitable for platforms which can execute +a command line binary and provide thread support. Currently this means the test +and benchmark program works for all platforms except the Windows Kernel. + +For documentation, see the testing and benchmarking guide in the mediawiki. + +porting +======= +Both the test program and liblfds provide an abstraction layer which acts to +mask platform differences. Porting is the act of implementing on your platform +the functions which make up the abstraction layers. You do not need to port +the test program to port liblfds, but obviously it is recommended, so you can +test your port. + +To support liblfds, your platform MUST support; + + * atomic single-word* increment + * atomic single-word compare-and-swap + * atomic contiguous double-word compare-and-swap* + * malloc and free + * compiler directive for alignment of variables declared on the stack + * compiler directives for compiler barriers and processor barriers + +* A ''word'' here means a type equal in length to the platform pointer size. +* This requirement excludes the Alpha, IA64, MIPS, PowerPC and SPARC platforms. + +Also, your platform MAY support; + + * compiler keyword for function inlining + +To support the test programme, your platform MUST support; + + * determining the number of logical cores + * threads (starting and waiting on for completion) + +For documentation, see the porting guide (lfds) in the mediawiki. + +release history +=============== +release 1, 25th September 2009, svn revision 1574. + - initial release + +release 2, 5th October 2009, svn revision 1599. + - added abstraction layer for Windows kernel + - minor code tidyups/fixes + +release 3, 25th October 2009, svn revision 1652. + - added singly linked list (logical delete only) + - minor code tidyups/fixes + +release 4, 7th December 2009, svn revision 1716. + - added ARM support + - added benchmarking functionality to the test program + - fixed a profound and pervasive pointer + declaration bug; earlier releases of liblfds + *should not be used* + +release 5, 19th December 2009, svn revision 1738. + - fixed subtle queue bug, which also affected ringbuffer + and caused data re-ordering under high load + - added benchmarks for freelist, ringbuffer and stack + +release 6, 29th December 2009, svn revision 1746. + - fixed two implementation errors, which reduced performance, + spotted by Codeplug from "http://cboard.cprogramming.com". + +release 6.0.0, 18th December 2012, svn revision 2537 + - introduction of namespaces, e.g. the "lfds600_" prefix + code otherwise COMPLETELY AND WHOLLY UNCHANGED + this release is a stepping-stone to 6.1.0 + +release 6.1.0, 31th December 2012, svn revision 2600 + - fixed all existing non-enhancement bugs + - discovered some new bugs and fixed them too + - a very few minor changes/enhancements + diff --git a/liblfds/liblfds6.1.0/liblfds610/runme_before_win_kernel_build_readme.txt b/liblfds/liblfds6.1.0/liblfds610/runme_before_win_kernel_build_readme.txt new file mode 100644 index 0000000..1481c8d --- /dev/null +++ b/liblfds/liblfds6.1.0/liblfds610/runme_before_win_kernel_build_readme.txt @@ -0,0 +1,32 @@ +The Windows kernel build environment is primitive and has a number +of severe limitations; in particular, all source files must be in +one directory and it is not possible to choose the output binary type +(static or dynamic library) from the build command line; rather, +a string has to be modified in a text file used by the build (!) + +To deal with these limitations, it is necessary for a Windows kernel +build to run a batch file prior to building. + +There are two batch files, one for static library builds and the other +for dynamic library builds. + +They are both idempotent; you can run them as often as you like and +switch between them as often as you want. It's all fine; whenever +you run one of them, it will take you from whatever state you were +previously in, into the state you want to be in. + +Both batch files copy all the sources file into a single directory, +"/src/single_dir_for_windows_kernel/". + +The static library batch file will then copy "/sources.static" into +"/src/single_dir_for_windows_kernel/", which will cause a static +library to be built. + +The dynamic library batch file will then copy "/sources.dynamic" into +"/src/single_dir_for_windows_kernel/", which will cause a dynamic +library to be built. It will also copy "src/driver_entry.c" into +"/src/single_dir_for_windows_kernel/", since the linker requires +the DriverEntry function to exist for dynamic libraries, even +though it's not used. + + diff --git a/liblfds/liblfds6.1.0/liblfds610/runme_before_win_kernel_dynamic_lib_build.bat b/liblfds/liblfds6.1.0/liblfds610/runme_before_win_kernel_dynamic_lib_build.bat new file mode 100644 index 0000000..65a1615 --- /dev/null +++ b/liblfds/liblfds6.1.0/liblfds610/runme_before_win_kernel_dynamic_lib_build.bat @@ -0,0 +1,15 @@ +@echo off +rmdir /q /s src\single_dir_for_windows_kernel 1>nul 2>nul +mkdir src\single_dir_for_windows_kernel 1>nul 2>nul +copy /y src\lfds610_abstraction\* src\single_dir_for_windows_kernel 1>nul 2>nul +copy /y src\lfds610_freelist\* src\single_dir_for_windows_kernel 1>nul 2>nul +copy /y src\lfds610_liblfds\* src\single_dir_for_windows_kernel 1>nul 2>nul +copy /y src\lfds610_queue\* src\single_dir_for_windows_kernel 1>nul 2>nul +copy /y src\lfds610_ringbuffer\* src\single_dir_for_windows_kernel 1>nul 2>nul +copy /y src\lfds610_slist\* src\single_dir_for_windows_kernel 1>nul 2>nul +copy /y src\lfds610_stack\* src\single_dir_for_windows_kernel 1>nul 2>nul +copy /y sources.dynamic src\single_dir_for_windows_kernel\sources 1>nul 2>nul +copy /y src\driver_entry.c src\single_dir_for_windows_kernel 1>nul 2>nul +echo Windows kernel dynamic library build directory structure created. +echo (Note the effects of this batch file are idempotent). + diff --git a/liblfds/liblfds6.1.0/liblfds610/runme_before_win_kernel_static_lib_build.bat b/liblfds/liblfds6.1.0/liblfds610/runme_before_win_kernel_static_lib_build.bat new file mode 100644 index 0000000..160a3e1 --- /dev/null +++ b/liblfds/liblfds6.1.0/liblfds610/runme_before_win_kernel_static_lib_build.bat @@ -0,0 +1,15 @@ +@echo off +rmdir /q /s src\single_dir_for_windows_kernel 1>nul 2>nul +mkdir src\single_dir_for_windows_kernel 1>nul 2>nul +copy /y src\lfds610_abstraction\* src\single_dir_for_windows_kernel 1>nul 2>nul +copy /y src\lfds610_freelist\* src\single_dir_for_windows_kernel 1>nul 2>nul +copy /y src\lfds610_liblfds\* src\single_dir_for_windows_kernel 1>nul 2>nul +copy /y src\lfds610_queue\* src\single_dir_for_windows_kernel 1>nul 2>nul +copy /y src\lfds610_ringbuffer\* src\single_dir_for_windows_kernel 1>nul 2>nul +copy /y src\lfds610_slist\* src\single_dir_for_windows_kernel 1>nul 2>nul +copy /y src\lfds610_stack\* src\single_dir_for_windows_kernel 1>nul 2>nul +copy /y sources.static src\single_dir_for_windows_kernel\sources 1>nul 2>nul +erase /f src\single_dir_for_windows_kernel\driver_entry.c 1>nul 2>nul +echo Windows kernel static library build directory structure created. +echo (Note the effects of this batch file are idempotent). + diff --git a/liblfds/liblfds6.1.0/liblfds610/sources.dynamic b/liblfds/liblfds6.1.0/liblfds610/sources.dynamic new file mode 100644 index 0000000..dac1ad1 --- /dev/null +++ b/liblfds/liblfds6.1.0/liblfds610/sources.dynamic @@ -0,0 +1,37 @@ +MSC_WARNING_LEVEL = /WX /W4 +DLLDEF = ../../liblfds610.def +TARGETNAME = liblfds610 +TARGETPATH = ../../bin/ +TARGETTYPE = EXPORT_DRIVER +UMTYPE = nt +USER_C_FLAGS = /DWIN_KERNEL_BUILD + +INCLUDES = ..;../../inc/ +SOURCES = lfds610_abstraction_free.c \ + lfds610_abstraction_malloc.c \ + lfds610_freelist_delete.c \ + lfds610_freelist_get_and_set.c \ + lfds610_freelist_new.c \ + lfds610_freelist_pop_push.c \ + lfds610_freelist_query.c \ + lfds610_liblfds_abstraction_test_helpers.c \ + lfds610_liblfds_aligned_free.c \ + lfds610_liblfds_aligned_malloc.c \ + lfds610_queue_delete.c \ + lfds610_queue_new.c \ + lfds610_queue_query.c \ + lfds610_queue_queue.c \ + lfds610_ringbuffer_delete.c \ + lfds610_ringbuffer_get_and_put.c \ + lfds610_ringbuffer_new.c \ + lfds610_ringbuffer_query.c \ + lfds610_slist_delete.c \ + lfds610_slist_get_and_set.c \ + lfds610_slist_link.c \ + lfds610_slist_new.c \ + lfds610_stack_delete.c \ + lfds610_stack_new.c \ + lfds610_stack_push_pop.c \ + lfds610_stack_query.c \ + driver_entry.c + diff --git a/liblfds/liblfds6.1.0/liblfds610/sources.static b/liblfds/liblfds6.1.0/liblfds610/sources.static new file mode 100644 index 0000000..090a90c --- /dev/null +++ b/liblfds/liblfds6.1.0/liblfds610/sources.static @@ -0,0 +1,35 @@ +MSC_WARNING_LEVEL = /WX /W4 +TARGETNAME = liblfds610 +TARGETPATH = ../../bin/ +TARGETTYPE = DRIVER_LIBRARY +UMTYPE = nt +USER_C_FLAGS = /DWIN_KERNEL_BUILD + +INCLUDES = ..;../../inc/ +SOURCES = lfds610_abstraction_free.c \ + lfds610_abstraction_malloc.c \ + lfds610_freelist_delete.c \ + lfds610_freelist_get_and_set.c \ + lfds610_freelist_new.c \ + lfds610_freelist_pop_push.c \ + lfds610_freelist_query.c \ + lfds610_liblfds_abstraction_test_helpers.c \ + lfds610_liblfds_aligned_free.c \ + lfds610_liblfds_aligned_malloc.c \ + lfds610_queue_delete.c \ + lfds610_queue_new.c \ + lfds610_queue_query.c \ + lfds610_queue_queue.c \ + lfds610_ringbuffer_delete.c \ + lfds610_ringbuffer_get_and_put.c \ + lfds610_ringbuffer_new.c \ + lfds610_ringbuffer_query.c \ + lfds610_slist_delete.c \ + lfds610_slist_get_and_set.c \ + lfds610_slist_link.c \ + lfds610_slist_new.c \ + lfds610_stack_delete.c \ + lfds610_stack_new.c \ + lfds610_stack_push_pop.c \ + lfds610_stack_query.c + diff --git a/liblfds/liblfds6.1.0/liblfds610/src/dirs b/liblfds/liblfds6.1.0/liblfds610/src/dirs new file mode 100644 index 0000000..64e002c --- /dev/null +++ b/liblfds/liblfds6.1.0/liblfds610/src/dirs @@ -0,0 +1,3 @@ +DIRS = single_dir_for_windows_kernel + + diff --git a/liblfds/liblfds6.1.0/liblfds610/src/driver_entry.c b/liblfds/liblfds6.1.0/liblfds610/src/driver_entry.c new file mode 100644 index 0000000..7eb60c9 --- /dev/null +++ b/liblfds/liblfds6.1.0/liblfds610/src/driver_entry.c @@ -0,0 +1,16 @@ +#include "liblfds610_internal.h" + + + + + +/****************************************************************************/ +#pragma warning( disable : 4100 ) + +NTSTATUS DriverEntry( struct _DRIVER_OBJECT *DriverObject, PUNICODE_STRING RegistryPath ) +{ + return( STATUS_SUCCESS ); +} + +#pragma warning( default : 4100 ) + diff --git a/liblfds/liblfds6.1.0/liblfds610/src/driver_entry_readme.txt b/liblfds/liblfds6.1.0/liblfds610/src/driver_entry_readme.txt new file mode 100644 index 0000000..bff054b --- /dev/null +++ b/liblfds/liblfds6.1.0/liblfds610/src/driver_entry_readme.txt @@ -0,0 +1,4 @@ +This C file (driver_entry.c) is used when building a dynamic library for +the Windows kernel. It exists to work around one of the limitations of +that build environment. It is not used by any other build; just ignore it. + diff --git a/liblfds/liblfds6.1.0/liblfds610/src/lfds610_abstraction/lfds610_abstraction_cas.c b/liblfds/liblfds6.1.0/liblfds610/src/lfds610_abstraction/lfds610_abstraction_cas.c new file mode 100644 index 0000000..2b912fe --- /dev/null +++ b/liblfds/liblfds6.1.0/liblfds610/src/lfds610_abstraction/lfds610_abstraction_cas.c @@ -0,0 +1,53 @@ +#include "lfds610_abstraction_internal_body.h" + + + + + +/****************************************************************************/ +#if (defined _WIN32 && defined _MSC_VER) + + /* TRD : 64 bit and 32 bit Windows (user-mode or kernel) on any CPU with the Microsoft C compiler + + _WIN32 indicates 64-bit or 32-bit Windows + _MSC_VER indicates Microsoft C compiler + */ + + static LFDS610_INLINE lfds610_atom_t lfds610_abstraction_cas( volatile lfds610_atom_t *destination, lfds610_atom_t exchange, lfds610_atom_t compare ) + { + assert( destination != NULL ); + // TRD : exchange can be any value in its range + // TRD : compare can be any value in its range + + return( (lfds610_atom_t) _InterlockedCompareExchangePointer((void * volatile *) destination, (void *) exchange, (void *) compare) ); + } + +#endif + + + + + +/****************************************************************************/ +#if (__GNUC__ >= 4 && __GNUC_MINOR__ >= 1 && __GNUC_PATCHLEVEL__ >= 0) + + /* TRD : any OS on any CPU with GCC 4.1.0 or better + + GCC 4.1.0 introduced the __sync_*() atomic intrinsics + + __GNUC__ / __GNUC_MINOR__ / __GNUC_PATCHLEVEL__ indicates GCC and which version + */ + + static LFDS610_INLINE lfds610_atom_t lfds610_abstraction_cas( volatile lfds610_atom_t *destination, lfds610_atom_t exchange, lfds610_atom_t compare ) + { + assert( destination != NULL ); + // TRD : exchange can be any value in its range + // TRD : compare can be any value in its range + + // TRD : note the different argument order for the GCC instrinsic to the MSVC instrinsic + + return( (lfds610_atom_t) __sync_val_compare_and_swap(destination, compare, exchange) ); + } + +#endif + diff --git a/liblfds/liblfds6.1.0/liblfds610/src/lfds610_abstraction/lfds610_abstraction_dcas.c b/liblfds/liblfds6.1.0/liblfds610/src/lfds610_abstraction/lfds610_abstraction_dcas.c new file mode 100644 index 0000000..6450b0b --- /dev/null +++ b/liblfds/liblfds6.1.0/liblfds610/src/lfds610_abstraction/lfds610_abstraction_dcas.c @@ -0,0 +1,139 @@ +#include "lfds610_abstraction_internal_body.h" + + + + + +/****************************************************************************/ +#if (defined _WIN64 && defined _MSC_VER) + + /* TRD : 64 bit Windows (user-mode or kernel) on any CPU with the Microsoft C compiler + + _WIN64 indicates 64 bit Windows + _MSC_VER indicates Microsoft C compiler + */ + + static LFDS610_INLINE unsigned char lfds610_abstraction_dcas( volatile lfds610_atom_t *destination, lfds610_atom_t *exchange, lfds610_atom_t *compare ) + { + assert( destination != NULL ); + assert( exchange != NULL ); + assert( compare != NULL ); + + return( _InterlockedCompareExchange128((volatile __int64 *) destination, (__int64) *(exchange+1), (__int64) *exchange, (__int64 *) compare) ); + } + +#endif + + + + + +/****************************************************************************/ +#if (!defined _WIN64 && defined _WIN32 && defined _MSC_VER) + + /* TRD : 32 bit Windows (user-mode or kernel) on any CPU with the Microsoft C compiler + + (!defined _WIN64 && defined _WIN32) indicates 32 bit Windows + _MSC_VER indicates Microsoft C compiler + */ + + static LFDS610_INLINE unsigned char lfds610_abstraction_dcas( volatile lfds610_atom_t *destination, lfds610_atom_t *exchange, lfds610_atom_t *compare ) + { + __int64 + original_compare; + + assert( destination != NULL ); + assert( exchange != NULL ); + assert( compare != NULL ); + + *(__int64 *) &original_compare = *(__int64 *) compare; + + *(__int64 *) compare = _InterlockedCompareExchange64( (volatile __int64 *) destination, *(__int64 *) exchange, *(__int64 *) compare ); + + return( (unsigned char) (*(__int64 *) compare == *(__int64 *) &original_compare) ); + } + +#endif + + + + + +/****************************************************************************/ +#if (defined __x86_64__ && defined __GNUC__) + + /* TRD : any OS on x64 with GCC + + __x86_64__ indicates x64 + __GNUC__ indicates GCC + */ + + static LFDS610_INLINE unsigned char lfds610_abstraction_dcas( volatile lfds610_atom_t *destination, lfds610_atom_t *exchange, lfds610_atom_t *compare ) + { + unsigned char + cas_result; + + assert( destination != NULL ); + assert( exchange != NULL ); + assert( compare != NULL ); + + __asm__ __volatile__ + ( + "lock;" // make cmpxchg16b atomic + "cmpxchg16b %0;" // cmpxchg16b sets ZF on success + "setz %3;" // if ZF set, set cas_result to 1 + + // output + : "+m" (*(volatile lfds610_atom_t (*)[2]) destination), "+a" (*compare), "+d" (*(compare+1)), "=q" (cas_result) + + // input + : "b" (*exchange), "c" (*(exchange+1)) + + // clobbered + : "cc", "memory" + ); + + return( cas_result ); + } + +#endif + + + + + +/****************************************************************************/ +#if ((defined __i686__ || defined __arm__) && __GNUC__ >= 4 && __GNUC_MINOR__ >= 1 && __GNUC_PATCHLEVEL__ >= 0) + + /* TRD : any OS on x86 or ARM with GCC 4.1.0 or better + + GCC 4.1.0 introduced the __sync_*() atomic intrinsics + + __GNUC__ / __GNUC_MINOR__ / __GNUC_PATCHLEVEL__ indicates GCC and which version + */ + + static LFDS610_INLINE unsigned char lfds610_abstraction_dcas( volatile lfds610_atom_t *destination, lfds610_atom_t *exchange, lfds610_atom_t *compare ) + { + unsigned char + cas_result = 0; + + unsigned long long int + original_destination; + + assert( destination != NULL ); + assert( exchange != NULL ); + assert( compare != NULL ); + + original_destination = __sync_val_compare_and_swap( (volatile unsigned long long int *) destination, *(unsigned long long int *) compare, *(unsigned long long int *) exchange ); + + if( original_destination == *(unsigned long long int *) compare ) + cas_result = 1; + + *(unsigned long long int *) compare = original_destination; + + return( cas_result ); + } + +#endif + + diff --git a/liblfds/liblfds6.1.0/liblfds610/src/lfds610_abstraction/lfds610_abstraction_free.c b/liblfds/liblfds6.1.0/liblfds610/src/lfds610_abstraction/lfds610_abstraction_free.c new file mode 100644 index 0000000..3248836 --- /dev/null +++ b/liblfds/liblfds6.1.0/liblfds610/src/lfds610_abstraction/lfds610_abstraction_free.c @@ -0,0 +1,44 @@ +#include "lfds610_abstraction_internal_wrapper.h" + + + + + +/****************************************************************************/ +#if (!defined WIN_KERNEL_BUILD) + + /* TRD : any OS except Windows kernel on any CPU with any compiler + + !WIN_KERNEL_BUILD indicates not Windows kernel + */ + + void lfds610_abstraction_free( void *memory ) + { + free( memory ); + + return; + } + +#endif + + + + + +/****************************************************************************/ +#if (defined WIN_KERNEL_BUILD) + + /* TRD : any Windows (kernel) on any CPU with the Microsoft C compiler + + WIN_KERNEL_BUILD indicates Windows kernel + */ + + void lfds610_abstraction_free( void *memory ) + { + ExFreePoolWithTag( memory, 'sdfl' ); + + return; + } + +#endif + diff --git a/liblfds/liblfds6.1.0/liblfds610/src/lfds610_abstraction/lfds610_abstraction_increment.c b/liblfds/liblfds6.1.0/liblfds610/src/lfds610_abstraction/lfds610_abstraction_increment.c new file mode 100644 index 0000000..6eb5558 --- /dev/null +++ b/liblfds/liblfds6.1.0/liblfds610/src/lfds610_abstraction/lfds610_abstraction_increment.c @@ -0,0 +1,71 @@ +#include "lfds610_abstraction_internal_body.h" + + + + + +/****************************************************************************/ +#if (defined _WIN64 && defined _MSC_VER) + + /* TRD : 64 bit Windows (user-mode or kernel) on any CPU with the Microsoft C compiler + + _WIN64 indicates 64 bit Windows + _MSC_VER indicates Microsoft C compiler + */ + + static LFDS610_INLINE lfds610_atom_t lfds610_abstraction_increment( volatile lfds610_atom_t *value ) + { + assert( value != NULL ); + + return( (lfds610_atom_t) _InterlockedIncrement64((__int64 *) value) ); + } + +#endif + + + + + +/****************************************************************************/ +#if (!defined _WIN64 && defined _WIN32 && defined _MSC_VER) + + /* TRD : 32 bit Windows (user-mode or kernel) on any CPU with the Microsoft C compiler + + (!defined _WIN64 && defined _WIN32) indicates 32 bit Windows + _MSC_VER indicates Microsoft C compiler + */ + + static LFDS610_INLINE lfds610_atom_t lfds610_abstraction_increment( volatile lfds610_atom_t *value ) + { + assert( value != NULL ); + + return( (lfds610_atom_t) _InterlockedIncrement((long int *) value) ); + } + +#endif + + + + + +/****************************************************************************/ +#if (__GNUC__ >= 4 && __GNUC_MINOR__ >= 1 && __GNUC_PATCHLEVEL__ >= 0) + + /* TRD : any OS on any CPU with GCC 4.1.0 or better + + GCC 4.1.0 introduced the __sync_*() atomic intrinsics + + __GNUC__ / __GNUC_MINOR__ / __GNUC_PATCHLEVEL__ indicates GCC and which version + */ + + static LFDS610_INLINE lfds610_atom_t lfds610_abstraction_increment( volatile lfds610_atom_t *value ) + { + assert( value != NULL ); + + // TRD : no need for casting here, GCC has a __sync_add_and_fetch() for all native types + + return( (lfds610_atom_t) __sync_add_and_fetch(value, 1) ); + } + +#endif + diff --git a/liblfds/liblfds6.1.0/liblfds610/src/lfds610_abstraction/lfds610_abstraction_internal_body.h b/liblfds/liblfds6.1.0/liblfds610/src/lfds610_abstraction/lfds610_abstraction_internal_body.h new file mode 100644 index 0000000..61ff8c7 --- /dev/null +++ b/liblfds/liblfds6.1.0/liblfds610/src/lfds610_abstraction/lfds610_abstraction_internal_body.h @@ -0,0 +1,2 @@ +/***** private prototypes *****/ + diff --git a/liblfds/liblfds6.1.0/liblfds610/src/lfds610_abstraction/lfds610_abstraction_internal_wrapper.h b/liblfds/liblfds6.1.0/liblfds610/src/lfds610_abstraction/lfds610_abstraction_internal_wrapper.h new file mode 100644 index 0000000..4603e7f --- /dev/null +++ b/liblfds/liblfds6.1.0/liblfds610/src/lfds610_abstraction/lfds610_abstraction_internal_wrapper.h @@ -0,0 +1,6 @@ +/***** the library wide include file *****/ +#include "liblfds610_internal.h" + +/***** the internal header body *****/ +#include "lfds610_abstraction_internal_body.h" + diff --git a/liblfds/liblfds6.1.0/liblfds610/src/lfds610_abstraction/lfds610_abstraction_malloc.c b/liblfds/liblfds6.1.0/liblfds610/src/lfds610_abstraction/lfds610_abstraction_malloc.c new file mode 100644 index 0000000..1e4e1cd --- /dev/null +++ b/liblfds/liblfds6.1.0/liblfds610/src/lfds610_abstraction/lfds610_abstraction_malloc.c @@ -0,0 +1,40 @@ +#include "lfds610_abstraction_internal_wrapper.h" + + + + + +/****************************************************************************/ +#if (!defined WIN_KERNEL_BUILD) + + /* TRD : any OS except Windows kernel on any CPU with any compiler + + !WIN_KERNEL_BUILD indicates not Windows kernel + */ + + void *lfds610_abstraction_malloc( size_t size ) + { + return( malloc(size) ); + } + +#endif + + + + + +/****************************************************************************/ +#if (defined WIN_KERNEL_BUILD) + + /* TRD : any Windows (kernel) on any CPU with the Microsoft C compiler + + WIN_KERNEL_BUILD indicates Windows kernel + */ + + void *lfds610_abstraction_malloc( size_t size ) + { + return( ExAllocatePoolWithTag(NonPagedPool, size, 'sdfl') ); + } + +#endif + diff --git a/liblfds/liblfds6.1.0/liblfds610/src/lfds610_freelist/lfds610_freelist_delete.c b/liblfds/liblfds6.1.0/liblfds610/src/lfds610_freelist/lfds610_freelist_delete.c new file mode 100644 index 0000000..b1455b7 --- /dev/null +++ b/liblfds/liblfds6.1.0/liblfds610/src/lfds610_freelist/lfds610_freelist_delete.c @@ -0,0 +1,37 @@ +#include "lfds610_freelist_internal.h" + + + + + +/****************************************************************************/ +void lfds610_freelist_delete( struct lfds610_freelist_state *fs, void (*user_data_delete_function)(void *user_data, void *user_state), void *user_state ) +{ + struct lfds610_freelist_element + *fe; + + void + *user_data; + + assert( fs != NULL ); + // TRD : user_data_delete_function can be NULL + // TRD : user_state can be NULL + + // TRD : leading load barrier not required as it will be performed by the pop + + while( lfds610_freelist_pop(fs, &fe) ) + { + if( user_data_delete_function != NULL ) + { + lfds610_freelist_get_user_data_from_element( fe, &user_data ); + user_data_delete_function( user_data, user_state ); + } + + lfds610_liblfds_aligned_free( fe ); + } + + lfds610_liblfds_aligned_free( fs ); + + return; +} + diff --git a/liblfds/liblfds6.1.0/liblfds610/src/lfds610_freelist/lfds610_freelist_get_and_set.c b/liblfds/liblfds6.1.0/liblfds610/src/lfds610_freelist/lfds610_freelist_get_and_set.c new file mode 100644 index 0000000..b4a6c74 --- /dev/null +++ b/liblfds/liblfds6.1.0/liblfds610/src/lfds610_freelist/lfds610_freelist_get_and_set.c @@ -0,0 +1,37 @@ +#include "lfds610_freelist_internal.h" + + + + + +/****************************************************************************/ +void *lfds610_freelist_get_user_data_from_element( struct lfds610_freelist_element *fe, void **user_data ) +{ + assert( fe != NULL ); + // TRD : user_data can be NULL + + LFDS610_BARRIER_LOAD; + + if( user_data != NULL ) + *user_data = fe->user_data; + + return( fe->user_data ); +} + + + + + +/****************************************************************************/ +void lfds610_freelist_set_user_data_in_element( struct lfds610_freelist_element *fe, void *user_data ) +{ + assert( fe != NULL ); + // TRD : user_data can be NULL + + fe->user_data = user_data; + + LFDS610_BARRIER_STORE; + + return; +} + diff --git a/liblfds/liblfds6.1.0/liblfds610/src/lfds610_freelist/lfds610_freelist_internal.h b/liblfds/liblfds6.1.0/liblfds610/src/lfds610_freelist/lfds610_freelist_internal.h new file mode 100644 index 0000000..3b15774 --- /dev/null +++ b/liblfds/liblfds6.1.0/liblfds610/src/lfds610_freelist/lfds610_freelist_internal.h @@ -0,0 +1,42 @@ +/***** the library wide include file *****/ +#include "liblfds610_internal.h" + +/***** defines *****/ +#define LFDS610_FREELIST_POINTER 0 +#define LFDS610_FREELIST_COUNTER 1 +#define LFDS610_FREELIST_PAC_SIZE 2 + +/***** structures *****/ +#pragma pack( push, LFDS610_ALIGN_DOUBLE_POINTER ) + +struct lfds610_freelist_state +{ + struct lfds610_freelist_element + *volatile top[LFDS610_FREELIST_PAC_SIZE]; + + int + (*user_data_init_function)( void **user_data, void *user_state ); + + void + *user_state; + + lfds610_atom_t + aba_counter, + element_count; +}; + +struct lfds610_freelist_element +{ + struct lfds610_freelist_element + *next[LFDS610_FREELIST_PAC_SIZE]; + + void + *user_data; +}; + +#pragma pack( pop ) + +/***** private prototypes *****/ +lfds610_atom_t lfds610_freelist_internal_new_element( struct lfds610_freelist_state *fs, struct lfds610_freelist_element **fe ); +void lfds610_freelist_internal_validate( struct lfds610_freelist_state *fs, struct lfds610_validation_info *vi, enum lfds610_data_structure_validity *lfds610_freelist_validity ); + diff --git a/liblfds/liblfds6.1.0/liblfds610/src/lfds610_freelist/lfds610_freelist_new.c b/liblfds/liblfds6.1.0/liblfds610/src/lfds610_freelist/lfds610_freelist_new.c new file mode 100644 index 0000000..09d6a7b --- /dev/null +++ b/liblfds/liblfds6.1.0/liblfds610/src/lfds610_freelist/lfds610_freelist_new.c @@ -0,0 +1,143 @@ +#include "lfds610_freelist_internal.h" + + + + + +/****************************************************************************/ +int lfds610_freelist_new( struct lfds610_freelist_state **fs, lfds610_atom_t number_elements, int (*user_data_init_function)(void **user_data, void *user_state), void *user_state ) +{ + int + rv = 0; + + lfds610_atom_t + element_count; + + assert( fs != NULL ); + // TRD : number_elements can be any value in its range + // TRD : user_data_init_function can be NULL + + *fs = (struct lfds610_freelist_state *) lfds610_liblfds_aligned_malloc( sizeof(struct lfds610_freelist_state), LFDS610_ALIGN_DOUBLE_POINTER ); + + if( (*fs) != NULL ) + { + (*fs)->top[LFDS610_FREELIST_POINTER] = NULL; + (*fs)->top[LFDS610_FREELIST_COUNTER] = 0; + (*fs)->user_data_init_function = user_data_init_function; + (*fs)->user_state = user_state; + (*fs)->aba_counter = 0; + (*fs)->element_count = 0; + + element_count = lfds610_freelist_new_elements( *fs, number_elements ); + + if( element_count == number_elements ) + rv = 1; + + if( element_count != number_elements ) + { + lfds610_liblfds_aligned_free( (*fs) ); + *fs = NULL; + } + } + + LFDS610_BARRIER_STORE; + + return( rv ); +} + + + + + +/****************************************************************************/ +#pragma warning( disable : 4100 ) + +void lfds610_freelist_use( struct lfds610_freelist_state *fs ) +{ + assert( fs != NULL ); + + LFDS610_BARRIER_LOAD; + + return; +} + +#pragma warning( default : 4100 ) + + + + + +/****************************************************************************/ +lfds610_atom_t lfds610_freelist_new_elements( struct lfds610_freelist_state *fs, lfds610_atom_t number_elements ) +{ + struct lfds610_freelist_element + *fe; + + lfds610_atom_t + loop, + count = 0; + + assert( fs != NULL ); + // TRD : number_elements can be any value in its range + // TRD : user_data_init_function can be NULL + + for( loop = 0 ; loop < number_elements ; loop++ ) + if( lfds610_freelist_internal_new_element(fs, &fe) ) + { + lfds610_freelist_push( fs, fe ); + count++; + } + + return( count ); +} + + + + + +/****************************************************************************/ +lfds610_atom_t lfds610_freelist_internal_new_element( struct lfds610_freelist_state *fs, struct lfds610_freelist_element **fe ) +{ + lfds610_atom_t + rv = 0; + + assert( fs != NULL ); + assert( fe != NULL ); + + /* TRD : basically, does what you'd expect; + + allocates an element + calls the user init function + if anything fails, cleans up, + sets *fe to NULL + and returns 0 + */ + + *fe = (struct lfds610_freelist_element *) lfds610_liblfds_aligned_malloc( sizeof(struct lfds610_freelist_element), LFDS610_ALIGN_DOUBLE_POINTER ); + + if( *fe != NULL ) + { + if( fs->user_data_init_function == NULL ) + { + (*fe)->user_data = NULL; + rv = 1; + } + + if( fs->user_data_init_function != NULL ) + { + rv = fs->user_data_init_function( &(*fe)->user_data, fs->user_state ); + + if( rv == 0 ) + { + lfds610_liblfds_aligned_free( *fe ); + *fe = NULL; + } + } + } + + if( rv == 1 ) + lfds610_abstraction_increment( (lfds610_atom_t *) &fs->element_count ); + + return( rv ); +} + diff --git a/liblfds/liblfds6.1.0/liblfds610/src/lfds610_freelist/lfds610_freelist_pop_push.c b/liblfds/liblfds6.1.0/liblfds610/src/lfds610_freelist/lfds610_freelist_pop_push.c new file mode 100644 index 0000000..a8dd9a6 --- /dev/null +++ b/liblfds/liblfds6.1.0/liblfds610/src/lfds610_freelist/lfds610_freelist_pop_push.c @@ -0,0 +1,92 @@ +#include "lfds610_freelist_internal.h" + + + + + +/****************************************************************************/ +struct lfds610_freelist_element *lfds610_freelist_pop( struct lfds610_freelist_state *fs, struct lfds610_freelist_element **fe ) +{ + LFDS610_ALIGN(LFDS610_ALIGN_DOUBLE_POINTER) struct lfds610_freelist_element + *fe_local[LFDS610_FREELIST_PAC_SIZE]; + + assert( fs != NULL ); + assert( fe != NULL ); + + LFDS610_BARRIER_LOAD; + + fe_local[LFDS610_FREELIST_COUNTER] = fs->top[LFDS610_FREELIST_COUNTER]; + fe_local[LFDS610_FREELIST_POINTER] = fs->top[LFDS610_FREELIST_POINTER]; + + /* TRD : note that lfds610_abstraction_dcas loads the original value of the destination (fs->top) into the compare (fe_local) + (this happens of course after the CAS itself has occurred inside lfds610_abstraction_dcas) + */ + + do + { + if( fe_local[LFDS610_FREELIST_POINTER] == NULL ) + { + *fe = NULL; + return( *fe ); + } + } + while( 0 == lfds610_abstraction_dcas((volatile lfds610_atom_t *) fs->top, (lfds610_atom_t *) fe_local[LFDS610_FREELIST_POINTER]->next, (lfds610_atom_t *) fe_local) ); + + *fe = (struct lfds610_freelist_element *) fe_local[LFDS610_FREELIST_POINTER]; + + return( *fe ); +} + + + + + +/****************************************************************************/ +struct lfds610_freelist_element *lfds610_freelist_guaranteed_pop( struct lfds610_freelist_state *fs, struct lfds610_freelist_element **fe ) +{ + assert( fs != NULL ); + assert( fe != NULL ); + + lfds610_freelist_internal_new_element( fs, fe ); + + return( *fe ); +} + + + + + +/****************************************************************************/ +void lfds610_freelist_push( struct lfds610_freelist_state *fs, struct lfds610_freelist_element *fe ) +{ + LFDS610_ALIGN(LFDS610_ALIGN_DOUBLE_POINTER) struct lfds610_freelist_element + *fe_local[LFDS610_FREELIST_PAC_SIZE], + *original_fe_next[LFDS610_FREELIST_PAC_SIZE]; + + assert( fs != NULL ); + assert( fe != NULL ); + + LFDS610_BARRIER_LOAD; + + fe_local[LFDS610_FREELIST_POINTER] = fe; + fe_local[LFDS610_FREELIST_COUNTER] = (struct lfds610_freelist_element *) lfds610_abstraction_increment( (lfds610_atom_t *) &fs->aba_counter ); + + original_fe_next[LFDS610_FREELIST_POINTER] = fs->top[LFDS610_FREELIST_POINTER]; + original_fe_next[LFDS610_FREELIST_COUNTER] = fs->top[LFDS610_FREELIST_COUNTER]; + + /* TRD : note that lfds610_abstraction_dcas loads the original value of the destination (fs->top) into the compare (original_fe_next) + (this happens of course after the CAS itself has occurred inside lfds610_abstraction_dcas) + this then causes us in our loop, should we repeat it, to update fe_local->next to a more + up-to-date version of the head of the lfds610_freelist + */ + + do + { + fe_local[LFDS610_FREELIST_POINTER]->next[LFDS610_FREELIST_POINTER] = original_fe_next[LFDS610_FREELIST_POINTER]; + fe_local[LFDS610_FREELIST_POINTER]->next[LFDS610_FREELIST_COUNTER] = original_fe_next[LFDS610_FREELIST_COUNTER]; + } + while( 0 == lfds610_abstraction_dcas((volatile lfds610_atom_t *) fs->top, (lfds610_atom_t *) fe_local, (lfds610_atom_t *) original_fe_next) ); + + return; +} + diff --git a/liblfds/liblfds6.1.0/liblfds610/src/lfds610_freelist/lfds610_freelist_query.c b/liblfds/liblfds6.1.0/liblfds610/src/lfds610_freelist/lfds610_freelist_query.c new file mode 100644 index 0000000..7651ae7 --- /dev/null +++ b/liblfds/liblfds6.1.0/liblfds610/src/lfds610_freelist/lfds610_freelist_query.c @@ -0,0 +1,115 @@ +#include "lfds610_freelist_internal.h" + + + + + +/****************************************************************************/ +void lfds610_freelist_query( struct lfds610_freelist_state *fs, enum lfds610_freelist_query_type query_type, void *query_input, void *query_output ) +{ + assert( fs != NULL ); + // TRD : query type can be any value in its range + // TRD : query_input can be NULL in some cases + assert( query_output != NULL ); + + LFDS610_BARRIER_LOAD; + + switch( query_type ) + { + case LFDS610_FREELIST_QUERY_ELEMENT_COUNT: + assert( query_input == NULL ); + + *(lfds610_atom_t *) query_output = fs->element_count; + break; + + case LFDS610_FREELIST_QUERY_VALIDATE: + // TRD : query_input can be NULL + + lfds610_freelist_internal_validate( fs, (struct lfds610_validation_info *) query_input, (enum lfds610_data_structure_validity *) query_output ); + break; + } + + return; +} + + + + + +/****************************************************************************/ +void lfds610_freelist_internal_validate( struct lfds610_freelist_state *fs, struct lfds610_validation_info *vi, enum lfds610_data_structure_validity *lfds610_freelist_validity ) +{ + struct lfds610_freelist_element + *fe, + *fe_slow, + *fe_fast; + + lfds610_atom_t + element_count = 0; + + assert( fs != NULL ); + // TRD : vi can be NULL + assert( lfds610_freelist_validity != NULL ); + + *lfds610_freelist_validity = LFDS610_VALIDITY_VALID; + + fe_slow = fe_fast = (struct lfds610_freelist_element *) fs->top[LFDS610_FREELIST_POINTER]; + + /* TRD : first, check for a loop + we have two pointers + both of which start at the top of the lfds610_freelist + we enter a loop + and on each iteration + we advance one pointer by one element + and the other by two + + we exit the loop when both pointers are NULL + (have reached the end of the lfds610_freelist) + + or + + if we fast pointer 'sees' the slow pointer + which means we have a loop + */ + + if( fe_slow != NULL ) + do + { + fe_slow = fe_slow->next[LFDS610_FREELIST_POINTER]; + + if( fe_fast != NULL ) + fe_fast = fe_fast->next[LFDS610_FREELIST_POINTER]; + + if( fe_fast != NULL ) + fe_fast = fe_fast->next[LFDS610_FREELIST_POINTER]; + } + while( fe_slow != NULL and fe_fast != fe_slow ); + + if( fe_fast != NULL and fe_slow != NULL and fe_fast == fe_slow ) + *lfds610_freelist_validity = LFDS610_VALIDITY_INVALID_LOOP; + + /* TRD : now check for expected number of elements + vi can be NULL, in which case we do not check + we know we don't have a loop from our earlier check + */ + + if( *lfds610_freelist_validity == LFDS610_VALIDITY_VALID and vi != NULL ) + { + fe = (struct lfds610_freelist_element *) fs->top[LFDS610_FREELIST_POINTER]; + + while( fe != NULL ) + { + element_count++; + fe = (struct lfds610_freelist_element *) fe->next[LFDS610_FREELIST_POINTER]; + } + + if( element_count < vi->min_elements ) + *lfds610_freelist_validity = LFDS610_VALIDITY_INVALID_MISSING_ELEMENTS; + + if( element_count > vi->max_elements ) + *lfds610_freelist_validity = LFDS610_VALIDITY_INVALID_ADDITIONAL_ELEMENTS; + } + + return; +} + diff --git a/liblfds/liblfds6.1.0/liblfds610/src/lfds610_liblfds/lfds610_liblfds_abstraction_test_helpers.c b/liblfds/liblfds6.1.0/liblfds610/src/lfds610_liblfds/lfds610_liblfds_abstraction_test_helpers.c new file mode 100644 index 0000000..2ca980a --- /dev/null +++ b/liblfds/liblfds6.1.0/liblfds610/src/lfds610_liblfds/lfds610_liblfds_abstraction_test_helpers.c @@ -0,0 +1,112 @@ +#include "lfds610_liblfds_internal.h" + + + + + +/****************************************************************************/ +void lfds610_liblfds_abstraction_test_helper_increment_non_atomic( lfds610_atom_t *shared_counter ) +{ + /* TRD : lfds610_atom_t must be volatile or the compiler + optimizes it away into a single store + */ + + volatile lfds610_atom_t + count = 0; + + assert( shared_counter != NULL ); + + while( count++ < 10000000 ) + (*(lfds610_atom_t *) shared_counter)++; + + return; +} + + + + + +/****************************************************************************/ +void lfds610_liblfds_abstraction_test_helper_increment_atomic( volatile lfds610_atom_t *shared_counter ) +{ + lfds610_atom_t + count = 0; + + assert( shared_counter != NULL ); + + while( count++ < 10000000 ) + lfds610_abstraction_increment( shared_counter ); + + return; +} + + + + + +/****************************************************************************/ +void lfds610_liblfds_abstraction_test_helper_cas( volatile lfds610_atom_t *shared_counter, lfds610_atom_t *local_counter ) +{ + lfds610_atom_t + loop = 0, + original_destination; + + LFDS610_ALIGN(LFDS610_ALIGN_SINGLE_POINTER) lfds610_atom_t + exchange, + compare; + + assert( shared_counter != NULL ); + assert( local_counter != NULL ); + + while( loop++ < 1000000 ) + { + do + { + compare = *shared_counter; + exchange = compare + 1; + + original_destination = lfds610_abstraction_cas( shared_counter, exchange, compare ); + } + while( original_destination != compare ); + + (*local_counter)++; + } + + return; +} + + + + + +/****************************************************************************/ +void lfds610_liblfds_abstraction_test_helper_dcas( volatile lfds610_atom_t *shared_counter, lfds610_atom_t *local_counter ) +{ + lfds610_atom_t + loop = 0; + + LFDS610_ALIGN(LFDS610_ALIGN_DOUBLE_POINTER) lfds610_atom_t + exchange[2], + compare[2]; + + assert( shared_counter != NULL ); + assert( local_counter != NULL ); + + while( loop++ < 1000000 ) + { + compare[0] = *shared_counter; + compare[1] = *(shared_counter+1); + + do + { + exchange[0] = compare[0] + 1; + exchange[1] = compare[1]; + } + while( 0 == lfds610_abstraction_dcas(shared_counter, exchange, compare) ); + + (*local_counter)++; + } + + return; +} + diff --git a/liblfds/liblfds6.1.0/liblfds610/src/lfds610_liblfds/lfds610_liblfds_aligned_free.c b/liblfds/liblfds6.1.0/liblfds610/src/lfds610_liblfds/lfds610_liblfds_aligned_free.c new file mode 100644 index 0000000..6aafe9f --- /dev/null +++ b/liblfds/liblfds6.1.0/liblfds610/src/lfds610_liblfds/lfds610_liblfds_aligned_free.c @@ -0,0 +1,17 @@ +#include "lfds610_liblfds_internal.h" + + + + + +/****************************************************************************/ +void lfds610_liblfds_aligned_free( void *memory ) +{ + assert( memory != NULL ); + + // TRD : the "void *" stored above memory points to the root of the allocation + lfds610_abstraction_free( *( (void **) memory - 1 ) ); + + return; +} + diff --git a/liblfds/liblfds6.1.0/liblfds610/src/lfds610_liblfds/lfds610_liblfds_aligned_malloc.c b/liblfds/liblfds6.1.0/liblfds610/src/lfds610_liblfds/lfds610_liblfds_aligned_malloc.c new file mode 100644 index 0000000..7fdf7be --- /dev/null +++ b/liblfds/liblfds6.1.0/liblfds610/src/lfds610_liblfds/lfds610_liblfds_aligned_malloc.c @@ -0,0 +1,32 @@ +#include "lfds610_liblfds_internal.h" + + + + + +/****************************************************************************/ +void *lfds610_liblfds_aligned_malloc( size_t size, size_t align_in_bytes ) +{ + void + *original_memory, + *memory; + + size_t + offset; + + // TRD : size can be any value in its range + // TRD : align_in_bytes can be any value in its range + + original_memory = memory = lfds610_abstraction_malloc( size + sizeof(void *) + align_in_bytes ); + + if( memory != NULL ) + { + memory = (void **) memory + 1; + offset = align_in_bytes - (size_t) memory % align_in_bytes; + memory = (unsigned char *) memory + offset; + *( (void **) memory - 1 ) = original_memory; + } + + return( memory ); +} + diff --git a/liblfds/liblfds6.1.0/liblfds610/src/lfds610_liblfds/lfds610_liblfds_internal.h b/liblfds/liblfds6.1.0/liblfds610/src/lfds610_liblfds/lfds610_liblfds_internal.h new file mode 100644 index 0000000..92b5ae8 --- /dev/null +++ b/liblfds/liblfds6.1.0/liblfds610/src/lfds610_liblfds/lfds610_liblfds_internal.h @@ -0,0 +1,4 @@ +/***** the library wide include file *****/ +#include "liblfds610_internal.h" + + diff --git a/liblfds/liblfds6.1.0/liblfds610/src/lfds610_liblfds/lfds610_liblfds_readme.txt b/liblfds/liblfds6.1.0/liblfds610/src/lfds610_liblfds/lfds610_liblfds_readme.txt new file mode 100644 index 0000000..193a22c --- /dev/null +++ b/liblfds/liblfds6.1.0/liblfds610/src/lfds610_liblfds/lfds610_liblfds_readme.txt @@ -0,0 +1,2 @@ +This is not a data structure but rather functions internal to the library. + diff --git a/liblfds/liblfds6.1.0/liblfds610/src/lfds610_queue/lfds610_queue_delete.c b/liblfds/liblfds6.1.0/liblfds610/src/lfds610_queue/lfds610_queue_delete.c new file mode 100644 index 0000000..ff80a25 --- /dev/null +++ b/liblfds/liblfds6.1.0/liblfds610/src/lfds610_queue/lfds610_queue_delete.c @@ -0,0 +1,57 @@ +#include "lfds610_queue_internal.h" + + + + + +/****************************************************************************/ +void lfds610_queue_delete( struct lfds610_queue_state *qs, void (*user_data_delete_function)(void *user_data, void *user_state), void *user_state ) +{ + void + *user_data; + + assert( qs != NULL ); + // TRD : user_data_delete_function can be NULL + // TRD : user_state can be NULL + + // TRD : leading load barrier not required as it will be performed by the dequeue + + while( lfds610_queue_dequeue(qs, &user_data) ) + if( user_data_delete_function != NULL ) + user_data_delete_function( user_data, user_state ); + + /* TRD : fully dequeuing will leave us + with a single dummy element + which both qs->enqueue and qs->dequeue point at + we push this back onto the lfds610_freelist + before we delete the lfds610_freelist + */ + + lfds610_freelist_push( qs->fs, qs->enqueue[LFDS610_QUEUE_POINTER]->fe ); + + lfds610_freelist_delete( qs->fs, lfds610_queue_internal_freelist_delete_function, NULL ); + + lfds610_liblfds_aligned_free( qs ); + + return; +} + + + + + +/****************************************************************************/ +#pragma warning( disable : 4100 ) + +void lfds610_queue_internal_freelist_delete_function( void *user_data, void *user_state ) +{ + assert( user_data != NULL ); + assert( user_state == NULL ); + + lfds610_liblfds_aligned_free( user_data ); + + return; +} + +#pragma warning( default : 4100 ) + diff --git a/liblfds/liblfds6.1.0/liblfds610/src/lfds610_queue/lfds610_queue_internal.h b/liblfds/liblfds6.1.0/liblfds610/src/lfds610_queue/lfds610_queue_internal.h new file mode 100644 index 0000000..3fb2458 --- /dev/null +++ b/liblfds/liblfds6.1.0/liblfds610/src/lfds610_queue/lfds610_queue_internal.h @@ -0,0 +1,60 @@ +/***** the library wide include file *****/ +#include "liblfds610_internal.h" + +/***** pragmas *****/ + +/***** defines *****/ +#define LFDS610_QUEUE_STATE_UNKNOWN -1 +#define LFDS610_QUEUE_STATE_EMPTY 0 +#define LFDS610_QUEUE_STATE_ENQUEUE_OUT_OF_PLACE 1 +#define LFDS610_QUEUE_STATE_ATTEMPT_DELFDS610_QUEUE 2 + +#define LFDS610_QUEUE_POINTER 0 +#define LFDS610_QUEUE_COUNTER 1 +#define LFDS610_QUEUE_PAC_SIZE 2 + +/***** structures *****/ +#pragma pack( push, LFDS610_ALIGN_DOUBLE_POINTER ) + +struct lfds610_queue_state +{ + struct lfds610_queue_element + *volatile enqueue[LFDS610_QUEUE_PAC_SIZE], + *volatile dequeue[LFDS610_QUEUE_PAC_SIZE]; + + lfds610_atom_t + aba_counter; + + struct lfds610_freelist_state + *fs; +}; + +struct lfds610_queue_element +{ + // TRD : next in a lfds610_queue requires volatile as it is target of CAS + struct lfds610_queue_element + *volatile next[LFDS610_QUEUE_PAC_SIZE]; + + struct lfds610_freelist_element + *fe; + + void + *user_data; +}; + +#pragma pack( pop ) + +/***** externs *****/ + +/***** private prototypes *****/ +int lfds610_queue_internal_freelist_init_function( void **user_data, void *user_state ); +void lfds610_queue_internal_freelist_delete_function( void *user_data, void *user_state ); + +void lfds610_queue_internal_new_element_from_freelist( struct lfds610_queue_state *qs, struct lfds610_queue_element *qe[LFDS610_QUEUE_PAC_SIZE], void *user_data ); +void lfds610_queue_internal_guaranteed_new_element_from_freelist( struct lfds610_queue_state *qs, struct lfds610_queue_element * qe[LFDS610_QUEUE_PAC_SIZE], void *user_data ); +void lfds610_queue_internal_init_element( struct lfds610_queue_state *qs, struct lfds610_queue_element *qe[LFDS610_QUEUE_PAC_SIZE], struct lfds610_freelist_element *fe, void *user_data ); + +void lfds610_queue_internal_queue( struct lfds610_queue_state *qs, struct lfds610_queue_element *qe[LFDS610_QUEUE_PAC_SIZE] ); + +void lfds610_queue_internal_validate( struct lfds610_queue_state *qs, struct lfds610_validation_info *vi, enum lfds610_data_structure_validity *lfds610_queue_validity, enum lfds610_data_structure_validity *lfds610_freelist_validity ); + diff --git a/liblfds/liblfds6.1.0/liblfds610/src/lfds610_queue/lfds610_queue_new.c b/liblfds/liblfds6.1.0/liblfds610/src/lfds610_queue/lfds610_queue_new.c new file mode 100644 index 0000000..000afba --- /dev/null +++ b/liblfds/liblfds6.1.0/liblfds610/src/lfds610_queue/lfds610_queue_new.c @@ -0,0 +1,161 @@ +#include "lfds610_queue_internal.h" + + + + + +/****************************************************************************/ +int lfds610_queue_new( struct lfds610_queue_state **qs, lfds610_atom_t number_elements ) +{ + int + rv = 0; + + struct lfds610_queue_element + *qe[LFDS610_QUEUE_PAC_SIZE]; + + assert( qs != NULL ); + // TRD : number_elements can be any value in its range + + *qs = (struct lfds610_queue_state *) lfds610_liblfds_aligned_malloc( sizeof(struct lfds610_queue_state), LFDS610_ALIGN_DOUBLE_POINTER ); + + if( *qs != NULL ) + { + // TRD : the size of the lfds610_freelist is the size of the lfds610_queue (+1 for the leading dummy element, which is hidden from the caller) + lfds610_freelist_new( &(*qs)->fs, number_elements+1, lfds610_queue_internal_freelist_init_function, NULL ); + + if( (*qs)->fs != NULL ) + { + lfds610_queue_internal_new_element_from_freelist( *qs, qe, NULL ); + (*qs)->enqueue[LFDS610_QUEUE_POINTER] = (*qs)->dequeue[LFDS610_QUEUE_POINTER] = qe[LFDS610_QUEUE_POINTER]; + (*qs)->enqueue[LFDS610_QUEUE_COUNTER] = (*qs)->dequeue[LFDS610_QUEUE_COUNTER] = 0; + (*qs)->aba_counter = 0; + rv = 1; + } + + if( (*qs)->fs == NULL ) + { + lfds610_liblfds_aligned_free( *qs ); + *qs = NULL; + } + } + + LFDS610_BARRIER_STORE; + + return( rv ); +} + + + + + +/****************************************************************************/ +#pragma warning( disable : 4100 ) + +void lfds610_queue_use( struct lfds610_queue_state *qs ) +{ + assert( qs != NULL ); + + LFDS610_BARRIER_LOAD; + + return; +} + +#pragma warning( default : 4100 ) + + + + + +/****************************************************************************/ +#pragma warning( disable : 4100 ) + +int lfds610_queue_internal_freelist_init_function( void **user_data, void *user_state ) +{ + int + rv = 0; + + assert( user_data != NULL ); + assert( user_state == NULL ); + + *user_data = lfds610_liblfds_aligned_malloc( sizeof(struct lfds610_queue_element), LFDS610_ALIGN_DOUBLE_POINTER ); + + if( *user_data != NULL ) + rv = 1; + + return( rv ); +} + +#pragma warning( default : 4100 ) + + + + + +/****************************************************************************/ +void lfds610_queue_internal_new_element_from_freelist( struct lfds610_queue_state *qs, struct lfds610_queue_element *qe[LFDS610_QUEUE_PAC_SIZE], void *user_data ) +{ + struct lfds610_freelist_element + *fe; + + assert( qs != NULL ); + assert( qe != NULL ); + // TRD : user_data can be any value in its range + + qe[LFDS610_QUEUE_POINTER] = NULL; + + lfds610_freelist_pop( qs->fs, &fe ); + + if( fe != NULL ) + lfds610_queue_internal_init_element( qs, qe, fe, user_data ); + + return; +} + + + + + +/****************************************************************************/ +void lfds610_queue_internal_guaranteed_new_element_from_freelist( struct lfds610_queue_state *qs, struct lfds610_queue_element *qe[LFDS610_QUEUE_PAC_SIZE], void *user_data ) +{ + struct lfds610_freelist_element + *fe; + + assert( qs != NULL ); + assert( qe != NULL ); + // TRD : user_data can be any value in its range + + qe[LFDS610_QUEUE_POINTER] = NULL; + + lfds610_freelist_guaranteed_pop( qs->fs, &fe ); + + if( fe != NULL ) + lfds610_queue_internal_init_element( qs, qe, fe, user_data ); + + return; +} + + + + + +/****************************************************************************/ +void lfds610_queue_internal_init_element( struct lfds610_queue_state *qs, struct lfds610_queue_element *qe[LFDS610_QUEUE_PAC_SIZE], struct lfds610_freelist_element *fe, void *user_data ) +{ + assert( qs != NULL ); + assert( qe != NULL ); + assert( fe != NULL ); + // TRD : user_data can be any value in its range + + lfds610_freelist_get_user_data_from_element( fe, (void **) &qe[LFDS610_QUEUE_POINTER] ); + qe[LFDS610_QUEUE_COUNTER] = (struct lfds610_queue_element *) lfds610_abstraction_increment( (lfds610_atom_t *) &qs->aba_counter ); + + qe[LFDS610_QUEUE_POINTER]->next[LFDS610_QUEUE_POINTER] = NULL; + qe[LFDS610_QUEUE_POINTER]->next[LFDS610_QUEUE_COUNTER] = (struct lfds610_queue_element *) lfds610_abstraction_increment( (lfds610_atom_t *) &qs->aba_counter ); + + qe[LFDS610_QUEUE_POINTER]->fe = fe; + qe[LFDS610_QUEUE_POINTER]->user_data = user_data; + + return; +} + diff --git a/liblfds/liblfds6.1.0/liblfds610/src/lfds610_queue/lfds610_queue_query.c b/liblfds/liblfds6.1.0/liblfds610/src/lfds610_queue/lfds610_queue_query.c new file mode 100644 index 0000000..38c73ee --- /dev/null +++ b/liblfds/liblfds6.1.0/liblfds610/src/lfds610_queue/lfds610_queue_query.c @@ -0,0 +1,155 @@ +#include "lfds610_queue_internal.h" + + + + + +/****************************************************************************/ +#pragma warning( disable : 4100 ) + +void lfds610_queue_query( struct lfds610_queue_state *qs, enum lfds610_queue_query_type query_type, void *query_input, void *query_output ) +{ + assert( qs != NULL ); + // TRD : query_type can be any value in its range + // TRD : query_input can be NULL + assert( query_output != NULL ); + + switch( query_type ) + { + case LFDS610_QUEUE_QUERY_ELEMENT_COUNT: + assert( query_input == NULL ); + + lfds610_freelist_query( qs->fs, LFDS610_FREELIST_QUERY_ELEMENT_COUNT, NULL, query_output ); + break; + + case LFDS610_QUEUE_QUERY_VALIDATE: + // TRD : query_input can be NULL + + lfds610_queue_internal_validate( qs, (struct lfds610_validation_info *) query_input, (enum lfds610_data_structure_validity *) query_output, ((enum lfds610_data_structure_validity *) query_output)+1 ); + break; + } + + return; +} + +#pragma warning( default : 4100 ) + + + + + +/****************************************************************************/ +void lfds610_queue_internal_validate( struct lfds610_queue_state *qs, struct lfds610_validation_info *vi, enum lfds610_data_structure_validity *lfds610_queue_validity, enum lfds610_data_structure_validity *lfds610_freelist_validity ) +{ + struct lfds610_queue_element + *qe, + *qe_slow, + *qe_fast; + + lfds610_atom_t + element_count = 0, + total_elements; + + struct lfds610_validation_info + lfds610_freelist_vi; + + assert( qs != NULL ); + // TRD : vi can be NULL + assert( lfds610_queue_validity != NULL ); + assert( lfds610_freelist_validity != NULL ); + + *lfds610_queue_validity = LFDS610_VALIDITY_VALID; + + LFDS610_BARRIER_LOAD; + + qe_slow = qe_fast = (struct lfds610_queue_element *) qs->dequeue[LFDS610_QUEUE_POINTER]; + + /* TRD : first, check for a loop + we have two pointers + both of which start at the dequeue end of the lfds610_queue + we enter a loop + and on each iteration + we advance one pointer by one element + and the other by two + + we exit the loop when both pointers are NULL + (have reached the end of the lfds610_queue) + + or + + if we fast pointer 'sees' the slow pointer + which means we have a loop + */ + + if( qe_slow != NULL ) + do + { + qe_slow = qe_slow->next[LFDS610_QUEUE_POINTER]; + + if( qe_fast != NULL ) + qe_fast = qe_fast->next[LFDS610_QUEUE_POINTER]; + + if( qe_fast != NULL ) + qe_fast = qe_fast->next[LFDS610_QUEUE_POINTER]; + } + while( qe_slow != NULL and qe_fast != qe_slow ); + + if( qe_fast != NULL and qe_slow != NULL and qe_fast == qe_slow ) + *lfds610_queue_validity = LFDS610_VALIDITY_INVALID_LOOP; + + /* TRD : now check for expected number of elements + vi can be NULL, in which case we do not check + we know we don't have a loop from our earlier check + */ + + if( *lfds610_queue_validity == LFDS610_VALIDITY_VALID and vi != NULL ) + { + qe = (struct lfds610_queue_element *) qs->dequeue[LFDS610_QUEUE_POINTER]; + + while( qe != NULL ) + { + element_count++; + qe = (struct lfds610_queue_element *) qe->next[LFDS610_QUEUE_POINTER]; + } + + /* TRD : remember there is a dummy element in the lfds610_queue */ + element_count--; + + if( element_count < vi->min_elements ) + *lfds610_queue_validity = LFDS610_VALIDITY_INVALID_MISSING_ELEMENTS; + + if( element_count > vi->max_elements ) + *lfds610_queue_validity = LFDS610_VALIDITY_INVALID_ADDITIONAL_ELEMENTS; + } + + /* TRD : now we validate the lfds610_freelist + + we may be able to check for the expected number of + elements in the lfds610_freelist + + if the caller has given us an expected min and max + number of elements in the lfds610_queue, then the total number + of elements in the lfds610_freelist, minus that min and max, + gives us the expected number of elements in the + lfds610_freelist + */ + + if( vi != NULL ) + { + lfds610_freelist_query( qs->fs, LFDS610_FREELIST_QUERY_ELEMENT_COUNT, NULL, (void *) &total_elements ); + + /* TRD : remember there is a dummy element in the lfds610_queue */ + total_elements--; + + lfds610_freelist_vi.min_elements = total_elements - vi->max_elements; + lfds610_freelist_vi.max_elements = total_elements - vi->min_elements; + + lfds610_freelist_query( qs->fs, LFDS610_FREELIST_QUERY_VALIDATE, (void *) &lfds610_freelist_vi, (void *) lfds610_freelist_validity ); + } + + if( vi == NULL ) + lfds610_freelist_query( qs->fs, LFDS610_FREELIST_QUERY_VALIDATE, NULL, (void *) lfds610_freelist_validity ); + + return; +} + diff --git a/liblfds/liblfds6.1.0/liblfds610/src/lfds610_queue/lfds610_queue_queue.c b/liblfds/liblfds6.1.0/liblfds610/src/lfds610_queue/lfds610_queue_queue.c new file mode 100644 index 0000000..974a8b6 --- /dev/null +++ b/liblfds/liblfds6.1.0/liblfds610/src/lfds610_queue/lfds610_queue_queue.c @@ -0,0 +1,193 @@ +#include "lfds610_queue_internal.h" + + + + + +/****************************************************************************/ +int lfds610_queue_enqueue( struct lfds610_queue_state *qs, void *user_data ) +{ + LFDS610_ALIGN(LFDS610_ALIGN_DOUBLE_POINTER) struct lfds610_queue_element + *qe[LFDS610_QUEUE_PAC_SIZE]; + + assert( qs != NULL ); + // TRD : user_data can be NULL + + lfds610_queue_internal_new_element_from_freelist( qs, qe, user_data ); + + if( qe[LFDS610_QUEUE_POINTER] == NULL ) + return( 0 ); + + lfds610_queue_internal_queue( qs, qe ); + + return( 1 ); +} + + + + + +/****************************************************************************/ +int lfds610_queue_guaranteed_enqueue( struct lfds610_queue_state *qs, void *user_data ) +{ + LFDS610_ALIGN(LFDS610_ALIGN_DOUBLE_POINTER) struct lfds610_queue_element + *qe[LFDS610_QUEUE_PAC_SIZE]; + + assert( qs != NULL ); + // TRD : user_data can be NULL + + lfds610_queue_internal_guaranteed_new_element_from_freelist( qs, qe, user_data ); + + if( qe[LFDS610_QUEUE_POINTER] == NULL ) + return( 0 ); + + lfds610_queue_internal_queue( qs, qe ); + + return( 1 ); +} + + + + + +/****************************************************************************/ +void lfds610_queue_internal_queue( struct lfds610_queue_state *qs, struct lfds610_queue_element *qe[LFDS610_QUEUE_PAC_SIZE] ) +{ + LFDS610_ALIGN(LFDS610_ALIGN_DOUBLE_POINTER) struct lfds610_queue_element + *enqueue[LFDS610_QUEUE_PAC_SIZE], + *next[LFDS610_QUEUE_PAC_SIZE]; + + unsigned char + cas_result = 0; + + assert( qs != NULL ); + assert( qe != NULL ); + + // TRD : the DCAS operation issues a read and write barrier, so we don't need a read barrier in the do() loop + + LFDS610_BARRIER_LOAD; + + do + { + enqueue[LFDS610_QUEUE_POINTER] = qs->enqueue[LFDS610_QUEUE_POINTER]; + enqueue[LFDS610_QUEUE_COUNTER] = qs->enqueue[LFDS610_QUEUE_COUNTER]; + + next[LFDS610_QUEUE_POINTER] = enqueue[LFDS610_QUEUE_POINTER]->next[LFDS610_QUEUE_POINTER]; + next[LFDS610_QUEUE_COUNTER] = enqueue[LFDS610_QUEUE_POINTER]->next[LFDS610_QUEUE_COUNTER]; + + /* TRD : this if() ensures that the next we read, just above, + really is from qs->enqueue (which we copied into enqueue) + */ + + LFDS610_BARRIER_LOAD; + + if( qs->enqueue[LFDS610_QUEUE_POINTER] == enqueue[LFDS610_QUEUE_POINTER] and qs->enqueue[LFDS610_QUEUE_COUNTER] == enqueue[LFDS610_QUEUE_COUNTER] ) + { + if( next[LFDS610_QUEUE_POINTER] == NULL ) + { + qe[LFDS610_QUEUE_COUNTER] = next[LFDS610_QUEUE_COUNTER] + 1; + cas_result = lfds610_abstraction_dcas( (volatile lfds610_atom_t *) enqueue[LFDS610_QUEUE_POINTER]->next, (lfds610_atom_t *) qe, (lfds610_atom_t *) next ); + } + else + { + next[LFDS610_QUEUE_COUNTER] = enqueue[LFDS610_QUEUE_COUNTER] + 1; + lfds610_abstraction_dcas( (volatile lfds610_atom_t *) qs->enqueue, (lfds610_atom_t *) next, (lfds610_atom_t *) enqueue ); + } + } + } + while( cas_result == 0 ); + + qe[LFDS610_QUEUE_COUNTER] = enqueue[LFDS610_QUEUE_COUNTER] + 1; + lfds610_abstraction_dcas( (volatile lfds610_atom_t *) qs->enqueue, (lfds610_atom_t *) qe, (lfds610_atom_t *) enqueue ); + + return; +} + + + + + +/****************************************************************************/ +int lfds610_queue_dequeue( struct lfds610_queue_state *qs, void **user_data ) +{ + LFDS610_ALIGN(LFDS610_ALIGN_DOUBLE_POINTER) struct lfds610_queue_element + *enqueue[LFDS610_QUEUE_PAC_SIZE], + *dequeue[LFDS610_QUEUE_PAC_SIZE], + *next[LFDS610_QUEUE_PAC_SIZE]; + + unsigned char + cas_result = 0; + + int + rv = 1, + state = LFDS610_QUEUE_STATE_UNKNOWN, + finished_flag = LOWERED; + + assert( qs != NULL ); + assert( user_data != NULL ); + + // TRD : the DCAS operation issues a read and write barrier, so we don't need a read barrier in the do() loop + + LFDS610_BARRIER_LOAD; + + do + { + dequeue[LFDS610_QUEUE_POINTER] = qs->dequeue[LFDS610_QUEUE_POINTER]; + dequeue[LFDS610_QUEUE_COUNTER] = qs->dequeue[LFDS610_QUEUE_COUNTER]; + + enqueue[LFDS610_QUEUE_POINTER] = qs->enqueue[LFDS610_QUEUE_POINTER]; + enqueue[LFDS610_QUEUE_COUNTER] = qs->enqueue[LFDS610_QUEUE_COUNTER]; + + next[LFDS610_QUEUE_POINTER] = dequeue[LFDS610_QUEUE_POINTER]->next[LFDS610_QUEUE_POINTER]; + next[LFDS610_QUEUE_COUNTER] = dequeue[LFDS610_QUEUE_POINTER]->next[LFDS610_QUEUE_COUNTER]; + + /* TRD : confirm that dequeue didn't move between reading it + and reading its next pointer + */ + + LFDS610_BARRIER_LOAD; + + if( dequeue[LFDS610_QUEUE_POINTER] == qs->dequeue[LFDS610_QUEUE_POINTER] and dequeue[LFDS610_QUEUE_COUNTER] == qs->dequeue[LFDS610_QUEUE_COUNTER] ) + { + if( enqueue[LFDS610_QUEUE_POINTER] == dequeue[LFDS610_QUEUE_POINTER] and next[LFDS610_QUEUE_POINTER] == NULL ) + state = LFDS610_QUEUE_STATE_EMPTY; + + if( enqueue[LFDS610_QUEUE_POINTER] == dequeue[LFDS610_QUEUE_POINTER] and next[LFDS610_QUEUE_POINTER] != NULL ) + state = LFDS610_QUEUE_STATE_ENQUEUE_OUT_OF_PLACE; + + if( enqueue[LFDS610_QUEUE_POINTER] != dequeue[LFDS610_QUEUE_POINTER] ) + state = LFDS610_QUEUE_STATE_ATTEMPT_DELFDS610_QUEUE; + + switch( state ) + { + case LFDS610_QUEUE_STATE_EMPTY: + *user_data = NULL; + rv = 0; + finished_flag = RAISED; + break; + + case LFDS610_QUEUE_STATE_ENQUEUE_OUT_OF_PLACE: + next[LFDS610_QUEUE_COUNTER] = enqueue[LFDS610_QUEUE_COUNTER] + 1; + lfds610_abstraction_dcas( (volatile lfds610_atom_t *) qs->enqueue, (lfds610_atom_t *) next, (lfds610_atom_t *) enqueue ); + break; + + case LFDS610_QUEUE_STATE_ATTEMPT_DELFDS610_QUEUE: + *user_data = next[LFDS610_QUEUE_POINTER]->user_data; + + next[LFDS610_QUEUE_COUNTER] = dequeue[LFDS610_QUEUE_COUNTER] + 1; + cas_result = lfds610_abstraction_dcas( (volatile lfds610_atom_t *) qs->dequeue, (lfds610_atom_t *) next, (lfds610_atom_t *) dequeue ); + + if( cas_result == 1 ) + finished_flag = RAISED; + break; + } + } + } + while( finished_flag == LOWERED ); + + if( cas_result == 1 ) + lfds610_freelist_push( qs->fs, dequeue[LFDS610_QUEUE_POINTER]->fe ); + + return( rv ); +} + diff --git a/liblfds/liblfds6.1.0/liblfds610/src/lfds610_ringbuffer/lfds610_ringbuffer_delete.c b/liblfds/liblfds6.1.0/liblfds610/src/lfds610_ringbuffer/lfds610_ringbuffer_delete.c new file mode 100644 index 0000000..43da103 --- /dev/null +++ b/liblfds/liblfds6.1.0/liblfds610/src/lfds610_ringbuffer/lfds610_ringbuffer_delete.c @@ -0,0 +1,22 @@ +#include "lfds610_ringbuffer_internal.h" + + + + + +/****************************************************************************/ +void lfds610_ringbuffer_delete( struct lfds610_ringbuffer_state *rs, void (*user_data_delete_function)(void *user_data, void *user_state), void *user_state ) +{ + assert( rs != NULL ); + // TRD : user_data_delete_function can be NULL + // TRD : user_state can be NULL + + lfds610_queue_delete( rs->qs, NULL, NULL ); + + lfds610_freelist_delete( rs->fs, user_data_delete_function, user_state ); + + lfds610_liblfds_aligned_free( rs ); + + return; +} + diff --git a/liblfds/liblfds6.1.0/liblfds610/src/lfds610_ringbuffer/lfds610_ringbuffer_get_and_put.c b/liblfds/liblfds6.1.0/liblfds610/src/lfds610_ringbuffer/lfds610_ringbuffer_get_and_put.c new file mode 100644 index 0000000..430d4ef --- /dev/null +++ b/liblfds/liblfds6.1.0/liblfds610/src/lfds610_ringbuffer/lfds610_ringbuffer_get_and_put.c @@ -0,0 +1,108 @@ +#include "lfds610_ringbuffer_internal.h" + + + + + +/****************************************************************************/ +struct lfds610_freelist_element *lfds610_ringbuffer_get_read_element( struct lfds610_ringbuffer_state *rs, struct lfds610_freelist_element **fe ) +{ + assert( rs != NULL ); + assert( fe != NULL ); + + lfds610_queue_dequeue( rs->qs, (void **) fe ); + + return( *fe ); +} + + + + + +/****************************************************************************/ +struct lfds610_freelist_element *lfds610_ringbuffer_get_write_element( struct lfds610_ringbuffer_state *rs, struct lfds610_freelist_element **fe, int *overwrite_flag ) +{ + assert( rs != NULL ); + assert( fe != NULL ); + // TRD : overwrite_flag can be NULL + + /* TRD : we try to obtain an element from the lfds610_freelist + if we can, we populate it and add it to the lfds610_queue + + if we cannot, then the lfds610_ringbuffer is full + so instead we grab the current read element and + use that instead + + dequeue may fail since the lfds610_queue may be emptied + during our dequeue attempt + + so what we actually do here is a loop, attempting + the lfds610_freelist and if it fails then a dequeue, until + we obtain an element + + once we have an element, we lfds610_queue it + + you may be wondering why this operation is in a loop + remember - these operations are lock-free; anything + can happen in between + + so for example the pop could fail because the lfds610_freelist + is empty; but by the time we go to get an element from + the lfds610_queue, the whole lfds610_queue has been emptied back into + the lfds610_freelist! + + if overwrite_flag is provided, we set it to 0 if we + obtained a new element from the lfds610_freelist, 1 if we + stole an element from the lfds610_queue + */ + + do + { + if( overwrite_flag != NULL ) + *overwrite_flag = 0; + + lfds610_freelist_pop( rs->fs, fe ); + + if( *fe == NULL ) + { + lfds610_ringbuffer_get_read_element( rs, fe ); + + if( overwrite_flag != NULL and *fe != NULL ) + *overwrite_flag = 1; + } + } + while( *fe == NULL ); + + return( *fe ); +} + + + + + +/****************************************************************************/ +void lfds610_ringbuffer_put_read_element( struct lfds610_ringbuffer_state *rs, struct lfds610_freelist_element *fe ) +{ + assert( rs != NULL ); + assert( fe != NULL ); + + lfds610_freelist_push( rs->fs, fe ); + + return; +} + + + + + +/****************************************************************************/ +void lfds610_ringbuffer_put_write_element( struct lfds610_ringbuffer_state *rs, struct lfds610_freelist_element *fe ) +{ + assert( rs != NULL ); + assert( fe != NULL ); + + lfds610_queue_enqueue( rs->qs, fe ); + + return; +} + diff --git a/liblfds/liblfds6.1.0/liblfds610/src/lfds610_ringbuffer/lfds610_ringbuffer_internal.h b/liblfds/liblfds6.1.0/liblfds610/src/lfds610_ringbuffer/lfds610_ringbuffer_internal.h new file mode 100644 index 0000000..ea0ce09 --- /dev/null +++ b/liblfds/liblfds6.1.0/liblfds610/src/lfds610_ringbuffer/lfds610_ringbuffer_internal.h @@ -0,0 +1,24 @@ +/***** the library wide include file *****/ +#include "liblfds610_internal.h" + +/***** defines *****/ + +/***** structures *****/ +#pragma pack( push, LFDS610_ALIGN_DOUBLE_POINTER ) + +struct lfds610_ringbuffer_state +{ + struct lfds610_queue_state + *qs; + + struct lfds610_freelist_state + *fs; +}; + +#pragma pack( pop ) + +/***** externs *****/ + +/***** private prototypes *****/ +void lfds610_ringbuffer_internal_validate( struct lfds610_ringbuffer_state *rs, struct lfds610_validation_info *vi, enum lfds610_data_structure_validity *lfds610_queue_validity, enum lfds610_data_structure_validity *lfds610_freelist_validity ); + diff --git a/liblfds/liblfds6.1.0/liblfds610/src/lfds610_ringbuffer/lfds610_ringbuffer_new.c b/liblfds/liblfds6.1.0/liblfds610/src/lfds610_ringbuffer/lfds610_ringbuffer_new.c new file mode 100644 index 0000000..52a20fe --- /dev/null +++ b/liblfds/liblfds6.1.0/liblfds610/src/lfds610_ringbuffer/lfds610_ringbuffer_new.c @@ -0,0 +1,67 @@ +#include "lfds610_ringbuffer_internal.h" + + + + + +/****************************************************************************/ +int lfds610_ringbuffer_new( struct lfds610_ringbuffer_state **rs, lfds610_atom_t number_elements, int (*user_data_init_function)(void **user_data, void *user_state), void *user_state ) +{ + int + rv = 0; + + assert( rs != NULL ); + // TRD : number_elements can be any value in its range + // TRD : user_data_init_function can be NULL + // TRD : user_state can be NULL + + *rs = (struct lfds610_ringbuffer_state *) lfds610_liblfds_aligned_malloc( sizeof(struct lfds610_ringbuffer_state), LFDS610_ALIGN_DOUBLE_POINTER ); + + if( *rs != NULL ) + { + lfds610_freelist_new( &(*rs)->fs, number_elements, user_data_init_function, user_state ); + + if( (*rs)->fs != NULL ) + { + lfds610_queue_new( &(*rs)->qs, number_elements ); + + if( (*rs)->qs != NULL ) + rv = 1; + + if( (*rs)->qs == NULL ) + { + lfds610_liblfds_aligned_free( *rs ); + *rs = NULL; + } + } + + if( (*rs)->fs == NULL ) + { + lfds610_liblfds_aligned_free( *rs ); + *rs = NULL; + } + } + + LFDS610_BARRIER_STORE; + + return( rv ); +} + + + + + +/****************************************************************************/ +#pragma warning( disable : 4100 ) + +void lfds610_ringbuffer_use( struct lfds610_ringbuffer_state *rs ) +{ + assert( rs != NULL ); + + LFDS610_BARRIER_LOAD; + + return; +} + +#pragma warning( default : 4100 ) + diff --git a/liblfds/liblfds6.1.0/liblfds610/src/lfds610_ringbuffer/lfds610_ringbuffer_query.c b/liblfds/liblfds6.1.0/liblfds610/src/lfds610_ringbuffer/lfds610_ringbuffer_query.c new file mode 100644 index 0000000..ac48ca1 --- /dev/null +++ b/liblfds/liblfds6.1.0/liblfds610/src/lfds610_ringbuffer/lfds610_ringbuffer_query.c @@ -0,0 +1,64 @@ +#include "lfds610_ringbuffer_internal.h" + + + + + +/****************************************************************************/ +#pragma warning( disable : 4100 ) + +void lfds610_ringbuffer_query( struct lfds610_ringbuffer_state *rs, enum lfds610_ringbuffer_query_type query_type, void *query_input, void *query_output ) +{ + assert( rs != NULL ); + // TRD : query_type can be any value in its range + // TRD : query_input can be NULL + assert( query_output != NULL ); + + switch( query_type ) + { + case LFDS610_RINGBUFFER_QUERY_VALIDATE: + // TRD : query_input can be NULL + + lfds610_ringbuffer_internal_validate( rs, (struct lfds610_validation_info *) query_input, (enum lfds610_data_structure_validity *) query_output, ((enum lfds610_data_structure_validity *) query_output)+2 ); + break; + } + + return; +} + +#pragma warning( default : 4100 ) + + + + + +/****************************************************************************/ +void lfds610_ringbuffer_internal_validate( struct lfds610_ringbuffer_state *rs, struct lfds610_validation_info *vi, enum lfds610_data_structure_validity *lfds610_queue_validity, enum lfds610_data_structure_validity *lfds610_freelist_validity ) +{ + assert( rs != NULL ); + // TRD : vi can be NULL + assert( lfds610_queue_validity != NULL ); + assert( lfds610_freelist_validity != NULL ); + + lfds610_queue_query( rs->qs, LFDS610_QUEUE_QUERY_VALIDATE, vi, lfds610_queue_validity ); + + if( vi != NULL ) + { + struct lfds610_validation_info + lfds610_freelist_vi; + + lfds610_atom_t + total_elements; + + lfds610_freelist_query( rs->fs, LFDS610_FREELIST_QUERY_ELEMENT_COUNT, NULL, (void *) &total_elements ); + lfds610_freelist_vi.min_elements = total_elements - vi->max_elements; + lfds610_freelist_vi.max_elements = total_elements - vi->min_elements; + lfds610_freelist_query( rs->fs, LFDS610_FREELIST_QUERY_VALIDATE, (void *) &lfds610_freelist_vi, (void *) lfds610_freelist_validity ); + } + + if( vi == NULL ) + lfds610_freelist_query( rs->fs, LFDS610_FREELIST_QUERY_VALIDATE, NULL, (void *) lfds610_freelist_validity ); + + return; +} + diff --git a/liblfds/liblfds6.1.0/liblfds610/src/lfds610_slist/lfds610_slist_delete.c b/liblfds/liblfds6.1.0/liblfds610/src/lfds610_slist/lfds610_slist_delete.c new file mode 100644 index 0000000..dfed53f --- /dev/null +++ b/liblfds/liblfds6.1.0/liblfds610/src/lfds610_slist/lfds610_slist_delete.c @@ -0,0 +1,85 @@ +#include "lfds610_slist_internal.h" + + + + + +/****************************************************************************/ +void lfds610_slist_delete( struct lfds610_slist_state *ss ) +{ + lfds610_slist_single_threaded_physically_delete_all_elements( ss ); + + lfds610_liblfds_aligned_free( ss ); + + return; +} + + + + + +/****************************************************************************/ +int lfds610_slist_logically_delete_element( struct lfds610_slist_state *ss, struct lfds610_slist_element *se ) +{ + LFDS610_ALIGN(LFDS610_ALIGN_DOUBLE_POINTER) void + *volatile user_data_and_flags[2], + *volatile new_user_data_and_flags[2]; + + unsigned char + cas_rv = 0; + + assert( ss != NULL ); + assert( se != NULL ); + + LFDS610_BARRIER_LOAD; + + user_data_and_flags[LFDS610_SLIST_USER_DATA] = se->user_data_and_flags[LFDS610_SLIST_USER_DATA]; + user_data_and_flags[LFDS610_SLIST_FLAGS] = se->user_data_and_flags[LFDS610_SLIST_FLAGS]; + + do + { + new_user_data_and_flags[LFDS610_SLIST_USER_DATA] = user_data_and_flags[LFDS610_SLIST_USER_DATA]; + new_user_data_and_flags[LFDS610_SLIST_FLAGS] = (void *) ((lfds610_atom_t) user_data_and_flags[LFDS610_SLIST_FLAGS] | LFDS610_SLIST_FLAG_DELETED); + } + while( !((lfds610_atom_t) user_data_and_flags[LFDS610_SLIST_FLAGS] & LFDS610_SLIST_FLAG_DELETED) and 0 == (cas_rv = lfds610_abstraction_dcas((volatile lfds610_atom_t *) se->user_data_and_flags, (lfds610_atom_t *) new_user_data_and_flags, (lfds610_atom_t *) user_data_and_flags)) ); + + if( cas_rv == 1 ) + if( ss->user_data_delete_function != NULL ) + ss->user_data_delete_function( (void *) user_data_and_flags[LFDS610_SLIST_USER_DATA], ss->user_state ); + + return( cas_rv ); +} + + + + + +/****************************************************************************/ +void lfds610_slist_single_threaded_physically_delete_all_elements( struct lfds610_slist_state *ss ) +{ + struct lfds610_slist_element + *volatile se, + *volatile se_temp; + + LFDS610_BARRIER_LOAD; + + se = ss->head; + + while( se != NULL ) + { + // TRD : if a non-deleted element and there is a delete function, call the delete function + if( ss->user_data_delete_function != NULL ) + ss->user_data_delete_function( (void *) se->user_data_and_flags[LFDS610_SLIST_USER_DATA], ss->user_state ); + + se_temp = se; + se = se->next; + lfds610_liblfds_aligned_free( (void *) se_temp ); + } + + lfds610_slist_internal_init_slist( ss, ss->user_data_delete_function, ss->user_state ); + + LFDS610_BARRIER_STORE; + + return; +} + diff --git a/liblfds/liblfds6.1.0/liblfds610/src/lfds610_slist/lfds610_slist_get_and_set.c b/liblfds/liblfds6.1.0/liblfds610/src/lfds610_slist/lfds610_slist_get_and_set.c new file mode 100644 index 0000000..804c8ec --- /dev/null +++ b/liblfds/liblfds6.1.0/liblfds610/src/lfds610_slist/lfds610_slist_get_and_set.c @@ -0,0 +1,135 @@ +#include "lfds610_slist_internal.h" + + + + + +/****************************************************************************/ +int lfds610_slist_get_user_data_from_element( struct lfds610_slist_element *se, void **user_data ) +{ + int + rv = 1; + + assert( se != NULL ); + assert( user_data != NULL ); + + LFDS610_BARRIER_LOAD; + + *user_data = (void *) se->user_data_and_flags[LFDS610_SLIST_USER_DATA]; + + if( (lfds610_atom_t) se->user_data_and_flags[LFDS610_SLIST_FLAGS] & LFDS610_SLIST_FLAG_DELETED ) + rv = 0; + + return( rv ); +} + + + + + +/****************************************************************************/ +int lfds610_slist_set_user_data_in_element( struct lfds610_slist_element *se, void *user_data ) +{ + LFDS610_ALIGN(LFDS610_ALIGN_DOUBLE_POINTER) void + *user_data_and_flags[2], + *new_user_data_and_flags[2]; + + int + rv = 1; + + assert( se != NULL ); + // TRD : user_data can be NULL + + LFDS610_BARRIER_LOAD; + + user_data_and_flags[LFDS610_SLIST_USER_DATA] = se->user_data_and_flags[LFDS610_SLIST_USER_DATA]; + user_data_and_flags[LFDS610_SLIST_FLAGS] = se->user_data_and_flags[LFDS610_SLIST_FLAGS]; + + new_user_data_and_flags[LFDS610_SLIST_USER_DATA] = user_data; + + do + { + new_user_data_and_flags[LFDS610_SLIST_FLAGS] = user_data_and_flags[LFDS610_SLIST_FLAGS]; + } + while( !((lfds610_atom_t) user_data_and_flags[LFDS610_SLIST_FLAGS] & LFDS610_SLIST_FLAG_DELETED) and + 0 == lfds610_abstraction_dcas((volatile lfds610_atom_t *) se->user_data_and_flags, (lfds610_atom_t *) new_user_data_and_flags, (lfds610_atom_t *) user_data_and_flags) ); + + if( (lfds610_atom_t) user_data_and_flags[LFDS610_SLIST_FLAGS] & LFDS610_SLIST_FLAG_DELETED ) + rv = 0; + + LFDS610_BARRIER_STORE; + + return( rv ); +} + + + + + +/****************************************************************************/ +struct lfds610_slist_element *lfds610_slist_get_head( struct lfds610_slist_state *ss, struct lfds610_slist_element **se ) +{ + assert( ss != NULL ); + assert( se != NULL ); + + LFDS610_BARRIER_LOAD; + + *se = (struct lfds610_slist_element *) ss->head; + + lfds610_slist_internal_move_to_first_undeleted_element( se ); + + return( *se ); +} + + + + + +/****************************************************************************/ +struct lfds610_slist_element *lfds610_slist_get_next( struct lfds610_slist_element *se, struct lfds610_slist_element **next_se ) +{ + assert( se != NULL ); + assert( next_se != NULL ); + + LFDS610_BARRIER_LOAD; + + *next_se = (struct lfds610_slist_element *) se->next; + + lfds610_slist_internal_move_to_first_undeleted_element( next_se ); + + return( *next_se ); +} + + + + + +/****************************************************************************/ +struct lfds610_slist_element *lfds610_slist_get_head_and_then_next( struct lfds610_slist_state *ss, struct lfds610_slist_element **se ) +{ + assert( ss != NULL ); + assert( se != NULL ); + + if( *se == NULL ) + lfds610_slist_get_head( ss, se ); + else + lfds610_slist_get_next( *se, se ); + + return( *se ); +} + + + + + +/****************************************************************************/ +void lfds610_slist_internal_move_to_first_undeleted_element( struct lfds610_slist_element **se ) +{ + assert( se != NULL ); + + while( *se != NULL and (lfds610_atom_t) (*se)->user_data_and_flags[LFDS610_SLIST_FLAGS] & LFDS610_SLIST_FLAG_DELETED ) + (*se) = (struct lfds610_slist_element *) (*se)->next; + + return; +} + diff --git a/liblfds/liblfds6.1.0/liblfds610/src/lfds610_slist/lfds610_slist_internal.h b/liblfds/liblfds6.1.0/liblfds610/src/lfds610_slist/lfds610_slist_internal.h new file mode 100644 index 0000000..4ae428b --- /dev/null +++ b/liblfds/liblfds6.1.0/liblfds610/src/lfds610_slist/lfds610_slist_internal.h @@ -0,0 +1,55 @@ +/***** the library wide include file *****/ +#include "liblfds610_internal.h" + +/***** defines *****/ +#define LFDS610_SLIST_USER_DATA 0 +#define LFDS610_SLIST_FLAGS 1 + +#define LFDS610_SLIST_NO_FLAGS 0x0 +#define LFDS610_SLIST_FLAG_DELETED 0x1 + +/***** structures *****/ +#pragma pack( push, LFDS610_ALIGN_SINGLE_POINTER ) + +struct lfds610_slist_state +{ + struct lfds610_slist_element + *volatile head; + + void + (*user_data_delete_function)( void *user_data, void *user_state ), + *user_state; +}; + +#pragma pack( pop ) + +#pragma pack( push, LFDS610_ALIGN_DOUBLE_POINTER ) + +/* TRD : this pragma pack doesn't seem to work under Windows + if the structure members are the correct way round + (next first), then user_data_and_flags ends up on + a single pointer boundary and DCAS crashes + + accordingly, I've moved user_data_and_flags first +*/ + +struct lfds610_slist_element +{ + void + *volatile user_data_and_flags[2]; + + // TRD : requires volatile as is target of CAS + struct lfds610_slist_element + *volatile next; +}; + +#pragma pack( pop ) + +/***** private prototypes *****/ +void lfds610_slist_internal_init_slist( struct lfds610_slist_state *ss, void (*user_data_delete_function)(void *user_data, void *user_state), void *user_state ); + +void lfds610_slist_internal_link_element_to_head( struct lfds610_slist_state *lfds610_slist_state, struct lfds610_slist_element *volatile se ); +void lfds610_slist_internal_link_element_after_element( struct lfds610_slist_element *volatile lfds610_slist_in_list_element, struct lfds610_slist_element *volatile se ); + +void lfds610_slist_internal_move_to_first_undeleted_element( struct lfds610_slist_element **se ); + diff --git a/liblfds/liblfds6.1.0/liblfds610/src/lfds610_slist/lfds610_slist_link.c b/liblfds/liblfds6.1.0/liblfds610/src/lfds610_slist/lfds610_slist_link.c new file mode 100644 index 0000000..123cbaf --- /dev/null +++ b/liblfds/liblfds6.1.0/liblfds610/src/lfds610_slist/lfds610_slist_link.c @@ -0,0 +1,57 @@ +#include "lfds610_slist_internal.h" + + + + + +/****************************************************************************/ +void lfds610_slist_internal_link_element_to_head( struct lfds610_slist_state *ss, struct lfds610_slist_element *volatile se ) +{ + LFDS610_ALIGN(LFDS610_ALIGN_SINGLE_POINTER) struct lfds610_slist_element + *se_next; + + assert( ss != NULL ); + assert( se != NULL ); + + LFDS610_BARRIER_LOAD; + + se_next = ss->head; + + do + { + se->next = se_next; + } + while( se->next != (se_next = (struct lfds610_slist_element *) lfds610_abstraction_cas((volatile lfds610_atom_t *) &ss->head, (lfds610_atom_t) se, (lfds610_atom_t) se->next)) ); + + return; +} + + + + + +/****************************************************************************/ +void lfds610_slist_internal_link_element_after_element( struct lfds610_slist_element *volatile lfds610_slist_in_list_element, struct lfds610_slist_element *volatile se ) +{ + LFDS610_ALIGN(LFDS610_ALIGN_SINGLE_POINTER) struct lfds610_slist_element + *se_prev, + *se_next; + + assert( lfds610_slist_in_list_element != NULL ); + assert( se != NULL ); + + LFDS610_BARRIER_LOAD; + + se_prev = (struct lfds610_slist_element *) lfds610_slist_in_list_element; + + se_next = se_prev->next; + + do + { + se->next = se_next; + } + while( se->next != (se_next = (struct lfds610_slist_element *) lfds610_abstraction_cas((volatile lfds610_atom_t *) &se_prev->next, (lfds610_atom_t) se, (lfds610_atom_t) se->next)) ); + + return; +} + diff --git a/liblfds/liblfds6.1.0/liblfds610/src/lfds610_slist/lfds610_slist_new.c b/liblfds/liblfds6.1.0/liblfds610/src/lfds610_slist/lfds610_slist_new.c new file mode 100644 index 0000000..ef2d340 --- /dev/null +++ b/liblfds/liblfds6.1.0/liblfds610/src/lfds610_slist/lfds610_slist_new.c @@ -0,0 +1,117 @@ +#include "lfds610_slist_internal.h" + + + + + +/****************************************************************************/ +int lfds610_slist_new( struct lfds610_slist_state **ss, void (*user_data_delete_function)(void *user_data, void *user_state), void *user_state ) +{ + int + rv = 0; + + assert( ss != NULL ); + // TRD : user_data_delete_function can be NULL + // TRD : user_state can be NULL + + *ss = (struct lfds610_slist_state *) lfds610_liblfds_aligned_malloc( sizeof(struct lfds610_slist_state), LFDS610_ALIGN_SINGLE_POINTER ); + + if( *ss != NULL ) + { + lfds610_slist_internal_init_slist( *ss, user_data_delete_function, user_state ); + rv = 1; + } + + LFDS610_BARRIER_STORE; + + return( rv ); +} + + + + + +/****************************************************************************/ +#pragma warning( disable : 4100 ) + +void lfds610_slist_use( struct lfds610_slist_state *ss ) +{ + assert( ss != NULL ); + + LFDS610_BARRIER_LOAD; + + return; +} + +#pragma warning( default : 4100 ) + + + + + +/****************************************************************************/ +void lfds610_slist_internal_init_slist( struct lfds610_slist_state *ss, void (*user_data_delete_function)(void *user_data, void *user_state), void *user_state ) +{ + assert( ss != NULL ); + // TRD : user_data_delete_function can be NULL + // TRD : user_state can be NULL + + ss->head = NULL; + ss->user_data_delete_function = user_data_delete_function; + ss->user_state = user_state; + + return; +} + + + + + +/****************************************************************************/ +struct lfds610_slist_element *lfds610_slist_new_head( struct lfds610_slist_state *ss, void *user_data ) +{ + LFDS610_ALIGN(LFDS610_ALIGN_SINGLE_POINTER) struct lfds610_slist_element + *volatile se; + + assert( ss != NULL ); + // TRD : user_data can be NULL + + se = (struct lfds610_slist_element *) lfds610_liblfds_aligned_malloc( sizeof(struct lfds610_slist_element), LFDS610_ALIGN_DOUBLE_POINTER ); + + if( se != NULL ) + { + se->user_data_and_flags[LFDS610_SLIST_USER_DATA] = user_data; + se->user_data_and_flags[LFDS610_SLIST_FLAGS] = LFDS610_SLIST_NO_FLAGS; + + lfds610_slist_internal_link_element_to_head( ss, se ); + } + + return( (struct lfds610_slist_element *) se ); +} + + + + + +/****************************************************************************/ +struct lfds610_slist_element *lfds610_slist_new_next( struct lfds610_slist_element *se, void *user_data ) +{ + LFDS610_ALIGN(LFDS610_ALIGN_SINGLE_POINTER) struct lfds610_slist_element + *volatile se_next; + + assert( se != NULL ); + // TRD : user_data can be NULL + + se_next = (struct lfds610_slist_element *) lfds610_liblfds_aligned_malloc( sizeof(struct lfds610_slist_element), LFDS610_ALIGN_DOUBLE_POINTER ); + + if( se_next != NULL ) + { + se_next->user_data_and_flags[LFDS610_SLIST_USER_DATA] = user_data; + se_next->user_data_and_flags[LFDS610_SLIST_FLAGS] = LFDS610_SLIST_NO_FLAGS; + + lfds610_slist_internal_link_element_after_element( se, se_next ); + } + + return( (struct lfds610_slist_element *) se_next ); +} + diff --git a/liblfds/liblfds6.1.0/liblfds610/src/lfds610_stack/lfds610_stack_delete.c b/liblfds/liblfds6.1.0/liblfds610/src/lfds610_stack/lfds610_stack_delete.c new file mode 100644 index 0000000..0e56617 --- /dev/null +++ b/liblfds/liblfds6.1.0/liblfds610/src/lfds610_stack/lfds610_stack_delete.c @@ -0,0 +1,67 @@ +#include "lfds610_stack_internal.h" + + + + + +/****************************************************************************/ +void lfds610_stack_delete( struct lfds610_stack_state *ss, void (*user_data_delete_function)(void *user_data, void *user_state), void *user_state ) +{ + void + *user_data; + + assert( ss != NULL ); + // TRD : user_data_delete_function can be NULL + // TRD : user_state can be NULL + + while( lfds610_stack_pop(ss, &user_data) ) + if( user_data_delete_function != NULL ) + user_data_delete_function( user_data, user_state ); + + lfds610_freelist_delete( ss->fs, lfds610_stack_internal_freelist_delete_function, NULL ); + + lfds610_liblfds_aligned_free( ss ); + + return; +} + + + + + +/****************************************************************************/ +void lfds610_stack_clear( struct lfds610_stack_state *ss, void (*user_data_clear_function)(void *user_data, void *user_state), void *user_state ) +{ + void + *user_data; + + assert( ss != NULL ); + // TRD : user_data_clear_function can be NULL + // TRD : user_state can be NULL + + while( lfds610_stack_pop(ss, &user_data) ) + if( user_data_clear_function != NULL ) + user_data_clear_function( user_data, user_state ); + + return; +} + + + + + +/****************************************************************************/ +#pragma warning( disable : 4100 ) + +void lfds610_stack_internal_freelist_delete_function( void *user_data, void *user_state ) +{ + assert( user_data != NULL ); + assert( user_state == NULL ); + + lfds610_liblfds_aligned_free( user_data ); + + return; +} + +#pragma warning( default : 4100 ) + diff --git a/liblfds/liblfds6.1.0/liblfds610/src/lfds610_stack/lfds610_stack_internal.h b/liblfds/liblfds6.1.0/liblfds610/src/lfds610_stack/lfds610_stack_internal.h new file mode 100644 index 0000000..c9ae616 --- /dev/null +++ b/liblfds/liblfds6.1.0/liblfds610/src/lfds610_stack/lfds610_stack_internal.h @@ -0,0 +1,52 @@ +/***** the library wide include file *****/ +#include "liblfds610_internal.h" + +/***** pragmas *****/ + +/***** defines *****/ +#define LFDS610_STACK_POINTER 0 +#define LFDS610_STACK_COUNTER 1 +#define LFDS610_STACK_PAC_SIZE 2 + +/***** structures *****/ +#pragma pack( push, LFDS610_ALIGN_DOUBLE_POINTER ) + +struct lfds610_stack_state +{ + // TRD : must come first for alignment + struct lfds610_stack_element + *volatile top[LFDS610_STACK_PAC_SIZE]; + + lfds610_atom_t + aba_counter; + + struct lfds610_freelist_state + *fs; +}; + +struct lfds610_stack_element +{ + struct lfds610_stack_element + *next[LFDS610_STACK_PAC_SIZE]; + + struct lfds610_freelist_element + *fe; + + void + *user_data; +}; + +#pragma pack( pop ) + +/***** private prototypes *****/ +int lfds610_stack_internal_freelist_init_function( void **user_data, void *user_state ); +void lfds610_stack_internal_freelist_delete_function( void *user_data, void *user_state ); + +void lfds610_stack_internal_new_element_from_freelist( struct lfds610_stack_state *ss, struct lfds610_stack_element *se[LFDS610_STACK_PAC_SIZE], void *user_data ); +void lfds610_stack_internal_new_element( struct lfds610_stack_state *ss, struct lfds610_stack_element *se[LFDS610_STACK_PAC_SIZE], void *user_data ); +void lfds610_stack_internal_init_element( struct lfds610_stack_state *ss, struct lfds610_stack_element *se[LFDS610_STACK_PAC_SIZE], struct lfds610_freelist_element *fe, void *user_data ); + +void lfds610_stack_internal_push( struct lfds610_stack_state *ss, struct lfds610_stack_element *se[LFDS610_STACK_PAC_SIZE] ); + +void lfds610_stack_internal_validate( struct lfds610_stack_state *ss, struct lfds610_validation_info *vi, enum lfds610_data_structure_validity *stack_validity, enum lfds610_data_structure_validity *freelist_validity ); + diff --git a/liblfds/liblfds6.1.0/liblfds610/src/lfds610_stack/lfds610_stack_new.c b/liblfds/liblfds6.1.0/liblfds610/src/lfds610_stack/lfds610_stack_new.c new file mode 100644 index 0000000..2716f4e --- /dev/null +++ b/liblfds/liblfds6.1.0/liblfds610/src/lfds610_stack/lfds610_stack_new.c @@ -0,0 +1,159 @@ +#include "lfds610_stack_internal.h" + + + + + +/****************************************************************************/ +int lfds610_stack_new( struct lfds610_stack_state **ss, lfds610_atom_t number_elements ) +{ + int + rv = 0; + + assert( ss != NULL ); + // TRD : number_elements can be any value in its range + + *ss = (struct lfds610_stack_state *) lfds610_liblfds_aligned_malloc( sizeof(struct lfds610_stack_state), LFDS610_ALIGN_DOUBLE_POINTER ); + + if( *ss != NULL ) + { + // TRD : the size of the lfds610_freelist is the size of the lfds610_stack + lfds610_freelist_new( &(*ss)->fs, number_elements, lfds610_stack_internal_freelist_init_function, NULL ); + + if( (*ss)->fs == NULL ) + { + lfds610_liblfds_aligned_free( *ss ); + *ss = NULL; + } + + if( (*ss)->fs != NULL ) + { + (*ss)->top[LFDS610_STACK_POINTER] = NULL; + (*ss)->top[LFDS610_STACK_COUNTER] = 0; + (*ss)->aba_counter = 0; + rv = 1; + } + } + + LFDS610_BARRIER_STORE; + + return( rv ); +} + + + + + +/****************************************************************************/ +#pragma warning( disable : 4100 ) + +void lfds610_stack_use( struct lfds610_stack_state *ss ) +{ + assert( ss != NULL ); + + LFDS610_BARRIER_LOAD; + + return; +} + +#pragma warning( default : 4100 ) + + + + + +/****************************************************************************/ +#pragma warning( disable : 4100 ) + +int lfds610_stack_internal_freelist_init_function( void **user_data, void *user_state ) +{ + int + rv = 0; + + assert( user_data != NULL ); + assert( user_state == NULL ); + + *user_data = lfds610_liblfds_aligned_malloc( sizeof(struct lfds610_stack_element), LFDS610_ALIGN_DOUBLE_POINTER ); + + if( *user_data != NULL ) + rv = 1; + + return( rv ); +} + +#pragma warning( default : 4100 ) + + + + + +/****************************************************************************/ +void lfds610_stack_internal_new_element_from_freelist( struct lfds610_stack_state *ss, struct lfds610_stack_element *se[LFDS610_STACK_PAC_SIZE], void *user_data ) +{ + struct lfds610_freelist_element + *fe; + + assert( ss != NULL ); + assert( se != NULL ); + // TRD : user_data can be any value in its range + + lfds610_freelist_pop( ss->fs, &fe ); + + if( fe == NULL ) + se[LFDS610_STACK_POINTER] = NULL; + + if( fe != NULL ) + lfds610_stack_internal_init_element( ss, se, fe, user_data ); + + return; +} + + + + + +/****************************************************************************/ +void lfds610_stack_internal_new_element( struct lfds610_stack_state *ss, struct lfds610_stack_element *se[LFDS610_STACK_PAC_SIZE], void *user_data ) +{ + struct lfds610_freelist_element + *fe; + + assert( ss != NULL ); + assert( se != NULL ); + // TRD : user_data can be any value in its range + + lfds610_freelist_guaranteed_pop( ss->fs, &fe ); + + if( fe == NULL ) + se[LFDS610_STACK_POINTER] = NULL; + + if( fe != NULL ) + lfds610_stack_internal_init_element( ss, se, fe, user_data ); + + return; +} + + + + + +/****************************************************************************/ +void lfds610_stack_internal_init_element( struct lfds610_stack_state *ss, struct lfds610_stack_element *se[LFDS610_STACK_PAC_SIZE], struct lfds610_freelist_element *fe, void *user_data ) +{ + assert( ss != NULL ); + assert( se != NULL ); + assert( fe != NULL ); + // TRD : user_data can be any value in its range + + lfds610_freelist_get_user_data_from_element( fe, (void **) &se[LFDS610_STACK_POINTER] ); + + se[LFDS610_STACK_COUNTER] = (struct lfds610_stack_element *) lfds610_abstraction_increment( (lfds610_atom_t *) &ss->aba_counter ); + + se[LFDS610_STACK_POINTER]->next[LFDS610_STACK_POINTER] = NULL; + se[LFDS610_STACK_POINTER]->next[LFDS610_STACK_COUNTER] = 0; + se[LFDS610_STACK_POINTER]->fe = fe; + se[LFDS610_STACK_POINTER]->user_data = user_data; + + return; +} + diff --git a/liblfds/liblfds6.1.0/liblfds610/src/lfds610_stack/lfds610_stack_push_pop.c b/liblfds/liblfds6.1.0/liblfds610/src/lfds610_stack/lfds610_stack_push_pop.c new file mode 100644 index 0000000..01074b1 --- /dev/null +++ b/liblfds/liblfds6.1.0/liblfds610/src/lfds610_stack/lfds610_stack_push_pop.c @@ -0,0 +1,114 @@ +#include "lfds610_stack_internal.h" + + + + + +/****************************************************************************/ +int lfds610_stack_push( struct lfds610_stack_state *ss, void *user_data ) +{ + LFDS610_ALIGN(LFDS610_ALIGN_DOUBLE_POINTER) struct lfds610_stack_element + *se[LFDS610_STACK_PAC_SIZE]; + + assert( ss != NULL ); + // TRD : user_data can be NULL + + lfds610_stack_internal_new_element_from_freelist( ss, se, user_data ); + + if( se[LFDS610_STACK_POINTER] == NULL ) + return( 0 ); + + lfds610_stack_internal_push( ss, se ); + + return( 1 ); +} + + + + + +/****************************************************************************/ +int lfds610_stack_guaranteed_push( struct lfds610_stack_state *ss, void *user_data ) +{ + LFDS610_ALIGN(LFDS610_ALIGN_DOUBLE_POINTER) struct lfds610_stack_element + *se[LFDS610_STACK_PAC_SIZE]; + + assert( ss != NULL ); + // TRD : user_data can be NULL + + /* TRD : this function allocated a new lfds610_freelist element and uses that + to push onto the lfds610_stack, guaranteeing success (unless malloc() + fails of course) + */ + + lfds610_stack_internal_new_element( ss, se, user_data ); + + // TRD : malloc failed + if( se[LFDS610_STACK_POINTER] == NULL ) + return( 0 ); + + lfds610_stack_internal_push( ss, se ); + + return( 1 ); +} + + + + + +/****************************************************************************/ +void lfds610_stack_internal_push( struct lfds610_stack_state *ss, struct lfds610_stack_element *se[LFDS610_STACK_PAC_SIZE] ) +{ + LFDS610_ALIGN(LFDS610_ALIGN_DOUBLE_POINTER) struct lfds610_stack_element + *original_se_next[LFDS610_STACK_PAC_SIZE]; + + assert( ss != NULL ); + assert( se != NULL ); + + LFDS610_BARRIER_LOAD; + + original_se_next[LFDS610_STACK_POINTER] = ss->top[LFDS610_STACK_POINTER]; + original_se_next[LFDS610_STACK_COUNTER] = ss->top[LFDS610_STACK_COUNTER]; + + do + { + se[LFDS610_STACK_POINTER]->next[LFDS610_STACK_POINTER] = original_se_next[LFDS610_STACK_POINTER]; + se[LFDS610_STACK_POINTER]->next[LFDS610_STACK_COUNTER] = original_se_next[LFDS610_STACK_COUNTER]; + } + while( 0 == lfds610_abstraction_dcas((volatile lfds610_atom_t *) ss->top, (lfds610_atom_t *) se, (lfds610_atom_t *) original_se_next) ); + + return; +} + + + + + +/****************************************************************************/ +int lfds610_stack_pop( struct lfds610_stack_state *ss, void **user_data ) +{ + LFDS610_ALIGN(LFDS610_ALIGN_DOUBLE_POINTER) struct lfds610_stack_element + *se[LFDS610_STACK_PAC_SIZE]; + + assert( ss != NULL ); + assert( user_data != NULL ); + + LFDS610_BARRIER_LOAD; + + se[LFDS610_STACK_COUNTER] = ss->top[LFDS610_STACK_COUNTER]; + se[LFDS610_STACK_POINTER] = ss->top[LFDS610_STACK_POINTER]; + + do + { + if( se[LFDS610_STACK_POINTER] == NULL ) + return( 0 ); + } + while( 0 == lfds610_abstraction_dcas((volatile lfds610_atom_t *) ss->top, (lfds610_atom_t *) se[LFDS610_STACK_POINTER]->next, (lfds610_atom_t *) se) ); + + *user_data = se[LFDS610_STACK_POINTER]->user_data; + + lfds610_freelist_push( ss->fs, se[LFDS610_STACK_POINTER]->fe ); + + return( 1 ); +} + diff --git a/liblfds/liblfds6.1.0/liblfds610/src/lfds610_stack/lfds610_stack_query.c b/liblfds/liblfds6.1.0/liblfds610/src/lfds610_stack/lfds610_stack_query.c new file mode 100644 index 0000000..db53de2 --- /dev/null +++ b/liblfds/liblfds6.1.0/liblfds610/src/lfds610_stack/lfds610_stack_query.c @@ -0,0 +1,158 @@ +#include "lfds610_stack_internal.h" + + + + + +/****************************************************************************/ +void lfds610_stack_query( struct lfds610_stack_state *ss, enum lfds610_stack_query_type query_type, void *query_input, void *query_output ) +{ + assert( ss != NULL ); + // TRD : query_type can be any value in its range + // TRD : query_iput can be NULL + assert( query_output != NULL ); + + LFDS610_BARRIER_LOAD; + + switch( query_type ) + { + case LFDS610_STACK_QUERY_ELEMENT_COUNT: + assert( query_input == NULL ); + + lfds610_freelist_query( ss->fs, LFDS610_FREELIST_QUERY_ELEMENT_COUNT, NULL, query_output ); + break; + + case LFDS610_STACK_QUERY_VALIDATE: + // TRD : query_input can be NULL + + /* TRD : the validation info passed in is for the stack + it indicates the minimum and maximum number of elements + which should be present + + we need to validate the freelist + and validate the stack + + we cannot know the min/max for the freelist, given only + the min/max for the stack + */ + + lfds610_freelist_query( ss->fs, LFDS610_FREELIST_QUERY_VALIDATE, NULL, (enum lfds610_data_structure_validity *) query_output ); + + if( *(enum lfds610_data_structure_validity *) query_output == LFDS610_VALIDITY_VALID ) + lfds610_stack_internal_validate( ss, (struct lfds610_validation_info *) query_input, (enum lfds610_data_structure_validity *) query_output, ((enum lfds610_data_structure_validity *) query_output)+1 ); + break; + } + + return; +} + + + + + +/****************************************************************************/ +void lfds610_stack_internal_validate( struct lfds610_stack_state *ss, struct lfds610_validation_info *vi, enum lfds610_data_structure_validity *stack_validity, enum lfds610_data_structure_validity *freelist_validity ) +{ + struct lfds610_stack_element + *se, + *se_slow, + *se_fast; + + lfds610_atom_t + element_count = 0, + total_elements; + + struct lfds610_validation_info + freelist_vi; + + assert( ss != NULL ); + // TRD : vi can be NULL + assert( stack_validity != NULL ); + + *stack_validity = LFDS610_VALIDITY_VALID; + + se_slow = se_fast = (struct lfds610_stack_element *) ss->top[LFDS610_STACK_POINTER]; + + /* TRD : first, check for a loop + we have two pointers + both of which start at the top of the stack + we enter a loop + and on each iteration + we advance one pointer by one element + and the other by two + + we exit the loop when both pointers are NULL + (have reached the end of the stack) + + or + + if we fast pointer 'sees' the slow pointer + which means we have a loop + */ + + if( se_slow != NULL ) + do + { + se_slow = se_slow->next[LFDS610_STACK_POINTER]; + + if( se_fast != NULL ) + se_fast = se_fast->next[LFDS610_STACK_POINTER]; + + if( se_fast != NULL ) + se_fast = se_fast->next[LFDS610_STACK_POINTER]; + } + while( se_slow != NULL and se_fast != se_slow ); + + if( se_fast != NULL and se_slow != NULL and se_fast == se_slow ) + *stack_validity = LFDS610_VALIDITY_INVALID_LOOP; + + /* TRD : now check for expected number of elements + vi can be NULL, in which case we do not check + we know we don't have a loop from our earlier check + */ + + if( *stack_validity == LFDS610_VALIDITY_VALID and vi != NULL ) + { + se = (struct lfds610_stack_element *) ss->top[LFDS610_STACK_POINTER]; + + while( se != NULL ) + { + element_count++; + se = (struct lfds610_stack_element *) se->next[LFDS610_STACK_POINTER]; + } + + if( element_count < vi->min_elements ) + *stack_validity = LFDS610_VALIDITY_INVALID_MISSING_ELEMENTS; + + if( element_count > vi->max_elements ) + *stack_validity = LFDS610_VALIDITY_INVALID_ADDITIONAL_ELEMENTS; + } + + /* TRD : now we validate the freelist + + we may be able to check for the expected number of + elements in the freelist + + if the caller has given us an expected min and max + number of elements in the stack, then the total number + of elements in the freelist, minus that min and max, + gives us the expected number of elements in the + freelist + */ + + if( vi != NULL ) + { + lfds610_freelist_query( ss->fs, LFDS610_FREELIST_QUERY_ELEMENT_COUNT, NULL, (void *) &total_elements ); + + freelist_vi.min_elements = total_elements - vi->max_elements; + freelist_vi.max_elements = total_elements - vi->min_elements; + + lfds610_freelist_query( ss->fs, LFDS610_FREELIST_QUERY_VALIDATE, (void *) &freelist_vi, (void *) freelist_validity ); + } + + if( vi == NULL ) + lfds610_freelist_query( ss->fs, LFDS610_FREELIST_QUERY_VALIDATE, NULL, (void *) freelist_validity ); + + return; +} + diff --git a/liblfds/liblfds6.1.0/liblfds610/src/liblfds610_internal.h b/liblfds/liblfds6.1.0/liblfds610/src/liblfds610_internal.h new file mode 100644 index 0000000..bd01c11 --- /dev/null +++ b/liblfds/liblfds6.1.0/liblfds610/src/liblfds610_internal.h @@ -0,0 +1,25 @@ +/***** public prototypes *****/ +#include "liblfds610.h" + +/***** defines *****/ +#define and && +#define or || + +#define RAISED 1 +#define LOWERED 0 + +#define NO_FLAGS 0x0 + +/***** private prototypes *****/ +void *lfds610_liblfds_aligned_malloc( size_t size, size_t align_in_bytes ); +void lfds610_liblfds_aligned_free( void *memory ); + +static LFDS610_INLINE lfds610_atom_t lfds610_abstraction_cas( volatile lfds610_atom_t *destination, lfds610_atom_t exchange, lfds610_atom_t compare ); +static LFDS610_INLINE unsigned char lfds610_abstraction_dcas( volatile lfds610_atom_t *destination, lfds610_atom_t *exchange, lfds610_atom_t *compare ); +static LFDS610_INLINE lfds610_atom_t lfds610_abstraction_increment( volatile lfds610_atom_t *value ); + +/***** inlined code *****/ +#include "lfds610_abstraction/lfds610_abstraction_cas.c" +#include "lfds610_abstraction/lfds610_abstraction_dcas.c" +#include "lfds610_abstraction/lfds610_abstraction_increment.c" + diff --git a/liblfds/liblfds6.1.0/test/bin/empty_dir_placeholder_for_git b/liblfds/liblfds6.1.0/test/bin/empty_dir_placeholder_for_git new file mode 100644 index 0000000..e69de29 diff --git a/liblfds/liblfds6.1.0/test/building.txt b/liblfds/liblfds6.1.0/test/building.txt new file mode 100644 index 0000000..da49cd8 --- /dev/null +++ b/liblfds/liblfds6.1.0/test/building.txt @@ -0,0 +1,51 @@ +building test +============= + +Windows (user-mode) +=================== +1. Use Microsoft Visual Studio 2008 or Visual C++ 2008 Express Edition (or + later versions) to load "liblfds.sln". The "Win32" platform is x86, + the "x64" platform is x64. The test programme provides the "Release" + and "Debug" targets. The other targets ("Release DLL", "Release Lib", + "Debug DLL" and "Debug Lib") are carried over will-nilly from the liblds + library. + + All builds will work, but DLL builds will require the DLL from liblfds + to be placed into a location where the test executable can find it (e.g. + the same directory). + +2. Use Microsoft Windows SDK and GNUmake to run makefile.windows (obviously + you'll need to have run setenv.bat or the appropriate vcvars*.bat first; + you can build for x64/64-bit and x86/32-bit - just run the correct batch + file). + + If liblfds has been built as a DLL, the DLL from liblfds needs to be + placed into a location where the test executable can find it (e.g. the + same directory). + + Targets are "rel", "dbg" and "clean". You need to clean between switching + targets. + +Windows (kernel) +================ +No build supported, since this is a command line utility. + +Linux +===== +Use GNUmake to run "makefile.linux". Targets are "rel", "dbg" and +"clean". You need to clean between switching targets. + +If liblfds has been built as a shared object, the shared object file from +liblfds will need to be placed somewhere the text executable can find it. + +A convenient solution is to place the shared object file in the same +directory as the text executable and set the environment variable +"LD_LIBRARY_PATH" to ".", e.g. in bash; + +export LD_LIBRARY_PATH=. + +Remember to unset after finishing testing, or your system will continue +to scan the current directory for shared object files. + +unset LD_LIBRARY_PATH + diff --git a/liblfds/liblfds6.1.0/test/makefile.linux b/liblfds/liblfds6.1.0/test/makefile.linux new file mode 100644 index 0000000..61fce5c --- /dev/null +++ b/liblfds/liblfds6.1.0/test/makefile.linux @@ -0,0 +1,82 @@ +##### paths ##### +BINDIR = bin +INCDIR = ../liblfds610/inc +LIBDIR = ../liblfds610/bin +OBJDIR = obj +SRCDIR = src + +##### misc ##### +QUIETLY = 1>nul 2>nul + +##### sources, objects and libraries ##### +BINNAME = test +BINARY = $(BINDIR)/$(BINNAME) +SRCDIRS = . +SOURCES = abstraction_cpu_count.c test_abstraction.c abstraction_thread_start.c abstraction_thread_wait.c benchmark_freelist.c benchmark_queue.c benchmark_ringbuffer.c benchmark_stack.c test_freelist.c main.c misc.c test_queue.c test_ringbuffer.c test_slist.c test_stack.c +OBJECTS = $(patsubst %.c,$(OBJDIR)/%.o,$(notdir $(SOURCES))) +SYSLIBS = -lpthread -lc -lm +USRLIBS = -llfds610 + +##### CPU variants ##### +UNAME = $(shell uname -m) +GCCARCH = -march=$(UNAME) + +ifeq ($(UNAME),x86_64) + GCCARCH = -march=core2 +endif + +ifeq ($(findstring arm,$(UNAME)),arm) + GCCARCH = -march=armv6k -marm +endif + +##### tools ##### +MAKE = make +MFLAGS = + +DG = gcc +DGFLAGS = -MM -std=c99 -I"$(SRCDIR)" -I"$(INCDIR)" + +CC = gcc +CFBASE = -Wall -Wno-unknown-pragmas -std=c99 $(GCCARCH) -pthread -c -I"$(SRCDIR)" -I"$(INCDIR)" +CFREL = -O2 -Wno-strict-aliasing +CFDBG = -O0 -g + +LD = gcc +LFBASE = -L"$(LIBDIR)" +LFREL = -O2 -s +LFDBG = -O0 -g + +##### variants ##### +CFLAGS = $(CFBASE) $(CFDBG) +LFLAGS = $(LFBASE) $(LFDBG) + +ifeq ($(MAKECMDGOALS),rel) + CFLAGS = $(CFBASE) $(CFREL) + LFLAGS = $(LFBASE) $(LFREL) +endif + +##### search paths ##### +vpath %.c $(patsubst %,$(SRCDIR)/%:,$(SRCDIRS)) + +##### implicit rules ##### +$(OBJDIR)/%.o : %.c + $(DG) $(DGFLAGS) $< >$(OBJDIR)/$*.d + $(CC) $(CFLAGS) -o $@ $< + +##### explicit rules ##### +$(BINARY) : $(OBJECTS) + $(LD) -o $(BINARY) $(LFLAGS) $(OBJECTS) $(USRLIBS) $(SYSLIBS) + chmod +x $(BINARY) + +##### phony ##### +.PHONY : clean rel dbg + +clean : + @rm -f $(BINDIR)/$(BINNAME) $(OBJDIR)/*.o $(OBJDIR)/*.d + +rel : $(BINARY) +dbg : $(BINARY) + +##### dependencies ##### +-include $(DEPENDS) + diff --git a/liblfds/liblfds6.1.0/test/makefile.windows b/liblfds/liblfds6.1.0/test/makefile.windows new file mode 100644 index 0000000..beb5fc3 --- /dev/null +++ b/liblfds/liblfds6.1.0/test/makefile.windows @@ -0,0 +1,64 @@ +##### paths ##### +BINDIR = bin +INCDIR = ../liblfds610/inc +LIBDIR = ../liblfds610/bin +OBJDIR = obj +SRCDIR = src + +##### misc ##### +QUIETLY = 1>nul 2>nul + +##### sources, objects and libraries ##### +BINNAME = test +BINARY = $(BINDIR)\$(BINNAME).exe +SRCDIRS = . +SOURCES = abstraction_cpu_count.c test_abstraction.c abstraction_thread_start.c abstraction_thread_wait.c benchmark_freelist.c benchmark_queue.c benchmark_ringbuffer.c benchmark_stack.c test_freelist.c main.c misc.c test_queue.c test_ringbuffer.c test_slist.c test_stack.c +OBJECTS = $(patsubst %.c,$(OBJDIR)/%.obj,$(notdir $(SOURCES))) +SYSLIBS = kernel32.lib +USRLIBS = liblfds610.lib + +##### tools ##### +MAKE = make +MFLAGS = + +CC = cl +CFBASE = /nologo /W4 /WX /c "-I$(SRCDIR)" "-I$(INCLUDE)" "-I$(INCDIR)" "/Fd$(BINDIR)\$(BINNAME).pdb" /D UNICODE /D _UNICODE /DWIN32_LEAN_AND_MEAN /D_CRT_SECURE_NO_WARNINGS +CFREL = /Ox /DNDEBUG /MT +CFDBG = /Od /Gm /Zi /D_DEBUG /MTd + +LD = link +LFBASE = "/libpath:$(LIB)" "/libpath:$(LIBDIR)" /nologo /subsystem:console /nodefaultlib /nxcompat /wx +LFREL = /incremental:no +LFDBG = /debug "/pdb:$(BINDIR)\$(BINNAME).pdb" + +##### variants ##### +CFLAGS = $(CFBASE) $(CFDBG) +LFLAGS = $(LFBASE) $(LFDBG) +CLIB = libcmtd.lib + +ifeq ($(MAKECMDGOALS),rel) + CFLAGS = $(CFBASE) $(CFREL) + LFLAGS = $(LFBASE) $(LFREL) + CLIB = libcmt.lib +endif + +##### search paths ##### +vpath %.c $(patsubst %,$(SRCDIR)/%;,$(SRCDIRS)) + +##### implicit rules ##### +$(OBJDIR)/%.obj : %.c + $(CC) $(CFLAGS) "/Fo$@" $< + +##### explicit rules ##### +$(BINARY) : $(OBJECTS) + $(LD) $(LFLAGS) $(CLIB) $(SYSLIBS) $(USRLIBS) $(OBJECTS) /out:$(BINARY) + +##### phony ##### +.PHONY : clean rel dbg + +clean : + @erase /Q $(OBJDIR)\*.obj $(BINDIR)\$(BINNAME).* $(QUIETLY) + +rel : $(BINARY) +dbg : $(BINARY) + diff --git a/liblfds/liblfds6.1.0/test/obj/empty_dir_placeholder_for_git b/liblfds/liblfds6.1.0/test/obj/empty_dir_placeholder_for_git new file mode 100644 index 0000000..e69de29 diff --git a/liblfds/liblfds6.1.0/test/src/abstraction.h b/liblfds/liblfds6.1.0/test/src/abstraction.h new file mode 100644 index 0000000..2978bd4 --- /dev/null +++ b/liblfds/liblfds6.1.0/test/src/abstraction.h @@ -0,0 +1,50 @@ +/***** defines *****/ +#if (defined _WIN32 && defined _MSC_VER && !defined WIN_KERNEL_BUILD) + /* TRD : any Windows (user-mode) on any CPU with the Microsoft C compiler + + _WIN32 indicates 64-bit or 32-bit Windows + _MSC_VER indicates Microsoft C compiler + !WIN_KERNEL_BUILD indicates Windows user-mode + */ + + #include + typedef HANDLE thread_state_t; + typedef DWORD thread_return_t; + #define CALLING_CONVENTION WINAPI +#endif + +#if (defined _WIN32 && defined _MSC_VER && defined WIN_KERNEL_BUILD) + /* TRD : any Windows (kernel-mode) on any CPU with the Microsoft C compiler + + _WIN32 indicates 64-bit or 32-bit Windows + _MSC_VER indicates Microsoft C compiler + WIN_KERNEL_BUILD indicates Windows kernel + */ + + #include + typedef HANDLE thread_state_t; + typedef VOID thread_return_t; + #define CALLING_CONVENTION +#endif + +#if (defined __unix__ && defined __GNUC__) + /* TRD : any UNIX on any CPU with GCC + + __unix__ indicates Solaris, Linux, HPUX, etc + __GNUC__ indicates GCC + */ + #include + #include + #include + typedef pthread_t thread_state_t; + typedef void * thread_return_t; + #define CALLING_CONVENTION +#endif + +typedef thread_return_t (CALLING_CONVENTION *thread_function_t)( void *thread_user_state ); + +/***** public prototypes *****/ +unsigned int abstraction_cpu_count( void ); +int abstraction_thread_start( thread_state_t *thread_state, unsigned int cpu, thread_function_t thread_function, void *thread_user_state ); +void abstraction_thread_wait( thread_state_t thread_state ); + diff --git a/liblfds/liblfds6.1.0/test/src/abstraction_cpu_count.c b/liblfds/liblfds6.1.0/test/src/abstraction_cpu_count.c new file mode 100644 index 0000000..370cacf --- /dev/null +++ b/liblfds/liblfds6.1.0/test/src/abstraction_cpu_count.c @@ -0,0 +1,81 @@ +#include "internal.h" + + + + + +/****************************************************************************/ +#if (defined _WIN32 && defined _MSC_VER && !defined WIN_KERNEL_BUILD) + + /* TRD : any Windows (user-mode) on any CPU with the Microsoft C compiler + + _WIN32 indicates 64-bit or 32-bit Windows + _MSC_VER indicates Microsoft C compiler + !WIN_KERNEL_BUILD indicates Windows user-mode + */ + + unsigned int abstraction_cpu_count() + { + SYSTEM_INFO + si; + + GetNativeSystemInfo( &si ); + + return( (unsigned int) si.dwNumberOfProcessors ); + } + +#endif + + + + + +/****************************************************************************/ +#if (defined _WIN32 && defined _MSC_VER && defined WIN_KERNEL_BUILD) + + /* TRD : any Windows on any CPU with the Microsoft C compiler + + _WIN32 indicates 64-bit or 32-bit Windows + _MSC_VER indicates Microsoft C compiler + WIN_KERNEL_BUILD indicates Windows kernel + */ + + unsigned int abstraction_cpu_count() + { + unsigned int + active_processor_count; + + active_processor_count = KeQueryActiveProcessorCount( NULL ); + + return( active_processor_count ); + } + +#endif + + + + + +/****************************************************************************/ +#if (defined __linux__ && defined __GNUC__) + + /* TRD : Linux on any CPU with GCC + + this function I believe is Linux specific and varies by UNIX flavour + + __linux__ indicates Linux + __GNUC__ indicates GCC + */ + + unsigned int abstraction_cpu_count() + { + long int + cpu_count; + + cpu_count = sysconf( _SC_NPROCESSORS_ONLN ); + + return( (unsigned int) cpu_count ); + } + +#endif + diff --git a/liblfds/liblfds6.1.0/test/src/abstraction_thread_start.c b/liblfds/liblfds6.1.0/test/src/abstraction_thread_start.c new file mode 100644 index 0000000..6333c46 --- /dev/null +++ b/liblfds/liblfds6.1.0/test/src/abstraction_thread_start.c @@ -0,0 +1,141 @@ +#include "internal.h" + + + + + +/****************************************************************************/ +#if (defined _WIN32 && defined _MSC_VER && !defined WIN_KERNEL_BUILD) + + /* TRD : any Windows (user-mode) on any CPU with the Microsoft C compiler + + _WIN32 indicates 64-bit or 32-bit Windows + _MSC_VER indicates Microsoft C compiler + !WIN_KERNEL_BUILD indicates Windows user-mode + */ + + int abstraction_thread_start( thread_state_t *thread_state, unsigned int cpu, thread_function_t thread_function, void *thread_user_state ) + { + int + rv = 0; + + DWORD + thread_id; + + DWORD_PTR + affinity_mask, + result; + + assert( thread_state != NULL ); + // TRD : cpu can be any value in its range + assert( thread_function != NULL ); + // TRD : thread_user_state can be NULL + + affinity_mask = (DWORD_PTR) (1 << cpu); + + *thread_state = CreateThread( NULL, 0, thread_function, thread_user_state, NO_FLAGS, &thread_id ); + + result = SetThreadAffinityMask( *thread_state, affinity_mask ); + + if( *thread_state != NULL and result != 0 ) + rv = 1; + + return( rv ); + } + +#endif + + + + + +/****************************************************************************/ +#if (defined _WIN32 && defined _MSC_VER && defined WIN_KERNEL_BUILD) + + /* TRD : any Windows on any CPU with the Microsoft C compiler + + _WIN32 indicates 64-bit or 32-bit Windows + _MSC_VER indicates Microsoft C compiler + WIN_KERNEL_BUILD indicates Windows kernel + */ + + int abstraction_thread_start( thread_state_t *thread_state, unsigned int cpu, thread_function_t thread_function, void *thread_user_state ) + { + int + rv = 0; + + KAFFINITY + affinity_mask + + NTSTATUS + nts_create, + nts_affinity; + + assert( thread_state != NULL ); + // TRD : cpu can be any value in its range + assert( thread_function != NULL ); + // TRD : thread_user_state can be NULL + + affinity_mask = 1 << cpu; + + nts_create = PsCreateSystemThread( thread_state, THREAD_ALL_ACCESS, NULL, NULL, NULL, thread_function, thread_user_state ); + + nts_affinity = ZwSetInformationThread( thread_state, ThreadAffinityMask, &affinity_mask, sizeof(KAFFINITY) ); + + if( nts_create == STATUS_SUCCESS and nts_affinity == STATUS_SUCCESS ) + rv = 1; + + return( rv ); + } + +#endif + + + + + +/****************************************************************************/ +#if (defined __unix__) + + /* TRD : any UNIX on any CPU with any compiler + + I assumed pthreads is available on any UNIX. + + __unix__ indicates Solaris, Linux, HPUX, etc + */ + + int abstraction_thread_start( thread_state_t *thread_state, unsigned int cpu, thread_function_t thread_function, void *thread_user_state ) + { + int + rv = 0, + rv_create; + + pthread_attr_t + attr; + + cpu_set_t + cpuset; + + assert( thread_state != NULL ); + // TRD : cpu can be any value in its range + assert( thread_function != NULL ); + // TRD : thread_user_state can be NULL + + pthread_attr_init( &attr ); + + CPU_ZERO( &cpuset ); + CPU_SET( cpu, &cpuset ); + pthread_attr_setaffinity_np( &attr, sizeof(cpuset), &cpuset ); + + rv_create = pthread_create( thread_state, &attr, thread_function, thread_user_state ); + + if( rv_create == 0 ) + rv = 1; + + pthread_attr_destroy( &attr ); + + return( rv ); + } + +#endif + diff --git a/liblfds/liblfds6.1.0/test/src/abstraction_thread_wait.c b/liblfds/liblfds6.1.0/test/src/abstraction_thread_wait.c new file mode 100644 index 0000000..ced5a5e --- /dev/null +++ b/liblfds/liblfds6.1.0/test/src/abstraction_thread_wait.c @@ -0,0 +1,71 @@ +#include "internal.h" + + + + + +/****************************************************************************/ +#if (defined _WIN32 && defined _MSC_VER && !defined WIN_KERNEL_BUILD) + + /* TRD : any Windows (user-mode) on any CPU with the Microsoft C compiler + + _WIN32 indicates 64-bit or 32-bit Windows + _MSC_VER indicates Microsoft C compiler + !WIN_KERNEL_BUILD indicates Windows user-mode + */ + + void abstraction_thread_wait( thread_state_t thread_state ) + { + WaitForSingleObject( thread_state, INFINITE ); + + return; + } + +#endif + + + + + +/****************************************************************************/ +#if (defined _WIN32 && defined _MSC_VER && defined WIN_KERNEL_BUILD) + + /* TRD : any Windows on any CPU with the Microsoft C compiler + + _WIN32 indicates 64-bit or 32-bit Windows + _MSC_VER indicates Microsoft C compiler + WIN_KERNEL_BUILD indicates Windows kernel + */ + + void abstraction_thread_wait( thread_state_t thread_state ) + { + KeWaitForSingleObject( thread_state, Executive, KernelMode, FALSE, NULL ); + + return; + } + +#endif + + + + + +/****************************************************************************/ +#if (defined __unix__) + + /* TRD : any UNIX on any CPU with any compiler + + I assumed pthreads is available on any UNIX. + + __unix__ indicates Solaris, Linux, HPUX, etc + */ + + void abstraction_thread_wait( thread_state_t thread_state ) + { + pthread_join( thread_state, NULL ); + + return; + } + +#endif + diff --git a/liblfds/liblfds6.1.0/test/src/benchmark_freelist.c b/liblfds/liblfds6.1.0/test/src/benchmark_freelist.c new file mode 100644 index 0000000..0ada751 --- /dev/null +++ b/liblfds/liblfds6.1.0/test/src/benchmark_freelist.c @@ -0,0 +1,138 @@ +#include "internal.h" + + + + + +/****************************************************************************/ +void benchmark_lfds610_freelist( void ) +{ + unsigned int + loop, + thread_count, + cpu_count; + + struct lfds610_freelist_state + *fs; + + struct lfds610_freelist_benchmark + *fb; + + thread_state_t + *thread_handles; + + lfds610_atom_t + total_operations_for_full_test_for_all_cpus, + total_operations_for_full_test_for_all_cpus_for_one_cpu = 0; + + double + mean_operations_per_second_per_cpu, + difference_per_second_per_cpu, + total_difference_per_second_per_cpu, + std_dev_per_second_per_cpu, + scalability; + + /* TRD : here we benchmark the freelist + + the benchmark is to have a single freelist + where a worker thread busy-works popping and then pushing + */ + + cpu_count = abstraction_cpu_count(); + + thread_handles = (thread_state_t *) malloc( sizeof(thread_state_t) * cpu_count ); + + fb = (struct lfds610_freelist_benchmark *) malloc( sizeof(struct lfds610_freelist_benchmark) * cpu_count ); + + // TRD : print the benchmark ID and CSV header + printf( "\n" + "Release %s Freelist Benchmark #1\n" + "CPUs,total ops,mean ops/sec per CPU,standard deviation,scalability\n", LFDS610_RELEASE_NUMBER_STRING ); + + // TRD : we run CPU count times for scalability + for( thread_count = 1 ; thread_count <= cpu_count ; thread_count++ ) + { + // TRD : initialisation + lfds610_freelist_new( &fs, 1000, NULL, NULL ); + + for( loop = 0 ; loop < cpu_count ; loop++ ) + { + (fb+loop)->fs = fs; + (fb+loop)->operation_count = 0; + } + + // TRD : main test + for( loop = 0 ; loop < thread_count ; loop++ ) + abstraction_thread_start( &thread_handles[loop], loop, benchmark_lfds610_freelist_thread_pop_and_push, fb+loop ); + + for( loop = 0 ; loop < thread_count ; loop++ ) + abstraction_thread_wait( thread_handles[loop] ); + + // TRD : post test math + total_operations_for_full_test_for_all_cpus = 0; + total_difference_per_second_per_cpu = 0; + + for( loop = 0 ; loop < thread_count ; loop++ ) + total_operations_for_full_test_for_all_cpus += (fb+loop)->operation_count; + + mean_operations_per_second_per_cpu = ((double) total_operations_for_full_test_for_all_cpus / (double) thread_count) / (double) 10; + + if( thread_count == 1 ) + total_operations_for_full_test_for_all_cpus_for_one_cpu = total_operations_for_full_test_for_all_cpus; + + for( loop = 0 ; loop < thread_count ; loop++ ) + { + difference_per_second_per_cpu = ((double) (fb+loop)->operation_count / (double) 10) - mean_operations_per_second_per_cpu; + total_difference_per_second_per_cpu += difference_per_second_per_cpu * difference_per_second_per_cpu; + } + + std_dev_per_second_per_cpu = sqrt( (double) total_difference_per_second_per_cpu ); + + scalability = (double) total_operations_for_full_test_for_all_cpus / (double) (total_operations_for_full_test_for_all_cpus_for_one_cpu * thread_count); + + printf( "%u,%u,%.0f,%.0f,%0.2f\n", thread_count, (unsigned int) total_operations_for_full_test_for_all_cpus, mean_operations_per_second_per_cpu, std_dev_per_second_per_cpu, scalability ); + + // TRD : cleanup + lfds610_freelist_delete( fs, NULL, NULL ); + } + + free( fb ); + + free( thread_handles ); + + return; +} + + + + + +/****************************************************************************/ +thread_return_t CALLING_CONVENTION benchmark_lfds610_freelist_thread_pop_and_push( void *freelist_benchmark ) +{ + struct lfds610_freelist_benchmark + *fb; + + struct lfds610_freelist_element + *fe; + + time_t + start_time; + + assert( freelist_benchmark != NULL ); + + fb = (struct lfds610_freelist_benchmark *) freelist_benchmark; + + time( &start_time ); + + while( time(NULL) < start_time + 10 ) + { + lfds610_freelist_pop( fb->fs, &fe ); + lfds610_freelist_push( fb->fs, fe ); + + fb->operation_count += 2; + } + + return( (thread_return_t) EXIT_SUCCESS ); +} + diff --git a/liblfds/liblfds6.1.0/test/src/benchmark_queue.c b/liblfds/liblfds6.1.0/test/src/benchmark_queue.c new file mode 100644 index 0000000..9194fcc --- /dev/null +++ b/liblfds/liblfds6.1.0/test/src/benchmark_queue.c @@ -0,0 +1,142 @@ +#include "internal.h" + + + + + +/****************************************************************************/ +void benchmark_lfds610_queue( void ) +{ + unsigned int + loop, + thread_count, + cpu_count; + + struct lfds610_queue_state + *qs; + + struct lfds610_queue_benchmark + *qb; + + thread_state_t + *thread_handles; + + lfds610_atom_t + total_operations_for_full_test_for_all_cpus, + total_operations_for_full_test_for_all_cpus_for_one_cpu = 0; + + double + mean_operations_per_second_per_cpu, + difference_per_second_per_cpu, + total_difference_per_second_per_cpu, + std_dev_per_second_per_cpu, + scalability; + + /* TRD : here we benchmark the queue + + the benchmark is to have a single queue + where a worker thread busy-works dequeuing and then queuing + */ + + cpu_count = abstraction_cpu_count(); + + thread_handles = (thread_state_t *) malloc( sizeof(thread_state_t) * cpu_count ); + + qb = (struct lfds610_queue_benchmark *) malloc( sizeof(struct lfds610_queue_benchmark) * cpu_count ); + + // TRD : print the benchmark ID and CSV header + printf( "\n" + "Release %s Queue Benchmark #1\n" + "CPUs,total ops,mean ops/sec per CPU,standard deviation,scalability\n", LFDS610_RELEASE_NUMBER_STRING ); + + // TRD : we run CPU count times for scalability + for( thread_count = 1 ; thread_count <= cpu_count ; thread_count++ ) + { + // TRD : initialisation + lfds610_queue_new( &qs, 1000 ); + + for( loop = 0 ; loop < cpu_count ; loop++ ) + { + (qb+loop)->qs = qs; + (qb+loop)->operation_count = 0; + } + + // TRD : populate the queue (we don't actually use the user data) + for( loop = 0 ; loop < 500 ; loop++ ) + lfds610_queue_enqueue( qs, (void *) (lfds610_atom_t) loop ); + + // TRD : main test + for( loop = 0 ; loop < thread_count ; loop++ ) + abstraction_thread_start( &thread_handles[loop], loop, benchmark_lfds610_queue_thread_delfds610_queue_and_enqueue, qb+loop ); + + for( loop = 0 ; loop < thread_count ; loop++ ) + abstraction_thread_wait( thread_handles[loop] ); + + // TRD : post test math + total_operations_for_full_test_for_all_cpus = 0; + total_difference_per_second_per_cpu = 0; + + for( loop = 0 ; loop < thread_count ; loop++ ) + total_operations_for_full_test_for_all_cpus += (qb+loop)->operation_count; + + mean_operations_per_second_per_cpu = ((double) total_operations_for_full_test_for_all_cpus / (double) thread_count) / (double) 10; + + if( thread_count == 1 ) + total_operations_for_full_test_for_all_cpus_for_one_cpu = total_operations_for_full_test_for_all_cpus; + + for( loop = 0 ; loop < thread_count ; loop++ ) + { + difference_per_second_per_cpu = ((double) (qb+loop)->operation_count / (double) 10) - mean_operations_per_second_per_cpu; + total_difference_per_second_per_cpu += difference_per_second_per_cpu * difference_per_second_per_cpu; + } + + std_dev_per_second_per_cpu = sqrt( (double) total_difference_per_second_per_cpu ); + + scalability = (double) total_operations_for_full_test_for_all_cpus / (double) (total_operations_for_full_test_for_all_cpus_for_one_cpu * thread_count); + + printf( "%u,%u,%.0f,%.0f,%0.2f\n", thread_count, (unsigned int) total_operations_for_full_test_for_all_cpus, mean_operations_per_second_per_cpu, std_dev_per_second_per_cpu, scalability ); + + // TRD : cleanup + lfds610_queue_delete( qs, NULL, NULL ); + } + + free( qb ); + + free( thread_handles ); + + return; +} + + + + + +/****************************************************************************/ +thread_return_t CALLING_CONVENTION benchmark_lfds610_queue_thread_delfds610_queue_and_enqueue( void *queue_benchmark ) +{ + struct lfds610_queue_benchmark + *qb; + + void + *user_data; + + time_t + start_time; + + assert( queue_benchmark != NULL ); + + qb = (struct lfds610_queue_benchmark *) queue_benchmark; + + time( &start_time ); + + while( time(NULL) < start_time + 10 ) + { + lfds610_queue_dequeue( qb->qs, &user_data ); + lfds610_queue_enqueue( qb->qs, user_data ); + + qb->operation_count += 2; + } + + return( (thread_return_t) EXIT_SUCCESS ); +} + diff --git a/liblfds/liblfds6.1.0/test/src/benchmark_ringbuffer.c b/liblfds/liblfds6.1.0/test/src/benchmark_ringbuffer.c new file mode 100644 index 0000000..aff5912 --- /dev/null +++ b/liblfds/liblfds6.1.0/test/src/benchmark_ringbuffer.c @@ -0,0 +1,141 @@ +#include "internal.h" + + + + + +/****************************************************************************/ +void benchmark_lfds610_ringbuffer( void ) +{ + unsigned int + loop, + thread_count, + cpu_count; + + struct lfds610_ringbuffer_state + *rs; + + struct lfds610_ringbuffer_benchmark + *rb; + + thread_state_t + *thread_handles; + + lfds610_atom_t + total_operations_for_full_test_for_all_cpus, + total_operations_for_full_test_for_all_cpus_for_one_cpu = 0; + + double + mean_operations_per_second_per_cpu, + difference_per_second_per_cpu, + total_difference_per_second_per_cpu, + std_dev_per_second_per_cpu, + scalability; + + /* TRD : here we benchmark the ringbuffer + + the benchmark is to have a single ringbuffer + where a worker thread busy-works writing and then reading + */ + + cpu_count = abstraction_cpu_count(); + + thread_handles = (thread_state_t *) malloc( sizeof(thread_state_t) * cpu_count ); + + rb = (struct lfds610_ringbuffer_benchmark *) malloc( sizeof(struct lfds610_ringbuffer_benchmark) * cpu_count ); + + // TRD : print the benchmark ID and CSV header + printf( "\n" + "Release %s Ringbuffer Benchmark #1\n" + "CPUs,total ops,mean ops/sec per CPU,standard deviation,scalability\n", LFDS610_RELEASE_NUMBER_STRING ); + + // TRD : we run CPU count times for scalability + for( thread_count = 1 ; thread_count <= cpu_count ; thread_count++ ) + { + // TRD : initialisation + lfds610_ringbuffer_new( &rs, 1000, NULL, NULL ); + + for( loop = 0 ; loop < cpu_count ; loop++ ) + { + (rb+loop)->rs = rs; + (rb+loop)->operation_count = 0; + } + + // TRD : main test + for( loop = 0 ; loop < thread_count ; loop++ ) + abstraction_thread_start( &thread_handles[loop], loop, benchmark_lfds610_ringbuffer_thread_write_and_read, rb+loop ); + + for( loop = 0 ; loop < thread_count ; loop++ ) + abstraction_thread_wait( thread_handles[loop] ); + + // TRD : post test math + total_operations_for_full_test_for_all_cpus = 0; + total_difference_per_second_per_cpu = 0; + + for( loop = 0 ; loop < thread_count ; loop++ ) + total_operations_for_full_test_for_all_cpus += (rb+loop)->operation_count; + + mean_operations_per_second_per_cpu = ((double) total_operations_for_full_test_for_all_cpus / (double) thread_count) / (double) 10; + + if( thread_count == 1 ) + total_operations_for_full_test_for_all_cpus_for_one_cpu = total_operations_for_full_test_for_all_cpus; + + for( loop = 0 ; loop < thread_count ; loop++ ) + { + difference_per_second_per_cpu = ((double) (rb+loop)->operation_count / (double) 10) - mean_operations_per_second_per_cpu; + total_difference_per_second_per_cpu += difference_per_second_per_cpu * difference_per_second_per_cpu; + } + + std_dev_per_second_per_cpu = sqrt( (double) total_difference_per_second_per_cpu ); + + scalability = (double) total_operations_for_full_test_for_all_cpus / (double) (total_operations_for_full_test_for_all_cpus_for_one_cpu * thread_count); + + printf( "%u,%u,%.0f,%.0f,%0.2f\n", thread_count, (unsigned int) total_operations_for_full_test_for_all_cpus, mean_operations_per_second_per_cpu, std_dev_per_second_per_cpu, scalability ); + + // TRD : cleanup + lfds610_ringbuffer_delete( rs, NULL, NULL ); + } + + free( rb ); + + free( thread_handles ); + + return; +} + + + + + +/****************************************************************************/ +thread_return_t CALLING_CONVENTION benchmark_lfds610_ringbuffer_thread_write_and_read( void *ringbuffer_benchmark ) +{ + struct lfds610_ringbuffer_benchmark + *rb; + + struct lfds610_freelist_element + *fe; + + time_t + start_time; + + assert( ringbuffer_benchmark != NULL ); + + rb = (struct lfds610_ringbuffer_benchmark *) ringbuffer_benchmark; + + time( &start_time ); + + while( time(NULL) < start_time + 10 ) + { + lfds610_ringbuffer_get_write_element( rb->rs, &fe, NULL ); + lfds610_ringbuffer_put_write_element( rb->rs, fe ); + + lfds610_ringbuffer_get_read_element( rb->rs, &fe ); + lfds610_ringbuffer_put_read_element( rb->rs, fe ); + + rb->operation_count += 2; + } + + return( (thread_return_t) EXIT_SUCCESS ); +} + diff --git a/liblfds/liblfds6.1.0/test/src/benchmark_stack.c b/liblfds/liblfds6.1.0/test/src/benchmark_stack.c new file mode 100644 index 0000000..92754ca --- /dev/null +++ b/liblfds/liblfds6.1.0/test/src/benchmark_stack.c @@ -0,0 +1,138 @@ +#include "internal.h" + + + + + +/****************************************************************************/ +void benchmark_lfds610_stack( void ) +{ + unsigned int + loop, + thread_count, + cpu_count; + + struct lfds610_stack_state + *ss; + + struct lfds610_stack_benchmark + *sb; + + thread_state_t + *thread_handles; + + lfds610_atom_t + total_operations_for_full_test_for_all_cpus, + total_operations_for_full_test_for_all_cpus_for_one_cpu = 0; + + double + mean_operations_per_second_per_cpu, + difference_per_second_per_cpu, + total_difference_per_second_per_cpu, + std_dev_per_second_per_cpu, + scalability; + + /* TRD : here we benchmark the stack + + the benchmark is to have a single stack + where a worker thread busy-works pushing then popping + */ + + cpu_count = abstraction_cpu_count(); + + thread_handles = (thread_state_t *) malloc( sizeof(thread_state_t) * cpu_count ); + + sb = (struct lfds610_stack_benchmark *) malloc( sizeof(struct lfds610_stack_benchmark) * cpu_count ); + + // TRD : print the benchmark ID and CSV header + printf( "\n" + "Release %s Stack Benchmark #1\n" + "CPUs,total ops,mean ops/sec per CPU,standard deviation,scalability\n", LFDS610_RELEASE_NUMBER_STRING ); + + // TRD : we run CPU count times for scalability + for( thread_count = 1 ; thread_count <= cpu_count ; thread_count++ ) + { + // TRD : initialisation + lfds610_stack_new( &ss, 1000 ); + + for( loop = 0 ; loop < cpu_count ; loop++ ) + { + (sb+loop)->ss = ss; + (sb+loop)->operation_count = 0; + } + + // TRD : main test + for( loop = 0 ; loop < thread_count ; loop++ ) + abstraction_thread_start( &thread_handles[loop], loop, benchmark_lfds610_stack_thread_push_and_pop, sb+loop ); + + for( loop = 0 ; loop < thread_count ; loop++ ) + abstraction_thread_wait( thread_handles[loop] ); + + // TRD : post test math + total_operations_for_full_test_for_all_cpus = 0; + total_difference_per_second_per_cpu = 0; + + for( loop = 0 ; loop < thread_count ; loop++ ) + total_operations_for_full_test_for_all_cpus += (sb+loop)->operation_count; + + mean_operations_per_second_per_cpu = ((double) total_operations_for_full_test_for_all_cpus / (double) thread_count) / (double) 10; + + if( thread_count == 1 ) + total_operations_for_full_test_for_all_cpus_for_one_cpu = total_operations_for_full_test_for_all_cpus; + + for( loop = 0 ; loop < thread_count ; loop++ ) + { + difference_per_second_per_cpu = ((double) (sb+loop)->operation_count / (double) 10) - mean_operations_per_second_per_cpu; + total_difference_per_second_per_cpu += difference_per_second_per_cpu * difference_per_second_per_cpu; + } + + std_dev_per_second_per_cpu = sqrt( (double) total_difference_per_second_per_cpu ); + + scalability = (double) total_operations_for_full_test_for_all_cpus / (double) (total_operations_for_full_test_for_all_cpus_for_one_cpu * thread_count); + + printf( "%u,%u,%.0f,%.0f,%0.2f\n", thread_count, (unsigned int) total_operations_for_full_test_for_all_cpus, mean_operations_per_second_per_cpu, std_dev_per_second_per_cpu, scalability ); + + // TRD : cleanup + lfds610_stack_delete( ss, NULL, NULL ); + } + + free( sb ); + + free( thread_handles ); + + return; +} + + + + + +/****************************************************************************/ +thread_return_t CALLING_CONVENTION benchmark_lfds610_stack_thread_push_and_pop( void *stack_benchmark ) +{ + struct lfds610_stack_benchmark + *sb; + + void + *user_data = NULL; + + time_t + start_time; + + assert( stack_benchmark != NULL ); + + sb = (struct lfds610_stack_benchmark *) stack_benchmark; + + time( &start_time ); + + while( time(NULL) < start_time + 10 ) + { + lfds610_stack_push( sb->ss, user_data ); + lfds610_stack_pop( sb->ss, &user_data ); + + sb->operation_count += 2; + } + + return( (thread_return_t) EXIT_SUCCESS ); +} + diff --git a/liblfds/liblfds6.1.0/test/src/internal.h b/liblfds/liblfds6.1.0/test/src/internal.h new file mode 100644 index 0000000..81e22d0 --- /dev/null +++ b/liblfds/liblfds6.1.0/test/src/internal.h @@ -0,0 +1,124 @@ +/***** ANSI includes *****/ +/* TRD : _GNU_SOURCE is required by sched.h for pthread_attr_setaffinity_np, CPU_ZERO and CPU_SET + however it has to be defined very early as even the ANSI headers pull in stuff + which uses _GNU_SOURCE and which I think must be protected against multiple inclusion, + which basically means if you set it too late, it's not seen, because the headers + have already been parsed with _GNU_SOURCE unset +*/ + +#define _GNU_SOURCE + +#include +#include +#include +#include +#include +#include +#include + +/***** internal includes *****/ +#include "abstraction.h" + +/***** external includes *****/ +#include "liblfds610.h" + +/***** defines *****/ +#define and && +#define or || + +#define RAISED 1 +#define LOWERED 0 + +#define NO_FLAGS 0x0 + +/***** enums *****/ +enum lfds610_test_operation +{ + UNKNOWN, + HELP, + TEST, + BENCHMARK +}; + +/***** structs *****/ +#include "structures.h" + +/***** prototypes *****/ +int main( int argc, char **argv ); + +void internal_display_test_name( char *test_name ); +void internal_display_test_result( unsigned int number_name_dvs_pairs, ... ); +void internal_display_lfds610_data_structure_validity( enum lfds610_data_structure_validity dvs ); + +void benchmark_lfds610_freelist( void ); + thread_return_t CALLING_CONVENTION benchmark_lfds610_freelist_thread_pop_and_push( void *freelist_benchmark ); + +void benchmark_lfds610_queue( void ); + thread_return_t CALLING_CONVENTION benchmark_lfds610_queue_thread_delfds610_queue_and_enqueue( void *queue_benchmark ); + +void benchmark_lfds610_ringbuffer( void ); + thread_return_t CALLING_CONVENTION benchmark_lfds610_ringbuffer_thread_write_and_read( void *ringbuffer_benchmark ); + +void benchmark_lfds610_stack( void ); + thread_return_t CALLING_CONVENTION benchmark_lfds610_stack_thread_push_and_pop( void *stack_benchmark ); + +void test_lfds610_abstraction( void ); + void abstraction_test_increment( void ); + thread_return_t CALLING_CONVENTION abstraction_test_internal_thread_increment( void *shared_counter ); + thread_return_t CALLING_CONVENTION abstraction_test_internal_thread_atomic_increment( void *shared_counter ); + void abstraction_test_cas( void ); + thread_return_t CALLING_CONVENTION abstraction_test_internal_thread_cas( void *abstraction_test_cas_state ); + void abstraction_test_dcas( void ); + thread_return_t CALLING_CONVENTION abstraction_test_internal_thread_dcas( void *abstraction_test_dcas_state ); + +void test_lfds610_freelist( void ); + void freelist_test_internal_popping( void ); + int freelist_test_internal_popping_init( void **user_data, void *user_state ); + thread_return_t CALLING_CONVENTION freelist_test_internal_thread_popping( void *freelist_test_popping_state ); + void freelist_test_internal_pushing( void ); + int freelist_test_internal_pushing_init( void **user_data, void *user_state ); + void freelist_test_internal_pushing_delete( void *user_data, void *user_state ); + thread_return_t CALLING_CONVENTION freelist_test_internal_thread_pushing( void *freelist_test_pushing_state ); + void freelist_test_internal_popping_and_pushing( void ); + thread_return_t CALLING_CONVENTION freelist_test_internal_thread_popping_and_pushing_start_popping( void *freelist_test_popping_and_pushing_state ); + thread_return_t CALLING_CONVENTION freelist_test_internal_thread_popping_and_pushing_start_pushing( void *freelist_test_popping_and_pushing_state ); + void freelist_test_internal_rapid_popping_and_pushing( void ); + thread_return_t CALLING_CONVENTION freelist_test_internal_thread_rapid_popping_and_pushing( void *lfds610_freelist_state ); + +void test_lfds610_queue( void ); + void queue_test_enqueuing( void ); + thread_return_t CALLING_CONVENTION queue_test_internal_thread_simple_enqueuer( void *queue_test_enqueuing_state ); + void queue_test_dequeuing( void ); + thread_return_t CALLING_CONVENTION queue_test_internal_thread_simple_dequeuer( void *queue_test_dequeuing_state ); + void queue_test_enqueuing_and_dequeuing( void ); + thread_return_t CALLING_CONVENTION queue_test_internal_thread_enqueuer_and_dequeuer( void *queue_test_rapid_enqueuing_and_dequeuing_state ); + void queue_test_rapid_enqueuing_and_dequeuing( void ); + thread_return_t CALLING_CONVENTION queue_test_internal_thread_rapid_enqueuer_and_dequeuer( void *queue_test_rapid_enqueuing_and_dequeuing_state ); + +void test_lfds610_ringbuffer( void ); + void ringbuffer_test_reading( void ); + thread_return_t CALLING_CONVENTION ringbuffer_test_thread_simple_reader( void *ringbuffer_test_reading_state ); + void ringbuffer_test_writing( void ); + thread_return_t CALLING_CONVENTION ringbuffer_test_thread_simple_writer( void *ringbuffer_test_writing_state ); + void ringbuffer_test_reading_and_writing( void ); + thread_return_t CALLING_CONVENTION ringbuffer_test_thread_reader_writer( void *ringbuffer_test_reading_and_writing_state ); + +void test_lfds610_slist( void ); + void test_slist_new_delete_get( void ); + thread_return_t CALLING_CONVENTION slist_test_internal_thread_new_delete_get_new_head_and_next( void *slist_test_state ); + thread_return_t CALLING_CONVENTION slist_test_internal_thread_new_delete_get_delete_and_get( void *slist_test_state ); + void test_slist_get_set_user_data( void ); + thread_return_t CALLING_CONVENTION slist_test_internal_thread_get_set_user_data( void *slist_test_state ); + void test_slist_delete_all_elements( void ); + +void test_lfds610_stack( void ); + void stack_test_internal_popping( void ); + thread_return_t CALLING_CONVENTION stack_test_internal_thread_popping( void *stack_test_popping_state ); + void stack_test_internal_pushing( void ); + thread_return_t CALLING_CONVENTION stack_test_internal_thread_pushing( void *stack_test_pushing_state ); + void stack_test_internal_popping_and_pushing( void ); + thread_return_t CALLING_CONVENTION stack_test_internal_thread_popping_and_pushing_start_popping( void *stack_test_popping_and_pushing_state ); + thread_return_t CALLING_CONVENTION stack_test_internal_thread_popping_and_pushing_start_pushing( void *stack_test_popping_and_pushing_state ); + void stack_test_internal_rapid_popping_and_pushing( void ); + thread_return_t CALLING_CONVENTION stack_test_internal_thread_rapid_popping_and_pushing( void *stack_state ); + diff --git a/liblfds/liblfds6.1.0/test/src/main.c b/liblfds/liblfds6.1.0/test/src/main.c new file mode 100644 index 0000000..8184fbd --- /dev/null +++ b/liblfds/liblfds6.1.0/test/src/main.c @@ -0,0 +1,87 @@ +#include "internal.h" + + + + + +/****************************************************************************/ +int main( int argc, char **argv ) +{ + enum lfds610_test_operation + operation = UNKNOWN; + + unsigned int + loop, + iterations = 1; + + assert( argc >= 1 ); + assert( argv != NULL ); + + if( argc == 1 or argc >= 4 ) + operation = HELP; + + if( operation == UNKNOWN ) + { + if( 0 == strcmp(*(argv+1), "test") ) + { + operation = TEST; + + // TRD : sscanf() may fail, but iterations is initialised to 1, so it's okay + if( argc == 3 ) + sscanf( *(argv+2), "%u", &iterations ); + } + + if( 0 == strcmp(*(argv+1), "benchmark") ) + { + operation = BENCHMARK; + + // TRD : sscanf() may fail, but iterations is initialised to 1, so it's okay + if( argc == 3 ) + sscanf( *(argv+2), "%u", &iterations ); + } + } + + switch( operation ) + { + case UNKNOWN: + case HELP: + printf( "test [test|benchmark] [iterations]\n" + " test : run the test suite\n" + " benchmark : run the benchmark suite\n" + " iterations : optional, default is 1\n" ); + break; + + case TEST: + for( loop = 1 ; loop < iterations+1 ; loop++ ) + { + printf( "\n" + "Test Iteration %02u\n" + "=================\n", loop ); + + test_lfds610_abstraction(); + test_lfds610_freelist(); + test_lfds610_queue(); + test_lfds610_ringbuffer(); + test_lfds610_slist(); + test_lfds610_stack(); + } + break; + + case BENCHMARK: + for( loop = 1 ; loop < iterations+1 ; loop++ ) + { + printf( "\n" + "Benchmark Iteration %02u\n" + "========================\n", loop ); + + benchmark_lfds610_freelist(); + benchmark_lfds610_queue(); + benchmark_lfds610_ringbuffer(); + benchmark_lfds610_stack(); + } + break; + } + + return( EXIT_SUCCESS ); +} + diff --git a/liblfds/liblfds6.1.0/test/src/misc.c b/liblfds/liblfds6.1.0/test/src/misc.c new file mode 100644 index 0000000..e9cb35f --- /dev/null +++ b/liblfds/liblfds6.1.0/test/src/misc.c @@ -0,0 +1,124 @@ +#include "internal.h" + + + + + +/****************************************************************************/ +void internal_display_test_name( char *test_name ) +{ + assert( test_name != NULL ); + + printf( "%s...", test_name ); + fflush( stdout ); + + return; +} + + + + + +/****************************************************************************/ +void internal_display_test_result( unsigned int number_name_dvs_pairs, ... ) +{ + va_list + va; + + int + passed_flag = RAISED; + + unsigned int + loop; + + char + *name; + + enum lfds610_data_structure_validity + dvs; + + // TRD : number_name_dvs_pairs can be any value in its range + + va_start( va, number_name_dvs_pairs ); + + for( loop = 0 ; loop < number_name_dvs_pairs ; loop++ ) + { + name = va_arg( va, char * ); + dvs = va_arg( va, enum lfds610_data_structure_validity ); + + if( dvs != LFDS610_VALIDITY_VALID ) + { + passed_flag = LOWERED; + break; + } + } + + va_end( va ); + + if( passed_flag == RAISED ) + puts( "passed" ); + + if( passed_flag == LOWERED ) + { + printf( "failed (" ); + + va_start( va, number_name_dvs_pairs ); + + for( loop = 0 ; loop < number_name_dvs_pairs ; loop++ ) + { + name = va_arg( va, char * ); + dvs = va_arg( va, enum lfds610_data_structure_validity ); + + printf( "%s ", name ); + internal_display_lfds610_data_structure_validity( dvs ); + + if( loop+1 < number_name_dvs_pairs ) + printf( ", " ); + } + + va_end( va ); + + printf( ")\n" ); + } + + return; +} + + + + + +/****************************************************************************/ +void internal_display_lfds610_data_structure_validity( enum lfds610_data_structure_validity dvs ) +{ + char + *string = NULL; + + switch( dvs ) + { + case LFDS610_VALIDITY_VALID: + string = "valid"; + break; + + case LFDS610_VALIDITY_INVALID_LOOP: + string = "invalid - loop detected"; + break; + + case LFDS610_VALIDITY_INVALID_MISSING_ELEMENTS: + string = "invalid - missing elements"; + break; + + case LFDS610_VALIDITY_INVALID_ADDITIONAL_ELEMENTS: + string = "invalid - additional elements"; + break; + + case LFDS610_VALIDITY_INVALID_TEST_DATA: + string = "invalid - invalid test data"; + break; + } + + printf( "%s", string ); + + return; +} + diff --git a/liblfds/liblfds6.1.0/test/src/structures.h b/liblfds/liblfds6.1.0/test/src/structures.h new file mode 100644 index 0000000..05ed872 --- /dev/null +++ b/liblfds/liblfds6.1.0/test/src/structures.h @@ -0,0 +1,227 @@ +/***** structs *****/ +#pragma pack( push, LFDS610_ALIGN_DOUBLE_POINTER ) + +/***** abstraction tests *****/ +struct abstraction_test_cas_state +{ + volatile lfds610_atom_t + *shared_counter; + + lfds610_atom_t + local_counter; +}; + +struct abstraction_test_dcas_state +{ + volatile lfds610_atom_t + *shared_counter; + + lfds610_atom_t + local_counter; +}; + +/***** freelist tests *****/ +struct freelist_test_popping_state +{ + struct lfds610_freelist_state + *fs, + *fs_thread_local; +}; + +struct freelist_test_pushing_state +{ + lfds610_atom_t + *count, + thread_number; + + struct lfds610_freelist_state + *source_fs, + *fs; +}; + +struct freelist_test_popping_and_pushing_state +{ + struct lfds610_freelist_state + *local_fs, + *fs; +}; + +struct freelist_test_counter_and_thread_number +{ + lfds610_atom_t + thread_number; + + unsigned long long int + counter; +}; + +/***** queue tests *****/ +struct queue_test_enqueuing_state +{ + struct lfds610_queue_state + *qs; + + lfds610_atom_t + counter; +}; + +struct queue_test_dequeuing_state +{ + struct lfds610_queue_state + *qs; + + int + error_flag; +}; + +struct queue_test_enqueuing_and_dequeuing_state +{ + struct lfds610_queue_state + *qs; + + lfds610_atom_t + counter, + thread_number, + *per_thread_counters; + + unsigned int + cpu_count; + + int + error_flag; +}; + +struct queue_test_rapid_enqueuing_and_dequeuing_state +{ + struct lfds610_queue_state + *qs; + + lfds610_atom_t + counter; +}; + +/***** ringbuffer tests *****/ +struct ringbuffer_test_reading_state +{ + struct lfds610_ringbuffer_state + *rs; + + int + error_flag; + + lfds610_atom_t + read_count; +}; + +struct ringbuffer_test_writing_state +{ + struct lfds610_ringbuffer_state + *rs; + + lfds610_atom_t + write_count; +}; + +struct ringbuffer_test_reading_and_writing_state +{ + struct lfds610_ringbuffer_state + *rs; + + lfds610_atom_t + counter, + *per_thread_counters; + + unsigned int + cpu_count; + + int + error_flag; +}; + +/***** slist tests *****/ +struct slist_test_state +{ + struct lfds610_slist_state + *ss; + + size_t + create_count, + delete_count; + + lfds610_atom_t + thread_and_count; +}; + +/***** stack tests *****/ +struct stack_test_popping_state +{ + struct lfds610_stack_state + *ss, + *ss_thread_local; +}; + +struct stack_test_pushing_state +{ + lfds610_atom_t + thread_number; + + struct lfds610_stack_state + *ss; +}; + +struct stack_test_popping_and_pushing_state +{ + struct lfds610_stack_state + *local_ss, + *ss; +}; + +struct stack_test_counter_and_thread_number +{ + lfds610_atom_t + thread_number, + counter; +}; + +/***** freelist benchmarks *****/ +struct lfds610_freelist_benchmark +{ + struct lfds610_freelist_state + *fs; + + lfds610_atom_t + operation_count; +}; + +/***** queue benchmarks *****/ +struct lfds610_queue_benchmark +{ + struct lfds610_queue_state + *qs; + + lfds610_atom_t + operation_count; +}; + +/***** ringbuffer benchmarks *****/ +struct lfds610_ringbuffer_benchmark +{ + struct lfds610_ringbuffer_state + *rs; + + lfds610_atom_t + operation_count; +}; + +/***** stack benchmarks *****/ +struct lfds610_stack_benchmark +{ + struct lfds610_stack_state + *ss; + + lfds610_atom_t + operation_count; +}; + +#pragma pack( pop ) + diff --git a/liblfds/liblfds6.1.0/test/src/test_abstraction.c b/liblfds/liblfds6.1.0/test/src/test_abstraction.c new file mode 100644 index 0000000..83bc48b --- /dev/null +++ b/liblfds/liblfds6.1.0/test/src/test_abstraction.c @@ -0,0 +1,321 @@ +#include "internal.h" + + + + + +/****************************************************************************/ +void test_lfds610_abstraction( void ) +{ + printf( "\n" + "Abstraction Tests\n" + "=================\n" ); + + abstraction_test_increment(); + abstraction_test_cas(); + abstraction_test_dcas(); + + return; +} + + + + + +/****************************************************************************/ +void abstraction_test_increment( void ) +{ + unsigned int + loop, + cpu_count; + + thread_state_t + *thread_handles; + + lfds610_atom_t + shared_counter, + atomic_shared_counter; + + /* TRD : here we test lfds610_abstraction_increment + + first, we run one thread per CPU where each thread increments + a shared counter 10,000,000 times - however, this first test + does NOT use atomic increment; it uses "++" + + second, we repeat the exercise, but this time using + lfds610_abstraction_increment() + + if the final value in the first test is less than (10,000,000*cpu_count) + then the system is sensitive to non-atomic increments; this means if + our atomic version of the test passes, we can have some degree of confidence + that it works + + if the final value in the first test is in fact correct, then we can't know + that our atomic version has changed anything + + and of course if the final value in the atomic test is wrong, we know things + are broken + */ + + internal_display_test_name( "Atomic increment" ); + + cpu_count = abstraction_cpu_count(); + + shared_counter = 0; + atomic_shared_counter = 0; + + LFDS610_BARRIER_STORE; + + thread_handles = malloc( sizeof(thread_state_t) * cpu_count ); + + // TRD : non-atomic + for( loop = 0 ; loop < cpu_count ; loop++ ) + abstraction_thread_start( &thread_handles[loop], loop, abstraction_test_internal_thread_increment, &shared_counter ); + + for( loop = 0 ; loop < cpu_count ; loop++ ) + abstraction_thread_wait( thread_handles[loop] ); + + // TRD : atomic + for( loop = 0 ; loop < cpu_count ; loop++ ) + abstraction_thread_start( &thread_handles[loop], loop, abstraction_test_internal_thread_atomic_increment, &atomic_shared_counter ); + + for( loop = 0 ; loop < cpu_count ; loop++ ) + abstraction_thread_wait( thread_handles[loop] ); + + free( thread_handles ); + + // TRD : results + if( shared_counter < (10000000 * cpu_count) and atomic_shared_counter == (10000000 * cpu_count) ) + puts( "passed" ); + + if( shared_counter == (10000000 * cpu_count) and atomic_shared_counter == (10000000 * cpu_count) ) + puts( "indeterminate" ); + + if( atomic_shared_counter < (10000000 * cpu_count) ) + puts( "failed" ); + + return; +} + + + + + +/****************************************************************************/ +thread_return_t CALLING_CONVENTION abstraction_test_internal_thread_increment( void *shared_counter ) +{ + assert( shared_counter != NULL ); + + LFDS610_BARRIER_LOAD; + + lfds610_liblfds_abstraction_test_helper_increment_non_atomic( shared_counter ); + + return( (thread_return_t) EXIT_SUCCESS ); +} + + + + + +/****************************************************************************/ +thread_return_t CALLING_CONVENTION abstraction_test_internal_thread_atomic_increment( void *shared_counter ) +{ + assert( shared_counter != NULL ); + + LFDS610_BARRIER_LOAD; + + lfds610_liblfds_abstraction_test_helper_increment_atomic( shared_counter ); + + return( (thread_return_t) EXIT_SUCCESS ); +} + + + + + +/****************************************************************************/ +void abstraction_test_cas( void ) +{ + unsigned int + loop, + cpu_count; + + thread_state_t + *thread_handles; + + struct abstraction_test_cas_state + *atcs; + + LFDS610_ALIGN(LFDS610_ALIGN_SINGLE_POINTER) volatile lfds610_atom_t + shared_counter = 0; + + lfds610_atom_t + local_total = 0; + + // TRD : number_logical_processors can be any value in its range + + /* TRD : here we test lfds610_abstraction_cas + + we run one thread per CPU + we use lfds610_abstraction_cas() to increment a shared counter + every time a thread successfully increments the counter, + it increments a thread local counter + the threads run for ten seconds + after the threads finish, we total the local counters + they should equal the shared counter + */ + + internal_display_test_name( "Atomic CAS" ); + + cpu_count = abstraction_cpu_count(); + + atcs = malloc( sizeof(struct abstraction_test_cas_state) * cpu_count ); + + for( loop = 0 ; loop < cpu_count ; loop++ ) + { + (atcs+loop)->shared_counter = &shared_counter; + (atcs+loop)->local_counter = 0; + } + + thread_handles = malloc( sizeof(thread_state_t) * cpu_count ); + + for( loop = 0 ; loop < cpu_count ; loop++ ) + abstraction_thread_start( &thread_handles[loop], loop, abstraction_test_internal_thread_cas, atcs+loop ); + + for( loop = 0 ; loop < cpu_count ; loop++ ) + abstraction_thread_wait( thread_handles[loop] ); + + free( thread_handles ); + + // TRD : results + for( loop = 0 ; loop < cpu_count ; loop++ ) + local_total += (atcs+loop)->local_counter; + + if( local_total == shared_counter ) + puts( "passed" ); + + if( local_total != shared_counter ) + puts( "failed" ); + + // TRD : cleanup + free( atcs ); + + return; +} + + + + + +/****************************************************************************/ +thread_return_t CALLING_CONVENTION abstraction_test_internal_thread_cas( void *abstraction_test_cas_state ) +{ + struct abstraction_test_cas_state + *atcs; + + assert( abstraction_test_cas_state != NULL ); + + atcs = (struct abstraction_test_cas_state *) abstraction_test_cas_state; + + LFDS610_BARRIER_LOAD; + + lfds610_liblfds_abstraction_test_helper_cas( atcs->shared_counter, &atcs->local_counter ); + + return( (thread_return_t) EXIT_SUCCESS ); +} + + + + + +/****************************************************************************/ +void abstraction_test_dcas( void ) +{ + unsigned int + loop, + cpu_count; + + thread_state_t + *thread_handles; + + struct abstraction_test_dcas_state + *atds; + + LFDS610_ALIGN(LFDS610_ALIGN_DOUBLE_POINTER) volatile lfds610_atom_t + shared_counter[2] = { 0, 0 }; + + lfds610_atom_t + local_total = 0; + + /* TRD : here we test lfds610_abstraction_dcas + + we run one thread per CPU + we use lfds610_abstraction_dcas() to increment a shared counter + every time a thread successfully increments the counter, + it increments a thread local counter + the threads run for ten seconds + after the threads finish, we total the local counters + they should equal the shared counter + */ + + internal_display_test_name( "Atomic DCAS" ); + + cpu_count = abstraction_cpu_count(); + + atds = malloc( sizeof(struct abstraction_test_dcas_state) * cpu_count ); + + for( loop = 0 ; loop < cpu_count ; loop++ ) + { + (atds+loop)->shared_counter = shared_counter; + (atds+loop)->local_counter = 0; + } + + LFDS610_BARRIER_STORE; + + thread_handles = malloc( sizeof(thread_state_t) * cpu_count ); + + for( loop = 0 ; loop < cpu_count ; loop++ ) + abstraction_thread_start( &thread_handles[loop], loop, abstraction_test_internal_thread_dcas, atds+loop ); + + for( loop = 0 ; loop < cpu_count ; loop++ ) + abstraction_thread_wait( thread_handles[loop] ); + + free( thread_handles ); + + // TRD : results + for( loop = 0 ; loop < cpu_count ; loop++ ) + local_total += (atds+loop)->local_counter; + + if( local_total == shared_counter[0] ) + puts( "passed" ); + + if( local_total != shared_counter[0] ) + puts( "failed" ); + + // TRD : cleanup + free( atds ); + + return; +} + + + + + +/****************************************************************************/ +thread_return_t CALLING_CONVENTION abstraction_test_internal_thread_dcas( void *abstraction_test_dcas_state ) +{ + struct abstraction_test_dcas_state + *atds; + + assert( abstraction_test_dcas_state != NULL ); + + atds = (struct abstraction_test_dcas_state *) abstraction_test_dcas_state; + + LFDS610_BARRIER_LOAD; + + lfds610_liblfds_abstraction_test_helper_dcas( atds->shared_counter, &atds->local_counter ); + + return( (thread_return_t) EXIT_SUCCESS ); +} + diff --git a/liblfds/liblfds6.1.0/test/src/test_freelist.c b/liblfds/liblfds6.1.0/test/src/test_freelist.c new file mode 100644 index 0000000..0f036ce --- /dev/null +++ b/liblfds/liblfds6.1.0/test/src/test_freelist.c @@ -0,0 +1,685 @@ +#include "internal.h" + + + + + +/****************************************************************************/ +void test_lfds610_freelist( void ) +{ + printf( "\n" + "Freelist Tests\n" + "==============\n" ); + + freelist_test_internal_popping(); + freelist_test_internal_pushing(); + freelist_test_internal_popping_and_pushing(); + freelist_test_internal_rapid_popping_and_pushing(); + + return; +} + + + + + +/****************************************************************************/ +void freelist_test_internal_popping( void ) +{ + unsigned int + loop, + cpu_count; + + lfds610_atom_t + count = 0; + + thread_state_t + *thread_handles; + + enum lfds610_data_structure_validity + dvs = LFDS610_VALIDITY_VALID; + + struct lfds610_freelist_state + *fs; + + struct lfds610_freelist_element + *fe; + + struct freelist_test_popping_state + *ftps; + + unsigned int + *found_count; + + /* TRD : we create a freelist with 1,000,000 elements + + the creation function runs in a single thread and creates + and pushes those elements onto the freelist + + each element contains a void pointer which is its element number + + we then run one thread per CPU + where each thread loops, popping as quickly as possible + each popped element is pushed onto a thread-local freelist + + the threads run till the source freelist is empty + + we then check the thread-local freelists + we should find we have every element + + then tidy up + */ + + internal_display_test_name( "Popping" ); + + cpu_count = abstraction_cpu_count(); + + lfds610_freelist_new( &fs, 1000000, freelist_test_internal_popping_init, &count ); + ftps = malloc( sizeof(struct freelist_test_popping_state) * cpu_count ); + for( loop = 0 ; loop < cpu_count ; loop++ ) + { + (ftps+loop)->fs = fs; + lfds610_freelist_new( &(ftps+loop)->fs_thread_local, 0, NULL, NULL ); + } + + thread_handles = malloc( sizeof(thread_state_t) * cpu_count ); + + for( loop = 0 ; loop < cpu_count ; loop++ ) + abstraction_thread_start( &thread_handles[loop], loop, freelist_test_internal_thread_popping, ftps+loop ); + + for( loop = 0 ; loop < cpu_count ; loop++ ) + abstraction_thread_wait( thread_handles[loop] ); + + free( thread_handles ); + + // TRD : now we check the thread-local freelists + found_count = malloc( sizeof(unsigned int) * 1000000 ); + for( loop = 0 ; loop < 1000000 ; loop++ ) + *(found_count+loop) = 0; + + for( loop = 0 ; loop < cpu_count ; loop++ ) + { + while( lfds610_freelist_pop((ftps+loop)->fs_thread_local, &fe) ) + { + lfds610_freelist_get_user_data_from_element( fe, (void **) &count ); + (*(found_count+count))++; + lfds610_freelist_push( fs, fe ); + } + } + + for( loop = 0 ; loop < 1000000 and dvs == LFDS610_VALIDITY_VALID ; loop++ ) + { + if( *(found_count+loop) == 0 ) + dvs = LFDS610_VALIDITY_INVALID_MISSING_ELEMENTS; + + if( *(found_count+loop) > 1 ) + dvs = LFDS610_VALIDITY_INVALID_ADDITIONAL_ELEMENTS; + } + + // TRD : cleanup + free( found_count ); + for( loop = 0 ; loop < cpu_count ; loop++ ) + lfds610_freelist_delete( (ftps+loop)->fs_thread_local, NULL, NULL ); + free( ftps ); + lfds610_freelist_delete( fs, NULL, NULL ); + + // TRD : print the test result + internal_display_test_result( 1, "freelist", dvs ); + + return; +} + + + + + +/****************************************************************************/ +#pragma warning( disable : 4100 ) + +int freelist_test_internal_popping_init( void **user_data, void *user_state ) +{ + lfds610_atom_t + *count; + + assert( user_data != NULL ); + assert( user_state != NULL ); + + count = (lfds610_atom_t *) user_state; + + *(lfds610_atom_t *) user_data = (*count)++; + + return( 1 ); +} + +#pragma warning( default : 4100 ) + + + + + +/****************************************************************************/ +thread_return_t CALLING_CONVENTION freelist_test_internal_thread_popping( void *freelist_test_popping_state ) +{ + struct freelist_test_popping_state + *ftps; + + struct lfds610_freelist_element + *fe; + + assert( freelist_test_popping_state != NULL ); + + ftps = (struct freelist_test_popping_state *) freelist_test_popping_state; + + lfds610_freelist_use( ftps->fs ); + lfds610_freelist_use( ftps->fs_thread_local ); + + while( lfds610_freelist_pop(ftps->fs, &fe) ) + lfds610_freelist_push( ftps->fs_thread_local, fe ); + + return( (thread_return_t) EXIT_SUCCESS ); +} + + + + + +/****************************************************************************/ +void freelist_test_internal_pushing( void ) +{ + unsigned int + loop, + cpu_count; + + lfds610_atom_t + count = 0; + + thread_state_t + *thread_handles; + + enum lfds610_data_structure_validity + dvs; + + struct freelist_test_pushing_state + *ftps; + + struct lfds610_freelist_element + *fe; + + struct lfds610_freelist_state + *fs, + *cleanup_fs; + + struct freelist_test_counter_and_thread_number + *cnt, + *counter_and_number_trackers; + + struct lfds610_validation_info + vi; + + /* TRD : we create an empty freelist, which we will push to + + we then create one freelist per CPU, where this freelist + contains 100,000 elements per thread and + each element is an incrementing counter and unique ID + (from 0 to number of CPUs) + + we then start one thread per CPU, where each thread is + given one of the populated freelists and pops from that + to push to the empty freelist + + the reason for this is to achieve memory pre-allocation + which allows the pushing threads to run at maximum speed + + the threads end when their freelists are empty + + we then fully pop the now populated main freelist (onto + a second freelist, so we can cleanly free all memory), + checking that the counts increment on a per unique ID basis + and that the number of elements we pop equals 1,000,000 per thread + (since each element has an incrementing counter which is + unique on a per unique ID basis, we can know we didn't lose + any elements) + */ + + internal_display_test_name( "Pushing" ); + + cpu_count = abstraction_cpu_count(); + + ftps = malloc( sizeof(struct freelist_test_pushing_state) * cpu_count ); + + lfds610_freelist_new( &fs, 0, NULL, NULL ); + + for( loop = 0 ; loop < cpu_count ; loop++ ) + { + (ftps+loop)->thread_number = (lfds610_atom_t) loop; + // TRD : note count is shared across threads, so thread 0 is 0-100000, thread 1 is 100000-200000, etc + (ftps+loop)->count = &count; + lfds610_freelist_new( &(ftps+loop)->source_fs, 100000, freelist_test_internal_pushing_init, (void *) (ftps+loop) ); + (ftps+loop)->fs = fs; + } + + thread_handles = malloc( sizeof(thread_state_t) * cpu_count ); + + for( loop = 0 ; loop < cpu_count ; loop++ ) + abstraction_thread_start( &thread_handles[loop], loop, freelist_test_internal_thread_pushing, ftps+loop ); + + for( loop = 0 ; loop < cpu_count ; loop++ ) + abstraction_thread_wait( thread_handles[loop] ); + + free( thread_handles ); + + // TRD : now fully pop and verify the main freelist + lfds610_freelist_new( &cleanup_fs, 0, NULL, NULL ); + + counter_and_number_trackers = malloc( sizeof(struct freelist_test_counter_and_thread_number) * cpu_count ); + + for( loop = 0 ; loop < cpu_count ; loop++ ) + { + (counter_and_number_trackers+loop)->counter = 100000 * loop; + (counter_and_number_trackers+loop)->thread_number = (lfds610_atom_t) loop; + } + + vi.min_elements = vi.max_elements = 100000 * cpu_count; + + lfds610_freelist_query( fs, LFDS610_FREELIST_QUERY_VALIDATE, &vi, (void *) &dvs ); + + while( dvs == LFDS610_VALIDITY_VALID and lfds610_freelist_pop(fs, &fe) ) + { + lfds610_freelist_get_user_data_from_element( fe, (void **) &cnt ); + + if( cnt->counter != (counter_and_number_trackers+cnt->thread_number)->counter++ ) + dvs = LFDS610_VALIDITY_INVALID_MISSING_ELEMENTS; + + lfds610_freelist_push( cleanup_fs, fe ); + } + + // TRD : clean up + free( counter_and_number_trackers ); + + for( loop = 0 ; loop < cpu_count ; loop++ ) + lfds610_freelist_delete( (ftps+loop)->source_fs, NULL, NULL ); + + free( ftps ); + + lfds610_freelist_delete( cleanup_fs, freelist_test_internal_pushing_delete, NULL ); + lfds610_freelist_delete( fs, NULL, NULL ); + + // TRD : print the test result + internal_display_test_result( 1, "freelist", dvs ); + + return; +} + + + + + +/****************************************************************************/ +int freelist_test_internal_pushing_init( void **user_data, void *user_state ) +{ + struct freelist_test_counter_and_thread_number + *ftcatn; + + struct freelist_test_pushing_state + *ftps; + + assert( user_data != NULL ); + // TRD : user_state is being used as an integer type + + *user_data = malloc( sizeof(struct freelist_test_counter_and_thread_number) ); + ftps = (struct freelist_test_pushing_state *) user_state; + + ftcatn = (struct freelist_test_counter_and_thread_number *) *user_data; + + ftcatn->counter = (*ftps->count)++; + ftcatn->thread_number = ftps->thread_number; + + return( 1 ); +} + + + + + +/****************************************************************************/ +#pragma warning( disable : 4100 ) + +void freelist_test_internal_pushing_delete( void *user_data, void *user_state ) +{ + assert( user_data != NULL ); + assert( user_state == NULL ); + + free( user_data ); + + return; +} + +#pragma warning( default : 4100 ) + + + + + +/****************************************************************************/ +thread_return_t CALLING_CONVENTION freelist_test_internal_thread_pushing( void *freelist_test_pushing_state ) +{ + struct freelist_test_pushing_state + *ftps; + + struct lfds610_freelist_element + *fe; + + assert( freelist_test_pushing_state != NULL ); + + ftps = (struct freelist_test_pushing_state *) freelist_test_pushing_state; + + lfds610_freelist_use( ftps->source_fs ); + lfds610_freelist_use( ftps->fs ); + + while( lfds610_freelist_pop(ftps->source_fs, &fe) ) + lfds610_freelist_push( ftps->fs, fe ); + + return( (thread_return_t) EXIT_SUCCESS ); +} + + + + + +/****************************************************************************/ +void freelist_test_internal_popping_and_pushing( void ) +{ + unsigned int + loop, + cpu_count; + + thread_state_t + *thread_handles; + + enum lfds610_data_structure_validity + dvs; + + struct lfds610_freelist_state + *fs; + + struct freelist_test_popping_and_pushing_state + *pps; + + struct lfds610_validation_info + vi; + + /* TRD : we have two threads per CPU + the threads loop for ten seconds + the first thread pushes 100000 elements then pops 100000 elements + the second thread pops 100000 elements then pushes 100000 elements + all pushes and pops go onto the single main freelist + + after time is up, all threads push what they have remaining onto + the main freelist + + we then validate the main freelist + */ + + internal_display_test_name( "Popping and pushing (10 seconds)" ); + + cpu_count = abstraction_cpu_count(); + + lfds610_freelist_new( &fs, 100000 * cpu_count, NULL, NULL ); + + pps = malloc( sizeof(struct freelist_test_popping_and_pushing_state) * cpu_count * 2 ); + + for( loop = 0 ; loop < cpu_count ; loop++ ) + { + (pps+loop)->fs = fs; + lfds610_freelist_new( &(pps+loop)->local_fs, 0, NULL, NULL ); + + (pps+loop+cpu_count)->fs = fs; + lfds610_freelist_new( &(pps+loop+cpu_count)->local_fs, 100000, NULL, NULL ); + } + + thread_handles = malloc( sizeof(thread_state_t) * cpu_count * 2 ); + + for( loop = 0 ; loop < cpu_count ; loop++ ) + { + abstraction_thread_start( &thread_handles[loop], loop, freelist_test_internal_thread_popping_and_pushing_start_popping, pps+loop ); + abstraction_thread_start( &thread_handles[loop+cpu_count], loop, freelist_test_internal_thread_popping_and_pushing_start_pushing, pps+loop+cpu_count ); + } + + for( loop = 0 ; loop < cpu_count * 2 ; loop++ ) + abstraction_thread_wait( thread_handles[loop] ); + + free( thread_handles ); + + for( loop = 0 ; loop < cpu_count * 2 ; loop++ ) + lfds610_freelist_delete( (pps+loop)->local_fs, NULL, NULL ); + + free( pps ); + + vi.min_elements = vi.max_elements = 100000 * cpu_count * 2; + + lfds610_freelist_query( fs, LFDS610_FREELIST_QUERY_VALIDATE, (void *) &vi, (void *) &dvs ); + + lfds610_freelist_delete( fs, NULL, NULL ); + + // TRD : print the test result + internal_display_test_result( 1, "freelist", dvs ); + + return; +} + + + + + + +/****************************************************************************/ +thread_return_t CALLING_CONVENTION freelist_test_internal_thread_popping_and_pushing_start_popping( void *freelist_test_popping_and_pushing_state ) +{ + struct freelist_test_popping_and_pushing_state + *pps; + + struct lfds610_freelist_element + *fe; + + time_t + start_time; + + unsigned int + count; + + assert( freelist_test_popping_and_pushing_state != NULL ); + + pps = (struct freelist_test_popping_and_pushing_state *) freelist_test_popping_and_pushing_state; + + lfds610_freelist_use( pps->fs ); + lfds610_freelist_use( pps->local_fs ); + + time( &start_time ); + + while( time(NULL) < start_time + 10 ) + { + count = 0; + + while( count < 100000 ) + { + lfds610_freelist_pop( pps->fs, &fe ); + + if( fe != NULL ) + { + lfds610_freelist_push( pps->local_fs, fe ); + count++; + } + } + + while( lfds610_freelist_pop(pps->local_fs, &fe) ) + lfds610_freelist_push( pps->fs, fe ); + } + + return( (thread_return_t) EXIT_SUCCESS ); +} + + + + + +/****************************************************************************/ +thread_return_t CALLING_CONVENTION freelist_test_internal_thread_popping_and_pushing_start_pushing( void *freelist_test_popping_and_pushing_state ) +{ + struct freelist_test_popping_and_pushing_state + *pps; + + struct lfds610_freelist_element + *fe; + + time_t + start_time; + + unsigned int + count; + + assert( freelist_test_popping_and_pushing_state != NULL ); + + pps = (struct freelist_test_popping_and_pushing_state *) freelist_test_popping_and_pushing_state; + + lfds610_freelist_use( pps->fs ); + lfds610_freelist_use( pps->local_fs ); + + time( &start_time ); + + while( time(NULL) < start_time + 10 ) + { + while( lfds610_freelist_pop(pps->local_fs, &fe) ) + lfds610_freelist_push( pps->fs, fe ); + + count = 0; + + while( count < 1000 ) + { + lfds610_freelist_pop( pps->fs, &fe ); + + if( fe != NULL ) + { + lfds610_freelist_push( pps->local_fs, fe ); + count++; + } + } + } + + // TRD : now push whatever we have in our local freelist + while( lfds610_freelist_pop(pps->local_fs, &fe) ) + lfds610_freelist_push( pps->fs, fe ); + + return( (thread_return_t) EXIT_SUCCESS ); +} + + + + + +/****************************************************************************/ +void freelist_test_internal_rapid_popping_and_pushing( void ) +{ + unsigned int + loop, + cpu_count; + + thread_state_t + *thread_handles; + + struct lfds610_freelist_state + *fs; + + struct lfds610_validation_info + vi; + + enum lfds610_data_structure_validity + dvs; + + /* TRD : in these tests there is a fundamental antagonism between + how much checking/memory clean up that we do and the + likelyhood of collisions between threads in their lock-free + operations + + the lock-free operations are very quick; if we do anything + much at all between operations, we greatly reduce the chance + of threads colliding + + so we have some tests which do enough checking/clean up that + they can tell the freelist is valid and don't leak memory + and here, this test now is one of those which does minimal + checking - in fact, the nature of the test is that you can't + do any real checking - but goes very quickly + + what we do is create a small freelist and then run one thread + per CPU, where each thread simply pops and then immediately + pushes + + the test runs for ten seconds + + after the test is done, the only check we do is to traverse + the freelist, checking for loops and ensuring the number of + elements is correct + */ + + internal_display_test_name( "Rapid popping and pushing (10 seconds)" ); + + cpu_count = abstraction_cpu_count(); + + lfds610_freelist_new( &fs, cpu_count, NULL, NULL ); + + thread_handles = malloc( sizeof(thread_state_t) * cpu_count ); + + for( loop = 0 ; loop < cpu_count ; loop++ ) + abstraction_thread_start( &thread_handles[loop], loop, freelist_test_internal_thread_rapid_popping_and_pushing, fs ); + + for( loop = 0 ; loop < cpu_count ; loop++ ) + abstraction_thread_wait( thread_handles[loop] ); + + free( thread_handles ); + + vi.min_elements = cpu_count; + vi.max_elements = cpu_count; + + lfds610_freelist_query( fs, LFDS610_FREELIST_QUERY_VALIDATE, (void *) &vi, (void *) &dvs ); + + lfds610_freelist_delete( fs, NULL, NULL ); + + // TRD : print the test result + internal_display_test_result( 1, "freelist", dvs ); + + return; +} + + + + + +/****************************************************************************/ +thread_return_t CALLING_CONVENTION freelist_test_internal_thread_rapid_popping_and_pushing( void *lfds610_freelist_state ) +{ + struct lfds610_freelist_state + *fs; + + struct lfds610_freelist_element + *fe; + + time_t + start_time; + + assert( lfds610_freelist_state != NULL ); + + fs = (struct lfds610_freelist_state *) lfds610_freelist_state; + + lfds610_freelist_use( fs ); + + time( &start_time ); + + while( time(NULL) < start_time + 10 ) + { + lfds610_freelist_pop( fs, &fe ); + lfds610_freelist_push( fs, fe ); + } + + return( (thread_return_t) EXIT_SUCCESS ); +} + diff --git a/liblfds/liblfds6.1.0/test/src/test_queue.c b/liblfds/liblfds6.1.0/test/src/test_queue.c new file mode 100644 index 0000000..97bd49e --- /dev/null +++ b/liblfds/liblfds6.1.0/test/src/test_queue.c @@ -0,0 +1,527 @@ +#include "internal.h" + + + + + +/****************************************************************************/ +void test_lfds610_queue( void ) +{ + printf( "\n" + "Queue Tests\n" + "===========\n" ); + + queue_test_enqueuing(); + queue_test_dequeuing(); + queue_test_enqueuing_and_dequeuing(); + queue_test_rapid_enqueuing_and_dequeuing(); + + return; +} + + + + + +/****************************************************************************/ +void queue_test_enqueuing( void ) +{ + unsigned int + loop, + cpu_count; + + thread_state_t + *thread_handles; + + struct lfds610_queue_state + *qs; + + struct queue_test_enqueuing_state + *qtes; + + lfds610_atom_t + user_data, + thread, + count, + *per_thread_counters; + + struct lfds610_validation_info + vi = { 1000000, 1000000 }; + + enum lfds610_data_structure_validity + dvs[2]; + + /* TRD : create an empty queue with 1,000,000 elements in its freelist + then run one thread per CPU + where each thread busy-works, enqueuing elements (until there are no more elements) + each element's void pointer of user data is (thread number | element number) + where element_number is a thread-local counter starting at 0 + where the thread_number occupies the top byte + + when we're done, we check that all the elements are present + and increment on a per-thread basis + */ + + internal_display_test_name( "Enqueuing" ); + + cpu_count = abstraction_cpu_count(); + + lfds610_queue_new( &qs, 1000000 ); + + qtes = malloc( sizeof(struct queue_test_enqueuing_state) * cpu_count ); + + for( loop = 0 ; loop < cpu_count ; loop++ ) + { + (qtes+loop)->qs = qs; + (qtes+loop)->counter = (lfds610_atom_t) loop << (sizeof(lfds610_atom_t)*8-8); + } + + thread_handles = malloc( sizeof(thread_state_t) * cpu_count ); + + for( loop = 0 ; loop < cpu_count ; loop++ ) + abstraction_thread_start( &thread_handles[loop], loop, queue_test_internal_thread_simple_enqueuer, qtes+loop ); + + for( loop = 0 ; loop < cpu_count ; loop++ ) + abstraction_thread_wait( thread_handles[loop] ); + + free( thread_handles ); + + free( qtes ); + + /* TRD : first, validate the queue + + then dequeue + we expect to find element numbers increment on a per thread basis + */ + + lfds610_queue_query( qs, LFDS610_QUEUE_QUERY_VALIDATE, &vi, dvs ); + + per_thread_counters = malloc( sizeof(lfds610_atom_t) * cpu_count ); + + for( loop = 0 ; loop < cpu_count ; loop++ ) + *(per_thread_counters+loop) = 0; + + while( dvs[0] == LFDS610_VALIDITY_VALID and dvs[1] == LFDS610_VALIDITY_VALID and lfds610_queue_dequeue(qs, (void *) &user_data) ) + { + thread = user_data >> (sizeof(lfds610_atom_t)*8-8); + count = (user_data << 8) >> 8; + + if( thread >= cpu_count ) + { + dvs[0] = LFDS610_VALIDITY_INVALID_TEST_DATA; + break; + } + + if( count < per_thread_counters[thread] ) + dvs[0] = LFDS610_VALIDITY_INVALID_ADDITIONAL_ELEMENTS; + + if( count > per_thread_counters[thread] ) + dvs[0] = LFDS610_VALIDITY_INVALID_MISSING_ELEMENTS; + + if( count == per_thread_counters[thread] ) + per_thread_counters[thread]++; + } + + free( per_thread_counters ); + + lfds610_queue_delete( qs, NULL, NULL ); + + internal_display_test_result( 2, "queue", dvs[0], "queue freelist", dvs[1] ); + + return; +} + + + + + +/****************************************************************************/ +thread_return_t CALLING_CONVENTION queue_test_internal_thread_simple_enqueuer( void *queue_test_enqueuing_state ) +{ + struct queue_test_enqueuing_state + *qtes; + + assert( queue_test_enqueuing_state != NULL ); + + qtes = (struct queue_test_enqueuing_state *) queue_test_enqueuing_state; + + lfds610_queue_use( qtes->qs ); + + // TRD : top byte of counter is already our thread number + while( lfds610_queue_enqueue(qtes->qs, (void *) qtes->counter++) ); + + return( (thread_return_t) EXIT_SUCCESS ); +} + + + + + +/****************************************************************************/ +void queue_test_dequeuing( void ) +{ + unsigned int + loop, + cpu_count; + + thread_state_t + *thread_handles; + + struct lfds610_queue_state + *qs; + + struct queue_test_dequeuing_state + *qtds; + + struct lfds610_validation_info + vi = { 0, 0 }; + + enum lfds610_data_structure_validity + dvs[2]; + + /* TRD : create a queue with 1,000,000 elements + + use a single thread to enqueue every element + each elements user data is an incrementing counter + + then run one thread per CPU + where each busy-works dequeuing + + when an element is dequeued, we check (on a per-thread basis) the + value deqeued is greater than the element previously dequeued + */ + + internal_display_test_name( "Dequeuing" ); + + cpu_count = abstraction_cpu_count(); + + lfds610_queue_new( &qs, 1000000 ); + + for( loop = 0 ; loop < 1000000 ; loop++ ) + lfds610_queue_enqueue( qs, (void *) (lfds610_atom_t) loop ); + + qtds = malloc( sizeof(struct queue_test_dequeuing_state) * cpu_count ); + + for( loop = 0 ; loop < cpu_count ; loop++ ) + { + (qtds+loop)->qs = qs; + (qtds+loop)->error_flag = LOWERED; + } + + thread_handles = malloc( sizeof(thread_state_t) * cpu_count ); + + for( loop = 0 ; loop < cpu_count ; loop++ ) + abstraction_thread_start( &thread_handles[loop], loop, queue_test_internal_thread_simple_dequeuer, qtds+loop ); + + for( loop = 0 ; loop < cpu_count ; loop++ ) + abstraction_thread_wait( thread_handles[loop] ); + + free( thread_handles ); + + // TRD : check queue is empty + lfds610_queue_query( qs, LFDS610_QUEUE_QUERY_VALIDATE, (void *) &vi, (void *) dvs ); + + // TRD : check for raised error flags + for( loop = 0 ; loop < cpu_count ; loop++ ) + if( (qtds+loop)->error_flag == RAISED ) + dvs[0] = LFDS610_VALIDITY_INVALID_TEST_DATA; + + free( qtds ); + + lfds610_queue_delete( qs, NULL, NULL ); + + internal_display_test_result( 2, "queue", dvs[0], "queue freelist", dvs[1] ); + + return; +} + + + + + +/****************************************************************************/ +thread_return_t CALLING_CONVENTION queue_test_internal_thread_simple_dequeuer( void *queue_test_dequeuing_state ) +{ + struct queue_test_dequeuing_state + *qtds; + + lfds610_atom_t + *prev_user_data, + *user_data; + + assert( queue_test_dequeuing_state != NULL ); + + qtds = (struct queue_test_dequeuing_state *) queue_test_dequeuing_state; + + lfds610_queue_use( qtds->qs ); + + lfds610_queue_dequeue( qtds->qs, (void *) &prev_user_data ); + + while( lfds610_queue_dequeue(qtds->qs, (void *) &user_data) ) + { + if( user_data <= prev_user_data ) + qtds->error_flag = RAISED; + + prev_user_data = user_data; + } + + return( (thread_return_t) EXIT_SUCCESS ); +} + + + + + +/****************************************************************************/ +void queue_test_enqueuing_and_dequeuing( void ) +{ + unsigned int + loop, + subloop, + cpu_count; + + thread_state_t + *thread_handles; + + struct lfds610_queue_state + *qs; + + struct queue_test_enqueuing_and_dequeuing_state + *qteds; + + struct lfds610_validation_info + vi = { 0, 0 }; + + enum lfds610_data_structure_validity + dvs[2]; + + internal_display_test_name( "Enqueuing and dequeuing (10 seconds)" ); + + cpu_count = abstraction_cpu_count(); + + lfds610_queue_new( &qs, cpu_count ); + + qteds = malloc( sizeof(struct queue_test_enqueuing_and_dequeuing_state) * cpu_count ); + + for( loop = 0 ; loop < cpu_count ; loop++ ) + { + (qteds+loop)->qs = qs; + (qteds+loop)->thread_number = loop; + (qteds+loop)->counter = (lfds610_atom_t) loop << (sizeof(lfds610_atom_t)*8-8); + (qteds+loop)->cpu_count = cpu_count; + (qteds+loop)->error_flag = LOWERED; + (qteds+loop)->per_thread_counters = malloc( sizeof(lfds610_atom_t) * cpu_count ); + + for( subloop = 0 ; subloop < cpu_count ; subloop++ ) + *((qteds+loop)->per_thread_counters+subloop) = 0; + } + + thread_handles = malloc( sizeof(thread_state_t) * cpu_count ); + + for( loop = 0 ; loop < cpu_count ; loop++ ) + abstraction_thread_start( &thread_handles[loop], loop, queue_test_internal_thread_enqueuer_and_dequeuer, qteds+loop ); + + for( loop = 0 ; loop < cpu_count ; loop++ ) + abstraction_thread_wait( thread_handles[loop] ); + + free( thread_handles ); + + lfds610_queue_query( qs, LFDS610_QUEUE_QUERY_VALIDATE, (void *) &vi, (void *) dvs ); + + for( loop = 0 ; loop < cpu_count ; loop++ ) + if( (qteds+loop)->error_flag == RAISED ) + dvs[0] = LFDS610_VALIDITY_INVALID_TEST_DATA; + + for( loop = 0 ; loop < cpu_count ; loop++ ) + free( (qteds+loop)->per_thread_counters ); + + free( qteds ); + + lfds610_queue_delete( qs, NULL, NULL ); + + internal_display_test_result( 2, "queue", dvs[0], "queue freelist", dvs[1] ); + + return; +} + + + + + +/****************************************************************************/ +thread_return_t CALLING_CONVENTION queue_test_internal_thread_enqueuer_and_dequeuer( void *queue_test_enqueuing_and_dequeuing_state ) +{ + struct queue_test_enqueuing_and_dequeuing_state + *qteds; + + time_t + start_time; + + lfds610_atom_t + thread, + count, + user_data; + + assert( queue_test_enqueuing_and_dequeuing_state != NULL ); + + qteds = (struct queue_test_enqueuing_and_dequeuing_state *) queue_test_enqueuing_and_dequeuing_state; + + lfds610_queue_use( qteds->qs ); + + time( &start_time ); + + while( time(NULL) < start_time + 10 ) + { + lfds610_queue_enqueue( qteds->qs, (void *) (qteds->counter++) ); + lfds610_queue_dequeue( qteds->qs, (void *) &user_data ); + + thread = user_data >> (sizeof(lfds610_atom_t)*8-8); + count = (user_data << 8) >> 8; + + if( thread >= qteds->cpu_count ) + qteds->error_flag = RAISED; + else + { + if( count < qteds->per_thread_counters[thread] ) + qteds->error_flag = RAISED; + + if( count >= qteds->per_thread_counters[thread] ) + qteds->per_thread_counters[thread] = count+1; + } + } + + return( (thread_return_t) EXIT_SUCCESS ); +} + + + + + +/****************************************************************************/ +void queue_test_rapid_enqueuing_and_dequeuing( void ) +{ + unsigned int + loop, + cpu_count; + + thread_state_t + *thread_handles; + + struct lfds610_queue_state + *qs; + + struct queue_test_rapid_enqueuing_and_dequeuing_state + *qtreds; + + struct lfds610_validation_info + vi = { 50000, 50000 }; + + lfds610_atom_t + user_data, + thread, + count, + *per_thread_counters; + + enum lfds610_data_structure_validity + dvs[2]; + + internal_display_test_name( "Rapid enqueuing and dequeuing (10 seconds)" ); + + cpu_count = abstraction_cpu_count(); + + lfds610_queue_new( &qs, 100000 ); + + for( loop = 0 ; loop < 50000 ; loop++ ) + lfds610_queue_enqueue( qs, NULL ); + + qtreds = malloc( sizeof(struct queue_test_rapid_enqueuing_and_dequeuing_state) * cpu_count ); + + for( loop = 0 ; loop < cpu_count ; loop++ ) + { + (qtreds+loop)->qs = qs; + (qtreds+loop)->counter = (lfds610_atom_t) loop << (sizeof(lfds610_atom_t)*8-8); + } + + thread_handles = malloc( sizeof(thread_state_t) * cpu_count ); + + for( loop = 0 ; loop < cpu_count ; loop++ ) + abstraction_thread_start( &thread_handles[loop], loop, queue_test_internal_thread_rapid_enqueuer_and_dequeuer, qtreds+loop ); + + for( loop = 0 ; loop < cpu_count ; loop++ ) + abstraction_thread_wait( thread_handles[loop] ); + + free( thread_handles ); + + lfds610_queue_query( qs, LFDS610_QUEUE_QUERY_VALIDATE, (void *) &vi, (void *) dvs ); + + // TRD : now check results + per_thread_counters = malloc( sizeof(lfds610_atom_t) * cpu_count ); + + for( loop = 0 ; loop < cpu_count ; loop++ ) + *(per_thread_counters+loop) = 0; + + while( dvs[0] == LFDS610_VALIDITY_VALID and dvs[1] == LFDS610_VALIDITY_VALID and lfds610_queue_dequeue(qs, (void *) &user_data) ) + { + thread = user_data >> (sizeof(lfds610_atom_t)*8-8); + count = (user_data << 8) >> 8; + + if( thread >= cpu_count ) + { + dvs[0] = LFDS610_VALIDITY_INVALID_TEST_DATA; + break; + } + + if( per_thread_counters[thread] == 0 ) + per_thread_counters[thread] = count; + + if( count < per_thread_counters[thread] ) + dvs[0] = LFDS610_VALIDITY_INVALID_ADDITIONAL_ELEMENTS; + + if( count >= per_thread_counters[thread] ) + per_thread_counters[thread] = count+1; + } + + free( per_thread_counters ); + + free( qtreds ); + + lfds610_queue_delete( qs, NULL, NULL ); + + internal_display_test_result( 2, "queue", dvs[0], "queue freelist", dvs[1] ); + + return; +} + + + + + +/****************************************************************************/ +thread_return_t CALLING_CONVENTION queue_test_internal_thread_rapid_enqueuer_and_dequeuer( void *queue_test_rapid_enqueuing_and_dequeuing_state ) +{ + struct queue_test_rapid_enqueuing_and_dequeuing_state + *qtreds; + + time_t + start_time; + + lfds610_atom_t + user_data; + + assert( queue_test_rapid_enqueuing_and_dequeuing_state != NULL ); + + qtreds = (struct queue_test_rapid_enqueuing_and_dequeuing_state *) queue_test_rapid_enqueuing_and_dequeuing_state; + + lfds610_queue_use( qtreds->qs ); + + time( &start_time ); + + while( time(NULL) < start_time + 10 ) + { + lfds610_queue_enqueue( qtreds->qs, (void *) (qtreds->counter++) ); + lfds610_queue_dequeue( qtreds->qs, (void *) &user_data ); + } + + return( (thread_return_t) EXIT_SUCCESS ); +} + diff --git a/liblfds/liblfds6.1.0/test/src/test_ringbuffer.c b/liblfds/liblfds6.1.0/test/src/test_ringbuffer.c new file mode 100644 index 0000000..abd4cfc --- /dev/null +++ b/liblfds/liblfds6.1.0/test/src/test_ringbuffer.c @@ -0,0 +1,480 @@ +#include "internal.h" + + + + + +/****************************************************************************/ +void test_lfds610_ringbuffer( void ) +{ + printf( "\n" + "Ringbuffer Tests\n" + "================\n" ); + + ringbuffer_test_reading(); + ringbuffer_test_writing(); + ringbuffer_test_reading_and_writing(); + + return; +} + + + + + +/****************************************************************************/ +void ringbuffer_test_reading( void ) +{ + unsigned int + loop, + cpu_count; + + thread_state_t + *thread_handles; + + struct lfds610_ringbuffer_state + *rs; + + struct lfds610_freelist_element + *fe; + + struct ringbuffer_test_reading_state + *rtrs; + + struct lfds610_validation_info + vi = { 0, 0 }; + + enum lfds610_data_structure_validity + dvs[3]; + + lfds610_atom_t + total_read = 0; + + /* TRD : we create a single ringbuffer + with 1,000,000 elements + we populate the ringbuffer, where the + user data is an incrementing counter + + we create one thread per CPU + where each thread busy-works, + reading until the ringbuffer is empty + + each thread keeps track of the number of reads it manages + and that each user data it reads is greater than the + previous user data that was read + */ + + internal_display_test_name( "Reading" ); + + cpu_count = abstraction_cpu_count(); + + lfds610_ringbuffer_new( &rs, 1000000, NULL, NULL ); + + for( loop = 0 ; loop < 1000000 ; loop++ ) + { + lfds610_ringbuffer_get_write_element( rs, &fe, NULL ); + lfds610_freelist_set_user_data_in_element( fe, (void *) (lfds610_atom_t) loop ); + lfds610_ringbuffer_put_write_element( rs, fe ); + } + + rtrs = malloc( sizeof(struct ringbuffer_test_reading_state) * cpu_count ); + + for( loop = 0 ; loop < cpu_count ; loop++ ) + { + (rtrs+loop)->rs = rs; + (rtrs+loop)->read_count = 0; + (rtrs+loop)->error_flag = LOWERED; + } + + thread_handles = malloc( sizeof(thread_state_t) * cpu_count ); + + for( loop = 0 ; loop < cpu_count ; loop++ ) + abstraction_thread_start( &thread_handles[loop], loop, ringbuffer_test_thread_simple_reader, rtrs+loop ); + + for( loop = 0 ; loop < cpu_count ; loop++ ) + abstraction_thread_wait( thread_handles[loop] ); + + free( thread_handles ); + + lfds610_ringbuffer_query( rs, LFDS610_RINGBUFFER_QUERY_VALIDATE, (void *) &vi, (void *) dvs ); + + // TRD : check for raised error flags + for( loop = 0 ; loop < cpu_count ; loop++ ) + if( (rtrs+loop)->error_flag == RAISED ) + dvs[0] = LFDS610_VALIDITY_INVALID_TEST_DATA; + + // TRD : check thread reads total to 1,000,000 + for( loop = 0 ; loop < cpu_count ; loop++ ) + total_read += (rtrs+loop)->read_count; + + if( total_read < 1000000 ) + dvs[0] = LFDS610_VALIDITY_INVALID_MISSING_ELEMENTS; + + if( total_read > 1000000 ) + dvs[0] = LFDS610_VALIDITY_INVALID_ADDITIONAL_ELEMENTS; + + free( rtrs ); + + lfds610_ringbuffer_delete( rs, NULL, NULL ); + + internal_display_test_result( 3, "queue", dvs[0], "queue freelist", dvs[1], "freelist", dvs[2] ); + + return; +} + + + + + +/****************************************************************************/ +thread_return_t CALLING_CONVENTION ringbuffer_test_thread_simple_reader( void *ringbuffer_test_reading_state ) +{ + struct ringbuffer_test_reading_state + *rtrs; + + struct lfds610_freelist_element + *fe; + + lfds610_atom_t + *prev_user_data, + *user_data; + + assert( ringbuffer_test_reading_state != NULL ); + + rtrs = (struct ringbuffer_test_reading_state *) ringbuffer_test_reading_state; + + lfds610_ringbuffer_use( rtrs->rs ); + + /* TRD : read an initial element to load a value into prev_user_data + it may be (under valgrind for example) that by the time we start + there are no elements remaining to read + */ + + lfds610_ringbuffer_get_read_element( rtrs->rs, &fe ); + if( fe == NULL ) + return( (thread_return_t) EXIT_SUCCESS ); + lfds610_freelist_get_user_data_from_element( fe, (void **) &prev_user_data ); + lfds610_ringbuffer_put_read_element( rtrs->rs, fe ); + + rtrs->read_count++; + + while( lfds610_ringbuffer_get_read_element(rtrs->rs, &fe) ) + { + lfds610_freelist_get_user_data_from_element( fe, (void **) &user_data ); + lfds610_ringbuffer_put_read_element( rtrs->rs, fe ); + + if( user_data <= prev_user_data ) + rtrs->error_flag = RAISED; + + prev_user_data = user_data; + + rtrs->read_count++; + } + + return( (thread_return_t) EXIT_SUCCESS ); +} + + + + + +/****************************************************************************/ +void ringbuffer_test_writing( void ) +{ + unsigned int + loop, + cpu_count; + + thread_state_t + *thread_handles; + + struct lfds610_ringbuffer_state + *rs; + + struct lfds610_freelist_element + *fe; + + struct ringbuffer_test_writing_state + *rtws; + + struct lfds610_validation_info + vi = { 100000, 100000 }; + + enum lfds610_data_structure_validity + dvs[3]; + + lfds610_atom_t + thread, + count, + user_data, + *per_thread_counters; + + /* TRD : we create a single ringbuffer + with 100000 elements + the ringbuffers starts empty + + we create one thread per CPU + where each thread busy-works writing + for ten seconds + + the user data in each written element is a combination + of the thread number and the counter + + after the threads are complete, we validate by + checking the user data counters increment on a per thread + basis + */ + + internal_display_test_name( "Writing (10 seconds)" ); + + cpu_count = abstraction_cpu_count(); + + lfds610_ringbuffer_new( &rs, 100000, NULL, NULL ); + + rtws = malloc( sizeof(struct ringbuffer_test_writing_state) * cpu_count ); + + for( loop = 0 ; loop < cpu_count ; loop++ ) + { + (rtws+loop)->rs = rs; + (rtws+loop)->write_count = (lfds610_atom_t) loop << (sizeof(lfds610_atom_t)*8-8); + } + + thread_handles = malloc( sizeof(thread_state_t) * cpu_count ); + + for( loop = 0 ; loop < cpu_count ; loop++ ) + abstraction_thread_start( &thread_handles[loop], loop, ringbuffer_test_thread_simple_writer, rtws+loop ); + + for( loop = 0 ; loop < cpu_count ; loop++ ) + abstraction_thread_wait( thread_handles[loop] ); + + free( thread_handles ); + + // TRD : now check results + per_thread_counters = malloc( sizeof(lfds610_atom_t) * cpu_count ); + + for( loop = 0 ; loop < cpu_count ; loop++ ) + *(per_thread_counters+loop) = 0; + + lfds610_ringbuffer_query( rs, LFDS610_RINGBUFFER_QUERY_VALIDATE, (void *) &vi, (void *) dvs ); + + while( dvs[0] == LFDS610_VALIDITY_VALID and dvs[1] == LFDS610_VALIDITY_VALID and dvs[2] == LFDS610_VALIDITY_VALID and lfds610_ringbuffer_get_read_element(rs, &fe) ) + { + lfds610_freelist_get_user_data_from_element( fe, (void *) &user_data ); + + thread = user_data >> (sizeof(lfds610_atom_t)*8-8); + count = (user_data << 8) >> 8; + + if( thread >= cpu_count ) + { + dvs[0] = LFDS610_VALIDITY_INVALID_TEST_DATA; + lfds610_ringbuffer_put_read_element( rs, fe ); + break; + } + + if( per_thread_counters[thread] == 0 ) + per_thread_counters[thread] = count; + + if( count < per_thread_counters[thread] ) + dvs[0] = LFDS610_VALIDITY_INVALID_ADDITIONAL_ELEMENTS; + + if( count >= per_thread_counters[thread] ) + per_thread_counters[thread] = count+1; + + lfds610_ringbuffer_put_read_element( rs, fe ); + } + + free( per_thread_counters ); + + free( rtws ); + + lfds610_ringbuffer_delete( rs, NULL, NULL ); + + internal_display_test_result( 3, "queue", dvs[0], "queue freelist", dvs[1], "freelist", dvs[2] ); + + return; +} + + + + + +/****************************************************************************/ +thread_return_t CALLING_CONVENTION ringbuffer_test_thread_simple_writer( void *ringbuffer_test_writing_state ) +{ + struct ringbuffer_test_writing_state + *rtws; + + struct lfds610_freelist_element + *fe; + + time_t + start_time; + + assert( ringbuffer_test_writing_state != NULL ); + + rtws = (struct ringbuffer_test_writing_state *) ringbuffer_test_writing_state; + + lfds610_ringbuffer_use( rtws->rs ); + + time( &start_time ); + + while( time(NULL) < start_time + 10 ) + { + lfds610_ringbuffer_get_write_element( rtws->rs, &fe, NULL ); + lfds610_freelist_set_user_data_in_element( fe, (void *) (lfds610_atom_t) (rtws->write_count++) ); + lfds610_ringbuffer_put_write_element( rtws->rs, fe ); + } + + return( (thread_return_t) EXIT_SUCCESS ); +} + + + + + +/****************************************************************************/ +void ringbuffer_test_reading_and_writing( void ) +{ + unsigned int + loop, + subloop, + cpu_count; + + thread_state_t + *thread_handles; + + struct lfds610_ringbuffer_state + *rs; + + struct ringbuffer_test_reading_and_writing_state + *rtrws; + + struct lfds610_validation_info + vi = { 0, 0 }; + + enum lfds610_data_structure_validity + dvs[3]; + + /* TRD : we create a single ringbuffer + with 100000 elements + the ringbuffers starts empty + + we create one thread per CPU + where each thread busy-works writing + and then immediately reading + for ten seconds + + the user data in each written element is a combination + of the thread number and the counter + + while a thread runs, it keeps track of the + counters for the other threads and throws an error + if it sees the number stay the same or decrease + */ + + internal_display_test_name( "Reading and writing (10 seconds)" ); + + cpu_count = abstraction_cpu_count(); + + lfds610_ringbuffer_new( &rs, 100000, NULL, NULL ); + + rtrws = malloc( sizeof(struct ringbuffer_test_reading_and_writing_state) * cpu_count ); + + for( loop = 0 ; loop < cpu_count ; loop++ ) + { + (rtrws+loop)->rs = rs; + (rtrws+loop)->counter = (lfds610_atom_t) loop << (sizeof(lfds610_atom_t)*8-8); + (rtrws+loop)->cpu_count = cpu_count; + (rtrws+loop)->error_flag = LOWERED; + (rtrws+loop)->per_thread_counters = malloc( sizeof(lfds610_atom_t) * cpu_count ); + + for( subloop = 0 ; subloop < cpu_count ; subloop++ ) + *((rtrws+loop)->per_thread_counters+subloop) = 0; + } + + thread_handles = malloc( sizeof(thread_state_t) * cpu_count ); + + for( loop = 0 ; loop < cpu_count ; loop++ ) + abstraction_thread_start( &thread_handles[loop], loop, ringbuffer_test_thread_reader_writer, rtrws+loop ); + + for( loop = 0 ; loop < cpu_count ; loop++ ) + abstraction_thread_wait( thread_handles[loop] ); + + free( thread_handles ); + + lfds610_ringbuffer_query( rs, LFDS610_RINGBUFFER_QUERY_VALIDATE, (void *) &vi, (void *) dvs ); + + for( loop = 0 ; loop < cpu_count ; loop++ ) + if( (rtrws+loop)->error_flag == RAISED ) + dvs[0] = LFDS610_VALIDITY_INVALID_TEST_DATA; + + for( loop = 0 ; loop < cpu_count ; loop++ ) + free( (rtrws+loop)->per_thread_counters ); + + free( rtrws ); + + lfds610_ringbuffer_delete( rs, NULL, NULL ); + + internal_display_test_result( 3, "queue", dvs[0], "queue freelist", dvs[1], "freelist", dvs[2] ); + + return; +} + + + + + +/****************************************************************************/ +thread_return_t CALLING_CONVENTION ringbuffer_test_thread_reader_writer( void *ringbuffer_test_reading_and_writing_state ) +{ + struct ringbuffer_test_reading_and_writing_state + *rtrws; + + struct lfds610_freelist_element + *fe; + + lfds610_atom_t + user_data, + thread, + count; + + time_t + start_time; + + assert( ringbuffer_test_reading_and_writing_state != NULL ); + + rtrws = (struct ringbuffer_test_reading_and_writing_state *) ringbuffer_test_reading_and_writing_state; + + lfds610_ringbuffer_use( rtrws->rs ); + + time( &start_time ); + + while( time(NULL) < start_time + 10 ) + { + lfds610_ringbuffer_get_write_element( rtrws->rs, &fe, NULL ); + lfds610_freelist_set_user_data_in_element( fe, (void *) (lfds610_atom_t) (rtrws->counter++) ); + lfds610_ringbuffer_put_write_element( rtrws->rs, fe ); + + lfds610_ringbuffer_get_read_element( rtrws->rs, &fe ); + lfds610_freelist_get_user_data_from_element( fe, (void *) &user_data ); + + thread = user_data >> (sizeof(lfds610_atom_t)*8-8); + count = (user_data << 8) >> 8; + + if( thread >= rtrws->cpu_count ) + rtrws->error_flag = RAISED; + else + { + if( count < rtrws->per_thread_counters[thread] ) + rtrws->error_flag = RAISED; + + if( count >= rtrws->per_thread_counters[thread] ) + rtrws->per_thread_counters[thread] = count+1; + } + + lfds610_ringbuffer_put_read_element( rtrws->rs, fe ); + } + + return( (thread_return_t) EXIT_SUCCESS ); +} + diff --git a/liblfds/liblfds6.1.0/test/src/test_slist.c b/liblfds/liblfds6.1.0/test/src/test_slist.c new file mode 100644 index 0000000..1303efb --- /dev/null +++ b/liblfds/liblfds6.1.0/test/src/test_slist.c @@ -0,0 +1,402 @@ +#include "internal.h" + + + + + +/****************************************************************************/ +void test_lfds610_slist( void ) +{ + printf( "\n" + "SList Tests\n" + "===========\n" ); + + test_slist_new_delete_get(); + test_slist_get_set_user_data(); + test_slist_delete_all_elements(); + + return; +} + + + + + +/****************************************************************************/ +void test_slist_new_delete_get( void ) +{ + unsigned int + loop, + cpu_count; + + struct lfds610_slist_state + *ss; + + struct lfds610_slist_element + *se = NULL; + + struct slist_test_state + *sts; + + thread_state_t + *thread_handles; + + size_t + total_create_count = 0, + total_delete_count = 0, + element_count = 0; + + enum lfds610_data_structure_validity + dvs = LFDS610_VALIDITY_VALID; + + /* TRD : two threads per CPU + first simply alternates between new_head() and new_next() (next on element created by head) + second calls get_next, if NULL, then calls get_head, and deletes the element + both threads keep count of created and deleted + validate is to reconcile created, deleted and remaining in list + */ + + internal_display_test_name( "New head/next, delete and get next" ); + + cpu_count = abstraction_cpu_count(); + + lfds610_slist_new( &ss, NULL, NULL ); + + sts = malloc( sizeof(struct slist_test_state) * cpu_count * 2 ); + + for( loop = 0 ; loop < cpu_count * 2 ; loop++ ) + { + (sts+loop)->ss = ss; + (sts+loop)->create_count = 0; + (sts+loop)->delete_count = 0; + } + + thread_handles = malloc( sizeof(thread_state_t) * cpu_count * 2 ); + + for( loop = 0 ; loop < cpu_count ; loop++ ) + { + abstraction_thread_start( &thread_handles[loop], loop, slist_test_internal_thread_new_delete_get_new_head_and_next, sts+loop ); + abstraction_thread_start( &thread_handles[loop+cpu_count], loop, slist_test_internal_thread_new_delete_get_delete_and_get, sts+loop+cpu_count ); + } + + for( loop = 0 ; loop < cpu_count * 2 ; loop++ ) + abstraction_thread_wait( thread_handles[loop] ); + + free( thread_handles ); + + // TRD : now validate + for( loop = 0 ; loop < cpu_count * 2 ; loop++ ) + { + total_create_count += (sts+loop)->create_count; + total_delete_count += (sts+loop)->delete_count; + } + + while( NULL != lfds610_slist_get_head_and_then_next(ss, &se) ) + element_count++; + + if( total_create_count - total_delete_count - element_count != 0 ) + dvs = LFDS610_VALIDITY_INVALID_TEST_DATA; + + free( sts ); + + lfds610_slist_delete( ss ); + + internal_display_test_result( 1, "slist", dvs ); + + return; +} + + + + + +/****************************************************************************/ +thread_return_t CALLING_CONVENTION slist_test_internal_thread_new_delete_get_new_head_and_next( void *slist_test_state ) +{ + struct slist_test_state + *sts; + + time_t + start_time; + + struct lfds610_slist_element + *se = NULL; + + assert( slist_test_state != NULL ); + + sts = (struct slist_test_state *) slist_test_state; + + lfds610_slist_use( sts->ss ); + + time( &start_time ); + + while( time(NULL) < start_time + 1 ) + { + if( sts->create_count % 2 == 0 ) + se = lfds610_slist_new_head( sts->ss, NULL ); + else + lfds610_slist_new_next( se, NULL ); + + sts->create_count++; + } + + return( (thread_return_t) EXIT_SUCCESS ); +} + + + + + +/****************************************************************************/ +thread_return_t CALLING_CONVENTION slist_test_internal_thread_new_delete_get_delete_and_get( void *slist_test_state ) +{ + struct slist_test_state + *sts; + + time_t + start_time; + + struct lfds610_slist_element + *se = NULL; + + assert( slist_test_state != NULL ); + + sts = (struct slist_test_state *) slist_test_state; + + lfds610_slist_use( sts->ss ); + + time( &start_time ); + + while( time(NULL) < start_time + 1 ) + { + if( se == NULL ) + lfds610_slist_get_head( sts->ss, &se ); + else + lfds610_slist_get_next( se, &se ); + + if( se != NULL ) + { + if( 1 == lfds610_slist_logically_delete_element(sts->ss, se) ) + sts->delete_count++; + } + } + + return( (thread_return_t) EXIT_SUCCESS ); +} + + + + + +/****************************************************************************/ +void test_slist_get_set_user_data( void ) +{ + unsigned int + loop, + cpu_count; + + struct lfds610_slist_state + *ss; + + struct lfds610_slist_element + *se = NULL; + + struct slist_test_state + *sts; + + thread_state_t + *thread_handles; + + lfds610_atom_t + thread_and_count, + thread, + count, + *per_thread_counters, + *per_thread_drop_flags; + + enum lfds610_data_structure_validity + dvs = LFDS610_VALIDITY_VALID; + + /* TRD : create a list of (cpu_count*10) elements, user data 0 + one thread per CPU + each thread loops, setting user_data to ((thread_number << (sizeof(lfds610_atom_t)*8-8)) | count) + validation is to scan list, count on a per thread basis should go down only once + */ + + internal_display_test_name( "Get and set user data" ); + + cpu_count = abstraction_cpu_count(); + + lfds610_slist_new( &ss, NULL, NULL ); + + for( loop = 0 ; loop < cpu_count * 10 ; loop++ ) + lfds610_slist_new_head( ss, NULL ); + + sts = malloc( sizeof(struct slist_test_state) * cpu_count ); + + for( loop = 0 ; loop < cpu_count ; loop++ ) + { + (sts+loop)->ss = ss; + (sts+loop)->thread_and_count = (lfds610_atom_t) loop << (sizeof(lfds610_atom_t)*8-8); + } + + thread_handles = malloc( sizeof(thread_state_t) * cpu_count ); + + for( loop = 0 ; loop < cpu_count ; loop++ ) + abstraction_thread_start( &thread_handles[loop], loop, slist_test_internal_thread_get_set_user_data, sts+loop ); + + for( loop = 0 ; loop < cpu_count ; loop++ ) + abstraction_thread_wait( thread_handles[loop] ); + + free( thread_handles ); + + // now validate + per_thread_counters = malloc( sizeof(lfds610_atom_t) * cpu_count ); + per_thread_drop_flags = malloc( sizeof(lfds610_atom_t) * cpu_count ); + + for( loop = 0 ; loop < cpu_count ; loop++ ) + { + *(per_thread_counters+loop) = 0; + *(per_thread_drop_flags+loop) = 0; + } + + while( dvs == LFDS610_VALIDITY_VALID and NULL != lfds610_slist_get_head_and_then_next(ss, &se) ) + { + lfds610_slist_get_user_data_from_element( se, (void **) &thread_and_count ); + + thread = thread_and_count >> (sizeof(lfds610_atom_t)*8-8); + count = (thread_and_count << 8) >> 8; + + if( thread >= cpu_count ) + { + dvs = LFDS610_VALIDITY_INVALID_TEST_DATA; + break; + } + + if( per_thread_counters[thread] == 0 ) + { + per_thread_counters[thread] = count; + continue; + } + + per_thread_counters[thread]++; + + if( count < per_thread_counters[thread] and per_thread_drop_flags[thread] == 1 ) + { + dvs = LFDS610_VALIDITY_INVALID_ADDITIONAL_ELEMENTS; + break; + } + + if( count < per_thread_counters[thread] and per_thread_drop_flags[thread] == 0 ) + { + per_thread_drop_flags[thread] = 1; + per_thread_counters[thread] = count; + continue; + } + + if( count < per_thread_counters[thread] ) + dvs = LFDS610_VALIDITY_INVALID_ADDITIONAL_ELEMENTS; + + if( count >= per_thread_counters[thread] ) + per_thread_counters[thread] = count; + } + + free( per_thread_drop_flags ); + free( per_thread_counters ); + + free( sts ); + + lfds610_slist_delete( ss ); + + internal_display_test_result( 1, "slist", dvs ); + + return; +} + + + + + +/****************************************************************************/ +thread_return_t CALLING_CONVENTION slist_test_internal_thread_get_set_user_data( void *slist_test_state ) +{ + struct slist_test_state + *sts; + + time_t + start_time; + + struct lfds610_slist_element + *se = NULL; + + assert( slist_test_state != NULL ); + + sts = (struct slist_test_state *) slist_test_state; + + lfds610_slist_use( sts->ss ); + + time( &start_time ); + + while( time(NULL) < start_time + 1 ) + { + if( se == NULL ) + lfds610_slist_get_head( sts->ss, &se ); + + lfds610_slist_set_user_data_in_element( se, (void *) sts->thread_and_count++ ); + + lfds610_slist_get_next( se, &se ); + } + + return( (thread_return_t) EXIT_SUCCESS ); +} + + + + + +/****************************************************************************/ +void test_slist_delete_all_elements( void ) +{ + struct lfds610_slist_state + *ss; + + struct lfds610_slist_element + *se = NULL; + + size_t + element_count = 0; + + unsigned int + loop; + + enum lfds610_data_structure_validity + dvs = LFDS610_VALIDITY_VALID; + + /* TRD : this test creates a list of 100,000 elements + then simply calls delete_all_elements() + we then count the number of elements remaining + should be zero :-) + */ + + internal_display_test_name( "Delete all elements" ); + + lfds610_slist_new( &ss, NULL, NULL ); + + for( loop = 0 ; loop < 1000000 ; loop++ ) + lfds610_slist_new_head( ss, NULL ); + + lfds610_slist_single_threaded_physically_delete_all_elements( ss ); + + while( NULL != lfds610_slist_get_head_and_then_next(ss, &se) ) + element_count++; + + if( element_count != 0 ) + dvs = LFDS610_VALIDITY_INVALID_TEST_DATA; + + lfds610_slist_delete( ss ); + + internal_display_test_result( 1, "slist", dvs ); + + return; +} + diff --git a/liblfds/liblfds6.1.0/test/src/test_stack.c b/liblfds/liblfds6.1.0/test/src/test_stack.c new file mode 100644 index 0000000..295e4c4 --- /dev/null +++ b/liblfds/liblfds6.1.0/test/src/test_stack.c @@ -0,0 +1,590 @@ +#include "internal.h" + + + + + +/****************************************************************************/ +void test_lfds610_stack( void ) +{ + printf( "\n" + "Stack Tests\n" + "===========\n" ); + + stack_test_internal_popping(); + stack_test_internal_pushing(); + stack_test_internal_popping_and_pushing(); + stack_test_internal_rapid_popping_and_pushing(); + + return; +} + + + + + +/****************************************************************************/ +void stack_test_internal_popping( void ) +{ + unsigned int + loop, + *found_count, + cpu_count; + + lfds610_atom_t + count; + + thread_state_t + *thread_handles; + + enum lfds610_data_structure_validity + dvs = LFDS610_VALIDITY_VALID; + + struct lfds610_stack_state + *ss; + + struct stack_test_popping_state + *stps; + + /* TRD : we create a stack with 1,000,000 elements + + we then populate the stack, where each element is + set to contain a void pointer which is its element number + + we then run one thread per CPU + where each thread loops, popping as quickly as possible + each popped element is pushed onto a thread-local stack + + the threads run till the source stack is empty + + we then check the thread-local stacks + we should find we have every element + + then tidy up + */ + + internal_display_test_name( "Popping" ); + + cpu_count = abstraction_cpu_count(); + + lfds610_stack_new( &ss, 1000000 ); + + for( loop = 0 ; loop < 1000000 ; loop++ ) + lfds610_stack_push( ss, (void *) (lfds610_atom_t) loop ); + + stps = malloc( sizeof(struct stack_test_popping_state) * cpu_count ); + for( loop = 0 ; loop < cpu_count ; loop++ ) + { + (stps+loop)->ss = ss; + lfds610_stack_new( &(stps+loop)->ss_thread_local, 1000000 ); + } + + thread_handles = malloc( sizeof(thread_state_t) * cpu_count ); + + for( loop = 0 ; loop < cpu_count ; loop++ ) + abstraction_thread_start( &thread_handles[loop], loop, stack_test_internal_thread_popping, stps+loop ); + + for( loop = 0 ; loop < cpu_count ; loop++ ) + abstraction_thread_wait( thread_handles[loop] ); + + free( thread_handles ); + + // TRD : now we check the thread-local stacks + found_count = malloc( sizeof(unsigned int) * 1000000 ); + for( loop = 0 ; loop < 1000000 ; loop++ ) + *(found_count+loop) = 0; + + for( loop = 0 ; loop < cpu_count ; loop++ ) + while( lfds610_stack_pop((stps+loop)->ss_thread_local, (void **) &count) ) + (*(found_count+count))++; + + for( loop = 0 ; loop < 1000000 and dvs == LFDS610_VALIDITY_VALID ; loop++ ) + { + if( *(found_count+loop) == 0 ) + dvs = LFDS610_VALIDITY_INVALID_MISSING_ELEMENTS; + + if( *(found_count+loop) > 1 ) + dvs = LFDS610_VALIDITY_INVALID_ADDITIONAL_ELEMENTS; + } + + // TRD : cleanup + free( found_count ); + for( loop = 0 ; loop < cpu_count ; loop++ ) + lfds610_stack_delete( (stps+loop)->ss_thread_local, NULL, NULL ); + free( stps ); + lfds610_stack_delete( ss, NULL, NULL ); + + // TRD : print the test result + internal_display_test_result( 1, "stack", dvs ); + + return; +} + + + + + +/****************************************************************************/ +thread_return_t CALLING_CONVENTION stack_test_internal_thread_popping( void *stack_test_popping_state ) +{ + struct stack_test_popping_state + *stps; + + lfds610_atom_t + count; + + assert( stack_test_popping_state != NULL ); + + stps = (struct stack_test_popping_state *) stack_test_popping_state; + + lfds610_stack_use( stps->ss ); + + while( lfds610_stack_pop(stps->ss, (void **) &count) ) + lfds610_stack_push( stps->ss_thread_local, (void *) count ); + + return( (thread_return_t) EXIT_SUCCESS ); +} + + + + + +/****************************************************************************/ +void stack_test_internal_pushing( void ) +{ + unsigned int + loop, + cpu_count; + + thread_state_t + *thread_handles; + + enum lfds610_data_structure_validity + dvs[2]; + + struct stack_test_pushing_state + *stps; + + struct lfds610_stack_state + *ss; + + lfds610_atom_t + user_data, + thread, + count, + *per_thread_counters; + + struct lfds610_validation_info + vi = { 1000000, 1000000 }; + + /* TRD : we create a stack with 1,000,000 elements + + we then create one thread per CPU, where each thread + pushes as quickly as possible to the stack + + the data pushed is a counter and a thread ID + + the threads exit when the stack is full + + we then validate the stack; + + checking that the counts increment on a per unique ID basis + and that the number of elements we pop equals 1,000,000 + (since each element has an incrementing counter which is + unique on a per unique ID basis, we can know we didn't lose + any elements) + */ + + internal_display_test_name( "Pushing" ); + + cpu_count = abstraction_cpu_count(); + + stps = malloc( sizeof(struct stack_test_pushing_state) * cpu_count ); + + // TRD : the main stack + lfds610_stack_new( &ss, 1000000 ); + + for( loop = 0 ; loop < cpu_count ; loop++ ) + { + (stps+loop)->thread_number = (lfds610_atom_t) loop; + (stps+loop)->ss = ss; + } + + thread_handles = malloc( sizeof(thread_state_t) * cpu_count ); + + for( loop = 0 ; loop < cpu_count ; loop++ ) + abstraction_thread_start( &thread_handles[loop], loop, stack_test_internal_thread_pushing, stps+loop ); + + for( loop = 0 ; loop < cpu_count ; loop++ ) + abstraction_thread_wait( thread_handles[loop] ); + + free( thread_handles ); + + // TRD : the stack is now fully pushed; time to verify + per_thread_counters = malloc( sizeof(lfds610_atom_t) * cpu_count ); + + for( loop = 0 ; loop < cpu_count ; loop++ ) + *(per_thread_counters+loop) = 1000000; + + lfds610_stack_query( ss, LFDS610_STACK_QUERY_VALIDATE, &vi, (void *) dvs ); + + while( dvs[0] == LFDS610_VALIDITY_VALID and lfds610_stack_pop(ss, (void **) &user_data) ) + { + thread = user_data >> (sizeof(lfds610_atom_t)*8-8); + count = (user_data << 8) >> 8; + + if( thread >= cpu_count ) + { + dvs[0] = LFDS610_VALIDITY_INVALID_TEST_DATA; + break; + } + + if( count > per_thread_counters[thread] ) + dvs[0] = LFDS610_VALIDITY_INVALID_ADDITIONAL_ELEMENTS; + + if( count < per_thread_counters[thread] ) + per_thread_counters[thread] = count-1; + } + + // TRD : clean up + free( per_thread_counters ); + + free( stps ); + + lfds610_stack_delete( ss, NULL, NULL ); + + // TRD : print the test result + internal_display_test_result( 2, "stack", dvs[0], "stack freelist", dvs[1] ); + + return; +} + + + + + +/****************************************************************************/ +thread_return_t CALLING_CONVENTION stack_test_internal_thread_pushing( void *stack_test_pushing_state ) +{ + struct stack_test_pushing_state + *stps; + + lfds610_atom_t + counter = 0; + + assert( stack_test_pushing_state != NULL ); + + stps = (struct stack_test_pushing_state *) stack_test_pushing_state; + + lfds610_stack_use( stps->ss ); + + // TRD : we write (thread_number | counter), where thread_number is the top 8 bits of the lfds610_atom_t + while( lfds610_stack_push(stps->ss, (void **) ((stps->thread_number << (sizeof(lfds610_atom_t)*8-8)) | counter++)) ); + + return( (thread_return_t) EXIT_SUCCESS ); +} + + + + + +/****************************************************************************/ +void stack_test_internal_popping_and_pushing( void ) +{ + unsigned int + loop, + subloop, + cpu_count; + + thread_state_t + *thread_handles; + + enum lfds610_data_structure_validity + dvs[2]; + + struct lfds610_stack_state + *ss; + + struct stack_test_popping_and_pushing_state + *stpps; + + struct lfds610_validation_info + vi; + + /* TRD : we have two threads per CPU + the threads loop for ten seconds + the first thread pushes 100000 elements then pops 100000 elements + the second thread pops 100000 elements then pushes 100000 elements + all pushes and pops go onto the single main stack + + after time is up, all threads push what they have remaining onto + the main stack + + we then validate the main stack + */ + + internal_display_test_name( "Popping and pushing (10 seconds)" ); + + cpu_count = abstraction_cpu_count(); + + // TRD : just some initial elements so the pushing threads can start immediately + lfds610_stack_new( &ss, 100000 * cpu_count * 2 ); + + for( loop = 0 ; loop < 100000 * cpu_count ; loop++ ) + lfds610_stack_push( ss, (void *) (lfds610_atom_t) loop ); + + stpps = malloc( sizeof(struct stack_test_popping_and_pushing_state) * cpu_count * 2 ); + + for( loop = 0 ; loop < cpu_count ; loop++ ) + { + (stpps+loop)->ss = ss; + lfds610_stack_new( &(stpps+loop)->local_ss, 100000 ); + + (stpps+loop+cpu_count)->ss = ss; + lfds610_stack_new( &(stpps+loop+cpu_count)->local_ss, 100000 ); + + // TRD : fill the pushing thread stacks + for( subloop = 0 ; subloop < 100000 ; subloop++ ) + lfds610_stack_push( (stpps+loop+cpu_count)->local_ss, (void *) (lfds610_atom_t) subloop ); + } + + thread_handles = malloc( sizeof(thread_state_t) * cpu_count * 2 ); + + for( loop = 0 ; loop < cpu_count ; loop++ ) + { + abstraction_thread_start( &thread_handles[loop], loop, stack_test_internal_thread_popping_and_pushing_start_popping, stpps+loop ); + abstraction_thread_start( &thread_handles[loop+cpu_count], loop, stack_test_internal_thread_popping_and_pushing_start_pushing, stpps+loop+cpu_count ); + } + + for( loop = 0 ; loop < cpu_count * 2 ; loop++ ) + abstraction_thread_wait( thread_handles[loop] ); + + free( thread_handles ); + + for( loop = 0 ; loop < cpu_count * 2 ; loop++ ) + lfds610_stack_delete( (stpps+loop)->local_ss, NULL, NULL ); + + free( stpps ); + + vi.min_elements = vi.max_elements = 100000 * cpu_count * 2; + + lfds610_stack_query( ss, LFDS610_STACK_QUERY_VALIDATE, (void *) &vi, (void *) dvs ); + + lfds610_stack_delete( ss, NULL, NULL ); + + // TRD : print the test result + internal_display_test_result( 2, "stack", dvs[0], "stack freelist", dvs[1] ); + + return; +} + + + + + + +/****************************************************************************/ +thread_return_t CALLING_CONVENTION stack_test_internal_thread_popping_and_pushing_start_popping( void *stack_test_popping_and_pushing_state ) +{ + struct stack_test_popping_and_pushing_state + *stpps; + + void + *user_data; + + time_t + start_time; + + unsigned int + count; + + assert( stack_test_popping_and_pushing_state != NULL ); + + stpps = (struct stack_test_popping_and_pushing_state *) stack_test_popping_and_pushing_state; + + lfds610_stack_use( stpps->ss ); + lfds610_stack_use( stpps->local_ss ); + + time( &start_time ); + + while( time(NULL) < start_time + 10 ) + { + count = 0; + + while( count < 100000 ) + if( lfds610_stack_pop(stpps->ss, &user_data) ) + { + lfds610_stack_push( stpps->local_ss, user_data ); + count++; + } + + // TRD : return our local stack to the main stack + while( lfds610_stack_pop(stpps->local_ss, &user_data) ) + lfds610_stack_push( stpps->ss, user_data ); + } + + return( (thread_return_t) EXIT_SUCCESS ); +} + + + + + +/****************************************************************************/ +thread_return_t CALLING_CONVENTION stack_test_internal_thread_popping_and_pushing_start_pushing( void *stack_test_popping_and_pushing_state ) +{ + struct stack_test_popping_and_pushing_state + *stpps; + + void + *user_data; + + time_t + start_time; + + unsigned int + count; + + assert( stack_test_popping_and_pushing_state != NULL ); + + stpps = (struct stack_test_popping_and_pushing_state *) stack_test_popping_and_pushing_state; + + lfds610_stack_use( stpps->ss ); + lfds610_stack_use( stpps->local_ss ); + + time( &start_time ); + + while( time(NULL) < start_time + 10 ) + { + // TRD : return our local stack to the main stack + while( lfds610_stack_pop(stpps->local_ss, &user_data) ) + lfds610_stack_push( stpps->ss, user_data ); + + count = 0; + + while( count < 100000 ) + if( lfds610_stack_pop(stpps->ss, &user_data) ) + { + lfds610_stack_push( stpps->local_ss, user_data ); + count++; + } + } + + // TRD : now push whatever we have in our local stack + while( lfds610_stack_pop(stpps->local_ss, &user_data) ) + lfds610_stack_push( stpps->ss, user_data ); + + return( (thread_return_t) EXIT_SUCCESS ); +} + + + + + +/****************************************************************************/ +void stack_test_internal_rapid_popping_and_pushing( void ) +{ + unsigned int + loop, + cpu_count; + + thread_state_t + *thread_handles; + + struct lfds610_stack_state + *ss; + + struct lfds610_validation_info + vi; + + enum lfds610_data_structure_validity + dvs[2]; + + /* TRD : in these tests there is a fundamental antagonism between + how much checking/memory clean up that we do and the + likelyhood of collisions between threads in their lock-free + operations + + the lock-free operations are very quick; if we do anything + much at all between operations, we greatly reduce the chance + of threads colliding + + so we have some tests which do enough checking/clean up that + they can tell the stack is valid and don't leak memory + and here, this test now is one of those which does minimal + checking - in fact, the nature of the test is that you can't + do any real checking - but goes very quickly + + what we do is create a small stack and then run one thread + per CPU, where each thread simply pushes and then immediately + pops + + the test runs for ten seconds + + after the test is done, the only check we do is to traverse + the stack, checking for loops and ensuring the number of + elements is correct + */ + + internal_display_test_name( "Rapid popping and pushing (10 seconds)" ); + + cpu_count = abstraction_cpu_count(); + + lfds610_stack_new( &ss, cpu_count ); + + thread_handles = malloc( sizeof(thread_state_t) * cpu_count ); + + for( loop = 0 ; loop < cpu_count ; loop++ ) + abstraction_thread_start( &thread_handles[loop], loop, stack_test_internal_thread_rapid_popping_and_pushing, ss ); + + for( loop = 0 ; loop < cpu_count ; loop++ ) + abstraction_thread_wait( thread_handles[loop] ); + + free( thread_handles ); + + vi.min_elements = 0; + vi.max_elements = 0; + + lfds610_stack_query( ss, LFDS610_STACK_QUERY_VALIDATE, (void *) &vi, (void *) dvs ); + + lfds610_stack_delete( ss, NULL, NULL ); + + // TRD : print the test result + internal_display_test_result( 2, "stack", dvs[0], "stack freelist", dvs[1] ); + + return; +} + + + + + +/****************************************************************************/ +thread_return_t CALLING_CONVENTION stack_test_internal_thread_rapid_popping_and_pushing( void *stack_state ) +{ + struct lfds610_stack_state + *ss; + + void + *user_data = NULL; + + time_t + start_time; + + assert( stack_state != NULL ); + + ss = (struct lfds610_stack_state *) stack_state; + + lfds610_stack_use( ss ); + + time( &start_time ); + + while( time(NULL) < start_time + 10 ) + { + lfds610_stack_push( ss, user_data ); + lfds610_stack_pop( ss, &user_data ); + } + + return( (thread_return_t) EXIT_SUCCESS ); +} + diff --git a/liblfds/liblfds6.1.0/test/test.sln b/liblfds/liblfds6.1.0/test/test.sln new file mode 100644 index 0000000..b528bf3 --- /dev/null +++ b/liblfds/liblfds6.1.0/test/test.sln @@ -0,0 +1,79 @@ + +Microsoft Visual Studio Solution File, Format Version 10.00 +# Visual Studio 2008 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "test", "test.vcproj", "{6E4CBF20-DF1A-4FA0-8A90-58E2A3A5CF09}" + ProjectSection(ProjectDependencies) = postProject + {F73AE755-F6D8-4C3A-977D-FBB40DC0ED05} = {F73AE755-F6D8-4C3A-977D-FBB40DC0ED05} + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "liblfds610", "..\liblfds610\liblfds610.vcproj", "{F73AE755-F6D8-4C3A-977D-FBB40DC0ED05}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug DLL|Win32 = Debug DLL|Win32 + Debug DLL|x64 = Debug DLL|x64 + Debug Lib|Win32 = Debug Lib|Win32 + Debug Lib|x64 = Debug Lib|x64 + Debug|Win32 = Debug|Win32 + Debug|x64 = Debug|x64 + Release DLL|Win32 = Release DLL|Win32 + Release DLL|x64 = Release DLL|x64 + Release Lib|Win32 = Release Lib|Win32 + Release Lib|x64 = Release Lib|x64 + Release|Win32 = Release|Win32 + Release|x64 = Release|x64 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {6E4CBF20-DF1A-4FA0-8A90-58E2A3A5CF09}.Debug DLL|Win32.ActiveCfg = Debug|Win32 + {6E4CBF20-DF1A-4FA0-8A90-58E2A3A5CF09}.Debug DLL|Win32.Build.0 = Debug|Win32 + {6E4CBF20-DF1A-4FA0-8A90-58E2A3A5CF09}.Debug DLL|x64.ActiveCfg = Debug|x64 + {6E4CBF20-DF1A-4FA0-8A90-58E2A3A5CF09}.Debug DLL|x64.Build.0 = Debug|x64 + {6E4CBF20-DF1A-4FA0-8A90-58E2A3A5CF09}.Debug Lib|Win32.ActiveCfg = Debug|Win32 + {6E4CBF20-DF1A-4FA0-8A90-58E2A3A5CF09}.Debug Lib|Win32.Build.0 = Debug|Win32 + {6E4CBF20-DF1A-4FA0-8A90-58E2A3A5CF09}.Debug Lib|x64.ActiveCfg = Debug|x64 + {6E4CBF20-DF1A-4FA0-8A90-58E2A3A5CF09}.Debug Lib|x64.Build.0 = Debug|x64 + {6E4CBF20-DF1A-4FA0-8A90-58E2A3A5CF09}.Debug|Win32.ActiveCfg = Debug|Win32 + {6E4CBF20-DF1A-4FA0-8A90-58E2A3A5CF09}.Debug|Win32.Build.0 = Debug|Win32 + {6E4CBF20-DF1A-4FA0-8A90-58E2A3A5CF09}.Debug|x64.ActiveCfg = Debug|x64 + {6E4CBF20-DF1A-4FA0-8A90-58E2A3A5CF09}.Debug|x64.Build.0 = Debug|x64 + {6E4CBF20-DF1A-4FA0-8A90-58E2A3A5CF09}.Release DLL|Win32.ActiveCfg = Release|Win32 + {6E4CBF20-DF1A-4FA0-8A90-58E2A3A5CF09}.Release DLL|Win32.Build.0 = Release|Win32 + {6E4CBF20-DF1A-4FA0-8A90-58E2A3A5CF09}.Release DLL|x64.ActiveCfg = Release|x64 + {6E4CBF20-DF1A-4FA0-8A90-58E2A3A5CF09}.Release DLL|x64.Build.0 = Release|x64 + {6E4CBF20-DF1A-4FA0-8A90-58E2A3A5CF09}.Release Lib|Win32.ActiveCfg = Release|Win32 + {6E4CBF20-DF1A-4FA0-8A90-58E2A3A5CF09}.Release Lib|Win32.Build.0 = Release|Win32 + {6E4CBF20-DF1A-4FA0-8A90-58E2A3A5CF09}.Release Lib|x64.ActiveCfg = Release|x64 + {6E4CBF20-DF1A-4FA0-8A90-58E2A3A5CF09}.Release Lib|x64.Build.0 = Release|x64 + {6E4CBF20-DF1A-4FA0-8A90-58E2A3A5CF09}.Release|Win32.ActiveCfg = Release|Win32 + {6E4CBF20-DF1A-4FA0-8A90-58E2A3A5CF09}.Release|Win32.Build.0 = Release|Win32 + {6E4CBF20-DF1A-4FA0-8A90-58E2A3A5CF09}.Release|x64.ActiveCfg = Release|x64 + {6E4CBF20-DF1A-4FA0-8A90-58E2A3A5CF09}.Release|x64.Build.0 = Release|x64 + {F73AE755-F6D8-4C3A-977D-FBB40DC0ED05}.Debug DLL|Win32.ActiveCfg = Debug DLL|Win32 + {F73AE755-F6D8-4C3A-977D-FBB40DC0ED05}.Debug DLL|Win32.Build.0 = Debug DLL|Win32 + {F73AE755-F6D8-4C3A-977D-FBB40DC0ED05}.Debug DLL|x64.ActiveCfg = Debug DLL|x64 + {F73AE755-F6D8-4C3A-977D-FBB40DC0ED05}.Debug DLL|x64.Build.0 = Debug DLL|x64 + {F73AE755-F6D8-4C3A-977D-FBB40DC0ED05}.Debug Lib|Win32.ActiveCfg = Debug Lib|Win32 + {F73AE755-F6D8-4C3A-977D-FBB40DC0ED05}.Debug Lib|Win32.Build.0 = Debug Lib|Win32 + {F73AE755-F6D8-4C3A-977D-FBB40DC0ED05}.Debug Lib|x64.ActiveCfg = Debug Lib|x64 + {F73AE755-F6D8-4C3A-977D-FBB40DC0ED05}.Debug Lib|x64.Build.0 = Debug Lib|x64 + {F73AE755-F6D8-4C3A-977D-FBB40DC0ED05}.Debug|Win32.ActiveCfg = Debug Lib|Win32 + {F73AE755-F6D8-4C3A-977D-FBB40DC0ED05}.Debug|Win32.Build.0 = Debug Lib|Win32 + {F73AE755-F6D8-4C3A-977D-FBB40DC0ED05}.Debug|x64.ActiveCfg = Debug Lib|x64 + {F73AE755-F6D8-4C3A-977D-FBB40DC0ED05}.Debug|x64.Build.0 = Debug Lib|x64 + {F73AE755-F6D8-4C3A-977D-FBB40DC0ED05}.Release DLL|Win32.ActiveCfg = Release DLL|Win32 + {F73AE755-F6D8-4C3A-977D-FBB40DC0ED05}.Release DLL|Win32.Build.0 = Release DLL|Win32 + {F73AE755-F6D8-4C3A-977D-FBB40DC0ED05}.Release DLL|x64.ActiveCfg = Release DLL|x64 + {F73AE755-F6D8-4C3A-977D-FBB40DC0ED05}.Release DLL|x64.Build.0 = Release DLL|x64 + {F73AE755-F6D8-4C3A-977D-FBB40DC0ED05}.Release Lib|Win32.ActiveCfg = Release Lib|Win32 + {F73AE755-F6D8-4C3A-977D-FBB40DC0ED05}.Release Lib|Win32.Build.0 = Release Lib|Win32 + {F73AE755-F6D8-4C3A-977D-FBB40DC0ED05}.Release Lib|x64.ActiveCfg = Release Lib|x64 + {F73AE755-F6D8-4C3A-977D-FBB40DC0ED05}.Release Lib|x64.Build.0 = Release Lib|x64 + {F73AE755-F6D8-4C3A-977D-FBB40DC0ED05}.Release|Win32.ActiveCfg = Release Lib|Win32 + {F73AE755-F6D8-4C3A-977D-FBB40DC0ED05}.Release|Win32.Build.0 = Release Lib|Win32 + {F73AE755-F6D8-4C3A-977D-FBB40DC0ED05}.Release|x64.ActiveCfg = Release Lib|x64 + {F73AE755-F6D8-4C3A-977D-FBB40DC0ED05}.Release|x64.Build.0 = Release Lib|x64 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/liblfds/liblfds6.1.0/test/test.vcproj b/liblfds/liblfds6.1.0/test/test.vcproj new file mode 100644 index 0000000..1a8551c --- /dev/null +++ b/liblfds/liblfds6.1.0/test/test.vcproj @@ -0,0 +1,415 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +