Commit f47f596a authored by Xenofon Foukas's avatar Xenofon Foukas

Added support for liblfds7

parent 197726ce
...@@ -757,6 +757,7 @@ include_directories("${OPENAIR_DIR}/targets/ARCH/EXMIMO/DEFS") ...@@ -757,6 +757,7 @@ include_directories("${OPENAIR_DIR}/targets/ARCH/EXMIMO/DEFS")
include_directories("${OPENAIR2_DIR}/ENB_APP") include_directories("${OPENAIR2_DIR}/ENB_APP")
include_directories("${OPENAIR2_DIR}/UTIL/OSA") include_directories("${OPENAIR2_DIR}/UTIL/OSA")
include_directories("${OPENAIR2_DIR}/UTIL/LFDS/liblfds6.1.1/liblfds611/inc") include_directories("${OPENAIR2_DIR}/UTIL/LFDS/liblfds6.1.1/liblfds611/inc")
include_directories("${OPENAIR2_DIR}/UTIL/LFDS/liblfds7.0.0/liblfds700/inc")
include_directories("${OPENAIR2_DIR}/UTIL/MEM") include_directories("${OPENAIR2_DIR}/UTIL/MEM")
include_directories("${OPENAIR2_DIR}/UTIL/LISTS") include_directories("${OPENAIR2_DIR}/UTIL/LISTS")
include_directories("${OPENAIR2_DIR}/UTIL/FIFO") include_directories("${OPENAIR2_DIR}/UTIL/FIFO")
...@@ -1475,6 +1476,23 @@ add_library(LFDS ...@@ -1475,6 +1476,23 @@ add_library(LFDS
${lfds}/lfds611_abstraction/lfds611_abstraction_malloc.c ${lfds}/lfds611_abstraction/lfds611_abstraction_malloc.c
) )
set(lfds7 ${OPENAIR2_DIR}/UTIL/LFDS/liblfds7.0.0/liblfds700/src/)
file(GLOB lfds7_queue ${lfds7}/lfds700_queue/*.c)
file(GLOB lfds7_ring ${lfds7}/lfds700_ringbuffer/*.c)
file(GLOB lfds7_qbss ${lfds7}/lfds700_queue_bounded_singleconsumer_singleproducer/*.c)
file(GLOB lfds7_stack ${lfds7}/lfds700_stack/*.c)
file(GLOB lfds7_freelist ${lfds7}/lfds700_freelist/*.c)
file(GLOB lfds7_btree ${lfds7}/lfds700_btree_addonly_unbalanced/*.c)
file(GLOB lfds7_hash ${lfds7}/lfds700_hash_addonly/*.c)
file(GLOB lfds7_ordered_list ${lfds7}/lfds700_list_addonly_ordered_singlylinked/*.c)
file(GLOB lfds7_unordered_list ${lfds7}/lfds700_list_addonly_singlylinked_unordered/*.c)
file(GLOB lfds7_misc ${lfds7}/lfds700_misc/*.c)
include_directories(${lfds7})
add_library(LFDS7
${lfds7_queue} ${lfds7_ring} ${lfds7_qbss} ${lfds7_stack} ${lfds7_freelist} ${lfds7_btree} ${lfds7_hash} ${lfds7_ordered_list} ${lfds7_unordered_list} ${lfds7_misc}
)
# Simulation library # Simulation library
########################## ##########################
add_library(SIMU add_library(SIMU
...@@ -1604,7 +1622,7 @@ add_executable(lte-softmodem ...@@ -1604,7 +1622,7 @@ add_executable(lte-softmodem
target_link_libraries (lte-softmodem target_link_libraries (lte-softmodem
-Wl,--start-group -Wl,--start-group
RRC_LIB S1AP_LIB S1AP_ENB GTPV1U SECU_CN SECU_OSA UTIL HASHTABLE SCTP_CLIENT UDP SCHED_LIB PHY LFDS L2 ${MSC_LIB} ${RAL_LIB} ${NAS_UE_LIB} ${ITTI_LIB} ${MIH_LIB} ${PRPT_MSG_LIB} ${ASYNC_IF_LIB} ${ENB_AGENT_LIB} RRC_LIB S1AP_LIB S1AP_ENB GTPV1U SECU_CN SECU_OSA UTIL HASHTABLE SCTP_CLIENT UDP SCHED_LIB PHY LFDS L2 ${MSC_LIB} ${RAL_LIB} ${NAS_UE_LIB} ${ITTI_LIB} ${MIH_LIB} ${PRPT_MSG_LIB} ${ASYNC_IF_LIB} ${ENB_AGENT_LIB} LFDS7
-Wl,--end-group ) -Wl,--end-group )
...@@ -1639,7 +1657,7 @@ add_executable(lte-softmodem-nos1 ...@@ -1639,7 +1657,7 @@ add_executable(lte-softmodem-nos1
) )
target_link_libraries (lte-softmodem-nos1 target_link_libraries (lte-softmodem-nos1
-Wl,--start-group -Wl,--start-group
RRC_LIB SECU_CN SECU_OSA UTIL HASHTABLE SCHED_LIB PHY LFDS L2 ${MSC_LIB} ${RAL_LIB} ${ITTI_LIB} ${MIH_LIB} ${PRPT_MSG_LIB} ${ASYNC_IF_LIB} ${ENB_AGENT_LIB} RRC_LIB SECU_CN SECU_OSA UTIL HASHTABLE SCHED_LIB PHY LFDS L2 ${MSC_LIB} ${RAL_LIB} ${ITTI_LIB} ${MIH_LIB} ${PRPT_MSG_LIB} ${ASYNC_IF_LIB} ${ENB_AGENT_LIB} LFDS7
-Wl,--end-group ) -Wl,--end-group )
target_link_libraries (lte-softmodem-nos1 ${LIBXML2_LIBRARIES}) target_link_libraries (lte-softmodem-nos1 ${LIBXML2_LIBRARIES})
...@@ -1775,7 +1793,7 @@ add_executable(oaisim_nos1 ...@@ -1775,7 +1793,7 @@ add_executable(oaisim_nos1
target_include_directories(oaisim_nos1 PUBLIC ${OPENAIR_TARGETS}/SIMU/USER) target_include_directories(oaisim_nos1 PUBLIC ${OPENAIR_TARGETS}/SIMU/USER)
target_link_libraries (oaisim_nos1 target_link_libraries (oaisim_nos1
-Wl,--start-group -Wl,--start-group
RRC_LIB X2AP_LIB SECU_CN UTIL HASHTABLE SCHED_LIB PHY LFDS ${MSC_LIB} L2 ${RAL_LIB} SIMU SIMU_ETH SECU_OSA ${ITTI_LIB} ${MIH_LIB} ${PRPT_MSG_LIB} ${ASYNC_IF_LIB} ${ENB_AGENT_LIB} RRC_LIB X2AP_LIB SECU_CN UTIL HASHTABLE SCHED_LIB PHY LFDS ${MSC_LIB} L2 ${RAL_LIB} SIMU SIMU_ETH SECU_OSA ${ITTI_LIB} ${MIH_LIB} ${PRPT_MSG_LIB} ${ASYNC_IF_LIB} ${ENB_AGENT_LIB} LFDS7
-Wl,--end-group ) -Wl,--end-group )
target_link_libraries (oaisim_nos1 ${LIBXML2_LIBRARIES} ${LAPACK_LIBRARIES}) target_link_libraries (oaisim_nos1 ${LIBXML2_LIBRARIES} ${LAPACK_LIBRARIES})
...@@ -1796,7 +1814,7 @@ foreach(myExe dlsim ulsim pbchsim scansim mbmssim pdcchsim pucchsim prachsim syn ...@@ -1796,7 +1814,7 @@ foreach(myExe dlsim ulsim pbchsim scansim mbmssim pdcchsim pucchsim prachsim syn
${XFORMS_SOURCE} ${XFORMS_SOURCE}
) )
target_link_libraries (${myExe} target_link_libraries (${myExe}
-Wl,--start-group SIMU UTIL SCHED_LIB PHY LFDS ${ITTI_LIB} -Wl,--end-group -Wl,--start-group SIMU UTIL SCHED_LIB PHY LFDS ${ITTI_LIB} LFDS7 -Wl,--end-group
pthread m rt ${CONFIG_LIBRARIES} ${ATLAS_LIBRARIES} ${XFORMS_LIBRARIES} pthread m rt ${CONFIG_LIBRARIES} ${ATLAS_LIBRARIES} ${XFORMS_LIBRARIES}
) )
endforeach(myExe) endforeach(myExe)
......
##### paths #####
BINDIR := ../../bin
INCDIR := ../../inc
OBJDIR := ../../obj
SRCDIR := ../../src
##### misc #####
QUIETLY := 1>/dev/null 2>/dev/null
VERSION_NUMBER := 1
MINOR_NUMBER := 0
RELEASE_NUMBER := 0
##### sources, objects and libraries #####
BINNAME := liblfds700
ARFILENAME := $(BINNAME).a
ARPATHNAME := $(BINDIR)/$(ARFILENAME)
SOBASENAME := $(BINNAME).so
SONAME := $(SOBASENAME).$(VERSION_NUMBER)
SOFILENAME := $(SONAME).$(MINOR_NUMBER).$(RELEASE_NUMBER)
SOPATHNAME := $(BINDIR)/$(SOFILENAME)
INCNAME := $(INCDIR)/$(BINNAME).h
SRCDIRS := lfds700_btree_addonly_unbalanced lfds700_freelist lfds700_hash_addonly lfds700_list_addonly_ordered_singlylinked lfds700_list_addonly_singlylinked_unordered lfds700_misc lfds700_queue lfds700_queue_bounded_singleconsumer_singleproducer lfds700_ringbuffer lfds700_stack
SOURCES := lfds700_hash_addonly_cleanup.c lfds700_hash_addonly_get.c lfds700_hash_addonly_init.c lfds700_hash_addonly_insert.c lfds700_hash_addonly_iterate.c lfds700_hash_addonly_query.c \
lfds700_list_addonly_ordered_singlylinked_cleanup.c lfds700_list_addonly_ordered_singlylinked_get.c lfds700_list_addonly_ordered_singlylinked_init.c lfds700_list_addonly_ordered_singlylinked_insert.c lfds700_list_addonly_ordered_singlylinked_query.c \
lfds700_list_addonly_singlylinked_unordered_cleanup.c lfds700_list_addonly_singlylinked_unordered_get.c lfds700_list_addonly_singlylinked_unordered_init.c lfds700_list_addonly_singlylinked_unordered_insert.c lfds700_list_addonly_singlylinked_unordered_query.c \
lfds700_btree_addonly_unbalanced_cleanup.c lfds700_btree_addonly_unbalanced_get.c lfds700_btree_addonly_unbalanced_init.c lfds700_btree_addonly_unbalanced_insert.c lfds700_btree_addonly_unbalanced_query.c \
lfds700_freelist_cleanup.c lfds700_freelist_init.c lfds700_freelist_pop.c lfds700_freelist_push.c lfds700_freelist_query.c \
lfds700_misc_cleanup.c lfds700_misc_globals.c lfds700_misc_init.c lfds700_misc_prng.c lfds700_misc_query.c \
lfds700_queue_cleanup.c lfds700_queue_dequeue.c lfds700_queue_enqueue.c lfds700_queue_init.c lfds700_queue_query.c \
lfds700_queue_bounded_singleconsumer_singleproducer_cleanup.c lfds700_queue_bounded_singleconsumer_singleproducer_dequeue.c lfds700_queue_bounded_singleconsumer_singleproducer_enqueue.c lfds700_queue_bounded_singleconsumer_singleproducer_init.c lfds700_queue_bounded_singleconsumer_singleproducer_query.c \
lfds700_ringbuffer_cleanup.c lfds700_ringbuffer_init.c lfds700_ringbuffer_query.c lfds700_ringbuffer_read.c lfds700_ringbuffer_write.c \
lfds700_stack_cleanup.c lfds700_stack_init.c lfds700_stack_pop.c lfds700_stack_push.c lfds700_stack_query.c
OBJECTS := $(patsubst %.c,$(OBJDIR)/%.o,$(notdir $(SOURCES)))
SYSLIBS :=
##### default paths fix up #####
CPATH := $(subst : ,:,$(SRCDIR):$(INCDIR))
##### tools #####
MAKE := make
MFLAGS :=
DG := gcc
DGFLAGS := -MM -std=gnu89
CC := gcc
CFBASE := -c -fno-strict-aliasing -std=gnu89 -Wall -Werror -Wno-unknown-pragmas -Wno-unused-but-set-variable -Wno-unused-variable
CFCOV := -O0 -ggdb -DCOVERAGE -fprofile-arcs -ftest-coverage
CFDBG := -O0 -ggdb -D_DEBUG
CFPROF := -O0 -ggdb -DPROF -pg
CFREL := -O2 -DNDEBUG -finline-functions
CFTSAN := -O0 -ggdb -DTSAN -fsanitize=thread -fPIC
CFBARE := -ffreestanding -nodefaultlibs -nostdinc -nostdlib
AR := ar
AFLAGS := -rcs
LD := gcc
LFBASE := -pthread -shared -std=gnu89 -Wl,-soname,$(SONAME) -o $(SOPATHNAME) -Wall -Werror
LFCOV := -O0 -fprofile-arcs -ftest-coverage
LFDBG := -O0 -ggdb
LFPROF := -O0 -pg
LFREL := -O2 -s -finline-functions
LFTSAN := -O0 -fsanitize=thread -fPIC
LFBARE := -ffreestanding -nodefaultlibs -nostdinc -nostdlib
##### CPU variants #####
GCCARCH := native
CFBASE += -march=$(GCCARCH)
##### build variants #####
ifeq ($(findstring so,$(MAKECMDGOALS)),so)
CFBASE += -fPIC
endif
CFLAGS += $(CFBASE)
LFLAGS += $(LFBASE)
ifeq ($(MAKECMDGOALS),)
CFLAGS += $(CFDBG)
LFLAGS += $(LFDBG)
endif
ifeq ($(findstring cov,$(MAKECMDGOALS)),cov)
CFLAGS += $(CFCOV)
LFLAGS += $(LFCOV)
SYSLIBS += -lgcov
endif
ifeq ($(findstring dbg,$(MAKECMDGOALS)),dbg)
CFLAGS += $(CFDBG)
LFLAGS += $(LFDBG)
endif
ifeq ($(findstring prof,$(MAKECMDGOALS)),prof)
CFLAGS += $(CFPROF)
LFLAGS += $(LFPROF)
endif
ifeq ($(findstring rel,$(MAKECMDGOALS)),rel)
CFLAGS += $(CFREL)
LFLAGS += $(LFREL)
endif
ifeq ($(findstring tsan,$(MAKECMDGOALS)),tsan)
CFLAGS += $(CFTSAN)
LFLAGS += $(LFTSAN)
endif
ifeq ($(findstring b_,$(MAKECMDGOALS)),b_)
CFLAGS += $(CFBARE)
LFLAGS += $(CFBARE)
endif
##### search paths #####
vpath %.c $(patsubst %,$(SRCDIR)/%:,$(SRCDIRS))
##### implicit rules #####
$(OBJDIR)/%.o : %.c
$(DG) $(DGFLAGS) $< >$(OBJDIR)/$*.d
$(CC) $(CFLAGS) -o $@ $<
##### explicit rules #####
$(ARPATHNAME) : $(OBJECTS)
$(AR) $(AFLAGS) $(ARPATHNAME) $(OBJECTS)
$(SOPATHNAME) : $(OBJECTS)
$(LD) $(LFLAGS) $(OBJECTS) -o $(SOPATHNAME)
@ln -fs $(SOFILENAME) $(BINDIR)/$(SONAME)
@ln -fs $(SOFILENAME) $(BINDIR)/$(SOBASENAME)
##### phony #####
.PHONY : clean bare_ar_cov bare_ar_dbg bare_ar_prof bare_ar_rel bare_ar_tsan bare_so_cov bare_so_dbg bare_so_prof bare_so_rel bare_so_tsan hosted_ar_cov hosted_ar_dbg hosted_ar_prof hosted_ar_rel hosted_ar_tsan hosted_so_cov hosted_so_dbg hosted_so_prof hosted_so_rel hosted_so_tsan
clean :
@rm -f $(BINDIR)/* $(OBJDIR)/*
bare_ar_cov : $(ARPATHNAME) # bare, archive (.a), coverage
bare_ar_dbg : $(ARPATHNAME) # bare, archive (.a), debug
bare_ar_prof : $(ARPATHNAME) # bare, archive (.a), profiling
bare_ar_rel : $(ARPATHNAME) # bare, archive (.a), release
bare_ar_tsan : $(ARPATHNAME) # bare, archive (.a), thread sanitizer
bare_so_cov : $(SOPATHNAME) # bare, shared (.so), coverage
bare_so_dbg : $(SOPATHNAME) # bare, shared (.so), debug
bare_so_prof : $(SOPATHNAME) # bare, shared (.so), profiling
bare_so_rel : $(SOPATHNAME) # bare, shared (.so), release
bare_so_tsan : $(SOPATHNAME) # bare, shared (.so), thread sanitizer
hosted_ar_cov : $(ARPATHNAME) # hosted implementation, archive (.a), coverage
hosted_ar_dbg : $(ARPATHNAME) # hosted implementation, archive (.a), debug
hosted_ar_prof : $(ARPATHNAME) # hosted implementation, archive (.a), profiling
hosted_ar_rel : $(ARPATHNAME) # hosted implementation, archive (.a), release
hosted_ar_tsan : $(ARPATHNAME) # hosted implementation, archive (.a), thread sanitizer
hosted_so_cov : $(SOPATHNAME) # hosted implementation, shared (.so), coverage
hosted_so_dbg : $(SOPATHNAME) # hosted implementation, shared (.so), debug
hosted_so_prof : $(SOPATHNAME) # hosted implementation, shared (.so), profiling
hosted_so_rel : $(SOPATHNAME) # hosted implementation, shared (.so), release
hosted_so_tsan : $(SOPATHNAME) # hosted implementation, shared (.so), thread sanitizer
##### dependencies #####
-include $(DEPENDS)
##### notes #####
# TRD : we use -std=gnu89 for C++ style comments
# hosted implementation differs from bare simply in that <assert.h> ends up being included
lib-y :=
lib-y += ../../src/lfds700_btree_addonly_unbalanced/lfds700_btree_addonly_unbalanced_cleanup.o
lib-y += ../../src/lfds700_btree_addonly_unbalanced/lfds700_btree_addonly_unbalanced_get.o
lib-y += ../../src/lfds700_btree_addonly_unbalanced/lfds700_btree_addonly_unbalanced_init.o
lib-y += ../../src/lfds700_btree_addonly_unbalanced/lfds700_btree_addonly_unbalanced_insert.o
lib-y += ../../src/lfds700_btree_addonly_unbalanced/lfds700_btree_addonly_unbalanced_query.o
lib-y += ../../src/lfds700_freelist/lfds700_freelist_cleanup.o
lib-y += ../../src/lfds700_freelist/lfds700_freelist_init.o
lib-y += ../../src/lfds700_freelist/lfds700_freelist_pop.o
lib-y += ../../src/lfds700_freelist/lfds700_freelist_push.o
lib-y += ../../src/lfds700_freelist/lfds700_freelist_query.o
lib-y += ../../src/lfds700_hash_addonly/lfds700_hash_addonly_cleanup.o
lib-y += ../../src/lfds700_hash_addonly/lfds700_hash_addonly_get.o
lib-y += ../../src/lfds700_hash_addonly/lfds700_hash_addonly_init.o
lib-y += ../../src/lfds700_hash_addonly/lfds700_hash_addonly_insert.o
lib-y += ../../src/lfds700_hash_addonly/lfds700_hash_addonly_iterate.o
lib-y += ../../src/lfds700_hash_addonly/lfds700_hash_addonly_query.o
lib-y += ../../src/lfds700_list_addonly_ordered_singlylinked/lfds700_list_addonly_ordered_singlylinked_cleanup.o
lib-y += ../../src/lfds700_list_addonly_ordered_singlylinked/lfds700_list_addonly_ordered_singlylinked_get.o
lib-y += ../../src/lfds700_list_addonly_ordered_singlylinked/lfds700_list_addonly_ordered_singlylinked_init.o
lib-y += ../../src/lfds700_list_addonly_ordered_singlylinked/lfds700_list_addonly_ordered_singlylinked_insert.o
lib-y += ../../src/lfds700_list_addonly_ordered_singlylinked/lfds700_list_addonly_ordered_singlylinked_query.o
lib-y += ../../src/lfds700_list_addonly_singlylinked_unordered/lfds700_list_addonly_singlylinked_unordered_cleanup.o
lib-y += ../../src/lfds700_list_addonly_singlylinked_unordered/lfds700_list_addonly_singlylinked_unordered_get.o
lib-y += ../../src/lfds700_list_addonly_singlylinked_unordered/lfds700_list_addonly_singlylinked_unordered_init.o
lib-y += ../../src/lfds700_list_addonly_singlylinked_unordered/lfds700_list_addonly_singlylinked_unordered_insert.o
lib-y += ../../src/lfds700_list_addonly_singlylinked_unordered/lfds700_list_addonly_singlylinked_unordered_query.o
lib-y += ../../src/lfds700_misc/lfds700_misc_cleanup.o
lib-y += ../../src/lfds700_misc/lfds700_misc_globals.o
lib-y += ../../src/lfds700_misc/lfds700_misc_init.o
lib-y += ../../src/lfds700_misc/lfds700_misc_prng.o
lib-y += ../../src/lfds700_misc/lfds700_misc_query.o
lib-y += ../../src/lfds700_queue/lfds700_queue_cleanup.o
lib-y += ../../src/lfds700_queue/lfds700_queue_dequeue.o
lib-y += ../../src/lfds700_queue/lfds700_queue_enqueue.o
lib-y += ../../src/lfds700_queue/lfds700_queue_init.o
lib-y += ../../src/lfds700_queue/lfds700_queue_query.o
lib-y += ../../src/lfds700_queue_bounded_singleconsumer_singleproducer/lfds700_queue_bounded_singleconsumer_singleproducer_cleanup.o
lib-y += ../../src/lfds700_queue_bounded_singleconsumer_singleproducer/lfds700_queue_bounded_singleconsumer_singleproducer_dequeue.o
lib-y += ../../src/lfds700_queue_bounded_singleconsumer_singleproducer/lfds700_queue_bounded_singleconsumer_singleproducer_enqueue.o
lib-y += ../../src/lfds700_queue_bounded_singleconsumer_singleproducer/lfds700_queue_bounded_singleconsumer_singleproducer_init.o
lib-y += ../../src/lfds700_queue_bounded_singleconsumer_singleproducer/lfds700_queue_bounded_singleconsumer_singleproducer_query.o
lib-y += ../../src/lfds700_ringbuffer/lfds700_ringbuffer_cleanup.o
lib-y += ../../src/lfds700_ringbuffer/lfds700_ringbuffer_init.o
lib-y += ../../src/lfds700_ringbuffer/lfds700_ringbuffer_query.o
lib-y += ../../src/lfds700_ringbuffer/lfds700_ringbuffer_read.o
lib-y += ../../src/lfds700_ringbuffer/lfds700_ringbuffer_write.o
lib-y += ../../src/lfds700_stack/lfds700_stack_cleanup.o
lib-y += ../../src/lfds700_stack/lfds700_stack_init.o
lib-y += ../../src/lfds700_stack/lfds700_stack_pop.o
lib-y += ../../src/lfds700_stack/lfds700_stack_push.o
lib-y += ../../src/lfds700_stack/lfds700_stack_query.o
libs-y := ../../bin/
ccflags-y := -I$(src)/../../inc
ccflags-y += -I$(src)/../../inc/liblfds700
ccflags-y += -D_KERNEL_MODE
ccflags-y += -fno-strict-aliasing
ccflags-y += -std=gnu89
ccflags-y += -Wall
ccflags-y += -Werror
ccflags-y += -Wno-unknown-pragmas
ccflags-y += -Wno-unused-but-set-variable
ccflags-y += -Wno-unused-variable
default:
$(MAKE) -C /lib/modules/`uname -r`/build M=$(PWD)
clean:
$(MAKE) -C /lib/modules/`uname -r`/build M=$(PWD) clean
find ../../src/ -name "*.o" -type f -delete
help:
$(MAKE) -C /lib/modules/`uname -r`/build M=$(PWD) help
modules:
$(MAKE) -C /lib/modules/`uname -r`/build M=$(PWD) modules
EXPORTS
lfds700_btree_au_init_valid_on_current_logical_core = lfds700_btree_au_init_valid_on_current_logical_core
lfds700_btree_au_cleanup = lfds700_btree_au_cleanup
lfds700_btree_au_insert = lfds700_btree_au_insert
lfds700_btree_au_get_by_absolute_position_and_then_by_relative_position = lfds700_btree_au_get_by_absolute_position_and_then_by_relative_position
lfds700_btree_au_get_by_absolute_position = lfds700_btree_au_get_by_absolute_position
lfds700_btree_au_get_by_relative_position = lfds700_btree_au_get_by_relative_position
lfds700_btree_au_get_by_key = lfds700_btree_au_get_by_key
lfds700_btree_au_query = lfds700_btree_au_query
lfds700_freelist_init_valid_on_current_logical_core = lfds700_freelist_init_valid_on_current_logical_core
lfds700_freelist_cleanup = lfds700_freelist_cleanup
lfds700_freelist_push = lfds700_freelist_push
lfds700_freelist_pop = lfds700_freelist_pop
lfds700_freelist_query = lfds700_freelist_query
lfds700_hash_a_init_valid_on_current_logical_core = lfds700_hash_a_init_valid_on_current_logical_core
lfds700_hash_a_cleanup = lfds700_hash_a_cleanup
lfds700_hash_a_insert = lfds700_hash_a_insert
lfds700_hash_a_get_by_key = lfds700_hash_a_get_by_key
lfds700_hash_a_iterate_init = lfds700_hash_a_iterate_init
lfds700_hash_a_iterate = lfds700_hash_a_iterate
lfds700_hash_a_query = lfds700_hash_a_query
lfds700_list_aos_init_valid_on_current_logical_core = lfds700_list_aos_init_valid_on_current_logical_core
lfds700_list_aos_cleanup = lfds700_list_aos_cleanup
lfds700_list_aos_insert = lfds700_list_aos_insert
lfds700_list_aos_get_by_key = lfds700_list_aos_get_by_key
lfds700_list_aos_query = lfds700_list_aos_query
lfds700_list_asu_init_valid_on_current_logical_core = lfds700_list_asu_init_valid_on_current_logical_core
lfds700_list_asu_cleanup = lfds700_list_asu_cleanup
lfds700_list_asu_insert_at_position = lfds700_list_asu_insert_at_position
lfds700_list_asu_insert_at_start = lfds700_list_asu_insert_at_start
lfds700_list_asu_insert_at_end = lfds700_list_asu_insert_at_end
lfds700_list_asu_insert_after_element = lfds700_list_asu_insert_after_element
lfds700_list_asu_get_by_key = lfds700_list_asu_get_by_key
lfds700_list_asu_query = lfds700_list_asu_query
lfds700_misc_library_init_valid_on_current_logical_core = lfds700_misc_library_init_valid_on_current_logical_core
lfds700_misc_library_cleanup = lfds700_misc_library_cleanup
lfds700_misc_prng_init = lfds700_misc_prng_init
lfds700_misc_query = lfds700_misc_query
lfds700_queue_init_valid_on_current_logical_core = lfds700_queue_init_valid_on_current_logical_core
lfds700_queue_cleanup = lfds700_queue_cleanup
lfds700_queue_enqueue = lfds700_queue_enqueue
lfds700_queue_dequeue = lfds700_queue_dequeue
lfds700_queue_query = lfds700_queue_query
lfds700_queue_bss_init_valid_on_current_logical_core = lfds700_queue_bss_init_valid_on_current_logical_core
lfds700_queue_bss_cleanup = lfds700_queue_bss_cleanup
lfds700_queue_bss_enqueue = lfds700_queue_bss_enqueue
lfds700_queue_bss_dequeue = lfds700_queue_bss_dequeue
lfds700_queue_bss_query = lfds700_queue_bss_query
lfds700_ringbuffer_init_valid_on_current_logical_core = lfds700_ringbuffer_init_valid_on_current_logical_core
lfds700_ringbuffer_cleanup = lfds700_ringbuffer_cleanup
lfds700_ringbuffer_read = lfds700_ringbuffer_read
lfds700_ringbuffer_write = lfds700_ringbuffer_write
lfds700_ringbuffer_query = lfds700_ringbuffer_query
lfds700_stack_init_valid_on_current_logical_core = lfds700_stack_init_valid_on_current_logical_core
lfds700_stack_cleanup = lfds700_stack_cleanup
lfds700_stack_push = lfds700_stack_push
lfds700_stack_pop = lfds700_stack_pop
lfds700_stack_query = lfds700_stack_query
##### paths #####
BINDIR := ..\..\bin
INCDIR := ..\..\inc
OBJDIR := ..\..\obj
SRCDIR := ..\..\src
##### misc #####
QUIETLY := 1>nul 2>nul
NULL :=
SPACE := $(NULL) # TRD : with a trailing space
##### sources, objects and libraries #####
BINNAME := liblfds700
LIB_BINARY := $(BINDIR)\$(BINNAME).lib
DLL_BINARY := $(BINDIR)\$(BINNAME).dll
SRCDIRS := lfds700_btree_addonly_unbalanced lfds700_freelist lfds700_hash_addonly lfds700_list_addonly_ordered_singlylinked lfds700_list_addonly_singlylinked_unordered lfds700_misc lfds700_queue lfds700_queue_bounded_singleconsumer_singleproducer lfds700_ringbuffer lfds700_stack
SOURCES := lfds700_hash_addonly_cleanup.c lfds700_hash_addonly_get.c lfds700_hash_addonly_init.c lfds700_hash_addonly_insert.c lfds700_hash_addonly_iterate.c lfds700_hash_addonly_query.c \
lfds700_list_addonly_ordered_singlylinked_cleanup.c lfds700_list_addonly_ordered_singlylinked_get.c lfds700_list_addonly_ordered_singlylinked_init.c lfds700_list_addonly_ordered_singlylinked_insert.c lfds700_list_addonly_ordered_singlylinked_query.c \
lfds700_list_addonly_singlylinked_unordered_cleanup.c lfds700_list_addonly_singlylinked_unordered_get.c lfds700_list_addonly_singlylinked_unordered_init.c lfds700_list_addonly_singlylinked_unordered_insert.c lfds700_list_addonly_singlylinked_unordered_query.c \
lfds700_btree_addonly_unbalanced_cleanup.c lfds700_btree_addonly_unbalanced_get.c lfds700_btree_addonly_unbalanced_init.c lfds700_btree_addonly_unbalanced_insert.c lfds700_btree_addonly_unbalanced_query.c \
lfds700_freelist_cleanup.c lfds700_freelist_init.c lfds700_freelist_pop.c lfds700_freelist_push.c lfds700_freelist_query.c \
lfds700_misc_cleanup.c lfds700_misc_globals.c lfds700_misc_init.c lfds700_misc_prng.c lfds700_misc_query.c \
lfds700_queue_cleanup.c lfds700_queue_dequeue.c lfds700_queue_enqueue.c lfds700_queue_init.c lfds700_queue_query.c \
lfds700_queue_bounded_singleconsumer_singleproducer_cleanup.c lfds700_queue_bounded_singleconsumer_singleproducer_dequeue.c lfds700_queue_bounded_singleconsumer_singleproducer_enqueue.c lfds700_queue_bounded_singleconsumer_singleproducer_init.c lfds700_queue_bounded_singleconsumer_singleproducer_query.c \
lfds700_ringbuffer_cleanup.c lfds700_ringbuffer_init.c lfds700_ringbuffer_query.c lfds700_ringbuffer_read.c lfds700_ringbuffer_write.c \
lfds700_stack_cleanup.c lfds700_stack_init.c lfds700_stack_pop.c lfds700_stack_push.c lfds700_stack_query.c
OBJECTS := $(patsubst %.c,$(OBJDIR)/%.obj,$(notdir $(SOURCES)))
SYSLIBS := kernel32.lib
##### default paths fix up #####
INCDIRS := $(patsubst %,%;,$(INCDIR))
INCLUDE += $(subst $(SPACE),,$(INCDIRS))
##### tools #####
MAKE := make
MFLAGS :=
CC := cl
CBASE := /c "-I$(SRCDIR)" "/Fd$(BINDIR)\$(BINNAME).pdb" /D_CRT_SECURE_NO_WARNINGS /DWIN32_LEAN_AND_MEAN /DUNICODE /D_UNICODE /DUNICODE /nologo /W4 /wd 4068 /WX
CFREL := /DNDEBUG /Ox
CFDBG := /D_DEBUG /Gm /Od /Zi
AR := lib
AFLAGS := /nologo /subsystem:console /verbose /wx
LD := link
LFBASE := /def:$(BINNAME).def /dll /nodefaultlib /nologo /nxcompat /subsystem:console /wx
LFREL := /incremental:no
LFDBG := /debug "/pdb:$(BINDIR)\$(BINNAME).pdb"
##### variants #####
CFLAGS := $(CBASE) $(CFDBG) /MTd
ASFLAGS := $(ASBASE) $(ASDBG)
LFLAGS := $(LFBASE) $(LFDBG)
CLIB := libcmtd.lib
ifeq ($(MAKECMDGOALS),librel)
CFLAGS := $(CBASE) $(CFREL) /MT
ASFLAGS := $(ASBASE) $(ASREL)
LFLAGS := $(LFBASE) $(LFREL)
CLIB := libcmt.lib
endif
ifeq ($(MAKECMDGOALS),libdbg)
CFLAGS := $(CBASE) $(CFDBG) /MTd
ASFLAGS := $(ASBASE) $(ASDBG)
LFLAGS := $(LFBASE) $(LFDBG)
CLIB := libcmtd.lib
endif
ifeq ($(MAKECMDGOALS),dllrel)
CFLAGS := $(CBASE) $(CFREL) /MD
ASFLAGS := $(ASBASE) $(ASREL)
LFLAGS := $(LFBASE) $(LFREL)
CLIB := msvcrt.lib
endif
ifeq ($(MAKECMDGOALS),dlldbg)
CFLAGS := $(CBASE) $(CFDBG) /MDd
ASFLAGS := $(ASBASE) $(ASDBG)
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)
dlldbg : $(DLL_BINARY)
dllrel : $(DLL_BINARY)
libdbg : $(LIB_BINARY)
librel : $(LIB_BINARY)
##### notes #####
# /wd 4068 : turn off "unknown pragma" warning
EXPORTS
lfds700_btree_au_init_valid_on_current_logical_core = lfds700_btree_au_init_valid_on_current_logical_core
lfds700_btree_au_cleanup = lfds700_btree_au_cleanup
lfds700_btree_au_insert = lfds700_btree_au_insert
lfds700_btree_au_get_by_absolute_position_and_then_by_relative_position = lfds700_btree_au_get_by_absolute_position_and_then_by_relative_position
lfds700_btree_au_get_by_absolute_position = lfds700_btree_au_get_by_absolute_position
lfds700_btree_au_get_by_relative_position = lfds700_btree_au_get_by_relative_position
lfds700_btree_au_get_by_key = lfds700_btree_au_get_by_key
lfds700_btree_au_query = lfds700_btree_au_query
lfds700_freelist_init_valid_on_current_logical_core = lfds700_freelist_init_valid_on_current_logical_core
lfds700_freelist_cleanup = lfds700_freelist_cleanup
lfds700_freelist_push = lfds700_freelist_push
lfds700_freelist_pop = lfds700_freelist_pop
lfds700_freelist_query = lfds700_freelist_query
lfds700_hash_a_init_valid_on_current_logical_core = lfds700_hash_a_init_valid_on_current_logical_core
lfds700_hash_a_cleanup = lfds700_hash_a_cleanup
lfds700_hash_a_insert = lfds700_hash_a_insert
lfds700_hash_a_get_by_key = lfds700_hash_a_get_by_key
lfds700_hash_a_iterate_init = lfds700_hash_a_iterate_init
lfds700_hash_a_iterate = lfds700_hash_a_iterate
lfds700_hash_a_query = lfds700_hash_a_query
lfds700_list_aos_init_valid_on_current_logical_core = lfds700_list_aos_init_valid_on_current_logical_core
lfds700_list_aos_cleanup = lfds700_list_aos_cleanup
lfds700_list_aos_insert = lfds700_list_aos_insert
lfds700_list_aos_get_by_key = lfds700_list_aos_get_by_key
lfds700_list_aos_query = lfds700_list_aos_query
lfds700_list_asu_init_valid_on_current_logical_core = lfds700_list_asu_init_valid_on_current_logical_core
lfds700_list_asu_cleanup = lfds700_list_asu_cleanup
lfds700_list_asu_insert_at_position = lfds700_list_asu_insert_at_position
lfds700_list_asu_insert_at_start = lfds700_list_asu_insert_at_start
lfds700_list_asu_insert_at_end = lfds700_list_asu_insert_at_end
lfds700_list_asu_insert_after_element = lfds700_list_asu_insert_after_element
lfds700_list_asu_get_by_key = lfds700_list_asu_get_by_key
lfds700_list_asu_query = lfds700_list_asu_query
lfds700_misc_library_init_valid_on_current_logical_core = lfds700_misc_library_init_valid_on_current_logical_core
lfds700_misc_library_cleanup = lfds700_misc_library_cleanup
lfds700_misc_prng_init = lfds700_misc_prng_init
lfds700_misc_query = lfds700_misc_query
lfds700_queue_init_valid_on_current_logical_core = lfds700_queue_init_valid_on_current_logical_core
lfds700_queue_cleanup = lfds700_queue_cleanup
lfds700_queue_enqueue = lfds700_queue_enqueue
lfds700_queue_dequeue = lfds700_queue_dequeue
lfds700_queue_query = lfds700_queue_query
lfds700_queue_bss_init_valid_on_current_logical_core = lfds700_queue_bss_init_valid_on_current_logical_core
lfds700_queue_bss_cleanup = lfds700_queue_bss_cleanup
lfds700_queue_bss_enqueue = lfds700_queue_bss_enqueue
lfds700_queue_bss_dequeue = lfds700_queue_bss_dequeue
lfds700_queue_bss_query = lfds700_queue_bss_query
lfds700_ringbuffer_init_valid_on_current_logical_core = lfds700_ringbuffer_init_valid_on_current_logical_core
lfds700_ringbuffer_cleanup = lfds700_ringbuffer_cleanup
lfds700_ringbuffer_read = lfds700_ringbuffer_read
lfds700_ringbuffer_write = lfds700_ringbuffer_write
lfds700_ringbuffer_query = lfds700_ringbuffer_query
lfds700_stack_init_valid_on_current_logical_core = lfds700_stack_init_valid_on_current_logical_core
lfds700_stack_cleanup = lfds700_stack_cleanup
lfds700_stack_push = lfds700_stack_push
lfds700_stack_pop = lfds700_stack_pop
lfds700_stack_query = lfds700_stack_query

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 2012
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "liblfds700", "liblfds700.vcxproj", "{1E5D7D09-94F2-455D-AE5E-6C7F4C96BCE0}"
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
{1E5D7D09-94F2-455D-AE5E-6C7F4C96BCE0}.Debug DLL|Win32.ActiveCfg = Debug DLL|Win32
{1E5D7D09-94F2-455D-AE5E-6C7F4C96BCE0}.Debug DLL|Win32.Build.0 = Debug DLL|Win32
{1E5D7D09-94F2-455D-AE5E-6C7F4C96BCE0}.Debug DLL|Win32.Deploy.0 = Debug DLL|Win32
{1E5D7D09-94F2-455D-AE5E-6C7F4C96BCE0}.Debug DLL|x64.ActiveCfg = Debug DLL|x64
{1E5D7D09-94F2-455D-AE5E-6C7F4C96BCE0}.Debug DLL|x64.Build.0 = Debug DLL|x64
{1E5D7D09-94F2-455D-AE5E-6C7F4C96BCE0}.Debug DLL|x64.Deploy.0 = Debug DLL|x64
{1E5D7D09-94F2-455D-AE5E-6C7F4C96BCE0}.Debug LIB|Win32.ActiveCfg = Debug LIB|Win32
{1E5D7D09-94F2-455D-AE5E-6C7F4C96BCE0}.Debug LIB|Win32.Build.0 = Debug LIB|Win32
{1E5D7D09-94F2-455D-AE5E-6C7F4C96BCE0}.Debug LIB|Win32.Deploy.0 = Debug LIB|Win32
{1E5D7D09-94F2-455D-AE5E-6C7F4C96BCE0}.Debug LIB|x64.ActiveCfg = Debug LIB|x64
{1E5D7D09-94F2-455D-AE5E-6C7F4C96BCE0}.Debug LIB|x64.Build.0 = Debug LIB|x64
{1E5D7D09-94F2-455D-AE5E-6C7F4C96BCE0}.Debug LIB|x64.Deploy.0 = Debug LIB|x64
{1E5D7D09-94F2-455D-AE5E-6C7F4C96BCE0}.Release DLL|Win32.ActiveCfg = Release DLL|Win32
{1E5D7D09-94F2-455D-AE5E-6C7F4C96BCE0}.Release DLL|Win32.Build.0 = Release DLL|Win32
{1E5D7D09-94F2-455D-AE5E-6C7F4C96BCE0}.Release DLL|Win32.Deploy.0 = Release DLL|Win32
{1E5D7D09-94F2-455D-AE5E-6C7F4C96BCE0}.Release DLL|x64.ActiveCfg = Release DLL|x64
{1E5D7D09-94F2-455D-AE5E-6C7F4C96BCE0}.Release DLL|x64.Build.0 = Release DLL|x64
{1E5D7D09-94F2-455D-AE5E-6C7F4C96BCE0}.Release DLL|x64.Deploy.0 = Release DLL|x64
{1E5D7D09-94F2-455D-AE5E-6C7F4C96BCE0}.Release LIB|Win32.ActiveCfg = Release LIB|Win32
{1E5D7D09-94F2-455D-AE5E-6C7F4C96BCE0}.Release LIB|Win32.Build.0 = Release LIB|Win32
{1E5D7D09-94F2-455D-AE5E-6C7F4C96BCE0}.Release LIB|Win32.Deploy.0 = Release LIB|Win32
{1E5D7D09-94F2-455D-AE5E-6C7F4C96BCE0}.Release LIB|x64.ActiveCfg = Release LIB|x64
{1E5D7D09-94F2-455D-AE5E-6C7F4C96BCE0}.Release LIB|x64.Build.0 = Release LIB|x64
{1E5D7D09-94F2-455D-AE5E-6C7F4C96BCE0}.Release LIB|x64.Deploy.0 = Release LIB|x64
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
EndGlobal
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug DLL|Win32">
<Configuration>Debug DLL</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Debug DLL|x64">
<Configuration>Debug DLL</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Debug LIB|Win32">
<Configuration>Debug LIB</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Debug LIB|x64">
<Configuration>Debug LIB</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release DLL|Win32">
<Configuration>Release DLL</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release DLL|x64">
<Configuration>Release DLL</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release LIB|Win32">
<Configuration>Release LIB</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release LIB|x64">
<Configuration>Release LIB</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<ProjectGuid>{1E5D7D09-94F2-455D-AE5E-6C7F4C96BCE0}</ProjectGuid>
<Keyword>Win32Proj</Keyword>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug LIB|Win32'" Label="Configuration">
<ConfigurationType>StaticLibrary</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v110</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug DLL|Win32'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v110</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug LIB|x64'" Label="Configuration">
<ConfigurationType>StaticLibrary</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v110</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug DLL|x64'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v110</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release LIB|Win32'" Label="Configuration">
<ConfigurationType>StaticLibrary</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v110</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release DLL|Win32'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v110</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release LIB|x64'" Label="Configuration">
<ConfigurationType>StaticLibrary</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v110</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release DLL|x64'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v110</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug LIB|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug DLL|Win32'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug LIB|x64'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug DLL|x64'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release LIB|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release DLL|Win32'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release LIB|x64'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release DLL|x64'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug LIB|Win32'">
<LinkIncremental>true</LinkIncremental>
<OutDir>$(ProjectDir)..\..\bin\$(Platform) $(Configuration)\</OutDir>
<IntDir>$(ProjectDir)..\..\obj\$(Platform) $(Configuration)\</IntDir>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug DLL|Win32'">
<LinkIncremental>
</LinkIncremental>
<OutDir>$(ProjectDir)..\..\bin\$(Platform) $(Configuration)\</OutDir>
<IntDir>$(ProjectDir)..\..\obj\$(Platform) $(Configuration)\</IntDir>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug LIB|x64'">
<LinkIncremental>true</LinkIncremental>
<OutDir>$(ProjectDir)..\..\bin\$(Platform) $(Configuration)\</OutDir>
<IntDir>$(ProjectDir)..\..\obj\$(Platform) $(Configuration)\</IntDir>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug DLL|x64'">
<LinkIncremental>
</LinkIncremental>
<OutDir>$(ProjectDir)..\..\bin\$(Platform) $(Configuration)\</OutDir>
<IntDir>$(ProjectDir)..\..\obj\$(Platform) $(Configuration)\</IntDir>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release LIB|Win32'">
<LinkIncremental>true</LinkIncremental>
<OutDir>$(ProjectDir)..\..\bin\$(Platform) $(Configuration)\</OutDir>
<IntDir>$(ProjectDir)..\..\obj\$(Platform) $(Configuration)\</IntDir>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release DLL|Win32'">
<LinkIncremental>
</LinkIncremental>
<OutDir>$(ProjectDir)..\..\bin\$(Platform) $(Configuration)\</OutDir>
<IntDir>$(ProjectDir)..\..\obj\$(Platform) $(Configuration)\</IntDir>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release LIB|x64'">
<LinkIncremental>true</LinkIncremental>
<OutDir>$(ProjectDir)..\..\bin\$(Platform) $(Configuration)\</OutDir>
<IntDir>$(ProjectDir)..\..\obj\$(Platform) $(Configuration)\</IntDir>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release DLL|x64'">
<LinkIncremental>
</LinkIncremental>
<OutDir>$(ProjectDir)..\..\bin\$(Platform) $(Configuration)\</OutDir>
<IntDir>$(ProjectDir)..\..\obj\$(Platform) $(Configuration)\</IntDir>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug LIB|Win32'">
<ClCompile>
<PreprocessorDefinitions>WIN32;_DEBUG;_LIB;LFDS700_BUILD_TYPE_STRING="Debug";%(PreprocessorDefinitions)</PreprocessorDefinitions>
<AdditionalIncludeDirectories>
</AdditionalIncludeDirectories>
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
<WarningLevel>Level4</WarningLevel>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
<Optimization>Disabled</Optimization>
<CompileAsManaged>false</CompileAsManaged>
<CompileAsWinRT>false</CompileAsWinRT>
<TreatWarningAsError>true</TreatWarningAsError>
<MultiProcessorCompilation>true</MultiProcessorCompilation>
<IntrinsicFunctions>true</IntrinsicFunctions>
<StringPooling>true</StringPooling>
<ExceptionHandling>false</ExceptionHandling>
<SmallerTypeCheck>true</SmallerTypeCheck>
<FunctionLevelLinking>
</FunctionLevelLinking>
<EnableParallelCodeGeneration>
</EnableParallelCodeGeneration>
<EnableEnhancedInstructionSet>
</EnableEnhancedInstructionSet>
<FloatingPointExceptions>true</FloatingPointExceptions>
<CreateHotpatchableImage>false</CreateHotpatchableImage>
<RuntimeTypeInfo>false</RuntimeTypeInfo>
<OpenMPSupport>false</OpenMPSupport>
<BrowseInformation>true</BrowseInformation>
<CompileAs>CompileAsC</CompileAs>
<UseFullPaths>true</UseFullPaths>
<ErrorReporting>None</ErrorReporting>
<SDLCheck>true</SDLCheck>
<MinimalRebuild>false</MinimalRebuild>
<DisableSpecificWarnings>4068</DisableSpecificWarnings>
</ClCompile>
<Link>
<TargetMachine>MachineX86</TargetMachine>
<GenerateDebugInformation>true</GenerateDebugInformation>
<SubSystem>Windows</SubSystem>
</Link>
<Lib>
<TreatLibWarningAsErrors>true</TreatLibWarningAsErrors>
</Lib>
<Lib>
<TargetMachine>MachineX86</TargetMachine>
</Lib>
<Lib>
<SubSystem>Console</SubSystem>
</Lib>
<Lib>
<LinkTimeCodeGeneration>false</LinkTimeCodeGeneration>
<IgnoreAllDefaultLibraries>true</IgnoreAllDefaultLibraries>
</Lib>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug DLL|Win32'">
<ClCompile>
<PreprocessorDefinitions>WIN32;_DEBUG;_LIB;LFDS700_BUILD_TYPE_STRING="Debug";%(PreprocessorDefinitions)</PreprocessorDefinitions>
<AdditionalIncludeDirectories>
</AdditionalIncludeDirectories>
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
<WarningLevel>Level4</WarningLevel>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
<Optimization>Disabled</Optimization>
<CompileAsManaged>false</CompileAsManaged>
<CompileAsWinRT>false</CompileAsWinRT>
<TreatWarningAsError>true</TreatWarningAsError>
<MultiProcessorCompilation>true</MultiProcessorCompilation>
<IntrinsicFunctions>true</IntrinsicFunctions>
<StringPooling>true</StringPooling>
<ExceptionHandling>false</ExceptionHandling>
<SmallerTypeCheck>true</SmallerTypeCheck>
<FunctionLevelLinking>
</FunctionLevelLinking>
<EnableParallelCodeGeneration>
</EnableParallelCodeGeneration>
<EnableEnhancedInstructionSet>
</EnableEnhancedInstructionSet>
<FloatingPointExceptions>true</FloatingPointExceptions>
<CreateHotpatchableImage>false</CreateHotpatchableImage>
<RuntimeTypeInfo>false</RuntimeTypeInfo>
<OpenMPSupport>false</OpenMPSupport>
<BrowseInformation>true</BrowseInformation>
<CompileAs>CompileAsC</CompileAs>
<UseFullPaths>true</UseFullPaths>
<ErrorReporting>None</ErrorReporting>
<SDLCheck>true</SDLCheck>
<MinimalRebuild>false</MinimalRebuild>
<DisableSpecificWarnings>4068</DisableSpecificWarnings>
</ClCompile>
<Link>
<TargetMachine>MachineX86</TargetMachine>
<GenerateDebugInformation>true</GenerateDebugInformation>
<SubSystem>Console</SubSystem>
<AdditionalDependencies>kernel32.lib;msvcrtd.lib</AdditionalDependencies>
<LinkStatus>
</LinkStatus>
<TreatLinkerWarningAsErrors>true</TreatLinkerWarningAsErrors>
<IgnoreAllDefaultLibraries>true</IgnoreAllDefaultLibraries>
<ModuleDefinitionFile>liblfds700.def</ModuleDefinitionFile>
<MapExports>true</MapExports>
<LinkErrorReporting>NoErrorReport</LinkErrorReporting>
<GenerateMapFile>true</GenerateMapFile>
</Link>
<Lib>
<TreatLibWarningAsErrors>true</TreatLibWarningAsErrors>
</Lib>
<Lib>
<TargetMachine>MachineX86</TargetMachine>
</Lib>
<Lib>
<SubSystem>Console</SubSystem>
</Lib>
<Lib>
<LinkTimeCodeGeneration>false</LinkTimeCodeGeneration>
<IgnoreAllDefaultLibraries>true</IgnoreAllDefaultLibraries>
</Lib>
<ProjectReference>
<LinkLibraryDependencies>true</LinkLibraryDependencies>
</ProjectReference>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug LIB|x64'">
<ClCompile>
<PreprocessorDefinitions>WIN32;_DEBUG;_LIB;LFDS700_BUILD_TYPE_STRING="Debug";%(PreprocessorDefinitions)</PreprocessorDefinitions>
<AdditionalIncludeDirectories>
</AdditionalIncludeDirectories>
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
<WarningLevel>Level4</WarningLevel>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
<Optimization>Disabled</Optimization>
<CompileAsManaged>false</CompileAsManaged>
<CompileAsWinRT>false</CompileAsWinRT>
<TreatWarningAsError>true</TreatWarningAsError>
<MultiProcessorCompilation>true</MultiProcessorCompilation>
<IntrinsicFunctions>true</IntrinsicFunctions>
<StringPooling>true</StringPooling>
<ExceptionHandling>false</ExceptionHandling>
<SmallerTypeCheck>true</SmallerTypeCheck>
<FunctionLevelLinking>
</FunctionLevelLinking>
<EnableParallelCodeGeneration>
</EnableParallelCodeGeneration>
<EnableEnhancedInstructionSet>
</EnableEnhancedInstructionSet>
<FloatingPointExceptions>true</FloatingPointExceptions>
<CreateHotpatchableImage>false</CreateHotpatchableImage>
<RuntimeTypeInfo>false</RuntimeTypeInfo>
<OpenMPSupport>false</OpenMPSupport>
<BrowseInformation>true</BrowseInformation>
<CompileAs>CompileAsC</CompileAs>
<UseFullPaths>true</UseFullPaths>
<ErrorReporting>None</ErrorReporting>
<SDLCheck>true</SDLCheck>
<MinimalRebuild>false</MinimalRebuild>
<DisableSpecificWarnings>4068</DisableSpecificWarnings>
<OmitFramePointers>false</OmitFramePointers>
</ClCompile>
<Link>
<GenerateDebugInformation>true</GenerateDebugInformation>
<SubSystem>Windows</SubSystem>
</Link>
<Lib>
<TreatLibWarningAsErrors>true</TreatLibWarningAsErrors>
</Lib>
<Lib>
<TargetMachine>MachineX64</TargetMachine>
</Lib>
<Lib>
<SubSystem>Console</SubSystem>
</Lib>
<Lib>
<LinkTimeCodeGeneration>false</LinkTimeCodeGeneration>
<IgnoreAllDefaultLibraries>true</IgnoreAllDefaultLibraries>
</Lib>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug DLL|x64'">
<ClCompile>
<PreprocessorDefinitions>WIN32;_DEBUG;_LIB;LFDS700_BUILD_TYPE_STRING="Debug";%(PreprocessorDefinitions)</PreprocessorDefinitions>
<AdditionalIncludeDirectories>
</AdditionalIncludeDirectories>
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
<WarningLevel>Level4</WarningLevel>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
<Optimization>Disabled</Optimization>
<CompileAsManaged>false</CompileAsManaged>
<CompileAsWinRT>false</CompileAsWinRT>
<TreatWarningAsError>true</TreatWarningAsError>
<MultiProcessorCompilation>true</MultiProcessorCompilation>
<IntrinsicFunctions>true</IntrinsicFunctions>
<StringPooling>true</StringPooling>
<ExceptionHandling>false</ExceptionHandling>
<SmallerTypeCheck>true</SmallerTypeCheck>
<FunctionLevelLinking>
</FunctionLevelLinking>
<EnableParallelCodeGeneration>
</EnableParallelCodeGeneration>
<EnableEnhancedInstructionSet>
</EnableEnhancedInstructionSet>
<FloatingPointExceptions>true</FloatingPointExceptions>
<CreateHotpatchableImage>false</CreateHotpatchableImage>
<RuntimeTypeInfo>false</RuntimeTypeInfo>
<OpenMPSupport>false</OpenMPSupport>
<BrowseInformation>true</BrowseInformation>
<CompileAs>CompileAsC</CompileAs>
<UseFullPaths>true</UseFullPaths>
<ErrorReporting>None</ErrorReporting>
<SDLCheck>true</SDLCheck>
<MinimalRebuild>false</MinimalRebuild>
<DisableSpecificWarnings>4068</DisableSpecificWarnings>
<OmitFramePointers>false</OmitFramePointers>
</ClCompile>
<Link>
<GenerateDebugInformation>true</GenerateDebugInformation>
<SubSystem>Console</SubSystem>
<TreatLinkerWarningAsErrors>true</TreatLinkerWarningAsErrors>
<IgnoreAllDefaultLibraries>true</IgnoreAllDefaultLibraries>
<ModuleDefinitionFile>liblfds700.def</ModuleDefinitionFile>
<MapExports>true</MapExports>
<OptimizeReferences>false</OptimizeReferences>
<LinkErrorReporting>NoErrorReport</LinkErrorReporting>
<AdditionalDependencies>kernel32.lib;msvcrtd.lib</AdditionalDependencies>
<GenerateMapFile>true</GenerateMapFile>
</Link>
<Lib>
<TreatLibWarningAsErrors>true</TreatLibWarningAsErrors>
</Lib>
<Lib>
<TargetMachine>MachineX64</TargetMachine>
</Lib>
<Lib>
<SubSystem>Console</SubSystem>
</Lib>
<Lib>
<LinkTimeCodeGeneration>false</LinkTimeCodeGeneration>
<IgnoreAllDefaultLibraries>true</IgnoreAllDefaultLibraries>
</Lib>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release LIB|Win32'">
<ClCompile>
<PreprocessorDefinitions>WIN32;NDEBUG;_LIB;LFDS700_BUILD_TYPE_STRING="Release";%(PreprocessorDefinitions)</PreprocessorDefinitions>
<AdditionalIncludeDirectories>
</AdditionalIncludeDirectories>
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
<WarningLevel>Level4</WarningLevel>
<DebugInformationFormat>None</DebugInformationFormat>
<CompileAsManaged>false</CompileAsManaged>
<CompileAsWinRT>false</CompileAsWinRT>
<TreatWarningAsError>true</TreatWarningAsError>
<MultiProcessorCompilation>true</MultiProcessorCompilation>
<InlineFunctionExpansion>AnySuitable</InlineFunctionExpansion>
<IntrinsicFunctions>true</IntrinsicFunctions>
<FavorSizeOrSpeed>Speed</FavorSizeOrSpeed>
<StringPooling>true</StringPooling>
<ExceptionHandling>false</ExceptionHandling>
<BufferSecurityCheck>false</BufferSecurityCheck>
<FunctionLevelLinking>
</FunctionLevelLinking>
<EnableParallelCodeGeneration>
</EnableParallelCodeGeneration>
<EnableEnhancedInstructionSet>
</EnableEnhancedInstructionSet>
<FloatingPointExceptions>false</FloatingPointExceptions>
<CreateHotpatchableImage>
</CreateHotpatchableImage>
<RuntimeTypeInfo>false</RuntimeTypeInfo>
<OpenMPSupport>false</OpenMPSupport>
<CompileAs>CompileAsC</CompileAs>
<UseFullPaths>true</UseFullPaths>
<ErrorReporting>None</ErrorReporting>
<OmitFramePointers>true</OmitFramePointers>
<DisableSpecificWarnings>4068</DisableSpecificWarnings>
<EnableFiberSafeOptimizations>true</EnableFiberSafeOptimizations>
</ClCompile>
<Link>
<TargetMachine>MachineX86</TargetMachine>
<GenerateDebugInformation>true</GenerateDebugInformation>
<SubSystem>Windows</SubSystem>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
</Link>
<Lib>
<TreatLibWarningAsErrors>true</TreatLibWarningAsErrors>
</Lib>
<Lib>
<TargetMachine>MachineX86</TargetMachine>
</Lib>
<Lib>
<SubSystem>Console</SubSystem>
<IgnoreAllDefaultLibraries>true</IgnoreAllDefaultLibraries>
</Lib>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release DLL|Win32'">
<ClCompile>
<PreprocessorDefinitions>WIN32;NDEBUG;_LIB;LFDS700_BUILD_TYPE_STRING="Release";%(PreprocessorDefinitions)</PreprocessorDefinitions>
<AdditionalIncludeDirectories>
</AdditionalIncludeDirectories>
<RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
<WarningLevel>Level4</WarningLevel>
<DebugInformationFormat>None</DebugInformationFormat>
<CompileAsManaged>false</CompileAsManaged>
<CompileAsWinRT>false</CompileAsWinRT>
<TreatWarningAsError>true</TreatWarningAsError>
<MultiProcessorCompilation>true</MultiProcessorCompilation>
<InlineFunctionExpansion>AnySuitable</InlineFunctionExpansion>
<IntrinsicFunctions>true</IntrinsicFunctions>
<FavorSizeOrSpeed>Speed</FavorSizeOrSpeed>
<StringPooling>true</StringPooling>
<ExceptionHandling>false</ExceptionHandling>
<BufferSecurityCheck>false</BufferSecurityCheck>
<FunctionLevelLinking>
</FunctionLevelLinking>
<EnableParallelCodeGeneration>
</EnableParallelCodeGeneration>
<EnableEnhancedInstructionSet>
</EnableEnhancedInstructionSet>
<FloatingPointExceptions>false</FloatingPointExceptions>
<CreateHotpatchableImage>
</CreateHotpatchableImage>
<RuntimeTypeInfo>false</RuntimeTypeInfo>
<OpenMPSupport>false</OpenMPSupport>
<CompileAs>CompileAsC</CompileAs>
<UseFullPaths>true</UseFullPaths>
<ErrorReporting>None</ErrorReporting>
<OmitFramePointers>true</OmitFramePointers>
<DisableSpecificWarnings>4068</DisableSpecificWarnings>
<EnableFiberSafeOptimizations>true</EnableFiberSafeOptimizations>
</ClCompile>
<Link>
<TargetMachine>MachineX86</TargetMachine>
<GenerateDebugInformation>false</GenerateDebugInformation>
<SubSystem>Console</SubSystem>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<AdditionalDependencies>kernel32.lib;msvcrt.lib</AdditionalDependencies>
<LinkStatus>
</LinkStatus>
<TreatLinkerWarningAsErrors>true</TreatLinkerWarningAsErrors>
<IgnoreAllDefaultLibraries>true</IgnoreAllDefaultLibraries>
<ModuleDefinitionFile>liblfds700.def</ModuleDefinitionFile>
<LinkErrorReporting>NoErrorReport</LinkErrorReporting>
</Link>
<Lib>
<TreatLibWarningAsErrors>true</TreatLibWarningAsErrors>
</Lib>
<Lib>
<TargetMachine>MachineX86</TargetMachine>
</Lib>
<Lib>
<SubSystem>Console</SubSystem>
<IgnoreAllDefaultLibraries>true</IgnoreAllDefaultLibraries>
</Lib>
<ProjectReference>
<LinkLibraryDependencies>true</LinkLibraryDependencies>
</ProjectReference>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release LIB|x64'">
<ClCompile>
<PreprocessorDefinitions>WIN32;NDEBUG;_LIB;LFDS700_BUILD_TYPE_STRING="Release";%(PreprocessorDefinitions)</PreprocessorDefinitions>
<AdditionalIncludeDirectories>
</AdditionalIncludeDirectories>
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
<WarningLevel>Level4</WarningLevel>
<DebugInformationFormat>None</DebugInformationFormat>
<CompileAsManaged>false</CompileAsManaged>
<CompileAsWinRT>false</CompileAsWinRT>
<TreatWarningAsError>true</TreatWarningAsError>
<MultiProcessorCompilation>true</MultiProcessorCompilation>
<InlineFunctionExpansion>AnySuitable</InlineFunctionExpansion>
<IntrinsicFunctions>true</IntrinsicFunctions>
<FavorSizeOrSpeed>Speed</FavorSizeOrSpeed>
<StringPooling>true</StringPooling>
<ExceptionHandling>false</ExceptionHandling>
<BufferSecurityCheck>false</BufferSecurityCheck>
<FunctionLevelLinking>
</FunctionLevelLinking>
<EnableParallelCodeGeneration>
</EnableParallelCodeGeneration>
<EnableEnhancedInstructionSet>
</EnableEnhancedInstructionSet>
<FloatingPointExceptions>false</FloatingPointExceptions>
<CreateHotpatchableImage>
</CreateHotpatchableImage>
<RuntimeTypeInfo>false</RuntimeTypeInfo>
<OpenMPSupport>false</OpenMPSupport>
<CompileAs>CompileAsC</CompileAs>
<UseFullPaths>true</UseFullPaths>
<ErrorReporting>None</ErrorReporting>
<OmitFramePointers>true</OmitFramePointers>
<DisableSpecificWarnings>4068</DisableSpecificWarnings>
<EnableFiberSafeOptimizations>true</EnableFiberSafeOptimizations>
</ClCompile>
<Link>
<GenerateDebugInformation>true</GenerateDebugInformation>
<SubSystem>Windows</SubSystem>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
</Link>
<Lib>
<TreatLibWarningAsErrors>true</TreatLibWarningAsErrors>
</Lib>
<Lib>
<TargetMachine>MachineX64</TargetMachine>
</Lib>
<Lib>
<SubSystem>Console</SubSystem>
<IgnoreAllDefaultLibraries>true</IgnoreAllDefaultLibraries>
</Lib>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release DLL|x64'">
<ClCompile>
<PreprocessorDefinitions>WIN32;NDEBUG;_LIB;LFDS700_BUILD_TYPE_STRING="Release";%(PreprocessorDefinitions)</PreprocessorDefinitions>
<AdditionalIncludeDirectories>
</AdditionalIncludeDirectories>
<RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
<WarningLevel>Level4</WarningLevel>
<DebugInformationFormat>None</DebugInformationFormat>
<CompileAsManaged>false</CompileAsManaged>
<CompileAsWinRT>false</CompileAsWinRT>
<TreatWarningAsError>true</TreatWarningAsError>
<MultiProcessorCompilation>true</MultiProcessorCompilation>
<InlineFunctionExpansion>AnySuitable</InlineFunctionExpansion>
<IntrinsicFunctions>true</IntrinsicFunctions>
<FavorSizeOrSpeed>Speed</FavorSizeOrSpeed>
<StringPooling>true</StringPooling>
<ExceptionHandling>false</ExceptionHandling>
<BufferSecurityCheck>false</BufferSecurityCheck>
<FunctionLevelLinking>
</FunctionLevelLinking>
<EnableParallelCodeGeneration>
</EnableParallelCodeGeneration>
<EnableEnhancedInstructionSet>
</EnableEnhancedInstructionSet>
<FloatingPointExceptions>false</FloatingPointExceptions>
<CreateHotpatchableImage>
</CreateHotpatchableImage>
<RuntimeTypeInfo>false</RuntimeTypeInfo>
<OpenMPSupport>false</OpenMPSupport>
<CompileAs>CompileAsC</CompileAs>
<UseFullPaths>true</UseFullPaths>
<ErrorReporting>None</ErrorReporting>
<OmitFramePointers>true</OmitFramePointers>
<DisableSpecificWarnings>4068</DisableSpecificWarnings>
<EnableFiberSafeOptimizations>true</EnableFiberSafeOptimizations>
</ClCompile>
<Link>
<GenerateDebugInformation>false</GenerateDebugInformation>
<SubSystem>Console</SubSystem>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<TreatLinkerWarningAsErrors>true</TreatLinkerWarningAsErrors>
<IgnoreAllDefaultLibraries>true</IgnoreAllDefaultLibraries>
<ModuleDefinitionFile>liblfds700.def</ModuleDefinitionFile>
<LinkErrorReporting>NoErrorReport</LinkErrorReporting>
<AdditionalDependencies>kernel32.lib;msvcrt.lib</AdditionalDependencies>
</Link>
<Lib>
<TreatLibWarningAsErrors>true</TreatLibWarningAsErrors>
</Lib>
<Lib>
<TargetMachine>MachineX64</TargetMachine>
</Lib>
<Lib>
<SubSystem>Console</SubSystem>
<IgnoreAllDefaultLibraries>true</IgnoreAllDefaultLibraries>
</Lib>
</ItemDefinitionGroup>
<ItemGroup>
<ClInclude Include="..\..\inc\liblfds700.h" />
<ClInclude Include="..\..\inc\liblfds700\lfds700_btree_addonly_unbalanced.h" />
<ClInclude Include="..\..\inc\liblfds700\lfds700_freelist.h" />
<ClInclude Include="..\..\inc\liblfds700\lfds700_hash_addonly.h" />
<ClInclude Include="..\..\inc\liblfds700\lfds700_list_addonly_ordered_singlylinked.h" />
<ClInclude Include="..\..\inc\liblfds700\lfds700_list_addonly_singlylinked_unordered.h" />
<ClInclude Include="..\..\inc\liblfds700\lfds700_misc.h" />
<ClInclude Include="..\..\inc\liblfds700\lfds700_porting_abstraction_layer_compiler.h" />
<ClInclude Include="..\..\inc\liblfds700\lfds700_porting_abstraction_layer_operating_system.h" />
<ClInclude Include="..\..\inc\liblfds700\lfds700_porting_abstraction_layer_processor.h" />
<ClInclude Include="..\..\inc\liblfds700\lfds700_queue.h" />
<ClInclude Include="..\..\inc\liblfds700\lfds700_queue_bounded_singleconsumer_singleproducer.h" />
<ClInclude Include="..\..\inc\liblfds700\lfds700_ringbuffer.h" />
<ClInclude Include="..\..\inc\liblfds700\lfds700_stack.h" />
<ClInclude Include="..\..\src\lfds700_btree_addonly_unbalanced\lfds700_btree_addonly_unbalanced_internal.h" />
<ClInclude Include="..\..\src\lfds700_freelist\lfds700_freelist_internal.h" />
<ClInclude Include="..\..\src\lfds700_hash_addonly\lfds700_hash_addonly_internal.h" />
<ClInclude Include="..\..\src\lfds700_list_addonly_ordered_singlylinked\lfds700_list_addonly_ordered_singlylinked_internal.h" />
<ClInclude Include="..\..\src\lfds700_list_addonly_singlylinked_unordered\lfds700_list_addonly_singlylinked_unordered_internal.h" />
<ClInclude Include="..\..\src\lfds700_misc\lfds700_misc_internal.h" />
<ClInclude Include="..\..\src\lfds700_queue\lfds700_queue_internal.h" />
<ClInclude Include="..\..\src\lfds700_queue_bounded_singleconsumer_singleproducer\lfds700_queue_bounded_singleconsumer_singleproducer_internal.h" />
<ClInclude Include="..\..\src\lfds700_ringbuffer\lfds700_ringbuffer_internal.h" />
<ClInclude Include="..\..\src\lfds700_stack\lfds700_stack_internal.h" />
</ItemGroup>
<ItemGroup>
<ClCompile Include="..\..\src\lfds700_btree_addonly_unbalanced\lfds700_btree_addonly_unbalanced_cleanup.c" />
<ClCompile Include="..\..\src\lfds700_btree_addonly_unbalanced\lfds700_btree_addonly_unbalanced_get.c" />
<ClCompile Include="..\..\src\lfds700_btree_addonly_unbalanced\lfds700_btree_addonly_unbalanced_init.c" />
<ClCompile Include="..\..\src\lfds700_btree_addonly_unbalanced\lfds700_btree_addonly_unbalanced_insert.c" />
<ClCompile Include="..\..\src\lfds700_btree_addonly_unbalanced\lfds700_btree_addonly_unbalanced_query.c" />
<ClCompile Include="..\..\src\lfds700_freelist\lfds700_freelist_cleanup.c" />
<ClCompile Include="..\..\src\lfds700_freelist\lfds700_freelist_init.c" />
<ClCompile Include="..\..\src\lfds700_freelist\lfds700_freelist_pop.c" />
<ClCompile Include="..\..\src\lfds700_freelist\lfds700_freelist_push.c" />
<ClCompile Include="..\..\src\lfds700_freelist\lfds700_freelist_query.c" />
<ClCompile Include="..\..\src\lfds700_hash_addonly\lfds700_hash_addonly_cleanup.c" />
<ClCompile Include="..\..\src\lfds700_hash_addonly\lfds700_hash_addonly_get.c" />
<ClCompile Include="..\..\src\lfds700_hash_addonly\lfds700_hash_addonly_init.c" />
<ClCompile Include="..\..\src\lfds700_hash_addonly\lfds700_hash_addonly_insert.c" />
<ClCompile Include="..\..\src\lfds700_hash_addonly\lfds700_hash_addonly_iterate.c" />
<ClCompile Include="..\..\src\lfds700_hash_addonly\lfds700_hash_addonly_query.c" />
<ClCompile Include="..\..\src\lfds700_list_addonly_ordered_singlylinked\lfds700_list_addonly_ordered_singlylinked_cleanup.c" />
<ClCompile Include="..\..\src\lfds700_list_addonly_ordered_singlylinked\lfds700_list_addonly_ordered_singlylinked_get.c" />
<ClCompile Include="..\..\src\lfds700_list_addonly_ordered_singlylinked\lfds700_list_addonly_ordered_singlylinked_init.c" />
<ClCompile Include="..\..\src\lfds700_list_addonly_ordered_singlylinked\lfds700_list_addonly_ordered_singlylinked_insert.c" />
<ClCompile Include="..\..\src\lfds700_list_addonly_ordered_singlylinked\lfds700_list_addonly_ordered_singlylinked_query.c" />
<ClCompile Include="..\..\src\lfds700_list_addonly_singlylinked_unordered\lfds700_list_addonly_singlylinked_unordered_cleanup.c" />
<ClCompile Include="..\..\src\lfds700_list_addonly_singlylinked_unordered\lfds700_list_addonly_singlylinked_unordered_get.c" />
<ClCompile Include="..\..\src\lfds700_list_addonly_singlylinked_unordered\lfds700_list_addonly_singlylinked_unordered_init.c" />
<ClCompile Include="..\..\src\lfds700_list_addonly_singlylinked_unordered\lfds700_list_addonly_singlylinked_unordered_insert.c" />
<ClCompile Include="..\..\src\lfds700_list_addonly_singlylinked_unordered\lfds700_list_addonly_singlylinked_unordered_query.c" />
<ClCompile Include="..\..\src\lfds700_misc\lfds700_misc_cleanup.c" />
<ClCompile Include="..\..\src\lfds700_misc\lfds700_misc_globals.c" />
<ClCompile Include="..\..\src\lfds700_misc\lfds700_misc_init.c" />
<ClCompile Include="..\..\src\lfds700_misc\lfds700_misc_prng.c" />
<ClCompile Include="..\..\src\lfds700_misc\lfds700_misc_query.c" />
<ClCompile Include="..\..\src\lfds700_queue\lfds700_queue_cleanup.c" />
<ClCompile Include="..\..\src\lfds700_queue\lfds700_queue_dequeue.c" />
<ClCompile Include="..\..\src\lfds700_queue\lfds700_queue_enqueue.c" />
<ClCompile Include="..\..\src\lfds700_queue\lfds700_queue_init.c" />
<ClCompile Include="..\..\src\lfds700_queue\lfds700_queue_query.c" />
<ClCompile Include="..\..\src\lfds700_queue_bounded_singleconsumer_singleproducer\lfds700_queue_bounded_singleconsumer_singleproducer_cleanup.c" />
<ClCompile Include="..\..\src\lfds700_queue_bounded_singleconsumer_singleproducer\lfds700_queue_bounded_singleconsumer_singleproducer_dequeue.c" />
<ClCompile Include="..\..\src\lfds700_queue_bounded_singleconsumer_singleproducer\lfds700_queue_bounded_singleconsumer_singleproducer_enqueue.c" />
<ClCompile Include="..\..\src\lfds700_queue_bounded_singleconsumer_singleproducer\lfds700_queue_bounded_singleconsumer_singleproducer_init.c" />
<ClCompile Include="..\..\src\lfds700_queue_bounded_singleconsumer_singleproducer\lfds700_queue_bounded_singleconsumer_singleproducer_query.c" />
<ClCompile Include="..\..\src\lfds700_ringbuffer\lfds700_ringbuffer_cleanup.c" />
<ClCompile Include="..\..\src\lfds700_ringbuffer\lfds700_ringbuffer_init.c" />
<ClCompile Include="..\..\src\lfds700_ringbuffer\lfds700_ringbuffer_query.c" />
<ClCompile Include="..\..\src\lfds700_ringbuffer\lfds700_ringbuffer_read.c" />
<ClCompile Include="..\..\src\lfds700_ringbuffer\lfds700_ringbuffer_write.c" />
<ClCompile Include="..\..\src\lfds700_stack\lfds700_stack_cleanup.c" />
<ClCompile Include="..\..\src\lfds700_stack\lfds700_stack_init.c" />
<ClCompile Include="..\..\src\lfds700_stack\lfds700_stack_pop.c" />
<ClCompile Include="..\..\src\lfds700_stack\lfds700_stack_push.c" />
<ClCompile Include="..\..\src\lfds700_stack\lfds700_stack_query.c" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<Filter Include="Source Files">
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
<Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
</Filter>
<Filter Include="Header Files">
<UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
<Extensions>h;hpp;hxx;hm;inl;inc;xsd</Extensions>
</Filter>
<Filter Include="Resource Files">
<UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
<Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav</Extensions>
</Filter>
<Filter Include="Header Files\liblfds700">
<UniqueIdentifier>{258be429-7dac-4999-b995-753aa2f0c505}</UniqueIdentifier>
</Filter>
<Filter Include="Source Files\lfds700_freelist">
<UniqueIdentifier>{469abf8e-47d8-4678-bd66-7c7e65c5f52e}</UniqueIdentifier>
</Filter>
<Filter Include="Source Files\lfds700_ringbuffer">
<UniqueIdentifier>{62ee141b-2acb-4555-b016-7be20a57f2bf}</UniqueIdentifier>
</Filter>
<Filter Include="Source Files\lfds700_stack">
<UniqueIdentifier>{19c73b0f-25e0-4166-9093-427f1dfb4f70}</UniqueIdentifier>
</Filter>
<Filter Include="Source Files\lfds700_queue">
<UniqueIdentifier>{00eb30fe-e638-4c2b-8ca1-1f09c4a0ed45}</UniqueIdentifier>
</Filter>
<Filter Include="Source Files\lfds700_misc">
<UniqueIdentifier>{400ae4e9-2281-4549-b918-59d1a27a2d07}</UniqueIdentifier>
</Filter>
<Filter Include="Source Files\lfds700_btree_addonly_unbalanced">
<UniqueIdentifier>{0b1fafc3-817b-4c18-8eb1-121884e3a29b}</UniqueIdentifier>
</Filter>
<Filter Include="Source Files\lfds700_hash_addonly">
<UniqueIdentifier>{bcbadc74-1748-4696-aad7-7fdbe5614624}</UniqueIdentifier>
</Filter>
<Filter Include="Source Files\lfds700_list_addonly_ordered_singlylinked">
<UniqueIdentifier>{c45194af-7b41-4c28-bc0e-1095ec347664}</UniqueIdentifier>
</Filter>
<Filter Include="Source Files\lfds700_queue_bounded_singleconsumer_singleproducer">
<UniqueIdentifier>{6250c4d5-ac8e-4c28-93de-0954c5bed1cb}</UniqueIdentifier>
</Filter>
<Filter Include="Source Files\lfds700_list_addonly_singlylinked_unordered">
<UniqueIdentifier>{3ac93721-1d81-49e4-9581-dbc12ace5c0c}</UniqueIdentifier>
</Filter>
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\..\inc\liblfds700.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\..\src\lfds700_freelist\lfds700_freelist_internal.h">
<Filter>Source Files\lfds700_freelist</Filter>
</ClInclude>
<ClInclude Include="..\..\src\lfds700_queue\lfds700_queue_internal.h">
<Filter>Source Files\lfds700_queue</Filter>
</ClInclude>
<ClInclude Include="..\..\src\lfds700_stack\lfds700_stack_internal.h">
<Filter>Source Files\lfds700_stack</Filter>
</ClInclude>
<ClInclude Include="..\..\inc\liblfds700\lfds700_btree_addonly_unbalanced.h">
<Filter>Header Files\liblfds700</Filter>
</ClInclude>
<ClInclude Include="..\..\inc\liblfds700\lfds700_freelist.h">
<Filter>Header Files\liblfds700</Filter>
</ClInclude>
<ClInclude Include="..\..\inc\liblfds700\lfds700_hash_addonly.h">
<Filter>Header Files\liblfds700</Filter>
</ClInclude>
<ClInclude Include="..\..\inc\liblfds700\lfds700_list_addonly_ordered_singlylinked.h">
<Filter>Header Files\liblfds700</Filter>
</ClInclude>
<ClInclude Include="..\..\inc\liblfds700\lfds700_list_addonly_singlylinked_unordered.h">
<Filter>Header Files\liblfds700</Filter>
</ClInclude>
<ClInclude Include="..\..\inc\liblfds700\lfds700_misc.h">
<Filter>Header Files\liblfds700</Filter>
</ClInclude>
<ClInclude Include="..\..\inc\liblfds700\lfds700_porting_abstraction_layer_compiler.h">
<Filter>Header Files\liblfds700</Filter>
</ClInclude>
<ClInclude Include="..\..\inc\liblfds700\lfds700_porting_abstraction_layer_operating_system.h">
<Filter>Header Files\liblfds700</Filter>
</ClInclude>
<ClInclude Include="..\..\inc\liblfds700\lfds700_porting_abstraction_layer_processor.h">
<Filter>Header Files\liblfds700</Filter>
</ClInclude>
<ClInclude Include="..\..\inc\liblfds700\lfds700_queue.h">
<Filter>Header Files\liblfds700</Filter>
</ClInclude>
<ClInclude Include="..\..\inc\liblfds700\lfds700_queue_bounded_singleconsumer_singleproducer.h">
<Filter>Header Files\liblfds700</Filter>
</ClInclude>
<ClInclude Include="..\..\inc\liblfds700\lfds700_ringbuffer.h">
<Filter>Header Files\liblfds700</Filter>
</ClInclude>
<ClInclude Include="..\..\inc\liblfds700\lfds700_stack.h">
<Filter>Header Files\liblfds700</Filter>
</ClInclude>
<ClInclude Include="..\..\src\lfds700_hash_addonly\lfds700_hash_addonly_internal.h">
<Filter>Source Files\lfds700_hash_addonly</Filter>
</ClInclude>
<ClInclude Include="..\..\src\lfds700_misc\lfds700_misc_internal.h">
<Filter>Source Files\lfds700_misc</Filter>
</ClInclude>
<ClInclude Include="..\..\src\lfds700_btree_addonly_unbalanced\lfds700_btree_addonly_unbalanced_internal.h">
<Filter>Source Files\lfds700_btree_addonly_unbalanced</Filter>
</ClInclude>
<ClInclude Include="..\..\src\lfds700_ringbuffer\lfds700_ringbuffer_internal.h">
<Filter>Source Files\lfds700_ringbuffer</Filter>
</ClInclude>
<ClInclude Include="..\..\src\lfds700_queue_bounded_singleconsumer_singleproducer\lfds700_queue_bounded_singleconsumer_singleproducer_internal.h">
<Filter>Source Files\lfds700_queue_bounded_singleconsumer_singleproducer</Filter>
</ClInclude>
<ClInclude Include="..\..\src\lfds700_list_addonly_ordered_singlylinked\lfds700_list_addonly_ordered_singlylinked_internal.h">
<Filter>Source Files\lfds700_list_addonly_ordered_singlylinked</Filter>
</ClInclude>
<ClInclude Include="..\..\src\lfds700_list_addonly_singlylinked_unordered\lfds700_list_addonly_singlylinked_unordered_internal.h">
<Filter>Source Files\lfds700_list_addonly_singlylinked_unordered</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ClCompile Include="..\..\src\lfds700_freelist\lfds700_freelist_cleanup.c">
<Filter>Source Files\lfds700_freelist</Filter>
</ClCompile>
<ClCompile Include="..\..\src\lfds700_freelist\lfds700_freelist_init.c">
<Filter>Source Files\lfds700_freelist</Filter>
</ClCompile>
<ClCompile Include="..\..\src\lfds700_freelist\lfds700_freelist_pop.c">
<Filter>Source Files\lfds700_freelist</Filter>
</ClCompile>
<ClCompile Include="..\..\src\lfds700_freelist\lfds700_freelist_push.c">
<Filter>Source Files\lfds700_freelist</Filter>
</ClCompile>
<ClCompile Include="..\..\src\lfds700_freelist\lfds700_freelist_query.c">
<Filter>Source Files\lfds700_freelist</Filter>
</ClCompile>
<ClCompile Include="..\..\src\lfds700_queue\lfds700_queue_cleanup.c">
<Filter>Source Files\lfds700_queue</Filter>
</ClCompile>
<ClCompile Include="..\..\src\lfds700_queue\lfds700_queue_dequeue.c">
<Filter>Source Files\lfds700_queue</Filter>
</ClCompile>
<ClCompile Include="..\..\src\lfds700_queue\lfds700_queue_enqueue.c">
<Filter>Source Files\lfds700_queue</Filter>
</ClCompile>
<ClCompile Include="..\..\src\lfds700_queue\lfds700_queue_init.c">
<Filter>Source Files\lfds700_queue</Filter>
</ClCompile>
<ClCompile Include="..\..\src\lfds700_queue\lfds700_queue_query.c">
<Filter>Source Files\lfds700_queue</Filter>
</ClCompile>
<ClCompile Include="..\..\src\lfds700_stack\lfds700_stack_cleanup.c">
<Filter>Source Files\lfds700_stack</Filter>
</ClCompile>
<ClCompile Include="..\..\src\lfds700_stack\lfds700_stack_init.c">
<Filter>Source Files\lfds700_stack</Filter>
</ClCompile>
<ClCompile Include="..\..\src\lfds700_stack\lfds700_stack_pop.c">
<Filter>Source Files\lfds700_stack</Filter>
</ClCompile>
<ClCompile Include="..\..\src\lfds700_stack\lfds700_stack_push.c">
<Filter>Source Files\lfds700_stack</Filter>
</ClCompile>
<ClCompile Include="..\..\src\lfds700_stack\lfds700_stack_query.c">
<Filter>Source Files\lfds700_stack</Filter>
</ClCompile>
<ClCompile Include="..\..\src\lfds700_hash_addonly\lfds700_hash_addonly_cleanup.c">
<Filter>Source Files\lfds700_hash_addonly</Filter>
</ClCompile>
<ClCompile Include="..\..\src\lfds700_hash_addonly\lfds700_hash_addonly_get.c">
<Filter>Source Files\lfds700_hash_addonly</Filter>
</ClCompile>
<ClCompile Include="..\..\src\lfds700_hash_addonly\lfds700_hash_addonly_init.c">
<Filter>Source Files\lfds700_hash_addonly</Filter>
</ClCompile>
<ClCompile Include="..\..\src\lfds700_hash_addonly\lfds700_hash_addonly_insert.c">
<Filter>Source Files\lfds700_hash_addonly</Filter>
</ClCompile>
<ClCompile Include="..\..\src\lfds700_hash_addonly\lfds700_hash_addonly_iterate.c">
<Filter>Source Files\lfds700_hash_addonly</Filter>
</ClCompile>
<ClCompile Include="..\..\src\lfds700_hash_addonly\lfds700_hash_addonly_query.c">
<Filter>Source Files\lfds700_hash_addonly</Filter>
</ClCompile>
<ClCompile Include="..\..\src\lfds700_misc\lfds700_misc_cleanup.c">
<Filter>Source Files\lfds700_misc</Filter>
</ClCompile>
<ClCompile Include="..\..\src\lfds700_misc\lfds700_misc_globals.c">
<Filter>Source Files\lfds700_misc</Filter>
</ClCompile>
<ClCompile Include="..\..\src\lfds700_misc\lfds700_misc_init.c">
<Filter>Source Files\lfds700_misc</Filter>
</ClCompile>
<ClCompile Include="..\..\src\lfds700_misc\lfds700_misc_prng.c">
<Filter>Source Files\lfds700_misc</Filter>
</ClCompile>
<ClCompile Include="..\..\src\lfds700_misc\lfds700_misc_query.c">
<Filter>Source Files\lfds700_misc</Filter>
</ClCompile>
<ClCompile Include="..\..\src\lfds700_btree_addonly_unbalanced\lfds700_btree_addonly_unbalanced_cleanup.c">
<Filter>Source Files\lfds700_btree_addonly_unbalanced</Filter>
</ClCompile>
<ClCompile Include="..\..\src\lfds700_btree_addonly_unbalanced\lfds700_btree_addonly_unbalanced_get.c">
<Filter>Source Files\lfds700_btree_addonly_unbalanced</Filter>
</ClCompile>
<ClCompile Include="..\..\src\lfds700_btree_addonly_unbalanced\lfds700_btree_addonly_unbalanced_init.c">
<Filter>Source Files\lfds700_btree_addonly_unbalanced</Filter>
</ClCompile>
<ClCompile Include="..\..\src\lfds700_btree_addonly_unbalanced\lfds700_btree_addonly_unbalanced_insert.c">
<Filter>Source Files\lfds700_btree_addonly_unbalanced</Filter>
</ClCompile>
<ClCompile Include="..\..\src\lfds700_btree_addonly_unbalanced\lfds700_btree_addonly_unbalanced_query.c">
<Filter>Source Files\lfds700_btree_addonly_unbalanced</Filter>
</ClCompile>
<ClCompile Include="..\..\src\lfds700_ringbuffer\lfds700_ringbuffer_cleanup.c">
<Filter>Source Files\lfds700_ringbuffer</Filter>
</ClCompile>
<ClCompile Include="..\..\src\lfds700_ringbuffer\lfds700_ringbuffer_init.c">
<Filter>Source Files\lfds700_ringbuffer</Filter>
</ClCompile>
<ClCompile Include="..\..\src\lfds700_ringbuffer\lfds700_ringbuffer_query.c">
<Filter>Source Files\lfds700_ringbuffer</Filter>
</ClCompile>
<ClCompile Include="..\..\src\lfds700_ringbuffer\lfds700_ringbuffer_read.c">
<Filter>Source Files\lfds700_ringbuffer</Filter>
</ClCompile>
<ClCompile Include="..\..\src\lfds700_ringbuffer\lfds700_ringbuffer_write.c">
<Filter>Source Files\lfds700_ringbuffer</Filter>
</ClCompile>
<ClCompile Include="..\..\src\lfds700_queue_bounded_singleconsumer_singleproducer\lfds700_queue_bounded_singleconsumer_singleproducer_cleanup.c">
<Filter>Source Files\lfds700_queue_bounded_singleconsumer_singleproducer</Filter>
</ClCompile>
<ClCompile Include="..\..\src\lfds700_queue_bounded_singleconsumer_singleproducer\lfds700_queue_bounded_singleconsumer_singleproducer_dequeue.c">
<Filter>Source Files\lfds700_queue_bounded_singleconsumer_singleproducer</Filter>
</ClCompile>
<ClCompile Include="..\..\src\lfds700_queue_bounded_singleconsumer_singleproducer\lfds700_queue_bounded_singleconsumer_singleproducer_enqueue.c">
<Filter>Source Files\lfds700_queue_bounded_singleconsumer_singleproducer</Filter>
</ClCompile>
<ClCompile Include="..\..\src\lfds700_queue_bounded_singleconsumer_singleproducer\lfds700_queue_bounded_singleconsumer_singleproducer_init.c">
<Filter>Source Files\lfds700_queue_bounded_singleconsumer_singleproducer</Filter>
</ClCompile>
<ClCompile Include="..\..\src\lfds700_queue_bounded_singleconsumer_singleproducer\lfds700_queue_bounded_singleconsumer_singleproducer_query.c">
<Filter>Source Files\lfds700_queue_bounded_singleconsumer_singleproducer</Filter>
</ClCompile>
<ClCompile Include="..\..\src\lfds700_list_addonly_ordered_singlylinked\lfds700_list_addonly_ordered_singlylinked_cleanup.c">
<Filter>Source Files\lfds700_list_addonly_ordered_singlylinked</Filter>
</ClCompile>
<ClCompile Include="..\..\src\lfds700_list_addonly_ordered_singlylinked\lfds700_list_addonly_ordered_singlylinked_get.c">
<Filter>Source Files\lfds700_list_addonly_ordered_singlylinked</Filter>
</ClCompile>
<ClCompile Include="..\..\src\lfds700_list_addonly_ordered_singlylinked\lfds700_list_addonly_ordered_singlylinked_init.c">
<Filter>Source Files\lfds700_list_addonly_ordered_singlylinked</Filter>
</ClCompile>
<ClCompile Include="..\..\src\lfds700_list_addonly_ordered_singlylinked\lfds700_list_addonly_ordered_singlylinked_insert.c">
<Filter>Source Files\lfds700_list_addonly_ordered_singlylinked</Filter>
</ClCompile>
<ClCompile Include="..\..\src\lfds700_list_addonly_ordered_singlylinked\lfds700_list_addonly_ordered_singlylinked_query.c">
<Filter>Source Files\lfds700_list_addonly_ordered_singlylinked</Filter>
</ClCompile>
<ClCompile Include="..\..\src\lfds700_list_addonly_singlylinked_unordered\lfds700_list_addonly_singlylinked_unordered_cleanup.c">
<Filter>Source Files\lfds700_list_addonly_singlylinked_unordered</Filter>
</ClCompile>
<ClCompile Include="..\..\src\lfds700_list_addonly_singlylinked_unordered\lfds700_list_addonly_singlylinked_unordered_get.c">
<Filter>Source Files\lfds700_list_addonly_singlylinked_unordered</Filter>
</ClCompile>
<ClCompile Include="..\..\src\lfds700_list_addonly_singlylinked_unordered\lfds700_list_addonly_singlylinked_unordered_init.c">
<Filter>Source Files\lfds700_list_addonly_singlylinked_unordered</Filter>
</ClCompile>
<ClCompile Include="..\..\src\lfds700_list_addonly_singlylinked_unordered\lfds700_list_addonly_singlylinked_unordered_insert.c">
<Filter>Source Files\lfds700_list_addonly_singlylinked_unordered</Filter>
</ClCompile>
<ClCompile Include="..\..\src\lfds700_list_addonly_singlylinked_unordered\lfds700_list_addonly_singlylinked_unordered_query.c">
<Filter>Source Files\lfds700_list_addonly_singlylinked_unordered</Filter>
</ClCompile>
</ItemGroup>
</Project>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup />
</Project>
\ No newline at end of file
EXPORTS
lfds700_btree_au_init_valid_on_current_logical_core = lfds700_btree_au_init_valid_on_current_logical_core
lfds700_btree_au_cleanup = lfds700_btree_au_cleanup
lfds700_btree_au_insert = lfds700_btree_au_insert
lfds700_btree_au_get_by_absolute_position_and_then_by_relative_position = lfds700_btree_au_get_by_absolute_position_and_then_by_relative_position
lfds700_btree_au_get_by_absolute_position = lfds700_btree_au_get_by_absolute_position
lfds700_btree_au_get_by_relative_position = lfds700_btree_au_get_by_relative_position
lfds700_btree_au_get_by_key = lfds700_btree_au_get_by_key
lfds700_btree_au_query = lfds700_btree_au_query
lfds700_freelist_init_valid_on_current_logical_core = lfds700_freelist_init_valid_on_current_logical_core
lfds700_freelist_cleanup = lfds700_freelist_cleanup
lfds700_freelist_push = lfds700_freelist_push
lfds700_freelist_pop = lfds700_freelist_pop
lfds700_freelist_query = lfds700_freelist_query
lfds700_hash_a_init_valid_on_current_logical_core = lfds700_hash_a_init_valid_on_current_logical_core
lfds700_hash_a_cleanup = lfds700_hash_a_cleanup
lfds700_hash_a_insert = lfds700_hash_a_insert
lfds700_hash_a_get_by_key = lfds700_hash_a_get_by_key
lfds700_hash_a_iterate_init = lfds700_hash_a_iterate_init
lfds700_hash_a_iterate = lfds700_hash_a_iterate
lfds700_hash_a_query = lfds700_hash_a_query
lfds700_list_aos_init_valid_on_current_logical_core = lfds700_list_aos_init_valid_on_current_logical_core
lfds700_list_aos_cleanup = lfds700_list_aos_cleanup
lfds700_list_aos_insert = lfds700_list_aos_insert
lfds700_list_aos_get_by_key = lfds700_list_aos_get_by_key
lfds700_list_aos_query = lfds700_list_aos_query
lfds700_list_asu_init_valid_on_current_logical_core = lfds700_list_asu_init_valid_on_current_logical_core
lfds700_list_asu_cleanup = lfds700_list_asu_cleanup
lfds700_list_asu_insert_at_position = lfds700_list_asu_insert_at_position
lfds700_list_asu_insert_at_start = lfds700_list_asu_insert_at_start
lfds700_list_asu_insert_at_end = lfds700_list_asu_insert_at_end
lfds700_list_asu_insert_after_element = lfds700_list_asu_insert_after_element
lfds700_list_asu_get_by_key = lfds700_list_asu_get_by_key
lfds700_list_asu_query = lfds700_list_asu_query
lfds700_misc_library_init_valid_on_current_logical_core = lfds700_misc_library_init_valid_on_current_logical_core
lfds700_misc_library_cleanup = lfds700_misc_library_cleanup
lfds700_misc_prng_init = lfds700_misc_prng_init
lfds700_misc_query = lfds700_misc_query
lfds700_queue_init_valid_on_current_logical_core = lfds700_queue_init_valid_on_current_logical_core
lfds700_queue_cleanup = lfds700_queue_cleanup
lfds700_queue_enqueue = lfds700_queue_enqueue
lfds700_queue_dequeue = lfds700_queue_dequeue
lfds700_queue_query = lfds700_queue_query
lfds700_queue_bss_init_valid_on_current_logical_core = lfds700_queue_bss_init_valid_on_current_logical_core
lfds700_queue_bss_cleanup = lfds700_queue_bss_cleanup
lfds700_queue_bss_enqueue = lfds700_queue_bss_enqueue
lfds700_queue_bss_dequeue = lfds700_queue_bss_dequeue
lfds700_queue_bss_query = lfds700_queue_bss_query
lfds700_ringbuffer_init_valid_on_current_logical_core = lfds700_ringbuffer_init_valid_on_current_logical_core
lfds700_ringbuffer_cleanup = lfds700_ringbuffer_cleanup
lfds700_ringbuffer_read = lfds700_ringbuffer_read
lfds700_ringbuffer_write = lfds700_ringbuffer_write
lfds700_ringbuffer_query = lfds700_ringbuffer_query
lfds700_stack_init_valid_on_current_logical_core = lfds700_stack_init_valid_on_current_logical_core
lfds700_stack_cleanup = lfds700_stack_cleanup
lfds700_stack_push = lfds700_stack_push
lfds700_stack_pop = lfds700_stack_pop
lfds700_stack_query = lfds700_stack_query

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 2012
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "liblfds700", "liblfds700.vcxproj", "{1E5D7D09-94F2-455D-AE5E-6C7F4C96BCE0}"
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
{1E5D7D09-94F2-455D-AE5E-6C7F4C96BCE0}.Debug DLL|Win32.ActiveCfg = Debug DLL|Win32
{1E5D7D09-94F2-455D-AE5E-6C7F4C96BCE0}.Debug DLL|Win32.Build.0 = Debug DLL|Win32
{1E5D7D09-94F2-455D-AE5E-6C7F4C96BCE0}.Debug DLL|Win32.Deploy.0 = Debug DLL|Win32
{1E5D7D09-94F2-455D-AE5E-6C7F4C96BCE0}.Debug DLL|x64.ActiveCfg = Debug DLL|x64
{1E5D7D09-94F2-455D-AE5E-6C7F4C96BCE0}.Debug DLL|x64.Build.0 = Debug DLL|x64
{1E5D7D09-94F2-455D-AE5E-6C7F4C96BCE0}.Debug DLL|x64.Deploy.0 = Debug DLL|x64
{1E5D7D09-94F2-455D-AE5E-6C7F4C96BCE0}.Debug LIB|Win32.ActiveCfg = Debug LIB|Win32
{1E5D7D09-94F2-455D-AE5E-6C7F4C96BCE0}.Debug LIB|Win32.Build.0 = Debug LIB|Win32
{1E5D7D09-94F2-455D-AE5E-6C7F4C96BCE0}.Debug LIB|Win32.Deploy.0 = Debug LIB|Win32
{1E5D7D09-94F2-455D-AE5E-6C7F4C96BCE0}.Debug LIB|x64.ActiveCfg = Debug LIB|x64
{1E5D7D09-94F2-455D-AE5E-6C7F4C96BCE0}.Debug LIB|x64.Build.0 = Debug LIB|x64
{1E5D7D09-94F2-455D-AE5E-6C7F4C96BCE0}.Debug LIB|x64.Deploy.0 = Debug LIB|x64
{1E5D7D09-94F2-455D-AE5E-6C7F4C96BCE0}.Release DLL|Win32.ActiveCfg = Release DLL|Win32
{1E5D7D09-94F2-455D-AE5E-6C7F4C96BCE0}.Release DLL|Win32.Build.0 = Release DLL|Win32
{1E5D7D09-94F2-455D-AE5E-6C7F4C96BCE0}.Release DLL|Win32.Deploy.0 = Release DLL|Win32
{1E5D7D09-94F2-455D-AE5E-6C7F4C96BCE0}.Release DLL|x64.ActiveCfg = Release DLL|x64
{1E5D7D09-94F2-455D-AE5E-6C7F4C96BCE0}.Release DLL|x64.Build.0 = Release DLL|x64
{1E5D7D09-94F2-455D-AE5E-6C7F4C96BCE0}.Release DLL|x64.Deploy.0 = Release DLL|x64
{1E5D7D09-94F2-455D-AE5E-6C7F4C96BCE0}.Release LIB|Win32.ActiveCfg = Release LIB|Win32
{1E5D7D09-94F2-455D-AE5E-6C7F4C96BCE0}.Release LIB|Win32.Build.0 = Release LIB|Win32
{1E5D7D09-94F2-455D-AE5E-6C7F4C96BCE0}.Release LIB|Win32.Deploy.0 = Release LIB|Win32
{1E5D7D09-94F2-455D-AE5E-6C7F4C96BCE0}.Release LIB|x64.ActiveCfg = Release LIB|x64
{1E5D7D09-94F2-455D-AE5E-6C7F4C96BCE0}.Release LIB|x64.Build.0 = Release LIB|x64
{1E5D7D09-94F2-455D-AE5E-6C7F4C96BCE0}.Release LIB|x64.Deploy.0 = Release LIB|x64
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
EndGlobal
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug DLL|Win32">
<Configuration>Debug DLL</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Debug DLL|x64">
<Configuration>Debug DLL</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Debug LIB|Win32">
<Configuration>Debug LIB</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Debug LIB|x64">
<Configuration>Debug LIB</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release DLL|Win32">
<Configuration>Release DLL</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release DLL|x64">
<Configuration>Release DLL</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release LIB|Win32">
<Configuration>Release LIB</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release LIB|x64">
<Configuration>Release LIB</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<ProjectGuid>{1E5D7D09-94F2-455D-AE5E-6C7F4C96BCE0}</ProjectGuid>
<Keyword>Win32Proj</Keyword>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug LIB|Win32'" Label="Configuration">
<ConfigurationType>StaticLibrary</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>WindowsKernelModeDriver8.0</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug DLL|Win32'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>WindowsKernelModeDriver8.0</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug LIB|x64'" Label="Configuration">
<ConfigurationType>StaticLibrary</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>WindowsKernelModeDriver8.0</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug DLL|x64'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>WindowsKernelModeDriver8.0</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release LIB|Win32'" Label="Configuration">
<ConfigurationType>StaticLibrary</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>WindowsKernelModeDriver8.0</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release DLL|Win32'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>WindowsKernelModeDriver8.0</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release LIB|x64'" Label="Configuration">
<ConfigurationType>StaticLibrary</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>WindowsKernelModeDriver8.0</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release DLL|x64'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>WindowsKernelModeDriver8.0</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug LIB|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug DLL|Win32'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug LIB|x64'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug DLL|x64'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release LIB|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release DLL|Win32'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release LIB|x64'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release DLL|x64'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug LIB|Win32'">
<LinkIncremental>true</LinkIncremental>
<OutDir>$(ProjectDir)..\..\bin\$(Platform) $(Configuration)\</OutDir>
<IntDir>$(ProjectDir)..\..\obj\$(Platform) $(Configuration)\</IntDir>
<IncludePath>$(ProjectDir);$(IncludePath);</IncludePath>
<LibraryPath>$(WDKContentRoot)lib\$(DDKSpec)\KM\$(DDKPlatform);$(LibraryPath);</LibraryPath>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug DLL|Win32'">
<LinkIncremental>
</LinkIncremental>
<OutDir>$(ProjectDir)..\..\bin\$(Platform) $(Configuration)\</OutDir>
<IntDir>$(ProjectDir)..\..\obj\$(Platform) $(Configuration)\</IntDir>
<IncludePath>$(ProjectDir);$(IncludePath);</IncludePath>
<LibraryPath>$(WDKContentRoot)lib\$(DDKSpec)\KM\$(DDKPlatform);$(LibraryPath);</LibraryPath>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug LIB|x64'">
<LinkIncremental>true</LinkIncremental>
<OutDir>$(ProjectDir)..\..\bin\$(Platform) $(Configuration)\</OutDir>
<IntDir>$(ProjectDir)..\..\obj\$(Platform) $(Configuration)\</IntDir>
<IncludePath>$(ProjectDir);$(IncludePath);</IncludePath>
<LibraryPath>$(WDKContentRoot)lib\$(DDKSpec)\KM\$(DDKPlatform);$(LibraryPath);</LibraryPath>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug DLL|x64'">
<LinkIncremental>
</LinkIncremental>
<OutDir>$(ProjectDir)..\..\bin\$(Platform) $(Configuration)\</OutDir>
<IntDir>$(ProjectDir)..\..\obj\$(Platform) $(Configuration)\</IntDir>
<IncludePath>$(ProjectDir);$(IncludePath);</IncludePath>
<LibraryPath>$(WDKContentRoot)lib\$(DDKSpec)\KM\$(DDKPlatform);$(LibraryPath);</LibraryPath>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release LIB|Win32'">
<LinkIncremental>true</LinkIncremental>
<OutDir>$(ProjectDir)..\..\bin\$(Platform) $(Configuration)\</OutDir>
<IntDir>$(ProjectDir)..\..\obj\$(Platform) $(Configuration)\</IntDir>
<IncludePath>$(ProjectDir);$(IncludePath);</IncludePath>
<LibraryPath>$(WDKContentRoot)lib\$(DDKSpec)\KM\$(DDKPlatform);$(LibraryPath);</LibraryPath>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release DLL|Win32'">
<LinkIncremental>
</LinkIncremental>
<OutDir>$(ProjectDir)..\..\bin\$(Platform) $(Configuration)\</OutDir>
<IntDir>$(ProjectDir)..\..\obj\$(Platform) $(Configuration)\</IntDir>
<IncludePath>$(ProjectDir);$(IncludePath);</IncludePath>
<LibraryPath>$(WDKContentRoot)lib\$(DDKSpec)\KM\$(DDKPlatform);$(LibraryPath);</LibraryPath>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release LIB|x64'">
<LinkIncremental>true</LinkIncremental>
<OutDir>$(ProjectDir)..\..\bin\$(Platform) $(Configuration)\</OutDir>
<IntDir>$(ProjectDir)..\..\obj\$(Platform) $(Configuration)\</IntDir>
<IncludePath>$(ProjectDir);$(IncludePath);</IncludePath>
<LibraryPath>$(WDKContentRoot)lib\$(DDKSpec)\KM\$(DDKPlatform);$(LibraryPath);</LibraryPath>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release DLL|x64'">
<LinkIncremental>
</LinkIncremental>
<OutDir>$(ProjectDir)..\..\bin\$(Platform) $(Configuration)\</OutDir>
<IntDir>$(ProjectDir)..\..\obj\$(Platform) $(Configuration)\</IntDir>
<IncludePath>$(ProjectDir);$(IncludePath);</IncludePath>
<LibraryPath>$(WDKContentRoot)lib\$(DDKSpec)\KM\$(DDKPlatform);$(LibraryPath);</LibraryPath>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug LIB|Win32'">
<ClCompile>
<PreprocessorDefinitions>WIN32;_DEBUG;_LIB;LFDS700_BUILD_TYPE_STRING="Debug";%(PreprocessorDefinitions)</PreprocessorDefinitions>
<AdditionalIncludeDirectories>
</AdditionalIncludeDirectories>
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
<WarningLevel>Level4</WarningLevel>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
<Optimization>Disabled</Optimization>
<CompileAsManaged>false</CompileAsManaged>
<CompileAsWinRT>false</CompileAsWinRT>
<TreatWarningAsError>true</TreatWarningAsError>
<MultiProcessorCompilation>true</MultiProcessorCompilation>
<IntrinsicFunctions>true</IntrinsicFunctions>
<StringPooling>true</StringPooling>
<ExceptionHandling>false</ExceptionHandling>
<SmallerTypeCheck>true</SmallerTypeCheck>
<FunctionLevelLinking>
</FunctionLevelLinking>
<EnableParallelCodeGeneration>
</EnableParallelCodeGeneration>
<EnableEnhancedInstructionSet>
</EnableEnhancedInstructionSet>
<FloatingPointExceptions>true</FloatingPointExceptions>
<CreateHotpatchableImage>false</CreateHotpatchableImage>
<RuntimeTypeInfo>false</RuntimeTypeInfo>
<OpenMPSupport>false</OpenMPSupport>
<BrowseInformation>true</BrowseInformation>
<CompileAs>CompileAsC</CompileAs>
<UseFullPaths>true</UseFullPaths>
<ErrorReporting>None</ErrorReporting>
<SDLCheck>true</SDLCheck>
<MinimalRebuild>false</MinimalRebuild>
<DisableSpecificWarnings>4068</DisableSpecificWarnings>
<AdditionalOptions>/kernel %(AdditionalOptions)</AdditionalOptions>
</ClCompile>
<Link>
<TargetMachine>MachineX86</TargetMachine>
<GenerateDebugInformation>true</GenerateDebugInformation>
<SubSystem>Windows</SubSystem>
</Link>
<Lib>
<TreatLibWarningAsErrors>true</TreatLibWarningAsErrors>
</Lib>
<Lib>
<TargetMachine>MachineX86</TargetMachine>
</Lib>
<Lib>
<SubSystem>Native</SubSystem>
</Lib>
<Lib>
<LinkTimeCodeGeneration>false</LinkTimeCodeGeneration>
<IgnoreAllDefaultLibraries>true</IgnoreAllDefaultLibraries>
</Lib>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug DLL|Win32'">
<ClCompile>
<PreprocessorDefinitions>WIN32;_DEBUG;_LIB;LFDS700_BUILD_TYPE_STRING="Debug";%(PreprocessorDefinitions)</PreprocessorDefinitions>
<AdditionalIncludeDirectories>
</AdditionalIncludeDirectories>
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
<WarningLevel>Level4</WarningLevel>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
<Optimization>Disabled</Optimization>
<CompileAsManaged>false</CompileAsManaged>
<CompileAsWinRT>false</CompileAsWinRT>
<TreatWarningAsError>true</TreatWarningAsError>
<MultiProcessorCompilation>true</MultiProcessorCompilation>
<IntrinsicFunctions>true</IntrinsicFunctions>
<StringPooling>true</StringPooling>
<ExceptionHandling>false</ExceptionHandling>
<SmallerTypeCheck>true</SmallerTypeCheck>
<FunctionLevelLinking>
</FunctionLevelLinking>
<EnableParallelCodeGeneration>
</EnableParallelCodeGeneration>
<EnableEnhancedInstructionSet>
</EnableEnhancedInstructionSet>
<FloatingPointExceptions>true</FloatingPointExceptions>
<CreateHotpatchableImage>false</CreateHotpatchableImage>
<RuntimeTypeInfo>false</RuntimeTypeInfo>
<OpenMPSupport>false</OpenMPSupport>
<BrowseInformation>true</BrowseInformation>
<CompileAs>CompileAsC</CompileAs>
<UseFullPaths>true</UseFullPaths>
<ErrorReporting>None</ErrorReporting>
<SDLCheck>true</SDLCheck>
<MinimalRebuild>false</MinimalRebuild>
<DisableSpecificWarnings>4068</DisableSpecificWarnings>
<AdditionalOptions>/kernel %(AdditionalOptions)</AdditionalOptions>
</ClCompile>
<Link>
<TargetMachine>MachineX86</TargetMachine>
<GenerateDebugInformation>true</GenerateDebugInformation>
<SubSystem>Native</SubSystem>
<AdditionalDependencies>kernel32.lib;msvcrtd.lib</AdditionalDependencies>
<LinkStatus>
</LinkStatus>
<TreatLinkerWarningAsErrors>true</TreatLinkerWarningAsErrors>
<IgnoreAllDefaultLibraries>true</IgnoreAllDefaultLibraries>
<ModuleDefinitionFile>liblfds700.def</ModuleDefinitionFile>
<MapExports>true</MapExports>
<LinkErrorReporting>NoErrorReport</LinkErrorReporting>
<GenerateMapFile>true</GenerateMapFile>
<Driver>WDM</Driver>
</Link>
<Lib>
<TreatLibWarningAsErrors>true</TreatLibWarningAsErrors>
</Lib>
<Lib>
<TargetMachine>MachineX86</TargetMachine>
</Lib>
<Lib>
<SubSystem>Console</SubSystem>
</Lib>
<Lib>
<LinkTimeCodeGeneration>false</LinkTimeCodeGeneration>
<IgnoreAllDefaultLibraries>true</IgnoreAllDefaultLibraries>
</Lib>
<ProjectReference>
<LinkLibraryDependencies>true</LinkLibraryDependencies>
</ProjectReference>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug LIB|x64'">
<ClCompile>
<PreprocessorDefinitions>WIN32;_DEBUG;_LIB;LFDS700_BUILD_TYPE_STRING="Debug";%(PreprocessorDefinitions)</PreprocessorDefinitions>
<AdditionalIncludeDirectories>
</AdditionalIncludeDirectories>
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
<WarningLevel>Level4</WarningLevel>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
<Optimization>Disabled</Optimization>
<CompileAsManaged>false</CompileAsManaged>
<CompileAsWinRT>false</CompileAsWinRT>
<TreatWarningAsError>true</TreatWarningAsError>
<MultiProcessorCompilation>true</MultiProcessorCompilation>
<IntrinsicFunctions>true</IntrinsicFunctions>
<StringPooling>true</StringPooling>
<ExceptionHandling>false</ExceptionHandling>
<SmallerTypeCheck>true</SmallerTypeCheck>
<FunctionLevelLinking>
</FunctionLevelLinking>
<EnableParallelCodeGeneration>
</EnableParallelCodeGeneration>
<EnableEnhancedInstructionSet>
</EnableEnhancedInstructionSet>
<FloatingPointExceptions>true</FloatingPointExceptions>
<CreateHotpatchableImage>false</CreateHotpatchableImage>
<RuntimeTypeInfo>false</RuntimeTypeInfo>
<OpenMPSupport>false</OpenMPSupport>
<BrowseInformation>true</BrowseInformation>
<CompileAs>CompileAsC</CompileAs>
<UseFullPaths>true</UseFullPaths>
<ErrorReporting>None</ErrorReporting>
<SDLCheck>true</SDLCheck>
<MinimalRebuild>false</MinimalRebuild>
<DisableSpecificWarnings>4068</DisableSpecificWarnings>
<OmitFramePointers>false</OmitFramePointers>
<AdditionalOptions>/kernel %(AdditionalOptions)</AdditionalOptions>
</ClCompile>
<Link>
<GenerateDebugInformation>true</GenerateDebugInformation>
<SubSystem>Windows</SubSystem>
</Link>
<Lib>
<TreatLibWarningAsErrors>true</TreatLibWarningAsErrors>
</Lib>
<Lib>
<TargetMachine>MachineX64</TargetMachine>
</Lib>
<Lib>
<SubSystem>Native</SubSystem>
</Lib>
<Lib>
<LinkTimeCodeGeneration>false</LinkTimeCodeGeneration>
<IgnoreAllDefaultLibraries>true</IgnoreAllDefaultLibraries>
</Lib>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug DLL|x64'">
<ClCompile>
<PreprocessorDefinitions>WIN32;_DEBUG;_LIB;LFDS700_BUILD_TYPE_STRING="Debug";%(PreprocessorDefinitions)</PreprocessorDefinitions>
<AdditionalIncludeDirectories>
</AdditionalIncludeDirectories>
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
<WarningLevel>Level4</WarningLevel>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
<Optimization>Disabled</Optimization>
<CompileAsManaged>false</CompileAsManaged>
<CompileAsWinRT>false</CompileAsWinRT>
<TreatWarningAsError>true</TreatWarningAsError>
<MultiProcessorCompilation>true</MultiProcessorCompilation>
<IntrinsicFunctions>true</IntrinsicFunctions>
<StringPooling>true</StringPooling>
<ExceptionHandling>false</ExceptionHandling>
<SmallerTypeCheck>true</SmallerTypeCheck>
<FunctionLevelLinking>
</FunctionLevelLinking>
<EnableParallelCodeGeneration>
</EnableParallelCodeGeneration>
<EnableEnhancedInstructionSet>
</EnableEnhancedInstructionSet>
<FloatingPointExceptions>true</FloatingPointExceptions>
<CreateHotpatchableImage>false</CreateHotpatchableImage>
<RuntimeTypeInfo>false</RuntimeTypeInfo>
<OpenMPSupport>false</OpenMPSupport>
<BrowseInformation>true</BrowseInformation>
<CompileAs>CompileAsC</CompileAs>
<UseFullPaths>true</UseFullPaths>
<ErrorReporting>None</ErrorReporting>
<SDLCheck>true</SDLCheck>
<MinimalRebuild>false</MinimalRebuild>
<DisableSpecificWarnings>4068</DisableSpecificWarnings>
<OmitFramePointers>false</OmitFramePointers>
<AdditionalOptions>/kernel %(AdditionalOptions)</AdditionalOptions>
</ClCompile>
<Link>
<GenerateDebugInformation>true</GenerateDebugInformation>
<SubSystem>Native</SubSystem>
<TreatLinkerWarningAsErrors>true</TreatLinkerWarningAsErrors>
<IgnoreAllDefaultLibraries>true</IgnoreAllDefaultLibraries>
<ModuleDefinitionFile>liblfds700.def</ModuleDefinitionFile>
<MapExports>true</MapExports>
<OptimizeReferences>false</OptimizeReferences>
<LinkErrorReporting>NoErrorReport</LinkErrorReporting>
<AdditionalDependencies>kernel32.lib;msvcrtd.lib</AdditionalDependencies>
<GenerateMapFile>true</GenerateMapFile>
<Driver>WDM</Driver>
</Link>
<Lib>
<TreatLibWarningAsErrors>true</TreatLibWarningAsErrors>
</Lib>
<Lib>
<TargetMachine>MachineX64</TargetMachine>
</Lib>
<Lib>
<SubSystem>Console</SubSystem>
</Lib>
<Lib>
<LinkTimeCodeGeneration>false</LinkTimeCodeGeneration>
<IgnoreAllDefaultLibraries>true</IgnoreAllDefaultLibraries>
</Lib>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release LIB|Win32'">
<ClCompile>
<PreprocessorDefinitions>WIN32;NDEBUG;_LIB;LFDS700_BUILD_TYPE_STRING="Release";%(PreprocessorDefinitions)</PreprocessorDefinitions>
<AdditionalIncludeDirectories>
</AdditionalIncludeDirectories>
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
<WarningLevel>Level4</WarningLevel>
<DebugInformationFormat>None</DebugInformationFormat>
<CompileAsManaged>false</CompileAsManaged>
<CompileAsWinRT>false</CompileAsWinRT>
<TreatWarningAsError>true</TreatWarningAsError>
<MultiProcessorCompilation>true</MultiProcessorCompilation>
<InlineFunctionExpansion>AnySuitable</InlineFunctionExpansion>
<IntrinsicFunctions>true</IntrinsicFunctions>
<FavorSizeOrSpeed>Speed</FavorSizeOrSpeed>
<StringPooling>true</StringPooling>
<ExceptionHandling>false</ExceptionHandling>
<BufferSecurityCheck>false</BufferSecurityCheck>
<FunctionLevelLinking>
</FunctionLevelLinking>
<EnableParallelCodeGeneration>
</EnableParallelCodeGeneration>
<EnableEnhancedInstructionSet>
</EnableEnhancedInstructionSet>
<FloatingPointExceptions>false</FloatingPointExceptions>
<CreateHotpatchableImage>
</CreateHotpatchableImage>
<RuntimeTypeInfo>false</RuntimeTypeInfo>
<OpenMPSupport>false</OpenMPSupport>
<CompileAs>CompileAsC</CompileAs>
<UseFullPaths>true</UseFullPaths>
<ErrorReporting>None</ErrorReporting>
<OmitFramePointers>true</OmitFramePointers>
<DisableSpecificWarnings>4068</DisableSpecificWarnings>
<EnableFiberSafeOptimizations>true</EnableFiberSafeOptimizations>
<AdditionalOptions>/kernel %(AdditionalOptions)</AdditionalOptions>
</ClCompile>
<Link>
<TargetMachine>MachineX86</TargetMachine>
<GenerateDebugInformation>true</GenerateDebugInformation>
<SubSystem>Windows</SubSystem>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
</Link>
<Lib>
<TreatLibWarningAsErrors>true</TreatLibWarningAsErrors>
</Lib>
<Lib>
<TargetMachine>MachineX86</TargetMachine>
</Lib>
<Lib>
<SubSystem>Native</SubSystem>
<IgnoreAllDefaultLibraries>true</IgnoreAllDefaultLibraries>
</Lib>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release DLL|Win32'">
<ClCompile>
<PreprocessorDefinitions>WIN32;NDEBUG;_LIB;LFDS700_BUILD_TYPE_STRING="Release";%(PreprocessorDefinitions)</PreprocessorDefinitions>
<AdditionalIncludeDirectories>
</AdditionalIncludeDirectories>
<RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
<WarningLevel>Level4</WarningLevel>
<DebugInformationFormat>None</DebugInformationFormat>
<CompileAsManaged>false</CompileAsManaged>
<CompileAsWinRT>false</CompileAsWinRT>
<TreatWarningAsError>true</TreatWarningAsError>
<MultiProcessorCompilation>true</MultiProcessorCompilation>
<InlineFunctionExpansion>AnySuitable</InlineFunctionExpansion>
<IntrinsicFunctions>true</IntrinsicFunctions>
<FavorSizeOrSpeed>Speed</FavorSizeOrSpeed>
<StringPooling>true</StringPooling>
<ExceptionHandling>false</ExceptionHandling>
<BufferSecurityCheck>false</BufferSecurityCheck>
<FunctionLevelLinking>
</FunctionLevelLinking>
<EnableParallelCodeGeneration>
</EnableParallelCodeGeneration>
<EnableEnhancedInstructionSet>
</EnableEnhancedInstructionSet>
<FloatingPointExceptions>false</FloatingPointExceptions>
<CreateHotpatchableImage>
</CreateHotpatchableImage>
<RuntimeTypeInfo>false</RuntimeTypeInfo>
<OpenMPSupport>false</OpenMPSupport>
<CompileAs>CompileAsC</CompileAs>
<UseFullPaths>true</UseFullPaths>
<ErrorReporting>None</ErrorReporting>
<OmitFramePointers>true</OmitFramePointers>
<DisableSpecificWarnings>4068</DisableSpecificWarnings>
<EnableFiberSafeOptimizations>true</EnableFiberSafeOptimizations>
<AdditionalOptions>/kernel %(AdditionalOptions)</AdditionalOptions>
</ClCompile>
<Link>
<TargetMachine>MachineX86</TargetMachine>
<GenerateDebugInformation>false</GenerateDebugInformation>
<SubSystem>Native</SubSystem>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<AdditionalDependencies>kernel32.lib;msvcrt.lib</AdditionalDependencies>
<LinkStatus>
</LinkStatus>
<TreatLinkerWarningAsErrors>true</TreatLinkerWarningAsErrors>
<IgnoreAllDefaultLibraries>true</IgnoreAllDefaultLibraries>
<ModuleDefinitionFile>liblfds700.def</ModuleDefinitionFile>
<LinkErrorReporting>NoErrorReport</LinkErrorReporting>
<Driver>WDM</Driver>
</Link>
<Lib>
<TreatLibWarningAsErrors>true</TreatLibWarningAsErrors>
</Lib>
<Lib>
<TargetMachine>MachineX86</TargetMachine>
</Lib>
<Lib>
<SubSystem>Console</SubSystem>
<IgnoreAllDefaultLibraries>true</IgnoreAllDefaultLibraries>
</Lib>
<ProjectReference>
<LinkLibraryDependencies>true</LinkLibraryDependencies>
</ProjectReference>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release LIB|x64'">
<ClCompile>
<PreprocessorDefinitions>WIN32;NDEBUG;_LIB;LFDS700_BUILD_TYPE_STRING="Release";%(PreprocessorDefinitions)</PreprocessorDefinitions>
<AdditionalIncludeDirectories>
</AdditionalIncludeDirectories>
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
<WarningLevel>Level4</WarningLevel>
<DebugInformationFormat>None</DebugInformationFormat>
<CompileAsManaged>false</CompileAsManaged>
<CompileAsWinRT>false</CompileAsWinRT>
<TreatWarningAsError>true</TreatWarningAsError>
<MultiProcessorCompilation>true</MultiProcessorCompilation>
<InlineFunctionExpansion>AnySuitable</InlineFunctionExpansion>
<IntrinsicFunctions>true</IntrinsicFunctions>
<FavorSizeOrSpeed>Speed</FavorSizeOrSpeed>
<StringPooling>true</StringPooling>
<ExceptionHandling>false</ExceptionHandling>
<BufferSecurityCheck>false</BufferSecurityCheck>
<FunctionLevelLinking>
</FunctionLevelLinking>
<EnableParallelCodeGeneration>
</EnableParallelCodeGeneration>
<EnableEnhancedInstructionSet>
</EnableEnhancedInstructionSet>
<FloatingPointExceptions>false</FloatingPointExceptions>
<CreateHotpatchableImage>
</CreateHotpatchableImage>
<RuntimeTypeInfo>false</RuntimeTypeInfo>
<OpenMPSupport>false</OpenMPSupport>
<CompileAs>CompileAsC</CompileAs>
<UseFullPaths>true</UseFullPaths>
<ErrorReporting>None</ErrorReporting>
<OmitFramePointers>true</OmitFramePointers>
<DisableSpecificWarnings>4068</DisableSpecificWarnings>
<EnableFiberSafeOptimizations>true</EnableFiberSafeOptimizations>
<AdditionalOptions>/kernel %(AdditionalOptions)</AdditionalOptions>
</ClCompile>
<Link>
<GenerateDebugInformation>true</GenerateDebugInformation>
<SubSystem>Windows</SubSystem>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
</Link>
<Lib>
<TreatLibWarningAsErrors>true</TreatLibWarningAsErrors>
</Lib>
<Lib>
<TargetMachine>MachineX64</TargetMachine>
</Lib>
<Lib>
<SubSystem>Native</SubSystem>
<IgnoreAllDefaultLibraries>true</IgnoreAllDefaultLibraries>
</Lib>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release DLL|x64'">
<ClCompile>
<PreprocessorDefinitions>WIN32;NDEBUG;_LIB;LFDS700_BUILD_TYPE_STRING="Release";%(PreprocessorDefinitions)</PreprocessorDefinitions>
<AdditionalIncludeDirectories>
</AdditionalIncludeDirectories>
<RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
<WarningLevel>Level4</WarningLevel>
<DebugInformationFormat>None</DebugInformationFormat>
<CompileAsManaged>false</CompileAsManaged>
<CompileAsWinRT>false</CompileAsWinRT>
<TreatWarningAsError>true</TreatWarningAsError>
<MultiProcessorCompilation>true</MultiProcessorCompilation>
<InlineFunctionExpansion>AnySuitable</InlineFunctionExpansion>
<IntrinsicFunctions>true</IntrinsicFunctions>
<FavorSizeOrSpeed>Speed</FavorSizeOrSpeed>
<StringPooling>true</StringPooling>
<ExceptionHandling>false</ExceptionHandling>
<BufferSecurityCheck>false</BufferSecurityCheck>
<FunctionLevelLinking>
</FunctionLevelLinking>
<EnableParallelCodeGeneration>
</EnableParallelCodeGeneration>
<EnableEnhancedInstructionSet>
</EnableEnhancedInstructionSet>
<FloatingPointExceptions>false</FloatingPointExceptions>
<CreateHotpatchableImage>
</CreateHotpatchableImage>
<RuntimeTypeInfo>false</RuntimeTypeInfo>
<OpenMPSupport>false</OpenMPSupport>
<CompileAs>CompileAsC</CompileAs>
<UseFullPaths>true</UseFullPaths>
<ErrorReporting>None</ErrorReporting>
<OmitFramePointers>true</OmitFramePointers>
<DisableSpecificWarnings>4068</DisableSpecificWarnings>
<EnableFiberSafeOptimizations>true</EnableFiberSafeOptimizations>
<AdditionalOptions>/kernel %(AdditionalOptions)</AdditionalOptions>
</ClCompile>
<Link>
<GenerateDebugInformation>false</GenerateDebugInformation>
<SubSystem>Native</SubSystem>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<TreatLinkerWarningAsErrors>true</TreatLinkerWarningAsErrors>
<IgnoreAllDefaultLibraries>true</IgnoreAllDefaultLibraries>
<ModuleDefinitionFile>liblfds700.def</ModuleDefinitionFile>
<LinkErrorReporting>NoErrorReport</LinkErrorReporting>
<AdditionalDependencies>kernel32.lib;msvcrt.lib</AdditionalDependencies>
<Driver>WDM</Driver>
</Link>
<Lib>
<TreatLibWarningAsErrors>true</TreatLibWarningAsErrors>
</Lib>
<Lib>
<TargetMachine>MachineX64</TargetMachine>
</Lib>
<Lib>
<SubSystem>Console</SubSystem>
<IgnoreAllDefaultLibraries>true</IgnoreAllDefaultLibraries>
</Lib>
</ItemDefinitionGroup>
<ItemGroup>
<ClInclude Include="..\..\inc\liblfds700.h" />
<ClInclude Include="..\..\inc\liblfds700\lfds700_btree_addonly_unbalanced.h" />
<ClInclude Include="..\..\inc\liblfds700\lfds700_freelist.h" />
<ClInclude Include="..\..\inc\liblfds700\lfds700_hash_addonly.h" />
<ClInclude Include="..\..\inc\liblfds700\lfds700_list_addonly_ordered_singlylinked.h" />
<ClInclude Include="..\..\inc\liblfds700\lfds700_list_addonly_singlylinked_unordered.h" />
<ClInclude Include="..\..\inc\liblfds700\lfds700_misc.h" />
<ClInclude Include="..\..\inc\liblfds700\lfds700_porting_abstraction_layer_compiler.h" />
<ClInclude Include="..\..\inc\liblfds700\lfds700_porting_abstraction_layer_operating_system.h" />
<ClInclude Include="..\..\inc\liblfds700\lfds700_porting_abstraction_layer_processor.h" />
<ClInclude Include="..\..\inc\liblfds700\lfds700_queue.h" />
<ClInclude Include="..\..\inc\liblfds700\lfds700_queue_bounded_singleconsumer_singleproducer.h" />
<ClInclude Include="..\..\inc\liblfds700\lfds700_ringbuffer.h" />
<ClInclude Include="..\..\inc\liblfds700\lfds700_stack.h" />
<ClInclude Include="..\..\src\lfds700_btree_addonly_unbalanced\lfds700_btree_addonly_unbalanced_internal.h" />
<ClInclude Include="..\..\src\lfds700_freelist\lfds700_freelist_internal.h" />
<ClInclude Include="..\..\src\lfds700_hash_addonly\lfds700_hash_addonly_internal.h" />
<ClInclude Include="..\..\src\lfds700_list_addonly_ordered_singlylinked\lfds700_list_addonly_ordered_singlylinked_internal.h" />
<ClInclude Include="..\..\src\lfds700_list_addonly_singlylinked_unordered\lfds700_list_addonly_singlylinked_unordered_internal.h" />
<ClInclude Include="..\..\src\lfds700_misc\lfds700_misc_internal.h" />
<ClInclude Include="..\..\src\lfds700_queue\lfds700_queue_internal.h" />
<ClInclude Include="..\..\src\lfds700_queue_bounded_singleconsumer_singleproducer\lfds700_queue_bounded_singleconsumer_singleproducer_internal.h" />
<ClInclude Include="..\..\src\lfds700_ringbuffer\lfds700_ringbuffer_internal.h" />
<ClInclude Include="..\..\src\lfds700_stack\lfds700_stack_internal.h" />
</ItemGroup>
<ItemGroup>
<ClCompile Include="..\..\src\lfds700_btree_addonly_unbalanced\lfds700_btree_addonly_unbalanced_cleanup.c" />
<ClCompile Include="..\..\src\lfds700_btree_addonly_unbalanced\lfds700_btree_addonly_unbalanced_get.c" />
<ClCompile Include="..\..\src\lfds700_btree_addonly_unbalanced\lfds700_btree_addonly_unbalanced_init.c" />
<ClCompile Include="..\..\src\lfds700_btree_addonly_unbalanced\lfds700_btree_addonly_unbalanced_insert.c" />
<ClCompile Include="..\..\src\lfds700_btree_addonly_unbalanced\lfds700_btree_addonly_unbalanced_query.c" />
<ClCompile Include="..\..\src\lfds700_freelist\lfds700_freelist_cleanup.c" />
<ClCompile Include="..\..\src\lfds700_freelist\lfds700_freelist_init.c" />
<ClCompile Include="..\..\src\lfds700_freelist\lfds700_freelist_pop.c" />
<ClCompile Include="..\..\src\lfds700_freelist\lfds700_freelist_push.c" />
<ClCompile Include="..\..\src\lfds700_freelist\lfds700_freelist_query.c" />
<ClCompile Include="..\..\src\lfds700_hash_addonly\lfds700_hash_addonly_cleanup.c" />
<ClCompile Include="..\..\src\lfds700_hash_addonly\lfds700_hash_addonly_get.c" />
<ClCompile Include="..\..\src\lfds700_hash_addonly\lfds700_hash_addonly_init.c" />
<ClCompile Include="..\..\src\lfds700_hash_addonly\lfds700_hash_addonly_insert.c" />
<ClCompile Include="..\..\src\lfds700_hash_addonly\lfds700_hash_addonly_iterate.c" />
<ClCompile Include="..\..\src\lfds700_hash_addonly\lfds700_hash_addonly_query.c" />
<ClCompile Include="..\..\src\lfds700_list_addonly_ordered_singlylinked\lfds700_list_addonly_ordered_singlylinked_cleanup.c" />
<ClCompile Include="..\..\src\lfds700_list_addonly_ordered_singlylinked\lfds700_list_addonly_ordered_singlylinked_get.c" />
<ClCompile Include="..\..\src\lfds700_list_addonly_ordered_singlylinked\lfds700_list_addonly_ordered_singlylinked_init.c" />
<ClCompile Include="..\..\src\lfds700_list_addonly_ordered_singlylinked\lfds700_list_addonly_ordered_singlylinked_insert.c" />
<ClCompile Include="..\..\src\lfds700_list_addonly_ordered_singlylinked\lfds700_list_addonly_ordered_singlylinked_query.c" />
<ClCompile Include="..\..\src\lfds700_list_addonly_singlylinked_unordered\lfds700_list_addonly_singlylinked_unordered_cleanup.c" />
<ClCompile Include="..\..\src\lfds700_list_addonly_singlylinked_unordered\lfds700_list_addonly_singlylinked_unordered_get.c" />
<ClCompile Include="..\..\src\lfds700_list_addonly_singlylinked_unordered\lfds700_list_addonly_singlylinked_unordered_init.c" />
<ClCompile Include="..\..\src\lfds700_list_addonly_singlylinked_unordered\lfds700_list_addonly_singlylinked_unordered_insert.c" />
<ClCompile Include="..\..\src\lfds700_list_addonly_singlylinked_unordered\lfds700_list_addonly_singlylinked_unordered_query.c" />
<ClCompile Include="..\..\src\lfds700_misc\lfds700_misc_cleanup.c" />
<ClCompile Include="..\..\src\lfds700_misc\lfds700_misc_globals.c" />
<ClCompile Include="..\..\src\lfds700_misc\lfds700_misc_init.c" />
<ClCompile Include="..\..\src\lfds700_misc\lfds700_misc_prng.c" />
<ClCompile Include="..\..\src\lfds700_misc\lfds700_misc_query.c" />
<ClCompile Include="..\..\src\lfds700_queue\lfds700_queue_cleanup.c" />
<ClCompile Include="..\..\src\lfds700_queue\lfds700_queue_dequeue.c" />
<ClCompile Include="..\..\src\lfds700_queue\lfds700_queue_enqueue.c" />
<ClCompile Include="..\..\src\lfds700_queue\lfds700_queue_init.c" />
<ClCompile Include="..\..\src\lfds700_queue\lfds700_queue_query.c" />
<ClCompile Include="..\..\src\lfds700_queue_bounded_singleconsumer_singleproducer\lfds700_queue_bounded_singleconsumer_singleproducer_cleanup.c" />
<ClCompile Include="..\..\src\lfds700_queue_bounded_singleconsumer_singleproducer\lfds700_queue_bounded_singleconsumer_singleproducer_dequeue.c" />
<ClCompile Include="..\..\src\lfds700_queue_bounded_singleconsumer_singleproducer\lfds700_queue_bounded_singleconsumer_singleproducer_enqueue.c" />
<ClCompile Include="..\..\src\lfds700_queue_bounded_singleconsumer_singleproducer\lfds700_queue_bounded_singleconsumer_singleproducer_init.c" />
<ClCompile Include="..\..\src\lfds700_queue_bounded_singleconsumer_singleproducer\lfds700_queue_bounded_singleconsumer_singleproducer_query.c" />
<ClCompile Include="..\..\src\lfds700_ringbuffer\lfds700_ringbuffer_cleanup.c" />
<ClCompile Include="..\..\src\lfds700_ringbuffer\lfds700_ringbuffer_init.c" />
<ClCompile Include="..\..\src\lfds700_ringbuffer\lfds700_ringbuffer_query.c" />
<ClCompile Include="..\..\src\lfds700_ringbuffer\lfds700_ringbuffer_read.c" />
<ClCompile Include="..\..\src\lfds700_ringbuffer\lfds700_ringbuffer_write.c" />
<ClCompile Include="..\..\src\lfds700_stack\lfds700_stack_cleanup.c" />
<ClCompile Include="..\..\src\lfds700_stack\lfds700_stack_init.c" />
<ClCompile Include="..\..\src\lfds700_stack\lfds700_stack_pop.c" />
<ClCompile Include="..\..\src\lfds700_stack\lfds700_stack_push.c" />
<ClCompile Include="..\..\src\lfds700_stack\lfds700_stack_query.c" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<Filter Include="Source Files">
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
<Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
</Filter>
<Filter Include="Header Files">
<UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
<Extensions>h;hpp;hxx;hm;inl;inc;xsd</Extensions>
</Filter>
<Filter Include="Resource Files">
<UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
<Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav</Extensions>
</Filter>
<Filter Include="Header Files\liblfds700">
<UniqueIdentifier>{258be429-7dac-4999-b995-753aa2f0c505}</UniqueIdentifier>
</Filter>
<Filter Include="Source Files\lfds700_freelist">
<UniqueIdentifier>{469abf8e-47d8-4678-bd66-7c7e65c5f52e}</UniqueIdentifier>
</Filter>
<Filter Include="Source Files\lfds700_ringbuffer">
<UniqueIdentifier>{62ee141b-2acb-4555-b016-7be20a57f2bf}</UniqueIdentifier>
</Filter>
<Filter Include="Source Files\lfds700_stack">
<UniqueIdentifier>{19c73b0f-25e0-4166-9093-427f1dfb4f70}</UniqueIdentifier>
</Filter>
<Filter Include="Source Files\lfds700_queue">
<UniqueIdentifier>{00eb30fe-e638-4c2b-8ca1-1f09c4a0ed45}</UniqueIdentifier>
</Filter>
<Filter Include="Source Files\lfds700_queue_bounded_singleconsumer_singleproducer">
<UniqueIdentifier>{6250c4d5-ac8e-4c28-93de-0954c5bed1cb}</UniqueIdentifier>
</Filter>
<Filter Include="Source Files\lfds700_misc">
<UniqueIdentifier>{400ae4e9-2281-4549-b918-59d1a27a2d07}</UniqueIdentifier>
</Filter>
<Filter Include="Source Files\lfds700_list_addonly_ordered_singlylinked">
<UniqueIdentifier>{c45194af-7b41-4c28-bc0e-1095ec347664}</UniqueIdentifier>
</Filter>
<Filter Include="Source Files\lfds700_list_addonly_singlylinked_unordered">
<UniqueIdentifier>{8b3cbb5c-7436-429f-9b72-bae1f4721746}</UniqueIdentifier>
</Filter>
<Filter Include="Source Files\lfds700_hash_addonly">
<UniqueIdentifier>{bcbadc74-1748-4696-aad7-7fdbe5614624}</UniqueIdentifier>
</Filter>
<Filter Include="Source Files\lfds700_btree_addonly_unbalanced">
<UniqueIdentifier>{0b1fafc3-817b-4c18-8eb1-121884e3a29b}</UniqueIdentifier>
</Filter>
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\..\inc\liblfds700.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\..\src\lfds700_freelist\lfds700_freelist_internal.h">
<Filter>Source Files\lfds700_freelist</Filter>
</ClInclude>
<ClInclude Include="..\..\src\lfds700_stack\lfds700_stack_internal.h">
<Filter>Source Files\lfds700_stack</Filter>
</ClInclude>
<ClInclude Include="..\..\src\lfds700_queue\lfds700_queue_internal.h">
<Filter>Source Files\lfds700_queue</Filter>
</ClInclude>
<ClInclude Include="..\..\inc\liblfds700\lfds700_btree_addonly_unbalanced.h">
<Filter>Header Files\liblfds700</Filter>
</ClInclude>
<ClInclude Include="..\..\inc\liblfds700\lfds700_freelist.h">
<Filter>Header Files\liblfds700</Filter>
</ClInclude>
<ClInclude Include="..\..\inc\liblfds700\lfds700_hash_addonly.h">
<Filter>Header Files\liblfds700</Filter>
</ClInclude>
<ClInclude Include="..\..\inc\liblfds700\lfds700_list_addonly_ordered_singlylinked.h">
<Filter>Header Files\liblfds700</Filter>
</ClInclude>
<ClInclude Include="..\..\inc\liblfds700\lfds700_list_addonly_singlylinked_unordered.h">
<Filter>Header Files\liblfds700</Filter>
</ClInclude>
<ClInclude Include="..\..\inc\liblfds700\lfds700_misc.h">
<Filter>Header Files\liblfds700</Filter>
</ClInclude>
<ClInclude Include="..\..\inc\liblfds700\lfds700_porting_abstraction_layer_compiler.h">
<Filter>Header Files\liblfds700</Filter>
</ClInclude>
<ClInclude Include="..\..\inc\liblfds700\lfds700_porting_abstraction_layer_operating_system.h">
<Filter>Header Files\liblfds700</Filter>
</ClInclude>
<ClInclude Include="..\..\inc\liblfds700\lfds700_porting_abstraction_layer_processor.h">
<Filter>Header Files\liblfds700</Filter>
</ClInclude>
<ClInclude Include="..\..\inc\liblfds700\lfds700_queue.h">
<Filter>Header Files\liblfds700</Filter>
</ClInclude>
<ClInclude Include="..\..\inc\liblfds700\lfds700_queue_bounded_singleconsumer_singleproducer.h">
<Filter>Header Files\liblfds700</Filter>
</ClInclude>
<ClInclude Include="..\..\inc\liblfds700\lfds700_ringbuffer.h">
<Filter>Header Files\liblfds700</Filter>
</ClInclude>
<ClInclude Include="..\..\inc\liblfds700\lfds700_stack.h">
<Filter>Header Files\liblfds700</Filter>
</ClInclude>
<ClInclude Include="..\..\src\lfds700_hash_addonly\lfds700_hash_addonly_internal.h">
<Filter>Source Files\lfds700_hash_addonly</Filter>
</ClInclude>
<ClInclude Include="..\..\src\lfds700_list_addonly_ordered_singlylinked\lfds700_list_addonly_ordered_singlylinked_internal.h">
<Filter>Source Files\lfds700_list_addonly_ordered_singlylinked</Filter>
</ClInclude>
<ClInclude Include="..\..\src\lfds700_btree_addonly_unbalanced\lfds700_btree_addonly_unbalanced_internal.h">
<Filter>Source Files\lfds700_btree_addonly_unbalanced</Filter>
</ClInclude>
<ClInclude Include="..\..\src\lfds700_misc\lfds700_misc_internal.h">
<Filter>Source Files\lfds700_misc</Filter>
</ClInclude>
<ClInclude Include="..\..\src\lfds700_queue_bounded_singleconsumer_singleproducer\lfds700_queue_bounded_singleconsumer_singleproducer_internal.h">
<Filter>Source Files\lfds700_queue_bounded_singleconsumer_singleproducer</Filter>
</ClInclude>
<ClInclude Include="..\..\src\lfds700_list_addonly_singlylinked_unordered\lfds700_list_addonly_singlylinked_unordered_internal.h">
<Filter>Source Files\lfds700_list_addonly_singlylinked_unordered</Filter>
</ClInclude>
<ClInclude Include="..\..\src\lfds700_ringbuffer\lfds700_ringbuffer_internal.h">
<Filter>Source Files\lfds700_ringbuffer</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ClCompile Include="..\..\src\lfds700_freelist\lfds700_freelist_cleanup.c">
<Filter>Source Files\lfds700_freelist</Filter>
</ClCompile>
<ClCompile Include="..\..\src\lfds700_freelist\lfds700_freelist_init.c">
<Filter>Source Files\lfds700_freelist</Filter>
</ClCompile>
<ClCompile Include="..\..\src\lfds700_freelist\lfds700_freelist_pop.c">
<Filter>Source Files\lfds700_freelist</Filter>
</ClCompile>
<ClCompile Include="..\..\src\lfds700_freelist\lfds700_freelist_push.c">
<Filter>Source Files\lfds700_freelist</Filter>
</ClCompile>
<ClCompile Include="..\..\src\lfds700_freelist\lfds700_freelist_query.c">
<Filter>Source Files\lfds700_freelist</Filter>
</ClCompile>
<ClCompile Include="..\..\src\lfds700_stack\lfds700_stack_cleanup.c">
<Filter>Source Files\lfds700_stack</Filter>
</ClCompile>
<ClCompile Include="..\..\src\lfds700_stack\lfds700_stack_init.c">
<Filter>Source Files\lfds700_stack</Filter>
</ClCompile>
<ClCompile Include="..\..\src\lfds700_stack\lfds700_stack_pop.c">
<Filter>Source Files\lfds700_stack</Filter>
</ClCompile>
<ClCompile Include="..\..\src\lfds700_stack\lfds700_stack_push.c">
<Filter>Source Files\lfds700_stack</Filter>
</ClCompile>
<ClCompile Include="..\..\src\lfds700_stack\lfds700_stack_query.c">
<Filter>Source Files\lfds700_stack</Filter>
</ClCompile>
<ClCompile Include="..\..\src\lfds700_queue\lfds700_queue_cleanup.c">
<Filter>Source Files\lfds700_queue</Filter>
</ClCompile>
<ClCompile Include="..\..\src\lfds700_queue\lfds700_queue_dequeue.c">
<Filter>Source Files\lfds700_queue</Filter>
</ClCompile>
<ClCompile Include="..\..\src\lfds700_queue\lfds700_queue_enqueue.c">
<Filter>Source Files\lfds700_queue</Filter>
</ClCompile>
<ClCompile Include="..\..\src\lfds700_queue\lfds700_queue_init.c">
<Filter>Source Files\lfds700_queue</Filter>
</ClCompile>
<ClCompile Include="..\..\src\lfds700_queue\lfds700_queue_query.c">
<Filter>Source Files\lfds700_queue</Filter>
</ClCompile>
<ClCompile Include="..\..\src\lfds700_hash_addonly\lfds700_hash_addonly_cleanup.c">
<Filter>Source Files\lfds700_hash_addonly</Filter>
</ClCompile>
<ClCompile Include="..\..\src\lfds700_hash_addonly\lfds700_hash_addonly_get.c">
<Filter>Source Files\lfds700_hash_addonly</Filter>
</ClCompile>
<ClCompile Include="..\..\src\lfds700_hash_addonly\lfds700_hash_addonly_init.c">
<Filter>Source Files\lfds700_hash_addonly</Filter>
</ClCompile>
<ClCompile Include="..\..\src\lfds700_hash_addonly\lfds700_hash_addonly_insert.c">
<Filter>Source Files\lfds700_hash_addonly</Filter>
</ClCompile>
<ClCompile Include="..\..\src\lfds700_hash_addonly\lfds700_hash_addonly_iterate.c">
<Filter>Source Files\lfds700_hash_addonly</Filter>
</ClCompile>
<ClCompile Include="..\..\src\lfds700_hash_addonly\lfds700_hash_addonly_query.c">
<Filter>Source Files\lfds700_hash_addonly</Filter>
</ClCompile>
<ClCompile Include="..\..\src\lfds700_list_addonly_ordered_singlylinked\lfds700_list_addonly_ordered_singlylinked_cleanup.c">
<Filter>Source Files\lfds700_list_addonly_ordered_singlylinked</Filter>
</ClCompile>
<ClCompile Include="..\..\src\lfds700_list_addonly_ordered_singlylinked\lfds700_list_addonly_ordered_singlylinked_get.c">
<Filter>Source Files\lfds700_list_addonly_ordered_singlylinked</Filter>
</ClCompile>
<ClCompile Include="..\..\src\lfds700_list_addonly_ordered_singlylinked\lfds700_list_addonly_ordered_singlylinked_init.c">
<Filter>Source Files\lfds700_list_addonly_ordered_singlylinked</Filter>
</ClCompile>
<ClCompile Include="..\..\src\lfds700_list_addonly_ordered_singlylinked\lfds700_list_addonly_ordered_singlylinked_insert.c">
<Filter>Source Files\lfds700_list_addonly_ordered_singlylinked</Filter>
</ClCompile>
<ClCompile Include="..\..\src\lfds700_list_addonly_ordered_singlylinked\lfds700_list_addonly_ordered_singlylinked_query.c">
<Filter>Source Files\lfds700_list_addonly_ordered_singlylinked</Filter>
</ClCompile>
<ClCompile Include="..\..\src\lfds700_btree_addonly_unbalanced\lfds700_btree_addonly_unbalanced_cleanup.c">
<Filter>Source Files\lfds700_btree_addonly_unbalanced</Filter>
</ClCompile>
<ClCompile Include="..\..\src\lfds700_btree_addonly_unbalanced\lfds700_btree_addonly_unbalanced_get.c">
<Filter>Source Files\lfds700_btree_addonly_unbalanced</Filter>
</ClCompile>
<ClCompile Include="..\..\src\lfds700_btree_addonly_unbalanced\lfds700_btree_addonly_unbalanced_init.c">
<Filter>Source Files\lfds700_btree_addonly_unbalanced</Filter>
</ClCompile>
<ClCompile Include="..\..\src\lfds700_btree_addonly_unbalanced\lfds700_btree_addonly_unbalanced_insert.c">
<Filter>Source Files\lfds700_btree_addonly_unbalanced</Filter>
</ClCompile>
<ClCompile Include="..\..\src\lfds700_btree_addonly_unbalanced\lfds700_btree_addonly_unbalanced_query.c">
<Filter>Source Files\lfds700_btree_addonly_unbalanced</Filter>
</ClCompile>
<ClCompile Include="..\..\src\lfds700_misc\lfds700_misc_cleanup.c">
<Filter>Source Files\lfds700_misc</Filter>
</ClCompile>
<ClCompile Include="..\..\src\lfds700_misc\lfds700_misc_globals.c">
<Filter>Source Files\lfds700_misc</Filter>
</ClCompile>
<ClCompile Include="..\..\src\lfds700_misc\lfds700_misc_init.c">
<Filter>Source Files\lfds700_misc</Filter>
</ClCompile>
<ClCompile Include="..\..\src\lfds700_misc\lfds700_misc_prng.c">
<Filter>Source Files\lfds700_misc</Filter>
</ClCompile>
<ClCompile Include="..\..\src\lfds700_misc\lfds700_misc_query.c">
<Filter>Source Files\lfds700_misc</Filter>
</ClCompile>
<ClCompile Include="..\..\src\lfds700_queue_bounded_singleconsumer_singleproducer\lfds700_queue_bounded_singleconsumer_singleproducer_cleanup.c">
<Filter>Source Files\lfds700_queue_bounded_singleconsumer_singleproducer</Filter>
</ClCompile>
<ClCompile Include="..\..\src\lfds700_queue_bounded_singleconsumer_singleproducer\lfds700_queue_bounded_singleconsumer_singleproducer_dequeue.c">
<Filter>Source Files\lfds700_queue_bounded_singleconsumer_singleproducer</Filter>
</ClCompile>
<ClCompile Include="..\..\src\lfds700_queue_bounded_singleconsumer_singleproducer\lfds700_queue_bounded_singleconsumer_singleproducer_enqueue.c">
<Filter>Source Files\lfds700_queue_bounded_singleconsumer_singleproducer</Filter>
</ClCompile>
<ClCompile Include="..\..\src\lfds700_queue_bounded_singleconsumer_singleproducer\lfds700_queue_bounded_singleconsumer_singleproducer_init.c">
<Filter>Source Files\lfds700_queue_bounded_singleconsumer_singleproducer</Filter>
</ClCompile>
<ClCompile Include="..\..\src\lfds700_queue_bounded_singleconsumer_singleproducer\lfds700_queue_bounded_singleconsumer_singleproducer_query.c">
<Filter>Source Files\lfds700_queue_bounded_singleconsumer_singleproducer</Filter>
</ClCompile>
<ClCompile Include="..\..\src\lfds700_list_addonly_singlylinked_unordered\lfds700_list_addonly_singlylinked_unordered_cleanup.c">
<Filter>Source Files\lfds700_list_addonly_singlylinked_unordered</Filter>
</ClCompile>
<ClCompile Include="..\..\src\lfds700_list_addonly_singlylinked_unordered\lfds700_list_addonly_singlylinked_unordered_get.c">
<Filter>Source Files\lfds700_list_addonly_singlylinked_unordered</Filter>
</ClCompile>
<ClCompile Include="..\..\src\lfds700_list_addonly_singlylinked_unordered\lfds700_list_addonly_singlylinked_unordered_init.c">
<Filter>Source Files\lfds700_list_addonly_singlylinked_unordered</Filter>
</ClCompile>
<ClCompile Include="..\..\src\lfds700_list_addonly_singlylinked_unordered\lfds700_list_addonly_singlylinked_unordered_insert.c">
<Filter>Source Files\lfds700_list_addonly_singlylinked_unordered</Filter>
</ClCompile>
<ClCompile Include="..\..\src\lfds700_list_addonly_singlylinked_unordered\lfds700_list_addonly_singlylinked_unordered_query.c">
<Filter>Source Files\lfds700_list_addonly_singlylinked_unordered</Filter>
</ClCompile>
<ClCompile Include="..\..\src\lfds700_ringbuffer\lfds700_ringbuffer_cleanup.c">
<Filter>Source Files\lfds700_ringbuffer</Filter>
</ClCompile>
<ClCompile Include="..\..\src\lfds700_ringbuffer\lfds700_ringbuffer_init.c">
<Filter>Source Files\lfds700_ringbuffer</Filter>
</ClCompile>
<ClCompile Include="..\..\src\lfds700_ringbuffer\lfds700_ringbuffer_query.c">
<Filter>Source Files\lfds700_ringbuffer</Filter>
</ClCompile>
<ClCompile Include="..\..\src\lfds700_ringbuffer\lfds700_ringbuffer_read.c">
<Filter>Source Files\lfds700_ringbuffer</Filter>
</ClCompile>
<ClCompile Include="..\..\src\lfds700_ringbuffer\lfds700_ringbuffer_write.c">
<Filter>Source Files\lfds700_ringbuffer</Filter>
</ClCompile>
</ItemGroup>
</Project>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup />
</Project>
\ No newline at end of file
EXPORTS
lfds700_btree_au_init_valid_on_current_logical_core = lfds700_btree_au_init_valid_on_current_logical_core
lfds700_btree_au_cleanup = lfds700_btree_au_cleanup
lfds700_btree_au_insert = lfds700_btree_au_insert
lfds700_btree_au_get_by_absolute_position_and_then_by_relative_position = lfds700_btree_au_get_by_absolute_position_and_then_by_relative_position
lfds700_btree_au_get_by_absolute_position = lfds700_btree_au_get_by_absolute_position
lfds700_btree_au_get_by_relative_position = lfds700_btree_au_get_by_relative_position
lfds700_btree_au_get_by_key = lfds700_btree_au_get_by_key
lfds700_btree_au_query = lfds700_btree_au_query
lfds700_freelist_init_valid_on_current_logical_core = lfds700_freelist_init_valid_on_current_logical_core
lfds700_freelist_cleanup = lfds700_freelist_cleanup
lfds700_freelist_push = lfds700_freelist_push
lfds700_freelist_pop = lfds700_freelist_pop
lfds700_freelist_query = lfds700_freelist_query
lfds700_hash_a_init_valid_on_current_logical_core = lfds700_hash_a_init_valid_on_current_logical_core
lfds700_hash_a_cleanup = lfds700_hash_a_cleanup
lfds700_hash_a_insert = lfds700_hash_a_insert
lfds700_hash_a_get_by_key = lfds700_hash_a_get_by_key
lfds700_hash_a_iterate_init = lfds700_hash_a_iterate_init
lfds700_hash_a_iterate = lfds700_hash_a_iterate
lfds700_hash_a_query = lfds700_hash_a_query
lfds700_list_aos_init_valid_on_current_logical_core = lfds700_list_aos_init_valid_on_current_logical_core
lfds700_list_aos_cleanup = lfds700_list_aos_cleanup
lfds700_list_aos_insert = lfds700_list_aos_insert
lfds700_list_aos_get_by_key = lfds700_list_aos_get_by_key
lfds700_list_aos_query = lfds700_list_aos_query
lfds700_list_asu_init_valid_on_current_logical_core = lfds700_list_asu_init_valid_on_current_logical_core
lfds700_list_asu_cleanup = lfds700_list_asu_cleanup
lfds700_list_asu_insert_at_position = lfds700_list_asu_insert_at_position
lfds700_list_asu_insert_at_start = lfds700_list_asu_insert_at_start
lfds700_list_asu_insert_at_end = lfds700_list_asu_insert_at_end
lfds700_list_asu_insert_after_element = lfds700_list_asu_insert_after_element
lfds700_list_asu_get_by_key = lfds700_list_asu_get_by_key
lfds700_list_asu_query = lfds700_list_asu_query
lfds700_misc_library_init_valid_on_current_logical_core = lfds700_misc_library_init_valid_on_current_logical_core
lfds700_misc_library_cleanup = lfds700_misc_library_cleanup
lfds700_misc_prng_init = lfds700_misc_prng_init
lfds700_misc_query = lfds700_misc_query
lfds700_queue_init_valid_on_current_logical_core = lfds700_queue_init_valid_on_current_logical_core
lfds700_queue_cleanup = lfds700_queue_cleanup
lfds700_queue_enqueue = lfds700_queue_enqueue
lfds700_queue_dequeue = lfds700_queue_dequeue
lfds700_queue_query = lfds700_queue_query
lfds700_queue_bss_init_valid_on_current_logical_core = lfds700_queue_bss_init_valid_on_current_logical_core
lfds700_queue_bss_cleanup = lfds700_queue_bss_cleanup
lfds700_queue_bss_enqueue = lfds700_queue_bss_enqueue
lfds700_queue_bss_dequeue = lfds700_queue_bss_dequeue
lfds700_queue_bss_query = lfds700_queue_bss_query
lfds700_ringbuffer_init_valid_on_current_logical_core = lfds700_ringbuffer_init_valid_on_current_logical_core
lfds700_ringbuffer_cleanup = lfds700_ringbuffer_cleanup
lfds700_ringbuffer_read = lfds700_ringbuffer_read
lfds700_ringbuffer_write = lfds700_ringbuffer_write
lfds700_ringbuffer_query = lfds700_ringbuffer_query
lfds700_stack_init_valid_on_current_logical_core = lfds700_stack_init_valid_on_current_logical_core
lfds700_stack_cleanup = lfds700_stack_cleanup
lfds700_stack_push = lfds700_stack_push
lfds700_stack_pop = lfds700_stack_pop
lfds700_stack_query = lfds700_stack_query
Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 2013
VisualStudioVersion = 12.0.40629.0
MinimumVisualStudioVersion = 10.0.40219.1
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "liblfds700", "liblfds700.vcxproj", "{1E5D7D09-94F2-455D-AE5E-6C7F4C96BCE0}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug DLL|ARM = Debug DLL|ARM
Debug DLL|Win32 = Debug DLL|Win32
Debug DLL|x64 = Debug DLL|x64
Debug LIB|ARM = Debug LIB|ARM
Debug LIB|Win32 = Debug LIB|Win32
Debug LIB|x64 = Debug LIB|x64
Release DLL|ARM = Release DLL|ARM
Release DLL|Win32 = Release DLL|Win32
Release DLL|x64 = Release DLL|x64
Release LIB|ARM = Release LIB|ARM
Release LIB|Win32 = Release LIB|Win32
Release LIB|x64 = Release LIB|x64
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{1E5D7D09-94F2-455D-AE5E-6C7F4C96BCE0}.Debug DLL|ARM.ActiveCfg = Debug DLL|ARM
{1E5D7D09-94F2-455D-AE5E-6C7F4C96BCE0}.Debug DLL|ARM.Build.0 = Debug DLL|ARM
{1E5D7D09-94F2-455D-AE5E-6C7F4C96BCE0}.Debug DLL|Win32.ActiveCfg = Debug DLL|Win32
{1E5D7D09-94F2-455D-AE5E-6C7F4C96BCE0}.Debug DLL|Win32.Build.0 = Debug DLL|Win32
{1E5D7D09-94F2-455D-AE5E-6C7F4C96BCE0}.Debug DLL|Win32.Deploy.0 = Debug DLL|Win32
{1E5D7D09-94F2-455D-AE5E-6C7F4C96BCE0}.Debug DLL|x64.ActiveCfg = Debug DLL|x64
{1E5D7D09-94F2-455D-AE5E-6C7F4C96BCE0}.Debug DLL|x64.Build.0 = Debug DLL|x64
{1E5D7D09-94F2-455D-AE5E-6C7F4C96BCE0}.Debug DLL|x64.Deploy.0 = Debug DLL|x64
{1E5D7D09-94F2-455D-AE5E-6C7F4C96BCE0}.Debug LIB|ARM.ActiveCfg = Debug LIB|ARM
{1E5D7D09-94F2-455D-AE5E-6C7F4C96BCE0}.Debug LIB|ARM.Build.0 = Debug LIB|ARM
{1E5D7D09-94F2-455D-AE5E-6C7F4C96BCE0}.Debug LIB|Win32.ActiveCfg = Debug LIB|Win32
{1E5D7D09-94F2-455D-AE5E-6C7F4C96BCE0}.Debug LIB|Win32.Build.0 = Debug LIB|Win32
{1E5D7D09-94F2-455D-AE5E-6C7F4C96BCE0}.Debug LIB|Win32.Deploy.0 = Debug LIB|Win32
{1E5D7D09-94F2-455D-AE5E-6C7F4C96BCE0}.Debug LIB|x64.ActiveCfg = Debug LIB|x64
{1E5D7D09-94F2-455D-AE5E-6C7F4C96BCE0}.Debug LIB|x64.Build.0 = Debug LIB|x64
{1E5D7D09-94F2-455D-AE5E-6C7F4C96BCE0}.Debug LIB|x64.Deploy.0 = Debug LIB|x64
{1E5D7D09-94F2-455D-AE5E-6C7F4C96BCE0}.Release DLL|ARM.ActiveCfg = Release DLL|ARM
{1E5D7D09-94F2-455D-AE5E-6C7F4C96BCE0}.Release DLL|ARM.Build.0 = Release DLL|ARM
{1E5D7D09-94F2-455D-AE5E-6C7F4C96BCE0}.Release DLL|Win32.ActiveCfg = Release DLL|Win32
{1E5D7D09-94F2-455D-AE5E-6C7F4C96BCE0}.Release DLL|Win32.Build.0 = Release DLL|Win32
{1E5D7D09-94F2-455D-AE5E-6C7F4C96BCE0}.Release DLL|Win32.Deploy.0 = Release DLL|Win32
{1E5D7D09-94F2-455D-AE5E-6C7F4C96BCE0}.Release DLL|x64.ActiveCfg = Release DLL|x64
{1E5D7D09-94F2-455D-AE5E-6C7F4C96BCE0}.Release DLL|x64.Build.0 = Release DLL|x64
{1E5D7D09-94F2-455D-AE5E-6C7F4C96BCE0}.Release DLL|x64.Deploy.0 = Release DLL|x64
{1E5D7D09-94F2-455D-AE5E-6C7F4C96BCE0}.Release LIB|ARM.ActiveCfg = Release LIB|ARM
{1E5D7D09-94F2-455D-AE5E-6C7F4C96BCE0}.Release LIB|ARM.Build.0 = Release LIB|ARM
{1E5D7D09-94F2-455D-AE5E-6C7F4C96BCE0}.Release LIB|Win32.ActiveCfg = Release LIB|Win32
{1E5D7D09-94F2-455D-AE5E-6C7F4C96BCE0}.Release LIB|Win32.Build.0 = Release LIB|Win32
{1E5D7D09-94F2-455D-AE5E-6C7F4C96BCE0}.Release LIB|Win32.Deploy.0 = Release LIB|Win32
{1E5D7D09-94F2-455D-AE5E-6C7F4C96BCE0}.Release LIB|x64.ActiveCfg = Release LIB|x64
{1E5D7D09-94F2-455D-AE5E-6C7F4C96BCE0}.Release LIB|x64.Build.0 = Release LIB|x64
{1E5D7D09-94F2-455D-AE5E-6C7F4C96BCE0}.Release LIB|x64.Deploy.0 = Release LIB|x64
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
EndGlobal
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug DLL|ARM">
<Configuration>Debug DLL</Configuration>
<Platform>ARM</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Debug DLL|Win32">
<Configuration>Debug DLL</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Debug DLL|x64">
<Configuration>Debug DLL</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Debug LIB|ARM">
<Configuration>Debug LIB</Configuration>
<Platform>ARM</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Debug LIB|Win32">
<Configuration>Debug LIB</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Debug LIB|x64">
<Configuration>Debug LIB</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release DLL|ARM">
<Configuration>Release DLL</Configuration>
<Platform>ARM</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release DLL|Win32">
<Configuration>Release DLL</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release DLL|x64">
<Configuration>Release DLL</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release LIB|ARM">
<Configuration>Release LIB</Configuration>
<Platform>ARM</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release LIB|Win32">
<Configuration>Release LIB</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release LIB|x64">
<Configuration>Release LIB</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<ProjectGuid>{1E5D7D09-94F2-455D-AE5E-6C7F4C96BCE0}</ProjectGuid>
<Keyword>Win32Proj</Keyword>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug LIB|Win32'" Label="Configuration">
<ConfigurationType>StaticLibrary</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>WindowsKernelModeDriver8.1</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug LIB|ARM'" Label="Configuration">
<ConfigurationType>StaticLibrary</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>WindowsKernelModeDriver8.1</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug DLL|Win32'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>WindowsKernelModeDriver8.1</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug DLL|ARM'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>WindowsKernelModeDriver8.1</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug LIB|x64'" Label="Configuration">
<ConfigurationType>StaticLibrary</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>WindowsKernelModeDriver8.1</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug DLL|x64'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>WindowsKernelModeDriver8.1</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release LIB|Win32'" Label="Configuration">
<ConfigurationType>StaticLibrary</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>WindowsKernelModeDriver8.1</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release LIB|ARM'" Label="Configuration">
<ConfigurationType>StaticLibrary</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>WindowsKernelModeDriver8.1</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release DLL|Win32'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>WindowsKernelModeDriver8.1</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release DLL|ARM'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>WindowsKernelModeDriver8.1</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release LIB|x64'" Label="Configuration">
<ConfigurationType>StaticLibrary</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>WindowsKernelModeDriver8.1</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release DLL|x64'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>WindowsKernelModeDriver8.1</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug LIB|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug LIB|ARM'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug DLL|Win32'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug DLL|ARM'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug LIB|x64'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug DLL|x64'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release LIB|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release LIB|ARM'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release DLL|Win32'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release DLL|ARM'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release LIB|x64'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release DLL|x64'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug LIB|Win32'">
<LinkIncremental>true</LinkIncremental>
<OutDir>$(ProjectDir)..\..\bin\$(Platform) $(Configuration)\</OutDir>
<IntDir>$(ProjectDir)..\..\obj\$(Platform) $(Configuration)\</IntDir>
<IncludePath>$(ProjectDir);$(IncludePath);$(WDKContentRoot)include\km\;$(WDKContentRoot)include\wdf\kmdf\1.11\</IncludePath>
<LibraryPath>$(VCInstallDir)lib;$(VCInstallDir)atlmfc\lib;$(WindowsSDK_LibraryPath_x86);$(WDKContentRoot)lib\wdf\kmdf\x86\</LibraryPath>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug LIB|ARM'">
<LinkIncremental>true</LinkIncremental>
<OutDir>$(ProjectDir)..\..\bin\$(Platform) $(Configuration)\</OutDir>
<IntDir>$(ProjectDir)..\..\obj\$(Platform) $(Configuration)\</IntDir>
<IncludePath>$(ProjectDir);$(IncludePath)</IncludePath>
<LibraryPath>$(WDKContentRoot)lib\$(DDKSpec)\KM\$(DDKPlatform);$(LibraryPath)</LibraryPath>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug DLL|Win32'">
<LinkIncremental>
</LinkIncremental>
<OutDir>$(ProjectDir)..\..\bin\$(Platform) $(Configuration)\</OutDir>
<IntDir>$(ProjectDir)..\..\obj\$(Platform) $(Configuration)\</IntDir>
<IncludePath>$(ProjectDir);$(IncludePath);$(WDKContentRoot)include\km\;$(WDKContentRoot)include\wdf\kmdf\1.11\</IncludePath>
<LibraryPath>$(VCInstallDir)lib;$(VCInstallDir)atlmfc\lib;$(WindowsSDK_LibraryPath_x86);$(WDKContentRoot)lib\wdf\kmdf\x86\</LibraryPath>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug DLL|ARM'">
<LinkIncremental />
<OutDir>$(ProjectDir)..\..\bin\$(Platform) $(Configuration)\</OutDir>
<IntDir>$(ProjectDir)..\..\obj\$(Platform) $(Configuration)\</IntDir>
<IncludePath>$(ProjectDir);$(IncludePath)</IncludePath>
<LibraryPath>$(WDKContentRoot)lib\$(DDKSpec)\KM\$(DDKPlatform);$(LibraryPath)</LibraryPath>
<ExcludePath>$(VC_IncludePath);$(WindowsSDK_IncludePath);$(MSBuildToolsPath);$(MSBuildFrameworkToolsPath);$(MSBuild_ExecutablePath);$(VC_LibraryPath_ARM);</ExcludePath>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug LIB|x64'">
<LinkIncremental>true</LinkIncremental>
<OutDir>$(ProjectDir)..\..\bin\$(Platform) $(Configuration)\</OutDir>
<IntDir>$(ProjectDir)..\..\obj\$(Platform) $(Configuration)\</IntDir>
<IncludePath>$(ProjectDir);$(IncludePath);$(WDKContentRoot)include\km\;$(WDKContentRoot)include\wdf\kmdf\1.11\</IncludePath>
<LibraryPath>$(VCInstallDir)lib\amd64;$(VCInstallDir)atlmfc\lib\amd64;$(WindowsSDK_LibraryPath_x64);;$(WDKContentRoot)lib\wdf\kmdf\x64\</LibraryPath>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug DLL|x64'">
<LinkIncremental>
</LinkIncremental>
<OutDir>$(ProjectDir)..\..\bin\$(Platform) $(Configuration)\</OutDir>
<IntDir>$(ProjectDir)..\..\obj\$(Platform) $(Configuration)\</IntDir>
<IncludePath>$(ProjectDir);$(IncludePath);$(WDKContentRoot)include\km\;$(WDKContentRoot)include\wdf\kmdf\1.11\</IncludePath>
<LibraryPath>$(VCInstallDir)lib\amd64;$(VCInstallDir)atlmfc\lib\amd64;$(WindowsSDK_LibraryPath_x64);;$(WDKContentRoot)lib\wdf\kmdf\x64\</LibraryPath>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release LIB|Win32'">
<LinkIncremental>true</LinkIncremental>
<OutDir>$(ProjectDir)..\..\bin\$(Platform) $(Configuration)\</OutDir>
<IntDir>$(ProjectDir)..\..\obj\$(Platform) $(Configuration)\</IntDir>
<IncludePath>$(ProjectDir);$(IncludePath);$(WDKContentRoot)include\km\;$(WDKContentRoot)include\wdf\kmdf\1.11\</IncludePath>
<LibraryPath>$(VCInstallDir)lib;$(VCInstallDir)atlmfc\lib;$(WindowsSDK_LibraryPath_x86);$(WDKContentRoot)lib\wdf\kmdf\x86\</LibraryPath>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release LIB|ARM'">
<LinkIncremental>true</LinkIncremental>
<OutDir>$(ProjectDir)..\..\bin\$(Platform) $(Configuration)\</OutDir>
<IntDir>$(ProjectDir)..\..\obj\$(Platform) $(Configuration)\</IntDir>
<IncludePath>$(ProjectDir);$(IncludePath)</IncludePath>
<LibraryPath>$(WDKContentRoot)lib\$(DDKSpec)\KM\$(DDKPlatform);$(LibraryPath)</LibraryPath>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release DLL|Win32'">
<LinkIncremental>
</LinkIncremental>
<OutDir>$(ProjectDir)..\..\bin\$(Platform) $(Configuration)\</OutDir>
<IntDir>$(ProjectDir)..\..\obj\$(Platform) $(Configuration)\</IntDir>
<IncludePath>$(ProjectDir);$(IncludePath);$(WDKContentRoot)include\km\;$(WDKContentRoot)include\wdf\kmdf\1.11\</IncludePath>
<LibraryPath>$(VCInstallDir)lib;$(VCInstallDir)atlmfc\lib;$(WindowsSDK_LibraryPath_x86);$(WDKContentRoot)lib\wdf\kmdf\x86\</LibraryPath>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release DLL|ARM'">
<LinkIncremental />
<OutDir>$(ProjectDir)..\..\bin\$(Platform) $(Configuration)\</OutDir>
<IntDir>$(ProjectDir)..\..\obj\$(Platform) $(Configuration)\</IntDir>
<IncludePath>$(ProjectDir);$(IncludePath)</IncludePath>
<LibraryPath>$(WDKContentRoot)lib\$(DDKSpec)\KM\$(DDKPlatform);$(LibraryPath)</LibraryPath>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release LIB|x64'">
<LinkIncremental>true</LinkIncremental>
<OutDir>$(ProjectDir)..\..\bin\$(Platform) $(Configuration)\</OutDir>
<IntDir>$(ProjectDir)..\..\obj\$(Platform) $(Configuration)\</IntDir>
<IncludePath>$(ProjectDir);$(IncludePath);$(WDKContentRoot)include\km\;$(WDKContentRoot)include\wdf\kmdf\1.11\</IncludePath>
<LibraryPath>$(VCInstallDir)lib\amd64;$(VCInstallDir)atlmfc\lib\amd64;$(WindowsSDK_LibraryPath_x64);;$(WDKContentRoot)lib\wdf\kmdf\x64\</LibraryPath>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release DLL|x64'">
<LinkIncremental>
</LinkIncremental>
<OutDir>$(ProjectDir)..\..\bin\$(Platform) $(Configuration)\</OutDir>
<IntDir>$(ProjectDir)..\..\obj\$(Platform) $(Configuration)\</IntDir>
<IncludePath>$(ProjectDir);$(IncludePath);$(WDKContentRoot)include\km\;$(WDKContentRoot)include\wdf\kmdf\1.11\</IncludePath>
<LibraryPath>$(VCInstallDir)lib\amd64;$(VCInstallDir)atlmfc\lib\amd64;$(WindowsSDK_LibraryPath_x64);;$(WDKContentRoot)lib\wdf\kmdf\x64\</LibraryPath>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug LIB|Win32'">
<ClCompile>
<PreprocessorDefinitions>WIN32;_DEBUG;_LIB;LFDS700_BUILD_TYPE_STRING="Debug";%(PreprocessorDefinitions)</PreprocessorDefinitions>
<AdditionalIncludeDirectories>
</AdditionalIncludeDirectories>
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
<WarningLevel>Level4</WarningLevel>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
<Optimization>Disabled</Optimization>
<CompileAsManaged>false</CompileAsManaged>
<CompileAsWinRT>false</CompileAsWinRT>
<TreatWarningAsError>true</TreatWarningAsError>
<MultiProcessorCompilation>true</MultiProcessorCompilation>
<IntrinsicFunctions>true</IntrinsicFunctions>
<StringPooling>true</StringPooling>
<ExceptionHandling>false</ExceptionHandling>
<SmallerTypeCheck>true</SmallerTypeCheck>
<FunctionLevelLinking>
</FunctionLevelLinking>
<EnableParallelCodeGeneration>
</EnableParallelCodeGeneration>
<EnableEnhancedInstructionSet>
</EnableEnhancedInstructionSet>
<FloatingPointExceptions>true</FloatingPointExceptions>
<CreateHotpatchableImage>false</CreateHotpatchableImage>
<RuntimeTypeInfo>false</RuntimeTypeInfo>
<OpenMPSupport>false</OpenMPSupport>
<BrowseInformation>true</BrowseInformation>
<CompileAs>CompileAsC</CompileAs>
<UseFullPaths>true</UseFullPaths>
<ErrorReporting>None</ErrorReporting>
<SDLCheck>true</SDLCheck>
<MinimalRebuild>false</MinimalRebuild>
<DisableSpecificWarnings>4068</DisableSpecificWarnings>
<AdditionalOptions>/kernel %(AdditionalOptions)</AdditionalOptions>
</ClCompile>
<Link>
<TargetMachine>MachineX86</TargetMachine>
<GenerateDebugInformation>true</GenerateDebugInformation>
<SubSystem>Windows</SubSystem>
</Link>
<Lib>
<TreatLibWarningAsErrors>true</TreatLibWarningAsErrors>
</Lib>
<Lib>
<TargetMachine>MachineX86</TargetMachine>
</Lib>
<Lib>
<SubSystem>Native</SubSystem>
</Lib>
<Lib>
<LinkTimeCodeGeneration>false</LinkTimeCodeGeneration>
<IgnoreAllDefaultLibraries>true</IgnoreAllDefaultLibraries>
</Lib>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug LIB|ARM'">
<ClCompile>
<PreprocessorDefinitions>WIN32;_DEBUG;_LIB;LFDS700_BUILD_TYPE_STRING="Debug";%(PreprocessorDefinitions)</PreprocessorDefinitions>
<AdditionalIncludeDirectories>
</AdditionalIncludeDirectories>
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
<WarningLevel>Level4</WarningLevel>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
<Optimization>Disabled</Optimization>
<CompileAsManaged>false</CompileAsManaged>
<CompileAsWinRT>false</CompileAsWinRT>
<TreatWarningAsError>true</TreatWarningAsError>
<MultiProcessorCompilation>true</MultiProcessorCompilation>
<IntrinsicFunctions>true</IntrinsicFunctions>
<StringPooling>true</StringPooling>
<ExceptionHandling>false</ExceptionHandling>
<SmallerTypeCheck>true</SmallerTypeCheck>
<FunctionLevelLinking>
</FunctionLevelLinking>
<EnableParallelCodeGeneration>
</EnableParallelCodeGeneration>
<EnableEnhancedInstructionSet>
</EnableEnhancedInstructionSet>
<FloatingPointExceptions>true</FloatingPointExceptions>
<CreateHotpatchableImage>false</CreateHotpatchableImage>
<RuntimeTypeInfo>false</RuntimeTypeInfo>
<OpenMPSupport>false</OpenMPSupport>
<BrowseInformation>true</BrowseInformation>
<CompileAs>CompileAsC</CompileAs>
<UseFullPaths>true</UseFullPaths>
<ErrorReporting>None</ErrorReporting>
<SDLCheck>true</SDLCheck>
<MinimalRebuild>false</MinimalRebuild>
<DisableSpecificWarnings>4068</DisableSpecificWarnings>
<AdditionalOptions>/kernel %(AdditionalOptions)</AdditionalOptions>
</ClCompile>
<Link>
<GenerateDebugInformation>true</GenerateDebugInformation>
<SubSystem>Windows</SubSystem>
</Link>
<Lib>
<TreatLibWarningAsErrors>true</TreatLibWarningAsErrors>
</Lib>
<Lib>
<TargetMachine>MachineARM</TargetMachine>
</Lib>
<Lib>
<SubSystem>Native</SubSystem>
</Lib>
<Lib>
<LinkTimeCodeGeneration>false</LinkTimeCodeGeneration>
<IgnoreAllDefaultLibraries>true</IgnoreAllDefaultLibraries>
</Lib>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug DLL|Win32'">
<ClCompile>
<PreprocessorDefinitions>WIN32;_DEBUG;_LIB;LFDS700_BUILD_TYPE_STRING="Debug";%(PreprocessorDefinitions)</PreprocessorDefinitions>
<AdditionalIncludeDirectories>
</AdditionalIncludeDirectories>
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
<WarningLevel>Level4</WarningLevel>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
<Optimization>Disabled</Optimization>
<CompileAsManaged>false</CompileAsManaged>
<CompileAsWinRT>false</CompileAsWinRT>
<TreatWarningAsError>true</TreatWarningAsError>
<MultiProcessorCompilation>true</MultiProcessorCompilation>
<IntrinsicFunctions>true</IntrinsicFunctions>
<StringPooling>true</StringPooling>
<ExceptionHandling>false</ExceptionHandling>
<SmallerTypeCheck>true</SmallerTypeCheck>
<FunctionLevelLinking>
</FunctionLevelLinking>
<EnableParallelCodeGeneration>
</EnableParallelCodeGeneration>
<EnableEnhancedInstructionSet>
</EnableEnhancedInstructionSet>
<FloatingPointExceptions>true</FloatingPointExceptions>
<CreateHotpatchableImage>false</CreateHotpatchableImage>
<RuntimeTypeInfo>false</RuntimeTypeInfo>
<OpenMPSupport>false</OpenMPSupport>
<BrowseInformation>true</BrowseInformation>
<CompileAs>CompileAsC</CompileAs>
<UseFullPaths>true</UseFullPaths>
<ErrorReporting>None</ErrorReporting>
<SDLCheck>true</SDLCheck>
<MinimalRebuild>false</MinimalRebuild>
<DisableSpecificWarnings>4068</DisableSpecificWarnings>
<AdditionalOptions>/kernel %(AdditionalOptions)</AdditionalOptions>
</ClCompile>
<Link>
<TargetMachine>MachineX86</TargetMachine>
<GenerateDebugInformation>true</GenerateDebugInformation>
<SubSystem>Native</SubSystem>
<AdditionalDependencies>kernel32.lib;msvcrtd.lib</AdditionalDependencies>
<LinkStatus>
</LinkStatus>
<TreatLinkerWarningAsErrors>true</TreatLinkerWarningAsErrors>
<IgnoreAllDefaultLibraries>true</IgnoreAllDefaultLibraries>
<ModuleDefinitionFile>liblfds700.def</ModuleDefinitionFile>
<MapExports>true</MapExports>
<LinkErrorReporting>NoErrorReport</LinkErrorReporting>
<GenerateMapFile>true</GenerateMapFile>
<Driver>WDM</Driver>
</Link>
<Lib>
<TreatLibWarningAsErrors>true</TreatLibWarningAsErrors>
</Lib>
<Lib>
<TargetMachine>MachineX86</TargetMachine>
</Lib>
<Lib>
<SubSystem>Console</SubSystem>
</Lib>
<Lib>
<LinkTimeCodeGeneration>false</LinkTimeCodeGeneration>
<IgnoreAllDefaultLibraries>true</IgnoreAllDefaultLibraries>
</Lib>
<ProjectReference>
<LinkLibraryDependencies>true</LinkLibraryDependencies>
</ProjectReference>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug DLL|ARM'">
<ClCompile>
<PreprocessorDefinitions>WIN32;_DEBUG;_LIB;LFDS700_BUILD_TYPE_STRING="Debug";%(PreprocessorDefinitions)</PreprocessorDefinitions>
<AdditionalIncludeDirectories>
</AdditionalIncludeDirectories>
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
<WarningLevel>Level4</WarningLevel>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
<Optimization>Disabled</Optimization>
<CompileAsManaged>false</CompileAsManaged>
<CompileAsWinRT>false</CompileAsWinRT>
<TreatWarningAsError>true</TreatWarningAsError>
<MultiProcessorCompilation>true</MultiProcessorCompilation>
<IntrinsicFunctions>true</IntrinsicFunctions>
<StringPooling>true</StringPooling>
<ExceptionHandling>false</ExceptionHandling>
<SmallerTypeCheck>true</SmallerTypeCheck>
<FunctionLevelLinking>
</FunctionLevelLinking>
<EnableParallelCodeGeneration>
</EnableParallelCodeGeneration>
<EnableEnhancedInstructionSet>
</EnableEnhancedInstructionSet>
<FloatingPointExceptions>true</FloatingPointExceptions>
<CreateHotpatchableImage>false</CreateHotpatchableImage>
<RuntimeTypeInfo>false</RuntimeTypeInfo>
<OpenMPSupport>false</OpenMPSupport>
<BrowseInformation>true</BrowseInformation>
<CompileAs>CompileAsC</CompileAs>
<UseFullPaths>true</UseFullPaths>
<ErrorReporting>None</ErrorReporting>
<SDLCheck>true</SDLCheck>
<MinimalRebuild>false</MinimalRebuild>
<DisableSpecificWarnings>4068</DisableSpecificWarnings>
<AdditionalOptions>/kernel %(AdditionalOptions)</AdditionalOptions>
</ClCompile>
<Link>
<GenerateDebugInformation>true</GenerateDebugInformation>
<SubSystem>Native</SubSystem>
<AdditionalDependencies>kernel32.lib;msvcrtd.lib</AdditionalDependencies>
<LinkStatus>
</LinkStatus>
<TreatLinkerWarningAsErrors>true</TreatLinkerWarningAsErrors>
<IgnoreAllDefaultLibraries>true</IgnoreAllDefaultLibraries>
<ModuleDefinitionFile>liblfds700.def</ModuleDefinitionFile>
<MapExports>true</MapExports>
<LinkErrorReporting>NoErrorReport</LinkErrorReporting>
<GenerateMapFile>true</GenerateMapFile>
<Driver>WDM</Driver>
<IgnoreSpecificDefaultLibraries />
</Link>
<Lib>
<TreatLibWarningAsErrors>true</TreatLibWarningAsErrors>
</Lib>
<Lib>
<TargetMachine>MachineX86</TargetMachine>
</Lib>
<Lib>
<SubSystem>Console</SubSystem>
</Lib>
<Lib>
<LinkTimeCodeGeneration>false</LinkTimeCodeGeneration>
<IgnoreAllDefaultLibraries>true</IgnoreAllDefaultLibraries>
</Lib>
<ProjectReference>
<LinkLibraryDependencies>true</LinkLibraryDependencies>
</ProjectReference>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug LIB|x64'">
<ClCompile>
<PreprocessorDefinitions>WIN32;_DEBUG;_LIB;LFDS700_BUILD_TYPE_STRING="Debug";%(PreprocessorDefinitions)</PreprocessorDefinitions>
<AdditionalIncludeDirectories>
</AdditionalIncludeDirectories>
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
<WarningLevel>Level4</WarningLevel>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
<Optimization>Disabled</Optimization>
<CompileAsManaged>false</CompileAsManaged>
<CompileAsWinRT>false</CompileAsWinRT>
<TreatWarningAsError>true</TreatWarningAsError>
<MultiProcessorCompilation>true</MultiProcessorCompilation>
<IntrinsicFunctions>true</IntrinsicFunctions>
<StringPooling>true</StringPooling>
<ExceptionHandling>false</ExceptionHandling>
<SmallerTypeCheck>true</SmallerTypeCheck>
<FunctionLevelLinking>
</FunctionLevelLinking>
<EnableParallelCodeGeneration>
</EnableParallelCodeGeneration>
<EnableEnhancedInstructionSet>
</EnableEnhancedInstructionSet>
<FloatingPointExceptions>true</FloatingPointExceptions>
<CreateHotpatchableImage>false</CreateHotpatchableImage>
<RuntimeTypeInfo>false</RuntimeTypeInfo>
<OpenMPSupport>false</OpenMPSupport>
<BrowseInformation>true</BrowseInformation>
<CompileAs>CompileAsC</CompileAs>
<UseFullPaths>true</UseFullPaths>
<ErrorReporting>None</ErrorReporting>
<SDLCheck>true</SDLCheck>
<MinimalRebuild>false</MinimalRebuild>
<DisableSpecificWarnings>4068</DisableSpecificWarnings>
<OmitFramePointers>false</OmitFramePointers>
<AdditionalOptions>/kernel %(AdditionalOptions)</AdditionalOptions>
</ClCompile>
<Link>
<GenerateDebugInformation>true</GenerateDebugInformation>
<SubSystem>Windows</SubSystem>
</Link>
<Lib>
<TreatLibWarningAsErrors>true</TreatLibWarningAsErrors>
</Lib>
<Lib>
<TargetMachine>MachineX64</TargetMachine>
</Lib>
<Lib>
<SubSystem>Native</SubSystem>
</Lib>
<Lib>
<LinkTimeCodeGeneration>false</LinkTimeCodeGeneration>
<IgnoreAllDefaultLibraries>true</IgnoreAllDefaultLibraries>
</Lib>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug DLL|x64'">
<ClCompile>
<PreprocessorDefinitions>WIN32;_DEBUG;_LIB;LFDS700_BUILD_TYPE_STRING="Debug";%(PreprocessorDefinitions)</PreprocessorDefinitions>
<AdditionalIncludeDirectories>
</AdditionalIncludeDirectories>
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
<WarningLevel>Level4</WarningLevel>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
<Optimization>Disabled</Optimization>
<CompileAsManaged>false</CompileAsManaged>
<CompileAsWinRT>false</CompileAsWinRT>
<TreatWarningAsError>true</TreatWarningAsError>
<MultiProcessorCompilation>true</MultiProcessorCompilation>
<IntrinsicFunctions>true</IntrinsicFunctions>
<StringPooling>true</StringPooling>
<ExceptionHandling>false</ExceptionHandling>
<SmallerTypeCheck>true</SmallerTypeCheck>
<FunctionLevelLinking>
</FunctionLevelLinking>
<EnableParallelCodeGeneration>
</EnableParallelCodeGeneration>
<EnableEnhancedInstructionSet>
</EnableEnhancedInstructionSet>
<FloatingPointExceptions>true</FloatingPointExceptions>
<CreateHotpatchableImage>false</CreateHotpatchableImage>
<RuntimeTypeInfo>false</RuntimeTypeInfo>
<OpenMPSupport>false</OpenMPSupport>
<BrowseInformation>true</BrowseInformation>
<CompileAs>CompileAsC</CompileAs>
<UseFullPaths>true</UseFullPaths>
<ErrorReporting>None</ErrorReporting>
<SDLCheck>true</SDLCheck>
<MinimalRebuild>false</MinimalRebuild>
<DisableSpecificWarnings>4068</DisableSpecificWarnings>
<OmitFramePointers>false</OmitFramePointers>
<AdditionalOptions>/kernel %(AdditionalOptions)</AdditionalOptions>
</ClCompile>
<Link>
<GenerateDebugInformation>true</GenerateDebugInformation>
<SubSystem>Native</SubSystem>
<TreatLinkerWarningAsErrors>true</TreatLinkerWarningAsErrors>
<IgnoreAllDefaultLibraries>true</IgnoreAllDefaultLibraries>
<ModuleDefinitionFile>liblfds700.def</ModuleDefinitionFile>
<MapExports>true</MapExports>
<OptimizeReferences>false</OptimizeReferences>
<LinkErrorReporting>NoErrorReport</LinkErrorReporting>
<AdditionalDependencies>kernel32.lib;msvcrtd.lib</AdditionalDependencies>
<GenerateMapFile>true</GenerateMapFile>
<Driver>WDM</Driver>
</Link>
<Lib>
<TreatLibWarningAsErrors>true</TreatLibWarningAsErrors>
</Lib>
<Lib>
<TargetMachine>MachineX64</TargetMachine>
</Lib>
<Lib>
<SubSystem>Console</SubSystem>
</Lib>
<Lib>
<LinkTimeCodeGeneration>false</LinkTimeCodeGeneration>
<IgnoreAllDefaultLibraries>true</IgnoreAllDefaultLibraries>
</Lib>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release LIB|Win32'">
<ClCompile>
<PreprocessorDefinitions>WIN32;NDEBUG;_LIB;LFDS700_BUILD_TYPE_STRING="Release";%(PreprocessorDefinitions)</PreprocessorDefinitions>
<AdditionalIncludeDirectories>
</AdditionalIncludeDirectories>
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
<WarningLevel>Level4</WarningLevel>
<DebugInformationFormat>None</DebugInformationFormat>
<CompileAsManaged>false</CompileAsManaged>
<CompileAsWinRT>false</CompileAsWinRT>
<TreatWarningAsError>true</TreatWarningAsError>
<MultiProcessorCompilation>true</MultiProcessorCompilation>
<InlineFunctionExpansion>AnySuitable</InlineFunctionExpansion>
<IntrinsicFunctions>true</IntrinsicFunctions>
<FavorSizeOrSpeed>Speed</FavorSizeOrSpeed>
<StringPooling>true</StringPooling>
<ExceptionHandling>false</ExceptionHandling>
<BufferSecurityCheck>false</BufferSecurityCheck>
<FunctionLevelLinking>
</FunctionLevelLinking>
<EnableParallelCodeGeneration>
</EnableParallelCodeGeneration>
<EnableEnhancedInstructionSet>
</EnableEnhancedInstructionSet>
<FloatingPointExceptions>false</FloatingPointExceptions>
<CreateHotpatchableImage>
</CreateHotpatchableImage>
<RuntimeTypeInfo>false</RuntimeTypeInfo>
<OpenMPSupport>false</OpenMPSupport>
<CompileAs>CompileAsC</CompileAs>
<UseFullPaths>true</UseFullPaths>
<ErrorReporting>None</ErrorReporting>
<OmitFramePointers>true</OmitFramePointers>
<DisableSpecificWarnings>4068</DisableSpecificWarnings>
<EnableFiberSafeOptimizations>true</EnableFiberSafeOptimizations>
<AdditionalOptions>/kernel %(AdditionalOptions)</AdditionalOptions>
</ClCompile>
<Link>
<TargetMachine>MachineX86</TargetMachine>
<GenerateDebugInformation>true</GenerateDebugInformation>
<SubSystem>Windows</SubSystem>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
</Link>
<Lib>
<TreatLibWarningAsErrors>true</TreatLibWarningAsErrors>
</Lib>
<Lib>
<TargetMachine>MachineX86</TargetMachine>
</Lib>
<Lib>
<SubSystem>Native</SubSystem>
<IgnoreAllDefaultLibraries>true</IgnoreAllDefaultLibraries>
</Lib>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release LIB|ARM'">
<ClCompile>
<PreprocessorDefinitions>WIN32;NDEBUG;_LIB;LFDS700_BUILD_TYPE_STRING="Release";%(PreprocessorDefinitions)</PreprocessorDefinitions>
<AdditionalIncludeDirectories>
</AdditionalIncludeDirectories>
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
<WarningLevel>Level4</WarningLevel>
<DebugInformationFormat>None</DebugInformationFormat>
<CompileAsManaged>false</CompileAsManaged>
<CompileAsWinRT>false</CompileAsWinRT>
<TreatWarningAsError>true</TreatWarningAsError>
<MultiProcessorCompilation>true</MultiProcessorCompilation>
<InlineFunctionExpansion>AnySuitable</InlineFunctionExpansion>
<IntrinsicFunctions>true</IntrinsicFunctions>
<FavorSizeOrSpeed>Speed</FavorSizeOrSpeed>
<StringPooling>true</StringPooling>
<ExceptionHandling>false</ExceptionHandling>
<BufferSecurityCheck>false</BufferSecurityCheck>
<FunctionLevelLinking>
</FunctionLevelLinking>
<EnableParallelCodeGeneration>
</EnableParallelCodeGeneration>
<EnableEnhancedInstructionSet>
</EnableEnhancedInstructionSet>
<FloatingPointExceptions>false</FloatingPointExceptions>
<CreateHotpatchableImage>
</CreateHotpatchableImage>
<RuntimeTypeInfo>false</RuntimeTypeInfo>
<OpenMPSupport>false</OpenMPSupport>
<CompileAs>CompileAsC</CompileAs>
<UseFullPaths>true</UseFullPaths>
<ErrorReporting>None</ErrorReporting>
<OmitFramePointers>true</OmitFramePointers>
<DisableSpecificWarnings>4068</DisableSpecificWarnings>
<EnableFiberSafeOptimizations>true</EnableFiberSafeOptimizations>
<AdditionalOptions>/kernel %(AdditionalOptions)</AdditionalOptions>
</ClCompile>
<Link>
<GenerateDebugInformation>true</GenerateDebugInformation>
<SubSystem>Windows</SubSystem>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
</Link>
<Lib>
<TreatLibWarningAsErrors>true</TreatLibWarningAsErrors>
</Lib>
<Lib>
<TargetMachine>MachineARM</TargetMachine>
</Lib>
<Lib>
<SubSystem>Native</SubSystem>
<IgnoreAllDefaultLibraries>true</IgnoreAllDefaultLibraries>
</Lib>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release DLL|Win32'">
<ClCompile>
<PreprocessorDefinitions>WIN32;NDEBUG;_LIB;LFDS700_BUILD_TYPE_STRING="Release";%(PreprocessorDefinitions)</PreprocessorDefinitions>
<AdditionalIncludeDirectories>
</AdditionalIncludeDirectories>
<RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
<WarningLevel>Level4</WarningLevel>
<DebugInformationFormat>None</DebugInformationFormat>
<CompileAsManaged>false</CompileAsManaged>
<CompileAsWinRT>false</CompileAsWinRT>
<TreatWarningAsError>true</TreatWarningAsError>
<MultiProcessorCompilation>true</MultiProcessorCompilation>
<InlineFunctionExpansion>AnySuitable</InlineFunctionExpansion>
<IntrinsicFunctions>true</IntrinsicFunctions>
<FavorSizeOrSpeed>Speed</FavorSizeOrSpeed>
<StringPooling>true</StringPooling>
<ExceptionHandling>false</ExceptionHandling>
<BufferSecurityCheck>false</BufferSecurityCheck>
<FunctionLevelLinking>
</FunctionLevelLinking>
<EnableParallelCodeGeneration>
</EnableParallelCodeGeneration>
<EnableEnhancedInstructionSet>
</EnableEnhancedInstructionSet>
<FloatingPointExceptions>false</FloatingPointExceptions>
<CreateHotpatchableImage>
</CreateHotpatchableImage>
<RuntimeTypeInfo>false</RuntimeTypeInfo>
<OpenMPSupport>false</OpenMPSupport>
<CompileAs>CompileAsC</CompileAs>
<UseFullPaths>true</UseFullPaths>
<ErrorReporting>None</ErrorReporting>
<OmitFramePointers>true</OmitFramePointers>
<DisableSpecificWarnings>4068</DisableSpecificWarnings>
<EnableFiberSafeOptimizations>true</EnableFiberSafeOptimizations>
<AdditionalOptions>/kernel %(AdditionalOptions)</AdditionalOptions>
</ClCompile>
<Link>
<TargetMachine>MachineX86</TargetMachine>
<GenerateDebugInformation>false</GenerateDebugInformation>
<SubSystem>Native</SubSystem>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<AdditionalDependencies>kernel32.lib;msvcrt.lib</AdditionalDependencies>
<LinkStatus>
</LinkStatus>
<TreatLinkerWarningAsErrors>true</TreatLinkerWarningAsErrors>
<IgnoreAllDefaultLibraries>true</IgnoreAllDefaultLibraries>
<ModuleDefinitionFile>liblfds700.def</ModuleDefinitionFile>
<LinkErrorReporting>NoErrorReport</LinkErrorReporting>
<Driver>WDM</Driver>
</Link>
<Lib>
<TreatLibWarningAsErrors>true</TreatLibWarningAsErrors>
</Lib>
<Lib>
<TargetMachine>MachineX86</TargetMachine>
</Lib>
<Lib>
<SubSystem>Console</SubSystem>
<IgnoreAllDefaultLibraries>true</IgnoreAllDefaultLibraries>
</Lib>
<ProjectReference>
<LinkLibraryDependencies>true</LinkLibraryDependencies>
</ProjectReference>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release DLL|ARM'">
<ClCompile>
<PreprocessorDefinitions>WIN32;NDEBUG;_LIB;LFDS700_BUILD_TYPE_STRING="Release";%(PreprocessorDefinitions)</PreprocessorDefinitions>
<AdditionalIncludeDirectories>
</AdditionalIncludeDirectories>
<RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
<WarningLevel>Level4</WarningLevel>
<DebugInformationFormat>None</DebugInformationFormat>
<CompileAsManaged>false</CompileAsManaged>
<CompileAsWinRT>false</CompileAsWinRT>
<TreatWarningAsError>true</TreatWarningAsError>
<MultiProcessorCompilation>true</MultiProcessorCompilation>
<InlineFunctionExpansion>AnySuitable</InlineFunctionExpansion>
<IntrinsicFunctions>true</IntrinsicFunctions>
<FavorSizeOrSpeed>Speed</FavorSizeOrSpeed>
<StringPooling>true</StringPooling>
<ExceptionHandling>false</ExceptionHandling>
<BufferSecurityCheck>false</BufferSecurityCheck>
<FunctionLevelLinking>
</FunctionLevelLinking>
<EnableParallelCodeGeneration>
</EnableParallelCodeGeneration>
<EnableEnhancedInstructionSet>
</EnableEnhancedInstructionSet>
<FloatingPointExceptions>false</FloatingPointExceptions>
<CreateHotpatchableImage>
</CreateHotpatchableImage>
<RuntimeTypeInfo>false</RuntimeTypeInfo>
<OpenMPSupport>false</OpenMPSupport>
<CompileAs>CompileAsC</CompileAs>
<UseFullPaths>true</UseFullPaths>
<ErrorReporting>None</ErrorReporting>
<OmitFramePointers>true</OmitFramePointers>
<DisableSpecificWarnings>4068</DisableSpecificWarnings>
<EnableFiberSafeOptimizations>true</EnableFiberSafeOptimizations>
<AdditionalOptions>/kernel %(AdditionalOptions)</AdditionalOptions>
</ClCompile>
<Link>
<GenerateDebugInformation>false</GenerateDebugInformation>
<SubSystem>Native</SubSystem>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<AdditionalDependencies>kernel32.lib;msvcrt.lib</AdditionalDependencies>
<LinkStatus>
</LinkStatus>
<TreatLinkerWarningAsErrors>true</TreatLinkerWarningAsErrors>
<IgnoreAllDefaultLibraries>true</IgnoreAllDefaultLibraries>
<ModuleDefinitionFile>liblfds700.def</ModuleDefinitionFile>
<LinkErrorReporting>NoErrorReport</LinkErrorReporting>
<Driver>WDM</Driver>
<IgnoreSpecificDefaultLibraries />
</Link>
<Lib>
<TreatLibWarningAsErrors>true</TreatLibWarningAsErrors>
</Lib>
<Lib>
<TargetMachine>MachineX86</TargetMachine>
</Lib>
<Lib>
<SubSystem>Console</SubSystem>
<IgnoreAllDefaultLibraries>true</IgnoreAllDefaultLibraries>
</Lib>
<ProjectReference>
<LinkLibraryDependencies>true</LinkLibraryDependencies>
</ProjectReference>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release LIB|x64'">
<ClCompile>
<PreprocessorDefinitions>WIN32;NDEBUG;_LIB;LFDS700_BUILD_TYPE_STRING="Release";%(PreprocessorDefinitions)</PreprocessorDefinitions>
<AdditionalIncludeDirectories>
</AdditionalIncludeDirectories>
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
<WarningLevel>Level4</WarningLevel>
<DebugInformationFormat>None</DebugInformationFormat>
<CompileAsManaged>false</CompileAsManaged>
<CompileAsWinRT>false</CompileAsWinRT>
<TreatWarningAsError>true</TreatWarningAsError>
<MultiProcessorCompilation>true</MultiProcessorCompilation>
<InlineFunctionExpansion>AnySuitable</InlineFunctionExpansion>
<IntrinsicFunctions>true</IntrinsicFunctions>
<FavorSizeOrSpeed>Speed</FavorSizeOrSpeed>
<StringPooling>true</StringPooling>
<ExceptionHandling>false</ExceptionHandling>
<BufferSecurityCheck>false</BufferSecurityCheck>
<FunctionLevelLinking>
</FunctionLevelLinking>
<EnableParallelCodeGeneration>
</EnableParallelCodeGeneration>
<EnableEnhancedInstructionSet>
</EnableEnhancedInstructionSet>
<FloatingPointExceptions>false</FloatingPointExceptions>
<CreateHotpatchableImage>
</CreateHotpatchableImage>
<RuntimeTypeInfo>false</RuntimeTypeInfo>
<OpenMPSupport>false</OpenMPSupport>
<CompileAs>CompileAsC</CompileAs>
<UseFullPaths>true</UseFullPaths>
<ErrorReporting>None</ErrorReporting>
<OmitFramePointers>true</OmitFramePointers>
<DisableSpecificWarnings>4068</DisableSpecificWarnings>
<EnableFiberSafeOptimizations>true</EnableFiberSafeOptimizations>
<AdditionalOptions>/kernel %(AdditionalOptions)</AdditionalOptions>
</ClCompile>
<Link>
<GenerateDebugInformation>true</GenerateDebugInformation>
<SubSystem>Windows</SubSystem>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
</Link>
<Lib>
<TreatLibWarningAsErrors>true</TreatLibWarningAsErrors>
</Lib>
<Lib>
<TargetMachine>MachineX64</TargetMachine>
</Lib>
<Lib>
<SubSystem>Native</SubSystem>
<IgnoreAllDefaultLibraries>true</IgnoreAllDefaultLibraries>
</Lib>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release DLL|x64'">
<ClCompile>
<PreprocessorDefinitions>WIN32;NDEBUG;_LIB;LFDS700_BUILD_TYPE_STRING="Release";%(PreprocessorDefinitions)</PreprocessorDefinitions>
<AdditionalIncludeDirectories>
</AdditionalIncludeDirectories>
<RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
<WarningLevel>Level4</WarningLevel>
<DebugInformationFormat>None</DebugInformationFormat>
<CompileAsManaged>false</CompileAsManaged>
<CompileAsWinRT>false</CompileAsWinRT>
<TreatWarningAsError>true</TreatWarningAsError>
<MultiProcessorCompilation>true</MultiProcessorCompilation>
<InlineFunctionExpansion>AnySuitable</InlineFunctionExpansion>
<IntrinsicFunctions>true</IntrinsicFunctions>
<FavorSizeOrSpeed>Speed</FavorSizeOrSpeed>
<StringPooling>true</StringPooling>
<ExceptionHandling>false</ExceptionHandling>
<BufferSecurityCheck>false</BufferSecurityCheck>
<FunctionLevelLinking>
</FunctionLevelLinking>
<EnableParallelCodeGeneration>
</EnableParallelCodeGeneration>
<EnableEnhancedInstructionSet>
</EnableEnhancedInstructionSet>
<FloatingPointExceptions>false</FloatingPointExceptions>
<CreateHotpatchableImage>
</CreateHotpatchableImage>
<RuntimeTypeInfo>false</RuntimeTypeInfo>
<OpenMPSupport>false</OpenMPSupport>
<CompileAs>CompileAsC</CompileAs>
<UseFullPaths>true</UseFullPaths>
<ErrorReporting>None</ErrorReporting>
<OmitFramePointers>true</OmitFramePointers>
<DisableSpecificWarnings>4068</DisableSpecificWarnings>
<EnableFiberSafeOptimizations>true</EnableFiberSafeOptimizations>
<AdditionalOptions>/kernel %(AdditionalOptions)</AdditionalOptions>
</ClCompile>
<Link>
<GenerateDebugInformation>false</GenerateDebugInformation>
<SubSystem>Native</SubSystem>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<TreatLinkerWarningAsErrors>true</TreatLinkerWarningAsErrors>
<IgnoreAllDefaultLibraries>true</IgnoreAllDefaultLibraries>
<ModuleDefinitionFile>liblfds700.def</ModuleDefinitionFile>
<LinkErrorReporting>NoErrorReport</LinkErrorReporting>
<AdditionalDependencies>kernel32.lib;msvcrt.lib</AdditionalDependencies>
<Driver>WDM</Driver>
</Link>
<Lib>
<TreatLibWarningAsErrors>true</TreatLibWarningAsErrors>
</Lib>
<Lib>
<TargetMachine>MachineX64</TargetMachine>
</Lib>
<Lib>
<SubSystem>Console</SubSystem>
<IgnoreAllDefaultLibraries>true</IgnoreAllDefaultLibraries>
</Lib>
</ItemDefinitionGroup>
<ItemGroup>
<ClInclude Include="..\..\inc\liblfds700.h" />
<ClInclude Include="..\..\inc\liblfds700\lfds700_btree_addonly_unbalanced.h" />
<ClInclude Include="..\..\inc\liblfds700\lfds700_freelist.h" />
<ClInclude Include="..\..\inc\liblfds700\lfds700_hash_addonly.h" />
<ClInclude Include="..\..\inc\liblfds700\lfds700_list_addonly_ordered_singlylinked.h" />
<ClInclude Include="..\..\inc\liblfds700\lfds700_list_addonly_singlylinked_unordered.h" />
<ClInclude Include="..\..\inc\liblfds700\lfds700_misc.h" />
<ClInclude Include="..\..\inc\liblfds700\lfds700_porting_abstraction_layer_compiler.h" />
<ClInclude Include="..\..\inc\liblfds700\lfds700_porting_abstraction_layer_operating_system.h" />
<ClInclude Include="..\..\inc\liblfds700\lfds700_porting_abstraction_layer_processor.h" />
<ClInclude Include="..\..\inc\liblfds700\lfds700_queue.h" />
<ClInclude Include="..\..\inc\liblfds700\lfds700_queue_bounded_singleconsumer_singleproducer.h" />
<ClInclude Include="..\..\inc\liblfds700\lfds700_ringbuffer.h" />
<ClInclude Include="..\..\inc\liblfds700\lfds700_stack.h" />
<ClInclude Include="..\..\src\lfds700_btree_addonly_unbalanced\lfds700_btree_addonly_unbalanced_internal.h" />
<ClInclude Include="..\..\src\lfds700_freelist\lfds700_freelist_internal.h" />
<ClInclude Include="..\..\src\lfds700_hash_addonly\lfds700_hash_addonly_internal.h" />
<ClInclude Include="..\..\src\lfds700_list_addonly_ordered_singlylinked\lfds700_list_addonly_ordered_singlylinked_internal.h" />
<ClInclude Include="..\..\src\lfds700_list_addonly_singlylinked_unordered\lfds700_list_addonly_singlylinked_unordered_internal.h" />
<ClInclude Include="..\..\src\lfds700_misc\lfds700_misc_internal.h" />
<ClInclude Include="..\..\src\lfds700_queue\lfds700_queue_internal.h" />
<ClInclude Include="..\..\src\lfds700_queue_bounded_singleconsumer_singleproducer\lfds700_queue_bounded_singleconsumer_singleproducer_internal.h" />
<ClInclude Include="..\..\src\lfds700_ringbuffer\lfds700_ringbuffer_internal.h" />
<ClInclude Include="..\..\src\lfds700_stack\lfds700_stack_internal.h" />
</ItemGroup>
<ItemGroup>
<ClCompile Include="..\..\src\lfds700_btree_addonly_unbalanced\lfds700_btree_addonly_unbalanced_cleanup.c" />
<ClCompile Include="..\..\src\lfds700_btree_addonly_unbalanced\lfds700_btree_addonly_unbalanced_get.c" />
<ClCompile Include="..\..\src\lfds700_btree_addonly_unbalanced\lfds700_btree_addonly_unbalanced_init.c" />
<ClCompile Include="..\..\src\lfds700_btree_addonly_unbalanced\lfds700_btree_addonly_unbalanced_insert.c" />
<ClCompile Include="..\..\src\lfds700_btree_addonly_unbalanced\lfds700_btree_addonly_unbalanced_query.c" />
<ClCompile Include="..\..\src\lfds700_freelist\lfds700_freelist_cleanup.c" />
<ClCompile Include="..\..\src\lfds700_freelist\lfds700_freelist_init.c" />
<ClCompile Include="..\..\src\lfds700_freelist\lfds700_freelist_pop.c" />
<ClCompile Include="..\..\src\lfds700_freelist\lfds700_freelist_push.c" />
<ClCompile Include="..\..\src\lfds700_freelist\lfds700_freelist_query.c" />
<ClCompile Include="..\..\src\lfds700_hash_addonly\lfds700_hash_addonly_cleanup.c" />
<ClCompile Include="..\..\src\lfds700_hash_addonly\lfds700_hash_addonly_get.c" />
<ClCompile Include="..\..\src\lfds700_hash_addonly\lfds700_hash_addonly_init.c" />
<ClCompile Include="..\..\src\lfds700_hash_addonly\lfds700_hash_addonly_insert.c" />
<ClCompile Include="..\..\src\lfds700_hash_addonly\lfds700_hash_addonly_iterate.c" />
<ClCompile Include="..\..\src\lfds700_hash_addonly\lfds700_hash_addonly_query.c" />
<ClCompile Include="..\..\src\lfds700_list_addonly_ordered_singlylinked\lfds700_list_addonly_ordered_singlylinked_cleanup.c" />
<ClCompile Include="..\..\src\lfds700_list_addonly_ordered_singlylinked\lfds700_list_addonly_ordered_singlylinked_get.c" />
<ClCompile Include="..\..\src\lfds700_list_addonly_ordered_singlylinked\lfds700_list_addonly_ordered_singlylinked_init.c" />
<ClCompile Include="..\..\src\lfds700_list_addonly_ordered_singlylinked\lfds700_list_addonly_ordered_singlylinked_insert.c" />
<ClCompile Include="..\..\src\lfds700_list_addonly_ordered_singlylinked\lfds700_list_addonly_ordered_singlylinked_query.c" />
<ClCompile Include="..\..\src\lfds700_list_addonly_singlylinked_unordered\lfds700_list_addonly_singlylinked_unordered_cleanup.c" />
<ClCompile Include="..\..\src\lfds700_list_addonly_singlylinked_unordered\lfds700_list_addonly_singlylinked_unordered_get.c" />
<ClCompile Include="..\..\src\lfds700_list_addonly_singlylinked_unordered\lfds700_list_addonly_singlylinked_unordered_init.c" />
<ClCompile Include="..\..\src\lfds700_list_addonly_singlylinked_unordered\lfds700_list_addonly_singlylinked_unordered_insert.c" />
<ClCompile Include="..\..\src\lfds700_list_addonly_singlylinked_unordered\lfds700_list_addonly_singlylinked_unordered_query.c" />
<ClCompile Include="..\..\src\lfds700_misc\lfds700_misc_cleanup.c" />
<ClCompile Include="..\..\src\lfds700_misc\lfds700_misc_globals.c" />
<ClCompile Include="..\..\src\lfds700_misc\lfds700_misc_init.c" />
<ClCompile Include="..\..\src\lfds700_misc\lfds700_misc_prng.c" />
<ClCompile Include="..\..\src\lfds700_misc\lfds700_misc_query.c" />
<ClCompile Include="..\..\src\lfds700_queue\lfds700_queue_cleanup.c" />
<ClCompile Include="..\..\src\lfds700_queue\lfds700_queue_dequeue.c" />
<ClCompile Include="..\..\src\lfds700_queue\lfds700_queue_enqueue.c" />
<ClCompile Include="..\..\src\lfds700_queue\lfds700_queue_init.c" />
<ClCompile Include="..\..\src\lfds700_queue\lfds700_queue_query.c" />
<ClCompile Include="..\..\src\lfds700_queue_bounded_singleconsumer_singleproducer\lfds700_queue_bounded_singleconsumer_singleproducer_cleanup.c" />
<ClCompile Include="..\..\src\lfds700_queue_bounded_singleconsumer_singleproducer\lfds700_queue_bounded_singleconsumer_singleproducer_dequeue.c" />
<ClCompile Include="..\..\src\lfds700_queue_bounded_singleconsumer_singleproducer\lfds700_queue_bounded_singleconsumer_singleproducer_enqueue.c" />
<ClCompile Include="..\..\src\lfds700_queue_bounded_singleconsumer_singleproducer\lfds700_queue_bounded_singleconsumer_singleproducer_init.c" />
<ClCompile Include="..\..\src\lfds700_queue_bounded_singleconsumer_singleproducer\lfds700_queue_bounded_singleconsumer_singleproducer_query.c" />
<ClCompile Include="..\..\src\lfds700_ringbuffer\lfds700_ringbuffer_cleanup.c" />
<ClCompile Include="..\..\src\lfds700_ringbuffer\lfds700_ringbuffer_init.c" />
<ClCompile Include="..\..\src\lfds700_ringbuffer\lfds700_ringbuffer_query.c" />
<ClCompile Include="..\..\src\lfds700_ringbuffer\lfds700_ringbuffer_read.c" />
<ClCompile Include="..\..\src\lfds700_ringbuffer\lfds700_ringbuffer_write.c" />
<ClCompile Include="..\..\src\lfds700_stack\lfds700_stack_cleanup.c" />
<ClCompile Include="..\..\src\lfds700_stack\lfds700_stack_init.c" />
<ClCompile Include="..\..\src\lfds700_stack\lfds700_stack_pop.c" />
<ClCompile Include="..\..\src\lfds700_stack\lfds700_stack_push.c" />
<ClCompile Include="..\..\src\lfds700_stack\lfds700_stack_query.c" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<Filter Include="Source Files">
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
<Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
</Filter>
<Filter Include="Header Files">
<UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
<Extensions>h;hpp;hxx;hm;inl;inc;xsd</Extensions>
</Filter>
<Filter Include="Resource Files">
<UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
<Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav</Extensions>
</Filter>
<Filter Include="Header Files\liblfds700">
<UniqueIdentifier>{258be429-7dac-4999-b995-753aa2f0c505}</UniqueIdentifier>
</Filter>
<Filter Include="Source Files\lfds700_freelist">
<UniqueIdentifier>{469abf8e-47d8-4678-bd66-7c7e65c5f52e}</UniqueIdentifier>
</Filter>
<Filter Include="Source Files\lfds700_ringbuffer">
<UniqueIdentifier>{62ee141b-2acb-4555-b016-7be20a57f2bf}</UniqueIdentifier>
</Filter>
<Filter Include="Source Files\lfds700_stack">
<UniqueIdentifier>{19c73b0f-25e0-4166-9093-427f1dfb4f70}</UniqueIdentifier>
</Filter>
<Filter Include="Source Files\lfds700_queue">
<UniqueIdentifier>{00eb30fe-e638-4c2b-8ca1-1f09c4a0ed45}</UniqueIdentifier>
</Filter>
<Filter Include="Source Files\lfds700_queue_bounded_singleconsumer_singleproducer">
<UniqueIdentifier>{6250c4d5-ac8e-4c28-93de-0954c5bed1cb}</UniqueIdentifier>
</Filter>
<Filter Include="Source Files\lfds700_misc">
<UniqueIdentifier>{400ae4e9-2281-4549-b918-59d1a27a2d07}</UniqueIdentifier>
</Filter>
<Filter Include="Source Files\lfds700_list_addonly_ordered_singlylinked">
<UniqueIdentifier>{c45194af-7b41-4c28-bc0e-1095ec347664}</UniqueIdentifier>
</Filter>
<Filter Include="Source Files\lfds700_list_addonly_singlylinked_unordered">
<UniqueIdentifier>{8b3cbb5c-7436-429f-9b72-bae1f4721746}</UniqueIdentifier>
</Filter>
<Filter Include="Source Files\lfds700_hash_addonly">
<UniqueIdentifier>{bcbadc74-1748-4696-aad7-7fdbe5614624}</UniqueIdentifier>
</Filter>
<Filter Include="Source Files\lfds700_btree_addonly_unbalanced">
<UniqueIdentifier>{0b1fafc3-817b-4c18-8eb1-121884e3a29b}</UniqueIdentifier>
</Filter>
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\..\inc\liblfds700.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\..\src\lfds700_freelist\lfds700_freelist_internal.h">
<Filter>Source Files\lfds700_freelist</Filter>
</ClInclude>
<ClInclude Include="..\..\src\lfds700_stack\lfds700_stack_internal.h">
<Filter>Source Files\lfds700_stack</Filter>
</ClInclude>
<ClInclude Include="..\..\src\lfds700_queue\lfds700_queue_internal.h">
<Filter>Source Files\lfds700_queue</Filter>
</ClInclude>
<ClInclude Include="..\..\inc\liblfds700\lfds700_btree_addonly_unbalanced.h">
<Filter>Header Files\liblfds700</Filter>
</ClInclude>
<ClInclude Include="..\..\inc\liblfds700\lfds700_freelist.h">
<Filter>Header Files\liblfds700</Filter>
</ClInclude>
<ClInclude Include="..\..\inc\liblfds700\lfds700_hash_addonly.h">
<Filter>Header Files\liblfds700</Filter>
</ClInclude>
<ClInclude Include="..\..\inc\liblfds700\lfds700_list_addonly_ordered_singlylinked.h">
<Filter>Header Files\liblfds700</Filter>
</ClInclude>
<ClInclude Include="..\..\inc\liblfds700\lfds700_list_addonly_singlylinked_unordered.h">
<Filter>Header Files\liblfds700</Filter>
</ClInclude>
<ClInclude Include="..\..\inc\liblfds700\lfds700_misc.h">
<Filter>Header Files\liblfds700</Filter>
</ClInclude>
<ClInclude Include="..\..\inc\liblfds700\lfds700_porting_abstraction_layer_compiler.h">
<Filter>Header Files\liblfds700</Filter>
</ClInclude>
<ClInclude Include="..\..\inc\liblfds700\lfds700_porting_abstraction_layer_operating_system.h">
<Filter>Header Files\liblfds700</Filter>
</ClInclude>
<ClInclude Include="..\..\inc\liblfds700\lfds700_porting_abstraction_layer_processor.h">
<Filter>Header Files\liblfds700</Filter>
</ClInclude>
<ClInclude Include="..\..\inc\liblfds700\lfds700_queue.h">
<Filter>Header Files\liblfds700</Filter>
</ClInclude>
<ClInclude Include="..\..\inc\liblfds700\lfds700_queue_bounded_singleconsumer_singleproducer.h">
<Filter>Header Files\liblfds700</Filter>
</ClInclude>
<ClInclude Include="..\..\inc\liblfds700\lfds700_ringbuffer.h">
<Filter>Header Files\liblfds700</Filter>
</ClInclude>
<ClInclude Include="..\..\inc\liblfds700\lfds700_stack.h">
<Filter>Header Files\liblfds700</Filter>
</ClInclude>
<ClInclude Include="..\..\src\lfds700_hash_addonly\lfds700_hash_addonly_internal.h">
<Filter>Source Files\lfds700_hash_addonly</Filter>
</ClInclude>
<ClInclude Include="..\..\src\lfds700_list_addonly_ordered_singlylinked\lfds700_list_addonly_ordered_singlylinked_internal.h">
<Filter>Source Files\lfds700_list_addonly_ordered_singlylinked</Filter>
</ClInclude>
<ClInclude Include="..\..\src\lfds700_btree_addonly_unbalanced\lfds700_btree_addonly_unbalanced_internal.h">
<Filter>Source Files\lfds700_btree_addonly_unbalanced</Filter>
</ClInclude>
<ClInclude Include="..\..\src\lfds700_misc\lfds700_misc_internal.h">
<Filter>Source Files\lfds700_misc</Filter>
</ClInclude>
<ClInclude Include="..\..\src\lfds700_queue_bounded_singleconsumer_singleproducer\lfds700_queue_bounded_singleconsumer_singleproducer_internal.h">
<Filter>Source Files\lfds700_queue_bounded_singleconsumer_singleproducer</Filter>
</ClInclude>
<ClInclude Include="..\..\src\lfds700_list_addonly_singlylinked_unordered\lfds700_list_addonly_singlylinked_unordered_internal.h">
<Filter>Source Files\lfds700_list_addonly_singlylinked_unordered</Filter>
</ClInclude>
<ClInclude Include="..\..\src\lfds700_ringbuffer\lfds700_ringbuffer_internal.h">
<Filter>Source Files\lfds700_ringbuffer</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ClCompile Include="..\..\src\lfds700_freelist\lfds700_freelist_cleanup.c">
<Filter>Source Files\lfds700_freelist</Filter>
</ClCompile>
<ClCompile Include="..\..\src\lfds700_freelist\lfds700_freelist_init.c">
<Filter>Source Files\lfds700_freelist</Filter>
</ClCompile>
<ClCompile Include="..\..\src\lfds700_freelist\lfds700_freelist_pop.c">
<Filter>Source Files\lfds700_freelist</Filter>
</ClCompile>
<ClCompile Include="..\..\src\lfds700_freelist\lfds700_freelist_push.c">
<Filter>Source Files\lfds700_freelist</Filter>
</ClCompile>
<ClCompile Include="..\..\src\lfds700_freelist\lfds700_freelist_query.c">
<Filter>Source Files\lfds700_freelist</Filter>
</ClCompile>
<ClCompile Include="..\..\src\lfds700_stack\lfds700_stack_cleanup.c">
<Filter>Source Files\lfds700_stack</Filter>
</ClCompile>
<ClCompile Include="..\..\src\lfds700_stack\lfds700_stack_init.c">
<Filter>Source Files\lfds700_stack</Filter>
</ClCompile>
<ClCompile Include="..\..\src\lfds700_stack\lfds700_stack_pop.c">
<Filter>Source Files\lfds700_stack</Filter>
</ClCompile>
<ClCompile Include="..\..\src\lfds700_stack\lfds700_stack_push.c">
<Filter>Source Files\lfds700_stack</Filter>
</ClCompile>
<ClCompile Include="..\..\src\lfds700_stack\lfds700_stack_query.c">
<Filter>Source Files\lfds700_stack</Filter>
</ClCompile>
<ClCompile Include="..\..\src\lfds700_queue\lfds700_queue_cleanup.c">
<Filter>Source Files\lfds700_queue</Filter>
</ClCompile>
<ClCompile Include="..\..\src\lfds700_queue\lfds700_queue_dequeue.c">
<Filter>Source Files\lfds700_queue</Filter>
</ClCompile>
<ClCompile Include="..\..\src\lfds700_queue\lfds700_queue_enqueue.c">
<Filter>Source Files\lfds700_queue</Filter>
</ClCompile>
<ClCompile Include="..\..\src\lfds700_queue\lfds700_queue_init.c">
<Filter>Source Files\lfds700_queue</Filter>
</ClCompile>
<ClCompile Include="..\..\src\lfds700_queue\lfds700_queue_query.c">
<Filter>Source Files\lfds700_queue</Filter>
</ClCompile>
<ClCompile Include="..\..\src\lfds700_hash_addonly\lfds700_hash_addonly_cleanup.c">
<Filter>Source Files\lfds700_hash_addonly</Filter>
</ClCompile>
<ClCompile Include="..\..\src\lfds700_hash_addonly\lfds700_hash_addonly_get.c">
<Filter>Source Files\lfds700_hash_addonly</Filter>
</ClCompile>
<ClCompile Include="..\..\src\lfds700_hash_addonly\lfds700_hash_addonly_init.c">
<Filter>Source Files\lfds700_hash_addonly</Filter>
</ClCompile>
<ClCompile Include="..\..\src\lfds700_hash_addonly\lfds700_hash_addonly_insert.c">
<Filter>Source Files\lfds700_hash_addonly</Filter>
</ClCompile>
<ClCompile Include="..\..\src\lfds700_hash_addonly\lfds700_hash_addonly_iterate.c">
<Filter>Source Files\lfds700_hash_addonly</Filter>
</ClCompile>
<ClCompile Include="..\..\src\lfds700_hash_addonly\lfds700_hash_addonly_query.c">
<Filter>Source Files\lfds700_hash_addonly</Filter>
</ClCompile>
<ClCompile Include="..\..\src\lfds700_list_addonly_ordered_singlylinked\lfds700_list_addonly_ordered_singlylinked_cleanup.c">
<Filter>Source Files\lfds700_list_addonly_ordered_singlylinked</Filter>
</ClCompile>
<ClCompile Include="..\..\src\lfds700_list_addonly_ordered_singlylinked\lfds700_list_addonly_ordered_singlylinked_get.c">
<Filter>Source Files\lfds700_list_addonly_ordered_singlylinked</Filter>
</ClCompile>
<ClCompile Include="..\..\src\lfds700_list_addonly_ordered_singlylinked\lfds700_list_addonly_ordered_singlylinked_init.c">
<Filter>Source Files\lfds700_list_addonly_ordered_singlylinked</Filter>
</ClCompile>
<ClCompile Include="..\..\src\lfds700_list_addonly_ordered_singlylinked\lfds700_list_addonly_ordered_singlylinked_insert.c">
<Filter>Source Files\lfds700_list_addonly_ordered_singlylinked</Filter>
</ClCompile>
<ClCompile Include="..\..\src\lfds700_list_addonly_ordered_singlylinked\lfds700_list_addonly_ordered_singlylinked_query.c">
<Filter>Source Files\lfds700_list_addonly_ordered_singlylinked</Filter>
</ClCompile>
<ClCompile Include="..\..\src\lfds700_btree_addonly_unbalanced\lfds700_btree_addonly_unbalanced_cleanup.c">
<Filter>Source Files\lfds700_btree_addonly_unbalanced</Filter>
</ClCompile>
<ClCompile Include="..\..\src\lfds700_btree_addonly_unbalanced\lfds700_btree_addonly_unbalanced_get.c">
<Filter>Source Files\lfds700_btree_addonly_unbalanced</Filter>
</ClCompile>
<ClCompile Include="..\..\src\lfds700_btree_addonly_unbalanced\lfds700_btree_addonly_unbalanced_init.c">
<Filter>Source Files\lfds700_btree_addonly_unbalanced</Filter>
</ClCompile>
<ClCompile Include="..\..\src\lfds700_btree_addonly_unbalanced\lfds700_btree_addonly_unbalanced_insert.c">
<Filter>Source Files\lfds700_btree_addonly_unbalanced</Filter>
</ClCompile>
<ClCompile Include="..\..\src\lfds700_btree_addonly_unbalanced\lfds700_btree_addonly_unbalanced_query.c">
<Filter>Source Files\lfds700_btree_addonly_unbalanced</Filter>
</ClCompile>
<ClCompile Include="..\..\src\lfds700_misc\lfds700_misc_cleanup.c">
<Filter>Source Files\lfds700_misc</Filter>
</ClCompile>
<ClCompile Include="..\..\src\lfds700_misc\lfds700_misc_globals.c">
<Filter>Source Files\lfds700_misc</Filter>
</ClCompile>
<ClCompile Include="..\..\src\lfds700_misc\lfds700_misc_init.c">
<Filter>Source Files\lfds700_misc</Filter>
</ClCompile>
<ClCompile Include="..\..\src\lfds700_misc\lfds700_misc_prng.c">
<Filter>Source Files\lfds700_misc</Filter>
</ClCompile>
<ClCompile Include="..\..\src\lfds700_misc\lfds700_misc_query.c">
<Filter>Source Files\lfds700_misc</Filter>
</ClCompile>
<ClCompile Include="..\..\src\lfds700_queue_bounded_singleconsumer_singleproducer\lfds700_queue_bounded_singleconsumer_singleproducer_cleanup.c">
<Filter>Source Files\lfds700_queue_bounded_singleconsumer_singleproducer</Filter>
</ClCompile>
<ClCompile Include="..\..\src\lfds700_queue_bounded_singleconsumer_singleproducer\lfds700_queue_bounded_singleconsumer_singleproducer_dequeue.c">
<Filter>Source Files\lfds700_queue_bounded_singleconsumer_singleproducer</Filter>
</ClCompile>
<ClCompile Include="..\..\src\lfds700_queue_bounded_singleconsumer_singleproducer\lfds700_queue_bounded_singleconsumer_singleproducer_enqueue.c">
<Filter>Source Files\lfds700_queue_bounded_singleconsumer_singleproducer</Filter>
</ClCompile>
<ClCompile Include="..\..\src\lfds700_queue_bounded_singleconsumer_singleproducer\lfds700_queue_bounded_singleconsumer_singleproducer_init.c">
<Filter>Source Files\lfds700_queue_bounded_singleconsumer_singleproducer</Filter>
</ClCompile>
<ClCompile Include="..\..\src\lfds700_queue_bounded_singleconsumer_singleproducer\lfds700_queue_bounded_singleconsumer_singleproducer_query.c">
<Filter>Source Files\lfds700_queue_bounded_singleconsumer_singleproducer</Filter>
</ClCompile>
<ClCompile Include="..\..\src\lfds700_list_addonly_singlylinked_unordered\lfds700_list_addonly_singlylinked_unordered_cleanup.c">
<Filter>Source Files\lfds700_list_addonly_singlylinked_unordered</Filter>
</ClCompile>
<ClCompile Include="..\..\src\lfds700_list_addonly_singlylinked_unordered\lfds700_list_addonly_singlylinked_unordered_get.c">
<Filter>Source Files\lfds700_list_addonly_singlylinked_unordered</Filter>
</ClCompile>
<ClCompile Include="..\..\src\lfds700_list_addonly_singlylinked_unordered\lfds700_list_addonly_singlylinked_unordered_init.c">
<Filter>Source Files\lfds700_list_addonly_singlylinked_unordered</Filter>
</ClCompile>
<ClCompile Include="..\..\src\lfds700_list_addonly_singlylinked_unordered\lfds700_list_addonly_singlylinked_unordered_insert.c">
<Filter>Source Files\lfds700_list_addonly_singlylinked_unordered</Filter>
</ClCompile>
<ClCompile Include="..\..\src\lfds700_list_addonly_singlylinked_unordered\lfds700_list_addonly_singlylinked_unordered_query.c">
<Filter>Source Files\lfds700_list_addonly_singlylinked_unordered</Filter>
</ClCompile>
<ClCompile Include="..\..\src\lfds700_ringbuffer\lfds700_ringbuffer_cleanup.c">
<Filter>Source Files\lfds700_ringbuffer</Filter>
</ClCompile>
<ClCompile Include="..\..\src\lfds700_ringbuffer\lfds700_ringbuffer_init.c">
<Filter>Source Files\lfds700_ringbuffer</Filter>
</ClCompile>
<ClCompile Include="..\..\src\lfds700_ringbuffer\lfds700_ringbuffer_query.c">
<Filter>Source Files\lfds700_ringbuffer</Filter>
</ClCompile>
<ClCompile Include="..\..\src\lfds700_ringbuffer\lfds700_ringbuffer_read.c">
<Filter>Source Files\lfds700_ringbuffer</Filter>
</ClCompile>
<ClCompile Include="..\..\src\lfds700_ringbuffer\lfds700_ringbuffer_write.c">
<Filter>Source Files\lfds700_ringbuffer</Filter>
</ClCompile>
</ItemGroup>
</Project>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup />
</Project>
\ No newline at end of file
#include "liblfds700_internal.h"
/****************************************************************************/
DRIVER_INITIALIZE DriverEntry;
/****************************************************************************/
#pragma warning( disable : 4100 )
NTSTATUS DriverEntry( struct _DRIVER_OBJECT *DriverObject, PUNICODE_STRING RegistryPath )
{
return( STATUS_SUCCESS );
}
#pragma warning( default : 4100 )
EXPORTS
lfds700_btree_au_init_valid_on_current_logical_core = lfds700_btree_au_init_valid_on_current_logical_core
lfds700_btree_au_cleanup = lfds700_btree_au_cleanup
lfds700_btree_au_insert = lfds700_btree_au_insert
lfds700_btree_au_get_by_absolute_position_and_then_by_relative_position = lfds700_btree_au_get_by_absolute_position_and_then_by_relative_position
lfds700_btree_au_get_by_absolute_position = lfds700_btree_au_get_by_absolute_position
lfds700_btree_au_get_by_relative_position = lfds700_btree_au_get_by_relative_position
lfds700_btree_au_get_by_key = lfds700_btree_au_get_by_key
lfds700_btree_au_query = lfds700_btree_au_query
lfds700_freelist_init_valid_on_current_logical_core = lfds700_freelist_init_valid_on_current_logical_core
lfds700_freelist_cleanup = lfds700_freelist_cleanup
lfds700_freelist_push = lfds700_freelist_push
lfds700_freelist_pop = lfds700_freelist_pop
lfds700_freelist_query = lfds700_freelist_query
lfds700_hash_a_init_valid_on_current_logical_core = lfds700_hash_a_init_valid_on_current_logical_core
lfds700_hash_a_cleanup = lfds700_hash_a_cleanup
lfds700_hash_a_insert = lfds700_hash_a_insert
lfds700_hash_a_get_by_key = lfds700_hash_a_get_by_key
lfds700_hash_a_iterate_init = lfds700_hash_a_iterate_init
lfds700_hash_a_iterate = lfds700_hash_a_iterate
lfds700_hash_a_query = lfds700_hash_a_query
lfds700_list_aos_init_valid_on_current_logical_core = lfds700_list_aos_init_valid_on_current_logical_core
lfds700_list_aos_cleanup = lfds700_list_aos_cleanup
lfds700_list_aos_insert = lfds700_list_aos_insert
lfds700_list_aos_get_by_key = lfds700_list_aos_get_by_key
lfds700_list_aos_query = lfds700_list_aos_query
lfds700_list_asu_init_valid_on_current_logical_core = lfds700_list_asu_init_valid_on_current_logical_core
lfds700_list_asu_cleanup = lfds700_list_asu_cleanup
lfds700_list_asu_insert_at_position = lfds700_list_asu_insert_at_position
lfds700_list_asu_insert_at_start = lfds700_list_asu_insert_at_start
lfds700_list_asu_insert_at_end = lfds700_list_asu_insert_at_end
lfds700_list_asu_insert_after_element = lfds700_list_asu_insert_after_element
lfds700_list_asu_get_by_key = lfds700_list_asu_get_by_key
lfds700_list_asu_query = lfds700_list_asu_query
lfds700_misc_library_init_valid_on_current_logical_core = lfds700_misc_library_init_valid_on_current_logical_core
lfds700_misc_library_cleanup = lfds700_misc_library_cleanup
lfds700_misc_prng_init = lfds700_misc_prng_init
lfds700_misc_query = lfds700_misc_query
lfds700_queue_init_valid_on_current_logical_core = lfds700_queue_init_valid_on_current_logical_core
lfds700_queue_cleanup = lfds700_queue_cleanup
lfds700_queue_enqueue = lfds700_queue_enqueue
lfds700_queue_dequeue = lfds700_queue_dequeue
lfds700_queue_query = lfds700_queue_query
lfds700_queue_bss_init_valid_on_current_logical_core = lfds700_queue_bss_init_valid_on_current_logical_core
lfds700_queue_bss_cleanup = lfds700_queue_bss_cleanup
lfds700_queue_bss_enqueue = lfds700_queue_bss_enqueue
lfds700_queue_bss_dequeue = lfds700_queue_bss_dequeue
lfds700_queue_bss_query = lfds700_queue_bss_query
lfds700_ringbuffer_init_valid_on_current_logical_core = lfds700_ringbuffer_init_valid_on_current_logical_core
lfds700_ringbuffer_cleanup = lfds700_ringbuffer_cleanup
lfds700_ringbuffer_read = lfds700_ringbuffer_read
lfds700_ringbuffer_write = lfds700_ringbuffer_write
lfds700_ringbuffer_query = lfds700_ringbuffer_query
lfds700_stack_init_valid_on_current_logical_core = lfds700_stack_init_valid_on_current_logical_core
lfds700_stack_cleanup = lfds700_stack_cleanup
lfds700_stack_push = lfds700_stack_push
lfds700_stack_pop = lfds700_stack_pop
lfds700_stack_query = lfds700_stack_query
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.
@echo off
rmdir /q /s single_dir_for_windows_kernel 1>nul 2>nul
mkdir single_dir_for_windows_kernel 1>nul 2>nul
copy /y ..\..\src\lfds700_btree_addonly_unbalanced\* single_dir_for_windows_kernel\ 1>nul 2>nul
copy /y ..\..\src\lfds700_freelist\* single_dir_for_windows_kernel\ 1>nul 2>nul
copy /y ..\..\src\lfds700_hash_addonly\* single_dir_for_windows_kernel\ 1>nul 2>nul
copy /y ..\..\src\lfds700_list_addonly_ordered_singlylinked\* single_dir_for_windows_kernel\ 1>nul 2>nul
copy /y ..\..\src\lfds700_list_addonly_singlylinked_unordered\* single_dir_for_windows_kernel\ 1>nul 2>nul
copy /y ..\..\src\lfds700_misc\* single_dir_for_windows_kernel\ 1>nul 2>nul
copy /y ..\..\src\lfds700_queue\* single_dir_for_windows_kernel\ 1>nul 2>nul
copy /y ..\..\src\lfds700_queue_bounded_singleconsumer_singleproducer\* single_dir_for_windows_kernel\ 1>nul 2>nul
copy /y ..\..\src\lfds700_ringbuffer\* single_dir_for_windows_kernel\ 1>nul 2>nul
copy /y ..\..\src\lfds700_stack\* single_dir_for_windows_kernel\ 1>nul 2>nul
copy /y ..\..\src\liblfds700_internal.h single_dir_for_windows_kernel\ 1>nul 2>nul
copy /y driver_entry_renamed_to_avoid_compiler_warning.c single_dir_for_windows_kernel\driver_entry.c 1>nul 2>nul
copy /y sources.dynamic single_dir_for_windows_kernel\sources 1>nul 2>nul
echo Windows kernel dynamic library build directory structure created.
echo (Note the effects of this batch file are idempotent).
@echo off
rmdir /q /s single_dir_for_windows_kernel 1>nul 2>nul
mkdir single_dir_for_windows_kernel 1>nul 2>nul
copy /y ..\..\src\lfds700_btree_addonly_unbalanced\* single_dir_for_windows_kernel\ 1>nul 2>nul
copy /y ..\..\src\lfds700_freelist\* single_dir_for_windows_kernel\ 1>nul 2>nul
copy /y ..\..\src\lfds700_hash_addonly\* single_dir_for_windows_kernel\ 1>nul 2>nul
copy /y ..\..\src\lfds700_list_addonly_ordered_singlylinked\* single_dir_for_windows_kernel\ 1>nul 2>nul
copy /y ..\..\src\lfds700_list_addonly_singlylinked_unordered\* single_dir_for_windows_kernel\ 1>nul 2>nul
copy /y ..\..\src\lfds700_misc\* single_dir_for_windows_kernel\ 1>nul 2>nul
copy /y ..\..\src\lfds700_queue\* single_dir_for_windows_kernel\ 1>nul 2>nul
copy /y ..\..\src\lfds700_queue_bounded_singleconsumer_singleproducer\* single_dir_for_windows_kernel\ 1>nul 2>nul
copy /y ..\..\src\lfds700_ringbuffer\* single_dir_for_windows_kernel\ 1>nul 2>nul
copy /y ..\..\src\lfds700_stack\* single_dir_for_windows_kernel\ 1>nul 2>nul
copy /y ..\..\src\liblfds700_internal.h single_dir_for_windows_kernel\ 1>nul 2>nul
copy /y sources.static single_dir_for_windows_kernel\sources 1>nul 2>nul
echo Windows kernel static library build directory structure created.
echo (Note the effects of this batch file are idempotent).
MSC_WARNING_LEVEL = /WX /wd4127 /W4
DLLDEF = ../liblfds700.def
TARGETNAME = liblfds700
TARGETPATH = ../../../bin/
TARGETTYPE = EXPORT_DRIVER
UMTYPE = nt
USER_C_FLAGS = /D_KERNEL_MODE
INCLUDES = ../../../inc/
SOURCES = lfds700_hash_addonly_cleanup.c \
lfds700_hash_addonly_get.c \
lfds700_hash_addonly_init.c \
lfds700_hash_addonly_insert.c \
lfds700_hash_addonly_iterate.c \
lfds700_hash_addonly_query.c \
lfds700_list_addonly_ordered_singlylinked_cleanup.c \
lfds700_list_addonly_ordered_singlylinked_get.c \
lfds700_list_addonly_ordered_singlylinked_init.c \
lfds700_list_addonly_ordered_singlylinked_insert.c \
lfds700_list_addonly_ordered_singlylinked_query.c \
lfds700_list_addonly_singlylinked_unordered_cleanup.c \
lfds700_list_addonly_singlylinked_unordered_get.c \
lfds700_list_addonly_singlylinked_unordered_init.c \
lfds700_list_addonly_singlylinked_unordered_insert.c \
lfds700_list_addonly_singlylinked_unordered_query.c \
lfds700_btree_addonly_unbalanced_cleanup.c \
lfds700_btree_addonly_unbalanced_get.c \
lfds700_btree_addonly_unbalanced_init.c \
lfds700_btree_addonly_unbalanced_insert.c \
lfds700_btree_addonly_unbalanced_query.c \
lfds700_freelist_cleanup.c \
lfds700_freelist_init.c \
lfds700_freelist_pop.c \
lfds700_freelist_push.c \
lfds700_freelist_query.c \
lfds700_misc_cleanup.c \
lfds700_misc_globals.c \
lfds700_misc_init.c \
lfds700_misc_prng.c \
lfds700_misc_query.c \
lfds700_queue_cleanup.c \
lfds700_queue_dequeue.c \
lfds700_queue_enqueue.c \
lfds700_queue_init.c \
lfds700_queue_query.c \
lfds700_queue_bounded_singleconsumer_singleproducer_cleanup.c \
lfds700_queue_bounded_singleconsumer_singleproducer_dequeue.c \
lfds700_queue_bounded_singleconsumer_singleproducer_enqueue.c \
lfds700_queue_bounded_singleconsumer_singleproducer_init.c \
lfds700_queue_bounded_singleconsumer_singleproducer_query.c \
lfds700_ringbuffer_cleanup.c \
lfds700_ringbuffer_init.c \
lfds700_ringbuffer_query.c \
lfds700_ringbuffer_read.c \
lfds700_ringbuffer_write.c \
lfds700_stack_cleanup.c \
lfds700_stack_init.c \
lfds700_stack_pop.c \
lfds700_stack_push.c \
lfds700_stack_query.c \
driver_entry.c
MSC_WARNING_LEVEL = /WX /wd4127 /W4
TARGETNAME = liblfds700
TARGETPATH = ../../../bin/
TARGETTYPE = DRIVER_LIBRARY
UMTYPE = nt
USER_C_FLAGS = /D_KERNEL_MODE
INCLUDES = ../../../inc/
SOURCES = lfds700_hash_addonly_cleanup.c \
lfds700_hash_addonly_get.c \
lfds700_hash_addonly_init.c \
lfds700_hash_addonly_insert.c \
lfds700_hash_addonly_iterate.c \
lfds700_hash_addonly_query.c \
lfds700_list_addonly_ordered_singlylinked_cleanup.c \
lfds700_list_addonly_ordered_singlylinked_get.c \
lfds700_list_addonly_ordered_singlylinked_init.c \
lfds700_list_addonly_ordered_singlylinked_insert.c \
lfds700_list_addonly_ordered_singlylinked_query.c \
lfds700_list_addonly_singlylinked_unordered_cleanup.c \
lfds700_list_addonly_singlylinked_unordered_get.c \
lfds700_list_addonly_singlylinked_unordered_init.c \
lfds700_list_addonly_singlylinked_unordered_insert.c \
lfds700_list_addonly_singlylinked_unordered_query.c \
lfds700_btree_addonly_unbalanced_cleanup.c \
lfds700_btree_addonly_unbalanced_get.c \
lfds700_btree_addonly_unbalanced_init.c \
lfds700_btree_addonly_unbalanced_insert.c \
lfds700_btree_addonly_unbalanced_query.c \
lfds700_freelist_cleanup.c \
lfds700_freelist_init.c \
lfds700_freelist_pop.c \
lfds700_freelist_push.c \
lfds700_freelist_query.c \
lfds700_misc_cleanup.c \
lfds700_misc_globals.c \
lfds700_misc_init.c \
lfds700_misc_prng.c \
lfds700_misc_query.c \
lfds700_queue_cleanup.c \
lfds700_queue_dequeue.c \
lfds700_queue_enqueue.c \
lfds700_queue_init.c \
lfds700_queue_query.c \
lfds700_queue_bounded_singleconsumer_singleproducer_cleanup.c \
lfds700_queue_bounded_singleconsumer_singleproducer_dequeue.c \
lfds700_queue_bounded_singleconsumer_singleproducer_enqueue.c \
lfds700_queue_bounded_singleconsumer_singleproducer_init.c \
lfds700_queue_bounded_singleconsumer_singleproducer_query.c \
lfds700_ringbuffer_cleanup.c \
lfds700_ringbuffer_init.c \
lfds700_ringbuffer_query.c \
lfds700_ringbuffer_read.c \
lfds700_ringbuffer_write.c \
lfds700_stack_cleanup.c \
lfds700_stack_init.c \
lfds700_stack_pop.c \
lfds700_stack_push.c \
lfds700_stack_query.c
#ifndef LIBLFDS700_H
/***** defines *****/
#define LIBLFDS700_H
/***** pragmas on *****/
#pragma warning( disable : 4324 ) // TRD : 4324 disables MSVC warnings for structure alignment padding due to alignment specifiers
#pragma prefast( disable : 28113 28182 28183, "blah" )
/***** includes *****/
#include "liblfds700/lfds700_porting_abstraction_layer_compiler.h"
#include "liblfds700/lfds700_porting_abstraction_layer_operating_system.h"
#include "liblfds700/lfds700_porting_abstraction_layer_processor.h"
#include "liblfds700/lfds700_misc.h" // TRD : everything after depends on misc
#include "liblfds700/lfds700_btree_addonly_unbalanced.h" // TRD : hash_addonly depends on btree_addonly_unbalanced
#include "liblfds700/lfds700_freelist.h"
#include "liblfds700/lfds700_hash_addonly.h"
#include "liblfds700/lfds700_list_addonly_ordered_singlylinked.h"
#include "liblfds700/lfds700_list_addonly_singlylinked_unordered.h"
#include "liblfds700/lfds700_queue.h"
#include "liblfds700/lfds700_queue_bounded_singleconsumer_singleproducer.h"
#include "liblfds700/lfds700_ringbuffer.h"
#include "liblfds700/lfds700_stack.h"
/***** pragmas off *****/
#pragma warning( default : 4324 )
#endif
/***** defines *****/
#define LFDS700_BTREE_AU_GET_KEY_FROM_ELEMENT( btree_au_element ) ( (btree_au_element).key )
#define LFDS700_BTREE_AU_SET_KEY_IN_ELEMENT( btree_au_element, new_key ) ( (btree_au_element).key = (void *) (lfds700_pal_uint_t) (new_key) )
#define LFDS700_BTREE_AU_GET_VALUE_FROM_ELEMENT( btree_au_element ) ( LFDS700_MISC_BARRIER_LOAD, (btree_au_element).value )
#define LFDS700_BTREE_AU_SET_VALUE_IN_ELEMENT( btree_au_element, new_value ) { void *local_new_value = (void *) (lfds700_pal_uint_t) (new_value); LFDS700_PAL_ATOMIC_EXCHANGE( &(btree_au_element).value, &local_new_value ); }
#define LFDS700_BTREE_AU_GET_USER_STATE_FROM_STATE( btree_au_state ) ( (btree_au_state).user_state )
/***** enums *****/
enum lfds700_btree_au_absolute_position
{
LFDS700_BTREE_AU_ABSOLUTE_POSITION_ROOT,
LFDS700_BTREE_AU_ABSOLUTE_POSITION_SMALLEST_IN_TREE,
LFDS700_BTREE_AU_ABSOLUTE_POSITION_LARGEST_IN_TREE
};
enum lfds700_btree_au_existing_key
{
LFDS700_BTREE_AU_EXISTING_KEY_OVERWRITE,
LFDS700_BTREE_AU_EXISTING_KEY_FAIL
};
enum lfds700_btree_au_insert_result
{
LFDS700_BTREE_AU_INSERT_RESULT_FAILURE_EXISTING_KEY,
LFDS700_BTREE_AU_INSERT_RESULT_SUCCESS_OVERWRITE,
LFDS700_BTREE_AU_INSERT_RESULT_SUCCESS
};
enum lfds700_btree_au_relative_position
{
LFDS700_BTREE_AU_RELATIVE_POSITION_UP,
LFDS700_BTREE_AU_RELATIVE_POSITION_LEFT,
LFDS700_BTREE_AU_RELATIVE_POSITION_RIGHT,
LFDS700_BTREE_AU_RELATIVE_POSITION_SMALLEST_ELEMENT_BELOW_CURRENT_ELEMENT,
LFDS700_BTREE_AU_RELATIVE_POSITION_LARGEST_ELEMENT_BELOW_CURRENT_ELEMENT,
LFDS700_BTREE_AU_RELATIVE_POSITION_NEXT_SMALLER_ELEMENT_IN_ENTIRE_TREE,
LFDS700_BTREE_AU_RELATIVE_POSITION_NEXT_LARGER_ELEMENT_IN_ENTIRE_TREE
};
enum lfds700_btree_au_query
{
LFDS700_BTREE_AU_QUERY_GET_POTENTIALLY_INACCURATE_COUNT,
LFDS700_BTREE_AU_QUERY_SINGLETHREADED_VALIDATE
};
/***** structs *****/
struct lfds700_btree_au_element
{
struct lfds700_btree_au_element LFDS700_PAL_ALIGN(LFDS700_PAL_ATOMIC_ISOLATION_IN_BYTES)
*volatile left,
*volatile right,
*volatile up;
void LFDS700_PAL_ALIGN(LFDS700_PAL_ATOMIC_ISOLATION_IN_BYTES)
*volatile value;
void LFDS700_PAL_ALIGN(LFDS700_PAL_ATOMIC_ISOLATION_IN_BYTES)
*key;
};
struct lfds700_btree_au_state
{
struct lfds700_btree_au_element LFDS700_PAL_ALIGN(LFDS700_PAL_ATOMIC_ISOLATION_IN_BYTES)
*volatile root;
int LFDS700_PAL_ALIGN(LFDS700_PAL_ATOMIC_ISOLATION_IN_BYTES)
(*key_compare_function)( void const *new_key, void const *existing_key );
enum lfds700_btree_au_existing_key
existing_key;
void
*user_state;
};
/***** public prototypes *****/
void lfds700_btree_au_init_valid_on_current_logical_core( struct lfds700_btree_au_state *baus,
int (*key_compare_function)(void const *new_key, void const *existing_key),
enum lfds700_btree_au_existing_key existing_key,
void *user_state );
// TRD : used in conjunction with the #define LFDS700_MISC_MAKE_VALID_ON_CURRENT_LOGICAL_CORE_INITS_COMPLETED_BEFORE_NOW_ON_ANY_OTHER_LOGICAL_CORE
void lfds700_btree_au_cleanup( struct lfds700_btree_au_state *baus,
void (*element_cleanup_callback)(struct lfds700_btree_au_state *baus, struct lfds700_btree_au_element *baue) );
enum lfds700_btree_au_insert_result lfds700_btree_au_insert( struct lfds700_btree_au_state *baus,
struct lfds700_btree_au_element *baue,
struct lfds700_btree_au_element **existing_baue,
struct lfds700_misc_prng_state *ps );
// TRD : if a link collides with an existing key and existing_baue is non-NULL, existing_baue is set to the existing element
int lfds700_btree_au_get_by_key( struct lfds700_btree_au_state *baus,
void *key,
struct lfds700_btree_au_element **baue );
int lfds700_btree_au_get_by_absolute_position_and_then_by_relative_position( struct lfds700_btree_au_state *baus,
struct lfds700_btree_au_element **baue,
enum lfds700_btree_au_absolute_position absolute_position,
enum lfds700_btree_au_relative_position relative_position );
// TRD : if *baue is NULL, we get the element at position, otherwise we move from *baue according to direction
int lfds700_btree_au_get_by_absolute_position( struct lfds700_btree_au_state *baus,
struct lfds700_btree_au_element **baue,
enum lfds700_btree_au_absolute_position absolute_position );
int lfds700_btree_au_get_by_relative_position( struct lfds700_btree_au_element **baue,
enum lfds700_btree_au_relative_position relative_position );
void lfds700_btree_au_query( struct lfds700_btree_au_state *baus,
enum lfds700_btree_au_query query_type,
void *query_input,
void *query_output );
/***** defines *****/
#define LFDS700_FREELIST_GET_KEY_FROM_ELEMENT( freelist_element ) ( (freelist_element).key )
#define LFDS700_FREELIST_SET_KEY_IN_ELEMENT( freelist_element, new_key ) ( (freelist_element).key = (void *) (lfds700_pal_uint_t) (new_key) )
#define LFDS700_FREELIST_GET_VALUE_FROM_ELEMENT( freelist_element ) ( (freelist_element).value )
#define LFDS700_FREELIST_SET_VALUE_IN_ELEMENT( freelist_element, new_value ) ( (freelist_element).value = (void *) (lfds700_pal_uint_t) (new_value) )
#define LFDS700_FREELIST_GET_USER_STATE_FROM_STATE( freelist_state ) ( (freelist_state).user_state )
/***** enums *****/
enum lfds700_freelist_query
{
LFDS700_FREELIST_QUERY_SINGLETHREADED_GET_COUNT,
LFDS700_FREELIST_QUERY_SINGLETHREADED_VALIDATE
};
/***** structures *****/
struct lfds700_freelist_element
{
struct lfds700_freelist_element
*volatile next;
void
*key,
*value;
};
struct lfds700_freelist_state
{
struct lfds700_freelist_element LFDS700_PAL_ALIGN(LFDS700_PAL_ATOMIC_ISOLATION_IN_BYTES)
*volatile top[PAC_SIZE];
void LFDS700_PAL_ALIGN(LFDS700_PAL_ATOMIC_ISOLATION_IN_BYTES)
*user_state;
};
/***** public prototypes *****/
void lfds700_freelist_init_valid_on_current_logical_core( struct lfds700_freelist_state *fs, void *user_state );
// TRD : used in conjunction with the #define LFDS700_MISC_MAKE_VALID_ON_CURRENT_LOGICAL_CORE_INITS_COMPLETED_BEFORE_NOW_ON_ANY_OTHER_LOGICAL_CORE
void lfds700_freelist_cleanup( struct lfds700_freelist_state *fs,
void (*element_cleanup_callback)(struct lfds700_freelist_state *fs, struct lfds700_freelist_element *fe) );
void lfds700_freelist_push( struct lfds700_freelist_state *fs,
struct lfds700_freelist_element *fe,
struct lfds700_misc_prng_state *ps );
int lfds700_freelist_pop( struct lfds700_freelist_state *fs,
struct lfds700_freelist_element **fe,
struct lfds700_misc_prng_state *ps );
void lfds700_freelist_query( struct lfds700_freelist_state *fs,
enum lfds700_freelist_query query_type,
void *query_input,
void *query_output );
/***** defines *****/
#define LFDS700_HASH_A_GET_KEY_FROM_ELEMENT( hash_a_element ) ( (hash_a_element).key )
#define LFDS700_HASH_A_SET_KEY_IN_ELEMENT( hash_a_element, new_key ) ( (hash_a_element).key = (void *) (lfds700_pal_uint_t) (new_key) )
#define LFDS700_HASH_A_GET_VALUE_FROM_ELEMENT( hash_a_element ) ( LFDS700_MISC_BARRIER_LOAD, (hash_a_element).value )
#define LFDS700_HASH_A_SET_VALUE_IN_ELEMENT( hash_a_element, new_value ) { void *local_new_value = (void *) (lfds700_pal_uint_t) (new_value); LFDS700_PAL_ATOMIC_EXCHANGE( &(hash_a_element).value, &local_new_value ); }
#define LFDS700_HASH_A_GET_USER_STATE_FROM_STATE( hash_a_state ) ( (hash_a_state).user_state )
#define LFDS700_HASH_A_32BIT_HASH_FUNCTION( data, data_length_in_bytes, hash ) { \
lfds700_pal_uint_t \
loop; \
\
for( loop = 0 ; loop < (data_length_in_bytes) ; loop++ ) \
{ \
(hash) += *( (char unsigned *) (data) + loop ); \
(hash) += ((hash) << 10); \
(hash) ^= ((hash) >> 6); \
} \
\
(hash) += ((hash) << 3); \
(hash) ^= ((hash) >> 11); \
(hash) += ((hash) << 15); \
}
/* TRD : this is the Jenkins one-at-a-time hash
it produces a 32 bit hash
http://en.wikipedia.org/wiki/Jenkins_hash_function
we ourselves do *not* initialize the value of *hash, so that
our caller has the option to call us multiple times, each
time with for example a different member of a struct, which is
then hashed into the existing, built-up-so-far hash value, and
so build up a quality hash
*/
/***** enums *****/
enum lfds700_hash_a_existing_key
{
LFDS700_HASH_A_EXISTING_KEY_OVERWRITE,
LFDS700_HASH_A_EXISTING_KEY_FAIL
};
enum lfds700_hash_a_insert_result
{
LFDS700_HASH_A_PUT_RESULT_FAILURE_EXISTING_KEY,
LFDS700_HASH_A_PUT_RESULT_SUCCESS_OVERWRITE,
LFDS700_HASH_A_PUT_RESULT_SUCCESS
};
enum lfds700_hash_a_query
{
LFDS700_HASH_A_QUERY_GET_POTENTIALLY_INACCURATE_COUNT,
LFDS700_HASH_A_QUERY_SINGLETHREADED_VALIDATE
};
/***** structs *****/
struct lfds700_hash_a_element
{
struct lfds700_btree_au_element
baue;
void
*key;
void LFDS700_PAL_ALIGN(LFDS700_PAL_ATOMIC_ISOLATION_IN_BYTES)
*volatile value;
};
struct lfds700_hash_a_iterate
{
struct lfds700_btree_au_element
*baue;
struct lfds700_btree_au_state
*baus,
*baus_end;
};
struct lfds700_hash_a_state
{
enum lfds700_hash_a_existing_key
existing_key;
int
(*key_compare_function)( void const *new_key, void const *existing_key );
lfds700_pal_uint_t
array_size;
struct lfds700_btree_au_state
*baus_array;
void
(*element_cleanup_callback)( struct lfds700_hash_a_state *has, struct lfds700_hash_a_element *hae ),
(*key_hash_function)( void const *key, lfds700_pal_uint_t *hash ),
*user_state;
};
/***** public prototypes *****/
void lfds700_hash_a_init_valid_on_current_logical_core( struct lfds700_hash_a_state *has,
struct lfds700_btree_au_state *baus_array,
lfds700_pal_uint_t array_size,
int (*key_compare_function)(void const *new_key, void const *existing_key),
void (*key_hash_function)(void const *key, lfds700_pal_uint_t *hash),
enum lfds700_hash_a_existing_key existing_key,
void *user_state );
// TRD : used in conjunction with the #define LFDS700_MISC_MAKE_VALID_ON_CURRENT_LOGICAL_CORE_INITS_COMPLETED_BEFORE_NOW_ON_ANY_OTHER_LOGICAL_CORE
void lfds700_hash_a_cleanup( struct lfds700_hash_a_state *has,
void (*element_cleanup_function)(struct lfds700_hash_a_state *has, struct lfds700_hash_a_element *hae) );
enum lfds700_hash_a_insert_result lfds700_hash_a_insert( struct lfds700_hash_a_state *has,
struct lfds700_hash_a_element *hae,
struct lfds700_hash_a_element **existing_hae,
struct lfds700_misc_prng_state *ps );
// TRD : if existing_value is not NULL and the key exists, existing_value is set to the value of the existing key
int lfds700_hash_a_get_by_key( struct lfds700_hash_a_state *has,
void *key,
struct lfds700_hash_a_element **hae );
void lfds700_hash_a_iterate_init( struct lfds700_hash_a_state *has, struct lfds700_hash_a_iterate *hai );
int lfds700_hash_a_iterate( struct lfds700_hash_a_iterate *hai, struct lfds700_hash_a_element **hae );
void lfds700_hash_a_query( struct lfds700_hash_a_state *has,
enum lfds700_hash_a_query query_type,
void *query_input,
void *query_output );
/***** defines *****/
#define LFDS700_LIST_AOS_GET_START( list_aos_state ) ( LFDS700_MISC_BARRIER_LOAD, (list_aos_state).start->next )
#define LFDS700_LIST_AOS_GET_NEXT( list_aos_element ) ( LFDS700_MISC_BARRIER_LOAD, (list_aos_element).next )
#define LFDS700_LIST_AOS_GET_START_AND_THEN_NEXT( list_aos_state, pointer_to_list_aos_element ) ( (pointer_to_list_aos_element) == NULL ? ( (pointer_to_list_aos_element) = LFDS700_LIST_AOS_GET_START(list_aos_state) ) : ( (pointer_to_list_aos_element) = LFDS700_LIST_AOS_GET_NEXT(*(pointer_to_list_aos_element)) ) )
#define LFDS700_LIST_AOS_GET_KEY_FROM_ELEMENT( list_aos_element ) ( (list_aos_element).key )
#define LFDS700_LIST_AOS_SET_KEY_IN_ELEMENT( list_aos_element, new_key ) ( (list_aos_element).key = (void *) (lfds700_pal_uint_t) (new_key) )
#define LFDS700_LIST_AOS_GET_VALUE_FROM_ELEMENT( list_aos_element ) ( LFDS700_MISC_BARRIER_LOAD, (list_aos_element).value )
#define LFDS700_LIST_AOS_SET_VALUE_IN_ELEMENT( list_aos_element, new_value ) { void *local_new_value = (void *) (lfds700_pal_uint_t) (new_value); LFDS700_PAL_ATOMIC_EXCHANGE( &(list_aos_element).value, &local_new_value ); }
#define LFDS700_LIST_AOS_GET_USER_STATE_FROM_STATE( list_aos_state ) ( (list_aos_state).user_state )
/***** enums *****/
enum lfds700_list_aos_existing_key
{
LFDS700_LIST_AOS_EXISTING_KEY_OVERWRITE,
LFDS700_LIST_AOS_EXISTING_KEY_FAIL
};
enum lfds700_list_aos_insert_result
{
LFDS700_LIST_AOS_INSERT_RESULT_FAILURE_EXISTING_KEY,
LFDS700_LIST_AOS_INSERT_RESULT_SUCCESS_OVERWRITE,
LFDS700_LIST_AOS_INSERT_RESULT_SUCCESS
};
enum lfds700_list_aos_query
{
LFDS700_LIST_AOS_QUERY_GET_POTENTIALLY_INACCURATE_COUNT,
LFDS700_LIST_AOS_QUERY_SINGLETHREADED_VALIDATE
};
/***** structures *****/
struct lfds700_list_aos_element
{
struct lfds700_list_aos_element LFDS700_PAL_ALIGN(LFDS700_PAL_ATOMIC_ISOLATION_IN_BYTES)
*volatile next;
void LFDS700_PAL_ALIGN(LFDS700_PAL_ATOMIC_ISOLATION_IN_BYTES)
*volatile value;
void LFDS700_PAL_ALIGN(LFDS700_PAL_ATOMIC_ISOLATION_IN_BYTES)
*key;
};
struct lfds700_list_aos_state
{
struct lfds700_list_aos_element LFDS700_PAL_ALIGN(LFDS700_PAL_ATOMIC_ISOLATION_IN_BYTES)
*volatile start;
struct lfds700_list_aos_element LFDS700_PAL_ALIGN(LFDS700_PAL_ATOMIC_ISOLATION_IN_BYTES)
dummy_element;
int LFDS700_PAL_ALIGN(LFDS700_PAL_ATOMIC_ISOLATION_IN_BYTES)
(*key_compare_function)( void const *new_key, void const *existing_key );
enum lfds700_list_aos_existing_key
existing_key;
void
*user_state;
};
/***** public prototypes *****/
void lfds700_list_aos_init_valid_on_current_logical_core( struct lfds700_list_aos_state *laoss,
int (*key_compare_function)(void const *new_key, void const *existing_key),
enum lfds700_list_aos_existing_key existing_key,
void *user_state );
// TRD : used in conjunction with the #define LFDS700_MISC_MAKE_VALID_ON_CURRENT_LOGICAL_CORE_INITS_COMPLETED_BEFORE_NOW_ON_ANY_OTHER_LOGICAL_CORE
void lfds700_list_aos_cleanup( struct lfds700_list_aos_state *laoss,
void (*element_cleanup_callback)(struct lfds700_list_aos_state *laoss, struct lfds700_list_aos_element *laose) );
enum lfds700_list_aos_insert_result lfds700_list_aos_insert( struct lfds700_list_aos_state *laoss,
struct lfds700_list_aos_element *laose,
struct lfds700_list_aos_element **existing_laose,
struct lfds700_misc_prng_state *ps );
int lfds700_list_aos_get_by_key( struct lfds700_list_aos_state *laoss,
void *key,
struct lfds700_list_aos_element **laose );
void lfds700_list_aos_query( struct lfds700_list_aos_state *laoss,
enum lfds700_list_aos_query query_type,
void *query_input,
void *query_output );
/***** defines *****/
#define LFDS700_LIST_ASU_GET_START( list_asu_state ) ( LFDS700_MISC_BARRIER_LOAD, (list_asu_state).start->next )
#define LFDS700_LIST_ASU_GET_NEXT( list_asu_element ) ( LFDS700_MISC_BARRIER_LOAD, (list_asu_element).next )
#define LFDS700_LIST_ASU_GET_START_AND_THEN_NEXT( list_asu_state, pointer_to_list_asu_element ) ( (pointer_to_list_asu_element) == NULL ? ( (pointer_to_list_asu_element) = LFDS700_LIST_ASU_GET_START(list_asu_state) ) : ( (pointer_to_list_asu_element) = LFDS700_LIST_ASU_GET_NEXT(*(pointer_to_list_asu_element)) ) )
#define LFDS700_LIST_ASU_GET_KEY_FROM_ELEMENT( list_asu_element ) ( (list_asu_element).key )
#define LFDS700_LIST_ASU_SET_KEY_IN_ELEMENT( list_asu_element, new_key ) ( (list_asu_element).key = (void *) (lfds700_pal_uint_t) (new_key) )
#define LFDS700_LIST_ASU_GET_VALUE_FROM_ELEMENT( list_asu_element ) ( LFDS700_MISC_BARRIER_LOAD, (list_asu_element).value )
#define LFDS700_LIST_ASU_SET_VALUE_IN_ELEMENT( list_asu_element, new_value ) { void *local_new_value = (void *) (lfds700_pal_uint_t) (new_value); LFDS700_PAL_ATOMIC_EXCHANGE( &(list_asu_element).value, &local_new_value ); }
#define LFDS700_LIST_ASU_GET_USER_STATE_FROM_STATE( list_asu_state ) ( (list_asu_state).user_state )
/***** enums *****/
enum lfds700_list_asu_position
{
LFDS700_LIST_ASU_POSITION_START,
LFDS700_LIST_ASU_POSITION_END,
LFDS700_LIST_ASU_POSITION_AFTER
};
enum lfds700_list_asu_query
{
LFDS700_LIST_ASU_QUERY_GET_POTENTIALLY_INACCURATE_COUNT,
LFDS700_LIST_ASU_QUERY_SINGLETHREADED_VALIDATE
};
/***** structures *****/
struct lfds700_list_asu_element
{
struct lfds700_list_asu_element LFDS700_PAL_ALIGN(LFDS700_PAL_ATOMIC_ISOLATION_IN_BYTES)
*volatile next;
void LFDS700_PAL_ALIGN(LFDS700_PAL_ATOMIC_ISOLATION_IN_BYTES)
*volatile value;
void LFDS700_PAL_ALIGN(LFDS700_PAL_ATOMIC_ISOLATION_IN_BYTES)
*key;
};
struct lfds700_list_asu_state
{
struct lfds700_list_asu_element LFDS700_PAL_ALIGN(LFDS700_PAL_ATOMIC_ISOLATION_IN_BYTES)
*volatile end,
*volatile start;
struct lfds700_list_asu_element LFDS700_PAL_ALIGN(LFDS700_PAL_ATOMIC_ISOLATION_IN_BYTES)
dummy_element;
int LFDS700_PAL_ALIGN(LFDS700_PAL_ATOMIC_ISOLATION_IN_BYTES)
(*key_compare_function)( void const *new_key, void const *existing_key );
void
*user_state;
};
/***** public prototypes *****/
void lfds700_list_asu_init_valid_on_current_logical_core( struct lfds700_list_asu_state *lasus,
int (*key_compare_function)(void const *new_key, void const *existing_key),
void *user_state );
// TRD : used in conjunction with the #define LFDS700_MISC_MAKE_VALID_ON_CURRENT_LOGICAL_CORE_INITS_COMPLETED_BEFORE_NOW_ON_ANY_OTHER_LOGICAL_CORE
void lfds700_list_asu_cleanup( struct lfds700_list_asu_state *lasus,
void (*element_cleanup_callback)(struct lfds700_list_asu_state *lasus, struct lfds700_list_asu_element *lasue) );
void lfds700_list_asu_insert_at_position( struct lfds700_list_asu_state *lasus,
struct lfds700_list_asu_element *lasue,
struct lfds700_list_asu_element *lasue_predecessor,
enum lfds700_list_asu_position position,
struct lfds700_misc_prng_state *ps );
void lfds700_list_asu_insert_at_start( struct lfds700_list_asu_state *lasus,
struct lfds700_list_asu_element *lasue,
struct lfds700_misc_prng_state *ps );
void lfds700_list_asu_insert_at_end( struct lfds700_list_asu_state *lasus,
struct lfds700_list_asu_element *lasue,
struct lfds700_misc_prng_state *ps );
void lfds700_list_asu_insert_after_element( struct lfds700_list_asu_state *lasus,
struct lfds700_list_asu_element *lasue,
struct lfds700_list_asu_element *lasue_predecessor,
struct lfds700_misc_prng_state *ps );
int lfds700_list_asu_get_by_key( struct lfds700_list_asu_state *lasus,
void *key,
struct lfds700_list_asu_element **lasue );
void lfds700_list_asu_query( struct lfds700_list_asu_state *lasus,
enum lfds700_list_asu_query query_type,
void *query_input,
void *query_output );
/***** defines *****/
#define LFDS700_MISC_VERSION_STRING "7.0.0"
#define LFDS700_MISC_VERSION_INTEGER 700
#ifndef NULL
#define NULL ( (void *) 0 )
#endif
#define POINTER 0
#define COUNTER 1
#define PAC_SIZE 2
#define LFDS700_MISC_ABSTRACTION_BACKOFF_INITIAL_VALUE 0
#define LFDS700_MISC_PRNG_MAX ( (lfds700_pal_uint_t) -1 )
#define LFDS700_MISC_DELIBERATELY_CRASH { char *c = 0; *c = 0; }
#define LFDS700_MISC_PRNG_SEED 0x0a34655d34c092feULL
/* TRD : from an on-line hardware RNG, using atmospheric noise
the URL eblow will generate another 16 random hex digits (e.g. a 64-bit number) and is
the RNG used to generate the number above (0x0a34655d34c092fe)
http://www.random.org/integers/?num=16&min=0&max=15&col=1&base=16&format=plain&rnd=new
this seed is a fixed seed which is used for the slow, high quality PRNG,
which in turn is used when thread start to generate a single high quality seed
for the fast, low quality PRNG used for the CAS exponential backoff
*/
#if( LFDS700_PAL_ALIGN_SINGLE_POINTER == 4 ) // TRD : any 32-bit platform
// TRD : PRNG is a 32-bit xorshift, numbers suggested by George Marsaglia, in his paper http://www.jstatsoft.org/v08/i14/paper
#define LFDS700_MISC_PRNG_GENERATE( pointer_to_lfds700_misc_prng_state ) ( (pointer_to_lfds700_misc_prng_state)->prng_state ^= (pointer_to_lfds700_misc_prng_state)->prng_state >> 13, (pointer_to_lfds700_misc_prng_state)->prng_state ^= (pointer_to_lfds700_misc_prng_state)->prng_state << 17, (pointer_to_lfds700_misc_prng_state)->prng_state ^= (pointer_to_lfds700_misc_prng_state)->prng_state >> 5 )
#endif
#if( LFDS700_PAL_ALIGN_SINGLE_POINTER == 8 ) // TRD : any 64-bit platform
// TRD : PRNG is 64-bit xorshift (xorshift64*), from Sebastiano Vigna (vigna at acm dot org), http://creativecommons.org/publicdomain/zero/1.0/
#define LFDS700_MISC_PRNG_GENERATE( pointer_to_lfds700_misc_prng_state ) ( (pointer_to_lfds700_misc_prng_state)->prng_state ^= (pointer_to_lfds700_misc_prng_state)->prng_state >> 12, (pointer_to_lfds700_misc_prng_state)->prng_state ^= (pointer_to_lfds700_misc_prng_state)->prng_state << 25, (pointer_to_lfds700_misc_prng_state)->prng_state ^= (pointer_to_lfds700_misc_prng_state)->prng_state >> 27, (pointer_to_lfds700_misc_prng_state)->prng_state *= 2685821657736338717LL )
#endif
#if( !defined LFDS700_PAL_ATOMIC_CAS )
#define LFDS700_PAL_NO_ATOMIC_CAS
// TRD : lfds700_pal_atom_t volatile *destination, lfds700_pal_atom_t *compare, lfds700_pal_atom_t new_destination, enum lfds700_misc_cas_strength cas_strength, char unsigned result
#define LFDS700_PAL_ATOMIC_CAS( pointer_to_destination, pointer_to_compare, new_destination, cas_strength, result ) \
{ \
LFDS700_PAL_ASSERT( !"LFDS700_PAL_ATOMIC_CAS not implemented for this platform." ); \
LFDS700_MISC_DELIBERATELY_CRASH; \
(result) = (char unsigned) 1; \
}
#endif
#if( !defined LFDS700_PAL_ATOMIC_DWCAS )
#define LFDS700_PAL_NO_ATOMIC_DWCAS
// TRD : lfds700_pal_atom_t volatile (*destination)[2], lfds700_pal_atom_t (*compare)[2], lfds700_pal_atom_t (*new_destination)[2], enum lfds700_misc_cas_strength cas_strength, unsigned char result
#define LFDS700_PAL_ATOMIC_DWCAS( pointer_to_destination, pointer_to_compare, pointer_to_new_destination, cas_strength, result ) \
{ \
LFDS700_PAL_ASSERT( !"LFDS700_PAL_ATOMIC_DWCAS not implemented for this platform." ); \
LFDS700_MISC_DELIBERATELY_CRASH; \
(result) = (char unsigned) 1; \
}
#endif
#if( !defined LFDS700_PAL_ATOMIC_EXCHANGE )
#define LFDS700_PAL_NO_ATOMIC_EXCHANGE
// TRD : lfds700_pal_atom_t volatile *destination, lfds700_pal_atom_t *exchange
#define LFDS700_PAL_ATOMIC_EXCHANGE( pointer_to_destination, pointer_to_exchange ) \
{ \
LFDS700_PAL_ASSERT( !"LFDS700_PAL_ATOMIC_EXCHANGE not implemented for this platform." ); \
LFDS700_MISC_DELIBERATELY_CRASH; \
}
#endif
#if( defined LFDS700_PAL_NO_COMPILER_BARRIERS )
#define LFDS700_MISC_BARRIER_LOAD ( LFDS700_PAL_BARRIER_PROCESSOR_LOAD )
#define LFDS700_MISC_BARRIER_STORE ( LFDS700_PAL_BARRIER_PROCESSOR_STORE )
#define LFDS700_MISC_BARRIER_FULL ( LFDS700_PAL_BARRIER_PROCESSOR_FULL )
#else
#define LFDS700_MISC_BARRIER_LOAD ( LFDS700_PAL_BARRIER_COMPILER_LOAD, LFDS700_PAL_BARRIER_PROCESSOR_LOAD, LFDS700_PAL_BARRIER_COMPILER_LOAD )
#define LFDS700_MISC_BARRIER_STORE ( LFDS700_PAL_BARRIER_COMPILER_STORE, LFDS700_PAL_BARRIER_PROCESSOR_STORE, LFDS700_PAL_BARRIER_COMPILER_STORE )
#define LFDS700_MISC_BARRIER_FULL ( LFDS700_PAL_BARRIER_COMPILER_FULL, LFDS700_PAL_BARRIER_PROCESSOR_FULL, LFDS700_PAL_BARRIER_COMPILER_FULL )
#endif
#define LFDS700_MISC_MAKE_VALID_ON_CURRENT_LOGICAL_CORE_INITS_COMPLETED_BEFORE_NOW_ON_ANY_OTHER_LOGICAL_CORE LFDS700_MISC_BARRIER_LOAD
#if( defined LFDS700_PAL_NO_ATOMIC_CAS )
#define LFDS700_MISC_ATOMIC_SUPPORT_CAS 0
#else
#define LFDS700_MISC_ATOMIC_SUPPORT_CAS 1
#endif
#if( defined LFDS700_PAL_NO_ATOMIC_DWCAS )
#define LFDS700_MISC_ATOMIC_SUPPORT_DWCAS 0
#else
#define LFDS700_MISC_ATOMIC_SUPPORT_DWCAS 1
#endif
#if( defined LFDS700_PAL_NO_ATOMIC_EXCHANGE )
#define LFDS700_MISC_ATOMIC_SUPPORT_EXCHANGE 0
#else
#define LFDS700_MISC_ATOMIC_SUPPORT_EXCHANGE 1
#endif
/***** enums *****/
enum lfds700_misc_cas_strength
{
// TRD : yes, weak is 1 (one) - blame GCC!
LFDS700_MISC_CAS_STRENGTH_WEAK = 1,
LFDS700_MISC_CAS_STRENGTH_STRONG = 0
};
enum lfds700_misc_validity
{
LFDS700_MISC_VALIDITY_VALID,
LFDS700_MISC_VALIDITY_INVALID_LOOP,
LFDS700_MISC_VALIDITY_INVALID_MISSING_ELEMENTS,
LFDS700_MISC_VALIDITY_INVALID_ADDITIONAL_ELEMENTS,
LFDS700_MISC_VALIDITY_INVALID_TEST_DATA,
LFDS700_MISC_VALIDITY_INVALID_ORDER
};
enum lfds700_misc_flag
{
LFDS700_MISC_FLAG_LOWERED,
LFDS700_MISC_FLAG_RAISED
};
enum lfds700_misc_query
{
LFDS700_MISC_QUERY_GET_EXPONENTIAL_BACKOFF_TIMESLOT_LENGTH_IN_LOOP_ITERATIONS_FOR_CAS,
LFDS700_MISC_QUERY_SET_EXPONENTIAL_BACKOFF_TIMESLOT_LENGTH_IN_LOOP_ITERATIONS_FOR_CAS,
LFDS700_MISC_QUERY_GET_EXPONENTIAL_BACKOFF_TIMESLOT_LENGTH_IN_LOOP_ITERATIONS_FOR_DWCAS,
LFDS700_MISC_QUERY_SET_EXPONENTIAL_BACKOFF_TIMESLOT_LENGTH_IN_LOOP_ITERATIONS_FOR_DWCAS,
LFDS700_MISC_QUERY_GET_BUILD_AND_VERSION_STRING
};
/***** struct *****/
struct lfds700_misc_globals
{
lfds700_pal_atom_t
exponential_backoff_timeslot_length_in_loop_iterations_for_cas,
exponential_backoff_timeslot_length_in_loop_iterations_for_dwcas;
};
struct lfds700_misc_prng_state
{
lfds700_pal_uint_t
prng_state;
// TRD : here to be on the same cache-line as prng_state, and so all are obtained from one cache-line read
lfds700_pal_atom_t
local_copy_of_global_exponential_backoff_timeslot_length_in_loop_iterations_for_cas,
local_copy_of_global_exponential_backoff_timeslot_length_in_loop_iterations_for_dwcas;
};
struct lfds700_misc_validation_info
{
lfds700_pal_uint_t
min_elements,
max_elements;
};
/***** externs *****/
extern struct lfds700_misc_globals
lfds700_misc_globals;
/***** public prototypes *****/
void lfds700_misc_library_init_valid_on_current_logical_core( void );
// TRD : used in conjunction with the #define LFDS700_MISC_MAKE_VALID_ON_CURRENT_LOGICAL_CORE_INITS_COMPLETED_BEFORE_NOW_ON_ANY_OTHER_LOGICAL_CORE
void lfds700_misc_library_cleanup( void );
static LFDS700_PAL_INLINE void lfds700_misc_force_store( void );
void lfds700_misc_prng_init( struct lfds700_misc_prng_state *ps );
void lfds700_misc_query( enum lfds700_misc_query query_type, void *query_input, void *query_output );
/***** public in-line functions *****/
#pragma prefast( disable : 28112, "blah" )
static LFDS700_PAL_INLINE void lfds700_misc_force_store()
{
lfds700_pal_uint_t
exchange = 0;
lfds700_pal_atom_t volatile LFDS700_PAL_ALIGN(LFDS700_PAL_ATOMIC_ISOLATION_IN_BYTES)
destination;
LFDS700_PAL_ATOMIC_EXCHANGE( &destination, &exchange );
return;
}
/****************************************************************************/
#if( defined __GNUC__ )
// TRD : makes checking GCC versions much tidier
#define LFDS700_PAL_GCC_VERSION ( __GNUC__ * 100 + __GNUC_MINOR__ * 10 + __GNUC_PATCHLEVEL__ )
#endif
/****************************************************************************/
#if( defined _MSC_VER && _MSC_VER >= 1400 )
/* TRD : MSVC 8.0 and greater
_MSC_VER indicates Microsoft C compiler and version
- __declspec(align) requires 7.1 (1310)
- __nop requires 8.0 (1400)
- _ReadBarrier requires 8.0 (1400)
- _WriteBarrier requires 8.0 (1400)
- _ReadWriteBarrier requires 7.1 (1310)
- _InterlockedCompareExchangePointer requires 8.0 (1400)
- _InterlockedExchange requires 7.1 (1310)
- _InterlockedExchangePointer requires 8.0 (1400)
- _InterlockedCompareExchange64 requires 8.0 (1400) (seems to, docs unclear)
- _InterlockedCompareExchange128 requires 9.0 (1500)
load/store barriers are mandatory for liblfds, which means the earliest viable version of MSCV is 1400
strictly we could get away with 1310 and use _ReadWriteBarrier, but the difference between 1310 and 1400 is small, so WTH
_InterlockedCompareExchange128 is needed on 64-bit platforms to provide DWCAS, but DWCAS is not mandatory,
so we check against the compiler version - remember, any unimplemented atomic will be masked by its dummy define,
so everything will compile - it just means you can't use data structures which require that atomic
*/
#ifdef LFDS700_PAL_PORTING_ABSTRACTION_LAYER_COMPILER
#error More than one porting abstraction layer matches the current platform in lfds700_porting_abstraction_layer_compiler.h
#endif
#define LFDS700_PAL_PORTING_ABSTRACTION_LAYER_COMPILER
#define LFDS700_PAL_COMPILER_STRING "MSVC"
#define LFDS700_PAL_ALIGN(alignment) __declspec( align(alignment) )
#define LFDS700_PAL_INLINE __forceinline
#define LFDS700_PAL_BARRIER_COMPILER_LOAD _ReadBarrier()
#define LFDS700_PAL_BARRIER_COMPILER_STORE _WriteBarrier()
#define LFDS700_PAL_BARRIER_COMPILER_FULL _ReadWriteBarrier()
/* TRD : there are four processors to consider;
. ARM32 (32 bit, CAS, DWCAS) (defined _M_ARM)
. Itanium (64 bit, CAS) (defined _M_IA64)
. x64 (64 bit, CAS, DWCAS) (defined _M_X64 || defined _M_AMD64)
. x86 (32 bit, CAS, DWCAS) (defined _M_IX86)
can't find any indications of 64-bit ARM support yet
ARM has better intrinsics than the others, as there are no-fence variants
in theory we also have to deal with 32-bit Windows on a 64-bit platform,
and I presume we'd see the compiler properly indicate this in its macros,
but this would require that we use 32-bit atomics on the 64-bit platforms,
while keeping 64-bit cache line lengths and so on, and this is just so
wierd a thing to do these days that it's not supported
note that _InterlockedCompareExchangePointer performs CAS on all processors
however, it is documented as being available for x86 when in fact it is not
so we have to #if for processor type and use the length specific intrinsics
*/
#if( defined _M_ARM )
#define LFDS700_PAL_BARRIER_PROCESSOR_LOAD __dmb( _ARM_BARRIER_ISH )
#define LFDS700_PAL_BARRIER_PROCESSOR_STORE __dmb( _ARM_BARRIER_ISHST )
#define LFDS700_PAL_BARRIER_PROCESSOR_FULL __dmb( _ARM_BARRIER_ISH )
#define LFDS700_PAL_ATOMIC_CAS( pointer_to_destination, pointer_to_compare, new_destination, cas_strength, result ) \
{ \
lfds700_pal_atom_t \
original_compare; \
\
/* LFDS700_PAL_ASSERT( (pointer_to_destination) != NULL ); */ \
/* LFDS700_PAL_ASSERT( (pointer_to_compare) != NULL ); */ \
/* TRD : new_destination can be any value in its range */ \
/* TRD : cas_strength can be any value in its range */ \
/* TRD : result can be any value in its range */ \
\
original_compare = (lfds700_pal_atom_t) *(pointer_to_compare); \
\
LFDS700_PAL_BARRIER_COMPILER_FULL; \
*(lfds700_pal_atom_t *) (pointer_to_compare) = (lfds700_pal_atom_t) _InterlockedCompareExchange_nf( (long volatile *) (pointer_to_destination), (long) (new_destination), (long) *(pointer_to_compare) ); \
LFDS700_PAL_BARRIER_COMPILER_FULL; \
\
result = (char unsigned) ( original_compare == (lfds700_pal_atom_t) *(pointer_to_compare) ); \
}
#define LFDS700_PAL_ATOMIC_DWCAS( pointer_to_destination, pointer_to_compare, pointer_to_new_destination, cas_strength, result ) \
{ \
__int64 \
original_compare; \
\
/* LFDS700_PAL_ASSERT( (pointer_to_destination) != NULL ); */ \
/* LFDS700_PAL_ASSERT( (pointer_to_compare) != NULL ); */ \
/* LFDS700_PAL_ASSERT( (pointer_to_new_destination) != NULL ); */ \
/* TRD : cas_strength can be any value in its range */ \
/* TRD : result can be any value in its range */ \
\
original_compare = *(__int64 *) (pointer_to_compare); \
\
LFDS700_PAL_BARRIER_COMPILER_FULL; \
*(__int64 *) (pointer_to_compare) = _InterlockedCompareExchange64_nf( (__int64 volatile *) (pointer_to_destination), *(__int64 *) (pointer_to_new_destination), *(__int64 *) (pointer_to_compare) ); \
LFDS700_PAL_BARRIER_COMPILER_FULL; \
\
result = (char unsigned) ( *(__int64 *) (pointer_to_compare) == original_compare ); \
}
#define LFDS700_PAL_ATOMIC_EXCHANGE( pointer_to_destination, pointer_to_exchange ) \
{ \
/* LFDS700_PAL_ASSERT( (pointer_to_destination) != NULL ); */ \
/* LFDS700_PAL_ASSERT( (pointer_to_exchange) != NULL ); */ \
\
LFDS700_PAL_BARRIER_COMPILER_FULL; \
*(lfds700_pal_atom_t *) (pointer_to_exchange) = (lfds700_pal_atom_t) _InterlockedExchange_nf( (int long volatile *) (pointer_to_destination), (int long) *(pointer_to_exchange) ); \
LFDS700_PAL_BARRIER_COMPILER_FULL; \
}
#endif
#if( defined _M_IA64 )
#define LFDS700_PAL_BARRIER_PROCESSOR_LOAD __mf()
#define LFDS700_PAL_BARRIER_PROCESSOR_STORE __mf()
#define LFDS700_PAL_BARRIER_PROCESSOR_FULL __mf()
#define LFDS700_PAL_ATOMIC_CAS( pointer_to_destination, pointer_to_compare, new_destination, cas_strength, result ) \
{ \
lfds700_pal_atom_t \
original_compare; \
\
/* LFDS700_PAL_ASSERT( (pointer_to_destination) != NULL ); */ \
/* LFDS700_PAL_ASSERT( (pointer_to_compare) != NULL ); */ \
/* TRD : new_destination can be any value in its range */ \
/* TRD : cas_strength can be any value in its range */ \
/* TRD : result can be any value in its range */ \
\
original_compare = (lfds700_pal_atom_t) *(pointer_to_compare); \
\
LFDS700_PAL_BARRIER_COMPILER_FULL; \
*(lfds700_pal_atom_t *) (pointer_to_compare) = (lfds700_pal_atom_t) _InterlockedCompareExchange64_acq( (__int64 volatile *) (pointer_to_destination), (__int64) (new_destination), (__int64) *(pointer_to_compare) ); \
LFDS700_PAL_BARRIER_COMPILER_FULL; \
\
result = (char unsigned) ( original_compare == (lfds700_pal_atom_t) *(pointer_to_compare) ); \
}
#define LFDS700_PAL_ATOMIC_EXCHANGE( pointer_to_destination, pointer_to_exchange ) \
{ \
/* LFDS700_PAL_ASSERT( (pointer_to_destination) != NULL ); */ \
/* LFDS700_PAL_ASSERT( (pointer_to_exchange) != NULL ); */ \
\
LFDS700_PAL_BARRIER_COMPILER_FULL; \
*(lfds700_pal_atom_t *) (pointer_to_exchange) = (lfds700_pal_atom_t) _InterlockedExchange64_acq( (__int64 volatile *) (pointer_to_destination), (__int64) *(pointer_to_exchange) ); \
LFDS700_PAL_BARRIER_COMPILER_FULL; \
}
#endif
#if( defined _M_X64 || defined _M_AMD64 )
#define LFDS700_PAL_BARRIER_PROCESSOR_LOAD _mm_lfence()
#define LFDS700_PAL_BARRIER_PROCESSOR_STORE _mm_sfence()
#define LFDS700_PAL_BARRIER_PROCESSOR_FULL _mm_mfence()
#define LFDS700_PAL_ATOMIC_CAS( pointer_to_destination, pointer_to_compare, new_destination, cas_strength, result ) \
{ \
lfds700_pal_atom_t \
original_compare; \
\
/* LFDS700_PAL_ASSERT( (pointer_to_destination) != NULL ); */ \
/* LFDS700_PAL_ASSERT( (pointer_to_compare) != NULL ); */ \
/* TRD : new_destination can be any value in its range */ \
/* TRD : cas_strength can be any value in its range */ \
/* TRD : result can be any value in its range */ \
\
original_compare = (lfds700_pal_atom_t) *(pointer_to_compare); \
\
LFDS700_PAL_BARRIER_COMPILER_FULL; \
*(lfds700_pal_atom_t *) (pointer_to_compare) = (lfds700_pal_atom_t) _InterlockedCompareExchange64( (__int64 volatile *) (pointer_to_destination), (__int64) (new_destination), (__int64) *(pointer_to_compare) ); \
LFDS700_PAL_BARRIER_COMPILER_FULL; \
\
result = (char unsigned) ( original_compare == (lfds700_pal_atom_t) *(pointer_to_compare) ); \
}
#if( _MSC_VER >= 1500 )
#define LFDS700_PAL_ATOMIC_DWCAS( pointer_to_destination, pointer_to_compare, pointer_to_new_destination, cas_strength, result ) \
{ \
/* LFDS700_PAL_ASSERT( (pointer_to_new_destination) != NULL ); */ \
/* LFDS700_PAL_ASSERT( (pointer_to_destination) != NULL ); */ \
/* LFDS700_PAL_ASSERT( (pointer_to_compare) != NULL ); */ \
/* TRD : cas_strength can be any value in its range */ \
/* TRD : result can be any value in its range */ \
\
LFDS700_PAL_BARRIER_COMPILER_FULL; \
result = (char unsigned) _InterlockedCompareExchange128( (__int64 volatile *) (pointer_to_destination), (__int64) (pointer_to_new_destination[1]), (__int64) (pointer_to_new_destination[0]), (__int64 *) (pointer_to_compare) ); \
LFDS700_PAL_BARRIER_COMPILER_FULL; \
}
#endif
#define LFDS700_PAL_ATOMIC_EXCHANGE( pointer_to_destination, pointer_to_exchange ) \
{ \
/* LFDS700_PAL_ASSERT( (pointer_to_destination) != NULL ); */ \
/* LFDS700_PAL_ASSERT( (pointer_to_exchange) != NULL ); */ \
\
LFDS700_PAL_BARRIER_COMPILER_FULL; \
*(lfds700_pal_atom_t *) (pointer_to_exchange) = (lfds700_pal_atom_t) _InterlockedExchangePointer( (void * volatile *) (pointer_to_destination), (void *) *(pointer_to_exchange) ); \
LFDS700_PAL_BARRIER_COMPILER_FULL; \
}
#endif
#if( defined _M_IX86 )
#define LFDS700_PAL_BARRIER_PROCESSOR_LOAD lfds700_misc_force_store()
#define LFDS700_PAL_BARRIER_PROCESSOR_STORE lfds700_misc_force_store()
#define LFDS700_PAL_BARRIER_PROCESSOR_FULL lfds700_misc_force_store()
#define LFDS700_PAL_ATOMIC_CAS( pointer_to_destination, pointer_to_compare, new_destination, cas_strength, result ) \
{ \
lfds700_pal_atom_t \
original_compare; \
\
/* LFDS700_PAL_ASSERT( (pointer_to_destination) != NULL ); */ \
/* LFDS700_PAL_ASSERT( (pointer_to_compare) != NULL ); */ \
/* TRD : new_destination can be any value in its range */ \
/* TRD : cas_strength can be any value in its range */ \
/* TRD : result can be any value in its range */ \
\
original_compare = (lfds700_pal_atom_t) *(pointer_to_compare); \
\
LFDS700_PAL_BARRIER_COMPILER_FULL; \
*(lfds700_pal_atom_t *) (pointer_to_compare) = (lfds700_pal_atom_t) _InterlockedCompareExchange( (long volatile *) (pointer_to_destination), (long) (new_destination), (long) *(pointer_to_compare) ); \
LFDS700_PAL_BARRIER_COMPILER_FULL; \
\
result = (char unsigned) ( original_compare == (lfds700_pal_atom_t) *(pointer_to_compare) ); \
}
#define LFDS700_PAL_ATOMIC_DWCAS( pointer_to_destination, pointer_to_compare, pointer_to_new_destination, cas_strength, result ) \
{ \
__int64 \
original_compare; \
\
/* LFDS700_PAL_ASSERT( (pointer_to_destination) != NULL ); */ \
/* LFDS700_PAL_ASSERT( (pointer_to_compare) != NULL ); */ \
/* LFDS700_PAL_ASSERT( (pointer_to_new_destination) != NULL ); */ \
/* TRD : cas_strength can be any value in its range */ \
/* TRD : result can be any value in its range */ \
\
original_compare = *(__int64 *) (pointer_to_compare); \
\
LFDS700_PAL_BARRIER_COMPILER_FULL; \
*(__int64 *) (pointer_to_compare) = _InterlockedCompareExchange64( (__int64 volatile *) (pointer_to_destination), *(__int64 *) (pointer_to_new_destination), *(__int64 *) (pointer_to_compare) ); \
LFDS700_PAL_BARRIER_COMPILER_FULL; \
\
result = (char unsigned) ( *(__int64 *) (pointer_to_compare) == original_compare ); \
}
#define LFDS700_PAL_ATOMIC_EXCHANGE( pointer_to_destination, pointer_to_exchange ) \
{ \
/* LFDS700_PAL_ASSERT( (pointer_to_destination) != NULL ); */ \
/* LFDS700_PAL_ASSERT( (pointer_to_exchange) != NULL ); */ \
\
LFDS700_PAL_BARRIER_COMPILER_FULL; \
*(lfds700_pal_atom_t *) (pointer_to_exchange) = (lfds700_pal_atom_t) _InterlockedExchange( (int long volatile *) (pointer_to_destination), (int long) *(pointer_to_exchange) ); \
LFDS700_PAL_BARRIER_COMPILER_FULL; \
}
#endif
#endif
/****************************************************************************/
#if( defined __GNUC__ && LFDS700_PAL_GCC_VERSION >= 412 && LFDS700_PAL_GCC_VERSION < 473 )
/* TRD : GCC 4.1.2 up to 4.7.3
__GNUC__ indicates GCC
LFDS700_PAL_GCC_VERSION indicates which version
- __sync_synchronize requires 4.1.2
GCC 4.1.2 introduced the __sync_*() atomic intrinsics
*/
#ifdef LFDS700_PAL_PORTING_ABSTRACTION_LAYER_COMPILER
#error More than one porting abstraction layer matches the current platform in lfds700_porting_abstraction_layer_compiler.h
#endif
#define LFDS700_PAL_PORTING_ABSTRACTION_LAYER_COMPILER
#define LFDS700_PAL_COMPILER_STRING "GCC < 4.7.3"
#define LFDS700_PAL_ALIGN(alignment) __attribute__( (aligned(alignment)) )
#define LFDS700_PAL_INLINE inline
static LFDS700_PAL_INLINE void lfds700_pal_barrier_compiler( void )
{
__asm__ __volatile__ ( "" : : : "memory" );
}
#define LFDS700_PAL_BARRIER_COMPILER_LOAD lfds700_pal_barrier_compiler()
#define LFDS700_PAL_BARRIER_COMPILER_STORE lfds700_pal_barrier_compiler()
#define LFDS700_PAL_BARRIER_COMPILER_FULL lfds700_pal_barrier_compiler()
#define LFDS700_PAL_BARRIER_PROCESSOR_LOAD __sync_synchronize()
#define LFDS700_PAL_BARRIER_PROCESSOR_STORE __sync_synchronize()
#define LFDS700_PAL_BARRIER_PROCESSOR_FULL __sync_synchronize()
#define LFDS700_PAL_ATOMIC_CAS( pointer_to_destination, pointer_to_compare, new_destination, cas_strength, result ) \
{ \
lfds700_pal_atom_t \
original_compare; \
\
/* LFDS700_PAL_ASSERT( (pointer_to_destination) != NULL ); */ \
/* LFDS700_PAL_ASSERT( (pointer_to_compare) != NULL ); */ \
/* TRD : new_destination can be any value in its range */ \
/* TRD : cas_strength can be any value in its range */ \
/* TRD : result can be any value in its range */ \
\
original_compare = (lfds700_pal_atom_t) *(pointer_to_compare); \
\
LFDS700_PAL_BARRIER_COMPILER_FULL; \
*(pointer_to_compare) = __sync_val_compare_and_swap( pointer_to_destination, *(pointer_to_compare), new_destination ); \
LFDS700_PAL_BARRIER_COMPILER_FULL; \
\
result = (unsigned char) ( original_compare == (lfds700_pal_atom_t) *(pointer_to_compare) ); \
}
// TRD : ARM and x86 have DWCAS which we can get via GCC intrinsics
#if( defined __arm__ || defined __i686__ || defined __i586__ || defined __i486__ )
#define LFDS700_PAL_ATOMIC_DWCAS( pointer_to_destination, pointer_to_compare, pointer_to_new_destination, cas_strength, result ) \
{ \
int long long unsigned \
original_destination; \
\
/* LFDS700_PAL_ASSERT( (pointer_to_destination) != NULL ); */ \
/* LFDS700_PAL_ASSERT( (pointer_to_compare) != NULL ); */ \
/* LFDS700_PAL_ASSERT( (pointer_to_new_destination) != NULL ); */ \
/* TRD : cas_strength can be any value in its range */ \
/* TRD : result can be any value in its range */ \
\
LFDS700_PAL_BARRIER_COMPILER_FULL; \
original_destination = __sync_val_compare_and_swap( (int long long unsigned volatile *) (pointer_to_destination), *(int long long unsigned *) (pointer_to_compare), *(int long long unsigned *) (pointer_to_new_destination) ); \
LFDS700_PAL_BARRIER_COMPILER_FULL; \
\
result = (char unsigned) ( original_destination == *(int long long unsigned *) (pointer_to_compare) ); \
\
*(int long long unsigned *) (pointer_to_compare) = original_destination; \
}
#endif
#define LFDS700_PAL_ATOMIC_EXCHANGE( pointer_to_destination, pointer_to_exchange ) \
{ \
/* LFDS700_PAL_ASSERT( (pointer_to_destination) != NULL ); */ \
/* LFDS700_PAL_ASSERT( (pointer_to_exchange) != NULL ); */ \
\
LFDS700_PAL_BARRIER_COMPILER_FULL; \
*( (lfds700_pal_atom_t *) pointer_to_exchange) = (lfds700_pal_atom_t) __sync_lock_test_and_set( pointer_to_destination, *(pointer_to_exchange) ); \
LFDS700_PAL_BARRIER_COMPILER_FULL; \
}
#endif
/****************************************************************************/
#if( defined __GNUC__ && LFDS700_PAL_GCC_VERSION >= 473 )
/* TRD : GCC 4.7.3 and greater
__GNUC__ indicates GCC
LFDS700_PAL_GCC_VERSION indicates which version
- __atomic_thread_fence requires 4.7.3
GCC 4.7.3 introduced the better __atomic*() atomic intrinsics
*/
#ifdef LFDS700_PAL_PORTING_ABSTRACTION_LAYER_COMPILER
#error More than one porting abstraction layer matches the current platform in lfds700_porting_abstraction_layer_compiler.h
#endif
#define LFDS700_PAL_PORTING_ABSTRACTION_LAYER_COMPILER
#define LFDS700_PAL_COMPILER_STRING "GCC >= 4.7.3"
#define LFDS700_PAL_ALIGN(alignment) __attribute__( (aligned(alignment)) )
#define LFDS700_PAL_INLINE inline
// TRD : GCC >= 4.7.3 compiler barriers are built into the intrinsics
#define LFDS700_PAL_NO_COMPILER_BARRIERS
#define LFDS700_PAL_BARRIER_PROCESSOR_LOAD __atomic_thread_fence( __ATOMIC_ACQUIRE )
#define LFDS700_PAL_BARRIER_PROCESSOR_STORE __atomic_thread_fence( __ATOMIC_RELEASE )
#define LFDS700_PAL_BARRIER_PROCESSOR_FULL __atomic_thread_fence( __ATOMIC_ACQ_REL )
#define LFDS700_PAL_ATOMIC_CAS( pointer_to_destination, pointer_to_compare, new_destination, cas_strength, result ) \
{ \
/* LFDS700_PAL_ASSERT( (pointer_to_destination) != NULL ); */ \
/* LFDS700_PAL_ASSERT( (pointer_to_compare) != NULL ); */ \
/* TRD : new_destination can be any value in its range */ \
/* TRD : cas_strength can be any value in its range */ \
/* TRD : result can be any value in its range */ \
\
result = (char unsigned) __atomic_compare_exchange_n( pointer_to_destination, (void *) (pointer_to_compare), (new_destination), (cas_strength), __ATOMIC_RELAXED, __ATOMIC_RELAXED ); \
}
// TRD : ARM and x86 have DWCAS which we can get via GCC intrinsics
#if( defined __arm__ || defined __i686__ || defined __i586__ || defined __i486__ )
#define LFDS700_PAL_ATOMIC_DWCAS( pointer_to_destination, pointer_to_compare, pointer_to_new_destination, cas_strength, result ) \
{ \
/* LFDS700_PAL_ASSERT( (pointer_to_destination) != NULL ); */ \
/* LFDS700_PAL_ASSERT( (pointer_to_compare) != NULL ); */ \
/* LFDS700_PAL_ASSERT( (pointer_to_new_destination) != NULL ); */ \
/* TRD : cas_strength can be any value in its range */ \
/* TRD : result can be any value in its range */ \
\
(result) = (char unsigned) __atomic_compare_exchange_n( (int long long unsigned volatile *) (pointer_to_destination), (int long long unsigned *) (pointer_to_compare), *(int long long unsigned *) (pointer_to_new_destination), (cas_strength), __ATOMIC_RELAXED, __ATOMIC_RELAXED ); \
}
#endif
#if( defined __x86_64__ )
/* TRD : __GNUC__ indicates GCC
- __asm__ requires GCC
- __volatile__ requires GCC
__x86_64__ indicates x64
- cmpxchg16b requires x64
On 64 bit platforms, unsigned long long int is 64 bit, so we must manually use cmpxchg16b,
as __sync_val_compare_and_swap() will only emit cmpxchg8b
*/
// TRD : lfds700_pal_atom_t volatile (*destination)[2], lfds700_pal_atom_t (*compare)[2], lfds700_pal_atom_t (*new_destination)[2], enum lfds700_misc_cas_strength cas_strength, char unsigned result
#define LFDS700_PAL_ATOMIC_DWCAS( pointer_to_destination, pointer_to_compare, pointer_to_new_destination, cas_strength, result ) \
{ \
/* LFDS700_PAL_ASSERT( (pointer_to_destination) != NULL ); */ \
/* LFDS700_PAL_ASSERT( (pointer_to_compare) != NULL ); */ \
/* LFDS700_PAL_ASSERT( (pointer_to_new_destination) != NULL ); */ \
/* TRD : cas_strength can be any value in its range */ \
/* TRD : result can be any value in its range */ \
\
(result) = 0; \
\
__asm__ __volatile__ \
( \
"lock;" /* make cmpxchg16b atomic */ \
"cmpxchg16b %0;" /* cmpxchg16b sets ZF on success */ \
"setz %3;" /* if ZF set, set result to 1 */ \
\
/* output */ \
: "+m" (*pointer_to_destination), "+a" ((pointer_to_compare)[0]), "+d" ((pointer_to_compare)[1]), "=q" (result) \
\
/* input */ \
: "b" ((pointer_to_new_destination)[0]), "c" ((pointer_to_new_destination)[1]) \
\
/* clobbered */ \
: "cc", "memory" \
); \
}
#endif
#define LFDS700_PAL_ATOMIC_EXCHANGE( pointer_to_destination, pointer_to_exchange ) \
{ \
/* LFDS700_PAL_ASSERT( (pointer_to_destination) != NULL ); */ \
/* LFDS700_PAL_ASSERT( (pointer_to_exchange) != NULL ); */ \
\
*(pointer_to_exchange) = __atomic_exchange_n( (pointer_to_destination), *(pointer_to_exchange), __ATOMIC_RELAXED ); \
}
#endif
/****************************************************************************/
#if( defined _MSC_VER )
/* TRD : MSVC compiler
an unfortunately necessary hack for MSVC
MSVC only defines __STDC__ if /Za is given, where /Za turns off MSVC C extensions -
which prevents Windows header files from compiling.
*/
#define __STDC__ 1
#define __STDC_HOSTED__ 1
#endif
/****************************************************************************/
#if( defined _MSC_VER && _MSC_VER >= 1400 && __STDC_HOSTED__ == 1 && !defined _KERNEL_MODE )
// TRD : MSVC
#ifdef LFDS700_PAL_PORTING_ABSTRACTION_LAYER_OPERATING_SYSTEM
#error More than one porting abstraction layer matches the current platform in lfds700_porting_abstraction_layer_operating_system.h
#endif
#define LFDS700_PAL_PORTING_ABSTRACTION_LAYER_OPERATING_SYSTEM
#include <assert.h>
#define LFDS700_PAL_OS_STRING "Windows"
#define LFDS700_PAL_ASSERT( expression ) assert( expression )
#endif
/****************************************************************************/
#if( defined _MSC_VER && _MSC_VER >= 1400 && defined __STDC_HOSTED__ && __STDC_HOSTED__ == 1 && defined _WIN32 && defined _KERNEL_MODE )
// TRD : MSVC, Windows kernel-mode
#ifdef LFDS700_PAL_PORTING_ABSTRACTION_LAYER_OPERATING_SYSTEM
#error More than one porting abstraction layer matches the current platform in lfds700_porting_abstraction_layer_operating_system.h
#endif
#define LFDS700_PAL_PORTING_ABSTRACTION_LAYER_OPERATING_SYSTEM
#include <assert.h>
#include <intrin.h>
#define LFDS700_PAL_OS_STRING "Windows"
#define LFDS700_PAL_ASSERT( expression ) assert( expression )
#endif
/****************************************************************************/
#if( defined __GNUC__ && __STDC_HOSTED__ == 1 && !(defined __linux__ && defined _KERNEL_MODE) )
// TRD : GCC, hosted implementation (except for Linux kernel mode)
#ifdef LFDS700_PAL_PORTING_ABSTRACTION_LAYER_OPERATING_SYSTEM
#error More than one porting abstraction layer matches the current platform in lfds700_porting_abstraction_layer_operating_system.h
#endif
#define LFDS700_PAL_PORTING_ABSTRACTION_LAYER_OPERATING_SYSTEM
#include <assert.h>
#define LFDS700_PAL_OS_STRING "Embedded (hosted)"
#define LFDS700_PAL_ASSERT( expression ) assert( expression )
#endif
/****************************************************************************/
#if( defined __GNUC__ && __STDC_HOSTED__ == 0 )
// TRD : GCC, freestanding or bare implementation
#ifdef LFDS700_PAL_PORTING_ABSTRACTION_LAYER_OPERATING_SYSTEM
#error More than one porting abstraction layer matches the current platform in lfds700_porting_abstraction_layer_operating_system.h
#endif
#define LFDS700_PAL_PORTING_ABSTRACTION_LAYER_OPERATING_SYSTEM
#define LFDS700_PAL_OS_STRING "Embedded (freestanding/bare)"
#define LFDS700_PAL_ASSERT( expression )
#endif
/****************************************************************************/
#if( defined __GNUC__ && defined __linux__ && defined _KERNEL_MODE )
// TRD : GCC, Linux kernel-mode
#ifdef LFDS700_PAL_PORTING_ABSTRACTION_LAYER_OPERATING_SYSTEM
#error More than one porting abstraction layer matches the current platform in lfds700_porting_abstraction_layer_operating_system.h
#endif
#define LFDS700_PAL_PORTING_ABSTRACTION_LAYER_OPERATING_SYSTEM
#include <linux/module.h>
#define LFDS700_PAL_OS_STRING "Linux"
#define LFDS700_PAL_ASSERT( expression ) BUG_ON( expression )
#endif
/****************************************************************************/
#if( !defined LFDS700_PAL_PORTING_ABSTRACTION_LAYER_OPERATING_SYSTEM )
#error No matching porting abstraction layer in lfds700_porting_abstraction_layer_operating_system.h
#endif
/****************************************************************************/
#if( defined _MSC_VER && _MSC_VER >= 1400 && defined _M_IX86 )
/* TRD : MSVC, x86
x86 is CAS, so isolation is cache-line length
*/
#ifdef LFDS700_PAL_PORTING_ABSTRACTION_LAYER_PROCESSOR
#error More than one porting abstraction layer matches the current platform in lfds700_porting_abstraction_layer_processor.h
#endif
#define LFDS700_PAL_PORTING_ABSTRACTION_LAYER_PROCESSOR
typedef int long unsigned lfds700_pal_atom_t;
typedef int long unsigned lfds700_pal_uint_t;
#define LFDS700_PAL_PROCESSOR_STRING "x86"
#define LFDS700_PAL_ALIGN_SINGLE_POINTER 4
#define LFDS700_PAL_ALIGN_DOUBLE_POINTER 8
#define LFDS700_PAL_CACHE_LINE_LENGTH_IN_BYTES 32
#define LFDS700_PAL_ATOMIC_ISOLATION_IN_BYTES 32
#endif
/****************************************************************************/
#if( defined _MSC_VER && _MSC_VER >= 1400 && (defined _M_X64 || defined _M_AMD64) )
/* TRD : MSVC, x64
x64 is CAS, so isolation is cache-line length
*/
#ifdef LFDS700_PAL_PORTING_ABSTRACTION_LAYER_PROCESSOR
#error More than one porting abstraction layer matches the current platform in lfds700_porting_abstraction_layer_processor.h
#endif
#define LFDS700_PAL_PORTING_ABSTRACTION_LAYER_PROCESSOR
typedef int long long unsigned lfds700_pal_atom_t;
typedef int long long unsigned lfds700_pal_uint_t;
#define LFDS700_PAL_PROCESSOR_STRING "x64"
#define LFDS700_PAL_ALIGN_SINGLE_POINTER 8
#define LFDS700_PAL_ALIGN_DOUBLE_POINTER 16
#define LFDS700_PAL_CACHE_LINE_LENGTH_IN_BYTES 64
#define LFDS700_PAL_ATOMIC_ISOLATION_IN_BYTES 64
#endif
/****************************************************************************/
#if( defined _MSC_VER && _MSC_VER >= 1400 && defined _M_IA64 )
/* TRD : MSVC, Itanium
IA64 is CAS, so isolation is cache-line length
*/
#ifdef LFDS700_PAL_PORTING_ABSTRACTION_LAYER_PROCESSOR
#error More than one porting abstraction layer matches the current platform in lfds700_porting_abstraction_layer_processor.h
#endif
#define LFDS700_PAL_PORTING_ABSTRACTION_LAYER_PROCESSOR
typedef int long long unsigned lfds700_pal_atom_t;
typedef int long long unsigned lfds700_pal_uint_t;
#define LFDS700_PAL_PROCESSOR_STRING "IA64"
#define LFDS700_PAL_ALIGN_SINGLE_POINTER 8
#define LFDS700_PAL_ALIGN_DOUBLE_POINTER 16
#define LFDS700_PAL_CACHE_LINE_LENGTH_IN_BYTES 64
#define LFDS700_PAL_ATOMIC_ISOLATION_IN_BYTES 64
#endif
/****************************************************************************/
#if( defined _MSC_VER && _MSC_VER >= 1400 && defined _M_ARM )
/* TRD : MSVC, 32-bit ARM
ARM is LL/SC and uses a reservation granule of 8 to 2048 bytes
so the isolation value used here is worst-case - be sure to set
this correctly, otherwise structures are painfully large
*/
#ifdef LFDS700_PAL_PORTING_ABSTRACTION_LAYER_PROCESSOR
#error More than one porting abstraction layer matches the current platform in lfds700_porting_abstraction_layer_processor.h
#endif
#define LFDS700_PAL_PORTING_ABSTRACTION_LAYER_PROCESSOR
typedef int long unsigned lfds700_pal_atom_t;
typedef int long unsigned lfds700_pal_uint_t;
#define LFDS700_PAL_PROCESSOR_STRING "ARM (32-bit)"
#define LFDS700_PAL_ALIGN_SINGLE_POINTER 4
#define LFDS700_PAL_ALIGN_DOUBLE_POINTER 8
#define LFDS700_PAL_CACHE_LINE_LENGTH_IN_BYTES 32
#define LFDS700_PAL_ATOMIC_ISOLATION_IN_BYTES 2048
#endif
/****************************************************************************/
#if( defined __GNUC__ && defined __arm__ )
/* TRD : GCC, 32-bit ARM
ARM is LL/SC and uses a reservation granule of 8 to 2048 bytes
so the isolation value used here is worst-case - be sure to set
this correctly, otherwise structures are painfully large
*/
#ifdef LFDS700_PAL_PORTING_ABSTRACTION_LAYER_PROCESSOR
#error More than one porting abstraction layer matches the current platform in lfds700_porting_abstraction_layer_processor.h
#endif
#define LFDS700_PAL_PORTING_ABSTRACTION_LAYER_PROCESSOR
typedef int long unsigned lfds700_pal_atom_t;
typedef int long unsigned lfds700_pal_uint_t;
#define LFDS700_PAL_PROCESSOR_STRING "ARM (32-bit)"
#define LFDS700_PAL_ALIGN_SINGLE_POINTER 4
#define LFDS700_PAL_ALIGN_DOUBLE_POINTER 8
#define LFDS700_PAL_CACHE_LINE_LENGTH_IN_BYTES 32
#define LFDS700_PAL_ATOMIC_ISOLATION_IN_BYTES 2048
#endif
/****************************************************************************/
#if( defined __GNUC__ && defined __aarch64__ )
/* TRD : GCC, 64-bit ARM
ARM is LL/SC and uses a reservation granule of 8 to 2048 bytes
so the isolation value used here is worst-case - be sure to set
this correctly, otherwise structures are painfully large
*/
#ifdef LFDS700_PAL_PORTING_ABSTRACTION_LAYER_PROCESSOR
#error More than one porting abstraction layer matches the current platform in lfds700_porting_abstraction_layer_processor.h
#endif
#define LFDS700_PAL_PORTING_ABSTRACTION_LAYER_PROCESSOR
typedef int long long unsigned lfds700_pal_atom_t;
typedef int long long unsigned lfds700_pal_uint_t;
#define LFDS700_PAL_PROCESSOR_STRING "ARM (64-bit)"
#define LFDS700_PAL_ALIGN_SINGLE_POINTER 8
#define LFDS700_PAL_ALIGN_DOUBLE_POINTER 16
#define LFDS700_PAL_CACHE_LINE_LENGTH_IN_BYTES 64
#define LFDS700_PAL_ATOMIC_ISOLATION_IN_BYTES 2048
#endif
/****************************************************************************/
#if( defined __GNUC__ && (defined __i686__ || defined __i586__ || defined __i486__) )
/* TRD : GCC, x86
x86 is CAS, so isolation is cache-line length
*/
#ifdef LFDS700_PAL_PORTING_ABSTRACTION_LAYER_PROCESSOR
#error More than one porting abstraction layer matches the current platform in lfds700_porting_abstraction_layer_processor.h
#endif
#define LFDS700_PAL_PORTING_ABSTRACTION_LAYER_PROCESSOR
typedef int long unsigned lfds700_pal_atom_t;
typedef int long unsigned lfds700_pal_uint_t;
#define LFDS700_PAL_PROCESSOR_STRING "x86"
#define LFDS700_PAL_ALIGN_SINGLE_POINTER 4
#define LFDS700_PAL_ALIGN_DOUBLE_POINTER 8
#define LFDS700_PAL_CACHE_LINE_LENGTH_IN_BYTES 32
#define LFDS700_PAL_ATOMIC_ISOLATION_IN_BYTES 32
#endif
/****************************************************************************/
#if( defined __GNUC__ && defined __x86_64__ )
/* TRD : GCC, x86
x64 is CAS, so isolation is cache-line length
*/
#ifdef LFDS700_PAL_PORTING_ABSTRACTION_LAYER_PROCESSOR
#error More than one porting abstraction layer matches the current platform in lfds700_porting_abstraction_layer_processor.h
#endif
#define LFDS700_PAL_PORTING_ABSTRACTION_LAYER_PROCESSOR
typedef int long long unsigned lfds700_pal_atom_t;
typedef int long long unsigned lfds700_pal_uint_t;
#define LFDS700_PAL_PROCESSOR_STRING "x64"
#define LFDS700_PAL_ALIGN_SINGLE_POINTER 8
#define LFDS700_PAL_ALIGN_DOUBLE_POINTER 16
#define LFDS700_PAL_CACHE_LINE_LENGTH_IN_BYTES 64
#define LFDS700_PAL_ATOMIC_ISOLATION_IN_BYTES 64
#endif
/****************************************************************************/
#if( defined __GNUC__ && defined __alpha__ )
/* TRD : GCC, alpha
alpha is LL/SC, but there is only one reservation per processor,
so the isolation value used here is cache-line length
*/
#ifdef LFDS700_PAL_PORTING_ABSTRACTION_LAYER_PROCESSOR
#error More than one porting abstraction layer matches the current platform in lfds700_porting_abstraction_layer_processor.h
#endif
#define LFDS700_PAL_PORTING_ABSTRACTION_LAYER_PROCESSOR
typedef int long unsigned lfds700_pal_atom_t;
typedef int long unsigned lfds700_pal_uint_t;
#define LFDS700_PAL_PROCESSOR_STRING "alpha"
#define LFDS700_PAL_ALIGN_SINGLE_POINTER 8
#define LFDS700_PAL_ALIGN_DOUBLE_POINTER 16
#define LFDS700_PAL_CACHE_LINE_LENGTH_IN_BYTES 32
#define LFDS700_PAL_ATOMIC_ISOLATION_IN_BYTES 64
#endif
/****************************************************************************/
#if( defined __GNUC__ && defined __ia64__ )
/* TRD : GCC, Itanium
Itanium is CAS, so isolation is cache-line length
*/
#ifdef LFDS700_PAL_PORTING_ABSTRACTION_LAYER_PROCESSOR
#error More than one porting abstraction layer matches the current platform in lfds700_porting_abstraction_layer_processor.h
#endif
#define LFDS700_PAL_PORTING_ABSTRACTION_LAYER_PROCESSOR
typedef int long long unsigned lfds700_pal_atom_t;
typedef int long long unsigned lfds700_pal_uint_t;
#define LFDS700_PAL_PROCESSOR_STRING "IA64"
#define LFDS700_PAL_ALIGN_SINGLE_POINTER 8
#define LFDS700_PAL_ALIGN_DOUBLE_POINTER 16
#define LFDS700_PAL_CACHE_LINE_LENGTH_IN_BYTES 64
#define LFDS700_PAL_ATOMIC_ISOLATION_IN_BYTES 64
#endif
/****************************************************************************/
#if( defined __GNUC__ && defined __mips__ )
/* TRD : GCC, MIPS (32-bit)
MIPS is LL/SC, but there is only one reservation per processor,
so the isolation value used here is cache-line length
*/
#ifdef LFDS700_PAL_PORTING_ABSTRACTION_LAYER_PROCESSOR
#error More than one porting abstraction layer matches the current platform in lfds700_porting_abstraction_layer_processor.h
#endif
#define LFDS700_PAL_PORTING_ABSTRACTION_LAYER_PROCESSOR
typedef int long unsigned lfds700_pal_atom_t;
typedef int long unsigned lfds700_pal_uint_t;
#define LFDS700_PAL_PROCESSOR_STRING "MIPS (32-bit)"
#define LFDS700_PAL_ALIGN_SINGLE_POINTER 4
#define LFDS700_PAL_ALIGN_DOUBLE_POINTER 8
#define LFDS700_PAL_CACHE_LINE_LENGTH_IN_BYTES 32
#define LFDS700_PAL_ATOMIC_ISOLATION_IN_BYTES 32
#endif
/****************************************************************************/
#if( defined __GNUC__ && defined __mips64 )
/* TRD : GCC, MIPS (64-bit)
MIPS is LL/SC, but there is only one reservation per processor,
so the isolation value used here is cache-line length
*/
#ifdef LFDS700_PAL_PORTING_ABSTRACTION_LAYER_PROCESSOR
#error More than one porting abstraction layer matches the current platform in lfds700_porting_abstraction_layer_processor.h
#endif
#define LFDS700_PAL_PORTING_ABSTRACTION_LAYER_PROCESSOR
typedef int long long unsigned lfds700_pal_atom_t;
typedef int long long unsigned lfds700_pal_uint_t;
#define LFDS700_PAL_PROCESSOR_STRING "MIPS (64-bit)"
#define LFDS700_PAL_ALIGN_SINGLE_POINTER 8
#define LFDS700_PAL_ALIGN_DOUBLE_POINTER 16
#define LFDS700_PAL_CACHE_LINE_LENGTH_IN_BYTES 64
#define LFDS700_PAL_ATOMIC_ISOLATION_IN_BYTES 64
#endif
/****************************************************************************/
#if( defined __GNUC__ && defined __ppc__ )
/* TRD : GCC, POWERPC (32-bit)
POWERPC is LL/SC and uses a reservation granule but I can't find
canonical documentation for its size - 128 bytes seems to be the
largest value I've found
*/
#ifdef LFDS700_PAL_PORTING_ABSTRACTION_LAYER_PROCESSOR
#error More than one porting abstraction layer matches the current platform in lfds700_porting_abstraction_layer_processor.h
#endif
#define LFDS700_PAL_PORTING_ABSTRACTION_LAYER_PROCESSOR
typedef int long unsigned lfds700_pal_atom_t;
typedef int long unsigned lfds700_pal_uint_t;
#define LFDS700_PAL_PROCESSOR_STRING "POWERPC (32-bit)"
#define LFDS700_PAL_ALIGN_SINGLE_POINTER 4
#define LFDS700_PAL_ALIGN_DOUBLE_POINTER 8
#define LFDS700_PAL_CACHE_LINE_LENGTH_IN_BYTES 32
#define LFDS700_PAL_ATOMIC_ISOLATION_IN_BYTES 128
#endif
/****************************************************************************/
#if( defined __GNUC__ && defined __ppc64__ )
/* TRD : GCC, POWERPC (64-bit)
POWERPC is LL/SC and uses a reservation granule but I can't find
canonical documentation for its size - 128 bytes seems to be the
largest value I've found
*/
#ifdef LFDS700_PAL_PORTING_ABSTRACTION_LAYER_PROCESSOR
#error More than one porting abstraction layer matches the current platform in lfds700_porting_abstraction_layer_processor.h
#endif
#define LFDS700_PAL_PORTING_ABSTRACTION_LAYER_PROCESSOR
typedef int long long unsigned lfds700_pal_atom_t;
typedef int long long unsigned lfds700_pal_uint_t;
#define LFDS700_PAL_PROCESSOR_STRING "POWERPC (64-bit)"
#define LFDS700_PAL_ALIGN_SINGLE_POINTER 8
#define LFDS700_PAL_ALIGN_DOUBLE_POINTER 16
#define LFDS700_PAL_CACHE_LINE_LENGTH_IN_BYTES 64
#define LFDS700_PAL_ATOMIC_ISOLATION_IN_BYTES 128
#endif
/****************************************************************************/
#if( defined __GNUC__ && defined __sparc__ && !defined __sparc_v9__ )
/* TRD : GCC, SPARC (32-bit)
SPARC is CAS, so isolation is cache-line length
*/
#ifdef LFDS700_PAL_PORTING_ABSTRACTION_LAYER_PROCESSOR
#error More than one porting abstraction layer matches the current platform in lfds700_porting_abstraction_layer_processor.h
#endif
#define LFDS700_PAL_PORTING_ABSTRACTION_LAYER_PROCESSOR
typedef int long unsigned lfds700_pal_atom_t;
typedef int long unsigned lfds700_pal_uint_t;
#define LFDS700_PAL_PROCESSOR_STRING "SPARC (32-bit)"
#define LFDS700_PAL_ALIGN_SINGLE_POINTER 4
#define LFDS700_PAL_ALIGN_DOUBLE_POINTER 8
#define LFDS700_PAL_CACHE_LINE_LENGTH_IN_BYTES 32
#define LFDS700_PAL_ATOMIC_ISOLATION_IN_BYTES 32
#endif
/****************************************************************************/
#if( defined __GNUC__ && defined __sparc__ && defined __sparc_v9__ )
/* TRD : GCC, SPARC (64-bit)
SPARC is CAS, so isolation is cache-line length
*/
#ifdef LFDS700_PAL_PORTING_ABSTRACTION_LAYER_PROCESSOR
#error More than one porting abstraction layer matches the current platform in lfds700_porting_abstraction_layer_processor.h
#endif
#define LFDS700_PAL_PORTING_ABSTRACTION_LAYER_PROCESSOR
typedef int long long unsigned lfds700_pal_atom_t;
typedef int long long unsigned lfds700_pal_uint_t;
#define LFDS700_PAL_PROCESSOR_STRING "SPARC (64-bit)"
#define LFDS700_PAL_ALIGN_SINGLE_POINTER 8
#define LFDS700_PAL_ALIGN_DOUBLE_POINTER 16
#define LFDS700_PAL_CACHE_LINE_LENGTH_IN_BYTES 64
#define LFDS700_PAL_ATOMIC_ISOLATION_IN_BYTES 64
#endif
/****************************************************************************/
#if( defined __GNUC__ && defined __m68k__ )
/* TRD : GCC, 680x0
680x0 is CAS, so isolation is cache-line length
*/
#ifdef LFDS700_PAL_PORTING_ABSTRACTION_LAYER_PROCESSOR
#error More than one porting abstraction layer matches the current platform in lfds700_porting_abstraction_layer_processor.h
#endif
#define LFDS700_PAL_PORTING_ABSTRACTION_LAYER_PROCESSOR
typedef int long unsigned lfds700_pal_atom_t;
typedef int long unsigned lfds700_pal_uint_t;
#define LFDS700_PAL_PROCESSOR_STRING "680x0"
#define LFDS700_PAL_ALIGN_SINGLE_POINTER 4
#define LFDS700_PAL_ALIGN_DOUBLE_POINTER 8
#define LFDS700_PAL_CACHE_LINE_LENGTH_IN_BYTES 32
#define LFDS700_PAL_ATOMIC_ISOLATION_IN_BYTES 32
#endif
/****************************************************************************/
#if( !defined LFDS700_PAL_PORTING_ABSTRACTION_LAYER_PROCESSOR )
#error No matching porting abstraction layer in lfds700_porting_abstraction_layer_processor.h
#endif
/***** defines *****/
#define LFDS700_QUEUE_GET_KEY_FROM_ELEMENT( queue_element ) ( (queue_element).key )
#define LFDS700_QUEUE_SET_KEY_IN_ELEMENT( queue_element, new_key ) ( (queue_element).key = (void *) (lfds700_pal_uint_t) (new_key) )
#define LFDS700_QUEUE_GET_VALUE_FROM_ELEMENT( queue_element ) ( (queue_element).value )
#define LFDS700_QUEUE_SET_VALUE_IN_ELEMENT( queue_element, new_value ) ( (queue_element).value = (void *) (lfds700_pal_uint_t) (new_value) )
#define LFDS700_QUEUE_GET_USER_STATE_FROM_STATE( queue_state ) ( (queue_state).user_state )
/***** enums *****/
enum lfds700_queue_query
{
LFDS700_QUEUE_QUERY_SINGLETHREADED_GET_COUNT,
LFDS700_QUEUE_QUERY_SINGLETHREADED_VALIDATE
};
/***** structures *****/
struct lfds700_queue_element
{
struct lfds700_queue_element LFDS700_PAL_ALIGN(LFDS700_PAL_ATOMIC_ISOLATION_IN_BYTES)
*volatile next[PAC_SIZE];
void LFDS700_PAL_ALIGN(LFDS700_PAL_ATOMIC_ISOLATION_IN_BYTES)
*key;
void
*value;
};
struct lfds700_queue_state
{
struct lfds700_queue_element LFDS700_PAL_ALIGN(LFDS700_PAL_ATOMIC_ISOLATION_IN_BYTES)
*volatile enqueue[PAC_SIZE],
*volatile dequeue[PAC_SIZE];
void LFDS700_PAL_ALIGN(LFDS700_PAL_ATOMIC_ISOLATION_IN_BYTES)
*user_state;
};
/***** public prototypes *****/
void lfds700_queue_init_valid_on_current_logical_core( struct lfds700_queue_state *qs,
struct lfds700_queue_element *qe_dummy,
struct lfds700_misc_prng_state *ps,
void *user_state );
// TRD : used in conjunction with the #define LFDS700_MISC_MAKE_VALID_ON_CURRENT_LOGICAL_CORE_INITS_COMPLETED_BEFORE_NOW_ON_ANY_OTHER_LOGICAL_CORE
void lfds700_queue_cleanup( struct lfds700_queue_state *qs,
void (*element_cleanup_callback)(struct lfds700_queue_state *qs, struct lfds700_queue_element *qe, enum lfds700_misc_flag dummy_element_flag) );
void lfds700_queue_enqueue( struct lfds700_queue_state *qs,
struct lfds700_queue_element *qe,
struct lfds700_misc_prng_state *ps );
int lfds700_queue_dequeue( struct lfds700_queue_state *qs,
struct lfds700_queue_element **qe,
struct lfds700_misc_prng_state *ps );
void lfds700_queue_query( struct lfds700_queue_state *qs,
enum lfds700_queue_query query_type,
void *query_input,
void *query_output );
/***** defines *****/
#define LFDS700_QUEUE_BSS_GET_USER_STATE_FROM_STATE( queue_bss_state ) ( (queue_bss_state).user_state )
/***** enums *****/
enum lfds700_queue_bss_query
{
LFDS700_QUEUE_BSS_QUERY_GET_POTENTIALLY_INACCURATE_COUNT,
LFDS700_QUEUE_BSS_QUERY_VALIDATE
};
/***** structures *****/
struct lfds700_queue_bss_element
{
void
*volatile key,
*volatile value;
};
struct lfds700_queue_bss_state
{
lfds700_pal_uint_t
number_elements,
mask;
lfds700_pal_uint_t volatile
read_index,
write_index;
struct lfds700_queue_bss_element
*element_array;
void
*user_state;
};
/***** public prototypes *****/
void lfds700_queue_bss_init_valid_on_current_logical_core( struct lfds700_queue_bss_state *qbsss,
struct lfds700_queue_bss_element *element_array,
lfds700_pal_uint_t number_elements,
void *user_state );
// TRD : number_elements must be a positive integer power of 2
// TRD : used in conjunction with the #define LFDS700_MISC_MAKE_VALID_ON_CURRENT_LOGICAL_CORE_INITS_COMPLETED_BEFORE_NOW_ON_ANY_OTHER_LOGICAL_CORE
void lfds700_queue_bss_cleanup( struct lfds700_queue_bss_state *qbsss,
void (*element_cleanup_callback)(struct lfds700_queue_bss_state *qbsss, void *key, void *value) );
int lfds700_queue_bss_enqueue( struct lfds700_queue_bss_state *qbsss,
void *key,
void *value );
int lfds700_queue_bss_dequeue( struct lfds700_queue_bss_state *qbsss,
void **key,
void **value );
void lfds700_queue_bss_query( struct lfds700_queue_bss_state *qbsss,
enum lfds700_queue_bss_query query_type,
void *query_input,
void *query_output );
/***** enums *****/
#define LFDS700_RINGBUFFER_GET_USER_STATE_FROM_STATE( ringbuffer_state ) ( (ringbuffer_state).user_state )
/***** enums *****/
enum lfds700_ringbuffer_query
{
LFDS700_RINGBUFFER_QUERY_SINGLETHREADED_GET_COUNT,
LFDS700_RINGBUFFER_QUERY_SINGLETHREADED_VALIDATE
};
/***** structures *****/
struct lfds700_ringbuffer_element
{
struct lfds700_freelist_element LFDS700_PAL_ALIGN(LFDS700_PAL_ATOMIC_ISOLATION_IN_BYTES)
fe;
struct lfds700_queue_element LFDS700_PAL_ALIGN(LFDS700_PAL_ATOMIC_ISOLATION_IN_BYTES)
qe;
struct lfds700_queue_element
*qe_use; // TRD : hack for 7.0.0; we need a new queue with no dummy element
void
*key,
*value;
};
struct lfds700_ringbuffer_state
{
struct lfds700_freelist_state LFDS700_PAL_ALIGN(LFDS700_PAL_ATOMIC_ISOLATION_IN_BYTES)
fs;
struct lfds700_queue_state LFDS700_PAL_ALIGN(LFDS700_PAL_ATOMIC_ISOLATION_IN_BYTES)
qs;
void
(*element_cleanup_callback)( struct lfds700_ringbuffer_state *rs, void *key, void *value, enum lfds700_misc_flag unread_flag ),
*user_state;
};
/***** public prototypes *****/
void lfds700_ringbuffer_init_valid_on_current_logical_core( struct lfds700_ringbuffer_state *rs,
struct lfds700_ringbuffer_element *re_array_inc_dummy,
lfds700_pal_uint_t number_elements,
struct lfds700_misc_prng_state *ps,
void *user_state );
// TRD : used in conjunction with the #define LFDS700_MISC_MAKE_VALID_ON_CURRENT_LOGICAL_CORE_INITS_COMPLETED_BEFORE_NOW_ON_ANY_OTHER_LOGICAL_CORE
void lfds700_ringbuffer_cleanup( struct lfds700_ringbuffer_state *rs,
void (*element_cleanup_callback)(struct lfds700_ringbuffer_state *rs, void *key, void *value, enum lfds700_misc_flag unread_flag) );
int lfds700_ringbuffer_read( struct lfds700_ringbuffer_state *rs,
void **key,
void **value,
struct lfds700_misc_prng_state *ps );
void lfds700_ringbuffer_write( struct lfds700_ringbuffer_state *rs,
void *key,
void *value,
enum lfds700_misc_flag *overwrite_occurred_flag,
void **overwritten_key,
void **overwritten_value,
struct lfds700_misc_prng_state *ps );
void lfds700_ringbuffer_query( struct lfds700_ringbuffer_state *rs,
enum lfds700_ringbuffer_query query_type,
void *query_input,
void *query_output );
/***** defines *****/
#define LFDS700_STACK_GET_KEY_FROM_ELEMENT( stack_element ) ( (stack_element).key )
#define LFDS700_STACK_SET_KEY_IN_ELEMENT( stack_element, new_key ) ( (stack_element).key = (void *) (lfds700_pal_uint_t) (new_key) )
#define LFDS700_STACK_GET_VALUE_FROM_ELEMENT( stack_element ) ( (stack_element).value )
#define LFDS700_STACK_SET_VALUE_IN_ELEMENT( stack_element, new_value ) ( (stack_element).value = (void *) (lfds700_pal_uint_t) (new_value) )
#define LFDS700_STACK_GET_USER_STATE_FROM_STATE( stack_state ) ( (stack_state).user_state )
/***** enums *****/
enum lfds700_stack_query
{
LFDS700_STACK_QUERY_SINGLETHREADED_GET_COUNT,
LFDS700_STACK_QUERY_SINGLETHREADED_VALIDATE
};
/***** structures *****/
struct lfds700_stack_element
{
struct lfds700_stack_element
*volatile next;
void
*key,
*value;
};
struct lfds700_stack_state
{
struct lfds700_stack_element LFDS700_PAL_ALIGN(LFDS700_PAL_ATOMIC_ISOLATION_IN_BYTES)
*volatile top[PAC_SIZE];
void LFDS700_PAL_ALIGN(LFDS700_PAL_ATOMIC_ISOLATION_IN_BYTES)
*user_state;
};
/***** public prototypes *****/
void lfds700_stack_init_valid_on_current_logical_core( struct lfds700_stack_state *ss, void *user_state );
// TRD : used in conjunction with the #define LFDS700_MISC_MAKE_VALID_ON_CURRENT_LOGICAL_CORE_INITS_COMPLETED_BEFORE_NOW_ON_ANY_OTHER_LOGICAL_CORE
void lfds700_stack_cleanup( struct lfds700_stack_state *ss,
void (*element_cleanup_callback)(struct lfds700_stack_state *ss, struct lfds700_stack_element *se) );
void lfds700_stack_push( struct lfds700_stack_state *ss,
struct lfds700_stack_element *se,
struct lfds700_misc_prng_state *ps );
int lfds700_stack_pop( struct lfds700_stack_state *ss,
struct lfds700_stack_element **se,
struct lfds700_misc_prng_state *ps );
void lfds700_stack_query( struct lfds700_stack_state *ss,
enum lfds700_stack_query query_type,
void *query_input,
void *query_output );
/***** includes *****/
#include "lfds700_btree_addonly_unbalanced_internal.h"
/****************************************************************************/
void lfds700_btree_au_cleanup( struct lfds700_btree_au_state *baus,
void (*element_cleanup_callback)(struct lfds700_btree_au_state *baus, struct lfds700_btree_au_element *baue) )
{
enum lfds700_btree_au_delete_action
delete_action = LFDS700_BTREE_AU_DELETE_SELF; // TRD : to remove compiler warning
struct lfds700_btree_au_element
*baue;
struct lfds700_btree_au_element
*temp;
LFDS700_PAL_ASSERT( baus != NULL );
// TRD : element_delete_function can be NULL
/* TRD : we're not lock-free now, so delete at will
but be iterative, so can be used in kernels (where there's little stack)
and be performant, since the user may be
creating/destroying many of these trees
also remember the user may be deallocating user data
so we cannot visit an element twice
we start at the root and iterate till we go to NULL
if the element has zero children, we delete it and move up to its parent
if the element has one child, we delete it, move its child into its place, and continue from its child
if the element has two children, we move left
the purpose of this is to minimize walking around the tree
to prevent visiting an element twice
while also minimizing code complexity
*/
if( element_cleanup_callback == NULL )
return;
LFDS700_MISC_BARRIER_LOAD;
lfds700_btree_au_get_by_absolute_position( baus, &baue, LFDS700_BTREE_AU_ABSOLUTE_POSITION_ROOT );
while( baue != NULL )
{
if( baue->left == NULL and baue->right == NULL )
delete_action = LFDS700_BTREE_AU_DELETE_SELF;
if( baue->left != NULL and baue->right == NULL )
delete_action = LFDS700_BTREE_AU_DELETE_SELF_REPLACE_WITH_LEFT_CHILD;
if( baue->left == NULL and baue->right != NULL )
delete_action = LFDS700_BTREE_AU_DELETE_SELF_REPLACE_WITH_RIGHT_CHILD;
if( baue->left != NULL and baue->right != NULL )
delete_action = LFDS700_BTREE_AU_DELETE_MOVE_LEFT;
switch( delete_action )
{
case LFDS700_BTREE_AU_DELETE_SELF:
// TRD : if we have a parent (we could be root) set his point to us to NULL
if( baue->up != NULL )
{
if( baue->up->left == baue )
baue->up->left = NULL;
if( baue->up->right == baue )
baue->up->right = NULL;
}
temp = baue;
lfds700_btree_au_get_by_relative_position( &baue, LFDS700_BTREE_AU_RELATIVE_POSITION_UP );
element_cleanup_callback( baus, temp );
break;
case LFDS700_BTREE_AU_DELETE_SELF_REPLACE_WITH_LEFT_CHILD:
baue->left->up = baue->up;
if( baue->up != NULL )
{
if( baue->up->left == baue )
baue->up->left = baue->left;
if( baue->up->right == baue )
baue->up->right = baue->left;
}
temp = baue;
lfds700_btree_au_get_by_relative_position( &baue, LFDS700_BTREE_AU_RELATIVE_POSITION_LEFT );
element_cleanup_callback( baus, temp );
break;
case LFDS700_BTREE_AU_DELETE_SELF_REPLACE_WITH_RIGHT_CHILD:
baue->right->up = baue->up;
if( baue->up != NULL )
{
if( baue->up->left == baue )
baue->up->left = baue->right;
if( baue->up->right == baue )
baue->up->right = baue->right;
}
temp = baue;
lfds700_btree_au_get_by_relative_position( &baue, LFDS700_BTREE_AU_RELATIVE_POSITION_RIGHT );
element_cleanup_callback( baus, temp );
break;
case LFDS700_BTREE_AU_DELETE_MOVE_LEFT:
lfds700_btree_au_get_by_relative_position( &baue, LFDS700_BTREE_AU_RELATIVE_POSITION_LEFT );
break;
}
}
return;
}
/***** includes *****/
#include "lfds700_btree_addonly_unbalanced_internal.h"
/***** private prototypes *****/
static void lfds700_btree_au_internal_inorder_walk_from_largest_get_next_smallest_element( struct lfds700_btree_au_element **baue );
static void lfds700_btree_au_internal_inorder_walk_from_smallest_get_next_largest_element( struct lfds700_btree_au_element **baue );
/****************************************************************************/
int lfds700_btree_au_get_by_key( struct lfds700_btree_au_state *baus,
void *key,
struct lfds700_btree_au_element **baue )
{
int
compare_result = !0,
rv = 1;
LFDS700_PAL_ASSERT( baus != NULL );
// TRD : key can be NULL
LFDS700_PAL_ASSERT( baue != NULL );
LFDS700_MISC_BARRIER_LOAD;
*baue = baus->root;
LFDS700_MISC_BARRIER_LOAD;
while( *baue != NULL and compare_result != 0 )
{
compare_result = baus->key_compare_function( key, (*baue)->key );
if( compare_result < 0 )
{
*baue = (*baue)->left;
LFDS700_MISC_BARRIER_LOAD;
}
if( compare_result > 0 )
{
*baue = (*baue)->right;
LFDS700_MISC_BARRIER_LOAD;
}
}
if( *baue == NULL )
rv = 0;
return( rv );
}
/****************************************************************************/
int lfds700_btree_au_get_by_absolute_position( struct lfds700_btree_au_state *baus, struct lfds700_btree_au_element **baue, enum lfds700_btree_au_absolute_position absolute_position )
{
int
rv = 1;
LFDS700_PAL_ASSERT( baus != NULL );
LFDS700_PAL_ASSERT( baue != NULL );
// TRD : absolute_position can be any value in its range
LFDS700_MISC_BARRIER_LOAD;
*baue = baus->root;
LFDS700_MISC_BARRIER_LOAD;
switch( absolute_position )
{
case LFDS700_BTREE_AU_ABSOLUTE_POSITION_ROOT:
break;
case LFDS700_BTREE_AU_ABSOLUTE_POSITION_LARGEST_IN_TREE:
if( *baue != NULL )
while( (*baue)->right != NULL )
{
*baue = (*baue)->right;
LFDS700_MISC_BARRIER_LOAD;
}
break;
case LFDS700_BTREE_AU_ABSOLUTE_POSITION_SMALLEST_IN_TREE:
if( *baue != NULL )
while( (*baue)->left != NULL )
{
*baue = (*baue)->left;
LFDS700_MISC_BARRIER_LOAD;
}
break;
}
if( *baue == NULL )
rv = 0;
return( rv );
}
/****************************************************************************/
int lfds700_btree_au_get_by_relative_position( struct lfds700_btree_au_element **baue, enum lfds700_btree_au_relative_position relative_position )
{
int
rv = 1;
LFDS700_PAL_ASSERT( baue != NULL );
// TRD : relative_position can baue any value in its range
if( *baue == NULL )
return( 0 );
LFDS700_MISC_BARRIER_LOAD;
switch( relative_position )
{
case LFDS700_BTREE_AU_RELATIVE_POSITION_UP:
*baue = (*baue)->up;
// TRD : no load barrier - up already existed, so is known to be safely propagated
break;
case LFDS700_BTREE_AU_RELATIVE_POSITION_LEFT:
*baue = (*baue)->left;
LFDS700_MISC_BARRIER_LOAD;
break;
case LFDS700_BTREE_AU_RELATIVE_POSITION_RIGHT:
*baue = (*baue)->right;
LFDS700_MISC_BARRIER_LOAD;
break;
case LFDS700_BTREE_AU_RELATIVE_POSITION_SMALLEST_ELEMENT_BELOW_CURRENT_ELEMENT:
*baue = (*baue)->left;
if( *baue != NULL )
{
LFDS700_MISC_BARRIER_LOAD;
while( (*baue)->right != NULL )
{
*baue = (*baue)->right;
LFDS700_MISC_BARRIER_LOAD;
}
}
break;
case LFDS700_BTREE_AU_RELATIVE_POSITION_LARGEST_ELEMENT_BELOW_CURRENT_ELEMENT:
*baue = (*baue)->right;
if( *baue != NULL )
{
LFDS700_MISC_BARRIER_LOAD;
while( (*baue)->left != NULL )
{
*baue = (*baue)->left;
LFDS700_MISC_BARRIER_LOAD;
}
}
break;
case LFDS700_BTREE_AU_RELATIVE_POSITION_NEXT_SMALLER_ELEMENT_IN_ENTIRE_TREE:
lfds700_btree_au_internal_inorder_walk_from_largest_get_next_smallest_element( baue );
break;
case LFDS700_BTREE_AU_RELATIVE_POSITION_NEXT_LARGER_ELEMENT_IN_ENTIRE_TREE:
lfds700_btree_au_internal_inorder_walk_from_smallest_get_next_largest_element( baue );
break;
}
if( *baue == NULL )
rv = 0;
return( rv );
}
/****************************************************************************/
static void lfds700_btree_au_internal_inorder_walk_from_largest_get_next_smallest_element( struct lfds700_btree_au_element **baue )
{
enum lfds700_btree_au_move
action = LFDS700_BTREE_AU_MOVE_INVALID;
enum lfds700_misc_flag
finished_flag = LFDS700_MISC_FLAG_LOWERED,
load_finished_flag = LFDS700_MISC_FLAG_LOWERED;
struct lfds700_btree_au_element
*left = NULL,
*right = NULL,
*up = NULL,
*up_left = NULL,
*up_right = NULL;
LFDS700_PAL_ASSERT( baue != NULL );
/* TRD : from any given element, the next smallest element is;
1. if we have a left, it's the largest element on the right branch of our left child
2. if we don't have a left, and we're on the right of our parent, then it's our parent
3. if we don't have a left, and we're on the left of our parent or we have no parent,
iterative up the tree until we find the first child who is on the right of its parent; then it's the parent
*/
/* TRD : we need to ensure the variables we use to decide our action are self-consistent
to do this, we make local copies of them all
then, if they are all not NULL, we can know they cannot change and we can continue
if however any of them are NULL, they could have changed while we were reading
and so our variables could be non-self-consistent
to check for this, we issue another processor read barrier
and then compare our local variables with the values in the tree
if they all match, then we know our variable set is self-consistent
(even though it may now be wrong - but we will discover this when we try the atomic operation)
*/
LFDS700_MISC_BARRIER_LOAD;
while( load_finished_flag == LFDS700_MISC_FLAG_LOWERED )
{
left = (*baue)->left;
right = (*baue)->right;
up = (*baue)->up;
if( up != NULL )
{
up_left = (*baue)->up->left;
up_right = (*baue)->up->right;
}
if( left != NULL and right != NULL and (up == NULL or (up != NULL and up_left != NULL and up_right != NULL)) )
break;
LFDS700_MISC_BARRIER_LOAD;
if( left == (*baue)->left and right == (*baue)->right and (up == NULL or (up != NULL and up == (*baue)->up and up_left == (*baue)->up->left and up_right == (*baue)->up->right)) )
load_finished_flag = LFDS700_MISC_FLAG_RAISED;
}
if( left != NULL )
action = LFDS700_BTREE_AU_MOVE_LARGEST_FROM_LEFT_CHILD;
if( left == NULL and up != NULL and up_right == *baue )
action = LFDS700_BTREE_AU_MOVE_GET_PARENT;
if( (left == NULL and up == NULL) or (up != NULL and up_left == *baue and left == NULL) )
action = LFDS700_BTREE_AU_MOVE_MOVE_UP_TREE;
switch( action )
{
case LFDS700_BTREE_AU_MOVE_INVALID:
case LFDS700_BTREE_AU_MOVE_SMALLEST_FROM_RIGHT_CHILD:
// TRD : eliminates a compiler warning
break;
case LFDS700_BTREE_AU_MOVE_LARGEST_FROM_LEFT_CHILD:
*baue = left;
if( *baue != NULL )
{
LFDS700_MISC_BARRIER_LOAD;
while( (*baue)->right != NULL )
{
*baue = (*baue)->right;
LFDS700_MISC_BARRIER_LOAD;
}
}
break;
case LFDS700_BTREE_AU_MOVE_GET_PARENT:
*baue = up;
break;
case LFDS700_BTREE_AU_MOVE_MOVE_UP_TREE:
while( finished_flag == LFDS700_MISC_FLAG_LOWERED )
{
load_finished_flag = LFDS700_MISC_FLAG_LOWERED;
while( load_finished_flag == LFDS700_MISC_FLAG_LOWERED )
{
up = (*baue)->up;
if( up != NULL )
up_left = (*baue)->up->left;
if( up == NULL or (up != NULL and up_left != NULL) )
break;
LFDS700_MISC_BARRIER_LOAD;
if( up == (*baue)->up and up_left == (*baue)->up->left )
load_finished_flag = LFDS700_MISC_FLAG_RAISED;
}
if( *baue != NULL and up != NULL and *baue == up_left )
*baue = up;
else
finished_flag = LFDS700_MISC_FLAG_RAISED;
}
*baue = up;
/*
while( *baue != NULL and (*baue)->up != NULL and *baue == (*baue)->up->left )
*baue = (*baue)->up;
*baue = (*baue)->up;
*/
break;
}
return;
}
/****************************************************************************/
static void lfds700_btree_au_internal_inorder_walk_from_smallest_get_next_largest_element( struct lfds700_btree_au_element **baue )
{
enum lfds700_btree_au_move
action = LFDS700_BTREE_AU_MOVE_INVALID;
enum lfds700_misc_flag
finished_flag = LFDS700_MISC_FLAG_LOWERED,
load_finished_flag = LFDS700_MISC_FLAG_LOWERED;
struct lfds700_btree_au_element
*left = NULL,
*right = NULL,
*up = NULL,
*up_left = NULL,
*up_right = NULL;
LFDS700_PAL_ASSERT( baue != NULL );
/* TRD : from any given element, the next largest element is;
1. if we have a right, it's the smallest element on the left branch of our right child
2. if we don't have a right, and we're on the left of our parent, then it's our parent
3. if we don't have a right, and we're on the right of our parent or we have no parent,
iterate up the tree until we find the first child who is on the left of its parent; then it's the parent
*/
LFDS700_MISC_BARRIER_LOAD;
while( load_finished_flag == LFDS700_MISC_FLAG_LOWERED )
{
left = (*baue)->left;
right = (*baue)->right;
up = (*baue)->up;
if( up != NULL )
{
up_left = (*baue)->up->left;
up_right = (*baue)->up->right;
}
if( left != NULL and right != NULL and (up == NULL or (up != NULL and up_left != NULL and up_right != NULL)) )
break;
LFDS700_MISC_BARRIER_LOAD;
if( left == (*baue)->left and right == (*baue)->right and (up == NULL or (up != NULL and up == (*baue)->up and up_left == (*baue)->up->left and up_right == (*baue)->up->right)) )
load_finished_flag = LFDS700_MISC_FLAG_RAISED;
}
if( right != NULL )
action = LFDS700_BTREE_AU_MOVE_SMALLEST_FROM_RIGHT_CHILD;
if( right == NULL and up != NULL and up_left == *baue )
action = LFDS700_BTREE_AU_MOVE_GET_PARENT;
if( (right == NULL and up == NULL) or (up != NULL and up_right == *baue and right == NULL) )
action = LFDS700_BTREE_AU_MOVE_MOVE_UP_TREE;
switch( action )
{
case LFDS700_BTREE_AU_MOVE_INVALID:
case LFDS700_BTREE_AU_MOVE_LARGEST_FROM_LEFT_CHILD:
// TRD : remove compiler warning
break;
case LFDS700_BTREE_AU_MOVE_SMALLEST_FROM_RIGHT_CHILD:
*baue = right;
if( *baue != NULL )
{
LFDS700_MISC_BARRIER_LOAD;
while( (*baue)->left != NULL )
{
*baue = (*baue)->left;
LFDS700_MISC_BARRIER_LOAD;
}
}
break;
case LFDS700_BTREE_AU_MOVE_GET_PARENT:
*baue = up;
break;
case LFDS700_BTREE_AU_MOVE_MOVE_UP_TREE:
while( finished_flag == LFDS700_MISC_FLAG_LOWERED )
{
load_finished_flag = LFDS700_MISC_FLAG_LOWERED;
while( load_finished_flag == LFDS700_MISC_FLAG_LOWERED )
{
up = (*baue)->up;
if( up != NULL )
up_right = (*baue)->up->right;
if( up == NULL or (up != NULL and up_right != NULL) )
break;
LFDS700_MISC_BARRIER_LOAD;
if( up == (*baue)->up and up_right == (*baue)->up->right )
load_finished_flag = LFDS700_MISC_FLAG_RAISED;
}
if( *baue != NULL and up != NULL and *baue == up_right )
*baue = up;
else
finished_flag = LFDS700_MISC_FLAG_RAISED;
}
*baue = up;
/*
while( *baue != NULL and (*baue)->up != NULL and *baue == (*baue)->up->right )
*baue = (*baue)->up;
*baue = (*baue)->up;
*/
break;
}
return;
}
/****************************************************************************/
int lfds700_btree_au_get_by_absolute_position_and_then_by_relative_position( struct lfds700_btree_au_state *baus, struct lfds700_btree_au_element **baue, enum lfds700_btree_au_absolute_position absolute_position, enum lfds700_btree_au_relative_position relative_position )
{
int
rv;
LFDS700_PAL_ASSERT( baus != NULL );
LFDS700_PAL_ASSERT( baue != NULL );
// TRD: absolute_position can be any value in its range
// TRD: relative_position can be any value in its range
if( *baue == NULL )
rv = lfds700_btree_au_get_by_absolute_position( baus, baue, absolute_position );
else
rv = lfds700_btree_au_get_by_relative_position( baue, relative_position );
return( rv );
}
/***** includes *****/
#include "lfds700_btree_addonly_unbalanced_internal.h"
/****************************************************************************/
void lfds700_btree_au_init_valid_on_current_logical_core( struct lfds700_btree_au_state *baus,
int (*key_compare_function)(void const *new_key, void const *existing_key),
enum lfds700_btree_au_existing_key existing_key,
void *user_state )
{
LFDS700_PAL_ASSERT( baus != NULL );
LFDS700_PAL_ASSERT( (lfds700_pal_uint_t) &baus->root % LFDS700_PAL_ATOMIC_ISOLATION_IN_BYTES == 0 );
LFDS700_PAL_ASSERT( (lfds700_pal_uint_t) &baus->key_compare_function % LFDS700_PAL_ATOMIC_ISOLATION_IN_BYTES == 0 );
LFDS700_PAL_ASSERT( key_compare_function != NULL );
// TRD : existing_key can be any value in its range
// TRD : user_state can be NULL
baus->root = NULL;
baus->key_compare_function = key_compare_function;
baus->existing_key = existing_key;
baus->user_state = user_state;
LFDS700_MISC_BARRIER_STORE;
lfds700_misc_force_store();
return;
}
/***** includes *****/
#include "lfds700_btree_addonly_unbalanced_internal.h"
/****************************************************************************/
enum lfds700_btree_au_insert_result lfds700_btree_au_insert( struct lfds700_btree_au_state *baus,
struct lfds700_btree_au_element *baue,
struct lfds700_btree_au_element **existing_baue,
struct lfds700_misc_prng_state *ps )
{
char unsigned
result = 0;
int
compare_result = 0;
lfds700_pal_uint_t
backoff_iteration = LFDS700_MISC_ABSTRACTION_BACKOFF_INITIAL_VALUE;
struct lfds700_btree_au_element
*volatile compare = NULL,
*volatile baue_next = NULL,
*volatile baue_parent = NULL,
*volatile baue_temp;
LFDS700_PAL_ASSERT( baus != NULL );
LFDS700_PAL_ASSERT( baue != NULL );
LFDS700_PAL_ASSERT( (lfds700_pal_uint_t) &baue->left % LFDS700_PAL_ATOMIC_ISOLATION_IN_BYTES == 0 );
LFDS700_PAL_ASSERT( (lfds700_pal_uint_t) &baue->right % LFDS700_PAL_ATOMIC_ISOLATION_IN_BYTES == 0 );
LFDS700_PAL_ASSERT( (lfds700_pal_uint_t) &baue->up % LFDS700_PAL_ATOMIC_ISOLATION_IN_BYTES == 0 );
LFDS700_PAL_ASSERT( (lfds700_pal_uint_t) &baue->value % LFDS700_PAL_ATOMIC_ISOLATION_IN_BYTES == 0 );
LFDS700_PAL_ASSERT( (lfds700_pal_uint_t) &baue->key % LFDS700_PAL_ATOMIC_ISOLATION_IN_BYTES == 0 );
// TRD : existing_baue can be NULL
LFDS700_PAL_ASSERT( ps != NULL );
/* TRD : we follow a normal search for the insert node and which side to insert
the difference is that insertion may fail because someone else inserts
there before we do
in this case, we resume searching for the insert node from the node
we were attempting to insert upon
(if we attempted to insert the root node and this failed, i.e. we thought
the tree was empty but then it wasn't, then we start searching from the
new root)
*/
baue->up = baue->left = baue->right = NULL;
LFDS700_MISC_BARRIER_LOAD;
baue_temp = baus->root;
LFDS700_MISC_BARRIER_LOAD;
while( result == 0 )
{
// TRD : first we find where to insert
while( baue_temp != NULL )
{
compare_result = baus->key_compare_function( baue->key, baue_temp->key );
if( compare_result == 0 )
{
if( existing_baue != NULL )
*existing_baue = baue_temp;
switch( baus->existing_key )
{
case LFDS700_BTREE_AU_EXISTING_KEY_OVERWRITE:
LFDS700_BTREE_AU_SET_VALUE_IN_ELEMENT( *baue_temp, baue->value );
return( LFDS700_BTREE_AU_INSERT_RESULT_SUCCESS_OVERWRITE );
break;
case LFDS700_BTREE_AU_EXISTING_KEY_FAIL:
return( LFDS700_BTREE_AU_INSERT_RESULT_FAILURE_EXISTING_KEY );
break;
}
}
if( compare_result < 0 )
baue_next = baue_temp->left;
if( compare_result > 0 )
baue_next = baue_temp->right;
baue_parent = baue_temp;
baue_temp = baue_next;
if( baue_temp != NULL )
LFDS700_MISC_BARRIER_LOAD;
}
/* TRD : second, we actually insert
at this point baue_temp has come to NULL
and baue_parent is the element to insert at
and result of the last compare indicates
the direction of insertion
it may be that another tree has already inserted an element with
the same key as ourselves, or other elements which mean our position
is now wrong
in this case, it is either inserted in the position we're trying
to insert in now, in which case our insert will fail
or, similarly, other elements will have come in where we are,
and our insert will fail
*/
if( baue_parent == NULL )
{
compare = NULL;
baue->up = baus->root;
LFDS700_MISC_BARRIER_STORE;
LFDS700_PAL_ATOMIC_CAS_WITH_BACKOFF( &baus->root, &compare, baue, LFDS700_MISC_CAS_STRENGTH_WEAK, result, backoff_iteration, ps );
if( result == 0 )
baue_temp = baus->root;
}
if( baue_parent != NULL )
{
if( compare_result <= 0 )
{
compare = NULL;
baue->up = baue_parent;
LFDS700_MISC_BARRIER_STORE;
LFDS700_PAL_ATOMIC_CAS_WITH_BACKOFF( &baue_parent->left, &compare, baue, LFDS700_MISC_CAS_STRENGTH_WEAK, result, backoff_iteration, ps );
}
if( compare_result > 0 )
{
compare = NULL;
baue->up = baue_parent;
LFDS700_MISC_BARRIER_STORE;
LFDS700_PAL_ATOMIC_CAS_WITH_BACKOFF( &baue_parent->right, &compare, baue, LFDS700_MISC_CAS_STRENGTH_WEAK, result, backoff_iteration, ps );
}
// TRD : if the insert fails, resume searching at the insert node
if( result == 0 )
baue_temp = baue_parent;
}
}
// TRD : if we get to here, we added (not failed or overwrite on exist) a new element
if( existing_baue != NULL )
*existing_baue = NULL;
return( LFDS700_BTREE_AU_INSERT_RESULT_SUCCESS );
}
/***** the library-wide header file *****/
#include "../liblfds700_internal.h"
/***** enums *****/
enum lfds700_btree_au_move
{
LFDS700_BTREE_AU_MOVE_INVALID,
LFDS700_BTREE_AU_MOVE_SMALLEST_FROM_RIGHT_CHILD,
LFDS700_BTREE_AU_MOVE_LARGEST_FROM_LEFT_CHILD,
LFDS700_BTREE_AU_MOVE_GET_PARENT,
LFDS700_BTREE_AU_MOVE_MOVE_UP_TREE
};
enum lfds700_btree_au_delete_action
{
LFDS700_BTREE_AU_DELETE_SELF,
LFDS700_BTREE_AU_DELETE_SELF_REPLACE_WITH_LEFT_CHILD,
LFDS700_BTREE_AU_DELETE_SELF_REPLACE_WITH_RIGHT_CHILD,
LFDS700_BTREE_AU_DELETE_MOVE_LEFT
};
/***** private prototypes *****/
/***** includes *****/
#include "lfds700_btree_addonly_unbalanced_internal.h"
/***** private prototypes *****/
static void lfds700_btree_au_internal_validate( struct lfds700_btree_au_state *abs, struct lfds700_misc_validation_info *vi, enum lfds700_misc_validity *lfds700_btree_au_validity );
/****************************************************************************/
void lfds700_btree_au_query( struct lfds700_btree_au_state *baus, enum lfds700_btree_au_query query_type, void *query_input, void *query_output )
{
LFDS700_PAL_ASSERT( baus != NULL );
// TRD : query_type can be any value in its range
LFDS700_MISC_BARRIER_LOAD;
switch( query_type )
{
case LFDS700_BTREE_AU_QUERY_GET_POTENTIALLY_INACCURATE_COUNT:
{
struct lfds700_btree_au_element
*baue = NULL;
LFDS700_PAL_ASSERT( query_input == NULL );
LFDS700_PAL_ASSERT( query_output != NULL );
*(lfds700_pal_uint_t *) query_output = 0;
while( lfds700_btree_au_get_by_absolute_position_and_then_by_relative_position(baus, &baue, LFDS700_BTREE_AU_ABSOLUTE_POSITION_SMALLEST_IN_TREE, LFDS700_BTREE_AU_RELATIVE_POSITION_NEXT_LARGER_ELEMENT_IN_ENTIRE_TREE) )
( *(lfds700_pal_uint_t *) query_output )++;
}
break;
case LFDS700_BTREE_AU_QUERY_SINGLETHREADED_VALIDATE:
// TRD : query_input can be NULL
LFDS700_PAL_ASSERT( query_output != NULL );
lfds700_btree_au_internal_validate( baus, (struct lfds700_misc_validation_info *) query_input, (enum lfds700_misc_validity *) query_output );
break;
}
return;
}
/****************************************************************************/
static void lfds700_btree_au_internal_validate( struct lfds700_btree_au_state *baus, struct lfds700_misc_validation_info *vi, enum lfds700_misc_validity *lfds700_btree_au_validity )
{
lfds700_pal_uint_t
number_elements_from_query_tree = 0,
number_elements_from_walk = 0;
struct lfds700_btree_au_element
*baue = NULL,
*baue_prev = NULL;
LFDS700_PAL_ASSERT( baus!= NULL );
// TRD : vi can be NULL
LFDS700_PAL_ASSERT( lfds700_btree_au_validity != NULL );
*lfds700_btree_au_validity = LFDS700_MISC_VALIDITY_VALID;
/* TRD : validation is performed by;
performing an in-order walk
we should see every element is larger than the preceeding element
we count elements as we go along (visited elements, that is)
and check our tally equals the expected count
*/
LFDS700_MISC_BARRIER_LOAD;
while( lfds700_btree_au_get_by_absolute_position_and_then_by_relative_position(baus, &baue, LFDS700_BTREE_AU_ABSOLUTE_POSITION_SMALLEST_IN_TREE, LFDS700_BTREE_AU_RELATIVE_POSITION_NEXT_LARGER_ELEMENT_IN_ENTIRE_TREE) )
{
// TRD : baue_prev should always be smaller than or equal to baue
if( baue_prev != NULL )
if( baus->key_compare_function(baue_prev->key, baue->key) > 0 )
{
*lfds700_btree_au_validity = LFDS700_MISC_VALIDITY_INVALID_ORDER;
return;
}
baue_prev = baue;
number_elements_from_walk++;
}
if( *lfds700_btree_au_validity == LFDS700_MISC_VALIDITY_VALID )
{
lfds700_btree_au_query( (struct lfds700_btree_au_state *) baus, LFDS700_BTREE_AU_QUERY_GET_POTENTIALLY_INACCURATE_COUNT, NULL, &number_elements_from_query_tree );
if( number_elements_from_walk > number_elements_from_query_tree )
*lfds700_btree_au_validity = LFDS700_MISC_VALIDITY_INVALID_ADDITIONAL_ELEMENTS;
if( number_elements_from_walk < number_elements_from_query_tree )
*lfds700_btree_au_validity = LFDS700_MISC_VALIDITY_INVALID_MISSING_ELEMENTS;
}
/* 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( *lfds700_btree_au_validity == LFDS700_MISC_VALIDITY_VALID and vi != NULL )
{
lfds700_btree_au_query( (struct lfds700_btree_au_state *) baus, LFDS700_BTREE_AU_QUERY_GET_POTENTIALLY_INACCURATE_COUNT, NULL, &number_elements_from_query_tree );
if( number_elements_from_query_tree < vi->min_elements )
*lfds700_btree_au_validity = LFDS700_MISC_VALIDITY_INVALID_MISSING_ELEMENTS;
if( number_elements_from_query_tree > vi->max_elements )
*lfds700_btree_au_validity = LFDS700_MISC_VALIDITY_INVALID_ADDITIONAL_ELEMENTS;
}
return;
}
/***** includes *****/
#include "lfds700_freelist_internal.h"
/****************************************************************************/
void lfds700_freelist_cleanup( struct lfds700_freelist_state *fs,
void (*element_cleanup_callback)(struct lfds700_freelist_state *fs, struct lfds700_freelist_element *fe) )
{
struct lfds700_freelist_element
*fe,
*fe_temp;
LFDS700_PAL_ASSERT( fs != NULL );
// TRD : element_cleanup_callback can be NULL
LFDS700_MISC_BARRIER_LOAD;
if( element_cleanup_callback != NULL )
{
fe = fs->top[POINTER];
while( fe != NULL )
{
fe_temp = fe;
fe = fe->next;
element_cleanup_callback( fs, fe_temp );
}
}
return;
}
/***** includes *****/
#include "lfds700_freelist_internal.h"
/****************************************************************************/
void lfds700_freelist_init_valid_on_current_logical_core( struct lfds700_freelist_state *fs, void *user_state )
{
LFDS700_PAL_ASSERT( fs != NULL );
LFDS700_PAL_ASSERT( (lfds700_pal_uint_t) fs->top % LFDS700_PAL_ATOMIC_ISOLATION_IN_BYTES == 0 );
LFDS700_PAL_ASSERT( (lfds700_pal_uint_t) &fs->user_state % LFDS700_PAL_ATOMIC_ISOLATION_IN_BYTES == 0 );
// TRD : user_state can be NULL
fs->top[POINTER] = NULL;
fs->top[COUNTER] = 0;
fs->user_state = user_state;
LFDS700_MISC_BARRIER_STORE;
lfds700_misc_force_store();
return;
}
/***** the library wide include file *****/
#include "../liblfds700_internal.h"
/***** private prototypes *****/
/***** includes *****/
#include "lfds700_freelist_internal.h"
/****************************************************************************/
int lfds700_freelist_pop( struct lfds700_freelist_state *fs, struct lfds700_freelist_element **fe, struct lfds700_misc_prng_state *ps )
{
char unsigned
result;
lfds700_pal_uint_t
backoff_iteration = LFDS700_MISC_ABSTRACTION_BACKOFF_INITIAL_VALUE;
struct lfds700_freelist_element LFDS700_PAL_ALIGN(LFDS700_PAL_ALIGN_DOUBLE_POINTER)
*new_top[PAC_SIZE],
*volatile original_top[PAC_SIZE];
LFDS700_PAL_ASSERT( fs != NULL );
LFDS700_PAL_ASSERT( fe != NULL );
LFDS700_PAL_ASSERT( ps != NULL );
LFDS700_PAL_BARRIER_PROCESSOR_LOAD;
original_top[COUNTER] = fs->top[COUNTER];
original_top[POINTER] = fs->top[POINTER];
do
{
if( original_top[POINTER] == NULL )
{
*fe = NULL;
return( 0 );
}
new_top[COUNTER] = original_top[COUNTER] + 1;
new_top[POINTER] = original_top[POINTER]->next;
LFDS700_PAL_ATOMIC_DWCAS_WITH_BACKOFF( &fs->top, original_top, new_top, LFDS700_MISC_CAS_STRENGTH_WEAK, result, backoff_iteration, ps );
if( result != 1 )
LFDS700_PAL_BARRIER_PROCESSOR_LOAD;
}
while( result != 1 );
*fe = original_top[POINTER];
return( 1 );
}
/***** includes *****/
#include "lfds700_freelist_internal.h"
/****************************************************************************/
void lfds700_freelist_push( struct lfds700_freelist_state *fs, struct lfds700_freelist_element *fe, struct lfds700_misc_prng_state *ps )
{
char unsigned
result;
lfds700_pal_uint_t
backoff_iteration = LFDS700_MISC_ABSTRACTION_BACKOFF_INITIAL_VALUE;
struct lfds700_freelist_element LFDS700_PAL_ALIGN(LFDS700_PAL_ALIGN_DOUBLE_POINTER)
*new_top[PAC_SIZE],
*volatile original_top[PAC_SIZE];
LFDS700_PAL_ASSERT( fs != NULL );
LFDS700_PAL_ASSERT( fe != NULL );
LFDS700_PAL_ASSERT( ps != NULL );
new_top[POINTER] = fe;
original_top[COUNTER] = fs->top[COUNTER];
original_top[POINTER] = fs->top[POINTER];
do
{
new_top[COUNTER] = original_top[COUNTER] + 1;
fe->next = original_top[POINTER];
LFDS700_PAL_BARRIER_PROCESSOR_STORE;
LFDS700_PAL_ATOMIC_DWCAS_WITH_BACKOFF( &fs->top, original_top, new_top, LFDS700_MISC_CAS_STRENGTH_WEAK, result, backoff_iteration, ps );
}
while( result != 1 );
return;
}
/***** includes *****/
#include "lfds700_freelist_internal.h"
/***** private prototypes *****/
static void lfds700_freelist_internal_freelist_validate( struct lfds700_freelist_state *fs, struct lfds700_misc_validation_info *vi, enum lfds700_misc_validity *lfds700_freelist_validity );
/****************************************************************************/
void lfds700_freelist_query( struct lfds700_freelist_state *fs, enum lfds700_freelist_query query_type, void *query_input, void *query_output )
{
struct lfds700_freelist_element
*fe;
LFDS700_PAL_ASSERT( fs != NULL );
// TRD : query_type can be any value in its range
LFDS700_MISC_BARRIER_LOAD;
switch( query_type )
{
case LFDS700_FREELIST_QUERY_SINGLETHREADED_GET_COUNT:
LFDS700_PAL_ASSERT( query_input == NULL );
LFDS700_PAL_ASSERT( query_output != NULL );
*(lfds700_pal_uint_t *) query_output = 0;
fe = (struct lfds700_freelist_element *) fs->top[POINTER];
while( fe != NULL )
{
( *(lfds700_pal_uint_t *) query_output )++;
fe = (struct lfds700_freelist_element *) fe->next;
}
break;
case LFDS700_FREELIST_QUERY_SINGLETHREADED_VALIDATE:
// TRD : query_input can be NULL
LFDS700_PAL_ASSERT( query_output != NULL );
lfds700_freelist_internal_freelist_validate( fs, (struct lfds700_misc_validation_info *) query_input, (enum lfds700_misc_validity *) query_output );
break;
}
return;
}
/****************************************************************************/
static void lfds700_freelist_internal_freelist_validate( struct lfds700_freelist_state *fs, struct lfds700_misc_validation_info *vi, enum lfds700_misc_validity *lfds700_freelist_validity )
{
lfds700_pal_uint_t
number_elements = 0;
struct lfds700_freelist_element
*fe_slow,
*fe_fast;
LFDS700_PAL_ASSERT( fs != NULL );
// TRD : vi can be NULL
LFDS700_PAL_ASSERT( lfds700_freelist_validity != NULL );
*lfds700_freelist_validity = LFDS700_MISC_VALIDITY_VALID;
fe_slow = fe_fast = (struct lfds700_freelist_element *) fs->top[POINTER];
/* TRD : first, check for a loop
we have two pointers
both of which start at the top of the freelist
we enter a loop
and on each iteration
we advance one pointer by one element
and the other by two
we exit the loop when both pointers are NULL
(have reached the end of the freelist)
or
if we fast pointer 'sees' the slow pointer
which means we have a loop
*/
if( fe_slow != NULL )
do
{
fe_slow = fe_slow->next;
if( fe_fast != NULL )
fe_fast = fe_fast->next;
if( fe_fast != NULL )
fe_fast = fe_fast->next;
}
while( fe_slow != NULL and fe_fast != fe_slow );
if( fe_fast != NULL and fe_slow != NULL and fe_fast == fe_slow )
*lfds700_freelist_validity = LFDS700_MISC_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( *lfds700_freelist_validity == LFDS700_MISC_VALIDITY_VALID and vi != NULL )
{
lfds700_freelist_query( fs, LFDS700_FREELIST_QUERY_SINGLETHREADED_GET_COUNT, NULL, (void *) &number_elements );
if( number_elements < vi->min_elements )
*lfds700_freelist_validity = LFDS700_MISC_VALIDITY_INVALID_MISSING_ELEMENTS;
if( number_elements > vi->max_elements )
*lfds700_freelist_validity = LFDS700_MISC_VALIDITY_INVALID_ADDITIONAL_ELEMENTS;
}
return;
}
/***** includes *****/
#include "lfds700_hash_addonly_internal.h"
/***** private prototypes*****/
static void btree_au_element_cleanup_function( struct lfds700_btree_au_state *baus, struct lfds700_btree_au_element *baue );
/****************************************************************************/
void lfds700_hash_a_cleanup( struct lfds700_hash_a_state *has,
void (*element_cleanup_callback)(struct lfds700_hash_a_state *has, struct lfds700_hash_a_element *hae) )
{
lfds700_pal_uint_t
loop;
LFDS700_PAL_ASSERT( has != NULL );
// TRD : element_cleanup_callback can be NULL
if( element_cleanup_callback == NULL )
return;
LFDS700_MISC_BARRIER_LOAD;
has->element_cleanup_callback = element_cleanup_callback;
for( loop = 0 ; loop < has->array_size ; loop++ )
lfds700_btree_au_cleanup( has->baus_array+loop, btree_au_element_cleanup_function );
return;
}
/****************************************************************************/
#pragma warning( disable : 4100 )
static void btree_au_element_cleanup_function( struct lfds700_btree_au_state *baus, struct lfds700_btree_au_element *baue )
{
struct lfds700_hash_a_state
*has;
struct lfds700_hash_a_element
*hae;
LFDS700_PAL_ASSERT( baus != NULL );
LFDS700_PAL_ASSERT( baue != NULL );
hae = (struct lfds700_hash_a_element *) LFDS700_BTREE_AU_GET_VALUE_FROM_ELEMENT( *baue );
has = (struct lfds700_hash_a_state *) LFDS700_BTREE_AU_GET_USER_STATE_FROM_STATE( *baus );
has->element_cleanup_callback( has, hae );
return;
}
#pragma warning( default : 4100 )
/***** includes *****/
#include "lfds700_hash_addonly_internal.h"
/****************************************************************************/
int lfds700_hash_a_get_by_key( struct lfds700_hash_a_state *has,
void *key,
struct lfds700_hash_a_element **hae )
{
int
rv;
lfds700_pal_uint_t
hash = 0;
struct lfds700_btree_au_element
*baue;
LFDS700_PAL_ASSERT( has != NULL );
// TRD : key can be NULL
LFDS700_PAL_ASSERT( hae != NULL );
has->key_hash_function( key, &hash );
rv = lfds700_btree_au_get_by_key( has->baus_array + (hash % has->array_size), key, &baue );
if( rv == 1 )
*hae = LFDS700_BTREE_AU_GET_VALUE_FROM_ELEMENT( *baue );
else
*hae = NULL;
return( rv );
}
/***** includes *****/
#include "lfds700_hash_addonly_internal.h"
/****************************************************************************/
void lfds700_hash_a_init_valid_on_current_logical_core( struct lfds700_hash_a_state *has,
struct lfds700_btree_au_state *baus_array,
lfds700_pal_uint_t array_size,
int (*key_compare_function)(void const *new_key, void const *existing_key),
void (*key_hash_function)(void const *key, lfds700_pal_uint_t *hash),
enum lfds700_hash_a_existing_key existing_key,
void *user_state )
{
enum lfds700_btree_au_existing_key
btree_au_existing_key = LFDS700_BTREE_AU_EXISTING_KEY_OVERWRITE; // TRD : for compiler warning
lfds700_pal_uint_t
loop;
LFDS700_PAL_ASSERT( has != NULL );
LFDS700_PAL_ASSERT( baus_array != NULL );
LFDS700_PAL_ASSERT( array_size > 0 );
LFDS700_PAL_ASSERT( key_compare_function != NULL );
LFDS700_PAL_ASSERT( key_hash_function != NULL );
// TRD : existing_key can be any value in its range
// TRD : user_state can be NULL
has->array_size = array_size;
has->key_compare_function = key_compare_function;
has->key_hash_function = key_hash_function;
has->existing_key = existing_key;
has->baus_array = baus_array;
has->user_state = user_state;
if( has->existing_key == LFDS700_HASH_A_EXISTING_KEY_OVERWRITE )
btree_au_existing_key = LFDS700_BTREE_AU_EXISTING_KEY_OVERWRITE;
if( has->existing_key == LFDS700_HASH_A_EXISTING_KEY_FAIL )
btree_au_existing_key = LFDS700_BTREE_AU_EXISTING_KEY_FAIL;
// TRD : since the addonly_hash atomic counts, if that flag is set, the btree_addonly_unbalanceds don't have to
for( loop = 0 ; loop < array_size ; loop++ )
lfds700_btree_au_init_valid_on_current_logical_core( has->baus_array+loop, key_compare_function, btree_au_existing_key, user_state );
LFDS700_MISC_BARRIER_STORE;
lfds700_misc_force_store();
return;
}
/***** includes *****/
#include "lfds700_hash_addonly_internal.h"
/****************************************************************************/
enum lfds700_hash_a_insert_result lfds700_hash_a_insert( struct lfds700_hash_a_state *has,
struct lfds700_hash_a_element *hae,
struct lfds700_hash_a_element **existing_hae,
struct lfds700_misc_prng_state *ps )
{
enum lfds700_hash_a_insert_result
apr = LFDS700_HASH_A_PUT_RESULT_SUCCESS;
enum lfds700_btree_au_insert_result
alr;
lfds700_pal_uint_t
hash = 0;
struct lfds700_btree_au_element
*existing_baue;
LFDS700_PAL_ASSERT( has != NULL );
LFDS700_PAL_ASSERT( hae != NULL );
LFDS700_PAL_ASSERT( (lfds700_pal_uint_t) &hae->value % LFDS700_PAL_ATOMIC_ISOLATION_IN_BYTES == 0 );
// TRD : existing_hae can be NULL
LFDS700_PAL_ASSERT( ps != NULL );
// TRD : alignment checks
LFDS700_PAL_ASSERT( (lfds700_pal_uint_t) &hae->baue % LFDS700_PAL_ALIGN_SINGLE_POINTER == 0 );
has->key_hash_function( hae->key, &hash );
LFDS700_BTREE_AU_SET_KEY_IN_ELEMENT( hae->baue, hae->key );
LFDS700_BTREE_AU_SET_VALUE_IN_ELEMENT( hae->baue, hae );
alr = lfds700_btree_au_insert( has->baus_array + (hash % has->array_size), &hae->baue, &existing_baue, ps );
switch( alr )
{
case LFDS700_BTREE_AU_INSERT_RESULT_FAILURE_EXISTING_KEY:
if( existing_hae != NULL )
*existing_hae = LFDS700_BTREE_AU_GET_VALUE_FROM_ELEMENT( *existing_baue );
apr = LFDS700_HASH_A_PUT_RESULT_FAILURE_EXISTING_KEY;
break;
case LFDS700_BTREE_AU_INSERT_RESULT_SUCCESS_OVERWRITE:
apr = LFDS700_HASH_A_PUT_RESULT_SUCCESS_OVERWRITE;
break;
case LFDS700_BTREE_AU_INSERT_RESULT_SUCCESS:
apr = LFDS700_HASH_A_PUT_RESULT_SUCCESS;
break;
}
return( apr );
}
/***** the library wide include file *****/
#include "../liblfds700_internal.h"
/***** private prototypes *****/
/***** includes *****/
#include "lfds700_hash_addonly_internal.h"
/****************************************************************************/
void lfds700_hash_a_iterate_init( struct lfds700_hash_a_state *has, struct lfds700_hash_a_iterate *hai )
{
LFDS700_PAL_ASSERT( has != NULL );
LFDS700_PAL_ASSERT( hai != NULL );
hai->baus = has->baus_array;
hai->baus_end = has->baus_array + has->array_size;
hai->baue = NULL;
return;
}
/****************************************************************************/
int lfds700_hash_a_iterate( struct lfds700_hash_a_iterate *hai, struct lfds700_hash_a_element **hae )
{
enum lfds700_misc_flag
finished_flag = LFDS700_MISC_FLAG_LOWERED;
int
rv = 0;
LFDS700_PAL_ASSERT( hai != NULL );
LFDS700_PAL_ASSERT( hae != NULL );
while( finished_flag == LFDS700_MISC_FLAG_LOWERED )
{
lfds700_btree_au_get_by_absolute_position_and_then_by_relative_position( hai->baus, &hai->baue, LFDS700_BTREE_AU_ABSOLUTE_POSITION_SMALLEST_IN_TREE, LFDS700_BTREE_AU_RELATIVE_POSITION_NEXT_LARGER_ELEMENT_IN_ENTIRE_TREE );
if( hai->baue != NULL )
{
*hae = LFDS700_BTREE_AU_GET_VALUE_FROM_ELEMENT( *hai->baue );
finished_flag = LFDS700_MISC_FLAG_RAISED;
rv = 1;
}
if( hai->baue == NULL )
if( ++hai->baus == hai->baus_end )
{
*hae = NULL;
finished_flag = LFDS700_MISC_FLAG_RAISED;
}
}
return( rv );
}
/***** includes *****/
#include "lfds700_hash_addonly_internal.h"
/***** private prototypes *****/
static void lfds700_hash_a_internal_validate( struct lfds700_hash_a_state *has, struct lfds700_misc_validation_info *vi, enum lfds700_misc_validity *lfds700_hash_a_validity );
/****************************************************************************/
void lfds700_hash_a_query( struct lfds700_hash_a_state *has, enum lfds700_hash_a_query query_type, void *query_input, void *query_output )
{
LFDS700_PAL_ASSERT( has != NULL );
// TRD : query_type can be any value in its range
LFDS700_MISC_BARRIER_LOAD;
switch( query_type )
{
case LFDS700_HASH_A_QUERY_GET_POTENTIALLY_INACCURATE_COUNT:
{
struct lfds700_hash_a_iterate
ai;
struct lfds700_hash_a_element
*hae;
LFDS700_PAL_ASSERT( query_input == NULL );
LFDS700_PAL_ASSERT( query_output != NULL );
*(lfds700_pal_uint_t *) query_output = 0;
lfds700_hash_a_iterate_init( has, &ai );
while( lfds700_hash_a_iterate(&ai, &hae) )
( *(lfds700_pal_uint_t *) query_output )++;
}
break;
case LFDS700_HASH_A_QUERY_SINGLETHREADED_VALIDATE:
// TRD: query_input can be any value in its range
LFDS700_PAL_ASSERT( query_output != NULL );
lfds700_hash_a_internal_validate( has, (struct lfds700_misc_validation_info *) query_input, (enum lfds700_misc_validity *) query_output );
break;
}
return;
}
/****************************************************************************/
static void lfds700_hash_a_internal_validate( struct lfds700_hash_a_state *has, struct lfds700_misc_validation_info *vi, enum lfds700_misc_validity *lfds700_hash_a_validity )
{
lfds700_pal_uint_t
lfds700_hash_a_total_number_elements = 0,
lfds700_btree_au_total_number_elements = 0,
number_elements;
lfds700_pal_uint_t
loop;
LFDS700_PAL_ASSERT( has!= NULL );
// TRD : vi can be NULL
LFDS700_PAL_ASSERT( lfds700_hash_a_validity != NULL );
/* TRD : validate every btree_addonly_unbalanced in the addonly_hash
sum elements in each btree_addonly_unbalanced
check matches expected element counts (if vi is provided)
*/
*lfds700_hash_a_validity = LFDS700_MISC_VALIDITY_VALID;
for( loop = 0 ; *lfds700_hash_a_validity == LFDS700_MISC_VALIDITY_VALID and loop < has->array_size ; loop++ )
lfds700_btree_au_query( has->baus_array+loop, LFDS700_BTREE_AU_QUERY_SINGLETHREADED_VALIDATE, NULL, (void *) lfds700_hash_a_validity );
if( *lfds700_hash_a_validity == LFDS700_MISC_VALIDITY_VALID )
{
for( loop = 0 ; loop < has->array_size ; loop++ )
{
lfds700_btree_au_query( has->baus_array+loop, LFDS700_BTREE_AU_QUERY_GET_POTENTIALLY_INACCURATE_COUNT, NULL, (void *) &number_elements );
lfds700_btree_au_total_number_elements += number_elements;
}
// TRD : first, check btree_addonly_unbalanced total vs the addonly_hash total
lfds700_hash_a_query( has, LFDS700_HASH_A_QUERY_GET_POTENTIALLY_INACCURATE_COUNT, NULL, &lfds700_hash_a_total_number_elements );
// TRD : the btree_addonly_unbalanceds are assumed to speak the truth
if( lfds700_hash_a_total_number_elements < lfds700_btree_au_total_number_elements )
*lfds700_hash_a_validity = LFDS700_MISC_VALIDITY_INVALID_ADDITIONAL_ELEMENTS;
if( lfds700_hash_a_total_number_elements > lfds700_btree_au_total_number_elements )
*lfds700_hash_a_validity = LFDS700_MISC_VALIDITY_INVALID_MISSING_ELEMENTS;
// TRD : second, if we're still valid and vi is provided, check the btree_addonly_unbalanced total against vi
if( *lfds700_hash_a_validity == LFDS700_MISC_VALIDITY_VALID and vi != NULL )
{
if( lfds700_btree_au_total_number_elements < vi->min_elements )
*lfds700_hash_a_validity = LFDS700_MISC_VALIDITY_INVALID_MISSING_ELEMENTS;
if( lfds700_btree_au_total_number_elements > vi->max_elements )
*lfds700_hash_a_validity = LFDS700_MISC_VALIDITY_INVALID_ADDITIONAL_ELEMENTS;
}
}
return;
}
/***** includes *****/
#include "lfds700_list_addonly_ordered_singlylinked_internal.h"
/****************************************************************************/
void lfds700_list_aos_cleanup( struct lfds700_list_aos_state *laoss,
void (*element_cleanup_callback)(struct lfds700_list_aos_state *laoss, struct lfds700_list_aos_element *laose) )
{
struct lfds700_list_aos_element
*laose,
*temp;
LFDS700_PAL_ASSERT( laoss != NULL );
// TRD : element_cleanup_callback can be NULL
LFDS700_MISC_BARRIER_LOAD;
if( element_cleanup_callback == NULL )
return;
laose = LFDS700_LIST_AOS_GET_START( *laoss );
while( laose != NULL )
{
temp = laose;
laose = LFDS700_LIST_AOS_GET_NEXT( *laose );
element_cleanup_callback( laoss, temp );
}
return;
}
/***** includes *****/
#include "lfds700_list_addonly_ordered_singlylinked_internal.h"
/****************************************************************************/
int lfds700_list_aos_get_by_key( struct lfds700_list_aos_state *laoss,
void *key,
struct lfds700_list_aos_element **laose )
{
int
cr = !0,
rv = 1;
LFDS700_PAL_ASSERT( laoss != NULL );
LFDS700_PAL_ASSERT( key != NULL );
LFDS700_PAL_ASSERT( laose != NULL );
while( cr != 0 and LFDS700_LIST_AOS_GET_START_AND_THEN_NEXT(*laoss, *laose) )
cr = laoss->key_compare_function( key, (*laose)->key );
if( *laose == NULL )
rv = 0;
return( rv );
}
/***** includes *****/
#include "lfds700_list_addonly_ordered_singlylinked_internal.h"
/****************************************************************************/
void lfds700_list_aos_init_valid_on_current_logical_core( struct lfds700_list_aos_state *laoss,
int (*key_compare_function)(void const *new_key, void const *existing_key),
enum lfds700_list_aos_existing_key existing_key,
void *user_state )
{
LFDS700_PAL_ASSERT( laoss != NULL );
LFDS700_PAL_ASSERT( (lfds700_pal_uint_t) &laoss->start % LFDS700_PAL_ATOMIC_ISOLATION_IN_BYTES == 0 );
LFDS700_PAL_ASSERT( (lfds700_pal_uint_t) &laoss->dummy_element % LFDS700_PAL_ATOMIC_ISOLATION_IN_BYTES == 0 );
LFDS700_PAL_ASSERT( (lfds700_pal_uint_t) &laoss->key_compare_function % LFDS700_PAL_ATOMIC_ISOLATION_IN_BYTES == 0 );
LFDS700_PAL_ASSERT( key_compare_function != NULL );
// TRD : existing_key can be any value in its range
// TRD : user_state can be NULL
// TRD : dummy start element - makes code easier when you can always use ->next
laoss->start = &laoss->dummy_element;
laoss->start->next = NULL;
laoss->start->value = NULL;
laoss->key_compare_function = key_compare_function;
laoss->existing_key = existing_key;
laoss->user_state = user_state;
LFDS700_MISC_BARRIER_STORE;
lfds700_misc_force_store();
return;
}
/***** includes *****/
#include "lfds700_list_addonly_ordered_singlylinked_internal.h"
/****************************************************************************/
enum lfds700_list_aos_insert_result lfds700_list_aos_insert( struct lfds700_list_aos_state *laoss,
struct lfds700_list_aos_element *laose,
struct lfds700_list_aos_element **existing_laose,
struct lfds700_misc_prng_state *ps )
{
char unsigned
result;
enum lfds700_misc_flag
finished_flag = LFDS700_MISC_FLAG_LOWERED;
int
compare_result = 0;
lfds700_pal_uint_t
backoff_iteration = LFDS700_MISC_ABSTRACTION_BACKOFF_INITIAL_VALUE;
struct lfds700_list_aos_element
*volatile laose_temp = NULL,
*volatile laose_trailing;
LFDS700_PAL_ASSERT( laoss != NULL );
LFDS700_PAL_ASSERT( laose != NULL );
LFDS700_PAL_ASSERT( (lfds700_pal_uint_t) &laose->next % LFDS700_PAL_ATOMIC_ISOLATION_IN_BYTES == 0 );
LFDS700_PAL_ASSERT( (lfds700_pal_uint_t) &laose->value % LFDS700_PAL_ATOMIC_ISOLATION_IN_BYTES == 0 );
LFDS700_PAL_ASSERT( (lfds700_pal_uint_t) &laose->key % LFDS700_PAL_ATOMIC_ISOLATION_IN_BYTES == 0 );
// TRD : existing_laose can be NULL
LFDS700_PAL_ASSERT( ps != NULL );
/* TRD : imagine a list, sorted small to large
we arrive at an element
we obtain its next pointer
we check we are greater than the current element and smaller than the next element
this means we have found the correct location to insert
we try to CAS ourselves in; in the meantime,
someone else has *aready* swapped in an element which is smaller than we are
e.g.
the list is { 1, 10 } and we are the value 5
we arrive at 1; we check the next element and see it is 10
so we are larger than the current element and smaller than the next
we are in the correct location to insert and we go to insert...
in the meantime, someone else with the value 3 comes along
he too finds this is the correct location and inserts before we do
the list is now { 1, 3, 10 } and we are trying to insert now after
1 and before 3!
our insert CAS fails, because the next pointer of 1 has changed aready;
but we see we are in the wrong location - we need to move forward an
element
*/
LFDS700_MISC_BARRIER_LOAD;
/* TRD : we need to begin with the leading dummy element
as the element to be inserted
may be smaller than all elements in the list
*/
laose_trailing = laoss->start;
laose_temp = laoss->start->next;
while( finished_flag == LFDS700_MISC_FLAG_LOWERED )
{
if( laose_temp == NULL )
compare_result = -1;
if( laose_temp != NULL )
{
LFDS700_MISC_BARRIER_LOAD;
compare_result = laoss->key_compare_function( laose->key, laose_temp->key );
}
if( compare_result == 0 )
{
if( existing_laose != NULL )
*existing_laose = laose_temp;
switch( laoss->existing_key )
{
case LFDS700_LIST_AOS_EXISTING_KEY_OVERWRITE:
LFDS700_LIST_AOS_SET_VALUE_IN_ELEMENT( *laose_temp, laose->value );
return( LFDS700_LIST_AOS_INSERT_RESULT_SUCCESS_OVERWRITE );
break;
case LFDS700_LIST_AOS_EXISTING_KEY_FAIL:
return( LFDS700_LIST_AOS_INSERT_RESULT_FAILURE_EXISTING_KEY );
break;
}
finished_flag = LFDS700_MISC_FLAG_RAISED;
}
if( compare_result < 0 )
{
laose->next = laose_temp;
LFDS700_MISC_BARRIER_STORE;
LFDS700_PAL_ATOMIC_CAS_WITH_BACKOFF( &laose_trailing->next, &laose->next, laose, LFDS700_MISC_CAS_STRENGTH_WEAK, result, backoff_iteration, ps );
if( result == 1 )
finished_flag = LFDS700_MISC_FLAG_RAISED;
else
// TRD : if we fail to link, someone else has linked and so we need to redetermine our position is correct
laose_temp = laose_trailing->next;
}
if( compare_result > 0 )
{
// TRD : move trailing along by one element
laose_trailing = laose_trailing->next;
/* TRD : set temp as the element after trailing
if the new element we're linking is larger than all elements in the list,
laose_temp will now go to NULL and we'll link at the end
*/
laose_temp = laose_trailing->next;
}
}
return( LFDS700_LIST_AOS_INSERT_RESULT_SUCCESS );
}
/***** the library wide include file *****/
#include "../liblfds700_internal.h"
/***** private prototypes *****/
/***** includes *****/
#include "lfds700_list_addonly_ordered_singlylinked_internal.h"
/***** private prototypes *****/
static void lfds700_list_aos_internal_validate( struct lfds700_list_aos_state *laoss, struct lfds700_misc_validation_info *vi, enum lfds700_misc_validity *lfds700_list_aos_validity );
/****************************************************************************/
void lfds700_list_aos_query( struct lfds700_list_aos_state *laoss, enum lfds700_list_aos_query query_type, void *query_input, void *query_output )
{
LFDS700_PAL_ASSERT( laoss != NULL );
// TRD : query_type can be any value in its range
LFDS700_MISC_BARRIER_LOAD;
switch( query_type )
{
case LFDS700_LIST_AOS_QUERY_GET_POTENTIALLY_INACCURATE_COUNT:
{
struct lfds700_list_aos_element
*laose = NULL;
LFDS700_PAL_ASSERT( query_input == NULL );
LFDS700_PAL_ASSERT( query_output != NULL );
*(lfds700_pal_uint_t *) query_output = 0;
while( LFDS700_LIST_AOS_GET_START_AND_THEN_NEXT(*laoss, laose) )
( *(lfds700_pal_uint_t *) query_output )++;
}
break;
case LFDS700_LIST_AOS_QUERY_SINGLETHREADED_VALIDATE:
// TRD : query_input can be NULL
LFDS700_PAL_ASSERT( query_output != NULL );
lfds700_list_aos_internal_validate( laoss, (struct lfds700_misc_validation_info *) query_input, (enum lfds700_misc_validity *) query_output );
break;
}
return;
}
/****************************************************************************/
static void lfds700_list_aos_internal_validate( struct lfds700_list_aos_state *laoss, struct lfds700_misc_validation_info *vi, enum lfds700_misc_validity *lfds700_list_aos_validity )
{
lfds700_pal_uint_t
number_elements = 0;
struct lfds700_list_aos_element
*laose_fast,
*laose_slow;
LFDS700_PAL_ASSERT( laoss!= NULL );
// TRD : vi can be NULL
LFDS700_PAL_ASSERT( lfds700_list_aos_validity != NULL );
*lfds700_list_aos_validity = LFDS700_MISC_VALIDITY_VALID;
laose_slow = laose_fast = laoss->start->next;
/* TRD : first, check for a loop
we have two pointers
both of which start at the start of the list
we enter a loop
and on each iteration
we advance one pointer by one element
and the other by two
we exit the loop when both pointers are NULL
(have reached the end of the queue)
or
if we fast pointer 'sees' the slow pointer
which means we have a loop
*/
if( laose_slow != NULL )
do
{
laose_slow = laose_slow->next;
if( laose_fast != NULL )
laose_fast = laose_fast->next;
if( laose_fast != NULL )
laose_fast = laose_fast->next;
}
while( laose_slow != NULL and laose_fast != laose_slow );
if( laose_fast != NULL and laose_slow != NULL and laose_fast == laose_slow )
*lfds700_list_aos_validity = LFDS700_MISC_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( *lfds700_list_aos_validity == LFDS700_MISC_VALIDITY_VALID and vi != NULL )
{
lfds700_list_aos_query( laoss, LFDS700_LIST_AOS_QUERY_GET_POTENTIALLY_INACCURATE_COUNT, NULL, &number_elements );
if( number_elements < vi->min_elements )
*lfds700_list_aos_validity = LFDS700_MISC_VALIDITY_INVALID_MISSING_ELEMENTS;
if( number_elements > vi->max_elements )
*lfds700_list_aos_validity = LFDS700_MISC_VALIDITY_INVALID_ADDITIONAL_ELEMENTS;
}
return;
}
/***** includes *****/
#include "lfds700_list_addonly_singlylinked_unordered_internal.h"
/****************************************************************************/
void lfds700_list_asu_cleanup( struct lfds700_list_asu_state *lasus,
void (*element_cleanup_callback)(struct lfds700_list_asu_state *lasus, struct lfds700_list_asu_element *lasue) )
{
struct lfds700_list_asu_element
*lasue,
*temp;
LFDS700_PAL_ASSERT( lasus != NULL );
// TRD : element_cleanup_callback can be NULL
LFDS700_MISC_BARRIER_LOAD;
if( element_cleanup_callback == NULL )
return;
lasue = LFDS700_LIST_ASU_GET_START( *lasus );
while( lasue != NULL )
{
temp = lasue;
lasue = LFDS700_LIST_ASU_GET_NEXT( *lasue );
element_cleanup_callback( lasus, temp );
}
return;
}
/***** includes *****/
#include "lfds700_list_addonly_singlylinked_unordered_internal.h"
/****************************************************************************/
int lfds700_list_asu_get_by_key( struct lfds700_list_asu_state *lasus,
void *key,
struct lfds700_list_asu_element **lasue )
{
int
cr = !0,
rv = 1;
LFDS700_PAL_ASSERT( lasus != NULL );
LFDS700_PAL_ASSERT( key != NULL );
LFDS700_PAL_ASSERT( lasue != NULL );
while( cr != 0 and LFDS700_LIST_ASU_GET_START_AND_THEN_NEXT(*lasus, *lasue) )
cr = lasus->key_compare_function( key, (*lasue)->key );
if( *lasue == NULL )
rv = 0;
return( rv );
}
/***** includes *****/
#include "lfds700_list_addonly_singlylinked_unordered_internal.h"
/****************************************************************************/
void lfds700_list_asu_init_valid_on_current_logical_core( struct lfds700_list_asu_state *lasus,
int (*key_compare_function)(void const *new_key, void const *existing_key),
void *user_state )
{
LFDS700_PAL_ASSERT( lasus != NULL );
LFDS700_PAL_ASSERT( (lfds700_pal_uint_t) &lasus->end % LFDS700_PAL_ATOMIC_ISOLATION_IN_BYTES == 0 );
LFDS700_PAL_ASSERT( (lfds700_pal_uint_t) &lasus->start % LFDS700_PAL_ATOMIC_ISOLATION_IN_BYTES == 0 );
LFDS700_PAL_ASSERT( (lfds700_pal_uint_t) &lasus->dummy_element % LFDS700_PAL_ATOMIC_ISOLATION_IN_BYTES == 0 );
LFDS700_PAL_ASSERT( (lfds700_pal_uint_t) &lasus->key_compare_function % LFDS700_PAL_ATOMIC_ISOLATION_IN_BYTES == 0 );
// TRD : key_compare_function can be NULL
// TRD : user_state can be NULL
// TRD : dummy start element - makes code easier when you can always use ->next
lasus->start = lasus->end = &lasus->dummy_element;
lasus->start->next = NULL;
lasus->start->value = NULL;
lasus->key_compare_function = key_compare_function;
lasus->user_state = user_state;
LFDS700_MISC_BARRIER_STORE;
lfds700_misc_force_store();
return;
}
/***** includes *****/
#include "lfds700_list_addonly_singlylinked_unordered_internal.h"
/****************************************************************************/
void lfds700_list_asu_insert_at_position( struct lfds700_list_asu_state *lasus,
struct lfds700_list_asu_element *lasue,
struct lfds700_list_asu_element *lasue_predecessor,
enum lfds700_list_asu_position position,
struct lfds700_misc_prng_state *ps )
{
LFDS700_PAL_ASSERT( lasus != NULL );
LFDS700_PAL_ASSERT( lasue != NULL );
LFDS700_PAL_ASSERT( (lfds700_pal_uint_t) &lasue->next % LFDS700_PAL_ATOMIC_ISOLATION_IN_BYTES == 0 );
LFDS700_PAL_ASSERT( (lfds700_pal_uint_t) &lasue->value % LFDS700_PAL_ATOMIC_ISOLATION_IN_BYTES == 0 );
LFDS700_PAL_ASSERT( (lfds700_pal_uint_t) &lasue->key % LFDS700_PAL_ATOMIC_ISOLATION_IN_BYTES == 0 );
// TRD : lasue_predecessor asserted in the switch
// TRD : position can be any value in its range
LFDS700_PAL_ASSERT( ps != NULL );
switch( position )
{
case LFDS700_LIST_ASU_POSITION_START:
lfds700_list_asu_insert_at_start( lasus, lasue, ps );
break;
case LFDS700_LIST_ASU_POSITION_END:
lfds700_list_asu_insert_at_end( lasus, lasue, ps );
break;
case LFDS700_LIST_ASU_POSITION_AFTER:
lfds700_list_asu_insert_after_element( lasus, lasue, lasue_predecessor, ps );
break;
}
return;
}
/****************************************************************************/
void lfds700_list_asu_insert_at_start( struct lfds700_list_asu_state *lasus,
struct lfds700_list_asu_element *lasue,
struct lfds700_misc_prng_state *ps )
{
char unsigned
result;
lfds700_pal_uint_t
backoff_iteration = LFDS700_MISC_ABSTRACTION_BACKOFF_INITIAL_VALUE;
LFDS700_PAL_ASSERT( lasus != NULL );
LFDS700_PAL_ASSERT( lasue != NULL );
LFDS700_PAL_ASSERT( (lfds700_pal_uint_t) &lasue->next % LFDS700_PAL_ATOMIC_ISOLATION_IN_BYTES == 0 );
LFDS700_PAL_ASSERT( (lfds700_pal_uint_t) &lasue->value % LFDS700_PAL_ATOMIC_ISOLATION_IN_BYTES == 0 );
LFDS700_PAL_ASSERT( (lfds700_pal_uint_t) &lasue->key % LFDS700_PAL_ATOMIC_ISOLATION_IN_BYTES == 0 );
LFDS700_PAL_ASSERT( ps != NULL );
LFDS700_MISC_BARRIER_LOAD;
lasue->next = lasus->start->next;
do
{
LFDS700_MISC_BARRIER_STORE;
LFDS700_PAL_ATOMIC_CAS_WITH_BACKOFF( &lasus->start->next, &lasue->next, lasue, LFDS700_MISC_CAS_STRENGTH_WEAK, result, backoff_iteration, ps );
}
while( result != 1 );
return;
}
/****************************************************************************/
void lfds700_list_asu_insert_at_end( struct lfds700_list_asu_state *lasus,
struct lfds700_list_asu_element *lasue,
struct lfds700_misc_prng_state *ps )
{
char unsigned
result;
enum lfds700_misc_flag
finished_flag = LFDS700_MISC_FLAG_LOWERED;
lfds700_pal_uint_t
backoff_iteration = LFDS700_MISC_ABSTRACTION_BACKOFF_INITIAL_VALUE;
struct lfds700_list_asu_element LFDS700_PAL_ALIGN(LFDS700_PAL_ALIGN_SINGLE_POINTER)
*compare;
struct lfds700_list_asu_element
*volatile lasue_next,
*volatile lasue_end;
LFDS700_PAL_ASSERT( lasus != NULL );
LFDS700_PAL_ASSERT( lasue != NULL );
LFDS700_PAL_ASSERT( (lfds700_pal_uint_t) &lasue->next % LFDS700_PAL_ATOMIC_ISOLATION_IN_BYTES == 0 );
LFDS700_PAL_ASSERT( (lfds700_pal_uint_t) &lasue->value % LFDS700_PAL_ATOMIC_ISOLATION_IN_BYTES == 0 );
LFDS700_PAL_ASSERT( (lfds700_pal_uint_t) &lasue->key % LFDS700_PAL_ATOMIC_ISOLATION_IN_BYTES == 0 );
LFDS700_PAL_ASSERT( ps != NULL );
/* TRD : begin by assuming end is correctly pointing to the final element
try to link (comparing for next being NULL)
if we fail, move down list till we find last element
and retry
when successful, update end to ourselves
note there's a leading dummy element
so lasus->end always points to an element
*/
LFDS700_MISC_BARRIER_LOAD;
lasue->next = NULL;
lasue_end = lasus->end;
while( finished_flag == LFDS700_MISC_FLAG_LOWERED )
{
compare = NULL;
LFDS700_MISC_BARRIER_STORE;
LFDS700_PAL_ATOMIC_CAS_WITH_BACKOFF( &lasue_end->next, &compare, lasue, LFDS700_MISC_CAS_STRENGTH_STRONG, result, backoff_iteration, ps );
if( result == 1 )
finished_flag = LFDS700_MISC_FLAG_RAISED;
else
{
lasue_end = compare;
lasue_next = LFDS700_LIST_ASU_GET_NEXT( *lasue_end );
while( lasue_next != NULL )
{
lasue_end = lasue_next;
lasue_next = LFDS700_LIST_ASU_GET_NEXT( *lasue_end );
}
}
}
lasus->end = lasue;
return;
}
/****************************************************************************/
#pragma warning( disable : 4100 )
void lfds700_list_asu_insert_after_element( struct lfds700_list_asu_state *lasus,
struct lfds700_list_asu_element *lasue,
struct lfds700_list_asu_element *lasue_predecessor,
struct lfds700_misc_prng_state *ps )
{
char unsigned
result;
lfds700_pal_uint_t
backoff_iteration = LFDS700_MISC_ABSTRACTION_BACKOFF_INITIAL_VALUE;
LFDS700_PAL_ASSERT( lasus != NULL );
LFDS700_PAL_ASSERT( lasue != NULL );
LFDS700_PAL_ASSERT( (lfds700_pal_uint_t) &lasue->next % LFDS700_PAL_ATOMIC_ISOLATION_IN_BYTES == 0 );
LFDS700_PAL_ASSERT( (lfds700_pal_uint_t) &lasue->value % LFDS700_PAL_ATOMIC_ISOLATION_IN_BYTES == 0 );
LFDS700_PAL_ASSERT( (lfds700_pal_uint_t) &lasue->key % LFDS700_PAL_ATOMIC_ISOLATION_IN_BYTES == 0 );
LFDS700_PAL_ASSERT( lasue_predecessor != NULL );
LFDS700_PAL_ASSERT( ps != NULL );
LFDS700_MISC_BARRIER_LOAD;
lasue->next = lasue_predecessor->next;
do
{
LFDS700_MISC_BARRIER_STORE;
LFDS700_PAL_ATOMIC_CAS_WITH_BACKOFF( &lasue_predecessor->next, &lasue->next, lasue, LFDS700_MISC_CAS_STRENGTH_WEAK, result, backoff_iteration, ps );
}
while( result != 1 );
return;
}
#pragma warning( default : 4100 )
/***** the library wide include file *****/
#include "../liblfds700_internal.h"
/***** private prototypes *****/
/***** includes *****/
#include "lfds700_list_addonly_singlylinked_unordered_internal.h"
/***** private prototypes *****/
static void lfds700_list_asu_internal_validate( struct lfds700_list_asu_state *lasus, struct lfds700_misc_validation_info *vi, enum lfds700_misc_validity *lfds700_list_asu_validity );
/****************************************************************************/
void lfds700_list_asu_query( struct lfds700_list_asu_state *lasus, enum lfds700_list_asu_query query_type, void *query_input, void *query_output )
{
LFDS700_PAL_ASSERT( lasus != NULL );
// TRD : query_type can be any value in its range
LFDS700_MISC_BARRIER_LOAD;
switch( query_type )
{
case LFDS700_LIST_ASU_QUERY_GET_POTENTIALLY_INACCURATE_COUNT:
{
struct lfds700_list_asu_element
*lasue = NULL;
LFDS700_PAL_ASSERT( query_input == NULL );
LFDS700_PAL_ASSERT( query_output != NULL );
*(lfds700_pal_uint_t *) query_output = 0;
while( LFDS700_LIST_ASU_GET_START_AND_THEN_NEXT(*lasus, lasue) )
( *(lfds700_pal_uint_t *) query_output )++;
}
break;
case LFDS700_LIST_ASU_QUERY_SINGLETHREADED_VALIDATE:
// TRD : query_input can be NULL
LFDS700_PAL_ASSERT( query_output != NULL );
lfds700_list_asu_internal_validate( lasus, (struct lfds700_misc_validation_info *) query_input, (enum lfds700_misc_validity *) query_output );
break;
}
return;
}
/****************************************************************************/
static void lfds700_list_asu_internal_validate( struct lfds700_list_asu_state *lasus, struct lfds700_misc_validation_info *vi, enum lfds700_misc_validity *lfds700_list_asu_validity )
{
lfds700_pal_uint_t
number_elements = 0;
struct lfds700_list_asu_element
*lasue_fast,
*lasue_slow;
LFDS700_PAL_ASSERT( lasus!= NULL );
// TRD : vi can be NULL
LFDS700_PAL_ASSERT( lfds700_list_asu_validity != NULL );
*lfds700_list_asu_validity = LFDS700_MISC_VALIDITY_VALID;
lasue_slow = lasue_fast = lasus->start->next;
/* TRD : first, check for a loop
we have two pointers
both of which start at the start of the list
we enter a loop
and on each iteration
we advance one pointer by one element
and the other by two
we exit the loop when both pointers are NULL
(have reached the end of the queue)
or
if we fast pointer 'sees' the slow pointer
which means we have a loop
*/
if( lasue_slow != NULL )
do
{
lasue_slow = lasue_slow->next;
if( lasue_fast != NULL )
lasue_fast = lasue_fast->next;
if( lasue_fast != NULL )
lasue_fast = lasue_fast->next;
}
while( lasue_slow != NULL and lasue_fast != lasue_slow );
if( lasue_fast != NULL and lasue_slow != NULL and lasue_fast == lasue_slow )
*lfds700_list_asu_validity = LFDS700_MISC_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( *lfds700_list_asu_validity == LFDS700_MISC_VALIDITY_VALID and vi != NULL )
{
lfds700_list_asu_query( lasus, LFDS700_LIST_ASU_QUERY_GET_POTENTIALLY_INACCURATE_COUNT, NULL, &number_elements );
if( number_elements < vi->min_elements )
*lfds700_list_asu_validity = LFDS700_MISC_VALIDITY_INVALID_MISSING_ELEMENTS;
if( number_elements > vi->max_elements )
*lfds700_list_asu_validity = LFDS700_MISC_VALIDITY_INVALID_ADDITIONAL_ELEMENTS;
}
return;
}
/***** includes *****/
#include "lfds700_misc_internal.h"
/****************************************************************************/
void lfds700_misc_library_cleanup( void )
{
// TRD : we do nuuuuuuthin'
return;
}
/***** includes *****/
#include "lfds700_misc_internal.h"
/****************************************************************************/
struct lfds700_misc_globals
lfds700_misc_globals;
/***** includes *****/
#include "lfds700_misc_internal.h"
/****************************************************************************/
void lfds700_misc_library_init_valid_on_current_logical_core()
{
/* TRD : the PRNG arrangement is that each thread has its own state, for a maximum-speed PRNG, where output
quality is second consideration to performance
on 64-bit platforms this is xorshift64*, on 32-bit platforms, an unadorned xorshift32
the seed for each thread however comes from a single, global, maximum-quality PRNG, where quality of
output is the primary consideration
for this, I'm using a xorshift1024*
since the generation from this global PRNG state is not thread safe, but is still quick in
thread start-up terms, I run a little spin-lock around it
regarding the seed for this high quality PRNG; it is customary to use time(), but this has a number of
drawbacks;
1. liblfds would depend on time() (currently it does not depend on a hosted implementation of standard library)
2. the output from time may only be 32 bit, and even when it isn't, the top 32 bits are currently all zero...
3. many threads can begin in the same second; I'd need to add in their thread number,
which means I'd need to *get* their thread number...
as such, I've decided to use a *fixed* 64-bit seed for the high-quality PRNG; this seed is run
through the MurmerHash3 avalanche phase to generate successive 64-bit values, which populate
the 1024 state of xorshift1024*
if you have access to a high-frequency clock (often 64-bit), you can use this for the seed
(don't use it for the per-thread PRNG, unless you know the clock can be read without a context switch)
murmurhash3 code from here; http://xorshift.di.unimi.it/murmurhash3.c
*/
lfds700_misc_prng_internal_big_slow_high_quality_init( LFDS700_MISC_PRNG_SEED );
lfds700_misc_globals.exponential_backoff_timeslot_length_in_loop_iterations_for_cas = EXPONENTIAL_BACKOFF_TIMESLOT_LENGTH_IN_INCS_FOR_CAS;
lfds700_misc_globals.exponential_backoff_timeslot_length_in_loop_iterations_for_dwcas = EXPONENTIAL_BACKOFF_TIMESLOT_LENGTH_IN_INCS_FOR_DWCAS;
LFDS700_MISC_BARRIER_STORE;
lfds700_misc_force_store();
return;
}
/***** the library wide include file *****/
#include "../liblfds700_internal.h"
/***** defines *****/
#define EXPONENTIAL_BACKOFF_TIMESLOT_LENGTH_IN_INCS_FOR_CAS 8
#define EXPONENTIAL_BACKOFF_TIMESLOT_LENGTH_IN_INCS_FOR_DWCAS 16
/***** private prototypes *****/
void lfds700_misc_prng_internal_big_slow_high_quality_init( int long long unsigned seed );
/***** includes *****/
#include "lfds700_misc_internal.h"
/***** defines *****/
#define LFDS700_PRNG_STATE_SIZE 16
/***** struct *****/
struct lfds700_misc_prng_big_slow_high_quality_state
{
lfds700_pal_atom_t LFDS700_PAL_ALIGN(LFDS700_PAL_ATOMIC_ISOLATION_IN_BYTES)
xorshift1024star_spinlock;
// TRD : must be a 32 bit signed int
int
xorshift1024star_index;
int long long unsigned
xorshift1024star_state[LFDS700_PRNG_STATE_SIZE];
};
/***** locals *****/
struct lfds700_misc_prng_big_slow_high_quality_state
pbshqs;
/***** private prototypes *****/
static void lfds700_misc_prng_internal_hash_murmurhash3( int long long unsigned *murmurhash3_state );
static void lfds700_misc_prng_internal_big_slow_high_quality_generate( struct lfds700_misc_prng_big_slow_high_quality_state *ps, lfds700_pal_uint_t *random_value );
/****************************************************************************/
void lfds700_misc_prng_init( struct lfds700_misc_prng_state *ps )
{
LFDS700_PAL_ASSERT( ps != NULL );
/* TRD : we use the big, slow, high quality PRNG to generate the initial value
for the small, fast, low qulity PRNG, which is used in exponential backoff
we need the load barrier to catch any changes to the backoff periods
*/
lfds700_misc_prng_internal_big_slow_high_quality_generate( &pbshqs, &ps->prng_state );
LFDS700_MISC_BARRIER_LOAD;
ps->local_copy_of_global_exponential_backoff_timeslot_length_in_loop_iterations_for_cas = lfds700_misc_globals.exponential_backoff_timeslot_length_in_loop_iterations_for_cas;
ps->local_copy_of_global_exponential_backoff_timeslot_length_in_loop_iterations_for_dwcas = lfds700_misc_globals.exponential_backoff_timeslot_length_in_loop_iterations_for_dwcas;
return;
}
/****************************************************************************/
void lfds700_misc_prng_internal_big_slow_high_quality_init( int long long unsigned seed )
{
lfds700_pal_uint_t
loop;
LFDS700_PAL_ASSERT( seed != 0 ); // TRD : a 0 seed causes all zeros in the entropy state, so is forbidden
pbshqs.xorshift1024star_spinlock = LFDS700_MISC_FLAG_LOWERED;
for( loop = 0 ; loop < LFDS700_PRNG_STATE_SIZE ; loop++ )
{
lfds700_misc_prng_internal_hash_murmurhash3( &seed );
pbshqs.xorshift1024star_state[loop] = seed;
}
pbshqs.xorshift1024star_index = 0;
return;
}
/****************************************************************************/
static void lfds700_misc_prng_internal_hash_murmurhash3( int long long unsigned *murmurhash3_state )
{
LFDS700_PAL_ASSERT( murmurhash3_state != NULL );
*murmurhash3_state ^= *murmurhash3_state >> 33;
*murmurhash3_state *= 0xff51afd7ed558ccdULL;
*murmurhash3_state ^= *murmurhash3_state >> 33;
*murmurhash3_state *= 0xc4ceb9fe1a85ec53ULL;
*murmurhash3_state ^= *murmurhash3_state >> 33;
return;
}
/****************************************************************************/
static void lfds700_misc_prng_internal_big_slow_high_quality_generate( struct lfds700_misc_prng_big_slow_high_quality_state *ps, lfds700_pal_uint_t *random_value )
{
char unsigned
result;
int long long unsigned
xs_temp_one,
xs_temp_two;
lfds700_pal_atom_t
compare = LFDS700_MISC_FLAG_LOWERED,
exchange = LFDS700_MISC_FLAG_LOWERED;
LFDS700_PAL_ASSERT( ps != NULL );
LFDS700_PAL_ASSERT( random_value != NULL );
// TRD : this is single-threaded code, on a per-state basis
do
{
compare = LFDS700_MISC_FLAG_LOWERED;
LFDS700_PAL_ATOMIC_CAS( &ps->xorshift1024star_spinlock, &compare, (lfds700_pal_atom_t) LFDS700_MISC_FLAG_RAISED, LFDS700_MISC_CAS_STRENGTH_STRONG, result );
}
while( result == 0 );
// TRD : xorshift1024* code from here; http://xorshift.di.unimi.it/xorshift1024star.c
xs_temp_one = ps->xorshift1024star_state[ ps->xorshift1024star_index ];
ps->xorshift1024star_index = ( ps->xorshift1024star_index + 1 ) & 15;
xs_temp_two = ps->xorshift1024star_state[ ps->xorshift1024star_index ];
xs_temp_two ^= xs_temp_two << 31;
xs_temp_two ^= xs_temp_two >> 11;
xs_temp_one ^= xs_temp_one >> 30;
ps->xorshift1024star_state[ ps->xorshift1024star_index ] = xs_temp_one ^ xs_temp_two;
*random_value = (lfds700_pal_uint_t) ( ps->xorshift1024star_state[ ps->xorshift1024star_index ] * 1181783497276652981LL );
LFDS700_PAL_ATOMIC_EXCHANGE( &ps->xorshift1024star_spinlock, &exchange );
return;
}
/***** includes *****/
#include "lfds700_misc_internal.h"
/****************************************************************************/
void lfds700_misc_query( enum lfds700_misc_query query_type, void *query_input, void *query_output )
{
// TRD : query type can be any value in its range
// TRD : query_input can be NULL in some cases
// TRD : query_outputput can be NULL in some cases
switch( query_type )
{
case LFDS700_MISC_QUERY_GET_EXPONENTIAL_BACKOFF_TIMESLOT_LENGTH_IN_LOOP_ITERATIONS_FOR_CAS:
*(lfds700_pal_atom_t *) query_output = lfds700_misc_globals.exponential_backoff_timeslot_length_in_loop_iterations_for_cas;
break;
case LFDS700_MISC_QUERY_SET_EXPONENTIAL_BACKOFF_TIMESLOT_LENGTH_IN_LOOP_ITERATIONS_FOR_CAS:
LFDS700_PAL_ATOMIC_EXCHANGE( &lfds700_misc_globals.exponential_backoff_timeslot_length_in_loop_iterations_for_cas, (lfds700_pal_atom_t *) query_input );
break;
case LFDS700_MISC_QUERY_GET_EXPONENTIAL_BACKOFF_TIMESLOT_LENGTH_IN_LOOP_ITERATIONS_FOR_DWCAS:
*(lfds700_pal_atom_t *) query_output = lfds700_misc_globals.exponential_backoff_timeslot_length_in_loop_iterations_for_dwcas;
break;
case LFDS700_MISC_QUERY_SET_EXPONENTIAL_BACKOFF_TIMESLOT_LENGTH_IN_LOOP_ITERATIONS_FOR_DWCAS:
LFDS700_PAL_ATOMIC_EXCHANGE( &lfds700_misc_globals.exponential_backoff_timeslot_length_in_loop_iterations_for_dwcas, (lfds700_pal_atom_t *) query_input );
break;
case LFDS700_MISC_QUERY_GET_BUILD_AND_VERSION_STRING:
{
char static const
* const build_and_version_string = "liblfds " LFDS700_MISC_VERSION_STRING " (" BUILD_TYPE_STRING ", " LFDS700_PAL_OS_STRING ", " MODE_TYPE_STRING ", " LFDS700_PAL_PROCESSOR_STRING ", " LFDS700_PAL_COMPILER_STRING ")";
LFDS700_PAL_ASSERT( query_input == NULL );
LFDS700_PAL_ASSERT( query_output != NULL );
*(char const **) query_output = build_and_version_string;
}
break;
}
return;
}
/***** includes *****/
#include "lfds700_queue_internal.h"
/****************************************************************************/
void lfds700_queue_cleanup( struct lfds700_queue_state *qs,
void (*element_cleanup_callback)(struct lfds700_queue_state *qs, struct lfds700_queue_element *qe, enum lfds700_misc_flag dummy_element_flag) )
{
struct lfds700_queue_element
*qe;
void
*value;
LFDS700_PAL_ASSERT( qs != NULL );
// TRD : element_cleanup_callback can be NULL
LFDS700_MISC_BARRIER_LOAD;
if( element_cleanup_callback != NULL )
{
while( qs->dequeue[POINTER] != qs->enqueue[POINTER] )
{
// TRD : trailing dummy element, so the first real value is in the next element
value = qs->dequeue[POINTER]->next[POINTER]->value;
// TRD : user is given back *an* element, but not the one his user data was in
qe = qs->dequeue[POINTER];
// TRD : remove the element from queue
qs->dequeue[POINTER] = qs->dequeue[POINTER]->next[POINTER];
// TRD : write value into the qe we're going to give the user
qe->value = value;
element_cleanup_callback( qs, qe, LFDS700_MISC_FLAG_LOWERED );
}
// TRD : and now the final element
element_cleanup_callback( qs, (struct lfds700_queue_element *) qs->dequeue[POINTER], LFDS700_MISC_FLAG_RAISED );
}
return;
}
/***** includes *****/
#include "lfds700_queue_internal.h"
/****************************************************************************/
int lfds700_queue_dequeue( struct lfds700_queue_state *qs,
struct lfds700_queue_element **qe,
struct lfds700_misc_prng_state *ps )
{
char unsigned
result = 0,
unwanted_result;
enum lfds700_queue_queue_state
state = LFDS700_QUEUE_QUEUE_STATE_UNKNOWN;
int
rv = 1,
finished_flag = LFDS700_MISC_FLAG_LOWERED;
lfds700_pal_uint_t
backoff_iteration = LFDS700_MISC_ABSTRACTION_BACKOFF_INITIAL_VALUE;
struct lfds700_queue_element LFDS700_PAL_ALIGN(LFDS700_PAL_ALIGN_DOUBLE_POINTER)
*dequeue[PAC_SIZE],
*enqueue[PAC_SIZE],
*next[PAC_SIZE];
void
*key = NULL,
*value = NULL;
LFDS700_PAL_ASSERT( qs != NULL );
LFDS700_PAL_ASSERT( qe != NULL );
LFDS700_PAL_ASSERT( ps != NULL );
LFDS700_MISC_BARRIER_LOAD;
do
{
dequeue[COUNTER] = qs->dequeue[COUNTER];
dequeue[POINTER] = qs->dequeue[POINTER];
enqueue[COUNTER] = qs->enqueue[COUNTER];
enqueue[POINTER] = qs->enqueue[POINTER];
next[COUNTER] = qs->dequeue[POINTER]->next[COUNTER];
next[POINTER] = qs->dequeue[POINTER]->next[POINTER];
LFDS700_MISC_BARRIER_LOAD;
if( dequeue[COUNTER] == qs->dequeue[COUNTER] and dequeue[POINTER] == qs->dequeue[POINTER] )
{
if( enqueue[POINTER] == dequeue[POINTER] and next[POINTER] == NULL )
state = LFDS700_QUEUE_QUEUE_STATE_EMPTY;
if( enqueue[POINTER] == dequeue[POINTER] and next[POINTER] != NULL )
state = LFDS700_QUEUE_QUEUE_STATE_ENQUEUE_OUT_OF_PLACE;
if( enqueue[POINTER] != dequeue[POINTER] )
state = LFDS700_QUEUE_QUEUE_STATE_ATTEMPT_DEQUEUE;
switch( state )
{
case LFDS700_QUEUE_QUEUE_STATE_UNKNOWN:
// TRD : eliminates compiler warning
break;
case LFDS700_QUEUE_QUEUE_STATE_EMPTY:
rv = 0;
*qe = NULL;
finished_flag = LFDS700_MISC_FLAG_RAISED;
break;
case LFDS700_QUEUE_QUEUE_STATE_ENQUEUE_OUT_OF_PLACE:
next[COUNTER] = enqueue[COUNTER] + 1;
LFDS700_MISC_BARRIER_STORE;
LFDS700_PAL_ATOMIC_DWCAS( qs->enqueue, enqueue, next, LFDS700_MISC_CAS_STRENGTH_WEAK, unwanted_result );
break;
case LFDS700_QUEUE_QUEUE_STATE_ATTEMPT_DEQUEUE:
key = next[POINTER]->key;
value = next[POINTER]->value;
next[COUNTER] = dequeue[COUNTER] + 1;
LFDS700_MISC_BARRIER_STORE;
LFDS700_PAL_ATOMIC_DWCAS_WITH_BACKOFF( qs->dequeue, dequeue, next, LFDS700_MISC_CAS_STRENGTH_WEAK, result, backoff_iteration, ps );
if( result == 1 )
finished_flag = LFDS700_MISC_FLAG_RAISED;
break;
}
}
}
while( finished_flag == LFDS700_MISC_FLAG_LOWERED );
if( result == 1 )
{
*qe = dequeue[POINTER];
(*qe)->key = key;
(*qe)->value = value;
}
return( rv );
}
/***** includes *****/
#include "lfds700_queue_internal.h"
/****************************************************************************/
void lfds700_queue_enqueue( struct lfds700_queue_state *qs,
struct lfds700_queue_element *qe,
struct lfds700_misc_prng_state *ps )
{
char unsigned
result = 0,
unwanted_result;
lfds700_pal_uint_t
backoff_iteration = LFDS700_MISC_ABSTRACTION_BACKOFF_INITIAL_VALUE;
struct lfds700_queue_element LFDS700_PAL_ALIGN(LFDS700_PAL_ALIGN_DOUBLE_POINTER)
*volatile enqueue[PAC_SIZE],
*new_enqueue[PAC_SIZE],
*volatile next[PAC_SIZE];
LFDS700_PAL_ASSERT( qs != NULL );
LFDS700_PAL_ASSERT( qe != NULL );
LFDS700_PAL_ASSERT( (lfds700_pal_uint_t) qe->next % LFDS700_PAL_ATOMIC_ISOLATION_IN_BYTES == 0 );
LFDS700_PAL_ASSERT( (lfds700_pal_uint_t) &qe->key % LFDS700_PAL_ATOMIC_ISOLATION_IN_BYTES == 0 );
LFDS700_PAL_ASSERT( ps != NULL );
qe->next[COUNTER] = (struct lfds700_queue_element *) LFDS700_MISC_PRNG_GENERATE( ps );
qe->next[POINTER] = NULL;
new_enqueue[POINTER] = qe;
LFDS700_MISC_BARRIER_LOAD;
do
{
enqueue[COUNTER] = qs->enqueue[COUNTER];
enqueue[POINTER] = qs->enqueue[POINTER];
next[COUNTER] = qs->enqueue[POINTER]->next[COUNTER];
next[POINTER] = qs->enqueue[POINTER]->next[POINTER];
LFDS700_MISC_BARRIER_LOAD;
if( qs->enqueue[COUNTER] == enqueue[COUNTER] and qs->enqueue[POINTER] == enqueue[POINTER] )
{
if( next[POINTER] == NULL )
{
new_enqueue[COUNTER] = next[COUNTER] + 1;
LFDS700_MISC_BARRIER_STORE;
LFDS700_PAL_ATOMIC_DWCAS_WITH_BACKOFF( enqueue[POINTER]->next, next, new_enqueue, LFDS700_MISC_CAS_STRENGTH_WEAK, result, backoff_iteration, ps );
}
else
{
next[COUNTER] = enqueue[COUNTER] + 1;
LFDS700_MISC_BARRIER_STORE;
// TRD : strictly, this is a weak CAS, but we do an extra iteration of the main loop on a fake failure, so we set it to be strong
LFDS700_PAL_ATOMIC_DWCAS( qs->enqueue, enqueue, next, LFDS700_MISC_CAS_STRENGTH_STRONG, unwanted_result );
}
}
}
while( result != 1 );
new_enqueue[COUNTER] = enqueue[COUNTER] + 1;
LFDS700_MISC_BARRIER_STORE;
// TRD : move enqueue along; only a weak CAS as the dequeue will solve this if its out of place
LFDS700_PAL_ATOMIC_DWCAS( qs->enqueue, enqueue, new_enqueue, LFDS700_MISC_CAS_STRENGTH_WEAK, unwanted_result );
return;
}
/***** includes *****/
#include "lfds700_queue_internal.h"
/****************************************************************************/
void lfds700_queue_init_valid_on_current_logical_core( struct lfds700_queue_state *qs, struct lfds700_queue_element *qe_dummy, struct lfds700_misc_prng_state *ps, void *user_state )
{
LFDS700_PAL_ASSERT( qs != NULL );
LFDS700_PAL_ASSERT( (lfds700_pal_uint_t) &qs->enqueue % LFDS700_PAL_ATOMIC_ISOLATION_IN_BYTES == 0 );
LFDS700_PAL_ASSERT( (lfds700_pal_uint_t) &qs->dequeue % LFDS700_PAL_ATOMIC_ISOLATION_IN_BYTES == 0 );
LFDS700_PAL_ASSERT( (lfds700_pal_uint_t) &qs->user_state % LFDS700_PAL_ATOMIC_ISOLATION_IN_BYTES == 0 );
LFDS700_PAL_ASSERT( qe_dummy != NULL );
LFDS700_PAL_ASSERT( (lfds700_pal_uint_t) qe_dummy->next % LFDS700_PAL_ATOMIC_ISOLATION_IN_BYTES == 0 );
LFDS700_PAL_ASSERT( (lfds700_pal_uint_t) &qe_dummy->key % LFDS700_PAL_ATOMIC_ISOLATION_IN_BYTES == 0 );
LFDS700_PAL_ASSERT( ps != NULL );
// TRD : user_state can be UNLL
/* TRD : qe_dummy is a dummy element, needed for init
the qs->enqueue and qs->dequeue counters do not need to be initialized
but it does no harm to do so, and stops a valgrind complaint
*/
qs->enqueue[POINTER] = qe_dummy;
qs->enqueue[COUNTER] = (struct lfds700_queue_element *) 0;
qs->dequeue[POINTER] = qe_dummy;
qs->dequeue[COUNTER] = (struct lfds700_queue_element *) 0;
qe_dummy->next[POINTER] = NULL;
qe_dummy->next[COUNTER] = (struct lfds700_queue_element *) LFDS700_MISC_PRNG_GENERATE( ps );
qe_dummy->value = NULL;
qs->user_state = user_state;
LFDS700_MISC_BARRIER_STORE;
lfds700_misc_force_store();
return;
}
/***** the library wide include file *****/
#include "../liblfds700_internal.h"
/***** enums *****/
enum lfds700_queue_queue_state
{
LFDS700_QUEUE_QUEUE_STATE_UNKNOWN,
LFDS700_QUEUE_QUEUE_STATE_EMPTY,
LFDS700_QUEUE_QUEUE_STATE_ENQUEUE_OUT_OF_PLACE,
LFDS700_QUEUE_QUEUE_STATE_ATTEMPT_DEQUEUE
};
/***** private prototypes *****/
/***** includes *****/
#include "lfds700_queue_internal.h"
/***** private prototypes *****/
static void lfds700_queue_internal_validate( struct lfds700_queue_state *qs, struct lfds700_misc_validation_info *vi, enum lfds700_misc_validity *lfds700_queue_validity );
/****************************************************************************/
void lfds700_queue_query( struct lfds700_queue_state *qs, enum lfds700_queue_query query_type, void *query_input, void *query_output )
{
struct lfds700_queue_element
*qe;
LFDS700_MISC_BARRIER_LOAD;
LFDS700_PAL_ASSERT( qs != NULL );
// TRD : query_type can be any value in its range
switch( query_type )
{
case LFDS700_QUEUE_QUERY_SINGLETHREADED_GET_COUNT:
LFDS700_PAL_ASSERT( query_input == NULL );
LFDS700_PAL_ASSERT( query_output != NULL );
*(lfds700_pal_uint_t *) query_output = 0;
qe = (struct lfds700_queue_element *) qs->dequeue[POINTER];
while( qe != NULL )
{
( *(lfds700_pal_uint_t *) query_output )++;
qe = (struct lfds700_queue_element *) qe->next[POINTER];
}
// TRD : remember there is a dummy element in the queue
( *(lfds700_pal_uint_t *) query_output )--;
break;
case LFDS700_QUEUE_QUERY_SINGLETHREADED_VALIDATE:
// TRD : query_input can be NULL
LFDS700_PAL_ASSERT( query_output != NULL );
lfds700_queue_internal_validate( qs, (struct lfds700_misc_validation_info *) query_input, (enum lfds700_misc_validity *) query_output );
break;
}
return;
}
/****************************************************************************/
static void lfds700_queue_internal_validate( struct lfds700_queue_state *qs, struct lfds700_misc_validation_info *vi, enum lfds700_misc_validity *lfds700_queue_validity )
{
lfds700_pal_uint_t
number_elements = 0;
struct lfds700_queue_element
*qe_fast,
*qe_slow;
LFDS700_PAL_ASSERT( qs != NULL );
// TRD : vi can be NULL
LFDS700_PAL_ASSERT( lfds700_queue_validity != NULL );
*lfds700_queue_validity = LFDS700_MISC_VALIDITY_VALID;
qe_slow = qe_fast = (struct lfds700_queue_element *) qs->dequeue[POINTER];
/* TRD : first, check for a loop
we have two pointers
both of which start at the dequeue end of the queue
we enter a loop
and on each iteration
we advance one pointer by one element
and the other by two
we exit the loop when both pointers are NULL
(have reached the end of the queue)
or
if we fast pointer 'sees' the slow pointer
which means we have a loop
*/
if( qe_slow != NULL )
do
{
qe_slow = qe_slow->next[POINTER];
if( qe_fast != NULL )
qe_fast = qe_fast->next[POINTER];
if( qe_fast != NULL )
qe_fast = qe_fast->next[POINTER];
}
while( qe_slow != NULL and qe_fast != qe_slow );
if( qe_fast != NULL and qe_slow != NULL and qe_fast == qe_slow )
*lfds700_queue_validity = LFDS700_MISC_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( *lfds700_queue_validity == LFDS700_MISC_VALIDITY_VALID and vi != NULL )
{
lfds700_queue_query( qs, LFDS700_QUEUE_QUERY_SINGLETHREADED_GET_COUNT, NULL, (void *) &number_elements );
if( number_elements < vi->min_elements )
*lfds700_queue_validity = LFDS700_MISC_VALIDITY_INVALID_MISSING_ELEMENTS;
if( number_elements > vi->max_elements )
*lfds700_queue_validity = LFDS700_MISC_VALIDITY_INVALID_ADDITIONAL_ELEMENTS;
}
return;
}
/***** includes *****/
#include "lfds700_queue_bounded_singleconsumer_singleproducer_internal.h"
/****************************************************************************/
void lfds700_queue_bss_cleanup( struct lfds700_queue_bss_state *qbsss,
void (*element_cleanup_callback)(struct lfds700_queue_bss_state *qbsss, void *key, void *value) )
{
int long long unsigned
loop;
struct lfds700_queue_bss_element
*qbsse;
LFDS700_PAL_ASSERT( qbsss != NULL );
// TRD : element_cleanup_callback can be NULL
if( element_cleanup_callback != NULL )
for( loop = qbsss->read_index ; loop < qbsss->read_index + qbsss->number_elements ; loop++ )
{
qbsse = qbsss->element_array + (loop % qbsss->number_elements);
element_cleanup_callback( qbsss, qbsse->key, qbsse->value );
}
return;
}
/***** includes *****/
#include "lfds700_queue_bounded_singleconsumer_singleproducer_internal.h"
/****************************************************************************/
int lfds700_queue_bss_dequeue( struct lfds700_queue_bss_state *qbsss, void **key, void **value )
{
int
rv = 0;
struct lfds700_queue_bss_element
*qbsse;
LFDS700_PAL_ASSERT( qbsss != NULL );
// TRD : key can be NULL
// TRD : value can be NULL
LFDS700_MISC_BARRIER_LOAD;
if( qbsss->read_index != qbsss->write_index )
{
qbsse = qbsss->element_array + qbsss->read_index;
if( key != NULL )
*key = qbsse->key;
if( value != NULL )
*value = qbsse->value;
qbsss->read_index = (qbsss->read_index + 1) & qbsss->mask;
LFDS700_MISC_BARRIER_STORE;
rv = 1;
}
return( rv );
}
/***** includes *****/
#include "lfds700_queue_bounded_singleconsumer_singleproducer_internal.h"
/****************************************************************************/
int lfds700_queue_bss_enqueue( struct lfds700_queue_bss_state *qbsss, void *key, void *value )
{
int
rv = 0;
struct lfds700_queue_bss_element
*qbsse;
LFDS700_PAL_ASSERT( qbsss != NULL );
// TRD : key can be NULL
// TRD : value can be NULL
LFDS700_MISC_BARRIER_LOAD;
if( ( (qbsss->write_index+1) & qbsss->mask ) != qbsss->read_index )
{
qbsse = qbsss->element_array + qbsss->write_index;
qbsse->key = key;
qbsse->value = value;
LFDS700_MISC_BARRIER_STORE;
qbsss->write_index = (qbsss->write_index + 1) & qbsss->mask;
rv = 1;
}
return( rv );
}
/***** includes *****/
#include "lfds700_queue_bounded_singleconsumer_singleproducer_internal.h"
/****************************************************************************/
void lfds700_queue_bss_init_valid_on_current_logical_core( struct lfds700_queue_bss_state *qbsss,
struct lfds700_queue_bss_element *element_array,
lfds700_pal_uint_t number_elements,
void *user_state )
{
LFDS700_PAL_ASSERT( qbsss != NULL );
LFDS700_PAL_ASSERT( element_array != NULL );
LFDS700_PAL_ASSERT( number_elements >= 2 );
LFDS700_PAL_ASSERT( ( number_elements & (number_elements-1) ) == 0 ); // TRD : number_elements must be a positive integer power of 2
// TRD : user_state can be NULL
/* TRD : the use of mask and the restriction on a power of two
upon the number of elements bears some remark
in this queue, there are a fixed number of elements
we have a read index and a write index
when we write, and thre is space to write, we increment the write index
(if no space to write, we just return)
when we read, and there are elements to be read, we after reading increment the read index
(if no elements to read, we just return)
the problem is - how do we handle wrap around?
e.g. when I write, but my write index is now equal to the number of elements
the usual solution is to modulus the write index by the nunmber of elements
problem is modulus is slow
there is a better way
first, we restrict the number of elements to be a power of two
so imagine we have a 64-bit system and we set the number of elements to be 2^64
this gives us a bit pattern of 1000 0000 0000 0000 (...etc, lots of zeros)
now (just roll with this for a bit) subtract one from this
this gives us a mask (on a two's compliment machine)
0111 1111 1111 1111 (...etc, lots of ones)
so what we do now, when we increment an index (think of the write index as the example)
we bitwise and it with the mask
now think about thwt happens
all the numbers up to 2^64 will be unchanged - their MSB is never set, and we and with all the other bits
but when we finally hit 2^64 and need to roll over... bingo!
we drop MSB (which we finally have) and have the value 0!
this is exactly what we want
bitwise and is much faster than modulus
*/
qbsss->number_elements = number_elements;
qbsss->mask = qbsss->number_elements - 1;
qbsss->read_index = 0;
qbsss->write_index = 0;
qbsss->element_array = element_array;
qbsss->user_state = user_state;
LFDS700_MISC_BARRIER_STORE;
lfds700_misc_force_store();
return;
}
/***** the library wide include file *****/
#include "../liblfds700_internal.h"
/***** private prototypes *****/
/***** includes *****/
#include "lfds700_queue_bounded_singleconsumer_singleproducer_internal.h"
/***** private prototypes *****/
static void lfds700_queue_bss_internal_validate( struct lfds700_queue_bss_state *qbsss, struct lfds700_misc_validation_info *vi, enum lfds700_misc_validity *lfds700_validity );
/****************************************************************************/
void lfds700_queue_bss_query( struct lfds700_queue_bss_state *qbsss, enum lfds700_queue_bss_query query_type, void *query_input, void *query_output )
{
LFDS700_PAL_ASSERT( qbsss != NULL );
// TRD : query_type can be any value in its range
switch( query_type )
{
case LFDS700_QUEUE_BSS_QUERY_GET_POTENTIALLY_INACCURATE_COUNT:
LFDS700_PAL_ASSERT( query_input == NULL );
LFDS700_PAL_ASSERT( query_output != NULL );
LFDS700_MISC_BARRIER_LOAD;
*(lfds700_pal_uint_t *) query_output = +( qbsss->write_index - qbsss->read_index );
if( qbsss->read_index > qbsss->write_index )
*(lfds700_pal_uint_t *) query_output = qbsss->number_elements - *(lfds700_pal_uint_t *) query_output;
break;
case LFDS700_QUEUE_BSS_QUERY_VALIDATE:
// TRD : query_input can be NULL
LFDS700_PAL_ASSERT( query_output != NULL );
lfds700_queue_bss_internal_validate( qbsss, (struct lfds700_misc_validation_info *) query_input, (enum lfds700_misc_validity *) query_output );
break;
}
return;
}
/****************************************************************************/
static void lfds700_queue_bss_internal_validate( struct lfds700_queue_bss_state *qbsss, struct lfds700_misc_validation_info *vi, enum lfds700_misc_validity *lfds700_validity )
{
LFDS700_PAL_ASSERT( qbsss != NULL );
// TRD : vi can be NULL
LFDS700_PAL_ASSERT( lfds700_validity != NULL );
*lfds700_validity = LFDS700_MISC_VALIDITY_VALID;
if( vi != NULL )
{
lfds700_pal_uint_t
number_elements;
lfds700_queue_bss_query( qbsss, LFDS700_QUEUE_BSS_QUERY_GET_POTENTIALLY_INACCURATE_COUNT, NULL, (void *) &number_elements );
if( number_elements < vi->min_elements )
*lfds700_validity = LFDS700_MISC_VALIDITY_INVALID_MISSING_ELEMENTS;
if( number_elements > vi->max_elements )
*lfds700_validity = LFDS700_MISC_VALIDITY_INVALID_ADDITIONAL_ELEMENTS;
}
return;
}
/***** includes *****/
#include "lfds700_ringbuffer_internal.h"
/***** private prototypes *****/
static void lfds700_ringbuffer_internal_queue_element_cleanup_callback( struct lfds700_queue_state *qs, struct lfds700_queue_element *qe, enum lfds700_misc_flag dummy_element_flag );
static void lfds700_ringbuffer_internal_freelist_element_cleanup_callback( struct lfds700_freelist_state *fs, struct lfds700_freelist_element *fe );
/****************************************************************************/
void lfds700_ringbuffer_cleanup( struct lfds700_ringbuffer_state *rs,
void (*element_cleanup_callback)(struct lfds700_ringbuffer_state *rs, void *key, void *value, enum lfds700_misc_flag unread_flag) )
{
LFDS700_PAL_ASSERT( rs != NULL );
// TRD : element_cleanup_callback can be NULL
if( element_cleanup_callback != NULL )
{
rs->element_cleanup_callback = element_cleanup_callback;
lfds700_queue_cleanup( &rs->qs, lfds700_ringbuffer_internal_queue_element_cleanup_callback );
lfds700_freelist_cleanup( &rs->fs, lfds700_ringbuffer_internal_freelist_element_cleanup_callback );
}
return;
}
/****************************************************************************/
#pragma warning( disable : 4100 )
static void lfds700_ringbuffer_internal_queue_element_cleanup_callback( struct lfds700_queue_state *qs, struct lfds700_queue_element *qe, enum lfds700_misc_flag dummy_element_flag )
{
struct lfds700_ringbuffer_element
*re;
struct lfds700_ringbuffer_state
*rs;
LFDS700_PAL_ASSERT( qs != NULL );
LFDS700_PAL_ASSERT( qe != NULL );
// TRD : dummy_element can be any value in its range
rs = (struct lfds700_ringbuffer_state *) LFDS700_QUEUE_GET_USER_STATE_FROM_STATE( *qs );
re = (struct lfds700_ringbuffer_element *) LFDS700_QUEUE_GET_VALUE_FROM_ELEMENT( *qe );
if( dummy_element_flag == LFDS700_MISC_FLAG_LOWERED )
rs->element_cleanup_callback( rs, re->key, re->value, LFDS700_MISC_FLAG_RAISED );
return;
}
#pragma warning( default : 4100 )
/****************************************************************************/
#pragma warning( disable : 4100 )
static void lfds700_ringbuffer_internal_freelist_element_cleanup_callback( struct lfds700_freelist_state *fs, struct lfds700_freelist_element *fe )
{
struct lfds700_ringbuffer_element
*re;
struct lfds700_ringbuffer_state
*rs;
LFDS700_PAL_ASSERT( fs != NULL );
LFDS700_PAL_ASSERT( fe != NULL );
rs = (struct lfds700_ringbuffer_state *) LFDS700_FREELIST_GET_USER_STATE_FROM_STATE( *fs );
re = (struct lfds700_ringbuffer_element *) LFDS700_FREELIST_GET_VALUE_FROM_ELEMENT( *fe );
rs->element_cleanup_callback( rs, re->key, re->value, LFDS700_MISC_FLAG_LOWERED );
return;
}
#pragma warning( default : 4100 )
/***** includes *****/
#include "lfds700_ringbuffer_internal.h"
/****************************************************************************/
void lfds700_ringbuffer_init_valid_on_current_logical_core( struct lfds700_ringbuffer_state *rs,
struct lfds700_ringbuffer_element *re_array_inc_dummy,
lfds700_pal_uint_t number_elements,
struct lfds700_misc_prng_state *ps,
void *user_state )
{
lfds700_pal_uint_t
loop;
LFDS700_PAL_ASSERT( rs != NULL );
LFDS700_PAL_ASSERT( (lfds700_pal_uint_t) &rs->fs % LFDS700_PAL_ATOMIC_ISOLATION_IN_BYTES == 0 );
LFDS700_PAL_ASSERT( (lfds700_pal_uint_t) &rs->qs % LFDS700_PAL_ATOMIC_ISOLATION_IN_BYTES == 0 );
LFDS700_PAL_ASSERT( re_array_inc_dummy != NULL );
LFDS700_PAL_ASSERT( (lfds700_pal_uint_t) &re_array_inc_dummy[0].fe % LFDS700_PAL_ATOMIC_ISOLATION_IN_BYTES == 0 );
LFDS700_PAL_ASSERT( (lfds700_pal_uint_t) &re_array_inc_dummy[0].qe % LFDS700_PAL_ATOMIC_ISOLATION_IN_BYTES == 0 );
LFDS700_PAL_ASSERT( number_elements >= 2 );
LFDS700_PAL_ASSERT( ps != NULL );
// TRD : user_state can be NULL
rs->user_state = user_state;
re_array_inc_dummy[0].qe_use = &re_array_inc_dummy[0].qe;
lfds700_freelist_init_valid_on_current_logical_core( &rs->fs, rs );
lfds700_queue_init_valid_on_current_logical_core( &rs->qs, &re_array_inc_dummy[0].qe, ps, rs );
for( loop = 1 ; loop < number_elements ; loop++ )
{
LFDS700_PAL_ASSERT( (lfds700_pal_uint_t) &re_array_inc_dummy[loop].fe % LFDS700_PAL_ATOMIC_ISOLATION_IN_BYTES == 0 );
LFDS700_PAL_ASSERT( (lfds700_pal_uint_t) &re_array_inc_dummy[loop].qe % LFDS700_PAL_ATOMIC_ISOLATION_IN_BYTES == 0 );
re_array_inc_dummy[loop].qe_use = &re_array_inc_dummy[loop].qe;
LFDS700_FREELIST_SET_VALUE_IN_ELEMENT( re_array_inc_dummy[loop].fe, &re_array_inc_dummy[loop] );
lfds700_freelist_push( &rs->fs, &re_array_inc_dummy[loop].fe, ps );
}
LFDS700_MISC_BARRIER_STORE;
lfds700_misc_force_store();
return;
}
/***** the library wide include file *****/
#include "../liblfds700_internal.h"
/***** private prototypes *****/
/***** includes *****/
#include "lfds700_ringbuffer_internal.h"
/***** private prototypes *****/
static void lfds700_ringbuffer_internal_validate( struct lfds700_ringbuffer_state *rs, struct lfds700_misc_validation_info *vi, enum lfds700_misc_validity *lfds700_queue_validity, enum lfds700_misc_validity *lfds700_freelist_validity );
/****************************************************************************/
void lfds700_ringbuffer_query( struct lfds700_ringbuffer_state *rs, enum lfds700_ringbuffer_query query_type, void *query_input, void *query_output )
{
LFDS700_PAL_ASSERT( rs != NULL );
// TRD : query_type can be any value in its range
LFDS700_MISC_BARRIER_LOAD;
switch( query_type )
{
case LFDS700_RINGBUFFER_QUERY_SINGLETHREADED_GET_COUNT:
LFDS700_PAL_ASSERT( query_input == NULL );
LFDS700_PAL_ASSERT( query_output != NULL );
lfds700_queue_query( &rs->qs, LFDS700_QUEUE_QUERY_SINGLETHREADED_GET_COUNT, NULL, query_output );
break;
case LFDS700_RINGBUFFER_QUERY_SINGLETHREADED_VALIDATE:
// TRD : query_input can be NULL
LFDS700_PAL_ASSERT( query_output != NULL );
lfds700_ringbuffer_internal_validate( rs, (struct lfds700_misc_validation_info *) query_input, (enum lfds700_misc_validity *) query_output, ((enum lfds700_misc_validity *) query_output)+1 );
break;
}
return;
}
/****************************************************************************/
static void lfds700_ringbuffer_internal_validate( struct lfds700_ringbuffer_state *rs, struct lfds700_misc_validation_info *vi, enum lfds700_misc_validity *lfds700_queue_validity, enum lfds700_misc_validity *lfds700_freelist_validity )
{
LFDS700_PAL_ASSERT( rs != NULL );
// TRD : vi can be NULL
LFDS700_PAL_ASSERT( lfds700_queue_validity != NULL );
LFDS700_PAL_ASSERT( lfds700_freelist_validity != NULL );
if( vi == NULL )
{
lfds700_queue_query( &rs->qs, LFDS700_QUEUE_QUERY_SINGLETHREADED_VALIDATE, NULL, lfds700_queue_validity );
lfds700_freelist_query( &rs->fs, LFDS700_FREELIST_QUERY_SINGLETHREADED_VALIDATE, NULL, lfds700_freelist_validity );
}
if( vi != NULL )
{
struct lfds700_misc_validation_info
freelist_vi,
queue_vi;
queue_vi.min_elements = 0;
freelist_vi.min_elements = 0;
queue_vi.max_elements = vi->max_elements;
freelist_vi.max_elements = vi->max_elements;
lfds700_queue_query( &rs->qs, LFDS700_QUEUE_QUERY_SINGLETHREADED_VALIDATE, &queue_vi, lfds700_queue_validity );
lfds700_freelist_query( &rs->fs, LFDS700_FREELIST_QUERY_SINGLETHREADED_VALIDATE, &freelist_vi, lfds700_freelist_validity );
}
return;
}
/***** includes *****/
#include "lfds700_ringbuffer_internal.h"
/****************************************************************************/
int lfds700_ringbuffer_read( struct lfds700_ringbuffer_state *rs,
void **key,
void **value,
struct lfds700_misc_prng_state *ps )
{
int
rv;
struct lfds700_queue_element
*qe;
struct lfds700_ringbuffer_element
*re;
LFDS700_PAL_ASSERT( rs != NULL );
// TRD : key can be NULL
// TRD : value can be NULL
LFDS700_PAL_ASSERT( ps != NULL );
rv = lfds700_queue_dequeue( &rs->qs, &qe, ps );
if( rv == 1 )
{
re = LFDS700_QUEUE_GET_VALUE_FROM_ELEMENT( *qe );
re->qe_use = (struct lfds700_queue_element *) qe;
if( key != NULL )
*key = re->key;
if( value != NULL )
*value = re->value;
LFDS700_FREELIST_SET_VALUE_IN_ELEMENT( re->fe, re );
lfds700_freelist_push( &rs->fs, &re->fe, ps );
}
return( rv );
}
/***** includes *****/
#include "lfds700_ringbuffer_internal.h"
/****************************************************************************/
void lfds700_ringbuffer_write( struct lfds700_ringbuffer_state *rs,
void *key,
void *value,
enum lfds700_misc_flag *overwrite_occurred_flag,
void **overwritten_key,
void **overwritten_value,
struct lfds700_misc_prng_state *ps )
{
int
rv = 0;
struct lfds700_freelist_element
*fe;
struct lfds700_queue_element
*qe;
struct lfds700_ringbuffer_element
*re = NULL;
LFDS700_PAL_ASSERT( rs != NULL );
// TRD : key can be NULL
// TRD : value can be NULL
// TRD : overwrite_occurred_flag can be NULL
// TRD : overwritten_key can be NULL
// TRD : overwritten_value can be NULL
LFDS700_PAL_ASSERT( ps != NULL );
if( overwrite_occurred_flag != NULL )
*overwrite_occurred_flag = LFDS700_MISC_FLAG_LOWERED;
do
{
rv = lfds700_freelist_pop( &rs->fs, &fe, ps );
if( rv == 1 )
re = LFDS700_FREELIST_GET_VALUE_FROM_ELEMENT( *fe );
if( rv == 0 )
{
// TRD : the queue can return empty as well - remember, we're lock-free; anything could have happened since the previous instruction
rv = lfds700_queue_dequeue( &rs->qs, &qe, ps );
if( rv == 1 )
{
re = LFDS700_QUEUE_GET_VALUE_FROM_ELEMENT( *qe );
re->qe_use = (struct lfds700_queue_element *) qe;
if( overwrite_occurred_flag != NULL )
*overwrite_occurred_flag = LFDS700_MISC_FLAG_RAISED;
if( overwritten_key != NULL )
*overwritten_key = re->key;
if( overwritten_value != NULL )
*overwritten_value = re->value;
}
}
}
while( rv == 0 );
re->key = key;
re->value = value;
LFDS700_QUEUE_SET_VALUE_IN_ELEMENT( *re->qe_use, re );
lfds700_queue_enqueue( &rs->qs, re->qe_use, ps );
return;
}
/***** includes *****/
#include "lfds700_stack_internal.h"
/****************************************************************************/
void lfds700_stack_cleanup( struct lfds700_stack_state *ss,
void (*element_cleanup_callback)(struct lfds700_stack_state *ss, struct lfds700_stack_element *se) )
{
struct lfds700_stack_element
*se,
*se_temp;
LFDS700_PAL_ASSERT( ss != NULL );
// TRD : element_cleanup_callback can be NULL
LFDS700_MISC_BARRIER_LOAD;
if( element_cleanup_callback != NULL )
{
se = ss->top[POINTER];
while( se != NULL )
{
se_temp = se;
se = se->next;
element_cleanup_callback( ss, se_temp );
}
}
return;
}
/***** includes *****/
#include "lfds700_stack_internal.h"
/****************************************************************************/
void lfds700_stack_init_valid_on_current_logical_core( struct lfds700_stack_state *ss, void *user_state )
{
LFDS700_PAL_ASSERT( ss != NULL );
LFDS700_PAL_ASSERT( (lfds700_pal_uint_t) ss->top % LFDS700_PAL_ATOMIC_ISOLATION_IN_BYTES == 0 );
LFDS700_PAL_ASSERT( (lfds700_pal_uint_t) &ss->user_state % LFDS700_PAL_ATOMIC_ISOLATION_IN_BYTES == 0 );
// TRD : user_state can be NULL
ss->top[POINTER] = NULL;
ss->top[COUNTER] = 0;
ss->user_state = user_state;
LFDS700_MISC_BARRIER_STORE;
lfds700_misc_force_store();
return;
}
/***** the library wide include file *****/
#include "../liblfds700_internal.h"
/***** private prototypes *****/
/***** includes *****/
#include "lfds700_stack_internal.h"
/****************************************************************************/
int lfds700_stack_pop( struct lfds700_stack_state *ss, struct lfds700_stack_element **se, struct lfds700_misc_prng_state *ps )
{
char unsigned
result;
lfds700_pal_uint_t
backoff_iteration = LFDS700_MISC_ABSTRACTION_BACKOFF_INITIAL_VALUE;
struct lfds700_stack_element LFDS700_PAL_ALIGN(LFDS700_PAL_ALIGN_DOUBLE_POINTER)
*new_top[PAC_SIZE],
*volatile original_top[PAC_SIZE];
LFDS700_PAL_ASSERT( ss != NULL );
LFDS700_PAL_ASSERT( se != NULL );
LFDS700_PAL_ASSERT( ps != NULL );
LFDS700_PAL_BARRIER_PROCESSOR_LOAD;
original_top[COUNTER] = ss->top[COUNTER];
original_top[POINTER] = ss->top[POINTER];
do
{
if( original_top[POINTER] == NULL )
{
*se = NULL;
return( 0 );
}
new_top[COUNTER] = original_top[COUNTER] + 1;
new_top[POINTER] = original_top[POINTER]->next;
LFDS700_PAL_ATOMIC_DWCAS_WITH_BACKOFF( &ss->top, original_top, new_top, LFDS700_MISC_CAS_STRENGTH_WEAK, result, backoff_iteration, ps );
if( result != 1 )
LFDS700_PAL_BARRIER_PROCESSOR_LOAD;
}
while( result != 1 );
*se = original_top[POINTER];
return( 1 );
}
/***** includes *****/
#include "lfds700_stack_internal.h"
/****************************************************************************/
void lfds700_stack_push( struct lfds700_stack_state *ss, struct lfds700_stack_element *se, struct lfds700_misc_prng_state *ps )
{
char unsigned
result;
lfds700_pal_uint_t
backoff_iteration = LFDS700_MISC_ABSTRACTION_BACKOFF_INITIAL_VALUE;
struct lfds700_stack_element LFDS700_PAL_ALIGN(LFDS700_PAL_ALIGN_DOUBLE_POINTER)
*new_top[PAC_SIZE],
*volatile original_top[PAC_SIZE];
LFDS700_PAL_ASSERT( ss != NULL );
LFDS700_PAL_ASSERT( se != NULL );
LFDS700_PAL_ASSERT( ps != NULL );
new_top[POINTER] = se;
original_top[COUNTER] = ss->top[COUNTER];
original_top[POINTER] = ss->top[POINTER];
do
{
new_top[COUNTER] = original_top[COUNTER] + 1;
se->next = original_top[POINTER];
LFDS700_PAL_BARRIER_PROCESSOR_STORE;
LFDS700_PAL_ATOMIC_DWCAS_WITH_BACKOFF( &ss->top, original_top, new_top, LFDS700_MISC_CAS_STRENGTH_WEAK, result, backoff_iteration, ps );
}
while( result != 1 );
return;
}
/***** includes *****/
#include "lfds700_stack_internal.h"
/***** private prototypes *****/
static void lfds700_stack_internal_stack_validate( struct lfds700_stack_state *ss, struct lfds700_misc_validation_info *vi, enum lfds700_misc_validity *lfds700_stack_validity );
/****************************************************************************/
void lfds700_stack_query( struct lfds700_stack_state *ss, enum lfds700_stack_query query_type, void *query_input, void *query_output )
{
struct lfds700_stack_element
*se;
LFDS700_MISC_BARRIER_LOAD;
LFDS700_PAL_ASSERT( ss != NULL );
// TRD : query_type can be any value in its range
switch( query_type )
{
case LFDS700_STACK_QUERY_SINGLETHREADED_GET_COUNT:
LFDS700_PAL_ASSERT( query_input == NULL );
LFDS700_PAL_ASSERT( query_output != NULL );
*(lfds700_pal_uint_t *) query_output = 0;
se = (struct lfds700_stack_element *) ss->top[POINTER];
while( se != NULL )
{
( *(lfds700_pal_uint_t *) query_output )++;
se = (struct lfds700_stack_element *) se->next;
}
break;
case LFDS700_STACK_QUERY_SINGLETHREADED_VALIDATE:
// TRD : query_input can be NULL
LFDS700_PAL_ASSERT( query_output != NULL );
lfds700_stack_internal_stack_validate( ss, (struct lfds700_misc_validation_info *) query_input, (enum lfds700_misc_validity *) query_output );
break;
}
return;
}
/****************************************************************************/
static void lfds700_stack_internal_stack_validate( struct lfds700_stack_state *ss, struct lfds700_misc_validation_info *vi, enum lfds700_misc_validity *lfds700_stack_validity )
{
lfds700_pal_uint_t
number_elements = 0;
struct lfds700_stack_element
*se_fast,
*se_slow;
LFDS700_PAL_ASSERT( ss != NULL );
// TRD : vi can be NULL
LFDS700_PAL_ASSERT( lfds700_stack_validity != NULL );
*lfds700_stack_validity = LFDS700_MISC_VALIDITY_VALID;
se_slow = se_fast = (struct lfds700_stack_element *) ss->top[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;
if( se_fast != NULL )
se_fast = se_fast->next;
if( se_fast != NULL )
se_fast = se_fast->next;
}
while( se_slow != NULL and se_fast != se_slow );
if( se_fast != NULL and se_slow != NULL and se_fast == se_slow )
*lfds700_stack_validity = LFDS700_MISC_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( *lfds700_stack_validity == LFDS700_MISC_VALIDITY_VALID and vi != NULL )
{
lfds700_stack_query( ss, LFDS700_STACK_QUERY_SINGLETHREADED_GET_COUNT, NULL, (void *) &number_elements );
if( number_elements < vi->min_elements )
*lfds700_stack_validity = LFDS700_MISC_VALIDITY_INVALID_MISSING_ELEMENTS;
if( number_elements > vi->max_elements )
*lfds700_stack_validity = LFDS700_MISC_VALIDITY_INVALID_ADDITIONAL_ELEMENTS;
}
return;
}
/***** public prototypes *****/
#include "../inc/liblfds700.h"
/***** defines *****/
#define and &&
#define or ||
#define NO_FLAGS 0x0
#define LFDS700_ABSTRACTION_BACKOFF_LIMIT (0x1 << 10)
#if( defined _KERNEL_MODE )
#define MODE_TYPE_STRING "kernel-mode"
#endif
#if( !defined _KERNEL_MODE )
#define MODE_TYPE_STRING "user-mode"
#endif
#if( defined NDEBUG && !defined COVERAGE && !defined TSAN )
#define BUILD_TYPE_STRING "release"
#endif
#if( !defined NDEBUG && !defined COVERAGE && !defined TSAN )
#define BUILD_TYPE_STRING "debug"
#endif
#if( !defined NDEBUG && defined COVERAGE && !defined TSAN )
#define BUILD_TYPE_STRING "coverage"
#endif
#if( !defined NDEBUG && !defined COVERAGE && defined TSAN )
#define BUILD_TYPE_STRING "threadsanitizer"
#endif
// TRD : lfds700_pal_atom_t volatile *destination, lfds700_pal_atom_t *compare, lfds700_pal_atom_t new_destination, enum lfds700_misc_cas_strength cas_strength, char unsigned result, lfds700_pal_uint_t *backoff_iteration
#define LFDS700_PAL_ATOMIC_CAS_WITH_BACKOFF( pointer_to_destination, pointer_to_compare, new_destination, cas_strength, result, backoff_iteration, ps ) \
{ \
LFDS700_PAL_ATOMIC_CAS( pointer_to_destination, pointer_to_compare, new_destination, cas_strength, result ); \
\
if( result == 0 ) \
{ \
lfds700_pal_uint_t \
endloop; \
\
lfds700_pal_uint_t volatile \
loop; \
\
if( (backoff_iteration) == LFDS700_ABSTRACTION_BACKOFF_LIMIT ) \
(backoff_iteration) = LFDS700_MISC_ABSTRACTION_BACKOFF_INITIAL_VALUE; \
\
if( (backoff_iteration) == LFDS700_MISC_ABSTRACTION_BACKOFF_INITIAL_VALUE ) \
(backoff_iteration) = 1; \
else \
{ \
endloop = ( LFDS700_MISC_PRNG_GENERATE(ps) % (backoff_iteration) ) * ps->local_copy_of_global_exponential_backoff_timeslot_length_in_loop_iterations_for_cas; \
for( loop = 0 ; loop < endloop ; loop++ ); \
} \
\
(backoff_iteration) <<= 1; \
} \
}
// TRD : lfds700_pal_atom_t volatile (*destination)[2], lfds700_pal_atom_t (*compare)[2], lfds700_pal_atom_t (*new_destination)[2], enum lfds700_misc_cas_strength cas_strength, char unsigned result, lfds700_pal_uint_t *backoff_iteration
#define LFDS700_PAL_ATOMIC_DWCAS_WITH_BACKOFF( pointer_to_destination, pointer_to_compare, pointer_to_new_destination, cas_strength, result, backoff_iteration, ps ) \
{ \
LFDS700_PAL_ATOMIC_DWCAS( pointer_to_destination, pointer_to_compare, pointer_to_new_destination, cas_strength, result ); \
\
if( result == 0 ) \
{ \
lfds700_pal_uint_t \
endloop; \
\
lfds700_pal_uint_t volatile \
loop; \
\
if( (backoff_iteration) == LFDS700_ABSTRACTION_BACKOFF_LIMIT ) \
(backoff_iteration) = LFDS700_MISC_ABSTRACTION_BACKOFF_INITIAL_VALUE; \
\
if( (backoff_iteration) == LFDS700_MISC_ABSTRACTION_BACKOFF_INITIAL_VALUE ) \
(backoff_iteration) = 1; \
else \
{ \
endloop = ( LFDS700_MISC_PRNG_GENERATE(ps) % (backoff_iteration) ) * ps->local_copy_of_global_exponential_backoff_timeslot_length_in_loop_iterations_for_dwcas; \
for( loop = 0 ; loop < endloop ; loop++ ); \
} \
\
(backoff_iteration) <<= 1; \
} \
}
/***** library-wide prototypes *****/
##### paths #####
BINDIR := ../../bin
OBJDIR := ../../obj
SRCDIR := ../../src
LIBINCDIRS := ../../../liblfds700/inc/
LIBBINDIRS := ../../../liblfds700/bin/
##### misc #####
QUIETLY := 1>nul 2>nul
##### sources, objects and libraries #####
BINNAME := test
BINARY := $(BINDIR)/$(BINNAME)
SRCDIRS := .
SOURCES := main.c misc.c \
test_lfds700_btree_addonly_unbalanced.c test_lfds700_btree_addonly_unbalanced_alignment.c test_lfds700_btree_addonly_unbalanced_random_adds_fail.c test_lfds700_btree_addonly_unbalanced_random_adds_fail_and_overwrite.c test_lfds700_btree_addonly_unbalanced_random_adds_overwrite.c \
test_lfds700_freelist.c test_lfds700_freelist_alignment.c test_lfds700_freelist_popping.c test_lfds700_freelist_popping_and_pushing.c test_lfds700_freelist_pushing.c test_lfds700_freelist_rapid_popping_and_pushing.c \
test_lfds700_hash_addonly.c test_lfds700_hash_addonly_alignment.c test_lfds700_hash_addonly_iterate.c test_lfds700_hash_addonly_random_adds_fail.c test_lfds700_hash_addonly_random_adds_fail_and_overwrite.c test_lfds700_hash_addonly_random_adds_overwrite.c \
test_lfds700_list_addonly_ordered_singlylinked.c test_lfds700_list_addonly_ordered_singlylinked_alignment.c test_lfds700_list_addonly_ordered_singlylinked_new_ordered.c test_lfds700_list_addonly_ordered_singlylinked_new_ordered_with_cursor.c \
test_lfds700_list_addonly_singlylinked_unordered.c test_lfds700_list_addonly_singlylinked_unordered_alignment.c test_lfds700_list_addonly_singlylinked_unordered_new_after.c test_lfds700_list_addonly_singlylinked_unordered_new_end.c test_lfds700_list_addonly_singlylinked_unordered_new_start.c \
test_lfds700_porting_abstraction_layer_atomic.c test_lfds700_porting_abstraction_layer_atomic_cas.c test_lfds700_porting_abstraction_layer_atomic_dcas.c test_lfds700_porting_abstraction_layer_atomic_exchange.c \
test_lfds700_queue.c test_lfds700_queue_alignment.c test_lfds700_queue_dequeuing.c test_lfds700_queue_enqueuing.c test_lfds700_queue_enqueuing_and_dequeuing.c test_lfds700_queue_enqueuing_and_dequeuing_with_free.c test_lfds700_queue_enqueuing_with_malloc_and_dequeuing_with_free.c test_lfds700_queue_rapid_enqueuing_and_dequeuing.c \
test_lfds700_queue_bounded_singleconsumer_singleproducer.c test_lfds700_queue_bounded_singleconsumer_singleproducer_dequeuing.c test_lfds700_queue_bounded_singleconsumer_singleproducer_enqueuing.c test_lfds700_queue_bounded_singleconsumer_singleproducer_enqueuing_and_dequeuing.c \
test_lfds700_ringbuffer.c test_lfds700_ringbuffer_reading.c test_lfds700_ringbuffer_reading_and_writing.c test_lfds700_ringbuffer_writing.c \
test_lfds700_stack.c test_lfds700_stack_alignment.c test_lfds700_stack_popping.c test_lfds700_stack_popping_and_pushing.c test_lfds700_stack_pushing.c test_lfds700_stack_rapid_popping_and_pushing.c \
test_porting_abstraction_layer_get_logical_core_ids.c test_porting_abstraction_layer_thread_start.c test_porting_abstraction_layer_thread_wait.c \
util_cmdline.c util_memory_helpers.c util_thread_starter.c
OBJECTS := $(patsubst %.c,$(OBJDIR)/%.o,$(notdir $(SOURCES)))
SYSLIBS := -lm -lpthread -lrt
USRLIBS := -llfds700
##### default paths #####
CPATH += $(LIBINCDIRS)
LIBRARY_PATH += $(LIBBINDIRS)
export CPATH
export LIBRARY_PATH
##### tools #####
MAKE := make
MFLAGS :=
DG := gcc
DGFLAGS := -MM -std=gnu89
CC := gcc
CFBASE := -c -pthread -std=gnu89 -Wall -Wno-unknown-pragmas
CFCOV := -O0 -ggdb -DCOVERAGE -fprofile-arcs -ftest-coverage
CFDBG := -O0 -ggdb -D_DEBUG
CFPROF := -O0 -ggdb -DPROF -pg
CFREL := -O2 -DNDEBUG -finline-functions -Wno-strict-aliasing
CFTSAN := -O0 -ggdb -DTSAN -fsanitize=thread -fPIE
LD := gcc
LFBASE := -pthread -std=gnu89 -Wall -Werror
LFCOV := -O0 -fprofile-arcs -ftest-coverage
LFDBG := -O0 -ggdb
LFPROF := -O0 -pg
LFREL := -O2 -s -finline-functions
LFTSAN := -O0 -fsanitize=thread -pie
PROF := gprof
PFBASE := -b -p -Q $(BINARY) gmon.out
##### variants and libnuma check #####
CFLAGS += $(CFBASE)
LFLAGS += $(LFBASE)
ifeq ($(MAKECMDGOALS),)
CFLAGS += $(CFDBG)
LFLAGS += $(LFDBG)
endif
ifeq ($(MAKECMDGOALS),cov)
CFLAGS += $(CFCOV)
LFLAGS += $(LFCOV)
SYSLIBS += -lgcov
endif
ifeq ($(MAKECMDGOALS),dbg)
CFLAGS += $(CFDBG)
LFLAGS += $(LFDBG)
endif
ifeq ($(MAKECMDGOALS),prof)
CFLAGS += $(CFPROF)
LFLAGS += $(LFPROF)
endif
ifeq ($(MAKECMDGOALS),rel)
CFLAGS += $(CFREL)
LFLAGS += $(LFREL)
endif
ifeq ($(MAKECMDGOALS),tsan)
CFLAGS += $(CFTSAN)
LFLAGS += $(LFTSAN)
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 cov dbg prof rel tsan
clean :
@rm -f $(BINDIR)/$(BINNAME) $(OBJDIR)/*.o $(OBJDIR)/*.d $(OBJDIR)/*.gcno
cov : $(BINARY)
dbg : $(BINARY)
prof : $(BINARY)
rel : $(BINARY)
tsan : $(BINARY)
genprof :
@$(PROF) $(PFBASE)
##### dependencies #####
-include $(DEPENDS)
##### paths #####
BINDIR := ..\..\bin
OBJDIR := ..\..\obj
SRCDIR := ..\..\src
##### misc #####
QUIETLY := 1>nul 2>nul
NULL :=
SPACE := $(NULL) # TRD : necessary trailing space after the close bracket
##### sources, objects and libraries #####
BINNAME := test
BINARY := $(BINDIR)\$(BINNAME).exe
SRCDIRS := .
SOURCES := main.c misc.c \
test_lfds700_btree_addonly_unbalanced.c test_lfds700_btree_addonly_unbalanced_alignment.c test_lfds700_btree_addonly_unbalanced_random_adds_fail.c test_lfds700_btree_addonly_unbalanced_random_adds_fail_and_overwrite.c test_lfds700_btree_addonly_unbalanced_random_adds_overwrite.c \
test_lfds700_freelist.c test_lfds700_freelist_alignment.c test_lfds700_freelist_popping.c test_lfds700_freelist_popping_and_pushing.c test_lfds700_freelist_pushing.c test_lfds700_freelist_rapid_popping_and_pushing.c \
test_lfds700_hash_addonly.c test_lfds700_hash_addonly_alignment.c test_lfds700_hash_addonly_iterate.c test_lfds700_hash_addonly_random_adds_fail.c test_lfds700_hash_addonly_random_adds_fail_and_overwrite.c test_lfds700_hash_addonly_random_adds_overwrite.c \
test_lfds700_list_addonly_ordered_singlylinked.c test_lfds700_list_addonly_ordered_singlylinked_alignment.c test_lfds700_list_addonly_ordered_singlylinked_new_ordered.c test_lfds700_list_addonly_ordered_singlylinked_new_ordered_with_cursor.c \
test_lfds700_list_addonly_singlylinked_unordered.c test_lfds700_list_addonly_singlylinked_unordered_alignment.c test_lfds700_list_addonly_singlylinked_unordered_new_after.c test_lfds700_list_addonly_singlylinked_unordered_new_end.c test_lfds700_list_addonly_singlylinked_unordered_new_start.c \
test_lfds700_porting_abstraction_layer_atomic.c test_lfds700_porting_abstraction_layer_atomic_cas.c test_lfds700_porting_abstraction_layer_atomic_dcas.c test_lfds700_porting_abstraction_layer_atomic_exchange.c \
test_lfds700_queue.c test_lfds700_queue_alignment.c test_lfds700_queue_dequeuing.c test_lfds700_queue_enqueuing.c test_lfds700_queue_enqueuing_and_dequeuing.c test_lfds700_queue_enqueuing_and_dequeuing_with_free.c test_lfds700_queue_enqueuing_with_malloc_and_dequeuing_with_free.c test_lfds700_queue_rapid_enqueuing_and_dequeuing.c \
test_lfds700_queue_bounded_singleconsumer_singleproducer.c test_lfds700_queue_bounded_singleconsumer_singleproducer_dequeuing.c test_lfds700_queue_bounded_singleconsumer_singleproducer_enqueuing.c test_lfds700_queue_bounded_singleconsumer_singleproducer_enqueuing_and_dequeuing.c \
test_lfds700_ringbuffer.c test_lfds700_ringbuffer_reading.c test_lfds700_ringbuffer_reading_and_writing.c test_lfds700_ringbuffer_writing.c \
test_lfds700_stack.c test_lfds700_stack_alignment.c test_lfds700_stack_popping.c test_lfds700_stack_popping_and_pushing.c test_lfds700_stack_pushing.c test_lfds700_stack_rapid_popping_and_pushing.c \
test_porting_abstraction_layer_get_logical_core_ids.c test_porting_abstraction_layer_thread_start.c test_porting_abstraction_layer_thread_wait.c \
util_cmdline.c util_memory_helpers.c util_thread_starter.c
OBJECTS := $(patsubst %.c,$(OBJDIR)/%.obj,$(notdir $(SOURCES)))
RESFILE := $(patsubst %.rc,$(OBJDIR)/%.res,$(notdir $(RCFILE)))
SYSLIBS := kernel32.lib
EXTLIBS :=
USRLIBS := ../../../liblfds700/bin/liblfds700.lib
##### default paths fix up #####
INCLUDE += ;../../../../liblfds700/inc/
LIB += ;../../../../liblfds700/bin/
##### tools #####
MAKE := make
MFLAGS :=
CC := cl
CFBASE := /c /D_CRT_SECURE_NO_WARNINGS /DWIN32_LEAN_AND_MEAN /DUNICODE /D_UNICODE /DUNICODE "/Fd$(BINDIR)\$(BINNAME).pdb" /nologo /W4 /WX
CFREL := /DNDEBUG /Ox
CFDBG := /D_DEBUG /Od /Gm /Zi
LD := link
LFBASE := /nologo /subsystem:console /nodefaultlib /nxcompat /wx
LFREL := /incremental:no
LFDBG := /debug "/pdb:$(BINDIR)\$(BINNAME).pdb"
##### variants #####
CFLAGS := $(CFBASE) $(CFDBG) /MTd
LFLAGS := $(LFBASE) $(LFDBG)
CLIB := libcmtd.lib
ifeq ($(MAKECMDGOALS),librel)
CFLAGS := $(CFBASE) $(CFREL) /MT
LFLAGS := $(LFBASE) $(LFREL)
CLIB := libcmt.lib
endif
ifeq ($(MAKECMDGOALS),libdbg)
CFLAGS := $(CFBASE) $(CFDBG) /MTd
LFLAGS := $(LFBASE) $(LFDBG)
CLIB := libcmtd.lib
endif
ifeq ($(MAKECMDGOALS),dllrel)
CFLAGS := $(CFBASE) $(CFREL) /MD
LFLAGS := $(LFBASE) $(LFREL)
CLIB := msvcrt.lib
endif
ifeq ($(MAKECMDGOALS),dlldbg)
CFLAGS := $(CFBASE) $(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 #####
$(BINARY) : $(OBJECTS) $(USRLIBS)
$(LD) $(LFLAGS) $(CLIB) $(SYSLIBS) $(EXTLIBS) $(USRLIBS) $(OBJECTS) /out:$(BINARY)
##### phony #####
.PHONY : clean librel libdbg dllrel dlldbg
clean :
@erase /Q $(OBJDIR)\*.obj $(OBJDIR)\*.res $(BINDIR)\$(BINNAME).* $(QUIETLY)
dlldbg : $(BINARY)
dllrel : $(BINARY)
libdbg : $(BINARY)
librel : $(BINARY)
##### notes #####
# TRD : we fix up the default paths because cl and link require an extra argument per additional path, which is ugly as hell

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 2012
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "test", "test.vcxproj", "{A6BA3A68-A1D4-4C07-A0D5-7EAE73272A43}"
ProjectSection(ProjectDependencies) = postProject
{1E5D7D09-94F2-455D-AE5E-6C7F4C96BCE0} = {1E5D7D09-94F2-455D-AE5E-6C7F4C96BCE0}
EndProjectSection
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "liblfds700", "..\..\..\liblfds700\build\visual_studio_professional_2012\liblfds700.vcxproj", "{1E5D7D09-94F2-455D-AE5E-6C7F4C96BCE0}"
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
{A6BA3A68-A1D4-4C07-A0D5-7EAE73272A43}.Debug DLL|Win32.ActiveCfg = Debug DLL|Win32
{A6BA3A68-A1D4-4C07-A0D5-7EAE73272A43}.Debug DLL|Win32.Build.0 = Debug DLL|Win32
{A6BA3A68-A1D4-4C07-A0D5-7EAE73272A43}.Debug DLL|Win32.Deploy.0 = Debug DLL|Win32
{A6BA3A68-A1D4-4C07-A0D5-7EAE73272A43}.Debug DLL|x64.ActiveCfg = Debug DLL|x64
{A6BA3A68-A1D4-4C07-A0D5-7EAE73272A43}.Debug DLL|x64.Build.0 = Debug DLL|x64
{A6BA3A68-A1D4-4C07-A0D5-7EAE73272A43}.Debug DLL|x64.Deploy.0 = Debug DLL|x64
{A6BA3A68-A1D4-4C07-A0D5-7EAE73272A43}.Debug LIB|Win32.ActiveCfg = Debug LIB|Win32
{A6BA3A68-A1D4-4C07-A0D5-7EAE73272A43}.Debug LIB|Win32.Build.0 = Debug LIB|Win32
{A6BA3A68-A1D4-4C07-A0D5-7EAE73272A43}.Debug LIB|Win32.Deploy.0 = Debug LIB|Win32
{A6BA3A68-A1D4-4C07-A0D5-7EAE73272A43}.Debug LIB|x64.ActiveCfg = Debug LIB|x64
{A6BA3A68-A1D4-4C07-A0D5-7EAE73272A43}.Debug LIB|x64.Build.0 = Debug LIB|x64
{A6BA3A68-A1D4-4C07-A0D5-7EAE73272A43}.Debug LIB|x64.Deploy.0 = Debug LIB|x64
{A6BA3A68-A1D4-4C07-A0D5-7EAE73272A43}.Release DLL|Win32.ActiveCfg = Release DLL|Win32
{A6BA3A68-A1D4-4C07-A0D5-7EAE73272A43}.Release DLL|Win32.Build.0 = Release DLL|Win32
{A6BA3A68-A1D4-4C07-A0D5-7EAE73272A43}.Release DLL|Win32.Deploy.0 = Release DLL|Win32
{A6BA3A68-A1D4-4C07-A0D5-7EAE73272A43}.Release DLL|x64.ActiveCfg = Release DLL|x64
{A6BA3A68-A1D4-4C07-A0D5-7EAE73272A43}.Release DLL|x64.Build.0 = Release DLL|x64
{A6BA3A68-A1D4-4C07-A0D5-7EAE73272A43}.Release DLL|x64.Deploy.0 = Release DLL|x64
{A6BA3A68-A1D4-4C07-A0D5-7EAE73272A43}.Release LIB|Win32.ActiveCfg = Release LIB|Win32
{A6BA3A68-A1D4-4C07-A0D5-7EAE73272A43}.Release LIB|Win32.Build.0 = Release LIB|Win32
{A6BA3A68-A1D4-4C07-A0D5-7EAE73272A43}.Release LIB|Win32.Deploy.0 = Release LIB|Win32
{A6BA3A68-A1D4-4C07-A0D5-7EAE73272A43}.Release LIB|x64.ActiveCfg = Release LIB|x64
{A6BA3A68-A1D4-4C07-A0D5-7EAE73272A43}.Release LIB|x64.Build.0 = Release LIB|x64
{A6BA3A68-A1D4-4C07-A0D5-7EAE73272A43}.Release LIB|x64.Deploy.0 = Release LIB|x64
{1E5D7D09-94F2-455D-AE5E-6C7F4C96BCE0}.Debug DLL|Win32.ActiveCfg = Debug DLL|Win32
{1E5D7D09-94F2-455D-AE5E-6C7F4C96BCE0}.Debug DLL|Win32.Build.0 = Debug DLL|Win32
{1E5D7D09-94F2-455D-AE5E-6C7F4C96BCE0}.Debug DLL|x64.ActiveCfg = Debug DLL|x64
{1E5D7D09-94F2-455D-AE5E-6C7F4C96BCE0}.Debug DLL|x64.Build.0 = Debug DLL|x64
{1E5D7D09-94F2-455D-AE5E-6C7F4C96BCE0}.Debug LIB|Win32.ActiveCfg = Debug LIB|Win32
{1E5D7D09-94F2-455D-AE5E-6C7F4C96BCE0}.Debug LIB|Win32.Build.0 = Debug LIB|Win32
{1E5D7D09-94F2-455D-AE5E-6C7F4C96BCE0}.Debug LIB|x64.ActiveCfg = Debug LIB|x64
{1E5D7D09-94F2-455D-AE5E-6C7F4C96BCE0}.Debug LIB|x64.Build.0 = Debug LIB|x64
{1E5D7D09-94F2-455D-AE5E-6C7F4C96BCE0}.Release DLL|Win32.ActiveCfg = Release DLL|Win32
{1E5D7D09-94F2-455D-AE5E-6C7F4C96BCE0}.Release DLL|Win32.Build.0 = Release DLL|Win32
{1E5D7D09-94F2-455D-AE5E-6C7F4C96BCE0}.Release DLL|x64.ActiveCfg = Release DLL|x64
{1E5D7D09-94F2-455D-AE5E-6C7F4C96BCE0}.Release DLL|x64.Build.0 = Release DLL|x64
{1E5D7D09-94F2-455D-AE5E-6C7F4C96BCE0}.Release LIB|Win32.ActiveCfg = Release LIB|Win32
{1E5D7D09-94F2-455D-AE5E-6C7F4C96BCE0}.Release LIB|Win32.Build.0 = Release LIB|Win32
{1E5D7D09-94F2-455D-AE5E-6C7F4C96BCE0}.Release LIB|x64.ActiveCfg = Release LIB|x64
{1E5D7D09-94F2-455D-AE5E-6C7F4C96BCE0}.Release LIB|x64.Build.0 = Release LIB|x64
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
EndGlobal
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug DLL|Win32">
<Configuration>Debug DLL</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Debug DLL|x64">
<Configuration>Debug DLL</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Debug LIB|Win32">
<Configuration>Debug LIB</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Debug LIB|x64">
<Configuration>Debug LIB</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release DLL|Win32">
<Configuration>Release DLL</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release DLL|x64">
<Configuration>Release DLL</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release LIB|Win32">
<Configuration>Release LIB</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release LIB|x64">
<Configuration>Release LIB</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\..\src\internal.h" />
<ClInclude Include="..\..\src\test_porting_abstraction_layer_operating_system.h" />
<ClInclude Include="..\..\src\util_cmdline.h" />
<ClInclude Include="..\..\src\util_memory_helpers.h" />
<ClInclude Include="..\..\src\util_thread_starter.h" />
</ItemGroup>
<ItemGroup>
<ClCompile Include="..\..\src\main.c" />
<ClCompile Include="..\..\src\misc.c" />
<ClCompile Include="..\..\src\test_lfds700_btree_addonly_unbalanced.c" />
<ClCompile Include="..\..\src\test_lfds700_btree_addonly_unbalanced_alignment.c" />
<ClCompile Include="..\..\src\test_lfds700_btree_addonly_unbalanced_random_adds_fail.c" />
<ClCompile Include="..\..\src\test_lfds700_btree_addonly_unbalanced_random_adds_fail_and_overwrite.c" />
<ClCompile Include="..\..\src\test_lfds700_btree_addonly_unbalanced_random_adds_overwrite.c" />
<ClCompile Include="..\..\src\test_lfds700_freelist.c" />
<ClCompile Include="..\..\src\test_lfds700_freelist_alignment.c" />
<ClCompile Include="..\..\src\test_lfds700_freelist_popping.c" />
<ClCompile Include="..\..\src\test_lfds700_freelist_popping_and_pushing.c" />
<ClCompile Include="..\..\src\test_lfds700_freelist_pushing.c" />
<ClCompile Include="..\..\src\test_lfds700_freelist_rapid_popping_and_pushing.c" />
<ClCompile Include="..\..\src\test_lfds700_hash_addonly.c" />
<ClCompile Include="..\..\src\test_lfds700_hash_addonly_alignment.c" />
<ClCompile Include="..\..\src\test_lfds700_hash_addonly_iterate.c" />
<ClCompile Include="..\..\src\test_lfds700_hash_addonly_random_adds_fail.c" />
<ClCompile Include="..\..\src\test_lfds700_hash_addonly_random_adds_fail_and_overwrite.c" />
<ClCompile Include="..\..\src\test_lfds700_hash_addonly_random_adds_overwrite.c" />
<ClCompile Include="..\..\src\test_lfds700_list_addonly_ordered_singlylinked.c" />
<ClCompile Include="..\..\src\test_lfds700_list_addonly_ordered_singlylinked_alignment.c" />
<ClCompile Include="..\..\src\test_lfds700_list_addonly_ordered_singlylinked_new_ordered.c" />
<ClCompile Include="..\..\src\test_lfds700_list_addonly_ordered_singlylinked_new_ordered_with_cursor.c" />
<ClCompile Include="..\..\src\test_lfds700_list_addonly_singlylinked_unordered.c" />
<ClCompile Include="..\..\src\test_lfds700_list_addonly_singlylinked_unordered_alignment.c" />
<ClCompile Include="..\..\src\test_lfds700_list_addonly_singlylinked_unordered_new_after.c" />
<ClCompile Include="..\..\src\test_lfds700_list_addonly_singlylinked_unordered_new_end.c" />
<ClCompile Include="..\..\src\test_lfds700_list_addonly_singlylinked_unordered_new_start.c" />
<ClCompile Include="..\..\src\test_lfds700_porting_abstraction_layer_atomic.c" />
<ClCompile Include="..\..\src\test_lfds700_porting_abstraction_layer_atomic_cas.c" />
<ClCompile Include="..\..\src\test_lfds700_porting_abstraction_layer_atomic_dcas.c" />
<ClCompile Include="..\..\src\test_lfds700_porting_abstraction_layer_atomic_exchange.c" />
<ClCompile Include="..\..\src\test_lfds700_queue.c" />
<ClCompile Include="..\..\src\test_lfds700_queue_alignment.c" />
<ClCompile Include="..\..\src\test_lfds700_queue_bounded_singleconsumer_singleproducer.c" />
<ClCompile Include="..\..\src\test_lfds700_queue_bounded_singleconsumer_singleproducer_dequeuing.c" />
<ClCompile Include="..\..\src\test_lfds700_queue_bounded_singleconsumer_singleproducer_enqueuing.c" />
<ClCompile Include="..\..\src\test_lfds700_queue_bounded_singleconsumer_singleproducer_enqueuing_and_dequeuing.c" />
<ClCompile Include="..\..\src\test_lfds700_queue_dequeuing.c" />
<ClCompile Include="..\..\src\test_lfds700_queue_enqueuing.c" />
<ClCompile Include="..\..\src\test_lfds700_queue_enqueuing_and_dequeuing.c" />
<ClCompile Include="..\..\src\test_lfds700_queue_enqueuing_and_dequeuing_with_free.c" />
<ClCompile Include="..\..\src\test_lfds700_queue_enqueuing_with_malloc_and_dequeuing_with_free.c" />
<ClCompile Include="..\..\src\test_lfds700_queue_rapid_enqueuing_and_dequeuing.c" />
<ClCompile Include="..\..\src\test_lfds700_ringbuffer.c" />
<ClCompile Include="..\..\src\test_lfds700_ringbuffer_reading.c" />
<ClCompile Include="..\..\src\test_lfds700_ringbuffer_reading_and_writing.c" />
<ClCompile Include="..\..\src\test_lfds700_ringbuffer_writing.c" />
<ClCompile Include="..\..\src\test_lfds700_stack.c" />
<ClCompile Include="..\..\src\test_lfds700_stack_alignment.c" />
<ClCompile Include="..\..\src\test_lfds700_stack_popping.c" />
<ClCompile Include="..\..\src\test_lfds700_stack_popping_and_pushing.c" />
<ClCompile Include="..\..\src\test_lfds700_stack_pushing.c" />
<ClCompile Include="..\..\src\test_lfds700_stack_rapid_popping_and_pushing.c" />
<ClCompile Include="..\..\src\test_porting_abstraction_layer_get_logical_core_ids.c" />
<ClCompile Include="..\..\src\test_porting_abstraction_layer_thread_start.c" />
<ClCompile Include="..\..\src\test_porting_abstraction_layer_thread_wait.c" />
<ClCompile Include="..\..\src\util_cmdline.c" />
<ClCompile Include="..\..\src\util_memory_helpers.c" />
<ClCompile Include="..\..\src\util_thread_starter.c" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\..\liblfds700\build\visual_studio_professional_2012\liblfds700.vcxproj">
<Project>{1e5d7d09-94f2-455d-ae5e-6c7f4c96bce0}</Project>
</ProjectReference>
</ItemGroup>
<PropertyGroup Label="Globals">
<ProjectGuid>{A6BA3A68-A1D4-4C07-A0D5-7EAE73272A43}</ProjectGuid>
<Keyword>Win32Proj</Keyword>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug DLL|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v110</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug LIB|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v110</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug DLL|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v110</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug LIB|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v110</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release DLL|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v110</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release LIB|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v110</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release DLL|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v110</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release LIB|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v110</PlatformToolset>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug DLL|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug LIB|Win32'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug DLL|x64'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug LIB|x64'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release DLL|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release LIB|Win32'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release DLL|x64'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release LIB|x64'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug DLL|Win32'">
<LinkIncremental>false</LinkIncremental>
<OutDir>$(ProjectDir)..\..\bin\$(Platform) $(Configuration)\</OutDir>
<IntDir>$(ProjectDir)..\..\obj\$(Platform) $(Configuration)\</IntDir>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug LIB|Win32'">
<LinkIncremental>false</LinkIncremental>
<OutDir>$(ProjectDir)..\..\bin\$(Platform) $(Configuration)\</OutDir>
<IntDir>$(ProjectDir)..\..\obj\$(Platform) $(Configuration)\</IntDir>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug DLL|x64'">
<LinkIncremental>false</LinkIncremental>
<OutDir>$(ProjectDir)..\..\bin\$(Platform) $(Configuration)\</OutDir>
<IntDir>$(ProjectDir)..\..\obj\$(Platform) $(Configuration)\</IntDir>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug LIB|x64'">
<LinkIncremental>false</LinkIncremental>
<OutDir>$(ProjectDir)..\..\bin\$(Platform) $(Configuration)\</OutDir>
<IntDir>$(ProjectDir)..\..\obj\$(Platform) $(Configuration)\</IntDir>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release DLL|Win32'">
<LinkIncremental>false</LinkIncremental>
<OutDir>$(ProjectDir)..\..\bin\$(Platform) $(Configuration)\</OutDir>
<IntDir>$(ProjectDir)..\..\obj\$(Platform) $(Configuration)\</IntDir>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release LIB|Win32'">
<LinkIncremental>false</LinkIncremental>
<OutDir>$(ProjectDir)..\..\bin\$(Platform) $(Configuration)\</OutDir>
<IntDir>$(ProjectDir)..\..\obj\$(Platform) $(Configuration)\</IntDir>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release DLL|x64'">
<LinkIncremental>false</LinkIncremental>
<OutDir>$(ProjectDir)..\..\bin\$(Platform) $(Configuration)\</OutDir>
<IntDir>$(ProjectDir)..\..\obj\$(Platform) $(Configuration)\</IntDir>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release LIB|x64'">
<LinkIncremental>false</LinkIncremental>
<OutDir>$(ProjectDir)..\..\bin\$(Platform) $(Configuration)\</OutDir>
<IntDir>$(ProjectDir)..\..\obj\$(Platform) $(Configuration)\</IntDir>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug DLL|Win32'">
<ClCompile>
<PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
<WarningLevel>Level4</WarningLevel>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
<Optimization>Disabled</Optimization>
<CompileAsManaged>false</CompileAsManaged>
<CompileAsWinRT>false</CompileAsWinRT>
<TreatWarningAsError>true</TreatWarningAsError>
<SDLCheck>true</SDLCheck>
<MultiProcessorCompilation>true</MultiProcessorCompilation>
<IntrinsicFunctions>true</IntrinsicFunctions>
<StringPooling>true</StringPooling>
<MinimalRebuild>false</MinimalRebuild>
<ExceptionHandling>false</ExceptionHandling>
<FunctionLevelLinking>false</FunctionLevelLinking>
<EnableParallelCodeGeneration>false</EnableParallelCodeGeneration>
<EnableEnhancedInstructionSet>NoExtensions</EnableEnhancedInstructionSet>
<FloatingPointExceptions>false</FloatingPointExceptions>
<CreateHotpatchableImage>false</CreateHotpatchableImage>
<RuntimeTypeInfo>false</RuntimeTypeInfo>
<BrowseInformation>true</BrowseInformation>
<CompileAs>CompileAsC</CompileAs>
<ErrorReporting>None</ErrorReporting>
<AdditionalIncludeDirectories>..\liblfds700\inc;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<BufferSecurityCheck>true</BufferSecurityCheck>
</ClCompile>
<Link>
<TargetMachine>MachineX86</TargetMachine>
<GenerateDebugInformation>true</GenerateDebugInformation>
<SubSystem>Console</SubSystem>
<TreatLinkerWarningAsErrors>true</TreatLinkerWarningAsErrors>
<LinkTimeCodeGeneration>
</LinkTimeCodeGeneration>
<LinkStatus>
</LinkStatus>
<AdditionalDependencies>kernel32.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug LIB|Win32'">
<ClCompile>
<PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
<WarningLevel>Level4</WarningLevel>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
<Optimization>Disabled</Optimization>
<CompileAsManaged>false</CompileAsManaged>
<CompileAsWinRT>false</CompileAsWinRT>
<TreatWarningAsError>true</TreatWarningAsError>
<SDLCheck>true</SDLCheck>
<MultiProcessorCompilation>true</MultiProcessorCompilation>
<IntrinsicFunctions>true</IntrinsicFunctions>
<StringPooling>true</StringPooling>
<MinimalRebuild>false</MinimalRebuild>
<ExceptionHandling>false</ExceptionHandling>
<FunctionLevelLinking>false</FunctionLevelLinking>
<EnableParallelCodeGeneration>false</EnableParallelCodeGeneration>
<EnableEnhancedInstructionSet>NoExtensions</EnableEnhancedInstructionSet>
<FloatingPointExceptions>false</FloatingPointExceptions>
<CreateHotpatchableImage>false</CreateHotpatchableImage>
<RuntimeTypeInfo>false</RuntimeTypeInfo>
<BrowseInformation>true</BrowseInformation>
<CompileAs>CompileAsC</CompileAs>
<ErrorReporting>None</ErrorReporting>
<AdditionalIncludeDirectories>..\liblfds700\inc;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<BufferSecurityCheck>true</BufferSecurityCheck>
</ClCompile>
<Link>
<TargetMachine>MachineX86</TargetMachine>
<GenerateDebugInformation>true</GenerateDebugInformation>
<SubSystem>Console</SubSystem>
<TreatLinkerWarningAsErrors>true</TreatLinkerWarningAsErrors>
<LinkTimeCodeGeneration>
</LinkTimeCodeGeneration>
<LinkStatus>
</LinkStatus>
<AdditionalDependencies>kernel32.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug DLL|x64'">
<ClCompile>
<PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
<WarningLevel>Level4</WarningLevel>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
<Optimization>Disabled</Optimization>
<CompileAsManaged>false</CompileAsManaged>
<CompileAsWinRT>false</CompileAsWinRT>
<TreatWarningAsError>true</TreatWarningAsError>
<SDLCheck>true</SDLCheck>
<MultiProcessorCompilation>true</MultiProcessorCompilation>
<IntrinsicFunctions>true</IntrinsicFunctions>
<StringPooling>true</StringPooling>
<MinimalRebuild>false</MinimalRebuild>
<ExceptionHandling>false</ExceptionHandling>
<FunctionLevelLinking>false</FunctionLevelLinking>
<EnableParallelCodeGeneration>false</EnableParallelCodeGeneration>
<EnableEnhancedInstructionSet>NotSet</EnableEnhancedInstructionSet>
<FloatingPointExceptions>false</FloatingPointExceptions>
<CreateHotpatchableImage>false</CreateHotpatchableImage>
<RuntimeTypeInfo>false</RuntimeTypeInfo>
<BrowseInformation>true</BrowseInformation>
<CompileAs>CompileAsC</CompileAs>
<ErrorReporting>None</ErrorReporting>
<BufferSecurityCheck>true</BufferSecurityCheck>
<OmitFramePointers>false</OmitFramePointers>
</ClCompile>
<Link>
<GenerateDebugInformation>true</GenerateDebugInformation>
<SubSystem>Console</SubSystem>
<TreatLinkerWarningAsErrors>true</TreatLinkerWarningAsErrors>
<LinkTimeCodeGeneration>
</LinkTimeCodeGeneration>
<AdditionalDependencies>kernel32.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug LIB|x64'">
<ClCompile>
<PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
<WarningLevel>Level4</WarningLevel>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
<Optimization>Disabled</Optimization>
<CompileAsManaged>false</CompileAsManaged>
<CompileAsWinRT>false</CompileAsWinRT>
<TreatWarningAsError>true</TreatWarningAsError>
<SDLCheck>true</SDLCheck>
<MultiProcessorCompilation>true</MultiProcessorCompilation>
<IntrinsicFunctions>true</IntrinsicFunctions>
<StringPooling>true</StringPooling>
<MinimalRebuild>false</MinimalRebuild>
<ExceptionHandling>false</ExceptionHandling>
<FunctionLevelLinking>false</FunctionLevelLinking>
<EnableParallelCodeGeneration>false</EnableParallelCodeGeneration>
<EnableEnhancedInstructionSet>NotSet</EnableEnhancedInstructionSet>
<FloatingPointExceptions>false</FloatingPointExceptions>
<CreateHotpatchableImage>false</CreateHotpatchableImage>
<RuntimeTypeInfo>false</RuntimeTypeInfo>
<BrowseInformation>true</BrowseInformation>
<CompileAs>CompileAsC</CompileAs>
<ErrorReporting>None</ErrorReporting>
<BufferSecurityCheck>true</BufferSecurityCheck>
<OmitFramePointers>false</OmitFramePointers>
</ClCompile>
<Link>
<GenerateDebugInformation>true</GenerateDebugInformation>
<SubSystem>Console</SubSystem>
<TreatLinkerWarningAsErrors>true</TreatLinkerWarningAsErrors>
<LinkTimeCodeGeneration>
</LinkTimeCodeGeneration>
<AdditionalDependencies>kernel32.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link>
<ProjectReference>
<LinkLibraryDependencies>true</LinkLibraryDependencies>
</ProjectReference>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release DLL|Win32'">
<ClCompile>
<PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
<WarningLevel>Level4</WarningLevel>
<DebugInformationFormat>None</DebugInformationFormat>
<CompileAsManaged>false</CompileAsManaged>
<CompileAsWinRT>false</CompileAsWinRT>
<ExceptionHandling>false</ExceptionHandling>
<CreateHotpatchableImage>false</CreateHotpatchableImage>
<CompileAs>CompileAsC</CompileAs>
<TreatWarningAsError>true</TreatWarningAsError>
<SDLCheck>
</SDLCheck>
<MultiProcessorCompilation>true</MultiProcessorCompilation>
<InlineFunctionExpansion>AnySuitable</InlineFunctionExpansion>
<IntrinsicFunctions>true</IntrinsicFunctions>
<FavorSizeOrSpeed>Speed</FavorSizeOrSpeed>
<OmitFramePointers>true</OmitFramePointers>
<EnableFiberSafeOptimizations>true</EnableFiberSafeOptimizations>
<WholeProgramOptimization>true</WholeProgramOptimization>
<StringPooling>true</StringPooling>
<BufferSecurityCheck>false</BufferSecurityCheck>
<FunctionLevelLinking>true</FunctionLevelLinking>
<EnableParallelCodeGeneration>true</EnableParallelCodeGeneration>
<FloatingPointExceptions>false</FloatingPointExceptions>
<RuntimeTypeInfo>false</RuntimeTypeInfo>
<OpenMPSupport>false</OpenMPSupport>
<ErrorReporting>None</ErrorReporting>
</ClCompile>
<Link>
<TargetMachine>MachineX86</TargetMachine>
<GenerateDebugInformation>false</GenerateDebugInformation>
<SubSystem>Console</SubSystem>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<TreatLinkerWarningAsErrors>true</TreatLinkerWarningAsErrors>
<SetChecksum>true</SetChecksum>
<LinkErrorReporting>NoErrorReport</LinkErrorReporting>
<AdditionalDependencies>kernel32.lib;%(AdditionalDependencies)</AdditionalDependencies>
<LinkTimeCodeGeneration>UseLinkTimeCodeGeneration</LinkTimeCodeGeneration>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release LIB|Win32'">
<ClCompile>
<PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
<WarningLevel>Level4</WarningLevel>
<DebugInformationFormat>None</DebugInformationFormat>
<CompileAsManaged>false</CompileAsManaged>
<CompileAsWinRT>false</CompileAsWinRT>
<ExceptionHandling>false</ExceptionHandling>
<CreateHotpatchableImage>false</CreateHotpatchableImage>
<CompileAs>CompileAsC</CompileAs>
<TreatWarningAsError>true</TreatWarningAsError>
<SDLCheck>
</SDLCheck>
<MultiProcessorCompilation>true</MultiProcessorCompilation>
<InlineFunctionExpansion>AnySuitable</InlineFunctionExpansion>
<IntrinsicFunctions>true</IntrinsicFunctions>
<FavorSizeOrSpeed>Speed</FavorSizeOrSpeed>
<OmitFramePointers>true</OmitFramePointers>
<EnableFiberSafeOptimizations>true</EnableFiberSafeOptimizations>
<WholeProgramOptimization>true</WholeProgramOptimization>
<StringPooling>true</StringPooling>
<BufferSecurityCheck>false</BufferSecurityCheck>
<FunctionLevelLinking>true</FunctionLevelLinking>
<EnableParallelCodeGeneration>true</EnableParallelCodeGeneration>
<FloatingPointExceptions>false</FloatingPointExceptions>
<RuntimeTypeInfo>false</RuntimeTypeInfo>
<OpenMPSupport>false</OpenMPSupport>
<ErrorReporting>None</ErrorReporting>
</ClCompile>
<Link>
<TargetMachine>MachineX86</TargetMachine>
<GenerateDebugInformation>false</GenerateDebugInformation>
<SubSystem>Console</SubSystem>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<TreatLinkerWarningAsErrors>true</TreatLinkerWarningAsErrors>
<SetChecksum>true</SetChecksum>
<LinkErrorReporting>NoErrorReport</LinkErrorReporting>
<AdditionalDependencies>kernel32.lib;%(AdditionalDependencies)</AdditionalDependencies>
<LinkTimeCodeGeneration>UseLinkTimeCodeGeneration</LinkTimeCodeGeneration>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release DLL|x64'">
<ClCompile>
<PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
<WarningLevel>Level4</WarningLevel>
<DebugInformationFormat>None</DebugInformationFormat>
<CompileAsManaged>false</CompileAsManaged>
<CompileAsWinRT>false</CompileAsWinRT>
<ExceptionHandling>false</ExceptionHandling>
<CreateHotpatchableImage>false</CreateHotpatchableImage>
<CompileAs>CompileAsC</CompileAs>
<TreatWarningAsError>true</TreatWarningAsError>
<SDLCheck>
</SDLCheck>
<MultiProcessorCompilation>true</MultiProcessorCompilation>
<InlineFunctionExpansion>AnySuitable</InlineFunctionExpansion>
<IntrinsicFunctions>true</IntrinsicFunctions>
<FavorSizeOrSpeed>Speed</FavorSizeOrSpeed>
<OmitFramePointers>true</OmitFramePointers>
<EnableFiberSafeOptimizations>true</EnableFiberSafeOptimizations>
<WholeProgramOptimization>true</WholeProgramOptimization>
<StringPooling>true</StringPooling>
<BufferSecurityCheck>false</BufferSecurityCheck>
<FunctionLevelLinking>true</FunctionLevelLinking>
<EnableParallelCodeGeneration>true</EnableParallelCodeGeneration>
<FloatingPointExceptions>false</FloatingPointExceptions>
<RuntimeTypeInfo>false</RuntimeTypeInfo>
<OpenMPSupport>false</OpenMPSupport>
<ErrorReporting>None</ErrorReporting>
</ClCompile>
<Link>
<GenerateDebugInformation>false</GenerateDebugInformation>
<SubSystem>Console</SubSystem>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<TreatLinkerWarningAsErrors>true</TreatLinkerWarningAsErrors>
<SetChecksum>true</SetChecksum>
<LinkErrorReporting>NoErrorReport</LinkErrorReporting>
<AdditionalDependencies>kernel32.lib;%(AdditionalDependencies)</AdditionalDependencies>
<LinkTimeCodeGeneration>UseLinkTimeCodeGeneration</LinkTimeCodeGeneration>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release LIB|x64'">
<ClCompile>
<PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
<WarningLevel>Level4</WarningLevel>
<DebugInformationFormat>None</DebugInformationFormat>
<CompileAsManaged>false</CompileAsManaged>
<CompileAsWinRT>false</CompileAsWinRT>
<ExceptionHandling>false</ExceptionHandling>
<CreateHotpatchableImage>false</CreateHotpatchableImage>
<CompileAs>CompileAsC</CompileAs>
<TreatWarningAsError>true</TreatWarningAsError>
<SDLCheck>
</SDLCheck>
<MultiProcessorCompilation>true</MultiProcessorCompilation>
<InlineFunctionExpansion>AnySuitable</InlineFunctionExpansion>
<IntrinsicFunctions>true</IntrinsicFunctions>
<FavorSizeOrSpeed>Speed</FavorSizeOrSpeed>
<OmitFramePointers>true</OmitFramePointers>
<EnableFiberSafeOptimizations>true</EnableFiberSafeOptimizations>
<WholeProgramOptimization>true</WholeProgramOptimization>
<StringPooling>true</StringPooling>
<BufferSecurityCheck>false</BufferSecurityCheck>
<FunctionLevelLinking>true</FunctionLevelLinking>
<EnableParallelCodeGeneration>true</EnableParallelCodeGeneration>
<FloatingPointExceptions>false</FloatingPointExceptions>
<RuntimeTypeInfo>false</RuntimeTypeInfo>
<OpenMPSupport>false</OpenMPSupport>
<ErrorReporting>None</ErrorReporting>
</ClCompile>
<Link>
<GenerateDebugInformation>false</GenerateDebugInformation>
<SubSystem>Console</SubSystem>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<TreatLinkerWarningAsErrors>true</TreatLinkerWarningAsErrors>
<SetChecksum>true</SetChecksum>
<LinkErrorReporting>NoErrorReport</LinkErrorReporting>
<AdditionalDependencies>kernel32.lib;%(AdditionalDependencies)</AdditionalDependencies>
<LinkTimeCodeGeneration>UseLinkTimeCodeGeneration</LinkTimeCodeGeneration>
</Link>
</ItemDefinitionGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<Filter Include="Source Files">
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
<Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
</Filter>
<Filter Include="Header Files">
<UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
<Extensions>h;hpp;hxx;hm;inl;inc;xsd</Extensions>
</Filter>
<Filter Include="Resource Files">
<UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
<Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav</Extensions>
</Filter>
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\..\src\internal.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\..\src\test_porting_abstraction_layer_operating_system.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\..\src\util_cmdline.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\..\src\util_memory_helpers.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\..\src\util_thread_starter.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ClCompile Include="..\..\src\main.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\..\src\misc.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\..\src\test_lfds700_btree_addonly_unbalanced.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\..\src\test_lfds700_btree_addonly_unbalanced_alignment.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\..\src\test_lfds700_btree_addonly_unbalanced_random_adds_fail.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\..\src\test_lfds700_btree_addonly_unbalanced_random_adds_fail_and_overwrite.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\..\src\test_lfds700_btree_addonly_unbalanced_random_adds_overwrite.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\..\src\test_lfds700_freelist.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\..\src\test_lfds700_freelist_alignment.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\..\src\test_lfds700_freelist_popping.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\..\src\test_lfds700_freelist_popping_and_pushing.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\..\src\test_lfds700_freelist_pushing.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\..\src\test_lfds700_freelist_rapid_popping_and_pushing.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\..\src\test_lfds700_hash_addonly.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\..\src\test_lfds700_hash_addonly_alignment.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\..\src\test_lfds700_hash_addonly_iterate.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\..\src\test_lfds700_hash_addonly_random_adds_fail.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\..\src\test_lfds700_hash_addonly_random_adds_fail_and_overwrite.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\..\src\test_lfds700_hash_addonly_random_adds_overwrite.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\..\src\test_lfds700_list_addonly_ordered_singlylinked.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\..\src\test_lfds700_list_addonly_ordered_singlylinked_alignment.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\..\src\test_lfds700_list_addonly_ordered_singlylinked_new_ordered.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\..\src\test_lfds700_list_addonly_ordered_singlylinked_new_ordered_with_cursor.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\..\src\test_lfds700_list_addonly_singlylinked_unordered.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\..\src\test_lfds700_list_addonly_singlylinked_unordered_alignment.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\..\src\test_lfds700_list_addonly_singlylinked_unordered_new_after.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\..\src\test_lfds700_list_addonly_singlylinked_unordered_new_end.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\..\src\test_lfds700_list_addonly_singlylinked_unordered_new_start.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\..\src\test_lfds700_porting_abstraction_layer_atomic.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\..\src\test_lfds700_porting_abstraction_layer_atomic_cas.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\..\src\test_lfds700_porting_abstraction_layer_atomic_dcas.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\..\src\test_lfds700_porting_abstraction_layer_atomic_exchange.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\..\src\test_lfds700_queue.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\..\src\test_lfds700_queue_alignment.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\..\src\test_lfds700_queue_bounded_singleconsumer_singleproducer.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\..\src\test_lfds700_queue_bounded_singleconsumer_singleproducer_dequeuing.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\..\src\test_lfds700_queue_bounded_singleconsumer_singleproducer_enqueuing.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\..\src\test_lfds700_queue_bounded_singleconsumer_singleproducer_enqueuing_and_dequeuing.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\..\src\test_lfds700_queue_dequeuing.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\..\src\test_lfds700_queue_enqueuing.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\..\src\test_lfds700_queue_enqueuing_and_dequeuing.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\..\src\test_lfds700_queue_enqueuing_and_dequeuing_with_free.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\..\src\test_lfds700_queue_enqueuing_with_malloc_and_dequeuing_with_free.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\..\src\test_lfds700_queue_rapid_enqueuing_and_dequeuing.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\..\src\test_lfds700_ringbuffer.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\..\src\test_lfds700_ringbuffer_reading.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\..\src\test_lfds700_ringbuffer_reading_and_writing.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\..\src\test_lfds700_ringbuffer_writing.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\..\src\test_lfds700_stack.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\..\src\test_lfds700_stack_alignment.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\..\src\test_lfds700_stack_popping.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\..\src\test_lfds700_stack_popping_and_pushing.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\..\src\test_lfds700_stack_pushing.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\..\src\test_lfds700_stack_rapid_popping_and_pushing.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\..\src\test_porting_abstraction_layer_get_logical_core_ids.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\..\src\test_porting_abstraction_layer_thread_start.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\..\src\test_porting_abstraction_layer_thread_wait.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\..\src\util_cmdline.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\..\src\util_memory_helpers.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\..\src\util_thread_starter.c">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
</Project>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup />
</Project>
\ No newline at end of file
/***** includes *****/
#define _GNU_SOURCE
#include <assert.h>
#include <ctype.h>
#include <limits.h>
#include <math.h>
#include <stdarg.h>
#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include "../../liblfds700/inc/liblfds700.h"
#include "test_porting_abstraction_layer_operating_system.h"
/***** defines *****/
#define and &&
#define or ||
#define NO_FLAGS 0x0
#define BITS_PER_BYTE 8
#define TEST_DURATION_IN_SECONDS 5
#define TIME_LOOP_COUNT 10000
#define REDUCED_TIME_LOOP_COUNT 1000
#define NUMBER_OF_NANOSECONDS_IN_ONE_SECOND 1000000000LLU
#define ONE_MEGABYTE_IN_BYTES (1024 * 1024)
#define DEFAULT_TEST_MEMORY_IN_MEGABYTES 512U
#define TEST_PAL_DEFAULT_NUMA_NODE_ID 0
#define LFDS700_TEST_VERSION_STRING "7.0.0"
#define LFDS700_TEST_VERSION_INTEGER 700
#if( defined _KERNEL_MODE )
#define MODE_TYPE_STRING "kernel-mode"
#endif
#if( !defined _KERNEL_MODE )
#define MODE_TYPE_STRING "user-mode"
#endif
#if( defined NDEBUG && !defined COVERAGE && !defined TSAN )
#define BUILD_TYPE_STRING "release"
#endif
#if( !defined NDEBUG && !defined COVERAGE && !defined TSAN )
#define BUILD_TYPE_STRING "debug"
#endif
#if( !defined NDEBUG && defined COVERAGE && !defined TSAN )
#define BUILD_TYPE_STRING "coverage"
#endif
#if( !defined NDEBUG && !defined COVERAGE && defined TSAN )
#define BUILD_TYPE_STRING "threadsanitizer"
#endif
/***** enums *****/
enum flag
{
LOWERED,
RAISED
};
/***** structs *****/
struct test_pal_logical_processor
{
lfds700_pal_uint_t
logical_processor_number,
windows_logical_processor_group_number;
struct lfds700_list_asu_element
lasue;
};
/***** prototypes *****/
int main( int argc, char **argv );
void internal_display_test_name( char *format_string, ... );
void internal_display_test_result( lfds700_pal_uint_t number_name_dvs_pairs, ... );
void internal_display_data_structure_validity( enum lfds700_misc_validity dvs );
void internal_show_version( void );
void internal_logical_core_id_element_cleanup_callback( struct lfds700_list_asu_state *lasus, struct lfds700_list_asu_element *lasue );
int test_pal_thread_start( test_pal_thread_state_t *thread_state, struct test_pal_logical_processor *lp, test_pal_thread_return_t (TEST_PAL_CALLING_CONVENTION *thread_function)(void *thread_user_state), void *thread_user_state );
void test_pal_thread_wait( test_pal_thread_state_t thread_state );
void test_pal_get_logical_core_ids( struct lfds700_list_asu_state *lasus );
void test_lfds700_pal_atomic( struct lfds700_list_asu_state *list_of_logical_processors, lfds700_pal_uint_t memory_in_megabytes );
void test_lfds700_pal_atomic_cas( struct lfds700_list_asu_state *list_of_logical_processors );
void test_lfds700_pal_atomic_dwcas( struct lfds700_list_asu_state *list_of_logical_processors );
void test_lfds700_pal_atomic_exchange( struct lfds700_list_asu_state *list_of_logical_processors, lfds700_pal_uint_t memory_in_megabytes );
void test_lfds700_hash_a( struct lfds700_list_asu_state *list_of_logical_processors, lfds700_pal_uint_t memory_in_megabytes );
void test_lfds700_hash_a_alignment( void );
void test_lfds700_hash_a_fail_and_overwrite_on_existing_key( void );
void test_lfds700_hash_a_random_adds_fail_on_existing( struct lfds700_list_asu_state *list_of_logical_processors, lfds700_pal_uint_t memory_in_megabytes );
void test_lfds700_hash_a_random_adds_overwrite_on_existing( struct lfds700_list_asu_state *list_of_logical_processors, lfds700_pal_uint_t memory_in_megabytes );
void test_lfds700_hash_a_iterate( void );
void test_lfds700_list_aos( struct lfds700_list_asu_state *list_of_logical_processors, lfds700_pal_uint_t memory_in_megabytes );
void test_lfds700_list_aos_alignment( void );
void test_lfds700_list_aos_new_ordered( struct lfds700_list_asu_state *list_of_logical_processors, lfds700_pal_uint_t memory_in_megabytes );
void test_lfds700_list_aos_new_ordered_with_cursor( struct lfds700_list_asu_state *list_of_logical_processors, lfds700_pal_uint_t memory_in_megabytes );
void test_lfds700_list_asu( struct lfds700_list_asu_state *list_of_logical_processors, lfds700_pal_uint_t memory_in_megabytes );
void test_lfds700_list_asu_alignment( void );
void test_lfds700_list_asu_new_start( struct lfds700_list_asu_state *list_of_logical_processors, lfds700_pal_uint_t memory_in_megabytes );
void test_lfds700_list_asu_new_end( struct lfds700_list_asu_state *list_of_logical_processors, lfds700_pal_uint_t memory_in_megabytes );
void test_lfds700_list_asu_new_after( struct lfds700_list_asu_state *list_of_logical_processors, lfds700_pal_uint_t memory_in_megabytes );
void test_lfds700_btree_au( struct lfds700_list_asu_state *list_of_logical_processors, lfds700_pal_uint_t memory_in_megabytes );
void test_lfds700_btree_au_alignment( void );
void test_lfds700_btree_au_fail_and_overwrite_on_existing_key( void );
void test_lfds700_btree_au_random_adds_fail_on_existing( struct lfds700_list_asu_state *list_of_logical_processors, lfds700_pal_uint_t memory_in_megabytes );
void test_lfds700_btree_au_random_adds_overwrite_on_existing( struct lfds700_list_asu_state *list_of_logical_processors, lfds700_pal_uint_t memory_in_megabytes );
void test_lfds700_freelist( struct lfds700_list_asu_state *list_of_logical_processors, lfds700_pal_uint_t memory_in_megabytes );
void test_lfds700_freelist_alignment( void );
void test_lfds700_freelist_popping( struct lfds700_list_asu_state *list_of_logical_processors, lfds700_pal_uint_t memory_in_megabytes );
void test_lfds700_freelist_pushing( struct lfds700_list_asu_state *list_of_logical_processors, lfds700_pal_uint_t memory_in_megabytes );
void test_lfds700_freelist_popping_and_pushing( struct lfds700_list_asu_state *list_of_logical_processors, lfds700_pal_uint_t memory_in_megabytes );
void test_lfds700_freelist_rapid_popping_and_pushing( struct lfds700_list_asu_state *list_of_logical_processors );
void test_lfds700_freelist_pushing_array( void );
void test_lfds700_queue( struct lfds700_list_asu_state *list_of_logical_processors, lfds700_pal_uint_t memory_in_megabytes );
void test_lfds700_queue_alignment( void );
void test_lfds700_queue_enqueuing( struct lfds700_list_asu_state *list_of_logical_processors, lfds700_pal_uint_t memory_in_megabytes );
void test_lfds700_queue_dequeuing( struct lfds700_list_asu_state *list_of_logical_processors, lfds700_pal_uint_t memory_in_megabytes );
void test_lfds700_queue_enqueuing_and_dequeuing( struct lfds700_list_asu_state *list_of_logical_processors );
void test_lfds700_queue_rapid_enqueuing_and_dequeuing( struct lfds700_list_asu_state *list_of_logical_processors, lfds700_pal_uint_t memory_in_megabytes );
void test_lfds700_queue_enqueuing_and_dequeuing_with_free( struct lfds700_list_asu_state *list_of_logical_processors, lfds700_pal_uint_t memory_in_megabytes );
void test_lfds700_queue_enqueuing_with_malloc_and_dequeuing_with_free( struct lfds700_list_asu_state *list_of_logical_processors );
void test_lfds700_queue_bss( struct lfds700_list_asu_state *list_of_logical_processors );
void test_lfds700_queue_bss_enqueuing( void );
void test_lfds700_queue_bss_dequeuing( void );
void test_lfds700_queue_bss_enqueuing_and_dequeuing( struct lfds700_list_asu_state *list_of_logical_processors );
void test_lfds700_ringbuffer( struct lfds700_list_asu_state *list_of_logical_processors, lfds700_pal_uint_t memory_in_megabytes );
void test_lfds700_ringbuffer_reading( struct lfds700_list_asu_state *list_of_logical_processors, lfds700_pal_uint_t memory_in_megabytes );
void test_lfds700_ringbuffer_reading_and_writing( struct lfds700_list_asu_state *list_of_logical_processors, lfds700_pal_uint_t memory_in_megabytes );
void test_lfds700_ringbuffer_writing( struct lfds700_list_asu_state *list_of_logical_processors, lfds700_pal_uint_t memory_in_megabytes );
void test_lfds700_stack( struct lfds700_list_asu_state *list_of_logical_processors, lfds700_pal_uint_t memory_in_megabytes );
void test_lfds700_stack_alignment( void );
void test_lfds700_stack_pushing( struct lfds700_list_asu_state *list_of_logical_processors, lfds700_pal_uint_t memory_in_megabytes );
void test_lfds700_stack_popping( struct lfds700_list_asu_state *list_of_logical_processors, lfds700_pal_uint_t memory_in_megabytes );
void test_lfds700_stack_popping_and_pushing( struct lfds700_list_asu_state *list_of_logical_processors, lfds700_pal_uint_t memory_in_megabytes );
void test_lfds700_stack_rapid_popping_and_pushing( struct lfds700_list_asu_state *list_of_logical_processors );
void test_lfds700_stack_pushing_array( void );
/***** late includes *****/
#include "util_cmdline.h"
#include "util_memory_helpers.h"
#include "util_thread_starter.h"
/***** includes *****/
#include "internal.h"
/****************************************************************************/
int main( int argc, char **argv )
{
enum flag
run_flag = LOWERED,
show_error_flag = LOWERED,
show_help_flag = LOWERED,
show_version_flag = LOWERED;
int
rv;
lfds700_pal_uint_t
loop,
iterations = 1,
memory_in_megabytes = DEFAULT_TEST_MEMORY_IN_MEGABYTES;
struct lfds700_list_asu_state
list_of_logical_processors;
struct util_cmdline_state
cs;
union util_cmdline_arg_data
*arg_data;
assert( argc >= 1 );
assert( argv != NULL );
lfds700_misc_library_init_valid_on_current_logical_core();
util_cmdline_init( &cs );
util_cmdline_add_arg( &cs, 'h', LIBCOMMON_CMDLINE_ARG_TYPE_FLAG );
util_cmdline_add_arg( &cs, 'i', LIBCOMMON_CMDLINE_ARG_TYPE_INTEGER );
util_cmdline_add_arg( &cs, 'm', LIBCOMMON_CMDLINE_ARG_TYPE_INTEGER );
util_cmdline_add_arg( &cs, 'r', LIBCOMMON_CMDLINE_ARG_TYPE_FLAG );
util_cmdline_add_arg( &cs, 'v', LIBCOMMON_CMDLINE_ARG_TYPE_FLAG );
rv = util_cmdline_process_args( &cs, argc, argv );
if( rv == 0 )
show_error_flag = RAISED;
if( rv == 1 )
{
util_cmdline_get_arg_data( &cs, 'h', &arg_data );
if( arg_data != NULL )
show_help_flag = RAISED;
util_cmdline_get_arg_data( &cs, 'i', &arg_data );
if( arg_data != NULL )
iterations = (lfds700_pal_uint_t) arg_data->integer.integer;
util_cmdline_get_arg_data( &cs, 'm', &arg_data );
if( arg_data != NULL )
memory_in_megabytes = (lfds700_pal_uint_t) arg_data->integer.integer;
util_cmdline_get_arg_data( &cs, 'r', &arg_data );
if( arg_data != NULL )
run_flag = RAISED;
util_cmdline_get_arg_data( &cs, 'v', &arg_data );
if( arg_data != NULL )
show_version_flag = RAISED;
}
util_cmdline_cleanup( &cs );
if( argc == 1 or (run_flag == LOWERED and show_version_flag == LOWERED) )
show_help_flag = RAISED;
if( show_error_flag == RAISED )
{
printf( "\nInvalid arguments. Sorry - it's a simple parser, so no clues.\n"
"-h or run with no args to see the help text.\n" );
return( EXIT_SUCCESS );
}
if( show_help_flag == RAISED )
{
printf( "test -h -i [n] -m [n] -r -v\n"
" -h : help\n"
" -i [n] : number of iterations (default : 1)\n"
" -m [n] : memory for tests, in mb (default : %u)\n"
" -r : run (causes test to run; present so no args gives help)\n"
" -v : version\n", DEFAULT_TEST_MEMORY_IN_MEGABYTES );
return( EXIT_SUCCESS );
}
if( show_version_flag == RAISED )
{
internal_show_version();
return( EXIT_SUCCESS );
}
if( run_flag == RAISED )
{
test_pal_get_logical_core_ids( &list_of_logical_processors );
for( loop = 0 ; loop < (lfds700_pal_uint_t) iterations ; loop++ )
{
printf( "\n"
"Test Iteration %02llu\n"
"=================\n", (int long long unsigned) (loop+1) );
test_lfds700_pal_atomic( &list_of_logical_processors, memory_in_megabytes );
test_lfds700_btree_au( &list_of_logical_processors, memory_in_megabytes );
test_lfds700_freelist( &list_of_logical_processors, memory_in_megabytes );
test_lfds700_hash_a( &list_of_logical_processors, memory_in_megabytes );
test_lfds700_list_aos( &list_of_logical_processors, memory_in_megabytes );
test_lfds700_list_asu( &list_of_logical_processors, memory_in_megabytes );
test_lfds700_queue( &list_of_logical_processors, memory_in_megabytes );
test_lfds700_queue_bss( &list_of_logical_processors );
test_lfds700_ringbuffer( &list_of_logical_processors, memory_in_megabytes );
test_lfds700_stack( &list_of_logical_processors, memory_in_megabytes );
}
lfds700_list_asu_cleanup( &list_of_logical_processors, internal_logical_core_id_element_cleanup_callback );
}
lfds700_misc_library_cleanup();
return( EXIT_SUCCESS );
}
/***** includes *****/
#include "internal.h"
/****************************************************************************/
void internal_display_test_name( char *format_string, ... )
{
va_list
va;
assert( format_string != NULL );
va_start( va, format_string );
vprintf( format_string, va );
printf( "..." );
va_end( va );
fflush( stdout );
return;
}
/****************************************************************************/
void internal_display_test_result( lfds700_pal_uint_t number_name_dvs_pairs, ... )
{
char
*name;
enum flag
passed_flag = RAISED;
enum lfds700_misc_validity
dvs;
lfds700_pal_uint_t
loop;
va_list
va;
// 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 lfds700_misc_validity );
if( dvs != LFDS700_MISC_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 lfds700_misc_validity );
printf( "%s ", name );
internal_display_data_structure_validity( dvs );
if( loop+1 < number_name_dvs_pairs )
printf( ", " );
}
va_end( va );
printf( ")\n" );
/* TRD : quick hack
the whole test programme needs rewriting
and for now I just want to make it so we
exit with failure upon any test failing
*/
exit( EXIT_FAILURE );
}
return;
}
/****************************************************************************/
void internal_display_data_structure_validity( enum lfds700_misc_validity dvs )
{
char
*string = NULL;
switch( dvs )
{
case LFDS700_MISC_VALIDITY_VALID:
string = "valid";
break;
case LFDS700_MISC_VALIDITY_INVALID_LOOP:
string = "invalid - loop detected";
break;
case LFDS700_MISC_VALIDITY_INVALID_ORDER:
string = "invalid - invalid order detected";
break;
case LFDS700_MISC_VALIDITY_INVALID_MISSING_ELEMENTS:
string = "invalid - missing elements";
break;
case LFDS700_MISC_VALIDITY_INVALID_ADDITIONAL_ELEMENTS:
string = "invalid - additional elements";
break;
case LFDS700_MISC_VALIDITY_INVALID_TEST_DATA:
string = "invalid - invalid test data";
break;
}
printf( "%s", string );
return;
}
/****************************************************************************/
void internal_show_version()
{
char const
*version_and_build_string;
printf( "test %s (%s, %s) (" __DATE__ " " __TIME__ ")\n", LFDS700_TEST_VERSION_STRING, BUILD_TYPE_STRING, MODE_TYPE_STRING );
lfds700_misc_query( LFDS700_MISC_QUERY_GET_BUILD_AND_VERSION_STRING, NULL, (void **) &version_and_build_string );
printf( "%s\n", version_and_build_string );
return;
}
/****************************************************************************/
#pragma warning( disable : 4100 )
void internal_logical_core_id_element_cleanup_callback( struct lfds700_list_asu_state *lasus, struct lfds700_list_asu_element *lasue )
{
struct test_pal_logical_processor
*lp;
assert( lasus != NULL );
assert( lasue != NULL );
lp = LFDS700_LIST_ASU_GET_VALUE_FROM_ELEMENT( *lasue );
util_aligned_free( lp );
return;
}
#pragma warning( default : 4100 )
/***** includes *****/
#include "internal.h"
/****************************************************************************/
#pragma warning( disable : 4127 ) // TRD : disables MSVC warning for condition expressions being const
void test_lfds700_btree_au( struct lfds700_list_asu_state *list_of_logical_processors, lfds700_pal_uint_t memory_in_megabytes )
{
assert( list_of_logical_processors != NULL );
// TRD : memory_in_megabytes can be any value in its range
if( LFDS700_MISC_ATOMIC_SUPPORT_CAS and LFDS700_MISC_ATOMIC_SUPPORT_EXCHANGE )
{
printf( "\n"
"Binary Tree (add-only, unbalanced) Tests\n"
"========================================\n" );
test_lfds700_btree_au_alignment();
test_lfds700_btree_au_fail_and_overwrite_on_existing_key();
test_lfds700_btree_au_random_adds_fail_on_existing( list_of_logical_processors, memory_in_megabytes );
test_lfds700_btree_au_random_adds_overwrite_on_existing( list_of_logical_processors, memory_in_megabytes );
}
return;
}
#pragma warning( default : 4127 )
/***** includes *****/
#include "internal.h"
/****************************************************************************/
#pragma warning( disable : 4127 ) // TRD : disables MSVC warning for condition expressions being const
void test_lfds700_btree_au_alignment()
{
enum lfds700_misc_validity
dvs = LFDS700_MISC_VALIDITY_VALID;
/* TRD : these are compile time checks
but we do them here because this is a test programme
and it should indicate issues to users when it is *run*,
not when it is compiled, because a compile error normally
indicates a problem with the code itself and so is misleading
*/
internal_display_test_name( "Alignment" );
// TRD : struct lfds700_btree_au_element
if( offsetof(struct lfds700_btree_au_element,up) % LFDS700_PAL_ATOMIC_ISOLATION_IN_BYTES != 0 )
dvs = LFDS700_MISC_VALIDITY_INVALID_TEST_DATA;
if( offsetof(struct lfds700_btree_au_element,left) % LFDS700_PAL_ATOMIC_ISOLATION_IN_BYTES != 0 )
dvs = LFDS700_MISC_VALIDITY_INVALID_TEST_DATA;
if( offsetof(struct lfds700_btree_au_element,right) % LFDS700_PAL_ATOMIC_ISOLATION_IN_BYTES != 0 )
dvs = LFDS700_MISC_VALIDITY_INVALID_TEST_DATA;
if( offsetof(struct lfds700_btree_au_element,key) % LFDS700_PAL_ATOMIC_ISOLATION_IN_BYTES != 0 )
dvs = LFDS700_MISC_VALIDITY_INVALID_TEST_DATA;
if( offsetof(struct lfds700_btree_au_element,value) % LFDS700_PAL_ATOMIC_ISOLATION_IN_BYTES != 0 )
dvs = LFDS700_MISC_VALIDITY_INVALID_TEST_DATA;
if( offsetof(struct lfds700_btree_au_element,key) % LFDS700_PAL_ATOMIC_ISOLATION_IN_BYTES != 0 )
dvs = LFDS700_MISC_VALIDITY_INVALID_TEST_DATA;
// TRD : struct lfds700_btree_au_state
if( offsetof(struct lfds700_btree_au_state,root) % LFDS700_PAL_ATOMIC_ISOLATION_IN_BYTES != 0 )
dvs = LFDS700_MISC_VALIDITY_INVALID_TEST_DATA;
if( offsetof(struct lfds700_btree_au_state,key_compare_function) % LFDS700_PAL_ATOMIC_ISOLATION_IN_BYTES != 0 )
dvs = LFDS700_MISC_VALIDITY_INVALID_TEST_DATA;
// TRD : print the test result
internal_display_test_result( 1, "btree_au", dvs );
return;
}
#pragma warning( default : 4127 )
/***** includes *****/
#include "internal.h"
/***** structs *****/
struct test_element
{
struct lfds700_btree_au_element
baue;
lfds700_pal_uint_t
key;
};
struct test_state
{
lfds700_pal_uint_t
insert_fail_count,
number_elements;
struct lfds700_btree_au_state
*baus;
struct test_element
*element_array;
};
/***** private prototypes *****/
static int key_compare_function( void const *new_value, void const *value_in_tree );
static test_pal_thread_return_t TEST_PAL_CALLING_CONVENTION thread_adding( void *util_thread_starter_thread_state );
/****************************************************************************/
void test_lfds700_btree_au_random_adds_fail_on_existing( struct lfds700_list_asu_state *list_of_logical_processors, lfds700_pal_uint_t memory_in_megabytes )
{
enum lfds700_misc_validity
dvs = LFDS700_MISC_VALIDITY_VALID;
lfds700_pal_uint_t
actual_sum_insert_failure_count,
expected_sum_insert_failure_count,
index = 0,
*key_count_array,
loop,
number_elements,
number_logical_processors,
random_value,
subloop;
struct lfds700_list_asu_element
*lasue;
struct lfds700_btree_au_element
*baue = NULL;
struct lfds700_btree_au_state
baus;
struct lfds700_misc_prng_state
ps;
struct lfds700_misc_validation_info
vi;
struct test_pal_logical_processor
*lp;
struct util_thread_starter_state
*tts;
struct test_state
*ts;
test_pal_thread_state_t
*thread_handles;
void
*key;
assert( list_of_logical_processors != NULL );
// TRD : memory_in_megabytes can be any value in its range
/* TRD : we create a single btree_au
we generate 10k elements per thread (one per logical processor) in an array
we set a random number in each element, which is the key
random numbers are generated are from 0 to 5000, so we must have some duplicates
(we don't use value, so we always pass in a NULL for that when we insert)
each thread loops, adds those elements into the btree, and counts the total number of insert fails
(we don't count on a per value basis because of the performance hit - we'll be TLBing all the time)
this test has the btree_au set to fail on add, so duplicates should be eliminated
we then merge the per-thread arrays
we should find in the tree one of every value, and the sum of the counts of each value (beyond the
first value, which was inserted) in the merged arrays should equal the sum of the insert fails from
each thread
we check the count of unique values in the merged array and use that when calling the btree_au validation function
we in-order walk and check that what we have in the tree matches what we have in the merged array
and then check the fail counts
*/
internal_display_test_name( "Random adds and walking (fail on existing key)" );
lfds700_misc_prng_init( &ps );
lfds700_list_asu_query( list_of_logical_processors, LFDS700_LIST_ASU_QUERY_GET_POTENTIALLY_INACCURATE_COUNT, NULL, (void **) &number_logical_processors );
lfds700_btree_au_init_valid_on_current_logical_core( &baus, key_compare_function, LFDS700_BTREE_AU_EXISTING_KEY_FAIL, NULL );
ts = util_malloc_wrapper( sizeof(struct test_state) * number_logical_processors );
number_elements = ( memory_in_megabytes * ONE_MEGABYTE_IN_BYTES ) / ( sizeof(struct test_element) * number_logical_processors );
for( loop = 0 ; loop < number_logical_processors ; loop++ )
{
(ts+loop)->baus = &baus;
(ts+loop)->element_array = util_aligned_malloc( sizeof(struct test_element) * number_elements, LFDS700_PAL_ATOMIC_ISOLATION_IN_BYTES );
(ts+loop)->number_elements = number_elements;
(ts+loop)->insert_fail_count = 0;
for( subloop = 0 ; subloop < number_elements ; subloop++ )
{
random_value = LFDS700_MISC_PRNG_GENERATE( &ps );
((ts+loop)->element_array+subloop)->key = (lfds700_pal_uint_t) floor( (number_elements/2) * ((double) random_value / (double) LFDS700_MISC_PRNG_MAX) );
}
}
thread_handles = util_malloc_wrapper( sizeof(test_pal_thread_state_t) * number_logical_processors );
util_thread_starter_new( &tts, number_logical_processors );
LFDS700_MISC_BARRIER_STORE;
lfds700_misc_force_store();
loop = 0;
lasue = NULL;
while( LFDS700_LIST_ASU_GET_START_AND_THEN_NEXT(*list_of_logical_processors, lasue) )
{
lp = LFDS700_LIST_ASU_GET_VALUE_FROM_ELEMENT( *lasue );
util_thread_starter_start( tts, &thread_handles[loop], loop, lp, thread_adding, ts+loop );
loop++;
}
util_thread_starter_run( tts );
for( loop = 0 ; loop < number_logical_processors ; loop++ )
test_pal_thread_wait( thread_handles[loop] );
util_thread_starter_delete( tts );
free( thread_handles );
LFDS700_MISC_BARRIER_LOAD;
/* TRD : now for validation
make an array equal to number_elements, set all to 0
iterate over every per-thread array, counting the number of each value into this array
so we can know how many elements ought to have failed to be inserted
as well as being able to work out the actual number of elements which should be present in the btree, for the btree validation call
*/
key_count_array = util_malloc_wrapper( sizeof(lfds700_pal_uint_t) * number_elements );
for( loop = 0 ; loop < number_elements ; loop++ )
*(key_count_array+loop) = 0;
for( loop = 0 ; loop < number_logical_processors ; loop++ )
for( subloop = 0 ; subloop < number_elements ; subloop++ )
( *(key_count_array+( (ts+loop)->element_array+subloop)->key) )++;
// TRD : first, btree validation function
vi.min_elements = number_elements;
for( loop = 0 ; loop < number_elements ; loop++ )
if( *(key_count_array+loop) == 0 )
vi.min_elements--;
vi.max_elements = vi.min_elements;
lfds700_btree_au_query( &baus, LFDS700_BTREE_AU_QUERY_SINGLETHREADED_VALIDATE, (void *) &vi, (void *) &dvs );
/* TRD : now check the sum of per-thread insert failures
is what it should be, which is the sum of key_count_array,
but with every count minus one (for the single succesful insert)
and where elements of 0 are ignored (i.e. do not have -1 applied)
*/
expected_sum_insert_failure_count = 0;
for( loop = 0 ; loop < number_elements ; loop++ )
if( *(key_count_array+loop) != 0 )
expected_sum_insert_failure_count += *(key_count_array+loop) - 1;
actual_sum_insert_failure_count = 0;
for( loop = 0 ; loop < number_logical_processors ; loop++ )
actual_sum_insert_failure_count += (ts+loop)->insert_fail_count;
if( expected_sum_insert_failure_count != actual_sum_insert_failure_count )
dvs = LFDS700_MISC_VALIDITY_INVALID_TEST_DATA;
/* TRD : now compared the combined array and an in-order walk of the tree
ignoring array elements with the value 0, we should find an exact match
*/
if( dvs == LFDS700_MISC_VALIDITY_VALID )
{
// TRD : in-order walk over btree_au and check key_count_array matches
while( dvs == LFDS700_MISC_VALIDITY_VALID and lfds700_btree_au_get_by_absolute_position_and_then_by_relative_position(&baus, &baue, LFDS700_BTREE_AU_ABSOLUTE_POSITION_SMALLEST_IN_TREE, LFDS700_BTREE_AU_RELATIVE_POSITION_NEXT_LARGER_ELEMENT_IN_ENTIRE_TREE) )
{
key = LFDS700_BTREE_AU_GET_KEY_FROM_ELEMENT( *baue );
while( *(key_count_array+index) == 0 )
index++;
if( index++ != (lfds700_pal_uint_t) key )
dvs = LFDS700_MISC_VALIDITY_INVALID_TEST_DATA;
}
}
// TRD : cleanup
free( key_count_array );
lfds700_btree_au_cleanup( &baus, NULL );
// TRD : cleanup
for( loop = 0 ; loop < number_logical_processors ; loop++ )
util_aligned_free( (ts+loop)->element_array );
free( ts );
// TRD : print the test result
internal_display_test_result( 1, "btree_au", dvs );
return;
}
/****************************************************************************/
#pragma warning( disable : 4100 )
static int key_compare_function( void const *new_key, void const *key_in_tree )
{
int
cr = 0;
// TRD : key_new can be any value in its range
// TRD : key_in_tree can be any value in its range
if( (lfds700_pal_uint_t) new_key < (lfds700_pal_uint_t) key_in_tree )
cr = -1;
if( (lfds700_pal_uint_t) new_key > (lfds700_pal_uint_t) key_in_tree )
cr = 1;
return( cr );
}
#pragma warning( default : 4100 )
/****************************************************************************/
static test_pal_thread_return_t TEST_PAL_CALLING_CONVENTION thread_adding( void *util_thread_starter_thread_state )
{
enum lfds700_btree_au_insert_result
alr;
lfds700_pal_uint_t
index = 0;
struct test_state
*ts;
struct lfds700_misc_prng_state
ps;
struct util_thread_starter_thread_state
*tsts;
LFDS700_MISC_MAKE_VALID_ON_CURRENT_LOGICAL_CORE_INITS_COMPLETED_BEFORE_NOW_ON_ANY_OTHER_LOGICAL_CORE;
assert( util_thread_starter_thread_state != NULL );
tsts = (struct util_thread_starter_thread_state *) util_thread_starter_thread_state;
ts = (struct test_state *) tsts->thread_user_state;
lfds700_misc_prng_init( &ps );
util_thread_starter_ready_and_wait( tsts );
while( index < ts->number_elements )
{
LFDS700_BTREE_AU_SET_KEY_IN_ELEMENT( (ts->element_array+index)->baue, (ts->element_array+index)->key );
LFDS700_BTREE_AU_SET_VALUE_IN_ELEMENT( (ts->element_array+index)->baue, 0 );
alr = lfds700_btree_au_insert( ts->baus, &(ts->element_array+index)->baue, NULL, &ps );
if( alr == LFDS700_BTREE_AU_INSERT_RESULT_FAILURE_EXISTING_KEY )
ts->insert_fail_count++;
index++;
}
LFDS700_MISC_BARRIER_STORE;
lfds700_misc_force_store();
return( (test_pal_thread_return_t) EXIT_SUCCESS );
}
/***** includes *****/
#include "internal.h"
/***** private prototypes *****/
static int key_compare_function( void const *new_value, void const *value_in_tree );
/****************************************************************************/
void test_lfds700_btree_au_fail_and_overwrite_on_existing_key()
{
enum lfds700_btree_au_insert_result
alr;
enum lfds700_misc_validity
dvs = LFDS700_MISC_VALIDITY_VALID;
struct lfds700_btree_au_element
baue_one,
baue_two,
*existing_baue;
struct lfds700_btree_au_state
baus;
struct lfds700_misc_prng_state
ps;
void
*value;
/* TRD : the random_adds tests with fail and overwrite don't (can't, not in a performant manner)
test that the fail and/or overwrite of user data has *actually* happened - they use the
return value from the link function call, rather than empirically observing the final
state of the tree
as such, we now have a couple of single threaded tests where we check that the user data
value really is being modified (or not modified, as the case may be)
*/
internal_display_test_name( "Fail and overwrite on existing key" );
lfds700_misc_prng_init( &ps );
/* TRD : so, we make a tree which is fail on existing
add one element, with a known user data
we then try to add the same key again, with a different user data
the call should fail, and then we get the element by its key
and check its user data is unchanged
(and confirm the failed link returned the correct existing_baue)
that's the first test done
*/
lfds700_btree_au_init_valid_on_current_logical_core( &baus, key_compare_function, LFDS700_BTREE_AU_EXISTING_KEY_FAIL, NULL );
LFDS700_BTREE_AU_SET_KEY_IN_ELEMENT( baue_one, 0 );
LFDS700_BTREE_AU_SET_VALUE_IN_ELEMENT( baue_one, 1 );
alr = lfds700_btree_au_insert( &baus, &baue_one, NULL, &ps );
if( alr != LFDS700_BTREE_AU_INSERT_RESULT_SUCCESS )
dvs = LFDS700_MISC_VALIDITY_INVALID_TEST_DATA;
LFDS700_BTREE_AU_SET_KEY_IN_ELEMENT( baue_two, 0 );
LFDS700_BTREE_AU_SET_VALUE_IN_ELEMENT( baue_two, 2 );
alr = lfds700_btree_au_insert( &baus, &baue_two, &existing_baue, &ps );
if( alr != LFDS700_BTREE_AU_INSERT_RESULT_FAILURE_EXISTING_KEY )
dvs = LFDS700_MISC_VALIDITY_INVALID_TEST_DATA;
if( existing_baue != &baue_one )
dvs = LFDS700_MISC_VALIDITY_INVALID_TEST_DATA;
value = LFDS700_BTREE_AU_GET_VALUE_FROM_ELEMENT( *existing_baue );
if( (void *) (lfds700_pal_uint_t) value != (void *) (lfds700_pal_uint_t) 1 )
dvs = LFDS700_MISC_VALIDITY_INVALID_TEST_DATA;
lfds700_btree_au_cleanup( &baus, NULL );
/* TRD : second test, make a tree which is overwrite on existing
add one element, with a known user data
we then try to add the same key again, with a different user data
the call should succeed, and then we get the element by its key
and check its user data is changed
(and confirm the failed link returned the correct existing_baue)
that's the secondtest done
*/
lfds700_btree_au_init_valid_on_current_logical_core( &baus, key_compare_function, LFDS700_BTREE_AU_EXISTING_KEY_OVERWRITE, NULL );
LFDS700_BTREE_AU_SET_KEY_IN_ELEMENT( baue_one, 0 );
LFDS700_BTREE_AU_SET_VALUE_IN_ELEMENT( baue_one, 1 );
alr = lfds700_btree_au_insert( &baus, &baue_one, NULL, &ps );
if( alr != LFDS700_BTREE_AU_INSERT_RESULT_SUCCESS )
dvs = LFDS700_MISC_VALIDITY_INVALID_TEST_DATA;
LFDS700_BTREE_AU_SET_KEY_IN_ELEMENT( baue_two, 0 );
LFDS700_BTREE_AU_SET_VALUE_IN_ELEMENT( baue_two, 2 );
alr = lfds700_btree_au_insert( &baus, &baue_two, NULL, &ps );
if( alr != LFDS700_BTREE_AU_INSERT_RESULT_SUCCESS_OVERWRITE )
dvs = LFDS700_MISC_VALIDITY_INVALID_TEST_DATA;
lfds700_btree_au_cleanup( &baus, NULL );
// TRD : print the test result
internal_display_test_result( 1, "btree_au", dvs );
return;
}
/****************************************************************************/
#pragma warning( disable : 4100 )
static int key_compare_function( void const *new_key, void const *key_in_tree )
{
int
cr = 0;
// TRD : key_new can be any value in its range
// TRD : key_in_tree can be any value in its range
if( (lfds700_pal_uint_t) new_key < (lfds700_pal_uint_t) key_in_tree )
cr = -1;
if( (lfds700_pal_uint_t) new_key > (lfds700_pal_uint_t) key_in_tree )
cr = 1;
return( cr );
}
#pragma warning( default : 4100 )
/***** includes *****/
#include "internal.h"
/***** structs *****/
struct test_element
{
struct lfds700_btree_au_element
baue;
lfds700_pal_uint_t
key;
};
struct test_state
{
lfds700_pal_uint_t
insert_existing_count,
number_elements;
struct lfds700_btree_au_state
*baus;
struct test_element
*element_array;
};
/***** private prototypes *****/
static int key_compare_function( void const *new_value, void const *value_in_tree );
static test_pal_thread_return_t TEST_PAL_CALLING_CONVENTION thread_adding( void *util_thread_starter_thread_state );
/****************************************************************************/
void test_lfds700_btree_au_random_adds_overwrite_on_existing( struct lfds700_list_asu_state *list_of_logical_processors, lfds700_pal_uint_t memory_in_megabytes )
{
enum lfds700_misc_validity
dvs = LFDS700_MISC_VALIDITY_VALID;
lfds700_pal_uint_t
actual_sum_insert_existing_count,
expected_sum_insert_existing_count,
index = 0,
*key_count_array,
loop,
number_elements,
number_logical_processors,
random_value,
subloop;
struct lfds700_list_asu_element
*lasue;
struct lfds700_btree_au_element
*baue = NULL;
struct lfds700_btree_au_state
baus;
struct lfds700_misc_prng_state
ps;
struct lfds700_misc_validation_info
vi;
struct test_pal_logical_processor
*lp;
struct util_thread_starter_state
*tts;
struct test_state
*ts;
test_pal_thread_state_t
*thread_handles;
void
*key;
assert( list_of_logical_processors != NULL );
// TRD : memory_in_megabytes can be any value in its range
/* TRD : we create a single btree_au
we generate 10k elements per thread (one per logical processor) in an array
we set a random number in each element, which is the key
random numbers are generated are from 0 to 5000, so we must have some duplicates
(we don't use value, so we always pass in a NULL for that when we insert)
each thread loops, adds those elements into the btree, and counts the total number of insert fails
(we don't count on a per value basis because of the performance hit - we'll be TLBing all the time)
this test has the btree_au set to overwrite on add, so duplicates should be eliminated
we then merge the per-thread arrays
we should find in the tree one of every value, and the sum of the counts of each value (beyond the
first value, which was inserted) in the merged arrays should equal the sum of the existing_baues returned
from each thread when they inserted and found an existing element
we check the count of unique values in the merged array and use that when calling the btree_au validation function
we in-order walk and check that what we have in the tree matches what we have in the merged array
and then check the fail counts
*/
internal_display_test_name( "Random adds and walking (overwrite on existing key)" );
lfds700_misc_prng_init( &ps );
lfds700_list_asu_query( list_of_logical_processors, LFDS700_LIST_ASU_QUERY_GET_POTENTIALLY_INACCURATE_COUNT, NULL, (void **) &number_logical_processors );
lfds700_btree_au_init_valid_on_current_logical_core( &baus, key_compare_function, LFDS700_BTREE_AU_EXISTING_KEY_OVERWRITE, NULL );
ts = util_malloc_wrapper( sizeof(struct test_state) * number_logical_processors );
number_elements = ( memory_in_megabytes * ONE_MEGABYTE_IN_BYTES ) / ( sizeof(struct test_element) * number_logical_processors );
for( loop = 0 ; loop < number_logical_processors ; loop++ )
{
(ts+loop)->baus = &baus;
(ts+loop)->element_array = util_aligned_malloc( sizeof(struct test_element) * number_elements, LFDS700_PAL_ATOMIC_ISOLATION_IN_BYTES );
(ts+loop)->number_elements = number_elements;
(ts+loop)->insert_existing_count = 0;
for( subloop = 0 ; subloop < number_elements ; subloop++ )
{
random_value = LFDS700_MISC_PRNG_GENERATE( &ps );
((ts+loop)->element_array+subloop)->key = (lfds700_pal_uint_t) floor( (number_elements/2) * ((double) random_value / (double) LFDS700_MISC_PRNG_MAX) );
}
}
thread_handles = util_malloc_wrapper( sizeof(test_pal_thread_state_t) * number_logical_processors );
util_thread_starter_new( &tts, number_logical_processors );
LFDS700_MISC_BARRIER_STORE;
lfds700_misc_force_store();
loop = 0;
lasue = NULL;
while( LFDS700_LIST_ASU_GET_START_AND_THEN_NEXT(*list_of_logical_processors, lasue) )
{
lp = LFDS700_LIST_ASU_GET_VALUE_FROM_ELEMENT( *lasue );
util_thread_starter_start( tts, &thread_handles[loop], loop, lp, thread_adding, ts+loop );
loop++;
}
util_thread_starter_run( tts );
for( loop = 0 ; loop < number_logical_processors ; loop++ )
test_pal_thread_wait( thread_handles[loop] );
util_thread_starter_delete( tts );
free( thread_handles );
LFDS700_MISC_BARRIER_LOAD;
/* TRD : now for validation
make an array equal to number_elements, set all to 0
iterate over every per-thread array, counting the number of each value into this array
so we can know how many elements ought to have failed to be inserted
as well as being able to work out the actual number of elements which should be present in the btree, for the btree validation call
*/
key_count_array = util_malloc_wrapper( sizeof(lfds700_pal_uint_t) * number_elements );
for( loop = 0 ; loop < number_elements ; loop++ )
*(key_count_array+loop) = 0;
for( loop = 0 ; loop < number_logical_processors ; loop++ )
for( subloop = 0 ; subloop < number_elements ; subloop++ )
( *(key_count_array+( (ts+loop)->element_array+subloop)->key) )++;
// TRD : first, btree validation function
vi.min_elements = number_elements;
for( loop = 0 ; loop < number_elements ; loop++ )
if( *(key_count_array+loop) == 0 )
vi.min_elements--;
vi.max_elements = vi.min_elements;
lfds700_btree_au_query( &baus, LFDS700_BTREE_AU_QUERY_SINGLETHREADED_VALIDATE, (void *) &vi, (void *) &dvs );
/* TRD : now check the sum of per-thread insert failures
is what it should be, which is the sum of key_count_array,
but with every count minus one (for the single succesful insert)
and where elements of 0 are ignored (i.e. do not have -1 applied)
*/
expected_sum_insert_existing_count = 0;
for( loop = 0 ; loop < number_elements ; loop++ )
if( *(key_count_array+loop) != 0 )
expected_sum_insert_existing_count += *(key_count_array+loop) - 1;
actual_sum_insert_existing_count = 0;
for( loop = 0 ; loop < number_logical_processors ; loop++ )
actual_sum_insert_existing_count += (ts+loop)->insert_existing_count;
if( expected_sum_insert_existing_count != actual_sum_insert_existing_count )
dvs = LFDS700_MISC_VALIDITY_INVALID_TEST_DATA;
/* TRD : now compared the combined array and an in-order walk of the tree
ignoring array elements with the value 0, we should find an exact match
*/
if( dvs == LFDS700_MISC_VALIDITY_VALID )
{
// TRD : in-order walk over btree_au and check key_count_array matches
while( dvs == LFDS700_MISC_VALIDITY_VALID and lfds700_btree_au_get_by_absolute_position_and_then_by_relative_position(&baus, &baue, LFDS700_BTREE_AU_ABSOLUTE_POSITION_SMALLEST_IN_TREE, LFDS700_BTREE_AU_RELATIVE_POSITION_NEXT_LARGER_ELEMENT_IN_ENTIRE_TREE) )
{
key = LFDS700_BTREE_AU_GET_KEY_FROM_ELEMENT( *baue );
while( *(key_count_array+index) == 0 )
index++;
if( index++ != (lfds700_pal_uint_t) key )
dvs = LFDS700_MISC_VALIDITY_INVALID_TEST_DATA;
}
}
// TRD : cleanup
free( key_count_array );
lfds700_btree_au_cleanup( &baus, NULL );
// TRD : cleanup
for( loop = 0 ; loop < number_logical_processors ; loop++ )
util_aligned_free( (ts+loop)->element_array );
free( ts );
// TRD : print the test result
internal_display_test_result( 1, "btree_au", dvs );
return;
}
/****************************************************************************/
#pragma warning( disable : 4100 )
static int key_compare_function( void const *new_key, void const *key_in_tree )
{
int
cr = 0;
// TRD : key_new can be any value in its range
// TRD : key_in_tree can be any value in its range
if( (lfds700_pal_uint_t) new_key < (lfds700_pal_uint_t) key_in_tree )
cr = -1;
if( (lfds700_pal_uint_t) new_key > (lfds700_pal_uint_t) key_in_tree )
cr = 1;
return( cr );
}
#pragma warning( default : 4100 )
/****************************************************************************/
static test_pal_thread_return_t TEST_PAL_CALLING_CONVENTION thread_adding( void *util_thread_starter_thread_state )
{
enum lfds700_btree_au_insert_result
alr;
lfds700_pal_uint_t
index = 0;
struct test_state
*ts;
struct lfds700_btree_au_element
*existing_baue;
struct lfds700_misc_prng_state
ps;
struct util_thread_starter_thread_state
*tsts;
LFDS700_MISC_MAKE_VALID_ON_CURRENT_LOGICAL_CORE_INITS_COMPLETED_BEFORE_NOW_ON_ANY_OTHER_LOGICAL_CORE;
assert( util_thread_starter_thread_state != NULL );
tsts = (struct util_thread_starter_thread_state *) util_thread_starter_thread_state;
ts = (struct test_state *) tsts->thread_user_state;
lfds700_misc_prng_init( &ps );
util_thread_starter_ready_and_wait( tsts );
while( index < ts->number_elements )
{
LFDS700_BTREE_AU_SET_KEY_IN_ELEMENT( (ts->element_array+index)->baue, (ts->element_array+index)->key );
LFDS700_BTREE_AU_SET_VALUE_IN_ELEMENT( (ts->element_array+index)->baue, 0 );
alr = lfds700_btree_au_insert( ts->baus, &(ts->element_array+index)->baue, &existing_baue, &ps );
if( alr == LFDS700_BTREE_AU_INSERT_RESULT_SUCCESS_OVERWRITE )
ts->insert_existing_count++;
index++;
}
LFDS700_MISC_BARRIER_STORE;
lfds700_misc_force_store();
return( (test_pal_thread_return_t) EXIT_SUCCESS );
}
/***** includes *****/
#include "internal.h"
/****************************************************************************/
#pragma warning( disable : 4127 ) // TRD : disables MSVC warning for condition expressions being const
void test_lfds700_freelist( struct lfds700_list_asu_state *list_of_logical_processors, lfds700_pal_uint_t memory_in_megabytes )
{
assert( list_of_logical_processors != NULL );
// TRD : memory_in_megabytes can be any value in its range
if( LFDS700_MISC_ATOMIC_SUPPORT_DWCAS )
{
printf( "\n"
"Freelist Tests\n"
"==============\n" );
test_lfds700_freelist_alignment();
test_lfds700_freelist_popping( list_of_logical_processors, memory_in_megabytes );
test_lfds700_freelist_pushing( list_of_logical_processors, memory_in_megabytes );
test_lfds700_freelist_popping_and_pushing( list_of_logical_processors, memory_in_megabytes );
test_lfds700_freelist_rapid_popping_and_pushing( list_of_logical_processors );
}
return;
}
#pragma warning( default : 4127 )
/***** includes *****/
#include "internal.h"
/****************************************************************************/
#pragma warning( disable : 4127 ) // TRD : disables MSVC warning for condition expressions being const
void test_lfds700_freelist_alignment()
{
enum lfds700_misc_validity
dvs = LFDS700_MISC_VALIDITY_VALID;
/* TRD : these are compile time checks
but we do them here because this is a test programme
and it should indicate issues to users when it is *run*,
not when it is compiled, because a compile error normally
indicates a problem with the code itself and so is misleading
*/
internal_display_test_name( "Alignment" );
// TRD : struct lfds700_freelist_state
if( offsetof(struct lfds700_freelist_state,top) % LFDS700_PAL_ATOMIC_ISOLATION_IN_BYTES != 0 )
dvs = LFDS700_MISC_VALIDITY_INVALID_TEST_DATA;
if( offsetof(struct lfds700_freelist_state,user_state) % LFDS700_PAL_ATOMIC_ISOLATION_IN_BYTES != 0 )
dvs = LFDS700_MISC_VALIDITY_INVALID_TEST_DATA;
// TRD : print the test result
internal_display_test_result( 1, "freelist", dvs );
return;
}
#pragma warning( default : 4127 )
/***** includes *****/
#include "internal.h"
/***** structs *****/
struct test_state
{
struct lfds700_freelist_state
*fs;
};
struct test_element
{
struct lfds700_freelist_element
fe;
enum flag
popped_flag;
};
/***** private prototypes *****/
static test_pal_thread_return_t TEST_PAL_CALLING_CONVENTION thread_popping( void *util_thread_starter_thread_state );
/****************************************************************************/
void test_lfds700_freelist_popping( struct lfds700_list_asu_state *list_of_logical_processors, lfds700_pal_uint_t memory_in_megabytes )
{
enum lfds700_misc_validity
dvs = LFDS700_MISC_VALIDITY_VALID;
lfds700_pal_uint_t
loop,
number_elements,
number_logical_processors;
struct lfds700_list_asu_element
*lasue;
struct lfds700_freelist_state
fs;
struct lfds700_misc_prng_state
ps;
struct lfds700_misc_validation_info
vi = { 0, 0 };
struct test_pal_logical_processor
*lp;
struct util_thread_starter_state
*tts;
struct test_element
*te_array;
struct test_state
*ts;
test_pal_thread_state_t
*thread_handles;
assert( list_of_logical_processors != NULL );
// TRD : memory_in_megabytes can be any value in its range
/* 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 to the container test element
we then run one thread per CPU
where each thread loops, popping as quickly as possible
each test element has a flag which indicates it has been popped
the threads run till the source freelist is empty
we then check the test elements
every element should have been popped
then tidy up
we have no extra code for CAS/GC as we're only popping
*/
internal_display_test_name( "Popping" );
lfds700_list_asu_query( list_of_logical_processors, LFDS700_LIST_ASU_QUERY_GET_POTENTIALLY_INACCURATE_COUNT, NULL, (void **) &number_logical_processors );
lfds700_misc_prng_init( &ps );
lfds700_freelist_init_valid_on_current_logical_core( &fs, NULL );
number_elements = ( memory_in_megabytes * ONE_MEGABYTE_IN_BYTES ) / sizeof(struct test_element);
te_array = util_aligned_malloc( sizeof(struct test_element) * number_elements, LFDS700_PAL_ATOMIC_ISOLATION_IN_BYTES );
for( loop = 0 ; loop < number_elements ; loop++ )
{
(te_array+loop)->popped_flag = LOWERED;
LFDS700_FREELIST_SET_VALUE_IN_ELEMENT( (te_array+loop)->fe, te_array+loop );
lfds700_freelist_push( &fs, &(te_array+loop)->fe, &ps );
}
ts = util_aligned_malloc( sizeof(struct test_state) * number_logical_processors, LFDS700_PAL_ATOMIC_ISOLATION_IN_BYTES );
for( loop = 0 ; loop < number_logical_processors ; loop++ )
(ts+loop)->fs = &fs;
thread_handles = util_malloc_wrapper( sizeof(test_pal_thread_state_t) * number_logical_processors );
util_thread_starter_new( &tts, number_logical_processors );
LFDS700_MISC_BARRIER_STORE;
lfds700_misc_force_store();
loop = 0;
lasue = NULL;
while( LFDS700_LIST_ASU_GET_START_AND_THEN_NEXT(*list_of_logical_processors, lasue) )
{
lp = LFDS700_LIST_ASU_GET_VALUE_FROM_ELEMENT( *lasue );
util_thread_starter_start( tts, &thread_handles[loop], loop, lp, thread_popping, ts+loop );
loop++;
}
util_thread_starter_run( tts );
for( loop = 0 ; loop < number_logical_processors ; loop++ )
test_pal_thread_wait( thread_handles[loop] );
util_thread_starter_delete( tts );
free( thread_handles );
LFDS700_MISC_BARRIER_LOAD;
lfds700_freelist_query( &fs, LFDS700_FREELIST_QUERY_SINGLETHREADED_VALIDATE, &vi, &dvs );
// TRD : now we check each element has popped_flag set to RAISED
for( loop = 0 ; loop < number_elements ; loop++ )
if( (te_array+loop)->popped_flag == LOWERED )
dvs = LFDS700_MISC_VALIDITY_INVALID_TEST_DATA;
// TRD : cleanup
lfds700_freelist_cleanup( &fs, NULL );
util_aligned_free( ts );
util_aligned_free( te_array );
// TRD : print the test result
internal_display_test_result( 1, "freelist", dvs );
return;
}
/****************************************************************************/
static test_pal_thread_return_t TEST_PAL_CALLING_CONVENTION thread_popping( void *util_thread_starter_thread_state )
{
struct lfds700_freelist_element
*fe;
struct lfds700_misc_prng_state
ps;
struct test_element
*te;
struct test_state
*ts;
struct util_thread_starter_thread_state
*tsts;
LFDS700_MISC_MAKE_VALID_ON_CURRENT_LOGICAL_CORE_INITS_COMPLETED_BEFORE_NOW_ON_ANY_OTHER_LOGICAL_CORE;
assert( util_thread_starter_thread_state != NULL );
tsts = (struct util_thread_starter_thread_state *) util_thread_starter_thread_state;
ts = (struct test_state *) tsts->thread_user_state;
lfds700_misc_prng_init( &ps );
util_thread_starter_ready_and_wait( tsts );
while( lfds700_freelist_pop(ts->fs, &fe, &ps) )
{
te = LFDS700_FREELIST_GET_VALUE_FROM_ELEMENT( *fe );
te->popped_flag = RAISED;
}
LFDS700_MISC_BARRIER_STORE;
lfds700_misc_force_store();
return( (test_pal_thread_return_t) EXIT_SUCCESS );
}
/***** includes *****/
#include "internal.h"
/***** structs *****/
struct test_element;
struct test_state
{
struct lfds700_freelist_state
fs_thread_local,
*fs;
lfds700_pal_uint_t
number_elements;
struct test_element
*fs_thread_local_te_array;
};
struct test_element
{
struct lfds700_freelist_element
fe,
thread_local_fe;
lfds700_pal_uint_t
datum;
};
/***** private prototypes *****/
static test_pal_thread_return_t TEST_PAL_CALLING_CONVENTION thread_popping_and_pushing_start_popping( void *util_thread_starter_thread_state );
static test_pal_thread_return_t TEST_PAL_CALLING_CONVENTION thread_popping_and_pushing_start_pushing( void *util_thread_starter_thread_state );
/****************************************************************************/
void test_lfds700_freelist_popping_and_pushing( struct lfds700_list_asu_state *list_of_logical_processors, lfds700_pal_uint_t memory_in_megabytes )
{
enum lfds700_misc_validity
dvs;
lfds700_pal_uint_t
loop,
number_elements,
number_logical_processors,
subloop;
struct lfds700_list_asu_element
*lasue;
struct lfds700_freelist_state
fs;
struct lfds700_misc_prng_state
ps;
struct lfds700_misc_validation_info
vi;
struct test_pal_logical_processor
*lp;
struct util_thread_starter_state
*tts;
struct test_element
*te_array;
struct test_state
*ts;
test_pal_thread_state_t
*thread_handles;
assert( list_of_logical_processors != NULL );
// TRD : memory_in_megabytes can be any value in its range
/* TRD : we have two threads per CPU
the threads loop for ten seconds
the first thread pushes 10000 elements then pops 10000 elements
the second thread pops 10000 elements then pushes 10000 elements
all pushes and pops go onto the single main freelist
with a per-thread local freelist to store the pops
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 (%d seconds)", TEST_DURATION_IN_SECONDS );
lfds700_list_asu_query( list_of_logical_processors, LFDS700_LIST_ASU_QUERY_GET_POTENTIALLY_INACCURATE_COUNT, NULL, (void **) &number_logical_processors );
lfds700_misc_prng_init( &ps );
number_elements = ( memory_in_megabytes * ONE_MEGABYTE_IN_BYTES ) / ( sizeof(struct test_element) * number_logical_processors * 2 );
lfds700_freelist_init_valid_on_current_logical_core( &fs, NULL );
// TRD : we allocate half the total elements here, and half again later, which is why *2 above, but not here
te_array = util_aligned_malloc( sizeof(struct test_element) * number_elements * number_logical_processors, LFDS700_PAL_ATOMIC_ISOLATION_IN_BYTES );
// TRD : initial elements in the main freelist so the popping threads can start immediately
for( loop = 0 ; loop < number_elements * number_logical_processors ; loop++ )
{
(te_array+loop)->datum = loop;
LFDS700_FREELIST_SET_VALUE_IN_ELEMENT( (te_array+loop)->fe, te_array+loop );
lfds700_freelist_push( &fs, &(te_array+loop)->fe, &ps );
}
ts = util_aligned_malloc( sizeof(struct test_state) * number_logical_processors * 2, LFDS700_PAL_ATOMIC_ISOLATION_IN_BYTES );
for( loop = 0 ; loop < number_logical_processors ; loop++ )
{
// TRD : first set of threads (poppers)
(ts+loop)->fs = &fs;
(ts+loop)->number_elements = number_elements;
lfds700_freelist_init_valid_on_current_logical_core( &(ts+loop)->fs_thread_local, NULL );
// TRD : second set of threads (pushers - who need elements in their per-thread freelists)
(ts+loop+number_logical_processors)->fs = &fs;
(ts+loop+number_logical_processors)->number_elements = number_elements;
lfds700_freelist_init_valid_on_current_logical_core( &(ts+loop+number_logical_processors)->fs_thread_local, NULL );
// TRD : fill the pushing thread freelists
(ts+loop+number_logical_processors)->fs_thread_local_te_array = util_aligned_malloc( sizeof(struct test_element) * number_elements, LFDS700_PAL_ATOMIC_ISOLATION_IN_BYTES );
for( subloop = 0 ; subloop < number_elements ; subloop++ )
{
((ts+loop+number_logical_processors)->fs_thread_local_te_array+subloop)->datum = loop;
LFDS700_FREELIST_SET_VALUE_IN_ELEMENT( ((ts+loop+number_logical_processors)->fs_thread_local_te_array+subloop)->thread_local_fe, (ts+loop+number_logical_processors)->fs_thread_local_te_array+subloop );
lfds700_freelist_push( &(ts+loop+number_logical_processors)->fs_thread_local, &((ts+loop+number_logical_processors)->fs_thread_local_te_array+subloop)->thread_local_fe, &ps );
}
}
thread_handles = util_malloc_wrapper( sizeof(test_pal_thread_state_t) * number_logical_processors * 2 );
util_thread_starter_new( &tts, number_logical_processors * 2 );
LFDS700_MISC_BARRIER_STORE;
lfds700_misc_force_store();
loop = 0;
lasue = NULL;
while( LFDS700_LIST_ASU_GET_START_AND_THEN_NEXT(*list_of_logical_processors, lasue) )
{
lp = LFDS700_LIST_ASU_GET_VALUE_FROM_ELEMENT( *lasue );
util_thread_starter_start( tts, &thread_handles[loop], loop, lp, thread_popping_and_pushing_start_popping, ts+loop );
util_thread_starter_start( tts, &thread_handles[loop+number_logical_processors], loop+number_logical_processors, lp, thread_popping_and_pushing_start_pushing, ts+loop+number_logical_processors );
loop++;
}
util_thread_starter_run( tts );
for( loop = 0 ; loop < number_logical_processors * 2 ; loop++ )
test_pal_thread_wait( thread_handles[loop] );
util_thread_starter_delete( tts );
free( thread_handles );
LFDS700_MISC_BARRIER_LOAD;
vi.min_elements = vi.max_elements = number_elements * number_logical_processors * 2;
lfds700_freelist_query( &fs, LFDS700_FREELIST_QUERY_SINGLETHREADED_VALIDATE, (void *) &vi, (void *) &dvs );
lfds700_freelist_cleanup( &fs, NULL );
for( loop = 0 ; loop < number_logical_processors ; loop++ )
{
lfds700_freelist_cleanup( &(ts+loop)->fs_thread_local, NULL );
lfds700_freelist_cleanup( &(ts+loop+number_logical_processors)->fs_thread_local, NULL );
util_aligned_free( (ts+loop+number_logical_processors)->fs_thread_local_te_array );
}
util_aligned_free( ts );
util_aligned_free( te_array );
// TRD : print the test result
internal_display_test_result( 1, "freelist", dvs );
return;
}
/****************************************************************************/
static test_pal_thread_return_t TEST_PAL_CALLING_CONVENTION thread_popping_and_pushing_start_popping( void *util_thread_starter_thread_state )
{
lfds700_pal_uint_t
count;
struct lfds700_freelist_element
*fe;
struct lfds700_misc_prng_state
ps;
struct util_thread_starter_thread_state
*tsts;
struct test_state
*ts;
time_t
start_time;
LFDS700_MISC_MAKE_VALID_ON_CURRENT_LOGICAL_CORE_INITS_COMPLETED_BEFORE_NOW_ON_ANY_OTHER_LOGICAL_CORE;
assert( util_thread_starter_thread_state != NULL );
tsts = (struct util_thread_starter_thread_state *) util_thread_starter_thread_state;
ts = (struct test_state *) tsts->thread_user_state;
lfds700_misc_prng_init( &ps );
util_thread_starter_ready_and_wait( tsts );
start_time = time( NULL );
while( time(NULL) < start_time + TEST_DURATION_IN_SECONDS )
{
count = 0;
while( count < ts->number_elements )
if( lfds700_freelist_pop(ts->fs, &fe, &ps) )
{
// TRD : we do nothing with the test data, so there'ss no GET or SET here
lfds700_freelist_push( &ts->fs_thread_local, fe, &ps );
count++;
}
// TRD : return our local freelist to the main freelist
while( lfds700_freelist_pop(&ts->fs_thread_local, &fe, &ps) )
lfds700_freelist_push( ts->fs, fe, &ps );
}
LFDS700_MISC_BARRIER_STORE;
lfds700_misc_force_store();
return( (test_pal_thread_return_t) EXIT_SUCCESS );
}
/****************************************************************************/
static test_pal_thread_return_t TEST_PAL_CALLING_CONVENTION thread_popping_and_pushing_start_pushing( void *util_thread_starter_thread_state )
{
lfds700_pal_uint_t
count;
struct lfds700_freelist_element
*fe;
struct lfds700_misc_prng_state
ps;
struct test_state
*ts;
struct util_thread_starter_thread_state
*tsts;
time_t
start_time;
LFDS700_MISC_MAKE_VALID_ON_CURRENT_LOGICAL_CORE_INITS_COMPLETED_BEFORE_NOW_ON_ANY_OTHER_LOGICAL_CORE;
assert( util_thread_starter_thread_state != NULL );
tsts = (struct util_thread_starter_thread_state *) util_thread_starter_thread_state;
ts = (struct test_state *) tsts->thread_user_state;
lfds700_misc_prng_init( &ps );
util_thread_starter_ready_and_wait( tsts );
start_time = time( NULL );
while( time(NULL) < start_time + TEST_DURATION_IN_SECONDS )
{
// TRD : return our local freelist to the main freelist
while( lfds700_freelist_pop(&ts->fs_thread_local, &fe, &ps) )
lfds700_freelist_push( ts->fs, fe, &ps );
count = 0;
while( count < ts->number_elements )
if( lfds700_freelist_pop(ts->fs, &fe, &ps) )
{
lfds700_freelist_push( &ts->fs_thread_local, fe, &ps );
count++;
}
}
// TRD : now push whatever we have in our local freelist
while( lfds700_freelist_pop(&ts->fs_thread_local, &fe, &ps) )
lfds700_freelist_push( ts->fs, fe, &ps );
LFDS700_MISC_BARRIER_STORE;
lfds700_misc_force_store();
return( (test_pal_thread_return_t) EXIT_SUCCESS );
}
/***** includes *****/
#include "internal.h"
/***** structs *****/
struct test_state
{
lfds700_pal_uint_t
number_elements,
thread_number;
struct lfds700_freelist_state
*fs;
struct test_element
*te_array;
};
struct test_element
{
struct lfds700_freelist_element
fe;
lfds700_pal_uint_t
datum,
thread_number;
};
/***** private prototypes *****/
static test_pal_thread_return_t TEST_PAL_CALLING_CONVENTION thread_pushing( void *util_thread_starter_thread_state );
/****************************************************************************/
void test_lfds700_freelist_pushing( struct lfds700_list_asu_state *list_of_logical_processors, lfds700_pal_uint_t memory_in_megabytes )
{
enum lfds700_misc_validity
dvs = LFDS700_MISC_VALIDITY_VALID;
lfds700_pal_uint_t
loop,
number_elements,
number_logical_processors,
*per_thread_counters;
struct lfds700_list_asu_element
*lasue;
struct lfds700_freelist_element
*fe;
struct lfds700_freelist_state
fs;
struct lfds700_misc_prng_state
ps;
struct lfds700_misc_validation_info
vi;
struct test_pal_logical_processor
*lp;
struct util_thread_starter_state
*tts;
struct test_element
*te,
*first_te = NULL;
struct test_state
*ts;
test_pal_thread_state_t
*thread_handles;
assert( list_of_logical_processors != NULL );
// TRD : memory_in_megabytes can be any value in its range
/* TRD : we create an empty freelist
we then create one thread per CPU, where each thread
pushes 100,000 elements each as quickly as possible to the freelist
the data pushed is a counter and a thread ID
the threads exit when the freelist is full
we then validate the freelist;
checking that the counts increment on a per unique ID basis
and that the number of elements we pop equals 100,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" );
lfds700_list_asu_query( list_of_logical_processors, LFDS700_LIST_ASU_QUERY_GET_POTENTIALLY_INACCURATE_COUNT, NULL, (void **) &number_logical_processors );
lfds700_misc_prng_init( &ps );
number_elements = ( memory_in_megabytes * ONE_MEGABYTE_IN_BYTES ) / ( sizeof(struct test_element) * number_logical_processors );
// TRD : the main freelist
lfds700_freelist_init_valid_on_current_logical_core( &fs, NULL );
ts = util_malloc_wrapper( sizeof(struct test_state) * number_logical_processors );
for( loop = 0 ; loop < number_logical_processors ; loop++ )
{
(ts+loop)->fs = &fs;
(ts+loop)->thread_number = loop;
(ts+loop)->number_elements = number_elements;
}
thread_handles = util_malloc_wrapper( sizeof(test_pal_thread_state_t) * number_logical_processors );
util_thread_starter_new( &tts, number_logical_processors );
LFDS700_MISC_BARRIER_STORE;
lfds700_misc_force_store();
loop = 0;
lasue = NULL;
while( LFDS700_LIST_ASU_GET_START_AND_THEN_NEXT(*list_of_logical_processors, lasue) )
{
lp = LFDS700_LIST_ASU_GET_VALUE_FROM_ELEMENT( *lasue );
util_thread_starter_start( tts, &thread_handles[loop], loop, lp, thread_pushing, ts+loop );
loop++;
}
util_thread_starter_run( tts );
for( loop = 0 ; loop < number_logical_processors ; loop++ )
test_pal_thread_wait( thread_handles[loop] );
util_thread_starter_delete( tts );
free( thread_handles );
LFDS700_MISC_BARRIER_LOAD;
per_thread_counters = util_malloc_wrapper( sizeof(lfds700_pal_uint_t) * number_logical_processors );
for( loop = 0 ; loop < number_logical_processors ; loop++ )
*(per_thread_counters+loop) = number_elements - 1;
vi.min_elements = vi.max_elements = number_elements * number_logical_processors;
lfds700_freelist_query( &fs, LFDS700_STACK_QUERY_SINGLETHREADED_VALIDATE, &vi, &dvs );
while( dvs == LFDS700_MISC_VALIDITY_VALID and lfds700_freelist_pop(&fs, &fe, &ps) )
{
te = LFDS700_FREELIST_GET_VALUE_FROM_ELEMENT( *fe );
if( first_te == NULL )
first_te = te;
if( te->thread_number >= number_logical_processors )
{
dvs = LFDS700_MISC_VALIDITY_INVALID_TEST_DATA;
break;
}
if( te->datum > per_thread_counters[te->thread_number] )
dvs = LFDS700_MISC_VALIDITY_INVALID_ADDITIONAL_ELEMENTS;
if( te->datum < per_thread_counters[te->thread_number] )
dvs = LFDS700_MISC_VALIDITY_INVALID_MISSING_ELEMENTS;
if( te->datum == per_thread_counters[te->thread_number] )
per_thread_counters[te->thread_number]--;
}
// TRD : clean up
for( loop = 0 ; loop < number_logical_processors ; loop++ )
util_aligned_free( (ts+loop)->te_array );
free( per_thread_counters );
free( ts );
lfds700_freelist_cleanup( &fs, NULL );
// TRD : print the test result
internal_display_test_result( 1, "freelist", dvs );
return;
}
/****************************************************************************/
static test_pal_thread_return_t TEST_PAL_CALLING_CONVENTION thread_pushing( void *util_thread_starter_thread_state )
{
lfds700_pal_uint_t
loop;
struct lfds700_misc_prng_state
ps;
struct test_state
*ts;
struct util_thread_starter_thread_state
*tsts;
LFDS700_MISC_BARRIER_LOAD;
assert( util_thread_starter_thread_state != NULL );
tsts = (struct util_thread_starter_thread_state *) util_thread_starter_thread_state;
ts = (struct test_state *) tsts->thread_user_state;
lfds700_misc_prng_init( &ps );
ts->te_array = util_aligned_malloc( sizeof(struct test_element) * ts->number_elements, LFDS700_PAL_ATOMIC_ISOLATION_IN_BYTES );
for( loop = 0 ; loop < ts->number_elements ; loop++ )
{
(ts->te_array+loop)->thread_number = ts->thread_number;
(ts->te_array+loop)->datum = loop;
}
util_thread_starter_ready_and_wait( tsts );
for( loop = 0 ; loop < ts->number_elements ; loop++ )
{
LFDS700_FREELIST_SET_VALUE_IN_ELEMENT( (ts->te_array+loop)->fe, ts->te_array+loop );
lfds700_freelist_push( ts->fs, &(ts->te_array+loop)->fe, &ps );
}
LFDS700_MISC_BARRIER_STORE;
lfds700_misc_force_store();
return( (test_pal_thread_return_t) EXIT_SUCCESS );
}
/***** includes *****/
#include "internal.h"
/***** structs *****/
struct test_state
{
struct lfds700_freelist_state
*fs;
};
struct test_element
{
struct lfds700_freelist_element
fe;
lfds700_pal_uint_t
datum;
};
/***** private prototypes *****/
static test_pal_thread_return_t TEST_PAL_CALLING_CONVENTION thread_rapid_popping_and_pushing( void *util_thread_starter_thread_state );
/****************************************************************************/
void test_lfds700_freelist_rapid_popping_and_pushing( struct lfds700_list_asu_state *list_of_logical_processors )
{
enum lfds700_misc_validity
dvs = LFDS700_MISC_VALIDITY_VALID;
lfds700_pal_uint_t
loop,
number_logical_processors;
struct lfds700_list_asu_element
*lasue;
struct lfds700_freelist_state
fs;
struct lfds700_misc_prng_state
ps;
struct lfds700_misc_validation_info
vi = { 0, 0 };
struct test_pal_logical_processor
*lp;
struct util_thread_starter_state
*tts;
struct test_element
*te_array;
struct test_state
*ts;
test_pal_thread_state_t
*thread_handles;
assert( list_of_logical_processors != NULL );
/* 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 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 freelist, checking for loops and ensuring the number of
elements is correct
*/
internal_display_test_name( "Rapid popping and pushing (10 seconds)" );
lfds700_list_asu_query( list_of_logical_processors, LFDS700_LIST_ASU_QUERY_GET_POTENTIALLY_INACCURATE_COUNT, NULL, (void **) &number_logical_processors );
lfds700_misc_prng_init( &ps );
lfds700_freelist_init_valid_on_current_logical_core( &fs, NULL );
ts = util_malloc_wrapper( sizeof(struct test_state) * number_logical_processors );
for( loop = 0 ; loop < number_logical_processors ; loop++ )
(ts+loop)->fs = &fs;
thread_handles = util_malloc_wrapper( sizeof(test_pal_thread_state_t) * number_logical_processors );
// TRD : we need one element per thread
te_array = util_aligned_malloc( sizeof(struct test_element) * number_logical_processors, LFDS700_PAL_ATOMIC_ISOLATION_IN_BYTES );
for( loop = 0 ; loop < number_logical_processors ; loop++ )
{
LFDS700_FREELIST_SET_VALUE_IN_ELEMENT( (te_array+loop)->fe, te_array+loop );
lfds700_freelist_push( &fs, &(te_array+loop)->fe, &ps );
}
util_thread_starter_new( &tts, number_logical_processors );
LFDS700_MISC_BARRIER_STORE;
lfds700_misc_force_store();
loop = 0;
lasue = NULL;
while( LFDS700_LIST_ASU_GET_START_AND_THEN_NEXT(*list_of_logical_processors, lasue) )
{
lp = LFDS700_LIST_ASU_GET_VALUE_FROM_ELEMENT( *lasue );
util_thread_starter_start( tts, &thread_handles[loop], loop, lp, thread_rapid_popping_and_pushing, ts+loop );
loop++;
}
util_thread_starter_run( tts );
for( loop = 0 ; loop < number_logical_processors ; loop++ )
test_pal_thread_wait( thread_handles[loop] );
util_thread_starter_delete( tts );
free( thread_handles );
LFDS700_MISC_BARRIER_LOAD;
vi.min_elements = vi.max_elements = number_logical_processors;
lfds700_freelist_query( &fs, LFDS700_STACK_QUERY_SINGLETHREADED_VALIDATE, &vi, &dvs );
lfds700_freelist_cleanup( &fs, NULL );
util_aligned_free( te_array );
free( ts );
// TRD : print the test result
internal_display_test_result( 1, "freelist", dvs );
return;
}
/****************************************************************************/
static test_pal_thread_return_t TEST_PAL_CALLING_CONVENTION thread_rapid_popping_and_pushing( void *util_thread_starter_thread_state )
{
lfds700_pal_uint_t
time_loop = 0;
struct lfds700_freelist_element
*fe;
struct lfds700_misc_prng_state
ps;
struct test_state
*ts;
struct util_thread_starter_thread_state
*tsts;
time_t
current_time,
start_time;
LFDS700_MISC_MAKE_VALID_ON_CURRENT_LOGICAL_CORE_INITS_COMPLETED_BEFORE_NOW_ON_ANY_OTHER_LOGICAL_CORE;
assert( util_thread_starter_thread_state != NULL );
tsts = (struct util_thread_starter_thread_state *) util_thread_starter_thread_state;
ts = (struct test_state *) tsts->thread_user_state;
lfds700_misc_prng_init( &ps );
util_thread_starter_ready_and_wait( tsts );
current_time = start_time = time( NULL );
while( current_time < start_time + TEST_DURATION_IN_SECONDS )
{
lfds700_freelist_pop( ts->fs, &fe, &ps );
lfds700_freelist_push( ts->fs, fe, &ps );
if( time_loop++ == TIME_LOOP_COUNT )
{
time_loop = 0;
time( &current_time );
}
}
LFDS700_MISC_BARRIER_STORE;
lfds700_misc_force_store();
return( (test_pal_thread_return_t) EXIT_SUCCESS );
}
/***** includes *****/
#include "internal.h"
/****************************************************************************/
#pragma warning( disable : 4127 ) // TRD : disables MSVC warning for condition expressions being const
void test_lfds700_hash_a( struct lfds700_list_asu_state *list_of_logical_processors, lfds700_pal_uint_t memory_in_megabytes )
{
assert( list_of_logical_processors != NULL );
// TRD : memory_in_megabytes can be any value in its range
if( LFDS700_MISC_ATOMIC_SUPPORT_CAS )
{
printf( "\n"
"Hash (add-only) Tests\n"
"=====================\n" );
test_lfds700_hash_a_alignment();
test_lfds700_hash_a_fail_and_overwrite_on_existing_key();
test_lfds700_hash_a_random_adds_fail_on_existing( list_of_logical_processors, memory_in_megabytes );
test_lfds700_hash_a_random_adds_overwrite_on_existing( list_of_logical_processors, memory_in_megabytes );
test_lfds700_hash_a_iterate();
}
return;
}
#pragma warning( default : 4127 )
/***** includes *****/
#include "internal.h"
/****************************************************************************/
#pragma warning( disable : 4127 ) // TRD : disables MSVC warning for condition expressions being const
void test_lfds700_hash_a_alignment()
{
enum lfds700_misc_validity
dvs = LFDS700_MISC_VALIDITY_VALID;
/* TRD : these are compile time checks
but we do them here because this is a test programme
and it should indicate issues to users when it is *run*,
not when it is compiled, because a compile error normally
indicates a problem with the code itself and so is misleading
*/
internal_display_test_name( "Alignment" );
// TRD : struct lfds700_hash_a_element
if( offsetof(struct lfds700_hash_a_element,value) % LFDS700_PAL_ATOMIC_ISOLATION_IN_BYTES != 0 )
dvs = LFDS700_MISC_VALIDITY_INVALID_TEST_DATA;
// TRD : print the test result
internal_display_test_result( 1, "freelist", dvs );
return;
}
#pragma warning( default : 4127 )
/***** includes *****/
#include "internal.h"
/***** structs *****/
struct test_element
{
struct lfds700_btree_au_element
baue;
lfds700_pal_uint_t
datum;
};
struct test_state
{
enum lfds700_misc_flag
error_flag;
struct lfds700_hash_a_state
*has;
struct test_element
*element_array;
};
/***** private prototypes *****/
static int key_compare_function( void const *new_key, void const *existing_key );
static void key_hash_function( void const *key, lfds700_pal_uint_t *hash );
/****************************************************************************/
void test_lfds700_hash_a_iterate( void )
{
enum lfds700_misc_validity
dvs = LFDS700_MISC_VALIDITY_VALID;
lfds700_pal_uint_t
*counter_array,
loop;
struct lfds700_hash_a_element
*hae;
struct lfds700_hash_a_iterate
hai;
struct lfds700_hash_a_state
has;
struct lfds700_hash_a_element
*element_array;
struct lfds700_btree_au_state
*baus;
struct lfds700_misc_prng_state
ps;
void
*value;
/* TRD : single-threaded test
we create a single hash_a
we populate with 1000 elements
where key and value is the number of the element (e.g. 0 to 999)
we then allocate 1000 counters, init to 0
we then iterate
we increment each element as we see it in the iterate
if any are missing or seen more than once, problemo!
we do this once with a table of 10, to ensure each table has (or almost certainly has) something in
and then a second tiem with a table of 10000, to ensure some empty tables exist
*/
internal_display_test_name( "Iterate" );
lfds700_misc_prng_init( &ps );
element_array = util_aligned_malloc( sizeof(struct lfds700_hash_a_element) * 1000, LFDS700_PAL_ATOMIC_ISOLATION_IN_BYTES );
counter_array = util_malloc_wrapper( sizeof(lfds700_pal_uint_t) * 1000 );
// TRD : first time around
baus = util_aligned_malloc( sizeof(struct lfds700_btree_au_state) * 10, LFDS700_PAL_ATOMIC_ISOLATION_IN_BYTES );
lfds700_hash_a_init_valid_on_current_logical_core( &has, baus, 10, key_compare_function, key_hash_function, LFDS700_HASH_A_EXISTING_KEY_FAIL, NULL );
for( loop = 0 ; loop < 1000 ; loop++ )
{
LFDS700_HASH_A_SET_KEY_IN_ELEMENT( *(element_array+loop), loop );
LFDS700_HASH_A_SET_VALUE_IN_ELEMENT( *(element_array+loop), loop );
lfds700_hash_a_insert( &has, element_array+loop, NULL, &ps );
}
for( loop = 0 ; loop < 1000 ; loop++ )
*(counter_array+loop) = 0;
lfds700_hash_a_iterate_init( &has, &hai );
while( dvs == LFDS700_MISC_VALIDITY_VALID and lfds700_hash_a_iterate(&hai, &hae) )
{
value = LFDS700_HASH_A_GET_VALUE_FROM_ELEMENT( *hae );
( *(counter_array + (lfds700_pal_uint_t) value) )++;
}
if( dvs == LFDS700_MISC_VALIDITY_VALID )
for( loop = 0 ; loop < 1000 ; loop++ )
{
if( *(counter_array+loop) > 1 )
dvs = LFDS700_MISC_VALIDITY_INVALID_ADDITIONAL_ELEMENTS;
if( *(counter_array+loop) == 0 )
dvs = LFDS700_MISC_VALIDITY_INVALID_MISSING_ELEMENTS;
}
lfds700_hash_a_cleanup( &has, NULL );
util_aligned_free( baus );
// TRD : second time around
if( dvs == LFDS700_MISC_VALIDITY_VALID )
{
baus = util_aligned_malloc( sizeof(struct lfds700_btree_au_state) * 10000, LFDS700_PAL_ATOMIC_ISOLATION_IN_BYTES );
lfds700_hash_a_init_valid_on_current_logical_core( &has, baus, 10000, key_compare_function, key_hash_function, LFDS700_HASH_A_EXISTING_KEY_FAIL, NULL );
for( loop = 0 ; loop < 1000 ; loop++ )
{
LFDS700_HASH_A_SET_KEY_IN_ELEMENT( *(element_array+loop), loop );
LFDS700_HASH_A_SET_VALUE_IN_ELEMENT( *(element_array+loop), loop );
lfds700_hash_a_insert( &has, element_array+loop, NULL, &ps );
}
for( loop = 0 ; loop < 1000 ; loop++ )
*(counter_array+loop) = 0;
lfds700_hash_a_iterate_init( &has, &hai );
while( dvs == LFDS700_MISC_VALIDITY_VALID and lfds700_hash_a_iterate(&hai, &hae) )
{
value = LFDS700_HASH_A_GET_VALUE_FROM_ELEMENT( *hae );
( *(counter_array + (lfds700_pal_uint_t) value ) )++;
}
if( dvs == LFDS700_MISC_VALIDITY_VALID )
for( loop = 0 ; loop < 1000 ; loop++ )
{
if( *(counter_array+loop) > 1 )
dvs = LFDS700_MISC_VALIDITY_INVALID_ADDITIONAL_ELEMENTS;
if( *(counter_array+loop) == 0 )
dvs = LFDS700_MISC_VALIDITY_INVALID_MISSING_ELEMENTS;
}
lfds700_hash_a_cleanup( &has, NULL );
util_aligned_free( baus );
}
// TRD : cleanup
util_aligned_free( element_array );
free( counter_array );
// TRD : print the test result
internal_display_test_result( 1, "hash_a", dvs );
return;
}
/****************************************************************************/
#pragma warning( disable : 4100 )
static int key_compare_function( void const *new_key, void const *existing_key )
{
int
cr = 0;
// TRD : new_key can be NULL (i.e. 0)
// TRD : existing_key can be NULL (i.e. 0)
if( (lfds700_pal_uint_t) new_key < (lfds700_pal_uint_t) existing_key )
cr = -1;
if( (lfds700_pal_uint_t) new_key > (lfds700_pal_uint_t) existing_key )
cr = 1;
return( cr );
}
#pragma warning( default : 4100 )
/****************************************************************************/
#pragma warning( disable : 4100 )
static void key_hash_function( void const *key, lfds700_pal_uint_t *hash )
{
// TRD : key can be NULL
assert( hash != NULL );
*hash = 0;
/* TRD : this function iterates over the user data
and we are using the void pointer AS user data
so here we need to pass in the addy of value
*/
LFDS700_HASH_A_32BIT_HASH_FUNCTION( (void *) &key, sizeof(lfds700_pal_uint_t), *hash );
return;
}
#pragma warning( default : 4100 )
/***** includes *****/
#include "internal.h"
/***** structs *****/
struct test_element
{
struct lfds700_hash_a_element
hae;
lfds700_pal_uint_t
datum,
key;
};
struct test_state
{
enum flag
error_flag;
lfds700_pal_uint_t
number_elements_per_thread;
struct lfds700_hash_a_state
*has;
struct test_element
*element_array;
};
/***** private prototypes *****/
static test_pal_thread_return_t TEST_PAL_CALLING_CONVENTION thread_adding( void *util_thread_starter_thread_state );
static int key_compare_function( void const *new_key, void const *existing_key );
static void key_hash_function( void const *key, lfds700_pal_uint_t *hash );
/****************************************************************************/
void test_lfds700_hash_a_random_adds_fail_on_existing( struct lfds700_list_asu_state *list_of_logical_processors, lfds700_pal_uint_t memory_in_megabytes )
{
enum lfds700_misc_validity
dvs = LFDS700_MISC_VALIDITY_VALID;
lfds700_pal_uint_t
loop,
number_elements_per_thread,
number_elements_total,
number_logical_processors,
offset,
temp,
value;
struct lfds700_hash_a_element
*hae;
struct lfds700_hash_a_state
has;
struct lfds700_list_asu_element
*lasue = NULL;
struct lfds700_btree_au_state
*baus;
struct lfds700_misc_prng_state
ps;
struct lfds700_misc_validation_info
vi;
struct test_pal_logical_processor
*lp;
struct util_thread_starter_state
*tts;
struct test_element
*element_array;
struct test_state
*ts;
test_pal_thread_state_t
*thread_handles;
assert( list_of_logical_processors != NULL );
// TRD : memory_in_megabytes can be any value in its range
/* TRD : we create a single hash_a
we generate 100k elements per thread (with one thread per logical processor) in an array
each element is unique
we randomly sort the elements
then each thread loops, adds those elements into the hash_a
we check that each datum inserts okay - failure will occur on non-unique data, i.e. two identical keys
we should have no failures
we then call the hash_a validation function
then using the hash_a get() we check all the elements we added are present
*/
internal_display_test_name( "Random adds and get (fail on existing key)" );
lfds700_misc_prng_init( &ps );
lfds700_list_asu_query( list_of_logical_processors, LFDS700_LIST_ASU_QUERY_GET_POTENTIALLY_INACCURATE_COUNT, NULL, (void **) &number_logical_processors );
baus = util_aligned_malloc( sizeof(struct lfds700_btree_au_state) * 1000, LFDS700_PAL_ATOMIC_ISOLATION_IN_BYTES );
lfds700_hash_a_init_valid_on_current_logical_core( &has, baus, 1000, key_compare_function, key_hash_function, LFDS700_HASH_A_EXISTING_KEY_FAIL, NULL );
number_elements_per_thread = ( memory_in_megabytes * ONE_MEGABYTE_IN_BYTES ) / ( sizeof(struct test_element) * number_logical_processors );
number_elements_total = number_elements_per_thread * number_logical_processors;
// TRD : created an ordered list of unique numbers
element_array = util_aligned_malloc( sizeof(struct test_element) * number_elements_total, LFDS700_PAL_ATOMIC_ISOLATION_IN_BYTES );
for( loop = 0 ; loop < number_elements_total ; loop++ )
{
(element_array+loop)->key = loop;
// TRD : + number_elements just to make it different to the key
(element_array+loop)->datum = loop + number_elements_total;
}
for( loop = 0 ; loop < number_elements_total ; loop++ )
{
offset = LFDS700_MISC_PRNG_GENERATE( &ps );
offset %= number_elements_total;
temp = (element_array + offset)->key;
(element_array + offset)->key = (element_array + loop)->key;
(element_array + loop)->key = temp;
}
ts = util_malloc_wrapper( sizeof(struct test_state) * number_logical_processors );
for( loop = 0 ; loop < number_logical_processors ; loop++ )
{
(ts+loop)->has = &has;
(ts+loop)->element_array = element_array + number_elements_per_thread*loop;
(ts+loop)->error_flag = LOWERED;
(ts+loop)->number_elements_per_thread = number_elements_per_thread;
}
thread_handles = util_malloc_wrapper( sizeof(test_pal_thread_state_t) * number_logical_processors );
util_thread_starter_new( &tts, number_logical_processors );
LFDS700_MISC_BARRIER_STORE;
lfds700_misc_force_store();
loop = 0;
while( LFDS700_LIST_ASU_GET_START_AND_THEN_NEXT(*list_of_logical_processors, lasue) )
{
lp = LFDS700_LIST_ASU_GET_VALUE_FROM_ELEMENT( *lasue );
util_thread_starter_start( tts, &thread_handles[loop], loop, lp, thread_adding, ts+loop );
loop++;
}
util_thread_starter_run( tts );
for( loop = 0 ; loop < number_logical_processors ; loop++ )
test_pal_thread_wait( thread_handles[loop] );
util_thread_starter_delete( tts );
free( thread_handles );
LFDS700_MISC_BARRIER_LOAD;
// TRD : now for validation
vi.min_elements = vi.max_elements = number_elements_total;
lfds700_hash_a_query( &has, LFDS700_HASH_A_QUERY_SINGLETHREADED_VALIDATE, (void *) &vi, (void *) &dvs );
/* TRD : now we attempt to lfds700_hash_a_get_by_key() for every element in number_array
any failure to find is an error
we also check we've obtained the correct element
*/
for( loop = 0 ; dvs == LFDS700_MISC_VALIDITY_VALID and loop < number_elements_total ; loop++ )
if( 0 == lfds700_hash_a_get_by_key(&has, (void *) (ts->element_array+loop)->key, &hae) )
dvs = LFDS700_MISC_VALIDITY_INVALID_MISSING_ELEMENTS;
else
{
value = (lfds700_pal_uint_t) LFDS700_HASH_A_GET_VALUE_FROM_ELEMENT( *hae );
if( (ts->element_array+loop)->datum != value )
dvs = LFDS700_MISC_VALIDITY_INVALID_TEST_DATA;
}
// TRD : just check error_flags weren't raised
if( dvs == LFDS700_MISC_VALIDITY_VALID )
for( loop = 0 ; loop < number_logical_processors ; loop++ )
if( (ts+loop)->error_flag == RAISED )
dvs = LFDS700_MISC_VALIDITY_INVALID_TEST_DATA;
// TRD : cleanup
lfds700_hash_a_cleanup( &has, NULL );
util_aligned_free( baus );
free( ts );
util_aligned_free( element_array );
// TRD : print the test result
internal_display_test_result( 1, "hash_a", dvs );
return;
}
/****************************************************************************/
static test_pal_thread_return_t TEST_PAL_CALLING_CONVENTION thread_adding( void *util_thread_starter_thread_state )
{
enum lfds700_hash_a_insert_result
apr;
lfds700_pal_uint_t
index = 0;
struct test_state
*ts;
struct lfds700_misc_prng_state
ps;
struct util_thread_starter_thread_state
*tsts;
LFDS700_MISC_MAKE_VALID_ON_CURRENT_LOGICAL_CORE_INITS_COMPLETED_BEFORE_NOW_ON_ANY_OTHER_LOGICAL_CORE;
assert( util_thread_starter_thread_state != NULL );
tsts = (struct util_thread_starter_thread_state *) util_thread_starter_thread_state;
ts = (struct test_state *) tsts->thread_user_state;
lfds700_misc_prng_init( &ps );
util_thread_starter_ready_and_wait( tsts );
while( index < ts->number_elements_per_thread )
{
LFDS700_HASH_A_SET_KEY_IN_ELEMENT( (ts->element_array+index)->hae, (ts->element_array+index)->key );
LFDS700_HASH_A_SET_VALUE_IN_ELEMENT( (ts->element_array+index)->hae, (ts->element_array+index)->datum );
apr = lfds700_hash_a_insert( ts->has, &(ts->element_array+index)->hae, NULL, &ps );
if( apr == LFDS700_HASH_A_PUT_RESULT_FAILURE_EXISTING_KEY )
ts->error_flag = RAISED;
index++;
}
LFDS700_MISC_BARRIER_STORE;
lfds700_misc_force_store();
return( (test_pal_thread_return_t) EXIT_SUCCESS );
}
/****************************************************************************/
#pragma warning( disable : 4100 )
static int key_compare_function( void const *new_key, void const *existing_key )
{
int
cr = 0;
// TRD : new_key can be NULL (i.e. 0)
// TRD : existing_key can be NULL (i.e. 0)
if( (lfds700_pal_uint_t) new_key < (lfds700_pal_uint_t) existing_key )
cr = -1;
if( (lfds700_pal_uint_t) new_key > (lfds700_pal_uint_t) existing_key )
cr = 1;
return( cr );
}
#pragma warning( default : 4100 )
/****************************************************************************/
#pragma warning( disable : 4100 )
static void key_hash_function( void const *key, lfds700_pal_uint_t *hash )
{
// TRD : key can be NULL
assert( hash != NULL );
*hash = 0;
/* TRD : this function iterates over the user data
and we are using the void pointer *as* key data
so here we need to pass in the addy of key
*/
LFDS700_HASH_A_32BIT_HASH_FUNCTION( (void *) &key, sizeof(lfds700_pal_uint_t), *hash );
return;
}
#pragma warning( default : 4100 )
/***** includes *****/
#include "internal.h"
/***** private prototypes *****/
static int key_compare_function( void const *new_value, void const *value_in_tree );
static void key_hash_function( void const *key, lfds700_pal_uint_t *hash );
/****************************************************************************/
void test_lfds700_hash_a_fail_and_overwrite_on_existing_key()
{
enum lfds700_hash_a_insert_result
apr;
enum lfds700_misc_validity
dvs = LFDS700_MISC_VALIDITY_VALID;
struct lfds700_hash_a_element
hae_one,
hae_two;
struct lfds700_hash_a_state
has;
struct lfds700_btree_au_state
*baus;
struct lfds700_misc_prng_state
ps;
internal_display_test_name( "Fail and overwrite on existing key" );
lfds700_misc_prng_init( &ps );
baus = util_aligned_malloc( sizeof(struct lfds700_btree_au_state) * 10, LFDS700_PAL_ATOMIC_ISOLATION_IN_BYTES );
// TRD : fail on overwrite
lfds700_hash_a_init_valid_on_current_logical_core( &has, baus, 10, key_compare_function, key_hash_function, LFDS700_HASH_A_EXISTING_KEY_FAIL, NULL );
LFDS700_HASH_A_SET_KEY_IN_ELEMENT( hae_one, 1 );
LFDS700_HASH_A_SET_VALUE_IN_ELEMENT( hae_one, 0 );
apr = lfds700_hash_a_insert( &has, &hae_one, NULL, &ps );
if( apr != LFDS700_HASH_A_PUT_RESULT_SUCCESS )
dvs = LFDS700_MISC_VALIDITY_INVALID_TEST_DATA;
LFDS700_HASH_A_SET_KEY_IN_ELEMENT( hae_two, 1 );
LFDS700_HASH_A_SET_VALUE_IN_ELEMENT( hae_two, 1 );
apr = lfds700_hash_a_insert( &has, &hae_two, NULL, &ps );
if( apr != LFDS700_HASH_A_PUT_RESULT_FAILURE_EXISTING_KEY )
dvs = LFDS700_MISC_VALIDITY_INVALID_TEST_DATA;
lfds700_hash_a_cleanup( &has, NULL );
// TRD : success on overwrite
lfds700_hash_a_init_valid_on_current_logical_core( &has, baus, 10, key_compare_function, key_hash_function, LFDS700_HASH_A_EXISTING_KEY_OVERWRITE, NULL );
LFDS700_HASH_A_SET_KEY_IN_ELEMENT( hae_one, 1 );
LFDS700_HASH_A_SET_VALUE_IN_ELEMENT( hae_one, 1 );
apr = lfds700_hash_a_insert( &has, &hae_one, NULL, &ps );
if( apr != LFDS700_HASH_A_PUT_RESULT_SUCCESS )
dvs = LFDS700_MISC_VALIDITY_INVALID_TEST_DATA;
LFDS700_HASH_A_SET_KEY_IN_ELEMENT( hae_two, 1 );
LFDS700_HASH_A_SET_VALUE_IN_ELEMENT( hae_two, 1 );
apr = lfds700_hash_a_insert( &has, &hae_two, NULL, &ps );
if( apr != LFDS700_HASH_A_PUT_RESULT_SUCCESS_OVERWRITE )
dvs = LFDS700_MISC_VALIDITY_INVALID_TEST_DATA;
lfds700_hash_a_cleanup( &has, NULL );
util_aligned_free( baus );
// TRD : print the test result
internal_display_test_result( 1, "hash_a", dvs );
return;
}
/****************************************************************************/
#pragma warning( disable : 4100 )
static int key_compare_function( void const *new_key, void const *key_in_tree )
{
int
cr = 0;
// TRD : key_new can be any value in its range
// TRD : key_in_tree can be any value in its range
if( (lfds700_pal_uint_t) new_key < (lfds700_pal_uint_t) key_in_tree )
cr = -1;
if( (lfds700_pal_uint_t) new_key > (lfds700_pal_uint_t) key_in_tree )
cr = 1;
return( cr );
}
#pragma warning( default : 4100 )
/****************************************************************************/
#pragma warning( disable : 4100 )
static void key_hash_function( void const *key, lfds700_pal_uint_t *hash )
{
// TRD : key can be NULL
assert( hash != NULL );
*hash = 0;
/* TRD : this function iterates over the user data
and we are using the void pointer *as* key data
so here we need to pass in the addy of key
*/
LFDS700_HASH_A_32BIT_HASH_FUNCTION( (void *) &key, sizeof(lfds700_pal_uint_t), *hash );
return;
}
#pragma warning( default : 4100 )
/***** includes *****/
#include "internal.h"
/***** structs *****/
struct test_element
{
struct lfds700_hash_a_element
hae;
lfds700_pal_uint_t
key;
};
struct test_state
{
lfds700_pal_uint_t
number_elements_per_thread,
overwrite_count;
struct lfds700_hash_a_state
*has;
struct test_element
*element_array;
};
/***** private prototypes *****/
static test_pal_thread_return_t TEST_PAL_CALLING_CONVENTION thread_adding( void *util_thread_starter_thread_state );
static int key_compare_function( void const *new_key, void const *existing_key );
static void key_hash_function( void const *key, lfds700_pal_uint_t *hash );
static int qsort_and_bsearch_key_compare_function( void const *e1, void const *e2 );
/****************************************************************************/
void test_lfds700_hash_a_random_adds_overwrite_on_existing( struct lfds700_list_asu_state *list_of_logical_processors, lfds700_pal_uint_t memory_in_megabytes )
{
enum lfds700_misc_validity
dvs = LFDS700_MISC_VALIDITY_VALID;
int
rv;
lfds700_pal_uint_t
actual_sum_overwrite_existing_count,
expected_sum_overwrite_existing_count,
*key_count_array,
loop,
number_elements_per_thread,
number_elements_total,
number_logical_processors,
random_value;
struct lfds700_hash_a_iterate
hai;
struct lfds700_hash_a_element
*hae;
struct lfds700_hash_a_state
has;
struct lfds700_list_asu_element
*lasue = NULL;
struct lfds700_btree_au_state
*baus;
struct lfds700_misc_prng_state
ps;
struct lfds700_misc_validation_info
vi;
struct test_pal_logical_processor
*lp;
struct util_thread_starter_state
*tts;
struct test_element
*element_array;
struct test_state
*ts;
test_pal_thread_state_t
*thread_handles;
void
*key_pointer,
*key;
assert( list_of_logical_processors != NULL );
// TRD : memory_in_megabytes can be any value in its range
/* TRD : we create a single hash_a
we generate n elements per thread
each element contains a key value, which is set to a random value
(we don't use value, so it's just set to 0)
the threads then run, putting
the threads count their number of overwrite hits
once the threads are done, then we
count the number of each key
from this we figure out the min/max element for hash_a validation, so we call validation
we check the sum of overwrites for each thread is what it should be
then using the hash_a get() we check all the elements we expect are present
and then we iterate over the hash_a
checking we see each key once
*/
internal_display_test_name( "Random adds, get and iterate (overwrite on existing key)" );
lfds700_misc_prng_init( &ps );
lfds700_list_asu_query( list_of_logical_processors, LFDS700_LIST_ASU_QUERY_GET_POTENTIALLY_INACCURATE_COUNT, NULL, (void **) &number_logical_processors );
baus = util_aligned_malloc( sizeof(struct lfds700_btree_au_state) * 1000, LFDS700_PAL_ATOMIC_ISOLATION_IN_BYTES );
lfds700_hash_a_init_valid_on_current_logical_core( &has, baus, 1000, key_compare_function, key_hash_function, LFDS700_HASH_A_EXISTING_KEY_OVERWRITE, NULL );
// TRD : we divide by 2 beccause we have to allocate a second array of this size later
number_elements_per_thread = ( memory_in_megabytes * ONE_MEGABYTE_IN_BYTES ) / ( sizeof(struct test_element) * number_logical_processors ) / 2;
number_elements_total = number_elements_per_thread * number_logical_processors;
// TRD : created an ordered list of unique numbers
element_array = util_aligned_malloc( sizeof(struct test_element) * number_elements_total, LFDS700_PAL_ATOMIC_ISOLATION_IN_BYTES );
for( loop = 0 ; loop < number_elements_total ; loop++ )
{
random_value = LFDS700_MISC_PRNG_GENERATE( &ps );
(element_array+loop)->key = (lfds700_pal_uint_t) floor( (number_elements_total/2) * ((double) random_value / (double) LFDS700_MISC_PRNG_MAX) );
}
ts = util_malloc_wrapper( sizeof(struct test_state) * number_logical_processors );
for( loop = 0 ; loop < number_logical_processors ; loop++ )
{
(ts+loop)->has = &has;
(ts+loop)->element_array = element_array + number_elements_per_thread*loop;
(ts+loop)->overwrite_count = 0;
(ts+loop)->number_elements_per_thread = number_elements_per_thread;
}
thread_handles = util_malloc_wrapper( sizeof(test_pal_thread_state_t) * number_logical_processors );
util_thread_starter_new( &tts, number_logical_processors );
LFDS700_MISC_BARRIER_STORE;
lfds700_misc_force_store();
loop = 0;
while( LFDS700_LIST_ASU_GET_START_AND_THEN_NEXT(*list_of_logical_processors, lasue) )
{
lp = LFDS700_LIST_ASU_GET_VALUE_FROM_ELEMENT( *lasue );
util_thread_starter_start( tts, &thread_handles[loop], loop, lp, thread_adding, ts+loop );
loop++;
}
util_thread_starter_run( tts );
for( loop = 0 ; loop < number_logical_processors ; loop++ )
test_pal_thread_wait( thread_handles[loop] );
util_thread_starter_delete( tts );
free( thread_handles );
LFDS700_MISC_BARRIER_LOAD;
// TRD : now for validation
key_count_array = util_malloc_wrapper( sizeof(lfds700_pal_uint_t) * number_elements_total );
for( loop = 0 ; loop < number_elements_total ; loop++ )
*(key_count_array+loop) = 0;
for( loop = 0 ; loop < number_elements_total ; loop++ )
( *(key_count_array + (element_array+loop)->key) )++;
vi.min_elements = number_elements_total;
for( loop = 0 ; loop < number_elements_total ; loop++ )
if( *(key_count_array+loop) == 0 )
vi.min_elements--;
vi.max_elements = vi.min_elements;
lfds700_hash_a_query( &has, LFDS700_HASH_A_QUERY_SINGLETHREADED_VALIDATE, (void *) &vi, (void *) &dvs );
expected_sum_overwrite_existing_count = 0;
for( loop = 0 ; loop < number_elements_total ; loop++ )
if( *(key_count_array+loop) != 0 )
expected_sum_overwrite_existing_count += *(key_count_array+loop) - 1;
actual_sum_overwrite_existing_count = 0;
for( loop = 0 ; loop < number_logical_processors ; loop++ )
actual_sum_overwrite_existing_count += (ts+loop)->overwrite_count;
if( expected_sum_overwrite_existing_count != actual_sum_overwrite_existing_count )
dvs = LFDS700_MISC_VALIDITY_INVALID_TEST_DATA;
// TRD : now loop over the expected array and check we can get() every element
for( loop = 0 ; loop < number_elements_total ; loop++ )
if( *(key_count_array+loop) > 0 )
{
rv = lfds700_hash_a_get_by_key( &has, (void *) loop, &hae );
if( rv != 1 )
dvs = LFDS700_MISC_VALIDITY_INVALID_TEST_DATA;
}
/* TRD : now iterate, checking we find every element and no others
to do this in a timely manner, we need to qsort() the key values
and use bsearch() to check for items in the array
*/
for( loop = 0 ; loop < number_elements_total ; loop++ )
if( *(key_count_array+loop) != 0 )
*(key_count_array+loop) = loop;
else
*(key_count_array+loop) = 0;
qsort( key_count_array, number_elements_total, sizeof(lfds700_pal_uint_t), qsort_and_bsearch_key_compare_function );
lfds700_hash_a_iterate_init( &has, &hai );
while( dvs == LFDS700_MISC_VALIDITY_VALID and lfds700_hash_a_iterate(&hai, &hae) )
{
key = LFDS700_HASH_A_GET_KEY_FROM_ELEMENT( *hae );
key_pointer = bsearch( &key, key_count_array, number_elements_total, sizeof(lfds700_pal_uint_t), qsort_and_bsearch_key_compare_function );
if( key_pointer == NULL )
dvs = LFDS700_MISC_VALIDITY_INVALID_TEST_DATA;
}
// TRD : cleanup
lfds700_hash_a_cleanup( &has, NULL );
util_aligned_free( baus );
free( ts );
util_aligned_free( element_array );
free( key_count_array );
// TRD : print the test result
internal_display_test_result( 1, "hash_a", dvs );
return;
}
/****************************************************************************/
static test_pal_thread_return_t TEST_PAL_CALLING_CONVENTION thread_adding( void *util_thread_starter_thread_state )
{
enum lfds700_hash_a_insert_result
apr;
lfds700_pal_uint_t
index = 0;
struct test_state
*ts;
struct lfds700_misc_prng_state
ps;
struct util_thread_starter_thread_state
*tsts;
LFDS700_MISC_MAKE_VALID_ON_CURRENT_LOGICAL_CORE_INITS_COMPLETED_BEFORE_NOW_ON_ANY_OTHER_LOGICAL_CORE;
assert( util_thread_starter_thread_state != NULL );
tsts = (struct util_thread_starter_thread_state *) util_thread_starter_thread_state;
ts = (struct test_state *) tsts->thread_user_state;
lfds700_misc_prng_init( &ps );
util_thread_starter_ready_and_wait( tsts );
while( index < ts->number_elements_per_thread )
{
LFDS700_HASH_A_SET_KEY_IN_ELEMENT( (ts->element_array+index)->hae, (ts->element_array+index)->key );
LFDS700_HASH_A_SET_VALUE_IN_ELEMENT( (ts->element_array+index)->hae, 0 );
apr = lfds700_hash_a_insert( ts->has, &(ts->element_array+index)->hae, NULL, &ps );
if( apr == LFDS700_HASH_A_PUT_RESULT_SUCCESS_OVERWRITE )
ts->overwrite_count++;
index++;
}
LFDS700_MISC_BARRIER_STORE;
lfds700_misc_force_store();
return( (test_pal_thread_return_t) EXIT_SUCCESS );
}
/****************************************************************************/
#pragma warning( disable : 4100 )
static int key_compare_function( void const *new_key, void const *existing_key )
{
int
cr = 0;
// TRD : new_key can be NULL (i.e. 0)
// TRD : existing_key can be NULL (i.e. 0)
if( (lfds700_pal_uint_t) new_key < (lfds700_pal_uint_t) existing_key )
cr = -1;
if( (lfds700_pal_uint_t) new_key > (lfds700_pal_uint_t) existing_key )
cr = 1;
return( cr );
}
#pragma warning( default : 4100 )
/****************************************************************************/
#pragma warning( disable : 4100 )
static void key_hash_function( void const *key, lfds700_pal_uint_t *hash )
{
// TRD : key can be NULL
assert( hash != NULL );
*hash = 0;
/* TRD : this function iterates over the user data
and we are using the void pointer *as* key data
so here we need to pass in the addy of key
*/
LFDS700_HASH_A_32BIT_HASH_FUNCTION( (void *) &key, sizeof(lfds700_pal_uint_t), *hash );
return;
}
#pragma warning( default : 4100 )
/****************************************************************************/
static int qsort_and_bsearch_key_compare_function( void const *e1, void const *e2 )
{
int
cr = 0;
lfds700_pal_uint_t
s1,
s2;
s1 = *(lfds700_pal_uint_t *) e1;
s2 = *(lfds700_pal_uint_t *) e2;
if( s1 > s2 )
cr = 1;
if( s1 < s2 )
cr = -1;
return( cr );
}
/***** includes *****/
#include "internal.h"
/****************************************************************************/
#pragma warning( disable : 4127 ) // TRD : disables MSVC warning for condition expressions being const
void test_lfds700_list_aos( struct lfds700_list_asu_state *list_of_logical_processors, lfds700_pal_uint_t memory_in_megabytes )
{
assert( list_of_logical_processors != NULL );
// TRD : memory_in_megabytes can be any value in its range
if( LFDS700_MISC_ATOMIC_SUPPORT_CAS )
{
printf( "\n"
"List (add-only, ordered, singly-linked) Tests\n"
"=============================================\n" );
test_lfds700_list_aos_alignment();
test_lfds700_list_aos_new_ordered( list_of_logical_processors, memory_in_megabytes );
test_lfds700_list_aos_new_ordered_with_cursor( list_of_logical_processors, memory_in_megabytes );
}
return;
}
#pragma warning( default : 4127 )
/***** includes *****/
#include "internal.h"
/****************************************************************************/
#pragma warning( disable : 4127 ) // TRD : disables MSVC warning for condition expressions being const
void test_lfds700_list_aos_alignment()
{
enum lfds700_misc_validity
dvs = LFDS700_MISC_VALIDITY_VALID;
/* TRD : these are compile time checks
but we do them here because this is a test programme
and it should indicate issues to users when it is *run*,
not when it is compiled, because a compile error normally
indicates a problem with the code itself and so is misleading
*/
internal_display_test_name( "Alignment" );
// TRD : struct lfds700_list_aos_element
if( offsetof(struct lfds700_list_aos_element,next) % LFDS700_PAL_ATOMIC_ISOLATION_IN_BYTES != 0 )
dvs = LFDS700_MISC_VALIDITY_INVALID_TEST_DATA;
if( offsetof(struct lfds700_list_aos_element,value) % LFDS700_PAL_ATOMIC_ISOLATION_IN_BYTES != 0 )
dvs = LFDS700_MISC_VALIDITY_INVALID_TEST_DATA;
if( offsetof(struct lfds700_list_aos_element,key) % LFDS700_PAL_ATOMIC_ISOLATION_IN_BYTES != 0 )
dvs = LFDS700_MISC_VALIDITY_INVALID_TEST_DATA;
// TRD : struct lfds700_list_asu_state
if( offsetof(struct lfds700_list_aos_state,start) % LFDS700_PAL_ATOMIC_ISOLATION_IN_BYTES != 0 )
dvs = LFDS700_MISC_VALIDITY_INVALID_TEST_DATA;
if( offsetof(struct lfds700_list_aos_state,dummy_element) % LFDS700_PAL_ATOMIC_ISOLATION_IN_BYTES != 0 )
dvs = LFDS700_MISC_VALIDITY_INVALID_TEST_DATA;
if( offsetof(struct lfds700_list_aos_state,key_compare_function) % LFDS700_PAL_ATOMIC_ISOLATION_IN_BYTES != 0 )
dvs = LFDS700_MISC_VALIDITY_INVALID_TEST_DATA;
// TRD : print the test result
internal_display_test_result( 1, "list_aos", dvs );
return;
}
#pragma warning( default : 4127 )
/***** includes *****/
#include "internal.h"
/***** structs *****/
struct test_element
{
struct lfds700_list_aos_element
laose;
lfds700_pal_uint_t
element_number,
thread_number;
};
struct test_state
{
lfds700_pal_uint_t
number_elements_per_thread;
struct lfds700_list_aos_state
*laoss;
struct test_element
*element_array;
};
/***** private prototypes *****/
static int new_ordered_compare_function( void const *value_new, void const *value_in_list );
static test_pal_thread_return_t TEST_PAL_CALLING_CONVENTION new_ordered_thread( void *util_thread_starter_thread_state );
/****************************************************************************/
void test_lfds700_list_aos_new_ordered( struct lfds700_list_asu_state *list_of_logical_processors, lfds700_pal_uint_t memory_in_megabytes )
{
enum lfds700_misc_validity
dvs = LFDS700_MISC_VALIDITY_VALID;
lfds700_pal_uint_t
loop,
expected_element_number,
number_elements_per_thread,
number_elements_total,
number_logical_processors,
offset,
temp;
struct lfds700_list_aos_element
*laose = NULL;
struct lfds700_list_asu_element
*lasue = NULL;
struct lfds700_list_aos_state
laoss;
struct lfds700_misc_prng_state
ps;
struct lfds700_misc_validation_info
vi;
struct test_pal_logical_processor
*lp;
struct test_element
*element_array,
*element;
struct test_state
*ts;
struct util_thread_starter_state
*tts;
test_pal_thread_state_t
*thread_handles;
assert( list_of_logical_processors != NULL );
// TRD : memory_in_megabytes can be any value in its range
/* TRD : run one thread per logical processor
we have a single array of 10k elements per thread
this is set to be randomly ordered (but with contigious numbers from 0 to n)
we give 10k to each thread (a pointer into the array at the correct point)
which then loops through that array
calling lfds700_list_aos_insert_element_by_position( LFDS700_LIST_AOS_POSITION_ORDERED )
verification should show list is sorted
*/
internal_display_test_name( "New ordered" );
lfds700_misc_prng_init( &ps );
lfds700_list_asu_query( list_of_logical_processors, LFDS700_LIST_ASU_QUERY_GET_POTENTIALLY_INACCURATE_COUNT, NULL, (void **) &number_logical_processors );
lfds700_list_aos_init_valid_on_current_logical_core( &laoss, new_ordered_compare_function, LFDS700_LIST_AOS_INSERT_RESULT_FAILURE_EXISTING_KEY, NULL );
/* TRD : create randomly ordered number array with unique elements
unique isn't necessary - the list will sort anyway - but
it permits slightly better validation
*/
number_elements_per_thread = ( memory_in_megabytes * ONE_MEGABYTE_IN_BYTES ) / ( sizeof(struct test_element) * number_logical_processors );
// TRD : or the test takes a looooooong time...
if( number_elements_per_thread > 10000 )
number_elements_per_thread = 10000;
number_elements_total = number_elements_per_thread * number_logical_processors;
element_array = util_aligned_malloc( sizeof(struct test_element) * number_elements_total, LFDS700_PAL_ATOMIC_ISOLATION_IN_BYTES );
for( loop = 0 ; loop < number_elements_total ; loop++ )
(element_array+loop)->element_number = loop;
for( loop = 0 ; loop < number_elements_total ; loop++ )
{
offset = LFDS700_MISC_PRNG_GENERATE( &ps );
offset %= number_elements_total;
temp = (element_array + offset)->element_number;
(element_array + offset)->element_number = (element_array + loop)->element_number;
(element_array + loop)->element_number = temp;
}
ts = util_malloc_wrapper( sizeof(struct test_state) * number_logical_processors );
for( loop = 0 ; loop < number_logical_processors ; loop++ )
{
(ts+loop)->laoss = &laoss;
(ts+loop)->element_array = element_array + (loop*number_elements_per_thread);
(ts+loop)->number_elements_per_thread = number_elements_per_thread;
}
thread_handles = util_malloc_wrapper( sizeof(test_pal_thread_state_t) * number_logical_processors );
util_thread_starter_new( &tts, number_logical_processors );
LFDS700_MISC_BARRIER_STORE;
lfds700_misc_force_store();
loop = 0;
while( LFDS700_LIST_ASU_GET_START_AND_THEN_NEXT(*list_of_logical_processors, lasue) )
{
lp = LFDS700_LIST_ASU_GET_VALUE_FROM_ELEMENT( *lasue );
util_thread_starter_start( tts, &thread_handles[loop], loop, lp, new_ordered_thread, ts+loop );
loop++;
}
util_thread_starter_run( tts );
for( loop = 0 ; loop < number_logical_processors ; loop++ )
test_pal_thread_wait( thread_handles[loop] );
util_thread_starter_delete( tts );
free( thread_handles );
free( ts );
/* TRD : validate the resultant list
iterate over the list
we expect to find the list is sorted,
which means that element_number will
increment from zero
*/
LFDS700_MISC_BARRIER_LOAD;
vi.min_elements = vi.max_elements = number_elements_total;
lfds700_list_aos_query( &laoss, LFDS700_LIST_AOS_QUERY_SINGLETHREADED_VALIDATE, &vi, &dvs );
if( dvs == LFDS700_MISC_VALIDITY_VALID )
{
expected_element_number = 0;
// TRD : traverse the list and check combined_data_array matches
while( dvs == LFDS700_MISC_VALIDITY_VALID and LFDS700_LIST_AOS_GET_START_AND_THEN_NEXT(laoss, laose) )
{
element = LFDS700_LIST_AOS_GET_VALUE_FROM_ELEMENT( *laose );
if( element->element_number != expected_element_number++ )
dvs = LFDS700_MISC_VALIDITY_INVALID_TEST_DATA;
}
}
lfds700_list_aos_cleanup( &laoss, NULL );
util_aligned_free( element_array );
internal_display_test_result( 1, "list_aos", dvs );
return;
}
/****************************************************************************/
#pragma warning( disable : 4100 )
static int new_ordered_compare_function( void const *value_new, void const *value_in_list )
{
int
cr = 0;
struct test_element
*e1,
*e2;
// TRD : value_new can be any value in its range
// TRD : value_in_list can be any value in its range
e1 = (struct test_element *) value_new;
e2 = (struct test_element *) value_in_list;
if( e1->element_number < e2->element_number )
cr = -1;
if( e1->element_number > e2->element_number )
cr = 1;
return( cr );
}
#pragma warning( default : 4100 )
/****************************************************************************/
static test_pal_thread_return_t TEST_PAL_CALLING_CONVENTION new_ordered_thread( void *util_thread_starter_thread_state )
{
lfds700_pal_uint_t
loop;
struct lfds700_misc_prng_state
ps;
struct test_state
*ts;
struct util_thread_starter_thread_state
*tsts;
LFDS700_MISC_MAKE_VALID_ON_CURRENT_LOGICAL_CORE_INITS_COMPLETED_BEFORE_NOW_ON_ANY_OTHER_LOGICAL_CORE;
assert( util_thread_starter_thread_state != NULL );
tsts = (struct util_thread_starter_thread_state *) util_thread_starter_thread_state;
ts = (struct test_state *) tsts->thread_user_state;
lfds700_misc_prng_init( &ps );
util_thread_starter_ready_and_wait( tsts );
for( loop = 0 ; loop < ts->number_elements_per_thread ; loop++ )
{
LFDS700_LIST_AOS_SET_KEY_IN_ELEMENT( (ts->element_array+loop)->laose, ts->element_array+loop );
LFDS700_LIST_AOS_SET_VALUE_IN_ELEMENT( (ts->element_array+loop)->laose, ts->element_array+loop );
lfds700_list_aos_insert( ts->laoss, &(ts->element_array+loop)->laose, NULL, &ps );
}
LFDS700_MISC_BARRIER_STORE;
lfds700_misc_force_store();
return( (test_pal_thread_return_t) EXIT_SUCCESS );
}
/***** includes *****/
#include "internal.h"
/***** structs *****/
struct test_element
{
struct lfds700_list_aos_element
laose;
lfds700_pal_uint_t
element_number,
thread_number;
};
struct test_state
{
enum flag
error_flag;
lfds700_pal_uint_t
number_elements_per_thread;
struct lfds700_list_aos_state
*laoss;
struct test_element
*element_array;
};
/***** private prototypes *****/
static int new_ordered_with_cursor_compare_function( void const *value_new, void const *value_in_list );
static test_pal_thread_return_t TEST_PAL_CALLING_CONVENTION new_ordered_with_cursor_insert_thread( void *util_thread_starter_thread_state );
static test_pal_thread_return_t TEST_PAL_CALLING_CONVENTION new_ordered_with_cursor_cursor_thread( void *util_thread_starter_thread_state );
/****************************************************************************/
void test_lfds700_list_aos_new_ordered_with_cursor( struct lfds700_list_asu_state *list_of_logical_processors, lfds700_pal_uint_t memory_in_megabytes )
{
enum lfds700_misc_validity
dvs = LFDS700_MISC_VALIDITY_VALID;
lfds700_pal_uint_t
loop,
number_elements_per_thread,
number_elements_total,
number_logical_processors,
offset,
temp;
struct lfds700_list_aos_state
laoss;
struct lfds700_list_asu_element
*lasue = NULL;
struct lfds700_misc_prng_state
ps;
struct lfds700_misc_validation_info
vi;
struct test_pal_logical_processor
*lp;
struct util_thread_starter_state
*tts;
struct test_element
*element_array;
struct test_state
*ts;
test_pal_thread_state_t
*thread_handles;
assert( list_of_logical_processors != NULL );
// TRD : memory_in_megabytes can be any value in its range
/* TRD : run two threads per logical processor
the test runs for 10 seconds
the first thread loops over a pre-set list of random numbers
continually adding them using ordered insert
the second thread keeps iterating over the list, checking that
each element is larger than its predecessor
*/
internal_display_test_name( "New ordered with cursor (%d seconds)", TEST_DURATION_IN_SECONDS );
lfds700_misc_prng_init( &ps );
lfds700_list_asu_query( list_of_logical_processors, LFDS700_LIST_ASU_QUERY_GET_POTENTIALLY_INACCURATE_COUNT, NULL, (void **) &number_logical_processors );
lfds700_list_aos_init_valid_on_current_logical_core( &laoss, new_ordered_with_cursor_compare_function, LFDS700_LIST_AOS_INSERT_RESULT_FAILURE_EXISTING_KEY, NULL );
/* TRD : create randomly ordered number array with unique elements
unique isn't necessary - the list will sort anyway - but
it permits slightly better validation
*/
number_elements_per_thread = ( memory_in_megabytes * ONE_MEGABYTE_IN_BYTES ) / ( sizeof(struct test_element) * number_logical_processors );
// TRD : or the test takes a looooooong time...
if( number_elements_per_thread > 1000 )
number_elements_per_thread = 1000;
number_elements_total = number_elements_per_thread * number_logical_processors;
element_array = util_aligned_malloc( sizeof(struct test_element) * number_elements_total, LFDS700_PAL_ATOMIC_ISOLATION_IN_BYTES );
for( loop = 0 ; loop < number_elements_total ; loop++ )
(element_array+loop)->element_number = loop;
for( loop = 0 ; loop < number_elements_total ; loop++ )
{
offset = LFDS700_MISC_PRNG_GENERATE( &ps );
offset %= number_elements_total;
temp = (element_array + offset)->element_number;
(element_array + offset)->element_number = (element_array + loop)->element_number;
(element_array + loop)->element_number = temp;
}
ts = util_malloc_wrapper( sizeof(struct test_state) * number_logical_processors * 2 );
// TRD : the insert threads
for( loop = 0 ; loop < number_logical_processors ; loop++ )
{
(ts+loop)->laoss = &laoss;
(ts+loop)->element_array = element_array + number_elements_per_thread*loop;
(ts+loop)->error_flag = LOWERED;
(ts+loop)->number_elements_per_thread = number_elements_per_thread;
}
// TRD : the cursor threads
for( loop = number_logical_processors ; loop < number_logical_processors * 2 ; loop++ )
{
(ts+loop)->laoss = &laoss;
(ts+loop)->element_array = NULL;
(ts+loop)->error_flag = LOWERED;
}
thread_handles = util_malloc_wrapper( sizeof(test_pal_thread_state_t) * number_logical_processors * 2 );
util_thread_starter_new( &tts, number_logical_processors * 2 );
LFDS700_MISC_BARRIER_STORE;
lfds700_misc_force_store();
loop = 0;
while( LFDS700_LIST_ASU_GET_START_AND_THEN_NEXT(*list_of_logical_processors, lasue) )
{
lp = LFDS700_LIST_ASU_GET_VALUE_FROM_ELEMENT( *lasue );
util_thread_starter_start( tts, &thread_handles[loop], loop, lp, new_ordered_with_cursor_insert_thread, ts+loop );
util_thread_starter_start( tts, &thread_handles[loop+number_logical_processors], loop+number_logical_processors, lp, new_ordered_with_cursor_cursor_thread, ts+loop+number_logical_processors );
loop++;
}
util_thread_starter_run( tts );
for( loop = 0 ; loop < number_logical_processors * 2 ; loop++ )
test_pal_thread_wait( thread_handles[loop] );
util_thread_starter_delete( tts );
free( thread_handles );
/* TRD : validate the resultant list
the cursor threads were checking for orderedness
if that failed, they raise their error_flag
so validate the list, then check error_flags
*/
LFDS700_MISC_BARRIER_LOAD;
vi.min_elements = vi.max_elements = number_elements_total;
lfds700_list_aos_query( &laoss, LFDS700_LIST_AOS_QUERY_SINGLETHREADED_VALIDATE, &vi, &dvs );
if( dvs == LFDS700_MISC_VALIDITY_VALID )
for( loop = number_logical_processors ; loop < number_logical_processors * 2 ; loop++ )
if( (ts+loop)->error_flag == RAISED )
dvs = LFDS700_MISC_VALIDITY_INVALID_ORDER;
lfds700_list_aos_cleanup( &laoss, NULL );
util_aligned_free( element_array );
free( ts );
internal_display_test_result( 1, "list_aos", dvs );
return;
}
/****************************************************************************/
#pragma warning( disable : 4100 )
static int new_ordered_with_cursor_compare_function( void const *value_new, void const *value_in_list )
{
int
cr = 0;
struct test_element
*e1,
*e2;
// TRD : value_new can be any value in its range
// TRD : value_in_list can be any value in its range
e1 = (struct test_element *) value_new;
e2 = (struct test_element *) value_in_list;
if( e1->element_number < e2->element_number )
cr = -1;
if( e1->element_number > e2->element_number )
cr = 1;
return( cr );
}
#pragma warning( default : 4100 )
/****************************************************************************/
static test_pal_thread_return_t TEST_PAL_CALLING_CONVENTION new_ordered_with_cursor_insert_thread( void *util_thread_starter_thread_state )
{
lfds700_pal_uint_t
loop;
struct lfds700_misc_prng_state
ps;
struct test_state
*ts;
struct util_thread_starter_thread_state
*tsts;
LFDS700_MISC_BARRIER_LOAD;
assert( util_thread_starter_thread_state != NULL );
tsts = (struct util_thread_starter_thread_state *) util_thread_starter_thread_state;
ts = (struct test_state *) tsts->thread_user_state;
lfds700_misc_prng_init( &ps );
util_thread_starter_ready_and_wait( tsts );
for( loop = 0 ; loop < ts->number_elements_per_thread ; loop++ )
{
LFDS700_LIST_AOS_SET_KEY_IN_ELEMENT( (ts->element_array+loop)->laose, ts->element_array+loop );
LFDS700_LIST_AOS_SET_VALUE_IN_ELEMENT( (ts->element_array+loop)->laose, ts->element_array+loop );
lfds700_list_aos_insert( ts->laoss, &(ts->element_array+loop)->laose, NULL, &ps );
}
LFDS700_MISC_BARRIER_STORE;
lfds700_misc_force_store();
return( (test_pal_thread_return_t) EXIT_SUCCESS );
}
/****************************************************************************/
static test_pal_thread_return_t TEST_PAL_CALLING_CONVENTION new_ordered_with_cursor_cursor_thread( void *util_thread_starter_thread_state )
{
lfds700_pal_uint_t
prev_element_number;
lfds700_pal_uint_t
time_loop = 0;
struct lfds700_list_aos_element
*laose;
struct test_element
*element;
struct test_state
*ts;
struct util_thread_starter_thread_state
*tsts;
time_t
current_time,
start_time;
LFDS700_MISC_MAKE_VALID_ON_CURRENT_LOGICAL_CORE_INITS_COMPLETED_BEFORE_NOW_ON_ANY_OTHER_LOGICAL_CORE;
assert( util_thread_starter_thread_state != NULL );
tsts = (struct util_thread_starter_thread_state *) util_thread_starter_thread_state;
ts = (struct test_state *) tsts->thread_user_state;
util_thread_starter_ready_and_wait( tsts );
current_time = start_time = time( NULL );
while( current_time < start_time + TEST_DURATION_IN_SECONDS )
{
prev_element_number = 0;
laose = LFDS700_LIST_AOS_GET_START( *ts->laoss );
// TRD : we may get start before any element has been added to the list
if( laose == NULL )
continue;
element = LFDS700_LIST_AOS_GET_VALUE_FROM_ELEMENT( *laose );
if( element->element_number < prev_element_number )
ts->error_flag = RAISED;
prev_element_number = element->element_number;
laose = LFDS700_LIST_AOS_GET_NEXT( *laose );
while( laose != NULL )
{
element = LFDS700_LIST_AOS_GET_VALUE_FROM_ELEMENT( *laose );
if( element->element_number <= prev_element_number )
ts->error_flag = RAISED;
prev_element_number = element->element_number;
laose = LFDS700_LIST_AOS_GET_NEXT( *laose );
}
if( time_loop++ == REDUCED_TIME_LOOP_COUNT )
{
time_loop = 0;
time( &current_time );
}
}
LFDS700_MISC_BARRIER_STORE;
lfds700_misc_force_store();
return( (test_pal_thread_return_t) EXIT_SUCCESS );
}
/***** includes *****/
#include "internal.h"
/****************************************************************************/
#pragma warning( disable : 4127 ) // TRD : disables MSVC warning for condition expressions being const
void test_lfds700_list_asu( struct lfds700_list_asu_state *list_of_logical_processors, lfds700_pal_uint_t memory_in_megabytes )
{
assert( list_of_logical_processors != NULL );
// TRD : memory_in_megabytes can be any value in its range
if( LFDS700_MISC_ATOMIC_SUPPORT_CAS )
{
printf( "\n"
"List (add-only, singly-linked, unordered) Tests\n"
"===============================================\n" );
test_lfds700_list_asu_alignment();
test_lfds700_list_asu_new_start( list_of_logical_processors, memory_in_megabytes );
test_lfds700_list_asu_new_end( list_of_logical_processors, memory_in_megabytes );
test_lfds700_list_asu_new_after( list_of_logical_processors, memory_in_megabytes );
}
return;
}
#pragma warning( default : 4127 )
/***** includes *****/
#include "internal.h"
/****************************************************************************/
#pragma warning( disable : 4127 ) // TRD : disables MSVC warning for condition expressions being const
void test_lfds700_list_asu_alignment()
{
enum lfds700_misc_validity
dvs = LFDS700_MISC_VALIDITY_VALID;
/* TRD : these are compile time checks
but we do them here because this is a test programme
and it should indicate issues to users when it is *run*,
not when it is compiled, because a compile error normally
indicates a problem with the code itself and so is misleading
*/
internal_display_test_name( "Alignment" );
// TRD : struct lfds700_list_asu_element
if( offsetof(struct lfds700_list_asu_element,next) % LFDS700_PAL_ATOMIC_ISOLATION_IN_BYTES != 0 )
dvs = LFDS700_MISC_VALIDITY_INVALID_TEST_DATA;
if( offsetof(struct lfds700_list_asu_element,value) % LFDS700_PAL_ATOMIC_ISOLATION_IN_BYTES != 0 )
dvs = LFDS700_MISC_VALIDITY_INVALID_TEST_DATA;
if( offsetof(struct lfds700_list_asu_element,key) % LFDS700_PAL_ATOMIC_ISOLATION_IN_BYTES != 0 )
dvs = LFDS700_MISC_VALIDITY_INVALID_TEST_DATA;
// TRD : struct lfds700_list_asu_state
if( offsetof(struct lfds700_list_asu_state,end) % LFDS700_PAL_ATOMIC_ISOLATION_IN_BYTES != 0 )
dvs = LFDS700_MISC_VALIDITY_INVALID_TEST_DATA;
if( offsetof(struct lfds700_list_asu_state,start) % LFDS700_PAL_ATOMIC_ISOLATION_IN_BYTES != 0 )
dvs = LFDS700_MISC_VALIDITY_INVALID_TEST_DATA;
if( offsetof(struct lfds700_list_asu_state,dummy_element) % LFDS700_PAL_ATOMIC_ISOLATION_IN_BYTES != 0 )
dvs = LFDS700_MISC_VALIDITY_INVALID_TEST_DATA;
if( offsetof(struct lfds700_list_asu_state,key_compare_function) % LFDS700_PAL_ATOMIC_ISOLATION_IN_BYTES != 0 )
dvs = LFDS700_MISC_VALIDITY_INVALID_TEST_DATA;
// TRD : print the test result
internal_display_test_result( 1, "list_asu", dvs );
return;
}
#pragma warning( default : 4127 )
/***** includes *****/
#include "internal.h"
/***** structs *****/
struct test_element
{
struct lfds700_list_asu_element
lasue;
lfds700_pal_uint_t
element_number,
thread_number;
};
struct test_state
{
lfds700_pal_uint_t
number_elements;
struct lfds700_list_asu_state
*lasus;
struct test_element
*element_array;
struct lfds700_list_asu_element
*first_element;
};
/***** private prototypes *****/
static test_pal_thread_return_t TEST_PAL_CALLING_CONVENTION new_after_thread( void *util_thread_starter_thread_state );
/****************************************************************************/
void test_lfds700_list_asu_new_after( struct lfds700_list_asu_state *list_of_logical_processors, lfds700_pal_uint_t memory_in_megabytes )
{
enum lfds700_misc_validity
dvs = LFDS700_MISC_VALIDITY_VALID;
lfds700_pal_uint_t
loop,
number_elements,
number_logical_processors,
*per_thread_counters,
subloop;
struct lfds700_list_asu_element
*lasue,
first_element;
struct lfds700_list_asu_state
lasus;
struct lfds700_misc_prng_state
ps;
struct lfds700_misc_validation_info
vi;
struct test_pal_logical_processor
*lp;
struct util_thread_starter_state
*tts;
struct test_element
*element_array,
*element;
struct test_state
*ts;
test_pal_thread_state_t
*thread_handles;
assert( list_of_logical_processors != NULL );
// TRD : memory_in_megabytes can be any value in its range
/* TRD : run one thread per logical processor
run for 250k elements
we put a single first element into the list and
each thread loops, calling lfds700_list_asu_new_element_by_position( LFDS700_LIST_ASU_POSITION_AFTER ),
inserting after the single first element
data element contain s thread_number and element_number
verification should show element_number decreasing on a per thread basis
*/
internal_display_test_name( "New after" );
lfds700_list_asu_query( list_of_logical_processors, LFDS700_LIST_ASU_QUERY_GET_POTENTIALLY_INACCURATE_COUNT, NULL, (void **) &number_logical_processors );
lfds700_misc_prng_init( &ps );
lfds700_list_asu_init_valid_on_current_logical_core( &lasus, NULL, NULL );
LFDS700_LIST_ASU_SET_KEY_IN_ELEMENT( first_element, NULL );
LFDS700_LIST_ASU_SET_VALUE_IN_ELEMENT( first_element, NULL );
lfds700_list_asu_insert_at_position( &lasus, &first_element, NULL, LFDS700_LIST_ASU_POSITION_START, &ps );
number_elements = ( memory_in_megabytes * ONE_MEGABYTE_IN_BYTES ) / ( sizeof(struct test_element) * number_logical_processors );
element_array = util_aligned_malloc( sizeof(struct test_element) * number_logical_processors * number_elements, LFDS700_PAL_ATOMIC_ISOLATION_IN_BYTES );
for( loop = 0 ; loop < number_logical_processors ; loop++ )
for( subloop = 0 ; subloop < number_elements ; subloop++ )
{
(element_array+(loop*number_elements)+subloop)->thread_number = loop;
(element_array+(loop*number_elements)+subloop)->element_number = subloop;
}
ts = util_malloc_wrapper( sizeof(struct test_state) * number_logical_processors );
for( loop = 0 ; loop < number_logical_processors ; loop++ )
{\
(ts+loop)->lasus = &lasus;
(ts+loop)->element_array = element_array + (loop*number_elements);
(ts+loop)->first_element = &first_element;
(ts+loop)->number_elements = number_elements;
}
thread_handles = util_malloc_wrapper( sizeof(test_pal_thread_state_t) * number_logical_processors );
util_thread_starter_new( &tts, number_logical_processors );
LFDS700_MISC_BARRIER_STORE;
lfds700_misc_force_store();
loop = 0;
lasue = NULL;
while( LFDS700_LIST_ASU_GET_START_AND_THEN_NEXT(*list_of_logical_processors, lasue) )
{
lp = LFDS700_LIST_ASU_GET_VALUE_FROM_ELEMENT( *lasue );
util_thread_starter_start( tts, &thread_handles[loop], loop, lp, new_after_thread, ts+loop );
loop++;
}
util_thread_starter_run( tts );
for( loop = 0 ; loop < number_logical_processors ; loop++ )
test_pal_thread_wait( thread_handles[loop] );
util_thread_starter_delete( tts );
free( thread_handles );
free( ts );
/* TRD : validate the resultant list
iterate over each element
we expect to find element numbers increment on a per thread basis
*/
LFDS700_MISC_BARRIER_LOAD;
vi.min_elements = vi.max_elements = number_elements * number_logical_processors + 1;
lfds700_list_asu_query( &lasus, LFDS700_LIST_ASU_QUERY_SINGLETHREADED_VALIDATE, &vi, &dvs );
per_thread_counters = util_malloc_wrapper( sizeof(lfds700_pal_uint_t) * number_logical_processors );
for( loop = 0 ; loop < number_logical_processors ; loop++ )
*(per_thread_counters+loop) = number_elements - 1;
/* TRD : we have a leading element, after which all inserts occurred
we need to get past that element for validation
this is why we're not using lfds700_list_asu_get_start_and_then_next()
*/
lasue = LFDS700_LIST_ASU_GET_START( lasus );
lasue = LFDS700_LIST_ASU_GET_NEXT( *lasue );
while( dvs == LFDS700_MISC_VALIDITY_VALID and lasue != NULL )
{
element = LFDS700_LIST_ASU_GET_VALUE_FROM_ELEMENT( *lasue );
if( element->thread_number >= number_logical_processors )
{
dvs = LFDS700_MISC_VALIDITY_INVALID_TEST_DATA;
break;
}
if( element->element_number < per_thread_counters[element->thread_number] )
dvs = LFDS700_MISC_VALIDITY_INVALID_MISSING_ELEMENTS;
if( element->element_number > per_thread_counters[element->thread_number] )
dvs = LFDS700_MISC_VALIDITY_INVALID_ADDITIONAL_ELEMENTS;
if( element->element_number == per_thread_counters[element->thread_number] )
per_thread_counters[element->thread_number]--;
lasue = LFDS700_LIST_ASU_GET_NEXT( *lasue );
}
free( per_thread_counters );
lfds700_list_asu_cleanup( &lasus, NULL );
util_aligned_free( element_array );
internal_display_test_result( 1, "list_asu", dvs );
return;
}
/****************************************************************************/
static test_pal_thread_return_t TEST_PAL_CALLING_CONVENTION new_after_thread( void *util_thread_starter_thread_state )
{
lfds700_pal_uint_t
loop;
struct lfds700_misc_prng_state
ps;
struct test_state
*ts;
struct util_thread_starter_thread_state
*tsts;
LFDS700_MISC_MAKE_VALID_ON_CURRENT_LOGICAL_CORE_INITS_COMPLETED_BEFORE_NOW_ON_ANY_OTHER_LOGICAL_CORE;
assert( util_thread_starter_thread_state != NULL );
tsts = (struct util_thread_starter_thread_state *) util_thread_starter_thread_state;
ts = (struct test_state *) tsts->thread_user_state;
lfds700_misc_prng_init( &ps );
util_thread_starter_ready_and_wait( tsts );
for( loop = 0 ; loop < ts->number_elements ; loop++ )
{
LFDS700_LIST_ASU_SET_KEY_IN_ELEMENT( (ts->element_array+loop)->lasue, ts->element_array+loop );
LFDS700_LIST_ASU_SET_VALUE_IN_ELEMENT( (ts->element_array+loop)->lasue, ts->element_array+loop );
lfds700_list_asu_insert_at_position( ts->lasus, &(ts->element_array+loop)->lasue, ts->first_element, LFDS700_LIST_ASU_POSITION_AFTER, &ps );
}
LFDS700_MISC_BARRIER_STORE;
lfds700_misc_force_store();
return( (test_pal_thread_return_t) EXIT_SUCCESS );
}
/***** includes *****/
#include "internal.h"
/***** structs *****/
struct test_element
{
struct lfds700_list_asu_element
lasue;
lfds700_pal_uint_t
element_number,
thread_number;
};
struct test_state
{
lfds700_pal_uint_t
number_elements;
struct lfds700_list_asu_state
*lasus;
struct test_element
*element_array;
};
/***** private prototypes *****/
static test_pal_thread_return_t TEST_PAL_CALLING_CONVENTION new_end_thread( void *util_thread_starter_thread_state );
/****************************************************************************/
void test_lfds700_list_asu_new_end( struct lfds700_list_asu_state *list_of_logical_processors, lfds700_pal_uint_t memory_in_megabytes )
{
enum lfds700_misc_validity
dvs = LFDS700_MISC_VALIDITY_VALID;
lfds700_pal_uint_t
loop,
number_elements,
number_logical_processors,
*per_thread_counters,
subloop;
struct lfds700_list_asu_element
*lasue = NULL;
struct lfds700_list_asu_state
lasus;
struct lfds700_misc_validation_info
vi;
struct test_pal_logical_processor
*lp;
struct util_thread_starter_state
*tts;
struct test_element
*element_array,
*element;
struct test_state
*ts;
test_pal_thread_state_t
*thread_handles;
assert( list_of_logical_processors != NULL );
// TRD : memory_in_megabytes can be any value in its range
/* TRD : run one thread per logical processor
run for 250k elements
each thread loops, calling lfds700_list_asu_new_element_by_position( LFDS700_LIST_ASU_POSITION_END )
data element contain a thread_number and element_number
verification should show element_number increasing on a per thread basis
*/
internal_display_test_name( "New end" );
lfds700_list_asu_query( list_of_logical_processors, LFDS700_LIST_ASU_QUERY_GET_POTENTIALLY_INACCURATE_COUNT, NULL, (void **) &number_logical_processors );
lfds700_list_asu_init_valid_on_current_logical_core( &lasus, NULL, NULL );
number_elements = ( memory_in_megabytes * ONE_MEGABYTE_IN_BYTES ) / ( sizeof(struct test_element) * number_logical_processors );
element_array = util_aligned_malloc( sizeof(struct test_element) * number_logical_processors * number_elements, LFDS700_PAL_ATOMIC_ISOLATION_IN_BYTES );
for( loop = 0 ; loop < number_logical_processors ; loop++ )
for( subloop = 0 ; subloop < number_elements ; subloop++ )
{
(element_array+(loop*number_elements)+subloop)->thread_number = loop;
(element_array+(loop*number_elements)+subloop)->element_number = subloop;
}
ts = util_malloc_wrapper( sizeof(struct test_state) * number_logical_processors );
for( loop = 0 ; loop < number_logical_processors ; loop++ )
{
(ts+loop)->lasus = &lasus;
(ts+loop)->element_array = element_array + (loop*number_elements);
(ts+loop)->number_elements = number_elements;
}
thread_handles = util_malloc_wrapper( sizeof(test_pal_thread_state_t) * number_logical_processors );
util_thread_starter_new( &tts, number_logical_processors );
LFDS700_MISC_BARRIER_STORE;
lfds700_misc_force_store();
loop = 0;
lasue = NULL;
while( LFDS700_LIST_ASU_GET_START_AND_THEN_NEXT(*list_of_logical_processors, lasue) )
{
lp = LFDS700_LIST_ASU_GET_VALUE_FROM_ELEMENT( *lasue );
util_thread_starter_start( tts, &thread_handles[loop], loop, lp, new_end_thread, ts+loop );
loop++;
}
util_thread_starter_run( tts );
for( loop = 0 ; loop < number_logical_processors ; loop++ )
test_pal_thread_wait( thread_handles[loop] );
util_thread_starter_delete( tts );
free( thread_handles );
free( ts );
/* TRD : validate the resultant list
iterate over each element
we expect to find element numbers increment on a per thread basis
*/
LFDS700_MISC_BARRIER_LOAD;
vi.min_elements = vi.max_elements = number_elements * number_logical_processors;
lfds700_list_asu_query( &lasus, LFDS700_LIST_ASU_QUERY_SINGLETHREADED_VALIDATE, &vi, &dvs );
per_thread_counters = util_malloc_wrapper( sizeof(lfds700_pal_uint_t) * number_logical_processors );
for( loop = 0 ; loop < number_logical_processors ; loop++ )
*(per_thread_counters+loop) = 0;
lasue = NULL;
while( dvs == LFDS700_MISC_VALIDITY_VALID and LFDS700_LIST_ASU_GET_START_AND_THEN_NEXT(lasus, lasue) )
{
element = LFDS700_LIST_ASU_GET_VALUE_FROM_ELEMENT( *lasue );
if( element->thread_number >= number_logical_processors )
{
dvs = LFDS700_MISC_VALIDITY_INVALID_TEST_DATA;
break;
}
if( element->element_number > per_thread_counters[element->thread_number] )
dvs = LFDS700_MISC_VALIDITY_INVALID_MISSING_ELEMENTS;
if( element->element_number < per_thread_counters[element->thread_number] )
dvs = LFDS700_MISC_VALIDITY_INVALID_ADDITIONAL_ELEMENTS;
if( element->element_number == per_thread_counters[element->thread_number] )
per_thread_counters[element->thread_number]++;
}
free( per_thread_counters );
lfds700_list_asu_cleanup( &lasus, NULL );
util_aligned_free( element_array );
internal_display_test_result( 1, "list_asu", dvs );
return;
}
/****************************************************************************/
static test_pal_thread_return_t TEST_PAL_CALLING_CONVENTION new_end_thread( void *util_thread_starter_thread_state )
{
lfds700_pal_uint_t
loop;
struct lfds700_misc_prng_state
ps;
struct test_state
*ts;
struct util_thread_starter_thread_state
*tsts;
LFDS700_MISC_MAKE_VALID_ON_CURRENT_LOGICAL_CORE_INITS_COMPLETED_BEFORE_NOW_ON_ANY_OTHER_LOGICAL_CORE;
assert( util_thread_starter_thread_state != NULL );
tsts = (struct util_thread_starter_thread_state *) util_thread_starter_thread_state;
ts = (struct test_state *) tsts->thread_user_state;
lfds700_misc_prng_init( &ps );
util_thread_starter_ready_and_wait( tsts );
for( loop = 0 ; loop < ts->number_elements ; loop++ )
{
LFDS700_LIST_ASU_SET_KEY_IN_ELEMENT( (ts->element_array+loop)->lasue, ts->element_array+loop );
LFDS700_LIST_ASU_SET_VALUE_IN_ELEMENT( (ts->element_array+loop)->lasue, ts->element_array+loop );
lfds700_list_asu_insert_at_position( ts->lasus, &(ts->element_array+loop)->lasue, NULL, LFDS700_LIST_ASU_POSITION_END, &ps );
}
LFDS700_MISC_BARRIER_STORE;
lfds700_misc_force_store();
return( (test_pal_thread_return_t) EXIT_SUCCESS );
}
/***** includes *****/
#include "internal.h"
/***** structs *****/
struct test_element
{
struct lfds700_list_asu_element
lasue;
lfds700_pal_uint_t
element_number,
thread_number;
};
struct test_state
{
lfds700_pal_uint_t
number_elements;
struct lfds700_list_asu_state
*lasus;
struct test_element
*element_array;
};
/***** private prototypes *****/
static test_pal_thread_return_t TEST_PAL_CALLING_CONVENTION new_start_thread( void *util_thread_starter_thread_state );
/****************************************************************************/
void test_lfds700_list_asu_new_start( struct lfds700_list_asu_state *list_of_logical_processors, lfds700_pal_uint_t memory_in_megabytes )
{
enum lfds700_misc_validity
dvs = LFDS700_MISC_VALIDITY_VALID;
lfds700_pal_uint_t
loop,
number_elements,
number_logical_processors,
*per_thread_counters,
subloop;
struct lfds700_list_asu_element
*lasue = NULL;
struct lfds700_list_asu_state
lasus;
struct lfds700_misc_validation_info
vi;
struct test_element
*element_array,
*element;
struct test_state
*ts;
struct test_pal_logical_processor
*lp;
struct util_thread_starter_state
*tts;
test_pal_thread_state_t
*thread_handles;
assert( list_of_logical_processors != NULL );
// TRD : memory_in_megabytes can be any value in its range
/* TRD : run one thread per logical processor
run for 250k elements
each thread loops, calling lfds700_list_asu_new_element_by_position( LFDS700_LIST_ASU_POSITION_START )
data element contain s thread_number and element_number
verification should show element_number decreasing on a per thread basis
*/
internal_display_test_name( "New start" );
lfds700_list_asu_query( list_of_logical_processors, LFDS700_LIST_ASU_QUERY_GET_POTENTIALLY_INACCURATE_COUNT, NULL, (void **) &number_logical_processors );
lfds700_list_asu_init_valid_on_current_logical_core( &lasus, NULL, NULL );
number_elements = ( memory_in_megabytes * ONE_MEGABYTE_IN_BYTES ) / ( sizeof(struct test_element) * number_logical_processors );
element_array = util_aligned_malloc( sizeof(struct test_element) * number_logical_processors * number_elements, LFDS700_PAL_ATOMIC_ISOLATION_IN_BYTES );
for( loop = 0 ; loop < number_logical_processors ; loop++ )
for( subloop = 0 ; subloop < number_elements ; subloop++ )
{
(element_array+(loop*number_elements)+subloop)->thread_number = loop;
(element_array+(loop*number_elements)+subloop)->element_number = subloop;
}
ts = util_malloc_wrapper( sizeof(struct test_state) * number_logical_processors );
for( loop = 0 ; loop < number_logical_processors ; loop++ )
{
(ts+loop)->lasus = &lasus;
(ts+loop)->element_array = element_array + (loop*number_elements);
(ts+loop)->number_elements = number_elements;
}
thread_handles = util_malloc_wrapper( sizeof(test_pal_thread_state_t) * number_logical_processors );
util_thread_starter_new( &tts, number_logical_processors );
LFDS700_MISC_BARRIER_STORE;
lfds700_misc_force_store();
loop = 0;
lasue = NULL;
while( LFDS700_LIST_ASU_GET_START_AND_THEN_NEXT(*list_of_logical_processors, lasue) )
{
lp = LFDS700_LIST_ASU_GET_VALUE_FROM_ELEMENT( *lasue );
util_thread_starter_start( tts, &thread_handles[loop], loop, lp, new_start_thread, ts+loop );
loop++;
}
util_thread_starter_run( tts );
for( loop = 0 ; loop < number_logical_processors ; loop++ )
test_pal_thread_wait( thread_handles[loop] );
util_thread_starter_delete( tts );
free( thread_handles );
free( ts );
LFDS700_MISC_BARRIER_LOAD;
/* TRD : validate the resultant list
iterate over each element
we expect to find element numbers increment on a per thread basis
*/
vi.min_elements = vi.max_elements = number_elements * number_logical_processors;
lfds700_list_asu_query( &lasus, LFDS700_LIST_ASU_QUERY_SINGLETHREADED_VALIDATE, &vi, &dvs );
per_thread_counters = util_malloc_wrapper( sizeof(lfds700_pal_uint_t) * number_logical_processors );
for( loop = 0 ; loop < number_logical_processors ; loop++ )
*(per_thread_counters+loop) = number_elements - 1;
lasue = NULL;
while( dvs == LFDS700_MISC_VALIDITY_VALID and LFDS700_LIST_ASU_GET_START_AND_THEN_NEXT(lasus, lasue) )
{
element = LFDS700_LIST_ASU_GET_VALUE_FROM_ELEMENT( *lasue );
if( element->thread_number >= number_logical_processors )
{
dvs = LFDS700_MISC_VALIDITY_INVALID_TEST_DATA;
break;
}
if( element->element_number < per_thread_counters[element->thread_number] )
dvs = LFDS700_MISC_VALIDITY_INVALID_MISSING_ELEMENTS;
if( element->element_number > per_thread_counters[element->thread_number] )
dvs = LFDS700_MISC_VALIDITY_INVALID_ADDITIONAL_ELEMENTS;
if( element->element_number == per_thread_counters[element->thread_number] )
per_thread_counters[element->thread_number]--;
}
free( per_thread_counters );
lfds700_list_asu_cleanup( &lasus, NULL );
util_aligned_free( element_array );
internal_display_test_result( 1, "list_asu", dvs );
return;
}
/****************************************************************************/
static test_pal_thread_return_t TEST_PAL_CALLING_CONVENTION new_start_thread( void *util_thread_starter_thread_state )
{
lfds700_pal_uint_t
loop;
struct lfds700_misc_prng_state
ps;
struct test_state
*ts;
struct util_thread_starter_thread_state
*tsts;
LFDS700_MISC_MAKE_VALID_ON_CURRENT_LOGICAL_CORE_INITS_COMPLETED_BEFORE_NOW_ON_ANY_OTHER_LOGICAL_CORE;
assert( util_thread_starter_thread_state != NULL );
tsts = (struct util_thread_starter_thread_state *) util_thread_starter_thread_state;
ts = (struct test_state *) tsts->thread_user_state;
lfds700_misc_prng_init( &ps );
util_thread_starter_ready_and_wait( tsts );
for( loop = 0 ; loop < ts->number_elements ; loop++ )
{
LFDS700_LIST_ASU_SET_KEY_IN_ELEMENT( (ts->element_array+loop)->lasue, ts->element_array+loop );
LFDS700_LIST_ASU_SET_VALUE_IN_ELEMENT( (ts->element_array+loop)->lasue, ts->element_array+loop );
lfds700_list_asu_insert_at_position( ts->lasus, &(ts->element_array+loop)->lasue, NULL, LFDS700_LIST_ASU_POSITION_START, &ps );
}
LFDS700_MISC_BARRIER_STORE;
lfds700_misc_force_store();
return( (test_pal_thread_return_t) EXIT_SUCCESS );
}
/***** includes *****/
#include "internal.h"
/****************************************************************************/
#pragma warning( disable : 4127 ) // TRD : disables MSVC warning for condition expressions being const
void test_lfds700_pal_atomic( struct lfds700_list_asu_state *list_of_logical_processors, lfds700_pal_uint_t memory_in_megabytes )
{
assert( list_of_logical_processors != NULL );
// TRD : memory_in_megabytes can be any value in its range
printf( "\n"
"Abstraction Atomic Tests\n"
"========================\n" );
if( LFDS700_MISC_ATOMIC_SUPPORT_CAS )
test_lfds700_pal_atomic_cas( list_of_logical_processors );
if( LFDS700_MISC_ATOMIC_SUPPORT_DWCAS )
test_lfds700_pal_atomic_dwcas( list_of_logical_processors );
if( LFDS700_MISC_ATOMIC_SUPPORT_EXCHANGE )
test_lfds700_pal_atomic_exchange( list_of_logical_processors, memory_in_megabytes );
return;
}
#pragma warning( default : 4127 )
/***** includes *****/
#include "internal.h"
/***** structs *****/
struct test_lfds700_pal_atomic_cas_state
{
lfds700_pal_uint_t
local_counter;
lfds700_pal_atom_t volatile
*shared_counter;
};
/***** private prototyps *****/
static test_pal_thread_return_t TEST_PAL_CALLING_CONVENTION thread_cas( void *util_thread_starter_thread_state );
/****************************************************************************/
void test_lfds700_pal_atomic_cas( struct lfds700_list_asu_state *list_of_logical_processors )
{
lfds700_pal_atom_t volatile LFDS700_PAL_ALIGN(LFDS700_PAL_ATOMIC_ISOLATION_IN_BYTES)
shared_counter;
lfds700_pal_uint_t
local_total = 0;
lfds700_pal_uint_t
loop,
number_logical_processors;
struct lfds700_list_asu_element
*lasue;
struct test_pal_logical_processor
*lp;
struct util_thread_starter_state
*tts;
struct test_lfds700_pal_atomic_cas_state
*atcs;
test_pal_thread_state_t
*thread_handles;
assert( list_of_logical_processors != NULL );
/* TRD : here we test pal_cas
we run one thread per CPU
we use pal_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" );
lfds700_list_asu_query( list_of_logical_processors, LFDS700_LIST_ASU_QUERY_GET_POTENTIALLY_INACCURATE_COUNT, NULL, (void **) &number_logical_processors );
shared_counter = 0;
atcs = util_malloc_wrapper( sizeof(struct test_lfds700_pal_atomic_cas_state) * number_logical_processors );
for( loop = 0 ; loop < number_logical_processors ; loop++ )
{
(atcs+loop)->shared_counter = &shared_counter;
(atcs+loop)->local_counter = 0;
}
thread_handles = util_malloc_wrapper( sizeof(test_pal_thread_state_t) * number_logical_processors );
util_thread_starter_new( &tts, number_logical_processors );
LFDS700_MISC_BARRIER_STORE;
lfds700_misc_force_store();
loop = 0;
lasue = NULL;
while( LFDS700_LIST_ASU_GET_START_AND_THEN_NEXT(*list_of_logical_processors, lasue) )
{
lp = LFDS700_LIST_ASU_GET_VALUE_FROM_ELEMENT( *lasue );
util_thread_starter_start( tts, &thread_handles[loop], loop, lp, thread_cas, atcs+loop );
loop++;
}
util_thread_starter_run( tts );
for( loop = 0 ; loop < number_logical_processors ; loop++ )
test_pal_thread_wait( thread_handles[loop] );
util_thread_starter_delete( tts );
free( thread_handles );
// TRD : results
LFDS700_MISC_BARRIER_LOAD;
for( loop = 0 ; loop < number_logical_processors ; loop++ )
local_total += (atcs+loop)->local_counter;
if( local_total == shared_counter )
puts( "passed" );
if( local_total != shared_counter )
{
puts( "failed" );
exit( EXIT_FAILURE );
}
// TRD : cleanup
free( atcs );
return;
}
/****************************************************************************/
static test_pal_thread_return_t TEST_PAL_CALLING_CONVENTION thread_cas( void *util_thread_starter_thread_state )
{
char unsigned
result;
lfds700_pal_uint_t
loop = 0;
lfds700_pal_atom_t LFDS700_PAL_ALIGN(LFDS700_PAL_ALIGN_SINGLE_POINTER)
exchange,
compare;
struct test_lfds700_pal_atomic_cas_state
*atcs;
struct util_thread_starter_thread_state
*tsts;
LFDS700_MISC_BARRIER_LOAD;
assert( util_thread_starter_thread_state != NULL );
tsts = (struct util_thread_starter_thread_state *) util_thread_starter_thread_state;
atcs = (struct test_lfds700_pal_atomic_cas_state *) tsts->thread_user_state;
util_thread_starter_ready_and_wait( tsts );
while( loop++ < 10000000 )
{
compare = *atcs->shared_counter;
do
{
exchange = compare + 1;
LFDS700_PAL_ATOMIC_CAS( atcs->shared_counter, &compare, exchange, LFDS700_MISC_CAS_STRENGTH_WEAK, result );
}
while( result == 0 );
atcs->local_counter++;
}
LFDS700_MISC_BARRIER_STORE;
lfds700_misc_force_store();
return( (test_pal_thread_return_t) EXIT_SUCCESS );
}
/***** includes *****/
#include "internal.h"
/***** structs *****/
struct test_lfds700_pal_atomic_dwcas_state
{
lfds700_pal_uint_t
local_counter;
lfds700_pal_atom_t volatile
(*shared_counter)[2];
};
/***** private prototyps *****/
static test_pal_thread_return_t TEST_PAL_CALLING_CONVENTION thread_dwcas( void *util_thread_starter_thread_state );
/****************************************************************************/
void test_lfds700_pal_atomic_dwcas( struct lfds700_list_asu_state *list_of_logical_processors )
{
lfds700_pal_uint_t
local_total = 0,
loop,
number_logical_processors;
lfds700_pal_atom_t volatile LFDS700_PAL_ALIGN(LFDS700_PAL_ATOMIC_ISOLATION_IN_BYTES)
shared_counter[2] = { 0, 0 };
struct lfds700_list_asu_element
*lasue;
struct test_pal_logical_processor
*lp;
struct util_thread_starter_state
*tts;
struct test_lfds700_pal_atomic_dwcas_state
*atds;
test_pal_thread_state_t
*thread_handles;
assert( list_of_logical_processors != NULL );
/* TRD : here we test pal_dwcas
we run one thread per CPU
we use pal_dwcas() 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 DWCAS" );
lfds700_list_asu_query( list_of_logical_processors, LFDS700_LIST_ASU_QUERY_GET_POTENTIALLY_INACCURATE_COUNT, NULL, (void **) &number_logical_processors );
atds = util_malloc_wrapper( sizeof(struct test_lfds700_pal_atomic_dwcas_state) * number_logical_processors );
for( loop = 0 ; loop < number_logical_processors ; loop++ )
{
(atds+loop)->shared_counter = &shared_counter;
(atds+loop)->local_counter = 0;
}
thread_handles = util_malloc_wrapper( sizeof(test_pal_thread_state_t) * number_logical_processors );
util_thread_starter_new( &tts, number_logical_processors );
LFDS700_MISC_BARRIER_STORE;
lfds700_misc_force_store();
loop = 0;
lasue = NULL;
while( LFDS700_LIST_ASU_GET_START_AND_THEN_NEXT(*list_of_logical_processors, lasue) )
{
lp = LFDS700_LIST_ASU_GET_VALUE_FROM_ELEMENT( *lasue );
util_thread_starter_start( tts, &thread_handles[loop], loop, lp, thread_dwcas, atds+loop );
loop++;
}
util_thread_starter_run( tts );
for( loop = 0 ; loop < number_logical_processors ; loop++ )
test_pal_thread_wait( thread_handles[loop] );
util_thread_starter_delete( tts );
free( thread_handles );
// TRD : results
LFDS700_MISC_BARRIER_LOAD;
for( loop = 0 ; loop < number_logical_processors ; loop++ )
local_total += (atds+loop)->local_counter;
if( local_total == shared_counter[0] )
puts( "passed" );
if( local_total != shared_counter[0] )
{
printf( "%llu != %llu\n", (int long long unsigned) local_total, (int long long unsigned) shared_counter[0] );
puts( "failed" );
exit( EXIT_FAILURE );
}
// TRD : cleanup
free( atds );
return;
}
#pragma warning( disable : 4702 )
/****************************************************************************/
static test_pal_thread_return_t TEST_PAL_CALLING_CONVENTION thread_dwcas( void *util_thread_starter_thread_state )
{
char unsigned
result;
lfds700_pal_uint_t
loop = 0;
lfds700_pal_atom_t LFDS700_PAL_ALIGN(LFDS700_PAL_ALIGN_DOUBLE_POINTER)
exchange[2],
compare[2];
struct test_lfds700_pal_atomic_dwcas_state
*atds;
struct util_thread_starter_thread_state
*tsts;
assert( util_thread_starter_thread_state != NULL );
tsts = (struct util_thread_starter_thread_state *) util_thread_starter_thread_state;
atds = (struct test_lfds700_pal_atomic_dwcas_state *) tsts->thread_user_state;
LFDS700_MISC_BARRIER_LOAD;
util_thread_starter_ready_and_wait( tsts );
while( loop++ < 10000000 )
{
compare[0] = (*atds->shared_counter)[0];
compare[1] = (*atds->shared_counter)[1];
do
{
exchange[0] = compare[0] + 1;
exchange[1] = compare[1];
LFDS700_PAL_ATOMIC_DWCAS( atds->shared_counter, compare, exchange, LFDS700_MISC_CAS_STRENGTH_WEAK, result );
}
while( result == 0 );
atds->local_counter++;
}
LFDS700_MISC_BARRIER_STORE;
lfds700_misc_force_store();
return( (test_pal_thread_return_t) EXIT_SUCCESS );
}
/***** includes *****/
#include "internal.h"
/***** structs *****/
struct test_state
{
lfds700_pal_uint_t
counter,
*counter_array,
number_elements,
number_logical_processors;
lfds700_pal_uint_t volatile
*shared_exchange;
};
/***** private prototyps *****/
static test_pal_thread_return_t TEST_PAL_CALLING_CONVENTION thread_exchange( void *util_thread_starter_thread_state );
static test_pal_thread_return_t TEST_PAL_CALLING_CONVENTION thread_atomic_exchange( void *util_thread_starter_thread_state );
/****************************************************************************/
void test_lfds700_pal_atomic_exchange( struct lfds700_list_asu_state *list_of_logical_processors, lfds700_pal_uint_t memory_in_megabytes )
{
enum flag
atomic_exchange_success_flag = RAISED,
exchange_success_flag = RAISED;
lfds700_pal_uint_t
loop,
*merged_counter_arrays,
number_elements,
number_logical_processors,
subloop;
lfds700_pal_uint_t volatile LFDS700_PAL_ALIGN(LFDS700_PAL_ATOMIC_ISOLATION_IN_BYTES)
exchange;
struct lfds700_list_asu_element
*lasue;
struct test_state
*ts;
struct test_pal_logical_processor
*lp;
struct util_thread_starter_state
*tts;
test_pal_thread_state_t
*thread_handles;
assert( list_of_logical_processors != NULL );
// TRD : memory_in_megabytes can be any value in its range
/* TRD : here we test pal_atomic_exchange
we have one thread per logical core
there is one variable which every thread will exchange to/from
we know the number of logical cores
the threads have a counter each, which begins with their logical core number plus one
(plus one because the exchange counter begins with 0 already in place)
(e.g. thread 0 begins with its counter at 1, thread 1 begins with its counter at 2, etc)
there is an array per thread of 1 million elements, each a counter, set to 0
when running, each thread increments its counter by the number of threads
the threads busy loop, exchanging
every time aa thread pulls a number off the central, shared exchange variable,
it increments the counter for that variable in its thread-local counter array
(we're not using a global array, because we'd have to be atomic in our increments,
which is a slow-down we don't want)
at the end, we merge all the counter arrays and if the frequency for a counter is a value
other than 1, the exchange was not atomic
we perform the test twice, once with pal_atomic_exchange, once with a non-atomic exchange
we expect the atomic to pass and the non-atomic to fail
*/
internal_display_test_name( "Atomic exchange" );
lfds700_list_asu_query( list_of_logical_processors, LFDS700_LIST_ASU_QUERY_GET_POTENTIALLY_INACCURATE_COUNT, NULL, (void **) &number_logical_processors );
number_elements = ( memory_in_megabytes * ONE_MEGABYTE_IN_BYTES ) / ( sizeof(lfds700_pal_uint_t) * (number_logical_processors + 1) );
merged_counter_arrays = util_malloc_wrapper( sizeof(lfds700_pal_uint_t) * number_elements );
for( loop = 0 ; loop < number_elements ; loop++ )
*(merged_counter_arrays+loop) = 0;
ts = util_malloc_wrapper( sizeof(struct test_state) * number_logical_processors );
for( loop = 0 ; loop < number_logical_processors ; loop++ )
{
(ts+loop)->counter = loop + 1;
(ts+loop)->counter_array = util_malloc_wrapper( sizeof(lfds700_pal_uint_t) * number_elements );
for( subloop = 0 ; subloop < number_elements ; subloop++ )
*((ts+loop)->counter_array+subloop) = 0;
(ts+loop)->number_logical_processors = number_logical_processors;
(ts+loop)->shared_exchange = &exchange;
(ts+loop)->number_elements = number_elements;
}
exchange = 0;
thread_handles = util_malloc_wrapper( sizeof(test_pal_thread_state_t) * number_logical_processors );
// TRD : non-atomic
util_thread_starter_new( &tts, number_logical_processors );
LFDS700_MISC_BARRIER_STORE;
lfds700_misc_force_store();
loop = 0;
lasue = NULL;
while( LFDS700_LIST_ASU_GET_START_AND_THEN_NEXT(*list_of_logical_processors, lasue) )
{
lp = LFDS700_LIST_ASU_GET_VALUE_FROM_ELEMENT( *lasue );
util_thread_starter_start( tts, &thread_handles[loop], loop, lp, thread_exchange, ts+loop );
loop++;
}
util_thread_starter_run( tts );
for( loop = 0 ; loop < number_logical_processors ; loop++ )
test_pal_thread_wait( thread_handles[loop] );
util_thread_starter_delete( tts );
LFDS700_MISC_BARRIER_LOAD;
for( loop = 0 ; loop < number_elements ; loop++ )
for( subloop = 0 ; subloop < number_logical_processors ; subloop++ )
*(merged_counter_arrays+loop) += *( (ts+subloop)->counter_array+loop );
/* TRD : the worker threads exit when their per-thread counter exceeds 1,000,000
as such the final number_logical_processors numbers are not read
we could change the threads to exit when the number they read exceeds 1,000,000
but then we'd need an if() in their work-loop,
and we need to go as fast as possible
*/
for( loop = 0 ; loop < number_elements - number_logical_processors ; loop++ )
if( *(merged_counter_arrays+loop) != 1 )
exchange_success_flag = LOWERED;
// TRD : now for atomic exchange - we need to re-init the data structures
for( loop = 0 ; loop < number_elements ; loop++ )
*(merged_counter_arrays+loop) = 0;
for( loop = 0 ; loop < number_logical_processors ; loop++ )
for( subloop = 0 ; subloop < number_elements ; subloop++ )
*((ts+loop)->counter_array+subloop) = 0;
exchange = 0;
util_thread_starter_new( &tts, number_logical_processors );
LFDS700_MISC_BARRIER_STORE;
lfds700_misc_force_store();
loop = 0;
lasue = NULL;
while( LFDS700_LIST_ASU_GET_START_AND_THEN_NEXT(*list_of_logical_processors, lasue) )
{
lp = LFDS700_LIST_ASU_GET_VALUE_FROM_ELEMENT( *lasue );
util_thread_starter_start( tts, &thread_handles[loop], loop, lp, thread_atomic_exchange, ts+loop );
loop++;
}
util_thread_starter_run( tts );
for( loop = 0 ; loop < number_logical_processors ; loop++ )
test_pal_thread_wait( thread_handles[loop] );
for( loop = 0 ; loop < number_elements ; loop++ )
for( subloop = 0 ; subloop < number_logical_processors ; subloop++ )
*(merged_counter_arrays+loop) += *( (ts+subloop)->counter_array+loop );
for( loop = 0 ; loop < number_elements - number_logical_processors ; loop++ )
if( *(merged_counter_arrays+loop) != 1 )
atomic_exchange_success_flag = LOWERED;
// TRD : cleanup
free( merged_counter_arrays );
for( loop = 0 ; loop < number_logical_processors ; loop++ )
free( (ts+loop)->counter_array );
util_thread_starter_delete( tts );
free( thread_handles );
free( ts );
/* TRD : results
on a single core, atomic and non-atomic exchange should both work
if we find our non-atomic test passes, then we can't really say anything
about whether or not the atomic test is really working
*/
LFDS700_MISC_BARRIER_LOAD;
if( number_logical_processors == 1 )
{
if( exchange_success_flag == RAISED and atomic_exchange_success_flag == RAISED )
puts( "passed" );
if( exchange_success_flag != RAISED or atomic_exchange_success_flag != RAISED )
puts( "failed (atomic and non-atomic both failed)" );
}
if( number_logical_processors >= 2 )
{
if( atomic_exchange_success_flag == RAISED and exchange_success_flag == LOWERED )
puts( "passed" );
if( atomic_exchange_success_flag == RAISED and exchange_success_flag == RAISED )
puts( "indeterminate (atomic and non-atomic both passed)" );
if( atomic_exchange_success_flag == LOWERED )
{
puts( "failed (atomic failed)" );
exit( EXIT_FAILURE );
}
}
return;
}
/****************************************************************************/
static test_pal_thread_return_t TEST_PAL_CALLING_CONVENTION thread_exchange( void *util_thread_starter_thread_state )
{
lfds700_pal_uint_t
local_counter,
exchange;
struct test_state
*ts;
struct util_thread_starter_thread_state
*tsts;
LFDS700_MISC_BARRIER_LOAD;
assert( util_thread_starter_thread_state != NULL );
tsts = (struct util_thread_starter_thread_state *) util_thread_starter_thread_state;
ts = (struct test_state *) tsts->thread_user_state;
util_thread_starter_ready_and_wait( tsts );
local_counter = ts->counter;
while( local_counter < ts->number_elements )
{
exchange = *ts->shared_exchange;
*ts->shared_exchange = local_counter;
( *(ts->counter_array + exchange) )++;
local_counter += ts->number_logical_processors;
}
LFDS700_MISC_BARRIER_STORE;
lfds700_misc_force_store();
return( (test_pal_thread_return_t) EXIT_SUCCESS );
}
/****************************************************************************/
static test_pal_thread_return_t TEST_PAL_CALLING_CONVENTION thread_atomic_exchange( void *util_thread_starter_thread_state )
{
lfds700_pal_uint_t
local_counter,
exchange;
struct test_state
*ts;
struct util_thread_starter_thread_state
*tsts;
LFDS700_MISC_BARRIER_LOAD;
assert( util_thread_starter_thread_state != NULL );
tsts = (struct util_thread_starter_thread_state *) util_thread_starter_thread_state;
ts = (struct test_state *) tsts->thread_user_state;
util_thread_starter_ready_and_wait( tsts );
local_counter = ts->counter;
while( local_counter < ts->number_elements )
{
exchange = local_counter;
LFDS700_PAL_ATOMIC_EXCHANGE( ts->shared_exchange, &exchange );
( *(ts->counter_array + exchange) )++;
local_counter += ts->number_logical_processors;
}
LFDS700_MISC_BARRIER_STORE;
lfds700_misc_force_store();
return( (test_pal_thread_return_t) EXIT_SUCCESS );
}
/***** includes *****/
#include "internal.h"
/****************************************************************************/
#pragma warning( disable : 4127 ) // TRD : disables MSVC warning for condition expressions being const
void test_lfds700_queue( struct lfds700_list_asu_state *list_of_logical_processors, lfds700_pal_uint_t memory_in_megabytes )
{
assert( list_of_logical_processors != NULL );
// TRD : memory_in_megabytes can be any value in its range
if( LFDS700_MISC_ATOMIC_SUPPORT_DWCAS )
{
printf( "\n"
"Queue Tests\n"
"===========\n" );
test_lfds700_queue_alignment();
test_lfds700_queue_enqueuing( list_of_logical_processors, memory_in_megabytes );
test_lfds700_queue_dequeuing( list_of_logical_processors, memory_in_megabytes );
test_lfds700_queue_enqueuing_and_dequeuing( list_of_logical_processors );
test_lfds700_queue_rapid_enqueuing_and_dequeuing( list_of_logical_processors, memory_in_megabytes );
test_lfds700_queue_enqueuing_and_dequeuing_with_free( list_of_logical_processors, memory_in_megabytes );
test_lfds700_queue_enqueuing_with_malloc_and_dequeuing_with_free( list_of_logical_processors );
}
return;
}
#pragma warning( default : 4127 )
/***** includes *****/
#include "internal.h"
/****************************************************************************/
#pragma warning( disable : 4127 ) // TRD : disables MSVC warning for condition expressions being const
void test_lfds700_queue_alignment()
{
enum lfds700_misc_validity
dvs = LFDS700_MISC_VALIDITY_VALID;
/* TRD : these are compile time checks
but we do them here because this is a test programme
and it should indicate issues to users when it is *run*,
not when it is compiled, because a compile error normally
indicates a problem with the code itself and so is misleading
*/
internal_display_test_name( "Alignment" );
// TRD : struct lfds700_queue_element
if( offsetof(struct lfds700_queue_element,next) % LFDS700_PAL_ATOMIC_ISOLATION_IN_BYTES != 0 )
dvs = LFDS700_MISC_VALIDITY_INVALID_TEST_DATA;
if( offsetof(struct lfds700_queue_element,key) % LFDS700_PAL_ATOMIC_ISOLATION_IN_BYTES != 0 )
dvs = LFDS700_MISC_VALIDITY_INVALID_TEST_DATA;
// TRD : struct lfds700_queue_state
if( offsetof(struct lfds700_queue_state,enqueue) % LFDS700_PAL_ATOMIC_ISOLATION_IN_BYTES != 0 )
dvs = LFDS700_MISC_VALIDITY_INVALID_TEST_DATA;
if( offsetof(struct lfds700_queue_state,dequeue) % LFDS700_PAL_ATOMIC_ISOLATION_IN_BYTES != 0 )
dvs = LFDS700_MISC_VALIDITY_INVALID_TEST_DATA;
if( offsetof(struct lfds700_queue_state,user_state) % LFDS700_PAL_ATOMIC_ISOLATION_IN_BYTES != 0 )
dvs = LFDS700_MISC_VALIDITY_INVALID_TEST_DATA;
// TRD : print the test result
internal_display_test_result( 1, "queue", dvs );
return;
}
#pragma warning( default : 4127 )
/***** includes *****/
#include "internal.h"
/****************************************************************************/
void test_lfds700_queue_bss( struct lfds700_list_asu_state *list_of_logical_processors )
{
assert( list_of_logical_processors != NULL );
// TRD : memory_in_megabytes can be any value in its range
printf( "\n"
"Queue (bounded, single consumer, single producer) Tests\n"
"=======================================================\n" );
// TRD : no alignment checks are required for queue_bss
test_lfds700_queue_bss_enqueuing();
test_lfds700_queue_bss_dequeuing();
test_lfds700_queue_bss_enqueuing_and_dequeuing( list_of_logical_processors );
return;
}
/***** includes *****/
#include "internal.h"
/****************************************************************************/
void test_lfds700_queue_bss_dequeuing()
{
enum lfds700_misc_validity
dvs = LFDS700_MISC_VALIDITY_VALID;
lfds700_pal_uint_t
loop;
struct lfds700_queue_bss_element
element_array[128];
struct lfds700_queue_bss_state
qs;
struct lfds700_misc_validation_info
vi;
void
*value;
/* TRD : create an empty queue
enqueue 128 elements
then dequeue the elements, in the same thread - we're API testing
it's a single producer queue, so we just do this in our current thread
since we're enqueuing and dequeuing in the same thread,
*/
internal_display_test_name( "Dequeuing" );
lfds700_queue_bss_init_valid_on_current_logical_core( &qs, element_array, 128, NULL );
for( loop = 0 ; loop < 127 ; loop++ )
lfds700_queue_bss_enqueue( &qs, NULL, (void *) loop );
for( loop = 0 ; loop < 127 ; loop++ )
{
lfds700_queue_bss_dequeue( &qs, NULL, &value );
if( (lfds700_pal_uint_t) value != 127 - loop )
dvs = LFDS700_MISC_VALIDITY_INVALID_TEST_DATA;
}
vi.min_elements = vi.max_elements = 0;
lfds700_queue_bss_query( &qs, LFDS700_QUEUE_BSS_QUERY_VALIDATE, &vi, &dvs );
lfds700_queue_bss_cleanup( &qs, NULL );
internal_display_test_result( 1, "queue_bss", dvs );
return;
}
/***** includes *****/
#include "internal.h"
/****************************************************************************/
void test_lfds700_queue_bss_enqueuing()
{
enum lfds700_misc_validity
dvs = LFDS700_MISC_VALIDITY_VALID;
int
rv;
lfds700_pal_uint_t
loop;
struct lfds700_queue_bss_element
element_array[128];
struct lfds700_queue_bss_state
qs;
struct lfds700_misc_validation_info
vi;
/* TRD : create an empty queue
enqueue 128 elements
it's a single producer queue, so we just do this in our current thread
it's an API test
*/
internal_display_test_name( "Enqueuing" );
lfds700_queue_bss_init_valid_on_current_logical_core( &qs, element_array, 128, NULL );
for( loop = 0 ; loop < 127 ; loop++ )
if( 1 != lfds700_queue_bss_enqueue(&qs, NULL, (void *) loop) )
dvs = LFDS700_MISC_VALIDITY_INVALID_TEST_DATA;
// TRD : at this point enqueuing one more should return 0
rv = lfds700_queue_bss_enqueue( &qs, NULL, (void *) loop );
if( rv != 0 )
dvs = LFDS700_MISC_VALIDITY_INVALID_TEST_DATA;
vi.min_elements = vi.max_elements = 127;
lfds700_queue_bss_query( &qs, LFDS700_QUEUE_BSS_QUERY_VALIDATE, &vi, &dvs );
lfds700_queue_bss_cleanup( &qs, NULL );
internal_display_test_result( 1, "queue_bss", dvs );
return;
}
/***** includes *****/
#include "internal.h"
/***** structs *****/
struct test_state
{
enum flag
error_flag;
struct lfds700_queue_bss_state
*qs;
};
/***** private prototypes *****/
static test_pal_thread_return_t TEST_PAL_CALLING_CONVENTION thread_enqueuer( void *util_thread_starter_thread_state );
static test_pal_thread_return_t TEST_PAL_CALLING_CONVENTION thread_dequeuer( void *util_thread_starter_thread_state );
/****************************************************************************/
void test_lfds700_queue_bss_enqueuing_and_dequeuing( struct lfds700_list_asu_state *list_of_logical_processors )
{
enum lfds700_misc_validity
dvs = LFDS700_MISC_VALIDITY_VALID;
lfds700_pal_uint_t
loop,
number_logical_processors,
subloop;
struct lfds700_list_asu_element
*lasue;
struct lfds700_queue_bss_element
element_array[4];
struct lfds700_queue_bss_state
qs;
struct test_pal_logical_processor
*lp,
*lp_first;
struct util_thread_starter_state
*tts;
struct test_state
*ts;
test_pal_thread_state_t
*thread_handles;
assert( list_of_logical_processors != NULL );
/* TRD : so, this is the real test
problem is, because we use memory barriers only
and we only support one producer and one consumer
we need to ensure these threads are on different physical cores
if they're on the same core, the code would work even without memory barriers
problem is, in the test application, we only know the *number* of logical cores
obtaining topology information adds a great deal of complexity to the test app
and makes porting much harder
so, we know how many logical cores there are; my thought is to partially
permutate over them - we always run the producer on core 0, but we iterate
over the other logical cores, running the test once each time, with the
consumer being run on core 0, then core 1, then core 2, etc
(we run on core 0 for the single-cpu case; it's redundent, since a single
logical core running both producer and consumer will work, but otherwise
we have to skip the test, which is confusing for the user)
the test is one thread enqueuing and one thread dequeuing for two seconds
*/
lfds700_list_asu_query( list_of_logical_processors, LFDS700_LIST_ASU_QUERY_GET_POTENTIALLY_INACCURATE_COUNT, NULL, (void **) &number_logical_processors );
internal_display_test_name( "Enqueuing and dequeuing (%d seconds)", number_logical_processors * 2 );
ts = util_malloc_wrapper( sizeof(struct test_state) * 2 );
for( loop = 0 ; loop < 2 ; loop++ )
{
(ts+loop)->qs = &qs;
(ts+loop)->error_flag = LOWERED;
}
thread_handles = util_malloc_wrapper( sizeof(test_pal_thread_state_t) * 2 );
/* TRD : producer always on core 0
iterate over the other cores with consumer
*/
lasue = LFDS700_LIST_ASU_GET_START( *list_of_logical_processors );
lp_first = LFDS700_LIST_ASU_GET_VALUE_FROM_ELEMENT( *lasue );
while( lasue != NULL )
{
lp = LFDS700_LIST_ASU_GET_VALUE_FROM_ELEMENT( *lasue );
lfds700_queue_bss_init_valid_on_current_logical_core( &qs, element_array, 4, NULL );
util_thread_starter_new( &tts, 2 );
LFDS700_MISC_BARRIER_STORE;
lfds700_misc_force_store();
util_thread_starter_start( tts, &thread_handles[0], 0, lp_first, thread_enqueuer, ts );
util_thread_starter_start( tts, &thread_handles[1], 1, lp, thread_dequeuer, ts+1 );
util_thread_starter_run( tts );
for( subloop = 0 ; subloop < 2 ; subloop++ )
test_pal_thread_wait( thread_handles[subloop] );
util_thread_starter_delete( tts );
LFDS700_MISC_BARRIER_LOAD;
lfds700_queue_bss_cleanup( &qs, NULL );
lasue = LFDS700_LIST_ASU_GET_NEXT( *lasue );
}
if( (ts+1)->error_flag == RAISED )
dvs = LFDS700_MISC_VALIDITY_INVALID_TEST_DATA;
free( thread_handles );
free( ts );
internal_display_test_result( 1, "queue_bss", dvs );
return;
}
/****************************************************************************/
static test_pal_thread_return_t TEST_PAL_CALLING_CONVENTION thread_enqueuer( void *util_thread_starter_thread_state )
{
int
rv;
lfds700_pal_uint_t
datum = 0,
time_loop = 0;
struct test_state
*ts;
struct util_thread_starter_thread_state
*tsts;
time_t
current_time,
start_time;
LFDS700_MISC_MAKE_VALID_ON_CURRENT_LOGICAL_CORE_INITS_COMPLETED_BEFORE_NOW_ON_ANY_OTHER_LOGICAL_CORE;
assert( util_thread_starter_thread_state != NULL );
tsts = (struct util_thread_starter_thread_state *) util_thread_starter_thread_state;
ts = (struct test_state *) tsts->thread_user_state;
util_thread_starter_ready_and_wait( tsts );
current_time = start_time = time( NULL );
while( current_time < start_time + 2 )
{
rv = lfds700_queue_bss_enqueue( ts->qs, NULL, (void *) datum );
if( rv == 1 )
if( ++datum == 4 )
datum = 0;
if( time_loop++ == TIME_LOOP_COUNT )
{
time_loop = 0;
time( &current_time );
}
}
LFDS700_MISC_BARRIER_STORE;
lfds700_misc_force_store();
return( (test_pal_thread_return_t) EXIT_SUCCESS );
}
/****************************************************************************/
static test_pal_thread_return_t TEST_PAL_CALLING_CONVENTION thread_dequeuer( void *util_thread_starter_thread_state )
{
int
rv;
lfds700_pal_uint_t
datum,
expected_datum = 0,
time_loop = 0;
struct test_state
*ts;
struct util_thread_starter_thread_state
*tsts;
time_t
current_time,
start_time;
LFDS700_MISC_BARRIER_LOAD;
assert( util_thread_starter_thread_state != NULL );
tsts = (struct util_thread_starter_thread_state *) util_thread_starter_thread_state;
ts = (struct test_state *) tsts->thread_user_state;
util_thread_starter_ready_and_wait( tsts );
current_time = start_time = time( NULL );
while( current_time < start_time + 2 )
{
rv = lfds700_queue_bss_dequeue( ts->qs, NULL, (void *) &datum );
if( rv == 1 )
{
if( datum != expected_datum )
ts->error_flag = RAISED;
if( ++expected_datum == 4 )
expected_datum = 0;
}
if( time_loop++ == TIME_LOOP_COUNT )
{
time_loop = 0;
time( &current_time );
}
}
LFDS700_MISC_BARRIER_STORE;
lfds700_misc_force_store();
return( (test_pal_thread_return_t) EXIT_SUCCESS );
}
/***** includes *****/
#include "internal.h"
/***** structs *****/
struct test_state
{
enum flag
error_flag;
struct lfds700_queue_state
*qs;
};
struct test_element
{
struct lfds700_queue_element
qe;
};
/***** private prototypes *****/
static test_pal_thread_return_t TEST_PAL_CALLING_CONVENTION thread_simple_dequeuer( void *util_thread_starter_thread_state );
/****************************************************************************/
void test_lfds700_queue_dequeuing( struct lfds700_list_asu_state *list_of_logical_processors, lfds700_pal_uint_t memory_in_megabytes )
{
enum lfds700_misc_validity
dvs = LFDS700_MISC_VALIDITY_VALID;
lfds700_pal_uint_t
loop,
number_elements_with_dummy_element,
number_elements_without_dummy_element,
number_logical_processors;
struct lfds700_list_asu_element
*lasue;
struct lfds700_misc_prng_state
ps;
struct lfds700_queue_state
qs;
struct lfds700_misc_validation_info
vi = { 0, 0 };
struct test_pal_logical_processor
*lp;
struct util_thread_starter_state
*tts;
struct test_element
*te_array;
struct test_state
*ts;
test_pal_thread_state_t
*thread_handles;
assert( list_of_logical_processors != NULL );
// TRD : memory_in_megabytes can be any value in its range
/* TRD : create a queue, add 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 dequeued is greater than the element previously dequeued
note we have no variation in the test for CAS+GC vs DWCAS
this is because all we do is dequeue
what we actually want to stress test is the queue
not CAS
so it's better to let the dequeue run as fast as possible
*/
internal_display_test_name( "Dequeuing" );
lfds700_list_asu_query( list_of_logical_processors, LFDS700_LIST_ASU_QUERY_GET_POTENTIALLY_INACCURATE_COUNT, NULL, (void **) &number_logical_processors );
lfds700_misc_prng_init( &ps );
number_elements_with_dummy_element = ( memory_in_megabytes * ONE_MEGABYTE_IN_BYTES ) / sizeof(struct test_element);
number_elements_without_dummy_element = number_elements_with_dummy_element - 1;
te_array = util_aligned_malloc( sizeof(struct test_element) * number_elements_with_dummy_element, LFDS700_PAL_ATOMIC_ISOLATION_IN_BYTES );
lfds700_queue_init_valid_on_current_logical_core( &qs, &(te_array + number_elements_without_dummy_element)->qe, &ps, NULL );
for( loop = 0 ; loop < number_elements_without_dummy_element ; loop++ )
{
LFDS700_QUEUE_SET_VALUE_IN_ELEMENT( (te_array+loop)->qe, loop );
lfds700_queue_enqueue( &qs, &(te_array+loop)->qe, &ps );
}
ts = util_malloc_wrapper( sizeof(struct test_state) * number_logical_processors );
for( loop = 0 ; loop < number_logical_processors ; loop++ )
{
(ts+loop)->qs = &qs;
(ts+loop)->error_flag = LOWERED;
}
thread_handles = util_malloc_wrapper( sizeof(test_pal_thread_state_t) * number_logical_processors );
util_thread_starter_new( &tts, number_logical_processors );
LFDS700_MISC_BARRIER_STORE;
lfds700_misc_force_store();
loop = 0;
lasue = NULL;
while( LFDS700_LIST_ASU_GET_START_AND_THEN_NEXT(*list_of_logical_processors, lasue) )
{
lp = LFDS700_LIST_ASU_GET_VALUE_FROM_ELEMENT( *lasue );
util_thread_starter_start( tts, &thread_handles[loop], loop, lp, thread_simple_dequeuer, ts+loop );
loop++;
}
util_thread_starter_run( tts );
for( loop = 0 ; loop < number_logical_processors ; loop++ )
test_pal_thread_wait( thread_handles[loop] );
util_thread_starter_delete( tts );
free( thread_handles );
LFDS700_MISC_BARRIER_LOAD;
// TRD : check queue is empty
lfds700_queue_query( &qs, LFDS700_QUEUE_QUERY_SINGLETHREADED_VALIDATE, &vi, &dvs );
// TRD : check for raised error flags
for( loop = 0 ; loop < number_logical_processors ; loop++ )
if( (ts+loop)->error_flag == RAISED )
dvs = LFDS700_MISC_VALIDITY_INVALID_TEST_DATA;
free( ts );
util_aligned_free( te_array );
lfds700_queue_cleanup( &qs, NULL );
internal_display_test_result( 1, "queue", dvs );
return;
}
/****************************************************************************/
static test_pal_thread_return_t TEST_PAL_CALLING_CONVENTION thread_simple_dequeuer( void *util_thread_starter_thread_state )
{
lfds700_pal_uint_t
*prev_value,
*value;
struct lfds700_misc_prng_state
ps;
struct lfds700_queue_element
*qe;
struct test_state
*ts;
struct util_thread_starter_thread_state
*tsts;
LFDS700_MISC_MAKE_VALID_ON_CURRENT_LOGICAL_CORE_INITS_COMPLETED_BEFORE_NOW_ON_ANY_OTHER_LOGICAL_CORE;
assert( util_thread_starter_thread_state != NULL );
tsts = (struct util_thread_starter_thread_state *) util_thread_starter_thread_state;
ts = (struct test_state *) tsts->thread_user_state;
lfds700_misc_prng_init( &ps );
lfds700_queue_dequeue( ts->qs, &qe, &ps );
prev_value = LFDS700_QUEUE_GET_VALUE_FROM_ELEMENT( *qe );
util_thread_starter_ready_and_wait( tsts );
while( lfds700_queue_dequeue(ts->qs, &qe, &ps) )
{
value = LFDS700_QUEUE_GET_VALUE_FROM_ELEMENT( *qe );
if( value <= prev_value )
ts->error_flag = RAISED;
prev_value = value;
}
LFDS700_MISC_BARRIER_STORE;
lfds700_misc_force_store();
return( (test_pal_thread_return_t) EXIT_SUCCESS );
}
/***** includes *****/
#include "internal.h"
/***** structs *****/
struct test_state
{
lfds700_pal_uint_t
number_elements,
thread_number;
struct lfds700_queue_state
*qs;
struct test_element
*te_array;
};
struct test_element
{
struct lfds700_queue_element
qe;
lfds700_pal_uint_t
counter,
thread_number;
};
/***** private prototypes *****/
static test_pal_thread_return_t TEST_PAL_CALLING_CONVENTION thread_simple_enqueuer( void *util_thread_starter_thread_state );
/****************************************************************************/
void test_lfds700_queue_enqueuing( struct lfds700_list_asu_state *list_of_logical_processors, lfds700_pal_uint_t memory_in_megabytes )
{
enum lfds700_misc_validity
dvs = LFDS700_MISC_VALIDITY_VALID;
lfds700_pal_uint_t
*per_thread_counters,
loop,
number_elements,
number_logical_processors;
struct lfds700_list_asu_element
*lasue;
struct lfds700_misc_prng_state
ps;
struct lfds700_queue_element
dummy_qe,
*qe;
struct lfds700_queue_state
qs;
struct lfds700_misc_validation_info
vi;
struct test_pal_logical_processor
*lp;
struct util_thread_starter_state
*tts;
struct test_element
*te;
struct test_state
*ts;
test_pal_thread_state_t
*thread_handles;
assert( list_of_logical_processors != NULL );
// TRD : memory_in_megabytes can be any value in its range
/* TRD : create an empty queue
then run one thread per CPU
where each thread busy-works, enqueuing elements from a freelist (one local freelist per thread)
until 100000 elements are enqueued, per thread
each element's void pointer of user data is a struct containing thread number and element number
where element_number is a thread-local counter starting at 0
when we're done, we check that all the elements are present
and increment on a per-thread basis
*/
internal_display_test_name( "Enqueuing" );
lfds700_list_asu_query( list_of_logical_processors, LFDS700_LIST_ASU_QUERY_GET_POTENTIALLY_INACCURATE_COUNT, NULL, (void **) &number_logical_processors );
lfds700_misc_prng_init( &ps );
number_elements = ( memory_in_megabytes * ONE_MEGABYTE_IN_BYTES ) / ( sizeof(struct test_element) * number_logical_processors );
lfds700_queue_init_valid_on_current_logical_core( &qs, &dummy_qe, &ps, NULL );
ts = util_malloc_wrapper( sizeof(struct test_state) * number_logical_processors );
for( loop = 0 ; loop < number_logical_processors ; loop++ )
{
(ts+loop)->qs = &qs;
(ts+loop)->thread_number = loop;
(ts+loop)->number_elements = number_elements;
}
thread_handles = util_malloc_wrapper( sizeof(test_pal_thread_state_t) * number_logical_processors );
util_thread_starter_new( &tts, number_logical_processors );
LFDS700_MISC_BARRIER_STORE;
lfds700_misc_force_store();
loop = 0;
lasue = NULL;
while( LFDS700_LIST_ASU_GET_START_AND_THEN_NEXT(*list_of_logical_processors, lasue) )
{
lp = LFDS700_LIST_ASU_GET_VALUE_FROM_ELEMENT( *lasue );
util_thread_starter_start( tts, &thread_handles[loop], loop, lp, thread_simple_enqueuer, ts+loop );
loop++;
}
util_thread_starter_run( tts );
for( loop = 0 ; loop < number_logical_processors ; loop++ )
test_pal_thread_wait( thread_handles[loop] );
util_thread_starter_delete( tts );
free( thread_handles );
LFDS700_MISC_BARRIER_LOAD;
/* TRD : first, validate the queue
then dequeue
we expect to find element numbers increment on a per thread basis
*/
vi.min_elements = vi.max_elements = number_elements * number_logical_processors;
lfds700_queue_query( &qs, LFDS700_QUEUE_QUERY_SINGLETHREADED_VALIDATE, &vi, &dvs );
per_thread_counters = util_malloc_wrapper( sizeof(lfds700_pal_uint_t) * number_logical_processors );
for( loop = 0 ; loop < number_logical_processors ; loop++ )
*(per_thread_counters+loop) = 0;
while( dvs == LFDS700_MISC_VALIDITY_VALID and lfds700_queue_dequeue(&qs, &qe, &ps) )
{
te = LFDS700_QUEUE_GET_VALUE_FROM_ELEMENT( *qe );
if( te->thread_number >= number_logical_processors )
{
dvs = LFDS700_MISC_VALIDITY_INVALID_TEST_DATA;
break;
}
if( te->counter > per_thread_counters[te->thread_number] )
dvs = LFDS700_MISC_VALIDITY_INVALID_MISSING_ELEMENTS;
if( te->counter < per_thread_counters[te->thread_number] )
dvs = LFDS700_MISC_VALIDITY_INVALID_ADDITIONAL_ELEMENTS;
if( te->counter == per_thread_counters[te->thread_number] )
per_thread_counters[te->thread_number]++;
}
free( per_thread_counters );
for( loop = 0 ; loop < number_logical_processors ; loop++ )
util_aligned_free( (ts+loop)->te_array );
free( ts );
lfds700_queue_cleanup( &qs, NULL );
internal_display_test_result( 1, "queue", dvs );
return;
}
/****************************************************************************/
static test_pal_thread_return_t TEST_PAL_CALLING_CONVENTION thread_simple_enqueuer( void *util_thread_starter_thread_state )
{
lfds700_pal_uint_t
loop;
struct lfds700_misc_prng_state
ps;
struct test_state
*ts;
struct util_thread_starter_thread_state
*tsts;
LFDS700_MISC_MAKE_VALID_ON_CURRENT_LOGICAL_CORE_INITS_COMPLETED_BEFORE_NOW_ON_ANY_OTHER_LOGICAL_CORE;
assert( util_thread_starter_thread_state != NULL );
tsts = (struct util_thread_starter_thread_state *) util_thread_starter_thread_state;
ts = (struct test_state *) tsts->thread_user_state;
lfds700_misc_prng_init( &ps );
ts->te_array = util_aligned_malloc( sizeof(struct test_element) * ts->number_elements, LFDS700_PAL_ATOMIC_ISOLATION_IN_BYTES );
for( loop = 0 ; loop < ts->number_elements ; loop++ )
{
(ts->te_array+loop)->thread_number = ts->thread_number;
(ts->te_array+loop)->counter = loop;
}
util_thread_starter_ready_and_wait( tsts );
for( loop = 0 ; loop < ts->number_elements ; loop++ )
{
LFDS700_QUEUE_SET_VALUE_IN_ELEMENT( (ts->te_array+loop)->qe, ts->te_array+loop );
lfds700_queue_enqueue( ts->qs, &(ts->te_array+loop)->qe, &ps );
}
LFDS700_MISC_BARRIER_STORE;
lfds700_misc_force_store();
return( (test_pal_thread_return_t) EXIT_SUCCESS );
}
/***** includes *****/
#include "internal.h"
/***** structs *****/
struct test_state
{
enum flag
error_flag;
lfds700_pal_uint_t
counter,
number_logical_processors,
*per_thread_counters,
thread_number;
struct lfds700_queue_state
*qs;
};
struct test_element
{
struct lfds700_queue_element
qe,
*qe_use;
lfds700_pal_uint_t
counter,
thread_number;
};
/***** private prototypes *****/
static test_pal_thread_return_t TEST_PAL_CALLING_CONVENTION thread_enqueuer_and_dequeuer( void *util_thread_starter_thread_state );
/****************************************************************************/
void test_lfds700_queue_enqueuing_and_dequeuing( struct lfds700_list_asu_state *list_of_logical_processors )
{
enum lfds700_misc_validity
dvs = LFDS700_MISC_VALIDITY_VALID;
lfds700_pal_uint_t
loop,
number_logical_processors,
subloop;
struct lfds700_list_asu_element
*lasue;
struct lfds700_misc_prng_state
ps;
struct lfds700_queue_state
qs;
struct lfds700_misc_validation_info
vi;
struct test_pal_logical_processor
*lp;
struct util_thread_starter_state
*tts;
struct test_element
*te_array;
struct test_state
*ts;
test_pal_thread_state_t
*thread_handles;
assert( list_of_logical_processors != NULL );
// TRD : qt can be any value in its range
/* TRD : create a queue with one element per thread
each thread constly dequeues and enqueues from that one queue
where when enqueuing sets in the element
its thread number and counter
and when dequeuing, checks the thread number and counter
against previously seen counter for that thread
where it should always see a higher number
*/
internal_display_test_name( "Enqueuing and dequeuing (%d seconds)", TEST_DURATION_IN_SECONDS );
lfds700_list_asu_query( list_of_logical_processors, LFDS700_LIST_ASU_QUERY_GET_POTENTIALLY_INACCURATE_COUNT, NULL, (void **) &number_logical_processors );
lfds700_misc_prng_init( &ps );
te_array = util_aligned_malloc( sizeof(struct test_element) * (number_logical_processors+1), LFDS700_PAL_ATOMIC_ISOLATION_IN_BYTES );
lfds700_queue_init_valid_on_current_logical_core( &qs, &(te_array+number_logical_processors)->qe, &ps, NULL );
// TRD : we assume the test will iterate at least once (or we'll have a false negative)
for( loop = 0 ; loop < number_logical_processors ; loop++ )
{
(te_array+loop)->thread_number = loop;
(te_array+loop)->counter = 0;
LFDS700_QUEUE_SET_VALUE_IN_ELEMENT( (te_array+loop)->qe, te_array+loop );
lfds700_queue_enqueue( &qs, &(te_array+loop)->qe, &ps );
}
ts = util_malloc_wrapper( sizeof(struct test_state) * number_logical_processors );
for( loop = 0 ; loop < number_logical_processors ; loop++ )
{
(ts+loop)->qs = &qs;
(ts+loop)->thread_number = loop;
(ts+loop)->counter = 0;
(ts+loop)->error_flag = LOWERED;
(ts+loop)->per_thread_counters = util_malloc_wrapper( sizeof(lfds700_pal_uint_t) * number_logical_processors );
(ts+loop)->number_logical_processors = number_logical_processors;
for( subloop = 0 ; subloop < number_logical_processors ; subloop++ )
*((ts+loop)->per_thread_counters+subloop) = 0;
}
thread_handles = util_malloc_wrapper( sizeof(test_pal_thread_state_t) * number_logical_processors );
util_thread_starter_new( &tts, number_logical_processors );
LFDS700_MISC_BARRIER_STORE;
lfds700_misc_force_store();
loop = 0;
lasue = NULL;
while( LFDS700_LIST_ASU_GET_START_AND_THEN_NEXT(*list_of_logical_processors, lasue) )
{
lp = LFDS700_LIST_ASU_GET_VALUE_FROM_ELEMENT( *lasue );
util_thread_starter_start( tts, &thread_handles[loop], loop, lp, thread_enqueuer_and_dequeuer, ts+loop );
loop++;
}
util_thread_starter_run( tts );
for( loop = 0 ; loop < number_logical_processors ; loop++ )
test_pal_thread_wait( thread_handles[loop] );
util_thread_starter_delete( tts );
free( thread_handles );
LFDS700_MISC_BARRIER_LOAD;
vi.min_elements = vi.max_elements = number_logical_processors;
lfds700_queue_query( &qs, LFDS700_QUEUE_QUERY_SINGLETHREADED_VALIDATE, &vi, &dvs );
for( loop = 0 ; loop < number_logical_processors ; loop++ )
if( (ts+loop)->error_flag == RAISED )
dvs = LFDS700_MISC_VALIDITY_INVALID_TEST_DATA;
for( loop = 0 ; loop < number_logical_processors ; loop++ )
free( (ts+loop)->per_thread_counters );
util_aligned_free( te_array );
free( ts );
lfds700_queue_cleanup( &qs, NULL );
internal_display_test_result( 1, "queue", dvs );
return;
}
/****************************************************************************/
static test_pal_thread_return_t TEST_PAL_CALLING_CONVENTION thread_enqueuer_and_dequeuer( void *util_thread_starter_thread_state )
{
lfds700_pal_uint_t
time_loop = 0;
struct lfds700_misc_prng_state
ps;
struct lfds700_queue_element
*qe;
struct test_element
*te;
struct test_state
*ts;
struct util_thread_starter_thread_state
*tsts;
time_t
current_time,
start_time;
LFDS700_MISC_MAKE_VALID_ON_CURRENT_LOGICAL_CORE_INITS_COMPLETED_BEFORE_NOW_ON_ANY_OTHER_LOGICAL_CORE;
assert( util_thread_starter_thread_state != NULL );
tsts = (struct util_thread_starter_thread_state *) util_thread_starter_thread_state;
ts = (struct test_state *) tsts->thread_user_state;
lfds700_misc_prng_init( &ps );
util_thread_starter_ready_and_wait( tsts );
current_time = start_time = time( NULL );
while( current_time < start_time + TEST_DURATION_IN_SECONDS )
{
lfds700_queue_dequeue( ts->qs, &qe, &ps );
te = LFDS700_QUEUE_GET_VALUE_FROM_ELEMENT( *qe );
if( te->thread_number >= ts->number_logical_processors )
ts->error_flag = RAISED;
else
{
if( te->counter < ts->per_thread_counters[te->thread_number] )
ts->error_flag = RAISED;
if( te->counter >= ts->per_thread_counters[te->thread_number] )
ts->per_thread_counters[te->thread_number] = te->counter+1;
}
te->thread_number = ts->thread_number;
te->counter = ++ts->counter;
LFDS700_QUEUE_SET_VALUE_IN_ELEMENT( *qe, te );
lfds700_queue_enqueue( ts->qs, qe, &ps );
if( time_loop++ == TIME_LOOP_COUNT )
{
time_loop = 0;
time( &current_time );
}
}
LFDS700_MISC_BARRIER_STORE;
lfds700_misc_force_store();
return( (test_pal_thread_return_t) EXIT_SUCCESS );
}
/***** includes *****/
#include "internal.h"
/***** structs *****/
struct test_state
{
lfds700_pal_uint_t
number_of_elements_per_thread;
struct lfds700_queue_state
*qs;
};
/***** private prototypes *****/
static test_pal_thread_return_t TEST_PAL_CALLING_CONVENTION thread_enqueue_dequeuer_with_free( void *util_thread_starter_thread_state );
static void queue_element_cleanup_callback( struct lfds700_queue_state *qs, struct lfds700_queue_element *qe, enum lfds700_misc_flag dummy_element_flag );
/****************************************************************************/
void test_lfds700_queue_enqueuing_and_dequeuing_with_free( struct lfds700_list_asu_state *list_of_logical_processors, lfds700_pal_uint_t memory_in_megabytes )
{
enum lfds700_misc_validity
dvs = LFDS700_MISC_VALIDITY_VALID;
lfds700_pal_uint_t
loop,
number_elements,
number_logical_processors,
number_of_elements_per_thread;
struct lfds700_list_asu_element
*lasue;
struct lfds700_misc_prng_state
ps;
struct lfds700_queue_element
*qe;
struct lfds700_queue_state
qs;
struct lfds700_misc_validation_info
vi;
struct test_pal_logical_processor
*lp;
struct test_state
*ts;
struct util_thread_starter_state
*tts;
test_pal_thread_state_t
*thread_handles;
assert( list_of_logical_processors != NULL );
// TRD : memory_in_megabytes can be any value in its range
/* TRD : the M&Q queue supports free()ing queue elements after they've been dequeued
we need to test this
we spawn one thread per logical core
there's one master queue which all threads work on
we create one freelist per thread
and allocate as many queue elements as we can (no payload)
- but note each allocate is its own malloc()
each freelist receives an equal share (i.e. we get the mallocs out of the way)
each thread enqueues as rapidly as possible
and dequeues as rapidly as possible
(i.e. each thread loops, doing an enqueue and a dequeue)
when the dequeue is done, the element is free()ed
*/
internal_display_test_name( "Enqueuing and dequeuing with free" );
lfds700_list_asu_query( list_of_logical_processors, LFDS700_LIST_ASU_QUERY_GET_POTENTIALLY_INACCURATE_COUNT, NULL, (void **) &number_logical_processors );
lfds700_misc_prng_init( &ps );
number_elements = ( memory_in_megabytes * ONE_MEGABYTE_IN_BYTES ) / ( sizeof(struct lfds700_freelist_element) + sizeof(struct lfds700_queue_element) );
number_of_elements_per_thread = number_elements / number_logical_processors;
qe = util_aligned_malloc( sizeof(struct lfds700_queue_element), (lfds700_pal_uint_t) LFDS700_PAL_ATOMIC_ISOLATION_IN_BYTES );
lfds700_queue_init_valid_on_current_logical_core( &qs, qe, &ps, NULL );
ts = util_malloc_wrapper( sizeof(struct test_state) * number_logical_processors );
for( loop = 0 ; loop < number_logical_processors ; loop++ )
{
(ts+loop)->qs = &qs;
(ts+loop)->number_of_elements_per_thread = number_of_elements_per_thread;
}
thread_handles = util_malloc_wrapper( sizeof(test_pal_thread_state_t) * number_logical_processors );
util_thread_starter_new( &tts, number_logical_processors );
LFDS700_MISC_BARRIER_STORE;
lfds700_misc_force_store();
loop = 0;
lasue = NULL;
while( LFDS700_LIST_ASU_GET_START_AND_THEN_NEXT(*list_of_logical_processors, lasue) )
{
lp = LFDS700_LIST_ASU_GET_VALUE_FROM_ELEMENT( *lasue );
util_thread_starter_start( tts, &thread_handles[loop], loop, lp, thread_enqueue_dequeuer_with_free, ts+loop );
loop++;
}
util_thread_starter_run( tts );
for( loop = 0 ; loop < number_logical_processors ; loop++ )
test_pal_thread_wait( thread_handles[loop] );
util_thread_starter_delete( tts );
free( thread_handles );
LFDS700_MISC_BARRIER_LOAD;
vi.min_elements = 0;
vi.max_elements = 0;
lfds700_queue_query( &qs, LFDS700_QUEUE_QUERY_SINGLETHREADED_VALIDATE, &vi, &dvs );
lfds700_queue_cleanup( &qs, queue_element_cleanup_callback );
free( ts );
internal_display_test_result( 1, "queue", dvs );
return;
}
/****************************************************************************/
static test_pal_thread_return_t TEST_PAL_CALLING_CONVENTION thread_enqueue_dequeuer_with_free( void *util_thread_starter_thread_state )
{
enum flag
finished_flag = LOWERED;
lfds700_pal_uint_t
loop;
struct lfds700_misc_prng_state
ps;
struct lfds700_freelist_element
*fe,
*fe_array;
struct lfds700_freelist_state
fs;
struct lfds700_queue_element
*qe;
struct test_state
*ts;
struct util_thread_starter_thread_state
*tsts;
LFDS700_MISC_MAKE_VALID_ON_CURRENT_LOGICAL_CORE_INITS_COMPLETED_BEFORE_NOW_ON_ANY_OTHER_LOGICAL_CORE;
assert( util_thread_starter_thread_state != NULL );
tsts = (struct util_thread_starter_thread_state *) util_thread_starter_thread_state;
ts = (struct test_state *) tsts->thread_user_state;
lfds700_misc_prng_init( &ps );
lfds700_freelist_init_valid_on_current_logical_core( &fs, NULL );
fe_array = util_malloc_wrapper( sizeof(struct lfds700_freelist_element) * ts->number_of_elements_per_thread );
for( loop = 0 ; loop < ts->number_of_elements_per_thread ; loop++ )
{
qe = util_aligned_malloc( sizeof(struct lfds700_queue_element), LFDS700_PAL_ATOMIC_ISOLATION_IN_BYTES );
LFDS700_FREELIST_SET_VALUE_IN_ELEMENT( fe_array[loop], qe );
lfds700_freelist_push( &fs, &fe_array[loop], &ps );
}
util_thread_starter_ready_and_wait( tsts );
while( finished_flag == LOWERED )
{
loop = 0;
while( loop++ < 1000 and lfds700_freelist_pop(&fs, &fe, &ps) )
{
qe = LFDS700_FREELIST_GET_VALUE_FROM_ELEMENT( *fe );
lfds700_queue_enqueue( ts->qs, qe, &ps );
}
if( loop < 1000 )
finished_flag = RAISED;
loop = 0;
while( loop++ < 1000 and lfds700_queue_dequeue(ts->qs, &qe, &ps) )
util_aligned_free( qe );
}
LFDS700_MISC_BARRIER_STORE;
lfds700_misc_force_store();
lfds700_freelist_cleanup( &fs, NULL );
free( fe_array );
return( (test_pal_thread_return_t) EXIT_SUCCESS );
}
/****************************************************************************/
#pragma warning( disable : 4100 )
static void queue_element_cleanup_callback( struct lfds700_queue_state *qs, struct lfds700_queue_element *qe, enum lfds700_misc_flag dummy_element_flag )
{
assert( qs != NULL );
assert( qe != NULL );
// TRD : dummy_element_flag can be any value in its range
util_aligned_free( qe );
return;
}
#pragma warning( default : 4100 )
/***** includes *****/
#include "internal.h"
/***** structs *****/
struct test_state
{
struct lfds700_queue_state
*qs;
};
/***** private prototypes *****/
static test_pal_thread_return_t TEST_PAL_CALLING_CONVENTION thread_enqueuer_with_malloc_and_dequeuer_with_free( void *util_thread_starter_thread_state );
static void queue_element_cleanup_callback( struct lfds700_queue_state *qs, struct lfds700_queue_element *qe, enum lfds700_misc_flag dummy_element_flag );
/****************************************************************************/
void test_lfds700_queue_enqueuing_with_malloc_and_dequeuing_with_free( struct lfds700_list_asu_state *list_of_logical_processors )
{
enum lfds700_misc_validity
dvs = LFDS700_MISC_VALIDITY_VALID;
lfds700_pal_uint_t
loop,
number_logical_processors;
struct lfds700_list_asu_element
*lasue;
struct lfds700_misc_prng_state
ps;
struct lfds700_queue_element
*qe;
struct lfds700_queue_state
qs;
struct lfds700_misc_validation_info
vi;
struct test_pal_logical_processor
*lp;
struct util_thread_starter_state
*tts;
struct test_state
*ts;
test_pal_thread_state_t
*thread_handles;
assert( list_of_logical_processors != NULL );
// TRD : qt can be any value in its range
/* TRD : one thread per logical core
each thread loops for ten seconds
mallocs and enqueues 1k elements, then dequeues and frees 1k elements
*/
internal_display_test_name( "Enqueuing with malloc dequeuing with free (%d seconds)", TEST_DURATION_IN_SECONDS );
lfds700_list_asu_query( list_of_logical_processors, LFDS700_LIST_ASU_QUERY_GET_POTENTIALLY_INACCURATE_COUNT, NULL, (void **) &number_logical_processors );
lfds700_misc_prng_init( &ps );
qe = util_aligned_malloc( sizeof(struct lfds700_queue_element), LFDS700_PAL_ATOMIC_ISOLATION_IN_BYTES );
lfds700_queue_init_valid_on_current_logical_core( &qs, qe, &ps, NULL );
ts = util_malloc_wrapper( sizeof(struct test_state) * number_logical_processors );
for( loop = 0 ; loop < number_logical_processors ; loop++ )
(ts+loop)->qs = &qs;
thread_handles = util_malloc_wrapper( sizeof(test_pal_thread_state_t) * number_logical_processors );
util_thread_starter_new( &tts, number_logical_processors );
LFDS700_MISC_BARRIER_STORE;
lfds700_misc_force_store();
loop = 0;
lasue = NULL;
while( LFDS700_LIST_ASU_GET_START_AND_THEN_NEXT(*list_of_logical_processors, lasue) )
{
lp = LFDS700_LIST_ASU_GET_VALUE_FROM_ELEMENT( *lasue );
util_thread_starter_start( tts, &thread_handles[loop], loop, lp, thread_enqueuer_with_malloc_and_dequeuer_with_free, ts+loop );
loop++;
}
util_thread_starter_run( tts );
for( loop = 0 ; loop < number_logical_processors ; loop++ )
test_pal_thread_wait( thread_handles[loop] );
util_thread_starter_delete( tts );
free( thread_handles );
LFDS700_MISC_BARRIER_LOAD;
vi.min_elements = vi.max_elements = 0;
lfds700_queue_query( &qs, LFDS700_QUEUE_QUERY_SINGLETHREADED_VALIDATE, &vi, &dvs );
free( ts );
lfds700_queue_cleanup( &qs, queue_element_cleanup_callback );
internal_display_test_result( 1, "queue", dvs );
return;
}
/****************************************************************************/
static test_pal_thread_return_t TEST_PAL_CALLING_CONVENTION thread_enqueuer_with_malloc_and_dequeuer_with_free( void *util_thread_starter_thread_state )
{
lfds700_pal_uint_t
loop,
time_loop = 0;
struct lfds700_misc_prng_state
ps;
struct lfds700_queue_element
*qe;
struct test_state
*ts;
struct util_thread_starter_thread_state
*tsts;
time_t
current_time,
start_time;
LFDS700_MISC_MAKE_VALID_ON_CURRENT_LOGICAL_CORE_INITS_COMPLETED_BEFORE_NOW_ON_ANY_OTHER_LOGICAL_CORE;
assert( util_thread_starter_thread_state != NULL );
tsts = (struct util_thread_starter_thread_state *) util_thread_starter_thread_state;
ts = (struct test_state *) tsts->thread_user_state;
lfds700_misc_prng_init( &ps );
util_thread_starter_ready_and_wait( tsts );
current_time = start_time = time( NULL );
while( current_time < start_time + TEST_DURATION_IN_SECONDS )
{
for( loop = 0 ; loop < 1000 ; loop++ )
{
qe = util_aligned_malloc( sizeof(struct lfds700_queue_element), LFDS700_PAL_ATOMIC_ISOLATION_IN_BYTES );
lfds700_queue_enqueue( ts->qs, qe, &ps );
}
for( loop = 0 ; loop < 1000 ; loop++ )
{
lfds700_queue_dequeue( ts->qs, &qe, &ps );
util_aligned_free( qe );
}
if( time_loop++ == REDUCED_TIME_LOOP_COUNT )
{
time_loop = 0;
time( &current_time );
}
}
LFDS700_MISC_BARRIER_STORE;
lfds700_misc_force_store();
return( (test_pal_thread_return_t) EXIT_SUCCESS );
}
/****************************************************************************/
#pragma warning( disable : 4100 )
static void queue_element_cleanup_callback( struct lfds700_queue_state *qs, struct lfds700_queue_element *qe, enum lfds700_misc_flag dummy_element_flag )
{
assert( qs != NULL );
assert( qe != NULL );
// TRD : dummy_element_flag can be any value in its range
util_aligned_free( qe );
return;
}
#pragma warning( default : 4100 )
/***** includes *****/
#include "internal.h"
/***** structs *****/
struct test_state
{
lfds700_pal_uint_t
counter,
thread_number;
struct lfds700_queue_state
*qs;
};
struct test_element
{
struct lfds700_queue_element
qe,
*qe_use;
lfds700_pal_uint_t
counter,
thread_number;
};
/***** private prototypes *****/
static test_pal_thread_return_t TEST_PAL_CALLING_CONVENTION thread_rapid_enqueuer_and_dequeuer( void *util_thread_starter_thread_state );
/****************************************************************************/
void test_lfds700_queue_rapid_enqueuing_and_dequeuing( struct lfds700_list_asu_state *list_of_logical_processors, lfds700_pal_uint_t memory_in_megabytes )
{
enum lfds700_misc_validity
dvs = LFDS700_MISC_VALIDITY_VALID;
lfds700_pal_uint_t
loop,
number_elements_with_dummy_element,
number_elements_without_dummy_element,
number_logical_processors,
*per_thread_counters;
struct lfds700_list_asu_element
*lasue;
struct lfds700_misc_prng_state
ps;
struct lfds700_queue_element
*qe;
struct lfds700_misc_validation_info
vi;
struct lfds700_queue_state
qs;
struct test_pal_logical_processor
*lp;
struct util_thread_starter_state
*tts;
struct test_element
*te_array,
*te;
struct test_state
*ts;
test_pal_thread_state_t
*thread_handles;
assert( list_of_logical_processors != NULL );
// TRD : memory_in_megabytes can be any value in its range
/* TRD : we create a single queue with 50,000 elements
we don't want too many elements, so we ensure plenty of element re-use
each thread simply loops dequeuing and enqueuing
where the user data indicates thread number and an increment counter
vertification is that the counter increments on a per-thread basis
*/
internal_display_test_name( "Rapid enqueuing and dequeuing (%d seconds)", TEST_DURATION_IN_SECONDS );
lfds700_list_asu_query( list_of_logical_processors, LFDS700_LIST_ASU_QUERY_GET_POTENTIALLY_INACCURATE_COUNT, NULL, (void **) &number_logical_processors );
lfds700_misc_prng_init( &ps );
number_elements_with_dummy_element = ( memory_in_megabytes * ONE_MEGABYTE_IN_BYTES ) / sizeof(struct test_element);
if( number_elements_with_dummy_element > (10000 * number_logical_processors) + 1 )
number_elements_with_dummy_element = (10000 * number_logical_processors) + 1;
number_elements_without_dummy_element = number_elements_with_dummy_element - 1;
vi.min_elements = number_elements_without_dummy_element;
vi.max_elements = number_elements_without_dummy_element;
te_array = util_aligned_malloc( sizeof(struct test_element) * number_elements_with_dummy_element, LFDS700_PAL_ATOMIC_ISOLATION_IN_BYTES );
lfds700_queue_init_valid_on_current_logical_core( &qs, &(te_array+number_elements_without_dummy_element)->qe, &ps, NULL );
// TRD : we assume the test will iterate at least once (or we'll have a false negative)
for( loop = 0 ; loop < number_elements_without_dummy_element ; loop++ )
{
(te_array+loop)->thread_number = loop;
(te_array+loop)->counter = 0;
LFDS700_QUEUE_SET_VALUE_IN_ELEMENT( (te_array+loop)->qe, te_array+loop );
lfds700_queue_enqueue( &qs, &(te_array+loop)->qe, &ps );
}
ts = util_malloc_wrapper( sizeof(struct test_state) * number_logical_processors );
for( loop = 0 ; loop < number_logical_processors ; loop++ )
{
(ts+loop)->qs = &qs;
(ts+loop)->thread_number = loop;
(ts+loop)->counter = 0;
}
thread_handles = util_malloc_wrapper( sizeof(test_pal_thread_state_t) * number_logical_processors );
util_thread_starter_new( &tts, number_logical_processors );
LFDS700_MISC_BARRIER_STORE;
lfds700_misc_force_store();
loop = 0;
lasue = NULL;
while( LFDS700_LIST_ASU_GET_START_AND_THEN_NEXT(*list_of_logical_processors, lasue) )
{
lp = LFDS700_LIST_ASU_GET_VALUE_FROM_ELEMENT( *lasue );
util_thread_starter_start( tts, &thread_handles[loop], loop, lp, thread_rapid_enqueuer_and_dequeuer, ts+loop );
loop++;
}
util_thread_starter_run( tts );
for( loop = 0 ; loop < number_logical_processors ; loop++ )
test_pal_thread_wait( thread_handles[loop] );
util_thread_starter_delete( tts );
free( thread_handles );
LFDS700_MISC_BARRIER_LOAD;
lfds700_queue_query( &qs, LFDS700_QUEUE_QUERY_SINGLETHREADED_VALIDATE, &vi, &dvs );
// TRD : now check results
per_thread_counters = util_malloc_wrapper( sizeof(lfds700_pal_uint_t) * number_logical_processors );
for( loop = 0 ; loop < number_logical_processors ; loop++ )
*(per_thread_counters+loop) = 0;
while( dvs == LFDS700_MISC_VALIDITY_VALID and lfds700_queue_dequeue(&qs, &qe, &ps) )
{
te = LFDS700_QUEUE_GET_VALUE_FROM_ELEMENT( *qe );
if( te->thread_number >= number_logical_processors )
{
dvs = LFDS700_MISC_VALIDITY_INVALID_TEST_DATA;
break;
}
if( per_thread_counters[te->thread_number] == 0 )
per_thread_counters[te->thread_number] = te->counter;
if( te->counter > per_thread_counters[te->thread_number] )
dvs = LFDS700_MISC_VALIDITY_INVALID_MISSING_ELEMENTS;
if( te->counter < per_thread_counters[te->thread_number] )
dvs = LFDS700_MISC_VALIDITY_INVALID_ADDITIONAL_ELEMENTS;
if( te->counter == per_thread_counters[te->thread_number] )
per_thread_counters[te->thread_number]++;
}
free( per_thread_counters );
lfds700_queue_cleanup( &qs, NULL );
util_aligned_free( te_array );
free( ts );
internal_display_test_result( 1, "queue", dvs );
return;
}
/****************************************************************************/
static test_pal_thread_return_t TEST_PAL_CALLING_CONVENTION thread_rapid_enqueuer_and_dequeuer( void *util_thread_starter_thread_state )
{
lfds700_pal_uint_t
time_loop = 0;
struct lfds700_misc_prng_state
ps;
struct lfds700_queue_element
*qe;
struct test_element
*te;
struct test_state
*ts;
struct util_thread_starter_thread_state
*tsts;
time_t
current_time,
start_time;
LFDS700_MISC_MAKE_VALID_ON_CURRENT_LOGICAL_CORE_INITS_COMPLETED_BEFORE_NOW_ON_ANY_OTHER_LOGICAL_CORE;
assert( util_thread_starter_thread_state != NULL );
tsts = (struct util_thread_starter_thread_state *) util_thread_starter_thread_state;
ts = (struct test_state *) tsts->thread_user_state;
lfds700_misc_prng_init( &ps );
util_thread_starter_ready_and_wait( tsts );
current_time = start_time = time( NULL );
while( current_time < start_time + TEST_DURATION_IN_SECONDS )
{
lfds700_queue_dequeue( ts->qs, &qe, &ps );
te = LFDS700_QUEUE_GET_VALUE_FROM_ELEMENT( *qe );
te->thread_number = ts->thread_number;
te->counter = ts->counter++;
LFDS700_QUEUE_SET_VALUE_IN_ELEMENT( *qe, te );
lfds700_queue_enqueue( ts->qs, qe, &ps );
if( time_loop++ == TIME_LOOP_COUNT )
{
time_loop = 0;
time( &current_time );
}
}
LFDS700_MISC_BARRIER_STORE;
lfds700_misc_force_store();
return( (test_pal_thread_return_t) EXIT_SUCCESS );
}
/***** includes *****/
#include "internal.h"
/****************************************************************************/
#pragma warning( disable : 4127 ) // TRD : disables MSVC warning for condition expressions being const
void test_lfds700_ringbuffer( struct lfds700_list_asu_state *list_of_logical_processors, lfds700_pal_uint_t memory_in_megabytes )
{
assert( list_of_logical_processors != NULL );
// TRD : memory_in_megabytes can be any value in its range
if( LFDS700_MISC_ATOMIC_SUPPORT_DWCAS )
{
printf( "\n"
"Ringbuffer Tests\n"
"================\n" );
test_lfds700_ringbuffer_reading( list_of_logical_processors, memory_in_megabytes );
test_lfds700_ringbuffer_reading_and_writing( list_of_logical_processors, memory_in_megabytes );
test_lfds700_ringbuffer_writing( list_of_logical_processors, memory_in_megabytes );
}
return;
}
#pragma warning( default : 4127 )
/***** includes *****/
#include "internal.h"
/***** structs *****/
struct test_state
{
enum flag
error_flag;
lfds700_pal_uint_t
read_count;
struct lfds700_ringbuffer_state
*rs;
};
/***** private prototypes *****/
static test_pal_thread_return_t TEST_PAL_CALLING_CONVENTION thread_simple_reader( void *util_thread_starter_thread_state );
/****************************************************************************/
void test_lfds700_ringbuffer_reading( struct lfds700_list_asu_state *list_of_logical_processors, lfds700_pal_uint_t memory_in_megabytes )
{
enum lfds700_misc_validity
dvs[2] = { LFDS700_MISC_VALIDITY_VALID, LFDS700_MISC_VALIDITY_VALID };
lfds700_pal_uint_t
loop,
number_elements_with_dummy_element,
number_elements_without_dummy_element,
number_logical_processors,
total_read = 0;
struct lfds700_list_asu_element
*lasue;
struct lfds700_misc_prng_state
ps;
struct lfds700_ringbuffer_element
*re_array;
struct lfds700_ringbuffer_state
rs;
struct lfds700_misc_validation_info
vi;
struct test_pal_logical_processor
*lp;
struct util_thread_starter_state
*tts;
struct test_state
*ts;
test_pal_thread_state_t
*thread_handles;
assert( list_of_logical_processors != NULL );
// TRD : memory_in_megabytes can be any value in its range
/* 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" );
lfds700_list_asu_query( list_of_logical_processors, LFDS700_LIST_ASU_QUERY_GET_POTENTIALLY_INACCURATE_COUNT, NULL, (void **) &number_logical_processors );
lfds700_misc_prng_init( &ps );
number_elements_with_dummy_element = ( memory_in_megabytes * ONE_MEGABYTE_IN_BYTES ) / sizeof(struct lfds700_ringbuffer_element);
number_elements_without_dummy_element = number_elements_with_dummy_element - 1;
vi.min_elements = 0;
vi.max_elements = number_elements_without_dummy_element;
re_array = util_aligned_malloc( sizeof(struct lfds700_ringbuffer_element) * number_elements_with_dummy_element, LFDS700_PAL_ATOMIC_ISOLATION_IN_BYTES );
lfds700_ringbuffer_init_valid_on_current_logical_core( &rs, re_array, number_elements_with_dummy_element, &ps, NULL );
// TRD : init the ringbuffer contents for the test
for( loop = 0 ; loop < number_elements_without_dummy_element ; loop++ )
lfds700_ringbuffer_write( &rs, NULL, (void *) (size_t) loop, NULL, NULL, NULL, &ps );
ts = util_malloc_wrapper( sizeof(struct test_state) * number_logical_processors );
for( loop = 0 ; loop < number_logical_processors ; loop++ )
{
(ts+loop)->rs = &rs;
(ts+loop)->read_count = 0;
(ts+loop)->error_flag = LOWERED;
}
thread_handles = util_malloc_wrapper( sizeof(test_pal_thread_state_t) * number_logical_processors );
util_thread_starter_new( &tts, number_logical_processors );
LFDS700_MISC_BARRIER_STORE;
lfds700_misc_force_store();
loop = 0;
lasue = NULL;
while( LFDS700_LIST_ASU_GET_START_AND_THEN_NEXT(*list_of_logical_processors, lasue) )
{
lp = LFDS700_LIST_ASU_GET_VALUE_FROM_ELEMENT( *lasue );
util_thread_starter_start( tts, &thread_handles[loop], loop, lp, thread_simple_reader, ts+loop );
loop++;
}
util_thread_starter_run( tts );
for( loop = 0 ; loop < number_logical_processors ; loop++ )
test_pal_thread_wait( thread_handles[loop] );
util_thread_starter_delete( tts );
free( thread_handles );
LFDS700_MISC_BARRIER_LOAD;
lfds700_ringbuffer_query( &rs, LFDS700_RINGBUFFER_QUERY_SINGLETHREADED_VALIDATE, (void *) &vi, (void *) dvs );
// TRD : check for raised error flags
for( loop = 0 ; loop < number_logical_processors ; loop++ )
if( (ts+loop)->error_flag == RAISED )
dvs[0] = LFDS700_MISC_VALIDITY_INVALID_TEST_DATA;
// TRD : check thread reads total to 1,000,000
for( loop = 0 ; loop < number_logical_processors ; loop++ )
total_read += (ts+loop)->read_count;
if( total_read < number_elements_without_dummy_element )
dvs[0] = LFDS700_MISC_VALIDITY_INVALID_MISSING_ELEMENTS;
if( total_read > number_elements_without_dummy_element )
dvs[0] = LFDS700_MISC_VALIDITY_INVALID_ADDITIONAL_ELEMENTS;
free( ts );
lfds700_ringbuffer_cleanup( &rs, NULL );
util_aligned_free( re_array );
internal_display_test_result( 2, "queue", dvs[0], "freelist", dvs[1] );
return;
}
/****************************************************************************/
static test_pal_thread_return_t TEST_PAL_CALLING_CONVENTION thread_simple_reader( void *util_thread_starter_thread_state )
{
lfds700_pal_uint_t
*prev_value,
*value;
struct lfds700_misc_prng_state
ps;
struct test_state
*ts;
struct util_thread_starter_thread_state
*tsts;
LFDS700_MISC_MAKE_VALID_ON_CURRENT_LOGICAL_CORE_INITS_COMPLETED_BEFORE_NOW_ON_ANY_OTHER_LOGICAL_CORE;
assert( util_thread_starter_thread_state != NULL );
tsts = (struct util_thread_starter_thread_state *) util_thread_starter_thread_state;
ts = (struct test_state *) tsts->thread_user_state;
lfds700_misc_prng_init( &ps );
lfds700_ringbuffer_read( ts->rs, NULL, (void **) &prev_value, &ps );
ts->read_count++;
util_thread_starter_ready_and_wait( tsts );
while( lfds700_ringbuffer_read(ts->rs, NULL, (void **) &value, &ps) )
{
if( value <= prev_value )
ts->error_flag = RAISED;
prev_value = value;
ts->read_count++;
}
LFDS700_MISC_BARRIER_STORE;
lfds700_misc_force_store();
return( (test_pal_thread_return_t) EXIT_SUCCESS );
}
/***** includes *****/
#include "internal.h"
/***** structs *****/
struct test_state
{
enum flag
error_flag;
lfds700_pal_uint_t
counter,
number_logical_processors,
*per_thread_counters,
thread_number;
struct lfds700_ringbuffer_state
*rs;
};
struct test_element
{
lfds700_pal_uint_t
datum,
thread_number;
};
/***** private prototypes *****/
static test_pal_thread_return_t TEST_PAL_CALLING_CONVENTION thread_reader_writer( void *util_thread_starter_thread_state );
/****************************************************************************/
void test_lfds700_ringbuffer_reading_and_writing( struct lfds700_list_asu_state *list_of_logical_processors, lfds700_pal_uint_t memory_in_megabytes )
{
enum lfds700_misc_validity
dvs[2] = { LFDS700_MISC_VALIDITY_VALID, LFDS700_MISC_VALIDITY_VALID };
lfds700_pal_uint_t
loop,
number_elements_with_dummy_element,
number_elements_without_dummy_element,
number_logical_processors,
subloop;
test_pal_thread_state_t
*thread_handles;
struct lfds700_list_asu_element
*lasue;
struct lfds700_misc_prng_state
ps;
struct lfds700_ringbuffer_element
*re_array;
struct lfds700_ringbuffer_state
rs;
struct lfds700_misc_validation_info
vi;
struct test_pal_logical_processor
*lp;
struct util_thread_starter_state
*tts;
struct test_element
*te_array;
struct test_state
*ts;
assert( list_of_logical_processors != NULL );
// TRD : memory_in_megabytes can be any value in its range
/* TRD : we create a single ringbuffer
with 100,000 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 (%d seconds)", TEST_DURATION_IN_SECONDS );
lfds700_list_asu_query( list_of_logical_processors, LFDS700_LIST_ASU_QUERY_GET_POTENTIALLY_INACCURATE_COUNT, NULL, (void **) &number_logical_processors );
lfds700_misc_prng_init( &ps );
number_elements_with_dummy_element = ( memory_in_megabytes * ONE_MEGABYTE_IN_BYTES ) / ( sizeof(struct test_element) + sizeof(struct lfds700_ringbuffer_element) );
number_elements_without_dummy_element = number_elements_with_dummy_element - 1;
vi.min_elements = 0;
vi.max_elements = number_elements_without_dummy_element;
re_array = util_aligned_malloc( sizeof(struct lfds700_ringbuffer_element) * number_elements_with_dummy_element, LFDS700_PAL_ATOMIC_ISOLATION_IN_BYTES );
lfds700_ringbuffer_init_valid_on_current_logical_core( &rs, re_array, number_elements_with_dummy_element, &ps, NULL );
te_array = util_malloc_wrapper( sizeof(struct test_element) * number_elements_without_dummy_element );
// TRD : populate the ringbuffer
for( loop = 0 ; loop < number_elements_without_dummy_element ; loop++ )
{
te_array[loop].thread_number = 0;
te_array[loop].datum = (lfds700_pal_uint_t) -1 ;
lfds700_ringbuffer_write( &rs, NULL, &te_array[loop], NULL, NULL, NULL, &ps );
}
ts = util_malloc_wrapper( sizeof(struct test_state) * number_logical_processors );
for( loop = 0 ; loop < number_logical_processors ; loop++ )
{
(ts+loop)->rs = &rs;
(ts+loop)->thread_number = loop;
(ts+loop)->counter = 0;
(ts+loop)->number_logical_processors = number_logical_processors;
(ts+loop)->error_flag = LOWERED;
(ts+loop)->per_thread_counters = util_malloc_wrapper( sizeof(lfds700_pal_uint_t) * number_logical_processors );
for( subloop = 0 ; subloop < number_logical_processors ; subloop++ )
*((ts+loop)->per_thread_counters+subloop) = 0;
}
thread_handles = util_malloc_wrapper( sizeof(test_pal_thread_state_t) * number_logical_processors );
util_thread_starter_new( &tts, number_logical_processors );
LFDS700_MISC_BARRIER_STORE;
lfds700_misc_force_store();
loop = 0;
lasue = NULL;
while( LFDS700_LIST_ASU_GET_START_AND_THEN_NEXT(*list_of_logical_processors, lasue) )
{
lp = LFDS700_LIST_ASU_GET_VALUE_FROM_ELEMENT( *lasue );
util_thread_starter_start( tts, &thread_handles[loop], loop, lp, thread_reader_writer, ts+loop );
loop++;
}
util_thread_starter_run( tts );
for( loop = 0 ; loop < number_logical_processors ; loop++ )
test_pal_thread_wait( thread_handles[loop] );
util_thread_starter_delete( tts );
free( thread_handles );
LFDS700_MISC_BARRIER_LOAD;
lfds700_ringbuffer_query( &rs, LFDS700_RINGBUFFER_QUERY_SINGLETHREADED_VALIDATE, (void *) &vi, (void *) dvs );
for( loop = 0 ; loop < number_logical_processors ; loop++ )
if( (ts+loop)->error_flag == RAISED )
dvs[0] = LFDS700_MISC_VALIDITY_INVALID_TEST_DATA;
for( loop = 0 ; loop < number_logical_processors ; loop++ )
free( (ts+loop)->per_thread_counters );
free( ts );
lfds700_ringbuffer_cleanup( &rs, NULL );
util_aligned_free( re_array );
free( te_array );
internal_display_test_result( 2, "queue", dvs[0], "freelist", dvs[1] );
return;
}
/****************************************************************************/
static test_pal_thread_return_t TEST_PAL_CALLING_CONVENTION thread_reader_writer( void *util_thread_starter_thread_state )
{
lfds700_pal_uint_t
time_loop = 0;
struct lfds700_misc_prng_state
ps;
struct test_element
*te;
struct test_state
*ts;
struct util_thread_starter_thread_state
*tsts;
time_t
current_time,
start_time;
LFDS700_MISC_MAKE_VALID_ON_CURRENT_LOGICAL_CORE_INITS_COMPLETED_BEFORE_NOW_ON_ANY_OTHER_LOGICAL_CORE;
assert( util_thread_starter_thread_state != NULL );
tsts = (struct util_thread_starter_thread_state *) util_thread_starter_thread_state;
ts = (struct test_state *) tsts->thread_user_state;
lfds700_misc_prng_init( &ps );
util_thread_starter_ready_and_wait( tsts );
current_time = start_time = time( NULL );
while( current_time < start_time + TEST_DURATION_IN_SECONDS )
{
lfds700_ringbuffer_read( ts->rs, NULL, (void **) &te, &ps );
if( te->thread_number >= ts->number_logical_processors )
ts->error_flag = RAISED;
else
{
if( te->datum < ts->per_thread_counters[te->thread_number] )
ts->error_flag = RAISED;
if( te->datum >= ts->per_thread_counters[te->thread_number] )
ts->per_thread_counters[te->thread_number] = te->datum+1;
}
te->thread_number = ts->thread_number;
te->datum = ts->counter++;
lfds700_ringbuffer_write( ts->rs, NULL, te, NULL, NULL, NULL, &ps );
if( time_loop++ == TIME_LOOP_COUNT )
{
time_loop = 0;
time( &current_time );
}
}
LFDS700_MISC_BARRIER_STORE;
lfds700_misc_force_store();
return( (test_pal_thread_return_t) EXIT_SUCCESS );
}
/***** includes *****/
#include "internal.h"
/***** structs *****/
struct test_element
{
lfds700_pal_uint_t
thread_number,
datum;
};
struct test_state
{
lfds700_pal_uint_t
thread_number,
write_count;
struct test_element
te;
struct lfds700_ringbuffer_state
*rs;
};
/***** private prototypes *****/
static test_pal_thread_return_t TEST_PAL_CALLING_CONVENTION thread_simple_writer( void *util_thread_starter_thread_state );
/****************************************************************************/
void test_lfds700_ringbuffer_writing( struct lfds700_list_asu_state *list_of_logical_processors, lfds700_pal_uint_t memory_in_megabytes )
{
enum lfds700_misc_validity
dvs[2] = { LFDS700_MISC_VALIDITY_VALID, LFDS700_MISC_VALIDITY_VALID };
lfds700_pal_uint_t
loop,
number_elements_with_dummy_element,
number_elements_without_dummy_element,
number_logical_processors,
*per_thread_counters;
test_pal_thread_state_t
*thread_handles;
struct lfds700_list_asu_element
*lasue;
struct lfds700_misc_prng_state
ps;
struct lfds700_ringbuffer_element
*re_array;
struct lfds700_ringbuffer_state
rs;
struct lfds700_misc_validation_info
vi;
struct test_pal_logical_processor
*lp;
struct util_thread_starter_state
*tts;
struct test_element
*te,
*te_array;
struct test_state
*ts;
assert( list_of_logical_processors != NULL );
// TRD : memory_in_megabytes can be any value in its range
/* TRD : we create a single ringbuffer
with n elements
we create n test elements
which are thread_number/counter pairs
init them to safe values
and fully populate the ringbuffer
we create one thread per CPU
where each thread busy-works writing
for ten seconds; each thread has one extra element
which it uses for the first write and after that
it uses the element it picks up from overwriting
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 (%d seconds)", TEST_DURATION_IN_SECONDS );
lfds700_list_asu_query( list_of_logical_processors, LFDS700_LIST_ASU_QUERY_GET_POTENTIALLY_INACCURATE_COUNT, NULL, (void **) &number_logical_processors );
lfds700_misc_prng_init( &ps );
number_elements_with_dummy_element = ( memory_in_megabytes * ONE_MEGABYTE_IN_BYTES ) / ( sizeof(struct test_element) + sizeof(struct lfds700_ringbuffer_element) );
number_elements_without_dummy_element = number_elements_with_dummy_element - 1;
vi.min_elements = number_elements_without_dummy_element;
vi.max_elements = number_elements_without_dummy_element;
re_array = util_aligned_malloc( sizeof(struct lfds700_ringbuffer_element) * number_elements_with_dummy_element, LFDS700_PAL_ATOMIC_ISOLATION_IN_BYTES );
lfds700_ringbuffer_init_valid_on_current_logical_core( &rs, re_array, number_elements_with_dummy_element, &ps, NULL );
te_array = util_malloc_wrapper( sizeof(struct lfds700_ringbuffer_element) * number_elements_without_dummy_element );
// TRD : init the test elements and write them into the ringbuffer
for( loop = 0 ; loop < number_elements_without_dummy_element ; loop++ )
{
te_array[loop].thread_number = 0;
te_array[loop].datum = 0;
lfds700_ringbuffer_write( &rs, NULL, &te_array[loop], NULL, NULL, NULL, &ps );
}
ts = util_malloc_wrapper( sizeof(struct test_state) * number_logical_processors );
for( loop = 0 ; loop < number_logical_processors ; loop++ )
{
(ts+loop)->rs = &rs;
(ts+loop)->thread_number = loop;
(ts+loop)->write_count = 0;
}
thread_handles = util_malloc_wrapper( sizeof(test_pal_thread_state_t) * number_logical_processors );
util_thread_starter_new( &tts, number_logical_processors );
LFDS700_MISC_BARRIER_STORE;
lfds700_misc_force_store();
loop = 0;
lasue = NULL;
while( LFDS700_LIST_ASU_GET_START_AND_THEN_NEXT(*list_of_logical_processors, lasue) )
{
lp = LFDS700_LIST_ASU_GET_VALUE_FROM_ELEMENT( *lasue );
util_thread_starter_start( tts, &thread_handles[loop], loop, lp, thread_simple_writer, ts+loop );
loop++;
}
util_thread_starter_run( tts );
for( loop = 0 ; loop < number_logical_processors ; loop++ )
test_pal_thread_wait( thread_handles[loop] );
util_thread_starter_delete( tts );
free( thread_handles );
LFDS700_MISC_BARRIER_LOAD;
// TRD : now check results
per_thread_counters = util_malloc_wrapper( sizeof(lfds700_pal_uint_t) * number_logical_processors );
for( loop = 0 ; loop < number_logical_processors ; loop++ )
*(per_thread_counters+loop) = 0;
lfds700_ringbuffer_query( &rs, LFDS700_RINGBUFFER_QUERY_SINGLETHREADED_VALIDATE, &vi, dvs );
while( dvs[0] == LFDS700_MISC_VALIDITY_VALID and dvs[1] == LFDS700_MISC_VALIDITY_VALID and lfds700_ringbuffer_read(&rs, NULL, (void **) &te, &ps) )
{
if( te->thread_number >= number_logical_processors )
{
dvs[0] = LFDS700_MISC_VALIDITY_INVALID_TEST_DATA;
break;
}
if( per_thread_counters[te->thread_number] == 0 )
per_thread_counters[te->thread_number] = te->datum;
if( te->datum < per_thread_counters[te->thread_number] )
dvs[0] = LFDS700_MISC_VALIDITY_INVALID_ADDITIONAL_ELEMENTS;
if( te->datum >= per_thread_counters[te->thread_number] )
per_thread_counters[te->thread_number] = te->datum+1;
}
free( per_thread_counters );
lfds700_ringbuffer_cleanup( &rs, NULL );
free( ts );
util_aligned_free( re_array );
free( te_array );
internal_display_test_result( 2, "queue", dvs[0], "freelist", dvs[1] );
return;
}
/****************************************************************************/
static test_pal_thread_return_t TEST_PAL_CALLING_CONVENTION thread_simple_writer( void *util_thread_starter_thread_state )
{
enum lfds700_misc_flag
overwrite_occurred_flag;
lfds700_pal_uint_t
time_loop = 0;
struct lfds700_misc_prng_state
ps;
struct test_element
*te;
struct test_state
*ts;
struct util_thread_starter_thread_state
*tsts;
time_t
current_time,
start_time;
LFDS700_MISC_MAKE_VALID_ON_CURRENT_LOGICAL_CORE_INITS_COMPLETED_BEFORE_NOW_ON_ANY_OTHER_LOGICAL_CORE;
assert( util_thread_starter_thread_state != NULL );
tsts = (struct util_thread_starter_thread_state *) util_thread_starter_thread_state;
ts = (struct test_state *) tsts->thread_user_state;
lfds700_misc_prng_init( &ps );
ts->te.thread_number = 0;
ts->te.datum = 0;
lfds700_ringbuffer_write( ts->rs, NULL, &ts->te, &overwrite_occurred_flag, NULL, (void **) &te, &ps );
util_thread_starter_ready_and_wait( tsts );
current_time = start_time = time( NULL );
while( current_time < start_time + TEST_DURATION_IN_SECONDS )
{
te->thread_number = ts->thread_number;
te->datum = ts->write_count++;
lfds700_ringbuffer_write( ts->rs, NULL, te, &overwrite_occurred_flag, NULL, (void **) &te, &ps );
if( time_loop++ == TIME_LOOP_COUNT )
{
time_loop = 0;
time( &current_time );
}
}
LFDS700_MISC_BARRIER_STORE;
lfds700_misc_force_store();
return( (test_pal_thread_return_t) EXIT_SUCCESS );
}
/***** includes *****/
#include "internal.h"
/****************************************************************************/
#pragma warning( disable : 4127 ) // TRD : disables MSVC warning for condition expressions being const
void test_lfds700_stack( struct lfds700_list_asu_state *list_of_logical_processors, lfds700_pal_uint_t memory_in_megabytes )
{
assert( list_of_logical_processors != NULL );
// TRD : memory_in_megabytes can be any value in its range
if( LFDS700_MISC_ATOMIC_SUPPORT_DWCAS )
{
printf( "\n"
"Stack Tests\n"
"===========\n" );
test_lfds700_stack_alignment();
test_lfds700_stack_popping( list_of_logical_processors, memory_in_megabytes );
test_lfds700_stack_pushing( list_of_logical_processors, memory_in_megabytes );
test_lfds700_stack_popping_and_pushing( list_of_logical_processors, memory_in_megabytes );
test_lfds700_stack_rapid_popping_and_pushing( list_of_logical_processors );
}
return;
}
#pragma warning( default : 4127 )
/***** includes *****/
#include "internal.h"
/****************************************************************************/
#pragma warning( disable : 4127 ) // TRD : disables MSVC warning for condition expressions being const
void test_lfds700_stack_alignment()
{
enum lfds700_misc_validity
dvs = LFDS700_MISC_VALIDITY_VALID;
/* TRD : these are compile time checks
but we do them here because this is a test programme
and it should indicate issues to users when it is *run*,
not when it is compiled, because a compile error normally
indicates a problem with the code itself and so is misleading
*/
internal_display_test_name( "Alignment" );
// TRD : struct lfds700_stack_state
if( offsetof(struct lfds700_stack_state,top) % LFDS700_PAL_ATOMIC_ISOLATION_IN_BYTES != 0 )
dvs = LFDS700_MISC_VALIDITY_INVALID_TEST_DATA;
if( offsetof(struct lfds700_stack_state,user_state) % LFDS700_PAL_ATOMIC_ISOLATION_IN_BYTES != 0 )
dvs = LFDS700_MISC_VALIDITY_INVALID_TEST_DATA;
// TRD : print the test result
internal_display_test_result( 1, "stack", dvs );
return;
}
#pragma warning( default : 4127 )
/***** includes *****/
#include "internal.h"
/***** structs *****/
struct test_state
{
struct lfds700_stack_state
*ss;
};
struct test_element
{
struct lfds700_stack_element
se;
enum flag
popped_flag;
};
/***** private prototypes *****/
static test_pal_thread_return_t TEST_PAL_CALLING_CONVENTION thread_popping( void *util_thread_starter_thread_state );
/****************************************************************************/
void test_lfds700_stack_popping( struct lfds700_list_asu_state *list_of_logical_processors, lfds700_pal_uint_t memory_in_megabytes )
{
enum lfds700_misc_validity
dvs = LFDS700_MISC_VALIDITY_VALID;
lfds700_pal_uint_t
loop,
number_elements,
number_logical_processors;
struct lfds700_misc_prng_state
ps;
struct lfds700_list_asu_element
*lasue;
struct lfds700_stack_state
ss;
struct lfds700_misc_validation_info
vi = { 0, 0 };
struct test_pal_logical_processor
*lp;
struct util_thread_starter_state
*tts;
struct test_element
*te_array;
struct test_state
*ts;
test_pal_thread_state_t
*thread_handles;
assert( list_of_logical_processors != NULL );
// TRD : memory_in_megabytes can be any value in its range
/* TRD : we create a stack
we then populate the stack with 1,000,000 elements
each void pointer of data points to the containing test element
we then run one thread per CPU
where each thread loops, popping as quickly as possible
upon popping, a flag is set in the containing test element
the threads run till the source stack is empty
we then check the poppged flag, all should be raised
then tidy up
no CAS+GC code, as we only pop
*/
internal_display_test_name( "Popping" );
lfds700_list_asu_query( list_of_logical_processors, LFDS700_LIST_ASU_QUERY_GET_POTENTIALLY_INACCURATE_COUNT, NULL, (void **) &number_logical_processors );
lfds700_misc_prng_init( &ps );
lfds700_stack_init_valid_on_current_logical_core( &ss, NULL );
number_elements = ( memory_in_megabytes * ONE_MEGABYTE_IN_BYTES ) / sizeof(struct test_element) ;
te_array = util_aligned_malloc( sizeof(struct test_element) * number_elements, LFDS700_PAL_ATOMIC_ISOLATION_IN_BYTES );
for( loop = 0 ; loop < number_elements ; loop++ )
{
(te_array+loop)->popped_flag = LOWERED;
LFDS700_STACK_SET_VALUE_IN_ELEMENT( (te_array+loop)->se, te_array+loop );
lfds700_stack_push( &ss, &(te_array+loop)->se, &ps );
}
ts = util_aligned_malloc( sizeof(struct test_state) * number_logical_processors, LFDS700_PAL_ATOMIC_ISOLATION_IN_BYTES );
for( loop = 0 ; loop < number_logical_processors ; loop++ )
(ts+loop)->ss = &ss;
thread_handles = util_malloc_wrapper( sizeof(test_pal_thread_state_t) * number_logical_processors );
util_thread_starter_new( &tts, number_logical_processors );
LFDS700_MISC_BARRIER_STORE;
lfds700_misc_force_store();
loop = 0;
lasue = NULL;
while( LFDS700_LIST_ASU_GET_START_AND_THEN_NEXT(*list_of_logical_processors, lasue) )
{
lp = LFDS700_LIST_ASU_GET_VALUE_FROM_ELEMENT( *lasue );
util_thread_starter_start( tts, &thread_handles[loop], loop, lp, thread_popping, ts+loop );
loop++;
}
util_thread_starter_run( tts );
for( loop = 0 ; loop < number_logical_processors ; loop++ )
test_pal_thread_wait( thread_handles[loop] );
util_thread_starter_delete( tts );
free( thread_handles );
LFDS700_MISC_BARRIER_LOAD;
lfds700_stack_query( &ss, LFDS700_STACK_QUERY_SINGLETHREADED_VALIDATE, &vi, (void *) &dvs );
// TRD : now we check each element has popped_flag set to RAISED
for( loop = 0 ; loop < number_elements ; loop++ )
if( (te_array+loop)->popped_flag == LOWERED )
dvs = LFDS700_MISC_VALIDITY_INVALID_TEST_DATA;
// TRD : cleanup
lfds700_stack_cleanup( &ss, NULL );
util_aligned_free( te_array );
util_aligned_free( ts );
// TRD : print the test result
internal_display_test_result( 1, "stack", dvs );
return;
}
/****************************************************************************/
static test_pal_thread_return_t TEST_PAL_CALLING_CONVENTION thread_popping( void *util_thread_starter_thread_state )
{
struct lfds700_misc_prng_state
ps;
struct lfds700_stack_element
*se;
struct test_element
*te;
struct test_state
*ts;
struct util_thread_starter_thread_state
*tsts;
LFDS700_MISC_MAKE_VALID_ON_CURRENT_LOGICAL_CORE_INITS_COMPLETED_BEFORE_NOW_ON_ANY_OTHER_LOGICAL_CORE;
assert( util_thread_starter_thread_state != NULL );
tsts = (struct util_thread_starter_thread_state *) util_thread_starter_thread_state;
ts = (struct test_state *) tsts->thread_user_state;
lfds700_misc_prng_init( &ps );
util_thread_starter_ready_and_wait( tsts );
while( lfds700_stack_pop(ts->ss, &se, &ps) )
{
te = LFDS700_STACK_GET_VALUE_FROM_ELEMENT( *se );
te->popped_flag = RAISED;
}
LFDS700_MISC_BARRIER_STORE;
lfds700_misc_force_store();
return( (test_pal_thread_return_t) EXIT_SUCCESS );
}
/***** includes *****/
#include "internal.h"
/***** structs *****/
struct test_element;
struct test_state
{
lfds700_pal_uint_t
number_elements;
struct lfds700_stack_state
*ss,
ss_thread_local;
struct test_element
*ss_thread_local_te_array;
};
struct test_element
{
struct lfds700_stack_element
se,
thread_local_se;
lfds700_pal_uint_t
datum;
};
/***** private prototypes *****/
static test_pal_thread_return_t TEST_PAL_CALLING_CONVENTION thread_popping_and_pushing_start_popping( void *util_thread_starter_thread_state );
static test_pal_thread_return_t TEST_PAL_CALLING_CONVENTION thread_popping_and_pushing_start_pushing( void *util_thread_starter_thread_state );
/****************************************************************************/
void test_lfds700_stack_popping_and_pushing( struct lfds700_list_asu_state *list_of_logical_processors, lfds700_pal_uint_t memory_in_megabytes )
{
enum lfds700_misc_validity
dvs = LFDS700_MISC_VALIDITY_VALID;
lfds700_pal_uint_t
loop,
number_elements,
number_logical_processors,
subloop;
struct lfds700_list_asu_element
*lasue;
struct lfds700_misc_prng_state
ps;
struct lfds700_stack_state
ss;
struct lfds700_misc_validation_info
vi;
struct test_pal_logical_processor
*lp;
struct util_thread_starter_state
*tts;
struct test_element
*te_array;
struct test_state
*ts;
test_pal_thread_state_t
*thread_handles;
assert( list_of_logical_processors != NULL );
// TRD : memory_in_megabytes can be any value in its range
/* TRD : we have two threads per CPU
the threads loop for ten seconds
the first thread pushes 10000 elements then pops 10000 elements
the second thread pops 10000 elements then pushes 10000 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 (%d seconds)", TEST_DURATION_IN_SECONDS );
lfds700_list_asu_query( list_of_logical_processors, LFDS700_LIST_ASU_QUERY_GET_POTENTIALLY_INACCURATE_COUNT, NULL, (void **) &number_logical_processors );
lfds700_misc_prng_init( &ps );
number_elements = ( memory_in_megabytes * ONE_MEGABYTE_IN_BYTES ) / ( sizeof(struct test_element) * number_logical_processors * 2 );
lfds700_stack_init_valid_on_current_logical_core( &ss, NULL );
te_array = util_aligned_malloc( sizeof(struct test_element) * number_elements * number_logical_processors, LFDS700_PAL_ATOMIC_ISOLATION_IN_BYTES );
// TRD : some initial elements so the pushing threads can start immediately
for( loop = 0 ; loop < number_elements * number_logical_processors ; loop++ )
{
(te_array+loop)->datum = loop;
LFDS700_STACK_SET_VALUE_IN_ELEMENT( (te_array+loop)->se, te_array+loop );
lfds700_stack_push( &ss, &(te_array+loop)->se, &ps );
}
ts = util_aligned_malloc( sizeof(struct test_state) * number_logical_processors * 2, LFDS700_PAL_ATOMIC_ISOLATION_IN_BYTES );
for( loop = 0 ; loop < number_logical_processors ; loop++ )
{
// TRD : first set of threads
(ts+loop)->ss = &ss;
(ts+loop)->number_elements = number_elements;
lfds700_stack_init_valid_on_current_logical_core( &(ts+loop)->ss_thread_local, NULL );
// TRD : second set of threads
(ts+loop+number_logical_processors)->ss = &ss;
(ts+loop+number_logical_processors)->number_elements = number_elements;
lfds700_stack_init_valid_on_current_logical_core( &(ts+loop+number_logical_processors)->ss_thread_local, NULL );
// TRD : fill the pushing thread stacks
(ts+loop+number_logical_processors)->ss_thread_local_te_array = util_aligned_malloc( sizeof(struct test_element) * number_elements, LFDS700_PAL_ATOMIC_ISOLATION_IN_BYTES );
for( subloop = 0 ; subloop < number_elements ; subloop++ )
{
((ts+loop+number_logical_processors)->ss_thread_local_te_array+subloop)->datum = loop;
LFDS700_STACK_SET_VALUE_IN_ELEMENT( ((ts+loop+number_logical_processors)->ss_thread_local_te_array+subloop)->thread_local_se, (ts+loop+number_logical_processors)->ss_thread_local_te_array+subloop );
lfds700_stack_push( &(ts+loop+number_logical_processors)->ss_thread_local, &((ts+loop+number_logical_processors)->ss_thread_local_te_array+subloop)->thread_local_se, &ps );
}
}
thread_handles = util_malloc_wrapper( sizeof(test_pal_thread_state_t) * number_logical_processors * 2 );
util_thread_starter_new( &tts, number_logical_processors * 2 );
LFDS700_MISC_BARRIER_STORE;
lfds700_misc_force_store();
loop = 0;
lasue = NULL;
while( LFDS700_LIST_ASU_GET_START_AND_THEN_NEXT(*list_of_logical_processors, lasue) )
{
lp = LFDS700_LIST_ASU_GET_VALUE_FROM_ELEMENT( *lasue );
util_thread_starter_start( tts, &thread_handles[loop], loop, lp, thread_popping_and_pushing_start_popping, ts+loop );
util_thread_starter_start( tts, &thread_handles[loop+number_logical_processors], loop+number_logical_processors, lp, thread_popping_and_pushing_start_pushing, ts+loop+number_logical_processors );
loop++;
}
util_thread_starter_run( tts );
for( loop = 0 ; loop < number_logical_processors * 2 ; loop++ )
test_pal_thread_wait( thread_handles[loop] );
util_thread_starter_delete( tts );
free( thread_handles );
LFDS700_MISC_BARRIER_LOAD;
vi.min_elements = vi.max_elements = number_elements * number_logical_processors * 2;
lfds700_stack_query( &ss, LFDS700_STACK_QUERY_SINGLETHREADED_VALIDATE, &vi, &dvs );
lfds700_stack_cleanup( &ss, NULL );
for( loop = 0 ; loop < number_logical_processors ; loop++ )
{
lfds700_stack_cleanup( &(ts+loop)->ss_thread_local, NULL );
lfds700_stack_cleanup( &(ts+loop+number_logical_processors)->ss_thread_local, NULL );
util_aligned_free( (ts+loop+number_logical_processors)->ss_thread_local_te_array );
}
util_aligned_free( ts );
util_aligned_free( te_array );
// TRD : print the test result
internal_display_test_result( 1, "stack", dvs );
return;
}
/****************************************************************************/
static test_pal_thread_return_t TEST_PAL_CALLING_CONVENTION thread_popping_and_pushing_start_popping( void *util_thread_starter_thread_state )
{
lfds700_pal_uint_t
count;
struct lfds700_misc_prng_state
ps;
struct lfds700_stack_element
*se;
struct test_state
*ts;
struct util_thread_starter_thread_state
*tsts;
time_t
start_time;
LFDS700_MISC_MAKE_VALID_ON_CURRENT_LOGICAL_CORE_INITS_COMPLETED_BEFORE_NOW_ON_ANY_OTHER_LOGICAL_CORE;
assert( util_thread_starter_thread_state != NULL );
tsts = (struct util_thread_starter_thread_state *) util_thread_starter_thread_state;
ts = (struct test_state *) tsts->thread_user_state;
lfds700_misc_prng_init( &ps );
util_thread_starter_ready_and_wait( tsts );
start_time = time( NULL );
while( time(NULL) < start_time + TEST_DURATION_IN_SECONDS )
{
count = 0;
while( count < ts->number_elements )
if( lfds700_stack_pop(ts->ss, &se, &ps) )
{
lfds700_stack_push( &ts->ss_thread_local, se, &ps );
count++;
}
// TRD : return our local stack to the main stack
while( lfds700_stack_pop(&ts->ss_thread_local, &se, &ps) )
lfds700_stack_push( ts->ss, se, &ps );
}
LFDS700_MISC_BARRIER_STORE;
lfds700_misc_force_store();
return( (test_pal_thread_return_t) EXIT_SUCCESS );
}
/****************************************************************************/
static test_pal_thread_return_t TEST_PAL_CALLING_CONVENTION thread_popping_and_pushing_start_pushing( void *util_thread_starter_thread_state )
{
lfds700_pal_uint_t
count;
struct lfds700_misc_prng_state
ps;
struct lfds700_stack_element
*se;
struct test_state
*ts;
struct util_thread_starter_thread_state
*tsts;
time_t
start_time;
LFDS700_MISC_MAKE_VALID_ON_CURRENT_LOGICAL_CORE_INITS_COMPLETED_BEFORE_NOW_ON_ANY_OTHER_LOGICAL_CORE;
assert( util_thread_starter_thread_state != NULL );
tsts = (struct util_thread_starter_thread_state *) util_thread_starter_thread_state;
ts = (struct test_state *) tsts->thread_user_state;
lfds700_misc_prng_init( &ps );
util_thread_starter_ready_and_wait( tsts );
start_time = time( NULL );
while( time(NULL) < start_time + TEST_DURATION_IN_SECONDS )
{
// TRD : return our local stack to the main stack
while( lfds700_stack_pop(&ts->ss_thread_local, &se, &ps) )
lfds700_stack_push( ts->ss, se, &ps );
count = 0;
while( count < ts->number_elements )
if( lfds700_stack_pop(ts->ss, &se, &ps) )
{
lfds700_stack_push( &ts->ss_thread_local, se, &ps );
count++;
}
}
// TRD : now push whatever we have in our local stack
while( lfds700_stack_pop(&ts->ss_thread_local, &se, &ps) )
lfds700_stack_push( ts->ss, se, &ps );
LFDS700_MISC_BARRIER_STORE;
lfds700_misc_force_store();
return( (test_pal_thread_return_t) EXIT_SUCCESS );
}
/***** includes *****/
#include "internal.h"
/***** structs *****/
struct test_state
{
lfds700_pal_uint_t
number_elements,
thread_number;
struct lfds700_stack_state
*ss;
struct test_element
*te_array;
};
struct test_element
{
struct lfds700_stack_element
se;
lfds700_pal_uint_t
datum,
thread_number;
};
/***** private prototypes *****/
static test_pal_thread_return_t TEST_PAL_CALLING_CONVENTION thread_pushing( void *util_thread_starter_thread_state );
/****************************************************************************/
void test_lfds700_stack_pushing( struct lfds700_list_asu_state *list_of_logical_processors, lfds700_pal_uint_t memory_in_megabytes )
{
enum lfds700_misc_validity
dvs = LFDS700_MISC_VALIDITY_VALID;
lfds700_pal_uint_t
loop,
number_elements,
number_logical_processors,
*per_thread_counters;
struct lfds700_list_asu_element
*lasue;
struct lfds700_misc_prng_state
ps;
struct lfds700_stack_element
*se;
struct lfds700_stack_state
ss;
struct lfds700_misc_validation_info
vi;
struct test_pal_logical_processor
*lp;
struct util_thread_starter_state
*tts;
struct test_element
*te,
*first_te = NULL;
struct test_state
*ts;
test_pal_thread_state_t
*thread_handles;
assert( list_of_logical_processors != NULL );
// TRD : memory_in_megabytes can be any value in its range
/* TRD : we create an empty stack
we then create one thread per CPU, where each thread
pushes 100,000 elements each as quickly as possible to the stack
(the threads themselves alloc these elements, to obtain NUMA closeness)
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 100,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)
there's no CAS+GC code, as we only push
*/
internal_display_test_name( "Pushing" );
lfds700_list_asu_query( list_of_logical_processors, LFDS700_LIST_ASU_QUERY_GET_POTENTIALLY_INACCURATE_COUNT, NULL, (void **) &number_logical_processors );
lfds700_misc_prng_init( &ps );
number_elements = ( memory_in_megabytes * ONE_MEGABYTE_IN_BYTES ) / ( sizeof(struct test_element) * number_logical_processors );
ts = util_malloc_wrapper( sizeof(struct test_state) * number_logical_processors );
// TRD : the main stack
lfds700_stack_init_valid_on_current_logical_core( &ss, NULL );
for( loop = 0 ; loop < number_logical_processors ; loop++ )
{
(ts+loop)->ss = &ss;
(ts+loop)->thread_number = loop;
(ts+loop)->number_elements = number_elements;
}
thread_handles = util_malloc_wrapper( sizeof(test_pal_thread_state_t) * number_logical_processors );
util_thread_starter_new( &tts, number_logical_processors );
LFDS700_MISC_BARRIER_STORE;
lfds700_misc_force_store();
loop = 0;
lasue = NULL;
while( LFDS700_LIST_ASU_GET_START_AND_THEN_NEXT(*list_of_logical_processors, lasue) )
{
lp = LFDS700_LIST_ASU_GET_VALUE_FROM_ELEMENT( *lasue );
util_thread_starter_start( tts, &thread_handles[loop], loop, lp, thread_pushing, ts+loop );
loop++;
}
util_thread_starter_run( tts );
for( loop = 0 ; loop < number_logical_processors ; loop++ )
test_pal_thread_wait( thread_handles[loop] );
util_thread_starter_delete( tts );
free( thread_handles );
LFDS700_MISC_BARRIER_LOAD;
// TRD : the stack is now fully pushed; time to verify
per_thread_counters = util_malloc_wrapper( sizeof(lfds700_pal_uint_t) * number_logical_processors );
for( loop = 0 ; loop < number_logical_processors ; loop++ )
*(per_thread_counters+loop) = number_elements - 1;
vi.min_elements = vi.max_elements = number_elements * number_logical_processors;
lfds700_stack_query( &ss, LFDS700_STACK_QUERY_SINGLETHREADED_VALIDATE, &vi, &dvs );
while( dvs == LFDS700_MISC_VALIDITY_VALID and lfds700_stack_pop(&ss, &se, &ps) )
{
te = LFDS700_STACK_GET_VALUE_FROM_ELEMENT( *se );
if( first_te == NULL )
first_te = te;
if( te->thread_number >= number_logical_processors )
{
dvs = LFDS700_MISC_VALIDITY_INVALID_TEST_DATA;
break;
}
if( te->datum > per_thread_counters[te->thread_number] )
dvs = LFDS700_MISC_VALIDITY_INVALID_ADDITIONAL_ELEMENTS;
if( te->datum < per_thread_counters[te->thread_number] )
dvs = LFDS700_MISC_VALIDITY_INVALID_MISSING_ELEMENTS;
if( te->datum == per_thread_counters[te->thread_number] )
per_thread_counters[te->thread_number]--;
}
// TRD : clean up
for( loop = 0 ; loop < number_logical_processors ; loop++ )
util_aligned_free( (ts+loop)->te_array );
free( per_thread_counters );
free( ts );
lfds700_stack_cleanup( &ss, NULL );
// TRD : print the test result
internal_display_test_result( 1, "stack", dvs );
return;
}
/****************************************************************************/
static test_pal_thread_return_t TEST_PAL_CALLING_CONVENTION thread_pushing( void *util_thread_starter_thread_state )
{
lfds700_pal_uint_t
loop;
struct lfds700_misc_prng_state
ps;
struct test_state
*ts;
struct util_thread_starter_thread_state
*tsts;
LFDS700_MISC_MAKE_VALID_ON_CURRENT_LOGICAL_CORE_INITS_COMPLETED_BEFORE_NOW_ON_ANY_OTHER_LOGICAL_CORE;
assert( util_thread_starter_thread_state != NULL );
tsts = (struct util_thread_starter_thread_state *) util_thread_starter_thread_state;
ts = (struct test_state *) tsts->thread_user_state;
lfds700_misc_prng_init( &ps );
// TRD : alloc local 100,000 elements
ts->te_array = util_aligned_malloc( sizeof(struct test_element) * ts->number_elements, LFDS700_PAL_ATOMIC_ISOLATION_IN_BYTES );
for( loop = 0 ; loop < ts->number_elements ; loop++ )
{
(ts->te_array+loop)->thread_number = ts->thread_number;
(ts->te_array+loop)->datum = loop;
}
util_thread_starter_ready_and_wait( tsts );
for( loop = 0 ; loop < ts->number_elements ; loop++ )
{
LFDS700_STACK_SET_VALUE_IN_ELEMENT( (ts->te_array+loop)->se, ts->te_array+loop );
lfds700_stack_push( ts->ss, &(ts->te_array+loop)->se, &ps );
}
LFDS700_MISC_BARRIER_STORE;
lfds700_misc_force_store();
return( (test_pal_thread_return_t) EXIT_SUCCESS );
}
/***** includes *****/
#include "internal.h"
/***** structs *****/
struct test_state
{
struct lfds700_stack_state
*ss;
};
struct test_element
{
struct lfds700_stack_element
se;
lfds700_pal_uint_t
datum;
};
/***** private prototypes *****/
static test_pal_thread_return_t TEST_PAL_CALLING_CONVENTION thread_rapid_popping_and_pushing( void *util_thread_starter_thread_state );
/****************************************************************************/
void test_lfds700_stack_rapid_popping_and_pushing( struct lfds700_list_asu_state *list_of_logical_processors )
{
enum lfds700_misc_validity
dvs = LFDS700_MISC_VALIDITY_VALID;
lfds700_pal_uint_t
loop,
number_logical_processors;
struct lfds700_misc_prng_state
ps;
struct lfds700_list_asu_element
*lasue;
struct lfds700_stack_state
ss;
struct lfds700_misc_validation_info
vi = { 0, 0 };
struct test_pal_logical_processor
*lp;
struct util_thread_starter_state
*tts;
struct test_element
*te_array;
struct test_state
*ts;
test_pal_thread_state_t
*thread_handles;
assert( list_of_logical_processors != NULL );
// TRD : st can be any value in its range
/* 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 (%d seconds)", TEST_DURATION_IN_SECONDS );
lfds700_list_asu_query( list_of_logical_processors, LFDS700_LIST_ASU_QUERY_GET_POTENTIALLY_INACCURATE_COUNT, NULL, (void **) &number_logical_processors );
lfds700_misc_prng_init( &ps );
ts = util_malloc_wrapper( sizeof(struct test_state) * number_logical_processors );
lfds700_stack_init_valid_on_current_logical_core( &ss, NULL );
for( loop = 0 ; loop < number_logical_processors ; loop++ )
(ts+loop)->ss = &ss;
thread_handles = util_malloc_wrapper( sizeof(test_pal_thread_state_t) * number_logical_processors );
// TRD : we need one element per thread
te_array = util_aligned_malloc( sizeof(struct test_element) * number_logical_processors, LFDS700_PAL_ATOMIC_ISOLATION_IN_BYTES );
for( loop = 0 ; loop < number_logical_processors ; loop++ )
{
LFDS700_STACK_SET_VALUE_IN_ELEMENT( (te_array+loop)->se, te_array+loop );
lfds700_stack_push( &ss, &(te_array+loop)->se, &ps );
}
util_thread_starter_new( &tts, number_logical_processors );
LFDS700_MISC_BARRIER_STORE;
lfds700_misc_force_store();
loop = 0;
lasue = NULL;
while( LFDS700_LIST_ASU_GET_START_AND_THEN_NEXT(*list_of_logical_processors, lasue) )
{
lp = LFDS700_LIST_ASU_GET_VALUE_FROM_ELEMENT( *lasue );
util_thread_starter_start( tts, &thread_handles[loop], loop, lp, thread_rapid_popping_and_pushing, ts+loop );
loop++;
}
util_thread_starter_run( tts );
for( loop = 0 ; loop < number_logical_processors ; loop++ )
test_pal_thread_wait( thread_handles[loop] );
util_thread_starter_delete( tts );
free( thread_handles );
LFDS700_MISC_BARRIER_LOAD;
vi.min_elements = vi.max_elements = number_logical_processors;
lfds700_stack_query( &ss, LFDS700_STACK_QUERY_SINGLETHREADED_VALIDATE, &vi, &dvs );
lfds700_stack_cleanup( &ss, NULL );
util_aligned_free( te_array );
free( ts );
// TRD : print the test result
internal_display_test_result( 1, "stack", dvs );
return;
}
/****************************************************************************/
static test_pal_thread_return_t TEST_PAL_CALLING_CONVENTION thread_rapid_popping_and_pushing( void *util_thread_starter_thread_state )
{
lfds700_pal_uint_t
time_loop = 0;
struct lfds700_misc_prng_state
ps;
struct lfds700_stack_element
*se;
struct test_state
*ts;
struct util_thread_starter_thread_state
*tsts;
time_t
current_time,
start_time;
LFDS700_MISC_MAKE_VALID_ON_CURRENT_LOGICAL_CORE_INITS_COMPLETED_BEFORE_NOW_ON_ANY_OTHER_LOGICAL_CORE;
assert( util_thread_starter_thread_state != NULL );
tsts = (struct util_thread_starter_thread_state *) util_thread_starter_thread_state;
ts = (struct test_state *) tsts->thread_user_state;
lfds700_misc_prng_init( &ps );
util_thread_starter_ready_and_wait( tsts );
current_time = start_time = time( NULL );
while( current_time < start_time + TEST_DURATION_IN_SECONDS )
{
lfds700_stack_pop( ts->ss, &se, &ps );
lfds700_stack_push( ts->ss, se, &ps );
if( time_loop++ == TIME_LOOP_COUNT )
{
time_loop = 0;
time( &current_time );
}
}
LFDS700_MISC_BARRIER_STORE;
lfds700_misc_force_store();
return( (test_pal_thread_return_t) EXIT_SUCCESS );
}
/***** includes *****/
#include "internal.h"
/****************************************************************************/
#if( defined _WIN32 && !defined _KERNEL_MODE && NTDDI_VERSION >= NTDDI_WIN7 )
/* TRD : _WIN32 indicates 64-bit or 32-bit Windows
!_KERNEL_MODE indicates Windows user-mode
NTDDI_VERSION indicates Windows version
- GetLogicalProcessorInformationEx requires Windows 7
*/
#ifdef TEST_PAL_GET_LOGICAL_CORE_IDS
#error More than one porting abstraction layer matches current platform in test_porting_abstraction_layer_get_logical_core_ids.c
#endif
#define TEST_PAL_GET_LOGICAL_CORE_IDS
void test_pal_get_logical_core_ids( struct lfds700_list_asu_state *lasus )
{
BOOL
rv;
DWORD
loop,
number_slpie,
slpie_length = 0;
lfds700_pal_uint_t
bitmask,
logical_processor_number,
windows_logical_processor_group_number;
struct lfds700_misc_prng_state
ps;
struct test_pal_logical_processor
*lp;
SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX
*slpie = NULL;
assert( lasus != NULL );
lfds700_misc_prng_init( &ps );
lfds700_list_asu_init_valid_on_current_logical_core( lasus, NULL, NULL );
rv = GetLogicalProcessorInformationEx( RelationGroup, slpie, &slpie_length );
slpie = malloc( slpie_length );
rv = GetLogicalProcessorInformationEx( RelationGroup, slpie, &slpie_length );
number_slpie = slpie_length / sizeof(SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX);
for( loop = 0 ; loop < number_slpie ; loop++ )
if( (slpie+loop)->Relationship == RelationGroup )
for( windows_logical_processor_group_number = 0 ; windows_logical_processor_group_number < (slpie+loop)->Group.ActiveGroupCount ; windows_logical_processor_group_number++ )
for( logical_processor_number = 0 ; logical_processor_number < sizeof(KAFFINITY) * BITS_PER_BYTE ; logical_processor_number++ )
{
bitmask = (lfds700_pal_uint_t) 1 << logical_processor_number;
// TRD : if we've found a processor for this group, add it to the list
if( (slpie+loop)->Group.GroupInfo[windows_logical_processor_group_number].ActiveProcessorMask & bitmask )
{
lp = util_aligned_malloc( sizeof(struct test_pal_logical_processor), LFDS700_PAL_ATOMIC_ISOLATION_IN_BYTES );
lp->logical_processor_number = logical_processor_number;
lp->windows_logical_processor_group_number = windows_logical_processor_group_number;
LFDS700_LIST_ASU_SET_VALUE_IN_ELEMENT( lp->lasue, lp );
lfds700_list_asu_insert_at_start( lasus, &lp->lasue, &ps );
}
}
free( slpie );
return;
}
#endif
/****************************************************************************/
#if( defined _WIN32 && !defined _KERNEL_MODE && NTDDI_VERSION >= NTDDI_WINXP && NTDDI_VERSION < NTDDI_WIN7 )
/* TRD : _WIN32 indicates 64-bit or 32-bit Windows
!_KERNEL_MODE indicates Windows user-mode
NTDDI_VERSION indicates Windows version
- GetLogicalProcessorInformation requires XP SP3
*/
#ifdef TEST_PAL_GET_LOGICAL_CORE_IDS
#error More than one porting abstraction layer matches current platform in test_porting_abstraction_layer_get_logical_core_ids.c
#endif
#define TEST_PAL_GET_LOGICAL_CORE_IDS
void test_pal_get_logical_core_ids( struct lfds700_list_asu_state *lasus )
{
DWORD
slpi_length = 0;
lfds700_pal_uint_t
number_slpi,
loop;
struct lfds700_misc_prng_state
ps;
struct test_pal_logical_processor
*lp;
SYSTEM_LOGICAL_PROCESSOR_INFORMATION
*slpi = NULL;
ULONG_PTR
mask;
assert( lasus != NULL );
lfds700_misc_prng_init( &ps );
lfds700_list_asu_init_valid_on_current_logical_core( lasus, NULL, NULL );
*number_logical_processors = 0;
GetLogicalProcessorInformation( slpi, &slpi_length );
slpi = malloc( slpi_length );
GetLogicalProcessorInformation( slpi, &slpi_length );
number_slpi = slpi_length / sizeof(SYSTEM_LOGICAL_PROCESSOR_INFORMATION);
for( loop = 0 ; loop < number_slpi ; loop++ )
if( (slpi+loop)->Relationship == RelationProcessorCore )
for( logical_processor_number = 0 ; logical_processor_number < sizeof(ULONG_PTR) * BITS_PER_BYTE ; logical_processor_number++ )
{
bitmask = 1 << logical_processor_number;
if( (slpi+loop)->ProcessorMask & bitmask )
{
lp = util_aligned_malloc( sizeof(struct test_pal_logical_processor), LFDS700_PAL_ATOMIC_ISOLATION_IN_BYTES );
lp->logical_processor_number = logical_processor_number;
lp->windows_logical_processor_group_number = 0;
LFDS700_LIST_ASU_SET_VALUE_IN_ELEMENT( lp->lasue, lp );
lfds700_list_asu_insert_at_start( lasus, &lp->lasue, &ps );
}
free( slpi );
return;
}
#endif
/****************************************************************************/
#if( defined __linux__ )
/* TRD : __linux__ indicates Linux
__STDC__ indicates Standard Library
__STDC_HOSTED__ indicates Standard Library hosted implementation
- fopen requires a Standard Library hosted environment
- setbuf requires a Standard Library hosted environment
- fgets requires a Standard Library hosted environment
- sscanf requires a Standard Library hosted environment
- fclose requires a Standard Library hosted environment
*/
#ifdef TEST_PAL_GET_LOGICAL_CORE_IDS
#error More than one porting abstraction layer matches current platform in test_porting_abstraction_layer_get_logical_core_ids.c
#endif
#define TEST_PAL_GET_LOGICAL_CORE_IDS
void test_pal_get_logical_core_ids( struct lfds700_list_asu_state *lasus )
{
char
diskbuffer[BUFSIZ],
string[1024];
FILE
*diskfile;
int long long unsigned
logical_processor_number;
struct lfds700_misc_prng_state
ps;
struct test_pal_logical_processor
*lp;
assert( lasus != NULL );
lfds700_misc_prng_init( &ps );
lfds700_list_asu_init_valid_on_current_logical_core( lasus, NULL, NULL );
diskfile = fopen( "/proc/cpuinfo", "r" );
if( diskfile != NULL )
{
setbuf( diskfile, diskbuffer );
while( NULL != fgets(string, 1024, diskfile) )
if( 1 == sscanf(string, "processor : %llu", &logical_processor_number) )
{
lp = util_aligned_malloc( sizeof(struct test_pal_logical_processor), LFDS700_PAL_ATOMIC_ISOLATION_IN_BYTES );
lp->logical_processor_number = (lfds700_pal_uint_t) logical_processor_number;
lp->windows_logical_processor_group_number = 0;
LFDS700_LIST_ASU_SET_VALUE_IN_ELEMENT( lp->lasue, lp );
lfds700_list_asu_insert_at_start( lasus, &lp->lasue, &ps );
}
fclose( diskfile );
}
return;
}
#endif
/****************************************************************************/
#if( !defined TEST_PAL_GET_LOGICAL_CORE_IDS )
#error test_pal_get_logical_core_ids() not implemented for this platform.
#endif
/****************************************************************************/
#if( defined _MSC_VER )
/* TRD : MSVC compiler
an unfortunately necessary hack for MSVC
MSVC only defines __STDC__ if /Za is given, where /Za turns off MSVC C extensions -
which prevents Windows header files from compiling.
*/
#define __STDC__ 1
#define __STDC_HOSTED__ 1
#endif
#if( defined __linux__ )
#define _GNU_SOURCE
#include <unistd.h>
#endif
/****************************************************************************/
#if( defined _MSC_VER && _MSC_VER >= 1310 && NTDDI_VERSION >= NTDDI_WINXP && defined _WIN32 )
#ifdef TEST_PAL_PORTING_ABSTRACTION_LAYER
#error More than one porting abstraction layer matches current platform.
#endif
#define TEST_PAL_PORTING_ABSTRACTION_LAYER
#define TEST_PAL_OS_STRING "Windows"
#include <windows.h>
typedef HANDLE test_pal_thread_state_t;
typedef DWORD test_pal_thread_return_t;
#define TEST_PAL_CALLING_CONVENTION WINAPI
#endif
/****************************************************************************/
#if( defined __GNUC__ && defined __linux__ && _POSIX_THREADS > 0 )
#ifdef TEST_PAL_PORTING_ABSTRACTION_LAYER
#error More than one porting abstraction layer matches current platform.
#endif
#define TEST_PAL_PORTING_ABSTRACTION_LAYER
#define TEST_PAL_OS_STRING "Linux"
#define _GNU_SOURCE
#include <pthread.h>
#include <sched.h>
#include <sys/syscall.h>
#include <sys/types.h>
typedef pthread_t test_pal_thread_state_t;
typedef void * test_pal_thread_return_t;
#define TEST_PAL_CALLING_CONVENTION
#endif
/****************************************************************************/
#if( !defined TEST_PAL_PORTING_ABSTRACTION_LAYER )
#error No matching porting abstraction layer in test_porting_abstraction_layer_operating_system.h
#endif
/***** includes *****/
#include "internal.h"
/****************************************************************************/
#if( defined _WIN32 && !defined _KERNEL_MODE && NTDDI_VERSION >= NTDDI_WIN7 )
/* TRD : _WIN32 indicates 32-bit or 64-bit Windows
!_KERNEL_MODE indicates Windows user-mode
NTDDI_VERSION indicates Windows version
- GetCurrentProcess requires XP
- InitializeProcThreadAttributeList requires Windows 7
- CreateRemoteThreadEx requires Windows 7
*/
#ifdef TEST_PAL_THREAD_START
#error More than one porting abstraction layer matches the current platform in test_porting_abstraction_layer_thread_start.c
#endif
#define TEST_PAL_THREAD_START
int test_pal_thread_start( test_pal_thread_state_t *thread_state,
struct test_pal_logical_processor *lp,
test_pal_thread_return_t (TEST_PAL_CALLING_CONVENTION *thread_function)(void *thread_user_state),
void *thread_user_state )
{
BOOL
brv;
DWORD
thread_id;
GROUP_AFFINITY
ga;
int
rv = 0;
LPPROC_THREAD_ATTRIBUTE_LIST
attribute_list;
SIZE_T
attribute_list_length;
assert( thread_state != NULL );
assert( lp != NULL );
assert( thread_function != NULL );
// TRD : thread_user_state can be NULL
/* TRD : here we're using CreateRemoteThreadEx() to start a thread in our own process
we do this because as a function, it allows us to specify processor and processor group affinity in the create call
*/
brv = InitializeProcThreadAttributeList( NULL, 1, 0, &attribute_list_length );
attribute_list = malloc( attribute_list_length );
brv = InitializeProcThreadAttributeList( attribute_list, 1, 0, &attribute_list_length );
ga.Mask = ( (KAFFINITY) 1 << lp->logical_processor_number );
ga.Group = (WORD) lp->windows_logical_processor_group_number;
memset( ga.Reserved, 0, sizeof(WORD) * 3 );
brv = UpdateProcThreadAttribute( attribute_list, 0, PROC_THREAD_ATTRIBUTE_GROUP_AFFINITY, &ga, sizeof(GROUP_AFFINITY), NULL, NULL );
*thread_state = CreateRemoteThreadEx( GetCurrentProcess(), NULL, 0, thread_function, thread_user_state, NO_FLAGS, attribute_list, &thread_id );
DeleteProcThreadAttributeList( attribute_list );
free( attribute_list );
if( *thread_state != NULL )
rv = 1;
return( rv );
}
#endif
/****************************************************************************/
#if( defined _WIN32 && !defined _KERNEL_MODE && NTDDI_VERSION >= NTDDI_WINXP && NTDDI_VERSION < NTDDI_WIN7 )
/* TRD : _WIN32 indicates 64-bit or 32-bit Windows
NTDDI_VERSION indicates Windows version
- CreateThread requires XP
- SetThreadAffinityMask requires XP
- ResumeThread requires XP
*/
#ifdef TEST_PAL_THREAD_START
#error More than one porting abstraction layer matches the current platform in test_porting_abstraction_layer_thread_start.c
#endif
#define TEST_PAL_THREAD_START
int test_pal_thread_start( test_pal_thread_state_t *thread_state,
struct test_pal_logical_processor *lp,
test_pal_thread_return_t (TEST_PAL_CALLING_CONVENTION *thread_function)(void *thread_user_state),
void *thread_user_state )
{
int
rv = 0;
DWORD
thread_id;
DWORD_PTR
affinity_mask,
result;
assert( thread_state != NULL );
assert( lp != NULL );
assert( thread_function != NULL );
// TRD : thread_user_state can be NULL
/* TRD : Vista and earlier do not support processor groups
as such, there is a single implicit processor group
also, there's no support for actually starting a thread in its correct NUMA node / logical processor
so we make the best of it; we start suspended, set the affinity, and then resume
the thread itself internally is expected to be making allocs from the correct NUMA node
*/
*thread_state = CreateThread( NULL, 0, thread_function, thread_user_state, CREATE_SUSPENDED, &thread_id );
affinity_mask = (DWORD_PTR) (1 << lp->logical_processor_number);
SetThreadAffinityMask( *thread_state, affinity_mask );
ResumeThread( *thread_state );
if( *thread_state != NULL )
rv = 1;
return( rv );
}
#endif
/****************************************************************************/
#if( defined __linux__ && _POSIX_THREADS > 0 )
/* TRD : __linux__ indicates Linux
- gettid requires Linux
- sched_setaffinity requires Linux
_POSIX_THREADS indicates POSIX threads
- pthread_create requires POSIX
*/
#ifdef TEST_PAL_THREAD_START
#error More than one porting abstraction layer matches the current platform in test_porting_abstraction_layer_thread_start.c
#endif
#define TEST_PAL_THREAD_START
/***** structs *****/
struct test_pal_internal_thread_state
{
struct test_pal_logical_processor
lp;
test_pal_thread_return_t
(TEST_PAL_CALLING_CONVENTION *thread_function)( void *thread_user_state );
void
*thread_user_state;
};
/***** prototypes *****/
test_pal_thread_return_t TEST_PAL_CALLING_CONVENTION test_pal_internal_thread_function( void *thread_user_state );
/****************************************************************************/
int test_pal_thread_start( test_pal_thread_state_t *thread_state,
struct test_pal_logical_processor *lp,
test_pal_thread_return_t (TEST_PAL_CALLING_CONVENTION *thread_function)(void *thread_user_state),
void *thread_user_state )
{
int
rv;
struct test_pal_internal_thread_state
*its;
/* TRD : this implementation works on Linux only as it uses sched_setaffinity(), which is Linux specific
although I cannot currently test, I believe this function also works on Android
this implementation exists because the pthreads function for setting thread affinity,
pthread_attr_setaffinity_np(), works on Linux, but not Android
*/
assert( thread_state != NULL );
assert( lp != NULL );
assert( thread_function != NULL );
// TRD : thread_user_state can be NULL
its = malloc( sizeof(struct test_pal_internal_thread_state) );
its->lp = *lp;
its->thread_function = thread_function;
its->thread_user_state = thread_user_state;
rv = pthread_create( thread_state, NULL, test_pal_internal_thread_function, its );
if( rv == 0 )
rv = 1;
return( rv );
}
/****************************************************************************/
test_pal_thread_return_t TEST_PAL_CALLING_CONVENTION test_pal_internal_thread_function( void *thread_user_state )
{
cpu_set_t
cpuset;
pid_t
tid;
struct test_pal_internal_thread_state
*its;
test_pal_thread_return_t
rv;
assert( thread_user_state != NULL );
/* TRD : the APIs under Linux/POSIX for setting thread affinity are in a mess
pthreads offers pthread_attr_setaffinity_np(), which glibc supports,
but which is not supported by Android
Linux offers sched_setaffinity(), but this needs a *thread pid*,
and the only API to get a thread pid is gettid(), which works for
and only for *the calling thread*
so we come to this - a wrapper thread function, which is the function used
when starting a thread; this calls gettid() and then sched_setaffinity(),
and then calls into the actual thread function
generally shaking my head in disbelief at this point
*/
assert( thread_user_state != NULL );
its = (struct test_pal_internal_thread_state *) thread_user_state;
CPU_ZERO( &cpuset );
CPU_SET( its->lp.logical_processor_number, &cpuset );
tid = syscall( SYS_gettid );
sched_setaffinity( tid, sizeof(cpu_set_t), &cpuset );
rv = its->thread_function( its->thread_user_state );
free( its );
return( rv );
}
#endif
/****************************************************************************/
#if( !defined __linux__ && _POSIX_THREADS > 0 )
/* TRD : !__linux__ indicates not Linux
_POSIX_THREADS indicates POSIX threads
- pthread_attr_init requires POSIX
- pthread_attr_setaffinity_np requires POSIX
- pthread_create requires POSIX
- pthread_attr_destroy requires POSIX
*/
#ifdef TEST_PAL_THREAD_START
#error More than one porting abstraction layer matches the current platform in test_porting_abstraction_layer_thread_start.c
#endif
#define TEST_PAL_THREAD_START
int test_pal_thread_start( test_pal_thread_state_t *thread_state,
struct test_pal_logical_processor *lp,
test_pal_thread_return_t (TEST_PAL_CALLING_CONVENTION *thread_function)(void *thread_user_state),
void *thread_user_state )
{
int
rv = 0,
rv_create;
cpu_set_t
cpuset;
pthread_attr_t
attr;
assert( thread_state != NULL );
assert( lp != NULL );
assert( thread_function != NULL );
// TRD : thread_user_state can be NULL
pthread_attr_init( &attr );
CPU_ZERO( &cpuset );
CPU_SET( lp->logical_processor_number, &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
/****************************************************************************/
#if( !defined TEST_PAL_THREAD_START )
#error test_pal_thread_start() not implemented for this platform.
#endif
/***** includes *****/
#include "internal.h"
/****************************************************************************/
#if( defined _WIN32 && NTDDI_VERSION >= NTDDI_WINXP )
/* TRD : _WIN32 indicates 32-bit or 64-bit Windows
NTDDI_VERSION indicates Windows version
- WaitForSingleObject requires XP
*/
#ifdef TEST_PAL_THREAD_WAIT
#error More than one porting abstraction layer matches current platform in test_porting_abstraction_layer_thread_wait.c
#endif
#define TEST_PAL_THREAD_WAIT
void test_pal_thread_wait( test_pal_thread_state_t thread_state )
{
WaitForSingleObject( thread_state, INFINITE );
return;
}
#endif
/****************************************************************************/
#if( _POSIX_THREADS > 0 )
/* TRD : POSIX threads
_POSIX_THREADS indicates POSIX threads
- pthread_join requires POSIX
*/
#ifdef TEST_PAL_THREAD_WAIT
#error More than one porting abstraction layer matches current platform in test_porting_abstraction_layer_thread_wait.c
#endif
#define TEST_PAL_THREAD_WAIT
void test_pal_thread_wait( test_pal_thread_state_t thread_state )
{
pthread_join( thread_state, NULL );
return;
}
#endif
/****************************************************************************/
#if( !defined TEST_PAL_THREAD_WAIT )
#error test_pal_thread_wait() not implemented for this platform.
#endif
/***** includes *****/
#include "internal.h"
/****************************************************************************/
void util_cmdline_init( struct util_cmdline_state *cs )
{
lfds700_pal_uint_t
loop;
assert( cs != NULL );
for( loop = 0 ; loop < NUMBER_OF_LOWERCASE_LETTERS_IN_LATIN_ALPHABET ; loop++ )
{
cs->args[loop].arg_type = LIBCOMMON_CMDLINE_ARG_TYPE_UNSET;
cs->args[loop].processed_flag = LOWERED;
}
return;
}
/****************************************************************************/
#pragma warning( disable : 4100 )
void util_cmdline_cleanup( struct util_cmdline_state *cs )
{
assert( cs != NULL );
return;
}
#pragma warning( default : 4100 )
/****************************************************************************/
void util_cmdline_add_arg( struct util_cmdline_state *cs, char arg_letter, enum util_cmdline_arg_type arg_type )
{
lfds700_pal_uint_t
index;
assert( cs != NULL );
assert( arg_letter >= 'a' and arg_letter <= 'z' );
// TRD : arg_type can be any value in its range
index = arg_letter - 'a';
cs->args[index].arg_type = arg_type;
if( arg_type == LIBCOMMON_CMDLINE_ARG_TYPE_FLAG )
cs->args[index].arg_data.flag.flag = LOWERED;
return;
}
/****************************************************************************/
int util_cmdline_process_args( struct util_cmdline_state *cs, int argc, char **argv )
{
char
*arg;
int
arg_letter,
cc,
loop,
rv = 1;
lfds700_pal_uint_t
index;
assert( cs != NULL );
assert( argc >= 1 );
assert( argv != NULL );
for( loop = 1 ; loop < argc ; loop++ )
{
arg = *(argv+loop);
switch( *arg )
{
case '-':
arg_letter = tolower( *(arg+1) );
if( arg_letter >= 'a' and arg_letter <= 'z' )
{
index = arg_letter - 'a';
switch( cs->args[index].arg_type )
{
case LIBCOMMON_CMDLINE_ARG_TYPE_INTEGER_RANGE:
if( loop+1 >= argc )
rv = 0;
if( loop+1 < argc )
{
cc = sscanf( *(argv+loop+1), "%llu-%llu", &cs->args[index].arg_data.integer_range.integer_start, &cs->args[index].arg_data.integer_range.integer_end );
if( cc != 2 )
rv = 0;
if( cc == 2 )
{
cs->args[index].processed_flag = RAISED;
loop++;
}
}
break;
case LIBCOMMON_CMDLINE_ARG_TYPE_INTEGER:
if( loop+1 >= argc )
rv = 0;
if( loop+1 < argc )
{
cc = sscanf( *(argv+loop+1), "%llu", &cs->args[index].arg_data.integer.integer );
if( cc != 1 )
rv = 0;
if( cc == 1 )
{
cs->args[index].processed_flag = RAISED;
loop++;
}
}
break;
case LIBCOMMON_CMDLINE_ARG_TYPE_FLAG:
cs->args[index].arg_data.flag.flag = RAISED;
cs->args[index].processed_flag = RAISED;
break;
case LIBCOMMON_CMDLINE_ARG_TYPE_UNSET:
break;
}
}
break;
default:
rv = 0;
break;
}
}
return( rv );
}
/****************************************************************************/
void util_cmdline_get_arg_data( struct util_cmdline_state *cs, char arg_letter, union util_cmdline_arg_data **arg_data )
{
lfds700_pal_uint_t
index;
assert( cs != NULL );
assert( arg_letter >= 'a' and arg_letter <= 'z' );
assert( arg_data != NULL );
index = arg_letter - 'a';
if( cs->args[index].processed_flag == RAISED )
*arg_data = &cs->args[index].arg_data;
else
*arg_data = NULL;
return;
}
/***** defines *****/
#define NUMBER_OF_LOWERCASE_LETTERS_IN_LATIN_ALPHABET 26
/***** enums *****/
enum util_cmdline_arg_type
{
LIBCOMMON_CMDLINE_ARG_TYPE_INTEGER_RANGE,
LIBCOMMON_CMDLINE_ARG_TYPE_INTEGER,
LIBCOMMON_CMDLINE_ARG_TYPE_FLAG,
LIBCOMMON_CMDLINE_ARG_TYPE_UNSET
};
/***** structs *****/
struct util_cmdline_arg_integer_range
{
int long long unsigned
integer_start,
integer_end;
};
struct util_cmdline_arg_integer
{
int long long unsigned
integer;
};
struct util_cmdline_arg_flag
{
enum flag
flag;
};
union util_cmdline_arg_data
{
struct util_cmdline_arg_integer_range
integer_range;
struct util_cmdline_arg_integer
integer;
struct util_cmdline_arg_flag
flag;
};
struct util_cmdline_arg_letter_and_data
{
enum util_cmdline_arg_type
arg_type;
enum flag
processed_flag;
union util_cmdline_arg_data
arg_data;
};
struct util_cmdline_state
{
struct util_cmdline_arg_letter_and_data
args[NUMBER_OF_LOWERCASE_LETTERS_IN_LATIN_ALPHABET];
};
/***** public protoypes *****/
void util_cmdline_init( struct util_cmdline_state *cs );
void util_cmdline_cleanup( struct util_cmdline_state *cs );
void util_cmdline_add_arg( struct util_cmdline_state *cs, char arg_letter, enum util_cmdline_arg_type arg_type );
int util_cmdline_process_args( struct util_cmdline_state *cs, int argc, char **argv );
void util_cmdline_get_arg_data( struct util_cmdline_state *cs, char arg_letter, union util_cmdline_arg_data **arg_data );
/***** includes *****/
#include "internal.h"
/****************************************************************************/
void *util_aligned_malloc( lfds700_pal_uint_t size, lfds700_pal_uint_t align_in_bytes )
{
lfds700_pal_uint_t
offset;
void
*memory,
*original_memory;
// TRD : size can be any value in its range
// TRD : align_in_bytes can be any value in its range
/* TRD : helper function to provide aligned allocations
no porting required
*/
original_memory = memory = util_malloc_wrapper( size + sizeof(void *) + align_in_bytes );
if( memory != NULL )
{
memory = (void **) memory + 1;
offset = align_in_bytes - (lfds700_pal_uint_t) memory % align_in_bytes;
memory = (char unsigned *) memory + offset;
*( (void **) memory - 1 ) = original_memory;
}
return( memory );
}
/****************************************************************************/
void util_aligned_free( void *memory )
{
assert( memory != NULL );
// TRD : the "void *" stored above memory points to the root of the allocation
free( *( (void **) memory - 1 ) );
return;
}
/****************************************************************************/
void *util_malloc_wrapper( lfds700_pal_uint_t size )
{
void
*memory;
// TRD : size can be any value in its range
memory = malloc( size );
if( memory == NULL )
{
puts( "malloc() failed, exiting." );
exit( EXIT_FAILURE );
}
return( memory );
}
/***** public prototypes *****/
void *util_aligned_malloc( lfds700_pal_uint_t size, lfds700_pal_uint_t align_in_bytes );
void util_aligned_free( void *memory );
void *util_malloc_wrapper( lfds700_pal_uint_t size );
/***** includes *****/
#include "internal.h"
/****************************************************************************/
void util_thread_starter_new( struct util_thread_starter_state **tts, lfds700_pal_uint_t number_threads )
{
lfds700_pal_uint_t
loop;
assert( tts != NULL );
// TRD : number_threads cam be any value in its range
*tts = util_malloc_wrapper( sizeof(struct util_thread_starter_state) );
(*tts)->tsts = util_malloc_wrapper( sizeof(struct util_thread_starter_thread_state) * number_threads );
(*tts)->thread_start_flag = LOWERED;
(*tts)->number_thread_states = number_threads;
for( loop = 0 ; loop < number_threads ; loop++ )
{
((*tts)->tsts+loop)->thread_ready_flag = LOWERED;
((*tts)->tsts+loop)->thread_start_flag = &(*tts)->thread_start_flag;
}
LFDS700_MISC_BARRIER_STORE;
lfds700_misc_force_store();
return;
}
/****************************************************************************/
void util_thread_starter_start( struct util_thread_starter_state *tts,
test_pal_thread_state_t *thread_state,
lfds700_pal_uint_t thread_number,
struct test_pal_logical_processor *lp,
test_pal_thread_return_t (TEST_PAL_CALLING_CONVENTION *thread_function)( void *thread_user_state ),
void *thread_user_state )
{
assert( tts != NULL );
assert( thread_state != NULL );
assert( lp != NULL );
assert( thread_function != NULL );
// TRD : thread_user_state can be NULL
(tts->tsts+thread_number)->thread_user_state = thread_user_state;
util_thread_start_wrapper( thread_state, lp, thread_function, tts->tsts+thread_number );
// TRD : wait for the thread to indicate it is ready and waiting
while( (tts->tsts+thread_number)->thread_ready_flag == LOWERED );
return;
}
/****************************************************************************/
void util_thread_starter_ready_and_wait( struct util_thread_starter_thread_state *tsts )
{
assert( tsts != NULL );
tsts->thread_ready_flag = RAISED;
LFDS700_MISC_BARRIER_FULL;
// TRD : threads here are all looping, so we don't need to force a store
while( *tsts->thread_start_flag == LOWERED )
LFDS700_MISC_BARRIER_LOAD;
return;
}
/****************************************************************************/
void util_thread_starter_run( struct util_thread_starter_state *tts )
{
assert( tts != NULL );
/* TRD : all threads at this point are ready to go
as we wait for their ready flag immediately after their spawn
*/
tts->thread_start_flag = RAISED;
LFDS700_MISC_BARRIER_STORE;
lfds700_misc_force_store();
return;
}
/****************************************************************************/
void util_thread_starter_delete( struct util_thread_starter_state *tts )
{
assert( tts != NULL );
free( tts->tsts );
free( tts );
return;
}
/****************************************************************************/
void util_thread_start_wrapper( test_pal_thread_state_t *thread_state,
struct test_pal_logical_processor *lp,
test_pal_thread_return_t (TEST_PAL_CALLING_CONVENTION *thread_function)(void *thread_user_state),
void *thread_user_state )
{
int
rv;
assert( thread_state != NULL );
assert( lp != NULL );
assert( thread_function != NULL );
// TRD : thread_user_state can be NULL
rv = test_pal_thread_start( thread_state, lp, thread_function, thread_user_state );
if( rv == 0 )
{
puts( "test_pal_thread_start() failed." );
exit( EXIT_FAILURE );
}
return;
}
/***** structs *****/
struct util_thread_starter_thread_state
{
// TRD : must be volatile or the compiler optimizes it away into a single load
enum flag volatile
thread_ready_flag,
*thread_start_flag;
void
*thread_user_state;
};
struct util_thread_starter_state
{
enum flag volatile
thread_start_flag;
lfds700_pal_uint_t
number_thread_states;
struct util_thread_starter_thread_state
*tsts;
};
/***** prototypes *****/
void util_thread_starter_new( struct util_thread_starter_state **tts, lfds700_pal_uint_t number_threads );
void util_thread_starter_start( struct util_thread_starter_state *tts,
test_pal_thread_state_t *thread_state,
lfds700_pal_uint_t thread_number,
struct test_pal_logical_processor *lp,
test_pal_thread_return_t (TEST_PAL_CALLING_CONVENTION *thread_function)( void *thread_user_state ),
void *thread_user_state );
void util_thread_starter_ready_and_wait( struct util_thread_starter_thread_state *tsts );
void util_thread_starter_run( struct util_thread_starter_state *tts );
void util_thread_starter_delete( struct util_thread_starter_state *tts );
void util_thread_start_wrapper( test_pal_thread_state_t *thread_state,
struct test_pal_logical_processor *lp,
test_pal_thread_return_t (TEST_PAL_CALLING_CONVENTION *thread_function)(void *thread_user_state),
void *thread_user_state );
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment